diff --git a/src/386.c b/src/386.c index 3bb5a18..3c92623 100644 --- a/src/386.c +++ b/src/386.c @@ -257,7 +257,7 @@ void x86_int_sw(int num) void x86illegal() { uint16_t addr; - pclog("x86 illegal %04X %08X %04X:%08X %02X\n",msw,cr0,CS,pc,opcode); +// pclog("x86 illegal %04X %08X %04X:%08X %02X\n",msw,cr0,CS,pc,opcode); // if (output) // { // dumpregs(); diff --git a/src/386_dynarec.c b/src/386_dynarec.c index 3249263..779687d 100644 --- a/src/386_dynarec.c +++ b/src/386_dynarec.c @@ -269,7 +269,7 @@ void x86_int_sw(int num) void x86illegal() { uint16_t addr; - pclog("x86 illegal %04X %08X %04X:%08X %02X\n",msw,cr0,CS,pc,opcode); +// pclog("x86 illegal %04X %08X %04X:%08X %02X\n",msw,cr0,CS,pc,opcode); // if (output) // { @@ -1183,44 +1183,6 @@ void exec386(int cycs) // output=3; while (cycles>0) { - int stack_check = 0; - -// if ((pc & 0xf0000000) == 0x26470948) -// fatal("Bad\n"); - -/* if (SS != 0x30) - stack_check = 1; - if (SS == 0x30 && ESP < 0x100) - output = 3;*/ -// if (stack32 && (ESP >= 2 && ESP < 0x10)) -// stack_check = 1; -// if (CS == 0x117) -// output = 3; -// if (cs+pc == 0x7c00) -// output = 3; -// if (output) -// dump_block(); -// if (ins > 19428567) -// output = 3; -// if (ins > 161000000) -// output = 3; -/* if (ins > 363365892) - { - if (!output) - timetolive = 15000; - output = 3; - }*/ -/* if (cr0 & (1 << 31)) - output = 3; - else - output = 0;*/ - -// if (CS == 0x28 && pc == 0x8000A89D) -// fatal("Over\n"); -// if (CS == 0xFDC8 && pc == 0x00005488) -// output = 3; -// if (ins >= 265000000) output = 1; - oldcs = CS; oldpc = pc; oldcpl = CPL; @@ -1317,18 +1279,9 @@ void exec386(int cycs) if (valid_block && !dirty) { void (*code)() = (void *)&block->data[BLOCK_START]; -/* if ((cs+pc) == 0xfe771) - output = 1;*/ -// if (output && pc != 0xe790 && pc != 0xe798) pclog("Calling block %i %08X for %08X %08X %08X %08X %08X %08X %02X %02X %02X %02X\n", codeblock_hash_pnt[HASH(cs + pc)], code, cs+pc, EAX, EBX, ECX, EDX, ESI, ram[0x7bd2+6],ram[0x7bd2+7],ram[0x7bd2+8],ram[0x7bd2+9]); -/* if (pc == 0xe79e) - { - fatal("Here\n"); - }*/ + if (output) pclog("Run block at %04x:%04x %04x %04x %04x %04x %04x %04x ESP=%08x %04x %02x%02x:%02x%02x %02x%02x:%02x%02x %02x%02x:%02x%02x %08x %08x\n", CS, pc, AX, BX, CX, DX, SI, DI, ESP, BP, ram[0x116330+0x6df4+0xa+3], ram[0x116330+0x6df4+0xa+2], ram[0x116330+0x6df4+0xa+1], ram[0x116330+0x6df4+0xa+0], ram[0x11d136+3],ram[0x11d136+2],ram[0x11d136+1],ram[0x11d136+0], ram[(0x119abe)+0x3],ram[(0x119abe)+0x2],ram[(0x119abe)+0x1],ram[(0x119abe)+0x0], get_phys(cs+pc), block->phys); -/* if (CS == 0xfef1 && pc == 0x0c07) - { - int a=1; - }*/ + oldcs = CS; oldcpl = CPL; inrecomp=1; diff --git a/src/386_dynarec_ops.c b/src/386_dynarec_ops.c index 07b73c0..efa4fc3 100644 --- a/src/386_dynarec_ops.c +++ b/src/386_dynarec_ops.c @@ -22,64 +22,6 @@ static inline void fetch_ea_32_long(uint32_t rmdat) eal_r = eal_w = NULL; easeg = ea_seg->base; ea_rseg = ea_seg->seg; - if (rm == 4) - { - uint8_t sib = rmdat >> 8; - - switch (mod) - { - case 0: - eaaddr = regs[sib & 7].l; - pc++; - break; - case 1: - pc++; - eaaddr = ((uint32_t)(int8_t)getbyte()) + regs[sib & 7].l; -// pc++; - break; - case 2: - eaaddr = (fastreadl(cs + pc + 1)) + regs[sib & 7].l; - pc += 5; - break; - } - /*SIB byte present*/ - if ((sib & 7) == 5 && !mod) - eaaddr = getlong(); - else if ((sib & 6) == 4 && !ssegs) - { - easeg = ss; - ea_rseg = SS; - ea_seg = &_ss; - } - if (((sib >> 3) & 7) != 4) - eaaddr += regs[(sib >> 3) & 7].l << (sib >> 6); - } - else - { - eaaddr = regs[rm].l; - if (mod) - { - if (rm == 5 && !ssegs) - { - easeg = ss; - ea_rseg = SS; - ea_seg = &_ss; - } - if (mod == 1) - { - eaaddr += ((uint32_t)(int8_t)(rmdat >> 8)); - pc++; - } - else - { - eaaddr += getlong(); - } - } - else if (rm == 5) - { - eaaddr = getlong(); - } - } if (easeg != 0xFFFFFFFF && ((easeg + eaaddr) & 0xFFF) <= 0xFFC) { if ( readlookup2[(easeg + eaaddr) >> 12] != -1) @@ -94,33 +36,6 @@ static inline void fetch_ea_16_long(uint32_t rmdat) eal_r = eal_w = NULL; easeg = ea_seg->base; ea_rseg = ea_seg->seg; - if (!mod && rm == 6) - { - eaaddr = getword(); - } - else - { - switch (mod) - { - case 0: - eaaddr = 0; - break; - case 1: - eaaddr = (uint16_t)(int8_t)(rmdat >> 8); pc++; - break; - case 2: - eaaddr = getword(); - break; - } - eaaddr += (*mod1add[0][rm]) + (*mod1add[1][rm]); - if (mod1seg[rm] == &ss && !ssegs) - { - easeg = ss; - ea_rseg = SS; - ea_seg = &_ss; - } - eaaddr &= 0xFFFF; - } if (easeg != 0xFFFFFFFF && ((easeg + eaaddr) & 0xFFF) <= 0xFFC) { if ( readlookup2[(easeg + eaaddr) >> 12] != -1) @@ -130,8 +45,8 @@ static inline void fetch_ea_16_long(uint32_t rmdat) } } -#define fetch_ea_16(rmdat) pc++; mod=(rmdat >> 6) & 3; reg=(rmdat >> 3) & 7; rm = rmdat & 7; if (mod != 3) { fetch_ea_16_long(rmdat); if (abrt) return 1; } -#define fetch_ea_32(rmdat) pc++; mod=(rmdat >> 6) & 3; reg=(rmdat >> 3) & 7; rm = rmdat & 7; if (mod != 3) { fetch_ea_32_long(rmdat); } if (abrt) return 1 +#define fetch_ea_16(rmdat) pc++; if (mod != 3) fetch_ea_16_long(rmdat); +#define fetch_ea_32(rmdat) pc++; if (mod != 3) fetch_ea_32_long(rmdat); #define OP_TABLE(name) dynarec_ops_ ## name #define CLOCK_CYCLES(c) diff --git a/src/codegen_x86.c b/src/codegen_x86.c index ed08f49..f3a3b27 100644 --- a/src/codegen_x86.c +++ b/src/codegen_x86.c @@ -45,6 +45,7 @@ int cpu_recomp_removed, cpu_recomp_removed_latched; static uint32_t codegen_endpc; int codegen_block_cycles; +static int codegen_block_ins; static uint32_t last_op32; static x86seg *last_ea_seg; @@ -307,6 +308,8 @@ void codegen_block_init(uint32_t phys_addr) codegen_block_cycles = 0; codegen_timing_block_start(); + + codegen_block_ins = 0; } void codegen_block_remove() @@ -361,10 +364,20 @@ void codegen_block_end() codegen_timing_block_end(); - addbyte(0x81); /*SUB $codegen_block_cycles, cyclcs*/ - addbyte(0x2d); - addlong((uint32_t)&cycles); - addlong((uint32_t)codegen_block_cycles); + if (codegen_block_cycles) + { + addbyte(0x81); /*SUB $codegen_block_cycles, cyclcs*/ + addbyte(0x2d); + addlong((uint32_t)&cycles); + addlong((uint32_t)codegen_block_cycles); + } + if (codegen_block_ins) + { + addbyte(0x81); /*ADD $codegen_block_ins,ins*/ + addbyte(0x05); + addlong((uint32_t)&cpu_recomp_ins); + addlong(codegen_block_ins); + } addbyte(0x83); /*ADDL $8,%esp*/ addbyte(0xC4); @@ -443,6 +456,51 @@ static int opcode_conditional_jump[256] = 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*f0*/ }; +static int opcode_modrm[256] = +{ + 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*00*/ + 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*10*/ + 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*20*/ + 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, /*30*/ + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*40*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*50*/ + 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, /*60*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*70*/ + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*80*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*90*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*a0*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*b0*/ + + 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, /*c0*/ + 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, /*d0*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*e0*/ + 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, /*f0*/ +}; +int opcode_0f_modrm[256] = +{ + 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*00*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*10*/ + 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*20*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*30*/ + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*40*/ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*50*/ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, /*60*/ + 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, /*70*/ + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /*80*/ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*90*/ + 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, /*a0*/ + 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, /*b0*/ + + 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, /*c0*/ + 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, /*d0*/ + 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, /*e0*/ + 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0 /*f0*/ +}; + void codegen_debug() { if (output) @@ -451,6 +509,180 @@ void codegen_debug() } } +static x86seg *codegen_generate_ea_16_long(x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc) +{ + if (!mod && rm == 6) + { + addbyte(0xC7); /*MOVL $0,(ssegs)*/ + addbyte(0x05); + addlong((uint32_t)&eaaddr); + addlong((fetchdat >> 8) & 0xffff); + (*op_pc) += 2; + } + else + { + switch (mod) + { + case 0: + addbyte(0xa1); /*MOVL *mod1add[0][rm], %eax*/ + addlong((uint32_t)mod1add[0][rm]); + addbyte(0x03); /*ADDL *mod1add[1][rm], %eax*/ + addbyte(0x05); + addlong((uint32_t)mod1add[1][rm]); + break; + case 1: + addbyte(0xb8); /*MOVL ,%eax*/ + addlong((uint32_t)(int8_t)(rmdat >> 8));// pc++; + addbyte(0x03); /*ADDL *mod1add[0][rm], %eax*/ + addbyte(0x05); + addlong((uint32_t)mod1add[0][rm]); + addbyte(0x03); /*ADDL *mod1add[1][rm], %eax*/ + addbyte(0x05); + addlong((uint32_t)mod1add[1][rm]); + (*op_pc)++; + break; + case 2: + addbyte(0xb8); /*MOVL ,%eax*/ + addlong((fetchdat >> 8) & 0xffff);// pc++; + addbyte(0x03); /*ADDL *mod1add[0][rm], %eax*/ + addbyte(0x05); + addlong((uint32_t)mod1add[0][rm]); + addbyte(0x03); /*ADDL *mod1add[1][rm], %eax*/ + addbyte(0x05); + addlong((uint32_t)mod1add[1][rm]); + (*op_pc) += 2; + break; + } + addbyte(0x25); /*ANDL $0xffff, %eax*/ + addlong(0xffff); + addbyte(0xa3); + addlong((uint32_t)&eaaddr); + + if (mod1seg[rm] == &ss && !op_ssegs) + op_ea_seg = &_ss; + } + return op_ea_seg; +} + +static x86seg *codegen_generate_ea_32_long(x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, int stack_offset) +{ + uint32_t new_eaaddr; + + if (rm == 4) + { + uint8_t sib = fetchdat >> 8; + (*op_pc)++; + + switch (mod) + { + case 0: + if ((sib & 7) == 5) + { + new_eaaddr = fastreadl(cs + (*op_pc) + 1); + addbyte(0xb8); /*MOVL ,%eax*/ + addlong(new_eaaddr);// pc++; + (*op_pc) += 4; + } + else + { + addbyte(0xa1); /*MOVL regs[sib&7].l, %eax*/ + addlong((uint32_t)®s[sib & 7].l); + } + break; + case 1: + new_eaaddr = (uint32_t)(int8_t)((fetchdat >> 16) & 0xff); + addbyte(0xb8); /*MOVL new_eaaddr, %eax*/ + addlong(new_eaaddr); + addbyte(0x03); /*ADDL regs[sib&7].l, %eax*/ + addbyte(0x05); + addlong((uint32_t)®s[sib & 7].l); + (*op_pc)++; + break; + case 2: + new_eaaddr = fastreadl(cs + (*op_pc) + 1); + addbyte(0xb8); /*MOVL new_eaaddr, %eax*/ + addlong(new_eaaddr); + addbyte(0x03); /*ADDL regs[sib&7].l, %eax*/ + addbyte(0x05); + addlong((uint32_t)®s[sib & 7].l); + (*op_pc) += 4; + break; + } + if (stack_offset && (sib & 7) == 4 && (mod || (sib & 7) != 5)) /*ESP*/ + { + addbyte(0x05); + addlong(stack_offset); + } + if (((sib & 7) == 4 || (mod && (sib & 7) == 5)) && !op_ssegs) + op_ea_seg = &_ss; + if (((sib >> 3) & 7) != 4) + { + switch (sib >> 6) + { + case 0: + addbyte(0x03); /*ADDL regs[sib&7].l, %eax*/ + addbyte(0x05); + addlong((uint32_t)®s[(sib >> 3) & 7].l); + break; + case 1: + addbyte(0x8B); addbyte(0x1D); addlong((uint32_t)®s[(sib >> 3) & 7].l); /*MOVL armregs[RD],%ebx*/ + addbyte(0x01); addbyte(0xD8); /*ADDL %ebx,%eax*/ + addbyte(0x01); addbyte(0xD8); /*ADDL %ebx,%eax*/ + break; + case 2: + addbyte(0x8B); addbyte(0x1D); addlong((uint32_t)®s[(sib >> 3) & 7].l); /*MOVL armregs[RD],%ebx*/ + addbyte(0xC1); addbyte(0xE3); addbyte(2); /*SHL $2,%ebx*/ + addbyte(0x01); addbyte(0xD8); /*ADDL %ebx,%eax*/ + break; + case 3: + addbyte(0x8B); addbyte(0x1D); addlong((uint32_t)®s[(sib >> 3) & 7].l); /*MOVL armregs[RD],%ebx*/ + addbyte(0xC1); addbyte(0xE3); addbyte(3); /*SHL $2,%ebx*/ + addbyte(0x01); addbyte(0xD8); /*ADDL %ebx,%eax*/ + break; + } + } + addbyte(0xa3); + addlong((uint32_t)&eaaddr); + } + else + { + if (!mod && rm == 5) + { + new_eaaddr = fastreadl(cs + (*op_pc) + 1); + addbyte(0xC7); /*MOVL $new_eaaddr,(eaaddr)*/ + addbyte(0x05); + addlong((uint32_t)&eaaddr); + addlong(new_eaaddr); + (*op_pc) += 4; + return op_ea_seg; + } + addbyte(0xa1); /*MOVL regs[rm].l, %eax*/ + addlong((uint32_t)®s[rm].l); + eaaddr = regs[rm].l; + if (mod) + { + if (rm == 5 && !op_ssegs) + op_ea_seg = &_ss; + if (mod == 1) + { + addbyte(0x05); + addlong((uint32_t)(int8_t)(fetchdat >> 8)); + (*op_pc)++; + } + else + { + new_eaaddr = fastreadl(cs + (*op_pc) + 1); + addbyte(0x05); + addlong(new_eaaddr); + (*op_pc) += 4; + } + } + addbyte(0xa3); + addlong((uint32_t)&eaaddr); + } + return op_ea_seg; +} + void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_pc, uint32_t old_pc) { codeblock_t *block = &codeblock[block_current]; @@ -463,7 +695,8 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t int opcode_mask = 0x3ff; int over = 0; int pc_off = 0; - + int test_modrm = 1; + codegen_timing_start(); while (!over) @@ -513,24 +746,28 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t opcode_mask = 0x1f; over = 1; pc_off = -1; + test_modrm = 0; break; case 0xd9: op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_d9_a32 : x86_dynarec_opcodes_d9_a16; opcode_mask = 0xff; over = 1; pc_off = -1; + test_modrm = 0; break; case 0xda: op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_da_a32 : x86_dynarec_opcodes_da_a16; opcode_mask = 0xff; over = 1; pc_off = -1; + test_modrm = 0; break; case 0xdb: op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_db_a32 : x86_dynarec_opcodes_db_a16; opcode_mask = 0xff; over = 1; pc_off = -1; + test_modrm = 0; break; case 0xdc: op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dc_a32 : x86_dynarec_opcodes_dc_a16; @@ -538,24 +775,28 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t opcode_mask = 0x1f; over = 1; pc_off = -1; + test_modrm = 0; break; case 0xdd: op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dd_a32 : x86_dynarec_opcodes_dd_a16; opcode_mask = 0xff; over = 1; pc_off = -1; + test_modrm = 0; break; case 0xde: op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_de_a32 : x86_dynarec_opcodes_de_a16; opcode_mask = 0xff; over = 1; pc_off = -1; + test_modrm = 0; break; case 0xdf: op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_df_a32 : x86_dynarec_opcodes_df_a16; opcode_mask = 0xff; over = 1; pc_off = -1; + test_modrm = 0; break; case 0xf0: /*LOCK*/ @@ -577,7 +818,7 @@ void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t generate_call: codegen_timing_opcode(opcode, fetchdat, op_32); - + op = op_table[((opcode >> opcode_shift) | op_32) & opcode_mask]; // if (output) // pclog("Generate call at %08X %02X %08X %02X %08X %08X %08X %08X %08X %02X %02X %02X %02X\n", &codeblock[block_current][block_pos], opcode, new_pc, ram[old_pc], EAX, EBX, ECX, EDX, ESI, ram[0x7bd2+6],ram[0x7bd2+7],ram[0x7bd2+8],ram[0x7bd2+9]); @@ -599,6 +840,41 @@ generate_call: addlong((uint32_t)&ssegs); addlong(op_ssegs); } + + if (!test_modrm || + (op_table == x86_dynarec_opcodes && opcode_modrm[opcode]) || + (op_table == x86_dynarec_opcodes_0f && opcode_0f_modrm[opcode])) + { + int stack_offset = 0; + + if (op_table == x86_dynarec_opcodes && opcode == 0x8f) /*POP*/ + stack_offset = (op_32 & 0x100) ? 4 : 2; + + mod = (fetchdat >> 6) & 3; + reg = (fetchdat >> 3) & 7; + rm = fetchdat & 7; + + addbyte(0xC7); /*MOVL $mod,(mod)*/ + addbyte(0x05); + addlong((uint32_t)&mod); + addlong(mod); + addbyte(0xC7); /*MOVL $reg,(reg)*/ + addbyte(0x05); + addlong((uint32_t)®); + addlong(reg); + addbyte(0xC7); /*MOVL $rm,(rm)*/ + addbyte(0x05); + addlong((uint32_t)&rm); + addlong(rm); + + op_pc += pc_off; + if (mod != 3 && !(op_32 & 0x200)) + op_ea_seg = codegen_generate_ea_16_long(op_ea_seg, fetchdat, op_ssegs, &op_pc); + if (mod != 3 && (op_32 & 0x200)) + op_ea_seg = codegen_generate_ea_32_long(op_ea_seg, fetchdat, op_ssegs, &op_pc, stack_offset); + op_pc -= pc_off; + } + // if (op_ea_seg != last_ea_seg) // { // last_ea_seg = op_ea_seg; @@ -607,6 +883,8 @@ generate_call: addlong((uint32_t)&ea_seg); addlong((uint32_t)op_ea_seg); // } + + addbyte(0xC7); /*MOVL $new_pc,(pc)*/ addbyte(0x05); addlong((uint32_t)&pc); @@ -629,25 +907,32 @@ generate_call: addbyte(0x24); addlong(fetchdat); - addbyte(0x83); /*ADD $1,ins*/ - addbyte(0x05); - addlong((uint32_t)&cpu_recomp_ins); - addbyte(1); - addbyte(0xE8); /*CALL*/ addlong(((uint8_t *)op - (uint8_t *)(&block->data[block_pos + 4]))); - if (codegen_block_cycles && - ((op_table == x86_dynarec_opcodes && ((opcode & 0xf0) == 0x70)) || + codegen_block_ins++; + + if (((op_table == x86_dynarec_opcodes && ((opcode & 0xf0) == 0x70)) || (op_table == x86_dynarec_opcodes && ((opcode & 0xfc) == 0xe0)) || (op_table == x86_dynarec_opcodes_0f && ((opcode & 0xf0) == 0x80)))) { /*Opcode is likely to cause block to exit, update cycle count*/ - 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_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; + } } block->ins++; diff --git a/src/x86_ops_mov.h b/src/x86_ops_mov.h index f3323cf..7f9b5f9 100644 --- a/src/x86_ops_mov.h +++ b/src/x86_ops_mov.h @@ -358,15 +358,14 @@ static int opXLAT_a32(uint32_t fetchdat) static int opMOV_b_r_a16(uint32_t fetchdat) { - if ((uint8_t)fetchdat >= 0xc0) + fetch_ea_16(fetchdat); + if (mod == 3) { - pc++; - setr8(fetchdat & 7, getr8((fetchdat >> 3) & 7)); + setr8(rm, getr8(reg)); CLOCK_CYCLES(timing_rr); } else { - fetch_ea_16(fetchdat); CHECK_WRITE(ea_seg, eaaddr, eaaddr); seteab(getr8(reg)); CLOCK_CYCLES(is486 ? 1 : 2); @@ -375,15 +374,14 @@ static int opMOV_b_r_a16(uint32_t fetchdat) } static int opMOV_b_r_a32(uint32_t fetchdat) { - if ((uint8_t)fetchdat >= 0xc0) + fetch_ea_32(fetchdat); + if (mod == 3) { - pc++; - setr8(fetchdat & 7, getr8((fetchdat >> 3) & 7)); + setr8(rm, getr8(reg)); CLOCK_CYCLES(timing_rr); } else { - fetch_ea_32(fetchdat); CHECK_WRITE(ea_seg, eaaddr, eaaddr); seteab(getr8(reg)); CLOCK_CYCLES(is486 ? 1 : 2); @@ -392,15 +390,14 @@ static int opMOV_b_r_a32(uint32_t fetchdat) } static int opMOV_w_r_a16(uint32_t fetchdat) { - if ((uint8_t)fetchdat >= 0xc0) + fetch_ea_16(fetchdat); + if (mod == 3) { - pc++; - regs[fetchdat & 7].w = regs[(fetchdat >> 3) & 7].w; + regs[rm].w = regs[reg].w; CLOCK_CYCLES(timing_rr); } else { - fetch_ea_16(fetchdat); CHECK_WRITE(ea_seg, eaaddr, eaaddr+1); seteaw(regs[reg].w); CLOCK_CYCLES(is486 ? 1 : 2); @@ -409,15 +406,14 @@ static int opMOV_w_r_a16(uint32_t fetchdat) } static int opMOV_w_r_a32(uint32_t fetchdat) { - if ((uint8_t)fetchdat >= 0xc0) + fetch_ea_32(fetchdat); + if (mod == 3) { - pc++; - regs[fetchdat & 7].w = regs[(fetchdat >> 3) & 7].w; + regs[rm].w = regs[reg].w; CLOCK_CYCLES(timing_rr); } else { - fetch_ea_32(fetchdat); CHECK_WRITE(ea_seg, eaaddr, eaaddr+1); seteaw(regs[reg].w); CLOCK_CYCLES(is486 ? 1 : 2); @@ -426,15 +422,14 @@ static int opMOV_w_r_a32(uint32_t fetchdat) } static int opMOV_l_r_a16(uint32_t fetchdat) { - if ((uint8_t)fetchdat >= 0xc0) + fetch_ea_16(fetchdat); + if (mod == 3) { - pc++; - regs[fetchdat & 7].l = regs[(fetchdat >> 3) & 7].l; + regs[rm].l = regs[reg].l; CLOCK_CYCLES(timing_rr); } else { - fetch_ea_16(fetchdat); CHECK_WRITE(ea_seg, eaaddr, eaaddr+3); seteal(regs[reg].l); CLOCK_CYCLES(is486 ? 1 : 2); @@ -443,15 +438,14 @@ static int opMOV_l_r_a16(uint32_t fetchdat) } static int opMOV_l_r_a32(uint32_t fetchdat) { - if ((uint8_t)fetchdat >= 0xc0) + fetch_ea_32(fetchdat); + if (mod == 3) { - pc++; - regs[fetchdat & 7].l = regs[(fetchdat >> 3) & 7].l; + regs[rm].l = regs[reg].l; CLOCK_CYCLES(timing_rr); } else { - fetch_ea_32(fetchdat); CHECK_WRITE(ea_seg, eaaddr, eaaddr+3); seteal(regs[reg].l); CLOCK_CYCLES(is486 ? 1 : 2); @@ -461,16 +455,15 @@ static int opMOV_l_r_a32(uint32_t fetchdat) static int opMOV_r_b_a16(uint32_t fetchdat) { - if ((uint8_t)fetchdat >= 0xc0) + fetch_ea_16(fetchdat); + if (mod == 3) { - pc++; - setr8((fetchdat >> 3) & 7, getr8(fetchdat & 7)); + setr8(reg, getr8(rm)); CLOCK_CYCLES(timing_rr); } else { uint8_t temp; - fetch_ea_16(fetchdat); CHECK_READ(ea_seg, eaaddr, eaaddr); temp = geteab(); if (abrt) return 1; setr8(reg, temp); @@ -480,16 +473,15 @@ static int opMOV_r_b_a16(uint32_t fetchdat) } static int opMOV_r_b_a32(uint32_t fetchdat) { - if ((uint8_t)fetchdat >= 0xc0) + fetch_ea_32(fetchdat); + if (mod == 3) { - pc++; - setr8((fetchdat >> 3) & 7, getr8(fetchdat & 7)); + setr8(reg, getr8(rm)); CLOCK_CYCLES(timing_rr); } else { uint8_t temp; - fetch_ea_32(fetchdat); CHECK_READ(ea_seg, eaaddr, eaaddr); temp = geteab(); if (abrt) return 1; setr8(reg, temp); @@ -499,16 +491,15 @@ static int opMOV_r_b_a32(uint32_t fetchdat) } static int opMOV_r_w_a16(uint32_t fetchdat) { - if ((uint8_t)fetchdat >= 0xc0) + fetch_ea_16(fetchdat); + if (mod == 3) { - pc++; - regs[(fetchdat >> 3) & 7].w = regs[fetchdat & 7].w; + regs[reg].w = regs[rm].w; CLOCK_CYCLES(timing_rr); } else { uint16_t temp; - fetch_ea_16(fetchdat); CHECK_READ(ea_seg, eaaddr, eaaddr+1); temp = geteaw(); if (abrt) return 1; regs[reg].w = temp; @@ -518,16 +509,15 @@ static int opMOV_r_w_a16(uint32_t fetchdat) } static int opMOV_r_w_a32(uint32_t fetchdat) { - if ((uint8_t)fetchdat >= 0xc0) + fetch_ea_32(fetchdat); + if (mod == 3) { - pc++; - regs[(fetchdat >> 3) & 7].w = regs[fetchdat & 7].w; + regs[reg].w = regs[rm].w; CLOCK_CYCLES(timing_rr); } else { uint16_t temp; - fetch_ea_32(fetchdat); CHECK_READ(ea_seg, eaaddr, eaaddr+1); temp = geteaw(); if (abrt) return 1; regs[reg].w = temp; @@ -537,16 +527,15 @@ static int opMOV_r_w_a32(uint32_t fetchdat) } static int opMOV_r_l_a16(uint32_t fetchdat) { - if ((uint8_t)fetchdat >= 0xc0) + fetch_ea_16(fetchdat); + if (mod == 3) { - pc++; - regs[(fetchdat >> 3) & 7].l = regs[fetchdat & 7].l; + regs[reg].l = regs[rm].l; CLOCK_CYCLES(timing_rr); } else { uint32_t temp; - fetch_ea_16(fetchdat); CHECK_READ(ea_seg, eaaddr, eaaddr+3); temp = geteal(); if (abrt) return 1; regs[reg].l = temp; @@ -556,16 +545,15 @@ static int opMOV_r_l_a16(uint32_t fetchdat) } static int opMOV_r_l_a32(uint32_t fetchdat) { - if ((uint8_t)fetchdat >= 0xc0) + fetch_ea_32(fetchdat); + if (mod == 3) { - pc++; - regs[(fetchdat >> 3) & 7].l = regs[fetchdat & 7].l; + regs[reg].l = regs[rm].l; CLOCK_CYCLES(timing_rr); } else { uint32_t temp; - fetch_ea_32(fetchdat); CHECK_READ(ea_seg, eaaddr, eaaddr+3); temp = geteal(); if (abrt) return 1; regs[reg].l = temp;