Add recompiled versions of mem->reg, reg->mem and imm->mem versions of MOV.
This commit is contained in:
parent
91143d3c68
commit
f27b7f757a
30 changed files with 5225 additions and 2160 deletions
|
|
@ -70,20 +70,20 @@ pcem_SOURCES += wx-sdl2-midi.c
|
|||
endif
|
||||
|
||||
if CPU_I386
|
||||
pcem_SOURCES += codegen_backend_x86.c codegen_backend_x86_uops.c
|
||||
pcem_SOURCES += codegen_backend_x86.c codegen_backend_x86_ops.c codegen_backend_x86_uops.c
|
||||
pcem_CFLAGS += -msse2
|
||||
endif
|
||||
|
||||
if CPU_X86_64
|
||||
pcem_SOURCES += codegen_backend_x86-64.c codegen_backend_x86-64_uops.c
|
||||
pcem_SOURCES += codegen_backend_x86-64.c codegen_backend_x86-64_ops.c codegen_backend_x86-64_uops.c
|
||||
endif
|
||||
|
||||
if CPU_ARM
|
||||
pcem_SOURCES += codegen_backend_arm.c codegen_backend_arm_uops.c
|
||||
pcem_SOURCES += codegen_backend_arm.c codegen_backend_arm_ops.c codegen_backend_arm_uops.c
|
||||
endif
|
||||
|
||||
if CPU_ARM64
|
||||
pcem_SOURCES += codegen_backend_arm64.c codegen_backend_arm64_uops.c
|
||||
pcem_SOURCES += codegen_backend_arm64.c codegen_backend_arm64_ops.c codegen_backend_arm64_uops.c
|
||||
endif
|
||||
|
||||
if USE_NETWORKING
|
||||
|
|
|
|||
|
|
@ -45,6 +45,41 @@ void codegen_generate_reset()
|
|||
has_ea = 0;
|
||||
}
|
||||
|
||||
void codegen_check_seg_read(codeblock_t *block, ir_data_t *ir, x86seg *seg)
|
||||
{
|
||||
/*Segments always valid in real/V86 mode*/
|
||||
if (!(cr0 & 1) || (eflags & VM_FLAG))
|
||||
return;
|
||||
/*CS and SS must always be valid*/
|
||||
if (seg == &cpu_state.seg_cs || seg == &cpu_state.seg_ss)
|
||||
return;
|
||||
if (seg->checked)
|
||||
return;
|
||||
if (seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS))
|
||||
return;
|
||||
|
||||
uop_CMP_IMM_JZ(ir, ireg_seg_base(seg), (uint32_t)-1, &block->data[BLOCK_GPF_OFFSET]);
|
||||
|
||||
seg->checked = 1;
|
||||
}
|
||||
void codegen_check_seg_write(codeblock_t *block, ir_data_t *ir, x86seg *seg)
|
||||
{
|
||||
/*Segments always valid in real/V86 mode*/
|
||||
if (!(cr0 & 1) || (eflags & VM_FLAG))
|
||||
return;
|
||||
/*CS and SS must always be valid*/
|
||||
if (seg == &cpu_state.seg_cs || seg == &cpu_state.seg_ss)
|
||||
return;
|
||||
if (seg->checked)
|
||||
return;
|
||||
if (seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS))
|
||||
return;
|
||||
|
||||
uop_CMP_IMM_JZ(ir, ireg_seg_base(seg), (uint32_t)-1, &block->data[BLOCK_GPF_OFFSET]);
|
||||
|
||||
seg->checked = 1;
|
||||
}
|
||||
|
||||
static x86seg *codegen_generate_ea_16_long(ir_data_t *ir, x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc)
|
||||
{
|
||||
// pclog("codegen - mod=%i rm=%i reg=%i fetchdat=%08x\n", cpu_mod, cpu_rm, cpu_reg, fetchdat);
|
||||
|
|
@ -203,6 +238,18 @@ static x86seg *codegen_generate_ea_32_long(ir_data_t *ir, x86seg *op_ea_seg, uin
|
|||
return op_ea_seg;
|
||||
}
|
||||
|
||||
x86seg *codegen_generate_ea(ir_data_t *ir, x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, uint32_t op_32)
|
||||
{
|
||||
cpu_mod = (fetchdat >> 6) & 3;
|
||||
cpu_reg = (fetchdat >> 3) & 7;
|
||||
cpu_rm = fetchdat & 7;
|
||||
|
||||
if (op_32 & 0x200)
|
||||
return codegen_generate_ea_32_long(ir, op_ea_seg, fetchdat, op_ssegs, op_pc, 0);
|
||||
|
||||
return codegen_generate_ea_16_long(ir, op_ea_seg, fetchdat, op_ssegs, op_pc);
|
||||
}
|
||||
|
||||
static uint8_t opcode_modrm[256] =
|
||||
{
|
||||
1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*00*/
|
||||
|
|
|
|||
|
|
@ -263,6 +263,10 @@ void codegen_generate_seg_restore();
|
|||
void codegen_set_op32();
|
||||
void codegen_flush();
|
||||
void codegen_check_flush(struct page_t *page, uint64_t mask, uint32_t phys_addr);
|
||||
struct ir_data_t;
|
||||
x86seg *codegen_generate_ea(struct ir_data_t *ir, x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, uint32_t op_32);
|
||||
void codegen_check_seg_read(codeblock_t *block, struct ir_data_t *ir, x86seg *seg);
|
||||
void codegen_check_seg_write(codeblock_t *block, struct ir_data_t *ir, x86seg *seg);
|
||||
|
||||
extern int cpu_block_end;
|
||||
extern uint32_t codegen_endpc;
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
#include "codegen.h"
|
||||
#include "codegen_backend.h"
|
||||
#include "codegen_backend_arm_defs.h"
|
||||
#include "codegen_backend_arm_ops.h"
|
||||
#include "x86.h"
|
||||
|
||||
#if defined(__linux__) || defined(__APPLE__)
|
||||
|
|
@ -15,6 +16,14 @@
|
|||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
void *codegen_mem_load_byte;
|
||||
void *codegen_mem_load_word;
|
||||
void *codegen_mem_load_long;
|
||||
|
||||
void *codegen_mem_store_byte;
|
||||
void *codegen_mem_store_word;
|
||||
void *codegen_mem_store_long;
|
||||
|
||||
int codegen_host_reg_list[CODEGEN_HOST_REGS] =
|
||||
{
|
||||
REG_R4,
|
||||
|
|
@ -22,6 +31,137 @@ int codegen_host_reg_list[CODEGEN_HOST_REGS] =
|
|||
REG_R6,
|
||||
};
|
||||
|
||||
static void build_load_routine(codeblock_t *block, int size)
|
||||
{
|
||||
uint32_t *branch_offset;
|
||||
uint8_t *misaligned_offset;
|
||||
|
||||
/*In - R0 = address
|
||||
Out - R0 = data, R1 = abrt*/
|
||||
/*MOV R1, R0, LSR #12
|
||||
MOV R2, #readlookup2
|
||||
LDR R1, [R2, R1, LSL #2]
|
||||
CMP R1, #-1
|
||||
BNE +
|
||||
LDRB R0, [R1, R0]
|
||||
MOV R1, #0
|
||||
MOV PC, LR
|
||||
* STR LR, [SP, -4]!
|
||||
BL readmemb386l
|
||||
LDRB R1, cpu_state.abrt
|
||||
LDR PC, [SP], #4
|
||||
*/
|
||||
host_arm_MOV_REG_LSR(block, REG_R1, REG_R0, 12);
|
||||
host_arm_MOV_IMM(block, REG_R2, (uint32_t)readlookup2);
|
||||
host_arm_LDR_REG_LSL(block, REG_R1, REG_R2, REG_R1, 2);
|
||||
if (size != 1)
|
||||
{
|
||||
host_arm_TST_IMM(block, REG_R0, size-1);
|
||||
misaligned_offset = host_arm_BNE_(block);
|
||||
}
|
||||
host_arm_CMP_IMM(block, REG_R1, -1);
|
||||
branch_offset = host_arm_BEQ_(block);
|
||||
if (size == 1)
|
||||
host_arm_LDRB_REG(block, REG_R0, REG_R1, REG_R0);
|
||||
else if (size == 2)
|
||||
host_arm_LDRH_REG(block, REG_R0, REG_R1, REG_R0);
|
||||
else if (size == 4)
|
||||
host_arm_LDR_REG(block, REG_R0, REG_R1, REG_R0);
|
||||
host_arm_MOV_IMM(block, REG_R1, 0);
|
||||
host_arm_MOV_REG(block, REG_PC, REG_LR);
|
||||
|
||||
*branch_offset |= ((((uintptr_t)&block->data[block_pos] - (uintptr_t)branch_offset) - 8) & 0x3fffffc) >> 2;
|
||||
if (size != 1)
|
||||
*misaligned_offset |= ((((uintptr_t)&block->data[block_pos] - (uintptr_t)misaligned_offset) - 8) & 0x3fffffc) >> 2;
|
||||
host_arm_STR_IMM_WB(block, REG_LR, REG_SP, -4);
|
||||
if (size == 1)
|
||||
host_arm_BL(block, (uintptr_t)readmemb386l);
|
||||
else if (size == 2)
|
||||
host_arm_BL(block, (uintptr_t)readmemwl);
|
||||
else if (size == 4)
|
||||
host_arm_BL(block, (uintptr_t)readmemll);
|
||||
else
|
||||
fatal("build_load_routine - unknown size %i\n", size);
|
||||
host_arm_LDRB_ABS(block, REG_R1, &cpu_state.abrt);
|
||||
host_arm_LDR_IMM_POST(block, REG_PC, REG_SP, 4);
|
||||
|
||||
block_pos = (block_pos + 63) & ~63;
|
||||
}
|
||||
|
||||
static void build_store_routine(codeblock_t *block, int size)
|
||||
{
|
||||
uint8_t *branch_offset;
|
||||
uint8_t *misaligned_offset;
|
||||
|
||||
/*In - R0 = address
|
||||
Out - R0 = data, R1 = abrt*/
|
||||
/*MOV R1, R0, LSR #12
|
||||
MOV R2, #readlookup2
|
||||
LDR R1, [R2, R1, LSL #2]
|
||||
CMP R1, #-1
|
||||
BNE +
|
||||
LDRB R0, [R1, R0]
|
||||
MOV R1, #0
|
||||
MOV PC, LR
|
||||
* STR LR, [SP, -4]!
|
||||
BL readmemb386l
|
||||
LDRB R1, cpu_state.abrt
|
||||
LDR PC, [SP], #4
|
||||
*/
|
||||
host_arm_MOV_REG_LSR(block, REG_R2, REG_R0, 12);
|
||||
host_arm_MOV_IMM(block, REG_R3, (uint32_t)writelookup2);
|
||||
host_arm_LDR_REG_LSL(block, REG_R2, REG_R3, REG_R2, 2);
|
||||
if (size != 1)
|
||||
{
|
||||
host_arm_TST_IMM(block, REG_R0, size-1);
|
||||
misaligned_offset = host_arm_BNE_(block);
|
||||
}
|
||||
host_arm_CMP_IMM(block, REG_R2, -1);
|
||||
branch_offset = host_arm_BEQ_(block);
|
||||
if (size == 1)
|
||||
host_arm_STRB_REG(block, REG_R1, REG_R2, REG_R0);
|
||||
else if (size == 2)
|
||||
host_arm_STRH_REG(block, REG_R1, REG_R2, REG_R0);
|
||||
else if (size == 4)
|
||||
host_arm_STR_REG(block, REG_R1, REG_R2, REG_R0);
|
||||
host_arm_MOV_IMM(block, REG_R1, 0);
|
||||
host_arm_MOV_REG(block, REG_PC, REG_LR);
|
||||
|
||||
*branch_offset |= ((((uintptr_t)&block->data[block_pos] - (uintptr_t)branch_offset) - 8) & 0x3fffffc) >> 2;
|
||||
if (size != 1)
|
||||
*misaligned_offset |= ((((uintptr_t)&block->data[block_pos] - (uintptr_t)misaligned_offset) - 8) & 0x3fffffc) >> 2;
|
||||
host_arm_STR_IMM_WB(block, REG_LR, REG_SP, -4);
|
||||
if (size == 1)
|
||||
host_arm_BL(block, (uintptr_t)writememb386l);
|
||||
else if (size == 2)
|
||||
host_arm_BL(block, (uintptr_t)writememwl);
|
||||
else if (size == 4)
|
||||
host_arm_BL(block, (uintptr_t)writememll);
|
||||
else
|
||||
fatal("build_store_routine - unknown size %i\n", size);
|
||||
host_arm_LDRB_ABS(block, REG_R1, &cpu_state.abrt);
|
||||
host_arm_LDR_IMM_POST(block, REG_PC, REG_SP, 4);
|
||||
|
||||
block_pos = (block_pos + 63) & ~63;
|
||||
}
|
||||
|
||||
static void build_loadstore_routines(codeblock_t *block)
|
||||
{
|
||||
codegen_mem_load_byte = &codeblock[block_current].data[block_pos];
|
||||
build_load_routine(block, 1);
|
||||
codegen_mem_load_word = &codeblock[block_current].data[block_pos];
|
||||
build_load_routine(block, 2);
|
||||
codegen_mem_load_long = &codeblock[block_current].data[block_pos];
|
||||
build_load_routine(block, 4);
|
||||
|
||||
codegen_mem_store_byte = &codeblock[block_current].data[block_pos];
|
||||
build_store_routine(block, 1);
|
||||
codegen_mem_store_word = &codeblock[block_current].data[block_pos];
|
||||
build_store_routine(block, 2);
|
||||
codegen_mem_store_long = &codeblock[block_current].data[block_pos];
|
||||
build_store_routine(block, 4);
|
||||
}
|
||||
|
||||
void codegen_backend_init()
|
||||
{
|
||||
int c;
|
||||
|
|
@ -57,6 +197,10 @@ void codegen_backend_init()
|
|||
}
|
||||
#endif
|
||||
// pclog("Codegen is %p\n", (void *)pages[0xfab12 >> 12].block);
|
||||
|
||||
block_current = BLOCK_SIZE;
|
||||
block_pos = 0;
|
||||
build_loadstore_routines(&codeblock[block_current]);
|
||||
}
|
||||
|
||||
/*R11 - literal pool
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
#include "codegen.h"
|
||||
#include "codegen_backend.h"
|
||||
#include "codegen_backend_arm64_defs.h"
|
||||
#include "codegen_backend_arm64_ops.h"
|
||||
#include "x86.h"
|
||||
|
||||
#if defined(__linux__) || defined(__APPLE__)
|
||||
|
|
@ -15,6 +16,14 @@
|
|||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
void *codegen_mem_load_byte;
|
||||
void *codegen_mem_load_word;
|
||||
void *codegen_mem_load_long;
|
||||
|
||||
void *codegen_mem_store_byte;
|
||||
void *codegen_mem_store_word;
|
||||
void *codegen_mem_store_long;
|
||||
|
||||
int codegen_host_reg_list[CODEGEN_HOST_REGS] =
|
||||
{
|
||||
REG_X19,
|
||||
|
|
@ -24,6 +33,145 @@ int codegen_host_reg_list[CODEGEN_HOST_REGS] =
|
|||
REG_X23
|
||||
};
|
||||
|
||||
static void build_load_routine(codeblock_t *block, int size)
|
||||
{
|
||||
uint32_t *branch_offset;
|
||||
uint8_t *misaligned_offset;
|
||||
int offset;
|
||||
|
||||
/*In - W0 = address
|
||||
Out - W0 = data, W1 = abrt*/
|
||||
/*MOV W1, W0, LSR #12
|
||||
MOV X2, #readlookup2
|
||||
LDR X1, [X2, X1, LSL #3]
|
||||
CMP X1, #-1
|
||||
BEQ +
|
||||
LDRB W0, [X1, X0]
|
||||
MOV W1, #0
|
||||
RET
|
||||
* STP X29, X30, [SP, #-16]
|
||||
BL readmemb386l
|
||||
LDRB R1, cpu_state.abrt
|
||||
LDP X29, X30, [SP, #-16]
|
||||
RET
|
||||
*/
|
||||
host_arm64_MOV_REG_LSR(block, REG_W1, REG_W0, 12);
|
||||
offset = add_literal_q(block, (uintptr_t)readlookup2);
|
||||
host_arm64_LDR_LITERAL_X(block, REG_X2, offset);
|
||||
host_arm64_LDRX_REG_LSL3(block, REG_X1, REG_X2, REG_X1);
|
||||
if (size != 1)
|
||||
{
|
||||
host_arm64_TST_IMM(block, REG_W0, size-1);
|
||||
misaligned_offset = host_arm64_BNE_(block);
|
||||
}
|
||||
host_arm64_CMPX_IMM(block, REG_X1, -1);
|
||||
branch_offset = host_arm64_BEQ_(block);
|
||||
if (size == 1)
|
||||
host_arm64_LDRB_REG(block, REG_W0, REG_W1, REG_W0);
|
||||
else if (size == 2)
|
||||
host_arm64_LDRH_REG(block, REG_W0, REG_W1, REG_W0);
|
||||
else if (size == 4)
|
||||
host_arm64_LDR_REG(block, REG_W0, REG_W1, REG_W0);
|
||||
host_arm64_MOVZ_IMM(block, REG_W1, 0);
|
||||
host_arm64_RET(block, REG_X30);
|
||||
|
||||
host_arm64_branch_set_offset(branch_offset, &block->data[block_pos]);
|
||||
if (size != 1)
|
||||
host_arm64_branch_set_offset(misaligned_offset, &block->data[block_pos]);
|
||||
host_arm64_STP_PREIDX_X(block, REG_X29, REG_X30, REG_SP, -16);
|
||||
if (size == 1)
|
||||
host_arm64_call(block, (uintptr_t)readmemb386l);
|
||||
else if (size == 2)
|
||||
host_arm64_call(block, (uintptr_t)readmemwl);
|
||||
else if (size == 4)
|
||||
host_arm64_call(block, (uintptr_t)readmemll);
|
||||
else
|
||||
fatal("build_load_routine - unknown size %i\n", size);
|
||||
codegen_direct_read_8(block, REG_W1, &cpu_state.abrt);
|
||||
host_arm64_LDP_POSTIDX_X(block, REG_X29, REG_X30, REG_SP, 16);
|
||||
host_arm64_RET(block, REG_X30);
|
||||
|
||||
block_pos = (block_pos + 63) & ~63;
|
||||
}
|
||||
|
||||
static void build_store_routine(codeblock_t *block, int size)
|
||||
{
|
||||
uint8_t *branch_offset;
|
||||
uint8_t *misaligned_offset;
|
||||
int offset;
|
||||
|
||||
/*In - R0 = address, R1 = data
|
||||
Out - R1 = abrt*/
|
||||
/*MOV W2, W0, LSR #12
|
||||
MOV X3, #writelookup2
|
||||
LDR X2, [X3, X2, LSL #3]
|
||||
CMP X2, #-1
|
||||
BEQ +
|
||||
STRB W1, [X2, X0]
|
||||
MOV W1, #0
|
||||
RET
|
||||
* STP X29, X30, [SP, #-16]
|
||||
BL writememb386l
|
||||
LDRB R1, cpu_state.abrt
|
||||
LDP X29, X30, [SP, #-16]
|
||||
RET
|
||||
*/
|
||||
host_arm64_MOV_REG_LSR(block, REG_W2, REG_W0, 12);
|
||||
offset = add_literal_q(block, (uintptr_t)writelookup2);
|
||||
host_arm64_LDR_LITERAL_X(block, REG_X3, offset);
|
||||
host_arm64_LDRX_REG_LSL3(block, REG_X2, REG_X3, REG_X2);
|
||||
if (size != 1)
|
||||
{
|
||||
host_arm64_TST_IMM(block, REG_W0, size-1);
|
||||
misaligned_offset = host_arm64_BNE_(block);
|
||||
}
|
||||
host_arm64_CMPX_IMM(block, REG_X2, -1);
|
||||
branch_offset = host_arm64_BEQ_(block);
|
||||
if (size == 1)
|
||||
host_arm64_STRB_REG(block, REG_X1, REG_X2, REG_X0);
|
||||
else if (size == 2)
|
||||
host_arm64_STRH_REG(block, REG_X1, REG_X2, REG_X0);
|
||||
else if (size == 4)
|
||||
host_arm64_STR_REG(block, REG_X1, REG_X2, REG_X0);
|
||||
host_arm64_MOVZ_IMM(block, REG_X1, 0);
|
||||
host_arm64_RET(block, REG_X30);
|
||||
|
||||
host_arm64_branch_set_offset(branch_offset, &block->data[block_pos]);
|
||||
if (size != 1)
|
||||
host_arm64_branch_set_offset(misaligned_offset, &block->data[block_pos]);
|
||||
host_arm64_STP_PREIDX_X(block, REG_X29, REG_X30, REG_SP, -16);
|
||||
if (size == 1)
|
||||
host_arm64_call(block, (uintptr_t)writememb386l);
|
||||
else if (size == 2)
|
||||
host_arm64_call(block, (uintptr_t)writememwl);
|
||||
else if (size == 4)
|
||||
host_arm64_call(block, (uintptr_t)writememll);
|
||||
else
|
||||
fatal("build_store_routine - unknown size %i\n", size);
|
||||
codegen_direct_read_8(block, REG_W1, &cpu_state.abrt);
|
||||
host_arm64_LDP_POSTIDX_X(block, REG_X29, REG_X30, REG_SP, 16);
|
||||
host_arm64_RET(block, REG_X30);
|
||||
|
||||
block_pos = (block_pos + 63) & ~63;
|
||||
}
|
||||
|
||||
static void build_loadstore_routines(codeblock_t *block)
|
||||
{
|
||||
codegen_mem_load_byte = &codeblock[block_current].data[block_pos];
|
||||
build_load_routine(block, 1);
|
||||
codegen_mem_load_word = &codeblock[block_current].data[block_pos];
|
||||
build_load_routine(block, 2);
|
||||
codegen_mem_load_long = &codeblock[block_current].data[block_pos];
|
||||
build_load_routine(block, 4);
|
||||
|
||||
codegen_mem_store_byte = &codeblock[block_current].data[block_pos];
|
||||
build_store_routine(block, 1);
|
||||
codegen_mem_store_word = &codeblock[block_current].data[block_pos];
|
||||
build_store_routine(block, 2);
|
||||
codegen_mem_store_long = &codeblock[block_current].data[block_pos];
|
||||
build_store_routine(block, 4);
|
||||
}
|
||||
|
||||
void codegen_backend_init()
|
||||
{
|
||||
int c;
|
||||
|
|
@ -59,6 +207,11 @@ void codegen_backend_init()
|
|||
}
|
||||
#endif
|
||||
// pclog("Codegen is %p\n", (void *)pages[0xfab12 >> 12].block);
|
||||
|
||||
block_current = BLOCK_SIZE;
|
||||
block_pos = 0;
|
||||
codegen_reset_literal_pool(&codeblock[block_current]);
|
||||
build_loadstore_routines(&codeblock[block_current]);
|
||||
}
|
||||
|
||||
/*R11 - literal pool
|
||||
|
|
|
|||
|
|
@ -75,4 +75,12 @@
|
|||
|
||||
#define REG_TEMP REG_X7
|
||||
|
||||
#define CODEGEN_HOST_REGS 5
|
||||
#define CODEGEN_HOST_REGS 5
|
||||
|
||||
extern void *codegen_mem_load_byte;
|
||||
extern void *codegen_mem_load_word;
|
||||
extern void *codegen_mem_load_long;
|
||||
|
||||
extern void *codegen_mem_store_byte;
|
||||
extern void *codegen_mem_store_word;
|
||||
extern void *codegen_mem_store_long;
|
||||
613
src/codegen_backend_arm64_ops.c
Normal file
613
src/codegen_backend_arm64_ops.c
Normal file
|
|
@ -0,0 +1,613 @@
|
|||
#ifdef __aarch64__
|
||||
|
||||
#include "ibm.h"
|
||||
#include "codegen.h"
|
||||
#include "codegen_backend.h"
|
||||
#include "codegen_backend_arm64_defs.h"
|
||||
#include "codegen_backend_arm64_ops.h"
|
||||
|
||||
|
||||
static inline void codegen_addlong(codeblock_t *block, uint32_t val)
|
||||
{
|
||||
*(uint32_t *)&block->data[block_pos] = val;
|
||||
block_pos += 4;
|
||||
if (block_pos >= BLOCK_MAX)
|
||||
{
|
||||
fatal("codegen_addlong over! %i\n", block_pos);
|
||||
CPU_BLOCK_END();
|
||||
}
|
||||
}
|
||||
|
||||
#define Rt(x) (x)
|
||||
#define Rd(x) (x)
|
||||
#define Rn(x) ((x) << 5)
|
||||
#define Rt2(x) ((x) << 10)
|
||||
#define Rm(x) ((x) << 16)
|
||||
|
||||
#define shift_imm6(x) ((x) << 10)
|
||||
|
||||
#define DATA_OFFSET_UP (1 << 23)
|
||||
#define DATA_OFFSET_DOWN (0 << 23)
|
||||
|
||||
#define COND_EQ (0x0)
|
||||
#define COND_NE (0x1)
|
||||
|
||||
#define OPCODE_SHIFT 24
|
||||
#define OPCODE_ADD_IMM (0x11 << OPCODE_SHIFT)
|
||||
#define OPCODE_BCOND (0x54 << OPCODE_SHIFT)
|
||||
#define OPCODE_CBNZ (0xb5 << OPCODE_SHIFT)
|
||||
#define OPCODE_CMN_IMM (0x31 << OPCODE_SHIFT)
|
||||
#define OPCODE_CMNX_IMM (0xb1 << OPCODE_SHIFT)
|
||||
#define OPCODE_CMP_IMM (0x71 << OPCODE_SHIFT)
|
||||
#define OPCODE_CMPX_IMM (0xf1 << OPCODE_SHIFT)
|
||||
#define OPCODE_LDR_LITERAL_W (0x18 << OPCODE_SHIFT)
|
||||
#define OPCODE_LDR_LITERAL_X (0x58 << OPCODE_SHIFT)
|
||||
#define OPCODE_SUB_IMM (0x51 << OPCODE_SHIFT)
|
||||
|
||||
#define OPCODE_AND_IMM (0x024 << 23)
|
||||
#define OPCODE_ANDS_IMM (0x0e4 << 23)
|
||||
#define OPCODE_EOR_IMM (0x0a4 << 23)
|
||||
#define OPCODE_MOVK_W (0x0e5 << 23)
|
||||
#define OPCODE_MOVZ_W (0x0a5 << 23)
|
||||
#define OPCODE_ORR_IMM (0x064 << 23)
|
||||
|
||||
#define OPCODE_BFI (0x0cc << 22)
|
||||
#define OPCODE_LDR_IMM_W (0x2e5 << 22)
|
||||
#define OPCODE_LDRB_IMM_W (0x0e5 << 22)
|
||||
#define OPCODE_LDP_POSTIDX_X (0x2a3 << 22)
|
||||
#define OPCODE_STP_PREIDX_X (0x2a6 << 22)
|
||||
#define OPCODE_STR_IMM_W (0x2e4 << 22)
|
||||
#define OPCODE_STR_IMM_Q (0x3e4 << 22)
|
||||
#define OPCODE_STRB_IMM (0x0e4 << 22)
|
||||
#define OPCODE_UBFX (0x14c << 22)
|
||||
|
||||
#define OPCODE_ADD_LSL (0x058 << 21)
|
||||
#define OPCODE_ADD_LSR (0x05a << 21)
|
||||
#define OPCODE_AND_ASR (0x054 << 21)
|
||||
#define OPCODE_AND_LSL (0x050 << 21)
|
||||
#define OPCODE_AND_ROR (0x056 << 21)
|
||||
#define OPCODE_ANDS_LSL (0x350 << 21)
|
||||
#define OPCODE_EOR_LSL (0x250 << 21)
|
||||
#define OPCODE_ORR_LSL (0x150 << 21)
|
||||
#define OPCODE_ORR_LSR (0x152 << 21)
|
||||
#define OPCODE_SUB_LSL (0x258 << 21)
|
||||
#define OPCODE_SUB_LSR (0x25a << 21)
|
||||
|
||||
#define OPCODE_BLR (0xd63f0000)
|
||||
#define OPCODE_LDR_REG (0xb8606800)
|
||||
#define OPCODE_LDRB_REG (0x38606800)
|
||||
#define OPCODE_LDRH_REG (0x78606800)
|
||||
#define OPCODE_LDRX_REG_LSL3 (0xf8607800)
|
||||
#define OPCODE_NOP (0xd503201f)
|
||||
#define OPCODE_RET (0xd65f0000)
|
||||
#define OPCODE_STR_REG (0xb8206800)
|
||||
#define OPCODE_STRB_REG (0x38206800)
|
||||
#define OPCODE_STRH_REG (0x78206800)
|
||||
|
||||
#define DATPROC_SHIFT(sh) (sh << 10)
|
||||
#define DATPROC_IMM_SHIFT(sh) (sh << 22)
|
||||
#define MOV_WIDE_HW(hw) (hw << 21)
|
||||
|
||||
#define IMM7_X(imm_data) (((imm_data >> 3) & 0x7f) << 15)
|
||||
#define IMM12(imm_data) ((imm_data) << 10)
|
||||
#define IMM16(imm_data) ((imm_data) << 5)
|
||||
|
||||
#define IMMN(immn) ((immn) << 22)
|
||||
#define IMMR(immr) ((immr) << 16)
|
||||
#define IMMS(imms) ((imms) << 10)
|
||||
|
||||
#define OFFSET19(offset) (((offset >> 2) << 5) & 0x00ffffe0)
|
||||
|
||||
#define OFFSET12_B(offset) (offset << 10)
|
||||
#define OFFSET12_W(offset) ((offset >> 2) << 10)
|
||||
#define OFFSET12_Q(offset) ((offset >> 3) << 10)
|
||||
|
||||
static int literal_offset = 0;
|
||||
void codegen_reset_literal_pool(codeblock_t *block)
|
||||
{
|
||||
literal_offset = 0;
|
||||
}
|
||||
|
||||
/*Returns true if offset fits into 19 bits*/
|
||||
static int offset_is_19bit(int offset)
|
||||
{
|
||||
if (offset >= (1 << (18+2)))
|
||||
return 0;
|
||||
if (offset < -(1 << (18+2)))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int add_literal(codeblock_t *block, uint32_t data)
|
||||
{
|
||||
if (literal_offset >= 4096)
|
||||
fatal("add_literal - literal pool full\n");
|
||||
|
||||
*(uint32_t *)&block->data[ARM_LITERAL_POOL_OFFSET + literal_offset] = data;
|
||||
|
||||
literal_offset += 4;
|
||||
|
||||
return literal_offset - 4;
|
||||
}
|
||||
|
||||
int add_literal_q(codeblock_t *block, uint64_t data)
|
||||
{
|
||||
if (literal_offset & 4)
|
||||
literal_offset += 4;
|
||||
|
||||
if (literal_offset >= 4096-4)
|
||||
fatal("add_literal - literal pool full\n");
|
||||
|
||||
*(uint64_t *)&block->data[ARM_LITERAL_POOL_OFFSET + literal_offset] = data;
|
||||
|
||||
literal_offset += 8;
|
||||
|
||||
return literal_offset - 8;
|
||||
}
|
||||
|
||||
static inline int imm_is_imm16(uint32_t imm_data)
|
||||
{
|
||||
if (!(imm_data & 0xffff0000) || !(imm_data & 0x0000ffff))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
static inline int imm_is_imm12(uint32_t imm_data)
|
||||
{
|
||||
if (!(imm_data & 0xfffff000) || !(imm_data & 0xff000fff))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void host_arm64_ADD_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data)
|
||||
{
|
||||
if (!imm_data)
|
||||
host_arm64_MOV_REG(block, dst_reg, src_n_reg, 0);
|
||||
else if ((int32_t)imm_data < 0 && imm_data != 0x80000000)
|
||||
{
|
||||
host_arm64_SUB_IMM(block, dst_reg, src_n_reg, -(int32_t)imm_data);
|
||||
}
|
||||
else if (!(imm_data & 0xff000000))
|
||||
{
|
||||
if (imm_data & 0xfff)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_ADD_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM12(imm_data & 0xfff) | DATPROC_IMM_SHIFT(0));
|
||||
if (imm_data & 0xfff000)
|
||||
codegen_addlong(block, OPCODE_ADD_IMM | Rd(dst_reg) | Rn(dst_reg) | IMM12((imm_data >> 12) & 0xfff) | DATPROC_IMM_SHIFT(1));
|
||||
}
|
||||
else if (imm_data & 0xfff000)
|
||||
codegen_addlong(block, OPCODE_ADD_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM12((imm_data >> 12) & 0xfff) | DATPROC_IMM_SHIFT(1));
|
||||
}
|
||||
else
|
||||
{
|
||||
host_arm64_MOVZ_IMM(block, REG_W16, imm_data & 0xffff);
|
||||
host_arm64_MOVK_IMM(block, REG_W16, imm_data & 0xffff0000);
|
||||
codegen_addlong(block, OPCODE_ADD_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(REG_W16) | DATPROC_SHIFT(0));
|
||||
}
|
||||
}
|
||||
void host_arm64_ADD_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_ADD_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift));
|
||||
}
|
||||
void host_arm64_ADD_REG_LSR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_ADD_LSR | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift));
|
||||
}
|
||||
|
||||
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 */
|
||||
{
|
||||
codegen_addlong(block, OPCODE_AND_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(0) | IMMS(0x07));
|
||||
}
|
||||
else if (imm_data == 0xffff) /*Quick hack until proper immediate generation is written */
|
||||
{
|
||||
codegen_addlong(block, OPCODE_AND_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(0) | IMMS(0x0f));
|
||||
}
|
||||
else if (imm_data == 0xffffff00)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_AND_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(24) | IMMS(0x17));
|
||||
}
|
||||
else if (imm_data == 0xffff00ff)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_AND_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(16) | IMMS(0x17));
|
||||
}
|
||||
else if (imm_data == 0x0000ff00)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_AND_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(24) | IMMS(0x07));
|
||||
}
|
||||
else
|
||||
{
|
||||
host_arm64_mov_imm(block, REG_W16, imm_data);
|
||||
codegen_addlong(block, OPCODE_AND_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(REG_W16) | DATPROC_SHIFT(0));
|
||||
}
|
||||
}
|
||||
void host_arm64_AND_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_AND_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift));
|
||||
}
|
||||
void host_arm64_AND_REG_ASR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_AND_ASR | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift));
|
||||
}
|
||||
void host_arm64_AND_REG_ROR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_AND_ROR | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift));
|
||||
}
|
||||
|
||||
void host_arm64_ANDS_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 */
|
||||
{
|
||||
codegen_addlong(block, OPCODE_ANDS_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(0) | IMMS(0x07));
|
||||
}
|
||||
else if (imm_data == 0xffff) /*Quick hack until proper immediate generation is written */
|
||||
{
|
||||
codegen_addlong(block, OPCODE_ANDS_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(0) | IMMS(0x0f));
|
||||
}
|
||||
else if (imm_data == 0xffffff00)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_ANDS_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(24) | IMMS(0x17));
|
||||
}
|
||||
else if (imm_data == 0xffff00ff)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_ANDS_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(16) | IMMS(0x17));
|
||||
}
|
||||
else if (imm_data == 0x0000ff00)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_ANDS_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(24) | IMMS(0x07));
|
||||
}
|
||||
else
|
||||
{
|
||||
host_arm64_mov_imm(block, REG_W16, imm_data);
|
||||
codegen_addlong(block, OPCODE_ANDS_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(REG_W16) | DATPROC_SHIFT(0));
|
||||
}
|
||||
}
|
||||
|
||||
void host_arm64_BFI(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_BFI | Rd(dst_reg) | Rn(src_reg) | IMMN(0) | IMMR((32 - lsb) & 31) | IMMS((width-1) & 31));
|
||||
}
|
||||
|
||||
void host_arm64_BLR(codeblock_t *block, int addr_reg)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_BLR | Rn(addr_reg));
|
||||
}
|
||||
|
||||
uint32_t *host_arm64_BEQ_(codeblock_t *block)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_BCOND | COND_EQ);
|
||||
return &block->data[block_pos-4];
|
||||
}
|
||||
uint32_t *host_arm64_BNE_(codeblock_t *block)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_BCOND | COND_NE);
|
||||
return &block->data[block_pos-4];
|
||||
}
|
||||
|
||||
void host_arm64_branch_set_offset(uint32_t *opcode, void *dest)
|
||||
{
|
||||
int offset = (uintptr_t)dest - (uintptr_t)opcode;
|
||||
*opcode |= OFFSET19(offset);
|
||||
}
|
||||
|
||||
void host_arm64_BEQ(codeblock_t *block, void *dest)
|
||||
{
|
||||
uint32_t *opcode = host_arm64_BEQ_(block);
|
||||
host_arm64_branch_set_offset(opcode, dest);
|
||||
}
|
||||
|
||||
void host_arm64_CBNZ(codeblock_t *block, int reg, uintptr_t dest)
|
||||
{
|
||||
int offset = dest - (uintptr_t)&block->data[block_pos];
|
||||
if (!offset_is_19bit(offset))
|
||||
fatal("host_arm64_CBNZ - offset out of range %x\n", offset);
|
||||
codegen_addlong(block, OPCODE_CBNZ | OFFSET19(offset) | Rt(reg));
|
||||
}
|
||||
|
||||
void host_arm64_CMN_IMM(codeblock_t *block, int src_n_reg, uint32_t imm_data)
|
||||
{
|
||||
if ((int32_t)imm_data < 0 && imm_data != (1ull << 31))
|
||||
{
|
||||
host_arm64_CMP_IMM(block, src_n_reg, -(int32_t)imm_data);
|
||||
}
|
||||
else if (!(imm_data & 0xfffff000))
|
||||
{
|
||||
codegen_addlong(block, OPCODE_CMN_IMM | Rd(REG_WZR) | Rn(src_n_reg) | IMM12(imm_data & 0xfff) | DATPROC_IMM_SHIFT(0));
|
||||
}
|
||||
else
|
||||
fatal("CMN_IMM %08x\n", imm_data);
|
||||
}
|
||||
void host_arm64_CMNX_IMM(codeblock_t *block, int src_n_reg, uint64_t imm_data)
|
||||
{
|
||||
if ((int64_t)imm_data < 0 && imm_data != (1ull << 63))
|
||||
{
|
||||
host_arm64_CMPX_IMM(block, src_n_reg, -(int64_t)imm_data);
|
||||
}
|
||||
else if (!(imm_data & 0xfffffffffffff000ull))
|
||||
{
|
||||
codegen_addlong(block, OPCODE_CMNX_IMM | Rd(REG_XZR) | Rn(src_n_reg) | IMM12(imm_data & 0xfff) | DATPROC_IMM_SHIFT(0));
|
||||
}
|
||||
else
|
||||
fatal("CMNX_IMM %08x\n", imm_data);
|
||||
}
|
||||
|
||||
void host_arm64_CMP_IMM(codeblock_t *block, int src_n_reg, uint32_t imm_data)
|
||||
{
|
||||
if ((int32_t)imm_data < 0 && imm_data != (1ull << 31))
|
||||
{
|
||||
host_arm64_CMN_IMM(block, src_n_reg, -(int32_t)imm_data);
|
||||
}
|
||||
else if (!(imm_data & 0xfffff000))
|
||||
{
|
||||
codegen_addlong(block, OPCODE_CMP_IMM | Rd(REG_WZR) | Rn(src_n_reg) | IMM12(imm_data & 0xfff) | DATPROC_IMM_SHIFT(0));
|
||||
}
|
||||
else
|
||||
fatal("CMP_IMM %08x\n", imm_data);
|
||||
}
|
||||
void host_arm64_CMPX_IMM(codeblock_t *block, int src_n_reg, uint64_t imm_data)
|
||||
{
|
||||
if ((int64_t)imm_data < 0 && imm_data != (1ull << 63))
|
||||
{
|
||||
host_arm64_CMNX_IMM(block, src_n_reg, -(int64_t)imm_data);
|
||||
}
|
||||
else if (!(imm_data & 0xfffffffffffff000ull))
|
||||
{
|
||||
codegen_addlong(block, OPCODE_CMPX_IMM | Rd(REG_XZR) | Rn(src_n_reg) | IMM12(imm_data & 0xfff) | DATPROC_IMM_SHIFT(0));
|
||||
}
|
||||
else
|
||||
fatal("CMPX_IMM %08x\n", imm_data);
|
||||
}
|
||||
|
||||
void host_arm64_EOR_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data)
|
||||
{
|
||||
if (imm_data == 0xffff) /*Quick hack until proper immediate generation is written */
|
||||
{
|
||||
codegen_addlong(block, OPCODE_EOR_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(0) | IMMS(0x0f));
|
||||
}
|
||||
else
|
||||
{
|
||||
host_arm64_mov_imm(block, REG_W16, imm_data);
|
||||
codegen_addlong(block, OPCODE_EOR_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(REG_W16) | DATPROC_SHIFT(0));
|
||||
}
|
||||
}
|
||||
void host_arm64_EOR_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_EOR_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift));
|
||||
}
|
||||
|
||||
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))
|
||||
fatal("host_arm64_LDP_POSTIDX out of range7 %i\n", offset);
|
||||
codegen_addlong(block, OPCODE_LDP_POSTIDX_X | IMM7_X(offset) | Rn(base_reg) | Rt(src_reg1) | Rt2(src_reg2));
|
||||
}
|
||||
|
||||
void host_arm64_LDR_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int offset)
|
||||
{
|
||||
if (!in_range12_w(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));
|
||||
}
|
||||
|
||||
void host_arm64_LDR_LITERAL_W(codeblock_t *block, int dest_reg, int literal_offset)
|
||||
{
|
||||
int offset = (ARM_LITERAL_POOL_OFFSET + literal_offset) - block_pos;
|
||||
|
||||
if (!offset_is_19bit(offset))
|
||||
fatal("host_arm64_CBNZ - offset out of range %x\n", offset);
|
||||
|
||||
codegen_addlong(block, OPCODE_LDR_LITERAL_W | OFFSET19(offset) | Rt(dest_reg));
|
||||
}
|
||||
void host_arm64_LDR_LITERAL_X(codeblock_t *block, int dest_reg, int literal_offset)
|
||||
{
|
||||
int offset = (ARM_LITERAL_POOL_OFFSET + literal_offset) - block_pos;
|
||||
|
||||
if (!offset_is_19bit(offset))
|
||||
fatal("host_arm64_CBNZ - offset out of range %x\n", offset);
|
||||
|
||||
codegen_addlong(block, OPCODE_LDR_LITERAL_X | OFFSET19(offset) | Rt(dest_reg));
|
||||
}
|
||||
void host_arm64_LDR_REG(codeblock_t *block, int dest_reg, int base_reg, int offset_reg)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_LDR_REG | Rn(base_reg) | Rm(offset_reg) | Rt(dest_reg));
|
||||
}
|
||||
|
||||
void host_arm64_LDRB_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int offset)
|
||||
{
|
||||
if (!in_range12_b(offset))
|
||||
fatal("host_arm64_LDRB_IMM_W out of range12 %i\n", offset);
|
||||
codegen_addlong(block, OPCODE_LDRB_IMM_W | OFFSET12_B(offset) | Rn(base_reg) | Rt(dest_reg));
|
||||
}
|
||||
void host_arm64_LDRB_REG(codeblock_t *block, int dest_reg, int base_reg, int offset_reg)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_LDRB_REG | Rn(base_reg) | Rm(offset_reg) | Rt(dest_reg));
|
||||
}
|
||||
|
||||
void host_arm64_LDRH_REG(codeblock_t *block, int dest_reg, int base_reg, int offset_reg)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_LDRH_REG | Rn(base_reg) | Rm(offset_reg) | Rt(dest_reg));
|
||||
}
|
||||
|
||||
void host_arm64_LDRX_REG_LSL3(codeblock_t *block, int dest_reg, int base_reg, int offset_reg)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_LDRX_REG_LSL3 | Rn(base_reg) | Rm(offset_reg) | Rt(dest_reg));
|
||||
}
|
||||
|
||||
void host_arm64_MOV_REG(codeblock_t *block, int dst_reg, int src_m_reg, int shift)
|
||||
{
|
||||
if (dst_reg != src_m_reg)
|
||||
codegen_addlong(block, OPCODE_ORR_LSL | Rd(dst_reg) | Rn(REG_WZR) | Rm(src_m_reg) | DATPROC_SHIFT(shift));
|
||||
}
|
||||
|
||||
void host_arm64_MOV_REG_LSR(codeblock_t *block, int dst_reg, int src_m_reg, int shift)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_ORR_LSR | Rd(dst_reg) | Rn(REG_WZR) | Rm(src_m_reg) | DATPROC_SHIFT(shift));
|
||||
}
|
||||
|
||||
void host_arm64_MOVZ_IMM(codeblock_t *block, int reg, uint32_t imm_data)
|
||||
{
|
||||
int hw;
|
||||
|
||||
if (!imm_is_imm16(imm_data))
|
||||
fatal("MOVZ_IMM - imm not representable %08x\n", imm_data);
|
||||
|
||||
hw = (imm_data & 0xffff0000) ? 1 : 0;
|
||||
if (hw)
|
||||
imm_data >>= 16;
|
||||
|
||||
codegen_addlong(block, OPCODE_MOVZ_W | MOV_WIDE_HW(hw) | IMM16(imm_data) | Rd(reg));
|
||||
}
|
||||
|
||||
void host_arm64_MOVK_IMM(codeblock_t *block, int reg, uint32_t imm_data)
|
||||
{
|
||||
int hw;
|
||||
|
||||
if (!imm_is_imm16(imm_data))
|
||||
fatal("MOVK_IMM - imm not representable %08x\n", imm_data);
|
||||
|
||||
hw = (imm_data & 0xffff0000) ? 1 : 0;
|
||||
if (hw)
|
||||
imm_data >>= 16;
|
||||
|
||||
codegen_addlong(block, OPCODE_MOVK_W | MOV_WIDE_HW(hw) | IMM16(imm_data) | Rd(reg));
|
||||
}
|
||||
|
||||
void host_arm64_NOP(codeblock_t *block)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_NOP);
|
||||
}
|
||||
|
||||
void host_arm64_ORR_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data)
|
||||
{
|
||||
if (imm_data == 0xffff) /*Quick hack until proper immediate generation is written */
|
||||
{
|
||||
codegen_addlong(block, OPCODE_ORR_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(0) | IMMS(0x0f));
|
||||
}
|
||||
else if (imm_data == 0xffff0000)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_ORR_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(16) | IMMS(0x0f));
|
||||
}
|
||||
else if (imm_data == 0xffffff00)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_ORR_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(24) | IMMS(0x17));
|
||||
}
|
||||
else if (imm_data == 0xffff00ff)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_ORR_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(16) | IMMS(0x17));
|
||||
}
|
||||
else
|
||||
{
|
||||
host_arm64_mov_imm(block, REG_W16, imm_data);
|
||||
codegen_addlong(block, OPCODE_ORR_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(REG_W16) | DATPROC_SHIFT(0));
|
||||
}
|
||||
}
|
||||
void host_arm64_ORR_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_ORR_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift));
|
||||
}
|
||||
|
||||
void host_arm64_RET(codeblock_t *block, int reg)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_RET | Rn(reg));
|
||||
}
|
||||
|
||||
void host_arm64_STP_PREIDX_X(codeblock_t *block, int src_reg1, int src_reg2, int base_reg, int offset)
|
||||
{
|
||||
if (!in_range7_x(offset))
|
||||
fatal("host_arm64_STP_PREIDX out of range7 %i\n", offset);
|
||||
codegen_addlong(block, OPCODE_STP_PREIDX_X | IMM7_X(offset) | Rn(base_reg) | Rt(src_reg1) | Rt2(src_reg2));
|
||||
}
|
||||
|
||||
void host_arm64_STR_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int offset)
|
||||
{
|
||||
if (!in_range12_w(offset))
|
||||
fatal("host_arm64_STR_IMM_W out of range12 %i\n", offset);
|
||||
codegen_addlong(block, OPCODE_STR_IMM_W | OFFSET12_W(offset) | Rn(base_reg) | Rt(dest_reg));
|
||||
}
|
||||
void host_arm64_STR_IMM_Q(codeblock_t *block, int dest_reg, int base_reg, int offset)
|
||||
{
|
||||
if (!in_range12_q(offset))
|
||||
fatal("host_arm64_STR_IMM_W out of range12 %i\n", offset);
|
||||
codegen_addlong(block, OPCODE_STR_IMM_Q | OFFSET12_Q(offset) | Rn(base_reg) | Rt(dest_reg));
|
||||
}
|
||||
void host_arm64_STR_REG(codeblock_t *block, int src_reg, int base_reg, int offset_reg)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_STR_REG | Rn(base_reg) | Rm(offset_reg) | Rt(src_reg));
|
||||
}
|
||||
|
||||
void host_arm64_STRB_IMM(codeblock_t *block, int dest_reg, int base_reg, int offset)
|
||||
{
|
||||
if (!in_range12_b(offset))
|
||||
fatal("host_arm64_STRB_IMM out of range12 %i\n", offset);
|
||||
codegen_addlong(block, OPCODE_STRB_IMM | OFFSET12_B(offset) | Rn(base_reg) | Rt(dest_reg));
|
||||
}
|
||||
void host_arm64_STRB_REG(codeblock_t *block, int src_reg, int base_reg, int offset_reg)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_STRB_REG | Rn(base_reg) | Rm(offset_reg) | Rt(src_reg));
|
||||
}
|
||||
|
||||
void host_arm64_STRH_REG(codeblock_t *block, int src_reg, int base_reg, int offset_reg)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_STRH_REG | Rn(base_reg) | Rm(offset_reg) | Rt(src_reg));
|
||||
}
|
||||
|
||||
void host_arm64_SUB_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data)
|
||||
{
|
||||
if (!imm_data)
|
||||
host_arm64_MOV_REG(block, dst_reg, src_n_reg, 0);
|
||||
else if ((int32_t)imm_data < 0 && imm_data != 0x80000000)
|
||||
{
|
||||
host_arm64_ADD_IMM(block, dst_reg, src_n_reg, -(int32_t)imm_data);
|
||||
}
|
||||
else if (!(imm_data & 0xff000000))
|
||||
{
|
||||
if (imm_data & 0xfff)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_SUB_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM12(imm_data & 0xfff) | DATPROC_IMM_SHIFT(0));
|
||||
if (imm_data & 0xfff000)
|
||||
codegen_addlong(block, OPCODE_SUB_IMM | Rd(dst_reg) | Rn(dst_reg) | IMM12((imm_data >> 12) & 0xfff) | DATPROC_IMM_SHIFT(1));
|
||||
}
|
||||
else if (imm_data & 0xfff000)
|
||||
codegen_addlong(block, OPCODE_SUB_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM12((imm_data >> 12) & 0xfff) | DATPROC_IMM_SHIFT(1));
|
||||
}
|
||||
else
|
||||
{
|
||||
host_arm64_MOVZ_IMM(block, REG_W16, imm_data & 0xffff);
|
||||
host_arm64_MOVK_IMM(block, REG_W16, imm_data & 0xffff0000);
|
||||
codegen_addlong(block, OPCODE_SUB_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(REG_W16) | DATPROC_SHIFT(0));
|
||||
}
|
||||
}
|
||||
void host_arm64_SUB_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_SUB_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift));
|
||||
}
|
||||
void host_arm64_SUB_REG_LSR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_SUB_LSR | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift));
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
|
||||
void host_arm64_call(codeblock_t *block, void *dst_addr)
|
||||
{
|
||||
int offset = add_literal_q(block, (uintptr_t)dst_addr);
|
||||
host_arm64_LDR_LITERAL_X(block, REG_X16, offset);
|
||||
host_arm64_BLR(block, REG_X16);
|
||||
}
|
||||
|
||||
void host_arm64_mov_imm(codeblock_t *block, int reg, uint32_t imm_data)
|
||||
{
|
||||
if (imm_is_imm16(imm_data))
|
||||
host_arm64_MOVZ_IMM(block, reg, imm_data);
|
||||
else
|
||||
{
|
||||
host_arm64_MOVZ_IMM(block, reg, imm_data & 0xffff);
|
||||
host_arm64_MOVK_IMM(block, reg, imm_data & 0xffff0000);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
92
src/codegen_backend_arm64_ops.h
Normal file
92
src/codegen_backend_arm64_ops.h
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
void host_arm64_ADD_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data);
|
||||
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_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_ASR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift);
|
||||
void host_arm64_AND_REG_ROR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift);
|
||||
|
||||
void host_arm64_ANDS_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data);
|
||||
|
||||
void host_arm64_BFI(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width);
|
||||
|
||||
void host_arm64_BLR(codeblock_t *block, int addr_reg);
|
||||
|
||||
void host_arm64_BEQ(codeblock_t *block, void *dest);
|
||||
|
||||
uint32_t *host_arm64_BEQ_(codeblock_t *block);
|
||||
uint32_t *host_arm64_BNE_(codeblock_t *block);
|
||||
|
||||
void host_arm64_branch_set_offset(uint32_t *opcode, void *dest);
|
||||
|
||||
void host_arm64_CBNZ(codeblock_t *block, int reg, uintptr_t dest);
|
||||
|
||||
void host_arm64_CMN_IMM(codeblock_t *block, int src_n_reg, uint32_t imm_data);
|
||||
void host_arm64_CMNX_IMM(codeblock_t *block, int src_n_reg, uint64_t imm_data);
|
||||
|
||||
void host_arm64_CMP_IMM(codeblock_t *block, int src_n_reg, uint32_t imm_data);
|
||||
void host_arm64_CMPX_IMM(codeblock_t *block, int src_n_reg, uint64_t imm_data);
|
||||
|
||||
void host_arm64_EOR_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data);
|
||||
void host_arm64_EOR_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift);
|
||||
|
||||
void host_arm64_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_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_REG(codeblock_t *block, int dest_reg, int base_reg, int offset_reg);
|
||||
|
||||
void host_arm64_LDRB_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int offset);
|
||||
void host_arm64_LDRB_REG(codeblock_t *block, int dest_reg, int base_reg, int offset_reg);
|
||||
|
||||
void host_arm64_LDRH_REG(codeblock_t *block, int dest_reg, int base_reg, int offset_reg);
|
||||
|
||||
void host_arm64_LDRX_REG_LSL3(codeblock_t *block, int dest_reg, int base_reg, int offset_reg);
|
||||
|
||||
void host_arm64_MOV_REG(codeblock_t *block, int dst_reg, int src_m_reg, int shift);
|
||||
void host_arm64_MOV_REG_LSR(codeblock_t *block, int dst_reg, int src_m_reg, int shift);
|
||||
|
||||
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_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_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift);
|
||||
|
||||
void host_arm64_RET(codeblock_t *block, int reg);
|
||||
|
||||
void host_arm64_STP_PREIDX_X(codeblock_t *block, int src_reg1, int src_reg2, int base_reg, int offset);
|
||||
|
||||
void host_arm64_STR_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int offset);
|
||||
void host_arm64_STR_IMM_Q(codeblock_t *block, int dest_reg, int base_reg, int offset);
|
||||
void host_arm64_STR_REG(codeblock_t *block, int src_reg, int base_reg, int offset_reg);
|
||||
|
||||
void host_arm64_STRB_IMM(codeblock_t *block, int dest_reg, int base_reg, int offset);
|
||||
void host_arm64_STRB_REG(codeblock_t *block, int src_reg, int base_reg, int offset_reg);
|
||||
|
||||
void host_arm64_STRH_REG(codeblock_t *block, int src_reg, int base_reg, int offset_reg);
|
||||
|
||||
void host_arm64_SUB_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data);
|
||||
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);
|
||||
|
||||
#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_call(codeblock_t *block, void *dst_addr);
|
||||
void host_arm64_mov_imm(codeblock_t *block, int reg, uint32_t imm_data);
|
||||
|
||||
|
||||
#define in_range7_x(offset) (((offset) >= -0x200) && ((offset) < (0x200)) && !((offset) & 7))
|
||||
#define in_range12_b(offset) (((offset) >= 0) && ((offset) < 0x1000))
|
||||
#define in_range12_w(offset) (((offset) >= 0) && ((offset) < 0x4000) && !((offset) & 3))
|
||||
#define in_range12_q(offset) (((offset) >= 0) && ((offset) < 0x8000) && !((offset) & 7))
|
||||
|
||||
|
||||
void codegen_direct_read_8(codeblock_t *block, int host_reg, void *p);
|
||||
|
||||
int add_literal_q(codeblock_t *block, uint64_t data);
|
||||
|
|
@ -4,459 +4,9 @@
|
|||
#include "codegen.h"
|
||||
#include "codegen_backend.h"
|
||||
#include "codegen_backend_arm64_defs.h"
|
||||
#include "codegen_backend_arm64_ops.h"
|
||||
#include "codegen_ir_defs.h"
|
||||
|
||||
static inline void codegen_addlong(codeblock_t *block, uint32_t val)
|
||||
{
|
||||
*(uint32_t *)&block->data[block_pos] = val;
|
||||
block_pos += 4;
|
||||
if (block_pos >= BLOCK_MAX)
|
||||
{
|
||||
fatal("codegen_addlong over! %i\n", block_pos);
|
||||
CPU_BLOCK_END();
|
||||
}
|
||||
}
|
||||
|
||||
#define Rt(x) (x)
|
||||
#define Rd(x) (x)
|
||||
#define Rn(x) ((x) << 5)
|
||||
#define Rt2(x) ((x) << 10)
|
||||
#define Rm(x) ((x) << 16)
|
||||
|
||||
#define shift_imm6(x) ((x) << 10)
|
||||
|
||||
#define DATA_OFFSET_UP (1 << 23)
|
||||
#define DATA_OFFSET_DOWN (0 << 23)
|
||||
|
||||
#define COND_SHIFT 28
|
||||
#define COND_NE (0x1 << COND_SHIFT)
|
||||
#define COND_AL (0xe << COND_SHIFT)
|
||||
|
||||
#define OPCODE_SHIFT 24
|
||||
#define OPCODE_ADD_IMM (0x11 << OPCODE_SHIFT)
|
||||
#define OPCODE_CBNZ (0xb5 << OPCODE_SHIFT)
|
||||
#define OPCODE_LDR_LITERAL_W (0x18 << OPCODE_SHIFT)
|
||||
#define OPCODE_LDR_LITERAL_X (0x58 << OPCODE_SHIFT)
|
||||
#define OPCODE_SUB_IMM (0x51 << OPCODE_SHIFT)
|
||||
|
||||
#define OPCODE_AND_IMM (0x024 << 23)
|
||||
#define OPCODE_EOR_IMM (0x0a4 << 23)
|
||||
#define OPCODE_MOVK_W (0x0e5 << 23)
|
||||
#define OPCODE_MOVZ_W (0x0a5 << 23)
|
||||
#define OPCODE_ORR_IMM (0x064 << 23)
|
||||
|
||||
#define OPCODE_BFI (0x0cc << 22)
|
||||
#define OPCODE_LDR_IMM_W (0x2e5 << 22)
|
||||
#define OPCODE_LDP_POSTIDX_X (0x2a3 << 22)
|
||||
#define OPCODE_STP_PREIDX_X (0x2a6 << 22)
|
||||
#define OPCODE_STR_IMM_W (0x2e4 << 22)
|
||||
#define OPCODE_STR_IMM_Q (0x3e4 << 22)
|
||||
#define OPCODE_STRB_IMM (0x0e4 << 22)
|
||||
#define OPCODE_UBFX (0x14c << 22)
|
||||
|
||||
#define OPCODE_ADD_LSL (0x058 << 21)
|
||||
#define OPCODE_ADD_LSR (0x05a << 21)
|
||||
#define OPCODE_AND_ASR (0x054 << 21)
|
||||
#define OPCODE_AND_LSL (0x050 << 21)
|
||||
#define OPCODE_AND_ROR (0x056 << 21)
|
||||
#define OPCODE_EOR_LSL (0x250 << 21)
|
||||
#define OPCODE_ORR_LSL (0x150 << 21)
|
||||
#define OPCODE_ORR_LSR (0x152 << 21)
|
||||
#define OPCODE_SUB_LSL (0x258 << 21)
|
||||
#define OPCODE_SUB_LSR (0x25a << 21)
|
||||
|
||||
#define OPCODE_BLR (0xd63f0000)
|
||||
#define OPCODE_NOP (0xd503201f)
|
||||
#define OPCODE_RET (0xd65f0000)
|
||||
|
||||
#define DATPROC_SHIFT(sh) (sh << 10)
|
||||
#define DATPROC_IMM_SHIFT(sh) (sh << 22)
|
||||
#define MOV_WIDE_HW(hw) (hw << 21)
|
||||
|
||||
#define IMM7_X(imm_data) (((imm_data >> 3) & 0x7f) << 15)
|
||||
#define IMM12(imm_data) ((imm_data) << 10)
|
||||
#define IMM16(imm_data) ((imm_data) << 5)
|
||||
|
||||
#define IMMN(immn) ((immn) << 22)
|
||||
#define IMMR(immr) ((immr) << 16)
|
||||
#define IMMS(imms) ((imms) << 10)
|
||||
|
||||
#define OFFSET19(offset) (((offset >> 2) << 5) & 0x00ffffe0)
|
||||
|
||||
#define OFFSET12_B(offset) (offset << 10)
|
||||
#define OFFSET12_W(offset) ((offset >> 2) << 10)
|
||||
#define OFFSET12_Q(offset) ((offset >> 3) << 10)
|
||||
|
||||
static int literal_offset = 0;
|
||||
void codegen_reset_literal_pool(codeblock_t *block)
|
||||
{
|
||||
literal_offset = 0;
|
||||
}
|
||||
|
||||
/*Returns true if offset fits into 19 bits*/
|
||||
static int offset_is_19bit(int offset)
|
||||
{
|
||||
if (offset >= (1 << (18+2)))
|
||||
return 0;
|
||||
if (offset < -(1 << (18+2)))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define in_range7_x(offset) (((offset) >= -0x200) && ((offset) < (0x200)) && !((offset) & 7))
|
||||
#define in_range12_b(offset) (((offset) >= 0) && ((offset) < 0x1000))
|
||||
#define in_range12_w(offset) (((offset) >= 0) && ((offset) < 0x4000) && !((offset) & 3))
|
||||
#define in_range12_q(offset) (((offset) >= 0) && ((offset) < 0x8000) && !((offset) & 7))
|
||||
|
||||
int add_literal(codeblock_t *block, uint32_t data)
|
||||
{
|
||||
if (literal_offset >= 4096)
|
||||
fatal("add_literal - literal pool full\n");
|
||||
|
||||
*(uint32_t *)&block->data[ARM_LITERAL_POOL_OFFSET + literal_offset] = data;
|
||||
|
||||
literal_offset += 4;
|
||||
|
||||
return literal_offset - 4;
|
||||
}
|
||||
|
||||
int add_literal_q(codeblock_t *block, uint64_t data)
|
||||
{
|
||||
if (literal_offset & 4)
|
||||
literal_offset += 4;
|
||||
|
||||
if (literal_offset >= 4096-4)
|
||||
fatal("add_literal - literal pool full\n");
|
||||
|
||||
*(uint64_t *)&block->data[ARM_LITERAL_POOL_OFFSET + literal_offset] = data;
|
||||
|
||||
literal_offset += 8;
|
||||
|
||||
return literal_offset - 8;
|
||||
}
|
||||
|
||||
static inline int imm_is_imm16(uint32_t imm_data)
|
||||
{
|
||||
if (!(imm_data & 0xffff0000) || !(imm_data & 0x0000ffff))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
static inline int imm_is_imm12(uint32_t imm_data)
|
||||
{
|
||||
if (!(imm_data & 0xfffff000) || !(imm_data & 0xff000fff))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void host_arm64_MOV_REG(codeblock_t *block, int dst_reg, int src_m_reg, int shift);
|
||||
void host_arm64_SUB_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data);
|
||||
|
||||
void host_arm64_ADD_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data)
|
||||
{
|
||||
if (!imm_data)
|
||||
host_arm64_MOV_REG(block, dst_reg, src_n_reg, 0);
|
||||
else if ((int32_t)imm_data < 0 && imm_data != 0x80000000)
|
||||
{
|
||||
host_arm64_SUB_IMM(block, dst_reg, src_n_reg, -(int32_t)imm_data);
|
||||
}
|
||||
else if (!(imm_data & 0xff000000))
|
||||
{
|
||||
if (imm_data & 0xfff)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_ADD_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM12(imm_data & 0xfff) | DATPROC_IMM_SHIFT(0));
|
||||
if (imm_data & 0xfff000)
|
||||
codegen_addlong(block, OPCODE_ADD_IMM | Rd(dst_reg) | Rn(dst_reg) | IMM12((imm_data >> 12) & 0xfff) | DATPROC_IMM_SHIFT(1));
|
||||
}
|
||||
else if (imm_data & 0xfff000)
|
||||
codegen_addlong(block, OPCODE_ADD_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM12((imm_data >> 12) & 0xfff) | DATPROC_IMM_SHIFT(1));
|
||||
}
|
||||
else
|
||||
{
|
||||
host_arm64_MOVZ_IMM(block, REG_W16, imm_data & 0xffff);
|
||||
host_arm64_MOVK_IMM(block, REG_W16, imm_data & 0xffff0000);
|
||||
codegen_addlong(block, OPCODE_ADD_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(REG_W16) | DATPROC_SHIFT(0));
|
||||
}
|
||||
}
|
||||
void host_arm64_ADD_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_ADD_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift));
|
||||
}
|
||||
void host_arm64_ADD_REG_LSR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_ADD_LSR | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift));
|
||||
}
|
||||
//12001c00 S=0 R=7
|
||||
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 */
|
||||
{
|
||||
codegen_addlong(block, OPCODE_AND_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(0) | IMMS(0x07));
|
||||
}
|
||||
else if (imm_data == 0xffff) /*Quick hack until proper immediate generation is written */
|
||||
{
|
||||
codegen_addlong(block, OPCODE_AND_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(0) | IMMS(0x0f));
|
||||
}
|
||||
else if (imm_data == 0xffffff00)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_AND_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(24) | IMMS(0x17));
|
||||
}
|
||||
else if (imm_data == 0xffff00ff)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_AND_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(16) | IMMS(0x17));
|
||||
}
|
||||
else if (imm_data == 0x0000ff00)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_AND_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(24) | IMMS(0x07));
|
||||
}
|
||||
else
|
||||
{
|
||||
host_arm64_mov_imm(block, REG_W16, imm_data);
|
||||
codegen_addlong(block, OPCODE_AND_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(REG_W16) | DATPROC_SHIFT(0));
|
||||
}
|
||||
}
|
||||
void host_arm64_AND_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_AND_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift));
|
||||
}
|
||||
void host_arm64_AND_REG_ASR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_AND_ASR | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift));
|
||||
}
|
||||
void host_arm64_AND_REG_ROR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_AND_ROR | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift));
|
||||
}
|
||||
|
||||
void host_arm64_BFI(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_BFI | Rd(dst_reg) | Rn(src_reg) | IMMN(0) | IMMR((32 - lsb) & 31) | IMMS((width-1) & 31));
|
||||
}
|
||||
|
||||
void host_arm64_BLR(codeblock_t *block, int addr_reg)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_BLR | Rn(addr_reg));
|
||||
}
|
||||
|
||||
void host_arm64_CBNZ(codeblock_t *block, int reg, uintptr_t dest)
|
||||
{
|
||||
int offset = dest - (uintptr_t)&block->data[block_pos];
|
||||
if (!offset_is_19bit(offset))
|
||||
fatal("host_arm64_CBNZ - offset out of range %x\n", offset);
|
||||
codegen_addlong(block, OPCODE_CBNZ | OFFSET19(offset) | Rt(reg));
|
||||
}
|
||||
|
||||
void host_arm64_EOR_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data)
|
||||
{
|
||||
if (imm_data == 0xffff) /*Quick hack until proper immediate generation is written */
|
||||
{
|
||||
codegen_addlong(block, OPCODE_EOR_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(0) | IMMS(0x0f));
|
||||
}
|
||||
else
|
||||
{
|
||||
host_arm64_mov_imm(block, REG_W16, imm_data);
|
||||
codegen_addlong(block, OPCODE_EOR_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(REG_W16) | DATPROC_SHIFT(0));
|
||||
}
|
||||
}
|
||||
void host_arm64_EOR_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_EOR_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift));
|
||||
}
|
||||
|
||||
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))
|
||||
fatal("host_arm64_LDP_POSTIDX out of range7 %i\n", offset);
|
||||
codegen_addlong(block, OPCODE_LDP_POSTIDX_X | IMM7_X(offset) | Rn(base_reg) | Rt(src_reg1) | Rt2(src_reg2));
|
||||
}
|
||||
|
||||
void host_arm64_LDR_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int offset)
|
||||
{
|
||||
if (!in_range12_w(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));
|
||||
}
|
||||
|
||||
void host_arm64_LDR_LITERAL_W(codeblock_t *block, int dest_reg, int literal_offset)
|
||||
{
|
||||
int offset = (ARM_LITERAL_POOL_OFFSET + literal_offset) - block_pos;
|
||||
|
||||
if (!offset_is_19bit(offset))
|
||||
fatal("host_arm64_CBNZ - offset out of range %x\n", offset);
|
||||
|
||||
codegen_addlong(block, OPCODE_LDR_LITERAL_W | OFFSET19(offset) | Rt(dest_reg));
|
||||
}
|
||||
void host_arm64_LDR_LITERAL_X(codeblock_t *block, int dest_reg, int literal_offset)
|
||||
{
|
||||
int offset = (ARM_LITERAL_POOL_OFFSET + literal_offset) - block_pos;
|
||||
|
||||
if (!offset_is_19bit(offset))
|
||||
fatal("host_arm64_CBNZ - offset out of range %x\n", offset);
|
||||
|
||||
codegen_addlong(block, OPCODE_LDR_LITERAL_X | OFFSET19(offset) | Rt(dest_reg));
|
||||
}
|
||||
|
||||
void host_arm64_MOV_REG(codeblock_t *block, int dst_reg, int src_m_reg, int shift)
|
||||
{
|
||||
if (dst_reg != src_m_reg)
|
||||
codegen_addlong(block, OPCODE_ORR_LSL | Rd(dst_reg) | Rn(REG_WZR) | Rm(src_m_reg) | DATPROC_SHIFT(shift));
|
||||
}
|
||||
|
||||
void host_arm64_MOV_REG_LSR(codeblock_t *block, int dst_reg, int src_m_reg, int shift)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_ORR_LSR | Rd(dst_reg) | Rn(REG_WZR) | Rm(src_m_reg) | DATPROC_SHIFT(shift));
|
||||
}
|
||||
|
||||
void host_arm64_MOVZ_IMM(codeblock_t *block, int reg, uint32_t imm_data)
|
||||
{
|
||||
int hw;
|
||||
|
||||
if (!imm_is_imm16(imm_data))
|
||||
fatal("MOVZ_IMM - imm not representable %08x\n", imm_data);
|
||||
|
||||
hw = (imm_data & 0xffff0000) ? 1 : 0;
|
||||
if (hw)
|
||||
imm_data >>= 16;
|
||||
|
||||
codegen_addlong(block, OPCODE_MOVZ_W | MOV_WIDE_HW(hw) | IMM16(imm_data) | Rd(reg));
|
||||
}
|
||||
|
||||
void host_arm64_MOVK_IMM(codeblock_t *block, int reg, uint32_t imm_data)
|
||||
{
|
||||
int hw;
|
||||
|
||||
if (!imm_is_imm16(imm_data))
|
||||
fatal("MOVK_IMM - imm not representable %08x\n", imm_data);
|
||||
|
||||
hw = (imm_data & 0xffff0000) ? 1 : 0;
|
||||
if (hw)
|
||||
imm_data >>= 16;
|
||||
|
||||
codegen_addlong(block, OPCODE_MOVK_W | MOV_WIDE_HW(hw) | IMM16(imm_data) | Rd(reg));
|
||||
}
|
||||
|
||||
void host_arm64_NOP(codeblock_t *block)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_NOP);
|
||||
}
|
||||
|
||||
void host_arm64_ORR_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data)
|
||||
{
|
||||
if (imm_data == 0xffff) /*Quick hack until proper immediate generation is written */
|
||||
{
|
||||
codegen_addlong(block, OPCODE_ORR_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(0) | IMMS(0x0f));
|
||||
}
|
||||
else if (imm_data == 0xffff0000)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_ORR_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(16) | IMMS(0x0f));
|
||||
}
|
||||
else if (imm_data == 0xffffff00)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_ORR_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(24) | IMMS(0x17));
|
||||
}
|
||||
else if (imm_data == 0xffff00ff)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_ORR_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMMN(0) | IMMR(16) | IMMS(0x17));
|
||||
}
|
||||
else
|
||||
{
|
||||
host_arm64_mov_imm(block, REG_W16, imm_data);
|
||||
codegen_addlong(block, OPCODE_ORR_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(REG_W16) | DATPROC_SHIFT(0));
|
||||
}
|
||||
}
|
||||
void host_arm64_ORR_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_ORR_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift));
|
||||
}
|
||||
|
||||
void host_arm64_RET(codeblock_t *block, int reg)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_RET | Rn(reg));
|
||||
}
|
||||
|
||||
void host_arm64_STP_PREIDX_X(codeblock_t *block, int src_reg1, int src_reg2, int base_reg, int offset)
|
||||
{
|
||||
if (!in_range7_x(offset))
|
||||
fatal("host_arm64_STP_PREIDX out of range7 %i\n", offset);
|
||||
codegen_addlong(block, OPCODE_STP_PREIDX_X | IMM7_X(offset) | Rn(base_reg) | Rt(src_reg1) | Rt2(src_reg2));
|
||||
}
|
||||
|
||||
void host_arm64_STR_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int offset)
|
||||
{
|
||||
if (!in_range12_w(offset))
|
||||
fatal("host_arm64_STR_IMM_W out of range12 %i\n", offset);
|
||||
codegen_addlong(block, OPCODE_STR_IMM_W | OFFSET12_W(offset) | Rn(base_reg) | Rt(dest_reg));
|
||||
}
|
||||
void host_arm64_STR_IMM_Q(codeblock_t *block, int dest_reg, int base_reg, int offset)
|
||||
{
|
||||
if (!in_range12_q(offset))
|
||||
fatal("host_arm64_STR_IMM_W out of range12 %i\n", offset);
|
||||
codegen_addlong(block, OPCODE_STR_IMM_Q | OFFSET12_Q(offset) | Rn(base_reg) | Rt(dest_reg));
|
||||
}
|
||||
void host_arm64_STRB_IMM(codeblock_t *block, int dest_reg, int base_reg, int offset)
|
||||
{
|
||||
if (!in_range12_b(offset))
|
||||
fatal("host_arm64_STRB_IMM out of range12 %i\n", offset);
|
||||
codegen_addlong(block, OPCODE_STRB_IMM | OFFSET12_B(offset) | Rn(base_reg) | Rt(dest_reg));
|
||||
}
|
||||
|
||||
void host_arm64_SUB_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data)
|
||||
{
|
||||
if (!imm_data)
|
||||
host_arm64_MOV_REG(block, dst_reg, src_n_reg, 0);
|
||||
else if ((int32_t)imm_data < 0 && imm_data != 0x80000000)
|
||||
{
|
||||
host_arm64_ADD_IMM(block, dst_reg, src_n_reg, -(int32_t)imm_data);
|
||||
}
|
||||
else if (!(imm_data & 0xff000000))
|
||||
{
|
||||
if (imm_data & 0xfff)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_SUB_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM12(imm_data & 0xfff) | DATPROC_IMM_SHIFT(0));
|
||||
if (imm_data & 0xfff000)
|
||||
codegen_addlong(block, OPCODE_SUB_IMM | Rd(dst_reg) | Rn(dst_reg) | IMM12((imm_data >> 12) & 0xfff) | DATPROC_IMM_SHIFT(1));
|
||||
}
|
||||
else if (imm_data & 0xfff000)
|
||||
codegen_addlong(block, OPCODE_SUB_IMM | Rd(dst_reg) | Rn(src_n_reg) | IMM12((imm_data >> 12) & 0xfff) | DATPROC_IMM_SHIFT(1));
|
||||
}
|
||||
else
|
||||
{
|
||||
host_arm64_MOVZ_IMM(block, REG_W16, imm_data & 0xffff);
|
||||
host_arm64_MOVK_IMM(block, REG_W16, imm_data & 0xffff0000);
|
||||
codegen_addlong(block, OPCODE_SUB_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(REG_W16) | DATPROC_SHIFT(0));
|
||||
}
|
||||
}
|
||||
void host_arm64_SUB_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_SUB_LSL | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift));
|
||||
}
|
||||
void host_arm64_SUB_REG_LSR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_SUB_LSR | Rd(dst_reg) | Rn(src_n_reg) | Rm(src_m_reg) | DATPROC_SHIFT(shift));
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
void host_arm64_call(codeblock_t *block, void *dst_addr)
|
||||
{
|
||||
int offset = add_literal_q(block, (uintptr_t)dst_addr);
|
||||
host_arm64_LDR_LITERAL_X(block, REG_X16, offset);
|
||||
host_arm64_BLR(block, REG_X16);
|
||||
}
|
||||
|
||||
void host_arm64_mov_imm(codeblock_t *block, int reg, uint32_t imm_data)
|
||||
{
|
||||
if (imm_is_imm16(imm_data))
|
||||
host_arm64_MOVZ_IMM(block, reg, imm_data);
|
||||
else
|
||||
{
|
||||
host_arm64_MOVZ_IMM(block, reg, imm_data & 0xffff);
|
||||
host_arm64_MOVK_IMM(block, reg, imm_data & 0xffff0000);
|
||||
}
|
||||
}
|
||||
|
||||
#define HOST_REG_GET(reg) (IREG_GET_REG(reg) & 0x1f)
|
||||
|
||||
#define REG_IS_L(size) (size == IREG_SIZE_L)
|
||||
|
|
@ -605,7 +155,7 @@ static int codegen_AND_IMM(codeblock_t *block, uop_t *uop)
|
|||
}
|
||||
else
|
||||
fatal("AND_IMM %x %x\n", uop->dest_reg_a_real, uop->src_reg_a_real);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -617,6 +167,22 @@ static int codegen_CALL_INSTRUCTION_FUNC(codeblock_t *block, uop_t *uop)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_CMP_IMM_JZ(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int src_reg = HOST_REG_GET(uop->src_reg_a_real);
|
||||
int src_size = IREG_GET_SIZE(uop->src_reg_a_real);
|
||||
|
||||
if (REG_IS_L(src_size))
|
||||
{
|
||||
host_arm64_CMP_IMM(block, src_reg, uop->imm_data);
|
||||
}
|
||||
else
|
||||
fatal("CMP_IMM_JZ %02x\n", uop->src_reg_a_real);
|
||||
host_arm64_BEQ(block, uop->p);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_LOAD_FUNC_ARG0_IMM(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
host_arm64_mov_imm(block, REG_ARG0, uop->imm_data);
|
||||
|
|
@ -642,6 +208,186 @@ static int codegen_LOAD_FUNC_ARG3_IMM(codeblock_t *block, uop_t *uop)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_MEM_LOAD_ABS(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real);
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real);
|
||||
|
||||
host_arm64_ADD_IMM(block, REG_X0, seg_reg, uop->imm_data);
|
||||
if (REG_IS_B(dest_size) || REG_IS_BH(dest_size))
|
||||
{
|
||||
host_arm64_call(block, codegen_mem_load_byte);
|
||||
}
|
||||
else if (REG_IS_W(dest_size))
|
||||
{
|
||||
host_arm64_call(block, codegen_mem_load_word);
|
||||
}
|
||||
else if (REG_IS_L(dest_size))
|
||||
{
|
||||
host_arm64_call(block, codegen_mem_load_long);
|
||||
}
|
||||
else
|
||||
fatal("MEM_LOAD_ABS - %02x\n", uop->dest_reg_a_real);
|
||||
host_arm64_CBNZ(block, REG_X1, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]);
|
||||
if (REG_IS_B(dest_size))
|
||||
{
|
||||
host_arm64_BFI(block, dest_reg, REG_X0, 0, 8);
|
||||
}
|
||||
else if (REG_IS_BH(dest_size))
|
||||
{
|
||||
host_arm64_BFI(block, dest_reg, REG_X0, 8, 8);
|
||||
}
|
||||
else if (REG_IS_W(dest_size))
|
||||
{
|
||||
host_arm64_BFI(block, dest_reg, REG_X0, 0, 16);
|
||||
}
|
||||
else if (REG_IS_L(dest_size))
|
||||
{
|
||||
host_arm64_MOV_REG(block, dest_reg, REG_X0, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_MEM_LOAD_REG(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real);
|
||||
|
||||
host_arm64_ADD_REG(block, REG_X0, seg_reg, addr_reg, 0);
|
||||
if (REG_IS_B(dest_size) || REG_IS_BH(dest_size))
|
||||
{
|
||||
host_arm64_call(block, codegen_mem_load_byte);
|
||||
}
|
||||
else if (REG_IS_W(dest_size))
|
||||
{
|
||||
host_arm64_call(block, codegen_mem_load_word);
|
||||
}
|
||||
else if (REG_IS_L(dest_size))
|
||||
{
|
||||
host_arm64_call(block, codegen_mem_load_long);
|
||||
}
|
||||
else
|
||||
fatal("MEM_LOAD_ABS - %02x\n", uop->dest_reg_a_real);
|
||||
host_arm64_CBNZ(block, REG_X1, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]);
|
||||
if (REG_IS_B(dest_size))
|
||||
{
|
||||
host_arm64_BFI(block, dest_reg, REG_X0, 0, 8);
|
||||
}
|
||||
else if (REG_IS_BH(dest_size))
|
||||
{
|
||||
host_arm64_BFI(block, dest_reg, REG_X0, 8, 8);
|
||||
}
|
||||
else if (REG_IS_W(dest_size))
|
||||
{
|
||||
host_arm64_BFI(block, dest_reg, REG_X0, 0, 16);
|
||||
}
|
||||
else if (REG_IS_L(dest_size))
|
||||
{
|
||||
host_arm64_MOV_REG(block, dest_reg, REG_X0, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_MEM_STORE_ABS(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int seg_reg = HOST_REG_GET(uop->src_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int src_size = IREG_GET_SIZE(uop->src_reg_b_real);
|
||||
|
||||
host_arm64_ADD_IMM(block, REG_W0, seg_reg, uop->imm_data);
|
||||
if (REG_IS_B(src_size))
|
||||
{
|
||||
host_arm64_AND_IMM(block, REG_W1, src_reg, 0xff);
|
||||
host_arm64_call(block, codegen_mem_store_byte);
|
||||
}
|
||||
else if (REG_IS_BH(src_size))
|
||||
{
|
||||
host_arm64_UBFX(block, REG_W1, src_reg, 8, 8);
|
||||
host_arm64_call(block, codegen_mem_store_byte);
|
||||
}
|
||||
else if (REG_IS_W(src_size))
|
||||
{
|
||||
host_arm64_AND_IMM(block, REG_W1, src_reg, 0xffff);
|
||||
host_arm64_call(block, codegen_mem_store_word);
|
||||
}
|
||||
else if (REG_IS_L(src_size))
|
||||
{
|
||||
host_arm64_MOV_REG(block, REG_W1, src_reg, 0);
|
||||
host_arm64_call(block, codegen_mem_store_long);
|
||||
}
|
||||
else
|
||||
fatal("MEM_STORE_ABS - %02x\n", uop->dest_reg_a_real);
|
||||
host_arm64_CBNZ(block, REG_X1, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_MEM_STORE_REG(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real), src_reg = HOST_REG_GET(uop->src_reg_c_real);
|
||||
int src_size = IREG_GET_SIZE(uop->src_reg_c_real);
|
||||
|
||||
host_arm64_ADD_REG(block, REG_W0, seg_reg, addr_reg, 0);
|
||||
if (REG_IS_B(src_size))
|
||||
{
|
||||
host_arm64_AND_IMM(block, REG_W1, src_reg, 0xff);
|
||||
host_arm64_call(block, codegen_mem_store_byte);
|
||||
}
|
||||
else if (REG_IS_BH(src_size))
|
||||
{
|
||||
host_arm64_UBFX(block, REG_W1, src_reg, 8, 8);
|
||||
host_arm64_call(block, codegen_mem_store_byte);
|
||||
}
|
||||
else if (REG_IS_W(src_size))
|
||||
{
|
||||
host_arm64_AND_IMM(block, REG_W1, src_reg, 0xffff);
|
||||
host_arm64_call(block, codegen_mem_store_word);
|
||||
}
|
||||
else if (REG_IS_L(src_size))
|
||||
{
|
||||
host_arm64_MOV_REG(block, REG_W1, src_reg, 0);
|
||||
host_arm64_call(block, codegen_mem_store_long);
|
||||
}
|
||||
else
|
||||
fatal("MEM_STORE_REG - %02x\n", uop->dest_reg_a_real);
|
||||
host_arm64_CBNZ(block, REG_X1, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_MEM_STORE_IMM_8(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real);
|
||||
|
||||
host_arm64_ADD_REG(block, REG_W0, seg_reg, addr_reg, 0);
|
||||
host_arm64_mov_imm(block, REG_W1, uop->imm_data);
|
||||
host_arm64_call(block, codegen_mem_store_byte);
|
||||
host_arm64_CBNZ(block, REG_X1, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_MEM_STORE_IMM_16(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real);
|
||||
|
||||
host_arm64_ADD_REG(block, REG_W0, seg_reg, addr_reg, 0);
|
||||
host_arm64_mov_imm(block, REG_W1, uop->imm_data);
|
||||
host_arm64_call(block, codegen_mem_store_word);
|
||||
host_arm64_CBNZ(block, REG_X1, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_MEM_STORE_IMM_32(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real);
|
||||
|
||||
host_arm64_ADD_REG(block, REG_W0, seg_reg, addr_reg, 0);
|
||||
host_arm64_mov_imm(block, REG_W1, uop->imm_data);
|
||||
host_arm64_call(block, codegen_mem_store_long);
|
||||
host_arm64_CBNZ(block, REG_X1, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_MOV(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);
|
||||
|
|
@ -799,7 +545,7 @@ static int codegen_OR_IMM(codeblock_t *block, uop_t *uop)
|
|||
}
|
||||
else
|
||||
fatal("OR_IMM %x %x\n", uop->dest_reg_a_real, uop->src_reg_a_real);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -978,7 +724,7 @@ static int codegen_XOR_IMM(codeblock_t *block, uop_t *uop)
|
|||
}
|
||||
else
|
||||
fatal("XOR_IMM %x %x\n", uop->dest_reg_a_real, uop->src_reg_a_real);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -994,6 +740,15 @@ const uOpFn uop_handlers[UOP_MAX] =
|
|||
[UOP_STORE_P_IMM & UOP_MASK] = codegen_STORE_PTR_IMM,
|
||||
[UOP_STORE_P_IMM_8 & UOP_MASK] = codegen_STORE_PTR_IMM_8,
|
||||
|
||||
[UOP_MEM_LOAD_ABS & UOP_MASK] = codegen_MEM_LOAD_ABS,
|
||||
[UOP_MEM_LOAD_REG & UOP_MASK] = codegen_MEM_LOAD_REG,
|
||||
|
||||
[UOP_MEM_STORE_ABS & UOP_MASK] = codegen_MEM_STORE_ABS,
|
||||
[UOP_MEM_STORE_REG & UOP_MASK] = codegen_MEM_STORE_REG,
|
||||
[UOP_MEM_STORE_IMM_8 & UOP_MASK] = codegen_MEM_STORE_IMM_8,
|
||||
[UOP_MEM_STORE_IMM_16 & UOP_MASK] = codegen_MEM_STORE_IMM_16,
|
||||
[UOP_MEM_STORE_IMM_32 & UOP_MASK] = codegen_MEM_STORE_IMM_32,
|
||||
|
||||
[UOP_MOV & UOP_MASK] = codegen_MOV,
|
||||
[UOP_MOV_PTR & UOP_MASK] = codegen_MOV_PTR,
|
||||
[UOP_MOV_IMM & UOP_MASK] = codegen_MOV_IMM,
|
||||
|
|
@ -1009,9 +764,19 @@ const uOpFn uop_handlers[UOP_MAX] =
|
|||
[UOP_SUB & UOP_MASK] = codegen_SUB,
|
||||
[UOP_SUB_IMM & UOP_MASK] = codegen_SUB_IMM,
|
||||
[UOP_XOR & UOP_MASK] = codegen_XOR,
|
||||
[UOP_XOR_IMM & UOP_MASK] = codegen_XOR_IMM
|
||||
[UOP_XOR_IMM & UOP_MASK] = codegen_XOR_IMM,
|
||||
|
||||
[UOP_CMP_IMM_JZ & UOP_MASK] = codegen_CMP_IMM_JZ
|
||||
};
|
||||
|
||||
void codegen_direct_read_8(codeblock_t *block, int host_reg, void *p)
|
||||
{
|
||||
if (in_range12_b((uintptr_t)p - (uintptr_t)&cpu_state))
|
||||
host_arm64_LDRB_IMM_W(block, host_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state);
|
||||
else
|
||||
fatal("codegen_direct_read_8 - not in range\n");
|
||||
}
|
||||
|
||||
void codegen_direct_read_32(codeblock_t *block, int host_reg, void *p)
|
||||
{
|
||||
if (in_range12_w((uintptr_t)p - (uintptr_t)&cpu_state))
|
||||
|
|
|
|||
|
|
@ -45,4 +45,12 @@
|
|||
#define REG_MASK_LOCAL (REG_MASK_R4 | REG_MASK_R5 | REG_MASK_R6 | REG_MASK_R7 | \
|
||||
REG_MASK_R8 | REG_MASK_R9 | REG_MASK_R10 | REG_MASK_R11)
|
||||
|
||||
#define CODEGEN_HOST_REGS 3
|
||||
#define CODEGEN_HOST_REGS 3
|
||||
|
||||
extern void *codegen_mem_load_byte;
|
||||
extern void *codegen_mem_load_word;
|
||||
extern void *codegen_mem_load_long;
|
||||
|
||||
extern void *codegen_mem_store_byte;
|
||||
extern void *codegen_mem_store_word;
|
||||
extern void *codegen_mem_store_long;
|
||||
|
|
|
|||
587
src/codegen_backend_arm_ops.c
Normal file
587
src/codegen_backend_arm_ops.c
Normal file
|
|
@ -0,0 +1,587 @@
|
|||
#ifdef __ARM_EABI__
|
||||
|
||||
#include "ibm.h"
|
||||
#include "codegen.h"
|
||||
#include "codegen_backend.h"
|
||||
#include "codegen_backend_arm_defs.h"
|
||||
#include "codegen_backend_arm_ops.h"
|
||||
|
||||
static inline void codegen_addlong(codeblock_t *block, uint32_t val)
|
||||
{
|
||||
*(uint32_t *)&block->data[block_pos] = val;
|
||||
block_pos += 4;
|
||||
if (block_pos >= BLOCK_MAX)
|
||||
{
|
||||
fatal("codegen_addlong over! %i\n", block_pos);
|
||||
CPU_BLOCK_END();
|
||||
}
|
||||
}
|
||||
|
||||
#define Rm(x) (x)
|
||||
#define Rd(x) ((x) << 12)
|
||||
#define Rn(x) ((x) << 16)
|
||||
|
||||
#define DATA_OFFSET_UP (1 << 23)
|
||||
#define DATA_OFFSET_DOWN (0 << 23)
|
||||
|
||||
#define COND_SHIFT 28
|
||||
#define COND_EQ (0x0 << COND_SHIFT)
|
||||
#define COND_NE (0x1 << COND_SHIFT)
|
||||
#define COND_AL (0xe << COND_SHIFT)
|
||||
|
||||
#define OPCODE_SHIFT 20
|
||||
#define OPCODE_ADD_IMM (0x28 << OPCODE_SHIFT)
|
||||
#define OPCODE_ADD_REG (0x08 << OPCODE_SHIFT)
|
||||
#define OPCODE_AND_IMM (0x20 << OPCODE_SHIFT)
|
||||
#define OPCODE_AND_REG (0x00 << OPCODE_SHIFT)
|
||||
#define OPCODE_B (0xa0 << OPCODE_SHIFT)
|
||||
#define OPCODE_BIC_IMM (0x3c << OPCODE_SHIFT)
|
||||
#define OPCODE_BIC_REG (0x1c << OPCODE_SHIFT)
|
||||
#define OPCODE_BL (0xb0 << OPCODE_SHIFT)
|
||||
#define OPCODE_CMN_IMM (0x37 << OPCODE_SHIFT)
|
||||
#define OPCODE_CMN_REG (0x17 << OPCODE_SHIFT)
|
||||
#define OPCODE_CMP_IMM (0x35 << OPCODE_SHIFT)
|
||||
#define OPCODE_CMP_REG (0x15 << OPCODE_SHIFT)
|
||||
#define OPCODE_EOR_IMM (0x22 << OPCODE_SHIFT)
|
||||
#define OPCODE_EOR_REG (0x02 << OPCODE_SHIFT)
|
||||
#define OPCODE_LDMIA_WB (0x8b << OPCODE_SHIFT)
|
||||
#define OPCODE_LDR_IMM (0x51 << OPCODE_SHIFT)
|
||||
#define OPCODE_LDR_IMM_POST (0x41 << OPCODE_SHIFT)
|
||||
#define OPCODE_LDR_REG (0x79 << OPCODE_SHIFT)
|
||||
#define OPCODE_LDRB_IMM (0x55 << OPCODE_SHIFT)
|
||||
#define OPCODE_LDRB_REG (0x7d << OPCODE_SHIFT)
|
||||
#define OPCODE_MOV_IMM (0x3a << OPCODE_SHIFT)
|
||||
#define OPCODE_MOVT_IMM (0x34 << OPCODE_SHIFT)
|
||||
#define OPCODE_MOVW_IMM (0x30 << OPCODE_SHIFT)
|
||||
#define OPCODE_MOV_REG (0x1a << OPCODE_SHIFT)
|
||||
#define OPCODE_MVN_REG (0x1e << OPCODE_SHIFT)
|
||||
#define OPCODE_ORR_IMM (0x38 << OPCODE_SHIFT)
|
||||
#define OPCODE_ORR_REG (0x18 << OPCODE_SHIFT)
|
||||
#define OPCODE_RSB_REG (0x06 << OPCODE_SHIFT)
|
||||
#define OPCODE_STMDB_WB (0x92 << OPCODE_SHIFT)
|
||||
#define OPCODE_STR_IMM (0x50 << OPCODE_SHIFT)
|
||||
#define OPCODE_STR_IMM_WB (0x52 << OPCODE_SHIFT)
|
||||
#define OPCODE_STR_REG (0x78 << OPCODE_SHIFT)
|
||||
#define OPCODE_STRB_IMM (0x54 << OPCODE_SHIFT)
|
||||
#define OPCODE_STRB_REG (0x7c << OPCODE_SHIFT)
|
||||
#define OPCODE_SUB_IMM (0x24 << OPCODE_SHIFT)
|
||||
#define OPCODE_SUB_REG (0x04 << OPCODE_SHIFT)
|
||||
#define OPCODE_TST_IMM (0x31 << OPCODE_SHIFT)
|
||||
#define OPCODE_TST_REG (0x11 << OPCODE_SHIFT)
|
||||
|
||||
#define OPCODE_BFI 0xe7c00010
|
||||
#define OPCODE_BLX 0xe12fff30
|
||||
#define OPCODE_LDRH_REG 0xe19000b0
|
||||
#define OPCODE_STRH_REG 0xe18000b0
|
||||
#define OPCODE_UADD8 0xe6500f90
|
||||
#define OPCODE_UADD16 0xe6500f10
|
||||
#define OPCODE_USUB8 0xe6500ff0
|
||||
#define OPCODE_USUB16 0xe6500f70
|
||||
#define OPCODE_UXTB 0xe6ef0070
|
||||
#define OPCODE_UXTH 0xe6ff0070
|
||||
|
||||
#define B_OFFSET(x) (((x) >> 2) & 0xffffff)
|
||||
|
||||
#define SHIFT_TYPE_SHIFT 5
|
||||
#define SHIFT_TYPE_LSL (0 << SHIFT_TYPE_SHIFT)
|
||||
#define SHIFT_TYPE_LSR (1 << SHIFT_TYPE_SHIFT)
|
||||
#define SHIFT_TYPE_ASR (2 << SHIFT_TYPE_SHIFT)
|
||||
#define SHIFT_TYPE_ROR (3 << SHIFT_TYPE_SHIFT)
|
||||
|
||||
#define SHIFT_TYPE_IMM (0 << 4)
|
||||
#define SHIFT_TYPE_REG (1 << 4)
|
||||
|
||||
#define SHIFT_IMM_SHIFT 7
|
||||
#define SHIFT_LSL_IMM(x) (SHIFT_TYPE_LSL | SHIFT_TYPE_IMM | ((x) << SHIFT_IMM_SHIFT))
|
||||
#define SHIFT_LSR_IMM(x) (SHIFT_TYPE_LSR | SHIFT_TYPE_IMM | ((x) << SHIFT_IMM_SHIFT))
|
||||
|
||||
#define BFI_lsb(lsb) ((lsb) << 7)
|
||||
#define BFI_msb(msb) ((msb) << 16)
|
||||
|
||||
#define UXTB_ROTATE(rotate) (((rotate) >> 3) << 10)
|
||||
|
||||
#define MOVT_IMM(imm) (((imm) & 0xfff) | (((imm) & 0xf000) << 4))
|
||||
#define MOVW_IMM(imm) (((imm) & 0xfff) | (((imm) & 0xf000) << 4))
|
||||
|
||||
static int literal_offset = 0;
|
||||
void codegen_reset_literal_pool(codeblock_t *block)
|
||||
{
|
||||
literal_offset = 0;
|
||||
}
|
||||
|
||||
int add_literal(codeblock_t *block, uint32_t data)
|
||||
{
|
||||
int c;
|
||||
|
||||
if (literal_offset >= 4096)
|
||||
fatal("add_literal - literal pool full\n");
|
||||
|
||||
/*Search for pre-existing value*/
|
||||
for (c = 0; c < literal_offset; c += 4)
|
||||
{
|
||||
if (*(uint32_t *)&block->data[ARM_LITERAL_POOL_OFFSET + c] == data)
|
||||
return c;
|
||||
}
|
||||
|
||||
*(uint32_t *)&block->data[ARM_LITERAL_POOL_OFFSET + literal_offset] = data;
|
||||
|
||||
literal_offset += 4;
|
||||
|
||||
return literal_offset - 4;
|
||||
}
|
||||
|
||||
|
||||
static inline uint32_t arm_data_offset(int offset)
|
||||
{
|
||||
if (offset < -0xffc || offset > 0xffc)
|
||||
fatal("arm_data_offset out of range - %i\n", offset);
|
||||
|
||||
if (offset >= 0)
|
||||
return offset | DATA_OFFSET_UP;
|
||||
return (-offset) | DATA_OFFSET_DOWN;
|
||||
}
|
||||
|
||||
static inline int get_arm_imm(uint32_t imm_data, uint32_t *arm_imm)
|
||||
{
|
||||
int shift = 0;
|
||||
//pclog("get_arm_imm - imm_data=%08x\n", imm_data);
|
||||
if (!(imm_data & 0xffff))
|
||||
{
|
||||
shift += 16;
|
||||
imm_data >>= 16;
|
||||
}
|
||||
if (!(imm_data & 0xff))
|
||||
{
|
||||
shift += 8;
|
||||
imm_data >>= 8;
|
||||
}
|
||||
if (!(imm_data & 0xf))
|
||||
{
|
||||
shift += 4;
|
||||
imm_data >>= 4;
|
||||
}
|
||||
if (!(imm_data & 0x3))
|
||||
{
|
||||
shift += 2;
|
||||
imm_data >>= 2;
|
||||
}
|
||||
if (imm_data > 0xff) /*Note - should handle rotation round the word*/
|
||||
return 0;
|
||||
//pclog(" imm_data=%02x shift=%i\n", imm_data, shift);
|
||||
*arm_imm = imm_data | ((((32 - shift) >> 1) & 15) << 8);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline int in_range(void *addr, void *base)
|
||||
{
|
||||
int diff = (uintptr_t)addr - (uintptr_t)base;
|
||||
|
||||
if (diff < -4095 || diff > 4095)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void host_arm_ADD_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift);
|
||||
void host_arm_AND_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift);
|
||||
void host_arm_EOR_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift);
|
||||
void host_arm_ORR_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift);
|
||||
void host_arm_SUB_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift);
|
||||
|
||||
void host_arm_ADD_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm)
|
||||
{
|
||||
uint32_t arm_imm;
|
||||
|
||||
if ((int32_t)imm < 0 && imm != 0x80000000)
|
||||
{
|
||||
host_arm_SUB_IMM(block, dst_reg, src_reg, -(int32_t)imm);
|
||||
}
|
||||
else if (get_arm_imm(imm, &arm_imm))
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_ADD_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm);
|
||||
}
|
||||
else
|
||||
{
|
||||
int offset = add_literal(block, imm);
|
||||
host_arm_LDR_IMM(block, REG_TEMP, REG_LITERAL, offset);
|
||||
host_arm_ADD_REG_LSL(block, dst_reg, src_reg, REG_TEMP, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void host_arm_ADD_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift)
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_ADD_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift));
|
||||
}
|
||||
|
||||
void host_arm_AND_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm)
|
||||
{
|
||||
uint32_t arm_imm;
|
||||
|
||||
if (get_arm_imm(imm, &arm_imm))
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_AND_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm);
|
||||
}
|
||||
else if (get_arm_imm(~imm, &arm_imm))
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_BIC_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm);
|
||||
}
|
||||
else
|
||||
{
|
||||
int offset = add_literal(block, imm);
|
||||
host_arm_LDR_IMM(block, REG_TEMP, REG_LITERAL, offset);
|
||||
host_arm_AND_REG_LSL(block, dst_reg, src_reg, REG_TEMP, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void host_arm_AND_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift)
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_AND_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift));
|
||||
}
|
||||
|
||||
void host_arm_BFI(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_BFI | Rd(dst_reg) | Rm(src_reg) | BFI_lsb(lsb) | BFI_msb((lsb + width) - 1));
|
||||
}
|
||||
|
||||
void host_arm_BIC_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift)
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_BIC_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift));
|
||||
}
|
||||
void host_arm_BIC_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift)
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_BIC_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSR_IMM(shift));
|
||||
}
|
||||
|
||||
void host_arm_BL(codeblock_t *block, uintptr_t dest_addr)
|
||||
{
|
||||
uint32_t offset = (dest_addr - (uintptr_t)&block->data[block_pos]) - 8;
|
||||
|
||||
if ((offset & 0xfe000000) && (offset & 0xfe000000) != 0xfe000000)
|
||||
{
|
||||
host_arm_MOV_IMM(block, REG_R3, dest_addr);
|
||||
host_arm_BLX(block, REG_R3);
|
||||
}
|
||||
else
|
||||
codegen_addlong(block, COND_AL | OPCODE_BL | B_OFFSET(offset));
|
||||
}
|
||||
void host_arm_BLX(codeblock_t *block, int addr_reg)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_BLX | Rm(addr_reg));
|
||||
}
|
||||
|
||||
uint32_t *host_arm_BEQ_(codeblock_t *block)
|
||||
{
|
||||
codegen_addlong(block, COND_EQ | OPCODE_B);
|
||||
|
||||
return (uint32_t *)&block->data[block_pos - 4];
|
||||
}
|
||||
uint32_t *host_arm_BNE_(codeblock_t *block)
|
||||
{
|
||||
codegen_addlong(block, COND_NE | OPCODE_B);
|
||||
|
||||
return (uint32_t *)&block->data[block_pos - 4];
|
||||
}
|
||||
|
||||
void host_arm_BEQ(codeblock_t *block, uintptr_t dest_addr)
|
||||
{
|
||||
uint32_t offset = (dest_addr - (uintptr_t)&block->data[block_pos]) - 8;
|
||||
|
||||
if ((offset & 0xfe000000) && (offset & 0xfe000000) != 0xfe000000)
|
||||
fatal("host_arm_BEQ - out of range %08x %i\n", offset, offset);
|
||||
|
||||
codegen_addlong(block, COND_EQ | OPCODE_B | B_OFFSET(offset));
|
||||
}
|
||||
void host_arm_BNE(codeblock_t *block, uintptr_t dest_addr)
|
||||
{
|
||||
uint32_t offset = (dest_addr - (uintptr_t)&block->data[block_pos]) - 8;
|
||||
|
||||
if ((offset & 0xfe000000) && (offset & 0xfe000000) != 0xfe000000)
|
||||
fatal("host_arm_BNE - out of range %08x %i\n", offset, offset);
|
||||
|
||||
codegen_addlong(block, COND_NE | OPCODE_B | B_OFFSET(offset));
|
||||
}
|
||||
|
||||
void host_arm_CMN_IMM(codeblock_t *block, int src_reg, uint32_t imm)
|
||||
{
|
||||
uint32_t arm_imm;
|
||||
|
||||
if ((int32_t)imm < 0 && imm != 0x80000000)
|
||||
{
|
||||
host_arm_CMP_IMM(block, src_reg, -(int32_t)imm);
|
||||
}
|
||||
else if (get_arm_imm(imm, &arm_imm))
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_CMN_IMM | Rn(src_reg) | arm_imm);
|
||||
}
|
||||
else
|
||||
{
|
||||
int offset = add_literal(block, imm);
|
||||
host_arm_LDR_IMM(block, REG_TEMP, REG_LITERAL, offset);
|
||||
host_arm_CMN_REG_LSL(block, src_reg, REG_TEMP, 0);
|
||||
}
|
||||
}
|
||||
void host_arm_CMN_REG_LSL(codeblock_t *block, int src_reg_n, int src_reg_m, int shift)
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_CMN_REG | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift));
|
||||
}
|
||||
|
||||
void host_arm_CMP_IMM(codeblock_t *block, int src_reg, uint32_t imm)
|
||||
{
|
||||
uint32_t arm_imm;
|
||||
|
||||
if ((int32_t)imm < 0 && imm != 0x80000000)
|
||||
{
|
||||
host_arm_CMN_IMM(block, src_reg, -(int32_t)imm);
|
||||
}
|
||||
else if (get_arm_imm(imm, &arm_imm))
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_CMP_IMM | Rn(src_reg) | arm_imm);
|
||||
}
|
||||
else
|
||||
{
|
||||
int offset = add_literal(block, imm);
|
||||
host_arm_LDR_IMM(block, REG_TEMP, REG_LITERAL, offset);
|
||||
host_arm_CMP_REG_LSL(block, src_reg, REG_TEMP, 0);
|
||||
}
|
||||
}
|
||||
void host_arm_CMP_REG_LSL(codeblock_t *block, int src_reg_n, int src_reg_m, int shift)
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_CMP_REG | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift));
|
||||
}
|
||||
|
||||
void host_arm_EOR_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm)
|
||||
{
|
||||
uint32_t arm_imm;
|
||||
|
||||
if (get_arm_imm(imm, &arm_imm))
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_EOR_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm);
|
||||
}
|
||||
else
|
||||
{
|
||||
int offset = add_literal(block, imm);
|
||||
host_arm_LDR_IMM(block, REG_TEMP, REG_LITERAL, offset);
|
||||
host_arm_EOR_REG_LSL(block, dst_reg, src_reg, REG_TEMP, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void host_arm_EOR_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift)
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_EOR_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift));
|
||||
}
|
||||
|
||||
void host_arm_LDMIA_WB(codeblock_t *block, int addr_reg, uint32_t reg_mask)
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_LDMIA_WB | Rn(addr_reg) | reg_mask);
|
||||
}
|
||||
|
||||
void host_arm_LDR_IMM(codeblock_t *block, int dst_reg, int addr_reg, int offset)
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_LDR_IMM | Rn(addr_reg) | Rd(dst_reg) | arm_data_offset(offset));
|
||||
}
|
||||
void host_arm_LDR_IMM_POST(codeblock_t *block, int dst_reg, int addr_reg, int offset)
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_LDR_IMM_POST | Rn(addr_reg) | Rd(dst_reg) | arm_data_offset(offset));
|
||||
}
|
||||
void host_arm_LDR_REG_LSL(codeblock_t *block, int dst_reg, int addr_reg, int offset_reg, int shift)
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_LDR_REG | Rn(addr_reg) | Rd(dst_reg) | Rm(offset_reg) | SHIFT_LSL_IMM(shift));
|
||||
}
|
||||
|
||||
void host_arm_LDRB_ABS(codeblock_t *block, int dst_reg, void *p)
|
||||
{
|
||||
if (in_range(p, &cpu_state))
|
||||
host_arm_LDRB_IMM(block, dst_reg, REG_CPUSTATE, (uintptr_t)p - (uintptr_t)&cpu_state);
|
||||
else
|
||||
fatal("LDRB_ABS - not in range\n");
|
||||
}
|
||||
void host_arm_LDRB_IMM(codeblock_t *block, int dst_reg, int addr_reg, int offset)
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_LDRB_IMM | Rn(addr_reg) | Rd(dst_reg) | arm_data_offset(offset));
|
||||
}
|
||||
void host_arm_LDRB_REG_LSL(codeblock_t *block, int dst_reg, int addr_reg, int offset_reg, int shift)
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_LDRB_REG | Rn(addr_reg) | Rd(dst_reg) | Rm(offset_reg) | SHIFT_LSL_IMM(shift));
|
||||
}
|
||||
|
||||
void host_arm_LDRH_REG(codeblock_t *block, int dst_reg, int addr_reg, int offset_reg)
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_LDRH_REG | Rn(addr_reg) | Rd(dst_reg) | Rm(offset_reg));
|
||||
}
|
||||
|
||||
void host_arm_MOV_IMM(codeblock_t *block, int dst_reg, uint32_t imm)
|
||||
{
|
||||
uint32_t arm_imm;
|
||||
|
||||
if (get_arm_imm(imm, &arm_imm))
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_MOV_IMM | Rd(dst_reg) | arm_imm);
|
||||
}
|
||||
else
|
||||
{
|
||||
host_arm_MOVW_IMM(block, dst_reg, imm & 0xffff);
|
||||
if (imm >> 16)
|
||||
host_arm_MOVT_IMM(block, dst_reg, imm >> 16);
|
||||
}
|
||||
}
|
||||
|
||||
void host_arm_MOV_REG_LSL(codeblock_t *block, int dst_reg, int src_reg, int shift)
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_MOV_REG | Rd(dst_reg) | Rm(src_reg) | SHIFT_LSL_IMM(shift));
|
||||
}
|
||||
void host_arm_MOV_REG_LSR(codeblock_t *block, int dst_reg, int src_reg, int shift)
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_MOV_REG | Rd(dst_reg) | Rm(src_reg) | SHIFT_LSR_IMM(shift));
|
||||
}
|
||||
|
||||
void host_arm_MOVT_IMM(codeblock_t *block, int dst_reg, uint16_t imm)
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_MOVT_IMM | Rd(dst_reg) | MOVT_IMM(imm));
|
||||
}
|
||||
void host_arm_MOVW_IMM(codeblock_t *block, int dst_reg, uint16_t imm)
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_MOVW_IMM | Rd(dst_reg) | MOVW_IMM(imm));
|
||||
}
|
||||
|
||||
void host_arm_MVN_REG_LSL(codeblock_t *block, int dst_reg, int src_reg, int shift)
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_MVN_REG | Rd(dst_reg) | Rm(src_reg) | SHIFT_LSL_IMM(shift));
|
||||
}
|
||||
|
||||
void host_arm_ORR_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm)
|
||||
{
|
||||
uint32_t arm_imm;
|
||||
|
||||
if (get_arm_imm(imm, &arm_imm))
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_ORR_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm);
|
||||
}
|
||||
else
|
||||
{
|
||||
int offset = add_literal(block, imm);
|
||||
host_arm_LDR_IMM(block, REG_TEMP, REG_LITERAL, offset);
|
||||
host_arm_ORR_REG_LSL(block, dst_reg, src_reg, REG_TEMP, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void host_arm_ORR_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift)
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_ORR_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift));
|
||||
}
|
||||
|
||||
void host_arm_RSB_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift)
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_RSB_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSR_IMM(shift));
|
||||
}
|
||||
|
||||
void host_arm_STMDB_WB(codeblock_t *block, int addr_reg, uint32_t reg_mask)
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_STMDB_WB | Rn(addr_reg) | reg_mask);
|
||||
}
|
||||
|
||||
void host_arm_STR_IMM(codeblock_t *block, int src_reg, int addr_reg, int offset)
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_STR_IMM | Rn(addr_reg) | Rd(src_reg) | arm_data_offset(offset));
|
||||
}
|
||||
void host_arm_STR_IMM_WB(codeblock_t *block, int src_reg, int addr_reg, int offset)
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_STR_IMM_WB | Rn(addr_reg) | Rd(src_reg) | arm_data_offset(offset));
|
||||
}
|
||||
void host_arm_STR_REG_LSL(codeblock_t *block, int src_reg, int addr_reg, int offset_reg, int shift)
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_STR_REG | Rn(addr_reg) | Rd(src_reg) | Rm(offset_reg) | SHIFT_LSL_IMM(shift));
|
||||
}
|
||||
|
||||
void host_arm_STRB_IMM(codeblock_t *block, int src_reg, int addr_reg, int offset)
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_STRB_IMM | Rn(addr_reg) | Rd(src_reg) | arm_data_offset(offset));
|
||||
}
|
||||
void host_arm_STRB_REG_LSL(codeblock_t *block, int src_reg, int addr_reg, int offset_reg, int shift)
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_STRB_REG | Rn(addr_reg) | Rd(src_reg) | Rm(offset_reg) | SHIFT_LSL_IMM(shift));
|
||||
}
|
||||
|
||||
void host_arm_STRH_REG(codeblock_t *block, int src_reg, int addr_reg, int offset_reg)
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_STRH_REG | Rn(addr_reg) | Rd(src_reg) | Rm(offset_reg));
|
||||
}
|
||||
|
||||
void host_arm_SUB_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm)
|
||||
{
|
||||
uint32_t arm_imm;
|
||||
|
||||
if ((int32_t)imm < 0 && imm != 0x80000000)
|
||||
{
|
||||
host_arm_ADD_IMM(block, dst_reg, src_reg, -(int32_t)imm);
|
||||
}
|
||||
else if (get_arm_imm(imm, &arm_imm))
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_SUB_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm);
|
||||
}
|
||||
else
|
||||
{
|
||||
int offset = add_literal(block, imm);
|
||||
host_arm_LDR_IMM(block, REG_TEMP, REG_LITERAL, offset);
|
||||
host_arm_SUB_REG_LSL(block, dst_reg, src_reg, REG_TEMP, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void host_arm_SUB_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift)
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_SUB_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift));
|
||||
}
|
||||
void host_arm_SUB_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift)
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_SUB_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSR_IMM(shift));
|
||||
}
|
||||
|
||||
void host_arm_TST_IMM(codeblock_t *block, int src_reg, uint32_t imm)
|
||||
{
|
||||
uint32_t arm_imm;
|
||||
|
||||
if (get_arm_imm(imm, &arm_imm))
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_TST_IMM | Rn(src_reg) | arm_imm);
|
||||
}
|
||||
else
|
||||
{
|
||||
int offset = add_literal(block, imm);
|
||||
host_arm_LDR_IMM(block, REG_TEMP, REG_LITERAL, offset);
|
||||
host_arm_TST_REG(block, src_reg, REG_TEMP);
|
||||
}
|
||||
}
|
||||
void host_arm_TST_REG(codeblock_t *block, int src_reg1, int src_reg2)
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_TST_REG | Rn(src_reg1) | Rm(src_reg2));
|
||||
}
|
||||
|
||||
void host_arm_UADD8(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_UADD8 | Rd(dst_reg) | Rn(src_reg_a) | Rm(src_reg_b));
|
||||
}
|
||||
|
||||
void host_arm_UADD16(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_UADD16 | Rd(dst_reg) | Rn(src_reg_a) | Rm(src_reg_b));
|
||||
}
|
||||
|
||||
void host_arm_USUB8(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_USUB8 | Rd(dst_reg) | Rn(src_reg_a) | Rm(src_reg_b));
|
||||
}
|
||||
|
||||
void host_arm_USUB16(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_USUB16 | Rd(dst_reg) | Rn(src_reg_a) | Rm(src_reg_b));
|
||||
}
|
||||
|
||||
void host_arm_UXTB(codeblock_t *block, int dst_reg, int src_reg, int rotate)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_UXTB | Rd(dst_reg) | Rm(src_reg) | UXTB_ROTATE(rotate));
|
||||
}
|
||||
|
||||
void host_arm_UXTH(codeblock_t *block, int dst_reg, int src_reg, int rotate)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_UXTH | Rd(dst_reg) | Rm(src_reg) | UXTB_ROTATE(rotate));
|
||||
}
|
||||
|
||||
#endif
|
||||
84
src/codegen_backend_arm_ops.h
Normal file
84
src/codegen_backend_arm_ops.h
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
void host_arm_ADD_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm);
|
||||
#define host_arm_ADD_REG(block, dst_reg, src_reg_n, src_reg_m) host_arm_ADD_REG_LSL(block, dst_reg, src_reg_n, src_reg_m, 0)
|
||||
void host_arm_ADD_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift);
|
||||
|
||||
void host_arm_AND_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm);
|
||||
void host_arm_AND_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift);
|
||||
|
||||
void host_arm_BFI(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width);
|
||||
|
||||
void host_arm_BIC_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift);
|
||||
void host_arm_BIC_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift);
|
||||
|
||||
void host_arm_BL(codeblock_t *block, uintptr_t dest_addr);
|
||||
void host_arm_BLX(codeblock_t *block, int addr_reg);
|
||||
uint32_t *host_arm_BEQ_(codeblock_t *block);
|
||||
uint32_t *host_arm_BNE_(codeblock_t *block);
|
||||
void host_arm_BEQ(codeblock_t *block, uintptr_t dest_addr);
|
||||
void host_arm_BNE(codeblock_t *block, uintptr_t dest_addr);
|
||||
|
||||
void host_arm_CMN_IMM(codeblock_t *block, int src_reg, uint32_t imm);
|
||||
void host_arm_CMN_REG_LSL(codeblock_t *block, int src_reg_n, int src_reg_m, int shift);
|
||||
|
||||
void host_arm_CMP_IMM(codeblock_t *block, int src_reg, uint32_t imm);
|
||||
void host_arm_CMP_REG_LSL(codeblock_t *block, int src_reg_n, int src_reg_m, int shift);
|
||||
|
||||
void host_arm_EOR_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm);
|
||||
void host_arm_EOR_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift);
|
||||
|
||||
void host_arm_LDMIA_WB(codeblock_t *block, int addr_reg, uint32_t reg_mask);
|
||||
|
||||
void host_arm_LDR_IMM(codeblock_t *block, int dst_reg, int addr_reg, int offset);
|
||||
void host_arm_LDR_IMM_POST(codeblock_t *block, int dst_reg, int addr_reg, int offset);
|
||||
#define host_arm_LDR_REG(block, dst_reg, addr_reg, offset_reg) host_arm_LDR_REG_LSL(block, dst_reg, addr_reg, offset_reg, 0)
|
||||
void host_arm_LDR_REG_LSL(codeblock_t *block, int dst_reg, int addr_reg, int offset_reg, int shift);
|
||||
|
||||
void host_arm_LDRB_ABS(codeblock_t *block, int dst, void *p);
|
||||
void host_arm_LDRB_IMM(codeblock_t *block, int dst_reg, int addr_reg, int offset);
|
||||
#define host_arm_LDRB_REG(block, dst_reg, addr_reg, offset_reg) host_arm_LDRB_REG_LSL(block, dst_reg, addr_reg, offset_reg, 0)
|
||||
void host_arm_LDRB_REG_LSL(codeblock_t *block, int dst_reg, int addr_reg, int offset_reg, int shift);
|
||||
|
||||
void host_arm_LDRH_REG(codeblock_t *block, int dst_reg, int addr_reg, int offset_reg);
|
||||
|
||||
void host_arm_MOV_IMM(codeblock_t *block, int dst_reg, uint32_t imm);
|
||||
#define host_arm_MOV_REG(block, dst_reg, src_reg) host_arm_MOV_REG_LSL(block, dst_reg, src_reg, 0)
|
||||
void host_arm_MOV_REG_LSL(codeblock_t *block, int dst_reg, int src_reg, int shift);
|
||||
void host_arm_MOV_REG_LSR(codeblock_t *block, int dst_reg, int src_reg, int shift);
|
||||
void host_arm_MOVT_IMM(codeblock_t *block, int dst_reg, uint16_t imm);
|
||||
void host_arm_MOVW_IMM(codeblock_t *block, int dst_reg, uint16_t imm);
|
||||
|
||||
void host_arm_MVN_REG_LSL(codeblock_t *block, int dst_reg, int src_reg, int shift);
|
||||
|
||||
void host_arm_ORR_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm);
|
||||
void host_arm_ORR_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift);
|
||||
|
||||
void host_arm_RSB_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift);
|
||||
|
||||
void host_arm_STMDB_WB(codeblock_t *block, int addr_reg, uint32_t reg_mask);
|
||||
|
||||
void host_arm_STR_IMM(codeblock_t *block, int src_reg, int addr_reg, int offset);
|
||||
void host_arm_STR_IMM_WB(codeblock_t *block, int src_reg, int addr_reg, int offset);
|
||||
#define host_arm_STR_REG(block, src_reg, addr_reg, offset_reg) host_arm_STR_REG_LSL(block, src_reg, addr_reg, offset_reg, 0)
|
||||
void host_arm_STR_REG_LSL(codeblock_t *block, int src_reg, int addr_reg, int offset_reg, int shift);
|
||||
|
||||
void host_arm_STRB_IMM(codeblock_t *block, int src_reg, int addr_reg, int offset);
|
||||
#define host_arm_STRB_REG(block, src_reg, addr_reg, offset_reg) host_arm_STRB_REG_LSL(block, src_reg, addr_reg, offset_reg, 0)
|
||||
void host_arm_STRB_REG_LSL(codeblock_t *block, int src_reg, int addr_reg, int offset_reg, int shift);
|
||||
|
||||
void host_arm_STRH_REG(codeblock_t *block, int src_reg, int addr_reg, int offset_reg);
|
||||
|
||||
void host_arm_SUB_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm);
|
||||
void host_arm_SUB_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift);
|
||||
void host_arm_SUB_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift);
|
||||
|
||||
void host_arm_TST_IMM(codeblock_t *block, int src_reg1, uint32_t imm);
|
||||
void host_arm_TST_REG(codeblock_t *block, int src_reg1, int src_reg2);
|
||||
|
||||
void host_arm_UADD8(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
|
||||
void host_arm_UADD16(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
|
||||
|
||||
void host_arm_USUB8(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
|
||||
void host_arm_USUB16(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
|
||||
|
||||
void host_arm_UXTB(codeblock_t *block, int dst_reg, int src_reg, int rotate);
|
||||
void host_arm_UXTH(codeblock_t *block, int dst_reg, int src_reg, int rotate);
|
||||
|
|
@ -4,125 +4,9 @@
|
|||
#include "codegen.h"
|
||||
#include "codegen_backend.h"
|
||||
#include "codegen_backend_arm_defs.h"
|
||||
#include "codegen_backend_arm_ops.h"
|
||||
#include "codegen_ir_defs.h"
|
||||
|
||||
static inline void codegen_addlong(codeblock_t *block, uint32_t val)
|
||||
{
|
||||
*(uint32_t *)&block->data[block_pos] = val;
|
||||
block_pos += 4;
|
||||
if (block_pos >= BLOCK_MAX)
|
||||
{
|
||||
fatal("codegen_addlong over! %i\n", block_pos);
|
||||
CPU_BLOCK_END();
|
||||
}
|
||||
}
|
||||
|
||||
#define Rm(x) (x)
|
||||
#define Rd(x) ((x) << 12)
|
||||
#define Rn(x) ((x) << 16)
|
||||
|
||||
#define DATA_OFFSET_UP (1 << 23)
|
||||
#define DATA_OFFSET_DOWN (0 << 23)
|
||||
|
||||
#define COND_SHIFT 28
|
||||
#define COND_NE (0x1 << COND_SHIFT)
|
||||
#define COND_AL (0xe << COND_SHIFT)
|
||||
|
||||
#define OPCODE_SHIFT 20
|
||||
#define OPCODE_ADD_IMM (0x28 << OPCODE_SHIFT)
|
||||
#define OPCODE_ADD_REG (0x08 << OPCODE_SHIFT)
|
||||
#define OPCODE_AND_IMM (0x20 << OPCODE_SHIFT)
|
||||
#define OPCODE_AND_REG (0x00 << OPCODE_SHIFT)
|
||||
#define OPCODE_B (0xa0 << OPCODE_SHIFT)
|
||||
#define OPCODE_BIC_IMM (0x3c << OPCODE_SHIFT)
|
||||
#define OPCODE_BIC_REG (0x1c << OPCODE_SHIFT)
|
||||
#define OPCODE_EOR_IMM (0x22 << OPCODE_SHIFT)
|
||||
#define OPCODE_EOR_REG (0x02 << OPCODE_SHIFT)
|
||||
#define OPCODE_LDMIA_WB (0x8b << OPCODE_SHIFT)
|
||||
#define OPCODE_LDR_IMM (0x51 << OPCODE_SHIFT)
|
||||
#define OPCODE_MOV_IMM (0x3a << OPCODE_SHIFT)
|
||||
#define OPCODE_MOVW_IMM (0x30 << OPCODE_SHIFT)
|
||||
#define OPCODE_MOV_REG (0x1a << OPCODE_SHIFT)
|
||||
#define OPCODE_MVN_REG (0x1e << OPCODE_SHIFT)
|
||||
#define OPCODE_ORR_IMM (0x38 << OPCODE_SHIFT)
|
||||
#define OPCODE_ORR_REG (0x18 << OPCODE_SHIFT)
|
||||
#define OPCODE_RSB_REG (0x06 << OPCODE_SHIFT)
|
||||
#define OPCODE_STMDB_WB (0x92 << OPCODE_SHIFT)
|
||||
#define OPCODE_STR_IMM (0x50 << OPCODE_SHIFT)
|
||||
#define OPCODE_STRB_IMM (0x54 << OPCODE_SHIFT)
|
||||
#define OPCODE_SUB_IMM (0x24 << OPCODE_SHIFT)
|
||||
#define OPCODE_SUB_REG (0x04 << OPCODE_SHIFT)
|
||||
#define OPCODE_TST_REG (0x11 << OPCODE_SHIFT)
|
||||
|
||||
#define OPCODE_BFI 0xe7c00010
|
||||
#define OPCODE_BLX 0xe12fff30
|
||||
#define OPCODE_UADD8 0xe6500f90
|
||||
#define OPCODE_UADD16 0xe6500f10
|
||||
#define OPCODE_USUB8 0xe6500ff0
|
||||
#define OPCODE_USUB16 0xe6500f70
|
||||
#define OPCODE_UXTB 0xe6ef0070
|
||||
#define OPCODE_UXTH 0xe6ff0070
|
||||
|
||||
#define B_OFFSET(x) (((x) >> 2) & 0xffffff)
|
||||
|
||||
#define SHIFT_TYPE_SHIFT 5
|
||||
#define SHIFT_TYPE_LSL (0 << SHIFT_TYPE_SHIFT)
|
||||
#define SHIFT_TYPE_LSR (1 << SHIFT_TYPE_SHIFT)
|
||||
#define SHIFT_TYPE_ASR (2 << SHIFT_TYPE_SHIFT)
|
||||
#define SHIFT_TYPE_ROR (3 << SHIFT_TYPE_SHIFT)
|
||||
|
||||
#define SHIFT_TYPE_IMM (0 << 4)
|
||||
#define SHIFT_TYPE_REG (1 << 4)
|
||||
|
||||
#define SHIFT_IMM_SHIFT 7
|
||||
#define SHIFT_LSL_IMM(x) (SHIFT_TYPE_LSL | SHIFT_TYPE_IMM | ((x) << SHIFT_IMM_SHIFT))
|
||||
#define SHIFT_LSR_IMM(x) (SHIFT_TYPE_LSR | SHIFT_TYPE_IMM | ((x) << SHIFT_IMM_SHIFT))
|
||||
|
||||
#define BFI_lsb(lsb) ((lsb) << 7)
|
||||
#define BFI_msb(msb) ((msb) << 16)
|
||||
|
||||
#define UXTB_ROTATE(rotate) (((rotate) >> 3) << 10)
|
||||
|
||||
#define MOVW_IMM(imm) (((imm) & 0xfff) | (((imm) & 0xf000) << 4))
|
||||
|
||||
static int literal_offset = 0;
|
||||
void codegen_reset_literal_pool(codeblock_t *block)
|
||||
{
|
||||
literal_offset = 0;
|
||||
}
|
||||
|
||||
int add_literal(codeblock_t *block, uint32_t data)
|
||||
{
|
||||
int c;
|
||||
|
||||
if (literal_offset >= 4096)
|
||||
fatal("add_literal - literal pool full\n");
|
||||
|
||||
/*Search for pre-existing value*/
|
||||
for (c = 0; c < literal_offset; c += 4)
|
||||
{
|
||||
if (*(uint32_t *)&block->data[ARM_LITERAL_POOL_OFFSET + c] == data)
|
||||
return c;
|
||||
}
|
||||
|
||||
*(uint32_t *)&block->data[ARM_LITERAL_POOL_OFFSET + literal_offset] = data;
|
||||
|
||||
literal_offset += 4;
|
||||
|
||||
return literal_offset - 4;
|
||||
}
|
||||
|
||||
|
||||
static inline uint32_t arm_data_offset(int offset)
|
||||
{
|
||||
if (offset < -0xffc || offset > 0xffc)
|
||||
fatal("arm_data_offset out of range - %i\n", offset);
|
||||
|
||||
if (offset >= 0)
|
||||
return offset | DATA_OFFSET_UP;
|
||||
return (-offset) | DATA_OFFSET_DOWN;
|
||||
}
|
||||
|
||||
static inline int get_arm_imm(uint32_t imm_data, uint32_t *arm_imm)
|
||||
{
|
||||
int shift = 0;
|
||||
|
|
@ -163,261 +47,6 @@ static inline int in_range(void *addr, void *base)
|
|||
return 1;
|
||||
}
|
||||
|
||||
void host_arm_ADD_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift);
|
||||
void host_arm_AND_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift);
|
||||
void host_arm_EOR_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift);
|
||||
void host_arm_ORR_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift);
|
||||
void host_arm_SUB_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift);
|
||||
|
||||
void host_arm_ADD_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm)
|
||||
{
|
||||
uint32_t arm_imm;
|
||||
|
||||
if ((int32_t)imm < 0 && imm != 0x80000000)
|
||||
{
|
||||
host_arm_SUB_IMM(block, dst_reg, src_reg, -(int32_t)imm);
|
||||
}
|
||||
else if (get_arm_imm(imm, &arm_imm))
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_ADD_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm);
|
||||
}
|
||||
else
|
||||
{
|
||||
int offset = add_literal(block, imm);
|
||||
host_arm_LDR_IMM(block, REG_TEMP, REG_LITERAL, offset);
|
||||
host_arm_ADD_REG_LSL(block, dst_reg, src_reg, REG_TEMP, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void host_arm_ADD_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift)
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_ADD_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift));
|
||||
}
|
||||
|
||||
void host_arm_AND_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm)
|
||||
{
|
||||
uint32_t arm_imm;
|
||||
|
||||
if (get_arm_imm(imm, &arm_imm))
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_AND_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm);
|
||||
}
|
||||
else if (get_arm_imm(~imm, &arm_imm))
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_BIC_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm);
|
||||
}
|
||||
else
|
||||
{
|
||||
int offset = add_literal(block, imm);
|
||||
host_arm_LDR_IMM(block, REG_TEMP, REG_LITERAL, offset);
|
||||
host_arm_AND_REG_LSL(block, dst_reg, src_reg, REG_TEMP, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void host_arm_AND_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift)
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_AND_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift));
|
||||
}
|
||||
|
||||
void host_arm_BFI(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_BFI | Rd(dst_reg) | Rm(src_reg) | BFI_lsb(lsb) | BFI_msb((lsb + width) - 1));
|
||||
}
|
||||
|
||||
void host_arm_BIC_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift)
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_BIC_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift));
|
||||
}
|
||||
void host_arm_BIC_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift)
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_BIC_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSR_IMM(shift));
|
||||
}
|
||||
|
||||
void host_arm_BLX(codeblock_t *block, int addr_reg)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_BLX | Rm(addr_reg));
|
||||
}
|
||||
|
||||
void host_arm_BNE(codeblock_t *block, uintptr_t dest_addr)
|
||||
{
|
||||
uint32_t offset = (dest_addr - (uintptr_t)&block->data[block_pos]) - 8;
|
||||
|
||||
if ((offset & 0xfe000000) && (offset & 0xfe000000) != 0xfe000000)
|
||||
fatal("host_arm_BNE - out of range %08x %i\n", offset, offset);
|
||||
|
||||
codegen_addlong(block, COND_NE | OPCODE_B | B_OFFSET(offset));
|
||||
}
|
||||
|
||||
void host_arm_EOR_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm)
|
||||
{
|
||||
uint32_t arm_imm;
|
||||
|
||||
if (get_arm_imm(imm, &arm_imm))
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_EOR_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm);
|
||||
}
|
||||
else
|
||||
{
|
||||
int offset = add_literal(block, imm);
|
||||
host_arm_LDR_IMM(block, REG_TEMP, REG_LITERAL, offset);
|
||||
host_arm_EOR_REG_LSL(block, dst_reg, src_reg, REG_TEMP, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void host_arm_EOR_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift)
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_EOR_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift));
|
||||
}
|
||||
|
||||
void host_arm_LDMIA_WB(codeblock_t *block, int addr_reg, uint32_t reg_mask)
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_LDMIA_WB | Rn(addr_reg) | reg_mask);
|
||||
}
|
||||
|
||||
void host_arm_LDR_IMM(codeblock_t *block, int dst_reg, int addr_reg, int offset)
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_LDR_IMM | Rn(addr_reg) | Rd(dst_reg) | arm_data_offset(offset));
|
||||
}
|
||||
|
||||
void host_arm_MOV_IMM(codeblock_t *block, int dst_reg, uint32_t imm)
|
||||
{
|
||||
uint32_t arm_imm;
|
||||
|
||||
if (get_arm_imm(imm, &arm_imm))
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_MOV_IMM | Rd(dst_reg) | arm_imm);
|
||||
}
|
||||
else
|
||||
{
|
||||
int offset = add_literal(block, imm);
|
||||
host_arm_LDR_IMM(block, dst_reg, REG_LITERAL, offset);
|
||||
}
|
||||
}
|
||||
|
||||
void host_arm_MOV_REG_LSL(codeblock_t *block, int dst_reg, int src_reg, int shift)
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_MOV_REG | Rd(dst_reg) | Rm(src_reg) | SHIFT_LSL_IMM(shift));
|
||||
}
|
||||
void host_arm_MOV_REG_LSR(codeblock_t *block, int dst_reg, int src_reg, int shift)
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_MOV_REG | Rd(dst_reg) | Rm(src_reg) | SHIFT_LSR_IMM(shift));
|
||||
}
|
||||
|
||||
void host_arm_MOVW_IMM(codeblock_t *block, int dst_reg, uint16_t imm)
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_MOVW_IMM | Rd(dst_reg) | MOVW_IMM(imm));
|
||||
}
|
||||
|
||||
void host_arm_MVN_REG_LSL(codeblock_t *block, int dst_reg, int src_reg, int shift)
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_MVN_REG | Rd(dst_reg) | Rm(src_reg) | SHIFT_LSL_IMM(shift));
|
||||
}
|
||||
|
||||
void host_arm_ORR_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm)
|
||||
{
|
||||
uint32_t arm_imm;
|
||||
|
||||
if (get_arm_imm(imm, &arm_imm))
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_ORR_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm);
|
||||
}
|
||||
else
|
||||
{
|
||||
int offset = add_literal(block, imm);
|
||||
host_arm_LDR_IMM(block, REG_TEMP, REG_LITERAL, offset);
|
||||
host_arm_ORR_REG_LSL(block, dst_reg, src_reg, REG_TEMP, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void host_arm_ORR_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift)
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_ORR_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift));
|
||||
}
|
||||
|
||||
void host_arm_RSB_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift)
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_RSB_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSR_IMM(shift));
|
||||
}
|
||||
|
||||
void host_arm_STMDB_WB(codeblock_t *block, int addr_reg, uint32_t reg_mask)
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_STMDB_WB | Rn(addr_reg) | reg_mask);
|
||||
}
|
||||
|
||||
void host_arm_STR_IMM(codeblock_t *block, int src_reg, int addr_reg, int offset)
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_STR_IMM | Rn(addr_reg) | Rd(src_reg) | arm_data_offset(offset));
|
||||
}
|
||||
|
||||
void host_arm_STRB_IMM(codeblock_t *block, int src_reg, int addr_reg, int offset)
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_STRB_IMM | Rn(addr_reg) | Rd(src_reg) | arm_data_offset(offset));
|
||||
}
|
||||
|
||||
void host_arm_SUB_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm)
|
||||
{
|
||||
uint32_t arm_imm;
|
||||
|
||||
if ((int32_t)imm < 0 && imm != 0x80000000)
|
||||
{
|
||||
host_arm_ADD_IMM(block, dst_reg, src_reg, -(int32_t)imm);
|
||||
}
|
||||
else if (get_arm_imm(imm, &arm_imm))
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_SUB_IMM | Rd(dst_reg) | Rn(src_reg) | arm_imm);
|
||||
}
|
||||
else
|
||||
{
|
||||
int offset = add_literal(block, imm);
|
||||
host_arm_LDR_IMM(block, REG_TEMP, REG_LITERAL, offset);
|
||||
host_arm_SUB_REG_LSL(block, dst_reg, src_reg, REG_TEMP, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void host_arm_SUB_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift)
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_SUB_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSL_IMM(shift));
|
||||
}
|
||||
void host_arm_SUB_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift)
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_SUB_REG | Rd(dst_reg) | Rn(src_reg_n) | Rm(src_reg_m) | SHIFT_LSR_IMM(shift));
|
||||
}
|
||||
|
||||
void host_arm_TST_REG(codeblock_t *block, int src_reg1, int src_reg2)
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_TST_REG | Rn(src_reg1) | Rm(src_reg2));
|
||||
}
|
||||
|
||||
void host_arm_UADD8(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_UADD8 | Rd(dst_reg) | Rn(src_reg_a) | Rm(src_reg_b));
|
||||
}
|
||||
|
||||
void host_arm_UADD16(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_UADD16 | Rd(dst_reg) | Rn(src_reg_a) | Rm(src_reg_b));
|
||||
}
|
||||
|
||||
void host_arm_USUB8(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_USUB8 | Rd(dst_reg) | Rn(src_reg_a) | Rm(src_reg_b));
|
||||
}
|
||||
|
||||
void host_arm_USUB16(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
codegen_addlong(block, COND_AL | OPCODE_USUB16 | Rd(dst_reg) | Rn(src_reg_a) | Rm(src_reg_b));
|
||||
}
|
||||
|
||||
void host_arm_UXTB(codeblock_t *block, int dst_reg, int src_reg, int rotate)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_UXTB | Rd(dst_reg) | Rm(src_reg) | UXTB_ROTATE(rotate));
|
||||
}
|
||||
|
||||
void host_arm_UXTH(codeblock_t *block, int dst_reg, int src_reg, int rotate)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_UXTH | Rd(dst_reg) | Rm(src_reg) | UXTB_ROTATE(rotate));
|
||||
}
|
||||
|
||||
void host_arm_call(codeblock_t *block, void *dst_addr)
|
||||
{
|
||||
int offset = add_literal(block, (uintptr_t)dst_addr);
|
||||
|
|
@ -593,6 +222,22 @@ static int codegen_CALL_INSTRUCTION_FUNC(codeblock_t *block, uop_t *uop)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_CMP_IMM_JZ(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int src_reg = HOST_REG_GET(uop->src_reg_a_real);
|
||||
int src_size = IREG_GET_SIZE(uop->src_reg_a_real);
|
||||
|
||||
if (REG_IS_L(src_size))
|
||||
{
|
||||
host_arm_CMP_IMM(block, src_reg, uop->imm_data);
|
||||
}
|
||||
else
|
||||
fatal("CMP_IMM_JZ %02x\n", uop->src_reg_a_real);
|
||||
host_arm_BEQ(block, uop->p);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_LOAD_FUNC_ARG0_IMM(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
uint32_t arm_imm;
|
||||
|
|
@ -646,6 +291,190 @@ static int codegen_LOAD_FUNC_ARG3_IMM(codeblock_t *block, uop_t *uop)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_MEM_LOAD_ABS(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real);
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real);
|
||||
|
||||
host_arm_ADD_IMM(block, REG_R0, seg_reg, uop->imm_data);
|
||||
if (REG_IS_B(dest_size) || REG_IS_BH(dest_size))
|
||||
{
|
||||
host_arm_BL(block, codegen_mem_load_byte);
|
||||
}
|
||||
else if (REG_IS_W(dest_size))
|
||||
{
|
||||
host_arm_BL(block, codegen_mem_load_word);
|
||||
}
|
||||
else if (REG_IS_L(dest_size))
|
||||
{
|
||||
host_arm_BL(block, codegen_mem_load_long);
|
||||
}
|
||||
else
|
||||
fatal("MEM_LOAD_ABS - %02x\n", uop->dest_reg_a_real);
|
||||
host_arm_TST_REG(block, REG_R1, REG_R1);
|
||||
host_arm_BNE(block, &block->data[BLOCK_EXIT_OFFSET]);
|
||||
if (REG_IS_B(dest_size))
|
||||
{
|
||||
host_arm_BFI(block, dest_reg, REG_R0, 0, 8);
|
||||
}
|
||||
else if (REG_IS_BH(dest_size))
|
||||
{
|
||||
host_arm_BFI(block, dest_reg, REG_R0, 8, 8);
|
||||
}
|
||||
else if (REG_IS_W(dest_size))
|
||||
{
|
||||
host_arm_BFI(block, dest_reg, REG_R0, 0, 16);
|
||||
}
|
||||
else if (REG_IS_L(dest_size))
|
||||
{
|
||||
host_arm_MOV_REG(block, dest_reg, REG_R0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_MEM_LOAD_REG(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real);
|
||||
|
||||
host_arm_ADD_REG(block, REG_R0, seg_reg, addr_reg);
|
||||
if (REG_IS_B(dest_size) || REG_IS_BH(dest_size))
|
||||
{
|
||||
host_arm_BL(block, codegen_mem_load_byte);
|
||||
}
|
||||
else if (REG_IS_W(dest_size))
|
||||
{
|
||||
host_arm_BL(block, codegen_mem_load_word);
|
||||
}
|
||||
else if (REG_IS_L(dest_size))
|
||||
{
|
||||
host_arm_BL(block, codegen_mem_load_long);
|
||||
}
|
||||
else
|
||||
fatal("MEM_LOAD_REG - %02x\n", uop->dest_reg_a_real);
|
||||
host_arm_TST_REG(block, REG_R1, REG_R1);
|
||||
host_arm_BNE(block, &block->data[BLOCK_EXIT_OFFSET]);
|
||||
if (REG_IS_B(dest_size))
|
||||
{
|
||||
host_arm_BFI(block, dest_reg, REG_R0, 0, 8);
|
||||
}
|
||||
else if (REG_IS_BH(dest_size))
|
||||
{
|
||||
host_arm_BFI(block, dest_reg, REG_R0, 8, 8);
|
||||
}
|
||||
else if (REG_IS_W(dest_size))
|
||||
{
|
||||
host_arm_BFI(block, dest_reg, REG_R0, 0, 16);
|
||||
}
|
||||
else if (REG_IS_L(dest_size))
|
||||
{
|
||||
host_arm_MOV_REG(block, dest_reg, REG_R0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_MEM_STORE_ABS(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int seg_reg = HOST_REG_GET(uop->src_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int src_size = IREG_GET_SIZE(uop->src_reg_b_real);
|
||||
|
||||
host_arm_ADD_IMM(block, REG_R0, seg_reg, uop->imm_data);
|
||||
if (REG_IS_B(src_size))
|
||||
{
|
||||
host_arm_MOV_REG(block, REG_R1, src_reg);
|
||||
host_arm_BL(block, codegen_mem_store_byte);
|
||||
}
|
||||
else if (REG_IS_W(src_size))
|
||||
{
|
||||
host_arm_MOV_REG(block, REG_R1, src_reg);
|
||||
host_arm_BL(block, codegen_mem_store_word);
|
||||
}
|
||||
else if (REG_IS_L(src_size))
|
||||
{
|
||||
host_arm_MOV_REG(block, REG_R1, src_reg);
|
||||
host_arm_BL(block, codegen_mem_store_long);
|
||||
}
|
||||
else
|
||||
fatal("MEM_STORE_ABS - %02x\n", uop->src_reg_b_real);
|
||||
host_arm_TST_REG(block, REG_R1, REG_R1);
|
||||
host_arm_BNE(block, &block->data[BLOCK_EXIT_OFFSET]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_MEM_STORE_REG(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real), src_reg = HOST_REG_GET(uop->src_reg_c_real);
|
||||
int src_size = IREG_GET_SIZE(uop->src_reg_c_real);
|
||||
|
||||
host_arm_ADD_REG(block, REG_R0, seg_reg, addr_reg);
|
||||
if (REG_IS_B(src_size))
|
||||
{
|
||||
host_arm_MOV_REG(block, REG_R1, src_reg);
|
||||
host_arm_BL(block, codegen_mem_store_byte);
|
||||
}
|
||||
else if (REG_IS_BH(src_size))
|
||||
{
|
||||
host_arm_MOV_REG_LSR(block, REG_R1, src_reg, 8);
|
||||
host_arm_BL(block, codegen_mem_store_byte);
|
||||
}
|
||||
else if (REG_IS_W(src_size))
|
||||
{
|
||||
host_arm_MOV_REG(block, REG_R1, src_reg);
|
||||
host_arm_BL(block, codegen_mem_store_word);
|
||||
}
|
||||
else if (REG_IS_L(src_size))
|
||||
{
|
||||
host_arm_MOV_REG(block, REG_R1, src_reg);
|
||||
host_arm_BL(block, codegen_mem_store_long);
|
||||
}
|
||||
else
|
||||
fatal("MEM_STORE_REG - %02x\n", uop->src_reg_c_real);
|
||||
host_arm_TST_REG(block, REG_R1, REG_R1);
|
||||
host_arm_BNE(block, &block->data[BLOCK_EXIT_OFFSET]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_MEM_STORE_IMM_8(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real);
|
||||
|
||||
host_arm_ADD_REG(block, REG_R0, seg_reg, addr_reg);
|
||||
host_arm_MOV_IMM(block, REG_R1, uop->imm_data);
|
||||
host_arm_BL(block, codegen_mem_store_byte);
|
||||
host_arm_TST_REG(block, REG_R1, REG_R1);
|
||||
host_arm_BNE(block, &block->data[BLOCK_EXIT_OFFSET]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_MEM_STORE_IMM_16(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real);
|
||||
|
||||
host_arm_ADD_REG(block, REG_R0, seg_reg, addr_reg);
|
||||
host_arm_MOV_IMM(block, REG_R1, uop->imm_data);
|
||||
host_arm_BL(block, codegen_mem_store_word);
|
||||
host_arm_TST_REG(block, REG_R1, REG_R1);
|
||||
host_arm_BNE(block, &block->data[BLOCK_EXIT_OFFSET]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_MEM_STORE_IMM_32(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real);
|
||||
|
||||
host_arm_ADD_REG(block, REG_R0, seg_reg, addr_reg);
|
||||
host_arm_MOV_IMM(block, REG_R1, uop->imm_data);
|
||||
host_arm_BL(block, codegen_mem_store_long);
|
||||
host_arm_TST_REG(block, REG_R1, REG_R1);
|
||||
host_arm_BNE(block, &block->data[BLOCK_EXIT_OFFSET]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_MOV(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);
|
||||
|
|
@ -1015,11 +844,20 @@ const uOpFn uop_handlers[UOP_MAX] =
|
|||
[UOP_STORE_P_IMM & UOP_MASK] = codegen_STORE_PTR_IMM,
|
||||
[UOP_STORE_P_IMM_8 & UOP_MASK] = codegen_STORE_PTR_IMM_8,
|
||||
|
||||
[UOP_MEM_LOAD_ABS & UOP_MASK] = codegen_MEM_LOAD_ABS,
|
||||
[UOP_MEM_LOAD_REG & UOP_MASK] = codegen_MEM_LOAD_REG,
|
||||
|
||||
[UOP_MEM_STORE_ABS & UOP_MASK] = codegen_MEM_STORE_ABS,
|
||||
[UOP_MEM_STORE_REG & UOP_MASK] = codegen_MEM_STORE_REG,
|
||||
[UOP_MEM_STORE_IMM_8 & UOP_MASK] = codegen_MEM_STORE_IMM_8,
|
||||
[UOP_MEM_STORE_IMM_16 & UOP_MASK] = codegen_MEM_STORE_IMM_16,
|
||||
[UOP_MEM_STORE_IMM_32 & UOP_MASK] = codegen_MEM_STORE_IMM_32,
|
||||
|
||||
[UOP_MOV & UOP_MASK] = codegen_MOV,
|
||||
[UOP_MOV_PTR & UOP_MASK] = codegen_MOV_PTR,
|
||||
[UOP_MOV_IMM & UOP_MASK] = codegen_MOV_IMM,
|
||||
[UOP_MOVZX & UOP_MASK] = codegen_MOVZX,
|
||||
|
||||
|
||||
[UOP_ADD & UOP_MASK] = codegen_ADD,
|
||||
[UOP_ADD_IMM & UOP_MASK] = codegen_ADD_IMM,
|
||||
[UOP_ADD_LSHIFT & UOP_MASK] = codegen_ADD_LSHIFT,
|
||||
|
|
@ -1030,7 +868,9 @@ const uOpFn uop_handlers[UOP_MAX] =
|
|||
[UOP_SUB & UOP_MASK] = codegen_SUB,
|
||||
[UOP_SUB_IMM & UOP_MASK] = codegen_SUB_IMM,
|
||||
[UOP_XOR & UOP_MASK] = codegen_XOR,
|
||||
[UOP_XOR_IMM & UOP_MASK] = codegen_XOR_IMM
|
||||
[UOP_XOR_IMM & UOP_MASK] = codegen_XOR_IMM,
|
||||
|
||||
[UOP_CMP_IMM_JZ & UOP_MASK] = codegen_CMP_IMM_JZ
|
||||
};
|
||||
|
||||
void codegen_direct_read_32(codeblock_t *block, int host_reg, void *p)
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@
|
|||
#include "ibm.h"
|
||||
#include "codegen.h"
|
||||
#include "codegen_backend.h"
|
||||
#include "codegen_backend_x86-64_defs.h"
|
||||
#include "codegen_backend_x86-64_ops.h"
|
||||
#include "x86.h"
|
||||
|
||||
#if defined(__linux__) || defined(__APPLE__)
|
||||
|
|
@ -13,6 +15,14 @@
|
|||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
void *codegen_mem_load_byte;
|
||||
void *codegen_mem_load_word;
|
||||
void *codegen_mem_load_long;
|
||||
|
||||
void *codegen_mem_store_byte;
|
||||
void *codegen_mem_store_word;
|
||||
void *codegen_mem_store_long;
|
||||
|
||||
int codegen_host_reg_list[CODEGEN_HOST_REGS] =
|
||||
{
|
||||
REG_EAX,
|
||||
|
|
@ -22,6 +32,183 @@ int codegen_host_reg_list[CODEGEN_HOST_REGS] =
|
|||
|
||||
static void *mem_abrt_rout;
|
||||
|
||||
static void build_load_routine(codeblock_t *block, int size)
|
||||
{
|
||||
uint8_t *branch_offset;
|
||||
uint8_t *misaligned_offset;
|
||||
|
||||
/*In - ESI = address
|
||||
Out - ECX = data, ESI = abrt*/
|
||||
/*MOV ECX, ESI
|
||||
SHR ESI, 12
|
||||
MOV RSI, [readlookup2+ESI*4]
|
||||
CMP ESI, -1
|
||||
JNZ +
|
||||
MOVZX ECX, B[RSI+RCX]
|
||||
XOR ESI,ESI
|
||||
RET
|
||||
* PUSH EAX
|
||||
PUSH EDX
|
||||
PUSH ECX
|
||||
CALL readmemb386l
|
||||
POP ECX
|
||||
POP EDX
|
||||
POP EAX
|
||||
MOVZX ECX, AL
|
||||
RET
|
||||
*/
|
||||
host_x86_MOV32_REG_REG(block, REG_ECX, REG_ESI);
|
||||
host_x86_SHR32_IMM(block, REG_ESI, 12);
|
||||
host_x86_MOV64_REG_IMM(block, REG_RDI, (uint64_t)(uintptr_t)readlookup2);
|
||||
host_x86_MOV64_REG_BASE_INDEX_SHIFT(block, REG_RSI, REG_RDI, REG_RSI, 3);
|
||||
if (size != 1)
|
||||
{
|
||||
host_x86_TEST32_REG_IMM(block, REG_ECX, size-1);
|
||||
misaligned_offset = host_x86_JNZ_short(block);
|
||||
}
|
||||
host_x86_CMP64_REG_IMM(block, REG_RSI, (uint32_t)-1);
|
||||
branch_offset = host_x86_JZ_short(block);
|
||||
if (size == 1)
|
||||
host_x86_MOVZX_BASE_INDEX_32_8(block, REG_ECX, REG_RSI, REG_RCX);
|
||||
else if (size == 2)
|
||||
host_x86_MOVZX_BASE_INDEX_32_16(block, REG_ECX, REG_RSI, REG_RCX);
|
||||
else if (size == 4)
|
||||
host_x86_MOV32_REG_BASE_INDEX(block, REG_ECX, REG_RSI, REG_RCX);
|
||||
else
|
||||
fatal("build_load_routine: size=%i\n", size);
|
||||
host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI, REG_ESI);
|
||||
host_x86_RET(block);
|
||||
|
||||
*branch_offset = (uint8_t)((uintptr_t)&block->data[block_pos] - (uintptr_t)branch_offset) - 1;
|
||||
if (size != 1)
|
||||
*misaligned_offset = (uint8_t)((uintptr_t)&block->data[block_pos] - (uintptr_t)misaligned_offset) - 1;
|
||||
host_x86_PUSH(block, REG_RAX);
|
||||
host_x86_PUSH(block, REG_RDX);
|
||||
#if WIN64
|
||||
host_x86_SUB64_REG_IMM(block, REG_RSP, 0x20);
|
||||
//host_x86_MOV32_REG_REG(block, REG_ECX, uop->imm_data);
|
||||
#else
|
||||
host_x86_MOV32_REG_REG(block, REG_EDI, REG_ECX);
|
||||
#endif
|
||||
if (size == 1)
|
||||
{
|
||||
host_x86_CALL(block, (void *)readmemb386l);
|
||||
host_x86_MOVZX_REG_32_8(block, REG_ECX, REG_EAX);
|
||||
}
|
||||
else if (size == 2)
|
||||
{
|
||||
host_x86_CALL(block, (void *)readmemwl);
|
||||
host_x86_MOVZX_REG_32_16(block, REG_ECX, REG_EAX);
|
||||
}
|
||||
else if (size == 4)
|
||||
{
|
||||
host_x86_CALL(block, (void *)readmemll);
|
||||
host_x86_MOV32_REG_REG(block, REG_ECX, REG_EAX);
|
||||
}
|
||||
#if WIN64
|
||||
host_x86_ADD64_REG_IMM(block, REG_RSP, 0x20);
|
||||
#endif
|
||||
host_x86_POP(block, REG_RDX);
|
||||
host_x86_POP(block, REG_RAX);
|
||||
host_x86_MOVZX_REG_ABS_32_8(block, REG_ESI, &cpu_state.abrt);
|
||||
host_x86_RET(block);
|
||||
block_pos = (block_pos + 63) & ~63;
|
||||
}
|
||||
|
||||
static void build_store_routine(codeblock_t *block, int size)
|
||||
{
|
||||
uint8_t *branch_offset;
|
||||
uint8_t *misaligned_offset;
|
||||
|
||||
/*In - ECX = data, ESI = address
|
||||
Out - ESI = abrt
|
||||
Corrupts EDI*/
|
||||
/*MOV EDI, ESI
|
||||
SHR ESI, 12
|
||||
MOV ESI, [writelookup2+ESI*4]
|
||||
CMP ESI, -1
|
||||
JNZ +
|
||||
MOV [RSI+RDI], ECX
|
||||
XOR ESI,ESI
|
||||
RET
|
||||
* PUSH EAX
|
||||
PUSH EDX
|
||||
PUSH ECX
|
||||
CALL writememb386l
|
||||
POP ECX
|
||||
POP EDX
|
||||
POP EAX
|
||||
MOVZX ECX, AL
|
||||
RET
|
||||
*/
|
||||
host_x86_MOV32_REG_REG(block, REG_EDI, REG_ESI);
|
||||
host_x86_SHR32_IMM(block, REG_ESI, 12);
|
||||
host_x86_MOV64_REG_IMM(block, REG_R8, (uint64_t)(uintptr_t)writelookup2);
|
||||
host_x86_MOV64_REG_BASE_INDEX_SHIFT(block, REG_RSI, REG_R8, REG_RSI, 3);
|
||||
if (size != 1)
|
||||
{
|
||||
host_x86_TEST32_REG_IMM(block, REG_EDI, size-1);
|
||||
misaligned_offset = host_x86_JNZ_short(block);
|
||||
}
|
||||
host_x86_CMP64_REG_IMM(block, REG_RSI, (uint32_t)-1);
|
||||
branch_offset = host_x86_JZ_short(block);
|
||||
if (size == 1)
|
||||
host_x86_MOV8_BASE_INDEX_REG(block, REG_RSI, REG_RDI, REG_ECX);
|
||||
else if (size == 2)
|
||||
host_x86_MOV16_BASE_INDEX_REG(block, REG_RSI, REG_RDI, REG_ECX);
|
||||
else if (size == 4)
|
||||
host_x86_MOV32_BASE_INDEX_REG(block, REG_RSI, REG_RDI, REG_ECX);
|
||||
else
|
||||
fatal("build_store_routine: size=%i\n", size);
|
||||
host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI, REG_ESI);
|
||||
host_x86_RET(block);
|
||||
|
||||
*branch_offset = (uint8_t)((uintptr_t)&block->data[block_pos] - (uintptr_t)branch_offset) - 1;
|
||||
if (size != 1)
|
||||
*misaligned_offset = (uint8_t)((uintptr_t)&block->data[block_pos] - (uintptr_t)misaligned_offset) - 1;
|
||||
host_x86_PUSH(block, REG_RAX);
|
||||
host_x86_PUSH(block, REG_RDX);
|
||||
#if WIN64
|
||||
host_x86_SUB64_REG_IMM(block, REG_RSP, 0x20);
|
||||
host_x86_MOV32_REG_REG(block, REG_EDX, REG_ECX); //data
|
||||
host_x86_MOV32_REG_REG(block, REG_ECX, REG_EDI); //address
|
||||
#else
|
||||
//host_x86_MOV32_REG_REG(block, REG_EDI, REG_ECX); //address
|
||||
host_x86_MOV32_REG_REG(block, REG_ESI, REG_ECX); //data
|
||||
#endif
|
||||
if (size == 1)
|
||||
host_x86_CALL(block, (void *)writememb386l);
|
||||
else if (size == 2)
|
||||
host_x86_CALL(block, (void *)writememwl);
|
||||
else if (size == 4)
|
||||
host_x86_CALL(block, (void *)writememll);
|
||||
#if WIN64
|
||||
host_x86_ADD64_REG_IMM(block, REG_RSP, 0x20);
|
||||
#endif
|
||||
host_x86_POP(block, REG_RDX);
|
||||
host_x86_POP(block, REG_RAX);
|
||||
host_x86_MOVZX_REG_ABS_32_8(block, REG_ESI, &cpu_state.abrt);
|
||||
host_x86_RET(block);
|
||||
block_pos = (block_pos + 63) & ~63;
|
||||
}
|
||||
|
||||
static void build_loadstore_routines(codeblock_t *block)
|
||||
{
|
||||
codegen_mem_load_byte = &codeblock[block_current].data[block_pos];
|
||||
build_load_routine(block, 1);
|
||||
codegen_mem_load_word = &codeblock[block_current].data[block_pos];
|
||||
build_load_routine(block, 2);
|
||||
codegen_mem_load_long = &codeblock[block_current].data[block_pos];
|
||||
build_load_routine(block, 4);
|
||||
|
||||
codegen_mem_store_byte = &codeblock[block_current].data[block_pos];
|
||||
build_store_routine(block, 1);
|
||||
codegen_mem_store_word = &codeblock[block_current].data[block_pos];
|
||||
build_store_routine(block, 2);
|
||||
codegen_mem_store_long = &codeblock[block_current].data[block_pos];
|
||||
build_store_routine(block, 4);
|
||||
}
|
||||
|
||||
void codegen_backend_init()
|
||||
{
|
||||
int c;
|
||||
|
|
@ -55,6 +242,11 @@ void codegen_backend_init()
|
|||
}
|
||||
#endif
|
||||
// pclog("Codegen is %p\n", (void *)pages[0xfab12 >> 12].block);
|
||||
|
||||
block_current = BLOCK_SIZE;
|
||||
block_pos = 0;
|
||||
build_loadstore_routines(&codeblock[block_current]);
|
||||
// fatal("Here\n");
|
||||
}
|
||||
|
||||
static inline void call(codeblock_t *block, uintptr_t func)
|
||||
|
|
|
|||
|
|
@ -6,3 +6,20 @@
|
|||
#define REG_EBP 5
|
||||
#define REG_ESI 6
|
||||
#define REG_EDI 7
|
||||
|
||||
#define REG_RAX 0
|
||||
#define REG_RCX 1
|
||||
#define REG_RDX 2
|
||||
#define REG_RBX 3
|
||||
#define REG_RSP 4
|
||||
#define REG_RBP 5
|
||||
#define REG_RSI 6
|
||||
#define REG_RDI 7
|
||||
#define REG_R8 8
|
||||
#define REG_R9 9
|
||||
#define REG_R10 10
|
||||
#define REG_R11 11
|
||||
#define REG_R12 12
|
||||
#define REG_R13 13
|
||||
#define REG_R14 14
|
||||
#define REG_R15 15
|
||||
|
|
|
|||
888
src/codegen_backend_x86-64_ops.c
Normal file
888
src/codegen_backend_x86-64_ops.c
Normal file
|
|
@ -0,0 +1,888 @@
|
|||
#ifdef __amd64__
|
||||
|
||||
#include "ibm.h"
|
||||
#include "codegen.h"
|
||||
#include "codegen_backend.h"
|
||||
#include "codegen_backend_x86-64_defs.h"
|
||||
#include "codegen_backend_x86-64_ops.h"
|
||||
|
||||
#define RM_OP_ADD 0x00
|
||||
#define RM_OP_OR 0x08
|
||||
#define RM_OP_AND 0x20
|
||||
#define RM_OP_SUB 0x28
|
||||
#define RM_OP_XOR 0x30
|
||||
#define RM_OP_CMP 0x38
|
||||
|
||||
#define RM_OP_SHR 0x28
|
||||
|
||||
static inline void codegen_addbyte(codeblock_t *block, uint8_t val)
|
||||
{
|
||||
block->data[block_pos++] = val;
|
||||
if (block_pos >= BLOCK_MAX)
|
||||
{
|
||||
fatal("codegen_addbyte over! %i\n", block_pos);
|
||||
// CPU_BLOCK_END();
|
||||
}
|
||||
}
|
||||
static inline void codegen_addbyte2(codeblock_t *block, uint8_t vala, uint8_t valb)
|
||||
{
|
||||
block->data[block_pos++] = vala;
|
||||
block->data[block_pos++] = valb;
|
||||
if (block_pos >= BLOCK_MAX)
|
||||
{
|
||||
fatal("codegen_addbyte2 over! %i\n", block_pos);
|
||||
CPU_BLOCK_END();
|
||||
}
|
||||
}
|
||||
static inline void codegen_addbyte3(codeblock_t *block, uint8_t vala, uint8_t valb, uint8_t valc)
|
||||
{
|
||||
block->data[block_pos++] = vala;
|
||||
block->data[block_pos++] = valb;
|
||||
block->data[block_pos++] = valc;
|
||||
if (block_pos >= BLOCK_MAX)
|
||||
{
|
||||
fatal("codegen_addbyte3 over! %i\n", block_pos);
|
||||
CPU_BLOCK_END();
|
||||
}
|
||||
}
|
||||
static inline void codegen_addbyte4(codeblock_t *block, uint8_t vala, uint8_t valb, uint8_t valc, uint8_t vald)
|
||||
{
|
||||
block->data[block_pos++] = vala;
|
||||
block->data[block_pos++] = valb;
|
||||
block->data[block_pos++] = valc;
|
||||
block->data[block_pos++] = vald;
|
||||
if (block_pos >= BLOCK_MAX)
|
||||
{
|
||||
fatal("codegen_addbyte4 over! %i\n", block_pos);
|
||||
CPU_BLOCK_END();
|
||||
}
|
||||
}
|
||||
|
||||
static inline void codegen_addword(codeblock_t *block, uint16_t val)
|
||||
{
|
||||
*(uint16_t *)&block->data[block_pos] = val;
|
||||
block_pos += 2;
|
||||
if (block_pos >= BLOCK_MAX)
|
||||
{
|
||||
fatal("codegen_addword over! %i\n", block_pos);
|
||||
CPU_BLOCK_END();
|
||||
}
|
||||
}
|
||||
|
||||
static inline void codegen_addlong(codeblock_t *block, uint32_t val)
|
||||
{
|
||||
*(uint32_t *)&block->data[block_pos] = val;
|
||||
block_pos += 4;
|
||||
if (block_pos >= BLOCK_MAX)
|
||||
{
|
||||
fatal("codegen_addlong over! %i\n", block_pos);
|
||||
CPU_BLOCK_END();
|
||||
}
|
||||
}
|
||||
|
||||
static inline void codegen_addquad(codeblock_t *block, uint64_t val)
|
||||
{
|
||||
*(uint64_t *)&block->data[block_pos] = val;
|
||||
block_pos += 8;
|
||||
if (block_pos >= BLOCK_MAX)
|
||||
{
|
||||
fatal("codegen_addquad over! %i\n", block_pos);
|
||||
CPU_BLOCK_END();
|
||||
}
|
||||
}
|
||||
|
||||
static int is_imm8(uint32_t imm_data)
|
||||
{
|
||||
if (imm_data <= 0x7f || imm_data >= 0xffffff80)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void call(codeblock_t *block, uintptr_t func)
|
||||
{
|
||||
uintptr_t diff = func - (uintptr_t)&block->data[block_pos + 5];
|
||||
|
||||
if (diff >= -0x80000000 && diff < 0x7fffffff)
|
||||
{
|
||||
codegen_addbyte(block, 0xE8); /*CALL*/
|
||||
codegen_addlong(block, (uint32_t)diff);
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte2(block, 0x49, 0xb9); /*MOV R9, func*/
|
||||
codegen_addquad(block, func);
|
||||
codegen_addbyte3(block, 0x41, 0xff, 0xd1); /*CALL R9*/
|
||||
}
|
||||
}
|
||||
|
||||
void host_x86_ADD8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data)
|
||||
{
|
||||
if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8))
|
||||
fatal("host_x86_ADD8_REG_IMM - dst_reg != src_reg\n");
|
||||
|
||||
if (dst_reg == REG_EAX)
|
||||
codegen_addbyte2(block, 0x04, imm_data); /*ADD EAX, imm_data*/
|
||||
else
|
||||
codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_ADD | (dst_reg & 7), imm_data); /*ADD dst_reg, imm_data*/
|
||||
}
|
||||
void host_x86_ADD16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data)
|
||||
{
|
||||
if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8))
|
||||
fatal("host_x86_ADD32_REG_IMM - dst_reg != src_reg\n");
|
||||
|
||||
if (is_imm8(imm_data))
|
||||
codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_ADD | (dst_reg & 7), imm_data & 0xff); /*ADD dst_reg, imm_data*/
|
||||
else if (dst_reg == REG_EAX)
|
||||
{
|
||||
codegen_addbyte2(block, 0x66, 0x05); /*AND AX, imm_data*/
|
||||
codegen_addword(block, imm_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_ADD | (dst_reg & 7)); /*ADD dst_reg, imm_data*/
|
||||
codegen_addword(block, imm_data);
|
||||
}
|
||||
}
|
||||
void host_x86_ADD32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data)
|
||||
{
|
||||
if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8))
|
||||
fatal("host_x86_ADD32_REG_IMM - dst_reg != src_reg\n");
|
||||
|
||||
if (is_imm8(imm_data))
|
||||
codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_ADD | (dst_reg & 7), imm_data & 0xff); /*ADD dst_reg, imm_data*/
|
||||
else if (dst_reg == REG_EAX)
|
||||
{
|
||||
codegen_addbyte(block, 0x05); /*ADD EAX, imm_data*/
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_ADD | (dst_reg & 7)); /*ADD dst_reg, imm_data*/
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
}
|
||||
void host_x86_ADD64_REG_IMM(codeblock_t *block, int dst_reg, uint64_t imm_data)
|
||||
{
|
||||
if (dst_reg & 8)
|
||||
fatal("host_x86_ADD64_REG_IMM - dst_reg & 8\n");
|
||||
|
||||
if (is_imm8(imm_data))
|
||||
codegen_addbyte4(block, 0x48, 0x83, 0xc0 | RM_OP_ADD | (dst_reg & 7), imm_data & 0xff); /*ADD dst_reg, imm_data*/
|
||||
else
|
||||
fatal("ADD64_REG_IMM !is_imm8 %016llx\n", imm_data);
|
||||
}
|
||||
void host_x86_ADD8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8))
|
||||
fatal("host_x86_ADD8_REG_IMM - dst_reg != src_reg_a\n");
|
||||
|
||||
codegen_addbyte2(block, 0x00, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*ADD dst_reg, src_reg_b*/
|
||||
}
|
||||
void host_x86_ADD16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8))
|
||||
fatal("host_x86_ADD16_REG_IMM - dst_reg != src_reg_a\n");
|
||||
|
||||
codegen_addbyte3(block, 0x66, 0x01, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*ADD dst_reg, src_reg_b*/
|
||||
}
|
||||
void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8))
|
||||
fatal("host_x86_ADD32_REG_IMM - dst_reg != src_reg_a\n");
|
||||
|
||||
codegen_addbyte2(block, 0x01, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*ADD dst_reg, src_reg_b*/
|
||||
}
|
||||
|
||||
void host_x86_AND8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data)
|
||||
{
|
||||
if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8))
|
||||
fatal("host_x86_AND8_REG_IMM - dst_reg != src_reg\n");
|
||||
|
||||
if (dst_reg == REG_EAX)
|
||||
codegen_addbyte2(block, 0x24, imm_data); /*AND EAX, imm_data*/
|
||||
else
|
||||
codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_AND | (dst_reg & 7), imm_data); /*AND dst_reg, imm_data*/
|
||||
}
|
||||
void host_x86_AND16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data)
|
||||
{
|
||||
if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8))
|
||||
fatal("host_x86_AND32_REG_IMM - dst_reg != src_reg\n");
|
||||
|
||||
if (is_imm8(imm_data))
|
||||
codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_AND | (dst_reg & 7), imm_data & 0xff); /*AND dst_reg, imm_data*/
|
||||
else if (dst_reg == REG_EAX)
|
||||
{
|
||||
codegen_addbyte2(block, 0x66, 0x25); /*AND AX, imm_data*/
|
||||
codegen_addword(block, imm_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_AND | (dst_reg & 7)); /*AND dst_reg, imm_data*/
|
||||
codegen_addword(block, imm_data);
|
||||
}
|
||||
}
|
||||
void host_x86_AND32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data)
|
||||
{
|
||||
if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8))
|
||||
fatal("host_x86_AND32_REG_IMM - dst_reg != src_reg\n");
|
||||
|
||||
if (is_imm8(imm_data))
|
||||
codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_AND | (dst_reg & 7), imm_data & 0xff); /*AND dst_reg, imm_data*/
|
||||
else if (dst_reg == REG_EAX)
|
||||
{
|
||||
codegen_addbyte(block, 0x25); /*AND EAX, imm_data*/
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_AND | (dst_reg & 7)); /*AND dst_reg, imm_data*/
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
}
|
||||
void host_x86_AND8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8))
|
||||
fatal("host_x86_AND8_REG_IMM - dst_reg != src_reg_a\n");
|
||||
|
||||
codegen_addbyte2(block, 0x20, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*AND dst_reg, src_reg_b*/
|
||||
}
|
||||
void host_x86_AND16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8))
|
||||
fatal("host_x86_AND16_REG_IMM - dst_reg != src_reg_a\n");
|
||||
|
||||
codegen_addbyte3(block, 0x66, 0x21, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*AND dst_reg, src_reg_b*/
|
||||
}
|
||||
void host_x86_AND32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8))
|
||||
fatal("host_x86_AND32_REG_IMM - dst_reg != src_reg_a\n");
|
||||
|
||||
codegen_addbyte2(block, 0x21, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*AND dst_reg, src_reg_b*/
|
||||
}
|
||||
|
||||
void host_x86_CALL(codeblock_t *block, void *p)
|
||||
{
|
||||
call(block, (uintptr_t)p);
|
||||
}
|
||||
|
||||
void host_x86_CMP32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data)
|
||||
{
|
||||
if (is_imm8(imm_data))
|
||||
codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_CMP | dst_reg, imm_data & 0xff); /*CMP dst_reg, imm_data*/
|
||||
else if (dst_reg == REG_EAX)
|
||||
{
|
||||
codegen_addbyte(block, 0x3d); /*CMP EAX, imm_data*/
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_CMP | dst_reg); /*CMP dst_reg, imm_data*/
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
}
|
||||
void host_x86_CMP64_REG_IMM(codeblock_t *block, int dst_reg, uint64_t imm_data)
|
||||
{
|
||||
if (is_imm8(imm_data))
|
||||
codegen_addbyte4(block, 0x48, 0x83, 0xc0 | RM_OP_CMP | dst_reg, imm_data & 0xff); /*CMP dst_reg, imm_data*/
|
||||
else
|
||||
fatal("CMP64_REG_IMM not 8-bit imm\n");
|
||||
}
|
||||
|
||||
void host_x86_JNZ(codeblock_t *block, void *p)
|
||||
{
|
||||
codegen_addbyte2(block, 0x0f, 0x85); /*JNZ*/
|
||||
codegen_addlong(block, (uintptr_t)p - (uintptr_t)&block->data[block_pos + 4]);
|
||||
}
|
||||
void host_x86_JZ(codeblock_t *block, void *p)
|
||||
{
|
||||
codegen_addbyte2(block, 0x0f, 0x84); /*JZ*/
|
||||
codegen_addlong(block, (uintptr_t)p - (uintptr_t)&block->data[block_pos + 4]);
|
||||
}
|
||||
|
||||
uint8_t *host_x86_JNZ_short(codeblock_t *block)
|
||||
{
|
||||
codegen_addbyte2(block, 0x75, 0); /*JNZ*/
|
||||
return &block->data[block_pos-1];
|
||||
}
|
||||
uint8_t *host_x86_JZ_short(codeblock_t *block)
|
||||
{
|
||||
codegen_addbyte2(block, 0x74, 0); /*JZ*/
|
||||
return &block->data[block_pos-1];
|
||||
}
|
||||
|
||||
void host_x86_LEA_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t offset)
|
||||
{
|
||||
if (offset)
|
||||
{
|
||||
codegen_addbyte2(block, 0x8d, 0x80 | (dst_reg << 3) | src_reg); /*LEA dst_reg, [offset+src_reg]*/
|
||||
codegen_addlong(block, offset);
|
||||
}
|
||||
else
|
||||
codegen_addbyte2(block, 0x8d, 0x00 | (dst_reg << 3) | src_reg); /*LEA dst_reg, [src_reg]*/
|
||||
}
|
||||
void host_x86_LEA_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
if ((dst_reg & 8) || (src_reg_a & 8) || (src_reg_b & 8))
|
||||
fatal("host_x86_LEA_REG_REG - bad reg\n");
|
||||
|
||||
codegen_addbyte3(block, 0x8d, 0x04 | ((dst_reg & 7) << 3), /*LEA dst_reg, [Rsrc_reg_a + Rsrc_reg_b]*/
|
||||
((src_reg_b & 7) << 3) | (src_reg_a & 7));
|
||||
}
|
||||
void host_x86_LEA_REG_REG_SHIFT(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b, int shift)
|
||||
{
|
||||
if ((dst_reg & 8) || (src_reg_a & 8) || (src_reg_b & 8))
|
||||
fatal("host_x86_LEA_REG_REG_SHIFT - bad reg\n");
|
||||
|
||||
codegen_addbyte3(block, 0x8d, 0x04 | ((dst_reg & 7) << 3), /*LEA dst_reg, [Rsrc_reg_a + Rsrc_reg_b * (1 << shift)]*/
|
||||
(shift << 6) | ((src_reg_b & 7) << 3) | (src_reg_a & 7));
|
||||
}
|
||||
|
||||
void host_x86_MOV8_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data)
|
||||
{
|
||||
int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
|
||||
|
||||
if (offset >= -128 && offset < 127)
|
||||
{
|
||||
codegen_addbyte3(block, 0xc6, 0x45, offset); /*MOVB offset[RBP], imm_data*/
|
||||
codegen_addbyte(block, imm_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((uintptr_t)p >> 32)
|
||||
fatal("host_x86_MOV8_ABS_IMM - out of range %p\n", p);
|
||||
codegen_addbyte3(block, 0xc6, 0x04, 0x25); /*MOVB p, imm_data*/
|
||||
codegen_addlong(block, (uint32_t)(uintptr_t)p);
|
||||
codegen_addbyte(block, imm_data);
|
||||
}
|
||||
}
|
||||
void host_x86_MOV32_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data)
|
||||
{
|
||||
int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
|
||||
|
||||
if (offset >= -128 && offset < 127)
|
||||
{
|
||||
codegen_addbyte3(block, 0xc7, 0x45, offset); /*MOV offset[RBP], imm_data*/
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((uintptr_t)p >> 32)
|
||||
fatal("host_x86_MOV32_ABS_IMM - out of range %p\n", p);
|
||||
codegen_addbyte3(block, 0xc7, 0x04, 0x25); /*MOV p, imm_data*/
|
||||
codegen_addlong(block, (uint32_t)(uintptr_t)p);
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
}
|
||||
|
||||
void host_x86_MOV8_ABS_REG(codeblock_t *block, void *p, int src_reg)
|
||||
{
|
||||
int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
|
||||
|
||||
if (src_reg & 8)
|
||||
fatal("host_x86_MOV8_ABS_REG - bad reg\n");
|
||||
|
||||
if (offset >= -128 && offset < 127)
|
||||
{
|
||||
codegen_addbyte3(block, 0x88, 0x45 | ((src_reg & 7) << 3), offset); /*MOVB offset[RBP], src_reg*/
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((uintptr_t)p >> 32)
|
||||
fatal("host_x86_MOV8_ABS_REG - out of range %p\n", p);
|
||||
codegen_addbyte(block, 0x88); /*MOVB [p], src_reg*/
|
||||
codegen_addbyte(block, 0x05 | ((src_reg & 7) << 3));
|
||||
codegen_addlong(block, (uint32_t)(uintptr_t)p);
|
||||
}
|
||||
}
|
||||
void host_x86_MOV32_ABS_REG(codeblock_t *block, void *p, int src_reg)
|
||||
{
|
||||
int64_t offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
|
||||
|
||||
if (src_reg & 8)
|
||||
fatal("host_x86_MOV32_ABS_REG - bad reg\n");
|
||||
|
||||
if (offset >= -128 && offset < 127)
|
||||
{
|
||||
codegen_addbyte3(block, 0x89, 0x45 | ((src_reg & 7) << 3), offset); /*MOV offset[RBP], src_reg*/
|
||||
}
|
||||
else if (offset < (1ull << 32))
|
||||
{
|
||||
codegen_addbyte2(block, 0x89, 0x85 | ((src_reg & 7) << 3)); /*MOV offset[RBP], src_reg*/
|
||||
codegen_addlong(block, offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((uintptr_t)p >> 32)
|
||||
fatal("host_x86_MOV32_ABS_REG - out of range %p\n", p);
|
||||
codegen_addbyte(block, 0x89); /*MOV [p], src_reg*/
|
||||
codegen_addbyte(block, 0x05 | ((src_reg & 7) << 3));
|
||||
codegen_addlong(block, (uint32_t)(uintptr_t)p);
|
||||
}
|
||||
}
|
||||
void host_x86_MOV64_ABS_REG(codeblock_t *block, void *p, int src_reg)
|
||||
{
|
||||
int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
|
||||
|
||||
if (src_reg & 8)
|
||||
fatal("host_x86_MOV64_ABS_REG - bad reg\n");
|
||||
|
||||
if (offset >= -128 && offset < 127)
|
||||
{
|
||||
codegen_addbyte4(block, 0x48, 0x89, 0x45 | ((src_reg & 7) << 3), offset); /*MOV offset[RBP], src_reg*/
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((uintptr_t)p >> 32)
|
||||
fatal("host_x86_MOV64_ABS_REG - out of range %p\n", p);
|
||||
codegen_addbyte4(block, 0x48, 0x89, 0x04 | ((src_reg & 7) << 3), 0x25); /*MOV [p], src_reg*/
|
||||
codegen_addlong(block, (uint32_t)(uintptr_t)p);
|
||||
}
|
||||
}
|
||||
|
||||
void host_x86_MOV8_BASE_INDEX_REG(codeblock_t *block, int base_reg, int index_reg, int src_reg)
|
||||
{
|
||||
if ((src_reg & 8) || (base_reg & 8) | (index_reg & 8))
|
||||
fatal("host_x86_MOV8_BASE_INDEX_REG reg & 8\n");
|
||||
codegen_addbyte3(block, 0x88, 0x04 | (src_reg << 3), (index_reg << 3) | base_reg); /*MOV B[base_reg + index_reg], src_reg*/
|
||||
}
|
||||
void host_x86_MOV16_BASE_INDEX_REG(codeblock_t *block, int base_reg, int index_reg, int src_reg)
|
||||
{
|
||||
if ((src_reg & 8) || (base_reg & 8) | (index_reg & 8))
|
||||
fatal("host_x86_MOV8_BASE_INDEX_REG reg & 8\n");
|
||||
codegen_addbyte4(block, 0x66, 0x89, 0x04 | (src_reg << 3), (index_reg << 3) | base_reg); /*MOV W[base_reg + index_reg], src_reg*/
|
||||
}
|
||||
void host_x86_MOV32_BASE_INDEX_REG(codeblock_t *block, int base_reg, int index_reg, int src_reg)
|
||||
{
|
||||
if ((src_reg & 8) || (base_reg & 8) | (index_reg & 8))
|
||||
fatal("host_x86_MOV8_BASE_INDEX_REG reg & 8\n");
|
||||
codegen_addbyte3(block, 0x89, 0x04 | (src_reg << 3), (index_reg << 3) | base_reg); /*MOV L[base_reg + index_reg], src_reg*/
|
||||
}
|
||||
|
||||
void host_x86_MOV32_REG_ABS(codeblock_t *block, int dst_reg, void *p)
|
||||
{
|
||||
int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
|
||||
|
||||
if (dst_reg & 8)
|
||||
fatal("host_x86_MOV32_REG_ABS reg & 8\n");
|
||||
|
||||
if (offset >= -128 && offset < 127)
|
||||
{
|
||||
codegen_addbyte3(block, 0x8b, 0x45 | ((dst_reg & 7) << 3), offset); /*MOV dst_reg, offset[RBP]*/
|
||||
}
|
||||
else if (offset < (1ull << 32))
|
||||
{
|
||||
codegen_addbyte2(block, 0x8b, 0x85 | ((dst_reg & 7) << 3)); /*MOV dst_reg, offset[RBP]*/
|
||||
codegen_addlong(block, offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
fatal("host_x86_MOV32_REG_ABS - out of range\n");
|
||||
codegen_addbyte(block, 0x8b); /*MOV [p], src_reg*/
|
||||
codegen_addbyte(block, 0x05 | ((dst_reg & 7) << 3));
|
||||
codegen_addlong(block, (uint32_t)(uintptr_t)p);
|
||||
}
|
||||
}
|
||||
|
||||
void host_x86_MOV32_REG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int index_reg)
|
||||
{
|
||||
if ((dst_reg & 8) || (base_reg & 8) | (index_reg & 8))
|
||||
fatal("host_x86_MOV32_REG_BASE_INDEX reg & 8\n");
|
||||
codegen_addbyte3(block, 0x8b, 0x04 | (dst_reg << 3), (index_reg << 3) | base_reg); /*MOV dst_reg, Q[base_reg + index_reg]*/
|
||||
}
|
||||
|
||||
void host_x86_MOV64_REG_BASE_INDEX_SHIFT(codeblock_t *block, int dst_reg, int base_reg, int index_reg, int scale)
|
||||
{
|
||||
if ((dst_reg & 8) || (index_reg & 8))
|
||||
fatal("host_x86_MOV64_REG_BASE_INDEX_SHIFT reg & 8\n");
|
||||
if (base_reg & 8)
|
||||
codegen_addbyte4(block, 0x49, 0x8b, 0x04 | ((dst_reg & 7) << 3), (scale << 6) | ((index_reg & 7) << 3) | (base_reg & 7)); /*MOV dst_reg, Q[base_reg + index_reg << scale]*/
|
||||
else
|
||||
codegen_addbyte4(block, 0x48, 0x8b, 0x04 | ((dst_reg & 7) << 3), (scale << 6) | ((index_reg & 7) << 3) | (base_reg & 7)); /*MOV dst_reg, Q[base_reg + index_reg << scale]*/
|
||||
}
|
||||
|
||||
void host_x86_MOV8_REG_IMM(codeblock_t *block, int reg, uint16_t imm_data)
|
||||
{
|
||||
if (reg >= 8)
|
||||
fatal("host_x86_MOV8_REG_IMM reg >= 4\n");
|
||||
codegen_addbyte2(block, 0xb0 | reg, imm_data); /*MOV reg, imm_data*/
|
||||
}
|
||||
void host_x86_MOV16_REG_IMM(codeblock_t *block, int reg, uint16_t imm_data)
|
||||
{
|
||||
if (reg & 8)
|
||||
fatal("host_x86_MOV16_REG_IMM reg & 8\n");
|
||||
codegen_addbyte2(block, 0x66, 0xb8 | (reg & 7)); /*MOV reg, imm_data*/
|
||||
codegen_addword(block, imm_data);
|
||||
}
|
||||
void host_x86_MOV32_REG_IMM(codeblock_t *block, int reg, uint32_t imm_data)
|
||||
{
|
||||
if (reg & 8)
|
||||
fatal("host_x86_MOV32_REG_IMM reg & 8\n");
|
||||
codegen_addbyte(block, 0xb8 | (reg & 7)); /*MOV reg, imm_data*/
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
|
||||
void host_x86_MOV64_REG_IMM(codeblock_t *block, int reg, uint64_t imm_data)
|
||||
{
|
||||
if (reg & 8)
|
||||
{
|
||||
codegen_addbyte2(block, 0x49, 0xb8 | (reg & 7)); /*MOVQ reg, imm_data*/
|
||||
codegen_addquad(block, imm_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte2(block, 0x48, 0xb8 | (reg & 7)); /*MOVQ reg, imm_data*/
|
||||
codegen_addquad(block, imm_data);
|
||||
}
|
||||
}
|
||||
|
||||
void host_x86_MOV8_REG_REG(codeblock_t *block, int dst_reg, int src_reg)
|
||||
{
|
||||
if ((dst_reg & 8) || (src_reg & 8))
|
||||
fatal("host_x86_MOV8_REG_REG - bad reg\n");
|
||||
|
||||
codegen_addbyte2(block, 0x88, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3));
|
||||
}
|
||||
void host_x86_MOV16_REG_REG(codeblock_t *block, int dst_reg, int src_reg)
|
||||
{
|
||||
if ((dst_reg & 8) || (src_reg & 8))
|
||||
fatal("host_x86_MOV16_REG_REG - bad reg\n");
|
||||
|
||||
codegen_addbyte3(block, 0x66, 0x89, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3));
|
||||
}
|
||||
void host_x86_MOV32_REG_REG(codeblock_t *block, int dst_reg, int src_reg)
|
||||
{
|
||||
if ((dst_reg & 8) || (src_reg & 8))
|
||||
fatal("host_x86_MOV32_REG_REG - bad reg\n");
|
||||
|
||||
codegen_addbyte2(block, 0x89, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3));
|
||||
}
|
||||
|
||||
void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_data)
|
||||
{
|
||||
if (!offset)
|
||||
{
|
||||
codegen_addbyte3(block, 0xc7, 0x04, 0x24); /*MOV [ESP], imm_data*/
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
else if (offset >= -80 || offset < 0x80)
|
||||
{
|
||||
codegen_addbyte4(block, 0xc7, 0x44, 0x24, offset & 0xff); /*MOV offset[ESP], imm_data*/
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte3(block, 0xc7, 0x84, 0x24); /*MOV offset[ESP], imm_data*/
|
||||
codegen_addlong(block, offset);
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
}
|
||||
|
||||
void host_x86_MOVZX_BASE_INDEX_32_8(codeblock_t *block, int dst_reg, int base_reg, int index_reg)
|
||||
{
|
||||
if ((dst_reg & 8) || (base_reg & 8) | (index_reg & 8))
|
||||
fatal("host_x86_MOVZX_BASE_INDEX_32_8 reg & 8\n");
|
||||
codegen_addbyte4(block, 0x0f, 0xb6, 0x04 | (dst_reg << 3), (index_reg << 3) | base_reg);
|
||||
}
|
||||
void host_x86_MOVZX_BASE_INDEX_32_16(codeblock_t *block, int dst_reg, int base_reg, int index_reg)
|
||||
{
|
||||
if ((dst_reg & 8) || (base_reg & 8) | (index_reg & 8))
|
||||
fatal("host_x86_MOVZX_BASE_INDEX_32_16 reg & 8\n");
|
||||
codegen_addbyte4(block, 0x0f, 0xb7, 0x04 | (dst_reg << 3), (index_reg << 3) | base_reg);
|
||||
}
|
||||
|
||||
void host_x86_MOVZX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg)
|
||||
{
|
||||
if ((dst_reg & 8) || (src_reg & 8))
|
||||
fatal("host_x86_MOVZX_REG_32_8 - bad reg\n");
|
||||
codegen_addbyte3(block, 0x0f, 0xb6, 0xc0 | (dst_reg << 3) | src_reg); /*MOVZX dst_reg, src_reg*/
|
||||
}
|
||||
void host_x86_MOVZX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg)
|
||||
{
|
||||
if ((dst_reg & 8) || (src_reg & 8))
|
||||
fatal("host_x86_MOVZX_REG_16_8 - bad reg\n");
|
||||
codegen_addbyte3(block, 0x0f, 0xb7, 0xc0 | (dst_reg << 3) | src_reg); /*MOVZX dst_reg, src_reg*/
|
||||
}
|
||||
|
||||
void host_x86_MOVZX_REG_ABS_32_8(codeblock_t *block, int dst_reg, void *p)
|
||||
{
|
||||
int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
|
||||
|
||||
// if (dst_reg & 8)
|
||||
// fatal("host_x86_MOVZX_REG_ABS_32_8 - bad reg\n");
|
||||
|
||||
if (offset >= -128 && offset < 127)
|
||||
{
|
||||
if (dst_reg & 8)
|
||||
codegen_addbyte(block, 0x44);
|
||||
codegen_addbyte4(block, 0x0f, 0xb6, 0x45 | ((dst_reg & 7) << 3), offset); /*MOVZX dst_reg, offset[RBP]*/
|
||||
}
|
||||
else
|
||||
fatal("host_x86_MOVZX_REG_ABS_32_8 - bad offset %i\n", offset);
|
||||
}
|
||||
|
||||
void host_x86_OR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data)
|
||||
{
|
||||
if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8))
|
||||
fatal("host_x86_OR8_REG_IMM - dst_reg != src_reg\n");
|
||||
|
||||
if (dst_reg == REG_EAX)
|
||||
codegen_addbyte2(block, 0x0c, imm_data); /*OR EAX, imm_data*/
|
||||
else
|
||||
codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_OR | (dst_reg & 7), imm_data); /*OR dst_reg, imm_data*/
|
||||
}
|
||||
void host_x86_OR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data)
|
||||
{
|
||||
if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8))
|
||||
fatal("host_x86_OR16_REG_IMM - dst_reg != src_reg\n");
|
||||
|
||||
if (is_imm8(imm_data))
|
||||
codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_OR | (dst_reg & 7), imm_data & 0xff); /*OR dst_reg, imm_data*/
|
||||
else if (dst_reg == REG_EAX)
|
||||
{
|
||||
codegen_addbyte2(block, 0x66, 0x0d); /*OR AX, imm_data*/
|
||||
codegen_addword(block, imm_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_OR | (dst_reg & 7)); /*OR dst_reg, imm_data*/
|
||||
codegen_addword(block, imm_data);
|
||||
}
|
||||
}
|
||||
void host_x86_OR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data)
|
||||
{
|
||||
if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8))
|
||||
fatal("host_x86_OR32_REG_IMM - dst_reg != src_reg\n");
|
||||
|
||||
if (is_imm8(imm_data))
|
||||
codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_OR | (dst_reg & 7), imm_data & 0xff); /*OR dst_reg, imm_data*/
|
||||
else if (dst_reg == REG_EAX)
|
||||
{
|
||||
codegen_addbyte(block, 0x0d); /*OR EAX, imm_data*/
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_OR | (dst_reg & 7)); /*OR dst_reg, imm_data*/
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
}
|
||||
void host_x86_OR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8))
|
||||
fatal("host_x86_OR8_REG_IMM - dst_reg != src_reg_a\n");
|
||||
|
||||
codegen_addbyte2(block, 0x08, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*OR dst_reg, src_reg_b*/
|
||||
}
|
||||
void host_x86_OR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8))
|
||||
fatal("host_x86_OR16_REG_IMM - dst_reg != src_reg_a\n");
|
||||
|
||||
codegen_addbyte3(block, 0x66, 0x09, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*OR dst_reg, src_reg_b*/
|
||||
}
|
||||
void host_x86_OR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8))
|
||||
fatal("host_x86_OR32_REG_IMM - dst_reg != src_reg_a\n");
|
||||
|
||||
codegen_addbyte2(block, 0x09, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*OR dst_reg, src_reg_b*/
|
||||
}
|
||||
|
||||
void host_x86_POP(codeblock_t *block, int dst_reg)
|
||||
{
|
||||
if (dst_reg & 8)
|
||||
fatal("POP reg & 8\n");
|
||||
codegen_addbyte(block, 0x58 | dst_reg); /*POP reg*/
|
||||
}
|
||||
|
||||
void host_x86_PUSH(codeblock_t *block, int src_reg)
|
||||
{
|
||||
if (src_reg & 8)
|
||||
fatal("PUSH reg & 8\n");
|
||||
codegen_addbyte(block, 0x50 | src_reg); /*PUSH reg*/
|
||||
}
|
||||
|
||||
void host_x86_RET(codeblock_t *block)
|
||||
{
|
||||
codegen_addbyte(block, 0xc3); /*RET*/
|
||||
}
|
||||
|
||||
void host_x86_SHR32_IMM(codeblock_t *block, int dst_reg, int shift)
|
||||
{
|
||||
if (dst_reg & 8)
|
||||
fatal("SHR32_IMM reg & 8\n");
|
||||
codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_SHR | dst_reg, shift); /*SHR dst_reg, shift*/
|
||||
}
|
||||
|
||||
void host_x86_SUB8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data)
|
||||
{
|
||||
if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8))
|
||||
fatal("host_x86_SUB8_REG_IMM - dst_reg != src_reg\n");
|
||||
|
||||
if (dst_reg == REG_EAX)
|
||||
codegen_addbyte2(block, 0x2c, imm_data); /*SUB EAX, imm_data*/
|
||||
else
|
||||
codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_SUB | (dst_reg & 7), imm_data); /*SUB dst_reg, imm_data*/
|
||||
}
|
||||
void host_x86_SUB16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data)
|
||||
{
|
||||
if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8))
|
||||
fatal("host_x86_SUB16_REG_IMM - dst_reg != src_reg\n");
|
||||
|
||||
if (is_imm8(imm_data))
|
||||
codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_SUB | (dst_reg & 7), imm_data & 0xff); /*SUB dst_reg, imm_data*/
|
||||
else if (dst_reg == REG_EAX)
|
||||
{
|
||||
codegen_addbyte2(block, 0x66, 0x2d); /*SUB AX, imm_data*/
|
||||
codegen_addword(block, imm_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_SUB | (dst_reg & 7)); /*SUB dst_reg, imm_data*/
|
||||
codegen_addword(block, imm_data);
|
||||
}
|
||||
}
|
||||
void host_x86_SUB32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data)
|
||||
{
|
||||
if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8))
|
||||
fatal("host_x86_SUB32_REG_IMM - dst_reg != src_reg\n");
|
||||
|
||||
if (is_imm8(imm_data))
|
||||
codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_SUB | (dst_reg & 7), imm_data & 0xff); /*SUB dst_reg, imm_data*/
|
||||
else if (dst_reg == REG_EAX)
|
||||
{
|
||||
codegen_addbyte(block, 0x2d); /*SUB EAX, imm_data*/
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_SUB | (dst_reg & 7)); /*SUB dst_reg, imm_data*/
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
}
|
||||
void host_x86_SUB64_REG_IMM(codeblock_t *block, int dst_reg, uint64_t imm_data)
|
||||
{
|
||||
if (dst_reg & 8)
|
||||
fatal("host_x86_SUB64_REG_IMM - dst_reg & 8\n");
|
||||
|
||||
if (is_imm8(imm_data))
|
||||
codegen_addbyte4(block, 0x48, 0x83, 0xc0 | RM_OP_SUB | (dst_reg & 7), imm_data & 0xff); /*SUB dst_reg, imm_data*/
|
||||
else
|
||||
fatal("SUB64_REG_IMM !is_imm8 %016llx\n", imm_data);
|
||||
}
|
||||
void host_x86_SUB8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8))
|
||||
fatal("host_x86_SUB8_REG_REG - dst_reg != src_reg_a\n");
|
||||
|
||||
codegen_addbyte2(block, 0x28, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*SUB dst_reg, src_reg_b*/
|
||||
}
|
||||
void host_x86_SUB16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8))
|
||||
fatal("host_x86_SUB16_REG_REG - dst_reg != src_reg_a\n");
|
||||
|
||||
codegen_addbyte3(block, 0x66, 0x29, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*SUB dst_reg, src_reg_b*/
|
||||
}
|
||||
void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8))
|
||||
fatal("host_x86_SUB32_REG_REG - dst_reg != src_reg_a\n");
|
||||
|
||||
codegen_addbyte2(block, 0x29, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*SUB dst_reg, src_reg_b*/
|
||||
}
|
||||
|
||||
#define MODRM_MOD_REG(rm, reg) (0xc0 | reg | (rm << 3))
|
||||
|
||||
void host_x86_TEST32_REG(codeblock_t *block, int src_reg, int dst_reg)
|
||||
{
|
||||
if ((dst_reg & 8) || (src_reg & 8))
|
||||
fatal("host_x86_TEST32_REG - bad reg\n");
|
||||
codegen_addbyte2(block, 0x85, MODRM_MOD_REG(dst_reg, src_reg)); /*TEST dst_host_reg, src_host_reg*/
|
||||
}
|
||||
void host_x86_TEST32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data)
|
||||
{
|
||||
if (dst_reg & 8)
|
||||
fatal("TEST32_REG_IMM reg & 8\n");
|
||||
if (dst_reg == REG_EAX)
|
||||
{
|
||||
codegen_addbyte(block, 0xa9); /*TEST EAX, imm_data*/
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte2(block, 0xf7, 0xc0 | dst_reg); /*TEST dst_reg, imm_data*/
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
}
|
||||
|
||||
void host_x86_XOR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data)
|
||||
{
|
||||
if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8))
|
||||
fatal("host_x86_XOR8_REG_IMM - dst_reg != src_reg\n");
|
||||
|
||||
if (dst_reg == REG_EAX)
|
||||
codegen_addbyte2(block, 0x34, imm_data); /*XOR EAX, imm_data*/
|
||||
else
|
||||
codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_XOR | (dst_reg & 7), imm_data); /*XOR dst_reg, imm_data*/
|
||||
}
|
||||
void host_x86_XOR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data)
|
||||
{
|
||||
if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8))
|
||||
fatal("host_x86_XOR16_REG_IMM - dst_reg != src_reg\n");
|
||||
|
||||
if (is_imm8(imm_data))
|
||||
codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_XOR | (dst_reg & 7), imm_data & 0xff); /*XOR dst_reg, imm_data*/
|
||||
else if (dst_reg == REG_EAX)
|
||||
{
|
||||
codegen_addbyte2(block, 0x66, 0x35); /*XOR AX, imm_data*/
|
||||
codegen_addword(block, imm_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_XOR | (dst_reg & 7)); /*XOR dst_reg, imm_data*/
|
||||
codegen_addword(block, imm_data);
|
||||
}
|
||||
}
|
||||
void host_x86_XOR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data)
|
||||
{
|
||||
if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8))
|
||||
fatal("host_x86_XOR32_REG_IMM - dst_reg != src_reg\n");
|
||||
|
||||
if (is_imm8(imm_data))
|
||||
codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_XOR | (dst_reg & 7), imm_data & 0xff); /*XOR dst_reg, imm_data*/
|
||||
else if (dst_reg == REG_EAX)
|
||||
{
|
||||
codegen_addbyte(block, 0x35); /*XOR EAX, imm_data*/
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_XOR | (dst_reg & 7)); /*XOR dst_reg, imm_data*/
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
}
|
||||
void host_x86_XOR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8))
|
||||
fatal("host_x86_XOR8_REG_IMM - dst_reg != src_reg_a\n");
|
||||
|
||||
codegen_addbyte2(block, 0x30, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*XOR dst_reg, src_reg_b*/
|
||||
}
|
||||
void host_x86_XOR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8))
|
||||
fatal("host_x86_XOR16_REG_IMM - dst_reg != src_reg_a\n");
|
||||
|
||||
codegen_addbyte3(block, 0x66, 0x31, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*XOR dst_reg, src_reg_b*/
|
||||
}
|
||||
void host_x86_XOR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8))
|
||||
fatal("host_x86_XOR32_REG_IMM - dst_reg != src_reg_a\n");
|
||||
|
||||
codegen_addbyte2(block, 0x31, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*XOR dst_reg, src_reg_b*/
|
||||
}
|
||||
|
||||
#endif
|
||||
104
src/codegen_backend_x86-64_ops.h
Normal file
104
src/codegen_backend_x86-64_ops.h
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
void host_x86_ADD8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data);
|
||||
void host_x86_ADD16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data);
|
||||
void host_x86_ADD32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data);
|
||||
void host_x86_ADD64_REG_IMM(codeblock_t *block, int dst_reg, uint64_t imm_data);
|
||||
|
||||
void host_x86_ADD8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
|
||||
void host_x86_ADD16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
|
||||
void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
|
||||
|
||||
void host_x86_AND8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data);
|
||||
void host_x86_AND16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data);
|
||||
void host_x86_AND32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data);
|
||||
|
||||
void host_x86_AND8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
|
||||
void host_x86_AND16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
|
||||
void host_x86_AND32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
|
||||
|
||||
void host_x86_CALL(codeblock_t *block, void *p);
|
||||
|
||||
void host_x86_CMP32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data);
|
||||
void host_x86_CMP64_REG_IMM(codeblock_t *block, int dst_reg, uint64_t imm_data);
|
||||
|
||||
void host_x86_JNZ(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_JZ_short(codeblock_t *block);
|
||||
|
||||
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_SHIFT(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b, int shift);
|
||||
|
||||
void host_x86_MOV8_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data);
|
||||
void host_x86_MOV32_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data);
|
||||
|
||||
void host_x86_MOV8_ABS_REG(codeblock_t *block, void *p, int src_reg);
|
||||
void host_x86_MOV32_ABS_REG(codeblock_t *block, void *p, int src_reg);
|
||||
void host_x86_MOV64_ABS_REG(codeblock_t *block, void *p, int src_reg);
|
||||
|
||||
void host_x86_MOV8_BASE_INDEX_REG(codeblock_t *block, int dst_reg, int base_reg, int index_reg);
|
||||
void host_x86_MOV16_BASE_INDEX_REG(codeblock_t *block, int dst_reg, int base_reg, int index_reg);
|
||||
void host_x86_MOV32_BASE_INDEX_REG(codeblock_t *block, int dst_reg, int base_reg, int index_reg);
|
||||
|
||||
void host_x86_MOV32_REG_ABS(codeblock_t *block, int dst_reg, void *p);
|
||||
|
||||
void host_x86_MOV32_REG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int index_reg);
|
||||
|
||||
void host_x86_MOV64_REG_BASE_INDEX_SHIFT(codeblock_t *block, int dst_reg, int base_reg, int index_reg, int scale);
|
||||
|
||||
void host_x86_MOV8_REG_IMM(codeblock_t *block, int reg, uint16_t imm_data);
|
||||
void host_x86_MOV16_REG_IMM(codeblock_t *block, int reg, uint16_t imm_data);
|
||||
void host_x86_MOV32_REG_IMM(codeblock_t *block, int reg, uint32_t imm_data);
|
||||
|
||||
void host_x86_MOV64_REG_IMM(codeblock_t *block, int reg, uint64_t imm_data);
|
||||
|
||||
void host_x86_MOV8_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
|
||||
void host_x86_MOV16_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
|
||||
void host_x86_MOV32_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
|
||||
|
||||
void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_data);
|
||||
|
||||
void host_x86_MOVZX_BASE_INDEX_32_8(codeblock_t *block, int dst_reg, int base_reg, int index_reg);
|
||||
void host_x86_MOVZX_BASE_INDEX_32_16(codeblock_t *block, int dst_reg, int base_reg, int index_reg);
|
||||
|
||||
void host_x86_MOVZX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg);
|
||||
void host_x86_MOVZX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg);
|
||||
|
||||
void host_x86_MOVZX_REG_ABS_32_8(codeblock_t *block, int dst_reg, void *p);
|
||||
|
||||
void host_x86_OR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data);
|
||||
void host_x86_OR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data);
|
||||
void host_x86_OR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data);
|
||||
|
||||
void host_x86_OR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
|
||||
void host_x86_OR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
|
||||
void host_x86_OR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
|
||||
|
||||
void host_x86_POP(codeblock_t *block, int src_reg);
|
||||
|
||||
void host_x86_PUSH(codeblock_t *block, int src_reg);
|
||||
|
||||
void host_x86_RET(codeblock_t *block);
|
||||
|
||||
void host_x86_SHR32_IMM(codeblock_t *block, int dst_reg, int shift);
|
||||
|
||||
void host_x86_SUB8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data);
|
||||
void host_x86_SUB16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data);
|
||||
void host_x86_SUB32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data);
|
||||
void host_x86_SUB64_REG_IMM(codeblock_t *block, int dst_reg, uint64_t imm_data);
|
||||
|
||||
void host_x86_SUB8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
|
||||
void host_x86_SUB16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
|
||||
void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
|
||||
|
||||
void host_x86_TEST32_REG(codeblock_t *block, int src_reg, int dst_reg);
|
||||
void host_x86_TEST32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data);
|
||||
|
||||
void host_x86_XOR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data);
|
||||
void host_x86_XOR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data);
|
||||
void host_x86_XOR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data);
|
||||
|
||||
void host_x86_XOR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
|
||||
void host_x86_XOR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
|
||||
void host_x86_XOR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
|
||||
|
|
@ -4,6 +4,7 @@
|
|||
#include "codegen.h"
|
||||
#include "codegen_backend.h"
|
||||
#include "codegen_backend_x86-64_defs.h"
|
||||
#include "codegen_backend_x86-64_ops.h"
|
||||
#include "codegen_ir_defs.h"
|
||||
|
||||
#define STACK_ARG0 (0)
|
||||
|
|
@ -11,682 +12,6 @@
|
|||
#define STACK_ARG2 (8)
|
||||
#define STACK_ARG3 (12)
|
||||
|
||||
#define RM_OP_ADD 0x00
|
||||
#define RM_OP_OR 0x08
|
||||
#define RM_OP_AND 0x20
|
||||
#define RM_OP_SUB 0x28
|
||||
#define RM_OP_XOR 0x30
|
||||
|
||||
static inline void codegen_addbyte(codeblock_t *block, uint8_t val)
|
||||
{
|
||||
block->data[block_pos++] = val;
|
||||
if (block_pos >= BLOCK_MAX)
|
||||
{
|
||||
fatal("codegen_addbyte over! %i\n", block_pos);
|
||||
// CPU_BLOCK_END();
|
||||
}
|
||||
}
|
||||
static inline void codegen_addbyte2(codeblock_t *block, uint8_t vala, uint8_t valb)
|
||||
{
|
||||
block->data[block_pos++] = vala;
|
||||
block->data[block_pos++] = valb;
|
||||
if (block_pos >= BLOCK_MAX)
|
||||
{
|
||||
fatal("codegen_addbyte2 over! %i\n", block_pos);
|
||||
CPU_BLOCK_END();
|
||||
}
|
||||
}
|
||||
static inline void codegen_addbyte3(codeblock_t *block, uint8_t vala, uint8_t valb, uint8_t valc)
|
||||
{
|
||||
block->data[block_pos++] = vala;
|
||||
block->data[block_pos++] = valb;
|
||||
block->data[block_pos++] = valc;
|
||||
if (block_pos >= BLOCK_MAX)
|
||||
{
|
||||
fatal("codegen_addbyte3 over! %i\n", block_pos);
|
||||
CPU_BLOCK_END();
|
||||
}
|
||||
}
|
||||
static inline void codegen_addbyte4(codeblock_t *block, uint8_t vala, uint8_t valb, uint8_t valc, uint8_t vald)
|
||||
{
|
||||
block->data[block_pos++] = vala;
|
||||
block->data[block_pos++] = valb;
|
||||
block->data[block_pos++] = valc;
|
||||
block->data[block_pos++] = vald;
|
||||
if (block_pos >= BLOCK_MAX)
|
||||
{
|
||||
fatal("codegen_addbyte4 over! %i\n", block_pos);
|
||||
CPU_BLOCK_END();
|
||||
}
|
||||
}
|
||||
|
||||
static inline void codegen_addword(codeblock_t *block, uint16_t val)
|
||||
{
|
||||
*(uint16_t *)&block->data[block_pos] = val;
|
||||
block_pos += 2;
|
||||
if (block_pos >= BLOCK_MAX)
|
||||
{
|
||||
fatal("codegen_addword over! %i\n", block_pos);
|
||||
CPU_BLOCK_END();
|
||||
}
|
||||
}
|
||||
|
||||
static inline void codegen_addlong(codeblock_t *block, uint32_t val)
|
||||
{
|
||||
*(uint32_t *)&block->data[block_pos] = val;
|
||||
block_pos += 4;
|
||||
if (block_pos >= BLOCK_MAX)
|
||||
{
|
||||
fatal("codegen_addlong over! %i\n", block_pos);
|
||||
CPU_BLOCK_END();
|
||||
}
|
||||
}
|
||||
|
||||
static inline void codegen_addquad(codeblock_t *block, uint64_t val)
|
||||
{
|
||||
*(uint64_t *)&block->data[block_pos] = val;
|
||||
block_pos += 8;
|
||||
if (block_pos >= BLOCK_MAX)
|
||||
{
|
||||
fatal("codegen_addquad over! %i\n", block_pos);
|
||||
CPU_BLOCK_END();
|
||||
}
|
||||
}
|
||||
|
||||
static int is_imm8(uint32_t imm_data)
|
||||
{
|
||||
if (imm_data <= 0x7f || imm_data >= 0xffffff80)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void call(codeblock_t *block, uintptr_t func)
|
||||
{
|
||||
uintptr_t diff = func - (uintptr_t)&block->data[block_pos + 5];
|
||||
|
||||
if (diff >= -0x80000000 && diff < 0x7fffffff)
|
||||
{
|
||||
codegen_addbyte(block, 0xE8); /*CALL*/
|
||||
codegen_addlong(block, (uint32_t)diff);
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte2(block, 0x48, 0xb8); /*MOV RAX, func*/
|
||||
codegen_addquad(block, func);
|
||||
codegen_addbyte2(block, 0xff, 0xd0); /*CALL RAX*/
|
||||
}
|
||||
}
|
||||
|
||||
static void host_x86_ADD8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data)
|
||||
{
|
||||
if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8))
|
||||
fatal("host_x86_ADD8_REG_IMM - dst_reg != src_reg\n");
|
||||
|
||||
if (dst_reg == REG_EAX)
|
||||
codegen_addbyte2(block, 0x04, imm_data); /*ADD EAX, imm_data*/
|
||||
else
|
||||
codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_ADD | (dst_reg & 7), imm_data); /*ADD dst_reg, imm_data*/
|
||||
}
|
||||
static void host_x86_ADD16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data)
|
||||
{
|
||||
if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8))
|
||||
fatal("host_x86_ADD32_REG_IMM - dst_reg != src_reg\n");
|
||||
|
||||
if (is_imm8(imm_data))
|
||||
codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_ADD | (dst_reg & 7), imm_data & 0xff); /*ADD dst_reg, imm_data*/
|
||||
else if (dst_reg == REG_EAX)
|
||||
{
|
||||
codegen_addbyte2(block, 0x66, 0x05); /*AND AX, imm_data*/
|
||||
codegen_addword(block, imm_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_ADD | (dst_reg & 7)); /*ADD dst_reg, imm_data*/
|
||||
codegen_addword(block, imm_data);
|
||||
}
|
||||
}
|
||||
static void host_x86_ADD32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data)
|
||||
{
|
||||
if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8))
|
||||
fatal("host_x86_ADD32_REG_IMM - dst_reg != src_reg\n");
|
||||
|
||||
if (is_imm8(imm_data))
|
||||
codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_ADD | (dst_reg & 7), imm_data & 0xff); /*ADD dst_reg, imm_data*/
|
||||
else if (dst_reg == REG_EAX)
|
||||
{
|
||||
codegen_addbyte(block, 0x05); /*ADD EAX, imm_data*/
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_ADD | (dst_reg & 7)); /*ADD dst_reg, imm_data*/
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
}
|
||||
static void host_x86_ADD8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8))
|
||||
fatal("host_x86_ADD8_REG_IMM - dst_reg != src_reg_a\n");
|
||||
|
||||
codegen_addbyte2(block, 0x00, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*ADD dst_reg, src_reg_b*/
|
||||
}
|
||||
static void host_x86_ADD16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8))
|
||||
fatal("host_x86_ADD16_REG_IMM - dst_reg != src_reg_a\n");
|
||||
|
||||
codegen_addbyte3(block, 0x66, 0x01, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*ADD dst_reg, src_reg_b*/
|
||||
}
|
||||
static void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8))
|
||||
fatal("host_x86_ADD32_REG_IMM - dst_reg != src_reg_a\n");
|
||||
|
||||
codegen_addbyte2(block, 0x01, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*ADD dst_reg, src_reg_b*/
|
||||
}
|
||||
|
||||
static void host_x86_AND8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data)
|
||||
{
|
||||
if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8))
|
||||
fatal("host_x86_AND8_REG_IMM - dst_reg != src_reg\n");
|
||||
|
||||
if (dst_reg == REG_EAX)
|
||||
codegen_addbyte2(block, 0x24, imm_data); /*AND EAX, imm_data*/
|
||||
else
|
||||
codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_AND | (dst_reg & 7), imm_data); /*AND dst_reg, imm_data*/
|
||||
}
|
||||
static void host_x86_AND16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data)
|
||||
{
|
||||
if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8))
|
||||
fatal("host_x86_AND32_REG_IMM - dst_reg != src_reg\n");
|
||||
|
||||
if (is_imm8(imm_data))
|
||||
codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_AND | (dst_reg & 7), imm_data & 0xff); /*AND dst_reg, imm_data*/
|
||||
else if (dst_reg == REG_EAX)
|
||||
{
|
||||
codegen_addbyte2(block, 0x66, 0x25); /*AND AX, imm_data*/
|
||||
codegen_addword(block, imm_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_AND | (dst_reg & 7)); /*AND dst_reg, imm_data*/
|
||||
codegen_addword(block, imm_data);
|
||||
}
|
||||
}
|
||||
static void host_x86_AND32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data)
|
||||
{
|
||||
if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8))
|
||||
fatal("host_x86_AND32_REG_IMM - dst_reg != src_reg\n");
|
||||
|
||||
if (is_imm8(imm_data))
|
||||
codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_AND | (dst_reg & 7), imm_data & 0xff); /*AND dst_reg, imm_data*/
|
||||
else if (dst_reg == REG_EAX)
|
||||
{
|
||||
codegen_addbyte(block, 0x25); /*AND EAX, imm_data*/
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_AND | (dst_reg & 7)); /*AND dst_reg, imm_data*/
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
}
|
||||
static void host_x86_AND8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8))
|
||||
fatal("host_x86_AND8_REG_IMM - dst_reg != src_reg_a\n");
|
||||
|
||||
codegen_addbyte2(block, 0x20, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*AND dst_reg, src_reg_b*/
|
||||
}
|
||||
static void host_x86_AND16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8))
|
||||
fatal("host_x86_AND16_REG_IMM - dst_reg != src_reg_a\n");
|
||||
|
||||
codegen_addbyte3(block, 0x66, 0x21, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*AND dst_reg, src_reg_b*/
|
||||
}
|
||||
static void host_x86_AND32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8))
|
||||
fatal("host_x86_AND32_REG_IMM - dst_reg != src_reg_a\n");
|
||||
|
||||
codegen_addbyte2(block, 0x21, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*AND dst_reg, src_reg_b*/
|
||||
}
|
||||
|
||||
static void host_x86_CALL(codeblock_t *block, void *p)
|
||||
{
|
||||
call(block, (uintptr_t)p);
|
||||
}
|
||||
|
||||
static void host_x86_JNZ(codeblock_t *block, void *p)
|
||||
{
|
||||
codegen_addbyte2(block, 0x0f, 0x85); /*JNZ*/
|
||||
codegen_addlong(block, (uintptr_t)p - (uintptr_t)&block->data[block_pos + 4]);
|
||||
}
|
||||
|
||||
static void host_x86_LEA_REG_REG_SHIFT(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b, int shift)
|
||||
{
|
||||
if ((dst_reg & 8) || (src_reg_a & 8) || (src_reg_b & 8))
|
||||
fatal("host_x86_LEA_REG_REG_SHIFT - bad reg\n");
|
||||
|
||||
codegen_addbyte3(block, 0x8d, 0x04 | ((dst_reg & 7) << 3), /*LEA dst_reg, [Rsrc_reg_a + Rsrc_reg_b * (1 << shift)]*/
|
||||
(shift << 6) | ((src_reg_b & 7) << 3) | (src_reg_a & 7));
|
||||
}
|
||||
|
||||
static void host_x86_MOV8_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data)
|
||||
{
|
||||
int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
|
||||
|
||||
if (offset >= -128 && offset < 127)
|
||||
{
|
||||
codegen_addbyte3(block, 0xc6, 0x45, offset); /*MOVB offset[RBP], imm_data*/
|
||||
codegen_addbyte(block, imm_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((uintptr_t)p >> 32)
|
||||
fatal("host_x86_MOV8_ABS_IMM - out of range %p\n", p);
|
||||
codegen_addbyte3(block, 0xc6, 0x04, 0x25); /*MOVB p, imm_data*/
|
||||
codegen_addlong(block, (uint32_t)(uintptr_t)p);
|
||||
codegen_addbyte(block, imm_data);
|
||||
}
|
||||
}
|
||||
static void host_x86_MOV32_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data)
|
||||
{
|
||||
int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
|
||||
|
||||
if (offset >= -128 && offset < 127)
|
||||
{
|
||||
codegen_addbyte3(block, 0xc7, 0x45, offset); /*MOV offset[RBP], imm_data*/
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((uintptr_t)p >> 32)
|
||||
fatal("host_x86_MOV32_ABS_IMM - out of range %p\n", p);
|
||||
codegen_addbyte3(block, 0xc7, 0x04, 0x25); /*MOV p, imm_data*/
|
||||
codegen_addlong(block, (uint32_t)(uintptr_t)p);
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
}
|
||||
|
||||
static void host_x86_MOV8_ABS_REG(codeblock_t *block, void *p, int src_reg)
|
||||
{
|
||||
int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
|
||||
|
||||
if (src_reg & 8)
|
||||
fatal("host_x86_MOV8_ABS_REG - bad reg\n");
|
||||
|
||||
if (offset >= -128 && offset < 127)
|
||||
{
|
||||
codegen_addbyte3(block, 0x88, 0x45 | ((src_reg & 7) << 3), offset); /*MOVB offset[RBP], src_reg*/
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((uintptr_t)p >> 32)
|
||||
fatal("host_x86_MOV8_ABS_REG - out of range %p\n", p);
|
||||
codegen_addbyte(block, 0x88); /*MOVB [p], src_reg*/
|
||||
codegen_addbyte(block, 0x05 | ((src_reg & 7) << 3));
|
||||
codegen_addlong(block, (uint32_t)(uintptr_t)p);
|
||||
}
|
||||
}
|
||||
static void host_x86_MOV32_ABS_REG(codeblock_t *block, void *p, int src_reg)
|
||||
{
|
||||
int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
|
||||
|
||||
if (src_reg & 8)
|
||||
fatal("host_x86_MOV32_ABS_REG - bad reg\n");
|
||||
|
||||
if (offset >= -128 && offset < 127)
|
||||
{
|
||||
codegen_addbyte3(block, 0x89, 0x45 | ((src_reg & 7) << 3), offset); /*MOV offset[RBP], src_reg*/
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((uintptr_t)p >> 32)
|
||||
fatal("host_x86_MOV32_ABS_REG - out of range %p\n", p);
|
||||
codegen_addbyte(block, 0x89); /*MOV [p], src_reg*/
|
||||
codegen_addbyte(block, 0x05 | ((src_reg & 7) << 3));
|
||||
codegen_addlong(block, (uint32_t)(uintptr_t)p);
|
||||
}
|
||||
}
|
||||
static void host_x86_MOV64_ABS_REG(codeblock_t *block, void *p, int src_reg)
|
||||
{
|
||||
int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
|
||||
|
||||
if (src_reg & 8)
|
||||
fatal("host_x86_MOV64_ABS_REG - bad reg\n");
|
||||
|
||||
if (offset >= -128 && offset < 127)
|
||||
{
|
||||
codegen_addbyte4(block, 0x48, 0x89, 0x45 | ((src_reg & 7) << 3), offset); /*MOV offset[RBP], src_reg*/
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((uintptr_t)p >> 32)
|
||||
fatal("host_x86_MOV64_ABS_REG - out of range %p\n", p);
|
||||
codegen_addbyte4(block, 0x48, 0x89, 0x04 | ((src_reg & 7) << 3), 0x25); /*MOV [p], src_reg*/
|
||||
codegen_addlong(block, (uint32_t)(uintptr_t)p);
|
||||
}
|
||||
}
|
||||
|
||||
static void host_x86_MOV32_REG_ABS(codeblock_t *block, int dst_reg, void *p)
|
||||
{
|
||||
int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
|
||||
|
||||
if (dst_reg & 8)
|
||||
fatal("host_x86_MOV32_REG_ABS reg & 8\n");
|
||||
|
||||
if (offset >= -128 && offset < 127)
|
||||
{
|
||||
codegen_addbyte3(block, 0x8b, 0x45 | ((dst_reg & 7) << 3), offset); /*MOV offset[RBP], src_reg*/
|
||||
}
|
||||
else
|
||||
{
|
||||
fatal("host_x86_MOV32_REG_ABS - out of range\n");
|
||||
codegen_addbyte(block, 0x8b); /*MOV [p], src_reg*/
|
||||
codegen_addbyte(block, 0x05 | ((dst_reg & 7) << 3));
|
||||
codegen_addlong(block, (uint32_t)(uintptr_t)p);
|
||||
}
|
||||
}
|
||||
|
||||
static void host_x86_MOV8_REG_IMM(codeblock_t *block, int reg, uint16_t imm_data)
|
||||
{
|
||||
if (reg >= 8)
|
||||
fatal("host_x86_MOV8_REG_IMM reg >= 4\n");
|
||||
codegen_addbyte2(block, 0xb0 | reg, imm_data); /*MOV reg, imm_data*/
|
||||
}
|
||||
static void host_x86_MOV16_REG_IMM(codeblock_t *block, int reg, uint16_t imm_data)
|
||||
{
|
||||
if (reg & 8)
|
||||
fatal("host_x86_MOV16_REG_IMM reg & 8\n");
|
||||
codegen_addbyte2(block, 0x66, 0xb8 | (reg & 7)); /*MOV reg, imm_data*/
|
||||
codegen_addword(block, imm_data);
|
||||
}
|
||||
static void host_x86_MOV32_REG_IMM(codeblock_t *block, int reg, uint32_t imm_data)
|
||||
{
|
||||
if (reg & 8)
|
||||
fatal("host_x86_MOV32_REG_IMM reg & 8\n");
|
||||
codegen_addbyte(block, 0xb8 | (reg & 7)); /*MOV reg, imm_data*/
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
|
||||
static void host_x86_MOV64_REG_IMM(codeblock_t *block, int reg, uint64_t imm_data)
|
||||
{
|
||||
if (reg & 8)
|
||||
fatal("host_x86_MOV64_REG_IMM reg & 8\n");
|
||||
codegen_addbyte2(block, 0x48, 0xb8 | (reg & 7)); /*MOVQ reg, imm_data*/
|
||||
codegen_addquad(block, imm_data);
|
||||
}
|
||||
|
||||
static void host_x86_MOV8_REG_REG(codeblock_t *block, int dst_reg, int src_reg)
|
||||
{
|
||||
if ((dst_reg & 8) || (src_reg & 8))
|
||||
fatal("host_x86_MOV8_REG_REG - bad reg\n");
|
||||
|
||||
codegen_addbyte2(block, 0x88, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3));
|
||||
}
|
||||
static void host_x86_MOV16_REG_REG(codeblock_t *block, int dst_reg, int src_reg)
|
||||
{
|
||||
if ((dst_reg & 8) || (src_reg & 8))
|
||||
fatal("host_x86_MOV16_REG_REG - bad reg\n");
|
||||
|
||||
codegen_addbyte3(block, 0x66, 0x89, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3));
|
||||
}
|
||||
static void host_x86_MOV32_REG_REG(codeblock_t *block, int dst_reg, int src_reg)
|
||||
{
|
||||
if ((dst_reg & 8) || (src_reg & 8))
|
||||
fatal("host_x86_MOV32_REG_REG - bad reg\n");
|
||||
|
||||
codegen_addbyte2(block, 0x89, 0xc0 | (dst_reg & 7) | ((src_reg & 7) << 3));
|
||||
}
|
||||
|
||||
static void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_data)
|
||||
{
|
||||
if (!offset)
|
||||
{
|
||||
codegen_addbyte3(block, 0xc7, 0x04, 0x24); /*MOV [ESP], imm_data*/
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
else if (offset >= -80 || offset < 0x80)
|
||||
{
|
||||
codegen_addbyte4(block, 0xc7, 0x44, 0x24, offset & 0xff); /*MOV offset[ESP], imm_data*/
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte3(block, 0xc7, 0x84, 0x24); /*MOV offset[ESP], imm_data*/
|
||||
codegen_addlong(block, offset);
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
}
|
||||
|
||||
static void host_x86_MOVZX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg)
|
||||
{
|
||||
if ((dst_reg & 8) || (src_reg & 8))
|
||||
fatal("host_x86_MOVZX_REG_32_8 - bad reg\n");
|
||||
codegen_addbyte3(block, 0x0f, 0xb6, 0xc0 | (dst_reg << 3) | src_reg); /*MOVZX dst_reg, src_reg*/
|
||||
}
|
||||
static void host_x86_MOVZX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg)
|
||||
{
|
||||
if ((dst_reg & 8) || (src_reg & 8))
|
||||
fatal("host_x86_MOVZX_REG_16_8 - bad reg\n");
|
||||
codegen_addbyte3(block, 0x0f, 0xb7, 0xc0 | (dst_reg << 3) | src_reg); /*MOVZX dst_reg, src_reg*/
|
||||
}
|
||||
|
||||
static void host_x86_OR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data)
|
||||
{
|
||||
if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8))
|
||||
fatal("host_x86_OR8_REG_IMM - dst_reg != src_reg\n");
|
||||
|
||||
if (dst_reg == REG_EAX)
|
||||
codegen_addbyte2(block, 0x0c, imm_data); /*OR EAX, imm_data*/
|
||||
else
|
||||
codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_OR | (dst_reg & 7), imm_data); /*OR dst_reg, imm_data*/
|
||||
}
|
||||
static void host_x86_OR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data)
|
||||
{
|
||||
if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8))
|
||||
fatal("host_x86_OR16_REG_IMM - dst_reg != src_reg\n");
|
||||
|
||||
if (is_imm8(imm_data))
|
||||
codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_OR | (dst_reg & 7), imm_data & 0xff); /*OR dst_reg, imm_data*/
|
||||
else if (dst_reg == REG_EAX)
|
||||
{
|
||||
codegen_addbyte2(block, 0x66, 0x0d); /*OR AX, imm_data*/
|
||||
codegen_addword(block, imm_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_OR | (dst_reg & 7)); /*OR dst_reg, imm_data*/
|
||||
codegen_addword(block, imm_data);
|
||||
}
|
||||
}
|
||||
static void host_x86_OR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data)
|
||||
{
|
||||
if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8))
|
||||
fatal("host_x86_OR32_REG_IMM - dst_reg != src_reg\n");
|
||||
|
||||
if (is_imm8(imm_data))
|
||||
codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_OR | (dst_reg & 7), imm_data & 0xff); /*OR dst_reg, imm_data*/
|
||||
else if (dst_reg == REG_EAX)
|
||||
{
|
||||
codegen_addbyte(block, 0x0d); /*OR EAX, imm_data*/
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_OR | (dst_reg & 7)); /*OR dst_reg, imm_data*/
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
}
|
||||
static void host_x86_OR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8))
|
||||
fatal("host_x86_OR8_REG_IMM - dst_reg != src_reg_a\n");
|
||||
|
||||
codegen_addbyte2(block, 0x08, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*OR dst_reg, src_reg_b*/
|
||||
}
|
||||
static void host_x86_OR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8))
|
||||
fatal("host_x86_OR16_REG_IMM - dst_reg != src_reg_a\n");
|
||||
|
||||
codegen_addbyte3(block, 0x66, 0x09, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*OR dst_reg, src_reg_b*/
|
||||
}
|
||||
static void host_x86_OR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8))
|
||||
fatal("host_x86_OR32_REG_IMM - dst_reg != src_reg_a\n");
|
||||
|
||||
codegen_addbyte2(block, 0x09, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*OR dst_reg, src_reg_b*/
|
||||
}
|
||||
|
||||
static void host_x86_SUB8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data)
|
||||
{
|
||||
if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8))
|
||||
fatal("host_x86_SUB8_REG_IMM - dst_reg != src_reg\n");
|
||||
|
||||
if (dst_reg == REG_EAX)
|
||||
codegen_addbyte2(block, 0x2c, imm_data); /*SUB EAX, imm_data*/
|
||||
else
|
||||
codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_SUB | (dst_reg & 7), imm_data); /*SUB dst_reg, imm_data*/
|
||||
}
|
||||
static void host_x86_SUB16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data)
|
||||
{
|
||||
if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8))
|
||||
fatal("host_x86_SUB16_REG_IMM - dst_reg != src_reg\n");
|
||||
|
||||
if (is_imm8(imm_data))
|
||||
codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_SUB | (dst_reg & 7), imm_data & 0xff); /*SUB dst_reg, imm_data*/
|
||||
else if (dst_reg == REG_EAX)
|
||||
{
|
||||
codegen_addbyte2(block, 0x66, 0x2d); /*SUB AX, imm_data*/
|
||||
codegen_addword(block, imm_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_SUB | (dst_reg & 7)); /*SUB dst_reg, imm_data*/
|
||||
codegen_addword(block, imm_data);
|
||||
}
|
||||
}
|
||||
static void host_x86_SUB32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data)
|
||||
{
|
||||
if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8))
|
||||
fatal("host_x86_SUB32_REG_IMM - dst_reg != src_reg\n");
|
||||
|
||||
if (is_imm8(imm_data))
|
||||
codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_SUB | (dst_reg & 7), imm_data & 0xff); /*SUB dst_reg, imm_data*/
|
||||
else if (dst_reg == REG_EAX)
|
||||
{
|
||||
codegen_addbyte(block, 0x2d); /*SUB EAX, imm_data*/
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_SUB | (dst_reg & 7)); /*SUB dst_reg, imm_data*/
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
}
|
||||
static void host_x86_SUB8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8))
|
||||
fatal("host_x86_SUB8_REG_REG - dst_reg != src_reg_a\n");
|
||||
|
||||
codegen_addbyte2(block, 0x28, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*SUB dst_reg, src_reg_b*/
|
||||
}
|
||||
static void host_x86_SUB16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8))
|
||||
fatal("host_x86_SUB16_REG_REG - dst_reg != src_reg_a\n");
|
||||
|
||||
codegen_addbyte3(block, 0x66, 0x29, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*SUB dst_reg, src_reg_b*/
|
||||
}
|
||||
static void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8))
|
||||
fatal("host_x86_SUB32_REG_REG - dst_reg != src_reg_a\n");
|
||||
|
||||
codegen_addbyte2(block, 0x29, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*SUB dst_reg, src_reg_b*/
|
||||
}
|
||||
|
||||
#define MODRM_MOD_REG(rm, reg) (0xc0 | reg | (rm << 3))
|
||||
|
||||
static void host_x86_TEST32_REG(codeblock_t *block, int src_reg, int dst_reg)
|
||||
{
|
||||
if ((dst_reg & 8) || (src_reg & 8))
|
||||
fatal("host_x86_TEST32_REG - bad reg\n");
|
||||
codegen_addbyte2(block, 0x85, MODRM_MOD_REG(dst_reg, src_reg)); /*TEST dst_host_reg, src_host_reg*/
|
||||
}
|
||||
|
||||
static void host_x86_XOR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data)
|
||||
{
|
||||
if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8))
|
||||
fatal("host_x86_XOR8_REG_IMM - dst_reg != src_reg\n");
|
||||
|
||||
if (dst_reg == REG_EAX)
|
||||
codegen_addbyte2(block, 0x34, imm_data); /*XOR EAX, imm_data*/
|
||||
else
|
||||
codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_XOR | (dst_reg & 7), imm_data); /*XOR dst_reg, imm_data*/
|
||||
}
|
||||
static void host_x86_XOR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data)
|
||||
{
|
||||
if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8))
|
||||
fatal("host_x86_XOR16_REG_IMM - dst_reg != src_reg\n");
|
||||
|
||||
if (is_imm8(imm_data))
|
||||
codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_XOR | (dst_reg & 7), imm_data & 0xff); /*XOR dst_reg, imm_data*/
|
||||
else if (dst_reg == REG_EAX)
|
||||
{
|
||||
codegen_addbyte2(block, 0x66, 0x35); /*XOR AX, imm_data*/
|
||||
codegen_addword(block, imm_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_XOR | (dst_reg & 7)); /*XOR dst_reg, imm_data*/
|
||||
codegen_addword(block, imm_data);
|
||||
}
|
||||
}
|
||||
static void host_x86_XOR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data)
|
||||
{
|
||||
if (dst_reg != src_reg || (dst_reg & 8) || (src_reg & 8))
|
||||
fatal("host_x86_XOR32_REG_IMM - dst_reg != src_reg\n");
|
||||
|
||||
if (is_imm8(imm_data))
|
||||
codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_XOR | (dst_reg & 7), imm_data & 0xff); /*XOR dst_reg, imm_data*/
|
||||
else if (dst_reg == REG_EAX)
|
||||
{
|
||||
codegen_addbyte(block, 0x35); /*XOR EAX, imm_data*/
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_XOR | (dst_reg & 7)); /*XOR dst_reg, imm_data*/
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
}
|
||||
static void host_x86_XOR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8))
|
||||
fatal("host_x86_XOR8_REG_IMM - dst_reg != src_reg_a\n");
|
||||
|
||||
codegen_addbyte2(block, 0x30, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*XOR dst_reg, src_reg_b*/
|
||||
}
|
||||
static void host_x86_XOR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8))
|
||||
fatal("host_x86_XOR16_REG_IMM - dst_reg != src_reg_a\n");
|
||||
|
||||
codegen_addbyte3(block, 0x66, 0x31, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*XOR dst_reg, src_reg_b*/
|
||||
}
|
||||
static void host_x86_XOR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
if (dst_reg != src_reg_a || (dst_reg & 8) || (src_reg_b & 8))
|
||||
fatal("host_x86_XOR32_REG_IMM - dst_reg != src_reg_a\n");
|
||||
|
||||
codegen_addbyte2(block, 0x31, 0xc0 | (dst_reg & 7) | ((src_reg_b & 7) << 3)); /*XOR dst_reg, src_reg_b*/
|
||||
}
|
||||
|
||||
#define HOST_REG_GET(reg) ((IREG_GET_SIZE(reg) == IREG_SIZE_BH) ? (IREG_GET_REG((reg) & 3) | 4) : (IREG_GET_REG(reg) & 7))
|
||||
|
||||
#define REG_IS_L(size) (size == IREG_SIZE_L)
|
||||
|
|
@ -807,6 +132,22 @@ static int codegen_CALL_INSTRUCTION_FUNC(codeblock_t *block, uop_t *uop)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_CMP_IMM_JZ(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int src_reg = HOST_REG_GET(uop->src_reg_a_real);
|
||||
int src_size = IREG_GET_SIZE(uop->src_reg_a_real);
|
||||
|
||||
if (REG_IS_L(src_size))
|
||||
{
|
||||
host_x86_CMP32_REG_IMM(block, src_reg, uop->imm_data);
|
||||
}
|
||||
else
|
||||
fatal("CMP_IMM_JZ %02x\n", uop->src_reg_a_real);
|
||||
host_x86_JZ(block, uop->p);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_LOAD_FUNC_ARG0_IMM(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
#if WIN64
|
||||
|
|
@ -836,6 +177,177 @@ static int codegen_LOAD_FUNC_ARG3_IMM(codeblock_t *block, uop_t *uop)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_MEM_LOAD_ABS(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real);
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real);
|
||||
|
||||
host_x86_LEA_REG_IMM(block, REG_ESI, seg_reg, uop->imm_data);
|
||||
if (REG_IS_B(dest_size))
|
||||
{
|
||||
host_x86_CALL(block, codegen_mem_load_byte);
|
||||
}
|
||||
else if (REG_IS_W(dest_size))
|
||||
{
|
||||
host_x86_CALL(block, codegen_mem_load_word);
|
||||
}
|
||||
else if (REG_IS_L(dest_size))
|
||||
{
|
||||
host_x86_CALL(block, codegen_mem_load_long);
|
||||
}
|
||||
else
|
||||
fatal("MEM_LOAD_ABS - %02x\n", uop->dest_reg_a_real);
|
||||
host_x86_TEST32_REG(block, REG_ESI, REG_ESI);
|
||||
host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]);
|
||||
if (REG_IS_B(dest_size))
|
||||
{
|
||||
host_x86_MOV8_REG_REG(block, dest_reg, REG_ECX);
|
||||
}
|
||||
else if (REG_IS_W(dest_size))
|
||||
{
|
||||
host_x86_MOV16_REG_REG(block, dest_reg, REG_ECX);
|
||||
}
|
||||
else if (REG_IS_L(dest_size))
|
||||
{
|
||||
host_x86_MOV32_REG_REG(block, dest_reg, REG_ECX);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_MEM_LOAD_REG(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real);
|
||||
|
||||
host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg);
|
||||
if (REG_IS_B(dest_size))
|
||||
{
|
||||
host_x86_CALL(block, codegen_mem_load_byte);
|
||||
}
|
||||
else if (REG_IS_W(dest_size))
|
||||
{
|
||||
host_x86_CALL(block, codegen_mem_load_word);
|
||||
}
|
||||
else if (REG_IS_L(dest_size))
|
||||
{
|
||||
host_x86_CALL(block, codegen_mem_load_long);
|
||||
}
|
||||
else
|
||||
fatal("MEM_LOAD_REG - %02x\n", uop->dest_reg_a_real);
|
||||
host_x86_TEST32_REG(block, REG_ESI, REG_ESI);
|
||||
host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]);
|
||||
if (REG_IS_B(dest_size))
|
||||
{
|
||||
host_x86_MOV8_REG_REG(block, dest_reg, REG_ECX);
|
||||
// fatal("Here\n");
|
||||
}
|
||||
else if (REG_IS_W(dest_size))
|
||||
{
|
||||
host_x86_MOV16_REG_REG(block, dest_reg, REG_ECX);
|
||||
}
|
||||
else if (REG_IS_L(dest_size))
|
||||
{
|
||||
host_x86_MOV32_REG_REG(block, dest_reg, REG_ECX);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_MEM_STORE_ABS(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int seg_reg = HOST_REG_GET(uop->src_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int src_size = IREG_GET_SIZE(uop->src_reg_b_real);
|
||||
|
||||
host_x86_LEA_REG_IMM(block, REG_ESI, seg_reg, uop->imm_data);
|
||||
if (REG_IS_B(src_size))
|
||||
{
|
||||
host_x86_MOV8_REG_REG(block, REG_ECX, src_reg);
|
||||
host_x86_CALL(block, codegen_mem_store_byte);
|
||||
}
|
||||
else if (REG_IS_W(src_size))
|
||||
{
|
||||
host_x86_MOV16_REG_REG(block, REG_ECX, src_reg);
|
||||
host_x86_CALL(block, codegen_mem_store_word);
|
||||
}
|
||||
else if (REG_IS_L(src_size))
|
||||
{
|
||||
host_x86_MOV32_REG_REG(block, REG_ECX, src_reg);
|
||||
host_x86_CALL(block, codegen_mem_store_long);
|
||||
}
|
||||
else
|
||||
fatal("MEM_STORE_ABS - %02x\n", uop->src_reg_b_real);
|
||||
host_x86_TEST32_REG(block, REG_ESI, REG_ESI);
|
||||
host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_MEM_STORE_IMM_8(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real);
|
||||
|
||||
host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg);
|
||||
host_x86_MOV8_REG_IMM(block, REG_ECX, uop->imm_data);
|
||||
host_x86_CALL(block, codegen_mem_store_byte);
|
||||
host_x86_TEST32_REG(block, REG_ESI, REG_ESI);
|
||||
host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_MEM_STORE_IMM_16(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real);
|
||||
|
||||
host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg);
|
||||
host_x86_MOV16_REG_IMM(block, REG_ECX, uop->imm_data);
|
||||
host_x86_CALL(block, codegen_mem_store_word);
|
||||
host_x86_TEST32_REG(block, REG_ESI, REG_ESI);
|
||||
host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_MEM_STORE_IMM_32(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real);
|
||||
|
||||
host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg);
|
||||
host_x86_MOV32_REG_IMM(block, REG_ECX, uop->imm_data);
|
||||
host_x86_CALL(block, codegen_mem_store_long);
|
||||
host_x86_TEST32_REG(block, REG_ESI, REG_ESI);
|
||||
host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_MEM_STORE_REG(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real), src_reg = HOST_REG_GET(uop->src_reg_c_real);
|
||||
int src_size = IREG_GET_SIZE(uop->src_reg_c_real);
|
||||
|
||||
host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg);
|
||||
if (REG_IS_B(src_size))
|
||||
{
|
||||
host_x86_MOV8_REG_REG(block, REG_ECX, src_reg);
|
||||
host_x86_CALL(block, codegen_mem_store_byte);
|
||||
}
|
||||
else if (REG_IS_W(src_size))
|
||||
{
|
||||
host_x86_MOV16_REG_REG(block, REG_ECX, src_reg);
|
||||
host_x86_CALL(block, codegen_mem_store_word);
|
||||
}
|
||||
else if (REG_IS_L(src_size))
|
||||
{
|
||||
host_x86_MOV32_REG_REG(block, REG_ECX, src_reg);
|
||||
host_x86_CALL(block, codegen_mem_store_long);
|
||||
}
|
||||
else
|
||||
fatal("MEM_STORE_ABS - %02x\n", uop->src_reg_b_real);
|
||||
host_x86_TEST32_REG(block, REG_ESI, REG_ESI);
|
||||
host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_MOV(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);
|
||||
|
|
@ -1077,6 +589,15 @@ const uOpFn uop_handlers[UOP_MAX] =
|
|||
[UOP_STORE_P_IMM & UOP_MASK] = codegen_STORE_PTR_IMM,
|
||||
[UOP_STORE_P_IMM_8 & UOP_MASK] = codegen_STORE_PTR_IMM_8,
|
||||
|
||||
[UOP_MEM_LOAD_ABS & UOP_MASK] = codegen_MEM_LOAD_ABS,
|
||||
[UOP_MEM_LOAD_REG & UOP_MASK] = codegen_MEM_LOAD_REG,
|
||||
|
||||
[UOP_MEM_STORE_ABS & UOP_MASK] = codegen_MEM_STORE_ABS,
|
||||
[UOP_MEM_STORE_REG & UOP_MASK] = codegen_MEM_STORE_REG,
|
||||
[UOP_MEM_STORE_IMM_8 & UOP_MASK] = codegen_MEM_STORE_IMM_8,
|
||||
[UOP_MEM_STORE_IMM_16 & UOP_MASK] = codegen_MEM_STORE_IMM_16,
|
||||
[UOP_MEM_STORE_IMM_32 & UOP_MASK] = codegen_MEM_STORE_IMM_32,
|
||||
|
||||
[UOP_MOV & UOP_MASK] = codegen_MOV,
|
||||
[UOP_MOV_PTR & UOP_MASK] = codegen_MOV_PTR,
|
||||
[UOP_MOV_IMM & UOP_MASK] = codegen_MOV_IMM,
|
||||
|
|
@ -1092,7 +613,9 @@ const uOpFn uop_handlers[UOP_MAX] =
|
|||
[UOP_SUB & UOP_MASK] = codegen_SUB,
|
||||
[UOP_SUB_IMM & UOP_MASK] = codegen_SUB_IMM,
|
||||
[UOP_XOR & UOP_MASK] = codegen_XOR,
|
||||
[UOP_XOR_IMM & UOP_MASK] = codegen_XOR_IMM
|
||||
[UOP_XOR_IMM & UOP_MASK] = codegen_XOR_IMM,
|
||||
|
||||
[UOP_CMP_IMM_JZ & UOP_MASK] = codegen_CMP_IMM_JZ
|
||||
};
|
||||
|
||||
void codegen_direct_read_32(codeblock_t *block, int host_reg, void *p)
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@
|
|||
#include "ibm.h"
|
||||
#include "codegen.h"
|
||||
#include "codegen_backend.h"
|
||||
#include "codegen_backend_x86_defs.h"
|
||||
#include "codegen_backend_x86_ops.h"
|
||||
#include "x86.h"
|
||||
|
||||
#if defined(__linux__) || defined(__APPLE__)
|
||||
|
|
@ -13,6 +15,14 @@
|
|||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
void *codegen_mem_load_byte;
|
||||
void *codegen_mem_load_word;
|
||||
void *codegen_mem_load_long;
|
||||
|
||||
void *codegen_mem_store_byte;
|
||||
void *codegen_mem_store_word;
|
||||
void *codegen_mem_store_long;
|
||||
|
||||
int codegen_host_reg_list[CODEGEN_HOST_REGS] =
|
||||
{
|
||||
REG_EAX,
|
||||
|
|
@ -22,6 +32,164 @@ int codegen_host_reg_list[CODEGEN_HOST_REGS] =
|
|||
|
||||
static void *mem_abrt_rout;
|
||||
|
||||
static void build_load_routine(codeblock_t *block, int size)
|
||||
{
|
||||
uint8_t *branch_offset;
|
||||
uint8_t *misaligned_offset;
|
||||
|
||||
/*In - ESI = address
|
||||
Out - ECX = data, ESI = abrt*/
|
||||
/*MOV ECX, ESI
|
||||
SHR ESI, 12
|
||||
MOV ESI, [readlookup2+ESI*4]
|
||||
CMP ESI, -1
|
||||
JNZ +
|
||||
MOVZX ECX, B[ESI+ECX]
|
||||
XOR ESI,ESI
|
||||
RET
|
||||
* PUSH EAX
|
||||
PUSH EDX
|
||||
PUSH ECX
|
||||
CALL readmemb386l
|
||||
POP ECX
|
||||
POP EDX
|
||||
POP EAX
|
||||
MOVZX ECX, AL
|
||||
RET
|
||||
*/
|
||||
host_x86_MOV32_REG_REG(block, REG_ECX, REG_ESI);
|
||||
host_x86_SHR32_IMM(block, REG_ESI, 12);
|
||||
host_x86_MOV32_REG_ABS_INDEX_SHIFT(block, REG_ESI, readlookup2, REG_ESI, 2);
|
||||
if (size != 1)
|
||||
{
|
||||
host_x86_TEST32_REG_IMM(block, REG_ECX, size-1);
|
||||
misaligned_offset = host_x86_JNZ_short(block);
|
||||
}
|
||||
host_x86_CMP32_REG_IMM(block, REG_ESI, (uint32_t)-1);
|
||||
branch_offset = host_x86_JZ_short(block);
|
||||
if (size == 1)
|
||||
host_x86_MOVZX_BASE_INDEX_32_8(block, REG_ECX, REG_ESI, REG_ECX);
|
||||
else if (size == 2)
|
||||
host_x86_MOVZX_BASE_INDEX_32_16(block, REG_ECX, REG_ESI, REG_ECX);
|
||||
else if (size == 4)
|
||||
host_x86_MOV32_REG_BASE_INDEX(block, REG_ECX, REG_ESI, REG_ECX);
|
||||
else
|
||||
fatal("build_load_routine: size=%i\n", size);
|
||||
host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI, REG_ESI);
|
||||
host_x86_RET(block);
|
||||
|
||||
*branch_offset = (uint8_t)((uintptr_t)&block->data[block_pos] - (uintptr_t)branch_offset) - 1;
|
||||
if (size != 1)
|
||||
*misaligned_offset = (uint8_t)((uintptr_t)&block->data[block_pos] - (uintptr_t)misaligned_offset) - 1;
|
||||
host_x86_PUSH(block, REG_EAX);
|
||||
host_x86_PUSH(block, REG_EDX);
|
||||
host_x86_PUSH(block, REG_ECX);
|
||||
if (size == 1)
|
||||
host_x86_CALL(block, (void *)readmemb386l);
|
||||
else if (size == 2)
|
||||
host_x86_CALL(block, (void *)readmemwl);
|
||||
else if (size == 4)
|
||||
host_x86_CALL(block, (void *)readmemll);
|
||||
host_x86_POP(block, REG_ECX);
|
||||
if (size == 1)
|
||||
host_x86_MOVZX_REG_32_8(block, REG_ECX, REG_EAX);
|
||||
else if (size == 2)
|
||||
host_x86_MOVZX_REG_32_16(block, REG_ECX, REG_EAX);
|
||||
else if (size == 4)
|
||||
host_x86_MOV32_REG_REG(block, REG_ECX, REG_EAX);
|
||||
host_x86_POP(block, REG_EDX);
|
||||
host_x86_POP(block, REG_EAX);
|
||||
host_x86_MOVZX_REG_ABS_32_8(block, REG_ESI, &cpu_state.abrt);
|
||||
host_x86_RET(block);
|
||||
block_pos = (block_pos + 63) & ~63;
|
||||
}
|
||||
|
||||
static void build_store_routine(codeblock_t *block, int size)
|
||||
{
|
||||
uint8_t *branch_offset;
|
||||
uint8_t *misaligned_offset;
|
||||
|
||||
/*In - ECX = data, ESI = address
|
||||
Out - ESI = abrt
|
||||
Corrupts EDI*/
|
||||
/*MOV EDI, ESI
|
||||
SHR ESI, 12
|
||||
MOV ESI, [writelookup2+ESI*4]
|
||||
CMP ESI, -1
|
||||
JNZ +
|
||||
MOV [ESI+EDI], ECX
|
||||
XOR ESI,ESI
|
||||
RET
|
||||
* PUSH EAX
|
||||
PUSH EDX
|
||||
PUSH ECX
|
||||
CALL writememb386l
|
||||
POP ECX
|
||||
POP EDX
|
||||
POP EAX
|
||||
MOVZX ECX, AL
|
||||
RET
|
||||
*/
|
||||
host_x86_MOV32_REG_REG(block, REG_EDI, REG_ESI);
|
||||
host_x86_SHR32_IMM(block, REG_ESI, 12);
|
||||
host_x86_MOV32_REG_ABS_INDEX_SHIFT(block, REG_ESI, writelookup2, REG_ESI, 2);
|
||||
if (size != 1)
|
||||
{
|
||||
host_x86_TEST32_REG_IMM(block, REG_EDI, size-1);
|
||||
misaligned_offset = host_x86_JNZ_short(block);
|
||||
}
|
||||
host_x86_CMP32_REG_IMM(block, REG_ESI, (uint32_t)-1);
|
||||
branch_offset = host_x86_JZ_short(block);
|
||||
if (size == 1)
|
||||
host_x86_MOV8_BASE_INDEX_REG(block, REG_ESI, REG_EDI, REG_ECX);
|
||||
else if (size == 2)
|
||||
host_x86_MOV16_BASE_INDEX_REG(block, REG_ESI, REG_EDI, REG_ECX);
|
||||
else if (size == 4)
|
||||
host_x86_MOV32_BASE_INDEX_REG(block, REG_ESI, REG_EDI, REG_ECX);
|
||||
else
|
||||
fatal("build_store_routine: size=%i\n", size);
|
||||
host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI, REG_ESI);
|
||||
host_x86_RET(block);
|
||||
|
||||
*branch_offset = (uint8_t)((uintptr_t)&block->data[block_pos] - (uintptr_t)branch_offset) - 1;
|
||||
if (size != 1)
|
||||
*misaligned_offset = (uint8_t)((uintptr_t)&block->data[block_pos] - (uintptr_t)misaligned_offset) - 1;
|
||||
host_x86_PUSH(block, REG_EAX);
|
||||
host_x86_PUSH(block, REG_EDX);
|
||||
host_x86_PUSH(block, REG_ECX);
|
||||
host_x86_PUSH(block, REG_EDI);
|
||||
if (size == 1)
|
||||
host_x86_CALL(block, (void *)writememb386l);
|
||||
else if (size == 2)
|
||||
host_x86_CALL(block, (void *)writememwl);
|
||||
else if (size == 4)
|
||||
host_x86_CALL(block, (void *)writememll);
|
||||
host_x86_POP(block, REG_EDI);
|
||||
host_x86_POP(block, REG_ECX);
|
||||
host_x86_POP(block, REG_EDX);
|
||||
host_x86_POP(block, REG_EAX);
|
||||
host_x86_MOVZX_REG_ABS_32_8(block, REG_ESI, &cpu_state.abrt);
|
||||
host_x86_RET(block);
|
||||
block_pos = (block_pos + 63) & ~63;
|
||||
}
|
||||
|
||||
static void build_loadstore_routines(codeblock_t *block)
|
||||
{
|
||||
codegen_mem_load_byte = &codeblock[block_current].data[block_pos];
|
||||
build_load_routine(block, 1);
|
||||
codegen_mem_load_word = &codeblock[block_current].data[block_pos];
|
||||
build_load_routine(block, 2);
|
||||
codegen_mem_load_long = &codeblock[block_current].data[block_pos];
|
||||
build_load_routine(block, 4);
|
||||
|
||||
codegen_mem_store_byte = &codeblock[block_current].data[block_pos];
|
||||
build_store_routine(block, 1);
|
||||
codegen_mem_store_word = &codeblock[block_current].data[block_pos];
|
||||
build_store_routine(block, 2);
|
||||
codegen_mem_store_long = &codeblock[block_current].data[block_pos];
|
||||
build_store_routine(block, 4);
|
||||
}
|
||||
|
||||
void codegen_backend_init()
|
||||
{
|
||||
int c;
|
||||
|
|
@ -67,6 +235,10 @@ void codegen_backend_init()
|
|||
addbyte(0x5d); /*POP EBP*/
|
||||
addbyte(0x5b); /*POP EDX*/
|
||||
addbyte(0xC3); /*RET*/
|
||||
|
||||
block_pos = 64;
|
||||
build_loadstore_routines(&codeblock[block_current]);
|
||||
//fatal("Here\n");
|
||||
|
||||
asm(
|
||||
"fstcw %0\n"
|
||||
|
|
|
|||
|
|
@ -12,4 +12,12 @@
|
|||
|
||||
#define CODEGEN_HOST_REGS 3
|
||||
|
||||
extern void *codegen_mem_load_byte;
|
||||
extern void *codegen_mem_load_word;
|
||||
extern void *codegen_mem_load_long;
|
||||
|
||||
extern void *codegen_mem_store_byte;
|
||||
extern void *codegen_mem_store_word;
|
||||
extern void *codegen_mem_store_long;
|
||||
|
||||
#endif
|
||||
|
|
|
|||
779
src/codegen_backend_x86_ops.c
Normal file
779
src/codegen_backend_x86_ops.c
Normal file
|
|
@ -0,0 +1,779 @@
|
|||
#if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined WIN32 || defined _WIN32 || defined _WIN32
|
||||
|
||||
#include "ibm.h"
|
||||
#include "codegen.h"
|
||||
#include "codegen_backend.h"
|
||||
#include "codegen_backend_x86_defs.h"
|
||||
#include "codegen_backend_x86_ops.h"
|
||||
|
||||
#define RM_OP_ADD 0x00
|
||||
#define RM_OP_OR 0x08
|
||||
#define RM_OP_AND 0x20
|
||||
#define RM_OP_SUB 0x28
|
||||
#define RM_OP_XOR 0x30
|
||||
#define RM_OP_CMP 0x38
|
||||
|
||||
#define RM_OP_SHR 0x28
|
||||
|
||||
static inline void codegen_addbyte(codeblock_t *block, uint8_t val)
|
||||
{
|
||||
block->data[block_pos++] = val;
|
||||
if (block_pos >= BLOCK_MAX)
|
||||
{
|
||||
fatal("codegen_addbyte over! %i\n", block_pos);
|
||||
// CPU_BLOCK_END();
|
||||
}
|
||||
}
|
||||
static inline void codegen_addbyte2(codeblock_t *block, uint8_t vala, uint8_t valb)
|
||||
{
|
||||
block->data[block_pos++] = vala;
|
||||
block->data[block_pos++] = valb;
|
||||
if (block_pos >= BLOCK_MAX)
|
||||
{
|
||||
fatal("codegen_addbyte2 over! %i\n", block_pos);
|
||||
CPU_BLOCK_END();
|
||||
}
|
||||
}
|
||||
static inline void codegen_addbyte3(codeblock_t *block, uint8_t vala, uint8_t valb, uint8_t valc)
|
||||
{
|
||||
block->data[block_pos++] = vala;
|
||||
block->data[block_pos++] = valb;
|
||||
block->data[block_pos++] = valc;
|
||||
if (block_pos >= BLOCK_MAX)
|
||||
{
|
||||
fatal("codegen_addbyte3 over! %i\n", block_pos);
|
||||
CPU_BLOCK_END();
|
||||
}
|
||||
}
|
||||
static inline void codegen_addbyte4(codeblock_t *block, uint8_t vala, uint8_t valb, uint8_t valc, uint8_t vald)
|
||||
{
|
||||
block->data[block_pos++] = vala;
|
||||
block->data[block_pos++] = valb;
|
||||
block->data[block_pos++] = valc;
|
||||
block->data[block_pos++] = vald;
|
||||
if (block_pos >= BLOCK_MAX)
|
||||
{
|
||||
fatal("codegen_addbyte4 over! %i\n", block_pos);
|
||||
CPU_BLOCK_END();
|
||||
}
|
||||
}
|
||||
|
||||
static inline void codegen_addword(codeblock_t *block, uint16_t val)
|
||||
{
|
||||
*(uint16_t *)&block->data[block_pos] = val;
|
||||
block_pos += 2;
|
||||
if (block_pos >= BLOCK_MAX)
|
||||
{
|
||||
fatal("codegen_addword over! %i\n", block_pos);
|
||||
CPU_BLOCK_END();
|
||||
}
|
||||
}
|
||||
|
||||
static inline void codegen_addlong(codeblock_t *block, uint32_t val)
|
||||
{
|
||||
*(uint32_t *)&block->data[block_pos] = val;
|
||||
block_pos += 4;
|
||||
if (block_pos >= BLOCK_MAX)
|
||||
{
|
||||
fatal("codegen_addlong over! %i\n", block_pos);
|
||||
CPU_BLOCK_END();
|
||||
}
|
||||
}
|
||||
|
||||
static inline void codegen_addquad(codeblock_t *block, uint64_t val)
|
||||
{
|
||||
*(uint64_t *)&block->data[block_pos] = val;
|
||||
block_pos += 8;
|
||||
if (block_pos >= BLOCK_MAX)
|
||||
{
|
||||
fatal("codegen_addquad over! %i\n", block_pos);
|
||||
CPU_BLOCK_END();
|
||||
}
|
||||
}
|
||||
|
||||
static int is_imm8(uint32_t imm_data)
|
||||
{
|
||||
if (imm_data <= 0x7f || imm_data >= 0xffffff80)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void host_x86_ADD32_REG_ABS(codeblock_t *block, int dst_reg, int src_reg, void *p)
|
||||
{
|
||||
int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
|
||||
|
||||
if (offset >= -128 && offset < 127)
|
||||
{
|
||||
codegen_addbyte3(block, 0x03, 0x45 | (dst_reg << 3), offset); /*MOV offset[EBP], src_reg*/
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte(block, 0x03); /*MOV [p], src_reg*/
|
||||
codegen_addbyte(block, 0x05 | (dst_reg << 3));
|
||||
codegen_addlong(block, (uint32_t)p);
|
||||
}
|
||||
}
|
||||
|
||||
void host_x86_ADD8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data)
|
||||
{
|
||||
if (dst_reg != src_reg)
|
||||
fatal("host_x86_ADD8_REG_IMM - dst_reg != src_reg\n");
|
||||
|
||||
if (dst_reg == REG_EAX)
|
||||
codegen_addbyte2(block, 0x04, imm_data); /*ADD AL, imm_data*/
|
||||
else
|
||||
codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_ADD | dst_reg, imm_data); /*ADD dst_reg, imm_data*/
|
||||
}
|
||||
void host_x86_ADD16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data)
|
||||
{
|
||||
if (dst_reg != src_reg)
|
||||
fatal("host_x86_ADD16_REG_IMM - dst_reg != src_reg\n");
|
||||
|
||||
if (is_imm8(imm_data))
|
||||
codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_ADD | dst_reg, imm_data & 0xff); /*ADD dst_reg, imm_data*/
|
||||
else if (dst_reg == REG_EAX)
|
||||
{
|
||||
codegen_addbyte2(block, 0x66, 0x05); /*ADD AX, imm_data*/
|
||||
codegen_addword(block, imm_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_ADD | dst_reg); /*ADD dst_reg, imm_data*/
|
||||
codegen_addword(block, imm_data);
|
||||
}
|
||||
}
|
||||
void host_x86_ADD32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data)
|
||||
{
|
||||
if (dst_reg != src_reg)
|
||||
fatal("host_x86_ADD32_REG_IMM - dst_reg != src_reg\n");
|
||||
|
||||
if (is_imm8(imm_data))
|
||||
codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_ADD | dst_reg, imm_data & 0xff); /*ADD dst_reg, imm_data*/
|
||||
else if (dst_reg == REG_EAX)
|
||||
{
|
||||
codegen_addbyte(block, 0x05); /*ADD EAX, imm_data*/
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_ADD | dst_reg); /*ADD dst_reg, imm_data*/
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
}
|
||||
|
||||
void host_x86_ADD8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
if (dst_reg != src_reg_a)
|
||||
fatal("host_x86_ADD8_REG_IMM - dst_reg != src_reg_a\n");
|
||||
|
||||
codegen_addbyte2(block, 0x00, 0xc0 | dst_reg | (src_reg_b << 3)); /*ADD dst_reg, src_reg_b*/
|
||||
}
|
||||
void host_x86_ADD16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
if (dst_reg != src_reg_a)
|
||||
fatal("host_x86_ADD16_REG_IMM - dst_reg != src_reg_a\n");
|
||||
|
||||
codegen_addbyte3(block, 0x66, 0x01, 0xc0 | dst_reg | (src_reg_b << 3)); /*ADD dst_reg, src_reg_b*/
|
||||
}
|
||||
void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
if (dst_reg != src_reg_a)
|
||||
fatal("host_x86_ADD32_REG_IMM - dst_reg != src_reg_a\n");
|
||||
|
||||
codegen_addbyte2(block, 0x01, 0xc0 | dst_reg | (src_reg_b << 3)); /*ADD dst_reg, src_reg_b*/
|
||||
}
|
||||
|
||||
void host_x86_AND8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data)
|
||||
{
|
||||
if (dst_reg != src_reg)
|
||||
fatal("host_x86_AND8_REG_IMM - dst_reg != src_reg\n");
|
||||
|
||||
if (dst_reg == REG_EAX)
|
||||
codegen_addbyte2(block, 0x24, imm_data); /*AND AL, imm_data*/
|
||||
else
|
||||
codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_AND | dst_reg, imm_data); /*AND dst_reg, imm_data*/
|
||||
}
|
||||
void host_x86_AND16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data)
|
||||
{
|
||||
if (dst_reg != src_reg)
|
||||
fatal("host_x86_AND16_REG_IMM - dst_reg != src_reg\n");
|
||||
|
||||
if (is_imm8(imm_data))
|
||||
codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_AND | dst_reg, imm_data & 0xff); /*AND dst_reg, imm_data*/
|
||||
else if (dst_reg == REG_EAX)
|
||||
{
|
||||
codegen_addbyte2(block, 0x66, 0x25); /*AND AX, imm_data*/
|
||||
codegen_addword(block, imm_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_AND | dst_reg); /*AND dst_reg, imm_data*/
|
||||
codegen_addword(block, imm_data);
|
||||
}
|
||||
}
|
||||
void host_x86_AND32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data)
|
||||
{
|
||||
if (dst_reg != src_reg)
|
||||
fatal("host_x86_AND32_REG_IMM - dst_reg != src_reg\n");
|
||||
|
||||
if (is_imm8(imm_data))
|
||||
codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_AND | dst_reg, imm_data & 0xff); /*AND dst_reg, imm_data*/
|
||||
else if (dst_reg == REG_EAX)
|
||||
{
|
||||
codegen_addbyte(block, 0x25); /*AND EAX, imm_data*/
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_AND | dst_reg); /*AND dst_reg, imm_data*/
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
}
|
||||
|
||||
void host_x86_AND8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
if (dst_reg != src_reg_a)
|
||||
fatal("host_x86_AND8_REG_REG - dst_reg != src_reg_a\n");
|
||||
|
||||
codegen_addbyte2(block, 0x20, 0xc0 | dst_reg | (src_reg_b << 3)); /*AND dst_reg, src_reg_b*/
|
||||
}
|
||||
void host_x86_AND16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
if (dst_reg != src_reg_a)
|
||||
fatal("host_x86_AND16_REG_REG - dst_reg != src_reg_a\n");
|
||||
|
||||
codegen_addbyte3(block, 0x66, 0x21, 0xc0 | dst_reg | (src_reg_b << 3)); /*AND dst_reg, src_reg_b*/
|
||||
}
|
||||
void host_x86_AND32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
if (dst_reg != src_reg_a)
|
||||
fatal("host_x86_AND32_REG_REG - dst_reg != src_reg_a\n");
|
||||
|
||||
codegen_addbyte2(block, 0x21, 0xc0 | dst_reg | (src_reg_b << 3)); /*AND dst_reg, src_reg_b*/
|
||||
}
|
||||
|
||||
void host_x86_CALL(codeblock_t *block, void *p)
|
||||
{
|
||||
codegen_addbyte(block, 0xe8); /*CALL*/
|
||||
codegen_addlong(block, (uintptr_t)p - (uintptr_t)&block->data[block_pos + 4]);
|
||||
}
|
||||
|
||||
void host_x86_CMP32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data)
|
||||
{
|
||||
if (is_imm8(imm_data))
|
||||
codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_CMP | dst_reg, imm_data & 0xff); /*CMP dst_reg, imm_data*/
|
||||
else if (dst_reg == REG_EAX)
|
||||
{
|
||||
codegen_addbyte(block, 0x3d); /*CMP EAX, imm_data*/
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_CMP | dst_reg); /*CMP dst_reg, imm_data*/
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
}
|
||||
|
||||
void host_x86_JNZ(codeblock_t *block, void *p)
|
||||
{
|
||||
codegen_addbyte2(block, 0x0f, 0x85); /*JNZ*/
|
||||
codegen_addlong(block, (uintptr_t)p - (uintptr_t)&block->data[block_pos + 4]);
|
||||
}
|
||||
void host_x86_JZ(codeblock_t *block, void *p)
|
||||
{
|
||||
codegen_addbyte2(block, 0x0f, 0x84); /*JZ*/
|
||||
codegen_addlong(block, (uintptr_t)p - (uintptr_t)&block->data[block_pos + 4]);
|
||||
}
|
||||
|
||||
uint8_t *host_x86_JNZ_short(codeblock_t *block)
|
||||
{
|
||||
codegen_addbyte2(block, 0x75, 0); /*JNZ*/
|
||||
return &block->data[block_pos-1];
|
||||
}
|
||||
uint8_t *host_x86_JZ_short(codeblock_t *block)
|
||||
{
|
||||
codegen_addbyte2(block, 0x74, 0); /*JZ*/
|
||||
return &block->data[block_pos-1];
|
||||
}
|
||||
|
||||
void host_x86_LEA_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t offset)
|
||||
{
|
||||
if (offset)
|
||||
{
|
||||
codegen_addbyte2(block, 0x8d, 0x80 | (dst_reg << 3) | src_reg); /*LEA dst_reg, [offset+src_reg]*/
|
||||
codegen_addlong(block, offset);
|
||||
}
|
||||
else
|
||||
codegen_addbyte2(block, 0x8d, 0x00 | (dst_reg << 3) | src_reg); /*LEA dst_reg, [src_reg]*/
|
||||
}
|
||||
|
||||
void host_x86_LEA_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
codegen_addbyte3(block, 0x8d, 0x04 | (dst_reg << 3), (src_reg_b << 3) | src_reg_a); /*LEA dst_reg, [src_reg_a + 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)
|
||||
{
|
||||
codegen_addbyte3(block, 0x8d, 0x04 | (dst_reg << 3), (shift << 6) | (src_reg_b << 3) | src_reg_a); /*LEA dst_reg, [src_reg_a + src_reg_b * (1 << shift)]*/
|
||||
}
|
||||
|
||||
void host_x86_MOV8_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data)
|
||||
{
|
||||
int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
|
||||
|
||||
if (offset >= -128 && offset < 127)
|
||||
{
|
||||
codegen_addbyte3(block, 0xc6, 0x45, offset); /*MOVB offset[EBP], imm_data*/
|
||||
codegen_addbyte(block, imm_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte2(block, 0xc6, 0x05); /*MOVB p, imm_data*/
|
||||
codegen_addlong(block, (uint32_t)p);
|
||||
codegen_addbyte(block, imm_data);
|
||||
}
|
||||
}
|
||||
void host_x86_MOV32_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data)
|
||||
{
|
||||
int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
|
||||
|
||||
if (offset >= -128 && offset < 127)
|
||||
{
|
||||
codegen_addbyte3(block, 0xc7, 0x45, offset); /*MOV offset[EBP], imm_data*/
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte2(block, 0xc7, 0x05); /*MOV p, imm_data*/
|
||||
codegen_addlong(block, (uint32_t)p);
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
}
|
||||
|
||||
void host_x86_MOV8_ABS_REG(codeblock_t *block, void *p, int src_reg)
|
||||
{
|
||||
int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
|
||||
|
||||
if (offset >= -128 && offset < 127)
|
||||
{
|
||||
codegen_addbyte3(block, 0x88, 0x45 | (src_reg << 3), offset); /*MOVB offset[EBP], src_reg*/
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte(block, 0x88); /*MOVB [p], src_reg*/
|
||||
codegen_addbyte(block, 0x05 | (src_reg << 3));
|
||||
codegen_addlong(block, (uint32_t)p);
|
||||
}
|
||||
}
|
||||
void host_x86_MOV32_ABS_REG(codeblock_t *block, void *p, int src_reg)
|
||||
{
|
||||
int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
|
||||
|
||||
if (offset >= -128 && offset < 127)
|
||||
{
|
||||
codegen_addbyte3(block, 0x89, 0x45 | (src_reg << 3), offset); /*MOV offset[EBP], src_reg*/
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte(block, 0x89); /*MOV [p], src_reg*/
|
||||
codegen_addbyte(block, 0x05 | (src_reg << 3));
|
||||
codegen_addlong(block, (uint32_t)p);
|
||||
}
|
||||
}
|
||||
|
||||
void host_x86_MOV8_BASE_INDEX_REG(codeblock_t *block, int base_reg, int idx_reg, int src_reg)
|
||||
{
|
||||
codegen_addbyte3(block, 0x88, 0x04 | (src_reg << 3), base_reg | (idx_reg << 3)); /*MOV B[base_reg + idx_reg], src_reg*/
|
||||
}
|
||||
void host_x86_MOV16_BASE_INDEX_REG(codeblock_t *block, int base_reg, int idx_reg, int src_reg)
|
||||
{
|
||||
codegen_addbyte4(block, 0x66, 0x89, 0x04 | (src_reg << 3), base_reg | (idx_reg << 3)); /*MOV W[base_reg + idx_reg], src_reg*/
|
||||
}
|
||||
void host_x86_MOV32_BASE_INDEX_REG(codeblock_t *block, int base_reg, int idx_reg, int src_reg)
|
||||
{
|
||||
codegen_addbyte3(block, 0x89, 0x04 | (src_reg << 3), base_reg | (idx_reg << 3)); /*MOV L[base_reg + idx_reg], src_reg*/
|
||||
}
|
||||
|
||||
void host_x86_MOV32_REG_ABS(codeblock_t *block, int dst_reg, void *p)
|
||||
{
|
||||
int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
|
||||
|
||||
if (offset >= -128 && offset < 127)
|
||||
{
|
||||
codegen_addbyte3(block, 0x8b, 0x45 | (dst_reg << 3), offset); /*MOV offset[EBP], src_reg*/
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte(block, 0x8b); /*MOV [p], src_reg*/
|
||||
codegen_addbyte(block, 0x05 | (dst_reg << 3));
|
||||
codegen_addlong(block, (uint32_t)p);
|
||||
}
|
||||
}
|
||||
|
||||
void host_x86_MOV32_REG_ABS_INDEX_SHIFT(codeblock_t *block, int dst_reg, void *p, int idx_reg, int shift)
|
||||
{
|
||||
codegen_addbyte3(block, 0x8b, 0x04 | (dst_reg << 3), (shift << 6) | (idx_reg << 3) | 0x05); /*MOV dst_reg, [p + idx_reg << shift]*/
|
||||
codegen_addlong(block, (uint32_t)p);
|
||||
}
|
||||
|
||||
void host_x86_MOV32_REG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg)
|
||||
{
|
||||
codegen_addbyte3(block, 0x8b, 0x04 | (dst_reg << 3), base_reg | (idx_reg << 3)); /*MOV dst_reg, L[base_reg + idx_reg]*/
|
||||
}
|
||||
|
||||
void host_x86_MOV8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data)
|
||||
{
|
||||
codegen_addbyte2(block, 0xb0 + dst_reg, imm_data); /*MOV reg, imm_data*/
|
||||
}
|
||||
void host_x86_MOV16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data)
|
||||
{
|
||||
if (!imm_data)
|
||||
{
|
||||
codegen_addbyte3(block, 0x66, 0x31, 0xc0 | dst_reg | (dst_reg << 3)); /*XOR dst_reg, dst_reg*/
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte2(block, 0x66, 0xb8 + dst_reg); /*MOV reg, imm_data*/
|
||||
codegen_addword(block, imm_data);
|
||||
}
|
||||
}
|
||||
void host_x86_MOV32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data)
|
||||
{
|
||||
if (!imm_data)
|
||||
{
|
||||
codegen_addbyte2(block, 0x31, 0xc0 | dst_reg | (dst_reg << 3)); /*XOR dst_reg, dst_reg*/
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte(block, 0xb8 + dst_reg); /*MOV reg, imm_data*/
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
}
|
||||
|
||||
void host_x86_MOV8_REG_REG(codeblock_t *block, int dst_reg, int src_reg)
|
||||
{
|
||||
codegen_addbyte2(block, 0x88, 0xc0 | dst_reg | (src_reg << 3));
|
||||
}
|
||||
void host_x86_MOV16_REG_REG(codeblock_t *block, int dst_reg, int src_reg)
|
||||
{
|
||||
codegen_addbyte3(block, 0x66, 0x89, 0xc0 | dst_reg | (src_reg << 3));
|
||||
}
|
||||
void host_x86_MOV32_REG_REG(codeblock_t *block, int dst_reg, int src_reg)
|
||||
{
|
||||
codegen_addbyte2(block, 0x89, 0xc0 | dst_reg | (src_reg << 3));
|
||||
}
|
||||
|
||||
void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_data)
|
||||
{
|
||||
if (!offset)
|
||||
{
|
||||
codegen_addbyte3(block, 0xc7, 0x04, 0x24); /*MOV [ESP], imm_data*/
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
else if (offset >= -80 || offset < 0x80)
|
||||
{
|
||||
codegen_addbyte4(block, 0xc7, 0x44, 0x24, offset & 0xff); /*MOV offset[ESP], imm_data*/
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte3(block, 0xc7, 0x84, 0x24); /*MOV offset[ESP], imm_data*/
|
||||
codegen_addlong(block, offset);
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
}
|
||||
|
||||
void host_x86_MOVZX_REG_ABS_32_8(codeblock_t *block, int dst_reg, void *p)
|
||||
{
|
||||
int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
|
||||
|
||||
if (offset >= -128 && offset < 127)
|
||||
{
|
||||
codegen_addbyte4(block, 0x0f, 0xb6, 0x45 | (dst_reg << 3), offset); /*MOV dest_reg, [EBP+offset]*/
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte3(block, 0x0f, 0xb6, 0x05 | (dst_reg << 3)); /*MOVZX dst_reg, [p]*/
|
||||
codegen_addlong(block, (uint32_t)p);
|
||||
}
|
||||
}
|
||||
void host_x86_MOVZX_REG_ABS_32_16(codeblock_t *block, int dst_reg, void *p)
|
||||
{
|
||||
int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
|
||||
|
||||
if (offset >= -128 && offset < 127)
|
||||
{
|
||||
codegen_addbyte4(block, 0x0f, 0xb7, 0x45 | (dst_reg << 3), offset); /*MOV dest_reg, [EBP+offset]*/
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte3(block, 0x0f, 0xb7, 0x05 | (dst_reg << 3)); /*MOVZX dst_reg, [p]*/
|
||||
codegen_addlong(block, (uint32_t)p);
|
||||
}
|
||||
}
|
||||
|
||||
void host_x86_MOVZX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg)
|
||||
{
|
||||
codegen_addbyte3(block, 0x0f, 0xb6, 0xc0 | (dst_reg << 3) | src_reg); /*MOVZX dst_reg, src_reg*/
|
||||
}
|
||||
void host_x86_MOVZX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg)
|
||||
{
|
||||
codegen_addbyte3(block, 0x0f, 0xb7, 0xc0 | (dst_reg << 3) | src_reg); /*MOVZX dst_reg, src_reg*/
|
||||
}
|
||||
|
||||
void host_x86_MOVZX_BASE_INDEX_32_8(codeblock_t *block, int dst_reg, int base_reg, int idx_reg)
|
||||
{
|
||||
codegen_addbyte4(block, 0x0f, 0xb6, 0x04 | (dst_reg << 3), base_reg | (idx_reg << 3)); /*MOVZX dst_reg, B[base_reg + idx_reg]*/
|
||||
}
|
||||
void host_x86_MOVZX_BASE_INDEX_32_16(codeblock_t *block, int dst_reg, int base_reg, int idx_reg)
|
||||
{
|
||||
codegen_addbyte4(block, 0x0f, 0xb7, 0x04 | (dst_reg << 3), base_reg | (idx_reg << 3)); /*MOVZX dst_reg, W[base_reg + idx_reg]*/
|
||||
}
|
||||
|
||||
void host_x86_OR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
if (dst_reg != src_reg_a)
|
||||
fatal("host_x86_OR8_REG_REG - dst_reg != src_reg_a\n");
|
||||
|
||||
codegen_addbyte2(block, 0x08, 0xc0 | dst_reg | (src_reg_b << 3)); /*OR dst_reg, src_reg_b*/
|
||||
}
|
||||
void host_x86_OR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
if (dst_reg != src_reg_a)
|
||||
fatal("host_x86_OR16_REG_REG - dst_reg != src_reg_a\n");
|
||||
|
||||
codegen_addbyte3(block, 0x66, 0x09, 0xc0 | dst_reg | (src_reg_b << 3)); /*OR dst_reg, src_reg_b*/
|
||||
}
|
||||
void host_x86_OR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
if (dst_reg != src_reg_a)
|
||||
fatal("host_x86_OR32_REG_IMM - dst_reg != src_reg_a\n");
|
||||
|
||||
codegen_addbyte2(block, 0x09, 0xc0 | dst_reg | (src_reg_b << 3)); /*OR dst_reg, src_reg_b*/
|
||||
}
|
||||
|
||||
void host_x86_OR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data)
|
||||
{
|
||||
if (dst_reg != src_reg)
|
||||
fatal("host_x86_OR8_REG_IMM - dst_reg != src_reg\n");
|
||||
|
||||
if (dst_reg == REG_EAX)
|
||||
codegen_addbyte2(block, 0x0c, imm_data); /*OR AL, imm_data*/
|
||||
else
|
||||
codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_OR | dst_reg, imm_data); /*OR dst_reg, imm_data*/
|
||||
}
|
||||
void host_x86_OR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data)
|
||||
{
|
||||
if (dst_reg != src_reg)
|
||||
fatal("host_x86_OR16_REG_IMM - dst_reg != src_reg\n");
|
||||
|
||||
if (is_imm8(imm_data))
|
||||
codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_OR | dst_reg, imm_data & 0xff); /*OR dst_reg, imm_data*/
|
||||
else if (dst_reg == REG_EAX)
|
||||
{
|
||||
codegen_addbyte2(block, 0x66, 0x0d); /*OR AX, imm_data*/
|
||||
codegen_addword(block, imm_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_OR | dst_reg); /*OR dst_reg, imm_data*/
|
||||
codegen_addword(block, imm_data);
|
||||
}
|
||||
}
|
||||
void host_x86_OR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data)
|
||||
{
|
||||
if (dst_reg != src_reg)
|
||||
fatal("host_x86_OR32_REG_IMM - dst_reg != src_reg\n");
|
||||
|
||||
if (is_imm8(imm_data))
|
||||
codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_OR | dst_reg, imm_data & 0xff); /*OR dst_reg, imm_data*/
|
||||
else if (dst_reg == REG_EAX)
|
||||
{
|
||||
codegen_addbyte(block, 0x0d); /*OR EAX, imm_data*/
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_OR | dst_reg); /*OR dst_reg, imm_data*/
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
}
|
||||
|
||||
void host_x86_POP(codeblock_t *block, int src_reg)
|
||||
{
|
||||
codegen_addbyte(block, 0x58 | src_reg); /*POP reg*/
|
||||
}
|
||||
|
||||
void host_x86_PUSH(codeblock_t *block, int src_reg)
|
||||
{
|
||||
codegen_addbyte(block, 0x50 | src_reg); /*PUSH reg*/
|
||||
}
|
||||
|
||||
void host_x86_RET(codeblock_t *block)
|
||||
{
|
||||
codegen_addbyte(block, 0xc3); /*RET*/
|
||||
}
|
||||
|
||||
#define MODRM_MOD_REG(rm, reg) (0xc0 | reg | (rm << 3))
|
||||
|
||||
void host_x86_SHR32_IMM(codeblock_t *block, int dst_reg, int shift)
|
||||
{
|
||||
codegen_addbyte3(block, 0xc1, 0xc0 | RM_OP_SHR | dst_reg, shift); /*SHR dst_reg, shift*/
|
||||
}
|
||||
|
||||
void host_x86_SUB8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data)
|
||||
{
|
||||
if (dst_reg != src_reg)
|
||||
fatal("host_x86_SUB8_REG_IMM - dst_reg != src_reg\n");
|
||||
|
||||
if (dst_reg == REG_EAX)
|
||||
codegen_addbyte2(block, 0x2c, imm_data); /*SUB AL, imm_data*/
|
||||
else
|
||||
codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_SUB | dst_reg, imm_data); /*SUB dst_reg, imm_data*/
|
||||
}
|
||||
void host_x86_SUB16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data)
|
||||
{
|
||||
if (dst_reg != src_reg)
|
||||
fatal("host_x86_SUB16_REG_IMM - dst_reg != src_reg\n");
|
||||
|
||||
if (is_imm8(imm_data))
|
||||
codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_SUB | dst_reg, imm_data & 0xff); /*SUB dst_reg, imm_data*/
|
||||
else if (dst_reg == REG_EAX)
|
||||
{
|
||||
codegen_addbyte2(block, 0x66, 0x2d); /*SUB AX, imm_data*/
|
||||
codegen_addword(block, imm_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_SUB | dst_reg); /*SUB dst_reg, imm_data*/
|
||||
codegen_addword(block, imm_data);
|
||||
}
|
||||
}
|
||||
void host_x86_SUB32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data)
|
||||
{
|
||||
if (dst_reg != src_reg)
|
||||
fatal("host_x86_SUB32_REG_IMM - dst_reg != src_reg\n");
|
||||
|
||||
if (is_imm8(imm_data))
|
||||
codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_SUB | dst_reg, imm_data & 0xff); /*SUB dst_reg, imm_data*/
|
||||
else if (dst_reg == REG_EAX)
|
||||
{
|
||||
codegen_addbyte(block, 0x2d); /*SUB EAX, imm_data*/
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_SUB | dst_reg); /*SUB dst_reg, imm_data*/
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
}
|
||||
|
||||
void host_x86_SUB8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
if (dst_reg != src_reg_a)
|
||||
fatal("host_x86_SUB8_REG_REG - dst_reg != src_reg_a\n");
|
||||
|
||||
codegen_addbyte2(block, 0x28, 0xc0 | dst_reg | (src_reg_b << 3)); /*SUB dst_reg, src_reg_b*/
|
||||
}
|
||||
void host_x86_SUB16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
if (dst_reg != src_reg_a)
|
||||
fatal("host_x86_SUB16_REG_REG - dst_reg != src_reg_a\n");
|
||||
|
||||
codegen_addbyte3(block, 0x66, 0x29, 0xc0 | dst_reg | (src_reg_b << 3)); /*SUB dst_reg, src_reg_b*/
|
||||
}
|
||||
void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
if (dst_reg != src_reg_a)
|
||||
fatal("host_x86_SUB32_REG_REG - dst_reg != src_reg_a\n");
|
||||
|
||||
codegen_addbyte2(block, 0x29, 0xc0 | dst_reg | (src_reg_b << 3)); /*SUB dst_reg, src_reg_b*/
|
||||
}
|
||||
|
||||
void host_x86_TEST32_REG(codeblock_t *block, int src_host_reg, int dst_host_reg)
|
||||
{
|
||||
codegen_addbyte2(block, 0x85, MODRM_MOD_REG(dst_host_reg, src_host_reg)); /*TEST dst_host_reg, src_host_reg*/
|
||||
}
|
||||
void host_x86_TEST32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data)
|
||||
{
|
||||
if (dst_reg == REG_EAX)
|
||||
{
|
||||
codegen_addbyte(block, 0xa9); /*TEST EAX, imm_data*/
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte2(block, 0xf7, 0xc0 | dst_reg); /*TEST dst_reg, imm_data*/
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
}
|
||||
|
||||
void host_x86_XOR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
if (dst_reg != src_reg_a)
|
||||
fatal("host_x86_XOR8_REG_REG - dst_reg != src_reg_a\n");
|
||||
|
||||
codegen_addbyte2(block, 0x30, 0xc0 | dst_reg | (src_reg_b << 3)); /*XOR dst_reg, src_reg_b*/
|
||||
}
|
||||
void host_x86_XOR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
if (dst_reg != src_reg_a)
|
||||
fatal("host_x86_XOR16_REG_REG - dst_reg != src_reg_a\n");
|
||||
|
||||
codegen_addbyte3(block, 0x66, 0x31, 0xc0 | dst_reg | (src_reg_b << 3)); /*XOR dst_reg, src_reg_b*/
|
||||
}
|
||||
void host_x86_XOR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
if (dst_reg != src_reg_a)
|
||||
fatal("host_x86_XOR32_REG_IMM - dst_reg != src_reg_a\n");
|
||||
|
||||
codegen_addbyte2(block, 0x31, 0xc0 | dst_reg | (src_reg_b << 3)); /*XOR dst_reg, src_reg_b*/
|
||||
}
|
||||
|
||||
void host_x86_XOR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data)
|
||||
{
|
||||
if (dst_reg != src_reg)
|
||||
fatal("host_x86_XOR8_REG_IMM - dst_reg != src_reg\n");
|
||||
|
||||
if (dst_reg == REG_EAX)
|
||||
codegen_addbyte2(block, 0x34, imm_data); /*XOR AL, imm_data*/
|
||||
else
|
||||
codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_XOR | dst_reg, imm_data); /*XOR dst_reg, imm_data*/
|
||||
}
|
||||
void host_x86_XOR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data)
|
||||
{
|
||||
if (dst_reg != src_reg)
|
||||
fatal("host_x86_XOR16_REG_IMM - dst_reg != src_reg\n");
|
||||
|
||||
if (is_imm8(imm_data))
|
||||
codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_XOR | dst_reg, imm_data & 0xff); /*XOR dst_reg, imm_data*/
|
||||
else if (dst_reg == REG_EAX)
|
||||
{
|
||||
codegen_addbyte2(block, 0x66, 0x35); /*XOR AX, imm_data*/
|
||||
codegen_addword(block, imm_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_XOR | dst_reg); /*XOR dst_reg, imm_data*/
|
||||
codegen_addword(block, imm_data);
|
||||
}
|
||||
}
|
||||
void host_x86_XOR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data)
|
||||
{
|
||||
if (dst_reg != src_reg)
|
||||
fatal("host_x86_XOR32_REG_IMM - dst_reg != src_reg\n");
|
||||
|
||||
if (is_imm8(imm_data))
|
||||
codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_XOR | dst_reg, imm_data & 0xff); /*XOR dst_reg, imm_data*/
|
||||
else if (dst_reg == REG_EAX)
|
||||
{
|
||||
codegen_addbyte(block, 0x35); /*XOR EAX, imm_data*/
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_XOR | dst_reg); /*XOR dst_reg, imm_data*/
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
100
src/codegen_backend_x86_ops.h
Normal file
100
src/codegen_backend_x86_ops.h
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
void host_x86_ADD32_REG_ABS(codeblock_t *block, int dst_reg, int src_reg, void *p);
|
||||
|
||||
void host_x86_ADD8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data);
|
||||
void host_x86_ADD16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data);
|
||||
void host_x86_ADD32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data);
|
||||
|
||||
void host_x86_ADD8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
|
||||
void host_x86_ADD16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
|
||||
void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
|
||||
|
||||
void host_x86_AND8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data);
|
||||
void host_x86_AND16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data);
|
||||
void host_x86_AND32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data);
|
||||
|
||||
void host_x86_AND8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
|
||||
void host_x86_AND16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
|
||||
void host_x86_AND32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
|
||||
|
||||
void host_x86_CALL(codeblock_t *block, void *p);
|
||||
|
||||
void host_x86_CMP32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data);
|
||||
|
||||
void host_x86_JNZ(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_JZ_short(codeblock_t *block);
|
||||
|
||||
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_SHIFT(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b, int shift);
|
||||
|
||||
void host_x86_MOV8_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data);
|
||||
void host_x86_MOV32_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data);
|
||||
|
||||
void host_x86_MOV8_ABS_REG(codeblock_t *block, void *p, int src_reg);
|
||||
void host_x86_MOV32_ABS_REG(codeblock_t *block, void *p, int src_reg);
|
||||
|
||||
void host_x86_MOV8_BASE_INDEX_REG(codeblock_t *block, int base_reg, int idx_reg, int src_reg);
|
||||
void host_x86_MOV16_BASE_INDEX_REG(codeblock_t *block, int base_reg, int idx_reg, int src_reg);
|
||||
void host_x86_MOV32_BASE_INDEX_REG(codeblock_t *block, int base_reg, int idx_reg, int src_reg);
|
||||
|
||||
void host_x86_MOV32_REG_ABS(codeblock_t *block, int dst_reg, void *p);
|
||||
|
||||
void host_x86_MOV32_REG_ABS_INDEX_SHIFT(codeblock_t *block, int dst_reg, void *p, int idx_reg, int shift);
|
||||
|
||||
void host_x86_MOV32_REG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg);
|
||||
|
||||
void host_x86_MOV8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data);
|
||||
void host_x86_MOV16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data);
|
||||
void host_x86_MOV32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data);
|
||||
|
||||
void host_x86_MOV8_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
|
||||
void host_x86_MOV16_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
|
||||
void host_x86_MOV32_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
|
||||
|
||||
void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_data);
|
||||
|
||||
void host_x86_MOVZX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg);
|
||||
void host_x86_MOVZX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg);
|
||||
|
||||
void host_x86_MOVZX_REG_ABS_32_8(codeblock_t *block, int dst_reg, void *p);
|
||||
|
||||
void host_x86_MOVZX_BASE_INDEX_32_8(codeblock_t *block, int dst_reg, int base_reg, int idx_reg);
|
||||
void host_x86_MOVZX_BASE_INDEX_32_16(codeblock_t *block, int dst_reg, int base_reg, int idx_reg);
|
||||
|
||||
void host_x86_OR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
|
||||
void host_x86_OR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
|
||||
void host_x86_OR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
|
||||
|
||||
void host_x86_OR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data);
|
||||
void host_x86_OR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data);
|
||||
void host_x86_OR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data);
|
||||
|
||||
void host_x86_POP(codeblock_t *block, int src_reg);
|
||||
|
||||
void host_x86_PUSH(codeblock_t *block, int src_reg);
|
||||
|
||||
void host_x86_RET(codeblock_t *block);
|
||||
|
||||
void host_x86_SHR32_IMM(codeblock_t *block, int dst_reg, int shift);
|
||||
|
||||
void host_x86_SUB8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data);
|
||||
void host_x86_SUB16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data);
|
||||
void host_x86_SUB32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data);
|
||||
|
||||
void host_x86_SUB8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
|
||||
void host_x86_SUB16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
|
||||
void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
|
||||
|
||||
void host_x86_TEST32_REG(codeblock_t *block, int src_host_reg, int dst_host_reg);
|
||||
void host_x86_TEST32_REG_IMM(codeblock_t *block, int src_host_reg, uint32_t imm_data);
|
||||
|
||||
void host_x86_XOR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
|
||||
void host_x86_XOR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
|
||||
void host_x86_XOR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
|
||||
|
||||
void host_x86_XOR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data);
|
||||
void host_x86_XOR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data);
|
||||
void host_x86_XOR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data);
|
||||
|
|
@ -4,6 +4,7 @@
|
|||
#include "codegen.h"
|
||||
#include "codegen_backend.h"
|
||||
#include "codegen_backend_x86_defs.h"
|
||||
#include "codegen_backend_x86_ops.h"
|
||||
#include "codegen_ir_defs.h"
|
||||
|
||||
#define STACK_ARG0 (0)
|
||||
|
|
@ -11,616 +12,6 @@
|
|||
#define STACK_ARG2 (8)
|
||||
#define STACK_ARG3 (12)
|
||||
|
||||
#define RM_OP_ADD 0x00
|
||||
#define RM_OP_OR 0x08
|
||||
#define RM_OP_AND 0x20
|
||||
#define RM_OP_SUB 0x28
|
||||
#define RM_OP_XOR 0x30
|
||||
|
||||
static inline void codegen_addbyte(codeblock_t *block, uint8_t val)
|
||||
{
|
||||
block->data[block_pos++] = val;
|
||||
if (block_pos >= BLOCK_MAX)
|
||||
{
|
||||
fatal("codegen_addbyte over! %i\n", block_pos);
|
||||
// CPU_BLOCK_END();
|
||||
}
|
||||
}
|
||||
static inline void codegen_addbyte2(codeblock_t *block, uint8_t vala, uint8_t valb)
|
||||
{
|
||||
block->data[block_pos++] = vala;
|
||||
block->data[block_pos++] = valb;
|
||||
if (block_pos >= BLOCK_MAX)
|
||||
{
|
||||
fatal("codegen_addbyte2 over! %i\n", block_pos);
|
||||
CPU_BLOCK_END();
|
||||
}
|
||||
}
|
||||
static inline void codegen_addbyte3(codeblock_t *block, uint8_t vala, uint8_t valb, uint8_t valc)
|
||||
{
|
||||
block->data[block_pos++] = vala;
|
||||
block->data[block_pos++] = valb;
|
||||
block->data[block_pos++] = valc;
|
||||
if (block_pos >= BLOCK_MAX)
|
||||
{
|
||||
fatal("codegen_addbyte3 over! %i\n", block_pos);
|
||||
CPU_BLOCK_END();
|
||||
}
|
||||
}
|
||||
static inline void codegen_addbyte4(codeblock_t *block, uint8_t vala, uint8_t valb, uint8_t valc, uint8_t vald)
|
||||
{
|
||||
block->data[block_pos++] = vala;
|
||||
block->data[block_pos++] = valb;
|
||||
block->data[block_pos++] = valc;
|
||||
block->data[block_pos++] = vald;
|
||||
if (block_pos >= BLOCK_MAX)
|
||||
{
|
||||
fatal("codegen_addbyte4 over! %i\n", block_pos);
|
||||
CPU_BLOCK_END();
|
||||
}
|
||||
}
|
||||
|
||||
static inline void codegen_addword(codeblock_t *block, uint16_t val)
|
||||
{
|
||||
*(uint16_t *)&block->data[block_pos] = val;
|
||||
block_pos += 2;
|
||||
if (block_pos >= BLOCK_MAX)
|
||||
{
|
||||
fatal("codegen_addword over! %i\n", block_pos);
|
||||
CPU_BLOCK_END();
|
||||
}
|
||||
}
|
||||
|
||||
static inline void codegen_addlong(codeblock_t *block, uint32_t val)
|
||||
{
|
||||
*(uint32_t *)&block->data[block_pos] = val;
|
||||
block_pos += 4;
|
||||
if (block_pos >= BLOCK_MAX)
|
||||
{
|
||||
fatal("codegen_addlong over! %i\n", block_pos);
|
||||
CPU_BLOCK_END();
|
||||
}
|
||||
}
|
||||
|
||||
static inline void codegen_addquad(codeblock_t *block, uint64_t val)
|
||||
{
|
||||
*(uint64_t *)&block->data[block_pos] = val;
|
||||
block_pos += 8;
|
||||
if (block_pos >= BLOCK_MAX)
|
||||
{
|
||||
fatal("codegen_addquad over! %i\n", block_pos);
|
||||
CPU_BLOCK_END();
|
||||
}
|
||||
}
|
||||
|
||||
static int is_imm8(uint32_t imm_data)
|
||||
{
|
||||
if (imm_data <= 0x7f || imm_data >= 0xffffff80)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void host_x86_ADD8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data)
|
||||
{
|
||||
if (dst_reg != src_reg)
|
||||
fatal("host_x86_ADD8_REG_IMM - dst_reg != src_reg\n");
|
||||
|
||||
if (dst_reg == REG_EAX)
|
||||
codegen_addbyte2(block, 0x04, imm_data); /*ADD AL, imm_data*/
|
||||
else
|
||||
codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_ADD | dst_reg, imm_data); /*ADD dst_reg, imm_data*/
|
||||
}
|
||||
static void host_x86_ADD16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data)
|
||||
{
|
||||
if (dst_reg != src_reg)
|
||||
fatal("host_x86_ADD16_REG_IMM - dst_reg != src_reg\n");
|
||||
|
||||
if (is_imm8(imm_data))
|
||||
codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_ADD | dst_reg, imm_data & 0xff); /*ADD dst_reg, imm_data*/
|
||||
else if (dst_reg == REG_EAX)
|
||||
{
|
||||
codegen_addbyte2(block, 0x66, 0x05); /*ADD AX, imm_data*/
|
||||
codegen_addword(block, imm_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_ADD | dst_reg); /*ADD dst_reg, imm_data*/
|
||||
codegen_addword(block, imm_data);
|
||||
}
|
||||
}
|
||||
static void host_x86_ADD32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data)
|
||||
{
|
||||
if (dst_reg != src_reg)
|
||||
fatal("host_x86_ADD32_REG_IMM - dst_reg != src_reg\n");
|
||||
|
||||
if (is_imm8(imm_data))
|
||||
codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_ADD | dst_reg, imm_data & 0xff); /*ADD dst_reg, imm_data*/
|
||||
else if (dst_reg == REG_EAX)
|
||||
{
|
||||
codegen_addbyte(block, 0x05); /*ADD EAX, imm_data*/
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_ADD | dst_reg); /*ADD dst_reg, imm_data*/
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
}
|
||||
|
||||
static void host_x86_ADD8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
if (dst_reg != src_reg_a)
|
||||
fatal("host_x86_ADD8_REG_IMM - dst_reg != src_reg_a\n");
|
||||
|
||||
codegen_addbyte2(block, 0x00, 0xc0 | dst_reg | (src_reg_b << 3)); /*ADD dst_reg, src_reg_b*/
|
||||
}
|
||||
static void host_x86_ADD16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
if (dst_reg != src_reg_a)
|
||||
fatal("host_x86_ADD16_REG_IMM - dst_reg != src_reg_a\n");
|
||||
|
||||
codegen_addbyte3(block, 0x66, 0x01, 0xc0 | dst_reg | (src_reg_b << 3)); /*ADD dst_reg, src_reg_b*/
|
||||
}
|
||||
static void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
if (dst_reg != src_reg_a)
|
||||
fatal("host_x86_ADD32_REG_IMM - dst_reg != src_reg_a\n");
|
||||
|
||||
codegen_addbyte2(block, 0x01, 0xc0 | dst_reg | (src_reg_b << 3)); /*ADD dst_reg, src_reg_b*/
|
||||
}
|
||||
|
||||
static void host_x86_AND8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data)
|
||||
{
|
||||
if (dst_reg != src_reg)
|
||||
fatal("host_x86_AND8_REG_IMM - dst_reg != src_reg\n");
|
||||
|
||||
if (dst_reg == REG_EAX)
|
||||
codegen_addbyte2(block, 0x24, imm_data); /*AND AL, imm_data*/
|
||||
else
|
||||
codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_AND | dst_reg, imm_data); /*AND dst_reg, imm_data*/
|
||||
}
|
||||
static void host_x86_AND16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data)
|
||||
{
|
||||
if (dst_reg != src_reg)
|
||||
fatal("host_x86_AND16_REG_IMM - dst_reg != src_reg\n");
|
||||
|
||||
if (is_imm8(imm_data))
|
||||
codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_AND | dst_reg, imm_data & 0xff); /*AND dst_reg, imm_data*/
|
||||
else if (dst_reg == REG_EAX)
|
||||
{
|
||||
codegen_addbyte2(block, 0x66, 0x25); /*AND AX, imm_data*/
|
||||
codegen_addword(block, imm_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_AND | dst_reg); /*AND dst_reg, imm_data*/
|
||||
codegen_addword(block, imm_data);
|
||||
}
|
||||
}
|
||||
static void host_x86_AND32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data)
|
||||
{
|
||||
if (dst_reg != src_reg)
|
||||
fatal("host_x86_AND32_REG_IMM - dst_reg != src_reg\n");
|
||||
|
||||
if (is_imm8(imm_data))
|
||||
codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_AND | dst_reg, imm_data & 0xff); /*AND dst_reg, imm_data*/
|
||||
else if (dst_reg == REG_EAX)
|
||||
{
|
||||
codegen_addbyte(block, 0x25); /*AND EAX, imm_data*/
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_AND | dst_reg); /*AND dst_reg, imm_data*/
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
}
|
||||
|
||||
static void host_x86_AND8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
if (dst_reg != src_reg_a)
|
||||
fatal("host_x86_AND8_REG_REG - dst_reg != src_reg_a\n");
|
||||
|
||||
codegen_addbyte2(block, 0x20, 0xc0 | dst_reg | (src_reg_b << 3)); /*AND dst_reg, src_reg_b*/
|
||||
}
|
||||
static void host_x86_AND16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
if (dst_reg != src_reg_a)
|
||||
fatal("host_x86_AND16_REG_REG - dst_reg != src_reg_a\n");
|
||||
|
||||
codegen_addbyte3(block, 0x66, 0x21, 0xc0 | dst_reg | (src_reg_b << 3)); /*AND dst_reg, src_reg_b*/
|
||||
}
|
||||
static void host_x86_AND32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
if (dst_reg != src_reg_a)
|
||||
fatal("host_x86_AND32_REG_REG - dst_reg != src_reg_a\n");
|
||||
|
||||
codegen_addbyte2(block, 0x21, 0xc0 | dst_reg | (src_reg_b << 3)); /*AND dst_reg, src_reg_b*/
|
||||
}
|
||||
|
||||
static void host_x86_CALL(codeblock_t *block, void *p)
|
||||
{
|
||||
codegen_addbyte(block, 0xe8); /*CALL*/
|
||||
codegen_addlong(block, (uintptr_t)p - (uintptr_t)&block->data[block_pos + 4]);
|
||||
}
|
||||
|
||||
static void host_x86_JNZ(codeblock_t *block, void *p)
|
||||
{
|
||||
codegen_addbyte2(block, 0x0f, 0x85); /*JNZ*/
|
||||
codegen_addlong(block, (uintptr_t)p - (uintptr_t)&block->data[block_pos + 4]);
|
||||
}
|
||||
|
||||
static void host_x86_LEA_REG_REG_SHIFT(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b, int shift)
|
||||
{
|
||||
codegen_addbyte3(block, 0x8d, 0x04 | (dst_reg << 3), (shift << 6) | (src_reg_b << 3) | src_reg_a); /*LEA dst_reg, [src_reg_a + src_reg_b * (1 << shift)]*/
|
||||
}
|
||||
|
||||
static void host_x86_MOV8_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data)
|
||||
{
|
||||
int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
|
||||
|
||||
if (offset >= -128 && offset < 127)
|
||||
{
|
||||
codegen_addbyte3(block, 0xc6, 0x45, offset); /*MOVB offset[EBP], imm_data*/
|
||||
codegen_addbyte(block, imm_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte2(block, 0xc6, 0x05); /*MOVB p, imm_data*/
|
||||
codegen_addlong(block, (uint32_t)p);
|
||||
codegen_addbyte(block, imm_data);
|
||||
}
|
||||
}
|
||||
static void host_x86_MOV32_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data)
|
||||
{
|
||||
int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
|
||||
|
||||
if (offset >= -128 && offset < 127)
|
||||
{
|
||||
codegen_addbyte3(block, 0xc7, 0x45, offset); /*MOV offset[EBP], imm_data*/
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte2(block, 0xc7, 0x05); /*MOV p, imm_data*/
|
||||
codegen_addlong(block, (uint32_t)p);
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
}
|
||||
|
||||
static void host_x86_MOV8_ABS_REG(codeblock_t *block, void *p, int src_reg)
|
||||
{
|
||||
int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
|
||||
|
||||
if (offset >= -128 && offset < 127)
|
||||
{
|
||||
codegen_addbyte3(block, 0x88, 0x45 | (src_reg << 3), offset); /*MOVB offset[EBP], src_reg*/
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte(block, 0x88); /*MOVB [p], src_reg*/
|
||||
codegen_addbyte(block, 0x05 | (src_reg << 3));
|
||||
codegen_addlong(block, (uint32_t)p);
|
||||
}
|
||||
}
|
||||
static void host_x86_MOV32_ABS_REG(codeblock_t *block, void *p, int src_reg)
|
||||
{
|
||||
int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
|
||||
|
||||
if (offset >= -128 && offset < 127)
|
||||
{
|
||||
codegen_addbyte3(block, 0x89, 0x45 | (src_reg << 3), offset); /*MOV offset[EBP], src_reg*/
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte(block, 0x89); /*MOV [p], src_reg*/
|
||||
codegen_addbyte(block, 0x05 | (src_reg << 3));
|
||||
codegen_addlong(block, (uint32_t)p);
|
||||
}
|
||||
}
|
||||
|
||||
static void host_x86_MOV32_REG_ABS(codeblock_t *block, int dst_reg, void *p)
|
||||
{
|
||||
int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
|
||||
|
||||
if (offset >= -128 && offset < 127)
|
||||
{
|
||||
codegen_addbyte3(block, 0x8b, 0x45 | (dst_reg << 3), offset); /*MOV offset[EBP], src_reg*/
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte(block, 0x8b); /*MOV [p], src_reg*/
|
||||
codegen_addbyte(block, 0x05 | (dst_reg << 3));
|
||||
codegen_addlong(block, (uint32_t)p);
|
||||
}
|
||||
}
|
||||
|
||||
static void host_x86_MOV8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data)
|
||||
{
|
||||
codegen_addbyte2(block, 0xb0 + dst_reg, imm_data); /*MOV reg, imm_data*/
|
||||
}
|
||||
static void host_x86_MOV16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data)
|
||||
{
|
||||
if (!imm_data)
|
||||
{
|
||||
codegen_addbyte3(block, 0x66, 0x31, 0xc0 | dst_reg | (dst_reg << 3)); /*XOR dst_reg, dst_reg*/
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte2(block, 0x66, 0xb8 + dst_reg); /*MOV reg, imm_data*/
|
||||
codegen_addword(block, imm_data);
|
||||
}
|
||||
}
|
||||
static void host_x86_MOV32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data)
|
||||
{
|
||||
if (!imm_data)
|
||||
{
|
||||
codegen_addbyte2(block, 0x31, 0xc0 | dst_reg | (dst_reg << 3)); /*XOR dst_reg, dst_reg*/
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte(block, 0xb8 + dst_reg); /*MOV reg, imm_data*/
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
}
|
||||
|
||||
static void host_x86_MOV8_REG_REG(codeblock_t *block, int dst_reg, int src_reg)
|
||||
{
|
||||
codegen_addbyte2(block, 0x88, 0xc0 | dst_reg | (src_reg << 3));
|
||||
}
|
||||
static void host_x86_MOV16_REG_REG(codeblock_t *block, int dst_reg, int src_reg)
|
||||
{
|
||||
codegen_addbyte3(block, 0x66, 0x89, 0xc0 | dst_reg | (src_reg << 3));
|
||||
}
|
||||
static void host_x86_MOV32_REG_REG(codeblock_t *block, int dst_reg, int src_reg)
|
||||
{
|
||||
codegen_addbyte2(block, 0x89, 0xc0 | dst_reg | (src_reg << 3));
|
||||
}
|
||||
|
||||
static void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_data)
|
||||
{
|
||||
if (!offset)
|
||||
{
|
||||
codegen_addbyte3(block, 0xc7, 0x04, 0x24); /*MOV [ESP], imm_data*/
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
else if (offset >= -80 || offset < 0x80)
|
||||
{
|
||||
codegen_addbyte4(block, 0xc7, 0x44, 0x24, offset & 0xff); /*MOV offset[ESP], imm_data*/
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte3(block, 0xc7, 0x84, 0x24); /*MOV offset[ESP], imm_data*/
|
||||
codegen_addlong(block, offset);
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
}
|
||||
|
||||
static void host_x86_MOVZX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg)
|
||||
{
|
||||
codegen_addbyte3(block, 0x0f, 0xb6, 0xc0 | (dst_reg << 3) | src_reg); /*MOVZX dst_reg, src_reg*/
|
||||
}
|
||||
static void host_x86_MOVZX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg)
|
||||
{
|
||||
codegen_addbyte3(block, 0x0f, 0xb7, 0xc0 | (dst_reg << 3) | src_reg); /*MOVZX dst_reg, src_reg*/
|
||||
}
|
||||
|
||||
static void host_x86_OR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
if (dst_reg != src_reg_a)
|
||||
fatal("host_x86_OR8_REG_REG - dst_reg != src_reg_a\n");
|
||||
|
||||
codegen_addbyte2(block, 0x08, 0xc0 | dst_reg | (src_reg_b << 3)); /*OR dst_reg, src_reg_b*/
|
||||
}
|
||||
static void host_x86_OR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
if (dst_reg != src_reg_a)
|
||||
fatal("host_x86_OR16_REG_REG - dst_reg != src_reg_a\n");
|
||||
|
||||
codegen_addbyte3(block, 0x66, 0x09, 0xc0 | dst_reg | (src_reg_b << 3)); /*OR dst_reg, src_reg_b*/
|
||||
}
|
||||
static void host_x86_OR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
if (dst_reg != src_reg_a)
|
||||
fatal("host_x86_OR32_REG_IMM - dst_reg != src_reg_a\n");
|
||||
|
||||
codegen_addbyte2(block, 0x09, 0xc0 | dst_reg | (src_reg_b << 3)); /*OR dst_reg, src_reg_b*/
|
||||
}
|
||||
|
||||
static void host_x86_OR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data)
|
||||
{
|
||||
if (dst_reg != src_reg)
|
||||
fatal("host_x86_OR8_REG_IMM - dst_reg != src_reg\n");
|
||||
|
||||
if (dst_reg == REG_EAX)
|
||||
codegen_addbyte2(block, 0x0c, imm_data); /*OR AL, imm_data*/
|
||||
else
|
||||
codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_OR | dst_reg, imm_data); /*OR dst_reg, imm_data*/
|
||||
}
|
||||
static void host_x86_OR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data)
|
||||
{
|
||||
if (dst_reg != src_reg)
|
||||
fatal("host_x86_OR16_REG_IMM - dst_reg != src_reg\n");
|
||||
|
||||
if (is_imm8(imm_data))
|
||||
codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_OR | dst_reg, imm_data & 0xff); /*OR dst_reg, imm_data*/
|
||||
else if (dst_reg == REG_EAX)
|
||||
{
|
||||
codegen_addbyte2(block, 0x66, 0x0d); /*OR AX, imm_data*/
|
||||
codegen_addword(block, imm_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_OR | dst_reg); /*OR dst_reg, imm_data*/
|
||||
codegen_addword(block, imm_data);
|
||||
}
|
||||
}
|
||||
static void host_x86_OR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data)
|
||||
{
|
||||
if (dst_reg != src_reg)
|
||||
fatal("host_x86_OR32_REG_IMM - dst_reg != src_reg\n");
|
||||
|
||||
if (is_imm8(imm_data))
|
||||
codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_OR | dst_reg, imm_data & 0xff); /*OR dst_reg, imm_data*/
|
||||
else if (dst_reg == REG_EAX)
|
||||
{
|
||||
codegen_addbyte(block, 0x0d); /*OR EAX, imm_data*/
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_OR | dst_reg); /*OR dst_reg, imm_data*/
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
}
|
||||
|
||||
#define MODRM_MOD_REG(rm, reg) (0xc0 | reg | (rm << 3))
|
||||
|
||||
static void host_x86_SUB8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data)
|
||||
{
|
||||
if (dst_reg != src_reg)
|
||||
fatal("host_x86_SUB8_REG_IMM - dst_reg != src_reg\n");
|
||||
|
||||
if (dst_reg == REG_EAX)
|
||||
codegen_addbyte2(block, 0x2c, imm_data); /*SUB AL, imm_data*/
|
||||
else
|
||||
codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_SUB | dst_reg, imm_data); /*SUB dst_reg, imm_data*/
|
||||
}
|
||||
static void host_x86_SUB16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data)
|
||||
{
|
||||
if (dst_reg != src_reg)
|
||||
fatal("host_x86_SUB16_REG_IMM - dst_reg != src_reg\n");
|
||||
|
||||
if (is_imm8(imm_data))
|
||||
codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_SUB | dst_reg, imm_data & 0xff); /*SUB dst_reg, imm_data*/
|
||||
else if (dst_reg == REG_EAX)
|
||||
{
|
||||
codegen_addbyte2(block, 0x66, 0x2d); /*SUB AX, imm_data*/
|
||||
codegen_addword(block, imm_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_SUB | dst_reg); /*SUB dst_reg, imm_data*/
|
||||
codegen_addword(block, imm_data);
|
||||
}
|
||||
}
|
||||
static void host_x86_SUB32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data)
|
||||
{
|
||||
if (dst_reg != src_reg)
|
||||
fatal("host_x86_SUB32_REG_IMM - dst_reg != src_reg\n");
|
||||
|
||||
if (is_imm8(imm_data))
|
||||
codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_SUB | dst_reg, imm_data & 0xff); /*SUB dst_reg, imm_data*/
|
||||
else if (dst_reg == REG_EAX)
|
||||
{
|
||||
codegen_addbyte(block, 0x2d); /*SUB EAX, imm_data*/
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_SUB | dst_reg); /*SUB dst_reg, imm_data*/
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
}
|
||||
|
||||
static void host_x86_SUB8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
if (dst_reg != src_reg_a)
|
||||
fatal("host_x86_SUB8_REG_REG - dst_reg != src_reg_a\n");
|
||||
|
||||
codegen_addbyte2(block, 0x28, 0xc0 | dst_reg | (src_reg_b << 3)); /*SUB dst_reg, src_reg_b*/
|
||||
}
|
||||
static void host_x86_SUB16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
if (dst_reg != src_reg_a)
|
||||
fatal("host_x86_SUB16_REG_REG - dst_reg != src_reg_a\n");
|
||||
|
||||
codegen_addbyte3(block, 0x66, 0x29, 0xc0 | dst_reg | (src_reg_b << 3)); /*SUB dst_reg, src_reg_b*/
|
||||
}
|
||||
static void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
if (dst_reg != src_reg_a)
|
||||
fatal("host_x86_SUB32_REG_REG - dst_reg != src_reg_a\n");
|
||||
|
||||
codegen_addbyte2(block, 0x29, 0xc0 | dst_reg | (src_reg_b << 3)); /*SUB dst_reg, src_reg_b*/
|
||||
}
|
||||
|
||||
static void host_x86_TEST32_REG(codeblock_t *block, int src_host_reg, int dst_host_reg)
|
||||
{
|
||||
codegen_addbyte2(block, 0x85, MODRM_MOD_REG(dst_host_reg, src_host_reg)); /*TEST dst_host_reg, src_host_reg*/
|
||||
}
|
||||
|
||||
static void host_x86_XOR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
if (dst_reg != src_reg_a)
|
||||
fatal("host_x86_XOR8_REG_REG - dst_reg != src_reg_a\n");
|
||||
|
||||
codegen_addbyte2(block, 0x30, 0xc0 | dst_reg | (src_reg_b << 3)); /*XOR dst_reg, src_reg_b*/
|
||||
}
|
||||
static void host_x86_XOR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
if (dst_reg != src_reg_a)
|
||||
fatal("host_x86_XOR16_REG_REG - dst_reg != src_reg_a\n");
|
||||
|
||||
codegen_addbyte3(block, 0x66, 0x31, 0xc0 | dst_reg | (src_reg_b << 3)); /*XOR dst_reg, src_reg_b*/
|
||||
}
|
||||
static void host_x86_XOR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b)
|
||||
{
|
||||
if (dst_reg != src_reg_a)
|
||||
fatal("host_x86_XOR32_REG_IMM - dst_reg != src_reg_a\n");
|
||||
|
||||
codegen_addbyte2(block, 0x31, 0xc0 | dst_reg | (src_reg_b << 3)); /*XOR dst_reg, src_reg_b*/
|
||||
}
|
||||
|
||||
static void host_x86_XOR8_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint8_t imm_data)
|
||||
{
|
||||
if (dst_reg != src_reg)
|
||||
fatal("host_x86_XOR8_REG_IMM - dst_reg != src_reg\n");
|
||||
|
||||
if (dst_reg == REG_EAX)
|
||||
codegen_addbyte2(block, 0x34, imm_data); /*XOR AL, imm_data*/
|
||||
else
|
||||
codegen_addbyte3(block, 0x80, 0xc0 | RM_OP_XOR | dst_reg, imm_data); /*XOR dst_reg, imm_data*/
|
||||
}
|
||||
static void host_x86_XOR16_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint16_t imm_data)
|
||||
{
|
||||
if (dst_reg != src_reg)
|
||||
fatal("host_x86_XOR16_REG_IMM - dst_reg != src_reg\n");
|
||||
|
||||
if (is_imm8(imm_data))
|
||||
codegen_addbyte4(block, 0x66, 0x83, 0xc0 | RM_OP_XOR | dst_reg, imm_data & 0xff); /*XOR dst_reg, imm_data*/
|
||||
else if (dst_reg == REG_EAX)
|
||||
{
|
||||
codegen_addbyte2(block, 0x66, 0x35); /*XOR AX, imm_data*/
|
||||
codegen_addword(block, imm_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte3(block, 0x66, 0x81, 0xc0 | RM_OP_XOR | dst_reg); /*XOR dst_reg, imm_data*/
|
||||
codegen_addword(block, imm_data);
|
||||
}
|
||||
}
|
||||
static void host_x86_XOR32_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm_data)
|
||||
{
|
||||
if (dst_reg != src_reg)
|
||||
fatal("host_x86_XOR32_REG_IMM - dst_reg != src_reg\n");
|
||||
|
||||
if (is_imm8(imm_data))
|
||||
codegen_addbyte3(block, 0x83, 0xc0 | RM_OP_XOR | dst_reg, imm_data & 0xff); /*XOR dst_reg, imm_data*/
|
||||
else if (dst_reg == REG_EAX)
|
||||
{
|
||||
codegen_addbyte(block, 0x35); /*XOR EAX, imm_data*/
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
codegen_addbyte2(block, 0x81, 0xc0 | RM_OP_XOR | dst_reg); /*XOR dst_reg, imm_data*/
|
||||
codegen_addlong(block, imm_data);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*void codegen_debug()
|
||||
{
|
||||
pclog(" %04x:%04x : %08x %08x %08x %08x\n", CS, cpu_state.pc, AX, BX, CX, DX);
|
||||
|
|
@ -752,6 +143,22 @@ static int codegen_CALL_INSTRUCTION_FUNC(codeblock_t *block, uop_t *uop)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_CMP_IMM_JZ(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int src_reg = HOST_REG_GET(uop->src_reg_a_real);
|
||||
int src_size = IREG_GET_SIZE(uop->src_reg_a_real);
|
||||
|
||||
if (REG_IS_L(src_size))
|
||||
{
|
||||
host_x86_CMP32_REG_IMM(block, src_reg, uop->imm_data);
|
||||
}
|
||||
else
|
||||
fatal("CMP_IMM_JZ %02x\n", uop->src_reg_a_real);
|
||||
host_x86_JZ(block, uop->p);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_LOAD_FUNC_ARG0_IMM(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
host_x86_MOV32_STACK_IMM(block, STACK_ARG0, uop->imm_data);
|
||||
|
|
@ -773,6 +180,176 @@ static int codegen_LOAD_FUNC_ARG3_IMM(codeblock_t *block, uop_t *uop)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_MEM_LOAD_ABS(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real);
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real);
|
||||
|
||||
host_x86_LEA_REG_IMM(block, REG_ESI, seg_reg, uop->imm_data);
|
||||
if (REG_IS_B(dest_size))
|
||||
{
|
||||
host_x86_CALL(block, codegen_mem_load_byte);
|
||||
}
|
||||
else if (REG_IS_W(dest_size))
|
||||
{
|
||||
host_x86_CALL(block, codegen_mem_load_word);
|
||||
}
|
||||
else if (REG_IS_L(dest_size))
|
||||
{
|
||||
host_x86_CALL(block, codegen_mem_load_long);
|
||||
}
|
||||
else
|
||||
fatal("MEM_LOAD_ABS - %02x\n", uop->dest_reg_a_real);
|
||||
host_x86_TEST32_REG(block, REG_ESI, REG_ESI);
|
||||
host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]);
|
||||
if (REG_IS_B(dest_size))
|
||||
{
|
||||
host_x86_MOV8_REG_REG(block, dest_reg, REG_ECX);
|
||||
}
|
||||
else if (REG_IS_W(dest_size))
|
||||
{
|
||||
host_x86_MOV16_REG_REG(block, dest_reg, REG_ECX);
|
||||
}
|
||||
else if (REG_IS_L(dest_size))
|
||||
{
|
||||
host_x86_MOV32_REG_REG(block, dest_reg, REG_ECX);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_MEM_LOAD_REG(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int dest_reg = HOST_REG_GET(uop->dest_reg_a_real), seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int dest_size = IREG_GET_SIZE(uop->dest_reg_a_real);
|
||||
|
||||
host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg);
|
||||
if (REG_IS_B(dest_size))
|
||||
{
|
||||
host_x86_CALL(block, codegen_mem_load_byte);
|
||||
}
|
||||
else if (REG_IS_W(dest_size))
|
||||
{
|
||||
host_x86_CALL(block, codegen_mem_load_word);
|
||||
}
|
||||
else if (REG_IS_L(dest_size))
|
||||
{
|
||||
host_x86_CALL(block, codegen_mem_load_long);
|
||||
}
|
||||
else
|
||||
fatal("MEM_LOAD_REG - %02x\n", uop->dest_reg_a_real);
|
||||
host_x86_TEST32_REG(block, REG_ESI, REG_ESI);
|
||||
host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]);
|
||||
if (REG_IS_B(dest_size))
|
||||
{
|
||||
host_x86_MOV8_REG_REG(block, dest_reg, REG_ECX);
|
||||
}
|
||||
else if (REG_IS_W(dest_size))
|
||||
{
|
||||
host_x86_MOV16_REG_REG(block, dest_reg, REG_ECX);
|
||||
}
|
||||
else if (REG_IS_L(dest_size))
|
||||
{
|
||||
host_x86_MOV32_REG_REG(block, dest_reg, REG_ECX);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_MEM_STORE_ABS(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int seg_reg = HOST_REG_GET(uop->src_reg_a_real), src_reg = HOST_REG_GET(uop->src_reg_b_real);
|
||||
int src_size = IREG_GET_SIZE(uop->src_reg_b_real);
|
||||
|
||||
host_x86_LEA_REG_IMM(block, REG_ESI, seg_reg, uop->imm_data);
|
||||
if (REG_IS_B(src_size))
|
||||
{
|
||||
host_x86_MOV8_REG_REG(block, REG_ECX, src_reg);
|
||||
host_x86_CALL(block, codegen_mem_store_byte);
|
||||
}
|
||||
else if (REG_IS_W(src_size))
|
||||
{
|
||||
host_x86_MOV16_REG_REG(block, REG_ECX, src_reg);
|
||||
host_x86_CALL(block, codegen_mem_store_word);
|
||||
}
|
||||
else if (REG_IS_L(src_size))
|
||||
{
|
||||
host_x86_MOV32_REG_REG(block, REG_ECX, src_reg);
|
||||
host_x86_CALL(block, codegen_mem_store_long);
|
||||
}
|
||||
else
|
||||
fatal("MEM_STORE_ABS - %02x\n", uop->src_reg_b_real);
|
||||
host_x86_TEST32_REG(block, REG_ESI, REG_ESI);
|
||||
host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_MEM_STORE_REG(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real), src_reg = HOST_REG_GET(uop->src_reg_c_real);
|
||||
int src_size = IREG_GET_SIZE(uop->src_reg_c_real);
|
||||
|
||||
host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg);
|
||||
if (REG_IS_B(src_size))
|
||||
{
|
||||
host_x86_MOV8_REG_REG(block, REG_ECX, src_reg);
|
||||
host_x86_CALL(block, codegen_mem_store_byte);
|
||||
}
|
||||
else if (REG_IS_W(src_size))
|
||||
{
|
||||
host_x86_MOV16_REG_REG(block, REG_ECX, src_reg);
|
||||
host_x86_CALL(block, codegen_mem_store_word);
|
||||
}
|
||||
else if (REG_IS_L(src_size))
|
||||
{
|
||||
host_x86_MOV32_REG_REG(block, REG_ECX, src_reg);
|
||||
host_x86_CALL(block, codegen_mem_store_long);
|
||||
}
|
||||
else
|
||||
fatal("MEM_STORE_ABS - %02x\n", uop->src_reg_b_real);
|
||||
host_x86_TEST32_REG(block, REG_ESI, REG_ESI);
|
||||
host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_MEM_STORE_IMM_8(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real);
|
||||
|
||||
host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg);
|
||||
host_x86_MOV8_REG_IMM(block, REG_ECX, uop->imm_data);
|
||||
host_x86_CALL(block, codegen_mem_store_byte);
|
||||
host_x86_TEST32_REG(block, REG_ESI, REG_ESI);
|
||||
host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_MEM_STORE_IMM_16(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real);
|
||||
|
||||
host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg);
|
||||
host_x86_MOV16_REG_IMM(block, REG_ECX, uop->imm_data);
|
||||
host_x86_CALL(block, codegen_mem_store_word);
|
||||
host_x86_TEST32_REG(block, REG_ESI, REG_ESI);
|
||||
host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_MEM_STORE_IMM_32(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int seg_reg = HOST_REG_GET(uop->src_reg_a_real), addr_reg = HOST_REG_GET(uop->src_reg_b_real);
|
||||
|
||||
host_x86_LEA_REG_REG(block, REG_ESI, seg_reg, addr_reg);
|
||||
host_x86_MOV32_REG_IMM(block, REG_ECX, uop->imm_data);
|
||||
host_x86_CALL(block, codegen_mem_store_long);
|
||||
host_x86_TEST32_REG(block, REG_ESI, REG_ESI);
|
||||
host_x86_JNZ(block, &block->data[BLOCK_EXIT_OFFSET]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_MOV(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);
|
||||
|
|
@ -1010,6 +587,15 @@ const uOpFn uop_handlers[UOP_MAX] =
|
|||
[UOP_STORE_P_IMM & UOP_MASK] = codegen_STORE_PTR_IMM,
|
||||
[UOP_STORE_P_IMM_8 & UOP_MASK] = codegen_STORE_PTR_IMM_8,
|
||||
|
||||
[UOP_MEM_LOAD_ABS & UOP_MASK] = codegen_MEM_LOAD_ABS,
|
||||
[UOP_MEM_LOAD_REG & UOP_MASK] = codegen_MEM_LOAD_REG,
|
||||
|
||||
[UOP_MEM_STORE_ABS & UOP_MASK] = codegen_MEM_STORE_ABS,
|
||||
[UOP_MEM_STORE_REG & UOP_MASK] = codegen_MEM_STORE_REG,
|
||||
[UOP_MEM_STORE_IMM_8 & UOP_MASK] = codegen_MEM_STORE_IMM_8,
|
||||
[UOP_MEM_STORE_IMM_16 & UOP_MASK] = codegen_MEM_STORE_IMM_16,
|
||||
[UOP_MEM_STORE_IMM_32 & UOP_MASK] = codegen_MEM_STORE_IMM_32,
|
||||
|
||||
[UOP_MOV & UOP_MASK] = codegen_MOV,
|
||||
[UOP_MOV_PTR & UOP_MASK] = codegen_MOV_PTR,
|
||||
[UOP_MOV_IMM & UOP_MASK] = codegen_MOV_IMM,
|
||||
|
|
@ -1025,7 +611,9 @@ const uOpFn uop_handlers[UOP_MAX] =
|
|||
[UOP_SUB & UOP_MASK] = codegen_SUB,
|
||||
[UOP_SUB_IMM & UOP_MASK] = codegen_SUB_IMM,
|
||||
[UOP_XOR & UOP_MASK] = codegen_XOR,
|
||||
[UOP_XOR_IMM & UOP_MASK] = codegen_XOR_IMM
|
||||
[UOP_XOR_IMM & UOP_MASK] = codegen_XOR_IMM,
|
||||
|
||||
[UOP_CMP_IMM_JZ & UOP_MASK] = codegen_CMP_IMM_JZ
|
||||
};
|
||||
|
||||
void codegen_direct_read_32(codeblock_t *block, int host_reg, void *p)
|
||||
|
|
|
|||
|
|
@ -27,9 +27,14 @@ void codegen_ir_compile(ir_data_t *ir, codeblock_t *block)
|
|||
|
||||
// pclog("uOP %i : %08x\n", c, uop->type);
|
||||
|
||||
if (uop->type & UOP_TYPE_BARRIER)
|
||||
codegen_reg_flush_invalidate(ir, block);
|
||||
else if (uop->type & UOP_TYPE_ORDER_BARRIER)
|
||||
codegen_reg_flush(ir, block);
|
||||
|
||||
if (uop->type & UOP_TYPE_PARAMS_REGS)
|
||||
{
|
||||
codegen_reg_alloc_register(uop->dest_reg_a, uop->src_reg_a, uop->src_reg_b);
|
||||
codegen_reg_alloc_register(uop->dest_reg_a, uop->src_reg_a, uop->src_reg_b, uop->src_reg_c);
|
||||
if (uop->src_reg_a.reg != IREG_INVALID)
|
||||
{
|
||||
uop->src_reg_a_real = codegen_reg_alloc_read_reg(block, uop->src_reg_a, NULL);
|
||||
|
|
@ -38,19 +43,22 @@ void codegen_ir_compile(ir_data_t *ir, codeblock_t *block)
|
|||
{
|
||||
uop->src_reg_b_real = codegen_reg_alloc_read_reg(block, uop->src_reg_b, NULL);
|
||||
}
|
||||
if (uop->src_reg_c.reg != IREG_INVALID)
|
||||
{
|
||||
uop->src_reg_c_real = codegen_reg_alloc_read_reg(block, uop->src_reg_c, NULL);
|
||||
}
|
||||
if (uop->dest_reg_a.reg != IREG_INVALID)
|
||||
{
|
||||
uop->dest_reg_a_real = codegen_reg_alloc_write_reg(block, uop->dest_reg_a);
|
||||
}
|
||||
}
|
||||
|
||||
if (uop->type & UOP_TYPE_BARRIER)
|
||||
codegen_reg_flush(ir, block);
|
||||
|
||||
if (!uop_handlers[uop->type & UOP_MASK])
|
||||
fatal("!uop_handlers[uop->type & UOP_MASK]\n");
|
||||
uop_handlers[uop->type & UOP_MASK](block, uop);
|
||||
}
|
||||
|
||||
codegen_reg_flush(ir, block);
|
||||
codegen_reg_flush_invalidate(ir, block);
|
||||
|
||||
codegen_backend_epilogue(block);
|
||||
|
||||
|
|
|
|||
|
|
@ -6,9 +6,17 @@
|
|||
#define UOP_REG(reg, size, version) ((reg) | (size) | (version << 8))
|
||||
|
||||
/*uOP is a barrier. All previous uOPs must have completed before this one executes.
|
||||
All registers must have been written back or discarded*/
|
||||
All registers must have been written back or discarded.
|
||||
This should be used when calling external functions that may change any emulated
|
||||
registers.*/
|
||||
#define UOP_TYPE_BARRIER (1 << 31)
|
||||
|
||||
/*uOP is a barrier. All previous uOPs must have completed before this one executes.
|
||||
All registers must have been written back, but do not have to be discarded.
|
||||
This should be used when calling functions that preserve registers, but can cause
|
||||
the code block to exit (eg memory load/store functions).*/
|
||||
#define UOP_TYPE_ORDER_BARRIER (1 << 27)
|
||||
|
||||
/*uOP uses source and dest registers*/
|
||||
#define UOP_TYPE_PARAMS_REGS (1 << 28)
|
||||
/*uOP uses pointer*/
|
||||
|
|
@ -62,8 +70,24 @@
|
|||
#define UOP_XOR (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x39)
|
||||
/*UOP_XOR_IMM - dest_reg = src_reg_a ^ immediate*/
|
||||
#define UOP_XOR_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x3a)
|
||||
/*UOP_MEM_LOAD_ABS - dest_reg = src_reg_a:[immediate]*/
|
||||
#define UOP_MEM_LOAD_ABS (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x40 | UOP_TYPE_ORDER_BARRIER)
|
||||
/*UOP_MEM_LOAD_REG - dest_reg = src_reg_a:[src_reg_b]*/
|
||||
#define UOP_MEM_LOAD_REG (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x41 | UOP_TYPE_ORDER_BARRIER)
|
||||
/*UOP_MEM_STORE_ABS - src_reg_a:[immediate] = src_reg_b*/
|
||||
#define UOP_MEM_STORE_ABS (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x42 | UOP_TYPE_ORDER_BARRIER)
|
||||
/*UOP_MEM_STORE_REG - src_reg_a:[src_reg_b] = src_reg_c*/
|
||||
#define UOP_MEM_STORE_REG (UOP_TYPE_PARAMS_REGS | 0x43 | UOP_TYPE_ORDER_BARRIER)
|
||||
/*UOP_MEM_STORE_IMM_8 - byte src_reg_a:[src_reg_b] = imm_data*/
|
||||
#define UOP_MEM_STORE_IMM_8 (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x44 | UOP_TYPE_ORDER_BARRIER)
|
||||
/*UOP_MEM_STORE_IMM_16 - word src_reg_a:[src_reg_b] = imm_data*/
|
||||
#define UOP_MEM_STORE_IMM_16 (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x45 | UOP_TYPE_ORDER_BARRIER)
|
||||
/*UOP_MEM_STORE_IMM_32 - long src_reg_a:[src_reg_b] = imm_data*/
|
||||
#define UOP_MEM_STORE_IMM_32 (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x46 | UOP_TYPE_ORDER_BARRIER)
|
||||
/*UOP_CMP_JZ - if (src_reg_a == imm_data) then jump to ptr*/
|
||||
#define UOP_CMP_IMM_JZ (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x48 | UOP_TYPE_ORDER_BARRIER)
|
||||
|
||||
#define UOP_MAX 0x3b
|
||||
#define UOP_MAX 0x49
|
||||
|
||||
#define UOP_MASK 0xffff
|
||||
|
||||
|
|
@ -73,10 +97,11 @@ typedef struct uop_t
|
|||
ir_reg_t dest_reg_a;
|
||||
ir_reg_t src_reg_a;
|
||||
ir_reg_t src_reg_b;
|
||||
ir_reg_t src_reg_c;
|
||||
uint32_t imm_data;
|
||||
void *p;
|
||||
ir_host_reg_t dest_reg_a_real;
|
||||
ir_host_reg_t src_reg_a_real, src_reg_b_real;
|
||||
ir_host_reg_t src_reg_a_real, src_reg_b_real, src_reg_c_real;
|
||||
} uop_t;
|
||||
|
||||
#define UOP_NR_MAX 4096
|
||||
|
|
@ -99,7 +124,8 @@ static inline uop_t *uop_alloc(ir_data_t *ir)
|
|||
uop->dest_reg_a = invalid_ir_reg;
|
||||
uop->src_reg_a = invalid_ir_reg;
|
||||
uop->src_reg_b = invalid_ir_reg;
|
||||
|
||||
uop->src_reg_c = invalid_ir_reg;
|
||||
|
||||
return uop;
|
||||
}
|
||||
|
||||
|
|
@ -179,6 +205,26 @@ static inline void uop_gen_reg_dst_src_imm(uint32_t uop_type, ir_data_t *ir, int
|
|||
uop->imm_data = imm;
|
||||
}
|
||||
|
||||
static inline void uop_gen_reg_src2_imm(uint32_t uop_type, ir_data_t *ir, int src_reg_a, int src_reg_b, uint32_t imm)
|
||||
{
|
||||
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->imm_data = imm;
|
||||
}
|
||||
|
||||
static inline void uop_gen_reg_src3(uint32_t uop_type, ir_data_t *ir, 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);
|
||||
}
|
||||
|
||||
static inline void uop_gen_imm(uint32_t uop_type, ir_data_t *ir, uint32_t imm)
|
||||
{
|
||||
uop_t *uop = uop_alloc(ir);
|
||||
|
|
@ -204,6 +250,16 @@ static inline void uop_gen_pointer_imm(uint32_t uop_type, ir_data_t *ir, void *p
|
|||
uop->imm_data = imm;
|
||||
}
|
||||
|
||||
static inline void uop_gen_reg_src_pointer_imm(uint32_t uop_type, ir_data_t *ir, int src_reg_a, void *p, uint32_t imm)
|
||||
{
|
||||
uop_t *uop = uop_alloc(ir);
|
||||
|
||||
uop->type = uop_type;
|
||||
uop->src_reg_a = codegen_reg_read(src_reg_a);
|
||||
uop->p = p;
|
||||
uop->imm_data = imm;
|
||||
}
|
||||
|
||||
#define uop_LOAD_FUNC_ARG_REG(ir, arg, reg) uop_gen_reg_src1(UOP_LOAD_FUNC_ARG_0 + arg, ir, reg)
|
||||
|
||||
#define uop_LOAD_FUNC_ARG_IMM(ir, arg, imm) uop_gen_imm(UOP_LOAD_FUNC_ARG_0_IMM + arg, ir, imm)
|
||||
|
|
@ -223,6 +279,16 @@ static inline void uop_gen_pointer_imm(uint32_t uop_type, ir_data_t *ir, void *p
|
|||
#define uop_CALL_FUNC(ir, p) uop_gen_pointer(UOP_CALL_FUNC, ir, p)
|
||||
#define uop_CALL_INSTRUCTION_FUNC(ir, p) uop_gen_pointer(UOP_CALL_INSTRUCTION_FUNC, ir, p)
|
||||
|
||||
#define uop_CMP_IMM_JZ(ir, src_reg, imm, p) uop_gen_reg_src_pointer_imm(UOP_CMP_IMM_JZ, ir, src_reg, p, imm)
|
||||
|
||||
#define uop_MEM_LOAD_ABS(ir, dst_reg, seg_reg, imm) uop_gen_reg_dst_src_imm(UOP_MEM_LOAD_ABS, ir, dst_reg, seg_reg, imm)
|
||||
#define uop_MEM_LOAD_REG(ir, dst_reg, seg_reg, addr_reg) uop_gen_reg_dst_src2(UOP_MEM_LOAD_REG, ir, dst_reg, seg_reg, addr_reg)
|
||||
#define uop_MEM_STORE_ABS(ir, seg_reg, imm, src_reg) uop_gen_reg_src2_imm(UOP_MEM_STORE_ABS, ir, seg_reg, src_reg, imm)
|
||||
#define uop_MEM_STORE_REG(ir, seg_reg, addr_reg, src_reg) uop_gen_reg_src3(UOP_MEM_STORE_REG, ir, seg_reg, addr_reg, src_reg)
|
||||
#define uop_MEM_STORE_IMM_8(ir, seg_reg, addr_reg, imm) uop_gen_reg_src2_imm(UOP_MEM_STORE_IMM_8, ir, seg_reg, addr_reg, imm)
|
||||
#define uop_MEM_STORE_IMM_16(ir, seg_reg, addr_reg, imm) uop_gen_reg_src2_imm(UOP_MEM_STORE_IMM_16, ir, seg_reg, addr_reg, imm)
|
||||
#define uop_MEM_STORE_IMM_32(ir, seg_reg, addr_reg, imm) uop_gen_reg_src2_imm(UOP_MEM_STORE_IMM_32, ir, seg_reg, addr_reg, imm)
|
||||
|
||||
#define uop_MOV(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_MOV, ir, dst_reg, src_reg)
|
||||
#define uop_MOV_IMM(ir, reg, imm) uop_gen_reg_dst_imm(UOP_MOV_IMM, ir, reg, imm)
|
||||
#define uop_MOV_PTR(ir, reg, p) uop_gen_reg_dst_pointer(UOP_MOV_PTR, ir, reg, p)
|
||||
|
|
|
|||
|
|
@ -22,10 +22,10 @@ RecompOpFn recomp_opcodes[512] =
|
|||
|
||||
/*80*/ rop80, rop81_w, rop80, rop83_w, NULL, NULL, NULL, NULL, ropMOV_b_r, ropMOV_w_r, ropMOV_r_b, ropMOV_r_w, NULL, NULL, NULL, NULL,
|
||||
/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*a0*/ ropMOV_AL_abs, ropMOV_AX_abs, ropMOV_abs_AL, ropMOV_abs_AX, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*b0*/ ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm,
|
||||
|
||||
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, ropMOV_b_imm, ropMOV_w_imm, 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,
|
||||
/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
|
|
@ -44,10 +44,10 @@ RecompOpFn recomp_opcodes[512] =
|
|||
|
||||
/*80*/ rop80, rop81_l, rop80, rop83_l, NULL, NULL, NULL, NULL, ropMOV_b_r, ropMOV_l_r, ropMOV_r_b, ropMOV_r_l, NULL, NULL, NULL, NULL,
|
||||
/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*a0*/ ropMOV_AL_abs, ropMOV_EAX_abs, ropMOV_abs_AL, ropMOV_abs_EAX, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*b0*/ ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm,
|
||||
|
||||
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, ropMOV_b_imm, ropMOV_l_imm, 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,
|
||||
/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
||||
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
|
||||
|
|
|
|||
|
|
@ -36,43 +36,64 @@ uint32_t ropMOV_rl_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32
|
|||
|
||||
uint32_t ropMOV_b_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||
{
|
||||
int dest_reg = fetchdat & 7;
|
||||
int src_reg = (fetchdat >> 3) & 7;
|
||||
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
{
|
||||
int src_reg = (fetchdat >> 3) & 7;
|
||||
int dest_reg = fetchdat & 7;
|
||||
uop_MOV(ir, IREG_8(dest_reg), IREG_8(src_reg));
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
{
|
||||
x86seg *target_seg;
|
||||
|
||||
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
||||
codegen_check_seg_write(block, ir, target_seg);
|
||||
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_8(src_reg));
|
||||
}
|
||||
|
||||
return op_pc + 1;
|
||||
}
|
||||
uint32_t ropMOV_w_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||
{
|
||||
int dest_reg = fetchdat & 7;
|
||||
int src_reg = (fetchdat >> 3) & 7;
|
||||
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
{
|
||||
int src_reg = (fetchdat >> 3) & 7;
|
||||
int dest_reg = fetchdat & 7;
|
||||
uop_MOV(ir, IREG_16(dest_reg), IREG_16(src_reg));
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
{
|
||||
x86seg *target_seg;
|
||||
|
||||
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
||||
codegen_check_seg_write(block, ir, target_seg);
|
||||
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_16(src_reg));
|
||||
}
|
||||
|
||||
return op_pc + 1;
|
||||
}
|
||||
uint32_t ropMOV_l_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||
{
|
||||
int dest_reg = fetchdat & 7;
|
||||
int src_reg = (fetchdat >> 3) & 7;
|
||||
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
{
|
||||
int src_reg = (fetchdat >> 3) & 7;
|
||||
int dest_reg = fetchdat & 7;
|
||||
uop_MOV(ir, IREG_32(dest_reg), IREG_32(src_reg));
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
{
|
||||
x86seg *target_seg;
|
||||
|
||||
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
||||
codegen_check_seg_write(block, ir, target_seg);
|
||||
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_32(src_reg));
|
||||
}
|
||||
|
||||
return op_pc + 1;
|
||||
}
|
||||
|
|
@ -86,7 +107,15 @@ uint32_t ropMOV_r_b(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t
|
|||
uop_MOV(ir, IREG_8(dest_reg), IREG_8(src_reg));
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
{
|
||||
x86seg *target_seg;
|
||||
|
||||
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
||||
codegen_check_seg_read(block, ir, target_seg);
|
||||
uop_MEM_LOAD_REG(ir, IREG_8(dest_reg), ireg_seg_base(target_seg), IREG_eaaddr);
|
||||
CPU_BLOCK_END();
|
||||
}
|
||||
|
||||
return op_pc + 1;
|
||||
}
|
||||
|
|
@ -100,7 +129,14 @@ uint32_t ropMOV_r_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t
|
|||
uop_MOV(ir, IREG_16(dest_reg), IREG_16(src_reg));
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
{
|
||||
x86seg *target_seg;
|
||||
|
||||
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
||||
codegen_check_seg_read(block, ir, target_seg);
|
||||
uop_MEM_LOAD_REG(ir, IREG_16(dest_reg), ireg_seg_base(target_seg), IREG_eaaddr);
|
||||
}
|
||||
|
||||
return op_pc + 1;
|
||||
}
|
||||
|
|
@ -114,7 +150,176 @@ uint32_t ropMOV_r_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t
|
|||
uop_MOV(ir, IREG_32(dest_reg), IREG_32(src_reg));
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
{
|
||||
x86seg *target_seg;
|
||||
|
||||
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
||||
codegen_check_seg_read(block, ir, target_seg);
|
||||
uop_MEM_LOAD_REG(ir, IREG_32(dest_reg), ireg_seg_base(target_seg), IREG_eaaddr);
|
||||
}
|
||||
|
||||
return op_pc + 1;
|
||||
}
|
||||
|
||||
uint32_t ropMOV_AL_abs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||
{
|
||||
uint32_t addr;
|
||||
|
||||
if (op_32 & 0x200)
|
||||
addr = fastreadl(cs + op_pc);
|
||||
else
|
||||
addr = fastreadw(cs + op_pc);
|
||||
|
||||
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||
codegen_check_seg_read(block, ir, op_ea_seg);
|
||||
uop_MEM_LOAD_ABS(ir, IREG_AL, ireg_seg_base(op_ea_seg), addr);
|
||||
|
||||
return op_pc + ((op_32 & 0x200) ? 4 : 2);
|
||||
}
|
||||
uint32_t ropMOV_AX_abs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||
{
|
||||
uint32_t addr;
|
||||
|
||||
if (op_32 & 0x200)
|
||||
addr = fastreadl(cs + op_pc);
|
||||
else
|
||||
addr = fastreadw(cs + op_pc);
|
||||
|
||||
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||
codegen_check_seg_read(block, ir, op_ea_seg);
|
||||
uop_MEM_LOAD_ABS(ir, IREG_AX, ireg_seg_base(op_ea_seg), addr);
|
||||
|
||||
return op_pc + ((op_32 & 0x200) ? 4 : 2);
|
||||
}
|
||||
uint32_t ropMOV_EAX_abs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||
{
|
||||
uint32_t addr;
|
||||
|
||||
if (op_32 & 0x200)
|
||||
addr = fastreadl(cs + op_pc);
|
||||
else
|
||||
addr = fastreadw(cs + op_pc);
|
||||
|
||||
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||
codegen_check_seg_read(block, ir, op_ea_seg);
|
||||
uop_MEM_LOAD_ABS(ir, IREG_EAX, ireg_seg_base(op_ea_seg), addr);
|
||||
|
||||
return op_pc + ((op_32 & 0x200) ? 4 : 2);
|
||||
}
|
||||
|
||||
uint32_t ropMOV_abs_AL(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||
{
|
||||
uint32_t addr;
|
||||
|
||||
if (op_32 & 0x200)
|
||||
addr = fastreadl(cs + op_pc);
|
||||
else
|
||||
addr = fastreadw(cs + op_pc);
|
||||
|
||||
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||
codegen_check_seg_write(block, ir, op_ea_seg);
|
||||
uop_MEM_STORE_ABS(ir, ireg_seg_base(op_ea_seg), addr, IREG_AL);
|
||||
|
||||
return op_pc + ((op_32 & 0x200) ? 4 : 2);
|
||||
}
|
||||
uint32_t ropMOV_abs_AX(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||
{
|
||||
uint32_t addr;
|
||||
|
||||
if (op_32 & 0x200)
|
||||
addr = fastreadl(cs + op_pc);
|
||||
else
|
||||
addr = fastreadw(cs + op_pc);
|
||||
|
||||
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||
codegen_check_seg_write(block, ir, op_ea_seg);
|
||||
uop_MEM_STORE_ABS(ir, ireg_seg_base(op_ea_seg), addr, IREG_AX);
|
||||
|
||||
return op_pc + ((op_32 & 0x200) ? 4 : 2);
|
||||
}
|
||||
uint32_t ropMOV_abs_EAX(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||
{
|
||||
uint32_t addr;
|
||||
|
||||
if (op_32 & 0x200)
|
||||
addr = fastreadl(cs + op_pc);
|
||||
else
|
||||
addr = fastreadw(cs + op_pc);
|
||||
|
||||
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||
codegen_check_seg_write(block, ir, op_ea_seg);
|
||||
uop_MEM_STORE_ABS(ir, ireg_seg_base(op_ea_seg), addr, IREG_EAX);
|
||||
|
||||
return op_pc + ((op_32 & 0x200) ? 4 : 2);
|
||||
}
|
||||
|
||||
uint32_t ropMOV_b_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||
{
|
||||
x86seg *target_seg;
|
||||
uint8_t imm;
|
||||
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
{
|
||||
int dest_reg = fetchdat & 7;
|
||||
|
||||
imm = fastreadb(cs + op_pc + 1);
|
||||
uop_MOV_IMM(ir, IREG_8(dest_reg), imm);
|
||||
}
|
||||
else
|
||||
{
|
||||
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
||||
codegen_check_seg_write(block, ir, target_seg);
|
||||
imm = fastreadb(cs + op_pc + 1);
|
||||
uop_MEM_STORE_IMM_8(ir, ireg_seg_base(target_seg), IREG_eaaddr, imm);
|
||||
}
|
||||
|
||||
return op_pc + 2;
|
||||
}
|
||||
uint32_t ropMOV_w_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||
{
|
||||
x86seg *target_seg;
|
||||
uint16_t imm;
|
||||
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
{
|
||||
int dest_reg = fetchdat & 7;
|
||||
|
||||
imm = fastreadw(cs + op_pc + 1);
|
||||
uop_MOV_IMM(ir, IREG_16(dest_reg), imm);
|
||||
}
|
||||
else
|
||||
{
|
||||
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
||||
codegen_check_seg_write(block, ir, target_seg);
|
||||
imm = fastreadw(cs + op_pc + 1);
|
||||
uop_MEM_STORE_IMM_16(ir, ireg_seg_base(target_seg), IREG_eaaddr, imm);
|
||||
}
|
||||
|
||||
return op_pc + 3;
|
||||
}
|
||||
uint32_t ropMOV_l_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
|
||||
{
|
||||
x86seg *target_seg;
|
||||
uint32_t imm;
|
||||
|
||||
if ((fetchdat & 0xc0) == 0xc0)
|
||||
{
|
||||
int dest_reg = fetchdat & 7;
|
||||
|
||||
imm = fastreadl(cs + op_pc + 1);
|
||||
uop_MOV_IMM(ir, IREG_32(dest_reg), imm);
|
||||
}
|
||||
else
|
||||
{
|
||||
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
|
||||
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
|
||||
codegen_check_seg_write(block, ir, target_seg);
|
||||
imm = fastreadl(cs + op_pc + 1);
|
||||
uop_MEM_STORE_IMM_32(ir, ireg_seg_base(target_seg), IREG_eaaddr, imm);
|
||||
}
|
||||
|
||||
return op_pc + 5;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,22 @@
|
|||
uint32_t ropMOV_rb_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
uint32_t ropMOV_rw_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
uint32_t ropMOV_rl_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
|
||||
uint32_t ropMOV_b_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
uint32_t ropMOV_w_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
uint32_t ropMOV_l_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
uint32_t ropMOV_r_b(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
uint32_t ropMOV_r_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
uint32_t ropMOV_r_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
|
||||
uint32_t ropMOV_AL_abs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
uint32_t ropMOV_AX_abs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
uint32_t ropMOV_EAX_abs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
|
||||
uint32_t ropMOV_abs_AL(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
uint32_t ropMOV_abs_AX(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
uint32_t ropMOV_abs_EAX(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
|
||||
uint32_t ropMOV_b_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
uint32_t ropMOV_w_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
uint32_t ropMOV_l_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
|
||||
|
|
|
|||
|
|
@ -56,6 +56,13 @@ struct
|
|||
|
||||
[IREG_ins] = {REG_DWORD, &cpu_state.cpu_recomp_ins},
|
||||
[IREG_cycles] = {REG_DWORD, &cpu_state._cycles},
|
||||
|
||||
[IREG_CS_base] = {REG_DWORD, &cpu_state.seg_cs.base},
|
||||
[IREG_DS_base] = {REG_DWORD, &cpu_state.seg_ds.base},
|
||||
[IREG_ES_base] = {REG_DWORD, &cpu_state.seg_es.base},
|
||||
[IREG_FS_base] = {REG_DWORD, &cpu_state.seg_fs.base},
|
||||
[IREG_GS_base] = {REG_DWORD, &cpu_state.seg_gs.base},
|
||||
[IREG_SS_base] = {REG_DWORD, &cpu_state.seg_ss.base},
|
||||
|
||||
/*Temporary registers are stored on the stack, and are not guaranteed to
|
||||
be preserved across uOPs. They will not be written back if they will
|
||||
|
|
@ -63,7 +70,7 @@ struct
|
|||
[IREG_temp0] = {REG_DWORD, NULL},
|
||||
[IREG_temp1] = {REG_DWORD, NULL},
|
||||
[IREG_temp2] = {REG_DWORD, NULL},
|
||||
[IREG_temp3] = {REG_DWORD, NULL}
|
||||
[IREG_temp3] = {REG_DWORD, NULL},
|
||||
};
|
||||
|
||||
void codegen_reg_reset()
|
||||
|
|
@ -103,7 +110,7 @@ static void codegen_reg_load(codeblock_t *block, int c, ir_reg_t ir_reg)
|
|||
//pclog(" codegen_reg_load: c=%i reg=%02x.%i\n", c, host_regs[c].reg,host_regs[c].version);
|
||||
}
|
||||
|
||||
static void codegen_reg_writeback(codeblock_t *block, int c)
|
||||
static void codegen_reg_writeback(codeblock_t *block, int c, int invalidate)
|
||||
{
|
||||
int ir_reg = IREG_GET_REG(host_regs[c].reg);
|
||||
|
||||
|
|
@ -125,11 +132,12 @@ static void codegen_reg_writeback(codeblock_t *block, int c)
|
|||
fatal("codegen_reg_flush - native_size=%i\n", ireg_data[ir_reg].native_size);
|
||||
}
|
||||
|
||||
host_regs[c] = invalid_ir_reg;
|
||||
if (invalidate)
|
||||
host_regs[c] = invalid_ir_reg;
|
||||
host_reg_dirty[c] = 0;
|
||||
}
|
||||
|
||||
void codegen_reg_alloc_register(ir_reg_t dest_reg_a, ir_reg_t src_reg_a, ir_reg_t src_reg_b)
|
||||
void codegen_reg_alloc_register(ir_reg_t dest_reg_a, ir_reg_t src_reg_a, ir_reg_t src_reg_b, ir_reg_t src_reg_c)
|
||||
{
|
||||
int c;
|
||||
int dest_reference = 0;
|
||||
|
|
@ -146,6 +154,8 @@ void codegen_reg_alloc_register(ir_reg_t dest_reg_a, ir_reg_t src_reg_a, ir_reg_
|
|||
dest_reference++;
|
||||
if (!ir_reg_is_invalid(src_reg_b) && IREG_GET_REG(src_reg_b.reg) == IREG_GET_REG(dest_reg_a.reg) && src_reg_b.version == dest_reg_a.version-1)
|
||||
dest_reference++;
|
||||
if (!ir_reg_is_invalid(src_reg_c) && IREG_GET_REG(src_reg_c.reg) == IREG_GET_REG(dest_reg_a.reg) && src_reg_c.version == dest_reg_a.version-1)
|
||||
dest_reference++;
|
||||
}
|
||||
for (c = 0; c < CODEGEN_HOST_REGS; c++)
|
||||
{
|
||||
|
|
@ -161,6 +171,12 @@ void codegen_reg_alloc_register(ir_reg_t dest_reg_a, ir_reg_t src_reg_a, ir_reg_
|
|||
fatal("codegen_reg_alloc_register - host_regs[c].version != src_reg_b.version\n");
|
||||
host_regs_locked |= (1 << c);
|
||||
}
|
||||
if (!ir_reg_is_invalid(src_reg_c) && IREG_GET_REG(host_regs[c].reg) == IREG_GET_REG(src_reg_c.reg))
|
||||
{
|
||||
if (host_regs[c].version != src_reg_c.version)
|
||||
fatal("codegen_reg_alloc_register - host_regs[c].version != src_reg_c.version\n");
|
||||
host_regs_locked |= (1 << c);
|
||||
}
|
||||
if (!ir_reg_is_invalid(dest_reg_a) && IREG_GET_REG(host_regs[c].reg) == IREG_GET_REG(dest_reg_a.reg))
|
||||
{
|
||||
if (host_regs[c].version == dest_reg_a.version || (host_regs[c].version == (dest_reg_a.version-1) && reg_version_refcount[IREG_GET_REG(host_regs[c].reg)][host_regs[c].version] == dest_reference))
|
||||
|
|
@ -196,7 +212,7 @@ ir_host_reg_t codegen_reg_alloc_read_reg(codeblock_t *block, ir_reg_t ir_reg, in
|
|||
if (c == CODEGEN_HOST_REGS)
|
||||
fatal("codegen_reg_alloc_read_reg - out of registers\n");
|
||||
if (host_reg_dirty[c])
|
||||
codegen_reg_writeback(block, c);
|
||||
codegen_reg_writeback(block, c, 1);
|
||||
// pclog(" load %i\n", c);
|
||||
codegen_reg_load(block, c, ir_reg);
|
||||
host_regs_locked |= (1 << c);
|
||||
|
|
@ -277,7 +293,7 @@ ir_host_reg_t codegen_reg_alloc_write_reg(codeblock_t *block, ir_reg_t ir_reg)
|
|||
if (c == CODEGEN_HOST_REGS)
|
||||
fatal("codegen_reg_alloc_write_reg - out of registers\n");
|
||||
if (host_reg_dirty[c])
|
||||
codegen_reg_writeback(block, c);
|
||||
codegen_reg_writeback(block, c, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -289,6 +305,19 @@ ir_host_reg_t codegen_reg_alloc_write_reg(codeblock_t *block, ir_reg_t ir_reg)
|
|||
}
|
||||
|
||||
void codegen_reg_flush(ir_data_t *ir, codeblock_t *block)
|
||||
{
|
||||
int c;
|
||||
|
||||
for (c = 0; c < CODEGEN_HOST_REGS; c++)
|
||||
{
|
||||
if (!ir_reg_is_invalid(host_regs[c]) && host_reg_dirty[c])
|
||||
{
|
||||
codegen_reg_writeback(block, c, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void codegen_reg_flush_invalidate(ir_data_t *ir, codeblock_t *block)
|
||||
{
|
||||
int c;
|
||||
|
||||
|
|
@ -296,7 +325,7 @@ void codegen_reg_flush(ir_data_t *ir, codeblock_t *block)
|
|||
{
|
||||
if (!ir_reg_is_invalid(host_regs[c]))
|
||||
{
|
||||
codegen_reg_writeback(block, c);
|
||||
codegen_reg_writeback(block, c, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,13 +42,20 @@ enum
|
|||
IREG_ins = 19,
|
||||
IREG_cycles = 20,
|
||||
|
||||
IREG_CS_base = 21,
|
||||
IREG_DS_base = 22,
|
||||
IREG_ES_base = 23,
|
||||
IREG_FS_base = 24,
|
||||
IREG_GS_base = 25,
|
||||
IREG_SS_base = 26,
|
||||
|
||||
/*Temporary registers are stored on the stack, and are not guaranteed to
|
||||
be preserved across uOPs. They will not be written back if they will
|
||||
not be read again.*/
|
||||
IREG_temp0 = 21,
|
||||
IREG_temp1 = 22,
|
||||
IREG_temp2 = 23,
|
||||
IREG_temp3 = 24,
|
||||
IREG_temp0 = 27,
|
||||
IREG_temp1 = 28,
|
||||
IREG_temp2 = 29,
|
||||
IREG_temp3 = 30,
|
||||
|
||||
IREG_COUNT,
|
||||
|
||||
|
|
@ -82,6 +89,24 @@ enum
|
|||
#define IREG_16(reg) ((reg) + IREG_AX)
|
||||
#define IREG_32(reg) ((reg) + IREG_EAX)
|
||||
|
||||
static inline int ireg_seg_base(x86seg *seg)
|
||||
{
|
||||
if (seg == &cpu_state.seg_cs)
|
||||
return IREG_CS_base;
|
||||
if (seg == &cpu_state.seg_ds)
|
||||
return IREG_DS_base;
|
||||
if (seg == &cpu_state.seg_es)
|
||||
return IREG_ES_base;
|
||||
if (seg == &cpu_state.seg_fs)
|
||||
return IREG_FS_base;
|
||||
if (seg == &cpu_state.seg_gs)
|
||||
return IREG_GS_base;
|
||||
if (seg == &cpu_state.seg_ss)
|
||||
return IREG_SS_base;
|
||||
fatal("ireg_seg_base : unknown segment\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern uint8_t reg_last_version[IREG_COUNT];
|
||||
extern uint8_t reg_version_refcount[IREG_COUNT][256];
|
||||
|
||||
|
|
@ -131,10 +156,13 @@ static inline ir_reg_t codegen_reg_write(int reg)
|
|||
struct ir_data_t;
|
||||
|
||||
void codegen_reg_reset();
|
||||
/*Write back all dirty registers*/
|
||||
void codegen_reg_flush(struct ir_data_t *ir, codeblock_t *block);
|
||||
/*Write back and evict all registers*/
|
||||
void codegen_reg_flush_invalidate(struct ir_data_t *ir, codeblock_t *block);
|
||||
|
||||
/*Register ir_reg usage for this uOP. This ensures that required registers aren't evicted*/
|
||||
void codegen_reg_alloc_register(ir_reg_t dest_reg_a, ir_reg_t src_reg_a, ir_reg_t src_reg_b);
|
||||
void codegen_reg_alloc_register(ir_reg_t dest_reg_a, ir_reg_t src_reg_a, ir_reg_t src_reg_b, ir_reg_t src_reg_c);
|
||||
|
||||
ir_host_reg_t codegen_reg_alloc_read_reg(codeblock_t *block, ir_reg_t ir_reg, int *host_reg_idx);
|
||||
ir_host_reg_t codegen_reg_alloc_write_reg(codeblock_t *block, ir_reg_t ir_reg);
|
||||
|
|
|
|||
Loading…
Reference in a new issue