"$Header$"
/********************************************************************
 ****							         ****
 ****       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]"
				"xor %[1.2]"
				"jr z,$1"			| | |
zne | GEN_REG | 		remove(ALL) 	allocate(AREG)
				"ld a,%[1.1]"
				"xor %[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)
				"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},BC)
				"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		| |		allocate(ALL_REG)
				"call .nop"	| | |
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"      )
