When unrolling a loop, set op_32, ea_seg and ssegs to the correct values at the start of the loop. Fixes mode setting on Bahamas 64 and most likely some other bugs.

This commit is contained in:
SarahW 2019-04-01 21:23:09 +01:00
commit a0ab14f56f
5 changed files with 63 additions and 16 deletions

View file

@ -13,6 +13,41 @@
#include "codegen_ops.h" #include "codegen_ops.h"
#include "codegen_ops_helpers.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; int has_ea;
codeblock_t *codeblock; codeblock_t *codeblock;
@ -551,6 +586,12 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t
} }
generate_call: 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_timing_opcode(opcode, fetchdat, op_32, op_pc);
codegen_accumulate(ACCREG_ins, 1); codegen_accumulate(ACCREG_ins, 1);
@ -646,6 +687,11 @@ generate_call:
codegen_endpc = (cs + cpu_state.pc) + 8; codegen_endpc = (cs + cpu_state.pc) + 8;
block->ins++;
if (block->ins >= 50)
CPU_BLOCK_END();
return; return;
} }
} }

View file

@ -404,6 +404,8 @@ extern int codegen_in_recompile;
void codegen_generate_reset(); 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 #ifdef DEBUG_EXTRA
extern uint32_t instr_counts[256*256]; extern uint32_t instr_counts[256*256];

View file

@ -9,6 +9,7 @@ extern int has_ea;
static ir_data_t ir_block; static ir_data_t ir_block;
static int codegen_unroll_start, codegen_unroll_count; static int codegen_unroll_start, codegen_unroll_count;
static int codegen_unroll_first_instruction;
ir_data_t *codegen_ir_init() ir_data_t *codegen_ir_init()
{ {
@ -20,10 +21,11 @@ ir_data_t *codegen_ir_init()
return &ir_block; 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_count = count;
codegen_unroll_start = start; codegen_unroll_start = start;
codegen_unroll_first_instruction = first_instruction;
} }
static void duplicate_uop(ir_data_t *ir, uop_t *uop, int offset) 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) if (codegen_unroll_count)
{ {
int 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++) for (unroll_count = 1; unroll_count < codegen_unroll_count; unroll_count++)
{ {

View file

@ -2,5 +2,5 @@
ir_data_t *codegen_ir_init(); 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); void codegen_ir_compile(ir_data_t *ir, codeblock_t *block);

View file

@ -33,21 +33,13 @@ int codegen_can_unroll_full(codeblock_t *block, ir_data_t *ir, uint32_t next_pc,
{ {
int start; int start;
int max_unroll; int max_unroll;
int first_instruction;
/*Check that dest instruction was actually compiled into block*/ /*Check that dest instruction was actually compiled into block*/
for (start = 0; start < ir->wr_pos; start++) start = codegen_get_instruction_uop(block, dest_addr, &first_instruction);
{
// 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;
}
}
/*Couldn't find any uOPs corresponding to the destination instruction*/ /*Couldn't find any uOPs corresponding to the destination instruction*/
if (start == ir->wr_pos) if (start == -1)
{ {
/*Is instruction jumping to itself?*/ /*Is instruction jumping to itself?*/
if (dest_addr != cpu_state.oldpc) 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); // 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; return 0;
} }
else
start = ir->wr_pos;
} }
max_unroll = UNROLL_MAX_UOPS / ((ir->wr_pos-start)+6); 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) if (max_unroll <= 1)
return 0; return 0;
codegen_ir_set_unroll(max_unroll, start); codegen_ir_set_unroll(max_unroll, start, first_instruction);
return 1; return 1;
} }