mirror of
https://github.com/86Box/86Box.git
synced 2026-02-22 17:45:31 -07:00
Initial submission of the PCem-Experimental source code.
This commit is contained in:
380
src/386.c
Normal file
380
src/386.c
Normal 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
2
src/386.h
Normal file
@@ -0,0 +1,2 @@
|
||||
extern void cpu_386_flags_extract();
|
||||
extern void cpu_386_flags_rebuild();
|
||||
288
src/386_common.h
Normal file
288
src/386_common.h
Normal 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
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
57
src/386_dynarec_ops.c
Normal 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
1371
src/386_ops.h
Normal file
File diff suppressed because it is too large
Load Diff
3509
src/808x.c
Normal file
3509
src/808x.c
Normal file
File diff suppressed because it is too large
Load Diff
BIN
src/IBMPCAT-1.ico
Normal file
BIN
src/IBMPCAT-1.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 206 KiB |
51
src/Makefile.am
Normal file
51
src/Makefile.am
Normal 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
2956
src/Makefile.in
Normal file
File diff suppressed because it is too large
Load Diff
51
src/Makefile.mingw
Normal file
51
src/Makefile.mingw
Normal 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
49
src/Makefile.mingw64
Normal 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
50
src/Makefile_AMD.mingw
Normal 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
22
src/PCem.manifest
Normal 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
33
src/acer386sx.c
Normal 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
1
src/acer386sx.h
Normal file
@@ -0,0 +1 @@
|
||||
void acer386sx_init();
|
||||
29
src/acerm3a.c
Normal file
29
src/acerm3a.c
Normal 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
1
src/acerm3a.h
Normal file
@@ -0,0 +1 @@
|
||||
void acerm3a_io_init();
|
||||
86
src/ali1429.c
Normal file
86
src/ali1429.c
Normal 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
1
src/ali1429.h
Normal file
@@ -0,0 +1 @@
|
||||
void ali1429_init();
|
||||
636
src/allegro-gui-configure.c
Normal file
636
src/allegro-gui-configure.c
Normal 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;
|
||||
}
|
||||
|
||||
303
src/allegro-gui-deviceconfig.c
Normal file
303
src/allegro-gui-deviceconfig.c
Normal 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
513
src/allegro-gui-hdconf.c
Normal 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
226
src/allegro-gui.c
Normal 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
12
src/allegro-gui.h
Normal 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
49
src/allegro-joystick.c
Normal 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
49
src/allegro-keyboard.c
Normal 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
169
src/allegro-main.c
Normal 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
19
src/allegro-main.h
Normal 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
45
src/allegro-midi.c
Normal 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
31
src/allegro-mouse.c
Normal 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
127
src/allegro-video.c
Normal 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
3
src/allegro-video.h
Normal 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
83
src/amstrad.c
Normal 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
2
src/amstrad.h
Normal file
@@ -0,0 +1,2 @@
|
||||
void amstrad_init();
|
||||
|
||||
202
src/bswap.h
Normal file
202
src/bswap.h
Normal 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
724
src/cdrom-ioctl-linux.c
Normal 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
747
src/cdrom-ioctl.c
Normal 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,<oc,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,<oc,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, <oc, 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
12
src/cdrom-ioctl.h
Normal 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
396
src/cdrom-iso.c
Normal 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
14
src/cdrom-iso.h
Normal 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
139
src/cdrom-null.c
Normal 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
11
src/cdrom-null.h
Normal 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
21
src/codegen.c
Normal 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
340
src/codegen.h
Normal 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
497
src/codegen_ops.c
Normal 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
37
src/codegen_ops.h
Normal 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
816
src/codegen_ops_arith.h
Normal 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
601
src/codegen_ops_fpu.h
Normal 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
270
src/codegen_ops_jump.h
Normal 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
507
src/codegen_ops_logic.h
Normal 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
115
src/codegen_ops_misc.h
Normal 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
277
src/codegen_ops_mmx.h
Normal 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
506
src/codegen_ops_mov.h
Normal 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
114
src/codegen_ops_shift.h
Normal 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
250
src/codegen_ops_stack.h
Normal 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
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
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
93
src/codegen_ops_xchg.h
Normal 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
375
src/codegen_timing_486.c
Normal 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
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
1061
src/codegen_timing_pentium.c
Normal file
File diff suppressed because it is too large
Load Diff
375
src/codegen_timing_winchip.c
Normal file
375
src/codegen_timing_winchip.c
Normal 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
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
21
src/codegen_x86-64.h
Normal 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
1048
src/codegen_x86.c
Normal file
File diff suppressed because it is too large
Load Diff
21
src/codegen_x86.h
Normal file
21
src/codegen_x86.h
Normal 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
51
src/compaq.c
Normal 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
1
src/compaq.h
Normal file
@@ -0,0 +1 @@
|
||||
void compaq_init();
|
||||
400
src/config.c
Normal file
400
src/config.c
Normal 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(¤t_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, ¤t_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, §ion->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
16
src/config.h
Normal 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];
|
||||
146
src/cpu.h
Normal file
146
src/cpu.h
Normal 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
68
src/dac.c
Normal 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
137
src/device.c
Normal 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
50
src/device.h
Normal 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
453
src/disc.c
Normal 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
83
src/disc.h
Normal 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
513
src/disc_fdi.c
Normal 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
13
src/disc_fdi.h
Normal 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
702
src/disc_img.c
Normal 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
13
src/disc_img.h
Normal 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
525
src/disc_sector.c
Normal 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
43
src/disc_sector.h
Normal 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
389
src/dma.c
Normal 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
16
src/dma.h
Normal 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
1521
src/dosbox/dbopl.cpp
Normal file
File diff suppressed because it is too large
Load Diff
273
src/dosbox/dbopl.h
Normal file
273
src/dosbox/dbopl.h
Normal 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
|
||||
27
src/fdc.h
Normal file
27
src/fdc.h
Normal 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
165
src/fdc37c665.c
Normal 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
1
src/fdc37c665.h
Normal file
@@ -0,0 +1 @@
|
||||
extern void fdc37c665_init();
|
||||
478
src/fdc37c932fr.c
Normal file
478
src/fdc37c932fr.c
Normal 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
1
src/fdc37c932fr.h
Normal file
@@ -0,0 +1 @@
|
||||
extern void fdc37c932fr_init();
|
||||
325
src/fdd.c
Normal file
325
src/fdd.c
Normal 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
20
src/fdd.h
Normal 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
2190
src/fdi2raw.c
Normal file
File diff suppressed because it is too large
Load Diff
34
src/fdi2raw.h
Normal file
34
src/fdi2raw.h
Normal 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
281
src/filters.h
Normal 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
223
src/gameport.c
Normal 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
Reference in New Issue
Block a user