Added recompiled register versions of FADD, FDIV, FDIVR, FMUL, FSUB and FSUBR.

This commit is contained in:
SarahW 2018-10-07 22:02:31 +01:00
commit 78996b3e5c
31 changed files with 1642 additions and 166 deletions

View file

@ -360,7 +360,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t
case 0xd8:
op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_d8_a32 : x86_dynarec_opcodes_d8_a16;
recomp_op_table = NULL;//recomp_opcodes_d8;
recomp_op_table = recomp_opcodes_d8;
opcode_shift = 3;
opcode_mask = 0x1f;
over = 1;
@ -397,7 +397,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t
break;
case 0xdc:
op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dc_a32 : x86_dynarec_opcodes_dc_a16;
recomp_op_table = NULL;//recomp_opcodes_dc;
recomp_op_table = recomp_opcodes_dc;
opcode_shift = 3;
opcode_mask = 0x1f;
over = 1;

View file

@ -1,9 +1,9 @@
//#ifdef __amd64__
//#include "codegen_x86-64.h"
#if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined WIN32 || defined _WIN32 || defined _WIN32
#include "codegen_backend_x86.h"
#elif defined __amd64__
#if defined __amd64__
#include "codegen_backend_x86-64.h"
#elif defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined WIN32 || defined _WIN32 || defined _WIN32
#include "codegen_backend_x86.h"
#elif defined __ARM_EABI__
#include "codegen_backend_arm.h"
#elif defined __aarch64__
@ -65,3 +65,4 @@ typedef int (*uOpFn)(codeblock_t *codeblock, struct uop_t *uop);
extern const uOpFn uop_handlers[];
extern int codegen_host_reg_list[CODEGEN_HOST_REGS];
extern int codegen_host_fp_reg_list[CODEGEN_HOST_FP_REGS];

View file

@ -6,6 +6,7 @@
#include "codegen_backend.h"
#include "codegen_backend_arm_defs.h"
#include "codegen_backend_arm_ops.h"
#include "codegen_reg.h"
#include "x86.h"
#if defined(__linux__) || defined(__APPLE__)
@ -35,6 +36,18 @@ int codegen_host_reg_list[CODEGEN_HOST_REGS] =
REG_R11,
};
int codegen_host_fp_reg_list[CODEGEN_HOST_FP_REGS] =
{
REG_D8,
REG_D9,
REG_D10,
REG_D11,
REG_D12,
REG_D13,
REG_D14,
REG_D15
};
static void build_load_routine(codeblock_t *block, int size)
{
uint32_t *branch_offset;
@ -220,7 +233,7 @@ void codegen_backend_prologue(codeblock_t *block)
host_arm_nop(block);
block_pos = BLOCK_EXIT_OFFSET; /*Exit code*/
host_arm_ADD_IMM(block, REG_HOST_SP, REG_HOST_SP, 0x20);
host_arm_ADD_IMM(block, REG_HOST_SP, REG_HOST_SP, 0x40);
host_arm_LDMIA_WB(block, REG_HOST_SP, REG_MASK_LOCAL | REG_MASK_PC);
while (block_pos != BLOCK_START)
host_arm_nop(block);
@ -228,13 +241,19 @@ void codegen_backend_prologue(codeblock_t *block)
/*Entry code*/
host_arm_STMDB_WB(block, REG_HOST_SP, REG_MASK_LOCAL | REG_MASK_LR);
host_arm_SUB_IMM(block, REG_HOST_SP, REG_HOST_SP, 0x20);
host_arm_SUB_IMM(block, REG_HOST_SP, REG_HOST_SP, 0x40);
host_arm_MOV_IMM(block, REG_CPUSTATE, (uint32_t)&cpu_state);
if (block->flags & CODEBLOCK_HAS_FPU)
{
host_arm_LDR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.TOP - (uintptr_t)&cpu_state);
host_arm_SUB_IMM(block, REG_TEMP, REG_TEMP, block->TOP);
host_arm_STR_IMM(block, REG_TEMP, REG_HOST_SP, IREG_TOP_diff_stack_offset);
}
}
void codegen_backend_epilogue(codeblock_t *block)
{
host_arm_ADD_IMM(block, REG_HOST_SP, REG_HOST_SP, 0x20);
host_arm_ADD_IMM(block, REG_HOST_SP, REG_HOST_SP, 0x40);
host_arm_LDMIA_WB(block, REG_HOST_SP, REG_MASK_LOCAL | REG_MASK_PC);
if (block_pos > ARM_LITERAL_POOL_OFFSET)

View file

@ -6,6 +6,7 @@
#include "codegen_backend.h"
#include "codegen_backend_arm64_defs.h"
#include "codegen_backend_arm64_ops.h"
#include "codegen_reg.h"
#include "x86.h"
#if defined(__linux__) || defined(__APPLE__)
@ -38,6 +39,18 @@ int codegen_host_reg_list[CODEGEN_HOST_REGS] =
REG_X28
};
int codegen_host_fp_reg_list[CODEGEN_HOST_FP_REGS] =
{
REG_V8,
REG_V9,
REG_V10,
REG_V11,
REG_V12,
REG_V13,
REG_V14,
REG_V15
};
static void build_load_routine(codeblock_t *block, int size)
{
uint32_t *branch_offset;
@ -237,7 +250,7 @@ void codegen_backend_prologue(codeblock_t *block)
host_arm64_NOP(block);
block_pos = BLOCK_EXIT_OFFSET; /*Exit code*/
host_arm64_LDP_POSTIDX_X(block, REG_X19, REG_X20, REG_SP, 48);
host_arm64_LDP_POSTIDX_X(block, REG_X19, REG_X20, REG_SP, 64);
host_arm64_LDP_POSTIDX_X(block, REG_X21, REG_X22, REG_SP, 16);
host_arm64_LDP_POSTIDX_X(block, REG_X23, REG_X24, REG_SP, 16);
host_arm64_LDP_POSTIDX_X(block, REG_X25, REG_X26, REG_SP, 16);
@ -255,15 +268,22 @@ void codegen_backend_prologue(codeblock_t *block)
host_arm64_STP_PREIDX_X(block, REG_X25, REG_X26, REG_SP, -16);
host_arm64_STP_PREIDX_X(block, REG_X23, REG_X24, REG_SP, -16);
host_arm64_STP_PREIDX_X(block, REG_X21, REG_X22, REG_SP, -16);
host_arm64_STP_PREIDX_X(block, REG_X19, REG_X20, REG_SP, -48);
host_arm64_STP_PREIDX_X(block, REG_X19, REG_X20, REG_SP, -64);
offset = add_literal_q(block, (uintptr_t)&cpu_state);
host_arm64_LDR_LITERAL_X(block, REG_CPUSTATE, offset);
if (block->flags & CODEBLOCK_HAS_FPU)
{
host_arm64_LDR_IMM_W(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.TOP - (uintptr_t)&cpu_state);
host_arm64_SUB_IMM(block, REG_TEMP, REG_TEMP, block->TOP);
host_arm64_STR_IMM_W(block, REG_TEMP, REG_SP, IREG_TOP_diff_stack_offset);
}
}
void codegen_backend_epilogue(codeblock_t *block)
{
host_arm64_LDP_POSTIDX_X(block, REG_X19, REG_X20, REG_SP, 48);
host_arm64_LDP_POSTIDX_X(block, REG_X19, REG_X20, REG_SP, 64);
host_arm64_LDP_POSTIDX_X(block, REG_X21, REG_X22, REG_SP, 16);
host_arm64_LDP_POSTIDX_X(block, REG_X23, REG_X24, REG_SP, 16);
host_arm64_LDP_POSTIDX_X(block, REG_X25, REG_X26, REG_SP, 16);

View file

@ -64,6 +64,39 @@
#define REG_X30 30
#define REG_XZR 31
#define REG_V0 0
#define REG_V1 1
#define REG_V2 2
#define REG_V3 3
#define REG_V4 4
#define REG_V5 5
#define REG_V6 6
#define REG_V7 7
#define REG_V8 8
#define REG_V9 9
#define REG_V10 10
#define REG_V11 11
#define REG_V12 12
#define REG_V13 13
#define REG_V14 14
#define REG_V15 15
#define REG_V16 16
#define REG_V17 17
#define REG_V18 18
#define REG_V19 19
#define REG_V20 20
#define REG_V21 21
#define REG_V22 22
#define REG_V23 23
#define REG_V24 24
#define REG_V25 25
#define REG_V26 26
#define REG_V27 27
#define REG_V28 28
#define REG_V29 29
#define REG_V30 30
#define REG_V31 31
#define REG_SP 31
#define REG_ARG0 REG_X0
@ -73,9 +106,11 @@
#define REG_CPUSTATE REG_X29
#define REG_TEMP REG_X7
#define REG_TEMP REG_X7
#define REG_TEMP2 REG_X6
#define CODEGEN_HOST_REGS 10
#define CODEGEN_HOST_FP_REGS 8
extern void *codegen_mem_load_byte;
extern void *codegen_mem_load_word;

View file

@ -48,6 +48,7 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val)
#define OPCODE_SHIFT 24
#define OPCODE_ADD_IMM (0x11 << OPCODE_SHIFT)
#define OPCODE_ADDX_IMM (0x91 << OPCODE_SHIFT)
#define OPCODE_B (0x14 << OPCODE_SHIFT)
#define OPCODE_BCOND (0x54 << OPCODE_SHIFT)
#define OPCODE_CBNZ (0xb5 << OPCODE_SHIFT)
#define OPCODE_CMN_IMM (0x31 << OPCODE_SHIFT)
@ -68,6 +69,7 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val)
#define OPCODE_BFI (0x0cc << 22)
#define OPCODE_LDR_IMM_W (0x2e5 << 22)
#define OPCODE_LDR_IMM_F64 (0x3f5 << 22)
#define OPCODE_LDRB_IMM_W (0x0e5 << 22)
#define OPCODE_LDRH_IMM (0x1e5 << 22)
#define OPCODE_LDP_POSTIDX_X (0x2a3 << 22)
@ -75,6 +77,7 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val)
#define OPCODE_STP_PREIDX_X (0x2a6 << 22)
#define OPCODE_STR_IMM_W (0x2e4 << 22)
#define OPCODE_STR_IMM_Q (0x3e4 << 22)
#define OPCODE_STR_IMM_F64 (0x3f4 << 22)
#define OPCODE_STRB_IMM (0x0e4 << 22)
#define OPCODE_STRH_IMM (0x1e4 << 22)
#define OPCODE_UBFX (0x14c << 22)
@ -99,10 +102,15 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val)
#define OPCODE_ASR (0x1ac02800)
#define OPCODE_BLR (0xd63f0000)
#define OPCODE_BR (0xd61f0000)
#define OPCODE_FADD_D (0x1e602800)
#define OPCODE_FDIV_D (0x1e601800)
#define OPCODE_FMUL_D (0x1e600800)
#define OPCODE_FSUB_D (0x1e603800)
#define OPCODE_LDR_REG (0xb8606800)
#define OPCODE_LDRB_REG (0x38606800)
#define OPCODE_LDRH_REG (0x78606800)
#define OPCODE_LDRX_REG_LSL3 (0xf8607800)
#define OPCODE_LDR_REG_F64_S (0xfc607800)
#define OPCODE_LSL (0x1ac02000)
#define OPCODE_LSR (0x1ac02400)
#define OPCODE_NOP (0xd503201f)
@ -110,6 +118,7 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val)
#define OPCODE_STR_REG (0xb8206800)
#define OPCODE_STRB_REG (0x38206800)
#define OPCODE_STRH_REG (0x78206800)
#define OPCODE_STR_REG_F64_S (0xfc207800)
#define DATPROC_SHIFT(sh) (sh << 10)
#define DATPROC_IMM_SHIFT(sh) (sh << 22)
@ -124,6 +133,7 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val)
#define IMMS(imms) ((imms) << 10)
#define OFFSET19(offset) (((offset >> 2) << 5) & 0x00ffffe0)
#define OFFSET26(offset) ((offset >> 2) & 0x03ffffff)
#define OFFSET12_B(offset) (offset << 10)
#define OFFSET12_H(offset) ((offset >> 1) << 10)
@ -146,6 +156,16 @@ static int offset_is_19bit(int offset)
return 1;
}
/*Returns true if offset fits into 26 bits*/
static int offset_is_26bit(int offset)
{
if (offset >= (1 << (25+2)))
return 0;
if (offset < -(1 << (25+2)))
return 0;
return 1;
}
int add_literal(codeblock_t *block, uint32_t data)
{
if (literal_offset >= 4096)
@ -296,6 +316,15 @@ void host_arm64_ASR(codeblock_t *block, int dst_reg, int src_n_reg, int shift_re
codegen_addlong(block, OPCODE_ASR | Rd(dst_reg) | Rn(src_n_reg) | Rm(shift_reg));
}
void host_arm64_B(codeblock_t *block, void *dest)
{
int offset = (uintptr_t)dest - (uintptr_t)&block->data[block_pos];
if (!offset_is_26bit(offset))
fatal("host_arm64_B - offset out of range %x\n", offset);
codegen_addlong(block, OPCODE_B | OFFSET26(offset));
}
void host_arm64_BFI(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width)
{
codegen_addlong(block, OPCODE_BFI | Rd(dst_reg) | Rn(src_reg) | IMMN(0) | IMMR((32 - lsb) & 31) | IMMS((width-1) & 31));
@ -461,6 +490,26 @@ void host_arm64_CMP_REG_LSL(codeblock_t *block, int src_n_reg, int src_m_reg, in
codegen_addlong(block, OPCODE_CMP_LSL | Rd(0x1f) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift));
}
void host_arm64_FADD_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg)
{
codegen_addlong(block, OPCODE_FADD_D | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg));
}
void host_arm64_FDIV_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg)
{
codegen_addlong(block, OPCODE_FDIV_D | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg));
}
void host_arm64_FMUL_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg)
{
codegen_addlong(block, OPCODE_FMUL_D | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg));
}
void host_arm64_FSUB_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg)
{
codegen_addlong(block, OPCODE_FSUB_D | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg));
}
void host_arm64_EOR_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data)
{
if (imm_data == 0xffff) /*Quick hack until proper immediate generation is written */
@ -515,6 +564,15 @@ void host_arm64_LDR_REG(codeblock_t *block, int dest_reg, int base_reg, int offs
codegen_addlong(block, OPCODE_LDR_REG | Rn(base_reg) | Rm(offset_reg) | Rt(dest_reg));
}
void host_arm64_LDR_IMM_F64(codeblock_t *block, int dest_reg, int base_reg, int offset)
{
codegen_addlong(block, OPCODE_LDR_IMM_F64 | OFFSET12_Q(offset) | Rn(base_reg) | Rt(dest_reg));
}
void host_arm64_LDR_REG_F64_S(codeblock_t *block, int dest_reg, int base_reg, int offset_reg)
{
codegen_addlong(block, OPCODE_LDR_REG_F64_S | Rn(base_reg) | Rm(offset_reg) | Rt(dest_reg));
}
void host_arm64_LDRB_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int offset)
{
if (!in_range12_b(offset))
@ -670,6 +728,15 @@ void host_arm64_STR_REG(codeblock_t *block, int src_reg, int base_reg, int offse
codegen_addlong(block, OPCODE_STR_REG | Rn(base_reg) | Rm(offset_reg) | Rt(src_reg));
}
void host_arm64_STR_IMM_F64(codeblock_t *block, int src_reg, int base_reg, int offset)
{
codegen_addlong(block, OPCODE_STR_IMM_F64 | OFFSET12_Q(offset) | Rn(base_reg) | Rt(src_reg));
}
void host_arm64_STR_REG_F64_S(codeblock_t *block, int src_reg, int base_reg, int offset_reg)
{
codegen_addlong(block, OPCODE_STR_REG_F64_S | Rn(base_reg) | Rm(offset_reg) | Rt(src_reg));
}
void host_arm64_STRB_IMM(codeblock_t *block, int dest_reg, int base_reg, int offset)
{
if (!in_range12_b(offset))

View file

@ -11,6 +11,8 @@ void host_arm64_ANDS_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_
void host_arm64_ASR(codeblock_t *block, int dst_reg, int src_n_reg, int shift_reg);
void host_arm64_B(codeblock_t *block, void *dest);
void host_arm64_BFI(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width);
void host_arm64_BLR(codeblock_t *block, int addr_reg);
@ -49,6 +51,11 @@ void host_arm64_CMP_REG_LSL(codeblock_t *block, int src_n_reg, int src_m_reg, in
void host_arm64_EOR_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data);
void host_arm64_EOR_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift);
void host_arm64_FADD_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_FDIV_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_FMUL_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_FSUB_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_LDP_POSTIDX_X(codeblock_t *block, int src_reg1, int src_reg2, int base_reg, int offset);
void host_arm64_LDR_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int offset);
@ -56,6 +63,9 @@ void host_arm64_LDR_LITERAL_W(codeblock_t *block, int dest_reg, int literal_offs
void host_arm64_LDR_LITERAL_X(codeblock_t *block, int dest_reg, int literal_offset);
void host_arm64_LDR_REG(codeblock_t *block, int dest_reg, int base_reg, int offset_reg);
void host_arm64_LDR_IMM_F64(codeblock_t *block, int dest_reg, int base_reg, int offset);
void host_arm64_LDR_REG_F64_S(codeblock_t *block, int dest_reg, int base_reg, int offset_reg);
void host_arm64_LDRB_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int offset);
void host_arm64_LDRB_REG(codeblock_t *block, int dest_reg, int base_reg, int offset_reg);
@ -91,6 +101,9 @@ void host_arm64_STR_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int of
void host_arm64_STR_IMM_Q(codeblock_t *block, int dest_reg, int base_reg, int offset);
void host_arm64_STR_REG(codeblock_t *block, int src_reg, int base_reg, int offset_reg);
void host_arm64_STR_IMM_F64(codeblock_t *block, int src_reg, int base_reg, int offset);
void host_arm64_STR_REG_F64_S(codeblock_t *block, int src_reg, int base_reg, int offset_reg);
void host_arm64_STRB_IMM(codeblock_t *block, int dest_reg, int base_reg, int offset);
void host_arm64_STRB_REG(codeblock_t *block, int src_reg, int base_reg, int offset_reg);

View file

@ -1,6 +1,8 @@
#ifdef __aarch64__
#include "ibm.h"
#include "x86.h"
#include "386_common.h"
#include "codegen.h"
#include "codegen_backend.h"
#include "codegen_backend_arm64_defs.h"
@ -15,6 +17,7 @@
#define REG_IS_W(size) (size == IREG_SIZE_W)
#define REG_IS_B(size) (size == IREG_SIZE_B)
#define REG_IS_BH(size) (size == IREG_SIZE_BH)
#define REG_IS_D(size) (size == IREG_SIZE_D)
static int codegen_ADD(codeblock_t *block, uop_t *uop)
{
@ -595,6 +598,85 @@ static int codegen_CMP_JZ_DEST(codeblock_t *block, uop_t *uop)
return 0;
}
static int codegen_FADD(codeblock_t *block, uop_t *uop)
{
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real);
if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b))
{
host_arm64_FADD_D(block, dest_reg, src_reg_a, src_reg_b);
}
else
fatal("codegen_FADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real);
return 0;
}
static int codegen_FDIV(codeblock_t *block, uop_t *uop)
{
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real);
if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b))
{
host_arm64_FDIV_D(block, dest_reg, src_reg_a, src_reg_b);
}
else
fatal("codegen_FDIV %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real);
return 0;
}
static int codegen_FMUL(codeblock_t *block, uop_t *uop)
{
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real);
if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b))
{
host_arm64_FMUL_D(block, dest_reg, src_reg_a, src_reg_b);
}
else
fatal("codegen_FMUL %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real);
return 0;
}
static int codegen_FSUB(codeblock_t *block, uop_t *uop)
{
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real);
if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b))
{
host_arm64_FSUB_D(block, dest_reg, src_reg_a, src_reg_b);
}
else
fatal("codegen_FSUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real);
return 0;
}
static int codegen_FP_ENTER(codeblock_t *block, uop_t *uop)
{
uint32_t *branch_ptr;
if (!in_range12_w((uintptr_t)&cr0 - (uintptr_t)&cpu_state))
fatal("codegen_FP_ENTER - out of range\n");
host_arm64_LDR_IMM_W(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cr0 - (uintptr_t)&cpu_state);
host_arm64_TST_IMM(block, REG_TEMP, 0xc);
branch_ptr = host_arm64_BEQ_(block);
host_arm64_mov_imm(block, REG_TEMP, uop->imm_data);
host_arm64_STR_IMM_W(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.oldpc - (uintptr_t)&cpu_state);
host_arm64_mov_imm(block, REG_ARG0, 7);
host_arm64_call(block, x86_int);
host_arm64_B(block, &block->data[BLOCK_EXIT_OFFSET]);
host_arm64_branch_set_offset(branch_ptr, &block->data[block_pos]);
return 0;
}
static int codegen_JMP(codeblock_t *block, uop_t *uop)
{
host_arm64_jump(block, (uintptr_t)uop->p);
@ -1561,6 +1643,13 @@ const uOpFn uop_handlers[UOP_MAX] =
[UOP_TEST_JNS_DEST & UOP_MASK] = codegen_TEST_JNS_DEST,
[UOP_TEST_JS_DEST & UOP_MASK] = codegen_TEST_JS_DEST,
[UOP_FP_ENTER & UOP_MASK] = codegen_FP_ENTER,
[UOP_FADD & UOP_MASK] = codegen_FADD,
[UOP_FDIV & UOP_MASK] = codegen_FDIV,
[UOP_FMUL & UOP_MASK] = codegen_FMUL,
[UOP_FSUB & UOP_MASK] = codegen_FSUB
};
void codegen_direct_read_8(codeblock_t *block, int host_reg, void *p)
@ -1584,6 +1673,21 @@ void codegen_direct_read_32(codeblock_t *block, int host_reg, void *p)
else
fatal("codegen_direct_read_32 - not in range\n");
}
void codegen_direct_read_double(codeblock_t *block, int host_reg, void *p)
{
if (in_range12_q((uintptr_t)p - (uintptr_t)&cpu_state))
host_arm64_LDR_IMM_F64(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state);
else
fatal("codegen_direct_read_double - not in range\n");
}
void codegen_direct_read_st_double(codeblock_t *block, int host_reg, void *base, int reg_idx)
{
host_arm64_LDR_IMM_W(block, REG_TEMP, REG_SP, IREG_TOP_diff_stack_offset);
host_arm64_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx);
host_arm64_ADD_IMM(block, REG_TEMP2, REG_CPUSTATE, (uintptr_t)base - (uintptr_t)&cpu_state);
host_arm64_AND_IMM(block, REG_TEMP, REG_TEMP, 7);
host_arm64_LDR_REG_F64_S(block, host_reg, REG_TEMP2, REG_TEMP);
}
void codegen_direct_write_8(codeblock_t *block, void *p, int host_reg)
{
@ -1606,6 +1710,29 @@ void codegen_direct_write_32(codeblock_t *block, void *p, int host_reg)
else
fatal("codegen_direct_write_32 - not in range\n");
}
void codegen_direct_write_st_8(codeblock_t *block, void *base, int reg_idx, int host_reg)
{
host_arm64_LDR_IMM_W(block, REG_TEMP, REG_SP, IREG_TOP_diff_stack_offset);
host_arm64_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx);
host_arm64_ADD_IMM(block, REG_TEMP2, REG_CPUSTATE, (uintptr_t)base - (uintptr_t)&cpu_state);
host_arm64_AND_IMM(block, REG_TEMP, REG_TEMP, 7);
host_arm64_STRB_REG(block, host_reg, REG_TEMP2, REG_TEMP);
}
void codegen_direct_write_double(codeblock_t *block, void *p, int host_reg)
{
if (in_range12_q((uintptr_t)p - (uintptr_t)&cpu_state))
host_arm64_STR_IMM_F64(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state);
else
fatal("codegen_direct_write_double - not in range\n");
}
void codegen_direct_write_st_double(codeblock_t *block, void *base, int reg_idx, int host_reg)
{
host_arm64_LDR_IMM_W(block, REG_TEMP, REG_SP, IREG_TOP_diff_stack_offset);
host_arm64_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx);
host_arm64_ADD_IMM(block, REG_TEMP2, REG_CPUSTATE, (uintptr_t)base - (uintptr_t)&cpu_state);
host_arm64_AND_IMM(block, REG_TEMP, REG_TEMP, 7);
host_arm64_STR_REG_F64_S(block, host_reg, REG_TEMP2, REG_TEMP);
}
void codegen_direct_write_ptr(codeblock_t *block, void *p, int host_reg)
{

View file

@ -24,6 +24,23 @@
#define REG_TEMP REG_R3
#define REG_D0 0
#define REG_D1 1
#define REG_D2 2
#define REG_D3 3
#define REG_D4 4
#define REG_D5 5
#define REG_D6 6
#define REG_D7 7
#define REG_D8 8
#define REG_D9 9
#define REG_D10 10
#define REG_D11 11
#define REG_D12 12
#define REG_D13 13
#define REG_D14 14
#define REG_D15 15
#define REG_MASK_R0 (1 << REG_R0)
#define REG_MASK_R1 (1 << REG_R1)
#define REG_MASK_R2 (1 << REG_R2)
@ -45,6 +62,7 @@
REG_MASK_R8 | REG_MASK_R9 | REG_MASK_R10 | REG_MASK_R11)
#define CODEGEN_HOST_REGS 7
#define CODEGEN_HOST_FP_REGS 8
extern void *codegen_mem_load_byte;
extern void *codegen_mem_load_word;

View file

@ -97,6 +97,12 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val)
#define OPCODE_USUB16 0xe6500f70
#define OPCODE_UXTB 0xe6ef0070
#define OPCODE_UXTH 0xe6ff0070
#define OPCODE_VADD 0xee300b00
#define OPCODE_VDIV 0xee800b00
#define OPCODE_VLDR 0xed900b00
#define OPCODE_VMUL 0xee200b00
#define OPCODE_VSTR 0xed800b00
#define OPCODE_VSUB 0xee300b40
#define B_OFFSET(x) (((x) >> 2) & 0xffffff)
@ -724,4 +730,33 @@ void host_arm_UXTH(codeblock_t *block, int dst_reg, int src_reg, int rotate)
codegen_addlong(block, OPCODE_UXTH | Rd(dst_reg) | Rm(src_reg) | UXTB_ROTATE(rotate));
}
void host_arm_VADD_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m)
{
codegen_addlong(block, COND_AL | OPCODE_VADD | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m));
}
void host_arm_VDIV_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m)
{
codegen_addlong(block, COND_AL | OPCODE_VDIV | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m));
}
void host_arm_VLDR_D(codeblock_t *block, int dest_reg, int base_reg, int offset)
{
if ((offset > 1020) || (offset & 3))
fatal("VLDR bad offset %i\n", offset);
codegen_addlong(block, COND_AL | OPCODE_VLDR | Rd(dest_reg) | Rn(base_reg) | (offset >> 2));
}
void host_arm_VMUL_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m)
{
codegen_addlong(block, COND_AL | OPCODE_VMUL | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m));
}
void host_arm_VSTR_D(codeblock_t *block, int src_reg, int base_reg, int offset)
{
if ((offset > 1020) || (offset & 3))
fatal("VSTR bad offset %i\n", offset);
codegen_addlong(block, COND_AL | OPCODE_VSTR | Rd(src_reg) | Rn(base_reg) | (offset >> 2));
}
void host_arm_VSUB_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m)
{
codegen_addlong(block, COND_AL | OPCODE_VSUB | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m));
}
#endif

View file

@ -113,3 +113,10 @@ void host_arm_USUB16(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg
void host_arm_UXTB(codeblock_t *block, int dst_reg, int src_reg, int rotate);
void host_arm_UXTH(codeblock_t *block, int dst_reg, int src_reg, int rotate);
void host_arm_VADD_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VDIV_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VLDR_D(codeblock_t *block, int dest_reg, int base_reg, int offset);
void host_arm_VMUL_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VSTR_D(codeblock_t *block, int src_reg, int base_reg, int offset);
void host_arm_VSUB_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);

View file

@ -1,6 +1,8 @@
#ifdef __ARM_EABI__
#include "ibm.h"
#include "x86.h"
#include "386_common.h"
#include "codegen.h"
#include "codegen_backend.h"
#include "codegen_backend_arm_defs.h"
@ -73,6 +75,7 @@ void host_arm_nop(codeblock_t *block)
#define REG_IS_W(size) (size == IREG_SIZE_W)
#define REG_IS_B(size) (size == IREG_SIZE_B)
#define REG_IS_BH(size) (size == IREG_SIZE_BH)
#define REG_IS_D(size) (size == IREG_SIZE_D)
static int codegen_ADD(codeblock_t *block, uop_t *uop)
{
@ -669,6 +672,85 @@ static int codegen_CMP_JZ_DEST(codeblock_t *block, uop_t *uop)
return 0;
}
static int codegen_FADD(codeblock_t *block, uop_t *uop)
{
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real);
if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b))
{
host_arm_VADD_D(block, dest_reg, src_reg_a, src_reg_b);
}
else
fatal("codegen_FADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real);
return 0;
}
static int codegen_FDIV(codeblock_t *block, uop_t *uop)
{
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real);
if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b))
{
host_arm_VDIV_D(block, dest_reg, src_reg_a, src_reg_b);
}
else
fatal("codegen_FDIV %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real);
return 0;
}
static int codegen_FMUL(codeblock_t *block, uop_t *uop)
{
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real);
if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b))
{
host_arm_VMUL_D(block, dest_reg, src_reg_a, src_reg_b);
}
else
fatal("codegen_FMUL %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real);
return 0;
}
static int codegen_FSUB(codeblock_t *block, uop_t *uop)
{
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real);
if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b))
{
host_arm_VSUB_D(block, dest_reg, src_reg_a, src_reg_b);
}
else
fatal("codegen_FSUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real);
return 0;
}
static int codegen_FP_ENTER(codeblock_t *block, uop_t *uop)
{
uint32_t *branch_ptr;
if (!in_range(&cr0, &cpu_state))
fatal("codegen_FP_ENTER - out of range\n");
host_arm_LDR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cr0 - (uintptr_t)&cpu_state);
host_arm_TST_IMM(block, REG_TEMP, 0xc);
branch_ptr = host_arm_BEQ_(block);
host_arm_MOV_IMM(block, REG_TEMP, uop->imm_data);
host_arm_STR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.oldpc - (uintptr_t)&cpu_state);
host_arm_MOV_IMM(block, REG_ARG0, 7);
host_arm_call(block, x86_int);
host_arm_B(block, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]);
*branch_ptr |= ((((uintptr_t)&block->data[block_pos] - (uintptr_t)branch_ptr) - 8) & 0x3fffffc) >> 2;
return 0;
}
static int codegen_JMP(codeblock_t *block, uop_t *uop)
{
host_arm_B(block, (uintptr_t)uop->p);
@ -1641,6 +1723,13 @@ const uOpFn uop_handlers[UOP_MAX] =
[UOP_TEST_JNS_DEST & UOP_MASK] = codegen_TEST_JNS_DEST,
[UOP_TEST_JS_DEST & UOP_MASK] = codegen_TEST_JS_DEST,
[UOP_FP_ENTER & UOP_MASK] = codegen_FP_ENTER,
[UOP_FADD & UOP_MASK] = codegen_FADD,
[UOP_FDIV & UOP_MASK] = codegen_FDIV,
[UOP_FMUL & UOP_MASK] = codegen_FMUL,
[UOP_FSUB & UOP_MASK] = codegen_FSUB
};
void codegen_direct_read_16(codeblock_t *block, int host_reg, void *p)
@ -1660,6 +1749,18 @@ void codegen_direct_read_32(codeblock_t *block, int host_reg, void *p)
else
fatal("codegen_direct_read_32 - not in range\n");
}
void codegen_direct_read_double(codeblock_t *block, int host_reg, void *p)
{
host_arm_VLDR_D(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state);
}
void codegen_direct_read_st_double(codeblock_t *block, int host_reg, void *base, int reg_idx)
{
host_arm_LDR_IMM(block, REG_TEMP, REG_HOST_SP, IREG_TOP_diff_stack_offset);
host_arm_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx);
host_arm_AND_IMM(block, REG_TEMP, REG_TEMP, 7);
host_arm_ADD_REG_LSL(block, REG_TEMP, REG_CPUSTATE, REG_TEMP, 3);
host_arm_VLDR_D(block, host_reg, REG_TEMP, (uintptr_t)base - (uintptr_t)&cpu_state);
}
void codegen_direct_write_8(codeblock_t *block, void *p, int host_reg)
{
@ -1685,6 +1786,26 @@ void codegen_direct_write_32(codeblock_t *block, void *p, int host_reg)
else
fatal("codegen_direct_write_32 - not in range\n");
}
void codegen_direct_write_st_8(codeblock_t *block, void *base, int reg_idx, int host_reg)
{
host_arm_LDR_IMM(block, REG_TEMP, REG_HOST_SP, IREG_TOP_diff_stack_offset);
host_arm_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx);
host_arm_AND_IMM(block, REG_TEMP, REG_TEMP, 7);
host_arm_ADD_REG_LSL(block, REG_TEMP, REG_CPUSTATE, REG_TEMP, 3);
host_arm_STRB_IMM(block, host_reg, REG_TEMP, (uintptr_t)base - (uintptr_t)&cpu_state);
}
void codegen_direct_write_double(codeblock_t *block, void *p, int host_reg)
{
host_arm_VSTR_D(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state);
}
void codegen_direct_write_st_double(codeblock_t *block, void *base, int reg_idx, int host_reg)
{
host_arm_LDR_IMM(block, REG_TEMP, REG_HOST_SP, IREG_TOP_diff_stack_offset);
host_arm_ADD_IMM(block, REG_TEMP, REG_TEMP, reg_idx);
host_arm_AND_IMM(block, REG_TEMP, REG_TEMP, 7);
host_arm_ADD_REG_LSL(block, REG_TEMP, REG_CPUSTATE, REG_TEMP, 3);
host_arm_VSTR_D(block, host_reg, REG_TEMP, (uintptr_t)base - (uintptr_t)&cpu_state);
}
void codegen_direct_write_ptr(codeblock_t *block, void *p, int host_reg)
{

View file

@ -5,6 +5,7 @@
#include "codegen_backend.h"
#include "codegen_backend_x86-64_defs.h"
#include "codegen_backend_x86-64_ops.h"
#include "codegen_reg.h"
#include "x86.h"
#if defined(__linux__) || defined(__APPLE__)
@ -30,6 +31,17 @@ int codegen_host_reg_list[CODEGEN_HOST_REGS] =
REG_EDX
};
int codegen_host_fp_reg_list[CODEGEN_HOST_FP_REGS] =
{
REG_XMM0,
REG_XMM1,
REG_XMM2,
REG_XMM3,
REG_XMM4,
REG_XMM5,
REG_XMM6
};
static void *mem_abrt_rout;
static void build_load_routine(codeblock_t *block, int size)
@ -286,10 +298,16 @@ void codegen_backend_prologue(codeblock_t *block)
addbyte(0x48); /*SUBL $40,%rsp*/
addbyte(0x83);
addbyte(0xEC);
addbyte(0x28);
addbyte(0x38);
addbyte(0x48); /*MOVL RBP, &cpu_state*/
addbyte(0xBD);
addquad(((uintptr_t)&cpu_state) + 128);
if (block->flags & CODEBLOCK_HAS_FPU)
{
host_x86_MOV32_REG_ABS(block, REG_EAX, &cpu_state.TOP);
host_x86_SUB32_REG_IMM(block, REG_EAX, REG_EAX, block->TOP);
host_x86_MOV32_BASE_OFFSET_REG(block, REG_ESP, IREG_TOP_diff_stack_offset, REG_EAX);
}
}
void codegen_backend_epilogue(codeblock_t *block)
@ -297,7 +315,7 @@ void codegen_backend_epilogue(codeblock_t *block)
addbyte(0x48); /*ADDL $40,%rsp*/
addbyte(0x83);
addbyte(0xC4);
addbyte(0x28);
addbyte(0x38);
addbyte(0x41); /*POP R15*/
addbyte(0x5f);
addbyte(0x41); /*POP R14*/
@ -336,7 +354,7 @@ void codegen_backend_epilogue(codeblock_t *block)
addbyte(0x48); /*ADDL $40,%rsp*/
addbyte(0x83);
addbyte(0xC4);
addbyte(0x28);
addbyte(0x38);
addbyte(0x41); /*POP R15*/
addbyte(0x5f);
addbyte(0x41); /*POP R14*/

View file

@ -1,3 +1,5 @@
#include "codegen_backend_x86-64_defs.h"
#define BLOCK_SIZE 0x4000
#define BLOCK_MASK 0x3fff
#define BLOCK_START 0

View file

@ -32,3 +32,25 @@
#define REG_R13 13
#define REG_R14 14
#define REG_R15 15
#define REG_XMM0 0
#define REG_XMM1 1
#define REG_XMM2 2
#define REG_XMM3 3
#define REG_XMM4 4
#define REG_XMM5 5
#define REG_XMM6 6
#define REG_XMM7 7
#define REG_XMM_TEMP REG_XMM7
#define CODEGEN_HOST_REGS 3
#define CODEGEN_HOST_FP_REGS 7
extern void *codegen_mem_load_byte;
extern void *codegen_mem_load_word;
extern void *codegen_mem_load_long;
extern void *codegen_mem_store_byte;
extern void *codegen_mem_store_word;
extern void *codegen_mem_store_long;

View file

@ -212,6 +212,11 @@ void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int
codegen_addbyte2(block, 0x01, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*ADD dst_reg, src_reg_b*/
}
void host_x86_ADDSD_REG_REG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_addbyte4(block, 0xf2, 0x0f, 0x58, 0xc0 | src_reg | (dst_reg << 3));
}
void host_x86_AND8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data)
{
if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8))
@ -336,6 +341,11 @@ void host_x86_CMP32_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b)
codegen_addbyte2(block, 0x39, 0xc0 | src_reg_a | (src_reg_b << 3)); /*CMP src_reg_a, src_reg_b*/
}
void host_x86_DIVSD_REG_REG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_addbyte4(block, 0xf2, 0x0f, 0x5e, 0xc0 | src_reg | (dst_reg << 3));
}
void host_x86_JMP(codeblock_t *block, void *p)
{
jmp(block, (uintptr_t)p);
@ -599,6 +609,21 @@ void host_x86_MOV64_ABS_REG(codeblock_t *block, void *p, int src_reg)
}
}
void host_x86_MOV8_ABS_REG_REG_SHIFT_REG(codeblock_t *block, uint32_t addr, int base_reg, int index_reg, int shift, int src_reg)
{
if ((src_reg & 8) || (base_reg & 8) | (index_reg & 8))
fatal("host_x86_MOV8_BASE_INDEX_REG reg & 8\n");
if (addr < 0x80 || addr >= 0xffffff80)
{
codegen_addbyte4(block, 0x88, 0x44 | (src_reg << 3), base_reg | (index_reg << 3) | (shift << 6), addr & 0xff); /*MOV addr[base_reg + idx_reg << shift], src_reg*/
}
else
{
codegen_addbyte3(block, 0x88, 0x84 | (src_reg << 3), base_reg | (index_reg << 3) | (shift << 6)); /*MOV addr[base_reg + idx_reg << shift], src_reg*/
codegen_addlong(block, addr);
}
}
void host_x86_MOV8_BASE_INDEX_REG(codeblock_t *block, int base_reg, int index_reg, int src_reg)
{
if ((src_reg & 8) || (base_reg & 8) | (index_reg & 8))
@ -812,6 +837,86 @@ void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_d
}
}
void host_x86_MOVQ_ABS_REG(codeblock_t *block, void *p, int src_reg)
{
int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
if (src_reg & 8)
fatal("host_x86_MOVQ_ABS_REG reg & 8\n");
if (offset >= -128 && offset < 127)
{
codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x45 | (src_reg << 3)); /*MOVQ offset[EBP], src_reg*/
codegen_addbyte(block, offset);
}
else
{
if ((uintptr_t)p >> 32)
fatal("host_x86_MOVQ_ABS_REG - out of range %p\n", p);
codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x04 | (src_reg << 3)); /*MOVQ [p], src_reg*/
codegen_addbyte(block, 0x25);
codegen_addlong(block, (uint32_t)(uintptr_t)p);
}
}
void host_x86_MOVQ_ABS_REG_REG_SHIFT_REG(codeblock_t *block, uint32_t addr, int src_reg_a, int src_reg_b, int shift, int src_reg)
{
if ((src_reg & 8) || (src_reg_a & 8) || (src_reg_b & 8))
fatal("host_x86_MOVQ_ABS_REG_REG_SHIFT_REG - bad reg\n");
codegen_addbyte3(block, 0x66, 0x0f, 0xd6); /*MOVQ addr[src_reg_a + src_reg_b << shift], XMMx*/
if (addr < 0x80 || addr >= 0xffffff80)
{
codegen_addbyte3(block, 0x44 | (src_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6), addr & 0xff);
}
else
{
codegen_addbyte2(block, 0x84 | (src_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6));
codegen_addlong(block, addr);
}
}
void host_x86_MOVQ_REG_ABS(codeblock_t *block, int dst_reg, void *p)
{
int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
if (dst_reg & 8)
fatal("host_x86_MOVQ_REG_ABS reg & 8\n");
if (offset >= -128 && offset < 127)
{
codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x45 | (dst_reg << 3)); /*MOVQ offset[EBP], src_reg*/
codegen_addbyte(block, offset);
}
else
{
if ((uintptr_t)p >> 32)
fatal("host_x86_MOVQ_REG_ABS - out of range %p\n", p);
codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x04 | (dst_reg << 3)); /*MOVQ [p], src_reg*/
codegen_addbyte(block, 0x25);
codegen_addlong(block, (uint32_t)(uintptr_t)p);
}
}
void host_x86_MOVQ_REG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32_t addr, int src_reg_a, int src_reg_b, int shift)
{
if ((dst_reg & 8) || (src_reg_a & 8) || (src_reg_b & 8))
fatal("host_x86_MOVQ_REG_ABS_REG_REG_SHIFT - bad reg\n");
codegen_addbyte3(block, 0xf3, 0x0f, 0x7e); /*MOVQ XMMx, addr[src_reg_a + src_reg_b << shift]*/
if (addr < 0x80 || addr >= 0xffffff80)
{
codegen_addbyte3(block, 0x44 | (dst_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6), addr & 0xff);
}
else
{
codegen_addbyte2(block, 0x84 | (dst_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6));
codegen_addlong(block, addr);
}
}
void host_x86_MOVQ_REG_REG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0xc0 | src_reg | (dst_reg << 3)); /*MOVQ dst_reg, src_reg*/
}
void host_x86_MOVSX_REG_16_8(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_addbyte4(block, 0x66, 0x0f, 0xbe, 0xc0 | (dst_reg << 3) | src_reg); /*MOVSX dst_reg, src_reg*/
@ -874,6 +979,11 @@ void host_x86_MOVZX_REG_ABS_32_8(codeblock_t *block, int dst_reg, void *p)
fatal("host_x86_MOVZX_REG_ABS_32_8 - bad offset %i\n", offset);
}
void host_x86_MULSD_REG_REG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_addbyte4(block, 0xf2, 0x0f, 0x59, 0xc0 | src_reg | (dst_reg << 3));
}
void host_x86_OR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data)
{
if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8))
@ -1153,6 +1263,11 @@ void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int
codegen_addbyte2(block, 0x29, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*SUB dst_reg, src_reg_b*/
}
void host_x86_SUBSD_REG_REG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_addbyte4(block, 0xf2, 0x0f, 0x5c, 0xc0 | src_reg | (dst_reg << 3));
}
#define MODRM_MOD_REG(rm, reg) (0xc0 | reg | (rm << 3))
void host_x86_TEST8_REG(codeblock_t *block, int src_host_reg, int dst_host_reg)

View file

@ -7,6 +7,8 @@ void host_x86_ADD8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int s
void host_x86_ADD16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
void host_x86_ADDSD_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_AND8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data);
void host_x86_AND16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data);
void host_x86_AND32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data);
@ -25,6 +27,8 @@ void host_x86_CMP8_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b);
void host_x86_CMP16_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b);
void host_x86_CMP32_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b);
void host_x86_DIVSD_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_JMP(codeblock_t *block, void *p);
void host_x86_JNZ(codeblock_t *block, void *p);
@ -60,6 +64,8 @@ void host_x86_MOV16_ABS_REG(codeblock_t *block, void *p, int src_reg);
void host_x86_MOV32_ABS_REG(codeblock_t *block, void *p, int src_reg);
void host_x86_MOV64_ABS_REG(codeblock_t *block, void *p, int src_reg);
void host_x86_MOV8_ABS_REG_REG_SHIFT_REG(codeblock_t *block, uint32_t addr, int base_reg, int index_reg, int shift, int src_reg);
void host_x86_MOV8_BASE_INDEX_REG(codeblock_t *block, int dst_reg, int base_reg, int index_reg);
void host_x86_MOV16_BASE_INDEX_REG(codeblock_t *block, int dst_reg, int base_reg, int index_reg);
void host_x86_MOV32_BASE_INDEX_REG(codeblock_t *block, int dst_reg, int base_reg, int index_reg);
@ -86,6 +92,13 @@ void host_x86_MOV32_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_data);
void host_x86_MOVQ_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MOVQ_REG_ABS(codeblock_t *block, int dst_reg, void *p);
void host_x86_MOVQ_REG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32_t addr, int src_reg_a, int src_reg_b, int shift);
void host_x86_MOVQ_ABS_REG(codeblock_t *block, void *p, int src_reg);
void host_x86_MOVQ_ABS_REG_REG_SHIFT_REG(codeblock_t *block, uint32_t addr, int src_reg_a, int src_reg_b, int shift, int src_reg);
void host_x86_MOVSX_REG_16_8(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MOVSX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MOVSX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg);
@ -101,6 +114,8 @@ void host_x86_MOVZX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MOVZX_REG_ABS_32_8(codeblock_t *block, int dst_reg, void *p);
void host_x86_MULSD_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_OR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data);
void host_x86_OR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data);
void host_x86_OR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data);
@ -148,6 +163,8 @@ void host_x86_SUB8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int s
void host_x86_SUB16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
void host_x86_SUBSD_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_TEST8_REG(codeblock_t *block, int src_host_reg, int dst_host_reg);
void host_x86_TEST16_REG(codeblock_t *block, int src_host_reg, int dst_host_reg);
void host_x86_TEST32_REG(codeblock_t *block, int src_reg, int dst_reg);

View file

@ -1,6 +1,8 @@
#ifdef __amd64__
#include "ibm.h"
#include "x86.h"
#include "386_common.h"
#include "codegen.h"
#include "codegen_backend.h"
#include "codegen_backend_x86-64_defs.h"
@ -18,6 +20,7 @@
#define REG_IS_W(size) (size == IREG_SIZE_W)
#define REG_IS_B(size) (size == IREG_SIZE_B || size == IREG_SIZE_BH)
#define REG_IS_BH(size) (size == IREG_SIZE_BH)
#define REG_IS_D(size) (size == IREG_SIZE_D)
static int codegen_ADD(codeblock_t *block, uop_t *uop)
{
@ -524,6 +527,95 @@ static int codegen_CMP_JZ_DEST(codeblock_t *block, uop_t *uop)
return 0;
}
static int codegen_FADD(codeblock_t *block, uop_t *uop)
{
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real);
if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b) && dest_reg == src_reg_a)
{
host_x86_ADDSD_REG_REG(block, dest_reg, src_reg_b);
}
else
fatal("codegen_FADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real);
return 0;
}
static int codegen_FDIV(codeblock_t *block, uop_t *uop)
{
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real);
if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b) && dest_reg == src_reg_a)
{
host_x86_DIVSD_REG_REG(block, dest_reg, src_reg_b);
}
else if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b))
{
host_x86_MOVQ_REG_REG(block, REG_XMM_TEMP, src_reg_a);
host_x86_DIVSD_REG_REG(block, REG_XMM_TEMP, src_reg_b);
host_x86_MOVQ_REG_REG(block, dest_reg, REG_XMM_TEMP);
}
else
fatal("codegen_FDIV %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real);
return 0;
}
static int codegen_FMUL(codeblock_t *block, uop_t *uop)
{
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real);
if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b) && dest_reg == src_reg_a)
{
host_x86_MULSD_REG_REG(block, dest_reg, src_reg_b);
}
else
fatal("codegen_FMUL %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real);
return 0;
}
static int codegen_FSUB(codeblock_t *block, uop_t *uop)
{
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real);
if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b) && dest_reg == src_reg_a)
{
host_x86_SUBSD_REG_REG(block, dest_reg, src_reg_b);
}
else if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b))
{
host_x86_MOVQ_REG_REG(block, REG_XMM_TEMP, src_reg_a);
host_x86_SUBSD_REG_REG(block, REG_XMM_TEMP, src_reg_b);
host_x86_MOVQ_REG_REG(block, dest_reg, REG_XMM_TEMP);
}
else
fatal("codegen_FSUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real);
return 0;
}
static int codegen_FP_ENTER(codeblock_t *block, uop_t *uop)
{
uint8_t *branch_offset;
host_x86_MOV32_REG_ABS(block, REG_ECX, &cr0);
host_x86_TEST32_REG_IMM(block, REG_ECX, 0xc);
branch_offset = host_x86_JZ_short(block);
host_x86_MOV32_ABS_IMM(block, &cpu_state.oldpc, uop->imm_data);
#if WIN64
host_x86_MOV32_REG_IMM(block, REG_ECX, 7);
#else
host_x86_MOV32_REG_IMM(block, REG_EDI, 7);
#endif
host_x86_CALL(block, x86_int);
host_x86_JMP(block, &block->data[BLOCK_EXIT_OFFSET]);
*branch_offset = (uint8_t)((uintptr_t)&block->data[block_pos] - (uintptr_t)branch_offset) - 1;
return 0;
}
static int codegen_JMP(codeblock_t *block, uop_t *uop)
{
host_x86_JMP(block, uop->p);
@ -1346,6 +1438,13 @@ const uOpFn uop_handlers[UOP_MAX] =
[UOP_TEST_JNS_DEST & UOP_MASK] = codegen_TEST_JNS_DEST,
[UOP_TEST_JS_DEST & UOP_MASK] = codegen_TEST_JS_DEST,
[UOP_FP_ENTER & UOP_MASK] = codegen_FP_ENTER,
[UOP_FADD & UOP_MASK] = codegen_FADD,
[UOP_FDIV & UOP_MASK] = codegen_FDIV,
[UOP_FMUL & UOP_MASK] = codegen_FMUL,
[UOP_FSUB & UOP_MASK] = codegen_FSUB
};
void codegen_direct_read_16(codeblock_t *block, int host_reg, void *p)
@ -1356,6 +1455,19 @@ void codegen_direct_read_32(codeblock_t *block, int host_reg, void *p)
{
host_x86_MOV32_REG_ABS(block, host_reg, p);
}
void codegen_direct_read_double(codeblock_t *block, int host_reg, void *p)
{
host_x86_MOVQ_REG_ABS(block, host_reg, p);
}
void codegen_direct_read_st_double(codeblock_t *block, int host_reg, void *base, int reg_idx)
{
int offset = (uintptr_t)base - (((uintptr_t)&cpu_state) + 128);
host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_RSP, IREG_TOP_diff_stack_offset);
host_x86_ADD32_REG_IMM(block, REG_ECX, REG_ECX, reg_idx);
host_x86_AND32_REG_IMM(block, REG_ECX, REG_ECX, 7);
host_x86_MOVQ_REG_ABS_REG_REG_SHIFT(block, host_reg, offset, REG_RBP, REG_ECX, 3);
}
void codegen_direct_write_8(codeblock_t *block, void *p, int host_reg)
{
@ -1369,6 +1481,28 @@ void codegen_direct_write_32(codeblock_t *block, void *p, int host_reg)
{
host_x86_MOV32_ABS_REG(block, p, host_reg);
}
void codegen_direct_write_st_8(codeblock_t *block, void *base, int reg_idx, int host_reg)
{
int offset = (uintptr_t)base - (((uintptr_t)&cpu_state) + 128);
host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_RSP, IREG_TOP_diff_stack_offset);
host_x86_ADD32_REG_IMM(block, REG_ECX, REG_ECX, reg_idx);
host_x86_AND32_REG_IMM(block, REG_ECX, REG_ECX, 7);
host_x86_MOV8_ABS_REG_REG_SHIFT_REG(block, offset, REG_RBP, REG_ECX, 0, host_reg);
}
void codegen_direct_write_double(codeblock_t *block, void *p, int host_reg)
{
host_x86_MOVQ_ABS_REG(block, p, host_reg);
}
void codegen_direct_write_st_double(codeblock_t *block, void *base, int reg_idx, int host_reg)
{
int offset = (uintptr_t)base - (((uintptr_t)&cpu_state) + 128);
host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_RSP, IREG_TOP_diff_stack_offset);
host_x86_ADD32_REG_IMM(block, REG_ECX, REG_ECX, reg_idx);
host_x86_AND32_REG_IMM(block, REG_ECX, REG_ECX, 7);
host_x86_MOVQ_ABS_REG_REG_SHIFT_REG(block, offset, REG_RBP, REG_ECX, 3, host_reg);
}
void codegen_direct_write_ptr(codeblock_t *block, void *p, int host_reg)
{

View file

@ -5,6 +5,7 @@
#include "codegen_backend.h"
#include "codegen_backend_x86_defs.h"
#include "codegen_backend_x86_ops.h"
#include "codegen_reg.h"
#include "x86.h"
#if defined(__linux__) || defined(__APPLE__)
@ -30,12 +31,23 @@ int codegen_host_reg_list[CODEGEN_HOST_REGS] =
REG_EDX
};
int codegen_host_fp_reg_list[CODEGEN_HOST_FP_REGS] =
{
REG_XMM0,
REG_XMM1,
REG_XMM2,
REG_XMM3,
REG_XMM4,
REG_XMM5,
REG_XMM6
};
static void *mem_abrt_rout;
static void build_load_routine(codeblock_t *block, int size)
{
uint8_t *branch_offset;
uint8_t *misaligned_offset;
uint8_t *misaligned_offset = NULL;
/*In - ESI = address
Out - ECX = data, ESI = abrt*/
@ -107,7 +119,7 @@ static void build_load_routine(codeblock_t *block, int size)
static void build_store_routine(codeblock_t *block, int size)
{
uint8_t *branch_offset;
uint8_t *misaligned_offset;
uint8_t *misaligned_offset = NULL;
/*In - ECX = data, ESI = address
Out - ESI = abrt
@ -253,18 +265,24 @@ void codegen_backend_prologue(codeblock_t *block)
addbyte(0x55); /*PUSH EBP*/
addbyte(0x56); /*PUSH ESI*/
addbyte(0x57); /*PUSH EDI*/
addbyte(0x83); /*SUBL $32,%esp*/
addbyte(0x83); /*SUBL $64,%esp*/
addbyte(0xEC);
addbyte(0x20);
addbyte(0x40);
addbyte(0xBD); /*MOVL EBP, &cpu_state*/
addlong(((uintptr_t)&cpu_state) + 128);
if (block->flags & CODEBLOCK_HAS_FPU)
{
host_x86_MOV32_REG_ABS(block, REG_EAX, &cpu_state.TOP);
host_x86_SUB32_REG_IMM(block, REG_EAX, REG_EAX, block->TOP);
host_x86_MOV32_BASE_OFFSET_REG(block, REG_ESP, IREG_TOP_diff_stack_offset, REG_EAX);
}
}
void codegen_backend_epilogue(codeblock_t *block)
{
addbyte(0x83); /*ADDL $32,%esp*/
addbyte(0x83); /*ADDL $64,%esp*/
addbyte(0xC4);
addbyte(0x20);
addbyte(0x40);
addbyte(0x5f); /*POP EDI*/
addbyte(0x5e); /*POP ESI*/
addbyte(0x5d); /*POP EBP*/
@ -287,9 +305,9 @@ void codegen_backend_epilogue(codeblock_t *block)
addbyte(0xe8); /*CALL x86gpf*/
addlong((uint32_t)x86gpf - (uint32_t)(&codeblock[block_current].data[block_pos + 4]));
block_pos = BLOCK_EXIT_OFFSET; /*Exit code*/
addbyte(0x83); /*ADDL $32,%esp*/
addbyte(0x83); /*ADDL $64,%esp*/
addbyte(0xC4);
addbyte(0x20);
addbyte(0x40);
addbyte(0x5f); /*POP EDI*/
addbyte(0x5e); /*POP ESI*/
addbyte(0x5d); /*POP EBP*/

View file

@ -10,7 +10,19 @@
#define REG_ESI 6
#define REG_EDI 7
#define REG_XMM0 0
#define REG_XMM1 1
#define REG_XMM2 2
#define REG_XMM3 3
#define REG_XMM4 4
#define REG_XMM5 5
#define REG_XMM6 6
#define REG_XMM7 7
#define REG_XMM_TEMP REG_XMM7
#define CODEGEN_HOST_REGS 3
#define CODEGEN_HOST_FP_REGS 7
extern void *codegen_mem_load_byte;
extern void *codegen_mem_load_word;

View file

@ -185,6 +185,11 @@ void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int
codegen_addbyte2(block, 0x01, 0xc0 | dst_reg | (src_reg_b << 3)); /*ADD dst_reg, src_reg_b*/
}
void host_x86_ADDSD_REG_REG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_addbyte4(block, 0xf2, 0x0f, 0x58, 0xc0 | src_reg | (dst_reg << 3));
}
void host_x86_AND8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data)
{
if (dst_reg != src_reg)
@ -304,6 +309,11 @@ void host_x86_CMP32_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b)
codegen_addbyte2(block, 0x39, 0xc0 | src_reg_a | (src_reg_b << 3)); /*CMP src_reg_a, src_reg_b*/
}
void host_x86_DIVSD_REG_REG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_addbyte4(block, 0xf2, 0x0f, 0x5e, 0xc0 | src_reg | (dst_reg << 3));
}
void host_x86_JMP(codeblock_t *block, void *p)
{
codegen_addbyte(block, 0xe9); /*JMP*/
@ -515,6 +525,19 @@ void host_x86_MOV32_ABS_REG(codeblock_t *block, void *p, int src_reg)
}
}
void host_x86_MOV8_ABS_REG_REG_SHIFT_REG(codeblock_t *block, uint32_t addr, int base_reg, int idx_reg, int shift, int src_reg)
{
if (addr < 0x80 || addr >= 0xffffff80)
{
codegen_addbyte4(block, 0x88, 0x44 | (src_reg << 3), base_reg | (idx_reg << 3) | (shift << 6), addr & 0xff); /*MOV addr[base_reg + idx_reg << shift], src_reg*/
}
else
{
codegen_addbyte3(block, 0x88, 0x84 | (src_reg << 3), base_reg | (idx_reg << 3) | (shift << 6)); /*MOV addr[base_reg + idx_reg << shift], src_reg*/
codegen_addlong(block, addr);
}
}
void host_x86_MOV8_BASE_INDEX_REG(codeblock_t *block, int base_reg, int idx_reg, int src_reg)
{
codegen_addbyte3(block, 0x88, 0x04 | (src_reg << 3), base_reg | (idx_reg << 3)); /*MOV B[base_reg + idx_reg], src_reg*/
@ -691,6 +714,68 @@ void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_d
}
}
void host_x86_MOVQ_ABS_REG(codeblock_t *block, void *p, int src_reg)
{
int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
if (offset >= -128 && offset < 127)
{
codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x45 | (src_reg << 3)); /*MOVQ offset[EBP], src_reg*/
codegen_addbyte(block, offset);
}
else
{
codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x05 | (src_reg << 3)); /*MOVQ [p], src_reg*/
codegen_addlong(block, (uint32_t)p);
}
}
void host_x86_MOVQ_ABS_REG_REG_SHIFT_REG(codeblock_t *block, uint32_t addr, int src_reg_a, int src_reg_b, int shift, int src_reg)
{
codegen_addbyte3(block, 0x66, 0x0f, 0xd6); /*MOVQ addr[src_reg_a + src_reg_b << shift], XMMx*/
if (addr < 0x80 || addr >= 0xffffff80)
{
codegen_addbyte3(block, 0x44 | (src_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6), addr & 0xff);
}
else
{
codegen_addbyte2(block, 0x84 | (src_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6));
codegen_addlong(block, addr);
}
}
void host_x86_MOVQ_REG_ABS(codeblock_t *block, int dst_reg, void *p)
{
int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
if (offset >= -128 && offset < 127)
{
codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x45 | (dst_reg << 3)); /*MOVQ offset[EBP], src_reg*/
codegen_addbyte(block, offset);
}
else
{
codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x05 | (dst_reg << 3)); /*MOVQ [p], src_reg*/
codegen_addlong(block, (uint32_t)p);
}
}
void host_x86_MOVQ_REG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32_t addr, int src_reg_a, int src_reg_b, int shift)
{
codegen_addbyte3(block, 0xf3, 0x0f, 0x7e); /*MOVQ XMMx, addr[src_reg_a + src_reg_b << shift]*/
if (addr < 0x80 || addr >= 0xffffff80)
{
codegen_addbyte3(block, 0x44 | (dst_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6), addr & 0xff);
}
else
{
codegen_addbyte2(block, 0x84 | (dst_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6));
codegen_addlong(block, addr);
}
}
void host_x86_MOVQ_REG_REG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0xc0 | src_reg | (dst_reg << 3)); /*MOVQ dst_reg, src_reg*/
}
void host_x86_MOVSX_REG_16_8(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_addbyte4(block, 0x66, 0x0f, 0xbe, 0xc0 | (dst_reg << 3) | src_reg); /*MOVSX dst_reg, src_reg*/
@ -755,6 +840,11 @@ void host_x86_MOVZX_BASE_INDEX_32_16(codeblock_t *block, int dst_reg, int base_r
codegen_addbyte4(block, 0x0f, 0xb7, 0x04 | (dst_reg << 3), base_reg | (idx_reg << 3)); /*MOVZX dst_reg, W[base_reg + idx_reg]*/
}
void host_x86_MULSD_REG_REG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_addbyte4(block, 0xf2, 0x0f, 0x59, 0xc0 | src_reg | (dst_reg << 3));
}
void host_x86_OR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
{
if (dst_reg != src_reg_a)
@ -988,6 +1078,11 @@ void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int
codegen_addbyte2(block, 0x29, 0xc0 | dst_reg | (src_reg_b << 3)); /*SUB dst_reg, src_reg_b*/
}
void host_x86_SUBSD_REG_REG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_addbyte4(block, 0xf2, 0x0f, 0x5c, 0xc0 | src_reg | (dst_reg << 3));
}
void host_x86_TEST8_REG(codeblock_t *block, int src_host_reg, int dst_host_reg)
{
codegen_addbyte2(block, 0x84, MODRM_MOD_REG(dst_host_reg, src_host_reg)); /*TEST dst_host_reg, src_host_reg*/

View file

@ -8,6 +8,8 @@ void host_x86_ADD8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int s
void host_x86_ADD16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
void host_x86_ADDSD_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_AND8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data);
void host_x86_AND16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data);
void host_x86_AND32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data);
@ -25,6 +27,8 @@ void host_x86_CMP8_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b);
void host_x86_CMP16_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b);
void host_x86_CMP32_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b);
void host_x86_DIVSD_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_JMP(codeblock_t *block, void *p);
void host_x86_JNZ(codeblock_t *block, void *p);
@ -59,6 +63,8 @@ void host_x86_MOV8_ABS_REG(codeblock_t *block, void *p, int src_reg);
void host_x86_MOV16_ABS_REG(codeblock_t *block, void *p, int src_reg);
void host_x86_MOV32_ABS_REG(codeblock_t *block, void *p, int src_reg);
void host_x86_MOV8_ABS_REG_REG_SHIFT_REG(codeblock_t *block, uint32_t addr, int base_reg, int idx_reg, int shift, int src_reg);
void host_x86_MOV8_BASE_INDEX_REG(codeblock_t *block, int base_reg, int idx_reg, int src_reg);
void host_x86_MOV16_BASE_INDEX_REG(codeblock_t *block, int base_reg, int idx_reg, int src_reg);
void host_x86_MOV32_BASE_INDEX_REG(codeblock_t *block, int base_reg, int idx_reg, int src_reg);
@ -88,6 +94,13 @@ void host_x86_MOV32_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_data);
void host_x86_MOVQ_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MOVQ_REG_ABS(codeblock_t *block, int dst_reg, void *p);
void host_x86_MOVQ_REG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32_t addr, int src_reg_a, int src_reg_b, int shift);
void host_x86_MOVQ_ABS_REG(codeblock_t *block, void *p, int src_reg);
void host_x86_MOVQ_ABS_REG_REG_SHIFT_REG(codeblock_t *block, uint32_t addr, int src_reg_a, int src_reg_b, int shift, int src_reg);
void host_x86_MOVSX_REG_16_8(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MOVSX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MOVSX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg);
@ -101,6 +114,8 @@ void host_x86_MOVZX_REG_ABS_32_8(codeblock_t *block, int dst_reg, void *p);
void host_x86_MOVZX_BASE_INDEX_32_8(codeblock_t *block, int dst_reg, int base_reg, int idx_reg);
void host_x86_MOVZX_BASE_INDEX_32_16(codeblock_t *block, int dst_reg, int base_reg, int idx_reg);
void host_x86_MULSD_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_OR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
void host_x86_OR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
void host_x86_OR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
@ -147,6 +162,8 @@ void host_x86_SUB8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int s
void host_x86_SUB16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
void host_x86_SUBSD_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_TEST8_REG(codeblock_t *block, int src_host_reg, int dst_host_reg);
void host_x86_TEST16_REG(codeblock_t *block, int src_host_reg, int dst_host_reg);
void host_x86_TEST32_REG(codeblock_t *block, int src_host_reg, int dst_host_reg);

View file

@ -1,6 +1,8 @@
#if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined WIN32 || defined _WIN32 || defined _WIN32
#include "ibm.h"
#include "x86.h"
#include "386_common.h"
#include "codegen.h"
#include "codegen_backend.h"
#include "codegen_backend_x86_defs.h"
@ -28,6 +30,7 @@
#define REG_IS_W(size) (size == IREG_SIZE_W)
#define REG_IS_B(size) (size == IREG_SIZE_B || size == IREG_SIZE_BH)
#define REG_IS_BH(size) (size == IREG_SIZE_BH)
#define REG_IS_D(size) (size == IREG_SIZE_D)
static int codegen_ADD(codeblock_t *block, uop_t *uop)
{
@ -535,6 +538,91 @@ static int codegen_CMP_JZ_DEST(codeblock_t *block, uop_t *uop)
return 0;
}
static int codegen_FADD(codeblock_t *block, uop_t *uop)
{
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real);
if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b) && dest_reg == src_reg_a)
{
host_x86_ADDSD_REG_REG(block, dest_reg, src_reg_b);
}
else
fatal("codegen_FADD %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real);
return 0;
}
static int codegen_FDIV(codeblock_t *block, uop_t *uop)
{
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real);
if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b) && dest_reg == src_reg_a)
{
host_x86_DIVSD_REG_REG(block, dest_reg, src_reg_b);
}
else if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b))
{
host_x86_MOVQ_REG_REG(block, REG_XMM_TEMP, src_reg_a);
host_x86_DIVSD_REG_REG(block, REG_XMM_TEMP, src_reg_b);
host_x86_MOVQ_REG_REG(block, dest_reg, REG_XMM_TEMP);
}
else
fatal("codegen_FDIV %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real);
return 0;
}
static int codegen_FMUL(codeblock_t *block, uop_t *uop)
{
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real);
if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b) && dest_reg == src_reg_a)
{
host_x86_MULSD_REG_REG(block, dest_reg, src_reg_b);
}
else
fatal("codegen_FMUL %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real);
return 0;
}
static int codegen_FSUB(codeblock_t *block, uop_t *uop)
{
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg_a = HOST_REG_GET(uop->src_reg_a_real), src_reg_b = HOST_REG_GET(uop->src_reg_b_real);
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size_a = IREG_GET_SIZE(uop->src_reg_a_real), src_size_b = IREG_GET_SIZE(uop->src_reg_b_real);
if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b) && dest_reg == src_reg_a)
{
host_x86_SUBSD_REG_REG(block, dest_reg, src_reg_b);
}
else if (REG_IS_D(dest_size) && REG_IS_D(src_size_a) && REG_IS_D(src_size_b))
{
host_x86_MOVQ_REG_REG(block, REG_XMM_TEMP, src_reg_a);
host_x86_SUBSD_REG_REG(block, REG_XMM_TEMP, src_reg_b);
host_x86_MOVQ_REG_REG(block, dest_reg, REG_XMM_TEMP);
}
else
fatal("codegen_FSUB %02x %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real, uop->src_reg_b_real);
return 0;
}
static int codegen_FP_ENTER(codeblock_t *block, uop_t *uop)
{
uint8_t *branch_offset;
host_x86_MOV32_REG_ABS(block, REG_ECX, &cr0);
host_x86_TEST32_REG_IMM(block, REG_ECX, 0xc);
branch_offset = host_x86_JZ_short(block);
host_x86_MOV32_ABS_IMM(block, &cpu_state.oldpc, uop->imm_data);
host_x86_MOV32_STACK_IMM(block, STACK_ARG0, 7);
host_x86_CALL(block, x86_int);
host_x86_JMP(block, &block->data[BLOCK_EXIT_OFFSET]);
*branch_offset = (uint8_t)((uintptr_t)&block->data[block_pos] - (uintptr_t)branch_offset) - 1;
return 0;
}
static int codegen_JMP(codeblock_t *block, uop_t *uop)
{
host_x86_JMP(block, uop->p);
@ -1335,6 +1423,13 @@ const uOpFn uop_handlers[UOP_MAX] =
[UOP_TEST_JNS_DEST & UOP_MASK] = codegen_TEST_JNS_DEST,
[UOP_TEST_JS_DEST & UOP_MASK] = codegen_TEST_JS_DEST,
[UOP_FP_ENTER & UOP_MASK] = codegen_FP_ENTER,
[UOP_FADD & UOP_MASK] = codegen_FADD,
[UOP_FDIV & UOP_MASK] = codegen_FDIV,
[UOP_FMUL & UOP_MASK] = codegen_FMUL,
[UOP_FSUB & UOP_MASK] = codegen_FSUB
};
void codegen_direct_read_16(codeblock_t *block, int host_reg, void *p)
@ -1345,6 +1440,19 @@ void codegen_direct_read_32(codeblock_t *block, int host_reg, void *p)
{
host_x86_MOV32_REG_ABS(block, host_reg, p);
}
void codegen_direct_read_double(codeblock_t *block, int host_reg, void *p)
{
host_x86_MOVQ_REG_ABS(block, host_reg, p);
}
void codegen_direct_read_st_double(codeblock_t *block, int host_reg, void *base, int reg_idx)
{
int offset = (uintptr_t)base - (((uintptr_t)&cpu_state) + 128);
host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_ESP, IREG_TOP_diff_stack_offset);
host_x86_ADD32_REG_IMM(block, REG_ECX, REG_ECX, reg_idx);
host_x86_AND32_REG_IMM(block, REG_ECX, REG_ECX, 7);
host_x86_MOVQ_REG_ABS_REG_REG_SHIFT(block, host_reg, offset, REG_EBP, REG_ECX, 3);
}
void codegen_direct_write_8(codeblock_t *block, void *p, int host_reg)
{
@ -1358,6 +1466,28 @@ void codegen_direct_write_32(codeblock_t *block, void *p, int host_reg)
{
host_x86_MOV32_ABS_REG(block, p, host_reg);
}
void codegen_direct_write_st_8(codeblock_t *block, void *base, int reg_idx, int host_reg)
{
int offset = (uintptr_t)base - (((uintptr_t)&cpu_state) + 128);
host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_ESP, IREG_TOP_diff_stack_offset);
host_x86_ADD32_REG_IMM(block, REG_ECX, REG_ECX, reg_idx);
host_x86_AND32_REG_IMM(block, REG_ECX, REG_ECX, 7);
host_x86_MOV8_ABS_REG_REG_SHIFT_REG(block, offset, REG_EBP, REG_ECX, 0, host_reg);
}
void codegen_direct_write_double(codeblock_t *block, void *p, int host_reg)
{
host_x86_MOVQ_ABS_REG(block, p, host_reg);
}
void codegen_direct_write_st_double(codeblock_t *block, void *base, int reg_idx, int host_reg)
{
int offset = (uintptr_t)base - (((uintptr_t)&cpu_state) + 128);
host_x86_MOV32_REG_BASE_OFFSET(block, REG_ECX, REG_ESP, IREG_TOP_diff_stack_offset);
host_x86_ADD32_REG_IMM(block, REG_ECX, REG_ECX, reg_idx);
host_x86_AND32_REG_IMM(block, REG_ECX, REG_ECX, 7);
host_x86_MOVQ_ABS_REG_REG_SHIFT_REG(block, offset, REG_EBP, REG_ECX, 3, host_reg);
}
void codegen_direct_write_ptr(codeblock_t *block, void *p, int host_reg)
{

View file

@ -78,7 +78,7 @@
/*UOP_OR_IMM - dest_reg = src_reg_a | immediate*/
#define UOP_OR_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x36)
/*UOP_SUB - dest_reg = src_reg_a - src_reg_b*/
#define UOP_SUB (UOP_TYPE_PARAMS_REGS | 0x37)
#define UOP_SUB (UOP_TYPE_PARAMS_REGS | 0x37)
/*UOP_SUB_IMM - dest_reg = src_reg_a - immediate*/
#define UOP_SUB_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x38)
/*UOP_XOR - dest_reg = src_reg_a ^ src_reg_b*/
@ -151,7 +151,18 @@
/*UOP_TEST_JS_DEST - if (src_reg_a positive) then jump to ptr*/
#define UOP_TEST_JS_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x71 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP)
#define UOP_MAX 0x72
/*UOP_FP_ENTER - */
#define UOP_FP_ENTER (UOP_TYPE_PARAMS_IMM | 0x80 | UOP_TYPE_BARRIER)
/*UOP_FADD - (floating point) dest_reg = src_reg_a + src_reg_b*/
#define UOP_FADD (UOP_TYPE_PARAMS_REGS | 0x81)
/*UOP_FSUB - (floating point) dest_reg = src_reg_a - src_reg_b*/
#define UOP_FSUB (UOP_TYPE_PARAMS_REGS | 0x82)
/*UOP_FMUL - (floating point) dest_reg = src_reg_a * src_reg_b*/
#define UOP_FMUL (UOP_TYPE_PARAMS_REGS | 0x83)
/*UOP_FDIV - (floating point) dest_reg = src_reg_a / src_reg_b*/
#define UOP_FDIV (UOP_TYPE_PARAMS_REGS | 0x84)
#define UOP_MAX 0x85
#define UOP_MASK 0xffff
@ -205,6 +216,15 @@ static inline void uop_set_jump_dest(ir_data_t *ir, int jump_uop)
uop->jump_dest_uop = ir->wr_pos;
}
static inline int uop_gen(uint32_t uop_type, ir_data_t *ir)
{
uop_t *uop = uop_alloc(ir);
uop->type = uop_type;
return ir->wr_pos-1;
}
static inline int uop_gen_reg_src1(uint32_t uop_type, ir_data_t *ir, int src_reg_a)
{
uop_t *uop = uop_alloc(ir);
@ -433,6 +453,13 @@ static inline void uop_gen_reg_src_pointer_imm(uint32_t uop_type, ir_data_t *ir,
#define uop_CMP_JO_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JO_DEST, ir, src_reg_a, src_reg_b)
#define uop_CMP_JZ_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JZ_DEST, ir, src_reg_a, src_reg_b)
#define uop_FADD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_FADD, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_FDIV(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_FDIV, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_FMUL(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_FMUL, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_FSUB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_FSUB, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_FP_ENTER(ir) do { if (!codegen_fpu_entered) uop_gen_imm(UOP_FP_ENTER, ir, cpu_state.oldpc); codegen_fpu_entered = 1; } while (0)
#define uop_JMP(ir, p) uop_gen_pointer(UOP_JMP, ir, p)
#define uop_LOAD_SEG(ir, p, src_reg) uop_gen_reg_src_pointer(UOP_LOAD_SEG, ir, src_reg, p)
@ -461,11 +488,16 @@ static inline void uop_gen_reg_src_pointer_imm(uint32_t uop_type, ir_data_t *ir,
void codegen_direct_read_16(codeblock_t *block, int host_reg, void *p);
void codegen_direct_read_32(codeblock_t *block, int host_reg, void *p);
void codegen_direct_read_double(codeblock_t *block, int host_reg, void *p);
void codegen_direct_read_st_double(codeblock_t *block, int host_reg, void *base, int reg_idx);
void codegen_direct_write_8(codeblock_t *block, void *p, int host_reg);
void codegen_direct_write_16(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);
void codegen_direct_write_st_8(codeblock_t *block, void *base, int reg_idx, int host_reg);
void codegen_direct_write_double(codeblock_t *block, void *p, int host_reg);
void codegen_direct_write_st_double(codeblock_t *block, void *base, int reg_idx, int host_reg);
void codegen_direct_read_16_stack(codeblock_t *block, int host_reg, int stack_offset);
void codegen_direct_read_32_stack(codeblock_t *block, int host_reg, int stack_offset);

View file

@ -4,6 +4,7 @@
#include "codegen_ops.h"
#include "codegen_ops_arith.h"
#include "codegen_ops_branch.h"
#include "codegen_ops_fpu_arith.h"
#include "codegen_ops_jump.h"
#include "codegen_ops_logic.h"
#include "codegen_ops_misc.h"
@ -105,3 +106,97 @@ RecompOpFn recomp_opcodes_0f[512] =
/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
};
RecompOpFn recomp_opcodes_d8[512] =
{
/*16-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*80*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*c0*/ ropFADD, ropFADD, ropFADD, ropFADD, ropFADD, ropFADD, ropFADD, ropFADD, ropFMUL, ropFMUL, ropFMUL, ropFMUL, ropFMUL, ropFMUL, ropFMUL, ropFMUL,
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*e0*/ ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR,
/*f0*/ ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR,
/*32-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*80*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*c0*/ ropFADD, ropFADD, ropFADD, ropFADD, ropFADD, ropFADD, ropFADD, ropFADD, ropFMUL, ropFMUL, ropFMUL, ropFMUL, ropFMUL, ropFMUL, ropFMUL, ropFMUL,
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*e0*/ ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR,
/*f0*/ ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR,
};
RecompOpFn recomp_opcodes_dc[512] =
{
/*16-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*80*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*c0*/ ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, ropFMULr,
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*e0*/ ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr,
/*f0*/ ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr,
/*32-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*80*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*c0*/ ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, ropFMULr,
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*e0*/ ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr,
/*f0*/ ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr,
};

View file

@ -9,12 +9,12 @@ typedef uint32_t (*RecompOpFn)(codeblock_t *block, struct ir_data_t *ir, uint8_t
extern RecompOpFn recomp_opcodes[512];
extern RecompOpFn recomp_opcodes_0f[512];
/*extern RecompOpFn recomp_opcodes_d8[512];
extern RecompOpFn recomp_opcodes_d9[512];
extern RecompOpFn recomp_opcodes_d8[512];
/*extern RecompOpFn recomp_opcodes_d9[512];
extern RecompOpFn recomp_opcodes_da[512];
extern RecompOpFn recomp_opcodes_db[512];
extern RecompOpFn recomp_opcodes_db[512];*/
extern RecompOpFn recomp_opcodes_dc[512];
extern RecompOpFn recomp_opcodes_dd[512];
/*extern RecompOpFn recomp_opcodes_dd[512];
extern RecompOpFn recomp_opcodes_de[512];
extern RecompOpFn recomp_opcodes_df[512];
extern RecompOpFn recomp_opcodes_REPE[512];

134
src/codegen_ops_fpu_arith.c Normal file
View file

@ -0,0 +1,134 @@
#include "ibm.h"
#include "x86.h"
#include "x86_flags.h"
#include "386_common.h"
#include "x87.h"
#include "codegen.h"
#include "codegen_ir.h"
#include "codegen_ops.h"
#include "codegen_ops_fpu_arith.h"
uint32_t ropFADD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg = fetchdat & 7;
uop_FP_ENTER(ir);
uop_FADD(ir, IREG_ST(0), IREG_ST(0), IREG_ST(src_reg));
uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID);
return op_pc;
}
uint32_t ropFADDr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = fetchdat & 7;
uop_FP_ENTER(ir);
uop_FADD(ir, IREG_ST(dest_reg), IREG_ST(dest_reg), IREG_ST(0));
uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID);
return op_pc;
}
uint32_t ropFDIV(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg = fetchdat & 7;
uop_FP_ENTER(ir);
uop_FDIV(ir, IREG_ST(0), IREG_ST(0), IREG_ST(src_reg));
uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID);
return op_pc;
}
uint32_t ropFDIVr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = fetchdat & 7;
uop_FP_ENTER(ir);
uop_FDIV(ir, IREG_ST(dest_reg), IREG_ST(dest_reg), IREG_ST(0));
uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID);
return op_pc;
}
uint32_t ropFDIVR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg = fetchdat & 7;
uop_FP_ENTER(ir);
uop_FDIV(ir, IREG_ST(0), IREG_ST(src_reg), IREG_ST(0));
uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID);
return op_pc;
}
uint32_t ropFDIVRr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = fetchdat & 7;
uop_FP_ENTER(ir);
uop_FDIV(ir, IREG_ST(dest_reg), IREG_ST(0), IREG_ST(dest_reg));
uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID);
return op_pc;
}
uint32_t ropFMUL(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg = fetchdat & 7;
uop_FP_ENTER(ir);
uop_FMUL(ir, IREG_ST(0), IREG_ST(0), IREG_ST(src_reg));
uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID);
return op_pc;
}
uint32_t ropFMULr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = fetchdat & 7;
uop_FP_ENTER(ir);
uop_FMUL(ir, IREG_ST(dest_reg), IREG_ST(dest_reg), IREG_ST(0));
uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID);
return op_pc;
}
uint32_t ropFSUB(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg = fetchdat & 7;
uop_FP_ENTER(ir);
uop_FSUB(ir, IREG_ST(0), IREG_ST(0), IREG_ST(src_reg));
uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID);
return op_pc;
}
uint32_t ropFSUBr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = fetchdat & 7;
uop_FP_ENTER(ir);
uop_FSUB(ir, IREG_ST(dest_reg), IREG_ST(dest_reg), IREG_ST(0));
uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID);
return op_pc;
}
uint32_t ropFSUBR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg = fetchdat & 7;
uop_FP_ENTER(ir);
uop_FSUB(ir, IREG_ST(0), IREG_ST(src_reg), IREG_ST(0));
uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID);
return op_pc;
}
uint32_t ropFSUBRr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = fetchdat & 7;
uop_FP_ENTER(ir);
uop_FSUB(ir, IREG_ST(dest_reg), IREG_ST(0), IREG_ST(dest_reg));
uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID);
return op_pc;
}

View file

@ -0,0 +1,12 @@
uint32_t ropFADD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFADDr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFDIV(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFDIVr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFDIVR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFDIVRr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFMUL(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFMULr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFSUB(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFSUBr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFSUBR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFSUBRr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);

View file

@ -9,10 +9,22 @@ uint8_t reg_version_refcount[IREG_COUNT][256];
ir_reg_t invalid_ir_reg = {IREG_INVALID};
ir_reg_t host_regs[CODEGEN_HOST_REGS];
static uint8_t host_reg_dirty[CODEGEN_HOST_REGS];
ir_reg_t _host_regs[CODEGEN_HOST_REGS];
static uint8_t _host_reg_dirty[CODEGEN_HOST_REGS];
static uint8_t host_regs_locked;
ir_reg_t host_fp_regs[CODEGEN_HOST_FP_REGS];
static uint8_t host_fp_reg_dirty[CODEGEN_HOST_FP_REGS];
typedef struct host_reg_set_t
{
ir_reg_t *regs;
uint8_t *dirty;
int *reg_list;
uint16_t locked;
int nr_regs;
} host_reg_set_t;
static host_reg_set_t host_reg_set, host_fp_reg_set;
enum
{
@ -20,70 +32,110 @@ enum
REG_WORD,
REG_DWORD,
REG_QWORD,
REG_POINTER
REG_POINTER,
REG_FPU_ST_BYTE,
REG_FPU_ST_DOUBLE
};
enum
{
REG_INTEGER,
REG_FP
};
struct
{
int native_size;
void *p;
int type;
} ireg_data[IREG_COUNT] =
{
[IREG_EAX] = {REG_DWORD, &EAX},
[IREG_ECX] = {REG_DWORD, &ECX},
[IREG_EDX] = {REG_DWORD, &EDX},
[IREG_EBX] = {REG_DWORD, &EBX},
[IREG_ESP] = {REG_DWORD, &ESP},
[IREG_EBP] = {REG_DWORD, &EBP},
[IREG_ESI] = {REG_DWORD, &ESI},
[IREG_EDI] = {REG_DWORD, &EDI},
[IREG_EAX] = {REG_DWORD, &EAX, REG_INTEGER},
[IREG_ECX] = {REG_DWORD, &ECX, REG_INTEGER},
[IREG_EDX] = {REG_DWORD, &EDX, REG_INTEGER},
[IREG_EBX] = {REG_DWORD, &EBX, REG_INTEGER},
[IREG_ESP] = {REG_DWORD, &ESP, REG_INTEGER},
[IREG_EBP] = {REG_DWORD, &EBP, REG_INTEGER},
[IREG_ESI] = {REG_DWORD, &ESI, REG_INTEGER},
[IREG_EDI] = {REG_DWORD, &EDI, REG_INTEGER},
[IREG_flags_op] = {REG_DWORD, &cpu_state.flags_op},
[IREG_flags_res] = {REG_DWORD, &cpu_state.flags_res},
[IREG_flags_op1] = {REG_DWORD, &cpu_state.flags_op1},
[IREG_flags_op2] = {REG_DWORD, &cpu_state.flags_op2},
[IREG_flags_op] = {REG_DWORD, &cpu_state.flags_op, REG_INTEGER},
[IREG_flags_res] = {REG_DWORD, &cpu_state.flags_res, REG_INTEGER},
[IREG_flags_op1] = {REG_DWORD, &cpu_state.flags_op1, REG_INTEGER},
[IREG_flags_op2] = {REG_DWORD, &cpu_state.flags_op2, REG_INTEGER},
[IREG_pc] = {REG_DWORD, &cpu_state.pc},
[IREG_oldpc] = {REG_DWORD, &cpu_state.oldpc},
[IREG_pc] = {REG_DWORD, &cpu_state.pc, REG_INTEGER},
[IREG_oldpc] = {REG_DWORD, &cpu_state.oldpc, REG_INTEGER},
[IREG_eaaddr] = {REG_DWORD, &cpu_state.eaaddr},
[IREG_ea_seg] = {REG_POINTER, &cpu_state.ea_seg},
[IREG_eaaddr] = {REG_DWORD, &cpu_state.eaaddr, REG_INTEGER},
[IREG_ea_seg] = {REG_POINTER, &cpu_state.ea_seg, REG_INTEGER},
[IREG_op32] = {REG_DWORD, &cpu_state.op32},
[IREG_ssegs] = {REG_BYTE, &cpu_state.ssegs},
[IREG_op32] = {REG_DWORD, &cpu_state.op32, REG_INTEGER},
[IREG_ssegs] = {REG_BYTE, &cpu_state.ssegs, REG_INTEGER},
[IREG_rm_mod_reg] = {REG_DWORD, &cpu_state.rm_data.rm_mod_reg_data},
[IREG_rm_mod_reg] = {REG_DWORD, &cpu_state.rm_data.rm_mod_reg_data, REG_INTEGER},
[IREG_ins] = {REG_DWORD, &cpu_state.cpu_recomp_ins},
[IREG_cycles] = {REG_DWORD, &cpu_state._cycles},
[IREG_ins] = {REG_DWORD, &cpu_state.cpu_recomp_ins, REG_INTEGER},
[IREG_cycles] = {REG_DWORD, &cpu_state._cycles, REG_INTEGER},
[IREG_CS_base] = {REG_DWORD, &cpu_state.seg_cs.base},
[IREG_DS_base] = {REG_DWORD, &cpu_state.seg_ds.base},
[IREG_ES_base] = {REG_DWORD, &cpu_state.seg_es.base},
[IREG_FS_base] = {REG_DWORD, &cpu_state.seg_fs.base},
[IREG_GS_base] = {REG_DWORD, &cpu_state.seg_gs.base},
[IREG_SS_base] = {REG_DWORD, &cpu_state.seg_ss.base},
[IREG_CS_base] = {REG_DWORD, &cpu_state.seg_cs.base, REG_INTEGER},
[IREG_DS_base] = {REG_DWORD, &cpu_state.seg_ds.base, REG_INTEGER},
[IREG_ES_base] = {REG_DWORD, &cpu_state.seg_es.base, REG_INTEGER},
[IREG_FS_base] = {REG_DWORD, &cpu_state.seg_fs.base, REG_INTEGER},
[IREG_GS_base] = {REG_DWORD, &cpu_state.seg_gs.base, REG_INTEGER},
[IREG_SS_base] = {REG_DWORD, &cpu_state.seg_ss.base, REG_INTEGER},
[IREG_CS_seg] = {REG_WORD, &cpu_state.seg_cs.seg},
[IREG_DS_seg] = {REG_WORD, &cpu_state.seg_ds.seg},
[IREG_ES_seg] = {REG_WORD, &cpu_state.seg_es.seg},
[IREG_FS_seg] = {REG_WORD, &cpu_state.seg_fs.seg},
[IREG_GS_seg] = {REG_WORD, &cpu_state.seg_gs.seg},
[IREG_SS_seg] = {REG_WORD, &cpu_state.seg_ss.seg},
[IREG_CS_seg] = {REG_WORD, &cpu_state.seg_cs.seg, REG_INTEGER},
[IREG_DS_seg] = {REG_WORD, &cpu_state.seg_ds.seg, REG_INTEGER},
[IREG_ES_seg] = {REG_WORD, &cpu_state.seg_es.seg, REG_INTEGER},
[IREG_FS_seg] = {REG_WORD, &cpu_state.seg_fs.seg, REG_INTEGER},
[IREG_GS_seg] = {REG_WORD, &cpu_state.seg_gs.seg, REG_INTEGER},
[IREG_SS_seg] = {REG_WORD, &cpu_state.seg_ss.seg, REG_INTEGER},
[IREG_FPU_TOP] = {REG_DWORD, &cpu_state.TOP, REG_INTEGER},
[IREG_ST0] = {REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP},
[IREG_ST1] = {REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP},
[IREG_ST2] = {REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP},
[IREG_ST3] = {REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP},
[IREG_ST4] = {REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP},
[IREG_ST5] = {REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP},
[IREG_ST6] = {REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP},
[IREG_ST7] = {REG_FPU_ST_DOUBLE, &cpu_state.ST[0], REG_FP},
[IREG_tag0] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER},
[IREG_tag1] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER},
[IREG_tag2] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER},
[IREG_tag3] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER},
[IREG_tag4] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER},
[IREG_tag5] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER},
[IREG_tag6] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER},
[IREG_tag7] = {REG_FPU_ST_BYTE, &cpu_state.tag[0], REG_INTEGER},
/*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] = {REG_DWORD, (void *)16},
[IREG_temp1] = {REG_DWORD, (void *)20},
[IREG_temp2] = {REG_DWORD, (void *)24},
[IREG_temp3] = {REG_DWORD, (void *)28},
[IREG_temp0] = {REG_DWORD, (void *)16, REG_INTEGER},
[IREG_temp1] = {REG_DWORD, (void *)20, REG_INTEGER},
[IREG_temp2] = {REG_DWORD, (void *)24, REG_INTEGER},
[IREG_temp3] = {REG_DWORD, (void *)28, REG_INTEGER},
};
void codegen_reg_reset()
{
int c;
host_reg_set.regs = _host_regs;
host_reg_set.dirty = _host_reg_dirty;
host_reg_set.reg_list = codegen_host_reg_list;
host_reg_set.locked = 0;
host_reg_set.nr_regs = CODEGEN_HOST_REGS;
host_fp_reg_set.regs = host_fp_regs;
host_fp_reg_set.dirty = host_fp_reg_dirty;
host_fp_reg_set.reg_list = codegen_host_fp_reg_list;
host_fp_reg_set.locked = 0;
host_fp_reg_set.nr_regs = CODEGEN_HOST_FP_REGS;
for (c = 0; c < IREG_COUNT; c++)
{
reg_last_version[c] = 0;
@ -91,8 +143,13 @@ void codegen_reg_reset()
}
for (c = 0; c < CODEGEN_HOST_REGS; c++)
{
host_regs[c] = invalid_ir_reg;
host_reg_dirty[c] = 0;
host_reg_set.regs[c] = invalid_ir_reg;
host_reg_set.dirty[c] = 0;
}
for (c = 0; c < CODEGEN_HOST_FP_REGS; c++)
{
host_fp_reg_set.regs[c] = invalid_ir_reg;
host_fp_reg_set.dirty[c] = 0;
}
}
@ -101,62 +158,104 @@ static inline int ir_reg_is_invalid(ir_reg_t ir_reg)
return (IREG_GET_REG(ir_reg.reg) == IREG_INVALID);
}
static void codegen_reg_load(codeblock_t *block, int c, ir_reg_t ir_reg)
static inline host_reg_set_t *get_reg_set(ir_reg_t ir_reg)
{
if (ireg_data[IREG_GET_REG(ir_reg.reg)].type == REG_INTEGER)
return &host_reg_set;
else
return &host_fp_reg_set;
}
static void codegen_reg_load(host_reg_set_t *reg_set, codeblock_t *block, int c, ir_reg_t ir_reg)
{
switch (ireg_data[IREG_GET_REG(ir_reg.reg)].native_size)
{
case REG_WORD:
if (ireg_data[IREG_GET_REG(ir_reg.reg)].type != REG_INTEGER)
fatal("codegen_reg_load - REG_WORD !REG_INTEGER\n");
if ((uintptr_t)ireg_data[IREG_GET_REG(ir_reg.reg)].p < 256)
codegen_direct_read_16_stack(block, codegen_host_reg_list[c], (int)ireg_data[IREG_GET_REG(ir_reg.reg)].p);
codegen_direct_read_16_stack(block, reg_set->reg_list[c], (int)ireg_data[IREG_GET_REG(ir_reg.reg)].p);
else
codegen_direct_read_16(block, codegen_host_reg_list[c], ireg_data[IREG_GET_REG(ir_reg.reg)].p);
codegen_direct_read_16(block, reg_set->reg_list[c], ireg_data[IREG_GET_REG(ir_reg.reg)].p);
break;
case REG_DWORD:
if (ireg_data[IREG_GET_REG(ir_reg.reg)].type != REG_INTEGER)
fatal("codegen_reg_load - REG_DWORD !REG_INTEGER\n");
if ((uintptr_t)ireg_data[IREG_GET_REG(ir_reg.reg)].p < 256)
codegen_direct_read_32_stack(block, codegen_host_reg_list[c], (int)ireg_data[IREG_GET_REG(ir_reg.reg)].p);
codegen_direct_read_32_stack(block, reg_set->reg_list[c], (int)ireg_data[IREG_GET_REG(ir_reg.reg)].p);
else
codegen_direct_read_32(block, codegen_host_reg_list[c], ireg_data[IREG_GET_REG(ir_reg.reg)].p);
codegen_direct_read_32(block, reg_set->reg_list[c], ireg_data[IREG_GET_REG(ir_reg.reg)].p);
break;
case REG_FPU_ST_DOUBLE:
if (block->flags & CODEBLOCK_STATIC_TOP)
codegen_direct_read_double(block, reg_set->reg_list[c], &cpu_state.ST[ir_reg.reg & 7]);
else
codegen_direct_read_st_double(block, reg_set->reg_list[c], &cpu_state.ST[0], ir_reg.reg & 7);
break;
default:
fatal("codegen_reg_load - native_size=%i\n", ireg_data[IREG_GET_REG(ir_reg.reg)].native_size);
}
host_regs[c] = ir_reg;
reg_set->regs[c] = ir_reg;
//pclog(" codegen_reg_load: c=%i reg=%02x.%i\n", c, host_regs[c].reg,host_regs[c].version);
}
static void codegen_reg_writeback(codeblock_t *block, int c, int invalidate)
static void codegen_reg_writeback(host_reg_set_t *reg_set, codeblock_t *block, int c, int invalidate)
{
int ir_reg = IREG_GET_REG(host_regs[c].reg);
int ir_reg = IREG_GET_REG(reg_set->regs[c].reg);
void *p = ireg_data[ir_reg].p;
switch (ireg_data[ir_reg].native_size)
{
case REG_BYTE:
if (ireg_data[ir_reg].type != REG_INTEGER)
fatal("codegen_reg_writeback - REG_BYTE !REG_INTEGER\n");
if ((uintptr_t)p < 256)
fatal("codegen_reg_writeback - REG_BYTE %p\n", p);
codegen_direct_write_8(block, p, codegen_host_reg_list[c]);
codegen_direct_write_8(block, p, reg_set->reg_list[c]);
break;
case REG_WORD:
if (ireg_data[ir_reg].type != REG_INTEGER)
fatal("codegen_reg_writeback - REG_WORD !REG_INTEGER\n");
if ((uintptr_t)p < 256)
fatal("codegen_reg_writeback - REG_WORD %p\n", p);
codegen_direct_write_16(block, p, codegen_host_reg_list[c]);
codegen_direct_write_16(block, p, reg_set->reg_list[c]);
break;
case REG_DWORD:
if (ireg_data[ir_reg].type != REG_INTEGER)
fatal("codegen_reg_writeback - REG_DWORD !REG_INTEGER\n");
if ((uintptr_t)p < 256)
codegen_direct_write_32_stack(block, (int)p, codegen_host_reg_list[c]);
codegen_direct_write_32_stack(block, (int)p, reg_set->reg_list[c]);
else
codegen_direct_write_32(block, p, codegen_host_reg_list[c]);
codegen_direct_write_32(block, p, reg_set->reg_list[c]);
break;
case REG_POINTER:
if (ireg_data[ir_reg].type != REG_INTEGER)
fatal("codegen_reg_writeback - REG_POINTER !REG_INTEGER\n");
if ((uintptr_t)p < 256)
fatal("codegen_reg_writeback - REG_POINTER %p\n", p);
codegen_direct_write_ptr(block, p, codegen_host_reg_list[c]);
codegen_direct_write_ptr(block, p, reg_set->reg_list[c]);
break;
case REG_FPU_ST_BYTE:
if (block->flags & CODEBLOCK_STATIC_TOP)
codegen_direct_write_8(block, &cpu_state.tag[reg_set->regs[c].reg & 7], reg_set->reg_list[c]);
else
codegen_direct_write_st_8(block, &cpu_state.tag[0], reg_set->regs[c].reg & 7, reg_set->reg_list[c]);
break;
case REG_FPU_ST_DOUBLE:
if (block->flags & CODEBLOCK_STATIC_TOP)
codegen_direct_write_double(block, &cpu_state.ST[reg_set->regs[c].reg & 7], reg_set->reg_list[c]);
else
codegen_direct_write_st_double(block, &cpu_state.ST[0], reg_set->regs[c].reg & 7, reg_set->reg_list[c]);
break;
default:
@ -164,8 +263,8 @@ static void codegen_reg_writeback(codeblock_t *block, int c, int invalidate)
}
if (invalidate)
host_regs[c] = invalid_ir_reg;
host_reg_dirty[c] = 0;
reg_set->regs[c] = invalid_ir_reg;
reg_set->dirty[c] = 0;
}
void codegen_reg_alloc_register(ir_reg_t dest_reg_a, ir_reg_t src_reg_a, ir_reg_t src_reg_b, ir_reg_t src_reg_c)
@ -173,7 +272,8 @@ void codegen_reg_alloc_register(ir_reg_t dest_reg_a, ir_reg_t src_reg_a, ir_reg_
int c;
int dest_reference = 0;
host_regs_locked = 0;
host_reg_set.locked = 0;
host_fp_reg_set.locked = 0;
/* pclog("alloc_register: dst=%i.%i src_a=%i.%i src_b=%i.%i\n", dest_reg_a.reg, dest_reg_a.version,
src_reg_a.reg, src_reg_a.version,
@ -190,82 +290,88 @@ void codegen_reg_alloc_register(ir_reg_t dest_reg_a, ir_reg_t src_reg_a, ir_reg_
}
for (c = 0; c < CODEGEN_HOST_REGS; c++)
{
if (!ir_reg_is_invalid(src_reg_a) && IREG_GET_REG(host_regs[c].reg) == IREG_GET_REG(src_reg_a.reg))
host_reg_set_t *reg_set = get_reg_set(src_reg_a);
if (!ir_reg_is_invalid(src_reg_a) && IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(src_reg_a.reg))
{
if (host_regs[c].version != src_reg_a.version)
if (reg_set->regs[c].version != src_reg_a.version)
fatal("codegen_reg_alloc_register - host_regs[c].version != src_reg_a.version\n");
host_regs_locked |= (1 << c);
reg_set->locked |= (1 << c);
}
if (!ir_reg_is_invalid(src_reg_b) && IREG_GET_REG(host_regs[c].reg) == IREG_GET_REG(src_reg_b.reg))
reg_set = get_reg_set(src_reg_b);
if (!ir_reg_is_invalid(src_reg_b) && IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(src_reg_b.reg))
{
if (host_regs[c].version != src_reg_b.version)
if (reg_set->regs[c].version != src_reg_b.version)
fatal("codegen_reg_alloc_register - host_regs[c].version != src_reg_b.version\n");
host_regs_locked |= (1 << c);
reg_set->locked |= (1 << c);
}
if (!ir_reg_is_invalid(src_reg_c) && IREG_GET_REG(host_regs[c].reg) == IREG_GET_REG(src_reg_c.reg))
reg_set = get_reg_set(src_reg_c);
if (!ir_reg_is_invalid(src_reg_c) && IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(src_reg_c.reg))
{
if (host_regs[c].version != src_reg_c.version)
if (reg_set->regs[c].version != src_reg_c.version)
fatal("codegen_reg_alloc_register - host_regs[c].version != src_reg_c.version\n");
host_regs_locked |= (1 << c);
reg_set->locked |= (1 << c);
}
if (!ir_reg_is_invalid(dest_reg_a) && IREG_GET_REG(host_regs[c].reg) == IREG_GET_REG(dest_reg_a.reg))
reg_set = get_reg_set(dest_reg_a);
if (!ir_reg_is_invalid(dest_reg_a) && IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(dest_reg_a.reg))
{
if (host_regs[c].version == dest_reg_a.version || (host_regs[c].version == (dest_reg_a.version-1) && reg_version_refcount[IREG_GET_REG(host_regs[c].reg)][host_regs[c].version] == dest_reference))
host_regs_locked |= (1 << c);
if (reg_set->regs[c].version == dest_reg_a.version || (reg_set->regs[c].version == (dest_reg_a.version-1) && reg_version_refcount[IREG_GET_REG(reg_set->regs[c].reg)][reg_set->regs[c].version] == dest_reference))
reg_set->locked |= (1 << c);
else
fatal("codegen_reg_alloc_register - host_regs[c].version != dest_reg_a.version %i,%i %i\n", host_regs[c].version, dest_reg_a.version, dest_reference);
fatal("codegen_reg_alloc_register - host_regs[c].version != dest_reg_a.version %i,%i %i\n", reg_set->regs[c].version, dest_reg_a.version, dest_reference);
}
}
}
ir_host_reg_t codegen_reg_alloc_read_reg(codeblock_t *block, ir_reg_t ir_reg, int *host_reg_idx)
{
host_reg_set_t *reg_set = get_reg_set(ir_reg);
int c;
/*Search for required register*/
for (c = 0; c < CODEGEN_HOST_REGS; c++)
for (c = 0; c < reg_set->nr_regs; c++)
{
if (!ir_reg_is_invalid(host_regs[c]) && IREG_GET_REG(host_regs[c].reg) == IREG_GET_REG(ir_reg.reg) && host_regs[c].version == ir_reg.version)
if (!ir_reg_is_invalid(reg_set->regs[c]) && IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(ir_reg.reg) && reg_set->regs[c].version == ir_reg.version)
break;
if (!ir_reg_is_invalid(host_regs[c]) && IREG_GET_REG(host_regs[c].reg) == IREG_GET_REG(ir_reg.reg) && reg_version_refcount[IREG_GET_REG(host_regs[c].reg)][host_regs[c].version])
if (!ir_reg_is_invalid(reg_set->regs[c]) && IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(ir_reg.reg) && reg_version_refcount[IREG_GET_REG(reg_set->regs[c].reg)][reg_set->regs[c].version])
fatal("codegen_reg_alloc_read_reg - version mismatch!\n");
}
if (c == CODEGEN_HOST_REGS)
if (c == reg_set->nr_regs)
{
/*No unused registers. Search for an unlocked register*/
for (c = 0; c < CODEGEN_HOST_REGS; c++)
for (c = 0; c < reg_set->nr_regs; c++)
{
if (!(host_regs_locked & (1 << c)))
if (!(reg_set->locked & (1 << c)))
break;
}
if (c == CODEGEN_HOST_REGS)
if (c == reg_set->nr_regs)
fatal("codegen_reg_alloc_read_reg - out of registers\n");
if (host_reg_dirty[c])
codegen_reg_writeback(block, c, 1);
if (reg_set->dirty[c])
codegen_reg_writeback(reg_set, block, c, 1);
// pclog(" load %i\n", c);
codegen_reg_load(block, c, ir_reg);
host_regs_locked |= (1 << c);
codegen_reg_load(reg_set, block, c, ir_reg);
reg_set->locked |= (1 << c);
// fatal("codegen_reg_alloc_read_reg - read %i.%i to %i\n", ir_reg.reg,ir_reg.version, c);
// codegen_reg_writeback(block, c);
host_reg_dirty[c] = 0;
reg_set->dirty[c] = 0;
}
// else
// pclog(" already loaded %i\n", c);
reg_version_refcount[IREG_GET_REG(host_regs[c].reg)][host_regs[c].version]--;
if (reg_version_refcount[IREG_GET_REG(host_regs[c].reg)][host_regs[c].version] < 0)
reg_version_refcount[IREG_GET_REG(reg_set->regs[c].reg)][reg_set->regs[c].version]--;
if (reg_version_refcount[IREG_GET_REG(reg_set->regs[c].reg)][reg_set->regs[c].version] < 0)
fatal("codegen_reg_alloc_read_reg - refcount < 0\n");
if (host_reg_idx)
*host_reg_idx = c;
// pclog(" codegen_reg_alloc_read_reg: %i.%i %i %02x.%i %i\n", ir_reg.reg, ir_reg.version, codegen_host_reg_list[c], host_regs[c].reg,host_regs[c].version, c);
return codegen_host_reg_list[c] | IREG_GET_SIZE(ir_reg.reg);
return reg_set->reg_list[c] | IREG_GET_SIZE(ir_reg.reg);
}
ir_host_reg_t codegen_reg_alloc_write_reg(codeblock_t *block, ir_reg_t ir_reg)
{
host_reg_set_t *reg_set = get_reg_set(ir_reg);
int c;
if (IREG_GET_SIZE(ir_reg.reg) != IREG_SIZE_L)
@ -278,85 +384,107 @@ ir_host_reg_t codegen_reg_alloc_write_reg(codeblock_t *block, ir_reg_t ir_reg)
codegen_reg_alloc_read_reg(block, parent_reg, &c);
if (IREG_GET_REG(host_regs[c].reg) != IREG_GET_REG(ir_reg.reg) || host_regs[c].version != ir_reg.version-1)
if (IREG_GET_REG(reg_set->regs[c].reg) != IREG_GET_REG(ir_reg.reg) || reg_set->regs[c].version != ir_reg.version-1)
fatal("codegen_reg_alloc_write_reg sub_reg - doesn't match %i %02x.%i %02x.%i\n", c,
host_regs[c].reg,host_regs[c].version,
reg_set->regs[c].reg,reg_set->regs[c].version,
ir_reg.reg,ir_reg.version);
host_regs[c].reg = ir_reg.reg;
host_regs[c].version = ir_reg.version;
host_reg_dirty[c] = 1;
reg_set->regs[c].reg = ir_reg.reg;
reg_set->regs[c].version = ir_reg.version;
reg_set->dirty[c] = 1;
// pclog(" codegen_reg_alloc_write_reg: partial %i.%i %i\n", ir_reg.reg, ir_reg.version, codegen_host_reg_list[c]);
return codegen_host_reg_list[c] | IREG_GET_SIZE(ir_reg.reg);
return reg_set->reg_list[c] | IREG_GET_SIZE(ir_reg.reg);
}
/*Search for previous version in host register*/
for (c = 0; c < CODEGEN_HOST_REGS; c++)
for (c = 0; c < reg_set->nr_regs; c++)
{
if (!ir_reg_is_invalid(host_regs[c]) && IREG_GET_REG(host_regs[c].reg) == IREG_GET_REG(ir_reg.reg))
if (!ir_reg_is_invalid(reg_set->regs[c]) && IREG_GET_REG(reg_set->regs[c].reg) == IREG_GET_REG(ir_reg.reg))
{
if (host_regs[c].version == ir_reg.version-1)
if (reg_set->regs[c].version == ir_reg.version-1)
{
if (reg_version_refcount[IREG_GET_REG(host_regs[c].reg)][host_regs[c].version] != 0)
if (reg_version_refcount[IREG_GET_REG(reg_set->regs[c].reg)][reg_set->regs[c].version] != 0)
fatal("codegen_reg_alloc_write_reg - previous version refcount != 0\n");
break;
}
}
}
if (c == CODEGEN_HOST_REGS)
if (c == reg_set->nr_regs)
{
/*Search for unused registers*/
for (c = 0; c < CODEGEN_HOST_REGS; c++)
for (c = 0; c < reg_set->nr_regs; c++)
{
if (ir_reg_is_invalid(host_regs[c]))
if (ir_reg_is_invalid(reg_set->regs[c]))
break;
}
if (c == CODEGEN_HOST_REGS)
if (c == reg_set->nr_regs)
{
/*No unused registers. Search for an unlocked register*/
for (c = 0; c < CODEGEN_HOST_REGS; c++)
for (c = 0; c < reg_set->nr_regs; c++)
{
if (!(host_regs_locked & (1 << c)))
if (!(reg_set->locked & (1 << c)))
break;
}
if (c == CODEGEN_HOST_REGS)
if (c == reg_set->nr_regs)
fatal("codegen_reg_alloc_write_reg - out of registers\n");
if (host_reg_dirty[c])
codegen_reg_writeback(block, c, 1);
if (reg_set->dirty[c])
codegen_reg_writeback(reg_set, block, c, 1);
}
}
host_regs[c].reg = ir_reg.reg;
host_regs[c].version = ir_reg.version;
host_reg_dirty[c] = 1;
reg_set->regs[c].reg = ir_reg.reg;
reg_set->regs[c].version = ir_reg.version;
reg_set->dirty[c] = 1;
// pclog(" codegen_reg_alloc_write_reg: %i.%i %i\n", ir_reg.reg, ir_reg.version, codegen_host_reg_list[c]);
return codegen_host_reg_list[c] | IREG_GET_SIZE(ir_reg.reg);
return reg_set->reg_list[c] | IREG_GET_SIZE(ir_reg.reg);
}
void codegen_reg_flush(ir_data_t *ir, codeblock_t *block)
{
host_reg_set_t *reg_set;
int c;
for (c = 0; c < CODEGEN_HOST_REGS; c++)
reg_set = &host_reg_set;
for (c = 0; c < reg_set->nr_regs; c++)
{
if (!ir_reg_is_invalid(host_regs[c]) && host_reg_dirty[c])
if (!ir_reg_is_invalid(reg_set->regs[c]) && reg_set->dirty[c])
{
codegen_reg_writeback(block, c, 0);
codegen_reg_writeback(reg_set, block, c, 0);
}
}
reg_set = &host_fp_reg_set;
for (c = 0; c < reg_set->nr_regs; c++)
{
if (!ir_reg_is_invalid(reg_set->regs[c]) && reg_set->dirty[c])
{
codegen_reg_writeback(reg_set, block, c, 0);
}
}
}
void codegen_reg_flush_invalidate(ir_data_t *ir, codeblock_t *block)
{
host_reg_set_t *reg_set;
int c;
for (c = 0; c < CODEGEN_HOST_REGS; c++)
reg_set = &host_reg_set;
for (c = 0; c < reg_set->nr_regs; c++)
{
if (!ir_reg_is_invalid(host_regs[c]))
if (!ir_reg_is_invalid(reg_set->regs[c]))
{
codegen_reg_writeback(block, c, 1);
codegen_reg_writeback(reg_set, block, c, 1);
}
}
reg_set = &host_fp_reg_set;
for (c = 0; c < reg_set->nr_regs; c++)
{
if (!ir_reg_is_invalid(reg_set->regs[c]))
{
codegen_reg_writeback(reg_set, block, c, 1);
}
}
}

View file

@ -1,9 +1,9 @@
#ifndef _CODEGEN_REG_H_
#define _CODEGEN_REG_H_
#define IREG_REG_MASK 0x3f
#define IREG_SIZE_SHIFT 6
#define IREG_SIZE_MASK (3 << IREG_SIZE_SHIFT)
#define IREG_REG_MASK 0xff
#define IREG_SIZE_SHIFT 8
#define IREG_SIZE_MASK (7 << IREG_SIZE_SHIFT)
#define IREG_GET_REG(reg) ((reg) & IREG_REG_MASK)
#define IREG_GET_SIZE(reg) ((reg) & IREG_SIZE_MASK)
@ -12,6 +12,7 @@
#define IREG_SIZE_W (1 << IREG_SIZE_SHIFT)
#define IREG_SIZE_B (2 << IREG_SIZE_SHIFT)
#define IREG_SIZE_BH (3 << IREG_SIZE_SHIFT)
#define IREG_SIZE_D (4 << IREG_SIZE_SHIFT)
enum
{
@ -64,7 +65,33 @@ enum
IREG_temp2 = 35,
IREG_temp3 = 36,
IREG_COUNT,
IREG_FPU_TOP = 37,
/*FPU stack registers are physical registers. Use IREG_ST() / IREG_tag()
to access.
When CODEBLOCK_STATIC_TOP is set, the physical register number will be
used directly to index the stack. When it is clear, the difference
between the current value of TOP and the value when the block was
first compiled will be added to adjust for any changes in TOP.*/
IREG_ST0 = 40,
IREG_ST1 = 41,
IREG_ST2 = 42,
IREG_ST3 = 43,
IREG_ST4 = 44,
IREG_ST5 = 45,
IREG_ST6 = 46,
IREG_ST7 = 47,
IREG_tag0 = 48,
IREG_tag1 = 49,
IREG_tag2 = 50,
IREG_tag3 = 51,
IREG_tag4 = 52,
IREG_tag5 = 53,
IREG_tag6 = 54,
IREG_tag7 = 55,
IREG_COUNT = 56,
IREG_INVALID = 63,
@ -116,6 +143,11 @@ enum
#define IREG_16(reg) ((reg) + IREG_AX)
#define IREG_32(reg) ((reg) + IREG_EAX)
#define IREG_ST(r) (IREG_ST0 + ((cpu_state.TOP + (r)) & 7) + IREG_SIZE_D)
#define IREG_tag(r) (IREG_tag0 + ((cpu_state.TOP + (r)) & 7))
#define IREG_TOP_diff_stack_offset 32
static inline int ireg_seg_base(x86seg *seg)
{
if (seg == &cpu_state.seg_cs)
@ -139,13 +171,13 @@ extern uint8_t reg_version_refcount[IREG_COUNT][256];
typedef struct
{
uint8_t reg;
uint8_t version;
uint16_t reg;
uint16_t version;
} ir_reg_t;
extern ir_reg_t invalid_ir_reg;
typedef uint8_t ir_host_reg_t;
typedef uint16_t ir_host_reg_t;
#define REG_VERSION_MAX 250

View file

@ -180,6 +180,12 @@ struct
uint16_t old_npxc, new_npxc;
x86seg seg_cs,seg_ds,seg_es,seg_ss,seg_fs,seg_gs;
union
{
uint32_t l;
uint16_t w;
} CR0;
} cpu_state;
#define cycles cpu_state._cycles
@ -239,14 +245,8 @@ uint8_t *pccache2;
int loadseg(uint16_t seg, x86seg *s);
void loadcs(uint16_t seg);
union
{
uint32_t l;
uint16_t w;
} CR0;
#define cr0 CR0.l
#define msw CR0.w
#define cr0 cpu_state.CR0.l
#define msw cpu_state.CR0.w
uint32_t cr2, cr3, cr4;
uint32_t dr[8];