Effective address calculations now implemented by recompiled code. Up to 30% performance gain seen.
This commit is contained in:
parent
436c5b8cc2
commit
4855071ead
5 changed files with 345 additions and 204 deletions
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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++;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in a new issue