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

HEADER		"; Code generated by TXCG86A, S86 version"

SRC_DEST	FALSE
LONG_BRANCHES	FALSE

BPW		2

REGISTERS {
		[ "ax" ],
		[ "si" ],
		[ "di" ],
		[ "bx" ],
}

SET_TEXT	".text"
SET_DATA	".data"
SET_BSS		".bss"

WORDDATA	"dw\t"
BYTEDATA	"db\t"

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

INIT_SEQ {
		dest(TEXT);
		genraw(".extrn\t__exit, _TXINIT\n");
		dest(DATA);
		genraw(".extrn\t_GV_\n");
		dest(TEXT);
		genraw("call\t_TXINIT\n");
}
END_SEQ {
}

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

LOCAL_ROUTINES {
var	Saved;

savebx(v0, v1) do
	var	s;

	s := 0;
	if (v0[0][0] = 'a' /\ v0[0][1] = 'x') do
		if (Depth \/ Rx >= NReg) do
			genraw("push\tbx\n");
			s := 1;
		end
		gen("mov\tbx,%S", v1);
		v1[0] := "bx";
	end
	return s;
end

restbx(s) if (s) genraw("pop\tbx\n");
}

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

GLOB_REF	"A%D"
GLOB_VEC_REF	"offset A%D"
LOC_REF		va[0]>=0-> "[bp+%D]": "[bp%D]"
LOC_VEC_REF	"%D"
LOC_VEC_ADJUST	"add\t%S,bp"
LAB_REF		"offset A%D"
CONST_REF	"%D"

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

PUSH_REG_SEQ	gen("push\t%S", va);
POP_REG_SEQ	gen("pop\t%S", va);
LOAD_REG_SEQ	gen("mov\t%S,%S", va);
MOVE_REG_SEQ	gen("mov\t%S,%S", va);
SWAP_REGS_SEQ	gen("xchg\t%S,%S", va);
IND_REG_SEQ	{
		saved := savebx(va, @va[1]);
		gen("mov\t%S,[%S]", va);
		restbx(saved);
}
IND_REG_BYTE_SEQ {
		Saved := savebx(va, @va[1]);
		gen("xor\tcx,cx", 0);
		gen("mov\tcl,[%S]", @va[1]);
		gen("mov\t%S,cx", va);
		restbx(Saved);
}

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

STORE_REG_SEQ	gen("mov\t%S,%S", va);
STORE_IND_REG_SEQ {
		Saved := savebx(va, va);
		gen("mov\t[%S],%S", va);
		restbx(Saved);
}
STORE_BYTE_SEQ {
		Saved := savebx(va, va);
		gen("mov\tcx,%S", @va[1]);
		gen("mov\t[%S],cl", va);
		restbx(Saved);
}
DEREF_SEQ {
		gen("shl\t%S,1", @va[1]);
		gen("add\t%S,%S", va);
}
DEREF_BYTE_SEQ {
		gen("add\t%S,%S", va);
}
INC_GLOBAL_SEQ	gen("add\tword A%D,%D", va);
INC_LOCAL_SEQ {
		gen(va[0]>=0-> "add\tword [bp+%D],%D":
			"add\tword [bp%D],%D", va);
}

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

NEG_REG_SEQ	gen("neg\t%S", va);
NOT_REG_SEQ	gen("not\t%S", va);
LOGICAL_NOT_SEQ {
		gen("neg\t%S", va);
		gen("sbb\t%S,%S", va);
		gen("not\t%S", va);
}
CMP_ZERO_REG_SEQ {
		gen("or\t%S,%S", va);
}

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

MUL_REG_SEQ {
		var	save;

		gen("mov\tcx,%S", @va[1]);
		save := 0;
		if (va[0][0] \= 'a' \/ va[0][1] \= 'x') do
			gen("push\tax", 0);
			gen("mov\tax,%S", va);
			save := 1;
		end
		gen("imul\tcx", 0);
		if (save) do
			gen("mov\t%S,ax", va);
			gen("pop\tax", 0);
		end
}
DIV_REG_SEQ {
		var	save;

		gen("mov\tcx,%S", @va[1]);
		save := 0;
		if (va[0][0] \= 'a' \/ va[0][1] \= 'x') do
			gen("push\tax", 0);
			gen("mov\tax,%S", va);
			save := 1;
		end
		gen("cwd", 0);
		gen("idiv\tcx", 0);
		if (save) do
			gen("mov\t%S,ax", va);
			gen("pop\tax", 0);
		end
}
MOD_REG_SEQ {
		var	save;

		gen("mov\tcx,%S", @va[1]);
		save := 0;
		if (va[0][0] \= 'a' \/ va[0][1] \= 'x') do
			gen("push\tax", 0);
			gen("mov\tax,%S", va);
			save := 1;
		end
		gen("cwd", 0);
		gen("idiv\tcx", 0);
		if (save) gen("pop\tax", 0);
		gen("mov\t%S,dx", va);
}
UMUL_REG_SEQ {
		var	save;

		gen("mov\tcx,%S", @va[1]);
		save := 0;
		if (va[0][0] \= 'a' \/ va[0][1] \= 'x') do
			gen("push\tax", 0);
			gen("mov\tax,%S", va);
			save := 1;
		end
		gen("mul\tcx", 0);
		if (save) do
			gen("mov\t%S,ax", va);
			gen("pop\tax", 0);
		end
}
UDIV_REG_SEQ {
		var	save;

		gen("mov\tcx,%S", @va[1]);
		save := 0;
		if (va[0][0] \= 'a' \/ va[0][1] \= 'x') do
			gen("push\tax", 0);
			gen("mov\tax,%S", va);
			save := 1;
		end
		gen("xor\tdx,dx", 0);
		gen("div\tcx", 0);
		if (save) do
			gen("mov\t%S,ax", va);
			gen("pop\tax", 0);
		end
}
ADD_REG_SEQ	gen("add\t%S,%S", va);
SUB_REG_SEQ	gen("sub\t%S,%S", va);
BIN_AND_REG_SEQ	gen("and\t%S,%S", va);
BIN_OR_REG_SEQ	gen("or\t%S,%S", va);
BIN_XOR_REG_SEQ	gen("xor\t%S,%S", va);
BIN_SHL_REG_SEQ {
		gen("mov\tcx,%S", @va[1]);
		gen("shl\t%S,cl", va);
}
BIN_SHR_REG_SEQ {
		gen("mov\tcx,%S", @va[1]);
		gen("shr\t%S,cl", va);
}
COMP_REG_SEQ	gen("cmp\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		"jmps\tT%D"
TMPLAB		"T%D:"
JMP_TO_LABEL	"jmp"
TRUE_REG	"mov\t%S,-1"
FALSE_REG	"xor\t%S,%S"

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

PROC_PROLOGUE {
		gen("push\tbp", 0);
		gen("mov\tbp,sp", 0);
}
PROC_EPILOGUE {
		gen("pop\tbp", 0);
		gen("ret", 0);
}
CALL_REG_SEQ	gen("call\t%S", va);
CALL_PROC_SEQ	gen("call\t%S", va);
CALL_GVEC_PROC_SEQ {
		va[0] := va[0] * BPW;
		gen("mov\tax,_GV_+%D", va);
		va[0] := "ax";
		gen("call\t%S", va);
}
ADJUST_STACK_SEQ {
		gen("sub\tsp,%D", va);
}
CLEAN_STACK_SEQ	gen("add\tsp,%D", va);
HALT_SEQ {
		gen("xor\tax,ax", 0);
		gen("push\tax", 0);
		gen("call\t__exit", 0);
}

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

DECL_VAR_SEQ	gen("A%D:\tdw\t*%U", va);
DECL_NAMED_DATA_SEQ {
		gen(op = IDATA->
			"A%D:\tdw\t%D":
			"A%D:\tdw\toffset A%D", va);
}
DECL_DATA_SEQ {
		gen(op = IDATA->
			"dw\t%D":
			"dw\toffset A%D", va);
}
DECL_GLOBAL	".globl\t"
DECL_EXTERN	".extrn\t"

