diff --git a/src/codegen.c b/src/codegen.c index 5ffa2cc..503a6c4 100644 --- a/src/codegen.c +++ b/src/codegen.c @@ -13,6 +13,41 @@ #include "codegen_ops.h" #include "codegen_ops_helpers.h" +#define MAX_INSTRUCTION_COUNT 100 + +static struct +{ + uint32_t pc; + int op_ssegs; + x86seg *op_ea_seg; + uint32_t op_32; + int first_uop; +} codegen_instructions[MAX_INSTRUCTION_COUNT]; + +int codegen_get_instruction_uop(codeblock_t *block, uint32_t pc, int *first_instruction) +{ + int c; + + for (c = 0; c < block->ins; c++) + { + if (codegen_instructions[c].pc == pc) + { + *first_instruction = c; + return codegen_instructions[c].first_uop; + } + } + + *first_instruction = block->ins; + return -1; +} + +void codegen_set_loop_start(ir_data_t *ir, int first_instruction) +{ + uop_MOV_IMM(ir, IREG_op32, codegen_instructions[first_instruction].op_32); + uop_MOV_PTR(ir, IREG_ea_seg, (void *)codegen_instructions[first_instruction].op_ea_seg); + uop_MOV_IMM(ir, IREG_ssegs, codegen_instructions[first_instruction].op_ssegs); +} + int has_ea; codeblock_t *codeblock; @@ -551,6 +586,12 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t } generate_call: + codegen_instructions[block->ins].pc = cpu_state.oldpc; + codegen_instructions[block->ins].op_ssegs = last_op_ssegs; + codegen_instructions[block->ins].op_ea_seg = last_op_ea_seg; + codegen_instructions[block->ins].op_32 = last_op_32; + codegen_instructions[block->ins].first_uop = ir->wr_pos; + codegen_timing_opcode(opcode, fetchdat, op_32, op_pc); codegen_accumulate(ACCREG_ins, 1); @@ -646,6 +687,11 @@ generate_call: codegen_endpc = (cs + cpu_state.pc) + 8; + block->ins++; + + if (block->ins >= 50) + CPU_BLOCK_END(); + return; } } diff --git a/src/codegen.h b/src/codegen.h index 9365e44..0f246b3 100644 --- a/src/codegen.h +++ b/src/codegen.h @@ -404,6 +404,8 @@ extern int codegen_in_recompile; void codegen_generate_reset(); +int codegen_get_instruction_uop(codeblock_t *block, uint32_t pc, int *first_instruction); +void codegen_set_loop_start(struct ir_data_t *ir, int first_instruction); #ifdef DEBUG_EXTRA extern uint32_t instr_counts[256*256]; diff --git a/src/codegen_ir.c b/src/codegen_ir.c index e3a9377..d7e6157 100644 --- a/src/codegen_ir.c +++ b/src/codegen_ir.c @@ -9,6 +9,7 @@ extern int has_ea; static ir_data_t ir_block; static int codegen_unroll_start, codegen_unroll_count; +static int codegen_unroll_first_instruction; ir_data_t *codegen_ir_init() { @@ -20,10 +21,11 @@ ir_data_t *codegen_ir_init() return &ir_block; } -void codegen_ir_set_unroll(int count, int start) +void codegen_ir_set_unroll(int count, int start, int first_instruction) { codegen_unroll_count = count; codegen_unroll_start = start; + codegen_unroll_first_instruction = first_instruction; } static void duplicate_uop(ir_data_t *ir, uop_t *uop, int offset) @@ -59,7 +61,10 @@ void codegen_ir_compile(ir_data_t *ir, codeblock_t *block) if (codegen_unroll_count) { int unroll_count; - int unroll_end = ir->wr_pos; + int unroll_end; + + codegen_set_loop_start(ir, codegen_unroll_first_instruction); + unroll_end = ir->wr_pos; for (unroll_count = 1; unroll_count < codegen_unroll_count; unroll_count++) { diff --git a/src/codegen_ir.h b/src/codegen_ir.h index b560256..6274816 100644 --- a/src/codegen_ir.h +++ b/src/codegen_ir.h @@ -2,5 +2,5 @@ ir_data_t *codegen_ir_init(); -void codegen_ir_set_unroll(int count, int start); +void codegen_ir_set_unroll(int count, int start, int first_instruction); void codegen_ir_compile(ir_data_t *ir, codeblock_t *block); diff --git a/src/codegen_ops_helpers.c b/src/codegen_ops_helpers.c index fdde53b..903a0e5 100644 --- a/src/codegen_ops_helpers.c +++ b/src/codegen_ops_helpers.c @@ -33,21 +33,13 @@ int codegen_can_unroll_full(codeblock_t *block, ir_data_t *ir, uint32_t next_pc, { int start; int max_unroll; + int first_instruction; /*Check that dest instruction was actually compiled into block*/ - for (start = 0; start < ir->wr_pos; start++) - { -// pclog(" uOP %i %08x %08x\n", c, ir->uops[c].pc, dest_addr); - if (ir->uops[start].pc == dest_addr) - break; - if (ir->uops[start].pc > dest_addr) - { -// pclog("Went past dest_addr. start_pc=%08x end_pc=%08x dest_pc=%08x wr_pos=%i loop_size=%i\n", block->pc-cs, next_pc, dest_addr, ir->wr_pos, ir->wr_pos-start); - return 0; - } - } + start = codegen_get_instruction_uop(block, dest_addr, &first_instruction); + /*Couldn't find any uOPs corresponding to the destination instruction*/ - if (start == ir->wr_pos) + if (start == -1) { /*Is instruction jumping to itself?*/ if (dest_addr != cpu_state.oldpc) @@ -55,6 +47,8 @@ int codegen_can_unroll_full(codeblock_t *block, ir_data_t *ir, uint32_t next_pc, // pclog("Couldn't find start. start_pc=%08x end_pc=%08x dest_pc=%08x wr_pos=%i loop_size=%i\n", block->pc-cs, next_pc, dest_addr, ir->wr_pos, ir->wr_pos-start); return 0; } + else + start = ir->wr_pos; } max_unroll = UNROLL_MAX_UOPS / ((ir->wr_pos-start)+6); @@ -65,7 +59,7 @@ int codegen_can_unroll_full(codeblock_t *block, ir_data_t *ir, uint32_t next_pc, if (max_unroll <= 1) return 0; - codegen_ir_set_unroll(max_unroll, start); + codegen_ir_set_unroll(max_unroll, start, first_instruction); return 1; }