Added recompiled versions of FIST and FISTP.
This commit is contained in:
parent
589f50e479
commit
87191dde55
29 changed files with 829 additions and 57 deletions
|
|
@ -8,6 +8,7 @@
|
||||||
#include "codegen_backend_arm_ops.h"
|
#include "codegen_backend_arm_ops.h"
|
||||||
#include "codegen_reg.h"
|
#include "codegen_reg.h"
|
||||||
#include "x86.h"
|
#include "x86.h"
|
||||||
|
#include "x87.h"
|
||||||
|
|
||||||
#if defined(__linux__) || defined(__APPLE__)
|
#if defined(__linux__) || defined(__APPLE__)
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
|
|
@ -27,9 +28,12 @@ void *codegen_mem_load_double;
|
||||||
void *codegen_mem_store_byte;
|
void *codegen_mem_store_byte;
|
||||||
void *codegen_mem_store_word;
|
void *codegen_mem_store_word;
|
||||||
void *codegen_mem_store_long;
|
void *codegen_mem_store_long;
|
||||||
|
void *codegen_mem_store_quad;
|
||||||
void *codegen_mem_store_single;
|
void *codegen_mem_store_single;
|
||||||
void *codegen_mem_store_double;
|
void *codegen_mem_store_double;
|
||||||
|
|
||||||
|
void *codegen_fp_round;
|
||||||
|
|
||||||
int codegen_host_reg_list[CODEGEN_HOST_REGS] =
|
int codegen_host_reg_list[CODEGEN_HOST_REGS] =
|
||||||
{
|
{
|
||||||
REG_R4,
|
REG_R4,
|
||||||
|
|
@ -167,7 +171,7 @@ static void build_store_routine(codeblock_t *block, int size, int is_float)
|
||||||
host_arm_ADD_REG(block, REG_R0, REG_R0, REG_R2);
|
host_arm_ADD_REG(block, REG_R0, REG_R0, REG_R2);
|
||||||
host_arm_VSTR_S(block, REG_D_TEMP, REG_R0, 0);
|
host_arm_VSTR_S(block, REG_D_TEMP, REG_R0, 0);
|
||||||
}
|
}
|
||||||
else if (size == 8 && is_float)
|
else if (size == 8)
|
||||||
{
|
{
|
||||||
host_arm_ADD_REG(block, REG_R0, REG_R0, REG_R2);
|
host_arm_ADD_REG(block, REG_R0, REG_R0, REG_R2);
|
||||||
host_arm_VSTR_D(block, REG_D_TEMP, REG_R0, 0);
|
host_arm_VSTR_D(block, REG_D_TEMP, REG_R0, 0);
|
||||||
|
|
@ -181,7 +185,7 @@ static void build_store_routine(codeblock_t *block, int size, int is_float)
|
||||||
host_arm_STR_IMM_WB(block, REG_LR, REG_HOST_SP, -4);
|
host_arm_STR_IMM_WB(block, REG_LR, REG_HOST_SP, -4);
|
||||||
if (size == 4 && is_float)
|
if (size == 4 && is_float)
|
||||||
host_arm_VMOV_32_S(block, REG_R1, REG_D_TEMP);
|
host_arm_VMOV_32_S(block, REG_R1, REG_D_TEMP);
|
||||||
else if (size == 8 && is_float)
|
else if (size == 8)
|
||||||
host_arm_VMOV_64_D(block, REG_R2, REG_R3, REG_D_TEMP);
|
host_arm_VMOV_64_D(block, REG_R2, REG_R3, REG_D_TEMP);
|
||||||
if (size == 1)
|
if (size == 1)
|
||||||
host_arm_BL(block, (uintptr_t)writememb386l);
|
host_arm_BL(block, (uintptr_t)writememb386l);
|
||||||
|
|
@ -220,12 +224,65 @@ static void build_loadstore_routines(codeblock_t *block)
|
||||||
build_store_routine(block, 2, 0);
|
build_store_routine(block, 2, 0);
|
||||||
codegen_mem_store_long = &codeblock[block_current].data[block_pos];
|
codegen_mem_store_long = &codeblock[block_current].data[block_pos];
|
||||||
build_store_routine(block, 4, 0);
|
build_store_routine(block, 4, 0);
|
||||||
|
codegen_mem_store_quad = &codeblock[block_current].data[block_pos];
|
||||||
|
build_store_routine(block, 8, 0);
|
||||||
codegen_mem_store_single = &codeblock[block_current].data[block_pos];
|
codegen_mem_store_single = &codeblock[block_current].data[block_pos];
|
||||||
build_store_routine(block, 4, 1);
|
build_store_routine(block, 4, 1);
|
||||||
codegen_mem_store_double = &codeblock[block_current].data[block_pos];
|
codegen_mem_store_double = &codeblock[block_current].data[block_pos];
|
||||||
build_store_routine(block, 8, 1);
|
build_store_routine(block, 8, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*VFP has a specific round-to-zero instruction, and the default rounding mode
|
||||||
|
is nearest. For round up/down, temporarily change the rounding mode in FPCSR*/
|
||||||
|
#define FPCSR_ROUNDING_MASK (3 << 22)
|
||||||
|
#define FPCSR_ROUNDING_UP (1 << 22)
|
||||||
|
#define FPCSR_ROUNDING_DOWN (2 << 22)
|
||||||
|
|
||||||
|
static void build_fp_round_routine(codeblock_t *block)
|
||||||
|
{
|
||||||
|
uint32_t *jump_table;
|
||||||
|
|
||||||
|
host_arm_MOV_REG(block, REG_TEMP2, REG_LR);
|
||||||
|
host_arm_MOV_REG(block, REG_LR, REG_TEMP2);
|
||||||
|
host_arm_LDR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.new_fp_control - (uintptr_t)&cpu_state);
|
||||||
|
host_arm_LDR_REG(block, REG_PC, REG_PC, REG_TEMP);
|
||||||
|
addlong(0);
|
||||||
|
|
||||||
|
jump_table = (uint32_t *)&block->data[block_pos];
|
||||||
|
addlong(0);
|
||||||
|
addlong(0);
|
||||||
|
addlong(0);
|
||||||
|
addlong(0);
|
||||||
|
|
||||||
|
jump_table[X87_ROUNDING_NEAREST] = (uint64_t)(uintptr_t)&block->data[block_pos]; //tie even
|
||||||
|
host_arm_VCVTR_IS_D(block, REG_D_TEMP, REG_D_TEMP);
|
||||||
|
host_arm_MOV_REG(block, REG_PC, REG_LR);
|
||||||
|
|
||||||
|
jump_table[X87_ROUNDING_UP] = (uint64_t)(uintptr_t)&block->data[block_pos]; //pos inf
|
||||||
|
host_arm_LDR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.old_fp_control - (uintptr_t)&cpu_state);
|
||||||
|
host_arm_BIC_IMM(block, REG_TEMP2, REG_TEMP, FPCSR_ROUNDING_MASK);
|
||||||
|
host_arm_ORR_IMM(block, REG_TEMP2, REG_TEMP2, FPCSR_ROUNDING_UP);
|
||||||
|
host_arm_VMSR_FPSCR(block, REG_TEMP2);
|
||||||
|
host_arm_VCVTR_IS_D(block, REG_D_TEMP, REG_D_TEMP);
|
||||||
|
host_arm_VMSR_FPSCR(block, REG_TEMP);
|
||||||
|
host_arm_MOV_REG(block, REG_PC, REG_LR);
|
||||||
|
|
||||||
|
jump_table[X87_ROUNDING_DOWN] = (uint64_t)(uintptr_t)&block->data[block_pos]; //neg inf
|
||||||
|
host_arm_LDR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.old_fp_control - (uintptr_t)&cpu_state);
|
||||||
|
host_arm_BIC_IMM(block, REG_TEMP2, REG_TEMP, FPCSR_ROUNDING_MASK);
|
||||||
|
host_arm_ORR_IMM(block, REG_TEMP2, REG_TEMP, FPCSR_ROUNDING_DOWN);
|
||||||
|
host_arm_VMSR_FPSCR(block, REG_TEMP2);
|
||||||
|
host_arm_VCVTR_IS_D(block, REG_D_TEMP, REG_D_TEMP);
|
||||||
|
host_arm_VMSR_FPSCR(block, REG_TEMP);
|
||||||
|
host_arm_MOV_REG(block, REG_PC, REG_LR);
|
||||||
|
|
||||||
|
jump_table[X87_ROUNDING_CHOP] = (uint64_t)(uintptr_t)&block->data[block_pos]; //zero
|
||||||
|
host_arm_VCVT_IS_D(block, REG_D_TEMP, REG_D_TEMP);
|
||||||
|
host_arm_MOV_REG(block, REG_PC, REG_LR);
|
||||||
|
|
||||||
|
block_pos = (block_pos + 63) & ~63;
|
||||||
|
}
|
||||||
|
|
||||||
void codegen_backend_init()
|
void codegen_backend_init()
|
||||||
{
|
{
|
||||||
int c;
|
int c;
|
||||||
|
|
@ -265,6 +322,22 @@ void codegen_backend_init()
|
||||||
block_current = BLOCK_SIZE;
|
block_current = BLOCK_SIZE;
|
||||||
block_pos = 0;
|
block_pos = 0;
|
||||||
build_loadstore_routines(&codeblock[block_current]);
|
build_loadstore_routines(&codeblock[block_current]);
|
||||||
|
|
||||||
|
codegen_fp_round = &codeblock[block_current].data[block_pos];
|
||||||
|
build_fp_round_routine(&codeblock[block_current]);
|
||||||
|
|
||||||
|
asm("vmrs %0, fpscr\n"
|
||||||
|
: "=r" (cpu_state.old_fp_control)
|
||||||
|
);
|
||||||
|
if ((cpu_state.old_fp_control >> 22) & 3)
|
||||||
|
fatal("VFP not in nearest rounding mode\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void codegen_set_rounding_mode(int mode)
|
||||||
|
{
|
||||||
|
if (mode < 0 || mode > 3)
|
||||||
|
fatal("codegen_set_rounding_mode - invalid mode\n");
|
||||||
|
cpu_state.new_fp_control = mode << 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*R10 - cpu_state*/
|
/*R10 - cpu_state*/
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
#include "codegen_backend_arm64_ops.h"
|
#include "codegen_backend_arm64_ops.h"
|
||||||
#include "codegen_reg.h"
|
#include "codegen_reg.h"
|
||||||
#include "x86.h"
|
#include "x86.h"
|
||||||
|
#include "x87.h"
|
||||||
|
|
||||||
#if defined(__linux__) || defined(__APPLE__)
|
#if defined(__linux__) || defined(__APPLE__)
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
|
|
@ -27,9 +28,13 @@ void *codegen_mem_load_double;
|
||||||
void *codegen_mem_store_byte;
|
void *codegen_mem_store_byte;
|
||||||
void *codegen_mem_store_word;
|
void *codegen_mem_store_word;
|
||||||
void *codegen_mem_store_long;
|
void *codegen_mem_store_long;
|
||||||
|
void *codegen_mem_store_quad;
|
||||||
void *codegen_mem_store_single;
|
void *codegen_mem_store_single;
|
||||||
void *codegen_mem_store_double;
|
void *codegen_mem_store_double;
|
||||||
|
|
||||||
|
void *codegen_fp_round;
|
||||||
|
void *codegen_fp_round_quad;
|
||||||
|
|
||||||
int codegen_host_reg_list[CODEGEN_HOST_REGS] =
|
int codegen_host_reg_list[CODEGEN_HOST_REGS] =
|
||||||
{
|
{
|
||||||
REG_X19,
|
REG_X19,
|
||||||
|
|
@ -168,7 +173,7 @@ static void build_store_routine(codeblock_t *block, int size, int is_float)
|
||||||
host_arm64_STR_REG(block, REG_X1, REG_X2, REG_X0);
|
host_arm64_STR_REG(block, REG_X1, REG_X2, REG_X0);
|
||||||
else if (size == 4 && is_float)
|
else if (size == 4 && is_float)
|
||||||
host_arm64_STR_REG_F32(block, REG_V_TEMP, REG_X2, REG_X0);
|
host_arm64_STR_REG_F32(block, REG_V_TEMP, REG_X2, REG_X0);
|
||||||
else if (size == 8 && is_float)
|
else if (size == 8)
|
||||||
host_arm64_STR_REG_F64(block, REG_V_TEMP, REG_X2, REG_X0);
|
host_arm64_STR_REG_F64(block, REG_V_TEMP, REG_X2, REG_X0);
|
||||||
host_arm64_MOVZ_IMM(block, REG_X1, 0);
|
host_arm64_MOVZ_IMM(block, REG_X1, 0);
|
||||||
host_arm64_RET(block, REG_X30);
|
host_arm64_RET(block, REG_X30);
|
||||||
|
|
@ -179,7 +184,7 @@ static void build_store_routine(codeblock_t *block, int size, int is_float)
|
||||||
host_arm64_STP_PREIDX_X(block, REG_X29, REG_X30, REG_SP, -16);
|
host_arm64_STP_PREIDX_X(block, REG_X29, REG_X30, REG_SP, -16);
|
||||||
if (size == 4 && is_float)
|
if (size == 4 && is_float)
|
||||||
host_arm64_FMOV_W_S(block, REG_W1, REG_V_TEMP);
|
host_arm64_FMOV_W_S(block, REG_W1, REG_V_TEMP);
|
||||||
else if (size == 8 && is_float)
|
else if (size == 8)
|
||||||
host_arm64_FMOV_Q_D(block, REG_X1, REG_V_TEMP);
|
host_arm64_FMOV_Q_D(block, REG_X1, REG_V_TEMP);
|
||||||
if (size == 1)
|
if (size == 1)
|
||||||
host_arm64_call(block, (uintptr_t)writememb386l);
|
host_arm64_call(block, (uintptr_t)writememb386l);
|
||||||
|
|
@ -219,12 +224,60 @@ static void build_loadstore_routines(codeblock_t *block)
|
||||||
build_store_routine(block, 2, 0);
|
build_store_routine(block, 2, 0);
|
||||||
codegen_mem_store_long = &codeblock[block_current].data[block_pos];
|
codegen_mem_store_long = &codeblock[block_current].data[block_pos];
|
||||||
build_store_routine(block, 4, 0);
|
build_store_routine(block, 4, 0);
|
||||||
|
codegen_mem_store_quad = &codeblock[block_current].data[block_pos];
|
||||||
|
build_store_routine(block, 8, 0);
|
||||||
codegen_mem_store_single = &codeblock[block_current].data[block_pos];
|
codegen_mem_store_single = &codeblock[block_current].data[block_pos];
|
||||||
build_store_routine(block, 4, 1);
|
build_store_routine(block, 4, 1);
|
||||||
codegen_mem_store_double = &codeblock[block_current].data[block_pos];
|
codegen_mem_store_double = &codeblock[block_current].data[block_pos];
|
||||||
build_store_routine(block, 8, 1);
|
build_store_routine(block, 8, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void build_fp_round_routine(codeblock_t *block, int is_quad)
|
||||||
|
{
|
||||||
|
uint64_t *jump_table;
|
||||||
|
|
||||||
|
host_arm64_LDR_IMM_W(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.new_fp_control - (uintptr_t)&cpu_state);
|
||||||
|
host_arm64_ADR(block, REG_TEMP2, 12);
|
||||||
|
host_arm64_LDR_REG_X(block, REG_TEMP2, REG_TEMP2, REG_TEMP);
|
||||||
|
host_arm64_BR(block, REG_TEMP2);
|
||||||
|
|
||||||
|
jump_table = &block->data[block_pos];
|
||||||
|
addquad(0);
|
||||||
|
addquad(0);
|
||||||
|
addquad(0);
|
||||||
|
addquad(0);
|
||||||
|
|
||||||
|
jump_table[X87_ROUNDING_NEAREST] = (uint64_t)(uintptr_t)&block->data[block_pos]; //tie even
|
||||||
|
if (is_quad)
|
||||||
|
host_arm64_FCVTNS_X_D(block, REG_TEMP, REG_V_TEMP);
|
||||||
|
else
|
||||||
|
host_arm64_FCVTNS_W_D(block, REG_TEMP, REG_V_TEMP);
|
||||||
|
host_arm64_RET(block, REG_X30);
|
||||||
|
|
||||||
|
jump_table[X87_ROUNDING_UP] = (uint64_t)(uintptr_t)&block->data[block_pos]; //pos inf
|
||||||
|
if (is_quad)
|
||||||
|
host_arm64_FCVTPS_X_D(block, REG_TEMP, REG_V_TEMP);
|
||||||
|
else
|
||||||
|
host_arm64_FCVTPS_W_D(block, REG_TEMP, REG_V_TEMP);
|
||||||
|
host_arm64_RET(block, REG_X30);
|
||||||
|
|
||||||
|
jump_table[X87_ROUNDING_DOWN] = (uint64_t)(uintptr_t)&block->data[block_pos]; //neg inf
|
||||||
|
if (is_quad)
|
||||||
|
host_arm64_FCVTMS_X_D(block, REG_TEMP, REG_V_TEMP);
|
||||||
|
else
|
||||||
|
host_arm64_FCVTMS_W_D(block, REG_TEMP, REG_V_TEMP);
|
||||||
|
host_arm64_RET(block, REG_X30);
|
||||||
|
|
||||||
|
jump_table[X87_ROUNDING_CHOP] = (uint64_t)(uintptr_t)&block->data[block_pos]; //zero
|
||||||
|
if (is_quad)
|
||||||
|
host_arm64_FCVTZS_X_D(block, REG_TEMP, REG_V_TEMP);
|
||||||
|
else
|
||||||
|
host_arm64_FCVTZS_W_D(block, REG_TEMP, REG_V_TEMP);
|
||||||
|
host_arm64_RET(block, REG_X30);
|
||||||
|
|
||||||
|
block_pos = (block_pos + 63) & ~63;
|
||||||
|
}
|
||||||
|
|
||||||
void codegen_backend_init()
|
void codegen_backend_init()
|
||||||
{
|
{
|
||||||
int c;
|
int c;
|
||||||
|
|
@ -265,6 +318,22 @@ void codegen_backend_init()
|
||||||
block_pos = 0;
|
block_pos = 0;
|
||||||
codegen_reset_literal_pool(&codeblock[block_current]);
|
codegen_reset_literal_pool(&codeblock[block_current]);
|
||||||
build_loadstore_routines(&codeblock[block_current]);
|
build_loadstore_routines(&codeblock[block_current]);
|
||||||
|
|
||||||
|
codegen_fp_round = &codeblock[block_current].data[block_pos];
|
||||||
|
build_fp_round_routine(&codeblock[block_current], 0);
|
||||||
|
codegen_fp_round_quad = &codeblock[block_current].data[block_pos];
|
||||||
|
build_fp_round_routine(&codeblock[block_current], 1);
|
||||||
|
|
||||||
|
asm("mrs %0, fpcr\n"
|
||||||
|
: "=r" (cpu_state.old_fp_control)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void codegen_set_rounding_mode(int mode)
|
||||||
|
{
|
||||||
|
if (mode < 0 || mode > 3)
|
||||||
|
fatal("codegen_set_rounding_mode - invalid mode\n");
|
||||||
|
cpu_state.new_fp_control = mode << 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*R11 - literal pool
|
/*R11 - literal pool
|
||||||
|
|
|
||||||
|
|
@ -124,5 +124,9 @@ extern void *codegen_mem_load_double;
|
||||||
extern void *codegen_mem_store_byte;
|
extern void *codegen_mem_store_byte;
|
||||||
extern void *codegen_mem_store_word;
|
extern void *codegen_mem_store_word;
|
||||||
extern void *codegen_mem_store_long;
|
extern void *codegen_mem_store_long;
|
||||||
|
extern void *codegen_mem_store_quad;
|
||||||
extern void *codegen_mem_store_single;
|
extern void *codegen_mem_store_single;
|
||||||
extern void *codegen_mem_store_double;
|
extern void *codegen_mem_store_double;
|
||||||
|
|
||||||
|
extern void *codegen_fp_round;
|
||||||
|
extern void *codegen_fp_round_quad;
|
||||||
|
|
@ -48,6 +48,7 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val)
|
||||||
#define OPCODE_SHIFT 24
|
#define OPCODE_SHIFT 24
|
||||||
#define OPCODE_ADD_IMM (0x11 << OPCODE_SHIFT)
|
#define OPCODE_ADD_IMM (0x11 << OPCODE_SHIFT)
|
||||||
#define OPCODE_ADDX_IMM (0x91 << OPCODE_SHIFT)
|
#define OPCODE_ADDX_IMM (0x91 << OPCODE_SHIFT)
|
||||||
|
#define OPCODE_ADR (0x10 << OPCODE_SHIFT)
|
||||||
#define OPCODE_B (0x14 << OPCODE_SHIFT)
|
#define OPCODE_B (0x14 << OPCODE_SHIFT)
|
||||||
#define OPCODE_BCOND (0x54 << OPCODE_SHIFT)
|
#define OPCODE_BCOND (0x54 << OPCODE_SHIFT)
|
||||||
#define OPCODE_CBNZ (0xb5 << OPCODE_SHIFT)
|
#define OPCODE_CBNZ (0xb5 << OPCODE_SHIFT)
|
||||||
|
|
@ -59,6 +60,7 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val)
|
||||||
#define OPCODE_LDR_LITERAL_X (0x58 << OPCODE_SHIFT)
|
#define OPCODE_LDR_LITERAL_X (0x58 << OPCODE_SHIFT)
|
||||||
#define OPCODE_SUB_IMM (0x51 << OPCODE_SHIFT)
|
#define OPCODE_SUB_IMM (0x51 << OPCODE_SHIFT)
|
||||||
#define OPCODE_SUBX_IMM (0xd1 << OPCODE_SHIFT)
|
#define OPCODE_SUBX_IMM (0xd1 << OPCODE_SHIFT)
|
||||||
|
#define OPCODE_TBNZ (0x37 << OPCODE_SHIFT)
|
||||||
|
|
||||||
#define OPCODE_AND_IMM (0x024 << 23)
|
#define OPCODE_AND_IMM (0x024 << 23)
|
||||||
#define OPCODE_ANDS_IMM (0x0e4 << 23)
|
#define OPCODE_ANDS_IMM (0x0e4 << 23)
|
||||||
|
|
@ -69,6 +71,7 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val)
|
||||||
|
|
||||||
#define OPCODE_BFI (0x0cc << 22)
|
#define OPCODE_BFI (0x0cc << 22)
|
||||||
#define OPCODE_LDR_IMM_W (0x2e5 << 22)
|
#define OPCODE_LDR_IMM_W (0x2e5 << 22)
|
||||||
|
#define OPCODE_LDR_IMM_X (0x3e5 << 22)
|
||||||
#define OPCODE_LDR_IMM_F64 (0x3f5 << 22)
|
#define OPCODE_LDR_IMM_F64 (0x3f5 << 22)
|
||||||
#define OPCODE_LDRB_IMM_W (0x0e5 << 22)
|
#define OPCODE_LDRB_IMM_W (0x0e5 << 22)
|
||||||
#define OPCODE_LDRH_IMM (0x1e5 << 22)
|
#define OPCODE_LDRH_IMM (0x1e5 << 22)
|
||||||
|
|
@ -105,6 +108,14 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val)
|
||||||
#define OPCODE_FADD_D (0x1e602800)
|
#define OPCODE_FADD_D (0x1e602800)
|
||||||
#define OPCODE_FCVT_D_S (0x1e22c000)
|
#define OPCODE_FCVT_D_S (0x1e22c000)
|
||||||
#define OPCODE_FCVT_S_D (0x1e624000)
|
#define OPCODE_FCVT_S_D (0x1e624000)
|
||||||
|
#define OPCODE_FCVTMS_W_D (0x1e700000)
|
||||||
|
#define OPCODE_FCVTMS_X_D (0x9e700000)
|
||||||
|
#define OPCODE_FCVTNS_W_D (0x1e600000)
|
||||||
|
#define OPCODE_FCVTNS_X_D (0x9e600000)
|
||||||
|
#define OPCODE_FCVTPS_W_D (0x1e680000)
|
||||||
|
#define OPCODE_FCVTPS_X_D (0x9e680000)
|
||||||
|
#define OPCODE_FCVTZS_W_D (0x1e780000)
|
||||||
|
#define OPCODE_FCVTZS_X_D (0x9e780000)
|
||||||
#define OPCODE_FDIV_D (0x1e601800)
|
#define OPCODE_FDIV_D (0x1e601800)
|
||||||
#define OPCODE_FMOV_D_D (0x1e604000)
|
#define OPCODE_FMOV_D_D (0x1e604000)
|
||||||
#define OPCODE_FMOV_D_Q (0x9e670000)
|
#define OPCODE_FMOV_D_Q (0x9e670000)
|
||||||
|
|
@ -112,8 +123,10 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val)
|
||||||
#define OPCODE_FMOV_S_W (0x1e270000)
|
#define OPCODE_FMOV_S_W (0x1e270000)
|
||||||
#define OPCODE_FMOV_W_S (0x1e260000)
|
#define OPCODE_FMOV_W_S (0x1e260000)
|
||||||
#define OPCODE_FMUL_D (0x1e600800)
|
#define OPCODE_FMUL_D (0x1e600800)
|
||||||
|
#define OPCODE_FRINTX_D (0x1e674000)
|
||||||
#define OPCODE_FSUB_D (0x1e603800)
|
#define OPCODE_FSUB_D (0x1e603800)
|
||||||
#define OPCODE_LDR_REG (0xb8606800)
|
#define OPCODE_LDR_REG (0xb8606800)
|
||||||
|
#define OPCODE_LDRX_REG (0xf8606800)
|
||||||
#define OPCODE_LDRB_REG (0x38606800)
|
#define OPCODE_LDRB_REG (0x38606800)
|
||||||
#define OPCODE_LDRH_REG (0x78606800)
|
#define OPCODE_LDRH_REG (0x78606800)
|
||||||
#define OPCODE_LDRX_REG_LSL3 (0xf8607800)
|
#define OPCODE_LDRX_REG_LSL3 (0xf8607800)
|
||||||
|
|
@ -122,6 +135,7 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val)
|
||||||
#define OPCODE_LDR_REG_F64_S (0xfc607800)
|
#define OPCODE_LDR_REG_F64_S (0xfc607800)
|
||||||
#define OPCODE_LSL (0x1ac02000)
|
#define OPCODE_LSL (0x1ac02000)
|
||||||
#define OPCODE_LSR (0x1ac02400)
|
#define OPCODE_LSR (0x1ac02400)
|
||||||
|
#define OPCODE_MSR_FPCR (0xd51b4400)
|
||||||
#define OPCODE_NOP (0xd503201f)
|
#define OPCODE_NOP (0xd503201f)
|
||||||
#define OPCODE_RET (0xd65f0000)
|
#define OPCODE_RET (0xd65f0000)
|
||||||
#define OPCODE_SCVTF_D_Q (0x9e620000)
|
#define OPCODE_SCVTF_D_Q (0x9e620000)
|
||||||
|
|
@ -145,7 +159,10 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val)
|
||||||
#define IMMR(immr) ((immr) << 16)
|
#define IMMR(immr) ((immr) << 16)
|
||||||
#define IMMS(imms) ((imms) << 10)
|
#define IMMS(imms) ((imms) << 10)
|
||||||
|
|
||||||
|
#define BIT_TBxZ(bit) ((((bit) & 0x1f) << 19) | (((bit) & 0x20) ? (1 << 31) : 0))
|
||||||
|
|
||||||
#define OFFSET19(offset) (((offset >> 2) << 5) & 0x00ffffe0)
|
#define OFFSET19(offset) (((offset >> 2) << 5) & 0x00ffffe0)
|
||||||
|
#define OFFSET20(offset) (((offset & 3) << 29) | ((((offset) & 0x1fffff) >> 2) << 5))
|
||||||
#define OFFSET26(offset) ((offset >> 2) & 0x03ffffff)
|
#define OFFSET26(offset) ((offset >> 2) & 0x03ffffff)
|
||||||
|
|
||||||
#define OFFSET12_B(offset) (offset << 10)
|
#define OFFSET12_B(offset) (offset << 10)
|
||||||
|
|
@ -254,6 +271,11 @@ void host_arm64_ADD_REG_LSR(codeblock_t *block, int dst_reg, int src_n_reg, int
|
||||||
codegen_addlong(block, OPCODE_ADD_LSR | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift));
|
codegen_addlong(block, OPCODE_ADD_LSR | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void host_arm64_ADR(codeblock_t *block, int dst_reg, int offset)
|
||||||
|
{
|
||||||
|
codegen_addlong(block, OPCODE_ADR | Rd(dst_reg) | OFFSET20(offset));
|
||||||
|
}
|
||||||
|
|
||||||
void host_arm64_AND_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data)
|
void host_arm64_AND_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data)
|
||||||
{
|
{
|
||||||
if (imm_data == 0xff) /*Quick hack until proper immediate generation is written */
|
if (imm_data == 0xff) /*Quick hack until proper immediate generation is written */
|
||||||
|
|
@ -534,6 +556,39 @@ void host_arm64_FCVT_S_D(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
codegen_addlong(block, OPCODE_FCVT_S_D | Rd(dst_reg) | Rn(src_reg));
|
codegen_addlong(block, OPCODE_FCVT_S_D | Rd(dst_reg) | Rn(src_reg));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void host_arm64_FCVTMS_W_D(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_addlong(block, OPCODE_FCVTMS_W_D | Rd(dst_reg) | Rn(src_reg));
|
||||||
|
}
|
||||||
|
void host_arm64_FCVTMS_X_D(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_addlong(block, OPCODE_FCVTMS_X_D | Rd(dst_reg) | Rn(src_reg));
|
||||||
|
}
|
||||||
|
void host_arm64_FCVTNS_W_D(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_addlong(block, OPCODE_FCVTNS_W_D | Rd(dst_reg) | Rn(src_reg));
|
||||||
|
}
|
||||||
|
void host_arm64_FCVTNS_X_D(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_addlong(block, OPCODE_FCVTNS_X_D | Rd(dst_reg) | Rn(src_reg));
|
||||||
|
}
|
||||||
|
void host_arm64_FCVTPS_W_D(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_addlong(block, OPCODE_FCVTPS_W_D | Rd(dst_reg) | Rn(src_reg));
|
||||||
|
}
|
||||||
|
void host_arm64_FCVTPS_X_D(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_addlong(block, OPCODE_FCVTPS_X_D | Rd(dst_reg) | Rn(src_reg));
|
||||||
|
}
|
||||||
|
void host_arm64_FCVTZS_W_D(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_addlong(block, OPCODE_FCVTZS_W_D | Rd(dst_reg) | Rn(src_reg));
|
||||||
|
}
|
||||||
|
void host_arm64_FCVTZS_X_D(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_addlong(block, OPCODE_FCVTZS_X_D | Rd(dst_reg) | Rn(src_reg));
|
||||||
|
}
|
||||||
|
|
||||||
void host_arm64_FDIV_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)
|
||||||
{
|
{
|
||||||
codegen_addlong(block, OPCODE_FDIV_D | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg));
|
codegen_addlong(block, OPCODE_FDIV_D | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg));
|
||||||
|
|
@ -570,6 +625,11 @@ void host_arm64_FMOV_W_S(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
codegen_addlong(block, OPCODE_FMOV_W_S | Rd(dst_reg) | Rn(src_reg));
|
codegen_addlong(block, OPCODE_FMOV_W_S | Rd(dst_reg) | Rn(src_reg));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void host_arm64_FRINTX_D(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_addlong(block, OPCODE_FRINTX_D | Rd(dst_reg) | Rn(src_reg));
|
||||||
|
}
|
||||||
|
|
||||||
void host_arm64_LDP_POSTIDX_X(codeblock_t *block, int src_reg1, int src_reg2, int base_reg, int offset)
|
void host_arm64_LDP_POSTIDX_X(codeblock_t *block, int src_reg1, int src_reg2, int base_reg, int offset)
|
||||||
{
|
{
|
||||||
if (!in_range7_x(offset))
|
if (!in_range7_x(offset))
|
||||||
|
|
@ -583,6 +643,12 @@ void host_arm64_LDR_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int of
|
||||||
fatal("host_arm64_LDR_IMM_W out of range12 %i\n", offset);
|
fatal("host_arm64_LDR_IMM_W out of range12 %i\n", offset);
|
||||||
codegen_addlong(block, OPCODE_LDR_IMM_W | OFFSET12_W(offset) | Rn(base_reg) | Rt(dest_reg));
|
codegen_addlong(block, OPCODE_LDR_IMM_W | OFFSET12_W(offset) | Rn(base_reg) | Rt(dest_reg));
|
||||||
}
|
}
|
||||||
|
void host_arm64_LDR_IMM_X(codeblock_t *block, int dest_reg, int base_reg, int offset)
|
||||||
|
{
|
||||||
|
if (!in_range12_q(offset))
|
||||||
|
fatal("host_arm64_LDR_IMM_X out of range12 %i\n", offset);
|
||||||
|
codegen_addlong(block, OPCODE_LDR_IMM_X | OFFSET12_Q(offset) | Rn(base_reg) | Rt(dest_reg));
|
||||||
|
}
|
||||||
|
|
||||||
void host_arm64_LDR_LITERAL_W(codeblock_t *block, int dest_reg, int literal_offset)
|
void host_arm64_LDR_LITERAL_W(codeblock_t *block, int dest_reg, int literal_offset)
|
||||||
{
|
{
|
||||||
|
|
@ -606,6 +672,10 @@ 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));
|
codegen_addlong(block, OPCODE_LDR_REG | Rn(base_reg) | Rm(offset_reg) | Rt(dest_reg));
|
||||||
}
|
}
|
||||||
|
void host_arm64_LDR_REG_X(codeblock_t *block, int dest_reg, int base_reg, int offset_reg)
|
||||||
|
{
|
||||||
|
codegen_addlong(block, OPCODE_LDRX_REG | Rn(base_reg) | Rm(offset_reg) | Rt(dest_reg));
|
||||||
|
}
|
||||||
|
|
||||||
void host_arm64_LDR_REG_F32(codeblock_t *block, int dest_reg, int base_reg, int offset_reg)
|
void host_arm64_LDR_REG_F32(codeblock_t *block, int dest_reg, int base_reg, int offset_reg)
|
||||||
{
|
{
|
||||||
|
|
@ -711,6 +781,11 @@ void host_arm64_MOVK_IMM(codeblock_t *block, int reg, uint32_t imm_data)
|
||||||
codegen_addlong(block, OPCODE_MOVK_W | MOV_WIDE_HW(hw) | IMM16(imm_data) | Rd(reg));
|
codegen_addlong(block, OPCODE_MOVK_W | MOV_WIDE_HW(hw) | IMM16(imm_data) | Rd(reg));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void host_arm64_MSR_FPCR(codeblock_t *block, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_addlong(block, OPCODE_MSR_FPCR | Rd(src_reg));
|
||||||
|
}
|
||||||
|
|
||||||
void host_arm64_NOP(codeblock_t *block)
|
void host_arm64_NOP(codeblock_t *block)
|
||||||
{
|
{
|
||||||
codegen_addlong(block, OPCODE_NOP);
|
codegen_addlong(block, OPCODE_NOP);
|
||||||
|
|
@ -862,6 +937,12 @@ void host_arm64_SUB_REG_LSR(codeblock_t *block, int dst_reg, int src_n_reg, int
|
||||||
codegen_addlong(block, OPCODE_SUB_LSR | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift));
|
codegen_addlong(block, OPCODE_SUB_LSR | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t *host_arm64_TBNZ(codeblock_t *block, int reg, int bit)
|
||||||
|
{
|
||||||
|
codegen_addlong(block, OPCODE_TBNZ | Rt(reg) | BIT_TBxZ(bit));
|
||||||
|
return (uint32_t *)&block->data[block_pos-4];
|
||||||
|
}
|
||||||
|
|
||||||
void host_arm64_UBFX(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width)
|
void host_arm64_UBFX(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width)
|
||||||
{
|
{
|
||||||
codegen_addlong(block, OPCODE_UBFX | Rd(dst_reg) | Rn(src_reg) | IMMN(0) | IMMR(lsb) | IMMS((lsb+width-1) & 31));
|
codegen_addlong(block, OPCODE_UBFX | Rd(dst_reg) | Rn(src_reg) | IMMN(0) | IMMR(lsb) | IMMS((lsb+width-1) & 31));
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@ void host_arm64_ADD_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t
|
||||||
void host_arm64_ADD_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift);
|
void host_arm64_ADD_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift);
|
||||||
void host_arm64_ADD_REG_LSR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift);
|
void host_arm64_ADD_REG_LSR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift);
|
||||||
|
|
||||||
|
void host_arm64_ADR(codeblock_t *block, int dst_reg, int offset);
|
||||||
|
|
||||||
void host_arm64_AND_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data);
|
void host_arm64_AND_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data);
|
||||||
void host_arm64_AND_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift);
|
void host_arm64_AND_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift);
|
||||||
void host_arm64_AND_REG_ASR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift);
|
void host_arm64_AND_REG_ASR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift);
|
||||||
|
|
@ -59,18 +61,31 @@ void host_arm64_FSUB_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m
|
||||||
void host_arm64_FCVT_D_S(codeblock_t *block, int dst_reg, int src_reg);
|
void host_arm64_FCVT_D_S(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
void host_arm64_FCVT_S_D(codeblock_t *block, int dst_reg, int src_reg);
|
void host_arm64_FCVT_S_D(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
|
||||||
|
void host_arm64_FCVTMS_W_D(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_arm64_FCVTMS_X_D(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_arm64_FCVTNS_W_D(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_arm64_FCVTNS_X_D(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_arm64_FCVTPS_W_D(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_arm64_FCVTPS_X_D(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_arm64_FCVTZS_W_D(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_arm64_FCVTZS_X_D(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
|
||||||
void host_arm64_FMOV_D_D(codeblock_t *block, int dst_reg, int src_reg);
|
void host_arm64_FMOV_D_D(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
void host_arm64_FMOV_D_Q(codeblock_t *block, int dst_reg, int src_reg);
|
void host_arm64_FMOV_D_Q(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
void host_arm64_FMOV_Q_D(codeblock_t *block, int dst_reg, int src_reg);
|
void host_arm64_FMOV_Q_D(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
void host_arm64_FMOV_S_W(codeblock_t *block, int dst_reg, int src_reg);
|
void host_arm64_FMOV_S_W(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
void host_arm64_FMOV_W_S(codeblock_t *block, int dst_reg, int src_reg);
|
void host_arm64_FMOV_W_S(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
|
||||||
|
void host_arm64_FRINTX_D(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
|
||||||
void host_arm64_LDP_POSTIDX_X(codeblock_t *block, int src_reg1, int src_reg2, int base_reg, int offset);
|
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);
|
void host_arm64_LDR_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int offset);
|
||||||
|
void host_arm64_LDR_IMM_X(codeblock_t *block, int dest_reg, int base_reg, int offset);
|
||||||
void host_arm64_LDR_LITERAL_W(codeblock_t *block, int dest_reg, int literal_offset);
|
void host_arm64_LDR_LITERAL_W(codeblock_t *block, int dest_reg, int literal_offset);
|
||||||
void host_arm64_LDR_LITERAL_X(codeblock_t *block, int dest_reg, int literal_offset);
|
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_REG(codeblock_t *block, int dest_reg, int base_reg, int offset_reg);
|
||||||
|
void host_arm64_LDR_REG_X(codeblock_t *block, int dest_reg, int base_reg, int offset_reg);
|
||||||
|
|
||||||
void host_arm64_LDR_REG_F32(codeblock_t *block, int dest_reg, int base_reg, int offset_reg);
|
void host_arm64_LDR_REG_F32(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_IMM_F64(codeblock_t *block, int dest_reg, int base_reg, int offset);
|
||||||
|
|
@ -97,6 +112,8 @@ void host_arm64_MOVX_REG(codeblock_t *block, int dst_reg, int src_m_reg, int shi
|
||||||
void host_arm64_MOVZ_IMM(codeblock_t *block, int reg, uint32_t imm_data);
|
void host_arm64_MOVZ_IMM(codeblock_t *block, int reg, uint32_t imm_data);
|
||||||
void host_arm64_MOVK_IMM(codeblock_t *block, int reg, uint32_t imm_data);
|
void host_arm64_MOVK_IMM(codeblock_t *block, int reg, uint32_t imm_data);
|
||||||
|
|
||||||
|
void host_arm64_MSR_FPCR(codeblock_t *block, int src_reg);
|
||||||
|
|
||||||
void host_arm64_NOP(codeblock_t *block);
|
void host_arm64_NOP(codeblock_t *block);
|
||||||
|
|
||||||
void host_arm64_ORR_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data);
|
void host_arm64_ORR_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data);
|
||||||
|
|
@ -130,6 +147,8 @@ void host_arm64_SUB_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t
|
||||||
void host_arm64_SUB_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift);
|
void host_arm64_SUB_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift);
|
||||||
void host_arm64_SUB_REG_LSR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift);
|
void host_arm64_SUB_REG_LSR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift);
|
||||||
|
|
||||||
|
uint32_t *host_arm64_TBNZ(codeblock_t *block, int reg, int bit);
|
||||||
|
|
||||||
#define host_arm64_TST_IMM(block, src_n_reg, imm_data) host_arm64_ANDS_IMM(block, REG_XZR, src_n_reg, imm_data)
|
#define host_arm64_TST_IMM(block, src_n_reg, imm_data) host_arm64_ANDS_IMM(block, REG_XZR, src_n_reg, imm_data)
|
||||||
|
|
||||||
void host_arm64_UBFX(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width);
|
void host_arm64_UBFX(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width);
|
||||||
|
|
|
||||||
|
|
@ -942,8 +942,13 @@ static int codegen_MEM_STORE_REG(codeblock_t *block, uop_t *uop)
|
||||||
host_arm64_MOV_REG(block, REG_W1, src_reg, 0);
|
host_arm64_MOV_REG(block, REG_W1, src_reg, 0);
|
||||||
host_arm64_call(block, codegen_mem_store_long);
|
host_arm64_call(block, codegen_mem_store_long);
|
||||||
}
|
}
|
||||||
|
else if (REG_IS_Q(src_size))
|
||||||
|
{
|
||||||
|
host_arm64_FMOV_D_D(block, REG_V_TEMP, src_reg);
|
||||||
|
host_arm64_call(block, codegen_mem_store_quad);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
fatal("MEM_STORE_REG - %02x\n", uop->dest_reg_a_real);
|
fatal("MEM_STORE_REG - %02x\n", uop->src_reg_c_real);
|
||||||
host_arm64_CBNZ(block, REG_X1, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]);
|
host_arm64_CBNZ(block, REG_X1, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -1187,6 +1192,52 @@ static int codegen_MOV_DOUBLE_INT(codeblock_t *block, uop_t *uop)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
static int codegen_MOV_INT_DOUBLE(codeblock_t *block, uop_t *uop)
|
||||||
|
{
|
||||||
|
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real);
|
||||||
|
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real);
|
||||||
|
|
||||||
|
if (REG_IS_L(dest_size) && REG_IS_D(src_size))
|
||||||
|
{
|
||||||
|
host_arm64_FMOV_D_D(block, REG_V_TEMP, src_reg);
|
||||||
|
host_arm64_call(block, codegen_fp_round);
|
||||||
|
host_arm64_MOV_REG(block, dest_reg, REG_TEMP, 0);
|
||||||
|
}
|
||||||
|
else if (REG_IS_W(dest_size) && REG_IS_D(src_size))
|
||||||
|
{
|
||||||
|
host_arm64_FMOV_D_D(block, REG_V_TEMP, src_reg);
|
||||||
|
host_arm64_call(block, codegen_fp_round);
|
||||||
|
host_arm64_BFI(block, dest_reg, REG_TEMP, 0, 16);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
fatal("MOV_INT_DOUBLE %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static int codegen_MOV_INT_DOUBLE_64(codeblock_t *block, uop_t *uop)
|
||||||
|
{
|
||||||
|
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), src_64_reg = HOST_REG_GET(uop->src_reg_b_real), tag_reg = HOST_REG_GET(uop->src_reg_c_real);
|
||||||
|
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real), src_64_size = IREG_GET_SIZE(uop->src_reg_b_real);
|
||||||
|
|
||||||
|
if (REG_IS_Q(dest_size) && REG_IS_D(src_size) && REG_IS_Q(src_64_size))
|
||||||
|
{
|
||||||
|
uint8_t *branch_offset;
|
||||||
|
|
||||||
|
/*If TAG_UINT64 is set then the source is MM[]. Otherwise it is a double in ST()*/
|
||||||
|
host_arm64_FMOV_D_D(block, dest_reg, src_64_reg);
|
||||||
|
branch_offset = host_arm64_TBNZ(block, tag_reg, 7);
|
||||||
|
|
||||||
|
host_arm64_FMOV_D_D(block, REG_V_TEMP, src_reg);
|
||||||
|
host_arm64_call(block, codegen_fp_round_quad);
|
||||||
|
host_arm64_FMOV_D_Q(block, dest_reg, REG_TEMP);
|
||||||
|
|
||||||
|
host_arm64_branch_set_offset(branch_offset, &block->data[block_pos]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
fatal("MOV_INT_DOUBLE_64 %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int codegen_OR(codeblock_t *block, uop_t *uop)
|
static int codegen_OR(codeblock_t *block, uop_t *uop)
|
||||||
{
|
{
|
||||||
|
|
@ -1719,6 +1770,8 @@ const uOpFn uop_handlers[UOP_MAX] =
|
||||||
[UOP_MOVSX & UOP_MASK] = codegen_MOVSX,
|
[UOP_MOVSX & UOP_MASK] = codegen_MOVSX,
|
||||||
[UOP_MOVZX & UOP_MASK] = codegen_MOVZX,
|
[UOP_MOVZX & UOP_MASK] = codegen_MOVZX,
|
||||||
[UOP_MOV_DOUBLE_INT & UOP_MASK] = codegen_MOV_DOUBLE_INT,
|
[UOP_MOV_DOUBLE_INT & UOP_MASK] = codegen_MOV_DOUBLE_INT,
|
||||||
|
[UOP_MOV_INT_DOUBLE & UOP_MASK] = codegen_MOV_INT_DOUBLE,
|
||||||
|
[UOP_MOV_INT_DOUBLE_64 & UOP_MASK] = codegen_MOV_INT_DOUBLE_64,
|
||||||
|
|
||||||
[UOP_ADD & UOP_MASK] = codegen_ADD,
|
[UOP_ADD & UOP_MASK] = codegen_ADD,
|
||||||
[UOP_ADD_IMM & UOP_MASK] = codegen_ADD_IMM,
|
[UOP_ADD_IMM & UOP_MASK] = codegen_ADD_IMM,
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,8 @@
|
||||||
|
|
||||||
#define REG_CPUSTATE REG_R10
|
#define REG_CPUSTATE REG_R10
|
||||||
|
|
||||||
#define REG_TEMP REG_R3
|
#define REG_TEMP REG_R3
|
||||||
|
#define REG_TEMP2 REG_R2
|
||||||
|
|
||||||
#define REG_D0 0
|
#define REG_D0 0
|
||||||
#define REG_D1 1
|
#define REG_D1 1
|
||||||
|
|
@ -76,5 +77,8 @@ extern void *codegen_mem_load_double;
|
||||||
extern void *codegen_mem_store_byte;
|
extern void *codegen_mem_store_byte;
|
||||||
extern void *codegen_mem_store_word;
|
extern void *codegen_mem_store_word;
|
||||||
extern void *codegen_mem_store_long;
|
extern void *codegen_mem_store_long;
|
||||||
|
extern void *codegen_mem_store_quad;
|
||||||
extern void *codegen_mem_store_single;
|
extern void *codegen_mem_store_single;
|
||||||
extern void *codegen_mem_store_double;
|
extern void *codegen_mem_store_double;
|
||||||
|
|
||||||
|
extern void *codegen_fp_round;
|
||||||
|
|
@ -104,9 +104,11 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val)
|
||||||
#define OPCODE_UXTB 0xe6ef0070
|
#define OPCODE_UXTB 0xe6ef0070
|
||||||
#define OPCODE_UXTH 0xe6ff0070
|
#define OPCODE_UXTH 0xe6ff0070
|
||||||
#define OPCODE_VADD 0xee300b00
|
#define OPCODE_VADD 0xee300b00
|
||||||
#define OPCODE_VCVT_D_IS 0xeeb80bc0
|
#define OPCODE_VCVT_D_IS 0xeeb80bc0
|
||||||
#define OPCODE_VCVT_D_S 0xeeb70ac0
|
#define OPCODE_VCVT_D_S 0xeeb70ac0
|
||||||
#define OPCODE_VCVT_S_D 0xeeb70bc0
|
#define OPCODE_VCVT_IS_D 0xeebd0bc0
|
||||||
|
#define OPCODE_VCVT_S_D 0xeeb70bc0
|
||||||
|
#define OPCODE_VCVTR_IS_D 0xeebd0b40
|
||||||
#define OPCODE_VDIV 0xee800b00
|
#define OPCODE_VDIV 0xee800b00
|
||||||
#define OPCODE_VLDR_D 0xed900b00
|
#define OPCODE_VLDR_D 0xed900b00
|
||||||
#define OPCODE_VLDR_S 0xed900a00
|
#define OPCODE_VLDR_S 0xed900a00
|
||||||
|
|
@ -115,6 +117,7 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val)
|
||||||
#define OPCODE_VMOV_D_64 0xec400b10
|
#define OPCODE_VMOV_D_64 0xec400b10
|
||||||
#define OPCODE_VMOV_S_32 0xee000a10
|
#define OPCODE_VMOV_S_32 0xee000a10
|
||||||
#define OPCODE_VMOV_D_D 0xeeb00b40
|
#define OPCODE_VMOV_D_D 0xeeb00b40
|
||||||
|
#define OPCODE_VMSR_FPSCR 0xeee10a10
|
||||||
#define OPCODE_VMUL 0xee200b00
|
#define OPCODE_VMUL 0xee200b00
|
||||||
#define OPCODE_VSTR_D 0xed800b00
|
#define OPCODE_VSTR_D 0xed800b00
|
||||||
#define OPCODE_VSTR_S 0xed800a00
|
#define OPCODE_VSTR_S 0xed800a00
|
||||||
|
|
@ -770,10 +773,18 @@ void host_arm_VCVT_D_S(codeblock_t *block, int dest_reg, int src_reg)
|
||||||
{
|
{
|
||||||
codegen_addlong(block, COND_AL | OPCODE_VCVT_D_S | Vd(dest_reg) | Vm(src_reg));
|
codegen_addlong(block, COND_AL | OPCODE_VCVT_D_S | Vd(dest_reg) | Vm(src_reg));
|
||||||
}
|
}
|
||||||
|
void host_arm_VCVT_IS_D(codeblock_t *block, int dest_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_addlong(block, COND_AL | OPCODE_VCVT_IS_D | Vd(dest_reg) | Vm(src_reg));
|
||||||
|
}
|
||||||
void host_arm_VCVT_S_D(codeblock_t *block, int dest_reg, int src_reg)
|
void host_arm_VCVT_S_D(codeblock_t *block, int dest_reg, int src_reg)
|
||||||
{
|
{
|
||||||
codegen_addlong(block, COND_AL | OPCODE_VCVT_S_D | Vd(dest_reg) | Vm(src_reg));
|
codegen_addlong(block, COND_AL | OPCODE_VCVT_S_D | Vd(dest_reg) | Vm(src_reg));
|
||||||
}
|
}
|
||||||
|
void host_arm_VCVTR_IS_D(codeblock_t *block, int dest_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_addlong(block, COND_AL | OPCODE_VCVTR_IS_D | Vd(dest_reg) | Vm(src_reg));
|
||||||
|
}
|
||||||
void host_arm_VDIV_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)
|
||||||
{
|
{
|
||||||
codegen_addlong(block, COND_AL | OPCODE_VDIV | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m));
|
codegen_addlong(block, COND_AL | OPCODE_VDIV | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m));
|
||||||
|
|
@ -810,6 +821,10 @@ void host_arm_VMOV_D_D(codeblock_t *block, int dest_reg, int src_reg)
|
||||||
{
|
{
|
||||||
codegen_addlong(block, COND_AL | OPCODE_VMOV_D_D | Vd(dest_reg) | Vm(src_reg));
|
codegen_addlong(block, COND_AL | OPCODE_VMOV_D_D | Vd(dest_reg) | Vm(src_reg));
|
||||||
}
|
}
|
||||||
|
void host_arm_VMSR_FPSCR(codeblock_t *block, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_addlong(block, COND_AL | OPCODE_VMSR_FPSCR | Rd(src_reg));
|
||||||
|
}
|
||||||
void host_arm_VMUL_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m)
|
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));
|
codegen_addlong(block, COND_AL | OPCODE_VMUL | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m));
|
||||||
|
|
|
||||||
|
|
@ -118,7 +118,9 @@ 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_VADD_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
|
||||||
void host_arm_VCVT_D_IS(codeblock_t *block, int dest_reg, int src_reg);
|
void host_arm_VCVT_D_IS(codeblock_t *block, int dest_reg, int src_reg);
|
||||||
void host_arm_VCVT_D_S(codeblock_t *block, int dest_reg, int src_reg);
|
void host_arm_VCVT_D_S(codeblock_t *block, int dest_reg, int src_reg);
|
||||||
|
void host_arm_VCVT_IS_D(codeblock_t *block, int dest_reg, int src_reg);
|
||||||
void host_arm_VCVT_S_D(codeblock_t *block, int dest_reg, int src_reg);
|
void host_arm_VCVT_S_D(codeblock_t *block, int dest_reg, int src_reg);
|
||||||
|
void host_arm_VCVTR_IS_D(codeblock_t *block, int dest_reg, int src_reg);
|
||||||
void host_arm_VDIV_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_VLDR_D(codeblock_t *block, int dest_reg, int base_reg, int offset);
|
||||||
void host_arm_VLDR_S(codeblock_t *block, int dest_reg, int base_reg, int offset);
|
void host_arm_VLDR_S(codeblock_t *block, int dest_reg, int base_reg, int offset);
|
||||||
|
|
@ -127,6 +129,7 @@ void host_arm_VMOV_64_D(codeblock_t *block, int dest_reg_low, int dest_reg_high,
|
||||||
void host_arm_VMOV_D_64(codeblock_t *block, int dest_reg, int src_reg_low, int src_reg_high);
|
void host_arm_VMOV_D_64(codeblock_t *block, int dest_reg, int src_reg_low, int src_reg_high);
|
||||||
void host_arm_VMOV_S_32(codeblock_t *block, int dest_reg, int src_reg);
|
void host_arm_VMOV_S_32(codeblock_t *block, int dest_reg, int src_reg);
|
||||||
void host_arm_VMOV_D_D(codeblock_t *block, int dest_reg, int src_reg);
|
void host_arm_VMOV_D_D(codeblock_t *block, int dest_reg, int src_reg);
|
||||||
|
void host_arm_VMSR_FPSCR(codeblock_t *block, int src_reg);
|
||||||
void host_arm_VMUL_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
|
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_VSTR_D(codeblock_t *block, int src_reg, int base_reg, int offset);
|
||||||
void host_arm_VSTR_S(codeblock_t *block, int src_reg, int base_reg, int offset);
|
void host_arm_VSTR_S(codeblock_t *block, int src_reg, int base_reg, int offset);
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
#ifdef __ARM_EABI__
|
#ifdef __ARM_EABI__
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
#include "ibm.h"
|
#include "ibm.h"
|
||||||
#include "x86.h"
|
#include "x86.h"
|
||||||
|
#include "x87.h"
|
||||||
#include "386_common.h"
|
#include "386_common.h"
|
||||||
#include "codegen.h"
|
#include "codegen.h"
|
||||||
#include "codegen_backend.h"
|
#include "codegen_backend.h"
|
||||||
|
|
@ -1013,6 +1015,11 @@ static int codegen_MEM_STORE_REG(codeblock_t *block, uop_t *uop)
|
||||||
host_arm_MOV_REG(block, REG_R1, src_reg);
|
host_arm_MOV_REG(block, REG_R1, src_reg);
|
||||||
host_arm_BL(block, (uintptr_t)codegen_mem_store_long);
|
host_arm_BL(block, (uintptr_t)codegen_mem_store_long);
|
||||||
}
|
}
|
||||||
|
else if (REG_IS_Q(src_size))
|
||||||
|
{
|
||||||
|
host_arm_VMOV_D_D(block, REG_D_TEMP, src_reg);
|
||||||
|
host_arm_BL(block, (uintptr_t)codegen_mem_store_quad);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
fatal("MEM_STORE_REG - %02x\n", uop->src_reg_c_real);
|
fatal("MEM_STORE_REG - %02x\n", uop->src_reg_c_real);
|
||||||
host_arm_TST_REG(block, REG_R1, REG_R1);
|
host_arm_TST_REG(block, REG_R1, REG_R1);
|
||||||
|
|
@ -1278,6 +1285,81 @@ static int codegen_MOV_DOUBLE_INT(codeblock_t *block, uop_t *uop)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
static int codegen_MOV_INT_DOUBLE(codeblock_t *block, uop_t *uop)
|
||||||
|
{
|
||||||
|
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real);
|
||||||
|
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real);
|
||||||
|
|
||||||
|
if (REG_IS_L(dest_size) && REG_IS_D(src_size))
|
||||||
|
{
|
||||||
|
host_arm_VMOV_D_D(block, REG_D_TEMP, src_reg);
|
||||||
|
host_arm_BL(block, (uintptr_t)codegen_fp_round);
|
||||||
|
host_arm_VMOV_32_S(block, dest_reg, REG_D_TEMP);
|
||||||
|
}
|
||||||
|
else if (REG_IS_W(dest_size) && REG_IS_D(src_size))
|
||||||
|
{
|
||||||
|
host_arm_VMOV_D_D(block, REG_D_TEMP, src_reg);
|
||||||
|
host_arm_BL(block, (uintptr_t)codegen_fp_round);
|
||||||
|
host_arm_VMOV_32_S(block, REG_TEMP, REG_D_TEMP);
|
||||||
|
host_arm_BFI(block, dest_reg, REG_TEMP, 0, 16);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
fatal("MOV_INT_DOUBLE %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static int64_t x87_fround64(double b)
|
||||||
|
{
|
||||||
|
int64_t a, c;
|
||||||
|
|
||||||
|
switch ((cpu_state.npxc >> 10) & 3)
|
||||||
|
{
|
||||||
|
case 0: /*Nearest*/
|
||||||
|
a = (int64_t)floor(b);
|
||||||
|
c = (int64_t)floor(b + 1.0);
|
||||||
|
if ((b - a) < (c - b))
|
||||||
|
return a;
|
||||||
|
else if ((b - a) > (c - b))
|
||||||
|
return c;
|
||||||
|
else
|
||||||
|
return (a & 1) ? c : a;
|
||||||
|
case 1: /*Down*/
|
||||||
|
return (int64_t)floor(b);
|
||||||
|
case 2: /*Up*/
|
||||||
|
return (int64_t)ceil(b);
|
||||||
|
case 3: /*Chop*/
|
||||||
|
return (int64_t)b;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static int codegen_MOV_INT_DOUBLE_64(codeblock_t *block, uop_t *uop)
|
||||||
|
{
|
||||||
|
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), src_64_reg = HOST_REG_GET(uop->src_reg_b_real), tag_reg = HOST_REG_GET(uop->src_reg_c_real);
|
||||||
|
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real), src_64_size = IREG_GET_SIZE(uop->src_reg_b_real);
|
||||||
|
|
||||||
|
if (REG_IS_Q(dest_size) && REG_IS_D(src_size) && REG_IS_Q(src_64_size))
|
||||||
|
{
|
||||||
|
uint32_t *branch_offset;
|
||||||
|
|
||||||
|
/*If TAG_UINT64 is set then the source is MM[]. Otherwise it is a double in ST()*/
|
||||||
|
host_arm_VMOV_D_D(block, dest_reg, src_64_reg);
|
||||||
|
host_arm_TST_IMM(block, tag_reg, TAG_UINT64);
|
||||||
|
branch_offset = host_arm_BNE_(block);
|
||||||
|
|
||||||
|
/*VFP/NEON has no instructions to convert a float to 64-bit integer,
|
||||||
|
so call out to C.*/
|
||||||
|
host_arm_VMOV_D_D(block, REG_D0, src_reg);
|
||||||
|
host_arm_call(block, x87_fround64);
|
||||||
|
host_arm_VMOV_D_64(block, REG_D_TEMP, REG_R0, REG_R1);
|
||||||
|
|
||||||
|
*branch_offset |= ((((uintptr_t)&block->data[block_pos] - (uintptr_t)branch_offset) - 8) & 0x3fffffc) >> 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
fatal("MOV_INT_DOUBLE_64 %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int codegen_OR(codeblock_t *block, uop_t *uop)
|
static int codegen_OR(codeblock_t *block, uop_t *uop)
|
||||||
{
|
{
|
||||||
|
|
@ -1810,6 +1892,8 @@ const uOpFn uop_handlers[UOP_MAX] =
|
||||||
[UOP_MOVSX & UOP_MASK] = codegen_MOVSX,
|
[UOP_MOVSX & UOP_MASK] = codegen_MOVSX,
|
||||||
[UOP_MOVZX & UOP_MASK] = codegen_MOVZX,
|
[UOP_MOVZX & UOP_MASK] = codegen_MOVZX,
|
||||||
[UOP_MOV_DOUBLE_INT & UOP_MASK] = codegen_MOV_DOUBLE_INT,
|
[UOP_MOV_DOUBLE_INT & UOP_MASK] = codegen_MOV_DOUBLE_INT,
|
||||||
|
[UOP_MOV_INT_DOUBLE & UOP_MASK] = codegen_MOV_INT_DOUBLE,
|
||||||
|
[UOP_MOV_INT_DOUBLE_64 & UOP_MASK] = codegen_MOV_INT_DOUBLE_64,
|
||||||
|
|
||||||
[UOP_ADD & UOP_MASK] = codegen_ADD,
|
[UOP_ADD & UOP_MASK] = codegen_ADD,
|
||||||
[UOP_ADD_IMM & UOP_MASK] = codegen_ADD_IMM,
|
[UOP_ADD_IMM & UOP_MASK] = codegen_ADD_IMM,
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ void *codegen_mem_load_double;
|
||||||
void *codegen_mem_store_byte;
|
void *codegen_mem_store_byte;
|
||||||
void *codegen_mem_store_word;
|
void *codegen_mem_store_word;
|
||||||
void *codegen_mem_store_long;
|
void *codegen_mem_store_long;
|
||||||
|
void *codegen_mem_store_quad;
|
||||||
void *codegen_mem_store_single;
|
void *codegen_mem_store_single;
|
||||||
void *codegen_mem_store_double;
|
void *codegen_mem_store_double;
|
||||||
|
|
||||||
|
|
@ -192,7 +193,7 @@ static void build_store_routine(codeblock_t *block, int size, int is_float)
|
||||||
host_x86_MOV32_BASE_INDEX_REG(block, REG_RSI, REG_RDI, REG_ECX);
|
host_x86_MOV32_BASE_INDEX_REG(block, REG_RSI, REG_RDI, REG_ECX);
|
||||||
else if (size == 4 && is_float)
|
else if (size == 4 && is_float)
|
||||||
host_x86_MOVD_BASE_INDEX_XREG(block, REG_RSI, REG_RDI, REG_XMM_TEMP);
|
host_x86_MOVD_BASE_INDEX_XREG(block, REG_RSI, REG_RDI, REG_XMM_TEMP);
|
||||||
else if (size == 8 && is_float)
|
else if (size == 8)
|
||||||
host_x86_MOVQ_BASE_INDEX_XREG(block, REG_RSI, REG_RDI, REG_XMM_TEMP);
|
host_x86_MOVQ_BASE_INDEX_XREG(block, REG_RSI, REG_RDI, REG_XMM_TEMP);
|
||||||
else
|
else
|
||||||
fatal("build_store_routine: size=%i\n", size);
|
fatal("build_store_routine: size=%i\n", size);
|
||||||
|
|
@ -208,7 +209,7 @@ static void build_store_routine(codeblock_t *block, int size, int is_float)
|
||||||
host_x86_SUB64_REG_IMM(block, REG_RSP, 0x20);
|
host_x86_SUB64_REG_IMM(block, REG_RSP, 0x20);
|
||||||
if (size == 4 && is_float)
|
if (size == 4 && is_float)
|
||||||
host_x86_MOVD_REG_XREG(block, REG_EDX, REG_XMM_TEMP); //data
|
host_x86_MOVD_REG_XREG(block, REG_EDX, REG_XMM_TEMP); //data
|
||||||
else if (size == 8 && is_float)
|
else if (size == 8)
|
||||||
host_x86_MOVQ_REG_XREG(block, REG_RDX, REG_XMM_TEMP); //data
|
host_x86_MOVQ_REG_XREG(block, REG_RDX, REG_XMM_TEMP); //data
|
||||||
else
|
else
|
||||||
host_x86_MOV32_REG_REG(block, REG_EDX, REG_ECX); //data
|
host_x86_MOV32_REG_REG(block, REG_EDX, REG_ECX); //data
|
||||||
|
|
@ -256,6 +257,8 @@ static void build_loadstore_routines(codeblock_t *block)
|
||||||
build_store_routine(block, 2, 0);
|
build_store_routine(block, 2, 0);
|
||||||
codegen_mem_store_long = &codeblock[block_current].data[block_pos];
|
codegen_mem_store_long = &codeblock[block_current].data[block_pos];
|
||||||
build_store_routine(block, 4, 0);
|
build_store_routine(block, 4, 0);
|
||||||
|
codegen_mem_store_quad = &codeblock[block_current].data[block_pos];
|
||||||
|
build_store_routine(block, 8, 0);
|
||||||
codegen_mem_store_single = &codeblock[block_current].data[block_pos];
|
codegen_mem_store_single = &codeblock[block_current].data[block_pos];
|
||||||
build_store_routine(block, 4, 1);
|
build_store_routine(block, 4, 1);
|
||||||
codegen_mem_store_double = &codeblock[block_current].data[block_pos];
|
codegen_mem_store_double = &codeblock[block_current].data[block_pos];
|
||||||
|
|
@ -300,6 +303,16 @@ void codegen_backend_init()
|
||||||
block_pos = 0;
|
block_pos = 0;
|
||||||
build_loadstore_routines(&codeblock[block_current]);
|
build_loadstore_routines(&codeblock[block_current]);
|
||||||
// fatal("Here\n");
|
// fatal("Here\n");
|
||||||
|
|
||||||
|
asm(
|
||||||
|
"stmxcsr %0\n"
|
||||||
|
: "=m" (cpu_state.old_fp_control)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void codegen_set_rounding_mode(int mode)
|
||||||
|
{
|
||||||
|
cpu_state.new_fp_control = (cpu_state.old_fp_control & ~0x6000) | (mode << 13);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void call(codeblock_t *block, uintptr_t func)
|
static inline void call(codeblock_t *block, uintptr_t func)
|
||||||
|
|
|
||||||
|
|
@ -57,5 +57,6 @@ extern void *codegen_mem_load_double;
|
||||||
extern void *codegen_mem_store_byte;
|
extern void *codegen_mem_store_byte;
|
||||||
extern void *codegen_mem_store_word;
|
extern void *codegen_mem_store_word;
|
||||||
extern void *codegen_mem_store_long;
|
extern void *codegen_mem_store_long;
|
||||||
|
extern void *codegen_mem_store_quad;
|
||||||
extern void *codegen_mem_store_single;
|
extern void *codegen_mem_store_single;
|
||||||
extern void *codegen_mem_store_double;
|
extern void *codegen_mem_store_double;
|
||||||
|
|
|
||||||
|
|
@ -341,6 +341,15 @@ 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*/
|
codegen_addbyte2(block, 0x39, 0xc0 | src_reg_a | (src_reg_b << 3)); /*CMP src_reg_a, src_reg_b*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void host_x86_CVTSD2SI_REG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_addbyte4(block, 0xf2, 0x0f, 0x2d, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSD2SI dst_reg, src_reg*/
|
||||||
|
}
|
||||||
|
void host_x86_CVTSD2SI_REG64_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_addbyte4(block, 0xf2, 0x48, 0x0f, 0x2d); /*CVTSD2SI dst_reg, src_reg*/
|
||||||
|
codegen_addbyte(block, 0xc0 | src_reg | (dst_reg << 3));
|
||||||
|
}
|
||||||
void host_x86_CVTSD2SS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
void host_x86_CVTSD2SS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
{
|
{
|
||||||
codegen_addbyte4(block, 0xf2, 0x0f, 0x5a, 0xc0 | src_reg | (dst_reg << 3));
|
codegen_addbyte4(block, 0xf2, 0x0f, 0x5a, 0xc0 | src_reg | (dst_reg << 3));
|
||||||
|
|
@ -392,6 +401,11 @@ uint8_t *host_x86_JNZ_short(codeblock_t *block)
|
||||||
codegen_addbyte2(block, 0x75, 0); /*JNZ*/
|
codegen_addbyte2(block, 0x75, 0); /*JNZ*/
|
||||||
return &block->data[block_pos-1];
|
return &block->data[block_pos-1];
|
||||||
}
|
}
|
||||||
|
uint8_t *host_x86_JS_short(codeblock_t *block)
|
||||||
|
{
|
||||||
|
codegen_addbyte2(block, 0x78, 0); /*JS*/
|
||||||
|
return &block->data[block_pos-1];
|
||||||
|
}
|
||||||
uint8_t *host_x86_JZ_short(codeblock_t *block)
|
uint8_t *host_x86_JZ_short(codeblock_t *block)
|
||||||
{
|
{
|
||||||
codegen_addbyte2(block, 0x74, 0); /*JZ*/
|
codegen_addbyte2(block, 0x74, 0); /*JZ*/
|
||||||
|
|
@ -483,6 +497,20 @@ uint32_t *host_x86_JZ_long(codeblock_t *block)
|
||||||
return (uint32_t *)&block->data[block_pos-4];
|
return (uint32_t *)&block->data[block_pos-4];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void host_x86_LDMXCSR(codeblock_t *block, void *p)
|
||||||
|
{
|
||||||
|
int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
|
||||||
|
|
||||||
|
if (offset >= -128 && offset < 127)
|
||||||
|
{
|
||||||
|
codegen_addbyte4(block, 0x0f, 0xae, 0x50 | REG_EBP, offset); /*LDMXCSR offset[EBP]*/
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fatal("host_x86_LDMXCSR - out of range %p\n", p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void host_x86_LEA_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t offset)
|
void host_x86_LEA_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t offset)
|
||||||
{
|
{
|
||||||
if (offset)
|
if (offset)
|
||||||
|
|
|
||||||
|
|
@ -27,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_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_CMP32_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b);
|
||||||
|
|
||||||
|
void host_x86_CVTSD2SI_REG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
void host_x86_CVTSD2SI_REG64_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
void host_x86_CVTSD2SS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
void host_x86_CVTSD2SS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
void host_x86_CVTSI2SD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg);
|
void host_x86_CVTSI2SD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
void host_x86_CVTSI2SD_XREG_REG64(codeblock_t *block, int dst_reg, int src_reg);
|
void host_x86_CVTSI2SD_XREG_REG64(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
|
@ -41,6 +43,7 @@ void host_x86_JNZ(codeblock_t *block, void *p);
|
||||||
void host_x86_JZ(codeblock_t *block, void *p);
|
void host_x86_JZ(codeblock_t *block, void *p);
|
||||||
|
|
||||||
uint8_t *host_x86_JNZ_short(codeblock_t *block);
|
uint8_t *host_x86_JNZ_short(codeblock_t *block);
|
||||||
|
uint8_t *host_x86_JS_short(codeblock_t *block);
|
||||||
uint8_t *host_x86_JZ_short(codeblock_t *block);
|
uint8_t *host_x86_JZ_short(codeblock_t *block);
|
||||||
|
|
||||||
uint32_t *host_x86_JNB_long(codeblock_t *block);
|
uint32_t *host_x86_JNB_long(codeblock_t *block);
|
||||||
|
|
@ -58,6 +61,8 @@ uint32_t *host_x86_JO_long(codeblock_t *block);
|
||||||
uint32_t *host_x86_JS_long(codeblock_t *block);
|
uint32_t *host_x86_JS_long(codeblock_t *block);
|
||||||
uint32_t *host_x86_JZ_long(codeblock_t *block);
|
uint32_t *host_x86_JZ_long(codeblock_t *block);
|
||||||
|
|
||||||
|
void host_x86_LDMXCSR(codeblock_t *block, void *p);
|
||||||
|
|
||||||
void host_x86_LEA_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t offset);
|
void host_x86_LEA_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t offset);
|
||||||
void host_x86_LEA_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
|
void host_x86_LEA_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
|
||||||
void host_x86_LEA_REG_REG_SHIFT(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b, int shift);
|
void host_x86_LEA_REG_REG_SHIFT(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b, int shift);
|
||||||
|
|
@ -111,6 +116,7 @@ void host_x86_MOVD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
void host_x86_MOVQ_ABS_XREG(codeblock_t *block, void *p, int src_reg);
|
void host_x86_MOVQ_ABS_XREG(codeblock_t *block, void *p, int src_reg);
|
||||||
void host_x86_MOVQ_ABS_REG_REG_SHIFT_XREG(codeblock_t *block, uint32_t addr, int src_reg_a, int src_reg_b, int shift, int src_reg);
|
void host_x86_MOVQ_ABS_REG_REG_SHIFT_XREG(codeblock_t *block, uint32_t addr, int src_reg_a, int src_reg_b, int shift, int src_reg);
|
||||||
void host_x86_MOVQ_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg);
|
void host_x86_MOVQ_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg);
|
||||||
|
void host_x86_MOVQ_BASE_OFFSET_XREG(codeblock_t *block, int base_reg, int offset, int src_reg);
|
||||||
void host_x86_MOVQ_XREG_ABS(codeblock_t *block, int dst_reg, void *p);
|
void host_x86_MOVQ_XREG_ABS(codeblock_t *block, int dst_reg, void *p);
|
||||||
void host_x86_MOVQ_XREG_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_XREG_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_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg);
|
void host_x86_MOVQ_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg);
|
||||||
|
|
|
||||||
|
|
@ -918,8 +918,13 @@ static int codegen_MEM_STORE_REG(codeblock_t *block, uop_t *uop)
|
||||||
host_x86_MOV32_REG_REG(block, REG_ECX, src_reg);
|
host_x86_MOV32_REG_REG(block, REG_ECX, src_reg);
|
||||||
host_x86_CALL(block, codegen_mem_store_long);
|
host_x86_CALL(block, codegen_mem_store_long);
|
||||||
}
|
}
|
||||||
|
else if (REG_IS_Q(src_size))
|
||||||
|
{
|
||||||
|
host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg);
|
||||||
|
host_x86_CALL(block, codegen_mem_store_quad);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
fatal("MEM_STORE_ABS - %02x\n", uop->src_reg_b_real);
|
fatal("MEM_STORE_REG - %02x\n", uop->src_reg_b_real);
|
||||||
host_x86_TEST32_REG(block, REG_ESI, REG_ESI);
|
host_x86_TEST32_REG(block, REG_ESI, REG_ESI);
|
||||||
host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]);
|
host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]);
|
||||||
|
|
||||||
|
|
@ -1087,6 +1092,55 @@ static int codegen_MOV_DOUBLE_INT(codeblock_t *block, uop_t *uop)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
static int codegen_MOV_INT_DOUBLE(codeblock_t *block, uop_t *uop)
|
||||||
|
{
|
||||||
|
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real);
|
||||||
|
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real);
|
||||||
|
|
||||||
|
if (REG_IS_L(dest_size) && REG_IS_D(src_size))
|
||||||
|
{
|
||||||
|
host_x86_LDMXCSR(block, &cpu_state.new_fp_control);
|
||||||
|
host_x86_CVTSD2SI_REG_XREG(block, dest_reg, src_reg);
|
||||||
|
host_x86_LDMXCSR(block, &cpu_state.old_fp_control);
|
||||||
|
}
|
||||||
|
else if (REG_IS_W(dest_size) && REG_IS_D(src_size))
|
||||||
|
{
|
||||||
|
host_x86_LDMXCSR(block, &cpu_state.new_fp_control);
|
||||||
|
host_x86_CVTSD2SI_REG_XREG(block, REG_ECX, src_reg);
|
||||||
|
host_x86_MOV16_REG_REG(block, dest_reg, REG_ECX);
|
||||||
|
host_x86_LDMXCSR(block, &cpu_state.old_fp_control);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
fatal("MOV_INT_DOUBLE %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static int codegen_MOV_INT_DOUBLE_64(codeblock_t *block, uop_t *uop)
|
||||||
|
{
|
||||||
|
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), src_64_reg = HOST_REG_GET(uop->src_reg_b_real), tag_reg = HOST_REG_GET(uop->src_reg_c_real);
|
||||||
|
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real), src_64_size = IREG_GET_SIZE(uop->src_reg_b_real);
|
||||||
|
|
||||||
|
if (REG_IS_Q(dest_size) && REG_IS_D(src_size) && REG_IS_Q(src_64_size))
|
||||||
|
{
|
||||||
|
uint8_t *branch_offset;
|
||||||
|
|
||||||
|
/*If TAG_UINT64 is set then the source is MM[]. Otherwise it is a double in ST()*/
|
||||||
|
host_x86_MOVQ_XREG_XREG(block, dest_reg, src_64_reg);
|
||||||
|
host_x86_TEST8_REG(block, tag_reg, tag_reg);
|
||||||
|
branch_offset = host_x86_JS_short(block);
|
||||||
|
|
||||||
|
host_x86_LDMXCSR(block, &cpu_state.new_fp_control);
|
||||||
|
host_x86_CVTSD2SI_REG64_XREG(block, REG_RCX, src_reg);
|
||||||
|
host_x86_LDMXCSR(block, &cpu_state.old_fp_control);
|
||||||
|
host_x86_MOVQ_XREG_REG(block, dest_reg, REG_RCX);
|
||||||
|
|
||||||
|
*branch_offset = (uint8_t)((uintptr_t)&block->data[block_pos] - (uintptr_t)branch_offset) - 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
fatal("MOV_INT_DOUBLE_64 %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int codegen_OR(codeblock_t *block, uop_t *uop)
|
static int codegen_OR(codeblock_t *block, uop_t *uop)
|
||||||
{
|
{
|
||||||
|
|
@ -1517,6 +1571,8 @@ const uOpFn uop_handlers[UOP_MAX] =
|
||||||
[UOP_MOVSX & UOP_MASK] = codegen_MOVSX,
|
[UOP_MOVSX & UOP_MASK] = codegen_MOVSX,
|
||||||
[UOP_MOVZX & UOP_MASK] = codegen_MOVZX,
|
[UOP_MOVZX & UOP_MASK] = codegen_MOVZX,
|
||||||
[UOP_MOV_DOUBLE_INT & UOP_MASK] = codegen_MOV_DOUBLE_INT,
|
[UOP_MOV_DOUBLE_INT & UOP_MASK] = codegen_MOV_DOUBLE_INT,
|
||||||
|
[UOP_MOV_INT_DOUBLE & UOP_MASK] = codegen_MOV_INT_DOUBLE,
|
||||||
|
[UOP_MOV_INT_DOUBLE_64 & UOP_MASK] = codegen_MOV_INT_DOUBLE_64,
|
||||||
|
|
||||||
[UOP_ADD & UOP_MASK] = codegen_ADD,
|
[UOP_ADD & UOP_MASK] = codegen_ADD,
|
||||||
[UOP_ADD_IMM & UOP_MASK] = codegen_ADD_IMM,
|
[UOP_ADD_IMM & UOP_MASK] = codegen_ADD_IMM,
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ void *codegen_mem_load_double;
|
||||||
void *codegen_mem_store_byte;
|
void *codegen_mem_store_byte;
|
||||||
void *codegen_mem_store_word;
|
void *codegen_mem_store_word;
|
||||||
void *codegen_mem_store_long;
|
void *codegen_mem_store_long;
|
||||||
|
void *codegen_mem_store_quad;
|
||||||
void *codegen_mem_store_single;
|
void *codegen_mem_store_single;
|
||||||
void *codegen_mem_store_double;
|
void *codegen_mem_store_double;
|
||||||
|
|
||||||
|
|
@ -91,7 +92,7 @@ static void build_load_routine(codeblock_t *block, int size, int is_float)
|
||||||
host_x86_MOV32_REG_BASE_INDEX(block, REG_ECX, REG_ESI, REG_ECX);
|
host_x86_MOV32_REG_BASE_INDEX(block, REG_ECX, REG_ESI, REG_ECX);
|
||||||
else if (size == 4 && is_float)
|
else if (size == 4 && is_float)
|
||||||
host_x86_CVTSS2SD_XREG_BASE_INDEX(block, REG_XMM_TEMP, REG_ESI, REG_ECX);
|
host_x86_CVTSS2SD_XREG_BASE_INDEX(block, REG_XMM_TEMP, REG_ESI, REG_ECX);
|
||||||
else if (size == 8/* && is_float*/)
|
else if (size == 8)
|
||||||
host_x86_MOVQ_XREG_BASE_INDEX(block, REG_XMM_TEMP, REG_ESI, REG_ECX);
|
host_x86_MOVQ_XREG_BASE_INDEX(block, REG_XMM_TEMP, REG_ESI, REG_ECX);
|
||||||
else
|
else
|
||||||
fatal("build_load_routine: size=%i\n", size);
|
fatal("build_load_routine: size=%i\n", size);
|
||||||
|
|
@ -124,7 +125,7 @@ static void build_load_routine(codeblock_t *block, int size, int is_float)
|
||||||
host_x86_MOVD_XREG_REG(block, REG_XMM_TEMP, REG_EAX);
|
host_x86_MOVD_XREG_REG(block, REG_XMM_TEMP, REG_EAX);
|
||||||
host_x86_CVTSS2SD_XREG_XREG(block, REG_XMM_TEMP, REG_XMM_TEMP);
|
host_x86_CVTSS2SD_XREG_XREG(block, REG_XMM_TEMP, REG_XMM_TEMP);
|
||||||
}
|
}
|
||||||
else if (size == 8)// && is_float)
|
else if (size == 8)
|
||||||
{
|
{
|
||||||
host_x86_MOVD_XREG_REG(block, REG_XMM_TEMP, REG_EAX);
|
host_x86_MOVD_XREG_REG(block, REG_XMM_TEMP, REG_EAX);
|
||||||
host_x86_MOVD_XREG_REG(block, REG_XMM_TEMP2, REG_EDX);
|
host_x86_MOVD_XREG_REG(block, REG_XMM_TEMP2, REG_EDX);
|
||||||
|
|
@ -181,7 +182,7 @@ static void build_store_routine(codeblock_t *block, int size, int is_float)
|
||||||
host_x86_MOV32_BASE_INDEX_REG(block, REG_ESI, REG_EDI, REG_ECX);
|
host_x86_MOV32_BASE_INDEX_REG(block, REG_ESI, REG_EDI, REG_ECX);
|
||||||
else if (size == 4 && is_float)
|
else if (size == 4 && is_float)
|
||||||
host_x86_MOVD_BASE_INDEX_XREG(block, REG_ESI, REG_EDI, REG_XMM_TEMP);
|
host_x86_MOVD_BASE_INDEX_XREG(block, REG_ESI, REG_EDI, REG_XMM_TEMP);
|
||||||
else if (size == 8 && is_float)
|
else if (size == 8)
|
||||||
host_x86_MOVQ_BASE_INDEX_XREG(block, REG_ESI, REG_EDI, REG_XMM_TEMP);
|
host_x86_MOVQ_BASE_INDEX_XREG(block, REG_ESI, REG_EDI, REG_XMM_TEMP);
|
||||||
else
|
else
|
||||||
fatal("build_store_routine: size=%i is_float=%i\n", size, is_float);
|
fatal("build_store_routine: size=%i is_float=%i\n", size, is_float);
|
||||||
|
|
@ -196,7 +197,7 @@ static void build_store_routine(codeblock_t *block, int size, int is_float)
|
||||||
host_x86_PUSH(block, REG_EAX);
|
host_x86_PUSH(block, REG_EAX);
|
||||||
host_x86_PUSH(block, REG_EDX);
|
host_x86_PUSH(block, REG_EDX);
|
||||||
host_x86_PUSH(block, REG_ECX);
|
host_x86_PUSH(block, REG_ECX);
|
||||||
if (size == 8 && is_float)
|
if (size == 8)
|
||||||
{
|
{
|
||||||
host_x86_MOVQ_STACK_OFFSET_XREG(block, -8, REG_XMM_TEMP);
|
host_x86_MOVQ_STACK_OFFSET_XREG(block, -8, REG_XMM_TEMP);
|
||||||
host_x86_SUB32_REG_IMM(block, REG_ESP, REG_ESP, 8);
|
host_x86_SUB32_REG_IMM(block, REG_ESP, REG_ESP, 8);
|
||||||
|
|
@ -211,7 +212,7 @@ static void build_store_routine(codeblock_t *block, int size, int is_float)
|
||||||
else if (size == 8)
|
else if (size == 8)
|
||||||
host_x86_CALL(block, (void *)writememql);
|
host_x86_CALL(block, (void *)writememql);
|
||||||
host_x86_POP(block, REG_EDI);
|
host_x86_POP(block, REG_EDI);
|
||||||
if (size == 8 && is_float)
|
if (size == 8)
|
||||||
host_x86_ADD32_REG_IMM(block, REG_ESP, REG_ESP, 8);
|
host_x86_ADD32_REG_IMM(block, REG_ESP, REG_ESP, 8);
|
||||||
host_x86_POP(block, REG_ECX);
|
host_x86_POP(block, REG_ECX);
|
||||||
host_x86_POP(block, REG_EDX);
|
host_x86_POP(block, REG_EDX);
|
||||||
|
|
@ -242,6 +243,8 @@ static void build_loadstore_routines(codeblock_t *block)
|
||||||
build_store_routine(block, 2, 0);
|
build_store_routine(block, 2, 0);
|
||||||
codegen_mem_store_long = &codeblock[block_current].data[block_pos];
|
codegen_mem_store_long = &codeblock[block_current].data[block_pos];
|
||||||
build_store_routine(block, 4, 0);
|
build_store_routine(block, 4, 0);
|
||||||
|
codegen_mem_store_quad = &codeblock[block_current].data[block_pos];
|
||||||
|
build_store_routine(block, 8, 0);
|
||||||
codegen_mem_store_single = &codeblock[block_current].data[block_pos];
|
codegen_mem_store_single = &codeblock[block_current].data[block_pos];
|
||||||
build_store_routine(block, 4, 1);
|
build_store_routine(block, 4, 1);
|
||||||
codegen_mem_store_double = &codeblock[block_current].data[block_pos];
|
codegen_mem_store_double = &codeblock[block_current].data[block_pos];
|
||||||
|
|
@ -298,12 +301,23 @@ void codegen_backend_init()
|
||||||
build_loadstore_routines(&codeblock[block_current]);
|
build_loadstore_routines(&codeblock[block_current]);
|
||||||
//fatal("Here\n");
|
//fatal("Here\n");
|
||||||
|
|
||||||
|
cpu_state.old_fp_control = 0;
|
||||||
asm(
|
asm(
|
||||||
"fstcw %0\n"
|
"fstcw %0\n"
|
||||||
: "=m" (cpu_state.old_npxc)
|
"stmxcsr %1\n"
|
||||||
|
: "=m" (cpu_state.old_fp_control2),
|
||||||
|
"=m" (cpu_state.old_fp_control)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void codegen_set_rounding_mode(int mode)
|
||||||
|
{
|
||||||
|
/*SSE*/
|
||||||
|
cpu_state.new_fp_control = (cpu_state.old_fp_control & ~0x6000) | (mode << 13);
|
||||||
|
/*x87 - used for double -> i64 conversions*/
|
||||||
|
cpu_state.new_fp_control2 = (cpu_state.old_fp_control2 & ~0x0c00) | (mode << 10);
|
||||||
|
}
|
||||||
|
|
||||||
void codegen_backend_prologue(codeblock_t *block)
|
void codegen_backend_prologue(codeblock_t *block)
|
||||||
{
|
{
|
||||||
block_pos = 0; /*Entry code*/
|
block_pos = 0; /*Entry code*/
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,7 @@ extern void *codegen_mem_load_double;
|
||||||
extern void *codegen_mem_store_byte;
|
extern void *codegen_mem_store_byte;
|
||||||
extern void *codegen_mem_store_word;
|
extern void *codegen_mem_store_word;
|
||||||
extern void *codegen_mem_store_long;
|
extern void *codegen_mem_store_long;
|
||||||
|
extern void *codegen_mem_store_quad;
|
||||||
extern void *codegen_mem_store_single;
|
extern void *codegen_mem_store_single;
|
||||||
extern void *codegen_mem_store_double;
|
extern void *codegen_mem_store_double;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -309,14 +309,18 @@ 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*/
|
codegen_addbyte2(block, 0x39, 0xc0 | src_reg_a | (src_reg_b << 3)); /*CMP src_reg_a, src_reg_b*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void host_x86_CVTSD2SI_REG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
{
|
||||||
|
codegen_addbyte4(block, 0xf2, 0x0f, 0x2d, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSD2SI dst_reg, src_reg*/
|
||||||
|
}
|
||||||
void host_x86_CVTSD2SS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
void host_x86_CVTSD2SS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
{
|
{
|
||||||
codegen_addbyte4(block, 0xf2, 0x0f, 0x5a, 0xc0 | src_reg | (dst_reg << 3));
|
codegen_addbyte4(block, 0xf2, 0x0f, 0x5a, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSD2SS dst_reg, src_reg*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void host_x86_CVTSI2SD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg)
|
void host_x86_CVTSI2SD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
{
|
{
|
||||||
codegen_addbyte4(block, 0xf2, 0x0f, 0x2a, 0xc0 | src_reg | (dst_reg << 3));
|
codegen_addbyte4(block, 0xf2, 0x0f, 0x2a, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSI2SD dst_reg, src_reg*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void host_x86_CVTSS2SD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
void host_x86_CVTSS2SD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
|
||||||
|
|
@ -339,6 +343,12 @@ void host_x86_JMP(codeblock_t *block, void *p)
|
||||||
codegen_addbyte(block, 0xe9); /*JMP*/
|
codegen_addbyte(block, 0xe9); /*JMP*/
|
||||||
codegen_addlong(block, (uintptr_t)p - (uintptr_t)&block->data[block_pos + 4]);
|
codegen_addlong(block, (uintptr_t)p - (uintptr_t)&block->data[block_pos + 4]);
|
||||||
}
|
}
|
||||||
|
uint32_t *host_x86_JMP_long(codeblock_t *block)
|
||||||
|
{
|
||||||
|
codegen_addbyte(block, 0xe9); /*JMP*/
|
||||||
|
codegen_addlong(block, 0);
|
||||||
|
return (uint32_t *)&block->data[block_pos-4];
|
||||||
|
}
|
||||||
|
|
||||||
void host_x86_JNZ(codeblock_t *block, void *p)
|
void host_x86_JNZ(codeblock_t *block, void *p)
|
||||||
{
|
{
|
||||||
|
|
@ -356,6 +366,11 @@ uint8_t *host_x86_JNZ_short(codeblock_t *block)
|
||||||
codegen_addbyte2(block, 0x75, 0); /*JNZ*/
|
codegen_addbyte2(block, 0x75, 0); /*JNZ*/
|
||||||
return &block->data[block_pos-1];
|
return &block->data[block_pos-1];
|
||||||
}
|
}
|
||||||
|
uint8_t *host_x86_JS_short(codeblock_t *block)
|
||||||
|
{
|
||||||
|
codegen_addbyte2(block, 0x78, 0); /*JS*/
|
||||||
|
return &block->data[block_pos-1];
|
||||||
|
}
|
||||||
uint8_t *host_x86_JZ_short(codeblock_t *block)
|
uint8_t *host_x86_JZ_short(codeblock_t *block)
|
||||||
{
|
{
|
||||||
codegen_addbyte2(block, 0x74, 0); /*JZ*/
|
codegen_addbyte2(block, 0x74, 0); /*JZ*/
|
||||||
|
|
@ -447,6 +462,21 @@ uint32_t *host_x86_JZ_long(codeblock_t *block)
|
||||||
return (uint32_t *)&block->data[block_pos-4];
|
return (uint32_t *)&block->data[block_pos-4];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void host_x86_LDMXCSR(codeblock_t *block, void *p)
|
||||||
|
{
|
||||||
|
int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
|
||||||
|
|
||||||
|
if (offset >= -128 && offset < 127)
|
||||||
|
{
|
||||||
|
codegen_addbyte4(block, 0x0f, 0xae, 0x50 | REG_EBP, offset); /*LDMXCSR offset[EBP]*/
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
codegen_addbyte3(block, 0x0f, 0xae, 0x15); /*LDMXCSR [p]*/
|
||||||
|
codegen_addlong(block, (uint32_t)p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void host_x86_LEA_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t offset)
|
void host_x86_LEA_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t offset)
|
||||||
{
|
{
|
||||||
if (offset)
|
if (offset)
|
||||||
|
|
@ -1323,7 +1353,34 @@ void host_x87_FILDq_BASE(codeblock_t *block, int base_reg)
|
||||||
else
|
else
|
||||||
codegen_addbyte2(block, 0xdf, 0x28 | base_reg); /*FILDq [base_reg]*/
|
codegen_addbyte2(block, 0xdf, 0x28 | base_reg); /*FILDq [base_reg]*/
|
||||||
}
|
}
|
||||||
|
void host_x87_FISTPq_BASE(codeblock_t *block, int base_reg)
|
||||||
|
{
|
||||||
|
if (base_reg == REG_ESP)
|
||||||
|
codegen_addbyte3(block, 0xdf, 0x3c, 0x24); /*FISTPq [ESP]*/
|
||||||
|
else
|
||||||
|
codegen_addbyte2(block, 0xdf, 0x38 | base_reg); /*FISTPq [base_reg]*/
|
||||||
|
}
|
||||||
|
void host_x87_FLDCW(codeblock_t *block, void *p)
|
||||||
|
{
|
||||||
|
int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
|
||||||
|
|
||||||
|
if (offset >= -128 && offset < 127)
|
||||||
|
{
|
||||||
|
codegen_addbyte3(block, 0xd9, 0x68 | REG_EBP, offset); /*FLDCW offset[EBP]*/
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
codegen_addbyte2(block, 0xd9, 0x2d); /*FLDCW [p]*/
|
||||||
|
codegen_addlong(block, (uint32_t)p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void host_x87_FLDd_BASE(codeblock_t *block, int base_reg)
|
||||||
|
{
|
||||||
|
if (base_reg == REG_ESP)
|
||||||
|
codegen_addbyte3(block, 0xdd, 0x04, 0x24); /*FILDq [ESP]*/
|
||||||
|
else
|
||||||
|
codegen_addbyte2(block, 0xdd, 0x08 | base_reg); /*FILDq [base_reg]*/
|
||||||
|
}
|
||||||
void host_x87_FSTPd_BASE(codeblock_t *block, int base_reg)
|
void host_x87_FSTPd_BASE(codeblock_t *block, int base_reg)
|
||||||
{
|
{
|
||||||
if (base_reg == REG_ESP)
|
if (base_reg == REG_ESP)
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ 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_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_CMP32_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b);
|
||||||
|
|
||||||
|
void host_x86_CVTSD2SI_REG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
void host_x86_CVTSD2SS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
void host_x86_CVTSD2SS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
|
||||||
void host_x86_CVTSI2SD_XREG_REG(codeblock_t *block, int dest_reg, int src_reg);
|
void host_x86_CVTSI2SD_XREG_REG(codeblock_t *block, int dest_reg, int src_reg);
|
||||||
|
|
@ -37,11 +38,14 @@ void host_x86_CVTSS2SD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base
|
||||||
void host_x86_DIVSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
void host_x86_DIVSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||||
|
|
||||||
void host_x86_JMP(codeblock_t *block, void *p);
|
void host_x86_JMP(codeblock_t *block, void *p);
|
||||||
|
uint32_t *host_x86_JMP_short(codeblock_t *block);
|
||||||
|
uint32_t *host_x86_JMP_long(codeblock_t *block);
|
||||||
|
|
||||||
void host_x86_JNZ(codeblock_t *block, void *p);
|
void host_x86_JNZ(codeblock_t *block, void *p);
|
||||||
void host_x86_JZ(codeblock_t *block, void *p);
|
void host_x86_JZ(codeblock_t *block, void *p);
|
||||||
|
|
||||||
uint8_t *host_x86_JNZ_short(codeblock_t *block);
|
uint8_t *host_x86_JNZ_short(codeblock_t *block);
|
||||||
|
uint8_t *host_x86_JS_short(codeblock_t *block);
|
||||||
uint8_t *host_x86_JZ_short(codeblock_t *block);
|
uint8_t *host_x86_JZ_short(codeblock_t *block);
|
||||||
|
|
||||||
uint32_t *host_x86_JNB_long(codeblock_t *block);
|
uint32_t *host_x86_JNB_long(codeblock_t *block);
|
||||||
|
|
@ -59,6 +63,8 @@ uint32_t *host_x86_JO_long(codeblock_t *block);
|
||||||
uint32_t *host_x86_JS_long(codeblock_t *block);
|
uint32_t *host_x86_JS_long(codeblock_t *block);
|
||||||
uint32_t *host_x86_JZ_long(codeblock_t *block);
|
uint32_t *host_x86_JZ_long(codeblock_t *block);
|
||||||
|
|
||||||
|
void host_x86_LDMXCSR(codeblock_t *block, void *p);
|
||||||
|
|
||||||
void host_x86_LEA_REG_IMM(codeblock_t *block, int dst_reg, int src_reg_a, uint32_t offset);
|
void host_x86_LEA_REG_IMM(codeblock_t *block, int dst_reg, int src_reg_a, uint32_t offset);
|
||||||
void host_x86_LEA_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
|
void host_x86_LEA_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
|
||||||
void host_x86_LEA_REG_REG_SHIFT(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b, int shift);
|
void host_x86_LEA_REG_REG_SHIFT(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b, int shift);
|
||||||
|
|
@ -201,4 +207,7 @@ void host_x86_XOR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16
|
||||||
void host_x86_XOR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data);
|
void host_x86_XOR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data);
|
||||||
|
|
||||||
void host_x87_FILDq_BASE(codeblock_t *block, int base_reg);
|
void host_x87_FILDq_BASE(codeblock_t *block, int base_reg);
|
||||||
|
void host_x87_FISTPq_BASE(codeblock_t *block, int base_reg);
|
||||||
|
void host_x87_FLDCW(codeblock_t *block, void *p);
|
||||||
|
void host_x87_FLDd_BASE(codeblock_t *block, int base_reg);
|
||||||
void host_x87_FSTPd_BASE(codeblock_t *block, int base_reg);
|
void host_x87_FSTPd_BASE(codeblock_t *block, int base_reg);
|
||||||
|
|
|
||||||
|
|
@ -630,6 +630,12 @@ static int codegen_JMP(codeblock_t *block, uop_t *uop)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
static int codegen_JMP_DEST(codeblock_t *block, uop_t *uop)
|
||||||
|
{
|
||||||
|
uop->p = host_x86_JMP_long(block);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int codegen_LOAD_FUNC_ARG0(codeblock_t *block, uop_t *uop)
|
static int codegen_LOAD_FUNC_ARG0(codeblock_t *block, uop_t *uop)
|
||||||
{
|
{
|
||||||
|
|
@ -872,8 +878,13 @@ static int codegen_MEM_STORE_REG(codeblock_t *block, uop_t *uop)
|
||||||
host_x86_MOV32_REG_REG(block, REG_ECX, src_reg);
|
host_x86_MOV32_REG_REG(block, REG_ECX, src_reg);
|
||||||
host_x86_CALL(block, codegen_mem_store_long);
|
host_x86_CALL(block, codegen_mem_store_long);
|
||||||
}
|
}
|
||||||
|
else if (REG_IS_Q(src_size))
|
||||||
|
{
|
||||||
|
host_x86_MOVQ_XREG_XREG(block, REG_XMM_TEMP, src_reg);
|
||||||
|
host_x86_CALL(block, codegen_mem_store_quad);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
fatal("MEM_STORE_ABS - %02x\n", uop->src_reg_b_real);
|
fatal("MEM_STORE_REG - %02x\n", uop->src_reg_b_real);
|
||||||
host_x86_TEST32_REG(block, REG_ESI, REG_ESI);
|
host_x86_TEST32_REG(block, REG_ESI, REG_ESI);
|
||||||
host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]);
|
host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]);
|
||||||
|
|
||||||
|
|
@ -1082,6 +1093,60 @@ static int codegen_MOV_DOUBLE_INT(codeblock_t *block, uop_t *uop)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
static int codegen_MOV_INT_DOUBLE(codeblock_t *block, uop_t *uop)
|
||||||
|
{
|
||||||
|
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real);
|
||||||
|
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real);
|
||||||
|
|
||||||
|
if (REG_IS_L(dest_size) && REG_IS_D(src_size))
|
||||||
|
{
|
||||||
|
host_x86_LDMXCSR(block, &cpu_state.new_fp_control);
|
||||||
|
host_x86_CVTSD2SI_REG_XREG(block, dest_reg, src_reg);
|
||||||
|
host_x86_LDMXCSR(block, &cpu_state.old_fp_control);
|
||||||
|
}
|
||||||
|
else if (REG_IS_W(dest_size) && REG_IS_D(src_size))
|
||||||
|
{
|
||||||
|
host_x86_LDMXCSR(block, &cpu_state.new_fp_control);
|
||||||
|
host_x86_CVTSD2SI_REG_XREG(block, REG_ECX, src_reg);
|
||||||
|
host_x86_MOV16_REG_REG(block, dest_reg, REG_ECX);
|
||||||
|
host_x86_LDMXCSR(block, &cpu_state.old_fp_control);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
fatal("MOV_INT_DOUBLE %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int codegen_MOV_INT_DOUBLE_64(codeblock_t *block, uop_t *uop)
|
||||||
|
{
|
||||||
|
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_a_real), src_64_reg = HOST_REG_GET(uop->src_reg_b_real), tag_reg = HOST_REG_GET(uop->src_reg_c_real);
|
||||||
|
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real), src_size = IREG_GET_SIZE(uop->src_reg_a_real), src_64_size = IREG_GET_SIZE(uop->src_reg_b_real);
|
||||||
|
|
||||||
|
if (REG_IS_Q(dest_size) && REG_IS_D(src_size) && REG_IS_Q(src_64_size))
|
||||||
|
{
|
||||||
|
uint8_t *branch_offset;
|
||||||
|
|
||||||
|
/*If TAG_UINT64 is set then the source is MM[]. Otherwise it is a double in ST()*/
|
||||||
|
host_x86_MOVQ_XREG_XREG(block, dest_reg, src_64_reg);
|
||||||
|
host_x86_TEST8_REG(block, tag_reg, tag_reg);
|
||||||
|
branch_offset = host_x86_JS_short(block);
|
||||||
|
|
||||||
|
/*There is no SSE instruction to convert a floating point value to a 64-bit integer.
|
||||||
|
Instead we have to bounce through memory via x87.*/
|
||||||
|
host_x87_FLDCW(block, &cpu_state.new_fp_control2);
|
||||||
|
host_x86_MOVQ_BASE_OFFSET_XREG(block, REG_ESP, 0, src_reg);
|
||||||
|
host_x87_FLDd_BASE(block, REG_ESP);
|
||||||
|
host_x87_FISTPq_BASE(block, REG_ESP);
|
||||||
|
host_x86_MOVQ_XREG_BASE_OFFSET(block, dest_reg, REG_ESP, 0);
|
||||||
|
host_x87_FLDCW(block, &cpu_state.old_fp_control2);
|
||||||
|
|
||||||
|
*branch_offset = (uint8_t)((uintptr_t)&block->data[block_pos] - (uintptr_t)branch_offset) - 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
fatal("MOV_INT_DOUBLE_64 %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int codegen_OR(codeblock_t *block, uop_t *uop)
|
static int codegen_OR(codeblock_t *block, uop_t *uop)
|
||||||
{
|
{
|
||||||
|
|
@ -1473,6 +1538,7 @@ const uOpFn uop_handlers[UOP_MAX] =
|
||||||
[UOP_CALL_INSTRUCTION_FUNC & UOP_MASK] = codegen_CALL_INSTRUCTION_FUNC,
|
[UOP_CALL_INSTRUCTION_FUNC & UOP_MASK] = codegen_CALL_INSTRUCTION_FUNC,
|
||||||
|
|
||||||
[UOP_JMP & UOP_MASK] = codegen_JMP,
|
[UOP_JMP & UOP_MASK] = codegen_JMP,
|
||||||
|
[UOP_JMP_DEST & UOP_MASK] = codegen_JMP_DEST,
|
||||||
|
|
||||||
[UOP_LOAD_SEG & UOP_MASK] = codegen_LOAD_SEG,
|
[UOP_LOAD_SEG & UOP_MASK] = codegen_LOAD_SEG,
|
||||||
|
|
||||||
|
|
@ -1502,12 +1568,14 @@ const uOpFn uop_handlers[UOP_MAX] =
|
||||||
[UOP_MEM_STORE_SINGLE & UOP_MASK] = codegen_MEM_STORE_SINGLE,
|
[UOP_MEM_STORE_SINGLE & UOP_MASK] = codegen_MEM_STORE_SINGLE,
|
||||||
[UOP_MEM_STORE_DOUBLE & UOP_MASK] = codegen_MEM_STORE_DOUBLE,
|
[UOP_MEM_STORE_DOUBLE & UOP_MASK] = codegen_MEM_STORE_DOUBLE,
|
||||||
|
|
||||||
[UOP_MOV & UOP_MASK] = codegen_MOV,
|
[UOP_MOV & UOP_MASK] = codegen_MOV,
|
||||||
[UOP_MOV_PTR & UOP_MASK] = codegen_MOV_PTR,
|
[UOP_MOV_PTR & UOP_MASK] = codegen_MOV_PTR,
|
||||||
[UOP_MOV_IMM & UOP_MASK] = codegen_MOV_IMM,
|
[UOP_MOV_IMM & UOP_MASK] = codegen_MOV_IMM,
|
||||||
[UOP_MOVSX & UOP_MASK] = codegen_MOVSX,
|
[UOP_MOVSX & UOP_MASK] = codegen_MOVSX,
|
||||||
[UOP_MOVZX & UOP_MASK] = codegen_MOVZX,
|
[UOP_MOVZX & UOP_MASK] = codegen_MOVZX,
|
||||||
[UOP_MOV_DOUBLE_INT & UOP_MASK] = codegen_MOV_DOUBLE_INT,
|
[UOP_MOV_DOUBLE_INT & UOP_MASK] = codegen_MOV_DOUBLE_INT,
|
||||||
|
[UOP_MOV_INT_DOUBLE & UOP_MASK] = codegen_MOV_INT_DOUBLE,
|
||||||
|
[UOP_MOV_INT_DOUBLE_64 & UOP_MASK] = codegen_MOV_INT_DOUBLE_64,
|
||||||
|
|
||||||
[UOP_ADD & UOP_MASK] = codegen_ADD,
|
[UOP_ADD & UOP_MASK] = codegen_ADD,
|
||||||
[UOP_ADD_IMM & UOP_MASK] = codegen_ADD_IMM,
|
[UOP_ADD_IMM & UOP_MASK] = codegen_ADD_IMM,
|
||||||
|
|
|
||||||
|
|
@ -66,7 +66,7 @@ void codegen_ir_compile(ir_data_t *ir, codeblock_t *block)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!uop_handlers[uop->type & UOP_MASK])
|
if (!uop_handlers[uop->type & UOP_MASK])
|
||||||
fatal("!uop_handlers[uop->type & UOP_MASK]\n");
|
fatal("!uop_handlers[uop->type & UOP_MASK] %08x\n", uop->type);
|
||||||
uop_handlers[uop->type & UOP_MASK](block, uop);
|
uop_handlers[uop->type & UOP_MASK](block, uop);
|
||||||
|
|
||||||
if (uop->type & UOP_TYPE_JUMP)
|
if (uop->type & UOP_TYPE_JUMP)
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,8 @@
|
||||||
#define UOP_JMP (UOP_TYPE_PARAMS_POINTER | 0x15 | UOP_TYPE_ORDER_BARRIER)
|
#define UOP_JMP (UOP_TYPE_PARAMS_POINTER | 0x15 | UOP_TYPE_ORDER_BARRIER)
|
||||||
/*UOP_CALL_FUNC - call instruction handler at p, dest_reg = return value*/
|
/*UOP_CALL_FUNC - call instruction handler at p, dest_reg = return value*/
|
||||||
#define UOP_CALL_FUNC_RESULT (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x16 | UOP_TYPE_BARRIER)
|
#define UOP_CALL_FUNC_RESULT (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x16 | UOP_TYPE_BARRIER)
|
||||||
|
/*UOP_JMP_DEST - jump to ptr*/
|
||||||
|
#define UOP_JMP_DEST (UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x17 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP)
|
||||||
/*UOP_MOV_PTR - dest_reg = p*/
|
/*UOP_MOV_PTR - dest_reg = p*/
|
||||||
#define UOP_MOV_PTR (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x20)
|
#define UOP_MOV_PTR (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x20)
|
||||||
/*UOP_MOV_IMM - dest_reg = imm_data*/
|
/*UOP_MOV_IMM - dest_reg = imm_data*/
|
||||||
|
|
@ -64,6 +66,10 @@
|
||||||
#define UOP_MOVSX (UOP_TYPE_PARAMS_REGS | 0x24)
|
#define UOP_MOVSX (UOP_TYPE_PARAMS_REGS | 0x24)
|
||||||
/*UOP_MOV_DOUBLE_INT - dest_reg = (double)src_reg_a*/
|
/*UOP_MOV_DOUBLE_INT - dest_reg = (double)src_reg_a*/
|
||||||
#define UOP_MOV_DOUBLE_INT (UOP_TYPE_PARAMS_REGS | 0x25)
|
#define UOP_MOV_DOUBLE_INT (UOP_TYPE_PARAMS_REGS | 0x25)
|
||||||
|
/*UOP_MOV_INT_DOUBLE - dest_reg = (int)src_reg_a. New rounding control in src_reg_b, old rounding control in src_reg_c*/
|
||||||
|
#define UOP_MOV_INT_DOUBLE (UOP_TYPE_PARAMS_REGS | 0x26)
|
||||||
|
/*UOP_MOV_INT_DOUBLE_64 - dest_reg = (int)src_reg_a. New rounding control in src_reg_b, old rounding control in src_reg_c*/
|
||||||
|
#define UOP_MOV_INT_DOUBLE_64 (UOP_TYPE_PARAMS_REGS | 0x27)
|
||||||
/*UOP_ADD - dest_reg = src_reg_a + src_reg_b*/
|
/*UOP_ADD - dest_reg = src_reg_a + src_reg_b*/
|
||||||
#define UOP_ADD (UOP_TYPE_PARAMS_REGS | 0x30)
|
#define UOP_ADD (UOP_TYPE_PARAMS_REGS | 0x30)
|
||||||
/*UOP_ADD_IMM - dest_reg = src_reg_a + immediate*/
|
/*UOP_ADD_IMM - dest_reg = src_reg_a + immediate*/
|
||||||
|
|
@ -322,6 +328,17 @@ static inline void uop_gen_reg_dst_src2_imm(uint32_t uop_type, ir_data_t *ir, in
|
||||||
uop->imm_data = imm;
|
uop->imm_data = imm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void uop_gen_reg_dst_src3(uint32_t uop_type, ir_data_t *ir, int dest_reg, int src_reg_a, int src_reg_b, int src_reg_c)
|
||||||
|
{
|
||||||
|
uop_t *uop = uop_alloc(ir);
|
||||||
|
|
||||||
|
uop->type = uop_type;
|
||||||
|
uop->src_reg_a = codegen_reg_read(src_reg_a);
|
||||||
|
uop->src_reg_b = codegen_reg_read(src_reg_b);
|
||||||
|
uop->src_reg_c = codegen_reg_read(src_reg_c);
|
||||||
|
uop->dest_reg_a = codegen_reg_write(dest_reg);
|
||||||
|
}
|
||||||
|
|
||||||
static inline void uop_gen_reg_dst_src_imm(uint32_t uop_type, ir_data_t *ir, int dest_reg, int src_reg, uint32_t imm)
|
static inline void uop_gen_reg_dst_src_imm(uint32_t uop_type, ir_data_t *ir, int dest_reg, int src_reg, uint32_t imm)
|
||||||
{
|
{
|
||||||
uop_t *uop = uop_alloc(ir);
|
uop_t *uop = uop_alloc(ir);
|
||||||
|
|
@ -471,6 +488,7 @@ static inline void uop_gen_reg_src_pointer_imm(uint32_t uop_type, ir_data_t *ir,
|
||||||
#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_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_JMP(ir, p) uop_gen_pointer(UOP_JMP, ir, p)
|
||||||
|
#define uop_JMP_DEST(ir) uop_gen(UOP_JMP_DEST, ir)
|
||||||
|
|
||||||
#define uop_LOAD_SEG(ir, p, src_reg) uop_gen_reg_src_pointer(UOP_LOAD_SEG, ir, src_reg, p)
|
#define uop_LOAD_SEG(ir, p, src_reg) uop_gen_reg_src_pointer(UOP_LOAD_SEG, ir, src_reg, p)
|
||||||
|
|
||||||
|
|
@ -494,6 +512,8 @@ static inline void uop_gen_reg_src_pointer_imm(uint32_t uop_type, ir_data_t *ir,
|
||||||
#define uop_MOVSX(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_MOVSX, ir, dst_reg, src_reg)
|
#define uop_MOVSX(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_MOVSX, ir, dst_reg, src_reg)
|
||||||
#define uop_MOVZX(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_MOVZX, ir, dst_reg, src_reg)
|
#define uop_MOVZX(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_MOVZX, ir, dst_reg, src_reg)
|
||||||
#define uop_MOV_DOUBLE_INT(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_MOV_DOUBLE_INT, ir, dst_reg, src_reg)
|
#define uop_MOV_DOUBLE_INT(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_MOV_DOUBLE_INT, ir, dst_reg, src_reg)
|
||||||
|
#define uop_MOV_INT_DOUBLE(ir, dst_reg, src_reg/*, nrc, orc*/) uop_gen_reg_dst_src1(UOP_MOV_INT_DOUBLE, ir, dst_reg, src_reg/*, nrc, orc*/)
|
||||||
|
#define uop_MOV_INT_DOUBLE_64(ir, dst_reg, src_reg_d, src_reg_q, tag) uop_gen_reg_dst_src3(UOP_MOV_INT_DOUBLE_64, ir, dst_reg, src_reg_d, src_reg_q, tag)
|
||||||
|
|
||||||
#define uop_STORE_PTR_IMM(ir, p, imm) uop_gen_pointer_imm(UOP_STORE_P_IMM, ir, p, imm)
|
#define uop_STORE_PTR_IMM(ir, p, imm) uop_gen_pointer_imm(UOP_STORE_P_IMM, ir, p, imm)
|
||||||
#define uop_STORE_PTR_IMM_8(ir, p, imm) uop_gen_pointer_imm(UOP_STORE_P_IMM_8, ir, p, imm)
|
#define uop_STORE_PTR_IMM_8(ir, p, imm) uop_gen_pointer_imm(UOP_STORE_P_IMM_8, ir, p, imm)
|
||||||
|
|
|
||||||
|
|
@ -255,17 +255,17 @@ RecompOpFn recomp_opcodes_db[512] =
|
||||||
/*16-bit data*/
|
/*16-bit data*/
|
||||||
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
||||||
/*00*/ ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
/*00*/ ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, 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,
|
/*10*/ ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl,
|
||||||
/*20*/ 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,
|
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
|
|
||||||
/*40*/ ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
/*40*/ ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, 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,
|
/*50*/ ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl,
|
||||||
/*60*/ 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,
|
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
|
|
||||||
/*80*/ ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
/*80*/ ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, 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,
|
/*90*/ ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl,
|
||||||
/*a0*/ 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,
|
/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
|
|
||||||
|
|
@ -277,17 +277,17 @@ RecompOpFn recomp_opcodes_db[512] =
|
||||||
/*32-bit data*/
|
/*32-bit data*/
|
||||||
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
||||||
/*00*/ ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
/*00*/ ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, 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,
|
/*10*/ ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl,
|
||||||
/*20*/ 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,
|
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
|
|
||||||
/*40*/ ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
/*40*/ ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, 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,
|
/*50*/ ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl,
|
||||||
/*60*/ 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,
|
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
|
|
||||||
/*80*/ ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
/*80*/ ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, 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,
|
/*90*/ ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl,
|
||||||
/*a0*/ 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,
|
/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
|
|
||||||
|
|
@ -443,19 +443,19 @@ RecompOpFn recomp_opcodes_df[512] =
|
||||||
/*16-bit data*/
|
/*16-bit data*/
|
||||||
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
||||||
/*00*/ ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
/*00*/ ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, 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,
|
/*10*/ ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw,
|
||||||
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq,
|
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq,
|
||||||
/*30*/ 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, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq,
|
||||||
|
|
||||||
/*40*/ ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
/*40*/ ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, 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,
|
/*50*/ ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw,
|
||||||
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq,
|
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq,
|
||||||
/*70*/ 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, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq,
|
||||||
|
|
||||||
/*80*/ ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
/*80*/ ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, 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,
|
/*90*/ ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw,
|
||||||
/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq,
|
/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq,
|
||||||
/*b0*/ 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, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq,
|
||||||
|
|
||||||
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
|
|
@ -465,19 +465,19 @@ RecompOpFn recomp_opcodes_df[512] =
|
||||||
/*32-bit data*/
|
/*32-bit data*/
|
||||||
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
|
||||||
/*00*/ ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
/*00*/ ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, 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,
|
/*10*/ ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw,
|
||||||
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq,
|
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq,
|
||||||
/*30*/ 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, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq,
|
||||||
|
|
||||||
/*40*/ ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
/*40*/ ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, 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,
|
/*50*/ ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw,
|
||||||
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq,
|
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq,
|
||||||
/*70*/ 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, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq,
|
||||||
|
|
||||||
/*80*/ ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
/*80*/ ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, 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,
|
/*90*/ ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw,
|
||||||
/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq,
|
/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq,
|
||||||
/*b0*/ 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, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq,
|
||||||
|
|
||||||
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||||
|
|
|
||||||
|
|
@ -148,3 +148,82 @@ uint32_t ropFILDq(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe
|
||||||
|
|
||||||
return op_pc+1;
|
return op_pc+1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t ropFISTw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_FP_ENTER(ir);
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
op_pc--;
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_write(block, ir, target_seg);
|
||||||
|
uop_MOV_INT_DOUBLE(ir, IREG_temp0_W, IREG_ST(0));
|
||||||
|
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W);
|
||||||
|
uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY);
|
||||||
|
|
||||||
|
return op_pc+1;
|
||||||
|
}
|
||||||
|
uint32_t ropFISTPw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_FP_ENTER(ir);
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
op_pc--;
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_write(block, ir, target_seg);
|
||||||
|
uop_MOV_INT_DOUBLE(ir, IREG_temp0_W, IREG_ST(0));
|
||||||
|
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W);
|
||||||
|
uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY);
|
||||||
|
fpu_POP(ir);
|
||||||
|
|
||||||
|
return op_pc+1;
|
||||||
|
}
|
||||||
|
uint32_t ropFISTl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_FP_ENTER(ir);
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
op_pc--;
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_write(block, ir, target_seg);
|
||||||
|
uop_MOV_INT_DOUBLE(ir, IREG_temp0, IREG_ST(0));
|
||||||
|
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0);
|
||||||
|
uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY);
|
||||||
|
|
||||||
|
return op_pc+1;
|
||||||
|
}
|
||||||
|
uint32_t ropFISTPl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_FP_ENTER(ir);
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
op_pc--;
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_write(block, ir, target_seg);
|
||||||
|
uop_MOV_INT_DOUBLE(ir, IREG_temp0, IREG_ST(0));
|
||||||
|
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0);
|
||||||
|
uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY);
|
||||||
|
fpu_POP(ir);
|
||||||
|
|
||||||
|
return op_pc+1;
|
||||||
|
}
|
||||||
|
uint32_t ropFISTPq(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||||
|
{
|
||||||
|
x86seg *target_seg;
|
||||||
|
|
||||||
|
uop_FP_ENTER(ir);
|
||||||
|
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||||
|
op_pc--;
|
||||||
|
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
|
||||||
|
codegen_check_seg_write(block, ir, target_seg);
|
||||||
|
uop_MOV_INT_DOUBLE_64(ir, IREG_temp0_Q, IREG_ST(0), IREG_MM(0), IREG_tag(0));
|
||||||
|
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_Q);
|
||||||
|
uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY);
|
||||||
|
fpu_POP(ir);
|
||||||
|
|
||||||
|
return op_pc+1;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,3 +9,9 @@ uint32_t ropFSTPd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fe
|
||||||
uint32_t ropFILDw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
uint32_t ropFILDw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
uint32_t ropFILDl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
uint32_t ropFILDl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
uint32_t ropFILDq(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
uint32_t ropFILDq(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
|
||||||
|
uint32_t ropFISTw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFISTPw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFISTl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFISTPl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
uint32_t ropFISTPq(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||||
|
|
|
||||||
|
|
@ -165,6 +165,7 @@ enum
|
||||||
#define IREG_ST(r) (IREG_ST0 + ((cpu_state.TOP + (r)) & 7) + IREG_SIZE_D)
|
#define IREG_ST(r) (IREG_ST0 + ((cpu_state.TOP + (r)) & 7) + IREG_SIZE_D)
|
||||||
#define IREG_MM(r) (IREG_MM0 + ((cpu_state.TOP + (r)) & 7) + IREG_SIZE_Q)
|
#define IREG_MM(r) (IREG_MM0 + ((cpu_state.TOP + (r)) & 7) + IREG_SIZE_Q)
|
||||||
#define IREG_tag(r) (IREG_tag0 + ((cpu_state.TOP + (r)) & 7))
|
#define IREG_tag(r) (IREG_tag0 + ((cpu_state.TOP + (r)) & 7))
|
||||||
|
#define IREG_tag_B(r) (IREG_tag0 + ((cpu_state.TOP + (r)) & 7) + IREG_SIZE_B)
|
||||||
|
|
||||||
#define IREG_TOP_diff_stack_offset 32
|
#define IREG_TOP_diff_stack_offset 32
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -177,8 +177,10 @@ struct
|
||||||
|
|
||||||
MMX_REG MM[8];
|
MMX_REG MM[8];
|
||||||
|
|
||||||
uint16_t old_npxc, new_npxc;
|
uint32_t old_fp_control, new_fp_control;
|
||||||
|
#if defined i386 || defined __i386 || defined __i386__ || defined _X86_
|
||||||
|
uint16_t old_fp_control2, new_fp_control2;
|
||||||
|
#endif
|
||||||
x86seg seg_cs,seg_ds,seg_es,seg_ss,seg_fs,seg_gs;
|
x86seg seg_cs,seg_ds,seg_es,seg_ss,seg_fs,seg_gs;
|
||||||
|
|
||||||
union
|
union
|
||||||
|
|
|
||||||
|
|
@ -24,3 +24,9 @@ void x87_reset();
|
||||||
/*Hack for FPU copy. If set then MM[].q contains the 64-bit integer loaded by FILD*/
|
/*Hack for FPU copy. If set then MM[].q contains the 64-bit integer loaded by FILD*/
|
||||||
#define TAG_UINT64 (1 << 7)
|
#define TAG_UINT64 (1 << 7)
|
||||||
|
|
||||||
|
#define X87_ROUNDING_NEAREST 0
|
||||||
|
#define X87_ROUNDING_DOWN 1
|
||||||
|
#define X87_ROUNDING_UP 2
|
||||||
|
#define X87_ROUNDING_CHOP 3
|
||||||
|
|
||||||
|
void codegen_set_rounding_mode(int mode);
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ static int opFINIT(uint32_t fetchdat)
|
||||||
FP_ENTER();
|
FP_ENTER();
|
||||||
cpu_state.pc++;
|
cpu_state.pc++;
|
||||||
cpu_state.npxc = 0x37F;
|
cpu_state.npxc = 0x37F;
|
||||||
cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00);
|
codegen_set_rounding_mode(X87_ROUNDING_NEAREST);
|
||||||
cpu_state.npxs = 0;
|
cpu_state.npxs = 0;
|
||||||
*(uint64_t *)cpu_state.tag = 0;
|
*(uint64_t *)cpu_state.tag = 0;
|
||||||
cpu_state.TOP = 0;
|
cpu_state.TOP = 0;
|
||||||
|
|
@ -86,7 +86,7 @@ static int FSTOR()
|
||||||
case 0x000: /*16-bit real mode*/
|
case 0x000: /*16-bit real mode*/
|
||||||
case 0x001: /*16-bit protected mode*/
|
case 0x001: /*16-bit protected mode*/
|
||||||
cpu_state.npxc = readmemw(easeg, cpu_state.eaaddr);
|
cpu_state.npxc = readmemw(easeg, cpu_state.eaaddr);
|
||||||
cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00) | (cpu_state.npxc & 0xc00);
|
codegen_set_rounding_mode((cpu_state.npxc >> 10) & 3);
|
||||||
cpu_state.npxs = readmemw(easeg, cpu_state.eaaddr+2);
|
cpu_state.npxs = readmemw(easeg, cpu_state.eaaddr+2);
|
||||||
x87_settag(readmemw(easeg, cpu_state.eaaddr+4));
|
x87_settag(readmemw(easeg, cpu_state.eaaddr+4));
|
||||||
cpu_state.TOP = (cpu_state.npxs >> 11) & 7;
|
cpu_state.TOP = (cpu_state.npxs >> 11) & 7;
|
||||||
|
|
@ -95,7 +95,7 @@ static int FSTOR()
|
||||||
case 0x100: /*32-bit real mode*/
|
case 0x100: /*32-bit real mode*/
|
||||||
case 0x101: /*32-bit protected mode*/
|
case 0x101: /*32-bit protected mode*/
|
||||||
cpu_state.npxc = readmemw(easeg, cpu_state.eaaddr);
|
cpu_state.npxc = readmemw(easeg, cpu_state.eaaddr);
|
||||||
cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00) | (cpu_state.npxc & 0xc00);
|
codegen_set_rounding_mode((cpu_state.npxc >> 10) & 3);
|
||||||
cpu_state.npxs = readmemw(easeg, cpu_state.eaaddr+4);
|
cpu_state.npxs = readmemw(easeg, cpu_state.eaaddr+4);
|
||||||
x87_settag(readmemw(easeg, cpu_state.eaaddr+8));
|
x87_settag(readmemw(easeg, cpu_state.eaaddr+8));
|
||||||
cpu_state.TOP = (cpu_state.npxs >> 11) & 7;
|
cpu_state.TOP = (cpu_state.npxs >> 11) & 7;
|
||||||
|
|
@ -276,7 +276,7 @@ static int FSAVE()
|
||||||
}
|
}
|
||||||
|
|
||||||
cpu_state.npxc = 0x37F;
|
cpu_state.npxc = 0x37F;
|
||||||
cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00);
|
codegen_set_rounding_mode(X87_ROUNDING_NEAREST);
|
||||||
cpu_state.npxs = 0;
|
cpu_state.npxs = 0;
|
||||||
*(uint64_t *)cpu_state.tag = 0;
|
*(uint64_t *)cpu_state.tag = 0;
|
||||||
cpu_state.TOP = 0;
|
cpu_state.TOP = 0;
|
||||||
|
|
@ -682,7 +682,7 @@ static int FLDENV()
|
||||||
case 0x000: /*16-bit real mode*/
|
case 0x000: /*16-bit real mode*/
|
||||||
case 0x001: /*16-bit protected mode*/
|
case 0x001: /*16-bit protected mode*/
|
||||||
cpu_state.npxc = readmemw(easeg, cpu_state.eaaddr);
|
cpu_state.npxc = readmemw(easeg, cpu_state.eaaddr);
|
||||||
cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00) | (cpu_state.npxc & 0xc00);
|
codegen_set_rounding_mode((cpu_state.npxc >> 10) & 3);
|
||||||
cpu_state.npxs = readmemw(easeg, cpu_state.eaaddr+2);
|
cpu_state.npxs = readmemw(easeg, cpu_state.eaaddr+2);
|
||||||
x87_settag(readmemw(easeg, cpu_state.eaaddr+4));
|
x87_settag(readmemw(easeg, cpu_state.eaaddr+4));
|
||||||
cpu_state.TOP = (cpu_state.npxs >> 11) & 7;
|
cpu_state.TOP = (cpu_state.npxs >> 11) & 7;
|
||||||
|
|
@ -690,7 +690,7 @@ static int FLDENV()
|
||||||
case 0x100: /*32-bit real mode*/
|
case 0x100: /*32-bit real mode*/
|
||||||
case 0x101: /*32-bit protected mode*/
|
case 0x101: /*32-bit protected mode*/
|
||||||
cpu_state.npxc = readmemw(easeg, cpu_state.eaaddr);
|
cpu_state.npxc = readmemw(easeg, cpu_state.eaaddr);
|
||||||
cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00) | (cpu_state.npxc & 0xc00);
|
codegen_set_rounding_mode((cpu_state.npxc >> 10) & 3);
|
||||||
cpu_state.npxs = readmemw(easeg, cpu_state.eaaddr+4);
|
cpu_state.npxs = readmemw(easeg, cpu_state.eaaddr+4);
|
||||||
x87_settag(readmemw(easeg, cpu_state.eaaddr+8));
|
x87_settag(readmemw(easeg, cpu_state.eaaddr+8));
|
||||||
cpu_state.TOP = (cpu_state.npxs >> 11) & 7;
|
cpu_state.TOP = (cpu_state.npxs >> 11) & 7;
|
||||||
|
|
@ -727,7 +727,7 @@ static int opFLDCW_a16(uint32_t fetchdat)
|
||||||
tempw = geteaw();
|
tempw = geteaw();
|
||||||
if (cpu_state.abrt) return 1;
|
if (cpu_state.abrt) return 1;
|
||||||
cpu_state.npxc = tempw;
|
cpu_state.npxc = tempw;
|
||||||
cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00) | (cpu_state.npxc & 0xc00);
|
codegen_set_rounding_mode((cpu_state.npxc >> 10) & 3);
|
||||||
CLOCK_CYCLES(4);
|
CLOCK_CYCLES(4);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -741,7 +741,7 @@ static int opFLDCW_a32(uint32_t fetchdat)
|
||||||
tempw = geteaw();
|
tempw = geteaw();
|
||||||
if (cpu_state.abrt) return 1;
|
if (cpu_state.abrt) return 1;
|
||||||
cpu_state.npxc = tempw;
|
cpu_state.npxc = tempw;
|
||||||
cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00) | (cpu_state.npxc & 0xc00);
|
codegen_set_rounding_mode((cpu_state.npxc >> 10) & 3);
|
||||||
CLOCK_CYCLES(4);
|
CLOCK_CYCLES(4);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue