Add new codegen memory allocator. This allows the recompiler to allocate memory from a central pool as required. This central pool is by default 64 MB on x86, x86-64 and ARMv8, and 32 MB on ARMv7.
The current design does not allow for ARMv8 literal pools, therefore these have been removed.
This commit is contained in:
parent
56a4d5cf83
commit
66fba50e06
26 changed files with 1339 additions and 667 deletions
|
|
@ -7,6 +7,7 @@
|
|||
#include "386_common.h"
|
||||
|
||||
#include "codegen_accumulate.h"
|
||||
#include "codegen_allocator.h"
|
||||
#include "codegen_backend.h"
|
||||
#include "codegen_ir.h"
|
||||
#include "codegen_ops.h"
|
||||
|
|
|
|||
|
|
@ -59,14 +59,18 @@ typedef struct codeblock_t
|
|||
present in two pages.*/
|
||||
uint16_t prev, next;
|
||||
uint16_t prev_2, next_2;
|
||||
|
||||
/*First mem_block_t used by this block. Any subsequent mem_block_ts
|
||||
will be in the list starting at head_mem_block->next.*/
|
||||
struct mem_block_t *head_mem_block;
|
||||
} codeblock_t;
|
||||
|
||||
uint8_t *codeblock_data;
|
||||
|
||||
extern codeblock_t *codeblock;
|
||||
|
||||
extern uint16_t *codeblock_hash;
|
||||
|
||||
extern uint8_t *block_write_data;
|
||||
|
||||
/*Code block uses FPU*/
|
||||
#define CODEBLOCK_HAS_FPU 1
|
||||
/*Code block is always entered with the same FPU top-of-stack*/
|
||||
|
|
@ -300,6 +304,10 @@ x86seg *codegen_generate_ea(struct ir_data_t *ir, x86seg *op_ea_seg, uint32_t fe
|
|||
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);
|
||||
|
||||
/*Delete a random code block to free memory. This is obviously quite expensive, and
|
||||
will only be called when the allocator is out of memory*/
|
||||
void codegen_delete_random_block();
|
||||
|
||||
extern int cpu_block_end;
|
||||
extern uint32_t codegen_endpc;
|
||||
|
||||
|
|
|
|||
|
|
@ -11,10 +11,13 @@
|
|||
|
||||
#include "codegen.h"
|
||||
#include "codegen_accumulate.h"
|
||||
#include "codegen_allocator.h"
|
||||
#include "codegen_backend.h"
|
||||
#include "codegen_ir.h"
|
||||
#include "codegen_reg.h"
|
||||
|
||||
uint8_t *block_write_data = NULL;
|
||||
|
||||
int codegen_flat_ds, codegen_flat_ss;
|
||||
int mmx_ebx_ecx_loaded;
|
||||
int codegen_flags_changed = 0;
|
||||
|
|
@ -52,6 +55,7 @@ uint32_t instr_counts[256*256];
|
|||
|
||||
void codegen_init()
|
||||
{
|
||||
codegen_allocator_init();
|
||||
codegen_backend_init();
|
||||
#ifdef DEBUG_EXTRA
|
||||
memset(instr_counts, 0, sizeof(instr_counts));
|
||||
|
|
@ -96,10 +100,7 @@ void codegen_reset()
|
|||
mem_reset_page_blocks();
|
||||
|
||||
for (c = 0; c < BLOCK_SIZE; c++)
|
||||
{
|
||||
codeblock[c].pc = BLOCK_PC_INVALID;
|
||||
codeblock[c].data = &codeblock_data[c * BLOCK_DATA_SIZE];
|
||||
}
|
||||
}
|
||||
|
||||
void dump_block()
|
||||
|
|
@ -220,6 +221,28 @@ static void delete_block(codeblock_t *block)
|
|||
|
||||
codeblock_tree_delete(block);
|
||||
remove_from_block_list(block, old_pc);
|
||||
if (block->head_mem_block)
|
||||
codegen_allocator_free(block->head_mem_block);
|
||||
block->head_mem_block = NULL;
|
||||
}
|
||||
|
||||
void codegen_delete_random_block()
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
int block_nr = rand() & BLOCK_MASK;
|
||||
|
||||
if (block_nr && block_nr != block_current)
|
||||
{
|
||||
codeblock_t *block = &codeblock[block_nr];
|
||||
|
||||
if (block->pc != BLOCK_PC_INVALID && block->head_mem_block)
|
||||
{
|
||||
delete_block(block);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void codegen_check_flush(page_t *page, uint64_t mask, uint32_t phys_addr)
|
||||
|
|
@ -318,6 +341,9 @@ void codegen_block_start_recompile(codeblock_t *block)
|
|||
if (block->pc != cs + cpu_state.pc || (block->flags & CODEBLOCK_WAS_RECOMPILED))
|
||||
fatal("Recompile to used block!\n");
|
||||
|
||||
block->head_mem_block = codegen_allocator_allocate(NULL);
|
||||
block->data = codeblock_allocator_get_ptr(block->head_mem_block);
|
||||
|
||||
block->status = cpu_cur_status;
|
||||
|
||||
cpu_block_end = 0;
|
||||
|
|
|
|||
|
|
@ -16,45 +16,6 @@ void codegen_backend_init();
|
|||
void codegen_backend_prologue(codeblock_t *block);
|
||||
void codegen_backend_epilogue(codeblock_t *block);
|
||||
|
||||
static inline void addbyte(uint8_t val)
|
||||
{
|
||||
codeblock[block_current].data[block_pos++] = val;
|
||||
if (block_pos >= BLOCK_MAX)
|
||||
{
|
||||
CPU_BLOCK_END();
|
||||
}
|
||||
}
|
||||
|
||||
static inline void addword(uint16_t val)
|
||||
{
|
||||
*(uint16_t *)(void *)&codeblock[block_current].data[block_pos] = val;
|
||||
block_pos += 2;
|
||||
if (block_pos >= BLOCK_MAX)
|
||||
{
|
||||
CPU_BLOCK_END();
|
||||
}
|
||||
}
|
||||
|
||||
static inline void addlong(uint32_t val)
|
||||
{
|
||||
*(uint32_t *)&codeblock[block_current].data[block_pos] = val;
|
||||
block_pos += 4;
|
||||
if (block_pos >= BLOCK_MAX)
|
||||
{
|
||||
CPU_BLOCK_END();
|
||||
}
|
||||
}
|
||||
|
||||
static inline void addquad(uint64_t val)
|
||||
{
|
||||
*(uint64_t *)&codeblock[block_current].data[block_pos] = val;
|
||||
block_pos += 8;
|
||||
if (block_pos >= BLOCK_MAX)
|
||||
{
|
||||
CPU_BLOCK_END();
|
||||
}
|
||||
}
|
||||
|
||||
struct ir_data_t;
|
||||
struct uop_t;
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
#include <stdlib.h>
|
||||
#include "ibm.h"
|
||||
#include "codegen.h"
|
||||
#include "codegen_allocator.h"
|
||||
#include "codegen_backend.h"
|
||||
#include "codegen_backend_arm_defs.h"
|
||||
#include "codegen_backend_arm_ops.h"
|
||||
|
|
@ -126,8 +127,6 @@ static void build_load_routine(codeblock_t *block, int size, int is_float)
|
|||
host_arm_VMOV_D_64(block, REG_D_TEMP, REG_R0, REG_R1);
|
||||
host_arm_LDRB_ABS(block, REG_R1, &cpu_state.abrt);
|
||||
host_arm_LDR_IMM_POST(block, REG_PC, REG_HOST_SP, 4);
|
||||
|
||||
block_pos = (block_pos + 63) & ~63;
|
||||
}
|
||||
|
||||
static void build_store_routine(codeblock_t *block, int size, int is_float)
|
||||
|
|
@ -199,8 +198,6 @@ static void build_store_routine(codeblock_t *block, int size, int is_float)
|
|||
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_HOST_SP, 4);
|
||||
|
||||
block_pos = (block_pos + 63) & ~63;
|
||||
}
|
||||
|
||||
static void build_loadstore_routines(codeblock_t *block)
|
||||
|
|
@ -246,13 +243,13 @@ static void build_fp_round_routine(codeblock_t *block)
|
|||
host_arm_MOV_REG(block, REG_LR, REG_TEMP2);
|
||||
host_arm_LDR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.new_fp_control - (uintptr_t)&cpu_state);
|
||||
host_arm_LDR_REG(block, REG_PC, REG_PC, REG_TEMP);
|
||||
addlong(0);
|
||||
host_arm_NOP(block);
|
||||
|
||||
jump_table = (uint32_t *)&block->data[block_pos];
|
||||
addlong(0);
|
||||
addlong(0);
|
||||
addlong(0);
|
||||
addlong(0);
|
||||
host_arm_NOP(block);
|
||||
host_arm_NOP(block);
|
||||
host_arm_NOP(block);
|
||||
host_arm_NOP(block);
|
||||
|
||||
jump_table[X87_ROUNDING_NEAREST] = (uint64_t)(uintptr_t)&block->data[block_pos]; //tie even
|
||||
host_arm_VCVTR_IS_D(block, REG_D_TEMP, REG_D_TEMP);
|
||||
|
|
@ -279,12 +276,11 @@ static void build_fp_round_routine(codeblock_t *block)
|
|||
jump_table[X87_ROUNDING_CHOP] = (uint64_t)(uintptr_t)&block->data[block_pos]; //zero
|
||||
host_arm_VCVT_IS_D(block, REG_D_TEMP, REG_D_TEMP);
|
||||
host_arm_MOV_REG(block, REG_PC, REG_LR);
|
||||
|
||||
block_pos = (block_pos + 63) & ~63;
|
||||
}
|
||||
|
||||
void codegen_backend_init()
|
||||
{
|
||||
codeblock_t *block;
|
||||
int c;
|
||||
#if defined(__linux__) || defined(__APPLE__)
|
||||
void *start;
|
||||
|
|
@ -293,13 +289,6 @@ void codegen_backend_init()
|
|||
long pagemask = ~(pagesize - 1);
|
||||
#endif
|
||||
|
||||
#if defined WIN32 || defined _WIN32 || defined _WIN32
|
||||
codeblock_data = VirtualAlloc(NULL, BLOCK_SIZE * BLOCK_DATA_SIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
|
||||
#else
|
||||
codeblock_data = malloc(BLOCK_SIZE * BLOCK_DATA_SIZE);
|
||||
#endif
|
||||
if (!codeblock_data)
|
||||
fatal("codeblock_data failed to alloc - %i\n", (BLOCK_SIZE+1) * BLOCK_DATA_SIZE);
|
||||
codeblock = malloc(BLOCK_SIZE * sizeof(codeblock_t));
|
||||
codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *));
|
||||
|
||||
|
|
@ -307,29 +296,24 @@ void codegen_backend_init()
|
|||
memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *));
|
||||
|
||||
for (c = 0; c < BLOCK_SIZE; c++)
|
||||
{
|
||||
codeblock[c].pc = BLOCK_PC_INVALID;
|
||||
codeblock[c].data = &codeblock_data[c * BLOCK_DATA_SIZE];
|
||||
}
|
||||
|
||||
#if defined(__linux__) || defined(__APPLE__)
|
||||
start = (void *)((long)codeblock_data & pagemask);
|
||||
len = ((BLOCK_SIZE * BLOCK_DATA_SIZE) + pagesize) & pagemask;
|
||||
if (mprotect(start, len, PROT_READ | PROT_WRITE | PROT_EXEC) != 0)
|
||||
{
|
||||
perror("mprotect");
|
||||
exit(-1);
|
||||
}
|
||||
#endif
|
||||
// pclog("Codegen is %p\n", (void *)pages[0xfab12 >> 12].block);
|
||||
|
||||
block_current = 0;
|
||||
block_pos = 0;
|
||||
block = &codeblock[block_current];
|
||||
block->head_mem_block = codegen_allocator_allocate(NULL);
|
||||
block->data = codeblock_allocator_get_ptr(block->head_mem_block);
|
||||
block_write_data = block->data;
|
||||
build_loadstore_routines(&codeblock[block_current]);
|
||||
printf("block_pos=%i\n", block_pos);
|
||||
|
||||
codegen_fp_round = &codeblock[block_current].data[block_pos];
|
||||
build_fp_round_routine(&codeblock[block_current]);
|
||||
|
||||
block_write_data = NULL;
|
||||
|
||||
asm("vmrs %0, fpscr\n"
|
||||
: "=r" (cpu_state.old_fp_control)
|
||||
);
|
||||
|
|
@ -380,10 +364,7 @@ void codegen_backend_epilogue(codeblock_t *block)
|
|||
host_arm_ADD_IMM(block, REG_HOST_SP, REG_HOST_SP, 0x40);
|
||||
host_arm_LDMIA_WB(block, REG_HOST_SP, REG_MASK_LOCAL | REG_MASK_PC);
|
||||
|
||||
if (block_pos > ARM_LITERAL_POOL_OFFSET)
|
||||
fatal("Over limit!\n");
|
||||
|
||||
__clear_cache(&block->data[0], &block->data[block_pos]);
|
||||
codegen_allocator_clean_blocks(block->head_mem_block);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -9,17 +9,10 @@
|
|||
|
||||
#define HASH(l) ((l) & 0x1ffff)
|
||||
|
||||
/*Hack until better memory management written*/
|
||||
/*#define BLOCK_EXIT_OFFSET 0x7f0*/
|
||||
|
||||
#define BLOCK_GPF_OFFSET 0
|
||||
#define BLOCK_EXIT_OFFSET 32
|
||||
|
||||
#define ARM_LITERAL_POOL_OFFSET 0x10000
|
||||
|
||||
/*#define BLOCK_MAX 1720*/
|
||||
#define BLOCK_MAX 65208
|
||||
|
||||
#define BLOCK_MAX 0x3c0
|
||||
|
||||
void host_arm_ADD_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm);
|
||||
void host_arm_LDMIA_WB(codeblock_t *block, int addr_reg, uint32_t reg_mask);
|
||||
|
|
@ -30,6 +23,3 @@ void host_arm_SUB_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm
|
|||
|
||||
void host_arm_call(codeblock_t *block, void *dst_addr);
|
||||
void host_arm_nop(codeblock_t *block);
|
||||
|
||||
void codegen_reset_literal_pool(codeblock_t *block);
|
||||
int add_literal(codeblock_t *block, uint32_t data);
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
#include <stdlib.h>
|
||||
#include "ibm.h"
|
||||
#include "codegen.h"
|
||||
#include "codegen_allocator.h"
|
||||
#include "codegen_backend.h"
|
||||
#include "codegen_backend_arm64_defs.h"
|
||||
#include "codegen_backend_arm64_ops.h"
|
||||
|
|
@ -83,9 +84,9 @@ static void build_load_routine(codeblock_t *block, int size, int is_float)
|
|||
LDP X29, X30, [SP, #-16]
|
||||
RET
|
||||
*/
|
||||
codegen_alloc(block, 80);
|
||||
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_MOVX_IMM(block, REG_X2, (uint64_t)readlookup2);
|
||||
host_arm64_LDRX_REG_LSL3(block, REG_X1, REG_X2, REG_X1);
|
||||
if (size != 1)
|
||||
{
|
||||
|
|
@ -107,9 +108,9 @@ static void build_load_routine(codeblock_t *block, int size, int is_float)
|
|||
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]);
|
||||
host_arm64_branch_set_offset(branch_offset, &block_write_data[block_pos]);
|
||||
if (size != 1)
|
||||
host_arm64_branch_set_offset(misaligned_offset, &block->data[block_pos]);
|
||||
host_arm64_branch_set_offset(misaligned_offset, &block_write_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);
|
||||
|
|
@ -128,8 +129,6 @@ static void build_load_routine(codeblock_t *block, int size, int is_float)
|
|||
host_arm64_FMOV_D_Q(block, REG_V_TEMP, REG_X0);
|
||||
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, int is_float)
|
||||
|
|
@ -154,9 +153,9 @@ static void build_store_routine(codeblock_t *block, int size, int is_float)
|
|||
LDP X29, X30, [SP, #-16]
|
||||
RET
|
||||
*/
|
||||
codegen_alloc(block, 80);
|
||||
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_MOVX_IMM(block, REG_X3, (uint64_t)writelookup2);
|
||||
host_arm64_LDRX_REG_LSL3(block, REG_X2, REG_X3, REG_X2);
|
||||
if (size != 1)
|
||||
{
|
||||
|
|
@ -178,9 +177,9 @@ static void build_store_routine(codeblock_t *block, int size, int is_float)
|
|||
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]);
|
||||
host_arm64_branch_set_offset(branch_offset, &block_write_data[block_pos]);
|
||||
if (size != 1)
|
||||
host_arm64_branch_set_offset(misaligned_offset, &block->data[block_pos]);
|
||||
host_arm64_branch_set_offset(misaligned_offset, &block_write_data[block_pos]);
|
||||
host_arm64_STP_PREIDX_X(block, REG_X29, REG_X30, REG_SP, -16);
|
||||
if (size == 4 && is_float)
|
||||
host_arm64_FMOV_W_S(block, REG_W1, REG_V_TEMP);
|
||||
|
|
@ -199,36 +198,34 @@ static void build_store_routine(codeblock_t *block, int size, int is_float)
|
|||
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];
|
||||
codegen_mem_load_byte = &block_write_data[block_pos];
|
||||
build_load_routine(block, 1, 0);
|
||||
codegen_mem_load_word = &codeblock[block_current].data[block_pos];
|
||||
codegen_mem_load_word = &block_write_data[block_pos];
|
||||
build_load_routine(block, 2, 0);
|
||||
codegen_mem_load_long = &codeblock[block_current].data[block_pos];
|
||||
codegen_mem_load_long = &block_write_data[block_pos];
|
||||
build_load_routine(block, 4, 0);
|
||||
codegen_mem_load_quad = &codeblock[block_current].data[block_pos];
|
||||
codegen_mem_load_quad = &block_write_data[block_pos];
|
||||
build_load_routine(block, 8, 0);
|
||||
codegen_mem_load_single = &codeblock[block_current].data[block_pos];
|
||||
codegen_mem_load_single = &block_write_data[block_pos];
|
||||
build_load_routine(block, 4, 1);
|
||||
codegen_mem_load_double = &codeblock[block_current].data[block_pos];
|
||||
codegen_mem_load_double = &block_write_data[block_pos];
|
||||
build_load_routine(block, 8, 1);
|
||||
|
||||
codegen_mem_store_byte = &codeblock[block_current].data[block_pos];
|
||||
codegen_mem_store_byte = &block_write_data[block_pos];
|
||||
build_store_routine(block, 1, 0);
|
||||
codegen_mem_store_word = &codeblock[block_current].data[block_pos];
|
||||
codegen_mem_store_word = &block_write_data[block_pos];
|
||||
build_store_routine(block, 2, 0);
|
||||
codegen_mem_store_long = &codeblock[block_current].data[block_pos];
|
||||
codegen_mem_store_long = &block_write_data[block_pos];
|
||||
build_store_routine(block, 4, 0);
|
||||
codegen_mem_store_quad = &codeblock[block_current].data[block_pos];
|
||||
codegen_mem_store_quad = &block_write_data[block_pos];
|
||||
build_store_routine(block, 8, 0);
|
||||
codegen_mem_store_single = &codeblock[block_current].data[block_pos];
|
||||
codegen_mem_store_single = &block_write_data[block_pos];
|
||||
build_store_routine(block, 4, 1);
|
||||
codegen_mem_store_double = &codeblock[block_current].data[block_pos];
|
||||
codegen_mem_store_double = &block_write_data[block_pos];
|
||||
build_store_routine(block, 8, 1);
|
||||
}
|
||||
|
||||
|
|
@ -236,50 +233,47 @@ static void build_fp_round_routine(codeblock_t *block, int is_quad)
|
|||
{
|
||||
uint64_t *jump_table;
|
||||
|
||||
codegen_alloc(block, 80);
|
||||
host_arm64_LDR_IMM_W(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.new_fp_control - (uintptr_t)&cpu_state);
|
||||
host_arm64_ADR(block, REG_TEMP2, 12);
|
||||
host_arm64_LDR_REG_X(block, REG_TEMP2, REG_TEMP2, REG_TEMP);
|
||||
host_arm64_BR(block, REG_TEMP2);
|
||||
|
||||
jump_table = &block->data[block_pos];
|
||||
addquad(0);
|
||||
addquad(0);
|
||||
addquad(0);
|
||||
addquad(0);
|
||||
jump_table = &block_write_data[block_pos];
|
||||
block_pos += 4*8;
|
||||
|
||||
jump_table[X87_ROUNDING_NEAREST] = (uint64_t)(uintptr_t)&block->data[block_pos]; //tie even
|
||||
jump_table[X87_ROUNDING_NEAREST] = (uint64_t)(uintptr_t)&block_write_data[block_pos]; //tie even
|
||||
if (is_quad)
|
||||
host_arm64_FCVTNS_X_D(block, REG_TEMP, REG_V_TEMP);
|
||||
else
|
||||
host_arm64_FCVTNS_W_D(block, REG_TEMP, REG_V_TEMP);
|
||||
host_arm64_RET(block, REG_X30);
|
||||
|
||||
jump_table[X87_ROUNDING_UP] = (uint64_t)(uintptr_t)&block->data[block_pos]; //pos inf
|
||||
jump_table[X87_ROUNDING_UP] = (uint64_t)(uintptr_t)&block_write_data[block_pos]; //pos inf
|
||||
if (is_quad)
|
||||
host_arm64_FCVTPS_X_D(block, REG_TEMP, REG_V_TEMP);
|
||||
else
|
||||
host_arm64_FCVTPS_W_D(block, REG_TEMP, REG_V_TEMP);
|
||||
host_arm64_RET(block, REG_X30);
|
||||
|
||||
jump_table[X87_ROUNDING_DOWN] = (uint64_t)(uintptr_t)&block->data[block_pos]; //neg inf
|
||||
jump_table[X87_ROUNDING_DOWN] = (uint64_t)(uintptr_t)&block_write_data[block_pos]; //neg inf
|
||||
if (is_quad)
|
||||
host_arm64_FCVTMS_X_D(block, REG_TEMP, REG_V_TEMP);
|
||||
else
|
||||
host_arm64_FCVTMS_W_D(block, REG_TEMP, REG_V_TEMP);
|
||||
host_arm64_RET(block, REG_X30);
|
||||
|
||||
jump_table[X87_ROUNDING_CHOP] = (uint64_t)(uintptr_t)&block->data[block_pos]; //zero
|
||||
jump_table[X87_ROUNDING_CHOP] = (uint64_t)(uintptr_t)&block_write_data[block_pos]; //zero
|
||||
if (is_quad)
|
||||
host_arm64_FCVTZS_X_D(block, REG_TEMP, REG_V_TEMP);
|
||||
else
|
||||
host_arm64_FCVTZS_W_D(block, REG_TEMP, REG_V_TEMP);
|
||||
host_arm64_RET(block, REG_X30);
|
||||
|
||||
block_pos = (block_pos + 63) & ~63;
|
||||
}
|
||||
|
||||
void codegen_backend_init()
|
||||
{
|
||||
codeblock_t *block;
|
||||
int c;
|
||||
#if defined(__linux__) || defined(__APPLE__)
|
||||
void *start;
|
||||
|
|
@ -288,13 +282,6 @@ void codegen_backend_init()
|
|||
long pagemask = ~(pagesize - 1);
|
||||
#endif
|
||||
|
||||
#if defined WIN32 || defined _WIN32 || defined _WIN32
|
||||
codeblock_data = VirtualAlloc(NULL, BLOCK_SIZE * BLOCK_DATA_SIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
|
||||
#else
|
||||
codeblock_data = malloc(BLOCK_SIZE * BLOCK_DATA_SIZE);
|
||||
#endif
|
||||
if (!codeblock_data)
|
||||
fatal("codeblock_data failed to alloc - %i\n", (BLOCK_SIZE+1) * BLOCK_DATA_SIZE);
|
||||
codeblock = malloc(BLOCK_SIZE * sizeof(codeblock_t));
|
||||
codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *));
|
||||
|
||||
|
|
@ -304,29 +291,24 @@ void codegen_backend_init()
|
|||
for (c = 0; c < BLOCK_SIZE; c++)
|
||||
{
|
||||
codeblock[c].pc = BLOCK_PC_INVALID;
|
||||
codeblock[c].data = &codeblock_data[c * BLOCK_SIZE];
|
||||
}
|
||||
|
||||
#if defined(__linux__) || defined(__APPLE__)
|
||||
start = (void *)((long)codeblock_data & pagemask);
|
||||
len = ((BLOCK_SIZE * BLOCK_DATA_SIZE) + pagesize) & pagemask;
|
||||
if (mprotect(start, len, PROT_READ | PROT_WRITE | PROT_EXEC) != 0)
|
||||
{
|
||||
perror("mprotect");
|
||||
exit(-1);
|
||||
}
|
||||
#endif
|
||||
// pclog("Codegen is %p\n", (void *)pages[0xfab12 >> 12].block);
|
||||
|
||||
block_current = 0;
|
||||
block_pos = 0;
|
||||
codegen_reset_literal_pool(&codeblock[block_current]);
|
||||
build_loadstore_routines(&codeblock[block_current]);
|
||||
block = &codeblock[block_current];
|
||||
block->head_mem_block = codegen_allocator_allocate(NULL);
|
||||
block->data = codeblock_allocator_get_ptr(block->head_mem_block);
|
||||
block_write_data = block->data;
|
||||
build_loadstore_routines(block);
|
||||
|
||||
codegen_fp_round = &codeblock[block_current].data[block_pos];
|
||||
build_fp_round_routine(&codeblock[block_current], 0);
|
||||
codegen_fp_round_quad = &codeblock[block_current].data[block_pos];
|
||||
build_fp_round_routine(&codeblock[block_current], 1);
|
||||
codegen_fp_round = &block_write_data[block_pos];
|
||||
build_fp_round_routine(block, 0);
|
||||
codegen_fp_round_quad = &block_write_data[block_pos];
|
||||
build_fp_round_routine(block, 1);
|
||||
|
||||
block_write_data = NULL;
|
||||
|
||||
asm("mrs %0, fpcr\n"
|
||||
: "=r" (cpu_state.old_fp_control)
|
||||
|
|
@ -340,14 +322,11 @@ void codegen_set_rounding_mode(int mode)
|
|||
cpu_state.new_fp_control = mode << 3;
|
||||
}
|
||||
|
||||
/*R11 - literal pool
|
||||
R10 - cpu_state*/
|
||||
/*R10 - cpu_state*/
|
||||
void codegen_backend_prologue(codeblock_t *block)
|
||||
{
|
||||
int offset;
|
||||
|
||||
codegen_reset_literal_pool(block);
|
||||
|
||||
block_pos = 0;
|
||||
|
||||
block_pos = BLOCK_GPF_OFFSET;
|
||||
|
|
@ -378,8 +357,7 @@ void codegen_backend_prologue(codeblock_t *block)
|
|||
host_arm64_STP_PREIDX_X(block, REG_X21, REG_X22, REG_SP, -16);
|
||||
host_arm64_STP_PREIDX_X(block, REG_X19, REG_X20, REG_SP, -64);
|
||||
|
||||
offset = add_literal_q(block, (uintptr_t)&cpu_state);
|
||||
host_arm64_LDR_LITERAL_X(block, REG_CPUSTATE, offset);
|
||||
host_arm64_MOVX_IMM(block, REG_CPUSTATE, (uint64_t)&cpu_state);
|
||||
|
||||
if (block->flags & CODEBLOCK_HAS_FPU)
|
||||
{
|
||||
|
|
@ -399,12 +377,7 @@ void codegen_backend_epilogue(codeblock_t *block)
|
|||
host_arm64_LDP_POSTIDX_X(block, REG_X29, REG_X30, REG_SP, 16);
|
||||
host_arm64_RET(block, REG_X30);
|
||||
|
||||
if (block_pos > ARM_LITERAL_POOL_OFFSET)
|
||||
fatal("Over limit!\n");
|
||||
|
||||
|
||||
|
||||
__clear_cache(&block->data[0], &block->data[block_pos]);
|
||||
codegen_allocator_clean_blocks(block->head_mem_block);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -9,16 +9,10 @@
|
|||
|
||||
#define HASH(l) ((l) & 0x1ffff)
|
||||
|
||||
/*Hack until better memory management written*/
|
||||
/*#define BLOCK_EXIT_OFFSET 0x7f0*/
|
||||
|
||||
#define BLOCK_GPF_OFFSET 0
|
||||
#define BLOCK_EXIT_OFFSET 32
|
||||
|
||||
#define ARM_LITERAL_POOL_OFFSET 0xf000
|
||||
|
||||
/*#define BLOCK_MAX 1720*/
|
||||
#define BLOCK_MAX 65208
|
||||
#define BLOCK_MAX 0x3c0
|
||||
|
||||
|
||||
void host_arm64_BLR(codeblock_t *block, int addr_reg);
|
||||
|
|
@ -36,7 +30,3 @@ void host_arm64_STRB_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int o
|
|||
|
||||
void host_arm64_call(codeblock_t *block, void *dst_addr);
|
||||
void host_arm64_mov_imm(codeblock_t *block, int reg, uint32_t imm_data);
|
||||
|
||||
void codegen_reset_literal_pool(codeblock_t *block);
|
||||
int add_literal(codeblock_t *block, uint32_t data);
|
||||
int add_literal_q(codeblock_t *block, uint64_t data);
|
||||
|
|
|
|||
|
|
@ -2,22 +2,12 @@
|
|||
|
||||
#include "ibm.h"
|
||||
#include "codegen.h"
|
||||
#include "codegen_allocator.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)
|
||||
|
|
@ -53,21 +43,23 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val)
|
|||
#define OPCODE_B (0x14 << OPCODE_SHIFT)
|
||||
#define OPCODE_BCOND (0x54 << OPCODE_SHIFT)
|
||||
#define OPCODE_CBNZ (0xb5 << OPCODE_SHIFT)
|
||||
#define OPCODE_CBZ (0xb4 << 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_SUBX_IMM (0xd1 << OPCODE_SHIFT)
|
||||
#define OPCODE_TBNZ (0x37 << OPCODE_SHIFT)
|
||||
#define OPCODE_TBZ (0x36 << 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_MOVK_X (0x1e5 << 23)
|
||||
#define OPCODE_MOVZ_W (0x0a5 << 23)
|
||||
#define OPCODE_MOVZ_X (0x1a5 << 23)
|
||||
#define OPCODE_ORR_IMM (0x064 << 23)
|
||||
|
||||
#define OPCODE_BFI (0x0cc << 22)
|
||||
|
|
@ -225,6 +217,7 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val)
|
|||
|
||||
#define BIT_TBxZ(bit) ((((bit) & 0x1f) << 19) | (((bit) & 0x20) ? (1 << 31) : 0))
|
||||
|
||||
#define OFFSET14(offset) (((offset >> 2) << 5) & 0x0007ffe0)
|
||||
#define OFFSET19(offset) (((offset >> 2) << 5) & 0x00ffffe0)
|
||||
#define OFFSET20(offset) (((offset & 3) << 29) | ((((offset) & 0x1fffff) >> 2) << 5))
|
||||
#define OFFSET26(offset) ((offset >> 2) & 0x03ffffff)
|
||||
|
|
@ -242,12 +235,6 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val)
|
|||
|
||||
#define DUP_ELEMENT(element) ((element) << 19)
|
||||
|
||||
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)
|
||||
{
|
||||
|
|
@ -268,33 +255,6 @@ static int offset_is_26bit(int offset)
|
|||
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))
|
||||
|
|
@ -308,6 +268,39 @@ static inline int imm_is_imm12(uint32_t imm_data)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void codegen_allocate_new_block(codeblock_t *block);
|
||||
|
||||
static inline void codegen_addlong(codeblock_t *block, uint32_t val)
|
||||
{
|
||||
if (block_pos >= (BLOCK_MAX-4))
|
||||
codegen_allocate_new_block(block);
|
||||
*(uint32_t *)&block_write_data[block_pos] = val;
|
||||
block_pos += 4;
|
||||
}
|
||||
|
||||
static void codegen_allocate_new_block(codeblock_t *block)
|
||||
{
|
||||
/*Current block is full. Allocate a new block*/
|
||||
struct mem_block_t *new_block = codegen_allocator_allocate(block->head_mem_block);
|
||||
uint8_t *new_ptr = codeblock_allocator_get_ptr(new_block);
|
||||
uint32_t offset = (uintptr_t)new_ptr - (uintptr_t)&block_write_data[block_pos];
|
||||
|
||||
if (!offset_is_26bit(offset))
|
||||
fatal("codegen_allocate_new_block - offset out of range %x\n", offset);
|
||||
/*Add a jump instruction to the new block*/
|
||||
*(uint32_t *)&block_write_data[block_pos] = OPCODE_B | OFFSET26(offset);
|
||||
|
||||
/*Set write address to start of new block*/
|
||||
block_pos = 0;
|
||||
block_write_data = new_ptr;
|
||||
}
|
||||
|
||||
void codegen_alloc(codeblock_t *block, int size)
|
||||
{
|
||||
if (block_pos >= (BLOCK_MAX-size))
|
||||
codegen_allocate_new_block(block);
|
||||
}
|
||||
|
||||
void host_arm64_ADD_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data)
|
||||
{
|
||||
if (!imm_data)
|
||||
|
|
@ -462,7 +455,10 @@ void host_arm64_ASR(codeblock_t *block, int dst_reg, int src_n_reg, int shift_re
|
|||
|
||||
void host_arm64_B(codeblock_t *block, void *dest)
|
||||
{
|
||||
int offset = (uintptr_t)dest - (uintptr_t)&block->data[block_pos];
|
||||
int offset;
|
||||
|
||||
codegen_alloc(block, 4);
|
||||
offset = (uintptr_t)dest - (uintptr_t)&block_write_data[block_pos];
|
||||
|
||||
if (!offset_is_26bit(offset))
|
||||
fatal("host_arm64_B - offset out of range %x\n", offset);
|
||||
|
|
@ -481,79 +477,107 @@ void host_arm64_BLR(codeblock_t *block, int addr_reg)
|
|||
|
||||
uint32_t *host_arm64_BCC_(codeblock_t *block)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_BCOND | COND_CC);
|
||||
return (uint32_t *)&block->data[block_pos-4];
|
||||
codegen_alloc(block, 12);
|
||||
codegen_addlong(block, OPCODE_BCOND | COND_CS | OFFSET19(8));
|
||||
codegen_addlong(block, OPCODE_B);
|
||||
return (uint32_t *)&block_write_data[block_pos-4];
|
||||
}
|
||||
uint32_t *host_arm64_BCS_(codeblock_t *block)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_BCOND | COND_CS);
|
||||
return (uint32_t *)&block->data[block_pos-4];
|
||||
codegen_alloc(block, 12);
|
||||
codegen_addlong(block, OPCODE_BCOND | COND_CC | OFFSET19(8));
|
||||
codegen_addlong(block, OPCODE_B);
|
||||
return (uint32_t *)&block_write_data[block_pos-4];
|
||||
}
|
||||
uint32_t *host_arm64_BEQ_(codeblock_t *block)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_BCOND | COND_EQ);
|
||||
return (uint32_t *)&block->data[block_pos-4];
|
||||
codegen_alloc(block, 12);
|
||||
codegen_addlong(block, OPCODE_BCOND | COND_NE | OFFSET19(8));
|
||||
codegen_addlong(block, OPCODE_B);
|
||||
return (uint32_t *)&block_write_data[block_pos-4];
|
||||
}
|
||||
uint32_t *host_arm64_BGE_(codeblock_t *block)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_BCOND | COND_GE);
|
||||
return (uint32_t *)&block->data[block_pos-4];
|
||||
codegen_alloc(block, 12);
|
||||
codegen_addlong(block, OPCODE_BCOND | COND_LT | OFFSET19(8));
|
||||
codegen_addlong(block, OPCODE_B);
|
||||
return (uint32_t *)&block_write_data[block_pos-4];
|
||||
}
|
||||
uint32_t *host_arm64_BGT_(codeblock_t *block)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_BCOND | COND_GT);
|
||||
return (uint32_t *)&block->data[block_pos-4];
|
||||
codegen_alloc(block, 12);
|
||||
codegen_addlong(block, OPCODE_BCOND | COND_LE | OFFSET19(8));
|
||||
codegen_addlong(block, OPCODE_B);
|
||||
return (uint32_t *)&block_write_data[block_pos-4];
|
||||
}
|
||||
uint32_t *host_arm64_BHI_(codeblock_t *block)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_BCOND | COND_HI);
|
||||
return (uint32_t *)&block->data[block_pos-4];
|
||||
codegen_alloc(block, 12);
|
||||
codegen_addlong(block, OPCODE_BCOND | COND_LS | OFFSET19(8));
|
||||
codegen_addlong(block, OPCODE_B);
|
||||
return (uint32_t *)&block_write_data[block_pos-4];
|
||||
}
|
||||
uint32_t *host_arm64_BLE_(codeblock_t *block)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_BCOND | COND_LE);
|
||||
return (uint32_t *)&block->data[block_pos-4];
|
||||
codegen_alloc(block, 12);
|
||||
codegen_addlong(block, OPCODE_BCOND | COND_GT | OFFSET19(8));
|
||||
codegen_addlong(block, OPCODE_B);
|
||||
return (uint32_t *)&block_write_data[block_pos-4];
|
||||
}
|
||||
uint32_t *host_arm64_BLS_(codeblock_t *block)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_BCOND | COND_LS);
|
||||
return (uint32_t *)&block->data[block_pos-4];
|
||||
codegen_alloc(block, 12);
|
||||
codegen_addlong(block, OPCODE_BCOND | COND_HI | OFFSET19(8));
|
||||
codegen_addlong(block, OPCODE_B);
|
||||
return (uint32_t *)&block_write_data[block_pos-4];
|
||||
}
|
||||
uint32_t *host_arm64_BLT_(codeblock_t *block)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_BCOND | COND_LT);
|
||||
return (uint32_t *)&block->data[block_pos-4];
|
||||
codegen_alloc(block, 12);
|
||||
codegen_addlong(block, OPCODE_BCOND | COND_GE | OFFSET19(8));
|
||||
codegen_addlong(block, OPCODE_B);
|
||||
return (uint32_t *)&block_write_data[block_pos-4];
|
||||
}
|
||||
uint32_t *host_arm64_BMI_(codeblock_t *block)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_BCOND | COND_MI);
|
||||
return (uint32_t *)&block->data[block_pos-4];
|
||||
codegen_alloc(block, 12);
|
||||
codegen_addlong(block, OPCODE_BCOND | COND_PL | OFFSET19(8));
|
||||
codegen_addlong(block, OPCODE_B);
|
||||
return (uint32_t *)&block_write_data[block_pos-4];
|
||||
}
|
||||
uint32_t *host_arm64_BNE_(codeblock_t *block)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_BCOND | COND_NE);
|
||||
return (uint32_t *)&block->data[block_pos-4];
|
||||
codegen_alloc(block, 12);
|
||||
codegen_addlong(block, OPCODE_BCOND | COND_EQ | OFFSET19(8));
|
||||
codegen_addlong(block, OPCODE_B);
|
||||
return (uint32_t *)&block_write_data[block_pos-4];
|
||||
}
|
||||
uint32_t *host_arm64_BPL_(codeblock_t *block)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_BCOND | COND_PL);
|
||||
return (uint32_t *)&block->data[block_pos-4];
|
||||
codegen_alloc(block, 12);
|
||||
codegen_addlong(block, OPCODE_BCOND | COND_MI | OFFSET19(8));
|
||||
codegen_addlong(block, OPCODE_B);
|
||||
return (uint32_t *)&block_write_data[block_pos-4];
|
||||
}
|
||||
uint32_t *host_arm64_BVC_(codeblock_t *block)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_BCOND | COND_VC);
|
||||
return (uint32_t *)&block->data[block_pos-4];
|
||||
codegen_alloc(block, 12);
|
||||
codegen_addlong(block, OPCODE_BCOND | COND_VS | OFFSET19(8));
|
||||
codegen_addlong(block, OPCODE_B);
|
||||
return (uint32_t *)&block_write_data[block_pos-4];
|
||||
}
|
||||
uint32_t *host_arm64_BVS_(codeblock_t *block)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_BCOND | COND_VS);
|
||||
return (uint32_t *)&block->data[block_pos-4];
|
||||
codegen_alloc(block, 12);
|
||||
codegen_addlong(block, OPCODE_BCOND | COND_VC | OFFSET19(8));
|
||||
codegen_addlong(block, OPCODE_B);
|
||||
return (uint32_t *)&block_write_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);
|
||||
*opcode |= OFFSET26(offset);
|
||||
}
|
||||
|
||||
void host_arm64_BR(codeblock_t *block, int addr_reg)
|
||||
|
|
@ -574,10 +598,16 @@ void host_arm64_BIC_REG_V(codeblock_t *block, int dst_reg, int src_n_reg, int sr
|
|||
|
||||
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));
|
||||
int offset = dest - (uintptr_t)&block_write_data[block_pos];
|
||||
if (offset_is_19bit(offset))
|
||||
codegen_addlong(block, OPCODE_CBNZ | OFFSET19(offset) | Rt(reg));
|
||||
else
|
||||
{
|
||||
codegen_alloc(block, 12);
|
||||
codegen_addlong(block, OPCODE_CBZ | OFFSET19(8) | Rt(reg));
|
||||
offset = (uintptr_t)dest - (uintptr_t)&block_write_data[block_pos];
|
||||
codegen_addlong(block, OPCODE_B | OFFSET26(offset));
|
||||
}
|
||||
}
|
||||
|
||||
void host_arm64_CMEQ_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg)
|
||||
|
|
@ -880,24 +910,6 @@ void host_arm64_LDR_IMM_X(codeblock_t *block, int dest_reg, int base_reg, int of
|
|||
codegen_addlong(block, OPCODE_LDR_IMM_X | OFFSET12_Q(offset) | Rn(base_reg) | Rt(dest_reg));
|
||||
}
|
||||
|
||||
void host_arm64_LDR_LITERAL_W(codeblock_t *block, int dest_reg, int literal_offset)
|
||||
{
|
||||
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));
|
||||
|
|
@ -977,6 +989,16 @@ void host_arm64_MOV_REG_LSR(codeblock_t *block, int dst_reg, int src_m_reg, int
|
|||
codegen_addlong(block, OPCODE_ORR_LSR | Rd(dst_reg) | Rn(REG_WZR) | Rm(src_m_reg) | DATPROC_SHIFT(shift));
|
||||
}
|
||||
|
||||
void host_arm64_MOVX_IMM(codeblock_t *block, int reg, uint64_t imm_data)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_MOVZ_X | MOV_WIDE_HW(0) | IMM16(imm_data & 0xffff) | Rd(reg));
|
||||
if ((imm_data >> 16) & 0xffff)
|
||||
codegen_addlong(block, OPCODE_MOVK_X | MOV_WIDE_HW(1) | IMM16((imm_data >> 16) & 0xffff) | Rd(reg));
|
||||
if ((imm_data >> 32) & 0xffff)
|
||||
codegen_addlong(block, OPCODE_MOVK_X | MOV_WIDE_HW(2) | IMM16((imm_data >> 32) & 0xffff) | Rd(reg));
|
||||
if ((imm_data >> 48) & 0xffff)
|
||||
codegen_addlong(block, OPCODE_MOVK_X | MOV_WIDE_HW(3) | IMM16((imm_data >> 48) & 0xffff) | Rd(reg));
|
||||
}
|
||||
void host_arm64_MOVX_REG(codeblock_t *block, int dst_reg, int src_m_reg, int shift)
|
||||
{
|
||||
if (dst_reg != src_m_reg)
|
||||
|
|
@ -1265,8 +1287,10 @@ void host_arm64_SUB_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_
|
|||
|
||||
uint32_t *host_arm64_TBNZ(codeblock_t *block, int reg, int bit)
|
||||
{
|
||||
codegen_addlong(block, OPCODE_TBNZ | Rt(reg) | BIT_TBxZ(bit));
|
||||
return (uint32_t *)&block->data[block_pos-4];
|
||||
codegen_alloc(block, 12);
|
||||
codegen_addlong(block, OPCODE_TBZ | Rt(reg) | BIT_TBxZ(bit) | OFFSET14(8));
|
||||
codegen_addlong(block, OPCODE_B);
|
||||
return (uint32_t *)&block_write_data[block_pos-4];
|
||||
}
|
||||
|
||||
void host_arm64_UBFX(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width)
|
||||
|
|
@ -1346,15 +1370,13 @@ void host_arm64_ZIP2_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src
|
|||
|
||||
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_MOVX_IMM(block, REG_X16, (uint64_t)dst_addr);
|
||||
host_arm64_BLR(block, REG_X16);
|
||||
}
|
||||
|
||||
void host_arm64_jump(codeblock_t *block, uintptr_t dst_addr)
|
||||
{
|
||||
int offset = add_literal_q(block, (uintptr_t)dst_addr);
|
||||
host_arm64_LDR_LITERAL_X(block, REG_X16, offset);
|
||||
host_arm64_MOVX_IMM(block, REG_X16, (uint64_t)dst_addr);
|
||||
host_arm64_BR(block, REG_X16);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -121,8 +121,6 @@ void host_arm64_LDP_POSTIDX_X(codeblock_t *block, int src_reg1, int src_reg2, in
|
|||
|
||||
void host_arm64_LDR_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int offset);
|
||||
void host_arm64_LDR_IMM_X(codeblock_t *block, int dest_reg, int base_reg, int offset);
|
||||
void host_arm64_LDR_LITERAL_W(codeblock_t *block, int dest_reg, int literal_offset);
|
||||
void host_arm64_LDR_LITERAL_X(codeblock_t *block, int dest_reg, int literal_offset);
|
||||
void host_arm64_LDR_REG(codeblock_t *block, int dest_reg, int base_reg, int offset_reg);
|
||||
void host_arm64_LDR_REG_X(codeblock_t *block, int dest_reg, int base_reg, int offset_reg);
|
||||
|
||||
|
|
@ -146,6 +144,7 @@ void host_arm64_MOV_REG_ASR(codeblock_t *block, int dst_reg, int src_m_reg, int
|
|||
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_MOVX_IMM(codeblock_t *block, int reg, uint64_t imm_data);
|
||||
void host_arm64_MOVX_REG(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);
|
||||
|
|
@ -170,6 +169,8 @@ void host_arm64_SBFX(codeblock_t *block, int dst_reg, int src_reg, int lsb, int
|
|||
void host_arm64_SCVTF_D_Q(codeblock_t *block, int dst_reg, int src_reg);
|
||||
void host_arm64_SCVTF_D_W(codeblock_t *block, int dst_reg, int src_reg);
|
||||
|
||||
void host_arm64_SCVTF_V2S(codeblock_t *block, int dst_reg, int src_reg);
|
||||
|
||||
void host_arm64_SQADD_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
|
||||
void host_arm64_SQADD_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
|
||||
void host_arm64_SQSUB_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
|
||||
|
|
@ -253,4 +254,4 @@ void host_arm64_mov_imm(codeblock_t *block, int reg, uint32_t imm_data);
|
|||
|
||||
void codegen_direct_read_8(codeblock_t *block, int host_reg, void *p);
|
||||
|
||||
int add_literal_q(codeblock_t *block, uint64_t data);
|
||||
void codegen_alloc(codeblock_t *block, int size);
|
||||
|
|
@ -779,7 +779,7 @@ static int codegen_FP_ENTER(codeblock_t *block, uop_t *uop)
|
|||
host_arm64_call(block, x86_int);
|
||||
host_arm64_B(block, &block->data[BLOCK_EXIT_OFFSET]);
|
||||
|
||||
host_arm64_branch_set_offset(branch_ptr, &block->data[block_pos]);
|
||||
host_arm64_branch_set_offset(branch_ptr, &block_write_data[block_pos]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -876,12 +876,11 @@ static int codegen_LOAD_SEG(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);
|
||||
int offset = add_literal_q(block, (uintptr_t)uop->p);
|
||||
|
||||
if (!REG_IS_W(src_size))
|
||||
fatal("LOAD_SEG %02x %p\n", uop->src_reg_a_real, uop->p);
|
||||
|
||||
host_arm64_LDR_LITERAL_X(block, REG_ARG1, offset);
|
||||
host_arm64_MOVX_IMM(block, REG_ARG1, (uint64_t)uop->p);
|
||||
host_arm64_AND_IMM(block, REG_ARG0, src_reg, 0xffff);
|
||||
host_arm64_call(block, (void *)loadseg);
|
||||
host_arm64_CBNZ(block, REG_X0, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]);
|
||||
|
|
@ -1229,8 +1228,7 @@ static int codegen_MOV_IMM(codeblock_t *block, uop_t *uop)
|
|||
}
|
||||
static int codegen_MOV_PTR(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
int offset = add_literal_q(block, (uintptr_t)uop->p);
|
||||
host_arm64_LDR_LITERAL_X(block, uop->dest_reg_a_real, offset);
|
||||
host_arm64_MOVX_IMM(block, uop->dest_reg_a_real, (uint64_t)uop->p);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1371,7 +1369,7 @@ static int codegen_MOV_INT_DOUBLE_64(codeblock_t *block, uop_t *uop)
|
|||
host_arm64_call(block, codegen_fp_round_quad);
|
||||
host_arm64_FMOV_D_Q(block, dest_reg, REG_TEMP);
|
||||
|
||||
host_arm64_branch_set_offset(branch_offset, &block->data[block_pos]);
|
||||
host_arm64_branch_set_offset(branch_offset, &block_write_data[block_pos]);
|
||||
}
|
||||
else
|
||||
fatal("MOV_INT_DOUBLE_64 %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real);
|
||||
|
|
@ -3031,8 +3029,6 @@ void codegen_direct_write_double_stack(codeblock_t *block, int stack_offset, int
|
|||
|
||||
void codegen_set_jump_dest(codeblock_t *block, void *p)
|
||||
{
|
||||
int offset = (uintptr_t)&block->data[block_pos] - (uintptr_t)p;
|
||||
|
||||
*(uint32_t *)p |= OFFSET19(offset);
|
||||
host_arm64_branch_set_offset(p, &block_write_data[block_pos]);
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -2,21 +2,11 @@
|
|||
|
||||
#include "ibm.h"
|
||||
#include "codegen.h"
|
||||
#include "codegen_allocator.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 Rs(x) ((x) << 8)
|
||||
#define Rd(x) ((x) << 12)
|
||||
|
|
@ -207,6 +197,37 @@ static inline void codegen_addlong(codeblock_t *block, uint32_t val)
|
|||
|
||||
#define VDUP_32_IMM(imm) ((imm) << 19)
|
||||
|
||||
static void codegen_allocate_new_block(codeblock_t *block);
|
||||
|
||||
static inline void codegen_addlong(codeblock_t *block, uint32_t val)
|
||||
{
|
||||
if (block_pos >= (BLOCK_MAX-4))
|
||||
codegen_allocate_new_block(block);
|
||||
*(uint32_t *)&block_write_data[block_pos] = val;
|
||||
block_pos += 4;
|
||||
}
|
||||
|
||||
static void codegen_allocate_new_block(codeblock_t *block)
|
||||
{
|
||||
/*Current block is full. Allocate a new block*/
|
||||
struct mem_block_t *new_block = codegen_allocator_allocate(block->head_mem_block);
|
||||
uint8_t *new_ptr = codeblock_allocator_get_ptr(new_block);
|
||||
uint32_t offset = ((uintptr_t)new_ptr - (uintptr_t)&block_write_data[block_pos]) - 8;
|
||||
|
||||
/*Add a jump instruction to the new block*/
|
||||
*(uint32_t *)&block_write_data[block_pos] = COND_AL | OPCODE_B | B_OFFSET(offset);
|
||||
|
||||
/*Set write address to start of new block*/
|
||||
block_pos = 0;
|
||||
block_write_data = new_ptr;
|
||||
}
|
||||
|
||||
static inline void codegen_alloc_4(codeblock_t *block)
|
||||
{
|
||||
if (block_pos >= (BLOCK_MAX-4))
|
||||
codegen_allocate_new_block(block);
|
||||
}
|
||||
|
||||
static inline uint32_t arm_data_offset(int offset)
|
||||
{
|
||||
if (offset < -0xffc || offset > 0xffc)
|
||||
|
|
@ -321,7 +342,10 @@ void host_arm_AND_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int sr
|
|||
|
||||
void host_arm_B(codeblock_t *block, uintptr_t dest_addr)
|
||||
{
|
||||
uint32_t offset = (dest_addr - (uintptr_t)&block->data[block_pos]) - 8;
|
||||
uint32_t offset;
|
||||
|
||||
codegen_alloc_4(block);
|
||||
offset = (dest_addr - (uintptr_t)&block_write_data[block_pos]) - 8;
|
||||
|
||||
if ((offset & 0xfe000000) && (offset & 0xfe000000) != 0xfe000000)
|
||||
{
|
||||
|
|
@ -366,7 +390,10 @@ void host_arm_BIC_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int sr
|
|||
|
||||
void host_arm_BL(codeblock_t *block, uintptr_t dest_addr)
|
||||
{
|
||||
uint32_t offset = (dest_addr - (uintptr_t)&block->data[block_pos]) - 8;
|
||||
uint32_t offset;
|
||||
|
||||
codegen_alloc_4(block);
|
||||
offset = (dest_addr - (uintptr_t)&block_write_data[block_pos]) - 8;
|
||||
|
||||
if ((offset & 0xfe000000) && (offset & 0xfe000000) != 0xfe000000)
|
||||
{
|
||||
|
|
@ -378,7 +405,10 @@ void host_arm_BL(codeblock_t *block, uintptr_t dest_addr)
|
|||
}
|
||||
void host_arm_BL_r1(codeblock_t *block, uintptr_t dest_addr)
|
||||
{
|
||||
uint32_t offset = (dest_addr - (uintptr_t)&block->data[block_pos]) - 8;
|
||||
uint32_t offset;
|
||||
|
||||
codegen_alloc_4(block);
|
||||
offset = (dest_addr - (uintptr_t)&block_write_data[block_pos]) - 8;
|
||||
|
||||
if ((offset & 0xfe000000) && (offset & 0xfe000000) != 0xfe000000)
|
||||
{
|
||||
|
|
@ -397,90 +427,93 @@ uint32_t *host_arm_BCC_(codeblock_t *block)
|
|||
{
|
||||
codegen_addlong(block, COND_CC | OPCODE_B);
|
||||
|
||||
return (uint32_t *)&block->data[block_pos - 4];
|
||||
return (uint32_t *)&block_write_data[block_pos - 4];
|
||||
}
|
||||
uint32_t *host_arm_BCS_(codeblock_t *block)
|
||||
{
|
||||
codegen_addlong(block, COND_CS | OPCODE_B);
|
||||
|
||||
return (uint32_t *)&block->data[block_pos - 4];
|
||||
return (uint32_t *)&block_write_data[block_pos - 4];
|
||||
}
|
||||
uint32_t *host_arm_BEQ_(codeblock_t *block)
|
||||
{
|
||||
codegen_addlong(block, COND_EQ | OPCODE_B);
|
||||
|
||||
return (uint32_t *)&block->data[block_pos - 4];
|
||||
return (uint32_t *)&block_write_data[block_pos - 4];
|
||||
}
|
||||
uint32_t *host_arm_BGE_(codeblock_t *block)
|
||||
{
|
||||
codegen_addlong(block, COND_GE | OPCODE_B);
|
||||
|
||||
return (uint32_t *)&block->data[block_pos - 4];
|
||||
return (uint32_t *)&block_write_data[block_pos - 4];
|
||||
}
|
||||
uint32_t *host_arm_BGT_(codeblock_t *block)
|
||||
{
|
||||
codegen_addlong(block, COND_GT | OPCODE_B);
|
||||
|
||||
return (uint32_t *)&block->data[block_pos - 4];
|
||||
return (uint32_t *)&block_write_data[block_pos - 4];
|
||||
}
|
||||
uint32_t *host_arm_BHI_(codeblock_t *block)
|
||||
{
|
||||
codegen_addlong(block, COND_HI | OPCODE_B);
|
||||
|
||||
return (uint32_t *)&block->data[block_pos - 4];
|
||||
return (uint32_t *)&block_write_data[block_pos - 4];
|
||||
}
|
||||
uint32_t *host_arm_BLE_(codeblock_t *block)
|
||||
{
|
||||
codegen_addlong(block, COND_LE | OPCODE_B);
|
||||
|
||||
return (uint32_t *)&block->data[block_pos - 4];
|
||||
return (uint32_t *)&block_write_data[block_pos - 4];
|
||||
}
|
||||
uint32_t *host_arm_BLS_(codeblock_t *block)
|
||||
{
|
||||
codegen_addlong(block, COND_LS | OPCODE_B);
|
||||
|
||||
return (uint32_t *)&block->data[block_pos - 4];
|
||||
return (uint32_t *)&block_write_data[block_pos - 4];
|
||||
}
|
||||
uint32_t *host_arm_BLT_(codeblock_t *block)
|
||||
{
|
||||
codegen_addlong(block, COND_LT | OPCODE_B);
|
||||
|
||||
return (uint32_t *)&block->data[block_pos - 4];
|
||||
return (uint32_t *)&block_write_data[block_pos - 4];
|
||||
}
|
||||
uint32_t *host_arm_BMI_(codeblock_t *block)
|
||||
{
|
||||
codegen_addlong(block, COND_MI | OPCODE_B);
|
||||
|
||||
return (uint32_t *)&block->data[block_pos - 4];
|
||||
return (uint32_t *)&block_write_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];
|
||||
return (uint32_t *)&block_write_data[block_pos - 4];
|
||||
}
|
||||
uint32_t *host_arm_BPL_(codeblock_t *block)
|
||||
{
|
||||
codegen_addlong(block, COND_PL | OPCODE_B);
|
||||
|
||||
return (uint32_t *)&block->data[block_pos - 4];
|
||||
return (uint32_t *)&block_write_data[block_pos - 4];
|
||||
}
|
||||
uint32_t *host_arm_BVC_(codeblock_t *block)
|
||||
{
|
||||
codegen_addlong(block, COND_VC | OPCODE_B);
|
||||
|
||||
return (uint32_t *)&block->data[block_pos - 4];
|
||||
return (uint32_t *)&block_write_data[block_pos - 4];
|
||||
}
|
||||
uint32_t *host_arm_BVS_(codeblock_t *block)
|
||||
{
|
||||
codegen_addlong(block, COND_VS | OPCODE_B);
|
||||
|
||||
return (uint32_t *)&block->data[block_pos - 4];
|
||||
return (uint32_t *)&block_write_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;
|
||||
uint32_t offset;
|
||||
|
||||
codegen_alloc_4(block);
|
||||
offset = (dest_addr - (uintptr_t)&block_write_data[block_pos]) - 8;
|
||||
|
||||
if ((offset & 0xfe000000) && (offset & 0xfe000000) != 0xfe000000)
|
||||
fatal("host_arm_BEQ - out of range %08x %i\n", offset, offset);
|
||||
|
|
@ -489,7 +522,10 @@ void host_arm_BEQ(codeblock_t *block, uintptr_t dest_addr)
|
|||
}
|
||||
void host_arm_BNE(codeblock_t *block, uintptr_t dest_addr)
|
||||
{
|
||||
uint32_t offset = (dest_addr - (uintptr_t)&block->data[block_pos]) - 8;
|
||||
uint32_t offset;
|
||||
|
||||
codegen_alloc_4(block);
|
||||
offset = (dest_addr - (uintptr_t)&block_write_data[block_pos]) - 8;
|
||||
|
||||
if ((offset & 0xfe000000) && (offset & 0xfe000000) != 0xfe000000)
|
||||
fatal("host_arm_BNE - out of range %08x %i\n", offset, offset);
|
||||
|
|
|
|||
|
|
@ -94,6 +94,8 @@ 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);
|
||||
|
||||
#define host_arm_NOP(block) host_arm_MOV_REG(block, REG_R0, REG_R0)
|
||||
|
||||
void host_arm_ORR_IMM_cond(codeblock_t *block, uint32_t cond, int dst_reg, int src_reg, uint32_t imm);
|
||||
void host_arm_ORR_REG_LSL_cond(codeblock_t *block, uint32_t cond, int dst_reg, int src_reg_n, int src_reg_m, int shift);
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
#include "x87.h"
|
||||
#include "386_common.h"
|
||||
#include "codegen.h"
|
||||
#include "codegen_allocator.h"
|
||||
#include "codegen_backend.h"
|
||||
#include "codegen_backend_arm_defs.h"
|
||||
#include "codegen_backend_arm_ops.h"
|
||||
|
|
@ -849,7 +850,7 @@ static int codegen_FP_ENTER(codeblock_t *block, uop_t *uop)
|
|||
host_arm_call(block, x86_int);
|
||||
host_arm_B(block, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]);
|
||||
|
||||
*branch_ptr |= ((((uintptr_t)&block->data[block_pos] - (uintptr_t)branch_ptr) - 8) & 0x3fffffc) >> 2;
|
||||
*branch_ptr |= ((((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_ptr) - 8) & 0x3fffffc) >> 2;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -870,7 +871,7 @@ static int codegen_MMX_ENTER(codeblock_t *block, uop_t *uop)
|
|||
host_arm_call(block, x86_int);
|
||||
host_arm_B(block, (uintptr_t)&block->data[BLOCK_EXIT_OFFSET]);
|
||||
|
||||
*branch_ptr |= ((((uintptr_t)&block->data[block_pos] - (uintptr_t)branch_ptr) - 8) & 0x3fffffc) >> 2;
|
||||
*branch_ptr |= ((((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_ptr) - 8) & 0x3fffffc) >> 2;
|
||||
|
||||
host_arm_MOV_IMM(block, REG_TEMP, 0);
|
||||
host_arm_STR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.tag[0] - (uintptr_t)&cpu_state);
|
||||
|
|
@ -1489,7 +1490,7 @@ static int codegen_MOV_INT_DOUBLE_64(codeblock_t *block, uop_t *uop)
|
|||
host_arm_call(block, x87_fround64);
|
||||
host_arm_VMOV_D_64(block, REG_D_TEMP, REG_R0, REG_R1);
|
||||
|
||||
*branch_offset |= ((((uintptr_t)&block->data[block_pos] - (uintptr_t)branch_offset) - 8) & 0x3fffffc) >> 2;
|
||||
*branch_offset |= ((((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 8) & 0x3fffffc) >> 2;
|
||||
}
|
||||
else
|
||||
fatal("MOV_INT_DOUBLE_64 %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real);
|
||||
|
|
@ -3165,6 +3166,6 @@ void codegen_direct_write_double_stack(codeblock_t *block, int stack_offset, int
|
|||
|
||||
void codegen_set_jump_dest(codeblock_t *block, void *p)
|
||||
{
|
||||
*(uint32_t *)p |= ((((uintptr_t)&block->data[block_pos] - (uintptr_t)p) - 8) & 0x3fffffc) >> 2;
|
||||
*(uint32_t *)p |= ((((uintptr_t)&block_write_data[block_pos] - (uintptr_t)p) - 8) & 0x3fffffc) >> 2;
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include "ibm.h"
|
||||
#include "codegen.h"
|
||||
#include "codegen_allocator.h"
|
||||
#include "codegen_backend.h"
|
||||
#include "codegen_backend_x86-64_defs.h"
|
||||
#include "codegen_backend_x86-64_ops.h"
|
||||
|
|
@ -101,9 +102,9 @@ static void build_load_routine(codeblock_t *block, int size, int is_float)
|
|||
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;
|
||||
*branch_offset = (uint8_t)((uintptr_t)&block_write_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;
|
||||
*misaligned_offset = (uint8_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)misaligned_offset) - 1;
|
||||
host_x86_PUSH(block, REG_RAX);
|
||||
host_x86_PUSH(block, REG_RDX);
|
||||
#if WIN64
|
||||
|
|
@ -145,7 +146,6 @@ static void build_load_routine(codeblock_t *block, int size, int is_float)
|
|||
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, int is_float)
|
||||
|
|
@ -200,9 +200,9 @@ static void build_store_routine(codeblock_t *block, int size, int is_float)
|
|||
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;
|
||||
*branch_offset = (uint8_t)((uintptr_t)&block_write_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;
|
||||
*misaligned_offset = (uint8_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)misaligned_offset) - 1;
|
||||
host_x86_PUSH(block, REG_RAX);
|
||||
host_x86_PUSH(block, REG_RDX);
|
||||
#if WIN64
|
||||
|
|
@ -241,7 +241,6 @@ static void build_store_routine(codeblock_t *block, int size, int is_float)
|
|||
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)
|
||||
|
|
@ -283,11 +282,6 @@ void codegen_backend_init()
|
|||
long pagemask = ~(pagesize - 1);
|
||||
#endif
|
||||
|
||||
#if defined WIN32 || defined _WIN32 || defined _WIN32
|
||||
codeblock_data = VirtualAlloc(NULL, BLOCK_SIZE * BLOCK_DATA_SIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
|
||||
#else
|
||||
codeblock_data = mmap(0, BLOCK_SIZE * BLOCK_DATA_SIZE, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_PRIVATE, 0, 0);
|
||||
#endif
|
||||
codeblock = malloc(BLOCK_SIZE * sizeof(codeblock_t));
|
||||
codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *));
|
||||
|
||||
|
|
@ -295,16 +289,17 @@ void codegen_backend_init()
|
|||
memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *));
|
||||
|
||||
for (c = 0; c < BLOCK_SIZE; c++)
|
||||
{
|
||||
codeblock[c].data = &codeblock_data[c * BLOCK_DATA_SIZE];
|
||||
codeblock[c].pc = BLOCK_PC_INVALID;
|
||||
}
|
||||
|
||||
// pclog("Codegen is %p\n", (void *)pages[0xfab12 >> 12].block);
|
||||
|
||||
block_current = 0;
|
||||
block_pos = 0;
|
||||
codeblock[block_current].head_mem_block = codegen_allocator_allocate(NULL);
|
||||
codeblock[block_current].data = codeblock_allocator_get_ptr(codeblock[block_current].head_mem_block);
|
||||
block_write_data = codeblock[block_current].data;
|
||||
build_loadstore_routines(&codeblock[block_current]);
|
||||
// fatal("Here\n");
|
||||
block_write_data = NULL;
|
||||
|
||||
asm(
|
||||
"stmxcsr %0\n"
|
||||
|
|
@ -318,47 +313,46 @@ void codegen_set_rounding_mode(int mode)
|
|||
cpu_state.new_fp_control = (cpu_state.old_fp_control & ~0x6000) | (mode << 13);
|
||||
}
|
||||
|
||||
static inline void call(codeblock_t *block, uintptr_t func)
|
||||
{
|
||||
uintptr_t diff = func - (uintptr_t)&block->data[block_pos + 5];
|
||||
|
||||
if (diff >= -0x80000000 && diff < 0x7fffffff)
|
||||
{
|
||||
addbyte(0xE8); /*CALL*/
|
||||
addlong((uint32_t)diff);
|
||||
}
|
||||
else
|
||||
{
|
||||
addbyte(0x48); /*MOV RAX, func*/
|
||||
addbyte(0xb8);
|
||||
addquad(func);
|
||||
addbyte(0xff); /*CALL RAX*/
|
||||
addbyte(0xd0);
|
||||
}
|
||||
}
|
||||
|
||||
void codegen_backend_prologue(codeblock_t *block)
|
||||
{
|
||||
block_pos = 0; /*Entry code*/
|
||||
addbyte(0x53); /*PUSH RBX*/
|
||||
addbyte(0x55); /*PUSH RBP*/
|
||||
addbyte(0x56); /*PUSH RSI*/
|
||||
addbyte(0x57); /*PUSH RDI*/
|
||||
addbyte(0x41); /*PUSH R12*/
|
||||
addbyte(0x54);
|
||||
addbyte(0x41); /*PUSH R13*/
|
||||
addbyte(0x55);
|
||||
addbyte(0x41); /*PUSH R14*/
|
||||
addbyte(0x56);
|
||||
addbyte(0x41); /*PUSH R15*/
|
||||
addbyte(0x57);
|
||||
addbyte(0x48); /*SUBL $40,%rsp*/
|
||||
addbyte(0x83);
|
||||
addbyte(0xEC);
|
||||
addbyte(0x38);
|
||||
addbyte(0x48); /*MOVL RBP, &cpu_state*/
|
||||
addbyte(0xBD);
|
||||
addquad(((uintptr_t)&cpu_state) + 128);
|
||||
block_pos = BLOCK_GPF_OFFSET;
|
||||
#if WIN64
|
||||
host_x86_XOR32_REG_REG(block, REG_ECX, REG_ECX, REG_ECX);
|
||||
host_x86_XOR32_REG_REG(block, REG_EDX, REG_EDX, REG_EDX);
|
||||
#else
|
||||
host_x86_XOR32_REG_REG(block, REG_EDI, REG_EDI, REG_EDI);
|
||||
host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI, REG_ESI);
|
||||
#endif
|
||||
host_x86_CALL(block, (uintptr_t)x86gpf);
|
||||
while (block_pos < BLOCK_EXIT_OFFSET)
|
||||
host_x86_NOP(block);
|
||||
if (block_pos > BLOCK_EXIT_OFFSET)
|
||||
fatal("block_pos > BLOCK_EXIT_OFFSET\n");
|
||||
block_pos = BLOCK_EXIT_OFFSET; /*Exit code*/
|
||||
host_x86_ADD32_REG_IMM(block, REG_ESP, REG_ESP, 0x38);
|
||||
host_x86_POP(block, REG_R15);
|
||||
host_x86_POP(block, REG_R14);
|
||||
host_x86_POP(block, REG_R13);
|
||||
host_x86_POP(block, REG_R12);
|
||||
host_x86_POP(block, REG_RDI);
|
||||
host_x86_POP(block, REG_RSI);
|
||||
host_x86_POP(block, REG_RBP);
|
||||
host_x86_POP(block, REG_RDX);
|
||||
host_x86_RET(block);
|
||||
if (block_pos > BLOCK_START)
|
||||
fatal("block_pos > BLOCK_START\n");
|
||||
|
||||
block_pos = BLOCK_START; /*Entry code*/
|
||||
host_x86_PUSH(block, REG_RBX);
|
||||
host_x86_PUSH(block, REG_RBP);
|
||||
host_x86_PUSH(block, REG_RSI);
|
||||
host_x86_PUSH(block, REG_RDI);
|
||||
host_x86_PUSH(block, REG_R12);
|
||||
host_x86_PUSH(block, REG_R13);
|
||||
host_x86_PUSH(block, REG_R14);
|
||||
host_x86_PUSH(block, REG_R15);
|
||||
host_x86_SUB32_REG_IMM(block, REG_ESP, REG_ESP, 0x38);
|
||||
host_x86_MOV64_REG_IMM(block, REG_RBP, ((uintptr_t)&cpu_state) + 128);
|
||||
if (block->flags & CODEBLOCK_HAS_FPU)
|
||||
{
|
||||
host_x86_MOV32_REG_ABS(block, REG_EAX, &cpu_state.TOP);
|
||||
|
|
@ -369,62 +363,15 @@ void codegen_backend_prologue(codeblock_t *block)
|
|||
|
||||
void codegen_backend_epilogue(codeblock_t *block)
|
||||
{
|
||||
addbyte(0x48); /*ADDL $40,%rsp*/
|
||||
addbyte(0x83);
|
||||
addbyte(0xC4);
|
||||
addbyte(0x38);
|
||||
addbyte(0x41); /*POP R15*/
|
||||
addbyte(0x5f);
|
||||
addbyte(0x41); /*POP R14*/
|
||||
addbyte(0x5e);
|
||||
addbyte(0x41); /*POP R13*/
|
||||
addbyte(0x5d);
|
||||
addbyte(0x41); /*POP R12*/
|
||||
addbyte(0x5c);
|
||||
addbyte(0x5f); /*POP RDI*/
|
||||
addbyte(0x5e); /*POP RSI*/
|
||||
addbyte(0x5d); /*POP RBP*/
|
||||
addbyte(0x5b); /*POP RDX*/
|
||||
addbyte(0xC3); /*RET*/
|
||||
|
||||
if (block_pos > BLOCK_GPF_OFFSET)
|
||||
fatal("Over limit!\n");
|
||||
|
||||
block_pos = BLOCK_GPF_OFFSET;
|
||||
#if WIN64
|
||||
addbyte(0x48); /*XOR RCX, RCX*/
|
||||
addbyte(0x31);
|
||||
addbyte(0xc9);
|
||||
addbyte(0x31); /*XOR EDX, EDX*/
|
||||
addbyte(0xd2);
|
||||
#else
|
||||
addbyte(0x48); /*XOR RDI, RDI*/
|
||||
addbyte(0x31);
|
||||
addbyte(0xff);
|
||||
addbyte(0x31); /*XOR ESI, ESI*/
|
||||
addbyte(0xf6);
|
||||
#endif
|
||||
call(block, (uintptr_t)x86gpf);
|
||||
while (block_pos < BLOCK_EXIT_OFFSET)
|
||||
addbyte(0x90); /*NOP*/
|
||||
block_pos = BLOCK_EXIT_OFFSET; /*Exit code*/
|
||||
addbyte(0x48); /*ADDL $40,%rsp*/
|
||||
addbyte(0x83);
|
||||
addbyte(0xC4);
|
||||
addbyte(0x38);
|
||||
addbyte(0x41); /*POP R15*/
|
||||
addbyte(0x5f);
|
||||
addbyte(0x41); /*POP R14*/
|
||||
addbyte(0x5e);
|
||||
addbyte(0x41); /*POP R13*/
|
||||
addbyte(0x5d);
|
||||
addbyte(0x41); /*POP R12*/
|
||||
addbyte(0x5c);
|
||||
addbyte(0x5f); /*POP RDI*/
|
||||
addbyte(0x5e); /*POP RSI*/
|
||||
addbyte(0x5d); /*POP RBP*/
|
||||
addbyte(0x5b); /*POP RDX*/
|
||||
addbyte(0xC3); /*RET*/
|
||||
host_x86_ADD32_REG_IMM(block, REG_ESP, REG_ESP, 0x38);
|
||||
host_x86_POP(block, REG_R15);
|
||||
host_x86_POP(block, REG_R14);
|
||||
host_x86_POP(block, REG_R13);
|
||||
host_x86_POP(block, REG_R12);
|
||||
host_x86_POP(block, REG_RDI);
|
||||
host_x86_POP(block, REG_RSI);
|
||||
host_x86_POP(block, REG_RBP);
|
||||
host_x86_POP(block, REG_RDX);
|
||||
host_x86_RET(block);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -2,17 +2,14 @@
|
|||
|
||||
#define BLOCK_SIZE 0x4000
|
||||
#define BLOCK_MASK 0x3fff
|
||||
#define BLOCK_START 0
|
||||
#define BLOCK_START 40
|
||||
|
||||
#define HASH_SIZE 0x20000
|
||||
#define HASH_MASK 0x1ffff
|
||||
|
||||
#define HASH(l) ((l) & 0x1ffff)
|
||||
|
||||
/*Hack until better memory management written*/
|
||||
#define BLOCK_EXIT_OFFSET (BLOCK_DATA_SIZE - 32)
|
||||
/*#define BLOCK_EXIT_OFFSET 0x7f0*/
|
||||
#define BLOCK_GPF_OFFSET (BLOCK_EXIT_OFFSET - 20)
|
||||
#define BLOCK_EXIT_OFFSET 20
|
||||
#define BLOCK_GPF_OFFSET 0
|
||||
|
||||
/*#define BLOCK_MAX 1720*/
|
||||
#define BLOCK_MAX 65208
|
||||
#define BLOCK_MAX 0x3c0
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -163,6 +163,8 @@ void host_x86_MINPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
|||
void host_x86_MULSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||
void host_x86_MULSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
|
||||
|
||||
void host_x86_NOP(codeblock_t *block);
|
||||
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -715,11 +715,11 @@ static int codegen_FSUB(codeblock_t *block, uop_t *uop)
|
|||
|
||||
static int codegen_FP_ENTER(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
uint8_t *branch_offset;
|
||||
uint32_t *branch_offset;
|
||||
|
||||
host_x86_MOV32_REG_ABS(block, REG_ECX, &cr0);
|
||||
host_x86_TEST32_REG_IMM(block, REG_ECX, 0xc);
|
||||
branch_offset = host_x86_JZ_short(block);
|
||||
branch_offset = host_x86_JZ_long(block);
|
||||
host_x86_MOV32_ABS_IMM(block, &cpu_state.oldpc, uop->imm_data);
|
||||
#if WIN64
|
||||
host_x86_MOV32_REG_IMM(block, REG_ECX, 7);
|
||||
|
|
@ -728,17 +728,17 @@ static int codegen_FP_ENTER(codeblock_t *block, uop_t *uop)
|
|||
#endif
|
||||
host_x86_CALL(block, x86_int);
|
||||
host_x86_JMP(block, &block->data[BLOCK_EXIT_OFFSET]);
|
||||
*branch_offset = (uint8_t)((uintptr_t)&block->data[block_pos] - (uintptr_t)branch_offset) - 1;
|
||||
*branch_offset = (uint32_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 4;
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int codegen_MMX_ENTER(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
uint8_t *branch_offset;
|
||||
uint32_t *branch_offset;
|
||||
|
||||
host_x86_MOV32_REG_ABS(block, REG_ECX, &cr0);
|
||||
host_x86_TEST32_REG_IMM(block, REG_ECX, 0xc);
|
||||
branch_offset = host_x86_JZ_short(block);
|
||||
branch_offset = host_x86_JZ_long(block);
|
||||
host_x86_MOV32_ABS_IMM(block, &cpu_state.oldpc, uop->imm_data);
|
||||
#if WIN64
|
||||
host_x86_MOV32_REG_IMM(block, REG_ECX, 7);
|
||||
|
|
@ -747,7 +747,7 @@ static int codegen_MMX_ENTER(codeblock_t *block, uop_t *uop)
|
|||
#endif
|
||||
host_x86_CALL(block, x86_int);
|
||||
host_x86_JMP(block, &block->data[BLOCK_EXIT_OFFSET]);
|
||||
*branch_offset = (uint8_t)((uintptr_t)&block->data[block_pos] - (uintptr_t)branch_offset) - 1;
|
||||
*branch_offset = (uint32_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 4;
|
||||
host_x86_MOV32_ABS_IMM(block, &cpu_state.tag[0], 0);
|
||||
host_x86_MOV32_ABS_IMM(block, &cpu_state.tag[4], 0);
|
||||
host_x86_MOV32_ABS_IMM(block, &cpu_state.TOP, 0);
|
||||
|
|
@ -1269,19 +1269,19 @@ static int codegen_MOV_INT_DOUBLE_64(codeblock_t *block, uop_t *uop)
|
|||
|
||||
if (REG_IS_Q(dest_size) && REG_IS_D(src_size) && REG_IS_Q(src_64_size))
|
||||
{
|
||||
uint8_t *branch_offset;
|
||||
uint32_t *branch_offset;
|
||||
|
||||
/*If TAG_UINT64 is set then the source is MM[]. Otherwise it is a double in ST()*/
|
||||
host_x86_MOVQ_XREG_XREG(block, dest_reg, src_64_reg);
|
||||
host_x86_TEST8_REG(block, tag_reg, tag_reg);
|
||||
branch_offset = host_x86_JS_short(block);
|
||||
branch_offset = host_x86_JS_long(block);
|
||||
|
||||
host_x86_LDMXCSR(block, &cpu_state.new_fp_control);
|
||||
host_x86_CVTSD2SI_REG64_XREG(block, REG_RCX, src_reg);
|
||||
host_x86_LDMXCSR(block, &cpu_state.old_fp_control);
|
||||
host_x86_MOVQ_XREG_REG(block, dest_reg, REG_RCX);
|
||||
|
||||
*branch_offset = (uint8_t)((uintptr_t)&block->data[block_pos] - (uintptr_t)branch_offset) - 1;
|
||||
*branch_offset = (uint32_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 4;
|
||||
}
|
||||
else
|
||||
fatal("MOV_INT_DOUBLE_64 %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real);
|
||||
|
|
@ -2763,7 +2763,7 @@ void codegen_direct_write_double_stack(codeblock_t *block, int stack_offset, int
|
|||
|
||||
void codegen_set_jump_dest(codeblock_t *block, void *p)
|
||||
{
|
||||
*(uint32_t *)p = (uintptr_t)&block->data[block_pos] - ((uintptr_t)p + 4);
|
||||
*(uint32_t *)p = (uintptr_t)&block_write_data[block_pos] - ((uintptr_t)p + 4);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
#include <stddef.h>
|
||||
#include "ibm.h"
|
||||
#include "codegen.h"
|
||||
#include "codegen_allocator.h"
|
||||
#include "codegen_backend.h"
|
||||
#include "codegen_backend_x86_defs.h"
|
||||
#include "codegen_backend_x86_ops.h"
|
||||
|
|
@ -100,9 +101,9 @@ static void build_load_routine(codeblock_t *block, int size, int is_float)
|
|||
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;
|
||||
*branch_offset = (uint8_t)((uintptr_t)&block_write_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;
|
||||
*misaligned_offset = (uint8_t)((uintptr_t)&block_write_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);
|
||||
|
|
@ -190,9 +191,9 @@ static void build_store_routine(codeblock_t *block, int size, int is_float)
|
|||
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;
|
||||
*branch_offset = (uint8_t)((uintptr_t)&block_write_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;
|
||||
*misaligned_offset = (uint8_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)misaligned_offset) - 1;
|
||||
if (size == 4 && is_float)
|
||||
host_x86_MOVD_REG_XREG(block, REG_ECX, REG_XMM_TEMP);
|
||||
host_x86_PUSH(block, REG_EAX);
|
||||
|
|
@ -254,6 +255,7 @@ static void build_loadstore_routines(codeblock_t *block)
|
|||
|
||||
void codegen_backend_init()
|
||||
{
|
||||
codeblock_t *block;
|
||||
int c;
|
||||
#if defined(__linux__) || defined(__APPLE__)
|
||||
void *start;
|
||||
|
|
@ -283,48 +285,33 @@ pclog(" offsetof(codeblock_t, next)=%i\n", offsetof(codeblock_t, next));
|
|||
pclog(" offsetof(codeblock_t, prev_2)=%i\n", offsetof(codeblock_t, prev_2));
|
||||
pclog(" offsetof(codeblock_t, next_2)=%i\n", offsetof(codeblock_t, next_2));
|
||||
codeblock = malloc(BLOCK_SIZE * sizeof(codeblock_t));
|
||||
#if defined WIN32 || defined _WIN32 || defined _WIN32
|
||||
codeblock_data = VirtualAlloc(NULL, BLOCK_SIZE * BLOCK_DATA_SIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
|
||||
#else
|
||||
codeblock_data = malloc(BLOCK_SIZE * BLOCK_DATA_SIZE;
|
||||
#endif
|
||||
codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *));
|
||||
|
||||
memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t));
|
||||
memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *));
|
||||
|
||||
for (c = 0; c < BLOCK_SIZE; c++)
|
||||
{
|
||||
codeblock[c].data = &codeblock_data[c * BLOCK_DATA_SIZE];
|
||||
codeblock[c].pc = BLOCK_PC_INVALID;
|
||||
}
|
||||
|
||||
#if defined(__linux__) || defined(__APPLE__)
|
||||
start = (void *)((long)codeblock_data & pagemask);
|
||||
len = ((BLOCK_SIZE * BLOCK_DATA_SIZE) + pagesize) & pagemask;
|
||||
if (mprotect(start, len, PROT_READ | PROT_WRITE | PROT_EXEC) != 0)
|
||||
{
|
||||
perror("mprotect");
|
||||
exit(-1);
|
||||
}
|
||||
#endif
|
||||
// pclog("Codegen is %p\n", (void *)pages[0xfab12 >> 12].block);
|
||||
|
||||
block_current = 0;
|
||||
block_pos = 0;
|
||||
mem_abrt_rout = &codeblock[block_current].data[block_pos];
|
||||
addbyte(0x83); /*ADDL $16+4,%esp*/
|
||||
addbyte(0xC4);
|
||||
addbyte(0x10+4);
|
||||
addbyte(0x5f); /*POP EDI*/
|
||||
addbyte(0x5e); /*POP ESI*/
|
||||
addbyte(0x5d); /*POP EBP*/
|
||||
addbyte(0x5b); /*POP EDX*/
|
||||
addbyte(0xC3); /*RET*/
|
||||
|
||||
block = &codeblock[block_current];
|
||||
block->head_mem_block = codegen_allocator_allocate(NULL);
|
||||
block->data = codeblock_allocator_get_ptr(block->head_mem_block);
|
||||
block_write_data = block->data;
|
||||
mem_abrt_rout = &block->data[block_pos];
|
||||
host_x86_ADD32_REG_IMM(block, REG_ESP, REG_ESP, 0x10+4);
|
||||
host_x86_POP(block, REG_EDI);
|
||||
host_x86_POP(block, REG_ESI);
|
||||
host_x86_POP(block, REG_EBP);
|
||||
host_x86_POP(block, REG_EDX);
|
||||
host_x86_RET(block);
|
||||
|
||||
block_pos = 64;
|
||||
build_loadstore_routines(&codeblock[block_current]);
|
||||
//fatal("Here\n");
|
||||
build_loadstore_routines(block);
|
||||
block_write_data = NULL;
|
||||
|
||||
cpu_state.old_fp_control = 0;
|
||||
asm(
|
||||
|
|
@ -346,16 +333,25 @@ void codegen_set_rounding_mode(int mode)
|
|||
|
||||
void codegen_backend_prologue(codeblock_t *block)
|
||||
{
|
||||
block_pos = 0; /*Entry code*/
|
||||
addbyte(0x53); /*PUSH EBX*/
|
||||
addbyte(0x55); /*PUSH EBP*/
|
||||
addbyte(0x56); /*PUSH ESI*/
|
||||
addbyte(0x57); /*PUSH EDI*/
|
||||
addbyte(0x83); /*SUBL $64,%esp*/
|
||||
addbyte(0xEC);
|
||||
addbyte(0x40);
|
||||
addbyte(0xBD); /*MOVL EBP, &cpu_state*/
|
||||
addlong(((uintptr_t)&cpu_state) + 128);
|
||||
block_pos = BLOCK_GPF_OFFSET;
|
||||
host_x86_MOV32_STACK_IMM(block, STACK_ARG0, 0);
|
||||
host_x86_MOV32_STACK_IMM(block, STACK_ARG1, 0);
|
||||
host_x86_CALL(block, (void *)x86gpf);
|
||||
block_pos = BLOCK_EXIT_OFFSET; /*Exit code*/
|
||||
host_x86_ADD32_REG_IMM(block, REG_ESP, REG_ESP, 64);
|
||||
host_x86_POP(block, REG_EDI);
|
||||
host_x86_POP(block, REG_ESI);
|
||||
host_x86_POP(block, REG_EBP);
|
||||
host_x86_POP(block, REG_EDX);
|
||||
host_x86_RET(block);
|
||||
|
||||
block_pos = BLOCK_START; /*Entry code*/
|
||||
host_x86_PUSH(block, REG_EBX);
|
||||
host_x86_PUSH(block, REG_EBP);
|
||||
host_x86_PUSH(block, REG_ESI);
|
||||
host_x86_PUSH(block, REG_EDI);
|
||||
host_x86_SUB32_REG_IMM(block, REG_ESP, REG_ESP, 64);
|
||||
host_x86_MOV32_REG_IMM(block, REG_EBP, ((uintptr_t)&cpu_state) + 128);
|
||||
if (block->flags & CODEBLOCK_HAS_FPU)
|
||||
{
|
||||
host_x86_MOV32_REG_ABS(block, REG_EAX, &cpu_state.TOP);
|
||||
|
|
@ -366,39 +362,12 @@ void codegen_backend_prologue(codeblock_t *block)
|
|||
|
||||
void codegen_backend_epilogue(codeblock_t *block)
|
||||
{
|
||||
addbyte(0x83); /*ADDL $64,%esp*/
|
||||
addbyte(0xC4);
|
||||
addbyte(0x40);
|
||||
addbyte(0x5f); /*POP EDI*/
|
||||
addbyte(0x5e); /*POP ESI*/
|
||||
addbyte(0x5d); /*POP EBP*/
|
||||
addbyte(0x5b); /*POP EDX*/
|
||||
addbyte(0xC3); /*RET*/
|
||||
|
||||
if (block_pos > BLOCK_GPF_OFFSET)
|
||||
fatal("Over limit!\n");
|
||||
|
||||
block_pos = BLOCK_GPF_OFFSET;
|
||||
addbyte(0xc7); /*MOV [ESP],0*/
|
||||
addbyte(0x04);
|
||||
addbyte(0x24);
|
||||
addlong(0);
|
||||
addbyte(0xc7); /*MOV [ESP+4],0*/
|
||||
addbyte(0x44);
|
||||
addbyte(0x24);
|
||||
addbyte(0x04);
|
||||
addlong(0);
|
||||
addbyte(0xe8); /*CALL x86gpf*/
|
||||
addlong((uint32_t)x86gpf - (uint32_t)(&codeblock[block_current].data[block_pos + 4]));
|
||||
block_pos = BLOCK_EXIT_OFFSET; /*Exit code*/
|
||||
addbyte(0x83); /*ADDL $64,%esp*/
|
||||
addbyte(0xC4);
|
||||
addbyte(0x40);
|
||||
addbyte(0x5f); /*POP EDI*/
|
||||
addbyte(0x5e); /*POP ESI*/
|
||||
addbyte(0x5d); /*POP EBP*/
|
||||
addbyte(0x5b); /*POP EDX*/
|
||||
addbyte(0xC3); /*RET*/
|
||||
host_x86_ADD32_REG_IMM(block, REG_ESP, REG_ESP, 64);
|
||||
host_x86_POP(block, REG_EDI);
|
||||
host_x86_POP(block, REG_ESI);
|
||||
host_x86_POP(block, REG_EBP);
|
||||
host_x86_POP(block, REG_EDX);
|
||||
host_x86_RET(block);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -2,18 +2,14 @@
|
|||
|
||||
#define BLOCK_SIZE 0x4000
|
||||
#define BLOCK_MASK 0x3fff
|
||||
#define BLOCK_START 0
|
||||
#define BLOCK_START 32
|
||||
|
||||
#define HASH_SIZE 0x20000
|
||||
#define HASH_MASK 0x1ffff
|
||||
|
||||
#define HASH(l) ((l) & 0x1ffff)
|
||||
|
||||
/*Hack until better memory management written*/
|
||||
#define BLOCK_EXIT_OFFSET (BLOCK_DATA_SIZE - 16)
|
||||
//#define BLOCK_EXIT_OFFSET 0xfff0
|
||||
/*#define BLOCK_EXIT_OFFSET 0x7f0*/
|
||||
#define BLOCK_GPF_OFFSET (BLOCK_EXIT_OFFSET - 20)
|
||||
#define BLOCK_EXIT_OFFSET 20
|
||||
#define BLOCK_GPF_OFFSET 0
|
||||
|
||||
/*#define BLOCK_MAX 1720*/
|
||||
#define BLOCK_MAX 65208
|
||||
#define BLOCK_MAX 0x3c0
|
||||
|
|
|
|||
|
|
@ -39,4 +39,9 @@ extern void *codegen_mem_store_quad;
|
|||
extern void *codegen_mem_store_single;
|
||||
extern void *codegen_mem_store_double;
|
||||
|
||||
#define STACK_ARG0 (0)
|
||||
#define STACK_ARG1 (4)
|
||||
#define STACK_ARG2 (8)
|
||||
#define STACK_ARG3 (12)
|
||||
|
||||
#endif
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -5,16 +5,12 @@
|
|||
#include "x87.h"
|
||||
#include "386_common.h"
|
||||
#include "codegen.h"
|
||||
#include "codegen_allocator.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)
|
||||
#define STACK_ARG1 (4)
|
||||
#define STACK_ARG2 (8)
|
||||
#define STACK_ARG3 (12)
|
||||
|
||||
/*void codegen_debug()
|
||||
{
|
||||
pclog(" %04x:%04x : %08x %08x %08x %08x\n", CS, cpu_state.pc, AX, BX, CX, DX);
|
||||
|
|
@ -726,32 +722,32 @@ static int codegen_FSUB(codeblock_t *block, uop_t *uop)
|
|||
|
||||
static int codegen_FP_ENTER(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
uint8_t *branch_offset;
|
||||
uint32_t *branch_offset;
|
||||
|
||||
host_x86_MOV32_REG_ABS(block, REG_ECX, &cr0);
|
||||
host_x86_TEST32_REG_IMM(block, REG_ECX, 0xc);
|
||||
branch_offset = host_x86_JZ_short(block);
|
||||
branch_offset = host_x86_JZ_long(block);
|
||||
host_x86_MOV32_ABS_IMM(block, &cpu_state.oldpc, uop->imm_data);
|
||||
host_x86_MOV32_STACK_IMM(block, STACK_ARG0, 7);
|
||||
host_x86_CALL(block, x86_int);
|
||||
host_x86_JMP(block, &block->data[BLOCK_EXIT_OFFSET]);
|
||||
*branch_offset = (uint8_t)((uintptr_t)&block->data[block_pos] - (uintptr_t)branch_offset) - 1;
|
||||
*branch_offset = (uint32_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 4;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int codegen_MMX_ENTER(codeblock_t *block, uop_t *uop)
|
||||
{
|
||||
uint8_t *branch_offset;
|
||||
uint32_t *branch_offset;
|
||||
|
||||
host_x86_MOV32_REG_ABS(block, REG_ECX, &cr0);
|
||||
host_x86_TEST32_REG_IMM(block, REG_ECX, 0xc);
|
||||
branch_offset = host_x86_JZ_short(block);
|
||||
branch_offset = host_x86_JZ_long(block);
|
||||
host_x86_MOV32_ABS_IMM(block, &cpu_state.oldpc, uop->imm_data);
|
||||
host_x86_MOV32_STACK_IMM(block, STACK_ARG0, 7);
|
||||
host_x86_CALL(block, x86_int);
|
||||
host_x86_JMP(block, &block->data[BLOCK_EXIT_OFFSET]);
|
||||
*branch_offset = (uint8_t)((uintptr_t)&block->data[block_pos] - (uintptr_t)branch_offset) - 1;
|
||||
*branch_offset = (uint32_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 4;
|
||||
host_x86_MOV32_ABS_IMM(block, &cpu_state.tag[0], 0);
|
||||
host_x86_MOV32_ABS_IMM(block, &cpu_state.tag[4], 0);
|
||||
host_x86_MOV32_ABS_IMM(block, &cpu_state.TOP, 0);
|
||||
|
|
@ -1268,12 +1264,12 @@ static int codegen_MOV_INT_DOUBLE_64(codeblock_t *block, uop_t *uop)
|
|||
|
||||
if (REG_IS_Q(dest_size) && REG_IS_D(src_size) && REG_IS_Q(src_64_size))
|
||||
{
|
||||
uint8_t *branch_offset;
|
||||
uint32_t *branch_offset;
|
||||
|
||||
/*If TAG_UINT64 is set then the source is MM[]. Otherwise it is a double in ST()*/
|
||||
host_x86_MOVQ_XREG_XREG(block, dest_reg, src_64_reg);
|
||||
host_x86_TEST8_REG(block, tag_reg, tag_reg);
|
||||
branch_offset = host_x86_JS_short(block);
|
||||
branch_offset = host_x86_JS_long(block);
|
||||
|
||||
/*There is no SSE instruction to convert a floating point value to a 64-bit integer.
|
||||
Instead we have to bounce through memory via x87.*/
|
||||
|
|
@ -1284,7 +1280,7 @@ static int codegen_MOV_INT_DOUBLE_64(codeblock_t *block, uop_t *uop)
|
|||
host_x86_MOVQ_XREG_BASE_OFFSET(block, dest_reg, REG_ESP, 0);
|
||||
host_x87_FLDCW(block, &cpu_state.old_fp_control2);
|
||||
|
||||
*branch_offset = (uint8_t)((uintptr_t)&block->data[block_pos] - (uintptr_t)branch_offset) - 1;
|
||||
*branch_offset = (uint32_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 4;
|
||||
}
|
||||
else
|
||||
fatal("MOV_INT_DOUBLE_64 %02x %02x\n", uop->dest_reg_a_real, uop->src_reg_a_real);
|
||||
|
|
@ -2769,7 +2765,7 @@ void codegen_direct_write_double_stack(codeblock_t *block, int stack_offset, int
|
|||
|
||||
void codegen_set_jump_dest(codeblock_t *block, void *p)
|
||||
{
|
||||
*(uint32_t *)p = (uintptr_t)&block->data[block_pos] - ((uintptr_t)p + 4);
|
||||
*(uint32_t *)p = (uintptr_t)&block_write_data[block_pos] - ((uintptr_t)p + 4);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#include "ibm.h"
|
||||
#include "codegen.h"
|
||||
#include "codegen_allocator.h"
|
||||
#include "codegen_backend.h"
|
||||
#include "codegen_ir.h"
|
||||
#include "codegen_reg.h"
|
||||
|
|
@ -20,6 +21,8 @@ void codegen_ir_compile(ir_data_t *ir, codeblock_t *block)
|
|||
int jump_target_at_end = -1;
|
||||
int c;
|
||||
|
||||
block_write_data = codeblock_allocator_get_ptr(block->head_mem_block);
|
||||
block_pos = 0;
|
||||
codegen_backend_prologue(block);
|
||||
|
||||
for (c = 0; c < ir->wr_pos; c++)
|
||||
|
|
@ -114,7 +117,7 @@ void codegen_ir_compile(ir_data_t *ir, codeblock_t *block)
|
|||
}
|
||||
|
||||
codegen_backend_epilogue(block);
|
||||
|
||||
block_write_data = NULL;
|
||||
// if (has_ea)
|
||||
// fatal("IR compilation complete\n");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
#include "ide.h"
|
||||
#include "cdrom-image.h"
|
||||
#include "scsi_zip.h"
|
||||
#include "codegen_allocator.h"
|
||||
#include "wx-common.h"
|
||||
|
||||
drive_info_t drive_info[10];
|
||||
|
|
@ -135,7 +136,7 @@ int get_status(char* machine, char* device)
|
|||
"\n"
|
||||
|
||||
"New blocks : %i\nOld blocks : %i\nRecompiled speed : %f MIPS\nAverage size : %f\n"
|
||||
"Flushes : %i\nEvicted : %i\nReused : %i\nRemoved : %i\nReal speed : %f MIPS"
|
||||
"Flushes : %i\nEvicted : %i\nReused : %i\nRemoved : %i\nReal speed : %f MIPS\nMem blocks used : %i (%g MB)"
|
||||
// "\nFully recompiled ins %% : %f%%"
|
||||
,mips,
|
||||
flops,
|
||||
|
|
@ -158,7 +159,9 @@ int get_status(char* machine, char* device)
|
|||
cpu_recomp_flushes_latched, cpu_recomp_evicted_latched,
|
||||
cpu_recomp_reuse_latched, cpu_recomp_removed_latched,
|
||||
|
||||
((double)cpu_recomp_ins_latched / 1000000.0) / ((double)main_time / timer_freq)
|
||||
((double)cpu_recomp_ins_latched / 1000000.0) / ((double)main_time / timer_freq),
|
||||
codegen_allocator_usage,
|
||||
(double)(codegen_allocator_usage * MEM_BLOCK_SIZE) / (1024.0*1024.0)
|
||||
// ((double)cpu_recomp_full_ins_latched / (double)cpu_recomp_ins_latched) * 100.0
|
||||
// cpu_reps_latched, cpu_notreps_latched
|
||||
);
|
||||
|
|
|
|||
Loading…
Reference in a new issue