Implemented basic register allocation.

Mainly handles 'virtual' registers at the moment (eg current and last PC values, segment override status, etc).
This commit is contained in:
SarahW 2018-06-23 19:04:36 +01:00
commit ee3f9210dc
23 changed files with 776 additions and 76 deletions

View file

@ -1,45 +1,10 @@
#ifndef _CODEGEN_IR_DEFS_
#define _CODEGEN_IR_DEFS_
#define IREG_L (0 << 6)
#define IREG_W (1 << 6)
#define IREG_B (2 << 6)
#define IREG_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_reg = 9,
ireg_flags_op1 = 10,
ireg_flags_op2 = 11,
ireg_flags_pc = 12,
ireg_flags_oldpc = 13,
ireg_eaaddr = 14,
/*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 = 16,
ireg_temp1 = 17,
ireg_temp2 = 18,
ireg_temp3 = 19
};
#include "codegen_reg.h"
#define UOP_REG(reg, size, version) ((reg) | (size) | (version << 8))
#define UOP_REG_UNUSED 0xffff
/*uOP is a barrier. All previous uOPs must have completed before this one executes.
All registers must have been written back or discarded*/
#define UOP_TYPE_BARRIER (1 << 31)
@ -65,20 +30,23 @@ enum
#define UOP_CALL_INSTRUCTION_FUNC (UOP_TYPE_PARAMS_POINTER | 0x11 | UOP_TYPE_BARRIER)
#define UOP_STORE_P_IMM (UOP_TYPE_PARAMS_IMM | 0x12)
#define UOP_STORE_P_IMM_8 (UOP_TYPE_PARAMS_IMM | 0x13)
#define UOP_MOV_PTR (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x20)
#define UOP_MOV_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x21)
#define UOP_MAX 0x14
#define UOP_MAX 0x22
#define UOP_MASK 0xffff
typedef struct uop_t
{
uint32_t type;
uint16_t dest_reg_a;
uint16_t src_reg_a;
uint16_t src_reg_b;
uint16_t src_reg_c;
ir_reg_t dest_reg_a;
ir_reg_t src_reg_a;
ir_reg_t src_reg_b;
ir_reg_t src_reg_c;
uint32_t imm_data;
void *p;
ir_host_reg_t dest_reg_a_real;
} uop_t;
#define UOP_NR_MAX 4096
@ -98,20 +66,38 @@ static inline uop_t *uop_alloc(ir_data_t *ir)
uop = &ir->uops[ir->wr_pos++];
uop->dest_reg_a = UOP_REG_UNUSED;
uop->src_reg_a = UOP_REG_UNUSED;
uop->src_reg_b = UOP_REG_UNUSED;
uop->src_reg_c = UOP_REG_UNUSED;
uop->dest_reg_a = invalid_ir_reg;
uop->src_reg_a = invalid_ir_reg;
uop->src_reg_b = invalid_ir_reg;
uop->src_reg_c = invalid_ir_reg;
return uop;
}
static inline void uop_gen_reg_src1(uint32_t uop_type, ir_data_t *ir, int arg, uint16_t src_reg_a)
static inline void uop_gen_reg_src1(uint32_t uop_type, ir_data_t *ir, int arg, int src_reg_a)
{
uop_t *uop = uop_alloc(ir);
uop->type = uop_type;
uop->src_reg_a = src_reg_a;
uop->src_reg_a = codegen_reg_read(src_reg_a);
}
static inline void uop_gen_reg_dst_imm(uint32_t uop_type, ir_data_t *ir, int dest_reg, uint32_t imm)
{
uop_t *uop = uop_alloc(ir);
uop->type = uop_type;
uop->dest_reg_a = codegen_reg_write(dest_reg);
uop->imm_data = imm;
}
static inline void uop_gen_reg_dst_pointer(uint32_t uop_type, ir_data_t *ir, int dest_reg, void *p)
{
uop_t *uop = uop_alloc(ir);
uop->type = uop_type;
uop->dest_reg_a = codegen_reg_write(dest_reg);
uop->p = p;
}
static inline void uop_gen_imm(uint32_t uop_type, ir_data_t *ir, uint32_t imm)
@ -146,7 +132,14 @@ static inline void uop_gen_pointer_imm(uint32_t uop_type, ir_data_t *ir, void *p
#define uop_CALL_FUNC(ir, p) uop_gen_pointer(UOP_CALL_FUNC, ir, p)
#define uop_CALL_INSTRUCTION_FUNC(ir, p) uop_gen_pointer(UOP_CALL_INSTRUCTION_FUNC, ir, p)
#define uop_MOV_IMM(ir, reg, imm) uop_gen_reg_dst_imm(UOP_MOV_IMM, ir, reg, imm)
#define uop_MOV_PTR(ir, reg, p) uop_gen_reg_dst_pointer(UOP_MOV_PTR, ir, reg, p)
#define uop_STORE_PTR_IMM(ir, p, imm) uop_gen_pointer_imm(UOP_STORE_P_IMM, ir, p, imm)
#define uop_STORE_PTR_IMM_8(ir, p, imm) uop_gen_pointer_imm(UOP_STORE_P_IMM_8, ir, p, imm)
void codegen_direct_write_8(codeblock_t *block, void *p, int host_reg);
void codegen_direct_write_32(codeblock_t *block, void *p, int host_reg);
void codegen_direct_write_ptr(codeblock_t *block, void *p, int host_reg);
#endif