Added recompiled register versions of FADD, FDIV, FDIVR, FMUL, FSUB and FSUBR.
This commit is contained in:
parent
dbb01ef9e2
commit
78996b3e5c
31 changed files with 1642 additions and 166 deletions
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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*/
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
#include "codegen_backend_x86-64_defs.h"
|
||||
|
||||
#define BLOCK_SIZE 0x4000
|
||||
#define BLOCK_MASK 0x3fff
|
||||
#define BLOCK_START 0
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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*/
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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*/
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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
134
src/codegen_ops_fpu_arith.c
Normal 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;
|
||||
}
|
||||
12
src/codegen_ops_fpu_arith.h
Normal file
12
src/codegen_ops_fpu_arith.h
Normal 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);
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
16
src/ibm.h
16
src/ibm.h
|
|
@ -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];
|
||||
|
|
|
|||
Loading…
Reference in a new issue