ghidra/Ghidra/Processors/Z80/data/languages/z80.slaspec

2078 lines
43 KiB
Plaintext

# sleigh specification file for Zilog Z80
# TODO: Improve Flag bit implementation so that bit operations on F register work properly
define endian=little;
define alignment=1;
@if defined(Z180)
define space ram type=ram_space size=2 default;
@define PTRSIZE "2"
@else
define space ram type=ram_space size=2 default;
@define PTRSIZE "2"
@endif
define space io type=ram_space size=2;
define space register type=register_space size=1;
define register offset=0x00 size=1 [ F A C B E D L H I R ];
define register offset=0x00 size=2 [ AF BC DE HL ];
define register offset=0x20 size=1 [ F_ A_ C_ B_ E_ D_ L_ H_ ]; # Alternate registers
define register offset=0x20 size=2 [ AF_ BC_ DE_ HL_ ]; # Alternate registers
define register offset=0x40 size=2 [ _ PC SP IX IY ];
define register offset=0x50 size=1 [ rCBAR rCBR rBBR ];
# Fake Registers used for pcode control
define register offset=0x60 size=1 [
DECOMPILE_MODE
];
# Define context bits
define register offset=0xf0 size=4 contextreg;
define context contextreg
assume8bitIOSpace =(0,0) # only applies to Z180
;
# Flag bits (?? manual is very confusing - could be typos!)
@define C_flag "F[0,1]" # C: Carry
@define N_flag "F[1,1]" # N: Add/Subtract - used by DAA to distinguish between ADD and SUB instructions (0=ADD,1=SUB)
@define PV_flag "F[2,1]" # PV: Parity/Overflow
@define H_flag "F[4,1]" # H: Half Carry
@define Z_flag "F[6,1]" # Z: Zero
@define S_flag "F[7,1]" # S: Sign
define token opbyte (8)
op0_8 = (0,7)
op6_2 = (6,7)
dRegPair4_2 = (4,5)
pRegPair4_2 = (4,5)
sRegPair4_2 = (4,5)
qRegPair4_2 = (4,5)
rRegPair4_2 = (4,5)
reg3_3 = (3,5)
bits3_3 = (3,5)
bits0_4 = (0,3)
reg0_3 = (0,2)
bits0_3 = (0,2)
;
define token data8 (8)
imm8 = (0,7)
sign8 = (7,7)
simm8 = (0,7) signed
;
define token data16 (16)
timm4 = (12,15)
imm16 = ( 0,15)
sign16 = (15,15)
simm16 = ( 0,15) signed
;
attach variables [ reg0_3 reg3_3 ] [ B C D E H L _ A ];
attach variables [ sRegPair4_2 dRegPair4_2 ] [ BC DE HL SP ];
attach variables [ qRegPair4_2 ] [ BC DE HL AF ];
attach variables [ pRegPair4_2 ] [ BC DE IX SP ];
attach variables [ rRegPair4_2 ] [ BC DE IY SP ];
################################################################
# Psuedo Instructions
################################################################
define pcodeop segment; # Define special pcodeop that calculates the RAM address
# given the segment selector and offset as input
define pcodeop BCDadjust;
define pcodeop BCDadjustCarry;
define pcodeop hasEvenParity;
define pcodeop disableMaskableInterrupts;
define pcodeop enableMaskableInterrupts;
define pcodeop setInterruptMode;
define pcodeop parity;
define pcodeop sleep;
define pcodeop halt;
################################################################
# Macros
################################################################
macro setResultFlags(result) {
$(Z_flag) = (result == 0);
$(S_flag) = (result s< 0);
}
macro additionFlags(operand1, operand2) {
local AFmask = -1 >> 4;
$(H_flag) = (((operand1 & AFmask) + (operand2 & AFmask)) & (AFmask + 1)) != 0;
$(PV_flag) = scarry(operand1, operand2);
$(N_flag) = 0;
$(C_flag) = carry(operand1, operand2);
}
macro additionFlagsNoPV(operand1, operand2) {
local AFmask = -1 >> 4;
$(H_flag) = (((operand1 & AFmask) + (operand2 & AFmask)) & (AFmask + 1)) != 0;
# $(PV_flag) is not affected
$(N_flag) = 0;
$(C_flag) = carry(operand1, operand2);
}
macro additionWithCarry(operand1, operand2, result) {
local Ccopy = zext($(C_flag));
local AFmask = -1 >> 4;
$(H_flag) = (((operand1 & AFmask) + (operand2 & AFmask) + Ccopy) & (AFmask + 1)) != 0;
$(PV_flag) = scarry(operand1, operand2);
$(N_flag) = 0;
$(C_flag) = carry(operand1, operand2);
local tempResult = operand1 + operand2;
$(C_flag) = $(C_flag) || carry(tempResult, Ccopy);
$(PV_flag) = $(PV_flag) ^^ scarry(tempResult, Ccopy);
result = tempResult + Ccopy;
}
macro subtractionFlags(operand1, operand2) {
local AFmask = -1 >> 4;
$(H_flag) = (((operand1 & AFmask) - (operand2 & AFmask)) & (AFmask + 1)) != 0;
$(PV_flag) = sborrow(operand1, operand2);
$(N_flag) = 1;
$(C_flag) = operand1 < operand2;
}
macro subtractionFlagsNoC(operand1, operand2) {
local AFmask = -1 >> 4;
$(H_flag) = (((operand1 & AFmask) - (operand2 & AFmask)) & (AFmask + 1)) != 0;
$(PV_flag) = sborrow(operand1, operand2);
$(N_flag) = 1;
# $(C_flag) is not affected
}
macro subtractionWithCarry(operand1, operand2, result) {
local Ccopy = zext($(C_flag));
local AFmask = -1 >> 4;
$(H_flag) = (((operand1 & AFmask) - (operand2 & AFmask) - Ccopy) & (AFmask + 1)) != 0;
$(PV_flag) = sborrow(operand1, operand2);
$(N_flag) = 1;
$(C_flag) = operand1 < operand2;
local tempResult = operand1 - operand2;
$(C_flag) = $(C_flag) || (tempResult < Ccopy);
$(PV_flag) = $(PV_flag) ^^ sborrow(tempResult, Ccopy);
result = tempResult - Ccopy;
}
macro setSubtractFlags(op1,op2) {
$(C_flag) = (op1 < op2);
}
# places the parity bit of the given byte in out_parity_bit
# the upper 7 bits of out_parity_bit are cleared
macro setParity(in_byte) {
local tmp = in_byte ^ (in_byte >> 1);
tmp = tmp ^ (tmp >> 2);
tmp = (tmp ^ (tmp >> 4)) & 1;
$(PV_flag) = (tmp == 0);
# $(PV_flag) = hasEvenParity(in_byte);
}
macro ioWrite(addr,val) {
*[io]:1 addr = val;
}
macro ioRead(addr,dest) {
dest = *[io]:1 addr;
}
@if defined(Z180_SEGMENTED)
macro push16(val16) {
SP = SP - 2;
ptr:$(PTRSIZE) = segment(rBBR,SP);
*:2 ptr = val16;
}
macro pop16(ret16) {
ptr:$(PTRSIZE) = segment(rBBR,SP);
ret16 = *:2 ptr;
SP = SP + 2;
}
macro push8(val8) {
SP = SP - 1;
ptr:$(PTRSIZE) = segment(rBBR,SP);
*:1 ptr = val8;
}
macro pop8(ret8) {
ptr:$(PTRSIZE) = segment(rBBR,SP);
ret8 = *:1 ptr;
SP = SP + 1;
}
macro swap(val16) {
ptr:$(PTRSIZE) = segment(rBBR,SP);
tmp:2 = *:2 ptr;
*:2 ptr = val16;
val16 = tmp;
}
macro MemRead(dest,off) {
ptr:$(PTRSIZE) = segment(rBBR,off);
dest = *:1 ptr;
}
macro MemStore(off,val) {
ptr:$(PTRSIZE) = segment(rBBR,off);
*:1 ptr = val;
}
macro JumpToLoc(off) {
ptr:$(PTRSIZE) = segment(rBBR,off);
goto [ptr];
}
@else
macro push16(val16) {
SP = SP - 2;
*:2 SP = val16;
}
macro pop16(ret16) {
ret16 = *:2 SP;
SP = SP + 2;
}
macro push8(val8) {
SP = SP - 1;
ptr:$(PTRSIZE) = SP;
*:1 ptr = val8;
}
macro pop8(ret8) {
ptr:$(PTRSIZE) = SP;
ret8 = *:1 ptr;
SP = SP + 1;
}
macro swap(val16) {
ptr:$(PTRSIZE) = SP;
tmp:2 = *:2 ptr;
*:2 ptr = val16;
val16 = tmp;
}
macro MemRead(dest,off) {
ptr:$(PTRSIZE) = off;
dest = *:1 ptr;
}
macro MemStore(off,val) {
ptr:$(PTRSIZE) = off;
*:1 ptr = val;
}
macro JumpToLoc(off) {
ptr:$(PTRSIZE) = off;
goto [ptr];
}
@endif
################################################################
@if defined(Z180)
Flag: "Flag" is reg0_3 { }
@endif
@if defined(Z180_SEGMENTED)
hlMem8: (HL) is HL { ptr:$(PTRSIZE) = segment(rBBR,HL); export *:1 ptr; }
ixMem8: (IX+simm8) is IX & simm8 {
off:2 = IX + simm8;
ptr:$(PTRSIZE) = segment(rBBR,off); export *:1 ptr;
}
ixMem8: (IX-val) is IX & simm8 & sign8=1 [ val = -simm8; ] {
off:2 = IX + simm8;
ptr:$(PTRSIZE) = segment(rBBR,off); export *:1 ptr;
}
iyMem8: (IY+simm8) is IY & simm8 {
off:$(PTRSIZE) = simm8;
ptr:$(PTRSIZE) = segment(rBBR,IY);
ptr = ptr + off; export *:1 ptr;
}
iyMem8: (IY-val) is IY & simm8 & sign8=1 [ val = -simm8; ] {
off:$(PTRSIZE) = simm8;
ptr:$(PTRSIZE) = segment(rBBR,IY);
ptr = ptr + off; export *:1 ptr;
}
@else # if Z180_SEGMENTED
@if defined(Z180)
hlMem8: (HL) is HL { ptr:$(PTRSIZE) = HL; export *:1 ptr; }
@endif
ixMem8: (IX+simm8) is IX & simm8 { ptr:$(PTRSIZE) = IX + simm8; export *:1 ptr; }
ixMem8: (IX-val) is IX & simm8 & sign8=1 [ val = -simm8; ] { ptr:$(PTRSIZE) = IX + simm8; export *:1 ptr; }
iyMem8: (IY+simm8) is IY & simm8 { ptr:$(PTRSIZE) = IY + simm8; export *:1 ptr; }
iyMem8: (IY-val) is IY & simm8 & sign8=1 [ val = -simm8; ] { ptr:$(PTRSIZE) = IY + simm8; export *:1 ptr; }
@endif # end !Z180_SEGMENTED
@if defined(Z180)
Addr16: imm16 is imm16 { export *:1 imm16; }
Mem8: (imm16) is imm16 { export *:1 imm16; }
Mem16: (imm16) is imm16 { export *:2 imm16; }
@else
Addr16: imm16 is imm16 { export *:1 imm16; }
Mem8: (imm16) is imm16 { export *:1 imm16; }
Mem16: (imm16) is imm16 { export *:2 imm16; }
@endif
RelAddr8: loc is simm8 [ loc = inst_next + simm8; ] { export *:1 loc; }
RstAddr: loc is bits3_3 [ loc = bits3_3 << 3; ] { export *:1 loc; }
@if defined(Z180)
IOAddr8: (imm8) is imm8 { export *[const]:2 imm8; }
IOAddr8a: (imm8) is assume8bitIOSpace=0 & imm8 { ptr:2 = (zext(A) << 8) + imm8; export ptr; }
IOAddr8a: (imm8) is assume8bitIOSpace=1 & imm8 { export *[const]:2 imm8; }
IOAddrC: (C) is assume8bitIOSpace=0 & C { ptr:2 = (zext(B) << 8) + zext(C); export ptr; }
IOAddrC: (C) is assume8bitIOSpace=1 & C { ptr:2 = zext(C); export ptr; }
@else
IOAddr8a: (imm8) is imm8 { export *[const]:2 imm8; }
IOAddrC: (C) is C { ptr:2 = zext(C); export ptr; }
@endif
cc: "NZ" is bits3_3=0x0 { c:1 = ($(Z_flag) == 0); export c; }
cc: "Z" is bits3_3=0x1 { c:1 = $(Z_flag); export c; }
cc: "NC" is bits3_3=0x2 { c:1 = ($(C_flag) == 0); export c; }
cc: "C" is bits3_3=0x3 { c:1 = $(C_flag); export c; }
cc: "PO" is bits3_3=0x4 { c:1 = ($(PV_flag) == 0); export c; }
cc: "PE" is bits3_3=0x5 { c:1 = $(PV_flag); export c; }
cc: "P" is bits3_3=0x6 { c:1 = ($(S_flag) == 0); export c; }
cc: "M" is bits3_3=0x7 { c:1 = $(S_flag); export c; }
cc2: "NZ" is bits3_3=0x4 { c:1 = ($(Z_flag) == 0); export c; }
cc2: "Z" is bits3_3=0x5 { c:1 = $(Z_flag); export c; }
cc2: "NC" is bits3_3=0x6 { c:1 = ($(C_flag) == 0); export c; }
cc2: "C" is bits3_3=0x7 { c:1 = $(C_flag); export c; }
################################################################
:LD reg3_3,reg0_3 is op6_2=0x1 & reg3_3 & reg0_3 {
reg3_3 = reg0_3;
}
:LD reg3_3,imm8 is op6_2=0x0 & reg3_3 & bits0_3=0x6; imm8 {
reg3_3 = imm8;
}
:LD reg3_3,(HL) is op6_2=0x1 & reg3_3 & bits0_3=0x6 & HL {
MemRead(reg3_3,HL);
}
:LD reg3_3,ixMem8 is op0_8=0xdd; op6_2=0x1 & reg3_3 & bits3_3!=0x6 & bits0_3=0x6; ixMem8 {
reg3_3 = ixMem8;
}
:LD reg3_3,iyMem8 is op0_8=0xfd; op6_2=0x1 & reg3_3 & bits3_3!=0x6 & bits0_3=0x6; iyMem8 {
reg3_3 = iyMem8;
}
:LD (HL),reg0_3 is op6_2=0x1 & bits3_3=0x6 & reg0_3 & HL {
MemStore(HL,reg0_3);
}
:LD ixMem8,reg0_3 is op0_8=0xdd; op6_2=0x1 & bits3_3=0x6 & reg0_3 & bits0_3!=0x6; ixMem8 {
ixMem8 = reg0_3;
}
:LD iyMem8,reg0_3 is op0_8=0xfd; op6_2=0x1 & bits3_3=0x6 & reg0_3 & bits0_3!=0x6; iyMem8 {
iyMem8 = reg0_3;
}
:LD (HL),imm8 is op0_8=0x36 & HL; imm8 {
tmp:1 = imm8;
MemStore(HL,tmp);
}
:LD ixMem8,imm8 is op0_8=0xdd; op6_2=0x0 & bits3_3=0x6 & bits0_3=0x6; ixMem8; imm8 {
ixMem8 = imm8;
}
:LD iyMem8,imm8 is op0_8=0xfd; op6_2=0x0 & bits3_3=0x6 & bits0_3=0x6; iyMem8; imm8 {
iyMem8 = imm8;
}
:LD A,(BC) is op0_8=0x0a & A & BC {
MemRead(A,BC);
}
:LD A,(DE) is op0_8=0x1a & A & DE {
MemRead(A,DE);
}
:LD A,Mem8 is op0_8=0x3a & A; Mem8 {
A = Mem8;
}
:LD (BC),A is op0_8=0x2 & BC & A {
MemStore(BC,A);
}
:LD (DE),A is op0_8=0x12 & DE & A {
MemStore(DE,A);
}
:LD Mem8,A is op0_8=0x32 & A; Mem8 {
Mem8 = A;
}
:LD A,I is op0_8=0xed & A & I; op0_8=0x57 {
A = I;
setResultFlags(I);
$(H_flag) = 0;
# $(PV_flag) = IFF2;
$(N_flag) = 0;
}
:LD A,R is op0_8=0xed & A & R; op0_8=0x5f {
A = R;
setResultFlags(R);
$(H_flag) = 0;
# $(PV_flag) = IFF2;
$(N_flag) = 0;
}
:LD I,A is op0_8=0xed & A & I; op0_8=0x47 {
I = A;
}
:LD R,A is op0_8=0xed & A & R; op0_8=0x4f {
R = A;
}
:LD dRegPair4_2,imm16 is op6_2=0x0 & dRegPair4_2 & bits0_4=0x1; imm16 {
dRegPair4_2 = imm16;
}
:LD IX,imm16 is op0_8=0xdd & IX; op0_8=0x21; imm16 {
IX = imm16;
}
:LD IY,imm16 is op0_8=0xfd & IY; op0_8=0x21; imm16 {
IY = imm16;
}
:LD HL,Mem16 is op0_8=0x2a & HL; Mem16 {
HL = Mem16;
}
:LD dRegPair4_2,Mem16 is op0_8=0xed; op6_2=0x1 & dRegPair4_2 & bits0_4=0xb; Mem16 {
dRegPair4_2 = Mem16;
}
:LD IX,Mem16 is op0_8=0xdd & IX; op0_8=0x2a; Mem16 {
IX = Mem16;
}
:LD IY,Mem16 is op0_8=0xfd & IY; op0_8=0x2a; Mem16 {
IY = Mem16;
}
:LD Mem16,HL is op0_8=0x22 & HL; Mem16 {
Mem16 = HL;
}
:LD Mem16,dRegPair4_2 is op0_8=0xed; op6_2=0x1 & dRegPair4_2 & bits0_4=0x3; Mem16 {
Mem16 = dRegPair4_2;
}
:LD Mem16,IX is op0_8=0xdd & IX; op0_8=0x22; Mem16 {
Mem16 = IX;
}
:LD Mem16,IY is op0_8=0xfd & IY; op0_8=0x22; Mem16 {
Mem16 = IY;
}
:LD SP,HL is op0_8=0xf9 & SP & HL {
SP = HL;
}
:LD SP,IX is op0_8=0xdd & SP & IX; op0_8=0xf9 {
SP = IX;
}
:LD SP,IY is op0_8=0xfd & SP & IY; op0_8=0xf9 {
SP = IY;
}
:PUSH qRegPair4_2 is op6_2=0x3 & qRegPair4_2 & bits0_4=0x5 {
push16(qRegPair4_2);
}
:PUSH IX is op0_8=0xdd & IX; op0_8=0xe5 {
push16(IX);
}
:PUSH IY is op0_8=0xfd & IY; op0_8=0xe5 {
push16(IY);
}
:POP qRegPair4_2 is op6_2=0x3 & qRegPair4_2 & bits0_4=0x1 {
pop16(qRegPair4_2);
}
:POP IX is op0_8=0xdd & IX; op0_8=0xe1 {
pop16(IX);
}
# ?? Manual appears to have incorrect encoding
:POP IY is op0_8=0xfd & IY; op0_8=0xe1 {
pop16(IY);
}
:EX DE,HL is op0_8=0xeb & DE & HL {
tmp:2 = DE;
DE = HL;
HL = tmp;
}
:EX AF, AF_ is op0_8=0x08 & AF & AF_ {
tmp:2 = AF;
AF = AF_;
AF_ = tmp;
}
:EXX is op0_8=0xd9 {
tmp:2 = BC;
BC = BC_;
BC_ = tmp;
tmp = DE;
DE = DE_;
DE_ = tmp;
tmp = HL;
HL = HL_;
HL_ = tmp;
}
:EX (SP),HL is op0_8=0xe3 & SP & HL {
swap(HL);
}
:EX (SP),IX is op0_8=0xdd & SP & IX; op0_8=0xe3 {
swap(IX);
}
:EX (SP),IY is op0_8=0xfd & SP & IY; op0_8=0xe3 {
swap(IY);
}
# ?? Instruction manual contradicts itself - not sure what to do here ??
:LDI is op0_8=0xed; op0_8=0xa0 {
val:1 = 0;
MemRead(val,HL);
MemStore(DE,val);
DE = DE + 1;
HL = HL + 1;
BC = BC - 1;
$(H_flag) = 0;
$(PV_flag) = (BC != 0);
$(N_flag) = 0;
}
:LDIR is op0_8=0xed; op0_8=0xb0 {
tmp:1 = 0;
MemRead(tmp,HL);
MemStore(DE,tmp);
DE = DE + 1;
HL = HL + 1;
BC = BC - 1;
if (BC != 0) goto inst_start;
$(H_flag) = 0;
$(PV_flag) = (BC != 0);
$(N_flag) = 0;
}
:LDD is op0_8=0xed; op0_8=0xa8 {
DE = DE - 1;
HL = HL - 1;
BC = BC - 1;
$(H_flag) = 0;
$(PV_flag) = (BC != 0);
$(N_flag) = 0;
}
:LDDR is op0_8=0xed; op0_8=0xb8 {
tmp:1 = 0;
MemRead(tmp,HL);
MemStore(DE,tmp);
DE = DE - 1;
HL = HL - 1;
BC = BC - 1;
if (BC != 0) goto inst_start;
$(H_flag) = 0;
$(PV_flag) = 0;
$(N_flag) = 0;
}
:CPI is op0_8=0xed; op0_8=0xa1 {
val:1 = 0;
MemRead(val,HL);
cmp:1 = A - val;
setResultFlags(cmp);
HL = HL + 1;
BC = BC - 1;
carries:1 = (~A & val) | (val & cmp) | (cmp & ~A);
$(H_flag) = (carries & 0b00001000) != 0;
$(PV_flag) = (BC != 0);
$(N_flag) = 1;
}
:CPIR is op0_8=0xed; op0_8=0xb1 {
val:1 = 0;
MemRead(val,HL);
cmp:1 = A - val;
setResultFlags(cmp);
HL = HL + 1;
BC = BC - 1;
if (cmp != 0 || BC != 0) goto inst_start;
carries:1 = (~A & val) | (val & cmp) | (cmp & ~A);
$(H_flag) = (carries & 0b00001000) != 0;
$(PV_flag) = (BC != 0);
$(N_flag) = 1;
}
:CPD is op0_8=0xed; op0_8=0xa9 {
val:1 = 0;
MemRead(val,HL);
cmp:1 = A - val;
setResultFlags(cmp);
HL = HL - 1;
BC = BC - 1;
carries:1 = (~A & val) | (val & cmp) | (cmp & ~A);
$(H_flag) = (carries & 0b00001000) != 0;
$(PV_flag) = (BC != 0);
$(N_flag) = 1;
}
:CPDR is op0_8=0xed; op0_8=0xb9 {
val:1 = 0;
MemRead(val,HL);
cmp:1 = A - val;
setResultFlags(cmp);
HL = HL - 1;
BC = BC - 1;
if (cmp != 0 || BC != 0) goto inst_start;
carries:1 = (~A & val) | (val & cmp) | (cmp & ~A);
$(H_flag) = (carries & 0b00001000) != 0;
$(PV_flag) = (BC != 0);
$(N_flag) = 1;
}
:ADD A, reg0_3 is op6_2=0x2 & bits3_3=0x0 & reg0_3 & A {
local A_temp = A;
local reg_temp = reg0_3;
A = A + reg0_3;
setResultFlags(A);
additionFlags(A_temp, reg_temp);
}
:ADD A, imm8 is op0_8=0xc6; imm8 & A {
local A_temp = A;
A = A + imm8;
setResultFlags(A);
additionFlags(A_temp, imm8);
}
:ADD A, (HL) is op0_8=0x86 & HL & A {
val:1 = 0;
MemRead(val,HL);
local A_temp = A;
A = A + val;
setResultFlags(A);
additionFlags(A_temp, val);
}
:ADD A, ixMem8 is op0_8=0xdd; op0_8=0x86; ixMem8 & A {
val:1 = ixMem8;
local A_temp = A;
A = A + val;
setResultFlags(A);
additionFlags(A_temp, val);
}
:ADD A, iyMem8 is op0_8=0xfd; op0_8=0x86; iyMem8 & A {
val:1 = iyMem8;
local A_temp = A;
A = A + val;
setResultFlags(A);
additionFlags(A_temp, val);
}
:ADC A, reg0_3 is op6_2=0x2 & bits3_3=0x1 & reg0_3 & A {
additionWithCarry(A, reg0_3, A);
setResultFlags(A);
}
:ADC A, imm8 is op0_8=0xce; imm8 & A {
additionWithCarry(A, imm8, A);
setResultFlags(A);
}
:ADC A, (HL) is op0_8=0x8e & HL & A {
val:1 = 0;
MemRead(val,HL);
additionWithCarry(A, val, A);
setResultFlags(A);
}
:ADC A, ixMem8 is op0_8=0xdd; op0_8=0x8e; ixMem8 & A{
val:1 = ixMem8;
additionWithCarry(A, val, A);
}
:ADC A, iyMem8 is op0_8=0xfd; op0_8=0x8e; iyMem8 & A {
val:1 = iyMem8;
additionWithCarry(A, val, A);
setResultFlags(A);
}
:SUB reg0_3 is op6_2=0x2 & bits3_3=0x2 & reg0_3 {
local A_temp = A;
A = A - reg0_3;
subtractionFlags(A_temp, reg0_3);
setResultFlags(A);
}
:SUB imm8 is op0_8=0xd6; imm8 {
local A_temp = A;
A = A - imm8;
subtractionFlags(A_temp, imm8);
setResultFlags(A);
}
:SUB (HL) is op0_8=0x96 & HL {
val:1 = 0;
MemRead(val,HL);
local A_temp = A;
A = A - val;
subtractionFlags(A_temp, val);
setResultFlags(A);
}
:SUB ixMem8 is op0_8=0xdd; op0_8=0x96; ixMem8 {
val:1 = ixMem8;
local A_temp = A;
A = A - val;
subtractionFlags(A_temp, val);
setResultFlags(A);
}
:SUB iyMem8 is op0_8=0xfd; op0_8=0x96; iyMem8 {
val:1 = iyMem8;
local A_temp = A;
A = A - val;
subtractionFlags(A_temp, val);
setResultFlags(A);
}
:SBC A, reg0_3 is op6_2=0x2 & bits3_3=0x3 & reg0_3 & A {
subtractionWithCarry(A, reg0_3, A);
setResultFlags(A);
}
:SBC A, imm8 is op0_8=0xde; imm8 & A {
subtractionWithCarry(A, imm8, A);
setResultFlags(A);
}
:SBC A, (HL) is op0_8=0x9e & HL & A {
val:1 = 0;
MemRead(val,HL);
subtractionWithCarry(A, val, A);
setResultFlags(A);
}
:SBC A, ixMem8 is op0_8=0xdd; op0_8=0x9e; ixMem8 & A {
val:1 = ixMem8;
subtractionWithCarry(A, val, A);
setResultFlags(A);
}
:SBC A, iyMem8 is op0_8=0xfd; op0_8=0x9e; iyMem8 & A {
val:1 = iyMem8;
subtractionWithCarry(A, val, A);
setResultFlags(A);
}
:AND reg0_3 is op6_2=0x2 & bits3_3=0x4 & reg0_3 {
$(H_flag) = 1;
$(C_flag) = 0;
$(N_flag) = 0;
A = A & reg0_3;
setResultFlags(A);
setParity(A);
}
:AND imm8 is op0_8=0xe6; imm8 {
$(H_flag) = 1;
$(C_flag) = 0;
$(N_flag) = 0;
A = A & imm8;
setResultFlags(A);
setParity(A);
}
:AND (HL) is op0_8=0xa6 & HL {
$(H_flag) = 1;
$(C_flag) = 0;
$(N_flag) = 0;
tmp:1 = 0;
MemRead(tmp,HL);
A = A & tmp;
setResultFlags(A);
setParity(A);
}
:AND ixMem8 is op0_8=0xdd; op0_8=0xa6; ixMem8 {
$(H_flag) = 1;
$(C_flag) = 0;
$(N_flag) = 0;
A = A & ixMem8;
setResultFlags(A);
setParity(A);
}
:AND iyMem8 is op0_8=0xfd; op0_8=0xa6; iyMem8 {
$(H_flag) = 1;
$(C_flag) = 0;
$(N_flag) = 0;
A = A & iyMem8;
setResultFlags(A);
setParity(A);
}
:OR reg0_3 is op6_2=0x2 & bits3_3=0x6 & reg0_3 {
$(H_flag) = 0;
$(C_flag) = 0;
$(N_flag) = 0;
A = A | reg0_3;
setResultFlags(A);
setParity(A);
}
:OR imm8 is op0_8=0xf6; imm8 {
$(H_flag) = 0;
$(C_flag) = 0;
$(N_flag) = 0;
A = A | imm8;
setResultFlags(A);
setParity(A);
}
:OR (HL) is op0_8=0xb6 & HL {
$(H_flag) = 0;
$(C_flag) = 0;
$(N_flag) = 0;
val:1 = 0;
MemRead(val,HL);
A = A | val;
setResultFlags(A);
setParity(A);
}
:OR ixMem8 is op0_8=0xdd; op0_8=0xb6; ixMem8 {
$(H_flag) = 0;
$(C_flag) = 0;
$(N_flag) = 0;
A = A | ixMem8;
setResultFlags(A);
setParity(A);
}
:OR iyMem8 is op0_8=0xfd; op0_8=0xb6; iyMem8 {
$(H_flag) = 0;
$(C_flag) = 0;
$(N_flag) = 0;
A = A | iyMem8;
setResultFlags(A);
setParity(A);
}
:XOR reg0_3 is op6_2=0x2 & bits3_3=0x5 & reg0_3 {
$(H_flag) = 0;
$(C_flag) = 0;
$(N_flag) = 0;
A = A ^ reg0_3;
setResultFlags(A);
setParity(A);
}
:XOR imm8 is op0_8=0xee; imm8 {
$(H_flag) = 0;
$(C_flag) = 0;
$(N_flag) = 0;
A = A ^ imm8;
setResultFlags(A);
setParity(A);
}
:XOR (HL) is op0_8=0xae & HL {
$(H_flag) = 0;
$(C_flag) = 0;
$(N_flag) = 0;
val:1 = 0;
MemRead(val,HL);
A = A ^ val;
setResultFlags(A);
setParity(A);
}
:XOR ixMem8 is op0_8=0xdd; op0_8=0xae; ixMem8 {
$(H_flag) = 0;
$(C_flag) = 0;
$(N_flag) = 0;
A = A ^ ixMem8;
setResultFlags(A);
setParity(A);
}
:XOR iyMem8 is op0_8=0xfd; op0_8=0xae; iyMem8 {
$(H_flag) = 0;
$(C_flag) = 0;
$(N_flag) = 0;
A = A ^ iyMem8;
setResultFlags(A);
setParity(A);
}
:CP reg0_3 is op6_2=0x2 & bits3_3=0x7 & reg0_3 {
cmp:1 = A - reg0_3;
subtractionFlags(A, reg0_3);
setResultFlags(cmp);
}
:CP imm8 is op0_8=0xfe; imm8 {
cmp:1 = A - imm8;
subtractionFlags(A, imm8);
setResultFlags(cmp);
}
:CP (HL) is op0_8=0xbe & HL {
val:1 = 0;
MemRead(val,HL);
cmp:1 = A - val;
subtractionFlags(A, val);
setResultFlags(cmp);
}
:CP ixMem8 is op0_8=0xdd; op0_8=0xbe; ixMem8 {
val:1 = ixMem8;
cmp:1 = A - val;
subtractionFlags(A, val);
setResultFlags(cmp);
}
:CP iyMem8 is op0_8=0xfd; op0_8=0xbe; iyMem8 {
val:1 = iyMem8;
cmp:1 = A - val;
subtractionFlags(A, val);
setResultFlags(cmp);
}
:INC reg3_3 is op6_2=0x0 & reg3_3 & bits0_3=0x4 {
local r_temp = reg3_3;
reg3_3 = reg3_3 + 1;
setResultFlags(reg3_3);
additionFlags(r_temp, 1);
}
:INC (HL) is op0_8=0x34 & HL {
val:1 = 0;
MemRead(val,HL);
val_temp:1 = val;
val = val + 1;
MemStore(HL,val);
setResultFlags(val);
additionFlags(val_temp, 1);
}
:INC ixMem8 is op0_8=0xdd; op0_8=0x34; ixMem8 {
val:1 = ixMem8;
val_temp:1 = val;
val = val + 1;
ixMem8 = val;
setResultFlags(val);
additionFlags(val_temp, 1);
}
:INC iyMem8 is op0_8=0xfd; op0_8=0x34; iyMem8 {
val:1 = iyMem8;
val_temp:1 = val;
val = val + 1;
iyMem8 = val;
setResultFlags(val);
additionFlags(val_temp, 1);
}
:DEC reg3_3 is op6_2=0x0 & reg3_3 & bits0_3=0x5 {
local r_temp = reg3_3;
reg3_3 = reg3_3 - 1;
subtractionFlagsNoC(r_temp, 1);
setResultFlags(reg3_3);
}
:DEC (HL) is op0_8=0x35 & HL {
val:1 = 0;
MemRead(val,HL);
val_temp:1 = val;
val = val - 1;
MemStore(HL,val);
subtractionFlagsNoC(val_temp, 1);
setResultFlags(val);
}
:DEC ixMem8 is op0_8=0xdd; op0_8=0x35; ixMem8 {
val:1 = ixMem8;
val_temp:1 = val;
val = val - 1;
ixMem8 = val;
subtractionFlagsNoC(val_temp, 1);
setResultFlags(val);
}
:DEC iyMem8 is op0_8=0xfd; op0_8=0x35; iyMem8 {
val:1 = iyMem8;
val_temp:1 = val;
val = val - 1;
iyMem8 = val;
subtractionFlagsNoC(val_temp, 1);
setResultFlags(val);
}
:DAA is op0_8=0x27 {
if (DECOMPILE_MODE) goto <forDecompilation>;
HN:1 = A >> 4; # high nibble
LN:1 = A & 0xF; # low nibbble
#
# If (C and H are both 0, and both nibbles are in range[0,9] no
# adjustment is needed.
#
if (($(C_flag) == 0) & ($(H_flag) == 0) & (HN <= 0x9) & (LN <= 0x9)) goto <exit>;
if ($(N_flag) == 1) goto <adjustAfterSubtract>;
#<adjustAfterAdd>, in effect
if ($(C_flag) == 0 & $(H_flag) == 0 & HN <= 0x8 & LN >= 0xA & LN <= 0xF) goto <addcase2>;
if ($(C_flag) == 0 & $(H_flag) == 1 & HN <= 0x9 & LN <= 0x3) goto <addcase3>;
if ($(C_flag) == 0 & $(H_flag) == 0 & HN >= 0xA & HN <= 0xF & LN <= 0x9) goto <addcase4>;
if ($(C_flag) == 0 & $(H_flag) == 0 & HN >= 0x9 & HN <= 0xF & LN >= 0xA & LN <= 0xF) goto <addcase5>;
if ($(C_flag) == 0 & $(H_flag) == 1 & HN >= 0xA & HN <= 0xF & LN <= 0x3) goto <addcase6>;
if ($(C_flag) == 1 & $(H_flag) == 0 & HN <= 0x2 & LN <= 0x9) goto <addcase7>;
if ($(C_flag) == 1 & $(H_flag) == 0 & HN <= 0x2 & LN >= 0xA & LN <= 0xF) goto <addcase8>;
if ($(C_flag) == 1 & $(H_flag) == 1 & HN <= 0x3 & LN <= 0x3) goto <addcase9>;
goto <exit>;
# Cases for addition
#<addcase1>
# Isn't used
<addcase2>
A = A + 0x06;
goto <exit>;
<addcase3>
A = A + 0x06;
goto <exit>;
<addcase4>
A = A + 0x60;
$(C_flag) = 1;
goto <exit>;
<addcase5>
A = A + 0x66;
$(C_flag) = 1;
goto <exit>;
<addcase6>
A = A + 0x66;
$(C_flag) = 1;
goto <exit>;
<addcase7>
A = A + 0x60;
goto <exit>;
<addcase8>
A = A + 0x66;
goto <exit>;
<addcase9>
A = A + 0x66;
goto <exit>;
<adjustAfterSubtract>
# Cases for subtraction
#if ($(C_flag) == 0 & $(H_flag) == 0 & HN >= 0x0 & HN <= 0x9 & LN >= 0x0 & LN <= 0x9) goto <subcase1>;
if ($(C_flag) == 0 & $(H_flag) == 1 & HN <= 0x8 & LN >= 0x6 & LN <= 0xF) goto <subcase2>;
if ($(C_flag) == 1 & $(H_flag) == 0 & HN >= 0x7 & HN <= 0xF & LN <= 0x9) goto <subcase3>;
if ($(C_flag) == 1 & $(H_flag) == 1 & HN >= 0x6 & HN <= 0xF & LN >= 0x6 & LN <= 0xF) goto <subcase4>;
goto <exit>;
#<subcase1>
# Isn't used
<subcase2>
A = A + 0xFA;
goto <exit>;
<subcase3>
A = A + 0xA0;
goto <exit>;
<subcase4>
A = A + 0x9A;
<exit>
setResultFlags(A);
setParity(A);
goto <endDAA>;
<forDecompilation>
A_temp:1 = A;
A = BCDadjust(A_temp, $(C_flag), $(H_flag));
$(C_flag) = BCDadjustCarry(A_temp, $(C_flag), $(H_flag));
setResultFlags(A);
$(PV_flag) = hasEvenParity(A);
<endDAA>
}
:CPL is op0_8=0x2f {
A = ~A;
$(H_flag) = 1;
$(N_flag) = 1;
}
:NEG is op0_8=0xed; op0_8=0x44 {
A_temp:1 = A;
A = -A;
subtractionFlags(0, A_temp);
setResultFlags(A);
}
:CCF is op0_8=0x3f {
$(C_flag) = !$(C_flag);
$(N_flag) = 0;
}
:SCF is op0_8=0x37 {
$(C_flag) = 1;
$(H_flag) = 0;
$(N_flag) = 0;
}
:NOP is op0_8=0x0 {
}
:HALT is op0_8=0x76 {
halt();
}
:DI is op0_8=0xf3 {
# IFF1 = 0;
# IFF2 = 0;
disableMaskableInterrupts();
}
:EI is op0_8=0xfb {
# IFF1 = 1;
# IFF2 = 1;
enableMaskableInterrupts();
}
:IM 0 is op0_8=0xed; op0_8=0x46 {
setInterruptMode(0:1);
}
:IM 1 is op0_8=0xed; op0_8=0x56 {
setInterruptMode(1:1);
}
:IM 2 is op0_8=0xed; op0_8=0x5e {
setInterruptMode(2:1);
}
:ADD HL,sRegPair4_2 is op6_2=0x0 & sRegPair4_2 & bits0_4=0x9 & HL {
local HL_temp = HL;
local Reg_temp = sRegPair4_2;
HL = HL + sRegPair4_2;
additionFlagsNoPV(HL_temp, Reg_temp);
}
:ADC HL,sRegPair4_2 is op0_8=0xed & HL; op6_2=0x1 & sRegPair4_2 & bits0_4=0xa {
local HL_temp = HL;
local Reg_temp = sRegPair4_2;
HL = HL + sRegPair4_2 + zext($(C_flag));
setResultFlags(HL);
additionFlagsNoPV(HL_temp, Reg_temp);
}
:SBC HL,sRegPair4_2 is op0_8=0xed & HL; op6_2=0x1 & sRegPair4_2 & bits0_4=0x2 {
subtractionWithCarry(HL, sRegPair4_2, HL);
setResultFlags(HL);
}
:ADD IX,pRegPair4_2 is op0_8=0xdd & IX; op6_2=0x0 & pRegPair4_2 & bits0_4=0x9 {
local IX_temp = IX;
local Reg_temp = pRegPair4_2;
IX = IX + pRegPair4_2;
additionFlagsNoPV(IX_temp, Reg_temp);
}
:ADD IY,pRegPair4_2 is op0_8=0xfd & IY; op6_2=0x0 & pRegPair4_2 & bits0_4=0x9 {
local IY_temp = IY;
local Reg_temp = pRegPair4_2;
IY = IY + pRegPair4_2;
additionFlagsNoPV(IY_temp, Reg_temp);
}
:INC sRegPair4_2 is op6_2=0x0 & sRegPair4_2 & bits0_4=0x3 {
sRegPair4_2 = sRegPair4_2 + 1;
}
:INC IX is op0_8=0xdd & IX; op0_8=0x23 {
IX = IX + 1;
}
:INC IY is op0_8=0xfd & IY; op0_8=0x23 {
IY = IY + 1;
}
:DEC sRegPair4_2 is op6_2=0x0 & sRegPair4_2 & bits0_4=0xb {
sRegPair4_2 = sRegPair4_2 - 1;
}
:DEC IX is op0_8=0xdd & IX; op0_8=0x2b {
IX = IX - 1;
}
:DEC IY is op0_8=0xfd & IY; op0_8=0x2b {
IY = IY - 1;
}
:RLCA is op0_8=0x07 {
$(C_flag) = (A >> 7);
A = (A << 1) | $(C_flag);
$(H_flag) = 0;
$(N_flag) = 0;
}
:RLA is op0_8=0x17 {
nextC:1 = (A >> 7);
A = (A << 1) | $(C_flag);
$(C_flag) = nextC;
$(H_flag) = 0;
$(N_flag) = 0;
}
:RRCA is op0_8=0x0f {
$(C_flag) = (A & 1);
A = (A >> 1) | ($(C_flag) << 7);
$(H_flag) = 0;
$(N_flag) = 0;
}
:RRA is op0_8=0x1f {
nextC:1 = (A & 1);
A = (A >> 1) | ($(C_flag) << 7);
$(C_flag) = nextC;
$(H_flag) = 0;
$(N_flag) = 0;
}
:RLC reg0_3 is op0_8=0x0cb; op6_2=0x0 & bits3_3=0x0 & reg0_3 {
$(C_flag) = (reg0_3 >> 7);
reg0_3 = (reg0_3 << 1) | $(C_flag);
setResultFlags(reg0_3);
$(H_flag) = 0;
setParity(reg0_3);
$(N_flag) = 0;
}
:RLC (HL) is op0_8=0x0cb & HL; op0_8=0x06 {
val:1 = 0;
MemRead(val,HL);
$(C_flag) = (val >> 7);
val = (val << 1) | $(C_flag);
setResultFlags(val);
MemStore(HL,val);
$(H_flag) = 0;
setParity(val);
$(N_flag) = 0;
}
:RLC ixMem8 is op0_8=0x0dd; op0_8=0xcb; ixMem8; op0_8=0x06 {
val:1 = ixMem8;
$(C_flag) = (val >> 7);
val = (val << 1) | $(C_flag);
setResultFlags(val);
ixMem8 = val;
$(H_flag) = 0;
$(N_flag) = 0;
}
:RLC iyMem8 is op0_8=0x0fd; op0_8=0xcb; iyMem8; op0_8=0x06 {
val:1 = iyMem8;
$(C_flag) = (val >> 7);
val = (val << 1) | $(C_flag);
setResultFlags(val);
iyMem8 = val;
$(H_flag) = 0;
setParity(val);
$(N_flag) = 0;
}
:RL reg0_3 is op0_8=0x0cb; op6_2=0x0 & bits3_3=0x2 & reg0_3 {
nextC:1 = (reg0_3 >> 7);
reg0_3 = (reg0_3 << 1) | $(C_flag);
$(C_flag) = nextC;
setResultFlags(reg0_3);
$(H_flag) = 0;
setParity(reg0_3);
$(N_flag) = 0;
}
:RL (HL) is op0_8=0x0cb & HL; op0_8=0x16 {
val:1 = 0;
MemRead(val,HL);
nextC:1 = (val >> 7);
val = (val << 1) | $(C_flag);
$(C_flag) = nextC;
setResultFlags(val);
MemStore(HL,val);
$(H_flag) = 0;
setParity(val);
$(N_flag) = 0;
}
:RL ixMem8 is op0_8=0x0dd; op0_8=0xcb; ixMem8; op0_8=0x16 {
val:1 = ixMem8;
nextC:1 = (val >> 7);
val = (val << 1) | $(C_flag);
$(C_flag) = nextC;
setResultFlags(val);
ixMem8 = val;
$(H_flag) = 0;
setParity(val);
$(N_flag) = 0;
}
:RL iyMem8 is op0_8=0x0fd; op0_8=0xcb; iyMem8; op0_8=0x16 {
val:1 = iyMem8;
nextC:1 = (val >> 7);
val = (val << 1) | $(C_flag);
$(C_flag) = nextC;
setResultFlags(val);
iyMem8 = val;
$(H_flag) = 0;
setParity(val);
$(N_flag) = 0;
}
:RRC reg0_3 is op0_8=0x0cb; op6_2=0x0 & bits3_3=0x1 & reg0_3 {
$(C_flag) = (reg0_3 & 1);
reg0_3 = (reg0_3 >> 1) | ($(C_flag) << 7);
setResultFlags(reg0_3);
$(H_flag) = 0;
setParity(reg0_3);
$(N_flag) = 0;
}
:RRC (HL) is op0_8=0x0cb & HL; op0_8=0x0e {
val:1 = 0;
MemRead(val,HL);
$(C_flag) = (val & 1);
val = (val >> 1) | ($(C_flag) << 7);
setResultFlags(val);
MemStore(HL,val);
$(H_flag) = 0;
setParity(val);
$(N_flag) = 0;
}
:RRC ixMem8 is op0_8=0x0dd; op0_8=0xcb; ixMem8; op0_8=0x0e {
val:1 = ixMem8;
$(C_flag) = (val & 1);
val = (val >> 1) | ($(C_flag) << 7);
setResultFlags(val);
ixMem8 = val;
$(H_flag) = 0;
setParity(val);
$(N_flag) = 0;
}
:RRC iyMem8 is op0_8=0x0fd; op0_8=0xcb; iyMem8; op0_8=0x0e {
val:1 = iyMem8;
$(C_flag) = (val & 1);
val = (val >> 1) | ($(C_flag) << 7);
setResultFlags(val);
iyMem8 = val;
$(H_flag) = 0;
setParity(val);
$(N_flag) = 0;
}
:RR reg0_3 is op0_8=0x0cb; op6_2=0x0 & bits3_3=0x3 & reg0_3 {
nextC:1 = (reg0_3 & 1);
reg0_3 = (reg0_3 >> 1) | ($(C_flag) << 7);
$(C_flag) = nextC;
setResultFlags(reg0_3);
$(H_flag) = 0;
setParity(reg0_3);
$(N_flag) = 0;
}
:RR (HL) is op0_8=0x0cb & HL; op0_8=0x1e {
val:1 = 0;
MemRead(val,HL);
nextC:1 = (val & 1);
val = (val >> 1) | ($(C_flag) << 7);
$(C_flag) = nextC;
setResultFlags(val);
MemStore(HL,val);
$(H_flag) = 0;
setParity(val);
$(N_flag) = 0;
}
:RR ixMem8 is op0_8=0x0dd; op0_8=0xcb; ixMem8; op0_8=0x1e {
val:1 = ixMem8;
nextC:1 = (val & 1);
val = (val >> 1) | ($(C_flag) << 7);
$(C_flag) = nextC;
setResultFlags(val);
ixMem8 = val;
$(H_flag) = 0;
setParity(val);
$(N_flag) = 0;
}
:RR iyMem8 is op0_8=0x0fd; op0_8=0xcb; iyMem8; op0_8=0x1e {
val:1 = iyMem8;
nextC:1 = (val & 1);
val = (val >> 1) | ($(C_flag) << 7);
$(C_flag) = nextC;
setResultFlags(val);
iyMem8 = val;
$(H_flag) = 0;
setParity(val);
$(N_flag) = 0;
}
:SLA reg0_3 is op0_8=0x0cb; op6_2=0x0 & bits3_3=0x4 & reg0_3 {
$(C_flag) = (reg0_3 >> 7);
reg0_3 = reg0_3 << 1;
setResultFlags(reg0_3);
$(H_flag) = 0;
setParity(reg0_3);
$(N_flag) = 0;
}
:SLA (HL) is op0_8=0x0cb & HL; op0_8=0x26 {
val:1 = 0;
MemRead(val,HL);
$(C_flag) = (val >> 7);
val = val << 1;
setResultFlags(val);
MemStore(HL,val);
$(H_flag) = 0;
setParity(val);
$(N_flag) = 0;
}
:SLA ixMem8 is op0_8=0x0dd; op0_8=0xcb; ixMem8; op0_8=0x26 {
val:1 = ixMem8;
$(C_flag) = (val >> 7);
val = val << 1;
setResultFlags(val);
ixMem8 = val;
$(H_flag) = 0;
setParity(val);
$(N_flag) = 0;
}
:SLA iyMem8 is op0_8=0x0fd; op0_8=0xcb; iyMem8; op0_8=0x26 {
val:1 = iyMem8;
$(C_flag) = (val >> 7);
val = val << 1;
setResultFlags(val);
iyMem8 = val;
$(H_flag) = 0;
setParity(val);
$(N_flag) = 0;
}
:SRA reg0_3 is op0_8=0x0cb; op6_2=0x0 & bits3_3=0x5 & reg0_3 {
$(C_flag) = (reg0_3 & 1);
reg0_3 = reg0_3 s>> 1;
setResultFlags(reg0_3);
$(H_flag) = 0;
setParity(reg0_3);
$(N_flag) = 0;
}
:SRA (HL) is op0_8=0x0cb & HL; op0_8=0x2e {
val:1 = 0;
MemRead(val,HL);
$(C_flag) = (val & 1);
val = val s>> 1;
setResultFlags(val);
MemStore(HL,val);
$(H_flag) = 0;
setParity(val);
$(N_flag) = 0;
}
:SRA ixMem8 is op0_8=0x0dd; op0_8=0xcb; ixMem8; op0_8=0x2e {
val:1 = ixMem8;
$(C_flag) = (val & 1);
val = val s>> 1;
setResultFlags(val);
ixMem8 = val;
$(H_flag) = 0;
setParity(val);
$(N_flag) = 0;
}
:SRA iyMem8 is op0_8=0x0fd; op0_8=0xcb; iyMem8; op0_8=0x2e {
val:1 = iyMem8;
$(C_flag) = (val & 1);
val = val s>> 1;
setResultFlags(val);
iyMem8 = val;
$(H_flag) = 0;
setParity(val);
$(N_flag) = 0;
}
:SRL reg0_3 is op0_8=0x0cb; op6_2=0x0 & bits3_3=0x7 & reg0_3 {
$(C_flag) = (reg0_3 & 1);
reg0_3 = reg0_3 >> 1;
setResultFlags(reg0_3);
$(H_flag) = 0;
setParity(reg0_3);
$(N_flag) = 0;
}
:SRL (HL) is op0_8=0x0cb & HL; op0_8=0x3e {
val:1 = 0;
MemRead(val,HL);
$(C_flag) = (val & 1);
val = val >> 1;
setResultFlags(val);
MemStore(HL,val);
$(H_flag) = 0;
setParity(val);
$(N_flag) = 0;
}
:SRL ixMem8 is op0_8=0x0dd; op0_8=0xcb; ixMem8; op0_8=0x3e {
val:1 = ixMem8;
$(C_flag) = (val & 1);
val = val >> 1;
setResultFlags(val);
ixMem8 = val;
$(H_flag) = 0;
setParity(val);
$(N_flag) = 0;
}
:SRL iyMem8 is op0_8=0x0fd; op0_8=0xcb; iyMem8; op0_8=0x3e {
val:1 = iyMem8;
$(C_flag) = (val & 1);
val = val >> 1;
setResultFlags(val);
iyMem8 = val;
$(H_flag) = 0;
setParity(val);
$(N_flag) = 0;
}
:RLD is op0_8=0xed; op0_8=0x6f {
val:1 = 0;
MemRead(val,HL);
nibA:1 = A & 0x0f;
nibM:1 = val >> 4;
val = (val << 4) | nibA;
A = (A & 0xf0) | nibM;
MemStore(HL,val);
@if defined(Z180)
setResultFlags(val);
@else
setResultFlags(A);
@endif
$(H_flag) = 0;
setParity(A);
$(N_flag) = 0;
}
:RRD is op0_8=0xed; op0_8=0x67 {
val:1 = 0;
MemRead(val,HL);
nibA:1 = A & 0x0f;
nibM:1 = val & 0x0f;
val = (val >> 4) | (nibA << 4);
A = (A & 0xf0) | nibM;
MemStore(HL,val);
@if defined(Z180)
setResultFlags(val);
@else
setResultFlags(A);
@endif
$(H_flag) = 0;
setParity(A);
$(N_flag) = 0;
}
:BIT bits3_3,reg0_3 is op0_8=0xcb; op6_2=0x1 & bits3_3 & reg0_3 {
mask:1 = (1 << bits3_3);
$(Z_flag) = ((reg0_3 & mask) == 0);
$(H_flag) = 1;
$(N_flag) = 0;
}
:BIT bits3_3,(HL) is op0_8=0xcb & HL; op6_2=0x1 & bits3_3 & bits0_3=0x6 {
mask:1 = (1 << bits3_3);
val:1 = 0;
MemRead(val,HL);
$(Z_flag) = ((val & mask) == 0);
$(H_flag) = 1;
$(N_flag) = 0;
}
:BIT bits3_3,ixMem8 is op0_8=0xdd; op0_8=0xcb; ixMem8; op6_2=0x1 & bits3_3 & bits0_3=0x6 {
mask:1 = (1 << bits3_3);
val:1 = ixMem8;
$(Z_flag) = ((val & mask) == 0);
$(H_flag) = 1;
$(N_flag) = 0;
}
:BIT bits3_3,iyMem8 is op0_8=0xfd; op0_8=0xcb; iyMem8; op6_2=0x1 & bits3_3 & bits0_3=0x6 {
mask:1 = (1 << bits3_3);
val:1 = iyMem8;
$(Z_flag) = ((val & mask) == 0);
$(H_flag) = 1;
$(N_flag) = 0;
}
:SET bits3_3,reg0_3 is op0_8=0xcb; op6_2=0x3 & bits3_3 & reg0_3 {
mask:1 = (1 << bits3_3);
reg0_3 = reg0_3 | mask;
}
:SET bits3_3,(HL) is op0_8=0xcb & HL; op6_2=0x3 & bits3_3 & bits0_3=0x6 {
mask:1 = (1 << bits3_3);
val:1 = 0;
MemRead(val,HL);
val = val | mask;
MemStore(HL,val);
}
:SET bits3_3,ixMem8 is op0_8=0xdd; op0_8=0xcb; ixMem8; op6_2=0x3 & bits3_3 & bits0_3=0x6 {
mask:1 = (1 << bits3_3);
val:1 = ixMem8;
ixMem8 = val | mask;
}
:SET bits3_3,iyMem8 is op0_8=0xfd; op0_8=0xcb; iyMem8; op6_2=0x3 & bits3_3 & bits0_3=0x6 {
mask:1 = (1 << bits3_3);
val:1 = iyMem8;
iyMem8 = val | mask;
}
:RES bits3_3,reg0_3 is op0_8=0xcb; op6_2=0x2 & bits3_3 & reg0_3 {
mask:1 = ~(1 << bits3_3);
reg0_3 = reg0_3 & mask;
}
:RES bits3_3,(HL) is op0_8=0xcb & HL; op6_2=0x2 & bits3_3 & bits0_3=0x6 {
mask:1 = ~(1 << bits3_3);
val:1 = 0;
MemRead(val,HL);
val = val & mask;
MemStore(HL,val);
}
:RES bits3_3,ixMem8 is op0_8=0xdd; op0_8=0xcb; ixMem8; op6_2=0x2 & bits3_3 & bits0_3=0x6 {
mask:1 = ~(1 << bits3_3);
val:1 = ixMem8;
ixMem8 = val & mask;
}
:RES bits3_3,iyMem8 is op0_8=0xfd; op0_8=0xcb; iyMem8; op6_2=0x2 & bits3_3 & bits0_3=0x6 {
mask:1 = ~(1 << bits3_3);
val:1 = iyMem8;
iyMem8 = val & mask;
}
:JP Addr16 is op0_8=0xc3; Addr16 {
goto Addr16;
}
:JP cc,Addr16 is op6_2=0x3 & cc & bits0_3=0x2; Addr16 {
if (cc) goto Addr16;
}
:JR RelAddr8 is op0_8=0x18; RelAddr8 {
goto RelAddr8;
}
:JR cc2,RelAddr8 is op6_2=0x0 & cc2 & bits0_3=0x0; RelAddr8 {
if (cc2) goto RelAddr8;
}
:JP (HL) is op0_8=0xe9 & HL {
off:2 = (zext(H) << 8) | zext(L);
JumpToLoc(off);
}
:JP (IX) is op0_8=0xdd & IX; op0_8=0xe9 {
JumpToLoc(IX);
}
:JP (IY) is op0_8=0xfd & IY; op0_8=0xe9 {
JumpToLoc(IY);
}
:DJNZ RelAddr8 is op0_8=0x10; RelAddr8 {
B = B - 1;
if (B != 0) goto RelAddr8;
}
:CALL Addr16 is op0_8=0xcd; Addr16 {
push16(&:2 inst_next);
call Addr16;
}
:CALL cc,Addr16 is op6_2=0x3 & cc & bits0_3=0x4; Addr16 {
if (!cc) goto inst_next;
push16(&:2 inst_next);
call Addr16;
}
:RET is op0_8=0xc9 {
pop16(PC);
ptr:$(PTRSIZE) = PC;
return [ptr];
}
:RET cc is op6_2=0x3 & cc & bits0_3=0x0 {
if (!cc) goto inst_next;
pop16(PC);
ptr:$(PTRSIZE) = PC;
return [ptr];
}
:RETI is op0_8=0xed; op0_8=0x4d {
pop16(PC);
ptr:$(PTRSIZE) = PC;
return [ptr];
}
:RETN is op0_8=0xed; op0_8=0x45 {
# IFF1 = IFF2;
pop16(PC);
ptr:$(PTRSIZE) = PC;
return [ptr];
}
:RST RstAddr is op6_2=0x3 & RstAddr & bits0_3=0x7 {
push16(&:2 inst_next);
call RstAddr;
}
:IN A,IOAddr8a is op0_8=0xdb & A; IOAddr8a {
ioRead(IOAddr8a, A);
}
:IN reg3_3,IOAddrC is op0_8=0xed & IOAddrC; op6_2=0x1 & reg3_3 & bits0_3=0x0 {
ioRead(IOAddrC, reg3_3);
setResultFlags(reg3_3);
$(H_flag) = 0;
setParity(reg3_3);
$(N_flag) = 0;
}
:INI is op0_8=0xed & IOAddrC; op0_8=0xa2 {
val:1 = 0;
ioRead(IOAddrC, val);
MemStore(HL,val);
B = B - 1;
HL = HL + 1;
$(Z_flag) = (B == 0);
$(N_flag) = (B s< 0);
}
:INIR is op0_8=0xed & IOAddrC; op0_8=0xb2 {
val:1 = 0;
ioRead(IOAddrC, val);
MemStore(HL,val);
B = B - 1;
HL = HL + 1;
if (B != 0) goto inst_start;
$(Z_flag) = 1;
$(N_flag) = 1;
}
:IND is op0_8=0xed & IOAddrC; op0_8=0xaa {
val:1 = 0;
ioRead(IOAddrC, val);
MemStore(HL,val);
B = B - 1;
HL = HL - 1;
$(Z_flag) = (B == 0);
$(N_flag) = (B s< 0);
}
:INDR is op0_8=0xed & IOAddrC; op0_8=0xba {
val:1 = 0;
ioRead(IOAddrC, val);
MemStore(HL,val);
B = B - 1;
HL = HL - 1;
if (B != 0) goto inst_start;
$(Z_flag) = 1;
$(N_flag) = 1;
}
:OUT IOAddr8a,A is op0_8=0xd3 & A; IOAddr8a {
ioWrite(IOAddr8a, A);
}
:OUT IOAddrC,reg3_3 is op0_8=0xed & IOAddrC; op6_2=0x1 & reg3_3 & bits0_3=0x1 {
ioWrite(IOAddrC, reg3_3);
}
:OUTI is op0_8=0xed & IOAddrC; op0_8=0xa3 {
val:1 = 0;
MemRead(val,HL);
ioWrite(IOAddrC, val);
B = B - 1;
HL = HL + 1;
$(Z_flag) = (B == 0);
$(N_flag) = (B s< 0);
}
:OTIR is op0_8=0xed & IOAddrC; op0_8=0xb3 {
B = B - 1;
val:1 = 0;
MemRead(val,HL);
ioWrite(IOAddrC, val);
HL = HL + 1;
if (B != 0) goto inst_start;
$(Z_flag) = 1;
$(N_flag) = 1;
}
:OUTD is op0_8=0xed & IOAddrC; op0_8=0xab {
B = B - 1;
val:1 = 0;
MemRead(val,HL);
ioWrite(IOAddrC, val);
HL = HL - 1;
$(Z_flag) = (B == 0);
$(N_flag) = (B s< 0);
}
:OTDR is op0_8=0xed & IOAddrC; op0_8=0xbb {
B = B - 1;
val:1 = 0;
MemRead(val,HL);
ioWrite(IOAddrC, val);
HL = HL - 1;
if (B != 0) goto inst_start;
$(Z_flag) = 1;
$(N_flag) = 1;
}
@if defined(Z180)
:MLT qRegPair4_2 is op0_8=0xed; op6_2=0x1 & qRegPair4_2 & bits0_4=0xc {
hi:2 = qRegPair4_2 >> 8;
lo:2 = qRegPair4_2 & 0xff;
qRegPair4_2 = hi * lo;
}
:TST reg3_3 is op0_8=0xed; op6_2=0x0 & reg3_3 & bits0_3=0x4 {
r:1 = reg3_3 & A;
setResultFlags(r);
$(H_flag)=1;
setParity(r);
$(N_flag)=0;
$(C_flag)=0;
}
:TST hlMem8 is op0_8=0xed; op0_8=0x34 & hlMem8 {
val:1 = 0;
MemRead(val,HL);
r:1 = val & A;
setResultFlags(r);
$(H_flag)=1;
setParity(r);
$(N_flag)=0;
$(C_flag)=0;
}
:TST imm8 is op0_8=0xed; op0_8=0x64; imm8 {
r:1 = imm8 & A;
setResultFlags(r);
$(H_flag)=1;
setParity(r);
$(N_flag)=0;
$(C_flag)=0;
}
:IN0 Flag,IOAddr8 is op0_8=0xed; op6_2=0x0 & bits3_3=0x6 & Flag & bits0_3=0x0; IOAddr8 {
r:1 = 0;
ioRead(IOAddr8,r); # read input location
setResultFlags(r);
$(H_flag)=0;
setParity(r);
$(N_flag)=0;
}
:IN0 reg3_3,IOAddr8 is op0_8=0xed; op6_2=0x0 & reg3_3 & bits0_3=0x0; IOAddr8 {
ioRead(IOAddr8,reg3_3); # read input location
setResultFlags(reg3_3);
$(H_flag)=0;
setParity(reg3_3);
$(N_flag)=0;
}
:OUT0 IOAddr8,reg3_3 is op0_8=0xed; op6_2=0x0 & reg3_3 & bits0_3=0x1; IOAddr8 {
ioWrite(IOAddr8, reg3_3);
}
:OTDM is op0_8=0xed; op0_8=0x8b & hlMem8 & IOAddrC {
r:1 = hlMem8;
ioWrite(IOAddrC, r);
HL = HL - 1;
C = C - 1;
setSubtractFlags(B,1); # ?? sets $(C_flag) based upon B-1 ??
B = B - 1;
setResultFlags(B);
# P_flag = parity(r);
$(PV_flag) = (r s< 0);
}
:OTDMR is op0_8=0xed; op0_8=0x9b & hlMem8 & IOAddrC {
r:1 = hlMem8;
ioWrite(IOAddrC, r);
HL = HL - 1;
C = C - 1;
B = B - 1;
if (B != 0) goto inst_start;
$(S_flag)=0;
$(Z_flag)=1;
$(H_flag) = 0;
# $(PV_flag)=1;
$(PV_flag) = (r s< 0); # based upon last output byte
$(C_flag)=0;
}
:TSTIO IOAddr8 is op0_8=0xed; op0_8=0x74; IOAddr8 {
v:1 = 0;
ioRead(IOAddr8,v);
r:1 = A & v;
setResultFlags(r);
$(H_flag) = 1;
# P_flag = parity(v);
$(N_flag) = 0;
$(C_flag)=0;
}
:OTIM is op0_8=0xed; op0_8=0x83 & hlMem8 & IOAddrC {
r:1 = hlMem8;
ioWrite(IOAddrC, r);
HL = HL + 1;
C = C + 1;
setSubtractFlags(B,1); # ?? sets $(C_flag) based upon B-1 ??
B = B - 1;
setResultFlags(B);
$(H_flag) = 1;
# P_flag = parity(r);
$(PV_flag) = (r s< 0);
$(N_flag) = 0;
$(C_flag)=0;
}
:OTIMR is op0_8=0xed; op0_8=0x93 & hlMem8 & IOAddrC {
r:1 = hlMem8;
ioWrite(IOAddrC, r);
HL = HL - 1;
C = C + 1;
B = B - 1;
if (B != 0) goto inst_start;
$(S_flag)=0;
$(Z_flag)=1;
$(H_flag) = 0;
# $(PV_flag)=1;
$(PV_flag) = (r s< 0); # based upon last output byte
$(C_flag)=0;
}
:SLP is op0_8=0xed; op0_8=0x76 {
sleep();
}
@endif