ghidra/Ghidra/Processors/6805/data/languages/6805.slaspec

670 lines
10 KiB
Plaintext

# sleigh specification file for Motorola 6805
define endian=big;
define alignment=1;
define space RAM type=ram_space size=2 default;
define space register type=register_space size=1;
define register offset=0x00 size=1 [ A X ];
define register offset=0x20 size=2 [ PC SP];
define register offset=0x30 size=1 [H I N Z C]; # status bits
define RAM offset=0x3ffc size=2 [ SWI_VECTOR ];
#TOKENS
define token opbyte (8)
op = (0,7)
op4_7 = (4,7)
op4_6 = (4,6)
n = (1,3)
bit_0 = (0,0)
;
define token data8 (8)
imm8 = (0,7)
rel = (0,7) signed
;
define token data (16)
imm16 = (0,15)
;
################################################################
# Psuedo Instructions
################################################################
define pcodeop readIRQ;
################################################################
REL: reloc is rel [ reloc = inst_next + rel; ] { export *:2 reloc; }
OP1: "#"imm8 is op4_6=2; imm8 { tmp:1 = imm8; export tmp; }
OP1: imm8 is op4_6=3; imm8 { export *:1 imm8; }
OP1: imm16 is op4_6=4; imm16 { export *:1 imm16; }
OP1: imm16,X is op4_6=5 & X; imm16 { tmp:2 = imm16 + zext(X); export *:1 tmp; }
OP1: imm8,X is op4_6=6 & X; imm8 { tmp:2 = imm8 + zext(X); export *:1 tmp; }
OP1: X is op4_6=7 & X { tmp:2 = zext(X); export *:1 tmp; }
ADDR: imm8 is op4_6=3; imm8 { export *:1 imm8; }
ADDR: imm16 is op4_6=4; imm16 { export *:1 imm16; }
ADDRI: imm16,X is op4_6=5 & X; imm16 { tmp:2 = imm16 + zext(X); export tmp; }
ADDRI: imm8,X is op4_6=6 & X; imm8 { tmp:2 = imm8 + zext(X); export tmp; }
ADDRI: X is op4_6=7 & X { tmp:2 = zext(X); export tmp; }
DIRECT: imm8 is imm8 { export *:1 imm8; }
:ADC OP1 is (op=0xA9 | op=0xB9 | op=0xC9 | op=0xD9 | op=0xE9 | op=0xF9) ... & OP1
{
local op1 = OP1;
# compute half carry
local halfop1 = op1 & 0xF;
local halfA = A & 0xF;
local halfresult = halfop1 + halfA + C;
H = (halfresult >> 4) & 1;
local result = A + op1;
local tmpC = carry(A, op1);
A = result + C;
C = carry(result, C);
C = C | tmpC;
Z = (A == 0);
N = (A s< 0);
}
:ADD OP1 is (op=0xAB | op=0xBB | op=0xCB | op=0xDB | op=0xEB | op=0xFB) ... & OP1
{
local op1 = OP1;
# compute half carry
local halfop1 = op1 & 0xF;
local halfA = A & 0xF;
local halfresult = halfop1 + halfA;
H = (halfresult >> 4) & 1;
C = carry(A, op1);
A = A + op1;
Z = (A == 0);
N = (A s< 0);
}
:AND OP1 is (op=0xA4 | op=0xB4 | op=0xC4 | op=0xD4 | op=0xE4 | op=0xF4) ... & OP1
{
A = A & OP1;
Z = (A == 0);
N = (A s< 0);
}
:ASLA is op=0x48
{
C = A >> 7;
A = A << 1;
Z = (A == 0);
N = (A s< 0);
}
:ASLX is op=0x58
{
C = X >> 7;
X = X << 1;
Z = (X == 0);
N = (X s< 0);
}
:ASL OP1 is (op=0x38 | op=0x68 | op=0x78) ... & OP1
{
local tmp = OP1;
C = tmp >> 7;
tmp = tmp << 1;
OP1 = tmp;
Z = (tmp == 0);
N = (tmp s< 0);
}
:ASRA is op=0x47
{
C = A & 1;
A = A s>> 1;
Z = (A == 0);
N = (A s< 0);
}
:ASRX is op=0x57
{
C = X & 1;
X = X s>> 1;
Z = (X == 0);
N = (X s< 0);
}
:ASR OP1 is (op=0x37 | op=0x67 | op=0x77) ... & OP1
{
local tmp = OP1;
C = tmp & 1;
tmp = tmp s>> 1;
OP1 = tmp;
Z = (tmp == 0);
N = (tmp s< 0);
}
:BCC REL is op=0x24;REL
{
if (C == 0) goto REL;
}
:BCLR n,DIRECT is op4_7=1 & bit_0=1 & n; DIRECT {
local mask = ~(1 << n);
DIRECT = DIRECT & mask;
}
:BCS REL is op=0x25;REL
{
if (C) goto REL;
}
:BEQ REL is op=0x27;REL
{
if (Z) goto REL;
}
:BHCC REL is op=0x28;REL
{
if (H == 0) goto REL;
}
:BHCS REL is op=0x29;REL
{
if (H) goto REL;
}
:BHI REL is op=0x22;REL
{
local tmp = C + Z;
if (tmp == 0) goto REL;
}
#:BHS REL is op=0x24;REL See BCC
:BIH REL is op=0x2F;REL
{
tmp:1 = readIRQ();
if (tmp) goto REL;
}
:BIL REL is op=0x2E;REL
{
tmp:1 = readIRQ();
if (tmp == 0) goto REL;
}
:BIT OP1 is (op=0xA5 | op=0xB5 | op=0xC5 | op=0xD5 | op=0xE5 | op=0xF5) ... & OP1
{
local result = A & OP1;
Z = (result == 0);
N = (result s< 0);
}
#:BLO REL is op=0x25;REL see BCS
:BLS REL is op=0x23;REL
{
local tmp = C + Z;
if (tmp) goto REL;
}
:BMC REL is op=0x2C;REL
{
if (I == 0) goto REL;
}
:BMI REL is op=0x2B;REL
{
if (N) goto REL;
}
:BMS REL is op=0x2D;REL
{
if (I) goto REL;
}
:BNE REL is op=0x26;REL
{
if (Z == 0) goto REL;
}
:BPL REL is op=0x2A;REL
{
if (N == 0) goto REL;
}
:BRA REL is op=0x20;REL
{
goto REL;
}
:BRN REL is op=0x21;REL
{
}
:BRCLR n,DIRECT,REL is op4_7=0 & bit_0=1 & n; DIRECT; REL
{
local mask = (1 << n);
local result = DIRECT & mask;
if (result == 0) goto REL;
}
:BRSET n,DIRECT,REL is op4_7=0 & bit_0=0 & n; DIRECT; REL
{
local mask = (1 << n);
local result = DIRECT & mask;
if (result != 0) goto REL;
}
:BSET n,DIRECT is op4_7=1 & bit_0=0 & n; DIRECT {
local mask = (1 << n);
DIRECT = DIRECT | mask;
}
:BSR REL is op=0xAD; REL
{
SP=SP-1;
*:2 SP = inst_next;
SP=SP-1;
call REL;
}
:CLC is op=0x98
{
C = 0;
}
:CLI is op=0x9A
{
I = 0;
}
:CLRA is op=0x4F
{
A = 0;
Z = 1;
N = 0;
}
:CLRX is op=0x5F
{
X = 0;
Z = 1;
N = 0;
}
:CLR OP1 is (op=0x3F | op=0x6F | op=0x7F) ... & OP1
{
OP1 = 0;
Z = 1;
N = 0;
}
:CMP OP1 is (op=0xA1 | op=0xB1 | op=0xC1 | op=0xD1 | op=0xE1 | op=0xF1) ... & OP1
{
local op1 = OP1;
local tmp = A - op1;
Z = tmp == 0;
N = tmp s< 0;
C = (A < op1);
}
:COMA is op=0x43
{
A = ~A;
Z = (A == 0);
N = (A s< 0);
C = 1;
}
:COMX is op=0x53
{
X = ~X;
Z = (X == 0);
N = (X s< 0);
C = 1;
}
:COM OP1 is (op=0x33 | op=0x63 | op=0x73) ... & OP1
{
local tmp = ~OP1;
OP1 = tmp;
Z = (tmp == 0);
N = (tmp s< 0);
C = 1;
}
:CPX OP1 is (op=0xA3 | op=0xB3 | op=0xC3 | op=0xD3 | op=0xE3 | op=0xF3) ... & OP1
{
local op1 = OP1;
local tmp = X - op1;
Z = tmp == 0;
N = tmp s< 0;
C = (X < op1);
}
:DECA is op=0x4A
{
A = A - 1;
Z = (A == 0);
N = (A s< 0);
}
:DECX is op=0x5A
{
X = X - 1;
Z = (X == 0);
N = (X s< 0);
}
:DEC OP1 is (op=0x3A | op=0x6A | op=0x7A) ... & OP1
{
local tmp = OP1 - 1;
OP1 = tmp;
Z = (tmp == 0);
N = (tmp s< 0);
}
:EOR OP1 is (op=0xA8 | op=0xB8 | op=0xC8 | op=0xD8 | op=0xE8 | op=0xF8) ... & OP1
{
local op1 = OP1;
A = A ^ op1;
Z = A == 0;
N = A s< 0;
}
:INCA is op=0x4C
{
A = A + 1;
Z = (A == 0);
N = (A s< 0);
}
:INCX is op=0x5C
{
X = X + 1;
Z = (X == 0);
N = (X s< 0);
}
:INC OP1 is (op=0x3C | op=0x6C | op=0x7C) ... & OP1
{
local tmp = OP1 + 1;
OP1 = tmp;
Z = (tmp == 0);
N = (tmp s< 0);
}
:JMP ADDR is (op=0xBC | op=0xCC) ... & ADDR
{
goto ADDR;
}
:JMP ADDRI is (op=0xDC | op=0xEC | op=0xFC) ... & ADDRI
{
goto [ADDRI];
}
:JSR ADDR is (op=0xBD | op=0xCD) ... & ADDR
{
*:2 (SP-1) = inst_next;
SP=SP-2;
call ADDR;
}
:JSR ADDRI is (op=0xDD | op=0xED | op=0xFD) ... & ADDRI
{
*:2 (SP-1) = inst_next;
SP=SP-2;
call [ADDRI];
}
:LDA OP1 is (op=0xA6 | op=0xB6 | op=0xC6 | op=0xD6 | op=0xE6 | op=0xF6) ... & OP1
{
A = OP1;
Z = A == 0;
N = A s< 0;
}
:LDX OP1 is (op=0xAE | op=0xBE | op=0xCE | op=0xDE | op=0xEE | op=0xFE) ... & OP1
{
X = OP1;
Z = X == 0;
N = X s< 0;
}
## Logical Shift left is same as arithmetic shift left
#:LSLA is op=0x48
#:LSLX is op=0x58
#:LSL OP1 is (op=0x38 | op=0x68 | op=0x78) ... & OP1
:LSRA is op=0x44
{
C = A & 1;
A = A >> 1;
Z = (A == 0);
N = 0;
}
:LSRX is op=0x54
{
C = X & 1;
X = X >> 1;
Z = (X == 0);
N = 0;
}
:LSR OP1 is (op=0x34 | op=0x64 | op=0x74) ... & OP1
{
local tmp = OP1;
C = tmp & 1;
tmp = tmp >> 1;
OP1 = tmp;
Z = (tmp == 0);
N = 0;
}
:MUL is op=0x42
{
op1:2 = zext(A);
op2:2 = zext(X);
local result = op1 * op2;
A = result:1;
result = result >> 8;
X = result:1;
}
:NEGA is op=0x40
{
C = A != 0;
A = -A;
Z = (A == 0);
N = (A s< 0);
}
:NEGX is op=0x50
{
C = X != 0;
X = -X;
Z = (X == 0);
N = (X s< 0);
}
:NEG OP1 is (op=0x30 | op=0x60 | op=0x70) ... & OP1
{
local op1 = OP1;
C = op1 != 0;
OP1 = -op1;
Z = (op1 == 0);
N = (op1 s< 0);
}
:NOP is op = 0x9D
{
}
:ORA OP1 is (op=0xAA | op=0xBA | op=0xCA | op=0xDA | op=0xEA | op=0xFA) ... & OP1
{
A = A | OP1;
Z = (A == 0);
N = (A s< 0);
}
:ROLA is op=0x49
{
local tmp = C ;
C = A >> 7;
A = A << 1;
A = A | tmp;
Z = (A == 0);
N = (A s< 0);
}
:ROLX is op=0x59
{
local tmp = C;
C = X >> 7;
X = X << 1;
X = X | tmp;
Z = (X == 0);
N = (X s< 0);
}
:ROL OP1 is (op=0x39 | op=0x69 | op=0x79) ... & OP1
{
local tmpC = C;
local op1 = OP1;
C = op1 >> 7;
local result = op1 << 1;
result = result | tmpC;
OP1 = result;
Z = (result == 0);
N = (result s< 0);
}
:RORA is op=0x46
{
local tmpC = C << 7;
C = A & 1;
A = A s>> 1;
A = A | tmpC;
Z = (A == 0);
N = (A s< 0);
}
:RORX is op=0x56
{
local tmpC = C << 7;
C = X & 1;
X = X s>> 1;
X = X | tmpC;
Z = (X == 0);
N = (X s< 0);
}
:ROR OP1 is (op=0x36 | op=0x66 | op=0x76) ... & OP1
{
local tmpC = C << 7;
local tmp = OP1;
C = tmp & 1;
tmp = tmp s>> 1;
tmp = tmp | tmpC;
OP1 = tmp;
Z = (tmp == 0);
N = (tmp s< 0);
}
:RSP is op = 0x9C
{
SP = 0xff;
}
:RTI is op = 0x80
{
SP = SP+1;
local ccr = *:1 SP;
H = ccr[4,1];
I = ccr[3,1];
N = ccr[2,1];
Z = ccr[1,1];
C = ccr[0,1];
SP = SP+1;
A = *:1 SP;
SP = SP+1;
X = *:1 SP;
SP = SP+1;
tmp:2 = *:2 SP;
SP = SP+1;
return [tmp];
}
:RTS is op = 0x81
{
SP = SP+1;
tmp:2 = *:2 SP;
SP = SP+1;
return [tmp];
}
:SBC OP1 is (op=0xA2 | op=0xB2 | op=0xC2 | op=0xD2 | op=0xE2 | op=0xF2) ... & OP1
{
local op1 = OP1;
local tmp = A - op1 - C;
Z = tmp == 0;
N = tmp s< 0;
C = ((A <= op1) * C) | (A < op1);
A = tmp;
}
:SEC is op = 0x99
{
C = 1;
}
:SEI is op = 0x9B
{
I = 1;
}
:STA OP1 is (op=0xB7 | op=0xC7 | op=0xD7 | op=0xE7 | op=0xF7) ... & OP1
{
OP1 = A;
Z = A == 0;
N = A s< 0;
}
:STOP is op=0x8E
{
I = 0;
}
:STX OP1 is (op=0xBF | op=0xCF | op=0xDF | op=0xEF | op=0xFF) ... & OP1
{
OP1 = X;
Z = X == 0;
N = X s< 0;
}
:SUB OP1 is (op=0xA0 | op=0xB0 | op=0xC0 | op=0xD0 | op=0xE0 | op=0xF0) ... & OP1
{
local op1 = OP1;
C = (A < op1);
A = A - op1;
Z = A == 0;
N = A s< 0;
A = A;
}
:SWI is op=0x83
{
SP=SP-1;
*:2 SP = inst_next;
SP=SP-1;
*:1 SP = X;
SP=SP-1;
*:1 SP = A;
tmp:1 = 0b11100000 | (H << 4) | (I << 3) | (N << 2) | ( Z << 1) | C;
SP=SP-1;
*:1 SP = tmp;
I = 1;
call [SWI_VECTOR];
}
:TAX is op=0x97
{
X = A;
}
:TSTA is op=0x4D
{
Z = (A == 0);
N = (A s< 0);
}
:TSTX is op=0x5D
{
Z = (X == 0);
N = (X s< 0);
}
:TST OP1 is (op=0x3D | op=0x6D | op=0x7D) ... & OP1
{
local op1 = OP1;
Z = (op1 == 0);
N = (op1 s< 0);
}
:TXA is op=0x9F
{
A = X;
}
:WAIT is op=0x8f
{
I = 0;
}