Merge from trunk

This commit is contained in:
SarahW 2019-04-18 20:46:38 +01:00
commit 50e7de5214
282 changed files with 51494 additions and 22451 deletions

133
src/386.c
View file

@ -2,7 +2,6 @@
#include <stdint.h>
#include <stdlib.h>
#include "ibm.h"
#include "386.h"
#include "x86.h"
#include "x87.h"
#include "mem.h"
@ -13,56 +12,15 @@
#include "nmi.h"
#include "386_common.h"
#include "codegen.h"
#undef CPU_BLOCK_END
#define CPU_BLOCK_END()
extern int codegen_flags_changed;
extern int nmi_enable;
int inscounts[256];
uint32_t oldpc2;
int trap;
extern int cpl_override;
int has_fpu;
extern int fpucount;
uint16_t rds;
uint16_t ea_rseg;
int is486;
int cgate32;
uint8_t romext[32768];
uint8_t *ram,*rom;
uint32_t rmdat32;
#define rmdat rmdat32
#define fetchdat rmdat32
uint32_t backupregs[16];
extern int oddeven;
int inttype;
uint32_t oldcs2;
uint32_t oldecx;
uint32_t *eal_r, *eal_w;
uint16_t *mod1add[2][8];
uint32_t *mod1seg[8];
static inline void fetch_ea_32_long(uint32_t rmdat)
{
eal_r = eal_w = NULL;
easeg = cpu_state.ea_seg->base;
ea_rseg = cpu_state.ea_seg->seg;
if (cpu_rm == 4)
{
uint8_t sib = rmdat >> 8;
@ -89,8 +47,7 @@ static inline void fetch_ea_32_long(uint32_t rmdat)
else if ((sib & 6) == 4 && !cpu_state.ssegs)
{
easeg = ss;
ea_rseg = SS;
cpu_state.ea_seg = &_ss;
cpu_state.ea_seg = &cpu_state.seg_ss;
}
if (((sib >> 3) & 7) != 4)
cpu_state.eaaddr += cpu_state.regs[(sib >> 3) & 7].l << (sib >> 6);
@ -103,8 +60,7 @@ static inline void fetch_ea_32_long(uint32_t rmdat)
if (cpu_rm == 5 && !cpu_state.ssegs)
{
easeg = ss;
ea_rseg = SS;
cpu_state.ea_seg = &_ss;
cpu_state.ea_seg = &cpu_state.seg_ss;
}
if (cpu_mod == 1)
{
@ -135,8 +91,7 @@ static inline void fetch_ea_16_long(uint32_t rmdat)
{
eal_r = eal_w = NULL;
easeg = cpu_state.ea_seg->base;
ea_rseg = cpu_state.ea_seg->seg;
if (!cpu_mod && cpu_rm == 6)
if (!cpu_mod && cpu_rm == 6)
{
cpu_state.eaaddr = getword();
}
@ -158,8 +113,7 @@ static inline void fetch_ea_16_long(uint32_t rmdat)
if (mod1seg[cpu_rm] == &ss && !cpu_state.ssegs)
{
easeg = ss;
ea_rseg = SS;
cpu_state.ea_seg = &_ss;
cpu_state.ea_seg = &cpu_state.seg_ss;
}
cpu_state.eaaddr &= 0xFFFF;
}
@ -182,19 +136,7 @@ static inline void fetch_ea_16_long(uint32_t rmdat)
#define getwordf() ((uint16_t)(fetchdat)); cpu_state.pc+=2
#define getbyte2f() ((uint8_t)(fetchdat>>8)); cpu_state.pc++
#define getword2f() ((uint16_t)(fetchdat>>8)); cpu_state.pc+=2
extern int xout;
int oldi;
uint32_t testr[9];
extern int dontprint;
#undef NOTRM
#define NOTRM if (!(msw & 1) || (eflags & VM_FLAG))\
{ \
x86_int(6); \
return 0; \
}
#define OP_TABLE(name) ops_ ## name
@ -203,13 +145,6 @@ extern int dontprint;
#include "x86_ops.h"
#undef NOTRM
#define NOTRM if (!(msw & 1) || (eflags & VM_FLAG))\
{ \
x86_int(6); \
break; \
}
void exec386(int cycs)
{
uint8_t temp;
@ -222,42 +157,31 @@ void exec386(int cycs)
// output=3;
while (cycles>0)
{
int cycle_period = (timer_count >> TIMER_SHIFT) + 1;
int cycle_period = (timer_target - (uint32_t)tsc) + 1;
x86_was_reset = 0;
cycdiff=0;
oldcyc=cycles;
timer_start_period(cycles << TIMER_SHIFT);
// pclog("%i %02X\n", ins, ram[8]);
while (cycdiff < cycle_period)
{
/* testr[0]=EAX; testr[1]=EBX; testr[2]=ECX; testr[3]=EDX;
testr[4]=ESI; testr[5]=EDI; testr[6]=EBP; testr[7]=ESP;*/
/* testr[8]=flags;*/
// oldcs2=oldcs;
// oldpc2=oldpc;
oldcs=CS;
cpu_state.oldpc = cpu_state.pc;
oldcpl=CPL;
cpu_state.op32 = use32;
dontprint=0;
cpu_state.ea_seg = &_ds;
cpu_state.ea_seg = &cpu_state.seg_ds;
cpu_state.ssegs = 0;
fetchdat = fastreadl(cs + cpu_state.pc);
if (!cpu_state.abrt)
{
trap = flags & T_FLAG;
opcode = fetchdat & 0xFF;
{
uint8_t opcode = fetchdat & 0xFF;
fetchdat >>= 8;
trap = cpu_state.flags & T_FLAG;
if (output == 3)
{
pclog("%04X(%06X):%04X : %08X %08X %08X %08X %04X %04X %04X(%08X) %04X %04X %04X(%08X) %08X %08X %08X SP=%04X:%08X %02X %04X %i %08X %08X %i %i %02X %02X %02X %02X %02X %f %02X%02X %02X%02X %02X%02X %02X\n",CS,cs,cpu_state.pc,EAX,EBX,ECX,EDX,CS,DS,ES,es,FS,GS,SS,ss,EDI,ESI,EBP,SS,ESP,opcode,flags,ins,0, ldt.base, CPL, stack32, pic.pend, pic.mask, pic.mask2, pic2.pend, pic2.mask, pit.c[0], ram[0xB270+0x3F5], ram[0xB270+0x3F4], ram[0xB270+0x3F7], ram[0xB270+0x3F6], ram[0xB270+0x3F9], ram[0xB270+0x3F8], ram[0x4430+0x0D49]);
pclog("%04X(%06X):%04X : %08X %08X %08X %08X %04X %04X %04X(%08X) %04X %04X %04X(%08X) %08X %08X %08X SP=%04X:%08X %02X %04X %i %08X %08X %i %i %02X %02X %02X %02X %02X\n",CS,cs,cpu_state.pc,EAX,EBX,ECX,EDX,CS,DS,ES,es,FS,GS,SS,ss,EDI,ESI,EBP,SS,ESP,opcode,cpu_state.flags,ins,0, ldt.base, CPL, stack32, pic.pend, pic.mask, pic.mask2, pic2.pend, pic2.mask);
}
cpu_state.pc++;
x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat);
@ -265,29 +189,17 @@ dontprint=0;
break;
}
if (!use32) cpu_state.pc &= 0xffff;
if (cpu_state.abrt)
{
flags_rebuild();
// pclog("Abort\n");
// if (CS == 0x228) pclog("Abort at %04X:%04X - %i %i %i\n",CS,pc,notpresent,nullseg,abrt);
/* if (testr[0]!=EAX) pclog("EAX corrupted %08X\n",pc);
if (testr[1]!=EBX) pclog("EBX corrupted %08X\n",pc);
if (testr[2]!=ECX) pclog("ECX corrupted %08X\n",pc);
if (testr[3]!=EDX) pclog("EDX corrupted %08X\n",pc);
if (testr[4]!=ESI) pclog("ESI corrupted %08X\n",pc);
if (testr[5]!=EDI) pclog("EDI corrupted %08X\n",pc);
if (testr[6]!=EBP) pclog("EBP corrupted %08X\n",pc);
if (testr[7]!=ESP) pclog("ESP corrupted %08X\n",pc);*/
/* if (testr[8]!=flags) pclog("FLAGS corrupted %08X\n",pc);*/
tempi = cpu_state.abrt;
cpu_state.abrt = 0;
x86_doabrt(tempi);
if (cpu_state.abrt)
{
cpu_state.abrt = 0;
CS = oldcs;
cpu_state.pc = cpu_state.oldpc;
pclog("Double fault %i\n", ins);
pmodeint(8, 0);
@ -306,20 +218,19 @@ dontprint=0;
{
flags_rebuild();
// oldpc=pc;
// oldcs=CS;
if (msw&1)
{
pmodeint(1,0);
}
else
{
writememw(ss,(SP-2)&0xFFFF,flags);
writememw(ss,(SP-2)&0xFFFF,cpu_state.flags);
writememw(ss,(SP-4)&0xFFFF,CS);
writememw(ss,(SP-6)&0xFFFF,cpu_state.pc);
SP-=6;
addr = (1 << 2) + idt.base;
flags&=~I_FLAG;
flags&=~T_FLAG;
cpu_state.flags &= ~I_FLAG;
cpu_state.flags &= ~T_FLAG;
cpu_state.pc=readmemw(0,addr);
loadcs(readmemw(0,addr+2));
}
@ -327,7 +238,6 @@ dontprint=0;
else if (nmi && nmi_enable && nmi_mask)
{
cpu_state.oldpc = cpu_state.pc;
oldcs = CS;
// pclog("NMI\n");
x86_int(2);
nmi_enable = 0;
@ -337,7 +247,7 @@ dontprint=0;
nmi = 0;
}
}
else if ((flags&I_FLAG) && pic_intpending)
else if ((cpu_state.flags & I_FLAG) && pic_intpending)
{
temp=picinterrupt();
if (temp!=0xFF)
@ -353,14 +263,13 @@ dontprint=0;
}
else
{
writememw(ss,(SP-2)&0xFFFF,flags);
writememw(ss,(SP-2)&0xFFFF,cpu_state.flags);
writememw(ss,(SP-4)&0xFFFF,CS);
writememw(ss,(SP-6)&0xFFFF,cpu_state.pc);
SP-=6;
addr = (temp << 2) + idt.base;
flags&=~I_FLAG;
flags&=~T_FLAG;
oxpc=cpu_state.pc;
cpu_state.flags &= ~I_FLAG;
cpu_state.flags &= ~T_FLAG;
cpu_state.pc=readmemw(0,addr);
loadcs(readmemw(0,addr+2));
// if (temp==0x76) pclog("INT to %04X:%04X\n",CS,pc);
@ -381,7 +290,7 @@ dontprint=0;
}
tsc += cycdiff;
timer_end_period(cycles << TIMER_SHIFT);
if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t)tsc))
timer_process();
}
}

View file

@ -1,13 +0,0 @@
extern void cpu_386_flags_extract();
extern void cpu_386_flags_rebuild();
void pmodeint(int num, int soft);
void loadcscall(uint16_t seg);
void loadcsjmp(uint16_t seg, uint32_t oxpc);
void pmoderetf(int is32, uint16_t off);
void pmodeiret(int is32);
void x86_int_sw(int num);
int x86_int_sw_rm(int num);
int divl(uint32_t val);
int idivl(int32_t val);

249
src/386_common.c Normal file
View file

@ -0,0 +1,249 @@
#include "ibm.h"
#include "x86.h"
#include "386_common.h"
#include "x86_flags.h"
#include "codegen.h"
x86seg gdt, ldt, idt, tr;
uint32_t cr2, cr3, cr4;
uint32_t dr[8];
uint32_t use32;
int stack32;
int optype;
int trap;
uint32_t rmdat;
uint32_t *eal_r, *eal_w;
int nmi_enable = 1;
int cpl_override=0;
int fpucount=0;
uint16_t cpu_cur_status = 0;
uint32_t pccache;
uint8_t *pccache2;
void x86_int(int num)
{
uint32_t addr;
// pclog("x86_int %02x %04x:%04x\n", num, CS,pc);
flags_rebuild();
cpu_state.pc=cpu_state.oldpc;
if (msw&1)
{
pmodeint(num,0);
}
else
{
addr = (num << 2) + idt.base;
if ((num << 2) + 3 > idt.limit)
{
if (idt.limit < 35)
{
cpu_state.abrt = 0;
softresetx86();
cpu_set_edx();
pclog("Triple fault in real mode - reset\n");
}
else
x86_int(8);
}
else
{
if (stack32)
{
writememw(ss,ESP-2,cpu_state.flags);
writememw(ss,ESP-4,CS);
writememw(ss,ESP-6,cpu_state.pc);
ESP-=6;
}
else
{
writememw(ss,((SP-2)&0xFFFF),cpu_state.flags);
writememw(ss,((SP-4)&0xFFFF),CS);
writememw(ss,((SP-6)&0xFFFF),cpu_state.pc);
SP-=6;
}
cpu_state.flags &= ~I_FLAG;
cpu_state.flags &= ~T_FLAG;
cpu_state.pc=readmemw(0,addr);
loadcs(readmemw(0,addr+2));
}
}
cycles-=70;
CPU_BLOCK_END();
}
void x86_int_sw(int num)
{
uint32_t addr;
// pclog("x86_int_sw %02x %04x:%04x\n", num, CS,pc);
// pclog("x86_int\n");
flags_rebuild();
cycles -= timing_int;
if (msw&1)
{
pmodeint(num,1);
}
else
{
addr = (num << 2) + idt.base;
if ((num << 2) + 3 > idt.limit)
{
x86_int(13);
}
else
{
if (stack32)
{
writememw(ss,ESP-2,cpu_state.flags);
writememw(ss,ESP-4,CS);
writememw(ss,ESP-6,cpu_state.pc);
ESP-=6;
}
else
{
writememw(ss,((SP-2)&0xFFFF),cpu_state.flags);
writememw(ss,((SP-4)&0xFFFF),CS);
writememw(ss,((SP-6)&0xFFFF),cpu_state.pc);
SP-=6;
}
cpu_state.flags &= ~I_FLAG;
cpu_state.flags &= ~T_FLAG;
cpu_state.pc=readmemw(0,addr);
loadcs(readmemw(0,addr+2));
cycles -= timing_int_rm;
}
}
trap = 0;
CPU_BLOCK_END();
}
int x86_int_sw_rm(int num)
{
uint32_t addr;
uint16_t new_pc, new_cs;
flags_rebuild();
cycles -= timing_int;
addr = num << 2;
new_pc = readmemw(0, addr);
new_cs = readmemw(0, addr + 2);
if (cpu_state.abrt) return 1;
writememw(ss,((SP-2)&0xFFFF),cpu_state.flags); if (cpu_state.abrt) {pclog("abrt5\n"); return 1; }
writememw(ss,((SP-4)&0xFFFF),CS);
writememw(ss,((SP-6)&0xFFFF),cpu_state.pc); if (cpu_state.abrt) {pclog("abrt6\n"); return 1; }
SP-=6;
cpu_state.eflags &= ~VIF_FLAG;
cpu_state.flags &= ~T_FLAG;
cpu_state.pc = new_pc;
loadcs(new_cs);
cycles -= timing_int_rm;
trap = 0;
CPU_BLOCK_END();
return 0;
}
void x86illegal()
{
// pclog("x86 illegal %04X %08X %04X:%08X %02X\n",msw,cr0,CS,pc,opcode);
// if (output)
// {
// dumpregs();
// exit(-1);
// }
x86_int(6);
}
int checkio(int port)
{
uint16_t t;
uint8_t d;
cpl_override = 1;
t = readmemw(tr.base, 0x66);
cpl_override = 0;
// pclog("CheckIO 1 %08X %04x %02x\n",tr.base, eflags, _cs.access);
if (cpu_state.abrt) return 0;
// pclog("CheckIO %04X %01X %01X %02X %04X %04X %08X ",CS,CPL,IOPL,port,t,t+(port>>3),tr.base+t+(port>>3));
if ((t+(port>>3))>tr.limit) return 1;
cpl_override = 1;
d = readmembl(tr.base + t + (port >> 3));
// d=readmemb(tr.base,t+(port>>3));
cpl_override = 0;
// pclog("%02X %02X\n",d,d&(1<<(port&7)));
return d&(1<<(port&7));
}
#define divexcp() { \
pclog("Divide exception at %04X(%06X):%04X\n",CS,cs,cpu_state.pc); \
x86_int(0); \
}
int divl(uint32_t val)
{
if (val==0)
{
divexcp();
return 1;
}
uint64_t num=(((uint64_t)EDX)<<32)|EAX;
uint64_t quo=num/val;
uint32_t rem=num%val;
uint32_t quo32=(uint32_t)(quo&0xFFFFFFFF);
if (quo!=(uint64_t)quo32)
{
divexcp();
return 1;
}
EDX=rem;
EAX=quo32;
return 0;
}
int idivl(int32_t val)
{
if (val==0)
{
divexcp();
return 1;
}
int64_t num=(((uint64_t)EDX)<<32)|EAX;
int64_t quo=num/val;
int32_t rem=num%val;
int32_t quo32=(int32_t)(quo&0xFFFFFFFF);
if (quo!=(int64_t)quo32)
{
divexcp();
return 1;
}
EDX=rem;
EAX=quo32;
return 0;
}
void cpu_386_flags_extract()
{
flags_extract();
}
void cpu_386_flags_rebuild()
{
flags_rebuild();
}

View file

@ -1,21 +1,19 @@
extern uint16_t ea_rseg;
#ifndef _386_COMMON_H_
#define _386_COMMON_H_
#undef readmemb
#undef writememb
#define readmemb(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==-1)?readmembl((s)+(a)): *(uint8_t *)(readlookup2[(uint32_t)((s)+(a))>>12] + (uint32_t)((s) + (a))) )
#define readmemw(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==-1 || (((s)+(a)) & 1))?readmemwl((s)+(a)):*(uint16_t *)(readlookup2[(uint32_t)((s)+(a))>>12]+(uint32_t)((s)+(a))))
#define readmeml(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==-1 || (((s)+(a)) & 3))?readmemll((s)+(a)):*(uint32_t *)(readlookup2[(uint32_t)((s)+(a))>>12]+(uint32_t)((s)+(a))))
#define readmemq(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==-1 || (((s)+(a)) & 7))?readmemql((s)+(a)):*(uint64_t *)(readlookup2[(uint32_t)((s)+(a))>>12]+(uint32_t)((s)+(a))))
#define readmemb(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF)?readmemb386l(s,a): *(uint8_t *)(readlookup2[(uint32_t)((s)+(a))>>12] + (uint32_t)((s) + (a))) )
#define readmemq(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF || (((s)+(a)) & 7))?readmemql(s,a):*(uint64_t *)(readlookup2[(uint32_t)((s)+(a))>>12]+(uint32_t)((s)+(a))))
#define writememb(s,a,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF) writememb386l(s,a,v); else *(uint8_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uint32_t)((s) + (a))) = v
#define writememw(s,a,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF || (((s)+(a)) & 1)) writememwl(s,a,v); else *(uint16_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uint32_t)((s) + (a))) = v
#define writememl(s,a,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF || (((s)+(a)) & 3)) writememll(s,a,v); else *(uint32_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uint32_t)((s) + (a))) = v
#define writememq(s,a,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF || (((s)+(a)) & 7)) writememql(s,a,v); else *(uint64_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uint32_t)((s) + (a))) = v
#define writememb(s,a,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==-1) writemembl((s)+(a),v); else *(uint8_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uint32_t)((s) + (a))) = v
#define writememw(s,a,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==-1 || (((s)+(a)) & 1)) writememwl((s)+(a),v); else *(uint16_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uint32_t)((s) + (a))) = v
#define writememl(s,a,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==-1 || (((s)+(a)) & 3)) writememll((s)+(a),v); else *(uint32_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uint32_t)((s) + (a))) = v
#define writememq(s,a,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==-1 || (((s)+(a)) & 7)) writememql((s)+(a),v); else *(uint64_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uint32_t)((s) + (a))) = v
int checkio(int port);
#define check_io_perm(port) if (!IOPLp || (eflags&VM_FLAG)) \
#define check_io_perm(port) if (!IOPLp || (cpu_state.eflags&VM_FLAG)) \
{ \
int tempi = checkio(port); \
if (cpu_state.abrt) return 1; \
@ -26,26 +24,35 @@ int checkio(int port);
} \
}
#define checkio_perm(port) if (!IOPLp || (eflags&VM_FLAG)) \
{ \
int tempi = checkio(port); \
if (cpu_state.abrt) break; \
if (tempi) \
{ \
x86gpf(NULL,0); \
break; \
} \
}
#define SEG_CHECK_READ(seg) \
do \
{ \
if ((seg)->base == 0xffffffff) \
{ \
x86gpf("Segment can't read", 0);\
return 1; \
} \
} while (0)
#define SEG_CHECK_WRITE(seg) \
do \
{ \
if ((seg)->base == 0xffffffff) \
{ \
x86gpf("Segment can't write", 0);\
return 1; \
} \
} while (0)
#define CHECK_READ(seg, low, high) \
if ((low < (seg)->limit_low) || (high > (seg)->limit_high) || ((msw & 1) && !(eflags & VM_FLAG) && (((seg)->access & 10) == 8))) \
if ((low < (seg)->limit_low) || (high > (seg)->limit_high) || ((msw & 1) && !(cpu_state.eflags & VM_FLAG) && (((seg)->access & 10) == 8))) \
{ \
x86gpf("Limit check", 0); \
return 1; \
}
#define CHECK_WRITE(seg, low, high) \
if ((low < (seg)->limit_low) || (high > (seg)->limit_high) || !((seg)->access & 2) || ((msw & 1) && !(eflags & VM_FLAG) && ((seg)->access & 8))) \
if ((low < (seg)->limit_low) || (high > (seg)->limit_high) || !((seg)->access & 2) || ((msw & 1) && !(cpu_state.eflags & VM_FLAG) && ((seg)->access & 8))) \
{ \
x86gpf("Limit check", 0); \
return 1; \
@ -59,7 +66,7 @@ int checkio(int port);
}
#define NOTRM if (!(msw & 1) || (eflags & VM_FLAG))\
#define NOTRM if (!(msw & 1) || (cpu_state.eflags & VM_FLAG))\
{ \
x86_int(6); \
return 1; \
@ -124,6 +131,17 @@ static inline uint32_t fastreadl(uint32_t a)
return val;
}
static inline void *get_ram_ptr(uint32_t a)
{
if ((a >> 12) == pccache)
return &pccache2[a];
else
{
uint8_t *t = getpccache(a);
return &t[a];
}
}
static inline uint8_t getbyte()
{
cpu_state.pc++;
@ -156,32 +174,30 @@ static inline uint8_t geteab()
return (cpu_rm & 4) ? cpu_state.regs[cpu_rm & 3].b.h : cpu_state.regs[cpu_rm&3].b.l;
if (eal_r)
return *(uint8_t *)eal_r;
return readmemb(easeg, cpu_state.eaaddr);
return readmemb(easeg,cpu_state.eaaddr);
}
static inline uint16_t geteaw()
{
if (cpu_mod == 3)
return cpu_state.regs[cpu_rm].w;
// cycles-=3;
if (eal_r)
return *(uint16_t *)eal_r;
return readmemw(easeg, cpu_state.eaaddr);
return readmemw(easeg,cpu_state.eaaddr);
}
static inline uint32_t geteal()
{
if (cpu_mod == 3)
return cpu_state.regs[cpu_rm].l;
// cycles-=3;
if (eal_r)
return *eal_r;
return readmeml(easeg, cpu_state.eaaddr);
return readmeml(easeg,cpu_state.eaaddr);
}
static inline uint64_t geteaq()
{
return readmemq(easeg, cpu_state.eaaddr);
return readmemq(easeg,cpu_state.eaaddr);
}
static inline uint8_t geteab_mem()
@ -202,24 +218,20 @@ static inline uint32_t geteal_mem()
static inline void seteaq(uint64_t v)
{
writememql(easeg, cpu_state.eaaddr, v);
writememql(easeg+cpu_state.eaaddr, v);
}
#define seteab(v) if (cpu_mod!=3) { if (eal_w) *(uint8_t *)eal_w=v; else writememb386l(easeg,cpu_state.eaaddr,v); } else if (cpu_rm&4) cpu_state.regs[cpu_rm&3].b.h=v; else cpu_state.regs[cpu_rm].b.l=v
#define seteaw(v) if (cpu_mod!=3) { if (eal_w) *(uint16_t *)eal_w=v; else writememwl(easeg,cpu_state.eaaddr,v); } else cpu_state.regs[cpu_rm].w=v
#define seteal(v) if (cpu_mod!=3) { if (eal_w) *eal_w=v; else writememll(easeg,cpu_state.eaaddr,v); } else cpu_state.regs[cpu_rm].l=v
#define seteab(v) if (cpu_mod!=3) { if (eal_w) *(uint8_t *)eal_w=v; else writemembl(easeg+cpu_state.eaaddr,v); } else if (cpu_rm&4) cpu_state.regs[cpu_rm&3].b.h=v; else cpu_state.regs[cpu_rm].b.l=v
#define seteaw(v) if (cpu_mod!=3) { if (eal_w) *(uint16_t *)eal_w=v; else writememwl(easeg+cpu_state.eaaddr,v); } else cpu_state.regs[cpu_rm].w=v
#define seteal(v) if (cpu_mod!=3) { if (eal_w) *eal_w=v; else writememll(easeg+cpu_state.eaaddr,v); } else cpu_state.regs[cpu_rm].l=v
#define seteab_mem(v) if (eal_w) *(uint8_t *)eal_w=v; else writememb386l(easeg,cpu_state.eaaddr,v);
#define seteaw_mem(v) if (eal_w) *(uint16_t *)eal_w=v; else writememwl(easeg,cpu_state.eaaddr,v);
#define seteal_mem(v) if (eal_w) *eal_w=v; else writememll(easeg,cpu_state.eaaddr,v);
#define seteab_mem(v) if (eal_w) *(uint8_t *)eal_w=v; else writemembl(easeg+cpu_state.eaaddr,v);
#define seteaw_mem(v) if (eal_w) *(uint16_t *)eal_w=v; else writememwl(easeg+cpu_state.eaaddr,v);
#define seteal_mem(v) if (eal_w) *eal_w=v; else writememll(easeg+cpu_state.eaaddr,v);
#define getbytef() ((uint8_t)(fetchdat)); cpu_state.pc++
#define getwordf() ((uint16_t)(fetchdat)); cpu_state.pc+=2
#define getbyte2f() ((uint8_t)(fetchdat>>8)); cpu_state.pc++
#define getword2f() ((uint16_t)(fetchdat>>8)); cpu_state.pc+=2
#define rmdat rmdat32
#define fetchdat rmdat32
void x86_int(int num);
#endif

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,5 @@
#include "ibm.h"
#include "cpu.h"
#include "386.h"
#include "x86.h"
#include "x86_ops.h"
#include "x87.h"
@ -15,14 +14,10 @@
#include "386_common.h"
extern uint16_t *mod1add[2][8];
extern uint32_t *mod1seg[8];
static inline void fetch_ea_32_long(uint32_t rmdat)
{
eal_r = eal_w = NULL;
easeg = cpu_state.ea_seg->base;
ea_rseg = cpu_state.ea_seg->seg;
if (easeg != 0xFFFFFFFF && ((easeg + cpu_state.eaaddr) & 0xFFF) <= 0xFFC)
{
uint32_t addr = easeg + cpu_state.eaaddr;
@ -37,7 +32,6 @@ static inline void fetch_ea_16_long(uint32_t rmdat)
{
eal_r = eal_w = NULL;
easeg = cpu_state.ea_seg->base;
ea_rseg = cpu_state.ea_seg->seg;
if (easeg != 0xFFFFFFFF && ((easeg + cpu_state.eaaddr) & 0xFFF) <= 0xFFC)
{
uint32_t addr = easeg + cpu_state.eaaddr;
@ -48,8 +42,8 @@ static inline void fetch_ea_16_long(uint32_t rmdat)
}
}
#define fetch_ea_16(rmdat) cpu_state.pc++; if (cpu_mod != 3) fetch_ea_16_long(rmdat);
#define fetch_ea_32(rmdat) cpu_state.pc++; if (cpu_mod != 3) fetch_ea_32_long(rmdat);
#define fetch_ea_16(rmdat) cpu_state.pc++; if (cpu_mod != 3) fetch_ea_16_long(rmdat);
#define fetch_ea_32(rmdat) cpu_state.pc++; if (cpu_mod != 3) fetch_ea_32_long(rmdat);
#define PREFETCH_RUN(instr_cycles, bytes, modrm, reads, read_ls, writes, write_ls, ea32)
@ -57,7 +51,8 @@ static inline void fetch_ea_16_long(uint32_t rmdat)
#define PREFETCH_FLUSH()
#define OP_TABLE(name) dynarec_ops_ ## name
#define CLOCK_CYCLES(c)
/*Temporary*/
#define CLOCK_CYCLES(c)
#define CLOCK_CYCLES_ALWAYS(c) cycles -= (c)
#include "386_ops.h"

View file

@ -104,6 +104,15 @@ static inline uint32_t POP_L_seg(uint32_t seg)
return ret;
}
static int ILLEGAL(uint32_t fetchdat)
{
cpu_state.pc = cpu_state.oldpc;
// fatal("Illegal instruction %08X\n", fetchdat);
x86illegal();
return 0;
}
#include "x86_ops_arith.h"
#include "x86_ops_atomic.h"
#include "x86_ops_bcd.h"
@ -118,6 +127,7 @@ static inline uint32_t POP_L_seg(uint32_t seg)
#include "x86_ops_jump.h"
#include "x86_ops_misc.h"
#include "x86_ops_mmx.h"
#include "x86_ops_3dnow.h"
#include "x86_ops_mmx_arith.h"
#include "x86_ops_mmx_cmp.h"
#include "x86_ops_mmx_logic.h"
@ -140,15 +150,6 @@ static inline uint32_t POP_L_seg(uint32_t seg)
#include "x86_ops_string.h"
#include "x86_ops_xchg.h"
static int ILLEGAL(uint32_t fetchdat)
{
cpu_state.pc = cpu_state.oldpc;
// fatal("Illegal instruction %08X\n", fetchdat);
x86illegal();
return 0;
}
static int op0F_w_a16(uint32_t fetchdat)
{
int opcode = fetchdat & 0xff;
@ -455,7 +456,98 @@ OpFn OP_TABLE(winchip_0f)[1024] =
/*f0*/ ILLEGAL, opPSLLW_a32, opPSLLD_a32, opPSLLQ_a32, ILLEGAL, opPMADDWD_a32, ILLEGAL, ILLEGAL, opPSUBB_a32, opPSUBW_a32, opPSUBD_a32, ILLEGAL, opPADDB_a32, opPADDW_a32, opPADDD_a32, ILLEGAL,
};
OpFn OP_TABLE(pentium_0f)[1024] =
OpFn OP_TABLE(winchip2_0f)[1024] =
{
/*16-bit data, 16-bit addr*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, opPREFETCH_a16, opFEMMS, op3DNOW_a16,
/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*60*/ opPUNPCKLBW_a16,opPUNPCKLWD_a16,opPUNPCKLDQ_a16,opPACKSSWB_a16, opPCMPGTB_a16, opPCMPGTW_a16, opPCMPGTD_a16, opPACKUSWB_a16, opPUNPCKHBW_a16,opPUNPCKHWD_a16,opPUNPCKHDQ_a16,opPACKSSDW_a16, ILLEGAL, ILLEGAL, opMOVD_l_mm_a16,opMOVQ_q_mm_a16,
/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a16, opPCMPEQW_a16, opPCMPEQD_a16, opEMMS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opMOVD_mm_l_a16,opMOVQ_mm_q_a16,
/*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w,
/*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16,
/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, ILLEGAL, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16,
/*b0*/ opCMPXCHG_b_a16,opCMPXCHG_w_a16,opLSS_w_a16, opBTR_w_r_a16, opLFS_w_a16, opLGS_w_a16, opMOVZX_w_b_a16,opMOVZX_w_w_a16,ILLEGAL, ILLEGAL, opBA_w_a16, opBTC_w_r_a16, opBSF_w_a16, opBSR_w_a16, opMOVSX_w_b_a16,ILLEGAL,
/*c0*/ opXADD_b_a16, opXADD_w_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI,
/*d0*/ ILLEGAL, opPSRLW_a16, opPSRLD_a16, opPSRLQ_a16, ILLEGAL, opPMULLW_a16, ILLEGAL, ILLEGAL, opPSUBUSB_a16, opPSUBUSW_a16, NULL, opPAND_a16, opPADDUSB_a16, opPADDUSW_a16, NULL, opPANDN_a16,
/*e0*/ ILLEGAL, opPSRAW_a16, opPSRAD_a16, ILLEGAL, ILLEGAL, opPMULHW_a16, ILLEGAL, ILLEGAL, opPSUBSB_a16, opPSUBSW_a16, NULL, opPOR_a16, opPADDSB_a16, opPADDSW_a16, NULL, opPXOR_a16,
/*f0*/ ILLEGAL, opPSLLW_a16, opPSLLD_a16, opPSLLQ_a16, ILLEGAL, opPMADDWD_a16, ILLEGAL, ILLEGAL, opPSUBB_a16, opPSUBW_a16, opPSUBD_a16, ILLEGAL, opPADDB_a16, opPADDW_a16, opPADDD_a16, ILLEGAL,
/*32-bit data, 16-bit addr*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ op0F00_a16, op0F01_l_a16, opLAR_l_a16, opLSL_l_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, opPREFETCH_a16, opFEMMS, op3DNOW_a16,
/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*60*/ opPUNPCKLBW_a16,opPUNPCKLWD_a16,opPUNPCKLDQ_a16,opPACKSSWB_a16, opPCMPGTB_a16, opPCMPGTW_a16, opPCMPGTD_a16, opPACKUSWB_a16, opPUNPCKHBW_a16,opPUNPCKHWD_a16,opPUNPCKHDQ_a16,opPACKSSDW_a16, ILLEGAL, ILLEGAL, opMOVD_l_mm_a16,opMOVQ_q_mm_a16,
/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a16, opPCMPEQW_a16, opPCMPEQD_a16, opEMMS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opMOVD_mm_l_a16,opMOVQ_mm_q_a16,
/*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l,
/*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16,
/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, ILLEGAL, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16,
/*b0*/ opCMPXCHG_b_a16,opCMPXCHG_l_a16,opLSS_l_a16, opBTR_l_r_a16, opLFS_l_a16, opLGS_l_a16, opMOVZX_l_b_a16,opMOVZX_l_w_a16,ILLEGAL, ILLEGAL, opBA_l_a16, opBTC_l_r_a16, opBSF_l_a16, opBSR_l_a16, opMOVSX_l_b_a16,opMOVSX_l_w_a16,
/*c0*/ opXADD_b_a16, opXADD_l_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI,
/*d0*/ ILLEGAL, opPSRLW_a16, opPSRLD_a16, opPSRLQ_a16, ILLEGAL, opPMULLW_a16, ILLEGAL, ILLEGAL, opPSUBUSB_a16, opPSUBUSW_a16, NULL, opPAND_a16, opPADDUSB_a16, opPADDUSW_a16, NULL, opPANDN_a16,
/*e0*/ ILLEGAL, opPSRAW_a16, opPSRAD_a16, ILLEGAL, ILLEGAL, opPMULHW_a16, ILLEGAL, ILLEGAL, opPSUBSB_a16, opPSUBSW_a16, NULL, opPOR_a16, opPADDSB_a16, opPADDSW_a16, NULL, opPXOR_a16,
/*f0*/ ILLEGAL, opPSLLW_a16, opPSLLD_a16, opPSLLQ_a16, ILLEGAL, opPMADDWD_a16, ILLEGAL, ILLEGAL, opPSUBB_a16, opPSUBW_a16, opPSUBD_a16, ILLEGAL, opPADDB_a16, opPADDW_a16, opPADDD_a16, ILLEGAL,
/*16-bit data, 32-bit addr*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ op0F00_a32, op0F01_w_a32, opLAR_w_a32, opLSL_w_a32, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, opPREFETCH_a32, opFEMMS, op3DNOW_a32,
/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*60*/ opPUNPCKLBW_a32,opPUNPCKLWD_a32,opPUNPCKLDQ_a32,opPACKSSWB_a32, opPCMPGTB_a32, opPCMPGTW_a32, opPCMPGTD_a32, opPACKUSWB_a32, opPUNPCKHBW_a32,opPUNPCKHWD_a32,opPUNPCKHDQ_a32,opPACKSSDW_a32, ILLEGAL, ILLEGAL, opMOVD_l_mm_a32,opMOVQ_q_mm_a32,
/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a32, opPCMPEQW_a32, opPCMPEQD_a32, opEMMS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opMOVD_mm_l_a32,opMOVQ_mm_q_a32,
/*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w,
/*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32,
/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, ILLEGAL, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32,
/*b0*/ opCMPXCHG_b_a32,opCMPXCHG_w_a32,opLSS_w_a32, opBTR_w_r_a32, opLFS_w_a32, opLGS_w_a32, opMOVZX_w_b_a32,opMOVZX_w_w_a32,ILLEGAL, ILLEGAL, opBA_w_a32, opBTC_w_r_a32, opBSF_w_a32, opBSR_w_a32, opMOVSX_w_b_a32,ILLEGAL,
/*c0*/ opXADD_b_a32, opXADD_w_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI,
/*d0*/ ILLEGAL, opPSRLW_a32, opPSRLD_a32, opPSRLQ_a32, ILLEGAL, opPMULLW_a32, ILLEGAL, ILLEGAL, opPSUBUSB_a32, opPSUBUSW_a32, NULL, opPAND_a32, opPADDUSB_a32, opPADDUSW_a32, NULL, opPANDN_a32,
/*e0*/ ILLEGAL, opPSRAW_a32, opPSRAD_a32, ILLEGAL, ILLEGAL, opPMULHW_a32, ILLEGAL, ILLEGAL, opPSUBSB_a32, opPSUBSW_a32, NULL, opPOR_a32, opPADDSB_a32, opPADDSW_a32, NULL, opPXOR_a32,
/*f0*/ ILLEGAL, opPSLLW_a32, opPSLLD_a32, opPSLLQ_a32, ILLEGAL, opPMADDWD_a32, ILLEGAL, ILLEGAL, opPSUBB_a32, opPSUBW_a32, opPSUBD_a32, ILLEGAL, opPADDB_a32, opPADDW_a32, opPADDD_a32, ILLEGAL,
/*32-bit data, 32-bit addr*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ op0F00_a32, op0F01_l_a32, opLAR_l_a32, opLSL_l_a32, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, opPREFETCH_a32, opFEMMS, op3DNOW_a32,
/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*60*/ opPUNPCKLBW_a32,opPUNPCKLWD_a32,opPUNPCKLDQ_a32,opPACKSSWB_a32, opPCMPGTB_a32, opPCMPGTW_a32, opPCMPGTD_a32, opPACKUSWB_a32, opPUNPCKHBW_a32,opPUNPCKHWD_a32,opPUNPCKHDQ_a32,opPACKSSDW_a32, ILLEGAL, ILLEGAL, opMOVD_l_mm_a32,opMOVQ_q_mm_a32,
/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a32, opPCMPEQW_a32, opPCMPEQD_a32, opEMMS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opMOVD_mm_l_a32,opMOVQ_mm_q_a32,
/*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l,
/*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32,
/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, ILLEGAL, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32,
/*b0*/ opCMPXCHG_b_a32,opCMPXCHG_l_a32,opLSS_l_a32, opBTR_l_r_a32, opLFS_l_a32, opLGS_l_a32, opMOVZX_l_b_a32,opMOVZX_l_w_a32,ILLEGAL, ILLEGAL, opBA_l_a32, opBTC_l_r_a32, opBSF_l_a32, opBSR_l_a32, opMOVSX_l_b_a32,opMOVSX_l_w_a32,
/*c0*/ opXADD_b_a32, opXADD_l_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI,
/*d0*/ ILLEGAL, opPSRLW_a32, opPSRLD_a32, opPSRLQ_a32, ILLEGAL, opPMULLW_a32, ILLEGAL, ILLEGAL, opPSUBUSB_a32, opPSUBUSW_a32, NULL, opPAND_a32, opPADDUSB_a32, opPADDUSW_a32, NULL, opPANDN_a32,
/*e0*/ ILLEGAL, opPSRAW_a32, opPSRAD_a32, ILLEGAL, ILLEGAL, opPMULHW_a32, ILLEGAL, ILLEGAL, opPSUBSB_a32, opPSUBSW_a32, NULL, opPOR_a32, opPADDSB_a32, opPADDSW_a32, NULL, opPXOR_a32,
/*f0*/ ILLEGAL, opPSLLW_a32, opPSLLD_a32, opPSLLQ_a32, ILLEGAL, opPMADDWD_a32, ILLEGAL, ILLEGAL, opPSUBB_a32, opPSUBW_a32, opPSUBD_a32, ILLEGAL, opPADDB_a32, opPADDW_a32, opPADDD_a32, ILLEGAL,
};
OpFn OP_TABLE(pentium_0f)[1024] =
{
/*16-bit data, 16-bit addr*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/

1054
src/808x.c

File diff suppressed because it is too large Load diff

View file

@ -23,24 +23,26 @@ wx-resources.cpp : pc.xrc
-wxrc -c pc.xrc -o wx-resources.cpp
# PCem
pcem_SOURCES = 386.c 386_dynarec.c 386_dynarec_ops.c 808x.c acc2036.c acc2168.c acc3221.c acer386sx.c ali1429.c amstrad.c cassette.c cbm_io.c cdrom-image.cc cdrom-null.c \
cmd640.c codegen.c codegen_ops.c codegen_timing_486.c codegen_timing_686.c codegen_timing_common.c codegen_timing_pentium.c codegen_timing_winchip.c compaq.c config.c cpu.c \
dells200.c device.c disc.c disc_fdi.c disc_img.c disc_sector.c dma.c esdi_at.c fdc.c fdc37c665.c fdd.c fdi2raw.c gameport.c \
hdd.c hdd_esdi.c hdd_file.c headland.c i430hx.c i430lx.c i430fx.c i430vx.c ide.c ide_atapi.c intel.c intel_flash.c io.c jim.c joystick_ch_flightstick_pro.c joystick_standard.c joystick_sw_pad.c \
pcem_SOURCES = 386.c 386_common.c 386_dynarec.c 386_dynarec_ops.c 808x.c acc2036.c acer386sx.c ali1429.c amstrad.c cbm_io.c cdrom-image.cc cdrom-null.c \
cmd640.c codegen.c codegen_accumulate.c codegen_allocator.c codegen_backend.c codegen_ir.c codegen_ops.c codegen_ops_3dnow.c codegen_ops_arith.c codegen_ops_branch.c codegen_ops_fpu_arith.c codegen_ops_fpu_constant.c codegen_ops_fpu_loadstore.c codegen_ops_fpu_misc.c codegen_ops_helpers.c codegen_ops_jump.c codegen_ops_logic.c codegen_ops_shift.c \
codegen_ops_misc.c codegen_ops_mov.c codegen_ops_stack.c codegen_reg.c codegen_timing_486.c codegen_timing_686.c codegen_timing_common.c codegen_timing_k6.c codegen_timing_pentium.c codegen_timing_winchip.c codegen_timing_winchip2.c compaq.c config.c cpu.c \
cpu_tables.c dells200.c device.c disc.c disc_fdi.c disc_img.c disc_sector.c dma.c esdi_at.c fdc.c fdc37c665.c fdd.c fdi2raw.c gameport.c \
hdd.c hdd_esdi.c hdd_file.c headland.c i430lx.c i430fx.c i430vx.c ide.c ide_atapi.c ide_sff8038i.c intel.c intel_flash.c io.c jim.c joystick_ch_flightstick_pro.c joystick_standard.c joystick_sw_pad.c \
joystick_tm_fcs.c keyboard.c keyboard_amstrad.c keyboard_at.c keyboard_olim24.c keyboard_pcjr.c keyboard_xt.c \
laserxt.c lpt.c lpt_dac.c lpt_dss.c mca.c mcr.c mem.c mem_bios.c mfm_at.c mfm_xebec.c model.c mouse.c mouse_msystems.c mouse_ps2.c mouse_serial.c neat.c nmi.c nvr.c olivetti_m24.c \
laserxt.c lpt.c lpt_dac.c lpt_dss.c mca.c mcr.c mem.c mem_bios.c mfm_at.c mfm_xebec.c model.c mouse.c mouse_msystems.c mouse_ps2.c mouse_serial.c mvp3.c neat.c nmi.c nvr.c olivetti_m24.c \
opti495.c paths.c pc.c pc87306.c pci.c pic.c piix.c pit.c ppi.c ps1.c ps2.c ps2_mca.c ps2_nvr.c nvr_tc8521.c pzx.c rom.c rtc.c rtc_tc8521.c scat.c scsi.c scsi_53c400.c scsi_aha1540.c scsi_cd.c scsi_hd.c scsi_zip.c \
serial.c sio.c sis496.c sl82c460.c sound.c sound_ad1848.c sound_adlib.c sound_adlibgold.c sound_audiopci.c sound_cms.c sound_emu8k.c sound_gus.c \
sound_mpu401_uart.c sound_opl.c sound_pas16.c sound_ps1.c sound_pssj.c sound_sb.c sound_sb_dsp.c sound_sn76489.c \
sound_speaker.c sound_ssi2001.c sound_wss.c sound_ym7128.c soundopenal.c tandy_eeprom.c tandy_rom.c \
sound_speaker.c sound_ssi2001.c sound_wss.c sound_ym7128.c soundopenal.c sst39sf010.c tandy_eeprom.c tandy_rom.c \
t1000.c t3100e.c \
timer.c um8669f.c um8881f.c vid_ati_eeprom.c vid_ati_mach64.c vid_ati18800.c vid_ati28800.c \
vid_ati68860_ramdac.c vid_cga.c vid_cl5429.c vid_colorplus.c vid_compaq_cga.c vid_ega.c vid_et4000.c vid_et4000w32.c vid_genius.c vid_hercules.c \
vid_ht216.c vid_icd2061.c vid_ics2595.c vid_incolor.c vid_mda.c vid_olivetti_m24.c vid_oti037.c vid_oti067.c vid_paradise.c vid_pc200.c \
vid_pc1512.c vid_pc1640.c vid_pcjr.c vid_ps1_svga.c vid_s3.c vid_s3_virge.c vid_sdac_ramdac.c vid_sigma.c \
vid_stg_ramdac.c vid_svga.c vid_svga_render.c vid_t1000.c vid_t3100e.c vid_tandy.c vid_tandysl.c vid_tgui9440.c \
vid_tkd8001_ramdac.c vid_tvga.c vid_unk_ramdac.c vid_vga.c vid_voodoo.c video.c wd76c10.c vid_wy700.c \
x86seg.c x87.c xi8088.c xtide.c zenith.c sound_dbopl.cc sound_resid.cc
vid_tkd8001_ramdac.c vid_tvga.c vid_unk_ramdac.c vid_vga.c vid_voodoo.c video.c wd76c10.c vid_wy700.c vt82c586b.c \
w83877tf.c x86seg.c x87.c xi8088.c xtide.c sound_dbopl.cc sound_resid.cc \
codegen_ops_mmx_arith.c codegen_ops_mmx_cmp.c codegen_ops_mmx_loadstore.c codegen_ops_mmx_logic.c codegen_ops_mmx_pack.c codegen_ops_mmx_shift.c
# DOSBox
pcem_SOURCES += dosbox/cdrom_image.cpp dosbox/dbopl.cpp dosbox/nukedopl.cpp dosbox/vid_cga_comp.c
@ -70,12 +72,20 @@ pcem_SOURCES += wx-sdl2-midi.c
endif
if CPU_I386
pcem_SOURCES += codegen_x86.c
pcem_SOURCES += codegen_backend_x86.c codegen_backend_x86_ops.c codegen_backend_x86_ops_fpu.c codegen_backend_x86_ops_sse.c codegen_backend_x86_uops.c
pcem_CFLAGS += -msse2
endif
if CPU_X86_64
pcem_SOURCES += codegen_x86-64.c
pcem_SOURCES += codegen_backend_x86-64.c codegen_backend_x86-64_ops.c codegen_backend_x86-64_ops_sse.c codegen_backend_x86-64_uops.c
endif
if CPU_ARM
pcem_SOURCES += codegen_backend_arm.c codegen_backend_arm_ops.c codegen_backend_arm_uops.c
endif
if CPU_ARM64
pcem_SOURCES += codegen_backend_arm64.c codegen_backend_arm64_imm.c codegen_backend_arm64_ops.c codegen_backend_arm64_uops.c
endif
if USE_NETWORKING
@ -114,10 +124,18 @@ pcem_LDADD += wx.res
endif
if !HAS_OFF64T
pcem_CFLAGS += -Doff64_t=off_t -Dfopen64=fopen -Dfseeko64=fseek -Dftello64=ftell
#pcem_CFLAGS += -Doff64_t=off_t -Dfopen64=fopen -Dfseeko64=fseek -Dftello64=ftell
endif
if RELEASE_BUILD
pcem_CFLAGS += -DRELEASE_BUILD
pcem_CXXFLAGS += -DRELEASE_BUILD
endif
pcem_CFLAGS += -mtune=cortex-a53
pcem_CXXFLAGS += -mtune=cortex-a53
#pcem_LDFLAGS = -flto -O3 -mtune=cortex-a15
# pcem_CFLAGS += -fprofile-use
# pcem_CXXFLAGS += -fprofile-use
# pcem_LDFLAGS = -fprofile-use

File diff suppressed because it is too large Load diff

View file

@ -6,25 +6,43 @@ WXVERSION = 31
WXINCLUDE = e:/MinGWget/include/wx/
CFLAGS = -O3 -march=i686 -fomit-frame-pointer -msse2 -mstackrealign -Werror -fno-strict-aliasing
CXXFLAGS = $(CFLAGS)
OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acc2036.o acc2168.o acc3221.o acer386sx.o ali1429.o amstrad.o cassette.o cbm_io.o cdrom-ioctl.o cdrom-image.o \
cmd640.o codegen.o codegen_ops.o codegen_timing_486.o codegen_timing_686.o codegen_timing_common.o codegen_timing_pentium.o codegen_timing_winchip.o codegen_x86.o compaq.o config.o cpu.o \
device.o dells200.o disc.o disc_fdi.o disc_img.o disc_sector.o dma.o esdi_at.o fdc.o fdc37c665.o fdd.o fdi2raw.o gameport.o hdd.o hdd_esdi.o hdd_file.o headland.o i430hx.o i430lx.o i430fx.o \
i430vx.o ide.o ide_atapi.o intel.o intel_flash.o io.o jim.o joystick_ch_flightstick_pro.o joystick_standard.o joystick_sw_pad.o joystick_tm_fcs.o keyboard.o keyboard_amstrad.o keyboard_at.o \
keyboard_olim24.o keyboard_pcjr.o keyboard_xt.o laserxt.o lpt.o lpt_dac.o lpt_dss.o mca.o mcr.o mem.o mem_bios.o mfm_at.o mfm_xebec.o model.o mouse.o mouse_msystems.o mouse_ps2.o \
mouse_serial.o neat.o nmi.o nvr.o nvr_tc8521.o olivetti_m24.o opti495.o paths.o pc.o pc87306.o pci.o pic.o piix.o pit.o ppi.o ps1.o ps2.o ps2_mca.o ps2_nvr.o pzx.o rom.o rtc.o rtc_tc8521.o \
scat.o scsi.o scsi_53c400.o scsi_aha1540.o scsi_cd.o scsi_hd.o scsi_zip.o serial.o sio.o sis496.o sl82c460.o sound.o sound_ad1848.o sound_adlib.o sound_adlibgold.o sound_audiopci.o sound_cms.o sound_dbopl.o \
sound_emu8k.o sound_gus.o sound_mpu401_uart.o sound_opl.o sound_pas16.o sound_ps1.o sound_pssj.o sound_resid.o \
sound_sb.o sound_sb_dsp.o sound_sn76489.o sound_speaker.o sound_ssi2001.o sound_wss.o \
sound_ym7128.o soundopenal.o t1000.o t3100e.o tandy_eeprom.o tandy_rom.o timer.o um8881f.o um8669f.o vid_ati_eeprom.o vid_ati_mach64.o vid_ati18800.o \
vid_ati28800.o vid_ati68860_ramdac.o vid_cga.o vid_cl5429.o vid_colorplus.o vid_compaq_cga.o vid_ega.o vid_et4000.o \
vid_et4000w32.o vid_et4000w32i.o vid_genius.o vid_hercules.o vid_ht216.o vid_icd2061.o vid_ics2595.o vid_incolor.o vid_mda.o \
OBJ = 386.o 386_common.o 386_dynarec.o 386_dynarec_ops.o 808x.o acc2036.o acer386sx.o ali1429.o amstrad.o \
cbm_io.o cdrom-ioctl.o cdrom-image.o cmd640.o codegen.o codegen_accumulate.o codegen_allocator.o \
codegen_backend.o codegen_backend_x86.o codegen_backend_x86_ops.o codegen_backend_x86_ops_fpu.o \
codegen_backend_x86_ops_sse.o codegen_backend_x86_uops.o codegen_ir.o codegen_ops.o \
codegen_ops_3dnow.o codegen_ops_branch.o codegen_ops_arith.o codegen_ops_fpu_arith.o \
codegen_ops_fpu_constant.o codegen_ops_fpu_loadstore.o codegen_ops_fpu_misc.o codegen_ops_helpers.o codegen_ops_jump.o \
codegen_ops_logic.o codegen_ops_misc.o codegen_ops_mmx_arith.o codegen_ops_mmx_cmp.o \
codegen_ops_mmx_loadstore.o codegen_ops_mmx_logic.o codegen_ops_mmx_pack.o codegen_ops_mmx_shift.o \
codegen_ops_mov.o codegen_ops_shift.o codegen_ops_stack.o codegen_reg.o codegen_timing_486.o \
codegen_timing_686.o codegen_timing_common.o codegen_timing_k6.o codegen_timing_pentium.o \
codegen_timing_winchip.o codegen_timing_winchip2.o compaq.o config.o cpu.o cpu_tables.o device.o \
dells200.o disc.o disc_fdi.o disc_img.o disc_sector.o dma.o esdi_at.o fdc.o fdc37c665.o fdd.o \
fdi2raw.o gameport.o hdd.o hdd_esdi.o hdd_file.o headland.o i430lx.o i430fx.o i430vx.o ide.o \
ide_atapi.o ide_sff8038i.o intel.o intel_flash.o io.o jim.o joystick_ch_flightstick_pro.o \
joystick_standard.o joystick_sw_pad.o joystick_tm_fcs.o keyboard.o keyboard_amstrad.o keyboard_at.o \
keyboard_olim24.o keyboard_pcjr.o keyboard_xt.o laserxt.o lpt.o lpt_dac.o lpt_dss.o mca.o mcr.o \
mem.o mem_bios.o mfm_at.o mfm_xebec.o model.o mouse.o mouse_msystems.o mouse_ps2.o mouse_serial.o \
mvp3.o neat.o nmi.o nvr.o nvr_tc8521.o olivetti_m24.o opti495.o paths.o pc.o pc87306.o pci.o pic.o \
piix.o pit.o ppi.o ps1.o ps2.o ps2_mca.o ps2_nvr.o rom.o rtc.o rtc_tc8521.o scat.o scsi.o \
scsi_53c400.o scsi_aha1540.o scsi_cd.o scsi_hd.o scsi_zip.o serial.o sio.o sis496.o sl82c460.o \
sound.o sound_ad1848.o sound_adlib.o sound_adlibgold.o sound_audiopci.o sound_cms.o sound_dbopl.o \
sound_emu8k.o sound_gus.o sound_mpu401_uart.o sound_opl.o sound_pas16.o sound_ps1.o sound_pssj.o \
sound_resid.o sound_sb.o sound_sb_dsp.o sound_sn76489.o sound_speaker.o sound_ssi2001.o sound_wss.o \
sound_ym7128.o soundopenal.o sst39sf010.o t1000.o t3100e.o tandy_eeprom.o tandy_rom.o timer.o um8881f.o um8669f.o \
vid_ati_eeprom.o vid_ati_mach64.o vid_ati18800.o vid_ati28800.o vid_ati68860_ramdac.o vid_cga.o \
vid_cl5429.o vid_colorplus.o vid_compaq_cga.o vid_ega.o vid_et4000.o vid_et4000w32.o \
vid_et4000w32i.o vid_genius.o vid_hercules.o vid_icd2061.o vid_ics2595.o vid_incolor.o vid_mda.o \
vid_olivetti_m24.o vid_oti037.c vid_oti067.o vid_paradise.o vid_pc1512.o vid_pc1640.o vid_pc200.o \
vid_pcjr.o vid_ps1_svga.o vid_s3.o vid_s3_virge.o vid_sdac_ramdac.o vid_sigma.o vid_stg_ramdac.o vid_svga.o \
vid_svga_render.o vid_t1000.o vid_t3100e.o vid_tandy.o vid_tandysl.o vid_tgui9440.o vid_tkd8001_ramdac.o vid_tvga.o vid_unk_ramdac.o \
vid_vga.o vid_voodoo.o vid_wy700.o video.o wd76c10.o x86seg.o x87.o xi8088.c xtide.o win-midi.o \
wx-main.o wx-config_sel.o wx-dialogbox.o wx-utils.o wx-app.o wx-sdl2-joystick.o wx-sdl2-mouse.o wx-sdl2-keyboard.o wx-sdl2-video.o \
wx-sdl2.o wx-config.o wx-deviceconfig.o wx-status.o wx-sdl2-status.o wx-resources.o wx-thread.o wx-common.o wx-sdl2-display-win.o \
wx-sdl2-video-renderer.o wx-sdl2-video-gl3.o wx-glslp-parser.o wx-shader_man.o wx-shaderconfig.o wx-joystickconfig.o wx-createdisc.o zenith.o wx.res
vid_svga_render.o vid_t1000.o vid_t3100e.o vid_tandy.o vid_tandysl.o vid_tgui9440.o \
vid_tkd8001_ramdac.o vid_tvga.o vid_unk_ramdac.o vid_vga.o vid_voodoo.o vid_wy700.o video.o \
vt82c586b.o w83877tf.o wd76c10.o x86seg.o x87.o xi8088.c xtide.o win-midi.o wx-main.o \
wx-config_sel.o wx-dialogbox.o wx-utils.o wx-app.o wx-sdl2-joystick.o wx-sdl2-mouse.o \
wx-sdl2-keyboard.o wx-sdl2-video.o wx-sdl2.o wx-config.o wx-deviceconfig.o wx-status.o \
wx-sdl2-status.o wx-resources.o wx-thread.o wx-common.o wx-sdl2-display-win.o \
wx-sdl2-video-renderer.o wx-sdl2-video-gl3.o wx-glslp-parser.o wx-shader_man.o wx-shaderconfig.o \
wx-joystickconfig.o wx-createdisc.o wx.res
DBOBJ = cdrom_image.o dbopl.o nukedopl.o vid_cga_comp.o
SIDOBJ = convolve.o convolve-sse.o envelope.o extfilt.o filter.o pot.o sid.o voice.o wave6581__ST.o wave6581_P_T.o wave6581_PS_.o wave6581_PST.o wave8580__ST.o wave8580_P_T.o wave8580_PS_.o wave8580_PST.o wave.o

View file

@ -55,8 +55,6 @@ void ali1429_write(uint16_t port, uint8_t val, void *priv)
ali1429_recalc();
break;
case 0x14:
shadowbios = val & 1;
shadowbios_write = val & 2;
ali1429_recalc();
break;
}

View file

@ -23,6 +23,7 @@
#include <stdlib.h>
#include "ibm.h"
#include "cpu.h"
#include "x86.h"
#include "device.h"
#include "pzx.h"

View file

@ -14,7 +14,6 @@ static ATAPI ioctl_atapi;
static uint32_t last_block = 0;
static uint32_t cdrom_capacity = 0;
static int ioctl_inited = 0;
static char ioctl_path[8];
static int tocvalid = 0;
static struct cdrom_tocentry toc[256];
static int toc_tracks;
@ -209,7 +208,7 @@ static int read_toc(int fd, struct cdrom_tocentry *btoc)
first_track = toc_hdr.cdth_trk0;
last_track = toc_hdr.cdth_trk1;
//pclog("read_toc: first_track=%i last_track=%i\n", first_track, last_track);
memset(btoc, 0, sizeof(btoc));
memset(btoc, 0, sizeof(struct cdrom_tocentry));
c = 0;
for (track = 0; track < 256; track++)
@ -233,8 +232,6 @@ static int read_toc(int fd, struct cdrom_tocentry *btoc)
static int ioctl_ready(void)
{
long size;
int temp;
struct cdrom_tochdr toc_hdr;
struct cdrom_tocentry toc_entry;
int err;
@ -266,7 +263,6 @@ static int ioctl_ready(void)
(toc_entry.cdte_addr.msf.frame != toc[toc_hdr.cdth_trk1].cdte_addr.msf.frame ) ||
!tocvalid)
{
int track;
ioctl_cd_state = CD_STOPPED;
tocvalid = read_toc(ioctl_fd, toc);
@ -306,8 +302,6 @@ static int ioctl_get_last_block(unsigned char starttrack, int msf, int maxlen, i
static int ioctl_medium_changed(void)
{
long size;
int temp;
struct cdrom_tochdr toc_hdr;
struct cdrom_tocentry toc_entry;
int err;
@ -338,15 +332,12 @@ static int ioctl_medium_changed(void)
static uint8_t ioctl_getcurrentsubchannel(uint8_t *b, int msf)
{
struct cdrom_subchnl sub;
uint32_t cdpos = ioctl_cd_pos;
int track = get_track_nr(cdpos);
uint32_t track_address = toc[track].cdte_addr.msf.frame +
(toc[track].cdte_addr.msf.second * 75) +
(toc[track].cdte_addr.msf.minute * 75 * 60);
long size;
int pos=0;
int err;
uint8_t ret;
//pclog("ioctl_getsubchannel: cdpos=%x track_address=%x track=%i\n", cdpos, track_address, track);
if (ioctl_cd_state == CD_PLAYING)
@ -460,7 +451,6 @@ static void ioctl_readsector_raw(uint8_t *b, int sector)
static int ioctl_readtoc(unsigned char *b, unsigned char starttrack, int msf, int maxlen, int single)
{
int len=4;
long size;
int c,d;
uint32_t temp;
uint32_t last_address = 0;
@ -644,7 +634,7 @@ static uint32_t ioctl_size()
static int ioctl_status()
{
if (!(ioctl_ready) && (cdrom_drive <= 0)) return CD_STATUS_EMPTY;
if (!ioctl_ready() && (cdrom_drive <= 0)) return CD_STATUS_EMPTY;
switch(ioctl_cd_state)
{
@ -653,6 +643,7 @@ static int ioctl_status()
case CD_PAUSED:
return CD_STATUS_PAUSED;
case CD_STOPPED:
default:
return CD_STATUS_STOPPED;
}
}

View file

@ -2,12 +2,63 @@
#include "x86_ops.h"
#include "mem.h"
#include "codegen.h"
#include "x86.h"
#include "386_common.h"
#include "codegen_accumulate.h"
#include "codegen_allocator.h"
#include "codegen_backend.h"
#include "codegen_ir.h"
#include "codegen_ops.h"
#include "codegen_ops_helpers.h"
#define MAX_INSTRUCTION_COUNT 50
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;
codeblock_t *codeblock;
uint16_t *codeblock_hash;
void (*codegen_timing_start)();
void (*codegen_timing_prefix)(uint8_t prefix, uint32_t fetchdat);
void (*codegen_timing_opcode)(uint8_t opcode, uint32_t fetchdat, int op_32);
void (*codegen_timing_opcode)(uint8_t opcode, uint32_t fetchdat, int op_32, uint32_t op_pc);
void (*codegen_timing_block_start)();
void (*codegen_timing_block_end)();
int (*codegen_timing_jump_cycles)();
void codegen_timing_set(codegen_timing_t *timing)
{
@ -16,6 +67,705 @@ void codegen_timing_set(codegen_timing_t *timing)
codegen_timing_opcode = timing->opcode;
codegen_timing_block_start = timing->block_start;
codegen_timing_block_end = timing->block_end;
codegen_timing_jump_cycles = timing->jump_cycles;
}
int codegen_in_recompile;
static int last_op_ssegs;
static x86seg *last_op_ea_seg;
static uint32_t last_op_32;
void codegen_generate_reset()
{
last_op_ssegs = -1;
last_op_ea_seg = NULL;
last_op_32 = -1;
has_ea = 0;
}
void codegen_check_seg_read(codeblock_t *block, ir_data_t *ir, x86seg *seg)
{
/*Segments always valid in real/V86 mode*/
if (!(cr0 & 1) || (cpu_state.eflags & VM_FLAG))
return;
/*CS and SS must always be valid*/
if (seg == &cpu_state.seg_cs || seg == &cpu_state.seg_ss)
return;
if (seg->checked)
return;
if (seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS))
return;
uop_CMP_IMM_JZ(ir, ireg_seg_base(seg), (uint32_t)-1, codegen_gpf_rout);
seg->checked = 1;
}
void codegen_check_seg_write(codeblock_t *block, ir_data_t *ir, x86seg *seg)
{
/*Segments always valid in real/V86 mode*/
if (!(cr0 & 1) || (cpu_state.eflags & VM_FLAG))
return;
/*CS and SS must always be valid*/
if (seg == &cpu_state.seg_cs || seg == &cpu_state.seg_ss)
return;
if (seg->checked)
return;
if (seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS))
return;
uop_CMP_IMM_JZ(ir, ireg_seg_base(seg), (uint32_t)-1, codegen_gpf_rout);
seg->checked = 1;
}
static x86seg *codegen_generate_ea_16_long(ir_data_t *ir, x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc)
{
uint32_t old_pc = (*op_pc) + 1;
// pclog("codegen - mod=%i rm=%i reg=%i fetchdat=%08x\n", cpu_mod, cpu_rm, cpu_reg, fetchdat);
if (!cpu_mod && cpu_rm == 6)
{
uint16_t addr = (fetchdat >> 8) & 0xffff;
uop_MOV_IMM(ir, IREG_eaaddr, addr);
(*op_pc) += 2;
}
else
{
int base_reg, index_reg, offset;
switch (cpu_rm & 7)
{
case 0: case 1: case 7:
base_reg = IREG_EBX;
break;
case 2: case 3: case 6:
base_reg = IREG_EBP;
break;
case 4:
base_reg = IREG_ESI;
break;
case 5:
base_reg = IREG_EDI;
break;
}
uop_MOV(ir, IREG_eaaddr, base_reg);
if (!(cpu_rm & 4))
{
if (!(cpu_rm & 1))
index_reg = IREG_ESI;
else
index_reg = IREG_EDI;
uop_ADD(ir, IREG_eaaddr, IREG_eaaddr, index_reg);
}
switch (cpu_mod)
{
case 1:
offset = (int)(int8_t)((fetchdat >> 8) & 0xff);
uop_ADD_IMM(ir, IREG_eaaddr, IREG_eaaddr, offset);
(*op_pc)++;
break;
case 2:
offset = (fetchdat >> 8) & 0xffff;
uop_ADD_IMM(ir, IREG_eaaddr, IREG_eaaddr, offset);
(*op_pc) += 2;
break;
}
uop_AND_IMM(ir, IREG_eaaddr, IREG_eaaddr, 0xffff);
if (mod1seg[cpu_rm] == &ss && !op_ssegs)
{
op_ea_seg = &cpu_state.seg_ss;
}
}
codegen_mark_code_present(ir->block, cs+old_pc, ((*op_pc)+1)-old_pc);
return op_ea_seg;
}
static x86seg *codegen_generate_ea_32_long(ir_data_t *ir, x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, int stack_offset)
{
codeblock_t *block = ir->block;
uint32_t old_pc = (*op_pc) + 1;
uint32_t new_eaaddr;
int extra_bytes = 0;
if (cpu_rm == 4)
{
uint8_t sib = fetchdat >> 8;
(*op_pc)++;
switch (cpu_mod)
{
case 0:
if ((sib & 7) == 5)
{
if (block->flags & CODEBLOCK_NO_IMMEDIATES)
{
LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_eaaddr, cs + (*op_pc) + 1);
extra_bytes = 1;
}
else
{
new_eaaddr = fastreadl(cs + (*op_pc) + 1);
uop_MOV_IMM(ir, IREG_eaaddr, new_eaaddr);
extra_bytes = 5;
}
(*op_pc) += 4;
}
else
{
uop_MOV(ir, IREG_eaaddr, sib & 7);
extra_bytes = 1;
}
break;
case 1:
new_eaaddr = (uint32_t)(int8_t)((fetchdat >> 16) & 0xff);
uop_MOV_IMM(ir, IREG_eaaddr, new_eaaddr);
uop_ADD(ir, IREG_eaaddr, IREG_eaaddr, sib & 7);
(*op_pc)++;
extra_bytes = 2;
break;
case 2:
if (block->flags & CODEBLOCK_NO_IMMEDIATES)
{
LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_eaaddr, cs + (*op_pc) + 1);
extra_bytes = 1;
}
else
{
new_eaaddr = fastreadl(cs + (*op_pc) + 1);
uop_MOV_IMM(ir, IREG_eaaddr, new_eaaddr);
extra_bytes = 5;
}
(*op_pc) += 4;
uop_ADD(ir, IREG_eaaddr, IREG_eaaddr, sib & 7);
break;
}
if (stack_offset && (sib & 7) == 4 && (cpu_mod || (sib & 7) != 5)) /*ESP*/
{
uop_ADD_IMM(ir, IREG_eaaddr, IREG_eaaddr, stack_offset);
// addbyte(0x05);
// addlong(stack_offset);
}
if (((sib & 7) == 4 || (cpu_mod && (sib & 7) == 5)) && !op_ssegs)
op_ea_seg = &cpu_state.seg_ss;
if (((sib >> 3) & 7) != 4)
{
switch (sib >> 6)
{
case 0:
uop_ADD(ir, IREG_eaaddr, IREG_eaaddr, (sib >> 3) & 7);
break;
case 1:
uop_ADD_LSHIFT(ir, IREG_eaaddr, IREG_eaaddr, (sib >> 3) & 7, 1);
break;
case 2:
uop_ADD_LSHIFT(ir, IREG_eaaddr, IREG_eaaddr, (sib >> 3) & 7, 2);
break;
case 3:
uop_ADD_LSHIFT(ir, IREG_eaaddr, IREG_eaaddr, (sib >> 3) & 7, 3);
break;
}
}
}
else
{
if (!cpu_mod && cpu_rm == 5)
{
if (block->flags & CODEBLOCK_NO_IMMEDIATES)
{
LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_eaaddr, cs + (*op_pc) + 1);
}
else
{
new_eaaddr = fastreadl(cs + (*op_pc) + 1);
uop_MOV_IMM(ir, IREG_eaaddr, new_eaaddr);
extra_bytes = 4;
}
(*op_pc) += 4;
}
else
{
uop_MOV(ir, IREG_eaaddr, cpu_rm);
if (cpu_mod)
{
if (cpu_rm == 5 && !op_ssegs)
op_ea_seg = &cpu_state.seg_ss;
if (cpu_mod == 1)
{
uop_ADD_IMM(ir, IREG_eaaddr, IREG_eaaddr, (uint32_t)(int8_t)(fetchdat >> 8));
(*op_pc)++;
extra_bytes = 1;
}
else
{
if (block->flags & CODEBLOCK_NO_IMMEDIATES)
{
LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_temp0, cs + (*op_pc) + 1);
uop_ADD(ir, IREG_eaaddr, IREG_eaaddr, IREG_temp0);
}
else
{
new_eaaddr = fastreadl(cs + (*op_pc) + 1);
uop_ADD_IMM(ir, IREG_eaaddr, IREG_eaaddr, new_eaaddr);
extra_bytes = 4;
}
(*op_pc) += 4;
}
}
}
}
if (extra_bytes)
codegen_mark_code_present(ir->block, cs+old_pc, extra_bytes);
return op_ea_seg;
}
x86seg *codegen_generate_ea(ir_data_t *ir, x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, uint32_t op_32, int stack_offset)
{
cpu_mod = (fetchdat >> 6) & 3;
cpu_reg = (fetchdat >> 3) & 7;
cpu_rm = fetchdat & 7;
if ((fetchdat & 0xc0) == 0xc0)
return NULL;
if (op_32 & 0x200)
return codegen_generate_ea_32_long(ir, op_ea_seg, fetchdat, op_ssegs, op_pc, stack_offset);
return codegen_generate_ea_16_long(ir, op_ea_seg, fetchdat, op_ssegs, op_pc);
}
static uint8_t 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*/
};
static uint8_t opcode_0f_modrm[256] =
{
1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, /*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*/
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /*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_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_pc, uint32_t old_pc)
{
codeblock_t *block = &codeblock[block_current];
ir_data_t *ir = codegen_get_ir_data();
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;
uint32_t recomp_opcode_mask = 0x1ff;
uint32_t op_32 = use32;
int over = 0;
int test_modrm = 1;
int pc_off = 0;
uint32_t next_pc = 0;
#ifdef DEBUG_EXTRA
uint8_t last_prefix = 0;
#endif
op_ea_seg = &cpu_state.seg_ds;
op_ssegs = 0;
codegen_timing_start();
while (!over)
{
switch (opcode)
{
case 0x0f:
#ifdef DEBUG_EXTRA
last_prefix = 0x0f;
#endif
op_table = x86_dynarec_opcodes_0f;
recomp_op_table = recomp_opcodes_0f;
over = 1;
break;
case 0x26: /*ES:*/
op_ea_seg = &cpu_state.seg_es;
op_ssegs = 1;
break;
case 0x2e: /*CS:*/
op_ea_seg = &cpu_state.seg_cs;
op_ssegs = 1;
break;
case 0x36: /*SS:*/
op_ea_seg = &cpu_state.seg_ss;
op_ssegs = 1;
break;
case 0x3e: /*DS:*/
op_ea_seg = &cpu_state.seg_ds;
op_ssegs = 1;
break;
case 0x64: /*FS:*/
op_ea_seg = &cpu_state.seg_fs;
op_ssegs = 1;
break;
case 0x65: /*GS:*/
op_ea_seg = &cpu_state.seg_gs;
op_ssegs = 1;
break;
case 0x66: /*Data size select*/
op_32 = ((use32 & 0x100) ^ 0x100) | (op_32 & 0x200);
break;
case 0x67: /*Address size select*/
op_32 = ((use32 & 0x200) ^ 0x200) | (op_32 & 0x100);
break;
case 0xd8:
#ifdef DEBUG_EXTRA
last_prefix = 0xd8;
#endif
op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_d8_a32 : x86_dynarec_opcodes_d8_a16;
recomp_op_table = recomp_opcodes_d8;
opcode_shift = 3;
opcode_mask = 0x1f;
over = 1;
pc_off = -1;
test_modrm = 0;
block->flags |= CODEBLOCK_HAS_FPU;
break;
case 0xd9:
#ifdef DEBUG_EXTRA
last_prefix = 0xd9;
#endif
op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_d9_a32 : x86_dynarec_opcodes_d9_a16;
recomp_op_table = recomp_opcodes_d9;
opcode_mask = 0xff;
over = 1;
pc_off = -1;
test_modrm = 0;
block->flags |= CODEBLOCK_HAS_FPU;
break;
case 0xda:
#ifdef DEBUG_EXTRA
last_prefix = 0xda;
#endif
op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_da_a32 : x86_dynarec_opcodes_da_a16;
recomp_op_table = recomp_opcodes_da;
opcode_mask = 0xff;
over = 1;
pc_off = -1;
test_modrm = 0;
block->flags |= CODEBLOCK_HAS_FPU;
break;
case 0xdb:
#ifdef DEBUG_EXTRA
last_prefix = 0xdb;
#endif
op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_db_a32 : x86_dynarec_opcodes_db_a16;
recomp_op_table = recomp_opcodes_db;
opcode_mask = 0xff;
over = 1;
pc_off = -1;
test_modrm = 0;
block->flags |= CODEBLOCK_HAS_FPU;
break;
case 0xdc:
#ifdef DEBUG_EXTRA
last_prefix = 0xdc;
#endif
op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dc_a32 : x86_dynarec_opcodes_dc_a16;
recomp_op_table = recomp_opcodes_dc;
opcode_shift = 3;
opcode_mask = 0x1f;
over = 1;
pc_off = -1;
test_modrm = 0;
block->flags |= CODEBLOCK_HAS_FPU;
break;
case 0xdd:
#ifdef DEBUG_EXTRA
last_prefix = 0xdd;
#endif
op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_dd_a32 : x86_dynarec_opcodes_dd_a16;
recomp_op_table = recomp_opcodes_dd;
opcode_mask = 0xff;
over = 1;
pc_off = -1;
test_modrm = 0;
block->flags |= CODEBLOCK_HAS_FPU;
break;
case 0xde:
#ifdef DEBUG_EXTRA
last_prefix = 0xde;
#endif
op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_de_a32 : x86_dynarec_opcodes_de_a16;
recomp_op_table = recomp_opcodes_de;
opcode_mask = 0xff;
over = 1;
pc_off = -1;
test_modrm = 0;
block->flags |= CODEBLOCK_HAS_FPU;
break;
case 0xdf:
#ifdef DEBUG_EXTRA
last_prefix = 0xdf;
#endif
op_table = (op_32 & 0x200) ? x86_dynarec_opcodes_df_a32 : x86_dynarec_opcodes_df_a16;
recomp_op_table = recomp_opcodes_df;
opcode_mask = 0xff;
over = 1;
pc_off = -1;
test_modrm = 0;
block->flags |= CODEBLOCK_HAS_FPU;
break;
case 0xf0: /*LOCK*/
break;
case 0xf2: /*REPNE*/
#ifdef DEBUG_EXTRA
last_prefix = 0xf2;
#endif
op_table = x86_dynarec_opcodes_REPNE;
recomp_op_table = NULL;//recomp_opcodes_REPNE;
break;
case 0xf3: /*REPE*/
#ifdef DEBUG_EXTRA
last_prefix = 0xf3;
#endif
op_table = x86_dynarec_opcodes_REPE;
recomp_op_table = NULL;//recomp_opcodes_REPE;
break;
default:
goto generate_call;
}
fetchdat = fastreadl(cs + op_pc);
codegen_timing_prefix(opcode, fetchdat);
if (cpu_state.abrt)
return;
opcode = fetchdat & 0xff;
if (!pc_off)
fetchdat >>= 8;
op_pc++;
}
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_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)))
{
/*On some CPUs (eg K6), a jump/branch instruction may be able to pair with
subsequent instructions, so no cycles may have been deducted for it yet.
To prevent having zero cycle blocks (eg with a jump instruction pointing
to itself), apply the cycles that would be taken if this jump is taken,
then reverse it for subsequent instructions if the jump is not taken*/
int jump_cycles = codegen_timing_jump_cycles();
if (jump_cycles)
codegen_accumulate(ACCREG_cycles, -jump_cycles);
codegen_accumulate_flush(ir);
if (jump_cycles)
codegen_accumulate(ACCREG_cycles, jump_cycles);
}
if (op_table == x86_dynarec_opcodes_0f && opcode == 0x0f)
{
/*3DNow opcodes are stored after ModR/M, SIB and any offset*/
uint8_t modrm = fetchdat & 0xff;
uint8_t sib = (fetchdat >> 8) & 0xff;
uint32_t opcode_pc = op_pc + 1;
uint8_t opcode_3dnow;
if ((modrm & 0xc0) != 0xc0)
{
if (op_32 & 0x200)
{
if ((modrm & 7) == 4)
{
/* Has SIB*/
opcode_pc++;
if ((modrm & 0xc0) == 0x40)
opcode_pc++;
else if ((modrm & 0xc0) == 0x80)
opcode_pc += 4;
else if ((sib & 0x07) == 0x05)
opcode_pc += 4;
}
else
{
if ((modrm & 0xc0) == 0x40)
opcode_pc++;
else if ((modrm & 0xc0) == 0x80)
opcode_pc += 4;
else if ((modrm & 0xc7) == 0x05)
opcode_pc += 4;
}
}
else
{
if ((modrm & 0xc0) == 0x40)
opcode_pc++;
else if ((modrm & 0xc0) == 0x80)
opcode_pc += 2;
else if ((modrm & 0xc7) == 0x06)
opcode_pc += 2;
}
}
opcode_3dnow = fastreadb(cs + opcode_pc);
// pclog("recomp_opcodes_3DNOW[%02x]=%p\n", opcode, recomp_opcodes_3DNOW[opcode]);
if (recomp_opcodes_3DNOW[opcode_3dnow])
{
next_pc = opcode_pc + 1;
op_table = x86_dynarec_opcodes_3DNOW;
recomp_op_table = recomp_opcodes_3DNOW;
opcode = opcode_3dnow;
recomp_opcode_mask = 0xff;
opcode_mask = 0xff;
}
}
codegen_mark_code_present(block, cs+old_pc, (op_pc - old_pc) - pc_off);
// pclog("%04x:%08x : %02x\n", CS, new_pc, opcode);
if (recomp_op_table && recomp_op_table[(opcode | op_32) & recomp_opcode_mask])
{
uint32_t new_pc = recomp_op_table[(opcode | op_32) & recomp_opcode_mask](block, ir, opcode, fetchdat, op_32, op_pc);
if (new_pc)
{
if (new_pc != -1)
uop_MOV_IMM(ir, IREG_pc, new_pc);
codegen_endpc = (cs + cpu_state.pc) + 8;
block->ins++;
if (block->ins >= MAX_INSTRUCTION_COUNT)
CPU_BLOCK_END();
return;
}
}
if ((op_table == x86_dynarec_opcodes_REPNE || op_table == x86_dynarec_opcodes_REPE) && !op_table[opcode | op_32])
{
op_table = x86_dynarec_opcodes;
recomp_op_table = recomp_opcodes;
}
op = op_table[((opcode >> opcode_shift) | op_32) & opcode_mask];
if (!test_modrm ||
(op_table == x86_dynarec_opcodes && opcode_modrm[opcode]) ||
(op_table == x86_dynarec_opcodes_0f && opcode_0f_modrm[opcode]) ||
(op_table == x86_dynarec_opcodes_3DNOW))
{
int stack_offset = 0;
if (op_table == x86_dynarec_opcodes && opcode == 0x8f) /*POP*/
stack_offset = (op_32 & 0x100) ? 4 : 2;
cpu_mod = (fetchdat >> 6) & 3;
cpu_reg = (fetchdat >> 3) & 7;
cpu_rm = fetchdat & 7;
uop_MOV_IMM(ir, IREG_rm_mod_reg, cpu_rm | (cpu_mod << 8) | (cpu_reg << 16));
op_pc += pc_off;
if (cpu_mod != 3 && !(op_32 & 0x200))
{
op_ea_seg = codegen_generate_ea_16_long(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc);
// has_ea = 1;
}
if (cpu_mod != 3 && (op_32 & 0x200))
{
op_ea_seg = codegen_generate_ea_32_long(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, stack_offset);
// has_ea = 1;
}
// op_ea_seg = codegen_generate_ea_32_long(op_ea_seg, fetchdat, op_ssegs, &op_pc, stack_offset);
op_pc -= pc_off;
}
#ifdef DEBUG_EXTRA
uop_LOG_INSTR(ir, opcode | (last_prefix << 8));
#endif
codegen_accumulate_flush(ir);
if (op_table == x86_dynarec_opcodes_3DNOW)
uop_MOV_IMM(ir, IREG_pc, next_pc);
else
uop_MOV_IMM(ir, IREG_pc, op_pc+pc_off);
uop_MOV_IMM(ir, IREG_oldpc, old_pc);
if (op_32 != last_op_32)
uop_MOV_IMM(ir, IREG_op32, op_32);
if (op_ea_seg != last_op_ea_seg)
uop_MOV_PTR(ir, IREG_ea_seg, (void *)op_ea_seg);
if (op_ssegs != last_op_ssegs)
uop_MOV_IMM(ir, IREG_ssegs, op_ssegs);
uop_LOAD_FUNC_ARG_IMM(ir, 0, fetchdat);
uop_CALL_INSTRUCTION_FUNC(ir, op);
codegen_mark_code_present(block, cs+cpu_state.pc, 8);
last_op_32 = op_32;
last_op_ea_seg = op_ea_seg;
last_op_ssegs = op_ssegs;
//codegen_block_ins++;
block->ins++;
if (block->ins >= MAX_INSTRUCTION_COUNT)
CPU_BLOCK_END();
codegen_endpc = (cs + cpu_state.pc) + 8;
// if (has_ea)
// fatal("Has EA\n");
}

View file

@ -4,14 +4,6 @@
#include "mem.h"
#include "x86_ops.h"
#ifdef __amd64__
#include "codegen_x86-64.h"
#elif defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined WIN32 || defined _WIN32 || defined _WIN32
#include "codegen_x86.h"
#else
#error Dynamic recompiler not implemented on your platform
#endif
/*Handling self-modifying code (of which there is a lot on x86) :
PCem tracks a 'dirty mask' for each physical page, in which each bit
@ -39,60 +31,88 @@
typedef struct codeblock_t
{
uint32_t pc;
uint32_t _cs;
uint32_t phys, phys_2;
uint16_t status;
uint16_t flags;
uint8_t ins;
uint8_t TOP;
/*Pointers for codeblock tree, used to search for blocks when hash lookup
fails.*/
uint16_t parent, left, right;
uint8_t *data;
uint64_t page_mask, page_mask2;
uint64_t *dirty_mask, *dirty_mask2;
uint64_t cmp;
/*Previous and next pointers, for the codeblock list associated with
each physical page. Two sets of pointers, as a codeblock can be
present in two pages.*/
struct codeblock_t *prev, *next;
struct codeblock_t *prev_2, *next_2;
/*Pointers for codeblock tree, used to search for blocks when hash lookup
fails.*/
struct codeblock_t *parent, *left, *right;
int pnt;
int ins;
int was_recompiled;
int TOP;
uint16_t prev, next;
uint16_t prev_2, next_2;
uint32_t pc;
uint32_t _cs;
uint32_t endpc;
uint32_t phys, phys_2;
uint32_t status;
uint32_t flags;
uint8_t data[2048];
/*First mem_block_t used by this block. Any subsequent mem_block_ts
will be in the list starting at head_mem_block->next.*/
struct mem_block_t *head_mem_block;
} codeblock_t;
extern codeblock_t *codeblock;
extern uint16_t *codeblock_hash;
extern uint8_t *block_write_data;
/*Code block uses FPU*/
#define CODEBLOCK_HAS_FPU 1
/*Code block is always entered with the same FPU top-of-stack*/
#define CODEBLOCK_STATIC_TOP 2
/*Code block has been compiled*/
#define CODEBLOCK_WAS_RECOMPILED 4
/*Code block is in free list and is not valid*/
#define CODEBLOCK_IN_FREE_LIST 8
/*Code block spans two pages, page_mask2 and dirty_mask2 are valid*/
#define CODEBLOCK_HAS_PAGE2 0x10
/*Code block is using a byte mask for code present and dirty*/
#define CODEBLOCK_BYTE_MASK 0x20
/*Code block is in dirty list*/
#define CODEBLOCK_IN_DIRTY_LIST 0x40
/*Code block is not inlining immediate parameters, parameters must be fetched from memory*/
#define CODEBLOCK_NO_IMMEDIATES 0x80
#define BLOCK_PC_INVALID 0xffffffff
#define BLOCK_INVALID 0
static inline int get_block_nr(codeblock_t *block)
{
return ((uintptr_t)block - (uintptr_t)codeblock) / sizeof(codeblock_t);
}
static inline codeblock_t *codeblock_tree_find(uint32_t phys, uint32_t _cs)
{
codeblock_t *block = pages[phys >> 12].head;
codeblock_t *block;
uint64_t a = _cs | ((uint64_t)phys << 32);
if (!pages[phys >> 12].head)
return NULL;
block = &codeblock[pages[phys >> 12].head];
while (block)
{
if (a == block->cmp)
uint64_t block_cmp = block->_cs | ((uint64_t)block->phys << 32);
if (a == block_cmp)
{
if (!((block->status ^ cpu_cur_status) & CPU_STATUS_FLAGS) &&
((block->status & cpu_cur_status & CPU_STATUS_MASK) == (cpu_cur_status & CPU_STATUS_MASK)))
break;
}
if (a < block->cmp)
block = block->left;
if (a < block_cmp)
block = block->left ? &codeblock[block->left] : NULL;
else
block = block->right;
block = block->right ? &codeblock[block->right] : NULL;
}
return block;
@ -100,75 +120,87 @@ static inline codeblock_t *codeblock_tree_find(uint32_t phys, uint32_t _cs)
static inline void codeblock_tree_add(codeblock_t *new_block)
{
codeblock_t *block = pages[new_block->phys >> 12].head;
codeblock_t *block = &codeblock[pages[new_block->phys >> 12].head];
uint64_t a = new_block->_cs | ((uint64_t)new_block->phys << 32);
new_block->cmp = a;
if (!block)
if (!pages[new_block->phys >> 12].head)
{
pages[new_block->phys >> 12].head = new_block;
new_block->parent = new_block->left = new_block->right = NULL;
pages[new_block->phys >> 12].head = get_block_nr(new_block);
new_block->parent = new_block->left = new_block->right = BLOCK_INVALID;
}
else
{
codeblock_t *old_block = NULL;
uint64_t old_block_cmp = 0;
while (block)
{
old_block = block;
if (a < old_block->cmp)
block = block->left;
old_block_cmp = old_block->_cs | ((uint64_t)old_block->phys << 32);
if (a < old_block_cmp)
block = block->left ? &codeblock[block->left] : NULL;
else
block = block->right;
block = block->right ? &codeblock[block->right] : NULL;
}
if (a < old_block->cmp)
old_block->left = new_block;
if (a < old_block_cmp)
old_block->left = get_block_nr(new_block);
else
old_block->right = new_block;
old_block->right = get_block_nr(new_block);
new_block->parent = old_block;
new_block->left = new_block->right = NULL;
new_block->parent = get_block_nr(old_block);
new_block->left = new_block->right = BLOCK_INVALID;
}
}
static inline void codeblock_tree_delete(codeblock_t *block)
{
codeblock_t *parent = block->parent;
uint16_t parent_nr = block->parent;
codeblock_t *parent;
if (block->parent)
parent = &codeblock[block->parent];
else
parent = NULL;
if (!block->left && !block->right)
{
/*Easy case - remove from parent*/
if (!parent)
pages[block->phys >> 12].head = NULL;
pages[block->phys >> 12].head = BLOCK_INVALID;
else
{
if (parent->left == block)
parent->left = NULL;
if (parent->right == block)
parent->right = NULL;
uint16_t block_nr = get_block_nr(block);
if (parent->left == block_nr)
parent->left = BLOCK_INVALID;
if (parent->right == block_nr)
parent->right = BLOCK_INVALID;
}
return;
}
else if (!block->left)
{
/*Only right node*/
if (!parent)
if (!parent_nr)
{
pages[block->phys >> 12].head = block->right;
pages[block->phys >> 12].head->parent = NULL;
codeblock[pages[block->phys >> 12].head].parent = BLOCK_INVALID;
}
else
{
if (parent->left == block)
uint16_t block_nr = get_block_nr(block);
if (parent->left == block_nr)
{
parent->left = block->right;
parent->left->parent = parent;
codeblock[parent->left].parent = parent_nr;
}
if (parent->right == block)
if (parent->right == block_nr)
{
parent->right = block->right;
parent->right->parent = parent;
codeblock[parent->right].parent = parent_nr;
}
}
return;
@ -176,22 +208,24 @@ static inline void codeblock_tree_delete(codeblock_t *block)
else if (!block->right)
{
/*Only left node*/
if (!parent)
if (!parent_nr)
{
pages[block->phys >> 12].head = block->left;
pages[block->phys >> 12].head->parent = NULL;
codeblock[pages[block->phys >> 12].head].parent = BLOCK_INVALID;
}
else
{
if (parent->left == block)
uint16_t block_nr = get_block_nr(block);
if (parent->left == block_nr)
{
parent->left = block->left;
parent->left->parent = parent;
codeblock[parent->left].parent = parent_nr;
}
if (parent->right == block)
if (parent->right == block_nr)
{
parent->right = block->left;
parent->right->parent = parent;
codeblock[parent->right].parent = parent_nr;
}
}
return;
@ -199,75 +233,109 @@ static inline void codeblock_tree_delete(codeblock_t *block)
else
{
/*Difficult case - node has two children. Walk right child to find lowest node*/
codeblock_t *lowest = block->right, *highest;
codeblock_t *lowest = &codeblock[block->right], *highest;
codeblock_t *old_parent;
uint16_t lowest_nr;
while (lowest->left)
lowest = lowest->left;
old_parent = lowest->parent;
lowest = &codeblock[lowest->left];
lowest_nr = get_block_nr(lowest);
old_parent = &codeblock[lowest->parent];
/*Replace deleted node with lowest node*/
if (!parent)
pages[block->phys >> 12].head = lowest;
if (!parent_nr)
pages[block->phys >> 12].head = lowest_nr;
else
{
if (parent->left == block)
parent->left = lowest;
if (parent->right == block)
parent->right = lowest;
uint16_t block_nr = get_block_nr(block);
if (parent->left == block_nr)
parent->left = lowest_nr;
if (parent->right == block_nr)
parent->right = lowest_nr;
}
lowest->parent = parent;
lowest->parent = parent_nr;
lowest->left = block->left;
if (lowest->left)
lowest->left->parent = lowest;
codeblock[lowest->left].parent = lowest_nr;
old_parent->left = NULL;
old_parent->left = BLOCK_INVALID;
highest = lowest->right;
if (!highest)
highest = &codeblock[lowest->right];
if (!lowest->right)
{
if (lowest != block->right)
if (lowest_nr != block->right)
{
lowest->right = block->right;
block->right->parent = lowest;
codeblock[block->right].parent = lowest_nr;
}
return;
}
while (highest->right)
highest = highest->right;
highest = &codeblock[highest->right];
if (block->right && block->right != lowest)
if (block->right && block->right != lowest_nr)
{
highest->right = block->right;
block->right->parent = highest;
codeblock[block->right].parent = get_block_nr(highest);
}
}
}
#define PAGE_MASK_INDEX_MASK 3
#define PAGE_MASK_INDEX_SHIFT 10
#define PAGE_MASK_MASK 63
#define PAGE_MASK_SHIFT 4
#define PAGE_MASK_SHIFT 6
extern codeblock_t *codeblock;
void codegen_mark_code_present_multibyte(codeblock_t *block, uint32_t start_pc, int len);
extern codeblock_t **codeblock_hash;
static inline void codegen_mark_code_present(codeblock_t *block, uint32_t start_pc, int len)
{
if (len == 1)
{
if (block->flags & CODEBLOCK_BYTE_MASK)
{
if (!((start_pc ^ block->pc) & ~0x3f)) /*Starts in second page*/
block->page_mask |= ((uint64_t)1 << (start_pc & PAGE_MASK_MASK));
else
block->page_mask2 |= ((uint64_t)1 << (start_pc & PAGE_MASK_MASK));
}
else
{
if (!((start_pc ^ block->pc) & ~0xfff)) /*Starts in second page*/
block->page_mask |= ((uint64_t)1 << ((start_pc >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK));
else
block->page_mask2 |= ((uint64_t)1 << ((start_pc >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK));
}
}
else
codegen_mark_code_present_multibyte(block, start_pc, len);
}
void codegen_init();
void codegen_close();
void codegen_reset();
void codegen_block_init(uint32_t phys_addr);
void codegen_block_remove();
void codegen_block_start_recompile(codeblock_t *block);
void codegen_block_end_recompile(codeblock_t *block);
void codegen_block_end();
void codegen_delete_block(codeblock_t *block);
void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_pc, uint32_t old_pc);
void codegen_generate_seg_restore();
void codegen_set_op32();
void codegen_flush();
void codegen_check_flush(struct page_t *page, uint64_t mask, uint32_t phys_addr);
struct ir_data_t;
x86seg *codegen_generate_ea(struct ir_data_t *ir, x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, uint32_t op_32, int stack_offset);
void codegen_check_seg_read(codeblock_t *block, struct ir_data_t *ir, x86seg *seg);
void codegen_check_seg_write(codeblock_t *block, struct ir_data_t *ir, x86seg *seg);
int codegen_purge_purgable_list();
/*Delete a random code block to free memory. This is obviously quite expensive, and
will only be called when the allocator is out of memory*/
void codegen_delete_random_block(int required_mem_block);
extern int cpu_block_end;
extern uint32_t codegen_endpc;
@ -286,23 +354,27 @@ extern int codegen_block_cycles;
extern void (*codegen_timing_start)();
extern void (*codegen_timing_prefix)(uint8_t prefix, uint32_t fetchdat);
extern void (*codegen_timing_opcode)(uint8_t opcode, uint32_t fetchdat, int op_32);
extern void (*codegen_timing_opcode)(uint8_t opcode, uint32_t fetchdat, int op_32, uint32_t op_pc);
extern void (*codegen_timing_block_start)();
extern void (*codegen_timing_block_end)();
extern int (*codegen_timing_jump_cycles)();
typedef struct codegen_timing_t
{
void (*start)();
void (*prefix)(uint8_t prefix, uint32_t fetchdat);
void (*opcode)(uint8_t opcode, uint32_t fetchdat, int op_32);
void (*opcode)(uint8_t opcode, uint32_t fetchdat, int op_32, uint32_t op_pc);
void (*block_start)();
void (*block_end)();
int (*jump_cycles)();
} codegen_timing_t;
extern codegen_timing_t codegen_timing_pentium;
extern codegen_timing_t codegen_timing_686;
extern codegen_timing_t codegen_timing_486;
extern codegen_timing_t codegen_timing_winchip;
extern codegen_timing_t codegen_timing_winchip2;
extern codegen_timing_t codegen_timing_k6;
void codegen_timing_set(codegen_timing_t *timing);
@ -311,45 +383,6 @@ extern int block_pos;
#define CPU_BLOCK_END() cpu_block_end = 1
static inline void addbyte(uint8_t val)
{
codeblock[block_current].data[block_pos++] = val;
if (block_pos >= BLOCK_MAX)
{
CPU_BLOCK_END();
}
}
static inline void addword(uint16_t val)
{
*(uint16_t *)(void *)&codeblock[block_current].data[block_pos] = val;
block_pos += 2;
if (block_pos >= BLOCK_MAX)
{
CPU_BLOCK_END();
}
}
static inline void addlong(uint32_t val)
{
*(uint32_t *)&codeblock[block_current].data[block_pos] = val;
block_pos += 4;
if (block_pos >= BLOCK_MAX)
{
CPU_BLOCK_END();
}
}
static inline void addquad(uint64_t val)
{
*(uint64_t *)&codeblock[block_current].data[block_pos] = val;
block_pos += 8;
if (block_pos >= BLOCK_MAX)
{
CPU_BLOCK_END();
}
}
/*Current physical page of block being recompiled. -1 if no recompilation taking place */
extern uint32_t recomp_page;
@ -369,4 +402,13 @@ extern int codegen_reg_loaded[8];
extern int codegen_in_recompile;
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
extern uint32_t instr_counts[256*256];
#endif
#endif

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();

126
src/codegen_allocator.c Normal file
View file

@ -0,0 +1,126 @@
#if defined(__linux__) || defined(__APPLE__)
#include <sys/mman.h>
#include <unistd.h>
#endif
#if defined WIN32 || defined _WIN32 || defined _WIN32
#include <windows.h>
#endif
#include "ibm.h"
#include "codegen.h"
#include "codegen_allocator.h"
typedef struct mem_block_t
{
uint32_t offset; /*Offset into mem_block_alloc*/
uint32_t next;
uint16_t code_block;
} mem_block_t;
static mem_block_t mem_blocks[MEM_BLOCK_NR];
static uint32_t mem_block_free_list;
static uint8_t *mem_block_alloc = NULL;
int codegen_allocator_usage = 0;
void codegen_allocator_init()
{
int c;
#if defined WIN32 || defined _WIN32 || defined _WIN32
mem_block_alloc = VirtualAlloc(NULL, MEM_BLOCK_NR * MEM_BLOCK_SIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
#else
mem_block_alloc = mmap(0, MEM_BLOCK_NR * MEM_BLOCK_SIZE, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_PRIVATE, 0, 0);
#endif
for (c = 0; c < MEM_BLOCK_NR; c++)
{
mem_blocks[c].offset = c * MEM_BLOCK_SIZE;
mem_blocks[c].code_block = BLOCK_INVALID;
if (c < MEM_BLOCK_NR-1)
mem_blocks[c].next = c+2;
else
mem_blocks[c].next = 0;
}
mem_block_free_list = 1;
}
mem_block_t *codegen_allocator_allocate(mem_block_t *parent, int code_block)
{
mem_block_t *block;
uint32_t block_nr;
while (!mem_block_free_list)
{
/*Pick a random memory block and free the owning code block*/
block_nr = rand() & MEM_BLOCK_MASK;
block = &mem_blocks[block_nr];
if (block->code_block && block->code_block != code_block)
codegen_delete_block(&codeblock[block->code_block]);
}
// fatal("codegen_allocator_allocate: free list empty!\n");
/*Remove from free list*/
block_nr = mem_block_free_list;
block = &mem_blocks[block_nr-1];
mem_block_free_list = block->next;
block->code_block = code_block;
if (parent)
{
/*Add to parent list*/
block->next = parent->next;
parent->next = block_nr;
}
else
block->next = 0;
codegen_allocator_usage++;
/* if (parent)
pclog("codegen_allocator_allocate with parent: %p %i %i %p\n", block, block_nr, codegen_allocator_usage, parent);
else
pclog("codegen_allocator_allocate: %p %i %i\n", block, block_nr, codegen_allocator_usage);*/
return block;
}
void codegen_allocator_free(mem_block_t *block)
{
int block_nr = (((uintptr_t)block - (uintptr_t)mem_blocks) / sizeof(mem_block_t)) + 1;
// pclog("codegen_allocator_free: %p %i %i %i\n", block, block_nr, codegen_allocator_usage, block->next);
while (1)
{
int next_block_nr = block->next;
// pclog(" free next=%i\n", next_block_nr);
codegen_allocator_usage--;
block->next = mem_block_free_list;
block->code_block = BLOCK_INVALID;
mem_block_free_list = block_nr;
block_nr = next_block_nr;
if (block_nr)
block = &mem_blocks[block_nr - 1];
else
break;
}
}
uint8_t *codeblock_allocator_get_ptr(mem_block_t *block)
{
return &mem_block_alloc[block->offset];
}
void codegen_allocator_clean_blocks(struct mem_block_t *block)
{
#if defined __ARM_EABI__ || defined __aarch64__
while (1)
{
__clear_cache(&mem_block_alloc[block->offset], &mem_block_alloc[block->offset + MEM_BLOCK_SIZE]);
if (block->next)
block = &mem_blocks[block->next - 1];
else
break;
}
#endif
}

39
src/codegen_allocator.h Normal file
View file

@ -0,0 +1,39 @@
#ifndef _CODEGEN_ALLOCATOR_H_
#define _CODEGEN_ALLOCATOR_H_
/*The allocator handles all allocation of executable memory. Since the two-pass
recompiler design makes applying hard limits to codeblock size difficult, the
allocator allows memory to be provided as and when required.
The allocator provides a block size of a little under 1 kB (slightly lower to
limit cache aliasing). Each generated codeblock is allocated one block by default,
and will allocate additional block(s) once the existing memory is sorted. Blocks
are chained together by jump instructions.
Due to the chaining, the total memory size is limited by the range of a jump
instruction. ARMv7 is restricted to +/- 32 MB, ARMv8 to +/- 128 MB, x86 to
+/- 2GB. As a result, total memory size is limited to 32 MB on ARMv7*/
#ifdef __ARM_EABI__
#define MEM_BLOCK_NR 32768
#else
#define MEM_BLOCK_NR 131072
#endif
#define MEM_BLOCK_MASK (MEM_BLOCK_NR-1)
#define MEM_BLOCK_SIZE 0x3c0
void codegen_allocator_init();
/*Allocate a mem_block_t, and the associated backing memory.
If parent is non-NULL, then the new block will be added to the list in
parent->next*/
struct mem_block_t *codegen_allocator_allocate(struct mem_block_t *parent, int code_block);
/*Free a mem_block_t, and any subsequent blocks in the list at block->next*/
void codegen_allocator_free(struct mem_block_t *block);
/*Get a pointer to the backing memory associated with block*/
uint8_t *codeblock_allocator_get_ptr(struct mem_block_t *block);
/*Cache clean memory block list*/
void codegen_allocator_clean_blocks(struct mem_block_t *block);
extern int codegen_allocator_usage;
#endif

889
src/codegen_backend.c Normal file
View file

@ -0,0 +1,889 @@
#include <stdlib.h>
#include "ibm.h"
#include "cpu.h"
#include "x86.h"
#include "x86_flags.h"
#include "x86_ops.h"
#include "x87.h"
#include "mem.h"
#include "386_common.h"
#include "codegen.h"
#include "codegen_accumulate.h"
#include "codegen_allocator.h"
#include "codegen_backend.h"
#include "codegen_ir.h"
#include "codegen_reg.h"
uint8_t *block_write_data = NULL;
int codegen_flat_ds, codegen_flat_ss;
int mmx_ebx_ecx_loaded;
int codegen_flags_changed = 0;
int codegen_fpu_entered = 0;
int codegen_mmx_entered = 0;
int codegen_fpu_loaded_iq[8];
x86seg *op_ea_seg;
int op_ssegs;
uint32_t op_old_pc;
uint32_t recomp_page = -1;
int block_current = 0;
static int block_num;
int block_pos;
int cpu_recomp_flushes, cpu_recomp_flushes_latched;
int cpu_recomp_evicted, cpu_recomp_evicted_latched;
int cpu_recomp_reuse, cpu_recomp_reuse_latched;
int cpu_recomp_removed, cpu_recomp_removed_latched;
uint32_t codegen_endpc;
int codegen_block_cycles;
static int codegen_block_ins;
static int codegen_block_full_ins;
static uint32_t last_op32;
static x86seg *last_ea_seg;
static int last_ssegs;
#ifdef DEBUG_EXTRA
uint32_t instr_counts[256*256];
#endif
static uint16_t block_free_list;
static void delete_block(codeblock_t *block);
static void delete_dirty_block(codeblock_t *block);
/*Temporary list of code blocks that have recently been evicted. This allows for
some historical state to be kept when a block is the target of self-modifying
code.
The size of this list is limited to DIRTY_LIST_MAX_SIZE blocks. When this is
exceeded the oldest entry will be moved to the free list.*/
static uint16_t block_dirty_list_head, block_dirty_list_tail;
static int dirty_list_size = 0;
#define DIRTY_LIST_MAX_SIZE 64
static void block_free_list_add(codeblock_t *block)
{
if (block->flags & CODEBLOCK_IN_DIRTY_LIST)
fatal("block_free_list_add: block=%p in dirty list\n", block);
if (block_free_list)
block->next = block_free_list;
else
block->next = 0;
block_free_list = get_block_nr(block);
block->flags = CODEBLOCK_IN_FREE_LIST;
// pclog("block_free_list_add: %p %p\n", block, block->next);
}
static void block_dirty_list_add(codeblock_t *block)
{
if (block->flags & CODEBLOCK_IN_DIRTY_LIST)
fatal("block_dirty_list_add: block=%p already in dirty list\n", block);
// pclog("block_dirty_list_add: block=%i size=%i %i head=%i tail=%i\n", get_block_nr(block), dirty_list_size, dirty_list_check_size(), block_dirty_list_head, block_dirty_list_tail);
if (block_dirty_list_head != BLOCK_INVALID)
{
codeblock_t *old_head = &codeblock[block_dirty_list_head];
block->next = block_dirty_list_head;
block->prev = BLOCK_INVALID;
block_dirty_list_head = old_head->prev = get_block_nr(block);
// pclog(" next=%p,%i prev=%i\n", old_head, block->next, old_head->prev);
}
else
{
/*List empty*/
block->prev = block->next = BLOCK_INVALID;
block_dirty_list_head = block_dirty_list_tail = get_block_nr(block);
}
block->flags |= CODEBLOCK_IN_DIRTY_LIST;
// pclog(" block_dirty_list_add: %p flags = %x\n", block, block->flags);
dirty_list_size++;
if (dirty_list_size > DIRTY_LIST_MAX_SIZE)
{
/*Evict oldest block to the free list*/
codeblock_t *evict_block = &codeblock[block_dirty_list_tail];
if (!(evict_block->flags & CODEBLOCK_IN_DIRTY_LIST))
fatal("block_dirty_list_add: evict_block=%p %x %x not in dirty list\n", evict_block, evict_block->phys, evict_block->flags);
if (!block_dirty_list_tail)
fatal("block_dirty_list_add - !block_dirty_list_tail\n");
if (evict_block->prev == BLOCK_INVALID)
fatal("block_dirty_list_add - evict_block->prev == BLOCK_INVALID\n");
block_dirty_list_tail = evict_block->prev;
codeblock[evict_block->prev].next = BLOCK_INVALID;
dirty_list_size--;
evict_block->flags &= ~CODEBLOCK_IN_DIRTY_LIST;
// pclog(" block_dirty_list_add: %p flags = %x\n", evict_block, evict_block->flags);
delete_dirty_block(evict_block);
}
// pclog("block_free_list_add: %p %p\n", block, block->next);
}
static void block_dirty_list_remove(codeblock_t *block)
{
codeblock_t *prev_block = &codeblock[block->prev];
codeblock_t *next_block = &codeblock[block->next];
if (!(block->flags & CODEBLOCK_IN_DIRTY_LIST))
fatal("block_dirty_list_remove: block=%p not in dirty list\n", block);
/*Is block head of list*/
if (block->prev == BLOCK_INVALID)
block_dirty_list_head = block->next;
else
prev_block->next = block->next;
/*Is block tail of list?*/
if (block->next == BLOCK_INVALID)
block_dirty_list_tail = block->prev;
else
next_block->prev = block->prev;
dirty_list_size--;
if (dirty_list_size < 0)
fatal("remove - dirty_list_size < 0!\n");
block->flags &= ~CODEBLOCK_IN_DIRTY_LIST;
// pclog(" block_dirty_list_remove: %p flags = %x\n", block, block->flags);
}
int codegen_purge_purgable_list()
{
if (purgable_page_list_head)
{
page_t *page = &pages[purgable_page_list_head];
if (page->code_present_mask & page->dirty_mask)
{
codegen_check_flush(page, page->dirty_mask, purgable_page_list_head << 12);
if (block_free_list)
return 1;
}
}
return 0;
}
static codeblock_t *block_free_list_get()
{
codeblock_t *block = NULL;
while (!block_free_list)
{
/*Free list is empty, check the dirty list*/
if (block_dirty_list_tail)
{
if (dirty_list_size <= 0)
fatal("get - dirty_list_size <= 0!\n");
/*Reuse oldest block*/
block = &codeblock[block_dirty_list_tail];
// pclog("block_free_list_get: remove block=%p size=%i\n", block, dirty_list_size);
block_dirty_list_tail = block->prev;
if (block->prev == BLOCK_INVALID)
block_dirty_list_head = BLOCK_INVALID;
else
codeblock[block->prev].next = BLOCK_INVALID;
dirty_list_size--;
block->flags &= ~CODEBLOCK_IN_DIRTY_LIST;
delete_dirty_block(block);
block_free_list = get_block_nr(block);
break;
}
/*Free list is empty - free up a block*/
if (!codegen_purge_purgable_list())
codegen_delete_random_block(0);
}
block = &codeblock[block_free_list];
block_free_list = block->next;
block->flags &= ~CODEBLOCK_IN_FREE_LIST;
// pclog(" block_free_list_get: %p flags = %x\n", block, block->flags);
block->next = 0;
// pclog("block_free_list_get: %p %p\n", block, block_free_list);
return block;
}
void codegen_init()
{
int c;
codegen_allocator_init();
codegen_backend_init();
block_free_list = 0;
for (c = 0; c < BLOCK_SIZE; c++)
block_free_list_add(&codeblock[c]);
block_dirty_list_head = block_dirty_list_tail = 0;
dirty_list_size = 0;
#ifdef DEBUG_EXTRA
memset(instr_counts, 0, sizeof(instr_counts));
#endif
}
void codegen_close()
{
#ifdef DEBUG_EXTRA
pclog("Instruction counts :\n");
while (1)
{
int c;
uint32_t highest_num = 0, highest_idx = 0;
for (c = 0; c < 256*256; c++)
{
if (instr_counts[c] > highest_num)
{
highest_num = instr_counts[c];
highest_idx = c;
}
}
if (!highest_num)
break;
instr_counts[highest_idx] = 0;
if (highest_idx > 256)
pclog(" %02x %02x = %u\n", highest_idx >> 8, highest_idx & 0xff, highest_num);
else
pclog(" %02x = %u\n", highest_idx & 0xff, highest_num);
}
#endif
}
void codegen_reset()
{
int c;
for (c = 1; c < BLOCK_SIZE; c++)
{
codeblock_t *block = &codeblock[c];
if (block->pc != BLOCK_PC_INVALID)
{
block->phys = 0;
block->phys_2 = 0;
delete_block(block);
}
}
memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t));
memset(codeblock_hash, 0, HASH_SIZE * sizeof(uint16_t));
mem_reset_page_blocks();
block_free_list = 0;
for (c = 0; c < BLOCK_SIZE; c++)
{
codeblock[c].pc = BLOCK_PC_INVALID;
block_free_list_add(&codeblock[c]);
}
}
void dump_block()
{
/* codeblock_t *block = pages[0x119000 >> 12].block;
pclog("dump_block:\n");
while (block)
{
uint32_t start_pc = (block->pc & 0xffc) | (block->phys & ~0xfff);
uint32_t end_pc = (block->endpc & 0xffc) | (block->phys & ~0xfff);
pclog(" %p : %08x-%08x %08x-%08x %p %p\n", (void *)block, start_pc, end_pc, block->pc, block->endpc, (void *)block->prev, (void *)block->next);
if (!block->pc)
fatal("Dead PC=0\n");
block = block->next;
}
pclog("dump_block done\n");*/
}
static void add_to_block_list(codeblock_t *block)
{
uint16_t block_prev_nr = pages[block->phys >> 12].block;
uint16_t block_nr = get_block_nr(block);
//pclog("Add to block list %p %08x %llx %x\n", block, block->phys, block->page_mask2, block->flags);
if (!block->page_mask)
fatal("add_to_block_list - mask = 0 %llx %llx\n", block->page_mask,block->page_mask2);
if (block_prev_nr)
{
block->next = block_prev_nr;
codeblock[block_prev_nr].prev = block_nr;
pages[block->phys >> 12].block = block_nr;
}
else
{
block->next = BLOCK_INVALID;
pages[block->phys >> 12].block = block_nr;
}
if (block->next)
{
if (codeblock[block->next].pc == BLOCK_PC_INVALID)
fatal("block->next->pc=BLOCK_PC_INVALID %p %p %x %x\n", (void *)&codeblock[block->next], (void *)codeblock, block_current, block_pos);
}
if (block->page_mask2)
{
block->flags |= CODEBLOCK_HAS_PAGE2;
block_prev_nr = pages[block->phys_2 >> 12].block_2;
if (block_prev_nr)
{
block->next_2 = block_prev_nr;
codeblock[block_prev_nr].prev_2 = block_nr;
pages[block->phys_2 >> 12].block_2 = block_nr;
}
else
{
block->next_2 = BLOCK_INVALID;
pages[block->phys_2 >> 12].block_2 = block_nr;
}
}
// pclog(" add_to_block_list: %p flags = %x\n", block, block->flags);
}
static void remove_from_block_list(codeblock_t *block, uint32_t pc)
{
if (!block->page_mask)
return;
if (block->flags & CODEBLOCK_IN_DIRTY_LIST)
fatal("remove_from_block_list: in dirty list\n");
if (block->prev)
{
codeblock[block->prev].next = block->next;
if (block->next)
codeblock[block->next].prev = block->prev;
}
else
{
pages[block->phys >> 12].block = block->next;
if (block->next)
codeblock[block->next].prev = BLOCK_INVALID;
else
mem_flush_write_page(block->phys, 0);
}
if (!(block->flags & CODEBLOCK_HAS_PAGE2))
{
if (block->prev_2 || block->next_2)
fatal("Invalid block_2 %x %p %08x\n", block->flags, block, block->phys);
return;
}
block->flags &= ~CODEBLOCK_HAS_PAGE2;
// pclog(" remove_from_block_list: %p flags = %x\n", block, block->flags);
if (block->prev_2)
{
codeblock[block->prev_2].next_2 = block->next_2;
if (block->next_2)
codeblock[block->next_2].prev_2 = block->prev_2;
}
else
{
// pclog(" pages.block_2=%p 3 %p %p\n", (void *)block->next_2, (void *)block, (void *)pages[block->phys_2 >> 12].block_2);
pages[block->phys_2 >> 12].block_2 = block->next_2;
if (block->next_2)
codeblock[block->next_2].prev_2 = BLOCK_INVALID;
else
mem_flush_write_page(block->phys_2, 0);
}
}
static void invalidate_block(codeblock_t *block)
{
uint32_t old_pc = block->pc;
if (block->flags & CODEBLOCK_IN_DIRTY_LIST)
fatal("invalidate_block: already in dirty list\n");
if (block->pc == BLOCK_PC_INVALID)
fatal("Invalidating deleted block\n");
remove_from_block_list(block, old_pc);
block_dirty_list_add(block);
if (block->head_mem_block)
codegen_allocator_free(block->head_mem_block);
block->head_mem_block = NULL;
}
static void delete_block(codeblock_t *block)
{
uint32_t old_pc = block->pc;
if (block == &codeblock[codeblock_hash[HASH(block->phys)]])
codeblock_hash[HASH(block->phys)] = BLOCK_INVALID;
if (block->pc == BLOCK_PC_INVALID)
fatal("Deleting deleted block\n");
block->pc = BLOCK_PC_INVALID;
codeblock_tree_delete(block);
if (block->flags & CODEBLOCK_IN_DIRTY_LIST)
block_dirty_list_remove(block);
else
remove_from_block_list(block, old_pc);
if (block->head_mem_block)
codegen_allocator_free(block->head_mem_block);
block->head_mem_block = NULL;
block_free_list_add(block);
}
static void delete_dirty_block(codeblock_t *block)
{
if (block == &codeblock[codeblock_hash[HASH(block->phys)]])
codeblock_hash[HASH(block->phys)] = BLOCK_INVALID;
if (block->pc == BLOCK_PC_INVALID)
fatal("Deleting deleted block\n");
block->pc = BLOCK_PC_INVALID;
codeblock_tree_delete(block);
block_free_list_add(block);
}
void codegen_delete_block(codeblock_t *block)
{
if (block->pc != BLOCK_PC_INVALID)
delete_block(block);
}
void codegen_delete_random_block(int required_mem_block)
{
int block_nr = rand() & BLOCK_MASK;
while (1)
{
if (block_nr && block_nr != block_current)
{
codeblock_t *block = &codeblock[block_nr];
if (block->pc != BLOCK_PC_INVALID && (!required_mem_block || block->head_mem_block))
{
delete_block(block);
return;
}
}
block_nr = (block_nr + 1) & BLOCK_MASK;
}
}
void codegen_check_flush(page_t *page, uint64_t mask, uint32_t phys_addr)
{
uint16_t block_nr = page->block;
int remove_from_evict_list = 0;
int c;
while (block_nr)
{
codeblock_t *block = &codeblock[block_nr];
uint16_t next_block = block->next;
if (*block->dirty_mask & block->page_mask)
{
// pclog("Delete block from codegen_check_flush %08x %08x %016llx %016llx %016llx %02x\n", phys_addr, block->pc, *block->dirty_mask, block->page_mask, *block->dirty_mask & block->page_mask, block->flags);
invalidate_block(block);
cpu_recomp_evicted++;
}
if (block_nr == next_block)
fatal("Broken 1\n");
block_nr = next_block;
}
block_nr = page->block_2;
while (block_nr)
{
codeblock_t *block = &codeblock[block_nr];
uint16_t next_block = block->next_2;
if (*block->dirty_mask2 & block->page_mask2)
{
// pclog("Delete block from codegen_check_flush2 %08x %08x\n", phys_addr, block->pc);*/
invalidate_block(block);
cpu_recomp_evicted++;
}
if (block_nr == next_block)
fatal("Broken 2\n");
block_nr = next_block;
}
if (page->code_present_mask & page->dirty_mask)
remove_from_evict_list = 1;
page->code_present_mask &= ~page->dirty_mask;
page->dirty_mask = 0;
for (c = 0; c < 64; c++)
{
if (page->byte_code_present_mask[c] & page->byte_dirty_mask[c])
remove_from_evict_list = 0;
page->byte_code_present_mask[c] &= ~page->byte_dirty_mask[c];
page->byte_dirty_mask[c] = 0;
}
if (remove_from_evict_list)
page_remove_from_evict_list(page);
}
void codegen_block_init(uint32_t phys_addr)
{
codeblock_t *block;
page_t *page = &pages[phys_addr >> 12];
if (!page->block)
mem_flush_write_page(phys_addr, cs+cpu_state.pc);
block = block_free_list_get();
if (!block)
fatal("codegen_block_init: block_free_list_get() returned NULL\n");
block_current = get_block_nr(block);
block_num = HASH(phys_addr);
codeblock_hash[block_num] = block_current;
block->ins = 0;
block->pc = cs + cpu_state.pc;
block->_cs = cs;
block->phys = phys_addr;
block->dirty_mask = &page->dirty_mask;
block->dirty_mask2 = NULL;
block->next = block->prev = BLOCK_INVALID;
block->next_2 = block->prev_2 = BLOCK_INVALID;
block->page_mask = block->page_mask2 = 0;
block->flags = CODEBLOCK_STATIC_TOP;
// pclog(" block_init: %p flags = %x\n", block, block->flags);
block->status = cpu_cur_status;
recomp_page = block->phys & ~0xfff;
// pclog("codegen_block_init: %08x\n", block->pc);
codeblock_tree_add(block);
}
static ir_data_t *ir_data;
ir_data_t *codegen_get_ir_data()
{
return ir_data;
}
void codegen_block_start_recompile(codeblock_t *block)
{
page_t *page = &pages[block->phys >> 12];
if (!page->block)
mem_flush_write_page(block->phys, cs+cpu_state.pc);
block_num = HASH(block->phys);
block_current = get_block_nr(block);//block->pnt;
if (block->pc != cs + cpu_state.pc || (block->flags & CODEBLOCK_WAS_RECOMPILED))
fatal("Recompile to used block!\n");
block->head_mem_block = codegen_allocator_allocate(NULL, block_current);
block->data = codeblock_allocator_get_ptr(block->head_mem_block);
block->status = cpu_cur_status;
block->page_mask = block->page_mask2 = 0;
block->ins = 0;
cpu_block_end = 0;
// pclog("New block %i for %08X %03x\n", block_current, cs+pc, block_num);
last_op32 = -1;
last_ea_seg = NULL;
last_ssegs = -1;
codegen_block_cycles = 0;
codegen_timing_block_start();
codegen_block_ins = 0;
codegen_block_full_ins = 0;
recomp_page = block->phys & ~0xfff;
codegen_flags_changed = 0;
codegen_fpu_entered = 0;
codegen_mmx_entered = 0;
codegen_fpu_loaded_iq[0] = codegen_fpu_loaded_iq[1] = codegen_fpu_loaded_iq[2] = codegen_fpu_loaded_iq[3] =
codegen_fpu_loaded_iq[4] = codegen_fpu_loaded_iq[5] = codegen_fpu_loaded_iq[6] = codegen_fpu_loaded_iq[7] = 0;
cpu_state.seg_ds.checked = cpu_state.seg_es.checked = cpu_state.seg_fs.checked = cpu_state.seg_gs.checked = (cr0 & 1) ? 0 : 1;
block->TOP = cpu_state.TOP & 7;
block->flags |= CODEBLOCK_WAS_RECOMPILED;
codegen_flat_ds = !(cpu_cur_status & CPU_STATUS_NOTFLATDS);
codegen_flat_ss = !(cpu_cur_status & CPU_STATUS_NOTFLATSS);
if (block->flags & CODEBLOCK_BYTE_MASK)
{
block->dirty_mask = &page->byte_dirty_mask[(block->phys >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK];
block->dirty_mask2 = NULL;
}
ir_data = codegen_ir_init();
ir_data->block = block;
codegen_reg_reset();
codegen_accumulate_reset();
codegen_generate_reset();
}
void codegen_block_remove()
{
codeblock_t *block = &codeblock[block_current];
delete_block(block);
cpu_recomp_removed++;
recomp_page = -1;
}
void codegen_block_generate_end_mask_recompile()
{
codeblock_t *block = &codeblock[block_current];
page_t *p;
//pclog("gen_end_mask: %08x %08x %016llx %016llx\n", block->pc, codegen_endpc, block->page_mask,block->page_mask2);
p = &pages[block->phys >> 12];
if (block->flags & CODEBLOCK_BYTE_MASK)
{
int offset = (block->phys >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK;
p->byte_code_present_mask[offset] |= block->page_mask;
}
else
p->code_present_mask |= block->page_mask;
if ((*(block->dirty_mask) & block->page_mask) && !page_in_evict_list(p))
page_add_to_evict_list(p);
block->phys_2 = -1;
block->next_2 = block->prev_2 = BLOCK_INVALID;
if (block->page_mask2)
{
block->phys_2 = get_phys_noabrt(codegen_endpc);
if (block->phys_2 != -1)
{
page_t *page_2 = &pages[block->phys_2 >> 12];
if (block->flags & CODEBLOCK_BYTE_MASK)
{
int offset = (block->phys_2 >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK;
page_2->byte_code_present_mask[offset] |= block->page_mask2;
block->dirty_mask2 = &page_2->byte_dirty_mask[offset];
}
else
{
page_2->code_present_mask |= block->page_mask2;
block->dirty_mask2 = &page_2->dirty_mask;
}
if (((*block->dirty_mask2) & block->page_mask2) && !page_in_evict_list(page_2))
page_add_to_evict_list(page_2);
if (!pages[block->phys_2 >> 12].block_2)
mem_flush_write_page(block->phys_2, codegen_endpc);
if (!block->page_mask2)
fatal("!page_mask2\n");
if (block->next_2)
{
// pclog(" next_2->pc=%08x\n", block->next_2->pc);
if (codeblock[block->next_2].pc == BLOCK_PC_INVALID)
fatal("block->next_2->pc=BLOCK_PC_INVALID %p\n", (void *)&codeblock[block->next_2]);
}
}
else
{
/*Second page not present. page_mask2 is most likely set only because
the recompiler didn't know how long the last instruction was, so
clear it*/
block->page_mask2 = 0;
}
}
// pclog("block_end: %08x %08x %016llx\n", block->pc, codegen_endpc, block->page_mask);
recomp_page = -1;
}
void codegen_block_generate_end_mask_mark()
{
codeblock_t *block = &codeblock[block_current];
uint32_t start_pc;
uint32_t end_pc;
page_t *p;
if (block->flags & CODEBLOCK_BYTE_MASK)
fatal("codegen_block_generate_end_mask2() - BYTE_MASK\n");
block->page_mask = 0;
start_pc = (block->pc & 0xfff) & ~63;
if ((block->pc ^ codegen_endpc) & ~0xfff)
end_pc = 0xfff & ~63;
else
end_pc = (codegen_endpc & 0xfff) & ~63;
if (end_pc < start_pc)
end_pc = 0xfff;
start_pc >>= PAGE_MASK_SHIFT;
end_pc >>= PAGE_MASK_SHIFT;
// pclog("block_end: %08x %08x\n", start_pc, end_pc);
for (; start_pc <= end_pc; start_pc++)
{
block->page_mask |= ((uint64_t)1 << start_pc);
// pclog(" %08x %llx\n", start_pc, block->page_mask);
}
p = &pages[block->phys >> 12];
p->code_present_mask |= block->page_mask;
if ((p->dirty_mask & block->page_mask) && !page_in_evict_list(p))
page_add_to_evict_list(p);
block->phys_2 = -1;
block->page_mask2 = 0;
block->next_2 = block->prev_2 = BLOCK_INVALID;
if ((block->pc ^ codegen_endpc) & ~0xfff)
{
block->phys_2 = get_phys_noabrt(codegen_endpc);
if (block->phys_2 != -1)
{
page_t *page_2 = &pages[block->phys_2 >> 12];
start_pc = 0;
end_pc = (codegen_endpc & 0xfff) >> PAGE_MASK_SHIFT;
for (; start_pc <= end_pc; start_pc++)
block->page_mask2 |= ((uint64_t)1 << start_pc);
page_2->code_present_mask |= block->page_mask2;
if ((page_2->dirty_mask & block->page_mask2) && !page_in_evict_list(page_2))
page_add_to_evict_list(page_2);
if (!pages[block->phys_2 >> 12].block_2)
mem_flush_write_page(block->phys_2, codegen_endpc);
if (!block->page_mask2)
fatal("!page_mask2\n");
if (block->next_2)
{
// pclog(" next_2->pc=%08x\n", block->next_2->pc);
if (codeblock[block->next_2].pc == BLOCK_PC_INVALID)
fatal("block->next_2->pc=BLOCK_PC_INVALID %p\n", (void *)&codeblock[block->next_2]);
}
block->dirty_mask2 = &page_2->dirty_mask;
}
else
{
/*Second page not present. page_mask2 is most likely set only because
the recompiler didn't know how long the last instruction was, so
clear it*/
block->page_mask2 = 0;
}
}
// pclog("block_end: %08x %08x %016llx\n", block->pc, codegen_endpc, block->page_mask);
recomp_page = -1;
}
void codegen_block_end()
{
codeblock_t *block = &codeblock[block_current];
codegen_block_generate_end_mask_mark();
add_to_block_list(block);
}
void codegen_block_end_recompile(codeblock_t *block)
{
codegen_timing_block_end();
codegen_accumulate(ACCREG_cycles, -codegen_block_cycles);
if (block->flags & CODEBLOCK_IN_DIRTY_LIST)
block_dirty_list_remove(block);
else
remove_from_block_list(block, block->pc);
block->next = block->prev = BLOCK_INVALID;
block->next_2 = block->prev_2 = BLOCK_INVALID;
codegen_block_generate_end_mask_recompile();
add_to_block_list(block);
// pclog("End block %i\n", block_num);
if (!(block->flags & CODEBLOCK_HAS_FPU))
block->flags &= ~CODEBLOCK_STATIC_TOP;
codegen_accumulate_flush(ir_data);
codegen_ir_compile(ir_data, block);
}
void codegen_flush()
{
return;
}
void codegen_mark_code_present_multibyte(codeblock_t *block, uint32_t start_pc, int len)
{
if (len)
{
uint32_t end_pc = start_pc + (len-1);
if (block->flags & CODEBLOCK_BYTE_MASK)
{
uint32_t start_pc_masked = start_pc & PAGE_MASK_MASK;
uint32_t end_pc_masked = end_pc & PAGE_MASK_MASK;
if ((start_pc ^ block->pc) & ~0x3f) /*Starts in second page*/
{
for (; start_pc_masked <= end_pc_masked; start_pc_masked++)
block->page_mask2 |= ((uint64_t)1 << start_pc_masked);
}
else if (((start_pc + (len-1)) ^ block->pc) & ~0x3f) /*Crosses both pages*/
{
for (; start_pc_masked <= 63; start_pc_masked++)
block->page_mask |= ((uint64_t)1 << start_pc_masked);
for (start_pc_masked = 0; start_pc_masked <= end_pc_masked; start_pc_masked++)
block->page_mask2 |= ((uint64_t)1 << start_pc_masked);
}
else /*First page only*/
{
for (; start_pc_masked <= end_pc_masked; start_pc_masked++)
block->page_mask |= ((uint64_t)1 << start_pc_masked);
}
}
else
{
uint32_t start_pc_shifted = start_pc >> PAGE_MASK_SHIFT;
uint32_t end_pc_shifted = end_pc >> PAGE_MASK_SHIFT;
start_pc_shifted &= PAGE_MASK_MASK;
end_pc_shifted &= PAGE_MASK_MASK;
if ((start_pc ^ block->pc) & ~0xfff) /*Starts in second page*/
{
for (; start_pc_shifted <= end_pc_shifted; start_pc_shifted++)
block->page_mask2 |= ((uint64_t)1 << start_pc_shifted);
}
else if (((start_pc + (len-1)) ^ block->pc) & ~0xfff) /*Crosses both pages*/
{
for (; start_pc_shifted <= 63; start_pc_shifted++)
block->page_mask |= ((uint64_t)1 << start_pc_shifted);
for (start_pc_shifted = 0; start_pc_shifted <= end_pc_shifted; start_pc_shifted++)
block->page_mask2 |= ((uint64_t)1 << start_pc_shifted);
}
else /*First page only*/
{
for (; start_pc_shifted <= end_pc_shifted; start_pc_shifted++)
block->page_mask |= ((uint64_t)1 << start_pc_shifted);
}
}
}
}

29
src/codegen_backend.h Normal file
View file

@ -0,0 +1,29 @@
//#ifdef __amd64__
//#include "codegen_x86-64.h"
#if defined __amd64__
#include "codegen_backend_x86-64.h"
#elif defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined WIN32 || defined _WIN32 || defined _WIN32
#include "codegen_backend_x86.h"
#elif defined __ARM_EABI__
#include "codegen_backend_arm.h"
#elif defined __aarch64__
#include "codegen_backend_arm64.h"
#else
#error Dynamic recompiler not implemented on your platform
#endif
void codegen_backend_init();
void codegen_backend_prologue(codeblock_t *block);
void codegen_backend_epilogue(codeblock_t *block);
struct ir_data_t;
struct uop_t;
struct ir_data_t *codegen_get_ir_data();
typedef int (*uOpFn)(codeblock_t *codeblock, struct uop_t *uop);
extern const uOpFn uop_handlers[];
extern int codegen_host_reg_list[CODEGEN_HOST_REGS];
extern int codegen_host_fp_reg_list[CODEGEN_HOST_FP_REGS];

368
src/codegen_backend_arm.c Normal file
View file

@ -0,0 +1,368 @@
#ifdef __ARM_EABI__
#include <stdlib.h>
#include "ibm.h"
#include "codegen.h"
#include "codegen_allocator.h"
#include "codegen_backend.h"
#include "codegen_backend_arm_defs.h"
#include "codegen_backend_arm_ops.h"
#include "codegen_reg.h"
#include "x86.h"
#include "x87.h"
#if defined(__linux__) || defined(__APPLE__)
#include <sys/mman.h>
#include <unistd.h>
#endif
#if defined WIN32 || defined _WIN32 || defined _WIN32
#include <windows.h>
#endif
void *codegen_mem_load_byte;
void *codegen_mem_load_word;
void *codegen_mem_load_long;
void *codegen_mem_load_quad;
void *codegen_mem_load_single;
void *codegen_mem_load_double;
void *codegen_mem_store_byte;
void *codegen_mem_store_word;
void *codegen_mem_store_long;
void *codegen_mem_store_quad;
void *codegen_mem_store_single;
void *codegen_mem_store_double;
void *codegen_fp_round;
void *codegen_gpf_rout;
void *codegen_exit_rout;
int codegen_host_reg_list[CODEGEN_HOST_REGS] =
{
REG_R4,
REG_R5,
REG_R6,
REG_R7,
REG_R8,
REG_R9,
REG_R11,
};
int codegen_host_fp_reg_list[CODEGEN_HOST_FP_REGS] =
{
REG_D8,
REG_D9,
REG_D10,
REG_D11,
REG_D12,
REG_D13,
REG_D14,
REG_D15
};
static void build_load_routine(codeblock_t *block, int size, int is_float)
{
uint32_t *branch_offset;
uint32_t *misaligned_offset;
/*In - R0 = address
Out - R0 = data, R1 = abrt*/
/*MOV R1, R0, LSR #12
MOV R2, #readlookup2
LDR R1, [R2, R1, LSL #2]
CMP R1, #-1
BNE +
LDRB R0, [R1, R0]
MOV R1, #0
MOV PC, LR
* STR LR, [SP, -4]!
BL readmembl
LDRB R1, cpu_state.abrt
LDR PC, [SP], #4
*/
codegen_alloc(block, 80);
host_arm_MOV_REG_LSR(block, REG_R1, REG_R0, 12);
host_arm_MOV_IMM(block, REG_R2, (uint32_t)readlookup2);
host_arm_LDR_REG_LSL(block, REG_R1, REG_R2, REG_R1, 2);
if (size != 1)
{
host_arm_TST_IMM(block, REG_R0, size-1);
misaligned_offset = host_arm_BNE_(block);
}
host_arm_CMP_IMM(block, REG_R1, -1);
branch_offset = host_arm_BEQ_(block);
if (size == 1 && !is_float)
host_arm_LDRB_REG(block, REG_R0, REG_R1, REG_R0);
else if (size == 2 && !is_float)
host_arm_LDRH_REG(block, REG_R0, REG_R1, REG_R0);
else if (size == 4 && !is_float)
host_arm_LDR_REG(block, REG_R0, REG_R1, REG_R0);
else if (size == 4 && is_float)
{
host_arm_ADD_REG(block, REG_R0, REG_R0, REG_R1);
host_arm_VLDR_S(block, REG_D_TEMP, REG_R0, 0);
}
else if (size == 8)
{
host_arm_ADD_REG(block, REG_R0, REG_R0, REG_R1);
host_arm_VLDR_D(block, REG_D_TEMP, REG_R0, 0);
}
host_arm_MOV_IMM(block, REG_R1, 0);
host_arm_MOV_REG(block, REG_PC, REG_LR);
*branch_offset |= ((((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 8) & 0x3fffffc) >> 2;
if (size != 1)
*misaligned_offset |= ((((uintptr_t)&block_write_data[block_pos] - (uintptr_t)misaligned_offset) - 8) & 0x3fffffc) >> 2;
host_arm_STR_IMM_WB(block, REG_LR, REG_HOST_SP, -4);
if (size == 1)
host_arm_BL(block, (uintptr_t)readmembl);
else if (size == 2)
host_arm_BL(block, (uintptr_t)readmemwl);
else if (size == 4)
host_arm_BL(block, (uintptr_t)readmemll);
else if (size == 8)
host_arm_BL(block, (uintptr_t)readmemql);
else
fatal("build_load_routine - unknown size %i\n", size);
if (size == 4 && is_float)
host_arm_VMOV_S_32(block, REG_D_TEMP, REG_R0);
else if (size == 8)
host_arm_VMOV_D_64(block, REG_D_TEMP, REG_R0, REG_R1);
host_arm_LDRB_ABS(block, REG_R1, &cpu_state.abrt);
host_arm_LDR_IMM_POST(block, REG_PC, REG_HOST_SP, 4);
}
static void build_store_routine(codeblock_t *block, int size, int is_float)
{
uint32_t *branch_offset;
uint32_t *misaligned_offset;
/*In - R0 = address
Out - R0 = data, R1 = abrt*/
/*MOV R1, R0, LSR #12
MOV R2, #readlookup2
LDR R1, [R2, R1, LSL #2]
CMP R1, #-1
BNE +
LDRB R0, [R1, R0]
MOV R1, #0
MOV PC, LR
* STR LR, [SP, -4]!
BL readmembl
LDRB R1, cpu_state.abrt
LDR PC, [SP], #4
*/
codegen_alloc(block, 80);
host_arm_MOV_REG_LSR(block, REG_R2, REG_R0, 12);
host_arm_MOV_IMM(block, REG_R3, (uint32_t)writelookup2);
host_arm_LDR_REG_LSL(block, REG_R2, REG_R3, REG_R2, 2);
if (size != 1)
{
host_arm_TST_IMM(block, REG_R0, size-1);
misaligned_offset = host_arm_BNE_(block);
}
host_arm_CMP_IMM(block, REG_R2, -1);
branch_offset = host_arm_BEQ_(block);
if (size == 1 && !is_float)
host_arm_STRB_REG(block, REG_R1, REG_R2, REG_R0);
else if (size == 2 && !is_float)
host_arm_STRH_REG(block, REG_R1, REG_R2, REG_R0);
else if (size == 4 && !is_float)
host_arm_STR_REG(block, REG_R1, REG_R2, REG_R0);
else if (size == 4 && is_float)
{
host_arm_ADD_REG(block, REG_R0, REG_R0, REG_R2);
host_arm_VSTR_S(block, REG_D_TEMP, REG_R0, 0);
}
else if (size == 8)
{
host_arm_ADD_REG(block, REG_R0, REG_R0, REG_R2);
host_arm_VSTR_D(block, REG_D_TEMP, REG_R0, 0);
}
host_arm_MOV_IMM(block, REG_R1, 0);
host_arm_MOV_REG(block, REG_PC, REG_LR);
*branch_offset |= ((((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 8) & 0x3fffffc) >> 2;
if (size != 1)
*misaligned_offset |= ((((uintptr_t)&block_write_data[block_pos] - (uintptr_t)misaligned_offset) - 8) & 0x3fffffc) >> 2;
host_arm_STR_IMM_WB(block, REG_LR, REG_HOST_SP, -4);
if (size == 4 && is_float)
host_arm_VMOV_32_S(block, REG_R1, REG_D_TEMP);
else if (size == 8)
host_arm_VMOV_64_D(block, REG_R2, REG_R3, REG_D_TEMP);
if (size == 1)
host_arm_BL(block, (uintptr_t)writemembl);
else if (size == 2)
host_arm_BL(block, (uintptr_t)writememwl);
else if (size == 4)
host_arm_BL(block, (uintptr_t)writememll);
else if (size == 8)
host_arm_BL_r1(block, (uintptr_t)writememql);
else
fatal("build_store_routine - unknown size %i\n", size);
host_arm_LDRB_ABS(block, REG_R1, &cpu_state.abrt);
host_arm_LDR_IMM_POST(block, REG_PC, REG_HOST_SP, 4);
}
static void build_loadstore_routines(codeblock_t *block)
{
codegen_mem_load_byte = &block_write_data[block_pos];
build_load_routine(block, 1, 0);
codegen_mem_load_word = &block_write_data[block_pos];
build_load_routine(block, 2, 0);
codegen_mem_load_long = &block_write_data[block_pos];
build_load_routine(block, 4, 0);
codegen_mem_load_quad = &block_write_data[block_pos];
build_load_routine(block, 8, 0);
codegen_mem_load_single = &block_write_data[block_pos];
build_load_routine(block, 4, 1);
codegen_mem_load_double = &block_write_data[block_pos];
build_load_routine(block, 8, 1);
codegen_mem_store_byte = &block_write_data[block_pos];
build_store_routine(block, 1, 0);
codegen_mem_store_word = &block_write_data[block_pos];
build_store_routine(block, 2, 0);
codegen_mem_store_long = &block_write_data[block_pos];
build_store_routine(block, 4, 0);
codegen_mem_store_quad = &block_write_data[block_pos];
build_store_routine(block, 8, 0);
codegen_mem_store_single = &block_write_data[block_pos];
build_store_routine(block, 4, 1);
codegen_mem_store_double = &block_write_data[block_pos];
build_store_routine(block, 8, 1);
}
/*VFP has a specific round-to-zero instruction, and the default rounding mode
is nearest. For round up/down, temporarily change the rounding mode in FPCSR*/
#define FPCSR_ROUNDING_MASK (3 << 22)
#define FPCSR_ROUNDING_UP (1 << 22)
#define FPCSR_ROUNDING_DOWN (2 << 22)
static void build_fp_round_routine(codeblock_t *block)
{
uint32_t *jump_table;
codegen_alloc(block, 80);
host_arm_MOV_REG(block, REG_TEMP2, REG_LR);
host_arm_MOV_REG(block, REG_LR, REG_TEMP2);
host_arm_LDR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.new_fp_control - (uintptr_t)&cpu_state);
host_arm_LDR_REG(block, REG_PC, REG_PC, REG_TEMP);
host_arm_NOP(block);
jump_table = (uint32_t *)&block_write_data[block_pos];
host_arm_NOP(block);
host_arm_NOP(block);
host_arm_NOP(block);
host_arm_NOP(block);
jump_table[X87_ROUNDING_NEAREST] = (uint64_t)(uintptr_t)&block_write_data[block_pos]; //tie even
host_arm_VCVTR_IS_D(block, REG_D_TEMP, REG_D_TEMP);
host_arm_MOV_REG(block, REG_PC, REG_LR);
jump_table[X87_ROUNDING_UP] = (uint64_t)(uintptr_t)&block_write_data[block_pos]; //pos inf
host_arm_LDR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.old_fp_control - (uintptr_t)&cpu_state);
host_arm_BIC_IMM(block, REG_TEMP2, REG_TEMP, FPCSR_ROUNDING_MASK);
host_arm_ORR_IMM(block, REG_TEMP2, REG_TEMP2, FPCSR_ROUNDING_UP);
host_arm_VMSR_FPSCR(block, REG_TEMP2);
host_arm_VCVTR_IS_D(block, REG_D_TEMP, REG_D_TEMP);
host_arm_VMSR_FPSCR(block, REG_TEMP);
host_arm_MOV_REG(block, REG_PC, REG_LR);
jump_table[X87_ROUNDING_DOWN] = (uint64_t)(uintptr_t)&block_write_data[block_pos]; //neg inf
host_arm_LDR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.old_fp_control - (uintptr_t)&cpu_state);
host_arm_BIC_IMM(block, REG_TEMP2, REG_TEMP, FPCSR_ROUNDING_MASK);
host_arm_ORR_IMM(block, REG_TEMP2, REG_TEMP, FPCSR_ROUNDING_DOWN);
host_arm_VMSR_FPSCR(block, REG_TEMP2);
host_arm_VCVTR_IS_D(block, REG_D_TEMP, REG_D_TEMP);
host_arm_VMSR_FPSCR(block, REG_TEMP);
host_arm_MOV_REG(block, REG_PC, REG_LR);
jump_table[X87_ROUNDING_CHOP] = (uint64_t)(uintptr_t)&block_write_data[block_pos]; //zero
host_arm_VCVT_IS_D(block, REG_D_TEMP, REG_D_TEMP);
host_arm_MOV_REG(block, REG_PC, REG_LR);
}
void codegen_backend_init()
{
codeblock_t *block;
int c;
codeblock = malloc(BLOCK_SIZE * sizeof(codeblock_t));
codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *));
memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t));
memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *));
for (c = 0; c < BLOCK_SIZE; c++)
codeblock[c].pc = BLOCK_PC_INVALID;
// pclog("Codegen is %p\n", (void *)pages[0xfab12 >> 12].block);
block_current = 0;
block_pos = 0;
block = &codeblock[block_current];
block->head_mem_block = codegen_allocator_allocate(NULL, block_current);
block->data = codeblock_allocator_get_ptr(block->head_mem_block);
block_write_data = block->data;
build_loadstore_routines(&codeblock[block_current]);
printf("block_pos=%i\n", block_pos);
codegen_fp_round = &block_write_data[block_pos];
build_fp_round_routine(&codeblock[block_current]);
codegen_alloc(block, 80);
codegen_gpf_rout = &block_write_data[block_pos];
host_arm_MOV_IMM(block, REG_R0, 0);
host_arm_MOV_IMM(block, REG_R1, 0);
host_arm_call(block, x86gpf);
codegen_exit_rout = &block_write_data[block_pos];
host_arm_ADD_IMM(block, REG_HOST_SP, REG_HOST_SP, 0x40);
host_arm_LDMIA_WB(block, REG_HOST_SP, REG_MASK_LOCAL | REG_MASK_PC);
block_write_data = NULL;
//fatal("block_pos=%i\n", block_pos);
asm("vmrs %0, fpscr\n"
: "=r" (cpu_state.old_fp_control)
);
if ((cpu_state.old_fp_control >> 22) & 3)
fatal("VFP not in nearest rounding mode\n");
}
void codegen_set_rounding_mode(int mode)
{
if (mode < 0 || mode > 3)
fatal("codegen_set_rounding_mode - invalid mode\n");
cpu_state.new_fp_control = mode << 2;
}
/*R10 - cpu_state*/
void codegen_backend_prologue(codeblock_t *block)
{
block_pos = BLOCK_START;
/*Entry code*/
host_arm_STMDB_WB(block, REG_HOST_SP, REG_MASK_LOCAL | REG_MASK_LR);
host_arm_SUB_IMM(block, REG_HOST_SP, REG_HOST_SP, 0x40);
host_arm_MOV_IMM(block, REG_CPUSTATE, (uint32_t)&cpu_state);
if (block->flags & CODEBLOCK_HAS_FPU)
{
host_arm_LDR_IMM(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.TOP - (uintptr_t)&cpu_state);
host_arm_SUB_IMM(block, REG_TEMP, REG_TEMP, block->TOP);
host_arm_STR_IMM(block, REG_TEMP, REG_HOST_SP, IREG_TOP_diff_stack_offset);
}
}
void codegen_backend_epilogue(codeblock_t *block)
{
host_arm_ADD_IMM(block, REG_HOST_SP, REG_HOST_SP, 0x40);
host_arm_LDMIA_WB(block, REG_HOST_SP, REG_MASK_LOCAL | REG_MASK_PC);
codegen_allocator_clean_blocks(block->head_mem_block);
}
#endif

24
src/codegen_backend_arm.h Normal file
View file

@ -0,0 +1,24 @@
#include "codegen_backend_arm_defs.h"
#define BLOCK_SIZE 0x4000
#define BLOCK_MASK 0x3fff
#define BLOCK_START 0
#define HASH_SIZE 0x20000
#define HASH_MASK 0x1ffff
#define HASH(l) ((l) & 0x1ffff)
#define BLOCK_MAX 0x3c0
void host_arm_ADD_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm);
void host_arm_LDMIA_WB(codeblock_t *block, int addr_reg, uint32_t reg_mask);
void host_arm_LDR_IMM(codeblock_t *block, int dst_reg, int addr_reg, int offset);
void host_arm_MOV_IMM(codeblock_t *block, int dst_reg, uint32_t imm);
void host_arm_STMDB_WB(codeblock_t *block, int addr_reg, uint32_t reg_mask);
void host_arm_SUB_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm);
void host_arm_call(codeblock_t *block, void *dst_addr);
void host_arm_nop(codeblock_t *block);
void codegen_alloc(codeblock_t *block, int size);

382
src/codegen_backend_arm64.c Normal file
View file

@ -0,0 +1,382 @@
#ifdef __aarch64__
#include <stdlib.h>
#include "ibm.h"
#include "codegen.h"
#include "codegen_allocator.h"
#include "codegen_backend.h"
#include "codegen_backend_arm64_defs.h"
#include "codegen_backend_arm64_ops.h"
#include "codegen_reg.h"
#include "x86.h"
#include "x87.h"
#if defined(__linux__) || defined(__APPLE__)
#include <sys/mman.h>
#include <unistd.h>
#endif
#if defined WIN32 || defined _WIN32 || defined _WIN32
#include <windows.h>
#endif
void *codegen_mem_load_byte;
void *codegen_mem_load_word;
void *codegen_mem_load_long;
void *codegen_mem_load_quad;
void *codegen_mem_load_single;
void *codegen_mem_load_double;
void *codegen_mem_store_byte;
void *codegen_mem_store_word;
void *codegen_mem_store_long;
void *codegen_mem_store_quad;
void *codegen_mem_store_single;
void *codegen_mem_store_double;
void *codegen_fp_round;
void *codegen_fp_round_quad;
void *codegen_gpf_rout;
void *codegen_exit_rout;
int codegen_host_reg_list[CODEGEN_HOST_REGS] =
{
REG_X19,
REG_X20,
REG_X21,
REG_X22,
REG_X23,
REG_X24,
REG_X25,
REG_X26,
REG_X27,
REG_X28
};
int codegen_host_fp_reg_list[CODEGEN_HOST_FP_REGS] =
{
REG_V8,
REG_V9,
REG_V10,
REG_V11,
REG_V12,
REG_V13,
REG_V14,
REG_V15
};
static void build_load_routine(codeblock_t *block, int size, int is_float)
{
uint32_t *branch_offset;
uint32_t *misaligned_offset;
int offset;
/*In - W0 = address
Out - W0 = data, W1 = abrt*/
/*MOV W1, W0, LSR #12
MOV X2, #readlookup2
LDR X1, [X2, X1, LSL #3]
CMP X1, #-1
BEQ +
LDRB W0, [X1, X0]
MOV W1, #0
RET
* STP X29, X30, [SP, #-16]
BL readmembl
LDRB R1, cpu_state.abrt
LDP X29, X30, [SP, #-16]
RET
*/
codegen_alloc(block, 80);
host_arm64_MOV_REG_LSR(block, REG_W1, REG_W0, 12);
host_arm64_MOVX_IMM(block, REG_X2, (uint64_t)readlookup2);
host_arm64_LDRX_REG_LSL3(block, REG_X1, REG_X2, REG_X1);
if (size != 1)
{
host_arm64_TST_IMM(block, REG_W0, size-1);
misaligned_offset = host_arm64_BNE_(block);
}
host_arm64_CMPX_IMM(block, REG_X1, -1);
branch_offset = host_arm64_BEQ_(block);
if (size == 1 && !is_float)
host_arm64_LDRB_REG(block, REG_W0, REG_W1, REG_W0);
else if (size == 2 && !is_float)
host_arm64_LDRH_REG(block, REG_W0, REG_W1, REG_W0);
else if (size == 4 && !is_float)
host_arm64_LDR_REG(block, REG_W0, REG_W1, REG_W0);
else if (size == 4 && is_float)
host_arm64_LDR_REG_F32(block, REG_V_TEMP, REG_W1, REG_W0);
else if (size == 8)
host_arm64_LDR_REG_F64(block, REG_V_TEMP, REG_W1, REG_W0);
host_arm64_MOVZ_IMM(block, REG_W1, 0);
host_arm64_RET(block, REG_X30);
host_arm64_branch_set_offset(branch_offset, &block_write_data[block_pos]);
if (size != 1)
host_arm64_branch_set_offset(misaligned_offset, &block_write_data[block_pos]);
host_arm64_STP_PREIDX_X(block, REG_X29, REG_X30, REG_XSP, -16);
if (size == 1)
host_arm64_call(block, (void *)readmembl);
else if (size == 2)
host_arm64_call(block, (void *)readmemwl);
else if (size == 4)
host_arm64_call(block, (void *)readmemll);
else if (size == 8)
host_arm64_call(block, (void *)readmemql);
else
fatal("build_load_routine - unknown size %i\n", size);
codegen_direct_read_8(block, REG_W1, &cpu_state.abrt);
if (size == 4 && is_float)
host_arm64_FMOV_S_W(block, REG_V_TEMP, REG_W0);
else if (size == 8)
host_arm64_FMOV_D_Q(block, REG_V_TEMP, REG_X0);
host_arm64_LDP_POSTIDX_X(block, REG_X29, REG_X30, REG_XSP, 16);
host_arm64_RET(block, REG_X30);
}
static void build_store_routine(codeblock_t *block, int size, int is_float)
{
uint32_t *branch_offset;
uint32_t *misaligned_offset;
int offset;
/*In - R0 = address, R1 = data
Out - R1 = abrt*/
/*MOV W2, W0, LSR #12
MOV X3, #writelookup2
LDR X2, [X3, X2, LSL #3]
CMP X2, #-1
BEQ +
STRB W1, [X2, X0]
MOV W1, #0
RET
* STP X29, X30, [SP, #-16]
BL writemembl
LDRB R1, cpu_state.abrt
LDP X29, X30, [SP, #-16]
RET
*/
codegen_alloc(block, 80);
host_arm64_MOV_REG_LSR(block, REG_W2, REG_W0, 12);
host_arm64_MOVX_IMM(block, REG_X3, (uint64_t)writelookup2);
host_arm64_LDRX_REG_LSL3(block, REG_X2, REG_X3, REG_X2);
if (size != 1)
{
host_arm64_TST_IMM(block, REG_W0, size-1);
misaligned_offset = host_arm64_BNE_(block);
}
host_arm64_CMPX_IMM(block, REG_X2, -1);
branch_offset = host_arm64_BEQ_(block);
if (size == 1 && !is_float)
host_arm64_STRB_REG(block, REG_X1, REG_X2, REG_X0);
else if (size == 2 && !is_float)
host_arm64_STRH_REG(block, REG_X1, REG_X2, REG_X0);
else if (size == 4 && !is_float)
host_arm64_STR_REG(block, REG_X1, REG_X2, REG_X0);
else if (size == 4 && is_float)
host_arm64_STR_REG_F32(block, REG_V_TEMP, REG_X2, REG_X0);
else if (size == 8)
host_arm64_STR_REG_F64(block, REG_V_TEMP, REG_X2, REG_X0);
host_arm64_MOVZ_IMM(block, REG_X1, 0);
host_arm64_RET(block, REG_X30);
host_arm64_branch_set_offset(branch_offset, &block_write_data[block_pos]);
if (size != 1)
host_arm64_branch_set_offset(misaligned_offset, &block_write_data[block_pos]);
host_arm64_STP_PREIDX_X(block, REG_X29, REG_X30, REG_XSP, -16);
if (size == 4 && is_float)
host_arm64_FMOV_W_S(block, REG_W1, REG_V_TEMP);
else if (size == 8)
host_arm64_FMOV_Q_D(block, REG_X1, REG_V_TEMP);
if (size == 1)
host_arm64_call(block, (void *)writemembl);
else if (size == 2)
host_arm64_call(block, (void *)writememwl);
else if (size == 4)
host_arm64_call(block, (void *)writememll);
else if (size == 8)
host_arm64_call(block, (void *)writememql);
else
fatal("build_store_routine - unknown size %i\n", size);
codegen_direct_read_8(block, REG_W1, &cpu_state.abrt);
host_arm64_LDP_POSTIDX_X(block, REG_X29, REG_X30, REG_XSP, 16);
host_arm64_RET(block, REG_X30);
}
static void build_loadstore_routines(codeblock_t *block)
{
codegen_mem_load_byte = &block_write_data[block_pos];
build_load_routine(block, 1, 0);
codegen_mem_load_word = &block_write_data[block_pos];
build_load_routine(block, 2, 0);
codegen_mem_load_long = &block_write_data[block_pos];
build_load_routine(block, 4, 0);
codegen_mem_load_quad = &block_write_data[block_pos];
build_load_routine(block, 8, 0);
codegen_mem_load_single = &block_write_data[block_pos];
build_load_routine(block, 4, 1);
codegen_mem_load_double = &block_write_data[block_pos];
build_load_routine(block, 8, 1);
codegen_mem_store_byte = &block_write_data[block_pos];
build_store_routine(block, 1, 0);
codegen_mem_store_word = &block_write_data[block_pos];
build_store_routine(block, 2, 0);
codegen_mem_store_long = &block_write_data[block_pos];
build_store_routine(block, 4, 0);
codegen_mem_store_quad = &block_write_data[block_pos];
build_store_routine(block, 8, 0);
codegen_mem_store_single = &block_write_data[block_pos];
build_store_routine(block, 4, 1);
codegen_mem_store_double = &block_write_data[block_pos];
build_store_routine(block, 8, 1);
}
static void build_fp_round_routine(codeblock_t *block, int is_quad)
{
uint64_t *jump_table;
codegen_alloc(block, 80);
host_arm64_LDR_IMM_W(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.new_fp_control - (uintptr_t)&cpu_state);
host_arm64_ADR(block, REG_TEMP2, 12);
host_arm64_LDR_REG_X(block, REG_TEMP2, REG_TEMP2, REG_TEMP);
host_arm64_BR(block, REG_TEMP2);
jump_table = (uint64_t *)&block_write_data[block_pos];
block_pos += 4*8;
jump_table[X87_ROUNDING_NEAREST] = (uint64_t)(uintptr_t)&block_write_data[block_pos]; //tie even
if (is_quad)
host_arm64_FCVTNS_X_D(block, REG_TEMP, REG_V_TEMP);
else
host_arm64_FCVTNS_W_D(block, REG_TEMP, REG_V_TEMP);
host_arm64_RET(block, REG_X30);
jump_table[X87_ROUNDING_UP] = (uint64_t)(uintptr_t)&block_write_data[block_pos]; //pos inf
if (is_quad)
host_arm64_FCVTPS_X_D(block, REG_TEMP, REG_V_TEMP);
else
host_arm64_FCVTPS_W_D(block, REG_TEMP, REG_V_TEMP);
host_arm64_RET(block, REG_X30);
jump_table[X87_ROUNDING_DOWN] = (uint64_t)(uintptr_t)&block_write_data[block_pos]; //neg inf
if (is_quad)
host_arm64_FCVTMS_X_D(block, REG_TEMP, REG_V_TEMP);
else
host_arm64_FCVTMS_W_D(block, REG_TEMP, REG_V_TEMP);
host_arm64_RET(block, REG_X30);
jump_table[X87_ROUNDING_CHOP] = (uint64_t)(uintptr_t)&block_write_data[block_pos]; //zero
if (is_quad)
host_arm64_FCVTZS_X_D(block, REG_TEMP, REG_V_TEMP);
else
host_arm64_FCVTZS_W_D(block, REG_TEMP, REG_V_TEMP);
host_arm64_RET(block, REG_X30);
}
void codegen_backend_init()
{
codeblock_t *block;
int c;
#if defined(__linux__) || defined(__APPLE__)
void *start;
size_t len;
long pagesize = sysconf(_SC_PAGESIZE);
long pagemask = ~(pagesize - 1);
#endif
codeblock = malloc(BLOCK_SIZE * sizeof(codeblock_t));
codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *));
memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t));
memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *));
for (c = 0; c < BLOCK_SIZE; c++)
{
codeblock[c].pc = BLOCK_PC_INVALID;
}
// pclog("Codegen is %p\n", (void *)pages[0xfab12 >> 12].block);
block_current = 0;
block_pos = 0;
block = &codeblock[block_current];
block->head_mem_block = codegen_allocator_allocate(NULL, block_current);
block->data = codeblock_allocator_get_ptr(block->head_mem_block);
block_write_data = block->data;
build_loadstore_routines(block);
codegen_fp_round = &block_write_data[block_pos];
build_fp_round_routine(block, 0);
codegen_fp_round_quad = &block_write_data[block_pos];
build_fp_round_routine(block, 1);
codegen_alloc(block, 80);
codegen_gpf_rout = &block_write_data[block_pos];
host_arm64_mov_imm(block, REG_ARG0, 0);
host_arm64_mov_imm(block, REG_ARG1, 0);
host_arm64_call(block, (void *)x86gpf);
codegen_exit_rout = &block_write_data[block_pos];
host_arm64_LDP_POSTIDX_X(block, REG_X19, REG_X20, REG_XSP, 64);
host_arm64_LDP_POSTIDX_X(block, REG_X21, REG_X22, REG_XSP, 16);
host_arm64_LDP_POSTIDX_X(block, REG_X23, REG_X24, REG_XSP, 16);
host_arm64_LDP_POSTIDX_X(block, REG_X25, REG_X26, REG_XSP, 16);
host_arm64_LDP_POSTIDX_X(block, REG_X27, REG_X28, REG_XSP, 16);
host_arm64_LDP_POSTIDX_X(block, REG_X29, REG_X30, REG_XSP, 16);
host_arm64_RET(block, REG_X30);
block_write_data = NULL;
codegen_allocator_clean_blocks(block->head_mem_block);
asm("mrs %0, fpcr\n"
: "=r" (cpu_state.old_fp_control)
);
}
void codegen_set_rounding_mode(int mode)
{
if (mode < 0 || mode > 3)
fatal("codegen_set_rounding_mode - invalid mode\n");
cpu_state.new_fp_control = mode << 3;
}
/*R10 - cpu_state*/
void codegen_backend_prologue(codeblock_t *block)
{
block_pos = BLOCK_START;
/*Entry code*/
host_arm64_STP_PREIDX_X(block, REG_X29, REG_X30, REG_XSP, -16);
host_arm64_STP_PREIDX_X(block, REG_X27, REG_X28, REG_XSP, -16);
host_arm64_STP_PREIDX_X(block, REG_X25, REG_X26, REG_XSP, -16);
host_arm64_STP_PREIDX_X(block, REG_X23, REG_X24, REG_XSP, -16);
host_arm64_STP_PREIDX_X(block, REG_X21, REG_X22, REG_XSP, -16);
host_arm64_STP_PREIDX_X(block, REG_X19, REG_X20, REG_XSP, -64);
host_arm64_MOVX_IMM(block, REG_CPUSTATE, (uint64_t)&cpu_state);
if (block->flags & CODEBLOCK_HAS_FPU)
{
host_arm64_LDR_IMM_W(block, REG_TEMP, REG_CPUSTATE, (uintptr_t)&cpu_state.TOP - (uintptr_t)&cpu_state);
host_arm64_SUB_IMM(block, REG_TEMP, REG_TEMP, block->TOP);
host_arm64_STR_IMM_W(block, REG_TEMP, REG_XSP, IREG_TOP_diff_stack_offset);
}
}
void codegen_backend_epilogue(codeblock_t *block)
{
host_arm64_LDP_POSTIDX_X(block, REG_X19, REG_X20, REG_XSP, 64);
host_arm64_LDP_POSTIDX_X(block, REG_X21, REG_X22, REG_XSP, 16);
host_arm64_LDP_POSTIDX_X(block, REG_X23, REG_X24, REG_XSP, 16);
host_arm64_LDP_POSTIDX_X(block, REG_X25, REG_X26, REG_XSP, 16);
host_arm64_LDP_POSTIDX_X(block, REG_X27, REG_X28, REG_XSP, 16);
host_arm64_LDP_POSTIDX_X(block, REG_X29, REG_X30, REG_XSP, 16);
host_arm64_RET(block, REG_X30);
codegen_allocator_clean_blocks(block->head_mem_block);
}
#endif

View file

@ -0,0 +1,31 @@
#include "codegen_backend_arm64_defs.h"
#define BLOCK_SIZE 0x4000
#define BLOCK_MASK 0x3fff
#define BLOCK_START 0
#define HASH_SIZE 0x20000
#define HASH_MASK 0x1ffff
#define HASH(l) ((l) & 0x1ffff)
#define BLOCK_MAX 0x3c0
void host_arm64_BLR(codeblock_t *block, int addr_reg);
void host_arm64_CBNZ(codeblock_t *block, int reg, uintptr_t dest);
void host_arm64_MOVK_IMM(codeblock_t *block, int reg, uint32_t imm_data);
void host_arm64_MOVZ_IMM(codeblock_t *block, int reg, uint32_t imm_data);
void host_arm64_LDP_POSTIDX_X(codeblock_t *block, int src_reg1, int src_reg2, int base_reg, int offset);
void host_arm64_LDR_LITERAL_W(codeblock_t *block, int dest_reg, int literal_offset);
void host_arm64_LDR_LITERAL_X(codeblock_t *block, int dest_reg, int literal_offset);
void host_arm64_NOP(codeblock_t *block);
void host_arm64_RET(codeblock_t *block, int reg);
void host_arm64_STP_PREIDX_X(codeblock_t *block, int src_reg1, int src_reg2, int base_reg, int offset);
void host_arm64_STR_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int offset);
void host_arm64_STRB_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int offset);
void host_arm64_call(codeblock_t *block, void *dst_addr);
void host_arm64_mov_imm(codeblock_t *block, int reg, uint32_t imm_data);
uint32_t host_arm64_find_imm(uint32_t data);

View file

@ -0,0 +1,135 @@
#define REG_W0 0
#define REG_W1 1
#define REG_W2 2
#define REG_W3 3
#define REG_W4 4
#define REG_W5 5
#define REG_W6 6
#define REG_W7 7
#define REG_W8 8
#define REG_W9 9
#define REG_W10 10
#define REG_W11 11
#define REG_W12 12
#define REG_W13 13
#define REG_W14 14
#define REG_W15 15
#define REG_W16 16
#define REG_W17 17
#define REG_W18 18
#define REG_W19 19
#define REG_W20 20
#define REG_W21 21
#define REG_W22 22
#define REG_W23 23
#define REG_W24 24
#define REG_W25 25
#define REG_W26 26
#define REG_W27 27
#define REG_W28 28
#define REG_W29 29
#define REG_W30 30
#define REG_WZR 31
#define REG_X0 0
#define REG_X1 1
#define REG_X2 2
#define REG_X3 3
#define REG_X4 4
#define REG_X5 5
#define REG_X6 6
#define REG_X7 7
#define REG_X8 8
#define REG_X9 9
#define REG_X10 10
#define REG_X11 11
#define REG_X12 12
#define REG_X13 13
#define REG_X14 14
#define REG_X15 15
#define REG_X16 16
#define REG_X17 17
#define REG_X18 18
#define REG_X19 19
#define REG_X20 20
#define REG_X21 21
#define REG_X22 22
#define REG_X23 23
#define REG_X24 24
#define REG_X25 25
#define REG_X26 26
#define REG_X27 27
#define REG_X28 28
#define REG_X29 29
#define REG_X30 30
#define REG_XZR 31
#define REG_V0 0
#define REG_V1 1
#define REG_V2 2
#define REG_V3 3
#define REG_V4 4
#define REG_V5 5
#define REG_V6 6
#define REG_V7 7
#define REG_V8 8
#define REG_V9 9
#define REG_V10 10
#define REG_V11 11
#define REG_V12 12
#define REG_V13 13
#define REG_V14 14
#define REG_V15 15
#define REG_V16 16
#define REG_V17 17
#define REG_V18 18
#define REG_V19 19
#define REG_V20 20
#define REG_V21 21
#define REG_V22 22
#define REG_V23 23
#define REG_V24 24
#define REG_V25 25
#define REG_V26 26
#define REG_V27 27
#define REG_V28 28
#define REG_V29 29
#define REG_V30 30
#define REG_V31 31
#define REG_XSP 31
#define REG_ARG0 REG_X0
#define REG_ARG1 REG_X1
#define REG_ARG2 REG_X2
#define REG_ARG3 REG_X3
#define REG_CPUSTATE REG_X29
#define REG_TEMP REG_X7
#define REG_TEMP2 REG_X6
#define REG_V_TEMP REG_V0
#define CODEGEN_HOST_REGS 10
#define CODEGEN_HOST_FP_REGS 8
extern void *codegen_mem_load_byte;
extern void *codegen_mem_load_word;
extern void *codegen_mem_load_long;
extern void *codegen_mem_load_quad;
extern void *codegen_mem_load_single;
extern void *codegen_mem_load_double;
extern void *codegen_mem_store_byte;
extern void *codegen_mem_store_word;
extern void *codegen_mem_store_long;
extern void *codegen_mem_store_quad;
extern void *codegen_mem_store_single;
extern void *codegen_mem_store_double;
extern void *codegen_fp_round;
extern void *codegen_fp_round_quad;
extern void *codegen_gpf_rout;
extern void *codegen_exit_rout;

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,264 @@
void host_arm64_ADD_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data);
void host_arm64_ADD_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift);
void host_arm64_ADD_REG_LSR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift);
void host_arm64_ADD_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_ADD_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_ADD_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_ADDX_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint64_t imm_data);
void host_arm64_ADDP_V4S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_ADR(codeblock_t *block, int dst_reg, int offset);
void host_arm64_AND_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data);
void host_arm64_AND_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift);
void host_arm64_AND_REG_ASR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift);
void host_arm64_AND_REG_ROR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift);
void host_arm64_AND_REG_V(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_ANDS_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data);
void host_arm64_ASR(codeblock_t *block, int dst_reg, int src_n_reg, int shift_reg);
void host_arm64_B(codeblock_t *block, void *dest);
void host_arm64_BFI(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width);
void host_arm64_BLR(codeblock_t *block, int addr_reg);
void host_arm64_BEQ(codeblock_t *block, void *dest);
uint32_t *host_arm64_BCC_(codeblock_t *block);
uint32_t *host_arm64_BCS_(codeblock_t *block);
uint32_t *host_arm64_BEQ_(codeblock_t *block);
uint32_t *host_arm64_BGE_(codeblock_t *block);
uint32_t *host_arm64_BGT_(codeblock_t *block);
uint32_t *host_arm64_BHI_(codeblock_t *block);
uint32_t *host_arm64_BLE_(codeblock_t *block);
uint32_t *host_arm64_BLS_(codeblock_t *block);
uint32_t *host_arm64_BLT_(codeblock_t *block);
uint32_t *host_arm64_BMI_(codeblock_t *block);
uint32_t *host_arm64_BNE_(codeblock_t *block);
uint32_t *host_arm64_BPL_(codeblock_t *block);
uint32_t *host_arm64_BVC_(codeblock_t *block);
uint32_t *host_arm64_BVS_(codeblock_t *block);
void host_arm64_branch_set_offset(uint32_t *opcode, void *dest);
void host_arm64_BR(codeblock_t *block, int addr_reg);
void host_arm64_BIC_REG_V(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_CBNZ(codeblock_t *block, int reg, uintptr_t dest);
void host_arm64_CMEQ_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_CMEQ_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_CMEQ_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_CMGT_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_CMGT_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_CMGT_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_CMN_IMM(codeblock_t *block, int src_n_reg, uint32_t imm_data);
void host_arm64_CMNX_IMM(codeblock_t *block, int src_n_reg, uint64_t imm_data);
void host_arm64_CMP_IMM(codeblock_t *block, int src_n_reg, uint32_t imm_data);
void host_arm64_CMPX_IMM(codeblock_t *block, int src_n_reg, uint64_t imm_data);
#define host_arm64_CMP_REG(block, src_n_reg, src_m_reg) host_arm64_CMP_REG_LSL(block, src_n_reg, src_m_reg, 0)
void host_arm64_CMP_REG_LSL(codeblock_t *block, int src_n_reg, int src_m_reg, int shift);
void host_arm64_CSEL_CC(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_CSEL_EQ(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_CSEL_VS(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_DUP_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int element);
void host_arm64_EOR_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data);
void host_arm64_EOR_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift);
void host_arm64_EOR_REG_V(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_FABS_D(codeblock_t *block, int dst_reg, int src_reg);
void host_arm64_FADD_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_FADD_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_FCMEQ_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_FCMGE_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_FCMGT_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_FCMP_D(codeblock_t *block, int src_n_reg, int src_m_reg);
void host_arm64_FDIV_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_FDIV_S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_FMAX_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_FMIN_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_FMUL_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_FMUL_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_FSUB_D(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_FSUB_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_FCVT_D_S(codeblock_t *block, int dst_reg, int src_reg);
void host_arm64_FCVT_S_D(codeblock_t *block, int dst_reg, int src_reg);
void host_arm64_FCVTMS_W_D(codeblock_t *block, int dst_reg, int src_reg);
void host_arm64_FCVTMS_X_D(codeblock_t *block, int dst_reg, int src_reg);
void host_arm64_FCVTNS_W_D(codeblock_t *block, int dst_reg, int src_reg);
void host_arm64_FCVTNS_X_D(codeblock_t *block, int dst_reg, int src_reg);
void host_arm64_FCVTPS_W_D(codeblock_t *block, int dst_reg, int src_reg);
void host_arm64_FCVTPS_X_D(codeblock_t *block, int dst_reg, int src_reg);
void host_arm64_FCVTZS_W_D(codeblock_t *block, int dst_reg, int src_reg);
void host_arm64_FCVTZS_X_D(codeblock_t *block, int dst_reg, int src_reg);
void host_arm64_FCVTZS_V2S(codeblock_t *block, int dst_reg, int src_reg);
void host_arm64_FMOV_D_D(codeblock_t *block, int dst_reg, int src_reg);
void host_arm64_FMOV_D_Q(codeblock_t *block, int dst_reg, int src_reg);
void host_arm64_FMOV_Q_D(codeblock_t *block, int dst_reg, int src_reg);
void host_arm64_FMOV_S_W(codeblock_t *block, int dst_reg, int src_reg);
void host_arm64_FMOV_W_S(codeblock_t *block, int dst_reg, int src_reg);
void host_arm64_FMOV_S_ONE(codeblock_t *block, int dst_reg);
void host_arm64_FNEG_D(codeblock_t *block, int dst_reg, int src_reg);
void host_arm64_FRINTX_D(codeblock_t *block, int dst_reg, int src_reg);
void host_arm64_FSQRT_D(codeblock_t *block, int dst_reg, int src_reg);
void host_arm64_FSQRT_S(codeblock_t *block, int dst_reg, int src_reg);
void host_arm64_LDP_POSTIDX_X(codeblock_t *block, int src_reg1, int src_reg2, int base_reg, int offset);
void host_arm64_LDR_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int offset);
void host_arm64_LDR_IMM_X(codeblock_t *block, int dest_reg, int base_reg, int offset);
void host_arm64_LDR_REG(codeblock_t *block, int dest_reg, int base_reg, int offset_reg);
void host_arm64_LDR_REG_X(codeblock_t *block, int dest_reg, int base_reg, int offset_reg);
void host_arm64_LDR_REG_F32(codeblock_t *block, int dest_reg, int base_reg, int offset_reg);
void host_arm64_LDR_IMM_F64(codeblock_t *block, int dest_reg, int base_reg, int offset);
void host_arm64_LDR_REG_F64(codeblock_t *block, int dest_reg, int base_reg, int offset_reg);
void host_arm64_LDR_REG_F64_S(codeblock_t *block, int dest_reg, int base_reg, int offset_reg);
void host_arm64_LDRB_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int offset);
void host_arm64_LDRB_REG(codeblock_t *block, int dest_reg, int base_reg, int offset_reg);
void host_arm64_LDRH_IMM(codeblock_t *block, int dest_reg, int base_reg, int offset);
void host_arm64_LDRH_REG(codeblock_t *block, int dest_reg, int base_reg, int offset_reg);
void host_arm64_LDRX_REG_LSL3(codeblock_t *block, int dest_reg, int base_reg, int offset_reg);
void host_arm64_LSL(codeblock_t *block, int dst_reg, int src_n_reg, int shift_reg);
void host_arm64_LSR(codeblock_t *block, int dst_reg, int src_n_reg, int shift_reg);
void host_arm64_MOV_REG_ASR(codeblock_t *block, int dst_reg, int src_m_reg, int shift);
void host_arm64_MOV_REG(codeblock_t *block, int dst_reg, int src_m_reg, int shift);
void host_arm64_MOV_REG_LSR(codeblock_t *block, int dst_reg, int src_m_reg, int shift);
void host_arm64_MOV_REG_ROR(codeblock_t *block, int dst_reg, int src_m_reg, int shift);
void host_arm64_MOVX_IMM(codeblock_t *block, int reg, uint64_t imm_data);
void host_arm64_MOVX_REG(codeblock_t *block, int dst_reg, int src_m_reg, int shift);
void host_arm64_MOVZ_IMM(codeblock_t *block, int reg, uint32_t imm_data);
void host_arm64_MOVK_IMM(codeblock_t *block, int reg, uint32_t imm_data);
void host_arm64_MSR_FPCR(codeblock_t *block, int src_reg);
void host_arm64_MUL_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_NOP(codeblock_t *block);
void host_arm64_ORR_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data);
void host_arm64_ORR_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift);
void host_arm64_ORR_REG_V(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_RET(codeblock_t *block, int reg);
void host_arm64_ROR(codeblock_t *block, int dst_reg, int src_n_reg, int shift_reg);
void host_arm64_SADDLP_V2S_4H(codeblock_t *block, int dst_reg, int src_n_reg);
void host_arm64_SBFX(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width);
void host_arm64_SCVTF_D_Q(codeblock_t *block, int dst_reg, int src_reg);
void host_arm64_SCVTF_D_W(codeblock_t *block, int dst_reg, int src_reg);
void host_arm64_SCVTF_V2S(codeblock_t *block, int dst_reg, int src_reg);
void host_arm64_SQADD_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_SQADD_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_SQSUB_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_SQSUB_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_SQXTN_V8B_8H(codeblock_t *block, int dst_reg, int src_reg);
void host_arm64_SQXTN_V4H_4S(codeblock_t *block, int dst_reg, int src_reg);
void host_arm64_SHL_V4H(codeblock_t *block, int dst_reg, int src_reg, int shift);
void host_arm64_SHL_V2S(codeblock_t *block, int dst_reg, int src_reg, int shift);
void host_arm64_SHL_V2D(codeblock_t *block, int dst_reg, int src_reg, int shift);
void host_arm64_SHRN_V4H_4S(codeblock_t *block, int dst_reg, int src_n_reg, int shift);
void host_arm64_SMULL_V4S_4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_SSHR_V4H(codeblock_t *block, int dst_reg, int src_reg, int shift);
void host_arm64_SSHR_V2S(codeblock_t *block, int dst_reg, int src_reg, int shift);
void host_arm64_SSHR_V2D(codeblock_t *block, int dst_reg, int src_reg, int shift);
void host_arm64_STP_PREIDX_X(codeblock_t *block, int src_reg1, int src_reg2, int base_reg, int offset);
void host_arm64_STR_IMM_W(codeblock_t *block, int dest_reg, int base_reg, int offset);
void host_arm64_STR_IMM_Q(codeblock_t *block, int dest_reg, int base_reg, int offset);
void host_arm64_STR_REG(codeblock_t *block, int src_reg, int base_reg, int offset_reg);
void host_arm64_STR_REG_F32(codeblock_t *block, int src_reg, int base_reg, int offset_reg);
void host_arm64_STR_IMM_F64(codeblock_t *block, int src_reg, int base_reg, int offset);
void host_arm64_STR_REG_F64(codeblock_t *block, int src_reg, int base_reg, int offset_reg);
void host_arm64_STR_REG_F64_S(codeblock_t *block, int src_reg, int base_reg, int offset_reg);
void host_arm64_STRB_IMM(codeblock_t *block, int dest_reg, int base_reg, int offset);
void host_arm64_STRB_REG(codeblock_t *block, int src_reg, int base_reg, int offset_reg);
void host_arm64_STRH_IMM(codeblock_t *block, int dest_reg, int base_reg, int offset);
void host_arm64_STRH_REG(codeblock_t *block, int src_reg, int base_reg, int offset_reg);
void host_arm64_SUB_IMM(codeblock_t *block, int dst_reg, int src_n_reg, uint32_t imm_data);
void host_arm64_SUB_REG(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift);
void host_arm64_SUB_REG_LSR(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg, int shift);
void host_arm64_SUB_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_SUB_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_SUB_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
uint32_t *host_arm64_TBNZ(codeblock_t *block, int reg, int bit);
#define host_arm64_TST_IMM(block, src_n_reg, imm_data) host_arm64_ANDS_IMM(block, REG_XZR, src_n_reg, imm_data)
void host_arm64_UBFX(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width);
void host_arm64_UQADD_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_UQADD_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_UQSUB_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_UQSUB_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_UQXTN_V8B_8H(codeblock_t *block, int dst_reg, int src_reg);
void host_arm64_UQXTN_V4H_4S(codeblock_t *block, int dst_reg, int src_reg);
void host_arm64_USHR_V4H(codeblock_t *block, int dst_reg, int src_reg, int shift);
void host_arm64_USHR_V2S(codeblock_t *block, int dst_reg, int src_reg, int shift);
void host_arm64_USHR_V2D(codeblock_t *block, int dst_reg, int src_reg, int shift);
void host_arm64_ZIP1_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_ZIP1_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_ZIP1_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_ZIP2_V8B(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_ZIP2_V4H(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_ZIP2_V2S(codeblock_t *block, int dst_reg, int src_n_reg, int src_m_reg);
void host_arm64_call(codeblock_t *block, void *dst_addr);
void host_arm64_jump(codeblock_t *block, uintptr_t dst_addr);
void host_arm64_mov_imm(codeblock_t *block, int reg, uint32_t imm_data);
#define in_range7_x(offset) (((offset) >= -0x200) && ((offset) < (0x200)) && !((offset) & 7))
#define in_range12_b(offset) (((offset) >= 0) && ((offset) < 0x1000))
#define in_range12_h(offset) (((offset) >= 0) && ((offset) < 0x2000) && !((offset) & 1))
#define in_range12_w(offset) (((offset) >= 0) && ((offset) < 0x4000) && !((offset) & 3))
#define in_range12_q(offset) (((offset) >= 0) && ((offset) < 0x8000) && !((offset) & 7))
void codegen_direct_read_8(codeblock_t *block, int host_reg, void *p);
void codegen_alloc(codeblock_t *block, int size);

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,89 @@
#define REG_R0 0
#define REG_R1 1
#define REG_R2 2
#define REG_R3 3
#define REG_R4 4
#define REG_R5 5
#define REG_R6 6
#define REG_R7 7
#define REG_R8 8
#define REG_R9 9
#define REG_R10 10
#define REG_R11 11
#define REG_R12 12
#define REG_HOST_SP 13
#define REG_LR 14
#define REG_PC 15
#define REG_ARG0 REG_R0
#define REG_ARG1 REG_R1
#define REG_ARG2 REG_R2
#define REG_ARG3 REG_R3
#define REG_CPUSTATE REG_R10
#define REG_TEMP REG_R3
#define REG_TEMP2 REG_R2
#define REG_D0 0
#define REG_D1 1
#define REG_D2 2
#define REG_D3 3
#define REG_D4 4
#define REG_D5 5
#define REG_D6 6
#define REG_D7 7
#define REG_D8 8
#define REG_D9 9
#define REG_D10 10
#define REG_D11 11
#define REG_D12 12
#define REG_D13 13
#define REG_D14 14
#define REG_D15 15
#define REG_D_TEMP REG_D0
#define REG_Q_TEMP REG_D0
#define REG_Q_TEMP_2 REG_D2
#define REG_MASK_R0 (1 << REG_R0)
#define REG_MASK_R1 (1 << REG_R1)
#define REG_MASK_R2 (1 << REG_R2)
#define REG_MASK_R3 (1 << REG_R3)
#define REG_MASK_R4 (1 << REG_R4)
#define REG_MASK_R5 (1 << REG_R5)
#define REG_MASK_R6 (1 << REG_R6)
#define REG_MASK_R7 (1 << REG_R7)
#define REG_MASK_R8 (1 << REG_R8)
#define REG_MASK_R9 (1 << REG_R9)
#define REG_MASK_R10 (1 << REG_R10)
#define REG_MASK_R11 (1 << REG_R11)
#define REG_MASK_R12 (1 << REG_R12)
#define REG_MASK_SP (1 << REG_HOST_SP)
#define REG_MASK_LR (1 << REG_LR)
#define REG_MASK_PC (1 << REG_PC)
#define REG_MASK_LOCAL (REG_MASK_R4 | REG_MASK_R5 | REG_MASK_R6 | REG_MASK_R7 | \
REG_MASK_R8 | REG_MASK_R9 | REG_MASK_R10 | REG_MASK_R11)
#define CODEGEN_HOST_REGS 7
#define CODEGEN_HOST_FP_REGS 8
extern void *codegen_mem_load_byte;
extern void *codegen_mem_load_word;
extern void *codegen_mem_load_long;
extern void *codegen_mem_load_quad;
extern void *codegen_mem_load_single;
extern void *codegen_mem_load_double;
extern void *codegen_mem_store_byte;
extern void *codegen_mem_store_word;
extern void *codegen_mem_store_long;
extern void *codegen_mem_store_quad;
extern void *codegen_mem_store_single;
extern void *codegen_mem_store_double;
extern void *codegen_fp_round;
extern void *codegen_gpf_rout;
extern void *codegen_exit_rout;

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,252 @@
#define COND_SHIFT 28
#define COND_EQ (0x0 << COND_SHIFT)
#define COND_NE (0x1 << COND_SHIFT)
#define COND_CS (0x2 << COND_SHIFT)
#define COND_CC (0x3 << COND_SHIFT)
#define COND_MI (0x4 << COND_SHIFT)
#define COND_PL (0x5 << COND_SHIFT)
#define COND_VS (0x6 << COND_SHIFT)
#define COND_VC (0x7 << COND_SHIFT)
#define COND_HI (0x8 << COND_SHIFT)
#define COND_LS (0x9 << COND_SHIFT)
#define COND_GE (0xa << COND_SHIFT)
#define COND_LT (0xb << COND_SHIFT)
#define COND_GT (0xc << COND_SHIFT)
#define COND_LE (0xd << COND_SHIFT)
#define COND_AL (0xe << COND_SHIFT)
void host_arm_ADD_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm);
#define host_arm_ADD_REG(block, dst_reg, src_reg_n, src_reg_m) host_arm_ADD_REG_LSL(block, dst_reg, src_reg_n, src_reg_m, 0)
void host_arm_ADD_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift);
void host_arm_ADD_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift);
void host_arm_AND_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm);
void host_arm_AND_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift);
void host_arm_AND_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift);
void host_arm_B(codeblock_t *block, uintptr_t dest_addr);
void host_arm_BFI(codeblock_t *block, int dst_reg, int src_reg, int lsb, int width);
void host_arm_BIC_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm);
void host_arm_BIC_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift);
void host_arm_BIC_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift);
void host_arm_BL(codeblock_t *block, uintptr_t dest_addr);
void host_arm_BL_r1(codeblock_t *block, uintptr_t dest_addr);
void host_arm_BLX(codeblock_t *block, int addr_reg);
uint32_t *host_arm_BCC_(codeblock_t *block);
uint32_t *host_arm_BCS_(codeblock_t *block);
uint32_t *host_arm_BEQ_(codeblock_t *block);
uint32_t *host_arm_BGE_(codeblock_t *block);
uint32_t *host_arm_BGT_(codeblock_t *block);
uint32_t *host_arm_BHI_(codeblock_t *block);
uint32_t *host_arm_BLE_(codeblock_t *block);
uint32_t *host_arm_BLS_(codeblock_t *block);
uint32_t *host_arm_BLT_(codeblock_t *block);
uint32_t *host_arm_BMI_(codeblock_t *block);
uint32_t *host_arm_BNE_(codeblock_t *block);
uint32_t *host_arm_BPL_(codeblock_t *block);
uint32_t *host_arm_BVC_(codeblock_t *block);
uint32_t *host_arm_BVS_(codeblock_t *block);
void host_arm_BEQ(codeblock_t *block, uintptr_t dest_addr);
void host_arm_BNE(codeblock_t *block, uintptr_t dest_addr);
void host_arm_BX(codeblock_t *block, int addr_reg);
void host_arm_CMN_IMM(codeblock_t *block, int src_reg, uint32_t imm);
void host_arm_CMN_REG_LSL(codeblock_t *block, int src_reg_n, int src_reg_m, int shift);
void host_arm_CMP_IMM(codeblock_t *block, int src_reg, uint32_t imm);
#define host_arm_CMP_REG(block, src_reg_n, src_reg_m) host_arm_CMP_REG_LSL(block, src_reg_n, src_reg_m, 0)
void host_arm_CMP_REG_LSL(codeblock_t *block, int src_reg_n, int src_reg_m, int shift);
void host_arm_EOR_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm);
void host_arm_EOR_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift);
void host_arm_LDMIA_WB(codeblock_t *block, int addr_reg, uint32_t reg_mask);
void host_arm_LDR_IMM(codeblock_t *block, int dst_reg, int addr_reg, int offset);
void host_arm_LDR_IMM_POST(codeblock_t *block, int dst_reg, int addr_reg, int offset);
#define host_arm_LDR_REG(block, dst_reg, addr_reg, offset_reg) host_arm_LDR_REG_LSL(block, dst_reg, addr_reg, offset_reg, 0)
void host_arm_LDR_REG_LSL(codeblock_t *block, int dst_reg, int addr_reg, int offset_reg, int shift);
void host_arm_LDRB_ABS(codeblock_t *block, int dst, void *p);
void host_arm_LDRB_IMM(codeblock_t *block, int dst_reg, int addr_reg, int offset);
#define host_arm_LDRB_REG(block, dst_reg, addr_reg, offset_reg) host_arm_LDRB_REG_LSL(block, dst_reg, addr_reg, offset_reg, 0)
void host_arm_LDRB_REG_LSL(codeblock_t *block, int dst_reg, int addr_reg, int offset_reg, int shift);
void host_arm_LDRH_IMM(codeblock_t *block, int dst_reg, int addr_reg, int offset);
void host_arm_LDRH_REG(codeblock_t *block, int dst_reg, int addr_reg, int offset_reg);
void host_arm_MOV_IMM(codeblock_t *block, int dst_reg, uint32_t imm);
#define host_arm_MOV_REG(block, dst_reg, src_reg) host_arm_MOV_REG_LSL(block, dst_reg, src_reg, 0)
void host_arm_MOV_REG_ASR(codeblock_t *block, int dst_reg, int src_reg, int shift);
void host_arm_MOV_REG_ASR_REG(codeblock_t *block, int dst_reg, int src_reg, int shift_reg);
void host_arm_MOV_REG_LSL(codeblock_t *block, int dst_reg, int src_reg, int shift);
void host_arm_MOV_REG_LSL_REG(codeblock_t *block, int dst_reg, int src_reg, int shift_reg);
void host_arm_MOV_REG_LSR(codeblock_t *block, int dst_reg, int src_reg, int shift);
void host_arm_MOV_REG_LSR_REG(codeblock_t *block, int dst_reg, int src_reg, int shift_reg);
void host_arm_MOV_REG_ROR(codeblock_t *block, int dst_reg, int src_reg, int shift);
void host_arm_MOV_REG_ROR_REG(codeblock_t *block, int dst_reg, int src_reg, int shift_reg);
void host_arm_MOVT_IMM(codeblock_t *block, int dst_reg, uint16_t imm);
void host_arm_MOVW_IMM(codeblock_t *block, int dst_reg, uint16_t imm);
void host_arm_MVN_REG_LSL(codeblock_t *block, int dst_reg, int src_reg, int shift);
#define host_arm_NOP(block) host_arm_MOV_REG(block, REG_R0, REG_R0)
void host_arm_ORR_IMM_cond(codeblock_t *block, uint32_t cond, int dst_reg, int src_reg, uint32_t imm);
void host_arm_ORR_REG_LSL_cond(codeblock_t *block, uint32_t cond, int dst_reg, int src_reg_n, int src_reg_m, int shift);
#define host_arm_ORR_IMM(block, dst_reg, src_reg, imm) host_arm_ORR_IMM_cond(block, COND_AL, dst_reg, src_reg, imm)
#define host_arm_ORR_REG_LSL(block, dst_reg, src_reg_a, src_reg_b, shift) host_arm_ORR_REG_LSL_cond(block, COND_AL, dst_reg, src_reg_a, src_reg_b, shift)
#define host_arm_ORRCC_IMM(block, dst_reg, src_reg, imm) host_arm_ORR_IMM_cond(block, COND_CC, dst_reg, src_reg, imm)
#define host_arm_ORREQ_IMM(block, dst_reg, src_reg, imm) host_arm_ORR_IMM_cond(block, COND_EQ, dst_reg, src_reg, imm)
#define host_arm_ORRVS_IMM(block, dst_reg, src_reg, imm) host_arm_ORR_IMM_cond(block, COND_VS, dst_reg, src_reg, imm)
void host_arm_RSB_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm);
void host_arm_RSB_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift);
void host_arm_RSB_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift);
void host_arm_STMDB_WB(codeblock_t *block, int addr_reg, uint32_t reg_mask);
void host_arm_STR_IMM(codeblock_t *block, int src_reg, int addr_reg, int offset);
void host_arm_STR_IMM_WB(codeblock_t *block, int src_reg, int addr_reg, int offset);
#define host_arm_STR_REG(block, src_reg, addr_reg, offset_reg) host_arm_STR_REG_LSL(block, src_reg, addr_reg, offset_reg, 0)
void host_arm_STR_REG_LSL(codeblock_t *block, int src_reg, int addr_reg, int offset_reg, int shift);
void host_arm_STRB_IMM(codeblock_t *block, int src_reg, int addr_reg, int offset);
#define host_arm_STRB_REG(block, src_reg, addr_reg, offset_reg) host_arm_STRB_REG_LSL(block, src_reg, addr_reg, offset_reg, 0)
void host_arm_STRB_REG_LSL(codeblock_t *block, int src_reg, int addr_reg, int offset_reg, int shift);
void host_arm_STRH_IMM(codeblock_t *block, int src_reg, int addr_reg, int offset);
void host_arm_STRH_REG(codeblock_t *block, int src_reg, int addr_reg, int offset_reg);
void host_arm_SUB_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t imm);
void host_arm_SUB_REG_LSL(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift);
void host_arm_SUB_REG_LSR(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m, int shift);
void host_arm_SXTB(codeblock_t *block, int dst_reg, int src_reg, int rotate);
void host_arm_SXTH(codeblock_t *block, int dst_reg, int src_reg, int rotate);
void host_arm_TST_IMM(codeblock_t *block, int src_reg1, uint32_t imm);
void host_arm_TST_REG(codeblock_t *block, int src_reg1, int src_reg2);
void host_arm_UADD8(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
void host_arm_UADD16(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
void host_arm_USUB8(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
void host_arm_USUB16(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
void host_arm_UXTB(codeblock_t *block, int dst_reg, int src_reg, int rotate);
void host_arm_UXTH(codeblock_t *block, int dst_reg, int src_reg, int rotate);
void host_arm_VABS_D(codeblock_t *block, int dest_reg, int src_reg);
void host_arm_VADD_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VADD_I8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VADD_I16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VADD_I32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VADD_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VAND_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VBIC_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VCMP_D(codeblock_t *block, int src_reg_d, int src_reg_m);
void host_arm_VCEQ_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VCEQ_I8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VCEQ_I16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VCEQ_I32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VCGE_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VCGT_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VCGT_S8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VCGT_S16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VCGT_S32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VCHS_D(codeblock_t *block, int dest_reg, int src_reg);
void host_arm_VCVT_D_IS(codeblock_t *block, int dest_reg, int src_reg);
void host_arm_VCVT_D_S(codeblock_t *block, int dest_reg, int src_reg);
void host_arm_VCVT_F32_S32(codeblock_t *block, int dest_reg, int src_reg);
void host_arm_VCVT_IS_D(codeblock_t *block, int dest_reg, int src_reg);
void host_arm_VCVT_S32_F32(codeblock_t *block, int dest_reg, int src_reg);
void host_arm_VCVT_S_D(codeblock_t *block, int dest_reg, int src_reg);
void host_arm_VCVTR_IS_D(codeblock_t *block, int dest_reg, int src_reg);
void host_arm_VDIV_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VDIV_S(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VDUP_32(codeblock_t *block, int dst_reg, int src_reg_m, int imm);
void host_arm_VEOR_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VLDR_D(codeblock_t *block, int dest_reg, int base_reg, int offset);
void host_arm_VLDR_S(codeblock_t *block, int dest_reg, int base_reg, int offset);
void host_arm_VMOV_32_S(codeblock_t *block, int dest_reg, int src_reg);
void host_arm_VMOV_64_D(codeblock_t *block, int dest_reg_low, int dest_reg_high, int src_reg);
void host_arm_VMOV_D_64(codeblock_t *block, int dest_reg, int src_reg_low, int src_reg_high);
void host_arm_VMOV_S_32(codeblock_t *block, int dest_reg, int src_reg);
void host_arm_VMOV_D_D(codeblock_t *block, int dest_reg, int src_reg);
void host_arm_VMOVN_I32(codeblock_t *block, int dest_reg, int src_reg);
void host_arm_VMOVN_I64(codeblock_t *block, int dest_reg, int src_reg);
void host_arm_VMRS_APSR(codeblock_t *block);
void host_arm_VMSR_FPSCR(codeblock_t *block, int src_reg);
void host_arm_VMAX_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VMIN_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VMOV_F32_ONE(codeblock_t *block, int dst_reg);
void host_arm_VMUL_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VMUL_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VMUL_S16(codeblock_t *block, int dest_reg, int src_reg_n, int src_reg_m);
void host_arm_VMULL_S16(codeblock_t *block, int dest_reg, int src_reg_n, int src_reg_m);
void host_arm_VNEG_D(codeblock_t *block, int dest_reg, int src_reg);
void host_arm_VORR_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VPADDL_S16(codeblock_t *block, int dst_reg, int src_reg);
void host_arm_VPADDL_S32(codeblock_t *block, int dst_reg, int src_reg);
void host_arm_VPADDL_Q_S32(codeblock_t *block, int dst_reg, int src_reg);
void host_arm_VQADD_S8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VQADD_U8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VQADD_S16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VQADD_U16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VQSUB_S8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VQSUB_U8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VQSUB_S16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VQSUB_U16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VQMOVN_S16(codeblock_t *block, int dst_reg, int src_reg);
void host_arm_VQMOVN_S32(codeblock_t *block, int dst_reg, int src_reg);
void host_arm_VQMOVN_U16(codeblock_t *block, int dst_reg, int src_reg);
void host_arm_VSHL_D_IMM_16(codeblock_t *block, int dest_reg, int src_reg, int shift);
void host_arm_VSHL_D_IMM_32(codeblock_t *block, int dest_reg, int src_reg, int shift);
void host_arm_VSHL_D_IMM_64(codeblock_t *block, int dest_reg, int src_reg, int shift);
void host_arm_VSHR_D_S16(codeblock_t *block, int dest_reg, int src_reg, int shift);
void host_arm_VSHR_D_S32(codeblock_t *block, int dest_reg, int src_reg, int shift);
void host_arm_VSHR_D_S64(codeblock_t *block, int dest_reg, int src_reg, int shift);
void host_arm_VSHR_D_U16(codeblock_t *block, int dest_reg, int src_reg, int shift);
void host_arm_VSHR_D_U32(codeblock_t *block, int dest_reg, int src_reg, int shift);
void host_arm_VSHR_D_U64(codeblock_t *block, int dest_reg, int src_reg, int shift);
void host_arm_VSHRN_32(codeblock_t *block, int dest_reg, int src_reg, int shift);
void host_arm_VSQRT_D(codeblock_t *block, int dest_reg, int src_reg);
void host_arm_VSQRT_S(codeblock_t *block, int dest_reg, int src_reg);
void host_arm_VSTR_D(codeblock_t *block, int src_reg, int base_reg, int offset);
void host_arm_VSTR_S(codeblock_t *block, int src_reg, int base_reg, int offset);
void host_arm_VSUB_D(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VSUB_F32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VSUB_S(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VSUB_I8(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VSUB_I16(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VSUB_I32(codeblock_t *block, int dst_reg, int src_reg_n, int src_reg_m);
void host_arm_VZIP_D8(codeblock_t *block, int d_reg, int m_reg);
void host_arm_VZIP_D16(codeblock_t *block, int d_reg, int m_reg);
void host_arm_VZIP_D32(codeblock_t *block, int d_reg, int m_reg);

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,376 @@
#ifdef __amd64__
#include "ibm.h"
#include "codegen.h"
#include "codegen_allocator.h"
#include "codegen_backend.h"
#include "codegen_backend_x86-64_defs.h"
#include "codegen_backend_x86-64_ops.h"
#include "codegen_backend_x86-64_ops_sse.h"
#include "codegen_reg.h"
#include "x86.h"
#if defined(__linux__) || defined(__APPLE__)
#include <sys/mman.h>
#include <unistd.h>
#endif
#if defined WIN32 || defined _WIN32 || defined _WIN32
#include <windows.h>
#endif
void *codegen_mem_load_byte;
void *codegen_mem_load_word;
void *codegen_mem_load_long;
void *codegen_mem_load_quad;
void *codegen_mem_load_single;
void *codegen_mem_load_double;
void *codegen_mem_store_byte;
void *codegen_mem_store_word;
void *codegen_mem_store_long;
void *codegen_mem_store_quad;
void *codegen_mem_store_single;
void *codegen_mem_store_double;
void *codegen_gpf_rout;
void *codegen_exit_rout;
int codegen_host_reg_list[CODEGEN_HOST_REGS] =
{
REG_EAX,
REG_EBX,
REG_EDX
};
int codegen_host_fp_reg_list[CODEGEN_HOST_FP_REGS] =
{
REG_XMM0,
REG_XMM1,
REG_XMM2,
REG_XMM3,
REG_XMM4,
REG_XMM5,
REG_XMM6
};
static void build_load_routine(codeblock_t *block, int size, int is_float)
{
uint8_t *branch_offset;
uint8_t *misaligned_offset;
/*In - ESI = address
Out - ECX = data, ESI = abrt*/
/*MOV ECX, ESI
SHR ESI, 12
MOV RSI, [readlookup2+ESI*4]
CMP ESI, -1
JNZ +
MOVZX ECX, B[RSI+RCX]
XOR ESI,ESI
RET
* PUSH EAX
PUSH EDX
PUSH ECX
CALL readmembl
POP ECX
POP EDX
POP EAX
MOVZX ECX, AL
RET
*/
host_x86_MOV32_REG_REG(block, REG_ECX, REG_ESI);
host_x86_SHR32_IMM(block, REG_ESI, 12);
host_x86_MOV64_REG_IMM(block, REG_RDI, (uint64_t)(uintptr_t)readlookup2);
host_x86_MOV64_REG_BASE_INDEX_SHIFT(block, REG_RSI, REG_RDI, REG_RSI, 3);
if (size != 1)
{
host_x86_TEST32_REG_IMM(block, REG_ECX, size-1);
misaligned_offset = host_x86_JNZ_short(block);
}
host_x86_CMP64_REG_IMM(block, REG_RSI, (uint32_t)-1);
branch_offset = host_x86_JZ_short(block);
if (size == 1 && !is_float)
host_x86_MOVZX_BASE_INDEX_32_8(block, REG_ECX, REG_RSI, REG_RCX);
else if (size == 2 && !is_float)
host_x86_MOVZX_BASE_INDEX_32_16(block, REG_ECX, REG_RSI, REG_RCX);
else if (size == 4 && !is_float)
host_x86_MOV32_REG_BASE_INDEX(block, REG_ECX, REG_RSI, REG_RCX);
else if (size == 4 && is_float)
host_x86_CVTSS2SD_XREG_BASE_INDEX(block, REG_XMM_TEMP, REG_RSI, REG_RCX);
else if (size == 8)
host_x86_MOVQ_XREG_BASE_INDEX(block, REG_XMM_TEMP, REG_RSI, REG_RCX);
else
fatal("build_load_routine: size=%i\n", size);
host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI);
host_x86_RET(block);
*branch_offset = (uint8_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 1;
if (size != 1)
*misaligned_offset = (uint8_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)misaligned_offset) - 1;
host_x86_PUSH(block, REG_RAX);
host_x86_PUSH(block, REG_RDX);
#if WIN64
host_x86_SUB64_REG_IMM(block, REG_RSP, 0x20);
//host_x86_MOV32_REG_REG(block, REG_ECX, uop->imm_data);
#else
host_x86_MOV32_REG_REG(block, REG_EDI, REG_ECX);
#endif
if (size == 1 && !is_float)
{
host_x86_CALL(block, (void *)readmembl);
host_x86_MOVZX_REG_32_8(block, REG_ECX, REG_EAX);
}
else if (size == 2 && !is_float)
{
host_x86_CALL(block, (void *)readmemwl);
host_x86_MOVZX_REG_32_16(block, REG_ECX, REG_EAX);
}
else if (size == 4 && !is_float)
{
host_x86_CALL(block, (void *)readmemll);
host_x86_MOV32_REG_REG(block, REG_ECX, REG_EAX);
}
else if (size == 4 && is_float)
{
host_x86_CALL(block, (void *)readmemll);
host_x86_MOVD_XREG_REG(block, REG_XMM_TEMP, REG_EAX);
host_x86_CVTSS2SD_XREG_XREG(block, REG_XMM_TEMP, REG_XMM_TEMP);
}
else if (size == 8)
{
host_x86_CALL(block, (void *)readmemql);
host_x86_MOVQ_XREG_REG(block, REG_XMM_TEMP, REG_RAX);
}
#if WIN64
host_x86_ADD64_REG_IMM(block, REG_RSP, 0x20);
#endif
host_x86_POP(block, REG_RDX);
host_x86_POP(block, REG_RAX);
host_x86_MOVZX_REG_ABS_32_8(block, REG_ESI, &cpu_state.abrt);
host_x86_RET(block);
}
static void build_store_routine(codeblock_t *block, int size, int is_float)
{
uint8_t *branch_offset;
uint8_t *misaligned_offset;
/*In - ECX = data, ESI = address
Out - ESI = abrt
Corrupts EDI*/
/*MOV EDI, ESI
SHR ESI, 12
MOV ESI, [writelookup2+ESI*4]
CMP ESI, -1
JNZ +
MOV [RSI+RDI], ECX
XOR ESI,ESI
RET
* PUSH EAX
PUSH EDX
PUSH ECX
CALL writemembl
POP ECX
POP EDX
POP EAX
MOVZX ECX, AL
RET
*/
host_x86_MOV32_REG_REG(block, REG_EDI, REG_ESI);
host_x86_SHR32_IMM(block, REG_ESI, 12);
host_x86_MOV64_REG_IMM(block, REG_R8, (uint64_t)(uintptr_t)writelookup2);
host_x86_MOV64_REG_BASE_INDEX_SHIFT(block, REG_RSI, REG_R8, REG_RSI, 3);
if (size != 1)
{
host_x86_TEST32_REG_IMM(block, REG_EDI, size-1);
misaligned_offset = host_x86_JNZ_short(block);
}
host_x86_CMP64_REG_IMM(block, REG_RSI, (uint32_t)-1);
branch_offset = host_x86_JZ_short(block);
if (size == 1 && !is_float)
host_x86_MOV8_BASE_INDEX_REG(block, REG_RSI, REG_RDI, REG_ECX);
else if (size == 2 && !is_float)
host_x86_MOV16_BASE_INDEX_REG(block, REG_RSI, REG_RDI, REG_ECX);
else if (size == 4 && !is_float)
host_x86_MOV32_BASE_INDEX_REG(block, REG_RSI, REG_RDI, REG_ECX);
else if (size == 4 && is_float)
host_x86_MOVD_BASE_INDEX_XREG(block, REG_RSI, REG_RDI, REG_XMM_TEMP);
else if (size == 8)
host_x86_MOVQ_BASE_INDEX_XREG(block, REG_RSI, REG_RDI, REG_XMM_TEMP);
else
fatal("build_store_routine: size=%i\n", size);
host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI);
host_x86_RET(block);
*branch_offset = (uint8_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 1;
if (size != 1)
*misaligned_offset = (uint8_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)misaligned_offset) - 1;
host_x86_PUSH(block, REG_RAX);
host_x86_PUSH(block, REG_RDX);
#if WIN64
host_x86_SUB64_REG_IMM(block, REG_RSP, 0x28);
if (size == 4 && is_float)
host_x86_MOVD_REG_XREG(block, REG_EDX, REG_XMM_TEMP); //data
else if (size == 8)
host_x86_MOVQ_REG_XREG(block, REG_RDX, REG_XMM_TEMP); //data
else
host_x86_MOV32_REG_REG(block, REG_EDX, REG_ECX); //data
host_x86_MOV32_REG_REG(block, REG_ECX, REG_EDI); //address
#else
host_x86_SUB64_REG_IMM(block, REG_RSP, 0x8);
//host_x86_MOV32_REG_REG(block, REG_EDI, REG_ECX); //address
if (size == 4 && is_float)
host_x86_MOVD_REG_XREG(block, REG_ESI, REG_XMM_TEMP); //data
else if (size == 8)
host_x86_MOVQ_REG_XREG(block, REG_RSI, REG_XMM_TEMP); //data
else
host_x86_MOV32_REG_REG(block, REG_ESI, REG_ECX); //data
#endif
if (size == 1)
host_x86_CALL(block, (void *)writemembl);
else if (size == 2)
host_x86_CALL(block, (void *)writememwl);
else if (size == 4)
host_x86_CALL(block, (void *)writememll);
else if (size == 8)
host_x86_CALL(block, (void *)writememql);
#if WIN64
host_x86_ADD64_REG_IMM(block, REG_RSP, 0x28);
#else
host_x86_ADD64_REG_IMM(block, REG_RSP, 0x8);
#endif
host_x86_POP(block, REG_RDX);
host_x86_POP(block, REG_RAX);
host_x86_MOVZX_REG_ABS_32_8(block, REG_ESI, &cpu_state.abrt);
host_x86_RET(block);
}
static void build_loadstore_routines(codeblock_t *block)
{
codegen_mem_load_byte = &codeblock[block_current].data[block_pos];
build_load_routine(block, 1, 0);
codegen_mem_load_word = &codeblock[block_current].data[block_pos];
build_load_routine(block, 2, 0);
codegen_mem_load_long = &codeblock[block_current].data[block_pos];
build_load_routine(block, 4, 0);
codegen_mem_load_quad = &codeblock[block_current].data[block_pos];
build_load_routine(block, 8, 0);
codegen_mem_load_single = &codeblock[block_current].data[block_pos];
build_load_routine(block, 4, 1);
codegen_mem_load_double = &codeblock[block_current].data[block_pos];
build_load_routine(block, 8, 1);
codegen_mem_store_byte = &codeblock[block_current].data[block_pos];
build_store_routine(block, 1, 0);
codegen_mem_store_word = &codeblock[block_current].data[block_pos];
build_store_routine(block, 2, 0);
codegen_mem_store_long = &codeblock[block_current].data[block_pos];
build_store_routine(block, 4, 0);
codegen_mem_store_quad = &codeblock[block_current].data[block_pos];
build_store_routine(block, 8, 0);
codegen_mem_store_single = &codeblock[block_current].data[block_pos];
build_store_routine(block, 4, 1);
codegen_mem_store_double = &codeblock[block_current].data[block_pos];
build_store_routine(block, 8, 1);
}
void codegen_backend_init()
{
codeblock_t *block;
int c;
#if defined(__linux__) || defined(__APPLE__)
void *start;
size_t len;
long pagesize = sysconf(_SC_PAGESIZE);
long pagemask = ~(pagesize - 1);
#endif
codeblock = malloc(BLOCK_SIZE * sizeof(codeblock_t));
codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *));
memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t));
memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *));
for (c = 0; c < BLOCK_SIZE; c++)
codeblock[c].pc = BLOCK_PC_INVALID;
// pclog("Codegen is %p\n", (void *)pages[0xfab12 >> 12].block);
block_current = 0;
block_pos = 0;
block = &codeblock[block_current];
codeblock[block_current].head_mem_block = codegen_allocator_allocate(NULL, block_current);
codeblock[block_current].data = codeblock_allocator_get_ptr(codeblock[block_current].head_mem_block);
block_write_data = codeblock[block_current].data;
build_loadstore_routines(&codeblock[block_current]);
codegen_gpf_rout = &codeblock[block_current].data[block_pos];
#if WIN64
host_x86_XOR32_REG_REG(block, REG_ECX, REG_ECX);
host_x86_XOR32_REG_REG(block, REG_EDX, REG_EDX);
#else
host_x86_XOR32_REG_REG(block, REG_EDI, REG_EDI);
host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI);
#endif
host_x86_CALL(block, (uintptr_t)x86gpf);
codegen_exit_rout = &codeblock[block_current].data[block_pos];
host_x86_ADD64_REG_IMM(block, REG_RSP, 0x38);
host_x86_POP(block, REG_R15);
host_x86_POP(block, REG_R14);
host_x86_POP(block, REG_R13);
host_x86_POP(block, REG_R12);
host_x86_POP(block, REG_RDI);
host_x86_POP(block, REG_RSI);
host_x86_POP(block, REG_RBP);
host_x86_POP(block, REG_RDX);
host_x86_RET(block);
block_write_data = NULL;
asm(
"stmxcsr %0\n"
: "=m" (cpu_state.old_fp_control)
);
cpu_state.trunc_fp_control = cpu_state.old_fp_control | 0x6000;
}
void codegen_set_rounding_mode(int mode)
{
cpu_state.new_fp_control = (cpu_state.old_fp_control & ~0x6000) | (mode << 13);
}
void codegen_backend_prologue(codeblock_t *block)
{
block_pos = BLOCK_START; /*Entry code*/
host_x86_PUSH(block, REG_RBX);
host_x86_PUSH(block, REG_RBP);
host_x86_PUSH(block, REG_RSI);
host_x86_PUSH(block, REG_RDI);
host_x86_PUSH(block, REG_R12);
host_x86_PUSH(block, REG_R13);
host_x86_PUSH(block, REG_R14);
host_x86_PUSH(block, REG_R15);
host_x86_SUB64_REG_IMM(block, REG_RSP, 0x38);
host_x86_MOV64_REG_IMM(block, REG_RBP, ((uintptr_t)&cpu_state) + 128);
if (block->flags & CODEBLOCK_HAS_FPU)
{
host_x86_MOV32_REG_ABS(block, REG_EAX, &cpu_state.TOP);
host_x86_SUB32_REG_IMM(block, REG_EAX, block->TOP);
host_x86_MOV32_BASE_OFFSET_REG(block, REG_RSP, IREG_TOP_diff_stack_offset, REG_EAX);
}
}
void codegen_backend_epilogue(codeblock_t *block)
{
host_x86_ADD64_REG_IMM(block, REG_RSP, 0x38);
host_x86_POP(block, REG_R15);
host_x86_POP(block, REG_R14);
host_x86_POP(block, REG_R13);
host_x86_POP(block, REG_R12);
host_x86_POP(block, REG_RDI);
host_x86_POP(block, REG_RSI);
host_x86_POP(block, REG_RBP);
host_x86_POP(block, REG_RDX);
host_x86_RET(block);
}
#endif

View file

@ -0,0 +1,12 @@
#include "codegen_backend_x86-64_defs.h"
#define BLOCK_SIZE 0x4000
#define BLOCK_MASK 0x3fff
#define BLOCK_START 0
#define HASH_SIZE 0x20000
#define HASH_MASK 0x1ffff
#define HASH(l) ((l) & 0x1ffff)
#define BLOCK_MAX 0x3c0

View file

@ -0,0 +1,65 @@
#define REG_AX 0
#define REG_CX 1
#define REG_DX 2
#define REG_BX 3
#define REG_SP 4
#define REG_BP 5
#define REG_SI 6
#define REG_DI 7
#define REG_EAX 0
#define REG_ECX 1
#define REG_EDX 2
#define REG_EBX 3
#define REG_ESP 4
#define REG_EBP 5
#define REG_ESI 6
#define REG_EDI 7
#define REG_RAX 0
#define REG_RCX 1
#define REG_RDX 2
#define REG_RBX 3
#define REG_RSP 4
#define REG_RBP 5
#define REG_RSI 6
#define REG_RDI 7
#define REG_R8 8
#define REG_R9 9
#define REG_R10 10
#define REG_R11 11
#define REG_R12 12
#define REG_R13 13
#define REG_R14 14
#define REG_R15 15
#define REG_XMM0 0
#define REG_XMM1 1
#define REG_XMM2 2
#define REG_XMM3 3
#define REG_XMM4 4
#define REG_XMM5 5
#define REG_XMM6 6
#define REG_XMM7 7
#define REG_XMM_TEMP REG_XMM7
#define CODEGEN_HOST_REGS 3
#define CODEGEN_HOST_FP_REGS 7
extern void *codegen_mem_load_byte;
extern void *codegen_mem_load_word;
extern void *codegen_mem_load_long;
extern void *codegen_mem_load_quad;
extern void *codegen_mem_load_single;
extern void *codegen_mem_load_double;
extern void *codegen_mem_store_byte;
extern void *codegen_mem_store_word;
extern void *codegen_mem_store_long;
extern void *codegen_mem_store_quad;
extern void *codegen_mem_store_single;
extern void *codegen_mem_store_double;
extern void *codegen_gpf_rout;
extern void *codegen_exit_rout;

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,193 @@
void host_x86_ADD8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data);
void host_x86_ADD16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data);
void host_x86_ADD32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data);
void host_x86_ADD64_REG_IMM(codeblock_t *block, int dst_reg, uint64_t imm_data);
void host_x86_ADD8_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_ADD16_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_AND8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data);
void host_x86_AND16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data);
void host_x86_AND32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data);
void host_x86_AND8_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_AND16_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_AND32_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_CALL(codeblock_t *block, void *p);
void host_x86_CMP16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data);
void host_x86_CMP32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data);
void host_x86_CMP64_REG_IMM(codeblock_t *block, int dst_reg, uint64_t imm_data);
void host_x86_CMP8_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b);
void host_x86_CMP16_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b);
void host_x86_CMP32_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b);
void host_x86_JMP(codeblock_t *block, void *p);
void host_x86_JNZ(codeblock_t *block, void *p);
void host_x86_JZ(codeblock_t *block, void *p);
uint8_t *host_x86_JNZ_short(codeblock_t *block);
uint8_t *host_x86_JS_short(codeblock_t *block);
uint8_t *host_x86_JZ_short(codeblock_t *block);
uint32_t *host_x86_JNB_long(codeblock_t *block);
uint32_t *host_x86_JNBE_long(codeblock_t *block);
uint32_t *host_x86_JNL_long(codeblock_t *block);
uint32_t *host_x86_JNLE_long(codeblock_t *block);
uint32_t *host_x86_JNO_long(codeblock_t *block);
uint32_t *host_x86_JNS_long(codeblock_t *block);
uint32_t *host_x86_JNZ_long(codeblock_t *block);
uint32_t *host_x86_JB_long(codeblock_t *block);
uint32_t *host_x86_JBE_long(codeblock_t *block);
uint32_t *host_x86_JL_long(codeblock_t *block);
uint32_t *host_x86_JLE_long(codeblock_t *block);
uint32_t *host_x86_JO_long(codeblock_t *block);
uint32_t *host_x86_JS_long(codeblock_t *block);
uint32_t *host_x86_JZ_long(codeblock_t *block);
void host_x86_LAHF(codeblock_t *block);
void host_x86_LEA_REG_IMM(codeblock_t *block, int dst_reg, int src_reg, uint32_t offset);
void host_x86_LEA_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
void host_x86_LEA_REG_REG_SHIFT(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b, int shift);
void host_x86_MOV8_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data);
void host_x86_MOV32_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data);
void host_x86_MOV8_ABS_REG(codeblock_t *block, void *p, int src_reg);
void host_x86_MOV16_ABS_REG(codeblock_t *block, void *p, int src_reg);
void host_x86_MOV32_ABS_REG(codeblock_t *block, void *p, int src_reg);
void host_x86_MOV64_ABS_REG(codeblock_t *block, void *p, int src_reg);
void host_x86_MOV8_ABS_REG_REG_SHIFT_REG(codeblock_t *block, uint32_t addr, int base_reg, int index_reg, int shift, int src_reg);
void host_x86_MOV8_BASE_INDEX_REG(codeblock_t *block, int dst_reg, int base_reg, int index_reg);
void host_x86_MOV16_BASE_INDEX_REG(codeblock_t *block, int dst_reg, int base_reg, int index_reg);
void host_x86_MOV32_BASE_INDEX_REG(codeblock_t *block, int dst_reg, int base_reg, int index_reg);
void host_x86_MOV32_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset, int src_reg);
void host_x86_MOV64_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset, int src_reg);
void host_x86_MOV8_REG_ABS(codeblock_t *block, int dst_reg, void *p);
void host_x86_MOV16_REG_ABS(codeblock_t *block, int dst_reg, void *p);
void host_x86_MOV32_REG_ABS(codeblock_t *block, int dst_reg, void *p);
void host_x86_MOV64_REG_ABS(codeblock_t *block, int dst_reg, void *p);
void host_x86_MOV8_REG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32_t addr, int base_reg, int index_reg, int shift);
void host_x86_MOV32_REG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int index_reg);
void host_x86_MOV64_REG_BASE_INDEX_SHIFT(codeblock_t *block, int dst_reg, int base_reg, int index_reg, int scale);
void host_x86_MOV16_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset);
void host_x86_MOV32_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset);
void host_x86_MOV64_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset);
void host_x86_MOV8_REG_IMM(codeblock_t *block, int reg, uint16_t imm_data);
void host_x86_MOV16_REG_IMM(codeblock_t *block, int reg, uint16_t imm_data);
void host_x86_MOV32_REG_IMM(codeblock_t *block, int reg, uint32_t imm_data);
void host_x86_MOV64_REG_IMM(codeblock_t *block, int reg, uint64_t imm_data);
void host_x86_MOV8_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MOV16_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MOV32_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_data);
void host_x86_MOVSX_REG_16_8(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MOVSX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MOVSX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MOVZX_BASE_INDEX_32_8(codeblock_t *block, int dst_reg, int base_reg, int index_reg);
void host_x86_MOVZX_BASE_INDEX_32_16(codeblock_t *block, int dst_reg, int base_reg, int index_reg);
void host_x86_MOVZX_REG_16_8(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MOVZX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MOVZX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MOVZX_REG_ABS_16_8(codeblock_t *block, int dst_reg, void *p);
void host_x86_MOVZX_REG_ABS_32_8(codeblock_t *block, int dst_reg, void *p);
void host_x86_MOVZX_REG_ABS_32_16(codeblock_t *block, int dst_reg, void *p);
void host_x86_NOP(codeblock_t *block);
void host_x86_OR8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data);
void host_x86_OR16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data);
void host_x86_OR32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data);
void host_x86_OR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_OR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_OR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_POP(codeblock_t *block, int src_reg);
void host_x86_PUSH(codeblock_t *block, int src_reg);
void host_x86_RET(codeblock_t *block);
void host_x86_ROL8_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_ROL16_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_ROL32_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_ROL8_CL(codeblock_t *block, int dst_reg);
void host_x86_ROL16_CL(codeblock_t *block, int dst_reg);
void host_x86_ROL32_CL(codeblock_t *block, int dst_reg);
void host_x86_ROR8_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_ROR16_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_ROR32_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_ROR8_CL(codeblock_t *block, int dst_reg);
void host_x86_ROR16_CL(codeblock_t *block, int dst_reg);
void host_x86_ROR32_CL(codeblock_t *block, int dst_reg);
void host_x86_SAR8_CL(codeblock_t *block, int dst_reg);
void host_x86_SAR16_CL(codeblock_t *block, int dst_reg);
void host_x86_SAR32_CL(codeblock_t *block, int dst_reg);
void host_x86_SAR8_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_SAR16_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_SAR32_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_SHL8_CL(codeblock_t *block, int dst_reg);
void host_x86_SHL16_CL(codeblock_t *block, int dst_reg);
void host_x86_SHL32_CL(codeblock_t *block, int dst_reg);
void host_x86_SHL8_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_SHL16_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_SHL32_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_SHR8_CL(codeblock_t *block, int dst_reg);
void host_x86_SHR16_CL(codeblock_t *block, int dst_reg);
void host_x86_SHR32_CL(codeblock_t *block, int dst_reg);
void host_x86_SHR8_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_SHR16_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_SHR32_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_SUB8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data);
void host_x86_SUB16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data);
void host_x86_SUB32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data);
void host_x86_SUB64_REG_IMM(codeblock_t *block, int dst_reg, uint64_t imm_data);
void host_x86_SUB8_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_SUB16_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_TEST8_REG(codeblock_t *block, int src_host_reg, int dst_host_reg);
void host_x86_TEST16_REG(codeblock_t *block, int src_host_reg, int dst_host_reg);
void host_x86_TEST32_REG(codeblock_t *block, int src_reg, int dst_reg);
void host_x86_TEST32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data);
void host_x86_XOR8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data);
void host_x86_XOR16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data);
void host_x86_XOR32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data);
void host_x86_XOR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_XOR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_XOR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg);

View file

@ -0,0 +1,102 @@
#define JMP_LEN_BYTES 5
static inline void codegen_addbyte(codeblock_t *block, uint8_t val)
{
if (block_pos >= BLOCK_MAX)
{
fatal("codegen_addbyte over! %i\n", block_pos);
// CPU_BLOCK_END();
}
block_write_data[block_pos++] = val;
}
static inline void codegen_addbyte2(codeblock_t *block, uint8_t vala, uint8_t valb)
{
if (block_pos > (BLOCK_MAX-2))
{
fatal("codegen_addbyte2 over! %i\n", block_pos);
CPU_BLOCK_END();
}
block_write_data[block_pos++] = vala;
block_write_data[block_pos++] = valb;
}
static inline void codegen_addbyte3(codeblock_t *block, uint8_t vala, uint8_t valb, uint8_t valc)
{
if (block_pos > (BLOCK_MAX-3))
{
fatal("codegen_addbyte3 over! %i\n", block_pos);
CPU_BLOCK_END();
}
block_write_data[block_pos++] = vala;
block_write_data[block_pos++] = valb;
block_write_data[block_pos++] = valc;
}
static inline void codegen_addbyte4(codeblock_t *block, uint8_t vala, uint8_t valb, uint8_t valc, uint8_t vald)
{
if (block_pos > (BLOCK_MAX-4))
{
fatal("codegen_addbyte4 over! %i\n", block_pos);
CPU_BLOCK_END();
}
block_write_data[block_pos++] = vala;
block_write_data[block_pos++] = valb;
block_write_data[block_pos++] = valc;
block_write_data[block_pos++] = vald;
}
static inline void codegen_addword(codeblock_t *block, uint16_t val)
{
if (block_pos > (BLOCK_MAX-2))
{
fatal("codegen_addword over! %i\n", block_pos);
CPU_BLOCK_END();
}
*(uint16_t *)&block_write_data[block_pos] = val;
block_pos += 2;
}
static inline void codegen_addlong(codeblock_t *block, uint32_t val)
{
if (block_pos > (BLOCK_MAX-4))
{
fatal("codegen_addlong over! %i\n", block_pos);
CPU_BLOCK_END();
}
*(uint32_t *)&block_write_data[block_pos] = val;
block_pos += 4;
}
static inline void codegen_addquad(codeblock_t *block, uint64_t val)
{
if (block_pos > (BLOCK_MAX-8))
{
fatal("codegen_addquad over! %i\n", block_pos);
CPU_BLOCK_END();
}
*(uint64_t *)&block_write_data[block_pos] = val;
block_pos += 8;
}
static inline void codegen_alloc_bytes(codeblock_t *block, int size)
{
if (block_pos > ((BLOCK_MAX - size) - JMP_LEN_BYTES))
{
/*Current block is full. Allocate a new block*/
struct mem_block_t *new_block = codegen_allocator_allocate(block->head_mem_block, get_block_nr(block));
uint8_t *new_ptr = codeblock_allocator_get_ptr(new_block);
/*Add a jump instruction to the new block*/
codegen_addbyte(block, 0xe9); /*JMP*/
codegen_addlong(block, (uintptr_t)new_ptr - (uintptr_t)&block_write_data[block_pos + 4]);
/*Set write address to start of new block*/
block_pos = 0;
block_write_data = new_ptr;
}
}
static inline int is_imm8(uint32_t imm_data)
{
if (imm_data <= 0x7f || imm_data >= 0xffffff80)
return 1;
return 0;
}

View file

@ -0,0 +1,614 @@
#ifdef __amd64__
#include "ibm.h"
#include "codegen.h"
#include "codegen_allocator.h"
#include "codegen_backend.h"
#include "codegen_backend_x86-64_defs.h"
#include "codegen_backend_x86-64_ops_sse.h"
#include "codegen_backend_x86-64_ops_helpers.h"
void host_x86_ADDPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 3);
codegen_addbyte3(block, 0x0f, 0x58, 0xc0 | src_reg | (dst_reg << 3)); /*ADDPS dst_reg, src_reg*/
}
void host_x86_ADDSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0xf2, 0x0f, 0x58, 0xc0 | src_reg | (dst_reg << 3));
}
void host_x86_CMPPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg, int type)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x0f, 0xc2, 0xc0 | src_reg | (dst_reg << 3), type); /*CMPPS dst_reg, src_reg, type*/
}
void host_x86_COMISD_XREG_XREG(codeblock_t *block, int src_reg_a, int src_reg_b)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0x2e, 0xc0 | src_reg_b | (src_reg_a << 3));
}
void host_x86_CVTDQ2PS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 3);
codegen_addbyte3(block, 0x0f, 0x5b, 0xc0 | src_reg | (dst_reg << 3)); /*CVTDQ2PS dst_reg, src_reg*/
}
void host_x86_CVTPS2DQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0x5b, 0xc0 | src_reg | (dst_reg << 3)); /*CVTPS2DQ dst_reg, src_reg*/
}
void host_x86_CVTSD2SI_REG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0xf2, 0x0f, 0x2d, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSD2SI dst_reg, src_reg*/
}
void host_x86_CVTSD2SI_REG64_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0xf2, 0x48, 0x0f, 0x2d); /*CVTSD2SI dst_reg, src_reg*/
codegen_addbyte(block, 0xc0 | src_reg | (dst_reg << 3));
}
void host_x86_CVTSD2SS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0xf2, 0x0f, 0x5a, 0xc0 | src_reg | (dst_reg << 3));
}
void host_x86_CVTSI2SD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0xf2, 0x0f, 0x2a, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSI2SD dst_reg, src_reg*/
}
void host_x86_CVTSI2SS_XREG_REG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0xf3, 0x0f, 0x2a, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSI2SD dst_reg, src_reg*/
}
void host_x86_CVTSI2SD_XREG_REG64(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0xf2, 0x48, 0x0f, 0x2a); /*CVTSI2SD dst_reg, src_reg*/
codegen_addbyte(block, 0xc0 | src_reg | (dst_reg << 3));
}
void host_x86_CVTSS2SD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0xf3, 0x0f, 0x5a, 0xc0 | src_reg | (dst_reg << 3));
}
void host_x86_CVTSS2SD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0xf3, 0x0f, 0x5a, 0x04 | (dst_reg << 3)); /*CVTSS2SD XMMx, [base_reg + idx_reg]*/
codegen_addbyte(block, base_reg | (idx_reg << 3));
}
void host_x86_DIVSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0xf2, 0x0f, 0x5e, 0xc0 | src_reg | (dst_reg << 3));
}
void host_x86_DIVSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0xf3, 0x0f, 0x5e, 0xc0 | src_reg | (dst_reg << 3)); /*DIVSS dst_reg, src_reg*/
}
void host_x86_LDMXCSR(codeblock_t *block, void *p)
{
int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
if (offset >= -128 && offset < 127)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x0f, 0xae, 0x50 | REG_EBP, offset); /*LDMXCSR offset[EBP]*/
}
else if (offset < (1ull << 32))
{
codegen_alloc_bytes(block, 7);
codegen_addbyte3(block, 0x0f, 0xae, 0x90 | REG_EBP); /*LDMXCSR offset[EBP]*/
codegen_addlong(block, offset);
}
else
{
fatal("host_x86_LDMXCSR - out of range %p\n", p);
}
}
void host_x86_MAXSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0xf2, 0x0f, 0x5f, 0xc0 | src_reg | (dst_reg << 3)); /*MAXSD dst_reg, src_reg*/
}
void host_x86_MOVD_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0x66, 0x0f, 0x7e, 0x04 | (src_reg << 3)); /*MOVD XMMx, [base_reg + idx_reg]*/
codegen_addbyte(block, base_reg | (idx_reg << 3));
}
void host_x86_MOVD_REG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0x7e, 0xc0 | dst_reg | (src_reg << 3));
}
void host_x86_MOVD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0x66, 0x0f, 0x6e, 0x04 | (dst_reg << 3)); /*MOVD XMMx, [base_reg + idx_reg]*/
codegen_addbyte(block, base_reg | (idx_reg << 3));
}
void host_x86_MOVD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0x6e, 0xc0 | src_reg | (dst_reg << 3));
}
void host_x86_MOVQ_ABS_XREG(codeblock_t *block, void *p, int src_reg)
{
int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
if (src_reg & 8)
fatal("host_x86_MOVQ_ABS_REG reg & 8\n");
if (offset >= -128 && offset < 127)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x45 | (src_reg << 3)); /*MOVQ offset[EBP], src_reg*/
codegen_addbyte(block, offset);
}
else
{
if ((uintptr_t)p >> 32)
fatal("host_x86_MOVQ_ABS_REG - out of range %p\n", p);
codegen_alloc_bytes(block, 9);
codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x04 | (src_reg << 3)); /*MOVQ [p], src_reg*/
codegen_addbyte(block, 0x25);
codegen_addlong(block, (uint32_t)(uintptr_t)p);
}
}
void host_x86_MOVQ_ABS_REG_REG_SHIFT_XREG(codeblock_t *block, uint32_t addr, int src_reg_a, int src_reg_b, int shift, int src_reg)
{
if ((src_reg & 8) || (src_reg_a & 8) || (src_reg_b & 8))
fatal("host_x86_MOVQ_ABS_REG_REG_SHIFT_REG - bad reg\n");
if (addr < 0x80 || addr >= 0xffffff80)
{
codegen_alloc_bytes(block, 6);
codegen_addbyte3(block, 0x66, 0x0f, 0xd6); /*MOVQ addr[src_reg_a + src_reg_b << shift], XMMx*/
codegen_addbyte3(block, 0x44 | (src_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6), addr & 0xff);
}
else
{
codegen_alloc_bytes(block, 9);
codegen_addbyte3(block, 0x66, 0x0f, 0xd6); /*MOVQ addr[src_reg_a + src_reg_b << shift], XMMx*/
codegen_addbyte2(block, 0x84 | (src_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6));
codegen_addlong(block, addr);
}
}
void host_x86_MOVQ_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x04 | (src_reg << 3)); /*MOVD XMMx, [base_reg + idx_reg]*/
codegen_addbyte(block, base_reg | (idx_reg << 3));
}
void host_x86_MOVQ_BASE_OFFSET_XREG(codeblock_t *block, int base_reg, int offset, int src_reg)
{
if (offset >= -128 && offset < 127)
{
if (base_reg == REG_RSP)
{
codegen_alloc_bytes(block, 6);
codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x44 | (src_reg << 3)); /*MOVQ [RSP + offset], XMMx*/
codegen_addbyte2(block, 0x24, offset);
}
else
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x40 | base_reg | (src_reg << 3)); /*MOVQ [base_reg + offset], XMMx*/
codegen_addbyte(block, offset);
}
}
else
fatal("MOVQ_BASE_OFFSET_XREG - offset %i\n", offset);
}
void host_x86_MOVQ_XREG_ABS(codeblock_t *block, int dst_reg, void *p)
{
int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
if (dst_reg & 8)
fatal("host_x86_MOVQ_REG_ABS reg & 8\n");
if (offset >= -128 && offset < 127)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x45 | (dst_reg << 3)); /*MOVQ offset[EBP], src_reg*/
codegen_addbyte(block, offset);
}
else
{
if ((uintptr_t)p >> 32)
fatal("host_x86_MOVQ_REG_ABS - out of range %p\n", p);
codegen_alloc_bytes(block, 9);
codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x04 | (dst_reg << 3)); /*MOVQ [p], src_reg*/
codegen_addbyte(block, 0x25);
codegen_addlong(block, (uint32_t)(uintptr_t)p);
}
}
void host_x86_MOVQ_XREG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32_t addr, int src_reg_a, int src_reg_b, int shift)
{
if ((dst_reg & 8) || (src_reg_a & 8) || (src_reg_b & 8))
fatal("host_x86_MOVQ_REG_ABS_REG_REG_SHIFT - bad reg\n");
if (addr < 0x80 || addr >= 0xffffff80)
{
codegen_alloc_bytes(block, 6);
codegen_addbyte3(block, 0xf3, 0x0f, 0x7e); /*MOVQ XMMx, addr[src_reg_a + src_reg_b << shift]*/
codegen_addbyte3(block, 0x44 | (dst_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6), addr & 0xff);
}
else
{
codegen_alloc_bytes(block, 9);
codegen_addbyte3(block, 0xf3, 0x0f, 0x7e); /*MOVQ XMMx, addr[src_reg_a + src_reg_b << shift]*/
codegen_addbyte2(block, 0x84 | (dst_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6));
codegen_addlong(block, addr);
}
}
void host_x86_MOVQ_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x04 | (dst_reg << 3)); /*MOVQ XMMx, [base_reg + idx_reg]*/
codegen_addbyte(block, base_reg | (idx_reg << 3));
}
void host_x86_MOVQ_XREG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset)
{
if (offset >= -128 && offset < 127)
{
if (base_reg == REG_ESP)
{
codegen_alloc_bytes(block, 6);
codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x44 | (dst_reg << 3)); /*MOVQ XMMx, [ESP + offset]*/
codegen_addbyte2(block, 0x24, offset);
}
else
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x40 | base_reg | (dst_reg << 3)); /*MOVQ XMMx, [base_reg + offset]*/
codegen_addbyte(block, offset);
}
}
else
fatal("MOVQ_REG_BASE_OFFSET - offset %i\n", offset);
}
void host_x86_MOVQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0xc0 | src_reg | (dst_reg << 3)); /*MOVQ dst_reg, src_reg*/
}
void host_x86_MOVQ_REG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0x66, 0x48, 0x0f, 0x7e); /*MOVQ dst_reg, src_reg*/
codegen_addbyte(block, 0xc0 | dst_reg | (src_reg << 3));
}
void host_x86_MOVQ_XREG_REG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0x66, 0x48, 0x0f, 0x6e); /*MOVQ dst_reg, src_reg*/
codegen_addbyte(block, 0xc0 | src_reg | (dst_reg << 3));
}
void host_x86_MAXPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 3);
codegen_addbyte3(block, 0x0f, 0x5f, 0xc0 | src_reg | (dst_reg << 3)); /*MAXPS dst_reg, src_reg*/
}
void host_x86_MINPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 3);
codegen_addbyte3(block, 0x0f, 0x5d, 0xc0 | src_reg | (dst_reg << 3)); /*MINPS dst_reg, src_reg*/
}
void host_x86_MULPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 3);
codegen_addbyte3(block, 0x0f, 0x59, 0xc0 | src_reg | (dst_reg << 3)); /*MULPS dst_reg, src_reg*/
}
void host_x86_MULSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0xf2, 0x0f, 0x59, 0xc0 | src_reg | (dst_reg << 3));
}
void host_x86_PACKSSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 9);
codegen_addbyte4(block, 0x66, 0x0f, 0x63, 0xc0 | src_reg | (dst_reg << 3)); /*PACKSSWB dst_reg, src_reg*/
codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0x88 (move bits 64-95 to 32-63)*/
codegen_addbyte(block, 0x88);
}
void host_x86_PACKSSDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 9);
codegen_addbyte4(block, 0x66, 0x0f, 0x6b, 0xc0 | src_reg | (dst_reg << 3)); /*PACKSSDW dst_reg, src_reg*/
codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0x88 (move bits 64-95 to 32-63)*/
codegen_addbyte(block, 0x88);
}
void host_x86_PACKUSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 9);
codegen_addbyte4(block, 0x66, 0x0f, 0x67, 0xc0 | src_reg | (dst_reg << 3)); /*PACKUSWB dst_reg, src_reg*/
codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0x88 (move bits 64-95 to 32-63)*/
codegen_addbyte(block, 0x88);
}
void host_x86_PADDB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xfc, 0xc0 | src_reg | (dst_reg << 3)); /*PADDB dst_reg, src_reg*/
}
void host_x86_PADDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xfd, 0xc0 | src_reg | (dst_reg << 3)); /*PADDW dst_reg, src_reg*/
}
void host_x86_PADDD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xfe, 0xc0 | src_reg | (dst_reg << 3)); /*PADDD dst_reg, src_reg*/
}
void host_x86_PADDSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xec, 0xc0 | src_reg | (dst_reg << 3)); /*PADDSB dst_reg, src_reg*/
}
void host_x86_PADDSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xed, 0xc0 | src_reg | (dst_reg << 3)); /*PADDSW dst_reg, src_reg*/
}
void host_x86_PADDUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xdc, 0xc0 | src_reg | (dst_reg << 3)); /*PADDUSB dst_reg, src_reg*/
}
void host_x86_PADDUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xdd, 0xc0 | src_reg | (dst_reg << 3)); /*PADDUSW dst_reg, src_reg*/
}
void host_x86_PAND_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xdb, 0xc0 | src_reg | (dst_reg << 3)); /*PAND dst_reg, src_reg*/
}
void host_x86_PANDN_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xdf, 0xc0 | src_reg | (dst_reg << 3)); /*PANDN dst_reg, src_reg*/
}
void host_x86_POR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xeb, 0xc0 | src_reg | (dst_reg << 3)); /*POR dst_reg, src_reg*/
}
void host_x86_PXOR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xef, 0xc0 | src_reg | (dst_reg << 3)); /*PXOR dst_reg, src_reg*/
}
void host_x86_PCMPEQB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0x74, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQB dst_reg, src_reg*/
}
void host_x86_PCMPEQW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0x75, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQW dst_reg, src_reg*/
}
void host_x86_PCMPEQD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0x76, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQD dst_reg, src_reg*/
}
void host_x86_PCMPGTB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0x64, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTB dst_reg, src_reg*/
}
void host_x86_PCMPGTW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0x65, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTW dst_reg, src_reg*/
}
void host_x86_PCMPGTD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0x66, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTD dst_reg, src_reg*/
}
void host_x86_PMADDWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xf5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/
}
void host_x86_PMULHW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xe5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/
}
void host_x86_PMULLW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xd5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/
}
void host_x86_PSLLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x30 | dst_reg); /*PSLLW dst_reg, imm*/
codegen_addbyte(block, shift);
}
void host_x86_PSLLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x30 | dst_reg); /*PSLLD dst_reg, imm*/
codegen_addbyte(block, shift);
}
void host_x86_PSLLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x30 | dst_reg); /*PSLLD dst_reg, imm*/
codegen_addbyte(block, shift);
}
void host_x86_PSRAW_XREG_IMM(codeblock_t *block, int dst_reg, int shift)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x20 | dst_reg); /*PSRAW dst_reg, imm*/
codegen_addbyte(block, shift);
}
void host_x86_PSRAD_XREG_IMM(codeblock_t *block, int dst_reg, int shift)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x20 | dst_reg); /*PSRAD dst_reg, imm*/
codegen_addbyte(block, shift);
}
void host_x86_PSRAQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x20 | dst_reg); /*PSRAD dst_reg, imm*/
codegen_addbyte(block, shift);
}
void host_x86_PSRLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x10 | dst_reg); /*PSRLW dst_reg, imm*/
codegen_addbyte(block, shift);
}
void host_x86_PSRLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x10 | dst_reg); /*PSRLD dst_reg, imm*/
codegen_addbyte(block, shift);
}
void host_x86_PSRLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x10 | dst_reg); /*PSRLD dst_reg, imm*/
codegen_addbyte(block, shift);
}
void host_x86_PSUBB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xf8, 0xc0 | src_reg | (dst_reg << 3)); /*PADDB dst_reg, src_reg*/
}
void host_x86_PSUBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xf9, 0xc0 | src_reg | (dst_reg << 3)); /*PADDW dst_reg, src_reg*/
}
void host_x86_PSUBD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xfa, 0xc0 | src_reg | (dst_reg << 3)); /*PADDD dst_reg, src_reg*/
}
void host_x86_PSUBSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xe8, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBSB dst_reg, src_reg*/
}
void host_x86_PSUBSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xe9, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBSW dst_reg, src_reg*/
}
void host_x86_PSUBUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xd8, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBUSB dst_reg, src_reg*/
}
void host_x86_PSUBUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xd9, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBUSW dst_reg, src_reg*/
}
void host_x86_PUNPCKHBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 9);
codegen_addbyte4(block, 0x66, 0x0f, 0x60, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLBW dst_reg, src_reg*/
codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0xee (move top 64-bits to low 64-bits)*/
codegen_addbyte(block, 0xee);
}
void host_x86_PUNPCKHWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 9);
codegen_addbyte4(block, 0x66, 0x0f, 0x61, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLWD dst_reg, src_reg*/
codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0xee (move top 64-bits to low 64-bits)*/
codegen_addbyte(block, 0xee);
}
void host_x86_PUNPCKHDQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 9);
codegen_addbyte4(block, 0x66, 0x0f, 0x62, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLDQ dst_reg, src_reg*/
codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0xee (move top 64-bits to low 64-bits)*/
codegen_addbyte(block, 0xee);
}
void host_x86_PUNPCKLBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0x60, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLBW dst_reg, src_reg*/
}
void host_x86_PUNPCKLWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0x61, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLWD dst_reg, src_reg*/
}
void host_x86_PUNPCKLDQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0x62, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLDQ dst_reg, src_reg*/
}
void host_x86_SQRTSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0xf2, 0x0f, 0x51, 0xc0 | src_reg | (dst_reg << 3)); /*SQRTSD dst_reg, src_reg*/
}
void host_x86_SQRTSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0xf3, 0x0f, 0x51, 0xc0 | src_reg | (dst_reg << 3)); /*SQRTSS dst_reg, src_reg*/
}
void host_x86_SUBPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 3);
codegen_addbyte3(block, 0x0f, 0x5c, 0xc0 | src_reg | (dst_reg << 3)); /*SUBPS dst_reg, src_reg*/
}
void host_x86_SUBSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0xf2, 0x0f, 0x5c, 0xc0 | src_reg | (dst_reg << 3));
}
void host_x86_UNPCKLPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 3);
codegen_addbyte3(block, 0x0f, 0x14, 0xc0 | src_reg | (dst_reg << 3));
}
#endif

View file

@ -0,0 +1,114 @@
void host_x86_ADDPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_ADDSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
#define CMPPS_EQ 0
#define CMPPS_NLT 5
#define CMPPS_NLE 6
void host_x86_CMPPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg, int type);
void host_x86_COMISD_XREG_XREG(codeblock_t *block, int src_reg_a, int src_reg_b);
void host_x86_CVTDQ2PS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_CVTPS2DQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_CVTSD2SI_REG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_CVTSD2SI_REG64_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_CVTSD2SS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_CVTSI2SD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_CVTSI2SD_XREG_REG64(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_CVTSI2SS_XREG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_CVTSS2SD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_CVTSS2SD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg);
void host_x86_DIVSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_DIVSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_LDMXCSR(codeblock_t *block, void *p);
void host_x86_MAXSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MOVD_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg);
void host_x86_MOVD_REG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MOVD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg);
void host_x86_MOVD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MOVQ_ABS_XREG(codeblock_t *block, void *p, int src_reg);
void host_x86_MOVQ_ABS_REG_REG_SHIFT_XREG(codeblock_t *block, uint32_t addr, int src_reg_a, int src_reg_b, int shift, int src_reg);
void host_x86_MOVQ_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg);
void host_x86_MOVQ_BASE_OFFSET_XREG(codeblock_t *block, int base_reg, int offset, int src_reg);
void host_x86_MOVQ_XREG_ABS(codeblock_t *block, int dst_reg, void *p);
void host_x86_MOVQ_XREG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32_t addr, int src_reg_a, int src_reg_b, int shift);
void host_x86_MOVQ_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg);
void host_x86_MOVQ_XREG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset);
void host_x86_MOVQ_REG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MOVQ_XREG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MOVQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MAXPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MINPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MULPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MULSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MULSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PACKSSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PACKSSDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PACKUSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PADDB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PADDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PADDD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PADDSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PADDSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PADDUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PADDUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PAND_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PANDN_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_POR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PXOR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PCMPEQB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PCMPEQW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PCMPEQD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PCMPGTB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PCMPGTW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PCMPGTD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PMADDWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PMULHW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PMULLW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PSLLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_PSLLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_PSLLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_PSRAW_XREG_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_PSRAD_XREG_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_PSRAQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_PSRLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_PSRLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_PSRLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_PSUBB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PSUBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PSUBD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PSUBSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PSUBSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PSUBUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PSUBUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PUNPCKHBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PUNPCKHWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PUNPCKHDQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PUNPCKLBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PUNPCKLWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PUNPCKLDQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_SQRTSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_SQRTSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_SUBPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_SUBSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_UNPCKLPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);

File diff suppressed because it is too large Load diff

366
src/codegen_backend_x86.c Normal file
View file

@ -0,0 +1,366 @@
#if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined WIN32 || defined _WIN32 || defined _WIN32
#include <stddef.h>
#include "ibm.h"
#include "codegen.h"
#include "codegen_allocator.h"
#include "codegen_backend.h"
#include "codegen_backend_x86_defs.h"
#include "codegen_backend_x86_ops.h"
#include "codegen_backend_x86_ops_sse.h"
#include "codegen_reg.h"
#include "x86.h"
#if defined(__linux__) || defined(__APPLE__)
#include <sys/mman.h>
#include <unistd.h>
#endif
#if defined WIN32 || defined _WIN32 || defined _WIN32
#include <windows.h>
#endif
void *codegen_mem_load_byte;
void *codegen_mem_load_word;
void *codegen_mem_load_long;
void *codegen_mem_load_quad;
void *codegen_mem_load_single;
void *codegen_mem_load_double;
void *codegen_mem_store_byte;
void *codegen_mem_store_word;
void *codegen_mem_store_long;
void *codegen_mem_store_quad;
void *codegen_mem_store_single;
void *codegen_mem_store_double;
void *codegen_gpf_rout;
void *codegen_exit_rout;
int codegen_host_reg_list[CODEGEN_HOST_REGS] =
{
REG_EAX,
REG_EBX,
REG_EDX
};
int codegen_host_fp_reg_list[CODEGEN_HOST_FP_REGS] =
{
REG_XMM0,
REG_XMM1,
REG_XMM2,
REG_XMM3,
REG_XMM4,
REG_XMM5
};
static void build_load_routine(codeblock_t *block, int size, int is_float)
{
uint8_t *branch_offset;
uint8_t *misaligned_offset = NULL;
/*In - ESI = address
Out - ECX = data, ESI = abrt*/
/*MOV ECX, ESI
SHR ESI, 12
MOV ESI, [readlookup2+ESI*4]
CMP ESI, -1
JNZ +
MOVZX ECX, B[ESI+ECX]
XOR ESI,ESI
RET
* PUSH EAX
PUSH EDX
PUSH ECX
CALL readmembl
POP ECX
POP EDX
POP EAX
MOVZX ECX, AL
RET
*/
host_x86_MOV32_REG_REG(block, REG_ECX, REG_ESI);
host_x86_SHR32_IMM(block, REG_ESI, 12);
host_x86_MOV32_REG_ABS_INDEX_SHIFT(block, REG_ESI, readlookup2, REG_ESI, 2);
if (size != 1)
{
host_x86_TEST32_REG_IMM(block, REG_ECX, size-1);
misaligned_offset = host_x86_JNZ_short(block);
}
host_x86_CMP32_REG_IMM(block, REG_ESI, (uint32_t)-1);
branch_offset = host_x86_JZ_short(block);
if (size == 1 && !is_float)
host_x86_MOVZX_BASE_INDEX_32_8(block, REG_ECX, REG_ESI, REG_ECX);
else if (size == 2 && !is_float)
host_x86_MOVZX_BASE_INDEX_32_16(block, REG_ECX, REG_ESI, REG_ECX);
else if (size == 4 && !is_float)
host_x86_MOV32_REG_BASE_INDEX(block, REG_ECX, REG_ESI, REG_ECX);
else if (size == 4 && is_float)
host_x86_CVTSS2SD_XREG_BASE_INDEX(block, REG_XMM_TEMP, REG_ESI, REG_ECX);
else if (size == 8)
host_x86_MOVQ_XREG_BASE_INDEX(block, REG_XMM_TEMP, REG_ESI, REG_ECX);
else
fatal("build_load_routine: size=%i\n", size);
host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI);
host_x86_RET(block);
*branch_offset = (uint8_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 1;
if (size != 1)
*misaligned_offset = (uint8_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)misaligned_offset) - 1;
host_x86_PUSH(block, REG_EAX);
host_x86_PUSH(block, REG_EDX);
host_x86_PUSH(block, REG_ECX);
if (size == 1)
host_x86_CALL(block, (void *)readmembl);
else if (size == 2)
host_x86_CALL(block, (void *)readmemwl);
else if (size == 4)
host_x86_CALL(block, (void *)readmemll);
else if (size == 8)
host_x86_CALL(block, (void *)readmemql);
host_x86_POP(block, REG_ECX);
if (size == 1 && !is_float)
host_x86_MOVZX_REG_32_8(block, REG_ECX, REG_EAX);
else if (size == 2 && !is_float)
host_x86_MOVZX_REG_32_16(block, REG_ECX, REG_EAX);
else if (size == 4 && !is_float)
host_x86_MOV32_REG_REG(block, REG_ECX, REG_EAX);
else if (size == 4 && is_float)
{
host_x86_MOVD_XREG_REG(block, REG_XMM_TEMP, REG_EAX);
host_x86_CVTSS2SD_XREG_XREG(block, REG_XMM_TEMP, REG_XMM_TEMP);
}
else if (size == 8)
{
host_x86_MOVD_XREG_REG(block, REG_XMM_TEMP, REG_EAX);
host_x86_MOVD_XREG_REG(block, REG_XMM_TEMP2, REG_EDX);
host_x86_UNPCKLPS_XREG_XREG(block, REG_XMM_TEMP, REG_XMM_TEMP2);
}
host_x86_POP(block, REG_EDX);
host_x86_POP(block, REG_EAX);
host_x86_MOVZX_REG_ABS_32_8(block, REG_ESI, &cpu_state.abrt);
host_x86_RET(block);
block_pos = (block_pos + 63) & ~63;
}
static void build_store_routine(codeblock_t *block, int size, int is_float)
{
uint8_t *branch_offset;
uint8_t *misaligned_offset = NULL;
/*In - ECX = data, ESI = address
Out - ESI = abrt
Corrupts EDI*/
/*MOV EDI, ESI
SHR ESI, 12
MOV ESI, [writelookup2+ESI*4]
CMP ESI, -1
JNZ +
MOV [ESI+EDI], ECX
XOR ESI,ESI
RET
* PUSH EAX
PUSH EDX
PUSH ECX
CALL writemembl
POP ECX
POP EDX
POP EAX
MOVZX ECX, AL
RET
*/
host_x86_MOV32_REG_REG(block, REG_EDI, REG_ESI);
host_x86_SHR32_IMM(block, REG_ESI, 12);
host_x86_MOV32_REG_ABS_INDEX_SHIFT(block, REG_ESI, writelookup2, REG_ESI, 2);
if (size != 1)
{
host_x86_TEST32_REG_IMM(block, REG_EDI, size-1);
misaligned_offset = host_x86_JNZ_short(block);
}
host_x86_CMP32_REG_IMM(block, REG_ESI, (uint32_t)-1);
branch_offset = host_x86_JZ_short(block);
if (size == 1 && !is_float)
host_x86_MOV8_BASE_INDEX_REG(block, REG_ESI, REG_EDI, REG_ECX);
else if (size == 2 && !is_float)
host_x86_MOV16_BASE_INDEX_REG(block, REG_ESI, REG_EDI, REG_ECX);
else if (size == 4 && !is_float)
host_x86_MOV32_BASE_INDEX_REG(block, REG_ESI, REG_EDI, REG_ECX);
else if (size == 4 && is_float)
host_x86_MOVD_BASE_INDEX_XREG(block, REG_ESI, REG_EDI, REG_XMM_TEMP);
else if (size == 8)
host_x86_MOVQ_BASE_INDEX_XREG(block, REG_ESI, REG_EDI, REG_XMM_TEMP);
else
fatal("build_store_routine: size=%i is_float=%i\n", size, is_float);
host_x86_XOR32_REG_REG(block, REG_ESI, REG_ESI);
host_x86_RET(block);
*branch_offset = (uint8_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)branch_offset) - 1;
if (size != 1)
*misaligned_offset = (uint8_t)((uintptr_t)&block_write_data[block_pos] - (uintptr_t)misaligned_offset) - 1;
if (size == 4 && is_float)
host_x86_MOVD_REG_XREG(block, REG_ECX, REG_XMM_TEMP);
host_x86_PUSH(block, REG_EAX);
host_x86_PUSH(block, REG_EDX);
host_x86_PUSH(block, REG_ECX);
if (size == 8)
{
host_x86_MOVQ_STACK_OFFSET_XREG(block, -8, REG_XMM_TEMP);
host_x86_SUB32_REG_IMM(block, REG_ESP, 8);
}
host_x86_PUSH(block, REG_EDI);
if (size == 1)
host_x86_CALL(block, (void *)writemembl);
else if (size == 2)
host_x86_CALL(block, (void *)writememwl);
else if (size == 4)
host_x86_CALL(block, (void *)writememll);
else if (size == 8)
host_x86_CALL(block, (void *)writememql);
host_x86_POP(block, REG_EDI);
if (size == 8)
host_x86_ADD32_REG_IMM(block, REG_ESP, 8);
host_x86_POP(block, REG_ECX);
host_x86_POP(block, REG_EDX);
host_x86_POP(block, REG_EAX);
host_x86_MOVZX_REG_ABS_32_8(block, REG_ESI, &cpu_state.abrt);
host_x86_RET(block);
block_pos = (block_pos + 63) & ~63;
}
static void build_loadstore_routines(codeblock_t *block)
{
codegen_mem_load_byte = &codeblock[block_current].data[block_pos];
build_load_routine(block, 1, 0);
codegen_mem_load_word = &codeblock[block_current].data[block_pos];
build_load_routine(block, 2, 0);
codegen_mem_load_long = &codeblock[block_current].data[block_pos];
build_load_routine(block, 4, 0);
codegen_mem_load_quad = &codeblock[block_current].data[block_pos];
build_load_routine(block, 8, 0);
codegen_mem_load_single = &codeblock[block_current].data[block_pos];
build_load_routine(block, 4, 1);
codegen_mem_load_double = &codeblock[block_current].data[block_pos];
build_load_routine(block, 8, 1);
codegen_mem_store_byte = &codeblock[block_current].data[block_pos];
build_store_routine(block, 1, 0);
codegen_mem_store_word = &codeblock[block_current].data[block_pos];
build_store_routine(block, 2, 0);
codegen_mem_store_long = &codeblock[block_current].data[block_pos];
build_store_routine(block, 4, 0);
codegen_mem_store_quad = &codeblock[block_current].data[block_pos];
build_store_routine(block, 8, 0);
codegen_mem_store_single = &codeblock[block_current].data[block_pos];
build_store_routine(block, 4, 1);
codegen_mem_store_double = &codeblock[block_current].data[block_pos];
build_store_routine(block, 8, 1);
}
void codegen_backend_init()
{
codeblock_t *block;
int c;
#if defined(__linux__) || defined(__APPLE__)
void *start;
size_t len;
long pagesize = sysconf(_SC_PAGESIZE);
long pagemask = ~(pagesize - 1);
#endif
pclog("sizeof(codeblock_t)=%i\n", sizeof(codeblock_t));
pclog(" offsetof(codeblock_t, pc)=%i\n", offsetof(codeblock_t, pc));
pclog(" offsetof(codeblock_t, _cs)=%i\n", offsetof(codeblock_t, _cs));
pclog(" offsetof(codeblock_t, phys)=%i\n", offsetof(codeblock_t, phys));
pclog(" offsetof(codeblock_t, phys_2)=%i\n", offsetof(codeblock_t, phys_2));
pclog(" offsetof(codeblock_t, status)=%i\n", offsetof(codeblock_t, status));
pclog(" offsetof(codeblock_t, flags)=%i\n", offsetof(codeblock_t, flags));
pclog(" offsetof(codeblock_t, ins)=%i\n", offsetof(codeblock_t, ins));
pclog(" offsetof(codeblock_t, TOP)=%i\n", offsetof(codeblock_t, TOP));
pclog(" offsetof(codeblock_t, parent)=%i\n", offsetof(codeblock_t, parent));
pclog(" offsetof(codeblock_t, left)=%i\n", offsetof(codeblock_t, left));
pclog(" offsetof(codeblock_t, right)=%i\n", offsetof(codeblock_t, right));
pclog(" offsetof(codeblock_t, data)=%i\n", offsetof(codeblock_t, data));
pclog(" offsetof(codeblock_t, page_mask)=%i\n", offsetof(codeblock_t, page_mask));
pclog(" offsetof(codeblock_t, page_mask2)=%i\n", offsetof(codeblock_t, page_mask2));
pclog(" offsetof(codeblock_t, dirty_mask)=%i\n", offsetof(codeblock_t, dirty_mask));
pclog(" offsetof(codeblock_t, dirty_mask2)=%i\n", offsetof(codeblock_t, dirty_mask2));
pclog(" offsetof(codeblock_t, prev)=%i\n", offsetof(codeblock_t, prev));
pclog(" offsetof(codeblock_t, next)=%i\n", offsetof(codeblock_t, next));
pclog(" offsetof(codeblock_t, prev_2)=%i\n", offsetof(codeblock_t, prev_2));
pclog(" offsetof(codeblock_t, next_2)=%i\n", offsetof(codeblock_t, next_2));
codeblock = malloc(BLOCK_SIZE * sizeof(codeblock_t));
codeblock_hash = malloc(HASH_SIZE * sizeof(codeblock_t *));
memset(codeblock, 0, BLOCK_SIZE * sizeof(codeblock_t));
memset(codeblock_hash, 0, HASH_SIZE * sizeof(codeblock_t *));
for (c = 0; c < BLOCK_SIZE; c++)
codeblock[c].pc = BLOCK_PC_INVALID;
// pclog("Codegen is %p\n", (void *)pages[0xfab12 >> 12].block);
block_current = 0;
block_pos = 0;
block = &codeblock[block_current];
block->head_mem_block = codegen_allocator_allocate(NULL, block_current);
block->data = codeblock_allocator_get_ptr(block->head_mem_block);
block_write_data = block->data;
build_loadstore_routines(block);
codegen_gpf_rout = &codeblock[block_current].data[block_pos];
host_x86_MOV32_STACK_IMM(block, STACK_ARG0, 0);
host_x86_MOV32_STACK_IMM(block, STACK_ARG1, 0);
host_x86_CALL(block, (void *)x86gpf);
codegen_exit_rout = &codeblock[block_current].data[block_pos];
host_x86_ADD32_REG_IMM(block, REG_ESP, 64);
host_x86_POP(block, REG_EDI);
host_x86_POP(block, REG_ESI);
host_x86_POP(block, REG_EBP);
host_x86_POP(block, REG_EDX);
host_x86_RET(block);
block_write_data = NULL;
cpu_state.old_fp_control = 0;
asm(
"fstcw %0\n"
"stmxcsr %1\n"
: "=m" (cpu_state.old_fp_control2),
"=m" (cpu_state.old_fp_control)
);
cpu_state.trunc_fp_control = cpu_state.old_fp_control | 0x6000;
}
void codegen_set_rounding_mode(int mode)
{
/*SSE*/
cpu_state.new_fp_control = (cpu_state.old_fp_control & ~0x6000) | (mode << 13);
/*x87 - used for double -> i64 conversions*/
cpu_state.new_fp_control2 = (cpu_state.old_fp_control2 & ~0x0c00) | (mode << 10);
}
void codegen_backend_prologue(codeblock_t *block)
{
block_pos = BLOCK_START; /*Entry code*/
host_x86_PUSH(block, REG_EBX);
host_x86_PUSH(block, REG_EBP);
host_x86_PUSH(block, REG_ESI);
host_x86_PUSH(block, REG_EDI);
host_x86_SUB32_REG_IMM(block, REG_ESP, 64);
host_x86_MOV32_REG_IMM(block, REG_EBP, ((uintptr_t)&cpu_state) + 128);
if (block->flags & CODEBLOCK_HAS_FPU)
{
host_x86_MOV32_REG_ABS(block, REG_EAX, &cpu_state.TOP);
host_x86_SUB32_REG_IMM(block, REG_EAX, block->TOP);
host_x86_MOV32_BASE_OFFSET_REG(block, REG_ESP, IREG_TOP_diff_stack_offset, REG_EAX);
}
}
void codegen_backend_epilogue(codeblock_t *block)
{
host_x86_ADD32_REG_IMM(block, REG_ESP, 64);
host_x86_POP(block, REG_EDI);
host_x86_POP(block, REG_ESI);
host_x86_POP(block, REG_EBP);
host_x86_POP(block, REG_EDX);
host_x86_RET(block);
}
#endif

12
src/codegen_backend_x86.h Normal file
View file

@ -0,0 +1,12 @@
#include "codegen_backend_x86_defs.h"
#define BLOCK_SIZE 0x10000
#define BLOCK_MASK 0xffff
#define BLOCK_START 0
#define HASH_SIZE 0x20000
#define HASH_MASK 0x1ffff
#define HASH(l) ((l) & 0x1ffff)
#define BLOCK_MAX 0x3c0

View file

@ -0,0 +1,50 @@
#ifndef _CODEGEN_BACKEND_X86_DEFS_H_
#define _CODEGEN_BACKEND_X86_DEFS_H_
#define REG_EAX 0
#define REG_ECX 1
#define REG_EDX 2
#define REG_EBX 3
#define REG_ESP 4
#define REG_EBP 5
#define REG_ESI 6
#define REG_EDI 7
#define REG_XMM0 0
#define REG_XMM1 1
#define REG_XMM2 2
#define REG_XMM3 3
#define REG_XMM4 4
#define REG_XMM5 5
#define REG_XMM6 6
#define REG_XMM7 7
#define REG_XMM_TEMP REG_XMM7
#define REG_XMM_TEMP2 REG_XMM6
#define CODEGEN_HOST_REGS 3
#define CODEGEN_HOST_FP_REGS 6
extern void *codegen_mem_load_byte;
extern void *codegen_mem_load_word;
extern void *codegen_mem_load_long;
extern void *codegen_mem_load_quad;
extern void *codegen_mem_load_single;
extern void *codegen_mem_load_double;
extern void *codegen_mem_store_byte;
extern void *codegen_mem_store_word;
extern void *codegen_mem_store_long;
extern void *codegen_mem_store_quad;
extern void *codegen_mem_store_single;
extern void *codegen_mem_store_double;
extern void *codegen_gpf_rout;
extern void *codegen_exit_rout;
#define STACK_ARG0 (0)
#define STACK_ARG1 (4)
#define STACK_ARG2 (8)
#define STACK_ARG3 (12)
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,192 @@
void host_x86_ADD32_REG_ABS(codeblock_t *block, int dst_reg, void *p);
void host_x86_ADD8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data);
void host_x86_ADD16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data);
void host_x86_ADD32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data);
void host_x86_ADD8_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_ADD16_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_ADD32_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_AND8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data);
void host_x86_AND16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data);
void host_x86_AND32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data);
void host_x86_AND8_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_AND16_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_AND32_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_CALL(codeblock_t *block, void *p);
void host_x86_CMP16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data);
void host_x86_CMP32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data);
void host_x86_CMP8_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b);
void host_x86_CMP16_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b);
void host_x86_CMP32_REG_REG(codeblock_t *block, int src_reg_a, int src_reg_b);
void host_x86_INC32_ABS(codeblock_t *block, void *p);
void host_x86_JMP(codeblock_t *block, void *p);
uint32_t *host_x86_JMP_short(codeblock_t *block);
uint32_t *host_x86_JMP_long(codeblock_t *block);
void host_x86_JNZ(codeblock_t *block, void *p);
void host_x86_JZ(codeblock_t *block, void *p);
uint8_t *host_x86_JNZ_short(codeblock_t *block);
uint8_t *host_x86_JS_short(codeblock_t *block);
uint8_t *host_x86_JZ_short(codeblock_t *block);
uint32_t *host_x86_JNB_long(codeblock_t *block);
uint32_t *host_x86_JNBE_long(codeblock_t *block);
uint32_t *host_x86_JNL_long(codeblock_t *block);
uint32_t *host_x86_JNLE_long(codeblock_t *block);
uint32_t *host_x86_JNO_long(codeblock_t *block);
uint32_t *host_x86_JNS_long(codeblock_t *block);
uint32_t *host_x86_JNZ_long(codeblock_t *block);
uint32_t *host_x86_JB_long(codeblock_t *block);
uint32_t *host_x86_JBE_long(codeblock_t *block);
uint32_t *host_x86_JL_long(codeblock_t *block);
uint32_t *host_x86_JLE_long(codeblock_t *block);
uint32_t *host_x86_JO_long(codeblock_t *block);
uint32_t *host_x86_JS_long(codeblock_t *block);
uint32_t *host_x86_JZ_long(codeblock_t *block);
void host_x86_LAHF(codeblock_t *block);
void host_x86_LEA_REG_IMM(codeblock_t *block, int dst_reg, int src_reg_a, uint32_t offset);
void host_x86_LEA_REG_REG(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b);
void host_x86_LEA_REG_REG_SHIFT(codeblock_t *block, int dst_reg, int src_reg_a, int src_reg_b, int shift);
void host_x86_MOV8_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data);
void host_x86_MOV32_ABS_IMM(codeblock_t *block, void *p, uint32_t imm_data);
void host_x86_MOV8_ABS_REG(codeblock_t *block, void *p, int src_reg);
void host_x86_MOV16_ABS_REG(codeblock_t *block, void *p, int src_reg);
void host_x86_MOV32_ABS_REG(codeblock_t *block, void *p, int src_reg);
void host_x86_MOV8_ABS_REG_REG_SHIFT_REG(codeblock_t *block, uint32_t addr, int base_reg, int idx_reg, int shift, int src_reg);
void host_x86_MOV8_BASE_INDEX_REG(codeblock_t *block, int base_reg, int idx_reg, int src_reg);
void host_x86_MOV16_BASE_INDEX_REG(codeblock_t *block, int base_reg, int idx_reg, int src_reg);
void host_x86_MOV32_BASE_INDEX_REG(codeblock_t *block, int base_reg, int idx_reg, int src_reg);
void host_x86_MOV16_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset, int dst_reg);
void host_x86_MOV32_BASE_OFFSET_REG(codeblock_t *block, int base_reg, int offset, int dst_reg);
void host_x86_MOV8_REG_ABS(codeblock_t *block, int dst_reg, void *p);
void host_x86_MOV16_REG_ABS(codeblock_t *block, int dst_reg, void *p);
void host_x86_MOV32_REG_ABS(codeblock_t *block, int dst_reg, void *p);
void host_x86_MOV32_REG_ABS_INDEX_SHIFT(codeblock_t *block, int dst_reg, void *p, int idx_reg, int shift);
void host_x86_MOV8_REG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_addr, uint32_t addr, int base_reg, int idx_reg, int shift);
void host_x86_MOV32_REG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg);
void host_x86_MOV16_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset);
void host_x86_MOV32_REG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset);
void host_x86_MOV8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data);
void host_x86_MOV16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data);
void host_x86_MOV32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data);
void host_x86_MOV8_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MOV16_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MOV32_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
#define host_x86_MOV16_STACK_REG(block, offset, src_reg) host_x86_MOV16_BASE_OFFSET_REG(block, REG_ESP, offset, src_reg)
void host_x86_MOV32_STACK_IMM(codeblock_t *block, int32_t offset, uint32_t imm_data);
void host_x86_MOVSX_REG_16_8(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MOVSX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MOVSX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MOVZX_REG_16_8(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MOVZX_REG_32_8(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MOVZX_REG_32_16(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MOVZX_REG_ABS_16_8(codeblock_t *block, int dst_reg, void *p);
void host_x86_MOVZX_REG_ABS_32_8(codeblock_t *block, int dst_reg, void *p);
void host_x86_MOVZX_REG_ABS_32_16(codeblock_t *block, int dst_reg, void *p);
void host_x86_MOVZX_BASE_INDEX_32_8(codeblock_t *block, int dst_reg, int base_reg, int idx_reg);
void host_x86_MOVZX_BASE_INDEX_32_16(codeblock_t *block, int dst_reg, int base_reg, int idx_reg);
void host_x86_OR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_OR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_OR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_OR8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data);
void host_x86_OR16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data);
void host_x86_OR32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data);
void host_x86_POP(codeblock_t *block, int src_reg);
void host_x86_PUSH(codeblock_t *block, int src_reg);
void host_x86_RET(codeblock_t *block);
void host_x86_ROL8_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_ROL16_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_ROL32_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_ROL8_CL(codeblock_t *block, int dst_reg);
void host_x86_ROL16_CL(codeblock_t *block, int dst_reg);
void host_x86_ROL32_CL(codeblock_t *block, int dst_reg);
void host_x86_ROR8_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_ROR16_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_ROR32_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_ROR8_CL(codeblock_t *block, int dst_reg);
void host_x86_ROR16_CL(codeblock_t *block, int dst_reg);
void host_x86_ROR32_CL(codeblock_t *block, int dst_reg);
void host_x86_SAR8_CL(codeblock_t *block, int dst_reg);
void host_x86_SAR16_CL(codeblock_t *block, int dst_reg);
void host_x86_SAR32_CL(codeblock_t *block, int dst_reg);
void host_x86_SAR8_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_SAR16_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_SAR32_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_SHL8_CL(codeblock_t *block, int dst_reg);
void host_x86_SHL16_CL(codeblock_t *block, int dst_reg);
void host_x86_SHL32_CL(codeblock_t *block, int dst_reg);
void host_x86_SHL8_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_SHL16_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_SHL32_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_SHR8_CL(codeblock_t *block, int dst_reg);
void host_x86_SHR16_CL(codeblock_t *block, int dst_reg);
void host_x86_SHR32_CL(codeblock_t *block, int dst_reg);
void host_x86_SHR8_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_SHR16_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_SHR32_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_SUB8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data);
void host_x86_SUB16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data);
void host_x86_SUB32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data);
void host_x86_SUB8_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_SUB16_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_SUB32_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_TEST8_REG(codeblock_t *block, int src_host_reg, int dst_host_reg);
void host_x86_TEST16_REG(codeblock_t *block, int src_host_reg, int dst_host_reg);
void host_x86_TEST32_REG(codeblock_t *block, int src_host_reg, int dst_host_reg);
void host_x86_TEST32_REG_IMM(codeblock_t *block, int src_host_reg, uint32_t imm_data);
void host_x86_XOR8_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_XOR16_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_XOR32_REG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_XOR8_REG_IMM(codeblock_t *block, int dst_reg, uint8_t imm_data);
void host_x86_XOR16_REG_IMM(codeblock_t *block, int dst_reg, uint16_t imm_data);
void host_x86_XOR32_REG_IMM(codeblock_t *block, int dst_reg, uint32_t imm_data);

View file

@ -0,0 +1,80 @@
#if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined WIN32 || defined _WIN32 || defined _WIN32
#include "ibm.h"
#include "codegen.h"
#include "codegen_allocator.h"
#include "codegen_backend.h"
#include "codegen_backend_x86_defs.h"
#include "codegen_backend_x86_ops_fpu.h"
#include "codegen_backend_x86_ops_helpers.h"
void host_x87_FILDq_BASE(codeblock_t *block, int base_reg)
{
if (base_reg == REG_ESP)
{
codegen_alloc_bytes(block, 3);
codegen_addbyte3(block, 0xdf, 0x2c, 0x24); /*FILDq [ESP]*/
}
else
{
codegen_alloc_bytes(block, 2);
codegen_addbyte2(block, 0xdf, 0x28 | base_reg); /*FILDq [base_reg]*/
}
}
void host_x87_FISTPq_BASE(codeblock_t *block, int base_reg)
{
if (base_reg == REG_ESP)
{
codegen_alloc_bytes(block, 3);
codegen_addbyte3(block, 0xdf, 0x3c, 0x24); /*FISTPq [ESP]*/
}
else
{
codegen_alloc_bytes(block, 2);
codegen_addbyte2(block, 0xdf, 0x38 | base_reg); /*FISTPq [base_reg]*/
}
}
void host_x87_FLDCW(codeblock_t *block, void *p)
{
int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
if (offset >= -128 && offset < 127)
{
codegen_alloc_bytes(block, 3);
codegen_addbyte3(block, 0xd9, 0x68 | REG_EBP, offset); /*FLDCW offset[EBP]*/
}
else
{
codegen_alloc_bytes(block, 6);
codegen_addbyte2(block, 0xd9, 0x2d); /*FLDCW [p]*/
codegen_addlong(block, (uint32_t)p);
}
}
void host_x87_FLDd_BASE(codeblock_t *block, int base_reg)
{
if (base_reg == REG_ESP)
{
codegen_alloc_bytes(block, 3);
codegen_addbyte3(block, 0xdd, 0x04, 0x24); /*FILDq [ESP]*/
}
else
{
codegen_alloc_bytes(block, 2);
codegen_addbyte2(block, 0xdd, 0x08 | base_reg); /*FILDq [base_reg]*/
}
}
void host_x87_FSTPd_BASE(codeblock_t *block, int base_reg)
{
if (base_reg == REG_ESP)
{
codegen_alloc_bytes(block, 3);
codegen_addbyte3(block, 0xdd, 0x1c, 0x24); /*FILDq [ESP]*/
}
else
{
codegen_alloc_bytes(block, 2);
codegen_addbyte2(block, 0xdd, 0x18 | base_reg); /*FILDq [base_reg]*/
}
}
#endif

View file

@ -0,0 +1,5 @@
void host_x87_FILDq_BASE(codeblock_t *block, int base_reg);
void host_x87_FISTPq_BASE(codeblock_t *block, int base_reg);
void host_x87_FLDCW(codeblock_t *block, void *p);
void host_x87_FLDd_BASE(codeblock_t *block, int base_reg);
void host_x87_FSTPd_BASE(codeblock_t *block, int base_reg);

View file

@ -0,0 +1,84 @@
#define JMP_LEN_BYTES 5
static inline void codegen_addbyte(codeblock_t *block, uint8_t val)
{
if (block_pos >= BLOCK_MAX)
fatal("codegen_addbyte over! %i\n", block_pos);
block_write_data[block_pos++] = val;
}
static inline void codegen_addbyte2(codeblock_t *block, uint8_t vala, uint8_t valb)
{
if (block_pos > (BLOCK_MAX-2))
fatal("codegen_addbyte2 over! %i\n", block_pos);
block_write_data[block_pos++] = vala;
block_write_data[block_pos++] = valb;
}
static inline void codegen_addbyte3(codeblock_t *block, uint8_t vala, uint8_t valb, uint8_t valc)
{
if (block_pos > (BLOCK_MAX-3))
fatal("codegen_addbyte3 over! %i\n", block_pos);
block_write_data[block_pos++] = vala;
block_write_data[block_pos++] = valb;
block_write_data[block_pos++] = valc;
}
static inline void codegen_addbyte4(codeblock_t *block, uint8_t vala, uint8_t valb, uint8_t valc, uint8_t vald)
{
if (block_pos > (BLOCK_MAX-4))
fatal("codegen_addbyte4 over! %i\n", block_pos);
block_write_data[block_pos++] = vala;
block_write_data[block_pos++] = valb;
block_write_data[block_pos++] = valc;
block_write_data[block_pos++] = vald;
}
static inline void codegen_addword(codeblock_t *block, uint16_t val)
{
if (block_pos > (BLOCK_MAX-2))
fatal("codegen_addword over! %i\n", block_pos);
*(uint16_t *)&block_write_data[block_pos] = val;
block_pos += 2;
}
static inline void codegen_addlong(codeblock_t *block, uint32_t val)
{
if (block_pos > (BLOCK_MAX-4))
fatal("codegen_addlong over! %i\n", block_pos);
*(uint32_t *)&block_write_data[block_pos] = val;
block_pos += 4;
}
static inline void codegen_addquad(codeblock_t *block, uint64_t val)
{
if (block_pos > (BLOCK_MAX-8))
fatal("codegen_addquad over! %i\n", block_pos);
*(uint64_t *)&block_write_data[block_pos] = val;
block_pos += 8;
}
static void codegen_allocate_new_block(codeblock_t *block)
{
/*Current block is full. Allocate a new block*/
struct mem_block_t *new_block = codegen_allocator_allocate(block->head_mem_block, get_block_nr(block));
uint8_t *new_ptr = codeblock_allocator_get_ptr(new_block);
/*Add a jump instruction to the new block*/
codegen_addbyte(block, 0xe9); /*JMP*/
codegen_addlong(block, (uintptr_t)new_ptr - (uintptr_t)&block_write_data[block_pos + 4]);
/*Set write address to start of new block*/
block_pos = 0;
block_write_data = new_ptr;
}
static inline void codegen_alloc_bytes(codeblock_t *block, int size)
{
if (block_pos > ((BLOCK_MAX - size) - JMP_LEN_BYTES))
codegen_allocate_new_block(block);
}
static inline int is_imm8(uint32_t imm_data)
{
if (imm_data <= 0x7f || imm_data >= 0xffffff80)
return 1;
return 0;
}

View file

@ -0,0 +1,588 @@
#if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined WIN32 || defined _WIN32 || defined _WIN32
#include "ibm.h"
#include "codegen.h"
#include "codegen_allocator.h"
#include "codegen_backend.h"
#include "codegen_backend_x86_defs.h"
#include "codegen_backend_x86_ops_sse.h"
#include "codegen_backend_x86_ops_helpers.h"
void host_x86_ADDPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 3);
codegen_addbyte3(block, 0x0f, 0x58, 0xc0 | src_reg | (dst_reg << 3)); /*ADDPS dst_reg, src_reg*/
}
void host_x86_ADDSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0xf2, 0x0f, 0x58, 0xc0 | src_reg | (dst_reg << 3));
}
void host_x86_CMPPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg, int type)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x0f, 0xc2, 0xc0 | src_reg | (dst_reg << 3), type); /*CMPPS dst_reg, src_reg, type*/
}
void host_x86_COMISD_XREG_XREG(codeblock_t *block, int src_reg_a, int src_reg_b)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0x2e, 0xc0 | src_reg_b | (src_reg_a << 3));
}
void host_x86_CVTDQ2PS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 3);
codegen_addbyte3(block, 0x0f, 0x5b, 0xc0 | src_reg | (dst_reg << 3)); /*CVTDQ2PS dst_reg, src_reg*/
}
void host_x86_CVTPS2DQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0x5b, 0xc0 | src_reg | (dst_reg << 3)); /*CVTPS2DQ dst_reg, src_reg*/
}
void host_x86_CVTSD2SI_REG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0xf2, 0x0f, 0x2d, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSD2SI dst_reg, src_reg*/
}
void host_x86_CVTSD2SS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0xf2, 0x0f, 0x5a, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSD2SS dst_reg, src_reg*/
}
void host_x86_CVTSI2SD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0xf2, 0x0f, 0x2a, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSI2SD dst_reg, src_reg*/
}
void host_x86_CVTSI2SS_XREG_REG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0xf3, 0x0f, 0x2a, 0xc0 | src_reg | (dst_reg << 3)); /*CVTSI2SD dst_reg, src_reg*/
}
void host_x86_CVTSS2SD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0xf3, 0x0f, 0x5a, 0xc0 | src_reg | (dst_reg << 3));
}
void host_x86_CVTSS2SD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0xf3, 0x0f, 0x5a, 0x04 | (dst_reg << 3)); /*CVTSS2SD XMMx, [base_reg + idx_reg]*/
codegen_addbyte(block, base_reg | (idx_reg << 3));
}
void host_x86_DIVSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0xf2, 0x0f, 0x5e, 0xc0 | src_reg | (dst_reg << 3)); /*DIVSD dst_reg, src_reg*/
}
void host_x86_DIVSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0xf3, 0x0f, 0x5e, 0xc0 | src_reg | (dst_reg << 3)); /*DIVSS dst_reg, src_reg*/
}
void host_x86_LDMXCSR(codeblock_t *block, void *p)
{
int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
if (offset >= -128 && offset < 127)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x0f, 0xae, 0x50 | REG_EBP, offset); /*LDMXCSR offset[EBP]*/
}
else
{
codegen_alloc_bytes(block, 7);
codegen_addbyte3(block, 0x0f, 0xae, 0x15); /*LDMXCSR [p]*/
codegen_addlong(block, (uint32_t)p);
}
}
void host_x86_MAXSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0xf2, 0x0f, 0x5f, 0xc0 | src_reg | (dst_reg << 3)); /*MAXSD dst_reg, src_reg*/
}
void host_x86_MOVD_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0x66, 0x0f, 0x7e, 0x04 | (src_reg << 3)); /*MOVD XMMx, [base_reg + idx_reg]*/
codegen_addbyte(block, base_reg | (idx_reg << 3));
}
void host_x86_MOVD_REG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0x7e, 0xc0 | dst_reg | (src_reg << 3));
}
void host_x86_MOVD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0x66, 0x0f, 0x6e, 0x04 | (dst_reg << 3)); /*MOVD XMMx, [base_reg + idx_reg]*/
codegen_addbyte(block, base_reg | (idx_reg << 3));
}
void host_x86_MOVD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0x6e, 0xc0 | src_reg | (dst_reg << 3));
}
void host_x86_MOVQ_ABS_XREG(codeblock_t *block, void *p, int src_reg)
{
int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
if (offset >= -128 && offset < 127)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x45 | (src_reg << 3)); /*MOVQ offset[EBP], src_reg*/
codegen_addbyte(block, offset);
}
else
{
codegen_alloc_bytes(block, 8);
codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x05 | (src_reg << 3)); /*MOVQ [p], src_reg*/
codegen_addlong(block, (uint32_t)p);
}
}
void host_x86_MOVQ_ABS_REG_REG_SHIFT_XREG(codeblock_t *block, uint32_t addr, int src_reg_a, int src_reg_b, int shift, int src_reg)
{
if (addr < 0x80 || addr >= 0xffffff80)
{
codegen_alloc_bytes(block, 6);
codegen_addbyte3(block, 0x66, 0x0f, 0xd6); /*MOVQ addr[src_reg_a + src_reg_b << shift], XMMx*/
codegen_addbyte3(block, 0x44 | (src_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6), addr & 0xff);
}
else
{
codegen_alloc_bytes(block, 9);
codegen_addbyte3(block, 0x66, 0x0f, 0xd6); /*MOVQ addr[src_reg_a + src_reg_b << shift], XMMx*/
codegen_addbyte2(block, 0x84 | (src_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6));
codegen_addlong(block, addr);
}
}
void host_x86_MOVQ_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x04 | (src_reg << 3)); /*MOVQ XMMx, [base_reg + idx_reg]*/
codegen_addbyte(block, base_reg | (idx_reg << 3));
}
void host_x86_MOVQ_BASE_OFFSET_XREG(codeblock_t *block, int base_reg, int offset, int src_reg)
{
if (offset >= -128 && offset < 127)
{
if (base_reg == REG_ESP)
{
codegen_alloc_bytes(block, 6);
codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x44 | (src_reg << 3)); /*MOVQ [ESP + offset], XMMx*/
codegen_addbyte2(block, 0x24, offset);
}
else
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x40 | base_reg | (src_reg << 3)); /*MOVQ [base_reg + offset], XMMx*/
codegen_addbyte(block, offset);
}
}
else
fatal("MOVQ_BASE_OFFSET_XREG - offset %i\n", offset);
}
void host_x86_MOVQ_STACK_OFFSET_XREG(codeblock_t *block, int offset, int src_reg)
{
if (!offset)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x04 | (src_reg << 3)); /*MOVQ [ESP], src_reg*/
codegen_addbyte(block, 0x24);
}
else if (offset >= -80 || offset < 0x80)
{
codegen_alloc_bytes(block, 6);
codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x44 | (src_reg << 3)); /*MOVQ offset[ESP], src_reg*/
codegen_addbyte2(block, 0x24, offset & 0xff);
}
else
{
codegen_alloc_bytes(block, 9);
codegen_addbyte4(block, 0x66, 0x0f, 0xd6, 0x84 | (src_reg << 3)); /*MOVQ offset[ESP], src_reg*/
codegen_addbyte(block, 0x24);
codegen_addlong(block, offset);
}
}
void host_x86_MOVQ_XREG_ABS(codeblock_t *block, int dst_reg, void *p)
{
int offset = (uintptr_t)p - (((uintptr_t)&cpu_state) + 128);
if (offset >= -128 && offset < 127)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x45 | (dst_reg << 3)); /*MOVQ offset[EBP], src_reg*/
codegen_addbyte(block, offset);
}
else
{
codegen_alloc_bytes(block, 8);
codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x05 | (dst_reg << 3)); /*MOVQ [p], src_reg*/
codegen_addlong(block, (uint32_t)p);
}
}
void host_x86_MOVQ_XREG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32_t addr, int src_reg_a, int src_reg_b, int shift)
{
if (addr < 0x80 || addr >= 0xffffff80)
{
codegen_alloc_bytes(block, 6);
codegen_addbyte3(block, 0xf3, 0x0f, 0x7e); /*MOVQ XMMx, addr[src_reg_a + src_reg_b << shift]*/
codegen_addbyte3(block, 0x44 | (dst_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6), addr & 0xff);
}
else
{
codegen_alloc_bytes(block, 9);
codegen_addbyte3(block, 0xf3, 0x0f, 0x7e); /*MOVQ XMMx, addr[src_reg_a + src_reg_b << shift]*/
codegen_addbyte2(block, 0x84 | (dst_reg << 3), src_reg_a | (src_reg_b << 3) | (shift << 6));
codegen_addlong(block, addr);
}
}
void host_x86_MOVQ_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x04 | (dst_reg << 3)); /*MOVQ XMMx, [base_reg + idx_reg]*/
codegen_addbyte(block, base_reg | (idx_reg << 3));
}
void host_x86_MOVQ_XREG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset)
{
if (offset >= -128 && offset < 127)
{
if (base_reg == REG_ESP)
{
codegen_alloc_bytes(block, 6);
codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x44 | (dst_reg << 3)); /*MOVQ XMMx, [ESP + offset]*/
codegen_addbyte2(block, 0x24, offset);
}
else
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0x40 | base_reg | (dst_reg << 3)); /*MOVQ XMMx, [base_reg + offset]*/
codegen_addbyte(block, offset);
}
}
else
fatal("MOVQ_REG_BASE_OFFSET - offset %i\n", offset);
}
void host_x86_MOVQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0xf3, 0x0f, 0x7e, 0xc0 | src_reg | (dst_reg << 3)); /*MOVQ dst_reg, src_reg*/
}
void host_x86_MAXPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 3);
codegen_addbyte3(block, 0x0f, 0x5f, 0xc0 | src_reg | (dst_reg << 3)); /*MAXPS dst_reg, src_reg*/
}
void host_x86_MINPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 3);
codegen_addbyte3(block, 0x0f, 0x5d, 0xc0 | src_reg | (dst_reg << 3)); /*MINPS dst_reg, src_reg*/
}
void host_x86_MULPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 3);
codegen_addbyte3(block, 0x0f, 0x59, 0xc0 | src_reg | (dst_reg << 3)); /*MULPS dst_reg, src_reg*/
}
void host_x86_MULSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0xf2, 0x0f, 0x59, 0xc0 | src_reg | (dst_reg << 3));
}
void host_x86_PACKSSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 9);
codegen_addbyte4(block, 0x66, 0x0f, 0x63, 0xc0 | src_reg | (dst_reg << 3)); /*PACKSSWB dst_reg, src_reg*/
codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0x88 (move bits 64-95 to 32-63)*/
codegen_addbyte(block, 0x88);
}
void host_x86_PACKSSDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 9);
codegen_addbyte4(block, 0x66, 0x0f, 0x6b, 0xc0 | src_reg | (dst_reg << 3)); /*PACKSSDW dst_reg, src_reg*/
codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0x88 (move bits 64-95 to 32-63)*/
codegen_addbyte(block, 0x88);
}
void host_x86_PACKUSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 9);
codegen_addbyte4(block, 0x66, 0x0f, 0x67, 0xc0 | src_reg | (dst_reg << 3)); /*PACKUSWB dst_reg, src_reg*/
codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0x88 (move bits 64-95 to 32-63)*/
codegen_addbyte(block, 0x88);
}
void host_x86_PADDB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xfc, 0xc0 | src_reg | (dst_reg << 3)); /*PADDB dst_reg, src_reg*/
}
void host_x86_PADDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xfd, 0xc0 | src_reg | (dst_reg << 3)); /*PADDW dst_reg, src_reg*/
}
void host_x86_PADDD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xfe, 0xc0 | src_reg | (dst_reg << 3)); /*PADDD dst_reg, src_reg*/
}
void host_x86_PADDSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xec, 0xc0 | src_reg | (dst_reg << 3)); /*PADDSB dst_reg, src_reg*/
}
void host_x86_PADDSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xed, 0xc0 | src_reg | (dst_reg << 3)); /*PADDSW dst_reg, src_reg*/
}
void host_x86_PADDUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xdc, 0xc0 | src_reg | (dst_reg << 3)); /*PADDUSB dst_reg, src_reg*/
}
void host_x86_PADDUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xdd, 0xc0 | src_reg | (dst_reg << 3)); /*PADDUSW dst_reg, src_reg*/
}
void host_x86_PAND_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xdb, 0xc0 | src_reg | (dst_reg << 3)); /*PAND dst_reg, src_reg*/
}
void host_x86_PANDN_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xdf, 0xc0 | src_reg | (dst_reg << 3)); /*PANDN dst_reg, src_reg*/
}
void host_x86_POR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xeb, 0xc0 | src_reg | (dst_reg << 3)); /*POR dst_reg, src_reg*/
}
void host_x86_PXOR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xef, 0xc0 | src_reg | (dst_reg << 3)); /*PXOR dst_reg, src_reg*/
}
void host_x86_PCMPEQB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0x74, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQB dst_reg, src_reg*/
}
void host_x86_PCMPEQW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0x75, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQW dst_reg, src_reg*/
}
void host_x86_PCMPEQD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0x76, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPEQD dst_reg, src_reg*/
}
void host_x86_PCMPGTB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0x64, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTB dst_reg, src_reg*/
}
void host_x86_PCMPGTW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0x65, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTW dst_reg, src_reg*/
}
void host_x86_PCMPGTD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0x66, 0xc0 | src_reg | (dst_reg << 3)); /*PCMPGTD dst_reg, src_reg*/
}
void host_x86_PMADDWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xf5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/
}
void host_x86_PMULHW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xe5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/
}
void host_x86_PMULLW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xd5, 0xc0 | src_reg | (dst_reg << 3)); /*PMULLW dst_reg, src_reg*/
}
void host_x86_PSLLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x30 | dst_reg); /*PSLLW dst_reg, imm*/
codegen_addbyte(block, shift);
}
void host_x86_PSLLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x30 | dst_reg); /*PSLLD dst_reg, imm*/
codegen_addbyte(block, shift);
}
void host_x86_PSLLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x30 | dst_reg); /*PSLLD dst_reg, imm*/
codegen_addbyte(block, shift);
}
void host_x86_PSRAW_XREG_IMM(codeblock_t *block, int dst_reg, int shift)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x20 | dst_reg); /*PSRAW dst_reg, imm*/
codegen_addbyte(block, shift);
}
void host_x86_PSRAD_XREG_IMM(codeblock_t *block, int dst_reg, int shift)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x20 | dst_reg); /*PSRAD dst_reg, imm*/
codegen_addbyte(block, shift);
}
void host_x86_PSRAQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x20 | dst_reg); /*PSRAD dst_reg, imm*/
codegen_addbyte(block, shift);
}
void host_x86_PSRLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0x66, 0x0f, 0x71, 0xc0 | 0x10 | dst_reg); /*PSRLW dst_reg, imm*/
codegen_addbyte(block, shift);
}
void host_x86_PSRLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0x66, 0x0f, 0x72, 0xc0 | 0x10 | dst_reg); /*PSRLD dst_reg, imm*/
codegen_addbyte(block, shift);
}
void host_x86_PSRLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift)
{
codegen_alloc_bytes(block, 5);
codegen_addbyte4(block, 0x66, 0x0f, 0x73, 0xc0 | 0x10 | dst_reg); /*PSRLD dst_reg, imm*/
codegen_addbyte(block, shift);
}
void host_x86_PSUBB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xf8, 0xc0 | src_reg | (dst_reg << 3)); /*PADDB dst_reg, src_reg*/
}
void host_x86_PSUBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xf9, 0xc0 | src_reg | (dst_reg << 3)); /*PADDW dst_reg, src_reg*/
}
void host_x86_PSUBD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xfa, 0xc0 | src_reg | (dst_reg << 3)); /*PADDD dst_reg, src_reg*/
}
void host_x86_PSUBSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xe8, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBSB dst_reg, src_reg*/
}
void host_x86_PSUBSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xe9, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBSW dst_reg, src_reg*/
}
void host_x86_PSUBUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xd8, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBUSB dst_reg, src_reg*/
}
void host_x86_PSUBUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0xd9, 0xc0 | src_reg | (dst_reg << 3)); /*PSUBUSW dst_reg, src_reg*/
}
void host_x86_PUNPCKHBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 9);
codegen_addbyte4(block, 0x66, 0x0f, 0x60, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLBW dst_reg, src_reg*/
codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0xee (move top 64-bits to low 64-bits)*/
codegen_addbyte(block, 0xee);
}
void host_x86_PUNPCKHWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 9);
codegen_addbyte4(block, 0x66, 0x0f, 0x61, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLWD dst_reg, src_reg*/
codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0xee (move top 64-bits to low 64-bits)*/
codegen_addbyte(block, 0xee);
}
void host_x86_PUNPCKHDQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 9);
codegen_addbyte4(block, 0x66, 0x0f, 0x62, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLDQ dst_reg, src_reg*/
codegen_addbyte4(block, 0x66, 0x0f, 0x70, 0xc0 | dst_reg | (dst_reg << 3)); /*PSHUFD dst_reg, dst_reg, 0xee (move top 64-bits to low 64-bits)*/
codegen_addbyte(block, 0xee);
}
void host_x86_PUNPCKLBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0x60, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLBW dst_reg, src_reg*/
}
void host_x86_PUNPCKLWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0x61, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLWD dst_reg, src_reg*/
}
void host_x86_PUNPCKLDQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0x66, 0x0f, 0x62, 0xc0 | src_reg | (dst_reg << 3)); /*PUNPCKLDQ dst_reg, src_reg*/
}
void host_x86_SQRTSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0xf2, 0x0f, 0x51, 0xc0 | src_reg | (dst_reg << 3)); /*SQRTSD dst_reg, src_reg*/
}
void host_x86_SQRTSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0xf3, 0x0f, 0x51, 0xc0 | src_reg | (dst_reg << 3)); /*SQRTSS dst_reg, src_reg*/
}
void host_x86_SUBPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 3);
codegen_addbyte3(block, 0x0f, 0x5c, 0xc0 | src_reg | (dst_reg << 3)); /*SUBPS dst_reg, src_reg*/
}
void host_x86_SUBSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 4);
codegen_addbyte4(block, 0xf2, 0x0f, 0x5c, 0xc0 | src_reg | (dst_reg << 3));
}
void host_x86_UNPCKLPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg)
{
codegen_alloc_bytes(block, 3);
codegen_addbyte3(block, 0x0f, 0x14, 0xc0 | src_reg | (dst_reg << 3));
}
#endif

View file

@ -0,0 +1,112 @@
void host_x86_ADDPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_ADDSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
#define CMPPS_EQ 0
#define CMPPS_NLT 5
#define CMPPS_NLE 6
void host_x86_CMPPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg, int type);
void host_x86_COMISD_XREG_XREG(codeblock_t *block, int src_reg_a, int src_reg_b);
void host_x86_CVTDQ2PS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_CVTPS2DQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_CVTSD2SI_REG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_CVTSD2SS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_CVTSI2SD_XREG_REG(codeblock_t *block, int dest_reg, int src_reg);
void host_x86_CVTSI2SS_XREG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_CVTSS2SD_XREG_XREG(codeblock_t *block, int dest_reg, int src_reg);
void host_x86_CVTSS2SD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg);
void host_x86_DIVSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_DIVSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_LDMXCSR(codeblock_t *block, void *p);
void host_x86_MAXSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MOVD_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg);
void host_x86_MOVD_REG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MOVD_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg);
void host_x86_MOVD_XREG_REG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MOVQ_ABS_XREG(codeblock_t *block, void *p, int src_reg);
void host_x86_MOVQ_ABS_REG_REG_SHIFT_XREG(codeblock_t *block, uint32_t addr, int src_reg_a, int src_reg_b, int shift, int src_reg);
void host_x86_MOVQ_BASE_INDEX_XREG(codeblock_t *block, int base_reg, int idx_reg, int src_reg);
void host_x86_MOVQ_BASE_OFFSET_XREG(codeblock_t *block, int base_reg, int offset, int src_reg);
void host_x86_MOVQ_STACK_OFFSET_XREG(codeblock_t *block, int offset, int src_reg);
void host_x86_MOVQ_XREG_ABS(codeblock_t *block, int dst_reg, void *p);
void host_x86_MOVQ_XREG_ABS_REG_REG_SHIFT(codeblock_t *block, int dst_reg, uint32_t addr, int src_reg_a, int src_reg_b, int shift);
void host_x86_MOVQ_XREG_BASE_INDEX(codeblock_t *block, int dst_reg, int base_reg, int idx_reg);
void host_x86_MOVQ_XREG_BASE_OFFSET(codeblock_t *block, int dst_reg, int base_reg, int offset);
void host_x86_MOVQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MAXPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MINPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MULPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_MULSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PACKSSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PACKSSDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PACKUSWB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PADDB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PADDW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PADDD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PADDSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PADDSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PADDUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PADDUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PAND_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PANDN_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_POR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PXOR_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PCMPEQB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PCMPEQW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PCMPEQD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PCMPGTB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PCMPGTW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PCMPGTD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PMADDWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PMULHW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PMULLW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PSLLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_PSLLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_PSLLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_PSRAW_XREG_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_PSRAD_XREG_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_PSRAQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_PSRLW_XREG_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_PSRLD_XREG_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_PSRLQ_XREG_IMM(codeblock_t *block, int dst_reg, int shift);
void host_x86_PSUBB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PSUBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PSUBD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PSUBSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PSUBSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PSUBUSB_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PSUBUSW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PUNPCKHBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PUNPCKHWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PUNPCKHDQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PUNPCKLBW_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PUNPCKLWD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_PUNPCKLDQ_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_SQRTSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_SQRTSS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_SUBPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_SUBSD_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);
void host_x86_UNPCKLPS_XREG_XREG(codeblock_t *block, int dst_reg, int src_reg);

File diff suppressed because it is too large Load diff

190
src/codegen_ir.c Normal file
View file

@ -0,0 +1,190 @@
#include "ibm.h"
#include "codegen.h"
#include "codegen_allocator.h"
#include "codegen_backend.h"
#include "codegen_ir.h"
#include "codegen_reg.h"
extern int has_ea;
static ir_data_t ir_block;
static int codegen_unroll_start, codegen_unroll_count;
static int codegen_unroll_first_instruction;
ir_data_t *codegen_ir_init()
{
ir_block.wr_pos = 0;
// pclog("codegen_ir_init %04x:%04x\n", CS,cpu_state.pc);
codegen_unroll_count = 0;
return &ir_block;
}
void codegen_ir_set_unroll(int count, int start, int first_instruction)
{
codegen_unroll_count = count;
codegen_unroll_start = start;
codegen_unroll_first_instruction = first_instruction;
}
static void duplicate_uop(ir_data_t *ir, uop_t *uop, int offset)
{
uop_t *new_uop = uop_alloc(ir, uop->type);
// pclog(" uop type %08x\n", uop->type);
if (!ir_reg_is_invalid(uop->src_reg_a))
new_uop->src_reg_a = codegen_reg_read(uop->src_reg_a.reg);
if (!ir_reg_is_invalid(uop->src_reg_b))
new_uop->src_reg_b = codegen_reg_read(uop->src_reg_b.reg);
if (!ir_reg_is_invalid(uop->src_reg_c))
new_uop->src_reg_c = codegen_reg_read(uop->src_reg_c.reg);
if (!ir_reg_is_invalid(uop->dest_reg_a))
new_uop->dest_reg_a = codegen_reg_write(uop->dest_reg_a.reg, ir->wr_pos-1);
new_uop->type = uop->type;
new_uop->imm_data = uop->imm_data;
new_uop->p = uop->p;
new_uop->pc = uop->pc;
if (uop->jump_dest_uop != -1)
{
new_uop->jump_dest_uop = uop->jump_dest_uop + offset;
}
}
void codegen_ir_compile(ir_data_t *ir, codeblock_t *block)
{
int jump_target_at_end = -1;
int c;
if (codegen_unroll_count)
{
int unroll_count;
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++)
{
int offset = ir->wr_pos - codegen_unroll_start;
// pclog("Unroll from %i to %i, offset %i - iteration %i\n", codegen_unroll_start, ir->wr_pos, offset, unroll_count);
for (c = codegen_unroll_start; c < unroll_end; c++)
{
// pclog(" Duplicate uop %i\n", c);
duplicate_uop(ir, &ir->uops[c], offset);
}
}
}
codegen_reg_mark_as_required();
codegen_reg_process_dead_list(ir);
block_write_data = codeblock_allocator_get_ptr(block->head_mem_block);
block_pos = 0;
codegen_backend_prologue(block);
for (c = 0; c < ir->wr_pos; c++)
{
uop_t *uop = &ir->uops[c];
// pclog("uOP %i : %08x\n", c, uop->type);
if (uop->type & UOP_TYPE_BARRIER)
codegen_reg_flush_invalidate(ir, block);
if (uop->type & UOP_TYPE_JUMP_DEST)
{
uop_t *uop_dest = uop;
while (uop_dest->jump_list_next != -1)
{
uop_dest = &ir->uops[uop_dest->jump_list_next];
codegen_set_jump_dest(block, uop_dest->p);
}
}
if ((uop->type & UOP_MASK) == UOP_INVALID)
continue;
if (uop->type & UOP_TYPE_PARAMS_REGS)
{
codegen_reg_alloc_register(uop->dest_reg_a, uop->src_reg_a, uop->src_reg_b, uop->src_reg_c);
if (uop->src_reg_a.reg != IREG_INVALID)
{
uop->src_reg_a_real = codegen_reg_alloc_read_reg(block, uop->src_reg_a, NULL);
}
if (uop->src_reg_b.reg != IREG_INVALID)
{
uop->src_reg_b_real = codegen_reg_alloc_read_reg(block, uop->src_reg_b, NULL);
}
if (uop->src_reg_c.reg != IREG_INVALID)
{
uop->src_reg_c_real = codegen_reg_alloc_read_reg(block, uop->src_reg_c, NULL);
}
}
if (uop->type & UOP_TYPE_ORDER_BARRIER)
codegen_reg_flush(ir, block);
if (uop->type & UOP_TYPE_PARAMS_REGS)
{
if (uop->dest_reg_a.reg != IREG_INVALID)
{
uop->dest_reg_a_real = codegen_reg_alloc_write_reg(block, uop->dest_reg_a);
}
}
if (!uop_handlers[uop->type & UOP_MASK])
fatal("!uop_handlers[uop->type & UOP_MASK] %08x\n", uop->type);
uop_handlers[uop->type & UOP_MASK](block, uop);
if (uop->type & UOP_TYPE_JUMP)
{
if (uop->jump_dest_uop == ir->wr_pos)
{
if (jump_target_at_end == -1)
jump_target_at_end = c;
else
{
uop_t *uop_dest = &ir->uops[jump_target_at_end];
while (uop_dest->jump_list_next != -1)
uop_dest = &ir->uops[uop_dest->jump_list_next];
uop_dest->jump_list_next = c;
}
}
else
{
uop_t *uop_dest = &ir->uops[uop->jump_dest_uop];
while (uop_dest->jump_list_next != -1)
uop_dest = &ir->uops[uop_dest->jump_list_next];
uop_dest->jump_list_next = c;
ir->uops[uop->jump_dest_uop].type |= UOP_TYPE_JUMP_DEST;
}
}
}
codegen_reg_flush_invalidate(ir, block);
if (jump_target_at_end != -1)
{
uop_t *uop_dest = &ir->uops[jump_target_at_end];
while (1)
{
codegen_set_jump_dest(block, uop_dest->p);
if (uop_dest->jump_list_next == -1)
break;
uop_dest = &ir->uops[uop_dest->jump_list_next];
}
}
codegen_backend_epilogue(block);
block_write_data = NULL;
// if (has_ea)
// fatal("IR compilation complete\n");
}

6
src/codegen_ir.h Normal file
View file

@ -0,0 +1,6 @@
#include "codegen_ir_defs.h"
ir_data_t *codegen_ir_init();
void codegen_ir_set_unroll(int count, int start, int first_instruction);
void codegen_ir_compile(ir_data_t *ir, codeblock_t *block);

810
src/codegen_ir_defs.h Normal file
View file

@ -0,0 +1,810 @@
#ifndef _CODEGEN_IR_DEFS_
#define _CODEGEN_IR_DEFS_
#include "codegen_reg.h"
#define UOP_REG(reg, size, version) ((reg) | (size) | (version << 8))
/*uOP is a barrier. All previous uOPs must have completed before this one executes.
All registers must have been written back or discarded.
This should be used when calling external functions that may change any emulated
registers.*/
#define UOP_TYPE_BARRIER (1 << 31)
/*uOP is a barrier. All previous uOPs must have completed before this one executes.
All registers must have been written back, but do not have to be discarded.
This should be used when calling functions that preserve registers, but can cause
the code block to exit (eg memory load/store functions).*/
#define UOP_TYPE_ORDER_BARRIER (1 << 27)
/*uOP uses source and dest registers*/
#define UOP_TYPE_PARAMS_REGS (1 << 28)
/*uOP uses pointer*/
#define UOP_TYPE_PARAMS_POINTER (1 << 29)
/*uOP uses immediate data*/
#define UOP_TYPE_PARAMS_IMM (1 << 30)
/*uOP is a jump, with the destination uOP in uop->jump_dest_uop. The compiler must
set jump_dest in the destination uOP to the address of the branch offset to be
written when known.*/
#define UOP_TYPE_JUMP (1 << 26)
/*uOP is the destination of a jump, and must set the destination offset of the jump
at compile time.*/
#define UOP_TYPE_JUMP_DEST (1 << 25)
#define UOP_LOAD_FUNC_ARG_0 (UOP_TYPE_PARAMS_REGS | 0x00)
#define UOP_LOAD_FUNC_ARG_1 (UOP_TYPE_PARAMS_REGS | 0x01)
#define UOP_LOAD_FUNC_ARG_2 (UOP_TYPE_PARAMS_REGS | 0x02)
#define UOP_LOAD_FUNC_ARG_3 (UOP_TYPE_PARAMS_REGS | 0x03)
#define UOP_LOAD_FUNC_ARG_0_IMM (UOP_TYPE_PARAMS_IMM | 0x08 | UOP_TYPE_BARRIER)
#define UOP_LOAD_FUNC_ARG_1_IMM (UOP_TYPE_PARAMS_IMM | 0x09 | UOP_TYPE_BARRIER)
#define UOP_LOAD_FUNC_ARG_2_IMM (UOP_TYPE_PARAMS_IMM | 0x0a | UOP_TYPE_BARRIER)
#define UOP_LOAD_FUNC_ARG_3_IMM (UOP_TYPE_PARAMS_IMM | 0x0b | UOP_TYPE_BARRIER)
#define UOP_CALL_FUNC (UOP_TYPE_PARAMS_POINTER | 0x10 | UOP_TYPE_BARRIER)
/*UOP_CALL_INSTRUCTION_FUNC - call instruction handler at p, check return value and exit block if non-zero*/
#define UOP_CALL_INSTRUCTION_FUNC (UOP_TYPE_PARAMS_POINTER | 0x11 | UOP_TYPE_BARRIER)
#define UOP_STORE_P_IMM (UOP_TYPE_PARAMS_IMM | 0x12)
#define UOP_STORE_P_IMM_8 (UOP_TYPE_PARAMS_IMM | 0x13)
/*UOP_LOAD_SEG - load segment in src_reg_a to segment p via loadseg(), check return value and exit block if non-zero*/
#define UOP_LOAD_SEG (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x14 | UOP_TYPE_BARRIER)
/*UOP_JMP - jump to ptr*/
#define UOP_JMP (UOP_TYPE_PARAMS_POINTER | 0x15 | UOP_TYPE_ORDER_BARRIER)
/*UOP_CALL_FUNC - call instruction handler at p, dest_reg = return value*/
#define UOP_CALL_FUNC_RESULT (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x16 | UOP_TYPE_BARRIER)
/*UOP_JMP_DEST - jump to ptr*/
#define UOP_JMP_DEST (UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x17 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP)
#define UOP_NOP_BARRIER (UOP_TYPE_BARRIER | 0x18)
#ifdef DEBUG_EXTRA
/*UOP_LOG_INSTR - log non-recompiled instruction in imm_data*/
#define UOP_LOG_INSTR (UOP_TYPE_PARAMS_IMM | 0x1f)
#endif
/*UOP_MOV_PTR - dest_reg = p*/
#define UOP_MOV_PTR (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x20)
/*UOP_MOV_IMM - dest_reg = imm_data*/
#define UOP_MOV_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x21)
/*UOP_MOV - dest_reg = src_reg_a*/
#define UOP_MOV (UOP_TYPE_PARAMS_REGS | 0x22)
/*UOP_MOVZX - dest_reg = zero_extend(src_reg_a)*/
#define UOP_MOVZX (UOP_TYPE_PARAMS_REGS | 0x23)
/*UOP_MOVSX - dest_reg = sign_extend(src_reg_a)*/
#define UOP_MOVSX (UOP_TYPE_PARAMS_REGS | 0x24)
/*UOP_MOV_DOUBLE_INT - dest_reg = (double)src_reg_a*/
#define UOP_MOV_DOUBLE_INT (UOP_TYPE_PARAMS_REGS | 0x25)
/*UOP_MOV_INT_DOUBLE - dest_reg = (int)src_reg_a. New rounding control in src_reg_b, old rounding control in src_reg_c*/
#define UOP_MOV_INT_DOUBLE (UOP_TYPE_PARAMS_REGS | 0x26)
/*UOP_MOV_INT_DOUBLE_64 - dest_reg = (int)src_reg_a. New rounding control in src_reg_b, old rounding control in src_reg_c*/
#define UOP_MOV_INT_DOUBLE_64 (UOP_TYPE_PARAMS_REGS | 0x27)
/*UOP_MOV_REG_PTR - dest_reg = *p*/
#define UOP_MOV_REG_PTR (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x28)
/*UOP_MOVZX_REG_PTR_8 - dest_reg = *(uint8_t *)p*/
#define UOP_MOVZX_REG_PTR_8 (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x29)
/*UOP_MOVZX_REG_PTR_16 - dest_reg = *(uint16_t *)p*/
#define UOP_MOVZX_REG_PTR_16 (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x2a)
/*UOP_ADD - dest_reg = src_reg_a + src_reg_b*/
#define UOP_ADD (UOP_TYPE_PARAMS_REGS | 0x30)
/*UOP_ADD_IMM - dest_reg = src_reg_a + immediate*/
#define UOP_ADD_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x31)
/*UOP_AND - dest_reg = src_reg_a & src_reg_b*/
#define UOP_AND (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x32)
/*UOP_AND_IMM - dest_reg = src_reg_a & immediate*/
#define UOP_AND_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x33)
/*UOP_ADD_LSHIFT - dest_reg = src_reg_a + (src_reg_b << imm_data)
Intended for EA calcluations, imm_data must be between 0 and 3*/
#define UOP_ADD_LSHIFT (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x34)
/*UOP_OR - dest_reg = src_reg_a | src_reg_b*/
#define UOP_OR (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x35)
/*UOP_OR_IMM - dest_reg = src_reg_a | immediate*/
#define UOP_OR_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x36)
/*UOP_SUB - dest_reg = src_reg_a - src_reg_b*/
#define UOP_SUB (UOP_TYPE_PARAMS_REGS | 0x37)
/*UOP_SUB_IMM - dest_reg = src_reg_a - immediate*/
#define UOP_SUB_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x38)
/*UOP_XOR - dest_reg = src_reg_a ^ src_reg_b*/
#define UOP_XOR (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x39)
/*UOP_XOR_IMM - dest_reg = src_reg_a ^ immediate*/
#define UOP_XOR_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x3a)
/*UOP_ANDN - dest_reg = ~src_reg_a & src_reg_b*/
#define UOP_ANDN (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x3b)
/*UOP_MEM_LOAD_ABS - dest_reg = src_reg_a:[immediate]*/
#define UOP_MEM_LOAD_ABS (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x40 | UOP_TYPE_ORDER_BARRIER)
/*UOP_MEM_LOAD_REG - dest_reg = src_reg_a:[src_reg_b]*/
#define UOP_MEM_LOAD_REG (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x41 | UOP_TYPE_ORDER_BARRIER)
/*UOP_MEM_STORE_ABS - src_reg_a:[immediate] = src_reg_b*/
#define UOP_MEM_STORE_ABS (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x42 | UOP_TYPE_ORDER_BARRIER)
/*UOP_MEM_STORE_REG - src_reg_a:[src_reg_b] = src_reg_c*/
#define UOP_MEM_STORE_REG (UOP_TYPE_PARAMS_REGS | 0x43 | UOP_TYPE_ORDER_BARRIER)
/*UOP_MEM_STORE_IMM_8 - byte src_reg_a:[src_reg_b] = imm_data*/
#define UOP_MEM_STORE_IMM_8 (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x44 | UOP_TYPE_ORDER_BARRIER)
/*UOP_MEM_STORE_IMM_16 - word src_reg_a:[src_reg_b] = imm_data*/
#define UOP_MEM_STORE_IMM_16 (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x45 | UOP_TYPE_ORDER_BARRIER)
/*UOP_MEM_STORE_IMM_32 - long src_reg_a:[src_reg_b] = imm_data*/
#define UOP_MEM_STORE_IMM_32 (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x46 | UOP_TYPE_ORDER_BARRIER)
/*UOP_MEM_LOAD_SINGLE - dest_reg = (float)src_reg_a:[src_reg_b]*/
#define UOP_MEM_LOAD_SINGLE (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x47 | UOP_TYPE_ORDER_BARRIER)
/*UOP_CMP_IMM_JZ - if (src_reg_a == imm_data) then jump to ptr*/
#define UOP_CMP_IMM_JZ (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x48 | UOP_TYPE_ORDER_BARRIER)
/*UOP_MEM_LOAD_DOUBLE - dest_reg = (double)src_reg_a:[src_reg_b]*/
#define UOP_MEM_LOAD_DOUBLE (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x49 | UOP_TYPE_ORDER_BARRIER)
/*UOP_MEM_STORE_SINGLE - src_reg_a:[src_reg_b] = src_reg_c*/
#define UOP_MEM_STORE_SINGLE (UOP_TYPE_PARAMS_REGS | 0x4a | UOP_TYPE_ORDER_BARRIER)
/*UOP_MEM_STORE_DOUBLE - src_reg_a:[src_reg_b] = src_reg_c*/
#define UOP_MEM_STORE_DOUBLE (UOP_TYPE_PARAMS_REGS | 0x4b | UOP_TYPE_ORDER_BARRIER)
/*UOP_CMP_JB - if (src_reg_a < src_reg_b) then jump to ptr*/
#define UOP_CMP_JB (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x4c | UOP_TYPE_ORDER_BARRIER)
/*UOP_CMP_JNBE - if (src_reg_a > src_reg_b) then jump to ptr*/
#define UOP_CMP_JNBE (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_POINTER | 0x4d | UOP_TYPE_ORDER_BARRIER)
/*UOP_SAR - dest_reg = src_reg_a >> src_reg_b*/
#define UOP_SAR (UOP_TYPE_PARAMS_REGS | 0x50)
/*UOP_SAR_IMM - dest_reg = src_reg_a >> immediate*/
#define UOP_SAR_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x51)
/*UOP_SHL - dest_reg = src_reg_a << src_reg_b*/
#define UOP_SHL (UOP_TYPE_PARAMS_REGS | 0x52)
/*UOP_SHL_IMM - dest_reg = src_reg_a << immediate*/
#define UOP_SHL_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x53)
/*UOP_SHR - dest_reg = src_reg_a >> src_reg_b*/
#define UOP_SHR (UOP_TYPE_PARAMS_REGS | 0x54)
/*UOP_SHR_IMM - dest_reg = src_reg_a >> immediate*/
#define UOP_SHR_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x55)
/*UOP_ROL - dest_reg = src_reg_a rotate<< src_reg_b*/
#define UOP_ROL (UOP_TYPE_PARAMS_REGS | 0x56)
/*UOP_ROL_IMM - dest_reg = src_reg_a rotate<< immediate*/
#define UOP_ROL_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x57)
/*UOP_ROR - dest_reg = src_reg_a rotate>> src_reg_b*/
#define UOP_ROR (UOP_TYPE_PARAMS_REGS | 0x58)
/*UOP_ROR_IMM - dest_reg = src_reg_a rotate>> immediate*/
#define UOP_ROR_IMM (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | 0x59)
/*UOP_CMP_IMM_JZ_DEST - if (src_reg_a == imm_data) then jump to ptr*/
#define UOP_CMP_IMM_JZ_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x60 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP)
/*UOP_CMP_IMM_JNZ_DEST - if (src_reg_a != imm_data) then jump to ptr*/
#define UOP_CMP_IMM_JNZ_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x61 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP)
/*UOP_CMP_JB_DEST - if (src_reg_a < src_reg_b) then jump to ptr*/
#define UOP_CMP_JB_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x62 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP)
/*UOP_CMP_JNB_DEST - if (src_reg_a >= src_reg_b) then jump to ptr*/
#define UOP_CMP_JNB_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x63 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP)
/*UOP_CMP_JO_DEST - if (src_reg_a < src_reg_b) then jump to ptr*/
#define UOP_CMP_JO_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x64 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP)
/*UOP_CMP_JNO_DEST - if (src_reg_a >= src_reg_b) then jump to ptr*/
#define UOP_CMP_JNO_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x65 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP)
/*UOP_CMP_JZ_DEST - if (src_reg_a == src_reg_b) then jump to ptr*/
#define UOP_CMP_JZ_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x66 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP)
/*UOP_CMP_JNZ_DEST - if (src_reg_a != src_reg_b) then jump to ptr*/
#define UOP_CMP_JNZ_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x67 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP)
/*UOP_CMP_JL_DEST - if (signed)(src_reg_a < src_reg_b) then jump to ptr*/
#define UOP_CMP_JL_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x68 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP)
/*UOP_CMP_JNL_DEST - if (signed)(src_reg_a >= src_reg_b) then jump to ptr*/
#define UOP_CMP_JNL_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x69 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP)
/*UOP_CMP_JBE_DEST - if (src_reg_a <= src_reg_b) then jump to ptr*/
#define UOP_CMP_JBE_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x6a | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP)
/*UOP_CMP_JNBE_DEST - if (src_reg_a > src_reg_b) then jump to ptr*/
#define UOP_CMP_JNBE_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x6b | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP)
/*UOP_CMP_JLE_DEST - if (signed)(src_reg_a <= src_reg_b) then jump to ptr*/
#define UOP_CMP_JLE_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x6c | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP)
/*UOP_CMP_JNLE_DEST - if (signed)(src_reg_a > src_reg_b) then jump to ptr*/
#define UOP_CMP_JNLE_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x6d | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP)
/*UOP_TEST_JNS_DEST - if (src_reg_a positive) then jump to ptr*/
#define UOP_TEST_JNS_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x70 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP)
/*UOP_TEST_JS_DEST - if (src_reg_a positive) then jump to ptr*/
#define UOP_TEST_JS_DEST (UOP_TYPE_PARAMS_REGS | UOP_TYPE_PARAMS_IMM | UOP_TYPE_PARAMS_POINTER | 0x71 | UOP_TYPE_ORDER_BARRIER | UOP_TYPE_JUMP)
/*UOP_FP_ENTER - must be called before any FPU register accessed*/
#define UOP_FP_ENTER (UOP_TYPE_PARAMS_IMM | 0x80 | UOP_TYPE_BARRIER)
/*UOP_FADD - (floating point) dest_reg = src_reg_a + src_reg_b*/
#define UOP_FADD (UOP_TYPE_PARAMS_REGS | 0x81)
/*UOP_FSUB - (floating point) dest_reg = src_reg_a - src_reg_b*/
#define UOP_FSUB (UOP_TYPE_PARAMS_REGS | 0x82)
/*UOP_FMUL - (floating point) dest_reg = src_reg_a * src_reg_b*/
#define UOP_FMUL (UOP_TYPE_PARAMS_REGS | 0x83)
/*UOP_FDIV - (floating point) dest_reg = src_reg_a / src_reg_b*/
#define UOP_FDIV (UOP_TYPE_PARAMS_REGS | 0x84)
/*UOP_FCOM - dest_reg = flags from compare(src_reg_a, src_reg_b)*/
#define UOP_FCOM (UOP_TYPE_PARAMS_REGS | 0x85)
/*UOP_FABS - dest_reg = fabs(src_reg_a)*/
#define UOP_FABS (UOP_TYPE_PARAMS_REGS | 0x86)
/*UOP_FCHS - dest_reg = fabs(src_reg_a)*/
#define UOP_FCHS (UOP_TYPE_PARAMS_REGS | 0x87)
/*UOP_FTST - dest_reg = flags from compare(src_reg_a, 0)*/
#define UOP_FTST (UOP_TYPE_PARAMS_REGS | 0x88)
/*UOP_FSQRT - dest_reg = fsqrt(src_reg_a)*/
#define UOP_FSQRT (UOP_TYPE_PARAMS_REGS | 0x89)
/*UOP_MMX_ENTER - must be called before any MMX registers accessed*/
#define UOP_MMX_ENTER (UOP_TYPE_PARAMS_IMM | 0x90 | UOP_TYPE_BARRIER)
/*UOP_PADDB - (packed byte) dest_reg = src_reg_a + src_reg_b*/
#define UOP_PADDB (UOP_TYPE_PARAMS_REGS | 0x91)
/*UOP_PADDW - (packed word) dest_reg = src_reg_a + src_reg_b*/
#define UOP_PADDW (UOP_TYPE_PARAMS_REGS | 0x92)
/*UOP_PADDD - (packed long) dest_reg = src_reg_a + src_reg_b*/
#define UOP_PADDD (UOP_TYPE_PARAMS_REGS | 0x93)
/*UOP_PADDSB - (packed byte with signed saturation) dest_reg = src_reg_a + src_reg_b*/
#define UOP_PADDSB (UOP_TYPE_PARAMS_REGS | 0x94)
/*UOP_PADDSW - (packed word with signed saturation) dest_reg = src_reg_a + src_reg_b*/
#define UOP_PADDSW (UOP_TYPE_PARAMS_REGS | 0x95)
/*UOP_PADDUSB - (packed byte with unsigned saturation) dest_reg = src_reg_a + src_reg_b*/
#define UOP_PADDUSB (UOP_TYPE_PARAMS_REGS | 0x96)
/*UOP_PADDUSW - (packed word with unsigned saturation) dest_reg = src_reg_a + src_reg_b*/
#define UOP_PADDUSW (UOP_TYPE_PARAMS_REGS | 0x97)
/*UOP_PSUBB - (packed byte) dest_reg = src_reg_a - src_reg_b*/
#define UOP_PSUBB (UOP_TYPE_PARAMS_REGS | 0x98)
/*UOP_PSUBW - (packed word) dest_reg = src_reg_a - src_reg_b*/
#define UOP_PSUBW (UOP_TYPE_PARAMS_REGS | 0x99)
/*UOP_PSUBD - (packed long) dest_reg = src_reg_a - src_reg_b*/
#define UOP_PSUBD (UOP_TYPE_PARAMS_REGS | 0x9a)
/*UOP_PSUBSB - (packed byte with signed saturation) dest_reg = src_reg_a - src_reg_b*/
#define UOP_PSUBSB (UOP_TYPE_PARAMS_REGS | 0x9b)
/*UOP_PSUBSW - (packed word with signed saturation) dest_reg = src_reg_a - src_reg_b*/
#define UOP_PSUBSW (UOP_TYPE_PARAMS_REGS | 0x9c)
/*UOP_PSUBUSB - (packed byte with unsigned saturation) dest_reg = src_reg_a - src_reg_b*/
#define UOP_PSUBUSB (UOP_TYPE_PARAMS_REGS | 0x9d)
/*UOP_PSUBUSW - (packed word with unsigned saturation) dest_reg = src_reg_a - src_reg_b*/
#define UOP_PSUBUSW (UOP_TYPE_PARAMS_REGS | 0x9e)
/*UOP_PSLLW_IMM - (packed word) dest_reg = src_reg_a << immediate*/
#define UOP_PSLLW_IMM (UOP_TYPE_PARAMS_REGS | 0x9f)
/*UOP_PSLLD_IMM - (packed long) dest_reg = src_reg_a << immediate*/
#define UOP_PSLLD_IMM (UOP_TYPE_PARAMS_REGS | 0xa0)
/*UOP_PSLLQ_IMM - (packed quad) dest_reg = src_reg_a << immediate*/
#define UOP_PSLLQ_IMM (UOP_TYPE_PARAMS_REGS | 0xa1)
/*UOP_PSRAW_IMM - (packed word) dest_reg = src_reg_a >> immediate*/
#define UOP_PSRAW_IMM (UOP_TYPE_PARAMS_REGS | 0xa2)
/*UOP_PSRAD_IMM - (packed long) dest_reg = src_reg_a >> immediate*/
#define UOP_PSRAD_IMM (UOP_TYPE_PARAMS_REGS | 0xa3)
/*UOP_PSRAQ_IMM - (packed quad) dest_reg = src_reg_a >> immediate*/
#define UOP_PSRAQ_IMM (UOP_TYPE_PARAMS_REGS | 0xa4)
/*UOP_PSRLW_IMM - (packed word) dest_reg = src_reg_a >> immediate*/
#define UOP_PSRLW_IMM (UOP_TYPE_PARAMS_REGS | 0xa5)
/*UOP_PSRLD_IMM - (packed long) dest_reg = src_reg_a >> immediate*/
#define UOP_PSRLD_IMM (UOP_TYPE_PARAMS_REGS | 0xa6)
/*UOP_PSRLQ_IMM - (packed quad) dest_reg = src_reg_a >> immediate*/
#define UOP_PSRLQ_IMM (UOP_TYPE_PARAMS_REGS | 0xa7)
/*UOP_PCMPEQB - (packed byte) dest_reg = (src_reg_a == src_reg_b) ? ~0 : 0*/
#define UOP_PCMPEQB (UOP_TYPE_PARAMS_REGS | 0xa8)
/*UOP_PCMPEQW - (packed word) dest_reg = (src_reg_a == src_reg_b) ? ~0 : 0*/
#define UOP_PCMPEQW (UOP_TYPE_PARAMS_REGS | 0xa9)
/*UOP_PCMPEQD - (packed long) dest_reg = (src_reg_a == src_reg_b) ? ~0 : 0*/
#define UOP_PCMPEQD (UOP_TYPE_PARAMS_REGS | 0xaa)
/*UOP_PCMPGTB - (packed signed byte) dest_reg = (src_reg_a > src_reg_b) ? ~0 : 0*/
#define UOP_PCMPGTB (UOP_TYPE_PARAMS_REGS | 0xab)
/*UOP_PCMPGTW - (packed signed word) dest_reg = (src_reg_a > src_reg_b) ? ~0 : 0*/
#define UOP_PCMPGTW (UOP_TYPE_PARAMS_REGS | 0xac)
/*UOP_PCMPGTD - (packed signed long) dest_reg = (src_reg_a > src_reg_b) ? ~0 : 0*/
#define UOP_PCMPGTD (UOP_TYPE_PARAMS_REGS | 0xad)
/*UOP_PUNPCKLBW - (packed byte) dest_reg = interleave low src_reg_a/src_reg_b*/
#define UOP_PUNPCKLBW (UOP_TYPE_PARAMS_REGS | 0xae)
/*UOP_PUNPCKLWD - (packed word) dest_reg = interleave low src_reg_a/src_reg_b*/
#define UOP_PUNPCKLWD (UOP_TYPE_PARAMS_REGS | 0xaf)
/*UOP_PUNPCKLDQ - (packed long) dest_reg = interleave low src_reg_a/src_reg_b*/
#define UOP_PUNPCKLDQ (UOP_TYPE_PARAMS_REGS | 0xb0)
/*UOP_PUNPCKHBW - (packed byte) dest_reg = interleave high src_reg_a/src_reg_b*/
#define UOP_PUNPCKHBW (UOP_TYPE_PARAMS_REGS | 0xb1)
/*UOP_PUNPCKHWD - (packed word) dest_reg = interleave high src_reg_a/src_reg_b*/
#define UOP_PUNPCKHWD (UOP_TYPE_PARAMS_REGS | 0xb2)
/*UOP_PUNPCKHDQ - (packed long) dest_reg = interleave high src_reg_a/src_reg_b*/
#define UOP_PUNPCKHDQ (UOP_TYPE_PARAMS_REGS | 0xb3)
/*UOP_PACKSSWB - dest_reg = interleave src_reg_a/src_reg_b, converting words to bytes with signed saturation*/
#define UOP_PACKSSWB (UOP_TYPE_PARAMS_REGS | 0xb4)
/*UOP_PACKSSDW - dest_reg = interleave src_reg_a/src_reg_b, converting longs to words with signed saturation*/
#define UOP_PACKSSDW (UOP_TYPE_PARAMS_REGS | 0xb5)
/*UOP_PACKUSWB - dest_reg = interleave src_reg_a/src_reg_b, converting words to bytes with unsigned saturation*/
#define UOP_PACKUSWB (UOP_TYPE_PARAMS_REGS | 0xb6)
/*UOP_PMULLW - (packed word) dest_reg = (src_reg_a * src_reg_b) & 0xffff*/
#define UOP_PMULLW (UOP_TYPE_PARAMS_REGS | 0xb7)
/*UOP_PMULHW - (packed word) dest_reg = (src_reg_a * src_reg_b) >> 16*/
#define UOP_PMULHW (UOP_TYPE_PARAMS_REGS | 0xb8)
/*UOP_PMADDWD - (packed word) dest_reg = (src_reg_a * src_reg_b) >> 16*/
#define UOP_PMADDWD (UOP_TYPE_PARAMS_REGS | 0xb9)
/*UOP_PFADD - (packed float) dest_reg = src_reg_a + src_reg_b*/
#define UOP_PFADD (UOP_TYPE_PARAMS_REGS | 0xba)
/*UOP_PFSUB - (packed float) dest_reg = src_reg_a - src_reg_b*/
#define UOP_PFSUB (UOP_TYPE_PARAMS_REGS | 0xbb)
/*UOP_PFMUL - (packed float) dest_reg = src_reg_a * src_reg_b*/
#define UOP_PFMUL (UOP_TYPE_PARAMS_REGS | 0xbc)
/*UOP_PFMAX - (packed float) dest_reg = MAX(src_reg_a, src_reg_b)*/
#define UOP_PFMAX (UOP_TYPE_PARAMS_REGS | 0xbd)
/*UOP_PFMIN - (packed float) dest_reg = MIN(src_reg_a, src_reg_b)*/
#define UOP_PFMIN (UOP_TYPE_PARAMS_REGS | 0xbe)
/*UOP_PFCMPEQ - (packed float) dest_reg = (src_reg_a == src_reg_b) ? ~0 : 0*/
#define UOP_PFCMPEQ (UOP_TYPE_PARAMS_REGS | 0xbf)
/*UOP_PFCMPGE - (packed float) dest_reg = (src_reg_a >= src_reg_b) ? ~0 : 0*/
#define UOP_PFCMPGE (UOP_TYPE_PARAMS_REGS | 0xc0)
/*UOP_PFCMPGT - (packed float) dest_reg = (src_reg_a > src_reg_b) ? ~0 : 0*/
#define UOP_PFCMPGT (UOP_TYPE_PARAMS_REGS | 0xc1)
/*UOP_PF2ID - (packed long)dest_reg = (packed float)src_reg_a*/
#define UOP_PF2ID (UOP_TYPE_PARAMS_REGS | 0xc2)
/*UOP_PI2FD - (packed float)dest_reg = (packed long)src_reg_a*/
#define UOP_PI2FD (UOP_TYPE_PARAMS_REGS | 0xc3)
/*UOP_PFRCP - (packed float) dest_reg[0] = dest_reg[1] = 1.0 / src_reg[0]*/
#define UOP_PFRCP (UOP_TYPE_PARAMS_REGS | 0xc4)
/*UOP_PFRSQRT - (packed float) dest_reg[0] = dest_reg[1] = 1.0 / sqrt(src_reg[0])*/
#define UOP_PFRSQRT (UOP_TYPE_PARAMS_REGS | 0xc5)
#define UOP_MAX 0xc6
#define UOP_INVALID 0xff
#define UOP_MASK 0xffff
typedef struct uop_t
{
uint32_t type;
ir_reg_t dest_reg_a;
ir_reg_t src_reg_a;
ir_reg_t src_reg_b;
ir_reg_t src_reg_c;
uint32_t imm_data;
void *p;
ir_host_reg_t dest_reg_a_real;
ir_host_reg_t src_reg_a_real, src_reg_b_real, src_reg_c_real;
int jump_dest_uop;
int jump_list_next;
void *jump_dest;
uint32_t pc;
} uop_t;
#define UOP_NR_MAX 4096
typedef struct ir_data_t
{
uop_t uops[UOP_NR_MAX];
int wr_pos;
struct codeblock_t *block;
} ir_data_t;
static inline uop_t *uop_alloc(ir_data_t *ir, uint32_t uop_type)
{
uop_t *uop;
if (ir->wr_pos >= UOP_NR_MAX)
fatal("Exceeded uOP max\n");
uop = &ir->uops[ir->wr_pos++];
uop->dest_reg_a = invalid_ir_reg;
uop->src_reg_a = invalid_ir_reg;
uop->src_reg_b = invalid_ir_reg;
uop->src_reg_c = invalid_ir_reg;
uop->pc = cpu_state.oldpc;
uop->jump_dest_uop = -1;
uop->jump_list_next = -1;
if (uop_type & (UOP_TYPE_BARRIER | UOP_TYPE_ORDER_BARRIER))
codegen_reg_mark_as_required();
return uop;
}
static inline void uop_set_jump_dest(ir_data_t *ir, int jump_uop)
{
uop_t *uop = &ir->uops[jump_uop];
uop->jump_dest_uop = ir->wr_pos;
}
static inline int uop_gen(uint32_t uop_type, ir_data_t *ir)
{
uop_t *uop = uop_alloc(ir, uop_type);
uop->type = uop_type;
return ir->wr_pos-1;
}
static inline int uop_gen_reg_src1(uint32_t uop_type, ir_data_t *ir, int src_reg_a)
{
uop_t *uop = uop_alloc(ir, uop_type);
uop->type = uop_type;
uop->src_reg_a = codegen_reg_read(src_reg_a);
return ir->wr_pos-1;
}
static inline void uop_gen_reg_src1_arg(uint32_t uop_type, ir_data_t *ir, int arg, int src_reg_a)
{
uop_t *uop = uop_alloc(ir, uop_type);
uop->type = uop_type;
uop->src_reg_a = codegen_reg_read(src_reg_a);
}
static inline int uop_gen_reg_src1_imm(uint32_t uop_type, ir_data_t *ir, int src_reg, uint32_t imm)
{
uop_t *uop = uop_alloc(ir, uop_type);
uop->type = uop_type;
uop->src_reg_a = codegen_reg_read(src_reg);
uop->imm_data = imm;
return ir->wr_pos-1;
}
static inline void uop_gen_reg_dst_imm(uint32_t uop_type, ir_data_t *ir, int dest_reg, uint32_t imm)
{
uop_t *uop = uop_alloc(ir, uop_type);
uop->type = uop_type;
uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1);
uop->imm_data = imm;
}
static inline void uop_gen_reg_dst_pointer(uint32_t uop_type, ir_data_t *ir, int dest_reg, void *p)
{
uop_t *uop = uop_alloc(ir, uop_type);
uop->type = uop_type;
uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1);
uop->p = p;
}
static inline void uop_gen_reg_dst_src1(uint32_t uop_type, ir_data_t *ir, int dest_reg, int src_reg)
{
uop_t *uop = uop_alloc(ir, uop_type);
uop->type = uop_type;
uop->src_reg_a = codegen_reg_read(src_reg);
uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1);
}
static inline void uop_gen_reg_dst_src1_imm(uint32_t uop_type, ir_data_t *ir, int dest_reg, int src_reg_a, uint32_t imm)
{
uop_t *uop = uop_alloc(ir, uop_type);
uop->type = uop_type;
uop->src_reg_a = codegen_reg_read(src_reg_a);
uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1);
uop->imm_data = imm;
}
static inline void uop_gen_reg_dst_src2(uint32_t uop_type, ir_data_t *ir, int dest_reg, int src_reg_a, int src_reg_b)
{
uop_t *uop = uop_alloc(ir, uop_type);
uop->type = uop_type;
uop->src_reg_a = codegen_reg_read(src_reg_a);
uop->src_reg_b = codegen_reg_read(src_reg_b);
uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1);
}
static inline void uop_gen_reg_dst_src2_imm(uint32_t uop_type, ir_data_t *ir, int dest_reg, int src_reg_a, int src_reg_b, uint32_t imm)
{
uop_t *uop = uop_alloc(ir, uop_type);
uop->type = uop_type;
uop->src_reg_a = codegen_reg_read(src_reg_a);
uop->src_reg_b = codegen_reg_read(src_reg_b);
uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1);
uop->imm_data = imm;
}
static inline void uop_gen_reg_dst_src3(uint32_t uop_type, ir_data_t *ir, int dest_reg, int src_reg_a, int src_reg_b, int src_reg_c)
{
uop_t *uop = uop_alloc(ir, uop_type);
uop->type = uop_type;
uop->src_reg_a = codegen_reg_read(src_reg_a);
uop->src_reg_b = codegen_reg_read(src_reg_b);
uop->src_reg_c = codegen_reg_read(src_reg_c);
uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1);
}
static inline void uop_gen_reg_dst_src_imm(uint32_t uop_type, ir_data_t *ir, int dest_reg, int src_reg, uint32_t imm)
{
uop_t *uop = uop_alloc(ir, uop_type);
uop->type = uop_type;
uop->src_reg_a = codegen_reg_read(src_reg);
uop->dest_reg_a = codegen_reg_write(dest_reg, ir->wr_pos - 1);
uop->imm_data = imm;
}
static inline int uop_gen_reg_src2(uint32_t uop_type, ir_data_t *ir, int src_reg_a, int src_reg_b)
{
uop_t *uop = uop_alloc(ir, uop_type);
uop->type = uop_type;
uop->src_reg_a = codegen_reg_read(src_reg_a);
uop->src_reg_b = codegen_reg_read(src_reg_b);
return ir->wr_pos-1;
}
static inline void uop_gen_reg_src2_imm(uint32_t uop_type, ir_data_t *ir, int src_reg_a, int src_reg_b, uint32_t imm)
{
uop_t *uop = uop_alloc(ir, uop_type);
uop->type = uop_type;
uop->src_reg_a = codegen_reg_read(src_reg_a);
uop->src_reg_b = codegen_reg_read(src_reg_b);
uop->imm_data = imm;
}
static inline void uop_gen_reg_src3(uint32_t uop_type, ir_data_t *ir, int src_reg_a, int src_reg_b, int src_reg_c)
{
uop_t *uop = uop_alloc(ir, uop_type);
uop->type = uop_type;
uop->src_reg_a = codegen_reg_read(src_reg_a);
uop->src_reg_b = codegen_reg_read(src_reg_b);
uop->src_reg_c = codegen_reg_read(src_reg_c);
}
static inline void uop_gen_reg_src3_imm(uint32_t uop_type, ir_data_t *ir, int src_reg_a, int src_reg_b, int src_reg_c, uint32_t imm)
{
uop_t *uop = uop_alloc(ir, uop_type);
uop->type = uop_type;
uop->src_reg_a = codegen_reg_read(src_reg_a);
uop->src_reg_b = codegen_reg_read(src_reg_b);
uop->src_reg_c = codegen_reg_read(src_reg_c);
uop->imm_data = imm;
}
static inline void uop_gen_imm(uint32_t uop_type, ir_data_t *ir, uint32_t imm)
{
uop_t *uop = uop_alloc(ir, uop_type);
uop->type = uop_type;
uop->imm_data = imm;
}
static inline void uop_gen_pointer(uint32_t uop_type, ir_data_t *ir, void *p)
{
uop_t *uop = uop_alloc(ir, uop_type);
uop->type = uop_type;
uop->p = p;
}
static inline void uop_gen_pointer_imm(uint32_t uop_type, ir_data_t *ir, void *p, uint32_t imm)
{
uop_t *uop = uop_alloc(ir, uop_type);
uop->type = uop_type;
uop->p = p;
uop->imm_data = imm;
}
static inline void uop_gen_reg_src_pointer(uint32_t uop_type, ir_data_t *ir, int src_reg_a, void *p)
{
uop_t *uop = uop_alloc(ir, uop_type);
uop->type = uop_type;
uop->src_reg_a = codegen_reg_read(src_reg_a);
uop->p = p;
}
static inline void uop_gen_reg_src_pointer_imm(uint32_t uop_type, ir_data_t *ir, int src_reg_a, void *p, uint32_t imm)
{
uop_t *uop = uop_alloc(ir, uop_type);
uop->type = uop_type;
uop->src_reg_a = codegen_reg_read(src_reg_a);
uop->p = p;
uop->imm_data = imm;
}
static inline void uop_gen_reg_src2_pointer(uint32_t uop_type, ir_data_t *ir, int src_reg_a, int src_reg_b, void *p)
{
uop_t *uop = uop_alloc(ir, uop_type);
uop->type = uop_type;
uop->src_reg_a = codegen_reg_read(src_reg_a);
uop->src_reg_b = codegen_reg_read(src_reg_b);
uop->p = p;
}
#define uop_LOAD_FUNC_ARG_REG(ir, arg, reg) uop_gen_reg_src1(UOP_LOAD_FUNC_ARG_0 + arg, ir, reg)
#define uop_LOAD_FUNC_ARG_IMM(ir, arg, imm) uop_gen_imm(UOP_LOAD_FUNC_ARG_0_IMM + arg, ir, imm)
#define uop_ADD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_ADD, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_ADD_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_ADD_IMM, ir, dst_reg, src_reg, imm)
#define uop_ADD_LSHIFT(ir, dst_reg, src_reg_a, src_reg_b, shift) uop_gen_reg_dst_src2_imm(UOP_ADD_LSHIFT, ir, dst_reg, src_reg_a, src_reg_b, shift)
#define uop_AND(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_AND, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_AND_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_AND_IMM, ir, dst_reg, src_reg, imm)
#define uop_ANDN(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_ANDN, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_OR(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_OR, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_OR_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_OR_IMM, ir, dst_reg, src_reg, imm)
#define uop_SUB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_SUB, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_SUB_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_SUB_IMM, ir, dst_reg, src_reg, imm)
#define uop_XOR(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_XOR, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_XOR_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_XOR_IMM, ir, dst_reg, src_reg, imm)
#define uop_SAR(ir, dst_reg, src_reg, shift_reg) uop_gen_reg_dst_src2(UOP_SAR, ir, dst_reg, src_reg, shift_reg)
#define uop_SAR_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_SAR_IMM, ir, dst_reg, src_reg, imm)
#define uop_SHL(ir, dst_reg, src_reg, shift_reg) uop_gen_reg_dst_src2(UOP_SHL, ir, dst_reg, src_reg, shift_reg)
#define uop_SHL_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_SHL_IMM, ir, dst_reg, src_reg, imm)
#define uop_SHR(ir, dst_reg, src_reg, shift_reg) uop_gen_reg_dst_src2(UOP_SHR, ir, dst_reg, src_reg, shift_reg)
#define uop_SHR_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_SHR_IMM, ir, dst_reg, src_reg, imm)
#define uop_ROL(ir, dst_reg, src_reg, shift_reg) uop_gen_reg_dst_src2(UOP_ROL, ir, dst_reg, src_reg, shift_reg)
#define uop_ROL_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_ROL_IMM, ir, dst_reg, src_reg, imm)
#define uop_ROR(ir, dst_reg, src_reg, shift_reg) uop_gen_reg_dst_src2(UOP_ROR, ir, dst_reg, src_reg, shift_reg)
#define uop_ROR_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_ROR_IMM, ir, dst_reg, src_reg, imm)
#define uop_CALL_FUNC(ir, p) uop_gen_pointer(UOP_CALL_FUNC, ir, p)
#define uop_CALL_FUNC_RESULT(ir, dst_reg, p) uop_gen_reg_dst_pointer(UOP_CALL_FUNC_RESULT, ir, dst_reg, p)
#define uop_CALL_INSTRUCTION_FUNC(ir, p) uop_gen_pointer(UOP_CALL_INSTRUCTION_FUNC, ir, p)
#define uop_CMP_IMM_JZ(ir, src_reg, imm, p) uop_gen_reg_src_pointer_imm(UOP_CMP_IMM_JZ, ir, src_reg, p, imm)
#define uop_CMP_IMM_JNZ_DEST(ir, src_reg, imm) uop_gen_reg_src1_imm(UOP_CMP_IMM_JNZ_DEST, ir, src_reg, imm)
#define uop_CMP_IMM_JZ_DEST(ir, src_reg, imm) uop_gen_reg_src1_imm(UOP_CMP_IMM_JZ_DEST, ir, src_reg, imm)
#define uop_CMP_JB(ir, src_reg_a, src_reg_b, p) uop_gen_reg_src2_pointer(UOP_CMP_JB, ir, src_reg_a, src_reg_b, p)
#define uop_CMP_JNBE(ir, src_reg_a, src_reg_b, p) uop_gen_reg_src2_pointer(UOP_CMP_JNBE, ir, src_reg_a, src_reg_b, p)
#define uop_CMP_JNB_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JNB_DEST, ir, src_reg_a, src_reg_b)
#define uop_CMP_JNBE_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JNBE_DEST, ir, src_reg_a, src_reg_b)
#define uop_CMP_JNL_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JNL_DEST, ir, src_reg_a, src_reg_b)
#define uop_CMP_JNLE_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JNLE_DEST, ir, src_reg_a, src_reg_b)
#define uop_CMP_JNO_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JNO_DEST, ir, src_reg_a, src_reg_b)
#define uop_CMP_JNZ_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JNZ_DEST, ir, src_reg_a, src_reg_b)
#define uop_CMP_JB_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JB_DEST, ir, src_reg_a, src_reg_b)
#define uop_CMP_JBE_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JBE_DEST, ir, src_reg_a, src_reg_b)
#define uop_CMP_JL_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JL_DEST, ir, src_reg_a, src_reg_b)
#define uop_CMP_JLE_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JLE_DEST, ir, src_reg_a, src_reg_b)
#define uop_CMP_JO_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JO_DEST, ir, src_reg_a, src_reg_b)
#define uop_CMP_JZ_DEST(ir, src_reg_a, src_reg_b) uop_gen_reg_src2(UOP_CMP_JZ_DEST, ir, src_reg_a, src_reg_b)
#define uop_FADD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_FADD, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_FCOM(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_FCOM, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_FDIV(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_FDIV, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_FMUL(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_FMUL, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_FSUB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_FSUB, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_FABS(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_FABS, ir, dst_reg, src_reg)
#define uop_FCHS(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_FCHS, ir, dst_reg, src_reg)
#define uop_FSQRT(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_FSQRT, ir, dst_reg, src_reg)
#define uop_FTST(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_FTST, ir, dst_reg, src_reg)
#define uop_FP_ENTER(ir) do { if (!codegen_fpu_entered) uop_gen_imm(UOP_FP_ENTER, ir, cpu_state.oldpc); codegen_fpu_entered = 1; codegen_mmx_entered = 0; } while (0)
#define uop_MMX_ENTER(ir) do { if (!codegen_mmx_entered) uop_gen_imm(UOP_MMX_ENTER, ir, cpu_state.oldpc); codegen_mmx_entered = 1; codegen_fpu_entered = 0; } while (0)
#define uop_JMP(ir, p) uop_gen_pointer(UOP_JMP, ir, p)
#define uop_JMP_DEST(ir) uop_gen(UOP_JMP_DEST, ir)
#define uop_LOAD_SEG(ir, p, src_reg) uop_gen_reg_src_pointer(UOP_LOAD_SEG, ir, src_reg, p)
#define uop_MEM_LOAD_ABS(ir, dst_reg, seg_reg, imm) uop_gen_reg_dst_src_imm(UOP_MEM_LOAD_ABS, ir, dst_reg, seg_reg, imm)
#define uop_MEM_LOAD_REG(ir, dst_reg, seg_reg, addr_reg) uop_gen_reg_dst_src2_imm(UOP_MEM_LOAD_REG, ir, dst_reg, seg_reg, addr_reg, 0)
#define uop_MEM_LOAD_REG_OFFSET(ir, dst_reg, seg_reg, addr_reg, offset) uop_gen_reg_dst_src2_imm(UOP_MEM_LOAD_REG, ir, dst_reg, seg_reg, addr_reg, offset)
#define uop_MEM_LOAD_SINGLE(ir, dst_reg, seg_reg, addr_reg) uop_gen_reg_dst_src2_imm(UOP_MEM_LOAD_SINGLE, ir, dst_reg, seg_reg, addr_reg, 0)
#define uop_MEM_LOAD_DOUBLE(ir, dst_reg, seg_reg, addr_reg) uop_gen_reg_dst_src2_imm(UOP_MEM_LOAD_DOUBLE, ir, dst_reg, seg_reg, addr_reg, 0)
#define uop_MEM_STORE_ABS(ir, seg_reg, imm, src_reg) uop_gen_reg_src2_imm(UOP_MEM_STORE_ABS, ir, seg_reg, src_reg, imm)
#define uop_MEM_STORE_REG(ir, seg_reg, addr_reg, src_reg) uop_gen_reg_src3_imm(UOP_MEM_STORE_REG, ir, seg_reg, addr_reg, src_reg, 0)
#define uop_MEM_STORE_REG_OFFSET(ir, seg_reg, addr_reg, offset, src_reg) uop_gen_reg_src3_imm(UOP_MEM_STORE_REG, ir, seg_reg, addr_reg, src_reg, offset)
#define uop_MEM_STORE_IMM_8(ir, seg_reg, addr_reg, imm) uop_gen_reg_src2_imm(UOP_MEM_STORE_IMM_8, ir, seg_reg, addr_reg, imm)
#define uop_MEM_STORE_IMM_16(ir, seg_reg, addr_reg, imm) uop_gen_reg_src2_imm(UOP_MEM_STORE_IMM_16, ir, seg_reg, addr_reg, imm)
#define uop_MEM_STORE_IMM_32(ir, seg_reg, addr_reg, imm) uop_gen_reg_src2_imm(UOP_MEM_STORE_IMM_32, ir, seg_reg, addr_reg, imm)
#define uop_MEM_STORE_SINGLE(ir, seg_reg, addr_reg, src_reg) uop_gen_reg_src3_imm(UOP_MEM_STORE_SINGLE, ir, seg_reg, addr_reg, src_reg, 0)
#define uop_MEM_STORE_DOUBLE(ir, seg_reg, addr_reg, src_reg) uop_gen_reg_src3_imm(UOP_MEM_STORE_DOUBLE, ir, seg_reg, addr_reg, src_reg, 0)
#define uop_MOV(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_MOV, ir, dst_reg, src_reg)
#define uop_MOV_IMM(ir, reg, imm) uop_gen_reg_dst_imm(UOP_MOV_IMM, ir, reg, imm)
#define uop_MOV_PTR(ir, reg, p) uop_gen_reg_dst_pointer(UOP_MOV_PTR, ir, reg, p)
#define uop_MOV_REG_PTR(ir, reg, p) uop_gen_reg_dst_pointer(UOP_MOV_REG_PTR, ir, reg, p)
#define uop_MOVZX_REG_PTR_8(ir, reg, p) uop_gen_reg_dst_pointer(UOP_MOVZX_REG_PTR_8, ir, reg, p)
#define uop_MOVZX_REG_PTR_16(ir, reg, p) uop_gen_reg_dst_pointer(UOP_MOVZX_REG_PTR_16, ir, reg, p)
#define uop_MOVSX(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_MOVSX, ir, dst_reg, src_reg)
#define uop_MOVZX(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_MOVZX, ir, dst_reg, src_reg)
#define uop_MOV_DOUBLE_INT(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_MOV_DOUBLE_INT, ir, dst_reg, src_reg)
#define uop_MOV_INT_DOUBLE(ir, dst_reg, src_reg/*, nrc, orc*/) uop_gen_reg_dst_src1(UOP_MOV_INT_DOUBLE, ir, dst_reg, src_reg/*, nrc, orc*/)
#define uop_MOV_INT_DOUBLE_64(ir, dst_reg, src_reg_d, src_reg_q, tag) uop_gen_reg_dst_src3(UOP_MOV_INT_DOUBLE_64, ir, dst_reg, src_reg_d, src_reg_q, tag)
#define uop_NOP_BARRIER(ir) uop_gen(UOP_NOP_BARRIER, ir)
#define uop_PACKSSWB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PACKSSWB, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PACKSSDW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PACKSSDW, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PACKUSWB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PACKUSWB, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PADDB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PADDB, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PADDW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PADDW, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PADDD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PADDD, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PADDSB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PADDSB, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PADDSW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PADDSW, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PADDUSB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PADDUSB, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PADDUSW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PADDUSW, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PCMPEQB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PCMPEQB, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PCMPEQW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PCMPEQW, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PCMPEQD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PCMPEQD, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PCMPGTB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PCMPGTB, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PCMPGTW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PCMPGTW, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PCMPGTD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PCMPGTD, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PF2ID(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_PF2ID, ir, dst_reg, src_reg)
#define uop_PFADD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PFADD, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PFCMPEQ(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PFCMPEQ, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PFCMPGE(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PFCMPGE, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PFCMPGT(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PFCMPGT, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PFMAX(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PFMAX, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PFMIN(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PFMIN, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PFMUL(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PFMUL, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PFRCP(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_PFRCP, ir, dst_reg, src_reg)
#define uop_PFRSQRT(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_PFRSQRT, ir, dst_reg, src_reg)
#define uop_PFSUB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PFSUB, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PI2FD(ir, dst_reg, src_reg) uop_gen_reg_dst_src1(UOP_PI2FD, ir, dst_reg, src_reg)
#define uop_PMADDWD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PMADDWD, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PMULHW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PMULHW, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PMULLW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PMULLW, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PSLLW_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSLLW_IMM, ir, dst_reg, src_reg, imm)
#define uop_PSLLD_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSLLD_IMM, ir, dst_reg, src_reg, imm)
#define uop_PSLLQ_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSLLQ_IMM, ir, dst_reg, src_reg, imm)
#define uop_PSRAW_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSRAW_IMM, ir, dst_reg, src_reg, imm)
#define uop_PSRAD_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSRAD_IMM, ir, dst_reg, src_reg, imm)
#define uop_PSRAQ_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSRAQ_IMM, ir, dst_reg, src_reg, imm)
#define uop_PSRLW_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSRLW_IMM, ir, dst_reg, src_reg, imm)
#define uop_PSRLD_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSRLD_IMM, ir, dst_reg, src_reg, imm)
#define uop_PSRLQ_IMM(ir, dst_reg, src_reg, imm) uop_gen_reg_dst_src_imm(UOP_PSRLQ_IMM, ir, dst_reg, src_reg, imm)
#define uop_PSUBB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PSUBB, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PSUBW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PSUBW, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PSUBD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PSUBD, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PSUBSB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PSUBSB, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PSUBSW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PSUBSW, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PSUBUSB(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PSUBUSB, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PSUBUSW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PSUBUSW, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PUNPCKHBW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PUNPCKHBW, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PUNPCKHWD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PUNPCKHWD, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PUNPCKHDQ(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PUNPCKHDQ, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PUNPCKLBW(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PUNPCKLBW, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PUNPCKLWD(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PUNPCKLWD, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_PUNPCKLDQ(ir, dst_reg, src_reg_a, src_reg_b) uop_gen_reg_dst_src2(UOP_PUNPCKLDQ, ir, dst_reg, src_reg_a, src_reg_b)
#define uop_STORE_PTR_IMM(ir, p, imm) uop_gen_pointer_imm(UOP_STORE_P_IMM, ir, p, imm)
#define uop_STORE_PTR_IMM_8(ir, p, imm) uop_gen_pointer_imm(UOP_STORE_P_IMM_8, ir, p, imm)
#define uop_TEST_JNS_DEST(ir, src_reg) uop_gen_reg_src1(UOP_TEST_JNS_DEST, ir, src_reg)
#define uop_TEST_JS_DEST(ir, src_reg) uop_gen_reg_src1(UOP_TEST_JS_DEST, ir, src_reg)
#ifdef DEBUG_EXTRA
#define uop_LOG_INSTR(ir, imm) uop_gen_imm(UOP_LOG_INSTR, ir, imm)
#endif
void codegen_direct_read_8(codeblock_t *block, int host_reg, void *p);
void codegen_direct_read_16(codeblock_t *block, int host_reg, void *p);
void codegen_direct_read_32(codeblock_t *block, int host_reg, void *p);
void codegen_direct_read_64(codeblock_t *block, int host_reg, void *p);
void codegen_direct_read_pointer(codeblock_t *block, int host_reg, void *p);
void codegen_direct_read_double(codeblock_t *block, int host_reg, void *p);
void codegen_direct_read_st_8(codeblock_t *block, int host_reg, void *base, int reg_idx);
void codegen_direct_read_st_64(codeblock_t *block, int host_reg, void *base, int reg_idx);
void codegen_direct_read_st_double(codeblock_t *block, int host_reg, void *base, int reg_idx);
void codegen_direct_write_8(codeblock_t *block, void *p, int host_reg);
void codegen_direct_write_16(codeblock_t *block, void *p, int host_reg);
void codegen_direct_write_32(codeblock_t *block, void *p, int host_reg);
void codegen_direct_write_64(codeblock_t *block, void *p, int host_reg);
void codegen_direct_write_pointer(codeblock_t *block, void *p, int host_reg);
void codegen_direct_write_ptr(codeblock_t *block, void *p, int host_reg);
void codegen_direct_write_double(codeblock_t *block, void *p, int host_reg);
void codegen_direct_write_st_8(codeblock_t *block, void *base, int reg_idx, int host_reg);
void codegen_direct_write_st_64(codeblock_t *block, void *base, int reg_idx, int host_reg);
void codegen_direct_write_st_double(codeblock_t *block, void *base, int reg_idx, int host_reg);
void codegen_direct_read_16_stack(codeblock_t *block, int host_reg, int stack_offset);
void codegen_direct_read_32_stack(codeblock_t *block, int host_reg, int stack_offset);
void codegen_direct_read_64_stack(codeblock_t *block, int host_reg, int stack_offset);
void codegen_direct_read_pointer_stack(codeblock_t *block, int host_reg, int stack_offset);
void codegen_direct_read_double_stack(codeblock_t *block, int host_reg, int stack_offset);
void codegen_direct_write_32_stack(codeblock_t *block, int stack_offset, int host_reg);
void codegen_direct_write_64_stack(codeblock_t *block, int stack_offset, int host_reg);
void codegen_direct_write_pointer_stack(codeblock_t *block, int stack_offset, int host_reg);
void codegen_direct_write_double_stack(codeblock_t *block, int stack_offset, int host_reg);
void codegen_set_jump_dest(codeblock_t *block, void *p);
#endif

View file

@ -1,129 +1,150 @@
#include "ibm.h"
#include "x86.h"
#include "x86_ops.h"
#include "x86_flags.h"
#include "x87.h"
#include "386_common.h"
#include "cpu.h"
#include "codegen.h"
#include "codegen_ir.h"
#include "codegen_ops.h"
#ifdef __amd64__
#include "codegen_ops_x86-64.h"
#elif defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined WIN32 || defined _WIN32 || defined _WIN32
#include "codegen_ops_x86.h"
#endif
#include "codegen_ops_3dnow.h"
#include "codegen_ops_arith.h"
#include "codegen_ops_fpu.h"
#include "codegen_ops_branch.h"
#include "codegen_ops_fpu_arith.h"
#include "codegen_ops_fpu_constant.h"
#include "codegen_ops_fpu_loadstore.h"
#include "codegen_ops_fpu_misc.h"
#include "codegen_ops_jump.h"
#include "codegen_ops_logic.h"
#include "codegen_ops_misc.h"
#include "codegen_ops_mmx.h"
#include "codegen_ops_mmx_arith.h"
#include "codegen_ops_mmx_cmp.h"
#include "codegen_ops_mmx_loadstore.h"
#include "codegen_ops_mmx_logic.h"
#include "codegen_ops_mmx_pack.h"
#include "codegen_ops_mmx_shift.h"
#include "codegen_ops_mov.h"
#include "codegen_ops_shift.h"
#include "codegen_ops_stack.h"
#include "codegen_ops_xchg.h"
RecompOpFn recomp_opcodes[512] =
{
/*16-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ ropADD_b_rmw, ropADD_w_rmw, ropADD_b_rm, ropADD_w_rm, ropADD_AL_imm, ropADD_AX_imm, ropPUSH_ES_16, ropPOP_ES_16, ropOR_b_rmw, ropOR_w_rmw, ropOR_b_rm, ropOR_w_rm, ropOR_AL_imm, ropOR_AX_imm, ropPUSH_CS_16, NULL,
/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_SS_16, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_DS_16, ropPOP_DS_16,
/*10*/ ropADC_b_rmw, ropADC_w_rmw, ropADC_b_rm, ropADC_w_rm, ropADC_AL_imm, ropADC_AX_imm, ropPUSH_SS_16, NULL, ropSBB_b_rmw, ropSBB_w_rmw, ropSBB_b_rm, ropSBB_w_rm, ropSBB_AL_imm, ropSBB_AX_imm, ropPUSH_DS_16, ropPOP_DS_16,
/*20*/ ropAND_b_rmw, ropAND_w_rmw, ropAND_b_rm, ropAND_w_rm, ropAND_AL_imm, ropAND_AX_imm, NULL, NULL, ropSUB_b_rmw, ropSUB_w_rmw, ropSUB_b_rm, ropSUB_w_rm, ropSUB_AL_imm, ropSUB_AX_imm, NULL, NULL,
/*30*/ ropXOR_b_rmw, ropXOR_w_rmw, ropXOR_b_rm, ropXOR_w_rm, ropXOR_AL_imm, ropXOR_AX_imm, NULL, NULL, ropCMP_b_rmw, ropCMP_w_rmw, ropCMP_b_rm, ropCMP_w_rm, ropCMP_AL_imm, ropCMP_AX_imm, NULL, NULL,
/*40*/ ropINC_rw, ropINC_rw, ropINC_rw, ropINC_rw, ropINC_rw, ropINC_rw, ropINC_rw, ropINC_rw, ropDEC_rw, ropDEC_rw, ropDEC_rw, ropDEC_rw, ropDEC_rw, ropDEC_rw, ropDEC_rw, ropDEC_rw,
/*50*/ ropPUSH_16, ropPUSH_16, ropPUSH_16, ropPUSH_16, ropPUSH_16, ropPUSH_16, ropPUSH_16, ropPUSH_16, ropPOP_16, ropPOP_16, ropPOP_16, ropPOP_16, ropPOP_16, ropPOP_16, ropPOP_16, ropPOP_16,
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_imm_16, NULL, ropPUSH_imm_b16,NULL, NULL, NULL, NULL, NULL,
/*70*/ ropJO, ropJNO, ropJB, ropJNB, ropJE, ropJNE, ropJBE, ropJNBE, ropJS, ropJNS, ropJP, ropJNP, ropJL, ropJNL, ropJLE, ropJNLE,
/*40*/ ropINC_r16, ropINC_r16, ropINC_r16, ropINC_r16, ropINC_r16, ropINC_r16, ropINC_r16, ropINC_r16, ropDEC_r16, ropDEC_r16, ropDEC_r16, ropDEC_r16, ropDEC_r16, ropDEC_r16, ropDEC_r16, ropDEC_r16,
/*50*/ ropPUSH_r16, ropPUSH_r16, ropPUSH_r16, ropPUSH_r16, ropPUSH_r16, ropPUSH_r16, ropPUSH_r16, ropPUSH_r16, ropPOP_r16, ropPOP_r16, ropPOP_r16, ropPOP_r16, ropPOP_r16, ropPOP_r16, ropPOP_r16, ropPOP_r16,
/*60*/ ropPUSHA_16, ropPOPA_16, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_imm_16, NULL, ropPUSH_imm_16_8,NULL, NULL, NULL, NULL, NULL,
/*70*/ ropJO_8, ropJNO_8, ropJB_8, ropJNB_8, ropJE_8, ropJNE_8, ropJBE_8, ropJNBE_8, ropJS_8, ropJNS_8, ropJP_8, ropJNP_8, ropJL_8, ropJNL_8, ropJLE_8, ropJNLE_8,
/*80*/ rop80, rop81_w, rop80, rop83_w, ropTEST_b_rm, ropTEST_w_rm, ropXCHG_b, ropXCHG_w, ropMOV_b_r, ropMOV_w_r, ropMOV_r_b, ropMOV_r_w, ropMOV_w_seg, ropLEA_w, ropMOV_seg_w, NULL,
/*90*/ ropNOP, ropXCHG_AX_CX, ropXCHG_AX_DX, ropXCHG_AX_BX, ropXCHG_AX_SP, ropXCHG_AX_BP, ropXCHG_AX_SI, ropXCHG_AX_DI, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*a0*/ ropMOV_AL_a, ropMOV_AX_a, ropMOV_a_AL, ropMOV_a_AX, NULL, NULL, NULL, NULL, ropTEST_AL_imm, ropTEST_AX_imm, NULL, NULL, NULL, NULL, NULL, NULL,
/*80*/ rop80, rop81_w, rop80, rop83_w, ropTEST_b_rm, ropTEST_w_rm, ropXCHG_8, ropXCHG_16, ropMOV_b_r, ropMOV_w_r, ropMOV_r_b, ropMOV_r_w, ropMOV_w_seg, ropLEA_16, ropMOV_seg_w, ropPOP_W,
/*90*/ ropNOP, ropXCHG_AX, ropXCHG_AX, ropXCHG_AX, ropXCHG_AX, ropXCHG_AX, ropXCHG_AX, ropXCHG_AX, ropCBW, ropCWD, NULL, NULL, ropPUSHF, NULL, NULL, NULL,
/*a0*/ ropMOV_AL_abs, ropMOV_AX_abs, ropMOV_abs_AL, ropMOV_abs_AX, NULL, NULL, NULL, NULL, ropTEST_AL_imm, ropTEST_AX_imm, NULL, NULL, NULL, NULL, NULL, NULL,
/*b0*/ ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm, ropMOV_rw_imm,
/*c0*/ ropC0, ropC1_w, ropRET_imm_16, ropRET_16, ropLES, ropLDS, ropMOV_b_imm, ropMOV_w_imm, NULL, ropLEAVE_16, NULL, NULL, NULL, NULL, NULL, NULL,
/*d0*/ ropD0, ropD1_w, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*e0*/ NULL, NULL, ropLOOP, ropJCXZ, NULL, NULL, NULL, NULL, ropCALL_r16, ropJMP_r16, NULL, ropJMP_r8, NULL, NULL, NULL, NULL,
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, ropF6, ropF7_w, NULL, NULL, ropCLI, ropSTI, ropCLD, ropSTD, ropFE, ropFF_16,
/*c0*/ ropC0, ropC1_w, ropRET_imm_16, ropRET_16, ropLES_16, ropLDS_16, ropMOV_b_imm, ropMOV_w_imm, NULL, ropLEAVE_16, ropRETF_imm_16, ropRETF_16, NULL, NULL, NULL, NULL,
/*d0*/ ropD0, ropD1_w, ropD2, ropD3_w, NULL, NULL, NULL, ropXLAT, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*e0*/ ropLOOPNE, ropLOOPE, ropLOOP, ropJCXZ, NULL, NULL, NULL, NULL, ropCALL_r16, ropJMP_r16, ropJMP_far_16, ropJMP_r8, NULL, NULL, NULL, NULL,
/*f0*/ NULL, NULL, NULL, NULL, NULL, ropCMC, ropF6, ropF7_16, ropCLC, ropSTC, ropCLI, ropSTI, ropCLD, ropSTD, ropINCDEC, ropFF_16,
/*32-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ ropADD_b_rmw, ropADD_l_rmw, ropADD_b_rm, ropADD_l_rm, ropADD_AL_imm, ropADD_EAX_imm, ropPUSH_ES_32, ropPOP_ES_32, ropOR_b_rmw, ropOR_l_rmw, ropOR_b_rm, ropOR_l_rm, ropOR_AL_imm, ropOR_EAX_imm, ropPUSH_CS_32, NULL,
/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_SS_32, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_DS_32, ropPOP_DS_32,
/*10*/ ropADC_b_rmw, ropADC_l_rmw, ropADC_b_rm, ropADC_l_rm, ropADC_AL_imm, ropADC_EAX_imm, ropPUSH_SS_32, NULL, ropSBB_b_rmw, ropSBB_l_rmw, ropSBB_b_rm, ropSBB_l_rm, ropSBB_AL_imm, ropSBB_EAX_imm, ropPUSH_DS_32, ropPOP_DS_32,
/*20*/ ropAND_b_rmw, ropAND_l_rmw, ropAND_b_rm, ropAND_l_rm, ropAND_AL_imm, ropAND_EAX_imm, NULL, NULL, ropSUB_b_rmw, ropSUB_l_rmw, ropSUB_b_rm, ropSUB_l_rm, ropSUB_AL_imm, ropSUB_EAX_imm, NULL, NULL,
/*30*/ ropXOR_b_rmw, ropXOR_l_rmw, ropXOR_b_rm, ropXOR_l_rm, ropXOR_AL_imm, ropXOR_EAX_imm, NULL, NULL, ropCMP_b_rmw, ropCMP_l_rmw, ropCMP_b_rm, ropCMP_l_rm, ropCMP_AL_imm, ropCMP_EAX_imm, NULL, NULL,
/*40*/ ropINC_rl, ropINC_rl, ropINC_rl, ropINC_rl, ropINC_rl, ropINC_rl, ropINC_rl, ropINC_rl, ropDEC_rl, ropDEC_rl, ropDEC_rl, ropDEC_rl, ropDEC_rl, ropDEC_rl, ropDEC_rl, ropDEC_rl,
/*50*/ ropPUSH_32, ropPUSH_32, ropPUSH_32, ropPUSH_32, ropPUSH_32, ropPUSH_32, ropPUSH_32, ropPUSH_32, ropPOP_32, ropPOP_32, ropPOP_32, ropPOP_32, ropPOP_32, ropPOP_32, ropPOP_32, ropPOP_32,
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_imm_32, NULL, ropPUSH_imm_b32,NULL, NULL, NULL, NULL, NULL,
/*70*/ ropJO, ropJNO, ropJB, ropJNB, ropJE, ropJNE, ropJBE, ropJNBE, ropJS, ropJNS, ropJP, ropJNP, ropJL, ropJNL, ropJLE, ropJNLE,
/*40*/ ropINC_r32, ropINC_r32, ropINC_r32, ropINC_r32, ropINC_r32, ropINC_r32, ropINC_r32, ropINC_r32, ropDEC_r32, ropDEC_r32, ropDEC_r32, ropDEC_r32, ropDEC_r32, ropDEC_r32, ropDEC_r32, ropDEC_r32,
/*50*/ ropPUSH_r32, ropPUSH_r32, ropPUSH_r32, ropPUSH_r32, ropPUSH_r32, ropPUSH_r32, ropPUSH_r32, ropPUSH_r32, ropPOP_r32, ropPOP_r32, ropPOP_r32, ropPOP_r32, ropPOP_r32, ropPOP_r32, ropPOP_r32, ropPOP_r32,
/*60*/ ropPUSHA_32, ropPOPA_32, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_imm_32, NULL, ropPUSH_imm_32_8,NULL, NULL, NULL, NULL, NULL,
/*70*/ ropJO_8, ropJNO_8, ropJB_8, ropJNB_8, ropJE_8, ropJNE_8, ropJBE_8, ropJNBE_8, ropJS_8, ropJNS_8, ropJP_8, ropJNP_8, ropJL_8, ropJNL_8, ropJLE_8, ropJNLE_8,
/*80*/ rop80, rop81_l, rop80, rop83_l, ropTEST_b_rm, ropTEST_l_rm, ropXCHG_b, ropXCHG_l, ropMOV_b_r, ropMOV_l_r, ropMOV_r_b, ropMOV_r_l, ropMOV_w_seg, ropLEA_l, ropMOV_seg_w, NULL,
/*90*/ ropNOP, ropXCHG_EAX_ECX,ropXCHG_EAX_EDX,ropXCHG_EAX_EBX,ropXCHG_EAX_ESP,ropXCHG_EAX_EBP,ropXCHG_EAX_ESI,ropXCHG_EAX_EDI,NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*a0*/ ropMOV_AL_a, ropMOV_EAX_a, ropMOV_a_AL, ropMOV_a_EAX, NULL, NULL, NULL, NULL, ropTEST_AL_imm, ropTEST_EAX_imm,NULL, NULL, NULL, NULL, NULL, NULL,
/*80*/ rop80, rop81_l, rop80, rop83_l, ropTEST_b_rm, ropTEST_l_rm, ropXCHG_8, ropXCHG_32, ropMOV_b_r, ropMOV_l_r, ropMOV_r_b, ropMOV_r_l, ropMOV_l_seg, ropLEA_32, ropMOV_seg_w, ropPOP_L,
/*90*/ ropNOP, ropXCHG_EAX, ropXCHG_EAX, ropXCHG_EAX, ropXCHG_EAX, ropXCHG_EAX, ropXCHG_EAX, ropXCHG_EAX, ropCWDE, ropCDQ, NULL, NULL, ropPUSHFD, NULL, NULL, NULL,
/*a0*/ ropMOV_AL_abs, ropMOV_EAX_abs, ropMOV_abs_AL, ropMOV_abs_EAX, NULL, NULL, NULL, NULL, ropTEST_AL_imm, ropTEST_EAX_imm,NULL, NULL, NULL, NULL, NULL, NULL,
/*b0*/ ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rb_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm, ropMOV_rl_imm,
/*c0*/ ropC0, ropC1_l, ropRET_imm_32, ropRET_32, ropLES, ropLDS, ropMOV_b_imm, ropMOV_l_imm, NULL, ropLEAVE_32, NULL, NULL, NULL, NULL, NULL, NULL,
/*d0*/ ropD0, ropD1_l, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*e0*/ NULL, NULL, ropLOOP, ropJCXZ, NULL, NULL, NULL, NULL, ropCALL_r32, ropJMP_r32, NULL, ropJMP_r8, NULL, NULL, NULL, NULL,
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, ropF6, ropF7_l, NULL, NULL, ropCLI, ropSTI, ropCLD, ropSTD, ropFE, ropFF_32
/*c0*/ ropC0, ropC1_l, ropRET_imm_32, ropRET_32, ropLES_32, ropLDS_32, ropMOV_b_imm, ropMOV_l_imm, NULL, ropLEAVE_32, ropRETF_imm_32, ropRETF_32, NULL, NULL, NULL, NULL,
/*d0*/ ropD0, ropD1_l, ropD2, ropD3_l, NULL, NULL, NULL, ropXLAT, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*e0*/ ropLOOPNE, ropLOOPE, ropLOOP, ropJCXZ, NULL, NULL, NULL, NULL, ropCALL_r32, ropJMP_r32, ropJMP_far_32, ropJMP_r8, NULL, NULL, NULL, NULL,
/*f0*/ NULL, NULL, NULL, NULL, NULL, ropCMC, ropF6, ropF7_32, ropCLC, ropSTC, ropCLI, ropSTI, ropCLD, ropSTD, ropINCDEC, ropFF_32
};
RecompOpFn recomp_opcodes_0f[512] =
{
/*16-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*60*/ ropPUNPCKLBW, ropPUNPCKLWD, ropPUNPCKLDQ, ropPACKSSWB, ropPCMPGTB, ropPCMPGTW, ropPCMPGTD, ropPACKUSWB, ropPUNPCKHBW, ropPUNPCKHWD, ropPUNPCKHDQ, ropPACKSSDW, NULL, NULL, ropMOVD_r_d, ropMOVQ_r_q,
/*70*/ NULL, ropPSxxW_imm, ropPSxxD_imm, ropPSxxQ_imm, ropPCMPEQB, ropPCMPEQW, ropPCMPEQD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVD_d_r, ropMOVQ_q_r,
/*80*/ ropJO_16, ropJNO_16, ropJB_16, ropJNB_16, ropJE_16, ropJNE_16, ropJBE_16, ropJNBE_16, ropJS_16, ropJNS_16, ropJP_16, ropJNP_16, ropJL_16, ropJNL_16, ropJLE_16, ropJNLE_16,
/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*a0*/ ropPUSH_FS_16, ropPOP_FS_16, NULL, NULL, ropSHLD_16_imm, NULL, NULL, NULL, ropPUSH_GS_16, ropPOP_GS_16, NULL, NULL, ropSHRD_16_imm, NULL, NULL, NULL,
/*b0*/ NULL, NULL, ropLSS_16, NULL, ropLFS_16, ropLGS_16, ropMOVZX_16_8, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVSX_16_8, NULL,
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*d0*/ NULL, NULL, NULL, NULL, NULL, ropPMULLW, NULL, NULL, ropPSUBUSB, ropPSUBUSW, NULL, ropPAND, ropPADDUSB, ropPADDUSW, NULL, ropPANDN,
/*e0*/ NULL, NULL, NULL, NULL, NULL, ropPMULHW, NULL, NULL, ropPSUBSB, ropPSUBSW, NULL, ropPOR, ropPADDSB, ropPADDSW, NULL, ropPXOR,
/*f0*/ NULL, NULL, NULL, NULL, NULL, ropPMADDWD, NULL, NULL, ropPSUBB, ropPSUBW, ropPSUBD, NULL, ropPADDB, ropPADDW, ropPADDD, NULL,
/*32-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*60*/ ropPUNPCKLBW, ropPUNPCKLWD, ropPUNPCKLDQ, ropPACKSSWB, ropPCMPGTB, ropPCMPGTW, ropPCMPGTD, ropPACKUSWB, ropPUNPCKHBW, ropPUNPCKHWD, ropPUNPCKHDQ, ropPACKSSDW, NULL, NULL, ropMOVD_r_d, ropMOVQ_r_q,
/*70*/ NULL, ropPSxxW_imm, ropPSxxD_imm, ropPSxxQ_imm, ropPCMPEQB, ropPCMPEQW, ropPCMPEQD, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVD_d_r, ropMOVQ_q_r,
/*80*/ ropJO_32, ropJNO_32, ropJB_32, ropJNB_32, ropJE_32, ropJNE_32, ropJBE_32, ropJNBE_32, ropJS_32, ropJNS_32, ropJP_32, ropJNP_32, ropJL_32, ropJNL_32, ropJLE_32, ropJNLE_32,
/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*a0*/ ropPUSH_FS_32, ropPOP_FS_32, NULL, NULL, ropSHLD_32_imm, NULL, NULL, NULL, ropPUSH_GS_32, ropPOP_GS_32, NULL, NULL, ropSHRD_32_imm, NULL, NULL, NULL,
/*b0*/ NULL, NULL, ropLSS_32, NULL, ropLFS_32, ropLGS_32, ropMOVZX_32_8, ropMOVZX_32_16, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVSX_32_8, ropMOVSX_32_16,
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*d0*/ NULL, NULL, NULL, NULL, NULL, ropPMULLW, NULL, NULL, ropPSUBUSB, ropPSUBUSW, NULL, ropPAND, ropPADDUSB, ropPADDUSW, NULL, ropPANDN,
/*e0*/ NULL, NULL, NULL, NULL, NULL, ropPMULHW, NULL, NULL, ropPSUBSB, ropPSUBSW, NULL, ropPOR, ropPADDSB, ropPADDSW, NULL, ropPXOR,
/*f0*/ NULL, NULL, NULL, NULL, NULL, ropPMADDWD, NULL, NULL, ropPSUBB, ropPSUBW, ropPSUBD, NULL, ropPADDB, ropPADDW, ropPADDD, NULL,
};
RecompOpFn recomp_opcodes_3DNOW[256] =
{
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPI2FD, NULL, NULL,
/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropPF2ID, NULL, NULL,
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropEMMS, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*80*/ ropJO_w, ropJNO_w, ropJB_w, ropJNB_w, ropJE_w, ropJNE_w, ropJBE_w, ropJNBE_w, ropJS_w, ropJNS_w, ropJP_w, ropJNP_w, ropJL_w, ropJNL_w, ropJLE_w, ropJNLE_w,
/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*a0*/ ropPUSH_FS_16, ropPOP_FS_16, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_GS_16, ropPOP_GS_16, NULL, NULL, NULL, NULL, NULL, NULL,
/*b0*/ NULL, NULL, ropLSS, NULL, ropLFS, ropLGS, ropMOVZX_w_b, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVSX_w_b, NULL,
/*80*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*90*/ ropPFCMPGE, NULL, NULL, NULL, ropPFMIN, NULL, ropPFRCP, ropPFRSQRT, NULL, NULL, ropPFSUB, NULL, NULL, NULL, ropPFADD, NULL,
/*a0*/ ropPFCMPGT, NULL, NULL, NULL, ropPFMAX, NULL, ropPFRCPIT, ropPFRSQIT1, NULL, NULL, ropPFSUBR, NULL, NULL, NULL, NULL, NULL,
/*b0*/ ropPFCMPEQ, NULL, NULL, NULL, ropPFMUL, NULL, ropPFRCPIT, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*32-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*60*/ ropPUNPCKLBW, ropPUNPCKLWD, ropPUNPCKLDQ, ropPACKSSWB, ropPCMPGTB, ropPCMPGTW, ropPCMPGTD, ropPACKUSWB, ropPUNPCKHBW, ropPUNPCKHWD, ropPUNPCKHDQ, ropPACKSSDW, NULL, NULL, ropMOVD_mm_l, ropMOVQ_mm_q,
/*70*/ NULL, ropPSxxW_imm, ropPSxxD_imm, ropPSxxQ_imm, ropPCMPEQB, ropPCMPEQW, ropPCMPEQD, ropEMMS, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVD_l_mm, ropMOVQ_q_mm,
/*80*/ ropJO_l, ropJNO_l, ropJB_l, ropJNB_l, ropJE_l, ropJNE_l, ropJBE_l, ropJNBE_l, ropJS_l, ropJNS_l, ropJP_l, ropJNP_l, ropJL_l, ropJNL_l, ropJLE_l, ropJNLE_l,
/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*a0*/ ropPUSH_FS_32, ropPOP_FS_32, NULL, NULL, NULL, NULL, NULL, NULL, ropPUSH_GS_32, ropPOP_GS_32, NULL, NULL, NULL, NULL, NULL, NULL,
/*b0*/ NULL, NULL, ropLSS, NULL, ropLFS, ropLGS, ropMOVZX_l_b, ropMOVZX_l_w, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVSX_l_b, ropMOVSX_l_w,
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*d0*/ NULL, ropPSRLW, ropPSRLD, ropPSRLQ, NULL, ropPMULLW, NULL, NULL, ropPSUBUSB, ropPSUBUSW, NULL, ropPAND, ropPADDUSB, ropPADDUSW, NULL, ropPANDN,
/*e0*/ NULL, ropPSRAW, ropPSRAD, NULL, NULL, ropPMULHW, NULL, NULL, ropPSUBSB, ropPSUBSW, NULL, ropPOR, ropPADDSB, ropPADDSW, NULL, ropPXOR,
/*f0*/ NULL, ropPSLLW, ropPSLLD, ropPSLLQ, NULL, ropPMADDWD, NULL, NULL, ropPSUBB, ropPSUBW, ropPSUBD, NULL, ropPADDB, ropPADDW, ropPADDD, NULL,
};
RecompOpFn recomp_opcodes_d8[512] =
{
/*16-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs,
/*10*/ ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs,
/*20*/ ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs,
@ -145,7 +166,7 @@ RecompOpFn recomp_opcodes_d8[512] =
/*f0*/ ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR,
/*32-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs,
/*10*/ ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs,
/*20*/ ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs,
@ -170,93 +191,93 @@ RecompOpFn recomp_opcodes_d8[512] =
RecompOpFn recomp_opcodes_d9[512] =
{
/*16-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*10*/ ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs,
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW,
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW,
/*40*/ ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*50*/ ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs,
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW,
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW,
/*80*/ ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*90*/ ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs,
/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW,
/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW,
/*c0*/ ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH,
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*e0*/ ropFCHS, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFLD1, ropFLDL2T, ropFLDL2E, ropFLDPI, ropFLDEG2, ropFLDLN2, ropFLDZ, NULL,
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP,
/*e0*/ ropFCHS, ropFABS, NULL, NULL, ropFTST, NULL, NULL, NULL, ropFLD1, NULL, NULL, NULL, NULL, NULL, ropFLDZ, NULL,
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSQRT, NULL, NULL, NULL, NULL, NULL,
/*32-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*10*/ ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs,
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW,
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW,
/*40*/ ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*50*/ ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs,
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW,
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW,
/*80*/ ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, ropFLDs, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*90*/ ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs, ropFSTPs,
/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW, ropFLDCW,
/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW, ropFSTCW,
/*c0*/ ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFLD, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH, ropFXCH,
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*e0*/ ropFCHS, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFLD1, ropFLDL2T, ropFLDL2E, ropFLDPI, ropFLDEG2, ropFLDLN2, ropFLDZ, NULL,
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP,
/*e0*/ ropFCHS, ropFABS, NULL, NULL, ropFTST, NULL, NULL, NULL, ropFLD1, NULL, NULL, NULL, NULL, NULL, ropFLDZ, NULL,
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSQRT, NULL, NULL, NULL, NULL, NULL,
};
RecompOpFn recomp_opcodes_da[512] =
{
/*16-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil,
/*10*/ ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil,
/*20*/ ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil,
/*30*/ ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil,
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl,
/*10*/ ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl,
/*20*/ ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl,
/*30*/ ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl,
/*40*/ ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil,
/*50*/ ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil,
/*60*/ ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil,
/*70*/ ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil,
/*40*/ ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl,
/*50*/ ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl,
/*60*/ ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl,
/*70*/ ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl,
/*80*/ ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil,
/*90*/ ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil,
/*a0*/ ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil,
/*b0*/ ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil,
/*80*/ ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl,
/*90*/ ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl,
/*a0*/ ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl,
/*b0*/ ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl,
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFUCOMPP, NULL, NULL, NULL, NULL, NULL, NULL,
/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*32-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil,
/*10*/ ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil,
/*20*/ ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil,
/*30*/ ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil,
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl,
/*10*/ ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl,
/*20*/ ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl,
/*30*/ ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl,
/*40*/ ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil,
/*50*/ ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil,
/*60*/ ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil,
/*70*/ ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil,
/*40*/ ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl,
/*50*/ ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl,
/*60*/ ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl,
/*70*/ ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl,
/*80*/ ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFADDil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil, ropFMULil,
/*90*/ ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil, ropFCOMPil,
/*a0*/ ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil, ropFSUBRil,
/*b0*/ ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil, ropFDIVRil,
/*80*/ ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIADDl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl, ropFIMULl,
/*90*/ ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl, ropFICOMPl,
/*a0*/ ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl, ropFISUBRl,
/*b0*/ ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl, ropFIDIVRl,
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFUCOMPP, NULL, NULL, NULL, NULL, NULL, NULL,
/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
};
@ -264,7 +285,7 @@ RecompOpFn recomp_opcodes_da[512] =
RecompOpFn recomp_opcodes_db[512] =
{
/*16-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*10*/ ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl,
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@ -286,8 +307,8 @@ RecompOpFn recomp_opcodes_db[512] =
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*32-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*80*/ ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*10*/ ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl,
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
@ -311,7 +332,7 @@ RecompOpFn recomp_opcodes_db[512] =
RecompOpFn recomp_opcodes_dc[512] =
{
/*16-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd,
/*10*/ ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd,
/*20*/ ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd,
@ -333,7 +354,7 @@ RecompOpFn recomp_opcodes_dc[512] =
/*f0*/ ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr,
/*32-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd,
/*10*/ ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd,
/*20*/ ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd,
@ -358,68 +379,68 @@ RecompOpFn recomp_opcodes_dc[512] =
RecompOpFn recomp_opcodes_dd[512] =
{
/*16-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*10*/ ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd,
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW,
/*40*/ ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*50*/ ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd,
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW,
/*80*/ ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*90*/ ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd,
/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW,
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*c0*/ ropFFREE, ropFFREE, ropFFREE, ropFFREE, ropFFREE, ropFFREE, ropFFREE, ropFFREE, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*d0*/ ropFST, ropFST, ropFST, ropFST, ropFST, ropFST, ropFST, ropFST, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP,
/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*e0*/ ropFUCOM, ropFUCOM, ropFUCOM, ropFUCOM, ropFUCOM, ropFUCOM, ropFUCOM, ropFUCOM, ropFUCOMP, ropFUCOMP, ropFUCOMP, ropFUCOMP, ropFUCOMP, ropFUCOMP, ropFUCOMP, ropFUCOMP,
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*32-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*10*/ ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd,
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW,
/*40*/ ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*50*/ ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd,
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW,
/*80*/ ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, ropFLDd, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*90*/ ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd, ropFSTPd,
/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW, ropFSTSW,
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*c0*/ ropFFREE, ropFFREE, ropFFREE, ropFFREE, ropFFREE, ropFFREE, ropFFREE, ropFFREE, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*d0*/ ropFST, ropFST, ropFST, ropFST, ropFST, ropFST, ropFST, ropFST, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP, ropFSTP,
/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*e0*/ ropFUCOM, ropFUCOM, ropFUCOM, ropFUCOM, ropFUCOM, ropFUCOM, ropFUCOM, ropFUCOM, ropFUCOMP, ropFUCOMP, ropFUCOMP, ropFUCOMP, ropFUCOMP, ropFUCOMP, ropFUCOMP, ropFUCOMP,
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
};
RecompOpFn recomp_opcodes_de[512] =
{
/*16-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw,
/*10*/ ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw,
/*20*/ ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw,
/*30*/ ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw,
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw,
/*10*/ ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw,
/*20*/ ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw,
/*30*/ ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw,
/*40*/ ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw,
/*50*/ ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw,
/*60*/ ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw,
/*70*/ ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw,
/*40*/ ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw,
/*50*/ ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw,
/*60*/ ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw,
/*70*/ ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw,
/*80*/ ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw,
/*90*/ ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw,
/*a0*/ ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw,
/*b0*/ ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw,
/*80*/ ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw,
/*90*/ ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw,
/*a0*/ ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw,
/*b0*/ ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw,
/*c0*/ ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP,
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFCOMPP, NULL, NULL, NULL, NULL, NULL, NULL,
@ -427,21 +448,21 @@ RecompOpFn recomp_opcodes_de[512] =
/*f0*/ ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP,
/*32-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw,
/*10*/ ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw,
/*20*/ ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw,
/*30*/ ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw,
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw,
/*10*/ ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw,
/*20*/ ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw,
/*30*/ ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw,
/*40*/ ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw,
/*50*/ ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw,
/*60*/ ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw,
/*70*/ ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw,
/*40*/ ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw,
/*50*/ ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw,
/*60*/ ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw,
/*70*/ ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw,
/*80*/ ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFADDiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw, ropFMULiw,
/*90*/ ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw, ropFCOMPiw,
/*a0*/ ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw, ropFSUBRiw,
/*b0*/ ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIViw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw, ropFDIVRiw,
/*80*/ ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIADDw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw, ropFIMULw,
/*90*/ ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw, ropFICOMPw,
/*a0*/ ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw, ropFISUBRw,
/*b0*/ ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw, ropFIDIVRw,
/*c0*/ ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFADDP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP, ropFMULP,
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFCOMPP, NULL, NULL, NULL, NULL, NULL, NULL,
@ -452,7 +473,7 @@ RecompOpFn recomp_opcodes_de[512] =
RecompOpFn recomp_opcodes_df[512] =
{
/*16-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*10*/ ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw,
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq,
@ -474,7 +495,7 @@ RecompOpFn recomp_opcodes_df[512] =
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*32-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*10*/ ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw,
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq,
@ -495,97 +516,3 @@ RecompOpFn recomp_opcodes_df[512] =
/*e0*/ ropFSTSW_AX, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
};
RecompOpFn recomp_opcodes_REPE[512] =
{
/*16-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*80*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*32-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*80*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
};
RecompOpFn recomp_opcodes_REPNE[512] =
{
/*16-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*80*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*32-bit data*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*20*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*40*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*50*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*80*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*90*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*d0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*e0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*f0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
};

View file

@ -3,10 +3,13 @@
#include "codegen.h"
typedef uint32_t (*RecompOpFn)(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block);
struct ir_data_t;
typedef uint32_t (*RecompOpFn)(codeblock_t *block, struct ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
extern RecompOpFn recomp_opcodes[512];
extern RecompOpFn recomp_opcodes_0f[512];
extern RecompOpFn recomp_opcodes_3DNOW[256];
extern RecompOpFn recomp_opcodes_d8[512];
extern RecompOpFn recomp_opcodes_d9[512];
extern RecompOpFn recomp_opcodes_da[512];
@ -15,8 +18,8 @@ extern RecompOpFn recomp_opcodes_dc[512];
extern RecompOpFn recomp_opcodes_dd[512];
extern RecompOpFn recomp_opcodes_de[512];
extern RecompOpFn recomp_opcodes_df[512];
RecompOpFn recomp_opcodes_REPE[512];
RecompOpFn recomp_opcodes_REPNE[512];
/*extern RecompOpFn recomp_opcodes_REPE[512];
extern RecompOpFn recomp_opcodes_REPNE[512];*/
#define REG_EAX 0
#define REG_ECX 1

208
src/codegen_ops_3dnow.c Normal file
View file

@ -0,0 +1,208 @@
#include "ibm.h"
#include "x86.h"
#include "x86_flags.h"
#include "386_common.h"
#include "codegen.h"
#include "codegen_accumulate.h"
#include "codegen_ir.h"
#include "codegen_ops.h"
#include "codegen_ops_3dnow.h"
#include "codegen_ops_helpers.h"
#define ropParith(func) \
uint32_t rop ## func(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
{ \
int dest_reg = (fetchdat >> 3) & 7; \
\
uop_MMX_ENTER(ir); \
codegen_mark_code_present(block, cs+op_pc, 1); \
if ((fetchdat & 0xc0) == 0xc0) \
{ \
int src_reg = fetchdat & 7; \
uop_ ## func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg)); \
} \
else \
{ \
x86seg *target_seg; \
\
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
codegen_check_seg_read(block, ir, target_seg); \
uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); \
uop_ ## func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); \
} \
\
codegen_mark_code_present(block, cs+op_pc+1, 1); \
return op_pc + 2; \
}
ropParith(PFADD)
ropParith(PFCMPEQ)
ropParith(PFCMPGE)
ropParith(PFCMPGT)
ropParith(PFMAX)
ropParith(PFMIN)
ropParith(PFMUL)
ropParith(PFSUB)
uint32_t ropPF2ID(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = (fetchdat >> 3) & 7;
uop_MMX_ENTER(ir);
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
uop_PF2ID(ir, IREG_MM(dest_reg), IREG_MM(src_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr);
uop_PF2ID(ir, IREG_MM(dest_reg), IREG_temp0_Q);
}
codegen_mark_code_present(block, cs+op_pc+1, 1);
return op_pc + 2;
}
uint32_t ropPFSUBR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = (fetchdat >> 3) & 7;
uop_MMX_ENTER(ir);
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
uop_PFSUB(ir, IREG_MM(dest_reg), IREG_MM(src_reg), IREG_MM(dest_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr);
uop_PFSUB(ir, IREG_MM(dest_reg), IREG_temp0_Q, IREG_MM(dest_reg));
}
codegen_mark_code_present(block, cs+op_pc+1, 1);
return op_pc + 2;
}
uint32_t ropPI2FD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = (fetchdat >> 3) & 7;
uop_MMX_ENTER(ir);
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
uop_PI2FD(ir, IREG_MM(dest_reg), IREG_MM(src_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr);
uop_PI2FD(ir, IREG_MM(dest_reg), IREG_temp0_Q);
}
codegen_mark_code_present(block, cs+op_pc+1, 1);
return op_pc + 2;
}
uint32_t ropPFRCPIT(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = (fetchdat >> 3) & 7;
uop_MMX_ENTER(ir);
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
uop_MOV(ir, IREG_MM(dest_reg), IREG_MM(src_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_MM(dest_reg), ireg_seg_base(target_seg), IREG_eaaddr);
}
codegen_mark_code_present(block, cs+op_pc+1, 1);
return op_pc + 2;
}
uint32_t ropPFRCP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = (fetchdat >> 3) & 7;
uop_MMX_ENTER(ir);
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
uop_PFRCP(ir, IREG_MM(dest_reg), IREG_MM(src_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr);
uop_PFRCP(ir, IREG_MM(dest_reg), IREG_temp0_Q);
}
codegen_mark_code_present(block, cs+op_pc+1, 1);
return op_pc + 2;
}
uint32_t ropPFRSQRT(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = (fetchdat >> 3) & 7;
uop_MMX_ENTER(ir);
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
uop_PFRSQRT(ir, IREG_MM(dest_reg), IREG_MM(src_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr);
uop_PFRSQRT(ir, IREG_MM(dest_reg), IREG_temp0_Q);
}
codegen_mark_code_present(block, cs+op_pc+1, 1);
return op_pc + 2;
}
uint32_t ropPFRSQIT1(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uop_MMX_ENTER(ir);
codegen_mark_code_present(block, cs+op_pc, 2);
return op_pc + 2;
}

15
src/codegen_ops_3dnow.h Normal file
View file

@ -0,0 +1,15 @@
uint32_t ropPF2ID(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPFADD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPFCMPEQ(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPFCMPGE(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPFCMPGT(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPFMAX(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPFMIN(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPFMUL(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPFRCP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPFRCPIT(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPFRSQRT(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPFRSQIT1(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPFSUB(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPFSUBR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPI2FD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);

2517
src/codegen_ops_arith.c Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

1011
src/codegen_ops_branch.c Normal file

File diff suppressed because it is too large Load diff

69
src/codegen_ops_branch.h Normal file
View file

@ -0,0 +1,69 @@
uint32_t ropJB_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJB_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJB_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJNB_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJNB_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJNB_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJBE_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJBE_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJBE_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJNBE_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJNBE_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJNBE_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJE_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJE_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJE_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJNE_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJNE_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJNE_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJL_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJL_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJL_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJNL_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJNL_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJNL_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJLE_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJLE_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJLE_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJNLE_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJNLE_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJNLE_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJO_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJO_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJO_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJNO_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJNO_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJNO_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJP_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJP_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJP_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJNP_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJNP_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJNP_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJS_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJS_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJS_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJNS_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJNS_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJNS_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJCXZ(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropLOOP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropLOOPE(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropLOOPNE(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);

View file

@ -1,645 +0,0 @@
static uint32_t ropFXCH(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
FP_ENTER();
FP_FXCH(opcode & 7);
return op_pc;
}
static uint32_t ropFLD(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
FP_ENTER();
FP_FLD(opcode & 7);
return op_pc;
}
static uint32_t ropFST(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
FP_ENTER();
FP_FST(opcode & 7);
return op_pc;
}
static uint32_t ropFSTP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
FP_ENTER();
FP_FST(opcode & 7);
FP_POP();
return op_pc;
}
static uint32_t ropFLDs(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
x86seg *target_seg;
FP_ENTER();
op_pc--;
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
CHECK_SEG_READ(target_seg);
MEM_LOAD_ADDR_EA_L(target_seg);
FP_LOAD_S();
return op_pc + 1;
}
static uint32_t ropFLDd(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
x86seg *target_seg;
FP_ENTER();
op_pc--;
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
CHECK_SEG_READ(target_seg);
MEM_LOAD_ADDR_EA_Q(target_seg);
FP_LOAD_D();
return op_pc + 1;
}
static uint32_t ropFILDw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
x86seg *target_seg;
FP_ENTER();
op_pc--;
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
CHECK_SEG_READ(target_seg);
MEM_LOAD_ADDR_EA_W(target_seg);
FP_LOAD_IW();
return op_pc + 1;
}
static uint32_t ropFILDl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
x86seg *target_seg;
FP_ENTER();
op_pc--;
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
CHECK_SEG_READ(target_seg);
MEM_LOAD_ADDR_EA_L(target_seg);
FP_LOAD_IL();
return op_pc + 1;
}
static uint32_t ropFILDq(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
x86seg *target_seg;
FP_ENTER();
op_pc--;
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
CHECK_SEG_READ(target_seg);
MEM_LOAD_ADDR_EA_Q(target_seg);
FP_LOAD_IQ();
codegen_fpu_loaded_iq[(cpu_state.TOP - 1) & 7] = 1;
return op_pc + 1;
}
static uint32_t ropFSTs(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
x86seg *target_seg;
int host_reg;
FP_ENTER();
op_pc--;
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
host_reg = FP_LOAD_REG(0);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
CHECK_SEG_WRITE(target_seg);
MEM_STORE_ADDR_EA_L(target_seg, host_reg);
return op_pc + 1;
}
static uint32_t ropFSTd(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
x86seg *target_seg;
int host_reg1, host_reg2;
FP_ENTER();
op_pc--;
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
FP_LOAD_REG_D(0, &host_reg1, &host_reg2);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
CHECK_SEG_WRITE(target_seg);
CHECK_SEG_LIMITS(target_seg, 7);
MEM_STORE_ADDR_EA_Q(target_seg, host_reg1, host_reg2);
return op_pc + 1;
}
static uint32_t ropFSTPs(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
uint32_t new_pc = ropFSTs(opcode, fetchdat, op_32, op_pc, block);
FP_POP();
return new_pc;
}
static uint32_t ropFSTPd(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
uint32_t new_pc = ropFSTd(opcode, fetchdat, op_32, op_pc, block);
FP_POP();
return new_pc;
}
#define ropFarith(name, size, load, op) \
static uint32_t ropF ## name ## size(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
{ \
x86seg *target_seg; \
\
FP_ENTER(); \
op_pc--; \
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \
\
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \
\
CHECK_SEG_READ(target_seg); \
load(target_seg); \
\
op(FPU_ ## name); \
\
return op_pc + 1; \
}
ropFarith(ADD, s, MEM_LOAD_ADDR_EA_L, FP_OP_S);
ropFarith(DIV, s, MEM_LOAD_ADDR_EA_L, FP_OP_S);
ropFarith(DIVR, s, MEM_LOAD_ADDR_EA_L, FP_OP_S);
ropFarith(MUL, s, MEM_LOAD_ADDR_EA_L, FP_OP_S);
ropFarith(SUB, s, MEM_LOAD_ADDR_EA_L, FP_OP_S);
ropFarith(SUBR, s, MEM_LOAD_ADDR_EA_L, FP_OP_S);
ropFarith(ADD, d, MEM_LOAD_ADDR_EA_Q, FP_OP_D);
ropFarith(DIV, d, MEM_LOAD_ADDR_EA_Q, FP_OP_D);
ropFarith(DIVR, d, MEM_LOAD_ADDR_EA_Q, FP_OP_D);
ropFarith(MUL, d, MEM_LOAD_ADDR_EA_Q, FP_OP_D);
ropFarith(SUB, d, MEM_LOAD_ADDR_EA_Q, FP_OP_D);
ropFarith(SUBR, d, MEM_LOAD_ADDR_EA_Q, FP_OP_D);
ropFarith(ADD, iw, MEM_LOAD_ADDR_EA_W, FP_OP_IW);
ropFarith(DIV, iw, MEM_LOAD_ADDR_EA_W, FP_OP_IW);
ropFarith(DIVR, iw, MEM_LOAD_ADDR_EA_W, FP_OP_IW);
ropFarith(MUL, iw, MEM_LOAD_ADDR_EA_W, FP_OP_IW);
ropFarith(SUB, iw, MEM_LOAD_ADDR_EA_W, FP_OP_IW);
ropFarith(SUBR, iw, MEM_LOAD_ADDR_EA_W, FP_OP_IW);
ropFarith(ADD, il, MEM_LOAD_ADDR_EA_L, FP_OP_IL);
ropFarith(DIV, il, MEM_LOAD_ADDR_EA_L, FP_OP_IL);
ropFarith(DIVR, il, MEM_LOAD_ADDR_EA_L, FP_OP_IL);
ropFarith(MUL, il, MEM_LOAD_ADDR_EA_L, FP_OP_IL);
ropFarith(SUB, il, MEM_LOAD_ADDR_EA_L, FP_OP_IL);
ropFarith(SUBR, il, MEM_LOAD_ADDR_EA_L, FP_OP_IL);
#define ropFcompare(name, size, load, op) \
static uint32_t ropF ## name ## size(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
{ \
x86seg *target_seg; \
\
FP_ENTER(); \
op_pc--; \
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \
\
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \
\
CHECK_SEG_READ(target_seg); \
load(target_seg); \
\
op(); \
\
return op_pc + 1; \
} \
static uint32_t ropF ## name ## P ## size(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
{ \
uint32_t new_pc = ropF ## name ## size(opcode, fetchdat, op_32, op_pc, block); \
\
FP_POP(); \
\
return new_pc; \
}
ropFcompare(COM, s, MEM_LOAD_ADDR_EA_L, FP_COMPARE_S);
ropFcompare(COM, d, MEM_LOAD_ADDR_EA_Q, FP_COMPARE_D);
ropFcompare(COM, iw, MEM_LOAD_ADDR_EA_W, FP_COMPARE_IW);
ropFcompare(COM, il, MEM_LOAD_ADDR_EA_L, FP_COMPARE_IL);
/*static uint32_t ropFADDs(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
x86seg *target_seg;
FP_ENTER();
op_pc--;
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
CHECK_SEG_READ(target_seg);
MEM_LOAD_ADDR_EA_L(target_seg);
FP_OP_S(FPU_ADD);
return op_pc + 1;
}
static uint32_t ropFDIVs(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
x86seg *target_seg;
FP_ENTER();
op_pc--;
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
CHECK_SEG_READ(target_seg);
MEM_LOAD_ADDR_EA_L(target_seg);
FP_OP_S(FPU_DIV);
return op_pc + 1;
}
static uint32_t ropFMULs(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
x86seg *target_seg;
FP_ENTER();
op_pc--;
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
CHECK_SEG_READ(target_seg);
MEM_LOAD_ADDR_EA_L(target_seg);
FP_OP_S(FPU_MUL);
return op_pc + 1;
}
static uint32_t ropFSUBs(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
x86seg *target_seg;
FP_ENTER();
op_pc--;
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
CHECK_SEG_READ(target_seg);
MEM_LOAD_ADDR_EA_L(target_seg);
FP_OP_S(FPU_SUB);
return op_pc + 1;
}*/
static uint32_t ropFADD(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
FP_ENTER();
FP_OP_REG(FPU_ADD, 0, opcode & 7);
return op_pc;
}
static uint32_t ropFCOM(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
FP_ENTER();
FP_COMPARE_REG(0, opcode & 7);
return op_pc;
}
static uint32_t ropFDIV(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
FP_ENTER();
FP_OP_REG(FPU_DIV, 0, opcode & 7);
return op_pc;
}
static uint32_t ropFDIVR(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
FP_ENTER();
FP_OP_REG(FPU_DIVR, 0, opcode & 7);
return op_pc;
}
static uint32_t ropFMUL(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
FP_ENTER();
FP_OP_REG(FPU_MUL, 0, opcode & 7);
return op_pc;
}
static uint32_t ropFSUB(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
FP_ENTER();
FP_OP_REG(FPU_SUB, 0, opcode & 7);
return op_pc;
}
static uint32_t ropFSUBR(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
FP_ENTER();
FP_OP_REG(FPU_SUBR, 0, opcode & 7);
return op_pc;
}
static uint32_t ropFADDr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
FP_ENTER();
FP_OP_REG(FPU_ADD, opcode & 7, 0);
return op_pc;
}
static uint32_t ropFDIVr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
FP_ENTER();
FP_OP_REG(FPU_DIV, opcode & 7, 0);
return op_pc;
}
static uint32_t ropFDIVRr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
FP_ENTER();
FP_OP_REG(FPU_DIVR, opcode & 7, 0);
return op_pc;
}
static uint32_t ropFMULr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
FP_ENTER();
FP_OP_REG(FPU_MUL, opcode & 7, 0);
return op_pc;
}
static uint32_t ropFSUBr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
FP_ENTER();
FP_OP_REG(FPU_SUB, opcode & 7, 0);
return op_pc;
}
static uint32_t ropFSUBRr(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
FP_ENTER();
FP_OP_REG(FPU_SUBR, opcode & 7, 0);
return op_pc;
}
static uint32_t ropFADDP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
FP_ENTER();
FP_OP_REG(FPU_ADD, opcode & 7, 0);
FP_POP();
return op_pc;
}
static uint32_t ropFCOMP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
FP_ENTER();
FP_COMPARE_REG(0, opcode & 7);
FP_POP();
return op_pc;
}
static uint32_t ropFDIVP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
FP_ENTER();
FP_OP_REG(FPU_DIV, opcode & 7, 0);
FP_POP();
return op_pc;
}
static uint32_t ropFDIVRP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
FP_ENTER();
FP_OP_REG(FPU_DIVR, opcode & 7, 0);
FP_POP();
return op_pc;
}
static uint32_t ropFMULP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
FP_ENTER();
FP_OP_REG(FPU_MUL, opcode & 7, 0);
FP_POP();
return op_pc;
}
static uint32_t ropFSUBP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
FP_ENTER();
FP_OP_REG(FPU_SUB, opcode & 7, 0);
FP_POP();
return op_pc;
}
static uint32_t ropFSUBRP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
FP_ENTER();
FP_OP_REG(FPU_SUBR, opcode & 7, 0);
FP_POP();
return op_pc;
}
static uint32_t ropFCOMPP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
FP_ENTER();
FP_COMPARE_REG(0, 1);
FP_POP2();
return op_pc;
}
static uint32_t ropFSTSW_AX(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
int host_reg;
FP_ENTER();
host_reg = LOAD_VAR_W((uintptr_t)&cpu_state.npxs);
STORE_REG_TARGET_W_RELEASE(host_reg, REG_AX);
return op_pc;
}
static uint32_t ropFISTw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
x86seg *target_seg;
int host_reg;
FP_ENTER();
op_pc--;
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
host_reg = FP_LOAD_REG_INT_W(0);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
CHECK_SEG_WRITE(target_seg);
MEM_STORE_ADDR_EA_W(target_seg, host_reg);
return op_pc + 1;
}
static uint32_t ropFISTl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
x86seg *target_seg;
int host_reg;
FP_ENTER();
op_pc--;
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
host_reg = FP_LOAD_REG_INT(0);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
CHECK_SEG_WRITE(target_seg);
MEM_STORE_ADDR_EA_L(target_seg, host_reg);
return op_pc + 1;
}
static uint32_t ropFISTPw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
uint32_t new_pc = ropFISTw(opcode, fetchdat, op_32, op_pc, block);
FP_POP();
return new_pc;
}
static uint32_t ropFISTPl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
uint32_t new_pc = ropFISTl(opcode, fetchdat, op_32, op_pc, block);
FP_POP();
return new_pc;
}
static uint32_t ropFISTPq(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
x86seg *target_seg;
int host_reg1, host_reg2;
FP_ENTER();
op_pc--;
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
FP_LOAD_REG_INT_Q(0, &host_reg1, &host_reg2);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
CHECK_SEG_WRITE(target_seg);
MEM_STORE_ADDR_EA_Q(target_seg, host_reg1, host_reg2);
FP_POP();
return op_pc + 1;
}
static uint32_t ropFLDCW(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
x86seg *target_seg;
FP_ENTER();
op_pc--;
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
CHECK_SEG_READ(target_seg);
MEM_LOAD_ADDR_EA_W(target_seg);
STORE_HOST_REG_ADDR_W((uintptr_t)&cpu_state.npxc, 0);
UPDATE_NPXC(0);
return op_pc + 1;
}
static uint32_t ropFSTCW(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
int host_reg;
x86seg *target_seg;
FP_ENTER();
op_pc--;
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
CHECK_SEG_WRITE(target_seg);
host_reg = LOAD_VAR_W((uintptr_t)&cpu_state.npxc);
MEM_STORE_ADDR_EA_W(target_seg, host_reg);
return op_pc + 1;
}
static uint32_t ropFCHS(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
FP_ENTER();
FP_FCHS();
return op_pc;
}
#define opFLDimm(name, v) \
static uint32_t ropFLD ## name(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
{ \
static double fp_imm = v; \
\
FP_ENTER(); \
FP_LOAD_IMM_Q(*(uint64_t *)&fp_imm); \
\
return op_pc; \
}
opFLDimm(1, 1.0)
opFLDimm(L2T, 3.3219280948873623)
opFLDimm(L2E, 1.4426950408889634);
opFLDimm(PI, 3.141592653589793);
opFLDimm(EG2, 0.3010299956639812);
opFLDimm(Z, 0.0)
static uint32_t ropFLDLN2(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
FP_ENTER();
FP_LOAD_IMM_Q(0x3fe62e42fefa39f0ull);
return op_pc;
}

570
src/codegen_ops_fpu_arith.c Normal file
View file

@ -0,0 +1,570 @@
#include "ibm.h"
#include "x86.h"
#include "x86_flags.h"
#include "386_common.h"
#include "x87.h"
#include "codegen.h"
#include "codegen_accumulate.h"
#include "codegen_ir.h"
#include "codegen_ops.h"
#include "codegen_ops_fpu_arith.h"
#include "codegen_ops_helpers.h"
uint32_t ropFADD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg = fetchdat & 7;
uop_FP_ENTER(ir);
uop_FADD(ir, IREG_ST(0), IREG_ST(0), IREG_ST(src_reg));
uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID);
return op_pc;
}
uint32_t ropFADDr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = fetchdat & 7;
uop_FP_ENTER(ir);
uop_FADD(ir, IREG_ST(dest_reg), IREG_ST(dest_reg), IREG_ST(0));
uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID);
return op_pc;
}
uint32_t ropFADDP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = fetchdat & 7;
uop_FP_ENTER(ir);
uop_FADD(ir, IREG_ST(dest_reg), IREG_ST(dest_reg), IREG_ST(0));
uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID);
fpu_POP(block, ir);
return op_pc;
}
uint32_t ropFCOM(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg = fetchdat & 7;
uop_FP_ENTER(ir);
uop_FCOM(ir, IREG_temp0_W, IREG_ST(0), IREG_ST(src_reg));
uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0|C2|C3));
uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W);
return op_pc;
}
uint32_t ropFCOMP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg = fetchdat & 7;
uop_FP_ENTER(ir);
uop_FCOM(ir, IREG_temp0_W, IREG_ST(0), IREG_ST(src_reg));
uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0|C2|C3));
uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W);
fpu_POP(block, ir);
return op_pc;
}
uint32_t ropFCOMPP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uop_FP_ENTER(ir);
uop_FCOM(ir, IREG_temp0_W, IREG_ST(0), IREG_ST(1));
uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0|C2|C3));
uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W);
fpu_POP2(block, ir);
return op_pc;
}
uint32_t ropFDIV(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg = fetchdat & 7;
uop_FP_ENTER(ir);
uop_FDIV(ir, IREG_ST(0), IREG_ST(0), IREG_ST(src_reg));
uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID);
return op_pc;
}
uint32_t ropFDIVR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg = fetchdat & 7;
uop_FP_ENTER(ir);
uop_FDIV(ir, IREG_ST(0), IREG_ST(src_reg), IREG_ST(0));
uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID);
return op_pc;
}
uint32_t ropFDIVr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = fetchdat & 7;
uop_FP_ENTER(ir);
uop_FDIV(ir, IREG_ST(dest_reg), IREG_ST(dest_reg), IREG_ST(0));
uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID);
return op_pc;
}
uint32_t ropFDIVRr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = fetchdat & 7;
uop_FP_ENTER(ir);
uop_FDIV(ir, IREG_ST(dest_reg), IREG_ST(0), IREG_ST(dest_reg));
uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID);
return op_pc;
}
uint32_t ropFDIVP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = fetchdat & 7;
uop_FP_ENTER(ir);
uop_FDIV(ir, IREG_ST(dest_reg), IREG_ST(dest_reg), IREG_ST(0));
uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID);
fpu_POP(block, ir);
return op_pc;
}
uint32_t ropFDIVRP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = fetchdat & 7;
uop_FP_ENTER(ir);
uop_FDIV(ir, IREG_ST(dest_reg), IREG_ST(0), IREG_ST(dest_reg));
uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID);
fpu_POP(block, ir);
return op_pc;
}
uint32_t ropFMUL(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg = fetchdat & 7;
uop_FP_ENTER(ir);
uop_FMUL(ir, IREG_ST(0), IREG_ST(0), IREG_ST(src_reg));
uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID);
return op_pc;
}
uint32_t ropFMULr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = fetchdat & 7;
uop_FP_ENTER(ir);
uop_FMUL(ir, IREG_ST(dest_reg), IREG_ST(dest_reg), IREG_ST(0));
uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID);
return op_pc;
}
uint32_t ropFMULP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = fetchdat & 7;
uop_FP_ENTER(ir);
uop_FMUL(ir, IREG_ST(dest_reg), IREG_ST(dest_reg), IREG_ST(0));
uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID);
fpu_POP(block, ir);
return op_pc;
}
uint32_t ropFSUB(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg = fetchdat & 7;
uop_FP_ENTER(ir);
uop_FSUB(ir, IREG_ST(0), IREG_ST(0), IREG_ST(src_reg));
uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID);
return op_pc;
}
uint32_t ropFSUBR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg = fetchdat & 7;
uop_FP_ENTER(ir);
uop_FSUB(ir, IREG_ST(0), IREG_ST(src_reg), IREG_ST(0));
uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID);
return op_pc;
}
uint32_t ropFSUBr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = fetchdat & 7;
uop_FP_ENTER(ir);
uop_FSUB(ir, IREG_ST(dest_reg), IREG_ST(dest_reg), IREG_ST(0));
uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID);
return op_pc;
}
uint32_t ropFSUBRr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = fetchdat & 7;
uop_FP_ENTER(ir);
uop_FSUB(ir, IREG_ST(dest_reg), IREG_ST(0), IREG_ST(dest_reg));
uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID);
return op_pc;
}
uint32_t ropFSUBP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = fetchdat & 7;
uop_FP_ENTER(ir);
uop_FSUB(ir, IREG_ST(dest_reg), IREG_ST(dest_reg), IREG_ST(0));
uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID);
fpu_POP(block, ir);
return op_pc;
}
uint32_t ropFSUBRP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = fetchdat & 7;
uop_FP_ENTER(ir);
uop_FSUB(ir, IREG_ST(dest_reg), IREG_ST(0), IREG_ST(dest_reg));
uop_MOV_IMM(ir, IREG_tag(dest_reg), TAG_VALID);
fpu_POP(block, ir);
return op_pc;
}
uint32_t ropFUCOM(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg = fetchdat & 7;
uop_FP_ENTER(ir);
uop_FCOM(ir, IREG_temp0_W, IREG_ST(0), IREG_ST(src_reg));
uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0|C2|C3));
uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W);
return op_pc;
}
uint32_t ropFUCOMP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg = fetchdat & 7;
uop_FP_ENTER(ir);
uop_FCOM(ir, IREG_temp0_W, IREG_ST(0), IREG_ST(src_reg));
uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0|C2|C3));
uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W);
fpu_POP(block, ir);
return op_pc;
}
uint32_t ropFUCOMPP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uop_FP_ENTER(ir);
uop_FCOM(ir, IREG_temp0_W, IREG_ST(0), IREG_ST(1));
uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0|C2|C3));
uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W);
fpu_POP2(block, ir);
return op_pc;
}
#define ropF_arith_mem(name, load_uop) \
uint32_t ropFADD ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
{ \
x86seg *target_seg; \
\
uop_FP_ENTER(ir); \
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
op_pc--; \
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
codegen_check_seg_read(block, ir, target_seg); \
load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \
uop_FADD(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \
uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \
\
return op_pc+1; \
} \
uint32_t ropFCOM ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
{ \
x86seg *target_seg; \
\
uop_FP_ENTER(ir); \
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
op_pc--; \
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
codegen_check_seg_read(block, ir, target_seg); \
load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \
uop_FCOM(ir, IREG_temp1_W, IREG_ST(0), IREG_temp0_D); \
uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0|C2|C3)); \
uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp1_W); \
\
return op_pc+1; \
} \
uint32_t ropFCOMP ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
{ \
x86seg *target_seg; \
\
uop_FP_ENTER(ir); \
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
op_pc--; \
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
codegen_check_seg_read(block, ir, target_seg); \
load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \
uop_FCOM(ir, IREG_temp1_W, IREG_ST(0), IREG_temp0_D); \
uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0|C2|C3)); \
uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp1_W); \
fpu_POP(block, ir); \
\
return op_pc+1; \
} \
uint32_t ropFDIV ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
{ \
x86seg *target_seg; \
\
uop_FP_ENTER(ir); \
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
op_pc--; \
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
codegen_check_seg_read(block, ir, target_seg); \
load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \
uop_FDIV(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \
uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \
\
return op_pc+1; \
} \
uint32_t ropFDIVR ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
{ \
x86seg *target_seg; \
\
uop_FP_ENTER(ir); \
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
op_pc--; \
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
codegen_check_seg_read(block, ir, target_seg); \
load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \
uop_FDIV(ir, IREG_ST(0), IREG_temp0_D, IREG_ST(0)); \
uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \
\
return op_pc+1; \
} \
uint32_t ropFMUL ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
{ \
x86seg *target_seg; \
\
uop_FP_ENTER(ir); \
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
op_pc--; \
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
codegen_check_seg_read(block, ir, target_seg); \
load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \
uop_FMUL(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \
uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \
\
return op_pc+1; \
} \
uint32_t ropFSUB ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
{ \
x86seg *target_seg; \
\
uop_FP_ENTER(ir); \
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
op_pc--; \
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
codegen_check_seg_read(block, ir, target_seg); \
load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \
uop_FSUB(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \
uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \
\
return op_pc+1; \
} \
uint32_t ropFSUBR ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
{ \
x86seg *target_seg; \
\
uop_FP_ENTER(ir); \
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
op_pc--; \
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
codegen_check_seg_read(block, ir, target_seg); \
load_uop(ir, IREG_temp0_D, ireg_seg_base(target_seg), IREG_eaaddr); \
uop_FSUB(ir, IREG_ST(0), IREG_temp0_D, IREG_ST(0)); \
uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \
\
return op_pc+1; \
}
ropF_arith_mem(s, uop_MEM_LOAD_SINGLE)
ropF_arith_mem(d, uop_MEM_LOAD_DOUBLE)
#define ropFI_arith_mem(name, temp_reg) \
uint32_t ropFIADD ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
{ \
x86seg *target_seg; \
\
uop_FP_ENTER(ir); \
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
op_pc--; \
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
codegen_check_seg_read(block, ir, target_seg); \
uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \
uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \
uop_FADD(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \
uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \
\
return op_pc+1; \
} \
uint32_t ropFICOM ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
{ \
x86seg *target_seg; \
\
uop_FP_ENTER(ir); \
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
op_pc--; \
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
codegen_check_seg_read(block, ir, target_seg); \
uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \
uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \
uop_FCOM(ir, IREG_temp1_W, IREG_ST(0), IREG_temp0_D); \
uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0|C2|C3)); \
uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp1_W); \
\
return op_pc+1; \
} \
uint32_t ropFICOMP ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
{ \
x86seg *target_seg; \
\
uop_FP_ENTER(ir); \
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
op_pc--; \
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
codegen_check_seg_read(block, ir, target_seg); \
uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \
uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \
uop_FCOM(ir, IREG_temp1_W, IREG_ST(0), IREG_temp0_D); \
uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0|C2|C3)); \
uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp1_W); \
fpu_POP(block, ir); \
\
return op_pc+1; \
} \
uint32_t ropFIDIV ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
{ \
x86seg *target_seg; \
\
uop_FP_ENTER(ir); \
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
op_pc--; \
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
codegen_check_seg_read(block, ir, target_seg); \
uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \
uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \
uop_FDIV(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \
uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \
\
return op_pc+1; \
} \
uint32_t ropFIDIVR ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)\
{ \
x86seg *target_seg; \
\
uop_FP_ENTER(ir); \
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
op_pc--; \
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
codegen_check_seg_read(block, ir, target_seg); \
uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \
uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \
uop_FDIV(ir, IREG_ST(0), IREG_temp0_D, IREG_ST(0)); \
uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \
\
return op_pc+1; \
} \
uint32_t ropFIMUL ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
{ \
x86seg *target_seg; \
\
uop_FP_ENTER(ir); \
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
op_pc--; \
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
codegen_check_seg_read(block, ir, target_seg); \
uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \
uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \
uop_FMUL(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \
uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \
\
return op_pc+1; \
} \
uint32_t ropFISUB ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
{ \
x86seg *target_seg; \
\
uop_FP_ENTER(ir); \
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
op_pc--; \
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
codegen_check_seg_read(block, ir, target_seg); \
uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \
uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \
uop_FSUB(ir, IREG_ST(0), IREG_ST(0), IREG_temp0_D); \
uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \
\
return op_pc+1; \
} \
uint32_t ropFISUBR ## name(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)\
{ \
x86seg *target_seg; \
\
uop_FP_ENTER(ir); \
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
op_pc--; \
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
codegen_check_seg_read(block, ir, target_seg); \
uop_MEM_LOAD_REG(ir, temp_reg, ireg_seg_base(target_seg), IREG_eaaddr); \
uop_MOV_DOUBLE_INT(ir, IREG_temp0_D, temp_reg); \
uop_FSUB(ir, IREG_ST(0), IREG_temp0_D, IREG_ST(0)); \
uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID); \
\
return op_pc+1; \
}
ropFI_arith_mem(l, IREG_temp0)
ropFI_arith_mem(w, IREG_temp0_W)
uint32_t ropFABS(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uop_FP_ENTER(ir);
uop_FABS(ir, IREG_ST(0), IREG_ST(0));
uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID);
return op_pc;
}
uint32_t ropFCHS(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uop_FP_ENTER(ir);
uop_FCHS(ir, IREG_ST(0), IREG_ST(0));
uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID);
return op_pc;
}
uint32_t ropFSQRT(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uop_FP_ENTER(ir);
uop_FSQRT(ir, IREG_ST(0), IREG_ST(0));
uop_MOV_IMM(ir, IREG_tag(0), TAG_VALID);
return op_pc;
}
uint32_t ropFTST(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uop_FP_ENTER(ir);
uop_FTST(ir, IREG_temp0_W, IREG_ST(0));
uop_AND_IMM(ir, IREG_NPXS, IREG_NPXS, ~(C0|C2|C3));
uop_OR(ir, IREG_NPXS, IREG_NPXS, IREG_temp0_W);
return op_pc;
}

View file

@ -0,0 +1,63 @@
uint32_t ropFADD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFADDr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFADDP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFCOM(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFCOMP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFCOMPP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFDIV(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFDIVR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFDIVr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFDIVRr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFDIVP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFDIVRP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFMUL(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFMULr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFMULP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFSUB(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFSUBR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFSUBr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFSUBRr(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFSUBP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFSUBRP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFUCOM(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFUCOMP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFUCOMPP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFADDs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFADDd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFCOMs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFCOMd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFCOMPs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFCOMPd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFDIVs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFDIVd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFDIVRs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFDIVRd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFMULs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFMULd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFSUBs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFSUBd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFSUBRs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFSUBRd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFIADDl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFIADDw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFICOMl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFICOMw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFICOMPl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFICOMPw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFIDIVl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFIDIVw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFIDIVRl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFIDIVRw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFIMULl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFIMULw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFISUBl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFISUBw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFISUBRl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFISUBRw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFABS(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFCHS(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFSQRT(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFTST(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);

View file

@ -0,0 +1,33 @@
#include "ibm.h"
#include "x86.h"
#include "x86_flags.h"
#include "386_common.h"
#include "x87.h"
#include "codegen.h"
#include "codegen_accumulate.h"
#include "codegen_ir.h"
#include "codegen_ops.h"
#include "codegen_ops_fpu_constant.h"
#include "codegen_ops_helpers.h"
uint32_t ropFLD1(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uop_FP_ENTER(ir);
uop_MOV_IMM(ir, IREG_temp0, 1);
uop_MOV_DOUBLE_INT(ir, IREG_ST(-1), IREG_temp0);
uop_MOV_IMM(ir, IREG_tag(-1), TAG_VALID);
fpu_PUSH(block, ir);
return op_pc;
}
uint32_t ropFLDZ(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uop_FP_ENTER(ir);
uop_MOV_IMM(ir, IREG_temp0, 0);
uop_MOV_DOUBLE_INT(ir, IREG_ST(-1), IREG_temp0);
uop_MOV_IMM(ir, IREG_tag(-1), TAG_VALID);
fpu_PUSH(block, ir);
return op_pc;
}

View file

@ -0,0 +1,2 @@
uint32_t ropFLD1(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFLDZ(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);

View file

@ -0,0 +1,231 @@
#include "ibm.h"
#include "x86.h"
#include "x86_flags.h"
#include "386_common.h"
#include "x87.h"
#include "codegen.h"
#include "codegen_accumulate.h"
#include "codegen_ir.h"
#include "codegen_ops.h"
#include "codegen_ops_fpu_arith.h"
#include "codegen_ops_helpers.h"
uint32_t ropFLDs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
x86seg *target_seg;
uop_FP_ENTER(ir);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
op_pc--;
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_SINGLE(ir, IREG_ST(-1), ireg_seg_base(target_seg), IREG_eaaddr);
uop_MOV_IMM(ir, IREG_tag(-1), TAG_VALID);
fpu_PUSH(block, ir);
return op_pc+1;
}
uint32_t ropFLDd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
x86seg *target_seg;
uop_FP_ENTER(ir);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
op_pc--;
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_DOUBLE(ir, IREG_ST(-1), ireg_seg_base(target_seg), IREG_eaaddr);
uop_MOV_IMM(ir, IREG_tag(-1), TAG_VALID);
fpu_PUSH(block, ir);
return op_pc+1;
}
uint32_t ropFSTs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
x86seg *target_seg;
uop_FP_ENTER(ir);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
op_pc--;
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
uop_MEM_STORE_SINGLE(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_ST(0));
return op_pc+1;
}
uint32_t ropFSTPs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
x86seg *target_seg;
uop_FP_ENTER(ir);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
op_pc--;
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
uop_MEM_STORE_SINGLE(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_ST(0));
uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY);
fpu_POP(block, ir);
return op_pc+1;
}
uint32_t ropFSTd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
x86seg *target_seg;
uop_FP_ENTER(ir);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
op_pc--;
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
CHECK_SEG_LIMITS(block, ir, target_seg, IREG_eaaddr, 7);
uop_MEM_STORE_DOUBLE(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_ST(0));
return op_pc+1;
}
uint32_t ropFSTPd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
x86seg *target_seg;
uop_FP_ENTER(ir);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
op_pc--;
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
CHECK_SEG_LIMITS(block, ir, target_seg, IREG_eaaddr, 7);
uop_MEM_STORE_DOUBLE(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_ST(0));
uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY);
fpu_POP(block, ir);
return op_pc+1;
}
uint32_t ropFILDw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
x86seg *target_seg;
uop_FP_ENTER(ir);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
op_pc--;
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr);
uop_MOV_DOUBLE_INT(ir, IREG_ST(-1), IREG_temp0_W);
uop_MOV_IMM(ir, IREG_tag(-1), TAG_VALID);
fpu_PUSH(block, ir);
return op_pc+1;
}
uint32_t ropFILDl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
x86seg *target_seg;
uop_FP_ENTER(ir);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
op_pc--;
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr);
uop_MOV_DOUBLE_INT(ir, IREG_ST(-1), IREG_temp0);
uop_MOV_IMM(ir, IREG_tag(-1), TAG_VALID);
fpu_PUSH(block, ir);
return op_pc+1;
}
uint32_t ropFILDq(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
x86seg *target_seg;
uop_FP_ENTER(ir);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
op_pc--;
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_ST_i64(-1), ireg_seg_base(target_seg), IREG_eaaddr);
uop_MOV_DOUBLE_INT(ir, IREG_ST(-1), IREG_ST_i64(-1));
uop_MOV_IMM(ir, IREG_tag(-1), TAG_VALID | TAG_UINT64);
fpu_PUSH(block, ir);
return op_pc+1;
}
uint32_t ropFISTw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
x86seg *target_seg;
uop_FP_ENTER(ir);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
op_pc--;
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
uop_MOV_INT_DOUBLE(ir, IREG_temp0_W, IREG_ST(0));
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W);
uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY);
return op_pc+1;
}
uint32_t ropFISTPw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
x86seg *target_seg;
uop_FP_ENTER(ir);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
op_pc--;
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
uop_MOV_INT_DOUBLE(ir, IREG_temp0_W, IREG_ST(0));
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W);
uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY);
fpu_POP(block, ir);
return op_pc+1;
}
uint32_t ropFISTl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
x86seg *target_seg;
uop_FP_ENTER(ir);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
op_pc--;
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
uop_MOV_INT_DOUBLE(ir, IREG_temp0, IREG_ST(0));
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0);
uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY);
return op_pc+1;
}
uint32_t ropFISTPl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
x86seg *target_seg;
uop_FP_ENTER(ir);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
op_pc--;
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
uop_MOV_INT_DOUBLE(ir, IREG_temp0, IREG_ST(0));
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0);
uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY);
fpu_POP(block, ir);
return op_pc+1;
}
uint32_t ropFISTPq(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
x86seg *target_seg;
uop_FP_ENTER(ir);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
op_pc--;
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
uop_MOV_INT_DOUBLE_64(ir, IREG_temp0_Q, IREG_ST(0), IREG_ST_i64(0), IREG_tag(0));
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_Q);
uop_MOV_IMM(ir, IREG_tag(0), TAG_EMPTY);
fpu_POP(block, ir);
return op_pc+1;
}

View file

@ -0,0 +1,17 @@
uint32_t ropFLDs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFLDd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFSTs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFSTPs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFSTd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFSTPd(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFILDw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFILDl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFILDq(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFISTw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFISTPw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFISTl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFISTPl(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFISTPq(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);

111
src/codegen_ops_fpu_misc.c Normal file
View file

@ -0,0 +1,111 @@
#include "ibm.h"
#include "x86.h"
#include "x86_flags.h"
#include "386_common.h"
#include "x87.h"
#include "codegen.h"
#include "codegen_accumulate.h"
#include "codegen_ir.h"
#include "codegen_ops.h"
#include "codegen_ops_fpu_misc.h"
#include "codegen_ops_helpers.h"
uint32_t ropFFREE(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = fetchdat & 7;
uop_FP_ENTER(ir);
uop_MOV(ir, IREG_tag(dest_reg), TAG_EMPTY);
return op_pc;
}
uint32_t ropFLD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg = fetchdat & 7;
uop_FP_ENTER(ir);
uop_MOV(ir, IREG_ST(-1), IREG_ST(src_reg));
uop_MOV(ir, IREG_ST_i64(-1), IREG_ST_i64(src_reg));
uop_MOV(ir, IREG_tag(-1), IREG_tag(src_reg));
fpu_PUSH(block, ir);
return op_pc;
}
uint32_t ropFST(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = fetchdat & 7;
uop_FP_ENTER(ir);
uop_MOV(ir, IREG_ST(dest_reg), IREG_ST(0));
uop_MOV(ir, IREG_ST_i64(dest_reg), IREG_ST_i64(0));
uop_MOV(ir, IREG_tag(dest_reg), IREG_tag(0));
return op_pc;
}
uint32_t ropFSTP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = fetchdat & 7;
uop_FP_ENTER(ir);
uop_MOV(ir, IREG_ST(dest_reg), IREG_ST(0));
uop_MOV(ir, IREG_ST_i64(dest_reg), IREG_ST_i64(0));
uop_MOV(ir, IREG_tag(dest_reg), IREG_tag(0));
fpu_POP(block, ir);
return op_pc;
}
uint32_t ropFSTCW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
x86seg *target_seg;
uop_FP_ENTER(ir);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
op_pc--;
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_NPXC);
return op_pc+1;
}
uint32_t ropFSTSW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
x86seg *target_seg;
uop_FP_ENTER(ir);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
op_pc--;
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_NPXS);
return op_pc+1;
}
uint32_t ropFSTSW_AX(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uop_FP_ENTER(ir);
uop_MOV(ir, IREG_AX, IREG_NPXS);
return op_pc;
}
uint32_t ropFXCH(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = fetchdat & 7;
uop_FP_ENTER(ir);
uop_MOV(ir, IREG_temp0_D, IREG_ST(0));
uop_MOV(ir, IREG_temp1_Q, IREG_ST_i64(0));
uop_MOV(ir, IREG_temp2, IREG_tag(0));
uop_MOV(ir, IREG_ST(0), IREG_ST(dest_reg));
uop_MOV(ir, IREG_ST_i64(0), IREG_ST_i64(dest_reg));
uop_MOV(ir, IREG_tag(0), IREG_tag(dest_reg));
uop_MOV(ir, IREG_ST(dest_reg), IREG_temp0_D);
uop_MOV(ir, IREG_ST_i64(dest_reg), IREG_temp1_Q);
uop_MOV(ir, IREG_tag(dest_reg), IREG_temp2);
return op_pc;
}

View file

@ -0,0 +1,12 @@
uint32_t ropFFREE(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFLD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFST(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFSTP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFSTCW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFSTSW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFSTSW_AX(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFXCH(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);

65
src/codegen_ops_helpers.c Normal file
View file

@ -0,0 +1,65 @@
#include "ibm.h"
#include "x86.h"
#include "386_common.h"
#include "codegen.h"
#include "codegen_ir.h"
#include "codegen_ir_defs.h"
#include "codegen_reg.h"
#include "codegen_ops_helpers.h"
void LOAD_IMMEDIATE_FROM_RAM_16_unaligned(codeblock_t *block, ir_data_t *ir, int dest_reg, uint32_t addr)
{
/*Word access that crosses two pages. Perform reads from both pages, shift and combine*/
uop_MOVZX_REG_PTR_8(ir, IREG_temp3_W, get_ram_ptr(addr));
uop_MOVZX_REG_PTR_8(ir, dest_reg, get_ram_ptr(addr+1));
uop_SHL_IMM(ir, IREG_temp3_W, IREG_temp3_W, 8);
uop_OR(ir, dest_reg, dest_reg, IREG_temp3_W);
}
void LOAD_IMMEDIATE_FROM_RAM_32_unaligned(codeblock_t *block, ir_data_t *ir, int dest_reg, uint32_t addr)
{
/*Dword access that crosses two pages. Perform reads from both pages, shift and combine*/
uop_MOV_REG_PTR(ir, dest_reg, get_ram_ptr(addr & ~3));
uop_MOV_REG_PTR(ir, IREG_temp3, get_ram_ptr((addr + 4) & ~3));
uop_SHR_IMM(ir, dest_reg, dest_reg, (addr & 3) * 8);
uop_SHL_IMM(ir, IREG_temp3, IREG_temp3, (4 - (addr & 3)) * 8);
uop_OR(ir, dest_reg, dest_reg, IREG_temp3);
}
#define UNROLL_MAX_REG_REFERENCES 200
#define UNROLL_MAX_UOPS 1000
#define UNROLL_MAX_COUNT 10
int codegen_can_unroll_full(codeblock_t *block, ir_data_t *ir, uint32_t next_pc, uint32_t dest_addr)
{
int start;
int max_unroll;
int first_instruction;
/*Check that dest instruction was actually compiled into block*/
start = codegen_get_instruction_uop(block, dest_addr, &first_instruction);
/*Couldn't find any uOPs corresponding to the destination instruction*/
if (start == -1)
{
/*Is instruction jumping to itself?*/
if (dest_addr != cpu_state.oldpc)
{
// 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;
}
else
start = ir->wr_pos;
}
max_unroll = UNROLL_MAX_UOPS / ((ir->wr_pos-start)+6);
if (max_unroll > (UNROLL_MAX_REG_REFERENCES / max_version_refcount))
max_unroll = (UNROLL_MAX_REG_REFERENCES / max_version_refcount);
if (max_unroll > UNROLL_MAX_COUNT)
max_unroll = UNROLL_MAX_COUNT;
if (max_unroll <= 1)
return 0;
codegen_ir_set_unroll(max_unroll, start, first_instruction);
return 1;
}

126
src/codegen_ops_helpers.h Normal file
View file

@ -0,0 +1,126 @@
#include "386_common.h"
#include "codegen_backend.h"
static inline int LOAD_SP_WITH_OFFSET(ir_data_t *ir, int offset)
{
if (stack32)
{
if (offset)
{
uop_ADD_IMM(ir, IREG_eaaddr, IREG_ESP, offset);
return IREG_eaaddr;
}
else
return IREG_ESP;
}
else
{
if (offset)
{
uop_ADD_IMM(ir, IREG_eaaddr_W, IREG_SP, offset);
uop_MOVZX(ir, IREG_eaaddr, IREG_eaaddr_W);
return IREG_eaaddr;
}
else
{
uop_MOVZX(ir, IREG_eaaddr, IREG_SP);
return IREG_eaaddr;
}
}
}
static inline int LOAD_SP(ir_data_t *ir)
{
return LOAD_SP_WITH_OFFSET(ir, 0);
}
static inline void ADD_SP(ir_data_t *ir, int offset)
{
if (stack32)
uop_ADD_IMM(ir, IREG_ESP, IREG_ESP, offset);
else
uop_ADD_IMM(ir, IREG_SP, IREG_SP, offset);
}
static inline void SUB_SP(ir_data_t *ir, int offset)
{
if (stack32)
uop_SUB_IMM(ir, IREG_ESP, IREG_ESP, offset);
else
uop_SUB_IMM(ir, IREG_SP, IREG_SP, offset);
}
static inline void fpu_POP(codeblock_t *block, ir_data_t *ir)
{
if (block->flags & CODEBLOCK_STATIC_TOP)
uop_MOV_IMM(ir, IREG_FPU_TOP, cpu_state.TOP + 1);
else
uop_ADD_IMM(ir, IREG_FPU_TOP, IREG_FPU_TOP, 1);
}
static inline void fpu_POP2(codeblock_t *block, ir_data_t *ir)
{
if (block->flags & CODEBLOCK_STATIC_TOP)
uop_MOV_IMM(ir, IREG_FPU_TOP, cpu_state.TOP + 2);
else
uop_ADD_IMM(ir, IREG_FPU_TOP, IREG_FPU_TOP, 2);
}
static inline void fpu_PUSH(codeblock_t *block, ir_data_t *ir)
{
if (block->flags & CODEBLOCK_STATIC_TOP)
uop_MOV_IMM(ir, IREG_FPU_TOP, cpu_state.TOP - 1);
else
uop_SUB_IMM(ir, IREG_FPU_TOP, IREG_FPU_TOP, 1);
}
static inline void CHECK_SEG_LIMITS(codeblock_t *block, ir_data_t *ir, x86seg *seg, int addr_reg, int end_offset)
{
if ((seg == &cpu_state.seg_ds && codegen_flat_ds && !(cpu_cur_status & CPU_STATUS_NOTFLATDS)) ||
(seg == &cpu_state.seg_ss && codegen_flat_ss && !(cpu_cur_status & CPU_STATUS_NOTFLATSS)))
return;
uop_CMP_JB(ir, addr_reg, ireg_seg_limit_low(seg), codegen_gpf_rout);
if (end_offset)
{
uop_ADD_IMM(ir, IREG_temp3, addr_reg, end_offset);
uop_CMP_JNBE(ir, IREG_temp3, ireg_seg_limit_high(seg), codegen_gpf_rout);
}
else
uop_CMP_JNBE(ir, addr_reg, ireg_seg_limit_high(seg), codegen_gpf_rout);
}
static inline void LOAD_IMMEDIATE_FROM_RAM_8(codeblock_t *block, ir_data_t *ir, int dest_reg, uint32_t addr)
{
uop_MOVZX_REG_PTR_8(ir, dest_reg, get_ram_ptr(addr));
}
void LOAD_IMMEDIATE_FROM_RAM_16_unaligned(codeblock_t *block, ir_data_t *ir, int dest_reg, uint32_t addr);
static inline void LOAD_IMMEDIATE_FROM_RAM_16(codeblock_t *block, ir_data_t *ir, int dest_reg, uint32_t addr)
{
if ((addr & 0xfff) == 0xfff)
LOAD_IMMEDIATE_FROM_RAM_16_unaligned(block, ir, dest_reg, addr);
else
uop_MOVZX_REG_PTR_16(ir, dest_reg, get_ram_ptr(addr));
}
void LOAD_IMMEDIATE_FROM_RAM_32_unaligned(codeblock_t *block, ir_data_t *ir, int dest_reg, uint32_t addr);
static inline void LOAD_IMMEDIATE_FROM_RAM_32(codeblock_t *block, ir_data_t *ir, int dest_reg, uint32_t addr)
{
if ((addr & 0xfff) >= 0xffd)
LOAD_IMMEDIATE_FROM_RAM_32_unaligned(block, ir, dest_reg, addr);
else
uop_MOV_REG_PTR(ir, dest_reg, get_ram_ptr(addr));
}
int codegen_can_unroll_full(codeblock_t *block, ir_data_t *ir, uint32_t next_pc, uint32_t dest_addr);
static inline int codegen_can_unroll(codeblock_t *block, ir_data_t *ir, uint32_t next_pc, uint32_t dest_addr)
{
if (block->flags & CODEBLOCK_BYTE_MASK)
return 0;
/*Is dest within block?*/
if (dest_addr > next_pc)
return 0;
if ((cs+dest_addr) < block->pc)
return 0;
return codegen_can_unroll_full(block, ir, next_pc, dest_addr);
}

289
src/codegen_ops_jump.c Normal file
View file

@ -0,0 +1,289 @@
#include "ibm.h"
#include "x86.h"
#include "386_common.h"
#include "codegen.h"
#include "codegen_ir.h"
#include "codegen_ops.h"
#include "codegen_ops_helpers.h"
#include "codegen_ops_mov.h"
uint32_t ropJMP_r8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uint32_t offset = (int32_t)(int8_t)fastreadb(cs + op_pc);
uint32_t dest_addr = op_pc+1+offset;
if (!(op_32 & 0x100))
dest_addr &= 0xffff;
if (offset < 0)
codegen_can_unroll(block, ir, op_pc+1, dest_addr);
codegen_mark_code_present(block, cs+op_pc, 1);
return dest_addr;
}
uint32_t ropJMP_r16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uint32_t offset = (int32_t)(int16_t)fastreadw(cs + op_pc);
uint32_t dest_addr = op_pc+2+offset;
dest_addr &= 0xffff;
if (offset < 0)
codegen_can_unroll(block, ir, op_pc+1, dest_addr);
codegen_mark_code_present(block, cs+op_pc, 2);
return dest_addr;
}
uint32_t ropJMP_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uint32_t offset = fastreadl(cs + op_pc);
uint32_t dest_addr = op_pc+4+offset;
if (offset < 0)
codegen_can_unroll(block, ir, op_pc+1, dest_addr);
codegen_mark_code_present(block, cs+op_pc, 4);
return dest_addr;
}
uint32_t ropJMP_far_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uint16_t new_pc = fastreadw(cs + op_pc);
uint16_t new_cs = fastreadw(cs + op_pc + 2);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
uop_MOV_IMM(ir, IREG_pc, new_pc);
uop_LOAD_FUNC_ARG_IMM(ir, 0, new_cs);
uop_LOAD_FUNC_ARG_IMM(ir, 1, op_pc + 4);
uop_CALL_FUNC(ir, loadcsjmp);
codegen_mark_code_present(block, cs+op_pc, 4);
return -1;
}
uint32_t ropJMP_far_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uint32_t new_pc = fastreadl(cs + op_pc);
uint16_t new_cs = fastreadw(cs + op_pc + 4);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
uop_MOV_IMM(ir, IREG_pc, new_pc);
uop_LOAD_FUNC_ARG_IMM(ir, 0, new_cs);
uop_LOAD_FUNC_ARG_IMM(ir, 1, op_pc + 4);
uop_CALL_FUNC(ir, loadcsjmp);
codegen_mark_code_present(block, cs+op_pc, 6);
return -1;
}
uint32_t ropCALL_r16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uint32_t offset = (int32_t)(int16_t)fastreadw(cs + op_pc);
uint16_t ret_addr = op_pc + 2;
uint16_t dest_addr = ret_addr + offset;
int sp_reg;
dest_addr &= 0xffff;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
sp_reg = LOAD_SP_WITH_OFFSET(ir, -2);
uop_MEM_STORE_IMM_16(ir, IREG_SS_base, sp_reg, ret_addr);
SUB_SP(ir, 2);
uop_MOV_IMM(ir, IREG_pc, dest_addr);
codegen_mark_code_present(block, cs+op_pc, 2);
return -1;
}
uint32_t ropCALL_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uint32_t offset = fastreadl(cs + op_pc);
uint32_t ret_addr = op_pc + 4;
uint32_t dest_addr = ret_addr + offset;
int sp_reg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
sp_reg = LOAD_SP_WITH_OFFSET(ir, -4);
uop_MEM_STORE_IMM_32(ir, IREG_SS_base, sp_reg, ret_addr);
SUB_SP(ir, 4);
uop_MOV_IMM(ir, IREG_pc, dest_addr);
codegen_mark_code_present(block, cs+op_pc, 4);
return -1;
}
uint32_t ropRET_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
if (stack32)
uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_ESP);
else
{
uop_MOVZX(ir, IREG_eaaddr, IREG_SP);
uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_eaaddr);
}
ADD_SP(ir, 2);
uop_MOVZX(ir, IREG_pc, IREG_temp0_W);
return -1;
}
uint32_t ropRET_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
if (stack32)
uop_MEM_LOAD_REG(ir, IREG_pc, IREG_SS_base, IREG_ESP);
else
{
uop_MOVZX(ir, IREG_eaaddr, IREG_SP);
uop_MEM_LOAD_REG(ir, IREG_pc, IREG_SS_base, IREG_eaaddr);
}
ADD_SP(ir, 4);
return -1;
}
uint32_t ropRET_imm_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uint16_t offset = fastreadw(cs + op_pc);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
if (stack32)
uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_ESP);
else
{
uop_MOVZX(ir, IREG_eaaddr, IREG_SP);
uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_eaaddr);
}
ADD_SP(ir, 2+offset);
uop_MOVZX(ir, IREG_pc, IREG_temp0_W);
codegen_mark_code_present(block, cs+op_pc, 2);
return -1;
}
uint32_t ropRET_imm_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uint16_t offset = fastreadw(cs + op_pc);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
if (stack32)
uop_MEM_LOAD_REG(ir, IREG_pc, IREG_SS_base, IREG_ESP);
else
{
uop_MOVZX(ir, IREG_eaaddr, IREG_SP);
uop_MEM_LOAD_REG(ir, IREG_pc, IREG_SS_base, IREG_eaaddr);
}
ADD_SP(ir, 4+offset);
codegen_mark_code_present(block, cs+op_pc, 2);
return -1;
}
uint32_t ropRETF_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
if ((msw&1) && !(cpu_state.eflags&VM_FLAG))
return 0;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
if (stack32)
{
uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_ESP);
uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, IREG_SS_base, IREG_ESP, 2);
}
else
{
uop_MOVZX(ir, IREG_eaaddr, IREG_SP);
uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_eaaddr);
uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, IREG_SS_base, IREG_eaaddr, 2);
}
uop_MOVZX(ir, IREG_pc, IREG_temp0_W);
uop_LOAD_FUNC_ARG_REG(ir, 0, IREG_temp1_W);
uop_CALL_FUNC(ir, loadcs);
ADD_SP(ir, 4);
return -1;
}
uint32_t ropRETF_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
if ((msw&1) && !(cpu_state.eflags&VM_FLAG))
return 0;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
if (stack32)
{
uop_MEM_LOAD_REG(ir, IREG_temp0, IREG_SS_base, IREG_ESP);
uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, IREG_SS_base, IREG_ESP, 4);
}
else
{
uop_MOVZX(ir, IREG_eaaddr, IREG_SP);
uop_MEM_LOAD_REG(ir, IREG_temp0, IREG_SS_base, IREG_eaaddr);
uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, IREG_SS_base, IREG_eaaddr, 4);
}
uop_MOV(ir, IREG_pc, IREG_temp0);
uop_LOAD_FUNC_ARG_REG(ir, 0, IREG_temp1_W);
uop_CALL_FUNC(ir, loadcs);
ADD_SP(ir, 8);
return -1;
}
uint32_t ropRETF_imm_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uint16_t offset;
if ((msw&1) && !(cpu_state.eflags&VM_FLAG))
return 0;
offset = fastreadw(cs + op_pc);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
if (stack32)
{
uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_ESP);
uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, IREG_SS_base, IREG_ESP, 2);
}
else
{
uop_MOVZX(ir, IREG_eaaddr, IREG_SP);
uop_MEM_LOAD_REG(ir, IREG_temp0_W, IREG_SS_base, IREG_eaaddr);
uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, IREG_SS_base, IREG_eaaddr, 2);
}
uop_MOVZX(ir, IREG_pc, IREG_temp0_W);
uop_LOAD_FUNC_ARG_REG(ir, 0, IREG_temp1_W);
uop_CALL_FUNC(ir, loadcs);
ADD_SP(ir, 4+offset);
codegen_mark_code_present(block, cs+op_pc, 2);
return -1;
}
uint32_t ropRETF_imm_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uint16_t offset;
if ((msw&1) && !(cpu_state.eflags&VM_FLAG))
return 0;
offset = fastreadw(cs + op_pc);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
if (stack32)
{
uop_MEM_LOAD_REG(ir, IREG_temp0, IREG_SS_base, IREG_ESP);
uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, IREG_SS_base, IREG_ESP, 4);
}
else
{
uop_MOVZX(ir, IREG_eaaddr, IREG_SP);
uop_MEM_LOAD_REG(ir, IREG_temp0, IREG_SS_base, IREG_eaaddr);
uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, IREG_SS_base, IREG_eaaddr, 4);
}
uop_MOV(ir, IREG_pc, IREG_temp0);
uop_LOAD_FUNC_ARG_REG(ir, 0, IREG_temp1_W);
uop_CALL_FUNC(ir, loadcs);
ADD_SP(ir, 8+offset);
codegen_mark_code_present(block, cs+op_pc, 2);
return -1;
}

View file

@ -1,270 +1,21 @@
static uint32_t ropJMP_r8(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
uint32_t offset = fetchdat & 0xff;
uint32_t ropJMP_r8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJMP_r16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJMP_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
if (offset & 0x80)
offset |= 0xffffff00;
uint32_t ropJMP_far_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropJMP_far_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.pc, op_pc+1+offset);
return -1;
}
uint32_t ropCALL_r16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropCALL_r32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
static uint32_t ropJMP_r16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
uint16_t offset = fetchdat & 0xffff;
uint32_t ropRET_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropRET_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.pc, (op_pc+2+offset) & 0xffff);
return -1;
}
uint32_t ropRET_imm_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropRET_imm_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
static uint32_t ropJMP_r32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
uint32_t offset = fastreadl(cs + op_pc);
uint32_t ropRETF_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropRETF_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.pc, op_pc+4+offset);
return -1;
}
static uint32_t ropJCXZ(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
uint32_t offset = fetchdat & 0xff;
if (offset & 0x80)
offset |= 0xffffff00;
if (op_32 & 0x200)
{
int host_reg = LOAD_REG_L(REG_ECX);
TEST_ZERO_JUMP_L(host_reg, op_pc+1+offset, 0);
}
else
{
int host_reg = LOAD_REG_W(REG_CX);
TEST_ZERO_JUMP_W(host_reg, op_pc+1+offset, 0);
}
return op_pc+1;
}
static uint32_t ropLOOP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
uint32_t offset = fetchdat & 0xff;
if (offset & 0x80)
offset |= 0xffffff00;
if (op_32 & 0x200)
{
int host_reg = LOAD_REG_L(REG_ECX);
SUB_HOST_REG_IMM(host_reg, 1);
STORE_REG_L_RELEASE(host_reg);
TEST_NONZERO_JUMP_L(host_reg, op_pc+1+offset, 0);
}
else
{
int host_reg = LOAD_REG_W(REG_CX);
SUB_HOST_REG_IMM(host_reg, 1);
STORE_REG_W_RELEASE(host_reg);
TEST_NONZERO_JUMP_W(host_reg, op_pc+1+offset, 0);
}
return op_pc+1;
}
static void BRANCH_COND_B(int pc_offset, uint32_t op_pc, uint32_t offset, int not)
{
CALL_FUNC((uintptr_t)CF_SET);
if (not)
TEST_ZERO_JUMP_L(0, op_pc+pc_offset+offset, timing_bt);
else
TEST_NONZERO_JUMP_L(0, op_pc+pc_offset+offset, timing_bt);
}
static void BRANCH_COND_E(int pc_offset, uint32_t op_pc, uint32_t offset, int not)
{
int host_reg;
switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN)
{
case FLAGS_ZN8:
case FLAGS_ZN16:
case FLAGS_ZN32:
case FLAGS_ADD8:
case FLAGS_ADD16:
case FLAGS_ADD32:
case FLAGS_SUB8:
case FLAGS_SUB16:
case FLAGS_SUB32:
case FLAGS_SHL8:
case FLAGS_SHL16:
case FLAGS_SHL32:
case FLAGS_SHR8:
case FLAGS_SHR16:
case FLAGS_SHR32:
case FLAGS_SAR8:
case FLAGS_SAR16:
case FLAGS_SAR32:
case FLAGS_INC8:
case FLAGS_INC16:
case FLAGS_INC32:
case FLAGS_DEC8:
case FLAGS_DEC16:
case FLAGS_DEC32:
host_reg = LOAD_VAR_L((uintptr_t)&cpu_state.flags_res);
if (not)
TEST_NONZERO_JUMP_L(host_reg, op_pc+pc_offset+offset, timing_bt);
else
TEST_ZERO_JUMP_L(host_reg, op_pc+pc_offset+offset, timing_bt);
break;
case FLAGS_UNKNOWN:
CALL_FUNC((uintptr_t)ZF_SET);
if (not)
TEST_ZERO_JUMP_L(0, op_pc+pc_offset+offset, timing_bt);
else
TEST_NONZERO_JUMP_L(0, op_pc+pc_offset+offset, timing_bt);
break;
}
}
static void BRANCH_COND_O(int pc_offset, uint32_t op_pc, uint32_t offset, int not)
{
CALL_FUNC((uintptr_t)VF_SET);
if (not)
TEST_ZERO_JUMP_L(0, op_pc+pc_offset+offset, timing_bt);
else
TEST_NONZERO_JUMP_L(0, op_pc+pc_offset+offset, timing_bt);
}
static void BRANCH_COND_P(int pc_offset, uint32_t op_pc, uint32_t offset, int not)
{
CALL_FUNC((uintptr_t)PF_SET);
if (not)
TEST_ZERO_JUMP_L(0, op_pc+pc_offset+offset, timing_bt);
else
TEST_NONZERO_JUMP_L(0, op_pc+pc_offset+offset, timing_bt);
}
static void BRANCH_COND_S(int pc_offset, uint32_t op_pc, uint32_t offset, int not)
{
int host_reg;
switch (codegen_flags_changed ? cpu_state.flags_op : FLAGS_UNKNOWN)
{
case FLAGS_ZN8:
case FLAGS_ADD8:
case FLAGS_SUB8:
case FLAGS_SHL8:
case FLAGS_SHR8:
case FLAGS_SAR8:
case FLAGS_INC8:
case FLAGS_DEC8:
host_reg = LOAD_VAR_L((uintptr_t)&cpu_state.flags_res);
AND_HOST_REG_IMM(host_reg, 0x80);
if (not)
TEST_ZERO_JUMP_L(host_reg, op_pc+pc_offset+offset, timing_bt);
else
TEST_NONZERO_JUMP_L(host_reg, op_pc+pc_offset+offset, timing_bt);
break;
case FLAGS_ZN16:
case FLAGS_ADD16:
case FLAGS_SUB16:
case FLAGS_SHL16:
case FLAGS_SHR16:
case FLAGS_SAR16:
case FLAGS_INC16:
case FLAGS_DEC16:
host_reg = LOAD_VAR_L((uintptr_t)&cpu_state.flags_res);
AND_HOST_REG_IMM(host_reg, 0x8000);
if (not)
TEST_ZERO_JUMP_L(host_reg, op_pc+pc_offset+offset, timing_bt);
else
TEST_NONZERO_JUMP_L(host_reg, op_pc+pc_offset+offset, timing_bt);
break;
case FLAGS_ZN32:
case FLAGS_ADD32:
case FLAGS_SUB32:
case FLAGS_SHL32:
case FLAGS_SHR32:
case FLAGS_SAR32:
case FLAGS_INC32:
case FLAGS_DEC32:
host_reg = LOAD_VAR_L((uintptr_t)&cpu_state.flags_res);
AND_HOST_REG_IMM(host_reg, 0x80000000);
if (not)
TEST_ZERO_JUMP_L(host_reg, op_pc+pc_offset+offset, timing_bt);
else
TEST_NONZERO_JUMP_L(host_reg, op_pc+pc_offset+offset, timing_bt);
break;
case FLAGS_UNKNOWN:
CALL_FUNC((uintptr_t)NF_SET);
if (not)
TEST_ZERO_JUMP_L(0, op_pc+pc_offset+offset, timing_bt);
else
TEST_NONZERO_JUMP_L(0, op_pc+pc_offset+offset, timing_bt);
break;
}
}
#define ropBRANCH(name, func, not) \
static uint32_t rop ## name(uint8_t opcode, uint32_t fetchdat, \
uint32_t op_32, uint32_t op_pc, \
codeblock_t *block) \
{ \
uint32_t offset = fetchdat & 0xff; \
\
if (offset & 0x80) \
offset |= 0xffffff00; \
\
func(1, op_pc, offset, not); \
\
return op_pc+1; \
} \
static uint32_t rop ## name ## _w(uint8_t opcode, \
uint32_t fetchdat, uint32_t op_32, \
uint32_t op_pc, codeblock_t *block) \
{ \
uint32_t offset = fetchdat & 0xffff; \
\
if (offset & 0x8000) \
offset |= 0xffff0000; \
\
func(2, op_pc, offset, not); \
\
return op_pc+2; \
} \
static uint32_t rop ## name ## _l(uint8_t opcode, \
uint32_t fetchdat, uint32_t op_32, \
uint32_t op_pc, codeblock_t *block) \
{ \
uint32_t offset = fastreadl(cs + op_pc); \
\
func(4, op_pc, offset, not); \
\
return op_pc+4; \
}
ropBRANCH(JB, BRANCH_COND_B, 0)
ropBRANCH(JNB, BRANCH_COND_B, 1)
ropBRANCH(JE, BRANCH_COND_E, 0)
ropBRANCH(JNE, BRANCH_COND_E, 1)
ropBRANCH(JO, BRANCH_COND_O, 0)
ropBRANCH(JNO, BRANCH_COND_O, 1)
ropBRANCH(JP, BRANCH_COND_P, 0)
ropBRANCH(JNP, BRANCH_COND_P, 1)
ropBRANCH(JS, BRANCH_COND_S, 0)
ropBRANCH(JNS, BRANCH_COND_S, 1)
ropBRANCH(JL, BRANCH_COND_L, 0)
ropBRANCH(JNL, BRANCH_COND_L, 1)
ropBRANCH(JLE, BRANCH_COND_LE, 0)
ropBRANCH(JNLE, BRANCH_COND_LE, 1)
ropBRANCH(JBE, BRANCH_COND_BE, 0)
ropBRANCH(JNBE, BRANCH_COND_BE, 1)
uint32_t ropRETF_imm_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropRETF_imm_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);

804
src/codegen_ops_logic.c Normal file
View file

@ -0,0 +1,804 @@
#include "ibm.h"
#include "x86.h"
#include "x86_flags.h"
#include "386_common.h"
#include "codegen.h"
#include "codegen_ir.h"
#include "codegen_ops.h"
#include "codegen_ops_helpers.h"
#include "codegen_ops_logic.h"
uint32_t ropAND_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uint8_t imm_data = fastreadb(cs + op_pc);
uop_AND_IMM(ir, IREG_AL, IREG_AL, imm_data);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8);
uop_MOVZX(ir, IREG_flags_res, IREG_AL);
codegen_flags_changed = 1;
codegen_mark_code_present(block, cs+op_pc, 1);
return op_pc + 1;
}
uint32_t ropAND_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uint16_t imm_data = fastreadw(cs + op_pc);
uop_AND_IMM(ir, IREG_AX, IREG_AX, imm_data);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16);
uop_MOVZX(ir, IREG_flags_res, IREG_AX);
codegen_flags_changed = 1;
codegen_mark_code_present(block, cs+op_pc, 2);
return op_pc + 2;
}
uint32_t ropAND_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
if (block->flags & CODEBLOCK_NO_IMMEDIATES)
{
LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_temp0, cs + op_pc);
uop_AND(ir, IREG_EAX, IREG_EAX, IREG_temp0);
}
else
{
fetchdat = fastreadl(cs + op_pc);
codegen_mark_code_present(block, cs+op_pc, 4);
uop_AND_IMM(ir, IREG_EAX, IREG_EAX, fetchdat);
}
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32);
uop_MOV(ir, IREG_flags_res, IREG_EAX);
codegen_flags_changed = 1;
return op_pc + 4;
}
uint32_t ropAND_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
uop_AND(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr);
uop_AND(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B);
}
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8);
uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg));
codegen_flags_changed = 1;
return op_pc + 1;
}
uint32_t ropAND_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int dest_reg = fetchdat & 7;
uop_AND(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg));
uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr);
uop_AND(ir, IREG_temp0_B, IREG_temp0_B, IREG_8(src_reg));
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_B);
uop_MOVZX(ir, IREG_flags_res, IREG_temp0_B);
}
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8);
codegen_flags_changed = 1;
return op_pc + 1;
}
uint32_t ropAND_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
uop_AND(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr);
uop_AND(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W);
}
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16);
uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg));
codegen_flags_changed = 1;
return op_pc + 1;
}
uint32_t ropAND_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int dest_reg = fetchdat & 7;
uop_AND(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg));
uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr);
uop_AND(ir, IREG_temp0_W, IREG_temp0_W, IREG_16(src_reg));
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W);
uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W);
}
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16);
codegen_flags_changed = 1;
return op_pc + 1;
}
uint32_t ropAND_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
uop_AND(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr);
uop_AND(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp0);
}
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32);
uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg));
codegen_flags_changed = 1;
return op_pc + 1;
}
uint32_t ropAND_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int dest_reg = fetchdat & 7;
uop_AND(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg));
uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr);
uop_AND(ir, IREG_temp0, IREG_temp0, IREG_32(src_reg));
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0);
uop_MOV(ir, IREG_flags_res, IREG_temp0);
}
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32);
codegen_flags_changed = 1;
return op_pc + 1;
}
uint32_t ropOR_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uint8_t imm_data = fastreadb(cs + op_pc);
uop_OR_IMM(ir, IREG_AL, IREG_AL, imm_data);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8);
uop_MOVZX(ir, IREG_flags_res, IREG_AL);
codegen_flags_changed = 1;
codegen_mark_code_present(block, cs+op_pc, 1);
return op_pc + 1;
}
uint32_t ropOR_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uint16_t imm_data = fastreadw(cs + op_pc);
uop_OR_IMM(ir, IREG_AX, IREG_AX, imm_data);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16);
uop_MOVZX(ir, IREG_flags_res, IREG_AX);
codegen_flags_changed = 1;
codegen_mark_code_present(block, cs+op_pc, 2);
return op_pc + 2;
}
uint32_t ropOR_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
if (block->flags & CODEBLOCK_NO_IMMEDIATES)
{
LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_temp0, cs + op_pc);
uop_OR(ir, IREG_EAX, IREG_EAX, IREG_temp0);
}
else
{
fetchdat = fastreadl(cs + op_pc);
codegen_mark_code_present(block, cs+op_pc, 4);
uop_OR_IMM(ir, IREG_EAX, IREG_EAX, fetchdat);
}
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32);
uop_MOV(ir, IREG_flags_res, IREG_EAX);
codegen_flags_changed = 1;
codegen_mark_code_present(block, cs+op_pc, 4);
return op_pc + 4;
}
uint32_t ropOR_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
uop_OR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr);
uop_OR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B);
}
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8);
uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg));
codegen_flags_changed = 1;
return op_pc + 1;
}
uint32_t ropOR_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int dest_reg = fetchdat & 7;
uop_OR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg));
uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr);
uop_OR(ir, IREG_temp0_B, IREG_temp0_B, IREG_8(src_reg));
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_B);
uop_MOVZX(ir, IREG_flags_res, IREG_temp0_B);
}
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8);
codegen_flags_changed = 1;
return op_pc + 1;
}
uint32_t ropOR_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
uop_OR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr);
uop_OR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W);
}
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16);
uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg));
codegen_flags_changed = 1;
return op_pc + 1;
}
uint32_t ropOR_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int dest_reg = fetchdat & 7;
uop_OR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg));
uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr);
uop_OR(ir, IREG_temp0_W, IREG_temp0_W, IREG_16(src_reg));
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W);
uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W);
}
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16);
codegen_flags_changed = 1;
return op_pc + 1;
}
uint32_t ropOR_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
uop_OR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr);
uop_OR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp0);
}
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32);
uop_MOV(ir, IREG_flags_res, dest_reg);
codegen_flags_changed = 1;
return op_pc + 1;
}
uint32_t ropOR_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int dest_reg = fetchdat & 7;
uop_OR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg));
uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr);
uop_OR(ir, IREG_temp0, IREG_temp0, IREG_32(src_reg));
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0);
uop_MOV(ir, IREG_flags_res, IREG_temp0);
}
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32);
codegen_flags_changed = 1;
return op_pc + 1;
}
uint32_t ropTEST_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uint8_t imm_data = fastreadb(cs + op_pc);
uop_AND_IMM(ir, IREG_flags_res, IREG_EAX, imm_data);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8);
codegen_flags_changed = 1;
codegen_mark_code_present(block, cs+op_pc, 1);
return op_pc + 1;
}
uint32_t ropTEST_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uint16_t imm_data = fastreadw(cs + op_pc);
uop_AND_IMM(ir, IREG_flags_res, IREG_EAX, imm_data);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16);
codegen_flags_changed = 1;
codegen_mark_code_present(block, cs+op_pc, 2);
return op_pc + 2;
}
uint32_t ropTEST_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
if (block->flags & CODEBLOCK_NO_IMMEDIATES)
{
LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_temp0, cs + op_pc);
uop_AND(ir, IREG_flags_res, IREG_EAX, IREG_temp0);
}
else
{
fetchdat = fastreadl(cs + op_pc);
codegen_mark_code_present(block, cs+op_pc, 4);
uop_AND_IMM(ir, IREG_flags_res, IREG_EAX, fetchdat);
}
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32);
codegen_flags_changed = 1;
codegen_mark_code_present(block, cs+op_pc, 4);
return op_pc + 4;
}
uint32_t ropTEST_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
uop_AND(ir, IREG_flags_res_B, IREG_8(dest_reg), IREG_8(src_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr);
uop_AND(ir, IREG_flags_res_B, IREG_8(dest_reg), IREG_temp0_B);
}
uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_B);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8);
codegen_flags_changed = 1;
return op_pc + 1;
}
uint32_t ropTEST_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
uop_AND(ir, IREG_flags_res_W, IREG_16(dest_reg), IREG_16(src_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr);
uop_AND(ir, IREG_flags_res_W, IREG_16(dest_reg), IREG_temp0_W);
}
uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_W);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16);
codegen_flags_changed = 1;
return op_pc + 1;
}
uint32_t ropTEST_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
uop_AND(ir, IREG_flags_res, IREG_32(dest_reg), IREG_32(src_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr);
uop_AND(ir, IREG_flags_res, IREG_32(dest_reg), IREG_temp0);
}
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32);
codegen_flags_changed = 1;
return op_pc + 1;
}
uint32_t ropXOR_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uint8_t imm_data = fastreadb(cs + op_pc);
uop_XOR_IMM(ir, IREG_AL, IREG_AL, imm_data);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8);
uop_MOVZX(ir, IREG_flags_res, IREG_AL);
codegen_flags_changed = 1;
codegen_mark_code_present(block, cs+op_pc, 1);
return op_pc + 1;
}
uint32_t ropXOR_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uint16_t imm_data = fastreadw(cs + op_pc);
uop_XOR_IMM(ir, IREG_AX, IREG_AX, imm_data);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16);
uop_MOVZX(ir, IREG_flags_res, IREG_AX);
codegen_flags_changed = 1;
codegen_mark_code_present(block, cs+op_pc, 2);
return op_pc + 2;
}
uint32_t ropXOR_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
if (block->flags & CODEBLOCK_NO_IMMEDIATES)
{
LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_temp0, cs + op_pc);
uop_XOR(ir, IREG_EAX, IREG_EAX, IREG_temp0);
}
else
{
fetchdat = fastreadl(cs + op_pc);
codegen_mark_code_present(block, cs+op_pc, 4);
uop_XOR_IMM(ir, IREG_EAX, IREG_EAX, fetchdat);
}
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32);
uop_MOV(ir, IREG_flags_res, IREG_EAX);
codegen_flags_changed = 1;
codegen_mark_code_present(block, cs+op_pc, 4);
return op_pc + 4;
}
uint32_t ropXOR_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
uop_XOR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr);
uop_XOR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_temp0_B);
}
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8);
uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg));
codegen_flags_changed = 1;
return op_pc + 1;
}
uint32_t ropXOR_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int dest_reg = fetchdat & 7;
uop_XOR(ir, IREG_8(dest_reg), IREG_8(dest_reg), IREG_8(src_reg));
uop_MOVZX(ir, IREG_flags_res, IREG_8(dest_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr);
uop_XOR(ir, IREG_temp0_B, IREG_temp0_B, IREG_8(src_reg));
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_B);
uop_MOVZX(ir, IREG_flags_res, IREG_temp0_B);
}
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8);
codegen_flags_changed = 1;
return op_pc + 1;
}
uint32_t ropXOR_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
uop_XOR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr);
uop_XOR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_temp0_W);
}
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16);
uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg));
codegen_flags_changed = 1;
return op_pc + 1;
}
uint32_t ropXOR_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int dest_reg = fetchdat & 7;
uop_XOR(ir, IREG_16(dest_reg), IREG_16(dest_reg), IREG_16(src_reg));
uop_MOVZX(ir, IREG_flags_res, IREG_16(dest_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr);
uop_XOR(ir, IREG_temp0_W, IREG_temp0_W, IREG_16(src_reg));
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0_W);
uop_MOVZX(ir, IREG_flags_res, IREG_temp0_W);
}
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16);
codegen_flags_changed = 1;
return op_pc + 1;
}
uint32_t ropXOR_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
uop_XOR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr);
uop_XOR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_temp0);
}
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32);
uop_MOV(ir, IREG_flags_res, dest_reg);
codegen_flags_changed = 1;
return op_pc + 1;
}
uint32_t ropXOR_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int dest_reg = fetchdat & 7;
uop_XOR(ir, IREG_32(dest_reg), IREG_32(dest_reg), IREG_32(src_reg));
uop_MOV(ir, IREG_flags_res, IREG_32(dest_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr);
uop_XOR(ir, IREG_temp0, IREG_temp0, IREG_32(src_reg));
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0);
uop_MOV(ir, IREG_flags_res, IREG_temp0);
}
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32);
codegen_flags_changed = 1;
return op_pc + 1;
}

View file

@ -1,564 +1,36 @@
#define ROP_LOGIC(name, op, writeback) \
static uint32_t rop ## name ## _b_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
{ \
int src_reg, dst_reg; \
x86seg *target_seg; \
\
if ((fetchdat & 0xc0) == 0xc0) \
{ \
dst_reg = LOAD_REG_B(fetchdat & 7); \
} \
else \
{ \
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \
SAVE_EA(); \
MEM_CHECK_WRITE(target_seg); \
dst_reg = MEM_LOAD_ADDR_EA_B_NO_ABRT(target_seg); \
} \
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN8); \
src_reg = LOAD_REG_B((fetchdat >> 3) & 7); \
op ## _HOST_REG_B(dst_reg, src_reg); \
STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, dst_reg); \
if (writeback) \
{ \
if ((fetchdat & 0xc0) == 0xc0) \
STORE_REG_B_RELEASE(dst_reg); \
else \
{ \
LOAD_EA(); \
MEM_STORE_ADDR_EA_B_NO_ABRT(target_seg, dst_reg); \
} \
} \
else \
RELEASE_REG(dst_reg); \
RELEASE_REG(src_reg); \
\
return op_pc + 1; \
} \
static uint32_t rop ## name ## _w_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
{ \
int src_reg, dst_reg; \
x86seg *target_seg; \
\
if ((fetchdat & 0xc0) == 0xc0) \
{ \
dst_reg = LOAD_REG_W(fetchdat & 7); \
} \
else \
{ \
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \
SAVE_EA(); \
MEM_CHECK_WRITE_W(target_seg); \
dst_reg = MEM_LOAD_ADDR_EA_W_NO_ABRT(target_seg); \
} \
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN16); \
src_reg = LOAD_REG_W((fetchdat >> 3) & 7); \
op ## _HOST_REG_W(dst_reg, src_reg); \
STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, dst_reg); \
if (writeback) \
{ \
if ((fetchdat & 0xc0) == 0xc0) \
STORE_REG_W_RELEASE(dst_reg); \
else \
{ \
LOAD_EA(); \
MEM_STORE_ADDR_EA_W_NO_ABRT(target_seg, dst_reg); \
} \
} \
else \
RELEASE_REG(dst_reg); \
RELEASE_REG(src_reg); \
\
return op_pc + 1; \
} \
static uint32_t rop ## name ## _l_rmw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
{ \
int src_reg, dst_reg; \
x86seg *target_seg; \
\
if ((fetchdat & 0xc0) == 0xc0) \
{ \
dst_reg = LOAD_REG_L(fetchdat & 7); \
} \
else \
{ \
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \
SAVE_EA(); \
MEM_CHECK_WRITE_L(target_seg); \
dst_reg = MEM_LOAD_ADDR_EA_L_NO_ABRT(target_seg); \
} \
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN32); \
src_reg = LOAD_REG_L((fetchdat >> 3) & 7); \
op ## _HOST_REG_L(dst_reg, src_reg); \
STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, dst_reg); \
if (writeback) \
{ \
if ((fetchdat & 0xc0) == 0xc0) \
STORE_REG_L_RELEASE(dst_reg); \
else \
{ \
LOAD_EA(); \
MEM_STORE_ADDR_EA_L_NO_ABRT(target_seg, dst_reg); \
} \
} \
else \
RELEASE_REG(dst_reg); \
RELEASE_REG(src_reg); \
\
return op_pc + 1; \
} \
static uint32_t rop ## name ## _b_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
{ \
int src_reg, dst_reg; \
\
if ((fetchdat & 0xc0) == 0xc0) \
{ \
src_reg = LOAD_REG_B(fetchdat & 7); \
} \
else \
{ \
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \
MEM_LOAD_ADDR_EA_B(target_seg); \
src_reg = 0; \
} \
\
dst_reg = LOAD_REG_B((fetchdat >> 3) & 7); \
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN8); \
op ## _HOST_REG_B(dst_reg, src_reg); \
STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, dst_reg); \
if (writeback) STORE_REG_B_RELEASE(dst_reg); \
else RELEASE_REG(dst_reg); \
RELEASE_REG(src_reg); \
\
return op_pc + 1; \
} \
static uint32_t rop ## name ## _w_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
{ \
int src_reg, dst_reg; \
\
if ((fetchdat & 0xc0) == 0xc0) \
{ \
src_reg = LOAD_REG_W(fetchdat & 7); \
} \
else \
{ \
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \
MEM_LOAD_ADDR_EA_W(target_seg); \
src_reg = 0; \
} \
\
dst_reg = LOAD_REG_W((fetchdat >> 3) & 7); \
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN16); \
op ## _HOST_REG_W(dst_reg, src_reg); \
STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, dst_reg); \
if (writeback) STORE_REG_W_RELEASE(dst_reg); \
else RELEASE_REG(dst_reg); \
RELEASE_REG(src_reg); \
\
return op_pc + 1; \
} \
static uint32_t rop ## name ## _l_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
{ \
int src_reg, dst_reg; \
\
if ((fetchdat & 0xc0) == 0xc0) \
{ \
src_reg = LOAD_REG_L(fetchdat & 7); \
} \
else \
{ \
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \
MEM_LOAD_ADDR_EA_L(target_seg); \
src_reg = 0; \
} \
\
dst_reg = LOAD_REG_L((fetchdat >> 3) & 7); \
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN32); \
op ## _HOST_REG_L(dst_reg, src_reg); \
STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, dst_reg); \
if (writeback) STORE_REG_L_RELEASE(dst_reg); \
else RELEASE_REG(dst_reg); \
RELEASE_REG(src_reg); \
\
return op_pc + 1; \
}
uint32_t ropAND_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropAND_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropAND_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropAND_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropAND_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropAND_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropAND_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropAND_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropAND_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
ROP_LOGIC(AND, AND, 1)
ROP_LOGIC(OR, OR, 1)
ROP_LOGIC(XOR, XOR, 1)
uint32_t ropOR_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropOR_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropOR_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropOR_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropOR_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropOR_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropOR_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropOR_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropOR_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
static uint32_t ropTEST_b_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
int src_reg, dst_reg;
uint32_t ropTEST_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropTEST_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropTEST_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropTEST_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropTEST_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropTEST_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
if ((fetchdat & 0xc0) == 0xc0)
{
src_reg = LOAD_REG_B(fetchdat & 7);
}
else
{
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
MEM_LOAD_ADDR_EA_B(target_seg);
src_reg = 0;
}
dst_reg = LOAD_REG_B((fetchdat >> 3) & 7);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN8);
dst_reg = TEST_HOST_REG_B(dst_reg, src_reg);
STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, dst_reg);
RELEASE_REG(dst_reg);
RELEASE_REG(src_reg);
return op_pc + 1;
}
static uint32_t ropTEST_w_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
int src_reg, dst_reg;
if ((fetchdat & 0xc0) == 0xc0)
{
src_reg = LOAD_REG_W(fetchdat & 7);
}
else
{
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
MEM_LOAD_ADDR_EA_W(target_seg);
src_reg = 0;
}
dst_reg = LOAD_REG_W((fetchdat >> 3) & 7);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN16);
dst_reg = TEST_HOST_REG_W(dst_reg, src_reg);
STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, dst_reg);
RELEASE_REG(dst_reg);
RELEASE_REG(src_reg);
return op_pc + 1;
}
static uint32_t ropTEST_l_rm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
int src_reg, dst_reg;
if ((fetchdat & 0xc0) == 0xc0)
{
src_reg = LOAD_REG_L(fetchdat & 7);
}
else
{
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
MEM_LOAD_ADDR_EA_L(target_seg);
src_reg = 0;
}
dst_reg = LOAD_REG_L((fetchdat >> 3) & 7);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN32);
dst_reg = TEST_HOST_REG_L(dst_reg, src_reg);
STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, dst_reg);
RELEASE_REG(dst_reg);
RELEASE_REG(src_reg);
return op_pc + 1;
}
static uint32_t ropAND_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
int host_reg = LOAD_REG_B(REG_AL);
AND_HOST_REG_IMM(host_reg, (fetchdat & 0xff) | 0xffffff00);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN8);
STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, host_reg);
STORE_REG_B_RELEASE(host_reg);
return op_pc + 1;
}
static uint32_t ropAND_AX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
int host_reg = LOAD_REG_W(REG_AX);
AND_HOST_REG_IMM(host_reg, (fetchdat & 0xffff) | 0xffff0000);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN16);
STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, host_reg);
STORE_REG_W_RELEASE(host_reg);
return op_pc + 2;
}
static uint32_t ropAND_EAX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
int host_reg = LOAD_REG_L(REG_EAX);
fetchdat = fastreadl(cs + op_pc);
AND_HOST_REG_IMM(host_reg, fetchdat);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN32);
STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg);
STORE_REG_L_RELEASE(host_reg);
return op_pc + 4;
}
static uint32_t ropOR_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
int host_reg = LOAD_REG_B(REG_AL);
OR_HOST_REG_IMM(host_reg, fetchdat & 0xff);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN8);
STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, host_reg);
STORE_REG_B_RELEASE(host_reg);
return op_pc + 1;
}
static uint32_t ropOR_AX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
int host_reg = LOAD_REG_W(REG_AX);
OR_HOST_REG_IMM(host_reg, fetchdat & 0xffff);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN16);
STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, host_reg);
STORE_REG_W_RELEASE(host_reg);
return op_pc + 2;
}
static uint32_t ropOR_EAX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
int host_reg = LOAD_REG_L(REG_EAX);
fetchdat = fastreadl(cs + op_pc);
OR_HOST_REG_IMM(host_reg, fetchdat);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN32);
STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg);
STORE_REG_L_RELEASE(host_reg);
return op_pc + 4;
}
static uint32_t ropTEST_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
int host_reg = LOAD_REG_B(REG_AL);
host_reg = TEST_HOST_REG_IMM(host_reg, fetchdat & 0xff);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN8);
STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg);
RELEASE_REG(host_reg);
return op_pc + 1;
}
static uint32_t ropTEST_AX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
int host_reg = LOAD_REG_W(REG_AX);
host_reg = TEST_HOST_REG_IMM(host_reg, fetchdat & 0xffff);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN16);
STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg);
RELEASE_REG(host_reg);
return op_pc + 2;
}
static uint32_t ropTEST_EAX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
int host_reg = LOAD_REG_L(REG_EAX);
fetchdat = fastreadl(cs + op_pc);
host_reg = TEST_HOST_REG_IMM(host_reg, fetchdat);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN32);
STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg);
RELEASE_REG(host_reg);
return op_pc + 4;
}
static uint32_t ropXOR_AL_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
int host_reg = LOAD_REG_B(REG_AL);
XOR_HOST_REG_IMM(host_reg, fetchdat & 0xff);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN8);
STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, host_reg);
STORE_REG_B_RELEASE(host_reg);
return op_pc + 1;
}
static uint32_t ropXOR_AX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
int host_reg = LOAD_REG_W(REG_AX);
XOR_HOST_REG_IMM(host_reg, fetchdat & 0xffff);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN16);
STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, host_reg);
STORE_REG_W_RELEASE(host_reg);
return op_pc + 2;
}
static uint32_t ropXOR_EAX_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
int host_reg = LOAD_REG_L(REG_EAX);
fetchdat = fastreadl(cs + op_pc);
XOR_HOST_REG_IMM(host_reg, fetchdat);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN32);
STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg);
STORE_REG_L_RELEASE(host_reg);
return op_pc + 4;
}
static uint32_t ropF6(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
x86seg *target_seg;
int host_reg;
uint8_t imm;
switch (fetchdat & 0x38)
{
case 0x00: /*TEST b,#8*/
if ((fetchdat & 0xc0) == 0xc0)
{
host_reg = LOAD_REG_B(fetchdat & 7);
imm = (fetchdat >> 8) & 0xff;
}
else
{
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
imm = fastreadb(cs + op_pc + 1);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
MEM_LOAD_ADDR_EA_B(target_seg);
host_reg = 0;
}
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN8);
host_reg = TEST_HOST_REG_IMM(host_reg, imm);
STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, host_reg);
RELEASE_REG(host_reg);
return op_pc + 2;
case 0x10: /*NOT b*/
if ((fetchdat & 0xc0) != 0xc0)
return 0;
host_reg = LOAD_REG_B(fetchdat & 7);
XOR_HOST_REG_IMM(host_reg, 0xff);
STORE_REG_B_RELEASE(host_reg);
return op_pc + 1;
case 0x18: /*NEG b*/
if ((fetchdat & 0xc0) != 0xc0)
return 0;
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB8);
host_reg = LOAD_REG_B(fetchdat & 7);
STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_op2, host_reg);
NEG_HOST_REG_B(host_reg);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op1, 0);
STORE_REG_B_RELEASE(host_reg);
STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, host_reg);
return op_pc + 1;
}
return 0;
}
static uint32_t ropF7_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
x86seg *target_seg;
int host_reg;
uint16_t imm;
switch (fetchdat & 0x38)
{
case 0x00: /*TEST w,#*/
if ((fetchdat & 0xc0) == 0xc0)
{
host_reg = LOAD_REG_W(fetchdat & 7);
imm = (fetchdat >> 8) & 0xffff;
}
else
{
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
imm = fastreadw(cs + op_pc + 1);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
MEM_LOAD_ADDR_EA_W(target_seg);
host_reg = 0;
}
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN16);
host_reg = TEST_HOST_REG_IMM(host_reg, imm);
STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, host_reg);
RELEASE_REG(host_reg);
return op_pc + 3;
case 0x10: /*NOT w*/
if ((fetchdat & 0xc0) != 0xc0)
return 0;
host_reg = LOAD_REG_W(fetchdat & 7);
XOR_HOST_REG_IMM(host_reg, 0xffff);
STORE_REG_W_RELEASE(host_reg);
return op_pc + 1;
case 0x18: /*NEG w*/
if ((fetchdat & 0xc0) != 0xc0)
return 0;
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB16);
host_reg = LOAD_REG_W(fetchdat & 7);
STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op2, host_reg);
NEG_HOST_REG_W(host_reg);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op1, 0);
STORE_REG_W_RELEASE(host_reg);
STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, host_reg);
return op_pc + 1;
}
return 0;
}
static uint32_t ropF7_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
x86seg *target_seg;
int host_reg;
uint32_t imm;
switch (fetchdat & 0x38)
{
case 0x00: /*TEST l,#*/
if ((fetchdat & 0xc0) == 0xc0)
{
host_reg = LOAD_REG_L(fetchdat & 7);
imm = fastreadl(cs + op_pc + 1);
}
else
{
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
imm = fastreadl(cs + op_pc + 1);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
MEM_LOAD_ADDR_EA_L(target_seg);
host_reg = 0;
}
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_ZN32);
host_reg = TEST_HOST_REG_IMM(host_reg, imm);
STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg);
RELEASE_REG(host_reg);
return op_pc + 5;
case 0x10: /*NOT l*/
if ((fetchdat & 0xc0) != 0xc0)
return 0;
host_reg = LOAD_REG_L(fetchdat & 7);
XOR_HOST_REG_IMM(host_reg, 0xffffffff);
STORE_REG_L_RELEASE(host_reg);
return op_pc + 1;
case 0x18: /*NEG l*/
if ((fetchdat & 0xc0) != 0xc0)
return 0;
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SUB32);
host_reg = LOAD_REG_L(fetchdat & 7);
STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op2, host_reg);
NEG_HOST_REG_L(host_reg);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op1, 0);
STORE_REG_L_RELEASE(host_reg);
STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg);
return op_pc + 1;
}
return 0;
}
uint32_t ropXOR_AL_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropXOR_AX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropXOR_EAX_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropXOR_b_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropXOR_b_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropXOR_w_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropXOR_w_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropXOR_l_rm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropXOR_l_rmw(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);

611
src/codegen_ops_misc.c Normal file
View file

@ -0,0 +1,611 @@
#include "ibm.h"
#include "x86.h"
#include "x86_flags.h"
#include "386_common.h"
#include "codegen.h"
#include "codegen_ir.h"
#include "codegen_ops.h"
#include "codegen_ops_helpers.h"
#include "codegen_ops_misc.h"
uint32_t ropLEA_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = (fetchdat >> 3) & 7;
if ((fetchdat & 0xc0) == 0xc0)
return 0;
codegen_mark_code_present(block, cs+op_pc, 1);
codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
uop_MOV(ir, IREG_16(dest_reg), IREG_eaaddr_W);
return op_pc + 1;
}
uint32_t ropLEA_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = (fetchdat >> 3) & 7;
if ((fetchdat & 0xc0) == 0xc0)
return 0;
codegen_mark_code_present(block, cs+op_pc, 1);
codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
uop_MOV(ir, IREG_32(dest_reg), IREG_eaaddr);
return op_pc + 1;
}
uint32_t ropF6(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
x86seg *target_seg = NULL;
uint8_t imm_data;
int reg;
if (fetchdat & 0x20)
return 0;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
reg = IREG_8(fetchdat & 7);
else
{
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
if ((fetchdat & 0x30) == 0x10) /*NEG/NOT*/
codegen_check_seg_write(block, ir, target_seg);
else
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr);
reg = IREG_temp0_B;
}
switch (fetchdat & 0x38)
{
case 0x00: case 0x08: /*TEST*/
imm_data = fastreadb(cs + op_pc + 1);
uop_AND_IMM(ir, IREG_flags_res_B, reg, imm_data);
uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_B);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN8);
codegen_flags_changed = 1;
codegen_mark_code_present(block, cs+op_pc+1, 1);
return op_pc+2;
case 0x10: /*NOT*/
uop_XOR_IMM(ir, reg, reg, 0xff);
if ((fetchdat & 0xc0) != 0xc0)
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, reg);
codegen_flags_changed = 1;
return op_pc+1;
case 0x18: /*NEG*/
uop_MOV_IMM(ir, IREG_temp1_B, 0);
if ((fetchdat & 0xc0) == 0xc0)
{
uop_MOVZX(ir, IREG_flags_op2, reg);
uop_SUB(ir, IREG_temp1_B, IREG_temp1_B, reg);
uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B);
uop_MOV(ir, reg, IREG_temp1_B);
}
else
{
uop_SUB(ir, IREG_temp1_B, IREG_temp1_B, reg);
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_B);
uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_B);
uop_MOVZX(ir, IREG_flags_res, IREG_temp1_B);
}
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB8);
uop_MOV_IMM(ir, IREG_flags_op1, 0);
codegen_flags_changed = 1;
return op_pc+1;
}
return 0;
}
uint32_t ropF7_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
x86seg *target_seg = NULL;
uint16_t imm_data;
int reg;
if (fetchdat & 0x20)
return 0;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
reg = IREG_16(fetchdat & 7);
else
{
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
if ((fetchdat & 0x30) == 0x10) /*NEG/NOT*/
codegen_check_seg_write(block, ir, target_seg);
else
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr);
reg = IREG_temp0_W;
}
switch (fetchdat & 0x38)
{
case 0x00: case 0x08: /*TEST*/
imm_data = fastreadw(cs + op_pc + 1);
uop_AND_IMM(ir, IREG_flags_res_W, reg, imm_data);
uop_MOVZX(ir, IREG_flags_res, IREG_flags_res_W);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN16);
codegen_flags_changed = 1;
codegen_mark_code_present(block, cs+op_pc+1, 2);
return op_pc+3;
case 0x10: /*NOT*/
uop_XOR_IMM(ir, reg, reg, 0xffff);
if ((fetchdat & 0xc0) != 0xc0)
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, reg);
codegen_flags_changed = 1;
return op_pc+1;
case 0x18: /*NEG*/
uop_MOV_IMM(ir, IREG_temp1_W, 0);
if ((fetchdat & 0xc0) == 0xc0)
{
uop_MOVZX(ir, IREG_flags_op2, reg);
uop_SUB(ir, IREG_temp1_W, IREG_temp1_W, reg);
uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W);
uop_MOV(ir, reg, IREG_temp1_W);
}
else
{
uop_SUB(ir, IREG_temp1_W, IREG_temp1_W, reg);
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W);
uop_MOVZX(ir, IREG_flags_op2, IREG_temp0_W);
uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W);
}
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB16);
uop_MOV_IMM(ir, IREG_flags_op1, 0);
codegen_flags_changed = 1;
return op_pc+1;
}
return 0;
}
uint32_t ropF7_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
x86seg *target_seg = NULL;
uint32_t imm_data;
int reg;
if (fetchdat & 0x20)
return 0;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
reg = IREG_32(fetchdat & 7);
else
{
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
if ((fetchdat & 0x30) == 0x10) /*NEG/NOT*/
codegen_check_seg_write(block, ir, target_seg);
else
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr);
reg = IREG_temp0;
}
switch (fetchdat & 0x38)
{
case 0x00: case 0x08: /*TEST*/
imm_data = fastreadl(cs + op_pc + 1);
uop_AND_IMM(ir, IREG_flags_res, reg, imm_data);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_ZN32);
codegen_flags_changed = 1;
codegen_mark_code_present(block, cs+op_pc+1, 4);
return op_pc+5;
case 0x10: /*NOT*/
uop_XOR_IMM(ir, reg, reg, 0xffffffff);
if ((fetchdat & 0xc0) != 0xc0)
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, reg);
codegen_flags_changed = 1;
return op_pc+1;
case 0x18: /*NEG*/
uop_MOV_IMM(ir, IREG_temp1, 0);
if ((fetchdat & 0xc0) == 0xc0)
{
uop_MOV(ir, IREG_flags_op2, reg);
uop_SUB(ir, IREG_temp1, IREG_temp1, reg);
uop_MOV(ir, IREG_flags_res, IREG_temp1);
uop_MOV(ir, reg, IREG_temp1);
}
else
{
uop_SUB(ir, IREG_temp1, IREG_temp1, reg);
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1);
uop_MOV(ir, IREG_flags_op2, IREG_temp0);
uop_MOV(ir, IREG_flags_res, IREG_temp1);
}
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_SUB32);
uop_MOV_IMM(ir, IREG_flags_op1, 0);
codegen_flags_changed = 1;
return op_pc+1;
}
return 0;
}
static void rebuild_c(ir_data_t *ir)
{
int needs_rebuild = 1;
if (codegen_flags_changed)
{
switch (cpu_state.flags_op)
{
case FLAGS_INC8: case FLAGS_INC16: case FLAGS_INC32:
case FLAGS_DEC8: case FLAGS_DEC16: case FLAGS_DEC32:
needs_rebuild = 0;
break;
}
}
if (needs_rebuild)
{
uop_CALL_FUNC(ir, flags_rebuild_c);
}
}
uint32_t ropFF_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
x86seg *target_seg = NULL;
int src_reg, sp_reg;
if ((fetchdat & 0x38) != 0x00 && (fetchdat & 0x38) != 0x08 && (fetchdat & 0x38) != 0x10 && (fetchdat & 0x38) != 0x20 && (fetchdat & 0x38) != 0x28 && (fetchdat & 0x38) != 0x30)
return 0;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
if ((fetchdat & 0x38) == 0x28)
return 0;
src_reg = IREG_16(fetchdat & 7);
}
else
{
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
if (!(fetchdat & 0x30)) /*INC/DEC*/
codegen_check_seg_write(block, ir, target_seg);
else
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr);
src_reg = IREG_temp0_W;
}
switch (fetchdat & 0x38)
{
case 0x00: /*INC*/
rebuild_c(ir);
codegen_flags_changed = 1;
if ((fetchdat & 0xc0) == 0xc0)
{
uop_MOVZX(ir, IREG_flags_op1, src_reg);
uop_ADD_IMM(ir, src_reg, src_reg, 1);
uop_MOVZX(ir, IREG_flags_res, src_reg);
uop_MOV_IMM(ir, IREG_flags_op2, 1);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_INC16);
}
else
{
uop_ADD_IMM(ir, IREG_temp1_W, src_reg, 1);
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W);
uop_MOVZX(ir, IREG_flags_op1, src_reg);
uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W);
uop_MOV_IMM(ir, IREG_flags_op2, 1);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_INC16);
}
return op_pc+1;
case 0x08: /*DEC*/
rebuild_c(ir);
codegen_flags_changed = 1;
if ((fetchdat & 0xc0) == 0xc0)
{
uop_MOVZX(ir, IREG_flags_op1, src_reg);
uop_SUB_IMM(ir, src_reg, src_reg, 1);
uop_MOVZX(ir, IREG_flags_res, src_reg);
uop_MOV_IMM(ir, IREG_flags_op2, 1);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_DEC16);
}
else
{
uop_SUB_IMM(ir, IREG_temp1_W, src_reg, 1);
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1_W);
uop_MOVZX(ir, IREG_flags_op1, src_reg);
uop_MOVZX(ir, IREG_flags_res, IREG_temp1_W);
uop_MOV_IMM(ir, IREG_flags_op2, 1);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_DEC16);
}
return op_pc+1;
case 0x10: /*CALL*/
if ((fetchdat & 0xc0) == 0xc0)
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
sp_reg = LOAD_SP_WITH_OFFSET(ir, -2);
uop_MEM_STORE_IMM_16(ir, IREG_SS_base, sp_reg, op_pc + 1);
SUB_SP(ir, 2);
uop_MOVZX(ir, IREG_pc, src_reg);
return -1;
case 0x20: /*JMP*/
uop_MOVZX(ir, IREG_pc, src_reg);
return -1;
case 0x28: /*JMP far*/
uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, ireg_seg_base(target_seg), IREG_eaaddr, 2);
uop_LOAD_FUNC_ARG_REG(ir, 0, IREG_temp1_W);
uop_LOAD_FUNC_ARG_IMM(ir, 1, cpu_state.oldpc);
uop_CALL_FUNC(ir, loadcsjmp);
uop_MOVZX(ir, IREG_pc, src_reg);
return -1;
case 0x30: /*PUSH*/
if ((fetchdat & 0xc0) == 0xc0)
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
sp_reg = LOAD_SP_WITH_OFFSET(ir, -2);
uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, src_reg);
SUB_SP(ir, 2);
return op_pc+1;
}
return 0;
}
uint32_t ropFF_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
x86seg *target_seg = NULL;
int src_reg, sp_reg;
if ((fetchdat & 0x38) != 0x00 && (fetchdat & 0x38) != 0x08 && (fetchdat & 0x38) != 0x10 && (fetchdat & 0x38) != 0x20 && (fetchdat & 0x38) != 0x28 && (fetchdat & 0x38) != 0x30)
return 0;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
if ((fetchdat & 0x38) == 0x28)
return 0;
src_reg = IREG_32(fetchdat & 7);
}
else
{
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
if (!(fetchdat & 0x30)) /*INC/DEC*/
codegen_check_seg_write(block, ir, target_seg);
else
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr);
src_reg = IREG_temp0;
}
switch (fetchdat & 0x38)
{
case 0x00: /*INC*/
rebuild_c(ir);
codegen_flags_changed = 1;
if ((fetchdat & 0xc0) == 0xc0)
{
uop_MOV(ir, IREG_flags_op1, src_reg);
uop_ADD_IMM(ir, src_reg, src_reg, 1);
uop_MOV(ir, IREG_flags_res, src_reg);
uop_MOV_IMM(ir, IREG_flags_op2, 1);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_INC32);
}
else
{
uop_ADD_IMM(ir, IREG_temp1, src_reg, 1);
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1);
uop_MOV(ir, IREG_flags_op1, src_reg);
uop_MOV(ir, IREG_flags_res, IREG_temp1);
uop_MOV_IMM(ir, IREG_flags_op2, 1);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_INC32);
}
return op_pc+1;
case 0x08: /*DEC*/
rebuild_c(ir);
codegen_flags_changed = 1;
if ((fetchdat & 0xc0) == 0xc0)
{
uop_MOV(ir, IREG_flags_op1, src_reg);
uop_SUB_IMM(ir, src_reg, src_reg, 1);
uop_MOV(ir, IREG_flags_res, src_reg);
uop_MOV_IMM(ir, IREG_flags_op2, 1);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_DEC32);
}
else
{
uop_SUB_IMM(ir, IREG_temp1, src_reg, 1);
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp1);
uop_MOV(ir, IREG_flags_op1, src_reg);
uop_MOV(ir, IREG_flags_res, IREG_temp1);
uop_MOV_IMM(ir, IREG_flags_op2, 1);
uop_MOV_IMM(ir, IREG_flags_op, FLAGS_DEC32);
}
return op_pc+1;
case 0x10: /*CALL*/
if ((fetchdat & 0xc0) == 0xc0)
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
sp_reg = LOAD_SP_WITH_OFFSET(ir, -4);
uop_MEM_STORE_IMM_32(ir, IREG_SS_base, sp_reg, op_pc + 1);
SUB_SP(ir, 4);
uop_MOV(ir, IREG_pc, src_reg);
return -1;
case 0x20: /*JMP*/
uop_MOV(ir, IREG_pc, src_reg);
return -1;
case 0x28: /*JMP far*/
uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, ireg_seg_base(target_seg), IREG_eaaddr, 4);
uop_LOAD_FUNC_ARG_REG(ir, 0, IREG_temp1_W);
uop_LOAD_FUNC_ARG_IMM(ir, 1, cpu_state.oldpc);
uop_CALL_FUNC(ir, loadcsjmp);
uop_MOV(ir, IREG_pc, src_reg);
return -1;
case 0x30: /*PUSH*/
if ((fetchdat & 0xc0) == 0xc0)
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
sp_reg = LOAD_SP_WITH_OFFSET(ir, -4);
uop_MEM_STORE_REG(ir, IREG_SS_base, sp_reg, src_reg);
SUB_SP(ir, 4);
return op_pc+1;
}
return 0;
}
uint32_t ropNOP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
return op_pc;
}
uint32_t ropCBW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uop_MOVSX(ir, IREG_AX, IREG_AL);
return op_pc;
}
uint32_t ropCDQ(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uop_SAR_IMM(ir, IREG_EDX, IREG_EAX, 31);
return op_pc;
}
uint32_t ropCWD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uop_SAR_IMM(ir, IREG_DX, IREG_AX, 15);
return op_pc;
}
uint32_t ropCWDE(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uop_MOVSX(ir, IREG_EAX, IREG_AX);
return op_pc;
}
#define ropLxS(name, seg) \
uint32_t rop ## name ## _16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
{ \
x86seg *target_seg = NULL; \
int dest_reg = (fetchdat >> 3) & 7; \
\
if ((fetchdat & 0xc0) == 0xc0) \
return 0; \
\
codegen_mark_code_present(block, cs+op_pc, 1); \
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
codegen_check_seg_read(block, ir, target_seg); \
uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr); \
uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, ireg_seg_base(target_seg), IREG_eaaddr, 2); \
uop_LOAD_SEG(ir, seg, IREG_temp1_W); \
uop_MOV(ir, IREG_16(dest_reg), IREG_temp0_W); \
\
if (seg == &cpu_state.seg_ss) \
CPU_BLOCK_END(); \
\
return op_pc + 1; \
} \
uint32_t rop ## name ## _32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
{ \
x86seg *target_seg = NULL; \
int dest_reg = (fetchdat >> 3) & 7; \
\
if ((fetchdat & 0xc0) == 0xc0) \
return 0; \
\
codegen_mark_code_present(block, cs+op_pc, 1); \
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
codegen_check_seg_read(block, ir, target_seg); \
uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr); \
uop_MEM_LOAD_REG_OFFSET(ir, IREG_temp1_W, ireg_seg_base(target_seg), IREG_eaaddr, 4); \
uop_LOAD_SEG(ir, seg, IREG_temp1_W); \
uop_MOV(ir, IREG_32(dest_reg), IREG_temp0); \
\
if (seg == &cpu_state.seg_ss) \
CPU_BLOCK_END(); \
\
return op_pc + 1; \
}
ropLxS(LDS, &cpu_state.seg_ds)
ropLxS(LES, &cpu_state.seg_es)
ropLxS(LFS, &cpu_state.seg_fs)
ropLxS(LGS, &cpu_state.seg_gs)
ropLxS(LSS, &cpu_state.seg_ss)
uint32_t ropCLC(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uop_CALL_FUNC(ir, flags_rebuild);
uop_AND_IMM(ir, IREG_flags, IREG_flags, ~C_FLAG);
return op_pc;
}
uint32_t ropCMC(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uop_CALL_FUNC(ir, flags_rebuild);
uop_XOR_IMM(ir, IREG_flags, IREG_flags, C_FLAG);
return op_pc;
}
uint32_t ropSTC(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uop_CALL_FUNC(ir, flags_rebuild);
uop_OR_IMM(ir, IREG_flags, IREG_flags, C_FLAG);
return op_pc;
}
uint32_t ropCLD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uop_AND_IMM(ir, IREG_flags, IREG_flags, ~D_FLAG);
return op_pc;
}
uint32_t ropSTD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uop_OR_IMM(ir, IREG_flags, IREG_flags, D_FLAG);
return op_pc;
}
uint32_t ropCLI(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
if (!IOPLp && (cr4 & (CR4_VME | CR4_PVI)))
return 0;
uop_AND_IMM(ir, IREG_flags, IREG_flags, ~I_FLAG);
return op_pc;
}
uint32_t ropSTI(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
if (!IOPLp && (cr4 & (CR4_VME | CR4_PVI)))
return 0;
uop_OR_IMM(ir, IREG_flags, IREG_flags, I_FLAG);
return op_pc;
}

View file

@ -1,269 +1,37 @@
static uint32_t ropNOP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
return op_pc;
}
uint32_t ropLEA_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropLEA_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
static uint32_t ropCLD(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
CLEAR_BITS((uintptr_t)&flags, D_FLAG);
return op_pc;
}
static uint32_t ropSTD(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
SET_BITS((uintptr_t)&flags, D_FLAG);
return op_pc;
}
uint32_t ropF6(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropF7_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropF7_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
static uint32_t ropCLI(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
if (!IOPLp && (cr4 & (CR4_VME | CR4_PVI)))
return 0;
CLEAR_BITS((uintptr_t)&flags, I_FLAG);
return op_pc;
}
static uint32_t ropSTI(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
if (!IOPLp && (cr4 & (CR4_VME | CR4_PVI)))
return 0;
SET_BITS((uintptr_t)&flags, I_FLAG);
return op_pc;
}
uint32_t ropFF_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropFF_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
static uint32_t ropFE(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
x86seg *target_seg = NULL;
int host_reg;
uint32_t ropNOP(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
if ((fetchdat & 0x30) != 0x00)
return 0;
uint32_t ropCBW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropCDQ(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropCWD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropCWDE(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
CALL_FUNC((uintptr_t)flags_rebuild_c);
if ((fetchdat & 0xc0) == 0xc0)
host_reg = LOAD_REG_B(fetchdat & 7);
else
{
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
uint32_t ropLDS_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropLDS_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropLES_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropLES_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropLFS_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropLFS_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropLGS_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropLGS_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropLSS_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropLSS_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
SAVE_EA();
MEM_CHECK_WRITE(target_seg);
host_reg = MEM_LOAD_ADDR_EA_B_NO_ABRT(target_seg);
}
switch (fetchdat & 0x38)
{
case 0x00: /*INC*/
STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_op1, host_reg);
ADD_HOST_REG_IMM_B(host_reg, 1);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, 1);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_INC8);
STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, host_reg);
break;
case 0x08: /*DEC*/
STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_op1, host_reg);
SUB_HOST_REG_IMM_B(host_reg, 1);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, 1);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_DEC8);
STORE_HOST_REG_ADDR_BL((uintptr_t)&cpu_state.flags_res, host_reg);
break;
}
uint32_t ropCLC(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropCMC(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropSTC(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
if ((fetchdat & 0xc0) == 0xc0)
STORE_REG_B_RELEASE(host_reg);
else
{
LOAD_EA();
MEM_STORE_ADDR_EA_B_NO_ABRT(target_seg, host_reg);
}
codegen_flags_changed = 1;
return op_pc + 1;
}
static uint32_t codegen_temp;
static uint32_t ropFF_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
x86seg *target_seg = NULL;
int host_reg;
if ((fetchdat & 0x30) != 0x00 && (fetchdat & 0x08))
return 0;
uint32_t ropCLD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropSTD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
if ((fetchdat & 0x30) == 0x00)
CALL_FUNC((uintptr_t)flags_rebuild_c);
if ((fetchdat & 0xc0) == 0xc0)
host_reg = LOAD_REG_W(fetchdat & 7);
else
{
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
if ((fetchdat & 0x30) != 0x00)
{
MEM_LOAD_ADDR_EA_W(target_seg);
host_reg = 0;
}
else
{
SAVE_EA();
MEM_CHECK_WRITE_W(target_seg);
host_reg = MEM_LOAD_ADDR_EA_W_NO_ABRT(target_seg);
}
}
switch (fetchdat & 0x38)
{
case 0x00: /*INC*/
STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op1, host_reg);
ADD_HOST_REG_IMM_W(host_reg, 1);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, 1);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_INC16);
STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, host_reg);
if ((fetchdat & 0xc0) == 0xc0)
STORE_REG_W_RELEASE(host_reg);
else
{
LOAD_EA();
MEM_STORE_ADDR_EA_W_NO_ABRT(target_seg, host_reg);
}
codegen_flags_changed = 1;
return op_pc + 1;
case 0x08: /*DEC*/
STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_op1, host_reg);
SUB_HOST_REG_IMM_W(host_reg, 1);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, 1);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_DEC16);
STORE_HOST_REG_ADDR_WL((uintptr_t)&cpu_state.flags_res, host_reg);
if ((fetchdat & 0xc0) == 0xc0)
STORE_REG_W_RELEASE(host_reg);
else
{
LOAD_EA();
MEM_STORE_ADDR_EA_W_NO_ABRT(target_seg, host_reg);
}
codegen_flags_changed = 1;
return op_pc + 1;
case 0x10: /*CALL*/
STORE_HOST_REG_ADDR_W((uintptr_t)&codegen_temp, host_reg);
RELEASE_REG(host_reg);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
LOAD_STACK_TO_EA(-2);
host_reg = LOAD_REG_IMM(op_pc + 1);
MEM_STORE_ADDR_EA_W(&_ss, host_reg);
SP_MODIFY(-2);
host_reg = LOAD_VAR_W((uintptr_t)&codegen_temp);
STORE_HOST_REG_ADDR_W((uintptr_t)&cpu_state.pc, host_reg);
return -1;
case 0x20: /*JMP*/
STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.pc, host_reg);
return -1;
case 0x30: /*PUSH*/
if (!host_reg)
host_reg = LOAD_HOST_REG(host_reg);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
LOAD_STACK_TO_EA(-2);
MEM_STORE_ADDR_EA_W(&_ss, host_reg);
SP_MODIFY(-2);
return op_pc + 1;
}
return 0;
}
static uint32_t ropFF_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
x86seg *target_seg = NULL;
int host_reg;
if ((fetchdat & 0x30) != 0x00 && (fetchdat & 0x08))
return 0;
if ((fetchdat & 0x30) == 0x00)
CALL_FUNC((uintptr_t)flags_rebuild_c);
if ((fetchdat & 0xc0) == 0xc0)
host_reg = LOAD_REG_L(fetchdat & 7);
else
{
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
if ((fetchdat & 0x30) != 0x00)
{
MEM_LOAD_ADDR_EA_L(target_seg);
host_reg = 0;
}
else
{
SAVE_EA();
MEM_CHECK_WRITE_L(target_seg);
host_reg = MEM_LOAD_ADDR_EA_L_NO_ABRT(target_seg);
}
}
switch (fetchdat & 0x38)
{
case 0x00: /*INC*/
STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op1, host_reg);
ADD_HOST_REG_IMM(host_reg, 1);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, 1);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_INC32);
STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg);
if ((fetchdat & 0xc0) == 0xc0)
STORE_REG_L_RELEASE(host_reg);
else
{
LOAD_EA();
MEM_STORE_ADDR_EA_L_NO_ABRT(target_seg, host_reg);
}
codegen_flags_changed = 1;
return op_pc + 1;
case 0x08: /*DEC*/
STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_op1, host_reg);
SUB_HOST_REG_IMM(host_reg, 1);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, 1);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_DEC32);
STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.flags_res, host_reg);
if ((fetchdat & 0xc0) == 0xc0)
STORE_REG_L_RELEASE(host_reg);
else
{
LOAD_EA();
MEM_STORE_ADDR_EA_L_NO_ABRT(target_seg, host_reg);
}
codegen_flags_changed = 1;
return op_pc + 1;
case 0x10: /*CALL*/
STORE_HOST_REG_ADDR((uintptr_t)&codegen_temp, host_reg);
RELEASE_REG(host_reg);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
LOAD_STACK_TO_EA(-4);
host_reg = LOAD_REG_IMM(op_pc + 1);
MEM_STORE_ADDR_EA_L(&_ss, host_reg);
SP_MODIFY(-4);
host_reg = LOAD_VAR_L((uintptr_t)&codegen_temp);
STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.pc, host_reg);
return -1;
case 0x20: /*JMP*/
STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.pc, host_reg);
return -1;
case 0x30: /*PUSH*/
if (!host_reg)
host_reg = LOAD_HOST_REG(host_reg);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
LOAD_STACK_TO_EA(-4);
MEM_STORE_ADDR_EA_L(&_ss, host_reg);
SP_MODIFY(-4);
return op_pc + 1;
}
return 0;
}
uint32_t ropCLI(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropSTI(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);

View file

@ -1,277 +0,0 @@
static uint32_t ropMOVQ_q_mm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
int host_reg1, host_reg2;
MMX_ENTER();
LOAD_MMX_Q((fetchdat >> 3) & 7, &host_reg1, &host_reg2);
if ((fetchdat & 0xc0) == 0xc0)
{
STORE_MMX_Q(fetchdat & 7, host_reg1, host_reg2);
}
else
{
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
CHECK_SEG_WRITE(target_seg);
CHECK_SEG_LIMITS(target_seg, 7);
MEM_STORE_ADDR_EA_Q(target_seg, host_reg1, host_reg2);
}
return op_pc + 1;
}
static uint32_t ropMOVQ_mm_q(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
MMX_ENTER();
if ((fetchdat & 0xc0) == 0xc0)
{
int host_reg1, host_reg2;
LOAD_MMX_Q(fetchdat & 7, &host_reg1, &host_reg2);
STORE_MMX_Q((fetchdat >> 3) & 7, host_reg1, host_reg2);
}
else
{
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
CHECK_SEG_READ(target_seg);
MEM_LOAD_ADDR_EA_Q(target_seg);
STORE_MMX_Q((fetchdat >> 3) & 7, LOAD_Q_REG_1, LOAD_Q_REG_2);
}
return op_pc + 1;
}
static uint32_t ropMOVD_l_mm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
int host_reg;
MMX_ENTER();
host_reg = LOAD_MMX_D((fetchdat >> 3) & 7);
if ((fetchdat & 0xc0) == 0xc0)
{
STORE_REG_TARGET_L_RELEASE(host_reg, fetchdat & 7);
}
else
{
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
CHECK_SEG_WRITE(target_seg);
CHECK_SEG_LIMITS(target_seg, 3);
MEM_STORE_ADDR_EA_L(target_seg, host_reg);
}
return op_pc + 1;
}
static uint32_t ropMOVD_mm_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
MMX_ENTER();
if ((fetchdat & 0xc0) == 0xc0)
{
int host_reg = LOAD_REG_L(fetchdat & 7);
STORE_MMX_LQ((fetchdat >> 3) & 7, host_reg);
}
else
{
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
CHECK_SEG_READ(target_seg);
MEM_LOAD_ADDR_EA_L(target_seg);
STORE_MMX_LQ((fetchdat >> 3) & 7, 0);
}
return op_pc + 1;
}
#define MMX_OP(name, func) \
static uint32_t name(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
{ \
int src_reg1, src_reg2; \
int xmm_src, xmm_dst; \
\
MMX_ENTER(); \
\
if ((fetchdat & 0xc0) == 0xc0) \
{ \
xmm_src = LOAD_MMX_Q_MMX(fetchdat & 7); \
} \
else \
{ \
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \
\
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \
\
CHECK_SEG_READ(target_seg); \
\
MEM_LOAD_ADDR_EA_Q(target_seg); \
src_reg1 = LOAD_Q_REG_1; \
src_reg2 = LOAD_Q_REG_2; \
xmm_src = LOAD_INT_TO_MMX(src_reg1, src_reg2); \
} \
xmm_dst = LOAD_MMX_Q_MMX((fetchdat >> 3) & 7); \
func(xmm_dst, xmm_src); \
STORE_MMX_Q_MMX((fetchdat >> 3) & 7, xmm_dst); \
\
return op_pc + 1; \
}
MMX_OP(ropPAND, MMX_AND)
MMX_OP(ropPANDN, MMX_ANDN)
MMX_OP(ropPOR, MMX_OR)
MMX_OP(ropPXOR, MMX_XOR)
MMX_OP(ropPADDB, MMX_ADDB)
MMX_OP(ropPADDW, MMX_ADDW)
MMX_OP(ropPADDD, MMX_ADDD)
MMX_OP(ropPADDSB, MMX_ADDSB)
MMX_OP(ropPADDSW, MMX_ADDSW)
MMX_OP(ropPADDUSB, MMX_ADDUSB)
MMX_OP(ropPADDUSW, MMX_ADDUSW)
MMX_OP(ropPSUBB, MMX_SUBB)
MMX_OP(ropPSUBW, MMX_SUBW)
MMX_OP(ropPSUBD, MMX_SUBD)
MMX_OP(ropPSUBSB, MMX_SUBSB)
MMX_OP(ropPSUBSW, MMX_SUBSW)
MMX_OP(ropPSUBUSB, MMX_SUBUSB)
MMX_OP(ropPSUBUSW, MMX_SUBUSW)
MMX_OP(ropPUNPCKLBW, MMX_PUNPCKLBW);
MMX_OP(ropPUNPCKLWD, MMX_PUNPCKLWD);
MMX_OP(ropPUNPCKLDQ, MMX_PUNPCKLDQ);
MMX_OP(ropPACKSSWB, MMX_PACKSSWB);
MMX_OP(ropPCMPGTB, MMX_PCMPGTB);
MMX_OP(ropPCMPGTW, MMX_PCMPGTW);
MMX_OP(ropPCMPGTD, MMX_PCMPGTD);
MMX_OP(ropPACKUSWB, MMX_PACKUSWB);
MMX_OP(ropPUNPCKHBW, MMX_PUNPCKHBW);
MMX_OP(ropPUNPCKHWD, MMX_PUNPCKHWD);
MMX_OP(ropPUNPCKHDQ, MMX_PUNPCKHDQ);
MMX_OP(ropPACKSSDW, MMX_PACKSSDW);
MMX_OP(ropPCMPEQB, MMX_PCMPEQB);
MMX_OP(ropPCMPEQW, MMX_PCMPEQW);
MMX_OP(ropPCMPEQD, MMX_PCMPEQD);
MMX_OP(ropPSRLW, MMX_PSRLW)
MMX_OP(ropPSRLD, MMX_PSRLD)
MMX_OP(ropPSRLQ, MMX_PSRLQ)
MMX_OP(ropPSRAW, MMX_PSRAW)
MMX_OP(ropPSRAD, MMX_PSRAD)
MMX_OP(ropPSLLW, MMX_PSLLW)
MMX_OP(ropPSLLD, MMX_PSLLD)
MMX_OP(ropPSLLQ, MMX_PSLLQ)
MMX_OP(ropPMULLW, MMX_PMULLW);
MMX_OP(ropPMULHW, MMX_PMULHW);
MMX_OP(ropPMADDWD, MMX_PMADDWD);
static uint32_t ropPSxxW_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
int xmm_dst;
if ((fetchdat & 0xc0) != 0xc0)
return 0;
if ((fetchdat & 0x08) || !(fetchdat & 0x30))
return 0;
MMX_ENTER();
xmm_dst = LOAD_MMX_Q_MMX(fetchdat & 7);
switch (fetchdat & 0x38)
{
case 0x10: /*PSRLW*/
MMX_PSRLW_imm(xmm_dst, (fetchdat >> 8) & 0xff);
break;
case 0x20: /*PSRAW*/
MMX_PSRAW_imm(xmm_dst, (fetchdat >> 8) & 0xff);
break;
case 0x30: /*PSLLW*/
MMX_PSLLW_imm(xmm_dst, (fetchdat >> 8) & 0xff);
break;
}
STORE_MMX_Q_MMX(fetchdat & 7, xmm_dst);
return op_pc + 2;
}
static uint32_t ropPSxxD_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
int xmm_dst;
if ((fetchdat & 0xc0) != 0xc0)
return 0;
if ((fetchdat & 0x08) || !(fetchdat & 0x30))
return 0;
MMX_ENTER();
xmm_dst = LOAD_MMX_Q_MMX(fetchdat & 7);
switch (fetchdat & 0x38)
{
case 0x10: /*PSRLD*/
MMX_PSRLD_imm(xmm_dst, (fetchdat >> 8) & 0xff);
break;
case 0x20: /*PSRAD*/
MMX_PSRAD_imm(xmm_dst, (fetchdat >> 8) & 0xff);
break;
case 0x30: /*PSLLD*/
MMX_PSLLD_imm(xmm_dst, (fetchdat >> 8) & 0xff);
break;
}
STORE_MMX_Q_MMX(fetchdat & 7, xmm_dst);
return op_pc + 2;
}
static uint32_t ropPSxxQ_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
int xmm_dst;
if ((fetchdat & 0xc0) != 0xc0)
return 0;
if ((fetchdat & 0x08) || !(fetchdat & 0x30))
return 0;
MMX_ENTER();
xmm_dst = LOAD_MMX_Q_MMX(fetchdat & 7);
switch (fetchdat & 0x38)
{
case 0x10: /*PSRLQ*/
MMX_PSRLQ_imm(xmm_dst, (fetchdat >> 8) & 0xff);
break;
case 0x20: /*PSRAQ*/
MMX_PSRAQ_imm(xmm_dst, (fetchdat >> 8) & 0xff);
break;
case 0x30: /*PSLLQ*/
MMX_PSLLQ_imm(xmm_dst, (fetchdat >> 8) & 0xff);
break;
}
STORE_MMX_Q_MMX(fetchdat & 7, xmm_dst);
return op_pc + 2;
}
static uint32_t ropEMMS(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
codegen_mmx_entered = 0;
return 0;
}

View file

@ -0,0 +1,57 @@
#include "ibm.h"
#include "x86.h"
#include "x86_flags.h"
#include "386_common.h"
#include "codegen.h"
#include "codegen_accumulate.h"
#include "codegen_ir.h"
#include "codegen_ops.h"
#include "codegen_ops_mmx_arith.h"
#include "codegen_ops_helpers.h"
#define ropParith(func) \
uint32_t rop ## func(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
{ \
int dest_reg = (fetchdat >> 3) & 7; \
\
uop_MMX_ENTER(ir); \
codegen_mark_code_present(block, cs+op_pc, 1); \
if ((fetchdat & 0xc0) == 0xc0) \
{ \
int src_reg = fetchdat & 7; \
uop_ ## func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg)); \
} \
else \
{ \
x86seg *target_seg; \
\
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
codegen_check_seg_read(block, ir, target_seg); \
uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); \
uop_ ## func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); \
} \
\
return op_pc + 1; \
}
ropParith(PADDB)
ropParith(PADDW)
ropParith(PADDD)
ropParith(PADDSB)
ropParith(PADDSW)
ropParith(PADDUSB)
ropParith(PADDUSW)
ropParith(PSUBB)
ropParith(PSUBW)
ropParith(PSUBD)
ropParith(PSUBSB)
ropParith(PSUBSW)
ropParith(PSUBUSB)
ropParith(PSUBUSW)
ropParith(PMADDWD)
ropParith(PMULHW)
ropParith(PMULLW)

View file

@ -0,0 +1,19 @@
uint32_t ropPADDB(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPADDW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPADDD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPADDSB(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPADDSW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPADDUSB(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPADDUSW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPSUBB(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPSUBW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPSUBD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPSUBSB(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPSUBSW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPSUBUSB(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPSUBUSW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPMADDWD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPMULHW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPMULLW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);

44
src/codegen_ops_mmx_cmp.c Normal file
View file

@ -0,0 +1,44 @@
#include "ibm.h"
#include "x86.h"
#include "x86_flags.h"
#include "386_common.h"
#include "codegen.h"
#include "codegen_accumulate.h"
#include "codegen_ir.h"
#include "codegen_ops.h"
#include "codegen_ops_mmx_cmp.h"
#include "codegen_ops_helpers.h"
#define ropPcmp(func) \
uint32_t rop ## func(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
{ \
int dest_reg = (fetchdat >> 3) & 7; \
\
uop_MMX_ENTER(ir); \
codegen_mark_code_present(block, cs+op_pc, 1); \
if ((fetchdat & 0xc0) == 0xc0) \
{ \
int src_reg = fetchdat & 7; \
uop_ ## func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg)); \
} \
else \
{ \
x86seg *target_seg; \
\
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
codegen_check_seg_read(block, ir, target_seg); \
uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); \
uop_ ## func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); \
} \
\
return op_pc + 1; \
}
ropPcmp(PCMPEQB)
ropPcmp(PCMPEQW)
ropPcmp(PCMPEQD)
ropPcmp(PCMPGTB)
ropPcmp(PCMPGTW)
ropPcmp(PCMPGTD)

View file

@ -0,0 +1,6 @@
uint32_t ropPCMPEQB(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPCMPEQW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPCMPEQD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPCMPGTB(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPCMPGTW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPCMPGTD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);

View file

@ -0,0 +1,110 @@
#include "ibm.h"
#include "x86.h"
#include "x86_flags.h"
#include "386_common.h"
#include "codegen.h"
#include "codegen_accumulate.h"
#include "codegen_ir.h"
#include "codegen_ops.h"
#include "codegen_ops_mmx_loadstore.h"
#include "codegen_ops_helpers.h"
uint32_t ropMOVD_r_d(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = (fetchdat >> 3) & 7;
uop_MMX_ENTER(ir);
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
uop_MOVZX(ir, IREG_MM(dest_reg), IREG_32(src_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr);
uop_MOVZX(ir, IREG_MM(dest_reg), IREG_temp0);
}
return op_pc + 1;
}
uint32_t ropMOVD_d_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg = (fetchdat >> 3) & 7;
uop_MMX_ENTER(ir);
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int dest_reg = fetchdat & 7;
uop_MOVZX(ir, IREG_32(dest_reg), IREG_MM(src_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
CHECK_SEG_LIMITS(block, ir, target_seg, IREG_eaaddr, 3);
uop_MOVZX(ir, IREG_temp0, IREG_MM(src_reg));
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_temp0);
}
return op_pc + 1;
}
uint32_t ropMOVQ_r_q(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = (fetchdat >> 3) & 7;
uop_MMX_ENTER(ir);
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
uop_MOV(ir, IREG_MM(dest_reg), IREG_MM(src_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_MM(dest_reg), ireg_seg_base(target_seg), IREG_eaaddr);
}
return op_pc + 1;
}
uint32_t ropMOVQ_q_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg = (fetchdat >> 3) & 7;
uop_MMX_ENTER(ir);
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int dest_reg = fetchdat & 7;
uop_MOV(ir, IREG_MM(dest_reg), IREG_MM(src_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
CHECK_SEG_LIMITS(block, ir, target_seg, IREG_eaaddr, 7);
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_MM(src_reg));
}
return op_pc + 1;
}

View file

@ -0,0 +1,5 @@
uint32_t ropMOVD_r_d(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropMOVD_d_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropMOVQ_r_q(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropMOVQ_q_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);

108
src/codegen_ops_mmx_logic.c Normal file
View file

@ -0,0 +1,108 @@
#include "ibm.h"
#include "x86.h"
#include "x86_flags.h"
#include "386_common.h"
#include "codegen.h"
#include "codegen_accumulate.h"
#include "codegen_ir.h"
#include "codegen_ops.h"
#include "codegen_ops_mmx_logic.h"
#include "codegen_ops_helpers.h"
uint32_t ropPAND(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = (fetchdat >> 3) & 7;
uop_MMX_ENTER(ir);
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
uop_AND(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr);
uop_AND(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q);
}
return op_pc + 1;
}
uint32_t ropPANDN(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = (fetchdat >> 3) & 7;
uop_MMX_ENTER(ir);
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
uop_ANDN(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr);
uop_ANDN(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q);
}
return op_pc + 1;
}
uint32_t ropPOR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = (fetchdat >> 3) & 7;
uop_MMX_ENTER(ir);
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
uop_OR(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr);
uop_OR(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q);
}
return op_pc + 1;
}
uint32_t ropPXOR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = (fetchdat >> 3) & 7;
uop_MMX_ENTER(ir);
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
uop_XOR(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr);
uop_XOR(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q);
}
return op_pc + 1;
}

View file

@ -0,0 +1,4 @@
uint32_t ropPAND(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPANDN(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPOR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPXOR(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);

View file

@ -0,0 +1,47 @@
#include "ibm.h"
#include "x86.h"
#include "x86_flags.h"
#include "386_common.h"
#include "codegen.h"
#include "codegen_accumulate.h"
#include "codegen_ir.h"
#include "codegen_ops.h"
#include "codegen_ops_mmx_pack.h"
#include "codegen_ops_helpers.h"
#define ropPpack(func) \
uint32_t rop ## func(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc) \
{ \
int dest_reg = (fetchdat >> 3) & 7; \
\
uop_MMX_ENTER(ir); \
codegen_mark_code_present(block, cs+op_pc, 1); \
if ((fetchdat & 0xc0) == 0xc0) \
{ \
int src_reg = fetchdat & 7; \
uop_ ## func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_MM(src_reg)); \
} \
else \
{ \
x86seg *target_seg; \
\
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc); \
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0); \
codegen_check_seg_read(block, ir, target_seg); \
uop_MEM_LOAD_REG(ir, IREG_temp0_Q, ireg_seg_base(target_seg), IREG_eaaddr); \
uop_ ## func(ir, IREG_MM(dest_reg), IREG_MM(dest_reg), IREG_temp0_Q); \
} \
\
return op_pc + 1; \
}
ropPpack(PACKSSWB)
ropPpack(PACKSSDW)
ropPpack(PACKUSWB)
ropPpack(PUNPCKLBW)
ropPpack(PUNPCKLWD)
ropPpack(PUNPCKLDQ)
ropPpack(PUNPCKHBW)
ropPpack(PUNPCKHWD)
ropPpack(PUNPCKHDQ)

View file

@ -0,0 +1,9 @@
uint32_t ropPACKSSWB(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPACKSSDW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPACKUSWB(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPUNPCKLBW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPUNPCKLWD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPUNPCKLDQ(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPUNPCKHBW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPUNPCKHWD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPUNPCKHDQ(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);

View file

@ -0,0 +1,93 @@
#include "ibm.h"
#include "x86.h"
#include "x86_flags.h"
#include "386_common.h"
#include "codegen.h"
#include "codegen_accumulate.h"
#include "codegen_ir.h"
#include "codegen_ops.h"
#include "codegen_ops_mmx_shift.h"
#include "codegen_ops_helpers.h"
uint32_t ropPSxxW_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int reg = fetchdat & 7;
int op = fetchdat & 0x38;
int shift = fastreadb(cs + op_pc + 1);
uop_MMX_ENTER(ir);
codegen_mark_code_present(block, cs+op_pc, 1);
switch (op)
{
case 0x10: /*PSRLW*/
uop_PSRLW_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift);
break;
case 0x20: /*PSRAW*/
uop_PSRAW_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift);
break;
case 0x30: /*PSLLW*/
uop_PSLLW_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift);
break;
default:
return 0;
}
codegen_mark_code_present(block, cs+op_pc+1, 1);
return op_pc + 2;
}
uint32_t ropPSxxD_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int reg = fetchdat & 7;
int op = fetchdat & 0x38;
int shift = fastreadb(cs + op_pc + 1);
uop_MMX_ENTER(ir);
codegen_mark_code_present(block, cs+op_pc, 1);
switch (op)
{
case 0x10: /*PSRLD*/
uop_PSRLD_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift);
break;
case 0x20: /*PSRAD*/
uop_PSRAD_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift);
break;
case 0x30: /*PSLLD*/
uop_PSLLD_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift);
break;
default:
return 0;
}
codegen_mark_code_present(block, cs+op_pc+1, 1);
return op_pc + 2;
}
uint32_t ropPSxxQ_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int reg = fetchdat & 7;
int op = fetchdat & 0x38;
int shift = fastreadb(cs + op_pc + 1);
uop_MMX_ENTER(ir);
codegen_mark_code_present(block, cs+op_pc, 1);
switch (op)
{
case 0x10: /*PSRLQ*/
uop_PSRLQ_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift);
break;
case 0x20: /*PSRAQ*/
uop_PSRAQ_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift);
break;
case 0x30: /*PSLLQ*/
uop_PSLLQ_IMM(ir, IREG_MM(reg), IREG_MM(reg), shift);
break;
default:
return 0;
}
codegen_mark_code_present(block, cs+op_pc+1, 1);
return op_pc + 2;
}

View file

@ -0,0 +1,7 @@
uint32_t ropPSxxW_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPSxxD_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPSxxQ_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPSLLW(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPSLLD(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropPSLLQ(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);

772
src/codegen_ops_mov.c Normal file
View file

@ -0,0 +1,772 @@
#include "ibm.h"
#include "x86.h"
#include "386_common.h"
#include "codegen.h"
#include "codegen_ir.h"
#include "codegen_ops.h"
#include "codegen_ops_helpers.h"
#include "codegen_ops_mov.h"
uint32_t ropMOV_rb_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uint8_t imm = fastreadb(cs + op_pc);
uop_MOV_IMM(ir, IREG_8(opcode & 7), imm);
codegen_mark_code_present(block, cs+op_pc, 1);
return op_pc + 1;
}
uint32_t ropMOV_rw_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uint16_t imm = fastreadw(cs + op_pc);
uop_MOV_IMM(ir, IREG_16(opcode & 7), imm);
codegen_mark_code_present(block, cs+op_pc, 2);
return op_pc + 2;
}
uint32_t ropMOV_rl_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
if (block->flags & CODEBLOCK_NO_IMMEDIATES)
{
LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_32(opcode & 7), cs + op_pc);
}
else
{
fetchdat = fastreadl(cs + op_pc);
uop_MOV_IMM(ir, IREG_32(opcode & 7), fetchdat);
codegen_mark_code_present(block, cs+op_pc, 4);
}
return op_pc + 4;
}
uint32_t ropMOV_b_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg = (fetchdat >> 3) & 7;
// if (block->phys == 0x49a400)
// pclog("ropMOVb_rmarkcode %08x 1\n", cs+op_pc);
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int dest_reg = fetchdat & 7;
uop_MOV(ir, IREG_8(dest_reg), IREG_8(src_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
CHECK_SEG_LIMITS(block, ir, target_seg, IREG_eaaddr, 0);
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_8(src_reg));
}
return op_pc + 1;
}
uint32_t ropMOV_w_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int dest_reg = fetchdat & 7;
uop_MOV(ir, IREG_16(dest_reg), IREG_16(src_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
CHECK_SEG_LIMITS(block, ir, target_seg, IREG_eaaddr, 1);
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_16(src_reg));
}
return op_pc + 1;
}
uint32_t ropMOV_l_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int dest_reg = fetchdat & 7;
uop_MOV(ir, IREG_32(dest_reg), IREG_32(src_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
CHECK_SEG_LIMITS(block, ir, target_seg, IREG_eaaddr, 3);
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, IREG_32(src_reg));
}
return op_pc + 1;
}
uint32_t ropMOV_r_b(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
uop_MOV(ir, IREG_8(dest_reg), IREG_8(src_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_8(dest_reg), ireg_seg_base(target_seg), IREG_eaaddr);
}
return op_pc + 1;
}
uint32_t ropMOV_r_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
uop_MOV(ir, IREG_16(dest_reg), IREG_16(src_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_16(dest_reg), ireg_seg_base(target_seg), IREG_eaaddr);
}
return op_pc + 1;
}
uint32_t ropMOV_r_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
uop_MOV(ir, IREG_32(dest_reg), IREG_32(src_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_32(dest_reg), ireg_seg_base(target_seg), IREG_eaaddr);
}
return op_pc + 1;
}
uint32_t ropMOV_AL_abs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uint32_t addr;
if (op_32 & 0x200)
addr = fastreadl(cs + op_pc);
else
addr = fastreadw(cs + op_pc);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
codegen_check_seg_read(block, ir, op_ea_seg);
uop_MEM_LOAD_ABS(ir, IREG_AL, ireg_seg_base(op_ea_seg), addr);
codegen_mark_code_present(block, cs+op_pc, (op_32 & 0x200) ? 4 : 2);
return op_pc + ((op_32 & 0x200) ? 4 : 2);
}
uint32_t ropMOV_AX_abs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uint32_t addr;
if (op_32 & 0x200)
addr = fastreadl(cs + op_pc);
else
addr = fastreadw(cs + op_pc);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
codegen_check_seg_read(block, ir, op_ea_seg);
uop_MEM_LOAD_ABS(ir, IREG_AX, ireg_seg_base(op_ea_seg), addr);
codegen_mark_code_present(block, cs+op_pc, (op_32 & 0x200) ? 4 : 2);
return op_pc + ((op_32 & 0x200) ? 4 : 2);
}
uint32_t ropMOV_EAX_abs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uint32_t addr = 0;
if (op_32 & 0x200)
{
if (block->flags & CODEBLOCK_NO_IMMEDIATES)
{
LOAD_IMMEDIATE_FROM_RAM_32(block, ir, IREG_eaaddr, cs + op_pc);
}
else
{
addr = fastreadl(cs + op_pc);
codegen_mark_code_present(block, cs+op_pc, 4);
}
}
else
{
addr = fastreadw(cs + op_pc);
codegen_mark_code_present(block, cs+op_pc, 2);
}
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
codegen_check_seg_read(block, ir, op_ea_seg);
if ((block->flags & CODEBLOCK_NO_IMMEDIATES) && (op_32 & 0x200))
uop_MEM_LOAD_REG(ir, IREG_EAX, ireg_seg_base(op_ea_seg), IREG_eaaddr);
else
uop_MEM_LOAD_ABS(ir, IREG_EAX, ireg_seg_base(op_ea_seg), addr);
return op_pc + ((op_32 & 0x200) ? 4 : 2);
}
uint32_t ropMOV_abs_AL(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uint32_t addr;
if (op_32 & 0x200)
addr = fastreadl(cs + op_pc);
else
addr = fastreadw(cs + op_pc);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
codegen_check_seg_write(block, ir, op_ea_seg);
uop_MEM_STORE_ABS(ir, ireg_seg_base(op_ea_seg), addr, IREG_AL);
codegen_mark_code_present(block, cs+op_pc, (op_32 & 0x200) ? 4 : 2);
return op_pc + ((op_32 & 0x200) ? 4 : 2);
}
uint32_t ropMOV_abs_AX(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uint32_t addr;
if (op_32 & 0x200)
addr = fastreadl(cs + op_pc);
else
addr = fastreadw(cs + op_pc);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
codegen_check_seg_write(block, ir, op_ea_seg);
uop_MEM_STORE_ABS(ir, ireg_seg_base(op_ea_seg), addr, IREG_AX);
codegen_mark_code_present(block, cs+op_pc, (op_32 & 0x200) ? 4 : 2);
return op_pc + ((op_32 & 0x200) ? 4 : 2);
}
uint32_t ropMOV_abs_EAX(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uint32_t addr;
if (op_32 & 0x200)
addr = fastreadl(cs + op_pc);
else
addr = fastreadw(cs + op_pc);
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
codegen_check_seg_write(block, ir, op_ea_seg);
uop_MEM_STORE_ABS(ir, ireg_seg_base(op_ea_seg), addr, IREG_EAX);
codegen_mark_code_present(block, cs+op_pc, (op_32 & 0x200) ? 4 : 2);
return op_pc + ((op_32 & 0x200) ? 4 : 2);
}
uint32_t ropMOV_b_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
x86seg *target_seg;
uint8_t imm;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int dest_reg = fetchdat & 7;
imm = fastreadb(cs + op_pc + 1);
uop_MOV_IMM(ir, IREG_8(dest_reg), imm);
}
else
{
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
imm = fastreadb(cs + op_pc + 1);
uop_MEM_STORE_IMM_8(ir, ireg_seg_base(target_seg), IREG_eaaddr, imm);
}
codegen_mark_code_present(block, cs+op_pc+1, 1);
return op_pc + 2;
}
uint32_t ropMOV_w_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
x86seg *target_seg;
uint16_t imm;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int dest_reg = fetchdat & 7;
imm = fastreadw(cs + op_pc + 1);
uop_MOV_IMM(ir, IREG_16(dest_reg), imm);
}
else
{
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
imm = fastreadw(cs + op_pc + 1);
uop_MEM_STORE_IMM_16(ir, ireg_seg_base(target_seg), IREG_eaaddr, imm);
}
codegen_mark_code_present(block, cs+op_pc+1, 2);
return op_pc + 3;
}
uint32_t ropMOV_l_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
x86seg *target_seg;
uint32_t imm;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int dest_reg = fetchdat & 7;
imm = fastreadl(cs + op_pc + 1);
uop_MOV_IMM(ir, IREG_32(dest_reg), imm);
}
else
{
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
imm = fastreadl(cs + op_pc + 1);
uop_MEM_STORE_IMM_32(ir, ireg_seg_base(target_seg), IREG_eaaddr, imm);
}
codegen_mark_code_present(block, cs+op_pc+1, 4);
return op_pc + 5;
}
uint32_t ropMOV_w_seg(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg;
codegen_mark_code_present(block, cs+op_pc, 1);
switch (fetchdat & 0x38)
{
case 0x00: /*ES*/
src_reg = IREG_ES_seg_W;
break;
case 0x08: /*CS*/
src_reg = IREG_CS_seg_W;
break;
case 0x18: /*DS*/
src_reg = IREG_DS_seg_W;
break;
case 0x10: /*SS*/
src_reg = IREG_SS_seg_W;
break;
case 0x20: /*FS*/
src_reg = IREG_FS_seg_W;
break;
case 0x28: /*GS*/
src_reg = IREG_GS_seg_W;
break;
default:
return 0;
}
if ((fetchdat & 0xc0) == 0xc0)
{
int dest_reg = fetchdat & 7;
uop_MOV(ir, IREG_16(dest_reg), src_reg);
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
CHECK_SEG_LIMITS(block, ir, target_seg, IREG_eaaddr, 1);
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, src_reg);
}
return op_pc + 1;
}
uint32_t ropMOV_l_seg(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg;
codegen_mark_code_present(block, cs+op_pc, 1);
switch (fetchdat & 0x38)
{
case 0x00: /*ES*/
src_reg = IREG_ES_seg_W;
break;
case 0x08: /*CS*/
src_reg = IREG_CS_seg_W;
break;
case 0x18: /*DS*/
src_reg = IREG_DS_seg_W;
break;
case 0x10: /*SS*/
src_reg = IREG_SS_seg_W;
break;
case 0x20: /*FS*/
src_reg = IREG_FS_seg_W;
break;
case 0x28: /*GS*/
src_reg = IREG_GS_seg_W;
break;
default:
return 0;
}
if ((fetchdat & 0xc0) == 0xc0)
{
int dest_reg = fetchdat & 7;
uop_MOVZX(ir, IREG_32(dest_reg), src_reg);
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, src_reg);
}
return op_pc + 1;
}
uint32_t ropMOV_seg_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int src_reg;
x86seg *rseg;
codegen_mark_code_present(block, cs+op_pc, 1);
switch (fetchdat & 0x38)
{
case 0x00: /*ES*/
rseg = &cpu_state.seg_es;
break;
case 0x18: /*DS*/
rseg = &cpu_state.seg_ds;
break;
case 0x20: /*FS*/
rseg = &cpu_state.seg_fs;
break;
case 0x28: /*GS*/
rseg = &cpu_state.seg_gs;
break;
default:
return 0;
}
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
if ((fetchdat & 0xc0) == 0xc0)
{
uop_MOV(ir, IREG_temp0_W, IREG_16(fetchdat & 7));
src_reg = IREG_temp0_W;
}
else
{
x86seg *target_seg;
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr);
src_reg = IREG_temp0_W;
}
uop_LOAD_SEG(ir, rseg, src_reg);
return op_pc + 1;
}
uint32_t ropMOVSX_16_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
uop_MOVSX(ir, IREG_16(dest_reg), IREG_8(src_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr);
uop_MOVSX(ir, IREG_16(dest_reg), IREG_temp0_B);
}
return op_pc + 1;
}
uint32_t ropMOVSX_32_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
uop_MOVSX(ir, IREG_32(dest_reg), IREG_8(src_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr);
uop_MOVSX(ir, IREG_32(dest_reg), IREG_temp0_B);
}
return op_pc + 1;
}
uint32_t ropMOVSX_32_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
uop_MOVSX(ir, IREG_32(dest_reg), IREG_16(src_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr);
uop_MOVSX(ir, IREG_32(dest_reg), IREG_temp0_W);
}
return op_pc + 1;
}
uint32_t ropMOVZX_16_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
uop_MOVZX(ir, IREG_16(dest_reg), IREG_8(src_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr);
uop_MOVZX(ir, IREG_16(dest_reg), IREG_temp0_B);
}
return op_pc + 1;
}
uint32_t ropMOVZX_32_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
uop_MOVZX(ir, IREG_32(dest_reg), IREG_8(src_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr);
uop_MOVZX(ir, IREG_32(dest_reg), IREG_temp0_B);
}
return op_pc + 1;
}
uint32_t ropMOVZX_32_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int dest_reg = (fetchdat >> 3) & 7;
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int src_reg = fetchdat & 7;
uop_MOVZX(ir, IREG_32(dest_reg), IREG_16(src_reg));
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_read(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr);
uop_MOVZX(ir, IREG_32(dest_reg), IREG_temp0_W);
}
return op_pc + 1;
}
uint32_t ropXCHG_AX(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int reg2 = IREG_16(opcode & 7);
uop_MOV(ir, IREG_temp0_W, IREG_AX);
uop_MOV(ir, IREG_AX, reg2);
uop_MOV(ir, reg2, IREG_temp0_W);
return op_pc;
}
uint32_t ropXCHG_EAX(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int reg2 = IREG_32(opcode & 7);
uop_MOV(ir, IREG_temp0, IREG_EAX);
uop_MOV(ir, IREG_EAX, reg2);
uop_MOV(ir, reg2, IREG_temp0);
return op_pc;
}
uint32_t ropXCHG_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int reg1 = IREG_8((fetchdat >> 3) & 7);
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int reg2 = IREG_8(fetchdat & 7);
uop_MOV(ir, IREG_temp0_B, reg1);
uop_MOV(ir, reg1, reg2);
uop_MOV(ir, reg2, IREG_temp0_B);
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_B, ireg_seg_base(target_seg), IREG_eaaddr);
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, reg1);
uop_MOV(ir, reg1, IREG_temp0_B);
}
return op_pc + 1;
}
uint32_t ropXCHG_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int reg1 = IREG_16((fetchdat >> 3) & 7);
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int reg2 = IREG_16(fetchdat & 7);
uop_MOV(ir, IREG_temp0_W, reg1);
uop_MOV(ir, reg1, reg2);
uop_MOV(ir, reg2, IREG_temp0_W);
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0_W, ireg_seg_base(target_seg), IREG_eaaddr);
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, reg1);
uop_MOV(ir, reg1, IREG_temp0_W);
}
return op_pc + 1;
}
uint32_t ropXCHG_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
int reg1 = IREG_32((fetchdat >> 3) & 7);
codegen_mark_code_present(block, cs+op_pc, 1);
if ((fetchdat & 0xc0) == 0xc0)
{
int reg2 = IREG_32(fetchdat & 7);
uop_MOV(ir, IREG_temp0, reg1);
uop_MOV(ir, reg1, reg2);
uop_MOV(ir, reg2, IREG_temp0);
}
else
{
x86seg *target_seg;
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
target_seg = codegen_generate_ea(ir, op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32, 0);
codegen_check_seg_write(block, ir, target_seg);
uop_MEM_LOAD_REG(ir, IREG_temp0, ireg_seg_base(target_seg), IREG_eaaddr);
uop_MEM_STORE_REG(ir, ireg_seg_base(target_seg), IREG_eaaddr, reg1);
uop_MOV(ir, reg1, IREG_temp0);
}
return op_pc + 1;
}
uint32_t ropXLAT(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc)
{
uop_MOV_IMM(ir, IREG_oldpc, cpu_state.oldpc);
uop_MOVZX(ir, IREG_eaaddr, IREG_AL);
uop_ADD(ir, IREG_eaaddr, IREG_eaaddr, IREG_EBX);
if (!(op_32 & 0x200))
uop_AND_IMM(ir, IREG_eaaddr, IREG_eaaddr, 0xffff);
uop_MEM_LOAD_REG(ir, IREG_AL, ireg_seg_base(op_ea_seg), IREG_eaaddr);
return op_pc;
}

View file

@ -1,656 +1,43 @@
static uint32_t ropMOV_rb_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
STORE_IMM_REG_B(opcode & 7, fetchdat & 0xff);
return op_pc + 1;
}
static uint32_t ropMOV_rw_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
STORE_IMM_REG_W(opcode & 7, fetchdat & 0xffff);
uint32_t ropMOV_rb_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropMOV_rw_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropMOV_rl_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
return op_pc + 2;
}
static uint32_t ropMOV_rl_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
fetchdat = fastreadl(cs + op_pc);
uint32_t ropMOV_b_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropMOV_w_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropMOV_l_r(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropMOV_r_b(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropMOV_r_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropMOV_r_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
STORE_IMM_REG_L(opcode & 7, fetchdat);
return op_pc + 4;
}
uint32_t ropMOV_AL_abs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropMOV_AX_abs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropMOV_EAX_abs(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropMOV_abs_AL(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropMOV_abs_AX(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropMOV_abs_EAX(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
static uint32_t ropMOV_b_r(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
int host_reg = LOAD_REG_B((fetchdat >> 3) & 7);
if ((fetchdat & 0xc0) == 0xc0)
{
STORE_REG_TARGET_B_RELEASE(host_reg, fetchdat & 7);
}
else
{
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
uint32_t ropMOV_b_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropMOV_w_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropMOV_l_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
CHECK_SEG_WRITE(target_seg);
CHECK_SEG_LIMITS(target_seg, 0);
uint32_t ropMOV_w_seg(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropMOV_l_seg(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropMOV_seg_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
MEM_STORE_ADDR_EA_B(target_seg, host_reg);
RELEASE_REG(host_reg);
}
return op_pc + 1;
}
static uint32_t ropMOV_w_r(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
int host_reg = LOAD_REG_W((fetchdat >> 3) & 7);
if ((fetchdat & 0xc0) == 0xc0)
{
STORE_REG_TARGET_W_RELEASE(host_reg, fetchdat & 7);
}
else
{
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
uint32_t ropMOVSX_16_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropMOVSX_32_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropMOVSX_32_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
CHECK_SEG_WRITE(target_seg);
CHECK_SEG_LIMITS(target_seg, 1);
uint32_t ropMOVZX_16_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropMOVZX_32_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropMOVZX_32_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
MEM_STORE_ADDR_EA_W(target_seg, host_reg);
RELEASE_REG(host_reg);
}
return op_pc + 1;
}
uint32_t ropXCHG_AX(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropXCHG_EAX(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
static uint32_t ropMOV_l_r(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
int host_reg;
host_reg = LOAD_REG_L((fetchdat >> 3) & 7);
if ((fetchdat & 0xc0) == 0xc0)
{
STORE_REG_TARGET_L_RELEASE(host_reg, fetchdat & 7);
}
else
{
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
uint32_t ropXCHG_8(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropXCHG_16(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropXCHG_32(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
CHECK_SEG_WRITE(target_seg);
CHECK_SEG_LIMITS(target_seg, 3);
MEM_STORE_ADDR_EA_L(target_seg, host_reg);
RELEASE_REG(host_reg);
}
return op_pc + 1;
}
static uint32_t ropMOV_r_b(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
if ((fetchdat & 0xc0) == 0xc0)
{
int host_reg = LOAD_REG_B(fetchdat & 7);
STORE_REG_TARGET_B_RELEASE(host_reg, (fetchdat >> 3) & 7);
}
else
{
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
CHECK_SEG_READ(target_seg);
MEM_LOAD_ADDR_EA_B(target_seg);
STORE_REG_TARGET_B_RELEASE(0, (fetchdat >> 3) & 7);
}
return op_pc + 1;
}
static uint32_t ropMOV_r_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
if ((fetchdat & 0xc0) == 0xc0)
{
int host_reg = LOAD_REG_W(fetchdat & 7);
STORE_REG_TARGET_W_RELEASE(host_reg, (fetchdat >> 3) & 7);
}
else
{
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
CHECK_SEG_READ(target_seg);
MEM_LOAD_ADDR_EA_W(target_seg);
STORE_REG_TARGET_W_RELEASE(0, (fetchdat >> 3) & 7);
}
return op_pc + 1;
}
static uint32_t ropMOV_r_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
if ((fetchdat & 0xc0) == 0xc0)
{
int host_reg = LOAD_REG_L(fetchdat & 7);
STORE_REG_TARGET_L_RELEASE(host_reg, (fetchdat >> 3) & 7);
}
else
{
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
CHECK_SEG_READ(target_seg);
MEM_LOAD_ADDR_EA_L(target_seg);
STORE_REG_TARGET_L_RELEASE(0, (fetchdat >> 3) & 7);
}
return op_pc + 1;
}
static uint32_t ropMOV_b_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
if ((fetchdat & 0xc0) == 0xc0)
{
STORE_IMM_REG_B(fetchdat & 7, (fetchdat >> 8) & 0xff);
}
else
{
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
uint32_t imm = fastreadb(cs + op_pc + 1);
int host_reg = LOAD_REG_IMM(imm);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
CHECK_SEG_WRITE(target_seg);
MEM_STORE_ADDR_EA_B(target_seg, host_reg);
RELEASE_REG(host_reg);
}
return op_pc + 2;
}
static uint32_t ropMOV_w_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
if ((fetchdat & 0xc0) == 0xc0)
{
STORE_IMM_REG_W(fetchdat & 7, (fetchdat >> 8) & 0xffff);
}
else
{
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
uint32_t imm = fastreadw(cs + op_pc + 1);
int host_reg = LOAD_REG_IMM(imm);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
CHECK_SEG_WRITE(target_seg);
MEM_STORE_ADDR_EA_W(target_seg, host_reg);
RELEASE_REG(host_reg);
}
return op_pc + 3;
}
static uint32_t ropMOV_l_imm(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
if ((fetchdat & 0xc0) == 0xc0)
{
uint32_t imm = fastreadl(cs + op_pc + 1);
STORE_IMM_REG_L(fetchdat & 7, imm);
}
else
{
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
uint32_t imm = fastreadl(cs + op_pc + 1);
int host_reg = LOAD_REG_IMM(imm);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
CHECK_SEG_WRITE(target_seg);
MEM_STORE_ADDR_EA_L(target_seg, host_reg);
RELEASE_REG(host_reg);
}
return op_pc + 5;
}
static uint32_t ropMOV_AL_a(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
uint32_t addr;
if (op_32 & 0x200)
addr = fastreadl(cs + op_pc);
else
addr = fastreadw(cs + op_pc);
CHECK_SEG_READ(op_ea_seg);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
MEM_LOAD_ADDR_IMM_B(op_ea_seg, addr);
STORE_REG_TARGET_B_RELEASE(0, REG_AL);
return op_pc + ((op_32 & 0x200) ? 4 : 2);
}
static uint32_t ropMOV_AX_a(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
uint32_t addr;
if (op_32 & 0x200)
addr = fastreadl(cs + op_pc);
else
addr = fastreadw(cs + op_pc);
CHECK_SEG_READ(op_ea_seg);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
MEM_LOAD_ADDR_IMM_W(op_ea_seg, addr);
STORE_REG_TARGET_W_RELEASE(0, REG_AX);
return op_pc + ((op_32 & 0x200) ? 4 : 2);
}
static uint32_t ropMOV_EAX_a(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
uint32_t addr;
if (op_32 & 0x200)
addr = fastreadl(cs + op_pc);
else
addr = fastreadw(cs + op_pc);
CHECK_SEG_READ(op_ea_seg);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
MEM_LOAD_ADDR_IMM_L(op_ea_seg, addr);
STORE_REG_TARGET_L_RELEASE(0, REG_EAX);
return op_pc + ((op_32 & 0x200) ? 4 : 2);
}
static uint32_t ropMOV_a_AL(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
uint32_t addr;
int host_reg;
if (op_32 & 0x200)
addr = fastreadl(cs + op_pc);
else
addr = fastreadw(cs + op_pc);
CHECK_SEG_WRITE(op_ea_seg);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
host_reg = LOAD_REG_B(REG_AL);
MEM_STORE_ADDR_IMM_B(op_ea_seg, addr, host_reg);
RELEASE_REG(host_reg);
return op_pc + ((op_32 & 0x200) ? 4 : 2);
}
static uint32_t ropMOV_a_AX(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
uint32_t addr;
int host_reg;
if (op_32 & 0x200)
addr = fastreadl(cs + op_pc);
else
addr = fastreadw(cs + op_pc);
CHECK_SEG_WRITE(op_ea_seg);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
host_reg = LOAD_REG_W(REG_AX);
MEM_STORE_ADDR_IMM_W(op_ea_seg, addr, host_reg);
RELEASE_REG(host_reg);
return op_pc + ((op_32 & 0x200) ? 4 : 2);
}
static uint32_t ropMOV_a_EAX(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
uint32_t addr;
int host_reg;
if (op_32 & 0x200)
addr = fastreadl(cs + op_pc);
else
addr = fastreadw(cs + op_pc);
CHECK_SEG_WRITE(op_ea_seg);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
host_reg = LOAD_REG_L(REG_EAX);
MEM_STORE_ADDR_IMM_L(op_ea_seg, addr, host_reg);
RELEASE_REG(host_reg);
return op_pc + ((op_32 & 0x200) ? 4 : 2);
}
static uint32_t ropLEA_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
int dest_reg = (fetchdat >> 3) & 7;
if ((fetchdat & 0xc0) == 0xc0)
return 0;
FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
STORE_REG_TARGET_W_RELEASE(0, dest_reg);
return op_pc + 1;
}
static uint32_t ropLEA_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
int dest_reg = (fetchdat >> 3) & 7;
if ((fetchdat & 0xc0) == 0xc0)
return 0;
FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
STORE_REG_TARGET_L_RELEASE(0, dest_reg);
return op_pc + 1;
}
static uint32_t ropMOVZX_w_b(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
if ((fetchdat & 0xc0) == 0xc0)
{
int host_reg = LOAD_REG_B(fetchdat & 7);
host_reg = ZERO_EXTEND_W_B(host_reg);
STORE_REG_TARGET_W_RELEASE(host_reg, (fetchdat >> 3) & 7);
}
else
{
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
CHECK_SEG_READ(target_seg);
MEM_LOAD_ADDR_EA_B(target_seg);
ZERO_EXTEND_W_B(0);
STORE_REG_TARGET_W_RELEASE(0, (fetchdat >> 3) & 7);
}
return op_pc + 1;
}
static uint32_t ropMOVZX_l_b(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
if ((fetchdat & 0xc0) == 0xc0)
{
int host_reg = LOAD_REG_B(fetchdat & 7);
host_reg = ZERO_EXTEND_L_B(host_reg);
STORE_REG_TARGET_L_RELEASE(host_reg, (fetchdat >> 3) & 7);
}
else
{
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
CHECK_SEG_READ(target_seg);
MEM_LOAD_ADDR_EA_B(target_seg);
ZERO_EXTEND_L_B(0);
STORE_REG_TARGET_L_RELEASE(0, (fetchdat >> 3) & 7);
}
return op_pc + 1;
}
static uint32_t ropMOVZX_l_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
if ((fetchdat & 0xc0) == 0xc0)
{
int host_reg = LOAD_REG_W(fetchdat & 7);
host_reg = ZERO_EXTEND_L_W(host_reg);
STORE_REG_TARGET_L_RELEASE(host_reg, (fetchdat >> 3) & 7);
}
else
{
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
CHECK_SEG_READ(target_seg);
MEM_LOAD_ADDR_EA_W(target_seg);
ZERO_EXTEND_L_W(0);
STORE_REG_TARGET_L_RELEASE(0, (fetchdat >> 3) & 7);
}
return op_pc + 1;
}
static uint32_t ropMOVSX_w_b(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
if ((fetchdat & 0xc0) == 0xc0)
{
int host_reg = LOAD_REG_B(fetchdat & 7);
host_reg = SIGN_EXTEND_W_B(host_reg);
STORE_REG_TARGET_W_RELEASE(host_reg, (fetchdat >> 3) & 7);
}
else
{
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
CHECK_SEG_READ(target_seg);
MEM_LOAD_ADDR_EA_B(target_seg);
SIGN_EXTEND_W_B(0);
STORE_REG_TARGET_W_RELEASE(0, (fetchdat >> 3) & 7);
}
return op_pc + 1;
}
static uint32_t ropMOVSX_l_b(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
if ((fetchdat & 0xc0) == 0xc0)
{
int host_reg = LOAD_REG_B(fetchdat & 7);
host_reg = SIGN_EXTEND_L_B(host_reg);
STORE_REG_TARGET_L_RELEASE(host_reg, (fetchdat >> 3) & 7);
}
else
{
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
CHECK_SEG_READ(target_seg);
MEM_LOAD_ADDR_EA_B(target_seg);
SIGN_EXTEND_L_B(0);
STORE_REG_TARGET_L_RELEASE(0, (fetchdat >> 3) & 7);
}
return op_pc + 1;
}
static uint32_t ropMOVSX_l_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
if ((fetchdat & 0xc0) == 0xc0)
{
int host_reg = LOAD_REG_W(fetchdat & 7);
host_reg = SIGN_EXTEND_L_W(host_reg);
STORE_REG_TARGET_L_RELEASE(host_reg, (fetchdat >> 3) & 7);
}
else
{
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
CHECK_SEG_READ(target_seg);
MEM_LOAD_ADDR_EA_W(target_seg);
SIGN_EXTEND_L_W(0);
STORE_REG_TARGET_L_RELEASE(0, (fetchdat >> 3) & 7);
}
return op_pc + 1;
}
static uint32_t ropMOV_w_seg(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
int host_reg;
switch (fetchdat & 0x38)
{
case 0x00: /*ES*/
host_reg = LOAD_VAR_WL((uintptr_t)&ES);
break;
case 0x08: /*CS*/
host_reg = LOAD_VAR_WL((uintptr_t)&CS);
break;
case 0x18: /*DS*/
host_reg = LOAD_VAR_WL((uintptr_t)&DS);
break;
case 0x10: /*SS*/
host_reg = LOAD_VAR_WL((uintptr_t)&SS);
break;
case 0x20: /*FS*/
host_reg = LOAD_VAR_WL((uintptr_t)&FS);
break;
case 0x28: /*GS*/
host_reg = LOAD_VAR_WL((uintptr_t)&GS);
break;
default:
return 0;
}
if ((fetchdat & 0xc0) == 0xc0)
{
if (op_32 & 0x100)
STORE_REG_TARGET_L_RELEASE(host_reg, fetchdat & 7);
else
STORE_REG_TARGET_W_RELEASE(host_reg, fetchdat & 7);
}
else
{
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
CHECK_SEG_WRITE(target_seg);
CHECK_SEG_LIMITS(target_seg, 1);
MEM_STORE_ADDR_EA_W(target_seg, host_reg);
RELEASE_REG(host_reg);
}
return op_pc + 1;
}
static uint32_t ropMOV_seg_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
int host_reg;
switch (fetchdat & 0x38)
{
case 0x00: /*ES*/
case 0x18: /*DS*/
case 0x20: /*FS*/
case 0x28: /*GS*/
break;
case 0x10: /*SS*/
default:
return 0;
}
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc);
if ((fetchdat & 0xc0) == 0xc0)
host_reg = LOAD_REG_W(fetchdat & 7);
else
{
x86seg *target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32);
CHECK_SEG_READ(target_seg);
MEM_LOAD_ADDR_EA_W(target_seg);
host_reg = 0;
}
switch (fetchdat & 0x38)
{
case 0x00: /*ES*/
LOAD_SEG(host_reg, &_es);
break;
case 0x18: /*DS*/
LOAD_SEG(host_reg, &_ds);
break;
case 0x20: /*FS*/
LOAD_SEG(host_reg, &_fs);
break;
case 0x28: /*GS*/
LOAD_SEG(host_reg, &_gs);
break;
}
return op_pc + 1;
}
#define ropLseg(seg, rseg) \
static uint32_t ropL ## seg(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
{ \
int dest_reg = (fetchdat >> 3) & 7; \
x86seg *target_seg; \
\
if ((fetchdat & 0xc0) == 0xc0) \
return 0; \
\
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \
SAVE_EA(); \
\
if (op_32 & 0x100) \
{ \
MEM_LOAD_ADDR_EA_L(target_seg); \
STORE_HOST_REG_ADDR((uintptr_t)&codegen_temp, 0); \
LOAD_EA(); \
MEM_LOAD_ADDR_EA_W_OFFSET(target_seg, 4); \
} \
else \
{ \
MEM_LOAD_ADDR_EA_W(target_seg); \
STORE_HOST_REG_ADDR_W((uintptr_t)&codegen_temp, 0); \
LOAD_EA(); \
MEM_LOAD_ADDR_EA_W_OFFSET(target_seg, 2); \
} \
LOAD_SEG(0, &rseg); \
if (op_32 & 0x100) \
{ \
\
int host_reg = LOAD_VAR_L((uintptr_t)&codegen_temp); \
STORE_REG_TARGET_L_RELEASE(host_reg, dest_reg); \
} \
else \
{ \
int host_reg = LOAD_VAR_W((uintptr_t)&codegen_temp); \
STORE_REG_TARGET_W_RELEASE(host_reg, dest_reg); \
} \
\
if (&rseg == &_ss) \
CPU_BLOCK_END(); /*Instruction might change stack size, so end block here*/ \
return op_pc + 1; \
}
ropLseg(DS, _ds)
ropLseg(ES, _es)
ropLseg(FS, _fs)
ropLseg(GS, _gs)
ropLseg(SS, _ss)
uint32_t ropXLAT(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);

1135
src/codegen_ops_shift.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -1,125 +1,16 @@
#define SHIFT(size, size2, res_store, immediate) \
if ((fetchdat & 0xc0) == 0xc0) \
{ \
reg = LOAD_REG_ ## size(fetchdat & 7); \
if (immediate) count = (fetchdat >> 8) & 0x1f; \
} \
else \
{ \
target_seg = FETCH_EA(op_ea_seg, fetchdat, op_ssegs, &op_pc, op_32); \
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.oldpc, op_old_pc); \
SAVE_EA(); \
MEM_CHECK_WRITE_ ## size(target_seg); \
reg = MEM_LOAD_ADDR_EA_ ## size ## _NO_ABRT(target_seg); \
if (immediate) count = fastreadb(cs + op_pc + 1) & 0x1f; \
} \
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op2, count); \
\
res_store((uintptr_t)&cpu_state.flags_op1, reg); \
\
switch (fetchdat & 0x38) \
{ \
case 0x20: case 0x30: /*SHL*/ \
SHL_ ## size ## _IMM(reg, count); \
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SHL ## size2); \
break; \
\
case 0x28: /*SHR*/ \
SHR_ ## size ## _IMM(reg, count); \
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SHR ## size2); \
break; \
\
case 0x38: /*SAR*/ \
SAR_ ## size ## _IMM(reg, count); \
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.flags_op, FLAGS_SAR ## size2); \
break; \
} \
\
res_store((uintptr_t)&cpu_state.flags_res, reg); \
if ((fetchdat & 0xc0) == 0xc0) \
STORE_REG_ ## size ## _RELEASE(reg); \
else \
{ \
LOAD_EA(); \
MEM_STORE_ADDR_EA_ ## size ## _NO_ABRT(target_seg, reg); \
}
uint32_t ropC0(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropC1_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropC1_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
static uint32_t ropC0(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
x86seg *target_seg = NULL;
int count;
int reg;
uint32_t ropD0(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropD1_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropD1_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
if ((fetchdat & 0x38) < 0x20)
return 0;
uint32_t ropD2(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropD3_w(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropD3_l(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
SHIFT(B, 8, STORE_HOST_REG_ADDR_BL, 1);
return op_pc + 2;
}
static uint32_t ropC1_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
x86seg *target_seg = NULL;
int count;
int reg;
if ((fetchdat & 0x38) < 0x20)
return 0;
SHIFT(W, 16, STORE_HOST_REG_ADDR_WL, 1);
return op_pc + 2;
}
static uint32_t ropC1_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
x86seg *target_seg = NULL;
int count;
int reg;
if ((fetchdat & 0x38) < 0x20)
return 0;
SHIFT(L, 32, STORE_HOST_REG_ADDR, 1);
return op_pc + 2;
}
static uint32_t ropD0(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
x86seg *target_seg = NULL;
int count = 1;
int reg;
if ((fetchdat & 0x38) < 0x20)
return 0;
SHIFT(B, 8, STORE_HOST_REG_ADDR_BL, 0);
return op_pc + 1;
}
static uint32_t ropD1_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
x86seg *target_seg = NULL;
int count = 1;
int reg;
if ((fetchdat & 0x38) < 0x20)
return 0;
SHIFT(W, 16, STORE_HOST_REG_ADDR_WL, 0);
return op_pc + 1;
}
static uint32_t ropD1_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
x86seg *target_seg = NULL;
int count = 1;
int reg;
if ((fetchdat & 0x38) < 0x20)
return 0;
SHIFT(L, 32, STORE_HOST_REG_ADDR, 0);
return op_pc + 1;
}
uint32_t ropSHLD_16_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropSHLD_32_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropSHRD_16_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);
uint32_t ropSHRD_32_imm(codeblock_t *block, ir_data_t *ir, uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc);

Some files were not shown because too many files have changed in this diff Show more