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:
SarahW 2019-01-12 15:15:43 +00:00
commit 66fba50e06
26 changed files with 1339 additions and 667 deletions

View file

@ -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"

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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

View file

@ -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);

View file

@ -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

View file

@ -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);

View file

@ -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);
}

View file

@ -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);

View file

@ -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

View file

@ -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);

View file

@ -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);

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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);

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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");
}

View file

@ -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
);