Initial submission of the PCem-Experimental source code.

This commit is contained in:
OBattler
2016-06-26 00:34:39 +02:00
parent 09d7c4384f
commit fd2a5bc9f5
610 changed files with 184352 additions and 0 deletions

380
src/386.c Normal file
View File

@@ -0,0 +1,380 @@
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include "ibm.h"
#include "x86.h"
#include "x87.h"
#include "mem.h"
#include "cpu.h"
#include "fdc.h"
#include "timer.h"
#include "386_common.h"
#define CPU_BLOCK_END()
extern int codegen_flags_changed;
x86seg *ea_seg;
extern int nmi_enable;
int inscounts[256];
uint32_t oldpc2;
int trap;
extern int cpl_override;
int has_fpu;
extern int fpucount;
int times;
uint16_t rds;
uint16_t ea_rseg;
int is486;
int cgate32;
uint8_t romext[32768];
uint8_t *ram,*rom;
uint32_t biosmask;
uint32_t rmdat32;
#define rmdat rmdat32
#define fetchdat rmdat32
uint32_t backupregs[16];
extern int oddeven;
int inttype,abrt;
uint32_t oldcs2;
uint32_t oldecx;
uint32_t op32;
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 = ea_seg->base;
ea_rseg = ea_seg->seg;
if (rm == 4)
{
uint8_t sib = rmdat >> 8;
switch (mod)
{
case 0:
eaaddr = cpu_state.regs[sib & 7].l;
cpu_state.pc++;
break;
case 1:
cpu_state.pc++;
eaaddr = ((uint32_t)(int8_t)getbyte()) + cpu_state.regs[sib & 7].l;
// pc++;
break;
case 2:
eaaddr = (fastreadl(cs + cpu_state.pc + 1)) + cpu_state.regs[sib & 7].l;
cpu_state.pc += 5;
break;
}
/*SIB byte present*/
if ((sib & 7) == 5 && !mod)
eaaddr = getlong();
else if ((sib & 6) == 4 && !ssegs)
{
easeg = ss;
ea_rseg = SS;
ea_seg = &_ss;
}
if (((sib >> 3) & 7) != 4)
eaaddr += cpu_state.regs[(sib >> 3) & 7].l << (sib >> 6);
}
else
{
eaaddr = cpu_state.regs[rm].l;
if (mod)
{
if (rm == 5 && !ssegs)
{
easeg = ss;
ea_rseg = SS;
ea_seg = &_ss;
}
if (mod == 1)
{
eaaddr += ((uint32_t)(int8_t)(rmdat >> 8));
cpu_state.pc++;
}
else
{
eaaddr += getlong();
}
}
else if (rm == 5)
{
eaaddr = getlong();
}
}
if (easeg != 0xFFFFFFFF && ((easeg + eaaddr) & 0xFFF) <= 0xFFC)
{
uint32_t addr = easeg + eaaddr;
if ( readlookup2[addr >> 12] != -1)
eal_r = (uint32_t *)(readlookup2[addr >> 12] + addr);
if (writelookup2[addr >> 12] != -1)
eal_w = (uint32_t *)(writelookup2[addr >> 12] + addr);
}
}
static inline void fetch_ea_16_long(uint32_t rmdat)
{
eal_r = eal_w = NULL;
easeg = ea_seg->base;
ea_rseg = ea_seg->seg;
if (!mod && rm == 6)
{
eaaddr = getword();
}
else
{
switch (mod)
{
case 0:
eaaddr = 0;
break;
case 1:
eaaddr = (uint16_t)(int8_t)(rmdat >> 8); cpu_state.pc++;
break;
case 2:
eaaddr = getword();
break;
}
eaaddr += (*mod1add[0][rm]) + (*mod1add[1][rm]);
if (mod1seg[rm] == &ss && !ssegs)
{
easeg = ss;
ea_rseg = SS;
ea_seg = &_ss;
}
eaaddr &= 0xFFFF;
}
if (easeg != 0xFFFFFFFF && ((easeg + eaaddr) & 0xFFF) <= 0xFFC)
{
uint32_t addr = easeg + eaaddr;
if ( readlookup2[addr >> 12] != -1)
eal_r = (uint32_t *)(readlookup2[addr >> 12] + addr);
if (writelookup2[addr >> 12] != -1)
eal_w = (uint32_t *)(writelookup2[addr >> 12] + addr);
}
}
#define fetch_ea_16(rmdat) cpu_state.pc++; mod=(rmdat >> 6) & 3; reg=(rmdat >> 3) & 7; rm = rmdat & 7; if (mod != 3) { fetch_ea_16_long(rmdat); if (abrt) return 0; }
#define fetch_ea_32(rmdat) cpu_state.pc++; mod=(rmdat >> 6) & 3; reg=(rmdat >> 3) & 7; rm = rmdat & 7; if (mod != 3) { fetch_ea_32_long(rmdat); } if (abrt) return 0
#include "x86_flags.h"
#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
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
#define CLOCK_CYCLES(c) cycles -= (c)
#define CLOCK_CYCLES_ALWAYS(c) cycles -= (c)
#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;
uint32_t addr;
int tempi;
int cycdiff;
int oldcyc;
cycles+=cycs;
// output=3;
while (cycles>0)
{
cycdiff=0;
oldcyc=cycles;
timer_start_period(cycles << TIMER_SHIFT);
// pclog("%i %02X\n", ins, ram[8]);
while (cycdiff<100)
{
/* 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;
opcode_realstart:
oldcs=CS;
oldpc=cpu_state.pc;
oldcpl=CPL;
op32=use32;
dontprint=0;
ea_seg = &_ds;
ssegs = 0;
opcodestart:
fetchdat = fastreadl(cs + cpu_state.pc);
if (!abrt)
{
trap = flags & T_FLAG;
opcode = fetchdat & 0xFF;
fetchdat >>= 8;
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]);
}
cpu_state.pc++;
x86_opcodes[(opcode | op32) & 0x3ff](fetchdat);
}
if (!use32) cpu_state.pc &= 0xffff;
if (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 = abrt;
abrt = 0;
x86_doabrt(tempi);
if (abrt)
{
abrt = 0;
CS = oldcs;
cpu_state.pc = oldpc;
pclog("Double fault %i\n", ins);
pmodeint(8, 0);
if (abrt)
{
abrt = 0;
softresetx86();
pclog("Triple fault - reset\n");
}
}
}
cycdiff=oldcyc-cycles;
if (trap)
{
flags_rebuild();
// oldpc=pc;
// oldcs=CS;
if (msw&1)
{
pmodeint(1,0);
}
else
{
writememw(ss,(SP-2)&0xFFFF,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.pc=readmemw(0,addr);
loadcs(readmemw(0,addr+2));
}
}
else if (nmi && nmi_enable)
{
oldpc = cpu_state.pc;
oldcs = CS;
// pclog("NMI\n");
x86_int(2);
nmi_enable = 0;
}
else if ((flags&I_FLAG) && pic_intpending)
{
temp=picinterrupt();
if (temp!=0xFF)
{
// if (temp == 0x54) pclog("Take int 54\n");
// if (output) output=3;
// if (temp == 0xd) pclog("Hardware int %02X %i %04X(%08X):%08X\n",temp,ins, CS,cs,pc);
// if (temp==0x54) output=3;
flags_rebuild();
if (msw&1)
{
pmodeint(temp,0);
}
else
{
writememw(ss,(SP-2)&0xFFFF,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.pc=readmemw(0,addr);
loadcs(readmemw(0,addr+2));
// if (temp==0x76) pclog("INT to %04X:%04X\n",CS,pc);
}
// pclog("Now at %04X(%08X):%08X\n", CS, cs, pc);
}
}
ins++;
insc++;
if (timetolive)
{
timetolive--;
if (!timetolive)
fatal("Life expired\n");
}
}
tsc += cycdiff;
timer_end_period(cycles << TIMER_SHIFT);
}
}

2
src/386.h Normal file
View File

@@ -0,0 +1,2 @@
extern void cpu_386_flags_extract();
extern void cpu_386_flags_rebuild();

288
src/386_common.h Normal file
View File

@@ -0,0 +1,288 @@
extern uint16_t ea_rseg;
#undef readmemb
#undef writememb
#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))&0xFFF)>0xFF8)?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))&0xFFF)>0xFFE) 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))&0xFFF)>0xFFC) 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))&0xFFF)>0xFF8) writememql(s,a,v); else *(uint64_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uint32_t)((s) + (a))) = v
#if 0
#define check_io_perm(port) if (!IOPLp || (eflags&VM_FLAG)) \
{ \
int tempi = checkio(port); \
if (abrt) return 1; \
if (tempi) \
{ \
pclog("No I/O permission on port %04Xh\n", port); \
x86gpf("check_io_perm(): no permission",0); \
return 1; \
} \
}
#define checkio_perm(port) if (!IOPLp || (eflags&VM_FLAG)) \
{ \
tempi = checkio(port); \
if (abrt) break; \
if (tempi) \
{ \
x86gpf("checkio_perm(): no permission",0); \
break; \
} \
}
#endif
#define check_io_perm(port) if (msw&1 && ((CPL > IOPL) || (eflags&VM_FLAG))) \
{ \
int tempi = checkio(port); \
if (abrt) return 1; \
if (tempi) \
{ \
pclog("No I/O permission on port %04Xh\n", port); \
x86gpf("check_io_perm(): no permission",0); \
return 1; \
} \
}
#define checkio_perm(port) if (msw&1 && ((CPL > IOPL) || (eflags&VM_FLAG))) \
{ \
tempi = checkio(port); \
if (abrt) break; \
if (tempi) \
{ \
x86gpf("checkio_perm(): no permission",0); \
break; \
} \
}
#define CHECK_READ(chseg, low, high) \
if ((low < (chseg)->limit_low) || (high > (chseg)->limit_high)) \
{ \
x86gpf("Limit check (READ)", 0); \
return 1; \
} \
if (msw&1 && !(eflags&VM_FLAG) && !((chseg)->access & 0x80)) \
{ \
if ((chseg) == &_ss) \
x86ss(NULL,(chseg)->seg & 0xfffc); \
else \
pclog("Read from seg not present", (chseg)->seg & 0xfffc); \
return 1; \
}
#define CHECK_WRITE(chseg, low, high) \
if ((low < (chseg)->limit_low) || (high > (chseg)->limit_high) || !((chseg)->access & 2)) \
{ \
x86gpf("Limit check (WRITE)", 0); \
return 1; \
} \
if (msw&1 && !(eflags&VM_FLAG) && !((chseg)->access & 0x80)) \
{ \
if ((chseg) == &_ss) \
x86ss(NULL,(chseg)->seg & 0xfffc); \
else \
x86np("Write to seg not present", (chseg)->seg & 0xfffc); \
return 1; \
}
#if 0
#define CHECK_WRITE_REP(chseg, low, high) \
if ((low < (chseg)->limit_low) || (high > (chseg)->limit_high)) \
{ \
x86gpf("Limit check (WRITE_REP)", 0); \
if (1 != 1) break; \
} \
if (msw&1 && !(eflags&VM_FLAG) && !((chseg)->access & 0x80)) \
{ \
if ((chseg) == &_ss) \
x86ss(NULL,(chseg)->seg & 0xfffc); \
else \
x86np("Write (REP) to seg not present", (chseg)->seg & 0xfffc); \
break; \
}
#endif
#define CHECK_WRITE_REP(chseg, low, high) \
if (msw&1 && !(eflags&VM_FLAG) && !((chseg)->access & 0x80)) \
{ \
if ((chseg) == &_ss) \
x86ss(NULL,(chseg)->seg & 0xfffc); \
else \
x86np("Write (REP) to seg not present", (chseg)->seg & 0xfffc); \
break; \
}
#define NOTRM if (!(msw & 1) || (eflags & VM_FLAG))\
{ \
x86_int(6); \
return 1; \
}
static inline uint8_t fastreadb(uint32_t a)
{
uint8_t *t;
if ((a >> 12) == pccache)
return *((uint8_t *)&pccache2[a]);
t = getpccache(a);
if (abrt)
return;
pccache = a >> 12;
pccache2 = t;
return *((uint8_t *)&pccache2[a]);
}
static inline uint16_t fastreadw(uint32_t a)
{
uint8_t *t;
uint16_t val;
if ((a&0xFFF)>0xFFE)
{
val = readmemb(0, a);
val |= (readmemb(0, a + 1) << 8);
return val;
}
if ((a>>12)==pccache) return *((uint16_t *)&pccache2[a]);
t = getpccache(a);
if (abrt)
return;
pccache = a >> 12;
pccache2 = t;
return *((uint16_t *)&pccache2[a]);
}
static inline uint32_t fastreadl(uint32_t a)
{
uint8_t *t;
uint32_t val;
if ((a&0xFFF)<0xFFD)
{
if ((a>>12)!=pccache)
{
t = getpccache(a);
if (abrt)
return 0;
pccache2 = t;
pccache=a>>12;
//return *((uint32_t *)&pccache2[a]);
}
return *((uint32_t *)&pccache2[a]);
}
val =readmemb(0,a);
val |=(readmemb(0,a+1)<<8);
val |=(readmemb(0,a+2)<<16);
val |=(readmemb(0,a+3)<<24);
return val;
}
static inline uint8_t getbyte()
{
cpu_state.pc++;
return fastreadb(cs + (cpu_state.pc - 1));
}
static inline uint16_t getword()
{
cpu_state.pc+=2;
return fastreadw(cs+(cpu_state.pc-2));
}
static inline uint32_t getlong()
{
cpu_state.pc+=4;
return fastreadl(cs+(cpu_state.pc-4));
}
static inline uint64_t getquad()
{
cpu_state.pc+=8;
return fastreadl(cs+(cpu_state.pc-8)) | ((uint64_t)fastreadl(cs+(cpu_state.pc-4)) << 32);
}
static inline uint8_t geteab()
{
if (mod == 3)
return (rm & 4) ? cpu_state.regs[rm & 3].b.h : cpu_state.regs[rm&3].b.l;
if (eal_r)
return *(uint8_t *)eal_r;
return readmemb(easeg, eaaddr);
}
static inline uint16_t geteaw()
{
if (mod == 3)
return cpu_state.regs[rm].w;
// cycles-=3;
if (eal_r)
return *(uint16_t *)eal_r;
return readmemw(easeg, eaaddr);
}
static inline uint32_t geteal()
{
if (mod == 3)
return cpu_state.regs[rm].l;
// cycles-=3;
if (eal_r)
return *eal_r;
return readmeml(easeg, eaaddr);
}
static inline uint64_t geteaq()
{
return readmemq(easeg, eaaddr);
}
static inline uint8_t geteab_mem()
{
if (eal_r) return *(uint8_t *)eal_r;
return readmemb(easeg,eaaddr);
}
static inline uint16_t geteaw_mem()
{
if (eal_r) return *(uint16_t *)eal_r;
return readmemw(easeg,eaaddr);
}
static inline uint32_t geteal_mem()
{
if (eal_r) return *eal_r;
return readmeml(easeg,eaaddr);
}
static inline void seteaq(uint64_t v)
{
writememql(easeg, eaaddr, v);
}
#define seteab(v) if (mod!=3) { if (eal_w) *(uint8_t *)eal_w=v; else writememb386l(easeg,eaaddr,v); } else if (rm&4) cpu_state.regs[rm&3].b.h=v; else cpu_state.regs[rm].b.l=v
#define seteaw(v) if (mod!=3) { if (eal_w) *(uint16_t *)eal_w=v; else writememwl(easeg,eaaddr,v); } else cpu_state.regs[rm].w=v
#define seteal(v) if (mod!=3) { if (eal_w) *eal_w=v; else writememll(easeg,eaaddr,v); } else cpu_state.regs[rm].l=v
#define seteab_mem(v) if (eal_w) *(uint8_t *)eal_w=v; else writememb386l(easeg,eaaddr,v);
#define seteaw_mem(v) if (eal_w) *(uint16_t *)eal_w=v; else writememwl(easeg,eaaddr,v);
#define seteal_mem(v) if (eal_w) *eal_w=v; else writememll(easeg,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);

1544
src/386_dynarec.c Normal file

File diff suppressed because it is too large Load Diff

57
src/386_dynarec_ops.c Normal file
View File

@@ -0,0 +1,57 @@
#include "ibm.h"
#include "cpu.h"
#include "x86.h"
#include "x86_ops.h"
#include "x87.h"
#include "x86_flags.h"
#include "mem.h"
#include "codegen.h"
#define CPU_BLOCK_END() cpu_block_end = 1
#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 = ea_seg->base;
ea_rseg = ea_seg->seg;
if (easeg != 0xFFFFFFFF && ((easeg + eaaddr) & 0xFFF) <= 0xFFC)
{
uint32_t addr = easeg + eaaddr;
if ( readlookup2[addr >> 12] != -1)
eal_r = (uint32_t *)(readlookup2[addr >> 12] + addr);
if (writelookup2[addr >> 12] != -1)
eal_w = (uint32_t *)(writelookup2[addr >> 12] + addr);
}
}
static inline void fetch_ea_16_long(uint32_t rmdat)
{
eal_r = eal_w = NULL;
easeg = ea_seg->base;
ea_rseg = ea_seg->seg;
if (easeg != 0xFFFFFFFF && ((easeg + eaaddr) & 0xFFF) <= 0xFFC)
{
uint32_t addr = easeg + eaaddr;
if ( readlookup2[addr >> 12] != -1)
eal_r = (uint32_t *)(readlookup2[addr >> 12] + addr);
if (writelookup2[addr >> 12] != -1)
eal_w = (uint32_t *)(writelookup2[addr >> 12] + addr);
}
}
#define fetch_ea_16(rmdat) cpu_state.pc++; if (mod != 3) fetch_ea_16_long(rmdat);
#define fetch_ea_32(rmdat) cpu_state.pc++; if (mod != 3) fetch_ea_32_long(rmdat);
#define OP_TABLE(name) dynarec_ops_ ## name
#define CLOCK_CYCLES(c)
#define CLOCK_CYCLES_ALWAYS(c) cycles -= (c)
#include "386_ops.h"

1371
src/386_ops.h Normal file

File diff suppressed because it is too large Load Diff

3509
src/808x.c Normal file

File diff suppressed because it is too large Load Diff

BIN
src/IBMPCAT-1.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 206 KiB

51
src/Makefile.am Normal file
View File

@@ -0,0 +1,51 @@
# Makefile.am for PCem
bin_PROGRAMS = pcem
noinst_SCRIPTS = ../pcem
CLEANFILES = $(noinst_SCRIPTS)
../pcem: pcem
cp pcem ..
amrefresh:
pcem_CFLAGS = $(allegro_CFLAGS)
pcem_LDADD = $(allegro_LIBS) -lopenal -lalut
pcem_SOURCES = 386.c 386_dynarec.c 386_dynarec_ops.c 808x.c acer386sx.c ali1429.c allegro-gui.c \
allegro-gui-configure.c allegro-gui-deviceconfig.c allegro-gui-hdconf.c allegro-joystick.c allegro-keyboard.c allegro-main.c \
allegro-midi.c allegro-mouse.c allegro-video.c amstrad.c cdrom-ioctl-linux.c cdrom-iso.c cdrom-null.c \
codegen.c codegen_ops.c codegen_timing_486.c codegen_timing_686.c codegen_timing_pentium.c codegen_timing_winchip.c compaq.c config.c cpu.c \
dac.c device.c disc.c disc_fdi.c disc_img.c disc_sector.c dma.c fdc.c fdc37c665.c fdd.c fdi2raw.c gameport.c \
headland.c i430lx.c i430fx.c i430vx.c ide.c intel.c intel_flash.c io.c jim.c \
keyboard.c keyboard_amstrad.c keyboard_at.c keyboard_olim24.c keyboard_pcjr.c keyboard_xt.c \
linux-time.c lpt.c mcr.c mem.c model.c mouse.c mouse_ps2.c mouse_serial.c neat.c nmi.c nvr.c \
olivetti_m24.c opti.c pc.c pci.c pic.c piix.c pit.c ppi.c ps1.c rom.c scat.c serial.c sis496.c sound.c \
sound_ad1848.c sound_adlib.c sound_adlibgold.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 thread-pthread.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_ega.c vid_et4000.c vid_et4000w32.c vid_hercules.c \
vid_icd2061.c vid_ics2595.c vid_incolor.c vid_mda.c vid_olivetti_m24.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_stg_ramdac.c vid_svga.c vid_svga_render.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 \
x86seg.c x87.c xtide.c sound_dbopl.cc sound_resid.cc dosbox/dbopl.cpp \
resid-fp/convolve.cc resid-fp/convolve-sse.cc resid-fp/envelope.cc \
resid-fp/extfilt.cc resid-fp/filter.cc resid-fp/pot.cc resid-fp/sid.cc \
resid-fp/voice.cc resid-fp/wave6581_PS_.cc resid-fp/wave6581_PST.cc \
resid-fp/wave6581_P_T.cc resid-fp/wave6581__ST.cc resid-fp/wave8580_PS_.cc \
resid-fp/wave8580_PST.cc resid-fp/wave8580_P_T.cc resid-fp/wave8580__ST.cc \
resid-fp/wave.cc
if CPU_I386
pcem_SOURCES += codegen_x86.c
pcem_CFLAGS += -msse2
endif
if CPU_X86_64
pcem_SOURCES += codegen_x86-64.c
endif

2956
src/Makefile.in Normal file

File diff suppressed because it is too large Load Diff

51
src/Makefile.mingw Normal file
View File

@@ -0,0 +1,51 @@
VPATH = . dosbox resid-fp slirp
CPP = g++.exe
CC = gcc.exe
WINDRES = windres.exe
KFLAGS = -O2 -flto -ffast-math -msse -msse2 -mfpmath=387 -mstackrealign
CFLAGS = -O3 -march=native -mtune=native -flto -fbranch-probabilities -fvpt -funroll-loops -fpeel-loops -ftracer -fomit-frame-pointer -ffast-math -msse -msse2 -msse3 -mssse3 -mfpmath=sse -mstackrealign
BFLAGS = -DRELEASE_BUILD
OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acer386sx.o acerm3a.o ali1429.o amstrad.o cdrom-ioctl.o cdrom-iso.o \
cdrom-null.o codegen.o codegen_ops.o codegen_timing_486.o codegen_timing_686.o codegen_timing_pentium.o codegen_timing_winchip.o codegen_x86.o compaq.o config.o cpu.o dac.o \
device.o disc.o disc_fdi.o disc_img.o disc_sector.o dma.o fdc.o fdc37c665.o fdc37c932fr.o fdd.o fdi2raw.o gameport.o headland.o i430hx.o i430lx.o i430fx.o \
i430nx.o i430vx.o i440fx.o ide.o intel.o intel_flash.o io.o jim.o joystick_standard.o joystick_sw_pad.o keyboard.o keyboard_amstrad.o keyboard_at.o \
keyboard_olim24.o keyboard_pcjr.o keyboard_xt.o lpt.o mcr.o mem.o memregs.o model.o mouse.o mouse_ps2.o \
mouse_serial.o ne2000.o neat.o nethandler.o nmi.o nvr.o olivetti_m24.o opti.o pc.o pc87306.o pci.o pic.o piix.o pit.o ppi.o ps1.o rom.o \
scat.o serial.o sis496.o sis85c471.o sio.o sound.o sound_ad1848.o sound_adlib.o sound_adlibgold.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 tandy_eeprom.o tandy_rom.o timer.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_cga_comp.o vid_cl5429.o vid_ega.o vid_et4000.o \
vid_et4000w32.o vid_hercules.o vid_icd2061.o vid_ics2595.o vid_incolor.o vid_mda.o \
vid_olivetti_m24.o 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_stg_ramdac.o vid_svga.o \
vid_svga_render.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 video.o w83877f.o wd76c10.o win.o win-config.o win-d3d.o win-d3d-fs.o win-ddraw.o \
win-ddraw-fs.o win-ddraw-screenshot.o win-deviceconfig.o win-hdconf.o win-joystick.o win-joystickconfig.o win-keyboard.o win-midi.o win-mouse.o \
win-status.o win-time.o win-video.o x86seg.o x87.o xtide.o pc.res
FMOBJ = dbopl.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
SLIRPOBJ = bootp.o ip_icmp.o misc.o socket.o tcp_timer.o cksum.o ip_input.o queue.o tcp_input.o tftp.o debug.o ip_output.o sbuf.o tcp_output.o udp.o if.o mbuf.o slirp.o tcp_subr.o
LIBS = -mwindows -lwinmm -lopenal.dll -lopenal -lddraw -ldinput8 -ldxguid -ld3d9 -ld3dx9 -lwsock32 -liphlpapi -lstdc++ -static-libstdc++ -static-libgcc -static
PCem.exe: $(OBJ) $(FMOBJ) $(SIDOBJ) $(SLIRPOBJ)
$(CC) $(OBJ) $(FMOBJ) $(SIDOBJ) $(SLIRPOBJ) -o "PCem.exe" $(LIBS)
strip "PCem.exe"
all : PCem.exe
clean :
rm *.o
rm *.exe
rm *.res
%.o : %.c
$(CC) $(CFLAGS) -c $<
%.o : %.cc
$(CPP) $(CFLAGS) -c $<
pc.res: pc.rc
$(WINDRES) -i pc.rc --input-format=rc -o pc.res -O coff

49
src/Makefile.mingw64 Normal file
View File

@@ -0,0 +1,49 @@
VPATH = . dosbox resid-fp slirp
CPP = g++.exe
CC = gcc.exe
WINDRES = windres.exe
CFLAGS = -O3 -march=native -mtune=native -fbranch-probabilities -fvpt -funroll-loops -fpeel-loops -ftracer -fomit-frame-pointer -ffast-math -msse -msse2 -msse3 -mssse3 -mfpmath=sse -mstackrealign
OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acer386sx.o acerm3a.o ali1429.o amstrad.o cdrom-ioctl.o cdrom-iso.o \
cdrom-null.o codegen.o codegen_ops.o codegen_timing_486.o codegen_timing_686.o codegen_timing_pentium.o codegen_timing_winchip.o codegen_x86-64.o compaq.o config.o cpu.o dac.o \
device.o disc.o disc_fdi.o disc_img.o disc_sector.o dma.o fdc.o fdc37c665.o fdc37c932fr.o fdd.o fdi2raw.o gameport.o headland.o i430hx.o i430lx.o i430fx.o \
i430nx.o i430vx.o i440fx.o ide.o intel.o intel_flash.o io.o jim.o joystick_standard.o joystick_sw_pad.o keyboard.o keyboard_amstrad.o keyboard_at.o \
keyboard_olim24.o keyboard_pcjr.o keyboard_xt.o lpt.o mcr.o mem.o memregs.o model.o mouse.o mouse_ps2.o \
mouse_serial.o ne2000.o neat.o nethandler.o nmi.o nvr.o olivetti_m24.o opti.o pc.o pc87306.o pci.o pic.o piix.o pit.o ppi.o ps1.o rom.o \
scat.o serial.o sis496.o sis85c471.o sio.o sound.o sound_ad1848.o sound_adlib.o sound_adlibgold.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 tandy_eeprom.o tandy_rom.o timer.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_cga_comp.o vid_cl5429.o vid_ega.o vid_et4000.o \
vid_et4000w32.o vid_hercules.o vid_icd2061.o vid_ics2595.o vid_incolor.o vid_mda.o \
vid_olivetti_m24.o 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_stg_ramdac.o vid_svga.o \
vid_svga_render.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 video.o w83877f.o wd76c10.o win.o win-config.o win-d3d.o win-d3d-fs.o win-ddraw.o \
win-ddraw-fs.o win-ddraw-screenshot.o win-deviceconfig.o win-hdconf.o win-joystick.o win-joystickconfig.o win-keyboard.o win-midi.o win-mouse.o \
win-status.o win-time.o win-video.o x86seg.o x87.o xtide.o pc.res
FMOBJ = dbopl.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
SLIRPOBJ = bootp.o ip_icmp.o misc.o socket.o tcp_timer.o cksum.o ip_input.o queue.o tcp_input.o tftp.o debug.o ip_output.o sbuf.o tcp_output.o udp.o if.o mbuf.o slirp.o tcp_subr.o
LIBS = -mwindows -lwinmm -lopenal -lddraw -ldinput8 -ldxguid -ld3d9 -ld3dx9 -lwsock32 -liphlpapi -lstdc++ -static-libstdc++ -static-libgcc -static -lopenal.dll -flto -lgcov -lPacket -lwpcap
PCem64.exe: $(OBJ) $(FMOBJ) $(SIDOBJ) $(SLIRPOBJ)
$(CC) $(OBJ) $(FMOBJ) $(SIDOBJ) $(SLIRPOBJ) -o "PCem64.exe" $(LIBS)
strip "PCem64.exe"
all : PCem64.exe
clean :
rm *.o
rm *.exe
rm *.res
%.o : %.c
$(CC) $(CFLAGS) -c $<
%.o : %.cc
$(CPP) $(CFLAGS) -c $<
pc.res: pc.rc
$(WINDRES) -i pc.rc --input-format=rc -o pc.res -O coff

50
src/Makefile_AMD.mingw Normal file
View File

@@ -0,0 +1,50 @@
VPATH = . dosbox resid-fp slirp
CPP = g++.exe
CC = gcc.exe
WINDRES = windres.exe
CFLAGS = -O3 -march=amdfam10 -mtune=amdfam10 -flto -fbranch-probabilities -fvpt -funroll-loops -fpeel-loops -ftracer -fomit-frame-pointer -ffast-math -msse -msse2 -msse3 -mfpmath=sse -mstackrealign
BFLAGS = -DRELEASE_BUILD
OBJ = 386.o 386_dynarec.o 386_dynarec_ops.o 808x.o acer386sx.o acerm3a.o ali1429.o amstrad.o cdrom-ioctl.o cdrom-iso.o \
cdrom-null.o codegen.o codegen_ops.o codegen_timing_486.o codegen_timing_686.o codegen_timing_pentium.o codegen_timing_winchip.o codegen_x86.o compaq.o config.o cpu.o dac.o \
device.o disc.o disc_fdi.o disc_img.o disc_sector.o dma.o fdc.o fdc37c665.o fdc37c932fr.o fdd.o fdi2raw.o gameport.o headland.o i430hx.o i430lx.o i430fx.o \
i430nx.o i430vx.o i440fx.o ide.o intel.o intel_flash.o io.o jim.o joystick_standard.o joystick_sw_pad.o keyboard.o keyboard_amstrad.o keyboard_at.o \
keyboard_olim24.o keyboard_pcjr.o keyboard_xt.o lpt.o mcr.o mem.o memregs.o model.o mouse.o mouse_ps2.o \
mouse_serial.o ne2000.o neat.o nethandler.o nmi.o nvr.o olivetti_m24.o opti.o pc.o pc87306.o pci.o pic.o piix.o pit.o ppi.o ps1.o rom.o \
scat.o serial.o sis496.o sis85c471.o sio.o sound.o sound_ad1848.o sound_adlib.o sound_adlibgold.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 tandy_eeprom.o tandy_rom.o timer.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_cga_comp.o vid_cl5429.o vid_ega.o vid_et4000.o \
vid_et4000w32.o vid_hercules.o vid_icd2061.o vid_ics2595.o vid_incolor.o vid_mda.o \
vid_olivetti_m24.o 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_stg_ramdac.o vid_svga.o \
vid_svga_render.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 video.o w83877f.o wd76c10.o win.o win-config.o win-d3d.o win-d3d-fs.o win-ddraw.o \
win-ddraw-fs.o win-ddraw-screenshot.o win-deviceconfig.o win-hdconf.o win-joystick.o win-joystickconfig.o win-keyboard.o win-midi.o win-mouse.o \
win-status.o win-time.o win-video.o x86seg.o x87.o xtide.o pc.res
FMOBJ = dbopl.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
SLIRPOBJ = bootp.o ip_icmp.o misc.o socket.o tcp_timer.o cksum.o ip_input.o queue.o tcp_input.o tftp.o debug.o ip_output.o sbuf.o tcp_output.o udp.o if.o mbuf.o slirp.o tcp_subr.o
LIBS = -mwindows -lwinmm -lopenal.dll -lopenal -lddraw -ldinput8 -ldxguid -ld3d9 -ld3dx9 -lwsock32 -liphlpapi -lstdc++ -static-libstdc++ -static-libgcc -static
PCem.exe: $(OBJ) $(FMOBJ) $(SIDOBJ) $(SLIRPOBJ)
$(CC) $(OBJ) $(FMOBJ) $(SIDOBJ) $(SLIRPOBJ) -o "PCem.exe" $(LIBS)
strip "PCem.exe"
all : PCem.exe
clean :
rm *.o
rm *.exe
rm *.res
%.o : %.c
$(CC) $(CFLAGS) -c $<
%.o : %.cc
$(CPP) $(CFLAGS) -c $<
pc.res: pc.rc
$(WINDRES) -i pc.rc --input-format=rc -o pc.res -O coff

22
src/PCem.manifest Normal file
View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity
version="1.0.0.0"
processorArchitecture="*"
name="PCem-X64.exe"
type="win32"
/>
<description>Your application description here.</description>
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
processorArchitecture="*"
publicKeyToken="6595b64144ccf1df"
language="*"
/>
</dependentAssembly>
</dependency>
</assembly>

33
src/acer386sx.c Normal file
View File

@@ -0,0 +1,33 @@
#include "ibm.h"
#include "io.h"
#include "cpu.h"
#include "acer386sx.h"
static int acer_index = 0;
static uint8_t acer_regs[256];
void acer386sx_write(uint16_t addr, uint8_t val, void *priv)
{
if (addr & 1)
acer_regs[acer_index] = val;
else
acer_index = val;
}
uint8_t acer386sx_read(uint16_t addr, void *priv)
{
if (addr & 1)
{
if ((acer_index >= 0xc0 || acer_index == 0x20) && cpu_iscyrix)
return 0xff; /*Don't conflict with Cyrix config registers*/
return acer_regs[acer_index];
}
else
return acer_index;
}
void acer386sx_init()
{
io_sethandler(0x0022, 0x0002, acer386sx_read, NULL, NULL, acer386sx_write, NULL, NULL, NULL);
}

1
src/acer386sx.h Normal file
View File

@@ -0,0 +1 @@
void acer386sx_init();

29
src/acerm3a.c Normal file
View File

@@ -0,0 +1,29 @@
#include "ibm.h"
#include "io.h"
#include "acerm3a.h"
static int acerm3a_index;
static void acerm3a_out(uint16_t port, uint8_t val, void *p)
{
if (port == 0xea)
acerm3a_index = val;
}
static uint8_t acerm3a_in(uint16_t port, void *p)
{
if (port == 0xeb)
{
switch (acerm3a_index)
{
case 2:
return 0xfd;
}
}
return 0xff;
}
void acerm3a_io_init()
{
io_sethandler(0x00ea, 0x0002, acerm3a_in, NULL, NULL, acerm3a_out, NULL, NULL, NULL);
}

1
src/acerm3a.h Normal file
View File

@@ -0,0 +1 @@
void acerm3a_io_init();

86
src/ali1429.c Normal file
View File

@@ -0,0 +1,86 @@
#include <string.h>
#include "ibm.h"
#include "io.h"
#include "mem.h"
#include "cpu.h"
#include "ali1429.h"
static int ali1429_index;
static uint8_t ali1429_regs[256];
static void ali1429_recalc()
{
int c;
for (c = 0; c < 8; c++)
{
uint32_t base = 0xc0000 + (c << 15);
if (ali1429_regs[0x13] & (1 << c))
{
switch (ali1429_regs[0x14] & 3)
{
case 0:
mem_set_mem_state(base, 0x8000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
break;
case 1:
mem_set_mem_state(base, 0x8000, MEM_READ_INTERNAL | MEM_WRITE_EXTERNAL);
break;
case 2:
mem_set_mem_state(base, 0x8000, MEM_READ_EXTERNAL | MEM_WRITE_INTERNAL);
break;
case 3:
mem_set_mem_state(base, 0x8000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
break;
}
}
else
mem_set_mem_state(base, 0x8000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
}
flushmmucache();
}
void ali1429_write(uint16_t port, uint8_t val, void *priv)
{
int c;
if (!(port & 1))
ali1429_index = val;
else
{
ali1429_regs[ali1429_index] = val;
// pclog("ALI1429 write %02X %02X %04X:%04X %i\n",ali1429_index,val,CS,pc,ins);
switch (ali1429_index)
{
case 0x13:
ali1429_recalc();
break;
case 0x14:
shadowbios = val & 1;
shadowbios_write = val & 2;
ali1429_recalc();
break;
}
}
}
uint8_t ali1429_read(uint16_t port, void *priv)
{
if (!(port & 1))
return ali1429_index;
if ((ali1429_index >= 0xc0 || ali1429_index == 0x20) && cpu_iscyrix)
return 0xff; /*Don't conflict with Cyrix config registers*/
return ali1429_regs[ali1429_index];
}
void ali1429_reset()
{
memset(ali1429_regs, 0xff, 256);
}
void ali1429_init()
{
io_sethandler(0x0022, 0x0002, ali1429_read, NULL, NULL, ali1429_write, NULL, NULL, NULL);
}

1
src/ali1429.h Normal file
View File

@@ -0,0 +1 @@
void ali1429_init();

636
src/allegro-gui-configure.c Normal file
View File

@@ -0,0 +1,636 @@
#include "ibm.h"
#include "device.h"
#include "allegro-main.h"
#include "allegro-gui.h"
#include "cpu.h"
#include "fdd.h"
#include "gameport.h"
#include "model.h"
#include "sound.h"
#include "video.h"
#include "vid_voodoo.h"
static int romstolist[ROM_MAX], listtomodel[ROM_MAX], romstomodel[ROM_MAX], modeltolist[ROM_MAX];
static int settings_sound_to_list[20], settings_list_to_sound[20];
typedef struct allegro_list_t
{
char name[256];
int num;
} allegro_list_t;
static allegro_list_t model_list[ROM_MAX+1];
static allegro_list_t video_list[GFX_MAX+1];
static allegro_list_t sound_list[GFX_MAX+1];
static allegro_list_t cpumanu_list[4];
static allegro_list_t cpu_list[32];
static allegro_list_t joystick_list[32];
static char mem_size_str[10], mem_size_units[3];
static allegro_list_t cache_list[] =
{
{"A little", 0},
{"A bit", 1},
{"Some", 2},
{"A lot", 3},
{"Infinite", 4},
{"", -1}
};
static allegro_list_t vidspeed_list[] =
{
{"8-bit", 0},
{"Slow 16-bit", 1},
{"Fast 16-bit", 2},
{"Slow VLB/PCI", 3},
{"Mid VLB/PCI", 4},
{"Fast VLB/PCI", 5},
{"", -1}
};
static allegro_list_t fdd_list[] =
{
{"None", 0},
{"5.25\" 360k", 1},
{"5.25\" 1.2M", 2},
{"5.25\" 1.2M Dual RPM", 3},
{"3.5\" 720k", 4},
{"3.5\" 1.44M", 5},
{"3.5\" 1.44M 3-Mode", 6},
{"3.5\" 2.88M", 7},
{"", -1}
};
static void reset_list();
static char *list_proc_model(int index, int *list_size)
{
if (index < 0)
{
int c = 0;
while (model_list[c].name[0])
c++;
*list_size = c;
return NULL;
}
return model_list[index].name;
}
static char *list_proc_video(int index, int *list_size)
{
if (index < 0)
{
int c = 0;
while (video_list[c].name[0])
c++;
*list_size = c;
return NULL;
}
return video_list[index].name;
}
static char *list_proc_cache(int index, int *list_size)
{
if (index < 0)
{
int c = 0;
while (cache_list[c].name[0])
c++;
*list_size = c;
return NULL;
}
return cache_list[index].name;
}
static char *list_proc_vidspeed(int index, int *list_size)
{
if (index < 0)
{
int c = 0;
while (vidspeed_list[c].name[0])
c++;
*list_size = c;
return NULL;
}
return vidspeed_list[index].name;
}
static char *list_proc_sound(int index, int *list_size)
{
if (index < 0)
{
int c = 0;
while (sound_list[c].name[0])
c++;
*list_size = c;
return NULL;
}
return sound_list[index].name;
}
static char *list_proc_cpumanu(int index, int *list_size)
{
if (index < 0)
{
int c = 0;
while (cpumanu_list[c].name[0])
c++;
*list_size = c;
return NULL;
}
return cpumanu_list[index].name;
}
static char *list_proc_cpu(int index, int *list_size)
{
if (index < 0)
{
int c = 0;
while (cpu_list[c].name[0])
c++;
*list_size = c;
return NULL;
}
return cpu_list[index].name;
}
static char *list_proc_fdd(int index, int *list_size)
{
if (index < 0)
{
int c = 0;
while (fdd_list[c].name[0])
c++;
*list_size = c;
return NULL;
}
return fdd_list[index].name;
}
static char *list_proc_joystick(int index, int *list_size)
{
if (index < 0)
{
int c = 0;
while (joystick_list[c].name[0])
c++;
*list_size = c;
return NULL;
}
return joystick_list[index].name;
}
static int voodoo_config_proc(int msg, DIALOG *d, int c)
{
int ret = d_button_proc(msg, d, c);
if (ret == D_CLOSE)
{
deviceconfig_open(&voodoo_device);
return D_O_K;
}
return ret;
}
static int video_config_proc(int msg, DIALOG *d, int c);
static int sound_config_proc(int msg, DIALOG *d, int c);
static int list_proc(int msg, DIALOG *d, int c);
static DIALOG configure_dialog[] =
{
{d_shadow_box_proc, 0, 0, 568,352,0,0xffffff,0,0, 0,0,0,0,0}, // 0
{d_button_proc, 226, 328, 50, 16, 0, 0xffffff, 0, D_EXIT, 0, 0, "OK", 0, 0}, // 1
{d_button_proc, 296, 328, 50, 16, 0, 0xffffff, 0, D_EXIT, 0, 0, "Cancel", 0, 0}, // 2
{list_proc, 70*2, 12, 152*2, 20, 0, 0xffffff, 0, 0, 0, 0, list_proc_model, 0, 0},
{list_proc, 70*2, 32, 152*2, 20, 0, 0xffffff, 0, 0, 0, 0, list_proc_video, 0, 0},
{list_proc, 70*2, 52, 152*2, 20, 0, 0xffffff, 0, 0, 0, 0, list_proc_cpumanu, 0, 0}, //5
{list_proc, 70*2, 72, 152*2, 20, 0, 0xffffff, 0, 0, 0, 0, list_proc_cpu, 0, 0},
{d_list_proc, 70*2, 112, 152*2, 20, 0, 0xffffff, 0, 0, 0, 0, list_proc_cache, 0, 0},
{d_list_proc, 70*2, 132, 152*2, 20, 0, 0xffffff, 0, 0, 0, 0, list_proc_vidspeed, 0, 0},
{list_proc, 70*2, 152, 152*2, 20, 0, 0xffffff, 0, 0, 0, 0, list_proc_sound, 0, 0}, //9
{d_edit_proc, 70*2, 236, 32, 14, 0, 0xffffff, 0, 0, 3, 0, mem_size_str, 0, 0},
{d_text_proc, 98*2, 236, 40, 10, 0, 0xffffff, 0, 0, 0, 0, mem_size_units, 0, 0},
{d_check_proc, 14*2, 252, 118*2, 10, 0, 0xffffff, 0, 0, 0, 0, "CMS / Game Blaster", 0, 0},
{d_check_proc, 14*2, 268, 118*2, 10, 0, 0xffffff, 0, 0, 0, 0, "Gravis Ultrasound", 0, 0},
{d_check_proc, 14*2, 284, 118*2, 10, 0, 0xffffff, 0, 0, 0, 0, "Innovation SSI-2001", 0, 0},
{d_check_proc, 14*2, 300, 118*2, 10, 0, 0xffffff, 0, 0, 0, 0, "Composite CGA", 0, 0},
{d_check_proc, 14*2, 316, 118*2, 10, 0, 0xffffff, 0, 0, 0, 0, "Voodoo Graphics", 0, 0},
{d_text_proc, 16*2, 16, 40, 10, 0, 0xffffff, 0, 0, 0, 0, "Machine :", 0, 0},
{d_text_proc, 16*2, 36, 40, 10, 0, 0xffffff, 0, 0, 0, 0, "Video :", 0, 0},
{d_text_proc, 16*2, 56, 40, 10, 0, 0xffffff, 0, 0, 0, 0, "CPU type :", 0, 0},
{d_text_proc, 16*2, 76, 40, 10, 0, 0xffffff, 0, 0, 0, 0, "CPU :", 0, 0},
{d_text_proc, 16*2, 116, 40, 10, 0, 0xffffff, 0, 0, 0, 0, "Cache :", 0, 0},
{d_text_proc, 16*2, 136, 40, 10, 0, 0xffffff, 0, 0, 0, 0, "Video speed :", 0, 0},
{d_text_proc, 16*2, 156, 40, 10, 0, 0xffffff, 0, 0, 0, 0, "Soundcard :", 0, 0},
{d_text_proc, 16*2, 236, 40, 10, 0, 0xffffff, 0, 0, 0, 0, "Memory :", 0, 0},
{d_check_proc, 14*2, 92, 118*2, 10, 0, 0xffffff, 0, 0, 0, 0, "Dynamic Recompiler", 0, 0},
{d_text_proc, 16*2, 176, 40, 10, 0, 0xffffff, 0, 0, 0, 0, "Drive A: :", 0, 0},
{d_text_proc, 16*2, 196, 40, 10, 0, 0xffffff, 0, 0, 0, 0, "Drive B: :", 0, 0},
{d_list_proc, 70*2, 172, 152*2, 20, 0, 0xffffff, 0, 0, 0, 0, list_proc_fdd, 0, 0},
{d_list_proc, 70*2, 192, 152*2, 20, 0, 0xffffff, 0, 0, 0, 0, list_proc_fdd, 0, 0},
{video_config_proc, 452, 32+4, 100, 14, 0, 0xffffff, 0, D_EXIT, 0, 0, "Configure...", 0, 0}, //30
{sound_config_proc, 452, 152+4, 100, 14, 0, 0xffffff, 0, D_EXIT, 0, 0, "Configure...", 0, 0},
{voodoo_config_proc, 452, 316, 100, 14, 0, 0xffffff, 0, D_EXIT, 0, 0, "Configure...", 0, 0},
{d_text_proc, 16*2, 216, 40, 10, 0, 0xffffff, 0, 0, 0, 0, "Joystick :", 0, 0},
{d_list_proc, 70*2, 212, 152*2, 20, 0, 0xffffff, 0, 0, 0, 0, list_proc_joystick, 0, 0}, //34
{0,0,0,0,0,0,0,0,0,0,0,NULL,NULL,NULL}
};
static int list_proc(int msg, DIALOG *d, int c)
{
int old = d->d1;
int ret = d_list_proc(msg, d, c);
if (d->d1 != old)
{
int new_model = model_list[configure_dialog[3].d1].num;
int new_cpu_m = configure_dialog[5].d1;
int new_cpu = configure_dialog[6].d1;
int new_dynarec = configure_dialog[25].flags & D_SELECTED;
int new_gfxcard = video_old_to_new(video_list[configure_dialog[4].d1].num);
int new_mem_size;
int cpu_flags;
reset_list();
if (models[new_model].fixed_gfxcard)
configure_dialog[4].flags |= D_DISABLED;
else
configure_dialog[4].flags &= ~D_DISABLED;
cpu_flags = models[new_model].cpu[new_cpu_m].cpus[new_cpu].cpu_flags;
configure_dialog[25].flags = (((cpu_flags & CPU_SUPPORTS_DYNAREC) && new_dynarec) || (cpu_flags & CPU_REQUIRES_DYNAREC)) ? D_SELECTED : 0;
if (!(cpu_flags & CPU_SUPPORTS_DYNAREC) || (cpu_flags & CPU_REQUIRES_DYNAREC))
configure_dialog[25].flags |= D_DISABLED;
sscanf(mem_size_str, "%i", &new_mem_size);
new_mem_size &= ~(models[new_model].ram_granularity - 1);
if (new_mem_size < models[new_model].min_ram)
new_mem_size = models[new_model].min_ram;
else if (new_mem_size > models[new_model].max_ram)
new_mem_size = models[new_model].max_ram;
sprintf(mem_size_str, "%i", new_mem_size);
if (models[new_model].is_at)
sprintf(mem_size_units, "MB");
else
sprintf(mem_size_units, "kB");
if (!video_card_has_config(new_gfxcard))
configure_dialog[30].flags |= D_DISABLED;
else
configure_dialog[30].flags &= ~D_DISABLED;
if (!sound_card_has_config(configure_dialog[9].d1))
configure_dialog[31].flags |= D_DISABLED;
else
configure_dialog[31].flags &= ~D_DISABLED;
return D_REDRAW;
}
return ret;
}
static int video_config_proc(int msg, DIALOG *d, int c)
{
int ret = d_button_proc(msg, d, c);
if (ret == D_CLOSE)
{
int new_gfxcard = video_old_to_new(video_list[configure_dialog[4].d1].num);
deviceconfig_open(video_card_getdevice(new_gfxcard));
return D_O_K;
}
return ret;
}
static int sound_config_proc(int msg, DIALOG *d, int c)
{
int ret = d_button_proc(msg, d, c);
if (ret == D_CLOSE)
{
int new_sndcard = sound_list[configure_dialog[9].d1].num;
deviceconfig_open(sound_card_getdevice(new_sndcard));
return D_O_K;
}
return ret;
}
static void reset_list()
{
int model = model_list[configure_dialog[3].d1].num;
int cpumanu = configure_dialog[5].d1;
int cpu = configure_dialog[6].d1;
int c;
memset(cpumanu_list, 0, sizeof(cpumanu_list));
memset(cpu_list, 0, sizeof(cpu_list));
c = 0;
while (models[model].cpu[c].cpus != NULL && c < 3)
{
strcpy(cpumanu_list[c].name, models[model].cpu[c].name);
cpumanu_list[c].num = c;
c++;
}
if (cpumanu >= c)
cpumanu = configure_dialog[6].d1 = c-1;
c = 0;
while (models[model].cpu[cpumanu].cpus[c].cpu_type != -1)
{
strcpy(cpu_list[c].name, models[model].cpu[cpumanu].cpus[c].name);
cpu_list[c].num = c;
c++;
}
if (cpu >= c)
cpu = configure_dialog[7].d1 = c-1;
}
int settings_configure()
{
int c, d;
int cpu_flags;
memset(model_list, 0, sizeof(model_list));
memset(video_list, 0, sizeof(video_list));
memset(sound_list, 0, sizeof(sound_list));
for (c = 0; c < ROM_MAX; c++)
romstolist[c] = 0;
c = d = 0;
while (models[c].id != -1)
{
pclog("INITDIALOG : %i %i %i\n",c,models[c].id,romspresent[models[c].id]);
if (romspresent[models[c].id])
{
strcpy(model_list[d].name, models[c].name);
model_list[d].num = c;
if (c == model)
configure_dialog[3].d1 = d;
d++;
}
c++;
}
if (models[model].fixed_gfxcard)
configure_dialog[4].flags |= D_DISABLED;
else
configure_dialog[4].flags &= ~D_DISABLED;
c = d = 0;
while (1)
{
char *s = video_card_getname(c);
if (!s[0])
break;
pclog("video_card_available : %i\n", c);
if (video_card_available(c))
{
strcpy(video_list[d].name, video_card_getname(c));
video_list[d].num = video_new_to_old(c);
if (video_new_to_old(c) == gfxcard)
configure_dialog[4].d1 = d;
d++;
}
c++;
}
if (!video_card_has_config(video_old_to_new(gfxcard)))
configure_dialog[30].flags |= D_DISABLED;
else
configure_dialog[30].flags &= ~D_DISABLED;
c = d = 0;
while (1)
{
char *s = sound_card_getname(c);
if (!s[0])
break;
if (sound_card_available(c))
{
strcpy(sound_list[d].name, sound_card_getname(c));
sound_list[d].num = c;
if (c == sound_card_current)
configure_dialog[9].d1 = d;
d++;
}
c++;
}
c = 0;
while (joystick_get_name(c))
{
strcpy(joystick_list[c].name, joystick_get_name(c));
if (c == joystick_type)
configure_dialog[34].d1 = c;
c++;
}
if (!sound_card_has_config(configure_dialog[9].d1))
configure_dialog[31].flags |= D_DISABLED;
else
configure_dialog[31].flags &= ~D_DISABLED;
configure_dialog[5].d1 = cpu_manufacturer;
configure_dialog[6].d1 = cpu;
configure_dialog[7].d1 = cache;
configure_dialog[8].d1 = video_speed;
reset_list();
// strcpy(cpumanu_str, models[romstomodel[romset]].cpu[cpu_manufacturer].name);
// strcpy(cpu_str, models[romstomodel[romset]].cpu[cpu_manufacturer].cpus[cpu].name);
// strcpy(cache_str, cache_str_list[cache]);
// strcpy(vidspeed_str, vidspeed_str_list[video_speed]);
// strcpy(soundcard_str, sound_card_getname(sound_card_current));
if (GAMEBLASTER)
configure_dialog[12].flags |= D_SELECTED;
else
configure_dialog[12].flags &= ~D_SELECTED;
if (GUS)
configure_dialog[13].flags |= D_SELECTED;
else
configure_dialog[13].flags &= ~D_SELECTED;
if (SSI2001)
configure_dialog[14].flags |= D_SELECTED;
else
configure_dialog[14].flags &= ~D_SELECTED;
if (cga_comp)
configure_dialog[15].flags |= D_SELECTED;
else
configure_dialog[15].flags &= ~D_SELECTED;
if (voodoo_enabled)
configure_dialog[16].flags |= D_SELECTED;
else
configure_dialog[16].flags &= ~D_SELECTED;
if (models[model].is_at)
sprintf(mem_size_str, "%i", mem_size / 1024);
else
sprintf(mem_size_str, "%i", mem_size);
if (models[model].is_at)
sprintf(mem_size_units, "MB");
else
sprintf(mem_size_units, "kB");
cpu_flags = models[model].cpu[cpu_manufacturer].cpus[cpu].cpu_flags;
configure_dialog[25].flags = (((cpu_flags & CPU_SUPPORTS_DYNAREC) && cpu_use_dynarec) || (cpu_flags & CPU_REQUIRES_DYNAREC)) ? D_SELECTED : 0;
if (!(cpu_flags & CPU_SUPPORTS_DYNAREC) || (cpu_flags & CPU_REQUIRES_DYNAREC))
configure_dialog[25].flags |= D_DISABLED;
configure_dialog[28].d1 = fdd_get_type(0);
configure_dialog[29].d1 = fdd_get_type(1);
while (1)
{
position_dialog(configure_dialog, SCREEN_W/2 - configure_dialog[0].w/2, SCREEN_H/2 - configure_dialog[0].h/2);
c = popup_dialog(configure_dialog, 1);
position_dialog(configure_dialog, -(SCREEN_W/2 - configure_dialog[0].w/2), -(SCREEN_H/2 - configure_dialog[0].h/2));
if (c == 1)
{
int new_model = model_list[configure_dialog[3].d1].num;
int new_gfxcard = video_list[configure_dialog[4].d1].num;
int new_sndcard = sound_list[configure_dialog[9].d1].num;
int new_cpu_m = configure_dialog[5].d1;
int new_cpu = configure_dialog[6].d1;
int new_mem_size;
int new_has_fpu = (models[new_model].cpu[new_cpu_m].cpus[new_cpu].cpu_type >= CPU_i486DX) ? 1 : 0;
int new_GAMEBLASTER = (configure_dialog[12].flags & D_SELECTED) ? 1 : 0;
int new_GUS = (configure_dialog[13].flags & D_SELECTED) ? 1 : 0;
int new_SSI2001 = (configure_dialog[14].flags & D_SELECTED) ? 1 : 0;
int new_voodoo = (configure_dialog[16].flags & D_SELECTED) ? 1 : 0;
int new_dynarec = (configure_dialog[25].flags & D_SELECTED) ? 1 : 0;
int new_fda = configure_dialog[28].d1;
int new_fdb = configure_dialog[29].d1;
sscanf(mem_size_str, "%i", &new_mem_size);
new_mem_size &= ~(models[new_model].ram_granularity - 1);
if (new_mem_size < models[new_model].min_ram)
new_mem_size = models[new_model].min_ram;
else if (new_mem_size > models[new_model].max_ram)
new_mem_size = models[new_model].max_ram;
if (models[new_model].is_at)
new_mem_size *= 1024;
if (new_model != model || new_gfxcard != gfxcard || new_mem_size != mem_size ||
new_has_fpu != hasfpu || new_GAMEBLASTER != GAMEBLASTER || new_GUS != GUS ||
new_SSI2001 != SSI2001 || new_sndcard != sound_card_current || new_voodoo != voodoo_enabled ||
new_dynarec != cpu_use_dynarec || new_fda != fdd_get_type(0) || new_fdb != fdd_get_type(1))
{
if (alert("This will reset PCem!", "Okay to continue?", NULL, "OK", "Cancel", 0, 0) != 1)
continue;
model = new_model;
romset = model_getromset();
gfxcard = new_gfxcard;
mem_size = new_mem_size;
cpu_manufacturer = new_cpu_m;
cpu = new_cpu;
GAMEBLASTER = new_GAMEBLASTER;
GUS = new_GUS;
SSI2001 = new_SSI2001;
sound_card_current = new_sndcard;
voodoo_enabled = new_voodoo;
cpu_use_dynarec = new_dynarec;
mem_resize();
loadbios();
resetpchard();
fdd_set_type(0, new_fda);
fdd_set_type(1, new_fdb);
}
video_speed = configure_dialog[8].d1;
cga_comp = (configure_dialog[15].flags & D_SELECTED) ? 1 : 0;
cpu_manufacturer = new_cpu_m;
cpu = new_cpu;
cpu_set();
cache = configure_dialog[7].d1;
mem_updatecache();
joystick_type = configure_dialog[34].d1;
gameport_update_joystick_type();
saveconfig();
speedchanged();
return D_O_K;
}
if (c == 2)
return D_O_K;
}
return D_O_K;
}

View File

@@ -0,0 +1,303 @@
#include "ibm.h"
#include "device.h"
#include "allegro-main.h"
#include "allegro-gui.h"
#include "config.h"
static device_t *config_device;
#define MAX_CONFIG_SIZE 64
#define MAX_CONFIG_SELECTIONS 8
static device_config_selection_t *config_selections[MAX_CONFIG_SELECTIONS];
#define list_proc_device_func(i) \
static char *list_proc_device_ ## i(int index, int *list_size) \
{ \
device_config_selection_t *config = config_selections[i]; \
\
if (index < 0) \
{ \
int c = 0; \
\
while (config[c].description[0]) \
c++; \
\
*list_size = c; \
return NULL; \
} \
\
return config[index].description; \
}
list_proc_device_func(0)
list_proc_device_func(1)
list_proc_device_func(2)
list_proc_device_func(3)
list_proc_device_func(4)
list_proc_device_func(5)
list_proc_device_func(6)
list_proc_device_func(7)
static DIALOG deviceconfig_dialog[MAX_CONFIG_SIZE] =
{
{d_shadow_box_proc, 0, 0, 568,332,0,0xffffff,0,0, 0,0,0,0,0} // 0
};
void deviceconfig_open(device_t *device)
{
DIALOG *d;
device_config_t *config = device->config;
int y = 10;
int dialog_pos = 1;
int list_pos = 0;
int c;
int id_ok, id_cancel;
memset((void *)((uintptr_t)deviceconfig_dialog) + sizeof(DIALOG), 0, sizeof(deviceconfig_dialog) - sizeof(DIALOG));
deviceconfig_dialog[0].x = deviceconfig_dialog[0].y = 0;
while (config->type != -1)
{
d = &deviceconfig_dialog[dialog_pos];
switch (config->type)
{
case CONFIG_BINARY:
d->x = 32;
d->y = y;
d->w = 118*2;
d->h = 15;
d->dp = config->description;
d->proc = d_check_proc;
d->flags = config_get_int(device->name, config->name, config->default_int) ? D_SELECTED : 0;
d->bg = 0xffffff;
d->fg = 0;
dialog_pos++;
y += 20;
break;
case CONFIG_SELECTION:
if (list_pos >= MAX_CONFIG_SELECTIONS)
break;
d->x = 32;
d->y = y;
d->w = 80;
d->h = 15;
d->dp = config->description;
d->proc = d_text_proc;
d->flags = 0;
d->bg = 0xffffff;
d->fg = 0;
d++;
d->x = 250;
d->y = y;
d->w = 304;
d->h = 20;
switch (list_pos)
{
case 0 : d->dp = list_proc_device_0; break;
case 1 : d->dp = list_proc_device_1; break;
case 2 : d->dp = list_proc_device_2; break;
case 3 : d->dp = list_proc_device_3; break;
case 4 : d->dp = list_proc_device_4; break;
case 5 : d->dp = list_proc_device_5; break;
case 6 : d->dp = list_proc_device_6; break;
case 7 : d->dp = list_proc_device_7; break;
}
d->proc = d_list_proc;
d->flags = 0;
d->bg = 0xffffff;
d->fg = 0;
config_selections[list_pos++] = config->selection;
c = 0;
while (config->selection[c].description[0])
{
if (config_get_int(device->name, config->name, config->default_int) == config->selection[c].value)
d->d1 = c;
c++;
}
dialog_pos += 2;
y += 20;
break;
case CONFIG_MIDI:
break;
}
config++;
if (dialog_pos >= MAX_CONFIG_SIZE-3)
break;
}
d = &deviceconfig_dialog[dialog_pos];
id_ok = dialog_pos;
id_cancel = dialog_pos + 1;
d->x = 226;
d->y = y+8;
d->w = 50;
d->h = 16;
d->dp = "OK";
d->proc = d_button_proc;
d->flags = D_EXIT;
d->bg = 0xffffff;
d->fg = 0;
d++;
d->x = 296;
d->y = y+8;
d->w = 50;
d->h = 16;
d->dp = "Cancel";
d->proc = d_button_proc;
d->flags = D_EXIT;
d->bg = 0xffffff;
d->fg = 0;
deviceconfig_dialog[0].h = y + 28;
config_device = device;
while (1)
{
position_dialog(deviceconfig_dialog, SCREEN_W/2 - deviceconfig_dialog[0].w/2, SCREEN_H/2 - deviceconfig_dialog[0].h/2);
c = popup_dialog(deviceconfig_dialog, 1);
position_dialog(deviceconfig_dialog, -(SCREEN_W/2 - deviceconfig_dialog[0].w/2), -(SCREEN_H/2 - deviceconfig_dialog[0].h/2));
if (c == id_ok)
{
int changed = 0;
dialog_pos = 1;
config = device->config;
while (config->type != -1)
{
int val;
d = &deviceconfig_dialog[dialog_pos];
switch (config->type)
{
case CONFIG_BINARY:
val = (d->flags & D_SELECTED) ? 1 : 0;
if (val != config_get_int(device->name, config->name, config->default_int))
changed = 1;
dialog_pos++;
break;
case CONFIG_SELECTION:
if (list_pos >= MAX_CONFIG_SELECTIONS)
break;
d++;
val = config->selection[d->d1].value;
if (val != config_get_int(device->name, config->name, config->default_int))
changed = 1;
dialog_pos += 2;
break;
case CONFIG_MIDI:
break;
}
config++;
if (dialog_pos >= MAX_CONFIG_SIZE-3)
break;
}
if (!changed)
return;
if (alert("This will reset PCem!", "Okay to continue?", NULL, "OK", "Cancel", 0, 0) != 1)
continue;
dialog_pos = 1;
config = device->config;
while (config->type != -1)
{
int val;
d = &deviceconfig_dialog[dialog_pos];
switch (config->type)
{
case CONFIG_BINARY:
val = (d->flags & D_SELECTED) ? 1 : 0;
config_set_int(config_device->name, config->name, val);
dialog_pos++;
break;
case CONFIG_SELECTION:
if (list_pos >= MAX_CONFIG_SELECTIONS)
break;
d++;
val = config->selection[d->d1].value;
config_set_int(config_device->name, config->name, val);
dialog_pos += 2;
break;
case CONFIG_MIDI:
break;
}
config++;
if (dialog_pos >= MAX_CONFIG_SIZE-3)
break;
}
saveconfig();
resetpchard();
return;
}
if (c == id_cancel)
break;
}
}

513
src/allegro-gui-hdconf.c Normal file
View File

@@ -0,0 +1,513 @@
#define _LARGEFILE_SOURCE
#define _LARGEFILE64_SOURCE
#define _GNU_SOURCE
#include <stdio.h>
#include "ibm.h"
#include "device.h"
#include "ide.h"
#include "allegro-main.h"
#include "allegro-gui.h"
static char hd_path[4][260];
static char hd_sectors[4][10];
static char hd_heads[4][10];
static char hd_cylinders[4][10];
static char hd_size[4][20];
static char hd_path_new[260];
static char hd_sectors_new[10];
static char hd_heads_new[10];
static char hd_cylinders_new[10];
static char hd_size_new[20];
static int new_cdrom_channel;
static PcemHDC hdc_new[4];
static DIALOG hdparams_dialog[]=
{
{d_shadow_box_proc, 0, 0, 194*2,86,0,0xffffff,0,0, 0,0,0,0,0}, // 0
{d_button_proc, 126, 66, 50, 14, 0, 0xffffff, 0, D_EXIT, 0, 0, "OK", 0, 0}, // 1
{d_button_proc, 196, 66, 50, 16, 0, 0xffffff, 0, D_EXIT, 0, 0, "Cancel", 0, 0}, // 2
{d_text_proc, 7*2, 6, 170, 10, 0, 0xffffff, 0, 0, 0, 0, "Initial settings are based on file size", 0, 0},
{d_text_proc, 7*2, 22, 27, 10, 0, 0xffffff, 0, 0, 0, 0, "Sectors:", 0, 0},
{d_text_proc, 63*2, 22, 29, 8, 0, 0xffffff, 0, 0, 0, 0, "Heads:", 0, 0},
{d_text_proc, 120*2, 22, 28, 12, 0, 0xffffff, 0, 0, 0, 0, "Cylinders:", 0, 0},
{d_edit_proc, 44*2, 22, 16*2, 12, 0, 0xffffff, 0, 0, 2, 0, hd_sectors_new, 0, 0},
{d_edit_proc, 92*2, 22, 16*2, 12, 0, 0xffffff, 0, 0, 3, 0, hd_heads_new, 0, 0},
{d_edit_proc, 168*2, 22, 24*2, 12, 0, 0xffffff, 0, 0, 5, 0, hd_cylinders_new, 0, 0},
{d_text_proc, 7*2, 54, 136, 12, 0, 0xffffff, 0, 0, 0, 0, hd_size_new, 0, 0},
{0,0,0,0,0,0,0,0,0,0,0,NULL,NULL,NULL}
};
static int hdconf_open(int msg, DIALOG *d, int c)
{
int drv = d->d2;
int ret = d_button_proc(msg, d, c);
if (ret == D_EXIT)
{
char fn[260];
int xsize = SCREEN_W - 32, ysize = SCREEN_H - 64;
strcpy(fn, hd_path[drv]);
ret = file_select_ex("Please choose a disc image", fn, "IMG", 260, xsize, ysize);
if (ret)
{
uint64_t sz;
FILE *f = fopen64(fn, "rb");
if (!f)
{
return D_REDRAW;
}
fseeko64(f, -1, SEEK_END);
sz = ftello64(f) + 1;
fclose(f);
sprintf(hd_sectors_new, "63");
sprintf(hd_heads_new, "16");
sprintf(hd_cylinders_new, "%i", (int)((sz / 512) / 16) / 63);
while (1)
{
position_dialog(hdparams_dialog, SCREEN_W/2 - 186, SCREEN_H/2 - 86/2);
ret = popup_dialog(hdparams_dialog, 1);
position_dialog(hdparams_dialog, -(SCREEN_W/2 - 186), -(SCREEN_H/2 - 86/2));
if (ret == 1)
{
int spt, hpc, cyl;
sscanf(hd_sectors_new, "%i", &spt);
sscanf(hd_heads_new, "%i", &hpc);
sscanf(hd_cylinders_new, "%i", &cyl);
if (spt > 63)
{
alert("Drive has too many sectors (maximum is 63)", NULL, NULL, "OK", NULL, 0, 0);
continue;
}
if (hpc > 128)
{
alert("Drive has too many heads (maximum is 128)", NULL, NULL, "OK", NULL, 0, 0);
continue;
}
if (cyl > 16383)
{
alert("Drive has too many cylinders (maximum is 16383)", NULL, NULL, "OK", NULL, 0, 0);
continue;
}
hdc_new[drv].spt = spt;
hdc_new[drv].hpc = hpc;
hdc_new[drv].tracks = cyl;
strcpy(hd_path[drv], fn);
sprintf(hd_sectors[drv], "%i", hdc_new[drv].spt);
sprintf(hd_heads[drv], "%i", hdc_new[drv].hpc);
sprintf(hd_cylinders[drv], "%i", hdc_new[drv].tracks);
sprintf(hd_size[drv], "Size : %imb", (((((uint64_t)hdc_new[drv].tracks*(uint64_t)hdc_new[drv].hpc)*(uint64_t)hdc_new[drv].spt)*512)/1024)/1024);
return D_REDRAW;
}
if (ret == 2)
break;
}
}
return D_REDRAW;
}
return ret;
}
static int hdconf_new_file(int msg, DIALOG *d, int c)
{
int ret = d_button_proc(msg, d, c);
if (ret == D_EXIT)
{
char fn[260];
int xsize = SCREEN_W - 32, ysize = SCREEN_H - 64;
strcpy(fn, hd_path_new);
ret = file_select_ex("Please choose a disc image", fn, "IMG", 260, xsize, ysize);
if (ret)
strcpy(hd_path_new, fn);
return D_REDRAW;
}
return ret;
}
static DIALOG hdnew_dialog[]=
{
{d_shadow_box_proc, 0, 0, 194*2,86,0,0xffffff,0,0, 0,0,0,0,0}, // 0
{d_button_proc, 126, 66, 50, 14, 0, 0xffffff, 0, D_EXIT, 0, 0, "OK", 0, 0}, // 1
{d_button_proc, 196, 66, 50, 16, 0, 0xffffff, 0, D_EXIT, 0, 0, "Cancel", 0, 0}, // 2
{d_edit_proc, 7*2, 6, 136*2, 10, 0, 0xffffff, 0, 0, 0, 0, hd_path_new, 0, 0},
{hdconf_new_file, 143*2, 6, 16*2, 14, 0, 0xffffff, 0, D_EXIT, 0, 0, "...", 0, 0},
{d_text_proc, 7*2, 22, 27, 10, 0, 0xffffff, 0, 0, 0, 0, "Sectors:", 0, 0},
{d_text_proc, 63*2, 22, 29, 8, 0, 0xffffff, 0, 0, 0, 0, "Heads:", 0, 0},
{d_text_proc, 120*2, 22, 28, 12, 0, 0xffffff, 0, 0, 0, 0, "Cylinders:", 0, 0},
{d_edit_proc, 44*2, 22, 16*2, 12, 0, 0xffffff, 0, 0, 2, 0, hd_sectors_new, 0, 0},
{d_edit_proc, 92*2, 22, 16*2, 12, 0, 0xffffff, 0, 0, 3, 0, hd_heads_new, 0, 0},
{d_edit_proc, 168*2, 22, 24*2, 12, 0, 0xffffff, 0, 0, 5, 0, hd_cylinders_new, 0, 0},
// {d_text_proc, 7*2, 54, 136, 12, 0, -1, 0, 0, 0, 0, hd_size_new, 0, 0},
{0,0,0,0,0,0,0,0,0,0,0,NULL,NULL,NULL}
};
static int create_hd(char *fn, int cyl, int hpc, int spt)
{
int c;
int e;
uint8_t buf[512];
FILE *f = fopen64(hd_path_new, "wb");
e = errno;
if (!f)
{
alert("Can't open file for write", NULL, NULL, "OK", NULL, 0, 0);
return -1;
}
memset(buf, 0, 512);
for (c = 0; c < (cyl * hpc * spt); c++)
{
fwrite(buf, 512, 1, f);
}
fclose(f);
}
static int hdconf_new(int msg, DIALOG *d, int c)
{
int drv = d->d2;
int ret = d_button_proc(msg, d, c);
if (ret == D_EXIT)
{
sprintf(hd_sectors_new, "63");
sprintf(hd_heads_new, "16");
sprintf(hd_cylinders_new, "511");
strcpy(hd_path_new, "");
while (1)
{
position_dialog(hdnew_dialog, SCREEN_W/2 - 186, SCREEN_H/2 - 86/2);
ret = popup_dialog(hdnew_dialog, 1);
position_dialog(hdnew_dialog, -(SCREEN_W/2 - 186), -(SCREEN_H/2 - 86/2));
if (ret == 1)
{
int spt, hpc, cyl;
int c, d;
FILE *f;
uint8_t *buf;
sscanf(hd_sectors_new, "%i", &spt);
sscanf(hd_heads_new, "%i", &hpc);
sscanf(hd_cylinders_new, "%i", &cyl);
if (spt > 63)
{
alert("Drive has too many sectors (maximum is 63)", NULL, NULL, "OK", NULL, 0, 0);
continue;
}
if (hpc > 128)
{
alert("Drive has too many heads (maximum is 128)", NULL, NULL, "OK", NULL, 0, 0);
continue;
}
if (cyl > 16383)
{
alert("Drive has too many cylinders (maximum is 16383)", NULL, NULL, "OK", NULL, 0, 0);
continue;
}
if (create_hd(hd_path_new, cyl, hpc, spt))
return D_REDRAW;
alert("Remember to partition and format the new drive", NULL, NULL, "OK", NULL, 0, 0);
hdc_new[drv].spt = spt;
hdc_new[drv].hpc = hpc;
hdc_new[drv].tracks = cyl;
strcpy(hd_path[drv], hd_path_new);
sprintf(hd_sectors[drv], "%i", hdc_new[drv].spt);
sprintf(hd_heads[drv], "%i", hdc_new[drv].hpc);
sprintf(hd_cylinders[drv], "%i", hdc_new[drv].tracks);
sprintf(hd_size[drv], "Size : %imb", (((((uint64_t)hdc_new[drv].tracks*(uint64_t)hdc_new[drv].hpc)*(uint64_t)hdc_new[drv].spt)*512)/1024)/1024);
return D_REDRAW;
}
if (ret == 2)
break;
}
return D_REDRAW;
}
return ret;
}
static int hdconf_eject(int msg, DIALOG *d, int c)
{
int drv = d->d2;
int ret = d_button_proc(msg, d, c);
if (ret == D_EXIT)
{
hdc_new[drv].spt = 0;
hdc_new[drv].hpc = 0;
hdc_new[drv].tracks = 0;
strcpy(hd_path[drv], "");
sprintf(hd_sectors[drv], "%i", hdc_new[drv].spt);
sprintf(hd_heads[drv], "%i", hdc_new[drv].hpc);
sprintf(hd_cylinders[drv], "%i", hdc_new[drv].tracks);
sprintf(hd_size[drv], "Size : %imb", (((((uint64_t)hdc_new[drv].tracks*(uint64_t)hdc_new[drv].hpc)*(uint64_t)hdc_new[drv].spt)*512)/1024)/1024);
return D_REDRAW;
}
return ret;
}
static int hdconf_radio_hd(int msg, DIALOG *d, int c);
static int hdconf_radio_cd(int msg, DIALOG *d, int c);
static DIALOG hdconf_dialog[]=
{
{d_shadow_box_proc, 0, 0, 210*2,354,0,0xffffff,0,0, 0,0,0,0,0}, // 0
{d_button_proc, 150, 334, 50, 16, 0, 0xffffff, 0, D_EXIT, 0, 0, "OK", 0, 0}, // 1
{d_button_proc, 220, 334, 50, 16, 0, 0xffffff, 0, D_EXIT, 0, 0, "Cancel", 0, 0}, // 2
{d_text_proc, 7*2, 6, 27, 10, 0, 0xffffff, 0, 0, 0, 0, "C:", 0, 0},
{hdconf_radio_hd, 7*2, 22, 96, 12, 0, 0xffffff, 0, D_EXIT, 0, 0, "Hard drive", 0, 0}, // 4
{hdconf_radio_cd, 100*2, 22, 64, 12, 0, 0xffffff, 0, D_EXIT, 0, 0, "CD-ROM", 0, 0}, // 5
{d_edit_proc, 7*2, 38, 136*2, 12, 0, 0xffffff, 0, D_DISABLED, 0, 0, hd_path[0], 0, 0},
{hdconf_open, 143*2, 38, 16*2, 14, 0, 0xffffff, 0, D_EXIT, 0, 0, "...", 0, 0},
{hdconf_new, 159*2, 38, 24*2, 14, 0, 0xffffff, 0, D_EXIT, 0, 0, "New", 0, 0},
{hdconf_eject, 183*2, 38, 24*2, 14, 0, 0xffffff, 0, D_EXIT, 0, 0, "Eject", 0, 0},
{d_text_proc, 7*2, 54, 27, 10, 0, 0xffffff, 0, 0, 0, 0, "Sectors:", 0, 0},
{d_text_proc, 63*2, 54, 29, 8, 0, 0xffffff, 0, 0, 0, 0, "Heads:", 0, 0},
{d_text_proc, 120*2, 54, 28, 12, 0, 0xffffff, 0, 0, 0, 0, "Cylinders:", 0, 0},
{d_edit_proc, 44*2, 54, 16*2, 12, 0, 0xffffff, 0, D_DISABLED, 0, 0, hd_sectors[0], 0, 0},
{d_edit_proc, 92*2, 54, 16*2, 12, 0, 0xffffff, 0, D_DISABLED, 0, 0, hd_heads[0], 0, 0},
{d_edit_proc, 168*2, 54, 24*2, 12, 0, 0xffffff, 0, D_DISABLED, 0, 0, hd_cylinders[0], 0, 0},
{d_text_proc, 7*2, 54, 136, 12, 0, 0xffffff, 0, 0, 0, 0, hd_size[0], 0, 0},
{d_text_proc, 7*2, 76, 27, 10, 0, 0xffffff, 0, 0, 0, 0, "D:", 0, 0},
{hdconf_radio_hd, 7*2, 92, 96, 12, 0, 0xffffff, 0, D_EXIT, 1, 0, "Hard drive", 0, 0}, // 18
{hdconf_radio_cd, 100*2, 92, 64, 12, 0, 0xffffff, 0, D_EXIT, 1, 0, "CD-ROM", 0, 0}, // 19
{d_edit_proc, 7*2, 108, 136*2, 12, 0, 0xffffff, 0, D_DISABLED, 0, 0, hd_path[1], 0, 0},
{hdconf_open, 143*2, 108, 16*2, 14, 0, 0xffffff, 0, D_EXIT, 0, 1, "...", 0, 0},
{hdconf_new, 159*2, 108, 24*2, 14, 0, 0xffffff, 0, D_EXIT, 0, 1, "New", 0, 0},
{hdconf_eject, 183*2, 108, 24*2, 14, 0, 0xffffff, 0, D_EXIT, 0, 1, "Eject", 0, 0},
{d_edit_proc, 44*2, 124, 16*2, 12, 0, 0xffffff, 0, D_DISABLED, 0, 0, hd_sectors[1], 0, 0},
{d_edit_proc, 92*2, 124, 16*2, 12, 0, 0xffffff, 0, D_DISABLED, 0, 0, hd_heads[1], 0, 0},
{d_edit_proc, 168*2, 124, 24*2, 12, 0, 0xffffff, 0, D_DISABLED, 0, 0, hd_cylinders[1], 0, 0},
{d_text_proc, 7*2, 124, 27, 10, 0, 0xffffff, 0, 0, 0, 0, "Sectors:", 0, 0},
{d_text_proc, 63*2, 124, 29, 8, 0, 0xffffff, 0, 0, 0, 0, "Heads:", 0, 0},
{d_text_proc, 120*2, 124, 32, 12, 0, 0xffffff, 0, 0, 0, 0, "Cylinders:", 0, 0},
{d_text_proc, 7*2, 140, 136, 12, 0, 0xffffff, 0, 0, 0, 0, hd_size[1], 0, 0},
{d_text_proc, 7*2, 162, 27, 10, 0, 0xffffff, 0, 0, 0, 0, "E:", 0, 0},
{hdconf_radio_hd, 7*2, 178, 96, 12, 0, 0xffffff, 0, D_EXIT, 2, 0, "Hard drive", 0, 0}, // 32
{hdconf_radio_cd, 100*2, 178, 64, 12, 0, 0xffffff, 0, D_EXIT, 2, 0, "CD-ROM", 0, 0}, // 33
{d_edit_proc, 7*2, 194, 136*2, 12, 0, 0xffffff, 0, D_DISABLED, 0, 0, hd_path[2], 0, 0},
{hdconf_open, 143*2, 194, 16*2, 14, 0, 0xffffff, 0, D_EXIT, 0, 2, "...", 0, 0},
{hdconf_new, 159*2, 194, 24*2, 14, 0, 0xffffff, 0, D_EXIT, 0, 2, "New", 0, 0},
{hdconf_eject, 183*2, 194, 24*2, 14, 0, 0xffffff, 0, D_EXIT, 0, 2, "Eject", 0, 0},
{d_edit_proc, 44*2, 210, 16*2, 12, 0, 0xffffff, 0, D_DISABLED, 0, 0, hd_sectors[2], 0, 0},
{d_edit_proc, 92*2, 210, 16*2, 12, 0, 0xffffff, 0, D_DISABLED, 0, 0, hd_heads[2], 0, 0},
{d_edit_proc, 168*2, 210, 24*2, 12, 0, 0xffffff, 0, D_DISABLED, 0, 0, hd_cylinders[2], 0, 0},
{d_text_proc, 7*2, 210, 27, 10, 0, 0xffffff, 0, 0, 0, 0, "Sectors:", 0, 0},
{d_text_proc, 63*2, 210, 29, 8, 0, 0xffffff, 0, 0, 0, 0, "Heads:", 0, 0},
{d_text_proc, 120*2, 210, 32, 12, 0, 0xffffff, 0, 0, 0, 0, "Cylinders:", 0, 0},
{d_text_proc, 7*2, 226, 136, 12, 0, 0xffffff, 0, 0, 0, 0, hd_size[2], 0, 0},
{d_text_proc, 7*2, 248, 27, 10, 0, 0xffffff, 0, 0, 0, 0, "F:", 0, 0},
{hdconf_radio_hd, 7*2, 264, 96, 12, 0, 0xffffff, 0, D_EXIT, 3, 0, "Hard drive", 0, 0}, // 46
{hdconf_radio_cd, 100*2, 264, 64, 12, 0, 0xffffff, 0, D_EXIT, 3, 0, "CD-ROM", 0, 0}, // 47
{d_edit_proc, 7*2, 280, 136*2, 12, 0, 0xffffff, 0, D_DISABLED, 0, 0, hd_path[3], 0, 0},
{hdconf_open, 143*2, 280, 16*2, 14, 0, 0xffffff, 0, D_EXIT, 0, 3, "...", 0, 0},
{hdconf_new, 159*2, 280, 24*2, 14, 0, 0xffffff, 0, D_EXIT, 0, 3, "New", 0, 0},
{hdconf_eject, 183*2, 280, 24*2, 14, 0, 0xffffff, 0, D_EXIT, 0, 3, "Eject", 0, 0},
{d_edit_proc, 44*2, 296, 16*2, 12, 0, 0xffffff, 0, D_DISABLED, 0, 0, hd_sectors[3], 0, 0},
{d_edit_proc, 92*2, 296, 16*2, 12, 0, 0xffffff, 0, D_DISABLED, 0, 0, hd_heads[3], 0, 0},
{d_edit_proc, 168*2, 296, 24*2, 12, 0, 0xffffff, 0, D_DISABLED, 0, 0, hd_cylinders[3], 0, 0},
{d_text_proc, 7*2, 296, 27, 10, 0, 0xffffff, 0, 0, 0, 0, "Sectors:", 0, 0},
{d_text_proc, 63*2, 296, 29, 8, 0, 0xffffff, 0, 0, 0, 0, "Heads:", 0, 0},
{d_text_proc, 120*2, 296, 32, 12, 0, 0xffffff, 0, 0, 0, 0, "Cylinders:", 0, 0},
{d_text_proc, 7*2, 312, 136, 12, 0, 0xffffff, 0, 0, 0, 0, hd_size[3], 0, 0},
{0,0,0,0,0,0,0,0,0,0,0,NULL,NULL,NULL}
};
static void update_hdd_cdrom()
{
if (new_cdrom_channel == 0)
{
hdconf_dialog[4].flags &= ~D_SELECTED;
hdconf_dialog[5].flags |= D_SELECTED;
}
else
{
hdconf_dialog[4].flags |= D_SELECTED;
hdconf_dialog[5].flags &= ~D_SELECTED;
}
if (new_cdrom_channel == 1)
{
hdconf_dialog[18].flags &= ~D_SELECTED;
hdconf_dialog[19].flags |= D_SELECTED;
}
else
{
hdconf_dialog[18].flags |= D_SELECTED;
hdconf_dialog[19].flags &= ~D_SELECTED;
}
if (new_cdrom_channel == 2)
{
hdconf_dialog[32].flags &= ~D_SELECTED;
hdconf_dialog[33].flags |= D_SELECTED;
}
else
{
hdconf_dialog[32].flags |= D_SELECTED;
hdconf_dialog[33].flags &= ~D_SELECTED;
}
if (new_cdrom_channel == 3)
{
hdconf_dialog[46].flags &= ~D_SELECTED;
hdconf_dialog[47].flags |= D_SELECTED;
}
else
{
hdconf_dialog[46].flags |= D_SELECTED;
hdconf_dialog[47].flags &= ~D_SELECTED;
}
}
static int hdconf_radio_hd(int msg, DIALOG *d, int c)
{
int ret = d_radio_proc(msg, d, c);
if (ret == D_CLOSE)
{
if (new_cdrom_channel == d->d1)
{
new_cdrom_channel = -1;
update_hdd_cdrom();
}
return D_REDRAW;
}
return ret;
}
static int hdconf_radio_cd(int msg, DIALOG *d, int c)
{
int ret = d_radio_proc(msg, d, c);
if (ret == D_CLOSE)
{
if (new_cdrom_channel != d->d1)
{
new_cdrom_channel = d->d1;
update_hdd_cdrom();
}
return D_REDRAW;
}
return ret;
}
int disc_hdconf()
{
int c;
int changed=0;
hdc_new[0] = hdc[0];
hdc_new[1] = hdc[1];
hdc_new[2] = hdc[2];
hdc_new[3] = hdc[3];
strcpy(hd_path[0], ide_fn[0]);
strcpy(hd_path[1], ide_fn[1]);
strcpy(hd_path[2], ide_fn[2]);
strcpy(hd_path[3], ide_fn[3]);
sprintf(hd_sectors[0], "%i", hdc[0].spt);
sprintf(hd_sectors[1], "%i", hdc[1].spt);
sprintf(hd_sectors[2], "%i", hdc[2].spt);
sprintf(hd_sectors[3], "%i", hdc[3].spt);
sprintf(hd_heads[0], "%i", hdc[0].hpc);
sprintf(hd_heads[1], "%i", hdc[1].hpc);
sprintf(hd_heads[2], "%i", hdc[2].hpc);
sprintf(hd_heads[3], "%i", hdc[3].hpc);
sprintf(hd_cylinders[0], "%i", hdc[0].tracks);
sprintf(hd_cylinders[1], "%i", hdc[1].tracks);
sprintf(hd_cylinders[2], "%i", hdc[2].tracks);
sprintf(hd_cylinders[3], "%i", hdc[3].tracks);
sprintf(hd_size[0], "Size : %imb", (((((uint64_t)hdc[0].tracks*(uint64_t)hdc[0].hpc)*(uint64_t)hdc[0].spt)*512)/1024)/1024);
sprintf(hd_size[1], "Size : %imb", (((((uint64_t)hdc[1].tracks*(uint64_t)hdc[1].hpc)*(uint64_t)hdc[1].spt)*512)/1024)/1024);
sprintf(hd_size[2], "Size : %imb", (((((uint64_t)hdc[2].tracks*(uint64_t)hdc[2].hpc)*(uint64_t)hdc[2].spt)*512)/1024)/1024);
sprintf(hd_size[3], "Size : %imb", (((((uint64_t)hdc[3].tracks*(uint64_t)hdc[3].hpc)*(uint64_t)hdc[3].spt)*512)/1024)/1024);
new_cdrom_channel = cdrom_channel;
update_hdd_cdrom();
while (1)
{
position_dialog(hdconf_dialog, SCREEN_W/2 - hdconf_dialog[0].w/2, SCREEN_H/2 - hdconf_dialog[0].h/2);
c = popup_dialog(hdconf_dialog, 1);
position_dialog(hdconf_dialog, -(SCREEN_W/2 - hdconf_dialog[0].w/2), -(SCREEN_H/2 - hdconf_dialog[0].h/2));
if (c == 1)
{
if (alert("This will reset PCem!", "Okay to continue?", NULL, "OK", "Cancel", 0, 0) == 1)
{
hdc[0] = hdc_new[0];
hdc[1] = hdc_new[1];
hdc[2] = hdc_new[2];
hdc[3] = hdc_new[3];
strcpy(ide_fn[0], hd_path[0]);
strcpy(ide_fn[1], hd_path[1]);
strcpy(ide_fn[2], hd_path[2]);
strcpy(ide_fn[3], hd_path[3]);
cdrom_channel = new_cdrom_channel;
saveconfig();
resetpchard();
return D_O_K;
}
}
if (c == 2)
return D_O_K;
}
return D_O_K;
}

226
src/allegro-gui.c Normal file
View File

@@ -0,0 +1,226 @@
#include "ibm.h"
#include "device.h"
#include "allegro-main.h"
#include "allegro-gui.h"
#include "disc.h"
#include "ide.h"
static int file_return(void)
{
return D_CLOSE;
}
static int file_exit(void)
{
quited = 1;
return D_CLOSE;
}
static int file_reset(void)
{
resetpchard();
return D_CLOSE;
}
static int file_cad(void)
{
resetpc_cad();
return D_CLOSE;
}
static MENU file_menu[]=
{
{"&Return", file_return, NULL, 0, NULL},
{"&Hard Reset", file_reset, NULL, 0, NULL},
{"&Ctrl+Alt+Del", file_cad, NULL, 0, NULL},
{"E&xit", file_exit, NULL, 0, NULL},
{NULL,NULL,NULL,0,NULL}
};
static int disc_load_a()
{
char fn[260];
int ret;
int xsize = SCREEN_W - 32, ysize = SCREEN_H - 64;
strcpy(fn, discfns[0]);
ret = file_select_ex("Please choose a disc image", fn, "IMG;IMA;FDI", 260, xsize, ysize);
if (ret)
{
disc_close(0);
disc_load(0, fn);
saveconfig();
}
return D_O_K;
}
static int disc_load_b()
{
char fn[260];
int ret;
int xsize = SCREEN_W - 32, ysize = SCREEN_H - 64;
strcpy(fn, discfns[1]);
ret = file_select_ex("Please choose a disc image", fn, "IMG;IMA;FDI", 260, xsize, ysize);
if (ret)
{
disc_close(1);
disc_load(1, fn);
saveconfig();
}
return D_O_K;
}
static int disc_eject_a()
{
disc_close(0);
saveconfig();
return D_O_K;
}
static int disc_eject_b()
{
disc_close(1);
saveconfig();
return D_O_K;
}
static MENU disc_menu[]=
{
{"Load drive &A:...", disc_load_a, NULL, 0, NULL},
{"Load drive &B:...", disc_load_b, NULL, 0, NULL},
{"&Eject drive &A:", disc_eject_a, NULL, 0, NULL},
{"Eject drive &B:", disc_eject_b, NULL, 0, NULL},
{"&Configure hard discs...", disc_hdconf, NULL, 0, NULL},
{NULL,NULL,NULL,0,NULL}
};
static MENU cdrom_menu[];
static void cdrom_update()
{
int c;
for (c = 0; cdrom_menu[c].text; c++)
cdrom_menu[c].flags = 0;
if (!cdrom_enabled)
cdrom_menu[0].flags = D_SELECTED;
else
cdrom_menu[1].flags = D_SELECTED;
return D_O_K;
}
static int cdrom_disabled()
{
if (!cdrom_enabled)
return D_O_K;
if (alert("This will reset PCem!", "Okay to continue?", NULL, "OK", "Cancel", 0, 0) == 1)
{
atapi->exit();
cdrom_enabled = 0;
saveconfig();
resetpchard();
cdrom_update();
}
return D_O_K;
}
static int cdrom_empty()
{
if (cdrom_enabled)
{
atapi->exit();
cdrom_drive = -1;
cdrom_null_open(cdrom_drive);
return D_O_K;
}
if (alert("This will reset PCem!", "Okay to continue?", NULL, "OK", "Cancel", 0, 0) == 1)
{
cdrom_drive = -1;
cdrom_enabled = 1;
cdrom_null_open(cdrom_drive);
saveconfig();
resetpchard();
cdrom_update();
}
}
static int cdrom_dev()
{
if (cdrom_enabled)
{
atapi->exit();
cdrom_drive = 1;
ioctl_open(cdrom_drive);
return D_O_K;
}
if (alert("This will reset PCem!", "Okay to continue?", NULL, "OK", "Cancel", 0, 0) == 1)
{
cdrom_drive = 1;
cdrom_enabled = 1;
ioctl_open(cdrom_drive);
saveconfig();
resetpchard();
cdrom_update();
}
}
static MENU cdrom_menu[] =
{
{"&Disabled", cdrom_disabled, NULL, 0, NULL},
{"&Empty", cdrom_empty, NULL, 0, NULL},
{"/dev/cdrom", cdrom_dev, NULL, 0, NULL},
{NULL,NULL,NULL,0,NULL}
};
static MENU settings_menu[]=
{
{"&Configure...", settings_configure, NULL, 0, NULL},
{"CD-ROM", NULL, cdrom_menu, 0, NULL},
{NULL,NULL,NULL,0,NULL}
};
static MENU main_menu[]=
{
{"&File", NULL, file_menu, 0, NULL},
{"&Disc", NULL, disc_menu, 0, NULL},
{"&Settings", NULL, settings_menu, 0, NULL},
{NULL,NULL,NULL,0,NULL}
};
static DIALOG pcem_gui[]=
{
{d_menu_proc, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, main_menu, NULL, NULL},
{d_yield_proc, 0, 0, 0, 0, 15, 0, 0, 0, 0, 0, NULL, NULL, NULL},
{0,0,0,0,0,0,0,0,0,0,0,NULL,NULL,NULL}
};
void gui_enter()
{
DIALOG_PLAYER *dp;
int x = 1;
infocus = 0;
dp = init_dialog(pcem_gui, 0);
show_mouse(screen);
while (x && !(mouse_b & 2) && !key[KEY_ESC])
{
x = update_dialog(dp);
}
show_mouse(NULL);
shutdown_dialog(dp);
clear(screen);
clear_keybuf();
infocus = 1;
device_force_redraw();
}

12
src/allegro-gui.h Normal file
View File

@@ -0,0 +1,12 @@
void gui_enter();
extern int quited;
extern int romspresent[ROM_MAX];
extern int gfx_present[GFX_MAX];
int disc_hdconf();
int settings_configure();
void deviceconfig_open(device_t *device);

49
src/allegro-joystick.c Normal file
View File

@@ -0,0 +1,49 @@
#include "allegro-main.h"
#include "plat-joystick.h"
#include "device.h"
#include "gameport.h"
plat_joystick_t plat_joystick_state[MAX_PLAT_JOYSTICKS];
joystick_t joystick_state[MAX_JOYSTICKS];
int joysticks_present;
void joystick_init()
{
install_joystick(JOY_TYPE_AUTODETECT);
joysticks_present = num_joysticks;
}
void joystick_close()
{
}
void joystick_poll()
{
int c, d;
poll_joystick();
for (c = 0; c < num_joysticks; c++)
{
plat_joystick_state[c].a[0] = joy[c].stick[0].axis[0].pos * 256;
plat_joystick_state[c].a[1] = joy[c].stick[0].axis[1].pos * 256;
for (d = 0; d < MAX_JOYSTICK_BUTTONS; d++)
plat_joystick_state[c].b[d] = joy[c].button[d].b;
}
for (c = 0; c < joystick_get_max_joysticks(joystick_type); c++)
{
if (c < num_joysticks)
{
for (d = 0; d < joystick_get_axis_count(joystick_type); d++)
joystick_state[c].axis[d] = plat_joystick_state[c].a[d];
for (d = 0; d < joystick_get_button_count(joystick_type); d++)
joystick_state[c].button[d] = plat_joystick_state[c].b[d];
}
else
{
for (d = 0; d < joystick_get_axis_count(joystick_type); d++)
joystick_state[c].axis[d] = 0;
for (d = 0; d < joystick_get_button_count(joystick_type); d++)
joystick_state[c].button[d] = 0;
}
}
}

49
src/allegro-keyboard.c Normal file
View File

@@ -0,0 +1,49 @@
#include "allegro-main.h"
#include "plat-keyboard.h"
int pcem_key[272];
int rawinputkey[272];
static int key_convert[128] =
{
-1, 0x1e, 0x30, 0x2e, 0x20, 0x12, 0x21, 0x22, /* , A, B, C, D, E, F, G*/
0x23, 0x17, 0x24, 0x25, 0x26, 0x32, 0x31, 0x18, /* H, I, J, K, L, M, N, O*/
0x19, 0x10, 0x13, 0x1f, 0x14, 0x16, 0x2f, 0x11, /* P, Q, R, S, T, U, V, W*/
0x2d, 0x15, 0x2c, 0x0b, 0x02, 0x03, 0x04, 0x05, /* X, Y, Z, 0, 1, 2, 3, 4*/
0x06, 0x07, 0x08, 0x09, 0x0a, 0x52, 0x4f, 0x50, /* 5, 6, 7, 8, 9, p0, p1, p2*/
0x51, 0x4b, 0x4c, 0x4d, 0x47, 0x48, 0x49, 0x3b, /* p3, p4, p5, p6, p7, p8, p9, F1*/
0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, /* F2, F3, F4, F5, F6, F7, F8, F9*/
0x44, 0x57, 0x58, 0x01, 0x29, 0x0c, 0x0d, 0x0e, /*F10, F11, F12, ESC, `ª, -_, =+, backspace*/
0x0f, 0x1a, 0x1b, 0x1c, 0x27, 0x28, 0x2b, 0x56, /*TAB, [{, ]}, ENT, ;:, '@, \|, #~*/
0x33, 0x34, 0x35, 0x39, 0xd2, 0xd3, 0xc7, 0xcf, /* ,<, .>, /?, SPC, INS, DEL, HOME, END*/
0xc9, 0xd1, 0xcb, 0xcd, 0xc8, 0xd0, 0xb5, 0x37, /*PGU, PGD, LFT, RHT, UP, DN, /, * */
0x4a, 0x4e, 0x53, 0x9c, 0xff, -1, -1, -1, /* p-, p+, pDL, pEN, psc, pse, abnt, yen*/
-1, -1, -1, -1, -1, -1, -1, -1, /*kana, convert, noconvert, at, circumflex, colon2, kanji, pad equals*/
-1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, 0x2a, 0x36, 0x1d, 0x9d, 0x38, /*, , lshift, rshift, lctrl, rctrl, alt*/
0xb8, 0xdb, 0xdc, 0xdd, 0x46, 0x45, 0x3a, -1 /*altgr, lwin, rwin, menu, scrlock, numlock, capslock*/
};
void keyboard_init()
{
install_keyboard();
}
void keyboard_close()
{
}
void keyboard_poll_host()
{
int c;
for (c = 0; c < 128; c++)
{
int key_idx = key_convert[c];
if (key_idx == -1)
continue;
if (key[c] != pcem_key[key_idx])
pcem_key[key_idx] = key[c];
}
}

169
src/allegro-main.c Normal file
View File

@@ -0,0 +1,169 @@
#include "allegro-main.h"
#include "ibm.h"
#include "cpu.h"
#include "model.h"
#include "nvr.h"
#include "video.h"
#undef printf
int mousecapture = 0;
int quited = 0;
int winsizex = -1, winsizey = -1;
int romspresent[ROM_MAX];
int gfx_present[GFX_MAX];
void updatewindowsize(int x, int y)
{
if (x < 128)
x = 128;
if (y < 128)
y = 128;
if (winsizex != x || winsizey != y)
{
winsizex = x;
winsizey = y;
allegro_video_update_size(x, y);
}
}
void startblit()
{
}
void endblit()
{
}
static int ticks = 0;
static void timer_rout()
{
ticks++;
}
uint64_t timer_freq;
uint64_t timer_read()
{
return 0;
}
int main(int argc, char *argv[])
{
int frames = 0;
int c, d;
allegro_init();
allegro_video_init();
install_timer();
install_int_ex(timer_rout, BPS_TO_TIMER(100));
install_int_ex(onesec, BPS_TO_TIMER(1));
midi_init();
initpc(argc, argv);
d = romset;
for (c = 0; c < ROM_MAX; c++)
{
romset = c;
romspresent[c] = loadbios();
pclog("romset %i - %i\n", c, romspresent[c]);
}
for (c = 0; c < ROM_MAX; c++)
{
if (romspresent[c])
break;
}
if (c == ROM_MAX)
{
printf("No ROMs present!\nYou must have at least one romset to use PCem.");
return 0;
}
romset=d;
c=loadbios();
if (!c)
{
if (romset != -1)
printf("Configured romset not available.\nDefaulting to available romset.");
for (c = 0; c < ROM_MAX; c++)
{
if (romspresent[c])
{
romset = c;
model = model_getmodel(romset);
saveconfig();
resetpchard();
break;
}
}
}
for (c = 0; c < GFX_MAX; c++)
gfx_present[c] = video_card_available(video_old_to_new(c));
if (!video_card_available(video_old_to_new(gfxcard)))
{
if (gfxcard) printf("Configured video BIOS not available.\nDefaulting to available romset.");
for (c = GFX_MAX-1; c >= 0; c--)
{
if (gfx_present[c])
{
gfxcard = c;
saveconfig();
resetpchard();
break;
}
}
}
resetpchard();
ticks = 0;
while (!quited)
{
if (ticks)
{
ticks--;
runpc();
frames++;
if (frames >= 200 && nvr_dosave)
{
frames = 0;
nvr_dosave = 0;
savenvr();
}
}
else
rest(1);
if (ticks > 10)
ticks = 0;
if ((mouse_b & 1) && !mousecapture)
mousecapture = 1;
if (((key[KEY_LCONTROL] || key[KEY_RCONTROL]) && key[KEY_END]) || (mouse_b & 4))
mousecapture = 0;
if ((key[KEY_LCONTROL] || key[KEY_RCONTROL]) && key[KEY_ALT] && key[KEY_PGDN])
{
int old_winsizex = winsizex, old_winsizey = winsizey;
if (winsizex < 512 || winsizey < 350)
updatewindowsize(512, 350);
gui_enter();
if (old_winsizex < 512 || old_winsizey < 350)
updatewindowsize(old_winsizex, old_winsizey);
ticks = 0;
}
}
closepc();
midi_close();
return 0;
}
END_OF_MAIN();

19
src/allegro-main.h Normal file
View File

@@ -0,0 +1,19 @@
#define getr8 allegro_getr8
#define setr8 allegro_setr8
#define get_filename allegro_get_filename
#define append_filename allegro_append_filename
#define put_backslash allegro_put_backslash
#define get_extension allegro_get_extension
#define GFX_VGA allegro_GFX_VGA
#define MAX_JOYSTICKS allegro_MAX_JOYSTICKS
#include <allegro.h>
#undef MAX_JOYSTICKS
#undef GFX_VGA
#undef getr8
#undef setr8
#undef get_filename
#undef append_filename
#undef put_backslash
#undef get_extension

45
src/allegro-midi.c Normal file
View File

@@ -0,0 +1,45 @@
#include "allegro-main.h"
#include "ibm.h"
#include "plat-midi.h"
//#define USE_ALLEGRO_MIDI
void midi_init()
{
#ifdef USE_ALLEGRO_MIDI
install_sound(DIGI_NONE, MIDI_AUTODETECT, NULL);
#endif
}
void midi_close()
{
#ifdef USE_ALLEGRO_MIDI
remove_sound();
#endif
}
static int midi_cmd_pos, midi_len;
static uint8_t midi_command[3];
static int midi_lengths[8] = {3, 3, 3, 3, 2, 2, 3, 0};
void midi_write(uint8_t val)
{
if (val & 0x80)
{
midi_cmd_pos = 0;
midi_len = midi_lengths[(val >> 4) & 7];
midi_command[0] = midi_command[1] = midi_command[2] = 0;
}
if (midi_len && midi_cmd_pos < 3)
{
midi_command[midi_cmd_pos] = val;
midi_cmd_pos++;
#ifdef USE_ALLEGRO_MIDI
if (midi_cmd_pos == midi_len)
midi_out(midi_command, midi_len);
#endif
}
}

31
src/allegro-mouse.c Normal file
View File

@@ -0,0 +1,31 @@
#include "allegro-main.h"
#include "plat-mouse.h"
int mouse_buttons;
void mouse_init()
{
install_mouse();
}
void mouse_close()
{
}
void mouse_poll_host()
{
//poll_mouse();
mouse_buttons = mouse_b;
}
void mouse_get_mickeys(int *x, int *y)
{
if (mousecapture)
{
get_mouse_mickeys(x, y);
// position_mouse(64, 64);
}
else
*x = *y = 0;
}

127
src/allegro-video.c Normal file
View File

@@ -0,0 +1,127 @@
#include "allegro-main.h"
#include "ibm.h"
#include "video.h"
#include "allegro-video.h"
static PALETTE cgapal=
{
{0,0,0},{0,42,0},{42,0,0},{42,21,0},
{0,0,0},{0,42,42},{42,0,42},{42,42,42},
{0,0,0},{21,63,21},{63,21,21},{63,63,21},
{0,0,0},{21,63,63},{63,21,63},{63,63,63},
{0,0,0},{0,0,42},{0,42,0},{0,42,42},
{42,0,0},{42,0,42},{42,21,00},{42,42,42},
{21,21,21},{21,21,63},{21,63,21},{21,63,63},
{63,21,21},{63,21,63},{63,63,21},{63,63,63},
{0,0,0},{0,21,0},{0,0,42},{0,42,42},
{42,0,21},{21,10,21},{42,0,42},{42,0,63},
{21,21,21},{21,63,21},{42,21,42},{21,63,63},
{63,0,0},{42,42,0},{63,21,42},{41,41,41},
{0,0,0},{0,42,42},{42,0,0},{42,42,42},
{0,0,0},{0,42,42},{42,0,0},{42,42,42},
{0,0,0},{0,63,63},{63,0,0},{63,63,63},
{0,0,0},{0,63,63},{63,0,0},{63,63,63},
};
static uint32_t pal_lookup[256];
static void allegro_blit_memtoscreen(int x, int y, int y1, int y2, int w, int h);
static void allegro_blit_memtoscreen_8(int x, int y, int w, int h);
static BITMAP *buffer32_vscale;
void allegro_video_init()
{
int c;
set_color_depth(32);
set_gfx_mode(GFX_AUTODETECT_WINDOWED, 640, 480, 0, 0);
video_blit_memtoscreen = allegro_blit_memtoscreen;
video_blit_memtoscreen_8 = allegro_blit_memtoscreen_8;
for (c = 0; c < 256; c++)
pal_lookup[c] = makecol(cgapal[c].r << 2, cgapal[c].g << 2, cgapal[c].b << 2);
buffer32_vscale = create_bitmap(2048, 2048);
}
void allegro_video_close()
{
destroy_bitmap(buffer32_vscale);
}
void allegro_video_update_size(int x, int y)
{
if (set_gfx_mode(GFX_AUTODETECT_WINDOWED, x, y, 0, 0))
fatal("Failed to set gfx mode %i,%i : %s\n", x, y, allegro_error);
}
static void allegro_blit_memtoscreen(int x, int y, int y1, int y2, int w, int h)
{
if (h < winsizey)
{
int yy;
for (yy = y+y1; yy < y+y2; yy++)
{
if (yy >= 0)
{
memcpy(&((uint32_t *)buffer32_vscale->line[yy*2])[x], &((uint32_t *)buffer32->line[yy])[x], w*4);
memcpy(&((uint32_t *)buffer32_vscale->line[(yy*2)+1])[x], &((uint32_t *)buffer32->line[yy])[x], w*4);
}
}
blit(buffer32_vscale, screen, x, (y+y1)*2, 0, y1, w, (y2-y1)*2);
}
else
blit(buffer32, screen, x, y+y1, 0, y1, w, y2-y1);
}
static void allegro_blit_memtoscreen_8(int x, int y, int w, int h)
{
int xx, yy;
int line_double = (winsizey > h) ? 1 : 0;
if (y < 0)
{
h += y;
y = 0;
}
for (yy = y; yy < y+h; yy++)
{
int dy = line_double ? yy*2 : yy;
if (dy < buffer->h)
{
if (line_double)
{
for (xx = x; xx < x+w; xx++)
{
((uint32_t *)buffer32->line[dy])[xx] =
((uint32_t *)buffer32->line[dy + 1])[xx] = pal_lookup[buffer->line[yy][xx]];
}
}
else
{
for (xx = x; xx < x+w; xx++)
((uint32_t *)buffer32->line[dy])[xx] = pal_lookup[buffer->line[yy][xx]];
}
}
}
if (readflash)
{
if (line_double)
rectfill(buffer32, x+SCREEN_W-40, y*2+8, SCREEN_W-8, y*2+14, makecol(255, 255, 255));
else
rectfill(buffer32, x+SCREEN_W-40, y+8, SCREEN_W-8, y+14, makecol(255, 255, 255));
readflash = 0;
}
if (line_double)
blit(buffer32, screen, x, y*2, 0, 0, w, h*2);
else
blit(buffer32, screen, x, y, 0, 0, w, h);
}

3
src/allegro-video.h Normal file
View File

@@ -0,0 +1,3 @@
void allegro_video_init();
void allegro_video_close();
void allegro_video_update_size(int x, int y);

83
src/amstrad.c Normal file
View File

@@ -0,0 +1,83 @@
#include "ibm.h"
#include "io.h"
#include "keyboard.h"
#include "lpt.h"
#include "mouse.h"
#include "amstrad.h"
static uint8_t amstrad_dead;
uint8_t amstrad_read(uint16_t port, void *priv)
{
pclog("amstrad_read : %04X\n",port);
switch (port)
{
case 0x379:
return 7 | readdacfifo();
case 0x37a:
if (romset == ROM_PC1512) return 0x20;
if (romset == ROM_PC200) return 0x80;
return 0;
case 0xdead:
return amstrad_dead;
}
return 0xff;
}
void amstrad_write(uint16_t port, uint8_t val, void *priv)
{
switch (port)
{
case 0xdead:
amstrad_dead = val;
break;
}
}
static uint8_t mousex,mousey;
void amstrad_mouse_write(uint16_t addr, uint8_t val, void *priv)
{
// pclog("Write mouse %04X %02X %04X:%04X\n", addr, val, CS, pc);
if (addr==0x78) mousex=0;
else mousey=0;
}
uint8_t amstrad_mouse_read(uint16_t addr, void *priv)
{
// printf("Read mouse %04X %04X:%04X %02X\n", addr, CS, pc, (addr == 0x78) ? mousex : mousey);
if (addr==0x78) return mousex;
return mousey;
}
static int oldb = 0;
void amstrad_mouse_poll(int x, int y, int b)
{
mousex += x;
mousey -= y;
if ((b & 1) && !(oldb & 1))
keyboard_send(0x7e);
if ((b & 2) && !(oldb & 2))
keyboard_send(0x7d);
if (!(b & 1) && (oldb & 1))
keyboard_send(0xfe);
if (!(b & 2) && (oldb & 2))
keyboard_send(0xfd);
oldb = b;
}
void amstrad_init()
{
lpt2_remove_ams();
io_sethandler(0x0078, 0x0001, amstrad_mouse_read, NULL, NULL, amstrad_mouse_write, NULL, NULL, NULL);
io_sethandler(0x007a, 0x0001, amstrad_mouse_read, NULL, NULL, amstrad_mouse_write, NULL, NULL, NULL);
io_sethandler(0x0379, 0x0002, amstrad_read, NULL, NULL, NULL, NULL, NULL, NULL);
io_sethandler(0xdead, 0x0001, amstrad_read, NULL, NULL, amstrad_write, NULL, NULL, NULL);
mouse_poll = amstrad_mouse_poll;
}

2
src/amstrad.h Normal file
View File

@@ -0,0 +1,2 @@
void amstrad_init();

202
src/bswap.h Normal file
View File

@@ -0,0 +1,202 @@
#ifndef BSWAP_H
#define BSWAP_H
//#include "config-host.h"
#include <inttypes.h>
#ifdef HAVE_BYTESWAP_H
#include <byteswap.h>
#else
#define bswap_16(x) \
({ \
uint16_t __x = (x); \
((uint16_t)( \
(((uint16_t)(__x) & (uint16_t)0x00ffU) << 8) | \
(((uint16_t)(__x) & (uint16_t)0xff00U) >> 8) )); \
})
#define bswap_32(x) \
({ \
uint32_t __x = (x); \
((uint32_t)( \
(((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
(((uint32_t)(__x) & (uint32_t)0x0000ff00UL) << 8) | \
(((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >> 8) | \
(((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) )); \
})
#define bswap_64(x) \
({ \
uint64_t __x = (x); \
((uint64_t)( \
(uint64_t)(((uint64_t)(__x) & (uint64_t)0x00000000000000ffULL) << 56) | \
(uint64_t)(((uint64_t)(__x) & (uint64_t)0x000000000000ff00ULL) << 40) | \
(uint64_t)(((uint64_t)(__x) & (uint64_t)0x0000000000ff0000ULL) << 24) | \
(uint64_t)(((uint64_t)(__x) & (uint64_t)0x00000000ff000000ULL) << 8) | \
(uint64_t)(((uint64_t)(__x) & (uint64_t)0x000000ff00000000ULL) >> 8) | \
(uint64_t)(((uint64_t)(__x) & (uint64_t)0x0000ff0000000000ULL) >> 24) | \
(uint64_t)(((uint64_t)(__x) & (uint64_t)0x00ff000000000000ULL) >> 40) | \
(uint64_t)(((uint64_t)(__x) & (uint64_t)0xff00000000000000ULL) >> 56) )); \
})
#endif /* !HAVE_BYTESWAP_H */
static inline uint16_t bswap16(uint16_t x)
{
return bswap_16(x);
}
static inline uint32_t bswap32(uint32_t x)
{
return bswap_32(x);
}
static inline uint64_t bswap64(uint64_t x)
{
return bswap_64(x);
}
static inline void bswap16s(uint16_t *s)
{
*s = bswap16(*s);
}
static inline void bswap32s(uint32_t *s)
{
*s = bswap32(*s);
}
static inline void bswap64s(uint64_t *s)
{
*s = bswap64(*s);
}
#if defined(WORDS_BIGENDIAN)
#define be_bswap(v, size) (v)
#define le_bswap(v, size) bswap ## size(v)
#define be_bswaps(v, size)
#define le_bswaps(p, size) *p = bswap ## size(*p);
#else
#define le_bswap(v, size) (v)
#define be_bswap(v, size) bswap ## size(v)
#define le_bswaps(v, size)
#define be_bswaps(p, size) *p = bswap ## size(*p);
#endif
#define CPU_CONVERT(endian, size, type)\
static inline type endian ## size ## _to_cpu(type v)\
{\
return endian ## _bswap(v, size);\
}\
\
static inline type cpu_to_ ## endian ## size(type v)\
{\
return endian ## _bswap(v, size);\
}\
\
static inline void endian ## size ## _to_cpus(type *p)\
{\
endian ## _bswaps(p, size)\
}\
\
static inline void cpu_to_ ## endian ## size ## s(type *p)\
{\
endian ## _bswaps(p, size)\
}\
\
static inline type endian ## size ## _to_cpup(const type *p)\
{\
return endian ## size ## _to_cpu(*p);\
}\
\
static inline void cpu_to_ ## endian ## size ## w(type *p, type v)\
{\
*p = cpu_to_ ## endian ## size(v);\
}
CPU_CONVERT(be, 16, uint16_t)
CPU_CONVERT(be, 32, uint32_t)
CPU_CONVERT(be, 64, uint64_t)
CPU_CONVERT(le, 16, uint16_t)
CPU_CONVERT(le, 32, uint32_t)
CPU_CONVERT(le, 64, uint64_t)
/* unaligned versions (optimized for frequent unaligned accesses)*/
#if defined(__i386__) || defined(__powerpc__)
#define cpu_to_le16wu(p, v) cpu_to_le16w(p, v)
#define cpu_to_le32wu(p, v) cpu_to_le32w(p, v)
#define le16_to_cpupu(p) le16_to_cpup(p)
#define le32_to_cpupu(p) le32_to_cpup(p)
#define cpu_to_be16wu(p, v) cpu_to_be16w(p, v)
#define cpu_to_be32wu(p, v) cpu_to_be32w(p, v)
#else
static inline void cpu_to_le16wu(uint16_t *p, uint16_t v)
{
uint8_t *p1 = (uint8_t *)p;
p1[0] = v;
p1[1] = v >> 8;
}
static inline void cpu_to_le32wu(uint32_t *p, uint32_t v)
{
uint8_t *p1 = (uint8_t *)p;
p1[0] = v;
p1[1] = v >> 8;
p1[2] = v >> 16;
p1[3] = v >> 24;
}
static inline uint16_t le16_to_cpupu(const uint16_t *p)
{
const uint8_t *p1 = (const uint8_t *)p;
return p1[0] | (p1[1] << 8);
}
static inline uint32_t le32_to_cpupu(const uint32_t *p)
{
const uint8_t *p1 = (const uint8_t *)p;
return p1[0] | (p1[1] << 8) | (p1[2] << 16) | (p1[3] << 24);
}
static inline void cpu_to_be16wu(uint16_t *p, uint16_t v)
{
uint8_t *p1 = (uint8_t *)p;
p1[0] = v >> 8;
p1[1] = v;
}
static inline void cpu_to_be32wu(uint32_t *p, uint32_t v)
{
uint8_t *p1 = (uint8_t *)p;
p1[0] = v >> 24;
p1[1] = v >> 16;
p1[2] = v >> 8;
p1[3] = v;
}
#endif
#ifdef WORDS_BIGENDIAN
#define cpu_to_32wu cpu_to_be32wu
#else
#define cpu_to_32wu cpu_to_le32wu
#endif
#undef le_bswap
#undef be_bswap
#undef le_bswaps
#undef be_bswaps
#endif /* BSWAP_H */

724
src/cdrom-ioctl-linux.c Normal file
View File

@@ -0,0 +1,724 @@
/*Linux CD-ROM support via IOCTL*/
#include <linux/cdrom.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include "ibm.h"
#include "ide.h"
#include "cdrom-ioctl.h"
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[100];
static int first_track, last_track;
int old_cdrom_drive;
#define MSFtoLBA(m,s,f) (((((m*60)+s)*75)+f)-150)
enum
{
CD_STOPPED = 0,
CD_PLAYING,
CD_PAUSED
};
static int ioctl_cd_state = CD_STOPPED;
static uint32_t ioctl_cd_pos = 0, ioctl_cd_end = 0;
#define BUF_SIZE 32768
static int16_t cd_buffer[BUF_SIZE];
static int cd_buflen = 0;
void ioctl_audio_callback(int16_t *output, int len)
{
int fd;
struct cdrom_read_audio read_audio;
// pclog("Audio callback %08X %08X %i %i %i %04X %i\n", ioctl_cd_pos, ioctl_cd_end, ioctl_cd_state, cd_buflen, len, cd_buffer[4], GetTickCount());
if (ioctl_cd_state != CD_PLAYING)
{
memset(output, 0, len * 2);
return;
}
fd = open("/dev/cdrom", O_RDONLY|O_NONBLOCK);
if (fd <= 0)
{
memset(output, 0, len * 2);
return;
}
while (cd_buflen < len)
{
if (ioctl_cd_pos < ioctl_cd_end)
{
read_audio.addr.lba = ioctl_cd_pos - 150;
read_audio.addr_format = CDROM_LBA;
read_audio.nframes = 1;
read_audio.buf = (__u8 *)&cd_buffer[cd_buflen];
if (ioctl(fd, CDROMREADAUDIO, &read_audio) < 0)
{
// pclog("DeviceIoControl returned false\n");
memset(&cd_buffer[cd_buflen], 0, (BUF_SIZE - cd_buflen) * 2);
ioctl_cd_state = CD_STOPPED;
cd_buflen = len;
}
else
{
// pclog("DeviceIoControl returned true\n");
ioctl_cd_pos++;
cd_buflen += (2352 / 2);
}
}
else
{
memset(&cd_buffer[cd_buflen], 0, (BUF_SIZE - cd_buflen) * 2);
ioctl_cd_state = CD_STOPPED;
cd_buflen = len;
}
}
close(fd);
memcpy(output, cd_buffer, len * 2);
// for (c = 0; c < BUF_SIZE - len; c++)
// cd_buffer[c] = cd_buffer[c + cd_buflen];
memcpy(&cd_buffer[0], &cd_buffer[len], (BUF_SIZE - len) * 2);
cd_buflen -= len;
// pclog("Done %i\n", GetTickCount());
}
void ioctl_audio_stop()
{
ioctl_cd_state = CD_STOPPED;
}
static int get_track_nr(uint32_t pos)
{
int c;
int track = 0;
if (!tocvalid)
return 0;
for (c = first_track; c < last_track; c++)
{
uint32_t track_address = toc[c].cdte_addr.msf.frame +
(toc[c].cdte_addr.msf.second * 75) +
(toc[c].cdte_addr.msf.minute * 75 * 60);
//pclog("get_track_nr: track=%i pos=%x track_address=%x\n", c, pos, track_address);
if (track_address <= pos)
track = c;
}
return track;
}
static int is_track_audio(uint32_t pos)
{
int c;
int control = 0;
if (!tocvalid)
return 0;
for (c = first_track; c < last_track; c++)
{
uint32_t track_address = toc[c].cdte_addr.msf.frame +
(toc[c].cdte_addr.msf.second * 75) +
(toc[c].cdte_addr.msf.minute * 75 * 60);
//pclog("get_track_nr: track=%i pos=%x track_address=%x\n", c, pos, track_address);
if (track_address <= pos)
control = toc[c].cdte_ctrl;
}
return (control & 4) ? 0 : 1;
}
static int ioctl_is_track_audio(uint32_t pos, int ismsf)
{
if (ismsf)
{
int m = (pos >> 16) & 0xff;
int s = (pos >> 8) & 0xff;
int f = pos & 0xff;
pos = MSFtoLBA(m, s, f);
}
return is_track_audio(pos);
}
static void ioctl_playaudio(uint32_t pos, uint32_t len, int ismsf)
{
// pclog("Play audio - %08X %08X %i\n", pos, len, ismsf);
if (ismsf)
{
pos = (pos & 0xff) + (((pos >> 8) & 0xff) * 75) + (((pos >> 16) & 0xff) * 75 * 60);
len = (len & 0xff) + (((len >> 8) & 0xff) * 75) + (((len >> 16) & 0xff) * 75 * 60);
// pclog("MSF - pos = %08X len = %08X\n", pos, len);
}
else
len += pos;
ioctl_cd_pos = pos;// + 150;
ioctl_cd_end = pos+len;// + 150;
ioctl_cd_state = CD_PLAYING;
if (ioctl_cd_pos < 150)
ioctl_cd_pos = 150;
// pclog("Audio start %08X %08X %i %i %i\n", ioctl_cd_pos, ioctl_cd_end, ioctl_cd_state, 0, len);
}
static void ioctl_pause(void)
{
if (ioctl_cd_state == CD_PLAYING)
ioctl_cd_state = CD_PAUSED;
}
static void ioctl_resume(void)
{
if (ioctl_cd_state == CD_PAUSED)
ioctl_cd_state = CD_PLAYING;
}
static void ioctl_stop(void)
{
ioctl_cd_state = CD_STOPPED;
}
static void ioctl_seek(uint32_t pos)
{
// pclog("Seek %08X\n", pos);
ioctl_cd_pos = pos;
ioctl_cd_state = CD_STOPPED;
}
static int read_toc(int fd, struct cdrom_tocentry *btoc)
{
struct cdrom_tochdr toc_hdr;
int track, err;
//pclog("read_toc\n");
err = ioctl(fd, CDROMREADTOCHDR, &toc_hdr);
if (err == -1)
{
pclog("read_toc: CDROMREADTOCHDR failed\n");
return 0;
}
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));
for (track = toc_hdr.cdth_trk0; track <= toc_hdr.cdth_trk1; track++)
{
btoc[track].cdte_track = track;
btoc[track].cdte_format = CDROM_MSF;
err = ioctl(fd, CDROMREADTOCENTRY, &btoc[track]);
if (err == -1)
{
// pclog("read_toc: CDROMREADTOCENTRY failed on track %i\n", track);
return 0;
}
// pclog("read_toc: Track %02X - number %02X control %02X adr %02X address %02X %02X %02X %02X\n", track, toc[track].cdte_track, toc[track].cdte_ctrl, toc[track].cdte_adr, 0, toc[track].cdte_addr.msf.minute, toc[track].cdte_addr.msf.second, toc[track].cdte_addr.msf.frame);
}
return 1;
}
static int ioctl_ready(void)
{
long size;
int temp;
struct cdrom_tochdr toc_hdr;
struct cdrom_tocentry toc_entry;
int err;
int fd = open("/dev/cdrom", O_RDONLY|O_NONBLOCK);
if (fd <= 0)
return 0;
err = ioctl(fd, CDROMREADTOCHDR, &toc_hdr);
if (err == -1)
{
close(fd);
return 0;
}
// pclog("CDROMREADTOCHDR: start track=%i end track=%i\n", toc_hdr.cdth_trk0, toc_hdr.cdth_trk1);
toc_entry.cdte_track = toc_hdr.cdth_trk1;
toc_entry.cdte_format = CDROM_MSF;
err = ioctl(fd, CDROMREADTOCENTRY, &toc_entry);
if (err == -1)
{
close(fd);
return 0;
}
// pclog("CDROMREADTOCENTRY: addr=%02i:%02i:%02i\n", toc_entry.cdte_addr.msf.minute, toc_entry.cdte_addr.msf.second, toc_entry.cdte_addr.msf.frame);
if ((toc_entry.cdte_addr.msf.minute != toc[toc_hdr.cdth_trk1].cdte_addr.msf.minute) ||
(toc_entry.cdte_addr.msf.second != toc[toc_hdr.cdth_trk1].cdte_addr.msf.second) ||
(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(fd, toc);
close(fd);
return 1;
}
close(fd);
return 1;
}
static int ioctl_get_last_block(unsigned char starttrack, int msf, int maxlen, int single)
{
int c;
int lb = 0;
int tv = 0;
struct cdrom_tocentry lbtoc[100];
int fd = open("/dev/cdrom", O_RDONLY|O_NONBLOCK);
if (fd <= 0)
return 0;
ioctl_cd_state = CD_STOPPED;
tv = read_toc(fd, lbtoc);
close(fd);
if (!tv)
return 0;
last_block = 0;
for (c = 0; c <= last_track; c++)
{
uint32_t address;
address = MSFtoLBA(toc[c].cdte_addr.msf.minute, toc[c].cdte_addr.msf.second, toc[c].cdte_addr.msf.frame);
if (address > last_block)
lb = address;
}
return lb;
}
static int ioctl_medium_changed(void)
{
long size;
int temp;
struct cdrom_tochdr toc_hdr;
struct cdrom_tocentry toc_entry;
int err;
int fd = open("/dev/cdrom", O_RDONLY|O_NONBLOCK);
if (fd <= 0)
return 0;
err = ioctl(fd, CDROMREADTOCHDR, &toc_hdr);
if (err == -1)
{
close(fd);
return 0;
}
toc_entry.cdte_track = toc_hdr.cdth_trk1;
toc_entry.cdte_format = CDROM_MSF;
err = ioctl(fd, CDROMREADTOCENTRY, &toc_entry);
if (err == -1)
{
close(fd);
return 0;
}
// pclog("CDROMREADTOCENTRY: addr=%02i:%02i:%02i\n", toc_entry.cdte_addr.msf.minute, toc_entry.cdte_addr.msf.second, toc_entry.cdte_addr.msf.frame);
if ((toc_entry.cdte_addr.msf.minute != toc[toc_hdr.cdth_trk1].cdte_addr.msf.minute) ||
(toc_entry.cdte_addr.msf.second != toc[toc_hdr.cdth_trk1].cdte_addr.msf.second) ||
(toc_entry.cdte_addr.msf.frame != toc[toc_hdr.cdth_trk1].cdte_addr.msf.frame ))
{
cdrom_capacity = ioctl_get_last_block(0, 0, 4096, 0);
return 1;
}
return 0;
}
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)
ret = 0x11;
else if (ioctl_cd_state == CD_PAUSED)
ret = 0x12;
else
ret = 0x13;
b[pos++] = (toc[track].cdte_adr << 4) | toc[track].cdte_ctrl;
b[pos++] = track;
b[pos++] = 0;
if (msf)
{
uint32_t dat = cdpos;
b[pos + 3] = (uint8_t)(dat % 75); dat /= 75;
b[pos + 2] = (uint8_t)(dat % 60); dat /= 60;
b[pos + 1] = (uint8_t)dat;
b[pos] = 0;
pos += 4;
dat = cdpos - track_address;
b[pos + 3] = (uint8_t)(dat % 75); dat /= 75;
b[pos + 2] = (uint8_t)(dat % 60); dat /= 60;
b[pos + 1] = (uint8_t)dat;
b[pos] = 0;
pos += 4;
}
else
{
b[pos++] = (cdpos >> 24) & 0xff;
b[pos++] = (cdpos >> 16) & 0xff;
b[pos++] = (cdpos >> 8) & 0xff;
b[pos++] = cdpos & 0xff;
cdpos -= track_address;
b[pos++] = (cdpos >> 24) & 0xff;
b[pos++] = (cdpos >> 16) & 0xff;
b[pos++] = (cdpos >> 8) & 0xff;
b[pos++] = cdpos & 0xff;
}
return ret;
}
static void ioctl_eject(void)
{
int fd = open("/dev/cdrom", O_RDONLY|O_NONBLOCK);
if (fd <= 0)
return;
ioctl(fd, CDROMEJECT);
close(fd);
}
static void ioctl_load(void)
{
int fd = open("/dev/cdrom", O_RDONLY|O_NONBLOCK);
if (fd <= 0)
return;
ioctl(fd, CDROMEJECT);
close(fd);
cdrom_capacity = ioctl_get_last_block(0, 0, 4096, 0);
}
static void ioctl_readsector(uint8_t *b, int sector)
{
int cdrom = open("/dev/cdrom", O_RDONLY|O_NONBLOCK);
if (cdrom <= 0)
return;
lseek(cdrom, sector*2048, SEEK_SET);
read(cdrom, b, 2048);
close(cdrom);
}
union
{
struct cdrom_msf *msf;
char b[CD_FRAMESIZE_RAW];
} raw_read_params;
static int lba_to_msf(int lba)
{
return (((lba / 75) / 60) << 16) + (((lba / 75) % 60) << 8) + (lba % 75);
}
static void ioctl_readsector_raw(uint8_t *b, int sector)
{
int err;
int imsf = lba_to_msf(sector);
int cdrom = open("/dev/cdrom", O_RDONLY|O_NONBLOCK);
if (cdrom <= 0)
return;
raw_read_params.msf = malloc(sizeof(struct cdrom_msf));
raw_read_params.msf->cdmsf_frame0 = imsf & 0xff;
raw_read_params.msf->cdmsf_sec0 = (imsf >> 8) & 0xff;
raw_read_params.msf->cdmsf_min0 = (imsf >> 16) & 0xff;
/* This will read the actual raw sectors from the disc. */
err = ioctl(cdrom, CDROMREADRAW, (void *) &raw_read_params);
if (err == -1)
{
pclog("read_toc: CDROMREADTOCHDR failed\n");
return;
}
memcpy(b, raw_read_params.b, 2352);
close(cdrom);
free(raw_read_params.msf);
}
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;
int fd = open("/dev/cdrom", O_RDONLY|O_NONBLOCK);
if (fd <= 0)
return 0;
ioctl_cd_state = CD_STOPPED;
tocvalid = read_toc(fd, toc);
close(fd);
if (!tocvalid)
return 4;
// pclog("Read TOC done! %i\n",single);
b[2] = first_track;
b[3] = last_track;
d = 0;
//pclog("Read TOC starttrack=%i\n", starttrack);
for (c = 1; c <= last_track; c++)
{
if (toc[c].cdte_track >= starttrack)
{
d = c;
break;
}
}
b[2] = toc[c].cdte_track;
last_block = 0;
for (c = d; c <= last_track; c++)
{
uint32_t address;
if ((len + 8) > maxlen)
break;
// pclog("Len %i max %i Track %02X - %02X %02X %02i:%02i:%02i %08X\n",len,maxlen,toc[c].cdte_track,toc[c].cdte_adr,toc[c].cdte_ctrl,toc[c].cdte_addr.msf.minute, toc[c].cdte_addr.msf.second, toc[c].cdte_addr.msf.frame,MSFtoLBA(toc[c].cdte_addr.msf.minute, toc[c].cdte_addr.msf.second, toc[c].cdte_addr.msf.frame));
b[len++] = 0; /*Reserved*/
b[len++] = (toc[c].cdte_adr << 4) | toc[c].cdte_ctrl;
b[len++] = toc[c].cdte_track;
b[len++] = 0; /*Reserved*/
address = MSFtoLBA(toc[c].cdte_addr.msf.minute, toc[c].cdte_addr.msf.second, toc[c].cdte_addr.msf.frame);
if (address > last_block)
last_block = address;
if (msf)
{
b[len++] = 0;
b[len++] = toc[c].cdte_addr.msf.minute;
b[len++] = toc[c].cdte_addr.msf.second;
b[len++] = toc[c].cdte_addr.msf.frame;
}
else
{
temp = MSFtoLBA(toc[c].cdte_addr.msf.minute, toc[c].cdte_addr.msf.second, toc[c].cdte_addr.msf.frame);
b[len++] = temp >> 24;
b[len++] = temp >> 16;
b[len++] = temp >> 8;
b[len++] = temp;
}
if (single)
break;
}
b[0] = (uint8_t)(((len-2) >> 8) & 0xff);
b[1] = (uint8_t)((len-2) & 0xff);
/* pclog("Table of Contents (%i bytes) : \n", size);
pclog("First track - %02X\n", first_track);
pclog("Last track - %02X\n", last_track);
for (c = 0; c <= last_track; c++)
pclog("Track %02X - number %02X control %02X adr %02X address %02X %02X %02X %02X\n", c, toc[c].cdte_track, toc[c].cdte_ctrl, toc[c].cdte_adr, 0, toc[c].cdte_addr.msf.minute, toc[c].cdte_addr.msf.second, toc[c].cdte_addr.msf.frame);
for (c = 0;c <= last_track; c++)
pclog("Track %02X - number %02X control %02X adr %02X address %06X\n", c, toc[c].cdte_track, toc[c].cdte_ctrl, toc[c].cdte_adr, MSFtoLBA(toc[c].cdte_addr.msf.minute, toc[c].cdte_addr.msf.second, toc[c].cdte_addr.msf.frame));*/
return len;
}
static int ioctl_readtoc_session(unsigned char *b, int msf, int maxlen)
{
struct cdrom_multisession session;
int len = 4;
int err;
int fd = open("/dev/cdrom", O_RDONLY|O_NONBLOCK);
if (fd <= 0)
return 0;
session.addr_format = CDROM_MSF;
err = ioctl(fd, CDROMMULTISESSION, &session);
if (err == -1)
{
close(fd);
return 0;
}
b[2] = 0;
b[3] = 0;
b[len++] = 0; /*Reserved*/
b[len++] = (toc[0].cdte_adr << 4) | toc[0].cdte_ctrl;
b[len++] = toc[0].cdte_track;
b[len++] = 0; /*Reserved*/
if (msf)
{
b[len++] = 0;
b[len++] = session.addr.msf.minute;
b[len++] = session.addr.msf.second;
b[len++] = session.addr.msf.frame;
}
else
{
uint32_t temp = MSFtoLBA(session.addr.msf.minute, session.addr.msf.second, session.addr.msf.frame);
b[len++] = temp >> 24;
b[len++] = temp >> 16;
b[len++] = temp >> 8;
b[len++] = temp;
}
return len;
}
static int ioctl_readtoc_raw(unsigned char *b, int maxlen)
{
struct cdrom_tochdr toc_hdr;
struct cdrom_tocentry toc2[100];
int track, err;
int len = 4;
int fd = open("/dev/cdrom", O_RDONLY|O_NONBLOCK);
//pclog("read_toc\n");
if (fd <= 0)
return 0;
err = ioctl(fd, CDROMREADTOCHDR, &toc_hdr);
if (err == -1)
{
pclog("read_toc: CDROMREADTOCHDR failed\n");
return 0;
}
b[2] = toc_hdr.cdth_trk0;
b[3] = toc_hdr.cdth_trk1;
//pclog("read_toc: first_track=%i last_track=%i\n", first_track, last_track);
memset(toc, 0, sizeof(toc));
for (track = toc_hdr.cdth_trk0; track <= toc_hdr.cdth_trk1; track++)
{
if ((len + 11) > maxlen)
{
pclog("ioctl_readtocraw: This iteration would fill the buffer beyond the bounds, aborting...\n");
close(fd);
return len;
}
toc2[track].cdte_track = track;
toc2[track].cdte_format = CDROM_MSF;
err = ioctl(fd, CDROMREADTOCENTRY, &toc2[track]);
if (err == -1)
{
// pclog("read_toc: CDROMREADTOCENTRY failed on track %i\n", track);
close(fd);
return 0;
}
// pclog("read_toc: Track %02X - number %02X control %02X adr %02X address %02X %02X %02X %02X\n", track, toc[track].cdte_track, toc[track].cdte_ctrl, toc[track].cdte_adr, 0, toc[track].cdte_addr.msf.minute, toc[track].cdte_addr.msf.second, toc[track].cdte_addr.msf.frame);
b[len++] = toc2[track].cdte_track;
b[len++]= (toc2[track].cdte_adr << 4) | toc[track].cdte_ctrl;
b[len++]=0;
b[len++]=0;
b[len++]=0;
b[len++]=0;
b[len++]=0;
b[len++]=0;
b[len++] = toc2[track].cdte_addr.msf.minute;
b[len++] = toc2[track].cdte_addr.msf.second;
b[len++] = toc2[track].cdte_addr.msf.frame;
}
close(fd);
return len;
}
static uint32_t ioctl_size()
{
return cdrom_capacity;
}
static int ioctl_status()
{
if (!(ioctl_ready) && (cdrom_drive <= 0)) return CD_STATUS_EMPTY;
switch(ioctl_cd_state)
{
case CD_PLAYING:
return CD_STATUS_PLAYING;
case CD_PAUSED:
return CD_STATUS_PAUSED;
case CD_STOPPED:
return CD_STATUS_STOPPED;
}
}
void ioctl_reset()
{
int fd = open("/dev/cdrom", O_RDONLY|O_NONBLOCK);
//pclog("ioctl_reset: fd=%i\n", fd);
tocvalid = 0;
if (fd <= 0)
return;
tocvalid = read_toc(fd, toc);
close(fd);
}
int ioctl_open(char d)
{
atapi=&ioctl_atapi;
return 0;
}
void ioctl_close(void)
{
}
static void ioctl_exit(void)
{
ioctl_stop();
ioctl_inited = 0;
tocvalid=0;
}
static ATAPI ioctl_atapi=
{
ioctl_ready,
ioctl_medium_changed,
ioctl_readtoc,
ioctl_readtoc_session,
ioctl_readtoc_raw,
ioctl_getcurrentsubchannel,
ioctl_readsector,
ioctl_readsector_raw,
ioctl_playaudio,
ioctl_seek,
ioctl_load,
ioctl_eject,
ioctl_pause,
ioctl_resume,
ioctl_size,
ioctl_status,
ioctl_is_track_audio,
ioctl_stop,
ioctl_exit
};

747
src/cdrom-ioctl.c Normal file
View File

@@ -0,0 +1,747 @@
/*Win32 CD-ROM support via IOCTL*/
#include <windows.h>
#include <io.h>
#include "ntddcdrm.h"
#include "ibm.h"
#include "ide.h"
#include "cdrom-ioctl.h"
int cdrom_drive;
int old_cdrom_drive;
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];
void ioctl_close(void);
static HANDLE hIOCTL;
static CDROM_TOC toc;
static int tocvalid = 0;
// #define MSFtoLBA(m,s,f) (((((m*60)+s)*75)+f)-150)
/* The addresses sent from the guest are absolute, ie. a LBA of 0 corresponds to a MSF of 00:00:00. Otherwise, the counter displayed by the guest is wrong:
there is a seeming 2 seconds in which audio plays but counter does not move, while a data track before audio jumps to 2 seconds before the actual start
of the audio while audio still plays. With an absolute conversion, the counter is fine. */
#define MSFtoLBA(m,s,f) ((((m*60)+s)*75)+f)
enum
{
CD_STOPPED = 0,
CD_PLAYING,
CD_PAUSED
};
static int ioctl_cd_state = CD_STOPPED;
static uint32_t ioctl_cd_pos = 0, ioctl_cd_end = 0;
#define BUF_SIZE 32768
static int16_t cd_buffer[BUF_SIZE];
static int cd_buflen = 0;
void ioctl_audio_callback(int16_t *output, int len)
{
RAW_READ_INFO in;
DWORD count;
// return;
// pclog("Audio callback %08X %08X %i %i %i %04X %i\n", ioctl_cd_pos, ioctl_cd_end, ioctl_cd_state, cd_buflen, len, cd_buffer[4], GetTickCount());
if (ioctl_cd_state != CD_PLAYING)
{
memset(output, 0, len * 2);
return;
}
while (cd_buflen < len)
{
if (ioctl_cd_pos < ioctl_cd_end)
{
in.DiskOffset.LowPart = (ioctl_cd_pos - 150) * 2048;
in.DiskOffset.HighPart = 0;
in.SectorCount = 1;
in.TrackMode = CDDA;
ioctl_open(0);
// pclog("Read to %i\n", cd_buflen);
if (!DeviceIoControl(hIOCTL, IOCTL_CDROM_RAW_READ, &in, sizeof(in), &cd_buffer[cd_buflen], 2352, &count, NULL))
{
// pclog("DeviceIoControl returned false\n");
memset(&cd_buffer[cd_buflen], 0, (BUF_SIZE - cd_buflen) * 2);
ioctl_cd_state = CD_STOPPED;
cd_buflen = len;
}
else
{
// pclog("DeviceIoControl returned true\n");
ioctl_cd_pos++;
cd_buflen += (2352 / 2);
}
ioctl_close();
}
else
{
memset(&cd_buffer[cd_buflen], 0, (BUF_SIZE - cd_buflen) * 2);
ioctl_cd_state = CD_STOPPED;
cd_buflen = len;
}
}
memcpy(output, cd_buffer, len * 2);
// for (c = 0; c < BUF_SIZE - len; c++)
// cd_buffer[c] = cd_buffer[c + cd_buflen];
memcpy(&cd_buffer[0], &cd_buffer[len], (BUF_SIZE - len) * 2);
cd_buflen -= len;
// pclog("Done %i\n", GetTickCount());
}
void ioctl_audio_stop()
{
ioctl_cd_state = CD_STOPPED;
}
static int get_track_nr(uint32_t pos)
{
int c;
int track = 0;
if (!tocvalid)
return 0;
for (c = toc.FirstTrack; c < toc.LastTrack; c++)
{
uint32_t track_address = toc.TrackData[c].Address[3] +
(toc.TrackData[c].Address[2] * 75) +
(toc.TrackData[c].Address[1] * 75 * 60);
if (track_address <= pos)
track = c;
}
return track;
}
static void ioctl_playaudio(uint32_t pos, uint32_t len, int ismsf)
{
if (!cdrom_drive) return;
pclog("Play audio - %08X %08X %i\n", pos, len, ismsf);
if (ismsf)
{
int m = (pos >> 16) & 0xff;
int s = (pos >> 8) & 0xff;
int f = pos & 0xff;
pos = MSFtoLBA(m, s, f);
m = (len >> 16) & 0xff;
s = (len >> 8) & 0xff;
f = len & 0xff;
len = MSFtoLBA(m, s, f);
pclog("MSF - pos = %08X len = %08X\n", pos, len);
}
else
len += pos;
ioctl_cd_pos = pos;// + 150;
ioctl_cd_end = len;// + 150;
if (ioctl_cd_pos < 150)
{
/* Adjust because the host expects a minimum adjusted LBA of 0 which is equivalent to an absolute LBA of 150. */
ioctl_cd_pos = 150;
}
ioctl_cd_state = CD_PLAYING;
pclog("Audio start %08X %08X %i %i %i\n", ioctl_cd_pos, ioctl_cd_end, ioctl_cd_state, cd_buflen, len);
/* CDROM_PLAY_AUDIO_MSF msf;
long size;
BOOL b;
if (ismsf)
{
msf.StartingF=pos&0xFF;
msf.StartingS=(pos>>8)&0xFF;
msf.StartingM=(pos>>16)&0xFF;
msf.EndingF=len&0xFF;
msf.EndingS=(len>>8)&0xFF;
msf.EndingM=(len>>16)&0xFF;
}
else
{
msf.StartingF=(uint8_t)(addr%75); addr/=75;
msf.StartingS=(uint8_t)(addr%60); addr/=60;
msf.StartingM=(uint8_t)(addr);
addr=pos+len+150;
msf.EndingF=(uint8_t)(addr%75); addr/=75;
msf.EndingS=(uint8_t)(addr%60); addr/=60;
msf.EndingM=(uint8_t)(addr);
}
ioctl_open(0);
b = DeviceIoControl(hIOCTL,IOCTL_CDROM_PLAY_AUDIO_MSF,&msf,sizeof(msf),NULL,0,&size,NULL);
pclog("DeviceIoControl returns %i\n", (int) b);
ioctl_close();*/
}
static void ioctl_pause(void)
{
if (!cdrom_drive) return;
if (ioctl_cd_state == CD_PLAYING)
ioctl_cd_state = CD_PAUSED;
// ioctl_open(0);
// DeviceIoControl(hIOCTL,IOCTL_CDROM_PAUSE_AUDIO,NULL,0,NULL,0,&size,NULL);
// ioctl_close();
}
static void ioctl_resume(void)
{
if (!cdrom_drive) return;
if (ioctl_cd_state == CD_PAUSED)
ioctl_cd_state = CD_PLAYING;
// ioctl_open(0);
// DeviceIoControl(hIOCTL,IOCTL_CDROM_RESUME_AUDIO,NULL,0,NULL,0,&size,NULL);
// ioctl_close();
}
static void ioctl_stop(void)
{
if (!cdrom_drive) return;
ioctl_cd_state = CD_STOPPED;
// ioctl_open(0);
// DeviceIoControl(hIOCTL,IOCTL_CDROM_STOP_AUDIO,NULL,0,NULL,0,&size,NULL);
// ioctl_close();
}
static void ioctl_seek(uint32_t pos)
{
if (!cdrom_drive) return;
// ioctl_cd_state = CD_STOPPED;
pclog("Seek %08X\n", pos);
ioctl_cd_pos = pos;
ioctl_cd_state = CD_STOPPED;
/* pos+=150;
CDROM_SEEK_AUDIO_MSF msf;
msf.F=(uint8_t)(pos%75); pos/=75;
msf.S=(uint8_t)(pos%60); pos/=60;
msf.M=(uint8_t)(pos);
// pclog("Seek to %02i:%02i:%02i\n",msf.M,msf.S,msf.F);
ioctl_open(0);
DeviceIoControl(hIOCTL,IOCTL_CDROM_SEEK_AUDIO_MSF,&msf,sizeof(msf),NULL,0,&size,NULL);
ioctl_close();*/
}
static int ioctl_ready(void)
{
long size;
int temp;
CDROM_TOC ltoc;
// pclog("Ready? %i\n",cdrom_drive);
if (!cdrom_drive) return 0;
ioctl_open(0);
temp=DeviceIoControl(hIOCTL,IOCTL_CDROM_READ_TOC, NULL,0,&ltoc,sizeof(ltoc),&size,NULL);
ioctl_close();
if (!temp)
return 0;
//pclog("ioctl_ready(): Drive opened successfully\n");
//if ((cdrom_drive != old_cdrom_drive)) pclog("Drive has changed\n");
if ((ltoc.TrackData[ltoc.LastTrack].Address[1] != toc.TrackData[toc.LastTrack].Address[1]) ||
(ltoc.TrackData[ltoc.LastTrack].Address[2] != toc.TrackData[toc.LastTrack].Address[2]) ||
(ltoc.TrackData[ltoc.LastTrack].Address[3] != toc.TrackData[toc.LastTrack].Address[3]) ||
!tocvalid || (cdrom_drive != old_cdrom_drive))
{
//pclog("ioctl_ready(): Disc or drive changed\n");
ioctl_cd_state = CD_STOPPED;
/* pclog("Not ready %02X %02X %02X %02X %02X %02X %i\n",ltoc.TrackData[ltoc.LastTrack].Address[1],ltoc.TrackData[ltoc.LastTrack].Address[2],ltoc.TrackData[ltoc.LastTrack].Address[3],
toc.TrackData[ltoc.LastTrack].Address[1], toc.TrackData[ltoc.LastTrack].Address[2], toc.TrackData[ltoc.LastTrack].Address[3],tocvalid);*/
// atapi_discchanged();
/* ioctl_open(0);
temp=DeviceIoControl(hIOCTL,IOCTL_CDROM_READ_TOC, NULL,0,&toc,sizeof(toc),&size,NULL);
ioctl_close();*/
if (cdrom_drive != old_cdrom_drive)
old_cdrom_drive = cdrom_drive;
return 1;
}
// pclog("IOCTL says ready\n");
// pclog("ioctl_ready(): All is good\n");
return 1;
}
static int ioctl_get_last_block(unsigned char starttrack, int msf, int maxlen, int single)
{
int len=4;
long size;
int c,d;
uint32_t temp;
CDROM_TOC lbtoc;
int lb=0;
if (!cdrom_drive) return 0;
ioctl_cd_state = CD_STOPPED;
pclog("ioctl_readtoc(): IOCtl state now CD_STOPPED\n");
ioctl_open(0);
DeviceIoControl(hIOCTL,IOCTL_CDROM_READ_TOC, NULL,0,&lbtoc,sizeof(lbtoc),&size,NULL);
ioctl_close();
tocvalid=1;
for (c=d;c<=lbtoc.LastTrack;c++)
{
uint32_t address;
address = MSFtoLBA(toc.TrackData[c].Address[1],toc.TrackData[c].Address[2],toc.TrackData[c].Address[3]);
if (address > lb)
lb = address;
}
return lb;
}
static int ioctl_medium_changed(void)
{
long size;
int temp;
CDROM_TOC ltoc;
if (!cdrom_drive) return 0; /* This will be handled by the not ready handler instead. */
ioctl_open(0);
temp=DeviceIoControl(hIOCTL,IOCTL_CDROM_READ_TOC, NULL,0,&ltoc,sizeof(ltoc),&size,NULL);
ioctl_close();
if (!temp)
return 0; /* Drive empty, a not ready handler matter, not disc change. */
if (!tocvalid || (cdrom_drive != old_cdrom_drive))
{
ioctl_cd_state = CD_STOPPED;
toc = ltoc;
tocvalid = 1;
if (cdrom_drive != old_cdrom_drive)
old_cdrom_drive = cdrom_drive;
cdrom_capacity = ioctl_get_last_block(0, 0, 4096, 0);
return 0;
}
if ((ltoc.TrackData[ltoc.LastTrack].Address[1] != toc.TrackData[toc.LastTrack].Address[1]) ||
(ltoc.TrackData[ltoc.LastTrack].Address[2] != toc.TrackData[toc.LastTrack].Address[2]) ||
(ltoc.TrackData[ltoc.LastTrack].Address[3] != toc.TrackData[toc.LastTrack].Address[3]))
{
ioctl_cd_state = CD_STOPPED;
toc = ltoc;
cdrom_capacity = ioctl_get_last_block(0, 0, 4096, 0);
return 1; /* TOC mismatches. */
}
return 0; /* None of the above, return 0. */
}
static uint8_t ioctl_getcurrentsubchannel(uint8_t *b, int msf)
{
CDROM_SUB_Q_DATA_FORMAT insub;
SUB_Q_CHANNEL_DATA sub;
long size;
int pos=0;
if (!cdrom_drive) return 0;
insub.Format = IOCTL_CDROM_CURRENT_POSITION;
ioctl_open(0);
DeviceIoControl(hIOCTL,IOCTL_CDROM_READ_Q_CHANNEL,&insub,sizeof(insub),&sub,sizeof(sub),&size,NULL);
ioctl_close();
if (ioctl_cd_state == CD_PLAYING || ioctl_cd_state == CD_PAUSED)
{
uint32_t cdpos = ioctl_cd_pos;
int track = get_track_nr(cdpos);
uint32_t track_address = toc.TrackData[track].Address[3] +
(toc.TrackData[track].Address[2] * 75) +
(toc.TrackData[track].Address[1] * 75 * 60);
b[pos++] = sub.CurrentPosition.Control;
b[pos++] = track + 1;
b[pos++] = sub.CurrentPosition.IndexNumber;
if (msf)
{
uint32_t dat = cdpos;
b[pos + 3] = (uint8_t)(dat % 75); dat /= 75;
b[pos + 2] = (uint8_t)(dat % 60); dat /= 60;
b[pos + 1] = (uint8_t)dat;
b[pos] = 0;
pos += 4;
dat = cdpos - track_address;
b[pos + 3] = (uint8_t)(dat % 75); dat /= 75;
b[pos + 2] = (uint8_t)(dat % 60); dat /= 60;
b[pos + 1] = (uint8_t)dat;
b[pos] = 0;
pos += 4;
}
else
{
b[pos++] = (cdpos >> 24) & 0xff;
b[pos++] = (cdpos >> 16) & 0xff;
b[pos++] = (cdpos >> 8) & 0xff;
b[pos++] = cdpos & 0xff;
cdpos -= track_address;
b[pos++] = (cdpos >> 24) & 0xff;
b[pos++] = (cdpos >> 16) & 0xff;
b[pos++] = (cdpos >> 8) & 0xff;
b[pos++] = cdpos & 0xff;
}
if (ioctl_cd_state == CD_PLAYING) return 0x11;
return 0x12;
}
b[pos++]=sub.CurrentPosition.Control;
b[pos++]=sub.CurrentPosition.TrackNumber;
b[pos++]=sub.CurrentPosition.IndexNumber;
if (msf)
{
int c;
for (c = 0; c < 4; c++)
b[pos++] = sub.CurrentPosition.AbsoluteAddress[c];
for (c = 0; c < 4; c++)
b[pos++] = sub.CurrentPosition.TrackRelativeAddress[c];
}
else
{
uint32_t temp = MSFtoLBA(sub.CurrentPosition.AbsoluteAddress[1], sub.CurrentPosition.AbsoluteAddress[2], sub.CurrentPosition.AbsoluteAddress[3]);
b[pos++] = temp >> 24;
b[pos++] = temp >> 16;
b[pos++] = temp >> 8;
b[pos++] = temp;
temp = MSFtoLBA(sub.CurrentPosition.TrackRelativeAddress[1], sub.CurrentPosition.TrackRelativeAddress[2], sub.CurrentPosition.TrackRelativeAddress[3]);
b[pos++] = temp >> 24;
b[pos++] = temp >> 16;
b[pos++] = temp >> 8;
b[pos++] = temp;
}
return 0x13;
}
static void ioctl_eject(void)
{
long size;
if (!cdrom_drive) return;
ioctl_cd_state = CD_STOPPED;
ioctl_open(0);
DeviceIoControl(hIOCTL,IOCTL_STORAGE_EJECT_MEDIA,NULL,0,NULL,0,&size,NULL);
ioctl_close();
}
static void ioctl_load(void)
{
long size;
if (!cdrom_drive) return;
ioctl_cd_state = CD_STOPPED;
ioctl_open(0);
DeviceIoControl(hIOCTL,IOCTL_STORAGE_LOAD_MEDIA,NULL,0,NULL,0,&size,NULL);
ioctl_close();
cdrom_capacity = ioctl_get_last_block(0, 0, 4096, 0);
}
static void ioctl_readsector(uint8_t *b, int sector)
{
LARGE_INTEGER pos;
long size;
if (!cdrom_drive) return;
if (ioctl_cd_state == CD_PLAYING)
return;
ioctl_cd_state = CD_STOPPED;
pos.QuadPart=sector*2048;
ioctl_open(0);
SetFilePointer(hIOCTL,pos.LowPart,&pos.HighPart,FILE_BEGIN);
ReadFile(hIOCTL,b,2048,&size,NULL);
ioctl_close();
}
static int is_track_audio(uint32_t pos)
{
int c;
int control = 0;
if (!tocvalid)
return 0;
for (c = toc.FirstTrack; c < toc.LastTrack; c++)
{
uint32_t track_address = toc.TrackData[c].Address[3] +
(toc.TrackData[c].Address[2] * 75) +
(toc.TrackData[c].Address[1] * 75 * 60);
if (track_address <= pos)
control = toc.TrackData[c].Control;
}
return (control & 4) ? 0 : 1;
}
static int ioctl_is_track_audio(uint32_t pos, int ismsf)
{
if (ismsf)
{
int m = (pos >> 16) & 0xff;
int s = (pos >> 8) & 0xff;
int f = pos & 0xff;
pos = MSFtoLBA(m, s, f);
}
return is_track_audio(pos);
}
static void ioctl_readsector_raw(uint8_t *b, int sector)
{
LARGE_INTEGER pos;
long size;
uint32_t temp;
if (!cdrom_drive) return;
if (ioctl_cd_state == CD_PLAYING)
return;
ioctl_cd_state = CD_STOPPED;
pos.QuadPart=sector*2048; /* Yes, 2048, the API specifies that. */
ioctl_open(0);
/* This should read the actual raw sectors from the disc. */
DeviceIoControl( hIOCTL, IOCTL_CDROM_RAW_READ, NULL, 0, b, 1, &size, NULL );
ioctl_close();
}
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;
if (!cdrom_drive) return 0;
ioctl_cd_state = CD_STOPPED;
ioctl_open(0);
DeviceIoControl(hIOCTL,IOCTL_CDROM_READ_TOC, NULL,0,&toc,sizeof(toc),&size,NULL);
ioctl_close();
tocvalid=1;
// pclog("Read TOC done! %i\n",single);
b[2]=toc.FirstTrack;
b[3]=toc.LastTrack;
d=0;
for (c=0;c<=toc.LastTrack;c++)
{
if (toc.TrackData[c].TrackNumber>=starttrack)
{
d=c;
break;
}
}
b[2]=toc.TrackData[c].TrackNumber;
last_block = 0;
for (c=d;c<=toc.LastTrack;c++)
{
uint32_t address;
if ((len+8)>maxlen) break;
// pclog("Len %i max %i Track %02X - %02X %02X %i %i %i %i %08X\n",len,maxlen,toc.TrackData[c].TrackNumber,toc.TrackData[c].Adr,toc.TrackData[c].Control,toc.TrackData[c].Address[0],toc.TrackData[c].Address[1],toc.TrackData[c].Address[2],toc.TrackData[c].Address[3],MSFtoLBA(toc.TrackData[c].Address[1],toc.TrackData[c].Address[2],toc.TrackData[c].Address[3]));
b[len++]=0; /*Reserved*/
b[len++]=(toc.TrackData[c].Adr<<4)|toc.TrackData[c].Control;
b[len++]=toc.TrackData[c].TrackNumber;
b[len++]=0; /*Reserved*/
address = MSFtoLBA(toc.TrackData[c].Address[1],toc.TrackData[c].Address[2],toc.TrackData[c].Address[3]);
if (address > last_block)
last_block = address;
if (msf)
{
b[len++]=toc.TrackData[c].Address[0];
b[len++]=toc.TrackData[c].Address[1];
b[len++]=toc.TrackData[c].Address[2];
b[len++]=toc.TrackData[c].Address[3];
}
else
{
temp=MSFtoLBA(toc.TrackData[c].Address[1],toc.TrackData[c].Address[2],toc.TrackData[c].Address[3]);
b[len++]=temp>>24;
b[len++]=temp>>16;
b[len++]=temp>>8;
b[len++]=temp;
}
if (single) break;
}
b[0] = (uint8_t)(((len-2) >> 8) & 0xff);
b[1] = (uint8_t)((len-2) & 0xff);
/* pclog("Table of Contents (%i bytes) : \n",size);
pclog("First track - %02X\n",toc.FirstTrack);
pclog("Last track - %02X\n",toc.LastTrack);
for (c=0;c<=toc.LastTrack;c++)
pclog("Track %02X - number %02X control %02X adr %02X address %02X %02X %02X %02X\n",c,toc.TrackData[c].TrackNumber,toc.TrackData[c].Control,toc.TrackData[c].Adr,toc.TrackData[c].Address[0],toc.TrackData[c].Address[1],toc.TrackData[c].Address[2],toc.TrackData[c].Address[3]);
for (c=0;c<=toc.LastTrack;c++)
pclog("Track %02X - number %02X control %02X adr %02X address %06X\n",c,toc.TrackData[c].TrackNumber,toc.TrackData[c].Control,toc.TrackData[c].Adr,MSFtoLBA(toc.TrackData[c].Address[1],toc.TrackData[c].Address[2],toc.TrackData[c].Address[3]));*/
return len;
}
static int ioctl_readtoc_session(unsigned char *b, int msf, int maxlen)
{
int len=4;
int size;
uint32_t temp;
CDROM_READ_TOC_EX toc_ex;
CDROM_TOC_SESSION_DATA toc;
if (!cdrom_drive) return 0;
ioctl_cd_state = CD_STOPPED;
memset(&toc_ex,0,sizeof(toc_ex));
memset(&toc,0,sizeof(toc));
toc_ex.Format=CDROM_READ_TOC_EX_FORMAT_SESSION;
toc_ex.Msf=msf;
toc_ex.SessionTrack=0;
ioctl_open(0);
DeviceIoControl(hIOCTL,IOCTL_CDROM_READ_TOC_EX, &toc_ex,sizeof(toc_ex),&toc,sizeof(toc),(PDWORD)&size,NULL);
ioctl_close();
// pclog("Read TOC session - %i %02X %02X %i %i %02X %02X %02X\n",size,toc.Length[0],toc.Length[1],toc.FirstCompleteSession,toc.LastCompleteSession,toc.TrackData[0].Adr,toc.TrackData[0].Control,toc.TrackData[0].TrackNumber);
b[2]=toc.FirstCompleteSession;
b[3]=toc.LastCompleteSession;
b[len++]=0; /*Reserved*/
b[len++]=(toc.TrackData[0].Adr<<4)|toc.TrackData[0].Control;
b[len++]=toc.TrackData[0].TrackNumber;
b[len++]=0; /*Reserved*/
if (msf)
{
b[len++]=toc.TrackData[0].Address[0];
b[len++]=toc.TrackData[0].Address[1];
b[len++]=toc.TrackData[0].Address[2];
b[len++]=toc.TrackData[0].Address[3];
}
else
{
temp=MSFtoLBA(toc.TrackData[0].Address[1],toc.TrackData[0].Address[2],toc.TrackData[0].Address[3]);
b[len++]=temp>>24;
b[len++]=temp>>16;
b[len++]=temp>>8;
b[len++]=temp;
}
return len;
}
static int ioctl_readtoc_raw(unsigned char *b, int maxlen)
{
int len=4;
int size;
uint32_t temp;
int i;
int BytesRead = 0;
CDROM_READ_TOC_EX toc_ex;
CDROM_TOC_FULL_TOC_DATA toc;
if (!cdrom_drive) return 0;
ioctl_cd_state = CD_STOPPED;
memset(&toc_ex,0,sizeof(toc_ex));
memset(&toc,0,sizeof(toc));
toc_ex.Format=CDROM_READ_TOC_EX_FORMAT_FULL_TOC;
toc_ex.Msf=1;
toc_ex.SessionTrack=0;
ioctl_open(0);
DeviceIoControl(hIOCTL,IOCTL_CDROM_READ_TOC_EX, &toc_ex,sizeof(toc_ex),&toc,sizeof(toc),(PDWORD)&size,NULL);
ioctl_close();
// pclog("Read TOC session - %i %02X %02X %i %i %02X %02X %02X\n",size,toc.Length[0],toc.Length[1],toc.FirstCompleteSession,toc.LastCompleteSession,toc.TrackData[0].Adr,toc.TrackData[0].Control,toc.TrackData[0].TrackNumber);
b[2]=toc.FirstCompleteSession;
b[3]=toc.LastCompleteSession;
size -= sizeof(CDROM_TOC_FULL_TOC_DATA);
size /= sizeof(toc.Descriptors[0]);
for (i = 0; i <= size; i++)
{
b[len++]=toc.Descriptors[i].SessionNumber;
b[len++]=(toc.Descriptors[i].Adr<<4)|toc.Descriptors[i].Control;
b[len++]=0;
b[len++]=toc.Descriptors[i].Reserved1; /*Reserved*/
b[len++]=toc.Descriptors[i].MsfExtra[0];
b[len++]=toc.Descriptors[i].MsfExtra[1];
b[len++]=toc.Descriptors[i].MsfExtra[2];
b[len++]=toc.Descriptors[i].Zero;
b[len++]=toc.Descriptors[i].Msf[0];
b[len++]=toc.Descriptors[i].Msf[1];
b[len++]=toc.Descriptors[i].Msf[2];
}
return len;
}
static uint32_t ioctl_size()
{
return cdrom_capacity;
}
static int ioctl_status()
{
if (!(ioctl_ready) && (cdrom_drive <= 0))
return CD_STATUS_EMPTY;
switch(ioctl_cd_state)
{
case CD_PLAYING:
return CD_STATUS_PLAYING;
case CD_PAUSED:
return CD_STATUS_PAUSED;
case CD_STOPPED:
return CD_STATUS_STOPPED;
}
}
void ioctl_reset()
{
CDROM_TOC ltoc;
int temp;
long size;
if (!cdrom_drive)
{
tocvalid = 0;
return;
}
ioctl_open(0);
temp = DeviceIoControl(hIOCTL, IOCTL_CDROM_READ_TOC, NULL, 0, &ltoc, sizeof(ltoc), &size, NULL);
ioctl_close();
toc = ltoc;
tocvalid = 1;
}
int ioctl_open(char d)
{
// char s[8];
if (!ioctl_inited)
{
sprintf(ioctl_path,"\\\\.\\%c:",d);
pclog("Path is %s\n",ioctl_path);
tocvalid=0;
}
// pclog("Opening %s\n",ioctl_path);
hIOCTL = CreateFile(/*"\\\\.\\g:"*/ioctl_path,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,0,NULL);
if (!hIOCTL)
{
//fatal("IOCTL");
}
atapi=&ioctl_atapi;
if (!ioctl_inited)
{
ioctl_inited=1;
CloseHandle(hIOCTL);
hIOCTL = NULL;
}
return 0;
}
void ioctl_close(void)
{
if (hIOCTL)
{
CloseHandle(hIOCTL);
hIOCTL = NULL;
}
}
static void ioctl_exit(void)
{
ioctl_stop();
ioctl_inited=0;
tocvalid=0;
}
static ATAPI ioctl_atapi=
{
ioctl_ready,
ioctl_medium_changed,
ioctl_readtoc,
ioctl_readtoc_session,
ioctl_readtoc_raw,
ioctl_getcurrentsubchannel,
ioctl_readsector,
ioctl_readsector_raw,
ioctl_playaudio,
ioctl_seek,
ioctl_load,
ioctl_eject,
ioctl_pause,
ioctl_resume,
ioctl_size,
ioctl_status,
ioctl_is_track_audio,
ioctl_stop,
ioctl_exit
};

12
src/cdrom-ioctl.h Normal file
View File

@@ -0,0 +1,12 @@
#ifndef CDROM_IOCTL_H
#define CDROM_IOCTL_H
/* this header file lists the functions provided by
various platform specific cdrom-ioctl files */
extern int ioctl_open(char d);
extern void ioctl_reset();
extern void ioctl_close(void);
#endif /* ! CDROM_IOCTL_H */

396
src/cdrom-iso.c Normal file
View File

@@ -0,0 +1,396 @@
/*ISO CD-ROM support*/
#include "ibm.h"
#include "ide.h"
#include "cdrom-iso.h"
#include <sys/stat.h>
static ATAPI iso_atapi;
static uint32_t last_block = 0;
static uint64_t image_size = 0;
static int iso_inited = 0;
char iso_path[1024];
void iso_close(void);
static FILE* iso_image;
static int iso_changed = 0;
static uint32_t iso_cd_pos = 0, iso_cd_end = 0;
void iso_audio_callback(int16_t *output, int len)
{
memset(output, 0, len * 2);
return;
}
void iso_audio_stop()
{
pclog("iso_audio_stop stub\n");
}
static int get_track_nr(uint32_t pos)
{
pclog("get_track_nr stub\n");
return 0;
}
static void iso_playaudio(uint32_t pos, uint32_t len, int ismsf)
{
pclog("iso_playaudio stub\n");
return;
}
static void iso_pause(void)
{
pclog("iso_pause stub\n");
return;
}
static void iso_resume(void)
{
pclog("iso_resume stub\n");
return;
}
static void iso_stop(void)
{
pclog("iso_stop stub\n");
return;
}
static void iso_seek(uint32_t pos)
{
pclog("iso_seek stub\n");
return;
}
static int iso_ready(void)
{
if (strlen(iso_path) == 0)
{
return 0;
}
if (old_cdrom_drive != cdrom_drive)
{
// old_cdrom_drive = cdrom_drive;
return 1;
}
if (iso_changed)
{
iso_changed = 0;
return 1;
}
return 1;
}
/* Always return 0, because there is no way to change the ISO without unmounting and remounting it. */
static int iso_medium_changed(void)
{
if (strlen(iso_path) == 0)
{
return 0;
}
if (old_cdrom_drive != cdrom_drive)
{
old_cdrom_drive = cdrom_drive;
return 0;
}
if (iso_changed)
{
iso_changed = 0;
return 0;
}
return 0;
}
static uint8_t iso_getcurrentsubchannel(uint8_t *b, int msf)
{
pclog("iso_getcurrentsubchannel stub\n");
return 0;
}
static void iso_eject(void)
{
pclog("iso_eject stub\n");
}
static void iso_load(void)
{
pclog("iso_load stub\n");
}
static void iso_readsector(uint8_t *b, int sector)
{
if (!cdrom_drive) return;
iso_image = fopen(iso_path, "rb");
fseek(iso_image,sector*2048,SEEK_SET);
fread(b,2048,1,iso_image);
fclose(iso_image);
}
static void lba_to_msf(uint8_t *buf, int lba)
{
double dlba = (double) lba + 150;
buf[2] = (uint8_t) (((uint32_t) dlba) % 75);
dlba /= 75;
buf[1] = (uint8_t) (((uint32_t) dlba) % 60);
dlba /= 60;
buf[0] = (uint8_t) dlba;
}
#if 0
static void lba_to_msf(uint8_t *buf, int lba)
{
lba += 150;
buf[0] = (lba / 75) / 60;
buf[1] = (lba / 75) % 60;
buf[2] = lba % 75;
}
#endif
static void iso_readsector_raw(uint8_t *b, int sector)
{
uint32_t temp;
if (!cdrom_drive) return;
iso_image = fopen(iso_path, "rb");
fseek(iso_image, sector*2048, SEEK_SET);
fread(b+16, 2048, 1, iso_image);
fclose(iso_image);
/* sync bytes */
b[0] = 0;
memset(b + 1, 0xff, 10);
b[11] = 0;
b += 12;
lba_to_msf(b, sector);
b[3] = 1; /* mode 1 data */
b += 4;
b += 2048;
memset(b, 0, 288);
}
static int iso_readtoc(unsigned char *buf, unsigned char start_track, int msf, int maxlen, int single)
{
uint8_t *q;
int len;
if (start_track > 1 && start_track != 0xaa)
return -1;
q = buf + 2;
*q++ = 1; /* first session */
*q++ = 1; /* last session */
if (start_track <= 1) {
*q++ = 0; /* reserved */
*q++ = 0x14; /* ADR, control */
*q++ = 1; /* track number */
*q++ = 0; /* reserved */
if (msf) {
*q++ = 0; /* reserved */
lba_to_msf(q, 0);
q += 3;
} else {
/* sector 0 */
*q++ = 0;
*q++ = 0;
*q++ = 0;
*q++ = 0;
}
}
/* lead out track */
*q++ = 0; /* reserved */
*q++ = 0x16; /* ADR, control */
*q++ = 0xaa; /* track number */
*q++ = 0; /* reserved */
last_block = image_size >> 11;
if (msf) {
*q++ = 0; /* reserved */
lba_to_msf(q, last_block);
q += 3;
} else {
*q++ = last_block >> 24;
*q++ = last_block >> 16;
*q++ = last_block >> 8;
*q++ = last_block;
}
len = q - buf;
buf[0] = (uint8_t)(((len-2) >> 8) & 0xff);
buf[1] = (uint8_t)((len-2) & 0xff);
return len;
}
static int iso_readtoc_session(unsigned char *buf, int msf, int maxlen)
{
uint8_t *q;
q = buf + 2;
*q++ = 1; /* first session */
*q++ = 1; /* last session */
*q++ = 1; /* session number */
*q++ = 0x14; /* data track */
*q++ = 0; /* track number */
*q++ = 0xa0; /* lead-in */
*q++ = 0; /* min */
*q++ = 0; /* sec */
*q++ = 0; /* frame */
*q++ = 0;
return 12;
}
static int iso_readtoc_raw(unsigned char *buf, int maxlen)
{
uint8_t *q;
int len;
q = buf + 2;
*q++ = 1; /* first session */
*q++ = 1; /* last session */
*q++ = 1; /* session number */
*q++ = 0x14; /* data track */
*q++ = 0; /* track number */
*q++ = 0xa0; /* lead-in */
*q++ = 0; /* min */
*q++ = 0; /* sec */
*q++ = 0; /* frame */
*q++ = 0;
*q++ = 1; /* first track */
*q++ = 0x00; /* disk type */
*q++ = 0x00;
*q++ = 1; /* session number */
*q++ = 0x14; /* data track */
*q++ = 0; /* track number */
*q++ = 0xa1;
*q++ = 0; /* min */
*q++ = 0; /* sec */
*q++ = 0; /* frame */
*q++ = 0;
*q++ = 1; /* last track */
*q++ = 0x00;
*q++ = 0x00;
*q++ = 1; /* session number */
*q++ = 0x14; /* data track */
*q++ = 0; /* track number */
*q++ = 0xa2; /* lead-out */
*q++ = 0; /* min */
*q++ = 0; /* sec */
*q++ = 0; /* frame */
last_block = image_size >> 11;
/* this is raw, must be msf */
*q++ = 0; /* reserved */
lba_to_msf(q, last_block);
q += 3;
*q++ = 1; /* session number */
*q++ = 0x14; /* ADR, control */
*q++ = 0; /* track number */
*q++ = 1; /* point */
*q++ = 0; /* min */
*q++ = 0; /* sec */
*q++ = 0; /* frame */
/* same here */
*q++ = 0;
*q++ = 0;
*q++ = 0;
*q++ = 0;
len = q - buf;
buf[0] = (uint8_t)(((len-2) >> 8) & 0xff);
buf[1] = (uint8_t)((len-2) & 0xff);
return len;
}
static uint32_t iso_size()
{
unsigned char b[4096];
atapi->readtoc(b, 0, 0, 4096, 0);
return last_block;
}
static int iso_status()
{
if (!(iso_ready()) && (cdrom_drive != 200)) return CD_STATUS_EMPTY;
return CD_STATUS_DATA_ONLY;
}
void iso_reset()
{
}
int iso_open(char *fn)
{
if (strcmp(fn, iso_path) != 0)
{
iso_changed = 1;
}
/* Make sure iso_changed stays when changing from ISO to another ISO. */
if (!iso_inited && (cdrom_drive != 200)) iso_changed = 0;
if (!iso_inited || iso_changed)
{
sprintf(iso_path, "%s", fn);
pclog("Path is %s\n", iso_path);
}
iso_image = fopen(iso_path, "rb");
atapi = &iso_atapi;
if (!iso_inited || iso_changed)
{
if (!iso_inited) iso_inited = 1;
fclose(iso_image);
}
struct stat st;
stat(iso_path, &st);
image_size = st.st_size;
return 0;
}
void iso_close(void)
{
if (iso_image) fclose(iso_image);
memset(iso_path, 0, 1024);
}
static void iso_exit(void)
{
// iso_stop();
iso_inited = 0;
}
static int iso_is_track_audio(uint32_t pos, int ismsf)
{
return 0;
}
static ATAPI iso_atapi =
{
iso_ready,
iso_medium_changed,
iso_readtoc,
iso_readtoc_session,
iso_readtoc_raw,
iso_getcurrentsubchannel,
iso_readsector,
iso_readsector_raw,
iso_playaudio,
iso_seek,
iso_load,
iso_eject,
iso_pause,
iso_resume,
iso_size,
iso_status,
iso_is_track_audio,
iso_stop,
iso_exit
};

14
src/cdrom-iso.h Normal file
View File

@@ -0,0 +1,14 @@
#ifndef CDROM_ISO_H
#define CDROM_ISO_H
/* this header file lists the functions provided by
various platform specific cdrom-ioctl files */
extern char iso_path[1024];
extern int iso_open(char *fn);
extern void iso_reset();
extern void iso_close(void);
#endif /* ! CDROM_ISO_H */

139
src/cdrom-null.c Normal file
View File

@@ -0,0 +1,139 @@
#include "ibm.h"
#include "ide.h"
#include "cdrom-ioctl.h"
int cdrom_drive;
static ATAPI null_atapi;
void cdrom_null_audio_callback(int16_t *output, int len)
{
memset(output, 0, len * 2);
}
void cdrom_null_audio_stop()
{
}
static void null_playaudio(uint32_t pos, uint32_t len, int ismsf)
{
}
static void null_pause(void)
{
}
static void null_resume(void)
{
}
static void null_stop(void)
{
}
static void null_seek(uint32_t pos)
{
}
static int null_ready(void)
{
return 0;
}
/* Always return 0, the contents of a null CD-ROM drive never change. */
static int null_medium_changed(void)
{
return 0;
}
static uint8_t null_getcurrentsubchannel(uint8_t *b, int msf)
{
return 0x13;
}
static void null_eject(void)
{
}
static void null_load(void)
{
}
static void null_readsector(uint8_t *b, int sector)
{
}
static void null_readsector_raw(uint8_t *b, int sector)
{
}
static int null_readtoc(unsigned char *b, unsigned char starttrack, int msf, int maxlen, int single)
{
return 0;
}
static int null_readtoc_session(unsigned char *b, int msf, int maxlen)
{
return 0;
}
static int null_readtoc_raw(unsigned char *b, int maxlen)
{
return 0;
}
static uint32_t null_size()
{
return 0;
}
static int null_status()
{
return CD_STATUS_EMPTY;
}
void cdrom_null_reset()
{
}
int cdrom_null_open(char d)
{
atapi = &null_atapi;
return 0;
}
void null_close(void)
{
}
static void null_exit(void)
{
}
static int null_is_track_audio(uint32_t pos, int ismsf)
{
return 0;
}
static ATAPI null_atapi =
{
null_ready,
null_medium_changed,
null_readtoc,
null_readtoc_session,
null_readtoc_raw,
null_getcurrentsubchannel,
null_readsector,
null_readsector_raw,
null_playaudio,
null_seek,
null_load,
null_eject,
null_pause,
null_resume,
null_size,
null_status,
null_is_track_audio,
null_stop,
null_exit
};

11
src/cdrom-null.h Normal file
View File

@@ -0,0 +1,11 @@
#ifndef CDROM_IOCTL_H
#define CDROM_IOCTL_H
/* this header file lists the functions provided by
various platform specific cdrom-ioctl files */
extern int cdrom_null_open(char d);
extern void cdrom_null_reset();
extern void null_close();
#endif /* ! CDROM_IOCTL_H */

21
src/codegen.c Normal file
View File

@@ -0,0 +1,21 @@
#include "ibm.h"
#include "x86_ops.h"
#include "mem.h"
#include "codegen.h"
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_block_start)();
void (*codegen_timing_block_end)();
void codegen_timing_set(codegen_timing_t *timing)
{
codegen_timing_start = timing->start;
codegen_timing_prefix = timing->prefix;
codegen_timing_opcode = timing->opcode;
codegen_timing_block_start = timing->block_start;
codegen_timing_block_end = timing->block_end;
}
int codegen_in_recompile;

340
src/codegen.h Normal file
View File

@@ -0,0 +1,340 @@
#include "mem.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
represents 64 bytes. This is only tracked for pages that have code in - when a
page first has a codeblock generated, it is evicted from the writelookup and
added to the page_lookup for this purpose. When in the page_lookup, each write
will go through the mem_write_ram*_page() functions and set the dirty mask
appropriately.
Each codeblock also contains a code mask (actually two masks, one for each
page the block is/may be in), again with each bit representing 64 bytes.
Each page has a list of codeblocks present in it. As each codeblock can span
up to two pages, two lists are present.
When a codeblock is about to be executed, the code masks are compared with the
dirty masks for the relevant pages. If either intersect, then
codegen_check_flush() is called on the affected page(s), and all affected
blocks are evicted.
The 64 byte granularity appears to work reasonably well for most cases,
avoiding most unnecessary evictions (eg when code & data are stored in the
same page).
*/
typedef struct codeblock_t
{
/*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;
uint32_t pc;
uint32_t _cs;
uint32_t endpc;
uint32_t phys, phys_2;
uint32_t use32;
int stack32;
int pnt;
int ins;
uint64_t page_mask, page_mask2;
uint8_t data[2048];
} codeblock_t;
static inline codeblock_t *codeblock_tree_find(uint32_t phys)
{
codeblock_t *block = pages[phys >> 12].head;
while (block)
{
if (phys == block->phys)
break;
else if (phys < block->phys)
block = block->left;
else
block = block->right;
}
return block;
}
static inline void codeblock_tree_add(codeblock_t *new_block)
{
codeblock_t *block = pages[new_block->phys >> 12].head;
if (!block)
{
pages[new_block->phys >> 12].head = new_block;
new_block->parent = new_block->left = new_block->right = NULL;
}
else
{
codeblock_t *old_block = NULL;
while (block)
{
old_block = block;
if (new_block->phys < old_block->phys)
block = block->left;
else
block = block->right;
}
if (new_block->phys < old_block->phys)
old_block->left = new_block;
else
old_block->right = new_block;
new_block->parent = old_block;
new_block->left = new_block->right = NULL;
}
}
static inline void codeblock_tree_delete(codeblock_t *block)
{
codeblock_t *parent = block->parent;
if (!block->left && !block->right)
{
/*Easy case - remove from parent*/
if (!parent)
pages[block->phys >> 12].head = NULL;
else
{
if (parent->left == block)
parent->left = NULL;
if (parent->right == block)
parent->right = NULL;
}
return;
}
else if (!block->left)
{
/*Only right node*/
if (!parent)
{
pages[block->phys >> 12].head = block->right;
pages[block->phys >> 12].head->parent = NULL;
}
else
{
if (parent->left == block)
{
parent->left = block->right;
parent->left->parent = parent;
}
if (parent->right == block)
{
parent->right = block->right;
parent->right->parent = parent;
}
}
return;
}
else if (!block->right)
{
/*Only left node*/
if (!parent)
{
pages[block->phys >> 12].head = block->left;
pages[block->phys >> 12].head->parent = NULL;
}
else
{
if (parent->left == block)
{
parent->left = block->left;
parent->left->parent = parent;
}
if (parent->right == block)
{
parent->right = block->left;
parent->right->parent = parent;
}
}
return;
}
else
{
/*Difficult case - node has two children. Walk right child to find lowest node*/
codeblock_t *lowest = block->right, *highest;
codeblock_t *old_parent;
while (lowest->left)
lowest = lowest->left;
old_parent = lowest->parent;
/*Replace deleted node with lowest node*/
if (!parent)
pages[block->phys >> 12].head = lowest;
else
{
if (parent->left == block)
parent->left = lowest;
if (parent->right == block)
parent->right = lowest;
}
lowest->parent = parent;
lowest->left = block->left;
if (lowest->left)
lowest->left->parent = lowest;
old_parent->left = NULL;
highest = lowest->right;
if (!highest)
{
if (lowest != block->right)
{
lowest->right = block->right;
block->right->parent = lowest;
}
return;
}
while (highest->right)
highest = highest->right;
if (block->right && block->right != lowest)
{
highest->right = block->right;
block->right->parent = highest;
}
}
}
#define PAGE_MASK_MASK 63
#define PAGE_MASK_SHIFT 6
extern codeblock_t *codeblock;
extern codeblock_t **codeblock_hash;
void codegen_init();
void codegen_reset();
void codegen_block_init(uint32_t phys_addr);
void codegen_block_remove();
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_check_abrt();
void codegen_set_op32();
void codegen_flush();
void codegen_check_flush(struct page_t *page, uint64_t mask, uint32_t phys_addr);
extern int cpu_block_end;
extern int cpu_recomp_blocks, cpu_recomp_ins, cpu_recomp_full_ins, cpu_new_blocks;
extern int cpu_recomp_blocks_latched, cpu_recomp_ins_latched, cpu_recomp_full_ins_latched, cpu_new_blocks_latched;
extern int cpu_recomp_flushes, cpu_recomp_flushes_latched;
extern int cpu_recomp_evicted, cpu_recomp_evicted_latched;
extern int cpu_recomp_reuse, cpu_recomp_reuse_latched;
extern int cpu_recomp_removed, cpu_recomp_removed_latched;
extern int cpu_reps, cpu_reps_latched;
extern int cpu_notreps, cpu_notreps_latched;
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_block_start)();
extern void (*codegen_timing_block_end)();
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 (*block_start)();
void (*block_end)();
} 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;
void codegen_timing_set(codegen_timing_t *timing);
extern int block_current;
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 >= 1760)
{
CPU_BLOCK_END();
}
}
static inline void addword(uint16_t val)
{
*(uint16_t *)&codeblock[block_current].data[block_pos] = val;
block_pos += 2;
if (block_pos >= 1720)
{
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 >= 1720)
{
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 >= 1720)
{
CPU_BLOCK_END();
}
}
/*Current physical page of block being recompiled. -1 if no recompilation taking place */
extern uint32_t recomp_page;
extern x86seg *op_ea_seg;
extern int op_ssegs;
extern uint32_t op_old_pc;
/*Set to 1 if flags have been changed in the block being recompiled, and hence
flags_op is known and can be relied on */
extern int codegen_flags_changed;
extern int codegen_fpu_entered;
extern int codegen_mmx_entered;
extern int codegen_fpu_loaded_iq[8];
extern int codegen_reg_loaded[8];
extern int codegen_in_recompile;

497
src/codegen_ops.c Normal file
View File

@@ -0,0 +1,497 @@
#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_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_arith.h"
#include "codegen_ops_fpu.h"
#include "codegen_ops_jump.h"
#include "codegen_ops_logic.h"
#include "codegen_ops_misc.h"
#include "codegen_ops_mmx.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*/ ropADD_b_rmw, ropADD_w_rmw, ropADD_b_rm, ropADD_w_rm, ropADD_AL_imm, ropADD_AX_imm, ropPUSH_ES_16, NULL, 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, NULL,
/*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,
/*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, NULL, ropLEA_w, NULL, 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,
/*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, NULL, NULL, 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, NULL, NULL, ropCLD, ropSTD, NULL, ropFF_16,
/*32-bit data*/
/* 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, NULL, 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, NULL,
/*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,
/*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, NULL, ropLEA_l, NULL, 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,
/*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, NULL, NULL, 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, NULL, NULL, ropCLD, ropSTD, NULL, 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*/ 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, ropEMMS, 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*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, ropMOVZX_w_b, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropMOVSX_w_b, 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*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, 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*/ 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,
/*30*/ ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs,
/*40*/ ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs,
/*50*/ ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs,
/*60*/ ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs,
/*70*/ ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs,
/*80*/ ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs,
/*90*/ ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs,
/*a0*/ ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs,
/*b0*/ ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs,
/*c0*/ ropFADD, ropFADD, ropFADD, ropFADD, ropFADD, ropFADD, ropFADD, ropFADD, ropFMUL, ropFMUL, ropFMUL, ropFMUL, ropFMUL, ropFMUL, ropFMUL, ropFMUL,
/*d0*/ ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP,
/*e0*/ ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR,
/*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*/ 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,
/*30*/ ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs,
/*40*/ ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs,
/*50*/ ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs,
/*60*/ ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs,
/*70*/ ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs,
/*80*/ ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFADDs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs, ropFMULs,
/*90*/ ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs, ropFCOMPs,
/*a0*/ ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs, ropFSUBRs,
/*b0*/ ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs, ropFDIVRs,
/*c0*/ ropFADD, ropFADD, ropFADD, ropFADD, ropFADD, ropFADD, ropFADD, ropFADD, ropFMUL, ropFMUL, ropFMUL, ropFMUL, ropFMUL, ropFMUL, ropFMUL, ropFMUL,
/*d0*/ ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP,
/*e0*/ ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUB, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR, ropFSUBR,
/*f0*/ ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIV, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR, ropFDIVR,
};
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*/ 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,
/*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,
/*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,
/*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*/ 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*/ 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,
/*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,
/*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,
/*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*/ 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_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,
/*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,
/*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,
/*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*/ 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,
/*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,
/*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,
/*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_db[512] =
{
/*16-bit data*/
/* 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,
/*40*/ ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*50*/ ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl,
/*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*/ ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*90*/ ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl,
/*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*/
/*80*/ 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,
/*40*/ ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*50*/ ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl,
/*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*/ ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, ropFILDl, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*90*/ ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl, ropFISTPl,
/*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_dc[512] =
{
/*16-bit data*/
/* 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,
/*30*/ ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd,
/*40*/ ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd,
/*50*/ ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd,
/*60*/ ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd,
/*70*/ ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd,
/*80*/ ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd,
/*90*/ ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd,
/*a0*/ ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd,
/*b0*/ ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd,
/*c0*/ ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, ropFMULr,
/*d0*/ ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP,
/*e0*/ ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr,
/*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*/ 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,
/*30*/ ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd,
/*40*/ ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd,
/*50*/ ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd,
/*60*/ ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd,
/*70*/ ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd,
/*80*/ ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFADDd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd, ropFMULd,
/*90*/ ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd, ropFCOMPd,
/*a0*/ ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd, ropFSUBRd,
/*b0*/ ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd, ropFDIVRd,
/*c0*/ ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFADDr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, ropFMULr, ropFMULr,
/*d0*/ ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOM, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP, ropFCOMP,
/*e0*/ ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBRr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr, ropFSUBr,
/*f0*/ ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVRr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr, ropFDIVr,
};
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*/ 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,
/*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,
/*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,
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 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,
/*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*/ 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,
/*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,
/*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,
/*c0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 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,
/*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,
/*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,
/*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,
/*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, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*e0*/ ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP,
/*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,
/*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,
/*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,
/*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, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*e0*/ ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBRP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP, ropFSUBP,
/*f0*/ ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVRP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP, ropFDIVP,
};
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*/ 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,
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq,
/*40*/ ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*50*/ ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw,
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq,
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq,
/*80*/ ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*90*/ ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw,
/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq,
/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq,
/*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*/ 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,
/*32-bit data*/
/* 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,
/*30*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq,
/*40*/ ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*50*/ ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw,
/*60*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq,
/*70*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq,
/*80*/ ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, ropFILDw, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*90*/ ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw, ropFISTPw,
/*a0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq, ropFILDq,
/*b0*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq, ropFISTPq,
/*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*/ 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,
};

37
src/codegen_ops.h Normal file
View File

@@ -0,0 +1,37 @@
typedef uint32_t (*RecompOpFn)(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block);
extern RecompOpFn recomp_opcodes[512];
extern RecompOpFn recomp_opcodes_0f[512];
extern RecompOpFn recomp_opcodes_d8[512];
extern RecompOpFn recomp_opcodes_d9[512];
extern RecompOpFn recomp_opcodes_da[512];
extern RecompOpFn recomp_opcodes_db[512];
extern RecompOpFn recomp_opcodes_dc[512];
extern RecompOpFn recomp_opcodes_dd[512];
extern RecompOpFn recomp_opcodes_de[512];
extern RecompOpFn recomp_opcodes_df[512];
#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_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_AL 0
#define REG_AH 4
#define REG_CL 1
#define REG_CH 5
#define REG_DL 2
#define REG_DH 6
#define REG_BL 3
#define REG_BH 7

816
src/codegen_ops_arith.h Normal file
View File

@@ -0,0 +1,816 @@
static uint32_t ropINC_rw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
int host_reg;
CALL_FUNC(flags_rebuild_c);
host_reg = LOAD_REG_W(opcode & 7);
STORE_HOST_REG_ADDR_WL((uint32_t)&cpu_state.flags_op1, host_reg);
ADD_HOST_REG_IMM_W(host_reg, 1);
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op2, 1);
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op, FLAGS_INC16);
STORE_HOST_REG_ADDR_WL((uint32_t)&cpu_state.flags_res, host_reg);
STORE_REG_W_RELEASE(host_reg);
codegen_flags_changed = 1;
return op_pc;
}
static uint32_t ropINC_rl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
int host_reg;
CALL_FUNC(flags_rebuild_c);
host_reg = LOAD_REG_L(opcode & 7);
STORE_HOST_REG_ADDR((uint32_t)&cpu_state.flags_op1, host_reg);
ADD_HOST_REG_IMM(host_reg, 1);
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op2, 1);
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op, FLAGS_INC32);
STORE_HOST_REG_ADDR((uint32_t)&cpu_state.flags_res, host_reg);
STORE_REG_L_RELEASE(host_reg);
codegen_flags_changed = 1;
return op_pc;
}
static uint32_t ropDEC_rw(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
int host_reg;
CALL_FUNC(flags_rebuild_c);
host_reg = LOAD_REG_W(opcode & 7);
STORE_HOST_REG_ADDR_WL((uint32_t)&cpu_state.flags_op1, host_reg);
SUB_HOST_REG_IMM_W(host_reg, 1);
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op2, 1);
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op, FLAGS_DEC16);
STORE_HOST_REG_ADDR_WL((uint32_t)&cpu_state.flags_res, host_reg);
STORE_REG_W_RELEASE(host_reg);
codegen_flags_changed = 1;
return op_pc;
}
static uint32_t ropDEC_rl(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
int host_reg;
CALL_FUNC(flags_rebuild_c);
host_reg = LOAD_REG_L(opcode & 7);
STORE_HOST_REG_ADDR((uint32_t)&cpu_state.flags_op1, host_reg);
SUB_HOST_REG_IMM(host_reg, 1);
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op2, 1);
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op, FLAGS_DEC32);
STORE_HOST_REG_ADDR((uint32_t)&cpu_state.flags_res, host_reg);
STORE_REG_L_RELEASE(host_reg);
codegen_flags_changed = 1;
return op_pc;
}
#define ROP_ARITH_RMW(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; \
\
if ((fetchdat & 0xc0) != 0xc0) \
return 0; \
\
dst_reg = LOAD_REG_B(fetchdat & 7); \
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op, FLAGS_ ## op ## 8); \
src_reg = LOAD_REG_B((fetchdat >> 3) & 7); \
STORE_HOST_REG_ADDR_BL((uint32_t)&cpu_state.flags_op1, dst_reg); \
STORE_HOST_REG_ADDR_BL((uint32_t)&cpu_state.flags_op2, src_reg); \
op ## _HOST_REG_B(dst_reg, src_reg); \
STORE_HOST_REG_ADDR_BL((uint32_t)&cpu_state.flags_res, dst_reg); \
if (writeback) STORE_REG_B_RELEASE(dst_reg); \
else RELEASE_REG(dst_reg); \
RELEASE_REG(src_reg); \
\
codegen_flags_changed = 1; \
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; \
\
if ((fetchdat & 0xc0) != 0xc0) \
return 0; \
\
dst_reg = LOAD_REG_W(fetchdat & 7); \
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op, FLAGS_ ## op ## 16); \
src_reg = LOAD_REG_W((fetchdat >> 3) & 7); \
STORE_HOST_REG_ADDR_WL((uint32_t)&cpu_state.flags_op1, dst_reg); \
STORE_HOST_REG_ADDR_WL((uint32_t)&cpu_state.flags_op2, src_reg); \
op ## _HOST_REG_W(dst_reg, src_reg); \
STORE_HOST_REG_ADDR_WL((uint32_t)&cpu_state.flags_res, dst_reg); \
if (writeback) STORE_REG_W_RELEASE(dst_reg); \
else RELEASE_REG(dst_reg); \
RELEASE_REG(src_reg); \
\
codegen_flags_changed = 1; \
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; \
\
if ((fetchdat & 0xc0) != 0xc0) \
return 0; \
\
dst_reg = LOAD_REG_L(fetchdat & 7); \
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op, FLAGS_ ## op ## 32); \
src_reg = LOAD_REG_L((fetchdat >> 3) & 7); \
STORE_HOST_REG_ADDR((uint32_t)&cpu_state.flags_op1, dst_reg); \
STORE_HOST_REG_ADDR((uint32_t)&cpu_state.flags_op2, src_reg); \
op ## _HOST_REG_L(dst_reg, src_reg); \
STORE_HOST_REG_ADDR((uint32_t)&cpu_state.flags_res, dst_reg); \
if (writeback) STORE_REG_L_RELEASE(dst_reg); \
else RELEASE_REG(dst_reg); \
RELEASE_REG(src_reg); \
\
codegen_flags_changed = 1; \
return op_pc + 1; \
}
#define ROP_ARITH_RM(name, op, writeback) \
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)&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((uint32_t)&cpu_state.flags_op, FLAGS_ ## op ## 8); \
STORE_HOST_REG_ADDR_BL((uint32_t)&cpu_state.flags_op1, dst_reg); \
STORE_HOST_REG_ADDR_BL((uint32_t)&cpu_state.flags_op2, src_reg); \
op ## _HOST_REG_B(dst_reg, src_reg); \
STORE_HOST_REG_ADDR_BL((uint32_t)&cpu_state.flags_res, dst_reg); \
if (writeback) STORE_REG_B_RELEASE(dst_reg); \
else RELEASE_REG(dst_reg); \
RELEASE_REG(src_reg); \
\
codegen_flags_changed = 1; \
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)&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((uint32_t)&cpu_state.flags_op, FLAGS_ ## op ## 16); \
STORE_HOST_REG_ADDR_WL((uint32_t)&cpu_state.flags_op1, dst_reg); \
STORE_HOST_REG_ADDR_WL((uint32_t)&cpu_state.flags_op2, src_reg); \
op ## _HOST_REG_W(dst_reg, src_reg); \
STORE_HOST_REG_ADDR_WL((uint32_t)&cpu_state.flags_res, dst_reg); \
if (writeback) STORE_REG_W_RELEASE(dst_reg); \
else RELEASE_REG(dst_reg); \
RELEASE_REG(src_reg); \
\
codegen_flags_changed = 1; \
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)&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((uint32_t)&cpu_state.flags_op, FLAGS_ ## op ## 32); \
STORE_HOST_REG_ADDR((uint32_t)&cpu_state.flags_op1, dst_reg); \
STORE_HOST_REG_ADDR((uint32_t)&cpu_state.flags_op2, src_reg); \
op ## _HOST_REG_L(dst_reg, src_reg); \
STORE_HOST_REG_ADDR((uint32_t)&cpu_state.flags_res, dst_reg); \
if (writeback) STORE_REG_L_RELEASE(dst_reg); \
else RELEASE_REG(dst_reg); \
RELEASE_REG(src_reg); \
\
codegen_flags_changed = 1; \
return op_pc + 1; \
}
ROP_ARITH_RMW(ADD, ADD, 1)
ROP_ARITH_RMW(SUB, SUB, 1)
ROP_ARITH_RM(ADD, ADD, 1)
ROP_ARITH_RM(SUB, SUB, 1)
static uint32_t ropCMP_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)&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((uint32_t)&cpu_state.flags_op, FLAGS_SUB8);
STORE_HOST_REG_ADDR_BL((uint32_t)&cpu_state.flags_op1, dst_reg);
dst_reg = CMP_HOST_REG_B(dst_reg, src_reg);
STORE_HOST_REG_ADDR_BL((uint32_t)&cpu_state.flags_op2, src_reg);
STORE_HOST_REG_ADDR_BL((uint32_t)&cpu_state.flags_res, dst_reg);
RELEASE_REG(dst_reg);
RELEASE_REG(src_reg);
codegen_flags_changed = 1;
return op_pc + 1;
}
static uint32_t ropCMP_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)&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((uint32_t)&cpu_state.flags_op, FLAGS_SUB16);
STORE_HOST_REG_ADDR_WL((uint32_t)&cpu_state.flags_op1, dst_reg);
dst_reg = CMP_HOST_REG_W(dst_reg, src_reg);
STORE_HOST_REG_ADDR_WL((uint32_t)&cpu_state.flags_op2, src_reg);
STORE_HOST_REG_ADDR_WL((uint32_t)&cpu_state.flags_res, dst_reg);
RELEASE_REG(dst_reg);
RELEASE_REG(src_reg);
codegen_flags_changed = 1;
return op_pc + 1;
}
static uint32_t ropCMP_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)&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((uint32_t)&cpu_state.flags_op, FLAGS_SUB32);
STORE_HOST_REG_ADDR((uint32_t)&cpu_state.flags_op1, dst_reg);
dst_reg = CMP_HOST_REG_L(dst_reg, src_reg);
STORE_HOST_REG_ADDR((uint32_t)&cpu_state.flags_op2, src_reg);
STORE_HOST_REG_ADDR((uint32_t)&cpu_state.flags_res, dst_reg);
RELEASE_REG(dst_reg);
RELEASE_REG(src_reg);
codegen_flags_changed = 1;
return op_pc + 1;
}
static uint32_t ropCMP_b_rmw(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)
{
dst_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)&oldpc, op_old_pc);
MEM_LOAD_ADDR_EA_B(target_seg);
dst_reg = 0;
}
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op, FLAGS_SUB8);
src_reg = LOAD_REG_B((fetchdat >> 3) & 7);
STORE_HOST_REG_ADDR_BL((uint32_t)&cpu_state.flags_op1, dst_reg);
dst_reg = CMP_HOST_REG_B(dst_reg, src_reg);
STORE_HOST_REG_ADDR_BL((uint32_t)&cpu_state.flags_op2, src_reg);
STORE_HOST_REG_ADDR_BL((uint32_t)&cpu_state.flags_res, dst_reg);
RELEASE_REG(dst_reg);
RELEASE_REG(src_reg);
codegen_flags_changed = 1;
return op_pc + 1;
}
static uint32_t ropCMP_w_rmw(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)
{
dst_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)&oldpc, op_old_pc);
MEM_LOAD_ADDR_EA_W(target_seg);
dst_reg = 0;
} \
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op, FLAGS_SUB16);
src_reg = LOAD_REG_W((fetchdat >> 3) & 7);
STORE_HOST_REG_ADDR_WL((uint32_t)&cpu_state.flags_op1, dst_reg);
dst_reg = CMP_HOST_REG_W(dst_reg, src_reg);
STORE_HOST_REG_ADDR_WL((uint32_t)&cpu_state.flags_op2, src_reg);
STORE_HOST_REG_ADDR_WL((uint32_t)&cpu_state.flags_res, dst_reg);
RELEASE_REG(dst_reg);
RELEASE_REG(src_reg);
codegen_flags_changed = 1;
return op_pc + 1;
}
static uint32_t ropCMP_l_rmw(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)
{
dst_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)&oldpc, op_old_pc);
MEM_LOAD_ADDR_EA_L(target_seg);
dst_reg = 0;
}
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op, FLAGS_SUB32);
src_reg = LOAD_REG_L((fetchdat >> 3) & 7);
STORE_HOST_REG_ADDR((uint32_t)&cpu_state.flags_op1, dst_reg);
dst_reg = CMP_HOST_REG_L(dst_reg, src_reg);
STORE_HOST_REG_ADDR((uint32_t)&cpu_state.flags_op2, src_reg);
STORE_HOST_REG_ADDR((uint32_t)&cpu_state.flags_res, dst_reg);
RELEASE_REG(dst_reg);
RELEASE_REG(src_reg);
codegen_flags_changed = 1;
return op_pc + 1;
}
static uint32_t ropADD_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);
STORE_HOST_REG_ADDR_BL((uint32_t)&cpu_state.flags_op1, host_reg);
ADD_HOST_REG_IMM_B(host_reg, fetchdat & 0xff);
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op2, fetchdat & 0xff);
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op, FLAGS_ADD8);
STORE_HOST_REG_ADDR_BL((uint32_t)&cpu_state.flags_res, host_reg);
STORE_REG_B_RELEASE(host_reg);
codegen_flags_changed = 1;
return op_pc + 1;
}
static uint32_t ropADD_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);
STORE_HOST_REG_ADDR_WL((uint32_t)&cpu_state.flags_op1, host_reg);
ADD_HOST_REG_IMM_W(host_reg, fetchdat & 0xffff);
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op2, fetchdat & 0xffff);
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op, FLAGS_ADD16);
STORE_HOST_REG_ADDR_WL((uint32_t)&cpu_state.flags_res, host_reg);
STORE_REG_W_RELEASE(host_reg);
codegen_flags_changed = 1;
return op_pc + 2;
}
static uint32_t ropADD_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);
STORE_HOST_REG_ADDR((uint32_t)&cpu_state.flags_op1, host_reg);
fetchdat = fastreadl(cs + op_pc);
ADD_HOST_REG_IMM(host_reg, fetchdat);
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op2, fetchdat);
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op, FLAGS_ADD32);
STORE_HOST_REG_ADDR((uint32_t)&cpu_state.flags_res, host_reg);
STORE_REG_L_RELEASE(host_reg);
codegen_flags_changed = 1;
return op_pc + 4;
}
static uint32_t ropCMP_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);
STORE_HOST_REG_ADDR_BL((uint32_t)&cpu_state.flags_op1, host_reg);
host_reg = CMP_HOST_REG_IMM_B(host_reg, fetchdat & 0xff);
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op2, fetchdat & 0xff);
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op, FLAGS_SUB8);
STORE_HOST_REG_ADDR_BL((uint32_t)&cpu_state.flags_res, host_reg);
RELEASE_REG(host_reg);
codegen_flags_changed = 1;
return op_pc + 1;
}
static uint32_t ropCMP_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);
STORE_HOST_REG_ADDR_WL((uint32_t)&cpu_state.flags_op1, host_reg);
host_reg = CMP_HOST_REG_IMM_W(host_reg, fetchdat & 0xffff);
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op2, fetchdat & 0xffff);
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op, FLAGS_SUB16);
STORE_HOST_REG_ADDR_WL((uint32_t)&cpu_state.flags_res, host_reg);
RELEASE_REG(host_reg);
codegen_flags_changed = 1;
return op_pc + 2;
}
static uint32_t ropCMP_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);
STORE_HOST_REG_ADDR((uint32_t)&cpu_state.flags_op1, host_reg);
fetchdat = fastreadl(cs + op_pc);
host_reg = CMP_HOST_REG_IMM_L(host_reg, fetchdat);
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op2, fetchdat);
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op, FLAGS_SUB32);
STORE_HOST_REG_ADDR((uint32_t)&cpu_state.flags_res, host_reg);
RELEASE_REG(host_reg);
codegen_flags_changed = 1;
return op_pc + 4;
}
static uint32_t ropSUB_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);
STORE_HOST_REG_ADDR_BL((uint32_t)&cpu_state.flags_op1, host_reg);
SUB_HOST_REG_IMM_B(host_reg, fetchdat & 0xff);
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op2, fetchdat & 0xff);
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op, FLAGS_SUB8);
STORE_HOST_REG_ADDR_BL((uint32_t)&cpu_state.flags_res, host_reg);
STORE_REG_B_RELEASE(host_reg);
codegen_flags_changed = 1;
return op_pc + 1;
}
static uint32_t ropSUB_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);
STORE_HOST_REG_ADDR_WL((uint32_t)&cpu_state.flags_op1, host_reg);
SUB_HOST_REG_IMM_W(host_reg, fetchdat & 0xffff);
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op2, fetchdat & 0xffff);
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op, FLAGS_SUB16);
STORE_HOST_REG_ADDR_WL((uint32_t)&cpu_state.flags_res, host_reg);
STORE_REG_W_RELEASE(host_reg);
codegen_flags_changed = 1;
return op_pc + 2;
}
static uint32_t ropSUB_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);
STORE_HOST_REG_ADDR((uint32_t)&cpu_state.flags_op1, host_reg);
fetchdat = fastreadl(cs + op_pc);
SUB_HOST_REG_IMM(host_reg, fetchdat);
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op2, fetchdat);
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op, FLAGS_SUB32);
STORE_HOST_REG_ADDR((uint32_t)&cpu_state.flags_res, host_reg);
STORE_REG_L_RELEASE(host_reg);
codegen_flags_changed = 1;
return op_pc + 4;
}
static uint32_t rop80(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
int host_reg;
uint32_t imm;
if ((fetchdat & 0x30) == 0x10 || (fetchdat & 0xc0) != 0xc0)
return 0;
host_reg = LOAD_REG_B(fetchdat & 7);
imm = (fetchdat >> 8) & 0xff;
switch (fetchdat & 0x38)
{
case 0x00: /*ADD*/
STORE_HOST_REG_ADDR_BL((uint32_t)&cpu_state.flags_op1, host_reg);
ADD_HOST_REG_IMM_B(host_reg, imm);
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op2, imm);
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op, FLAGS_ADD8);
break;
case 0x08: /*OR*/
OR_HOST_REG_IMM(host_reg, imm);
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op, FLAGS_ZN8);
break;
case 0x20: /*AND*/
AND_HOST_REG_IMM(host_reg, imm | 0xffffff00);
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op, FLAGS_ZN8);
break;
case 0x28: /*SUB*/
STORE_HOST_REG_ADDR_BL((uint32_t)&cpu_state.flags_op1, host_reg);
SUB_HOST_REG_IMM_B(host_reg, imm);
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op2, imm);
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op, FLAGS_SUB8);
break;
case 0x30: /*XOR*/
XOR_HOST_REG_IMM(host_reg, imm);
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op, FLAGS_ZN8);
break;
case 0x38: /*CMP*/
STORE_HOST_REG_ADDR_BL((uint32_t)&cpu_state.flags_op1, host_reg);
host_reg = CMP_HOST_REG_IMM_B(host_reg, imm);
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op2, imm);
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op, FLAGS_SUB8);
break;
}
STORE_HOST_REG_ADDR_BL((uint32_t)&cpu_state.flags_res, host_reg);
if ((fetchdat & 0x38) != 0x38)
STORE_REG_B_RELEASE(host_reg);
else
RELEASE_REG(host_reg);
codegen_flags_changed = 1;
return op_pc + 2;
}
static uint32_t rop81_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
int host_reg;
uint32_t imm;
if ((fetchdat & 0x30) == 0x10 || (fetchdat & 0xc0) != 0xc0)
return 0;
host_reg = LOAD_REG_W(fetchdat & 7);
imm = (fetchdat >> 8) & 0xffff;
switch (fetchdat & 0x38)
{
case 0x00: /*ADD*/
STORE_HOST_REG_ADDR_WL((uint32_t)&cpu_state.flags_op1, host_reg);
ADD_HOST_REG_IMM_W(host_reg, imm);
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op2, imm);
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op, FLAGS_ADD16);
break;
case 0x08: /*OR*/
OR_HOST_REG_IMM(host_reg, imm);
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op, FLAGS_ZN16);
break;
case 0x20: /*AND*/
AND_HOST_REG_IMM(host_reg, imm | 0xffff0000);
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op, FLAGS_ZN16);
break;
case 0x28: /*SUB*/
STORE_HOST_REG_ADDR_WL((uint32_t)&cpu_state.flags_op1, host_reg);
SUB_HOST_REG_IMM_W(host_reg, imm);
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op2, imm);
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op, FLAGS_SUB16);
break;
case 0x30: /*XOR*/
XOR_HOST_REG_IMM(host_reg, imm);
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op, FLAGS_ZN16);
break;
case 0x38: /*CMP*/
STORE_HOST_REG_ADDR_WL((uint32_t)&cpu_state.flags_op1, host_reg);
host_reg = CMP_HOST_REG_IMM_W(host_reg, imm);
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op2, imm);
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op, FLAGS_SUB16);
break;
}
STORE_HOST_REG_ADDR_WL((uint32_t)&cpu_state.flags_res, host_reg);
if ((fetchdat & 0x38) != 0x38)
STORE_REG_W_RELEASE(host_reg);
else
RELEASE_REG(host_reg);
codegen_flags_changed = 1;
return op_pc + 3;
}
static uint32_t rop81_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
int host_reg;
uint32_t imm;
if ((fetchdat & 0x30) == 0x10 || (fetchdat & 0xc0) != 0xc0)
return 0;
imm = fastreadl(cs + op_pc + 1);
host_reg = LOAD_REG_L(fetchdat & 7);
switch (fetchdat & 0x38)
{
case 0x00: /*ADD*/
STORE_HOST_REG_ADDR((uint32_t)&cpu_state.flags_op1, host_reg);
ADD_HOST_REG_IMM(host_reg, imm);
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op2, imm);
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op, FLAGS_ADD32);
break;
case 0x08: /*OR*/
OR_HOST_REG_IMM(host_reg, imm);
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op, FLAGS_ZN32);
break;
case 0x20: /*AND*/
AND_HOST_REG_IMM(host_reg, imm);
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op, FLAGS_ZN32);
break;
case 0x28: /*SUB*/
STORE_HOST_REG_ADDR((uint32_t)&cpu_state.flags_op1, host_reg);
SUB_HOST_REG_IMM(host_reg, imm);
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op2, imm);
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op, FLAGS_SUB32);
break;
case 0x30: /*XOR*/
XOR_HOST_REG_IMM(host_reg, imm);
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op, FLAGS_ZN32);
break;
case 0x38: /*CMP*/
STORE_HOST_REG_ADDR((uint32_t)&cpu_state.flags_op1, host_reg);
host_reg = CMP_HOST_REG_IMM_L(host_reg, imm);
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op2, imm);
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op, FLAGS_SUB32);
break;
}
STORE_HOST_REG_ADDR((uint32_t)&cpu_state.flags_res, host_reg);
if ((fetchdat & 0x38) != 0x38)
STORE_REG_L_RELEASE(host_reg);
else
RELEASE_REG(host_reg);
codegen_flags_changed = 1;
return op_pc + 5;
}
static uint32_t rop83_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
int host_reg;
uint32_t imm;
if ((fetchdat & 0x30) == 0x10 || (fetchdat & 0xc0) != 0xc0)
return 0;
host_reg = LOAD_REG_W(fetchdat & 7);
imm = (fetchdat >> 8) & 0xff;
if (imm & 0x80)
imm |= 0xff80;
switch (fetchdat & 0x38)
{
case 0x00: /*ADD*/
STORE_HOST_REG_ADDR_WL((uint32_t)&cpu_state.flags_op1, host_reg);
ADD_HOST_REG_IMM_W(host_reg, imm);
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op2, imm);
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op, FLAGS_ADD16);
break;
case 0x08: /*OR*/
OR_HOST_REG_IMM(host_reg, imm);
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op, FLAGS_ZN16);
break;
case 0x20: /*AND*/
AND_HOST_REG_IMM(host_reg, imm | 0xffff0000);
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op, FLAGS_ZN16);
break;
case 0x28: /*SUB*/
STORE_HOST_REG_ADDR_WL((uint32_t)&cpu_state.flags_op1, host_reg);
SUB_HOST_REG_IMM_W(host_reg, imm);
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op2, imm);
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op, FLAGS_SUB16);
break;
case 0x30: /*XOR*/
XOR_HOST_REG_IMM(host_reg, imm);
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op, FLAGS_ZN16);
break;
case 0x38: /*CMP*/
STORE_HOST_REG_ADDR_WL((uint32_t)&cpu_state.flags_op1, host_reg);
host_reg = CMP_HOST_REG_IMM_W(host_reg, imm);
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op2, imm);
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op, FLAGS_SUB16);
break;
}
STORE_HOST_REG_ADDR_WL((uint32_t)&cpu_state.flags_res, host_reg);
if ((fetchdat & 0x38) != 0x38)
STORE_REG_W_RELEASE(host_reg);
else
RELEASE_REG(host_reg);
codegen_flags_changed = 1;
return op_pc + 2;
}
static uint32_t rop83_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
int host_reg;
uint32_t imm;
if ((fetchdat & 0x30) == 0x10 || (fetchdat & 0xc0) != 0xc0)
return 0;
host_reg = LOAD_REG_L(fetchdat & 7);
imm = (fetchdat >> 8) & 0xff;
if (imm & 0x80)
imm |= 0xffffff80;
switch (fetchdat & 0x38)
{
case 0x00: /*ADD*/
STORE_HOST_REG_ADDR((uint32_t)&cpu_state.flags_op1, host_reg);
ADD_HOST_REG_IMM(host_reg, imm);
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op2, imm);
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op, FLAGS_ADD32);
break;
case 0x08: /*OR*/
OR_HOST_REG_IMM(host_reg, imm);
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op, FLAGS_ZN32);
break;
case 0x20: /*AND*/
AND_HOST_REG_IMM(host_reg, imm);
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op, FLAGS_ZN32);
break;
case 0x28: /*SUB*/
STORE_HOST_REG_ADDR((uint32_t)&cpu_state.flags_op1, host_reg);
SUB_HOST_REG_IMM(host_reg, imm);
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op2, imm);
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op, FLAGS_SUB32);
break;
case 0x30: /*XOR*/
XOR_HOST_REG_IMM(host_reg, imm);
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op, FLAGS_ZN32);
break;
case 0x38: /*CMP*/
STORE_HOST_REG_ADDR((uint32_t)&cpu_state.flags_op1, host_reg);
host_reg = CMP_HOST_REG_IMM_L(host_reg, imm);
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op2, imm);
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op, FLAGS_SUB32);
break;
}
STORE_HOST_REG_ADDR((uint32_t)&cpu_state.flags_res, host_reg);
if ((fetchdat & 0x38) != 0x38)
STORE_REG_L_RELEASE(host_reg);
else
RELEASE_REG(host_reg);
codegen_flags_changed = 1;
return op_pc + 2;
}

601
src/codegen_ops_fpu.h Normal file
View File

@@ -0,0 +1,601 @@
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)&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)&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)&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)&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)&oldpc, op_old_pc);
CHECK_SEG_READ(target_seg);
MEM_LOAD_ADDR_EA_Q(target_seg);
FP_LOAD_IQ();
codegen_fpu_loaded_iq[(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)&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)&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)&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)&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)&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)&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)&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)&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 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(&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)&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)&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)&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)&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)&npxc);
MEM_STORE_ADDR_EA_W(target_seg, host_reg);
return op_pc + 1;
}

270
src/codegen_ops_jump.h Normal file
View File

@@ -0,0 +1,270 @@
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;
if (offset & 0x80)
offset |= 0xffffff00;
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.pc, op_pc+1+offset);
return -1;
}
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;
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.pc, (op_pc+2+offset) & 0xffff);
return -1;
}
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);
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 int BRANCH_COND_B(int pc_offset, uint32_t op_pc, uint32_t offset, int not)
{
CALL_FUNC(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 int 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(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 int BRANCH_COND_O(int pc_offset, uint32_t op_pc, uint32_t offset, int not)
{
CALL_FUNC(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 int BRANCH_COND_P(int pc_offset, uint32_t op_pc, uint32_t offset, int not)
{
CALL_FUNC(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 int 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(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)

507
src/codegen_ops_logic.h Normal file
View File

@@ -0,0 +1,507 @@
#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; \
\
if ((fetchdat & 0xc0) != 0xc0) \
return 0; \
\
dst_reg = LOAD_REG_B(fetchdat & 7); \
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) 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_rmw(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) \
return 0; \
\
dst_reg = LOAD_REG_W(fetchdat & 7); \
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) 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_rmw(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) \
return 0; \
\
dst_reg = LOAD_REG_L(fetchdat & 7); \
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) STORE_REG_L_RELEASE(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)&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)&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)&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; \
}
ROP_LOGIC(AND, AND, 1)
ROP_LOGIC(OR, OR, 1)
ROP_LOGIC(XOR, XOR, 1)
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;
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)&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)&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)&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)&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)&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)&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;
}

115
src/codegen_ops_misc.h Normal file
View File

@@ -0,0 +1,115 @@
static uint32_t ropNOP(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
return 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;
}
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)
{
int host_reg;
if ((fetchdat & 0x38) != 0x10 && (fetchdat & 0x38) != 0x20)// && (fetchdat & 0x38) != 0x30)
return 0;
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);
STORE_IMM_ADDR_L((uintptr_t)&oldpc, op_old_pc);
MEM_LOAD_ADDR_EA_W(target_seg);
host_reg = 0;
}
switch (fetchdat & 0x38)
{
case 0x10: /*CALL*/
STORE_HOST_REG_ADDR_W((uintptr_t)&codegen_temp, host_reg);
RELEASE_REG(host_reg);
STORE_IMM_ADDR_L((uintptr_t)&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)&oldpc, op_old_pc);
LOAD_STACK_TO_EA(-2);
MEM_STORE_ADDR_EA_W(&_ss, host_reg);
SP_MODIFY(-2);
return op_pc + 1;
}
}
static uint32_t ropFF_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
int host_reg;
if ((fetchdat & 0x38) != 0x10 && (fetchdat & 0x38) != 0x20)// && (fetchdat & 0x38) != 0x30)
return 0;
if ((fetchdat & 0xc0) == 0xc0)
{
host_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)&oldpc, op_old_pc);
MEM_LOAD_ADDR_EA_L(target_seg);
host_reg = 0;
}
switch (fetchdat & 0x38)
{
case 0x10: /*CALL*/
STORE_HOST_REG_ADDR((uintptr_t)&codegen_temp, host_reg);
RELEASE_REG(host_reg);
STORE_IMM_ADDR_L((uintptr_t)&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)&oldpc, op_old_pc);
LOAD_STACK_TO_EA(-4);
MEM_STORE_ADDR_EA_L(&_ss, host_reg);
SP_MODIFY(-4);
return op_pc + 1;
}
}

277
src/codegen_ops_mmx.h Normal file
View File

@@ -0,0 +1,277 @@
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)&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)&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)&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)&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)&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;
}

506
src/codegen_ops_mov.h Normal file
View File

@@ -0,0 +1,506 @@
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);
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);
STORE_IMM_REG_L(opcode & 7, fetchdat);
return op_pc + 4;
}
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);
STORE_IMM_ADDR_L((uintptr_t)&oldpc, op_old_pc);
CHECK_SEG_WRITE(target_seg);
CHECK_SEG_LIMITS(target_seg, 0);
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);
STORE_IMM_ADDR_L((uintptr_t)&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_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);
STORE_IMM_ADDR_L((uintptr_t)&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)&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)&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)&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)&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)&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)&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)&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)&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)&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)&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)&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)&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)&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)&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)&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)&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)&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)&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;
}

114
src/codegen_ops_shift.h Normal file
View File

@@ -0,0 +1,114 @@
#define SHIFT(size, size2, count, res_store) \
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op2, count); \
reg = LOAD_REG_ ## size(fetchdat & 7); \
res_store((uint32_t)&cpu_state.flags_op1, reg); \
\
switch (fetchdat & 0x38) \
{ \
case 0x20: case 0x30: /*SHL*/ \
SHL_ ## size ## _IMM(reg, count); \
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op, FLAGS_SHL ## size2); \
break; \
\
case 0x28: /*SHR*/ \
SHR_ ## size ## _IMM(reg, count); \
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op, FLAGS_SHR ## size2); \
break; \
\
case 0x38: /*SAR*/ \
SAR_ ## size ## _IMM(reg, count); \
STORE_IMM_ADDR_L((uint32_t)&cpu_state.flags_op, FLAGS_SAR ## size2); \
break; \
} \
\
res_store((uint32_t)&cpu_state.flags_res, reg); \
STORE_REG_ ## size ## _RELEASE(reg);
static uint32_t ropC0(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
int count;
int reg;
if ((fetchdat & 0xc0) != 0xc0)
return 0;
if ((fetchdat & 0x38) < 0x20)
return 0;
count = (fetchdat >> 8) & 0x1f;
SHIFT(B, 8, count, STORE_HOST_REG_ADDR_BL);
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)
{
int count;
int reg;
if ((fetchdat & 0xc0) != 0xc0)
return 0;
if ((fetchdat & 0x38) < 0x20)
return 0;
count = (fetchdat >> 8) & 0x1f;
SHIFT(W, 16, count, STORE_HOST_REG_ADDR_WL);
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)
{
int count;
int reg;
if ((fetchdat & 0xc0) != 0xc0)
return 0;
if ((fetchdat & 0x38) < 0x20)
return 0;
count = (fetchdat >> 8) & 0x1f;
SHIFT(L, 32, count, STORE_HOST_REG_ADDR);
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)
{
int reg;
if ((fetchdat & 0xc0) != 0xc0)
return 0;
if ((fetchdat & 0x38) < 0x20)
return 0;
SHIFT(B, 8, 1, STORE_HOST_REG_ADDR_BL);
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)
{
int reg;
if ((fetchdat & 0xc0) != 0xc0)
return 0;
if ((fetchdat & 0x38) < 0x20)
return 0;
SHIFT(W, 16, 1, STORE_HOST_REG_ADDR_WL);
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)
{
int reg;
if ((fetchdat & 0xc0) != 0xc0)
return 0;
if ((fetchdat & 0x38) < 0x20)
return 0;
SHIFT(L, 32, 1, STORE_HOST_REG_ADDR);
return op_pc + 1;
}

250
src/codegen_ops_stack.h Normal file
View File

@@ -0,0 +1,250 @@
static uint32_t ropPUSH_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
int host_reg;
STORE_IMM_ADDR_L((uintptr_t)&oldpc, op_old_pc);
LOAD_STACK_TO_EA(-2);
host_reg = LOAD_REG_W(opcode & 7);
MEM_STORE_ADDR_EA_W(&_ss, host_reg);
SP_MODIFY(-2);
return op_pc;
}
static uint32_t ropPUSH_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
int host_reg;
STORE_IMM_ADDR_L((uintptr_t)&oldpc, op_old_pc);
LOAD_STACK_TO_EA(-4);
host_reg = LOAD_REG_L(opcode & 7);
MEM_STORE_ADDR_EA_L(&_ss, host_reg);
SP_MODIFY(-4);
return op_pc;
}
static uint32_t ropPUSH_imm_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
uint16_t imm = fetchdat & 0xffff;
int host_reg;
STORE_IMM_ADDR_L((uintptr_t)&oldpc, op_old_pc);
LOAD_STACK_TO_EA(-2);
host_reg = LOAD_REG_IMM(imm);
MEM_STORE_ADDR_EA_W(&_ss, host_reg);
SP_MODIFY(-2);
return op_pc+2;
}
static uint32_t ropPUSH_imm_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
uint32_t imm = fastreadl(cs + op_pc);
int host_reg;
STORE_IMM_ADDR_L((uintptr_t)&oldpc, op_old_pc);
LOAD_STACK_TO_EA(-4);
host_reg = LOAD_REG_IMM(imm);
MEM_STORE_ADDR_EA_L(&_ss, host_reg);
SP_MODIFY(-4);
return op_pc+4;
}
static uint32_t ropPUSH_imm_b16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
uint16_t imm = fetchdat & 0xff;
int host_reg;
if (imm & 0x80)
imm |= 0xff00;
STORE_IMM_ADDR_L((uintptr_t)&oldpc, op_old_pc);
LOAD_STACK_TO_EA(-2);
host_reg = LOAD_REG_IMM(imm);
MEM_STORE_ADDR_EA_W(&_ss, host_reg);
SP_MODIFY(-2);
return op_pc+1;
}
static uint32_t ropPUSH_imm_b32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
uint32_t imm = fetchdat & 0xff;
int host_reg;
if (imm & 0x80)
imm |= 0xffffff00;
STORE_IMM_ADDR_L((uintptr_t)&oldpc, op_old_pc);
LOAD_STACK_TO_EA(-4);
host_reg = LOAD_REG_IMM(imm);
MEM_STORE_ADDR_EA_L(&_ss, host_reg);
SP_MODIFY(-4);
return op_pc+1;
}
static uint32_t ropPOP_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
int host_reg;
STORE_IMM_ADDR_L((uintptr_t)&oldpc, op_old_pc);
LOAD_STACK_TO_EA(0);
MEM_LOAD_ADDR_EA_W(&_ss);
SP_MODIFY(2);
STORE_REG_TARGET_W_RELEASE(0, opcode & 7);
return op_pc;
}
static uint32_t ropPOP_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
int host_reg;
STORE_IMM_ADDR_L((uintptr_t)&oldpc, op_old_pc);
LOAD_STACK_TO_EA(0);
MEM_LOAD_ADDR_EA_L(&_ss);
SP_MODIFY(4);
STORE_REG_TARGET_L_RELEASE(0, opcode & 7);
return op_pc;
}
static uint32_t ropRET_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
int host_reg;
STORE_IMM_ADDR_L((uintptr_t)&oldpc, op_old_pc);
LOAD_STACK_TO_EA(0);
MEM_LOAD_ADDR_EA_W(&_ss);
STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.pc, 0);
SP_MODIFY(2);
return -1;
}
static uint32_t ropRET_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
int host_reg;
STORE_IMM_ADDR_L((uintptr_t)&oldpc, op_old_pc);
LOAD_STACK_TO_EA(0);
MEM_LOAD_ADDR_EA_L(&_ss);
STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.pc, 0);
SP_MODIFY(4);
return -1;
}
static uint32_t ropRET_imm_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
uint16_t offset = fetchdat & 0xffff;
int host_reg;
STORE_IMM_ADDR_L((uintptr_t)&oldpc, op_old_pc);
LOAD_STACK_TO_EA(0);
MEM_LOAD_ADDR_EA_W(&_ss);
STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.pc, 0);
SP_MODIFY(2+offset);
return -1;
}
static uint32_t ropRET_imm_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
uint16_t offset = fetchdat & 0xffff;
int host_reg;
STORE_IMM_ADDR_L((uintptr_t)&oldpc, op_old_pc);
LOAD_STACK_TO_EA(0);
MEM_LOAD_ADDR_EA_L(&_ss);
STORE_HOST_REG_ADDR((uintptr_t)&cpu_state.pc, 0);
SP_MODIFY(4+offset);
return -1;
}
static uint32_t ropCALL_r16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
uint16_t offset = fetchdat & 0xffff;
int host_reg;
STORE_IMM_ADDR_L((uintptr_t)&oldpc, op_old_pc);
LOAD_STACK_TO_EA(-2);
host_reg = LOAD_REG_IMM(op_pc+2);
MEM_STORE_ADDR_EA_W(&_ss, host_reg);
SP_MODIFY(-2);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.pc, (op_pc+2+offset) & 0xffff);
return -1;
}
static uint32_t ropCALL_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);
int host_reg;
STORE_IMM_ADDR_L((uintptr_t)&oldpc, op_old_pc);
LOAD_STACK_TO_EA(-4);
host_reg = LOAD_REG_IMM(op_pc+4);
MEM_STORE_ADDR_EA_L(&_ss, host_reg);
SP_MODIFY(-4);
STORE_IMM_ADDR_L((uintptr_t)&cpu_state.pc, op_pc+4+offset);
return -1;
}
static uint32_t ropLEAVE_16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
int host_reg;
STORE_IMM_ADDR_L((uintptr_t)&oldpc, op_old_pc);
LOAD_EBP_TO_EA(0);
MEM_LOAD_ADDR_EA_W(&_ss);
host_reg = LOAD_REG_W(REG_BP); /*SP = BP + 2*/
ADD_HOST_REG_IMM_W(host_reg, 2);
STORE_REG_TARGET_W_RELEASE(host_reg, REG_SP);
STORE_REG_TARGET_W_RELEASE(0, REG_BP); /*BP = POP_W()*/
return op_pc;
}
static uint32_t ropLEAVE_32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
int host_reg;
STORE_IMM_ADDR_L((uintptr_t)&oldpc, op_old_pc);
LOAD_EBP_TO_EA(0);
MEM_LOAD_ADDR_EA_L(&_ss);
host_reg = LOAD_REG_L(REG_EBP); /*ESP = EBP + 4*/
ADD_HOST_REG_IMM(host_reg, 4);
STORE_REG_TARGET_L_RELEASE(host_reg, REG_ESP);
STORE_REG_TARGET_L_RELEASE(0, REG_EBP); /*EBP = POP_L()*/
return op_pc;
}
#define ROP_PUSH_SEG(seg) \
static uint32_t ropPUSH_ ## seg ## _16(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
{ \
int host_reg; \
\
STORE_IMM_ADDR_L((uintptr_t)&oldpc, op_old_pc); \
LOAD_STACK_TO_EA(-2); \
host_reg = LOAD_VAR_W((uintptr_t)&seg); \
MEM_STORE_ADDR_EA_W(&_ss, host_reg); \
SP_MODIFY(-2); \
\
return op_pc; \
} \
static uint32_t ropPUSH_ ## seg ## _32(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
{ \
int host_reg; \
\
STORE_IMM_ADDR_L((uintptr_t)&oldpc, op_old_pc); \
LOAD_STACK_TO_EA(-4); \
host_reg = LOAD_VAR_W((uintptr_t)&seg); \
MEM_STORE_ADDR_EA_L(&_ss, host_reg); \
SP_MODIFY(-4); \
\
return op_pc; \
}
ROP_PUSH_SEG(CS)
ROP_PUSH_SEG(DS)
ROP_PUSH_SEG(ES)
ROP_PUSH_SEG(SS)

4734
src/codegen_ops_x86-64.h Normal file

File diff suppressed because it is too large Load Diff

3393
src/codegen_ops_x86.h Normal file

File diff suppressed because it is too large Load Diff

93
src/codegen_ops_xchg.h Normal file
View File

@@ -0,0 +1,93 @@
#define OP_XCHG_AX_(reg) \
static uint32_t ropXCHG_AX_ ## reg(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
{ \
int ax_reg, host_reg, temp_reg; \
\
ax_reg = LOAD_REG_W(REG_AX); \
host_reg = LOAD_REG_W(REG_ ## reg); \
temp_reg = COPY_REG(host_reg); \
STORE_REG_TARGET_W_RELEASE(ax_reg, REG_ ## reg); \
STORE_REG_TARGET_W_RELEASE(temp_reg, REG_AX); \
\
return op_pc; \
}
OP_XCHG_AX_(BX)
OP_XCHG_AX_(CX)
OP_XCHG_AX_(DX)
OP_XCHG_AX_(SI)
OP_XCHG_AX_(DI)
OP_XCHG_AX_(SP)
OP_XCHG_AX_(BP)
#define OP_XCHG_EAX_(reg) \
static uint32_t ropXCHG_EAX_ ## reg(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block) \
{ \
int eax_reg, host_reg, temp_reg; \
\
eax_reg = LOAD_REG_L(REG_EAX); \
host_reg = LOAD_REG_L(REG_ ## reg); \
temp_reg = COPY_REG(host_reg); \
STORE_REG_TARGET_L_RELEASE(eax_reg, REG_ ## reg); \
STORE_REG_TARGET_L_RELEASE(temp_reg, REG_EAX); \
\
return op_pc; \
}
OP_XCHG_EAX_(EBX)
OP_XCHG_EAX_(ECX)
OP_XCHG_EAX_(EDX)
OP_XCHG_EAX_(ESI)
OP_XCHG_EAX_(EDI)
OP_XCHG_EAX_(ESP)
OP_XCHG_EAX_(EBP)
static uint32_t ropXCHG_b(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
// #ifdef __amd64__
// return 0;
// #else
int src_reg, dst_reg, temp_reg;
if ((fetchdat & 0xc0) != 0xc0)
return 0;
dst_reg = LOAD_REG_B(fetchdat & 7);
src_reg = LOAD_REG_B((fetchdat >> 3) & 7);
temp_reg = COPY_REG(src_reg);
STORE_REG_TARGET_B_RELEASE(dst_reg, (fetchdat >> 3) & 7);
STORE_REG_TARGET_B_RELEASE(temp_reg, fetchdat & 7);
return op_pc + 1;
// #endif
}
static uint32_t ropXCHG_w(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
int src_reg, dst_reg, temp_reg;
if ((fetchdat & 0xc0) != 0xc0)
return 0;
dst_reg = LOAD_REG_W(fetchdat & 7);
src_reg = LOAD_REG_W((fetchdat >> 3) & 7);
temp_reg = COPY_REG(src_reg);
STORE_REG_TARGET_W_RELEASE(dst_reg, (fetchdat >> 3) & 7);
STORE_REG_TARGET_W_RELEASE(temp_reg, fetchdat & 7);
return op_pc + 1;
}
static uint32_t ropXCHG_l(uint8_t opcode, uint32_t fetchdat, uint32_t op_32, uint32_t op_pc, codeblock_t *block)
{
int src_reg, dst_reg, temp_reg;
if ((fetchdat & 0xc0) != 0xc0)
return 0;
dst_reg = LOAD_REG_L(fetchdat & 7);
src_reg = LOAD_REG_L((fetchdat >> 3) & 7);
temp_reg = COPY_REG(src_reg);
STORE_REG_TARGET_L_RELEASE(dst_reg, (fetchdat >> 3) & 7);
STORE_REG_TARGET_L_RELEASE(temp_reg, fetchdat & 7);
return op_pc + 1;
}

375
src/codegen_timing_486.c Normal file
View File

@@ -0,0 +1,375 @@
#include "ibm.h"
#include "cpu.h"
#include "x86.h"
#include "x86_ops.h"
#include "x87.h"
#include "mem.h"
#include "codegen.h"
#define CYCLES(c) (int *)c
#define CYCLES2(c16, c32) (int *)((-1 & ~0xffff) | c16 | (c32 << 8))
static int *opcode_timings[256] =
{
/*00*/ &timing_mr, &timing_mr, &timing_rm, &timing_rm, &timing_rr, &timing_rr, CYCLES(2), CYCLES(3), &timing_mr, &timing_mr, &timing_rm, &timing_rm, &timing_rr, &timing_rr, CYCLES(2), NULL,
/*10*/ &timing_mr, &timing_mr, &timing_rm, &timing_rm, &timing_rr, &timing_rr, CYCLES(2), CYCLES(3), &timing_mr, &timing_mr, &timing_rm, &timing_rm, &timing_rr, &timing_rr, CYCLES(2), CYCLES(3),
/*20*/ &timing_mr, &timing_mr, &timing_rm, &timing_rm, &timing_rr, &timing_rr, CYCLES(4), CYCLES(3), &timing_mr, &timing_mr, &timing_rm, &timing_rm, &timing_rr, &timing_rr, CYCLES(4), CYCLES(3),
/*30*/ &timing_mr, &timing_mr, &timing_rm, &timing_rm, &timing_rr, &timing_rr, CYCLES(4), CYCLES(2), &timing_mr, &timing_mr, &timing_rm, &timing_rm, &timing_rr, &timing_rr, CYCLES(4), CYCLES(2),
/*40*/ &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr,
/*50*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1),
/*60*/ CYCLES(11), CYCLES(9), CYCLES(7), CYCLES(9), CYCLES(4), CYCLES(4), CYCLES(2), CYCLES(2), CYCLES(1), CYCLES2(17,25), CYCLES(1), CYCLES2(17,20), CYCLES(17), CYCLES(17), CYCLES(17), CYCLES(17),
/*70*/ &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt,
/*80*/ &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_rm, &timing_rm, CYCLES(5), CYCLES(5), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(3), CYCLES(1), CYCLES(5), CYCLES(6),
/*90*/ CYCLES(1), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(0), CYCLES(4), CYCLES(4), CYCLES(5), CYCLES(2), CYCLES(3),
/*a0*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(7), CYCLES(7), CYCLES(8), CYCLES(8), CYCLES(1), CYCLES(1), CYCLES(5), CYCLES(5), CYCLES(5), CYCLES(5), CYCLES(6), CYCLES(6),
/*b0*/ &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr,
/*c0*/ CYCLES(4), CYCLES(4), CYCLES(5), CYCLES(5), CYCLES(6), CYCLES(6), CYCLES(1), CYCLES(1), CYCLES(14), CYCLES(5), CYCLES(0), CYCLES(0), &timing_int, &timing_int, CYCLES(3), CYCLES(0),
/*d0*/ CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(15), CYCLES(14), CYCLES(2), CYCLES(4), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*e0*/ CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(5), CYCLES(14), CYCLES(14), CYCLES(16), CYCLES(16), CYCLES(3), CYCLES(3), CYCLES(17), CYCLES(3), CYCLES(14), CYCLES(14), CYCLES(14), CYCLES(14),
/*f0*/ CYCLES(4), CYCLES(0), CYCLES(0), CYCLES(0), CYCLES(4), CYCLES(2), NULL, NULL, CYCLES(2), CYCLES(2), CYCLES(3), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(3), NULL
};
static int *opcode_timings_mod3[256] =
{
/*00*/ &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, CYCLES(2), CYCLES(3), &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, CYCLES(2), NULL,
/*10*/ &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, CYCLES(2), CYCLES(3), &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, CYCLES(2), CYCLES(3),
/*20*/ &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, CYCLES(4), CYCLES(3), &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, CYCLES(4), CYCLES(3),
/*30*/ &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, CYCLES(4), CYCLES(2), &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, CYCLES(4), CYCLES(2),
/*40*/ &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr,
/*50*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1),
/*60*/ CYCLES(11), CYCLES(9), CYCLES(7), CYCLES(9), CYCLES(4), CYCLES(4), CYCLES(2), CYCLES(2), CYCLES(1), CYCLES2(14,25), CYCLES(1), CYCLES2(17,20), CYCLES(17), CYCLES(17), CYCLES(17), CYCLES(17),
/*70*/ &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt,
/*80*/ &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, CYCLES(5), CYCLES(5), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(2), CYCLES(1), CYCLES(2), CYCLES(1),
/*90*/ CYCLES(1), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(0), CYCLES(4), CYCLES(4), CYCLES(5), CYCLES(2), CYCLES(3),
/*a0*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(7), CYCLES(7), CYCLES(8), CYCLES(8), CYCLES(1), CYCLES(1), CYCLES(5), CYCLES(5), CYCLES(5), CYCLES(5), CYCLES(6), CYCLES(6),
/*b0*/ &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr,
/*c0*/ CYCLES(4), CYCLES(4), CYCLES(5), CYCLES(5), CYCLES(6), CYCLES(6), CYCLES(1), CYCLES(1), CYCLES(14), CYCLES(5), CYCLES(0), CYCLES(0), &timing_int, &timing_int, CYCLES(3), CYCLES(0),
/*d0*/ CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(15), CYCLES(14), CYCLES(2), CYCLES(4), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*e0*/ CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(5), CYCLES(14), CYCLES(14), CYCLES(16), CYCLES(16), CYCLES(3), CYCLES(3), CYCLES(17), CYCLES(3), CYCLES(14), CYCLES(14), CYCLES(14), CYCLES(14),
/*f0*/ CYCLES(4), CYCLES(0), CYCLES(0), CYCLES(0), CYCLES(4), CYCLES(2), NULL, NULL, CYCLES(2), CYCLES(2), CYCLES(3), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(3), NULL
};
static int *opcode_timings_0f[256] =
{
/*00*/ CYCLES(20), CYCLES(11), CYCLES(11), CYCLES(10), NULL, CYCLES(195), CYCLES(7), NULL, CYCLES(1000), CYCLES(10000), NULL, NULL, NULL, NULL, NULL, NULL,
/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*20*/ CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(6), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*30*/ CYCLES(9), CYCLES(1), CYCLES(9), 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*/ &timing_rm, &timing_rm, &timing_rm, &timing_rm, &timing_rm, &timing_rm, &timing_rm, &timing_rm, &timing_rm, &timing_rm, &timing_rm, &timing_rm, NULL, NULL, &timing_rm, &timing_rm,
/*70*/ NULL, &timing_rm, &timing_rm, &timing_rm, &timing_rm, &timing_rm, &timing_rm, CYCLES(100), NULL, NULL, NULL, NULL, NULL, NULL, &timing_rm, &timing_rm,
/*80*/ &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt,
/*90*/ CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3),
/*a0*/ CYCLES(3), CYCLES(3), CYCLES(14), CYCLES(8), CYCLES(3), CYCLES(4), NULL, NULL, CYCLES(3), CYCLES(3), NULL, CYCLES(13), CYCLES(3), CYCLES(3), NULL, CYCLES2(18,30),
/*b0*/ CYCLES(10), CYCLES(10), CYCLES(6), CYCLES(13), CYCLES(6), CYCLES(6), CYCLES(3), CYCLES(3), NULL, NULL, CYCLES(6), CYCLES(13), CYCLES(7), CYCLES(7), CYCLES(3), CYCLES(3),
/*c0*/ CYCLES(4), CYCLES(4), NULL, NULL, NULL, NULL, NULL, NULL, CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1),
/*d0*/ NULL, &timing_rm, &timing_rm, &timing_rm, NULL, &timing_rm, NULL, NULL, &timing_rm, &timing_rm, NULL, &timing_rm, &timing_rm, &timing_rm, NULL, &timing_rm,
/*e0*/ NULL, &timing_rm, &timing_rm, NULL, NULL, &timing_rm, NULL, NULL, &timing_rm, &timing_rm, NULL, &timing_rm, &timing_rm, &timing_rm, NULL, &timing_rm,
/*f0*/ NULL, &timing_rm, &timing_rm, &timing_rm, NULL, &timing_rm, NULL, NULL, &timing_rm, &timing_rm, &timing_rm, NULL, &timing_rm, &timing_rm, &timing_rm, NULL,
};
static int *opcode_timings_0f_mod3[256] =
{
/*00*/ CYCLES(20), CYCLES(11), CYCLES(11), CYCLES(10), NULL, CYCLES(195), CYCLES(7), NULL, CYCLES(1000), CYCLES(10000), NULL, NULL, NULL, NULL, NULL, NULL,
/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*20*/ CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(6), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*30*/ CYCLES(9), CYCLES(1), CYCLES(9), 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*/ &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, NULL, NULL, &timing_rr, &timing_rr,
/*70*/ NULL, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, CYCLES(100), NULL, NULL, NULL, NULL, NULL, NULL, &timing_rr, &timing_rr,
/*80*/ &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt,
/*90*/ CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3),
/*a0*/ CYCLES(3), CYCLES(3), CYCLES(14), CYCLES(8), CYCLES(3), CYCLES(4), NULL, NULL, CYCLES(3), CYCLES(3), NULL, CYCLES(13), CYCLES(3), CYCLES(3), NULL, CYCLES2(18,30),
/*b0*/ CYCLES(10), CYCLES(10), CYCLES(6), CYCLES(13), CYCLES(6), CYCLES(6), CYCLES(3), CYCLES(3), NULL, NULL, CYCLES(6), CYCLES(13), CYCLES(7), CYCLES(7), CYCLES(3), CYCLES(3),
/*c0*/ CYCLES(4), CYCLES(4), NULL, NULL, NULL, NULL, NULL, NULL, CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1),
/*d0*/ NULL, &timing_rr, &timing_rr, &timing_rr, NULL, &timing_rr, NULL, NULL, &timing_rr, &timing_rr, NULL, &timing_rr, &timing_rr, &timing_rr, NULL, &timing_rr,
/*e0*/ NULL, &timing_rr, &timing_rr, NULL, NULL, &timing_rr, NULL, NULL, &timing_rr, &timing_rr, NULL, &timing_rr, &timing_rr, &timing_rr, NULL, &timing_rr,
/*f0*/ NULL, &timing_rr, &timing_rr, &timing_rr, NULL, &timing_rr, NULL, NULL, &timing_rr, &timing_rr, &timing_rr, NULL, &timing_rr, &timing_rr, &timing_rr, NULL,
};
static int *opcode_timings_shift[8] =
{
CYCLES(7), CYCLES(7), CYCLES(10), CYCLES(10), CYCLES(7), CYCLES(7), CYCLES(7), CYCLES(7)
};
static int *opcode_timings_shift_mod3[8] =
{
CYCLES(3), CYCLES(3), CYCLES(9), CYCLES(9), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3)
};
static int *opcode_timings_f6[8] =
{
&timing_rm, NULL, &timing_mm, &timing_mm, CYCLES(13), CYCLES(14), CYCLES(16), CYCLES(19)
};
static int *opcode_timings_f6_mod3[8] =
{
&timing_rr, NULL, &timing_rr, &timing_rr, CYCLES(13), CYCLES(14), CYCLES(16), CYCLES(19)
};
static int *opcode_timings_f7[8] =
{
&timing_rm, NULL, &timing_mm, &timing_mm, CYCLES(21), CYCLES2(22,38), CYCLES2(24,40), CYCLES2(27,43)
};
static int *opcode_timings_f7_mod3[8] =
{
&timing_rr, NULL, &timing_rr, &timing_rr, CYCLES(21), CYCLES2(22,38), CYCLES2(24,40), CYCLES2(27,43)
};
static int *opcode_timings_ff[8] =
{
&timing_mm, &timing_mm, CYCLES(5), CYCLES(0), CYCLES(5), CYCLES(0), CYCLES(5), NULL
};
static int *opcode_timings_ff_mod3[8] =
{
&timing_rr, &timing_rr, CYCLES(5), CYCLES(0), CYCLES(5), CYCLES(0), CYCLES(5), NULL
};
static int *opcode_timings_d8[8] =
{
/* FADDil FMULil FCOMil FCOMPil FSUBil FSUBRil FDIVil FDIVRil*/
CYCLES(8), CYCLES(11), CYCLES(4), CYCLES(4), CYCLES(8), CYCLES(8), CYCLES(73), CYCLES(73)
};
static int *opcode_timings_d8_mod3[8] =
{
/* FADD FMUL FCOM FCOMP FSUB FSUBR FDIV FDIVR*/
CYCLES(8), CYCLES(16), CYCLES(4), CYCLES(4), CYCLES(8), CYCLES(8), CYCLES(73), CYCLES(73)
};
static int *opcode_timings_d9[8] =
{
/* FLDs FSTs FSTPs FLDENV FLDCW FSTENV FSTCW*/
CYCLES(3), NULL, CYCLES(7), CYCLES(7), CYCLES(34), CYCLES(4), CYCLES(67), CYCLES(3)
};
static int *opcode_timings_d9_mod3[64] =
{
/*FLD*/
CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(4),
/*FXCH*/
CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(4),
/*FNOP*/
CYCLES(3), NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*FSTP*/
CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3),
/* opFCHS opFABS opFTST opFXAM*/
CYCLES(6), CYCLES(3), NULL, NULL, CYCLES(4), CYCLES(8), NULL, NULL,
/* opFLD1 opFLDL2T opFLDL2E opFLDPI opFLDEG2 opFLDLN2 opFLDZ*/
CYCLES(4), CYCLES(8), CYCLES(8), CYCLES(8), CYCLES(8), CYCLES(8), CYCLES(4), NULL,
/* opF2XM1 opFYL2X opFPTAN opFPATAN opFDECSTP opFINCSTP,*/
CYCLES(140), CYCLES(196), CYCLES(200), CYCLES(218), NULL, NULL, CYCLES(3), CYCLES(3),
/* opFPREM opFSQRT opFSINCOS opFRNDINT opFSCALE opFSIN opFCOS*/
CYCLES(70), NULL, CYCLES(83), CYCLES(292), CYCLES(21), CYCLES(30), CYCLES(257), CYCLES(257)
};
static int *opcode_timings_da[8] =
{
/* FADDil FMULil FCOMil FCOMPil FSUBil FSUBRil FDIVil FDIVRil*/
CYCLES(8), CYCLES(11), CYCLES(4), CYCLES(4), CYCLES(8), CYCLES(8), CYCLES(73), CYCLES(73)
};
static int *opcode_timings_da_mod3[8] =
{
NULL, NULL, NULL, NULL, NULL, CYCLES(5), NULL, NULL
};
static int *opcode_timings_db[8] =
{
/* FLDil FSTil FSTPil FLDe FSTPe*/
CYCLES(9), NULL, CYCLES(28), CYCLES(28), NULL, CYCLES(5), NULL, CYCLES(6)
};
static int *opcode_timings_db_mod3[64] =
{
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/* opFNOP opFCLEX opFINIT opFNOP opFNOP*/
NULL, CYCLES(3), CYCLES(7), CYCLES(17), CYCLES(3), CYCLES(3), NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
};
static int *opcode_timings_dc[8] =
{
/* opFADDd_a16 opFMULd_a16 opFCOMd_a16 opFCOMPd_a16 opFSUBd_a16 opFSUBRd_a16 opFDIVd_a16 opFDIVRd_a16*/
CYCLES(8), CYCLES(11), CYCLES(4), CYCLES(4), CYCLES(8), CYCLES(8), CYCLES(73), CYCLES(73)
};
static int *opcode_timings_dc_mod3[8] =
{
/* opFADDr opFMULr opFSUBRr opFSUBr opFDIVRr opFDIVr*/
CYCLES(8), CYCLES(16), NULL, NULL, CYCLES(8), CYCLES(8), CYCLES(73), CYCLES(73)
};
static int *opcode_timings_dd[8] =
{
/* FLDd FSTd FSTPd FRSTOR FSAVE FSTSW*/
CYCLES(3), NULL, CYCLES(8), CYCLES(8), CYCLES(131), NULL, CYCLES(154), CYCLES(3)
};
static int *opcode_timings_dd_mod3[8] =
{
/* FFFREE FST FSTP FUCOM FUCOMP*/
CYCLES(3), NULL, CYCLES(3), CYCLES(3), CYCLES(4), CYCLES(4), NULL, NULL
};
static int *opcode_timings_de[8] =
{
/* FADDiw FMULiw FCOMiw FCOMPiw FSUBil FSUBRil FDIVil FDIVRil*/
CYCLES(8), CYCLES(11), CYCLES(4), CYCLES(4), CYCLES(8), CYCLES(8), CYCLES(73), CYCLES(73)
};
static int *opcode_timings_de_mod3[8] =
{
/* FADD FMUL FCOMPP FSUB FSUBR FDIV FDIVR*/
CYCLES(8), CYCLES(16), NULL, CYCLES(5), CYCLES(8), CYCLES(8), CYCLES(73), CYCLES(73)
};
static int *opcode_timings_df[8] =
{
/* FILDiw FISTiw FISTPiw FILDiq FBSTP FISTPiq*/
CYCLES(13), NULL, CYCLES(29), CYCLES(29), NULL, CYCLES(10), CYCLES(172), CYCLES(28)
};
static int *opcode_timings_df_mod3[8] =
{
/* FFREE FST FSTP FUCOM FUCOMP*/
CYCLES(3), NULL, CYCLES(3), CYCLES(3), CYCLES(4), CYCLES(4), NULL, NULL
};
static int *opcode_timings_8x[8] =
{
&timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_rm
};
static int timing_count;
static uint8_t last_prefix;
static inline int COUNT(int *c, int op_32)
{
if ((uintptr_t)c <= 10000)
return (int)c;
if (((uintptr_t)c & ~0xffff) == (-1 & ~0xffff))
{
if (op_32 & 0x100)
return ((uintptr_t)c >> 8) & 0xff;
return (uintptr_t)c & 0xff;
}
return *c;
}
void codegen_timing_486_block_start()
{
}
void codegen_timing_486_start()
{
timing_count = 0;
last_prefix = 0;
}
void codegen_timing_486_prefix(uint8_t prefix, uint32_t fetchdat)
{
timing_count += COUNT(opcode_timings[prefix], 0);
last_prefix = prefix;
}
void codegen_timing_486_opcode(uint8_t opcode, uint32_t fetchdat, int op_32)
{
int **timings;
int mod3 = ((fetchdat & 0xc0) == 0xc0);
switch (last_prefix)
{
case 0x0f:
timings = mod3 ? opcode_timings_0f_mod3 : opcode_timings_0f;
break;
case 0xd8:
timings = mod3 ? opcode_timings_d8_mod3 : opcode_timings_d8;
opcode = (opcode >> 3) & 7;
break;
case 0xd9:
timings = mod3 ? opcode_timings_d9_mod3 : opcode_timings_d9;
opcode = mod3 ? opcode & 0x3f : (opcode >> 3) & 7;
break;
case 0xda:
timings = mod3 ? opcode_timings_da_mod3 : opcode_timings_da;
opcode = (opcode >> 3) & 7;
break;
case 0xdb:
timings = mod3 ? opcode_timings_db_mod3 : opcode_timings_db;
opcode = mod3 ? opcode & 0x3f : (opcode >> 3) & 7;
break;
case 0xdc:
timings = mod3 ? opcode_timings_dc_mod3 : opcode_timings_dc;
opcode = (opcode >> 3) & 7;
break;
case 0xdd:
timings = mod3 ? opcode_timings_dd_mod3 : opcode_timings_dd;
opcode = (opcode >> 3) & 7;
break;
case 0xde:
timings = mod3 ? opcode_timings_de_mod3 : opcode_timings_de;
opcode = (opcode >> 3) & 7;
break;
case 0xdf:
timings = mod3 ? opcode_timings_df_mod3 : opcode_timings_df;
opcode = (opcode >> 3) & 7;
break;
default:
switch (opcode)
{
case 0x80: case 0x81: case 0x82: case 0x83:
timings = mod3 ? opcode_timings_mod3 : opcode_timings_8x;
if (!mod3)
opcode = (fetchdat >> 3) & 7;
break;
case 0xc0: case 0xc1: case 0xd0: case 0xd1: case 0xd2: case 0xd3:
timings = mod3 ? opcode_timings_shift_mod3 : opcode_timings_shift;
opcode = (fetchdat >> 3) & 7;
break;
case 0xf6:
timings = mod3 ? opcode_timings_f6_mod3 : opcode_timings_f6;
opcode = (fetchdat >> 3) & 7;
break;
case 0xf7:
timings = mod3 ? opcode_timings_f7_mod3 : opcode_timings_f7;
opcode = (fetchdat >> 3) & 7;
break;
case 0xff:
timings = mod3 ? opcode_timings_ff_mod3 : opcode_timings_ff;
opcode = (fetchdat >> 3) & 7;
break;
default:
timings = mod3 ? opcode_timings_mod3 : opcode_timings;
break;
}
}
timing_count += COUNT(timings[opcode], op_32);
codegen_block_cycles += timing_count;
}
void codegen_timing_486_block_end()
{
}
codegen_timing_t codegen_timing_486 =
{
codegen_timing_486_start,
codegen_timing_486_prefix,
codegen_timing_486_opcode,
codegen_timing_486_block_start,
codegen_timing_486_block_end
};

1052
src/codegen_timing_686.c Normal file

File diff suppressed because it is too large Load Diff

1061
src/codegen_timing_pentium.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,375 @@
#include "ibm.h"
#include "cpu.h"
#include "x86.h"
#include "x86_ops.h"
#include "x87.h"
#include "mem.h"
#include "codegen.h"
#define CYCLES(c) (int *)c
#define CYCLES2(c16, c32) (int *)((-1 & ~0xffff) | c16 | (c32 << 8))
static int *opcode_timings[256] =
{
/*00*/ &timing_mr, &timing_mr, &timing_rm, &timing_rm, &timing_rr, &timing_rr, CYCLES(2), CYCLES(3), &timing_mr, &timing_mr, &timing_rm, &timing_rm, &timing_rr, &timing_rr, CYCLES(2), NULL,
/*10*/ &timing_mr, &timing_mr, &timing_rm, &timing_rm, &timing_rr, &timing_rr, CYCLES(2), CYCLES(3), &timing_mr, &timing_mr, &timing_rm, &timing_rm, &timing_rr, &timing_rr, CYCLES(2), CYCLES(3),
/*20*/ &timing_mr, &timing_mr, &timing_rm, &timing_rm, &timing_rr, &timing_rr, CYCLES(4), CYCLES(3), &timing_mr, &timing_mr, &timing_rm, &timing_rm, &timing_rr, &timing_rr, CYCLES(4), CYCLES(3),
/*30*/ &timing_mr, &timing_mr, &timing_rm, &timing_rm, &timing_rr, &timing_rr, CYCLES(4), CYCLES(2), &timing_mr, &timing_mr, &timing_rm, &timing_rm, &timing_rr, &timing_rr, CYCLES(4), CYCLES(2),
/*40*/ &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr,
/*50*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1),
/*60*/ CYCLES(11), CYCLES(9), CYCLES(7), CYCLES(9), CYCLES(4), CYCLES(4), CYCLES(2), CYCLES(2), CYCLES(1), CYCLES2(17,25), CYCLES(1), CYCLES2(17,20), CYCLES(17), CYCLES(17), CYCLES(17), CYCLES(17),
/*70*/ &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt,
/*80*/ &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_rm, &timing_rm, CYCLES(5), CYCLES(5), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(3), CYCLES(1), CYCLES(5), CYCLES(6),
/*90*/ CYCLES(1), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(0), CYCLES(4), CYCLES(4), CYCLES(5), CYCLES(2), CYCLES(3),
/*a0*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(7), CYCLES(7), CYCLES(8), CYCLES(8), CYCLES(1), CYCLES(1), CYCLES(5), CYCLES(5), CYCLES(5), CYCLES(5), CYCLES(6), CYCLES(6),
/*b0*/ &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr,
/*c0*/ CYCLES(4), CYCLES(4), CYCLES(5), CYCLES(5), CYCLES(6), CYCLES(6), CYCLES(1), CYCLES(1), CYCLES(14), CYCLES(5), CYCLES(0), CYCLES(0), &timing_int, &timing_int, CYCLES(3), CYCLES(0),
/*d0*/ CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(15), CYCLES(14), CYCLES(2), CYCLES(4), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*e0*/ CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(5), CYCLES(14), CYCLES(14), CYCLES(16), CYCLES(16), CYCLES(3), CYCLES(3), CYCLES(17), CYCLES(3), CYCLES(14), CYCLES(14), CYCLES(14), CYCLES(14),
/*f0*/ CYCLES(4), CYCLES(0), CYCLES(0), CYCLES(0), CYCLES(4), CYCLES(2), NULL, NULL, CYCLES(2), CYCLES(2), CYCLES(3), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(3), NULL
};
static int *opcode_timings_mod3[256] =
{
/*00*/ &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, CYCLES(2), CYCLES(3), &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, CYCLES(2), NULL,
/*10*/ &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, CYCLES(2), CYCLES(3), &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, CYCLES(2), CYCLES(3),
/*20*/ &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, CYCLES(4), CYCLES(3), &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, CYCLES(4), CYCLES(3),
/*30*/ &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, CYCLES(4), CYCLES(2), &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, CYCLES(4), CYCLES(2),
/*40*/ &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr,
/*50*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1),
/*60*/ CYCLES(11), CYCLES(9), CYCLES(7), CYCLES(9), CYCLES(4), CYCLES(4), CYCLES(2), CYCLES(2), CYCLES(1), CYCLES2(14,25), CYCLES(1), CYCLES2(17,20), CYCLES(17), CYCLES(17), CYCLES(17), CYCLES(17),
/*70*/ &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt,
/*80*/ &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, CYCLES(5), CYCLES(5), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(2), CYCLES(1), CYCLES(2), CYCLES(1),
/*90*/ CYCLES(1), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(0), CYCLES(4), CYCLES(4), CYCLES(5), CYCLES(2), CYCLES(3),
/*a0*/ CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(7), CYCLES(7), CYCLES(8), CYCLES(8), CYCLES(1), CYCLES(1), CYCLES(5), CYCLES(5), CYCLES(5), CYCLES(5), CYCLES(6), CYCLES(6),
/*b0*/ &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr,
/*c0*/ CYCLES(4), CYCLES(4), CYCLES(5), CYCLES(5), CYCLES(6), CYCLES(6), CYCLES(1), CYCLES(1), CYCLES(14), CYCLES(5), CYCLES(0), CYCLES(0), &timing_int, &timing_int, CYCLES(3), CYCLES(0),
/*d0*/ CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(15), CYCLES(14), CYCLES(2), CYCLES(4), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*e0*/ CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(5), CYCLES(14), CYCLES(14), CYCLES(16), CYCLES(16), CYCLES(3), CYCLES(3), CYCLES(17), CYCLES(3), CYCLES(14), CYCLES(14), CYCLES(14), CYCLES(14),
/*f0*/ CYCLES(4), CYCLES(0), CYCLES(0), CYCLES(0), CYCLES(4), CYCLES(2), NULL, NULL, CYCLES(2), CYCLES(2), CYCLES(3), CYCLES(2), CYCLES(2), CYCLES(2), CYCLES(3), NULL
};
static int *opcode_timings_0f[256] =
{
/*00*/ CYCLES(20), CYCLES(11), CYCLES(11), CYCLES(10), NULL, CYCLES(195), CYCLES(7), NULL, CYCLES(1000), CYCLES(10000), NULL, NULL, NULL, NULL, NULL, NULL,
/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*20*/ CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(6), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*30*/ CYCLES(9), CYCLES(1), CYCLES(9), 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*/ &timing_rm, &timing_rm, &timing_rm, &timing_rm, &timing_rm, &timing_rm, &timing_rm, &timing_rm, &timing_rm, &timing_rm, &timing_rm, &timing_rm, NULL, NULL, &timing_rm, &timing_rm,
/*70*/ NULL, &timing_rm, &timing_rm, &timing_rm, &timing_rm, &timing_rm, &timing_rm, CYCLES(100), NULL, NULL, NULL, NULL, NULL, NULL, &timing_rm, &timing_rm,
/*80*/ &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt,
/*90*/ CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3),
/*a0*/ CYCLES(3), CYCLES(3), CYCLES(14), CYCLES(8), CYCLES(3), CYCLES(4), NULL, NULL, CYCLES(3), CYCLES(3), NULL, CYCLES(13), CYCLES(3), CYCLES(3), NULL, CYCLES2(18,30),
/*b0*/ CYCLES(10), CYCLES(10), CYCLES(6), CYCLES(13), CYCLES(6), CYCLES(6), CYCLES(3), CYCLES(3), NULL, NULL, CYCLES(6), CYCLES(13), CYCLES(7), CYCLES(7), CYCLES(3), CYCLES(3),
/*c0*/ CYCLES(4), CYCLES(4), NULL, NULL, NULL, NULL, NULL, NULL, CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1),
/*d0*/ NULL, &timing_rm, &timing_rm, &timing_rm, NULL, &timing_rm, NULL, NULL, &timing_rm, &timing_rm, NULL, &timing_rm, &timing_rm, &timing_rm, NULL, &timing_rm,
/*e0*/ NULL, &timing_rm, &timing_rm, NULL, NULL, &timing_rm, NULL, NULL, &timing_rm, &timing_rm, NULL, &timing_rm, &timing_rm, &timing_rm, NULL, &timing_rm,
/*f0*/ NULL, &timing_rm, &timing_rm, &timing_rm, NULL, &timing_rm, NULL, NULL, &timing_rm, &timing_rm, &timing_rm, NULL, &timing_rm, &timing_rm, &timing_rm, NULL,
};
static int *opcode_timings_0f_mod3[256] =
{
/*00*/ CYCLES(20), CYCLES(11), CYCLES(11), CYCLES(10), NULL, CYCLES(195), CYCLES(7), NULL, CYCLES(1000), CYCLES(10000), NULL, NULL, NULL, NULL, NULL, NULL,
/*10*/ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*20*/ CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(6), CYCLES(6), NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*30*/ CYCLES(9), CYCLES(1), CYCLES(9), 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*/ &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, NULL, NULL, &timing_rr, &timing_rr,
/*70*/ NULL, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, &timing_rr, CYCLES(100), NULL, NULL, NULL, NULL, NULL, NULL, &timing_rr, &timing_rr,
/*80*/ &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt, &timing_bnt,
/*90*/ CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3),
/*a0*/ CYCLES(3), CYCLES(3), CYCLES(14), CYCLES(8), CYCLES(3), CYCLES(4), NULL, NULL, CYCLES(3), CYCLES(3), NULL, CYCLES(13), CYCLES(3), CYCLES(3), NULL, CYCLES2(18,30),
/*b0*/ CYCLES(10), CYCLES(10), CYCLES(6), CYCLES(13), CYCLES(6), CYCLES(6), CYCLES(3), CYCLES(3), NULL, NULL, CYCLES(6), CYCLES(13), CYCLES(7), CYCLES(7), CYCLES(3), CYCLES(3),
/*c0*/ CYCLES(4), CYCLES(4), NULL, NULL, NULL, NULL, NULL, NULL, CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1),
/*d0*/ NULL, &timing_rr, &timing_rr, &timing_rr, NULL, &timing_rr, NULL, NULL, &timing_rr, &timing_rr, NULL, &timing_rr, &timing_rr, &timing_rr, NULL, &timing_rr,
/*e0*/ NULL, &timing_rr, &timing_rr, NULL, NULL, &timing_rr, NULL, NULL, &timing_rr, &timing_rr, NULL, &timing_rr, &timing_rr, &timing_rr, NULL, &timing_rr,
/*f0*/ NULL, &timing_rr, &timing_rr, &timing_rr, NULL, &timing_rr, NULL, NULL, &timing_rr, &timing_rr, &timing_rr, NULL, &timing_rr, &timing_rr, &timing_rr, NULL,
};
static int *opcode_timings_shift[8] =
{
CYCLES(7), CYCLES(7), CYCLES(10), CYCLES(10), CYCLES(7), CYCLES(7), CYCLES(7), CYCLES(7)
};
static int *opcode_timings_shift_mod3[8] =
{
CYCLES(3), CYCLES(3), CYCLES(9), CYCLES(9), CYCLES(3), CYCLES(3), CYCLES(3), CYCLES(3)
};
static int *opcode_timings_f6[8] =
{
&timing_rm, NULL, &timing_mm, &timing_mm, CYCLES(13), CYCLES(14), CYCLES(16), CYCLES(19)
};
static int *opcode_timings_f6_mod3[8] =
{
&timing_rr, NULL, &timing_rr, &timing_rr, CYCLES(13), CYCLES(14), CYCLES(16), CYCLES(19)
};
static int *opcode_timings_f7[8] =
{
&timing_rm, NULL, &timing_mm, &timing_mm, CYCLES(21), CYCLES2(22,38), CYCLES2(24,40), CYCLES2(27,43)
};
static int *opcode_timings_f7_mod3[8] =
{
&timing_rr, NULL, &timing_rr, &timing_rr, CYCLES(21), CYCLES2(22,38), CYCLES2(24,40), CYCLES2(27,43)
};
static int *opcode_timings_ff[8] =
{
&timing_mm, &timing_mm, CYCLES(5), CYCLES(0), CYCLES(5), CYCLES(0), CYCLES(5), NULL
};
static int *opcode_timings_ff_mod3[8] =
{
&timing_rr, &timing_rr, CYCLES(5), CYCLES(0), CYCLES(5), CYCLES(0), CYCLES(5), NULL
};
static int *opcode_timings_d8[8] =
{
/* FADDil FMULil FCOMil FCOMPil FSUBil FSUBRil FDIVil FDIVRil*/
CYCLES(10), CYCLES(12), CYCLES(9), CYCLES(9), CYCLES(10), CYCLES(10), CYCLES(78), CYCLES(78)
};
static int *opcode_timings_d8_mod3[8] =
{
/* FADD FMUL FCOM FCOMP FSUB FSUBR FDIV FDIVR*/
CYCLES(4), CYCLES(6), CYCLES(3), CYCLES(3), CYCLES(4), CYCLES(4), CYCLES(72), CYCLES(72)
};
static int *opcode_timings_d9[8] =
{
/* FLDs FSTs FSTPs FLDENV FLDCW FSTENV FSTCW*/
CYCLES(2), NULL, CYCLES(7), CYCLES(7), CYCLES(34), CYCLES(4), CYCLES(67), CYCLES(3)
};
static int *opcode_timings_d9_mod3[64] =
{
/*FLD*/
CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1),
/*FXCH*/
CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(4), CYCLES(4),
/*FNOP*/
CYCLES(7), NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/*FSTP*/
CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1), CYCLES(1),
/* opFCHS opFABS opFTST opFXAM*/
CYCLES(2), CYCLES(2), NULL, NULL, CYCLES(5), CYCLES(7), NULL, NULL,
/* opFLD1 opFLDL2T opFLDL2E opFLDPI opFLDEG2 opFLDLN2 opFLDZ*/
CYCLES(5), CYCLES(7), CYCLES(7), CYCLES(7), CYCLES(7), CYCLES(7), CYCLES(5), NULL,
/* opF2XM1 opFYL2X opFPTAN opFPATAN opFDECSTP opFINCSTP,*/
CYCLES(300), CYCLES(58), CYCLES(676), CYCLES(355), NULL, NULL, CYCLES(3), CYCLES(3),
/* opFPREM opFSQRT opFSINCOS opFRNDINT opFSCALE opFSIN opFCOS*/
CYCLES(70), NULL, CYCLES(72), CYCLES(292), CYCLES(21), CYCLES(30), CYCLES(474), CYCLES(474)
};
static int *opcode_timings_da[8] =
{
/* FADDil FMULil FCOMil FCOMPil FSUBil FSUBRil FDIVil FDIVRil*/
CYCLES(10), CYCLES(12), CYCLES(9), CYCLES(9), CYCLES(10), CYCLES(10), CYCLES(78), CYCLES(78)
};
static int *opcode_timings_da_mod3[8] =
{
NULL, NULL, NULL, NULL, NULL, CYCLES(5), NULL, NULL
};
static int *opcode_timings_db[8] =
{
/* FLDil FSTil FSTPil FLDe FSTPe*/
CYCLES(6), NULL, CYCLES(7), CYCLES(7), NULL, CYCLES(8), NULL, CYCLES(8)
};
static int *opcode_timings_db_mod3[64] =
{
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
/* opFNOP opFCLEX opFINIT opFNOP opFNOP*/
NULL, CYCLES(7), CYCLES(18), CYCLES(27), CYCLES(7), CYCLES(7), NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
};
static int *opcode_timings_dc[8] =
{
/* opFADDd_a16 opFMULd_a16 opFCOMd_a16 opFCOMPd_a16 opFSUBd_a16 opFSUBRd_a16 opFDIVd_a16 opFDIVRd_a16*/
CYCLES(6), CYCLES(8), CYCLES(5), CYCLES(5), CYCLES(6), CYCLES(6), CYCLES(74), CYCLES(74)
};
static int *opcode_timings_dc_mod3[8] =
{
/* opFADDr opFMULr opFSUBRr opFSUBr opFDIVRr opFDIVr*/
CYCLES(4), CYCLES(6), NULL, NULL, CYCLES(4), CYCLES(4), CYCLES(72), CYCLES(72)
};
static int *opcode_timings_dd[8] =
{
/* FLDd FSTd FSTPd FRSTOR FSAVE FSTSW*/
CYCLES(2), NULL, CYCLES(8), CYCLES(8), CYCLES(131), NULL, CYCLES(154), CYCLES(5)
};
static int *opcode_timings_dd_mod3[8] =
{
/* FFFREE FST FSTP FUCOM FUCOMP*/
CYCLES(3), NULL, CYCLES(1), CYCLES(1), CYCLES(3), CYCLES(3), NULL, NULL
};
static int *opcode_timings_de[8] =
{
/* FADDiw FMULiw FCOMiw FCOMPiw FSUBil FSUBRil FDIVil FDIVRil*/
CYCLES(10), CYCLES(12), CYCLES(9), CYCLES(9), CYCLES(10), CYCLES(10), CYCLES(78), CYCLES(78)
};
static int *opcode_timings_de_mod3[8] =
{
/* FADD FMUL FCOMPP FSUB FSUBR FDIV FDIVR*/
CYCLES(4), CYCLES(6), NULL, CYCLES(3), CYCLES(4), CYCLES(4), CYCLES(72), CYCLES(72)
};
static int *opcode_timings_df[8] =
{
/* FILDiw FISTiw FISTPiw FILDiq FBSTP FISTPiq*/
CYCLES(6), NULL, CYCLES(7), CYCLES(7), NULL, CYCLES(8), CYCLES(172), CYCLES(8)
};
static int *opcode_timings_df_mod3[8] =
{
/* FFREE FST FSTP FUCOM FUCOMP*/
CYCLES(3), NULL, CYCLES(1), CYCLES(1), CYCLES(3), CYCLES(3), NULL, NULL
};
static int *opcode_timings_8x[8] =
{
&timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_mr, &timing_rm
};
static int timing_count;
static uint8_t last_prefix;
static inline int COUNT(int *c, int op_32)
{
if ((uintptr_t)c <= 10000)
return (int)c;
if (((uintptr_t)c & ~0xffff) == (-1 & ~0xffff))
{
if (op_32 & 0x100)
return ((uintptr_t)c >> 8) & 0xff;
return (uintptr_t)c & 0xff;
}
return *c;
}
void codegen_timing_winchip_block_start()
{
}
void codegen_timing_winchip_start()
{
timing_count = 0;
last_prefix = 0;
}
void codegen_timing_winchip_prefix(uint8_t prefix, uint32_t fetchdat)
{
timing_count += COUNT(opcode_timings[prefix], 0);
last_prefix = prefix;
}
void codegen_timing_winchip_opcode(uint8_t opcode, uint32_t fetchdat, int op_32)
{
int **timings;
int mod3 = ((fetchdat & 0xc0) == 0xc0);
switch (last_prefix)
{
case 0x0f:
timings = mod3 ? opcode_timings_0f_mod3 : opcode_timings_0f;
break;
case 0xd8:
timings = mod3 ? opcode_timings_d8_mod3 : opcode_timings_d8;
opcode = (opcode >> 3) & 7;
break;
case 0xd9:
timings = mod3 ? opcode_timings_d9_mod3 : opcode_timings_d9;
opcode = mod3 ? opcode & 0x3f : (opcode >> 3) & 7;
break;
case 0xda:
timings = mod3 ? opcode_timings_da_mod3 : opcode_timings_da;
opcode = (opcode >> 3) & 7;
break;
case 0xdb:
timings = mod3 ? opcode_timings_db_mod3 : opcode_timings_db;
opcode = mod3 ? opcode & 0x3f : (opcode >> 3) & 7;
break;
case 0xdc:
timings = mod3 ? opcode_timings_dc_mod3 : opcode_timings_dc;
opcode = (opcode >> 3) & 7;
break;
case 0xdd:
timings = mod3 ? opcode_timings_dd_mod3 : opcode_timings_dd;
opcode = (opcode >> 3) & 7;
break;
case 0xde:
timings = mod3 ? opcode_timings_de_mod3 : opcode_timings_de;
opcode = (opcode >> 3) & 7;
break;
case 0xdf:
timings = mod3 ? opcode_timings_df_mod3 : opcode_timings_df;
opcode = (opcode >> 3) & 7;
break;
default:
switch (opcode)
{
case 0x80: case 0x81: case 0x82: case 0x83:
timings = mod3 ? opcode_timings_mod3 : opcode_timings_8x;
if (!mod3)
opcode = (fetchdat >> 3) & 7;
break;
case 0xc0: case 0xc1: case 0xd0: case 0xd1: case 0xd2: case 0xd3:
timings = mod3 ? opcode_timings_shift_mod3 : opcode_timings_shift;
opcode = (fetchdat >> 3) & 7;
break;
case 0xf6:
timings = mod3 ? opcode_timings_f6_mod3 : opcode_timings_f6;
opcode = (fetchdat >> 3) & 7;
break;
case 0xf7:
timings = mod3 ? opcode_timings_f7_mod3 : opcode_timings_f7;
opcode = (fetchdat >> 3) & 7;
break;
case 0xff:
timings = mod3 ? opcode_timings_ff_mod3 : opcode_timings_ff;
opcode = (fetchdat >> 3) & 7;
break;
default:
timings = mod3 ? opcode_timings_mod3 : opcode_timings;
break;
}
}
timing_count += COUNT(timings[opcode], op_32);
codegen_block_cycles += timing_count;
}
void codegen_timing_winchip_block_end()
{
}
codegen_timing_t codegen_timing_winchip =
{
codegen_timing_winchip_start,
codegen_timing_winchip_prefix,
codegen_timing_winchip_opcode,
codegen_timing_winchip_block_start,
codegen_timing_winchip_block_end
};

1247
src/codegen_x86-64.c Normal file

File diff suppressed because it is too large Load Diff

21
src/codegen_x86-64.h Normal file
View File

@@ -0,0 +1,21 @@
#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_EXIT_OFFSET 0x7e0
#define BLOCK_GPF_OFFSET (BLOCK_EXIT_OFFSET - 20)
enum
{
OP_RET = 0xc3
};
#define NR_HOST_REGS 3
extern int host_reg_mapping[NR_HOST_REGS];
#define NR_HOST_XMM_REGS 7
extern int host_reg_xmm_mapping[NR_HOST_XMM_REGS];

1048
src/codegen_x86.c Normal file

File diff suppressed because it is too large Load Diff

21
src/codegen_x86.h Normal file
View File

@@ -0,0 +1,21 @@
#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_EXIT_OFFSET 0x7f0
#define BLOCK_GPF_OFFSET (BLOCK_EXIT_OFFSET - 20)
enum
{
OP_RET = 0xc3
};
#define NR_HOST_REGS 3
extern int host_reg_mapping[NR_HOST_REGS];
#define NR_HOST_XMM_REGS 7
extern int host_reg_xmm_mapping[NR_HOST_XMM_REGS];

51
src/compaq.c Normal file
View File

@@ -0,0 +1,51 @@
#include "ibm.h"
#include "mem.h"
/* Compaq Deskpro 386 remaps RAM from 0xA0000-0xFFFFF to 0xFA0000-0xFFFFFF */
static mem_mapping_t compaq_ram_mapping;
uint8_t compaq_read_ram(uint32_t addr, void *priv)
{
addr = (addr & 0x7ffff) + 0x80000;
addreadlookup(mem_logical_addr, addr);
return ram[addr];
}
uint16_t compaq_read_ramw(uint32_t addr, void *priv)
{
addr = (addr & 0x7ffff) + 0x80000;
addreadlookup(mem_logical_addr, addr);
return *(uint16_t *)&ram[addr];
}
uint32_t compaq_read_raml(uint32_t addr, void *priv)
{
addr = (addr & 0x7ffff) + 0x80000;
addreadlookup(mem_logical_addr, addr);
return *(uint32_t *)&ram[addr];
}
void compaq_write_ram(uint32_t addr, uint8_t val, void *priv)
{
addr = (addr & 0x7ffff) + 0x80000;
addwritelookup(mem_logical_addr, addr);
mem_write_ramb_page(addr, val, &pages[addr >> 12]);
}
void compaq_write_ramw(uint32_t addr, uint16_t val, void *priv)
{
addr = (addr & 0x7ffff) + 0x80000;
addwritelookup(mem_logical_addr, addr);
mem_write_ramw_page(addr, val, &pages[addr >> 12]);
}
void compaq_write_raml(uint32_t addr, uint32_t val, void *priv)
{
addr = (addr & 0x7ffff) + 0x80000;
addwritelookup(mem_logical_addr, addr);
mem_write_raml_page(addr, val, &pages[addr >> 12]);
}
void compaq_init()
{
mem_mapping_add(&compaq_ram_mapping, 0xfa0000, 0x60000,
compaq_read_ram, compaq_read_ramw, compaq_read_raml,
compaq_write_ram, compaq_write_ramw, compaq_write_raml,
ram + 0xa0000, MEM_MAPPING_INTERNAL, NULL);
}

1
src/compaq.h Normal file
View File

@@ -0,0 +1 @@
void compaq_init();

400
src/config.c Normal file
View File

@@ -0,0 +1,400 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "config.h"
char config_file_default[256];
static char config_file[256];
typedef struct list_t
{
struct list_t *next;
} list_t;
static list_t config_head;
typedef struct section_t
{
struct list_t list;
char name[256];
struct list_t entry_head;
} section_t;
typedef struct entry_t
{
struct list_t list;
char name[256];
char data[256];
} entry_t;
#define list_add(new, head) \
{ \
struct list_t *next = head; \
\
while (next->next) \
next = next->next; \
\
(next)->next = new; \
(new)->next = NULL; \
}
void config_dump()
{
section_t *current_section;
pclog("Config data :\n");
current_section = (section_t *)config_head.next;
while (current_section)
{
entry_t *current_entry;
pclog("[%s]\n", current_section->name);
current_entry = (entry_t *)current_section->entry_head.next;
while (current_entry)
{
pclog("%s = %s\n", current_entry->name, current_entry->data);
current_entry = (entry_t *)current_entry->list.next;
}
current_section = (section_t *)current_section->list.next;
}
}
void config_free()
{
section_t *current_section;
current_section = (section_t *)config_head.next;
while (current_section)
{
section_t *next_section = (section_t *)current_section->list.next;
entry_t *current_entry;
current_entry = (entry_t *)current_section->entry_head.next;
while (current_entry)
{
entry_t *next_entry = (entry_t *)current_entry->list.next;
free(current_entry);
current_entry = next_entry;
}
free(current_section);
current_section = next_section;
}
}
void config_load(char *fn)
{
FILE *f = fopen(fn, "rt");
section_t *current_section;
memset(&config_head, 0, sizeof(list_t));
current_section = malloc(sizeof(section_t));
memset(current_section, 0, sizeof(section_t));
list_add(&current_section->list, &config_head);
if (!f)
return;
while (1)
{
int c;
char buffer[256];
fgets(buffer, 255, f);
if (feof(f)) break;
c = 0;
while (buffer[c] == ' ' && buffer[c])
c++;
if (!buffer[c]) continue;
if (buffer[c] == '#') /*Comment*/
continue;
if (buffer[c] == '[') /*Section*/
{
section_t *new_section;
char name[256];
int d = 0;
c++;
while (buffer[c] != ']' && buffer[c])
name[d++] = buffer[c++];
if (buffer[c] != ']')
continue;
name[d] = 0;
new_section = malloc(sizeof(section_t));
memset(new_section, 0, sizeof(section_t));
strncpy(new_section->name, name, 256);
list_add(&new_section->list, &config_head);
current_section = new_section;
// pclog("New section : %s %p\n", name, (void *)current_section);
}
else
{
entry_t *new_entry;
char name[256];
int d = 0, data_pos;
while (buffer[c] != '=' && buffer[c] != ' ' && buffer[c])
name[d++] = buffer[c++];
if (!buffer[c]) continue;
name[d] = 0;
while ((buffer[c] == '=' || buffer[c] == ' ') && buffer[c])
c++;
if (!buffer[c]) continue;
data_pos = c;
while (buffer[c])
{
if (buffer[c] == '\n')
buffer[c] = 0;
c++;
}
new_entry = malloc(sizeof(entry_t));
memset(new_entry, 0, sizeof(entry_t));
strncpy(new_entry->name, name, 256);
strncpy(new_entry->data, &buffer[data_pos], 256);
list_add(&new_entry->list, &current_section->entry_head);
// pclog("New data under section [%s] : %s = %s\n", current_section->name, new_entry->name, new_entry->data);
}
}
fclose(f);
config_dump();
}
void config_new()
{
FILE *f = fopen(config_file, "wt");
fclose(f);
}
static section_t *find_section(char *name)
{
section_t *current_section;
char blank[] = "";
current_section = (section_t *)config_head.next;
if (!name)
name = blank;
while (current_section)
{
if (!strncmp(current_section->name, name, 256))
return current_section;
current_section = (section_t *)current_section->list.next;
}
return NULL;
}
static entry_t *find_entry(section_t *section, char *name)
{
entry_t *current_entry;
current_entry = (entry_t *)section->entry_head.next;
while (current_entry)
{
if (!strncmp(current_entry->name, name, 256))
return current_entry;
current_entry = (entry_t *)current_entry->list.next;
}
return NULL;
}
static section_t *create_section(char *name)
{
section_t *new_section = malloc(sizeof(section_t));
memset(new_section, 0, sizeof(section_t));
strncpy(new_section->name, name, 256);
list_add(&new_section->list, &config_head);
return new_section;
}
static entry_t *create_entry(section_t *section, char *name)
{
entry_t *new_entry = malloc(sizeof(entry_t));
memset(new_entry, 0, sizeof(entry_t));
strncpy(new_entry->name, name, 256);
list_add(&new_entry->list, &section->entry_head);
return new_entry;
}
int config_get_int(char *head, char *name, int def)
{
section_t *section;
entry_t *entry;
int value;
section = find_section(head);
if (!section)
return def;
entry = find_entry(section, name);
if (!entry)
return def;
sscanf(entry->data, "%i", &value);
return value;
}
char *config_get_string(char *head, char *name, char *def)
{
section_t *section;
entry_t *entry;
int value;
section = find_section(head);
if (!section)
return def;
entry = find_entry(section, name);
if (!entry)
return def;
return entry->data;
}
void config_set_int(char *head, char *name, int val)
{
section_t *section;
entry_t *entry;
section = find_section(head);
if (!section)
section = create_section(head);
entry = find_entry(section, name);
if (!entry)
entry = create_entry(section, name);
sprintf(entry->data, "%i", val);
}
void config_set_string(char *head, char *name, char *val)
{
section_t *section;
entry_t *entry;
section = find_section(head);
if (!section)
section = create_section(head);
entry = find_entry(section, name);
if (!entry)
entry = create_entry(section, name);
strncpy(entry->data, val, 256);
}
char *get_filename(char *s)
{
int c = strlen(s) - 1;
while (c > 0)
{
if (s[c] == '/' || s[c] == '\\')
return &s[c+1];
c--;
}
return s;
}
void append_filename(char *dest, char *s1, char *s2, int size)
{
sprintf(dest, "%s%s", s1, s2);
}
void put_backslash(char *s)
{
int c = strlen(s) - 1;
if (s[c] != '/' && s[c] != '\\')
s[c] = '/';
}
char *get_extension(char *s)
{
int c = strlen(s) - 1;
if (c <= 0)
return s;
while (c && s[c] != '.')
c--;
if (!c)
return &s[strlen(s)];
return &s[c+1];
}
void config_save(char *fn)
{
FILE *f = fopen(fn, "wt");
section_t *current_section;
current_section = (section_t *)config_head.next;
while (current_section)
{
entry_t *current_entry;
if (current_section->name[0])
fprintf(f, "\n[%s]\n", current_section->name);
current_entry = (entry_t *)current_section->entry_head.next;
while (current_entry)
{
fprintf(f, "%s = %s\n", current_entry->name, current_entry->data);
current_entry = (entry_t *)current_entry->list.next;
}
current_section = (section_t *)current_section->list.next;
}
fclose(f);
}

16
src/config.h Normal file
View File

@@ -0,0 +1,16 @@
int config_get_int(char *head, char *name, int def);
char *config_get_string(char *head, char *name, char *def);
void config_set_int(char *head, char *name, int val);
void config_set_string(char *head, char *name, char *val);
char *get_filename(char *s);
void append_filename(char *dest, char *s1, char *s2, int size);
void put_backslash(char *s);
char *get_extension(char *s);
void config_load(char *fn);
void config_save(char *fn);
void config_dump();
void config_free();
extern char config_file_default[256];

2260
src/cpu.c Normal file

File diff suppressed because it is too large Load Diff

146
src/cpu.h Normal file
View File

@@ -0,0 +1,146 @@
#ifndef _CPU_H_
#define _CPU_H_
extern int cpu, cpu_manufacturer;
/*808x class CPUs*/
#define CPU_8088 0
#define CPU_8086 1
/*286 class CPUs*/
#define CPU_286 2
/*386 class CPUs*/
#define CPU_386SX 3
#define CPU_386DX 4
#define CPU_486SLC 5
#define CPU_486DLC 6
/*486 class CPUs*/
#define CPU_i486SX 7
#define CPU_Am486SX 8
#define CPU_Cx486S 9
#define CPU_i486DX 10
#define CPU_Am486DX 11
#define CPU_Cx486DX 12
#define CPU_Cx5x86 13
/*586 class CPUs*/
#define CPU_WINCHIP 14
#define CPU_PENTIUM 15
#define CPU_PENTIUMMMX 16
#define CPU_Cx6x86 17
#define CPU_Cx6x86MX 18
#define CPU_Cx6x86L 19
#define CPU_CxGX1 20
#define CPU_K5 21
#define CPU_5K86 22
#define CPU_K6 23
/*686 class CPUs*/
#define CPU_PENTIUMPRO 24
#define CPU_PENTIUM2 25
#define CPU_PENTIUM2D 26
#define MANU_INTEL 0
#define MANU_AMD 1
#define MANU_CYRIX 2
#define MANU_IDT 3
extern int timing_rr;
extern int timing_mr, timing_mrl;
extern int timing_rm, timing_rml;
extern int timing_mm, timing_mml;
extern int timing_bt, timing_bnt;
extern int timing_int, timing_int_rm, timing_int_v86, timing_int_pm, timing_int_pm_outer;
extern int timing_iret_rm, timing_iret_v86, timing_iret_pm, timing_iret_pm_outer;
extern int timing_call_rm, timing_call_pm, timing_call_pm_gate, timing_call_pm_gate_inner;
extern int timing_retf_rm, timing_retf_pm, timing_retf_pm_outer;
extern int timing_jmp_rm, timing_jmp_pm, timing_jmp_pm_gate;
typedef struct
{
char name[32];
int cpu_type;
int speed;
int rspeed;
int multi;
int pci_speed;
uint32_t edx_reset;
uint32_t cpuid_model;
uint16_t cyrix_id;
int cpu_flags;
} CPU;
extern CPU cpus_8088[];
extern CPU cpus_8086[];
extern CPU cpus_286[];
extern CPU cpus_i386[];
extern CPU cpus_Am386[];
extern CPU cpus_486SDLC[];
extern CPU cpus_i486[];
extern CPU cpus_Am486[];
extern CPU cpus_Cx486[];
extern CPU cpus_WinChip[];
extern CPU cpus_Pentium5V[];
extern CPU cpus_Pentium5V50[];
extern CPU cpus_PentiumS5[];
extern CPU cpus_K5[];
extern CPU cpus_K56[];
extern CPU cpus_Pentium[];
extern CPU cpus_6x86[];
extern CPU cpus_PentiumPro[];
extern CPU cpus_Pentium2[];
extern CPU cpus_Pentium2D[];
extern CPU cpus_pcjr[];
extern CPU cpus_pc1512[];
extern CPU cpus_ibmat[];
extern CPU cpus_ps1_m2011[];
extern CPU cpus_acer[];
extern int cpu_iscyrix;
extern int cpu_16bitbus;
extern int cpu_busspeed;
extern int cpu_multi;
extern int cpu_hasrdtsc;
extern int cpu_hasMSR;
extern int cpu_hasMMX;
extern int cpu_hasCR4;
#define CR4_TSD (1 << 2)
#define CR4_DE (1 << 3)
#define CR4_MCE (1 << 6)
#define CR4_PCE (1 << 8)
#define CR4_OSFXSR (1 << 9)
extern uint64_t cpu_CR4_mask;
#define CPU_SUPPORTS_DYNAREC 1
// #define CPU_REQUIRES_DYNAREC 2
#define CPU_REQUIRES_DYNAREC 0
extern uint64_t tsc;
void cyrix_write(uint16_t addr, uint8_t val, void *priv);
uint8_t cyrix_read(uint16_t addr, void *priv);
extern int is8086;
void cpu_CPUID();
void cpu_RDMSR();
void cpu_WRMSR();
extern int cpu_use_dynarec;
extern int xt_cpu_multi;
#define ISA_CYCLES_SHIFT 6
extern int isa_cycles;
#define ISA_CYCLES(x) ((x * isa_cycles) >> ISA_CYCLES_SHIFT)
#endif

68
src/dac.c Normal file
View File

@@ -0,0 +1,68 @@
#include "ibm.h"
uint8_t dac,dac2;
uint8_t dacctrl;
int lptfifo;
uint8_t dssbuffer[16];
int dssstart=0,dssend=0;
int dssmode=0;
void writedac(uint16_t addr, uint8_t val)
{
if (dssmode) dac2=val;
else dac=val;
}
void writedacctrl(uint16_t addr, uint8_t val)
{
// printf("Write DAC ctrl %02X %i\n",val,lptfifo);
if (dacctrl&8 && !(val&8) && (lptfifo!=16))
{
// dac=dac2;
dssbuffer[dssend++]=dac2;
dssend&=15;
lptfifo++;
}
dacctrl=val;
}
uint8_t readdacfifo()
{
if (lptfifo==16) return 0x40;
return 0;
}
void pollss()
{
if (lptfifo)
{
dac=dssbuffer[dssstart++];
dssstart&=15;
lptfifo--;
}
}
int16_t dacbuffer[SOUNDBUFLEN+20];
int dacbufferpos=0;
void getdacsamp()
{
if (dacbufferpos<SOUNDBUFLEN+20) dacbuffer[dacbufferpos++]=(((int)(unsigned int)dac)-0x80)*0x20;
}
void adddac(int16_t *p)
{
int c;
if (dacbufferpos>SOUNDBUFLEN) dacbufferpos=SOUNDBUFLEN;
for (c=0;c<dacbufferpos;c++)
{
p[c<<1]+=(dacbuffer[c]);
p[(c<<1)+1]+=(dacbuffer[c]);
}
for (;c<SOUNDBUFLEN;c++)
{
p[c<<1]+=(dacbuffer[dacbufferpos-1]);
p[(c<<1)+1]+=(dacbuffer[dacbufferpos-1]);
}
dacbufferpos=0;
}

137
src/device.c Normal file
View File

@@ -0,0 +1,137 @@
#include "ibm.h"
#include "config.h"
#include "device.h"
#include "sound.h"
static void *device_priv[256];
static device_t *devices[256];
static device_t *current_device;
void device_init()
{
memset(devices, 0, sizeof(devices));
}
void device_add(device_t *d)
{
int c = 0;
void *priv;
while (devices[c] != NULL && c < 256)
c++;
if (c >= 256)
fatal("device_add : too many devices\n");
current_device = d;
priv = d->init();
if (priv == NULL)
fatal("device_add : device init failed\n");
devices[c] = d;
device_priv[c] = priv;
}
void device_close_all()
{
int c;
for (c = 0; c < 256; c++)
{
if (devices[c] != NULL)
{
devices[c]->close(device_priv[c]);
devices[c] = device_priv[c] = NULL;
}
}
}
int device_available(device_t *d)
{
#ifdef RELEASE_BUILD
if (d->flags & DEVICE_NOT_WORKING)
return 0;
#endif
if (d->available)
return d->available();
return 1;
}
void device_speed_changed()
{
int c;
for (c = 0; c < 256; c++)
{
if (devices[c] != NULL)
{
if (devices[c]->speed_changed != NULL)
{
devices[c]->speed_changed(device_priv[c]);
}
}
}
sound_speed_changed();
}
void device_force_redraw()
{
int c;
for (c = 0; c < 256; c++)
{
if (devices[c] != NULL)
{
if (devices[c]->force_redraw != NULL)
{
devices[c]->force_redraw(device_priv[c]);
}
}
}
}
char *device_add_status_info(char *s, int max_len)
{
int c;
for (c = 0; c < 256; c++)
{
if (devices[c] != NULL)
{
if (devices[c]->add_status_info != NULL)
devices[c]->add_status_info(s, max_len, device_priv[c]);
}
}
}
int device_get_config_int(char *s)
{
device_config_t *config = current_device->config;
while (config->type != -1)
{
if (!strcmp(s, config->name))
return config_get_int(current_device->name, s, config->default_int);
config++;
}
return 0;
}
char *device_get_config_string(char *s)
{
device_config_t *config = current_device->config;
while (config->type != -1)
{
if (!strcmp(s, config->name))
return config_get_string(current_device->name, s, config->default_string);
config++;
}
return NULL;
}

50
src/device.h Normal file
View File

@@ -0,0 +1,50 @@
#define CONFIG_STRING 0
#define CONFIG_INT 1
#define CONFIG_BINARY 2
#define CONFIG_SELECTION 3
#define CONFIG_MIDI 4
typedef struct device_config_selection_t
{
char description[256];
int value;
} device_config_selection_t;
typedef struct device_config_t
{
char name[256];
char description[256];
int type;
char default_string[256];
int default_int;
device_config_selection_t selection[16];
} device_config_t;
typedef struct device_t
{
char name[50];
uint32_t flags;
void *(*init)();
void (*close)(void *p);
int (*available)();
void (*speed_changed)(void *p);
void (*force_redraw)(void *p);
void (*add_status_info)(char *s, int max_len, void *p);
device_config_t *config;
} device_t;
void device_init();
void device_add(device_t *d);
void device_close_all();
int device_available(device_t *d);
void device_speed_changed();
void device_force_redraw();
char *device_add_status_info(char *s, int max_len);
int device_get_config_int(char *name);
char *device_get_config_string(char *name);
enum
{
DEVICE_NOT_WORKING = 1 /*Device does not currently work correctly and will be disabled in a release build*/
};

453
src/disc.c Normal file
View File

@@ -0,0 +1,453 @@
#include "ibm.h"
#include "config.h"
#include "disc.h"
#include "disc_fdi.h"
#include "disc_img.h"
#include "fdc.h"
#include "fdd.h"
#include "pit.h"
#include "timer.h"
#include "disc_sector.h"
int disc_drivesel = 0;
int disc_poll_time = 16;
int poll_time[2] = {16, 16};
int disc_track[2];
int writeprot[2], fwriteprot[2];
DRIVE drives[2];
int drive_type[2];
int curdrive = 0;
int swwp = 0;
int disable_write = 0;
//char discfns[2][260] = {"", ""};
int defaultwriteprot = 0;
int fdc_time;
int disc_time;
int fdc_ready;
int drive_empty[2] = {1, 1};
int disc_changed[2];
int bpulses[2] = {0, 0};
int motorspin;
int motoron;
int fdc_indexcount = 52;
/*void (*fdc_callback)();
void (*fdc_data)(uint8_t dat);
void (*fdc_spindown)();
void (*fdc_finishread)();
void (*fdc_notfound)();
void (*fdc_datacrcerror)();
void (*fdc_headercrcerror)();
void (*fdc_writeprotect)();
int (*fdc_getdata)(int last);
void (*fdc_sectorid)(uint8_t track, uint8_t side, uint8_t sector, uint8_t size, uint8_t crc1, uint8_t crc2);
void (*fdc_indexpulse)();*/
static struct
{
char *ext;
void (*load)(int drive, char *fn);
void (*close)(int drive);
int size;
}
loaders[]=
{
{"IMG", img_load, img_close, -1},
{"IMA", img_load, img_close, -1},
{"360", img_load, img_close, -1},
{"XDF", img_load, img_close, -1},
{"FDI", fdi_load, fdi_close, -1},
{0,0,0}
};
static int driveloaders[4];
void disc_load(int drive, char *fn)
{
int c = 0, size;
char *p;
FILE *f;
// pclog("disc_load %i %s\n", drive, fn);
// setejecttext(drive, "");
fdd_stepping_motor_on[drive] = fdd_track_diff[drive] = NULL;
if (!fn) return;
p = get_extension(fn);
if (!p) return;
// setejecttext(drive, fn);
pclog("Loading :%i %s %s\n", drive, fn,p);
f = fopen(fn, "rb");
if (!f) return;
fseek(f, -1, SEEK_END);
size = ftell(f) + 1;
fclose(f);
while (loaders[c].ext)
{
if (!strcasecmp(p, loaders[c].ext) && (size == loaders[c].size || loaders[c].size == -1))
{
pclog("Loading as %s\n", p);
driveloaders[drive] = c;
loaders[c].load(drive, fn);
drive_empty[drive] = 0;
disc_changed[drive] = 1;
strcpy(discfns[drive], fn);
return;
}
c++;
}
pclog("Couldn't load %s %s\n",fn,p);
drive_empty[drive] = 1;
discfns[drive][0] = 0;
}
void disc_close(int drive)
{
// pclog("disc_close %i\n", drive);
if (loaders[driveloaders[drive]].close) loaders[driveloaders[drive]].close(drive);
drive_empty[drive] = 1;
discfns[drive][0] = 0;
drives[drive].hole = NULL;
drives[drive].poll = NULL;
drives[drive].seek = NULL;
drives[drive].readsector = NULL;
drives[drive].writesector = NULL;
drives[drive].readaddress = NULL;
drives[drive].format = NULL;
drives[drive].realtrack = NULL;
drives[drive].stop = NULL;
fdd_stepping_motor_on[drive] = fdd_track_diff[drive] = 0;
}
int disc_notfound=0;
int not_found[2] = {0, 0};
static int disc_period = 32;
int disc_hole(int drive)
{
drive ^= fdd_swap;
if (drives[drive].hole)
{
return drives[drive].hole(drive);
}
else
{
return 0;
}
}
int disc_byteperiod(int drive)
{
drive ^= fdd_swap;
if (drives[drive].byteperiod)
{
return drives[drive].byteperiod(drive);
}
else
{
return 32;
}
}
#define ACCURATE_TIMER_USEC ((((double) cpuclock) / 1000000.0) * (double)(1 << TIMER_SHIFT))
uint32_t byte_pulses = 0;
#if 0
void disc_time_adjust()
{
if (disc_byteperiod(disc_drivesel ^ fdd_swap) == 26)
disc_poll_time -= ((160.0 / 6.0) * ACCURATE_TIMER_USEC);
else
disc_poll_time -= 25.0 * ((double) disc_byteperiod(disc_drivesel ^ fdd_swap)) * ACCURATE_TIMER_USEC;
}
void disc_poll()
{
// disc_poll_time += disc_period * TIMER_USEC;
if (disc_byteperiod(disc_drivesel ^ fdd_swap) == 26)
disc_poll_time += ((160.0 / 6.0) * ACCURATE_TIMER_USEC);
else
disc_poll_time += ((double) disc_byteperiod(disc_drivesel ^ fdd_swap)) * ACCURATE_TIMER_USEC;
byte_pulses++;
if ((byte_pulses > 6250) && (byte_pulses <= 6275)) pclog("Byte pulses is now %i!\n", byte_pulses);
if (drives[disc_drivesel].poll)
drives[disc_drivesel].poll(disc_drivesel);
if (disc_notfound)
{
disc_notfound--;
if (!disc_notfound)
fdc_notfound();
}
}
#endif
// #define TIMER_SUB 441 // 736
// #define TIMER_SUB 0
#define TIMER_SUB 0
double dt[2] = {0.0, 0.0};
double dt2[2] = {0.0, 0.0};
void disc_poll_ex(int poll_drive)
{
int dp = 0;
double pm = 1.0;
int dbp = disc_byteperiod(poll_drive ^ fdd_swap);
double ddbp = (double) dbp;
double dtime = 0.0;
double dusec = (double) TIMER_USEC;
double dsub = (double) TIMER_SUB;
if (dbp == 26) ddbp = 160.0 / 6.0;
if (not_found[poll_drive])
{
not_found[poll_drive]--;
if (!not_found[poll_drive])
fdc_notfound();
}
else
{
if (drives[poll_drive].poll)
dp = drives[poll_drive].poll(poll_drive);
}
#if 0
if (dp == 2)
{
pm = 15.0 / 16.0;
pclog("SYNC byte detected\n");
}
#endif
dtime = (ddbp * pm * dusec) - dsub;
poll_time[poll_drive] += (int) dtime;
dt[poll_drive] += dtime;
if (dp) dt2[poll_drive] += dtime;
if (dp) bpulses[poll_drive]++;
// if (!dp && (byte_pulses == 10416))
if (bpulses[poll_drive] == raw_tsize[poll_drive])
{
pclog("Sent %i byte pulses for drive %c (time: %lf | %lf)\n", raw_tsize[poll_drive], 0x41 + poll_drive, dt[poll_drive], dt2[poll_drive]);
// poll_time[poll_drive] += (dbp * (2.0 / 3.0) * pm * TIMER_USEC) - TIMER_SUB;
// dt[poll_drive] = dt2[poll_drive] = bpulses[poll_drive] = motor_on[poll_drive] = 0;
// disc_stop(poll_drive ^ fdd_swap); /* Send drive to idle state after enough byte pulses have been sent. */
/* Disc state is already set to idle on finish or error anyway. */
}
}
void disc_poll_0()
{
disc_poll_ex(0);
}
void disc_poll_1()
{
disc_poll_ex(1);
}
int disc_get_bitcell_period(int rate)
{
int bit_rate;
switch (rate)
{
case 0: /*High density*/
bit_rate = 500;
break;
case 1: /*Double density (360 rpm)*/
bit_rate = 300;
break;
case 2: /*Double density*/
bit_rate = 250;
break;
case 3: /*Extended density*/
bit_rate = 1000;
break;
}
return 1000000 / bit_rate*2; /*Bitcell period in ns*/
}
void disc_set_rate(int drive, int drvden, int rate)
{
switch (rate)
{
case 0: /*High density*/
disc_period = 16;
break;
case 1:
switch(drvden)
{
case 0: /*Double density (360 rpm)*/
disc_period = 26;
break;
case 1: /*High density (360 rpm)*/
disc_period = 16;
break;
case 2:
disc_period = 4;
break;
}
case 2: /*Double density*/
disc_period = 32;
break;
case 3: /*Extended density*/
disc_period = 8;
break;
}
}
void disc_reset()
{
curdrive = 0;
disc_period = 32;
fdd_stepping_motor_on[0] = fdd_track_diff[0] = 0;
fdd_stepping_motor_on[1] = fdd_track_diff[1] = 0;
// timer_add(disc_poll, &disc_poll_time, &motoron, NULL);
timer_add(disc_poll_0, &(poll_time[0]), &(motor_on[0]), NULL);
timer_add(disc_poll_1, &(poll_time[1]), &(motor_on[1]), NULL);
}
void disc_init()
{
// pclog("disc_init %p\n", drives);
drives[0].poll = drives[1].poll = 0;
drives[0].seek = drives[1].seek = 0;
drives[0].readsector = drives[1].readsector = 0;
disc_reset();
}
int oldtrack[2] = {0, 0};
void disc_seek(int drive, int track)
{
// pclog("disc_seek: drive=%i track=%i\n", drive, track);
if (drives[drive].seek)
drives[drive].seek(drive, track);
// if (track != oldtrack[drive])
// fdc_discchange_clear(drive);
// ddnoise_seek(track - oldtrack[drive]);
// oldtrack[drive] = track;
}
void disc_readsector(int drive, int sector, int track, int side, int density, int sector_size)
{
drive ^= fdd_swap;
if (drives[drive].readsector)
{
drives[drive].readsector(drive, sector, track, side, density, sector_size);
pclog("Byte pulses: %i\n", bpulses[drive]);
bpulses[drive] = 0;
dt[drive] = dt2[drive] = 0;
// motor_on[drive] = 1;
poll_time[drive] = 0;
}
else
not_found[drive] = 1000;
#if 0
disc_notfound = 1000;
#endif
}
void disc_writesector(int drive, int sector, int track, int side, int density, int sector_size)
{
drive ^= fdd_swap;
if (drives[drive].writesector)
{
drives[drive].writesector(drive, sector, track, side, density, sector_size);
bpulses[drive] = 0;
dt[drive] = dt2[drive] = 0;
// motor_on[drive] = 1;
poll_time[drive] = 0;
}
else
not_found[drive] = 1000;
#if 0
disc_notfound = 1000;
#endif
}
void disc_readaddress(int drive, int track, int side, int density)
{
drive ^= fdd_swap;
if (drives[drive].readaddress)
{
drives[drive].readaddress(drive, track, side, density);
bpulses[drive] = 0;
dt[drive] = dt2[drive] = 0;
// motor_on[drive] = 1;
poll_time[drive] = 0;
}
}
void disc_format(int drive, int track, int side, int density, uint8_t fill)
{
drive ^= fdd_swap;
if (drives[drive].format)
{
drives[drive].format(drive, track, side, density, fill);
bpulses[drive] = 0;
dt[drive] = dt2[drive] = 0;
// motor_on[drive] = 1;
poll_time[drive] = 0;
}
else
not_found[drive] = 1000;
#if 0
disc_notfound = 1000;
#endif
}
int disc_realtrack(int drive, int track)
{
drive ^= fdd_swap;
if (drives[drive].realtrack)
return drives[drive].realtrack(drive, track);
else
return track;
}
void disc_stop(int drive)
{
drive ^= fdd_swap;
if (drives[drive].stop)
drives[drive].stop(drive);
}
void disc_set_drivesel(int drive)
{
drive ^= fdd_swap;
disc_drivesel = drive;
}

83
src/disc.h Normal file
View File

@@ -0,0 +1,83 @@
typedef struct
{
void (*seek)(int drive, int track);
void (*readsector)(int drive, int sector, int track, int side, int density, int sector_size);
void (*writesector)(int drive, int sector, int track, int side, int density, int sector_size);
void (*readaddress)(int drive, int track, int side, int density);
void (*format)(int drive, int track, int side, int density, uint8_t fill);
int (*hole)(int drive);
int (*byteperiod)(int drive);
void (*stop)(int drive);
int (*poll)(int drive);
int (*realtrack)(int drive, int track);
} DRIVE;
extern DRIVE drives[2];
extern int curdrive;
void disc_load(int drive, char *fn);
void disc_new(int drive, char *fn);
void disc_close(int drive);
void disc_init();
void disc_reset();
void disc_poll();
void disc_seek(int drive, int track);
void disc_readsector(int drive, int sector, int track, int side, int density, int sector_size);
void disc_writesector(int drive, int sector, int track, int side, int density, int sector_size);
void disc_readaddress(int drive, int track, int side, int density);
void disc_format(int drive, int track, int side, int density, uint8_t fill);
void disc_time_adjust();
int disc_realtrack(int drive, int track);
int disc_hole(int drive);
int disc_byteperiod(int drive);
void disc_stop(int drive);
int disc_empty(int drive);
void disc_set_rate(int drive, int drvden, int rate);
void disc_set_drivesel(int drive);
extern int disc_time;
extern int disc_poll_time;
extern int poll_time[2];
extern int disc_drivesel;
extern int disc_notfound;
extern int not_found[2];
void fdc_callback();
int fdc_data(uint8_t dat);
void fdc_spindown();
void fdc_finishread();
void fdc_notfound();
void fdc_datacrcerror();
void fdc_headercrcerror();
void fdc_writeprotect();
int fdc_getdata(int last);
void fdc_sectorid(uint8_t track, uint8_t side, uint8_t sector, uint8_t size, uint8_t crc1, uint8_t crc2);
void fdc_indexpulse();
/*extern int fdc_time;
extern int fdc_ready;
extern int fdc_indexcount;*/
extern int motorspin;
extern int motoron;
extern int motor_on[2];
extern int swwp;
extern int disable_write;
extern int defaultwriteprot;
//extern char discfns[4][260];
extern int writeprot[2], fwriteprot[2];
extern int disc_track[2];
extern int disc_changed[2];
extern int drive_empty[2];
extern int drive_type[2];
extern uint32_t byte_pulses;
extern int bpulses[2];
/*Used in the Read A Track command. Only valid for disc_readsector(). */
#define SECTOR_FIRST -2
#define SECTOR_NEXT -1

513
src/disc_fdi.c Normal file
View File

@@ -0,0 +1,513 @@
#include <stdio.h>
#include <stdint.h>
#include "ibm.h"
#include "disc.h"
#include "disc_fdi.h"
#include "fdi2raw.h"
static struct
{
FILE *f;
FDI *h;
uint8_t track_data[2][4][256*1024];
int sides;
int tracklen[2][4];
int trackindex[2][4];
int lasttrack;
} fdi[2];
static uint8_t fdi_timing[256*1024];
#if 0
static int fdi_pos;
static int fdi_revs;
static int fdi_sector, fdi_track, fdi_side, fdi_drive, fdi_density, fdi_n;
static int fdi_inread, fdi_inwrite, fdi_readpos, fdi_inreadaddr;
#endif
static int fdi_pos[2];
static int fdi_revs[2];
static int fdi_sector[2], fdi_track[2], fdi_side[2], fdi_drive[2], fdi_density[2], fdi_n[2];
static int fdi_inread[2], fdi_inwrite[2], fdi_readpos[2], fdi_inreadaddr[2];
static uint16_t CRCTable[256];
static int pollbytesleft[2]={0, 0},pollbitsleft[2]={0, 0};
int fdi_realtrack(int drive, int track)
{
return track;
}
static void fdi_setupcrc(uint16_t poly, uint16_t rvalue)
{
int c = 256, bc;
uint16_t crctemp;
while(c--)
{
crctemp = c << 8;
bc = 8;
while(bc--)
{
if(crctemp & 0x8000)
{
crctemp = (crctemp << 1) ^ poly;
}
else
{
crctemp <<= 1;
}
}
CRCTable[c] = crctemp;
}
}
void fdi_init()
{
// printf("FDI reset\n");
memset(&fdi, 0, sizeof(fdi));
fdi_setupcrc(0x1021, 0xcdb4);
}
int fdi_hole(int drive)
{
switch (fdi2raw_get_bit_rate(fdi[drive].h))
{
case 1000:
return 2;
case 500:
return 1;
default:
return 0;
}
}
int fdi_byteperiod(int drive)
{
switch (fdi2raw_get_bit_rate(fdi[drive].h))
{
case 1000:
return 8;
case 500:
return 16;
case 300:
return 26;
case 250:
return 32;
default:
return 0;
}
}
void fdi_load(int drive, char *fn)
{
writeprot[drive] = fwriteprot[drive] = 1;
fdi[drive].f = fopen(fn, "rb");
if (!fdi[drive].f) return;
fdi[drive].h = fdi2raw_header(fdi[drive].f);
// if (!fdih[drive]) printf("Failed to load!\n");
fdi[drive].lasttrack = fdi2raw_get_last_track(fdi[drive].h);
fdi[drive].sides = fdi2raw_get_last_head(fdi[drive].h) + 1;
// printf("Last track %i\n",fdilasttrack[drive]);
drives[drive].seek = fdi_seek;
drives[drive].readsector = fdi_readsector;
drives[drive].writesector = fdi_writesector;
drives[drive].readaddress = fdi_readaddress;
drives[drive].hole = fdi_hole;
drives[drive].byteperiod = fdi_byteperiod;
drives[drive].poll = fdi_poll;
drives[drive].format = fdi_format;
drives[drive].stop = fdi_stop;
drives[drive].realtrack = fdi_realtrack;
// pclog("Loaded as FDI\n");
}
void fdi_close(int drive)
{
if (fdi[drive].h)
fdi2raw_header_free(fdi[drive].h);
if (fdi[drive].f)
fclose(fdi[drive].f);
fdi[drive].f = NULL;
}
void fdi_seek(int drive, int track)
{
int c;
int density;
if (!fdi[drive].f)
return;
// printf("Track start %i\n",track);
if (track < 0)
track = 0;
if (track > fdi[drive].lasttrack)
track = fdi[drive].lasttrack - 1;
for (density = 0; density < 4; density++)
{
int c = fdi2raw_loadtrack(fdi[drive].h, (uint16_t *)fdi[drive].track_data[0][density],
(uint16_t *)fdi_timing,
track * fdi[drive].sides,
&fdi[drive].tracklen[0][density],
&fdi[drive].trackindex[0][density], NULL, density);
if (!c)
memset(fdi[drive].track_data[0][density], 0, fdi[drive].tracklen[0][density]);
if (fdi[drive].sides == 2)
{
c = fdi2raw_loadtrack(fdi[drive].h, (uint16_t *)fdi[drive].track_data[1][density],
(uint16_t *)fdi_timing,
(track * fdi[drive].sides) + 1,
&fdi[drive].tracklen[1][density],
&fdi[drive].trackindex[1][density], NULL, density);
if (!c)
memset(fdi[drive].track_data[1][density], 0, fdi[drive].tracklen[1][density]);
}
else
{
memset(fdi[drive].track_data[1][density], 0, 65536);
fdi[drive].tracklen[0][density] = fdi[drive].tracklen[1][density] = 10000;
}
}
}
void fdi_writeback(int drive, int track)
{
return;
}
void fdi_readsector(int drive, int sector, int track, int side, int rate, int sector_size)
{
fdi_revs[drive] = 0;
fdi_sector[drive] = sector;
fdi_track[drive] = track;
fdi_side[drive] = side;
fdi_n[drive] = sector_size;
// fdi_drive = drive;
if (rate == 2)
fdi_density[drive] = 1;
if (rate == 0)
fdi_density[drive] = 2;
if (rate == 3)
fdi_density[drive] = 3;
// pclog("FDI Read sector %i %i %i %i %i\n",drive,side,track,sector, fdi_density);
// if (pollbytesleft)
// pclog("In the middle of a sector!\n");
fdi_inread[drive] = 1;
fdi_inwrite[drive] = 0;
fdi_inreadaddr[drive] = 0;
fdi_readpos[drive] = 0;
}
void fdi_writesector(int drive, int sector, int track, int side, int rate, int sector_size)
{
fdi_revs[drive] = 0;
fdi_sector[drive] = sector;
fdi_track[drive] = track;
fdi_side[drive] = side;
fdi_n[drive] = sector_size;
// fdi_drive = drive;
if (rate == 2)
fdi_density[drive] = 1;
if (rate == 0)
fdi_density[drive] = 2;
if (rate == 3)
fdi_density[drive] = 3;
// pclog("Write sector %i %i %i %i\n",drive,side,track,sector);
fdi_inread[drive] = 0;
fdi_inwrite[drive] = 1;
fdi_inreadaddr[drive] = 0;
fdi_readpos[drive] = 0;
}
void fdi_readaddress(int drive, int track, int side, int rate)
{
fdi_revs[drive] = 0;
fdi_track[drive] = track;
fdi_side[drive] = side;
// fdi_drive = drive;
if (rate == 2)
fdi_density[drive] = 1;
if (rate == 0)
fdi_density[drive] = 2;
if (rate == 3)
fdi_density[drive] = 3;
// pclog("Read address %i %i %i %i %i %p\n",drive,side,track, rate, fdi_density, &fdi_inreadaddr);
fdi_inread[drive] = 0;
fdi_inwrite[drive] = 0;
fdi_inreadaddr[drive] = 1;
fdi_readpos[drive] = 0;
}
void fdi_format(int drive, int track, int side, int rate, uint8_t fill)
{
fdi_revs[drive] = 0;
fdi_track[drive] = track;
fdi_side[drive] = side;
// fdi_drive = drive;
if (rate == 2)
fdi_density[drive] = 1;
if (rate == 0)
fdi_density[drive] = 2;
if (rate == 3)
fdi_density[drive] = 3;
// pclog("Format %i %i %i\n",drive,side,track);
fdi_inread[drive] = 0;
fdi_inwrite[drive] = 1;
fdi_inreadaddr[drive] = 0;
fdi_readpos[drive] = 0;
}
static uint16_t fdi_buffer[2];
static int readidpoll[2]={0, 0},readdatapoll[2]={0, 0},fdi_nextsector[2]={0, 0},inreadop[2]={0, 0};
static uint8_t fdi_sectordat[2][1026];
static int lastfdidat[2][2],sectorcrc[2][2];
static int sectorsize[2],fdc_sectorsize[2];
static int ddidbitsleft[2]={0, 0};
static uint8_t decodefm(uint16_t dat)
{
uint8_t temp;
temp = 0;
if (dat & 0x0001) temp |= 1;
if (dat & 0x0004) temp |= 2;
if (dat & 0x0010) temp |= 4;
if (dat & 0x0040) temp |= 8;
if (dat & 0x0100) temp |= 16;
if (dat & 0x0400) temp |= 32;
if (dat & 0x1000) temp |= 64;
if (dat & 0x4000) temp |= 128;
return temp;
}
void fdi_stop(int drive)
{
// pclog("fdi_stop\n");
fdi_inread[drive] = fdi_inwrite[drive] = fdi_inreadaddr[drive] = 0;
fdi_nextsector[drive] = ddidbitsleft[drive] = pollbitsleft[drive] = 0;
}
static uint16_t crc[2];
static void calccrc(int drive, uint8_t byte)
{
crc[drive] = (crc[drive] << 8) ^ CRCTable[(crc[drive] >> 8)^byte];
}
static int fdi_indextime_blank[2] = {6250 * 8, 6250 * 8};
int fdi_poll(int drive)
{
int tempi, c;
int bitcount;
for (bitcount = 0; bitcount < 16; bitcount++)
{
if (fdi_pos[drive] >= fdi[drive].tracklen[fdi_side[drive]][fdi_density[drive]])
{
fdi_pos[drive] = 0;
if (fdi[drive].tracklen[fdi_side[drive]][fdi_density[drive]])
fdc_indexpulse();
else
{
fdi_indextime_blank[drive]--;
if (!fdi_indextime_blank[drive])
{
fdi_indextime_blank[drive] = 6250 * 8;
fdc_indexpulse();
}
}
}
tempi = fdi[drive].track_data[fdi_side[drive]][fdi_density[drive]][((fdi_pos[drive] >> 3) & 0xFFFF) ^ 1] & (1 << (7 - (fdi_pos[drive] & 7)));
fdi_pos[drive]++;
fdi_buffer[drive] <<= 1;
fdi_buffer[drive] |= (tempi ? 1 : 0);
if (fdi_inwrite[drive])
{
fdi_inwrite[drive] = 0;
fdc_writeprotect();
return 1;
}
if (!fdi_inread[drive] && !fdi_inreadaddr[drive])
return 1;
if (fdi_pos[drive] == fdi[drive].trackindex[fdi_side[drive]][fdi_density[drive]])
{
fdi_revs[drive]++;
if (fdi_revs[drive] == 3)
{
// pclog("Not found!\n");
fdc_notfound();
fdi_inread[drive] = fdi_inreadaddr[drive] = 0;
return 1;
}
if (fdi_sector[drive] == SECTOR_FIRST)
fdi_sector[drive] = SECTOR_NEXT;
}
if (pollbitsleft[drive])
{
pollbitsleft[drive]--;
if (!pollbitsleft[drive])
{
pollbytesleft[drive]--;
if (pollbytesleft[drive]) pollbitsleft[drive] = 16; /*Set up another word if we need it*/
if (readidpoll[drive])
{
fdi_sectordat[drive][5 - pollbytesleft[drive]] = decodefm(fdi_buffer[drive]);
if (fdi_inreadaddr[drive] && !fdc_sectorid)// && pollbytesleft[drive] > 1)
{
// rpclog("inreadaddr - %02X\n", fdi_sectordat[drive][5 - pollbytesleft][drive]);
fdc_data(fdi_sectordat[drive][5 - pollbytesleft[drive]]);
}
if (!pollbytesleft[drive])
{
// pclog("Header over %i,%i %i,%i\n", fdi_sectordat[drive][0], fdi_sectordat[drive][2], fdi_track[drive], fdi_sector[drive]);
if ((fdi_sectordat[drive][0] == fdi_track[drive] && (fdi_sectordat[drive][3] == fdi_n[drive]) && (fdi_sectordat[drive][2] == fdi_sector[drive] || fdi_sector[drive] == SECTOR_NEXT)) || fdi_inreadaddr[drive])
{
crc[drive] = (fdi_density) ? 0xcdb4 : 0xffff;
calccrc(drive, 0xFE);
for (c = 0; c < 4; c++)
calccrc(drive, fdi_sectordat[drive][c]);
if ((crc[drive] >> 8) != fdi_sectordat[drive][4] || (crc[drive] & 0xFF) != fdi_sectordat[drive][5])
{
// pclog("Header CRC error : %02X %02X %02X %02X\n",crc[drive]>>8,crc[drive]&0xFF,fdi_sectordat[drive][4],fdi_sectordat[drive][5]);
// dumpregs();
// exit(-1);
inreadop[drive] = 0;
if (fdi_inreadaddr[drive])
{
// rpclog("inreadaddr - %02X\n", fdi_sector[drive]);
// fdc_data(fdi_sector[drive]);
if (fdc_sectorid)
fdc_sectorid(fdi_sectordat[drive][0], fdi_sectordat[drive][1], fdi_sectordat[drive][2], fdi_sectordat[drive][3], fdi_sectordat[drive][4], fdi_sectordat[drive][5]);
else
fdc_finishread(drive);
}
else fdc_headercrcerror();
return 1;
}
// pclog("Sector %i,%i %i,%i\n", fdi_sectordat[drive][0], fdi_sectordat[drive][2], fdi_track[drive], fdi_sector[drive]);
if (fdi_sectordat[drive][0] == fdi_track[drive] && (fdi_sectordat[drive][2] == fdi_sector[drive] || fdi_sector[drive] == SECTOR_NEXT) && fdi_inread[drive] && !fdi_inreadaddr[drive])
{
fdi_nextsector[drive] = 1;
readidpoll[drive] = 0;
sectorsize[drive] = (1 << (fdi_sectordat[drive][3] + 7)) + 2;
fdc_sectorsize[drive] = fdi_sectordat[drive][3];
}
if (fdi_inreadaddr[drive])
{
if (fdc_sectorid)
fdc_sectorid(fdi_sectordat[drive][0], fdi_sectordat[drive][1], fdi_sectordat[drive][2], fdi_sectordat[drive][3], fdi_sectordat[drive][4], fdi_sectordat[drive][5]);
else
fdc_finishread(drive);
fdi_inreadaddr[drive] = 0;
}
}
}
}
if (readdatapoll[drive])
{
// pclog("readdatapoll %i %02x\n", pollbytesleft[drive], decodefm(fdi_buffer[drive]));
if (pollbytesleft[drive] > 1)
{
calccrc(drive, decodefm(fdi_buffer[drive]));
}
else
sectorcrc[drive][1 - pollbytesleft[drive]] = decodefm(fdi_buffer[drive]);
if (!pollbytesleft[drive])
{
fdi_inread[drive] = 0;
//#if 0
if ((crc[drive] >> 8) != sectorcrc[drive][0] || (crc[drive] & 0xFF) != sectorcrc[drive][1])// || (fditrack[drive]==79 && fdisect[drive]==4 && fdc_side[drive]&1))
{
// pclog("Data CRC error : %02X %02X %02X %02X %i %04X %02X%02X\n",crc[drive]>>8,crc[drive]&0xFF,sectorcrc[0],sectorcrc[1],fdi_pos,crc,sectorcrc[0],sectorcrc[1]);
inreadop[drive] = 0;
fdc_data(decodefm(lastfdidat[drive][1]));
fdc_finishread(drive);
fdc_datacrcerror();
readdatapoll[drive] = 0;
return 1;
}
//#endif
// pclog("End of FDI read %02X %02X %02X %02X\n",crc[drive]>>8,crc[drive]&0xFF,sectorcrc[0],sectorcrc[1]);
fdc_data(decodefm(lastfdidat[drive][1]));
fdc_finishread(drive);
}
else if (lastfdidat[drive][1] != 0)
fdc_data(decodefm(lastfdidat[drive][1]));
lastfdidat[drive][1] = lastfdidat[drive][0];
lastfdidat[drive][0] = fdi_buffer[drive];
if (!pollbytesleft[drive])
readdatapoll[drive] = 0;
}
}
}
if (fdi_buffer[drive] == 0x4489 && fdi_density[drive])
{
// rpclog("Found sync\n");
ddidbitsleft[drive] = 17;
}
if (fdi_buffer[drive] == 0xF57E && !fdi_density[drive])
{
pollbytesleft[drive] = 6;
pollbitsleft[drive] = 16;
readidpoll[drive] = 1;
}
if ((fdi_buffer[drive] == 0xF56F || fdi_buffer[drive] == 0xF56A) && !fdi_density[drive])
{
if (fdi_nextsector[drive])
{
pollbytesleft[drive] = sectorsize[drive];
pollbitsleft[drive] = 16;
readdatapoll[drive] = 1;
fdi_nextsector[drive] = 0;
crc[drive] = 0xffff;
if (fdi_buffer[drive] == 0xF56A) calccrc(drive, 0xF8);
else calccrc(drive, 0xFB);
lastfdidat[drive][0] = lastfdidat[drive][1] = 0;
}
}
if (ddidbitsleft[drive])
{
ddidbitsleft[drive]--;
if (!ddidbitsleft[drive] && !readdatapoll[drive])
{
// printf("ID bits over %04X %02X %i\n",fdibuffer[drive],decodefm(fdibuffer[drive]),fdipos[drive]);
if (decodefm(fdi_buffer[drive]) == 0xFE)
{
// printf("Sector header %i %i\n", fdi_inread[drive], fdi_inreadaddr[drive]);
pollbytesleft[drive] = 6;
pollbitsleft[drive] = 16;
readidpoll[drive] = 1;
}
else if (decodefm(fdi_buffer[drive]) == 0xFB)
{
// printf("Data header %i %i\n", fdi_inread[drive], fdi_inreadaddr[drive]);
if (fdi_nextsector[drive])
{
pollbytesleft[drive] = sectorsize[drive];
pollbitsleft[drive] = 16;
readdatapoll[drive] = 1;
fdi_nextsector[drive] = 0;
crc[drive] = 0xcdb4;
if (fdi_buffer[drive] == 0xF56A) calccrc(drive, 0xF8);
else calccrc(drive, 0xFB);
lastfdidat[drive][0] = lastfdidat[drive][1] = 0;
}
}
}
}
}
}

13
src/disc_fdi.h Normal file
View File

@@ -0,0 +1,13 @@
void fdi_init();
void fdi_load(int drive, char *fn);
void fdi_close(int drive);
void fdi_seek(int drive, int track);
void fdi_readsector(int drive, int sector, int track, int side, int density, int sector_size);
void fdi_writesector(int drive, int sector, int track, int side, int density, int sector_size);
void fdi_readaddress(int drive, int sector, int side, int density);
void fdi_format(int drive, int sector, int side, int density, uint8_t fill);
int fdi_hole(int drive);
int fdi_byteperiod(int drive);
void fdi_stop(int drive);
int fdi_poll(int drive);
int fdi_realtrack(int track, int drive);

702
src/disc_img.c Normal file
View File

@@ -0,0 +1,702 @@
#include "ibm.h"
#include "fdd.h"
#include "disc.h"
#include "disc_img.h"
#include "disc_sector.h"
static struct
{
FILE *f;
// uint8_t track_data[2][20*1024];
uint8_t track_data[2][50000];
int sectors, tracks, sides;
int sector_size;
int rate;
int xdf_type; /* 0 = not XDF, 1-5 = one of the five XDF types */
int hole;
int byte_period;
double bitcell_period_300rpm;
} img[2];
#if 0
static uint8_t xdf_track0[5][3];
static uint8_t xdf_spt[5];
static uint8_t xdf_map[5][24][3];
#endif
static uint8_t xdf_track0[3][3];
static uint8_t xdf_spt[3];
static uint8_t xdf_map[3][24][3];
static uint16_t xdf_track0_layout[3][92] = { { 0x8100, 0x8200, 0x8300, 0x8400, 0x8500, 0x8600, 0x8700, 0x8800,
0x8101, 0x8201, 0x0100, 0x0200, 0x0300, 0x0400, 0x0500, 0x0600,
0x0700, 0x0800, 0, 0x8301, 0x8401, 0x8501, 0x8601, 0x8701,
0x8801, 0x8901, 0x8A01, 0x8B01, 0x8C01, 0x8D01, 0x8E01, 0x8F01,
0x9001 }, /* 5.25" 2HD */
{ 0x8100, 0x8200, 0x8300, 0x8400, 0x8500, 0x8600, 0x8700, 0x8800,
0x8900, 0x8A00, 0x8B00, 0x8101, 0x0100, 0x0200, 0x0300, 0x0400,
0x0500, 0x0600, 0x0700, 0x0800, 0, 0, 0, 0x8201,
0x8301, 0x8401, 0x8501, 0x8601, 0x8701, 0x8801, 0x8901, 0x8A01,
0x8B01, 0x8C01, 0x8D01, 0x8E01, 0x8F01, 0, 0, 0,
0, 0, 0x9001, 0x9101, 0x9201, 0x9301 }, /* 3.5" 2HD */
{ 0x8100, 0x8200, 0x8300, 0x8400, 0x8500, 0x8600, 0x8700, 0x8800,
0x8900, 0x8A00, 0x8B00, 0x8C00, 0x0100, 0x0200, 0x0300, 0x0400,
0x0500, 0x0600, 0x0700, 0x0800, 0x9500, 0x9600, 0x9700, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0x8D00, 0x8E00, 0x8F00, 0x9000, 0, 0,
0, 0, 0, 0, 0, 0x9800, 0x9900, 0x9A00,
0x9B00, 0x9C00, 0x9D00, 0x9E00, 0x8101, 0x8201, 0x8301, 0x8401,
0x8501, 0x8601, 0x8701, 0x9100, 0x9200, 0x9300, 0x9400, 0x8801,
0x8901, 0x8A01, 0x8B01, 0x8C01, 0x8D01, 0x8E01, 0x8F01, 0x9001,
0x9101, 0x9201, 0x9301, 0x9401, 0x9501, 0x9601, 0x9701, 0x9801,
0x9901, 0x9A01, 0x9B01, 0x9C01, 0x9D01, 0x9E01, 0x9F01, 0xA001,
0xA101, 0xA201, 0xA301, 0xA401 }, /* 3.5" 2ED - sectors 0x91 to 0x94 of side 0 are not written to the IMG file but
we read them in from the null-filled areas in order to have them as XDFCOPY
still expects their existence even if it does nothing with them. */
};
/* First dimension is possible sector sizes (0 = 128, 7 = 16384), second is possible bit rates (250/360, 250, 300, 500/360, 500, 1000). */
/* Disks formatted at 250 kbps @ 360 RPM can be read with a 360 RPM single-RPM 5.25" drive by setting the rate to 250 kbps.
Disks formatted at 300 kbps @ 300 RPM can be read with any 300 RPM single-RPM drive by setting the rate rate to 300 kbps. */
static uint8_t maximum_sectors[8][6] = { { 26, 31, 38, 53, 64, 118 }, /* 128 */
{ 15, 19, 23, 32, 38, 73 }, /* 256 */
{ 7, 10, 12, 19, 23, 46 }, /* 512 */
{ 3, 5, 6, 9, 11, 22 }, /* 1024 */
{ 2, 2, 3, 4, 5, 11 }, /* 2048 */
{ 1, 1, 1, 2, 2, 5 }, /* 4096 */
{ 0, 0, 0, 1, 1, 3 }, /* 8192 */
{ 0, 0, 0, 0, 0, 1 } }; /* 16384 */
static int gap3_sizes[5][8][256] = { [0][1][16] = 0x54,
[0][2][18] = 0x6C,
[0][2][19] = 0x48,
[0][2][20] = 0x2A,
[0][2][21] = 0x0C,
// [0][2][23] = 0x7A,
[0][2][23] = 0x01,
// [0][2][24] = 0x38,
[2][1][10] = 0x32,
[2][1][11] = 0x0C,
[2][1][15] = 0x36,
[2][1][16] = 0x32,
[2][2][8] = 0x58,
[2][2][9] = 0x50,
[2][2][10] = 0x2E,
[2][2][11] = 0x02,
[2][2][21] = 0x1C,
[2][3][4] = 0xF0,
[2][3][5] = 0x74,
[3][2][36] = 0x53,
[3][2][39] = 0x20,
// [3][2][46] = 0x0E,
[3][2][46] = 0x01,
// [3][2][48] = 0x51,
[4][1][32] = 0x36,
[4][2][15] = 0x54,
[4][2][17] = 0x23,
[4][2][18] = 0x02,
// [4][2][19] = 0x29,
[4][2][19] = 0x01,
[4][3][8] = 0x74,
[4][3][9] = 0x74,
[4][3][10] = 0x74
};
/* Needed for formatting! */
int img_realtrack(int drive, int track)
{
#ifdef MAINLINE
if ((img[drive].tracks <= 41) && fdd_doublestep_40(drive))
#else
if ((img[drive].tracks <= 43) && fdd_doublestep_40(drive))
#endif
track /= 2;
return track;
}
void img_writeback(int drive, int track);
static int img_sector_size_code(int drive)
{
switch(img[drive].sector_size)
{
case 128:
return 0;
case 256:
return 1;
default:
case 512:
return 2;
case 1024:
return 3;
case 2048:
return 4;
case 4096:
return 5;
case 8192:
return 6;
case 16384:
return 7;
}
}
static int sector_size_code(int sector_size)
{
switch(sector_size)
{
case 128:
return 0;
case 256:
return 1;
default:
case 512:
return 2;
case 1024:
return 3;
case 2048:
return 4;
case 4096:
return 5;
case 8192:
return 6;
case 16384:
return 7;
}
}
void img_init()
{
memset(img, 0, sizeof(img));
// adl[0] = adl[1] = 0;
}
static void add_to_map(uint8_t *arr, uint8_t p1, uint8_t p2, uint8_t p3)
{
arr[0] = p1;
arr[1] = p2;
arr[2] = p3;
}
static int xdf_maps_initialized = 0;
static void initialize_xdf_maps()
{
// XDF 5.25" 2HD
/* Adds, in this order: sectors per FAT, sectors per each side of track 0, difference between that and virtual sector number specified in BPB. */
add_to_map(xdf_track0[0], 9, 17, 2);
xdf_spt[0] = 3;
/* Adds, in this order: side, sequential order (not used in PCem), sector size. */
add_to_map(xdf_map[0][0], 0, 0, 3);
add_to_map(xdf_map[0][1], 0, 2, 6);
add_to_map(xdf_map[0][2], 1, 0, 2);
add_to_map(xdf_map[0][3], 0, 1, 2);
add_to_map(xdf_map[0][4], 1, 2, 6);
add_to_map(xdf_map[0][5], 1, 1, 3);
// XDF 3.5" 2HD
add_to_map(xdf_track0[1], 11, 19, 4);
xdf_spt[1] = 4;
add_to_map(xdf_map[1][0], 0, 0, 3);
add_to_map(xdf_map[1][1], 0, 2, 4);
add_to_map(xdf_map[1][2], 1, 3, 6);
add_to_map(xdf_map[1][3], 0, 1, 2);
add_to_map(xdf_map[1][4], 1, 1, 2);
add_to_map(xdf_map[1][5], 0, 3, 6);
add_to_map(xdf_map[1][6], 1, 0, 4);
add_to_map(xdf_map[1][7], 1, 2, 3);
// XDF 3.5" 2ED
add_to_map(xdf_track0[2], 22, 37, 9);
xdf_spt[2] = 4;
add_to_map(xdf_map[2][0], 0, 0, 3);
add_to_map(xdf_map[2][1], 0, 1, 4);
add_to_map(xdf_map[2][2], 0, 2, 5);
add_to_map(xdf_map[2][3], 0, 3, 7);
add_to_map(xdf_map[2][4], 1, 0, 3);
add_to_map(xdf_map[2][5], 1, 1, 4);
add_to_map(xdf_map[2][6], 1, 2, 5);
add_to_map(xdf_map[2][7], 1, 3, 7);
#if 0
// XXDF 3.5" 2HD
add_to_map(xdf_track0[3], 12, 20, 4);
xdf_spt[3] = 2;
add_to_map(xdf_map[3][0], 0, 0, 5);
add_to_map(xdf_map[3][1], 1, 1, 6);
add_to_map(xdf_map[3][2], 0, 1, 6);
add_to_map(xdf_map[3][3], 1, 0, 5);
// XXDF 3.5" 2ED
add_to_map(xdf_track0[4], 21, 39, 9);
xdf_spt[4] = 2;
add_to_map(xdf_map[4][0], 0, 0, 6);
add_to_map(xdf_map[4][1], 1, 1, 7);
add_to_map(xdf_map[4][2], 0, 1, 7);
add_to_map(xdf_map[4][3], 1, 0, 6);
#endif
xdf_maps_initialized = 1;
}
void img_load(int drive, char *fn)
{
int size;
double bit_rate_300;
uint16_t bpb_bps;
uint16_t bpb_total;
uint8_t bpb_mid; /* Media type ID. */
uint8_t bpb_sectors;
uint8_t bpb_sides;
uint32_t bpt;
uint8_t max_spt; /* Used for XDF detection. */
int temp_rate;
if (!xdf_maps_initialized) initialize_xdf_maps(); /* Initialize XDF maps, will need them to properly register sectors in tracks. */
writeprot[drive] = 0;
img[drive].f = fopen(fn, "rb+");
if (!img[drive].f)
{
img[drive].f = fopen(fn, "rb");
if (!img[drive].f)
return;
writeprot[drive] = 1;
}
fwriteprot[drive] = writeprot[drive];
/* Read the BPB */
fseek(img[drive].f, 0x0B, SEEK_SET);
fread(&bpb_bps, 1, 2, img[drive].f);
fseek(img[drive].f, 0x13, SEEK_SET);
fread(&bpb_total, 1, 2, img[drive].f);
fseek(img[drive].f, 0x15, SEEK_SET);
bpb_mid = fgetc(img[drive].f);
fseek(img[drive].f, 0x18, SEEK_SET);
bpb_sectors = fgetc(img[drive].f);
fseek(img[drive].f, 0x1A, SEEK_SET);
bpb_sides = fgetc(img[drive].f);
fseek(img[drive].f, -1, SEEK_END);
size = ftell(img[drive].f) + 1;
img[drive].sides = 2;
img[drive].sector_size = 512;
img[drive].hole = 0;
pclog("BPB reports %i sides and %i bytes per sector\n", bpb_sides, bpb_bps);
if ((bpb_sides < 1) || (bpb_sides > 2) || (bpb_bps < 128) || (bpb_bps > 2048))
{
/* The BPB is giving us a wacky number of sides and/or bytes per sector, therefore it is most probably
not a BPB at all, so we have to guess the parameters from file size. */
if (size <= (160*1024)) { img[drive].sectors = 8; img[drive].tracks = 40; img[drive].sides = 1; bit_rate_300 = 250; raw_tsize[drive] = 6250; }
else if (size <= (180*1024)) { img[drive].sectors = 9; img[drive].tracks = 40; img[drive].sides = 1; bit_rate_300 = 250; raw_tsize[drive] = 6250; }
else if (size <= (320*1024)) { img[drive].sectors = 8; img[drive].tracks = 40; bit_rate_300 = 250; raw_tsize[drive] = 6250; }
else if (size <= (360*1024)) { img[drive].sectors = 9; img[drive].tracks = 40; bit_rate_300 = 250; raw_tsize[drive] = 6250; } /*Double density*/
else if (size <= (640*1024)) { img[drive].sectors = 8; img[drive].tracks = 80; bit_rate_300 = 250; raw_tsize[drive] = 6250; } /*Double density 640k*/
else if (size < (1024*1024)) { img[drive].sectors = 9; img[drive].tracks = 80; bit_rate_300 = 250; raw_tsize[drive] = 6250; } /*Double density*/
else if (size <= 1228800) { img[drive].sectors = 15; img[drive].tracks = 80; bit_rate_300 = (500.0 * 300.0) / 360.0; raw_tsize[drive] = 10416; } /*High density 1.2MB*/
else if (size <= 1261568) { img[drive].sectors = 8; img[drive].tracks = 77; img[drive].sector_size = 1024; bit_rate_300 = (500.0 * 300.0) / 360.0; raw_tsize[drive] = 10416; } /*High density 1.25MB Japanese format*/
else if (size <= (0x1A4000-1)) { img[drive].sectors = 18; img[drive].tracks = 80; bit_rate_300 = 500; raw_tsize[drive] = 12500; } /*High density (not supported by Tandy 1000)*/
else if (size <= 1556480) { img[drive].sectors = 19; img[drive].tracks = 80; bit_rate_300 = 500; raw_tsize[drive] = 12500; } /*High density (not supported by Tandy 1000)*/
else if (size <= 1638400) { img[drive].sectors = 10; img[drive].tracks = 80; img[drive].sector_size = 1024; bit_rate_300 = 500; raw_tsize[drive] = 12500; } /*High density (not supported by Tandy 1000)*/
// else if (size == 1884160) { img[drive].sectors = 23; img[drive].tracks = 80; bit_rate_300 = 500; } /*XDF format - used by OS/2 Warp*/
// else if (size == 1763328) { img[drive].sectors = 21; img[drive].tracks = 82; bit_rate_300 = 500; } /*XDF format - used by OS/2 Warp*/
else if (size <= 2000000) { img[drive].sectors = 21; img[drive].tracks = 80; bit_rate_300 = 500; raw_tsize[drive] = 12500; } /*DMF format - used by Windows 95 - changed by OBattler to 2000000, ie. the real unformatted capacity @ 500 kbps and 300 rpm */
else if (size <= 2949120) { img[drive].sectors = 36; img[drive].tracks = 80; bit_rate_300 = 1000; raw_tsize[drive] = 25000; } /*E density*/
img[drive].xdf_type = 0;
}
else
{
/* The BPB readings appear to be valid, so let's set the values. */
/* Number of tracks = number of total sectors divided by sides times sectors per track. */
img[drive].tracks = ((uint32_t) bpb_total) / (((uint32_t) bpb_sides) * ((uint32_t) bpb_sectors));
/* The rest we just set directly from the BPB. */
img[drive].sectors = bpb_sectors;
img[drive].sides = bpb_sides;
/* Now we calculate bytes per track, which is bpb_sectors * bpb_bps. */
bpt = (uint32_t) bpb_sectors * (uint32_t) bpb_bps;
/* Now we should be able to calculate the bit rate. */
pclog("The image has %i bytes per track\n", bpt);
temp_rate = 2;
if (bpt <= (maximum_sectors[sector_size_code(bpb_bps)][0] * bpb_bps))
{
bit_rate_300 = ((250.0 * 300.0) / 360.0);
temp_rate = 2;
raw_tsize[drive] = 5208;
}
else if (bpt <= (maximum_sectors[sector_size_code(bpb_bps)][1] * bpb_bps))
{
bit_rate_300 = 250;
temp_rate = 2;
raw_tsize[drive] = 6250;
}
else if (bpt <= (maximum_sectors[sector_size_code(bpb_bps)][2] * bpb_bps))
{
bit_rate_300 = 300;
temp_rate = 1;
raw_tsize[drive] = 7500;
}
else if (bpt <= (maximum_sectors[sector_size_code(bpb_bps)][3] * bpb_bps))
{
bit_rate_300 = (bpb_mid == 0xF0) ? 500 : ((500.0 * 300.0) / 360.0);
if (bpb_bps == 512) max_spt = (bit_rate_300 == 500) ? 21 : 17;
temp_rate = (bit_rate_300 == 500) ? 0 : 4;
raw_tsize[drive] = (bit_rate_300 == 500) ? 12500 : 10416;
}
else if (bpt <= (maximum_sectors[sector_size_code(bpb_bps)][4] * bpb_bps))
{
bit_rate_300 = 500;
if (bpb_bps == 512) max_spt = 21;
pclog("max_spt is %i\n", max_spt);
temp_rate = 0;
raw_tsize[drive] = 12500;
}
else if (bpt <= (maximum_sectors[sector_size_code(bpb_bps)][5] * bpb_bps))
{
bit_rate_300 = 1000;
if (bpb_bps == 512) max_spt = 41;
temp_rate = 3;
raw_tsize[drive] = 25000;
}
else /* Image too big, eject */
{
pclog("Image is bigger than can fit on an ED floppy, ejecting...\n");
fclose(img[drive].f);
return;
}
if (bpb_bps == 512) /* BPB reports 512 bytes per sector, let's see if it's XDF or not */
{
if (bit_rate_300 <= 300) /* Double-density disk, not XDF */
{
img[drive].xdf_type = 0;
}
else
{
pclog("bpb_sectors is %i\n", bpb_sectors);
if (bpb_sectors > max_spt)
{
switch(bpb_sectors)
{
case 19: /* High density XDF @ 360 rpm */
img[drive].xdf_type = 1;
break;
case 23: /* High density XDF @ 300 rpm */
img[drive].xdf_type = 2;
pclog("XDF type is 2 @ %i kbps\n", bit_rate_300);
break;
#if 0
case 24: /* High density XXDF @ 300 rpm */
img[drive].xdf_type = 4;
break;
#endif
case 46: /* Extended density XDF */
img[drive].xdf_type = 3;
break;
#if 0
case 48: /* Extended density XXDF */
img[drive].xdf_type = 5;
break;
#endif
default: /* Unknown, as we're beyond maximum sectors, get out */
fclose(img[drive].f);
return;
}
}
else /* Amount of sectors per track that fits into a track, therefore not XDF */
{
img[drive].xdf_type = 0;
}
}
}
else /* BPB reports sector size other than 512, can't possibly be XDF */
{
img[drive].xdf_type = 0;
}
}
gap2_size[drive] = (temp_rate == 3) ? 41 : 22;
pclog("GAP2 size: %i bytes\n", gap2_size[drive]);
gap3_size[drive] = gap3_sizes[temp_rate][sector_size_code(img[drive].sector_size)][img[drive].sectors];
if (gap3_size)
{
pclog("GAP3 size: %i bytes\n", gap3_size[drive]);
}
else
{
// fclose(img[drive].f);
gap3_size[drive] = 40;
pclog("WARNING: Floppy image of unknown format was inserted into drive %c:!\n", drive + 0x41);
}
gap4_size[drive] = raw_tsize[drive] - (((pre_gap + gap2_size[drive] + pre_data + data_size + post_gap + gap3_size[drive]) * img[drive].sectors) + pre_track);
pclog("GAP4 size: %i bytes\n", gap4_size[drive]);
if (img[drive].xdf_type)
{
gap4_size[drive] = 1;
}
if (bit_rate_300 == 250)
{
img[drive].hole = 0;
/* If drive does not support 300 RPM, the medium is to be read at a period of 26 (300 kbps). */
img[drive].byte_period = 29;
}
else if (bit_rate_300 == 300)
{
img[drive].hole = 0;
img[drive].byte_period = 26;
}
else if (bit_rate_300 == 1000)
{
img[drive].hole = 2;
img[drive].byte_period = 8;
}
else if (bit_rate_300 < 250)
{
img[drive].hole = 0;
img[drive].byte_period = 32;
}
else
{
img[drive].hole = 1;
img[drive].byte_period = 16;
}
if (img[drive].xdf_type) /* In case of XDF-formatted image, write-protect */
{
writeprot[drive] = 1;
fwriteprot[drive] = writeprot[drive];
}
drives[drive].seek = img_seek;
drives[drive].readsector = disc_sector_readsector;
drives[drive].writesector = disc_sector_writesector;
drives[drive].readaddress = disc_sector_readaddress;
drives[drive].hole = img_hole;
drives[drive].byteperiod = img_byteperiod;
drives[drive].poll = disc_sector_poll;
drives[drive].format = disc_sector_format;
drives[drive].realtrack = img_realtrack;
drives[drive].stop = disc_sector_stop;
disc_sector_writeback[drive] = img_writeback;
img[drive].bitcell_period_300rpm = 1000000.0 / bit_rate_300*2.0;
pclog("bit_rate_300=%g\n", bit_rate_300);
pclog("bitcell_period_300=%g\n", img[drive].bitcell_period_300rpm);
// img[drive].bitcell_period_300rpm = disc_get_bitcell_period(img[drive].rate);
pclog("img_load %d %p sectors=%i tracks=%i sides=%i sector_size=%i hole=%i\n", drive, drives, img[drive].sectors, img[drive].tracks, img[drive].sides, img[drive].sector_size, img[drive].hole);
}
int img_hole(int drive)
{
return img[drive].hole;
}
int img_byteperiod(int drive)
{
if (img[drive].byte_period == 29)
{
return (fdd_get_type(drive) & 1) ? 32 : 26;
}
return img[drive].byte_period;
}
void img_close(int drive)
{
if (img[drive].f)
fclose(img[drive].f);
img[drive].f = NULL;
}
void img_seek(int drive, int track)
{
int side;
int current_xdft = img[drive].xdf_type - 1;
uint8_t sectors_fat, effective_sectors, sector_gap; /* Needed for XDF */
if (!img[drive].f)
return;
// pclog("Seek drive=%i track=%i sectors=%i sector_size=%i sides=%i\n", drive, track, img[drive].sectors,img[drive].sector_size, img[drive].sides);
// pclog(" %i %i\n", drive_type[drive], img[drive].tracks);
#ifdef MAINLINE
if ((img[drive].tracks <= 41) && fdd_doublestep_40(drive))
#else
if ((img[drive].tracks <= 43) && fdd_doublestep_40(drive))
#endif
track /= 2;
// pclog("Disk seeked to track %i\n", track);
disc_track[drive] = track;
if (img[drive].sides == 2)
{
fseek(img[drive].f, track * img[drive].sectors * img[drive].sector_size * 2, SEEK_SET);
// pclog("Seek: Current file position (H0) is: %08X\n", ftell(img[drive].f));
fread(img[drive].track_data[0], img[drive].sectors * img[drive].sector_size, 1, img[drive].f);
// pclog("Seek: Current file position (H1) is: %08X\n", ftell(img[drive].f));
fread(img[drive].track_data[1], img[drive].sectors * img[drive].sector_size, 1, img[drive].f);
}
else
{
fseek(img[drive].f, track * img[drive].sectors * img[drive].sector_size, SEEK_SET);
fread(img[drive].track_data[0], img[drive].sectors * img[drive].sector_size, 1, img[drive].f);
}
disc_sector_reset(drive, 0);
disc_sector_reset(drive, 1);
int sector, current_pos, sh, sr, spos, sside;
if (img[drive].xdf_type)
{
sectors_fat = xdf_track0[current_xdft][0];
effective_sectors = xdf_track0[current_xdft][1];
sector_gap = xdf_track0[current_xdft][2];
if (!track)
{
/* Track 0, register sectors according to track 0 layout. */
current_pos = 0;
for (sector = 0; sector < (img[drive].sectors * 2); sector++)
{
if (xdf_track0_layout[current_xdft][sector])
{
sh = xdf_track0_layout[current_xdft][sector] & 0xFF;
sr = xdf_track0_layout[current_xdft][sector] >> 8;
spos = current_pos;
sside = 0;
if (spos > (img[drive].sectors * img[drive].sector_size))
{
spos -= (img[drive].sectors * img[drive].sector_size);
sside = 1;
}
disc_sector_add(drive, sh, track, sh, sr, 2,
img[drive].bitcell_period_300rpm,
&img[drive].track_data[sside][spos]);
}
current_pos += 512;
}
#if 0
/* Track 0, register sectors according to track 0 map. */
/* First, the "Side 0" buffer, will also contain one sector from side 1. */
current_pos = 0;
for (sector = 0; sector < sectors_fat; sector++)
{
if ((sector+0x81) >= 0x91)
{
disc_sector_add(drive, 0, track, 0, sector+0x85, 2,
img[drive].bitcell_period_300rpm,
&img[drive].track_data[0][current_pos]);
}
else
{
disc_sector_add(drive, 0, track, 0, sector+0x81, 2,
img[drive].bitcell_period_300rpm,
&img[drive].track_data[0][current_pos]);
}
current_pos += 512;
}
disc_sector_add(drive, 1, track, 1, 0x81, 2,
img[drive].bitcell_period_300rpm,
&img[drive].track_data[0][current_pos]);
current_pos += 512;
for (sector = 0; sector < 7; sector++)
{
disc_sector_add(drive, 0, track, 0, sector+1, 2,
img[drive].bitcell_period_300rpm,
&img[drive].track_data[0][current_pos]);
current_pos += 512;
}
disc_sector_add(drive, 0, track, 0, 0x9B, 2,
img[drive].bitcell_period_300rpm,
&img[drive].track_data[0][current_pos]);
current_pos += 512;
disc_sector_add(drive, 0, track, 0, 0x9C, 2,
img[drive].bitcell_period_300rpm,
&img[drive].track_data[0][current_pos]);
current_pos += 512;
disc_sector_add(drive, 0, track, 0, 0x9D, 2,
img[drive].bitcell_period_300rpm,
&img[drive].track_data[0][current_pos]);
current_pos += 512;
disc_sector_add(drive, 0, track, 0, 0x9E, 2,
img[drive].bitcell_period_300rpm,
&img[drive].track_data[0][current_pos]);
current_pos += 512;
/* Now the "Side 1" buffer, will also contain one sector from side 0. */
current_pos = 0;
for (sector = 0; (sector < effective_sectors - 1); sector++)
{
disc_sector_add(drive, 1, track, 1, sector+0x82, 2,
img[drive].bitcell_period_300rpm,
&img[drive].track_data[1][current_pos]);
current_pos += 512;
}
disc_sector_add(drive, 0, track, 0, 8, 2,
img[drive].bitcell_period_300rpm,
&img[drive].track_data[1][current_pos]);
current_pos += 512;
#endif
}
else
{
/* Non-zero track, this will have sectors of various sizes. */
/* First, the "Side 0" buffer. */
current_pos = 0;
for (sector = 0; sector < xdf_spt[current_xdft]; sector++)
{
disc_sector_add(drive, xdf_map[current_xdft][sector][0], track, xdf_map[current_xdft][sector][0],
xdf_map[current_xdft][sector][2] + 0x80, xdf_map[current_xdft][sector][2],
img[drive].bitcell_period_300rpm,
&img[drive].track_data[0][current_pos]);
current_pos += (128 << xdf_map[current_xdft][sector][2]);
}
/* Then, the "Side 1" buffer. */
current_pos = 0;
for (sector = xdf_spt[current_xdft]; sector < (xdf_spt[current_xdft] << 1); sector++)
{
disc_sector_add(drive, xdf_map[current_xdft][sector][0], track, xdf_map[current_xdft][sector][0],
xdf_map[current_xdft][sector][2] + 0x80, xdf_map[current_xdft][sector][2],
img[drive].bitcell_period_300rpm,
&img[drive].track_data[1][current_pos]);
current_pos += (128 << xdf_map[current_xdft][sector][2]);
}
}
}
else
{
for (side = 0; side < img[drive].sides; side++)
{
for (sector = 0; sector < img[drive].sectors; sector++)
disc_sector_add(drive, side, track, side, sector+1, img_sector_size_code(drive),
img[drive].bitcell_period_300rpm,
&img[drive].track_data[side][sector * img[drive].sector_size]);
}
}
}
void img_writeback(int drive, int track)
{
if (!img[drive].f)
return;
if (img[drive].xdf_type)
return; /*Should never happen*/
if (img[drive].sides == 2)
{
fseek(img[drive].f, track * img[drive].sectors * img[drive].sector_size * 2, SEEK_SET);
fwrite(img[drive].track_data[0], img[drive].sectors * img[drive].sector_size, 1, img[drive].f);
fwrite(img[drive].track_data[1], img[drive].sectors * img[drive].sector_size, 1, img[drive].f);
}
else
{
fseek(img[drive].f, track * img[drive].sectors * img[drive].sector_size, SEEK_SET);
fwrite(img[drive].track_data[0], img[drive].sectors * img[drive].sector_size, 1, img[drive].f);
}
}

13
src/disc_img.h Normal file
View File

@@ -0,0 +1,13 @@
void img_init();
void img_load(int drive, char *fn);
void img_close(int drive);
void img_seek(int drive, int track);
void img_readsector(int drive, int sector, int track, int side, int density);
void img_writesector(int drive, int sector, int track, int side, int density);
void img_readaddress(int drive, int sector, int side, int density);
void img_format(int drive, int sector, int side, int density);
int img_hole(int drive);
int img_byteperiod(int drive);
void img_stop(int drive);
void img_poll();
int img_realtrack(int track, int drive);

525
src/disc_sector.c Normal file
View File

@@ -0,0 +1,525 @@
#include "ibm.h"
#include "disc.h"
#include "disc_sector.h"
#include "fdd.h"
/*Handling for 'sector based' image formats (like .IMG) as opposed to 'stream based' formats (eg .FDI)*/
#define MAX_SECTORS 256
typedef struct
{
uint8_t c, h, r, n;
int rate;
uint8_t *data;
} sector_t;
static sector_t disc_sector_data[2][2][MAX_SECTORS];
static int disc_sector_count[2][2];
void (*disc_sector_writeback[2])(int drive, int track);
enum
{
STATE_IDLE,
STATE_READ_FIND_SECTOR,
STATE_READ_SECTOR,
STATE_READ_FIND_FIRST_SECTOR,
STATE_READ_FIRST_SECTOR,
STATE_READ_FIND_NEXT_SECTOR,
STATE_READ_NEXT_SECTOR,
STATE_WRITE_FIND_SECTOR,
STATE_WRITE_SECTOR,
STATE_READ_FIND_ADDRESS,
STATE_READ_ADDRESS,
STATE_FORMAT_FIND,
STATE_FORMAT
};
static int processed_bytes[2] = {0, 0};
static int disc_sector_state[2] = {0, 0};
static int disc_sector_track[2] = {0, 0};
static int disc_sector_side[2] = {0, 0};
// static int disc_sector_drive[2] = {0, 0};
static int disc_sector_sector[2] = {0, 0};
static int disc_sector_n[2] = {0, 0};
static int disc_intersector_delay[2] = {0, 0};
static int disc_postdata_delay[2] = {0, 0};
static int disc_track_delay[2] = {0, 0};
static int disc_gap4_delay[2] = {0, 0};
static uint8_t disc_sector_fill[2] = {0, 0};
static int cur_sector[2], cur_byte[2];
static int index_count[2];
int gap2 = length_gap2;
int gap3 = length_gap3;
int gap3_0 = length_gap3_0;
int gap4 = raw_track_size - (((pre_gap + length_gap2 + pre_data + data_size + post_gap + length_gap3) * no_sectors) + pre_track);
int gap4_0 = raw_track_size_0 - (((pre_gap + length_gap2 + pre_data + data_size + post_gap + length_gap3_0) * no_sectors_0) + pre_track);
int raw_tsize[2] = {6250, 6250};
int gap2_size[2] = {22, 22};
int gap3_size[2] = {0, 0};
int gap4_size[2] = {0, 0};
void disc_sector_reset(int drive, int side)
{
disc_sector_count[drive][side] = 0;
disc_intersector_delay[drive] = 0;
disc_postdata_delay[drive] = 0;
disc_track_delay[drive] = 0;
disc_gap4_delay[drive] = 0;
cur_sector[drive] = 0;
cur_byte[drive] = 0;
index_count[drive] = 0;
}
void disc_sector_add(int drive, int side, uint8_t c, uint8_t h, uint8_t r, uint8_t n, int rate, uint8_t *data)
{
sector_t *s = &disc_sector_data[drive][side][disc_sector_count[drive][side]];
//pclog("disc_sector_add: drive=%i side=%i %i r=%i\n", drive, side, disc_sector_count[drive][side],r );
if (disc_sector_count[drive][side] >= MAX_SECTORS)
return;
s->c = c;
s->h = h;
s->r = r;
s->n = n;
s->rate = rate;
s->data = data;
disc_sector_count[drive][side]++;
}
static int get_bitcell_period(int drive)
{
return (disc_sector_data[drive][disc_sector_side[drive]][cur_sector[drive]].rate * 300) / fdd_getrpm(drive);
}
void disc_sector_readsector(int drive, int sector, int track, int side, int rate, int sector_size)
{
pclog("disc_sector_readsector: fdc_period=%i img_period=%i rate=%i sector=%i track=%i side=%i\n", fdc_get_bitcell_period(), get_bitcell_period(drive), rate, sector, track, side);
pclog("pre_track=%i, pre_sector=%i, gap4=%i\n", pre_track, post_gap + gap3 + pre_gap + gap2 + pre_data, gap4);
if (sector == SECTOR_FIRST)
disc_sector_state[drive] = STATE_READ_FIND_FIRST_SECTOR;
else if (sector == SECTOR_NEXT)
disc_sector_state[drive] = STATE_READ_FIND_NEXT_SECTOR;
else
disc_sector_state[drive] = STATE_READ_FIND_SECTOR;
disc_sector_track[drive] = track;
disc_sector_side[drive] = side;
// disc_sector_drive = drive;
disc_sector_sector[drive] = sector;
disc_sector_n[drive] = sector_size;
if ((cur_sector[drive] == 0) && (cur_byte[drive] == 0) && !disc_track_delay[drive]) disc_track_delay[drive] = pre_track;
index_count[drive] = 0;
processed_bytes[drive] = 0;
// pclog("Disk poll time is: %i\n", disc_poll_time);
}
void disc_sector_writesector(int drive, int sector, int track, int side, int rate, int sector_size)
{
pclog("disc_sector_writesector: fdc_period=%i img_period=%i rate=%i\n", fdc_get_bitcell_period(), get_bitcell_period(drive), rate);
disc_sector_state[drive] = STATE_WRITE_FIND_SECTOR;
disc_sector_track[drive] = track;
disc_sector_side[drive] = side;
// disc_sector_drive = drive;
disc_sector_sector[drive] = sector;
disc_sector_n[drive] = sector_size;
if ((cur_sector[drive] == 0) && (cur_byte[drive] == 0) && !disc_track_delay[drive]) disc_track_delay[drive] = pre_track;
index_count[drive] = 0;
processed_bytes[drive] = 0;
}
void disc_sector_readaddress(int drive, int track, int side, int rate)
{
pclog("disc_sector_readaddress: fdc_period=%i img_period=%i rate=%i track=%i side=%i\n", fdc_get_bitcell_period(), get_bitcell_period(drive), rate, track, side);
disc_sector_state[drive] = STATE_READ_FIND_ADDRESS;
disc_sector_track[drive] = track;
disc_sector_side[drive] = side;
// disc_sector_drive = drive;
if ((cur_sector[drive] == 0) && (cur_byte[drive] == 0) && !disc_track_delay[drive])
{
disc_track_delay[drive] = pre_track;
index_count[drive] = -1;
}
else
index_count[drive] = 0;
processed_bytes[drive] = 0;
}
void disc_sector_format(int drive, int track, int side, int rate, uint8_t fill)
{
disc_sector_state[drive] = STATE_FORMAT_FIND;
disc_sector_track[drive] = track;
disc_sector_side[drive] = side;
// disc_sector_drive = drive;
disc_sector_fill[drive] = fill;
index_count[drive] = 0;
}
void disc_sector_stop(int drive)
{
disc_sector_state[drive] = STATE_IDLE;
}
static void index_pulse(int drive)
{
if (disc_sector_state[drive] != STATE_IDLE) fdc_indexpulse();
}
static int advance_byte(int drive)
{
/* 0 = regular byte, 1 = missing clock pulse */
int type = 0;
processed_bytes[drive]++;
// pclog("advance_byte(%i): %i\n", drive, processed_bytes[drive]);
if (disc_postdata_delay[drive])
{
disc_postdata_delay[drive]--;
return type;
}
if (disc_gap4_delay[drive])
{
disc_gap4_delay[drive]--;
return type;
}
if (disc_track_delay[drive])
{
if ((disc_track_delay[drive] >= (pre_track - 92)) && (disc_track_delay[drive] <= (pre_track - 94))) type = 1;
if (disc_track_delay[drive] == pre_track)
{
// pclog("Track index pulse!\n");
index_pulse(drive);
index_count[drive]++;
}
disc_track_delay[drive]--;
if (type) pclog("advance_byte(): Track sync\n");
return type;
}
if (disc_intersector_delay[drive])
{
if ((disc_intersector_delay[drive] >= (pre_gap + gap2_size[drive] + pre_data - 12)) && (disc_intersector_delay[drive] <= (pre_gap + gap2_size[drive] + pre_data - 14))) type = 1;
if ((disc_intersector_delay[drive] >= (pre_gap + gap2_size[drive] + pre_data - 56)) && (disc_intersector_delay[drive] <= (pre_gap + gap2_size[drive] + pre_data - 58))) type = 2;
disc_intersector_delay[drive]--;
if (type == 1) pclog("advance_byte(): Sector address sync\n");
if (type == 2) pclog("advance_byte(): Sector sync\n");
return type;
}
cur_byte[drive]++;
if (cur_byte[drive] >= (128 << disc_sector_data[drive][disc_sector_side[drive]][cur_sector[drive]].n))
{
cur_byte[drive] = 0;
cur_sector[drive]++;
disc_postdata_delay[drive] = post_gap + (gap3_size[drive]);
if (cur_sector[drive] >= disc_sector_count[drive][disc_sector_side[drive]])
{
cur_sector[drive] = 0;
disc_gap4_delay[drive] = (gap4_size[drive]);
disc_track_delay[drive] = pre_track;
disc_intersector_delay[drive] = pre_gap + gap2_size[drive] + pre_data;
}
else
{
disc_gap4_delay[drive] = 0;
disc_track_delay[drive] = 0;
disc_intersector_delay[drive] = pre_gap + gap2_size[drive] + pre_data;
}
}
return type;
}
int head_byte(int drive, int h)
{
return (fdd_get_head(drive) << 2) | h;
}
int disc_sector_poll(int drive)
{
sector_t *s;
int data;
int do_period = 0;
int sector_type = 0;
if (cur_sector[drive] >= disc_sector_count[drive][disc_sector_side[drive]])
cur_sector[drive] = 0;
if (cur_byte[drive] >= (128 << disc_sector_data[drive][disc_sector_side[drive]][cur_sector[drive]].n))
cur_byte[drive] = 0;
/* Note: Side to read from should be chosen from FDC head select rather than from the sector ID. */
s = &disc_sector_data[drive][disc_sector_side[drive]][cur_sector[drive]];
if (fdd_stepping_motor_on[drive])
{
/* If stepping motor is on, turn off data separator. */
sector_type = advance_byte(drive);
do_period = 1;
do_period = do_period ? ((sector_type > 0) ? 2 : 1) : 0;
return do_period;
}
switch (disc_sector_state[drive])
{
case STATE_IDLE:
sector_type = advance_byte(drive);
do_period = 1;
break;
case STATE_READ_FIND_SECTOR:
/* pclog("STATE_READ_FIND_SECTOR: cur_sector=%i cur_byte=%i sector=%i,%i side=%i,%i track=%i,%i period=%i,%i\n",
cur_sector[drive], cur_byte[drive],
disc_sector_sector[drive], s->r,
disc_sector_side[drive], s->h,
disc_sector_track[drive], s->c,
fdc_get_bitcell_period(), get_bitcell_period(drive));*/
if (index_count[drive] > 1)
{
// pclog("Find sector not found\n");
pclog("READ: Sector (%i %i %i %i) not found (last: %i %i %i) (period=%i,%i)\n", s->c, s->h, s->r, s->n, disc_sector_track, disc_sector_side, disc_sector_sector, fdc_get_bitcell_period(), get_bitcell_period(drive));
fdc_notfound();
disc_sector_state[drive] = STATE_IDLE;
break;
}
/* pclog("%i %i %i %i %i\n", cur_byte[drive], disc_sector_track[drive] != s->c,
disc_sector_side[drive] != s->h,
disc_sector_sector[drive] != s->r,
fdc_get_bitcell_period() != get_bitcell_period(drive));*/
if (cur_byte[drive] || disc_sector_track[drive] != s->c ||
disc_sector_side[drive] != s->h ||
disc_sector_sector[drive] != s->r ||
disc_sector_n[drive] != s->n ||
(fdc_get_bitcell_period() != get_bitcell_period(drive)) ||
!fdd_can_read_medium(drive ^ fdd_swap) ||
disc_intersector_delay[drive] || disc_track_delay[drive])
{
// pclog("Poll: Find sector advance byte!\n");
sector_type = advance_byte(drive);
do_period = 1;
break;
}
disc_sector_state[drive] = STATE_READ_SECTOR;
case STATE_READ_SECTOR:
// pclog("STATE_READ_SECTOR: cur_byte=%i %i\n", cur_byte[drive], disc_intersector_delay[drive]);
if (fdc_data(s->data[cur_byte[drive]]))
{
// pclog("fdc_data failed\n");
return 0;
}
sector_type = advance_byte(drive);
do_period = 1;
if (!cur_byte[drive])
{
disc_sector_state[drive] = STATE_IDLE;
pclog("Processed bytes: %i, byte pulses: %i\n", processed_bytes[drive], bpulses[drive]);
// pclog("Disk poll time is: %i\n", disc_poll_time);
fdc_finishread(drive);
}
break;
case STATE_READ_FIND_FIRST_SECTOR:
if (!fdd_can_read_medium(drive ^ fdd_swap))
{
pclog("Medium is of a density not supported by the drive\n");
fdc_notfound();
disc_sector_state[drive] = STATE_IDLE;
break;
}
if (cur_byte[drive] || !index_count[drive] || fdc_get_bitcell_period() != get_bitcell_period(drive) ||
disc_intersector_delay[drive] || disc_track_delay[drive])
{
// pclog("Poll: Find sector advance byte!\n");
sector_type = advance_byte(drive);
do_period = 1;
break;
}
disc_sector_state[drive] = STATE_READ_FIRST_SECTOR;
case STATE_READ_FIRST_SECTOR:
if (fdc_data(s->data[cur_byte[drive]]))
return 0;
sector_type = advance_byte(drive);
do_period = 1;
if (!cur_byte[drive])
{
disc_sector_state[drive] = STATE_IDLE;
pclog("Processed bytes: %i, byte pulses: %i\n", processed_bytes[drive], bpulses[drive]);
// pclog("Disk poll time is: %i\n", disc_poll_time);
fdc_finishread(drive);
}
break;
case STATE_READ_FIND_NEXT_SECTOR:
if (!fdd_can_read_medium(drive ^ fdd_swap))
{
pclog("Medium is of a density not supported by the drive\n");
fdc_notfound();
disc_sector_state[drive] = STATE_IDLE;
break;
}
if (index_count[drive] > 0)
{
pclog("Find next sector hit end of track\n");
fdc_notfound();
disc_sector_state[drive] = STATE_IDLE;
break;
}
if (cur_byte[drive] || (fdc_get_bitcell_period() != get_bitcell_period(drive)) ||
disc_intersector_delay[drive] || disc_track_delay[drive])
{
// pclog("Poll: Find sector advance byte!\n");
sector_type = advance_byte(drive);
do_period = 1;
break;
}
disc_sector_state[drive] = STATE_READ_NEXT_SECTOR;
case STATE_READ_NEXT_SECTOR:
if (fdc_data(s->data[cur_byte[drive]]))
break;
sector_type = advance_byte(drive);
do_period = 1;
if (!cur_byte[drive])
{
disc_sector_state[drive] = STATE_IDLE;
pclog("Processed bytes: %i, byte pulses: %i\n", processed_bytes[drive], bpulses[drive]);
// pclog("Disk poll time is: %i\n", disc_poll_time);
fdc_finishread(drive);
}
break;
case STATE_WRITE_FIND_SECTOR:
if (!fdd_can_read_medium(drive ^ fdd_swap))
{
// pclog("Medium is of a density not supported by the drive\n");
fdc_notfound();
disc_sector_state[drive] = STATE_IDLE;
break;
}
if (writeprot[drive] || swwp)
{
fdc_writeprotect();
return 0;
}
if (index_count[drive] > 1)
{
// pclog("Write find sector not found\n");
pclog("WRITE: Sector (%i %i %i %i) not found\n", s->c, s->h, s->r, s->n);
fdc_notfound();
disc_sector_state[drive] = STATE_IDLE;
break;
}
if (cur_byte[drive] || disc_sector_track[drive] != s->c ||
disc_sector_side[drive] != s->h ||
disc_sector_sector[drive] != s->r ||
disc_sector_n[drive] != s->n ||
(fdc_get_bitcell_period() != get_bitcell_period(drive)) ||
disc_intersector_delay[drive] || disc_track_delay[drive])
{
// pclog("Poll: Find sector advance byte!\n");
sector_type = advance_byte(drive);
do_period = 1;
break;
}
disc_sector_state[drive] = STATE_WRITE_SECTOR;
case STATE_WRITE_SECTOR:
data = fdc_getdata(cur_byte[drive] == ((128 << s->n) - 1));
if (data == -1)
break;
if (!disable_write) s->data[cur_byte[drive]] = data;
sector_type = advance_byte(drive);
do_period = 1;
if (!cur_byte[drive])
{
disc_sector_state[drive] = STATE_IDLE;
if (!disable_write) disc_sector_writeback[drive](drive, disc_sector_track[drive]);
pclog("Processed bytes: %i, byte pulses: %i\n", processed_bytes[drive], bpulses[drive]);
// pclog("Disk poll time is: %i\n", disc_poll_time);
fdc_finishread(drive);
}
break;
case STATE_READ_FIND_ADDRESS:
if (!fdd_can_read_medium(drive ^ fdd_swap))
{
pclog("Medium is of a density not supported by the drive\n");
fdc_notfound();
disc_sector_state[drive] = STATE_IDLE;
break;
}
if (index_count[drive] > 0)
{
pclog("Find next sector hit end of track\n");
fdc_notfound();
disc_sector_state[drive] = STATE_IDLE;
break;
}
if (cur_byte[drive] || (fdc_get_bitcell_period() != get_bitcell_period(drive)) ||
disc_intersector_delay[drive] || disc_track_delay[drive])
{
// pclog("Poll: Find sector advance byte!\n");
sector_type = advance_byte(drive);
do_period = 1;
break;
}
disc_sector_state[drive] = STATE_READ_ADDRESS;
case STATE_READ_ADDRESS:
fdc_sectorid(s->c, s->h, s->r, s->n, 0, 0);
disc_sector_state[drive] = STATE_IDLE;
break;
case STATE_FORMAT_FIND:
if (writeprot[drive] || swwp)
{
fdc_writeprotect();
return 0;
}
if (!index_count[drive] || (fdc_get_bitcell_period() != get_bitcell_period(drive)) ||
disc_intersector_delay[drive] || disc_track_delay[drive])
{
sector_type = advance_byte(drive);
do_period = 1;
break;
}
if (!(fdd_can_read_medium(drive ^ fdd_swap)))
{
pclog("Medium is of a density not supported by the drive\n");
fdc_notfound();
disc_sector_state[drive] = STATE_IDLE;
break;
}
if (fdc_get_bitcell_period() != get_bitcell_period(drive))
{
pclog("Bitcell period mismatch\n");
fdc_notfound();
disc_sector_state[drive] = STATE_IDLE;
break;
}
disc_sector_state[drive] = STATE_FORMAT;
case STATE_FORMAT:
if (!disc_intersector_delay[drive] && fdc_get_bitcell_period() == get_bitcell_period(drive) && !disable_write)
s->data[cur_byte[drive]] = disc_sector_fill[drive];
sector_type = advance_byte(drive);
do_period = 1;
if (index_count[drive] == 2)
{
if (!disable_write) disc_sector_writeback[drive](drive, disc_sector_track[drive]);
pclog("Processed bytes: %i, byte pulses: %i\n", processed_bytes[drive], bpulses[drive]);
// pclog("Disk poll time is: %i\n", disc_poll_time);
fdc_finishread(drive);
disc_sector_state[drive] = STATE_IDLE;
}
break;
}
// if (do_period) pclog("disc_sector_poll(%i) = %i\n", drive, sector_type);
do_period = do_period ? ((sector_type > 0) ? 2 : 1) : 0;
return do_period;
}

43
src/disc_sector.h Normal file
View File

@@ -0,0 +1,43 @@
void disc_sector_reset(int drive, int side);
void disc_sector_add(int drive, int side, uint8_t c, uint8_t h, uint8_t r, uint8_t n, int rate, uint8_t *data);
void disc_sector_readsector(int drive, int sector, int track, int side, int density, int sector_size);
void disc_sector_writesector(int drive, int sector, int track, int side, int density, int sector_size);
void disc_sector_readaddress(int drive, int sector, int side, int density);
void disc_sector_format(int drive, int sector, int side, int density, uint8_t fill);
void disc_sector_stop(int drive);
int disc_sector_poll(int drive);
void disc_sector_stop(int drive);
#define length_gap0 80
#define length_gap1 50
#define length_sync 12
#define length_am 4
#define length_crc 2
#define length_gap2 22
#define length_gap3 84 // 88
#define length_gap3_0 108
#define no_sectors 15 // 8
#define no_sectors_0 18
#define raw_track_size 10416 // 6250
#define raw_track_size_0 12500
#define IBM
#define MFM
#ifdef IBM
#define pre_gap1 length_gap0 + length_sync + length_am
#else
#define pre_gap1 0
#endif
#define pre_track pre_gap1 + length_gap1
#define pre_gap length_sync + length_am + 4 + length_crc // 22
#define pre_data length_sync + length_am // 16
#define data_size 512
#define post_gap length_crc
extern int raw_tsize[2];
extern int gap2_size[2];
extern int gap3_size[2];
extern int gap4_size[2];
extern void (*disc_sector_writeback[2])(int drive, int track);

389
src/dma.c Normal file
View File

@@ -0,0 +1,389 @@
#include "ibm.h"
#include "dma.h"
#include "fdc.h"
#include "io.h"
#include "mem.h"
#include "video.h"
static uint8_t dmaregs[16];
static int dmaon[4];
static uint8_t dma16regs[16];
static int dma16on[4];
static uint8_t dmapages[16];
void dma_reset()
{
int c;
dma.wp = 0;
for (c = 0; c < 16; c++)
dmaregs[c] = 0;
for (c = 0; c < 4; c++)
{
dma.mode[c] = 0;
dma.ac[c] = 0;
dma.cc[c] = 0;
dma.ab[c] = 0;
dma.cb[c] = 0;
}
dma.m = 0;
dma16.wp = 0;
for (c = 0; c < 16; c++)
dma16regs[c] = 0;
for (c = 0; c < 4; c++)
{
dma16.mode[c] = 0;
dma16.ac[c] = 0;
dma16.cc[c] = 0;
dma16.ab[c] = 0;
dma16.cb[c] = 0;
}
dma16.m = 0;
}
uint8_t dma_read(uint16_t addr, void *priv)
{
uint8_t temp;
// printf("Read DMA %04X %04X:%04X %i %02X\n",addr,CS,pc, pic_intpending, pic.pend);
switch (addr & 0xf)
{
case 0: case 2: case 4: case 6: /*Address registers*/
dma.wp ^= 1;
if (dma.wp)
return dma.ac[(addr >> 1) & 3] & 0xff;
return dma.ac[(addr >> 1) & 3] >> 8;
case 1: case 3: case 5: case 7: /*Count registers*/
dma.wp ^= 1;
if (dma.wp) temp = dma.cc[(addr >> 1) & 3] & 0xff;
else temp = dma.cc[(addr >> 1) & 3] >> 8;
return temp;
case 8: /*Status register*/
temp = dma.stat;
dma.stat = 0;
return temp;
case 0xd:
return 0;
}
// printf("Bad DMA read %04X %04X:%04X\n",addr,CS,pc);
return dmaregs[addr & 0xf];
}
void dma_write(uint16_t addr, uint8_t val, void *priv)
{
// printf("Write DMA %04X %02X %04X:%04X\n",addr,val,CS,pc);
dmaregs[addr & 0xf] = val;
switch (addr & 0xf)
{
case 0: case 2: case 4: case 6: /*Address registers*/
dma.wp ^= 1;
if (dma.wp) dma.ab[(addr >> 1) & 3] = (dma.ab[(addr >> 1) & 3] & 0xff00) | val;
else dma.ab[(addr >> 1) & 3] = (dma.ab[(addr >> 1) & 3] & 0x00ff) | (val << 8);
dma.ac[(addr >> 1) & 3] = dma.ab[(addr >> 1) & 3];
dmaon[(addr >> 1) & 3] = 1;
return;
case 1: case 3: case 5: case 7: /*Count registers*/
dma.wp ^= 1;
if (dma.wp) dma.cb[(addr >> 1) & 3] = (dma.cb[(addr >> 1) & 3] & 0xff00) | val;
else dma.cb[(addr >> 1) & 3] = (dma.cb[(addr >> 1) & 3] & 0x00ff) | (val << 8);
dma.cc[(addr >> 1) & 3] = dma.cb[(addr >> 1) & 3];
dmaon[(addr >> 1) & 3] = 1;
return;
case 8: /*Control register*/
dma.command = val;
return;
case 0xa: /*Mask*/
if (val & 4) dma.m |= (1 << (val & 3));
else dma.m &= ~(1 << (val & 3));
return;
case 0xb: /*Mode*/
dma.mode[val & 3] = val;
return;
case 0xc: /*Clear FF*/
dma.wp = 0;
return;
case 0xd: /*Master clear*/
dma.wp = 0;
dma.m = 0xf;
return;
case 0xf: /*Mask write*/
dma.m = val & 0xf;
return;
}
}
uint8_t dma16_read(uint16_t addr, void *priv)
{
uint8_t temp;
// printf("Read DMA %04X %04X:%04X\n",addr,cs>>4,pc);
addr >>= 1;
switch (addr & 0xf)
{
case 0: case 2: case 4: case 6: /*Address registers*/
dma16.wp ^= 1;
if (dma16.wp)
return dma16.ac[(addr >> 1) & 3] & 0xff;
return dma16.ac[(addr >> 1) & 3] >> 8;
case 1: case 3: case 5: case 7: /*Count registers*/
dma16.wp ^= 1;
if (dma16.wp) temp = dma16.cc[(addr >> 1) & 3] & 0xff;
else temp = dma16.cc[(addr >> 1) & 3] >> 8;
return temp;
case 8: /*Status register*/
temp = dma16.stat;
dma16.stat = 0;
return temp;
}
return dma16regs[addr & 0xf];
}
void dma16_write(uint16_t addr, uint8_t val, void *priv)
{
// printf("Write dma16 %04X %02X %04X:%04X\n",addr,val,CS,pc);
addr >>= 1;
dma16regs[addr & 0xf] = val;
switch (addr & 0xf)
{
case 0: case 2: case 4: case 6: /*Address registers*/
dma16.wp ^= 1;
if (dma16.wp) dma16.ab[(addr >> 1) & 3] = (dma16.ab[(addr >> 1) & 3] & 0xff00) | val;
else dma16.ab[(addr >> 1) & 3] = (dma16.ab[(addr >> 1) & 3] & 0x00ff) | (val << 8);
dma16.ac[(addr >> 1) & 3] = dma16.ab[(addr >> 1) & 3];
dma16on[(addr >> 1) & 3] = 1;
return;
case 1: case 3: case 5: case 7: /*Count registers*/
dma16.wp ^= 1;
if (dma16.wp) dma16.cb[(addr >> 1) & 3] = (dma16.cb[(addr >> 1) & 3] & 0xff00) | val;
else dma16.cb[(addr >> 1) & 3] = (dma16.cb[(addr >> 1) & 3] & 0x00ff) | (val << 8);
dma16.cc[(addr >> 1) & 3] = dma16.cb[(addr >> 1) & 3];
dma16on[(addr >> 1) & 3] = 1;
return;
case 8: /*Control register*/
return;
case 0xa: /*Mask*/
if (val & 4) dma16.m |= (1 << (val & 3));
else dma16.m &= ~(1 << (val & 3));
return;
case 0xb: /*Mode*/
dma16.mode[val & 3] = val;
return;
case 0xc: /*Clear FF*/
dma16.wp = 0;
return;
case 0xd: /*Master clear*/
dma16.wp = 0;
dma16.m = 0xf;
return;
case 0xf: /*Mask write*/
dma16.m = val&0xf;
return;
}
}
void dma_page_write(uint16_t addr, uint8_t val, void *priv)
{
dmapages[addr & 0xf] = val;
switch (addr & 0xf)
{
case 1:
dma.page[2] = (AT) ? val : val & 0xf;
break;
case 2:
dma.page[3] = (AT) ? val : val & 0xf;
break;
case 3:
dma.page[1] = (AT) ? val : val & 0xf;
break;
case 0xb:
dma16.page[1] = val;
break;
}
}
uint8_t dma_page_read(uint16_t addr, void *priv)
{
return dmapages[addr & 0xf];
}
void dma_init()
{
io_sethandler(0x0000, 0x0010, dma_read, NULL, NULL, dma_write, NULL, NULL, NULL);
io_sethandler(0x0080, 0x0008, dma_page_read, NULL, NULL, dma_page_write, NULL, NULL, NULL);
}
void dma16_init()
{
io_sethandler(0x00C0, 0x0020, dma16_read, NULL, NULL, dma16_write, NULL, NULL, NULL);
io_sethandler(0x0088, 0x0008, dma_page_read, NULL, NULL, dma_page_write, NULL, NULL, NULL);
}
uint8_t _dma_read(uint32_t addr)
{
return mem_readb_phys(addr);
}
void _dma_write(uint32_t addr, uint8_t val)
{
mem_writeb_phys(addr, val);
mem_invalidate_range(addr, addr);
}
int dma_channel_read(int channel)
{
uint16_t temp;
int tc = 0;
if (dma.command & 0x04)
return DMA_NODATA;
if (!AT)
refreshread();
if (channel < 4)
{
if (dma.m & (1 << channel))
return DMA_NODATA;
if ((dma.mode[channel] & 0xC) != 8)
return DMA_NODATA;
temp = _dma_read(dma.ac[channel] + (dma.page[channel] << 16)); //ram[(dma.ac[2]+(dma.page[2]<<16))&rammask];
if (dma.mode[channel] & 0x20) dma.ac[channel]--;
else dma.ac[channel]++;
dma.cc[channel]--;
if (dma.cc[channel] < 0)
{
tc = 1;
if (dma.mode[channel] & 0x10) /*Auto-init*/
{
dma.cc[channel] = dma.cb[channel];
dma.ac[channel] = dma.ab[channel];
}
else
dma.m |= (1 << channel);
dma.stat |= (1 << channel);
}
if (tc)
return temp | DMA_OVER;
return temp;
}
else
{
channel &= 3;
if (dma16.m & (1 << channel))
return DMA_NODATA;
if ((dma16.mode[channel] & 0xC) != 8)
return DMA_NODATA;
temp = _dma_read((dma16.ac[channel] << 1) + ((dma16.page[channel] & ~1) << 16)) |
(_dma_read((dma16.ac[channel] << 1) + ((dma16.page[channel] & ~1) << 16) + 1) << 8);
if (dma16.mode[channel] & 0x20) dma16.ac[channel]--;
else dma16.ac[channel]++;
dma16.cc[channel]--;
if (dma16.cc[channel] < 0)
{
tc = 1;
if (dma16.mode[channel] & 0x10) /*Auto-init*/
{
dma16.cc[channel] = dma16.cb[channel];
dma16.ac[channel] = dma16.ab[channel];
}
else
dma16.m |= (1 << channel);
dma16.stat |= (1 << channel);
}
if (tc)
return temp | DMA_OVER;
return temp;
}
}
int dma_channel_write(int channel, uint16_t val)
{
if (dma.command & 0x04)
return DMA_NODATA;
if (!AT)
refreshread();
if (channel < 4)
{
if (dma.m & (1 << channel))
return DMA_NODATA;
if ((dma.mode[channel] & 0xC) != 4)
return DMA_NODATA;
_dma_write(dma.ac[channel] + (dma.page[channel] << 16), val);
if (dma.mode[channel]&0x20) dma.ac[channel]--;
else dma.ac[channel]++;
dma.cc[channel]--;
if (dma.cc[channel] < 0)
{
if (dma.mode[channel] & 0x10) /*Auto-init*/
{
dma.cc[channel] = dma.cb[channel];
dma.ac[channel] = dma.ab[channel];
}
else
dma.m |= (1 << channel);
dma.stat |= (1 << channel);
}
if (dma.m & (1 << channel))
return DMA_OVER;
}
else
{
channel &= 3;
if (dma16.m & (1 << channel))
return DMA_NODATA;
if ((dma16.mode[channel] & 0xC) != 4)
return DMA_NODATA;
_dma_write((dma16.ac[channel] << 1) + ((dma16.page[channel] & ~1) << 16), val);
_dma_write((dma16.ac[channel] << 1) + ((dma16.page[channel] & ~1) << 16) + 1, val >> 8);
if (dma16.mode[channel]&0x20) dma16.ac[channel]--;
else dma16.ac[channel]++;
dma16.cc[channel]--;
if (dma16.cc[channel] < 0)
{
if (dma16.mode[channel] & 0x10) /*Auto-init*/
{
dma16.cc[channel] = dma16.cb[channel] + 1;
dma16.ac[channel] = dma16.ab[channel];
}
dma16.m |= (1 << channel);
dma16.stat |= (1 << channel);
}
if (dma.m & (1 << channel))
return DMA_OVER;
}
return 0;
}

16
src/dma.h Normal file
View File

@@ -0,0 +1,16 @@
void dma_init();
void dma16_init();
void dma_reset();
#define DMA_NODATA -1
#define DMA_OVER 0x10000
void readdma0();
int readdma1();
uint8_t readdma2();
int readdma3();
void writedma2(uint8_t temp);
int dma_channel_read(int channel);
int dma_channel_write(int channel, uint16_t val);

1521
src/dosbox/dbopl.cpp Normal file

File diff suppressed because it is too large Load Diff

273
src/dosbox/dbopl.h Normal file
View File

@@ -0,0 +1,273 @@
/*
* Copyright (C) 2002-2010 The DOSBox Team
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
//#include "adlib.h"
//#include "dosbox.h"
#include <stdint.h>
typedef signed int Bits;
typedef unsigned int Bitu;
typedef int8_t Bit8s;
typedef uint8_t Bit8u;
typedef int16_t Bit16s;
typedef uint16_t Bit16u;
typedef int32_t Bit32s;
typedef uint32_t Bit32u;
#define INLINE inline
#define GCC_UNLIKELY(x) (x)
//Use 8 handlers based on a small logatirmic wavetabe and an exponential table for volume
#define WAVE_HANDLER 10
//Use a logarithmic wavetable with an exponential table for volume
#define WAVE_TABLELOG 11
//Use a linear wavetable with a multiply table for volume
#define WAVE_TABLEMUL 12
//Select the type of wave generator routine
#define DBOPL_WAVE WAVE_TABLEMUL
namespace DBOPL {
struct Chip;
struct Operator;
struct Channel;
#if (DBOPL_WAVE == WAVE_HANDLER)
typedef Bits ( DB_FASTCALL *WaveHandler) ( Bitu i, Bitu volume );
#endif
typedef Bits ( DBOPL::Operator::*VolumeHandler) ( );
typedef Channel* ( DBOPL::Channel::*SynthHandler) ( Chip* chip, Bit32u samples, Bit32s* output );
//Different synth modes that can generate blocks of data
typedef enum {
sm2AM,
sm2FM,
sm3AM,
sm3FM,
sm4Start,
sm3FMFM,
sm3AMFM,
sm3FMAM,
sm3AMAM,
sm6Start,
sm2Percussion,
sm3Percussion,
} SynthMode;
//Shifts for the values contained in chandata variable
enum {
SHIFT_KSLBASE = 16,
SHIFT_KEYCODE = 24,
};
struct Operator {
public:
//Masks for operator 20 values
enum {
MASK_KSR = 0x10,
MASK_SUSTAIN = 0x20,
MASK_VIBRATO = 0x40,
MASK_TREMOLO = 0x80,
};
typedef enum {
OFF,
RELEASE,
SUSTAIN,
DECAY,
ATTACK,
} State;
VolumeHandler volHandler;
#if (DBOPL_WAVE == WAVE_HANDLER)
WaveHandler waveHandler; //Routine that generate a wave
#else
Bit16s* waveBase;
Bit32u waveMask;
Bit32u waveStart;
#endif
Bit32u waveIndex; //WAVE_BITS shifted counter of the frequency index
Bit32u waveAdd; //The base frequency without vibrato
Bit32u waveCurrent; //waveAdd + vibratao
Bit32u chanData; //Frequency/octave and derived data coming from whatever channel controls this
Bit32u freqMul; //Scale channel frequency with this, TODO maybe remove?
Bit32u vibrato; //Scaled up vibrato strength
Bit32s sustainLevel; //When stopping at sustain level stop here
Bit32s totalLevel; //totalLevel is added to every generated volume
Bit32u currentLevel; //totalLevel + tremolo
Bit32s volume; //The currently active volume
Bit32u attackAdd; //Timers for the different states of the envelope
Bit32u decayAdd;
Bit32u releaseAdd;
Bit32u rateIndex; //Current position of the evenlope
Bit8u rateZero; //Bits for the different states of the envelope having no changes
Bit8u keyOn; //Bitmask of different values that can generate keyon
//Registers, also used to check for changes
Bit8u reg20, reg40, reg60, reg80, regE0;
//Active part of the envelope we're in
Bit8u state;
//0xff when tremolo is enabled
Bit8u tremoloMask;
//Strength of the vibrato
Bit8u vibStrength;
//Keep track of the calculated KSR so we can check for changes
Bit8u ksr;
private:
void SetState( Bit8u s );
void UpdateAttack( const Chip* chip );
void UpdateRelease( const Chip* chip );
void UpdateDecay( const Chip* chip );
public:
void UpdateAttenuation();
void UpdateRates( const Chip* chip );
void UpdateFrequency( );
void Write20( const Chip* chip, Bit8u val );
void Write40( const Chip* chip, Bit8u val );
void Write60( const Chip* chip, Bit8u val );
void Write80( const Chip* chip, Bit8u val );
void WriteE0( const Chip* chip, Bit8u val );
bool Silent() const;
void Prepare( const Chip* chip );
void KeyOn( Bit8u mask);
void KeyOff( Bit8u mask);
template< State state>
Bits TemplateVolume( );
Bit32s RateForward( Bit32u add );
Bitu ForwardWave();
Bitu ForwardVolume();
Bits GetSample( Bits modulation );
Bits GetWave( Bitu index, Bitu vol );
public:
Operator();
};
struct Channel {
Operator op[2];
inline Operator* Op( Bitu index ) {
return &( ( this + (index >> 1) )->op[ index & 1 ]);
}
SynthHandler synthHandler;
Bit32u chanData; //Frequency/octave and derived values
Bit32s old[2]; //Old data for feedback
Bit8u feedback; //Feedback shift
Bit8u regB0; //Register values to check for changes
Bit8u regC0;
//This should correspond with reg104, bit 6 indicates a Percussion channel, bit 7 indicates a silent channel
Bit8u fourMask;
Bit8s maskLeft; //Sign extended values for both channel's panning
Bit8s maskRight;
//Forward the channel data to the operators of the channel
void SetChanData( const Chip* chip, Bit32u data );
//Change in the chandata, check for new values and if we have to forward to operators
void UpdateFrequency( const Chip* chip, Bit8u fourOp );
void WriteA0( const Chip* chip, Bit8u val );
void WriteB0( const Chip* chip, Bit8u val );
void WriteC0( const Chip* chip, Bit8u val );
void ResetC0( const Chip* chip );
//call this for the first channel
template< bool opl3Mode >
void GeneratePercussion( Chip* chip, Bit32s* output );
//Generate blocks of data in specific modes
template<SynthMode mode>
Channel* BlockTemplate( Chip* chip, Bit32u samples, Bit32s* output );
Channel();
};
struct Chip {
//This is used as the base counter for vibrato and tremolo
Bit32u lfoCounter;
Bit32u lfoAdd;
Bit32u noiseCounter;
Bit32u noiseAdd;
Bit32u noiseValue;
//Frequency scales for the different multiplications
Bit32u freqMul[16];
//Rates for decay and release for rate of this chip
Bit32u linearRates[76];
//Best match attack rates for the rate of this chip
Bit32u attackRates[76];
//18 channels with 2 operators each
Channel chan[18];
Bit8u reg104;
Bit8u reg08;
Bit8u reg04;
Bit8u regBD;
Bit8u vibratoIndex;
Bit8u tremoloIndex;
Bit8s vibratoSign;
Bit8u vibratoShift;
Bit8u tremoloValue;
Bit8u vibratoStrength;
Bit8u tremoloStrength;
//Mask for allowed wave forms
Bit8u waveFormMask;
//0 or -1 when enabled
Bit8s opl3Active;
int is_opl3;
//Return the maximum amount of samples before and LFO change
Bit32u ForwardLFO( Bit32u samples );
Bit32u ForwardNoise();
void WriteBD( Bit8u val );
void WriteReg(Bit32u reg, Bit8u val );
Bit32u WriteAddr( Bit32u port, Bit8u val );
void GenerateBlock2( Bitu samples, Bit32s* output );
void GenerateBlock3( Bitu samples, Bit32s* output );
void Generate( Bit32u samples );
void Setup( Bit32u r, int chip_is_opl3 );
Chip();
};
/*struct Handler : public Adlib::Handler {
DBOPL::Chip chip;
virtual Bit32u WriteAddr( Bit32u port, Bit8u val );
virtual void WriteReg( Bit32u addr, Bit8u val );
virtual void Generate( MixerChannel* chan, Bitu samples );
virtual void Init( Bitu rate );
};*/
void InitTables( void );
}; //Namespace

1668
src/fdc.c Normal file

File diff suppressed because it is too large Load Diff

27
src/fdc.h Normal file
View File

@@ -0,0 +1,27 @@
void fdc_init();
void fdc_add();
void fdc_add_for_superio();
void fdc_add_pcjr();
void fdc_add_tandy();
void fdc_remove();
void fdc_reset();
void fdc_poll();
void fdc_abort();
void fdc_discchange_clear(int drive);
void fdc_set_dskchg_activelow();
void fdc_3f1_enable(int enable);
void fdc_set_ps1();
int fdc_get_bitcell_period();
/* A few functions to communicate between Super I/O chips and the FDC. */
void fdc_update_is_nsc(int is_nsc);
void fdc_update_enh_mode(int enh_mode);
int fdc_get_rwc(int drive);
void fdc_update_rwc(int drive, int rwc);
int fdc_get_boot_drive();
void fdc_update_boot_drive(int boot_drive);
void fdc_update_densel_polarity(int densel_polarity);
void fdc_update_densel_force(int densel_force);
void fdc_update_drvrate(int drive, int drvrate);
void fdc_update_drv2en(int drv2en);
int fdc_skip_pulses(int drive);

165
src/fdc37c665.c Normal file
View File

@@ -0,0 +1,165 @@
#include "ibm.h"
#include "fdc.h"
#include "fdd.h"
#include "io.h"
#include "lpt.h"
#include "serial.h"
#include "fdc37c665.h"
static uint8_t fdc37c665_lock[2];
static int fdc37c665_curreg;
static uint8_t fdc37c665_regs[16];
static void write_lock(uint8_t val)
{
if (val == 0x55 && fdc37c665_lock[1] == 0x55)
fdc_3f1_enable(0);
if (fdc37c665_lock[0] == 0x55 && fdc37c665_lock[1] == 0x55 && val != 0x55)
fdc_3f1_enable(1);
fdc37c665_lock[0] = fdc37c665_lock[1];
fdc37c665_lock[1] = val;
}
void fdc37c665_write(uint16_t port, uint8_t val, void *priv)
{
// pclog("Write SuperIO %04x %02x\n", port, val);
if (fdc37c665_lock[0] == 0x55 && fdc37c665_lock[1] == 0x55)
{
if (port == 0x3f0)
{
if (val == 0xaa)
write_lock(val);
else
fdc37c665_curreg = val & 0xf;
}
else
{
uint16_t com3_addr, com4_addr;
fdc37c665_regs[fdc37c665_curreg] = val;
// pclog("Write superIO %02x %02x %04x(%08x):%08x\n", fdc37c665_curreg, val, CS, cs, pc);
switch (fdc37c665_regs[1] & 0x60)
{
case 0x00:
com3_addr = 0x338;
com4_addr = 0x238;
break;
case 0x20:
com3_addr = 0x3e8;
com4_addr = 0x2e8;
break;
case 0x40:
com3_addr = 0x3e8;
com4_addr = 0x2e0;
break;
case 0x60:
com3_addr = 0x220;
com4_addr = 0x228;
break;
}
if (!(fdc37c665_regs[2] & 4))
serial1_remove();
else switch (fdc37c665_regs[2] & 3)
{
case 0:
serial1_set(0x3f8, 4);
break;
case 1:
serial1_set(0x2f8, 4);
break;
case 2:
serial1_set(com3_addr, 4);
break;
case 3:
serial1_set(com4_addr, 4);
break;
}
if (!(fdc37c665_regs[2] & 0x40))
serial2_remove();
else switch (fdc37c665_regs[2] & 0x30)
{
case 0x00:
serial2_set(0x3f8, 3);
break;
case 0x10:
serial2_set(0x2f8, 3);
break;
case 0x20:
serial2_set(com3_addr, 3);
break;
case 0x30:
serial2_set(com4_addr, 3);
break;
}
lpt1_remove();
lpt2_remove();
switch (fdc37c665_regs[1] & 3)
{
case 1:
lpt1_init(0x3bc);
break;
case 2:
lpt1_init(0x378);
break;
case 3:
lpt1_init(0x278);
break;
}
fdc_update_enh_mode((fdc37c665_regs[3] & 2) ? 1 : 0);
fdc_update_densel_force((fdc37c665_regs[5] & 0x18) >> 3);
fdd_swap = ((fdc37c665_regs[5] & 0x20) >> 5);
}
}
else
{
if (port == 0x3f0)
write_lock(val);
}
}
uint8_t fdc37c665_read(uint16_t port, void *priv)
{
// pclog("Read SuperIO %04x %02x\n", port, fdc37c665_curreg);
if (fdc37c665_lock[0] == 0x55 && fdc37c665_lock[1] == 0x55)
{
if (port == 0x3f1)
return fdc37c665_regs[fdc37c665_curreg];
}
return 0xff;
}
void fdc37c665_init()
{
io_sethandler(0x03f0, 0x0002, fdc37c665_read, NULL, NULL, fdc37c665_write, NULL, NULL, NULL);
fdc_update_is_nsc(0);
fdc37c665_lock[0] = fdc37c665_lock[1] = 0;
fdc37c665_regs[0x0] = 0x3b;
fdc37c665_regs[0x1] = 0x9f;
fdc37c665_regs[0x2] = 0xdc;
fdc37c665_regs[0x3] = 0x78;
fdc37c665_regs[0x4] = 0x00;
fdc37c665_regs[0x5] = 0x00;
fdc37c665_regs[0x6] = 0xff;
fdc37c665_regs[0x7] = 0x00;
fdc37c665_regs[0x8] = 0x00;
fdc37c665_regs[0x9] = 0x00;
fdc37c665_regs[0xa] = 0x00;
fdc37c665_regs[0xb] = 0x00;
fdc37c665_regs[0xc] = 0x00;
fdc37c665_regs[0xd] = 0x65;
fdc37c665_regs[0xe] = 0x01;
fdc37c665_regs[0xf] = 0x00;
fdc_update_densel_polarity(1);
fdc_update_densel_force(0);
fdd_swap = 0;
}

1
src/fdc37c665.h Normal file
View File

@@ -0,0 +1 @@
extern void fdc37c665_init();

478
src/fdc37c932fr.c Normal file
View File

@@ -0,0 +1,478 @@
/*
SMSC SMC fdc37c932fr Super I/O Chip
Used by all some Acer boards, and by the Epox P55-VA
*/
#include "ibm.h"
#include "fdc.h"
#include "fdd.h"
#include "ide.h"
#include "io.h"
#include "lpt.h"
#include "mouse_serial.h"
#include "serial.h"
#include "fdc37c932fr.h"
static int fdc37c932fr_locked;
static int fdc37c932fr_curreg = 0;
static int fdc37c932fr_gpio_curreg = 0;
static uint8_t fdc37c932fr_regs[48];
static uint8_t fdc37c932fr_ld_regs[10][256];
static uint8_t fdc37c932fr_gpio_regs[16] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
static uint8_t tries;
static uint16_t ld0_valid_ports[2] = {0x3F0, 0x370};
static uint16_t ld1_valid_ports[2] = {0x1F0, 0x170};
static uint16_t ld1_valid_ports2[2] = {0x3F6, 0x376};
static uint16_t ld2_valid_ports[2] = {0x170, 0x1F0};
static uint16_t ld2_valid_ports2[2] = {0x376, 0x3F6};
static uint16_t ld3_valid_ports[3] = {0x3BC, 0x378, 0x278};
static uint16_t ld4_valid_ports[9] = {0x3F8, 0x2F8, 0x338, 0x3E8, 0x2E8, 0x220, 0x238, 0x2E0, 0x228};
static uint16_t ld5_valid_ports[9] = {0x3F8, 0x2F8, 0x338, 0x3E8, 0x2E8, 0x220, 0x238, 0x2E0, 0x228};
static uint16_t ld5_valid_ports2[9] = {0x3F8, 0x2F8, 0x338, 0x3E8, 0x2E8, 0x220, 0x238, 0x2E0, 0x228};
static uint8_t is_in_array(uint16_t *port_array, uint8_t max, uint16_t port)
{
uint8_t i = 0;
for (i = 0; i < max; i++)
{
if (port_array[i] == port) return 1;
}
return 0;
}
static uint16_t make_port(uint8_t ld)
{
uint16_t r0 = fdc37c932fr_ld_regs[ld][0x60];
uint16_t r1 = fdc37c932fr_ld_regs[ld][0x61];
uint16_t p = (r0 << 8) + r1;
switch(ld)
{
case 0:
p &= 0xFF8;
if ((p < 0x100) || (p > 0xFF8)) p = 0x3F0;
if (!(is_in_array(ld0_valid_ports, 2, p))) p = 0x3F0;
break;
case 1:
p &= 0xFF8;
if ((p < 0x100) || (p > 0xFF8)) p = 0x1F0;
if (!(is_in_array(ld1_valid_ports, 2, p))) p = 0x1F0;
break;
case 2:
p &= 0xFF8;
if ((p < 0x100) || (p > 0xFF8)) p = 0x170;
if (!(is_in_array(ld2_valid_ports, 2, p))) p = 0x170;
break;
case 3:
p &= 0xFF8;
if ((p < 0x100) || (p > 0xFF8)) p = 0x378;
if (!(is_in_array(ld3_valid_ports, 3, p))) p = 0x378;
break;
case 4:
p &= 0xFF8;
if ((p < 0x100) || (p > 0xFF8)) p = 0x3F8;
if (!(is_in_array(ld4_valid_ports, 9, p))) p = 0x3F8;
break;
case 5:
p &= 0xFF8;
if ((p < 0x100) || (p > 0xFF8)) p = 0x2F8;
if (!(is_in_array(ld5_valid_ports, 9, p))) p = 0x2F8;
break;
}
fdc37c932fr_ld_regs[ld][0x60] = (p >> 8);
fdc37c932fr_ld_regs[ld][0x61] = (p & 0xFF);
return p;
}
uint16_t make_port2(uint8_t ld)
{
uint16_t r0 = fdc37c932fr_ld_regs[ld][0x62];
uint16_t r1 = fdc37c932fr_ld_regs[ld][0x63];
uint16_t p = (r0 << 8) + r1;
switch(ld)
{
case 1:
p &= 0xFFF;
if ((p < 0x100) || (p > 0xFF8)) p = 0x3F6;
if (!(is_in_array(ld1_valid_ports2, 2, p))) p = 0x3F6;
break;
case 2:
p &= 0xFFF;
if ((p < 0x100) || (p > 0xFF8)) p = 0x376;
if (!(is_in_array(ld2_valid_ports2, 2, p))) p = 0x376;
break;
case 5:
p &= 0xFF8;
if ((p < 0x100) || (p > 0xFF8)) p = 0x3E8;
if (!(is_in_array(ld5_valid_ports2, 9, p))) p = 0x3E8;
break;
}
fdc37c932fr_ld_regs[ld][0x62] = (p >> 8);
fdc37c932fr_ld_regs[ld][0x63] = (p & 0xFF);
return p;
}
void fdc37c932fr_gpio_write(uint16_t port, uint8_t val, void *priv)
{
if (port & 1)
{
if (fdc37c932fr_gpio_curreg && (fdc37c932fr_gpio_curreg <= 0xF))
fdc37c932fr_gpio_regs[fdc37c932fr_gpio_curreg] = val;
}
else
{
fdc37c932fr_gpio_curreg = val;
}
}
void fdc37c932fr_write(uint16_t port, uint8_t val, void *priv)
{
uint8_t index = (port & 1) ? 0 : 1;
uint8_t valxor = 0;
uint16_t ld_port = 0;
uint16_t ld_port2 = 0;
int temp;
// pclog("fdc37c932fr_write : port=%04x reg %02X = %02X locked=%i\n", port, fdc37c932fr_curreg, val, fdc37c932fr_locked);
if (index)
{
if ((val == 0x55) && !fdc37c932fr_locked)
{
if (tries)
{
fdc37c932fr_locked = 1;
fdc_3f1_enable(0);
tries = 0;
}
else
{
tries++;
}
}
else
{
if (fdc37c932fr_locked)
{
if (val == 0xaa)
{
fdc37c932fr_locked = 0;
fdc_3f1_enable(1);
return;
}
fdc37c932fr_curreg = val;
}
else
{
if (tries)
tries = 0;
}
}
}
else
{
if (fdc37c932fr_locked)
{
if (fdc37c932fr_curreg < 48)
{
valxor = val ^ fdc37c932fr_regs[fdc37c932fr_curreg];
fdc37c932fr_regs[fdc37c932fr_curreg] = val;
}
else
{
valxor = val ^ fdc37c932fr_ld_regs[fdc37c932fr_regs[7]][fdc37c932fr_curreg];
if ((fdc37c932fr_curreg & 0xF0 == 0x70) && (fdc37c932fr_regs[7] < 4)) return;
/* Block writes to IDE configuration. */
if (fdc37c932fr_regs[7] == 1) return;
if (fdc37c932fr_regs[7] == 2) return;
if (fdc37c932fr_regs[7] > 5) return;
fdc37c932fr_ld_regs[fdc37c932fr_regs[7]][fdc37c932fr_curreg] = val;
goto process_value;
}
}
}
return;
process_value:
switch(fdc37c932fr_regs[7])
{
case 0:
/* FDD */
switch(fdc37c932fr_curreg)
{
case 0x30:
/* Activate */
if (valxor)
{
if (!val)
fdc_remove();
else
{
fdc_add();
}
}
break;
case 0x60:
case 0x61:
if (valxor && fdc37c932fr_ld_regs[0][0x30])
{
fdc_remove();
ld_port = make_port(0);
fdc37c932fr_ld_regs[0][0x60] = make_port(0) >> 8;
fdc37c932fr_ld_regs[0][0x61] = make_port(0) & 0xFF;
fdc_add();
}
break;
case 0xF0:
if (valxor & 0x01) fdc_update_enh_mode(val & 0x01);
if (valxor & 0x10) fdd_swap = ((val & 0x10) >> 4);
break;
case 0xF1:
if (valxor & 0xC) fdc_update_densel_force((val & 0xC) >> 2);
break;
case 0xF2:
if (valxor & 0x0C) fdc_update_rwc(1, (valxor & 0x0C) >> 2);
if (valxor & 0x03) fdc_update_rwc(0, (valxor & 0x03));
break;
case 0xF4:
if (valxor & 0x18) fdc_update_drvrate(0, (val & 0x18) >> 3);
break;
case 0xF5:
if (valxor & 0x18) fdc_update_drvrate(1, (val & 0x18) >> 3);
break;
}
break;
case 3:
/* Parallel port */
switch(fdc37c932fr_curreg)
{
case 0x30:
/* Activate */
if (valxor)
{
if (!val)
lpt1_remove();
else
{
ld_port = make_port(3);
lpt1_init(ld_port);
}
}
break;
case 0x60:
case 0x61:
if (valxor && fdc37c932fr_ld_regs[3][0x30])
{
lpt1_remove();
ld_port = make_port(3);
lpt1_init(ld_port);
}
break;
}
break;
case 4:
/* Serial port 1 */
switch(fdc37c932fr_curreg)
{
case 0x30:
/* Activate */
if (valxor)
{
if (!val)
serial1_remove();
else
{
ld_port = make_port(4);
serial1_set(ld_port, fdc37c932fr_ld_regs[4][0x70]);
mouse_serial_init();
}
}
break;
case 0x60:
case 0x61:
case 0x70:
if (valxor && fdc37c932fr_ld_regs[4][0x30])
{
ld_port = make_port(4);
serial1_set(ld_port, fdc37c932fr_ld_regs[4][0x70]);
mouse_serial_init();
}
break;
}
break;
case 5:
/* Serial port 2 */
switch(fdc37c932fr_curreg)
{
case 0x30:
/* Activate */
if (valxor)
{
if (!val)
serial2_remove();
else
{
ld_port = make_port(5);
serial2_set(ld_port, fdc37c932fr_ld_regs[5][0x70]);
}
}
break;
case 0x60:
case 0x61:
case 0x70:
if (valxor && fdc37c932fr_ld_regs[5][0x30])
{
ld_port = make_port(5);
serial2_set(ld_port, fdc37c932fr_ld_regs[5][0x70]);
}
break;
}
break;
}
}
uint8_t fdc37c932fr_gpio_read(uint16_t port, void *priv)
{
if (port & 1)
{
if (fdc37c932fr_gpio_curreg && (fdc37c932fr_gpio_curreg <= 0xF))
return fdc37c932fr_gpio_regs[fdc37c932fr_gpio_curreg];
else
return 0xff;
}
else
{
return fdc37c932fr_gpio_curreg;
}
}
uint8_t fdc37c932fr_read(uint16_t port, void *priv)
{
// pclog("fdc37c932fr_read : port=%04x reg %02X locked=%i\n", port, fdc37c932fr_curreg, fdc37c932fr_locked);
uint8_t index = (port & 1) ? 0 : 1;
if (!fdc37c932fr_locked)
{
return 0xff;
}
if (index)
return fdc37c932fr_curreg;
else
{
if (fdc37c932fr_curreg < 0x30)
{
// pclog("0x03F1: %02X\n", fdc37c932fr_regs[fdc37c932fr_curreg]);
return fdc37c932fr_regs[fdc37c932fr_curreg];
}
else
{
// pclog("0x03F1 (CD=%02X): %02X\n", fdc37c932fr_regs[7], fdc37c932fr_ld_regs[fdc37c932fr_regs[7]][fdc37c932fr_curreg]);
if ((fdc37c932fr_regs[7] == 0) && (fdc37c932fr_curreg == 0xF2)) return (fdc_get_rwc(0) | (fdc_get_rwc(1) << 2));
return fdc37c932fr_ld_regs[fdc37c932fr_regs[7]][fdc37c932fr_curreg];
}
}
}
void fdc37c932fr_init()
{
int i = 0;
lpt2_remove();
fdc37c932fr_regs[3] = 3;
fdc37c932fr_regs[0x20] = 3;
fdc37c932fr_regs[0x21] = 1;
fdc37c932fr_regs[0x24] = 4;
fdc37c932fr_regs[0x26] = 0xF0;
fdc37c932fr_regs[0x27] = 3;
for (i = 0; i < 10; i++)
{
memset(fdc37c932fr_ld_regs[i], 0, 256);
}
/* Logical device 0: FDD */
fdc37c932fr_ld_regs[0][0x30] = 1;
fdc37c932fr_ld_regs[0][0x60] = 3;
fdc37c932fr_ld_regs[0][0x61] = 0xF0;
fdc37c932fr_ld_regs[0][0x70] = 6;
fdc37c932fr_ld_regs[0][0x74] = 2;
fdc37c932fr_ld_regs[0][0xF0] = 0xE;
fdc37c932fr_ld_regs[0][0xF2] = 0xFF;
/* Logical device 1: IDE1 */
fdc37c932fr_ld_regs[1][0x30] = 1;
fdc37c932fr_ld_regs[1][0x60] = 1;
fdc37c932fr_ld_regs[1][0x61] = 0xF0;
fdc37c932fr_ld_regs[1][0x62] = 3;
fdc37c932fr_ld_regs[1][0x63] = 0xF6;
fdc37c932fr_ld_regs[1][0x70] = 0xE;
fdc37c932fr_ld_regs[1][0xF0] = 0xC;
/* Logical device 2: IDE2 */
fdc37c932fr_ld_regs[2][0x30] = 1;
fdc37c932fr_ld_regs[2][0x60] = 1;
fdc37c932fr_ld_regs[2][0x61] = 0x70;
fdc37c932fr_ld_regs[2][0x62] = 3;
fdc37c932fr_ld_regs[2][0x63] = 0x76;
fdc37c932fr_ld_regs[2][0x70] = 0xF;
/* Logical device 3: Parallel Port */
fdc37c932fr_ld_regs[3][0x30] = 1;
fdc37c932fr_ld_regs[3][0x60] = 3;
fdc37c932fr_ld_regs[3][0x61] = 0x78;
fdc37c932fr_ld_regs[3][0x70] = 7;
fdc37c932fr_ld_regs[3][0x74] = 4;
fdc37c932fr_ld_regs[3][0xF0] = 0x3C;
/* Logical device 4: Serial Port 1 */
fdc37c932fr_ld_regs[4][0x30] = 1;
fdc37c932fr_ld_regs[4][0x60] = 3;
fdc37c932fr_ld_regs[4][0x61] = 0xf8;
fdc37c932fr_ld_regs[4][0x70] = 4;
fdc37c932fr_ld_regs[4][0xF0] = 3;
/* Logical device 5: Serial Port 2 */
fdc37c932fr_ld_regs[5][0x30] = 1;
fdc37c932fr_ld_regs[5][0x60] = 2;
fdc37c932fr_ld_regs[5][0x61] = 0xf8;
fdc37c932fr_ld_regs[5][0x70] = 3;
fdc37c932fr_ld_regs[5][0x74] = 4;
fdc37c932fr_ld_regs[5][0xF1] = 2;
fdc37c932fr_ld_regs[5][0xF2] = 3;
/* Logical device 6: RTC */
fdc37c932fr_ld_regs[6][0x63] = 0x70;
fdc37c932fr_ld_regs[6][0xF4] = 3;
/* Logical device 7: Keyboard */
fdc37c932fr_ld_regs[7][0x30] = 1;
fdc37c932fr_ld_regs[7][0x61] = 0x60;
fdc37c932fr_ld_regs[7][0x70] = 1;
/* Logical device 8: AUX I/O */
/* Logical device 9: ACCESS.bus */
fdc_update_densel_force(0);
fdd_swap = 0;
fdc_update_rwc(0, 0);
fdc_update_rwc(1, 0);
fdc_update_drvrate(0, 0);
fdc_update_drvrate(1, 0);
io_sethandler(0xe0, 0x0006, fdc37c932fr_gpio_read, NULL, NULL, fdc37c932fr_gpio_write, NULL, NULL, NULL);
io_sethandler(0xea, 0x0002, fdc37c932fr_gpio_read, NULL, NULL, fdc37c932fr_gpio_write, NULL, NULL, NULL);
io_sethandler(0x3f0, 0x0002, fdc37c932fr_read, NULL, NULL, fdc37c932fr_write, NULL, NULL, NULL);
fdc37c932fr_locked = 0;
}

1
src/fdc37c932fr.h Normal file
View File

@@ -0,0 +1 @@
extern void fdc37c932fr_init();

325
src/fdd.c Normal file
View File

@@ -0,0 +1,325 @@
#include "ibm.h"
#include "disc.h"
#include "fdc.h"
#include "fdd.h"
#include "timer.h"
static struct
{
int type;
int track;
int densel;
int drate;
int kbps;
int fdc_kbps;
int head;
} fdd[2];
/* Flags:
Bit 0: 300 rpm supported;
Bit 1: 360 rpm supported;
Bit 2: size (0 = 3.5", 1 = 5.25");
Bit 3: double density supported;
Bit 4: high density supported;
Bit 5: extended density supported;
Bit 6: double step for 40-track media;
*/
#define FLAG_RPM_300 1
#define FLAG_RPM_360 2
#define FLAG_525 4
#define FLAG_HOLE0 8
#define FLAG_HOLE1 16
#define FLAG_HOLE2 32
#define FLAG_DOUBLE_STEP 64
static struct
{
int max_track;
int flags;
} drive_types[] =
{
{ /*None*/
.max_track = 0,
.flags = 0
},
{ /*5.25" DD*/
#ifdef MAINLINE
.max_track = 41,
#else
.max_track = 43,
#endif
.flags = FLAG_RPM_300 | FLAG_525 | FLAG_HOLE0
},
{ /*5.25" HD*/
#ifdef MAINLINE
.max_track = 82,
#else
.max_track = 86,
#endif
.flags = FLAG_RPM_360 | FLAG_525 | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_DOUBLE_STEP
},
{ /*5.25" HD Dual RPM*/
#ifdef MAINLINE
.max_track = 82,
#else
.max_track = 86,
#endif
.flags = FLAG_RPM_300 | FLAG_RPM_360 | FLAG_525 | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_DOUBLE_STEP
},
{ /*3.5" DD*/
#ifdef MAINLINE
.max_track = 82,
#else
.max_track = 86,
#endif
.flags = FLAG_RPM_300 | FLAG_HOLE0
},
{ /*3.5" HD*/
#ifdef MAINLINE
.max_track = 82,
#else
.max_track = 86,
#endif
.flags = FLAG_RPM_300 | FLAG_HOLE0 | FLAG_HOLE1
},
{ /*3.5" HD 3-Mode*/
#ifdef MAINLINE
.max_track = 82,
#else
.max_track = 86,
#endif
.flags = FLAG_RPM_300 | FLAG_RPM_360 | FLAG_HOLE0 | FLAG_HOLE1
},
{ /*3.5" ED*/
#ifdef MAINLINE
.max_track = 82,
#else
.max_track = 86,
#endif
.flags = FLAG_RPM_300 | FLAG_HOLE0 | FLAG_HOLE1 | FLAG_HOLE2
}
};
int fdd_swap = 0;
int fdd_stepping_motor_on[2] = {0, 0};
int fdd_track_diff[2] = {0, 0};
int fdd_track_direction[2] = {0, 0};
int fdd_old_track[2] = {0, 0};
int fdd_poll_time[2] = {0, 0};
void fdd_seek_poll(int poll_drive)
{
if (!fdd_track_diff[poll_drive])
{
fdd_stepping_motor_on[poll_drive] = 0;
return;
}
/* 80-track drive takes 6 µs per step, 40-track drive takes 10 µs. */
// fdd_poll_time[poll_drive] += (drive_types[fdd[poll_drive].type].max_track <= 43) ? (10 * TIMER_USEC) : (6 * TIMER_USEC);
fdd_poll_time[poll_drive] += (drive_types[fdd[poll_drive].type].max_track <= 43) ? (5 * TIMER_USEC) : (3 * TIMER_USEC);
if (fdd_track_direction[poll_drive])
{
fdd[poll_drive].track++;
if (fdd[poll_drive].track > drive_types[fdd[poll_drive].type].max_track)
fdd[poll_drive].track = drive_types[fdd[poll_drive].type].max_track;
}
else
{
fdd[poll_drive].track--;
if (fdd[poll_drive].track < 0)
fdd[poll_drive].track = 0;
}
fdd_track_diff[poll_drive]--;
if (!fdd_track_diff[poll_drive])
{
fdc_discchange_clear(poll_drive);
disc_seek(poll_drive, fdd[poll_drive].track);
fdd_stepping_motor_on[poll_drive] = 0;
}
}
void fdd_seek_poll_0()
{
fdd_seek_poll(0);
}
void fdd_seek_poll_1()
{
fdd_seek_poll(1);
}
#if 0
void fdd_seek(int drive, int track_diff)
{
drive ^= fdd_swap;
fdd_old_track[drive] = fdd[drive].track;
if (!track_diff)
{
/* Do not turn on motor if there are no pulses to be sent. */
fdc_discchange_clear(drive);
return;
}
fdd_stepping_motor_on[drive] = (track_diff == 0) ? 0 : 1;
if (fdd_stepping_motor_on[drive]) pclog("fdd_seek(): Stepping motor now on\n");
if (track_diff < 0)
{
fdd_track_diff[drive] = -track_diff;
fdd_track_direction[drive] = 0;
}
else
{
fdd_track_diff[drive] = track_diff;
fdd_track_direction[drive] = 1;
}
fdd_old_track[drive] = fdd[drive].track;
}
#endif
void fdd_seek(int drive, int track_diff)
{
int old_track;
drive ^= fdd_swap;
old_track = fdd[drive].track;
fdd[drive].track += track_diff;
if (fdd[drive].track < 0)
fdd[drive].track = 0;
if (fdd[drive].track > drive_types[fdd[drive].type].max_track)
fdd[drive].track = drive_types[fdd[drive].type].max_track;
// pclog("fdd_seek: drive=%i track_diff=%i old_track=%i track=%i\n", drive, track_diff, old_track, fdd[drive].track);
// if (fdd[drive].track != old_track)
// fdc_discchange_clear(drive);
fdc_discchange_clear(drive);
disc_seek(drive, fdd[drive].track);
// disctime = 5000;
disctime = 50;
}
int fdd_track0(int drive)
{
drive ^= fdd_swap;
/* If drive is disabled, TRK0 never gets set. */
if (!drive_types[fdd[drive].type].max_track) return 0;
return !fdd[drive].track;
}
void fdd_set_densel(int densel)
{
fdd[0].densel = densel;
fdd[1].densel = densel;
}
int fdd_getrpm(int drive)
{
int hole = disc_hole(drive);
drive ^= fdd_swap;
if (!(drive_types[fdd[drive].type].flags & FLAG_RPM_360)) return 300;
if (!(drive_types[fdd[drive].type].flags & FLAG_RPM_300)) return 360;
if (drive_types[fdd[drive].type].flags & FLAG_525)
{
return fdd[drive].densel ? 360 : 300;
}
else
{
/* disc_hole(drive) returns 0 for double density media, 1 for high density, and 2 for extended density. */
if (hole == 1)
{
return fdd[drive].densel ? 300 : 360;
}
else
{
return 300;
}
}
}
void fdd_setswap(int swap)
{
fdd_swap = swap ? 1 : 0;
}
int fdd_can_read_medium(int drive)
{
int hole = disc_hole(drive);
drive ^= fdd_swap;
hole = 1 << (hole + 3);
// pclog("Drive %02X, type %02X, hole flag %02X, flags %02X, result %02X\n", drive, fdd[drive].type, hole, drive_types[fdd[drive].type].flags, drive_types[fdd[drive].type].flags & hole);
return (drive_types[fdd[drive].type].flags & hole) ? 1 : 0;
}
int fdd_doublestep_40(int drive)
{
return drive_types[fdd[drive].type].flags & FLAG_DOUBLE_STEP;
}
void fdd_set_type(int drive, int type)
{
fdd[drive].type = type;
}
int fdd_get_type(int drive)
{
return fdd[drive].type;
}
int fdd_is_525(int drive)
{
return drive_types[fdd[drive].type].flags & FLAG_525;
}
int fdd_is_ed(int drive)
{
return drive_types[fdd[drive].type].flags & FLAG_HOLE2;
}
void fdd_set_head(int drive, int head)
{
drive ^= fdd_swap;
fdd[drive].head = head;
}
int fdd_get_head(int drive)
{
return fdd[drive].head;
}
void fdd_init()
{
fdd_stepping_motor_on[0] = fdd_stepping_motor_on[1] = 0;
fdd_track_diff[0] = fdd_track_diff[1] = 0;
timer_add(fdd_seek_poll_0, &(fdd_poll_time[0]), &(fdd_stepping_motor_on[0]), NULL);
timer_add(fdd_seek_poll_1, &(fdd_poll_time[1]), &(fdd_stepping_motor_on[1]), NULL);
}

20
src/fdd.h Normal file
View File

@@ -0,0 +1,20 @@
#define SEEK_RECALIBRATE -999
void fdd_seek(int drive, int track_diff);
int fdd_track0(int drive);
int fdd_getrpm(int drive);
void fdd_set_densel(int densel);
int fdd_can_read_medium(int drive);
int fdd_doublestep_40(int drive);
int fdd_is_525(int drive);
int fdd_is_ed(int drive);
void fdd_set_head(int drive, int head);
int fdd_get_head(int drive);
void fdd_set_type(int drive, int type);
int fdd_get_type(int drive);
extern int fdd_swap;
extern int fdd_stepping_motor_on[2];
extern int fdd_track_diff[2];
void fdd_init();

2190
src/fdi2raw.c Normal file

File diff suppressed because it is too large Load Diff

34
src/fdi2raw.h Normal file
View File

@@ -0,0 +1,34 @@
#ifndef __FDI2RAW_H
#define __FDI2RAW_H
#define uae_u8 uint8_t
#define uae_u16 uint16_t
#define uae_u32 uint32_t
//#include "types.h"
#include <stdio.h>
typedef struct fdi FDI;
#ifdef __cplusplus
extern "C" {
#endif
extern int fdi2raw_loadtrack (FDI*, uae_u16 *mfmbuf, uae_u16 *tracktiming, int track, int *tracklength, int *indexoffset, int *multirev, int mfm);
extern int fdi2raw_loadrevolution (FDI*, uae_u16 *mfmbuf, uae_u16 *tracktiming, int track, int *tracklength, int mfm);
extern FDI *fdi2raw_header(FILE *f);
extern void fdi2raw_header_free (FDI *);
extern int fdi2raw_get_last_track(FDI *);
extern int fdi2raw_get_num_sector (FDI *);
extern int fdi2raw_get_last_head(FDI *);
extern int fdi2raw_get_type (FDI *);
extern int fdi2raw_get_bit_rate (FDI *);
extern int fdi2raw_get_rotation (FDI *);
extern int fdi2raw_get_write_protect (FDI *);
#ifdef __cplusplus
}
#endif
#endif

281
src/filters.h Normal file
View File

@@ -0,0 +1,281 @@
#define NCoef 2
//fc=350Hz
static inline float low_iir(int i, float NewSample) {
float ACoef[NCoef+1] = {
0.00049713569693400649,
0.00099427139386801299,
0.00049713569693400649
};
float BCoef[NCoef+1] = {
1.00000000000000000000,
-1.93522955470669530000,
0.93726236021404663000
};
static float y[2][NCoef+1]; //output samples
static float x[2][NCoef+1]; //input samples
int n;
//shift the old samples
for(n=NCoef; n>0; n--) {
x[i][n] = x[i][n-1];
y[i][n] = y[i][n-1];
}
//Calculate the new output
x[i][0] = NewSample;
y[i][0] = ACoef[0] * x[i][0];
for(n=1; n<=NCoef; n++)
y[i][0] += ACoef[n] * x[i][n] - BCoef[n] * y[i][n];
return y[i][0];
}
//fc=350Hz
static inline float low_cut_iir(int i, float NewSample) {
float ACoef[NCoef+1] = {
0.96839970114733542000,
-1.93679940229467080000,
0.96839970114733542000
};
float BCoef[NCoef+1] = {
1.00000000000000000000,
-1.93522955471202770000,
0.93726236021916731000
};
static float y[2][NCoef+1]; //output samples
static float x[2][NCoef+1]; //input samples
int n;
//shift the old samples
for(n=NCoef; n>0; n--) {
x[i][n] = x[i][n-1];
y[i][n] = y[i][n-1];
}
//Calculate the new output
x[i][0] = NewSample;
y[i][0] = ACoef[0] * x[i][0];
for(n=1; n<=NCoef; n++)
y[i][0] += ACoef[n] * x[i][n] - BCoef[n] * y[i][n];
return y[i][0];
}
//fc=3.5kHz
static inline float high_iir(int i, float NewSample) {
float ACoef[NCoef+1] = {
0.72248704753064896000,
-1.44497409506129790000,
0.72248704753064896000
};
float BCoef[NCoef+1] = {
1.00000000000000000000,
-1.36640781670578510000,
0.52352474706139873000
};
static float y[2][NCoef+1]; //output samples
static float x[2][NCoef+1]; //input samples
int n;
//shift the old samples
for(n=NCoef; n>0; n--) {
x[i][n] = x[i][n-1];
y[i][n] = y[i][n-1];
}
//Calculate the new output
x[i][0] = NewSample;
y[i][0] = ACoef[0] * x[i][0];
for(n=1; n<=NCoef; n++)
y[i][0] += ACoef[n] * x[i][n] - BCoef[n] * y[i][n];
return y[i][0];
}
//fc=3.5kHz
static inline float high_cut_iir(int i, float NewSample) {
float ACoef[NCoef+1] = {
0.03927726802250377400,
0.07855453604500754700,
0.03927726802250377400
};
float BCoef[NCoef+1] = {
1.00000000000000000000,
-1.36640781666419950000,
0.52352474703279628000
};
static float y[2][NCoef+1]; //output samples
static float x[2][NCoef+1]; //input samples
int n;
//shift the old samples
for(n=NCoef; n>0; n--) {
x[i][n] = x[i][n-1];
y[i][n] = y[i][n-1];
}
//Calculate the new output
x[i][0] = NewSample;
y[i][0] = ACoef[0] * x[i][0];
for(n=1; n<=NCoef; n++)
y[i][0] += ACoef[n] * x[i][n] - BCoef[n] * y[i][n];
return y[i][0];
}
#undef NCoef
#define NCoef 1
//fc=3.2kHz
static inline float sb_iir(int i, float NewSample) {
/* float ACoef[NCoef+1] = {
0.03356837051492005100,
0.06713674102984010200,
0.03356837051492005100
};
float BCoef[NCoef+1] = {
1.00000000000000000000,
-1.41898265221812010000,
0.55326988968868285000
};*/
float ACoef[NCoef+1] = {
0.17529642630084405000,
0.17529642630084405000
};
float BCoef[NCoef+1] = {
1.00000000000000000000,
-0.64940759319751051000
};
static float y[2][NCoef+1]; //output samples
static float x[2][NCoef+1]; //input samples
int n;
//shift the old samples
for(n=NCoef; n>0; n--) {
x[i][n] = x[i][n-1];
y[i][n] = y[i][n-1];
}
//Calculate the new output
x[i][0] = NewSample;
y[i][0] = ACoef[0] * x[i][0];
for(n=1; n<=NCoef; n++)
y[i][0] += ACoef[n] * x[i][n] - BCoef[n] * y[i][n];
return y[i][0];
}
#undef NCoef
#define NCoef 2
//fc=150Hz
static inline float adgold_highpass_iir(int i, float NewSample) {
float ACoef[NCoef+1] = {
0.98657437157334349000,
-1.97314874314668700000,
0.98657437157334349000
};
float BCoef[NCoef+1] = {
1.00000000000000000000,
-1.97223372919758360000,
0.97261396931534050000
};
static float y[2][NCoef+1]; //output samples
static float x[2][NCoef+1]; //input samples
int n;
//shift the old samples
for(n=NCoef; n>0; n--) {
x[i][n] = x[i][n-1];
y[i][n] = y[i][n-1];
}
//Calculate the new output
x[i][0] = NewSample;
y[i][0] = ACoef[0] * x[i][0];
for(n=1; n<=NCoef; n++)
y[i][0] += ACoef[n] * x[i][n] - BCoef[n] * y[i][n];
return y[i][0];
}
//fc=150Hz
static inline float adgold_lowpass_iir(int i, float NewSample) {
float ACoef[NCoef+1] = {
0.00009159473951071446,
0.00018318947902142891,
0.00009159473951071446
};
float BCoef[NCoef+1] = {
1.00000000000000000000,
-1.97223372919526560000,
0.97261396931306277000
};
static float y[2][NCoef+1]; //output samples
static float x[2][NCoef+1]; //input samples
int n;
//shift the old samples
for(n=NCoef; n>0; n--) {
x[i][n] = x[i][n-1];
y[i][n] = y[i][n-1];
}
//Calculate the new output
x[i][0] = NewSample;
y[i][0] = ACoef[0] * x[i][0];
for(n=1; n<=NCoef; n++)
y[i][0] += ACoef[n] * x[i][n] - BCoef[n] * y[i][n];
return y[i][0];
}
//fc=56Hz
static inline float adgold_pseudo_stereo_iir(float NewSample) {
float ACoef[NCoef+1] = {
0.00001409030866231767,
0.00002818061732463533,
0.00001409030866231767
};
float BCoef[NCoef+1] = {
1.00000000000000000000,
-1.98733021473466760000,
0.98738361004063568000
};
static float y[NCoef+1]; //output samples
static float x[NCoef+1]; //input samples
int n;
//shift the old samples
for(n=NCoef; n>0; n--) {
x[n] = x[n-1];
y[n] = y[n-1];
}
//Calculate the new output
x[0] = NewSample;
y[0] = ACoef[0] * x[0];
for(n=1; n<=NCoef; n++)
y[0] += ACoef[n] * x[n] - BCoef[n] * y[n];
return y[0];
}

223
src/gameport.c Normal file
View File

@@ -0,0 +1,223 @@
#include <stdlib.h>
#include "ibm.h"
#include "device.h"
#include "io.h"
#include "plat-joystick.h"
#include "timer.h"
#include "gameport.h"
#include "joystick_standard.h"
#include "joystick_sw_pad.h"
int joystick_type;
static joystick_if_t *joystick_list[] =
{
&joystick_standard,
&joystick_standard_4button,
&joystick_standard_6button,
&joystick_standard_8button,
&joystick_sw_pad,
NULL
};
char *joystick_get_name(int joystick)
{
if (!joystick_list[joystick])
return NULL;
return joystick_list[joystick]->name;
}
int joystick_get_max_joysticks(int joystick)
{
return joystick_list[joystick]->max_joysticks;
}
int joystick_get_axis_count(int joystick)
{
return joystick_list[joystick]->axis_count;
}
int joystick_get_button_count(int joystick)
{
return joystick_list[joystick]->button_count;
}
char *joystick_get_axis_name(int joystick, int id)
{
return joystick_list[joystick]->axis_names[id];
}
char *joystick_get_button_name(int joystick, int id)
{
return joystick_list[joystick]->button_names[id];
}
typedef struct gameport_axis_t
{
int count;
int axis_nr;
struct gameport_t *gameport;
} gameport_axis_t;
typedef struct gameport_t
{
uint8_t state;
gameport_axis_t axis[4];
joystick_if_t *joystick;
void *joystick_dat;
} gameport_t;
static gameport_t *gameport_global = NULL;
static int gameport_time(int axis)
{
if (axis == AXIS_NOT_PRESENT)
return 0;
axis += 32768;
axis = (axis * 100) / 65; /*Axis now in ohms*/
axis = (axis * 11) / 1000;
return TIMER_USEC * (axis + 24); /*max = 11.115 ms*/
}
void gameport_write(uint16_t addr, uint8_t val, void *p)
{
gameport_t *gameport = (gameport_t *)p;
timer_clock();
gameport->state |= 0x0f;
// pclog("gameport_write : joysticks_present=%i\n", joysticks_present);
gameport->axis[0].count = gameport_time(gameport->joystick->read_axis(gameport->joystick_dat, 0));
gameport->axis[1].count = gameport_time(gameport->joystick->read_axis(gameport->joystick_dat, 1));
gameport->axis[2].count = gameport_time(gameport->joystick->read_axis(gameport->joystick_dat, 2));
gameport->axis[3].count = gameport_time(gameport->joystick->read_axis(gameport->joystick_dat, 3));
gameport->joystick->write(gameport->joystick_dat);
cycles -= ISA_CYCLES(8);
}
uint8_t gameport_read(uint16_t addr, void *p)
{
gameport_t *gameport = (gameport_t *)p;
uint8_t ret;
timer_clock();
// if (joysticks_present)
ret = gameport->state | gameport->joystick->read(gameport->joystick_dat);//0xf0;
// else
// ret = 0xff;
// pclog("gameport_read: ret=%02x %08x:%08x isa_cycles=%i %i\n", ret, cs, cpu_state.pc, isa_cycles, gameport->axis[0].count);
cycles -= ISA_CYCLES(8);
return ret;
}
void gameport_timer_over(void *p)
{
gameport_axis_t *axis = (gameport_axis_t *)p;
gameport_t *gameport = axis->gameport;
gameport->state &= ~(1 << axis->axis_nr);
axis->count = 0;
if (axis == &gameport->axis[0])
gameport->joystick->a0_over(gameport->joystick_dat);
}
void *gameport_init_common()
{
gameport_t *gameport = malloc(sizeof(gameport_t));
memset(gameport, 0, sizeof(gameport_t));
gameport->axis[0].gameport = gameport;
gameport->axis[1].gameport = gameport;
gameport->axis[2].gameport = gameport;
gameport->axis[3].gameport = gameport;
gameport->axis[0].axis_nr = 0;
gameport->axis[1].axis_nr = 1;
gameport->axis[2].axis_nr = 2;
gameport->axis[3].axis_nr = 3;
timer_add(gameport_timer_over, &gameport->axis[0].count, &gameport->axis[0].count, &gameport->axis[0]);
timer_add(gameport_timer_over, &gameport->axis[1].count, &gameport->axis[1].count, &gameport->axis[1]);
timer_add(gameport_timer_over, &gameport->axis[2].count, &gameport->axis[2].count, &gameport->axis[2]);
timer_add(gameport_timer_over, &gameport->axis[3].count, &gameport->axis[3].count, &gameport->axis[3]);
gameport->joystick = joystick_list[joystick_type];
gameport->joystick_dat = gameport->joystick->init();
gameport_global = gameport;
return gameport;
}
void gameport_update_joystick_type()
{
gameport_t *gameport = gameport_global;
gameport->joystick->close(gameport->joystick_dat);
gameport->joystick = joystick_list[joystick_type];
gameport->joystick_dat = gameport->joystick->init();
}
void *gameport_init()
{
gameport_t *gameport = gameport_init_common();
io_sethandler(0x0200, 0x0008, gameport_read, NULL, NULL, gameport_write, NULL, NULL, gameport);
return gameport;
}
void *gameport_201_init()
{
gameport_t *gameport = gameport_init_common();
io_sethandler(0x0201, 0x0001, gameport_read, NULL, NULL, gameport_write, NULL, NULL, gameport);
return gameport;
}
void gameport_close(void *p)
{
gameport_t *gameport = (gameport_t *)p;
gameport->joystick->close(gameport->joystick_dat);
gameport_global = NULL;
free(gameport);
}
device_t gameport_device =
{
"Game port",
0,
gameport_init,
gameport_close,
NULL,
NULL,
NULL,
NULL
};
device_t gameport_201_device =
{
"Game port (port 201h only)",
0,
gameport_201_init,
gameport_close,
NULL,
NULL,
NULL,
NULL
};

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