ghidra/Ghidra/Processors/8051/data/languages/8051_main.sinc

918 lines
37 KiB
Plaintext

# sleigh specification file for Intel 8051
#@define BIT_OPS "PCODEOPS"
#@define BIT_OPS "SHIFTS"
@define BIT_OPS "BIT_ADDRS"
# It's sometimes clearer for decompilation to omit the pushing and
# restoring of the return value for function calls.
#@define OMIT_RETADDR
# TODO !!! need to fully employ resultflags macro after resolving the use of the above BIT_OPS !!!
# TODO !!! Need to reconcile use of PSW vs. PSW1 for MCS251 !!!
# TODO !!! Need to fill-out SFR bits in 80251.pspec !!!
@if defined(ENDIAN)
define endian=$(ENDIAN);
@else
define endian=big;
@endif
define alignment=1;
@if defined(MCS251)
@define PTRSIZE 3
@define SP_SIZE 3
define space RAM type=ram_space size=3 default;
define space SFR type=ram_space size=2;
define space BITS type=ram_space size=2;
# 8051 spaces map to the following regions of the 80251 RAM space:
# CODE - 0xff0000-0xffffff
# EXTERNAL - 0x010000-0x01ffff
# INTERNAL - 0x000000-0x0000ff
@elif defined(MCS51)
@if defined(PTRSIZE)
@else
@define PTRSIZE 2
@endif
# SP stack pointer should be set to the size of the space it is used in, to avoid "issues"
# This is a minor inconsistency with the model and the actual processor in some cases
# If pristine SP sizing is required for rollover and such, the model should be changed
#
@define SP_SIZE 1
define space CODE type=ram_space size=$(PTRSIZE) default;
define space INTMEM type=ram_space size=1;
define space EXTMEM type=ram_space size=2;
define space SFR type=ram_space size=1;
define space BITS type=ram_space size=1;
@elif defined(MCS80390)
@define PTRSIZE 3
@define SP_SIZE 1
define space CODE type=ram_space size=3 default;
define space INTMEM type=ram_space size=1;
define space EXTMEM type=ram_space size=3;
define space SFR type=ram_space size=1;
define space BITS type=ram_space size=1;
@elif defined(MX51)
@define PTRSIZE 3
@define SP_SIZE 3
# The right thing for decompilation is to represent these
# as part of one uniform space, similar to the 80251.
# Remember to load code at 800000
#
# xdata 0 (EXTMEM)
# data 7f0000 (INTMEM)
# code 800000
define space RAM type=ram_space size=3 default;
define space SFR type=ram_space size=1;
define space ESFR type=ram_space size=1;
define space BITS type=ram_space size=1;
define space EBITS type=ram_space size=1;
# Unsure where stack really is, but probably don't want it on normal
# registers
#@define STACKBASE 0x7f0100
@define STACKBASE 0
@else
# "error Unknown processor"
@endif
define space register type=register_space size=1;
# Register File
define register offset=0x00 size=1 [ R0 R1 R2 R3 R4 R5 R6 R7 ];
# for future jump table fixup
define register offset=0x70 size=1 [ jumpTableGuard1 jumpTableGuard2 ];
@if defined(MCS251)
define register offset=0x08 size=1 [ R8 R9 B ACC R12 R13 R14 R15
R16 R17 R18 R19 R20 R21 R22 R23
R24 R25 R26 R27 R28 R29 R30 R31
];
define register offset=0x0 size=2 [ WR0 WR2 WR4 WR6 WR8 AB WR12 WR14
WR16 WR18 WR20 WR22 WR24 WR26 WR28 WR30
];
define register offset=0x0 size=4 [ DR0 DR4 DR8 DR12 DR16 DR20 DR24 DR28 ];
define register offset=0x38 size=1 [ R56 DPXL DPH DPL R60 R61 SPH ];
define register offset=0x3A size=2 [ DPTR ];
define register offset=0x38 size=4 [ DPX SPX ];
@elif defined(MCS51) || defined(MCS80390) || defined(MX51)
define register offset=0x00 size=4 [ R0R1R2R3 ];
define register offset=0x01 size=3 [ R1R2R3 ]; # Used as R3R2R1
define register offset=0x01 size=2 [ R2R1 ];
define register offset=0x00 size=2 [ R0R1 R2R3 R4R5 R6R7 ];
define register offset=0x04 size=4 [ R4R5R6R7 ];
define register offset=0x05 size=3 [ R5R6R7 ];
define register offset=0x0A size=1 [ B ACC ]; # relocated to facilitate AB 16-bit access
define register offset=0x0A size=2 [ AB ];
@if defined(MCS51) || defined(MX51)
define register offset=0x82 size=2 [ DPTR ];
define register offset=0x82 size=1 [ DPH DPL ]; # relocated to facilitate DPTR 16-bit access
@elif defined(MCS80390)
# Following existing example, relocated DPX, DPH, and DPL for DPTR
# access. Rework some direct moves to compensate. Not clear that all
# cases are covered, thus might be problematic hack in the long term.
define register offset=0x82 size=3 [ DPTR ];
define register offset=0x82 size=1 [ DPX DPH DPL ];
@endif
@else
# "error Unknown processor"
@endif
define register offset=0x40 size=$(SP_SIZE) [ SP ];
define register offset=0x44 size=$(PTRSIZE) [ PC ];
define register offset=0x48 size=1 [ PSW ];
@if defined(DUAL_DPTR)
# Dual DPTR
# Rather than model it as context, we're just going
# to special case the INC and DEC instructions
# to swap the register values
define register offset=0x4a size=2 [ DPTR2 ];
define register offset=$(DPS_REG_NUM) size=1 [ AUXR1 ]; # Bit 0 is DPS
@endif
@define CY "PSW[7,1]"
@define AC "PSW[6,1]"
@define N "PSW[5,1]"
@define RS1 "PSW[4,1]"
@define RS0 "PSW[3,1]"
@define OV "PSW[2,1]"
@define Z "PSW[1,1]"
@if defined(MX51)
# remap these into the normal register file for decompiler use.
# Really belong on ESFR @0xfc - 0xfe with order EPL EPM EPH
define register offset=0xc0 size=1 [ EPH EPM EPL ];
define register offset=0xc0 size=3 [ EPTR ];
@endif
@if defined(MCS251)
define register offset=0x50 size=4 contextReg;
define context contextReg
phase = (0,0)
srcMode = (1,1) # (reflects UCONFIG0.0) 1: source mode, 0: binary mode
A5Prefix = (2,2) # reflects presence of A5 prefix
;
# GROUP1 - MCS51 instructions in 0x00-0x5F range
@define GROUP1 "epsilon"
# GROUP2 - MCS51 instructions in 0x60-0xff range
@define GROUP2 "((srcMode=0 & A5Prefix=0) | (srcMode=1 & A5Prefix=1))"
# GROUP3 - MCS251 instructions in 0x60-0xff range
@define GROUP3 "((srcMode=0 & A5Prefix=1) | (srcMode=1 & A5Prefix=0))"
@elif defined(MCS51) || defined(MCS80390) || defined(MX51)
@define GROUP1 "epsilon"
@define GROUP2 "epsilon"
@define GROUP3 "epsilon"
@endif
define pcodeop decimal_adjust;
define pcodeop nop;
@if BIT_OPS == "PCODEOPS"
define pcodeop get;
define pcodeop set;
define pcodeop set_bit_value;
define pcodeop clr;
@endif
#TOKENS
define token opbyte (8)
opfull = (0,7)
oplo = (0,3)
ophi = (4,7)
rn = (0,2)
rnfill = (3,3)
ri = (0,0)
rifill = (1,3)
opaddr = (5,7)
addrfill = (4,4)
b_0000 = (0,0)
b_0001 = (0,1)
b_0002 = (0,2)
b_0005 = (0,5)
b_0101 = (1,1)
b_0107 = (1,7)
b_0207 = (2,7)
b_0307 = (3,7)
b_0607 = (6,7)
@if defined(MX51)
PRi_sel = (2,2)
PRi_revend = (2,2) # reverse endian
emov_delta = (0,1)
@endif
;
define token AddrByte (8)
direct = (0,7)
bank = (7,7)
sfr = (0,6)
sfr6 = (6,6)
sfrlo = (0,3)
mainreg = (0,6)
direct17 = (1,7)
;
define token AddrByte2 (8)
direct2 = (0,7)
bank2 = (7,7)
sfr2 = (0,6)
sfr26 = (6,6)
sfr2lo = (0,3)
mainreg2 = (0,6)
;
define token BitByte (8)
bitaddr8 = (0,7)
bitaddr27 = (2,7)
bitbank = (7,7)
sfrbyte = (3,7)
bitaddr57 = (5,7)
sfrbit6 = (6,6)
sfrbit3 = (3,3)
sfrbit = (0,2) dec
lowbyte = (3,6)
bitaddr0 = (0,0)
;
define token AddrTwo (16)
addr16 = (0,15)
;
@if defined(MCS80390)
# todo: deconflict with 80251 version
define token AddrThree (24)
addr24 = (0,23)
;
@endif
define token RelByte (8) rel8=(0,7) signed;
define token ImmedByte (8) data=(0,7);
define token ImmedTwo (16)
data16 = (0,15)
rel16 = (0,15) signed
;
@if defined(MCS80390)
define token ImmedThree (24)
data24 = (0,23)
;
@endif
@if defined(MCS80390)
define token aopword (24)
aoplo = (16,19)
aopaddr = (21,23)
aaddrfill = (20,20)
adata = (0,15)
;
@else
define token aopword (16)
aoplo = (8,11)
aopaddr = (13,15)
aaddrfill = (12,12)
adata = (0,7)
;
@endif
attach variables rn [ R0 R1 R2 R3 R4 R5 R6 R7 ];
attach variables ri [ R0 R1 ];
# flags macros
#macro addflags(op1, op2) { # Flags set by add instructions
# PSW = PSW & 0x7b;
# PSW = PSW | (carry(op1,op2)<<7) # Check for carry
# | (scarry(op1,op2)<<2); # Check for signed carry
#}
#macro subflags(op1, op2) { # Flags set by sub instructions
# PSW = PSW & 0x7b;
# PSW = PSW | ((op1<op2)<<7) # Check for borrow
# | (sborrow(op1,op2)<<2); # Check for signed borrow
#}
#macro compflags(op1, op2) { # Flags set by the compare instructions
# PSW = PSW & 0x7f;
# PSW = PSW | ((op1 < op2) << 7);
#}
macro addflags(op1, op2) { # Flags set by add instructions
$(CY) = (carry(op1,op2)); # Check for carry
#OV = (scarry(op1,op2)); # Check for signed carry
}
macro subflags(op1, op2) { # Flags set by sub instructions
$(CY) = (op1 < op2); # Check for carry
#OV = sborrow(op1,op2); # Check for signed carry
}
macro compflags(op1, op2) { # Flags set by the compare instructions
$(CY) = (op1 < op2); # Check for carry
}
macro resultflags(op1) { # Set N,Z flag for results
$(N) = op1 s< 0;
$(Z) = op1 == 0;
}
macro push8(val) {
@if defined(MCS251)
SPX = SPX + 1;
ptr:3 = SPX:3;
*[RAM]:1 ptr = val;
@elif defined(MCS51) || defined(MCS80390)
SP = SP + 1;
*[INTMEM]:1 SP = val;
@elif defined(MX51)
SP = SP + 1;
#tmp:3 = zext(SP) + $(STACKBASE);
tmp:3 = SP;
*[RAM]:1 tmp = val;
@else
val = val;
@endif
}
@ifdef OMIT_RETADDR
@ifdef MCS80390
macro push24(val) { val = val; }
@else
macro push16(val) { val = val; }
@endif
@else
# Want to model pushes
@ifndef MCS80390
macro push16(val) {
@if defined(MCS251)
al:1 = val:1;
ah:1 = val(1);
SPX = SPX + 1;
*[RAM]:1 SPX:3 = al;
SPX = SPX + 1;
*[RAM]:1 SPX:3 = ah;
@elif defined(MCS51)
al:1 = val:1;
ah:1 = val(1);
SP = SP + 1;
*[INTMEM]:1 SP = al;
SP = SP + 1;
*[INTMEM]:1 SP = ah;
@elif defined(MX51)
# dptr push
#ptr:1 = SP + 1;
#tmp:3 = zext(ptr) + $(STACKBASE);
al:1 = val:1;
ah:1 = val(1);
SP = SP + 1;
*[RAM]:1 SP = al;
SP = SP + 1;
*[RAM]:1 SP = ah;
@else
val = val;
@endif
}
@else
#@if defined(MCS80390)
macro push24(val) {
al:1 = val:1;
ah:1 = val(1);
ax:1 = val(2);
SP = SP + 1;
*[INTMEM]:1 SP = al;
SP = SP + 1;
*[INTMEM]:1 SP = ah;
SP = SP + 1;
*[INTMEM]:1 SP = ax;
}
@endif
@endif
macro pop8(val) {
@if defined(MCS251)
ptr:3 = SPX:3;
val = *[RAM]:1 ptr;
SPX = SPX - 1;
@elif defined(MCS51) || defined(MCS80390)
val = *[INTMEM]:1 SP;
SP = SP - 1;
@elif defined(MX51)
#ptr:3 = zext(SP) + $(STACKBASE);
ptr:3 = SP;
val = *[RAM]:1 ptr;
SP = SP - 1;
@else
val = val;
@endif
}
@if defined(MCS80390)
@ifdef OMIT_RETADDR
macro pop24(val) { val = val; }
@else
macro pop24(val) {
ptr:1 = SP - 2;
al : 1 = *[INTMEM]:1 ptr;
ah : 1 = *[INTMEM]:1 (ptr+1);
ax : 1 = *[INTMEM]:1 (ptr+2);
bl:3 = zext(al);
bh:3 = zext(ah) << 8;
bx:3 = zext(ax) << 16;
z : 3 = bl;
z = (z | bh);
z = (z | bx);
val = z;
SP = ptr - 1;
}
@endif
@else
@ifdef OMIT_RETADDR
macro pop16(val) { val = val; }
@else
macro pop16(val) {
@if defined(MCS251)
ah:1 = *:1 SPX:$(SP_SIZE);
SPX = SPX - 1;
al:1 = *:1 SPX:$(SP_SIZE);
SPX = SPX - 1;
val = (zext(ah) << 8) | zext(al);
@elif defined(MCS51)
ah:1 = *[INTMEM]:1 SP;
SP = SP - 1;
al:1 = *[INTMEM]:1 SP;
SP = SP - 1;
val = (zext(ah) << 8) | zext(al);
@elif defined(MX51)
ah:1 = *[RAM]:1 SP;
SP = SP - 1;
al:1 = *[RAM]:1 SP;
SP = SP - 1;
val = (zext(ah) << 8) | zext(al);
@else
val = val;
@endif
}
@endif
@endif
# Operand display only
CY: "CY" is epsilon { }
Areg: "A" is ophi { export ACC; }
ABreg: AB is ophi & AB { export AB; }
DPTRreg: DPTR is ophi & DPTR { export DPTR; }
@if defined(MCS251)
ADPTR: "@A+"^DPTR is ophi & DPTR { ptr:3 = 0xff0000 + zext(DPTR) + zext(ACC); export ptr; }
@elif defined(MCS51)
ADPTR: "@A+"^DPTR is ophi & DPTR { ptr:$(PTRSIZE) = zext(DPTR) + zext(ACC); export ptr; }
@elif defined(MCS80390)
ADPTR: "@A+"^DPTR is ophi & DPTR { ptr:3 = zext(DPTR) + zext(ACC); export ptr; }
@elif defined(MX51)
ADPTR: "@A+"^DPTR is ophi & DPTR { ptr:3 = 0x800000 + zext(DPTR) + zext(ACC); export ptr; }
@endif
APC: "@A+PC" is epsilon { tmp:$(PTRSIZE) = inst_next + zext(ACC); export tmp; }
@if defined(MCS251)
ATDPTR: "@"^DPTR is ophi & DPTR { ptr:3 = 0x010000 + zext(DPTR); export *:1 ptr; } # 8051 External data address mapped into RAM space
@elif defined(MCS51)
ATDPTR: "@"^DPTR is ophi & DPTR { ptr:2 = DPTR; export *[EXTMEM]:1 ptr; }
@elif defined(MCS80390)
ATDPTR: "@"^DPTR is ophi & DPTR { ptr:3 = zext(DPTR); export *[EXTMEM]:1 ptr; }
@elif defined(MX51)
ATDPTR: "@"^DPTR is ophi & DPTR { ptr:3 = zext(DPTR); export *[RAM]:1 ptr; }
@endif
@if defined(MCS251)
Ri: @ri is ri { ptr:3 = zext(ri); export *[RAM]:1 ptr; }
@elif defined(MX51)
Ri: @ri is ri { ptr:3 = zext(ri) + 0x7f0000; export *[RAM]:1 ptr; }
@elif defined(MCS51) || defined(MCS80390)
Ri: @ri is ri { export *[INTMEM]:1 ri; }
@endif
@if defined(MCS251)
RiX: @ri is ri { ptr:3 = 0x010000 + zext(ri); export *:1 ptr; } # 8051 8-bit External data address mapped into RAM space
@elif defined(MCS51)
RiX: @ri is ri { ptr:2 = zext(ri); export *[EXTMEM]:1 ptr; } # limited to 8-bit external data address (I/O state can be used to produce 16-bit addr)
@elif defined(MCS80390)
RiX: @ri is ri { ptr:3 = zext(ri); export *[EXTMEM]:1 ptr; } # tocheck
@elif defined(MX51)
RiX: @ri is ri { ptr:3 = zext(ri); export *[RAM]:1 ptr; }
@endif
Data: "#"data is data { export *[const]:1 data; }
Data16: "#"data16 is data16 { export *[const]:2 data16; }
@if defined(MCS80390)
Data24: "#"data24 is data24 { export *[const]:3 data24; }
@endif
@if defined(MCS251)
Direct: mainreg is bank=0 & mainreg { export *[RAM]:1 mainreg; }
@elif defined(MX51)
Direct: mainreg is bank=0 & mainreg { tmp:3 = mainreg + 0x7f0000; export *[RAM]:1 tmp; }
@elif defined(MCS51) || defined(MCS80390)
Direct: mainreg is bank=0 & mainreg { export *[INTMEM]:1 mainreg; }
@endif
Direct: direct is bank=1 & direct { export *[SFR]:1 direct; }
Direct: PSW is bank=1 & direct=0xD0 & PSW { export PSW; }
Direct: "A" is bank=1 & direct=0xE0 { export ACC; }
Direct: B is bank=1 & direct=0xF0 & B { export B; }
Direct: DPL is bank=1 & direct=0x82 & DPL { export DPL; }
Direct: DPH is bank=1 & direct=0x83 & DPH { export DPH; }
@if defined(MCS80390)
Direct: DPX is bank=1 & direct=0x93 & DPX { export DPX; }
@endif
@if defined(MCS251)
Direct: DPXL is bank=1 & direct=0x84 & DPXL { export DPXL; }
@endif
@if defined(MCS251)
Direct2: mainreg2 is bank2=0 & mainreg2 { export *[RAM]:1 mainreg2; }
@elif defined(MX51)
Direct2: mainreg2 is bank2=0 & mainreg2 { tmp:3 = mainreg2 + 0x7f0000; export *[RAM]:1 tmp; }
@elif defined(MCS51) || defined(MCS80390)
Direct2: mainreg2 is bank2=0 & mainreg2 { export *[INTMEM]:1 mainreg2; }
@endif
Direct2: direct2 is bank2=1 & direct2 { export *[SFR]:1 direct2; }
Direct2: PSW is bank2=1 & direct2=0xD0 & PSW { export PSW; }
Direct2: "A" is bank2=1 & direct2=0xE0 { export ACC; }
Direct2: B is bank2=1 & direct2=0xF0 & B { export B; }
Direct2: DPL is bank2=1 & direct2=0x82 & DPL { export DPL; }
Direct2: DPH is bank2=1 & direct2=0x83 & DPH { export DPH; }
@if defined(MCS80390)
Direct2: DPX is bank2=1 & direct2=0x93 & DPX { export DPX; }
@endif
@if defined(MCS251)
Direct2: DPXL is bank2=1 & direct2=0x84 & DPXL { export DPXL; }
@endif
@if defined(MCS251)
BitAddr: bitaddr is bitbank=1 & sfrbyte & sfrbit [ bitaddr =(sfrbyte << 6)+sfrbit; ] { export *[BITS]:1 bitaddr; }
BitAddr: bitaddr is bitbank=0 & lowbyte & sfrbit [ bitaddr =(lowbyte << 3)+sfrbit; ] { export *[BITS]:1 bitaddr; }
BitAddr2: "/"bitaddr is bitbank=1 & sfrbyte & sfrbit [ bitaddr =(sfrbyte << 6)+sfrbit; ] { export *[BITS]:1 bitaddr; }
BitAddr2: "/"bitaddr is bitbank=0 & lowbyte & sfrbit [ bitaddr =(lowbyte << 3)+sfrbit; ] { export *[BITS]:1 bitaddr; }
@elif defined(MCS51) || defined(MCS80390) || defined(MX51)
##
##TODO !!! 8051 SFRBITS bit overlay block is probably incorrect since there is not a 1:1 mapping to the SFR space
## While the BitAddr is only used for disassembly markup, and labels come from pspec, the underlying data will
## not map correctly. We could switch completely to the full SFR bit mapping as done above for the 80251.
## This would require a change in the BITS space size.
##
BitAddr: bitaddr is bitbank=1 & sfrbyte & sfrbit [ bitaddr =(sfrbyte << 3)+sfrbit; ] { export *[BITS]:1 bitaddr; }
BitAddr: bitaddr is bitbank=0 & lowbyte & sfrbit [ bitaddr =(lowbyte << 3)+sfrbit; ] { export *[BITS]:1 bitaddr; }
BitAddr2: "/"bitaddr is bitbank=1 & sfrbyte & sfrbit [ bitaddr =(sfrbyte << 3)+sfrbit; ] { export *[BITS]:1 bitaddr; }
BitAddr2: "/"bitaddr is bitbank=0 & lowbyte & sfrbit [ bitaddr =(lowbyte << 3)+sfrbit; ] { export *[BITS]:1 bitaddr; }
@endif
BitByteAddr: byteaddr is bitbank=1 & sfrbyte & sfrbit [ byteaddr =(sfrbyte << 3); ] { export *[SFR]:1 byteaddr; }
BitByteAddr: "A" is bitbank=1 & sfrbyte=0x1C & sfrbit { export ACC; }
BitByteAddr: B is bitbank=1 & sfrbyte=0x1E & sfrbit & B { export B; }
BitByteAddr: PSW is bitbank=1 & sfrbyte=0x1A & sfrbit & PSW { export PSW; }
@if defined(MCS251)
BitByteAddr: byteaddr is bitbank=0 & lowbyte & sfrbit [ byteaddr = lowbyte + 0x20; ] { export *[RAM]:1 byteaddr; }
@elif defined(MX51)
BitByteAddr: byteaddr is bitbank=0 & lowbyte & sfrbit [ byteaddr = lowbyte + 0x20; ] { tmp:3 = byteaddr + 0x7f0000; export *[RAM]:1 tmp; }
@elif defined(MCS51) || defined(MCS80390)
BitByteAddr: byteaddr is bitbank=0 & lowbyte & sfrbit [ byteaddr = lowbyte + 0x20; ] { export *[INTMEM]:1 byteaddr; }
@endif
@if defined(MCS251) || defined(MX51)
Addr11: relAddr is aopaddr & adata [ relAddr = (inst_next $and 0xfff800)+(aopaddr*256)+adata; ] { export *:1 relAddr; }
Addr16: addr is addr16 [ addr = (inst_next $and 0xff0000) + addr16; ] { export *:1 addr; }
@elif defined(MCS51)
Addr11: relAddr is aopaddr & adata [ relAddr =(inst_next $and 0xf800)+(aopaddr*256)+adata; ] { export *:1 relAddr; }
Addr16: addr16 is addr16 { export *:1 addr16; }
@elif defined(MCS80390)
Addr19: relAddr is aopaddr & adata [ relAddr =(inst_next $and 0xf80000)+(aopaddr*256*256)+adata; ] { export *:1 relAddr; }
Addr24: addr24 is addr24 { export *:1 addr24; }
@endif
Rel8: relAddr is rel8 [ relAddr=inst_next+rel8; ] { export *:1 relAddr; }
Rel16: relAddr is rel16 [ relAddr=inst_next+rel16; ] { export *:1 relAddr; }
@if defined(MCS251)
# detect A5 prefix
:^instruction is phase=0 & ophi=0xa & oplo=0x5; instruction [ phase=1; A5Prefix=1; ] { }
:^instruction is phase=0 & instruction [ phase=1; A5Prefix=0; ] { }
@endif
@if defined(MCS80390)
:ACALL Addr19 is $(GROUP1) & aaddrfill=1 & aoplo=1 & Addr19 { ret:3 = inst_next; push24(ret); call Addr19; }
@else
:ACALL Addr11 is $(GROUP1) & aaddrfill=1 & aoplo=1 & Addr11 { ret:2 = inst_next; push16(ret); call Addr11; }
@endif
:ADD Areg,rn is $(GROUP2) & ophi=2 & Areg & rnfill=1 & rn { addflags(ACC,rn); ACC = ACC + rn; resultflags(ACC); }
:ADD Areg,Direct is $(GROUP1) & ophi=2 & oplo=5 & Areg; Direct { addflags(ACC,Direct); ACC = ACC + Direct; resultflags(ACC); }
:ADD Areg,Ri is $(GROUP2) & ophi=2 & Areg & rifill=3 & Ri { addflags(ACC,Ri); ACC = ACC + Ri; resultflags(ACC); }
:ADD Areg,Data is $(GROUP1) & ophi=2 & oplo=4 & Areg; Data { addflags(ACC,Data); ACC = ACC + Data; resultflags(ACC); }
:ADDC Areg,rn is $(GROUP2) & ophi=3 & Areg & rnfill=1 & rn { tmp:1 =$(CY)+ rn; addflags(ACC,tmp); ACC = ACC + tmp; resultflags(ACC); }
:ADDC Areg,Direct is $(GROUP1) & ophi=3 & oplo=5 & Areg; Direct { tmp:1 =$(CY)+ Direct; addflags(ACC,tmp); ACC = ACC + tmp; resultflags(ACC); }
:ADDC Areg,Ri is $(GROUP2) & ophi=3 & Areg & rifill=3 & Ri { tmp:1 =$(CY)+ Ri; addflags(ACC,tmp); ACC = ACC + tmp; resultflags(ACC); }
:ADDC Areg,Data is $(GROUP1) & ophi=3 & oplo=4 & Areg; Data { tmp:1 =$(CY)+ Data; addflags(ACC,tmp); ACC = ACC + tmp; resultflags(ACC); }
#TODO: which GROUP does AJMP belong to ??
@if defined(MCS80390)
:AJMP Addr19 is $(GROUP1) & aaddrfill=0 & aoplo=1 & Addr19 { goto Addr19; }
@else
:AJMP Addr11 is $(GROUP1) & aaddrfill=0 & aoplo=1 & Addr11 { goto Addr11; }
@endif
:ANL Areg,rn is $(GROUP2) & ophi=5 & Areg & rnfill=1 & rn { ACC = ACC & rn; resultflags(ACC); }
:ANL Areg,Direct is $(GROUP1) & ophi=5 & oplo=5 & Areg; Direct { ACC = ACC & Direct; resultflags(ACC); }
:ANL Areg,Ri is $(GROUP2) & ophi=5 & Areg & rifill=3 & Ri { ACC = ACC & Ri; resultflags(ACC); }
:ANL Areg,Data is $(GROUP2) & ophi=5 & oplo=4 & Areg; Data { ACC = ACC & Data; resultflags(ACC); }
:ANL Direct,Areg is $(GROUP1) & ophi=5 & oplo=2 & Areg; Direct { tmp:1 = Direct & ACC; Direct = tmp; resultflags(tmp); }
:ANL Direct,Data is $(GROUP1) & ophi=5 & oplo=3; Direct; Data { tmp:1 = Direct & Data; Direct = tmp; resultflags(tmp); }
:ANL CY,BitAddr is $(GROUP1) & CY & ophi=8 & oplo=2; BitAddr & bitaddr57=7 & sfrbit3=0 & sfrbit & BitByteAddr {tmp:1 = BitByteAddr; $(CY)=$(CY)& ((tmp>>sfrbit)&1); resultflags(tmp); }
:ANL CY,BitAddr2 is $(GROUP1) & CY & ophi=11 & oplo=0; BitAddr2 & bitaddr57=7 & sfrbit3=0 & sfrbit & BitByteAddr {tmp:1 = BitByteAddr; $(CY)=$(CY)& (~((tmp>>sfrbit)&1)); }
@if BIT_OPS == "BIT_ADDRS"
:ANL CY,BitAddr is $(GROUP1) & CY & ophi=8 & oplo=2; BitAddr & sfrbit & BitByteAddr {$(CY)=$(CY)& BitAddr; }
:ANL CY,BitAddr2 is $(GROUP1) & CY & ophi=11 & oplo=0; BitAddr2 & sfrbit & BitByteAddr {$(CY)=$(CY)& ~BitAddr2; }
@elif BIT_OPS == "PCODEOPS"
:ANL CY,BitAddr is $(GROUP1) & CY & ophi=8 & oplo=2; BitAddr & sfrbit & BitByteAddr {$(CY)=$(CY)& get(BitAddr, BitByteAddr); }
:ANL CY,BitAddr2 is $(GROUP1) & CY & ophi=11 & oplo=0; BitAddr2 & sfrbit & BitByteAddr {$(CY)=$(CY)& (get(BitAddr2, BitByteAddr)^1); }
@elif BIT_OPS == "SHIFTS"
:ANL CY,BitAddr is $(GROUP1) & CY & ophi=8 & oplo=2; BitAddr & sfrbit & BitByteAddr {$(CY)=$(CY)& ((BitByteAddr>>sfrbit)&1); }
:ANL CY,BitAddr2 is $(GROUP1) & CY & ophi=11 & oplo=0; BitAddr2 & sfrbit & BitByteAddr {$(CY)=$(CY)& (~((BitByteAddr>>sfrbit)&1)); }
@endif
:CJNE Areg,Direct,Rel8 is $(GROUP1) & ophi=11 & oplo=5 & Areg; Direct; Rel8 { compflags(ACC,Direct); if (ACC!=Direct) goto Rel8; }
:CJNE Areg,Data,Rel8 is $(GROUP1) & ophi=11 & oplo=4 & Areg; Data; Rel8 { compflags(ACC,Data); if (ACC!=Data) goto Rel8; }
:CJNE rn,Data,Rel8 is $(GROUP2) & ophi=11 & rnfill=1 & rn; Data; Rel8 { compflags(rn,Data); if (rn!=Data) goto Rel8; }
:CJNE Ri,Data,Rel8 is $(GROUP2) & ophi=11 & rifill=3 & Ri; Data; Rel8 { compflags(Ri,Data); if (Ri!=Data) goto Rel8; }
:CLR Areg is $(GROUP1) & ophi=14 & oplo=4 & Areg { ACC = 0; }
:CLR CY is $(GROUP1) & CY & ophi=12 & oplo=3 {$(CY)= 0; }
:CLR BitAddr is $(GROUP1) & ophi=12 & oplo=2; BitAddr & bitaddr57=7 & sfrbit3=0 & sfrbit & BitByteAddr { local tmp = ~(1<<sfrbit); BitByteAddr = BitByteAddr & tmp; }
@if BIT_OPS == "BIT_ADDRS"
:CLR BitAddr is $(GROUP1) & ophi=12 & oplo=2; BitAddr & sfrbit & BitByteAddr { BitAddr = 0; }
@elif BIT_OPS == "PCODEOPS"
:CLR BitAddr is $(GROUP1) & ophi=12 & oplo=2; BitAddr & sfrbit & BitByteAddr { BitByteAddr = clr(BitAddr, BitByteAddr); }
#:CLR PortBit is $(GROUP1) & ophi=12 & oplo=2; PortBit & sfrbit & BitByteAddr { outp(PortBit, 0:1, BitByteAddr); }
@elif BIT_OPS == "SHIFTS"
:CLR BitAddr is $(GROUP1) & ophi=12 & oplo=2; BitAddr & sfrbit & BitByteAddr { local tmp = ~(1<<sfrbit); BitByteAddr = BitByteAddr & tmp; }
@endif
:CPL Areg is $(GROUP2) & ophi=15 & oplo=4 & Areg { ACC = ~ACC; }
:CPL CY is $(GROUP2) & CY & ophi=11 & oplo=3 {$(CY)=$(CY)^ 1; }
:CPL BitAddr is $(GROUP1) & ophi=11 & oplo=2; BitAddr & bitaddr57=7 & sfrbit3=0 & sfrbit & BitByteAddr { tmp:1 = (1<<sfrbit); BitByteAddr = BitByteAddr ^ tmp; }
@if BIT_OPS == "BIT_ADDRS"
:CPL BitAddr is $(GROUP1) & ophi=11 & oplo=2; BitAddr & sfrbit & BitByteAddr { BitAddr = BitAddr ^ 1; }
@elif BIT_OPS == "PCODEOPS"
:CPL BitAddr is $(GROUP1) & ophi=11 & oplo=2; BitAddr & sfrbit & BitByteAddr { tmp:1 = get(BitAddr, BitByteAddr) ^ 1; BitByteAddr = set_bit_value(BitAddr, tmp, BitByteAddr); }
@elif BIT_OPS == "SHIFTS"
:CPL BitAddr is $(GROUP1) & ophi=11 & oplo=2; BitAddr & sfrbit & BitByteAddr { tmp:1 = (1<<sfrbit); BitByteAddr = BitByteAddr ^ tmp; }
@endif
:DA Areg is $(GROUP1) & ophi=13 & oplo=4 & Areg { ACC = decimal_adjust(ACC); }
:DEC Areg is $(GROUP1) & ophi=1 & oplo=4 & Areg { ACC = ACC - 1; }
:DEC rn is $(GROUP2) & ophi=1 & rnfill=1 & rn { rn = rn - 1; }
:DEC Direct is $(GROUP1) & ophi=1 & oplo=5; Direct { Direct = Direct - 1; }
:DEC Ri is $(GROUP2) & ophi=1 & rifill=3 & Ri { Ri = Ri - 1; }
:DIV ABreg is $(GROUP1) & ophi=8 & oplo=4 & ABreg { PSW = PSW & 0x7b; tmp : 1 = (B == 0)<<2; PSW = PSW | tmp; if (B==0) goto inst_next; tmp2 : 1 = ACC; ACC = tmp2 / B; B = tmp2 % B; }
# Specifying rnfill here is a temporary to allow distinguishing DJNZ1 and XCHD
:DJNZ rn,Rel8 is $(GROUP2) & ophi=13 & rnfill=1 & rnfill=1 & rn; Rel8 { rn = rn - 1; if (rn!=0) goto Rel8; }
:DJNZ Direct,Rel8 is $(GROUP1) & ophi=13 & oplo=5; Direct; Rel8 { Direct = Direct - 1; if (Direct!=0) goto Rel8; }
:INC Areg is $(GROUP1) & ophi=0 & oplo=4 & Areg { ACC = ACC + 1; }
:INC rn is $(GROUP2) & ophi=0 & rnfill=1 & rn { rn = rn + 1; }
:INC Direct is $(GROUP1) & ophi=0 & oplo=5; Direct { Direct = Direct + 1; }
@if defined(DUAL_DPTR) && defined(DPS_REG_NUM)
:INC Direct is $(GROUP1) & ophi=0 & oplo=5; Direct & direct=$(DPS_REG_NUM) {
AUXR1 = AUXR1 ^ 0x01;
tmp:2 = DPTR;
DPTR = DPTR2;
DPTR2 = tmp;
}
@endif
:INC Ri is $(GROUP2) & ophi=0 & rifill=3 & Ri { Ri = Ri + 1; }
:INC DPTRreg is $(GROUP1) & ophi=10 & oplo=3 & DPTRreg { DPTR = DPTR + 1; }
:JB BitAddr,Rel8 is $(GROUP1) & ophi=2 & oplo=0; BitAddr & bitaddr57=7 & sfrbit3=0 & sfrbit & BitByteAddr; Rel8 { if (((BitByteAddr>>sfrbit)&1) == 1:1) goto Rel8; }
:JBC BitAddr,Rel8 is $(GROUP1) & ophi=1 & oplo=0; BitAddr & bitaddr57=7 & sfrbit3=0 & sfrbit & BitByteAddr; Rel8 { tmp:1 = 1<<sfrbit; if ((BitByteAddr & tmp)==0) goto inst_next; BitByteAddr = BitByteAddr & ~tmp; goto Rel8; }
@if BIT_OPS == "BIT_ADDRS"
:JB BitAddr,Rel8 is $(GROUP1) & ophi=2 & oplo=0; BitAddr & sfrbit & BitByteAddr; Rel8 { if (BitAddr == 1:1) goto Rel8; }
:JBC BitAddr,Rel8 is $(GROUP1) & ophi=1 & oplo=0; BitAddr & sfrbit & BitByteAddr; Rel8 { if (BitAddr == 0:1) goto inst_next; BitAddr = 0; goto Rel8; }
@elif BIT_OPS == "PCODEOPS"
:JB BitAddr,Rel8 is $(GROUP1) & ophi=2 & oplo=0; BitAddr & sfrbit & BitByteAddr; Rel8 { if (get(BitAddr, BitByteAddr)==1:1) goto Rel8; }
:JBC BitAddr,Rel8 is $(GROUP1) & ophi=1 & oplo=0; BitAddr & sfrbit & BitByteAddr; Rel8 { tmp:1 = get(BitAddr, BitByteAddr); if (tmp==0) goto inst_next; BitByteAddr = clr(BitAddr, BitByteAddr); goto Rel8; }
@elif BIT_OPS == "SHIFTS"
:JB BitAddr,Rel8 is $(GROUP1) & ophi=2 & oplo=0; BitAddr & sfrbit & BitByteAddr; Rel8 { if (((BitByteAddr>>sfrbit)&1) == 1:1) goto Rel8; }
:JBC BitAddr,Rel8 is $(GROUP1) & ophi=1 & oplo=0; BitAddr & sfrbit & BitByteAddr; Rel8 { tmp:1 = 1<<sfrbit; if ((BitByteAddr & tmp)==0) goto inst_next; BitByteAddr = BitByteAddr & ~tmp; goto Rel8; }
@endif
:JC Rel8 is $(GROUP1) & ophi=4 & oplo=0; Rel8 { if ($(CY) != 0) goto Rel8; }
:JMP ADPTR is $(GROUP1) & ophi=7 & oplo=3 & ADPTR { goto [ADPTR]; }
:JNB BitAddr,Rel8 is $(GROUP1) & ophi=3 & oplo=0; BitAddr & bitaddr57=7 & sfrbit3=0 & sfrbit & BitByteAddr; Rel8 { if (((BitByteAddr>>sfrbit)&1)==0:1) goto Rel8; }
@if BIT_OPS == "BIT_ADDRS"
:JNB BitAddr,Rel8 is $(GROUP1) & ophi=3 & oplo=0; BitAddr & sfrbit & BitByteAddr; Rel8 { if (BitAddr == 0:1) goto Rel8; }
@elif BIT_OPS == "PCODEOPS"
:JNB BitAddr,Rel8 is $(GROUP1) & ophi=3 & oplo=0; BitAddr & sfrbit & BitByteAddr; Rel8 { if (get(BitAddr, BitByteAddr)==0:1) goto Rel8; }
@elif BIT_OPS == "SHIFTS"
:JNB BitAddr,Rel8 is $(GROUP1) & ophi=3 & oplo=0; BitAddr & sfrbit & BitByteAddr; Rel8 { if (((BitByteAddr>>sfrbit)&1)==0:1) goto Rel8; }
@endif
:JNC Rel8 is $(GROUP1) & ophi=5 & oplo=0; Rel8 { if ($(CY) == 0) goto Rel8; }
:JNZ Rel8 is $(GROUP1) & ophi=7 & oplo=0; Rel8 { if (ACC != 0) goto Rel8; }
:JZ Rel8 is $(GROUP1) & ophi=6 & oplo=0; Rel8 { if (ACC == 0) goto Rel8; }
@if defined(MCS80390)
:LCALL Addr24 is $(GROUP1) & ophi=1 & oplo=2; Addr24 { ret:$(PTRSIZE) = inst_next; push24(ret); call Addr24; }
:LJMP Addr24 is $(GROUP1) & ophi=0 & oplo=2; Addr24 { goto Addr24; }
@elif defined(MX51)
:LCALL Addr16 is $(GROUP1) & ophi=1 & oplo=2; Addr16 { ret:2 = inst_next; push16(ret); call Addr16; }
:LJMP Addr16 is $(GROUP1) & ophi=0 & oplo=2; Addr16 { goto Addr16; }
@else
:LCALL Addr16 is $(GROUP1) & ophi=1 & oplo=2; Addr16 { ret:$(PTRSIZE) = inst_next; push16(ret); call Addr16; }
:LJMP Addr16 is $(GROUP1) & ophi=0 & oplo=2; Addr16 { goto Addr16; }
@endif
:MOV Areg,rn is $(GROUP2) & ophi=14 & rnfill=1 & rn & Areg { ACC = rn; }
:MOV Areg,Direct is $(GROUP1) & ophi=14 & oplo=5 & Areg; Direct { ACC = Direct; }
:MOV Areg,Ri is $(GROUP2) & ophi=14 & Areg & rifill=3 & Ri { ACC = Ri; }
:MOV Areg,Data is $(GROUP1) & ophi=7 & oplo=4 & Areg; Data { ACC = Data; }
:MOV rn,Areg is $(GROUP2) & ophi=15 & rnfill=1 & rn & Areg { rn = ACC; }
:MOV rn,Direct is $(GROUP2) & ophi=10 & rnfill=1 & rn; Direct { rn = Direct; }
:MOV rn,Data is $(GROUP2) & ophi=7 & rnfill=1 & rn; Data { rn = Data; }
:MOV Direct,Areg is $(GROUP1) & ophi=15 & oplo=5 & Areg; Direct { Direct = ACC; }
:MOV Direct,rn is $(GROUP2) & ophi=8 & rnfill=1 & rn; Direct { Direct = rn; }
:MOV Direct2,Direct is $(GROUP1) & ophi=8 & oplo=5; Direct; Direct2 { Direct2 = Direct; }
:MOV Direct,Ri is $(GROUP2) & ophi=8 & rifill=3 & Ri; Direct { Direct = Ri; }
:MOV Direct,Data is $(GROUP1) & ophi=7 & oplo=5; Direct; Data { Direct = Data; }
:MOV Ri,Areg is $(GROUP2) & ophi=15 & rifill=3 & Ri & Areg { Ri = ACC; }
:MOV Ri,Direct is $(GROUP2) & ophi=10 & rifill=3 & Ri; Direct { Ri = Direct; }
:MOV Ri,Data is $(GROUP2) & ophi=7 & rifill=3 & Ri; Data { Ri = Data; }
@if defined(MCS80390)
:MOV DPTRreg,Data24 is $(GROUP1) & ophi=9 & oplo=0 & DPTRreg; Data24 { DPTR = Data24; }
@else
:MOV DPTRreg,Data16 is $(GROUP1) & ophi=9 & oplo=0 & DPTRreg; Data16 { DPTR = Data16; }
@endif
:MOV CY,BitAddr is $(GROUP1) & CY & ophi=10 & oplo=2; BitAddr & bitaddr57=7 & sfrbit3=0 & sfrbit & BitByteAddr {$(CY)= (BitByteAddr>>sfrbit)&1; }
:MOV BitAddr,CY is $(GROUP1) & CY & ophi=9 & oplo=2; BitAddr & bitaddr57=7 & sfrbit3=0 & sfrbit & BitByteAddr { BitByteAddr = BitByteAddr & (~(1<<sfrbit)); BitByteAddr = BitByteAddr | ($(CY)<<sfrbit); }
@if BIT_OPS == "BIT_ADDRS"
:MOV CY,BitAddr is $(GROUP1) & CY & ophi=10 & oplo=2; BitAddr & sfrbit & BitByteAddr {$(CY)= BitAddr; }
:MOV BitAddr,CY is $(GROUP1) & CY & ophi=9 & oplo=2; BitAddr & sfrbit & BitByteAddr { BitAddr = $(CY); }
@elif BIT_OPS == "PCODEOPS"
:MOV CY,BitAddr is $(GROUP1) & CY & ophi=10 & oplo=2; BitAddr & sfrbit & BitByteAddr {$(CY) = get(BitAddr, BitByteAddr); }
:MOV BitAddr,CY is $(GROUP1) & CY & ophi=9 & oplo=2; BitAddr & sfrbit & BitByteAddr { BitByteAddr = set_bit_value(BitAddr, $(CY), BitByteAddr); }
@elif BIT_OPS == "SHIFTS"
:MOV CY,BitAddr is $(GROUP1) & CY & ophi=10 & oplo=2; BitAddr & sfrbit & BitByteAddr{$(CY)= (BitByteAddr>>sfrbit)&1; }
:MOV BitAddr,CY is $(GROUP1) & CY & ophi=9 & oplo=2; BitAddr & sfrbit & BitByteAddr { BitByteAddr = BitByteAddr & (~(1<<sfrbit)); BitByteAddr = BitByteAddr | ($(CY)<<sfrbit); }
@endif
:MOVC Areg,ADPTR is $(GROUP1) & ophi=9 & oplo=3 & ADPTR & Areg { ACC = *:1 ADPTR; }
:MOVC Areg,APC is $(GROUP1) & ophi=8 & oplo=3 & APC & Areg { ACC = *:1 APC; }
:MOVX Areg,RiX is $(GROUP2) & ophi=14 & rifill=1 & RiX & Areg { ACC = RiX; }
:MOVX Areg,ATDPTR is $(GROUP1) & ophi=14 & oplo=0 & Areg & ATDPTR { ACC = ATDPTR; }
:MOVX RiX,Areg is $(GROUP2) & ophi=15 & rifill=1 & RiX & Areg { RiX = ACC; }
:MOVX ATDPTR,Areg is $(GROUP1) & ophi=15 & oplo=0 & Areg & ATDPTR { ATDPTR = ACC; }
:MUL ABreg is $(GROUP1) & ophi=10 & oplo=4 & ABreg { PSW = PSW & 0x7b; tmp:2 = zext(ACC) * zext(B); ACC = tmp(0); B = tmp(1); PSW = PSW | ((B!=0)<<2); }
#:MUL Areg,Breg is $(GROUP1) & ophi=10 & oplo=4 & Areg & Breg { PSW = PSW & 0x7b; tmp:2 = zext(ACC) * zext(B); ACC = tmp(0); B = tmp(1); PSW = PSW | ((B!=0)<<2); }
:NOP is $(GROUP1) & ophi=0 & oplo=0 { nop(); }
:ORL Areg,rn is $(GROUP2) & ophi=4 & rnfill=1 & rn & Areg { ACC = ACC | rn; }
:ORL Areg,Direct is $(GROUP1) & ophi=4 & oplo=5 & Areg; Direct { ACC = ACC | Direct; }
:ORL Areg,Ri is $(GROUP2) & ophi=4 & Areg & rifill=3 & Ri { ACC = ACC | Ri; }
:ORL Areg,Data is $(GROUP1) & ophi=4 & oplo=4 & Areg; Data { ACC = ACC | Data; }
:ORL Direct,Areg is $(GROUP1) & ophi=4 & oplo=2 & Areg; Direct { Direct = Direct | ACC; }
:ORL Direct,Data is $(GROUP1) & ophi=4 & oplo=3 & Areg; Direct; Data { Direct = Direct | Data; }
:ORL CY,BitAddr is $(GROUP1) & CY & ophi=7 & oplo=2; BitAddr & bitaddr57=7 & sfrbit3=0 & sfrbit & BitByteAddr {$(CY)=$(CY)| ((BitByteAddr>>sfrbit)&1); }
:ORL CY,BitAddr2 is $(GROUP1) & CY & ophi=10 & oplo=0; BitAddr2 & bitaddr57=7 & sfrbit3=0 & sfrbit & BitByteAddr {$(CY)=$(CY)| (((BitByteAddr>>sfrbit)&1)^1); }
@if BIT_OPS == "BIT_ADDRS"
:ORL CY,BitAddr is $(GROUP1) & CY & ophi=7 & oplo=2; BitAddr & sfrbit & BitByteAddr {$(CY)=$(CY)| BitAddr; }
:ORL CY,BitAddr2 is $(GROUP1) & CY & ophi=10 & oplo=0; BitAddr2 & sfrbit & BitByteAddr {$(CY)=$(CY)| (BitAddr2^1); }
@elif BIT_OPS == "PCODEOPS"
:ORL CY,BitAddr is $(GROUP1) & CY & ophi=7 & oplo=2; BitAddr & sfrbit & BitByteAddr {$(CY)=$(CY)| get(BitAddr, BitByteAddr); }
:ORL CY,BitAddr2 is $(GROUP1) & CY & ophi=10 & oplo=0; BitAddr2 & sfrbit & BitByteAddr {$(CY)=$(CY)| (get(BitAddr2, BitByteAddr)^1); }
@elif BIT_OPS == "SHIFTS"
:ORL CY,BitAddr is $(GROUP1) & CY & ophi=7 & oplo=2; BitAddr & sfrbit & BitByteAddr {$(CY)=$(CY)| ((BitByteAddr>>sfrbit)&1); }
:ORL CY,BitAddr2 is $(GROUP1) & CY & ophi=10 & oplo=0; BitAddr2 & sfrbit & BitByteAddr {$(CY)=$(CY)| (((BitByteAddr>>sfrbit)&1)^1); }
@endif
:POP Direct is $(GROUP1) & ophi=13 & oplo=0; Direct { pop8(Direct); }
:PUSH Direct is $(GROUP1) & ophi=12 & oplo=0; Direct { push8(Direct); }
:RET is $(GROUP1) & ophi=2 & oplo=2 {
@if defined(MCS251) || defined(MX51)
pc:2 = 0; pop16(pc); pc3:3 = (inst_next & 0xff0000) + zext(pc); return[pc3];
@elif defined(MCS51)
pc:2 = 0; pop16(pc); return[pc];
@elif defined(MCS80390)
pc:3 = 0; pop24(pc); return[pc];
@endif
}
:RETI is $(GROUP1) & ophi=3 & oplo=2 {
@if defined(MCS251) || defined(MX51)
pc:2 = 0; pop16(pc); pc3:3 = (inst_next & 0xff0000) + zext(pc); return[pc3];
@elif defined(MCS51)
pc:2 = 0; pop16(pc); return[pc];
@elif defined(MCS80390)
pc:3 = 0; pop24(pc); return[pc];
@endif
}
:RL Areg is $(GROUP1) & ophi=2 & oplo=3 & Areg { ACC = (ACC<<1) | (ACC>>7); }
:RLC Areg is $(GROUP1) & ophi=3 & oplo=3 & Areg { tmp : 1 = (ACC&0x80)>>7; ACC = (ACC<<1) | $(CY);$(CY)= tmp; }
:RR Areg is $(GROUP1) & ophi=0 & oplo=3 & Areg { ACC = (ACC>>1) | (ACC<<7); }
:RRC Areg is $(GROUP1) & ophi=1 & oplo=3 & Areg { tmp : 1 = ACC&1; ACC = (ACC>>1) | ($(CY)<<7);$(CY)= tmp; }
:SETB CY is $(GROUP1) & CY & ophi=13 & oplo=3 { $(CY)=1; }
:SETB BitAddr is $(GROUP1) & ophi=13 & oplo=2; BitAddr & bitaddr57=7 & sfrbit3=0 & sfrbit & BitByteAddr { BitByteAddr = BitByteAddr | (1<<sfrbit); }
@if BIT_OPS == "BIT_ADDRS"
:SETB BitAddr is $(GROUP1) & ophi=13 & oplo=2; BitAddr & sfrbit & BitByteAddr { BitAddr = 1; }
@elif BIT_OPS == "PCODEOPS"
:SETB BitAddr is $(GROUP1) & ophi=13 & oplo=2; BitAddr & sfrbit & BitByteAddr { BitByteAddr = set(BitAddr, BitByteAddr); }
@elif BIT_OPS == "SHIFTS"
:SETB BitAddr is $(GROUP1) & ophi=13 & oplo=2; BitAddr & sfrbit & BitByteAddr { BitByteAddr = BitByteAddr | (1<<sfrbit); }
@endif
:SJMP Rel8 is $(GROUP1) & ophi=8 & oplo=0; Rel8 { goto Rel8; }
:SUBB Areg,rn is $(GROUP2) & ophi=9 & rnfill=1 & rn & Areg { tmp : 1 = rn+$(CY); subflags(ACC,tmp); ACC = ACC - tmp; }
:SUBB Areg,Direct is $(GROUP1) & ophi=9 & oplo=5 & Areg; Direct { tmp:1 = Direct+$(CY); subflags(ACC,tmp); ACC = ACC - tmp; }
:SUBB Areg,Ri is $(GROUP2) & ophi=9 & Areg & rifill=3 & Ri { local tmp = Ri+$(CY); subflags(ACC,tmp); ACC = ACC - tmp; }
:SUBB Areg,Data is $(GROUP1) & ophi=9 & oplo=4 & Areg; Data { tmp:1 = Data+$(CY); subflags(ACC,tmp); ACC = ACC - tmp; }
:SWAP Areg is $(GROUP1) & ophi=12 & oplo=4 & Areg { ACC = (ACC>>4) | (ACC<<4); }
:XCH Areg,rn is $(GROUP2) & ophi=12 & rnfill=1 & rn & Areg { tmp : 1 = ACC; ACC = rn; rn = tmp; }
:XCH Areg,Direct is $(GROUP1) & ophi=12 & oplo=5 & Areg; Direct { tmp : 1 = ACC; ACC = Direct; Direct = tmp; }
:XCH Areg,Ri is $(GROUP2) & ophi=12 & rifill=3 & Ri & Areg { tmp : 1 = ACC; ACC = Ri; Ri = tmp; }
# TODO: This instruction appears to be in both GROUP2 & GROUP3 (always available)
:XCHD Areg,Ri is ophi=13 & Areg & rifill=3 & Ri { tmp : 1 = ACC & 0xf; ACC = (ACC&0xf0) | (Ri&0xf); Ri = (Ri&0xf0) | tmp; }
:XRL Areg,rn is $(GROUP2) & ophi=6 & rnfill=1 & rn & Areg { ACC = ACC ^ rn; }
:XRL Areg,Direct is $(GROUP1) & ophi=6 & oplo=5 & Areg; Direct { ACC = ACC ^ Direct; }
:XRL Areg,Ri is $(GROUP2) & ophi=6 & rifill=3 & Ri & Areg { ACC = ACC ^ Ri; }
:XRL Areg,Data is $(GROUP1) & ophi=6 & oplo=4 & Areg; Data { ACC = ACC ^ Data; }
:XRL Direct,Areg is $(GROUP1) & ophi=6 & oplo=2 & Areg; Direct { Direct = Direct ^ ACC; }
:XRL Direct,Data is $(GROUP1) & ophi=6 & oplo=3; Direct; Data { Direct = Direct ^ Data; }