"$Id$" /******************************************************************** **** **** **** Z 8 0 B A C K E N D T A B L E S **** **** **** ********************************************************************/ /* * INTEGER SIZE: 16 bits * POINTER SIZE: 16 bits */ /* We store LB in the iy index-register, because this results in the * cheapest addressing schemes for instruction like lol and stl. * For a lol with an argument that is too low (< 0-128) or too high * (>= 127) there is an overhead, because the offset cannot be * expressed in 8 bits. In these cases we copy the LB to the hl-register, * compute the required address and use register indirect mode to do * the load. These cases occur rarely (about 11.5 % in C and 5.5 % * in Pascal. */ EM_WSIZE = 2 EM_PSIZE = 2 EM_BSIZE = 4 /************************** ** R E G I S T E R S ** **************************/ REGISTERS: AA = ("a",1) REG1, AREG. BB = ("b",1) REG1. CC = ("c",1) REG1. DD = ("d",1) REG1. EE = ("e",1) REG1. HH = ("h",1) REG1. LL = ("l",1) REG1. BC = ("bc",2,BB,CC) REG, GEN_REG, BC_REG, ANY_REG. DE = ("de",2,DD,EE) REG, GEN_REG, DE_REG, ANY_REG. HL = ("hl",2,HH,LL) GEN_REG, HL_REG, ANY_REG. LB = ("iy",2) LOCALBASE. IX = ("ix",2) INDEXREG, IX_REG, ANY_REG. pseudo0 = ("",2,BC,DE). pseudo1 = ("",2,HL,IX). pseudo2 = ("",2,pseudo0,pseudo1). pseudo3 = ("",2,pseudo2,AA) ALL_REG. /***************** ** T O K E N S ** *****************/ TOKENS: IMMEDIATE1 = {INT off;} 1 "%[off]" IMMEDIATE = {INT off;} 2 "%[off]" IREG1 = {REGISTER reg;} 1 "(%[reg])" INDEXED = {REGISTER reg; INT off; } 1 "(%[reg]+%[off])" EXTENDED = {STRING off; } 2 "(%[off])" LOCAL_ADDR = {INT off; } 2 EXTENDED_ADDR = {STRING off; } 2 "%[off]" /************************************* ** T O K E N E X P R E S S I O N S ** *************************************/ TOKENEXPRESSIONS: ANYTOK = IMMEDIATE + EXTENDED ANY1 = REG1 + IMMEDIATE1 + IREG1 + INDEXED ANY_ADDR = EXTENDED_ADDR + LOCAL_ADDR ANY = ANYTOK + ANY_REG + ANY_ADDR MEM_ALL = ANY - ANY_REG REG_SCR = REG * SCRATCH ANY_REG_SCR = ANY_REG * SCRATCH GEN_REG_SCR = GEN_REG * SCRATCH HL_REG_SCR = HL_REG * SCRATCH BC_REG_SCR = BC_REG * SCRATCH DE_REG_SCR = DE_REG * SCRATCH IX_REG_SCR = IX_REG * SCRATCH /************* ** C O D E ** *************/ CODE: /* G R O U P I : L O A D S */ loc | | | {IMMEDIATE,$1} | | ldc | | | {IMMEDIATE,highw(1)} {IMMEDIATE,loww(1)} | | lol sfit($1,8) | | allocate(REG) move({INDEXED,LB,$1} , %[a.2] ) move({INDEXED,LB,$1+1} , %[a.1] ) | %[a] | | lol | | allocate(HL_REG,REG) "push iy" "pop %[b]" move({IMMEDIATE,$1} , %[a] ) "add hl,%[b]" "ld %[b.2],(hl)" "inc hl" "ld %[b.1],(hl)" erase(HL) erase(%[a]) | %[b] | | ldl $1<126 && $1>0-128 | | allocate(REG,REG) move({INDEXED,LB,$1} , %[a.2]) move({INDEXED,LB,$1+1},%[a.1]) move({INDEXED,LB,$1+2},%[b.2]) move({INDEXED,LB,$1+3},%[b.1]) | %[b] %[a] | | ldl | | remove(ALL) allocate(BC_REG,DE_REG,HL_REG={IMMEDIATE,$1}) "push iy" "pop bc" "add hl,bc" "ld e,(hl)" "inc hl" "ld d,(hl)" "inc hl" "ld c,(hl)" "inc hl" "ld b,(hl)" | BC DE | | loe | | | {EXTENDED,$1} | | lde | | | {EXTENDED,$1+"+2"} {EXTENDED,$1} | | lil sfit($1,8) | | allocate(HL_REG,REG) move({INDEXED,LB,$1} , %[a.2]) move({INDEXED,LB,$1+1} , %[a.1]) "ld %[b.2],(hl)" "inc hl" "ld %[b.1],(hl)" erase(HL) erase(%[a]) | %[b] | | lil | | allocate(HL_REG = {IMMEDIATE,$1} , REG) "push iy" "pop %[b]" "add hl,%[b]" "ld %[b.2],(hl)" "inc hl" "ld %[b.1],(hl)" "ld h,%[b.1]" "ld l,%[b.2]" "ld %[b.2],(hl)" "inc hl" "ld %[b.1],(hl)" erase(HL) erase(%[a]) | %[b] | | lof | HL_REG_SCR | allocate(REG = {IMMEDIATE,$1} ) "add hl,%[a]" "ld %[a.2],(hl)" "inc hl" "ld %[a.1],(hl)" erase(HL) erase(%[a]) | %[a] | | ... | REG_SCR | allocate(HL_REG = {IMMEDIATE,$1} ) "add hl,%[1]" "ld %[1.2],(hl)" "inc hl" "ld %[1.1],(hl)" erase(HL) erase(%[1]) | %[1] | | ldf | HL_REG_SCR | allocate(REG = {IMMEDIATE,$1} , REG) "add hl,%[a]" "ld %[a.2],(hl)" "inc hl" "ld %[a.1],(hl)" "inc hl" "ld %[b.2],(hl)" "inc hl" "ld %[b.1],(hl)" erase(HL) erase(%[a]) | %[b] %[a] | | ... | REG_SCR | allocate(HL_REG = {IMMEDIATE,$1} , REG) "add hl,%[1]" "ld %[1.2],(hl)" "inc hl" "ld %[1.1],(hl)" "inc hl" "ld %[b.2],(hl)" "inc hl" "ld %[b.1],(hl)" erase(HL) erase(%[1]) | %[b] %[1] | | lal | | remove(ALL) allocate(HL_REG, REG = {IMMEDIATE,$1} ) "push iy" "pop hl" "add hl,%[b]" erase(%[a]) | %[a] | | lae | | | {EXTENDED_ADDR,$1} | | lxl $1 == 0 | | remove(ALL) "push iy" | | | lxl | | remove(ALL) allocate(AREG = {IMMEDIATE1,$1} , HL_REG,BC_REG) "push iy" "pop %[c]" "1:" "ld hl,4" "add hl,%[c]" "ld %[c.2],(hl)" "inc hl" "ld %[c.1],(hl)" "dec a" "jr nz,1b" "push %[c]" erase(AA) | | | lxa $1 == 0 | | | | lxl $1 adp 4 | lxa $1 == 1 | | remove(ALL) allocate(HL_REG,BC_REG) "ld %[b],4" "push iy" "pop hl" "add hl,%[b]" "ld %[b.2],(hl)" "inc hl" "ld %[b.1],(hl)" "ld hl,4" "add hl,%[b]" | HL | | lxa $1 > 1 | | remove (ANY) allocate(AREG = {IMMEDIATE1,$1}, HL_REG,BC_REG) "push iy" "pop %[c]" "1:" "ld hl,4" "add hl,%[c]" "ld %[c.2],(hl)" "inc hl" "ld %[c.1],(hl)" "inc hl" "dec a" "jr nz,1b" "ld hl,4" "add hl,%[c]" erase(AA) | HL | | dch | | | | loi 2 | loi $1 == 1 | HL_REG | allocate(REG = {IMMEDIATE,0} ) "ld %[a.2],(hl)" erase(%[a]) | %[a] | | ... | REG | allocate(REG,AREG) move({IREG1,%[1]} , AA) move(AA , %[a.2]) move({IMMEDIATE1,0} , %[a.1]) erase(AA) | %[a] | | loi $1 == 2 | HL_REG_SCR | remove(ALL) allocate(REG) "ld %[a.2],(hl)" "inc hl" "ld %[a.1],(hl)" erase(%[1]) | %[a] | | loi $1 == 4 | HL_REG_SCR | remove(ALL) allocate(AREG,REG) "ld %[b.2],(hl)" "inc hl" "ld %[b.1],(hl)" "inc hl" "ld a,(hl)" "inc hl" "ld h,(hl)" "ld l,a" erase(HL) | HL %[b] | | loi $1 <= 511 && $1 > 4 | HL_REG_SCR | remove(ALL) allocate(AREG,REG) move({IMMEDIATE,$1-1} , %[b]) "add hl,%[b]" move({IMMEDIATE1,$1/2} , AA) "1:" "ld %[b.1],(hl)" "dec hl" "ld %[b.2],(hl)" "dec hl" "push %[b]" "dec a" "jr nz,1b" erase(%[a]) erase(%[b]) | | | loi $1 > 511 | STACK | remove(ALL) allocate(ALL_REG) move({IMMEDIATE,$1}, HL) "push hl" "call .los" erase(HL) | | | los $1 == 2 | STACK | remove(ALL) allocate(ALL_REG) "call .los" | | | lpi | | | {EXTENDED_ADDR,$1} | | /* G R O U P II : S T O R E S */ stl sfit($1,8) | REG + HL_REG | remove(ALL) move(%[1.2] , {INDEXED,LB,$1} ) move(%[1.1] , {INDEXED,LB,$1+1} ) | | | stl | REG | remove(ALL) allocate(HL_REG = {IMMEDIATE,$1} , REG) "push iy" "pop %[b]" "add hl,%[b]" "ld (hl),%[1.2]" "inc hl" "ld (hl),%[1.1]" erase(%[a]) | | | ste | ANY_REG | remove(EXTENDED,%[off] == $1) remove(ALL) move(%[1] , {EXTENDED,$1} ) | | | sil ($1 >= 0-128 && $1 < 127) | REG | remove(ALL) allocate(HL_REG) move({INDEXED,LB,$1} , %[a.2]) move({INDEXED,LB,$1+1} , %[a.1]) "ld (hl),%[1.2]" "inc hl" "ld (hl),%[1.1]" erase(%[a]) | | | sil ($1 < 0-128 || $1 >= 127) | REG | remove(ALL) allocate(HL_REG,REG) "push iy" "pop %[b]" move({IMMEDIATE,$1} , %[a]) "add hl,%[b]" "ld %[b.2],(hl)" "inc hl" "ld %[b.1],(hl)" "ld h,%[b.1]" "ld l,%[b.2]" "ld (hl),%[1.2]" "inc hl" "ld (hl),%[1.1]" erase(%[a]) | | | stf | HL_REG_SCR REG | remove(ALL) allocate(REG = {IMMEDIATE,$1}) "add hl,%[a]" "ld (hl),%[2.2]" "inc hl" "ld (hl),%[2.1]" erase(%[1]) | | | sti $1 == 1 | HL_REG REG | remove(ALL) "ld (hl),%[2.2]" | | | sti $1 == 2 | HL_REG_SCR REG | remove(ALL) "ld (hl),%[2.2]" "inc hl" "ld (hl),%[2.1]" erase(%[1]) | | | sti $1 == 4 | HL_REG_SCR REG REG | remove(ALL) "ld (hl),%[2.2]" "inc hl" "ld (hl),%[2.1]" "inc hl" "ld (hl),%[3.2]" "inc hl" "ld (hl),%[3.1]" erase(HL) | | | sti $1 <= 511 && $1 > 4 | HL_REG_SCR | remove(ALL) allocate(AREG,REG) move({IMMEDIATE1,$1/2} , AA) "1:" "pop %[b]" "ld (hl),%[b.2]" "inc hl" "ld (hl),%[b.1]" "inc hl" "dec a" "jr nz,1b" erase(AA) erase(HL) | | | sti $1 > 511 | STACK | remove(ALL) allocate(ALL_REG) move({IMMEDIATE,$1}, HL) "push hl" "call .sts" erase(HL) | | | sts $1 == 2 | STACK | remove(ALL) allocate(ALL_REG) "call .sts" | | | sdl ($1 >= 0-128 && $1 < 125) | REG REG | remove(ALL) move(%[1.2] , {INDEXED,LB,$1}) move(%[1.1] , {INDEXED,LB,$1+1}) move(%[2.2] , {INDEXED,LB,$1+2}) move(%[2.1] , {INDEXED,LB,$1+3}) | | | sdl ($1 < 0-128 || $1 >= 125) | STACK | remove(ALL) allocate(HL_REG = {IMMEDIATE,$1} , BC_REG,DE_REG,IX_REG,AREG ) "call .sdl" erase(HL) | | | sde | ANY_REG ANY_REG | remove(ALL) move(%[1] , {EXTENDED,$1}) move(%[2] , {EXTENDED,$1+"+2"}) | | | sdf | | remove(ALL) allocate(ALL_REG) move({IMMEDIATE,$1},DE) "call .sdf" | | | /* G R O U P III & IV : I N T E G E R A R I T H M E T I C */ adi $1 == 2 | HL_REG_SCR GEN_REG | "add hl,%[2]" erase(HL) | HL | | ... | GEN_REG HL_REG_SCR | "add hl,%[1]" erase(HL) | HL | | adi $1 == 4 | HL_REG_SCR DE_REG_SCR STACK | allocate(BC_REG) "pop bc" "add hl,bc" "ex de,hl" "pop bc" "adc hl,bc" erase(DE) erase(HL) | HL DE | | sbi $1 == 2 | GEN_REG HL_REG_SCR | "or a" "sbc hl,%[1]" erase(HL) | HL | | sbi $1 == 4 | BC_REG_SCR DE_REG_SCR STACK | allocate(HL_REG) "or a" "pop hl" "sbc hl,bc" /* least sign. */ "ex (sp),hl" "sbc hl,de" "pop de" erase(DE) erase(HL) | HL DE | | mli $1 == 2 | DE_REG_SCR BC_REG STACK | allocate(HL_REG,IX_REG,AREG) "call .mli2" erase(DE) | HL | | mli $1 == 4 | STACK | allocate(ALL_REG) "call .mli4" | | | dvi $1 == 2 | BC_REG_SCR DE_REG_SCR STACK | allocate(HL_REG,IX_REG,AREG) "call .dvi2" "push de" erase(BC) erase(DE) | | | dvi $1 == 4 | STACK | allocate(ALL_REG) "call .dvi4" | | | dvu $1 == 2 | BC_REG_SCR DE_REG_SCR STACK | allocate(HL_REG,IX_REG,AREG) "call .dvu2" erase(BC) erase(DE) | DE | | dvu $1 == 4 | STACK | allocate(ALL_REG) "call .dvu4" | | | rmi $1 == 2 | BC_REG_SCR DE_REG_SCR STACK | allocate(HL_REG,IX_REG,AREG) "call .rmi2" erase(BC) erase(DE) | DE | | rmi $1 == 4 | STACK | allocate(ALL_REG) "call .dvi4" "pop hl" "pop hl" erase(HL) | BC DE | | rmu $1 == 2 | BC_REG_SCR DE_REG_SCR STACK | allocate(HL_REG,IX_REG,AREG) "call .dvu2" erase(BC) erase(DE) | HL | | rmu $1 == 4 | STACK | allocate(ALL_REG) "call .dvu4" | BC DE | | ngi $1 == 2 | REG | allocate(HL_REG = {IMMEDIATE,0}) "or a" "sbc hl,%[1]" erase(HL) | HL | | ngi $1 == 4 | DE_REG_SCR BC_REG_SCR | allocate(HL_REG,AREG) "xor a" "ld h,a" "ld l,a" "sbc hl,de" "ex de,hl" "ld h,a" "ld l,a" "sbc hl,bc" erase(DE) | HL DE | | sli $1 == 2 | REG_SCR HL_REG_SCR | "inc %[1.1]" /* see if count >> 15 */ "dec %[1.1]" "jr z,1f" "ld %[1.2],15" "1:" "dec %[1.2]" "jp m,2f" "add hl,hl" "jr 1b" "2:" erase(%[1]) erase(HL) | HL | | sli $1 == 4 | REG_SCR IX_REG_SCR HL_REG_SCR | "inc %[1.1]" "dec %[1.1]" "jr z,1f" "ld %[1.2],31" "1:" "dec %[1.2]" "jp m,2f" "add ix,ix" "adc hl,hl" "jr 1b" "2:" erase(%[1]) erase(HL) erase(IX) | HL IX | | sri $1 == 2 | GEN_REG_SCR GEN_REG_SCR | "inc %[1.1]" "dec %[1.1]" "jr z,1f" "ld %[1.2],15" "1:" "dec %[1.2]" "jp m,2f" "sra %[2.1]" "rr %[2.2]" "jr 1b" "2:" erase(%[1]) erase(%[2]) | %[2] | | sri $1 == 4 | GEN_REG_SCR GEN_REG_SCR GEN_REG_SCR | "inc %[1.1]" "dec %[1.1]" "jr z,1f" "ld %[1.2],31" "1:" "dec %[1.2]" "jp m,2f" "sra %[3.1]" "rr %[3.2]" "rr %[2.1]" "rr %[2.2]" "jr 1b" "2:" erase(%[1]) erase(%[2]) erase(%[3]) | %[3] %[2] | | mlu | | | | mli $1 | sru $1 == 2 | GEN_REG_SCR GEN_REG_SCR | "inc %[1.1]" "dec %[1.1]" "jr z,1f" "ld %[1.2],15" "1:" "dec %[1.2]" "jp m,2f" "srl %[2.1]" "rr %[2.2]" "jr 1b" "2:" erase(%[1]) erase(%[2]) | %[2] | | sru $1 == 4 | GEN_REG_SCR GEN_REG_SCR GEN_REG_SCR | "inc %[1.1]" "dec %[1.1]" "jr z,1f" "ld %[1.2],31" "1:" "dec %[1.2]" "jp m,2f" "srl %[3.1]" "rr %[3.2]" "rr %[2.1]" "rr %[2.2]" "jr 1b" "2:" erase(%[1]) erase(%[2]) erase(%[3]) | %[3] %[2] | | adu | | | | adi $1 | sbu | | | | sbi $1 | slu | | | | sli $1 | /* G R O U P V : F L O A T I N G P O I N T */ adf | | "call .unimpld" | | | sbf | | "call .unimpld" | | | mlf | | "call .unimpld" | | | dvf | | "call .unimpld" | | | ngf | | "call .unimpld" | | | fif | | "call .unimpld" | | | fef | | "call .unimpld" | | | /* G R O U P VI : P O I N T E R A R I T H M E T I C */ adp $1 == 0 | | | | | adp $1 == 1 | ANY_REG_SCR | "inc %[1]" erase(%[1]) | %[1] | | adp $1 == 2 | ANY_REG_SCR | "inc %[1]" "inc %[1]" erase(%[1]) | %[1] | | adp $1 == 0-1 | ANY_REG_SCR | "dec %[1]" erase(%[1]) | %[1] | | adp $1 == 0-2 | ANY_REG_SCR | "dec %[1]" "dec %[1]" erase(%[1]) | %[1] | | adp $1 < 0-2 || $1 > 2 | HL_REG_SCR | allocate(REG = {IMMEDIATE,$1} ) "add hl,%[a]" erase(HL) | HL | | ... | REG | allocate(HL_REG = {IMMEDIATE,$1} ) "add hl,%[1]" erase(HL) | HL | | ... | LOCAL_ADDR | remove(ALL) | {LOCAL_ADDR, %[1.off]+$1} | | ads $1 == 2 | HL_REG_SCR REG | remove(ALL) "add hl,%[2]" erase(HL) | HL | | ... | REG HL_REG_SCR | "add hl,%[1]" erase(HL) | HL | | sbs $1 == 2 | REG HL_REG_SCR | "or a" "sbc hl,%[1]" erase(HL) | HL | | /* G R O U P VII : I N C R E M E N T / D E C R E M E N T */ inc | ANY_REG_SCR | "inc %[1]" erase(%[1]) | %[1] | | /* There is no efficient way on the Z80 to increment or decrement * a local or external. We first fetch the variable into a register, * increment/decrement it and then store it. */ inl | | | | lol $1 inc stl $1 | ine | | | | loe $1 inc ste $1 | dec | ANY_REG_SCR | "dec %[1]" erase(%[1]) | %[1] | | del | | | | lol $1 dec stl $1 | dee | | | | loe $1 dec ste $1 | zrl ($1 >= 0-128 && $1 < 127) | | remove(ALL) allocate(AREG) "xor a" move(AA , {INDEXED,LB,$1}) move(AA , {INDEXED,LB,$1+1}) | | | zrl ($1 < 0-128 || $1 >= 127) | | remove(ALL) allocate(HL_REG = {IMMEDIATE,$1} , REG, AREG) "push iy" "pop %[b]" "add hl,%[b]" "xor a" "ld (hl),a" "inc hl" "ld (hl),a" erase(HL) | | | zrf | | "call .unimpld" | | | zre | | remove(EXTENDED,%[off] == $1) remove(ALL) allocate(ANY_REG = {IMMEDIATE,0} ) move(%[a] , {EXTENDED,$1}) | | | zer $1 == 2 | | | {IMMEDIATE,0} | | zer $1 == 4 | | | {IMMEDIATE,0} {IMMEDIATE,0} | | zer $1 > 4 && $1 < 256 | STACK | allocate(BC_REG , GEN_REG) "ld b,$1" "ld %[b],0" "1:" "push %[b]" "djnz 1b" | | | /* G R O U P VIII : C O N V E R T */ cii | STACK | remove(ALL) allocate(ALL_REG) "call .cii" | | | cuu | STACK | remove(ALL) allocate(ALL_REG) "call .cuu" | | | cui | | | | cuu | ciu | | | | cuu | cfi | | "call .unimpld" | | | cif | | "call .unimpld" | | | cuf | | "call .unimpld" | | | cff | | "call .unimpld" | | | cfu | | "call .unimpld" | | | cmf | | "call .unimpld" | | | /* G R O U P IX : L O G I C A L */ and $1 == 2 | GEN_REG GEN_REG_SCR | allocate(AREG) "ld a,%[1.2]" "and %[2.2]" "ld %[2.2],a" "ld a,%[1.1]" "and %[2.1]" "ld %[2.1],a" erase(%[2]) | %[2] | | and defined($1) && $1 > 2 | STACK | allocate(DE_REG = {IMMEDIATE,$1}, BC_REG,HL_REG,IX_REG,AREG) "call .and" erase(DE) | | | and ! defined($1) | DE_REG_SCR STACK | allocate(BC_REG,HL_REG,IX_REG,AREG) "call .and" erase(DE) | | | ior $1 == 2 | GEN_REG GEN_REG_SCR | allocate(AREG) "ld a,%[1.2]" "or %[2.2]" "ld %[2.2],a" "ld a,%[1.1]" "or %[2.1]" "ld %[2.1],a" erase(%[2]) | %[2] | | ior defined($1) && $1 > 2 | STACK | allocate(DE_REG = {IMMEDIATE,$1}, BC_REG,HL_REG,IX_REG,AREG) "call .ior" erase(DE) | | | ior ! defined($1) | DE_REG_SCR STACK | allocate(BC_REG,HL_REG,IX_REG,AREG) "call .ior" erase(DE) | | | xor $1 == 2 | GEN_REG GEN_REG_SCR | allocate(AREG) "ld a,%[1.2]" "xor %[2.2]" "ld %[2.2],a" "ld a,%[1.1]" "xor %[2.1]" "ld %[2.1],a" erase(%[2]) | %[2] | | xor defined($1) && $1 > 2 | STACK | allocate(DE_REG = {IMMEDIATE,$1}, BC_REG,HL_REG,IX_REG,AREG) "call .xor" erase(DE) | | | xor ! defined($1) | DE_REG_SCR STACK | allocate(BC_REG,HL_REG,IX_REG,AREG) "call .xor" erase(DE) | | | com $1 == 2 | GEN_REG_SCR | allocate(AREG) "ld a,%[1.2]" "cpl" "ld %[1.2],a" "ld a,%[1.1]" "cpl" "ld %[1.1],a" erase(%[1]) | %[1] | | com defined($1) && $1 > 2 | STACK | allocate(AREG, HL_REG = {IMMEDIATE,$1} ) "add hl,sp" "1:" "dec hl" "ld a,(hl)" "cpl" "ld (hl),a" "xor a" "sbc hl,sp" "jr z,2f" "add hl,sp" "jr 1b" "2:" erase(HL) | | | com ! defined($1) | HL_REG_SCR STACK | allocate(AREG) "add hl,sp" "1:" "dec hl" "ld a,(hl)" "cpl" "ld (hl),a" "xor a" "sbc hl,sp" "jr z,2f" "add hl,sp" "jr 1b" "2:" erase(HL) | | | rol $1 == 2 | REG_SCR HL_REG_SCR | allocate(AREG) "ld a,%[1.2]" "and 15" "jr z,2f" "ld %[1],0" "1:" "add hl,hl" "adc hl,%[1]" "dec a" "jr nz,1b" "2:" erase(%[1]) erase(%[2]) | HL | | rol $1 == 4 | REG IX_REG_SCR HL_REG_SCR | allocate(AREG) "ld a,%[1.2]" "and 31" "jr z,3f" "1:" "add ix,ix" "adc hl,hl" "jr nc,2f" "inc ix" "2:" "dec a" "jr nz,1b" "3:" erase(HL) erase(IX) | HL IX | | ror $1 == 2 | GEN_REG_SCR GEN_REG_SCR | allocate(AREG) "ld a,%[1.2]" "and 15" "jr z,0f" "1:" "srl %[2.1]" "rr %[2.2]" "jr nc,2f" "set 7,%[2.1]" "2:" "dec a" "jr nz,1b" "0:" erase(%[1]) erase(%[2]) | %[2] | | ror $1 == 4 | GEN_REG_SCR GEN_REG_SCR GEN_REG_SCR | allocate(AREG) "ld a,%[1.2]" "and 31" "jr z,0f" "1:" "srl %[3.1]" "rr %[3.2]" "rr %[2.1]" "rr %[2.2]" "jr nc,2f" "set 7,%[3.1]" "2:" "dec a" "jr nz,1b" "0:" erase(%[1]) erase(%[2]) erase(%[3]) | %[3] %[2] | | /* G R O U P X : S E T S */ inn defined($1) | STACK | allocate(HL_REG = {IMMEDIATE,$1}, BC_REG,DE_REG,IX_REG,AREG) "call .inn" erase(HL) | | | inn !defined($1) | HL_REG_SCR STACK | allocate(BC_REG,DE_REG,IX_REG,AREG) "call .inn" erase(HL) | | | set defined($1) | STACK | allocate(HL_REG = {IMMEDIATE,$1}, BC_REG,DE_REG,IX_REG,AREG) "call .set" erase(HL) | | | set !defined($1) | HL_REG_SCR STACK | allocate(BC_REG,DE_REG,IX_REG,AREG) "call .set" erase(HL) | | | /* G R O U P XI : A R R A Y S */ lae aar $2 == 2 && rom(1,3) == 2 | STACK | allocate(ALL_REG) move({EXTENDED_ADDR,$1},BC) "push bc" "call .aar2" | | | lae aar $2 == 2 && rom(1,3) != 2 | STACK | allocate(ALL_REG) move({EXTENDED_ADDR,$1},BC) "push bc" "call .aar" | | | aar $1==2 | | remove(ALL) allocate(ALL_REG) "call .aar" | | | aar !defined($1) | | remove(ALL) allocate(ALL_REG) "call .aaru" | | | lae lar $2 == 2 && rom(1,3) == 2 | STACK | remove(ALL) allocate(ALL_REG) move({EXTENDED_ADDR,$1},BC) "push bc" "call .lar2" | | | lae lar $2 == 2 && rom(1,3) != 2 | STACK | remove(ALL) allocate(ALL_REG) move({EXTENDED_ADDR,$1},BC) "push bc" "call .lar" | | | lar $1==2 | | remove(ALL) allocate(ALL_REG) "call .lar" | | | lar !defined($1) | | remove(ALL) allocate(ALL_REG) "call .laru" | | | lae sar $2 == 2 && rom(1,3) == 2 | STACK | remove(ALL) allocate(ALL_REG) move({EXTENDED_ADDR, $1},BC) "push bc" "call .sar2" | | | lae sar $2 == 2 && rom(1,3) != 2 | STACK | remove(ALL) allocate(ALL_REG) move({EXTENDED_ADDR, $1},BC) "push bc" "call .sar" | | | sar $1==2 | | remove(ALL) allocate(ALL_REG) "call .sar" | | | sar !defined($1) | | remove(ALL) allocate(ALL_REG) "call .saru" | | | /* G R O U P XII : C O M P A R E */ cmi $1 == 2 | REG_SCR HL_REG_SCR | remove(ALL) allocate(AREG) "ld a,h" "xor %[1.1]" "jp m,1f" "sbc hl,%[1]" "jr 2f" "1:" "xor %[1.1]" "jp m,2f" "set 0,l" "2:" erase(%[1]) erase(%[2]) | HL | | cmi $1 == 4 | STACK | remove(ALL) allocate(AREG = {IMMEDIATE1,1}, BC_REG,DE_REG,HL_REG,IX_REG) "call .cmu4" erase(AA) | DE | | cmu $1 == 2 | REG_SCR HL_REG_SCR | remove(ALL) allocate(AREG) "ld a,h" "xor %[1.1]" /* resets carry bit */ "jp m,1f" "sbc hl,%[1]" "jr 2f" "1:" "xor %[1.1]" "cpl" "set 0,l" "2:" erase(%[1]) erase(%[2]) | HL | | cmu $1 == 4 | STACK | remove(ALL) allocate(AREG = {IMMEDIATE1,0}, BC_REG,DE_REG,HL_REG,IX_REG) "call .cmu4" erase(AA) | DE | | cmp | | | | cmu 2 | cms $1 == 2 | GEN_REG GEN_REG_SCR | remove(ALL) allocate(AREG) "ld a,%[1.1]" "xor %[2.1]" "ld %[2.1],a" "ld a,%[1.2]" "xor %[2.2]" "ld %[2.2],a" | %[2] | | /*** cmu defined($1) | STACK | allocate(HL_REG = {IMMEDIATE,$1}, BC_REG,DE_REG,IX_REG,AREG) "call .cmu" erase(HL) | | | cmu ! defined($1) | HL_REG_SCR STACK | allocate(BC_REG,DE_REG,IX_REG,AREG) "call .cmu" erase(HL) | | | */ cms defined($1) | STACK | remove(ALL) allocate(HL_REG = {IMMEDIATE,$1}, BC_REG,DE_REG,IX_REG,AREG) "call .cms" erase(HL) | | | cms ! defined($1) | HL_REG_SCR STACK | allocate(BC_REG,DE_REG,IX_REG,AREG) "call .cms" erase(HL) | | | tlt | GEN_REG | remove(ALL) allocate(GEN_REG = {IMMEDIATE,0}) "bit 7,%[1.1]" "jr z,1f" "inc %[a.2]" "1:" erase(%[a]) | %[a] | | tle | GEN_REG | remove(ALL) allocate(AREG, GEN_REG = {IMMEDIATE,1}) "xor a" "add a,%[1.1]" "jp m,2f" "jr nz,1f" "xor a" "add a,%[1.2]" "jr z,2f" "1:" "dec %[b.2]" "2:" erase(%[b]) | %[b] | | teq | GEN_REG | remove(ALL) allocate(AREG,GEN_REG = {IMMEDIATE,0}) "ld a,%[1.1]" "or a" "jp m,1f" "xor %[1.2]" "jr nz,1f" "inc %[b.2]" "1:" erase(%[b]) | %[b] | | tne | GEN_REG | remove(ALL) allocate(AREG, GEN_REG = {IMMEDIATE,0}) "ld a,%[1.1]" "or %[1.2]" "jr z,1f" "inc %[b.2]" "1:" erase(%[b]) | %[b] | | tge | GEN_REG | remove(ALL) allocate(GEN_REG = {IMMEDIATE,0}) "bit 7,%[1.1]" "jr nz,1f" "inc %[a.2]" "1:" erase(%[a]) | %[a] | | tgt | GEN_REG | remove(ALL) allocate(AREG, GEN_REG = {IMMEDIATE,0}) "xor a" "add a,%[1.1]" "jp m,2f" "jr nz,1f" "xor a" "add a,%[1.2]" "jr z,2f" "1:" "inc %[b.2]" "2:" erase(%[b]) | %[b] | | /* G R O U P XIII : B R A N C H */ bra | | remove(ALL) "jp $1" | | | blt | GEN_REG GEN_REG | remove(ALL) allocate(AREG) "ld a,%[2.2]" "sub %[1.2]" "ld a,%[2.1]" "sbc a,%[1.1]" "jp m,$1" | | | ble | GEN_REG GEN_REG | remove(ALL) allocate(AREG) "ld a,%[2.2]" "sub %[1.2]" "ld a,%[2.1]" "sbc a,%[1.1]" "jp m,$1" "jr nz,1f" "ld a,%[2.2]" "cp %[1.2]" "jr z,$1" "1:" | | | beq | GEN_REG GEN_REG | remove(ALL) allocate(AREG) "ld a,%[2.2]" "sub %[1.2]" "jr nz,1f" "ld a,%[2.1]" "sbc a,%[1.1]" "jr z,$1" "1:" | | | bne | GEN_REG GEN_REG | remove(ALL) allocate(AREG) "ld a,%[2.2]" "sub %[1.2]" "jr nz,$1" "ld a,%[2.1]" "sbc a,%[1.1]" "jr nz,$1" erase(AA) | | | bge | GEN_REG GEN_REG | remove(ALL) allocate(AREG) "ld a,%[2.2]" "sub %[1.2]" "ld a,%[2.1]" "sbc a,%[1.1]" "jp p,$1" | | | bgt | GEN_REG GEN_REG_SCR | remove(ALL) allocate(AREG) "ld a,%[2.2]" "sub %[1.2]" "ld %[2.2],a" "ld a,%[2.1]" "sbc a,%[1.1]" "jp m,1f" "jr nz,$1" "xor a" "cp %[2.2]" "jr nz,$1" "1:" erase(%[2]) | | | zlt | GEN_REG | remove(ALL) "bit 7,%[1.1]" "jr nz,$1" | | | zle | GEN_REG | remove(ALL) allocate(AREG) "xor a" "add a,%[1.1]" "jp m,$1" "jr nz,1f" "xor a" "add a,%[1.2]" "jr z,$1" "1:" | | | zeq | GEN_REG | remove(ALL) allocate(AREG) "ld a,%[1.1]" "or %[1.2]" "jr z,$1" | | | zne | GEN_REG | remove(ALL) allocate(AREG) "ld a,%[1.1]" "or %[1.2]" "jr nz,$1" | | | zge | GEN_REG | remove(ALL) "bit 7,%[1.1]" "jr z,$1" | | | zgt | GEN_REG | remove(ALL) allocate(AREG) "xor a" "add a,%[1.1]" "jp m,1f" "jr nz,$1" "xor a" "add a,%[1.2]" "jr nz,$1" "1:" | | | /* G R O U P XIV : P R O C E D U R E C A L L S */ cai | HL_REG | remove(ALL) allocate( GEN_REG ) "ld %[a],1f" "push %[a]" "jp (hl)" "1:" | | | cal | | remove(ALL) allocate(ALL_REG) "call $1" | | | lfr $1 == 2 | | remove(ALL) "push de" | | | lfr $1 == 4 | STACK | "push de" "push bc" | | | lfr | | remove(ALL) move({IMMEDIATE,$1},DE) "call .lfr" | | | ret $1 == 0 | STACK | remove(ALL) allocate(HL_REG,LOCALBASE) "push iy" "pop hl" "ld sp,hl" "pop iy" "ret" | | | ret $1 == 2 | STACK | remove(ALL) allocate(HL_REG,DE_REG,LOCALBASE) "pop de" "push iy" "pop hl" "ld sp,hl" "pop iy" "ret" | | | ret $1 == 4 | STACK | remove(ALL) allocate(BC_REG, DE_REG, HL_REG, LOCALBASE) "pop bc" "pop de" "push iy" "pop hl" "ld sp,hl" "pop iy" "ret" | | | ret | | remove(ALL) move({IMMEDIATE,$1},DE) "call .ret" erase(BC) | | | /* G R O U P XV : M I S C E L L A N E O U S */ asp $1 == 0 | | | | | asp $1 != 0 | STACK | remove(ALL) allocate(HL_REG) move({IMMEDIATE,$1} , HL) "add hl,sp" "ld sp,hl" erase(HL) | | | ass $1 == 2 | HL_REG_SCR STACK | remove(ALL) "add hl,sp" "ld sp,hl" erase(HL) | | | blm $1 == 0 | | | | | blm $1 > 0 |DE_REG_SCR HL_REG_SCR | allocate(BC_REG = {IMMEDIATE,$1} ) "ldir" erase(HL) erase(BC) erase(DE) | | | bls $1 == 2 | BC_REG_SCR DE_REG_SCR HL_REG_SCR | remove(MEM_ALL) "ldir" erase(HL) erase(BC) erase(DE) | | | csa $1 == 2 | STACK | allocate(ALL_REG) "jr .csa" | | | csb $1 == 2 | STACK | allocate(ALL_REG) "jr .csb" | | | dus $1 == 2 | BC_REG_SCR | remove(MEM_ALL) allocate(HL_REG,DE_REG) move({IMMEDIATE,0} , HL) "add hl,sp" "ld d,h" "ld e,l" /* destination */ "sbc hl,bc" /* source */ "ld sp,hl" "ex de,hl" "ldir" erase(HL) erase(BC) | | | dup $1 == 2 | ANY | | %[1] %[1] | | dup $1 == 4 | ANY ANY | | %[2] %[1] %[2] %[1] | | dup $1 == 6 | ANY ANY ANY | | %[3] %[2] %[1] %[3] %[2] %[1] | | dup $1 > 6 | STACK | allocate(HL_REG,BC_REG,DE_REG) move({IMMEDIATE,0} , HL) "add hl,sp" "ld d,h" "ld e,l" /* destination */ move ({IMMEDIATE,$1},BC) /* count */ "sbc hl,bc" /* source */ "ld sp,hl" "ex de,hl" "ldir" erase(HL) erase(BC) | | | lor $1 == 0 | | "push iy" | | | fil | | allocate(HL_REG) move({EXTENDED_ADDR,$1},HL) "ld (hol0+4),hl" erase(HL) | | | lor $1 == 1 | STACK | allocate(HL_REG) move({IMMEDIATE,0} , HL) "add hl,sp" erase(HL) | HL | | lor $1 == 2 | STACK | | {EXTENDED,".reghp"} | | exg $1 == 2 | ANY ANY | | %[1] %[2] | | exg | STACK | remove(MEM_ALL) allocate(HL_REG) move({IMMEDIATE,$1},HL) "push hl" "call .exg" | | | gto | | remove(ALL) allocate(ALL_REG) move({EXTENDED_ADDR,$1},HL) "call .gto" | | | lim | | | {EXTENDED,"ignmask"} | | lin | | remove(ALL) allocate(HL_REG) move({IMMEDIATE,$1},HL) "ld (hol0),hl" erase(HL) | | | lni | | allocate(HL_REG) "ld hl,hol0" "inc (hl)" erase(HL) | | | lpb | | | | adp 4 | nop | STACK | #ifdef DEBUG allocate(ALL_REG) "call .nop" #endif | | | rck $1 == 2 | STACK | allocate(ALL_REG) "call .rck" | | | rtt | | | | ret 0| sig | HL_REG_SCR | "ld (trapproc),hl" "ld hl,trapproc" | HL | | sim | HL_REG | remove(MEM_ALL) "pop hl" "ld (ignmask),hl" | | | str $1 == 0 | | "pop iy" | | | str $1 == 1 | STACK | allocate(HL_REG) "pop hl" "ld sp,hl" | | | str $1 == 2 | STACK | allocate(ALL_REG) "call .strhp" | | | trp| | remove(ALL) allocate(ALL_REG) "call .trp.z" | | | mon | | remove(MEM_ALL) "call .mon" | | | /* C O E R C I O N S */ /* from 4 bytes to 2 */ /* to a register */ | ANYTOK | allocate(ANY_REG) move(%[1],%[a]) | %[a] | | | STACK | allocate(ANY_REG) "pop %[a]" | %[a] | | | LOCAL_ADDR | allocate(ANY_REG) move(LB,%[a]) "add %[a],%[1]" | %[a] | | | IMMEDIATE | allocate(ANY_REG) move(%[1],%[a]) | %[a] | | /* between registers */ | GEN_REG | allocate(GEN_REG) "ld %[a.1],%[1.1]" "ld %[a.2],%[1.2]" | %[a] | | | LOCALBASE | allocate(ANY_REG) "push iy" "pop %[a]" | %[a] | | /*********** ** MOVES ** ***********/ MOVES: (ANY,ANY,"ld %[2],%[1]") (ANY1,ANY1,"ld %[2],%[1]") /************ * STACKS * ************/ STACKS: (ANY_REG, , "push %[1]" ) (MEM_ALL, ANY_REG, move(%[1],%[a]) "push %[a]" ) (MEM_ALL, , "push hl" move(%[1],HL) "ex (sp),hl" )