Recompiler now handles instruction and cycle counting.

This commit is contained in:
SarahW 2018-07-06 17:51:22 +01:00
commit 774f4201ee
8 changed files with 99 additions and 7 deletions

View file

@ -58,7 +58,7 @@ static inline void fetch_ea_16_long(uint32_t rmdat)
#define OP_TABLE(name) dynarec_ops_ ## name #define OP_TABLE(name) dynarec_ops_ ## name
/*Temporary*/ /*Temporary*/
#define CLOCK_CYCLES(c) cycles -= (c) #define CLOCK_CYCLES(c)
#define CLOCK_CYCLES_ALWAYS(c) cycles -= (c) #define CLOCK_CYCLES_ALWAYS(c) cycles -= (c)
#include "386_ops.h" #include "386_ops.h"

View file

@ -6,6 +6,7 @@
#include "386_common.h" #include "386_common.h"
#include "codegen_accumulate.h"
#include "codegen_backend.h" #include "codegen_backend.h"
#include "codegen_ir.h" #include "codegen_ir.h"
@ -262,7 +263,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t
op_ea_seg = &_ds; op_ea_seg = &_ds;
op_ea_seg = &_ds; codegen_timing_start();
while (!over) while (!over)
{ {
@ -397,7 +398,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t
goto generate_call; goto generate_call;
} }
fetchdat = fastreadl(cs + op_pc); fetchdat = fastreadl(cs + op_pc);
// codegen_timing_prefix(opcode, fetchdat); codegen_timing_prefix(opcode, fetchdat);
if (cpu_state.abrt) if (cpu_state.abrt)
return; return;
opcode = fetchdat & 0xff; opcode = fetchdat & 0xff;
@ -408,6 +409,19 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t
} }
generate_call: generate_call:
codegen_timing_opcode(opcode, fetchdat, op_32);
codegen_accumulate(ACCREG_ins, 1);
codegen_accumulate(ACCREG_cycles, -codegen_block_cycles);
codegen_block_cycles = 0;
if ((op_table == x86_dynarec_opcodes &&
((opcode & 0xf0) == 0x70 || (opcode & 0xfc) == 0xe0 || opcode == 0xc2 ||
(opcode & 0xfe) == 0xca || (opcode & 0xfc) == 0xcc || (opcode & 0xfc) == 0xe8 ||
(opcode == 0xff && ((fetchdat & 0x38) >= 0x10 && (fetchdat & 0x38) < 0x30)))) ||
(op_table == x86_dynarec_opcodes_0f && ((opcode & 0xf0) == 0x80)))
codegen_accumulate_flush(ir);
//pclog("%04x:%08x : %02x\n", CS, new_pc, opcode); //pclog("%04x:%08x : %02x\n", CS, new_pc, opcode);
op = op_table[((opcode >> opcode_shift) | op_32) & opcode_mask]; op = op_table[((opcode >> opcode_shift) | op_32) & opcode_mask];

50
src/codegen_accumulate.c Normal file
View file

@ -0,0 +1,50 @@
#include "ibm.h"
#include "codegen.h"
#include "codegen_accumulate.h"
#include "codegen_ir.h"
static struct
{
int count;
int dest_reg;
} acc_regs[] =
{
[ACCREG_ins] = {0, IREG_ins},
[ACCREG_cycles] = {0, IREG_cycles},
};
void codegen_accumulate(int acc_reg, int delta)
{
if (acc_reg == ACCREG_cycles)
{
// pclog("cycles %04x:%04x %i\n", CS, cpu_state.pc, delta);
// if (CS == 0x1000 && cpu_state.pc == 0x863)
// fatal("Here\n");
}
acc_regs[acc_reg].count += delta;
}
void codegen_accumulate_flush(ir_data_t *ir)
{
int c;
for (c = 0; c < ACCREG_COUNT; c++)
{
if (acc_regs[c].count)
{
// if (c == ACCREG_cycles)
// pclog("accumulate %i %i %i\n", c, acc_regs[c].dest_reg, acc_regs[c].count);
uop_ADD_IMM(ir, acc_regs[c].dest_reg, acc_regs[c].dest_reg, acc_regs[c].count);
}
acc_regs[c].count = 0;
}
}
void codegen_accumulate_reset()
{
int c;
for (c = 0; c < ACCREG_COUNT; c++)
acc_regs[c].count = 0;
}

13
src/codegen_accumulate.h Normal file
View file

@ -0,0 +1,13 @@
enum
{
ACCREG_ins = 0,
ACCREG_cycles = 1,
ACCREG_COUNT
};
struct ir_data_t;
void codegen_accumulate(int acc_reg, int delta);
void codegen_accumulate_flush(struct ir_data_t *ir);
void codegen_accumulate_reset();

View file

@ -10,6 +10,7 @@
#include "386_common.h" #include "386_common.h"
#include "codegen.h" #include "codegen.h"
#include "codegen_accumulate.h"
#include "codegen_backend.h" #include "codegen_backend.h"
#include "codegen_ir.h" #include "codegen_ir.h"
#include "codegen_reg.h" #include "codegen_reg.h"
@ -310,6 +311,7 @@ void codegen_block_start_recompile(codeblock_t *block)
ir_data = codegen_ir_init(); ir_data = codegen_ir_init();
codegen_reg_reset(); codegen_reg_reset();
codegen_accumulate_reset();
codegen_generate_reset(); codegen_generate_reset();
} }
@ -410,6 +412,7 @@ void codegen_block_end_recompile(codeblock_t *block)
if (!(block->flags & CODEBLOCK_HAS_FPU)) if (!(block->flags & CODEBLOCK_HAS_FPU))
block->flags &= ~CODEBLOCK_STATIC_TOP; block->flags &= ~CODEBLOCK_STATIC_TOP;
codegen_accumulate_flush(ir_data);
codegen_ir_compile(ir_data, block); codegen_ir_compile(ir_data, block);
} }

View file

@ -50,6 +50,8 @@ void codegen_ir_compile(ir_data_t *ir, codeblock_t *block)
uop_handlers[uop->type & UOP_MASK](block, uop); uop_handlers[uop->type & UOP_MASK](block, uop);
} }
codegen_reg_flush(ir, block);
codegen_backend_epilogue(block); codegen_backend_epilogue(block);
// if (has_ea) // if (has_ea)

View file

@ -54,6 +54,9 @@ struct
[IREG_rm_mod_reg] = {REG_DWORD, &cpu_state.rm_data.rm_mod_reg_data}, [IREG_rm_mod_reg] = {REG_DWORD, &cpu_state.rm_data.rm_mod_reg_data},
[IREG_ins] = {REG_DWORD, &cpu_state.cpu_recomp_ins},
[IREG_cycles] = {REG_DWORD, &cpu_state._cycles},
/*Temporary registers are stored on the stack, and are not guaranteed to /*Temporary registers are stored on the stack, and are not guaranteed to
be preserved across uOPs. They will not be written back if they will be preserved across uOPs. They will not be written back if they will
not be read again.*/ not be read again.*/
@ -73,7 +76,10 @@ void codegen_reg_reset()
reg_version_refcount[c][0] = 0; reg_version_refcount[c][0] = 0;
} }
for (c = 0; c < CODEGEN_HOST_REGS; c++) for (c = 0; c < CODEGEN_HOST_REGS; c++)
{
host_regs[c] = invalid_ir_reg; host_regs[c] = invalid_ir_reg;
host_reg_dirty[c] = 0;
}
} }
static inline int ir_reg_is_invalid(ir_reg_t ir_reg) static inline int ir_reg_is_invalid(ir_reg_t ir_reg)
@ -119,6 +125,7 @@ static void codegen_reg_writeback(codeblock_t *block, int c)
} }
host_regs[c] = invalid_ir_reg; host_regs[c] = invalid_ir_reg;
host_reg_dirty[c] = 0;
} }
void codegen_reg_alloc_register(ir_reg_t dest_reg_a, ir_reg_t src_reg_a, ir_reg_t src_reg_b) void codegen_reg_alloc_register(ir_reg_t dest_reg_a, ir_reg_t src_reg_a, ir_reg_t src_reg_b)

View file

@ -31,14 +31,17 @@ enum
IREG_ssegs = 17, IREG_ssegs = 17,
IREG_rm_mod_reg = 18, IREG_rm_mod_reg = 18,
IREG_ins = 19,
IREG_cycles = 20,
/*Temporary registers are stored on the stack, and are not guaranteed to /*Temporary registers are stored on the stack, and are not guaranteed to
be preserved across uOPs. They will not be written back if they will be preserved across uOPs. They will not be written back if they will
not be read again.*/ not be read again.*/
IREG_temp0 = 20, IREG_temp0 = 21,
IREG_temp1 = 21, IREG_temp1 = 22,
IREG_temp2 = 22, IREG_temp2 = 23,
IREG_temp3 = 23, IREG_temp3 = 24,
IREG_COUNT, IREG_COUNT,