110 lines
2.6 KiB
C
110 lines
2.6 KiB
C
#ifndef _CODEGEN_REG_H_
|
|
#define _CODEGEN_REG_H_
|
|
|
|
#define IREG_SIZE_L (0 << 6)
|
|
#define IREG_SIZE_W (1 << 6)
|
|
#define IREG_SIZE_B (2 << 6)
|
|
#define IREG_SIZE_BH (3 << 6)
|
|
|
|
enum
|
|
{
|
|
IREG_EAX = 0,
|
|
IREG_ECX = 1,
|
|
IREG_EDX = 2,
|
|
IREG_EBX = 3,
|
|
IREG_ESP = 4,
|
|
IREG_EBP = 5,
|
|
IREG_ESI = 6,
|
|
IREG_EDI = 7,
|
|
|
|
IREG_flags_op = 8,
|
|
IREG_flags_res = 9,
|
|
IREG_flags_op1 = 10,
|
|
IREG_flags_op2 = 11,
|
|
|
|
IREG_pc = 12,
|
|
IREG_oldpc = 13,
|
|
|
|
IREG_eaaddr = 14,
|
|
IREG_ea_seg = 15,
|
|
IREG_op32 = 16,
|
|
IREG_ssegs = 17,
|
|
|
|
IREG_rm_mod_reg = 18,
|
|
|
|
IREG_ins = 19,
|
|
IREG_cycles = 20,
|
|
|
|
/*Temporary registers are stored on the stack, and are not guaranteed to
|
|
be preserved across uOPs. They will not be written back if they will
|
|
not be read again.*/
|
|
IREG_temp0 = 21,
|
|
IREG_temp1 = 22,
|
|
IREG_temp2 = 23,
|
|
IREG_temp3 = 24,
|
|
|
|
IREG_COUNT,
|
|
|
|
IREG_INVALID = 255
|
|
};
|
|
|
|
#define IREG_32(reg) ((reg) + IREG_EAX)
|
|
|
|
extern uint8_t reg_last_version[IREG_COUNT];
|
|
extern uint8_t reg_version_refcount[IREG_COUNT][256];
|
|
|
|
typedef struct
|
|
{
|
|
uint8_t reg;
|
|
uint8_t version;
|
|
} ir_reg_t;
|
|
|
|
extern ir_reg_t invalid_ir_reg;
|
|
|
|
typedef uint8_t ir_host_reg_t;
|
|
|
|
static inline ir_reg_t codegen_reg_read(int reg)
|
|
{
|
|
ir_reg_t ireg;
|
|
|
|
if (reg == IREG_INVALID)
|
|
fatal("codegen_reg_read - IREG_INVALID\n");
|
|
|
|
ireg.reg = reg;
|
|
ireg.version = reg_last_version[reg];
|
|
reg_version_refcount[ireg.reg][ireg.version]++;
|
|
if (!reg_version_refcount[ireg.reg][ireg.version])
|
|
fatal("codegen_reg_read - refcount overflow\n");
|
|
|
|
return ireg;
|
|
}
|
|
|
|
static inline ir_reg_t codegen_reg_write(int reg)
|
|
{
|
|
ir_reg_t ireg;
|
|
|
|
if (reg == IREG_INVALID)
|
|
fatal("codegen_reg_write - IREG_INVALID\n");
|
|
|
|
ireg.reg = reg;
|
|
ireg.version = reg_last_version[reg] + 1;
|
|
reg_last_version[reg]++;
|
|
if (!reg_last_version[reg])
|
|
fatal("codegen_reg_write - version overflow\n");
|
|
reg_version_refcount[reg][ireg.version] = 0;
|
|
|
|
return ireg;
|
|
}
|
|
|
|
struct ir_data_t;
|
|
|
|
void codegen_reg_reset();
|
|
void codegen_reg_flush(struct ir_data_t *ir, codeblock_t *block);
|
|
|
|
/*Register ir_reg usage for this uOP. This ensures that required registers aren't evicted*/
|
|
void codegen_reg_alloc_register(ir_reg_t dest_reg_a, ir_reg_t src_reg_a, ir_reg_t src_reg_b);
|
|
|
|
ir_host_reg_t codegen_reg_alloc_read_reg(codeblock_t *block, ir_reg_t ir_reg);
|
|
ir_host_reg_t codegen_reg_alloc_write_reg(codeblock_t *block, ir_reg_t ir_reg);
|
|
|
|
#endif
|