// Registers
typedef enum {G0 = 0, G1,G2,G3,G4,G5,G6,G7,
	      O0,O1,O2,O3,O4,O5,O6,O7,
	      L0,L1,L2,L3,L4,L5,L6,L7,
	      I0,I1,I2,I3,I4,I5,I6,I7} reg;

// Memory ops
#define LD_OP 0x00
#define ST_OP 0x04

// Other ops
#define AND_OP 0x01
#define OR_OP  0x02
#define XOR_OP 0x03
#define SLL_OP 0x25
#define SRL_OP 0x26
#define SRA_OP 0x27
#define ADD_OP 0x00
#define SUB_OP 0x04
#define SMUL_OP 0x0b
#define SDIV_OP 0x0f
#define WRY_OP 0x30
#define SAVE_OP 0x3c
#define RESTORE_OP 0x3d
#define JMPL_OP 0x38

#define CC 0x10  // OR into op to set condition code

// Conditions
#define N_COND 0x0
#define E_COND 0x1
#define LE_COND 0x2
#define L_COND 0x3
#define LEU_COND 0x4
#define LU_COND 0x5
#define NEG_COND 0x6
#define VS_COND 0x7
#define A_COND 0x8
#define NE_COND 0x9
#define G_COND 0xA
#define GE_COND 0xB
#define GU_COND 0xC
#define GEU_COND 0xD
#define POS_COND 0xE
#define VC_COND 0xF

#define INVERT_COND(cond) (((cond)+8)%16)

// Instruction generators
uint32 gen_call(int32 disp);
uint32 gen_sethi(reg rd, int32 imm);
uint32 gen_bicc(uint8 cond,bool annul,int32 disp);
uint32 gen_mop(uint8 op,reg rd,reg rs1,reg rs2);
uint32 gen_mop_imm(uint8 op,reg rd,reg rs1,int16 disp);
uint32 gen_op(uint8 op,reg rd,reg rs1,reg rs2);
uint32 gen_op_imm(uint8 op,reg rd,reg rs1,int16 disp);

// useful shorthands
#define GEN_MOV(rd,rs) (gen_op(OR_OP,rd,G0,rs))
#define GEN_MOV_IMM(rd,s) (gen_op_imm(OR_OP,rd,G0,s))
#define GEN_CMP(rs1,rs2) (gen_op(SUB_OP|CC,G0,rs1,rs2))
#define GEN_CMP_IMM(rs1,s) (gen_op_imm(SUB_OP|CC,G0,rs1,s))
#define GEN_TST(rs) (gen_op(OR_OP|CC,G0,rs,G0))
#define GEN_NOP (gen_sethi(0,0))

// for use with sethi
#define HIBITS(v) (((uint32)v) >> 10)
#define LOBITS(v) (((uint32)v) & 0x3ff)

// debug
void dump(uint32 *scode,int length);
