/* codegen.h */
#ifndef CODEGEN_H
#define CODEGEN_H

/* 1 - Print specified number as label */
void printlabel(int label);

/** 2 - Print specified number as label **/
/** printlabel(flab1);colon();nl();     **/
void sa_mk_lbl(int n);

/* Print specified number as label for stack */
void ostklbl();

/* Write text destined for the assembler to read (i.e. stuff not in comments) */
void outasm(char* ptr);

void nl();

void tab();

void colon();

void bell();

void ol(char* ptr);

void ot(char* ptr);

/* Output a signed number to the ASM file. */
void outdec(int number);

/* Output an unsigned number to ASM file. */
void outudec(int number);

/*
	3 element evaluation array of ints -
		eval[0] = Symbol table address, else 0 for constant
		eval[1] = type indirect object to fetch, else 0 for static or const obj.)
		eval[2] = type pointer or array, else 0
*/
void sa_store(int* eval);

/** eval[1] holds typeobj, char or int, 0 for const. **/
/** This is to Retrieve Value, from auto or static **/
/** Syntactic Action for Dereferencing Symbol Value **/
/** Ren rvalue -> rq_val_sa                         **/
void rq_val_sa(int* eval);

/* True if val1 -> int pointer or int array and val2 not ptr or array */
int dbltest(int val1[], int val2[]);

/*
	3 element evaluation array of ints -
		eval[0] = Symbol table address, else 0 for constant
		eval[1] = type indirect object to fetch, else 0 for static object (const.)
		eval[2] = type pointer or array, else 0
*/
/*** determine type of binary operation ***/
void result(int eval[], int eval2[]);

/** boolean conditional test - jmp - if (t) **/
/** !superceded! **/
/**** logical_test(label) int label;
{
	needbrack("(");
	expression();
	needbrack(")");
	sa_tst_jump(label); ** gen syntactic action **
}  ****/

/** Ver_2 boolean conditional test - jmp - if (tf) **/
/**** -- abandoned --
logical_tst2(label,tf) int label, tf;
{
	needbrack("(");
	expression();      ** ref expr2(YES); for comma'd **
	needbrack(")");
	sa_tst2_jmp(label,tf); ** gen syntactic action **
}  ****/

void logic_tst(int t_lbl, int flab1);

/** new, for DO **/
void logic_do_tst(int t_lbl, int flab1);

/** parameter is a ptr, *val **/
int kind_const(int val[]);

int number(int val[]);

int chr_const(int val[]);

/** Quoted string entered into literals table **/
int str_const(int val[]);

/*	>>>>>> start of cc8 <<<<<<<	*/
/* Begin a comment line for the assembler */
void sa_comment();

/* Put out assembler info before any code is generated */
void header();

/* Print any assembler stuff needed after all code */
void trailer();

/* Continue code segment stuff. */
void sa_cseg();

/* Continue data segment stuff. */
void sa_dseg();

/* Function initialization. */
void FN_Prolog();

/* Function termination. */
void FN_Epilog();

/* Print out a name such that it won't annoy the assembler */
/*	(by matching anything reserved, like opcodes.) */
/** chgd outname() -> asm_symb(), removed leading "cz" **/
/** removed toupperi, nasm is case sensitive. **/

/* CHG(a).. Sun 14 Aug 2011 02:44:41 PM CDT added back leading chr
** to symbols generated for nasm so that the io_clib extern labels
** are not duplicates. ie..
** CHG: fclose(); -> fclose: -> call fclose ;extern clib_fn
** TO:  fclose(); -> _fclose: -> call fclose ;extern clib_fn
*/
void asm_symb(char* sname);

/* Fetch a static memory cell into the primary register */
void sa_getmem(char* sym);

/*
	Fetch the stack relative address of the specified
	automatic symbol into the primary register
*/
void sa_deref(char* sym);

/* Store the primary register into the specified static memory cell. */
void sa_putmem(char* sym);

/* Store the specified object type in the primary register */
/* at the address on the top of the stack. */
/** presumes DS:EDI is address of target **/
void sa_putstk(char typeobj);

/* Fetch the specified object type indirect through the */
/*	primary register into the primary register */
/** called as: indirect(eval[1], eval[0]);  **/
/** these are auto class on stack **/
/*** reverted, problem with array[0] is DS relative ***/
void sa_indirect(char typeobj);

/* Swap the primary and secondary registers */
void sa_swap();

/* Print partial instruction to get an immediate value */
/*	into the primary register */
void sa_immed();

/* Print partial instruction to get an immediate value into the primary register. */
/* global & non-array & function */
void sa_immedo();

/* Push the primary register onto the stack. */
void sa_push();

/* Pop the top of the stack into the secondary register */
void sa_pop();

/* Swap the primary register and the top of the stack */
/** ck for DS dependency - note, EA can use SS: vs default DS: **/
/*** reverted, problem with array[0] is DS relative ***/
void sa_swapstk();

/** EO C86N-8.C **/
/*	>>>>>> start of cc9 <<<<<<<	*/

/* Call the specified subroutine name */
void sa_call(char* sname);

/* Call a run-time library routine */
void sa_callrts(char* sname);

/* Return from subroutine */
void sa_ret();

/* Perform subroutine call to addr on top of stack */
/*** reverted, problem with array[0] is DS relative ***/
void sa_callstk();

/* Jump to specified internal label number */
void sa_jump(int label);

/* Test the primary register and jump if false to label */
/** testjump()->sa_tst_jump() **/
/** caller - logical_test(label); - superceded **/
/**** sa_tst_jump(label) int label;
{
	ol("OR   EBX, EBX");
	ol("JNZ  $+5");
	ot("JMP  ");
	printlabel(label);
	nl();
}  ****/

/* ver_2 - Test the primary register and jump if false to label */
/** the supplied condition, tf, dictates which form to codegen **/
/**** caller - logical_tst2(label,tf); !abandoned! --
sa_tst2_jmp(label, tf) int label, tf;
{
	ol("OR   EBX,EBX");
	if (tf)  ot("JNZ  ");
	else     ot("JZ   ");
	printlabel(label);
	nl();
}  ****/

/** ver_3 **/
void sa_if_tst(int t_lbl, int flab1);

void sa_do_tst(int t_lbl, int flab1);

/** Added, Modified for NASM, caller dumpstatics() **/
void def_sizein();

/* Print pseudo-op to define storage (Character). */
/** caller dumpstatics() **/

void defstorchr();

/* Print pseudo-op to define storage (Integer). */
/* Changed to DD */
/** Caller: dumpstatics() **/
void defstorint();

/* Print pseudo-op to define storage (Pointer). */
/* Changed to DD */
/** Caller: dumpstatics() **/
void defstorptr();

/* Print pseudo-op to define a byte */
void defbyte();

/* Print pseudo-op to define a word (changed to DD) */
void defword();

/* Modify the stack pointer to the new value indicated */
int sa_modstk(int newsp);

/* Modify the stack pointer to the new value indicated */
int sa_rtnstk(int newsp);

/* Primary Register = EBX, Secondary Register = EDX */
/* Double the primary register */
void sa_doublereg();

/* Add the primary and secondary registers (results in primary) */
void sa_add();

/* Subtract the primary register from the secondary (results in primary) */
void sa_sub();

/* Multiply the primary and secondary registers (results in primary) */
/** MUL EAX, r/m32 -> EDX:EAX **/
void sa_mult();

/*
	Divide the secondary register by the primary
	(quotient in primary, remainder in secondary)
*/
/** DIV EDX:EAX, r/m32 -> EAX = Quo., EDX = Rem. **/
void sa_div();

/* Compute remainder (modulo) of secondary register divided by the primary */
/* (remainder in primary, quotient in secondary) */
void sa_modulo();

/* Inclusive 'or' the primary and the secondary registers (results in primary) */
void sa_or();

/* Exclusive 'or' the primary and seconday registers (results in primary) */
void sa_xor();

/* 'And' the primary and secondary registers (results in primary) */
void sa_and();

/*
	Arithmetic shift right the secondary register by
	the count in the primary (results in primary).
*/
void sa_asr();

/*
	Arithmetic left shift the secondary register by the count in the primary.
	(results in primary)
*/
void sa_asl();

/* Form two's complement of primary register */
void sa_neg();

/* Form one's complement of primary register */
void sa_not();

/* Increment the primary register by one */
void sa_inc();

/* Decrement the primary register by one */
void sa_dec();

/* Following are the conditional operators */
/* They compare the secondary register against the primary */
/* and put a literal 1 in the primary if the condition is */
/* true, otherwise they clear the primary register */

/* Test for equal */
void sa_eq();

/* Test for not equal */
void sa_not_equal();

/* Test for less than (signed) */
void sa_sless_than();

/* Test for less than or equal to (signed) */
void sa_sless_or_eq();

/* Test for greater than (signed) */
void sa_sgreater_than();

/* Test for greater than or equal to (signed) */
void sa_sge();

/* Test for less than (unsigned) */
void sa_uless_than();

/* Test for less than or equal to (unsigned) */
void sa_uless_oreq();

/* Test for greater than (unsigned) */
void sa_ugt();

/* Test for greater than or equal to (unsigned) */
void sa_uge();

/** Convert primary value into logical (boolean) value, **/
/** that is, (0 if 0, 1 otherwise) **/
void sa_mk_bool();

/** Convert primary value into logical not (boolean) value, **/
/** that is, (1 if 0, 0 otherwise) **/
void sa_mk_nbool();

#endif /* CODEGEN_H */