/* code.h */

/*
 * Opcode is one byte
 */

/* Stack opcodes */
#define OP_NOP		0	/* Do nothing */
#define OP_PUSH		1	/* Push immediate */
#define OP_PUSHSTR	2	/* Push immediate string */
#define OP_POP		3	/* sp += n */
#define OP_ALLOC	4	/* sp -= n */
#define OP_LOAD		5	/* push(*(sp+n)) */
#define OP_STORE	6	/* *(sp+n) = pop() ; use sp after pop */

/* Branch opcodes are odd if link, even otherwise */
#define OP_B		8	/* relative branch */
#define OP_BL		9
#define OP_BI		10	/* indirect branch */
#define OP_BIL		11
#define OP_BZ		12	/* pop and relative branch if zero */
#define OP_BZL		13
#define OP_BNZ		14	/* pop and relative branch if not zero */
#define OP_BNZL		15
#define OP_RET		16	/* pop and branch to return address */

/* Calls */
#define OP_CALLNUM	17	/* call numbered function */
#define OP_CALLSTR	18	/* call string function */

/* Arithmetic */
#define OP_ADD		19
#define OP_SUB		20
#define OP_MUL		21
#define OP_DIV		22
#define OP_EQ		23
#define OP_NE		24
#define OP_LT		25
#define OP_GT		26
#define OP_LE		27
#define OP_GE		28

#define FLOP_ADD	29
#define FLOP_SUB	30
#define FLOP_MUL	31
#define FLOP_DIV	32
#define FLOP_EQ		33
#define FLOP_NE		34
#define FLOP_LT		35
#define FLOP_GT		36
#define FLOP_LE		37
#define FLOP_GE		38

char *instr_names[] = {
	"NOP",
	"PUSH",
	"PUSHSTR",
	"POP",
	"ALLOC",
	"LOAD",
	"STORE",
	"ERR",
	"B",
	"BL",
	"BI",
	"BIL",
	"BZ",
	"BZL",
	"BNZ",
	"BNZL",
	"RET",
	"CALLNUM",
	"CALLSTR",
	"ADD",
	"SUB",
	"MUL",
	"DIV",
	"EQ",
	"NE",
	"LT",
	"GT",
	"LE",
	"GE",
	"FLADD",
	"FLSUB",
	"FLMUL",
	"FLDIV",
	"FLEQ",
	"FLNE",
	"FLLT",
	"FLGT",
	"FLLE",
	"FLGE",
};

#define NINSTR (sizeof(instr_names)/sizeof(char *))
#define INSTR_NAME(x) (instr_names[x])

/*
 * For opcodes which take an operand, the byte count is stored
 * in the top 2 bits
 */
#define BYTECOUNT(x)	((((x) >> 6) & 3) + 1)
#define SET_BYTECOUNT(x) (((x)-1)<<6)
#define OPCODE_MASK(x)	((x) & 0x3f)

/*
 * For OP_PUSHSTR and OP_CALLSTR, the byte count is the number of bytes
 * which follow the opcode to describe the length of the string. In
 * most cases, the string will be <256 bytes long, so the byte count will
 * be 1.
 */


/* Internal functions */

#define INTFN_NOP			0
#define INTFN_GLOBAL_STORE		1
#define INTFN_GLOBAL_LOAD		2
#define INTFN_GLOBAL_ARRAY_STORE	3
#define INTFN_GLOBAL_ARRAY_LOAD		4


/*
 * This is important because sizeof(stkentry) must be the same both
 * in the compiler and the vm, in order to get string handling right.
 */
typedef int stkentry;


/*
 * Structure of the file header:
 *
 * 2	"LC"	(magic)
 * 2	0	(version)
 * 4	ptr	(pointer to function table)
 *
 * ptr-4	code
 *
 *  1 or more of:
 *   4	length of block, or 0 to terminate
 *   4	type of block (0 for function)
 *   4	pointer to function (offset within file)
 *   4	number of arguments (unused for now)
 *   n	NULL-terminated function name.
 *		- align to 4-byte boundary
 *
 */

#define MAGIC1 'L'
#define MAGIC2 'C'
#define VERSION1 0
#define VERSION2 0

