%{
enum { BC, DE, HL };
#include "c.h"
#define NODEPTR_TYPE Node
#define OP_LABEL(p) ((p)->op)
#define LEFT_CHILD(p) ((p)->kids[0])
#define RIGHT_CHILD(p) ((p)->kids[1])
#define LEFT_X_CHILD(p) ((p)->x.kids[0])
#define RIGHT_X_CHILD(p) ((p)->x.kids[1])
#define STATE_LABEL(p) ((p)->x.state)
static void address		ARGS((Symbol, Symbol, int));
static void blkfetch	ARGS((int, int, int, int));
static void blkloop		ARGS((int, int, int, int, int, int[]));
static void blkstore	ARGS((int, int, int, int));
static void defaddress	ARGS((Symbol));
static void defconst	ARGS((int, Value));
static void defstring	ARGS((int, char *));
static void defsymbol	ARGS((Symbol));
static void doarg		ARGS((Node));
static void emit2		ARGS((Node));
static void export		ARGS((Symbol));
static void clobber		ARGS((Node));
static void function	ARGS((Symbol, Symbol [], Symbol [], int));
static void global		ARGS((Symbol));
static void import		ARGS((Symbol));
static void local		ARGS((Symbol));
static void space		ARGS((int));
static void offsetsp	ARGS((int));
static void offsethl	ARGS((int));
static void progend		ARGS((void));
static void segment		ARGS((int));
static void space		ARGS((int));
static void target		ARGS((Node));
static int ckstack		ARGS((Node, int));
static Symbol charreg[32], intreg[32];
static Symbol fltreg[32];
static char *hreg[] = { "B", "D", "H" };
static char *lreg[] = { "C", "E", "L" };

static int cseg;
static int argstack;

%}
%start stmt
%term ADDD=306 ADDF=305 ADDI=309 ADDP=311 ADDU=310
%term ADDRFP=279
%term ADDRGP=263
%term ADDRLP=295
%term ARGB=41 ARGD=34 ARGF=33 ARGI=37 ARGP=39
%term ASGNB=57 ASGNC=51 ASGND=50 ASGNF=49 ASGNI=53 ASGNP=55 ASGNS=52
%term BANDU=390
%term BCOMU=406
%term BORU=422
%term BXORU=438
%term CALLB=217 CALLD=210 CALLF=209 CALLI=213 CALLV=216
%term CNSTC=19 CNSTD=18 CNSTF=17 CNSTI=21 CNSTP=23 CNSTS=20 CNSTU=22
%term CVCI=85 CVCU=86
%term CVDF=97 CVDI=101
%term CVFD=114
%term CVIC=131 CVID=130 CVIS=132 CVIU=134
%term CVPU=150
%term CVSI=165 CVSU=166
%term CVUC=179 CVUI=181 CVUP=183 CVUS=180
%term DIVD=450 DIVF=449 DIVI=453 DIVU=454
%term EQD=482 EQF=481 EQI=485
%term GED=498 GEF=497 GEI=501 GEU=502
%term GTD=514 GTF=513 GTI=517 GTU=518
%term INDIRB=73 INDIRC=67 INDIRD=66 INDIRF=65 INDIRI=69 INDIRP=71 INDIRS=68
%term JUMPV=584
%term LABELV=600
%term LED=530 LEF=529 LEI=533 LEU=534
%term LOADB=233 LOADC=227 LOADD=226 LOADF=225 LOADI=229 LOADP=231 LOADS=228 LOADU=230
%term LSHI=341 LSHU=342
%term LTD=546 LTF=545 LTI=549 LTU=550
%term MODI=357 MODU=358
%term MULD=466 MULF=465 MULI=469 MULU=470
%term NED=562 NEF=561 NEI=565
%term NEGD=194 NEGF=193 NEGI=197
%term RETD=242 RETF=241 RETI=245
%term RSHI=373 RSHU=374
%term SUBD=322 SUBF=321 SUBI=325 SUBP=327 SUBU=326
%term VREGP=615
%%
reg:  INDIRC(VREGP)     "# read register\n"
reg:  INDIRD(VREGP)     "# read register\n"
reg:  INDIRF(VREGP)     "# read register\n"
reg:  INDIRI(VREGP)     "# read register\n"
reg:  INDIRP(VREGP)     "# read register\n"
reg:  INDIRS(VREGP)     "# read register\n"
stmt: ASGNC(VREGP,reg)  "# write register\n"
stmt: ASGND(VREGP,reg)  "# write register\n"
stmt: ASGNF(VREGP,reg)  "# write register\n"
stmt: ASGNI(VREGP,reg)  "# write register\n"
stmt: ASGNP(VREGP,reg)  "# write register\n"
stmt: ASGNS(VREGP,reg)  "# write register\n"
con: CNSTC  "%#%a"
con: CNSTI  "%#%a"
con: CNSTP  "%#%a"
con: CNSTS  "%#%a"
con: CNSTU  "%#%a"
stmt: reg  ""
reg: CVIU(reg)  "%0"  notarget(a)
reg: CVPU(reg)  "%0"  notarget(a)
reg: CVUI(reg)  "%0"  notarget(a)
reg: CVUP(reg)  "%0"  notarget(a)

acon: ADDRGP "%#%a"
acon: con    "%0"

stk: ADDRFP   "%a+%F(SP)"
stk: ADDRLP   "%a+%F(SP)"
reg: stk   "# \tLD\t%c,%0\n"  3
base: reg     "%0"
base: acon     "%0"
addr: base    "%0"

rc:   reg  "%0"
rc:   con  "%0"

reg:  INDIRC(addr)  "# \tLD\t%c,(%0)\n"  3
reg:  INDIRI(addr)  "# \tLD\t%c,(%0)\n"  3
reg:  INDIRP(addr)  "# \tLD\t%c,(%0)\n"  3
reg:  INDIRS(addr)  "# \tLD\t%c,(%0)\n"  3
reg:  INDIRC(stk)   "# \tLD\t%c,(%0)\n"  1
reg:  INDIRI(stk)   "# \tLD\t%c,(%0)\n"  1
reg:  INDIRP(stk)   "# \tLD\t%c,(%0)\n"  1
reg:  INDIRS(stk)   "# \tLD\t%c,(%0)\n"  1

reg: addr        "\tLD\t%c,%0\n"  1
reg: rc          "\tLD\t%c,%0\n"  1
reg: LOADC(reg)  "\tLD\t%c,%0\n"  move(a)
reg: LOADI(reg)  "# \tLD\t%c,%0\n"  move(a)
reg: LOADP(reg)  "# \tLD\t%c,%0\n"  move(a)
reg: LOADS(reg)  "# \tLD\t%c,%0\n"  move(a)
reg: LOADU(reg)  "# \tLD\t%c,%0\n"  move(a)
reg: ADDI(reg,rc)  "# ?\tLD\t%c,%0\n\tADD\t%c,%1\n"  1
reg: ADDP(reg,rc) "# ?\tLD\t%c,%0\n\tADD\t%c,%1\n"  1
reg: ADDU(reg,rc)  "# ?\tLD\t%c,%0\n\tADD\t%c,%1\n"  1
reg: SUBI(reg,rc)  "# ?\tLD\t%c,%0\n\tSUB\t%c,%1\n"  1
reg: SUBP(reg,rc) "# ?\tLD\t%c,%0\n\tSUB\t%c,%1\n"  1
reg: SUBU(reg,rc)  "# ?\tLD\t%c,%0\n\tSUB\t%c,%1\n"  1
reg: BANDU(reg,rc) "# ?\tLD\t%c,%0\n\tAND\t%c,%1\n"  1
reg: BORU(reg,rc)  "# ?\tLD\t%c,%0\n\tOR\t%c,%1\n"   1
reg: BXORU(reg,rc) "# ?\tLD\t%c,%0\n\tXOR\t%c,%1\n"  1
reg: BCOMU(reg)    "# ?\tLD\t%c,%0\n\tCOM\t%c,%1\n"  1
reg: NEGI(reg)     "# ?\tLD\t%c,%0\n\tNEG\t%c,%1\n"  1

rc8: CNSTI  "%a"  range(a, 0, 255)
rc8: reg    "%0"  5
reg: LSHI(reg,rc8)  "# ?\tLD\t%c,%0\n\tLSHI\t%c,%1\n"  2
reg: LSHU(reg,rc8)  "# ?\tLD\t%c,%0\n\tLSHU\t%c,%1\n"  2
reg: RSHI(reg,rc8)  "# ?\tLD\t%c,%0\n\tRSHI\t%c,%1\n"  2
reg: RSHU(reg,rc8)  "# ?\tLD\t%c,%0\n\tRSHU\t%c,%1\n"  2

reg: MULI(reg,reg)  "\tCALL\t.mul\n"  14
reg: MULU(reg,reg)  "\tCALL\t.mulu\n"  14
reg: DIVI(reg,reg)  "\tCALL\t.div\n"  14
reg: DIVU(reg,reg)  "\tCALL\t.divu\n"  14
reg: MODI(reg,reg)  "\tCALL\t.mod\n"  14
reg: MODU(reg,reg)  "\tCALL\t.modu\n"  14
reg: CVIU(reg)  "# \tLD\t%c,%0\n"  move(a)
reg: CVPU(reg)  "# \tLD\t%c,%0\n"  move(a)
reg: CVUI(reg)  "# \tLD\t%c,%0\n"  move(a)
reg: CVUP(reg)  "# \tLD\t%c,%0\n"  move(a)
reg: CVSI(reg)  "# \tLD\t%c,%0\n"  move(a)
reg: CVSU(reg)  "# \tLD\t%c,%0\n"  move(a)
reg: CVIS(reg)  "# \tLD\t%c,%0\n"  move(a)
reg: CVUS(reg)  "# \tLD\t%c,%0\n"  move(a)
reg: CVCI(reg)  "# extend\n"  3
reg: CVCU(reg)  "# extend\n"  3
reg: CVIC(reg)  "# truncate\n"  1
reg: CVUC(reg)  "# truncate\n"  1

rc5: con    "%0"  5
rc5: reg    "%0"

stmt: ASGNC(addr,rc)  "# \tLD\t(%0),%1\n"   3
stmt: ASGNI(addr,rc)  "# \tLD\t(%0),%1\n"   3
stmt: ASGNP(addr,rc)  "# \tLD\t(%0),%1\n"   3
stmt: ASGNS(addr,rc)  "# \tLD\t(%0),%1\n"   3
stmt: ASGNC(stk,rc5)  "# \tLD\t(%0),%1\n"   1
stmt: ASGNI(stk,rc5)  "# \tLD\t(%0),%1\n"   1
stmt: ASGNP(stk,rc5)  "# \tLD\t(%0),%1\n"   1
stmt: ASGNS(stk,rc5)  "# \tLD\t(%0),%1\n"   1
stmt: ARGI(reg)  "# \tPUSH\t%0\n"  1
stmt: ARGP(reg)  "# \tPUSH\t%0\n"  1
stmt: ASGNB(reg,INDIRB(reg))  "# ASGN struct\n"
stmt: ARGB(INDIRB(reg))       "# ARG struct\n"

reg: INDIRD(addr)     "# load double"
reg: INDIRF(addr)     "# load float"
stmt: ASGND(addr,reg) "# store double"
stmt: ASGNF(addr,reg) "# store float"
stmt: ARGD(reg)       "# double argument\n"
stmt: ARGF(reg)       "# float argument\n"
reg: NEGD(reg)        "# invert double\n"
reg: NEGF(reg)        "# invert float\n"
reg: ADDD(reg,flt)    "# add double\n"
reg: ADDF(reg,flt)    "# add float\n"
reg: DIVD(reg,flt)    "# div double\n"
reg: DIVF(reg,flt)    "# div float\n"
reg: MULD(reg,flt)    "# mul double\n"
reg: MULF(reg,flt)    "# mul float\n"
reg: SUBD(reg,flt)    "# sub double\n"
reg: SUBF(reg,flt)    "# sub float\n"
reg: CVFD(reg)        "# CVFD\n"
reg: CVDF(reg)        "# CVDF\n"
reg: CVID(reg)        "# CVID\n"
reg: CVDI(reg)        "# CVDI\n"

addrj: ADDRGP  "%a"
addrj: reg     "(%0)"  2

stmt:  JUMPV(addrj)  "\tJP\t%0\n"  3
stmt:  LABELV        "%a:\n"
stmt: EQI(reg,rc)  "# \tCP\t%0,%1\n\tJP\tZ,%a\n"   4
stmt: GEI(reg,rc)  "# \tCP\t%0,%1\n\tJP\tPZ,%a\n"  4
stmt: GTI(reg,rc)  "# \tCP\t%0,%1\n\tJP\tP,%a\n"   4
stmt: LEI(reg,rc)  "# \tCP\t%0,%1\n\tJP\tMZ,%a\n"  4
stmt: LTI(reg,rc)  "# \tCP\t%0,%1\n\tJP\tM,%a\n"   4
stmt: NEI(reg,rc)  "# \tCP\t%0,%1\n\tJP\tNZ,%a\n"  4
stmt: GEU(reg,rc)  "# \tCPU\t%0,%1\n\tJP\tPZ,%a\n"  4
stmt: GTU(reg,rc)  "# \tCPU\t%0,%1\n\tJP\tP,%a\n"   4
stmt: LEU(reg,rc)  "# \tCPU\t%0,%1\n\tJP\tMZ,%a\n"  4
stmt: LTU(reg,rc)  "# \tCPU\t%0,%1\n\tJP\tM,%a\n"   4

stmt: EQD(reg,reg) "# compare double eq\n"
stmt: GED(reg,reg) "# compare double ge\n"
stmt: GTD(reg,reg) "# compare double gt\n"
stmt: LED(reg,reg) "# compare double le\n"
stmt: LTD(reg,reg) "# compare double lt\n"
stmt: NED(reg,reg) "# compare double ne\n"

stmt: EQF(reg,reg) "# compare float eq\n"
stmt: GEF(reg,reg) "# compare float ge\n"
stmt: GTF(reg,reg) "# compare float gt\n"
stmt: LEF(reg,reg) "# compare float le\n"
stmt: LTF(reg,reg) "# compare float lt\n"
stmt: NEF(reg,reg) "# compare float ne\n"

reg:  CALLI(addrj)  "# \tCALL\t%0\n"
stmt: CALLV(addrj)  "# \tCALL\t%0\n"
reg: CALLF(addrj)   "# \tCALL\t%0\n"
reg: CALLD(addrj)   "# \tCALL\t%0\n"

stmt: RETI(reg)  "# ret\n"
stmt: RETF(reg)  "# ret\n"
stmt: RETD(reg)  "# ret\n"

%%

static void progbeg(argc, argv) int argc; char *argv[]; {
	int i;
	extern unsigned (*emitter) ARGS((Node, int));

	{
		union {
			char c;
			int i;
		} u;
		u.i = 0;
		u.c = 1;
		swap = (u.i == 1) != IR->little_endian;
	}
	parseflags(argc, argv);

	intreg[BC] = mkreg("BC", BC, 1, IREG);
	intreg[DE] = mkreg("DE", DE, 1, IREG);
	intreg[HL] = mkreg("HL", HL, 1, IREG);

	charreg[BC]	 = mkreg("C", BC, 1, IREG);
	charreg[DE]	 = mkreg("E", DE, 1, IREG);
	charreg[HL]	 = mkreg("L", HL, 1, IREG);

	for(i = 0; i < 8; i++)
		fltreg[i] = mkreg("%d", i, 0, FREG);

	rmap[C] = mkwildcard(charreg);
	rmap[S] = rmap[P] = rmap[B] = rmap[U] = rmap[I] = mkwildcard(intreg);
	rmap[F] = rmap[D] = mkwildcard(fltreg);
	tmask[IREG] = (1<<BC) | (1<<DE) | (1<<HL);
	vmask[IREG] = 0;
	tmask[FREG] = 0xFF;
	vmask[FREG] = 0;
	print("\t; File generated by lcc\n");
	print("\n");
	print("\t.globl\t.mul, .div, .mod, .mulu, .divu, .modu\n");
	print("\t.globl\t.lsl, .lsr, .asl, .asr\n");
	print("\n");
	cseg = 0;
	argstack = 0;
}

static void segment(n) int n; {
	if(n == cseg)
		return;
	if(cseg == CODE)
		print("\t; _CODE ends\n");
	else if(cseg == LIT)
		print("\t; _LIT ends\n");
	else if(cseg == DATA)
		print("\t; _DATA ends\n");
	else if(cseg == BSS)
		print("\t; _BSS ends\n");
	cseg = n;
	if(cseg == CODE)
		print("\t.area\t_CODE\n");
	else if(cseg == LIT)
		print("\t.area\t_LIT\n");
	else if(cseg == DATA)
		print("\t.area\t_DATA\n");
	else if(cseg == BSS)
		print("\t.area\t_BSS\n");
}

static void progend() {
	segment(0);
	print("\t; End of program\n");
}

#define HARDWARE_REG_STR "__reg_"
#define HARDWARE_REG_LEN 6
#define HARDWARE_REG(addr) (!strncmp(addr, HARDWARE_REG_STR, HARDWARE_REG_LEN))

#define REG(p)  (getregnum(p))
#define LEFT_CHILD_REG(p)  (REG(LEFT_CHILD(p)))
#define RIGHT_CHILD_REG(p)  (REG(RIGHT_CHILD(p)))
#define LEFT_X_CHILD_REG(p)  (REG(LEFT_X_CHILD(p)))
#define RIGHT_X_CHILD_REG(p)  (REG(RIGHT_X_CHILD(p)))

#define RIGHT_REG(p) \
	(p->kids[1]->x.registered ? RIGHT_CHILD_REG(p) : \
	(p->x.kids[1] ? RIGHT_X_CHILD_REG(p) : LEFT_X_CHILD_REG(p)))
#define RIGHT_CONST(p) \
	(!p->kids[1]->x.registered \
	&& (generic(p->kids[1]->op) == CNST \
	|| (generic(p->kids[1]->op) == INDIR \
	&& p->kids[1]->kids[0]->op == VREG+P \
	&& p->kids[1]->syms[RX]->u.t.cse \
	&& generic(p->kids[1]->syms[RX]->u.t.cse->op) == CNST)))
#define RIGHT_ADDRGP(p) \
	(!p->kids[1]->x.registered \
	&& (p->kids[1]->op == ADDRGP \
	|| (generic(p->kids[1]->op) == INDIR \
	&& p->kids[1]->kids[0]->op == VREG+P \
	&& p->kids[1]->syms[RX]->u.t.cse \
	&& p->kids[1]->syms[RX]->u.t.cse->op == ADDRGP)))
#define RIGHT_VAL(p) \
	((generic(p->kids[1]->op) == CNST \
	|| p->kids[1]->op == ADDRGP) ? \
	p->kids[1]->syms[0]->x.name : \
	p->kids[1]->syms[RX]->u.t.cse->syms[0]->x.name);
#define LEFT_CONST(p) \
	(!p->kids[0]->x.registered \
	&& (generic(p->kids[0]->op) == CNST \
	|| (generic(p->kids[0]->op) == INDIR \
	&& p->kids[0]->kids[0]->op == VREG+P \
	&& p->kids[0]->syms[RX]->u.t.cse \
	&& generic(p->kids[0]->syms[RX]->u.t.cse->op) == CNST)))
#define LEFT_ADDRGP(p) \
	(!p->kids[0]->x.registered \
	&& (p->kids[0]->op == ADDRGP \
	|| (generic(p->kids[0]->op) == INDIR \
	&& p->kids[0]->kids[0]->op == VREG+P \
	&& p->kids[0]->syms[RX]->u.t.cse \
	&& p->kids[0]->syms[RX]->u.t.cse->op == ADDRGP)))
#define LEFT_VAL(p) \
	((generic(p->kids[0]->op) == CNST \
	|| p->kids[0]->op == ADDRGP) ? \
	p->kids[0]->syms[0]->x.name : \
	p->kids[0]->syms[RX]->u.t.cse->syms[0]->x.name);

static void target(p) Node p; {
	assert(p);
	switch (p->op) {

		case CALLI: case CALLV:
			setreg(p, intreg[HL]);
			break;
		case RETI:
			/* Return value in HL */
			rtarget(p, 0, intreg[HL]);
			break;
		case JUMPV:
			if(!LEFT_CONST(p))
				rtarget(p, 0, intreg[HL]);
			break;
		case MULI:
		case MULU:
			setreg(p, intreg[HL]);
			rtarget(p, 0, intreg[DE]);
			rtarget(p, 1, intreg[HL]);
			break;
		case DIVI:
		case DIVU:
			setreg(p, intreg[DE]);
			rtarget(p, 0, intreg[DE]);
			rtarget(p, 1, intreg[BC]);
			break;
		case MODI:
		case MODU:
			setreg(p, intreg[BC]);
			rtarget(p, 0, intreg[DE]);
			rtarget(p, 1, intreg[BC]);
			break;
		case LSHI: case RSHI:
		case LSHU: case RSHU:
			if(!RIGHT_CONST(p)) {
				setreg(p, intreg[HL]);
				rtarget(p, 0, intreg[HL]);
				rtarget(p, 1, intreg[DE]);
			}
			break;
	}
}

static void clobber(p) Node p; {
	static int nstack = 0;

	assert(p);

	nstack = ckstack(p, nstack);
	assert(p->count > 0 || nstack == 0);

	switch (p->op) {
	}
}

static void emit2(p) Node p; {
/*
	switch(p->op) {
		default: {
			int i, j;

			print("%s\n", opname(p->op));
			print("#%d %s (%x)\n", p->x.inst, opname(p->op), (char *)p);
			for(i = 0; i < NELEMS(p->kids) && p->kids[i]; i++) {
				print(" kids[%d]: #%d %s (%x)\n", i, p->kids[i]->x.inst, opname(p->kids[i]->op), (char *)p->kids[i]);
				for(j = 0; j < 3; j++) {
					if(p->kids[i]->syms[j] && p->kids[i]->syms[j]->x.name)
						print("  syms[%d]: %s\n", j, p->kids[i]->syms[j]->x.name);
				}
			}
			for(i = 0; i < NELEMS(p->x.kids) && p->x.kids[i]; i++) {
				print(" x.kids[%d]: #%d %s (%x)\n", i, p->x.kids[i]->x.inst, opname(p->x.kids[i]->op), (char *)p->x.kids[i]);
				for(j = 0; j < 3; j++) {
					if(p->x.kids[i]->syms[j] && p->x.kids[i]->syms[j]->x.name)
						print("  syms[%d]: %s\n", j, p->x.kids[i]->syms[j]->x.name);
				}
			}
			for(i = 0; i < 3; i++) {
				if(p->syms[i] && p->syms[i]->x.name)
					print(" syms[%d]: %s\n", i, p->syms[i]->x.name);
			}
			print("\n", opname(p->op));
			outflush();
			break;
		}
	}
*/
	switch(p->op) {
		case INDIRC:
		if(p->kids[0]->op == VREG+P)
			break;
		{
			int dreg = REG(p);
			char *dst;

			if(p->kids[0]->op == ADDRFP || p->kids[0]->op == ADDRLP) {
				int offset = atoi(p->kids[0]->syms[0]->x.name);

				dst = lreg[dreg];
				print("\n\t; Load %s\n", dst);

				if(dreg != HL)
					print("\tPUSH\t%s\n", "HL");
				offsethl(offset + framesize + argstack + (dreg != HL ? 2 : 0));
				print("\tLD\t%s,(%s)\n", "A", "HL");
				if(dreg != HL)
					print("\tPOP\t%s\n", "HL");
				print("\tLD\t%s,%s\n", dst, "A");
			} else if(LEFT_CONST(p) || LEFT_ADDRGP(p)) {
				char *addr = LEFT_VAL(p);

				dst = lreg[dreg];
				print("\n\t; Load %s\n", dst);

				if(HARDWARE_REG(addr))
					print("\tLDH\t%s,(%s)\n", "A", addr + HARDWARE_REG_LEN);
				else
					print("\tLD\t%s,(%s)\n", "A", addr);
				print("\tLD\t%s,%s\n", dst, "A");
			} else {
				int sreg = LEFT_X_CHILD_REG(p);
				char *src = intreg[sreg]->x.name;

				dst = lreg[dreg];
				print("\n\t; Load %s\n", dst);

				if(sreg == HL) {
					print("\tLD\t%s,(%s)\n", dst, src);
				} else {
					print("\tLD\t%s,(%s)\n", "A", src);
					print("\tLD\t%s,%s\n", dst, "A");
				}
			}
			print("\n");
			break;
		}
		case INDIRS:
		case INDIRI:
		case INDIRP:
		if(p->kids[0]->op == VREG+P)
			break;
		{
			int dreg = REG(p);
			char *dst = intreg[dreg]->x.name;

			print("\n\t; Load register %s\n", dst);
			if(p->kids[0]->op == ADDRFP || p->kids[0]->op == ADDRLP) {
				int offset = atoi(p->kids[0]->syms[0]->x.name) + framesize;

				if(dreg != HL) {
					print("\tPUSH\t%s\n", "HL");
					offsethl(offset + argstack + 2);
					print("\tLD\t%s,(HL)\n", lreg[dreg]);
					print("\tINC\t%s\n", "HL");
					print("\tLD\t%s,(HL)\n", hreg[dreg]);
					print("\tPOP\t%s\n", "HL");
				} else {
					offsethl(offset + argstack);
					print("\tLD\t%s,(HL+)\n", "A");
					print("\tLD\t%s,(HL)\n", hreg[dreg]);
					print("\tLD\t%s,%s\n", lreg[dreg], "A");
				}
/*
				offsetsp(offset + argstack);
				print("\tPOP\t%s\n", dst);
				offsetsp(-(offset + argstack + 2));
*/
			} else if(LEFT_CONST(p) || LEFT_ADDRGP(p)) {
				char *addr = LEFT_VAL(p);

				print("\n\t; Load %s\n", dst);

				if(HARDWARE_REG(addr))
					print("\tLDH\t%s,(%s+1)\n", "A", addr + HARDWARE_REG_LEN);
				else
					print("\tLD\t%s,(%s+1)\n", "A", addr);
				print("\tLD\t%s,%s\n", hreg[dreg], "A");
				if(HARDWARE_REG(addr))
					print("\tLDH\t%s,(%s)\n", "A", addr + HARDWARE_REG_LEN);
				else
					print("\tLD\t%s,(%s)\n", "A", addr);
				print("\tLD\t%s,%s\n", lreg[dreg], "A");
			} else {
				int sreg = LEFT_X_CHILD_REG(p);
				char *src = intreg[sreg]->x.name;

				if(sreg == HL) {
					print("\tINC\t%s\n", src);
					if(dreg == sreg)
						print("\tLD\t%s,(%s)\n", "A", src);
					else
						print("\tLD\t%s,(%s)\n", hreg[dreg], src);
					print("\tDEC\t%s\n", src);
					print("\tLD\t%s,(%s)\n", lreg[dreg], src);
					if(dreg == sreg)
						print("\tLD\t%s,%s\n", hreg[dreg], "A");
				} else {
					print("\tINC\t%s\n", src);
					print("\tLD\t%s,(%s)\n", "A", src);
					if(dreg == sreg)
						print("\tPUSH\t%s\n", "AF");
					else
						print("\tLD\t%s,%s\n", hreg[dreg], "A");
					print("\tDEC\t%s\n", src);
					print("\tLD\t%s,(%s)\n", "A", src);
					print("\tLD\t%s,%s\n", lreg[dreg], "A");
					if(dreg == sreg) {
						print("\tPOP\t%s\n", "AF");
						print("\tLD\t%s,%s\n", hreg[dreg], "A");
					}
				}
			}
			print("\n");
			break;
		}
		case ASGNC:
		if(p->kids[0]->op == VREG+P)
			break;
		{
			char *src;

			if(p->kids[0]->op == ADDRFP || p->kids[0]->op == ADDRLP) {
				int offset = atoi(p->kids[0]->syms[0]->x.name);

				if(RIGHT_CONST(p)) {
					char *val = RIGHT_VAL(p);

					print("\n\t; Store %s\n", val);
					print("\tLD\t%s,#%s\n", "A", val);
				} else {
					src = lreg[LEFT_X_CHILD_REG(p)];
					print("\n\t; Store %s\n", src);
					print("\tLD\t%s,%s\n", "A", src);
				}
				print("\tPUSH\t%s\n", "HL");
				offsethl(offset + framesize + argstack + 2);
				print("\tLD\t(%s),%s\n", "HL", "A");
				print("\tPOP\t%s\n", "HL");
			} else if(LEFT_CONST(p) || LEFT_ADDRGP(p)) {
				char *addr = LEFT_VAL(p);

				if(RIGHT_CONST(p)) {
					char *val = RIGHT_VAL(p);

					print("\n\t; Store %s\n", val);
					print("\tLD\t%s,#%s\n", "A", val);
				} else {
					src = lreg[LEFT_X_CHILD_REG(p)];
					print("\n\t; Store %s\n", src);
					print("\tLD\t%s,%s\n", "A", src);
				}
				if(HARDWARE_REG(addr))
					print("\tLDH\t(%s),%s\n", addr + HARDWARE_REG_LEN, "A");
				else
					print("\tLD\t(%s),%s\n", addr, "A");
			} else {
				int dreg = LEFT_X_CHILD_REG(p);
				char *dst = intreg[dreg]->x.name;

				if(RIGHT_CONST(p)) {
					char *val = RIGHT_VAL(p);

					print("\n\t; Store %s\n", val);
					if(dreg == HL)
						print("\tLD\t(%s),#%s\n", dst, val);
					else {
						print("\tLD\t%s,#%s\n", "A", val);
						print("\tLD\t(%s),%s\n", dst, "A");
					}
				} else {
					src = lreg[RIGHT_REG(p)];

					print("\n\t; Store %s\n", src);
					if(dreg == HL)
						print("\tLD\t(%s),%s\n", dst, src);
					else {
						print("\tLD\t%s,%s\n", "A", src);
						print("\tLD\t(%s),%s\n", dst, "A");
					}
				}
			}
			print("\n");
			break;
		}
		case ASGNS:
		case ASGNI:
		case ASGNP:
		if(p->kids[0]->op == VREG+P)
			break;
		{
			char *src;

			if(p->kids[0]->op == ADDRFP || p->kids[0]->op == ADDRLP) {
				int offset = atoi(p->kids[0]->syms[0]->x.name) + framesize;

				if(RIGHT_CONST(p)) {
					char *val = RIGHT_VAL(p);

					print("\n\t; Store %s\n", val);

					print("\tPUSH\t%s\n", "HL");
					offsethl(offset + argstack + 2);
					print("\tLD\t(HL),#<%d\n", val);
					print("\tINC\t%s\n", "HL");
					print("\tLD\t(HL),#>%d\n", val);
					print("\tPOP\t%s\n", "HL");
/*
					char *val = RIGHT_VAL(p);

					print("\n\t; Store %s\n", val);
					print("\tPUSH\t%s\n", "BC");
					print("\tLD\t%s,#%s\n", "BC", val);
					offsetsp(offset + argstack + 2 + 2);
					print("\tPUSH\t%s\n", "BC");
					offsetsp(-(offset + argstack + 2));
*/
					print("\tPOP\t%s\n", "BC");
				} else {
					int sreg = RIGHT_REG(p);
					src = intreg[sreg]->x.name;

					print("\n\t; Store %s\n", src);

					if(sreg != HL) {
						print("\tPUSH\t%s\n", "HL");
						offsethl(offset + argstack + 2);
						print("\tLD\t(HL),%s\n", lreg[sreg]);
						print("\tINC\t%s\n", "HL");
						print("\tLD\t(HL),%s\n", hreg[sreg]);
						print("\tPOP\t%s\n", "HL");
					} else {
						print("\tPUSH\t%s\n", "BC");
						print("\tLD\t%s,%s\n", "A", lreg[sreg]);
						print("\tLD\t%s,%s\n", "B", hreg[sreg]);
						offsethl(offset + argstack + 2);
						print("\tLD\t(HL+),%s\n", "A");
						print("\tLD\t(HL),%s\n", "B");
						print("\tLD\t%s,%s\n", lreg[sreg], "A");
						print("\tLD\t%s,%s\n", hreg[sreg], "B");
						print("\tPOP\t%s\n", "BC");
					}
/*
					offsetsp(offset + argstack + 2);
					print("\tPUSH\t%s\n", src);
					offsetsp(-(offset + argstack));
*/
				}
			} else if(LEFT_CONST(p) || LEFT_ADDRGP(p)) {
				char *addr = LEFT_VAL(p);

				if(RIGHT_CONST(p)) {
					char *val = RIGHT_VAL(p);

					print("\n\t; Store %s\n", val);

					print("\tLD\t%s,#>%s\n", "A", val);
					if(HARDWARE_REG(addr))
						print("\tLDH\t(%s+1),%s\n", addr + HARDWARE_REG_LEN, "A");
					else
						print("\tLD\t(%s+1),%s\n", addr, "A");
					print("\tLD\t%s,#<%s\n", "A", val);
					if(HARDWARE_REG(addr))
						print("\tLDH\t(%s),%s\n", addr + HARDWARE_REG_LEN, "A");
					else
						print("\tLD\t(%s),%s\n", addr, "A");
				} else {
					int sreg = RIGHT_REG(p);
					src = intreg[sreg]->x.name;

					print("\n\t; Store %s\n", src);
					print("\tLD\t%s,%s\n", "A", hreg[sreg]);
					if(HARDWARE_REG(addr))
						print("\tLDH\t(%s+1),%s\n", addr + HARDWARE_REG_LEN, "A");
					else
						print("\tLD\t(%s+1),%s\n", addr, "A");
					print("\tLD\t%s,%s\n", "A", lreg[sreg]);
					if(HARDWARE_REG(addr))
						print("\tLDH\t(%s),%s\n", addr + HARDWARE_REG_LEN, "A");
					else
						print("\tLD\t(%s),%s\n", addr, "A");
				}
			} else {
				int dreg = LEFT_X_CHILD_REG(p);
				char *dst = intreg[dreg]->x.name;

				if(RIGHT_CONST(p)) {
					char *val = RIGHT_VAL(p);

					print("\n\t; Store %s\n", val);

					print("\tINC\t%s\n", dst);
					print("\tLD\t%s,#>%s\n", "A", val);
					print("\tLD\t(%s),%s\n", dst, "A");
					print("\tDEC\t%s\n", dst);
					print("\tLD\t%s,#<%s\n", "A", val);
					print("\tLD\t(%s),%s\n", dst, "A");
				} else {
					int sreg = RIGHT_REG(p);

					assert(dreg != sreg);

					print("\n\t; Store %s\n", intreg[sreg]->x.name);
					if(dreg == HL) {
						print("\tINC\t%s\n", dst);
						print("\tLD\t(%s),%s\n", dst, hreg[sreg]);
						print("\tDEC\t%s\n", dst);
						print("\tLD\t(%s),%s\n", dst, lreg[sreg]);
					} else {
						print("\tINC\t%s\n", dst);
						print("\tLD\t%s,%s\n", "A", hreg[sreg]);
						print("\tLD\t(%s),%s\n", dst, "A");
						print("\tDEC\t%s\n", dst);
						print("\tLD\t%s,%s\n", "A", lreg[sreg]);
						print("\tLD\t(%s),%s\n", dst, "A");
					}
				}
			}
			print("\n");
			break;
		}
		case CALLI:
		case CALLV:
		case CALLF:
		case CALLD: {

			int i = atoi(p->syms[0]->x.name);

			print("\tCALL\t%s\n", p->kids[0]->syms[0]->x.name);
			if(i) {
				print("\tLDA\tSP,%d(SP)\n", i);
				argstack -= i;
			}
			break;
		}
		case ASGNB: {
			int sreg = RIGHT_X_CHILD_REG(p);
			char *src = intreg[sreg]->x.name;
			int dreg = LEFT_X_CHILD_REG(p);
			char *dst = intreg[dreg]->x.name;
			int size = p->syms[0]->u.c.v.i;
			int treg;
			char *tmp;

			print("\n\t; Assign structure from %s to %s\n", src, dst);

			if(size > 4) {
				treg = (sreg != BC && dreg != BC ? BC : (sreg != DE && dreg != DE ? DE : HL));
				tmp = intreg[treg]->x.name;

				print("\tPUSH\t%s\n", tmp);
				while(size > 0) {
					int lab = genlabel(1);
					print("\tLD\t%s,#%d\n", lreg[treg], size > 0xFF ? 0x00 : size);
					size -= 0x100;
					print(".L%d:\n", lab);
					print("\tLD\tA,(%s)\n", sreg == HL ? "HL+" : src);
					print("\tLD\t(%s),A\n", dreg == HL ? "HL+" : dst);
					if(sreg != HL)
						print("\tINC\t%s\n", src);
					if(dreg != HL)
						print("\tINC\t%s\n", dst);
					print("\tDEC\t%s\n", lreg[treg]);
					print("\tJR\tNZ,.L%d\n", lab);
				}
				print("\tPOP\t%s\n", tmp);
			} else {
				while(size--) {
					print("\tLD\tA,(%s)\n", sreg == HL ? "HL+" : src);
					print("\tLD\t(%s),A\n", dreg == HL ? "HL+" : dst);
					if(sreg != HL)
						print("\tINC\t%s\n", src);
					if(dreg != HL)
						print("\tINC\t%s\n", dst);
				}
			}
			print("\n");
			break;
		}
		case ARGB: {
			int lab = genlabel(1);
			int sreg = LEFT_X_CHILD_REG(p);
			char *src = intreg[sreg]->x.name;
			int size = p->syms[0]->u.c.v.i;

			argstack += size;

			print("\n\t; Pass structure parameter from %s\n", src);
			if(sreg != HL) {
				int treg = (sreg == BC ? DE : BC);
				char *tmp = intreg[treg]->x.name;

				offsetsp(-size);
				print("\tPUSH\tHL\n");
				print("\tPUSH\t%s\n", tmp);
				print("\tLDA\tHL,4(SP)\n");
				while(size > 0) {
					int lab = genlabel(1);
					print("\tLD\t%s,#%d\n", lreg[treg], size > 0xFF ? 0x00 : size);
					size -= 0x100;
					print(".L%d:\n", lab);
					print("\tLD\tA,(%s)\n", src);
					print("\tLD\t(HL+),A\n");
					print("\tINC\t%s\n", src);
					print("\tDEC\t%s\n", lreg[treg]);
					print("\tJR\tNZ,.L%d\n", lab);
				}
				print("\tPOP\t%s\n", tmp);
				print("\tPOP\tHL\n");
			} else {
				offsetsp(-size);
				print("\tPUSH\tBC\n");
				print("\tPUSH\tDE\n");
				print("\tLD\tB,H\n");
				print("\tLD\tC,L\n");
				print("\tLDA\tHL,4(SP)\n");
				while(size > 0) {
					int lab = genlabel(1);
					print("\tLD\t%s,#%d\n", "E", size > 0xFF ? 0x00 : size);
					size -= 0x100;
					print(".L%d:\n", lab);
					print("\tLD\tA,(%s)\n", "BC");
					print("\tLD\t(HL+),A\n");
					print("\tINC\t%s\n", "BC");
					print("\tDEC\t%s\n", "E");
					print("\tJR\tNZ,.L%d\n", lab);
				}
				print("\tPOP\tDE\n");
				print("\tPOP\tBC\n");
			}
			print("\n");
			break;
		}
		case ARGI:
		case ARGP: {
			int sreg = LEFT_X_CHILD_REG(p);
			char *src = intreg[sreg]->x.name;

			argstack += 2;

			print("\n\t; Integer (or pointer) argument\n");
			print("\tPUSH\t%s\n", src);
			break;
		}
		case CVCU: {
			int dreg = REG(p);
			int sreg = LEFT_X_CHILD_REG(p);

			print("\n\t; Convert char to unsigned\n");
			print("\tLD\t%s,#0\n", hreg[dreg]);
			if(dreg != sreg)
				print("\tLD\t%s,%s\n", lreg[dreg], lreg[sreg]);
			print("\n");
			break;
		}
		case CVCI: {
			int dreg = REG(p);
			int sreg = LEFT_X_CHILD_REG(p);

			print("\n\t; Convert char to int\n");
			print("\tLD\tA,%s\n", lreg[sreg]);
			if(dreg != sreg)
				print("\tLD\t%s,A\n", lreg[dreg]);
			print("\tRLCA\n");
			print("\tSBC\tA\n");
			print("\tLD\t%s,A\n", hreg[dreg]);
			print("\n");
			break;
		}
		case CVIC:
		case CVUC: {
			int dreg = REG(p);
			int sreg = LEFT_X_CHILD_REG(p);

			if(dreg != sreg)
				print("\tLD\t%s,%s\n", lreg[dreg], lreg[sreg]);
			break;
		}
		case CVIU:
		case CVPU:
		case CVUI:
		case CVUP:
		case CVIS:
		case CVUS:
		case CVSI:
		case CVSU:

		case LOADI:
		case LOADP:
		case LOADS:
		case LOADU: {
			int dreg = REG(p);
			int sreg = LEFT_X_CHILD_REG(p);

			if(dreg != sreg) {
				print("\tLD\t%s,%s\n", hreg[dreg], hreg[sreg]);
				print("\tLD\t%s,%s\n", lreg[dreg], lreg[sreg]);
			}
			break;
		}
		case ADDRFP:
		case ADDRLP: {
			int dreg = REG(p);
			char *dst = intreg[dreg]->x.name;
			int offset = atoi(p->syms[0]->x.name);

			print("\n\t; Load local address into %s\n", dst);
			if(dreg == HL)
				offsethl(offset + framesize + argstack);
			else {
				print("\tPUSH\t%s\n", "HL");
				offsethl(offset + framesize + argstack + 2);
				print("\tLD\t%s,%s\n", hreg[dreg], "H");
				print("\tLD\t%s,%s\n", lreg[dreg], "L");
				print("\tPOP\t%s\n", "HL");
			}
			print("\n");
			break;
		}
		case ADDI: case ADDP: case ADDU: {
			int dreg = REG(p);
			char *dst = intreg[dreg]->x.name;
			int sreg1 = LEFT_X_CHILD_REG(p);
			char *src1 = intreg[sreg1]->x.name;

			if(RIGHT_CONST(p)) {
				int n;
				char *val = RIGHT_VAL(p);

				print("\n\t; Add %s to %s into %s\n", val, src1, dst);

				n = atoi(val);
				if(n == 1) {
					if(sreg1 != dreg) {
						print("\tLD\t%s,%s\n", hreg[dreg], hreg[sreg1]);
						print("\tLD\t%s,%s\n", lreg[dreg], lreg[sreg1]);
					}
					print("\tINC\t%s\n", dst);
				} else if(n == -1) {
					if(sreg1 != dreg) {
						print("\tLD\t%s,%s\n", hreg[dreg], hreg[sreg1]);
						print("\tLD\t%s,%s\n", lreg[dreg], lreg[sreg1]);
					}
					print("\tDEC\t%s\n", dst);
				} else {
					print("\tLD\t%s,%s\n", "A", lreg[sreg1]);
					print("\tADD\t#<%s\n", val);
					print("\tLD\t%s,%s\n", lreg[dreg], "A");
					print("\tLD\t%s,%s\n", "A", hreg[sreg1]);
					print("\tADC\t#>%s\n", val);
					print("\tLD\t%s,%s\n", hreg[dreg], "A");
				}
			} else {
				int sreg2 = RIGHT_REG(p);
				char *src2 = intreg[sreg2]->x.name;
				
				print("\n\t; Add %s to %s into %s\n", src2, src1, dst);

				if(dreg == HL) {
					if(sreg1 == dreg)
						print("\tADD\t%s,%s\n", dst, src2);
					else if(sreg2 == dreg)
						print("\tADD\t%s,%s\n", dst, src1);
					else {
						print("\tLD\t%s,%s\n", hreg[dreg], hreg[sreg1]);
						print("\tLD\t%s,%s\n", lreg[dreg], lreg[sreg1]);
						print("\tADD\t%s,%s\n", dst, src2);
					}
				} else {
					print("\tLD\t%s,%s\n", "A", lreg[sreg1]);
					print("\tADD\t%s\n", lreg[sreg2]);
					print("\tLD\t%s,%s\n", lreg[dreg], "A");
					print("\tLD\t%s,%s\n", "A", hreg[sreg1]);
					print("\tADC\t%s\n", hreg[sreg2]);
					print("\tLD\t%s,%s\n", hreg[dreg], "A");
				}
			}
			print("\n");
			break;
		}
		case SUBI: case SUBP: case SUBU: {
			int dreg = REG(p);
			char *dst = intreg[dreg]->x.name;
			int sreg1 = LEFT_X_CHILD_REG(p);
			char *src1 = intreg[sreg1]->x.name;

			if(RIGHT_CONST(p)) {
				int n;
				char *val = RIGHT_VAL(p);

				print("\n\t; Substract %s from %s into %s\n", val, src1, dst);

				n = atoi(val);
				if(n == 1) {
					if(sreg1 != dreg) {
						print("\tLD\t%s,%s\n", hreg[dreg], hreg[sreg1]);
						print("\tLD\t%s,%s\n", lreg[dreg], lreg[sreg1]);
					}
					print("\tDEC\t%s\n", dst);
				} else if(n == -1) {
					if(sreg1 != dreg) {
						print("\tLD\t%s,%s\n", hreg[dreg], hreg[sreg1]);
						print("\tLD\t%s,%s\n", lreg[dreg], lreg[sreg1]);
					}
					print("\tINC\t%s\n", dst);
				} else {
					print("\tLD\t%s,%s\n", "A", lreg[sreg1]);
					print("\tSUB\t#<%s\n", val);
					print("\tLD\t%s,%s\n", lreg[dreg], "A");
					print("\tLD\t%s,%s\n", "A", hreg[sreg1]);
					print("\tSBC\t#>%s\n", val);
					print("\tLD\t%s,%s\n", hreg[dreg], "A");
				}
			} else {
				int sreg2 = RIGHT_REG(p);
				char *src2 = intreg[sreg2]->x.name;
				
				print("\n\t; Substract %s from %s into %s\n", src2, src1, dst);

				print("\tLD\t%s,%s\n", "A", lreg[sreg1]);
				print("\tSUB\t%s\n", lreg[sreg2]);
				print("\tLD\t%s,%s\n", lreg[dreg], "A");
				print("\tLD\t%s,%s\n", "A", hreg[sreg1]);
				print("\tSBC\t%s\n", hreg[sreg2]);
				print("\tLD\t%s,%s\n", hreg[dreg], "A");
			}
			print("\n");
			break;
		}
		case BANDU: {
			int dreg = REG(p);
			char *dst = intreg[dreg]->x.name;
			int sreg1 = LEFT_X_CHILD_REG(p);
			char *src1 = intreg[sreg1]->x.name;

			if(RIGHT_CONST(p)) {
				char *val = RIGHT_VAL(p);

				print("\n\t; And %s and %s into %s\n", src1, val, dst);

				print("\tLD\t%s,%s\n", "A", lreg[sreg1]);
				print("\tAND\t#<%s\n", val);
				print("\tLD\t%s,%s\n", lreg[dreg], "A");
				print("\tLD\t%s,%s\n", "A", hreg[sreg1]);
				print("\tAND\t#>%s\n", val);
				print("\tLD\t%s,%s\n", hreg[dreg], "A");
			} else {
				int sreg2 = RIGHT_REG(p);
				char *src2 = intreg[sreg2]->x.name;
				
				print("\n\t; And %s and %s into %s\n", src1, src2, dst);

				print("\tLD\t%s,%s\n", "A", lreg[sreg1]);
				print("\tAND\t%s\n", lreg[sreg2]);
				print("\tLD\t%s,%s\n", lreg[dreg], "A");
				print("\tLD\t%s,%s\n", "A", hreg[sreg1]);
				print("\tAND\t%s\n", hreg[sreg2]);
				print("\tLD\t%s,%s\n", hreg[dreg], "A");
			}
			print("\n");
			break;
		}
		case BORU: {
			int dreg = REG(p);
			char *dst = intreg[dreg]->x.name;
			int sreg1 = LEFT_X_CHILD_REG(p);
			char *src1 = intreg[sreg1]->x.name;

			if(RIGHT_CONST(p)) {
				char *val = RIGHT_VAL(p);

				print("\n\t; Or %s and %s into %s\n", src1, val, dst);

				print("\tLD\t%s,%s\n", "A", lreg[sreg1]);
				print("\tOR\t#<%s\n", val);
				print("\tLD\t%s,%s\n", lreg[dreg], "A");
				print("\tLD\t%s,%s\n", "A", hreg[sreg1]);
				print("\tOR\t#>%s\n", val);
				print("\tLD\t%s,%s\n", hreg[dreg], "A");
			} else {
				int sreg2 = RIGHT_REG(p);
				char *src2 = intreg[sreg2]->x.name;
				
				print("\n\t; Or %s and %s into %s\n", src1, src2, dst);

				print("\tLD\t%s,%s\n", "A", lreg[sreg1]);
				print("\tOR\t%s\n", lreg[sreg2]);
				print("\tLD\t%s,%s\n", lreg[dreg], "A");
				print("\tLD\t%s,%s\n", "A", hreg[sreg1]);
				print("\tOR\t%s\n", hreg[sreg2]);
				print("\tLD\t%s,%s\n", hreg[dreg], "A");
			}
			print("\n");
			break;
		}
		case BXORU: {
			int dreg = REG(p);
			char *dst = intreg[dreg]->x.name;
			int sreg1 = LEFT_X_CHILD_REG(p);
			char *src1 = intreg[sreg1]->x.name;

			if(RIGHT_CONST(p)) {
				char *val = RIGHT_VAL(p);

				print("\n\t; Xor %s and %s into %s\n", src1, val, dst);

				print("\tLD\t%s,%s\n", "A", lreg[sreg1]);
				print("\tXOR\t#<%s\n", val);
				print("\tLD\t%s,%s\n", lreg[dreg], "A");
				print("\tLD\t%s,%s\n", "A", hreg[sreg1]);
				print("\tXOR\t#>%s\n", val);
				print("\tLD\t%s,%s\n", hreg[dreg], "A");
			} else {
				int sreg2 = RIGHT_REG(p);
				char *src2 = intreg[sreg2]->x.name;
				
				print("\n\t; Xor %s and %s into %s\n", src1, src2, dst);

				print("\tLD\t%s,%s\n", "A", lreg[sreg1]);
				print("\tXOR\t%s\n", lreg[sreg2]);
				print("\tLD\t%s,%s\n", lreg[dreg], "A");
				print("\tLD\t%s,%s\n", "A", hreg[sreg1]);
				print("\tXOR\t%s\n", hreg[sreg2]);
				print("\tLD\t%s,%s\n", hreg[dreg], "A");
			}
			print("\n");
			break;
		}
		case BCOMU: {
			int dreg = REG(p);
			int sreg = LEFT_X_CHILD_REG(p);

			print("\n\t; Complement %s into %s\n", intreg[sreg]->x.name,
				 intreg[dreg]->x.name);
			print("\tLD\t%s,%s\n", "A", lreg[sreg]);
			print("\tCPL\n");
			print("\tLD\t%s,%s\n", lreg[dreg], "A");
			print("\tLD\t%s,%s\n", "A", hreg[sreg]);
			print("\tCPL\n");
			print("\tLD\t%s,%s\n", hreg[dreg], "A");
			print("\n");
			break;
		}
		case NEGI: {
			int dreg = REG(p);
			char *dst = intreg[dreg]->x.name;
			int sreg = LEFT_X_CHILD_REG(p);

			print("\n\t; Negate %s into %s\n", intreg[sreg]->x.name,
				 intreg[dreg]->x.name);
			print("\tLD\t%s,%s\n", "A", lreg[sreg]);
			print("\tCPL\n");
			print("\tLD\t%s,%s\n", lreg[dreg], "A");
			print("\tLD\t%s,%s\n", "A", hreg[sreg]);
			print("\tCPL\n");
			print("\tLD\t%s,%s\n", hreg[dreg], "A");
			print("\tINC\t%s\n", dst);
			print("\n");
			break;
		}
		case EQI: {
			int lab = genlabel(1);
			int sreg1 = LEFT_X_CHILD_REG(p);
			int sreg2;
			char *val;
			char *jmp = p->syms[0]->x.name;
			int cnst = (RIGHT_CONST(p));

			if(cnst) {
				val = RIGHT_VAL(p);
				print("\n\t; Compare EQ %s and %s\n", intreg[sreg1]->x.name,
					val);
			} else {
				sreg2 = RIGHT_REG(p);
				print("\n\t; Compare EQ %s and %s\n", intreg[sreg1]->x.name,
					intreg[sreg2]->x.name);
			}
			print("\tLD\t%s,%s\n", "A", lreg[sreg1]);
			if(cnst)
				print("\tCP\t#<%s\n", val);
			else
				print("\tCP\t%s\n", lreg[sreg2]);
			print("\tJR\tNZ,.L%d\n", lab);
			print("\tLD\t%s,%s\n", "A", hreg[sreg1]);
			if(cnst)
				print("\tCP\t#>%s\n", val);
			else
				print("\tCP\t%s\n", hreg[sreg2]);
			print("\tJP\tZ,%s\n", jmp);
			print(".L%d:\n", lab);
			print("\n");
			break;
		}
		case GEI: {
			int lab = genlabel(1);
			int sreg1 = LEFT_X_CHILD_REG(p);
			int sreg2;
			char *val;
			char *jmp = p->syms[0]->x.name;
			char *src1 = intreg[sreg1]->x.name;
			int cnst = (RIGHT_CONST(p));

			if(cnst) {
				val = RIGHT_VAL(p);
				print("\n\t; Compare GEI %s and %s\n", intreg[sreg1]->x.name,
					val);
			} else {
				sreg2 = RIGHT_REG(p);
				print("\n\t; Compare GEI %s and %s\n", intreg[sreg1]->x.name,
					intreg[sreg2]->x.name);
			}
			print("\tPUSH\t%s\n", src1);
			if(cnst)
				print("\tLD\t%s,#<%s\n", "A", val);
			else
				print("\tLD\t%s,%s\n", "A", lreg[sreg2]);
			print("\tSUB\t%s\n", lreg[sreg1]);
			print("\tLD\t%s,%s\n", lreg[sreg1], "A");
			if(cnst)
				print("\tLD\t%s,#>%s\n", "A", val);
			else
				print("\tLD\t%s,%s\n", "A", hreg[sreg2]);
			print("\tSBC\t%s\n", hreg[sreg1]);
			print("\tCP\t#0x80\n");
			print("\tJR\tC,.L%d\n", lab);
			print("\tPOP\t%s\n", src1);
			print("\tJP\t%s\n", jmp);
			print(".L%d:\n", lab);
			print("\tOR\t%s\n", lreg[sreg1]);
			print("\tPOP\t%s\n", src1);
			print("\tJP\tZ,%s\n", jmp);
			print("\n");
			break;
		}
		case LEI: {
			int lab = genlabel(1);
			int sreg1 = LEFT_X_CHILD_REG(p);
			int sreg2;
			char *val;
			char *jmp = p->syms[0]->x.name;
			char *src1 = intreg[sreg1]->x.name;
			int cnst = (RIGHT_CONST(p));

			if(cnst) {
				val = RIGHT_VAL(p);
				print("\n\t; Compare LEI %s and %s\n", intreg[sreg1]->x.name,
					val);
			} else {
				sreg2 = RIGHT_REG(p);
				print("\n\t; Compare LEI %s and %s\n", intreg[sreg1]->x.name,
					intreg[sreg2]->x.name);
			}
			print("\tPUSH\t%s\n", src1);
			print("\tLD\t%s,%s\n", "A", lreg[sreg1]);
			if(cnst)
				print("\tSUB\t#<%s\n", val);
			else
				print("\tSUB\t%s\n", lreg[sreg2]);
			print("\tLD\t%s,%s\n", lreg[sreg1], "A");
			print("\tLD\t%s,%s\n", "A", hreg[sreg1]);
			if(cnst)
				print("\tSBC\t#>%s\n", val);
			else
				print("\tSBC\t%s\n", hreg[sreg2]);
			print("\tCP\t#0x80\n");
			print("\tJR\tC,.L%d\n", lab);
			print("\tPOP\t%s\n", src1);
			print("\tJP\t%s\n", jmp);
			print(".L%d:\n", lab);
			print("\tOR\t%s\n", lreg[sreg1]);
			print("\tPOP\t%s\n", src1);
			print("\tJP\tZ,%s\n", jmp);
			print("\n");
			break;
		}
		case GTI: {
			int sreg1 = LEFT_X_CHILD_REG(p);
			int sreg2;
			char *val;
			char *jmp = p->syms[0]->x.name;
			int cnst = (RIGHT_CONST(p));

			if(cnst) {
				val = RIGHT_VAL(p);
				print("\n\t; Compare GTI %s and %s\n", intreg[sreg1]->x.name,
					val);
			} else {
				sreg2 = RIGHT_REG(p);
				print("\n\t; Compare GTI %s and %s\n", intreg[sreg1]->x.name,
					intreg[sreg2]->x.name);
			}
			if(cnst)
				print("\tLD\t%s,#<%s\n", "A", val);
			else
				print("\tLD\t%s,%s\n", "A", lreg[sreg2]);
			print("\tSUB\t%s\n", lreg[sreg1]);
			if(cnst)
				print("\tLD\t%s,#>%s\n", "A", val);
			else
				print("\tLD\t%s,%s\n", "A", hreg[sreg2]);
			print("\tSBC\t%s\n", hreg[sreg1]);
			print("\tCP\t#0x80\n");
			print("\tJP\tNC,%s\n", jmp);
			print("\n");
			break;
		}
		case LTI: {
			int sreg1 = LEFT_X_CHILD_REG(p);
			int sreg2;
			char *val;
			char *jmp = p->syms[0]->x.name;
			int cnst = (RIGHT_CONST(p));

			if(cnst) {
				val = RIGHT_VAL(p);
				print("\n\t; Compare LTI %s and %s\n", intreg[sreg1]->x.name,
					val);
			} else {
				sreg2 = RIGHT_REG(p);
				print("\n\t; Compare LTI %s and %s\n", intreg[sreg1]->x.name,
					intreg[sreg2]->x.name);
			}
			print("\tLD\t%s,%s\n", "A", lreg[sreg1]);
			if(cnst)
				print("\tSUB\t#<%s\n", val);
			else
				print("\tSUB\t%s\n", lreg[sreg2]);
			print("\tLD\t%s,%s\n", "A", hreg[sreg1]);
			if(cnst)
				print("\tSBC\t#>%s\n", val);
			else
				print("\tSBC\t%s\n", hreg[sreg2]);
			print("\tCP\t#0x80\n");
			print("\tJP\tNC,%s\n", jmp);
			print("\n");
			break;
		}
		case NEI: {
			int lab = genlabel(1);
			int sreg1 = LEFT_X_CHILD_REG(p);
			int sreg2;
			char *val;
			char *jmp = p->syms[0]->x.name;
			int cnst = (RIGHT_CONST(p));

			if(cnst) {
				val = RIGHT_VAL(p);
				print("\n\t; Compare NEI %s and %s\n", intreg[sreg1]->x.name,
					val);
			} else {
				sreg2 = RIGHT_REG(p);
				print("\n\t; Compare NEI %s and %s\n", intreg[sreg1]->x.name,
					intreg[sreg2]->x.name);
			}
			print("\tLD\t%s,%s\n", "A", lreg[sreg1]);
			if(cnst)
				print("\tCP\t#<%s\n", val);
			else
				print("\tCP\t%s\n", lreg[sreg2]);
			print("\tJP\tNZ,%s\n", jmp);
			print("\tLD\t%s,%s\n", "A", hreg[sreg1]);
			if(cnst)
				print("\tCP\t#>%s\n", val);
			else
				print("\tCP\t%s\n", hreg[sreg2]);
			print("\tJP\tNZ,%s\n", jmp);
			print(".L%d:\n", lab);
			print("\n");
			break;
		}
		case GEU: {
			int lab = genlabel(1);
			int sreg1 = LEFT_X_CHILD_REG(p);
			int sreg2;
			char *val;
			char *jmp = p->syms[0]->x.name;
			int cnst = (RIGHT_CONST(p));

			if(cnst) {
				val = RIGHT_VAL(p);
				print("\n\t; Compare GEU %s and %s\n", intreg[sreg1]->x.name,
					val);
			} else {
				sreg2 = RIGHT_REG(p);
				print("\n\t; Compare GEU %s and %s\n", intreg[sreg1]->x.name,
					intreg[sreg2]->x.name);
			}
			print("\tLD\t%s,%s\n", "A", hreg[sreg1]);
			if(cnst)
				print("\tCP\t#>%s\n", val);
			else
				print("\tCP\t%s\n", hreg[sreg2]);
			print("\tJR\tNZ,.L%d\n", lab);
			print("\tLD\t%s,%s\n", "A", lreg[sreg1]);
			if(cnst)
				print("\tCP\t#<%s\n", val);
			else
				print("\tCP\t%s\n", lreg[sreg2]);
			print(".L%d:\n", lab);
			print("\tJP\tNC,%s\n", jmp);
			print("\n");
			break;
		}
		case LEU: {
			int lab = genlabel(1);
			int sreg1 = LEFT_X_CHILD_REG(p);
			int sreg2;
			char *val;
			char *jmp = p->syms[0]->x.name;
			int cnst = (RIGHT_CONST(p));

			if(cnst) {
				val = RIGHT_VAL(p);
				print("\n\t; Compare LEU %s and %s\n", intreg[sreg1]->x.name,
					val);
			} else {
				sreg2 = RIGHT_REG(p);
				print("\n\t; Compare LEU %s and %s\n", intreg[sreg1]->x.name,
					intreg[sreg2]->x.name);
			}
			if(cnst)
				print("\tLD\t%s,#>%s\n", "A", val);
			else
				print("\tLD\t%s,%s\n", "A", hreg[sreg2]);
			print("\tCP\t%s\n", hreg[sreg1]);
			print("\tJR\tNZ,.L%d\n", lab);
			if(cnst)
				print("\tLD\t%s,#<%s\n", "A", val);
			else
				print("\tLD\t%s,%s\n", "A", lreg[sreg2]);
			print("\tCP\t%s\n", lreg[sreg1]);
			print(".L%d:\n", lab);
			print("\tJP\tNC,%s\n", jmp);
			print("\n");
			break;
		}
		case GTU: {
			int lab = genlabel(1);
			int sreg1 = LEFT_X_CHILD_REG(p);
			int sreg2;
			char *val;
			char *jmp = p->syms[0]->x.name;
			int cnst = (RIGHT_CONST(p));

			if(cnst) {
				val = RIGHT_VAL(p);
				print("\n\t; Compare GTU %s and %s\n", intreg[sreg1]->x.name,
					val);
			} else {
				sreg2 = RIGHT_REG(p);
				print("\n\t; Compare GTU %s and %s\n", intreg[sreg1]->x.name,
					intreg[sreg2]->x.name);
			}
			if(cnst)
				print("\tLD\t%s,#>%s\n", "A", val);
			else
				print("\tLD\t%s,%s\n", "A", hreg[sreg2]);
			print("\tCP\t%s\n", hreg[sreg1]);
			print("\tJR\tNZ,.L%d\n", lab);
			if(cnst)
				print("\tLD\t%s,#<%s\n", "A", val);
			else
				print("\tLD\t%s,%s\n", "A", lreg[sreg2]);
			print("\tCP\t%s\n", lreg[sreg1]);
			print(".L%d:\n", lab);
			print("\tJP\tC,%s\n", jmp);
			print("\n");
			break;
		}
		case LTU: {
			int lab = genlabel(1);
			int sreg1 = LEFT_X_CHILD_REG(p);
			int sreg2;
			char *val;
			char *jmp = p->syms[0]->x.name;
			int cnst = (RIGHT_CONST(p));

			if(cnst) {
				val = RIGHT_VAL(p);
				print("\n\t; Compare LTU %s and %s\n", intreg[sreg1]->x.name,
					val);
			} else {
				sreg2 = RIGHT_REG(p);
				print("\n\t; Compare LTU %s and %s\n", intreg[sreg1]->x.name,
					intreg[sreg2]->x.name);
			}
			print("\tLD\t%s,%s\n", "A", hreg[sreg1]);
			if(cnst)
				print("\tCP\t#>%s\n", val);
			else
				print("\tCP\t%s\n", hreg[sreg2]);
			print("\tJR\tNZ,.L%d\n", lab);
			print("\tLD\t%s,%s\n", "A", lreg[sreg1]);
			if(cnst)
				print("\tCP\t#<%s\n", val);
			else
				print("\tCP\t%s\n", lreg[sreg2]);
			print(".L%d:\n", lab);
			print("\tJP\tC,%s\n", jmp);
			print("\n");
			break;
		}
		case LSHI: {
			int dreg = REG(p);
			int sreg = LEFT_X_CHILD_REG(p);

			assert(p->kids[1]);

			if(!RIGHT_CONST(p)) {
				print("\n\t; Left shift (int) %s by %s into %s\n", intreg[sreg]->x.name,
					intreg[RIGHT_REG(p)]->x.name, intreg[dreg]->x.name);

				print("\tCALL\t.asl\n");
			} else {
				int nb;
				char *val = RIGHT_VAL(p);

				nb = atoi(val);
				print("\n\t; Left shift (int) %s by %d into %s\n", intreg[sreg]->x.name,
					nb, intreg[dreg]->x.name);

				if(dreg != HL)
					print("\tPUSH\t%s\n", "HL");
				if(dreg != HL || sreg != HL) {
					print("\tLD\t%s,%s\n", "H", hreg[sreg]);
					print("\tLD\t%s,%s\n", "L", lreg[sreg]);
				}
				while(nb-- > 0)
					print("\tADD\t%s,%s\n", "HL", "HL");
				if(dreg != HL) {
					print("\tLD\t%s,%s\n", hreg[dreg], "H");
					print("\tLD\t%s,%s\n", lreg[dreg], "L");
					print("\tPOP\t%s\n", "HL");
				}
			}
			print("\n");
			break;
		}
		case RSHI: {
			int dreg = REG(p);
			int sreg = LEFT_X_CHILD_REG(p);

			assert(p->kids[1]);

			if(!RIGHT_CONST(p)) {
				print("\n\t; Right shift (int) %s by %s into %s\n", intreg[sreg]->x.name,
					intreg[RIGHT_REG(p)]->x.name, intreg[dreg]->x.name);

				print("\tCALL\t.asr\n");
			} else {
				int nb;
				char *val = RIGHT_VAL(p);

				nb = atoi(val);
				print("\n\t; Right shift (int) %s by %d into %s\n", intreg[sreg]->x.name,
					nb, intreg[dreg]->x.name);

				if(dreg != sreg) {
					print("\tLD\t%s,%s\n", hreg[dreg], hreg[sreg]);
					print("\tLD\t%s,%s\n", lreg[dreg], lreg[sreg]);
				}
				while(nb-- > 0) {
					print("\tSRA\t%s\n", hreg[dreg]);
					print("\tRR\t%s\n", lreg[dreg]);
				}
			}
			print("\n");
			break;
		}
		case LSHU: {
			int dreg = REG(p);
			int sreg = LEFT_X_CHILD_REG(p);

			assert(p->kids[1]);

			if(!RIGHT_CONST(p)) {
				print("\n\t; Left shift (unsigned) %s by %s into %s\n", intreg[sreg]->x.name,
					intreg[RIGHT_REG(p)]->x.name, intreg[dreg]->x.name);

				print("\tCALL\t.lsl\n");
			} else {
				int nb;
				char *val = RIGHT_VAL(p);

				nb = atoi(val);
				print("\n\t; Left shift (unsigned) %s by %d into %s\n", intreg[sreg]->x.name,
					nb, intreg[dreg]->x.name);

				if(dreg != HL)
					print("\tPUSH\t%s\n", "HL");
				if(dreg != HL || sreg != HL) {
					print("\tLD\t%s,%s\n", "H", hreg[sreg]);
					print("\tLD\t%s,%s\n", "L", lreg[sreg]);
				}
				while(nb-- > 0)
					print("\tADD\t%s,%s\n", "HL", "HL");
				if(dreg != HL) {
					print("\tLD\t%s,%s\n", hreg[dreg], "H");
					print("\tLD\t%s,%s\n", lreg[dreg], "L");
					print("\tPOP\t%s\n", "HL");
				}
			}
			print("\n");
			break;
		}
		case RSHU: {
			int dreg = REG(p);
			int sreg = LEFT_X_CHILD_REG(p);

			assert(p->kids[1]);

			if(!RIGHT_CONST(p)) {
				print("\n\t; Right shift (unsigned) %s by %s into %s\n", intreg[sreg]->x.name,
					intreg[RIGHT_REG(p)]->x.name, intreg[dreg]->x.name);

				print("\tCALL\t.lsr\n");
			} else {
				int nb;
				char *val = RIGHT_VAL(p);

				nb = atoi(val);
				print("\n\t; Right shift (unsigned) %s by %d into %s\n", intreg[sreg]->x.name,
					nb, intreg[dreg]->x.name);

				if(dreg != sreg) {
					print("\tLD\t%s,%s\n", hreg[dreg], hreg[sreg]);
					print("\tLD\t%s,%s\n", lreg[dreg], lreg[sreg]);
				}
				while(nb-- > 0) {
					print("\tSRL\t%s\n", hreg[dreg]);
					print("\tRR\t%s\n", lreg[dreg]);
				}
			}
			print("\n");
			break;
		}
	}
}

static void offsetsp(offset) int offset; {
	while(offset < -0x80) {
		print("\tLDA\tSP,%d(SP)\n", -0x80);
		offset += 0x80;
	}
	while(offset > 0x7F) {
		print("\tLDA\tSP,%d(SP)\n", 0x7F);
		offset -= 0x7F;
	}
	if(offset != 0)
		print("\tLDA\tSP,%d(SP)\n", offset);
}

static void offsethl(offset) int offset; {
	if(offset >= -0x80 && offset <= 0x7F)
		print("\tLDA\tHL,%d(SP)\n", offset);
	else {
		print("\tLDA\t%s,0(SP)\n", "HL");
		print("\tPUSH\t%s\n", "BC");
		print("\tLD\t%s,#%d\n", "BC", offset);
		print("\tADD\t%s,%s\n", "HL", "BC");
		print("\tPOP\t%s\n", "BC");
	}
}

#define isfp(p) (optype((p)->op)==F || optype((p)->op)==D)

static int ckstack(p, n) Node p; int n; {
	int i;

	for(i = 0; i < NELEMS(p->x.kids) && p->x.kids[i]; i++)
		if(isfp(p->x.kids[i]))
			n--;
	if(isfp(p) && p->count > 0)
		n++;
	if(n > 8)
		error("expression too complicated\n");
	debug(fprint(2, "(ckstack(%x)=%d)\n", p, n));
	assert(n >= 0);
	return n;
}

static void doarg(p) Node p; {
	assert(p && p->syms[0]);
	mkactual(2, p->syms[0]->u.c.v.i);
}

static void blkfetch(k, off, reg, tmp)
int k, off, reg, tmp; {}

static void blkstore(k, off, reg, tmp)
int k, off, reg, tmp; {}

static void blkloop(dreg, doff, sreg, soff, size, tmps)
int dreg, doff, sreg, soff, size, tmps[]; {}

static void local(p) Symbol p; {
	if(isfloat(p->type))
		p->sclass = AUTO;
	if(askregvar(p, rmap[ttob(p->type)]) == 0)
		mkauto(p);
}

static void function(f, caller, callee, n)
Symbol f, callee[], caller[]; int n; {
	int i;

	print("%s:\n", f->x.name);
	print("\tPUSH\tBC\n");
	print("\tPUSH\tDE\n");
	usedmask[0] = usedmask[1] = 0;
	freemask[0] = freemask[1] = ~(unsigned)0;
	offset = 4 + 2;
	for(i = 0; callee[i]; i++) {
		Symbol p = callee[i];
		Symbol q = caller[i];
		assert(q);
		p->x.offset = q->x.offset = offset;
		p->x.name = q->x.name = stringf("%d", p->x.offset);
		p->sclass = q->sclass = AUTO;
		offset += q->type->size;
	}
	assert(caller[i] == 0);
	offset = maxoffset = 0;
	gencode(caller, callee);
	framesize = maxoffset;
	if(framesize > 0)
		offsetsp(-framesize);
	emitcode();
	if(framesize > 0)
		offsetsp(framesize);
	print("\tPOP\tDE\n");
	print("\tPOP\tBC\n");
	print("\tRET\n");
}

static void defsymbol(p) Symbol p; {
	if(p->scope >= LOCAL && p->sclass == STATIC)
		p->x.name = stringf("L%d", genlabel(1));
	else if(p->generated)
		p->x.name = stringf("L%s", p->name);
	else if(p->scope == GLOBAL || p->sclass == EXTERN)
		p->x.name = stringf("_%s", p->name);
	else if(p->scope == CONSTANTS
	&& (isint(p->type) || isptr(p->type))
	&& p->name[0] == '0' && p->name[1] == 'x')
		p->x.name = stringf("0x%s", &p->name[2]);
	else
		p->x.name = p->name;
}

static void address(q, p, n) Symbol q, p; int n; {
	if(p->scope == GLOBAL
	|| p->sclass == STATIC || p->sclass == EXTERN)
		q->x.name = stringf("%s%s%d",
			p->x.name, n >= 0 ? "+" : "", n);
	else {
		q->x.offset = p->x.offset + n;
		q->x.name = stringd(q->x.offset);
	}
}

static void defconst(ty, v) int ty; Value v; {
	switch (ty) {
		case C: print("\t.db\t%d\n", v.uc); return;
		case S: print("\t.dw\t%d\n", v.ss); return;
		case I: print("\t.dw\t%d\n", v.i ); return;
		case U: print("\t.dw\t0x%x\n", v.u ); return;
		case P: print("\t.dw\t0x%x\n", v.p ); return;
		case F:
			print("\t.dw\t0x%x\n", *(unsigned *)&v.f);
			return;
		case D: {
			unsigned *p = (unsigned *)&v.d;
			print("\t.dw\t0x%x,0x%x\n", p[swap], p[1 - swap]);
			return;
			}
	}
	assert(0);
}

static void defaddress(p) Symbol p; {
	print("\t.dw\t%s\n", p->x.name);
}

static void defstring(n, str) int n; char *str; {
	char *s;

	for(s = str; s < str + n; s++)
		print("\t.db\t%d\n", (*s)&0377);
}

static void export(p) Symbol p; {
	if(!HARDWARE_REG(p->x.name))
		print("\t.globl\t%s\n", p->x.name);
}

static void import(p) Symbol p; {
	if(p->ref > 0 && !HARDWARE_REG(p->x.name))
		print("\t.globl\t%s\n", p->x.name);
}

static void global(p) Symbol p; {
	print("%s:\n", p->x.name);
	if(p->u.seg == BSS)
		print("\t.blkb\t%d\n", p->type->size);
}

static void space(n) int n; {
	if(cseg != BSS)
		print("\t.blkb\t%d\n", n);
}

Interface z80IR = {
	1, 1, 0,  /* char */
	2, 1, 0,  /* short; all types have align set to 1 */
	2, 1, 0,  /* int */
	4, 1, 1,  /* float */
	8, 1, 1,  /* double */
	2, 1, 0,  /* T * */
	0, 1, 0,  /* struct; so that ARGB keeps stack aligned */
	1,		  /* little_endian */
	1,		  /* mulops_calls: mul/div/mod are library routines */
	0,		  /* wants_callb */
	1,		  /* wants_argb */
	0,		  /* left_to_right */
	0,		  /* wants_dag */
	address,
	blockbeg,
	blockend,
	defaddress,
	defconst,
	defstring,
	defsymbol,
	emit,
	export,
	function,
	gen,
	global,
	import,
	local,
	progbeg,
	progend,
	segment,
	space,
	0, 0, 0, 0, 0, 0, 0,
	{
		2,		/* max unaligned load is 2 */
		blkfetch, blkstore, blkloop,
		_label,
		_rule,
		_nts,
		_kids,
		_opname,
		_arity,
		_string,
		_templates,
		_isinstruction,
		_ntname,
		emit2,
		doarg,
		target,
		clobber
	}
};

