Added code generation for JCXZ, LOOP, JE, JNE, JS, JNS, JB, JNB, JO, JNO, JP and JNP.

This commit is contained in:
TomW 2015-04-14 20:40:40 +01:00
commit bbf0011e95
8 changed files with 485 additions and 42 deletions

View file

@ -21,6 +21,7 @@
#include <unistd.h>
#endif
int codegen_flags_changed = 0;
x86seg *op_ea_seg;
int op_ssegs;
uint32_t op_old_pc;
@ -250,6 +251,8 @@ void codegen_block_init(uint32_t phys_addr)
codegen_block_full_ins = 0;
recomp_page = phys_addr & ~0xfff;
codegen_flags_changed = 0;
}
void codegen_block_remove()
@ -686,6 +689,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t
uint32_t op_32 = use32;
uint32_t op_pc = new_pc;
OpFn *op_table = x86_dynarec_opcodes;
RecompOpFn *recomp_op_table = recomp_opcodes;
int opcode_shift = 0;
int opcode_mask = 0x3ff;
int over = 0;
@ -708,6 +712,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t
{
case 0x0f:
op_table = x86_dynarec_opcodes_0f;
recomp_op_table = recomp_opcodes_0f;
over = 1;
break;
@ -745,6 +750,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t
case 0xd8:
op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_d8_a32 : x86_dynarec_opcodes_d8_a16;
recomp_op_table = NULL;
opcode_shift = 3;
opcode_mask = 0x1f;
over = 1;
@ -753,6 +759,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t
break;
case 0xd9:
op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_d9_a32 : x86_dynarec_opcodes_d9_a16;
recomp_op_table = NULL;
opcode_mask = 0xff;
over = 1;
pc_off = -1;
@ -760,6 +767,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t
break;
case 0xda:
op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_da_a32 : x86_dynarec_opcodes_da_a16;
recomp_op_table = NULL;
opcode_mask = 0xff;
over = 1;
pc_off = -1;
@ -767,6 +775,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t
break;
case 0xdb:
op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_db_a32 : x86_dynarec_opcodes_db_a16;
recomp_op_table = NULL;
opcode_mask = 0xff;
over = 1;
pc_off = -1;
@ -774,6 +783,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t
break;
case 0xdc:
op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dc_a32 : x86_dynarec_opcodes_dc_a16;
recomp_op_table = NULL;
opcode_shift = 3;
opcode_mask = 0x1f;
over = 1;
@ -782,6 +792,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t
break;
case 0xdd:
op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dd_a32 : x86_dynarec_opcodes_dd_a16;
recomp_op_table = NULL;
opcode_mask = 0xff;
over = 1;
pc_off = -1;
@ -789,6 +800,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t
break;
case 0xde:
op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_de_a32 : x86_dynarec_opcodes_de_a16;
recomp_op_table = NULL;
opcode_mask = 0xff;
over = 1;
pc_off = -1;
@ -796,6 +808,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t
break;
case 0xdf:
op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_df_a32 : x86_dynarec_opcodes_df_a16;
recomp_op_table = NULL;
opcode_mask = 0xff;
over = 1;
pc_off = -1;
@ -822,11 +835,46 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t
generate_call:
codegen_timing_opcode(opcode, fetchdat, op_32);
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))))
{
/*Opcode is likely to cause block to exit, update cycle count*/
if (codegen_block_cycles)
{
addbyte(0x81); /*SUB $codegen_block_cycles, cyclcs*/
addbyte(0x2d);
addlong((uint32_t)&cycles);
addlong((uint32_t)codegen_block_cycles);
codegen_block_cycles = 0;
}
if (codegen_block_ins)
{
addbyte(0x81); /*ADD $codegen_block_ins,ins*/
addbyte(0x05);
addlong((uint32_t)&cpu_recomp_ins);
addlong(codegen_block_ins);
codegen_block_ins = 0;
}
#if 0
if (codegen_block_full_ins)
{
addbyte(0x81); /*ADD $codegen_block_ins,ins*/
addbyte(0x05);
addlong((uint32_t)&cpu_recomp_full_ins);
addlong(codegen_block_full_ins);
codegen_block_full_ins = 0;
}
#endif
}
addbyte(0xBD); /*MOVL EBP, &EAX*/
addlong((uint32_t)&EAX);
if (op_table == x86_dynarec_opcodes && recomp_opcodes[(opcode | op_32) & 0x1ff])
if (recomp_op_table && recomp_op_table[(opcode | op_32) & 0x1ff])
{
uint32_t new_pc = recomp_opcodes[(opcode | op_32) & 0x1ff](opcode, fetchdat, op_32, op_pc, block);
uint32_t new_pc = recomp_op_table[(opcode | op_32) & 0x1ff](opcode, fetchdat, op_32, op_pc, block);
if (new_pc)
{
if (new_pc != -1)
@ -933,41 +981,6 @@ generate_call:
addlong(((uint8_t *)op - (uint8_t *)(&block->data[block_pos + 4])));
codegen_block_ins++;
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))))
{
/*Opcode is likely to cause block to exit, update cycle count*/
if (codegen_block_cycles)
{
addbyte(0x81); /*SUB $codegen_block_cycles, cyclcs*/
addbyte(0x2d);
addlong((uint32_t)&cycles);
addlong((uint32_t)codegen_block_cycles);
codegen_block_cycles = 0;
}
if (codegen_block_ins)
{
addbyte(0x81); /*ADD $codegen_block_ins,ins*/
addbyte(0x05);
addlong((uint32_t)&cpu_recomp_ins);
addlong(codegen_block_ins);
codegen_block_ins = 0;
}
#if 0
if (codegen_block_full_ins)
{
addbyte(0x81); /*ADD $codegen_block_ins,ins*/
addbyte(0x05);
addlong((uint32_t)&cpu_recomp_full_ins);
addlong(codegen_block_full_ins);
codegen_block_full_ins = 0;
}
#endif
}
block->ins++;