!-------------------------------------------------------------------
!	This is a code generator definition file for
!	TXCGG, the T3X Code Generator Generator.
!	-- GAS-386 version --
!	Copyright (C) 1998 Nils M Holm.
!	See LICENSE for conditions of use.
!	For documentation, see 'cgdesc.doc'.
!-------------------------------------------------------------------

HEADER		"/* Code generated by TXCG386, GAS-386 version */"
SRC_DEST	TRUE
LONG_BRANCHES	FALSE
BPW		4
REGISTERS {
		[ "%eax" ],
		[ "%esi" ],
		[ "%edi" ],
		[ "%ebx" ],
}
SET_TEXT	".text"
SET_DATA	".data"
SET_BSS		".bss"
WORDDATA	".long\t"
BYTEDATA	".byte\t"

!----------------------------------------!

INIT_SEQ {
		dest(TEXT);
		genraw("/* keep 3.x ld happy */\n");
		genraw(".globl\t_start\n");
		genraw("_start:\n");
		genraw("call\tTXINIT\n");
}
END_SEQ {
}


!----------------------------------------!

LOCAL_ROUTINES {
}

!----------------------------------------!

GLOB_REF	"A_%D"
GLOB_VEC_REF	"$A_%D"
LOC_REF		"%D(%%ebp)"
LOC_VEC_REF	"$%D"
LOC_VEC_ADJUST	"addl\t%%ebp,%S"
LAB_REF		"$A_%D"
CONST_REF	"$%D"

!----------------------------------------!

PUSH_REG_SEQ	gen("pushl\t%S", va);
POP_REG_SEQ	gen("popl\t%S", va);
LOAD_REG_SEQ	gen("movl\t%S,%S", va);
MOVE_REG_SEQ	gen("movl\t%S,%S", va);
SWAP_REGS_SEQ	gen("xchgl\t%S,%S", va);
IND_REG_SEQ	gen("movl\t(%S),%S", va);
IND_REG_BYTE_SEQ {
		gen("xorl\t%%ecx,%%ecx", 0);
		gen("movb\t(%S),%%cl", va);
		gen("movl\t%%ecx,%S", va);
}

!----------------------------------------!

STORE_REG_SEQ	gen("movl\t%S,%S", va);
STORE_IND_REG_SEQ {
		gen("movl\t%S,(%S)", va);
}
STORE_BYTE_SEQ {
		gen("movl\t%S,%%ecx", va);
		gen("movb\t%%cl,(%S)", @va[1]);
}
DEREF_SEQ {
		gen("shll\t$2,%S", va);
		gen("addl\t%S,%S", va);
}
DEREF_BYTE_SEQ {
		gen("addl\t%S,%S", va);
}
INC_GLOBAL_SEQ	gen("addl\t$%D,A_%D", va);
INC_LOCAL_SEQ	gen("addl\t$%D,%D(%%ebp)", va);

!----------------------------------------!

NEG_REG_SEQ	gen("negl\t%S", va);
NOT_REG_SEQ	gen("notl\t%S", va);
LOGICAL_NOT_SEQ {
		gen("negl\t%S", va);
		gen("sbbl\t%S,%S", va);
		gen("notl\t%S", va);
}
CMP_ZERO_REG_SEQ {
		gen("orl\t%S,%S", va);
}

!----------------------------------------!

MUL_REG_SEQ	gen("imull\t%S,%S", va);
DIV_REG_SEQ {
		var     save;
		if (Qe-Qs /\ LdQueue[Qs] = INUM) do
			gen("movl\t%S,%%ecx", va);
			va[0] := "%ecx";
		end
		save := 0;
		if (va[1][0] \= '%' \/ va[1][2] \= 'a') do
			gen("pushl\t%%eax", 0);
			gen("movl\t%S,%%eax", @va[1]);
			save := 1;
		end
		gen("cdq", 0); gen("idivl\t%S,%%eax", va);
		if (save) do
			gen("movl\t%%eax,%S", @va[1]);
			gen("popl\t%%eax", 0);
		end
}
MOD_REG_SEQ {
		var     save;
		if (Qe-Qs /\ LdQueue[Qs] = INUM) do
			gen("movl\t%S,%%ecx", va);
			va[0] := "%ecx";
		end
		save := 0;
		if (va[1][0] \= '%' \/ va[1][2] \= 'a') do
			gen("pushl\t%%eax", 0);
			gen("movl\t%S,%%eax", @va[1]);
			save := 1;
		end
		gen("cdq", 0); gen("idivl\t%S,%%eax", va);
		if (save) do
			gen("movl\t%%eax,%S", @va[1]);
			gen("popl\t%%eax", 0);
		end
		va[0] := va[1];
		gen("movl\t%%edx,%S", va);
}
UMUL_REG_SEQ {
		var	save;
		if (Qe-Qs /\ LdQueue[Qs] = INUM) do
			gen("movl\t%S,%%ecx", va);
			va[0] := "%ecx";
		end
		save := 0;
		if (va[1][0] \= '%' \/ va[1][2] \= 'a') do
			gen("pushl\t%%eax", 0);
			gen("movl\t%S,%%eax", @va[1]);
			save := 1;
		end
		gen("mull\t%S", va);
		if (save) do
			gen("movl\t%%eax,%S", @va[1]);
			gen("popl\t%%eax", 0);
		end
}
UDIV_REG_SEQ {
		var	save;
		if (Qe-Qs /\ LdQueue[Qs] = INUM) do
			gen("movl\t%S,%%ecx", va);
			va[0] := "%ecx";
		end
		save := 0;
		if (va[1][0] \= '%' \/ va[1][2] \= 'a') do
			gen("pushl\t%%eax", 0);
			gen("movl\t%S,%%eax", @va[1]);
			save := 1;
		end
		gen("xorl\t%%edx,%%edx", 0); gen("divl\t%S", va);
		if (save) do
			gen("movl\t%%eax,%S", @va[1]);
			gen("popl\t%%eax", 0);
		end
}
ADD_REG_SEQ	gen("addl\t%S,%S", va);
SUB_REG_SEQ	gen("subl\t%S,%S", va);
BIN_AND_REG_SEQ	gen("andl\t%S,%S", va);
BIN_OR_REG_SEQ	gen("orl\t%S,%S", va);
BIN_XOR_REG_SEQ	gen("xorl\t%S,%S", va);
BIN_SHL_REG_SEQ {
		gen("movl\t%S,%%ecx", va);
		gen("shll\t%%cl,%S", @va[1]);
}
BIN_SHR_REG_SEQ {
		gen("movl\t%S,%%ecx", va);
		gen("shrl\t%%cl,%S", @va[1]);
}
COMP_REG_SEQ	gen("cmpl\t%S,%S", va);

!----------------------------------------!

BE		"je"
BNE		"jne"
BL		"jl"
BG		"jg"
BLE		"jle"
BGE		"jge"
BUL		"jb"
BUG		"ja"
BULE		"jbe"
BUGE		"jae"
BRANCH_DEST	"T_%D"
JUMP_DEST	"A_%D"
JUMP	"jmp\tA_%D"
LABEL		"A_%D:"
DATALABEL	"A_%D:"
DATALABEL_ALIAS	"A_%D:"
BRANCH		"jmp\tT_%D"
TMPLAB		"T_%D:"
JMP_TO_LABEL	"jmp"
TRUE_REG	"movl\t$-1,%S"
FALSE_REG	"xorl\t%S,%S"

!----------------------------------------!

PROC_PROLOGUE {
		gen("pushl\t%%ebp", 0);
		gen("movl\t%%esp,%%ebp", 0);
}
PROC_EPILOGUE {
		gen("popl\t%%ebp", 0);
		gen("ret", 0);
}
CALL_REG_SEQ	gen("call\t%S", va);
CALL_PROC_SEQ	gen("call\t%S", va);
CALL_GVEC_PROC_SEQ {
		gen("movl\t$%D,%%eax", va);
		genraw("movl\tGV_(,%eax,4),%ebx\n");
		va[0] := "*%ebx";
		gen("call\t%S", va);
}
ADJUST_STACK_SEQ {
		gen("subl\t$%D,%%esp", va);
}
CLEAN_STACK_SEQ	gen("addl\t$%D,%%esp", va);
HALT_SEQ {
		gen("xorl\t%%eax,%%eax", 0);
		gen("pushl\t%%eax", 0);
		gen("call\t__exit", 0);
}

!----------------------------------------!

DECL_VAR_SEQ {
	va[1] := va[1] * BPW;
	gen(".comm\tA_%D,%U", va);
}
DECL_NAMED_DATA_SEQ {
		gen(op = IDATA->
			"A_%D:\t.long\t%D":
			"A_%D:\t.long\tA_%D", va);
}
DECL_DATA_SEQ {
		gen(op = IDATA->
			".long\t%D":
			".long\tA_%D", va);
}
DECL_GLOBAL	".globl\t"
DECL_EXTERN	".extrn\t"

