/*
 * gencode.h  -  Definitions for code generator
 *
 * Copyright (C) 1997-2007 Gero Kuhlmann   <gero@gkminix.han.de>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 * $Id: gencode.h,v 1.13 2007/01/06 18:31:27 gkminix Exp $
 */


/*
 * When dealing with variables we have to consider the following cases:
 *
 *	1.) the variable is somewhere in memory, and addressed by:
 *		- absolute
 *		- relative to the current stack frame (BP) or another register
 *		- relative to an older stack frame
 *	2.) in a register for passing to another level of expression handling
 *
 * The following structure holds this information in terms of absolute/relative
 * addresses and the registers to be used. This includes the size information
 * for non-scalars. If the variable is a string, we consider the temporary
 * strings area at the beginning of the data segment a "register". Other
 * non-scalars cannot be represented as a register, so case 2.) doesn't apply.
 */
#define MEM_ADR_MASK	0x000f		/* mask for address field */
#define MEM_NOADDR	0x0000		/* expression doesn't return a result */
#define MEM_ABSOLUTE	0x0001		/* use address field */
#define MEM_RELATIVE	0x0002		/* use address and register field */
#define MEM_REGISTER	0x0003		/* use register field */

#define MEM_SIZE_MASK	0x00f0		/* mask for size field */
#define MEM_NOSIZE	0x0000		/* size field not used */
#define MEM_IMMEDIATE	0x0010		/* use immediate value for size */
#define MEM_SIZEREG	0x0020		/* use register for size */

#define MEM_USERELOC	0x0100		/* absolute addr needs relocation */

#define memaddr(dp)	((dp)->memtype & MEM_ADR_MASK)
#define memsize(dp)	((dp)->memtype & MEM_SIZE_MASK)

struct memval {
	addr_t i;		/* immediate value */
	unsigned int r;		/* register identifier */
};

struct meminfo {
	int memtype;
	struct memval addr;	/* Adress of variable */
	struct memval size;	/* Size of variable */
	struct typesdef *t;	/* Type which made up this meminfo record */
};



/*
 * Types of fixup information
 */
typedef enum {
	FIXUP_ABS,		/* Fixup is an absolute address */
	FIXUP_REL8,		/* Fixup is an 8-bit relative value */
	FIXUP_REL16		/* Fixup is a 16-bit relative value */
} fixuptype;



/*
 * Special label addresses
 */
#define LADDR_NONE	((addr_t) 0)
#define LADDR_UNDEF	((addr_t) -1)
#define LADDR_CODEPTR	((addr_t) -2)

#define islabspecial(a)	((addr_t)(a) <= (addr_t)0)



/*
 * General memory layout
 */
#define STACKSIZE	4096
#define CODESIZE	65535
#define DATASIZE	65535
#define CONSTSIZE	(DATASIZE - STACKSIZE)



/*
 * The following are the steps by which the buffers get increased
 */
#define RELOCSIZE	2048
#define DEBUGSIZE	1024
#define LABELSIZE	1024
#define FIXUPSIZE	2048



/*
 * Define which registers are presently used
 */
extern int si_inuse;			/* SI register is in use */
extern int di_inuse;			/* DI register is in use */
extern int bx_inuse;			/* BX register is in use */
extern int cx_inuse;			/* CX register is in use */
extern int dx_inuse;			/* DX register is in use */



/*
 * External variables
 */
extern addr_t dataptr;				/* Current data pointer */
extern addr_t constptr;				/* Current constant pointer */
extern addr_t codeptr;				/* Current code pointer */
extern addr_t startadr;				/* Start address */
extern addr_t stacksize;			/* Stack size */



/*
 * External routines in module: gencode.c
 */
extern void putcode __P((byte_t c));
extern void putconst __P((byte_t c));
extern addr_t putmemblock __P((const byte_t *memblock, size_t size));
extern void putint __P((long val, int usereloc));
extern void putaddr __P((slabel_t labelno, addr_t offset, fixuptype ftype));
extern void dofixup __P((void));
extern void setreloc __P((void));
extern void setdebug __P((void));
extern slabel_t setlabel __P((slabel_t labelno, addr_t addr));
extern addr_t getlabel __P((slabel_t labelno));
extern int mapcmp __P((int cmd));



/*
 * External routines in module: gencmd.c
 */
extern void putjmp __P((addr_t dest, slabel_t labelno, unsigned int jmpcode));
extern void putincdec __P((unsigned int reg, int inc));
extern void putimmed __P((unsigned int op,
			unsigned int reg, long val, addr_t disp));
extern void putregop __P((unsigned int op,
			unsigned int srcreg, unsigned int destreg, addr_t disp));
extern void putlea __P((unsigned int destreg, unsigned int basereg, addr_t disp));
extern void putstackreg __P((unsigned int reg, int push, addr_t disp));
extern void putimmedpush __P((long val, int immreloc));
extern void putbound __P((unsigned int srcreg, struct typesdef *tp));
extern void putsetbit __P((unsigned int reg, unsigned int cond));
extern byte_t getmodrm __P((unsigned int basereg, addr_t disp));
extern void putldaddr __P((unsigned int reg, struct meminfo *dp));
extern void setmeminfo __P((struct expr *ep, struct meminfo *dp,
				unsigned int basereg, unsigned int sizereg));

#define putpush(reg)	putstackreg((reg), TRUE, 0)
#define putpop(reg)	putstackreg((reg), FALSE, 0)



/*
 * External routines in module: genexpr.c
 */
extern void putscalarexpr __P((struct expr *ep, struct meminfo *dp));
extern void putcomplexexpr __P((struct expr *ep, struct meminfo *dp));
extern void putproc __P((struct expr *ep, struct meminfo *dp));



/*
 * Data area which contains the runtime module
 */
extern __u8 runtime_data[];
extern unsigned int runtime_data_size;

