#include <stdint.h>
#include <stdlib.h>
#include "ibm.h"
-#include "386.h"
#include "x86.h"
#include "x87.h"
#include "mem.h"
#include "nmi.h"
#include "386_common.h"
+#include "codegen.h"
+#undef CPU_BLOCK_END
#define CPU_BLOCK_END()
-extern int codegen_flags_changed;
-
-extern int nmi_enable;
-
-int inscounts[256];
-uint32_t oldpc2;
-
-int trap;
-
-
-
-extern int cpl_override;
-
-int has_fpu;
-extern int fpucount;
-uint16_t rds;
-uint16_t ea_rseg;
-
-extern int is486;
-extern int cgate32;
-
-
-
-extern uint8_t romext[32768];
-extern uint8_t *ram,*rom;
-
-uint32_t rmdat32;
-#define rmdat rmdat32
-#define fetchdat rmdat32
-uint32_t backupregs[16];
-extern int oddeven;
-int inttype;
-
-
-uint32_t oldcs2;
-uint32_t oldecx;
-
-uint32_t *eal_r, *eal_w;
-
-extern uint16_t *mod1add[2][8];
-extern uint32_t *mod1seg[8];
-
static inline void fetch_ea_32_long(uint32_t rmdat)
{
eal_r = eal_w = NULL;
easeg = cpu_state.ea_seg->base;
- ea_rseg = cpu_state.ea_seg->seg;
if (cpu_rm == 4)
{
uint8_t sib = rmdat >> 8;
else if ((sib & 6) == 4 && !cpu_state.ssegs)
{
easeg = ss;
- ea_rseg = SS;
- cpu_state.ea_seg = &_ss;
+ cpu_state.ea_seg = &cpu_state.seg_ss;
}
if (((sib >> 3) & 7) != 4)
cpu_state.eaaddr += cpu_state.regs[(sib >> 3) & 7].l << (sib >> 6);
if (cpu_rm == 5 && !cpu_state.ssegs)
{
easeg = ss;
- ea_rseg = SS;
- cpu_state.ea_seg = &_ss;
+ cpu_state.ea_seg = &cpu_state.seg_ss;
}
if (cpu_mod == 1)
{
{
eal_r = eal_w = NULL;
easeg = cpu_state.ea_seg->base;
- ea_rseg = cpu_state.ea_seg->seg;
- if (!cpu_mod && cpu_rm == 6)
+ if (!cpu_mod && cpu_rm == 6)
{
cpu_state.eaaddr = getword();
}
if (mod1seg[cpu_rm] == &ss && !cpu_state.ssegs)
{
easeg = ss;
- ea_rseg = SS;
- cpu_state.ea_seg = &_ss;
+ cpu_state.ea_seg = &cpu_state.seg_ss;
}
cpu_state.eaaddr &= 0xFFFF;
}
#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
#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;
// output=3;
while (cycles>0)
{
- int cycle_period = (timer_count >> TIMER_SHIFT) + 1;
+ int cycle_period = (timer_target - (uint32_t)tsc) + 1;
x86_was_reset = 0;
cycdiff=0;
oldcyc=cycles;
- timer_start_period(cycles << TIMER_SHIFT);
// pclog("%i %02X\n", ins, ram[8]);
while (cycdiff < cycle_period)
{
- /* testr[0]=EAX; testr[1]=EBX; testr[2]=ECX; testr[3]=EDX;
- testr[4]=ESI; testr[5]=EDI; testr[6]=EBP; testr[7]=ESP;*/
-/* testr[8]=flags;*/
-// oldcs2=oldcs;
-// oldpc2=oldpc;
-
- oldcs=CS;
+ int ins_cycles = cycles;
+
cpu_state.oldpc = cpu_state.pc;
- oldcpl=CPL;
cpu_state.op32 = use32;
-dontprint=0;
-
- cpu_state.ea_seg = &_ds;
+ cpu_state.ea_seg = &cpu_state.seg_ds;
cpu_state.ssegs = 0;
fetchdat = fastreadl(cs + cpu_state.pc);
if (!cpu_state.abrt)
- {
- trap = flags & T_FLAG;
- opcode = fetchdat & 0xFF;
+ {
+ uint8_t opcode = fetchdat & 0xFF;
fetchdat >>= 8;
+ trap = cpu_state.flags & T_FLAG;
if (output == 3)
{
- pclog("%04X(%06X):%04X : %08X %08X %08X %08X %04X %04X %04X(%08X) %04X %04X %04X(%08X) %08X %08X %08X SP=%04X:%08X %02X %04X %i %08X %08X %i %i %02X %02X %02X %02X %02X %f %02X%02X %02X%02X %02X%02X %02X\n",CS,cs,cpu_state.pc,EAX,EBX,ECX,EDX,CS,DS,ES,es,FS,GS,SS,ss,EDI,ESI,EBP,SS,ESP,opcode,flags,ins,0, ldt.base, CPL, stack32, pic.pend, pic.mask, pic.mask2, pic2.pend, pic2.mask, pit.c[0], ram[0xB270+0x3F5], ram[0xB270+0x3F4], ram[0xB270+0x3F7], ram[0xB270+0x3F6], ram[0xB270+0x3F9], ram[0xB270+0x3F8], ram[0x4430+0x0D49]);
+ pclog("%04X(%06X):%04X : %08X %08X %08X %08X %04X %04X %04X(%08X) %04X %04X %04X(%08X) %08X %08X %08X SP=%04X:%08X %02X %04X %i %08X %08X %i %i %02X %02X %02X %02X %02X\n",CS,cs,cpu_state.pc,EAX,EBX,ECX,EDX,CS,DS,ES,es,FS,GS,SS,ss,EDI,ESI,EBP,SS,ESP,opcode,cpu_state.flags,ins,0, ldt.base, CPL, stack32, pic.pend, pic.mask, pic.mask2, pic2.pend, pic2.mask);
}
cpu_state.pc++;
x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat);
break;
}
- if (!use32) cpu_state.pc &= 0xffff;
-
if (cpu_state.abrt)
{
flags_rebuild();
// pclog("Abort\n");
// if (CS == 0x228) pclog("Abort at %04X:%04X - %i %i %i\n",CS,pc,notpresent,nullseg,abrt);
-/* if (testr[0]!=EAX) pclog("EAX corrupted %08X\n",pc);
- if (testr[1]!=EBX) pclog("EBX corrupted %08X\n",pc);
- if (testr[2]!=ECX) pclog("ECX corrupted %08X\n",pc);
- if (testr[3]!=EDX) pclog("EDX corrupted %08X\n",pc);
- if (testr[4]!=ESI) pclog("ESI corrupted %08X\n",pc);
- if (testr[5]!=EDI) pclog("EDI corrupted %08X\n",pc);
- if (testr[6]!=EBP) pclog("EBP corrupted %08X\n",pc);
- if (testr[7]!=ESP) pclog("ESP corrupted %08X\n",pc);*/
-/* if (testr[8]!=flags) pclog("FLAGS corrupted %08X\n",pc);*/
tempi = cpu_state.abrt;
cpu_state.abrt = 0;
x86_doabrt(tempi);
if (cpu_state.abrt)
{
cpu_state.abrt = 0;
- CS = oldcs;
cpu_state.pc = cpu_state.oldpc;
pclog("Double fault %i\n", ins);
pmodeint(8, 0);
}
}
}
+ ins_cycles -= cycles;
+ tsc += ins_cycles;
+
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-2)&0xFFFF,cpu_state.flags);
writememw(ss,(SP-4)&0xFFFF,CS);
writememw(ss,(SP-6)&0xFFFF,cpu_state.pc);
SP-=6;
addr = (1 << 2) + idt.base;
- flags&=~I_FLAG;
- flags&=~T_FLAG;
+ cpu_state.flags &= ~I_FLAG;
+ cpu_state.flags &= ~T_FLAG;
cpu_state.pc=readmemw(0,addr);
loadcs(readmemw(0,addr+2));
}
else if (nmi && nmi_enable && nmi_mask)
{
cpu_state.oldpc = cpu_state.pc;
- oldcs = CS;
// pclog("NMI\n");
x86_int(2);
nmi_enable = 0;
nmi = 0;
}
}
- else if ((flags&I_FLAG) && pic_intpending)
+ else if ((cpu_state.flags & I_FLAG) && pic_intpending)
{
temp=picinterrupt();
if (temp!=0xFF)
}
else
{
- writememw(ss,(SP-2)&0xFFFF,flags);
+ writememw(ss,(SP-2)&0xFFFF,cpu_state.flags);
writememw(ss,(SP-4)&0xFFFF,CS);
writememw(ss,(SP-6)&0xFFFF,cpu_state.pc);
SP-=6;
addr = (temp << 2) + idt.base;
- flags&=~I_FLAG;
- flags&=~T_FLAG;
- oxpc=cpu_state.pc;
+ cpu_state.flags &= ~I_FLAG;
+ cpu_state.flags &= ~T_FLAG;
cpu_state.pc=readmemw(0,addr);
loadcs(readmemw(0,addr+2));
// if (temp==0x76) pclog("INT to %04X:%04X\n",CS,pc);
}
}
- tsc += cycdiff;
-
- timer_end_period(cycles << TIMER_SHIFT);
+ if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t)tsc))
+ timer_process();
}
}
+++ /dev/null
-extern void cpu_386_flags_extract();
-extern void cpu_386_flags_rebuild();
-
-void pmodeint(int num, int soft);
-void loadcscall(uint16_t seg);
-void loadcsjmp(uint16_t seg, uint32_t oxpc);
-void pmoderetf(int is32, uint16_t off);
-void pmodeiret(int is32);
-void x86_int_sw(int num);
-int x86_int_sw_rm(int num);
-
-int divl(uint32_t val);
-int idivl(int32_t val);
--- /dev/null
+#include "ibm.h"
+#include "x86.h"
+#include "386_common.h"
+#include "x86_flags.h"
+#include "codegen.h"
+
+x86seg gdt, ldt, idt, tr;
+
+uint32_t cr2, cr3, cr4;
+uint32_t dr[8];
+
+uint32_t use32;
+int stack32;
+int optype;
+
+int trap;
+
+uint32_t rmdat;
+
+uint32_t *eal_r, *eal_w;
+
+int nmi_enable = 1;
+
+int cpl_override=0;
+
+int fpucount=0;
+
+uint16_t cpu_cur_status = 0;
+
+uint32_t pccache;
+uint8_t *pccache2;
+
+void x86_int(int num)
+{
+ uint32_t addr;
+// pclog("x86_int %02x %04x:%04x\n", num, CS,pc);
+ flags_rebuild();
+ cpu_state.pc=cpu_state.oldpc;
+ if (msw&1)
+ {
+ pmodeint(num,0);
+ }
+ else
+ {
+ addr = (num << 2) + idt.base;
+
+ if ((num << 2) + 3 > idt.limit)
+ {
+ if (idt.limit < 35)
+ {
+ cpu_state.abrt = 0;
+ softresetx86();
+ cpu_set_edx();
+ pclog("Triple fault in real mode - reset\n");
+ }
+ else
+ x86_int(8);
+ }
+ else
+ {
+ if (stack32)
+ {
+ writememw(ss,ESP-2,cpu_state.flags);
+ writememw(ss,ESP-4,CS);
+ writememw(ss,ESP-6,cpu_state.pc);
+ ESP-=6;
+ }
+ else
+ {
+ writememw(ss,((SP-2)&0xFFFF),cpu_state.flags);
+ writememw(ss,((SP-4)&0xFFFF),CS);
+ writememw(ss,((SP-6)&0xFFFF),cpu_state.pc);
+ SP-=6;
+ }
+
+ cpu_state.flags &= ~I_FLAG;
+ cpu_state.flags &= ~T_FLAG;
+ cpu_state.pc=readmemw(0,addr);
+ loadcs(readmemw(0,addr+2));
+ }
+ }
+ cycles-=70;
+ CPU_BLOCK_END();
+}
+
+void x86_int_sw(int num)
+{
+ uint32_t addr;
+// pclog("x86_int_sw %02x %04x:%04x\n", num, CS,pc);
+// pclog("x86_int\n");
+ flags_rebuild();
+ cycles -= timing_int;
+ if (msw&1)
+ {
+ pmodeint(num,1);
+ }
+ else
+ {
+ addr = (num << 2) + idt.base;
+
+ if ((num << 2) + 3 > idt.limit)
+ {
+ x86_int(13);
+ }
+ else
+ {
+ if (stack32)
+ {
+ writememw(ss,ESP-2,cpu_state.flags);
+ writememw(ss,ESP-4,CS);
+ writememw(ss,ESP-6,cpu_state.pc);
+ ESP-=6;
+ }
+ else
+ {
+ writememw(ss,((SP-2)&0xFFFF),cpu_state.flags);
+ writememw(ss,((SP-4)&0xFFFF),CS);
+ writememw(ss,((SP-6)&0xFFFF),cpu_state.pc);
+ SP-=6;
+ }
+
+ cpu_state.flags &= ~I_FLAG;
+ cpu_state.flags &= ~T_FLAG;
+ cpu_state.pc=readmemw(0,addr);
+ loadcs(readmemw(0,addr+2));
+ cycles -= timing_int_rm;
+ }
+ }
+ trap = 0;
+ CPU_BLOCK_END();
+}
+
+int x86_int_sw_rm(int num)
+{
+ uint32_t addr;
+ uint16_t new_pc, new_cs;
+
+ flags_rebuild();
+ cycles -= timing_int;
+
+ addr = num << 2;
+ new_pc = readmemw(0, addr);
+ new_cs = readmemw(0, addr + 2);
+
+ if (cpu_state.abrt) return 1;
+
+ writememw(ss,((SP-2)&0xFFFF),cpu_state.flags); if (cpu_state.abrt) {pclog("abrt5\n"); return 1; }
+ writememw(ss,((SP-4)&0xFFFF),CS);
+ writememw(ss,((SP-6)&0xFFFF),cpu_state.pc); if (cpu_state.abrt) {pclog("abrt6\n"); return 1; }
+ SP-=6;
+
+ cpu_state.eflags &= ~VIF_FLAG;
+ cpu_state.flags &= ~T_FLAG;
+ cpu_state.pc = new_pc;
+ loadcs(new_cs);
+
+ cycles -= timing_int_rm;
+ trap = 0;
+ CPU_BLOCK_END();
+
+ return 0;
+}
+
+void x86illegal()
+{
+// pclog("x86 illegal %04X %08X %04X:%08X %02X\n",msw,cr0,CS,pc,opcode);
+
+// if (output)
+// {
+// dumpregs();
+// exit(-1);
+// }
+ x86_int(6);
+}
+
+int checkio(int port)
+{
+ uint16_t t;
+ uint8_t d;
+ cpl_override = 1;
+ t = readmemw(tr.base, 0x66);
+ cpl_override = 0;
+// pclog("CheckIO 1 %08X %04x %02x\n",tr.base, eflags, _cs.access);
+ if (cpu_state.abrt) return 0;
+// pclog("CheckIO %04X %01X %01X %02X %04X %04X %08X ",CS,CPL,IOPL,port,t,t+(port>>3),tr.base+t+(port>>3));
+ if ((t+(port>>3))>tr.limit) return 1;
+ cpl_override = 1;
+ d = readmembl(tr.base + t + (port >> 3));
+// d=readmemb(tr.base,t+(port>>3));
+ cpl_override = 0;
+// pclog("%02X %02X\n",d,d&(1<<(port&7)));
+ return d&(1<<(port&7));
+}
+
+#define divexcp() { \
+ pclog("Divide exception at %04X(%06X):%04X\n",CS,cs,cpu_state.pc); \
+ x86_int(0); \
+}
+
+int divl(uint32_t val)
+{
+ if (val==0)
+ {
+ divexcp();
+ return 1;
+ }
+ uint64_t num=(((uint64_t)EDX)<<32)|EAX;
+ uint64_t quo=num/val;
+ uint32_t rem=num%val;
+ uint32_t quo32=(uint32_t)(quo&0xFFFFFFFF);
+ if (quo!=(uint64_t)quo32)
+ {
+ divexcp();
+ return 1;
+ }
+ EDX=rem;
+ EAX=quo32;
+ return 0;
+}
+int idivl(int32_t val)
+{
+ if (val==0)
+ {
+ divexcp();
+ return 1;
+ }
+ int64_t num=(((uint64_t)EDX)<<32)|EAX;
+ int64_t quo=num/val;
+ int32_t rem=num%val;
+ int32_t quo32=(int32_t)(quo&0xFFFFFFFF);
+ if (quo!=(int64_t)quo32)
+ {
+ divexcp();
+ return 1;
+ }
+ EDX=rem;
+ EAX=quo32;
+ return 0;
+}
+
+
+void cpu_386_flags_extract()
+{
+ flags_extract();
+}
+void cpu_386_flags_rebuild()
+{
+ flags_rebuild();
+}
-extern uint16_t ea_rseg;
+#ifndef _386_COMMON_H_
+#define _386_COMMON_H_
-#undef readmemb
-#undef writememb
+#define readmemb(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==-1)?readmembl((s)+(a)): *(uint8_t *)(readlookup2[(uint32_t)((s)+(a))>>12] + (uint32_t)((s) + (a))) )
+#define readmemw(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==-1 || (((s)+(a)) & 1))?readmemwl((s)+(a)):*(uint16_t *)(readlookup2[(uint32_t)((s)+(a))>>12]+(uint32_t)((s)+(a))))
+#define readmeml(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==-1 || (((s)+(a)) & 3))?readmemll((s)+(a)):*(uint32_t *)(readlookup2[(uint32_t)((s)+(a))>>12]+(uint32_t)((s)+(a))))
+#define readmemq(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==-1 || (((s)+(a)) & 7))?readmemql((s)+(a)):*(uint64_t *)(readlookup2[(uint32_t)((s)+(a))>>12]+(uint32_t)((s)+(a))))
-
-#define readmemb(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF)?readmemb386l(s,a): *(uint8_t *)(readlookup2[(uint32_t)((s)+(a))>>12] + (uint32_t)((s) + (a))) )
-#define readmemq(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF || (((s)+(a)) & 7))?readmemql(s,a):*(uint64_t *)(readlookup2[(uint32_t)((s)+(a))>>12]+(uint32_t)((s)+(a))))
-
-#define writememb(s,a,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF) writememb386l(s,a,v); else *(uint8_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uint32_t)((s) + (a))) = v
-
-#define writememw(s,a,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF || (((s)+(a)) & 1)) writememwl(s,a,v); else *(uint16_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uint32_t)((s) + (a))) = v
-#define writememl(s,a,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF || (((s)+(a)) & 3)) writememll(s,a,v); else *(uint32_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uint32_t)((s) + (a))) = v
-#define writememq(s,a,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF || (((s)+(a)) & 7)) writememql(s,a,v); else *(uint64_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uint32_t)((s) + (a))) = v
+#define writememb(s,a,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==-1) writemembl((s)+(a),v); else *(uint8_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uint32_t)((s) + (a))) = v
+#define writememw(s,a,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==-1 || (((s)+(a)) & 1)) writememwl((s)+(a),v); else *(uint16_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uint32_t)((s) + (a))) = v
+#define writememl(s,a,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==-1 || (((s)+(a)) & 3)) writememll((s)+(a),v); else *(uint32_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uint32_t)((s) + (a))) = v
+#define writememq(s,a,v) if (writelookup2[(uint32_t)((s)+(a))>>12]==-1 || (((s)+(a)) & 7)) writememql((s)+(a),v); else *(uint64_t *)(writelookup2[(uint32_t)((s) + (a)) >> 12] + (uint32_t)((s) + (a))) = v
int checkio(int port);
-#define check_io_perm(port) if (!IOPLp || (eflags&VM_FLAG)) \
+#define check_io_perm(port) if (!IOPLp || (cpu_state.eflags&VM_FLAG)) \
{ \
int tempi = checkio(port); \
if (cpu_state.abrt) return 1; \
} \
}
-#define checkio_perm(port) if (!IOPLp || (eflags&VM_FLAG)) \
- { \
- int tempi = checkio(port); \
- if (cpu_state.abrt) break; \
- if (tempi) \
- { \
- x86gpf(NULL,0); \
- break; \
- } \
- }
+#define SEG_CHECK_READ(seg) \
+ do \
+ { \
+ if ((seg)->base == 0xffffffff) \
+ { \
+ x86gpf("Segment can't read", 0);\
+ return 1; \
+ } \
+ } while (0)
+
+#define SEG_CHECK_WRITE(seg) \
+ do \
+ { \
+ if ((seg)->base == 0xffffffff) \
+ { \
+ x86gpf("Segment can't write", 0);\
+ return 1; \
+ } \
+ } while (0)
#define CHECK_READ(seg, low, high) \
- if ((low < (seg)->limit_low) || (high > (seg)->limit_high) || ((msw & 1) && !(eflags & VM_FLAG) && (((seg)->access & 10) == 8))) \
+ if ((low < (seg)->limit_low) || (high > (seg)->limit_high) || ((msw & 1) && !(cpu_state.eflags & VM_FLAG) && (((seg)->access & 10) == 8))) \
{ \
x86gpf("Limit check", 0); \
return 1; \
}
#define CHECK_WRITE(seg, low, high) \
- if ((low < (seg)->limit_low) || (high > (seg)->limit_high) || !((seg)->access & 2) || ((msw & 1) && !(eflags & VM_FLAG) && ((seg)->access & 8))) \
+ if ((low < (seg)->limit_low) || (high > (seg)->limit_high) || !((seg)->access & 2) || ((msw & 1) && !(cpu_state.eflags & VM_FLAG) && ((seg)->access & 8))) \
{ \
x86gpf("Limit check", 0); \
return 1; \
}
-#define NOTRM if (!(msw & 1) || (eflags & VM_FLAG))\
+#define NOTRM if (!(msw & 1) || (cpu_state.eflags & VM_FLAG))\
{ \
x86_int(6); \
return 1; \
return val;
}
+static inline void *get_ram_ptr(uint32_t a)
+{
+ if ((a >> 12) == pccache)
+ return &pccache2[a];
+ else
+ {
+ uint8_t *t = getpccache(a);
+ return &t[a];
+ }
+}
+
static inline uint8_t getbyte()
{
cpu_state.pc++;
return (cpu_rm & 4) ? cpu_state.regs[cpu_rm & 3].b.h : cpu_state.regs[cpu_rm&3].b.l;
if (eal_r)
return *(uint8_t *)eal_r;
- return readmemb(easeg, cpu_state.eaaddr);
+ return readmemb(easeg,cpu_state.eaaddr);
}
static inline uint16_t geteaw()
{
if (cpu_mod == 3)
return cpu_state.regs[cpu_rm].w;
-// cycles-=3;
if (eal_r)
return *(uint16_t *)eal_r;
- return readmemw(easeg, cpu_state.eaaddr);
+ return readmemw(easeg,cpu_state.eaaddr);
}
static inline uint32_t geteal()
{
if (cpu_mod == 3)
return cpu_state.regs[cpu_rm].l;
-// cycles-=3;
if (eal_r)
return *eal_r;
- return readmeml(easeg, cpu_state.eaaddr);
+ return readmeml(easeg,cpu_state.eaaddr);
}
static inline uint64_t geteaq()
{
- return readmemq(easeg, cpu_state.eaaddr);
+ return readmemq(easeg,cpu_state.eaaddr);
}
static inline uint8_t geteab_mem()
static inline void seteaq(uint64_t v)
{
- writememql(easeg, cpu_state.eaaddr, v);
+ writememql(easeg+cpu_state.eaaddr, v);
}
-#define seteab(v) if (cpu_mod!=3) { if (eal_w) *(uint8_t *)eal_w=v; else writememb386l(easeg,cpu_state.eaaddr,v); } else if (cpu_rm&4) cpu_state.regs[cpu_rm&3].b.h=v; else cpu_state.regs[cpu_rm].b.l=v
-#define seteaw(v) if (cpu_mod!=3) { if (eal_w) *(uint16_t *)eal_w=v; else writememwl(easeg,cpu_state.eaaddr,v); } else cpu_state.regs[cpu_rm].w=v
-#define seteal(v) if (cpu_mod!=3) { if (eal_w) *eal_w=v; else writememll(easeg,cpu_state.eaaddr,v); } else cpu_state.regs[cpu_rm].l=v
+#define seteab(v) if (cpu_mod!=3) { if (eal_w) *(uint8_t *)eal_w=v; else writemembl(easeg+cpu_state.eaaddr,v); } else if (cpu_rm&4) cpu_state.regs[cpu_rm&3].b.h=v; else cpu_state.regs[cpu_rm].b.l=v
+#define seteaw(v) if (cpu_mod!=3) { if (eal_w) *(uint16_t *)eal_w=v; else writememwl(easeg+cpu_state.eaaddr,v); } else cpu_state.regs[cpu_rm].w=v
+#define seteal(v) if (cpu_mod!=3) { if (eal_w) *eal_w=v; else writememll(easeg+cpu_state.eaaddr,v); } else cpu_state.regs[cpu_rm].l=v
-#define seteab_mem(v) if (eal_w) *(uint8_t *)eal_w=v; else writememb386l(easeg,cpu_state.eaaddr,v);
-#define seteaw_mem(v) if (eal_w) *(uint16_t *)eal_w=v; else writememwl(easeg,cpu_state.eaaddr,v);
-#define seteal_mem(v) if (eal_w) *eal_w=v; else writememll(easeg,cpu_state.eaaddr,v);
+#define seteab_mem(v) if (eal_w) *(uint8_t *)eal_w=v; else writemembl(easeg+cpu_state.eaaddr,v);
+#define seteaw_mem(v) if (eal_w) *(uint16_t *)eal_w=v; else writememwl(easeg+cpu_state.eaaddr,v);
+#define seteal_mem(v) if (eal_w) *eal_w=v; else writememll(easeg+cpu_state.eaaddr,v);
#define getbytef() ((uint8_t)(fetchdat)); cpu_state.pc++
#define getwordf() ((uint16_t)(fetchdat)); cpu_state.pc+=2
#define getbyte2f() ((uint8_t)(fetchdat>>8)); cpu_state.pc++
#define getword2f() ((uint16_t)(fetchdat>>8)); cpu_state.pc+=2
-
-#define rmdat rmdat32
-#define fetchdat rmdat32
-
-void x86_int(int num);
+#endif
#include <stdint.h>
#include <stdlib.h>
#include "ibm.h"
-#include "386.h"
#include "x86.h"
#include "x86_ops.h"
#include "x87.h"
#include "mem.h"
#include "codegen.h"
+#include "codegen_backend.h"
#include "cpu.h"
#include "fdc.h"
#include "nmi.h"
#define CPU_BLOCK_END() cpu_block_end = 1
-uint32_t cpu_cur_status = 0;
-
-int cpu_reps, cpu_reps_latched;
-int cpu_notreps, cpu_notreps_latched;
-
int inrecomp = 0;
int cpu_recomp_blocks, cpu_recomp_full_ins, cpu_new_blocks;
int cpu_recomp_blocks_latched, cpu_recomp_ins_latched, cpu_recomp_full_ins_latched, cpu_new_blocks_latched;
int cpu_block_end = 0;
-int nmi_enable = 1;
-
-extern int inscounts[256];
-extern uint32_t oldpc2;
-
-extern int trap;
-
-
-
-extern int cpl_override;
-
-extern int has_fpu;
-int fpucount=0;
-extern uint16_t rds;
-extern uint16_t ea_rseg;
-
-extern int is486;
-extern int cgate32;
-
-
-extern uint8_t romext[32768];
-extern uint8_t *ram,*rom;
-
-extern uint32_t rmdat32;
-extern uint32_t backupregs[16];
-int oddeven=0;
-extern int inttype;
-
-
-extern uint32_t oldcs2;
-extern uint32_t oldecx;
-
-extern uint32_t *eal_r, *eal_w;
-extern uint16_t *mod1add[2][8];
-extern uint32_t *mod1seg[8];
static inline void fetch_ea_32_long(uint32_t rmdat)
{
eal_r = eal_w = NULL;
easeg = cpu_state.ea_seg->base;
- ea_rseg = cpu_state.ea_seg->seg;
if (cpu_rm == 4)
{
uint8_t sib = rmdat >> 8;
else if ((sib & 6) == 4 && !cpu_state.ssegs)
{
easeg = ss;
- ea_rseg = SS;
- cpu_state.ea_seg = &_ss;
+ cpu_state.ea_seg = &cpu_state.seg_ss;
}
if (((sib >> 3) & 7) != 4)
cpu_state.eaaddr += cpu_state.regs[(sib >> 3) & 7].l << (sib >> 6);
if (cpu_rm == 5 && !cpu_state.ssegs)
{
easeg = ss;
- ea_rseg = SS;
- cpu_state.ea_seg = &_ss;
+ cpu_state.ea_seg = &cpu_state.seg_ss;
}
if (cpu_mod == 1)
{
{
eal_r = eal_w = NULL;
easeg = cpu_state.ea_seg->base;
- ea_rseg = cpu_state.ea_seg->seg;
- if (!cpu_mod && cpu_rm == 6)
+ if (!cpu_mod && cpu_rm == 6)
{
cpu_state.eaaddr = getword();
}
if (mod1seg[cpu_rm] == &ss && !cpu_state.ssegs)
{
easeg = ss;
- ea_rseg = SS;
- cpu_state.ea_seg = &_ss;
+ cpu_state.ea_seg = &cpu_state.seg_ss;
}
cpu_state.eaaddr &= 0xFFFF;
}
#include "x86_flags.h"
-void x86_int(int num)
-{
- uint32_t addr;
-// pclog("x86_int %02x %04x:%04x\n", num, CS,pc);
- flags_rebuild();
- cpu_state.pc=cpu_state.oldpc;
- if (msw&1)
- {
- pmodeint(num,0);
- }
- else
- {
- addr = (num << 2) + idt.base;
-
- if ((num << 2) + 3 > idt.limit)
- {
- if (idt.limit < 35)
- {
- cpu_state.abrt = 0;
- softresetx86();
- cpu_set_edx();
- pclog("Triple fault in real mode - reset\n");
- }
- else
- x86_int(8);
- }
- else
- {
- if (stack32)
- {
- writememw(ss,ESP-2,flags);
- writememw(ss,ESP-4,CS);
- writememw(ss,ESP-6,cpu_state.pc);
- ESP-=6;
- }
- else
- {
- writememw(ss,((SP-2)&0xFFFF),flags);
- writememw(ss,((SP-4)&0xFFFF),CS);
- writememw(ss,((SP-6)&0xFFFF),cpu_state.pc);
- SP-=6;
- }
-
- flags&=~I_FLAG;
- flags&=~T_FLAG;
- oxpc=cpu_state.pc;
- cpu_state.pc=readmemw(0,addr);
- loadcs(readmemw(0,addr+2));
- }
- }
- cycles-=70;
- CPU_BLOCK_END();
-}
-
-void x86_int_sw(int num)
-{
- uint32_t addr;
-// pclog("x86_int_sw %02x %04x:%04x\n", num, CS,pc);
-// pclog("x86_int\n");
- flags_rebuild();
- cycles -= timing_int;
- if (msw&1)
- {
- pmodeint(num,1);
- }
- else
- {
- addr = (num << 2) + idt.base;
-
- if ((num << 2) + 3 > idt.limit)
- {
- x86_int(13);
- }
- else
- {
- if (stack32)
- {
- writememw(ss,ESP-2,flags);
- writememw(ss,ESP-4,CS);
- writememw(ss,ESP-6,cpu_state.pc);
- ESP-=6;
- }
- else
- {
- writememw(ss,((SP-2)&0xFFFF),flags);
- writememw(ss,((SP-4)&0xFFFF),CS);
- writememw(ss,((SP-6)&0xFFFF),cpu_state.pc);
- SP-=6;
- }
-
- flags&=~I_FLAG;
- flags&=~T_FLAG;
- oxpc=cpu_state.pc;
- cpu_state.pc=readmemw(0,addr);
- loadcs(readmemw(0,addr+2));
- cycles -= timing_int_rm;
- }
- }
- trap = 0;
- CPU_BLOCK_END();
-}
-
-int x86_int_sw_rm(int num)
-{
- uint32_t addr;
- uint16_t new_pc, new_cs;
-
- flags_rebuild();
- cycles -= timing_int;
-
- addr = num << 2;
- new_pc = readmemw(0, addr);
- new_cs = readmemw(0, addr + 2);
-
- if (cpu_state.abrt) return 1;
-
- writememw(ss,((SP-2)&0xFFFF),flags); if (cpu_state.abrt) {pclog("abrt5\n"); return 1; }
- writememw(ss,((SP-4)&0xFFFF),CS);
- writememw(ss,((SP-6)&0xFFFF),cpu_state.pc); if (cpu_state.abrt) {pclog("abrt6\n"); return 1; }
- SP-=6;
-
- eflags &= ~VIF_FLAG;
- flags &= ~T_FLAG;
- cpu_state.pc = new_pc;
- loadcs(new_cs);
- oxpc=cpu_state.pc;
-
- cycles -= timing_int_rm;
- trap = 0;
- CPU_BLOCK_END();
-
- return 0;
-}
-
-void x86illegal()
-{
-// pclog("x86 illegal %04X %08X %04X:%08X %02X\n",msw,cr0,CS,pc,opcode);
-
-// if (output)
-// {
-// dumpregs();
-// exit(-1);
-// }
- x86_int(6);
-}
/*Prefetch emulation is a fairly simplistic model:
- All instruction bytes must be fetched before it starts.
}
prefetch_prefixes = 0;
+ if (prefetch_bytes > 16)
+ prefetch_bytes = 16;
}
static void prefetch_flush()
#define PREFETCH_FLUSH() prefetch_flush()
-int checkio(int port)
-{
- uint16_t t;
- uint8_t d;
- cpl_override = 1;
- t = readmemw(tr.base, 0x66);
- cpl_override = 0;
-// pclog("CheckIO 1 %08X %04x %02x\n",tr.base, eflags, _cs.access);
- if (cpu_state.abrt) return 0;
-// pclog("CheckIO %04X %01X %01X %02X %04X %04X %08X ",CS,CPL,IOPL,port,t,t+(port>>3),tr.base+t+(port>>3));
- if ((t+(port>>3))>tr.limit) return 1;
- cpl_override = 1;
- d = readmemb386l(0, tr.base + t + (port >> 3));
-// d=readmemb(tr.base,t+(port>>3));
- cpl_override = 0;
-// pclog("%02X %02X\n",d,d&(1<<(port&7)));
- return d&(1<<(port&7));
-}
-
-int xout=0;
-
-
-#define divexcp() { \
- pclog("Divide exception at %04X(%06X):%04X\n",CS,cs,cpu_state.pc); \
- x86_int(0); \
-}
-
-int divl(uint32_t val)
-{
- if (val==0)
- {
- divexcp();
- return 1;
- }
- uint64_t num=(((uint64_t)EDX)<<32)|EAX;
- uint64_t quo=num/val;
- uint32_t rem=num%val;
- uint32_t quo32=(uint32_t)(quo&0xFFFFFFFF);
- if (quo!=(uint64_t)quo32)
- {
- divexcp();
- return 1;
- }
- EDX=rem;
- EAX=quo32;
- return 0;
-}
-int idivl(int32_t val)
-{
- if (val==0)
- {
- divexcp();
- return 1;
- }
- int64_t num=(((uint64_t)EDX)<<32)|EAX;
- int64_t quo=num/val;
- int32_t rem=num%val;
- int32_t quo32=(int32_t)(quo&0xFFFFFFFF);
- if (quo!=(int64_t)quo32)
- {
- divexcp();
- return 1;
- }
- EDX=rem;
- EAX=quo32;
- return 0;
-}
-
-
-void cpu_386_flags_extract()
-{
- flags_extract();
-}
-void cpu_386_flags_rebuild()
-{
- flags_rebuild();
-}
-
-extern int oldi;
-
-extern uint32_t testr[9];
-int dontprint=0;
-
#define OP_TABLE(name) ops_ ## name
#define CLOCK_CYCLES(c) cycles -= (c)
#define CLOCK_CYCLES_ALWAYS(c) cycles -= (c)
#include "386_ops.h"
-#define CACHE_ON() (!(cr0 & (1 << 30)) /*&& (cr0 & 1)*/ && !(flags & T_FLAG))
+#define CACHE_ON() (!(cr0 & (1 << 30)) && !(cpu_state.flags & T_FLAG))
//#define CACHE_ON() 0
static int cycles_main = 0;
int cycdiff;
int oldcyc;
int cyc_period = cycs / 2000; /*5us*/
-//output = 3;
+
cycles_main += cycs;
while (cycles_main > 0)
{
cycles += cyc_period;
cycles_start = cycles;
- timer_start_period(cycles << TIMER_SHIFT);
-// output=3;
- while (cycles>0)
- {
- oldcs = CS;
- cpu_state.oldpc = cpu_state.pc;
- oldcpl = CPL;
- cpu_state.op32 = use32;
-
-
- cycdiff=0;
- oldcyc=cycles;
-// if (output && CACHE_ON()) pclog("Block %04x:%04x %04x:%08x\n", CS, pc, SS,ESP);
- if (!CACHE_ON()) /*Interpret block*/
+ while (cycles>0)
{
- cpu_block_end = 0;
- x86_was_reset = 0;
-// if (output) pclog("Interpret block at %04x:%04x %04x %04x %04x %04x %04x %04x %04x\n", CS, pc, AX, BX, CX, DX, SI, DI, SP);
- while (!cpu_block_end)
+ oldcyc=cycles;
+// if (output && CACHE_ON()) pclog("Block %04x:%04x %04x:%08x\n", CS, pc, SS,ESP);
+ if (!CACHE_ON()) /*Interpret block*/
{
- oldcs=CS;
- cpu_state.oldpc = cpu_state.pc;
- oldcpl=CPL;
- cpu_state.op32 = use32;
+ cpu_block_end = 0;
+ x86_was_reset = 0;
+// if (output) pclog("Interpret block at %04x:%04x %04x %04x %04x %04x %04x %04x %04x\n", CS, pc, AX, BX, CX, DX, SI, DI, SP);
+ while (!cpu_block_end)
+ {
+ cpu_state.oldpc = cpu_state.pc;
+ cpu_state.op32 = use32;
- cpu_state.ea_seg = &_ds;
- cpu_state.ssegs = 0;
+ cpu_state.ea_seg = &cpu_state.seg_ds;
+ cpu_state.ssegs = 0;
- fetchdat = fastreadl(cs + cpu_state.pc);
-// if (!fetchdat)
-// fatal("Dead with cache off\n");
- if (!cpu_state.abrt)
- {
- trap = flags & T_FLAG;
- opcode = fetchdat & 0xFF;
- fetchdat >>= 8;
+ fetchdat = fastreadl(cs + cpu_state.pc);
-// if (output == 3)
-// pclog("int %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\n",CS,cs,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[0x8f13f], ram[0x8f13e], ram[0x8f141], ram[0x8f140]);
+ if (!cpu_state.abrt)
+ {
+ uint8_t opcode = fetchdat & 0xFF;
+ fetchdat >>= 8;
+ trap = cpu_state.flags & T_FLAG;
- cpu_state.pc++;
- x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat);
- }
+// if (output == 3)
+// pclog("int %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\n",CS,cs,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[0x8f13f], ram[0x8f13e], ram[0x8f141], ram[0x8f140]);
- if (!use32) cpu_state.pc &= 0xffff;
+ cpu_state.pc++;
+ x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat);
+ }
- if (((cs + cpu_state.pc) >> 12) != pccache)
- CPU_BLOCK_END();
+ if (((cs + cpu_state.pc) >> 12) != pccache)
+ CPU_BLOCK_END();
-/* if (ssegs)
- {
- ds=oldds;
- ss=oldss;
- ssegs=0;
- }*/
- if (cpu_state.abrt)
- CPU_BLOCK_END();
- if (trap)
- CPU_BLOCK_END();
- if (nmi && nmi_enable && nmi_mask)
- CPU_BLOCK_END();
+ if (cpu_state.abrt)
+ CPU_BLOCK_END();
+ if (trap)
+ CPU_BLOCK_END();
+ if (nmi && nmi_enable && nmi_mask)
+ CPU_BLOCK_END();
- ins++;
- insc++;
-
-/* if ((cs + pc) == 4)
- fatal("4\n");*/
-/* if (ins >= 141400000)
- output = 3;*/
+ ins++;
+ insc++;
+ }
}
- }
- else
- {
- uint32_t phys_addr = get_phys(cs+cpu_state.pc);
- int hash = HASH(phys_addr);
- codeblock_t *block = codeblock_hash[hash];
- int valid_block = 0;
- trap = 0;
-
- if (block && !cpu_state.abrt)
- {
- page_t *page = &pages[phys_addr >> 12];
-
- /*Block must match current CS, PC, code segment size,
- and physical address. The physical address check will
- also catch any page faults at this stage*/
- valid_block = (block->pc == cs + cpu_state.pc) && (block->_cs == cs) &&
- (block->phys == phys_addr) && !((block->status ^ cpu_cur_status) & CPU_STATUS_FLAGS) &&
- ((block->status & cpu_cur_status & CPU_STATUS_MASK) == (cpu_cur_status & CPU_STATUS_MASK));
- if (!valid_block)
+ else
{
- uint64_t mask = (uint64_t)1 << ((phys_addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK);
-
- if (page->code_present_mask[(phys_addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK] & mask)
+ uint32_t phys_addr = get_phys(cs+cpu_state.pc);
+ int hash = HASH(phys_addr);
+ codeblock_t *block = &codeblock[codeblock_hash[hash]];
+ int valid_block = 0;
+
+ if (!cpu_state.abrt)
{
- /*Walk page tree to see if we find the correct block*/
- codeblock_t *new_block = codeblock_tree_find(phys_addr, cs);
- if (new_block)
+ page_t *page = &pages[phys_addr >> 12];
+
+ /*Block must match current CS, PC, code segment size,
+ and physical address. The physical address check will
+ also catch any page faults at this stage*/
+ valid_block = (block->pc == cs + cpu_state.pc) && (block->_cs == cs) &&
+ (block->phys == phys_addr) && !((block->status ^ cpu_cur_status) & CPU_STATUS_FLAGS) &&
+ ((block->status & cpu_cur_status & CPU_STATUS_MASK) == (cpu_cur_status & CPU_STATUS_MASK));
+ if (!valid_block)
+ {
+ uint64_t mask = (uint64_t)1 << ((phys_addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK);
+ int byte_offset = (phys_addr >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK;
+ uint64_t byte_mask = 1ull << (PAGE_BYTE_MASK_MASK & 0x3f);
+
+ if ((page->code_present_mask & mask) || (page->byte_code_present_mask[byte_offset] & byte_mask))
+ {
+ /*Walk page tree to see if we find the correct block*/
+ codeblock_t *new_block = codeblock_tree_find(phys_addr, cs);
+ if (new_block)
+ {
+ valid_block = (new_block->pc == cs + cpu_state.pc) && (new_block->_cs == cs) &&
+ (new_block->phys == phys_addr) && !((new_block->status ^ cpu_cur_status) & CPU_STATUS_FLAGS) &&
+ ((new_block->status & cpu_cur_status & CPU_STATUS_MASK) == (cpu_cur_status & CPU_STATUS_MASK));
+ if (valid_block)
+ {
+ block = new_block;
+ codeblock_hash[hash] = get_block_nr(block);
+ }
+ }
+ }
+ }
+
+ if (valid_block && (block->page_mask & *block->dirty_mask))
+ {
+ codegen_check_flush(page, page->dirty_mask, phys_addr);
+ if (block->pc == BLOCK_PC_INVALID)
+ valid_block = 0;
+ else if (block->flags & CODEBLOCK_IN_DIRTY_LIST)
+ block->flags &= ~CODEBLOCK_WAS_RECOMPILED;
+ }
+ if (valid_block && block->page_mask2)
+ {
+ /*We don't want the second page to cause a page
+ fault at this stage - that would break any
+ code crossing a page boundary where the first
+ page is present but the second isn't. Instead
+ allow the first page to be interpreted and for
+ the page fault to occur when the page boundary
+ is actually crossed.*/
+ uint32_t phys_addr_2 = get_phys_noabrt(block->pc + ((block->flags & CODEBLOCK_BYTE_MASK) ? 0x40 : 0x400));
+ page_t *page_2 = &pages[phys_addr_2 >> 12];
+ if ((block->phys_2 ^ phys_addr_2) & ~0xfff)
+ valid_block = 0;
+ else if (block->page_mask2 & *block->dirty_mask2)
+ {
+ codegen_check_flush(page_2, page_2->dirty_mask, phys_addr_2);
+ if (block->pc == BLOCK_PC_INVALID)
+ valid_block = 0;
+ else if (block->flags & CODEBLOCK_IN_DIRTY_LIST)
+ block->flags &= ~CODEBLOCK_WAS_RECOMPILED;
+ }
+ }
+ if (valid_block && (block->flags & CODEBLOCK_IN_DIRTY_LIST))
{
- valid_block = (new_block->pc == cs + cpu_state.pc) && (new_block->_cs == cs) &&
- (new_block->phys == phys_addr) && !((new_block->status ^ cpu_cur_status) & CPU_STATUS_FLAGS) &&
- ((new_block->status & cpu_cur_status & CPU_STATUS_MASK) == (cpu_cur_status & CPU_STATUS_MASK));
- if (valid_block)
- block = new_block;
+ block->flags &= ~CODEBLOCK_WAS_RECOMPILED;
+ if (block->flags & CODEBLOCK_BYTE_MASK)
+ block->flags |= CODEBLOCK_NO_IMMEDIATES;
+ else
+ block->flags |= CODEBLOCK_BYTE_MASK;
+ }
+ if (valid_block && (block->flags & CODEBLOCK_WAS_RECOMPILED) && (block->flags & CODEBLOCK_STATIC_TOP) && block->TOP != (cpu_state.TOP & 7))
+ {
+ /*FPU top-of-stack does not match the value this block was compiled
+ with, re-compile using dynamic top-of-stack*/
+ block->flags &= ~(CODEBLOCK_STATIC_TOP | CODEBLOCK_WAS_RECOMPILED);
}
}
- }
- if (valid_block && (block->page_mask & *block->dirty_mask))
- {
- codegen_check_flush(page, page->dirty_mask[(phys_addr >> 10) & 3], phys_addr);
- page->dirty_mask[(phys_addr >> 10) & 3] = 0;
- if (block->pc == BLOCK_PC_INVALID)
- valid_block = 0;
- }
- if (valid_block && block->page_mask2)
- {
- /*We don't want the second page to cause a page
- fault at this stage - that would break any
- code crossing a page boundary where the first
- page is present but the second isn't. Instead
- allow the first page to be interpreted and for
- the page fault to occur when the page boundary
- is actually crossed.*/
- uint32_t phys_addr_2 = get_phys_noabrt(block->endpc);
- page_t *page_2 = &pages[phys_addr_2 >> 12];
- if ((block->phys_2 ^ phys_addr_2) & ~0xfff)
- valid_block = 0;
- else if (block->page_mask2 & *block->dirty_mask2)
+ if (valid_block && (block->flags & CODEBLOCK_WAS_RECOMPILED))
{
- codegen_check_flush(page_2, page_2->dirty_mask[(phys_addr_2 >> 10) & 3], phys_addr_2);
- page_2->dirty_mask[(phys_addr_2 >> 10) & 3] = 0;
- if (block->pc == BLOCK_PC_INVALID)
- valid_block = 0;
- }
- }
- if (valid_block && block->was_recompiled && (block->flags & CODEBLOCK_STATIC_TOP) && block->TOP != cpu_state.TOP)
- {
- /*FPU top-of-stack does not match the value this block was compiled
- with, re-compile using dynamic top-of-stack*/
- block->flags &= ~CODEBLOCK_STATIC_TOP;
- block->was_recompiled = 0;
- }
- }
+ void (*code)() = (void *)&block->data[BLOCK_START];
- if (valid_block && block->was_recompiled)
- {
- void (*code)() = (void(*)(void))&block->data[BLOCK_START];
-
- codeblock_hash[hash] = block;
-// if (output) pclog("Run block at %04x:%04x %04x %04x %04x %04x %04x %04x ESP=%08x %04x %08x %08x %016llx %08x\n", CS, pc, AX, BX, CX, DX, SI, DI, ESP, BP, get_phys(cs+pc), block->phys, block->page_mask, block->endpc);
-
-inrecomp=1;
- code();
-inrecomp=0;
- if (!use32) cpu_state.pc &= 0xffff;
-// cpu_recomp_ins += block->ins;
- cpu_recomp_blocks++;
-/* ins += codeblock_ins[index];
- insc += codeblock_ins[index];*/
-/* pclog("Exit block now %04X:%04X\n", CS, pc);*/
- }
- else if (valid_block && !cpu_state.abrt)
- {
- uint32_t start_pc = cpu_state.pc;
-
-// pclog("Hash %08x %i\n", codeblock_hash_pc[HASH(cs + pc)], codeblock_page_dirty[(cs + pc) >> 12]);
- cpu_block_end = 0;
- x86_was_reset = 0;
+// if (output) pclog("Run block at %04x:%04x %04x %04x %04x %04x %04x %04x ESP=%08x %04x %08x %08x %016llx %08x\n", CS, pc, AX, BX, CX, DX, SI, DI, ESP, BP, get_phys(cs+pc), block->phys, block->page_mask, block->endpc);
- cpu_new_blocks++;
+ inrecomp=1;
+ code();
+ inrecomp=0;
+
+ cpu_recomp_blocks++;
+ }
+ else if (valid_block && !cpu_state.abrt)
+ {
+ uint32_t start_pc = cs+cpu_state.pc;
+ const int max_block_size = (block->flags & CODEBLOCK_BYTE_MASK) ? ((128 - 25) - (start_pc & 0x3f)) : 1000;
+
+ cpu_block_end = 0;
+ x86_was_reset = 0;
+
+ cpu_new_blocks++;
- codegen_block_start_recompile(block);
- codegen_in_recompile = 1;
+ codegen_block_start_recompile(block);
+ codegen_in_recompile = 1;
-// if (output) pclog("Recompile block at %04x:%04x %04x %04x %04x %04x %04x %04x ESP=%04x %04x %02x%02x:%02x%02x %02x%02x:%02x%02x %02x%02x:%02x%02x\n", CS, pc, AX, BX, CX, DX, SI, DI, ESP, BP, ram[0x116330+0x6df4+0xa+3], ram[0x116330+0x6df4+0xa+2], ram[0x116330+0x6df4+0xa+1], ram[0x116330+0x6df4+0xa+0], ram[0x11d136+3],ram[0x11d136+2],ram[0x11d136+1],ram[0x11d136+0], ram[(0x119abe)+0x3],ram[(0x119abe)+0x2],ram[(0x119abe)+0x1],ram[(0x119abe)+0x0]);
- while (!cpu_block_end)
- {
- oldcs=CS;
- cpu_state.oldpc = cpu_state.pc;
- oldcpl=CPL;
- cpu_state.op32 = use32;
+// if (output) pclog("Recompile block at %04x:%04x %04x %04x %04x %04x %04x %04x ESP=%04x %04x %02x%02x:%02x%02x %02x%02x:%02x%02x %02x%02x:%02x%02x\n", CS, pc, AX, BX, CX, DX, SI, DI, ESP, BP, ram[0x116330+0x6df4+0xa+3], ram[0x116330+0x6df4+0xa+2], ram[0x116330+0x6df4+0xa+1], ram[0x116330+0x6df4+0xa+0], ram[0x11d136+3],ram[0x11d136+2],ram[0x11d136+1],ram[0x11d136+0], ram[(0x119abe)+0x3],ram[(0x119abe)+0x2],ram[(0x119abe)+0x1],ram[(0x119abe)+0x0]);
+ while (!cpu_block_end)
+ {
+ cpu_state.oldpc = cpu_state.pc;
+ cpu_state.op32 = use32;
- cpu_state.ea_seg = &_ds;
- cpu_state.ssegs = 0;
+ cpu_state.ea_seg = &cpu_state.seg_ds;
+ cpu_state.ssegs = 0;
- fetchdat = fastreadl(cs + cpu_state.pc);
-// if (fetchdat == 0xffffffff)
-// fatal("Dead ffffffff\n");
-// if (!fetchdat)
-// fatal("Dead\n");
- if (!cpu_state.abrt)
- {
- trap = flags & T_FLAG;
- opcode = fetchdat & 0xFF;
- fetchdat >>= 8;
+ fetchdat = fastreadl(cs + cpu_state.pc);
+
+ if (!cpu_state.abrt)
+ {
+ uint8_t opcode = fetchdat & 0xFF;
+ fetchdat >>= 8;
+
+ trap = cpu_state.flags & T_FLAG;
-// if (output == 3)
-// pclog("%04X(%06X):%04X : %08X %08X %08X %08X %04X %04X %04X(%08X) %04X %04X %04X(%08X) %08X %08X %08X SP=%04X:%08X %02X %04X %i %08X %08X %i %i %02X %02X %02X %02X %02X %08x %08x\n",CS,cs,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, cs+pc, pccache);
+// 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 %08x %08x\n",CS,cs,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, cs+pc, pccache);
- cpu_state.pc++;
+ cpu_state.pc++;
- codegen_generate_call(opcode, x86_opcodes[(opcode | cpu_state.op32) & 0x3ff], fetchdat, cpu_state.pc, cpu_state.pc-1);
+ codegen_generate_call(opcode, x86_opcodes[(opcode | cpu_state.op32) & 0x3ff], fetchdat, cpu_state.pc, cpu_state.pc-1);
- x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat);
+ x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat);
- if (x86_was_reset)
- break;
- }
+ if (x86_was_reset)
+ break;
+ }
- if (!use32) cpu_state.pc &= 0xffff;
-
- /*Cap source code at 4000 bytes per block; this
- will prevent any block from spanning more than
- 2 pages. In practice this limit will never be
- hit, as host block size is only 2kB*/
- if ((cpu_state.pc - start_pc) > 1000)
- CPU_BLOCK_END();
+ /*Cap source code at 4000 bytes per block; this
+ will prevent any block from spanning more than
+ 2 pages. In practice this limit will never be
+ hit, as host block size is only 2kB*/
+ if (((cs+cpu_state.pc) - start_pc) >= max_block_size)
+ CPU_BLOCK_END();
- if (trap)
- CPU_BLOCK_END();
+ if (trap)
+ CPU_BLOCK_END();
- if (nmi && nmi_enable && nmi_mask)
- CPU_BLOCK_END();
+ if (nmi && nmi_enable && nmi_mask)
+ CPU_BLOCK_END();
- if (cpu_state.abrt)
- {
- codegen_block_remove();
- CPU_BLOCK_END();
- }
+ if (cpu_state.abrt)
+ {
+ codegen_block_remove();
+ CPU_BLOCK_END();
+ }
- ins++;
- insc++;
- }
+ ins++;
+ insc++;
+ }
- if (!cpu_state.abrt && !x86_was_reset)
- codegen_block_end_recompile(block);
+ if (!cpu_state.abrt && !x86_was_reset)
+ codegen_block_end_recompile(block);
- if (x86_was_reset)
- codegen_reset();
+ if (x86_was_reset)
+ codegen_reset();
- codegen_in_recompile = 0;
-// output &= ~2;
- }
- else if (!cpu_state.abrt)
- {
- /*Mark block but do not recompile*/
- uint32_t start_pc = cpu_state.pc;
+ codegen_in_recompile = 0;
+ }
+ else if (!cpu_state.abrt)
+ {
+ /*Mark block but do not recompile*/
+ uint32_t start_pc = cs+cpu_state.pc;
+ const int max_block_size = (block->flags & CODEBLOCK_BYTE_MASK) ? ((128 - 25) - (start_pc & 0x3f)) : 1000;
-// pclog("Hash %08x %i\n", codeblock_hash_pc[HASH(cs + pc)], codeblock_page_dirty[(cs + pc) >> 12]);
- cpu_block_end = 0;
- x86_was_reset = 0;
+ cpu_block_end = 0;
+ x86_was_reset = 0;
-// cpu_new_blocks++;
-
- codegen_block_init(phys_addr);
+ codegen_block_init(phys_addr);
-// if (output) pclog("Recompile block at %04x:%04x %04x %04x %04x %04x %04x %04x ESP=%04x %04x %02x%02x:%02x%02x %02x%02x:%02x%02x %02x%02x:%02x%02x\n", CS, pc, AX, BX, CX, DX, SI, DI, ESP, BP, ram[0x116330+0x6df4+0xa+3], ram[0x116330+0x6df4+0xa+2], ram[0x116330+0x6df4+0xa+1], ram[0x116330+0x6df4+0xa+0], ram[0x11d136+3],ram[0x11d136+2],ram[0x11d136+1],ram[0x11d136+0], ram[(0x119abe)+0x3],ram[(0x119abe)+0x2],ram[(0x119abe)+0x1],ram[(0x119abe)+0x0]);
- while (!cpu_block_end)
- {
- oldcs=CS;
- cpu_state.oldpc = cpu_state.pc;
- oldcpl=CPL;
- cpu_state.op32 = use32;
+// if (output) pclog("Recompile block at %04x:%04x %04x %04x %04x %04x %04x %04x ESP=%04x %04x %02x%02x:%02x%02x %02x%02x:%02x%02x %02x%02x:%02x%02x\n", CS, pc, AX, BX, CX, DX, SI, DI, ESP, BP, ram[0x116330+0x6df4+0xa+3], ram[0x116330+0x6df4+0xa+2], ram[0x116330+0x6df4+0xa+1], ram[0x116330+0x6df4+0xa+0], ram[0x11d136+3],ram[0x11d136+2],ram[0x11d136+1],ram[0x11d136+0], ram[(0x119abe)+0x3],ram[(0x119abe)+0x2],ram[(0x119abe)+0x1],ram[(0x119abe)+0x0]);
+ while (!cpu_block_end)
+ {
+ cpu_state.oldpc = cpu_state.pc;
+ cpu_state.op32 = use32;
- cpu_state.ea_seg = &_ds;
- cpu_state.ssegs = 0;
+ cpu_state.ea_seg = &cpu_state.seg_ds;
+ cpu_state.ssegs = 0;
- codegen_endpc = (cs + cpu_state.pc) + 8;
- fetchdat = fastreadl(cs + cpu_state.pc);
-
- if (!cpu_state.abrt)
- {
- trap = flags & T_FLAG;
- opcode = fetchdat & 0xFF;
- fetchdat >>= 8;
+ codegen_endpc = (cs + cpu_state.pc) + 8;
+ fetchdat = fastreadl(cs + cpu_state.pc);
-// 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 %08x %08x\n",CS,cs,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, cs+pc, pccache);
+ if (!cpu_state.abrt)
+ {
+ uint8_t opcode = fetchdat & 0xFF;
+ fetchdat >>= 8;
- cpu_state.pc++;
-
- x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat);
-
- if (x86_was_reset)
- break;
- }
+ trap = cpu_state.flags & T_FLAG;
- if (!use32) cpu_state.pc &= 0xffff;
+// 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 %08x %08x\n",CS,cs,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, cs+pc, pccache);
- /*Cap source code at 4000 bytes per block; this
- will prevent any block from spanning more than
- 2 pages. In practice this limit will never be
- hit, as host block size is only 2kB*/
- if ((cpu_state.pc - start_pc) > 1000)
- CPU_BLOCK_END();
+ cpu_state.pc++;
+
+ x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat);
+
+ if (x86_was_reset)
+ break;
+ }
+
+ /*Cap source code at 4000 bytes per block; this
+ will prevent any block from spanning more than
+ 2 pages. In practice this limit will never be
+ hit, as host block size is only 2kB*/
+ if (((cs+cpu_state.pc) - start_pc) >= max_block_size)
+ CPU_BLOCK_END();
- if (trap)
- CPU_BLOCK_END();
+ if (trap)
+ CPU_BLOCK_END();
- if (nmi && nmi_enable && nmi_mask)
- CPU_BLOCK_END();
+ if (nmi && nmi_enable && nmi_mask)
+ CPU_BLOCK_END();
- if (cpu_state.abrt)
- {
- codegen_block_remove();
- CPU_BLOCK_END();
- }
+ if (cpu_state.abrt)
+ {
+ codegen_block_remove();
+ CPU_BLOCK_END();
+ }
- ins++;
- insc++;
- }
+ ins++;
+ insc++;
+ }
- if (!cpu_state.abrt && !x86_was_reset)
- codegen_block_end();
+ if (!cpu_state.abrt && !x86_was_reset)
+ codegen_block_end();
- if (x86_was_reset)
- codegen_reset();
+ if (x86_was_reset)
+ codegen_reset();
+ }
+ else
+ cpu_state.oldpc = cpu_state.pc;
-// output &= ~2;
- }
-// if (output && (SP & 1))
-// fatal("odd SP\n");
- }
+ }
- cycdiff=oldcyc-cycles;
- tsc += cycdiff;
-
-// timer_end_period(cycles);
+ cycdiff=oldcyc-cycles;
+ tsc += cycdiff;
- if (cpu_state.abrt)
- {
- flags_rebuild();
- tempi = cpu_state.abrt;
- cpu_state.abrt = 0;
- x86_doabrt(tempi);
if (cpu_state.abrt)
{
+ flags_rebuild();
+ tempi = cpu_state.abrt;
cpu_state.abrt = 0;
- CS = oldcs;
- cpu_state.pc = cpu_state.oldpc;
- pclog("Double fault %i\n", ins);
- pmodeint(8, 0);
+ x86_doabrt(tempi);
if (cpu_state.abrt)
{
cpu_state.abrt = 0;
- softresetx86();
- cpu_set_edx();
- pclog("Triple fault - reset\n");
+ cpu_state.pc = cpu_state.oldpc;
+ pclog("Double fault %i\n", ins);
+ pmodeint(8, 0);
+ if (cpu_state.abrt)
+ {
+ cpu_state.abrt = 0;
+ softresetx86();
+ cpu_set_edx();
+ pclog("Triple fault - reset\n");
+ }
}
}
- }
- if (trap)
- {
-
- flags_rebuild();
-// oldpc=pc;
-// oldcs=CS;
- if (msw&1)
- {
- pmodeint(1,0);
- }
- else
+ if (trap)
{
- 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 && nmi_mask)
- {
- cpu_state.oldpc = cpu_state.pc;
- oldcs = CS;
-// pclog("NMI\n");
- x86_int(2);
- nmi_enable = 0;
- if (nmi_auto_clear)
- {
- nmi_auto_clear = 0;
- nmi = 0;
- }
- }
- else if ((flags&I_FLAG) && pic_intpending)
- {
- temp=picinterrupt();
- if (temp!=0xFF)
- {
-// pclog("IRQ %02X %04X:%04X %04X:%04X\n", temp, SS, SP, CS, pc);
- CPU_BLOCK_END();
+ trap = 0;
flags_rebuild();
if (msw&1)
{
- pmodeint(temp,0);
+ pmodeint(1,0);
}
else
{
- writememw(ss,(SP-2)&0xFFFF,flags);
+ writememw(ss,(SP-2)&0xFFFF,cpu_state.flags);
writememw(ss,(SP-4)&0xFFFF,CS);
writememw(ss,(SP-6)&0xFFFF,cpu_state.pc);
SP-=6;
- addr=temp<<2;
- flags&=~I_FLAG;
- flags&=~T_FLAG;
- oxpc=cpu_state.pc;
+ addr = (1 << 2) + idt.base;
+ cpu_state.flags &= ~I_FLAG;
+ cpu_state.flags &= ~T_FLAG;
cpu_state.pc=readmemw(0,addr);
loadcs(readmemw(0,addr+2));
}
}
+ else if (nmi && nmi_enable && nmi_mask)
+ {
+ cpu_state.oldpc = cpu_state.pc;
+// pclog("NMI\n");
+ x86_int(2);
+ nmi_enable = 0;
+ if (nmi_auto_clear)
+ {
+ nmi_auto_clear = 0;
+ nmi = 0;
+ }
+ }
+ else if ((cpu_state.flags & I_FLAG) && pic_intpending)
+ {
+ temp=picinterrupt();
+ if (temp!=0xFF)
+ {
+// pclog("IRQ %02X %04X:%04X %04X:%04X\n", temp, SS, SP, CS, pc);
+ CPU_BLOCK_END();
+ flags_rebuild();
+ if (msw&1)
+ {
+ pmodeint(temp,0);
+ }
+ else
+ {
+ writememw(ss,(SP-2)&0xFFFF,cpu_state.flags);
+ writememw(ss,(SP-4)&0xFFFF,CS);
+ writememw(ss,(SP-6)&0xFFFF,cpu_state.pc);
+ SP-=6;
+ addr=temp<<2;
+ cpu_state.flags &= ~I_FLAG;
+ cpu_state.flags &= ~T_FLAG;
+ cpu_state.pc=readmemw(0,addr);
+ loadcs(readmemw(0,addr+2));
+ }
+ }
+ }
}
- }
- timer_end_period(cycles << TIMER_SHIFT);
+
+ if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t)tsc))
+ timer_process();
cycles_main -= (cycles_start - cycles);
}
}
--- /dev/null
+#include "ibm.h"
+#include "cpu.h"
+#include "x86.h"
+#include "x86_ops.h"
+#include "x87.h"
+#include "x86_flags.h"
+#include "mem.h"
+#include "nmi.h"
+#include "pic.h"
+#include "codegen.h"
+
+#define CPU_BLOCK_END() cpu_block_end = 1
+
+#include "386_common.h"
+
+
+static inline void fetch_ea_32_long(uint32_t rmdat)
+{
+ eal_r = eal_w = NULL;
+ easeg = cpu_state.ea_seg->base;
+ if (easeg != 0xFFFFFFFF && ((easeg + cpu_state.eaaddr) & 0xFFF) <= 0xFFC)
+ {
+ uint32_t addr = easeg + cpu_state.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 = cpu_state.ea_seg->base;
+ if (easeg != 0xFFFFFFFF && ((easeg + cpu_state.eaaddr) & 0xFFF) <= 0xFFC)
+ {
+ uint32_t addr = easeg + cpu_state.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 (cpu_mod != 3) fetch_ea_16_long(rmdat);
+#define fetch_ea_32(rmdat) cpu_state.pc++; if (cpu_mod != 3) fetch_ea_32_long(rmdat);
+
+
+#define PREFETCH_RUN(instr_cycles, bytes, modrm, reads, read_ls, writes, write_ls, ea32)
+#define PREFETCH_PREFIX()
+#define PREFETCH_FLUSH()
+
+#define OP_TABLE(name) dynarec_ops_ ## name
+/*Temporary*/
+#define CLOCK_CYCLES(c)
+#define CLOCK_CYCLES_ALWAYS(c) cycles -= (c)
+
+#include "386_ops.h"
return ret;
}
+static int ILLEGAL(uint32_t fetchdat)
+{
+ cpu_state.pc = cpu_state.oldpc;
+
+// fatal("Illegal instruction %08X\n", fetchdat);
+ x86illegal();
+ return 0;
+}
+
#include "x86_ops_arith.h"
#include "x86_ops_atomic.h"
#include "x86_ops_bcd.h"
#include "x86_ops_jump.h"
#include "x86_ops_misc.h"
#include "x86_ops_mmx.h"
+#include "x86_ops_3dnow.h"
#include "x86_ops_mmx_arith.h"
#include "x86_ops_mmx_cmp.h"
#include "x86_ops_mmx_logic.h"
#include "x86_ops_string.h"
#include "x86_ops_xchg.h"
-static int ILLEGAL(uint32_t fetchdat)
-{
- cpu_state.pc = cpu_state.oldpc;
-
-// fatal("Illegal instruction %08X\n", fetchdat);
- x86illegal();
- return 0;
-}
-
static int op0F_w_a16(uint32_t fetchdat)
{
int opcode = fetchdat & 0xff;
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
-/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ op0F00_a16, op0F01_l_a16, opLAR_l_a16, opLSL_l_a16, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
-/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ op0F00_a32, op0F01_w_a32, opLAR_w_a32, opLSL_w_a32, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
-/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ op0F00_a32, op0F01_l_a32, opLAR_l_a32, opLSL_l_a32, ILLEGAL, ILLEGAL, opCLTS, opLOADALL386, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
-/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
-/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ op0F00_a16, op0F01_l_a16, opLAR_l_a16, opLSL_l_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
-/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ op0F00_a32, op0F01_w_a32, opLAR_w_a32, opLSL_w_a32, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
-/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
/*00*/ op0F00_a32, op0F01_l_a32, opLAR_l_a32, opLSL_l_a32, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
-/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+
+/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*60*/ opPUNPCKLBW_a32,opPUNPCKLWD_a32,opPUNPCKLDQ_a32,opPACKSSWB_a32, opPCMPGTB_a32, opPCMPGTW_a32, opPCMPGTD_a32, opPACKUSWB_a32, opPUNPCKHBW_a32,opPUNPCKHWD_a32,opPUNPCKHDQ_a32,opPACKSSDW_a32, ILLEGAL, ILLEGAL, opMOVD_l_mm_a32,opMOVQ_q_mm_a32,
+/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a32, opPCMPEQW_a32, opPCMPEQD_a32, opEMMS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opMOVD_mm_l_a32,opMOVQ_mm_q_a32,
+
+/*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l,
+/*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32,
+/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a32, opSHLD_l_i_a32, opSHLD_l_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, ILLEGAL, opBTS_l_r_a32, opSHRD_l_i_a32, opSHRD_l_CL_a32,ILLEGAL, opIMUL_l_l_a32,
+/*b0*/ opCMPXCHG_b_a32,opCMPXCHG_l_a32,opLSS_l_a32, opBTR_l_r_a32, opLFS_l_a32, opLGS_l_a32, opMOVZX_l_b_a32,opMOVZX_l_w_a32,ILLEGAL, ILLEGAL, opBA_l_a32, opBTC_l_r_a32, opBSF_l_a32, opBSR_l_a32, opMOVSX_l_b_a32,opMOVSX_l_w_a32,
+
+/*c0*/ opXADD_b_a32, opXADD_l_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI,
+/*d0*/ ILLEGAL, opPSRLW_a32, opPSRLD_a32, opPSRLQ_a32, ILLEGAL, opPMULLW_a32, ILLEGAL, ILLEGAL, opPSUBUSB_a32, opPSUBUSW_a32, NULL, opPAND_a32, opPADDUSB_a32, opPADDUSW_a32, NULL, opPANDN_a32,
+/*e0*/ ILLEGAL, opPSRAW_a32, opPSRAD_a32, ILLEGAL, ILLEGAL, opPMULHW_a32, ILLEGAL, ILLEGAL, opPSUBSB_a32, opPSUBSW_a32, NULL, opPOR_a32, opPADDSB_a32, opPADDSW_a32, NULL, opPXOR_a32,
+/*f0*/ ILLEGAL, opPSLLW_a32, opPSLLD_a32, opPSLLQ_a32, ILLEGAL, opPMADDWD_a32, ILLEGAL, ILLEGAL, opPSUBB_a32, opPSUBW_a32, opPSUBD_a32, ILLEGAL, opPADDB_a32, opPADDW_a32, opPADDD_a32, ILLEGAL,
+};
+
+OpFn OP_TABLE(winchip2_0f)[1024] =
+{
+ /*16-bit data, 16-bit addr*/
+/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
+/*00*/ op0F00_a16, op0F01_w_a16, opLAR_w_a16, opLSL_w_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, opPREFETCH_a16, opFEMMS, op3DNOW_a16,
+/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+
+/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*60*/ opPUNPCKLBW_a16,opPUNPCKLWD_a16,opPUNPCKLDQ_a16,opPACKSSWB_a16, opPCMPGTB_a16, opPCMPGTW_a16, opPCMPGTD_a16, opPACKUSWB_a16, opPUNPCKHBW_a16,opPUNPCKHWD_a16,opPUNPCKHDQ_a16,opPACKSSDW_a16, ILLEGAL, ILLEGAL, opMOVD_l_mm_a16,opMOVQ_q_mm_a16,
+/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a16, opPCMPEQW_a16, opPCMPEQD_a16, opEMMS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opMOVD_mm_l_a16,opMOVQ_mm_q_a16,
+
+/*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w,
+/*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16,
+/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a16, opSHLD_w_i_a16, opSHLD_w_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, ILLEGAL, opBTS_w_r_a16, opSHRD_w_i_a16, opSHRD_w_CL_a16,ILLEGAL, opIMUL_w_w_a16,
+/*b0*/ opCMPXCHG_b_a16,opCMPXCHG_w_a16,opLSS_w_a16, opBTR_w_r_a16, opLFS_w_a16, opLGS_w_a16, opMOVZX_w_b_a16,opMOVZX_w_w_a16,ILLEGAL, ILLEGAL, opBA_w_a16, opBTC_w_r_a16, opBSF_w_a16, opBSR_w_a16, opMOVSX_w_b_a16,ILLEGAL,
+
+/*c0*/ opXADD_b_a16, opXADD_w_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI,
+/*d0*/ ILLEGAL, opPSRLW_a16, opPSRLD_a16, opPSRLQ_a16, ILLEGAL, opPMULLW_a16, ILLEGAL, ILLEGAL, opPSUBUSB_a16, opPSUBUSW_a16, NULL, opPAND_a16, opPADDUSB_a16, opPADDUSW_a16, NULL, opPANDN_a16,
+/*e0*/ ILLEGAL, opPSRAW_a16, opPSRAD_a16, ILLEGAL, ILLEGAL, opPMULHW_a16, ILLEGAL, ILLEGAL, opPSUBSB_a16, opPSUBSW_a16, NULL, opPOR_a16, opPADDSB_a16, opPADDSW_a16, NULL, opPXOR_a16,
+/*f0*/ ILLEGAL, opPSLLW_a16, opPSLLD_a16, opPSLLQ_a16, ILLEGAL, opPMADDWD_a16, ILLEGAL, ILLEGAL, opPSUBB_a16, opPSUBW_a16, opPSUBD_a16, ILLEGAL, opPADDB_a16, opPADDW_a16, opPADDD_a16, ILLEGAL,
+
+ /*32-bit data, 16-bit addr*/
+/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
+/*00*/ op0F00_a16, op0F01_l_a16, opLAR_l_a16, opLSL_l_a16, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, opPREFETCH_a16, opFEMMS, op3DNOW_a16,
+/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*20*/ opMOV_r_CRx_a16,opMOV_r_DRx_a16,opMOV_CRx_r_a16,opMOV_DRx_r_a16,opMOV_r_TRx_a16,ILLEGAL, opMOV_TRx_r_a16,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+
+/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*60*/ opPUNPCKLBW_a16,opPUNPCKLWD_a16,opPUNPCKLDQ_a16,opPACKSSWB_a16, opPCMPGTB_a16, opPCMPGTW_a16, opPCMPGTD_a16, opPACKUSWB_a16, opPUNPCKHBW_a16,opPUNPCKHWD_a16,opPUNPCKHDQ_a16,opPACKSSDW_a16, ILLEGAL, ILLEGAL, opMOVD_l_mm_a16,opMOVQ_q_mm_a16,
+/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a16, opPCMPEQW_a16, opPCMPEQD_a16, opEMMS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opMOVD_mm_l_a16,opMOVQ_mm_q_a16,
+
+/*80*/ opJO_l, opJNO_l, opJB_l, opJNB_l, opJE_l, opJNE_l, opJBE_l, opJNBE_l, opJS_l, opJNS_l, opJP_l, opJNP_l, opJL_l, opJNL_l, opJLE_l, opJNLE_l,
+/*90*/ opSETO_a16, opSETNO_a16, opSETB_a16, opSETNB_a16, opSETE_a16, opSETNE_a16, opSETBE_a16, opSETNBE_a16, opSETS_a16, opSETNS_a16, opSETP_a16, opSETNP_a16, opSETL_a16, opSETNL_a16, opSETLE_a16, opSETNLE_a16,
+/*a0*/ opPUSH_FS_l, opPOP_FS_l, opCPUID, opBT_l_r_a16, opSHLD_l_i_a16, opSHLD_l_CL_a16,ILLEGAL, ILLEGAL, opPUSH_GS_l, opPOP_GS_l, ILLEGAL, opBTS_l_r_a16, opSHRD_l_i_a16, opSHRD_l_CL_a16,ILLEGAL, opIMUL_l_l_a16,
+/*b0*/ opCMPXCHG_b_a16,opCMPXCHG_l_a16,opLSS_l_a16, opBTR_l_r_a16, opLFS_l_a16, opLGS_l_a16, opMOVZX_l_b_a16,opMOVZX_l_w_a16,ILLEGAL, ILLEGAL, opBA_l_a16, opBTC_l_r_a16, opBSF_l_a16, opBSR_l_a16, opMOVSX_l_b_a16,opMOVSX_l_w_a16,
+
+/*c0*/ opXADD_b_a16, opXADD_l_a16, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a16,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI,
+/*d0*/ ILLEGAL, opPSRLW_a16, opPSRLD_a16, opPSRLQ_a16, ILLEGAL, opPMULLW_a16, ILLEGAL, ILLEGAL, opPSUBUSB_a16, opPSUBUSW_a16, NULL, opPAND_a16, opPADDUSB_a16, opPADDUSW_a16, NULL, opPANDN_a16,
+/*e0*/ ILLEGAL, opPSRAW_a16, opPSRAD_a16, ILLEGAL, ILLEGAL, opPMULHW_a16, ILLEGAL, ILLEGAL, opPSUBSB_a16, opPSUBSW_a16, NULL, opPOR_a16, opPADDSB_a16, opPADDSW_a16, NULL, opPXOR_a16,
+/*f0*/ ILLEGAL, opPSLLW_a16, opPSLLD_a16, opPSLLQ_a16, ILLEGAL, opPMADDWD_a16, ILLEGAL, ILLEGAL, opPSUBB_a16, opPSUBW_a16, opPSUBD_a16, ILLEGAL, opPADDB_a16, opPADDW_a16, opPADDD_a16, ILLEGAL,
+
+ /*16-bit data, 32-bit addr*/
+/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
+/*00*/ op0F00_a32, op0F01_w_a32, opLAR_w_a32, opLSL_w_a32, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, opPREFETCH_a32, opFEMMS, op3DNOW_a32,
+/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+
+/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*60*/ opPUNPCKLBW_a32,opPUNPCKLWD_a32,opPUNPCKLDQ_a32,opPACKSSWB_a32, opPCMPGTB_a32, opPCMPGTW_a32, opPCMPGTD_a32, opPACKUSWB_a32, opPUNPCKHBW_a32,opPUNPCKHWD_a32,opPUNPCKHDQ_a32,opPACKSSDW_a32, ILLEGAL, ILLEGAL, opMOVD_l_mm_a32,opMOVQ_q_mm_a32,
+/*70*/ ILLEGAL, opPSxxW_imm, opPSxxD_imm, opPSxxQ_imm, opPCMPEQB_a32, opPCMPEQW_a32, opPCMPEQD_a32, opEMMS, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opMOVD_mm_l_a32,opMOVQ_mm_q_a32,
+
+/*80*/ opJO_w, opJNO_w, opJB_w, opJNB_w, opJE_w, opJNE_w, opJBE_w, opJNBE_w, opJS_w, opJNS_w, opJP_w, opJNP_w, opJL_w, opJNL_w, opJLE_w, opJNLE_w,
+/*90*/ opSETO_a32, opSETNO_a32, opSETB_a32, opSETNB_a32, opSETE_a32, opSETNE_a32, opSETBE_a32, opSETNBE_a32, opSETS_a32, opSETNS_a32, opSETP_a32, opSETNP_a32, opSETL_a32, opSETNL_a32, opSETLE_a32, opSETNLE_a32,
+/*a0*/ opPUSH_FS_w, opPOP_FS_w, opCPUID, opBT_w_r_a32, opSHLD_w_i_a32, opSHLD_w_CL_a32,ILLEGAL, ILLEGAL, opPUSH_GS_w, opPOP_GS_w, ILLEGAL, opBTS_w_r_a32, opSHRD_w_i_a32, opSHRD_w_CL_a32,ILLEGAL, opIMUL_w_w_a32,
+/*b0*/ opCMPXCHG_b_a32,opCMPXCHG_w_a32,opLSS_w_a32, opBTR_w_r_a32, opLFS_w_a32, opLGS_w_a32, opMOVZX_w_b_a32,opMOVZX_w_w_a32,ILLEGAL, ILLEGAL, opBA_w_a32, opBTC_w_r_a32, opBSF_w_a32, opBSR_w_a32, opMOVSX_w_b_a32,ILLEGAL,
+
+/*c0*/ opXADD_b_a32, opXADD_w_a32, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opCMPXCHG8B_a32,opBSWAP_EAX, opBSWAP_ECX, opBSWAP_EDX, opBSWAP_EBX, opBSWAP_ESP, opBSWAP_EBP, opBSWAP_ESI, opBSWAP_EDI,
+/*d0*/ ILLEGAL, opPSRLW_a32, opPSRLD_a32, opPSRLQ_a32, ILLEGAL, opPMULLW_a32, ILLEGAL, ILLEGAL, opPSUBUSB_a32, opPSUBUSW_a32, NULL, opPAND_a32, opPADDUSB_a32, opPADDUSW_a32, NULL, opPANDN_a32,
+/*e0*/ ILLEGAL, opPSRAW_a32, opPSRAD_a32, ILLEGAL, ILLEGAL, opPMULHW_a32, ILLEGAL, ILLEGAL, opPSUBSB_a32, opPSUBSW_a32, NULL, opPOR_a32, opPADDSB_a32, opPADDSW_a32, NULL, opPXOR_a32,
+/*f0*/ ILLEGAL, opPSLLW_a32, opPSLLD_a32, opPSLLQ_a32, ILLEGAL, opPMADDWD_a32, ILLEGAL, ILLEGAL, opPSUBB_a32, opPSUBW_a32, opPSUBD_a32, ILLEGAL, opPADDB_a32, opPADDW_a32, opPADDD_a32, ILLEGAL,
+
+ /*32-bit data, 32-bit addr*/
+/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
+/*00*/ op0F00_a32, op0F01_l_a32, opLAR_l_a32, opLSL_l_a32, ILLEGAL, ILLEGAL, opCLTS, ILLEGAL, opINVD, opWBINVD, ILLEGAL, ILLEGAL, ILLEGAL, opPREFETCH_a32, opFEMMS, op3DNOW_a32,
+/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*20*/ opMOV_r_CRx_a32,opMOV_r_DRx_a32,opMOV_CRx_r_a32,opMOV_DRx_r_a32,opMOV_r_TRx_a32,ILLEGAL, opMOV_TRx_r_a32,ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*30*/ opWRMSR, opRDTSC, opRDMSR, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
/*f0*/ ILLEGAL, opPSLLW_a32, opPSLLD_a32, opPSLLQ_a32, ILLEGAL, opPMADDWD_a32, ILLEGAL, ILLEGAL, opPSUBB_a32, opPSUBW_a32, opPSUBD_a32, ILLEGAL, opPADDB_a32, opPADDW_a32, opPADDD_a32, ILLEGAL,
};
-OpFn OP_TABLE(pentium_0f)[1024] =
+OpFn OP_TABLE(pentium_0f)[1024] =
{
/*16-bit data, 16-bit addr*/
/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
--- /dev/null
+/*This file is a series of macros to get the 386+ based x87 emulation working with
+ the 808x emulation*/
+#define X8087
+#define OP_TABLE(name) ops_808x_ ## name
+
+#define CLOCK_CYCLES(c) cycles -= (c)
+#define CLOCK_CYCLES_ALWAYS(c) cycles -= (c)
+
+#define fetch_ea_16(fetchdat)
+#define fetch_ea_32(fetchdat)
+#define SEG_CHECK_READ(seg)
+#define SEG_CHECK_WRITE(seg)
+#define CHECK_WRITE(seg, addr_lo, addr_hi)
+#define PREFETCH_RUN(timing, bytes, rmdat, a, b, c, d, e)
+
+static uint32_t readmeml(uint32_t seg, uint32_t addr)
+{
+ return readmemw(seg, addr) | (readmemw(seg, addr+2) << 16);
+}
+static uint64_t readmemq(uint32_t seg, uint32_t addr)
+{
+ return (uint64_t)readmemw(seg, addr) | ((uint64_t)readmemw(seg, addr+2) << 16) |
+ ((uint64_t)readmemw(seg, addr+4) << 32) |
+ ((uint64_t)readmemw(seg, addr+6) << 48);
+}
+
+static void writememb_8087(uint32_t seg, uint32_t addr, uint8_t val)
+{
+ writememb(seg+addr, val);
+}
+static void writememl(uint32_t seg, uint32_t addr, uint32_t val)
+{
+ writememw(seg, addr, val & 0xffff);
+ writememw(seg, addr+2, (val >> 16) & 0xffff);
+}
+static void writememq(uint32_t seg, uint32_t addr, uint64_t val)
+{
+ writememw(seg, addr, val & 0xffff);
+ writememw(seg, addr+2, (val >> 16) & 0xffff);
+ writememw(seg, addr+4, (val >> 32) & 0xffff);
+ writememw(seg, addr+6, (val >> 48) & 0xffff);
+}
+
+static inline uint32_t geteal()
+{
+ if (cpu_mod == 3)
+ fatal("geteal cpu_mod==3\n");
+ return readmeml(easeg, cpu_state.eaaddr);
+}
+static inline uint64_t geteaq()
+{
+ if (cpu_mod == 3)
+ fatal("geteaq cpu_mod==3\n");
+ return readmemq(easeg, cpu_state.eaaddr);
+}
+static inline void seteal(uint32_t val)
+{
+ if (cpu_mod == 3)
+ fatal("seteal cpu_mod==3\n");
+ else
+ writememl(easeg, cpu_state.eaaddr, val);
+}
+static inline void seteaq(uint64_t val)
+{
+ if (cpu_mod == 3)
+ fatal("seteaq cpu_mod==3\n");
+ else
+ writememq(easeg, cpu_state.eaaddr, val);
+}
+
+#define flags_rebuild()
+
+#define CF_SET() (cpu_state.flags & C_FLAG)
+#define NF_SET() (cpu_state.flags & N_FLAG)
+#define PF_SET() (cpu_state.flags & P_FLAG)
+#define VF_SET() (cpu_state.flags & V_FLAG)
+#define ZF_SET() (cpu_state.flags & Z_FLAG)
+
+#define cond_O ( VF_SET())
+#define cond_NO (!VF_SET())
+#define cond_B ( CF_SET())
+#define cond_NB (!CF_SET())
+#define cond_E ( ZF_SET())
+#define cond_NE (!ZF_SET())
+#define cond_BE ( CF_SET() || ZF_SET())
+#define cond_NBE (!CF_SET() && !ZF_SET())
+#define cond_S ( NF_SET())
+#define cond_NS (!NF_SET())
+#define cond_P ( PF_SET())
+#define cond_NP (!PF_SET())
+#define cond_L (((NF_SET()) ? 1 : 0) != ((VF_SET()) ? 1 : 0))
+#define cond_NL (((NF_SET()) ? 1 : 0) == ((VF_SET()) ? 1 : 0))
+#define cond_LE (((NF_SET()) ? 1 : 0) != ((VF_SET()) ? 1 : 0) || (ZF_SET()))
+#define cond_NLE (((NF_SET()) ? 1 : 0) == ((VF_SET()) ? 1 : 0) && (!ZF_SET()))
+
+#define writememb writememb_8087
+#include "x87_ops.h"
+#undef writememb
#include "x87.h"
#include "paths.h"
-int xt_cpu_multi;
+uint64_t xt_cpu_multi;
int nmi = 0;
int nmi_auto_clear = 0;
-int nextcyc=0;
-int cycdiff;
+int oldcpl;
+
+int tempc;
+static int noint=0;
+
+int output=0;
+int timetolive=0;
+int ins=0;
+
int is8086=0;
-int memcycs;
-int nopageerrors=0;
+static uint32_t oldds;
+uint32_t oldss;
-void FETCHCOMPLETE();
+static int nextcyc=0;
+static int memcycs;
-uint8_t readmembl(uint32_t addr);
-void writemembl(uint32_t addr, uint8_t val);
-uint16_t readmemwl(uint32_t seg, uint32_t addr);
-void writememwl(uint32_t seg, uint32_t addr, uint16_t val);
-uint32_t readmemll(uint32_t seg, uint32_t addr);
-void writememll(uint32_t seg, uint32_t addr, uint32_t val);
+static int cycdiff;
+static void FETCHCOMPLETE();
-#undef readmemb
-#undef readmemw
-uint8_t readmemb(uint32_t a)
+#define IRQTEST ((cpu_state.flags & I_FLAG) && (pic.pend&~pic.mask) && !noint)
+
+static uint8_t readmemb(uint32_t a)
{
if (a!=(cs+cpu_state.pc)) memcycs+=4;
if (readlookup2[(a)>>12]==-1) return readmembl(a);
else return *(uint8_t *)(readlookup2[(a) >> 12] + (a));
}
-uint8_t readmembf(uint32_t a)
+static uint8_t readmembf(uint32_t a)
{
if (readlookup2[(a)>>12]==-1) return readmembl(a);
else return *(uint8_t *)(readlookup2[(a) >> 12] + (a));
}
-uint16_t readmemw(uint32_t s, uint16_t a)
+static uint16_t readmemw(uint32_t s, uint16_t a)
{
if (a!=(cs+cpu_state.pc)) memcycs+=(8>>is8086);
- if ((readlookup2[((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF)) return readmemwl(s,a);
+ if ((readlookup2[((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF)) return readmemwl(s+a);
else return *(uint16_t *)(readlookup2[(s + a) >> 12] + s + a);
}
cpu_rm=rmdat&7; \
if (cpu_mod!=3) fetcheal(); }
-void writemembl(uint32_t addr, uint8_t val);
-void writememb(uint32_t a, uint8_t v)
+static void writememb(uint32_t a, uint8_t v)
{
memcycs+=4;
if (writelookup2[(a)>>12]==-1) writemembl(a,v);
else *(uint8_t *)(writelookup2[a >> 12] + a) = v;
}
-void writememwl(uint32_t seg, uint32_t addr, uint16_t val);
-void writememw(uint32_t s, uint32_t a, uint16_t v)
+static void writememw(uint32_t s, uint32_t a, uint16_t v)
{
memcycs+=(8>>is8086);
- if (writelookup2[((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF) writememwl(s,a,v);
+ if (writelookup2[((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF) writememwl(s+a,v);
else *(uint16_t *)(writelookup2[(s + a) >> 12] + s + a) = v;
}
-void writememll(uint32_t seg, uint32_t addr, uint32_t val);
-void writememl(uint32_t s, uint32_t a, uint32_t v)
-{
- if (writelookup2[((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF) writememll(s,a,v);
- else *(uint32_t *)(writelookup2[(s + a) >> 12] + s + a) = v;
-}
-
-uint16_t oldcs;
-int oldcpl;
-
-int tempc;
-uint8_t opcode;
-uint16_t pc2,pc3;
-int noint=0;
-int output=0;
-
-extern int shadowbios;
-
-int ins=0;
//#define readmemb(a) (((a)<0xA0000)?ram[a]:readmembl(a))
-int fetchcycles=0,fetchclocks;
+static int fetchcycles=0,fetchclocks;
+
+static uint8_t prefetchqueue[6];
+static uint16_t prefetchpc;
+static int prefetchw=0;
-uint8_t prefetchqueue[6];
-uint16_t prefetchpc;
-int prefetchw=0;
static inline uint8_t FETCH()
{
uint8_t temp;
// if (fetchcycles>24) fetchcycles=24;
}
-void FETCHCOMPLETE()
+static void FETCHCOMPLETE()
{
// pclog("Fetchcomplete %i %i %i\n",fetchcycles&3,fetchcycles,prefetchw);
if (!(fetchcycles&3)) return;
*/
uint32_t easeg;
-int rmdat;
+uint32_t rmdat;
-uint16_t zero=0;
+static uint16_t zero=0;
uint16_t *mod1add[2][8];
uint32_t *mod1seg[8];
/*Flags*/
uint8_t znptable8[256];
-uint16_t znptable16[65536];
+static uint16_t znptable16[65536];
void makeznptable()
{
// makemod1table();
}
-int timetolive=0;
-
-extern uint32_t oldcs2;
-extern uint32_t oldpc2;
int indump = 0;
void dumpregs()
{
-#if 0
int c,d=0,e=0;
#ifndef RELEASE_BUILD
FILE *f;
// savenvr();
// return;
chdir(logs_path);
- nopageerrors=1;
/* f=fopen("rram3.dmp","wb");
for (c=0;c<0x8000000;c++) putc(readmemb(c+0x10000000),f);
fclose(f);*/
fclose(f);*/
pclog("Dumping rram4.dmp\n");
f=fopen("rram4.dmp","wb");
- for (c=0;c<0x0050000;c++)
+ for (c=0;c<0x0050000;c++)
{
cpu_state.abrt = 0;
- putc(readmemb386l(0,c+0x80000000),f);
+ putc(readmembl(c+0x80000000),f);
}
fclose(f);
pclog("Dumping done\n");
printf("EAX=%08X EBX=%08X ECX=%08X EDX=%08X\nEDI=%08X ESI=%08X EBP=%08X ESP=%08X\n",EAX,EBX,ECX,EDX,EDI,ESI,EBP,ESP);
else
printf("AX=%04X BX=%04X CX=%04X DX=%04X DI=%04X SI=%04X BP=%04X SP=%04X\n",AX,BX,CX,DX,DI,SI,BP,SP);
- printf("PC=%04X CS=%04X DS=%04X ES=%04X SS=%04X FLAGS=%04X\n",cpu_state.pc,CS,DS,ES,SS,flags);
- printf("%04X:%04X %04X:%04X\n",oldcs,cpu_state.oldpc, oldcs2, oldpc2);
+ printf("PC=%04X CS=%04X DS=%04X ES=%04X SS=%04X FLAGS=%04X\n",cpu_state.pc,CS,DS,ES,SS,cpu_state.flags);
+ printf("%04X\n",cpu_state.oldpc);
printf("%i ins\n",ins);
if (is386)
- printf("In %s mode\n",(msw&1)?((eflags&VM_FLAG)?"V86":"protected"):"real");
+ printf("In %s mode\n",(msw&1)?((cpu_state.eflags&VM_FLAG)?"V86":"protected"):"real");
else
printf("In %s mode\n",(msw&1)?"protected":"real");
- printf("CS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",cs,_cs.limit,_cs.access, _cs.limit_low, _cs.limit_high);
- printf("DS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",ds,_ds.limit,_ds.access, _ds.limit_low, _ds.limit_high);
- printf("ES : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",es,_es.limit,_es.access, _es.limit_low, _es.limit_high);
+ printf("CS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",cs,cpu_state.seg_cs.limit,cpu_state.seg_cs.access, cpu_state.seg_cs.limit_low, cpu_state.seg_cs.limit_high);
+ printf("DS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",ds,cpu_state.seg_ds.limit,cpu_state.seg_ds.access, cpu_state.seg_ds.limit_low, cpu_state.seg_ds.limit_high);
+ printf("ES : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",es,cpu_state.seg_es.limit,cpu_state.seg_es.access, cpu_state.seg_es.limit_low, cpu_state.seg_es.limit_high);
if (is386)
{
- printf("FS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",seg_fs,_fs.limit,_fs.access, _fs.limit_low, _fs.limit_high);
- printf("GS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",gs,_gs.limit,_gs.access, _gs.limit_low, _gs.limit_high);
+ printf("FS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",cpu_state.seg_fs.base,cpu_state.seg_fs.limit,cpu_state.seg_fs.access, cpu_state.seg_fs.limit_low, cpu_state.seg_fs.limit_high);
+ printf("GS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",gs,cpu_state.seg_gs.limit,cpu_state.seg_gs.access, cpu_state.seg_gs.limit_low, cpu_state.seg_gs.limit_high);
}
- printf("SS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",ss,_ss.limit,_ss.access, _ss.limit_low, _ss.limit_high);
+ printf("SS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",ss,cpu_state.seg_ss.limit,cpu_state.seg_ss.access, cpu_state.seg_ss.limit_low, cpu_state.seg_ss.limit_high);
printf("GDT : base=%06X limit=%04X\n",gdt.base,gdt.limit);
printf("LDT : base=%06X limit=%04X\n",ldt.base,ldt.limit);
printf("IDT : base=%06X limit=%04X\n",idt.base,idt.limit);
printf("Entries in readlookup : %i writelookup : %i\n",d,e);
x87_dumpregs();
indump = 0;
-#endif
}
-int resets = 0;
int x86_was_reset = 0;
void resetx86()
{
pclog("x86 reset\n");
- resets++;
ins = 0;
use32=0;
cpu_cur_status = 0;
stack32=0;
- cpu_hasCX8 = 0;
// i86_Reset();
// cs=0xFFFF0;
msw=0;
cpu_cache_int_enabled = 0;
cpu_update_waitstates();
cr4 = 0;
- eflags=0;
+ cpu_state.eflags=0;
cgate32=0;
if (AT)
{
}
idt.base = 0;
idt.limit = is386 ? 0x03FF : 0xFFFF;
- flags=2;
+ cpu_state.flags=2;
+ EAX = EBX = ECX = EDX = ESI = EDI = EBP = ESP = 0;
makeznptable();
resetreadlookup();
makemod1table();
FETCHCLEAR();
x87_reset();
cpu_set_edx();
- EAX = 0;
- ESP=0;
mmu_perm=4;
- memset(inscounts, 0, sizeof(inscounts));
x86seg_reset();
codegen_reset();
x86_was_reset = 1;
cpu_cache_int_enabled = 0;
cpu_update_waitstates();
cr4 = 0;
- eflags=0;
+ cpu_state.eflags=0;
cgate32=0;
- cpu_hasCX8 = 0;
if (AT)
{
loadcs(0xF000);
rammask = 0xfffff;
}
//rammask=0xFFFFFFFF;
- flags=2;
+ cpu_state.flags=2;
idt.base = 0;
- idt.limit = is386 ? 0x03FF : 0xFFFF;
+ if (is386)
+ {
+ idt.limit = 0x03FF;
+ EAX = EBX = ECX = EDX = ESI = EDI = EBP = ESP = 0;
+ }
+ else
+ {
+ idt.limit = 0xFFFF;
+ }
x86seg_reset();
+ flushmmucache();
x86_was_reset = 1;
+ FETCHCLEAR();
}
static void setznp8(uint8_t val)
{
- flags&=~0xC4;
- flags|=znptable8[val];
+ cpu_state.flags &= ~0xC4;
+ cpu_state.flags |= znptable8[val];
}
static void setznp16(uint16_t val)
{
- flags&=~0xC4;
- flags|=znptable16[val];
+ cpu_state.flags &= ~0xC4;
+ cpu_state.flags |= znptable16[val];
}
static void setadd8(uint8_t a, uint8_t b)
{
- uint16_t c=(uint16_t)a+(uint16_t)b;
- flags&=~0x8D5;
- flags|=znptable8[c&0xFF];
- if (c&0x100) flags|=C_FLAG;
- if (!((a^b)&0x80)&&((a^c)&0x80)) flags|=V_FLAG;
- if (((a&0xF)+(b&0xF))&0x10) flags|=A_FLAG;
+ uint16_t c = (uint16_t)a + (uint16_t)b;
+ cpu_state.flags &= ~0x8D5;
+ cpu_state.flags |= znptable8[c&0xFF];
+ if (c & 0x100)
+ cpu_state.flags |= C_FLAG;
+ if (!((a ^ b) & 0x80) && ((a ^ c) & 0x80))
+ cpu_state.flags |= V_FLAG;
+ if (((a & 0xF) + (b & 0xF)) & 0x10)
+ cpu_state.flags |= A_FLAG;
}
static void setadd8nc(uint8_t a, uint8_t b)
{
- uint16_t c=(uint16_t)a+(uint16_t)b;
- flags&=~0x8D4;
- flags|=znptable8[c&0xFF];
- if (!((a^b)&0x80)&&((a^c)&0x80)) flags|=V_FLAG;
- if (((a&0xF)+(b&0xF))&0x10) flags|=A_FLAG;
+ uint16_t c = (uint16_t)a + (uint16_t)b;
+ cpu_state.flags &= ~0x8D4;
+ cpu_state.flags |= znptable8[c&0xFF];
+ if (!((a ^ b) & 0x80) && ((a ^ c) & 0x80))
+ cpu_state.flags |= V_FLAG;
+ if (((a & 0xF) + (b & 0xF)) & 0x10)
+ cpu_state.flags |= A_FLAG;
}
static void setadc8(uint8_t a, uint8_t b)
{
- uint16_t c=(uint16_t)a+(uint16_t)b+tempc;
- flags&=~0x8D5;
- flags|=znptable8[c&0xFF];
- if (c&0x100) flags|=C_FLAG;
- if (!((a^b)&0x80)&&((a^c)&0x80)) flags|=V_FLAG;
- if (((a&0xF)+(b&0xF))&0x10) flags|=A_FLAG;
+ uint16_t c = (uint16_t)a + (uint16_t)b+tempc;
+ cpu_state.flags &= ~0x8D5;
+ cpu_state.flags |= znptable8[c&0xFF];
+ if (c & 0x100)
+ cpu_state.flags |= C_FLAG;
+ if (!((a ^ b) & 0x80) && ((a ^ c) & 0x80))
+ cpu_state.flags |= V_FLAG;
+ if (((a & 0xF) + (b & 0xF)) & 0x10)
+ cpu_state.flags |= A_FLAG;
}
static void setadd16(uint16_t a, uint16_t b)
{
- uint32_t c=(uint32_t)a+(uint32_t)b;
- flags&=~0x8D5;
- flags|=znptable16[c&0xFFFF];
- if (c&0x10000) flags|=C_FLAG;
- if (!((a^b)&0x8000)&&((a^c)&0x8000)) flags|=V_FLAG;
- if (((a&0xF)+(b&0xF))&0x10) flags|=A_FLAG;
+ uint32_t c = (uint32_t)a + (uint32_t)b;
+ cpu_state.flags &= ~0x8D5;
+ cpu_state.flags |= znptable16[c&0xFFFF];
+ if (c & 0x10000)
+ cpu_state.flags |= C_FLAG;
+ if (!((a ^ b) & 0x8000) && ((a ^ c) & 0x8000))
+ cpu_state.flags |= V_FLAG;
+ if (((a & 0xF) + (b & 0xF)) & 0x10)
+ cpu_state.flags |= A_FLAG;
}
static void setadd16nc(uint16_t a, uint16_t b)
{
- uint32_t c=(uint32_t)a+(uint32_t)b;
- flags&=~0x8D4;
- flags|=znptable16[c&0xFFFF];
- if (!((a^b)&0x8000)&&((a^c)&0x8000)) flags|=V_FLAG;
- if (((a&0xF)+(b&0xF))&0x10) flags|=A_FLAG;
+ uint32_t c = (uint32_t)a + (uint32_t)b;
+ cpu_state.flags &= ~0x8D4;
+ cpu_state.flags |= znptable16[c&0xFFFF];
+ if (!((a ^ b) & 0x8000) && ((a ^ c) & 0x8000))
+ cpu_state.flags |= V_FLAG;
+ if (((a & 0xF) + (b & 0xF)) & 0x10)
+ cpu_state.flags |= A_FLAG;
}
static void setadc16(uint16_t a, uint16_t b)
{
- uint32_t c=(uint32_t)a+(uint32_t)b+tempc;
- flags&=~0x8D5;
- flags|=znptable16[c&0xFFFF];
- if (c&0x10000) flags|=C_FLAG;
- if (!((a^b)&0x8000)&&((a^c)&0x8000)) flags|=V_FLAG;
- if (((a&0xF)+(b&0xF))&0x10) flags|=A_FLAG;
+ uint32_t c = (uint32_t)a + (uint32_t)b+tempc;
+ cpu_state.flags &= ~0x8D5;
+ cpu_state.flags |= znptable16[c&0xFFFF];
+ if (c & 0x10000)
+ cpu_state.flags |= C_FLAG;
+ if (!((a ^ b) & 0x8000) && ((a ^ c) & 0x8000))
+ cpu_state.flags |= V_FLAG;
+ if (((a & 0xF) + (b & 0xF)) & 0x10)
+ cpu_state.flags |= A_FLAG;
}
static void setsub8(uint8_t a, uint8_t b)
{
- uint16_t c=(uint16_t)a-(uint16_t)b;
- flags&=~0x8D5;
- flags|=znptable8[c&0xFF];
- if (c&0x100) flags|=C_FLAG;
- if ((a^b)&(a^c)&0x80) flags|=V_FLAG;
- if (((a&0xF)-(b&0xF))&0x10) flags|=A_FLAG;
+ uint16_t c = (uint16_t)a - (uint16_t)b;
+ cpu_state.flags &= ~0x8D5;
+ cpu_state.flags |= znptable8[c&0xFF];
+ if (c & 0x100)
+ cpu_state.flags |= C_FLAG;
+ if ((a ^ b) & (a ^ c) & 0x80)
+ cpu_state.flags |= V_FLAG;
+ if (((a & 0xF) - (b & 0xF)) & 0x10)
+ cpu_state.flags |= A_FLAG;
}
static void setsub8nc(uint8_t a, uint8_t b)
{
- uint16_t c=(uint16_t)a-(uint16_t)b;
- flags&=~0x8D4;
- flags|=znptable8[c&0xFF];
- if ((a^b)&(a^c)&0x80) flags|=V_FLAG;
- if (((a&0xF)-(b&0xF))&0x10) flags|=A_FLAG;
+ uint16_t c = (uint16_t)a - (uint16_t)b;
+ cpu_state.flags &= ~0x8D4;
+ cpu_state.flags |= znptable8[c&0xFF];
+ if ((a ^ b) & (a ^ c) & 0x80)
+ cpu_state.flags |= V_FLAG;
+ if (((a & 0xF) - (b & 0xF)) & 0x10)
+ cpu_state.flags |= A_FLAG;
}
static void setsbc8(uint8_t a, uint8_t b)
{
- uint16_t c=(uint16_t)a-(((uint16_t)b)+tempc);
- flags&=~0x8D5;
- flags|=znptable8[c&0xFF];
- if (c&0x100) flags|=C_FLAG;
- if ((a^b)&(a^c)&0x80) flags|=V_FLAG;
- if (((a&0xF)-(b&0xF))&0x10) flags|=A_FLAG;
+ uint16_t c = (uint16_t)a - (((uint16_t)b) + tempc);
+ cpu_state.flags &= ~0x8D5;
+ cpu_state.flags |= znptable8[c&0xFF];
+ if (c & 0x100)
+ cpu_state.flags |= C_FLAG;
+ if ((a ^ b) & (a ^ c) & 0x80)
+ cpu_state.flags |= V_FLAG;
+ if (((a & 0xF) - (b & 0xF)) & 0x10)
+ cpu_state.flags |= A_FLAG;
}
static void setsub16(uint16_t a, uint16_t b)
{
- uint32_t c=(uint32_t)a-(uint32_t)b;
- flags&=~0x8D5;
- flags|=znptable16[c&0xFFFF];
- if (c&0x10000) flags|=C_FLAG;
- if ((a^b)&(a^c)&0x8000) flags|=V_FLAG;
-// if (output) printf("%04X %04X %i\n",a^b,a^c,flags&V_FLAG);
- if (((a&0xF)-(b&0xF))&0x10) flags|=A_FLAG;
+ uint32_t c = (uint32_t)a - (uint32_t)b;
+ cpu_state.flags &= ~0x8D5;
+ cpu_state.flags |= znptable16[c&0xFFFF];
+ if (c & 0x10000)
+ cpu_state.flags |= C_FLAG;
+ if ((a ^ b) & (a ^ c) & 0x8000)
+ cpu_state.flags |= V_FLAG;
+ if (((a & 0xF) - (b & 0xF)) & 0x10)
+ cpu_state.flags |= A_FLAG;
}
static void setsub16nc(uint16_t a, uint16_t b)
{
- uint32_t c=(uint32_t)a-(uint32_t)b;
- flags&=~0x8D4;
- flags|=(znptable16[c&0xFFFF]&~4);
- flags|=(znptable8[c&0xFF]&4);
- if ((a^b)&(a^c)&0x8000) flags|=V_FLAG;
- if (((a&0xF)-(b&0xF))&0x10) flags|=A_FLAG;
+ uint32_t c = (uint32_t)a - (uint32_t)b;
+ cpu_state.flags &= ~0x8D4;
+ cpu_state.flags |= (znptable16[c&0xFFFF]&~4);
+ cpu_state.flags |= (znptable8[c&0xFF]&4);
+ if ((a ^ b) & (a ^ c) & 0x8000)
+ cpu_state.flags |= V_FLAG;
+ if (((a & 0xF) - (b & 0xF)) & 0x10)
+ cpu_state.flags |= A_FLAG;
}
static void setsbc16(uint16_t a, uint16_t b)
{
- uint32_t c=(uint32_t)a-(((uint32_t)b)+tempc);
- flags&=~0x8D5;
- flags|=(znptable16[c&0xFFFF]&~4);
- flags|=(znptable8[c&0xFF]&4);
- if (c&0x10000) flags|=C_FLAG;
- if ((a^b)&(a^c)&0x8000) flags|=V_FLAG;
- if (((a&0xF)-(b&0xF))&0x10) flags|=A_FLAG;
+ uint32_t c = (uint32_t)a - (((uint32_t)b) + tempc);
+ cpu_state.flags &= ~0x8D5;
+ cpu_state.flags |= (znptable16[c&0xFFFF]&~4);
+ cpu_state.flags |= (znptable8[c&0xFF]&4);
+ if (c & 0x10000)
+ cpu_state.flags |= C_FLAG;
+ if ((a ^ b) & (a ^ c) & 0x8000)
+ cpu_state.flags |= V_FLAG;
+ if (((a & 0xF) - (b & 0xF)) & 0x10)
+ cpu_state.flags |= A_FLAG;
}
int current_diff = 0;
-void clockhardware()
+
+/*XT systems use the XT master oscillator (14.318 MHz) rather than the CPU clock
+ at the base timer frequency. Because there isn't an integer relationship
+ between the two frequencies, use fixed point arithmetic when updating TSC.*/
+static uint64_t tsc_frac = 0;
+
+static void clockhardware()
{
int diff = cycdiff - cycles - current_diff;
current_diff += diff;
-
- timer_end_period(cycles*xt_cpu_multi);
+
+ tsc_frac += (uint64_t)diff * xt_cpu_multi;
+
+ tsc += (tsc_frac >> 32);
+ tsc_frac &= 0xffffffff;
+ if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t)tsc))
+ timer_process();
}
static int takeint = 0;
int firstrepcycle=1;
-void rep(int fv)
+static void rep(int fv)
{
uint8_t temp;
int c=CX;
{
temp2=readmemb(ds+SI);
outb(DX,temp2);
- if (flags&D_FLAG) SI--;
- else SI++;
+ if (cpu_state.flags & D_FLAG) SI--;
+ else SI++;
c--;
cycles-=5;
}
temp2=readmemb(ds+SI);
writememb(es+DI,temp2);
// if (output) printf("Moved %02X from %04X:%04X to %04X:%04X\n",temp2,ds>>4,SI,es>>4,DI);
- if (flags&D_FLAG) { DI--; SI--; }
- else { DI++; SI++; }
+ if (cpu_state.flags & D_FLAG) { DI--; SI--; }
+ else { DI++; SI++; }
c--;
cycles-=17;
clockhardware();
memcycs=0;
tempw=readmemw(ds,SI);
writememw(es,DI,tempw);
- if (flags&D_FLAG) { DI-=2; SI-=2; }
- else { DI+=2; SI+=2; }
+ if (cpu_state.flags & D_FLAG) { DI-=2; SI-=2; }
+ else { DI+=2; SI+=2; }
c--;
cycles-=17;
clockhardware();
// }
break;
case 0xA6: /*REP CMPSB*/
- if (fv) flags|=Z_FLAG;
- else flags&=~Z_FLAG;
- while ((c>0) && (fv==((flags&Z_FLAG)?1:0)) && !IRQTEST)
+ if (fv) cpu_state.flags |= Z_FLAG;
+ else cpu_state.flags &= ~Z_FLAG;
+ while ((c>0) && (fv==((cpu_state.flags & Z_FLAG)?1:0)) && !IRQTEST)
{
memcycs=0;
temp=readmemb(ds+SI);
temp2=readmemb(es+DI);
// printf("CMPSB %c %c %i %05X %05X %04X:%04X\n",temp,temp2,c,ds+SI,es+DI,cs>>4,pc);
- if (flags&D_FLAG) { DI--; SI--; }
- else { DI++; SI++; }
+ if (cpu_state.flags & D_FLAG) { DI--; SI--; }
+ else { DI++; SI++; }
c--;
cycles -= 30;
setsub8(temp,temp2);
clockhardware();
FETCHADD(30 - memcycs);
}
- if (IRQTEST && c>0 && (fv==((flags&Z_FLAG)?1:0))) cpu_state.pc=ipc;
+ if (IRQTEST && c>0 && (fv==((cpu_state.flags & Z_FLAG)?1:0))) cpu_state.pc=ipc;
// if ((c>0) && (fv==((flags&Z_FLAG)?1:0))) { pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; FETCHCLEAR(); }
// else firstrepcycle=1;
break;
case 0xA7: /*REP CMPSW*/
- if (fv) flags|=Z_FLAG;
- else flags&=~Z_FLAG;
- while ((c>0) && (fv==((flags&Z_FLAG)?1:0)) && !IRQTEST)
+ if (fv) cpu_state.flags |= Z_FLAG;
+ else cpu_state.flags &= ~Z_FLAG;
+ while ((c>0) && (fv==((cpu_state.flags & Z_FLAG)?1:0)) && !IRQTEST)
{
memcycs=0;
tempw=readmemw(ds,SI);
tempw2=readmemw(es,DI);
- if (flags&D_FLAG) { DI-=2; SI-=2; }
- else { DI+=2; SI+=2; }
+ if (cpu_state.flags & D_FLAG) { DI-=2; SI-=2; }
+ else { DI+=2; SI+=2; }
c--;
cycles -= 30;
setsub16(tempw,tempw2);
clockhardware();
FETCHADD(30 - memcycs);
}
- if (IRQTEST && c>0 && (fv==((flags&Z_FLAG)?1:0))) cpu_state.pc=ipc;
+ if (IRQTEST && c>0 && (fv==((cpu_state.flags & Z_FLAG)?1:0))) cpu_state.pc=ipc;
// if ((c>0) && (fv==((flags&Z_FLAG)?1:0))) { pc=ipc; firstrepcycle=0; if (ssegs) ssegs++; FETCHCLEAR(); }
// else firstrepcycle=1;
// if (firstrepcycle) printf("REP CMPSW %06X:%04X %06X:%04X %04X %04X\n",ds,SI,es,DI,tempw,tempw2);
{
memcycs=0;
writememb(es+DI,AL);
- if (flags&D_FLAG) DI--;
- else DI++;
+ if (cpu_state.flags & D_FLAG) DI--;
+ else DI++;
c--;
cycles -= 10;
clockhardware();
{
memcycs=0;
writememw(es,DI,AX);
- if (flags&D_FLAG) DI-=2;
- else DI+=2;
+ if (cpu_state.flags & D_FLAG) DI -= 2;
+ else DI += 2;
c--;
cycles -= 10;
clockhardware();
if (c>0)
{
temp2=readmemb(ds+SI);
- if (flags&D_FLAG) SI--;
- else SI++;
+ if (cpu_state.flags & D_FLAG) SI--;
+ else SI++;
c--;
cycles-=4;
}
if (c>0)
{
tempw2=readmemw(ds,SI);
- if (flags&D_FLAG) SI-=2;
- else SI+=2;
+ if (cpu_state.flags & D_FLAG) SI -= 2;
+ else SI += 2;
c--;
cycles-=4;
}
else firstrepcycle=1;
break;
case 0xAE: /*REP SCASB*/
- if (fv) flags|=Z_FLAG;
- else flags&=~Z_FLAG;
- if ((c>0) && (fv==((flags&Z_FLAG)?1:0)))
+ if (fv) cpu_state.flags |= Z_FLAG;
+ else cpu_state.flags &= ~Z_FLAG;
+ if ((c>0) && (fv==((cpu_state.flags & Z_FLAG)?1:0)))
{
temp2=readmemb(es+DI);
// if (output) printf("SCASB %02X %c %02X %05X ",temp2,temp2,AL,es+DI);
setsub8(AL,temp2);
// if (output && flags&Z_FLAG) printf("Match %02X %02X\n",AL,temp2);
- if (flags&D_FLAG) DI--;
- else DI++;
+ if (cpu_state.flags & D_FLAG) DI--;
+ else DI++;
c--;
cycles -= 15;
}
//if (output) printf("%i %i %i %i\n",c,(c>0),(fv==((flags&Z_FLAG)?1:0)),((c>0) && (fv==((flags&Z_FLAG)?1:0))));
- if ((c>0) && (fv==((flags&Z_FLAG)?1:0))) { cpu_state.pc=ipc; firstrepcycle=0; if (cpu_state.ssegs) cpu_state.ssegs++; FETCHCLEAR(); }
+ if ((c>0) && (fv==((cpu_state.flags & Z_FLAG)?1:0))) { cpu_state.pc=ipc; firstrepcycle=0; if (cpu_state.ssegs) cpu_state.ssegs++; FETCHCLEAR(); }
else firstrepcycle=1;
// cycles-=120;
break;
case 0xAF: /*REP SCASW*/
- if (fv) flags|=Z_FLAG;
- else flags&=~Z_FLAG;
- if ((c>0) && (fv==((flags&Z_FLAG)?1:0)))
+ if (fv) cpu_state.flags |= Z_FLAG;
+ else cpu_state.flags &= ~Z_FLAG;
+ if ((c>0) && (fv==((cpu_state.flags & Z_FLAG)?1:0)))
{
tempw=readmemw(es,DI);
setsub16(AX,tempw);
- if (flags&D_FLAG) DI-=2;
- else DI+=2;
+ if (cpu_state.flags & D_FLAG) DI -= 2;
+ else DI += 2;
c--;
cycles -= 15;
}
- if ((c>0) && (fv==((flags&Z_FLAG)?1:0))) { cpu_state.pc=ipc; firstrepcycle=0; if (cpu_state.ssegs) cpu_state.ssegs++; FETCHCLEAR(); }
+ if ((c>0) && (fv==((cpu_state.flags & Z_FLAG)?1:0))) { cpu_state.pc=ipc; firstrepcycle=0; if (cpu_state.ssegs) cpu_state.ssegs++; FETCHCLEAR(); }
else firstrepcycle=1;
break;
default:
}
-int inhlt=0;
-uint16_t lastpc,lastcs;
-int skipnextprint=0;
+static int inhlt=0;
+static int skipnextprint=0;
+
+#include "8087.h"
-int instime=0;
-//#if 0
void execx86(int cycs)
{
uint8_t temp,temp2;
// return;
while (cycles>0)
{
-// old83=old82;
-// old82=old8;
-// old8=oldpc|(oldcs<<16);
-// if (pc==0x96B && cs==0x9E040) { printf("Hit it\n"); output=1; timetolive=150; }
-// if (pc<0x8000) printf("%04X : %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %02X %04X %i\n",pc,AX,BX,CX,DX,cs>>4,ds>>4,es>>4,ss>>4,DI,SI,BP,SP,opcode,flags,disctime);
+ uint8_t opcode;
+
cycdiff=cycles;
- timer_start_period(cycles*xt_cpu_multi);
current_diff = 0;
cycles-=nextcyc;
// if (instime) pclog("Cycles %i %i\n",cycles,cycdiff);
nextcyc=0;
// if (output) printf("CLOCK %i %i\n",cycdiff,cycles);
fetchclocks=0;
- oldcs=CS;
cpu_state.oldpc = cpu_state.pc;
opcodestart:
opcode=FETCH();
- tempc=flags&C_FLAG;
- trap=flags&T_FLAG;
+ tempc = cpu_state.flags & C_FLAG;
+ trap = cpu_state.flags & T_FLAG;
cpu_state.pc--;
// output=1;
// if (output) printf("%04X:%04X : %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %02X %04X\n",cs>>4,pc,AX,BX,CX,DX,cs>>4,ds>>4,es>>4,ss>>4,DI,SI,BP,SP,opcode,flags&~0x200,rmdat);
{
// if ((opcode!=0xF2 && opcode!=0xF3) || firstrepcycle)
// {
- if (!skipnextprint) printf("%04X:%04X : %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %02X %04X %i %p %02X\n",cs,cpu_state.pc,AX,BX,CX,DX,CS,DS,ES,SS,DI,SI,BP,SP,opcode,flags, ins, ram, ram[0x1a925]);
+ if (!skipnextprint) printf("%04X:%04X : %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %04X %02X %04X %i %p %02X\n",cs,cpu_state.pc,AX,BX,CX,DX,CS,DS,ES,SS,DI,SI,BP,SP,opcode,cpu_state.flags, ins, ram, ram[0x1a925]);
skipnextprint=0;
// ins++;
// }
case 0x07: /*POP ES*/
if (cpu_state.ssegs) ss=oldss;
tempw=readmemw(ss,SP);
- loadseg(tempw,&_es);
+ loadseg(tempw,&cpu_state.seg_es);
SP+=2;
cycles-=12;
break;
temp=geteab();
temp|=getr8(cpu_reg);
setznp8(temp);
- flags&=~(C_FLAG|V_FLAG|A_FLAG);
+ cpu_state.flags &= ~(C_FLAG|V_FLAG|A_FLAG);
seteab(temp);
cycles-=((cpu_mod==3)?3:24);
break;
tempw=geteaw();
tempw|=cpu_state.regs[cpu_reg].w;
setznp16(tempw);
- flags&=~(C_FLAG|V_FLAG|A_FLAG);
+ cpu_state.flags &= ~(C_FLAG|V_FLAG|A_FLAG);
seteaw(tempw);
cycles-=((cpu_mod==3)?3:24);
break;
temp=geteab();
temp|=getr8(cpu_reg);
setznp8(temp);
- flags&=~(C_FLAG|V_FLAG|A_FLAG);
+ cpu_state.flags &= ~(C_FLAG|V_FLAG|A_FLAG);
setr8(cpu_reg,temp);
cycles-=((cpu_mod==3)?3:13);
break;
tempw=geteaw();
tempw|=cpu_state.regs[cpu_reg].w;
setznp16(tempw);
- flags&=~(C_FLAG|V_FLAG|A_FLAG);
+ cpu_state.flags &= ~(C_FLAG|V_FLAG|A_FLAG);
cpu_state.regs[cpu_reg].w=tempw;
cycles-=((cpu_mod==3)?3:13);
break;
case 0x0C: /*OR AL,#8*/
AL|=FETCH();
setznp8(AL);
- flags&=~(C_FLAG|V_FLAG|A_FLAG);
+ cpu_state.flags &= ~(C_FLAG|V_FLAG|A_FLAG);
cycles-=4;
break;
case 0x0D: /*OR AX,#16*/
AX|=getword();
setznp16(AX);
- flags&=~(C_FLAG|V_FLAG|A_FLAG);
+ cpu_state.flags &= ~(C_FLAG|V_FLAG|A_FLAG);
cycles-=4;
break;
case 0x0F: /*POP CS - 8088/8086 only*/
if (cpu_state.ssegs) ss=oldss;
tempw=readmemw(ss,SP);
- loadseg(tempw,&_cs);
+ loadseg(tempw,&cpu_state.seg_cs);
SP+=2;
cycles-=12;
break;
case 0x17: /*POP SS*/
if (cpu_state.ssegs) ss=oldss;
tempw=readmemw(ss,SP);
- loadseg(tempw,&_ss);
+ loadseg(tempw,&cpu_state.seg_ss);
SP+=2;
noint=1;
cycles-=12;
case 0x1F: /*POP DS*/
if (cpu_state.ssegs) ss=oldss;
tempw=readmemw(ss,SP);
- loadseg(tempw,&_ds);
+ loadseg(tempw,&cpu_state.seg_ds);
if (cpu_state.ssegs) oldds=ds;
SP+=2;
cycles-=12;
temp=geteab();
temp&=getr8(cpu_reg);
setznp8(temp);
- flags&=~(C_FLAG|V_FLAG|A_FLAG);
+ cpu_state.flags &= ~(C_FLAG|V_FLAG|A_FLAG);
seteab(temp);
cycles-=((cpu_mod==3)?3:24);
break;
tempw=geteaw();
tempw&=cpu_state.regs[cpu_reg].w;
setznp16(tempw);
- flags&=~(C_FLAG|V_FLAG|A_FLAG);
+ cpu_state.flags &= ~(C_FLAG|V_FLAG|A_FLAG);
seteaw(tempw);
cycles-=((cpu_mod==3)?3:24);
break;
temp=geteab();
temp&=getr8(cpu_reg);
setznp8(temp);
- flags&=~(C_FLAG|V_FLAG|A_FLAG);
+ cpu_state.flags &= ~(C_FLAG|V_FLAG|A_FLAG);
setr8(cpu_reg,temp);
cycles-=((cpu_mod==3)?3:13);
break;
tempw=geteaw();
tempw&=cpu_state.regs[cpu_reg].w;
setznp16(tempw);
- flags&=~(C_FLAG|V_FLAG|A_FLAG);
+ cpu_state.flags &= ~(C_FLAG|V_FLAG|A_FLAG);
cpu_state.regs[cpu_reg].w=tempw;
cycles-=((cpu_mod==3)?3:13);
break;
case 0x24: /*AND AL,#8*/
AL&=FETCH();
setznp8(AL);
- flags&=~(C_FLAG|V_FLAG|A_FLAG);
+ cpu_state.flags &= ~(C_FLAG|V_FLAG|A_FLAG);
cycles-=4;
break;
case 0x25: /*AND AX,#16*/
AX&=getword();
setznp16(AX);
- flags&=~(C_FLAG|V_FLAG|A_FLAG);
+ cpu_state.flags &= ~(C_FLAG|V_FLAG|A_FLAG);
cycles-=4;
break;
// break;
case 0x27: /*DAA*/
- if ((flags&A_FLAG) || ((AL&0xF)>9))
+ if ((cpu_state.flags & A_FLAG) || ((AL & 0xF) > 9))
{
- tempi=((uint16_t)AL)+6;
- AL+=6;
- flags|=A_FLAG;
- if (tempi&0x100) flags|=C_FLAG;
+ tempi = ((uint16_t)AL) + 6;
+ AL += 6;
+ cpu_state.flags |= A_FLAG;
+ if (tempi & 0x100)
+ cpu_state.flags |= C_FLAG;
}
// else
// flags&=~A_FLAG;
- if ((flags&C_FLAG) || (AL>0x9F))
+ if ((cpu_state.flags & C_FLAG) || (AL > 0x9F))
{
- AL+=0x60;
- flags|=C_FLAG;
+ AL += 0x60;
+ cpu_state.flags |= C_FLAG;
}
// else
// flags&=~C_FLAG;
cycles-=4;
goto opcodestart;
case 0x2F: /*DAS*/
- if ((flags&A_FLAG)||((AL&0xF)>9))
+ if ((cpu_state.flags & A_FLAG) || ((AL & 0xF) > 9))
{
- tempi=((uint16_t)AL)-6;
- AL-=6;
- flags|=A_FLAG;
- if (tempi&0x100) flags|=C_FLAG;
+ tempi = ((uint16_t)AL) - 6;
+ AL -= 6;
+ cpu_state.flags |= A_FLAG;
+ if (tempi & 0x100)
+ cpu_state.flags |= C_FLAG;
}
// else
// flags&=~A_FLAG;
- if ((flags&C_FLAG)||(AL>0x9F))
+ if ((cpu_state.flags & C_FLAG) || (AL > 0x9F))
{
- AL-=0x60;
- flags|=C_FLAG;
+ AL -= 0x60;
+ cpu_state.flags |= C_FLAG;
}
// else
// flags&=~C_FLAG;
temp=geteab();
temp^=getr8(cpu_reg);
setznp8(temp);
- flags&=~(C_FLAG|V_FLAG|A_FLAG);
+ cpu_state.flags &= ~(C_FLAG|V_FLAG|A_FLAG);
seteab(temp);
cycles-=((cpu_mod==3)?3:24);
break;
tempw=geteaw();
tempw^=cpu_state.regs[cpu_reg].w;
setznp16(tempw);
- flags&=~(C_FLAG|V_FLAG|A_FLAG);
+ cpu_state.flags &= ~(C_FLAG|V_FLAG|A_FLAG);
seteaw(tempw);
cycles-=((cpu_mod==3)?3:24);
break;
temp=geteab();
temp^=getr8(cpu_reg);
setznp8(temp);
- flags&=~(C_FLAG|V_FLAG|A_FLAG);
+ cpu_state.flags &= ~(C_FLAG|V_FLAG|A_FLAG);
setr8(cpu_reg,temp);
cycles-=((cpu_mod==3)?3:13);
break;
tempw=geteaw();
tempw^=cpu_state.regs[cpu_reg].w;
setznp16(tempw);
- flags&=~(C_FLAG|V_FLAG|A_FLAG);
+ cpu_state.flags &= ~(C_FLAG|V_FLAG|A_FLAG);
cpu_state.regs[cpu_reg].w=tempw;
cycles-=((cpu_mod==3)?3:13);
break;
case 0x34: /*XOR AL,#8*/
AL^=FETCH();
setznp8(AL);
- flags&=~(C_FLAG|V_FLAG|A_FLAG);
+ cpu_state.flags &= ~(C_FLAG|V_FLAG|A_FLAG);
cycles-=4;
break;
case 0x35: /*XOR AX,#16*/
AX^=getword();
setznp16(AX);
- flags&=~(C_FLAG|V_FLAG|A_FLAG);
+ cpu_state.flags &= ~(C_FLAG|V_FLAG|A_FLAG);
cycles-=4;
break;
// break;
case 0x37: /*AAA*/
- if ((flags&A_FLAG)||((AL&0xF)>9))
+ if ((cpu_state.flags & A_FLAG)||((AL & 0xF) > 9))
{
- AL+=6;
+ AL += 6;
AH++;
- flags|=(A_FLAG|C_FLAG);
+ cpu_state.flags |= (A_FLAG|C_FLAG);
}
else
- flags&=~(A_FLAG|C_FLAG);
- AL&=0xF;
- cycles-=8;
+ cpu_state.flags &= ~(A_FLAG|C_FLAG);
+ AL &= 0xF;
+ cycles -= 8;
break;
case 0x38: /*CMP 8,reg*/
// break;
case 0x3F: /*AAS*/
- if ((flags&A_FLAG)||((AL&0xF)>9))
+ if ((cpu_state.flags & A_FLAG) || ((AL & 0xF) > 9))
{
- AL-=6;
+ AL -= 6;
AH--;
- flags|=(A_FLAG|C_FLAG);
+ cpu_state.flags |= (A_FLAG|C_FLAG);
}
else
- flags&=~(A_FLAG|C_FLAG);
- AL&=0xF;
- cycles-=8;
+ cpu_state.flags &= ~(A_FLAG|C_FLAG);
+ AL &= 0xF;
+ cycles -= 8;
break;
case 0x40: case 0x41: case 0x42: case 0x43: /*INC r16*/
case 0x60: /*JO alias*/
case 0x70: /*JO*/
offset=(int8_t)FETCH();
- if (flags&V_FLAG) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); }
+ if (cpu_state.flags & V_FLAG) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); }
cycles-=4;
break;
case 0x61: /*JNO alias*/
case 0x71: /*JNO*/
offset=(int8_t)FETCH();
- if (!(flags&V_FLAG)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); }
+ if (!(cpu_state.flags & V_FLAG)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); }
cycles-=4;
break;
case 0x62: /*JB alias*/
case 0x72: /*JB*/
offset=(int8_t)FETCH();
- if (flags&C_FLAG) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); }
+ if (cpu_state.flags & C_FLAG) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); }
cycles-=4;
break;
case 0x63: /*JNB alias*/
case 0x73: /*JNB*/
offset=(int8_t)FETCH();
- if (!(flags&C_FLAG)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); }
+ if (!(cpu_state.flags & C_FLAG)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); }
cycles-=4;
break;
case 0x64: /*JE alias*/
case 0x74: /*JE*/
offset=(int8_t)FETCH();
- if (flags&Z_FLAG) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); }
+ if (cpu_state.flags & Z_FLAG) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); }
cycles-=4;
break;
case 0x65: /*JNE alias*/
case 0x75: /*JNE*/
offset=(int8_t)FETCH();
cycles-=4;
- if (!(flags&Z_FLAG)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); }
+ if (!(cpu_state.flags & Z_FLAG)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); }
break;
case 0x66: /*JBE alias*/
case 0x76: /*JBE*/
offset=(int8_t)FETCH();
- if (flags&(C_FLAG|Z_FLAG)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); }
+ if (cpu_state.flags & (C_FLAG|Z_FLAG)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); }
cycles-=4;
break;
case 0x67: /*JNBE alias*/
case 0x77: /*JNBE*/
offset=(int8_t)FETCH();
- if (!(flags&(C_FLAG|Z_FLAG))) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); }
+ if (!(cpu_state.flags & (C_FLAG|Z_FLAG))) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); }
cycles-=4;
break;
case 0x68: /*JS alias*/
case 0x78: /*JS*/
offset=(int8_t)FETCH();
- if (flags&N_FLAG) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); }
+ if (cpu_state.flags & N_FLAG) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); }
cycles-=4;
break;
case 0x69: /*JNS alias*/
case 0x79: /*JNS*/
offset=(int8_t)FETCH();
- if (!(flags&N_FLAG)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); }
+ if (!(cpu_state.flags & N_FLAG)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); }
cycles-=4;
break;
case 0x6A: /*JP alias*/
case 0x7A: /*JP*/
offset=(int8_t)FETCH();
- if (flags&P_FLAG) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); }
+ if (cpu_state.flags & P_FLAG) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); }
cycles-=4;
break;
case 0x6B: /*JNP alias*/
case 0x7B: /*JNP*/
offset=(int8_t)FETCH();
- if (!(flags&P_FLAG)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); }
+ if (!(cpu_state.flags & P_FLAG)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); }
cycles-=4;
break;
case 0x6C: /*JL alias*/
case 0x7C: /*JL*/
offset=(int8_t)FETCH();
- temp=(flags&N_FLAG)?1:0;
- temp2=(flags&V_FLAG)?1:0;
+ temp=(cpu_state.flags & N_FLAG)?1:0;
+ temp2=(cpu_state.flags & V_FLAG)?1:0;
if (temp!=temp2) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); }
cycles-=4;
break;
case 0x6D: /*JNL alias*/
case 0x7D: /*JNL*/
offset=(int8_t)FETCH();
- temp=(flags&N_FLAG)?1:0;
- temp2=(flags&V_FLAG)?1:0;
+ temp=(cpu_state.flags & N_FLAG)?1:0;
+ temp2=(cpu_state.flags & V_FLAG)?1:0;
if (temp==temp2) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); }
cycles-=4;
break;
case 0x6E: /*JLE alias*/
case 0x7E: /*JLE*/
offset=(int8_t)FETCH();
- temp=(flags&N_FLAG)?1:0;
- temp2=(flags&V_FLAG)?1:0;
- if ((flags&Z_FLAG) || (temp!=temp2)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); }
+ temp=(cpu_state.flags & N_FLAG)?1:0;
+ temp2=(cpu_state.flags & V_FLAG)?1:0;
+ if ((cpu_state.flags & Z_FLAG) || (temp!=temp2)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); }
cycles-=4;
break;
case 0x6F: /*JNLE alias*/
case 0x7F: /*JNLE*/
offset=(int8_t)FETCH();
- temp=(flags&N_FLAG)?1:0;
- temp2=(flags&V_FLAG)?1:0;
- if (!((flags&Z_FLAG) || (temp!=temp2))) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); }
+ temp=(cpu_state.flags & N_FLAG)?1:0;
+ temp2=(cpu_state.flags & V_FLAG)?1:0;
+ if (!((cpu_state.flags & Z_FLAG) || (temp!=temp2))) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); }
cycles-=4;
break;
case 0x08: /*OR b,#8*/
temp|=temp2;
setznp8(temp);
- flags&=~(C_FLAG|V_FLAG|A_FLAG);
+ cpu_state.flags &= ~(C_FLAG|V_FLAG|A_FLAG);
seteab(temp);
cycles-=((cpu_mod==3)?4:23);
break;
case 0x20: /*AND b,#8*/
temp&=temp2;
setznp8(temp);
- flags&=~(C_FLAG|V_FLAG|A_FLAG);
+ cpu_state.flags &= ~(C_FLAG|V_FLAG|A_FLAG);
seteab(temp);
cycles-=((cpu_mod==3)?4:23);
break;
case 0x30: /*XOR b,#8*/
temp^=temp2;
setznp8(temp);
- flags&=~(C_FLAG|V_FLAG|A_FLAG);
+ cpu_state.flags &= ~(C_FLAG|V_FLAG|A_FLAG);
seteab(temp);
cycles-=((cpu_mod==3)?4:23);
break;
case 0x08: /*OR w,#16*/
tempw|=tempw2;
setznp16(tempw);
- flags&=~(C_FLAG|V_FLAG|A_FLAG);
+ cpu_state.flags &= ~(C_FLAG|V_FLAG|A_FLAG);
seteaw(tempw);
cycles-=((cpu_mod==3)?4:23);
break;
case 0x20: /*AND w,#16*/
tempw&=tempw2;
setznp16(tempw);
- flags&=~(C_FLAG|V_FLAG|A_FLAG);
+ cpu_state.flags &= ~(C_FLAG|V_FLAG|A_FLAG);
seteaw(tempw);
cycles-=((cpu_mod==3)?4:23);
break;
case 0x30: /*XOR w,#16*/
tempw^=tempw2;
setznp16(tempw);
- flags&=~(C_FLAG|V_FLAG|A_FLAG);
+ cpu_state.flags &= ~(C_FLAG|V_FLAG|A_FLAG);
seteaw(tempw);
cycles-=((cpu_mod==3)?4:23);
break;
tempw|=tempw2;
setznp16(tempw);
seteaw(tempw);
- flags&=~(C_FLAG|A_FLAG|V_FLAG);
+ cpu_state.flags &= ~(C_FLAG|A_FLAG|V_FLAG);
cycles-=((cpu_mod==3)?4:23);
break;
case 0x10: /*ADC w,#8*/
setznp16(tempw);
seteaw(tempw);
cycles-=((cpu_mod==3)?4:23);
- flags&=~(C_FLAG|A_FLAG|V_FLAG);
+ cpu_state.flags &= ~(C_FLAG|A_FLAG|V_FLAG);
break;
case 0x28: /*SUB w,#8*/
setsub16(tempw,tempw2);
setznp16(tempw);
seteaw(tempw);
cycles-=((cpu_mod==3)?4:23);
- flags&=~(C_FLAG|A_FLAG|V_FLAG);
+ cpu_state.flags &= ~(C_FLAG|A_FLAG|V_FLAG);
break;
case 0x38: /*CMP w,#8*/
setsub16(tempw,tempw2);
temp=geteab();
temp2=getr8(cpu_reg);
setznp8(temp&temp2);
- flags&=~(C_FLAG|V_FLAG|A_FLAG);
+ cpu_state.flags &= ~(C_FLAG|V_FLAG|A_FLAG);
cycles-=((cpu_mod==3)?3:13);
break;
case 0x85: /*TEST w,reg*/
tempw=geteaw();
tempw2=cpu_state.regs[cpu_reg].w;
setznp16(tempw&tempw2);
- flags&=~(C_FLAG|V_FLAG|A_FLAG);
+ cpu_state.flags &= ~(C_FLAG|V_FLAG|A_FLAG);
cycles-=((cpu_mod==3)?3:13);
break;
case 0x86: /*XCHG b,reg*/
{
case 0x00: /*ES*/
tempw=geteaw();
- loadseg(tempw,&_es);
+ loadseg(tempw,&cpu_state.seg_es);
break;
case 0x08: /*CS - 8088/8086 only*/
tempw=geteaw();
- loadseg(tempw,&_cs);
+ loadseg(tempw,&cpu_state.seg_cs);
break;
case 0x18: /*DS*/
tempw=geteaw();
- loadseg(tempw,&_ds);
+ loadseg(tempw,&cpu_state.seg_ds);
if (cpu_state.ssegs) oldds=ds;
break;
case 0x10: /*SS*/
tempw=geteaw();
- loadseg(tempw,&_ss);
+ loadseg(tempw,&cpu_state.seg_ss);
if (cpu_state.ssegs) oldss=ss;
// printf("LOAD SS %04X %04X\n",tempw,SS);
// printf("SS loaded with %04X %04X:%04X %04X %04X %04X\n",ss>>4,cs>>4,pc,CX,DX,es>>4);
break;
case 0x9C: /*PUSHF*/
if (cpu_state.ssegs) ss=oldss;
- writememw(ss,((SP-2)&0xFFFF),flags|0xF000);
+ writememw(ss, ((SP-2)&0xFFFF), cpu_state.flags | 0xF000);
SP-=2;
cycles-=14;
break;
case 0x9D: /*POPF*/
if (cpu_state.ssegs) ss=oldss;
- flags=readmemw(ss,SP)&0xFFF;
+ cpu_state.flags = readmemw(ss,SP) & 0xFFF;
SP+=2;
cycles-=12;
break;
case 0x9E: /*SAHF*/
- flags=(flags&0xFF00)|AH;
+ cpu_state.flags = (cpu_state.flags & 0xFF00) | AH;
cycles-=4;
break;
case 0x9F: /*LAHF*/
- AH=flags&0xFF;
+ AH = cpu_state.flags & 0xFF;
cycles-=4;
break;
case 0xA4: /*MOVSB*/
temp=readmemb(ds+SI);
writememb(es+DI,temp);
- if (flags&D_FLAG) { DI--; SI--; }
- else { DI++; SI++; }
+ if (cpu_state.flags & D_FLAG) { DI--; SI--; }
+ else { DI++; SI++; }
cycles-=18;
break;
case 0xA5: /*MOVSW*/
tempw=readmemw(ds,SI);
writememw(es,DI,tempw);
- if (flags&D_FLAG) { DI-=2; SI-=2; }
- else { DI+=2; SI+=2; }
+ if (cpu_state.flags & D_FLAG) { DI -= 2; SI -= 2; }
+ else { DI += 2; SI += 2; }
cycles-=18;
break;
case 0xA6: /*CMPSB*/
temp =readmemb(ds+SI);
temp2=readmemb(es+DI);
setsub8(temp,temp2);
- if (flags&D_FLAG) { DI--; SI--; }
- else { DI++; SI++; }
+ if (cpu_state.flags & D_FLAG) { DI--; SI--; }
+ else { DI++; SI++; }
cycles-=30;
break;
case 0xA7: /*CMPSW*/
tempw2=readmemw(es,DI);
// printf("CMPSW %04X %04X\n",tempw,tempw2);
setsub16(tempw,tempw2);
- if (flags&D_FLAG) { DI-=2; SI-=2; }
- else { DI+=2; SI+=2; }
+ if (cpu_state.flags & D_FLAG) { DI -= 2; SI -= 2; }
+ else { DI += 2; SI += 2; }
cycles-=30;
break;
case 0xA8: /*TEST AL,#8*/
temp=FETCH();
setznp8(AL&temp);
- flags&=~(C_FLAG|V_FLAG|A_FLAG);
+ cpu_state.flags &= ~(C_FLAG|V_FLAG|A_FLAG);
cycles-=5;
break;
case 0xA9: /*TEST AX,#16*/
tempw=getword();
setznp16(AX&tempw);
- flags&=~(C_FLAG|V_FLAG|A_FLAG);
+ cpu_state.flags &= ~(C_FLAG|V_FLAG|A_FLAG);
cycles-=5;
break;
case 0xAA: /*STOSB*/
writememb(es+DI,AL);
- if (flags&D_FLAG) DI--;
- else DI++;
+ if (cpu_state.flags & D_FLAG) DI--;
+ else DI++;
cycles-=11;
break;
case 0xAB: /*STOSW*/
writememw(es,DI,AX);
- if (flags&D_FLAG) DI-=2;
- else DI+=2;
+ if (cpu_state.flags & D_FLAG) DI -= 2;
+ else DI += 2;
cycles-=11;
break;
case 0xAC: /*LODSB*/
AL=readmemb(ds+SI);
// printf("LODSB %04X:%04X %02X %04X:%04X\n",cs>>4,pc,AL,ds>>4,SI);
- if (flags&D_FLAG) SI--;
- else SI++;
+ if (cpu_state.flags & D_FLAG) SI--;
+ else SI++;
cycles-=16;
break;
case 0xAD: /*LODSW*/
// if (times) printf("LODSW %04X:%04X\n",cs>>4,pc);
AX=readmemw(ds,SI);
- if (flags&D_FLAG) SI-=2;
- else SI+=2;
+ if (cpu_state.flags & D_FLAG) SI -= 2;
+ else SI += 2;
cycles-=16;
break;
case 0xAE: /*SCASB*/
temp=readmemb(es+DI);
setsub8(AL,temp);
- if (flags&D_FLAG) DI--;
- else DI++;
+ if (cpu_state.flags & D_FLAG) DI--;
+ else DI++;
cycles-=19;
break;
case 0xAF: /*SCASW*/
tempw=readmemw(es,DI);
setsub16(AX,tempw);
- if (flags&D_FLAG) DI-=2;
- else DI+=2;
+ if (cpu_state.flags & D_FLAG) DI -= 2;
+ else DI += 2;
cycles-=19;
break;
fetchea();
cpu_state.regs[cpu_reg].w=readmemw(easeg,cpu_state.eaaddr); //geteaw();
tempw=readmemw(easeg,(cpu_state.eaaddr+2)&0xFFFF); //geteaw2();
- loadseg(tempw,&_es);
+ loadseg(tempw,&cpu_state.seg_es);
cycles-=24;
break;
case 0xC5: /*LDS*/
fetchea();
cpu_state.regs[cpu_reg].w=readmemw(easeg,cpu_state.eaaddr);
tempw=readmemw(easeg,(cpu_state.eaaddr+2)&0xFFFF);
- loadseg(tempw,&_ds);
+ loadseg(tempw,&cpu_state.seg_ds);
if (cpu_state.ssegs) oldds=ds;
cycles-=24;
break;
break;
case 0xCC: /*INT 3*/
if (cpu_state.ssegs) ss=oldss;
- writememw(ss,((SP-2)&0xFFFF),flags|0xF000);
- writememw(ss,((SP-4)&0xFFFF),CS);
- writememw(ss,((SP-6)&0xFFFF),cpu_state.pc);
+ writememw(ss, ((SP-2)&0xFFFF), cpu_state.flags | 0xF000);
+ writememw(ss, ((SP-4)&0xFFFF), CS);
+ writememw(ss, ((SP-6)&0xFFFF), cpu_state.pc);
SP-=6;
addr=3<<2;
- flags&=~I_FLAG;
- flags&=~T_FLAG;
+ cpu_state.flags &= ~I_FLAG;
+ cpu_state.flags &= ~T_FLAG;
// printf("CC %04X:%04X ",CS,pc);
cpu_state.pc=readmemw(0,addr);
loadcs(readmemw(0,addr+2));
cycles-=72;
break;
case 0xCD: /*INT*/
- lastpc=cpu_state.pc;
- lastcs=CS;
temp=FETCH();
if (cpu_state.ssegs) ss=oldss;
- writememw(ss,((SP-2)&0xFFFF),flags|0xF000);
- writememw(ss,((SP-4)&0xFFFF),CS);
- writememw(ss,((SP-6)&0xFFFF),cpu_state.pc);
- flags&=~T_FLAG;
+ writememw(ss, ((SP-2)&0xFFFF), cpu_state.flags | 0xF000);
+ writememw(ss, ((SP-4)&0xFFFF), CS);
+ writememw(ss, ((SP-6)&0xFFFF), cpu_state.pc);
+ cpu_state.flags &= ~T_FLAG;
SP-=6;
addr=temp<<2;
cpu_state.pc=readmemw(0,addr);
cpu_state.pc=readmemw(ss,SP);
// printf("CF\n");
loadcs(readmemw(ss,((SP+2)&0xFFFF)));
- flags=readmemw(ss,((SP+4)&0xFFFF))&0xFFF;
+ cpu_state.flags = readmemw(ss,((SP+4)&0xFFFF))&0xFFF;
SP+=6;
cycles-=44;
FETCHCLEAR();
switch (rmdat&0x38)
{
case 0x00: /*ROL b,1*/
- if (temp&0x80) flags|=C_FLAG;
- else flags&=~C_FLAG;
+ if (temp&0x80) cpu_state.flags |= C_FLAG;
+ else cpu_state.flags &= ~C_FLAG;
temp<<=1;
- if (flags&C_FLAG) temp|=1;
+ if (cpu_state.flags & C_FLAG)
+ temp |= 1;
seteab(temp);
// setznp8(temp);
- if ((flags&C_FLAG)^(temp>>7)) flags|=V_FLAG;
- else flags&=~V_FLAG;
+ if ((cpu_state.flags&C_FLAG) ^ (temp >> 7)) cpu_state.flags |= V_FLAG;
+ else cpu_state.flags &= ~V_FLAG;
cycles-=((cpu_mod==3)?2:23);
break;
case 0x08: /*ROR b,1*/
- if (temp&1) flags|=C_FLAG;
- else flags&=~C_FLAG;
+ if (temp&1) cpu_state.flags |= C_FLAG;
+ else cpu_state.flags &= ~C_FLAG;
temp>>=1;
- if (flags&C_FLAG) temp|=0x80;
+ if (cpu_state.flags & C_FLAG)
+ temp |= 0x80;
seteab(temp);
// setznp8(temp);
- if ((temp^(temp>>1))&0x40) flags|=V_FLAG;
- else flags&=~V_FLAG;
+ if ((temp^(temp>>1))&0x40) cpu_state.flags |= V_FLAG;
+ else cpu_state.flags &= ~V_FLAG;
cycles-=((cpu_mod==3)?2:23);
break;
case 0x10: /*RCL b,1*/
- temp2=flags&C_FLAG;
- if (temp&0x80) flags|=C_FLAG;
- else flags&=~C_FLAG;
+ temp2 = cpu_state.flags & C_FLAG;
+ if (temp&0x80) cpu_state.flags |= C_FLAG;
+ else cpu_state.flags &= ~C_FLAG;
temp<<=1;
if (temp2) temp|=1;
seteab(temp);
// setznp8(temp);
- if ((flags&C_FLAG)^(temp>>7)) flags|=V_FLAG;
- else flags&=~V_FLAG;
+ if ((cpu_state.flags & C_FLAG)^(temp>>7)) cpu_state.flags |= V_FLAG;
+ else cpu_state.flags &= ~V_FLAG;
cycles-=((cpu_mod==3)?2:23);
break;
case 0x18: /*RCR b,1*/
- temp2=flags&C_FLAG;
- if (temp&1) flags|=C_FLAG;
- else flags&=~C_FLAG;
+ temp2 = cpu_state.flags & C_FLAG;
+ if (temp&1) cpu_state.flags |= C_FLAG;
+ else cpu_state.flags &= ~C_FLAG;
temp>>=1;
if (temp2) temp|=0x80;
seteab(temp);
// setznp8(temp);
- if ((temp^(temp>>1))&0x40) flags|=V_FLAG;
- else flags&=~V_FLAG;
+ if ((temp^(temp>>1))&0x40) cpu_state.flags |= V_FLAG;
+ else cpu_state.flags &= ~V_FLAG;
cycles-=((cpu_mod==3)?2:23);
break;
case 0x20: case 0x30: /*SHL b,1*/
- if (temp&0x80) flags|=C_FLAG;
- else flags&=~C_FLAG;
- if ((temp^(temp<<1))&0x80) flags|=V_FLAG;
- else flags&=~V_FLAG;
+ if (temp&0x80) cpu_state.flags |= C_FLAG;
+ else cpu_state.flags &= ~C_FLAG;
+ if ((temp^(temp<<1))&0x80) cpu_state.flags |= V_FLAG;
+ else cpu_state.flags &= ~V_FLAG;
temp<<=1;
seteab(temp);
setznp8(temp);
cycles-=((cpu_mod==3)?2:23);
- flags|=A_FLAG;
+ cpu_state.flags |= A_FLAG;
break;
case 0x28: /*SHR b,1*/
- if (temp&1) flags|=C_FLAG;
- else flags&=~C_FLAG;
- if (temp&0x80) flags|=V_FLAG;
- else flags&=~V_FLAG;
+ if (temp&1) cpu_state.flags |= C_FLAG;
+ else cpu_state.flags &= ~C_FLAG;
+ if (temp&0x80) cpu_state.flags |= V_FLAG;
+ else cpu_state.flags &= ~V_FLAG;
temp>>=1;
seteab(temp);
setznp8(temp);
cycles-=((cpu_mod==3)?2:23);
- flags|=A_FLAG;
+ cpu_state.flags |= A_FLAG;
break;
case 0x38: /*SAR b,1*/
- if (temp&1) flags|=C_FLAG;
- else flags&=~C_FLAG;
+ if (temp&1) cpu_state.flags |= C_FLAG;
+ else cpu_state.flags &= ~C_FLAG;
temp>>=1;
if (temp&0x40) temp|=0x80;
seteab(temp);
setznp8(temp);
cycles-=((cpu_mod==3)?2:23);
- flags|=A_FLAG;
- flags&=~V_FLAG;
+ cpu_state.flags |= A_FLAG;
+ cpu_state.flags &= ~V_FLAG;
break;
// default:
switch (rmdat&0x38)
{
case 0x00: /*ROL w,1*/
- if (tempw&0x8000) flags|=C_FLAG;
- else flags&=~C_FLAG;
+ if (tempw&0x8000) cpu_state.flags |= C_FLAG;
+ else cpu_state.flags &= ~C_FLAG;
tempw<<=1;
- if (flags&C_FLAG) tempw|=1;
+ if (cpu_state.flags & C_FLAG) tempw|=1;
seteaw(tempw);
// setznp16(tempw);
- if ((flags&C_FLAG)^(tempw>>15)) flags|=V_FLAG;
- else flags&=~V_FLAG;
+ if ((cpu_state.flags & C_FLAG)^(tempw>>15)) cpu_state.flags |= V_FLAG;
+ else cpu_state.flags &= ~V_FLAG;
cycles-=((cpu_mod==3)?2:23);
break;
case 0x08: /*ROR w,1*/
- if (tempw&1) flags|=C_FLAG;
- else flags&=~C_FLAG;
+ if (tempw&1) cpu_state.flags |= C_FLAG;
+ else cpu_state.flags &= ~C_FLAG;
tempw>>=1;
- if (flags&C_FLAG) tempw|=0x8000;
+ if (cpu_state.flags & C_FLAG) tempw|=0x8000;
seteaw(tempw);
// setznp16(tempw);
- if ((tempw^(tempw>>1))&0x4000) flags|=V_FLAG;
- else flags&=~V_FLAG;
+ if ((tempw^(tempw>>1))&0x4000) cpu_state.flags |= V_FLAG;
+ else cpu_state.flags &= ~V_FLAG;
cycles-=((cpu_mod==3)?2:23);
break;
case 0x10: /*RCL w,1*/
- temp2=flags&C_FLAG;
- if (tempw&0x8000) flags|=C_FLAG;
- else flags&=~C_FLAG;
+ temp2 = cpu_state.flags & C_FLAG;
+ if (tempw&0x8000) cpu_state.flags |= C_FLAG;
+ else cpu_state.flags &= ~C_FLAG;
tempw<<=1;
if (temp2) tempw|=1;
seteaw(tempw);
- if ((flags&C_FLAG)^(tempw>>15)) flags|=V_FLAG;
- else flags&=~V_FLAG;
+ if ((cpu_state.flags & C_FLAG)^(tempw>>15)) cpu_state.flags |= V_FLAG;
+ else cpu_state.flags &= ~V_FLAG;
cycles-=((cpu_mod==3)?2:23);
break;
case 0x18: /*RCR w,1*/
- temp2=flags&C_FLAG;
- if (tempw&1) flags|=C_FLAG;
- else flags&=~C_FLAG;
+ temp2 = cpu_state.flags & C_FLAG;
+ if (tempw&1) cpu_state.flags |= C_FLAG;
+ else cpu_state.flags &= ~C_FLAG;
tempw>>=1;
if (temp2) tempw|=0x8000;
seteaw(tempw);
// setznp16(tempw);
- if ((tempw^(tempw>>1))&0x4000) flags|=V_FLAG;
- else flags&=~V_FLAG;
+ if ((tempw^(tempw>>1))&0x4000) cpu_state.flags |= V_FLAG;
+ else cpu_state.flags &= ~V_FLAG;
cycles-=((cpu_mod==3)?2:23);
break;
case 0x20: case 0x30: /*SHL w,1*/
- if (tempw&0x8000) flags|=C_FLAG;
- else flags&=~C_FLAG;
- if ((tempw^(tempw<<1))&0x8000) flags|=V_FLAG;
- else flags&=~V_FLAG;
+ if (tempw&0x8000) cpu_state.flags |= C_FLAG;
+ else cpu_state.flags &= ~C_FLAG;
+ if ((tempw^(tempw<<1))&0x8000) cpu_state.flags |= V_FLAG;
+ else cpu_state.flags &= ~V_FLAG;
tempw<<=1;
seteaw(tempw);
setznp16(tempw);
cycles-=((cpu_mod==3)?2:23);
- flags|=A_FLAG;
+ cpu_state.flags |= A_FLAG;
break;
case 0x28: /*SHR w,1*/
- if (tempw&1) flags|=C_FLAG;
- else flags&=~C_FLAG;
- if (tempw&0x8000) flags|=V_FLAG;
- else flags&=~V_FLAG;
+ if (tempw&1) cpu_state.flags |= C_FLAG;
+ else cpu_state.flags &= ~C_FLAG;
+ if (tempw&0x8000) cpu_state.flags |= V_FLAG;
+ else cpu_state.flags &= ~V_FLAG;
tempw>>=1;
seteaw(tempw);
setznp16(tempw);
cycles-=((cpu_mod==3)?2:23);
- flags|=A_FLAG;
+ cpu_state.flags |= A_FLAG;
break;
case 0x38: /*SAR w,1*/
- if (tempw&1) flags|=C_FLAG;
- else flags&=~C_FLAG;
+ if (tempw&1) cpu_state.flags |= C_FLAG;
+ else cpu_state.flags &= ~C_FLAG;
tempw>>=1;
if (tempw&0x4000) tempw|=0x8000;
seteaw(tempw);
setznp16(tempw);
cycles-=((cpu_mod==3)?2:23);
- flags|=A_FLAG;
- flags&=~V_FLAG;
+ cpu_state.flags |= A_FLAG;
+ cpu_state.flags &= ~V_FLAG;
break;
// default:
c--;
cycles-=4;
}
- if (temp2) flags|=C_FLAG;
- else flags&=~C_FLAG;
+ if (temp2) cpu_state.flags |= C_FLAG;
+ else cpu_state.flags &= ~C_FLAG;
seteab(temp);
// setznp8(temp);
- if ((flags&C_FLAG)^(temp>>7)) flags|=V_FLAG;
- else flags&=~V_FLAG;
+ if ((cpu_state.flags & C_FLAG)^(temp>>7)) cpu_state.flags |= V_FLAG;
+ else cpu_state.flags &= ~V_FLAG;
cycles-=((cpu_mod==3)?8:28);
break;
case 0x08: /*ROR b,CL*/
c--;
cycles-=4;
}
- if (temp2) flags|=C_FLAG;
- else flags&=~C_FLAG;
+ if (temp2) cpu_state.flags |= C_FLAG;
+ else cpu_state.flags &= ~C_FLAG;
seteab(temp);
- if ((temp^(temp>>1))&0x40) flags|=V_FLAG;
- else flags&=~V_FLAG;
+ if ((temp^(temp>>1))&0x40) cpu_state.flags |= V_FLAG;
+ else cpu_state.flags &= ~V_FLAG;
cycles-=((cpu_mod==3)?8:28);
break;
case 0x10: /*RCL b,CL*/
// printf("RCL %i %02X %02X\n",c,CL,temp);
while (c>0)
{
- templ=flags&C_FLAG;
+ templ=cpu_state.flags & C_FLAG;
temp2=temp&0x80;
temp<<=1;
- if (temp2) flags|=C_FLAG;
- else flags&=~C_FLAG;
+ if (temp2) cpu_state.flags |= C_FLAG;
+ else cpu_state.flags &= ~C_FLAG;
if (templ) temp|=1;
c--;
cycles-=4;
}
// printf("Now %02X\n",temp);
seteab(temp);
- if ((flags&C_FLAG)^(temp>>7)) flags|=V_FLAG;
- else flags&=~V_FLAG;
+ if ((cpu_state.flags & C_FLAG)^(temp>>7)) cpu_state.flags |= V_FLAG;
+ else cpu_state.flags &= ~V_FLAG;
cycles-=((cpu_mod==3)?8:28);
break;
case 0x18: /*RCR b,CL*/
while (c>0)
{
- templ=flags&C_FLAG;
+ templ=cpu_state.flags & C_FLAG;
temp2=temp&1;
temp>>=1;
- if (temp2) flags|=C_FLAG;
- else flags&=~C_FLAG;
+ if (temp2) cpu_state.flags |= C_FLAG;
+ else cpu_state.flags &= ~C_FLAG;
if (templ) temp|=0x80;
c--;
cycles-=4;
// if (temp2) flags|=C_FLAG;
// else flags&=~C_FLAG;
seteab(temp);
- if ((temp^(temp>>1))&0x40) flags|=V_FLAG;
- else flags&=~V_FLAG;
+ if ((temp^(temp>>1))&0x40) cpu_state.flags |= V_FLAG;
+ else cpu_state.flags &= ~V_FLAG;
cycles-=((cpu_mod==3)?8:28);
break;
case 0x20: case 0x30: /*SHL b,CL*/
if (c > 8)
{
temp = 0;
- flags &= ~C_FLAG;
+ cpu_state.flags &= ~C_FLAG;
}
else
{
- if ((temp<<(c-1))&0x80) flags|=C_FLAG;
- else flags&=~C_FLAG;
+ if ((temp<<(c-1))&0x80) cpu_state.flags |= C_FLAG;
+ else cpu_state.flags &= ~C_FLAG;
temp<<=c;
}
seteab(temp);
setznp8(temp);
cycles-=(c*4);
cycles-=((cpu_mod==3)?8:28);
- flags|=A_FLAG;
+ cpu_state.flags |= A_FLAG;
break;
case 0x28: /*SHR b,CL*/
if (c > 8)
{
temp = 0;
- flags &= ~C_FLAG;
+ cpu_state.flags &= ~C_FLAG;
}
else
{
- if ((temp>>(c-1))&1) flags|=C_FLAG;
- else flags&=~C_FLAG;
+ if ((temp>>(c-1))&1) cpu_state.flags |= C_FLAG;
+ else cpu_state.flags &= ~C_FLAG;
temp>>=c;
}
seteab(temp);
setznp8(temp);
cycles-=(c*4);
cycles-=((cpu_mod==3)?8:28);
- flags|=A_FLAG;
+ cpu_state.flags |= A_FLAG;
break;
case 0x38: /*SAR b,CL*/
- if ((temp>>(c-1))&1) flags|=C_FLAG;
- else flags&=~C_FLAG;
+ if ((temp>>(c-1))&1) cpu_state.flags |= C_FLAG;
+ else cpu_state.flags &= ~C_FLAG;
while (c>0)
{
temp>>=1;
seteab(temp);
setznp8(temp);
cycles-=((cpu_mod==3)?8:28);
- flags|=A_FLAG;
+ cpu_state.flags |= A_FLAG;
break;
// default:
c--;
cycles-=4;
}
- if (temp) flags|=C_FLAG;
- else flags&=~C_FLAG;
+ if (temp) cpu_state.flags |= C_FLAG;
+ else cpu_state.flags &= ~C_FLAG;
seteaw(tempw);
- if ((flags&C_FLAG)^(tempw>>15)) flags|=V_FLAG;
- else flags&=~V_FLAG;
+ if ((cpu_state.flags & C_FLAG)^(tempw>>15)) cpu_state.flags |= V_FLAG;
+ else cpu_state.flags &= ~V_FLAG;
cycles-=((cpu_mod==3)?8:28);
break;
case 0x08: /*ROR w,CL*/
c--;
cycles-=4;
}
- if (tempw2) flags|=C_FLAG;
- else flags&=~C_FLAG;
+ if (tempw2) cpu_state.flags |= C_FLAG;
+ else cpu_state.flags &= ~C_FLAG;
seteaw(tempw);
- if ((tempw^(tempw>>1))&0x4000) flags|=V_FLAG;
- else flags&=~V_FLAG;
+ if ((tempw^(tempw>>1))&0x4000) cpu_state.flags |= V_FLAG;
+ else cpu_state.flags &= ~V_FLAG;
cycles-=((cpu_mod==3)?8:28);
break;
case 0x10: /*RCL w,CL*/
while (c>0)
{
- templ=flags&C_FLAG;
- if (tempw&0x8000) flags|=C_FLAG;
- else flags&=~C_FLAG;
+ templ = cpu_state.flags & C_FLAG;
+ if (tempw&0x8000) cpu_state.flags |= C_FLAG;
+ else cpu_state.flags &= ~C_FLAG;
tempw=(tempw<<1)|templ;
c--;
cycles-=4;
}
- if (templ) flags|=C_FLAG;
- else flags&=~C_FLAG;
+ if (templ) cpu_state.flags |= C_FLAG;
+ else cpu_state.flags &= ~C_FLAG;
seteaw(tempw);
- if ((flags&C_FLAG)^(tempw>>15)) flags|=V_FLAG;
- else flags&=~V_FLAG;
+ if ((cpu_state.flags & C_FLAG)^(tempw>>15)) cpu_state.flags |= V_FLAG;
+ else cpu_state.flags &= ~V_FLAG;
cycles-=((cpu_mod==3)?8:28);
break;
case 0x18: /*RCR w,CL*/
while (c>0)
{
- templ=flags&C_FLAG;
+ templ = cpu_state.flags & C_FLAG;
tempw2=(templ&1)?0x8000:0;
- if (tempw&1) flags|=C_FLAG;
- else flags&=~C_FLAG;
+ if (tempw&1) cpu_state.flags |= C_FLAG;
+ else cpu_state.flags &= ~C_FLAG;
tempw=(tempw>>1)|tempw2;
c--;
cycles-=4;
}
- if (tempw2) flags|=C_FLAG;
- else flags&=~C_FLAG;
+ if (tempw2) cpu_state.flags |= C_FLAG;
+ else cpu_state.flags &= ~C_FLAG;
seteaw(tempw);
- if ((tempw^(tempw>>1))&0x4000) flags|=V_FLAG;
- else flags&=~V_FLAG;
+ if ((tempw^(tempw>>1))&0x4000) cpu_state.flags |= V_FLAG;
+ else cpu_state.flags &= ~V_FLAG;
cycles-=((cpu_mod==3)?8:28);
break;
if (c>16)
{
tempw=0;
- flags&=~C_FLAG;
+ cpu_state.flags &= ~C_FLAG;
}
else
{
- if ((tempw<<(c-1))&0x8000) flags|=C_FLAG;
- else flags&=~C_FLAG;
+ if ((tempw<<(c-1))&0x8000) cpu_state.flags |= C_FLAG;
+ else cpu_state.flags &= ~C_FLAG;
tempw<<=c;
}
seteaw(tempw);
setznp16(tempw);
cycles-=(c*4);
cycles-=((cpu_mod==3)?8:28);
- flags|=A_FLAG;
+ cpu_state.flags |= A_FLAG;
break;
case 0x28: /*SHR w,CL*/
if (c > 16)
{
tempw = 0;
- flags &= ~C_FLAG;
+ cpu_state.flags &= ~C_FLAG;
}
else
{
- if ((tempw>>(c-1))&1) flags|=C_FLAG;
- else flags&=~C_FLAG;
+ if ((tempw>>(c-1))&1) cpu_state.flags |= C_FLAG;
+ else cpu_state.flags &= ~C_FLAG;
tempw>>=c;
}
seteaw(tempw);
setznp16(tempw);
cycles-=(c*4);
cycles-=((cpu_mod==3)?8:28);
- flags|=A_FLAG;
+ cpu_state.flags |= A_FLAG;
break;
case 0x38: /*SAR w,CL*/
tempw2=tempw&0x8000;
- if ((tempw>>(c-1))&1) flags|=C_FLAG;
- else flags&=~C_FLAG;
+ if ((tempw>>(c-1))&1) cpu_state.flags |= C_FLAG;
+ else cpu_state.flags &= ~C_FLAG;
while (c>0)
{
tempw=(tempw>>1)|tempw2;
seteaw(tempw);
setznp16(tempw);
cycles-=((cpu_mod==3)?8:28);
- flags|=A_FLAG;
+ cpu_state.flags |= A_FLAG;
break;
// default:
cycles-=60;
break;
case 0xD6: /*SETALC*/
- AL = (flags & C_FLAG) ? 0xff : 0;
+ AL = (cpu_state.flags & C_FLAG) ? 0xff : 0;
cycles -= 4;
break;
case 0xD7: /*XLAT*/
AL=readmemb(ds+addr);
cycles-=11;
break;
- case 0xD9: case 0xDA: case 0xDB: case 0xDD: /*ESCAPE*/
- case 0xDC: case 0xDE: case 0xDF: case 0xD8:
+
+ case 0xd8:
+ fetchea();
+ if (hasfpu)
+ {
+ uint16_t save_pc = cpu_state.pc;
+ ops_808x_fpu_d8_a16[rmdat >> 3](rmdat);
+ cpu_state.pc = save_pc;
+ }
+ break;
+ case 0xd9:
fetchea();
- geteab();
+ if (hasfpu)
+ {
+ uint16_t save_pc = cpu_state.pc;
+ ops_808x_fpu_d9_a16[rmdat](rmdat);
+ cpu_state.pc = save_pc;
+ }
+ break;
+ case 0xda:
+ fetchea();
+ if (hasfpu)
+ {
+ uint16_t save_pc = cpu_state.pc;
+ ops_808x_fpu_da_a16[rmdat](rmdat);
+ cpu_state.pc = save_pc;
+ }
+ break;
+ case 0xdb:
+ fetchea();
+ if (hasfpu)
+ {
+ uint16_t save_pc = cpu_state.pc;
+ ops_808x_fpu_db_a16[rmdat](rmdat);
+ cpu_state.pc = save_pc;
+ }
+ break;
+ case 0xdc:
+ fetchea();
+ if (hasfpu)
+ {
+ uint16_t save_pc = cpu_state.pc;
+ ops_808x_fpu_dc_a16[rmdat >> 3](rmdat);
+ cpu_state.pc = save_pc;
+ }
+ break;
+ case 0xdd:
+ fetchea();
+ if (hasfpu)
+ {
+ uint16_t save_pc = cpu_state.pc;
+ ops_808x_fpu_dd_a16[rmdat](rmdat);
+ cpu_state.pc = save_pc;
+ }
+ break;
+ case 0xde:
+ fetchea();
+ if (hasfpu)
+ {
+ uint16_t save_pc = cpu_state.pc;
+ ops_808x_fpu_de_a16[rmdat](rmdat);
+ cpu_state.pc = save_pc;
+ }
+ break;
+ case 0xdf:
+ fetchea();
+ if (hasfpu)
+ {
+ uint16_t save_pc = cpu_state.pc;
+ ops_808x_fpu_df_a16[rmdat](rmdat);
+ cpu_state.pc = save_pc;
+ }
break;
case 0xE0: /*LOOPNE*/
offset=(int8_t)FETCH();
CX--;
- if (CX && !(flags&Z_FLAG)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); }
+ if (CX && !(cpu_state.flags & Z_FLAG)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); }
cycles-=6;
break;
case 0xE1: /*LOOPE*/
offset=(int8_t)FETCH();
CX--;
- if (CX && (flags&Z_FLAG)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); }
+ if (CX && (cpu_state.flags & Z_FLAG)) { cpu_state.pc+=offset; cycles-=12; FETCHCLEAR(); }
cycles-=6;
break;
case 0xE2: /*LOOP*/
break;
case 0xF4: /*HLT*/
-// printf("IN HLT!!!! %04X:%04X %08X %08X %08X\n",oldcs,oldpc,old8,old82,old83);
+// printf("IN HLT!!!! %04X %08X %08X %08X\n",oldpc,old8,old82,old83);
/* if (!(flags & I_FLAG))
{
pclog("HLT\n");
cycles-=2;
break;
case 0xF5: /*CMC*/
- flags^=C_FLAG;
+ cpu_state.flags ^= C_FLAG;
cycles-=2;
break;
temp2=FETCH();
temp&=temp2;
setznp8(temp);
- flags&=~(C_FLAG|V_FLAG|A_FLAG);
+ cpu_state.flags &= ~(C_FLAG|V_FLAG|A_FLAG);
cycles-=((cpu_mod==3)?5:11);
break;
case 0x10: /*NOT b*/
case 0x20: /*MUL AL,b*/
setznp8(AL);
AX=AL*temp;
- if (AX) flags&=~Z_FLAG;
- else flags|=Z_FLAG;
- if (AH) flags|=(C_FLAG|V_FLAG);
- else flags&=~(C_FLAG|V_FLAG);
+ if (AX) cpu_state.flags &= ~Z_FLAG;
+ else cpu_state.flags |= Z_FLAG;
+ if (AH) cpu_state.flags |= (C_FLAG|V_FLAG);
+ else cpu_state.flags &= ~(C_FLAG|V_FLAG);
cycles-=70;
break;
case 0x28: /*IMUL AL,b*/
setznp8(AL);
tempws=(int)((int8_t)AL)*(int)((int8_t)temp);
AX=tempws&0xFFFF;
- if (AX) flags&=~Z_FLAG;
- else flags|=Z_FLAG;
- if (AH) flags|=(C_FLAG|V_FLAG);
- else flags&=~(C_FLAG|V_FLAG);
+ if (AX) cpu_state.flags &= ~Z_FLAG;
+ else cpu_state.flags |= Z_FLAG;
+ if (AH) cpu_state.flags |= (C_FLAG|V_FLAG);
+ else cpu_state.flags &= ~(C_FLAG|V_FLAG);
cycles-=80;
break;
case 0x30: /*DIV AL,b*/
else
{
printf("DIVb BY 0 %04X:%04X\n",cs>>4,cpu_state.pc);
- writememw(ss,(SP-2)&0xFFFF,flags|0xF000);
+ writememw(ss,(SP-2)&0xFFFF,cpu_state.flags | 0xF000);
writememw(ss,(SP-4)&0xFFFF,CS);
writememw(ss,(SP-6)&0xFFFF,cpu_state.pc);
SP-=6;
- flags&=~I_FLAG;
- flags&=~T_FLAG;
+ cpu_state.flags &= ~I_FLAG;
+ cpu_state.flags &= ~T_FLAG;
cpu_state.pc=readmemw(0,0);
// printf("F6 30\n");
loadcs(readmemw(0,2));
else
{
printf("IDIVb BY 0 %04X:%04X\n",cs>>4,cpu_state.pc);
- writememw(ss,(SP-2)&0xFFFF,flags|0xF000);
+ writememw(ss,(SP-2)&0xFFFF,cpu_state.flags | 0xF000);
writememw(ss,(SP-4)&0xFFFF,CS);
writememw(ss,(SP-6)&0xFFFF,cpu_state.pc);
SP-=6;
- flags&=~I_FLAG;
- flags&=~T_FLAG;
+ cpu_state.flags &= ~I_FLAG;
+ cpu_state.flags &= ~T_FLAG;
cpu_state.pc=readmemw(0,0);
// printf("F6 38\n");
loadcs(readmemw(0,2));
case 0x08:
tempw2=getword();
setznp16(tempw&tempw2);
- flags&=~(C_FLAG|V_FLAG|A_FLAG);
+ cpu_state.flags &= ~(C_FLAG|V_FLAG|A_FLAG);
cycles-=((cpu_mod==3)?5:11);
break;
case 0x10: /*NOT w*/
// if (output) printf("%04X*%04X=%08X\n",AX,tempw,templ);
AX=templ&0xFFFF;
DX=templ>>16;
- if (AX|DX) flags&=~Z_FLAG;
- else flags|=Z_FLAG;
- if (DX) flags|=(C_FLAG|V_FLAG);
- else flags&=~(C_FLAG|V_FLAG);
+ if (AX|DX) cpu_state.flags &= ~Z_FLAG;
+ else cpu_state.flags |= Z_FLAG;
+ if (DX) cpu_state.flags |= (C_FLAG|V_FLAG);
+ else cpu_state.flags &= ~(C_FLAG|V_FLAG);
cycles-=118;
break;
case 0x28: /*IMUL AX,w*/
setznp16(AX);
// printf("IMUL %i %i ",(int)((int16_t)AX),(int)((int16_t)tempw));
tempws=(int)((int16_t)AX)*(int)((int16_t)tempw);
- if ((tempws>>15) && ((tempws>>15)!=-1)) flags|=(C_FLAG|V_FLAG);
- else flags&=~(C_FLAG|V_FLAG);
+ if ((tempws>>15) && ((tempws>>15)!=-1)) cpu_state.flags |= (C_FLAG|V_FLAG);
+ else cpu_state.flags &= ~(C_FLAG|V_FLAG);
// printf("%i ",tempws);
AX=tempws&0xFFFF;
tempws=(uint16_t)(tempws>>16);
// printf("%04X %04X\n",AX,DX);
// dumpregs();
// exit(-1);
- if (AX|DX) flags&=~Z_FLAG;
- else flags|=Z_FLAG;
+ if (AX|DX) cpu_state.flags &= ~Z_FLAG;
+ else cpu_state.flags |= Z_FLAG;
cycles-=128;
break;
case 0x30: /*DIV AX,w*/
else
{
printf("DIVw BY 0 %04X:%04X\n",cs>>4,cpu_state.pc);
- writememw(ss,(SP-2)&0xFFFF,flags|0xF000);
+ writememw(ss,(SP-2)&0xFFFF,cpu_state.flags | 0xF000);
writememw(ss,(SP-4)&0xFFFF,CS);
writememw(ss,(SP-6)&0xFFFF,cpu_state.pc);
SP-=6;
- flags&=~I_FLAG;
- flags&=~T_FLAG;
+ cpu_state.flags &= ~I_FLAG;
+ cpu_state.flags &= ~T_FLAG;
cpu_state.pc=readmemw(0,0);
// printf("F7 30\n");
loadcs(readmemw(0,2));
else
{
printf("IDIVw BY 0 %04X:%04X\n",cs>>4,cpu_state.pc);
- writememw(ss,(SP-2)&0xFFFF,flags|0xF000);
+ writememw(ss,(SP-2)&0xFFFF,cpu_state.flags | 0xF000);
writememw(ss,(SP-4)&0xFFFF,CS);
writememw(ss,(SP-6)&0xFFFF,cpu_state.pc);
SP-=6;
- flags&=~I_FLAG;
- flags&=~T_FLAG;
+ cpu_state.flags &= ~I_FLAG;
+ cpu_state.flags &= ~T_FLAG;
cpu_state.pc=readmemw(0,0);
// printf("F7 38\n");
loadcs(readmemw(0,2));
break;
case 0xF8: /*CLC*/
- flags&=~C_FLAG;
+ cpu_state.flags &= ~C_FLAG;
cycles-=2;
break;
case 0xF9: /*STC*/
// printf("STC %04X\n",pc);
- flags|=C_FLAG;
+ cpu_state.flags |= C_FLAG;
cycles-=2;
break;
case 0xFA: /*CLI*/
- flags&=~I_FLAG;
+ cpu_state.flags &= ~I_FLAG;
// printf("CLI at %04X:%04X\n",cs>>4,pc);
cycles-=3;
break;
case 0xFB: /*STI*/
- flags|=I_FLAG;
+ cpu_state.flags |= I_FLAG;
// printf("STI at %04X:%04X\n",cs>>4,pc);
cycles-=2;
break;
case 0xFC: /*CLD*/
- flags&=~D_FLAG;
+ cpu_state.flags &= ~D_FLAG;
cycles-=2;
break;
case 0xFD: /*STD*/
- flags|=D_FLAG;
+ cpu_state.flags |= D_FLAG;
cycles-=2;
break;
case 0xFE: /*INC/DEC b*/
fetchea();
temp=geteab();
- flags&=~V_FLAG;
+ cpu_state.flags &= ~V_FLAG;
if (rmdat&0x38)
{
setsub8nc(temp,1);
temp2=temp-1;
- if ((temp&0x80) && !(temp2&0x80)) flags|=V_FLAG;
+ if ((temp&0x80) && !(temp2&0x80)) cpu_state.flags |= V_FLAG;
}
else
{
setadd8nc(temp,1);
temp2=temp+1;
- if ((temp2&0x80) && !(temp&0x80)) flags|=V_FLAG;
+ if ((temp2&0x80) && !(temp&0x80)) cpu_state.flags |= V_FLAG;
}
// setznp8(temp2);
seteab(temp2);
// if (instime) printf("%i %i %i %i\n",cycdiff,cycles,memcycs,fetchclocks);
FETCHADD(((cycdiff-cycles)-memcycs)-fetchclocks);
if ((cycdiff-cycles)<memcycs) cycles-=(memcycs-(cycdiff-cycles));
- if (romset==ROM_IBMPC)
- {
- if ((cs+cpu_state.pc)==0xFE4A7) /*You didn't seriously think I was going to emulate the cassette, did you?*/
- {
- CX=1;
- BX=0x500;
- }
- }
memcycs=0;
insc++;
clockhardware();
- if (trap && (flags&T_FLAG) && !noint)
+ if (trap && (cpu_state.flags & T_FLAG) && !noint)
{
// printf("TRAP!!! %04X:%04X\n",CS,pc);
- writememw(ss,(SP-2)&0xFFFF,flags|0xF000);
+ writememw(ss,(SP-2)&0xFFFF,cpu_state.flags | 0xF000);
writememw(ss,(SP-4)&0xFFFF,CS);
writememw(ss,(SP-6)&0xFFFF,cpu_state.pc);
SP-=6;
addr=1<<2;
- flags&=~I_FLAG;
- flags&=~T_FLAG;
+ cpu_state.flags &= ~I_FLAG;
+ cpu_state.flags &= ~T_FLAG;
cpu_state.pc=readmemw(0,addr);
loadcs(readmemw(0,addr+2));
FETCHCLEAR();
else if (nmi && nmi_enable && nmi_mask)
{
// output = 3;
- writememw(ss,(SP-2)&0xFFFF,flags|0xF000);
+ writememw(ss,(SP-2)&0xFFFF,cpu_state.flags | 0xF000);
writememw(ss,(SP-4)&0xFFFF,CS);
writememw(ss,(SP-6)&0xFFFF,cpu_state.pc);
SP-=6;
addr=2<<2;
- flags&=~I_FLAG;
- flags&=~T_FLAG;
+ cpu_state.flags &= ~I_FLAG;
+ cpu_state.flags &= ~T_FLAG;
cpu_state.pc=readmemw(0,addr);
loadcs(readmemw(0,addr+2));
FETCHCLEAR();
if (temp!=0xFF)
{
if (inhlt) cpu_state.pc++;
- writememw(ss,(SP-2)&0xFFFF,flags|0xF000);
+ writememw(ss,(SP-2)&0xFFFF,cpu_state.flags | 0xF000);
writememw(ss,(SP-4)&0xFFFF,CS);
writememw(ss,(SP-6)&0xFFFF,cpu_state.pc);
SP-=6;
addr=temp<<2;
- flags&=~I_FLAG;
- flags&=~T_FLAG;
+ cpu_state.flags &= ~I_FLAG;
+ cpu_state.flags &= ~T_FLAG;
cpu_state.pc=readmemw(0,addr);
// printf("INT INT INT\n");
loadcs(readmemw(0,addr+2));
// printf("INTERRUPT\n");
}
}
- takeint = (flags&I_FLAG) && (pic.pend&~pic.mask);
+ takeint = (cpu_state.flags & I_FLAG) && (pic.pend&~pic.mask);
if (noint) noint=0;
ins++;
#include "mem.h"
#include "x86_ops.h"
-#ifdef __amd64__
-#include "codegen_x86-64.h"
-#elif defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined WIN32 || defined _WIN32 || defined _WIN32
-#include "codegen_x86.h"
-#else
-#error Dynamic recompiler not implemented on your platform
-#endif
-
/*Handling self-modifying code (of which there is a lot on x86) :
PCem tracks a 'dirty mask' for each physical page, in which each bit
typedef struct codeblock_t
{
+ uint32_t pc;
+ uint32_t _cs;
+ uint32_t phys, phys_2;
+ uint16_t status;
+ uint16_t flags;
+ uint8_t ins;
+ uint8_t TOP;
+
+ /*Pointers for codeblock tree, used to search for blocks when hash lookup
+ fails.*/
+ uint16_t parent, left, right;
+
+ uint8_t *data;
+
uint64_t page_mask, page_mask2;
uint64_t *dirty_mask, *dirty_mask2;
- uint64_t cmp;
-
+
/*Previous and next pointers, for the codeblock list associated with
each physical page. Two sets of pointers, as a codeblock can be
present in two pages.*/
- struct codeblock_t *prev, *next;
- struct codeblock_t *prev_2, *next_2;
-
- /*Pointers for codeblock tree, used to search for blocks when hash lookup
- fails.*/
- struct codeblock_t *parent, *left, *right;
-
- int pnt;
- int ins;
-
- int was_recompiled;
- int TOP;
-
- uint32_t pc;
- uint32_t _cs;
- uint32_t endpc;
- uint32_t phys, phys_2;
- uint32_t status;
- uint32_t flags;
+ uint16_t prev, next;
+ uint16_t prev_2, next_2;
- uint8_t data[2048];
+ /*First mem_block_t used by this block. Any subsequent mem_block_ts
+ will be in the list starting at head_mem_block->next.*/
+ struct mem_block_t *head_mem_block;
} codeblock_t;
+extern codeblock_t *codeblock;
+
+extern uint16_t *codeblock_hash;
+
+extern uint8_t *block_write_data;
+
/*Code block uses FPU*/
#define CODEBLOCK_HAS_FPU 1
/*Code block is always entered with the same FPU top-of-stack*/
#define CODEBLOCK_STATIC_TOP 2
+/*Code block has been compiled*/
+#define CODEBLOCK_WAS_RECOMPILED 4
+/*Code block is in free list and is not valid*/
+#define CODEBLOCK_IN_FREE_LIST 8
+/*Code block spans two pages, page_mask2 and dirty_mask2 are valid*/
+#define CODEBLOCK_HAS_PAGE2 0x10
+/*Code block is using a byte mask for code present and dirty*/
+#define CODEBLOCK_BYTE_MASK 0x20
+/*Code block is in dirty list*/
+#define CODEBLOCK_IN_DIRTY_LIST 0x40
+/*Code block is not inlining immediate parameters, parameters must be fetched from memory*/
+#define CODEBLOCK_NO_IMMEDIATES 0x80
#define BLOCK_PC_INVALID 0xffffffff
+#define BLOCK_INVALID 0
+
+static inline int get_block_nr(codeblock_t *block)
+{
+ return ((uintptr_t)block - (uintptr_t)codeblock) / sizeof(codeblock_t);
+}
+
static inline codeblock_t *codeblock_tree_find(uint32_t phys, uint32_t _cs)
{
- codeblock_t *block = pages[phys >> 12].head;
+ codeblock_t *block;
uint64_t a = _cs | ((uint64_t)phys << 32);
+ if (!pages[phys >> 12].head)
+ return NULL;
+
+ block = &codeblock[pages[phys >> 12].head];
while (block)
{
- if (a == block->cmp)
+ uint64_t block_cmp = block->_cs | ((uint64_t)block->phys << 32);
+ if (a == block_cmp)
{
if (!((block->status ^ cpu_cur_status) & CPU_STATUS_FLAGS) &&
((block->status & cpu_cur_status & CPU_STATUS_MASK) == (cpu_cur_status & CPU_STATUS_MASK)))
break;
}
- if (a < block->cmp)
- block = block->left;
+ if (a < block_cmp)
+ block = block->left ? &codeblock[block->left] : NULL;
else
- block = block->right;
+ block = block->right ? &codeblock[block->right] : NULL;
}
return block;
static inline void codeblock_tree_add(codeblock_t *new_block)
{
- codeblock_t *block = pages[new_block->phys >> 12].head;
+ codeblock_t *block = &codeblock[pages[new_block->phys >> 12].head];
uint64_t a = new_block->_cs | ((uint64_t)new_block->phys << 32);
- new_block->cmp = a;
-
- if (!block)
+
+ if (!pages[new_block->phys >> 12].head)
{
- pages[new_block->phys >> 12].head = new_block;
- new_block->parent = new_block->left = new_block->right = NULL;
+ pages[new_block->phys >> 12].head = get_block_nr(new_block);
+ new_block->parent = new_block->left = new_block->right = BLOCK_INVALID;
}
else
{
codeblock_t *old_block = NULL;
+ uint64_t old_block_cmp = 0;
while (block)
{
old_block = block;
- if (a < old_block->cmp)
- block = block->left;
+ old_block_cmp = old_block->_cs | ((uint64_t)old_block->phys << 32);
+
+ if (a < old_block_cmp)
+ block = block->left ? &codeblock[block->left] : NULL;
else
- block = block->right;
+ block = block->right ? &codeblock[block->right] : NULL;
}
- if (a < old_block->cmp)
- old_block->left = new_block;
+ if (a < old_block_cmp)
+ old_block->left = get_block_nr(new_block);
else
- old_block->right = new_block;
+ old_block->right = get_block_nr(new_block);
- new_block->parent = old_block;
- new_block->left = new_block->right = NULL;
+ new_block->parent = get_block_nr(old_block);
+ new_block->left = new_block->right = BLOCK_INVALID;
}
}
static inline void codeblock_tree_delete(codeblock_t *block)
{
- codeblock_t *parent = block->parent;
+ uint16_t parent_nr = block->parent;
+ codeblock_t *parent;
+
+ if (block->parent)
+ parent = &codeblock[block->parent];
+ else
+ parent = NULL;
if (!block->left && !block->right)
{
/*Easy case - remove from parent*/
if (!parent)
- pages[block->phys >> 12].head = NULL;
+ pages[block->phys >> 12].head = BLOCK_INVALID;
else
{
- if (parent->left == block)
- parent->left = NULL;
- if (parent->right == block)
- parent->right = NULL;
+ uint16_t block_nr = get_block_nr(block);
+
+ if (parent->left == block_nr)
+ parent->left = BLOCK_INVALID;
+ if (parent->right == block_nr)
+ parent->right = BLOCK_INVALID;
}
return;
}
else if (!block->left)
{
/*Only right node*/
- if (!parent)
+ if (!parent_nr)
{
pages[block->phys >> 12].head = block->right;
- pages[block->phys >> 12].head->parent = NULL;
+ codeblock[pages[block->phys >> 12].head].parent = BLOCK_INVALID;
}
else
{
- if (parent->left == block)
+ uint16_t block_nr = get_block_nr(block);
+
+ if (parent->left == block_nr)
{
parent->left = block->right;
- parent->left->parent = parent;
+ codeblock[parent->left].parent = parent_nr;
}
- if (parent->right == block)
+ if (parent->right == block_nr)
{
parent->right = block->right;
- parent->right->parent = parent;
+ codeblock[parent->right].parent = parent_nr;
}
}
return;
else if (!block->right)
{
/*Only left node*/
- if (!parent)
+ if (!parent_nr)
{
pages[block->phys >> 12].head = block->left;
- pages[block->phys >> 12].head->parent = NULL;
+ codeblock[pages[block->phys >> 12].head].parent = BLOCK_INVALID;
}
else
{
- if (parent->left == block)
+ uint16_t block_nr = get_block_nr(block);
+
+ if (parent->left == block_nr)
{
parent->left = block->left;
- parent->left->parent = parent;
+ codeblock[parent->left].parent = parent_nr;
}
- if (parent->right == block)
+ if (parent->right == block_nr)
{
parent->right = block->left;
- parent->right->parent = parent;
+ codeblock[parent->right].parent = parent_nr;
}
}
return;
else
{
/*Difficult case - node has two children. Walk right child to find lowest node*/
- codeblock_t *lowest = block->right, *highest;
+ codeblock_t *lowest = &codeblock[block->right], *highest;
codeblock_t *old_parent;
+ uint16_t lowest_nr;
while (lowest->left)
- lowest = lowest->left;
-
- old_parent = lowest->parent;
+ lowest = &codeblock[lowest->left];
+ lowest_nr = get_block_nr(lowest);
+
+ old_parent = &codeblock[lowest->parent];
/*Replace deleted node with lowest node*/
- if (!parent)
- pages[block->phys >> 12].head = lowest;
+ if (!parent_nr)
+ pages[block->phys >> 12].head = lowest_nr;
else
{
- if (parent->left == block)
- parent->left = lowest;
- if (parent->right == block)
- parent->right = lowest;
+ uint16_t block_nr = get_block_nr(block);
+
+ if (parent->left == block_nr)
+ parent->left = lowest_nr;
+ if (parent->right == block_nr)
+ parent->right = lowest_nr;
}
- lowest->parent = parent;
+ lowest->parent = parent_nr;
lowest->left = block->left;
if (lowest->left)
- lowest->left->parent = lowest;
+ codeblock[lowest->left].parent = lowest_nr;
- old_parent->left = NULL;
+ old_parent->left = BLOCK_INVALID;
- highest = lowest->right;
- if (!highest)
+ highest = &codeblock[lowest->right];
+ if (!lowest->right)
{
- if (lowest != block->right)
+ if (lowest_nr != block->right)
{
lowest->right = block->right;
- block->right->parent = lowest;
+ codeblock[block->right].parent = lowest_nr;
}
return;
}
while (highest->right)
- highest = highest->right;
+ highest = &codeblock[highest->right];
- if (block->right && block->right != lowest)
+ if (block->right && block->right != lowest_nr)
{
highest->right = block->right;
- block->right->parent = highest;
+ codeblock[block->right].parent = get_block_nr(highest);
}
}
}
-#define PAGE_MASK_INDEX_MASK 3
-#define PAGE_MASK_INDEX_SHIFT 10
#define PAGE_MASK_MASK 63
-#define PAGE_MASK_SHIFT 4
+#define PAGE_MASK_SHIFT 6
-extern codeblock_t *codeblock;
+void codegen_mark_code_present_multibyte(codeblock_t *block, uint32_t start_pc, int len);
-extern codeblock_t **codeblock_hash;
+static inline void codegen_mark_code_present(codeblock_t *block, uint32_t start_pc, int len)
+{
+ if (len == 1)
+ {
+ if (block->flags & CODEBLOCK_BYTE_MASK)
+ {
+ if (!((start_pc ^ block->pc) & ~0x3f)) /*Starts in second page*/
+ block->page_mask |= ((uint64_t)1 << (start_pc & PAGE_MASK_MASK));
+ else
+ block->page_mask2 |= ((uint64_t)1 << (start_pc & PAGE_MASK_MASK));
+ }
+ else
+ {
+ if (!((start_pc ^ block->pc) & ~0xfff)) /*Starts in second page*/
+ block->page_mask |= ((uint64_t)1 << ((start_pc >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK));
+ else
+ block->page_mask2 |= ((uint64_t)1 << ((start_pc >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK));
+ }
+ }
+ else
+ codegen_mark_code_present_multibyte(block, start_pc, len);
+}
void codegen_init();
+void codegen_close();
void codegen_reset();
void codegen_block_init(uint32_t phys_addr);
void codegen_block_remove();
void codegen_block_start_recompile(codeblock_t *block);
void codegen_block_end_recompile(codeblock_t *block);
void codegen_block_end();
+void codegen_delete_block(codeblock_t *block);
void codegen_generate_call(uint8_t opcode, OpFn op, uint32_t fetchdat, uint32_t new_pc, uint32_t old_pc);
void codegen_generate_seg_restore();
void codegen_set_op32();
void codegen_flush();
void codegen_check_flush(struct page_t *page, uint64_t mask, uint32_t phys_addr);
+struct ir_data_t;
+x86seg *codegen_generate_ea(struct ir_data_t *ir, x86seg *op_ea_seg, uint32_t fetchdat, int op_ssegs, uint32_t *op_pc, uint32_t op_32, int stack_offset);
+void codegen_check_seg_read(codeblock_t *block, struct ir_data_t *ir, x86seg *seg);
+void codegen_check_seg_write(codeblock_t *block, struct ir_data_t *ir, x86seg *seg);
+
+int codegen_purge_purgable_list();
+/*Delete a random code block to free memory. This is obviously quite expensive, and
+ will only be called when the allocator is out of memory*/
+void codegen_delete_random_block(int required_mem_block);
extern int cpu_block_end;
extern uint32_t codegen_endpc;
extern void (*codegen_timing_start)();
extern void (*codegen_timing_prefix)(uint8_t prefix, uint32_t fetchdat);
-extern void (*codegen_timing_opcode)(uint8_t opcode, uint32_t fetchdat, int op_32);
+extern void (*codegen_timing_opcode)(uint8_t opcode, uint32_t fetchdat, int op_32, uint32_t op_pc);
extern void (*codegen_timing_block_start)();
extern void (*codegen_timing_block_end)();
+extern int (*codegen_timing_jump_cycles)();
typedef struct codegen_timing_t
{
void (*start)();
void (*prefix)(uint8_t prefix, uint32_t fetchdat);
- void (*opcode)(uint8_t opcode, uint32_t fetchdat, int op_32);
+ void (*opcode)(uint8_t opcode, uint32_t fetchdat, int op_32, uint32_t op_pc);
void (*block_start)();
void (*block_end)();
+ int (*jump_cycles)();
} codegen_timing_t;
extern codegen_timing_t codegen_timing_pentium;
extern codegen_timing_t codegen_timing_686;
extern codegen_timing_t codegen_timing_486;
extern codegen_timing_t codegen_timing_winchip;
+extern codegen_timing_t codegen_timing_winchip2;
+extern codegen_timing_t codegen_timing_k6;
void codegen_timing_set(codegen_timing_t *timing);
#define CPU_BLOCK_END() cpu_block_end = 1
-static inline void addbyte(uint8_t val)
-{
- codeblock[block_current].data[block_pos++] = val;
- if (block_pos >= BLOCK_MAX)
- {
- CPU_BLOCK_END();
- }
-}
-
-static inline void addword(uint16_t val)
-{
- *(uint16_t *)(void *)&codeblock[block_current].data[block_pos] = val;
- block_pos += 2;
- if (block_pos >= BLOCK_MAX)
- {
- CPU_BLOCK_END();
- }
-}
-
-static inline void addlong(uint32_t val)
-{
- *(uint32_t *)&codeblock[block_current].data[block_pos] = val;
- block_pos += 4;
- if (block_pos >= BLOCK_MAX)
- {
- CPU_BLOCK_END();
- }
-}
-
-static inline void addquad(uint64_t val)
-{
- *(uint64_t *)&codeblock[block_current].data[block_pos] = val;
- block_pos += 8;
- if (block_pos >= BLOCK_MAX)
- {
- CPU_BLOCK_END();
- }
-}
-
/*Current physical page of block being recompiled. -1 if no recompilation taking place */
extern uint32_t recomp_page;
extern int codegen_in_recompile;
+void codegen_generate_reset();
+
+int codegen_get_instruction_uop(codeblock_t *block, uint32_t pc, int *first_instruction, int *TOP);
+void codegen_set_loop_start(struct ir_data_t *ir, int first_instruction);
+
+#ifdef DEBUG_EXTRA
+extern uint32_t instr_counts[256*256];
+#endif
+
#endif
--- /dev/null
+#ifndef _CODEGEN_BACKEND_H_
+#define _CODEGEN_BACKEND_H_
+
+//#ifdef __amd64__
+//#include "codegen_x86-64.h"
+#if defined __amd64__
+#include "codegen_backend_x86-64.h"
+#elif defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined WIN32 || defined _WIN32 || defined _WIN32
+#include "codegen_backend_x86.h"
+#elif defined __ARM_EABI__
+#include "codegen_backend_arm.h"
+#elif defined __aarch64__
+#include "codegen_backend_arm64.h"
+#else
+#error Dynamic recompiler not implemented on your platform
+#endif
+
+void codegen_backend_init();
+void codegen_backend_prologue(codeblock_t *block);
+void codegen_backend_epilogue(codeblock_t *block);
+
+struct ir_data_t;
+struct uop_t;
+
+struct ir_data_t *codegen_get_ir_data();
+
+typedef int (*uOpFn)(codeblock_t *codeblock, struct uop_t *uop);
+
+extern const uOpFn uop_handlers[];
+
+/*Register will not be preserved across function calls*/
+#define HOST_REG_FLAG_VOLATILE (1 << 0)
+
+typedef struct host_reg_def_t
+{
+ int reg;
+ int flags;
+} host_reg_def_t;
+
+extern host_reg_def_t codegen_host_reg_list[CODEGEN_HOST_REGS];
+extern host_reg_def_t codegen_host_fp_reg_list[CODEGEN_HOST_FP_REGS];
+
+#endif
--- /dev/null
+#include "codegen_backend_x86-64_defs.h"
+
+#define BLOCK_SIZE 0x4000
+#define BLOCK_MASK 0x3fff
+#define BLOCK_START 0
+
+#define HASH_SIZE 0x20000
+#define HASH_MASK 0x1ffff
+
+#define HASH(l) ((l) & 0x1ffff)
+
+#define BLOCK_MAX 0x3c0
--- /dev/null
+/*RBP = cpu_state + 128
+ R12 = ram (if block->flags & CODEBLOCK_NO_IMMEDIATES)*/
+#define REG_AX 0
+#define REG_CX 1
+#define REG_DX 2
+#define REG_BX 3
+#define REG_SP 4
+#define REG_BP 5
+#define REG_SI 6
+#define REG_DI 7
+
+#define REG_EAX 0
+#define REG_ECX 1
+#define REG_EDX 2
+#define REG_EBX 3
+#define REG_ESP 4
+#define REG_EBP 5
+#define REG_ESI 6
+#define REG_EDI 7
+
+#define REG_RAX 0
+#define REG_RCX 1
+#define REG_RDX 2
+#define REG_RBX 3
+#define REG_RSP 4
+#define REG_RBP 5
+#define REG_RSI 6
+#define REG_RDI 7
+#define REG_R8 8
+#define REG_R9 9
+#define REG_R10 10
+#define REG_R11 11
+#define REG_R12 12
+#define REG_R13 13
+#define REG_R14 14
+#define REG_R15 15
+
+#define REG_XMM0 0
+#define REG_XMM1 1
+#define REG_XMM2 2
+#define REG_XMM3 3
+#define REG_XMM4 4
+#define REG_XMM5 5
+#define REG_XMM6 6
+#define REG_XMM7 7
+
+#define REG_XMM_TEMP REG_XMM0
+
+#define CODEGEN_HOST_REGS 3
+#define CODEGEN_HOST_FP_REGS 7
+
+extern void *codegen_mem_load_byte;
+extern void *codegen_mem_load_word;
+extern void *codegen_mem_load_long;
+extern void *codegen_mem_load_quad;
+extern void *codegen_mem_load_single;
+extern void *codegen_mem_load_double;
+
+extern void *codegen_mem_store_byte;
+extern void *codegen_mem_store_word;
+extern void *codegen_mem_store_long;
+extern void *codegen_mem_store_quad;
+extern void *codegen_mem_store_single;
+extern void *codegen_mem_store_double;
+
+extern void *codegen_gpf_rout;
+extern void *codegen_exit_rout;
--- /dev/null
+#include "codegen_backend_x86_defs.h"
+
+#define BLOCK_SIZE 0x10000
+#define BLOCK_MASK 0xffff
+#define BLOCK_START 0
+
+#define HASH_SIZE 0x20000
+#define HASH_MASK 0x1ffff
+
+#define HASH(l) ((l) & 0x1ffff)
+
+#define BLOCK_MAX 0x3c0
--- /dev/null
+#ifndef _CODEGEN_BACKEND_X86_DEFS_H_
+#define _CODEGEN_BACKEND_X86_DEFS_H_
+
+#define REG_EAX 0
+#define REG_ECX 1
+#define REG_EDX 2
+#define REG_EBX 3
+#define REG_ESP 4
+#define REG_EBP 5
+#define REG_ESI 6
+#define REG_EDI 7
+
+#define REG_XMM0 0
+#define REG_XMM1 1
+#define REG_XMM2 2
+#define REG_XMM3 3
+#define REG_XMM4 4
+#define REG_XMM5 5
+#define REG_XMM6 6
+#define REG_XMM7 7
+
+#define REG_XMM_TEMP REG_XMM7
+#define REG_XMM_TEMP2 REG_XMM6
+
+#define CODEGEN_HOST_REGS 3
+#define CODEGEN_HOST_FP_REGS 6
+
+extern void *codegen_mem_load_byte;
+extern void *codegen_mem_load_word;
+extern void *codegen_mem_load_long;
+extern void *codegen_mem_load_quad;
+extern void *codegen_mem_load_single;
+extern void *codegen_mem_load_double;
+
+extern void *codegen_mem_store_byte;
+extern void *codegen_mem_store_word;
+extern void *codegen_mem_store_long;
+extern void *codegen_mem_store_quad;
+extern void *codegen_mem_store_single;
+extern void *codegen_mem_store_double;
+
+extern void *codegen_gpf_rout;
+extern void *codegen_exit_rout;
+
+#define STACK_ARG0 (0)
+#define STACK_ARG1 (4)
+#define STACK_ARG2 (8)
+#define STACK_ARG3 (12)
+
+#endif
+++ /dev/null
-#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)
-
-#define BLOCK_MAX 1620
-
-enum
-{
- OP_RET = 0xc3
-};
-
-#define NR_HOST_REGS 4
-extern int host_reg_mapping[NR_HOST_REGS];
-#define NR_HOST_XMM_REGS 7
-extern int host_reg_xmm_mapping[NR_HOST_XMM_REGS];
+++ /dev/null
-#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)
-
-#define BLOCK_MAX 1720
-
-enum
-{
- OP_RET = 0xc3
-};
-
-#define NR_HOST_REGS 4
-extern int host_reg_mapping[NR_HOST_REGS];
-#define NR_HOST_XMM_REGS 7
-extern int host_reg_xmm_mapping[NR_HOST_XMM_REGS];
-
-extern uint32_t mem_load_addr_ea_b;
-extern uint32_t mem_load_addr_ea_w;
-extern uint32_t mem_load_addr_ea_l;
-extern uint32_t mem_load_addr_ea_q;
-extern uint32_t mem_store_addr_ea_b;
-extern uint32_t mem_store_addr_ea_w;
-extern uint32_t mem_store_addr_ea_l;
-extern uint32_t mem_store_addr_ea_q;
-
-extern uint32_t mem_load_addr_ea_b_no_abrt;
-extern uint32_t mem_store_addr_ea_b_no_abrt;
-extern uint32_t mem_load_addr_ea_w_no_abrt;
-extern uint32_t mem_store_addr_ea_w_no_abrt;
-extern uint32_t mem_load_addr_ea_l_no_abrt;
-extern uint32_t mem_store_addr_ea_l_no_abrt;
-extern uint32_t mem_check_write;
-extern uint32_t mem_check_write_w;
-extern uint32_t mem_check_write_l;
+float config_get_float(int is_global, char *head, char *name, float def);
+int config_get_int(int is_global, char *head, char *name, int def);
+char *config_get_string(int is_global, char *head, char *name, char *def);
+void config_set_float(int is_global, char *head, char *name, float val);
+void config_set_int(int is_global, char *head, char *name, int val);
+void config_set_string(int is_global, char *head, char *name, char *val);
+
+int config_free_section(int is_global, char *head);
+
+void add_config_callback(void(*loadconfig)(), void(*saveconfig)(), void(*onloaded)());
+
+char *get_filename(char *s);
+void append_filename(char *dest, char *s1, char *s2, int size);
+void append_slash(char *s, int size);
+void put_backslash(char *s);
+char *get_extension(char *s);
+
+void config_load(int is_global, char *fn);
+void config_save(int is_global, char *fn);
+void config_dump(int is_global);
+void config_free(int is_global);
+
+extern char config_file_default[256];
+extern char config_name[256];
+
+#define CFG_MACHINE 0
+#define CFG_GLOBAL 1
#include "mem.h"
#include "pci.h"
#include "codegen.h"
+#include "x87_timings.h"
+
+int fpu_type;
+uint32_t cpu_features;
static int cpu_turbo_speed, cpu_nonturbo_speed;
static int cpu_turbo = 1;
OpFn *x86_dynarec_opcodes_df_a32;
OpFn *x86_dynarec_opcodes_REPE;
OpFn *x86_dynarec_opcodes_REPNE;
+OpFn *x86_dynarec_opcodes_3DNOW;
OpFn *x86_opcodes;
OpFn *x86_opcodes_0f;
OpFn *x86_opcodes_df_a32;
OpFn *x86_opcodes_REPE;
OpFn *x86_opcodes_REPNE;
+OpFn *x86_opcodes_3DNOW;
enum
{
CPUID_MMX = (1 << 23)
};
+/*Addition flags returned by CPUID function 0x80000001*/
+enum
+{
+ CPUID_3DNOW = (1 << 31)
+};
+
int cpu = 3, cpu_manufacturer = 0;
CPU *cpu_s;
int cpu_multi;
int cpu_iscyrix;
int cpu_16bitbus;
int cpu_busspeed;
-int cpu_hasrdtsc;
-int cpu_hasMMX, cpu_hasMSR;
-int cpu_hasCR4;
-int cpu_hasCX8;
-int cpu_hasVME;
int cpu_use_dynarec;
int cpu_cyrix_alignment;
int cpu_cache_int_enabled, cpu_cache_ext_enabled;
int is386;
+int is486;
+int CPUID;
uint64_t tsc = 0;
uint64_t fcr2, fcr3;
} msr;
-/*Available cpuspeeds :
- 0 = 16 MHz
- 1 = 20 MHz
- 2 = 25 MHz
- 3 = 33 MHz
- 4 = 40 MHz
- 5 = 50 MHz
- 6 = 66 MHz
- 7 = 75 MHz
- 8 = 80 MHz
- 9 = 90 MHz
- 10 = 100 MHz
- 11 = 120 MHz
- 12 = 133 MHz
- 13 = 150 MHz
- 14 = 160 MHz
- 15 = 166 MHz
- 16 = 180 MHz
- 17 = 200 MHz
-*/
-
-CPU cpus_8088[] =
-{
- /*8088 standard*/
- {"8088/4.77", CPU_8088, 0, 4772728, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
- {"8088/7.16", CPU_8088, 1, 14318184/2, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
- {"8088/8", CPU_8088, 1, 8000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
- {"8088/10", CPU_8088, 2, 10000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
- {"8088/12", CPU_8088, 3, 12000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
- {"8088/16", CPU_8088, 4, 16000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
- {"", -1, 0, 0, 0, 0}
-};
-
-CPU cpus_pcjr[] =
-{
- /*8088 PCjr*/
- {"8088/4.77", CPU_8088, 0, 4772728, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
- {"", -1, 0, 0, 0, 0}
-};
-
-CPU cpus_europc[] =
-{
- /*8088 EuroPC*/
- {"8088/4.77", CPU_8088, 0, 4772728, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
- {"8088/7.16", CPU_8088, 1, 14318184/2, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
- {"8088/9.54", CPU_8088, 1, 4772728*2, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
- {"", -1, 0, 0, 0, 0}
-};
-
-CPU cpus_8086[] =
-{
- /*8086 standard*/
- {"8086/7.16", CPU_8086, 1, 14318184/2, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
- {"8086/8", CPU_8086, 1, 8000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
- {"8086/9.54", CPU_8086, 1, 4772728*2, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
- {"8086/10", CPU_8086, 2, 10000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
- {"8086/12", CPU_8086, 3, 12000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
- {"8086/16", CPU_8086, 4, 16000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 2},
- {"", -1, 0, 0, 0, 0}
-};
-
-CPU cpus_pc1512[] =
-{
- /*8086 Amstrad*/
- {"8086/8", CPU_8086, 1, 8000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
- {"", -1, 0, 0, 0, 0}
-};
-
-CPU cpus_286[] =
-{
- /*286*/
- {"286/6", CPU_286, 0, 6000000, 1, 0, 0, 0, 0, 0, 2,2,2,2, 1},
- {"286/8", CPU_286, 1, 8000000, 1, 0, 0, 0, 0, 0, 2,2,2,2, 1},
- {"286/10", CPU_286, 2, 10000000, 1, 0, 0, 0, 0, 0, 2,2,2,2, 1},
- {"286/12", CPU_286, 3, 12000000, 1, 0, 0, 0, 0, 0, 3,3,3,3, 2},
- {"286/16", CPU_286, 4, 16000000, 1, 0, 0, 0, 0, 0, 3,3,3,3, 2},
- {"286/20", CPU_286, 5, 20000000, 1, 0, 0, 0, 0, 0, 4,4,4,4, 3},
- {"286/25", CPU_286, 6, 25000000, 1, 0, 0, 0, 0, 0, 4,4,4,4, 3},
- {"", -1, 0, 0, 0, 0}
-};
-
-CPU cpus_ibmat[] =
-{
- /*286*/
- {"286/6", CPU_286, 0, 6000000, 1, 0, 0, 0, 0, 0, 3,3,3,3, 1},
- {"286/8", CPU_286, 0, 8000000, 1, 0, 0, 0, 0, 0, 3,3,3,3, 1},
- {"", -1, 0, 0, 0, 0}
-};
-
-CPU cpus_ibmxt286[] =
-{
- /*286*/
- {"286/6", CPU_286, 0, 6000000, 1, 0, 0, 0, 0, 0, 2,2,2,2, 1},
- {"", -1, 0, 0, 0, 0}
-};
-
-CPU cpus_ps1_m2011[] =
-{
- /*286*/
- {"286/10", CPU_286, 2, 10000000, 1, 0, 0, 0, 0, 0, 2,2,2,2, 1},
- {"", -1, 0, 0, 0, 0}
-};
-
-CPU cpus_ps2_m30_286[] =
-{
- /*286*/
- {"286/10", CPU_286, 2, 10000000, 1, 0, 0, 0, 0, 0, 2,2,2,2, 1},
- {"286/12", CPU_286, 3, 12000000, 1, 0, 0, 0, 0, 0, 3,3,3,3, 2},
- {"286/16", CPU_286, 4, 16000000, 1, 0, 0, 0, 0, 0, 3,3,3,3, 2},
- {"286/20", CPU_286, 5, 20000000, 1, 0, 0, 0, 0, 0, 4,4,4,4, 3},
- {"286/25", CPU_286, 6, 25000000, 1, 0, 0, 0, 0, 0, 4,4,4,4, 3},
- {"", -1, 0, 0, 0, 0}
-};
-
-CPU cpus_i386SX[] =
-{
- /*i386SX*/
- {"i386SX/16", CPU_386SX, 0, 16000000, 1, 0, 0x2308, 0, 0, 0, 3,3,3,3, 2},
- {"i386SX/20", CPU_386SX, 1, 20000000, 1, 0, 0x2308, 0, 0, 0, 4,4,3,3, 3},
- {"i386SX/25", CPU_386SX, 2, 25000000, 1, 0, 0x2308, 0, 0, 0, 4,4,3,3, 3},
- {"i386SX/33", CPU_386SX, 3, 33333333, 1, 0, 0x2308, 0, 0, 0, 6,6,3,3, 4},
- {"", -1, 0, 0, 0}
-};
-
-CPU cpus_i386DX[] =
-{
- /*i386DX*/
- {"i386DX/16", CPU_386DX, 0, 16000000, 1, 0, 0x0308, 0, 0, 0, 3,3,3,3, 2},
- {"i386DX/20", CPU_386DX, 1, 20000000, 1, 0, 0x0308, 0, 0, 0, 4,4,3,3, 3},
- {"i386DX/25", CPU_386DX, 2, 25000000, 1, 0, 0x0308, 0, 0, 0, 4,4,3,3, 3},
- {"i386DX/33", CPU_386DX, 3, 33333333, 1, 0, 0x0308, 0, 0, 0, 6,6,3,3, 4},
- {"", -1, 0, 0, 0}
-};
-
-CPU cpus_acer[] =
-{
- /*i386SX*/
- {"i386SX/25", CPU_386SX, 2, 25000000, 1, 0, 0x2308, 0, 0, 0, 4,4,4,4, 3},
- {"", -1, 0, 0, 0}
-};
-
-CPU cpus_Am386SX[] =
-{
- /*Am386*/
- {"Am386SX/16", CPU_386SX, 0, 16000000, 1, 0, 0x2308, 0, 0, 0, 3,3,3,3, 2},
- {"Am386SX/20", CPU_386SX, 1, 20000000, 1, 0, 0x2308, 0, 0, 0, 4,4,3,3, 3},
- {"Am386SX/25", CPU_386SX, 2, 25000000, 1, 0, 0x2308, 0, 0, 0, 4,4,3,3, 3},
- {"Am386SX/33", CPU_386SX, 3, 33333333, 1, 0, 0x2308, 0, 0, 0, 6,6,3,3, 4},
- {"Am386SX/40", CPU_386SX, 4, 40000000, 1, 0, 0x2308, 0, 0, 0, 7,7,3,3, 5},
- {"", -1, 0, 0, 0}
-};
-
-CPU cpus_Am386DX[] =
-{
- /*Am386*/
- {"Am386DX/25", CPU_386DX, 2, 25000000, 1, 0, 0x0308, 0, 0, 0, 4,4,3,3, 3},
- {"Am386DX/33", CPU_386DX, 3, 33333333, 1, 0, 0x0308, 0, 0, 0, 6,6,3,3, 4},
- {"Am386DX/40", CPU_386DX, 4, 40000000, 1, 0, 0x0308, 0, 0, 0, 7,7,3,3, 5},
- {"", -1, 0, 0, 0}
-};
-
-CPU cpus_486SLC[] =
-{
- /*Cx486SLC*/
- {"Cx486SLC/20", CPU_486SLC, 1, 20000000, 1, 0, 0x400, 0, 0x0000, 0, 4,4,3,3, 3},
- {"Cx486SLC/25", CPU_486SLC, 2, 25000000, 1, 0, 0x400, 0, 0x0000, 0, 4,4,3,3, 3},
- {"Cx486SLC/33", CPU_486SLC, 3, 33333333, 1, 0, 0x400, 0, 0x0000, 0, 6,6,3,3, 4},
- {"Cx486SRx2/32", CPU_486SLC, 3, 32000000, 2, 0, 0x406, 0, 0x0006, 0, 6,6,6,6, 2*2},
- {"Cx486SRx2/40", CPU_486SLC, 4, 40000000, 2, 0, 0x406, 0, 0x0006, 0, 8,8,6,6, 2*3},
- {"Cx486SRx2/50", CPU_486SLC, 5, 50000000, 2, 0, 0x406, 0, 0x0006, 0, 8,8,6,6, 2*3},
- {"", -1, 0, 0, 0}
-};
-
-CPU cpus_486DLC[] =
-{
- /*Cx486DLC*/
- {"Cx486DLC/25", CPU_486DLC, 2, 25000000, 1, 0, 0x401, 0, 0x0001, 0, 4,4,3,3, 3},
- {"Cx486DLC/33", CPU_486DLC, 3, 33333333, 1, 0, 0x401, 0, 0x0001, 0, 6,6,3,3, 4},
- {"Cx486DLC/40", CPU_486DLC, 4, 40000000, 1, 0, 0x401, 0, 0x0001, 0, 7,7,3,3, 5},
- {"Cx486DRx2/32", CPU_486DLC, 3, 32000000, 2, 0, 0x407, 0, 0x0007, 0, 6,6,6,6, 2*2},
- {"Cx486DRx2/40", CPU_486DLC, 4, 40000000, 2, 0, 0x407, 0, 0x0007, 0, 8,8,6,6, 2*3},
- {"Cx486DRx2/50", CPU_486DLC, 5, 50000000, 2, 0, 0x407, 0, 0x0007, 0, 8,8,6,6, 2*3},
- {"Cx486DRx2/66", CPU_486DLC, 6, 66666666, 2, 0, 0x407, 0, 0x0007, 0, 12,12,6,6, 2*4},
- {"", -1, 0, 0, 0}
-};
-
-CPU cpus_i486[] =
+void cpu_set_edx()
{
- /*i486*/
- {"i486SX/16", CPU_i486SX, 0, 16000000, 1, 16000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 3,3,3,3, 2},
- {"i486SX/20", CPU_i486SX, 1, 20000000, 1, 20000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 4,4,3,3, 3},
- {"i486SX/25", CPU_i486SX, 2, 25000000, 1, 25000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 4,4,3,3, 3},
- {"i486SX/33", CPU_i486SX, 3, 33333333, 1, 33333333, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 6,6,3,3, 4},
- {"i486SX2/50", CPU_i486SX, 5, 50000000, 2, 25000000, 0x45b, 0, 0, CPU_SUPPORTS_DYNAREC, 8,8,6,6, 2*3},
- {"i486DX/25", CPU_i486DX, 2, 25000000, 1, 25000000, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC, 4,4,3,3, 3},
- {"i486DX/33", CPU_i486DX, 3, 33333333, 1, 33333333, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC, 6,6,3,3, 4},
- {"i486DX/50", CPU_i486DX, 5, 50000000, 1, 25000000, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC, 8,8,4,4, 6},
- {"i486DX2/40", CPU_i486DX, 4, 40000000, 2, 20000000, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 8,8,6,6, 2*3},
- {"i486DX2/50", CPU_i486DX, 5, 50000000, 2, 25000000, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 8,8,6,6, 2*3},
- {"i486DX2/66", CPU_i486DX, 6, 66666666, 2, 33333333, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 2*4},
- {"iDX4/75", CPU_iDX4, 7, 75000000, 3, 25000000, 0x481, 0x481, 0, CPU_SUPPORTS_DYNAREC, 12,12,9,9, 3*3}, /*CPUID available on DX4, >= 75 MHz*/
- {"iDX4/100", CPU_iDX4, 10, 100000000, 3, 33333333, 0x481, 0x481, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*4}, /*Is on some real Intel DX2s, limit here is pretty arbitary*/
- {"Pentium OverDrive/63", CPU_PENTIUM, 6, 62500000, 3, 25000000, 0x1531, 0x1531, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,7,7, (5*3)/2},
- {"Pentium OverDrive/83", CPU_PENTIUM, 8, 83333333, 3, 33333333, 0x1532, 0x1532, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,8,8, (5*4)/2},
- {"", -1, 0, 0, 0}
-};
+ EDX = models[model].cpu[cpu_manufacturer].cpus[cpu].edx_reset;
+}
-CPU cpus_Am486[] =
+int fpu_get_type(int model, int manu, int cpu, const char *internal_name)
{
- /*Am486/5x86*/
- {"Am486SX/33", CPU_Am486SX, 3, 33333333, 1, 33333333, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 6,6,3,3, 4},
- {"Am486SX/40", CPU_Am486SX, 4, 40000000, 1, 20000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 7,7,3,3, 5},
- {"Am486SX2/50", CPU_Am486SX, 5, 50000000, 2, 25000000, 0x45b, 0x45b, 0, CPU_SUPPORTS_DYNAREC, 8,8,6,6, 2*3}, /*CPUID available on SX2, DX2, DX4, 5x86, >= 50 MHz*/
- {"Am486SX2/66", CPU_Am486SX, 6, 66666666, 2, 33333333, 0x45b, 0x45b, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 2*4}, /*Isn't on all real AMD SX2s and DX2s, availability here is pretty arbitary (and distinguishes them from the Intel chips)*/
- {"Am486DX/33", CPU_Am486DX, 3, 33333333, 1, 33333333, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 6,6,3,3, 4},
- {"Am486DX/40", CPU_Am486DX, 4, 40000000, 1, 20000000, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 7,7,3,3, 5},
- {"Am486DX2/50", CPU_Am486DX, 5, 50000000, 2, 25000000, 0x470, 0x470, 0, CPU_SUPPORTS_DYNAREC, 8,8,6,6, 2*3},
- {"Am486DX2/66", CPU_Am486DX, 6, 66666666, 2, 33333333, 0x470, 0x470, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 2*4},
- {"Am486DX2/80", CPU_Am486DX, 8, 80000000, 2, 20000000, 0x470, 0x470, 0, CPU_SUPPORTS_DYNAREC, 14,14,6,6, 2*5},
- {"Am486DX4/75", CPU_Am486DX, 7, 75000000, 3, 25000000, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 12,12,9,9, 3*3},
- {"Am486DX4/90", CPU_Am486DX, 9, 90000000, 3, 30000000, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 15,15,9,9, 3*4},
- {"Am486DX4/100", CPU_Am486DX, 10, 100000000, 3, 33333333, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 15,15,9,9, 3*4},
- {"Am486DX4/120", CPU_Am486DX, 11, 120000000, 3, 20000000, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 21,21,9,9, 3*5},
- {"Am5x86/P75", CPU_Am486DX, 12, 133333333, 4, 33333333, 0x4e0, 0x4e0, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 4*4},
- {"Am5x86/P75+", CPU_Am486DX, 13, 160000000, 4, 20000000, 0x4e0, 0x4e0, 0, CPU_SUPPORTS_DYNAREC, 28,28,12,12, 4*5},
- {"", -1, 0, 0, 0}
-};
+ CPU *cpu_s = &models[model].cpu[manu].cpus[cpu];
+ const FPU *fpus = cpu_s->fpus;
+ int fpu_type = fpus[0].type;
+ int c = 0;
+
+ while (fpus[c].internal_name)
+ {
+ if (!strcmp(internal_name, fpus[c].internal_name))
+ fpu_type = fpus[c].type;
+ c++;
+ }
+
+ return fpu_type;
+}
-CPU cpus_Cx486[] =
+const char *fpu_get_internal_name(int model, int manu, int cpu, int type)
{
- /*Cx486/5x86*/
- {"Cx486S/25", CPU_Cx486S, 2, 25000000, 1, 25000000, 0x420, 0, 0x0010, CPU_SUPPORTS_DYNAREC, 4,4,3,3, 3},
- {"Cx486S/33", CPU_Cx486S, 3, 33333333, 1, 33333333, 0x420, 0, 0x0010, CPU_SUPPORTS_DYNAREC, 6,6,3,3, 4},
- {"Cx486S/40", CPU_Cx486S, 4, 40000000, 1, 20000000, 0x420, 0, 0x0010, CPU_SUPPORTS_DYNAREC, 7,7,3,3, 5},
- {"Cx486DX/33", CPU_Cx486DX, 3, 33333333, 1, 33333333, 0x430, 0, 0x051a, CPU_SUPPORTS_DYNAREC, 6,6,3,3, 4},
- {"Cx486DX/40", CPU_Cx486DX, 4, 40000000, 1, 20000000, 0x430, 0, 0x051a, CPU_SUPPORTS_DYNAREC, 7,7,3,3, 5},
- {"Cx486DX2/50", CPU_Cx486DX, 5, 50000000, 2, 25000000, 0x430, 0, 0x081b, CPU_SUPPORTS_DYNAREC, 8,8,6,6, 2*3},
- {"Cx486DX2/66", CPU_Cx486DX, 6, 66666666, 2, 33333333, 0x430, 0, 0x0b1b, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 2*4},
- {"Cx486DX2/80", CPU_Cx486DX, 8, 80000000, 2, 20000000, 0x430, 0, 0x311b, CPU_SUPPORTS_DYNAREC, 14,14,16,16, 2*5},
- {"Cx486DX4/75", CPU_Cx486DX, 7, 75000000, 3, 25000000, 0x480, 0, 0x361f, CPU_SUPPORTS_DYNAREC, 12,12,9,9, 3*3},
- {"Cx486DX4/100", CPU_Cx486DX, 10, 100000000, 3, 33333333, 0x480, 0, 0x361f, CPU_SUPPORTS_DYNAREC, 15,15,9,9, 3*4},
- {"Cx5x86/100", CPU_Cx5x86, 10, 100000000, 3, 33333333, 0x480, 0, 0x002f, CPU_SUPPORTS_DYNAREC, 15,15,9,9, 3*4},
- {"Cx5x86/120", CPU_Cx5x86, 11, 120000000, 3, 20000000, 0x480, 0, 0x002f, CPU_SUPPORTS_DYNAREC, 21,21,9,9, 3*5},
- {"Cx5x86/133", CPU_Cx5x86, 12, 133333333, 4, 33333333, 0x480, 0, 0x002f, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 4*4},
- {"", -1, 0, 0, 0}
-};
+ CPU *cpu_s = &models[model].cpu[manu].cpus[cpu];
+ const FPU *fpus = cpu_s->fpus;
+ int c = 0;
-#if 0
- CPU cpus_6x86[] =
- {
- /*Cyrix 6x86*/
- {"6x86-P90", CPU_Cx6x86, 17, 80000000, 3, 40000000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 8,8,6,6, 2*5},
- {"6x86-PR120+", CPU_Cx6x86, 17, 100000000, 3, 25000000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,6,6, 2*6},
- {"6x86-PR133+", CPU_Cx6x86, 17, 110000000, 3, 27500000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,6,6, 2*7},
- {"6x86-PR150+", CPU_Cx6x86, 17, 120000000, 3, 30000000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*7},
- {"6x86-PR166+", CPU_Cx6x86, 17, 133333333, 3, 33333333, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*8},
- {"6x86-PR200+", CPU_Cx6x86, 17, 150000000, 3, 37500000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*9},
-
- /*Cyrix 6x86L*/
- {"6x86L-PR133+", CPU_Cx6x86L, 19, 110000000, 3, 27500000, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,6,6, 2*7},
- {"6x86L-PR150+", CPU_Cx6x86L, 19, 120000000, 3, 30000000, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*7},
- {"6x86L-PR166+", CPU_Cx6x86L, 19, 133333333, 3, 33333333, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*8},
- {"6x86L-PR200+", CPU_Cx6x86L, 19, 150000000, 3, 37500000, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*9},
-
- /*Cyrix 6x86MX*/
- {"6x86MX-PR166", CPU_Cx6x86MX, 18, 133333333, 3, 33333333, 0x600, 0x600, 0x0451, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*8},
- {"6x86MX-PR200", CPU_Cx6x86MX, 18, 166666666, 3, 33333333, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*8)/2},
- {"6x86MX-PR233", CPU_Cx6x86MX, 18, 188888888, 3, 37500000, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*9)/2},
- {"6x86MX-PR266", CPU_Cx6x86MX, 18, 207500000, 3, 41666667, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 17,17,7,7, (5*10)/2},
- {"6x86MX-PR300", CPU_Cx6x86MX, 18, 233333333, 3, 33333333, 0x600, 0x600, 0x0454, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,7,7, (7*8)/2},
- {"6x86MX-PR333", CPU_Cx6x86MX, 18, 250000000, 3, 41666667, 0x600, 0x600, 0x0453, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 20,20,9,9, 3*10},
- {"6x86MX-PR366", CPU_Cx6x86MX, 18, 250000000, 3, 33333333, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 3*10},
- {"6x86MX-PR400", CPU_Cx6x86MX, 18, 285000000, 3, 31666667, 0x600, 0x600, 0x0453, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 3*11},
- {"", -1, 0, 0, 0}
- };
-
-
-
-CPU cpus_WinChip[] =
-{
- /*IDT WinChip*/
- {"WinChip 75", CPU_WINCHIP, 7, 75000000, 2, 25000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 8,8,4,4, (3*6)/2},
- {"WinChip 90", CPU_WINCHIP, 9, 90000000, 2, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 9,9,4,4, (3*7)/2},
- {"WinChip 100", CPU_WINCHIP, 10, 100000000, 2, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 9,9,4,4, (3*8)/2},
- {"WinChip 120", CPU_WINCHIP, 11, 120000000, 2, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 2*7},
- {"WinChip 133", CPU_WINCHIP, 12, 133333333, 2, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 2*8},
- {"WinChip 150", CPU_WINCHIP, 13, 150000000, 3, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 15,15,7,7, (5*7)/2},
- {"WinChip 166", CPU_WINCHIP, 15, 166666666, 3, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 15,15,7,7, (5*8)/2},
- {"WinChip 180", CPU_WINCHIP, 16, 180000000, 3, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*7},
- {"WinChip 200", CPU_WINCHIP, 17, 200000000, 3, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*8},
- {"WinChip 225", CPU_WINCHIP, 17, 225000000, 3, 37500000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 3*9},
- {"WinChip 240", CPU_WINCHIP, 17, 240000000, 6, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 4*7},
- {"", -1, 0, 0, 0}
-};
+ while (fpus[c].internal_name)
+ {
+ if (fpus[c].type == type)
+ return fpus[c].internal_name;
+ c++;
+ }
-CPU cpus_Pentium5V[] =
-{
- /*Intel Pentium (5V, socket 4)*/
- {"Pentium 60", CPU_PENTIUM, 6, 60000000, 1, 30000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6,6,3,3, 7},
- {"Pentium 66", CPU_PENTIUM, 6, 66666666, 1, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6,6,3,3, 8},
- {"Pentium OverDrive 120",CPU_PENTIUM, 14, 120000000, 2, 30000000, 0x51A, 0x51A, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*7},
- {"Pentium OverDrive 133",CPU_PENTIUM, 16, 133333333, 2, 33333333, 0x51A, 0x51A, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*8},
- {"", -1, 0, 0, 0}
-};
+ return fpus[0].internal_name;
+}
-CPU cpus_PentiumS5[] =
+const char *fpu_get_name_from_index(int model, int manu, int cpu, int c)
{
- /*Intel Pentium (Socket 5)*/
- {"Pentium 75", CPU_PENTIUM, 9, 75000000, 2, 25000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7,7,4,4, (3*6)/2},
- {"Pentium 90", CPU_PENTIUM, 12, 90000000, 2, 30000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9,9,4,4, (3*7)/2},
- {"Pentium 100/50", CPU_PENTIUM, 13, 100000000, 2, 25000000, 0x525, 0x525, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,6,6, 2*6},
- {"Pentium 100/66", CPU_PENTIUM, 13, 100000000, 2, 33333333, 0x525, 0x525, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9,9,4,4, (3*8)/2},
- {"Pentium 120", CPU_PENTIUM, 14, 120000000, 2, 30000000, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*7},
- {"Pentium 133", CPU_PENTIUM, 16, 133333333, 2, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*8},
- {"Pentium OverDrive 125",CPU_PENTIUM,15, 125000000, 3, 25000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,7,7, (5*6)/2},
- {"Pentium OverDrive 150",CPU_PENTIUM,17, 150000000, 3, 30000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*7)/2},
- {"Pentium OverDrive 166",CPU_PENTIUM,17, 166666666, 3, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*8)/2},
- {"Pentium OverDrive MMX 125", CPU_PENTIUMMMX,15,125000000, 3, 25000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,7,7, (5*6)/2},
- {"Pentium OverDrive MMX 150/60", CPU_PENTIUMMMX,17,150000000, 3, 30000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*7)/2},
- {"Pentium OverDrive MMX 166", CPU_PENTIUMMMX,19,166000000, 3, 33333333, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*8)/2},
- {"Pentium OverDrive MMX 180", CPU_PENTIUMMMX,20,180000000, 3, 30000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 3*7},
- {"Pentium OverDrive MMX 200", CPU_PENTIUMMMX,21,200000000, 3, 33333333, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 3*8},
- {"", -1, 0, 0, 0}
-};
+ CPU *cpu_s = &models[model].cpu[manu].cpus[cpu];
+ const FPU *fpus = cpu_s->fpus;
+
+ return fpus[c].name;
+}
-CPU cpus_Pentium[] =
+int fpu_get_type_from_index(int model, int manu, int cpu, int c)
{
- /*Intel Pentium*/
- {"Pentium 75", CPU_PENTIUM, 9, 75000000, 2, 25000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7,7,4,4, (3*6)/2},
- {"Pentium 90", CPU_PENTIUM, 12, 90000000, 2, 30000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9,9,4,4, (3*7)/2},
- {"Pentium 100/50", CPU_PENTIUM, 13, 100000000, 2, 25000000, 0x525, 0x525, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,6,6, 2*6},
- {"Pentium 100/66", CPU_PENTIUM, 13, 100000000, 2, 33333333, 0x525, 0x525, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9,9,4,4, (3*8)/2},
- {"Pentium 120", CPU_PENTIUM, 14, 120000000, 2, 30000000, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*7},
- {"Pentium 133", CPU_PENTIUM, 16, 133333333, 2, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*8},
- {"Pentium 150", CPU_PENTIUM, 17, 150000000, 3, 30000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*7)/2},
- {"Pentium 166", CPU_PENTIUM, 19, 166666666, 3, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*8)/2},
- {"Pentium 200", CPU_PENTIUM, 21, 200000000, 3, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 3*8},
- {"Pentium MMX 166", CPU_PENTIUMMMX, 19, 166666666, 3, 33333333, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*8)/2},
- {"Pentium MMX 200", CPU_PENTIUMMMX, 21, 200000000, 3, 33333333, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 3*8},
- {"Pentium MMX 233", CPU_PENTIUMMMX, 24, 233333333, 4, 33333333, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, (7*8)/2},
- {"Mobile Pentium MMX 120", CPU_PENTIUMMMX, 14, 120000000, 2, 30000000, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*7},
- {"Mobile Pentium MMX 133", CPU_PENTIUMMMX, 16, 133333333, 2, 33333333, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 2*8},
- {"Mobile Pentium MMX 150", CPU_PENTIUMMMX, 17, 150000000, 3, 30000000, 0x544, 0x544, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*7)/2},
- {"Mobile Pentium MMX 166", CPU_PENTIUMMMX, 19, 166666666, 3, 33333333, 0x544, 0x544, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*8)/2},
- {"Mobile Pentium MMX 200", CPU_PENTIUMMMX, 21, 200000000, 3, 33333333, 0x581, 0x581, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 3*8},
- {"Mobile Pentium MMX 233", CPU_PENTIUMMMX, 24, 233333333, 4, 33333333, 0x581, 0x581, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, (7*8)/2},
- {"Mobile Pentium MMX 266", CPU_PENTIUMMMX, 26, 266666666, 4, 33333333, 0x582, 0x582, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 4*8},
- {"Mobile Pentium MMX 300", CPU_PENTIUMMMX, 28, 300000000, 5, 33333333, 0x582, 0x582, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, (9*8)/2},
- {"Pentium OverDrive 125",CPU_PENTIUM,15, 125000000, 3, 25000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,7,7, (5*6)/2},
- {"Pentium OverDrive 150",CPU_PENTIUM,17, 150000000, 3, 30000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*7)/2},
- {"Pentium OverDrive 166",CPU_PENTIUM,17, 166666666, 3, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*8)/2},
- {"Pentium OverDrive MMX 125", CPU_PENTIUMMMX,15,125000000, 3, 25000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,7,7, (5*6)/2},
- {"Pentium OverDrive MMX 150/60", CPU_PENTIUMMMX,17,150000000, 3, 30000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*7)/2},
- {"Pentium OverDrive MMX 166", CPU_PENTIUMMMX,19,166000000, 3, 33333333, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, (5*8)/2},
- {"Pentium OverDrive MMX 180", CPU_PENTIUMMMX,20,180000000, 3, 30000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 3*7},
- {"Pentium OverDrive MMX 200", CPU_PENTIUMMMX,21,200000000, 3, 33333333, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 3*8},
- {"", -1, 0, 0, 0}
-};
-#endif
+ CPU *cpu_s = &models[model].cpu[manu].cpus[cpu];
+ const FPU *fpus = cpu_s->fpus;
-void cpu_set_edx()
-{
- EDX = models[model].cpu[cpu_manufacturer].cpus[cpu].edx_reset;
+ return fpus[c].type;
}
-void cpu_set(int speedmultiplier)
+void cpu_set()
{
CPU *cpu_s;
-
+
if (!models[model].cpu[cpu_manufacturer].cpus)
{
/*CPU is invalid, set to default*/
cpu_s = &models[model].cpu[cpu_manufacturer].cpus[cpu];
- int rspeed = cpu_s->rspeed;
- cpu_multi = cpu_s->multi;
- if (speedmultiplier > 0) {
- rspeed = rspeed + (int32_t)(rspeed * (int64_t)speedmultiplier / 1000);
- cpu_multi += speedmultiplier / 1000;
- }
-
CPUID = cpu_s->cpuid_model;
cpuspeed = cpu_s->speed;
is8086 = (cpu_s->cpu_type > CPU_8088);
is386 = (cpu_s->cpu_type >= CPU_386SX);
is486 = (cpu_s->cpu_type >= CPU_i486SX) || (cpu_s->cpu_type == CPU_486SLC || cpu_s->cpu_type == CPU_486DLC);
- hasfpu = (cpu_s->cpu_type >= CPU_i486DX);
+ hasfpu = (fpu_type != FPU_NONE);
+
cpu_iscyrix = (cpu_s->cpu_type == CPU_486SLC || cpu_s->cpu_type == CPU_486DLC || cpu_s->cpu_type == CPU_Cx486S || cpu_s->cpu_type == CPU_Cx486DX || cpu_s->cpu_type == CPU_Cx5x86 || cpu_s->cpu_type == CPU_Cx6x86 || cpu_s->cpu_type == CPU_Cx6x86MX || cpu_s->cpu_type == CPU_Cx6x86L || cpu_s->cpu_type == CPU_CxGX1);
cpu_16bitbus = (cpu_s->cpu_type == CPU_286 || cpu_s->cpu_type == CPU_386SX || cpu_s->cpu_type == CPU_486SLC);
- if (cpu_multi)
- cpu_busspeed = rspeed / cpu_multi;
- cpu_hasrdtsc = 0;
- cpu_hasMMX = 0;
- cpu_hasMSR = 0;
- cpu_hasCR4 = 0;
- cpu_hasCX8 = 0;
+ if (cpu_s->multi)
+ cpu_busspeed = cpu_s->rspeed / cpu_s->multi;
+ cpu_multi = cpu_s->multi;
ccr0 = ccr1 = ccr2 = ccr3 = ccr4 = ccr5 = ccr6 = 0;
has_vlb = (cpu_s->cpu_type >= CPU_i486SX) && (cpu_s->cpu_type <= CPU_Cx5x86);
- cpu_turbo_speed = rspeed;
+ cpu_turbo_speed = cpu_s->rspeed;
if (cpu_s->cpu_type < CPU_286)
cpu_nonturbo_speed = 4772728;
- else if (rspeed < 8000000)
- cpu_nonturbo_speed = rspeed;
+ else if (cpu_s->rspeed < 8000000)
+ cpu_nonturbo_speed = cpu_s->rspeed;
else
cpu_nonturbo_speed = 8000000;
isa_cycles = cpu_s->atclk_div;
- if (rspeed <= 8000000)
+ if (cpu_s->rspeed <= 8000000)
cpu_rom_prefetch_cycles = cpu_mem_prefetch_cycles;
else
- cpu_rom_prefetch_cycles = rspeed / 1000000;
+ cpu_rom_prefetch_cycles = cpu_s->rspeed / 1000000;
-#if 0
if (cpu_s->pci_speed)
{
pci_nonburst_time = 4*cpu_s->rspeed / cpu_s->pci_speed;
pci_burst_time = 1;
}
pclog("PCI burst=%i nonburst=%i\n", pci_burst_time, pci_nonburst_time);
-#endif
if (cpu_iscyrix)
io_sethandler(0x0022, 0x0002, cyrix_read, NULL, NULL, cyrix_write, NULL, NULL, NULL);
pclog("hasfpu - %i\n",hasfpu);
pclog("is486 - %i %i\n",is486,cpu_s->cpu_type);
- x86_setopcodes(ops_386, ops_386_0f, NULL, NULL);// dynarec_ops_386, dynarec_ops_386_0f);
+ x86_setopcodes(ops_386, ops_386_0f, dynarec_ops_386, dynarec_ops_386_0f);
x86_opcodes_REPE = ops_REPE;
x86_opcodes_REPNE = ops_REPNE;
-
-#if 0
- x86_dynarec_opcodes_REPE = dynarec_ops_REPE;
+ x86_opcodes_3DNOW = ops_3DNOW;
+ x86_dynarec_opcodes_REPE = dynarec_ops_REPE;
x86_dynarec_opcodes_REPNE = dynarec_ops_REPNE;
+ x86_dynarec_opcodes_3DNOW = dynarec_ops_3DNOW;
- if (hasfpu)
+ if (hasfpu)
{
x86_dynarec_opcodes_d8_a16 = dynarec_ops_fpu_d8_a16;
x86_dynarec_opcodes_d8_a32 = dynarec_ops_fpu_d8_a32;
x86_dynarec_opcodes_df_a32 = dynarec_ops_nofpu_a32;
}
codegen_timing_set(&codegen_timing_486);
-#endif
+
if (hasfpu)
{
x86_opcodes_d8_a16 = ops_fpu_d8_a16;
case CPU_8088:
case CPU_8086:
break;
-
- case CPU_286:
- x86_setopcodes(ops_286, ops_286_0f, NULL, NULL); // dynarec_ops_286, dynarec_ops_286_0f);
+
+ case CPU_286:
+ x86_setopcodes(ops_286, ops_286_0f, dynarec_ops_286, dynarec_ops_286_0f);
timing_rr = 2; /*register dest - register src*/
timing_rm = 7; /*register dest - memory src*/
timing_mr = 7; /*memory dest - register src*/
timing_jmp_pm_gate = 45;
break;
- case CPU_486SLC:
+ case CPU_486SLC:
timing_rr = 1; /*register dest - register src*/
timing_rm = 3; /*register dest - memory src*/
timing_mr = 5; /*memory dest - register src*/
break;
case CPU_iDX4:
- cpu_hasCR4 = 1;
- cpu_hasVME = 1;
+ cpu_features = CPU_FEATURE_CR4 | CPU_FEATURE_VME;
cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_VME;
case CPU_i486SX:
case CPU_i486DX:
timing_jmp_pm_gate = 37;
timing_misaligned = 3;
break;
-#if 0
+
case CPU_Cx5x86:
timing_rr = 1; /*register dest - register src*/
timing_rm = 1; /*register dest - memory src*/
timing_mml = 3;
timing_bt = 3-1; /*branch taken*/
timing_bnt = 1; /*branch not taken*/
- cpu_hasrdtsc = 1;
- msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21);
- cpu_hasMMX = cpu_hasMSR = 1;
- cpu_hasCR4 = 1;
+ cpu_features = CPU_FEATURE_RDTSC | CPU_FEATURE_MMX | CPU_FEATURE_MSR | CPU_FEATURE_CR4;
+ msr.fcr = (1 << 8) | (1 << 16);
cpu_CR4_mask = CR4_TSD | CR4_DE | CR4_MCE | CR4_PCE;
/*unknown*/
timing_int_rm = 26;
codegen_timing_set(&codegen_timing_winchip);
break;
+ case CPU_WINCHIP2:
+ x86_setopcodes(ops_386, ops_winchip2_0f, dynarec_ops_386, dynarec_ops_winchip2_0f);
+ timing_rr = 1; /*register dest - register src*/
+ timing_rm = 2; /*register dest - memory src*/
+ timing_mr = 2; /*memory dest - register src*/
+ timing_mm = 3;
+ timing_rml = 2; /*register dest - memory src long*/
+ timing_mrl = 2; /*memory dest - register src long*/
+ timing_mml = 3;
+ timing_bt = 3-1; /*branch taken*/
+ timing_bnt = 1; /*branch not taken*/
+ cpu_features = CPU_FEATURE_RDTSC | CPU_FEATURE_MMX | CPU_FEATURE_MSR | CPU_FEATURE_CR4 | CPU_FEATURE_3DNOW;
+ msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 18) | (1 << 19) | (1 << 20) | (1 << 21);
+ cpu_CR4_mask = CR4_TSD | CR4_DE | CR4_MCE | CR4_PCE;
+ /*unknown*/
+ timing_int_rm = 26;
+ timing_int_v86 = 82;
+ timing_int_pm = 44;
+ timing_int_pm_outer = 71;
+ timing_iret_rm = 7;
+ timing_iret_v86 = 26;
+ timing_iret_pm = 10;
+ timing_iret_pm_outer = 26;
+ timing_call_rm = 4;
+ timing_call_pm = 15;
+ timing_call_pm_gate = 26;
+ timing_call_pm_gate_inner = 35;
+ timing_retf_rm = 4;
+ timing_retf_pm = 7;
+ timing_retf_pm_outer = 23;
+ timing_jmp_rm = 5;
+ timing_jmp_pm = 7;
+ timing_jmp_pm_gate = 17;
+ timing_misaligned = 2;
+ cpu_cyrix_alignment = 1;
+ codegen_timing_set(&codegen_timing_winchip2);
+ break;
+
case CPU_PENTIUM:
x86_setopcodes(ops_386, ops_pentium_0f, dynarec_ops_386, dynarec_ops_pentium_0f);
timing_rr = 1; /*register dest - register src*/
timing_jmp_pm = 3;
timing_jmp_pm_gate = 18;
timing_misaligned = 3;
- cpu_hasrdtsc = 1;
+ cpu_features = CPU_FEATURE_RDTSC | CPU_FEATURE_MSR | CPU_FEATURE_CR4 | CPU_FEATURE_VME;
msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21);
- cpu_hasMMX = 0;
- cpu_hasMSR = 1;
- cpu_hasCR4 = 1;
- cpu_hasVME = 1;
cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_PSE | CR4_MCE | CR4_PCE;
codegen_timing_set(&codegen_timing_pentium);
break;
timing_jmp_pm = 3;
timing_jmp_pm_gate = 18;
timing_misaligned = 3;
- cpu_hasrdtsc = 1;
+ cpu_features = CPU_FEATURE_RDTSC | CPU_FEATURE_MSR | CPU_FEATURE_CR4 | CPU_FEATURE_VME | CPU_FEATURE_MMX;
msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21);
- cpu_hasMMX = 1;
- cpu_hasMSR = 1;
- cpu_hasCR4 = 1;
- cpu_hasVME = 1;
cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_PSE | CR4_MCE | CR4_PCE;
codegen_timing_set(&codegen_timing_pentium);
break;
timing_jmp_pm_gate = 14;
timing_misaligned = 2;
cpu_cyrix_alignment = 1;
- cpu_hasrdtsc = 1;
+ cpu_features = CPU_FEATURE_RDTSC;
msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21);
- cpu_hasMMX = 0;
- cpu_hasMSR = 0;
- cpu_hasCR4 = 0;
codegen_timing_set(&codegen_timing_686);
CPUID = 0; /*Disabled on powerup by default*/
break;
timing_jmp_pm_gate = 14;
timing_misaligned = 2;
cpu_cyrix_alignment = 1;
- cpu_hasrdtsc = 1;
+ cpu_features = CPU_FEATURE_RDTSC;
msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21);
- cpu_hasMMX = 0;
- cpu_hasMSR = 0;
- cpu_hasCR4 = 0;
codegen_timing_set(&codegen_timing_686);
ccr4 = 0x80;
break;
timing_mml = 2;
timing_bt = 5-1; /*branch taken*/
timing_bnt = 1; /*branch not taken*/
- cpu_hasrdtsc = 1;
+ cpu_features = CPU_FEATURE_RDTSC | CPU_FEATURE_MSR | CPU_FEATURE_CR4;
msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21);
- cpu_hasMMX = 0;
- cpu_hasMSR = 1;
- cpu_hasCR4 = 1;
cpu_CR4_mask = CR4_TSD | CR4_DE | CR4_PCE;
codegen_timing_set(&codegen_timing_686);
break;
timing_jmp_pm_gate = 14;
timing_misaligned = 2;
cpu_cyrix_alignment = 1;
- cpu_hasrdtsc = 1;
+ cpu_features = CPU_FEATURE_RDTSC | CPU_FEATURE_MSR | CPU_FEATURE_CR4 | CPU_FEATURE_MMX;
msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21);
- cpu_hasMMX = 1;
- cpu_hasMSR = 1;
- cpu_hasCR4 = 1;
cpu_CR4_mask = CR4_TSD | CR4_DE | CR4_PCE;
codegen_timing_set(&codegen_timing_686);
ccr4 = 0x80;
break;
-#endif
+
+ case CPU_K6:
+ x86_setopcodes(ops_386, ops_pentiummmx_0f, dynarec_ops_386, dynarec_ops_pentiummmx_0f);
+ timing_rr = 1; /*register dest - register src*/
+ timing_rm = 2; /*register dest - memory src*/
+ timing_mr = 3; /*memory dest - register src*/
+ timing_mm = 3;
+ timing_rml = 2; /*register dest - memory src long*/
+ timing_mrl = 3; /*memory dest - register src long*/
+ timing_mml = 3;
+ timing_bt = 0; /*branch taken*/
+ timing_bnt = 1; /*branch not taken*/
+ timing_int = 6;
+ timing_int_rm = 11;
+ timing_int_v86 = 54;
+ timing_int_pm = 25;
+ timing_int_pm_outer = 42;
+ timing_iret_rm = 7;
+ timing_iret_v86 = 27; /*unknown*/
+ timing_iret_pm = 10;
+ timing_iret_pm_outer = 27;
+ timing_call_rm = 4;
+ timing_call_pm = 4;
+ timing_call_pm_gate = 22;
+ timing_call_pm_gate_inner = 44;
+ timing_retf_rm = 4;
+ timing_retf_pm = 4;
+ timing_retf_pm_outer = 23;
+ timing_jmp_rm = 3;
+ timing_jmp_pm = 3;
+ timing_jmp_pm_gate = 18;
+ timing_misaligned = 3;
+ cpu_features = CPU_FEATURE_RDTSC | CPU_FEATURE_MSR | CPU_FEATURE_CR4 | CPU_FEATURE_VME | CPU_FEATURE_MMX;
+ msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21);
+ cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_PSE | CR4_MCE;
+ codegen_timing_set(&codegen_timing_k6);
+ break;
+
+ case CPU_K6_2:
+ case CPU_K6_3:
+ case CPU_K6_2P:
+ case CPU_K6_3P:
+ x86_setopcodes(ops_386, ops_winchip2_0f, dynarec_ops_386, dynarec_ops_winchip2_0f);
+ timing_rr = 1; /*register dest - register src*/
+ timing_rm = 2; /*register dest - memory src*/
+ timing_mr = 3; /*memory dest - register src*/
+ timing_mm = 3;
+ timing_rml = 2; /*register dest - memory src long*/
+ timing_mrl = 3; /*memory dest - register src long*/
+ timing_mml = 3;
+ timing_bt = 0; /*branch taken*/
+ timing_bnt = 1; /*branch not taken*/
+ timing_int = 6;
+ timing_int_rm = 11;
+ timing_int_v86 = 54;
+ timing_int_pm = 25;
+ timing_int_pm_outer = 42;
+ timing_iret_rm = 7;
+ timing_iret_v86 = 27; /*unknown*/
+ timing_iret_pm = 10;
+ timing_iret_pm_outer = 27;
+ timing_call_rm = 4;
+ timing_call_pm = 4;
+ timing_call_pm_gate = 22;
+ timing_call_pm_gate_inner = 44;
+ timing_retf_rm = 4;
+ timing_retf_pm = 4;
+ timing_retf_pm_outer = 23;
+ timing_jmp_rm = 3;
+ timing_jmp_pm = 3;
+ timing_jmp_pm_gate = 18;
+ timing_misaligned = 3;
+ cpu_features = CPU_FEATURE_RDTSC | CPU_FEATURE_MSR | CPU_FEATURE_CR4 | CPU_FEATURE_VME | CPU_FEATURE_MMX | CPU_FEATURE_3DNOW;
+ msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21);
+ cpu_CR4_mask = CR4_VME | CR4_PVI | CR4_TSD | CR4_DE | CR4_PSE | CR4_MCE;
+ codegen_timing_set(&codegen_timing_k6);
+ break;
+
default:
fatal("cpu_set : unknown CPU type %i\n", cpu_s->cpu_type);
}
+
+ switch (fpu_type)
+ {
+ case FPU_NONE:
+ break;
+
+ case FPU_8087:
+ x87_timings = x87_timings_8087;
+ break;
+
+ case FPU_287:
+ x87_timings = x87_timings_287;
+ break;
+
+ case FPU_287XL:
+ case FPU_387:
+ x87_timings = x87_timings_387;
+ break;
+
+ default:
+ x87_timings = x87_timings_486;
+ break;
+ }
}
void cpu_CPUID()
else
{
EBX = 0x746e6543; /*CentaurHauls*/
- ECX = 0x736c7561;
+ ECX = 0x736c7561;
EDX = 0x48727561;
}
}
EAX = 0x540;
EBX = ECX = 0;
EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR;
- if (cpu_hasCX8)
- EDX |= CPUID_CMPXCHG8B;
+ if (cpu_has_feature(CPU_FEATURE_CX8))
+ EDX |= CPUID_CMPXCHG8B;
if (msr.fcr & (1 << 9))
EDX |= CPUID_MMX;
}
else
EAX = EBX = ECX = EDX = 0;
break;
+
+ case CPU_WINCHIP2:
+ switch (EAX)
+ {
+ case 0:
+ EAX = 1;
+ if (msr.fcr2 & (1 << 14))
+ {
+ EBX = msr.fcr3 >> 32;
+ ECX = msr.fcr3 & 0xffffffff;
+ EDX = msr.fcr2 >> 32;
+ }
+ else
+ {
+ EBX = 0x746e6543; /*CentaurHauls*/
+ ECX = 0x736c7561;
+ EDX = 0x48727561;
+ }
+ break;
+ case 1:
+ EAX = 0x580;
+ EBX = ECX = 0;
+ EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR;
+ if (cpu_has_feature(CPU_FEATURE_CX8))
+ EDX |= CPUID_CMPXCHG8B;
+ if (msr.fcr & (1 << 9))
+ EDX |= CPUID_MMX;
+ break;
+ case 0x80000000:
+ EAX = 0x80000005;
+ break;
+ case 0x80000001:
+ EAX = 0x580;
+ EDX = CPUID_FPU | CPUID_TSC | CPUID_MSR;
+ if (cpu_has_feature(CPU_FEATURE_CX8))
+ EDX |= CPUID_CMPXCHG8B;
+ if (msr.fcr & (1 << 9))
+ EDX |= CPUID_MMX;
+ if (cpu_has_feature(CPU_FEATURE_3DNOW))
+ EDX |= CPUID_3DNOW;
+ break;
+
+ case 0x80000002: /*Processor name string*/
+ EAX = 0x20544449; /*IDT WinChip 2-3D*/
+ EBX = 0x436e6957;
+ ECX = 0x20706968;
+ EDX = 0x44332d32;
+ break;
+
+ case 0x80000005: /*Cache information*/
+ EBX = 0x08800880; /*TLBs*/
+ ECX = 0x20040120; /*L1 data cache*/
+ EDX = 0x20020120; /*L1 instruction cache*/
+ break;
+
+ default:
+ EAX = EBX = ECX = EDX = 0;
+ break;
+ }
+ break;
case CPU_PENTIUM:
if (!EAX)
EAX = EBX = ECX = EDX = 0;
break;
+ case CPU_K6:
+ switch (EAX)
+ {
+ case 0:
+ EAX = 1;
+ EBX = 0x68747541; /*AuthenticAMD*/
+ ECX = 0x444d4163;
+ EDX = 0x69746e65;
+ break;
+ case 1:
+ EAX = CPUID;
+ EBX = ECX = 0;
+ EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B | CPUID_MMX;
+ break;
+ case 0x80000000:
+ EAX = 0x80000005;
+ break;
+ case 0x80000001:
+ EAX = CPUID+0x100;
+ EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B | CPUID_MMX;
+ break;
+
+ case 0x80000002: /*Processor name string*/
+ EAX = 0x2d444d41; /*AMD-K6tm w/ mult*/
+ EBX = 0x6d74364b;
+ ECX = 0x202f7720;
+ EDX = 0x746c756d;
+ break;
+
+ case 0x80000003: /*Processor name string*/
+ EAX = 0x64656d69; /*imedia extension*/
+ EBX = 0x65206169;
+ ECX = 0x6e657478;
+ EDX = 0x6e6f6973;
+ break;
+
+ case 0x80000004: /*Processor name string*/
+ EAX = 0x00000073; /*s*/
+ EBX = 0x00000000;
+ ECX = 0x00000000;
+ EDX = 0x00000000;
+ break;
+
+ case 0x80000005: /*Cache information*/
+ EBX = 0x02800140; /*TLBs*/
+ ECX = 0x20020220; /*L1 data cache*/
+ EDX = 0x20020220; /*L1 instruction cache*/
+ break;
+
+ default:
+ EAX = EBX = ECX = EDX = 0;
+ break;
+ }
+ break;
+
+ case CPU_K6_2:
+ switch (EAX)
+ {
+ case 0:
+ EAX = 1;
+ EBX = 0x68747541; /*AuthenticAMD*/
+ ECX = 0x444d4163;
+ EDX = 0x69746e65;
+ break;
+ case 1:
+ EAX = CPUID;
+ EBX = ECX = 0;
+ EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B | CPUID_MMX;
+ break;
+ case 0x80000000:
+ EAX = 0x80000005;
+ break;
+ case 0x80000001:
+ EAX = CPUID+0x100;
+ EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B | CPUID_MMX | CPUID_3DNOW;
+ break;
+
+ case 0x80000002: /*Processor name string*/
+ EAX = 0x2d444d41; /*AMD-K6(tm) 3D pr*/
+ EBX = 0x7428364b;
+ ECX = 0x3320296d;
+ EDX = 0x72702044;
+ break;
+
+ case 0x80000003: /*Processor name string*/
+ EAX = 0x7365636f; /*ocessor*/
+ EBX = 0x00726f73;
+ ECX = 0x00000000;
+ EDX = 0x00000000;
+ break;
+
+ case 0x80000005: /*Cache information*/
+ EBX = 0x02800140; /*TLBs*/
+ ECX = 0x20020220; /*L1 data cache*/
+ EDX = 0x20020220; /*L1 instruction cache*/
+ break;
+
+ default:
+ EAX = EBX = ECX = EDX = 0;
+ break;
+ }
+ break;
+
+ case CPU_K6_3:
+ switch (EAX)
+ {
+ case 0:
+ EAX = 1;
+ EBX = 0x68747541; /*AuthenticAMD*/
+ ECX = 0x444d4163;
+ EDX = 0x69746e65;
+ break;
+ case 1:
+ EAX = CPUID;
+ EBX = ECX = 0;
+ EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B | CPUID_MMX;
+ break;
+ case 0x80000000:
+ EAX = 0x80000006;
+ break;
+ case 0x80000001:
+ EAX = CPUID+0x100;
+ EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B | CPUID_MMX | CPUID_3DNOW;
+ break;
+
+ case 0x80000002: /*Processor name string*/
+ EAX = 0x2d444d41; /*AMD-K6(tm) 3D+ P*/
+ EBX = 0x7428364b;
+ ECX = 0x3320296d;
+ EDX = 0x50202b44;
+ break;
+
+ case 0x80000003: /*Processor name string*/
+ EAX = 0x65636f72; /*rocessor*/
+ EBX = 0x726f7373;
+ ECX = 0x00000000;
+ EDX = 0x00000000;
+ break;
+
+ case 0x80000005: /*Cache information*/
+ EBX = 0x02800140; /*TLBs*/
+ ECX = 0x20020220; /*L1 data cache*/
+ EDX = 0x20020220; /*L1 instruction cache*/
+ break;
+
+ case 0x80000006: /*L2 Cache information*/
+ ECX = 0x01004220;
+ break;
+
+ default:
+ EAX = EBX = ECX = EDX = 0;
+ break;
+ }
+ break;
+
+ case CPU_K6_2P:
+ case CPU_K6_3P:
+ switch (EAX)
+ {
+ case 0:
+ EAX = 1;
+ EBX = 0x68747541; /*AuthenticAMD*/
+ ECX = 0x444d4163;
+ EDX = 0x69746e65;
+ break;
+ case 1:
+ EAX = CPUID;
+ EBX = ECX = 0;
+ EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B | CPUID_MMX;
+ break;
+ case 0x80000000:
+ EAX = 0x80000007;
+ break;
+ case 0x80000001:
+ EAX = CPUID+0x100;
+ EDX = CPUID_FPU | CPUID_VME | CPUID_PSE | CPUID_TSC | CPUID_MSR | CPUID_CMPXCHG8B | CPUID_MMX | CPUID_3DNOW;
+ break;
+
+ case 0x80000002: /*Processor name string*/
+ EAX = 0x2d444d41; /*AMD-K6(tm)-III P*/
+ EBX = 0x7428364b;
+ ECX = 0x492d296d;
+ EDX = 0x50204949;
+ break;
+
+ case 0x80000003: /*Processor name string*/
+ EAX = 0x65636f72; /*rocessor*/
+ EBX = 0x726f7373;
+ ECX = 0x00000000;
+ EDX = 0x00000000;
+ break;
+
+ case 0x80000005: /*Cache information*/
+ EBX = 0x02800140; /*TLBs*/
+ ECX = 0x20020220; /*L1 data cache*/
+ EDX = 0x20020220; /*L1 instruction cache*/
+ break;
+
+ case 0x80000006: /*L2 Cache information*/
+ if (models[model].cpu[cpu_manufacturer].cpus[cpu].cpu_type == CPU_K6_3P)
+ ECX = 0x01004220;
+ else
+ ECX = 0x00804220;
+ break;
+
+ case 0x80000007: /*PowerNow information*/
+ EDX = 7;
+ break;
+
+ default:
+ EAX = EBX = ECX = EDX = 0;
+ break;
+ }
+ break;
}
}
switch (models[model].cpu[cpu_manufacturer].cpus[cpu].cpu_type)
{
case CPU_WINCHIP:
+ case CPU_WINCHIP2:
EAX = EDX = 0;
switch (ECX)
{
break;
}
break;
+ case CPU_K6:
+ case CPU_K6_2:
+ case CPU_K6_3:
+ case CPU_K6_2P:
+ case CPU_K6_3P:
+ EAX = EDX = 0;
+ switch (ECX)
+ {
+ case 0x10:
+ EAX = tsc & 0xffffffff;
+ EDX = tsc >> 32;
+ break;
+ }
+ break;
}
}
switch (models[model].cpu[cpu_manufacturer].cpus[cpu].cpu_type)
{
case CPU_WINCHIP:
+ case CPU_WINCHIP2:
switch (ECX)
{
case 0x02:
break;
case 0x107:
msr.fcr = EAX;
- cpu_hasMMX = EAX & (1 << 9);
+ if (EAX & (1 << 9))
+ cpu_features |= CPU_FEATURE_MMX;
+ else
+ cpu_features &= ~CPU_FEATURE_MMX;
if (EAX & (1 << 1))
- cpu_hasCX8 = 1;
+ cpu_features |= CPU_FEATURE_CX8;
+ else
+ cpu_features &= ~CPU_FEATURE_CX8;
+ if ((EAX & (1 << 20)) && models[model].cpu[cpu_manufacturer].cpus[cpu].cpu_type >= CPU_WINCHIP2)
+ cpu_features |= CPU_FEATURE_3DNOW;
else
- cpu_hasCX8 = 0;
+ cpu_features &= ~CPU_FEATURE_3DNOW;
if (EAX & (1 << 29))
CPUID = 0;
else
break;
}
break;
+ case CPU_K6:
+ case CPU_K6_2:
+ case CPU_K6_3:
+ case CPU_K6_2P:
+ case CPU_K6_3P:
+ switch (ECX)
+ {
+ case 0x10:
+ tsc = EAX | ((uint64_t)EDX << 32);
+ break;
+ }
+ break;
}
}
{
x86_opcodes = opcodes;
x86_opcodes_0f = opcodes_0f;
- //x86_dynarec_opcodes = dynarec_opcodes;
- //x86_dynarec_opcodes_0f = dynarec_opcodes_0f;
+ x86_dynarec_opcodes = dynarec_opcodes;
+ x86_dynarec_opcodes_0f = dynarec_opcodes_0f;
}
void cpu_update_waitstates()
#ifndef _CPU_H_
#define _CPU_H_
-//extern int cpu;
-extern int cpu_manufacturer;
+extern int cpu, cpu_manufacturer;
+extern int fpu_type;
/*808x class CPUs*/
#define CPU_8088 0
/*586 class CPUs*/
#define CPU_WINCHIP 15
-#define CPU_PENTIUM 16
-#define CPU_PENTIUMMMX 17
-#define CPU_Cx6x86 18
-#define CPU_Cx6x86MX 19
-#define CPU_Cx6x86L 20
-#define CPU_CxGX1 21
+#define CPU_WINCHIP2 16
+#define CPU_PENTIUM 17
+#define CPU_PENTIUMMMX 18
+#define CPU_Cx6x86 19
+#define CPU_Cx6x86MX 20
+#define CPU_Cx6x86L 21
+#define CPU_CxGX1 22
+#define CPU_K6 23
+#define CPU_K6_2 24
+#define CPU_K6_3 25
+#define CPU_K6_2P 26
+#define CPU_K6_3P 27
#define MANU_INTEL 0
#define MANU_AMD 1
extern int timing_misaligned;
+enum
+{
+ FPU_NONE,
+ FPU_8087,
+ FPU_287,
+ FPU_287XL,
+ FPU_387,
+ FPU_BUILTIN
+};
+
+typedef struct
+{
+ const char *name;
+ const char *internal_name;
+ const int type;
+} FPU;
+
typedef struct
{
char name[32];
int cpu_type;
+ const FPU *fpus;
int speed;
int rspeed;
int multi;
extern CPU cpus_Am486[];
extern CPU cpus_Cx486[];
extern CPU cpus_WinChip[];
+extern CPU cpus_WinChip_SS7[];
extern CPU cpus_Pentium5V[];
extern CPU cpus_PentiumS5[];
extern CPU cpus_Pentium[];
extern CPU cpus_6x86[];
+extern CPU cpus_6x86_SS7[];
+extern CPU cpus_K6_S7[];
+extern CPU cpus_K6_SS7[];
extern CPU cpus_pcjr[];
extern CPU cpus_europc[];
extern CPU cpus_pc1512[];
+extern CPU cpus_super286tr[];
extern CPU cpus_ibmat[];
extern CPU cpus_ibmxt286[];
extern CPU cpus_ps1_m2011[];
/*Cyrix 5x86/6x86 only has data misalignment penalties when crossing 8-byte boundaries*/
extern int cpu_cyrix_alignment;
-extern int cpu_hasrdtsc;
-extern int cpu_hasMSR;
-extern int cpu_hasMMX;
-extern int cpu_hasCR4;
-extern int cpu_hasVME;
-extern int cpu_hasCX8;
+#define CPU_FEATURE_RDTSC (1 << 0)
+#define CPU_FEATURE_MSR (1 << 1)
+#define CPU_FEATURE_MMX (1 << 2)
+#define CPU_FEATURE_CR4 (1 << 3)
+#define CPU_FEATURE_VME (1 << 4)
+#define CPU_FEATURE_CX8 (1 << 5)
+#define CPU_FEATURE_3DNOW (1 << 6)
+
+extern uint32_t cpu_features;
+static inline int cpu_has_feature(int feature)
+{
+ return cpu_features & feature;
+}
#define CR4_TSD (1 << 2)
#define CR4_DE (1 << 3)
uint8_t cyrix_read(uint16_t addr, void *priv);
extern int is8086;
+extern int is486;
+extern int CPUID;
void cpu_CPUID();
void cpu_RDMSR();
extern int cpu_use_dynarec;
-extern int xt_cpu_multi;
+extern uint64_t xt_cpu_multi;
extern int isa_cycles;
#define ISA_CYCLES(x) (x * isa_cycles)
void cpu_update_waitstates();
-void cpu_set(int);
+void cpu_set();
void cpu_set_edx();
void cpu_set_turbo(int turbo);
int cpu_get_speed();
extern int has_vlb;
+int fpu_get_type(int model, int manu, int cpu, const char *internal_name);
+const char *fpu_get_internal_name(int model, int manu, int cpu, int type);
+const char *fpu_get_name_from_index(int model, int manu, int cpu, int c);
+int fpu_get_type_from_index(int model, int manu, int cpu, int c);
+
#endif
void fdc_poll();
void fdc_abort();
void fdc_discchange_clear(int drive);
+int fdc_discchange_read();
void fdc_set_dskchg_activelow();
void fdc_3f1_enable(int enable);
void fdc_set_ps1();
void fdc_update_densel_polarity(int densel_polarity);
void fdc_update_densel_force(int densel_force);
void fdc_update_drvrate(int drive, int drvrate);
+
+
+
+enum
+{
+ FDC_STATUS_AM_NOT_FOUND,
+ FDC_STATUS_NOT_FOUND,
+ FDC_STATUS_WRONG_CYLINDER,
+ FDC_STATUS_BAD_CYLINDER
+};
#include <stdint.h>
#include <string.h>
+#include "timer.h"
+
#ifdef ABS
#undef ABS
#endif
#define readflash_get(offset, drive) ((readflash&(1<<((offset)+(drive)))) != 0)
/*Memory*/
-extern uint8_t *ram;
+uint8_t *ram;
-extern uint32_t rammask;
+uint32_t rammask;
-extern int readlookup[256],readlookupp[256];
-extern uintptr_t *readlookup2;
-extern int readlnext;
-extern int writelookup[256],writelookupp[256];
-extern uintptr_t *writelookup2;
-extern int writelnext;
+int readlookup[256],readlookupp[256];
+uintptr_t *readlookup2;
+int readlnext;
+int writelookup[256],writelookupp[256];
+uintptr_t *writelookup2;
+int writelnext;
extern int mmu_perm;
-#define readmemb(a) ((readlookup2[(a)>>12]==-1)?readmembl(a):*(uint8_t *)(readlookup2[(a) >> 12] + (a)))
-#define readmemw(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF || (((s)+(a)) & 1))?readmemwl(s,a):*(uint16_t *)(readlookup2[(uint32_t)((s)+(a))>>12]+(uint32_t)((s)+(a))))
-#define readmeml(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF || (((s)+(a)) & 3))?readmemll(s,a):*(uint32_t *)(readlookup2[(uint32_t)((s)+(a))>>12]+(uint32_t)((s)+(a))))
-
-//#define writememb(a,v) if (writelookup2[(a)>>12]==0xFFFFFFFF) writemembl(a,v); else ram[writelookup2[(a)>>12]+((a)&0xFFF)]=v
-//#define writememw(s,a,v) if (writelookup2[((s)+(a))>>12]==0xFFFFFFFF || (s)==0xFFFFFFFF) writememwl(s,a,v); else *((uint16_t *)(&ram[writelookup2[((s)+(a))>>12]+(((s)+(a))&0xFFF)]))=v
-//#define writememl(s,a,v) if (writelookup2[((s)+(a))>>12]==0xFFFFFFFF || (s)==0xFFFFFFFF) writememll(s,a,v); else *((uint32_t *)(&ram[writelookup2[((s)+(a))>>12]+(((s)+(a))&0xFFF)]))=v
-//#define readmemb(a) ((isram[((a)>>16)&255] && !(cr0>>31))?ram[a&0xFFFFFF]:readmembl(a))
-//#define writememb(a,v) if (isram[((a)>>16)&255] && !(cr0>>31)) ram[a&0xFFFFFF]=v; else writemembl(a,v)
-
-//void writememb(uint32_t addr, uint8_t val);
uint8_t readmembl(uint32_t addr);
void writemembl(uint32_t addr, uint8_t val);
-uint8_t readmemb386l(uint32_t seg, uint32_t addr);
-void writememb386l(uint32_t seg, uint32_t addr, uint8_t val);
-uint16_t readmemwl(uint32_t seg, uint32_t addr);
-void writememwl(uint32_t seg, uint32_t addr, uint16_t val);
-uint32_t readmemll(uint32_t seg, uint32_t addr);
-void writememll(uint32_t seg, uint32_t addr, uint32_t val);
-uint64_t readmemql(uint32_t seg, uint32_t addr);
-void writememql(uint32_t seg, uint32_t addr, uint64_t val);
+uint16_t readmemwl(uint32_t addr);
+void writememwl(uint32_t addr, uint16_t val);
+uint32_t readmemll(uint32_t addr);
+void writememll(uint32_t addr, uint32_t val);
+uint64_t readmemql(uint32_t addr);
+void writememql(uint32_t addr, uint64_t val);
uint8_t *getpccache(uint32_t a);
void outl(uint16_t port, uint32_t val);
FILE *romfopen(char *fn, char *mode);
-extern int shadowbios,shadowbios_write;
extern int mem_size;
extern int readlnum,writelnum;
/*Processor*/
-#define EAX cpu_state.regs[0].l
-#define ECX cpu_state.regs[1].l
-#define EDX cpu_state.regs[2].l
-#define EBX cpu_state.regs[3].l
-#define ESP cpu_state.regs[4].l
-#define EBP cpu_state.regs[5].l
-#define ESI cpu_state.regs[6].l
-#define EDI cpu_state.regs[7].l
-#define AX cpu_state.regs[0].w
-#define CX cpu_state.regs[1].w
-#define DX cpu_state.regs[2].w
-#define BX cpu_state.regs[3].w
-#define SP cpu_state.regs[4].w
-#define BP cpu_state.regs[5].w
-#define SI cpu_state.regs[6].w
-#define DI cpu_state.regs[7].w
-#define AL cpu_state.regs[0].b.l
-#define AH cpu_state.regs[0].b.h
-#define CL cpu_state.regs[1].b.l
-#define CH cpu_state.regs[1].b.h
-#define DL cpu_state.regs[2].b.l
-#define DH cpu_state.regs[2].b.h
-#define BL cpu_state.regs[3].b.l
-#define BH cpu_state.regs[3].b.h
-
-typedef union
-{
- uint32_t l;
- uint16_t w;
- struct
- {
- uint8_t l,h;
- } b;
-} x86reg;
-
-typedef struct
-{
- uint32_t base;
- uint32_t limit;
- uint8_t access;
- uint16_t seg;
- uint32_t limit_low, limit_high;
- int checked; /*Non-zero if selector is known to be valid*/
-} x86seg;
-
-typedef union MMX_REG
-{
- uint64_t q;
- int64_t sq;
- uint32_t l[2];
- int32_t sl[2];
- uint16_t w[4];
- int16_t sw[4];
- uint8_t b[8];
- int8_t sb[8];
-} MMX_REG;
+extern int ins, output, timetolive;
-typedef struct
-{
- x86reg regs[8];
-
- uint8_t tag[8];
-
- x86seg *ea_seg;
- uint32_t eaaddr;
-
- int flags_op;
- uint32_t flags_res;
- uint32_t flags_op1, flags_op2;
-
- uint32_t pc;
- uint32_t oldpc;
- uint32_t op32;
-
- int TOP;
-
- union
- {
- struct
- {
- int8_t rm, mod, reg;
- } rm_mod_reg;
- uint32_t rm_mod_reg_data;
- } rm_data;
-
- int8_t ssegs;
- int8_t ismmx;
- int8_t abrt;
-
- int _cycles;
- int cpu_recomp_ins;
-
- uint16_t npxs, npxc;
-
- double ST[8];
-
- uint16_t MM_w4[8];
-
- MMX_REG MM[8];
-
- uint16_t old_npxc, new_npxc;
-} cpu_state_s;
-
-extern cpu_state_s cpu_state;
-
-#define cycles cpu_state._cycles
-
-extern uint32_t cpu_cur_status;
-
-/*The flags below must match in both cpu_cur_status and block->status for a block
- to be valid*/
-#define CPU_STATUS_USE32 (1 << 0)
-#define CPU_STATUS_STACK32 (1 << 1)
-#define CPU_STATUS_PMODE (1 << 2)
-#define CPU_STATUS_V86 (1 << 3)
-#define CPU_STATUS_FLAGS 0xffff
-
-/*If the flags below are set in cpu_cur_status, they must be set in block->status.
- Otherwise they are ignored*/
-#define CPU_STATUS_NOTFLATDS (1 << 16)
-#define CPU_STATUS_NOTFLATSS (1 << 17)
-#define CPU_STATUS_MASK 0xffff0000
-
-#define COMPILE_TIME_ASSERT(expr) typedef char COMP_TIME_ASSERT[(expr) ? 1 : 0];
-
-//COMPILE_TIME_ASSERT(sizeof(cpu_state) <= 128);
-
-#define cpu_state_offset(MEMBER) ((uintptr_t)&cpu_state.MEMBER - (uintptr_t)&cpu_state - 128)
-
-extern uint16_t flags,eflags;
-extern uint32_t oldds,oldss,olddslimit,oldsslimit,olddslimitw,oldsslimitw;
-
-extern int ins,output;
-extern int cycdiff;
-
-extern x86seg gdt,ldt,idt,tr;
-extern x86seg _cs,_ds,_es,_ss,_fs,_gs;
-extern x86seg _oldds;
-
-extern int32_t pccache;
-extern uint8_t *pccache2;
-/*Segments -
- _cs,_ds,_es,_ss are the segment structures
- CS,DS,ES,SS is the 16-bit data
- cs,ds,es,ss are defines to the bases*/
-#define CS _cs.seg
-#define DS _ds.seg
-#define ES _es.seg
-#define SS _ss.seg
-#define FS _fs.seg
-#define GS _gs.seg
-#define cs _cs.base
-#define ds _ds.base
-#define es _es.base
-#define ss _ss.base
-#define seg_fs _fs.base
-#define gs _gs.base
-
-#define CPL ((_cs.access>>5)&3)
-
-void loadseg(uint16_t seg, x86seg *s);
-void loadcs(uint16_t seg);
-
-union CR0_s
-{
- uint32_t l;
- uint16_t w;
-};
-
-extern union CR0_s CR0;
-
-#define cr0 CR0.l
-#define msw CR0.w
-
-extern uint32_t cr2, cr3, cr4;
-extern uint32_t dr[8];
-
-#define C_FLAG 0x0001
-#define P_FLAG 0x0004
-#define A_FLAG 0x0010
-#define Z_FLAG 0x0040
-#define N_FLAG 0x0080
-#define T_FLAG 0x0100
-#define I_FLAG 0x0200
-#define D_FLAG 0x0400
-#define V_FLAG 0x0800
-#define NT_FLAG 0x4000
-#define VM_FLAG 0x0002 /*In EFLAGS*/
-#define VIF_FLAG 0x0008 /*In EFLAGS*/
-#define VIP_FLAG 0x0010 /*In EFLAGS*/
-
-#define WP_FLAG 0x10000 /*In CR0*/
-
-#define CR4_VME (1 << 0)
-#define CR4_PVI (1 << 1)
-#define CR4_PSE (1 << 4)
-
-#define IOPL ((flags>>12)&3)
-
-#define IOPLp ((!(msw&1)) || (CPL<=IOPL))
-//#define IOPLp 1
-
-//#define IOPLV86 ((!(msw&1)) || (CPL<=IOPL))
extern int cycles_lost;
-extern int is486;
-extern uint8_t opcode;
-extern int insc;
-extern int fpucount;
-extern float mips,flops;
-extern int cgate16;
-extern int CPUID;
-
-extern int cpl_override;
/*Timer*/
typedef struct PIT_nr
typedef struct PIT
{
uint32_t l[3];
- int c[3];
+ pc_timer_t timer[3];
uint8_t m[3];
uint8_t ctrl,ctrls[3];
int wp,rm[3],wm[3];
void (*set_out_funcs[3])(int new_out, int old_out);
} PIT;
-extern PIT pit, pit2;
+PIT pit, pit2;
void setpitclock(float clock);
float pit_timer0_freq();
uint16_t io_addr;
} dma_t;
-extern dma_t dma[8];
+dma_t dma[8];
/*PPI*/
typedef struct PPI
uint8_t pa,pb;
} PPI;
-extern PPI ppi;
+PPI ppi;
/*PIC*/
uint8_t level_sensitive;
} PIC;
-extern PIC pic,pic2;
+PIC pic,pic2;
extern int pic_intpending;
-extern int disctime;
-extern char discfns[2][256];
-extern int driveempty[2];
+char discfns[2][256];
+int driveempty[2];
#define PCJR (romset == ROM_IBMPCJR)
-extern int GAMEBLASTER, GUS, SSI2001, voodoo_enabled;
-extern int AMSTRAD, AT, is386, PCI, TANDY;
+int GAMEBLASTER, GUS, SSI2001, voodoo_enabled;
+extern int AMSTRAD, AT, is386, PCI, TANDY, MCA;
enum
{
- ROM_IBMPC = 0, /*301 keyboard error, 131 cassette (!!!) error*/
- ROM_IBMXT, /*301 keyboard error*/
+ ROM_IBMPC = 0,
+ ROM_IBMXT,
ROM_IBMPCJR,
ROM_GENXT, /*'Generic XT BIOS'*/
ROM_DTKXT,
ROM_IBMAT,
ROM_CMDPC30,
ROM_AMI286,
+ ROM_TG286M,
ROM_AWARD286,
+ ROM_GDC212M,
ROM_GW286CT,
ROM_SPC4200P,
ROM_SPC4216P,
+ ROM_SPC4620P,
ROM_DELL200,
ROM_MISC286,
ROM_IBMAT386,
ROM_ACER386,
ROM_KMXC02,
ROM_MEGAPC,
+ ROM_AMA932J,
ROM_AMI386SX,
ROM_AMI486,
ROM_WIN486,
ROM_PCI486,
ROM_SIS496,
+ ROM_P55VA, /* Epox P55-VA/430VX/Award/SMC FDC37C932FR*/
+ ROM_P55TVP4, /* ASUS P/I-P55TVP4/430VX/Award/Winbond W8387F*/
ROM_430VX,
ROM_ENDEAVOR,
ROM_REVENGE,
ROM_IBMPS1_2121,
ROM_AMI386DX_OPTI495,
ROM_MR386DX_OPTI495,
+ ROM_P55T2P4, /* ASUS P/I-P55T2P4/430HX/Award/Winbond W8387F*/
ROM_IBMPS2_M30_286,
ROM_IBMPS2_M50,
ROM_IBMPS2_M55SX,
ROM_XI8088,
ROM_IBMPS2_M70_TYPE3,
ROM_IBMPS2_M70_TYPE4,
-
+ ROM_TULIP_TC7,
+ ROM_ZD_SUPERS, /* [8088] Zenith Data Systems SupersPort */
+ ROM_PB410A,
+ ROM_PPC512,
+ ROM_BULL_MICRAL_45,
+ ROM_FIC_VA503P,
+ ROM_CBM_SL386SX25,
+ ROM_IBMPS1_2133_451,
+ ROM_ECS_386_32,
+ ROM_LEDGE_MODELM,
+ ROM_HYUNDAI_SUPER286TR,
+ ROM_ITAUTEC_INFOWAYM,
+
ROM_MAX
};
extern int romspresent[ROM_MAX];
-extern int hasfpu;
-extern int romset;
+int hasfpu;
+int romset;
enum
{
GFX_EGA, /*Using IBM EGA BIOS*/
GFX_TVGA, /*Using Trident TVGA8900D BIOS*/
GFX_ET4000, /*Tseng ET4000*/
+ GFX_TGKOREANVGA, /*Trigem Korean VGA(Tseng ET4000AX)*/
GFX_ET4000W32, /*Tseng ET4000/W32p (Diamond Stealth 32)*/
GFX_BAHAMAS64, /*S3 Vision864 (Paradise Bahamas 64)*/
GFX_N9_9FX, /*S3 764/Trio64 (Number Nine 9FX)*/
GFX_CL_GD5434, /*Cirrus Logic CL-GD5434*/
GFX_OTI037, /*Oak OTI-037*/
GFX_COMPAQ_CGA, /*Compaq CGA*/
+ GFX_SIGMA400, /*Sigma Designs Color 400 */
+ GFX_PGC, /*Professional Graphics Controller */
+ GFX_IM1024, /*Vermont Microsystems IM1024 */
+ GFX_EGAWONDER800, /*ATI EGA Wonder 800+*/
+ GFX_MYSTIQUE, /*Matrox Mystique*/
+ GFX_AVGA2, /*Acumos AVGA2 / Cirrus Logic CL-GD5402*/
+ GFX_CL_GD5428, /*Cirrus Logic CL-GD5428*/
+ GFX_IBM_GD5428, /*IBM 1MB SVGA Adapter/A*/
+
GFX_MAX
};
extern int gfx_present[GFX_MAX];
-extern int gfxcard;
+int gfxcard;
-extern int cpuspeed;
+int cpuspeed;
/*Video*/
-extern int readflash;
+int readflash;
extern int egareads,egawrites;
extern int vid_resize;
extern int vid_api;
/*Sound*/
-extern int ppispeakon;
-extern float CGACONST;
-extern float MDACONST;
-extern float VGACONST1,VGACONST2;
-extern float RTCCONST;
-extern int gated,speakval,speakon;
+int ppispeakon;
+extern uint64_t CGACONST;
+extern uint64_t MDACONST;
+extern uint64_t VGACONST1,VGACONST2;
+extern uint64_t RTCCONST;
+int gated,speakval,speakon;
/*Sound Blaster*/
int tracks;
} PcemHDC;
-extern PcemHDC hdc[7];
+PcemHDC hdc[7];
/*Keyboard*/
-extern int keybsenddelay;
+int keybsenddelay;
/*CD-ROM*/
typedef struct
{
- int scancodes_make[8];
- int scancodes_break[8];
+ uint8_t scancodes_make[8];
+ uint8_t scancodes_break[8];
} scancode;
/*272 = 256 + 16 fake interim scancodes for disambiguation purposes.*/
static scancode scancode_set1[272] =
{
- { {-1}, {-1} }, { {0x01, -1}, {0x81, -1} }, { {0x02, -1}, {0x82, -1} }, { {0x03, -1}, {0x83, -1} },
- { {0x04, -1}, {0x84, -1} }, { {0x05, -1}, {0x85, -1} }, { {0x06, -1}, {0x86, -1} }, { {0x07, -1}, {0x87, -1} },
- { {0x08, -1}, {0x88, -1} }, { {0x09, -1}, {0x89, -1} }, { {0x0a, -1}, {0x8a, -1} }, { {0x0b, -1}, {0x8b, -1} },
- { {0x0c, -1}, {0x8c, -1} }, { {0x0d, -1}, {0x8d, -1} }, { {0x0e, -1}, {0x8e, -1} }, { {0x0f, -1}, {0x8f, -1} },
- { {0x10, -1}, {0x90, -1} }, { {0x11, -1}, {0x91, -1} }, { {0x12, -1}, {0x92, -1} }, { {0x13, -1}, {0x93, -1} },
- { {0x14, -1}, {0x94, -1} }, { {0x15, -1}, {0x95, -1} }, { {0x16, -1}, {0x96, -1} }, { {0x17, -1}, {0x97, -1} },
- { {0x18, -1}, {0x98, -1} }, { {0x19, -1}, {0x99, -1} }, { {0x1a, -1}, {0x9a, -1} }, { {0x1b, -1}, {0x9b, -1} },
- { {0x1c, -1}, {0x9c, -1} }, { {0x1d, -1}, {0x9d, -1} }, { {0x1e, -1}, {0x9e, -1} }, { {0x1f, -1}, {0x9f, -1} },
- { {0x20, -1}, {0xa0, -1} }, { {0x21, -1}, {0xa1, -1} }, { {0x22, -1}, {0xa2, -1} }, { {0x23, -1}, {0xa3, -1} },
- { {0x24, -1}, {0xa4, -1} }, { {0x25, -1}, {0xa5, -1} }, { {0x26, -1}, {0xa6, -1} }, { {0x27, -1}, {0xa7, -1} },
- { {0x28, -1}, {0xa8, -1} }, { {0x29, -1}, {0xa9, -1} }, { {0x2a, -1}, {0xaa, -1} }, { {0x2b, -1}, {0xab, -1} },
- { {0x2c, -1}, {0xac, -1} }, { {0x2d, -1}, {0xad, -1} }, { {0x2e, -1}, {0xae, -1} }, { {0x2f, -1}, {0xaf, -1} },
- { {0x30, -1}, {0xb0, -1} }, { {0x31, -1}, {0xb1, -1} }, { {0x32, -1}, {0xb2, -1} }, { {0x33, -1}, {0xb3, -1} },
- { {0x34, -1}, {0xb4, -1} }, { {0x35, -1}, {0xb5, -1} }, { {0x36, -1}, {0xb6, -1} }, { {0x37, -1}, {0xb7, -1} },
- { {0x38, -1}, {0xb8, -1} }, { {0x39, -1}, {0xb9, -1} }, { {0x3a, -1}, {0xba, -1} }, { {0x3b, -1}, {0xbb, -1} },
- { {0x3c, -1}, {0xbc, -1} }, { {0x3d, -1}, {0xbd, -1} }, { {0x3e, -1}, {0xbe, -1} }, { {0x3f, -1}, {0xbf, -1} },
- { {0x40, -1}, {0xc0, -1} }, { {0x41, -1}, {0xc1, -1} }, { {0x42, -1}, {0xc2, -1} }, { {0x43, -1}, {0xc3, -1} },
- { {0x44, -1}, {0xc4, -1} }, { {0x45, -1}, {0xc5, -1} }, { {0x46, -1}, {0xc6, -1} }, { {0x47, -1}, {0xc7, -1} },
- { {0x48, -1}, {0xc8, -1} }, { {0x49, -1}, {0xc9, -1} }, { {0x4a, -1}, {0xca, -1} }, { {0x4b, -1}, {0xcb, -1} },
- { {0x4c, -1}, {0xcc, -1} }, { {0x4d, -1}, {0xcd, -1} }, { {0x4e, -1}, {0xce, -1} }, { {0x4f, -1}, {0xcf, -1} },
- { {0x50, -1}, {0xd0, -1} }, { {0x51, -1}, {0xd1, -1} }, { {0x52, -1}, {0xd2, -1} }, { {0x53, -1}, {0xd3, -1} },
- { {0x54, -1}, {0xd4, -1} }, { {0x55, -1}, {0xd5, -1} }, { {0x56, -1}, {0xd6, -1} }, { {0x57, -1}, {0xd7, -1} },
- { {0x58, -1}, {0xd8, -1} }, { {0x59, -1}, {0xd9, -1} }, { {0x5a, -1}, {0xda, -1} }, { {0x5b, -1}, {0xdb, -1} },
- { {0x5c, -1}, {0xdc, -1} }, { {0x5d, -1}, {0xdd, -1} }, { {0x5e, -1}, {0xde, -1} }, { {0x5f, -1}, {0xdf, -1} },
- { {0x60, -1}, {0xe0, -1} }, { {0x61, -1}, {0xe1, -1} }, { {0x62, -1}, {0xe2, -1} }, { {0x63, -1}, {0xe3, -1} },
- { {0x64, -1}, {0xe4, -1} }, { {0x65, -1}, {0xe5, -1} }, { {0x66, -1}, {0xe6, -1} }, { {0x67, -1}, {0xe7, -1} },
- { {0x68, -1}, {0xe8, -1} }, { {0x69, -1}, {0xe9, -1} }, { {0x6a, -1}, {0xea, -1} }, { {0x6b, -1}, {0xeb, -1} },
- { {0x6c, -1}, {0xec, -1} }, { {0x6d, -1}, {0xed, -1} }, { {0x6e, -1}, {0xee, -1} }, { {0x6f, -1}, {0xef, -1} },
- { {0x70, -1}, {0xf0, -1} }, { {0x71, -1}, {0xf1, -1} }, { {0x72, -1}, {0xf2, -1} }, { {0x73, -1}, {0xf3, -1} },
- { {0x74, -1}, {0xf4, -1} }, { {0x75, -1}, {0xf5, -1} }, { {0x76, -1}, {0xf6, -1} }, { {0x77, -1}, {0xf7, -1} },
- { {0x78, -1}, {0xf8, -1} }, { {0x79, -1}, {0xf9, -1} }, { {0x7a, -1}, {0xfa, -1} }, { {0x7b, -1}, {0xfb, -1} },
- { {0x7c, -1}, {0xfc, -1} }, { {0x7d, -1}, {0xfd, -1} }, { {0x7e, -1}, {0xfe, -1} }, { {0x7f, -1}, {0xff, -1} },
+ { {0}, {0} }, { {0x01, 0}, {0x81, 0} }, { {0x02, 0}, {0x82, 0} }, { {0x03, 0}, {0x83, 0} },
+ { {0x04, 0}, {0x84, 0} }, { {0x05, 0}, {0x85, 0} }, { {0x06, 0}, {0x86, 0} }, { {0x07, 0}, {0x87, 0} },
+ { {0x08, 0}, {0x88, 0} }, { {0x09, 0}, {0x89, 0} }, { {0x0a, 0}, {0x8a, 0} }, { {0x0b, 0}, {0x8b, 0} },
+ { {0x0c, 0}, {0x8c, 0} }, { {0x0d, 0}, {0x8d, 0} }, { {0x0e, 0}, {0x8e, 0} }, { {0x0f, 0}, {0x8f, 0} },
+ { {0x10, 0}, {0x90, 0} }, { {0x11, 0}, {0x91, 0} }, { {0x12, 0}, {0x92, 0} }, { {0x13, 0}, {0x93, 0} },
+ { {0x14, 0}, {0x94, 0} }, { {0x15, 0}, {0x95, 0} }, { {0x16, 0}, {0x96, 0} }, { {0x17, 0}, {0x97, 0} },
+ { {0x18, 0}, {0x98, 0} }, { {0x19, 0}, {0x99, 0} }, { {0x1a, 0}, {0x9a, 0} }, { {0x1b, 0}, {0x9b, 0} },
+ { {0x1c, 0}, {0x9c, 0} }, { {0x1d, 0}, {0x9d, 0} }, { {0x1e, 0}, {0x9e, 0} }, { {0x1f, 0}, {0x9f, 0} },
+ { {0x20, 0}, {0xa0, 0} }, { {0x21, 0}, {0xa1, 0} }, { {0x22, 0}, {0xa2, 0} }, { {0x23, 0}, {0xa3, 0} },
+ { {0x24, 0}, {0xa4, 0} }, { {0x25, 0}, {0xa5, 0} }, { {0x26, 0}, {0xa6, 0} }, { {0x27, 0}, {0xa7, 0} },
+ { {0x28, 0}, {0xa8, 0} }, { {0x29, 0}, {0xa9, 0} }, { {0x2a, 0}, {0xaa, 0} }, { {0x2b, 0}, {0xab, 0} },
+ { {0x2c, 0}, {0xac, 0} }, { {0x2d, 0}, {0xad, 0} }, { {0x2e, 0}, {0xae, 0} }, { {0x2f, 0}, {0xaf, 0} },
+ { {0x30, 0}, {0xb0, 0} }, { {0x31, 0}, {0xb1, 0} }, { {0x32, 0}, {0xb2, 0} }, { {0x33, 0}, {0xb3, 0} },
+ { {0x34, 0}, {0xb4, 0} }, { {0x35, 0}, {0xb5, 0} }, { {0x36, 0}, {0xb6, 0} }, { {0x37, 0}, {0xb7, 0} },
+ { {0x38, 0}, {0xb8, 0} }, { {0x39, 0}, {0xb9, 0} }, { {0x3a, 0}, {0xba, 0} }, { {0x3b, 0}, {0xbb, 0} },
+ { {0x3c, 0}, {0xbc, 0} }, { {0x3d, 0}, {0xbd, 0} }, { {0x3e, 0}, {0xbe, 0} }, { {0x3f, 0}, {0xbf, 0} },
+ { {0x40, 0}, {0xc0, 0} }, { {0x41, 0}, {0xc1, 0} }, { {0x42, 0}, {0xc2, 0} }, { {0x43, 0}, {0xc3, 0} },
+ { {0x44, 0}, {0xc4, 0} }, { {0x45, 0}, {0xc5, 0} }, { {0x46, 0}, {0xc6, 0} }, { {0x47, 0}, {0xc7, 0} },
+ { {0x48, 0}, {0xc8, 0} }, { {0x49, 0}, {0xc9, 0} }, { {0x4a, 0}, {0xca, 0} }, { {0x4b, 0}, {0xcb, 0} },
+ { {0x4c, 0}, {0xcc, 0} }, { {0x4d, 0}, {0xcd, 0} }, { {0x4e, 0}, {0xce, 0} }, { {0x4f, 0}, {0xcf, 0} },
+ { {0x50, 0}, {0xd0, 0} }, { {0x51, 0}, {0xd1, 0} }, { {0x52, 0}, {0xd2, 0} }, { {0x53, 0}, {0xd3, 0} },
+ { {0x54, 0}, {0xd4, 0} }, { {0x55, 0}, {0xd5, 0} }, { {0x56, 0}, {0xd6, 0} }, { {0x57, 0}, {0xd7, 0} },
+ { {0x58, 0}, {0xd8, 0} }, { {0x59, 0}, {0xd9, 0} }, { {0x5a, 0}, {0xda, 0} }, { {0x5b, 0}, {0xdb, 0} },
+ { {0x5c, 0}, {0xdc, 0} }, { {0x5d, 0}, {0xdd, 0} }, { {0x5e, 0}, {0xde, 0} }, { {0x5f, 0}, {0xdf, 0} },
+ { {0x60, 0}, {0xe0, 0} }, { {0x61, 0}, {0xe1, 0} }, { {0x62, 0}, {0xe2, 0} }, { {0x63, 0}, {0xe3, 0} },
+ { {0x64, 0}, {0xe4, 0} }, { {0x65, 0}, {0xe5, 0} }, { {0x66, 0}, {0xe6, 0} }, { {0x67, 0}, {0xe7, 0} },
+ { {0x68, 0}, {0xe8, 0} }, { {0x69, 0}, {0xe9, 0} }, { {0x6a, 0}, {0xea, 0} }, { {0x6b, 0}, {0xeb, 0} },
+ { {0x6c, 0}, {0xec, 0} }, { {0x6d, 0}, {0xed, 0} }, { {0x6e, 0}, {0xee, 0} }, { {0x6f, 0}, {0xef, 0} },
+ { {0x70, 0}, {0xf0, 0} }, { {0x71, 0}, {0xf1, 0} }, { {0x72, 0}, {0xf2, 0} }, { {0x73, 0}, {0xf3, 0} },
+ { {0x74, 0}, {0xf4, 0} }, { {0x75, 0}, {0xf5, 0} }, { {0x76, 0}, {0xf6, 0} }, { {0x77, 0}, {0xf7, 0} },
+ { {0x78, 0}, {0xf8, 0} }, { {0x79, 0}, {0xf9, 0} }, { {0x7a, 0}, {0xfa, 0} }, { {0x7b, 0}, {0xfb, 0} },
+ { {0x7c, 0}, {0xfc, 0} }, { {0x7d, 0}, {0xfd, 0} }, { {0x7e, 0}, {0xfe, 0} }, { {0x7f, 0}, {0xff, 0} },
- { {0x80, -1}, {-1} }, { {0x81, -1}, {-1} }, { {0x82, -1}, {-1} }, { {0xe0, 0x03, -1}, {0xe0, 0x83, -1} }, /*80*/
- { {0xe0, 0x04, -1}, {0xe0, 0x84, -1} }, { {0x85, -1}, {-1} }, { {0x86, -1}, {-1} }, { {0x87, -1}, {-1} }, /*84*/
- { {0xe0, 0x08, -1}, {0xe0, 0x88, -1} }, { {0xe0, 0x09, -1}, {0xe0, 0x89, -1} }, { {0xe0, 0x0a, -1}, {0xe0, 0x8a, -1} }, { {0xe0, 0x0b, -1}, {0xe0, 0x8b, -1} }, /*88*/
- { {0xe0, 0x0c, -1}, {0xe0, 0x8c, -1} }, { {-1}, {-1} }, { {0xe0, 0x0e, -1}, {0xe0, 0x8e, -1} }, { {0xe0, 0x0f, -1}, {0xe0, 0x8f, -1} }, /*8c*/
- { {0xe0, 0x10, -1}, {0xe0, 0x90, -1} }, { {0xe0, 0x11, -1}, {0xe0, 0x91, -1} }, { {0xe0, 0x12, -1}, {0xe0, 0x92, -1} }, { {0xe0, 0x13, -1}, {0xe0, 0x93, -1} }, /*90*/
- { {0xe0, 0x14, -1}, {0xe0, 0x94, -1} }, { {0xe0, 0x15, -1}, {0xe0, 0x95, -1} }, { {0xe0, 0x16, -1}, {0xe0, 0x96, -1} }, { {0xe0, 0x17, -1}, {0xe0, 0x97, -1} }, /*94*/
- { {0xe0, 0x18, -1}, {0xe0, 0x98, -1} }, { {0xe0, 0x19, -1}, {0xe0, 0x99, -1} }, { {0xe0, 0x1a, -1}, {0xe0, 0x9a, -1} }, { {0xe0, 0x1b, -1}, {0xe0, 0x9b, -1} }, /*98*/
- { {0xe0, 0x1c, -1}, {0xe0, 0x9c, -1} }, { {0xe0, 0x1d, -1}, {0xe0, 0x9d, -1} }, { {0xe0, 0x1e, -1}, {0xe0, 0x9e, -1} }, { {0xe0, 0x1f, -1}, {0xe0, 0x9f, -1} }, /*9c*/
- { {0xe0, 0x20, -1}, {0xe0, 0xa0, -1} }, { {0xe0, 0x21, -1}, {0xe0, 0xa1, -1} }, { {0xe0, 0x22, -1}, {0xe0, 0xa2, -1} }, { {0xe0, 0x23, -1}, {0xe0, 0xa3, -1} }, /*a0*/
- { {0xe0, 0x24, -1}, {0xe0, 0xa4, -1} }, { {0xe0, 0x25, -1}, {0xe0, 0xa5, -1} }, { {0xe0, 0x26, -1}, {0xe0, 0xa6, -1} }, { {-1}, {-1} }, /*a4*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {0xe0, 0x2a, -1}, {0xe0, 0xaa, -1} }, { {-1}, {-1} }, /*a8*/
- { {0xe0, 0x2c, -1}, {0xe0, 0xac, -1} }, { {0xe0, 0x2d, -1}, {0xe0, 0xad, -1} }, { {0xe0, 0x2e, -1}, {0xe0, 0xae, -1} }, { {0xe0, 0x2f, -1}, {0xe0, 0xaf, -1} }, /*ac*/
- { {0xe0, 0x30, -1}, {0xe0, 0xb0, -1} }, { {0xe0, 0x31, -1}, {0xe0, 0xb1, -1} }, { {0xe0, 0x32, -1}, {0xe0, 0xb2, -1} }, { {-1}, {-1} }, /*b0*/
- { {0xe0, 0x34, -1}, {0xe0, 0xb4, -1} }, { {0xe0, 0x35, -1}, {0xe0, 0xb5, -1} }, { {0xe0, 0x36, -1}, {0xe0, 0xb6, -1} }, { {0xe0, 0x37, -1}, {0xe0, 0xb7, -1} }, /*b4*/
- { {0xe0, 0x38, -1}, {0xe0, 0xb8, -1} }, { {-1}, {-1} }, { {0xe0, 0x3a, -1}, {0xe0, 0xba, -1} }, { {0xe0, 0x3b, -1}, {0xe0, 0xbb, -1} }, /*b8*/
- { {0xe0, 0x3c, -1}, {0xe0, 0xbc, -1} }, { {0xe0, 0x3d, -1}, {0xe0, 0xbd, -1} }, { {0xe0, 0x3e, -1}, {0xe0, 0xbe, -1} }, { {0xe0, 0x3f, -1}, {0xe0, 0xbf, -1} }, /*bc*/
- { {0xe0, 0x40, -1}, {0xe0, 0xc0, -1} }, { {0xe0, 0x41, -1}, {0xe0, 0xc1, -1} }, { {0xe0, 0x42, -1}, {0xe0, 0xc2, -1} }, { {0xe0, 0x43, -1}, {0xe0, 0xc3, -1} }, /*c0*/
- { {0xe0, 0x44, -1}, {0xe0, 0xc4, -1} }, { {-1}, {-1} }, { {0xe0, 0x46, -1}, {0xe0, 0xc6, -1} }, { {0xe0, 0x47, -1}, {0xe0, 0xc7, -1} }, /*c4*/
- { {0xe0, 0x48, -1}, {0xe0, 0xc8, -1} }, { {0xe0, 0x49, -1}, {0xe0, 0xc9, -1} }, { {-1}, {-1} }, { {0xe0, 0x4b, -1}, {0xe0, 0xcb, -1} }, /*c8*/
- { {0xe0, 0x4c, -1}, {0xe0, 0xcc, -1} }, { {0xe0, 0x4d, -1}, {0xe0, 0xcd, -1} }, { {0xe0, 0x4e, -1}, {0xe0, 0xce, -1} }, { {0xe0, 0x4f, -1}, {0xe0, 0xcf, -1} }, /*cc*/
- { {0xe0, 0x50, -1}, {0xe0, 0xd0, -1} }, { {0xe0, 0x51, -1}, {0xe0, 0xd1, -1} }, { {0xe0, 0x52, -1}, {0xe0, 0xd2, -1} }, { {0xe0, 0x53, -1}, {0xe0, 0xd3, -1} }, /*d0*/
- { {0xd4, -1}, {-1} }, { {0xe0, 0x55, -1}, {0xe0, 0xd5, -1} }, { {-1}, {-1} }, { {0xe0, 0x57, -1}, {0xe0, 0xd7, -1} }, /*d4*/
- { {0xe0, 0x58, -1}, {0xe0, 0xd8, -1} }, { {0xe0, 0x59, -1}, {0xe0, 0xd9, -1} }, { {0xe0, 0x5a, -1}, {0xe0, 0xaa, -1} }, { {0xe0, 0x5b, -1}, {0xe0, 0xdb, -1} }, /*d8*/
- { {0xe0, 0x5c, -1}, {0xe0, 0xdc, -1} }, { {0xe0, 0x5d, -1}, {0xe0, 0xdd, -1} }, { {0xe0, 0x5e, -1}, {0xe0, 0xee, -1} }, { {0xe0, 0x5f, -1}, {0xe0, 0xdf, -1} }, /*dc*/
- { {-1}, {-1} }, { {0xe0, 0x61, -1}, {0xe0, 0xe1, -1} }, { {0xe0, 0x62, -1}, {0xe0, 0xe2, -1} }, { {0xe0, 0x63, -1}, {0xe0, 0xe3, -1} }, /*e0*/
- { {0xe0, 0x64, -1}, {0xe0, 0xe4, -1} }, { {0xe0, 0x65, -1}, {0xe0, 0xe5, -1} }, { {0xe0, 0x66, -1}, {0xe0, 0xe6, -1} }, { {0xe0, 0x67, -1}, {0xe0, 0xe7, -1} }, /*e4*/
- { {0xe0, 0x68, -1}, {0xe0, 0xe8, -1} }, { {0xe0, 0x69, -1}, {0xe0, 0xe9, -1} }, { {0xe0, 0x6a, -1}, {0xe0, 0xea, -1} }, { {0xe0, 0x6b, -1}, {0xe0, 0xeb, -1} }, /*e8*/
- { {0xe0, 0x6c, -1}, {0xe0, 0xec, -1} }, { {0xe0, 0x6d, -1}, {0xe0, 0xed, -1} }, { {0xe0, 0x6e, -1}, {0xe0, 0xee, -1} }, { {-1}, {-1} }, /*ec*/
- { {0xe0, 0x70, -1}, {0xe0, 0xf0, -1} }, { {0xf1, -1}, {-1} }, { {0xf2, -1}, {-1} }, { {0xe0, 0x73, -1}, {0xe0, 0xf3, -1} }, /*f0*/
- { {0xe0, 0x74, -1}, {0xe0, 0xf4, -1} }, { {0xe0, 0x75, -1}, {0xe0, 0xf5, -1} }, { {-1}, {-1} }, { {0xe0, 0x77, -1}, {0xe0, 0xf7, -1} }, /*f4*/
- { {0xe0, 0x78, -1}, {0xe0, 0xf8, -1} }, { {0xe0, 0x79, -1}, {0xe0, 0xf9, -1} }, { {0xe0, 0x7a, -1}, {0xe0, 0xfa, -1} }, { {0xe0, 0x7b, -1}, {0xe0, 0xfb, -1} }, /*f8*/
- { {0xe0, 0x7c, -1}, {0xe0, 0xfc, -1} }, { {0xe0, 0x7d, -1}, {0xe0, 0xfd, -1} }, { {0xe0, 0x7e, -1}, {0xe0, 0xfe, -1} }, { {0xe1, 0x1d, 0x45, 0xe1, 0x9d, 0xc5, -1}, {-1} }, /*fc*/
- { {-1}, {-1} }, { {0xe0, 0x01, -1}, {0xe0, 0x81, -1} }, { {0xe0, 0x02, -1}, {0xe0, 0x82, -1} }, { {-1}, {-1} }, /*100*/
- { {-1}, {-1} }, { {0xe0, 0x05, -1}, {0xe0, 0x85, -1} }, { {0xe0, 0x06, -1}, {0xe0, 0x86, -1} }, { {0xe0, 0x07, -1}, {0xe0, 0x87, -1} }, /*104*/
- { {0xe0, 0x71, -1}, {0xe0, 0xf1, -1} }, { {0xe0, 0x72, -1}, {0xe0, 0xf2, -1} }, { {0xe0, 0x7f, -1}, {0xe0, 0xff, -1} }, { {0xe0, 0xe1, -1}, {-1} }, /*108*/
- { {0xe0, 0xee, -1}, {-1} }, { {0xe0, 0xf1, -1}, {-1} }, { {0xe0, 0xfe, -1}, {-1} }, { {0xe0, 0xff, -1}, {-1} } /*10c*/
+ { {0x80, 0}, {0} }, { {0x81, 0}, {0} }, { {0x82, 0}, {0} }, { {0xe0, 0x03, 0}, {0xe0, 0x83, 0} }, /*80*/
+ { {0xe0, 0x04, 0}, {0xe0, 0x84, 0} }, { {0x85, 0}, {0} }, { {0x86, 0}, {0} }, { {0x87, 0}, {0} }, /*84*/
+ { {0xe0, 0x08, 0}, {0xe0, 0x88, 0} }, { {0xe0, 0x09, 0}, {0xe0, 0x89, 0} }, { {0xe0, 0x0a, 0}, {0xe0, 0x8a, 0} }, { {0xe0, 0x0b, 0}, {0xe0, 0x8b, 0} }, /*88*/
+ { {0xe0, 0x0c, 0}, {0xe0, 0x8c, 0} }, { {0}, {0} }, { {0xe0, 0x0e, 0}, {0xe0, 0x8e, 0} }, { {0xe0, 0x0f, 0}, {0xe0, 0x8f, 0} }, /*8c*/
+ { {0xe0, 0x10, 0}, {0xe0, 0x90, 0} }, { {0xe0, 0x11, 0}, {0xe0, 0x91, 0} }, { {0xe0, 0x12, 0}, {0xe0, 0x92, 0} }, { {0xe0, 0x13, 0}, {0xe0, 0x93, 0} }, /*90*/
+ { {0xe0, 0x14, 0}, {0xe0, 0x94, 0} }, { {0xe0, 0x15, 0}, {0xe0, 0x95, 0} }, { {0xe0, 0x16, 0}, {0xe0, 0x96, 0} }, { {0xe0, 0x17, 0}, {0xe0, 0x97, 0} }, /*94*/
+ { {0xe0, 0x18, 0}, {0xe0, 0x98, 0} }, { {0xe0, 0x19, 0}, {0xe0, 0x99, 0} }, { {0xe0, 0x1a, 0}, {0xe0, 0x9a, 0} }, { {0xe0, 0x1b, 0}, {0xe0, 0x9b, 0} }, /*98*/
+ { {0xe0, 0x1c, 0}, {0xe0, 0x9c, 0} }, { {0xe0, 0x1d, 0}, {0xe0, 0x9d, 0} }, { {0xe0, 0x1e, 0}, {0xe0, 0x9e, 0} }, { {0xe0, 0x1f, 0}, {0xe0, 0x9f, 0} }, /*9c*/
+ { {0xe0, 0x20, 0}, {0xe0, 0xa0, 0} }, { {0xe0, 0x21, 0}, {0xe0, 0xa1, 0} }, { {0xe0, 0x22, 0}, {0xe0, 0xa2, 0} }, { {0xe0, 0x23, 0}, {0xe0, 0xa3, 0} }, /*a0*/
+ { {0xe0, 0x24, 0}, {0xe0, 0xa4, 0} }, { {0xe0, 0x25, 0}, {0xe0, 0xa5, 0} }, { {0xe0, 0x26, 0}, {0xe0, 0xa6, 0} }, { {0}, {0} }, /*a4*/
+ { {0}, {0} }, { {0}, {0} }, { {0xe0, 0x2a, 0}, {0xe0, 0xaa, 0} }, { {0}, {0} }, /*a8*/
+ { {0xe0, 0x2c, 0}, {0xe0, 0xac, 0} }, { {0xe0, 0x2d, 0}, {0xe0, 0xad, 0} }, { {0xe0, 0x2e, 0}, {0xe0, 0xae, 0} }, { {0xe0, 0x2f, 0}, {0xe0, 0xaf, 0} }, /*ac*/
+ { {0xe0, 0x30, 0}, {0xe0, 0xb0, 0} }, { {0xe0, 0x31, 0}, {0xe0, 0xb1, 0} }, { {0xe0, 0x32, 0}, {0xe0, 0xb2, 0} }, { {0}, {0} }, /*b0*/
+ { {0xe0, 0x34, 0}, {0xe0, 0xb4, 0} }, { {0xe0, 0x35, 0}, {0xe0, 0xb5, 0} }, { {0xe0, 0x36, 0}, {0xe0, 0xb6, 0} }, { {0xe0, 0x37, 0}, {0xe0, 0xb7, 0} }, /*b4*/
+ { {0xe0, 0x38, 0}, {0xe0, 0xb8, 0} }, { {0}, {0} }, { {0xe0, 0x3a, 0}, {0xe0, 0xba, 0} }, { {0xe0, 0x3b, 0}, {0xe0, 0xbb, 0} }, /*b8*/
+ { {0xe0, 0x3c, 0}, {0xe0, 0xbc, 0} }, { {0xe0, 0x3d, 0}, {0xe0, 0xbd, 0} }, { {0xe0, 0x3e, 0}, {0xe0, 0xbe, 0} }, { {0xe0, 0x3f, 0}, {0xe0, 0xbf, 0} }, /*bc*/
+ { {0xe0, 0x40, 0}, {0xe0, 0xc0, 0} }, { {0xe0, 0x41, 0}, {0xe0, 0xc1, 0} }, { {0xe0, 0x42, 0}, {0xe0, 0xc2, 0} }, { {0xe0, 0x43, 0}, {0xe0, 0xc3, 0} }, /*c0*/
+ { {0xe0, 0x44, 0}, {0xe0, 0xc4, 0} }, { {0}, {0} }, { {0xe0, 0x46, 0}, {0xe0, 0xc6, 0} }, { {0xe0, 0x47, 0}, {0xe0, 0xc7, 0} }, /*c4*/
+ { {0xe0, 0x48, 0}, {0xe0, 0xc8, 0} }, { {0xe0, 0x49, 0}, {0xe0, 0xc9, 0} }, { {0}, {0} }, { {0xe0, 0x4b, 0}, {0xe0, 0xcb, 0} }, /*c8*/
+ { {0xe0, 0x4c, 0}, {0xe0, 0xcc, 0} }, { {0xe0, 0x4d, 0}, {0xe0, 0xcd, 0} }, { {0xe0, 0x4e, 0}, {0xe0, 0xce, 0} }, { {0xe0, 0x4f, 0}, {0xe0, 0xcf, 0} }, /*cc*/
+ { {0xe0, 0x50, 0}, {0xe0, 0xd0, 0} }, { {0xe0, 0x51, 0}, {0xe0, 0xd1, 0} }, { {0xe0, 0x52, 0}, {0xe0, 0xd2, 0} }, { {0xe0, 0x53, 0}, {0xe0, 0xd3, 0} }, /*d0*/
+ { {0xd4, 0}, {0} }, { {0xe0, 0x55, 0}, {0xe0, 0xd5, 0} }, { {0}, {0} }, { {0xe0, 0x57, 0}, {0xe0, 0xd7, 0} }, /*d4*/
+ { {0xe0, 0x58, 0}, {0xe0, 0xd8, 0} }, { {0xe0, 0x59, 0}, {0xe0, 0xd9, 0} }, { {0xe0, 0x5a, 0}, {0xe0, 0xaa, 0} }, { {0xe0, 0x5b, 0}, {0xe0, 0xdb, 0} }, /*d8*/
+ { {0xe0, 0x5c, 0}, {0xe0, 0xdc, 0} }, { {0xe0, 0x5d, 0}, {0xe0, 0xdd, 0} }, { {0xe0, 0x5e, 0}, {0xe0, 0xee, 0} }, { {0xe0, 0x5f, 0}, {0xe0, 0xdf, 0} }, /*dc*/
+ { {0}, {0} }, { {0xe0, 0x61, 0}, {0xe0, 0xe1, 0} }, { {0xe0, 0x62, 0}, {0xe0, 0xe2, 0} }, { {0xe0, 0x63, 0}, {0xe0, 0xe3, 0} }, /*e0*/
+ { {0xe0, 0x64, 0}, {0xe0, 0xe4, 0} }, { {0xe0, 0x65, 0}, {0xe0, 0xe5, 0} }, { {0xe0, 0x66, 0}, {0xe0, 0xe6, 0} }, { {0xe0, 0x67, 0}, {0xe0, 0xe7, 0} }, /*e4*/
+ { {0xe0, 0x68, 0}, {0xe0, 0xe8, 0} }, { {0xe0, 0x69, 0}, {0xe0, 0xe9, 0} }, { {0xe0, 0x6a, 0}, {0xe0, 0xea, 0} }, { {0xe0, 0x6b, 0}, {0xe0, 0xeb, 0} }, /*e8*/
+ { {0xe0, 0x6c, 0}, {0xe0, 0xec, 0} }, { {0xe0, 0x6d, 0}, {0xe0, 0xed, 0} }, { {0xe0, 0x6e, 0}, {0xe0, 0xee, 0} }, { {0}, {0} }, /*ec*/
+ { {0xe0, 0x70, 0}, {0xe0, 0xf0, 0} }, { {0xf1, 0}, {0} }, { {0xf2, 0}, {0} }, { {0xe0, 0x73, 0}, {0xe0, 0xf3, 0} }, /*f0*/
+ { {0xe0, 0x74, 0}, {0xe0, 0xf4, 0} }, { {0xe0, 0x75, 0}, {0xe0, 0xf5, 0} }, { {0}, {0} }, { {0xe0, 0x77, 0}, {0xe0, 0xf7, 0} }, /*f4*/
+ { {0xe0, 0x78, 0}, {0xe0, 0xf8, 0} }, { {0xe0, 0x79, 0}, {0xe0, 0xf9, 0} }, { {0xe0, 0x7a, 0}, {0xe0, 0xfa, 0} }, { {0xe0, 0x7b, 0}, {0xe0, 0xfb, 0} }, /*f8*/
+ { {0xe0, 0x7c, 0}, {0xe0, 0xfc, 0} }, { {0xe0, 0x7d, 0}, {0xe0, 0xfd, 0} }, { {0xe0, 0x7e, 0}, {0xe0, 0xfe, 0} }, { {0xe1, 0x1d, 0x45, 0xe1, 0x9d, 0xc5, 0}, {0} }, /*fc*/
+ { {0}, {0} }, { {0xe0, 0x01, 0}, {0xe0, 0x81, 0} }, { {0xe0, 0x02, 0}, {0xe0, 0x82, 0} }, { {0}, {0} }, /*100*/
+ { {0}, {0} }, { {0xe0, 0x05, 0}, {0xe0, 0x85, 0} }, { {0xe0, 0x06, 0}, {0xe0, 0x86, 0} }, { {0xe0, 0x07, 0}, {0xe0, 0x87, 0} }, /*104*/
+ { {0xe0, 0x71, 0}, {0xe0, 0xf1, 0} }, { {0xe0, 0x72, 0}, {0xe0, 0xf2, 0} }, { {0xe0, 0x7f, 0}, {0xe0, 0xff, 0} }, { {0xe0, 0xe1, 0}, {0} }, /*108*/
+ { {0xe0, 0xee, 0}, {0} }, { {0xe0, 0xf1, 0}, {0} }, { {0xe0, 0xfe, 0}, {0} }, { {0xe0, 0xff, 0}, {0} } /*10c*/
+};
+
+/*272 = 256 + 16 fake interim scancodes for disambiguation purposes.*/
+static scancode scancode_set2[272] =
+{
+ { {0}, {0} }, { {0x76, 0}, {0xf0, 0x76, 0} }, { {0x16, 0}, {0xf0, 0x16, 0} }, { {0x1e, 0}, {0xf0, 0x1e, 0} },
+ { {0x26, 0}, {0xf0, 0x26, 0} }, { {0x25, 0}, {0xf0, 0x25, 0} }, { {0x2e, 0}, {0xf0, 0x2e, 0} }, { {0x36, 0}, {0xf0, 0x36, 0} },
+ { {0x3d, 0}, {0xf0, 0x3d, 0} }, { {0x3e, 0}, {0xf0, 0x3e, 0} }, { {0x46, 0}, {0xf0, 0x46, 0} }, { {0x45, 0}, {0xf0, 0x45, 0} },
+ { {0x4e, 0}, {0xf0, 0x4e, 0} }, { {0x55, 0}, {0xf0, 0x55, 0} }, { {0x66, 0}, {0xf0, 0x66, 0} }, { {0x0d, 0}, {0xf0, 0x0d, 0} },
+ { {0x15, 0}, {0xf0, 0x15, 0} }, { {0x1d, 0}, {0xf0, 0x1d, 0} }, { {0x24, 0}, {0xf0, 0x24, 0} }, { {0x2d, 0}, {0xf0, 0x2d, 0} },
+ { {0x2c, 0}, {0xf0, 0x2c, 0} }, { {0x35, 0}, {0xf0, 0x35, 0} }, { {0x3c, 0}, {0xf0, 0x3c, 0} }, { {0x43, 0}, {0xf0, 0x43, 0} },
+ { {0x44, 0}, {0xf0, 0x44, 0} }, { {0x4d, 0}, {0xf0, 0x4d, 0} }, { {0x54, 0}, {0xf0, 0x54, 0} }, { {0x5b, 0}, {0xf0, 0x5b, 0} },
+ { {0x5a, 0}, {0xf0, 0x5a, 0} }, { {0x14, 0}, {0xf0, 0x14, 0} }, { {0x1c, 0}, {0xf0, 0x1c, 0} }, { {0x1b, 0}, {0xf0, 0x1b, 0} },
+ { {0x23, 0}, {0xf0, 0x23, 0} }, { {0x2b, 0}, {0xf0, 0x2b, 0} }, { {0x34, 0}, {0xf0, 0x34, 0} }, { {0x33, 0}, {0xf0, 0x33, 0} },
+ { {0x3b, 0}, {0xf0, 0x3b, 0} }, { {0x42, 0}, {0xf0, 0x42, 0} }, { {0x4b, 0}, {0xf0, 0x4b, 0} }, { {0x4c, 0}, {0xf0, 0x4c, 0} },
+ { {0x52, 0}, {0xf0, 0x52, 0} }, { {0x0e, 0}, {0xf0, 0x0e, 0} }, { {0x12, 0}, {0xf0, 0x12, 0} }, { {0x5d, 0}, {0xf0, 0x5d, 0} },
+ { {0x1a, 0}, {0xf0, 0x1a, 0} }, { {0x22, 0}, {0xf0, 0x22, 0} }, { {0x21, 0}, {0xf0, 0x21, 0} }, { {0x2a, 0}, {0xf0, 0x2a, 0} },
+ { {0x32, 0}, {0xf0, 0x32, 0} }, { {0x31, 0}, {0xf0, 0x31, 0} }, { {0x3a, 0}, {0xf0, 0x3a, 0} }, { {0x41, 0}, {0xf0, 0x41, 0} },
+ { {0x49, 0}, {0xf0, 0x49, 0} }, { {0x4a, 0}, {0xf0, 0x4a, 0} }, { {0x59, 0}, {0xf0, 0x59, 0} }, { {0x7c, 0}, {0xf0, 0x7c, 0} },
+ { {0x11, 0}, {0xf0, 0x11, 0} }, { {0x29, 0}, {0xf0, 0x29, 0} }, { {0x58, 0}, {0xf0, 0x58, 0} }, { {0x05, 0}, {0xf0, 0x05, 0} },
+ { {0x06, 0}, {0xf0, 0x06, 0} }, { {0x04, 0}, {0xf0, 0x04, 0} }, { {0x0c, 0}, {0xf0, 0x0c, 0} }, { {0x03, 0}, {0xf0, 0x03, 0} },
+ { {0x0b, 0}, {0xf0, 0x0b, 0} }, { {0x83, 0}, {0xf0, 0x83, 0} }, { {0x0a, 0}, {0xf0, 0x0a, 0} }, { {0x01, 0}, {0xf0, 0x01, 0} },
+ { {0x09, 0}, {0xf0, 0x09, 0} }, { {0x77, 0}, {0xf0, 0x77, 0} }, { {0x7e, 0}, {0xf0, 0x7e, 0} }, { {0x6c, 0}, {0xf0, 0x6c, 0} },
+ { {0x75, 0}, {0xf0, 0x75, 0} }, { {0x7d, 0}, {0xf0, 0x7d, 0} }, { {0x7b, 0}, {0xf0, 0x7b, 0} }, { {0x6b, 0}, {0xf0, 0x6b, 0} },
+ { {0x73, 0}, {0xf0, 0x73, 0} }, { {0x74, 0}, {0xf0, 0x74, 0} }, { {0x79, 0}, {0xf0, 0x79, 0} }, { {0x69, 0}, {0xf0, 0x69, 0} },
+ { {0x72, 0}, {0xf0, 0x72, 0} }, { {0x7a, 0}, {0xf0, 0x7a, 0} }, { {0x70, 0}, {0xf0, 0x70, 0} }, { {0x71, 0}, {0xf0, 0x71, 0} },
+ { {0x84, 0}, {0xf0, 0x84, 0} }, { {0, 0}, {0, 0} }, { {0x61, 0}, {0xf0, 0x61, 0} }, { {0x78, 0}, {0xf0, 0x78, 0} },
+ { {0x07, 0}, {0xf0, 0x07, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0xe0, 0x5a, 0}, {0xe0, 0xf0, 0x5a, 0} }, { {0xe0, 0x14, 0}, {0xe0, 0xf0, 0x14, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0xe0, 0x4a, 0}, {0xe0, 0xf0, 0x4a, 0} }, { {0, 0}, {0, 0} }, { {0xe0, 0x7c, 0}, {0xe0, 0xf0, 0x7c, 0} },
+ { {0xe0, 0x11, 0}, {0xe0, 0xf0, 0x11, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0xe0, 0x6c, 0}, {0xe0, 0xf0, 0x6c, 0} },
+ { {0xe0, 0x75, 0}, {0xe0, 0xf0, 0x75, 0} }, { {0xe0, 0x7d, 0}, {0xe0, 0xf0, 0x7d, 0} }, { {0, 0}, {0, 0} }, { {0xe0, 0x6b, 0}, {0xe0, 0xf0, 0x6b, 0} },
+ { {0, 0}, {0, 0} }, { {0xe0, 0x74, 0}, {0xe0, 0xf0, 0x74, 0} }, { {0, 0}, {0, 0} }, { {0xe0, 0x69, 0}, {0xe0, 0xf0, 0x69, 0} },
+ { {0xe0, 0x72, 0}, {0xe0, 0xf0, 0x72, 0} }, { {0xe0, 0x7a, 0}, {0xe0, 0xf0, 0x7a, 0} }, { {0xe0, 0x70, 0}, {0xe0, 0xf0, 0x70, 0} }, { {0xe0, 0x71, 0}, {0xe0, 0xf0, 0x71, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0xe0, 0x1f, 0}, {0xe0, 0xf0, 0x1f, 0} },
+ { {0xe0, 0x27, 0}, {0xe0, 0xf0, 0x27, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+
+ { {0}, {0} }, { {0xe0, 0x01, 0}, {0xe0, 0xf0, 0x01, 0} }, { {0xe0, 0x02, 0}, {0xe0, 0xf0, 0x02, 0} }, { {0}, {0} }, /*100*/
+ { {0}, {0} }, { {0xe0, 0x05, 0}, {0xe0, 0xf0, 0x15, 0} }, { {0xe0, 0x06, 0}, {0xe0, 0xf0, 0x06, 0} }, { {0xe0, 0x07, 0}, {0xe0, 0xf0, 0x07, 0} }, /*104*/
+ { {0xe0, 0x71, 0}, {0xe0, 0xf0, 0x71, 0} }, { {0xe0, 0x72, 0}, {0xe0, 0xf0, 0x72, 0} }, { {0xe0, 0x7f, 0}, {0xe0, 0xf0, 0x7f, 0} }, { {0xe0, 0xe1, 0}, {0} }, /*108*/
+ { {0xe0, 0xee, 0}, {0} }, { {0xe0, 0xf1, 0}, {0} }, { {0xe0, 0xfe, 0}, {0} }, { {0xe0, 0xff, 0}, {0} } /*10c*/
+};
+
+/*272 = 256 + 16 fake interim scancodes for disambiguation purposes.*/
+static scancode scancode_set3[272] =
+{
+ { {0}, {0} }, { {0x76, 0}, {0xf0, 0x76, 0} }, { {0x16, 0}, {0xf0, 0x16, 0} }, { {0x1e, 0}, {0xf0, 0x1e, 0} },
+ { {0x26, 0}, {0xf0, 0x26, 0} }, { {0x25, 0}, {0xf0, 0x25, 0} }, { {0x2e, 0}, {0xf0, 0x2e, 0} }, { {0x36, 0}, {0xf0, 0x36, 0} },
+ { {0x3d, 0}, {0xf0, 0x3d, 0} }, { {0x3e, 0}, {0xf0, 0x3e, 0} }, { {0x46, 0}, {0xf0, 0x46, 0} }, { {0x45, 0}, {0xf0, 0x45, 0} },
+ { {0x4e, 0}, {0xf0, 0x4e, 0} }, { {0x55, 0}, {0xf0, 0x55, 0} }, { {0x66, 0}, {0xf0, 0x66, 0} }, { {0x0d, 0}, {0xf0, 0x0d, 0} },
+ { {0x15, 0}, {0xf0, 0x15, 0} }, { {0x1d, 0}, {0xf0, 0x1d, 0} }, { {0x24, 0}, {0xf0, 0x24, 0} }, { {0x2d, 0}, {0xf0, 0x2d, 0} },
+ { {0x2c, 0}, {0xf0, 0x2c, 0} }, { {0x35, 0}, {0xf0, 0x35, 0} }, { {0x3c, 0}, {0xf0, 0x3c, 0} }, { {0x43, 0}, {0xf0, 0x43, 0} },
+ { {0x44, 0}, {0xf0, 0x44, 0} }, { {0x4d, 0}, {0xf0, 0x4d, 0} }, { {0x54, 0}, {0xf0, 0x54, 0} }, { {0x5b, 0}, {0xf0, 0x5b, 0} },
+ { {0x5a, 0}, {0xf0, 0x5a, 0} }, { {0x19, 0}, {0xf0, 0x19, 0} }, { {0x1c, 0}, {0xf0, 0x1c, 0} }, { {0x1b, 0}, {0xf0, 0x1b, 0} },
+ { {0x23, 0}, {0xf0, 0x23, 0} }, { {0x2b, 0}, {0xf0, 0x2b, 0} }, { {0x34, 0}, {0xf0, 0x34, 0} }, { {0x33, 0}, {0xf0, 0x33, 0} },
+ { {0x3b, 0}, {0xf0, 0x3b, 0} }, { {0x42, 0}, {0xf0, 0x42, 0} }, { {0x4b, 0}, {0xf0, 0x4b, 0} }, { {0x4c, 0}, {0xf0, 0x4c, 0} },
+ { {0x52, 0}, {0xf0, 0x52, 0} }, { {0x0e, 0}, {0xf0, 0x0e, 0} }, { {0x12, 0}, {0xf0, 0x12, 0} }, { {0x5c, 0}, {0xf0, 0x5c, 0} },
+ { {0x1a, 0}, {0xf0, 0x1a, 0} }, { {0x22, 0}, {0xf0, 0x22, 0} }, { {0x21, 0}, {0xf0, 0x21, 0} }, { {0x2a, 0}, {0xf0, 0x2a, 0} },
+ { {0x32, 0}, {0xf0, 0x32, 0} }, { {0x31, 0}, {0xf0, 0x31, 0} }, { {0x3a, 0}, {0xf0, 0x3a, 0} }, { {0x41, 0}, {0xf0, 0x41, 0} },
+ { {0x49, 0}, {0xf0, 0x49, 0} }, { {0x4a, 0}, {0xf0, 0x4a, 0} }, { {0x59, 0}, {0xf0, 0x59, 0} }, { {0x7c, 0}, {0xf0, 0x7c, 0} },
+ { {0x11, 0}, {0xf0, 0x11, 0} }, { {0x29, 0}, {0xf0, 0x29, 0} }, { {0x14, 0}, {0xf0, 0x14, 0} }, { {0x05, 0}, {0xf0, 0x05, 0} },
+ { {0x06, 0}, {0xf0, 0x06, 0} }, { {0x04, 0}, {0xf0, 0x04, 0} }, { {0x0c, 0}, {0xf0, 0x0c, 0} }, { {0x03, 0}, {0xf0, 0x03, 0} },
+ { {0x0b, 0}, {0xf0, 0x0b, 0} }, { {0x83, 0}, {0xf0, 0x83, 0} }, { {0x0a, 0}, {0xf0, 0x0a, 0} }, { {0x01, 0}, {0xf0, 0x01, 0} },
+ { {0x09, 0}, {0xf0, 0x09, 0} }, { {0x77, 0}, {0xf0, 0x77, 0} }, { {0x7e, 0}, {0xf0, 0x7e, 0} }, { {0x6c, 0}, {0xf0, 0x6c, 0} },
+ { {0x75, 0}, {0xf0, 0x75, 0} }, { {0x7d, 0}, {0xf0, 0x7d, 0} }, { {0x7b, 0}, {0xf0, 0x7b, 0} }, { {0x6b, 0}, {0xf0, 0x6b, 0} },
+ { {0x73, 0}, {0xf0, 0x73, 0} }, { {0x74, 0}, {0xf0, 0x74, 0} }, { {0x79, 0}, {0xf0, 0x79, 0} }, { {0x69, 0}, {0xf0, 0x69, 0} },
+ { {0x72, 0}, {0xf0, 0x72, 0} }, { {0x7a, 0}, {0xf0, 0x7a, 0} }, { {0x70, 0}, {0xf0, 0x70, 0} }, { {0x71, 0}, {0xf0, 0x71, 0} },
+ { {0x84, 0}, {0xf0, 0x84, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0x78, 0}, {0xf0, 0x78, 0} },
+ { {0x07, 0}, {0xf0, 0x07, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0x79, 0}, {0xf0, 0x79, 0} }, { {0x58, 0}, {0xf0, 0x58, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0x77, 0}, {0xf0, 0x77, 0} }, { {0, 0}, {0, 0} }, { {0x57, 0}, {0xf0, 0x57, 0} },
+ { {0x39, 0}, {0xf0, 0x39, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0x6e, 0}, {0xf0, 0x6e, 0} },
+ { {0x63, 0}, {0xf0, 0x63, 0} }, { {0x6f, 0}, {0xf0, 0x6f, 0} }, { {0, 0}, {0, 0} }, { {0x61, 0}, {0xf0, 0x61, 0} },
+ { {0, 0}, {0, 0} }, { {0x6a, 0}, {0xf0, 0x6a, 0} }, { {0, 0}, {0, 0} }, { {0x65, 0}, {0xf0, 0x65, 0} },
+ { {0x60, 0}, {0xf0, 0x60, 0} }, { {0x6d, 0}, {0xf0, 0x6d, 0} }, { {0x67, 0}, {0xf0, 0x67, 0} }, { {0x64, 0}, {0xf0, 0x64, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0x8b, 0}, {0xf0, 0x8b, 0} },
+ { {0x8c, 0}, {0xf0, 0x8c, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
+ { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} }, { {0, 0}, {0, 0} },
};
/*XT keyboard has no escape scancodes, and no scancodes beyond 53*/
static scancode scancode_xt[272] =
{
- { {-1}, {-1} }, { {0x01, -1}, {0x81, -1} }, { {0x02, -1}, {0x82, -1} }, { {0x03, -1}, {0x83, -1} },
- { {0x04, -1}, {0x84, -1} }, { {0x05, -1}, {0x85, -1} }, { {0x06, -1}, {0x86, -1} }, { {0x07, -1}, {0x87, -1} },
- { {0x08, -1}, {0x88, -1} }, { {0x09, -1}, {0x89, -1} }, { {0x0a, -1}, {0x8a, -1} }, { {0x0b, -1}, {0x8b, -1} },
- { {0x0c, -1}, {0x8c, -1} }, { {0x0d, -1}, {0x8d, -1} }, { {0x0e, -1}, {0x8e, -1} }, { {0x0f, -1}, {0x8f, -1} },
- { {0x10, -1}, {0x90, -1} }, { {0x11, -1}, {0x91, -1} }, { {0x12, -1}, {0x92, -1} }, { {0x13, -1}, {0x93, -1} },
- { {0x14, -1}, {0x94, -1} }, { {0x15, -1}, {0x95, -1} }, { {0x16, -1}, {0x96, -1} }, { {0x17, -1}, {0x97, -1} },
- { {0x18, -1}, {0x98, -1} }, { {0x19, -1}, {0x99, -1} }, { {0x1a, -1}, {0x9a, -1} }, { {0x1b, -1}, {0x9b, -1} },
- { {0x1c, -1}, {0x9c, -1} }, { {0x1d, -1}, {0x9d, -1} }, { {0x1e, -1}, {0x9e, -1} }, { {0x1f, -1}, {0x9f, -1} },
- { {0x20, -1}, {0xa0, -1} }, { {0x21, -1}, {0xa1, -1} }, { {0x22, -1}, {0xa2, -1} }, { {0x23, -1}, {0xa3, -1} },
- { {0x24, -1}, {0xa4, -1} }, { {0x25, -1}, {0xa5, -1} }, { {0x26, -1}, {0xa6, -1} }, { {0x27, -1}, {0xa7, -1} },
- { {0x28, -1}, {0xa8, -1} }, { {0x29, -1}, {0xa9, -1} }, { {0x2a, -1}, {0xaa, -1} }, { {0x2b, -1}, {0xab, -1} },
- { {0x2c, -1}, {0xac, -1} }, { {0x2d, -1}, {0xad, -1} }, { {0x2e, -1}, {0xae, -1} }, { {0x2f, -1}, {0xaf, -1} },
- { {0x30, -1}, {0xb0, -1} }, { {0x31, -1}, {0xb1, -1} }, { {0x32, -1}, {0xb2, -1} }, { {0x33, -1}, {0xb3, -1} },
- { {0x34, -1}, {0xb4, -1} }, { {0x35, -1}, {0xb5, -1} }, { {0x36, -1}, {0xb6, -1} }, { {0x37, -1}, {0xb7, -1} },
- { {0x38, -1}, {0xb8, -1} }, { {0x39, -1}, {0xb9, -1} }, { {0x3a, -1}, {0xba, -1} }, { {0x3b, -1}, {0xbb, -1} },
- { {0x3c, -1}, {0xbc, -1} }, { {0x3d, -1}, {0xbd, -1} }, { {0x3e, -1}, {0xbe, -1} }, { {0x3f, -1}, {0xbf, -1} },
- { {0x40, -1}, {0xc0, -1} }, { {0x41, -1}, {0xc1, -1} }, { {0x42, -1}, {0xc2, -1} }, { {0x43, -1}, {0xc3, -1} },
- { {0x44, -1}, {0xc4, -1} }, { {0x45, -1}, {0xc5, -1} }, { {0x46, -1}, {0xc6, -1} }, { {0x47, -1}, {0xc7, -1} },
- { {0x48, -1}, {0xc8, -1} }, { {0x49, -1}, {0xc9, -1} }, { {0x4a, -1}, {0xca, -1} }, { {0x4b, -1}, {0xcb, -1} },
- { {0x4c, -1}, {0xcc, -1} }, { {0x4d, -1}, {0xcd, -1} }, { {0x4e, -1}, {0xce, -1} }, { {0x4f, -1}, {0xcf, -1} },
- { {0x50, -1}, {0xd0, -1} }, { {0x51, -1}, {0xd1, -1} }, { {0x52, -1}, {0xd2, -1} }, { {0x53, -1}, {0xd3, -1} },
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*54*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*58*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*5c*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*60*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*64*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*68*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*6c*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*70*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*74*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*78*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*7c*/
+ { {0}, {0} }, { {0x01, 0}, {0x81, 0} }, { {0x02, 0}, {0x82, 0} }, { {0x03, 0}, {0x83, 0} },
+ { {0x04, 0}, {0x84, 0} }, { {0x05, 0}, {0x85, 0} }, { {0x06, 0}, {0x86, 0} }, { {0x07, 0}, {0x87, 0} },
+ { {0x08, 0}, {0x88, 0} }, { {0x09, 0}, {0x89, 0} }, { {0x0a, 0}, {0x8a, 0} }, { {0x0b, 0}, {0x8b, 0} },
+ { {0x0c, 0}, {0x8c, 0} }, { {0x0d, 0}, {0x8d, 0} }, { {0x0e, 0}, {0x8e, 0} }, { {0x0f, 0}, {0x8f, 0} },
+ { {0x10, 0}, {0x90, 0} }, { {0x11, 0}, {0x91, 0} }, { {0x12, 0}, {0x92, 0} }, { {0x13, 0}, {0x93, 0} },
+ { {0x14, 0}, {0x94, 0} }, { {0x15, 0}, {0x95, 0} }, { {0x16, 0}, {0x96, 0} }, { {0x17, 0}, {0x97, 0} },
+ { {0x18, 0}, {0x98, 0} }, { {0x19, 0}, {0x99, 0} }, { {0x1a, 0}, {0x9a, 0} }, { {0x1b, 0}, {0x9b, 0} },
+ { {0x1c, 0}, {0x9c, 0} }, { {0x1d, 0}, {0x9d, 0} }, { {0x1e, 0}, {0x9e, 0} }, { {0x1f, 0}, {0x9f, 0} },
+ { {0x20, 0}, {0xa0, 0} }, { {0x21, 0}, {0xa1, 0} }, { {0x22, 0}, {0xa2, 0} }, { {0x23, 0}, {0xa3, 0} },
+ { {0x24, 0}, {0xa4, 0} }, { {0x25, 0}, {0xa5, 0} }, { {0x26, 0}, {0xa6, 0} }, { {0x27, 0}, {0xa7, 0} },
+ { {0x28, 0}, {0xa8, 0} }, { {0x29, 0}, {0xa9, 0} }, { {0x2a, 0}, {0xaa, 0} }, { {0x2b, 0}, {0xab, 0} },
+ { {0x2c, 0}, {0xac, 0} }, { {0x2d, 0}, {0xad, 0} }, { {0x2e, 0}, {0xae, 0} }, { {0x2f, 0}, {0xaf, 0} },
+ { {0x30, 0}, {0xb0, 0} }, { {0x31, 0}, {0xb1, 0} }, { {0x32, 0}, {0xb2, 0} }, { {0x33, 0}, {0xb3, 0} },
+ { {0x34, 0}, {0xb4, 0} }, { {0x35, 0}, {0xb5, 0} }, { {0x36, 0}, {0xb6, 0} }, { {0x37, 0}, {0xb7, 0} },
+ { {0x38, 0}, {0xb8, 0} }, { {0x39, 0}, {0xb9, 0} }, { {0x3a, 0}, {0xba, 0} }, { {0x3b, 0}, {0xbb, 0} },
+ { {0x3c, 0}, {0xbc, 0} }, { {0x3d, 0}, {0xbd, 0} }, { {0x3e, 0}, {0xbe, 0} }, { {0x3f, 0}, {0xbf, 0} },
+ { {0x40, 0}, {0xc0, 0} }, { {0x41, 0}, {0xc1, 0} }, { {0x42, 0}, {0xc2, 0} }, { {0x43, 0}, {0xc3, 0} },
+ { {0x44, 0}, {0xc4, 0} }, { {0x45, 0}, {0xc5, 0} }, { {0x46, 0}, {0xc6, 0} }, { {0x47, 0}, {0xc7, 0} },
+ { {0x48, 0}, {0xc8, 0} }, { {0x49, 0}, {0xc9, 0} }, { {0x4a, 0}, {0xca, 0} }, { {0x4b, 0}, {0xcb, 0} },
+ { {0x4c, 0}, {0xcc, 0} }, { {0x4d, 0}, {0xcd, 0} }, { {0x4e, 0}, {0xce, 0} }, { {0x4f, 0}, {0xcf, 0} },
+ { {0x50, 0}, {0xd0, 0} }, { {0x51, 0}, {0xd1, 0} }, { {0x52, 0}, {0xd2, 0} }, { {0x53, 0}, {0xd3, 0} },
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*54*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*58*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*5c*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*60*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*64*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*68*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*6c*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*70*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*74*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*78*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*7c*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*80*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*84*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*88*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*8c*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*90*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*94*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*98*/
- { {0x1c, -1}, {0x9c, -1} }, { {0x1d, -1}, {0x9d, -1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*9c*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*a0*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*a4*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {0x2a, -1}, {0xaa, -1} }, { {-1}, {-1} }, /*a8*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*ac*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*b0*/
- { {-1}, {-1} }, { {0x35, -1}, {0xb5, -1} }, { {0x36, -1}, {0xb6, -1} }, { {0x37, -1}, {0xb7, -1} }, /*b4*/
- { {0x38, -1}, {0xb8, -1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*b8*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*bc*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*c0*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {0x46, -1}, {0xc6, -1} }, { {0x47, -1}, {0xc7, -1} }, /*c4*/
- { {0x48, -1}, {0xc8, -1} }, { {0x49, -1}, {0xc9, -1} }, { {-1}, {-1} }, { {0x4b, -1}, {0xcb, -1} }, /*c8*/
- { {-1}, {-1} }, { {0x4d, -1}, {0xcd, -1} }, { {-1}, {-1} }, { {0x4f, -1}, {0xcf, -1} }, /*cc*/
- { {0x50, -1}, {0xd0, -1} }, { {0x51, -1}, {0xd1, -1} }, { {0x52, -1}, {0xd2, -1} }, { {0x53, -1}, {0xd3, -1} }, /*d0*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*d4*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*d8*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*dc*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*e0*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*e4*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*e8*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*ec*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*f0*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*f4*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*f8*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*fc*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*100*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*104*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*108*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*10c*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*80*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*84*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*88*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*8c*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*90*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*94*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*98*/
+ { {0x1c, 0}, {0x9c, 0} }, { {0x1d, 0}, {0x9d, 0} }, { {0}, {0} }, { {0}, {0} }, /*9c*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*a0*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*a4*/
+ { {0}, {0} }, { {0}, {0} }, { {0x2a, 0}, {0xaa, 0} }, { {0}, {0} }, /*a8*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*ac*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*b0*/
+ { {0}, {0} }, { {0x35, 0}, {0xb5, 0} }, { {0x36, 0}, {0xb6, 0} }, { {0x37, 0}, {0xb7, 0} }, /*b4*/
+ { {0x38, 0}, {0xb8, 0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*b8*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*bc*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*c0*/
+ { {0}, {0} }, { {0}, {0} }, { {0x46, 0}, {0xc6, 0} }, { {0x47, 0}, {0xc7, 0} }, /*c4*/
+ { {0x48, 0}, {0xc8, 0} }, { {0x49, 0}, {0xc9, 0} }, { {0}, {0} }, { {0x4b, 0}, {0xcb, 0} }, /*c8*/
+ { {0}, {0} }, { {0x4d, 0}, {0xcd, 0} }, { {0}, {0} }, { {0x4f, 0}, {0xcf, 0} }, /*cc*/
+ { {0x50, 0}, {0xd0, 0} }, { {0x51, 0}, {0xd1, 0} }, { {0x52, 0}, {0xd2, 0} }, { {0x53, 0}, {0xd3, 0} }, /*d0*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*d4*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*d8*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*dc*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*e0*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*e4*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*e8*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*ec*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*f0*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*f4*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*f8*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*fc*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*100*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*104*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*108*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*10c*/
};
/*Tandy keyboard has slightly different scancodes to XT*/
static scancode scancode_tandy[272] =
{
- { {-1}, {-1} }, { {0x01, -1}, {0x81, -1} }, { {0x02, -1}, {0x82, -1} }, { {0x03, -1}, {0x83, -1} },
- { {0x04, -1}, {0x84, -1} }, { {0x05, -1}, {0x85, -1} }, { {0x06, -1}, {0x86, -1} }, { {0x07, -1}, {0x87, -1} },
- { {0x08, -1}, {0x88, -1} }, { {0x09, -1}, {0x89, -1} }, { {0x0a, -1}, {0x8a, -1} }, { {0x0b, -1}, {0x8b, -1} },
- { {0x0c, -1}, {0x8c, -1} }, { {0x0d, -1}, {0x8d, -1} }, { {0x0e, -1}, {0x8e, -1} }, { {0x0f, -1}, {0x8f, -1} },
- { {0x10, -1}, {0x90, -1} }, { {0x11, -1}, {0x91, -1} }, { {0x12, -1}, {0x92, -1} }, { {0x13, -1}, {0x93, -1} },
- { {0x14, -1}, {0x94, -1} }, { {0x15, -1}, {0x95, -1} }, { {0x16, -1}, {0x96, -1} }, { {0x17, -1}, {0x97, -1} },
- { {0x18, -1}, {0x98, -1} }, { {0x19, -1}, {0x99, -1} }, { {0x1a, -1}, {0x9a, -1} }, { {0x1b, -1}, {0x9b, -1} },
- { {0x1c, -1}, {0x9c, -1} }, { {0x1d, -1}, {0x9d, -1} }, { {0x1e, -1}, {0x9e, -1} }, { {0x1f, -1}, {0x9f, -1} },
- { {0x20, -1}, {0xa0, -1} }, { {0x21, -1}, {0xa1, -1} }, { {0x22, -1}, {0xa2, -1} }, { {0x23, -1}, {0xa3, -1} },
- { {0x24, -1}, {0xa4, -1} }, { {0x25, -1}, {0xa5, -1} }, { {0x26, -1}, {0xa6, -1} }, { {0x27, -1}, {0xa7, -1} },
- { {0x28, -1}, {0xa8, -1} }, { {0x29, -1}, {0xa9, -1} }, { {0x2a, -1}, {0xaa, -1} }, { {0x47, -1}, {0xc7, -1} },
- { {0x2c, -1}, {0xac, -1} }, { {0x2d, -1}, {0xad, -1} }, { {0x2e, -1}, {0xae, -1} }, { {0x2f, -1}, {0xaf, -1} },
- { {0x30, -1}, {0xb0, -1} }, { {0x31, -1}, {0xb1, -1} }, { {0x32, -1}, {0xb2, -1} }, { {0x33, -1}, {0xb3, -1} },
- { {0x34, -1}, {0xb4, -1} }, { {0x35, -1}, {0xb5, -1} }, { {0x36, -1}, {0xb6, -1} }, { {0x37, -1}, {0xb7, -1} },
- { {0x38, -1}, {0xb8, -1} }, { {0x39, -1}, {0xb9, -1} }, { {0x3a, -1}, {0xba, -1} }, { {0x3b, -1}, {0xbb, -1} },
- { {0x3c, -1}, {0xbc, -1} }, { {0x3d, -1}, {0xbd, -1} }, { {0x3e, -1}, {0xbe, -1} }, { {0x3f, -1}, {0xbf, -1} },
- { {0x40, -1}, {0xc0, -1} }, { {0x41, -1}, {0xc1, -1} }, { {0x42, -1}, {0xc2, -1} }, { {0x43, -1}, {0xc3, -1} },
- { {0x44, -1}, {0xc4, -1} }, { {0x45, -1}, {0xc5, -1} }, { {0x46, -1}, {0xc6, -1} }, { {0x47, -1}, {0xc7, -1} },
- { {0x48, -1}, {0xc8, -1} }, { {0x49, -1}, {0xc9, -1} }, { {0x4a, -1}, {0xca, -1} }, { {0x4b, -1}, {0xcb, -1} },
- { {0x4c, -1}, {0xcc, -1} }, { {0x4d, -1}, {0xcd, -1} }, { {0x4e, -1}, {0xce, -1} }, { {0x4f, -1}, {0xcf, -1} },
- { {0x50, -1}, {0xd0, -1} }, { {0x51, -1}, {0xd1, -1} }, { {0x52, -1}, {0xd2, -1} }, { {0x56, -1}, {0xd6, -1} },
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*54*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*58*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*5c*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*60*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*64*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*68*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*6c*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*70*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*74*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*78*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*7c*/
+ { {0}, {0} }, { {0x01, 0}, {0x81, 0} }, { {0x02, 0}, {0x82, 0} }, { {0x03, 0}, {0x83, 0} },
+ { {0x04, 0}, {0x84, 0} }, { {0x05, 0}, {0x85, 0} }, { {0x06, 0}, {0x86, 0} }, { {0x07, 0}, {0x87, 0} },
+ { {0x08, 0}, {0x88, 0} }, { {0x09, 0}, {0x89, 0} }, { {0x0a, 0}, {0x8a, 0} }, { {0x0b, 0}, {0x8b, 0} },
+ { {0x0c, 0}, {0x8c, 0} }, { {0x0d, 0}, {0x8d, 0} }, { {0x0e, 0}, {0x8e, 0} }, { {0x0f, 0}, {0x8f, 0} },
+ { {0x10, 0}, {0x90, 0} }, { {0x11, 0}, {0x91, 0} }, { {0x12, 0}, {0x92, 0} }, { {0x13, 0}, {0x93, 0} },
+ { {0x14, 0}, {0x94, 0} }, { {0x15, 0}, {0x95, 0} }, { {0x16, 0}, {0x96, 0} }, { {0x17, 0}, {0x97, 0} },
+ { {0x18, 0}, {0x98, 0} }, { {0x19, 0}, {0x99, 0} }, { {0x1a, 0}, {0x9a, 0} }, { {0x1b, 0}, {0x9b, 0} },
+ { {0x1c, 0}, {0x9c, 0} }, { {0x1d, 0}, {0x9d, 0} }, { {0x1e, 0}, {0x9e, 0} }, { {0x1f, 0}, {0x9f, 0} },
+ { {0x20, 0}, {0xa0, 0} }, { {0x21, 0}, {0xa1, 0} }, { {0x22, 0}, {0xa2, 0} }, { {0x23, 0}, {0xa3, 0} },
+ { {0x24, 0}, {0xa4, 0} }, { {0x25, 0}, {0xa5, 0} }, { {0x26, 0}, {0xa6, 0} }, { {0x27, 0}, {0xa7, 0} },
+ { {0x28, 0}, {0xa8, 0} }, { {0x29, 0}, {0xa9, 0} }, { {0x2a, 0}, {0xaa, 0} }, { {0x47, 0}, {0xc7, 0} },
+ { {0x2c, 0}, {0xac, 0} }, { {0x2d, 0}, {0xad, 0} }, { {0x2e, 0}, {0xae, 0} }, { {0x2f, 0}, {0xaf, 0} },
+ { {0x30, 0}, {0xb0, 0} }, { {0x31, 0}, {0xb1, 0} }, { {0x32, 0}, {0xb2, 0} }, { {0x33, 0}, {0xb3, 0} },
+ { {0x34, 0}, {0xb4, 0} }, { {0x35, 0}, {0xb5, 0} }, { {0x36, 0}, {0xb6, 0} }, { {0x37, 0}, {0xb7, 0} },
+ { {0x38, 0}, {0xb8, 0} }, { {0x39, 0}, {0xb9, 0} }, { {0x3a, 0}, {0xba, 0} }, { {0x3b, 0}, {0xbb, 0} },
+ { {0x3c, 0}, {0xbc, 0} }, { {0x3d, 0}, {0xbd, 0} }, { {0x3e, 0}, {0xbe, 0} }, { {0x3f, 0}, {0xbf, 0} },
+ { {0x40, 0}, {0xc0, 0} }, { {0x41, 0}, {0xc1, 0} }, { {0x42, 0}, {0xc2, 0} }, { {0x43, 0}, {0xc3, 0} },
+ { {0x44, 0}, {0xc4, 0} }, { {0x45, 0}, {0xc5, 0} }, { {0x46, 0}, {0xc6, 0} }, { {0x47, 0}, {0xc7, 0} },
+ { {0x48, 0}, {0xc8, 0} }, { {0x49, 0}, {0xc9, 0} }, { {0x4a, 0}, {0xca, 0} }, { {0x4b, 0}, {0xcb, 0} },
+ { {0x4c, 0}, {0xcc, 0} }, { {0x4d, 0}, {0xcd, 0} }, { {0x4e, 0}, {0xce, 0} }, { {0x4f, 0}, {0xcf, 0} },
+ { {0x50, 0}, {0xd0, 0} }, { {0x51, 0}, {0xd1, 0} }, { {0x52, 0}, {0xd2, 0} }, { {0x56, 0}, {0xd6, 0} },
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*54*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*58*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*5c*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*60*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*64*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*68*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*6c*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*70*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*74*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*78*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*7c*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*80*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*84*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*88*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*8c*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*90*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*94*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*98*/
- { {0x57, -1}, {0xd7, -1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*9c*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*a0*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*a4*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {0x2a, -1}, {0xaa, -1} }, { {-1}, {-1} }, /*a8*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*ac*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*b0*/
- { {-1}, {-1} }, { {0x35, -1}, {0xb5, -1} }, { {0x36, -1}, {0xb6, -1} }, { {0x37, -1}, {0xb7, -1} }, /*b4*/
- { {0x38, -1}, {0xb8, -1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*b8*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*bc*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*c0*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {0x46, -1}, {0xc6, -1} }, { {0x47, -1}, {0xc7, -1} }, /*c4*/
- { {0x29, -1}, {0xa9, -1} }, { {0x49, -1}, {0xc9, -1} }, { {-1}, {-1} }, { {0x2b, -1}, {0xab, -1} }, /*c8*/
- { {-1}, {-1} }, { {0x4e, -1}, {0xce, -1} }, { {-1}, {-1} }, { {0x4f, -1}, {0xcf, -1} }, /*cc*/
- { {0x4a, -1}, {0xca, -1} }, { {0x51, -1}, {0xd1, -1} }, { {0x52, -1}, {0xd2, -1} }, { {0x53, -1}, {0xd3, -1} }, /*d0*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*d4*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*d8*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*dc*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*e0*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*e4*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*e8*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*ec*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*f0*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*f4*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*f8*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*fc*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*100*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*104*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*108*/
- { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, { {-1}, {-1} }, /*10c*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*80*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*84*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*88*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*8c*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*90*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*94*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*98*/
+ { {0x57, 0}, {0xd7, 0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*9c*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*a0*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*a4*/
+ { {0}, {0} }, { {0}, {0} }, { {0x2a, 0}, {0xaa, 0} }, { {0}, {0} }, /*a8*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*ac*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*b0*/
+ { {0}, {0} }, { {0x35, 0}, {0xb5, 0} }, { {0x36, 0}, {0xb6, 0} }, { {0x37, 0}, {0xb7, 0} }, /*b4*/
+ { {0x38, 0}, {0xb8, 0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*b8*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*bc*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*c0*/
+ { {0}, {0} }, { {0}, {0} }, { {0x46, 0}, {0xc6, 0} }, { {0x47, 0}, {0xc7, 0} }, /*c4*/
+ { {0x29, 0}, {0xa9, 0} }, { {0x49, 0}, {0xc9, 0} }, { {0}, {0} }, { {0x2b, 0}, {0xab, 0} }, /*c8*/
+ { {0}, {0} }, { {0x4e, 0}, {0xce, 0} }, { {0}, {0} }, { {0x4f, 0}, {0xcf, 0} }, /*cc*/
+ { {0x4a, 0}, {0xca, 0} }, { {0x51, 0}, {0xd1, 0} }, { {0x52, 0}, {0xd2, 0} }, { {0x53, 0}, {0xd3, 0} }, /*d0*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*d4*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*d8*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*dc*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*e0*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*e4*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*e8*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*ec*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*f0*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*f4*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*f8*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*fc*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*100*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*104*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*108*/
+ { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, { {0}, {0} }, /*10c*/
};
-static int oldkey[272];
-static int keydelay[272];
+static uint8_t oldkey[272];
+static uint8_t keydelay[272];
void (*keyboard_send)(uint8_t val);
void (*keyboard_poll)();
int keyboard_scan = 1;
+static scancode *at_scancodes;
+
+void keyboard_set_scancode_set(int set)
+{
+ switch (set)
+ {
+ case SCANCODE_SET_1:
+ at_scancodes = scancode_set1;
+ break;
+ case SCANCODE_SET_2:
+ at_scancodes = scancode_set2;
+ break;
+ case SCANCODE_SET_3:
+ at_scancodes = scancode_set3;
+ break;
+ default:
+ pclog("Invalid scancode set: %i\n", set);
+ }
+}
+
void keyboard_process()
{
int c;
int d;
- scancode *scancodes = (AT) ? scancode_set1 : scancode_xt;
+ scancode *scancodes = (AT || romset == ROM_XI8088) ? at_scancodes : scancode_xt;
if (!keyboard_scan) return;
if (TANDY) scancodes = scancode_tandy;
if (pcem_key[c] != oldkey[c])
{
oldkey[c] = pcem_key[c];
- if ( pcem_key[c] && scancodes[c].scancodes_make[0] == -1)
+ if ( pcem_key[c] && scancodes[c].scancodes_make[0] == 0)
continue;
- if (!pcem_key[c] && scancodes[c].scancodes_break[0] == -1)
+ if (!pcem_key[c] && scancodes[c].scancodes_break[0] == 0)
continue;
// pclog("Key %02X start\n", c);
d = 0;
if (pcem_key[c])
{
- while (scancodes[c].scancodes_make[d] != -1)
+ while (scancodes[c].scancodes_make[d] != 0)
keyboard_send(scancodes[c].scancodes_make[d++]);
}
else
{
- while (scancodes[c].scancodes_break[d] != -1)
+ while (scancodes[c].scancodes_break[d] != 0)
keyboard_send(scancodes[c].scancodes_break[d++]);
}
}
if (keydelay[c] >= 30)
{
keydelay[c] -= 10;
- if (scancode_set1[c].scancodes_make[0] == -1)
+ if (scancodes[c].scancodes_make[0] == 0)
continue;
d = 0;
- while (scancode_set1[c].scancodes_make[d] != -1)
- keyboard_send(scancode_set1[c].scancodes_make[d++]);
+ while (scancodes[c].scancodes_make[d] != 0)
+ keyboard_send(scancodes[c].scancodes_make[d++]);
}
}
}
+
+void keyboard_send_scancode(int code, int is_break)
+{
+ scancode *scancodes = (AT || romset == ROM_XI8088) ? at_scancodes : scancode_xt;
+ int d = 0;
+
+ if (!keyboard_scan) return;
+
+ if (!is_break)
+ {
+ while (scancodes[code].scancodes_make[d] != 0)
+ keyboard_send(scancodes[code].scancodes_make[d++]);
+ }
+ else
+ {
+ while (scancodes[code].scancodes_break[d] != 0)
+ keyboard_send(scancodes[code].scancodes_break[d++]);
+ }
+}
void keyboard_process();
extern int keyboard_scan;
-extern int pcem_key[272];
+extern uint8_t pcem_key[272];
+
+enum
+{
+ SCANCODE_SET_1,
+ SCANCODE_SET_2,
+ SCANCODE_SET_3
+};
+
+void keyboard_set_scancode_set(int set);
+void keyboard_send_scancode(int code, int is_break);
#include "keyboard.h"
#include "keyboard_at.h"
-extern bool ps2_mouse_supported;
-
#define STAT_PARITY 0x80
#define STAT_RTIMEOUT 0x40
#define STAT_TTIMEOUT 0x20
#define PS2_REFRESH_TIME (16 * TIMER_USEC)
+#define RESET_DELAY_TIME (100 * 10) /*600ms*/
+
struct
{
int initialised;
uint8_t mem[0x20];
uint8_t out;
int out_new, out_delayed;
+
+ int scancode_set;
+ int translate;
+ int next_is_release;
uint8_t input_port;
uint8_t output_port;
void (*mouse_write)(uint8_t val, void *p);
void *mouse_p;
- int refresh_time;
+ pc_timer_t refresh_timer;
int refresh;
int is_ps2;
+
+ pc_timer_t send_delay_timer;
+
+ int reset_delay;
} keyboard_at;
+/*Translation table taken from https://www.win.tue.nl/~aeb/linux/kbd/scancodes-10.html#ss10.3*/
+static uint8_t at_translation[256] =
+{
+ 0xff, 0x43, 0x41, 0x3f, 0x3d, 0x3b, 0x3c, 0x58, 0x64, 0x44, 0x42, 0x40, 0x3e, 0x0f, 0x29, 0x59,
+ 0x65, 0x38, 0x2a, 0x70, 0x1d, 0x10, 0x02, 0x5a, 0x66, 0x71, 0x2c, 0x1f, 0x1e, 0x11, 0x03, 0x5b,
+ 0x67, 0x2e, 0x2d, 0x20, 0x12, 0x05, 0x04, 0x5c, 0x68, 0x39, 0x2f, 0x21, 0x14, 0x13, 0x06, 0x5d,
+ 0x69, 0x31, 0x30, 0x23, 0x22, 0x15, 0x07, 0x5e, 0x6a, 0x72, 0x32, 0x24, 0x16, 0x08, 0x09, 0x5f,
+ 0x6b, 0x33, 0x25, 0x17, 0x18, 0x0b, 0x0a, 0x60, 0x6c, 0x34, 0x35, 0x26, 0x27, 0x19, 0x0c, 0x61,
+ 0x6d, 0x73, 0x28, 0x74, 0x1a, 0x0d, 0x62, 0x6e, 0x3a, 0x36, 0x1c, 0x1b, 0x75, 0x2b, 0x63, 0x76,
+ 0x55, 0x56, 0x77, 0x78, 0x79, 0x7a, 0x0e, 0x7b, 0x7c, 0x4f, 0x7d, 0x4b, 0x47, 0x7e, 0x7f, 0x6f,
+ 0x52, 0x53, 0x50, 0x4c, 0x4d, 0x48, 0x01, 0x45, 0x57, 0x4e, 0x51, 0x4a, 0x37, 0x49, 0x46, 0x54,
+ 0x80, 0x81, 0x82, 0x41, 0x54, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
+};
static uint8_t key_ctrl_queue[16];
static int key_ctrl_queue_start = 0, key_ctrl_queue_end = 0;
static uint8_t mouse_queue[16];
int mouse_queue_start = 0, mouse_queue_end = 0;
-void keyboard_at_poll(void *priv)
+void keyboard_at_adddata_keyboard(uint8_t val);
+
+void keyboard_at_poll()
{
- keybsenddelay += (100 * TIMER_USEC);
+ timer_advance_u64(&keyboard_at.send_delay_timer, (100 * TIMER_USEC));
if (keyboard_at.out_new != -1 && !keyboard_at.last_irq)
{
keyboard_at.wantirq = 0;
if (keyboard_at.out_new & 0x100)
{
- if (keyboard_at.mem[0] & 0x02)
- picint(0x1000);
- keyboard_at.out = keyboard_at.out_new & 0xff;
- keyboard_at.out_new = -1;
- keyboard_at.status |= STAT_OFULL;
- keyboard_at.status &= ~STAT_IFULL;
- keyboard_at.status |= STAT_MFULL;
-// pclog("keyboard_at : take IRQ12\n");
- keyboard_at.last_irq = 0x1000;
+ if (mouse_scan)
+ {
+// pclog("keyboard_at : take IRQ12\n");
+ if (keyboard_at.mem[0] & 0x02)
+ picint(0x1000);
+ keyboard_at.out = keyboard_at.out_new & 0xff;
+ keyboard_at.out_new = -1;
+ keyboard_at.status |= STAT_OFULL;
+ keyboard_at.status &= ~STAT_IFULL;
+ keyboard_at.status |= STAT_MFULL;
+ keyboard_at.last_irq = 0x1000;
+ }
+ else
+ {
+// pclog("keyboard_at: suppressing IRQ12\n");
+ keyboard_at.out_new = -1;
+ }
}
else
{
{
keyboard_at.out_new = mouse_queue[mouse_queue_start] | 0x100;
mouse_queue_start = (mouse_queue_start + 1) & 0xf;
- }
+ }
else if (!(keyboard_at.status & STAT_OFULL) && keyboard_at.out_new == -1 &&
!(keyboard_at.mem[0] & 0x10) && key_queue_start != key_queue_end)
{
keyboard_at.out_new = key_queue[key_queue_start];
key_queue_start = (key_queue_start + 1) & 0xf;
- }
-}
-void keyboard_at_poll()
-{
- keyboard_at_poll(NULL);
-}
+ }
+ if (keyboard_at.reset_delay)
+ {
+ keyboard_at.reset_delay--;
+ if (!keyboard_at.reset_delay)
+ keyboard_at_adddata_keyboard(0xaa);
+ }
+}
void keyboard_at_adddata(uint8_t val)
{
void keyboard_at_adddata_keyboard(uint8_t val)
{
+ if (keyboard_at.reset_delay)
+ return;
/* if (val == 0x1c)
{
key_1c++;
case 0x4D: t3100e_notify_set(0x0F); break; /* Right */
}
}
+ if (keyboard_at.translate)
+ {
+ if (val == 0xf0)
+ {
+ keyboard_at.next_is_release = 1;
+ return;
+ }
+ else
+ {
+ val = at_translation[val];
+ if (keyboard_at.next_is_release)
+ val |= 0x80;
+ keyboard_at.next_is_release = 0;
+ }
+ }
key_queue[key_queue_end] = val;
key_queue_end = (key_queue_end + 1) & 0xf;
// pclog("keyboard_at : %02X added to key queue\n", val);
return;
}
-uint8_t x86_get_jumpers(void);
-
void keyboard_at_write(uint16_t port, uint8_t val, void *priv)
{
- //pclog("keyboard_at : write %04X %02X %i %02X\n", port, val, keyboard_at.key_wantdata, ram[8]);
+// pclog("keyboard_at : write %04X %02X %i %02X\n", port, val, keyboard_at.key_wantdata, ram[8]);
if (romset == ROM_XI8088 && port == 0x63)
port = 0x61;
/* if (ram[8] == 0xc3)
if (!(val & 1) && keyboard_at.wantirq)
keyboard_at.wantirq = 0;
mouse_scan = !(val & 0x20);
+ keyboard_at.translate = val & 0x40;
}
break;
break;
case 0xd3: /*Write to mouse output buffer*/
- if (ps2_mouse_supported)
- keyboard_at_adddata_mouse(val);
+ keyboard_at_adddata_mouse(val);
break;
case 0xd4: /*Write to mouse*/
- if (keyboard_at.mouse_write && ps2_mouse_supported)
+ if (keyboard_at.mouse_write)
+ {
keyboard_at.mouse_write(val, keyboard_at.mouse_p);
+ /*Implicitly enable mouse*/
+ mouse_scan = 1;
+ keyboard_at.mem[0] &= ~0x20;
+ }
break;
default:
case 0xed: /*Set/reset LEDs*/
keyboard_at_adddata_keyboard(0xfa);
break;
+
+ case 0xf0: /*Set scancode set*/
+ switch (val)
+ {
+ case 0: /*Read current set*/
+ keyboard_at_adddata_keyboard(0xfa);
+ switch (keyboard_at.scancode_set)
+ {
+ case SCANCODE_SET_1:
+ keyboard_at_adddata_keyboard(0x01);
+ break;
+ case SCANCODE_SET_2:
+ keyboard_at_adddata_keyboard(0x02);
+ break;
+ case SCANCODE_SET_3:
+ keyboard_at_adddata_keyboard(0x03);
+ break;
+ }
+ break;
+ case 1:
+ keyboard_at.scancode_set = SCANCODE_SET_1;
+ keyboard_set_scancode_set(SCANCODE_SET_1);
+ keyboard_at_adddata_keyboard(0xfa);
+ break;
+ case 2:
+ keyboard_at.scancode_set = SCANCODE_SET_2;
+ keyboard_set_scancode_set(SCANCODE_SET_2);
+ keyboard_at_adddata_keyboard(0xfa);
+ break;
+ case 3:
+ keyboard_at.scancode_set = SCANCODE_SET_3;
+ keyboard_set_scancode_set(SCANCODE_SET_3);
+ keyboard_at_adddata_keyboard(0xfa);
+ break;
+ default:
+ keyboard_at_adddata_keyboard(0xfe);
+ break;
+ }
+ break;
case 0xf3: /*Set typematic rate/delay*/
keyboard_at_adddata_keyboard(0xfa);
keyboard_at_adddata_keyboard(0xfa);
break;
+ case 0xee: /*Diagnostic echo*/
+ keyboard_at_adddata_keyboard(0xee);
+ break;
+
+ case 0xf0: /*Set scancode set*/
+ keyboard_at.key_wantdata = 1;
+ keyboard_at_adddata_keyboard(0xfa);
+ break;
+
case 0xf2: /*Read ID*/
keyboard_at_adddata_keyboard(0xfa);
- // A2286/A2386 does not want these
- //keyboard_at_adddata_keyboard(0xab);
- //keyboard_at_adddata_keyboard(0x41);
+ keyboard_at_adddata_keyboard(0xab);
+ keyboard_at_adddata_keyboard(0x83);
break;
case 0xf3: /*Set typematic rate/delay*/
case 0xff: /*Reset*/
key_queue_start = key_queue_end = 0; /*Clear key queue*/
keyboard_at_adddata_keyboard(0xfa);
- keyboard_at_adddata_keyboard(0xaa);
+ keyboard_at.reset_delay = RESET_DELAY_TIME;
break;
default:
case 0x61:
ppi.pb = val;
- timer_process();
- timer_update_outstanding();
-
speaker_update();
speaker_gated = val & 1;
speaker_enable = val & 2;
case 0xa7: /*Disable mouse port*/
mouse_scan = 0;
+ keyboard_at.mem[0] |= 0x20;
break;
case 0xa8: /*Enable mouse port*/
- if (ps2_mouse_supported)
- mouse_scan = 1;
+ mouse_scan = 1;
+ keyboard_at.mem[0] &= ~0x20;
break;
case 0xa9: /*Test mouse port*/
- if (ps2_mouse_supported)
- keyboard_at_adddata(0x00); /*no error*/
+ keyboard_at_adddata(0x00); /*no error*/
break;
case 0xaa: /*Self-test*/
case 0xae: /*Enable keyboard*/
keyboard_at.mem[0] &= ~0x10;
- if (!keyboard_at.initialised)
- keyboard_at_adddata(0x00); // A2286 bios requires data in output buffer after enable keyboard.
break;
case 0xb0: /* T3100e: Turbo on */
if (romset == ROM_T3100E)
keyboard_at.input_port = (t3100e_mono_get() & 1) ? 0xFF : 0xBF;
- keyboard_at_adddata(x86_get_jumpers());
- //keyboard_at_adddata(keyboard_at.input_port | 4);
+ keyboard_at_adddata(keyboard_at.input_port | 4);
keyboard_at.input_port = ((keyboard_at.input_port + 1) & 3) | (keyboard_at.input_port & 0xfc);
break;
break;
case 0xd3: /*Write mouse output buffer*/
- if (ps2_mouse_supported)
- keyboard_at.want60 = 1;
+ keyboard_at.want60 = 1;
break;
case 0xd4: /*Write to mouse*/
- if (ps2_mouse_supported)
- keyboard_at.want60 = 1;
+ keyboard_at.want60 = 1;
break;
case 0xe0: /*Read test inputs*/
keyboard_at_adddata(0x00);
break;
+
+ case 0xe8: /* Super-286TR: turbo ON */
+ // TODO: 0xe8 is always followed by 0xba
+ // TODO: I don't know where to call cpu_set_turbo(1) to avoid slow POST after ctrl-alt-del when on low speed (if this is the real behavior!)
+ if (romset == ROM_HYUNDAI_SUPER286TR)
+ cpu_set_turbo(1); // 12 MHz
+ break;
+
+ case 0xe9: /* Super-286TR: turbo OFF */
+ if (romset == ROM_HYUNDAI_SUPER286TR)
+ cpu_set_turbo(0); // 8 MHz
+ break;
case 0xef: /*??? - sent by AMI486*/
break;
uint8_t keyboard_at_read(uint16_t port, void *priv)
{
uint8_t temp = 0xff;
+
+ if (romset != ROM_IBMAT && romset != ROM_IBMXT286)
+ cycles -= ISA_CYCLES(8);
// if (port != 0x61) pclog("keyboard_at : read %04X ", port);
if (romset == ROM_XI8088 && port == 0x63)
port = 0x61;
keyboard_at.input_port = (video_is_mda()) ? 0xb0 : 0xf0;
else
keyboard_at.input_port = (video_is_mda()) ? 0xf0 : 0xb0;
- keyboard_at.out_new = -1;
- keyboard_at.out_delayed = -1;
- keyboard_at.last_irq = 0;
+ keyboard_at.out_new = -1;
+ keyboard_at.out_delayed = -1;
+ keyboard_at.last_irq = 0;
keyboard_at.key_wantdata = 0;
static void at_refresh(void *p)
{
keyboard_at.refresh = !keyboard_at.refresh;
- keyboard_at.refresh_time += PS2_REFRESH_TIME;
+ timer_advance_u64(&keyboard_at.refresh_timer, PS2_REFRESH_TIME);
}
void keyboard_at_init()
keyboard_at.mouse_write = NULL;
keyboard_at.mouse_p = NULL;
keyboard_at.is_ps2 = 0;
+ keyboard_set_scancode_set(SCANCODE_SET_2);
+ keyboard_at.scancode_set = SCANCODE_SET_2;
- timer_add(keyboard_at_poll, &keybsenddelay, TIMER_ALWAYS_ENABLED, NULL);
+ timer_add(&keyboard_at.send_delay_timer, keyboard_at_poll, NULL, 1);
}
void keyboard_at_set_mouse(void (*mouse_write)(uint8_t val, void *p), void *p)
void keyboard_at_init_ps2()
{
- timer_add(at_refresh, &keyboard_at.refresh_time, TIMER_ALWAYS_ENABLED, NULL);
+ timer_add(&keyboard_at.refresh_timer, at_refresh, NULL, 1);
keyboard_at.is_ps2 = 1;
}
void mca_init(int nr_cards);
-void mca_add(uint8_t (*read)(int addr, void *priv), void (*write)(int addr, uint8_t val, void *priv), void *priv);
+void mca_add(uint8_t (*read)(int addr, void *priv), void (*write)(int addr, uint8_t val, void *priv), void (*reset)(void *priv), void *priv);
void mca_set_index(int index);
uint8_t mca_read(uint16_t port);
void mca_write(uint16_t port, uint8_t val);
+void mca_reset(void);
page_t *pages;
page_t **page_lookup;
-static uint8_t (*_mem_read_b[0x40000])(uint32_t addr, void *priv);
-static uint16_t (*_mem_read_w[0x40000])(uint32_t addr, void *priv);
-static uint32_t (*_mem_read_l[0x40000])(uint32_t addr, void *priv);
-static void (*_mem_write_b[0x40000])(uint32_t addr, uint8_t val, void *priv);
-static void (*_mem_write_w[0x40000])(uint32_t addr, uint16_t val, void *priv);
-static void (*_mem_write_l[0x40000])(uint32_t addr, uint32_t val, void *priv);
-static uint8_t *_mem_exec[0x40000];
-static void *_mem_priv_r[0x40000];
-static void *_mem_priv_w[0x40000];
-static mem_mapping_t *_mem_mapping_r[0x40000];
-static mem_mapping_t *_mem_mapping_w[0x40000];
-static int _mem_state[0x40000];
+static mem_mapping_t *read_mapping[0x40000];
+static mem_mapping_t *write_mapping[0x40000];
+static uint8_t *_mem_exec[0x40000];
+static uint8_t _mem_state[0x40000];
static mem_mapping_t base_mapping;
mem_mapping_t ram_low_mapping;
mem_mapping_t bios_high_mapping[8];
static mem_mapping_t romext_mapping;
-int shadowbios,shadowbios_write;
-
-unsigned char isram[0x10000];
-
static uint8_t ff_array[0x1000];
int mem_size;
uint8_t *ram, *rom = NULL;
uint8_t romext[32768];
-//int abrt=0;
+uint64_t *byte_dirty_mask;
+uint64_t *byte_code_present_mask;
+
+uint32_t mem_logical_addr;
+
+int mmuflush=0;
+int mmu_perm=4;
+
+int mem_addr_is_ram(uint32_t addr)
+{
+ mem_mapping_t *mapping = read_mapping[addr >> 14];
+
+ return (mapping == &ram_low_mapping) || (mapping == &ram_high_mapping) || (mapping == &ram_mid_mapping) || (mapping == &ram_remapped_mapping);
+}
void resetreadlookup()
{
}
-int mmuflush=0;
-int mmu_perm=4;
-
void flushmmucache()
{
int c;
}
}
-extern int output;
-
#define mmutranslate_read(addr) mmutranslatereal(addr,0)
#define mmutranslate_write(addr) mmutranslatereal(addr,1)
-int pctrans=0;
-
-extern uint32_t testr[9];
-
static inline uint32_t mmu_readl(uint32_t addr)
{
return *(uint32_t *)&_mem_exec[addr >> 14][addr & 0x3fff];
if (!(temp&1) || (CPL==3 && !(temp3&4) && !cpl_override) || (rw && !(temp3&2) && ((CPL == 3 && !cpl_override) || cr0&WP_FLAG)))
{
// if (!nopageerrors) pclog("Page not present! %08X %08X %02X %02X %i %08X %04X:%08X %04X:%08X %i %i %i\n",addr,temp,opcode,opcode2,frame,rmdat32, CS,pc,SS,ESP,ins,CPL,rw);
-
// dumpregs();
// exit(-1);
// if (addr == 0x815F6E90) output = 3;
// if (page_lookup[virt >> 12] && (writelookup2[virt>>12] != 0xffffffff))
// fatal("Bad write mapping\n");
- if (pages[phys >> 12].block[0] || pages[phys >> 12].block[1] || pages[phys >> 12].block[2] || pages[phys >> 12].block[3] || (phys & ~0xfff) == recomp_page)
+ if (pages[phys >> 12].block || (phys & ~0xfff) == recomp_page)
page_lookup[virt >> 12] = &pages[phys >> 12];//(uintptr_t)&ram[(uintptr_t)(phys & ~0xFFF) - (uintptr_t)(virt & ~0xfff)];
else
writelookup2[virt>>12] = (uintptr_t)&ram[(uintptr_t)(phys & ~0xFFF) - (uintptr_t)(virt & ~0xfff)];
cycles -= 9;
}
-#undef printf
uint8_t *getpccache(uint32_t a)
{
uint32_t a2=a;
if (cr0>>31)
{
- pctrans=1;
a = mmutranslate_read(a);
- pctrans=0;
if (a==0xFFFFFFFF) return ram;
}
if (_mem_exec[a >> 14])
{
- if (_mem_mapping_r[a >> 14]->flags & MEM_MAPPING_ROM)
+ if (read_mapping[a >> 14]->flags & MEM_MAPPING_ROM)
cpu_prefetch_cycles = cpu_rom_prefetch_cycles;
else
cpu_prefetch_cycles = cpu_mem_prefetch_cycles;
pclog("Bad getpccache %08X\n", a);
return &ff_array[0-(uintptr_t)(a2 & ~0xFFF)];
}
-#define printf pclog
-uint32_t mem_logical_addr;
uint8_t readmembl(uint32_t addr)
{
+ mem_mapping_t *map;
+
mem_logical_addr = addr;
if (cr0 >> 31)
{
}
addr &= rammask;
- if (_mem_read_b[addr >> 14]) return _mem_read_b[addr >> 14](addr, _mem_priv_r[addr >> 14]);
+ map = read_mapping[addr >> 14];
+ if (map && map->read_b)
+ return map->read_b(addr, map->p);
// pclog("Bad readmembl %08X %04X:%08X\n", addr, CS, pc);
return 0xFF;
}
void writemembl(uint32_t addr, uint8_t val)
{
+ mem_mapping_t *map;
+
mem_logical_addr = addr;
if (page_lookup[addr>>12])
}
addr &= rammask;
- if (_mem_write_b[addr >> 14]) _mem_write_b[addr >> 14](addr, val, _mem_priv_w[addr >> 14]);
+ map = write_mapping[addr >> 14];
+ if (map && map->write_b)
+ return map->write_b(addr, val, map->p);
// else pclog("Bad writemembl %08X %02X %04X:%08X\n", addr, val, CS, pc);
}
-uint8_t readmemb386l(uint32_t seg, uint32_t addr)
-{
- if (seg==-1)
- {
- x86gpf("NULL segment", 0);
- printf("NULL segment! rb %04X(%08X):%08X %02X %08X\n",CS,cs,cpu_state.pc,opcode,addr);
- return -1;
- }
- mem_logical_addr = addr = addr + seg;
-/* if (readlookup2[mem_logical_addr >> 12] != 0xFFFFFFFF)
- {
- return ram[readlookup2[mem_logical_addr >> 12] + (mem_logical_addr & 0xFFF)];
- }*/
-
- if (cr0 >> 31)
- {
- addr = mmutranslate_read(addr);
- if (addr == 0xFFFFFFFF) return 0xFF;
- }
-
- addr &= rammask;
-
- if (_mem_read_b[addr >> 14]) return _mem_read_b[addr >> 14](addr, _mem_priv_r[addr >> 14]);
-// pclog("Bad readmemb386l %08X %04X:%08X\n", addr, CS, pc);
- return 0xFF;
-}
-
-void writememb386l(uint32_t seg, uint32_t addr, uint8_t val)
+uint16_t readmemwl(uint32_t addr)
{
- if (seg==-1)
- {
- x86gpf("NULL segment", 0);
- printf("NULL segment! wb %04X(%08X):%08X %02X %08X\n",CS,cs,cpu_state.pc,opcode,addr);
- return;
- }
-
- mem_logical_addr = addr = addr + seg;
- if (page_lookup[addr>>12])
- {
- page_lookup[addr>>12]->write_b(addr, val, page_lookup[addr>>12]);
- return;
- }
- if (cr0 >> 31)
- {
- addr = mmutranslate_write(addr);
- if (addr == 0xFFFFFFFF) return;
- }
-
- addr &= rammask;
-
-/* if (addr >= 0xa0000 && addr < 0xc0000)
- pclog("writemembl %08X %02X\n", addr, val);*/
+ mem_mapping_t *map;
- if (_mem_write_b[addr >> 14]) _mem_write_b[addr >> 14](addr, val, _mem_priv_w[addr >> 14]);
-// else pclog("Bad writememb386l %08X %02X %04X:%08X\n", addr, val, CS, pc);
-}
-
-uint16_t readmemwl(uint32_t seg, uint32_t addr)
-{
- uint32_t addr2 = mem_logical_addr = seg + addr;
+ mem_logical_addr = addr;
- if (seg==-1)
+ if (addr & 1)
{
- x86gpf("NULL segment", 0);
- printf("NULL segment! rw %04X(%08X):%08X %02X %08X\n",CS,cs,cpu_state.pc,opcode,addr);
- return -1;
- }
- if (addr2 & 1)
- {
- if (!cpu_cyrix_alignment || (addr2 & 7) == 7)
+ if (!cpu_cyrix_alignment || (addr & 7) == 7)
cycles -= timing_misaligned;
- if ((addr2 & 0xFFF) > 0xFFE)
+ if ((addr & 0xFFF) > 0xFFE)
{
if (cr0 >> 31)
{
- if (mmutranslate_read(addr2) == 0xffffffff) return 0xffff;
- if (mmutranslate_read(addr2+1) == 0xffffffff) return 0xffff;
+ if (mmutranslate_read(addr) == 0xffffffff) return 0xffff;
+ if (mmutranslate_read(addr+1) == 0xffffffff) return 0xffff;
}
- if (is386) return readmemb386l(seg,addr)|(readmemb386l(seg,addr+1)<<8);
- else return readmembl(seg+addr)|(readmembl(seg+addr+1)<<8);
+ return readmembl(addr)|(readmembl(addr+1)<<8);
}
- else if (readlookup2[addr2 >> 12] != -1)
- return *(uint16_t *)(readlookup2[addr2 >> 12] + addr2);
+ else if (readlookup2[addr >> 12] != -1)
+ return *(uint16_t *)(readlookup2[addr >> 12] + addr);
}
if (cr0>>31)
{
- addr2 = mmutranslate_read(addr2);
- if (addr2==0xFFFFFFFF) return 0xFFFF;
+ addr = mmutranslate_read(addr);
+ if (addr==0xFFFFFFFF) return 0xFFFF;
}
- addr2 &= rammask;
-
- if (_mem_read_w[addr2 >> 14]) return _mem_read_w[addr2 >> 14](addr2, _mem_priv_r[addr2 >> 14]);
+ addr &= rammask;
- if (_mem_read_b[addr2 >> 14])
+ map = read_mapping[addr >> 14];
+ if (map)
{
- if (AT) return _mem_read_b[addr2 >> 14](addr2, _mem_priv_r[addr2 >> 14]) | (_mem_read_b[(addr2 + 1) >> 14](addr2 + 1, _mem_priv_r[addr2 >> 14]) << 8);
- else return _mem_read_b[addr2 >> 14](addr2, _mem_priv_r[addr2 >> 14]) | (_mem_read_b[(seg + ((addr + 1) & 0xffff)) >> 14](seg + ((addr + 1) & 0xffff), _mem_priv_r[addr2 >> 14]) << 8);
+ if (map->read_w)
+ return map->read_w(addr, map->p);
+
+ if (map->read_b)
+ return map->read_b(addr, map->p) | (map->read_b(addr + 1, map->p) << 8);
}
-// pclog("Bad readmemwl %08X\n", addr2);
+
+// pclog("Bad readmemwl %08X\n", addr);
return 0xffff;
}
-void writememwl(uint32_t seg, uint32_t addr, uint16_t val)
+void writememwl(uint32_t addr, uint16_t val)
{
- uint32_t addr2 = mem_logical_addr = seg + addr;
+ mem_mapping_t *map;
- if (seg==-1)
- {
- x86gpf("NULL segment", 0);
- printf("NULL segment! ww %04X(%08X):%08X %02X %08X\n",CS,cs,cpu_state.pc,opcode,addr);
- return;
- }
+ mem_logical_addr = addr;
- if (addr2 & 1)
+ if (addr & 1)
{
- if (!cpu_cyrix_alignment || (addr2 & 7) == 7)
+ if (!cpu_cyrix_alignment || (addr & 7) == 7)
cycles -= timing_misaligned;
- if ((addr2 & 0xFFF) > 0xFFE)
+ if ((addr & 0xFFF) > 0xFFE)
{
if (cr0 >> 31)
{
- if (mmutranslate_write(addr2) == 0xffffffff) return;
- if (mmutranslate_write(addr2+1) == 0xffffffff) return;
- }
- if (is386)
- {
- writememb386l(seg,addr,val);
- writememb386l(seg,addr+1,val>>8);
- }
- else
- {
- writemembl(seg+addr,val);
- writemembl(seg+addr+1,val>>8);
+ if (mmutranslate_write(addr) == 0xffffffff) return;
+ if (mmutranslate_write(addr+1) == 0xffffffff) return;
}
+ writemembl(addr,val);
+ writemembl(addr+1,val>>8);
return;
}
- else if (writelookup2[addr2 >> 12] != -1)
+ else if (writelookup2[addr >> 12] != -1)
{
- *(uint16_t *)(writelookup2[addr2 >> 12] + addr2) = val;
+ *(uint16_t *)(writelookup2[addr >> 12] + addr) = val;
return;
}
}
- if (page_lookup[addr2>>12])
+ if (page_lookup[addr>>12])
{
- page_lookup[addr2>>12]->write_w(addr2, val, page_lookup[addr2>>12]);
+ page_lookup[addr>>12]->write_w(addr, val, page_lookup[addr>>12]);
return;
}
if (cr0>>31)
{
- addr2 = mmutranslate_write(addr2);
- if (addr2==0xFFFFFFFF) return;
+ addr = mmutranslate_write(addr);
+ if (addr==0xFFFFFFFF) return;
}
- addr2 &= rammask;
+ addr &= rammask;
-/* if (addr2 >= 0xa0000 && addr2 < 0xc0000)
- pclog("writememwl %08X %02X\n", addr2, val);*/
-
- if (_mem_write_w[addr2 >> 14])
+ map = write_mapping[addr >> 14];
+ if (map)
{
- _mem_write_w[addr2 >> 14](addr2, val, _mem_priv_w[addr2 >> 14]);
- return;
+ if (map->write_w)
+ map->write_w(addr, val, map->p);
+ else if (map->write_b)
+ {
+ map->write_b(addr, val, map->p);
+ map->write_b(addr + 1, val >> 8, map->p);
+ }
}
- if (_mem_write_b[addr2 >> 14])
- {
- _mem_write_b[addr2 >> 14](addr2, val, _mem_priv_w[addr2 >> 14]);
- _mem_write_b[(addr2 + 1) >> 14](addr2 + 1, val >> 8, _mem_priv_w[addr2 >> 14]);
- return;
- }
-// pclog("Bad writememwl %08X %04X\n", addr2, val);
+// pclog("Bad writememwl %08X %04X\n", addr, val);
}
-uint32_t readmemll(uint32_t seg, uint32_t addr)
+uint32_t readmemll(uint32_t addr)
{
- uint32_t addr2 = mem_logical_addr = seg + addr;
+ mem_mapping_t *map;
- if (seg==-1)
- {
- x86gpf("NULL segment", 0);
- printf("NULL segment! rl %04X(%08X):%08X %02X %08X\n",CS,cs,cpu_state.pc,opcode,addr);
- return -1;
- }
+ mem_logical_addr = addr;
- if (addr2 & 3)
+ if (addr & 3)
{
- if (!cpu_cyrix_alignment || (addr2 & 7) > 4)
+ if (!cpu_cyrix_alignment || (addr & 7) > 4)
cycles -= timing_misaligned;
- if ((addr2&0xFFF)>0xFFC)
+ if ((addr&0xFFF)>0xFFC)
{
if (cr0>>31)
{
- if (mmutranslate_read(addr2) == 0xffffffff) return 0xffffffff;
- if (mmutranslate_read(addr2+3) == 0xffffffff) return 0xffffffff;
+ if (mmutranslate_read(addr) == 0xffffffff) return 0xffffffff;
+ if (mmutranslate_read(addr+3) == 0xffffffff) return 0xffffffff;
}
- return readmemwl(seg,addr)|(readmemwl(seg,addr+2)<<16);
+ return readmemwl(addr)|(readmemwl(addr+2)<<16);
}
- else if (readlookup2[addr2 >> 12] != -1)
- return *(uint32_t *)(readlookup2[addr2 >> 12] + addr2);
+ else if (readlookup2[addr >> 12] != -1)
+ return *(uint32_t *)(readlookup2[addr >> 12] + addr);
}
if (cr0>>31)
{
- addr2 = mmutranslate_read(addr2);
- if (addr2==0xFFFFFFFF) return 0xFFFFFFFF;
+ addr = mmutranslate_read(addr);
+ if (addr==0xFFFFFFFF) return 0xFFFFFFFF;
}
- addr2&=rammask;
+ addr&=rammask;
+
+ map = read_mapping[addr >> 14];
+ if (map)
+ {
+ if (map->read_l)
+ return map->read_l(addr, map->p);
- if (_mem_read_l[addr2 >> 14]) return _mem_read_l[addr2 >> 14](addr2, _mem_priv_r[addr2 >> 14]);
+ if (map->read_w)
+ return map->read_w(addr, map->p) | (map->read_w(addr + 2, map->p) << 16);
- if (_mem_read_w[addr2 >> 14]) return _mem_read_w[addr2 >> 14](addr2, _mem_priv_r[addr2 >> 14]) | (_mem_read_w[addr2 >> 14](addr2 + 2, _mem_priv_r[addr2 >> 14]) << 16);
-
- if (_mem_read_b[addr2 >> 14]) return _mem_read_b[addr2 >> 14](addr2, _mem_priv_r[addr2 >> 14]) | (_mem_read_b[addr2 >> 14](addr2 + 1, _mem_priv_r[addr2 >> 14]) << 8) | (_mem_read_b[addr2 >> 14](addr2 + 2, _mem_priv_r[addr2 >> 14]) << 16) | (_mem_read_b[addr2 >> 14](addr2 + 3, _mem_priv_r[addr2 >> 14]) << 24);
+ if (map->read_b)
+ return map->read_b(addr, map->p) | (map->read_b(addr + 1, map->p) << 8) |
+ (map->read_b(addr + 2, map->p) << 16) | (map->read_b(addr + 3, map->p) << 24);
+ }
-// pclog("Bad readmemll %08X\n", addr2);
+// pclog("Bad readmemll %08X\n", addr);
return 0xffffffff;
}
-void writememll(uint32_t seg, uint32_t addr, uint32_t val)
+void writememll(uint32_t addr, uint32_t val)
{
- uint32_t addr2 = mem_logical_addr = seg + addr;
+ mem_mapping_t *map;
- if (seg==-1)
- {
- x86gpf("NULL segment", 0);
- printf("NULL segment! wl %04X(%08X):%08X %02X %08X\n",CS,cs,cpu_state.pc,opcode,addr);
- return;
- }
- if (addr2 & 3)
+ mem_logical_addr = addr;
+
+ if (addr & 3)
{
- if (!cpu_cyrix_alignment || (addr2 & 7) > 4)
+ if (!cpu_cyrix_alignment || (addr & 7) > 4)
cycles -= timing_misaligned;
- if ((addr2 & 0xFFF) > 0xFFC)
+ if ((addr & 0xFFF) > 0xFFC)
{
if (cr0>>31)
{
- if (mmutranslate_write(addr2) == 0xffffffff) return;
- if (mmutranslate_write(addr2+3) == 0xffffffff) return;
+ if (mmutranslate_write(addr) == 0xffffffff) return;
+ if (mmutranslate_write(addr+3) == 0xffffffff) return;
}
- writememwl(seg,addr,val);
- writememwl(seg,addr+2,val>>16);
+ writememwl(addr,val);
+ writememwl(addr+2,val>>16);
return;
}
- else if (writelookup2[addr2 >> 12] != -1)
+ else if (writelookup2[addr >> 12] != -1)
{
- *(uint32_t *)(writelookup2[addr2 >> 12] + addr2) = val;
+ *(uint32_t *)(writelookup2[addr >> 12] + addr) = val;
return;
}
}
- if (page_lookup[addr2>>12])
+ if (page_lookup[addr>>12])
{
- page_lookup[addr2>>12]->write_l(addr2, val, page_lookup[addr2>>12]);
+ page_lookup[addr>>12]->write_l(addr, val, page_lookup[addr>>12]);
return;
}
if (cr0>>31)
{
- addr2 = mmutranslate_write(addr2);
- if (addr2==0xFFFFFFFF) return;
+ addr = mmutranslate_write(addr);
+ if (addr==0xFFFFFFFF) return;
}
- addr2&=rammask;
+ addr&=rammask;
-/* if (addr >= 0xa0000 && addr < 0xc0000)
- pclog("writememll %08X %08X\n", addr, val);*/
-
- if (_mem_write_l[addr2 >> 14])
- {
- _mem_write_l[addr2 >> 14](addr2, val, _mem_priv_w[addr2 >> 14]);
- return;
- }
- if (_mem_write_w[addr2 >> 14])
- {
- _mem_write_w[addr2 >> 14](addr2, val, _mem_priv_w[addr2 >> 14]);
- _mem_write_w[addr2 >> 14](addr2 + 2, val >> 16, _mem_priv_w[addr2 >> 14]);
- return;
- }
- if (_mem_write_b[addr2 >> 14])
+ map = write_mapping[addr >> 14];
+ if (map)
{
- _mem_write_b[addr2 >> 14](addr2, val, _mem_priv_w[addr2 >> 14]);
- _mem_write_b[addr2 >> 14](addr2 + 1, val >> 8, _mem_priv_w[addr2 >> 14]);
- _mem_write_b[addr2 >> 14](addr2 + 2, val >> 16, _mem_priv_w[addr2 >> 14]);
- _mem_write_b[addr2 >> 14](addr2 + 3, val >> 24, _mem_priv_w[addr2 >> 14]);
- return;
+ if (map->write_l)
+ map->write_l(addr, val, map->p);
+ else if (map->write_w)
+ {
+ map->write_w(addr, val, map->p);
+ map->write_w(addr + 2, val >> 16, map->p);
+ }
+ else if (map->write_b)
+ {
+ map->write_b(addr, val, map->p);
+ map->write_b(addr + 1, val >> 8, map->p);
+ map->write_b(addr + 2, val >> 16, map->p);
+ map->write_b(addr + 3, val >> 24, map->p);
+ }
}
-// pclog("Bad writememll %08X %08X\n", addr2, val);
+// pclog("Bad writememll %08X %08X\n", addr, val);
}
-uint64_t readmemql(uint32_t seg, uint32_t addr)
+uint64_t readmemql(uint32_t addr)
{
- uint32_t addr2 = mem_logical_addr = seg + addr;
+ mem_mapping_t *map;
- if (seg==-1)
- {
- x86gpf("NULL segment", 0);
- printf("NULL segment! rl %04X(%08X):%08X %02X %08X\n",CS,cs,cpu_state.pc,opcode,addr);
- return -1;
- }
+ mem_logical_addr = addr;
- if (addr2 & 7)
+ if (addr & 7)
{
cycles -= timing_misaligned;
- if ((addr2 & 0xFFF) > 0xFF8)
+ if ((addr & 0xFFF) > 0xFF8)
{
if (cr0>>31)
{
- if (mmutranslate_read(addr2) == 0xffffffff) return 0xffffffff;
- if (mmutranslate_read(addr2+7) == 0xffffffff) return 0xffffffff;
+ if (mmutranslate_read(addr) == 0xffffffff) return 0xffffffff;
+ if (mmutranslate_read(addr+7) == 0xffffffff) return 0xffffffff;
}
- return readmemll(seg,addr)|((uint64_t)readmemll(seg,addr+4)<<32);
+ return readmemll(addr)|((uint64_t)readmemll(addr+4)<<32);
}
- else if (readlookup2[addr2 >> 12] != -1)
- return *(uint64_t *)(readlookup2[addr2 >> 12] + addr2);
+ else if (readlookup2[addr >> 12] != -1)
+ return *(uint64_t *)(readlookup2[addr >> 12] + addr);
}
if (cr0>>31)
{
- addr2 = mmutranslate_read(addr2);
- if (addr2==0xFFFFFFFF) return 0xFFFFFFFF;
+ addr = mmutranslate_read(addr);
+ if (addr==0xFFFFFFFF) return 0xFFFFFFFF;
}
- addr2&=rammask;
+ addr&=rammask;
- if (_mem_read_l[addr2 >> 14])
- return _mem_read_l[addr2 >> 14](addr2, _mem_priv_r[addr2 >> 14]) |
- ((uint64_t)_mem_read_l[addr2 >> 14](addr2 + 4, _mem_priv_r[addr2 >> 14]) << 32);
+ map = read_mapping[addr >> 14];
+ if (map && map->read_l)
+ return map->read_l(addr, map->p) | ((uint64_t)map->read_l(addr + 4, map->p) << 32);
- return readmemll(seg,addr) | ((uint64_t)readmemll(seg,addr+4)<<32);
+ return readmemll(addr) | ((uint64_t)readmemll(addr+4)<<32);
}
-void writememql(uint32_t seg, uint32_t addr, uint64_t val)
+void writememql(uint32_t addr, uint64_t val)
{
- uint32_t addr2 = mem_logical_addr = seg + addr;
+ mem_mapping_t *map;
- if (seg==-1)
- {
- x86gpf("NULL segment", 0);
- printf("NULL segment! wl %04X(%08X):%08X %02X %08X\n",CS,cs,cpu_state.pc,opcode,addr);
- return;
- }
- if (addr2 & 7)
+ mem_logical_addr = addr;
+
+ if (addr & 7)
{
cycles -= timing_misaligned;
- if ((addr2 & 0xFFF) > 0xFF8)
+ if ((addr & 0xFFF) > 0xFF8)
{
if (cr0>>31)
{
- if (mmutranslate_write(addr2) == 0xffffffff) return;
- if (mmutranslate_write(addr2+7) == 0xffffffff) return;
+ if (mmutranslate_write(addr) == 0xffffffff) return;
+ if (mmutranslate_write(addr+7) == 0xffffffff) return;
}
- writememll(seg, addr, val);
- writememll(seg, addr+4, val >> 32);
+ writememll(addr, val);
+ writememll(addr+4, val >> 32);
return;
}
- else if (writelookup2[addr2 >> 12] != -1)
+ else if (writelookup2[addr >> 12] != -1)
{
- *(uint64_t *)(writelookup2[addr2 >> 12] + addr2) = val;
+ *(uint64_t *)(writelookup2[addr >> 12] + addr) = val;
return;
}
}
- if (page_lookup[addr2>>12])
+ if (page_lookup[addr>>12])
{
- page_lookup[addr2>>12]->write_l(addr2, val, page_lookup[addr2>>12]);
- page_lookup[addr2>>12]->write_l(addr2 + 4, val >> 32, page_lookup[addr2>>12]);
+ page_lookup[addr>>12]->write_l(addr, val, page_lookup[addr>>12]);
+ page_lookup[addr>>12]->write_l(addr + 4, val >> 32, page_lookup[addr>>12]);
return;
}
if (cr0>>31)
{
- addr2 = mmutranslate_write(addr2);
- if (addr2==0xFFFFFFFF) return;
+ addr = mmutranslate_write(addr);
+ if (addr==0xFFFFFFFF) return;
}
- addr2&=rammask;
+ addr&=rammask;
- if (_mem_write_l[addr2 >> 14])
- {
- _mem_write_l[addr2 >> 14](addr2, val, _mem_priv_w[addr2 >> 14]);
- _mem_write_l[addr2 >> 14](addr2+4, val >> 32, _mem_priv_w[addr2 >> 14]);
- return;
- }
- if (_mem_write_w[addr2 >> 14])
- {
- _mem_write_w[addr2 >> 14](addr2, val, _mem_priv_w[addr2 >> 14]);
- _mem_write_w[addr2 >> 14](addr2 + 2, val >> 16, _mem_priv_w[addr2 >> 14]);
- _mem_write_w[addr2 >> 14](addr2 + 4, val >> 32, _mem_priv_w[addr2 >> 14]);
- _mem_write_w[addr2 >> 14](addr2 + 6, val >> 48, _mem_priv_w[addr2 >> 14]);
- return;
- }
- if (_mem_write_b[addr2 >> 14])
+ map = write_mapping[addr >> 14];
+ if (map)
{
- _mem_write_b[addr2 >> 14](addr2, val, _mem_priv_w[addr2 >> 14]);
- _mem_write_b[addr2 >> 14](addr2 + 1, val >> 8, _mem_priv_w[addr2 >> 14]);
- _mem_write_b[addr2 >> 14](addr2 + 2, val >> 16, _mem_priv_w[addr2 >> 14]);
- _mem_write_b[addr2 >> 14](addr2 + 3, val >> 24, _mem_priv_w[addr2 >> 14]);
- _mem_write_b[addr2 >> 14](addr2 + 4, val >> 32, _mem_priv_w[addr2 >> 14]);
- _mem_write_b[addr2 >> 14](addr2 + 5, val >> 40, _mem_priv_w[addr2 >> 14]);
- _mem_write_b[addr2 >> 14](addr2 + 6, val >> 48, _mem_priv_w[addr2 >> 14]);
- _mem_write_b[addr2 >> 14](addr2 + 7, val >> 56, _mem_priv_w[addr2 >> 14]);
- return;
+ if (map->write_l)
+ {
+ map->write_l(addr, val, map->p);
+ map->write_l(addr + 4, val >> 32, map->p);
+ }
+ else if (map->write_w)
+ {
+ map->write_w(addr, val, map->p);
+ map->write_w(addr + 2, val >> 16, map->p);
+ map->write_w(addr + 4, val >> 32, map->p);
+ map->write_w(addr + 6, val >> 48, map->p);
+ }
+ else if (map->write_b)
+ {
+ map->write_b(addr, val, map->p);
+ map->write_b(addr + 1, val >> 8, map->p);
+ map->write_b(addr + 2, val >> 16, map->p);
+ map->write_b(addr + 3, val >> 24, map->p);
+ map->write_b(addr + 4, val >> 32, map->p);
+ map->write_b(addr + 5, val >> 40, map->p);
+ map->write_b(addr + 6, val >> 48, map->p);
+ map->write_b(addr + 7, val >> 56, map->p);
+ }
}
-// pclog("Bad writememql %08X %08X\n", addr2, val);
+// pclog("Bad writememql %08X %08X\n", addr, val);
}
uint8_t mem_readb_phys(uint32_t addr)
{
+ mem_mapping_t *map = read_mapping[addr >> 14];
+
mem_logical_addr = 0xffffffff;
- if (_mem_read_b[addr >> 14])
- return _mem_read_b[addr >> 14](addr, _mem_priv_r[addr >> 14]);
+ if (map && map->read_b)
+ return map->read_b(addr, map->p);
return 0xff;
}
uint16_t mem_readw_phys(uint32_t addr)
{
+ mem_mapping_t *map = read_mapping[addr >> 14];
+
mem_logical_addr = 0xffffffff;
- if (_mem_read_w[addr >> 14] && !(addr & 1))
- return _mem_read_w[addr >> 14](addr, _mem_priv_r[addr >> 14]);
+ if (map && map->read_w)
+ return map->read_w(addr, map->p);
return mem_readb_phys(addr) | (mem_readb_phys(addr + 1) << 8);
}
uint32_t mem_readl_phys(uint32_t addr)
{
+ mem_mapping_t *map = read_mapping[addr >> 14];
+
mem_logical_addr = 0xffffffff;
- if (_mem_read_l[addr >> 14] && !(addr & 3))
- return _mem_read_l[addr >> 14](addr, _mem_priv_r[addr >> 14]);
+ if (map && map->read_l)
+ return map->read_l(addr, map->p);
return mem_readw_phys(addr) | (mem_readw_phys(addr + 2) << 16);
}
void mem_writeb_phys(uint32_t addr, uint8_t val)
{
+ mem_mapping_t *map = write_mapping[addr >> 14];
+
mem_logical_addr = 0xffffffff;
- if (_mem_write_b[addr >> 14])
- _mem_write_b[addr >> 14](addr, val, _mem_priv_w[addr >> 14]);
+ if (map && map->write_b)
+ map->write_b(addr, val, map->p);
}
void mem_writew_phys(uint32_t addr, uint16_t val)
{
+ mem_mapping_t *map = write_mapping[addr >> 14];
+
mem_logical_addr = 0xffffffff;
- if (_mem_write_w[addr >> 14] && !(addr & 1))
- _mem_write_w[addr >> 14](addr, val, _mem_priv_w[addr >> 14]);
+ if (map && map->write_w && !(addr & 1))
+ map->write_w(addr, val, map->p);
else
{
mem_writeb_phys(addr, val);
}
void mem_writel_phys(uint32_t addr, uint32_t val)
{
+ mem_mapping_t *map = write_mapping[addr >> 14];
+
mem_logical_addr = 0xffffffff;
- if (_mem_write_l[addr >> 14] && !(addr & 3))
- _mem_write_l[addr >> 14](addr, val, _mem_priv_w[addr >> 14]);
+ if (map && map->write_l && !(addr & 3))
+ map->write_l(addr, val, map->p);
else
{
mem_writew_phys(addr, val);
return *(uint32_t *)&ram[addr];
}
+uint32_t purgable_page_list_head = 0;
+int purgeable_page_count = 0;
+
+static inline int page_index(page_t *p)
+{
+ return ((uintptr_t)p - (uintptr_t)pages) / sizeof(page_t);
+}
+void page_add_to_evict_list(page_t *p)
+{
+// pclog("page_add_to_evict_list: %08x %i\n", page_index(p), purgeable_page_count);
+ pages[purgable_page_list_head].evict_prev = page_index(p);
+ p->evict_next = purgable_page_list_head;
+ p->evict_prev = 0;
+ purgable_page_list_head = pages[purgable_page_list_head].evict_prev;
+ purgeable_page_count++;
+}
+void page_remove_from_evict_list(page_t *p)
+{
+// pclog("page_remove_from_evict_list: %08x %i\n", page_index(p), purgeable_page_count);
+ if (!page_in_evict_list(p))
+ fatal("page_remove_from_evict_list: not in evict list!\n");
+ if (p->evict_prev)
+ pages[p->evict_prev].evict_next = p->evict_next;
+ else
+ purgable_page_list_head = p->evict_next;
+ if (p->evict_next)
+ pages[p->evict_next].evict_prev = p->evict_prev;
+ p->evict_prev = EVICT_NOT_IN_LIST;
+ purgeable_page_count--;
+}
+
void mem_write_ramb_page(uint32_t addr, uint8_t val, page_t *p)
{
if (val != p->mem[addr & 0xfff] || codegen_in_recompile)
{
uint64_t mask = (uint64_t)1 << ((addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK);
-// pclog("mem_write_ramb_page: %08x %02x %08x %llx %llx\n", addr, val, cs+pc, p->dirty_mask, mask);
- p->dirty_mask[(addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK] |= mask;
+ int byte_offset = (addr >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK;
+ uint64_t byte_mask = (uint64_t)1 << (addr & PAGE_BYTE_MASK_MASK);
+
+// pclog("mem_write_ramb_page: %08x %02x %08x %llx %llx\n", addr, val, cs+cpu_state.pc, p->dirty_mask, mask);
p->mem[addr & 0xfff] = val;
+ p->dirty_mask |= mask;
+ if ((p->code_present_mask & mask) && !page_in_evict_list(p))
+ {
+// pclog("ramb add %08x %016llx %016llx\n", addr, p->code_present_mask[index], mask);
+ page_add_to_evict_list(p);
+ }
+ p->byte_dirty_mask[byte_offset] |= byte_mask;
+ if ((p->byte_code_present_mask[byte_offset] & byte_mask) && !page_in_evict_list(p))
+ {
+// pclog(" ramb add %08x %016llx %016llx\n", addr, p->byte_code_present_mask[byte_offset], byte_mask);
+ page_add_to_evict_list(p);
+ }
}
}
void mem_write_ramw_page(uint32_t addr, uint16_t val, page_t *p)
if (val != *(uint16_t *)&p->mem[addr & 0xfff] || codegen_in_recompile)
{
uint64_t mask = (uint64_t)1 << ((addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK);
+ int byte_offset = (addr >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK;
+ uint64_t byte_mask = (uint64_t)1 << (addr & PAGE_BYTE_MASK_MASK);
+
if ((addr & 0xf) == 0xf)
mask |= (mask << 1);
-// pclog("mem_write_ramw_page: %08x %04x %08x\n", addr, val, cs+pc);
- p->dirty_mask[(addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK] |= mask;
+// pclog("mem_write_ramw_page: %08x %04x %08x %016llx %016llx %016llx %08x %08x %p\n", addr, val, cs+cpu_state.pc, p->dirty_mask[index], p->code_present_mask[index], mask, p->evict_prev, p->evict_next, p);
*(uint16_t *)&p->mem[addr & 0xfff] = val;
+ p->dirty_mask |= mask;
+ if ((p->code_present_mask & mask) && !page_in_evict_list(p))
+ {
+// pclog("ramw add %08x %016llx %016llx\n", addr, p->code_present_mask[index], mask);
+ page_add_to_evict_list(p);
+ }
+ if ((addr & PAGE_BYTE_MASK_MASK) == PAGE_BYTE_MASK_MASK)
+ {
+ p->byte_dirty_mask[byte_offset+1] |= 1;
+ if ((p->byte_code_present_mask[byte_offset+1] & 1) && !page_in_evict_list(p))
+ {
+// pclog("ramw add %08x %016llx %016llx\n", addr, p->code_present_mask[index], mask);
+ page_add_to_evict_list(p);
+ }
+ }
+ else
+ byte_mask |= (byte_mask << 1);
+
+ p->byte_dirty_mask[byte_offset] |= byte_mask;
+
+ if ((p->byte_code_present_mask[byte_offset] & byte_mask) && !page_in_evict_list(p))
+ {
+// pclog("ramw add %08x %016llx %016llx\n", addr, p->code_present_mask[index], mask);
+ page_add_to_evict_list(p);
+ }
}
}
void mem_write_raml_page(uint32_t addr, uint32_t val, page_t *p)
if (val != *(uint32_t *)&p->mem[addr & 0xfff] || codegen_in_recompile)
{
uint64_t mask = (uint64_t)1 << ((addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK);
+ int byte_offset = (addr >> PAGE_BYTE_MASK_SHIFT) & PAGE_BYTE_MASK_OFFSET_MASK;
+ uint64_t byte_mask = (uint64_t)0xf << (addr & PAGE_BYTE_MASK_MASK);
+
if ((addr & 0xf) >= 0xd)
mask |= (mask << 1);
-// pclog("mem_write_raml_page: %08x %08x %08x\n", addr, val, cs+pc);
- p->dirty_mask[(addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK] |= mask;
+// pclog("mem_write_raml_page: %08x %08x %08x %016llx %016llx %016llx\n", addr, val, cs+cpu_state.pc, p->dirty_mask[index], p->code_present_mask[index], mask);
*(uint32_t *)&p->mem[addr & 0xfff] = val;
+ p->dirty_mask |= mask;
+ p->byte_dirty_mask[byte_offset] |= byte_mask;
+ if (!page_in_evict_list(p) && ((p->code_present_mask & mask) || (p->byte_code_present_mask[byte_offset] & byte_mask)))
+ {
+// pclog("raml add %08x %016llx %016llx\n", addr, p->code_present_mask[index], mask);
+ page_add_to_evict_list(p);
+ }
+ if ((addr & PAGE_BYTE_MASK_MASK) > (PAGE_BYTE_MASK_MASK-3))
+ {
+ uint32_t byte_mask_2 = 0xf >> (4 - (addr & 3));
+
+ p->byte_dirty_mask[byte_offset+1] |= byte_mask_2;
+ if ((p->byte_code_present_mask[byte_offset+1] & byte_mask_2) && !page_in_evict_list(p))
+ {
+// pclog("raml add %08x %016llx %016llx\n", addr, p->code_present_mask[index], mask);
+ page_add_to_evict_list(p);
+ }
+ }
}
}
for (; start_addr <= end_addr; start_addr += (1 << PAGE_MASK_SHIFT))
{
uint64_t mask = (uint64_t)1 << ((start_addr >> PAGE_MASK_SHIFT) & PAGE_MASK_MASK);
-
- pages[start_addr >> 12].dirty_mask[(start_addr >> PAGE_MASK_INDEX_SHIFT) & PAGE_MASK_INDEX_MASK] |= mask;
+ page_t *p = &pages[start_addr >> 12];
+
+//pclog("mem_invalidate: %08x\n", start_addr);
+ p->dirty_mask |= mask;
+ if ((p->code_present_mask & mask) && !page_in_evict_list(p))
+ {
+// pclog("invalidate add %08x %016llx %016llx\n", start_addr, p->code_present_mask[index], mask);
+ page_add_to_evict_list(p);
+ }
}
}
/*Clear out old mappings*/
for (c = base; c < base + size; c += 0x4000)
{
- _mem_read_b[c >> 14] = NULL;
- _mem_read_w[c >> 14] = NULL;
- _mem_read_l[c >> 14] = NULL;
- _mem_priv_r[c >> 14] = NULL;
- _mem_mapping_r[c >> 14] = NULL;
+ read_mapping[c >> 14] = NULL;
+ write_mapping[c >> 14] = NULL;
_mem_exec[c >> 14] = NULL;
- _mem_write_b[c >> 14] = NULL;
- _mem_write_w[c >> 14] = NULL;
- _mem_write_l[c >> 14] = NULL;
- _mem_priv_w[c >> 14] = NULL;
- _mem_mapping_w[c >> 14] = NULL;
}
/*Walk mapping list*/
if ((mapping->read_b || mapping->read_w || mapping->read_l) &&
mem_mapping_read_allowed(mapping->flags, _mem_state[c >> 14]))
{
- _mem_read_b[c >> 14] = mapping->read_b;
- _mem_read_w[c >> 14] = mapping->read_w;
- _mem_read_l[c >> 14] = mapping->read_l;
+ read_mapping[c >> 14] = mapping;
if (mapping->exec)
_mem_exec[c >> 14] = mapping->exec + (c - mapping->base);
else
_mem_exec[c >> 14] = NULL;
- _mem_priv_r[c >> 14] = mapping->p;
- _mem_mapping_r[c >> 14] = mapping;
}
if ((mapping->write_b || mapping->write_w || mapping->write_l) &&
mem_mapping_write_allowed(mapping->flags, _mem_state[c >> 14]))
{
- _mem_write_b[c >> 14] = mapping->write_b;
- _mem_write_w[c >> 14] = mapping->write_w;
- _mem_write_l[c >> 14] = mapping->write_l;
- _mem_priv_w[c >> 14] = mapping->p;
- _mem_mapping_w[c >> 14] = mapping;
+ write_mapping[c >> 14] = mapping;
}
}
}
int mem_a20_key = 0, mem_a20_alt = 0;
static int mem_a20_state = 2;
-void mem_free()
-{
- free(ram);
- ram = NULL;
- free(readlookup2);
- readlookup2 = NULL;
- free(writelookup2);
- writelookup2 = NULL;
- free(pages);
- pages = NULL;
- free(page_lookup);
- page_lookup = NULL;
-}
-
-void mem_init()
-{
- int c;
-
- ram = (uint8_t*)malloc(mem_size * 1024);
-// rom = malloc(0x20000);
- readlookup2 = (uintptr_t*)malloc(1024 * 1024 * sizeof(uintptr_t));
- writelookup2 = (uintptr_t*)malloc(1024 * 1024 * sizeof(uintptr_t));
- biosmask = 0xffff;
- pages = (page_t*)malloc((((mem_size + 384) * 1024) >> 12) * sizeof(page_t));
- page_lookup = (page_t**)malloc((1 << 20) * sizeof(page_t *));
-
- memset(ram, 0, mem_size * 1024);
- memset(pages, 0, (((mem_size + 384) * 1024) >> 12) * sizeof(page_t));
-
- memset(page_lookup, 0, (1 << 20) * sizeof(page_t *));
-
- for (c = 0; c < (((mem_size + 384) * 1024) >> 12); c++)
- {
- pages[c].mem = &ram[c << 12];
- pages[c].write_b = mem_write_ramb_page;
- pages[c].write_w = mem_write_ramw_page;
- pages[c].write_l = mem_write_raml_page;
- }
-
- memset(isram, 0, sizeof(isram));
- for (c = 0; c < (mem_size / 64); c++)
- {
- isram[c] = 1;
- if ((c >= 0xa && c <= 0xf) || (cpu_16bitbus && c >= 0xfe && c <= 0xff))
- isram[c] = 0;
- }
-
- memset(_mem_read_b, 0, sizeof(_mem_read_b));
- memset(_mem_read_w, 0, sizeof(_mem_read_w));
- memset(_mem_read_l, 0, sizeof(_mem_read_l));
- memset(_mem_write_b, 0, sizeof(_mem_write_b));
- memset(_mem_write_w, 0, sizeof(_mem_write_w));
- memset(_mem_write_l, 0, sizeof(_mem_write_l));
- memset(_mem_exec, 0, sizeof(_mem_exec));
-
- memset(ff_array, 0xff, sizeof(ff_array));
-
- memset(&base_mapping, 0, sizeof(base_mapping));
-
- memset(_mem_state, 0, sizeof(_mem_state));
-
- mem_set_mem_state(0x000000, (mem_size > 640) ? 0xa0000 : mem_size * 1024, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
- mem_set_mem_state(0x0c0000, 0x40000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
-
- mem_mapping_add(&ram_low_mapping, 0x00000, (mem_size > 640) ? 0xa0000 : mem_size * 1024, mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml, ram, MEM_MAPPING_INTERNAL, NULL);
- if (mem_size > 1024)
- {
- if (cpu_16bitbus && mem_size > 16256)
- {
- mem_set_mem_state(0x100000, (16256 - 1024) * 1024, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
- mem_mapping_add(&ram_high_mapping, 0x100000, ((16256 - 1024) * 1024), mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml, ram + 0x100000, MEM_MAPPING_INTERNAL, NULL);
- }
- else
- {
- mem_set_mem_state(0x100000, (mem_size - 1024) * 1024, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
- mem_mapping_add(&ram_high_mapping, 0x100000, ((mem_size - 1024) * 1024), mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml, ram + 0x100000, MEM_MAPPING_INTERNAL, NULL);
- }
- }
- if (mem_size > 768)
- mem_mapping_add(&ram_mid_mapping, 0xc0000, 0x40000, mem_read_ram, mem_read_ramw, mem_read_raml, mem_write_ram, mem_write_ramw, mem_write_raml, ram + 0xc0000, MEM_MAPPING_INTERNAL, NULL);
-
- if (romset == ROM_IBMPS1_2011)
- mem_mapping_add(&romext_mapping, 0xc8000, 0x08000, mem_read_romext, mem_read_romextw, mem_read_romextl, NULL, NULL, NULL, romext, 0, NULL);
-// pclog("Mem resize %i %i\n",mem_size,c);
- mem_a20_key = 2;
- mem_a20_alt = 0;
-}
-
static void mem_remap_top(int max_size)
{
int c;
for (c = ((start * 1024) >> 12); c < (((start + size) * 1024) >> 12); c++)
{
- pages[c].mem = &ram[0xA0000 + ((c - ((start * 1024) >> 12)) << 12)];
+ int offset = c - ((start * 1024) >> 12);
+ pages[c].mem = &ram[0xA0000 + (offset << 12)];
pages[c].write_b = mem_write_ramb_page;
pages[c].write_w = mem_write_ramw_page;
pages[c].write_l = mem_write_raml_page;
+ pages[c].evict_prev = EVICT_NOT_IN_LIST;
+ pages[c].byte_dirty_mask = &byte_dirty_mask[offset * 64];
+ pages[c].byte_code_present_mask = &byte_code_present_mask[offset * 64];
}
mem_set_mem_state(start * 1024, size * 1024, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
mem_mapping_set_addr(&ram_low_mapping, 0x00000, (mem_size > 704) ? 0xb0000 : mem_size * 1024);
}
-void mem_resize()
+void mem_init()
+{
+ readlookup2 = malloc(1024 * 1024 * sizeof(uintptr_t));
+ writelookup2 = malloc(1024 * 1024 * sizeof(uintptr_t));
+ page_lookup = malloc((1 << 20) * sizeof(page_t *));
+
+ memset(ff_array, 0xff, sizeof(ff_array));
+}
+
+void mem_alloc()
{
int c;
free(ram);
- ram = (uint8_t*)malloc(mem_size * 1024);
+ ram = malloc(mem_size * 1024);
memset(ram, 0, mem_size * 1024);
+ free(byte_dirty_mask);
+ byte_dirty_mask = malloc((mem_size * 1024) / 8);
+ memset(byte_dirty_mask, 0, (mem_size * 1024) / 8);
+ free(byte_code_present_mask);
+ byte_code_present_mask = malloc((mem_size * 1024) / 8);
+ memset(byte_code_present_mask, 0, (mem_size * 1024) / 8);
+
free(pages);
- pages = (page_t*)malloc((((mem_size + 384) * 1024) >> 12) * sizeof(page_t));
+ pages = malloc((((mem_size + 384) * 1024) >> 12) * sizeof(page_t));
memset(pages, 0, (((mem_size + 384) * 1024) >> 12) * sizeof(page_t));
for (c = 0; c < (((mem_size + 384) * 1024) >> 12); c++)
{
pages[c].write_b = mem_write_ramb_page;
pages[c].write_w = mem_write_ramw_page;
pages[c].write_l = mem_write_raml_page;
- }
-
- memset(isram, 0, sizeof(isram));
- for (c = 0; c < (mem_size / 64); c++)
- {
- isram[c] = 1;
- if ((c >= 0xa && c <= 0xf) || (cpu_16bitbus && c >= 0xfe && c <= 0xff))
- isram[c] = 0;
+ pages[c].evict_prev = EVICT_NOT_IN_LIST;
+ pages[c].byte_dirty_mask = &byte_dirty_mask[c * 64];
+ pages[c].byte_code_present_mask = &byte_code_present_mask[c * 64];
}
- memset(_mem_read_b, 0, sizeof(_mem_read_b));
- memset(_mem_read_w, 0, sizeof(_mem_read_w));
- memset(_mem_read_l, 0, sizeof(_mem_read_l));
- memset(_mem_write_b, 0, sizeof(_mem_write_b));
- memset(_mem_write_w, 0, sizeof(_mem_write_w));
- memset(_mem_write_l, 0, sizeof(_mem_write_l));
+ memset(page_lookup, 0, (1 << 20) * sizeof(page_t *));
+
+ memset(read_mapping, 0, sizeof(read_mapping));
+ memset(write_mapping, 0, sizeof(write_mapping));
memset(_mem_exec, 0, sizeof(_mem_exec));
memset(&base_mapping, 0, sizeof(base_mapping));
mem_a20_key = 2;
mem_a20_alt = 0;
mem_a20_recalc();
+
+ purgable_page_list_head = 0;
+ purgeable_page_count = 0;
}
void mem_reset_page_blocks()
pages[c].write_b = mem_write_ramb_page;
pages[c].write_w = mem_write_ramw_page;
pages[c].write_l = mem_write_raml_page;
- pages[c].block[0] = pages[c].block[1] = pages[c].block[2] = pages[c].block[3] = NULL;
- pages[c].block_2[0] = pages[c].block_2[1] = pages[c].block_2[2] = pages[c].block_2[3] = NULL;
+ pages[c].block = BLOCK_INVALID;
+ pages[c].block_2 = BLOCK_INVALID;
}
}
#ifndef _MEM_H_
#define _MEM_H_
+#include "x86.h"
+
typedef struct mem_mapping_t
{
struct mem_mapping_t *prev, *next;
extern uint8_t romext[32768];
extern int readlnum,writelnum;
extern int memspeed[11];
-extern int nopageerrors;
extern uint32_t biosmask;
void mem_mapping_add(mem_mapping_t *mapping,
FILE *romfopen(char *fn, char *mode);
-extern mem_mapping_t bios_mapping[8];
-extern mem_mapping_t bios_high_mapping[8];
+mem_mapping_t bios_mapping[8];
+mem_mapping_t bios_high_mapping[8];
extern mem_mapping_t ram_high_mapping;
extern mem_mapping_t ram_remapped_mapping;
+extern uint64_t *byte_dirty_mask;
+extern uint64_t *byte_code_present_mask;
+
+#define PAGE_BYTE_MASK_SHIFT 6
+#define PAGE_BYTE_MASK_OFFSET_MASK 63
+#define PAGE_BYTE_MASK_MASK 63
+
+#define EVICT_NOT_IN_LIST ((uint32_t)-1)
typedef struct page_t
{
void (*write_b)(uint32_t addr, uint8_t val, struct page_t *p);
uint8_t *mem;
- struct codeblock_t *block[4], *block_2[4];
+ uint16_t block, block_2;
/*Head of codeblock tree associated with this page*/
- struct codeblock_t *head;
+ uint16_t head;
+
+ uint64_t code_present_mask, dirty_mask;
- uint64_t code_present_mask[4], dirty_mask[4];
+ uint32_t evict_prev, evict_next;
+
+ uint64_t *byte_dirty_mask;
+ uint64_t *byte_code_present_mask;
} page_t;
extern page_t *pages;
extern page_t **page_lookup;
+extern uint32_t purgable_page_list_head;
+static inline int page_in_evict_list(page_t *p)
+{
+ return (p->evict_prev != EVICT_NOT_IN_LIST);
+}
+void page_remove_from_evict_list(page_t *p);
+void page_add_to_evict_list(page_t *p);
+
+int mem_addr_is_ram(uint32_t addr);
+
uint32_t mmutranslate_noabrt(uint32_t addr, int rw);
extern uint32_t get_phys_virt,get_phys_phys;
static inline uint32_t get_phys(uint32_t addr)
return addr & rammask;
}
- get_phys_phys = (mmutranslatereal(addr, 0) & rammask) & ~0xfff;
+ if (readlookup2[addr >> 12] != -1)
+ get_phys_phys = ((uintptr_t)readlookup2[addr >> 12] + (addr & ~0xfff)) - (uintptr_t)ram;
+ else
+ {
+ get_phys_phys = (mmutranslatereal(addr, 0) & rammask) & ~0xfff;
+ if (!cpu_state.abrt && mem_addr_is_ram(get_phys_phys))
+ addreadlookup(get_phys_virt, get_phys_phys);
+ }
+
return get_phys_phys | (addr & 0xfff);
// return mmutranslatereal(addr, 0) & rammask;
}
static inline uint32_t get_phys_noabrt(uint32_t addr)
{
+ uint32_t phys_addr;
+
if (!(cr0 >> 31))
return addr & rammask;
- return mmutranslate_noabrt(addr, 0) & rammask;
+ if (readlookup2[addr >> 12] != -1)
+ return ((uintptr_t)readlookup2[addr >> 12] + addr) - (uintptr_t)ram;
+
+ phys_addr = mmutranslate_noabrt(addr, 0) & rammask;
+ if (phys_addr != 0xffffffff && mem_addr_is_ram(phys_addr))
+ addreadlookup(addr, phys_addr);
+
+ return phys_addr;
}
void mem_invalidate_range(uint32_t start_addr, uint32_t end_addr);
void mem_add_bios();
void mem_init();
-void mem_free();
-void mem_resize();
+void mem_alloc();
void mem_set_704kb();
int loadbios();
-extern unsigned char isram[0x10000];
+extern int purgeable_page_count;
#endif
int model_count();
int model_getromset();
+int model_getromset_from_model(int model);
int model_getmodel(int romset);
char *model_getname();
char *model_get_internal_name();
keyboard_at_adddata_mouse(mouse->sample_rate);
break;
+ case 0xeb: /*Get mouse data*/
+ keyboard_at_adddata_mouse(0xfa);
+
+ temp = 0;
+ if (mouse->x < 0)
+ temp |= 0x10;
+ if (mouse->y < 0)
+ temp |= 0x20;
+ if (mouse_buttons & 1)
+ temp |= 1;
+ if (mouse_buttons & 2)
+ temp |= 2;
+ if ((mouse_buttons & 4) && (mouse_get_type(mouse_type) & MOUSE_TYPE_3BUTTON))
+ temp |= 4;
+ keyboard_at_adddata_mouse(temp);
+ keyboard_at_adddata_mouse(mouse->x & 0xff);
+ keyboard_at_adddata_mouse(mouse->y & 0xff);
+ if (mouse->intellimouse_mode)
+ keyboard_at_adddata_mouse(mouse->z);
+ break;
+
case 0xf2: /*Read ID*/
keyboard_at_adddata_mouse(0xfa);
if (mouse->intellimouse_mode)
mouse->mode = MOUSE_STREAM;
mouse->flags = 0;
mouse->intellimouse_mode = 0;
+ mouse_queue_start = mouse_queue_end = 0;
keyboard_at_adddata_mouse(0xfa);
keyboard_at_adddata_mouse(0xaa);
keyboard_at_adddata_mouse(0x00);
void *mouse_intellimouse_init()
{
- mouse_ps2_t *mouse = (mouse_ps2_t*)mouse_ps2_init();
+ mouse_ps2_t *mouse = mouse_ps2_init();
mouse->is_intellimouse = 1;
typedef struct mouse_serial_t
{
- int mousepos, mousedelay;
+ int mousepos;
+ pc_timer_t mousedelay_timer;
int oldb;
SERIAL *serial;
} mouse_serial_t;
mouse_serial_t *mouse = (mouse_serial_t *)p;
mouse->mousepos = -1;
- mouse->mousedelay = 5000 * (1 << TIMER_SHIFT);
+ timer_set_delay_u64(&mouse->mousedelay_timer, TIMER_USEC * 5000);
}
void mousecallback(void *p)
{
mouse_serial_t *mouse = (mouse_serial_t *)p;
- mouse->mousedelay = 0;
if (mouse->mousepos == -1)
{
mouse->mousepos = 0;
mouse->serial = &serial1;
serial1.rcr_callback = mouse_serial_rcr;
serial1.rcr_callback_p = mouse;
- timer_add(mousecallback, &mouse->mousedelay, &mouse->mousedelay, mouse);
+ timer_add(&mouse->mousedelay_timer, mousecallback, mouse, 0);
return mouse;
}
#include <stdio.h>
+#include <stdlib.h>
#include "ibm.h"
+#include "device.h"
#include "io.h"
#include "nvr.h"
#include "nvr_tc8521.h"
#include "model.h"
#include "nmi.h"
#include "t1000.h"
+#include "x86.h"
int oldromset;
int nvrmask=63;
-uint8_t nvrram[128+64];
+uint8_t nvrram[128];
int nvraddr;
int nvr_dosave = 0;
-static int nvr_onesec_time = 0, nvr_onesec_cnt = 0;
+typedef struct nvr_t
+{
+ pc_timer_t rtc_timer;
+ pc_timer_t onesec_timer;
+ pc_timer_t update_end_timer;
-static int rtctime;
+ int onesec_cnt;
+} nvr_t;
-#if 0
FILE *nvrfopen(char *fn, char *mode)
{
char s[512];
return NULL;
}
}
-#endif
void getnvrtime()
{
time_get(nvrram);
}
-void nvr_recalc()
+static void nvr_speed_changed(void *p)
{
- int c;
- int newrtctime;
- c = 1 << ((nvrram[RTC_REGA] & RTC_RS) - 1);
- newrtctime=(int)(RTCCONST * c * (1 << TIMER_SHIFT));
- if (rtctime>newrtctime) rtctime=newrtctime;
+ nvr_t *nvr = (nvr_t *)p;
+
+ if (!(nvrram[RTC_REGA] & RTC_RS))
+ {
+ timer_disable(&nvr->rtc_timer);
+ return;
+ }
+ else
+ {
+ int c = 1 << ((nvrram[RTC_REGA] & RTC_RS) - 1);
+ timer_set_delay_u64(&nvr->rtc_timer, (uint64_t)(RTCCONST * c));
+ }
}
-void nvr_rtc(void *p)
+static void nvr_rtc(void *p)
{
- int c;
+ nvr_t *nvr = (nvr_t *)p;
+
if (!(nvrram[RTC_REGA] & RTC_RS))
{
- rtctime=0x7fffffff;
+ timer_disable(&nvr->rtc_timer);
return;
}
- c = 1 << ((nvrram[RTC_REGA] & RTC_RS) - 1);
- rtctime += (int)(RTCCONST * c * (1 << TIMER_SHIFT));
-// pclog("RTCtime now %f\n",rtctime);
- nvrram[RTC_REGC] |= RTC_PF;
- if (nvrram[RTC_REGB] & RTC_PIE)
+ else
{
- nvrram[RTC_REGC] |= RTC_IRQF;
- if (AMSTRAD) picint(2);
- else picint(0x100);
-// pclog("RTC int\n");
+ int c = 1 << ((nvrram[RTC_REGA] & RTC_RS) - 1);
+ timer_advance_u64(&nvr->rtc_timer, (uint64_t)(RTCCONST * c));
+// pclog("RTCtime now %f\n",rtctime);
+ nvrram[RTC_REGC] |= RTC_PF;
+ if (nvrram[RTC_REGB] & RTC_PIE)
+ {
+ nvrram[RTC_REGC] |= RTC_IRQF;
+ if (AMSTRAD) picint(2);
+ else picint(0x100);
+// pclog("RTC int\n");
+ }
}
}
return (nvrram[nvraddr + 1] == nvrram[nvraddr] || (nvrram[nvraddr + 1] & ALARM_DONTCARE) == ALARM_DONTCARE);
}
-int nvr_update_end_count = 0;
-void nvr_update_end(void *p)
+static void nvr_update_end(void *p)
{
+// nvr_t *nvr = (nvr_t *)p;
+
if (!(nvrram[RTC_REGB] & RTC_SET))
{
getnvrtime();
}
// pclog("RTC onesec\n");
-
- nvr_update_end_count = 0;
}
-void nvr_onesec(void *p)
+static void nvr_onesec(void *p)
{
- nvr_onesec_cnt++;
- if (nvr_onesec_cnt >= 100)
+ nvr_t *nvr = (nvr_t *)p;
+
+ nvr->onesec_cnt++;
+ if (nvr->onesec_cnt >= 100)
{
if (!(nvrram[RTC_REGB] & RTC_SET))
{
nvr_update_status = RTC_UIP;
rtc_tick();
- nvr_update_end_count = (int)((244.0 + 1984.0) * TIMER_USEC);
+ timer_set_delay_u64(&nvr->update_end_timer, (uint64_t)((244.0 + 1984.0) * TIMER_USEC));
}
- nvr_onesec_cnt = 0;
+ nvr->onesec_cnt = 0;
}
- nvr_onesec_time += (int)(10000 * TIMER_USEC);
+ timer_advance_u64(&nvr->onesec_timer, (uint64_t)(10000 * TIMER_USEC));
}
-void writenvr(uint16_t addr, uint8_t val, void *priv)
+static void writenvr(uint16_t addr, uint8_t val, void *p)
{
+ nvr_t *nvr = (nvr_t *)p;
int c, old;
cycles -= ISA_CYCLES(8);
if (val & RTC_RS)
{
c = 1 << ((val & RTC_RS) - 1);
- rtctime += (int)(RTCCONST * c * (1 << TIMER_SHIFT));
+ timer_set_delay_u64(&nvr->rtc_timer, (uint64_t)(RTCCONST * c));
}
else
- rtctime = 0x7fffffff;
+ timer_disable(&nvr->rtc_timer);
}
else
{
else
{
nvraddr=val&nvrmask;
-
- // A2386SX extra 64 byte bank
- extern int x86_cmos_bank;
- if (nvraddr >= 64 && x86_cmos_bank)
- nvraddr += 64;
-
- /*PS/2 BIOSes will disable NMIs and expect the watchdog timer to still be able
+ /*PS/2 BIOSes will disable NMIs and expect the watchdog timer to still be able
to fire them. I suspect the watchdog is exempt from NMI masking. Currently NMIs
are always enabled for PS/2 machines - this would mean that other peripherals
could fire NMIs regardless of the mask state, but as there aren't any emulated
MCA peripherals that do this it's currently a moot point.*/
- if (!(models[model].flags & MODEL_MCA))
+
+ /* Also don't update the NMI mask on Amstrad PCs - actually
+ * ought not to do it for any XT because their NMI mask
+ * register is at 0xA0. But particularly important on the
+ * PC200 and PPC because their video subsystem issues NMIs */
+ if (!(models[model].flags & (MODEL_MCA | MODEL_AMSTRAD)))
+ {
nmi_mask = ~val & 0x80;
+ }
}
}
-uint8_t readnvr(uint16_t addr, void *priv)
+uint8_t readnvr(uint16_t addr, void *p)
{
+// nvr_t *nvr = (nvr_t *)p;
uint8_t temp;
// printf("Read NVR %03X %02X %02X %04X:%04X\n",addr,nvraddr,nvrram[nvraddr],cs>>4,pc);
cycles -= ISA_CYCLES(8);
void loadnvr()
{
- int c;
+ FILE *f;
+
nvrmask=63;
oldromset=romset;
-#if 0
- FILE *f;
- switch (romset)
+ switch (romset)
{
case ROM_PC1512: f = nvrfopen("pc1512.nvr", "rb"); break;
case ROM_PC1640: f = nvrfopen("pc1640.nvr", "rb"); break;
case ROM_PC200: f = nvrfopen("pc200.nvr", "rb"); break;
case ROM_PC2086: f = nvrfopen("pc2086.nvr", "rb"); break;
case ROM_PC3086: f = nvrfopen("pc3086.nvr", "rb"); break;
+ case ROM_PPC512: f = nvrfopen("ppc512.nvr", "rb"); break;
case ROM_IBMAT: f = nvrfopen("at.nvr", "rb"); break;
case ROM_IBMXT286: f = nvrfopen("ibmxt286.nvr", "rb"); break;
case ROM_IBMPS1_2011: f = nvrfopen("ibmps1_2011.nvr", "rb"); /*nvrmask = 127; */break;
case ROM_IBMPS2_M80: f = nvrfopen("ibmps2_m80.nvr", "rb"); break;
case ROM_CMDPC30: f = nvrfopen("cmdpc30.nvr", "rb"); nvrmask = 127; break;
case ROM_AMI286: f = nvrfopen("ami286.nvr", "rb"); nvrmask = 127; break;
+ case ROM_TG286M: f = nvrfopen("tg286m.nvr", "rb"); nvrmask = 127; break;
case ROM_AWARD286: f = nvrfopen("award286.nvr", "rb"); nvrmask = 127; break;
+ case ROM_GDC212M: f = nvrfopen("gdc212m.nvr", "rb"); nvrmask = 127; break;
+ case ROM_HYUNDAI_SUPER286TR: f = nvrfopen("super286tr.nvr", "rb"); nvrmask = 127; break;
case ROM_GW286CT: f = nvrfopen("gw286ct.nvr", "rb"); nvrmask = 127; break;
case ROM_SPC4200P: f = nvrfopen("spc4200p.nvr", "rb"); nvrmask = 127; break;
case ROM_SPC4216P: f = nvrfopen("spc4216p.nvr", "rb"); nvrmask = 127; break;
+ case ROM_SPC4620P: f = nvrfopen("spc4620p.nvr", "rb"); nvrmask = 127; break;
case ROM_DELL200: f = nvrfopen("dell200.nvr", "rb"); nvrmask = 127; break;
case ROM_IBMAT386: f = nvrfopen("at386.nvr", "rb"); nvrmask = 127; break;
case ROM_DESKPRO_386: f = nvrfopen("deskpro386.nvr", "rb"); break;
case ROM_ACER386: f = nvrfopen("acer386.nvr", "rb"); nvrmask = 127; break;
case ROM_KMXC02: f = nvrfopen("kmxc02.nvr", "rb"); nvrmask = 127; break;
case ROM_MEGAPC: f = nvrfopen("megapc.nvr", "rb"); nvrmask = 127; break;
+ case ROM_AMA932J: f = nvrfopen("ama932j.nvr", "rb"); nvrmask = 127; break;
case ROM_AMI386SX: f = nvrfopen("ami386.nvr", "rb"); nvrmask = 127; break;
case ROM_AMI486: f = nvrfopen("ami486.nvr", "rb"); nvrmask = 127; break;
case ROM_WIN486: f = nvrfopen("win486.nvr", "rb"); nvrmask = 127; break;
case ROM_PCI486: f = nvrfopen("hot-433.nvr", "rb"); nvrmask = 127; break;
case ROM_SIS496: f = nvrfopen("sis496.nvr", "rb"); nvrmask = 127; break;
+ case ROM_P55VA: f = nvrfopen("p55va.nvr", "rb"); nvrmask = 127; break;
+ case ROM_P55TVP4: f = nvrfopen("p55tvp4.nvr", "rb"); nvrmask = 127; break;
case ROM_430VX: f = nvrfopen("430vx.nvr", "rb"); nvrmask = 127; break;
case ROM_REVENGE: f = nvrfopen("revenge.nvr", "rb"); nvrmask = 127; break;
case ROM_ENDEAVOR: f = nvrfopen("endeavor.nvr", "rb"); nvrmask = 127; break;
+ case ROM_P55T2P4: f = nvrfopen("p55t2p4.nvr", "rb"); nvrmask = 127; break;
case ROM_PX386: f = nvrfopen("px386.nvr", "rb"); nvrmask = 127; break;
case ROM_DTK386: f = nvrfopen("dtk386.nvr", "rb"); nvrmask = 127; break;
case ROM_MR386DX_OPTI495: f = nvrfopen("mr386dx_opti495.nvr", "rb"); nvrmask = 127; break;
case ROM_ELX_PC425X: f = nvrfopen("elx_pc425.nvr", "rb"); nvrmask = 127; break;
case ROM_PB570: f = nvrfopen("pb570.nvr", "rb"); nvrmask = 127; break;
case ROM_ZAPPA: f = nvrfopen("zappa.nvr", "rb"); nvrmask = 127; break;
+ case ROM_ITAUTEC_INFOWAYM: f = nvrfopen("infowaym.nvr", "rb"); nvrmask = 127; break;
case ROM_PB520R: f = nvrfopen("pb520r.nvr", "rb"); nvrmask = 127; break;
case ROM_XI8088: f = nvrfopen("xi8088.nvr", "rb"); nvrmask = 127; break;
case ROM_IBMPS2_M70_TYPE3: f = nvrfopen("ibmps2_m70_type3.nvr","rb"); break;
case ROM_IBMPS2_M70_TYPE4: f = nvrfopen("ibmps2_m70_type4.nvr","rb"); break;
-
+ case ROM_TULIP_TC7: f = nvrfopen("tulip_tc7.nvr", "rb"); break;
+ case ROM_PB410A: f = nvrfopen("pb410a.nvr", "rb"); nvrmask = 127; break;
+ case ROM_BULL_MICRAL_45: f = nvrfopen("bull_micral_45.nvr", "rb"); break;
+ case ROM_FIC_VA503P: f = nvrfopen("fic_va503p.nvr", "rb"); nvrmask = 127; break;
+ case ROM_CBM_SL386SX25: f = nvrfopen("cbm_sl386sx25.nvr", "rb"); nvrmask = 127; break;
+ case ROM_IBMPS1_2133_451: f = nvrfopen("ibmps1_2133.nvr", "rb"); nvrmask = 127; break;
+ case ROM_ECS_386_32: f = nvrfopen("ecs_386_32.nvr", "rb"); nvrmask = 127; break;
+
default: return;
}
if (!f)
return;
}
fread(nvrram,128,1,f);
- fclose(f);
-#endif
- if (enable_sync)
+ if (enable_sync)
time_internal_sync(nvrram);
else
time_internal_set_nvrram(nvrram); /* Update the internal clock state based on the NVR registers. */
+ fclose(f);
nvrram[RTC_REGA] = 6;
nvrram[RTC_REGB] = RTC_2412;
- c = 1 << ((nvrram[RTC_REGA] & RTC_RS) - 1);
- rtctime += (int)(RTCCONST * c * (1 << TIMER_SHIFT));
}
-#if 0
void savenvr()
{
FILE *f;
case ROM_PC200: f = nvrfopen("pc200.nvr", "wb"); break;
case ROM_PC2086: f = nvrfopen("pc2086.nvr", "wb"); break;
case ROM_PC3086: f = nvrfopen("pc3086.nvr", "wb"); break;
+ case ROM_PPC512: f = nvrfopen("ppc512.nvr", "wb"); break;
case ROM_IBMAT: f = nvrfopen("at.nvr", "wb"); break;
case ROM_IBMXT286: f = nvrfopen("ibmxt286.nvr", "wb"); break;
case ROM_IBMPS1_2011: f = nvrfopen("ibmps1_2011.nvr", "wb"); break;
case ROM_IBMPS2_M80: f = nvrfopen("ibmps2_m80.nvr", "wb"); break;
case ROM_CMDPC30: f = nvrfopen("cmdpc30.nvr", "wb"); break;
case ROM_AMI286: f = nvrfopen("ami286.nvr", "wb"); break;
+ case ROM_TG286M: f = nvrfopen("tg286m.nvr", "wb"); break;
case ROM_AWARD286: f = nvrfopen("award286.nvr", "wb"); break;
+ case ROM_GDC212M: f = nvrfopen("gdc212m.nvr", "wb"); break;
+ case ROM_HYUNDAI_SUPER286TR: f = nvrfopen("super286tr.nvr", "wb"); break;
case ROM_GW286CT: f = nvrfopen("gw286ct.nvr", "wb"); break;
case ROM_SPC4200P: f = nvrfopen("spc4200p.nvr", "wb"); break;
case ROM_SPC4216P: f = nvrfopen("spc4216p.nvr", "wb"); break;
+ case ROM_SPC4620P: f = nvrfopen("spc4620p.nvr", "wb"); break;
case ROM_DELL200: f = nvrfopen("dell200.nvr", "wb"); break;
case ROM_IBMAT386: f = nvrfopen("at386.nvr", "wb"); break;
case ROM_DESKPRO_386: f = nvrfopen("deskpro386.nvr", "wb"); break;
case ROM_ACER386: f = nvrfopen("acer386.nvr", "wb"); break;
case ROM_KMXC02: f = nvrfopen("kmxc02.nvr", "wb"); break;
case ROM_MEGAPC: f = nvrfopen("megapc.nvr", "wb"); break;
+ case ROM_AMA932J: f = nvrfopen("ama932j.nvr", "wb"); break;
case ROM_AMI386SX: f = nvrfopen("ami386.nvr", "wb"); break;
case ROM_AMI486: f = nvrfopen("ami486.nvr", "wb"); break;
case ROM_WIN486: f = nvrfopen("win486.nvr", "wb"); break;
case ROM_PCI486: f = nvrfopen("hot-433.nvr", "wb"); break;
case ROM_SIS496: f = nvrfopen("sis496.nvr", "wb"); break;
+ case ROM_P55VA: f = nvrfopen("p55va.nvr", "wb"); break;
+ case ROM_P55TVP4: f = nvrfopen("p55tvp4.nvr", "wb"); break;
case ROM_430VX: f = nvrfopen("430vx.nvr", "wb"); break;
case ROM_REVENGE: f = nvrfopen("revenge.nvr", "wb"); break;
case ROM_ENDEAVOR: f = nvrfopen("endeavor.nvr", "wb"); break;
+ case ROM_P55T2P4: f = nvrfopen("p55t2p4.nvr", "wb"); break;
case ROM_PX386: f = nvrfopen("px386.nvr", "wb"); break;
case ROM_DTK386: f = nvrfopen("dtk386.nvr", "wb"); break;
case ROM_MR386DX_OPTI495: f = nvrfopen("mr386dx_opti495.nvr", "wb"); break;
case ROM_ELX_PC425X: f = nvrfopen("elx_pc425.nvr", "wb"); break;
case ROM_PB570: f = nvrfopen("pb570.nvr", "wb"); break;
case ROM_ZAPPA: f = nvrfopen("zappa.nvr", "wb"); break;
+ case ROM_ITAUTEC_INFOWAYM: f = nvrfopen("infowaym.nvr", "wb"); break;
case ROM_PB520R: f = nvrfopen("pb520r.nvr", "wb"); break;
case ROM_XI8088: f = nvrfopen("xi8088.nvr", "wb"); break;
case ROM_IBMPS2_M70_TYPE3: f = nvrfopen("ibmps2_m70_type3.nvr","wb"); break;
case ROM_IBMPS2_M70_TYPE4: f = nvrfopen("ibmps2_m70_type4.nvr","wb"); break;
-
+ case ROM_TULIP_TC7: f = nvrfopen("tulip_tc7.nvr", "wb"); break;
+ case ROM_PB410A: f = nvrfopen("pb410a.nvr", "wb"); break;
+ case ROM_BULL_MICRAL_45: f = nvrfopen("bull_micral_45.nvr", "wb"); break;
+ case ROM_FIC_VA503P: f = nvrfopen("fic_va503p.nvr", "wb"); break;
+ case ROM_CBM_SL386SX25: f = nvrfopen("cbm_sl386sx25.nvr", "wb"); break;
+ case ROM_IBMPS1_2133_451: f = nvrfopen("ibmps1_2133.nvr", "wb"); break;
+ case ROM_ECS_386_32: f = nvrfopen("ecs_386_32.nvr", "wb"); break;
+
default: return;
}
fwrite(nvrram,128,1,f);
fclose(f);
}
-#endif
-void nvr_init()
+static void *nvr_init()
{
- io_sethandler(0x0070, 0x0002, readnvr, NULL, NULL, writenvr, NULL, NULL, NULL);
- timer_add(nvr_rtc, &rtctime, TIMER_ALWAYS_ENABLED, NULL);
- timer_add(nvr_onesec, &nvr_onesec_time, TIMER_ALWAYS_ENABLED, NULL);
- timer_add(nvr_update_end, &nvr_update_end_count, &nvr_update_end_count, NULL);
+ nvr_t *nvr = (nvr_t *)malloc(sizeof(nvr_t));
+ memset(nvr, 0, sizeof(nvr_t));
+
+ io_sethandler(0x0070, 0x0002, readnvr, NULL, NULL, writenvr, NULL, NULL, nvr);
+ timer_add(&nvr->rtc_timer, nvr_rtc, nvr, 1);
+ timer_add(&nvr->onesec_timer, nvr_onesec, nvr, 1);
+ timer_add(&nvr->update_end_timer, nvr_update_end, nvr, 0);
+
+ return nvr;
+}
+static void nvr_close(void *p)
+{
+ nvr_t *nvr = (nvr_t *)p;
+
+ free(nvr);
}
+
+device_t nvr_device =
+{
+ "Motorola MC146818 RTC",
+ 0,
+ nvr_init,
+ nvr_close,
+ NULL,
+ nvr_speed_changed,
+ NULL,
+ NULL,
+ NULL
+};
-void nvr_init();
+#include "device.h"
+
+extern device_t nvr_device;
extern int enable_sync;
void loadnvr();
void savenvr();
-void nvr_recalc();
-
FILE *nvrfopen(char *fn, char *mode);
-extern uint8_t nvrram[128+64];
+extern uint8_t nvrram[128];
extern int nvrmask;
extern int oldromset;
#include "codegen.h"
#include "timer.h"
#include "sound.h"
-#include "sound_mpu401_uart.h"
+#include "rom.h"
+#include "thread.h"
#ifdef _WIN32
#include <windows.h>
#include "sysconfig.h"
#include "sysdeps.h"
+#include "threaddep/thread.h"
+#include "machdep/maccess.h"
+#include "gfxboard.h"
+#include "uae/time.h"
+
+#include "video.h"
+#include "vid_svga.h"
+
+CPU_STATE cpu_state;
PIT pit, pit2;
PIC pic, pic2;
int AT;
int ppispeakon;
-float CGACONST;
-float MDACONST;
-float VGACONST1, VGACONST2;
-float RTCCONST;
int gated, speakval, speakon;
PPI ppi;
-cpu_state_s cpu_state;
-
-
int codegen_flags_changed;
uint32_t codegen_endpc;
int codegen_in_recompile;
int codegen_flat_ds, codegen_flat_ss;
uint32_t recomp_page;
-codeblock_t **codeblock_hash;
+uint16_t *codeblock_hash;
+codeblock_t *codeblock;
void codegen_reset(void)
{
write_log(_T("device_speed_changed\n"));
}
-union CR0_s CR0;
-
int model;
int cpuspeed;
-int CPUID;
int insc;
int hasfpu;
int romset;
int nmi_mask;
-int use32;
-int stack32;
-uint32_t cr2, cr3, cr4;
uint32_t rammask;
uintptr_t *readlookup2;
uintptr_t *writelookup2;
uint16_t flags, eflags;
-x86seg gdt, ldt, idt, tr;
-x86seg _cs, _ds, _es, _ss, _fs, _gs;
-x86seg _oldds;
int writelookup[256], writelookupp[256];
int readlookup[256], readlookupp[256];
int readlnext;
int writelnext;
-int pccache;
-unsigned char *pccache2;
-int cpl_override;
-uint32_t oldds, oldss, olddslimit, oldsslimit, olddslimitw, oldsslimitw;
+uint32_t olddslimit, oldsslimit, olddslimitw, oldsslimitw;
int pci_burst_time, pci_nonburst_time;
-int optype;
uint32_t oxpc;
char logs_path[512];
uint32_t ealimit, ealimitw;
+int MCA;
+struct svga_t *mb_vga;
uint32_t x87_pc_off, x87_op_off;
uint16_t x87_pc_seg, x87_op_seg;
-uint32_t dr[8];
-
int xi8088_bios_128kb(void)
{
return 0;
int keybsenddelay;
int mouse_buttons;
int mouse_type;
-int pcem_key[272];
+uint8_t pcem_key[272];
int mouse_get_type(int mouse_type)
{
return 0;
}
+static FPU fpus_none[] =
+{
+ { "None", "none", FPU_NONE },
+ { NULL, NULL, 0 }
+};
+static FPU fpus_8088[] =
+{
+ { "None", "none", FPU_NONE },
+ { "8087", "8087", FPU_8087 },
+ { NULL, NULL, 0 }
+};
+static FPU fpus_80286[] =
+{
+ { "None", "none", FPU_NONE },
+ { "287", "287", FPU_287 },
+ { "287XL", "287xl", FPU_287XL },
+ { NULL, NULL, 0 }
+};
+static FPU fpus_80386[] =
+{
+ { "None", "none", FPU_NONE },
+ { "387", "387", FPU_387 },
+ { NULL, NULL, 0 }
+};
+static FPU fpus_builtin[] =
+{
+ { "Built-in", "builtin", FPU_BUILTIN },
+ { NULL, NULL, 0 }
+};
+
+static CPU cpus_8088[] =
+{
+ /*8088 standard*/
+ { "8088/4.77", CPU_8088, fpus_8088, 0, 4772728, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
+ { "8088/7.16", CPU_8088, fpus_8088, 1, 14318184 / 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
+ { "8088/8", CPU_8088, fpus_8088, 1, 8000000, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
+ { "8088/10", CPU_8088, fpus_8088, 2, 10000000, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
+ { "8088/12", CPU_8088, fpus_8088, 3, 12000000, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
+ { "8088/16", CPU_8088, fpus_8088, 4, 16000000, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 },
+ { "", -1, 0, 0, 0, 0 }
+};
+
+static CPU cpus_286[] =
+{
+ /*286*/
+ { "286/6", CPU_286, fpus_80286, 0, 6000000, 1, 0, 0, 0, 0, 0, 2, 2, 2, 2, 1 },
+ { "286/8", CPU_286, fpus_80286, 1, 8000000, 1, 0, 0, 0, 0, 0, 2, 2, 2, 2, 1 },
+ { "286/10", CPU_286, fpus_80286, 2, 10000000, 1, 0, 0, 0, 0, 0, 2, 2, 2, 2, 1 },
+ { "286/12", CPU_286, fpus_80286, 3, 12000000, 1, 0, 0, 0, 0, 0, 3, 3, 3, 3, 2 },
+ { "286/16", CPU_286, fpus_80286, 4, 16000000, 1, 0, 0, 0, 0, 0, 3, 3, 3, 3, 2 },
+ { "286/20", CPU_286, fpus_80286, 5, 20000000, 1, 0, 0, 0, 0, 0, 4, 4, 4, 4, 3 },
+ { "286/25", CPU_286, fpus_80286, 6, 25000000, 1, 0, 0, 0, 0, 0, 4, 4, 4, 4, 3 },
+ { "", -1, 0, 0, 0, 0 }
+};
+
+static CPU cpus_i386SX[] =
+{
+ /*i386SX*/
+ { "i386SX/16", CPU_386SX, fpus_80386, 0, 16000000, 1, 0, 0x2308, 0, 0, 0, 3, 3, 3, 3, 2 },
+ { "i386SX/20", CPU_386SX, fpus_80386, 1, 20000000, 1, 0, 0x2308, 0, 0, 0, 4, 4, 3, 3, 3 },
+ { "i386SX/25", CPU_386SX, fpus_80386, 2, 25000000, 1, 0, 0x2308, 0, 0, 0, 4, 4, 3, 3, 3 },
+ { "i386SX/33", CPU_386SX, fpus_80386, 3, 33333333, 1, 0, 0x2308, 0, 0, 0, 6, 6, 3, 3, 4 },
+ { "", -1, 0, 0, 0 }
+};
+
+static CPU cpus_i386DX[] =
+{
+ /*i386DX*/
+ { "i386DX/16", CPU_386DX, fpus_80386, 0, 16000000, 1, 0, 0x0308, 0, 0, 0, 3, 3, 3, 3, 2 },
+ { "i386DX/20", CPU_386DX, fpus_80386, 1, 20000000, 1, 0, 0x0308, 0, 0, 0, 4, 4, 3, 3, 3 },
+ { "i386DX/25", CPU_386DX, fpus_80386, 2, 25000000, 1, 0, 0x0308, 0, 0, 0, 4, 4, 3, 3, 3 },
+ { "i386DX/33", CPU_386DX, fpus_80386, 3, 33333333, 1, 0, 0x0308, 0, 0, 0, 6, 6, 3, 3, 4 },
+ { "", -1, 0, 0, 0 }
+};
+
+static CPU cpus_i486[] =
+{
+ /*i486*/
+ { "i486SX/16", CPU_i486SX, fpus_none, 0, 16000000, 1, 16000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 3, 3, 3, 3, 2 },
+ { "i486SX/20", CPU_i486SX, fpus_none, 1, 20000000, 1, 20000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 4, 4, 3, 3, 3 },
+ { "i486SX/25", CPU_i486SX, fpus_none, 2, 25000000, 1, 25000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 4, 4, 3, 3, 3 },
+ { "i486SX/33", CPU_i486SX, fpus_none, 3, 33333333, 1, 33333333, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 6, 6, 3, 3, 4 },
+ { "i486SX2/50", CPU_i486SX, fpus_none, 5, 50000000, 2, 25000000, 0x45b, 0, 0, CPU_SUPPORTS_DYNAREC, 8, 8, 6, 6, 2 * 3 },
+ { "i486DX/25", CPU_i486DX, fpus_builtin, 2, 25000000, 1, 25000000, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC, 4, 4, 3, 3, 3 },
+ { "i486DX/33", CPU_i486DX, fpus_builtin, 3, 33333333, 1, 33333333, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC, 6, 6, 3, 3, 4 },
+ { "i486DX/50", CPU_i486DX, fpus_builtin, 5, 50000000, 1, 25000000, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC, 8, 8, 4, 4, 6 },
+ { "i486DX2/40", CPU_i486DX, fpus_builtin, 4, 40000000, 2, 20000000, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 8, 8, 6, 6, 2 * 3 },
+ { "i486DX2/50", CPU_i486DX, fpus_builtin, 5, 50000000, 2, 25000000, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 8, 8, 6, 6, 2 * 3 },
+ { "i486DX2/66", CPU_i486DX, fpus_builtin, 6, 66666666, 2, 33333333, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 12, 12, 6, 6, 2 * 4 },
+ { "", -1, 0, 0, 0 }
+};
+
+
MODEL models[] =
{
{ "[8088] Generic XT clone", ROM_GENXT, "genxt", { { "", cpus_8088 }, { "", NULL }, { "", NULL } }, MODEL_GFX_NONE, 32, 704, 16, model_init, NULL },
midi_open = 0;
}
-// void (*code)() = (void(*)(void))&block->data[BLOCK_START];
+#ifdef CPU_i386
+void codegen_set_rounding_mode(int mode)
+{
+ /*SSE*/
+ cpu_state.new_fp_control = (cpu_state.old_fp_control & ~0x6000) | (mode << 13);
+ /*x87 - used for double -> i64 conversions*/
+ cpu_state.new_fp_control2 = (cpu_state.old_fp_control2 & ~0x0c00) | (mode << 10);
+}
+#else
+void codegen_set_rounding_mode(int mode)
+{
+ /*SSE*/
+ cpu_state.new_fp_control = (cpu_state.old_fp_control & ~0x6000) | (mode << 13);
+ /*x87 - used for double -> i64 conversions*/
+ cpu_state.new_fp_control2 = (cpu_state.old_fp_control2 & ~0x0c00) | (mode << 10);
+}
+#endif
+
+// VIDEO STUFF
+
+int video_timing_read_b;
+int video_timing_read_w;
+int video_timing_read_l;
+
+int video_timing_write_b;
+int video_timing_write_w;
+int video_timing_write_l;
+
+int cycles_lost;
+
+uint8_t fontdat[2048][8];
+uint8_t fontdatm[2048][16];
+uint8_t fontdatw[512][32]; /* Wyse700 font */
+uint8_t fontdat8x12[256][16]; /* MDSI Genius font */
+uint8_t fontdat12x18[256][36]; /* IM1024 font */
+uint8_t fontdatksc5601[16384][32]; /* Korean KSC-5601 font */
+uint8_t fontdatksc5601_user[192][32]; /* Korean KSC-5601 user defined font */
+
+int PCI;
+int readflash;
+int egareads;
+int egawrites;
+int changeframecount;
+PCBITMAP *buffer32;
+static int buffer32size;
+static uae_u8 *tempbuf;
+int vid_resize;
+int xsize, ysize;
+uint64_t timer_freq;
+
+uint8_t edatlookup[4][4];
+uint8_t rotatevga[8][256];
+uint32_t *video_15to32, *video_16to32;
+
+static void *gfxboard_priv;
+
+static mem_mapping_t *pcem_mapping_linear;
+void *pcem_mapping_linear_priv;
+uae_u32 pcem_mapping_linear_offset;
+uint8_t(*pcem_linear_read_b)(uint32_t addr, void *priv);
+uint16_t(*pcem_linear_read_w)(uint32_t addr, void *priv);
+uint32_t(*pcem_linear_read_l)(uint32_t addr, void *priv);
+void (*pcem_linear_write_b)(uint32_t addr, uint8_t val, void *priv);
+void (*pcem_linear_write_w)(uint32_t addr, uint16_t val, void *priv);
+void (*pcem_linear_write_l)(uint32_t addr, uint32_t val, void *priv);
+
+static uint8_t dummy_bread(uint32_t addr, void *p)
+{
+ return 0;
+}
+static uint16_t dummy_wread(uint32_t addr, void *p)
+{
+ return 0;
+}
+static uint32_t dummy_lread(uint32_t addr, void *p)
+{
+ return 0;
+}
+static void dummy_bwrite(uint32_t addr, uint8_t v, void *p)
+{
+
+}
+static void dummy_wwrite(uint32_t addr, uint16_t v, void *p)
+{
+
+}
+static void dummy_lwrite(uint32_t addr, uint32_t v, void *p)
+{
+
+}
+
+uint64_t timer_read(void)
+{
+ return read_processor_time();
+}
+
+void initpcemvideo(void *p, bool swapped)
+{
+ int c, d, e;
+
+ gfxboard_priv = p;
+ has_vlb = 0;
+ timer_freq = syncbase;
+
+ for (c = 0; c < 256; c++)
+ {
+ e = c;
+ for (d = 0; d < 8; d++)
+ {
+ rotatevga[d][c] = e;
+ e = (e >> 1) | ((e & 1) ? 0x80 : 0);
+ }
+ }
+ for (c = 0; c < 4; c++)
+ {
+ for (d = 0; d < 4; d++)
+ {
+ edatlookup[c][d] = 0;
+ if (c & 1) edatlookup[c][d] |= 1;
+ if (d & 1) edatlookup[c][d] |= 2;
+ if (c & 2) edatlookup[c][d] |= 0x10;
+ if (d & 2) edatlookup[c][d] |= 0x20;
+ // printf("Edat %i,%i now %02X\n",c,d,edatlookup[c][d]);
+ }
+ }
+
+ if (!video_15to32)
+ video_15to32 = (uint32_t*)malloc(4 * 65536);
+ for (c = 0; c < 65536; c++) {
+ if (swapped) {
+ video_15to32[c] = (((c >> 10) & 31) << 3) | (((c >> 5) & 31) << 11) | (((c >> 0) & 31) << 19);
+ } else {
+ video_15to32[c] = ((c & 31) << 3) | (((c >> 5) & 31) << 11) | (((c >> 10) & 31) << 19);
+ }
+ }
+
+ if (!video_16to32)
+ video_16to32 = (uint32_t*)malloc(4 * 65536);
+ for (c = 0; c < 65536; c++) {
+ if (swapped) {
+ video_16to32[c] = (((c >> 11) & 31) << 3) | (((c >> 5) & 63) << 10) | (((c >> 0) & 31) << 19);
+ } else {
+ video_16to32[c] = ((c & 31) << 3) | (((c >> 5) & 63) << 10) | (((c >> 11) & 31) << 19);
+ }
+ }
+
+ if (!buffer32) {
+ buffer32 = (PCBITMAP *)calloc(sizeof(PCBITMAP) + sizeof(uint8_t *) * 2048, 1);
+ buffer32->dat = xcalloc(uae_u8, 2048 * 2048 * 4);
+ buffer32->w = 2048;
+ buffer32->h = 2048;
+ for (int i = 0; i < buffer32->h; i++) {
+ buffer32->line[i] = buffer32->dat + buffer32->w * 4 * i;
+ }
+ }
+
+ pcem_linear_read_b = dummy_bread;
+ pcem_linear_read_w = dummy_wread;
+ pcem_linear_read_l = dummy_lread;
+ pcem_linear_write_b = dummy_bwrite;
+ pcem_linear_write_w = dummy_wwrite;
+ pcem_linear_write_l = dummy_lwrite;
+ pcem_mapping_linear = NULL;
+ pcem_mapping_linear_offset = 0;
+
+}
+
+extern void *svga_get_object(void);
+
+uae_u8 pcem_read_io(int port, int index)
+{
+ svga_t *svga = (svga_t*)svga_get_object();
+ if (port == 0x3d5) {
+ return svga->crtc[index];
+ } else {
+ write_log("unknown port %04x!\n", port);
+ abort();
+ }
+}
+
+#if 0
+void update_pcembuffer32(void *buf, int w, int h, int bytesperline)
+{
+ if (!buf) {
+ w = 2048;
+ h = 2048;
+ if (!tempbuf) {
+ tempbuf = xmalloc(uae_u8, w * 4);
+ }
+ buf = tempbuf;
+ bytesperline = 0;
+ }
+ if (!buffer32 || h > buffer32->h) {
+ free(buffer32);
+ buffer32 = (PCBITMAP *)calloc(sizeof(PCBITMAP) + sizeof(uint8_t *) * h, 1);
+ }
+ if (buffer32->w == w && buffer32->h == h && buffer32->line[0] == buf)
+ return;
+ buffer32->w = w;
+ buffer32->h = h;
+ uae_u8 *b = (uae_u8*)buf;
+ for (int i = 0; i < h; i++) {
+ buffer32->line[i] = b;
+ b += bytesperline;
+ }
+}
+#endif
+
+uae_u8 *getpcembuffer32(int x, int y, int yy)
+{
+ return buffer32->line[y + yy] + x * 4;
+}
+
+
+void video_wait_for_buffer(void)
+{
+ //write_log(_T("video_wait_for_buffer\n"));
+}
+void updatewindowsize(int x, int y)
+{
+ gfxboard_resize(x, y, gfxboard_priv);
+}
+
+static void (*pci_card_write)(int func, int addr, uint8_t val, void *priv);
+static uint8_t(*pci_card_read)(int func, int addr, void *priv);
+static void *pci_card_priv;
+
+void put_pci_pcem(uaecptr addr, uae_u8 v)
+{
+ if (pci_card_write) {
+ pci_card_write(0, addr, v, pci_card_priv);
+ }
+}
+uae_u8 get_pci_pcem(uaecptr addr)
+{
+ uae_u8 v = 0;
+ if (pci_card_read) {
+ v = pci_card_read(0, addr, pci_card_priv);
+ }
+ return v;
+}
+
+int pci_add(uint8_t(*read)(int func, int addr, void *priv), void (*write)(int func, int addr, uint8_t val, void *priv), void *priv)
+{
+ pci_card_read = read;
+ pci_card_write = write;
+ pci_card_priv = priv;
+ return 0;
+}
+extern void gfxboard_intreq(void *, int);
+void pci_set_irq_routing(int card, int irq)
+{
+ write_log(_T("pci_set_irq_routing %d %d\n"), card, irq);
+}
+void pci_set_irq(int card, int pci_int)
+{
+ //write_log(_T("pci_set_irq %d %d\n"), card, pci_int);
+ gfxboard_intreq(gfxboard_priv, 1);
+}
+void pci_clear_irq(int card, int pci_int)
+{
+ //write_log(_T("pci_clear_irq %d %d\n"), card, pci_int);
+ gfxboard_intreq(gfxboard_priv, 0);
+}
+int rom_init(rom_t *rom, char *fn, uint32_t address, int size, int mask, int file_offset, uint32_t flags)
+{
+ return 0;
+}
+
+thread_t *thread_create(void (*thread_rout)(void *param), void *param)
+{
+ uae_thread_id tid;
+ uae_start_thread(_T("PCem helper"), thread_rout, param, &tid);
+ return tid;
+}
+void thread_kill(thread_t *handle)
+{
+ uae_end_thread((uae_thread_id*)handle);
+}
+event_t *thread_create_event(void)
+{
+ uae_sem_t sem = { 0 };
+ uae_sem_init(&sem, 1, 0);
+ return sem;
+}
+void thread_set_event(event_t *event)
+{
+ uae_sem_post((uae_sem_t*)&event);
+}
+void thread_reset_event(event_t *_event)
+{
+ uae_sem_init((uae_sem_t*)&_event, 1, 0);
+}
+int thread_wait_event(event_t *event, int timeout)
+{
+ uae_sem_trywait_delay((uae_sem_t*)&event, timeout);
+ return 0;
+}
+void thread_destroy_event(event_t *_event)
+{
+ uae_sem_destroy((uae_sem_t*)&_event);
+}
+
+#define MAX_PCEMMAPPINGS 10
+static mem_mapping_t *pcemmappings[MAX_PCEMMAPPINGS];
+#define PCEMMAPBLOCKSIZE 0x10000
+#define MAX_PCEMMAPBLOCKS (0x10000000 / PCEMMAPBLOCKSIZE)
+mem_mapping_t *pcemmap[MAX_PCEMMAPBLOCKS];
+
+static mem_mapping_t *getmm(uaecptr *addrp)
+{
+ uaecptr addr = *addrp;
+ addr &= 0x0fffffff;
+ int index = addr / PCEMMAPBLOCKSIZE;
+ mem_mapping_t *m = pcemmap[index];
+ if (!m) {
+ write_log(_T("%08x no mapping\n"), addr);
+ }
+ return m;
+}
+
+void put_mem_pcem(uaecptr addr, uae_u32 v, int size)
+{
+ mem_mapping_t *m = getmm(&addr);
+ if (m) {
+ if (size == 0) {
+ m->write_b(addr, v, m->p);
+ } else if (size == 1) {
+ m->write_w(addr, v, m->p);
+ } else if (size == 2) {
+ m->write_l(addr, v, m->p);
+ }
+ }
+}
+uae_u32 get_mem_pcem(uaecptr addr, int size)
+{
+ uae_u32 v = 0;
+ mem_mapping_t *m = getmm(&addr);
+ if (m) {
+ if (size == 0) {
+ v = m->read_b(addr, m->p);
+ } else if (size == 1) {
+ v = m->read_w(addr, m->p);
+ } else if (size == 2) {
+ v = m->read_l(addr, m->p);
+ }
+ }
+ return v;
+}
+
+static void mapping_recalc(mem_mapping_t *mapping)
+{
+ if (mapping->read_b == NULL)
+ mapping->read_b = dummy_bread;
+ if (mapping->read_w == NULL)
+ mapping->read_w = dummy_wread;
+ if (mapping->read_l == NULL)
+ mapping->read_l = dummy_lread;
+ if (mapping->write_b == NULL)
+ mapping->write_b = dummy_bwrite;
+ if (mapping->write_w == NULL)
+ mapping->write_w = dummy_wwrite;
+ if (mapping->write_l == NULL)
+ mapping->write_l = dummy_lwrite;
+
+
+ if (mapping == pcem_mapping_linear || (!pcem_mapping_linear && mapping->size >= 1024 * 1024)) {
+ pcem_mapping_linear = mapping;
+ pcem_mapping_linear_priv = mapping->p;
+ pcem_mapping_linear_offset = mapping->base;
+ if (!mapping->enable) {
+ pcem_linear_read_b = dummy_bread;
+ pcem_linear_read_w = dummy_wread;
+ pcem_linear_read_l = dummy_lread;
+ pcem_linear_write_b = dummy_bwrite;
+ pcem_linear_write_w = dummy_wwrite;
+ pcem_linear_write_l = dummy_lwrite;
+ } else {
+ pcem_linear_read_b = mapping->read_b;
+ pcem_linear_read_w = mapping->read_w;
+ pcem_linear_read_l = mapping->read_l;
+ pcem_linear_write_b = mapping->write_b;
+ pcem_linear_write_w = mapping->write_w;
+ pcem_linear_write_l = mapping->write_l;
+ }
+ }
+
+ for (uae_u32 i = 0; i < mapping->size; i += PCEMMAPBLOCKSIZE) {
+ uae_u32 addr = i + mapping->base;
+ addr &= 0x0fffffff;
+ int offset = addr / PCEMMAPBLOCKSIZE;
+ if (offset >= 0 && offset < MAX_PCEMMAPBLOCKS) {
+ if (mapping->enable) {
+ pcemmap[offset] = mapping;
+ } else {
+ pcemmap[offset] = NULL;
+ }
+ }
+ }
+}
+
+void mem_mapping_addx(mem_mapping_t *mapping,
+ uint32_t base,
+ uint32_t size,
+ uint8_t(*read_b)(uint32_t addr, void *p),
+ uint16_t(*read_w)(uint32_t addr, void *p),
+ uint32_t(*read_l)(uint32_t addr, void *p),
+ void (*write_b)(uint32_t addr, uint8_t val, void *p),
+ void (*write_w)(uint32_t addr, uint16_t val, void *p),
+ void (*write_l)(uint32_t addr, uint32_t val, void *p),
+ uint8_t *exec,
+ uint32_t flags,
+ void *p)
+{
+ mapping->enable = 0;
+ for (int i = 0; i < MAX_PCEMMAPPINGS; i++) {
+ if (pcemmappings[i] == mapping)
+ return;
+ }
+ for (int i = 0; i < MAX_PCEMMAPPINGS; i++) {
+ if (pcemmappings[i] == NULL) {
+ pcemmappings[i] = mapping;
+ mapping->base = base;
+ mapping->size = size;
+ mapping->read_b = read_b;
+ mapping->read_w = read_w;
+ mapping->read_l = read_l;
+ mapping->write_b = write_b;
+ mapping->write_w = write_w;
+ mapping->write_l = write_l;
+ mapping->exec = exec;
+ mapping->flags = flags;
+ mapping->p = p;
+ mapping->next = NULL;
+ mapping_recalc(mapping);
+ return;
+ }
+ }
+}
+
+void mem_mapping_set_handlerx(mem_mapping_t *mapping,
+ uint8_t(*read_b)(uint32_t addr, void *p),
+ uint16_t(*read_w)(uint32_t addr, void *p),
+ uint32_t(*read_l)(uint32_t addr, void *p),
+ void (*write_b)(uint32_t addr, uint8_t val, void *p),
+ void (*write_w)(uint32_t addr, uint16_t val, void *p),
+ void (*write_l)(uint32_t addr, uint32_t val, void *p))
+{
+ mapping->read_b = read_b;
+ mapping->read_w = read_w;
+ mapping->read_l = read_l;
+ mapping->write_b = write_b;
+ mapping->write_w = write_w;
+ mapping->write_l = write_l;
+ mapping_recalc(mapping);
+}
+
+void mem_mapping_set_px(mem_mapping_t *mapping, void *p)
+{
+ mapping->p = p;
+}
+
+void pci_add_specific(int card, uint8_t(*read)(int func, int addr, void *priv), void (*write)(int func, int addr, uint8_t val, void *priv), void *priv)
+{
+}
+
+void mca_add(uint8_t(*read)(int addr, void *priv), void (*write)(int addr, uint8_t val, void *priv), void (*reset)(void *priv), void *priv)
+{
+}
+
+#define MAX_IO_PORT 0x10000
+static uint8_t(*port_inb[MAX_IO_PORT])(uint16_t addr, void *priv);
+static uint16_t(*port_inw[MAX_IO_PORT])(uint16_t addr, void *priv);
+static uint32_t(*port_inl[MAX_IO_PORT])(uint16_t addr, void *priv);
+static void(*port_outb[MAX_IO_PORT])(uint16_t addr, uint8_t val, void *priv);
+static void(*port_outw[MAX_IO_PORT])(uint16_t addr, uint16_t val, void *priv);
+static void(*port_outl[MAX_IO_PORT])(uint16_t addr, uint32_t val, void *priv);
+static void *port_priv[MAX_IO_PORT];
+
+void put_io_pcem(uaecptr addr, uae_u32 v, int size)
+{
+ addr &= MAX_IO_PORT - 1;
+ if (size == 0) {
+ if (port_outb[addr])
+ port_outb[addr](addr, v, port_priv[addr]);
+ } else if (size == 1) {
+ if (port_outw[addr]) {
+ port_outw[addr](addr, v, port_priv[addr]);
+ } else {
+ put_io_pcem(addr + 0, v >> 0, 0);
+ put_io_pcem(addr + 1, v >> 8, 0);
+ }
+ } else if (size == 2) {
+ if (port_outl[addr]) {
+ port_outl[addr](addr, v, port_priv[addr]);
+ } else {
+ put_io_pcem(addr + 0, v >> 16, 1);
+ put_io_pcem(addr + 2, v >> 0, 1);
+ }
+ }
+}
+uae_u32 get_io_pcem(uaecptr addr, int size)
+{
+ uae_u32 v = 0;
+ addr &= MAX_IO_PORT - 1;
+ if (size == 0) {
+ if (port_inb[addr])
+ v = port_inb[addr](addr, port_priv[addr]);
+ } else if (size == 1) {
+ if (port_inw[addr]) {
+ v = port_inw[addr](addr, port_priv[addr]);
+ } else {
+ v = get_io_pcem(addr + 0, 0) << 0;
+ v |= get_io_pcem(addr + 1, 0) << 8;
+ }
+ } else if (size == 2) {
+ if (port_inl[addr]) {
+ v = port_inl[addr](addr, port_priv[addr]);
+ } else {
+ v = get_io_pcem(addr + 0, 1) << 16;
+ v |= get_io_pcem(addr + 2, 1) << 0;
+ }
+ }
+ return v;
+}
+
+void io_sethandlerx(uint16_t base, int size,
+ uint8_t(*inb)(uint16_t addr, void *priv),
+ uint16_t(*inw)(uint16_t addr, void *priv),
+ uint32_t(*inl)(uint16_t addr, void *priv),
+ void (*outb)(uint16_t addr, uint8_t val, void *priv),
+ void (*outw)(uint16_t addr, uint16_t val, void *priv),
+ void (*outl)(uint16_t addr, uint32_t val, void *priv),
+ void *priv)
+{
+ if (base + size > MAX_IO_PORT)
+ return;
+
+ for (int i = 0; i < size; i++) {
+ int io = base + i;
+ port_inb[io] = inb;
+ port_inw[io] = inw;
+ port_inl[io] = inl;
+ port_outb[io] = outb;
+ port_outw[io] = outw;
+ port_outl[io] = outl;
+ port_priv[io] = priv;
+ }
+}
+
+void io_removehandlerx(uint16_t base, int size,
+ uint8_t(*inb)(uint16_t addr, void *priv),
+ uint16_t(*inw)(uint16_t addr, void *priv),
+ uint32_t(*inl)(uint16_t addr, void *priv),
+ void (*outb)(uint16_t addr, uint8_t val, void *priv),
+ void (*outw)(uint16_t addr, uint16_t val, void *priv),
+ void (*outl)(uint16_t addr, uint32_t val, void *priv),
+ void *priv)
+{
+ if (base + size > MAX_IO_PORT)
+ return;
+
+ for (int i = 0; i < size; i++) {
+ int io = base + i;
+ port_inb[io] = NULL;
+ port_inw[io] = NULL;
+ port_inl[io] = NULL;
+ port_outb[io] = NULL;
+ port_outw[io] = NULL;
+ port_outl[io] = NULL;
+ }
+}
+
+void mem_mapping_set_addrx(mem_mapping_t *mapping, uint32_t base, uint32_t size)
+{
+ mapping->enable = 0;
+ mapping_recalc(mapping);
+ mapping->enable = 1;
+ mapping->base = base;
+ mapping->size = size;
+ mapping_recalc(mapping);
+}
+
+void mem_mapping_disablex(mem_mapping_t *mapping)
+{
+ mapping->enable = 0;
+ mapping_recalc(mapping);
+}
+
+void mem_mapping_enablex(mem_mapping_t *mapping)
+{
+ mapping->enable = 1;
+ mapping_recalc(mapping);
+}
+
uint16_t mem_read_romextw(uint32_t addr, void *priv);
uint32_t mem_read_romextl(uint32_t addr, void *priv);
-void sound_speed_changed(void);
extern int SOUNDBUFLEN;
extern int32_t *x86_sndbuffer[2];
extern bool x86_sndbuffer_filled[2];
#include "pit.h"
#include "video.h"
-extern int output;
int intclear;
int keywaiting=0;
int pic_intpending;
}
}
-void x86_ack_keyboard(void);
-
void pic_write(uint16_t addr, uint8_t val, void *priv)
{
int c;
if ((val&0xE0)==0x60)
{
// pclog("Specific EOI - %02X %i\n",pic.ins,1<<(val&7));
-
- if ((pic.ins & (1 << 1)) && ((val & 7) == 1)) {
- x86_ack_keyboard();
- }
-
- pic.ins&=~(1<<(val&7));
+ pic.ins&=~(1<<(val&7));
pic_update_mask(&pic.mask2, pic.ins);
if (val == 2 && (pic2.pend&~pic2.mask)&~pic2.mask2)
pic.pend |= (1 << 2);
if (c == 2 && (pic2.pend&~pic2.mask)&~pic2.mask2)
pic.pend |= (1 << 2);
- if (c == 1) {
- x86_ack_keyboard();
- }
-
if (c==1 && keywaiting)
{
intclear&=~1;
void picint(uint16_t num)
{
- if (AT && num == (1 << 2))
+ if ((AT || romset == ROM_XI8088) && num == (1 << 2))
num = 1 << 9;
// pclog("picint : %04X\n", num);
// if (num == 0x10) pclog("PICINT 10\n");
{
int c = 0;
while (!(num & (1 << c))) c++;
- if (AT && c == 2)
+ if ((AT || romset == ROM_XI8088) && num == (1 << 2))
{
c = 9;
num = 1 << 9;
if (!num)
return;
while (!(num & (1 << c))) c++;
- if (AT && c == 2)
+ if ((AT || romset == ROM_XI8088) && num == (1 << 2))
{
c = 9;
num = 1 << 9;
//Tyrian writes 4300 or 17512
int displine;
-double PITCONST;
+uint64_t PITCONST;
+uint64_t CGACONST;
+uint64_t MDACONST;
+uint64_t VGACONST1, VGACONST2;
+uint64_t RTCCONST;
+
float cpuclock;
float isa_timing, bus_timing;
{
// printf("PIT clock %f\n",clock);
cpuclock=clock;
- PITCONST=clock/1193182.0;
- CGACONST=(clock/(19687503.0/11.0));
- MDACONST=(clock/2032125.0);
- VGACONST1=(clock/25175000.0);
- VGACONST2=(clock/28322000.0);
+ PITCONST = (uint64_t)(clock / 1193182.0 * (float)(1ull << 32));
+ CGACONST = (uint64_t)((clock / (19687503.0/11.0)) * (float)(1ull << 32));
+ MDACONST = (uint64_t)((clock / 2032125.0) * (float)(1ull << 32));
+ VGACONST1 = (uint64_t)((clock / 25175000.0) * (float)(1ull << 32));
+ VGACONST2 = (uint64_t)((clock / 28322000.0) * (float)(1ull << 32));
isa_timing = clock/8000000.0;
bus_timing = clock/(double)cpu_busspeed;
video_updatetiming();
// pclog("PITCONST=%f CGACONST=%f\n", PITCONST, CGACONST);
// pclog("CPUMULTI=%g\n", ((14318184.0*(double)(1 << TIMER_SHIFT)) / (double)models[model].cpu[cpu_manufacturer].cpus[cpu].rspeed));
- xt_cpu_multi = (int)((14318184.0*(double)(1 << TIMER_SHIFT)) / (double)cpu_get_speed());
+ xt_cpu_multi = (uint64_t)((14318184.0*(double)(1ull << 32)) / (double)cpu_get_speed());
// pclog("egacycles %i egacycles2 %i temp %f clock %f\n",egacycles,egacycles2,temp,clock);
/* if (video_recalctimings)
video_recalctimings();*/
- RTCCONST=clock/32768.0;
- TIMER_USEC = (int)((clock / 1000000.0f) * (float)(1 << TIMER_SHIFT));
+ RTCCONST = (uint64_t)((clock / 32768.0) * (float)(1ull << 32));
+ TIMER_USEC = (uint64_t)((clock / 1000000.0) * (float)(1ull << 32));
device_speed_changed();
}
void pit_reset(PIT *pit)
{
memset(pit, 0, sizeof(PIT));
- pit->l[0] = 0xFFFF; pit->c[0] = 0xFFFF*PITCONST;
- pit->l[1] = 0xFFFF; pit->c[1] = 0xFFFF*PITCONST;
- pit->l[2] = 0xFFFF; pit->c[2] = 0xFFFF*PITCONST;
+ pit->l[0] = 0xFFFF;
+ pit->l[1] = 0xFFFF;
+ pit->l[2] = 0xFFFF;
pit->m[0] = pit->m[1] = pit->m[2] = 0;
pit->ctrls[0] = pit->ctrls[1] = pit->ctrls[2] = 0;
pit->thit[0]=1;
pit->using_timer[0] = pit->using_timer[1] = pit->using_timer[2] = 1;
}
-void clearpit()
-{
- pit.c[0]=(pit.l[0]<<2);
-}
-
float pit_timer0_freq()
{
if (pit.l[0])
pit->out[t] = out;
}
+static int pit_read_timer(PIT *pit, int t)
+{
+// pclog("pit_read_timer: t=%i using_timer=%i m=%i enabled=%i\n", t, pit->using_timer[t], pit->m[t], timer_is_enabled(&pit->timer[t]));
+ if (pit->using_timer[t] && !(pit->m[t] == 3 && !pit->gate[t]) && timer_is_enabled(&pit->timer[t]))
+ {
+ int read = (int)((timer_get_remaining_u64(&pit->timer[t])) / PITCONST);
+// pclog(" read %i %08x %016llx\n", t, read, timer_get_remaining_u64(&pit->timer[t]));
+ if (pit->m[t] == 2)
+ read++;
+ if (read < 0)
+ read = 0;
+ if (read > 0x10000)
+ read = 0x10000;
+ if (pit->m[t] == 3)
+ read <<= 1;
+ return read;
+ }
+ if (pit->m[t] == 2)
+ return pit->count[t] + 1;
+ return pit->count[t];
+}
+
+/*Dump timer count back to pit->count[], and disable timer. This should be used
+ when stopping a PIT timer, to ensure the correct value can be read back.*/
+static void pit_dump_and_disable_timer(PIT *pit, int t)
+{
+ if (pit->using_timer[t] && timer_is_enabled(&pit->timer[t]))
+ {
+ pit->count[t] = pit_read_timer(pit, t);
+ timer_disable(&pit->timer[t]);
+ }
+}
+
static void pit_load(PIT *pit, int t)
{
int l = pit->l[t] ? pit->l[t] : 0x10000;
- timer_clock();
+
pit->newcount[t] = 0;
pit->disabled[t] = 0;
-// pclog("pit_load: t=%i l=%x\n", t, l);
+// pclog("pit_load: t=%i l=%x m=%i %016llx\n", t, l, pit->m[t], PITCONST);
switch (pit->m[t])
{
case 0: /*Interrupt on terminal count*/
pit->count[t] = l;
- pit->c[t] = (int)((l << TIMER_SHIFT) * PITCONST);
+ if (pit->using_timer[t])
+ timer_set_delay_u64(&pit->timer[t], (uint64_t)(l * PITCONST));
pit_set_out(pit, t, 0);
pit->thit[t] = 0;
pit->enabled[t] = pit->gate[t];
if (pit->initial[t])
{
pit->count[t] = l - 1;
- pit->c[t] = (int)(((l - 1) << TIMER_SHIFT) * PITCONST);
+ if (pit->using_timer[t])
+ timer_set_delay_u64(&pit->timer[t], (uint64_t)((l - 1) * PITCONST));
pit_set_out(pit, t, 1);
pit->thit[t] = 0;
}
if (pit->initial[t])
{
pit->count[t] = l;
- pit->c[t] = (int)((((l + 1) >> 1) << TIMER_SHIFT) * PITCONST);
+ if (pit->using_timer[t])
+ timer_set_delay_u64(&pit->timer[t], (uint64_t)(((l + 1) >> 1) * PITCONST));
pit_set_out(pit, t, 1);
pit->thit[t] = 0;
}
pit->enabled[t] = pit->gate[t];
-// pclog("pit_load: square wave mode c=%x\n", pit->c[t]);
+// pclog("pit_load: square wave mode c=%x\n", );
break;
case 4: /*Software triggered stobe*/
if (!pit->thit[t] && !pit->initial[t])
else
{
pit->count[t] = l;
- pit->c[t] = (int)((l << TIMER_SHIFT) * PITCONST);
+ if (pit->using_timer[t])
+ timer_set_delay_u64(&pit->timer[t], (uint64_t)(l * PITCONST));
pit_set_out(pit, t, 0);
pit->thit[t] = 0;
}
}
pit->initial[t] = 0;
pit->running[t] = pit->enabled[t] && pit->using_timer[t] && !pit->disabled[t];
- timer_update_outstanding();
+ if (pit->using_timer[t] && !pit->running[t])
+ pit_dump_and_disable_timer(pit, t);
+
// pclog("pit_load: t=%i running=%i thit=%i enabled=%i m=%i l=%x c=%g gate=%i\n", t, pit.running[t], pit.thit[t], pit.enabled[t], pit.m[t], pit.l[t], pit.c[t], pit.gate[t]);
}
{
case 0: /*Interrupt on terminal count*/
case 4: /*Software triggered stobe*/
+ if (pit->using_timer[t] && !pit->running[t])
+ timer_set_delay_u64(&pit->timer[t], (uint64_t)(l * PITCONST));
pit->enabled[t] = gate;
break;
case 1: /*Hardware retriggerable one-shot*/
if (gate && !pit->gate[t])
{
pit->count[t] = l;
- pit->c[t] = (int)((l << TIMER_SHIFT) * PITCONST);
+ if (pit->using_timer[t])
+ timer_set_delay_u64(&pit->timer[t], (uint64_t)(l * PITCONST));
pit_set_out(pit, t, 0);
pit->thit[t] = 0;
pit->enabled[t] = 1;
if (gate && !pit->gate[t])
{
pit->count[t] = l - 1;
- pit->c[t] = (int)(((l - 1) << TIMER_SHIFT) * PITCONST);
+ if (pit->using_timer[t])
+ timer_set_delay_u64(&pit->timer[t], (uint64_t)(l * PITCONST));
pit_set_out(pit, t, 1);
pit->thit[t] = 0;
}
if (gate && !pit->gate[t])
{
pit->count[t] = l;
- pit->c[t] = (int)((((l + 1) >> 1) << TIMER_SHIFT) * PITCONST);
+ if (pit->using_timer[t])
+ timer_set_delay_u64(&pit->timer[t], (uint64_t)(((l + 1) >> 1) * PITCONST));
pit_set_out(pit, t, 1);
pit->thit[t] = 0;
}
}
pit->gate[t] = gate;
pit->running[t] = pit->enabled[t] && pit->using_timer[t] && !pit->disabled[t];
+ if (pit->using_timer[t] && !pit->running[t])
+ pit_dump_and_disable_timer(pit, t);
// pclog("pit_set_gate: t=%i gate=%i\n", t, gate);
}
void pit_set_gate(PIT *pit, int t, int gate)
{
+// pclog("pit_set_gate: t=%i gate=%i\n", t, gate);
if (pit->disabled[t])
{
pit->gate[t] = gate;
return;
}
- timer_process();
-
pit_set_gate_no_timer(pit, t, gate);
-
- timer_update_outstanding();
-// pclog("pit_set_gate: t=%i gate=%i\n", t, gate);
}
static void pit_over(PIT *pit, int t)
if (pit->disabled[t])
{
pit->count[t] += 0xffff;
- pit->c[t] += (int)((0xffff << TIMER_SHIFT) * PITCONST);
+ if (pit->using_timer[t])
+ timer_advance_u64(&pit->timer[t], (uint64_t)(0xffff * PITCONST));
return;
}
-// if (!t) pclog("pit_over: t=%i l=%x c=%x %i hit=%i\n", t, pit->l[t], pit.c[t], pit.c[t] >> TIMER_SHIFT, pit.thit[t]);
+// if (t == 2) pclog("pit_over: t=%i l=%x c=%llx hit=%i %016llx\n", t, pit->l[t], timer_get_remaining_u64(&pit->timer[t]), pit->thit[t], tsc);
switch (pit->m[t])
{
case 0: /*Interrupt on terminal count*/
pit_set_out(pit, t, 1);
pit->thit[t] = 1;
pit->count[t] += 0xffff;
- pit->c[t] += (int)((0xffff << TIMER_SHIFT) * PITCONST);
+ if (pit->using_timer[t])
+ timer_advance_u64(&pit->timer[t], (uint64_t)(0xffff * PITCONST));
break;
case 2: /*Rate generator*/
pit->count[t] += l;
- pit->c[t] += (int)((l << TIMER_SHIFT) * PITCONST);
+ if (pit->using_timer[t])
+ timer_advance_u64(&pit->timer[t], (uint64_t)(l * PITCONST));
pit_set_out(pit, t, 0);
pit_set_out(pit, t, 1);
break;
{
pit_set_out(pit, t, 0);
pit->count[t] += (l >> 1);
- pit->c[t] += (int)(((l >> 1) << TIMER_SHIFT) * PITCONST);
+ if (pit->using_timer[t])
+ timer_advance_u64(&pit->timer[t], (uint64_t)((l >> 1) * PITCONST));
}
else
{
pit_set_out(pit, t, 1);
pit->count[t] += ((l + 1) >> 1);
- pit->c[t] = (int)((((l + 1) >> 1) << TIMER_SHIFT) * PITCONST);
+ if (pit->using_timer[t])
+ timer_advance_u64(&pit->timer[t], (uint64_t)(((l + 1) >> 1) * PITCONST));
}
// if (!t) pclog("pit_over: square wave mode c=%x %lli %f\n", pit.c[t], tsc, PITCONST);
break;
{
pit->newcount[t] = 0;
pit->count[t] += l;
- pit->c[t] += (int)((l << TIMER_SHIFT) * PITCONST);
+ if (pit->using_timer[t])
+ timer_advance_u64(&pit->timer[t], (uint64_t)(l * PITCONST));
}
else
{
pit->thit[t] = 1;
pit->count[t] += 0xffff;
- pit->c[t] += (int)((0xffff << TIMER_SHIFT) * PITCONST);
+ if (pit->using_timer[t])
+ timer_advance_u64(&pit->timer[t], (uint64_t)(0xffff * PITCONST));
}
break;
case 5: /*Hardware triggered strove*/
}
pit->thit[t] = 1;
pit->count[t] += 0xffff;
- pit->c[t] += (int)((0xffff << TIMER_SHIFT) * PITCONST);
+ if (pit->using_timer[t])
+ timer_advance_u64(&pit->timer[t], (uint64_t)(0xffff * PITCONST));
break;
}
pit->running[t] = pit->enabled[t] && pit->using_timer[t] && !pit->disabled[t];
-}
-
-int pit_get_timer_0()
-{
- int read = (int)((pit.c[0] + ((1 << TIMER_SHIFT) - 1)) / PITCONST) >> TIMER_SHIFT;
-//pclog("pit_get_timer_0: t=%i using_timer=%i m=%i\n", 0, pit.using_timer[0], pit.m[0]);
- if (pit.m[0] == 2)
- read++;
- if (read < 0)
- read = 0;
- if (read > 0x10000)
- read = 0x10000;
- if (pit.m[0] == 3)
- read <<= 1;
- return read;
-}
-
-static int pit_read_timer(PIT *pit, int t)
-{
- timer_clock();
-// pclog("pit_read_timer: t=%i using_timer=%i m=%i\n", t, pit.using_timer[t], pit.m[t]);
- if (pit->using_timer[t] && !(pit->m[t] == 3 && !pit->gate[t]))
- {
- int read = (int)((pit->c[t] + ((1 << TIMER_SHIFT) - 1)) / PITCONST) >> TIMER_SHIFT;
- if (pit->m[t] == 2)
- read++;
- if (read < 0)
- read = 0;
- if (read > 0x10000)
- read = 0x10000;
- if (pit->m[t] == 3)
- read <<= 1;
- return read;
- }
- if (pit->m[t] == 2)
- return pit->count[t] + 1;
- return pit->count[t];
+ if (pit->using_timer[t] && !pit->running[t])
+ pit_dump_and_disable_timer(pit, t);
}
void pit_write(uint16_t addr, uint8_t val, void *p)
{
PIT *pit = (PIT *)p;
int t;
-// /*if (val != 0x40) */pclog("Write PIT %04X %02X %04X:%08X %i %i\n",addr,val,CS,pc,ins, pit->gate[0]);
+// /*if (val != 0x40) */pclog("Write PIT %04X %02X %04X:%08X %i %i\n",addr,val,CS,cpu_state.pc,ins, pit->gate[0]);
switch (addr&3)
{
PIT *pit = (PIT *)p;
int t;
uint8_t temp = 0xff;
-// printf("Read PIT %04X ",addr);
+// printf("Read PIT %04X\n",addr);
switch (addr&3)
{
case 0: case 1: case 2: /*Timers*/
timer_process();
if (pit->using_timer[t] && !using_timer)
pit->count[t] = pit_read_timer(pit, t);
- if (!pit->using_timer[t] && using_timer)
- pit->c[t] = (int)((pit->count[t] << TIMER_SHIFT) * PITCONST);
+ pit->running[t] = pit->enabled[t] && using_timer && !pit->disabled[t];
+ if (!pit->using_timer[t] && using_timer && pit->running[t])
+ timer_set_delay_u64(&pit->timer[t], (uint64_t)(pit->count[t] * PITCONST));
+ else if (!pit->running[t])
+ timer_disable(&pit->timer[t]);
pit->using_timer[t] = using_timer;
- pit->running[t] = pit->enabled[t] && pit->using_timer[t] && !pit->disabled[t];
- timer_update_outstanding();
}
void pit_set_out_func(PIT *pit, int t, void (*func)(int new_out, int old_out))
pit.pit_nr[2].nr = 2;
pit.pit_nr[0].pit = pit.pit_nr[1].pit = pit.pit_nr[2].pit = &pit;
- timer_add(pit_timer_over, &pit.c[0], &pit.running[0], (void *)&pit.pit_nr[0]);
- timer_add(pit_timer_over, &pit.c[1], &pit.running[1], (void *)&pit.pit_nr[1]);
- timer_add(pit_timer_over, &pit.c[2], &pit.running[2], (void *)&pit.pit_nr[2]);
+ timer_add(&pit.timer[0], pit_timer_over, (void *)&pit.pit_nr[0], 0);
+ timer_add(&pit.timer[1], pit_timer_over, (void *)&pit.pit_nr[1], 0);
+ timer_add(&pit.timer[2], pit_timer_over, (void *)&pit.pit_nr[2], 0);
pit_set_out_func(&pit, 0, pit_irq0_timer);
pit_set_out_func(&pit, 1, pit_null_timer);
pit2.pit_nr[0].nr = 0;
pit2.pit_nr[0].pit = &pit2;
- timer_add(pit_timer_over, &pit2.c[0], &pit2.running[0], (void *)&pit2.pit_nr[0]);
+ timer_add(&pit2.timer[0], pit_timer_over, (void *)&pit2.pit_nr[0], 0);
pit_set_out_func(&pit, 0, pit_irq0_ps2);
pit_set_out_func(&pit2, 0, pit_nmi_ps2);
-extern double PITCONST;
+extern uint64_t PITCONST;
void pit_init();
void pit_ps2_init();
void pit_reset();
+#ifdef __cplusplus
+extern "C" {
+#endif
+ #include <stdint.h>
+
+ void keyboard_init();
+ void keyboard_close();
+ void keyboard_poll_host();
+ extern uint8_t pcem_key[272];
+ extern int rawinputkey[272];
+
+#ifndef __unix
+ #define KEY_LCONTROL 0x1d
+ #define KEY_RCONTROL (0x1d | 0x80)
+ #define KEY_END (0x4f | 0x80)
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
-
-void midi_write(uint8_t);
+void midi_init();
+void midi_close();
+void midi_write(uint8_t val);
+int midi_get_num_devs();
+void midi_get_dev_name(int num, char *s);
-extern int mouse_buttons;
\ No newline at end of file
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ void mouse_init();
+ void mouse_close();
+ extern int mouse_buttons;
+ void mouse_poll_host();
+ void mouse_get_mickeys(int *x, int *y, int *z);
+ extern int mousecapture;
+#ifdef __cplusplus
+}
+#endif
+#ifndef _ROM_H_
+#define _ROM_H_
+
+FILE *romfopen(char *fn, char *mode);
int rom_present(char *fn);
+
+typedef struct rom_t
+{
+ uint8_t *rom;
+ uint32_t mask;
+ mem_mapping_t mapping;
+} rom_t;
+
+int rom_init(rom_t *rom, char *fn, uint32_t address, int size, int mask, int file_offset, uint32_t flags);
+int rom_init_interleaved(rom_t *rom, char *fn_low, char *fn_high, uint32_t address, int size, int mask, int file_offset, uint32_t flags);
+
+uint8_t rom_read(uint32_t addr, void *p);
+uint16_t rom_readw(uint32_t addr, void *p);
+uint32_t rom_readl(uint32_t addr, void *p);
+
+#endif
stat = 1;
serial->iir = 6;
}
- else if ((serial->ier & 1) && (serial->int_status & SERIAL_INT_RECEIVE)) /*Recieved data available*/
+ else if ((serial->ier & 1) && (serial->int_status & SERIAL_INT_RECEIVE)) /*Received data available*/
{
stat = 1;
serial->iir = 4;
serial_update_ints(serial);
break;
case 2:
- serial->fcr = val;
+ if (serial->has_fifo)
+ serial->fcr = val;
break;
case 3:
serial->lcr = val;
serial_update_ints(serial);
temp = serial_read_fifo(serial);
if (serial->fifo_read != serial->fifo_write)
- serial->recieve_delay = 1000 * TIMER_USEC;
+ timer_set_delay_u64(&serial->receive_timer, 1000 * TIMER_USEC);
break;
case 1:
if (serial->lcr & 0x80)
return temp;
}
-void serial_recieve_callback(void *p)
+void serial_receive_callback(void *p)
{
SERIAL *serial = (SERIAL *)p;
- serial->recieve_delay = 0;
-
if (serial->fifo_read != serial->fifo_write)
{
serial->lsr |= 1;
}
/*Tandy might need COM1 at 2f8*/
-void serial1_init(uint16_t addr, int irq)
+void serial1_init(uint16_t addr, int irq, int has_fifo)
{
memset(&serial1, 0, sizeof(serial1));
io_sethandler(addr, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, &serial1);
serial1.irq = irq;
serial1.addr = addr;
serial1.rcr_callback = NULL;
- timer_add(serial_recieve_callback, &serial1.recieve_delay, &serial1.recieve_delay, &serial1);
+ timer_add(&serial1.receive_timer, serial_receive_callback, &serial1, 0);
+ serial1.has_fifo = has_fifo;
}
void serial1_set(uint16_t addr, int irq)
{
io_removehandler(serial1.addr, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, &serial1);
}
-void serial2_init(uint16_t addr, int irq)
+void serial2_init(uint16_t addr, int irq, int has_fifo)
{
memset(&serial2, 0, sizeof(serial2));
io_sethandler(addr, 0x0008, serial_read, NULL, NULL, serial_write, NULL, NULL, &serial2);
serial2.irq = irq;
serial2.addr = addr;
serial2.rcr_callback = NULL;
- timer_add(serial_recieve_callback, &serial2.recieve_delay, &serial2.recieve_delay, &serial2);
+ timer_add(&serial2.receive_timer, serial_receive_callback, &serial2, 0);
+ serial2.has_fifo = has_fifo;
}
void serial2_set(uint16_t addr, int irq)
{
-void serial1_init(uint16_t addr, int irq);
-void serial2_init(uint16_t addr, int irq);
+#include "timer.h"
+
+void serial1_init(uint16_t addr, int irq, int has_fifo);
+void serial2_init(uint16_t addr, int irq, int has_fifo);
void serial1_set(uint16_t addr, int irq);
void serial2_set(uint16_t addr, int irq);
void serial1_remove();
void serial2_remove();
void serial_reset();
-typedef struct SERIAL
+struct SERIAL;
+
+typedef struct
{
uint8_t lsr,thr,mctrl,rcr,iir,ier,lcr,msr;
uint8_t dlab1,dlab2;
void *rcr_callback_p;
uint8_t fifo[256];
int fifo_read, fifo_write;
+ int has_fifo;
- int recieve_delay;
+ pc_timer_t receive_timer;
} SERIAL;
void serial_write_fifo(SERIAL *serial, uint8_t dat);
+#include "timer.h"
+
+void sound_add_handler(void (*get_buffer)(int32_t *buffer, int len, void *p), void *p);
+
+extern int sound_card_current;
+
+int sound_card_available(int card);
+char *sound_card_getname(int card);
+struct device_t *sound_card_getdevice(int card);
+int sound_card_has_config(int card);
+char *sound_card_get_internal_name(int card);
+int sound_card_get_from_internal_name(char *s);
+void sound_card_init();
+void sound_set_cd_volume(unsigned int vol_l, unsigned int vol_r);
+
+#define CD_FREQ 44100
+#define CD_BUFLEN (CD_FREQ / 10)
-#define MAXSOUNDBUFLEN (8192)
extern int sound_pos_global;
-void sound_add_handler(void(*get_buffer)(int32_t *buffer, int len, void *p), void *p);
+void sound_speed_changed();
+
+void sound_init();
void sound_reset();
-void sound_set_cd_volume(unsigned int vol_l, unsigned int vol_r);
\ No newline at end of file
+
+void initalmain(int argc, char *argv[]);
+void inital();
+
+void givealbuffer(int32_t *buf);
+void givealbuffer_cd(int16_t *buf);
+
+extern int sound_buf_len;
+void sound_update_buf_length();
+
+extern int sound_gain;
+
+extern int SOUNDBUFLEN;
+#define MAXSOUNDBUFLEN (48000 / 10)
void *cms_init()
{
- cms_t *cms = (cms_t*)malloc(sizeof(cms_t));
+ cms_t *cms = malloc(sizeof(cms_t));
memset(cms, 0, sizeof(cms_t));
pclog("cms_init\n");
free(cms);
}
-#if 0
+
device_t cms_device =
{
"Creative Music System / Game Blaster",
NULL,
NULL
};
-#endif
\ No newline at end of file
return opl[nr].is_opl3 ? 0 : 0xff;
}
-static Bit32s buffer_32[8192 * 2];
-
void opl2_update(int nr, int16_t *buffer, int samples)
{
int c;
+ Bit32s buffer_32[samples];
opl[nr].chip.GenerateBlock2(samples, buffer_32);
void opl3_update(int nr, int16_t *buffer, int samples)
{
int c;
+ Bit32s buffer_32[samples*2];
if (opl[nr].opl_emu)
{
+#ifdef __cplusplus
+extern "C" {
+#endif
void opl_init(void (*timer_callback)(void *param, int timer, int64_t period), void *timer_param, int nr, int is_opl3, int opl_emu);
void opl_write(int nr, uint16_t addr, uint8_t val);
uint8_t opl_read(int nr, uint16_t addr);
void opl_timer_over(int nr, int timer);
void opl2_update(int nr, int16_t *buffer, int samples);
void opl3_update(int nr, int16_t *buffer, int samples);
+#ifdef __cplusplus
+}
+#endif
+#ifndef SOUND_EMU8K_H
+#define SOUND_EMU8K_H
/* All these defines are in samples, not in bytes. */
#define EMU8K_MEM_ADDRESS_MASK 0xFFFFFF
0xD308 0xD308 0xD308 0xD308 0xD308 0xD308 0xD3019 0xD32A 0xD34C 0xD36E 0xD36E 0xD36E
0x0001 0x0001 0x0001 0x0001 0x0001 0x0002 0x0002 0x0002 0x0002 0x0002 0x0002 0x0002
*/
+
+#endif /* SOUND_EMU8K_H */
#include "ibm.h"
#include "io.h"
+#include "pic.h"
#include "plat-midi.h"
#include "sound_mpu401_uart.h"
STATUS_INPUT_NOT_READY = 0x80
};
+static void mpu401_uart_raise_irq(void *p)
+{
+ mpu401_uart_t *mpu = (mpu401_uart_t *)p;
+
+ if (mpu->irq != -1)
+ picint(1 << mpu->irq);
+}
+
static void mpu401_uart_write(uint16_t addr, uint8_t val, void *p)
{
mpu401_uart_t *mpu = (mpu401_uart_t *)p;
switch (val)
{
case 0xff: /*Reset*/
+ // From Roland: "An ACK will not be sent back upon sending a SYSTEM RESET to leave the UART MODE ($3F)."
+ // But actual behaviour is weird. For example, the MPU401 port test in the AZT1605 drivers for Windows NT
+ // want this to return an Ack but the IRQ test in the same driver wants this to raise no interrupts!
mpu->rx_data = 0xfe; /*Acknowledge*/
- mpu->status = 0;
mpu->uart_mode = 0;
+ if (mpu->is_aztech)
+ mpu->status = STATUS_OUTPUT_NOT_READY;
+ else
+ {
+ mpu->status = 0;
+ mpu401_uart_raise_irq(p);
+ }
break;
case 0x3f: /*Enter UART mode*/
mpu->rx_data = 0xfe; /*Acknowledge*/
- mpu->status = 0;
mpu->uart_mode = 1;
+ if (mpu->is_aztech)
+ {
+ mpu->status = STATUS_OUTPUT_NOT_READY;
+ mpu401_uart_raise_irq(p);
+ }
+ else
+ mpu->status = 0;
break;
}
return;
return mpu->status;
/*Data*/
- mpu->status |= STATUS_INPUT_NOT_READY;
+ mpu->status = STATUS_INPUT_NOT_READY;
return mpu->rx_data;
}
-void mpu401_uart_init(mpu401_uart_t *mpu, uint16_t addr)
+void mpu401_uart_init(mpu401_uart_t *mpu, uint16_t addr, int irq, int is_aztech)
{
mpu->status = STATUS_INPUT_NOT_READY;
mpu->uart_mode = 0;
+ mpu->addr = addr;
+ mpu->irq = irq;
+ mpu->is_aztech = is_aztech;
io_sethandler(addr, 0x0002, mpu401_uart_read, NULL, NULL, mpu401_uart_write, NULL, NULL, mpu);
}
+
+void mpu401_uart_update_addr(mpu401_uart_t *mpu, uint16_t addr)
+{
+ io_removehandler(mpu->addr, 0x0002, mpu401_uart_read, NULL, NULL, mpu401_uart_write, NULL, NULL, mpu);
+ mpu->addr = addr;
+ if (addr != 0)
+ io_sethandler(addr, 0x0002, mpu401_uart_read, NULL, NULL, mpu401_uart_write, NULL, NULL, mpu);
+}
+
+void mpu401_uart_update_irq(mpu401_uart_t *mpu, int irq)
+{
+ mpu->irq = irq;
+}
+
+#ifndef SOUND_MPU401_UART
+#define SOUND_MPU401_UART
+
typedef struct mpu401_uart_t
{
uint8_t status;
uint8_t rx_data;
- int uart_mode;
+ int uart_mode;
+ uint16_t addr;
+ int irq;
+
+ int is_aztech;
} mpu401_uart_t;
-void mpu401_uart_init(mpu401_uart_t *mpu, uint16_t addr);
+void mpu401_uart_init(mpu401_uart_t *mpu, uint16_t addr, int irq, int is_aztech);
+void mpu401_uart_update_addr(mpu401_uart_t *mpu, uint16_t addr);
+void mpu401_uart_update_irq(mpu401_uart_t *mpu, int irq);
+
+#endif /* SOUND_MPU401_UART */
#include "sound.h"
#include "sound_opl.h"
#include "sound_dbopl.h"
-#include "timer.h"
+#include "x86.h"
/*Interfaces between PCem and the actual OPL emulator*/
{
opl_t *opl = (opl_t *)param;
- opl->timers[0][timer] = period * TIMER_USEC * 20;
- if (!opl->timers[0][timer]) opl->timers[0][timer] = 1;
- opl->timers_enable[0][timer] = period ? 1 : 0;
+ if (period)
+ timer_set_delay_u64(&opl->timers[0][timer], period * TIMER_USEC * 20);
+ else
+ timer_disable(&opl->timers[0][timer]);
}
void ym3812_timer_set_1(void *param, int timer, int64_t period)
{
opl_t *opl = (opl_t *)param;
- opl->timers[1][timer] = period * TIMER_USEC * 20;
- if (!opl->timers[1][timer]) opl->timers[1][timer] = 1;
- opl->timers_enable[1][timer] = period ? 1 : 0;
+ if (period)
+ timer_set_delay_u64(&opl->timers[1][timer], period * TIMER_USEC * 20);
+ else
+ timer_disable(&opl->timers[1][timer]);
}
void ymf262_timer_set(void *param, int timer, int64_t period)
{
opl_t *opl = (opl_t *)param;
- opl->timers[0][timer] = period * TIMER_USEC * 20;
- if (!opl->timers[0][timer]) opl->timers[0][timer] = 1;
- opl->timers_enable[0][timer] = period ? 1 : 0;
+ if (period)
+ timer_set_delay_u64(&opl->timers[0][timer], period * TIMER_USEC * 20);
+ else
+ timer_disable(&opl->timers[0][timer]);
}
static void opl_timer_callback00(void *p)
{
- opl_t *opl = (opl_t *)p;
-
- opl->timers_enable[0][0] = 0;
opl_timer_over(0, 0);
}
static void opl_timer_callback01(void *p)
{
- opl_t *opl = (opl_t *)p;
-
- opl->timers_enable[0][1] = 0;
opl_timer_over(0, 1);
}
static void opl_timer_callback10(void *p)
{
- opl_t *opl = (opl_t *)p;
-
- opl->timers_enable[1][0] = 0;
opl_timer_over(1, 0);
}
static void opl_timer_callback11(void *p)
{
- opl_t *opl = (opl_t *)p;
-
- opl->timers_enable[1][1] = 0;
opl_timer_over(1, 1);
}
{
opl_init(ym3812_timer_set_0, opl, 0, 0, 0);
opl_init(ym3812_timer_set_1, opl, 1, 0, 0);
- timer_add(opl_timer_callback00, &opl->timers[0][0], &opl->timers_enable[0][0], (void *)opl);
- timer_add(opl_timer_callback01, &opl->timers[0][1], &opl->timers_enable[0][1], (void *)opl);
- timer_add(opl_timer_callback10, &opl->timers[1][0], &opl->timers_enable[1][0], (void *)opl);
- timer_add(opl_timer_callback11, &opl->timers[1][1], &opl->timers_enable[1][1], (void *)opl);
+ timer_add(&opl->timers[0][0], opl_timer_callback00, (void *)opl, 0);
+ timer_add(&opl->timers[0][1], opl_timer_callback01, (void *)opl, 0);
+ timer_add(&opl->timers[1][0], opl_timer_callback10, (void *)opl, 0);
+ timer_add(&opl->timers[1][1], opl_timer_callback11, (void *)opl, 0);
}
void opl3_init(opl_t *opl, int opl_emu)
{
opl_init(ymf262_timer_set, opl, 0, 1, opl_emu);
- timer_add(opl_timer_callback00, &opl->timers[0][0], &opl->timers_enable[0][0], (void *)opl);
- timer_add(opl_timer_callback01, &opl->timers[0][1], &opl->timers_enable[0][1], (void *)opl);
+ timer_add(&opl->timers[0][0], opl_timer_callback00, (void *)opl, 0);
+ timer_add(&opl->timers[0][1], opl_timer_callback01, (void *)opl, 0);
}
{
int chip_nr[2];
- int timers[2][2];
- int timers_enable[2][2];
+ pc_timer_t timers[2][2];
int16_t filtbuf[2];
FILE* soundfsbin = 0/*NULL*/;
#endif
-
-
-/* SB 2.0 CD version */
-typedef struct sb_ct1335_mixer_t
-{
- int32_t master;
- int32_t voice;
- int32_t fm;
- int32_t cd;
-
- uint8_t index;
- uint8_t regs[256];
-} sb_ct1335_mixer_t;
-/* SB PRO */
-typedef struct sb_ct1345_mixer_t
-{
- int32_t master_l, master_r;
- int32_t voice_l, voice_r;
- int32_t fm_l, fm_r;
- int32_t cd_l, cd_r;
- int32_t line_l, line_r;
- int32_t mic;
- /*see sb_ct1745_mixer for values for input selector*/
- int32_t input_selector;
-
- int input_filter;
- int in_filter_freq;
- int output_filter;
-
- int stereo;
- int stereo_isleft;
-
- uint8_t index;
- uint8_t regs[256];
-
-} sb_ct1345_mixer_t;
-/* SB16 and AWE32 */
-typedef struct sb_ct1745_mixer_t
-{
- int32_t master_l, master_r;
- int32_t voice_l, voice_r;
- int32_t fm_l, fm_r;
- int32_t cd_l, cd_r;
- int32_t line_l, line_r;
- int32_t mic;
- int32_t speaker;
-
- int bass_l, bass_r;
- int treble_l, treble_r;
-
- int output_selector;
- #define OUTPUT_MIC 1
- #define OUTPUT_CD_R 2
- #define OUTPUT_CD_L 4
- #define OUTPUT_LINE_R 8
- #define OUTPUT_LINE_L 16
-
- int input_selector_left;
- int input_selector_right;
- #define INPUT_MIC 1
- #define INPUT_CD_R 2
- #define INPUT_CD_L 4
- #define INPUT_LINE_R 8
- #define INPUT_LINE_L 16
- #define INPUT_MIDI_R 32
- #define INPUT_MIDI_L 64
-
- int mic_agc;
-
- int32_t input_gain_L;
- int32_t input_gain_R;
- int32_t output_gain_L;
- int32_t output_gain_R;
-
- uint8_t index;
- uint8_t regs[256];
-} sb_ct1745_mixer_t;
-
-typedef struct sb_t
-{
- opl_t opl;
- sb_dsp_t dsp;
- union {
- sb_ct1335_mixer_t mixer_sb2;
- sb_ct1345_mixer_t mixer_sbpro;
- sb_ct1745_mixer_t mixer_sb16;
- };
- mpu401_uart_t mpu;
- emu8k_t emu8k;
-
- int pos;
-
- uint8_t pos_regs[8];
-
- int opl_emu;
-} sb_t;
/* 0 to 7 -> -14dB to 0dB i 2dB steps. 8 to 15 -> 0 to +14dB in 2dB steps.
Note that for positive dB values, this is not amplitude, it is amplitude-1. */
const float sb_bass_treble_4bits[]= {
sb->dsp.pos = 0;
}
-static void sb_get_buffer_sbpro(int32_t *buffer, int len, void *p)
+void sb_get_buffer_sbpro(int32_t *buffer, int len, void *p)
{
sb_t *sb = (sb_t *)p;
sb_ct1345_mixer_t *mixer = &sb->mixer_sbpro;
{
/* Compatibility: chain registers 0x02 and 0x22 as well as 0x06 and 0x26 */
case 0x02: case 0x06:
- mixer->regs[mixer->index+0x20]=((val&0xE) << 4)||(val&0xE) << 4;
+ mixer->regs[mixer->index+0x20]=((val&0xE) << 4) | (val&0xE);
break;
case 0x22: case 0x26:
2x0 to 2x3 -> CMS chip
2x6, 2xA, 2xC, 2xE -> DSP chip
2x8, 2x9, 388 and 389 FM chip*/
- sb_t *sb = (sb_t*)malloc(sizeof(sb_t));
+ sb_t *sb = malloc(sizeof(sb_t));
uint16_t addr = device_get_config_int("addr");
memset(sb, 0, sizeof(sb_t));
opl2_init(&sb->opl);
- sb_dsp_init(&sb->dsp, SB1);
+ sb_dsp_init(&sb->dsp, SB1, SB_SUBTYPE_DEFAULT, sb);
sb_dsp_setaddr(&sb->dsp, addr);
sb_dsp_setirq(&sb->dsp, device_get_config_int("irq"));
sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma"));
2x0 to 2x3 -> CMS chip
2x6, 2xA, 2xC, 2xE -> DSP chip
2x8, 2x9, 388 and 389 FM chip*/
- sb_t *sb = (sb_t*)malloc(sizeof(sb_t));
+ sb_t *sb = malloc(sizeof(sb_t));
uint16_t addr = device_get_config_int("addr");
memset(sb, 0, sizeof(sb_t));
opl2_init(&sb->opl);
- sb_dsp_init(&sb->dsp, SB15);
+ sb_dsp_init(&sb->dsp, SB15, SB_SUBTYPE_DEFAULT, sb);
sb_dsp_setaddr(&sb->dsp, addr);
sb_dsp_setirq(&sb->dsp, device_get_config_int("irq"));
sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma"));
return sb;
}
-#if 0
void *sb_mcv_init()
{
/*sb1/2 port mappings, 210h to 260h in 10h steps
2x6, 2xA, 2xC, 2xE -> DSP chip
2x8, 2x9, 388 and 389 FM chip*/
- sb_t *sb = (sb_t*)malloc(sizeof(sb_t));
+ sb_t *sb = malloc(sizeof(sb_t));
memset(sb, 0, sizeof(sb_t));
opl2_init(&sb->opl);
- sb_dsp_init(&sb->dsp, SB15);
+ sb_dsp_init(&sb->dsp, SB15, SB_SUBTYPE_DEFAULT, sb);
sb_dsp_setaddr(&sb->dsp, 0);//addr);
sb_dsp_setirq(&sb->dsp, device_get_config_int("irq"));
sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma"));
sound_add_handler(sb_get_buffer_sb2, sb);
/* I/O handlers activated in sb_mcv_write */
- mca_add(sb_mcv_read, sb_mcv_write, sb);
+ mca_add(sb_mcv_read, sb_mcv_write, NULL, sb);
sb->pos_regs[0] = 0x84;
sb->pos_regs[1] = 0x50;
return sb;
}
-#endif
-
void *sb_2_init()
{
/*sb2 port mappings. 220h or 240h.
test this. It shouldn't exist on SB 1.0 as the CMS chips are always
present there.
Syndicate requires this mirror for music to play.*/
- sb_t *sb = (sb_t*)malloc(sizeof(sb_t));
+ sb_t *sb = malloc(sizeof(sb_t));
uint16_t addr = device_get_config_int("addr");
memset(sb, 0, sizeof(sb_t));
opl2_init(&sb->opl);
- sb_dsp_init(&sb->dsp, SB2);
+ sb_dsp_init(&sb->dsp, SB2, SB_SUBTYPE_DEFAULT, sb);
sb_dsp_setaddr(&sb->dsp, addr);
sb_dsp_setirq(&sb->dsp, device_get_config_int("irq"));
sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma"));
2x6, 2xA, 2xC, 2xE -> DSP chip
2x8, 2x9, 388 and 389 FM chip (9 voices)
2x0+10 to 2x0+13 CDROM interface.*/
- sb_t *sb = (sb_t*)malloc(sizeof(sb_t));
+ sb_t *sb = malloc(sizeof(sb_t));
uint16_t addr = device_get_config_int("addr");
memset(sb, 0, sizeof(sb_t));
opl2_init(&sb->opl);
- sb_dsp_init(&sb->dsp, SBPRO);
+ sb_dsp_init(&sb->dsp, SBPRO, SB_SUBTYPE_DEFAULT, sb);
sb_dsp_setaddr(&sb->dsp, addr);
sb_dsp_setirq(&sb->dsp, device_get_config_int("irq"));
sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma"));
2x6, 2xA, 2xC, 2xE -> DSP chip
2x8, 2x9, 388 and 389 FM chip (9 voices)
2x0+10 to 2x0+13 CDROM interface.*/
- sb_t *sb = (sb_t*)malloc(sizeof(sb_t));
+ sb_t *sb = malloc(sizeof(sb_t));
memset(sb, 0, sizeof(sb_t));
uint16_t addr = device_get_config_int("addr");
sb->opl_emu = device_get_config_int("opl_emu");
opl3_init(&sb->opl, sb->opl_emu);
- sb_dsp_init(&sb->dsp, SBPRO2);
+ sb_dsp_init(&sb->dsp, SBPRO2, SB_SUBTYPE_DEFAULT, sb);
sb_dsp_setaddr(&sb->dsp, addr);
sb_dsp_setirq(&sb->dsp, device_get_config_int("irq"));
sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma"));
return sb;
}
-#if 0
void *sb_pro_mcv_init()
{
/*sbpro port mappings. 220h or 240h.
2x4 to 2x5 -> Mixer interface
2x6, 2xA, 2xC, 2xE -> DSP chip
2x8, 2x9, 388 and 389 FM chip (9 voices)*/
- sb_t *sb = (sb_t*)malloc(sizeof(sb_t));
+ sb_t *sb = malloc(sizeof(sb_t));
memset(sb, 0, sizeof(sb_t));
sb->opl_emu = device_get_config_int("opl_emu");
opl3_init(&sb->opl, sb->opl_emu);
- sb_dsp_init(&sb->dsp, SBPRO2);
+ sb_dsp_init(&sb->dsp, SBPRO2, SB_SUBTYPE_DEFAULT, sb);
sb_ct1345_mixer_reset(sb);
/* I/O handlers activated in sb_mcv_write */
sound_add_handler(sb_get_buffer_sbpro, sb);
/* I/O handlers activated in sb_pro_mcv_write */
- mca_add(sb_pro_mcv_read, sb_pro_mcv_write, sb);
+ mca_add(sb_pro_mcv_read, sb_pro_mcv_write, NULL, sb);
sb->pos_regs[0] = 0x03;
sb->pos_regs[1] = 0x51;
return sb;
}
-#endif
void *sb_16_init()
{
- sb_t *sb = (sb_t*)malloc(sizeof(sb_t));
+ sb_t *sb = malloc(sizeof(sb_t));
memset(sb, 0, sizeof(sb_t));
uint16_t addr = device_get_config_int("addr");
sb->opl_emu = device_get_config_int("opl_emu");
opl3_init(&sb->opl, sb->opl_emu);
- sb_dsp_init(&sb->dsp, SB16);
+ sb_dsp_init(&sb->dsp, SB16, SB_SUBTYPE_DEFAULT, sb);
sb_dsp_setaddr(&sb->dsp, addr);
// TODO: irq and dma options too?
sb_ct1745_mixer_reset(sb);
io_sethandler(0x0388, 0x0004, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &sb->opl);
io_sethandler(addr+4, 0x0002, sb_ct1745_mixer_read, NULL, NULL, sb_ct1745_mixer_write, NULL, NULL, sb);
sound_add_handler(sb_get_buffer_sb16, sb);
- mpu401_uart_init(&sb->mpu, 0x330);
+ mpu401_uart_init(&sb->mpu, 0x330, -1, 0);
return sb;
}
-#if 0
int sb_awe32_available()
{
return rom_present("awe32.raw");
void *sb_awe32_init()
{
- sb_t *sb = (sb_t*)malloc(sizeof(sb_t));
+ sb_t *sb = malloc(sizeof(sb_t));
int onboard_ram = device_get_config_int("onboard_ram");
memset(sb, 0, sizeof(sb_t));
uint16_t emu_addr = device_get_config_int("emu_addr");
sb->opl_emu = device_get_config_int("opl_emu");
opl3_init(&sb->opl, sb->opl_emu);
- sb_dsp_init(&sb->dsp, SB16 + 1);
+ sb_dsp_init(&sb->dsp, SB16 + 1, SB_SUBTYPE_DEFAULT, sb);
sb_dsp_setaddr(&sb->dsp, addr);
// TODO: irq and dma options too?
sb_ct1745_mixer_reset(sb);
io_sethandler(0x0388, 0x0004, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &sb->opl);
io_sethandler(addr+4, 0x0002, sb_ct1745_mixer_read, NULL, NULL, sb_ct1745_mixer_write, NULL, NULL, sb);
sound_add_handler(sb_get_buffer_emu8k, sb);
- mpu401_uart_init(&sb->mpu, 0x330);
+ mpu401_uart_init(&sb->mpu, 0x330, -1, 0);
emu8k_init(&sb->emu8k, emu_addr, onboard_ram);
return sb;
}
-#endif
void sb_close(void *p)
{
free(sb);
}
-#if 0
void sb_awe32_close(void *p)
{
sb_t *sb = (sb_t *)p;
sb_close(sb);
}
-#endif
void sb_speed_changed(void *p)
{
sb_dsp_add_status_info(s, max_len, &sb->dsp);
}
-#if 0
static device_config_t sb_config[] =
{
{
sb_add_status_info,
sb_awe32_config
};
-#endif
+#ifndef SOUND_SB_H
+#define SOUND_SB_H
+
+#include "sound_emu8k.h"
+#include "sound_mpu401_uart.h"
+#include "sound_sb_dsp.h"
+
extern device_t sb_1_device;
extern device_t sb_15_device;
extern device_t sb_mcv_device;
extern device_t sb_pro_mcv_device;
extern device_t sb_16_device;
extern device_t sb_awe32_device;
+
+/* SB 2.0 CD version */
+typedef struct sb_ct1335_mixer_t
+{
+ int32_t master;
+ int32_t voice;
+ int32_t fm;
+ int32_t cd;
+
+ uint8_t index;
+ uint8_t regs[256];
+} sb_ct1335_mixer_t;
+/* SB PRO */
+typedef struct sb_ct1345_mixer_t
+{
+ int32_t master_l, master_r;
+ int32_t voice_l, voice_r;
+ int32_t fm_l, fm_r;
+ int32_t cd_l, cd_r;
+ int32_t line_l, line_r;
+ int32_t mic;
+ /*see sb_ct1745_mixer for values for input selector*/
+ int32_t input_selector;
+
+ int input_filter;
+ int in_filter_freq;
+ int output_filter;
+
+ int stereo;
+ int stereo_isleft;
+
+ uint8_t index;
+ uint8_t regs[256];
+
+} sb_ct1345_mixer_t;
+/* SB16 and AWE32 */
+typedef struct sb_ct1745_mixer_t
+{
+ int32_t master_l, master_r;
+ int32_t voice_l, voice_r;
+ int32_t fm_l, fm_r;
+ int32_t cd_l, cd_r;
+ int32_t line_l, line_r;
+ int32_t mic;
+ int32_t speaker;
+
+ int bass_l, bass_r;
+ int treble_l, treble_r;
+
+ int output_selector;
+ #define OUTPUT_MIC 1
+ #define OUTPUT_CD_R 2
+ #define OUTPUT_CD_L 4
+ #define OUTPUT_LINE_R 8
+ #define OUTPUT_LINE_L 16
+
+ int input_selector_left;
+ int input_selector_right;
+ #define INPUT_MIC 1
+ #define INPUT_CD_R 2
+ #define INPUT_CD_L 4
+ #define INPUT_LINE_R 8
+ #define INPUT_LINE_L 16
+ #define INPUT_MIDI_R 32
+ #define INPUT_MIDI_L 64
+
+ int mic_agc;
+
+ int32_t input_gain_L;
+ int32_t input_gain_R;
+ int32_t output_gain_L;
+ int32_t output_gain_R;
+
+ uint8_t index;
+ uint8_t regs[256];
+} sb_ct1745_mixer_t;
+
+typedef struct sb_t
+{
+ opl_t opl;
+ sb_dsp_t dsp;
+ union {
+ sb_ct1335_mixer_t mixer_sb2;
+ sb_ct1345_mixer_t mixer_sbpro;
+ sb_ct1745_mixer_t mixer_sb16;
+ };
+ mpu401_uart_t mpu;
+ emu8k_t emu8k;
+
+ int pos;
+
+ uint8_t pos_regs[8];
+
+ int opl_emu;
+} sb_t;
+
+// exported for clone cards
+void sb_get_buffer_sbpro(int32_t *buffer, int len, void *p);
+void sb_ct1345_mixer_write(uint16_t addr, uint8_t val, void *p);
+uint8_t sb_ct1345_mixer_read(uint16_t addr, void *p);
+void sb_ct1345_mixer_reset(sb_t* sb);
+
+void sb_close(void *p);
+void sb_speed_changed(void *p);
+void sb_add_status_info(char *s, int max_len, void *p);
+
+#endif /* SOUND_SB_H */
#include "ibm.h"
+#include "device.h"
#include "dma.h"
#include "filters.h"
#include "io.h"
#include "pic.h"
#include "sound.h"
+#include "sound_azt2316a.h"
#include "sound_sb_dsp.h"
#include "timer.h"
+#include "x86.h"
/*The recording safety margin is intended for uneven "len" calls to the get_buffer mixer calls on sound_sb*/
#define SB_DSP_REC_SAFEFTY_MARGIN 4096
float low_fir_sb16_coef[SB16_NCoef];
-#define M_PI 3.1415927
-
static inline double sinc(double x)
{
return sin(M_PI * x) / (M_PI * x);
void sb_dsp_reset(sb_dsp_t *dsp)
{
- dsp->sbenable = dsp->sb_enable_i = 0;
+ timer_disable(&dsp->output_timer);
+ timer_disable(&dsp->input_timer);
+
dsp->sb_command = 0;
dsp->sb_8_length = 0xffff;
dsp->sbe2count = 0;
dsp->sbreset = 0;
- dsp->sbenable = dsp->sb_enable_i = dsp->sb_count_i = 0;
dsp->record_pos_read=0;
dsp->record_pos_write=SB_DSP_REC_SAFEFTY_MARGIN;
int c;
sb_dsp_reset(dsp);
-
- if (dsp->sb_type==SB16) sb_commands[8] = 1;
- else sb_commands[8] = -1;
-
+
+ if (IS_AZTECH(dsp))
+ {
+ sb_commands[8] = 1;
+ sb_commands[9] = 1;
+ }
+ else
+ {
+ if (dsp->sb_type==SB16) sb_commands[8] = 1;
+ else sb_commands[8] = -1;
+ }
+
for (c = 0; c < 256; c++)
dsp->sb_asp_regs[c] = 0;
dsp->sb_asp_regs[5] = 0x01;
if (dsp->sb_timeo < 256)
dsp->sblatcho = TIMER_USEC * (256 - dsp->sb_timeo);
else
- dsp->sblatcho = (int)(TIMER_USEC * (1000000.0f / (float)(dsp->sb_timeo - 256)));
+ dsp->sblatcho = (uint64_t)(TIMER_USEC * (1000000.0f / (float)(dsp->sb_timeo - 256)));
if (dsp->sb_timei < 256)
dsp->sblatchi = TIMER_USEC * (256 - dsp->sb_timei);
else
- dsp->sblatchi = (int)(TIMER_USEC * (1000000.0f / (float)(dsp->sb_timei - 256)));
+ dsp->sblatchi = (uint64_t)(TIMER_USEC * (1000000.0f / (float)(dsp->sb_timei - 256)));
}
void sb_add_data(sb_dsp_t *dsp, uint8_t v)
dsp->sb_8_enable = 1;
if (dsp->sb_16_enable && dsp->sb_16_output) dsp->sb_16_enable = 0;
dsp->sb_8_output = 1;
- timer_process();
- dsp->sbenable = dsp->sb_8_enable;
- timer_update_outstanding();
+ if (!timer_is_enabled(&dsp->output_timer))
+ timer_set_delay_u64(&dsp->output_timer, dsp->sblatcho);
dsp->sbleftright = 0;
dsp->sbdacpos = 0;
// pclog("Start 8-bit DMA addr %06X len %04X\n",dma.ac[1]+(dma.page[1]<<16),len);
dsp->sb_16_enable = 1;
if (dsp->sb_8_enable && dsp->sb_8_output) dsp->sb_8_enable = 0;
dsp->sb_16_output = 1;
- timer_process();
- dsp->sbenable = dsp->sb_16_enable;
- timer_update_outstanding();
+ if (!timer_is_enabled(&dsp->output_timer))
+ timer_set_delay_u64(&dsp->output_timer, dsp->sblatcho);
// pclog("Start 16-bit DMA addr %06X len %04X\n",dma16.ac[1]+(dma16.page[1]<<16),len);
}
}
dsp->sb_8_enable = 1;
if (dsp->sb_16_enable && !dsp->sb_16_output) dsp->sb_16_enable = 0;
dsp->sb_8_output = 0;
- timer_process();
- dsp->sb_enable_i = dsp->sb_8_enable;
- timer_update_outstanding();
+ if (!timer_is_enabled(&dsp->input_timer))
+ timer_set_delay_u64(&dsp->input_timer, dsp->sblatchi);
// pclog("Start 8-bit input DMA addr %06X len %04X\n",dma.ac[1]+(dma.page[1]<<16),len);
}
else
dsp->sb_16_enable = 1;
if (dsp->sb_8_enable && !dsp->sb_8_output) dsp->sb_8_enable = 0;
dsp->sb_16_output = 0;
- timer_process();
- dsp->sb_enable_i = dsp->sb_16_enable;
- timer_update_outstanding();
+ if (!timer_is_enabled(&dsp->input_timer))
+ timer_set_delay_u64(&dsp->input_timer, dsp->sblatchi);
// pclog("Start 16-bit input DMA addr %06X len %04X\n",dma.ac[1]+(dma.page[1]<<16),len);
}
memset(dsp->record_buffer,0,sizeof(dsp->record_buffer));
sb_add_data(dsp, (dsp->record_buffer[dsp->record_pos_read]>>8) ^0x80);
/*Due to the current implementation, I need to emulate a samplerate, even if this
* mode does not imply such samplerate. Position is increased in sb_poll_i*/
- if (dsp->sb_enable_i==0)
+ if (!timer_is_enabled(&dsp->input_timer))
{
dsp->sb_timei = 256 - 22;
dsp->sblatchi = TIMER_USEC * 22;
temp = 1000000 / 22;
dsp->sb_freq = temp;
- timer_process();
- dsp->sb_enable_i = 1;
- timer_update_outstanding();
+ timer_set_delay_u64(&dsp->input_timer, dsp->sblatchi);
}
break;
case 0x24: /*8-bit single cycle DMA input*/
case 0x41: /*Set output sampling rate*/
case 0x42: /*Set input sampling rate*/
if (dsp->sb_type < SB16) break;
- dsp->sblatcho = (int)(TIMER_USEC * (1000000.0f / (float)(dsp->sb_data[1] + (dsp->sb_data[0] << 8))));
+ dsp->sblatcho = (uint64_t)(TIMER_USEC * (1000000.0f / (float)(dsp->sb_data[1] + (dsp->sb_data[0] << 8))));
// pclog("Sample rate - %ihz (%i)\n",dsp->sb_data[1]+(dsp->sb_data[0]<<8), dsp->sblatcho);
temp = dsp->sb_freq;
dsp->sb_freq = dsp->sb_data[1] + (dsp->sb_data[0] << 8);
case 0x80: /*Pause DAC*/
dsp->sb_pausetime = dsp->sb_data[0] + (dsp->sb_data[1] << 8);
// pclog("SB pause %04X\n",sb_pausetime);
- timer_process();
- dsp->sbenable = 1;
- timer_update_outstanding();
+ if (!timer_is_enabled(&dsp->output_timer))
+ timer_set_delay_u64(&dsp->output_timer, dsp->sblatcho);
break;
case 0x90: /*High speed 8-bit autoinit DMA output*/
if (dsp->sb_type < SB2) break;
sb_add_data(dsp, ~dsp->sb_data[0]);
break;
case 0xE1: /*Get DSP version*/
+ if (IS_AZTECH(dsp))
+ {
+ if (dsp->sb_subtype == SB_SUBTYPE_CLONE_AZT2316A_0X11)
+ {
+ sb_add_data(dsp, 0x3);
+ sb_add_data(dsp, 0x1);
+ }
+ else if (dsp->sb_subtype == SB_SUBTYPE_CLONE_AZT1605_0X0C)
+ {
+ sb_add_data(dsp, 0x2);
+ sb_add_data(dsp, 0x1);
+ }
+ break;
+ }
sb_add_data(dsp, sb_dsp_versions[dsp->sb_type] >> 8);
sb_add_data(dsp, sb_dsp_versions[dsp->sb_type] & 0xff);
break;
case 0xFF:
break;
case 0x08: /*ASP get version*/
+ if (IS_AZTECH(dsp))
+ {
+ if ((dsp->sb_data[0] == 0x55 || dsp->sb_data[0] == 0x05) && dsp->sb_subtype == SB_SUBTYPE_CLONE_AZT2316A_0X11)
+ sb_add_data(dsp, 0x11); /* AZTECH get type, WASHINGTON/latest - according to devkit. E.g.: The one in the Itautec Infoway Multimidia */
+ else if ((dsp->sb_data[0] == 0x55 || dsp->sb_data[0] == 0x05) && dsp->sb_subtype == SB_SUBTYPE_CLONE_AZT1605_0X0C)
+ sb_add_data(dsp, 0x0C); /* AZTECH get type, CLINTON - according to devkit. E.g.: The one in the Packard Bell Legend 100CD */
+ else if (dsp->sb_data[0] == 0x08)
+ {
+ // EEPROM address to write followed by byte
+ if (dsp->sb_data[1] < 0 || dsp->sb_data[1] >= AZTECH_EEPROM_SIZE)
+ fatal("AZT EEPROM: out of bounds write to %02X\n", dsp->sb_data[1]);
+ dsp->azt_eeprom[dsp->sb_data[1]] = dsp->sb_data[2];
+ break;
+ }
+ else if (dsp->sb_data[0] == 0x07)
+ {
+ // EEPROM address to read
+ if (dsp->sb_data[1] < 0 || dsp->sb_data[1] >= AZTECH_EEPROM_SIZE)
+ fatal("AZT EEPROM: out of bounds read to %02X\n", dsp->sb_data[1]);
+ sb_add_data(dsp, dsp->azt_eeprom[dsp->sb_data[1]]);
+ break;
+ }
+ else
+ pclog("AZT2316A: UNKNOWN 0x08 COMMAND: %02X\n", dsp->sb_data[0]); // 0x08 (when shutting down, driver tries to read 1 byte of response), 0x55, 0x0D, 0x08D seen
+ break;
+ }
if (dsp->sb_type < SB16) break;
sb_add_data(dsp, 0x18);
break;
case 0x04:
case 0x05:
break;
+ case 0x09: /*AZTECH mode set*/
+ if (IS_AZTECH(dsp))
+ {
+ if (dsp->sb_data[0] == 0x00)
+ {
+ pclog("AZT2316A: WSS MODE!\n");
+ azt2316a_enable_wss(1, dsp->parent);
+ }
+ else if (dsp->sb_data[0] == 0x01)
+ {
+ pclog("AZT2316A: SB8PROV2 MODE!\n");
+ azt2316a_enable_wss(0, dsp->parent);
+ }
+ else
+ pclog("AZT2316A: UNKNOWN MODE!\n"); // sequences 0x02->0xFF, 0x04->0xFF seen
+ }
+ break;
+ case 0x38: /*TODO: AZTECH MIDI-related? */
+ break;
// default:
-// fatal("Exec bad SB command %02X\n",sb_command);
-
-
+// fatal("Exec bad SB command %02X\n",dsp->sb_command);
+
+
/*TODO: Some more data about the DSP registeres
* http://the.earth.li/~tfm/oldpage/sb_dsp.html
* http://www.synchrondata.com/pheaven/www/area19.htm
dsp->sbreset = v;
return;
case 0xC: /*Command/data write*/
- timer_process();
- dsp->wb_time = TIMER_USEC * 1;
- dsp->wb_full = 1;
- timer_update_outstanding();
+ timer_set_delay_u64(&dsp->wb_timer, TIMER_USEC * 1);
if (dsp->asp_data_len)
{
// pclog("ASP data %i\n", dsp->asp_data_len);
dsp->sb_data_stat++;
}
else
- dsp->sb_data[dsp->sb_data_stat++] = v;
+ {
+ dsp->sb_data[dsp->sb_data_stat++] = v;
+ if (IS_AZTECH(dsp))
+ {
+ // variable length commands
+ if (dsp->sb_command == 0x08 && dsp->sb_data_stat == 1 && dsp->sb_data[0] == 0x08)
+ sb_commands[dsp->sb_command] = 3;
+ else if (dsp->sb_command == 0x08 && dsp->sb_data_stat == 1 && dsp->sb_data[0] == 0x07)
+ sb_commands[dsp->sb_command] = 2;
+ }
+ }
if (dsp->sb_data_stat == sb_commands[dsp->sb_command] || sb_commands[dsp->sb_command] == -1)
{
sb_exec_command(dsp);
dsp->sb_data_stat = -1;
+ if (IS_AZTECH(dsp))
+ {
+ // variable length commands
+ if (dsp->sb_command == 0x08)
+ sb_commands[dsp->sb_command] = 1;
+ }
}
break;
}
dsp->busy_count = 0;
if (dsp->wb_full || (dsp->busy_count & 2))
{
- dsp->wb_full = dsp->wb_time;
- return 0xff;
+ dsp->wb_full = timer_is_enabled(&dsp->wb_timer);
+// pclog("SB read 0x80\n");
+ if (IS_AZTECH(dsp))
+ return 0x80;
+ else
+ return 0xFF;
}
- return 0x7f;
+// pclog("SB read 0x00\n");
+ if (IS_AZTECH(dsp))
+ return 0x00;
+ else
+ return 0x7F;
case 0xE: /*Read data ready*/
picintc(1 << dsp->sb_irqnum);
dsp->sb_irq8 = dsp->sb_irq16 = 0;
- return (dsp->sb_read_rp == dsp->sb_read_wp) ? 0x7f : 0xff;
+ // Only bit 7 is defined but aztech diagnostics fail if the others are set. Keep the original behavior to not interfere with what's already working.
+ if (IS_AZTECH(dsp))
+ {
+// pclog("SB read %02X\n",(dsp->sb_read_rp == dsp->sb_read_wp) ? 0x00 : 0x80);
+ return (dsp->sb_read_rp == dsp->sb_read_wp) ? 0x00 : 0x80;
+ }
+ else
+ {
+// pclog("SB read %02X\n",(dsp->sb_read_rp == dsp->sb_read_wp) ? 0x7F : 0xFF);
+ return (dsp->sb_read_rp == dsp->sb_read_wp) ? 0x7F : 0xFF;
+ }
case 0xF: /*16-bit ack*/
dsp->sb_irq16 = 0;
if (!dsp->sb_irq8) picintc(1 << dsp->sb_irqnum);
static void sb_wb_clear(void *p)
{
- sb_dsp_t *dsp = (sb_dsp_t *)p;
-
- dsp->wb_time = 0;
}
-void sb_dsp_init(sb_dsp_t *dsp, int type)
+void sb_dsp_init(sb_dsp_t *dsp, int type, int subtype, void *parent)
{
dsp->sb_type = type;
+ dsp->sb_subtype = subtype;
+ dsp->parent = parent;
// Default values. Use sb_dsp_setxxx() methods to change.
dsp->sb_irqnum = 7;
sb_doreset(dsp);
- timer_add(pollsb, &dsp->sbcount, &dsp->sbenable, dsp);
- timer_add(sb_poll_i, &dsp->sb_count_i, &dsp->sb_enable_i, dsp);
- timer_add(sb_wb_clear, &dsp->wb_time, &dsp->wb_time, dsp);
+ timer_add(&dsp->output_timer, pollsb, dsp, 0);
+ timer_add(&dsp->input_timer, sb_poll_i, dsp, 0);
+ timer_add(&dsp->wb_timer, sb_wb_clear, dsp, 0);
/*Initialise SB16 filter to same cutoff as 8-bit SBs (3.2 kHz). This will be recalculated when
a set frequency command is sent.*/
void sb_dsp_setaddr(sb_dsp_t *dsp, uint16_t addr)
{
// pclog("sb_dsp_setaddr : %04X\n", addr);
- dsp->sb_addr = addr;
io_removehandler(dsp->sb_addr + 6, 0x0002, sb_read, NULL, NULL, sb_write, NULL, NULL, dsp);
io_removehandler(dsp->sb_addr + 0xa, 0x0006, sb_read, NULL, NULL, sb_write, NULL, NULL, dsp);
+ dsp->sb_addr = addr;
if (dsp->sb_addr != 0)
{
io_sethandler(dsp->sb_addr + 6, 0x0002, sb_read, NULL, NULL, sb_write, NULL, NULL, dsp);
sb_dsp_t *dsp = (sb_dsp_t *)p;
int tempi,ref;
- dsp->sbcount += dsp->sblatcho;
+ timer_advance_u64(&dsp->output_timer, dsp->sblatcho);
+
// pclog("PollSB %i %i %i %i\n",sb_8_enable,sb_8_pause,sb_pausetime,sb_8_output);
if (dsp->sb_8_enable && !dsp->sb_8_pause && dsp->sb_pausetime < 0 && dsp->sb_8_output)
{
if (dsp->sb_8_length < 0)
{
- if (dsp->sb_8_autoinit) dsp->sb_8_length = dsp->sb_8_autolen;
- else dsp->sb_8_enable = dsp->sbenable=0;
+ if (dsp->sb_8_autoinit)
+ dsp->sb_8_length = dsp->sb_8_autolen;
+ else
+ {
+ dsp->sb_8_enable = 0;
+ timer_disable(&dsp->output_timer);
+ }
sb_irq(dsp, 1);
}
}
if (dsp->sb_16_length < 0)
{
// pclog("16DMA over %i\n",dsp->sb_16_autoinit);
- if (dsp->sb_16_autoinit) dsp->sb_16_length = dsp->sb_16_autolen;
- else dsp->sb_16_enable = dsp->sbenable = 0;
+ if (dsp->sb_16_autoinit)
+ dsp->sb_16_length = dsp->sb_16_autolen;
+ else
+ {
+ dsp->sb_16_enable = 0;
+ timer_disable(&dsp->output_timer);
+ }
sb_irq(dsp, 0);
}
}
if (dsp->sb_pausetime < 0)
{
sb_irq(dsp, 1);
- dsp->sbenable = dsp->sb_8_enable;
+ if (!dsp->sb_8_enable)
+ timer_disable(&dsp->output_timer);
// pclog("SB pause over\n");
}
}
{
sb_dsp_t *dsp = (sb_dsp_t *)p;
int processed=0;
- dsp->sb_count_i += dsp->sblatchi;
+
+ timer_advance_u64(&dsp->input_timer, dsp->sblatchi);
+
// pclog("PollSBi %i %i %i %i\n",sb_8_enable,sb_8_pause,sb_pausetime,sb_8_output);
if (dsp->sb_8_enable && !dsp->sb_8_pause && dsp->sb_pausetime < 0 && !dsp->sb_8_output)
{
if (dsp->sb_8_length < 0)
{
// pclog("Input DMA over %i\n",sb_8_autoinit);
- if (dsp->sb_8_autoinit) dsp->sb_8_length = dsp->sb_8_autolen;
- else dsp->sb_8_enable = dsp->sb_enable_i = 0;
+ if (dsp->sb_8_autoinit)
+ dsp->sb_8_length = dsp->sb_8_autolen;
+ else
+ {
+ dsp->sb_8_enable = 0;
+ timer_disable(&dsp->input_timer);
+ }
sb_irq(dsp, 1);
}
processed=1;
if (dsp->sb_16_length < 0)
{
// pclog("16iDMA over %i\n",sb_16_autoinit);
- if (dsp->sb_16_autoinit) dsp->sb_16_length = dsp->sb_16_autolen;
- else dsp->sb_16_enable = dsp->sb_enable_i = 0;
+ if (dsp->sb_16_autoinit)
+ dsp->sb_16_length = dsp->sb_16_autolen;
+ else
+ {
+ dsp->sb_16_enable = 0;
+ timer_disable(&dsp->input_timer);
+ }
sb_irq(dsp, 0);
}
processed=1;
sprintf(temps, "SB playback frequency : %iHz\n", freq);
strncat(s, temps, max_len);
}
+ strncat(s, "\n", max_len);
}
+#ifndef SOUND_SB_DSP_H
+#define SOUND_SB_DSP_H
+
+/*Sound Blaster Clones, for quirks*/
+#define SB_SUBTYPE_DEFAULT 0 /*Handle as a Creative card*/
+#define SB_SUBTYPE_CLONE_AZT2316A_0X11 1 /*Aztech Sound Galaxy Pro 16 AB, DSP 3.1 - SBPRO2 clone*/
+#define SB_SUBTYPE_CLONE_AZT1605_0X0C 2 /*Aztech Sound Galaxy Nova 16 Extra / Packard Bell Forte 16, DSP 2.1 - SBPRO2 clone*/
+
+// aztech-related
+#define IS_AZTECH(dsp) ((dsp)->sb_subtype == SB_SUBTYPE_CLONE_AZT2316A_0X11 || (dsp)->sb_subtype == SB_SUBTYPE_CLONE_AZT1605_0X0C) // check for future AZT cards here
+#define AZTECH_EEPROM_SIZE 16
+
typedef struct sb_dsp_t
{
int sb_type;
+ int sb_subtype; // which clone
+ void *parent; // "sb_t *" if default subtype, "azt2316a_t *" if aztech.
int sb_8_length, sb_8_format, sb_8_autoinit, sb_8_pause, sb_8_enable, sb_8_autolen, sb_8_output;
int sb_8_dmanum;
int sbenable, sb_enable_i;
- int sbcount, sb_count_i;
+ pc_timer_t output_timer, input_timer;
- int sblatcho, sblatchi;
+ uint64_t sblatcho, sblatchi;
uint16_t sb_addr;
int asp_data_len;
- int wb_time, wb_full;
+ pc_timer_t wb_timer;
+ int wb_full;
int busy_count;
int16_t record_buffer[0xFFFF];
int16_t buffer[MAXSOUNDBUFLEN * 2];
int pos;
+
+ uint8_t azt_eeprom[AZTECH_EEPROM_SIZE]; // the eeprom in the Aztech cards is attached to the DSP
} sb_dsp_t;
-void sb_dsp_init(sb_dsp_t *dsp, int type);
+void sb_dsp_init(sb_dsp_t *dsp, int type, int subtype, void *parent);
void sb_dsp_close(sb_dsp_t *dsp);
void sb_dsp_setirq(sb_dsp_t *dsp, int irq);
void sb_dsp_add_status_info(char *s, int max_len, sb_dsp_t *dsp);
void sb_dsp_update(sb_dsp_t *dsp);
+
+#endif /* SOUND_SB_DSP_H */
--- /dev/null
+typedef void thread_t;
+thread_t *thread_create(void (*thread_rout)(void *param), void *param);
+void thread_kill(thread_t *handle);
+
+typedef void event_t;
+event_t *thread_create_event();
+void thread_set_event(event_t *event);
+void thread_reset_event(event_t *_event);
+int thread_wait_event(event_t *event, int timeout);
+void thread_destroy_event(event_t *_event);
+
+typedef void mutex_t;
+mutex_t *thread_create_mutex(void);
+void thread_lock_mutex(mutex_t *mutex);
+void thread_unlock_mutex(mutex_t *mutex);
+void thread_destroy_mutex(mutex_t *mutex);
+
+void thread_sleep(int t);
#include "ibm.h"
-/*#include "sound_opl.h"
-#include "adlibgold.h"
-#include "sound_pas16.h"
-#include "sound_sb.h"
-#include "sound_sb_dsp.h"
-#include "sound_wss.h"*/
#include "timer.h"
-#define TIMERS_MAX 32
+uint64_t TIMER_USEC;
+uint32_t timer_target;
-int TIMER_USEC;
+/*Enabled timers are stored in a linked list, with the first timer to expire at
+ the head.*/
+static pc_timer_t *timer_head = NULL;
-static struct
+void timer_enable(pc_timer_t *timer)
{
- int present;
- void (*callback)(void *priv);
- void *priv;
- int *enable;
- int *count;
-} timers[TIMERS_MAX];
-
-int timers_present = 0;
-int timer_one = 1;
-
-int timer_count = 0, timer_latch = 0;
-int timer_start = 0;
+ pc_timer_t *timer_node = timer_head;
-void timer_process()
-{
- int c;
- int process = 0;
- /*Get actual elapsed time*/
- int diff = timer_latch - timer_count;
- int enable[TIMERS_MAX];
-
- timer_latch = 0;
-
- for (c = 0; c < timers_present; c++)
- {
- enable[c] = *timers[c].enable;
- if (*timers[c].enable)
- {
- *timers[c].count = *timers[c].count - diff;
- if (*timers[c].count <= 0)
- process = 1;
- }
- }
-
- if (!process)
- return;
-
- while (1)
- {
- int lowest = 1, lowest_c;
-
- for (c = 0; c < timers_present; c++)
- {
- if (enable[c])
- {
- if (*timers[c].count < lowest)
- {
- lowest = *timers[c].count;
- lowest_c = c;
- }
+// pclog("timer->enable %p %i\n", timer, timer->enabled);
+ if (timer->enabled)
+ timer_disable(timer);
+
+ if (timer->next || timer->prev)
+ fatal("timer_enable - timer->next\n");
+
+ timer->enabled = 1;
+
+ /*List currently empty - add to head*/
+ if (!timer_head)
+ {
+ timer_head = timer;
+ timer->next = timer->prev = NULL;
+ timer_target = timer_head->ts_integer;
+ return;
+ }
+
+ timer_node = timer_head;
+
+ while (1)
+ {
+ /*Timer expires before timer_node. Add to list in front of timer_node*/
+ if (TIMER_LESS_THAN(timer, timer_node))
+ {
+ timer->next = timer_node;
+ timer->prev = timer_node->prev;
+ timer_node->prev = timer;
+ if (timer->prev)
+ timer->prev->next = timer;
+ else
+ {
+ timer_head = timer;
+ timer_target = timer_head->ts_integer;
}
- }
-
- if (lowest > 0)
- break;
-
- timers[lowest_c].callback(timers[lowest_c].priv);
- enable[lowest_c] = *timers[lowest_c].enable;
- }
+ return;
+ }
+
+ /*timer_node is last in the list. Add timer to end of list*/
+ if (!timer_node->next)
+ {
+ timer_node->next = timer;
+ timer->prev = timer_node;
+ return;
+ }
+
+ timer_node = timer_node->next;
+ }
}
+void timer_disable(pc_timer_t *timer)
+{
+// pclog("timer->disable %p\n", timer);
+ if (!timer->enabled)
+ return;
+
+ if (!timer->next && !timer->prev && timer != timer_head)
+ fatal("timer_disable - !timer->next\n");
-void timer_update_outstanding()
+ timer->enabled = 0;
+
+ if (timer->prev)
+ timer->prev->next = timer->next;
+ else
+ timer_head = timer->next;
+ if (timer->next)
+ timer->next->prev = timer->prev;
+ timer->prev = timer->next = NULL;
+}
+static void timer_remove_head()
{
- int c;
- timer_latch = 0x7fffffff;
- for (c = 0; c < timers_present; c++)
+ if (timer_head)
{
- if (*timers[c].enable && *timers[c].count < timer_latch)
- timer_latch = *timers[c].count;
+ pc_timer_t *timer = timer_head;
+// pclog("timer_remove_head %p %p\n", timer_head, timer_head->next);
+ timer_head = timer->next;
+ timer_head->prev = NULL;
+ timer->next = timer->prev = NULL;
+ timer->enabled = 0;
}
- timer_count = timer_latch = (timer_latch + ((1 << TIMER_SHIFT) - 1));
}
-void timer_reset()
+void timer_process()
{
- pclog("timer_reset\n");
- timers_present = 0;
- timer_latch = timer_count = 0;
-// timer_process();
-}
+ if (!timer_head)
+ return;
-int timer_add(void (*callback)(void *priv), int *count, int *enable, void *priv)
-{
- if (timers_present < TIMERS_MAX)
+ while (1)
{
-// pclog("timer_add : adding timer %i\n", timers_present);
- timers[timers_present].present = 1;
- timers[timers_present].callback = callback;
- timers[timers_present].priv = priv;
- timers[timers_present].count = count;
- timers[timers_present].enable = enable;
- timers_present++;
- return timers_present - 1;
+ pc_timer_t *timer = timer_head;
+
+ if (!TIMER_LESS_THAN_VAL(timer, (uint32_t)tsc))
+ break;
+
+ timer_remove_head();
+ timer->callback(timer->p);
}
- return -1;
+
+ timer_target = timer_head->ts_integer;
+}
+
+void timer_reset()
+{
+ pclog("timer_reset\n");
+ timer_target = 0;
+ tsc = 0;
+ timer_head = NULL;
}
-void timer_set_callback(int timer, void (*callback)(void *priv))
+void timer_add(pc_timer_t *timer, void (*callback)(void *p), void *p, int start_timer)
{
- timers[timer].callback = callback;
+ memset(timer, 0, sizeof(pc_timer_t));
+
+ timer->callback = callback;
+ timer->p = p;
+ timer->enabled = 0;
+ timer->prev = timer->next = NULL;
+ if (start_timer)
+ timer_set_delay_u64(timer, 0);
}
#include "cpu.h"
-extern int timer_start;
-
-#define timer_start_period(cycles) \
- timer_start = cycles;
-
-#define timer_end_period(cycles) \
- do \
- { \
- int diff = timer_start - (cycles); \
- timer_count -= diff; \
- timer_start = cycles; \
- if (timer_count <= 0) \
- { \
- timer_process(); \
- timer_update_outstanding(); \
- } \
- } while (0)
-
-#define timer_clock() \
- do \
- { \
- int diff; \
- if (AT) \
- { \
- diff = timer_start - (cycles << TIMER_SHIFT); \
- timer_start = cycles << TIMER_SHIFT; \
- } \
- else \
- { \
- diff = timer_start - (cycles * xt_cpu_multi); \
- timer_start = cycles * xt_cpu_multi; \
- } \
- timer_count -= diff; \
- timer_process(); \
- timer_update_outstanding(); \
- } while (0)
+/*Timers are based on the CPU Time Stamp Counter. Timer timestamps are in a
+ 32:32 fixed point format, with the integer part compared against the TSC. The
+ fractional part is used when advancing the timestamp to ensure a more accurate
+ period.
+
+ As the timer only stores 32 bits of integer timestamp, and the TSC is 64 bits,
+ the timer period can only be at most 0x7fffffff CPU cycles. To allow room for
+ (optimistic) CPU frequency growth, timer period must be at most 1 second.
+ When a timer callback is called, the timer has been disabled. If the timer is
+ to repeat, the callback must call timer_advance_u64(). This is a change from
+ the old timer API.*/
+typedef struct pc_timer_t
+{
+ uint32_t ts_integer;
+ uint32_t ts_frac;
+ int enabled;
+
+ void (*callback)(void *p);
+ void *p;
+
+ struct pc_timer_t *prev, *next;
+} pc_timer_t;
+
+/*Timestamp of nearest enabled timer. CPU emulation must call timer_process()
+ when TSC matches or exceeds this.*/
+extern uint32_t timer_target;
+
+/*Enable timer, without updating timestamp*/
+void timer_enable(pc_timer_t *timer);
+/*Disable timer*/
+void timer_disable(pc_timer_t *timer);
+
+/*Process any pending timers*/
void timer_process();
-void timer_update_outstanding();
+
+/*Reset timer system*/
void timer_reset();
-int timer_add(void (*callback)(void *priv), int *count, int *enable, void *priv);
-void timer_set_callback(int timer, void (*callback)(void *priv));
-#define TIMER_ALWAYS_ENABLED &timer_one
+/*Add new timer. If start_timer is set, timer will be enabled with a zero
+ timestamp - this is useful for permanently enabled timers*/
+void timer_add(pc_timer_t *timer, void (*callback)(void *p), void *p, int start_timer);
+
+/*1us in 32:32 format*/
+extern uint64_t TIMER_USEC;
+
+/*True if timer a expires before timer b*/
+#define TIMER_LESS_THAN(a, b) ((int32_t)((a)->ts_integer - (b)->ts_integer) <= 0)
+/*True if timer a expires before 32 bit integer timestamp b*/
+#define TIMER_LESS_THAN_VAL(a, b) ((int32_t)((a)->ts_integer - (b)) <= 0)
+/*True if 32 bit integer timestamp a expires before 32 bit integer timestamp b*/
+#define TIMER_VAL_LESS_THAN_VAL(a, b) ((int32_t)((a) - (b)) <= 0)
+
+/*Advance timer by delay, specified in 32:32 format. This should be used to
+ resume a recurring timer in a callback routine*/
+static inline void timer_advance_u64(pc_timer_t *timer, uint64_t delay)
+{
+ uint32_t int_delay = delay >> 32;
+ uint32_t frac_delay = delay & 0xffffffff;
+
+ if ((frac_delay + timer->ts_frac) < frac_delay)
+ timer->ts_integer++;
+ timer->ts_frac += frac_delay;
+ timer->ts_integer += int_delay;
+
+ timer_enable(timer);
+}
+
+/*Set a timer to the given delay, specified in 32:32 format. This should be used
+ when starting a timer*/
+static inline void timer_set_delay_u64(pc_timer_t *timer, uint64_t delay)
+{
+ uint32_t int_delay = delay >> 32;
+ uint32_t frac_delay = delay & 0xffffffff;
+
+ timer->ts_frac = frac_delay;
+ timer->ts_integer = int_delay + (uint32_t)tsc;
+
+ timer_enable(timer);
+}
+
+/*True if timer currently enabled*/
+static inline int timer_is_enabled(pc_timer_t *timer)
+{
+ return timer->enabled;
+}
+
+/*Return integer timestamp of timer*/
+static inline uint32_t timer_get_ts_int(pc_timer_t *timer)
+{
+ return timer->ts_integer;
+}
+
+/*Return remaining time before timer expires, in us. If the timer has already
+ expired then return 0*/
+static inline uint32_t timer_get_remaining_us(pc_timer_t *timer)
+{
+ if (timer->enabled)
+ {
+ int64_t remaining = (((uint64_t)timer->ts_integer << 32) | timer->ts_frac) - (tsc << 32);
+
+ if (remaining < 0)
+ return 0;
+ return remaining / TIMER_USEC;
+ }
+
+ return 0;
+}
+
+/*Return remaining time before timer expires, in 32:32 timestamp format. If the
+ timer has already expired then return 0*/
+static inline uint64_t timer_get_remaining_u64(pc_timer_t *timer)
+{
+ if (timer->enabled)
+ {
+ int64_t remaining = (((uint64_t)timer->ts_integer << 32) | timer->ts_frac) - (tsc << 32);
-extern int timer_count;
-extern int timer_one;
+ if (remaining < 0)
+ return 0;
+ return remaining;
+ }
-#define TIMER_SHIFT 6
+ return 0;
+}
-extern int TIMER_USEC;
+/*Set timer callback function*/
+static inline void timer_set_callback(pc_timer_t *timer, void (*callback)(void *p))
+{
+ timer->callback = callback;
+}
+/*Set timer private data*/
+static inline void timer_set_p(pc_timer_t *timer, void *p)
+{
+ timer->p = p;
+}
#endif /*_TIMER_H_*/
--- /dev/null
+/*Cirrus Logic CL-GD5429 emulation*/
+#include <stdlib.h>
+#include "ibm.h"
+#include "cpu.h"
+#include "device.h"
+#include "io.h"
+#include "mca.h"
+#include "mem.h"
+#include "pci.h"
+#include "rom.h"
+#include "video.h"
+#include "vid_cl5429.h"
+#include "vid_svga.h"
+#include "vid_svga_render.h"
+#include "vid_vga.h"
+#include "vid_unk_ramdac.h"
+
+enum
+{
+ CL_TYPE_AVGA2 = 0,
+ CL_TYPE_GD5426,
+ CL_TYPE_GD5428,
+ CL_TYPE_GD5429,
+ CL_TYPE_GD5430,
+ CL_TYPE_GD5434
+};
+
+#define BLIT_DEPTH_8 0
+#define BLIT_DEPTH_16 1
+#define BLIT_DEPTH_32 3
+
+#define CL_GD5428_SYSTEM_BUS_MCA 5
+#define CL_GD5428_SYSTEM_BUS_VESA 6
+#define CL_GD5428_SYSTEM_BUS_ISA 7
+
+#define CL_GD5429_SYSTEM_BUS_VESA 5
+#define CL_GD5429_SYSTEM_BUS_ISA 7
+
+#define CL_GD543X_SYSTEM_BUS_PCI 4
+#define CL_GD543X_SYSTEM_BUS_VESA 6
+#define CL_GD543X_SYSTEM_BUS_ISA 7
+
+typedef struct gd5429_t
+{
+ mem_mapping_t mmio_mapping;
+ mem_mapping_t linear_mapping;
+
+ svga_t svga;
+
+ rom_t bios_rom;
+
+ uint32_t bank[2];
+ uint32_t mask;
+
+ uint32_t vram_mask;
+
+ int type;
+
+ struct
+ {
+ uint32_t bg_col, fg_col;
+ uint16_t trans_col, trans_mask;
+ uint16_t width, height;
+ uint16_t dst_pitch, src_pitch;
+ uint32_t dst_addr, src_addr;
+ uint8_t mask, mode, rop;
+
+ uint32_t dst_addr_backup, src_addr_backup;
+ uint16_t width_backup, height_internal;
+ int x_count, y_count;
+ int depth;
+
+ int mem_word_sel;
+ uint16_t mem_word_save;
+ } blt;
+
+ uint8_t hidden_dac_reg;
+ int dac_3c6_count;
+
+ uint8_t pci_regs[256];
+ uint8_t int_line;
+ int card;
+
+ uint8_t pos_regs[8];
+ svga_t *mb_vga;
+
+ uint32_t lfb_base;
+
+ int mmio_vram_overlap;
+
+ uint8_t sr10_read, sr11_read;
+
+ uint8_t latch_ext[4];
+
+ int vidsys_ena;
+} gd5429_t;
+
+#define GRB_X8_ADDRESSING (1 << 1)
+#define GRB_WRITEMODE_EXT (1 << 2)
+#define GRB_8B_LATCHES (1 << 3)
+
+static void gd5429_mmio_write(uint32_t addr, uint8_t val, void *p);
+static void gd5429_mmio_writew(uint32_t addr, uint16_t val, void *p);
+static void gd5429_mmio_writel(uint32_t addr, uint32_t val, void *p);
+static uint8_t gd5429_mmio_read(uint32_t addr, void *p);
+static uint16_t gd5429_mmio_readw(uint32_t addr, void *p);
+static uint32_t gd5429_mmio_readl(uint32_t addr, void *p);
+
+void gd5429_blt_write_w(uint32_t addr, uint16_t val, void *p);
+void gd5429_blt_write_l(uint32_t addr, uint32_t val, void *p);
+
+void gd5429_recalc_banking(gd5429_t *gd5429);
+void gd5429_recalc_mapping(gd5429_t *gd5429);
+
+uint8_t gd5429_read_linear(uint32_t addr, void *p);
+
+static void ibm_gd5428_mapping_update(gd5429_t *gd5429);
+
+void gd5429_out(uint16_t addr, uint8_t val, void *p)
+{
+ gd5429_t *gd5429 = (gd5429_t *)p;
+ svga_t *svga = &gd5429->svga;
+ uint8_t old;
+
+ if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1))
+ addr ^= 0x60;
+
+// pclog("gd5429 out %04X %02X\n", addr, val);
+
+ switch (addr)
+ {
+ case 0x3c3:
+ if (MCA)
+ {
+ gd5429->vidsys_ena = val & 1;
+ ibm_gd5428_mapping_update(gd5429);
+ }
+ break;
+
+ case 0x3c4:
+ svga->seqaddr = val;
+ break;
+ case 0x3c5:
+ if (svga->seqaddr > 5)
+ {
+ svga->seqregs[svga->seqaddr & 0x1f] = val;
+ switch (svga->seqaddr & 0x1f)
+ {
+ case 0x10: case 0x30: case 0x50: case 0x70:
+ case 0x90: case 0xb0: case 0xd0: case 0xf0:
+ svga->hwcursor.x = (val << 3) | ((svga->seqaddr >> 5) & 7);
+ gd5429->sr10_read = svga->seqaddr & 0xe0;
+// pclog("svga->hwcursor.x = %i\n", svga->hwcursor.x);
+ break;
+ case 0x11: case 0x31: case 0x51: case 0x71:
+ case 0x91: case 0xb1: case 0xd1: case 0xf1:
+ svga->hwcursor.y = (val << 3) | ((svga->seqaddr >> 5) & 7);
+ gd5429->sr11_read = svga->seqaddr & 0xe0;
+// pclog("svga->hwcursor.y = %i\n", svga->hwcursor.y);
+ break;
+ case 0x12:
+ svga->hwcursor.ena = val & 1;
+ svga->hwcursor.ysize = (val & 4) ? 64 : 32;
+ svga->hwcursor.yoff = 0;
+ if (svga->hwcursor.ysize == 64)
+ svga->hwcursor.addr = (0x3fc000 + ((svga->seqregs[0x13] & 0x3c) * 256)) & svga->vram_mask;
+ else
+ svga->hwcursor.addr = (0x3fc000 + ((svga->seqregs[0x13] & 0x3f) * 256)) & svga->vram_mask;
+// pclog("svga->hwcursor.ena = %i\n", svga->hwcursor.ena);
+ break;
+ case 0x13:
+ if (svga->hwcursor.ysize == 64)
+ svga->hwcursor.addr = (0x3fc000 + ((val & 0x3c) * 256)) & svga->vram_mask;
+ else
+ svga->hwcursor.addr = (0x3fc000 + ((val & 0x3f) * 256)) & svga->vram_mask;
+// pclog("svga->hwcursor.addr = %x\n", svga->hwcursor.addr);
+ break;
+
+ case 0x07:
+ svga->set_reset_disabled = svga->seqregs[7] & 1;
+ case 0x17:
+ if (gd5429->type >= CL_TYPE_GD5429)
+ gd5429_recalc_mapping(gd5429);
+ break;
+ }
+ return;
+ }
+ break;
+
+ case 0x3c6:
+// pclog("CL write 3c6 %02x %i\n", val, gd5429->dac_3c6_count);
+ if (gd5429->dac_3c6_count == 4)
+ {
+ gd5429->dac_3c6_count = 0;
+ gd5429->hidden_dac_reg = val;
+ svga_recalctimings(svga);
+ return;
+ }
+ gd5429->dac_3c6_count = 0;
+ break;
+ case 0x3c7: case 0x3c8: case 0x3c9:
+ gd5429->dac_3c6_count = 0;
+ break;
+
+ case 0x3cf:
+// pclog("Write GDC %02x %02x\n", svga->gdcaddr, val);
+ if (svga->gdcaddr == 0)
+ gd5429_mmio_write(0xb8000, val, gd5429);
+ if (svga->gdcaddr == 1)
+ gd5429_mmio_write(0xb8004, val, gd5429);
+ if (svga->gdcaddr == 5)
+ {
+ svga->gdcreg[5] = val;
+ if (svga->gdcreg[0xb] & 0x04)
+ svga->writemode = svga->gdcreg[5] & 7;
+ else
+ svga->writemode = svga->gdcreg[5] & 3;
+ svga->readmode = val & 8;
+ svga->chain2_read = val & 0x10;
+// pclog("writemode = %i\n", svga->writemode);
+ return;
+ }
+ if (svga->gdcaddr == 6)
+ {
+ if ((svga->gdcreg[6] & 0xc) != (val & 0xc))
+ {
+ svga->gdcreg[6] = val;
+ gd5429_recalc_mapping(gd5429);
+ }
+
+ /*Hack - the Windows 3.x drivers for the GD5426/8 require VRAM wraparound
+ for pattern & cursor writes to work correctly, but the BIOSes require
+ no wrapping to detect memory size - albeit with odd/even mode enabled.
+ This may be a quirk of address mapping. So change wrapping mode based on
+ odd/even mode for now*/
+ if (gd5429->type == CL_TYPE_GD5426 || gd5429->type == CL_TYPE_GD5428)
+ {
+ if (val & 2) /*Odd/Even*/
+ svga->decode_mask = 0x1fffff;
+ else
+ svga->decode_mask = svga->vram_mask;
+ }
+
+ svga->gdcreg[6] = val;
+ return;
+ }
+ if (svga->gdcaddr > 8)
+ {
+ svga->gdcreg[svga->gdcaddr & 0x3f] = val;
+ if (gd5429->type < CL_TYPE_GD5426 && (svga->gdcaddr > 0xb))
+ return;
+ switch (svga->gdcaddr)
+ {
+ case 0x09: case 0x0a: case 0x0b:
+ gd5429_recalc_banking(gd5429);
+ if (svga->gdcreg[0xb] & 0x04)
+ svga->writemode = svga->gdcreg[5] & 7;
+ else
+ svga->writemode = svga->gdcreg[5] & 3;
+ break;
+
+ case 0x10:
+ gd5429_mmio_write(0xb8001, val, gd5429);
+ break;
+ case 0x11:
+ gd5429_mmio_write(0xb8005, val, gd5429);
+ break;
+ case 0x12:
+ gd5429_mmio_write(0xb8002, val, gd5429);
+ break;
+ case 0x13:
+ gd5429_mmio_write(0xb8006, val, gd5429);
+ break;
+ case 0x14:
+ gd5429_mmio_write(0xb8003, val, gd5429);
+ break;
+ case 0x15:
+ gd5429_mmio_write(0xb8007, val, gd5429);
+ break;
+
+ case 0x20:
+ gd5429_mmio_write(0xb8008, val, gd5429);
+ break;
+ case 0x21:
+ gd5429_mmio_write(0xb8009, val, gd5429);
+ break;
+ case 0x22:
+ gd5429_mmio_write(0xb800a, val, gd5429);
+ break;
+ case 0x23:
+ gd5429_mmio_write(0xb800b, val, gd5429);
+ break;
+ case 0x24:
+ gd5429_mmio_write(0xb800c, val, gd5429);
+ break;
+ case 0x25:
+ gd5429_mmio_write(0xb800d, val, gd5429);
+ break;
+ case 0x26:
+ gd5429_mmio_write(0xb800e, val, gd5429);
+ break;
+ case 0x27:
+ gd5429_mmio_write(0xb800f, val, gd5429);
+ break;
+
+ case 0x28:
+ gd5429_mmio_write(0xb8010, val, gd5429);
+ break;
+ case 0x29:
+ gd5429_mmio_write(0xb8011, val, gd5429);
+ break;
+ case 0x2a:
+ gd5429_mmio_write(0xb8012, val, gd5429);
+ break;
+
+ case 0x2c:
+ gd5429_mmio_write(0xb8014, val, gd5429);
+ break;
+ case 0x2d:
+ gd5429_mmio_write(0xb8015, val, gd5429);
+ break;
+ case 0x2e:
+ gd5429_mmio_write(0xb8016, val, gd5429);
+ break;
+
+ case 0x2f:
+ gd5429_mmio_write(0xb8017, val, gd5429);
+ break;
+ case 0x30:
+ gd5429_mmio_write(0xb8018, val, gd5429);
+ break;
+
+ case 0x32:
+ gd5429_mmio_write(0xb801a, val, gd5429);
+ break;
+
+ case 0x31:
+ gd5429_mmio_write(0xb8040, val, gd5429);
+ break;
+
+ case 0x34:
+ if (gd5429->type <= CL_TYPE_GD5428)
+ gd5429->blt.trans_col = (gd5429->blt.trans_col & 0xff00) | val;
+ break;
+ case 0x35:
+ if (gd5429->type <= CL_TYPE_GD5428)
+ gd5429->blt.trans_col = (gd5429->blt.trans_col & 0x00ff) | (val << 8);
+ break;
+ case 0x36:
+ if (gd5429->type <= CL_TYPE_GD5428)
+ gd5429->blt.trans_mask = (gd5429->blt.trans_mask & 0xff00) | val;
+ break;
+ case 0x37:
+ if (gd5429->type <= CL_TYPE_GD5428)
+ gd5429->blt.trans_mask = (gd5429->blt.trans_mask & 0x00ff) | (val << 8);
+ break;
+ }
+ return;
+ }
+ break;
+
+ case 0x3D4:
+ svga->crtcreg = val & 0x3f;
+ return;
+ case 0x3D5:
+ if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80))
+ return;
+ if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80))
+ val = (svga->crtc[7] & ~0x10) | (val & 0x10);
+ old = svga->crtc[svga->crtcreg];
+ svga->crtc[svga->crtcreg] = val;
+
+ if (old != val)
+ {
+ if (svga->crtcreg < 0xe || svga->crtcreg > 0x10)
+ {
+ svga->fullchange = changeframecount;
+ svga_recalctimings(svga);
+ }
+ }
+ break;
+ }
+ svga_out(addr, val, svga);
+}
+
+uint8_t gd5429_in(uint16_t addr, void *p)
+{
+ gd5429_t *gd5429 = (gd5429_t *)p;
+ svga_t *svga = &gd5429->svga;
+
+ if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1))
+ addr ^= 0x60;
+
+// if (addr != 0x3da) pclog("IN gd5429 %04X\n", addr);
+
+ switch (addr)
+ {
+ case 0x3c3:
+ if (MCA)
+ return gd5429->vidsys_ena;
+ break;
+
+ case 0x3c4:
+ if ((svga->seqaddr & 0x1f) == 0x10)
+ return (svga->seqaddr & 0x1f) | gd5429->sr10_read;
+ if ((svga->seqaddr & 0x1f) == 0x11)
+ return (svga->seqaddr & 0x1f) | gd5429->sr11_read;
+ return svga->seqaddr & 0x1f;
+
+ case 0x3c5:
+ if (svga->seqaddr > 5)
+ {
+ uint8_t temp;
+
+ switch (svga->seqaddr)
+ {
+ case 6:
+ return ((svga->seqregs[6] & 0x17) == 0x12) ? 0x12 : 0x0f;
+
+ case 0x17:
+ if (gd5429->type < CL_TYPE_GD5426)
+ break;
+ temp = svga->seqregs[0x17];
+ temp &= ~(7 << 3);
+ if (gd5429->type == CL_TYPE_GD5426 || gd5429->type == CL_TYPE_GD5428)
+ {
+ if (MCA)
+ temp |= (CL_GD5428_SYSTEM_BUS_MCA << 3);
+ else if (has_vlb)
+ temp |= (CL_GD5428_SYSTEM_BUS_VESA << 3);
+ else
+ temp |= (CL_GD5428_SYSTEM_BUS_ISA << 3);
+ }
+ else if (gd5429->type == CL_TYPE_GD5429)
+ {
+ if (has_vlb)
+ temp |= (CL_GD5429_SYSTEM_BUS_VESA << 3);
+ else
+ temp |= (CL_GD5429_SYSTEM_BUS_ISA << 3);
+ }
+ else
+ {
+ if (PCI)
+ temp |= (CL_GD543X_SYSTEM_BUS_PCI << 3);
+ else if (has_vlb)
+ temp |= (CL_GD543X_SYSTEM_BUS_VESA << 3);
+ else
+ temp |= (CL_GD543X_SYSTEM_BUS_ISA << 3);
+ }
+ return temp;
+ }
+ return svga->seqregs[svga->seqaddr & 0x3f];
+ }
+ break;
+
+ case 0x3c6:
+// pclog("CL read 3c6 %i\n", gd5429->dac_3c6_count);
+ if (gd5429->dac_3c6_count == 4)
+ {
+ gd5429->dac_3c6_count = 0;
+ return gd5429->hidden_dac_reg;
+ }
+ gd5429->dac_3c6_count++;
+ break;
+ case 0x3c7: case 0x3c8: case 0x3c9:
+ gd5429->dac_3c6_count = 0;
+ break;
+
+ case 0x3cf:
+ if (svga->gdcaddr > 8)
+ {
+ return svga->gdcreg[svga->gdcaddr & 0x3f];
+ }
+ break;
+
+ case 0x3D4:
+ return svga->crtcreg;
+ case 0x3D5:
+ switch (svga->crtcreg)
+ {
+ case 0x27: /*ID*/
+ switch (gd5429->type)
+ {
+ case CL_TYPE_AVGA2:
+ return 0x18; /*AVGA2*/
+ case CL_TYPE_GD5426:
+ return 0x90; /*GD5426*/
+ case CL_TYPE_GD5428:
+ return 0x98; /*GD5428*/
+ case CL_TYPE_GD5429:
+ return 0x9c; /*GD5429*/
+ case CL_TYPE_GD5430:
+ return 0xa0; /*GD5430*/
+ case CL_TYPE_GD5434:
+ return 0xa8; /*GD5434*/
+ }
+ break;
+ case 0x28: /*Class ID*/
+ if (gd5429->type == CL_TYPE_GD5430)
+ return 0xff; /*Standard CL-GD5430*/
+ break;
+ }
+ return svga->crtc[svga->crtcreg];
+ }
+ return svga_in(addr, svga);
+}
+
+void gd5429_recalc_banking(gd5429_t *gd5429)
+{
+ svga_t *svga = &gd5429->svga;
+
+ if (svga->gdcreg[0xb] & 0x20)
+ gd5429->bank[0] = (svga->gdcreg[0x09] & 0xff) << 14;
+ else
+ gd5429->bank[0] = svga->gdcreg[0x09] << 12;
+
+ if (svga->gdcreg[0xb] & 0x01)
+ {
+ if (svga->gdcreg[0xb] & 0x20)
+ gd5429->bank[1] = (svga->gdcreg[0x0a] & 0xff) << 14;
+ else
+ gd5429->bank[1] = svga->gdcreg[0x0a] << 12;
+ }
+ else
+ gd5429->bank[1] = gd5429->bank[0] + 0x8000;
+}
+
+void gd5429_recalc_mapping(gd5429_t *gd5429)
+{
+ svga_t *svga = &gd5429->svga;
+
+ if ((PCI && gd5429->type >= CL_TYPE_GD5430 && !(gd5429->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_MEM)) ||
+ (MCA && (!(gd5429->pos_regs[2] & 0x01) || !gd5429->vidsys_ena)))
+ {
+ mem_mapping_disable(&svga->mapping);
+ mem_mapping_disable(&gd5429->linear_mapping);
+ mem_mapping_disable(&gd5429->mmio_mapping);
+ return;
+ }
+
+ gd5429->mmio_vram_overlap = 0;
+
+// pclog("Write mapping %02X %i\n", svga->gdcreg[6], svga->seqregs[0x17] & 0x04);
+ if (!(svga->seqregs[7] & 0xf0))
+ {
+ mem_mapping_disable(&gd5429->linear_mapping);
+ switch (svga->gdcreg[6] & 0x0C)
+ {
+ case 0x0: /*128k at A0000*/
+ mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000);
+ svga->banked_mask = 0xffff;
+ break;
+ case 0x4: /*64k at A0000*/
+ mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000);
+ svga->banked_mask = 0xffff;
+ break;
+ case 0x8: /*32k at B0000*/
+ mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000);
+ svga->banked_mask = 0x7fff;
+ break;
+ case 0xC: /*32k at B8000*/
+ mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000);
+ svga->banked_mask = 0x7fff;
+ gd5429->mmio_vram_overlap = 1;
+ break;
+ }
+ if (gd5429->type >= CL_TYPE_GD5429 && svga->seqregs[0x17] & 0x04)
+ mem_mapping_set_addr(&gd5429->mmio_mapping, 0xb8000, 0x00100);
+ else
+ mem_mapping_disable(&gd5429->mmio_mapping);
+ }
+ else
+ {
+ uint32_t base, size;
+
+ if (gd5429->type <= CL_TYPE_GD5429 || (!PCI && !has_vlb))
+ {
+ base = (svga->seqregs[7] & 0xf0) << 16;
+ if (svga->gdcreg[0xb] & 0x20)
+ size = 1 * 1024 * 1024;
+ else
+ size = 2 * 1024 * 1024;
+ }
+ else if (PCI)
+ {
+ base = gd5429->lfb_base;
+ size = 4 * 1024 * 1024;
+ }
+ else /*VLB*/
+ {
+ base = 128*1024*1024;
+ size = 4 * 1024 * 1024;
+ }
+ mem_mapping_disable(&svga->mapping);
+ mem_mapping_set_addr(&gd5429->linear_mapping, base, size);
+ if (gd5429->type >= CL_TYPE_GD5429 && svga->seqregs[0x17] & 0x04)
+ mem_mapping_set_addr(&gd5429->mmio_mapping, 0xb8000, 0x00100);
+ else
+ mem_mapping_disable(&gd5429->mmio_mapping);
+ }
+}
+
+void gd5429_recalctimings(svga_t *svga)
+{
+ gd5429_t *gd5429 = (gd5429_t *)svga->p;
+ int clock = (svga->miscout >> 2) & 3;
+ int n, d, p;
+ double vclk;
+
+ if (svga->crtc[0x1b] & 0x10)
+ svga->rowoffset |= 0x100;
+
+ if (!svga->rowoffset)
+ svga->rowoffset = 0x100;
+
+ svga->interlace = svga->crtc[0x1a] & 1;
+
+ if (svga->seqregs[7] & 0x01)
+ svga->render = svga_render_8bpp_highres;
+
+ svga->ma_latch |= ((svga->crtc[0x1b] & 0x01) << 16) | ((svga->crtc[0x1b] & 0xc) << 15);
+// pclog("MA now %05X %02X\n", svga->ma_latch, svga->crtc[0x1b]);
+
+ svga->bpp = 8;
+ if (gd5429->hidden_dac_reg & 0x80)
+ {
+ if (gd5429->hidden_dac_reg & 0x40)
+ {
+ switch (gd5429->hidden_dac_reg & 0xf)
+ {
+ case 0x0:
+ svga->render = svga_render_15bpp_highres;
+ svga->bpp = 15;
+ break;
+ case 0x1:
+ svga->render = svga_render_16bpp_highres;
+ svga->bpp = 16;
+ break;
+ case 0x5:
+ if (gd5429->type >= CL_TYPE_GD5434 && (svga->seqregs[7] & 8))
+ {
+ svga->render = svga_render_32bpp_highres;
+ svga->bpp = 32;
+ svga->rowoffset *= 2;
+ }
+ else
+ {
+ svga->render = svga_render_24bpp_highres;
+ svga->bpp = 24;
+ }
+ break;
+ }
+ }
+ else
+ {
+ svga->render = svga_render_15bpp_highres;
+ svga->bpp = 15;
+ }
+ }
+
+ n = svga->seqregs[0xb + clock] & 0x7f;
+ d = (svga->seqregs[0x1b + clock] >> 1) & 0x1f;
+ p = svga->seqregs[0x1b + clock] & 1;
+
+ /*Prevent divide by zero during clock setup*/
+ if (d && n)
+ vclk = (14318184.0 * ((float)n / (float)d)) / (float)(1 + p);
+ else
+ vclk = 14318184.0;
+ switch (svga->seqregs[7] & ((gd5429->type >= CL_TYPE_GD5434) ? 0xe : 0x6))
+ {
+ case 2:
+ vclk /= 2.0;
+ break;
+ case 4:
+ vclk /= 3.0;
+ break;
+ }
+ svga->clock = (cpuclock * (float)(1ull << 32)) / vclk;
+
+ svga->vram_display_mask = (svga->crtc[0x1b] & 2) ? gd5429->vram_mask : 0x3ffff;
+}
+
+void gd5429_hwcursor_draw(svga_t *svga, int displine)
+{
+ int x;
+ uint8_t dat[2];
+ int xx;
+ int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff;
+ int line_offset = (svga->seqregs[0x12] & 0x04) ? 16 : 4;
+
+ if (svga->interlace && svga->hwcursor_oddeven)
+ svga->hwcursor_latch.addr += line_offset;
+
+ if (svga->seqregs[0x12] & 0x04)
+ {
+ for (x = 0; x < 64; x += 8)
+ {
+ dat[0] = svga->vram[svga->hwcursor_latch.addr];
+ dat[1] = svga->vram[svga->hwcursor_latch.addr + 8];
+ for (xx = 0; xx < 8; xx++)
+ {
+ if (offset >= svga->hwcursor_latch.x)
+ {
+ if (dat[1] & 0x80)
+ ((uint32_t *)buffer32->line[displine])[offset + 32] = 0;
+ if (dat[0] & 0x80)
+ ((uint32_t *)buffer32->line[displine])[offset + 32] ^= 0xffffff;
+ }
+
+ offset++;
+ dat[0] <<= 1;
+ dat[1] <<= 1;
+ }
+ svga->hwcursor_latch.addr++;
+ }
+ svga->hwcursor_latch.addr += 8;
+ }
+ else
+ {
+ for (x = 0; x < 32; x += 8)
+ {
+ dat[0] = svga->vram[svga->hwcursor_latch.addr];
+ dat[1] = svga->vram[svga->hwcursor_latch.addr + 0x80];
+ for (xx = 0; xx < 8; xx++)
+ {
+ if (offset >= svga->hwcursor_latch.x)
+ {
+ if (dat[1] & 0x80)
+ ((uint32_t *)buffer32->line[displine])[offset + 32] = 0;
+ if (dat[0] & 0x80)
+ ((uint32_t *)buffer32->line[displine])[offset + 32] ^= 0xffffff;
+ }
+
+ offset++;
+ dat[0] <<= 1;
+ dat[1] <<= 1;
+ }
+ svga->hwcursor_latch.addr++;
+ }
+ }
+
+ if (svga->interlace && !svga->hwcursor_oddeven)
+ svga->hwcursor_latch.addr += line_offset;
+}
+
+
+void gd5429_write_linear(uint32_t addr, uint8_t val, void *p);
+
+static void gd5429_write(uint32_t addr, uint8_t val, void *p)
+{
+ gd5429_t *gd5429 = (gd5429_t *)p;
+ svga_t *svga = &gd5429->svga;
+
+ addr &= svga->banked_mask;
+ addr = (addr & 0x7fff) + gd5429->bank[(addr >> 15) & 1];
+
+ gd5429_write_linear(addr, val, p);
+}
+static void gd5429_writew(uint32_t addr, uint16_t val, void *p)
+{
+ gd5429_t *gd5429 = (gd5429_t *)p;
+ svga_t *svga = &gd5429->svga;
+
+ addr &= svga->banked_mask;
+ addr = (addr & 0x7fff) + gd5429->bank[(addr >> 15) & 1];
+
+ if ((svga->writemode < 4) && !(svga->gdcreg[0xb] & (GRB_X8_ADDRESSING | GRB_8B_LATCHES)))
+ svga_writew_linear(addr, val, svga);
+ else
+ {
+ gd5429_write_linear(addr, val, p);
+ gd5429_write_linear(addr+1, val >> 8, p);
+ }
+}
+static void gd5429_writel(uint32_t addr, uint32_t val, void *p)
+{
+ gd5429_t *gd5429 = (gd5429_t *)p;
+ svga_t *svga = &gd5429->svga;
+
+ addr &= svga->banked_mask;
+ addr = (addr & 0x7fff) + gd5429->bank[(addr >> 15) & 1];
+
+ if ((svga->writemode < 4) && !(svga->gdcreg[0xb] & (GRB_X8_ADDRESSING | GRB_8B_LATCHES)))
+ svga_writel_linear(addr, val, svga);
+ else
+ {
+ gd5429_write_linear(addr, val, p);
+ gd5429_write_linear(addr+1, val >> 8, p);
+ gd5429_write_linear(addr+2, val >> 16, p);
+ gd5429_write_linear(addr+3, val >> 24, p);
+ }
+}
+
+static uint8_t gd5429_read(uint32_t addr, void *p)
+{
+ gd5429_t *gd5429 = (gd5429_t *)p;
+ svga_t *svga = &gd5429->svga;
+
+ addr &= svga->banked_mask;
+ addr = (addr & 0x7fff) + gd5429->bank[(addr >> 15) & 1];
+ return gd5429_read_linear(addr, gd5429);
+}
+static uint16_t gd5429_readw(uint32_t addr, void *p)
+{
+ gd5429_t *gd5429 = (gd5429_t *)p;
+ svga_t *svga = &gd5429->svga;
+
+ addr &= svga->banked_mask;
+ addr = (addr & 0x7fff) + gd5429->bank[(addr >> 15) & 1];
+
+ if (!(svga->gdcreg[0xb] & (GRB_X8_ADDRESSING | GRB_8B_LATCHES)))
+ return svga_readw_linear(addr, &gd5429->svga);
+ return gd5429_read_linear(addr, gd5429) | (gd5429_read_linear(addr+1, gd5429) << 8);
+}
+static uint32_t gd5429_readl(uint32_t addr, void *p)
+{
+ gd5429_t *gd5429 = (gd5429_t *)p;
+ svga_t *svga = &gd5429->svga;
+
+ addr &= svga->banked_mask;
+ addr = (addr & 0x7fff) + gd5429->bank[(addr >> 15) & 1];
+
+ if (!(svga->gdcreg[0xb] & (GRB_X8_ADDRESSING | GRB_8B_LATCHES)))
+ return svga_readl_linear(addr, &gd5429->svga);
+ return gd5429_read_linear(addr, gd5429) | (gd5429_read_linear(addr+1, gd5429) << 8) |
+ (gd5429_read_linear(addr+2, gd5429) << 16) | (gd5429_read_linear(addr+3, gd5429) << 24);
+}
+
+void gd5429_write_linear(uint32_t addr, uint8_t val, void *p)
+{
+ gd5429_t *gd5429 = (gd5429_t *)p;
+ svga_t *svga = &gd5429->svga;
+ uint8_t vala, valb, valc, vald, wm = svga->writemask;
+ int writemask2 = svga->seqregs[2];
+
+ cycles -= video_timing_write_b;
+ cycles_lost += video_timing_write_b;
+
+ egawrites++;
+
+// if (svga_output) pclog("Write LFB %08X %02X ", addr, val);
+ if (!(svga->gdcreg[6] & 1))
+ svga->fullchange = 2;
+ if (svga->gdcreg[0xb] & GRB_X8_ADDRESSING)
+ addr <<= 3;
+ else if ((svga->chain4 || svga->fb_only) && (svga->writemode < 4))
+ {
+ writemask2 = 1 << (addr & 3);
+ addr &= ~3;
+ }
+ else if (svga->chain2_write)
+ {
+ writemask2 &= ~0xa;
+ if (addr & 1)
+ writemask2 <<= 1;
+ addr &= ~1;
+ addr <<= 2;
+ }
+ else
+ {
+ addr <<= 2;
+ }
+ addr &= svga->decode_mask;
+ if (addr >= svga->vram_max)
+ return;
+ addr &= svga->vram_mask;
+// if (svga_output) pclog("%08X\n", addr);
+ svga->changedvram[addr >> 12] = changeframecount;
+
+ switch (svga->writemode)
+ {
+ case 4:
+ if (svga->gdcreg[0xb] & 0x10)
+ {
+// pclog("Writemode 4 : %X ", addr);
+ addr <<= 2;
+ svga->changedvram[addr >> 12] = changeframecount;
+// pclog("%X %X %02x\n", addr, val, svga->gdcreg[0xb]);
+ if (val & svga->seqregs[2] & 0x80)
+ {
+ svga->vram[addr + 0] = svga->gdcreg[1];
+ svga->vram[addr + 1] = svga->gdcreg[0x11];
+ }
+ if (val & svga->seqregs[2] & 0x40)
+ {
+ svga->vram[addr + 2] = svga->gdcreg[1];
+ svga->vram[addr + 3] = svga->gdcreg[0x11];
+ }
+ if (val & svga->seqregs[2] & 0x20)
+ {
+ svga->vram[addr + 4] = svga->gdcreg[1];
+ svga->vram[addr + 5] = svga->gdcreg[0x11];
+ }
+ if (val & svga->seqregs[2] & 0x10)
+ {
+ svga->vram[addr + 6] = svga->gdcreg[1];
+ svga->vram[addr + 7] = svga->gdcreg[0x11];
+ }
+ if (val & svga->seqregs[2] & 0x08)
+ {
+ svga->vram[addr + 8] = svga->gdcreg[1];
+ svga->vram[addr + 9] = svga->gdcreg[0x11];
+ }
+ if (val & svga->seqregs[2] & 0x04)
+ {
+ svga->vram[addr + 10] = svga->gdcreg[1];
+ svga->vram[addr + 11] = svga->gdcreg[0x11];
+ }
+ if (val & svga->seqregs[2] & 0x02)
+ {
+ svga->vram[addr + 12] = svga->gdcreg[1];
+ svga->vram[addr + 13] = svga->gdcreg[0x11];
+ }
+ if (val & svga->seqregs[2] & 0x01)
+ {
+ svga->vram[addr + 14] = svga->gdcreg[1];
+ svga->vram[addr + 15] = svga->gdcreg[0x11];
+ }
+ }
+ else
+ {
+// pclog("Writemode 4 : %X ", addr);
+ svga->changedvram[addr >> 12] = changeframecount;
+// pclog("%X %X %02x\n", addr, val, svga->gdcreg[0xb]);
+ if (val & svga->seqregs[2] & 0x80)
+ svga->vram[addr + 0] = svga->gdcreg[1];
+ if (val & svga->seqregs[2] & 0x40)
+ svga->vram[addr + 1] = svga->gdcreg[1];
+ if (val & svga->seqregs[2] & 0x20)
+ svga->vram[addr + 2] = svga->gdcreg[1];
+ if (val & svga->seqregs[2] & 0x10)
+ svga->vram[addr + 3] = svga->gdcreg[1];
+ if (val & svga->seqregs[2] & 0x08)
+ svga->vram[addr + 4] = svga->gdcreg[1];
+ if (val & svga->seqregs[2] & 0x04)
+ svga->vram[addr + 5] = svga->gdcreg[1];
+ if (val & svga->seqregs[2] & 0x02)
+ svga->vram[addr + 6] = svga->gdcreg[1];
+ if (val & svga->seqregs[2] & 0x01)
+ svga->vram[addr + 7] = svga->gdcreg[1];
+ }
+ break;
+
+ case 5:
+ if (svga->gdcreg[0xb] & 0x10)
+ {
+// pclog("Writemode 5 : %X ", addr);
+ addr <<= 2;
+ svga->changedvram[addr >> 12] = changeframecount;
+// pclog("%X %X %02x\n", addr, val, svga->gdcreg[0xb]);
+ if (svga->seqregs[2] & 0x80)
+ {
+ svga->vram[addr + 0] = (val & 0x80) ? svga->gdcreg[1] : svga->gdcreg[0];
+ svga->vram[addr + 1] = (val & 0x80) ? svga->gdcreg[0x11] : svga->gdcreg[0x10];
+ }
+ if (svga->seqregs[2] & 0x40)
+ {
+ svga->vram[addr + 2] = (val & 0x40) ? svga->gdcreg[1] : svga->gdcreg[0];
+ svga->vram[addr + 3] = (val & 0x40) ? svga->gdcreg[0x11] : svga->gdcreg[0x10];
+ }
+ if (svga->seqregs[2] & 0x20)
+ {
+ svga->vram[addr + 4] = (val & 0x20) ? svga->gdcreg[1] : svga->gdcreg[0];
+ svga->vram[addr + 5] = (val & 0x20) ? svga->gdcreg[0x11] : svga->gdcreg[0x10];
+ }
+ if (svga->seqregs[2] & 0x10)
+ {
+ svga->vram[addr + 6] = (val & 0x10) ? svga->gdcreg[1] : svga->gdcreg[0];
+ svga->vram[addr + 7] = (val & 0x10) ? svga->gdcreg[0x11] : svga->gdcreg[0x10];
+ }
+ if (svga->seqregs[2] & 0x08)
+ {
+ svga->vram[addr + 8] = (val & 0x08) ? svga->gdcreg[1] : svga->gdcreg[0];
+ svga->vram[addr + 9] = (val & 0x08) ? svga->gdcreg[0x11] : svga->gdcreg[0x10];
+ }
+ if (svga->seqregs[2] & 0x04)
+ {
+ svga->vram[addr + 10] = (val & 0x04) ? svga->gdcreg[1] : svga->gdcreg[0];
+ svga->vram[addr + 11] = (val & 0x04) ? svga->gdcreg[0x11] : svga->gdcreg[0x10];
+ }
+ if (svga->seqregs[2] & 0x02)
+ {
+ svga->vram[addr + 12] = (val & 0x02) ? svga->gdcreg[1] : svga->gdcreg[0];
+ svga->vram[addr + 13] = (val & 0x02) ? svga->gdcreg[0x11] : svga->gdcreg[0x10];
+ }
+ if (svga->seqregs[2] & 0x01)
+ {
+ svga->vram[addr + 14] = (val & 0x01) ? svga->gdcreg[1] : svga->gdcreg[0];
+ svga->vram[addr + 15] = (val & 0x01) ? svga->gdcreg[0x11] : svga->gdcreg[0x10];
+ }
+ }
+ else
+ {
+// pclog("Writemode 5 : %X ", addr);
+ svga->changedvram[addr >> 12] = changeframecount;
+// pclog("%X %X %02x\n", addr, val, svga->gdcreg[0xb]);
+ if (svga->seqregs[2] & 0x80)
+ svga->vram[addr + 0] = (val & 0x80) ? svga->gdcreg[1] : svga->gdcreg[0];
+ if (svga->seqregs[2] & 0x40)
+ svga->vram[addr + 1] = (val & 0x40) ? svga->gdcreg[1] : svga->gdcreg[0];
+ if (svga->seqregs[2] & 0x20)
+ svga->vram[addr + 2] = (val & 0x20) ? svga->gdcreg[1] : svga->gdcreg[0];
+ if (svga->seqregs[2] & 0x10)
+ svga->vram[addr + 3] = (val & 0x10) ? svga->gdcreg[1] : svga->gdcreg[0];
+ if (svga->seqregs[2] & 0x08)
+ svga->vram[addr + 4] = (val & 0x08) ? svga->gdcreg[1] : svga->gdcreg[0];
+ if (svga->seqregs[2] & 0x04)
+ svga->vram[addr + 5] = (val & 0x04) ? svga->gdcreg[1] : svga->gdcreg[0];
+ if (svga->seqregs[2] & 0x02)
+ svga->vram[addr + 6] = (val & 0x02) ? svga->gdcreg[1] : svga->gdcreg[0];
+ if (svga->seqregs[2] & 0x01)
+ svga->vram[addr + 7] = (val & 0x01) ? svga->gdcreg[1] : svga->gdcreg[0];
+ }
+ break;
+
+ case 1:
+ if (svga->gdcreg[0xb] & GRB_WRITEMODE_EXT)
+ {
+ if (writemask2 & 0x80) svga->vram[addr] = svga->la;
+ if (writemask2 & 0x40) svga->vram[addr | 0x1] = svga->lb;
+ if (writemask2 & 0x20) svga->vram[addr | 0x2] = svga->lc;
+ if (writemask2 & 0x10) svga->vram[addr | 0x3] = svga->ld;
+ if (svga->gdcreg[0xb] & GRB_8B_LATCHES)
+ {
+ if (writemask2 & 0x08) svga->vram[addr | 0x4] = gd5429->latch_ext[0];
+ if (writemask2 & 0x04) svga->vram[addr | 0x5] = gd5429->latch_ext[1];
+ if (writemask2 & 0x02) svga->vram[addr | 0x6] = gd5429->latch_ext[2];
+ if (writemask2 & 0x01) svga->vram[addr | 0x7] = gd5429->latch_ext[3];
+ }
+ }
+ else
+ {
+ if (writemask2 & 1) svga->vram[addr] = svga->la;
+ if (writemask2 & 2) svga->vram[addr | 0x1] = svga->lb;
+ if (writemask2 & 4) svga->vram[addr | 0x2] = svga->lc;
+ if (writemask2 & 8) svga->vram[addr | 0x3] = svga->ld;
+ }
+ break;
+ case 0:
+ if (svga->gdcreg[3] & 7)
+ val = svga_rotate[svga->gdcreg[3] & 7][val];
+ if (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && (!svga->gdcreg[1] || svga->set_reset_disabled))
+ {
+ if (writemask2 & 1) svga->vram[addr] = val;
+ if (writemask2 & 2) svga->vram[addr | 0x1] = val;
+ if (writemask2 & 4) svga->vram[addr | 0x2] = val;
+ if (writemask2 & 8) svga->vram[addr | 0x3] = val;
+ }
+ else
+ {
+ if (svga->gdcreg[1] & 1) vala = (svga->gdcreg[0] & 1) ? 0xff : 0;
+ else vala = val;
+ if (svga->gdcreg[1] & 2) valb = (svga->gdcreg[0] & 2) ? 0xff : 0;
+ else valb = val;
+ if (svga->gdcreg[1] & 4) valc = (svga->gdcreg[0] & 4) ? 0xff : 0;
+ else valc = val;
+ if (svga->gdcreg[1] & 8) vald = (svga->gdcreg[0] & 8) ? 0xff : 0;
+ else vald = val;
+
+ switch (svga->gdcreg[3] & 0x18)
+ {
+ case 0: /*Set*/
+ if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]);
+ if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]);
+ if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | (svga->lc & ~svga->gdcreg[8]);
+ if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | (svga->ld & ~svga->gdcreg[8]);
+ break;
+ case 8: /*AND*/
+ if (writemask2 & 1) svga->vram[addr] = (vala | ~svga->gdcreg[8]) & svga->la;
+ if (writemask2 & 2) svga->vram[addr | 0x1] = (valb | ~svga->gdcreg[8]) & svga->lb;
+ if (writemask2 & 4) svga->vram[addr | 0x2] = (valc | ~svga->gdcreg[8]) & svga->lc;
+ if (writemask2 & 8) svga->vram[addr | 0x3] = (vald | ~svga->gdcreg[8]) & svga->ld;
+ break;
+ case 0x10: /*OR*/
+ if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | svga->la;
+ if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | svga->lb;
+ if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | svga->lc;
+ if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | svga->ld;
+ break;
+ case 0x18: /*XOR*/
+ if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) ^ svga->la;
+ if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) ^ svga->lb;
+ if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) ^ svga->lc;
+ if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) ^ svga->ld;
+ break;
+ }
+// pclog("- %02X %02X %02X %02X %08X\n",vram[addr],vram[addr|0x1],vram[addr|0x2],vram[addr|0x3],addr);
+ }
+ break;
+ case 2:
+ if (!(svga->gdcreg[3] & 0x18) && !svga->gdcreg[1])
+ {
+ if (writemask2 & 1) svga->vram[addr] = (((val & 1) ? 0xff : 0) & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]);
+ if (writemask2 & 2) svga->vram[addr | 0x1] = (((val & 2) ? 0xff : 0) & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]);
+ if (writemask2 & 4) svga->vram[addr | 0x2] = (((val & 4) ? 0xff : 0) & svga->gdcreg[8]) | (svga->lc & ~svga->gdcreg[8]);
+ if (writemask2 & 8) svga->vram[addr | 0x3] = (((val & 8) ? 0xff : 0) & svga->gdcreg[8]) | (svga->ld & ~svga->gdcreg[8]);
+ }
+ else
+ {
+ vala = ((val & 1) ? 0xff : 0);
+ valb = ((val & 2) ? 0xff : 0);
+ valc = ((val & 4) ? 0xff : 0);
+ vald = ((val & 8) ? 0xff : 0);
+ switch (svga->gdcreg[3] & 0x18)
+ {
+ case 0: /*Set*/
+ if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]);
+ if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]);
+ if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | (svga->lc & ~svga->gdcreg[8]);
+ if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | (svga->ld & ~svga->gdcreg[8]);
+ break;
+ case 8: /*AND*/
+ if (writemask2 & 1) svga->vram[addr] = (vala | ~svga->gdcreg[8]) & svga->la;
+ if (writemask2 & 2) svga->vram[addr | 0x1] = (valb | ~svga->gdcreg[8]) & svga->lb;
+ if (writemask2 & 4) svga->vram[addr | 0x2] = (valc | ~svga->gdcreg[8]) & svga->lc;
+ if (writemask2 & 8) svga->vram[addr | 0x3] = (vald | ~svga->gdcreg[8]) & svga->ld;
+ break;
+ case 0x10: /*OR*/
+ if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | svga->la;
+ if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | svga->lb;
+ if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | svga->lc;
+ if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | svga->ld;
+ break;
+ case 0x18: /*XOR*/
+ if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) ^ svga->la;
+ if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) ^ svga->lb;
+ if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) ^ svga->lc;
+ if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) ^ svga->ld;
+ break;
+ }
+ }
+ break;
+ case 3:
+ if (svga->gdcreg[3] & 7)
+ val = svga_rotate[svga->gdcreg[3] & 7][val];
+ wm = svga->gdcreg[8];
+ svga->gdcreg[8] &= val;
+
+ vala = (svga->gdcreg[0] & 1) ? 0xff : 0;
+ valb = (svga->gdcreg[0] & 2) ? 0xff : 0;
+ valc = (svga->gdcreg[0] & 4) ? 0xff : 0;
+ vald = (svga->gdcreg[0] & 8) ? 0xff : 0;
+ switch (svga->gdcreg[3] & 0x18)
+ {
+ case 0: /*Set*/
+ if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]);
+ if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]);
+ if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | (svga->lc & ~svga->gdcreg[8]);
+ if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | (svga->ld & ~svga->gdcreg[8]);
+ break;
+ case 8: /*AND*/
+ if (writemask2 & 1) svga->vram[addr] = (vala | ~svga->gdcreg[8]) & svga->la;
+ if (writemask2 & 2) svga->vram[addr | 0x1] = (valb | ~svga->gdcreg[8]) & svga->lb;
+ if (writemask2 & 4) svga->vram[addr | 0x2] = (valc | ~svga->gdcreg[8]) & svga->lc;
+ if (writemask2 & 8) svga->vram[addr | 0x3] = (vald | ~svga->gdcreg[8]) & svga->ld;
+ break;
+ case 0x10: /*OR*/
+ if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | svga->la;
+ if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | svga->lb;
+ if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | svga->lc;
+ if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | svga->ld;
+ break;
+ case 0x18: /*XOR*/
+ if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) ^ svga->la;
+ if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) ^ svga->lb;
+ if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) ^ svga->lc;
+ if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) ^ svga->ld;
+ break;
+ }
+ svga->gdcreg[8] = wm;
+ break;
+ }
+}
+
+uint8_t gd5429_read_linear(uint32_t addr, void *p)
+{
+ gd5429_t *gd5429 = (gd5429_t *)p;
+ svga_t *svga = &gd5429->svga;
+ uint8_t temp, temp2, temp3, temp4;
+ int readplane = svga->readplane;
+ uint32_t latch_addr;
+
+ cycles -= video_timing_read_b;
+ cycles_lost += video_timing_read_b;
+
+ egareads++;
+
+ if (svga->gdcreg[0xb] & GRB_X8_ADDRESSING)
+ latch_addr = (addr << 3) & svga->decode_mask;
+ else
+ latch_addr = (addr << 2) & svga->decode_mask;
+
+ if (svga->gdcreg[0xb] & GRB_X8_ADDRESSING)
+ addr <<= 3;
+ else if (svga->chain4 || svga->fb_only)
+ {
+ addr &= svga->decode_mask;
+ if (addr >= svga->vram_max)
+ return 0xff;
+ return svga->vram[addr & svga->vram_mask];
+ }
+ else if (svga->chain2_read)
+ {
+ readplane = (readplane & 2) | (addr & 1);
+ addr &= ~1;
+ addr <<= 2;
+ }
+ else
+ addr<<=2;
+
+ addr &= svga->decode_mask;
+
+ if (latch_addr >= svga->vram_max)
+ {
+ svga->la = svga->lb = svga->lc = svga->ld = 0xff;
+ if (svga->gdcreg[0xb] & GRB_8B_LATCHES)
+ gd5429->latch_ext[0] = gd5429->latch_ext[1] = gd5429->latch_ext[2] = gd5429->latch_ext[3] = 0xff;
+ }
+ else
+ {
+ latch_addr &= svga->vram_mask;
+ svga->la = svga->vram[latch_addr];
+ svga->lb = svga->vram[latch_addr | 0x1];
+ svga->lc = svga->vram[latch_addr | 0x2];
+ svga->ld = svga->vram[latch_addr | 0x3];
+ if (svga->gdcreg[0xb] & GRB_8B_LATCHES)
+ {
+ gd5429->latch_ext[0] = svga->vram[latch_addr | 0x4];
+ gd5429->latch_ext[1] = svga->vram[latch_addr | 0x5];
+ gd5429->latch_ext[2] = svga->vram[latch_addr | 0x6];
+ gd5429->latch_ext[3] = svga->vram[latch_addr | 0x7];
+ }
+ }
+
+ if (addr >= svga->vram_max)
+ return 0xff;
+
+ addr &= svga->vram_mask;
+
+ if (svga->readmode)
+ {
+ temp = svga->la;
+ temp ^= (svga->colourcompare & 1) ? 0xff : 0;
+ temp &= (svga->colournocare & 1) ? 0xff : 0;
+ temp2 = svga->lb;
+ temp2 ^= (svga->colourcompare & 2) ? 0xff : 0;
+ temp2 &= (svga->colournocare & 2) ? 0xff : 0;
+ temp3 = svga->lc;
+ temp3 ^= (svga->colourcompare & 4) ? 0xff : 0;
+ temp3 &= (svga->colournocare & 4) ? 0xff : 0;
+ temp4 = svga->ld;
+ temp4 ^= (svga->colourcompare & 8) ? 0xff : 0;
+ temp4 &= (svga->colournocare & 8) ? 0xff : 0;
+ return ~(temp | temp2 | temp3 | temp4);
+ }
+//printf("Read %02X %04X %04X\n",vram[addr|svga->readplane],addr,svga->readplane);
+ return svga->vram[addr | readplane];
+}
+
+static void gd5429_writeb_linear(uint32_t addr, uint8_t val, void *p)
+{
+ gd5429_t *gd5429 = (gd5429_t *)p;
+ svga_t *svga = &gd5429->svga;
+
+ if ((svga->writemode < 4) && !(svga->gdcreg[0xb] & (GRB_X8_ADDRESSING | GRB_8B_LATCHES)))
+ svga_write_linear(addr, val, svga);
+ else
+ gd5429_write_linear(addr, val & 0xff, gd5429);
+}
+static void gd5429_writew_linear(uint32_t addr, uint16_t val, void *p)
+{
+ gd5429_t *gd5429 = (gd5429_t *)p;
+ svga_t *svga = &gd5429->svga;
+
+ if ((svga->writemode < 4) && !(svga->gdcreg[0xb] & (GRB_X8_ADDRESSING | GRB_8B_LATCHES)))
+ svga_writew_linear(addr, val, svga);
+ else
+ {
+ gd5429_write_linear(addr, val & 0xff, gd5429);
+ gd5429_write_linear(addr+1, val >> 8, gd5429);
+ }
+}
+static void gd5429_writel_linear(uint32_t addr, uint32_t val, void *p)
+{
+ gd5429_t *gd5429 = (gd5429_t *)p;
+ svga_t *svga = &gd5429->svga;
+
+ if ((svga->writemode < 4) && !(svga->gdcreg[0xb] & (GRB_X8_ADDRESSING | GRB_8B_LATCHES)))
+ svga_writel_linear(addr, val, svga);
+ else
+ {
+ gd5429_write_linear(addr, val & 0xff, gd5429);
+ gd5429_write_linear(addr+1, val >> 8, gd5429);
+ gd5429_write_linear(addr+2, val >> 16, gd5429);
+ gd5429_write_linear(addr+3, val >> 24, gd5429);
+ }
+}
+
+static uint8_t gd5429_readb_linear(uint32_t addr, void *p)
+{
+ gd5429_t *gd5429 = (gd5429_t *)p;
+ svga_t *svga = &gd5429->svga;
+
+ if (!(svga->gdcreg[0xb] & (GRB_X8_ADDRESSING | GRB_8B_LATCHES)))
+ return svga_read_linear(addr, &gd5429->svga);
+ return gd5429_read_linear(addr, gd5429);
+}
+static uint16_t gd5429_readw_linear(uint32_t addr, void *p)
+{
+ gd5429_t *gd5429 = (gd5429_t *)p;
+ svga_t *svga = &gd5429->svga;
+
+ if (!(svga->gdcreg[0xb] & (GRB_X8_ADDRESSING | GRB_8B_LATCHES)))
+ return svga_readw_linear(addr, &gd5429->svga);
+ return gd5429_read_linear(addr, gd5429) | (gd5429_read_linear(addr+1, gd5429) << 8);
+}
+static uint32_t gd5429_readl_linear(uint32_t addr, void *p)
+{
+ gd5429_t *gd5429 = (gd5429_t *)p;
+ svga_t *svga = &gd5429->svga;
+
+ if (!(svga->gdcreg[0xb] & (GRB_X8_ADDRESSING | GRB_8B_LATCHES)))
+ return svga_readl_linear(addr, &gd5429->svga);
+ return gd5429_read_linear(addr, gd5429) | (gd5429_read_linear(addr+1, gd5429) << 8) |
+ (gd5429_read_linear(addr+2, gd5429) << 16) | (gd5429_read_linear(addr+3, gd5429) << 24);
+}
+
+
+void gd5429_start_blit(uint32_t cpu_dat, int count, void *p)
+{
+ gd5429_t *gd5429 = (gd5429_t *)p;
+ svga_t *svga = &gd5429->svga;
+ int blt_mask = gd5429->blt.mask & 7;
+ int x_max = 0;
+
+ switch (gd5429->blt.depth)
+ {
+ case BLIT_DEPTH_8:
+ x_max = 8;
+ break;
+ case BLIT_DEPTH_16:
+ x_max = 16;
+ blt_mask *= 2;
+ break;
+ case BLIT_DEPTH_32:
+ x_max = 32;
+ blt_mask *= 4;
+ break;
+ }
+
+// pclog("gd5429_start_blit %i\n", count);
+ if (count == -1)
+ {
+ gd5429->blt.dst_addr_backup = gd5429->blt.dst_addr;
+ gd5429->blt.src_addr_backup = gd5429->blt.src_addr;
+ gd5429->blt.width_backup = gd5429->blt.width;
+ gd5429->blt.height_internal = gd5429->blt.height;
+ gd5429->blt.x_count = 0;
+ if ((gd5429->blt.mode & 0xc0) == 0xc0)
+ gd5429->blt.y_count = gd5429->blt.src_addr & 7;
+ else
+ gd5429->blt.y_count = 0;
+// pclog("gd5429_start_blit : size %i, %i %i\n", gd5429->blt.width, gd5429->blt.height, gd5429->blt.x_count);
+
+ if (gd5429->blt.mode & 0x04)
+ {
+// pclog("blt.mode & 0x04\n");
+ if (!(svga->seqregs[7] & 0xf0))
+ {
+ mem_mapping_set_handler(&svga->mapping, NULL, NULL, NULL, NULL, gd5429_blt_write_w, gd5429_blt_write_l);
+ mem_mapping_set_p(&svga->mapping, gd5429);
+ }
+ else
+ {
+ mem_mapping_set_handler(&gd5429->linear_mapping, NULL, NULL, NULL, NULL, gd5429_blt_write_w, gd5429_blt_write_l);
+ mem_mapping_set_p(&gd5429->linear_mapping, gd5429);
+ }
+ gd5429_recalc_mapping(gd5429);
+ return;
+ }
+ else
+ {
+ if (!(svga->seqregs[7] & 0xf0))
+ mem_mapping_set_handler(&svga->mapping, gd5429_read, gd5429_readw, gd5429_readl, gd5429_write, gd5429_writew, gd5429_writel);
+ else
+ mem_mapping_set_handler(&gd5429->linear_mapping, gd5429_readb_linear, gd5429_readw_linear, gd5429_readl_linear, gd5429_writeb_linear, gd5429_writew_linear, gd5429_writel_linear);
+ gd5429_recalc_mapping(gd5429);
+ }
+ }
+ else if (gd5429->blt.height_internal == 0xffff)
+ return;
+
+ while (count)
+ {
+ uint8_t src = 0, dst;
+ int mask = 0;
+ int shift;
+
+ if (gd5429->blt.depth == BLIT_DEPTH_32)
+ shift = (gd5429->blt.x_count & 3) * 8;
+ else if (gd5429->blt.depth == BLIT_DEPTH_8)
+ shift = 0;
+ else
+ shift = (gd5429->blt.x_count & 1) * 8;
+
+ if (gd5429->blt.mode & 0x04)
+ {
+ if (gd5429->blt.mode & 0x80)
+ {
+ mask = cpu_dat & 0x80;
+
+ switch (gd5429->blt.depth)
+ {
+ case BLIT_DEPTH_8:
+ src = mask ? gd5429->blt.fg_col : gd5429->blt.bg_col;
+ cpu_dat <<= 1;
+ count--;
+ break;
+ case BLIT_DEPTH_16:
+ src = mask ? (gd5429->blt.fg_col >> shift) : (gd5429->blt.bg_col >> shift);
+ if (gd5429->blt.x_count & 1)
+ {
+ cpu_dat <<= 1;
+ count--;
+ }
+ break;
+ case BLIT_DEPTH_32:
+ src = mask ? (gd5429->blt.fg_col >> shift) : (gd5429->blt.bg_col >> shift);
+ if ((gd5429->blt.x_count & 3) == 3)
+ {
+ cpu_dat <<= 1;
+ count--;
+ }
+ break;
+ }
+ }
+ else
+ {
+ src = cpu_dat & 0xff;
+ cpu_dat >>= 8;
+ count -= 8;
+ mask = 1;
+ }
+ }
+ else
+ {
+ switch (gd5429->blt.mode & 0xc0)
+ {
+ case 0x00:
+ src = svga->vram[gd5429->blt.src_addr & svga->vram_mask];
+ gd5429->blt.src_addr += ((gd5429->blt.mode & 0x01) ? -1 : 1);
+ mask = 1;
+ break;
+ case 0x40:
+ switch (gd5429->blt.depth)
+ {
+ case BLIT_DEPTH_8:
+ src = svga->vram[(gd5429->blt.src_addr & (svga->vram_mask & ~7)) + (gd5429->blt.y_count << 3) + (gd5429->blt.x_count & 7)];
+ break;
+ case BLIT_DEPTH_16:
+ src = svga->vram[(gd5429->blt.src_addr & (svga->vram_mask & ~3)) + (gd5429->blt.y_count << 4) + (gd5429->blt.x_count & 15)];
+ break;
+ case BLIT_DEPTH_32:
+ src = svga->vram[(gd5429->blt.src_addr & (svga->vram_mask & ~3)) + (gd5429->blt.y_count << 5) + (gd5429->blt.x_count & 31)];
+ break;
+ }
+ mask = 1;
+ break;
+ case 0x80:
+ switch (gd5429->blt.depth)
+ {
+ case BLIT_DEPTH_8:
+ mask = svga->vram[gd5429->blt.src_addr & svga->vram_mask] & (0x80 >> gd5429->blt.x_count);
+ src = mask ? gd5429->blt.fg_col : gd5429->blt.bg_col;
+ break;
+ case BLIT_DEPTH_16:
+ mask = svga->vram[gd5429->blt.src_addr & svga->vram_mask] & (0x80 >> (gd5429->blt.x_count >> 1));
+ src = mask ? (gd5429->blt.fg_col >> shift) : (gd5429->blt.bg_col >> shift);
+ break;
+ case BLIT_DEPTH_32:
+ mask = svga->vram[gd5429->blt.src_addr & svga->vram_mask] & (0x80 >> (gd5429->blt.x_count >> 2));
+ src = mask ? (gd5429->blt.fg_col >> shift) : (gd5429->blt.bg_col >> shift);
+ break;
+ }
+ break;
+ case 0xc0:
+ switch (gd5429->blt.depth)
+ {
+ case BLIT_DEPTH_8:
+ mask = svga->vram[(gd5429->blt.src_addr & svga->vram_mask & ~7) | gd5429->blt.y_count] & (0x80 >> gd5429->blt.x_count);
+ src = mask ? gd5429->blt.fg_col : gd5429->blt.bg_col;
+ break;
+ case BLIT_DEPTH_16:
+ mask = svga->vram[(gd5429->blt.src_addr & svga->vram_mask & ~7) | gd5429->blt.y_count] & (0x80 >> (gd5429->blt.x_count >> 1));
+ src = mask ? (gd5429->blt.fg_col >> shift) : (gd5429->blt.bg_col >> shift);
+ break;
+ case BLIT_DEPTH_32:
+ mask = svga->vram[(gd5429->blt.src_addr & svga->vram_mask & ~7) | gd5429->blt.y_count] & (0x80 >> (gd5429->blt.x_count >> 2));
+ src = mask ? (gd5429->blt.fg_col >> shift) : (gd5429->blt.bg_col >> shift);
+ break;
+ }
+ break;
+ }
+ count--;
+ }
+ dst = svga->vram[gd5429->blt.dst_addr & svga->vram_mask];
+ svga->changedvram[(gd5429->blt.dst_addr & svga->vram_mask) >> 12] = changeframecount;
+
+// pclog("Blit %i,%i %06X %06X %06X %02X %02X %02X %02X ", gd5429->blt.width, gd5429->blt.height_internal, gd5429->blt.src_addr, gd5429->blt.dst_addr, gd5429->blt.src_addr & svga->vram_mask, svga->vram[gd5429->blt.src_addr & svga->vram_mask], 0x80 >> (gd5429->blt.dst_addr & 7), src, dst);
+ switch (gd5429->blt.rop)
+ {
+ case 0x00: dst = 0; break;
+ case 0x05: dst = src & dst; break;
+ case 0x06: dst = dst; break;
+ case 0x09: dst = src & ~dst; break;
+ case 0x0b: dst = ~ dst; break;
+ case 0x0d: dst = src; break;
+ case 0x0e: dst = 0xff; break;
+ case 0x50: dst = ~ src & dst; break;
+ case 0x59: dst = src ^ dst; break;
+ case 0x6d: dst = src | dst; break;
+ case 0x90: dst = ~(src | dst); break;
+ case 0x95: dst = ~(src ^ dst); break;
+ case 0xad: dst = src | ~dst; break;
+ case 0xd0: dst = ~src; break;
+ case 0xd6: dst = ~src | dst; break;
+ case 0xda: dst = ~(src & dst); break;
+ }
+ //pclog("%02X %02X\n", dst, mask);
+
+ if (gd5429->type <= CL_TYPE_GD5428)
+ {
+ if ((gd5429->blt.width_backup - gd5429->blt.width) >= blt_mask &&
+ (!(gd5429->blt.mode & 0x08) || (dst & gd5429->blt.trans_mask) != gd5429->blt.trans_col))
+ svga->vram[gd5429->blt.dst_addr & svga->vram_mask] = dst;
+ }
+ else
+ {
+ if ((gd5429->blt.width_backup - gd5429->blt.width) >= blt_mask &&
+ !((gd5429->blt.mode & 0x08) && !mask))
+ svga->vram[gd5429->blt.dst_addr & svga->vram_mask] = dst;
+ }
+
+ gd5429->blt.dst_addr += ((gd5429->blt.mode & 0x01) ? -1 : 1);
+
+ gd5429->blt.x_count++;
+ if (gd5429->blt.x_count == x_max)
+ {
+ gd5429->blt.x_count = 0;
+ if ((gd5429->blt.mode & 0xc0) == 0x80)
+ gd5429->blt.src_addr++;
+ }
+
+ gd5429->blt.width--;
+
+ if (gd5429->blt.width == 0xffff)
+ {
+ gd5429->blt.width = gd5429->blt.width_backup;
+
+ gd5429->blt.dst_addr = gd5429->blt.dst_addr_backup = gd5429->blt.dst_addr_backup + ((gd5429->blt.mode & 0x01) ? -gd5429->blt.dst_pitch : gd5429->blt.dst_pitch);
+
+ switch (gd5429->blt.mode & 0xc0)
+ {
+ case 0x00:
+ gd5429->blt.src_addr = gd5429->blt.src_addr_backup = gd5429->blt.src_addr_backup + ((gd5429->blt.mode & 0x01) ? -gd5429->blt.src_pitch : gd5429->blt.src_pitch);
+ break;
+ case 0x80:
+ if (gd5429->blt.x_count != 0)
+ gd5429->blt.src_addr++;
+ break;
+ }
+
+ gd5429->blt.x_count = 0;
+ if (gd5429->blt.mode & 0x01)
+ gd5429->blt.y_count = (gd5429->blt.y_count - 1) & 7;
+ else
+ gd5429->blt.y_count = (gd5429->blt.y_count + 1) & 7;
+
+ gd5429->blt.height_internal--;
+ if (gd5429->blt.height_internal == 0xffff)
+ {
+ if (gd5429->blt.mode & 0x04)
+ {
+ if (!(svga->seqregs[7] & 0xf0))
+ mem_mapping_set_handler(&svga->mapping, gd5429_read, gd5429_readw, gd5429_readl, gd5429_write, gd5429_writew, gd5429_writel);
+ else
+ mem_mapping_set_handler(&gd5429->linear_mapping, gd5429_readb_linear, gd5429_readw_linear, gd5429_readl_linear, gd5429_writeb_linear, gd5429_writew_linear, gd5429_writel_linear);
+// mem_mapping_set_handler(&gd5429->svga.mapping, gd5429_read, NULL, NULL, gd5429_write, NULL, NULL);
+// mem_mapping_set_p(&gd5429->svga.mapping, gd5429);
+ gd5429_recalc_mapping(gd5429);
+ }
+ return;
+ }
+
+ if (gd5429->blt.mode & 0x04)
+ return;
+ }
+ }
+}
+
+static void gd5429_mmio_write(uint32_t addr, uint8_t val, void *p)
+{
+ gd5429_t *gd5429 = (gd5429_t *)p;
+
+ if ((addr & ~0xff) == 0xb8000)
+ {
+ // pclog("MMIO write %08X %02X\n", addr, val);
+ switch (addr & 0xff)
+ {
+ case 0x00:
+ if (gd5429->type >= CL_TYPE_GD5434)
+ gd5429->blt.bg_col = (gd5429->blt.bg_col & 0xffffff00) | val;
+ else
+ gd5429->blt.bg_col = (gd5429->blt.bg_col & 0xff00) | val;
+ break;
+ case 0x01:
+ if (gd5429->type >= CL_TYPE_GD5434)
+ gd5429->blt.bg_col = (gd5429->blt.bg_col & 0xffff00ff) | (val << 8);
+ else
+ gd5429->blt.bg_col = (gd5429->blt.bg_col & 0x00ff) | (val << 8);
+ break;
+ case 0x02:
+ if (gd5429->type >= CL_TYPE_GD5434)
+ gd5429->blt.bg_col = (gd5429->blt.bg_col & 0xff00ffff) | (val << 16);
+ break;
+ case 0x03:
+ if (gd5429->type >= CL_TYPE_GD5434)
+ gd5429->blt.bg_col = (gd5429->blt.bg_col & 0x00ffffff) | (val << 24);
+ break;
+
+ case 0x04:
+ if (gd5429->type >= CL_TYPE_GD5434)
+ gd5429->blt.fg_col = (gd5429->blt.fg_col & 0xffffff00) | val;
+ else
+ gd5429->blt.fg_col = (gd5429->blt.fg_col & 0xff00) | val;
+ break;
+ case 0x05:
+ if (gd5429->type >= CL_TYPE_GD5434)
+ gd5429->blt.fg_col = (gd5429->blt.fg_col & 0xffff00ff) | (val << 8);
+ else
+ gd5429->blt.fg_col = (gd5429->blt.fg_col & 0x00ff) | (val << 8);
+ break;
+ case 0x06:
+ if (gd5429->type >= CL_TYPE_GD5434)
+ gd5429->blt.fg_col = (gd5429->blt.fg_col & 0xff00ffff) | (val << 16);
+ break;
+ case 0x07:
+ if (gd5429->type >= CL_TYPE_GD5434)
+ gd5429->blt.fg_col = (gd5429->blt.fg_col & 0x00ffffff) | (val << 24);
+ break;
+
+ case 0x08:
+ gd5429->blt.width = (gd5429->blt.width & 0xff00) | val;
+ break;
+ case 0x09:
+ gd5429->blt.width = (gd5429->blt.width & 0x00ff) | (val << 8);
+ if (gd5429->type >= CL_TYPE_GD5434)
+ gd5429->blt.width &= 0x1fff;
+ else
+ gd5429->blt.width &= 0x07ff;
+ break;
+ case 0x0a:
+ gd5429->blt.height = (gd5429->blt.height & 0xff00) | val;
+ break;
+ case 0x0b:
+ gd5429->blt.height = (gd5429->blt.height & 0x00ff) | (val << 8);
+ gd5429->blt.height &= 0x03ff;
+ break;
+ case 0x0c:
+ gd5429->blt.dst_pitch = (gd5429->blt.dst_pitch & 0xff00) | val;
+ break;
+ case 0x0d:
+ gd5429->blt.dst_pitch = (gd5429->blt.dst_pitch & 0x00ff) | (val << 8);
+ break;
+ case 0x0e:
+ gd5429->blt.src_pitch = (gd5429->blt.src_pitch & 0xff00) | val;
+ break;
+ case 0x0f:
+ gd5429->blt.src_pitch = (gd5429->blt.src_pitch & 0x00ff) | (val << 8);
+ break;
+
+ case 0x10:
+ gd5429->blt.dst_addr = (gd5429->blt.dst_addr & 0xffff00) | val;
+ break;
+ case 0x11:
+ gd5429->blt.dst_addr = (gd5429->blt.dst_addr & 0xff00ff) | (val << 8);
+ break;
+ case 0x12:
+ gd5429->blt.dst_addr = (gd5429->blt.dst_addr & 0x00ffff) | (val << 16);
+ if (gd5429->type >= CL_TYPE_GD5434)
+ gd5429->blt.dst_addr &= 0x3fffff;
+ else
+ gd5429->blt.dst_addr &= 0x1fffff;
+ break;
+
+ case 0x14:
+ gd5429->blt.src_addr = (gd5429->blt.src_addr & 0xffff00) | val;
+ break;
+ case 0x15:
+ gd5429->blt.src_addr = (gd5429->blt.src_addr & 0xff00ff) | (val << 8);
+ break;
+ case 0x16:
+ gd5429->blt.src_addr = (gd5429->blt.src_addr & 0x00ffff) | (val << 16);
+ if (gd5429->type >= CL_TYPE_GD5434)
+ gd5429->blt.src_addr &= 0x3fffff;
+ else
+ gd5429->blt.src_addr &= 0x1fffff;
+ break;
+
+ case 0x17:
+ gd5429->blt.mask = val;
+ break;
+ case 0x18:
+ gd5429->blt.mode = val;
+ if (gd5429->type >= CL_TYPE_GD5434)
+ gd5429->blt.depth = (val >> 4) & 3;
+ else
+ gd5429->blt.depth = (val >> 4) & 1;
+ break;
+
+ case 0x1a:
+ gd5429->blt.rop = val;
+ break;
+
+ case 0x40:
+ if (val & 0x02)
+ gd5429_start_blit(0, -1, gd5429);
+ break;
+ }
+ }
+ else if (gd5429->mmio_vram_overlap)
+ gd5429_write(addr, val, gd5429);
+}
+static void gd5429_mmio_writew(uint32_t addr, uint16_t val, void *p)
+{
+ gd5429_t *gd5429 = (gd5429_t *)p;
+
+ if ((addr & ~0xff) == 0xb8000)
+ {
+ gd5429_mmio_write(addr, val & 0xff, gd5429);
+ gd5429_mmio_write(addr + 1, val >> 8, gd5429);
+ }
+ else if (gd5429->mmio_vram_overlap)
+ gd5429_writew(addr, val, gd5429);
+}
+static void gd5429_mmio_writel(uint32_t addr, uint32_t val, void *p)
+{
+ gd5429_t *gd5429 = (gd5429_t *)p;
+
+ if ((addr & ~0xff) == 0xb8000)
+ {
+ gd5429_mmio_writew(addr, val & 0xffff, gd5429);
+ gd5429_mmio_writew(addr + 2, val >> 16, gd5429);
+ }
+ else if (gd5429->mmio_vram_overlap)
+ gd5429_writel(addr, val, gd5429);
+}
+
+static uint8_t gd5429_mmio_read(uint32_t addr, void *p)
+{
+ gd5429_t *gd5429 = (gd5429_t *)p;
+
+ if ((addr & ~0xff) == 0xb8000)
+ {
+// pclog("MMIO read %08X\n", addr);
+ switch (addr & 0xff)
+ {
+ case 0x40: /*BLT status*/
+ return 0;
+ }
+ return 0xff; /*All other registers read-only*/
+ }
+ if (gd5429->mmio_vram_overlap)
+ return gd5429_read(addr, gd5429);
+ return 0xff;
+}
+static uint16_t gd5429_mmio_readw(uint32_t addr, void *p)
+{
+ gd5429_t *gd5429 = (gd5429_t *)p;
+
+ if ((addr & ~0xff) == 0xb8000)
+ return gd5429_mmio_read(addr, gd5429) | (gd5429_mmio_read(addr+1, gd5429) << 8);
+ if (gd5429->mmio_vram_overlap)
+ return gd5429_readw(addr, gd5429);
+ return 0xffff;
+}
+static uint32_t gd5429_mmio_readl(uint32_t addr, void *p)
+{
+ gd5429_t *gd5429 = (gd5429_t *)p;
+
+ if ((addr & ~0xff) == 0xb8000)
+ return gd5429_mmio_readw(addr, gd5429) | (gd5429_mmio_readw(addr+2, gd5429) << 16);
+ if (gd5429->mmio_vram_overlap)
+ return gd5429_readl(addr, gd5429);
+ return 0xffffffff;
+}
+
+void gd5429_blt_write_w(uint32_t addr, uint16_t val, void *p)
+{
+ gd5429_t *gd5429 = (gd5429_t *)p;
+
+// pclog("gd5429_blt_write_w %08X %08X\n", addr, val);
+ if (!gd5429->blt.mem_word_sel)
+ gd5429->blt.mem_word_save = val;
+ else
+ gd5429_start_blit(gd5429->blt.mem_word_save | (val << 16), 32, p);
+ gd5429->blt.mem_word_sel = !gd5429->blt.mem_word_sel;
+
+}
+
+void gd5429_blt_write_l(uint32_t addr, uint32_t val, void *p)
+{
+ gd5429_t *gd5429 = (gd5429_t *)p;
+
+ gd5429->blt.mem_word_sel = 0;
+// pclog("gd5429_blt_write_l %08X %08X %04X %04X\n", addr, val, ((val >> 8) & 0x00ff) | ((val << 8) & 0xff00), ((val >> 24) & 0x00ff) | ((val >> 8) & 0xff00));
+ if ((gd5429->blt.mode & 0x84) == 0x84)
+ {
+ gd5429_start_blit( val & 0xff, 8, p);
+ gd5429_start_blit((val >> 8) & 0xff, 8, p);
+ gd5429_start_blit((val >> 16) & 0xff, 8, p);
+ gd5429_start_blit((val >> 24) & 0xff, 8, p);
+ }
+ else
+ gd5429_start_blit(val, 32, p);
+}
+
+uint8_t ibm_gd5428_mca_read(int port, void *p)
+{
+ gd5429_t *gd5429 = (gd5429_t *)p;
+
+// pclog("gd5429_pro_mcv_read: port=%04x %02x %04x:%04x\n", port, gd5429->pos_regs[port & 7], CS, cpu_state.pc);
+
+ return gd5429->pos_regs[port & 7];
+}
+
+static void ibm_gd5428_mapping_update(gd5429_t *gd5429)
+{
+ gd5429_recalc_mapping(gd5429);
+
+ io_removehandler(0x03a0, 0x0023, gd5429_in, NULL, NULL, gd5429_out, NULL, NULL, gd5429);
+ io_removehandler(0x03c4, 0x001c, gd5429_in, NULL, NULL, gd5429_out, NULL, NULL, gd5429);
+ if ((gd5429->pos_regs[2] & 0x01) && gd5429->vidsys_ena)
+ {
+// pclog(" GD5429 enable registers\n");
+ io_sethandler(0x03c0, 0x0003, gd5429_in, NULL, NULL, gd5429_out, NULL, NULL, gd5429);
+ io_sethandler(0x03c4, 0x001c, gd5429_in, NULL, NULL, gd5429_out, NULL, NULL, gd5429);
+ if (!(gd5429->svga.miscout & 1))
+ io_sethandler(0x03a0, 0x0020, gd5429_in, NULL, NULL, gd5429_out, NULL, NULL, gd5429);
+ gd5429->svga.override = 0;
+ if (mb_vga)
+ svga_set_override(mb_vga, 1);
+ }
+ else
+ {
+// pclog(" GD5429 disable registers\n");
+ gd5429->svga.override = 1;
+ if (mb_vga)
+ svga_set_override(mb_vga, 0);
+ }
+}
+
+void ibm_gd5428_mca_write(int port, uint8_t val, void *p)
+{
+// svga_set_override(voodoo->svga, val & 1);
+ gd5429_t *gd5429 = (gd5429_t *)p;
+
+// pclog("gd5429_pro_mcv_write: port=%04x val=%02x\n", port, val);
+
+ if (port < 0x102)
+ return;
+ gd5429->pos_regs[port & 7] = val;
+
+ if ((port & 7) == 2)
+ {
+ mem_mapping_disable(&gd5429->bios_rom.mapping);
+ io_removehandler(0x03c3, 0x0001, gd5429_in, NULL, NULL, gd5429_out, NULL, NULL, gd5429);
+ if (gd5429->pos_regs[2] & 0x01)
+ {
+// pclog("Enable BIOS mapping\n");
+ mem_mapping_enable(&gd5429->bios_rom.mapping);
+ io_sethandler(0x03c3, 0x0001, gd5429_in, NULL, NULL, gd5429_out, NULL, NULL, gd5429);
+ }
+// else
+// pclog("Disable BIOS mapping\n");
+ }
+
+ ibm_gd5428_mapping_update(gd5429);
+}
+
+static void ibm_gd5428_mca_reset(void *p)
+{
+ gd5429_t *gd5429 = (gd5429_t *)p;
+
+// pclog("ibm_gd5428_mca_reset\n");
+ gd5429->vidsys_ena = 0;
+ ibm_gd5428_mca_write(0x102, 0, gd5429);
+}
+
+static uint8_t cl_pci_read(int func, int addr, void *p)
+{
+ gd5429_t *gd5429 = (gd5429_t *)p;
+
+// pclog("CL PCI read %08X\n", addr);
+ switch (addr)
+ {
+ case 0x00: return 0x13; /*Cirrus Logic*/
+ case 0x01: return 0x10;
+
+ case 0x02:
+ switch (gd5429->type)
+ {
+ case CL_TYPE_GD5430:
+ return 0xa0;
+ case CL_TYPE_GD5434:
+ return 0xa8;
+ }
+ return 0xff;
+ case 0x03: return 0x00;
+
+ case PCI_REG_COMMAND:
+ return gd5429->pci_regs[PCI_REG_COMMAND]; /*Respond to IO and memory accesses*/
+
+ case 0x07: return 0 << 1; /*Fast DEVSEL timing*/
+
+ case 0x08: return 0; /*Revision ID*/
+ case 0x09: return 0; /*Programming interface*/
+
+ case 0x0a: return 0x00; /*Supports VGA interface*/
+ case 0x0b: return 0x03;
+
+ case 0x10: return 0x08; /*Linear frame buffer address*/
+ case 0x11: return 0x00;
+ case 0x12: return 0x00;
+ case 0x13: return gd5429->lfb_base >> 24;
+
+ case 0x30: return gd5429->pci_regs[0x30] & 0x01; /*BIOS ROM address*/
+ case 0x31: return 0x00;
+ case 0x32: return gd5429->pci_regs[0x32];
+ case 0x33: return gd5429->pci_regs[0x33];
+
+ case 0x3c: return gd5429->int_line;
+ case 0x3d: return PCI_INTA;
+ }
+ return 0;
+}
+
+static void cl_pci_write(int func, int addr, uint8_t val, void *p)
+{
+ gd5429_t *gd5429 = (gd5429_t *)p;
+
+// pclog("cl_pci_write: addr=%02x val=%02x\n", addr, val);
+ switch (addr)
+ {
+ case PCI_REG_COMMAND:
+ gd5429->pci_regs[PCI_REG_COMMAND] = val & 0x23;
+ io_removehandler(0x03c0, 0x0020, gd5429_in, NULL, NULL, gd5429_out, NULL, NULL, gd5429);
+ if (val & PCI_COMMAND_IO)
+ io_sethandler(0x03c0, 0x0020, gd5429_in, NULL, NULL, gd5429_out, NULL, NULL, gd5429);
+ gd5429_recalc_mapping(gd5429);
+ break;
+
+ case 0x13:
+ gd5429->lfb_base = val << 24;
+ gd5429_recalc_mapping(gd5429);
+ break;
+
+ case 0x30: case 0x32: case 0x33:
+ gd5429->pci_regs[addr] = val;
+ if (gd5429->pci_regs[0x30] & 0x01)
+ {
+ uint32_t addr = (gd5429->pci_regs[0x32] << 16) | (gd5429->pci_regs[0x33] << 24);
+ mem_mapping_set_addr(&gd5429->bios_rom.mapping, addr, 0x8000);
+ }
+ else
+ mem_mapping_disable(&gd5429->bios_rom.mapping);
+ return;
+
+ case 0x3c:
+ gd5429->int_line = val;
+ return;
+ }
+}
+
+static void *cl_init(int type, char *fn, int pci_card, uint32_t force_vram_size)
+{
+ gd5429_t *gd5429 = malloc(sizeof(gd5429_t));
+ svga_t *svga = &gd5429->svga;
+ int vram_size;
+ memset(gd5429, 0, sizeof(gd5429_t));
+
+ if (force_vram_size)
+ vram_size = force_vram_size;
+ else
+ vram_size = device_get_config_int("memory");
+ if (vram_size >= 256)
+ gd5429->vram_mask = (vram_size << 10) - 1;
+ else
+ gd5429->vram_mask = (vram_size << 20) - 1;
+
+ gd5429->type = type;
+
+ if (fn)
+ rom_init(&gd5429->bios_rom, fn, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
+
+ svga_init(&gd5429->svga, gd5429, (vram_size >= 256) ? (vram_size << 10) : (vram_size << 20),
+ gd5429_recalctimings,
+ gd5429_in, gd5429_out,
+ gd5429_hwcursor_draw,
+ NULL);
+
+ mem_mapping_set_handler(&gd5429->svga.mapping, gd5429_read, gd5429_readw, gd5429_readl, gd5429_write, gd5429_writew, gd5429_writel);
+ mem_mapping_set_p(&gd5429->svga.mapping, gd5429);
+
+ mem_mapping_add(&gd5429->mmio_mapping, 0, 0, gd5429_mmio_read, gd5429_mmio_readw, gd5429_mmio_readl, gd5429_mmio_write, gd5429_mmio_writew, gd5429_mmio_writel, NULL, 0, gd5429);
+ mem_mapping_add(&gd5429->linear_mapping, 0, 0, gd5429_readb_linear, gd5429_readw_linear, gd5429_readl_linear, gd5429_writeb_linear, gd5429_writew_linear, gd5429_writel_linear, NULL, 0, gd5429);
+
+ io_sethandler(0x03c0, 0x0020, gd5429_in, NULL, NULL, gd5429_out, NULL, NULL, gd5429);
+ if (type == CL_TYPE_AVGA2)
+ {
+ io_sethandler(0x0102, 0x0001, gd5429_in, NULL, NULL, gd5429_out, NULL, NULL, gd5429);
+ io_sethandler(0x46e8, 0x0002, gd5429_in, NULL, NULL, gd5429_out, NULL, NULL, gd5429);
+ svga->decode_mask = svga->vram_mask;
+ }
+
+ svga->hwcursor.yoff = 32;
+ svga->hwcursor.xoff = 0;
+
+ gd5429->bank[1] = 0x8000;
+
+ /*Default VCLK values*/
+ svga->seqregs[0xb] = 0x66;
+ svga->seqregs[0xc] = 0x5b;
+ svga->seqregs[0xd] = 0x45;
+ svga->seqregs[0xe] = 0x7e;
+ svga->seqregs[0x1b] = 0x3b;
+ svga->seqregs[0x1c] = 0x2f;
+ svga->seqregs[0x1d] = 0x30;
+ svga->seqregs[0x1e] = 0x33;
+
+ if (PCI && type >= CL_TYPE_GD5430)
+ {
+ if (pci_card != -1)
+ {
+ pci_add_specific(pci_card, cl_pci_read, cl_pci_write, gd5429);
+ gd5429->card = pci_card;
+ }
+ else
+ gd5429->card = pci_add(cl_pci_read, cl_pci_write, gd5429);
+
+ gd5429->pci_regs[0x04] = 7;
+
+ gd5429->pci_regs[0x30] = 0x00;
+ gd5429->pci_regs[0x32] = 0x0c;
+ gd5429->pci_regs[0x33] = 0x00;
+ }
+
+ return gd5429;
+}
+
+
+static void *avga2_init()
+{
+ return cl_init(CL_TYPE_AVGA2, "avga2vram.vbi", -1, 0);
+}
+static void *avga2_cbm_sl386sx_init()
+{
+ return cl_init(CL_TYPE_AVGA2, "cbm_sl386sx25/c000.rom", -1, 0);
+}
+static void *gd5426_ps1_init()
+{
+ return cl_init(CL_TYPE_GD5426, NULL, -1, 1);
+}
+static void *gd5428_init()
+{
+ return cl_init(CL_TYPE_GD5428, "Machspeed_VGA_GUI_2100_VLB.vbi", -1, 0);
+}
+static void *ibm_gd5428_init()
+{
+ gd5429_t *gd5429;
+ svga_t *mb_vga = svga_get_pri();
+
+ gd5429 = cl_init(CL_TYPE_GD5428, "SVGA141.ROM", -1, 1); /*Only supports 1MB*/
+ gd5429->mb_vga = mb_vga;
+
+ mca_add(ibm_gd5428_mca_read, ibm_gd5428_mca_write, ibm_gd5428_mca_reset, gd5429);
+ gd5429->pos_regs[0] = 0x7b;
+ gd5429->pos_regs[1] = 0x91;
+ gd5429->pos_regs[2] = 0;
+
+ gd5429_recalc_mapping(gd5429);
+ io_removehandler(0x03a0, 0x0040, gd5429_in, NULL, NULL, gd5429_out, NULL, NULL, gd5429);
+ gd5429->svga.override = 1;
+ mem_mapping_disable(&gd5429->bios_rom.mapping);
+ io_sethandler(0x46e8, 0x0001, gd5429_in, NULL, NULL, gd5429_out, NULL, NULL, gd5429);
+
+ return gd5429;
+}
+static void *gd5429_init()
+{
+ return cl_init(CL_TYPE_GD5429, "5429.vbi", -1, 0);
+}
+static void *gd5430_init()
+{
+ return cl_init(CL_TYPE_GD5430, "gd5430/pci.bin", -1, 0);
+}
+static void *gd5430_pb570_init()
+{
+ return cl_init(CL_TYPE_GD5430, "pb570/gd5430.bin", 8, 0);
+}
+static void *gd5434_init()
+{
+ return cl_init(CL_TYPE_GD5434, "gd5434.bin", -1, 0);
+}
+static void *gd5434_pb520r_init()
+{
+ return cl_init(CL_TYPE_GD5434, "pb520r/gd5434.bin", 3, 0);
+}
+
+static int avga2_available()
+{
+ return rom_present("avga2vram.vbi");
+}
+static int gd5428_available()
+{
+ return rom_present("Machspeed_VGA_GUI_2100_VLB.vbi");
+}
+static int ibm_gd5428_available()
+{
+ return rom_present(/*"FILE.ROM"*/"SVGA141.ROM");
+}
+static int gd5429_available()
+{
+ return rom_present("5429.vbi");
+}
+static int gd5430_available()
+{
+ return rom_present("gd5430/pci.bin");
+}
+static int gd5434_available()
+{
+ return rom_present("gd5434.bin");
+}
+
+void gd5429_close(void *p)
+{
+ gd5429_t *gd5429 = (gd5429_t *)p;
+
+ svga_close(&gd5429->svga);
+
+ free(gd5429);
+}
+
+void gd5429_speed_changed(void *p)
+{
+ gd5429_t *gd5429 = (gd5429_t *)p;
+
+ svga_recalctimings(&gd5429->svga);
+}
+
+void gd5429_force_redraw(void *p)
+{
+ gd5429_t *gd5429 = (gd5429_t *)p;
+
+ gd5429->svga.fullchange = changeframecount;
+}
+
+void gd5429_add_status_info(char *s, int max_len, void *p)
+{
+ gd5429_t *gd5429 = (gd5429_t *)p;
+
+ svga_add_status_info(s, max_len, &gd5429->svga);
+}
+
+static device_config_t avga2_config[] =
+{
+ {
+ .name = "memory",
+ .description = "Memory size",
+ .type = CONFIG_SELECTION,
+ .selection =
+ {
+ {
+ .description = "256 kB",
+ .value = 256
+ },
+ {
+ .description = "512 kB",
+ .value = 512
+ },
+ {
+ .description = ""
+ }
+ },
+ .default_int = 512
+ },
+ {
+ .type = -1
+ }
+};
+
+static device_config_t gd5429_config[] =
+{
+ {
+ .name = "memory",
+ .description = "Memory size",
+ .type = CONFIG_SELECTION,
+ .selection =
+ {
+ {
+ .description = "1 MB",
+ .value = 1
+ },
+ {
+ .description = "2 MB",
+ .value = 2
+ },
+ {
+ .description = ""
+ }
+ },
+ .default_int = 2
+ },
+ {
+ .type = -1
+ }
+};
+static device_config_t gd5434_config[] =
+{
+ {
+ .name = "memory",
+ .description = "Memory size",
+ .type = CONFIG_SELECTION,
+ .selection =
+ {
+ {
+ .description = "2 MB",
+ .value = 2
+ },
+ {
+ .description = "4 MB",
+ .value = 4
+ },
+ {
+ .description = ""
+ }
+ },
+ .default_int = 4
+ },
+ {
+ .type = -1
+ }
+};
+
+device_t avga2_device =
+{
+ "AVGA2 / Cirrus Logic GD5402",
+ 0,
+ avga2_init,
+ gd5429_close,
+ avga2_available,
+ gd5429_speed_changed,
+ gd5429_force_redraw,
+ gd5429_add_status_info,
+ avga2_config
+};
+
+device_t avga2_cbm_sl386sx_device =
+{
+ "AVGA2 (Commodore SL386SX-25)",
+ 0,
+ avga2_cbm_sl386sx_init,
+ gd5429_close,
+ gd5430_available,
+ gd5429_speed_changed,
+ gd5429_force_redraw,
+ gd5429_add_status_info,
+ avga2_config
+};
+
+device_t gd5426_ps1_device =
+{
+ "Cirrus Logic GD5426 (IBM PS/1)",
+ 0,
+ gd5426_ps1_init,
+ gd5429_close,
+ NULL,
+ gd5429_speed_changed,
+ gd5429_force_redraw,
+ gd5429_add_status_info,
+ NULL
+};
+
+device_t gd5428_device =
+{
+ "Cirrus Logic GD5428",
+ 0,
+ gd5428_init,
+ gd5429_close,
+ gd5428_available,
+ gd5429_speed_changed,
+ gd5429_force_redraw,
+ gd5429_add_status_info,
+ gd5429_config
+};
+
+device_t ibm_gd5428_device =
+{
+ "IBM 1MB SVGA Adapter/A (Cirrus Logic GD5428)",
+ DEVICE_MCA,
+ ibm_gd5428_init,
+ gd5429_close,
+ ibm_gd5428_available,
+ gd5429_speed_changed,
+ gd5429_force_redraw,
+ gd5429_add_status_info,
+ NULL
+};
+
+device_t gd5429_device =
+{
+ "Cirrus Logic GD5429",
+ 0,
+ gd5429_init,
+ gd5429_close,
+ gd5429_available,
+ gd5429_speed_changed,
+ gd5429_force_redraw,
+ gd5429_add_status_info,
+ gd5429_config
+};
+
+device_t gd5430_device =
+{
+ "Cirrus Logic GD5430",
+ 0,
+ gd5430_init,
+ gd5429_close,
+ gd5430_available,
+ gd5429_speed_changed,
+ gd5429_force_redraw,
+ gd5429_add_status_info,
+ gd5429_config
+};
+
+device_t gd5430_pb570_device =
+{
+ "Cirrus Logic GD5430 (PB570)",
+ 0,
+ gd5430_pb570_init,
+ gd5429_close,
+ gd5430_available,
+ gd5429_speed_changed,
+ gd5429_force_redraw,
+ gd5429_add_status_info,
+ gd5429_config
+};
+
+device_t gd5434_device =
+{
+ "Cirrus Logic GD5434",
+ 0,
+ gd5434_init,
+ gd5429_close,
+ gd5434_available,
+ gd5429_speed_changed,
+ gd5429_force_redraw,
+ gd5429_add_status_info,
+ gd5434_config
+};
+
+device_t gd5434_pb520r_device =
+{
+ "Cirrus Logic GD5434 (PB520r)",
+ 0,
+ gd5434_pb520r_init,
+ gd5429_close,
+ gd5434_available,
+ gd5429_speed_changed,
+ gd5429_force_redraw,
+ gd5429_add_status_info,
+ gd5434_config
+};
--- /dev/null
+extern device_t avga2_device;
+extern device_t avga2_cbm_sl386sx_device;
+extern device_t gd5426_ps1_device;
+extern device_t gd5428_device;
+extern device_t ibm_gd5428_device;
+extern device_t gd5429_device;
+extern device_t gd5429_reply_m25_device;
+extern device_t gd5430_device;
+extern device_t gd5430_pb570_device;
+extern device_t gd5434_device;
+extern device_t gd5434_pb520r_device;
--- /dev/null
+/*S3 emulation*/
+#include <stdlib.h>
+#include "ibm.h"
+#include "device.h"
+#include "io.h"
+#include "mem.h"
+#include "pci.h"
+#include "rom.h"
+#include "thread.h"
+#include "video.h"
+#include "vid_s3.h"
+#include "vid_svga.h"
+#include "vid_svga_render.h"
+#include "vid_sdac_ramdac.h"
+
+enum
+{
+ S3_VISION864,
+ S3_TRIO32,
+ S3_TRIO64
+};
+
+enum
+{
+ VRAM_4MB = 0,
+ VRAM_8MB = 3,
+ VRAM_2MB = 4,
+ VRAM_1MB = 6,
+ VRAM_512KB = 7
+};
+
+#define FIFO_SIZE 65536
+#define FIFO_MASK (FIFO_SIZE - 1)
+#define FIFO_ENTRY_SIZE (1 << 31)
+
+#define FIFO_ENTRIES (s3->fifo_write_idx - s3->fifo_read_idx)
+#define FIFO_FULL ((s3->fifo_write_idx - s3->fifo_read_idx) >= FIFO_SIZE)
+#define FIFO_EMPTY (s3->fifo_read_idx == s3->fifo_write_idx)
+
+#define FIFO_TYPE 0xff000000
+#define FIFO_ADDR 0x00ffffff
+
+enum
+{
+ FIFO_INVALID = (0x00 << 24),
+ FIFO_WRITE_BYTE = (0x01 << 24),
+ FIFO_WRITE_WORD = (0x02 << 24),
+ FIFO_WRITE_DWORD = (0x03 << 24),
+ FIFO_OUT_BYTE = (0x04 << 24),
+ FIFO_OUT_WORD = (0x05 << 24),
+ FIFO_OUT_DWORD = (0x06 << 24)
+};
+
+typedef struct
+{
+ uint32_t addr_type;
+ uint32_t val;
+} fifo_entry_t;
+
+typedef struct s3_t
+{
+ mem_mapping_t linear_mapping;
+ mem_mapping_t mmio_mapping;
+
+ rom_t bios_rom;
+
+ svga_t svga;
+ sdac_ramdac_t ramdac;
+
+ uint8_t bank;
+ uint8_t ma_ext;
+ int width;
+ int bpp;
+
+ int chip;
+
+ uint8_t id, id_ext, id_ext_pci;
+
+ uint8_t int_line;
+
+ int packed_mmio;
+
+ uint32_t linear_base, linear_size;
+
+ uint8_t pci_regs[256];
+ int card;
+
+ uint32_t vram_mask;
+
+ float (*getclock)(int clock, void *p);
+ void *getclock_p;
+
+ struct
+ {
+ uint8_t subsys_cntl;
+ uint8_t setup_md;
+ uint8_t advfunc_cntl;
+ uint16_t cur_y, cur_y2;
+ uint16_t cur_x, cur_x2;
+ uint16_t x2;
+ int16_t desty_axstp, desty_axstp2;
+ int16_t destx_distp;
+ int16_t err_term, err_term2;
+ int16_t maj_axis_pcnt, maj_axis_pcnt2;
+ uint16_t cmd;
+ uint16_t short_stroke;
+ uint32_t bkgd_color;
+ uint32_t frgd_color;
+ uint32_t wrt_mask;
+ uint32_t rd_mask;
+ uint32_t color_cmp;
+ uint8_t bkgd_mix;
+ uint8_t frgd_mix;
+ uint16_t multifunc_cntl;
+ uint16_t multifunc[16];
+ uint8_t pix_trans[4];
+
+ int cx, cy;
+ int sx, sy;
+ int dx, dy;
+ uint32_t src, dest, pattern;
+ int pix_trans_count;
+
+ int poly_cx, poly_cx2;
+ int poly_cy, poly_cy2;
+ int point_1_updated, point_2_updated;
+ int poly_dx1, poly_dx2;
+ int poly_x;
+
+ uint32_t dat_buf;
+ int dat_count;
+ } accel;
+
+ fifo_entry_t fifo[FIFO_SIZE];
+ volatile int fifo_read_idx, fifo_write_idx;
+
+ thread_t *fifo_thread;
+ event_t *wake_fifo_thread;
+ event_t *fifo_not_full_event;
+
+ int blitter_busy;
+ uint64_t blitter_time;
+ uint64_t status_time;
+
+ uint8_t subsys_cntl, subsys_stat;
+
+ uint32_t hwc_fg_col, hwc_bg_col;
+ int hwc_col_stack_pos;
+
+ volatile int force_busy;
+} s3_t;
+
+#define INT_VSY (1 << 0)
+#define INT_GE_BSY (1 << 1)
+#define INT_FIFO_OVR (1 << 2)
+#define INT_FIFO_EMP (1 << 3)
+#define INT_MASK 0xf
+
+void s3_updatemapping();
+
+void s3_accel_write(uint32_t addr, uint8_t val, void *p);
+void s3_accel_write_w(uint32_t addr, uint16_t val, void *p);
+void s3_accel_write_l(uint32_t addr, uint32_t val, void *p);
+uint8_t s3_accel_read(uint32_t addr, void *p);
+
+static inline void wake_fifo_thread(s3_t *s3)
+{
+ thread_set_event(s3->wake_fifo_thread); /*Wake up FIFO thread if moving from idle*/
+}
+
+static void s3_wait_fifo_idle(s3_t *s3)
+{
+ while (!FIFO_EMPTY)
+ {
+ wake_fifo_thread(s3);
+ thread_wait_event(s3->fifo_not_full_event, 1);
+ }
+}
+
+static void s3_update_irqs(s3_t *s3)
+{
+ if (s3->subsys_cntl & s3->subsys_stat & INT_MASK)
+ pci_set_irq(s3->card, PCI_INTA);
+ else
+ pci_clear_irq(s3->card, PCI_INTA);
+}
+
+void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_t *s3);
+
+#define WRITE8(addr, var, val) switch ((addr) & 3) \
+ { \
+ case 0: var = (var & 0xffffff00) | (val); break; \
+ case 1: var = (var & 0xffff00ff) | ((val) << 8); break; \
+ case 2: var = (var & 0xff00ffff) | ((val) << 16); break; \
+ case 3: var = (var & 0x00ffffff) | ((val) << 24); break; \
+ }
+
+static void s3_accel_out_fifo(s3_t *s3, uint16_t port, uint8_t val)
+{
+ switch (port)
+ {
+ case 0x82e8:
+ s3->accel.cur_y = (s3->accel.cur_y & 0xf00) | val;
+ s3->accel.poly_cy = s3->accel.cur_y;
+ break;
+ case 0x82e9:
+ s3->accel.cur_y = (s3->accel.cur_y & 0xff) | ((val & 0x1f) << 8);
+ s3->accel.poly_cy = s3->accel.cur_y;
+ break;
+ case 0x82ea:
+ s3->accel.cur_y2 = (s3->accel.cur_y2 & 0xf00) | val;
+ s3->accel.poly_cy2 = s3->accel.cur_y2;
+ break;
+ case 0x82eb:
+ s3->accel.cur_y2 = (s3->accel.cur_y2 & 0xff) | ((val & 0x1f) << 8);
+ s3->accel.poly_cy2 = s3->accel.cur_y2;
+ break;
+
+ case 0x86e8:
+ s3->accel.cur_x = (s3->accel.cur_x & 0xf00) | val;
+ s3->accel.poly_cx = s3->accel.cur_x << 20;
+ s3->accel.poly_x = s3->accel.poly_cx >> 20;
+ break;
+ case 0x86e9:
+ s3->accel.cur_x = (s3->accel.cur_x & 0xff) | ((val & 0x1f) << 8);
+ s3->accel.poly_cx = s3->accel.poly_x = s3->accel.cur_x << 20;
+ s3->accel.poly_x = s3->accel.poly_cx >> 20;
+ break;
+ case 0x86ea:
+ s3->accel.cur_x2 = (s3->accel.cur_x2 & 0xf00) | val;
+ s3->accel.poly_cx2 = s3->accel.cur_x2 << 20;
+ break;
+ case 0x86eb:
+ s3->accel.cur_x2 = (s3->accel.cur_x2 & 0xff) | ((val & 0x1f) << 8);
+ s3->accel.poly_cx2 = s3->accel.cur_x2 << 20;
+ break;
+
+ case 0x8ae8:
+ s3->accel.desty_axstp = (s3->accel.desty_axstp & 0x3f00) | val;
+ s3->accel.point_1_updated = 1;
+ break;
+ case 0x8ae9:
+ s3->accel.desty_axstp = (s3->accel.desty_axstp & 0xff) | ((val & 0x3f) << 8);
+ if (val & 0x20)
+ s3->accel.desty_axstp |= ~0x3fff;
+ s3->accel.point_1_updated = 1;
+ break;
+ case 0x8aea:
+ s3->accel.desty_axstp2 = (s3->accel.desty_axstp2 & 0x3f00) | val;
+ s3->accel.point_2_updated = 1;
+ break;
+ case 0x8aeb:
+ s3->accel.desty_axstp2 = (s3->accel.desty_axstp2 & 0xff) | ((val & 0x3f) << 8);
+ if (val & 0x20)
+ s3->accel.desty_axstp2 |= ~0x3fff;
+ s3->accel.point_2_updated = 1;
+ break;
+
+ case 0x8ee8:
+ s3->accel.destx_distp = (s3->accel.destx_distp & 0x3f00) | val;
+ s3->accel.point_1_updated = 1;
+ break;
+ case 0x8ee9:
+ s3->accel.destx_distp = (s3->accel.destx_distp & 0xff) | ((val & 0x3f) << 8);
+ if (val & 0x20)
+ s3->accel.destx_distp |= ~0x3fff;
+ s3->accel.point_1_updated = 1;
+ break;
+ case 0x8eea:
+ s3->accel.x2 = (s3->accel.x2 & 0xf00) | val;
+ s3->accel.point_2_updated = 1;
+ break;
+ case 0x8eeb:
+ s3->accel.x2 = (s3->accel.x2 & 0xff) | ((val & 0xf) << 8);
+ s3->accel.point_2_updated = 1;
+ break;
+
+ case 0x92e8:
+ s3->accel.err_term = (s3->accel.err_term & 0x3f00) | val;
+ break;
+ case 0x92e9:
+ s3->accel.err_term = (s3->accel.err_term & 0xff) | ((val & 0x3f) << 8);
+ if (val & 0x20)
+ s3->accel.err_term |= ~0x3fff;
+ break;
+ case 0x92ea:
+ s3->accel.err_term2 = (s3->accel.err_term2 & 0x3f00) | val;
+ break;
+ case 0x92eb:
+ s3->accel.err_term2 = (s3->accel.err_term2 & 0xff) | ((val & 0x3f) << 8);
+ if (val & 0x20)
+ s3->accel.err_term2 |= ~0x3fff;
+ break;
+
+ case 0x96e8:
+ s3->accel.maj_axis_pcnt = (s3->accel.maj_axis_pcnt & 0x3f00) | val;
+ break;
+ case 0x96e9:
+ s3->accel.maj_axis_pcnt = (s3->accel.maj_axis_pcnt & 0xff) | ((val & 0x0f) << 8);
+ if (val & 0x08)
+ s3->accel.maj_axis_pcnt |= ~0x0fff;
+ break;
+ case 0x96ea:
+ s3->accel.maj_axis_pcnt2 = (s3->accel.maj_axis_pcnt2 & 0xf00) | val;
+ break;
+ case 0x96eb:
+ s3->accel.maj_axis_pcnt2 = (s3->accel.maj_axis_pcnt2 & 0xff) | ((val & 0x0f) << 8);
+ if (val & 0x08)
+ s3->accel.maj_axis_pcnt2 |= ~0x0fff;
+ break;
+
+ case 0x9ae8:
+ s3->accel.cmd = (s3->accel.cmd & 0xff00) | val;
+ break;
+ case 0x9ae9:
+ s3->accel.cmd = (s3->accel.cmd & 0xff) | (val << 8);
+ s3_accel_start(-1, 0, 0xffffffff, 0, s3);
+ s3->accel.pix_trans_count = 0;
+ s3->accel.multifunc[0xe] &= ~0x10; /*hack*/
+ break;
+
+ case 0x9ee8:
+ s3->accel.short_stroke = (s3->accel.short_stroke & 0xff00) | val;
+ break;
+ case 0x9ee9:
+ s3->accel.short_stroke = (s3->accel.short_stroke & 0xff) | (val << 8);
+ break;
+
+ case 0xa2e8:
+ if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200))
+ s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x00ff0000) | (val << 16);
+ else
+ s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x000000ff) | val;
+ break;
+ case 0xa2e9:
+ if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200))
+ s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0xff000000) | (val << 24);
+ else
+ s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x0000ff00) | (val << 8);
+ if (!(s3->accel.multifunc[0xe] & 0x200))
+ s3->accel.multifunc[0xe] ^= 0x10;
+ break;
+ case 0xa2ea:
+ if (s3->accel.multifunc[0xe] & 0x200)
+ s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x00ff0000) | (val << 16);
+ else if (s3->bpp == 3)
+ {
+ if (s3->accel.multifunc[0xe] & 0x10)
+ s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x00ff0000) | (val << 16);
+ else
+ s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x000000ff) | val;
+ }
+ break;
+ case 0xa2eb:
+ if (s3->accel.multifunc[0xe] & 0x200)
+ s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0xff000000) | (val << 24);
+ else if (s3->bpp == 3)
+ {
+ if (s3->accel.multifunc[0xe] & 0x10)
+ s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0xff000000) | (val << 24);
+ else
+ s3->accel.bkgd_color = (s3->accel.bkgd_color & ~0x0000ff00) | (val << 8);
+ s3->accel.multifunc[0xe] ^= 0x10;
+ }
+ break;
+
+ case 0xa6e8:
+ if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200))
+ s3->accel.frgd_color = (s3->accel.frgd_color & ~0x00ff0000) | (val << 16);
+ else
+ s3->accel.frgd_color = (s3->accel.frgd_color & ~0x000000ff) | val;
+ break;
+ case 0xa6e9:
+ if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200))
+ s3->accel.frgd_color = (s3->accel.frgd_color & ~0xff000000) | (val << 24);
+ else
+ s3->accel.frgd_color = (s3->accel.frgd_color & ~0x0000ff00) | (val << 8);
+ if (!(s3->accel.multifunc[0xe] & 0x200))
+ s3->accel.multifunc[0xe] ^= 0x10;
+ break;
+ case 0xa6ea:
+ if (s3->accel.multifunc[0xe] & 0x200)
+ s3->accel.frgd_color = (s3->accel.frgd_color & ~0x00ff0000) | (val << 16);
+ else if (s3->bpp == 3)
+ {
+ if (s3->accel.multifunc[0xe] & 0x10)
+ s3->accel.frgd_color = (s3->accel.frgd_color & ~0x00ff0000) | (val << 16);
+ else
+ s3->accel.frgd_color = (s3->accel.frgd_color & ~0x000000ff) | val;
+ }
+ break;
+ case 0xa6eb:
+ if (s3->accel.multifunc[0xe] & 0x200)
+ s3->accel.frgd_color = (s3->accel.frgd_color & ~0xff000000) | (val << 24);
+ else if (s3->bpp == 3)
+ {
+ if (s3->accel.multifunc[0xe] & 0x10)
+ s3->accel.frgd_color = (s3->accel.frgd_color & ~0xff000000) | (val << 24);
+ else
+ s3->accel.frgd_color = (s3->accel.frgd_color & ~0x0000ff00) | (val << 8);
+ s3->accel.multifunc[0xe] ^= 0x10;
+ }
+ break;
+
+ case 0xaae8:
+ if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200))
+ s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x00ff0000) | (val << 16);
+ else
+ s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x000000ff) | val;
+ break;
+ case 0xaae9:
+ if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200))
+ s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0xff000000) | (val << 24);
+ else
+ s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x0000ff00) | (val << 8);
+ if (!(s3->accel.multifunc[0xe] & 0x200))
+ s3->accel.multifunc[0xe] ^= 0x10;
+ break;
+ case 0xaaea:
+ if (s3->accel.multifunc[0xe] & 0x200)
+ s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x00ff0000) | (val << 16);
+ else if (s3->bpp == 3)
+ {
+ if (s3->accel.multifunc[0xe] & 0x10)
+ s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x00ff0000) | (val << 16);
+ else
+ s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x000000ff) | val;
+ }
+ break;
+ case 0xaaeb:
+ if (s3->accel.multifunc[0xe] & 0x200)
+ s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0xff000000) | (val << 24);
+ else if (s3->bpp == 3)
+ {
+ if (s3->accel.multifunc[0xe] & 0x10)
+ s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0xff000000) | (val << 24);
+ else
+ s3->accel.wrt_mask = (s3->accel.wrt_mask & ~0x0000ff00) | (val << 8);
+ s3->accel.multifunc[0xe] ^= 0x10;
+ }
+ break;
+
+ case 0xaee8:
+ if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200))
+ s3->accel.rd_mask = (s3->accel.rd_mask & ~0x00ff0000) | (val << 16);
+ else
+ s3->accel.rd_mask = (s3->accel.rd_mask & ~0x000000ff) | val;
+ break;
+ case 0xaee9:
+ if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200))
+ s3->accel.rd_mask = (s3->accel.rd_mask & ~0xff000000) | (val << 24);
+ else
+ s3->accel.rd_mask = (s3->accel.rd_mask & ~0x0000ff00) | (val << 8);
+ if (!(s3->accel.multifunc[0xe] & 0x200))
+ s3->accel.multifunc[0xe] ^= 0x10;
+ break;
+ case 0xaeea:
+ if (s3->accel.multifunc[0xe] & 0x200)
+ s3->accel.rd_mask = (s3->accel.rd_mask & ~0x00ff0000) | (val << 16);
+ else if (s3->bpp == 3)
+ {
+ if (s3->accel.multifunc[0xe] & 0x10)
+ s3->accel.rd_mask = (s3->accel.rd_mask & ~0x00ff0000) | (val << 16);
+ else
+ s3->accel.rd_mask = (s3->accel.rd_mask & ~0x000000ff) | val;
+ }
+ break;
+ case 0xaeeb:
+ if (s3->accel.multifunc[0xe] & 0x200)
+ s3->accel.rd_mask = (s3->accel.rd_mask & ~0xff000000) | (val << 24);
+ else if (s3->bpp == 3)
+ {
+ if (s3->accel.multifunc[0xe] & 0x10)
+ s3->accel.rd_mask = (s3->accel.rd_mask & ~0xff000000) | (val << 24);
+ else
+ s3->accel.rd_mask = (s3->accel.rd_mask & ~0x0000ff00) | (val << 8);
+ s3->accel.multifunc[0xe] ^= 0x10;
+ }
+ break;
+
+ case 0xb2e8:
+ if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200))
+ s3->accel.color_cmp = (s3->accel.color_cmp & ~0x00ff0000) | (val << 16);
+ else
+ s3->accel.color_cmp = (s3->accel.color_cmp & ~0x000000ff) | val;
+ break;
+ case 0xb2e9:
+ if (s3->bpp == 3 && s3->accel.multifunc[0xe] & 0x10 && !(s3->accel.multifunc[0xe] & 0x200))
+ s3->accel.color_cmp = (s3->accel.color_cmp & ~0xff000000) | (val << 24);
+ else
+ s3->accel.color_cmp = (s3->accel.color_cmp & ~0x0000ff00) | (val << 8);
+ if (!(s3->accel.multifunc[0xe] & 0x200))
+ s3->accel.multifunc[0xe] ^= 0x10;
+ break;
+ case 0xb2ea:
+ if (s3->accel.multifunc[0xe] & 0x200)
+ s3->accel.color_cmp = (s3->accel.color_cmp & ~0x00ff0000) | (val << 16);
+ else if (s3->bpp == 3)
+ {
+ if (s3->accel.multifunc[0xe] & 0x10)
+ s3->accel.color_cmp = (s3->accel.color_cmp & ~0x00ff0000) | (val << 16);
+ else
+ s3->accel.color_cmp = (s3->accel.color_cmp & ~0x000000ff) | val;
+ }
+ break;
+ case 0xb2eb:
+ if (s3->accel.multifunc[0xe] & 0x200)
+ s3->accel.color_cmp = (s3->accel.color_cmp & ~0xff000000) | (val << 24);
+ else if (s3->bpp == 3)
+ {
+ if (s3->accel.multifunc[0xe] & 0x10)
+ s3->accel.color_cmp = (s3->accel.color_cmp & ~0xff000000) | (val << 24);
+ else
+ s3->accel.color_cmp = (s3->accel.color_cmp & ~0x0000ff00) | (val << 8);
+ s3->accel.multifunc[0xe] ^= 0x10;
+ }
+ break;
+
+ case 0xb6e8:
+ s3->accel.bkgd_mix = val;
+ break;
+
+ case 0xbae8:
+ s3->accel.frgd_mix = val;
+ break;
+
+ case 0xbee8:
+ s3->accel.multifunc_cntl = (s3->accel.multifunc_cntl & 0xff00) | val;
+ break;
+ case 0xbee9:
+ s3->accel.multifunc_cntl = (s3->accel.multifunc_cntl & 0xff) | (val << 8);
+ s3->accel.multifunc[s3->accel.multifunc_cntl >> 12] = s3->accel.multifunc_cntl & 0xfff;
+ break;
+
+ case 0xe2e8:
+ s3->accel.pix_trans[0] = val;
+ if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && !(s3->accel.cmd & 0x600) && (s3->accel.cmd & 0x100))
+ s3_accel_start(8, 1, s3->accel.pix_trans[0], 0, s3);
+ else if (!(s3->accel.cmd & 0x600) && (s3->accel.cmd & 0x100))
+ s3_accel_start(1, 1, 0xffffffff, s3->accel.pix_trans[0], s3);
+ break;
+ case 0xe2e9:
+ s3->accel.pix_trans[1] = val;
+ if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && (s3->accel.cmd & 0x600) == 0x200 && (s3->accel.cmd & 0x100))
+ {
+ if (s3->accel.cmd & 0x1000) s3_accel_start(16, 1, s3->accel.pix_trans[1] | (s3->accel.pix_trans[0] << 8), 0, s3);
+ else s3_accel_start(16, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), 0, s3);
+ }
+ else if ((s3->accel.cmd & 0x600) == 0x200 && (s3->accel.cmd & 0x100))
+ {
+ if (s3->accel.cmd & 0x1000) s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[1] | (s3->accel.pix_trans[0] << 8), s3);
+ else s3_accel_start(2, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8), s3);
+ }
+ break;
+ case 0xe2ea:
+ s3->accel.pix_trans[2] = val;
+ break;
+ case 0xe2eb:
+ s3->accel.pix_trans[3] = val;
+ if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && (s3->accel.cmd & 0x600) == 0x600 && (s3->accel.cmd & 0x100) && s3->chip == S3_TRIO32)
+ {
+ s3_accel_start(8, 1, s3->accel.pix_trans[3], 0, s3);
+ s3_accel_start(8, 1, s3->accel.pix_trans[2], 0, s3);
+ s3_accel_start(8, 1, s3->accel.pix_trans[1], 0, s3);
+ s3_accel_start(8, 1, s3->accel.pix_trans[0], 0, s3);
+ }
+ else if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && (s3->accel.cmd & 0x400) == 0x400 && (s3->accel.cmd & 0x100))
+ s3_accel_start(32, 1, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), 0, s3);
+ else if ((s3->accel.cmd & 0x600) == 0x400 && (s3->accel.cmd & 0x100))
+ s3_accel_start(4, 1, 0xffffffff, s3->accel.pix_trans[0] | (s3->accel.pix_trans[1] << 8) | (s3->accel.pix_trans[2] << 16) | (s3->accel.pix_trans[3] << 24), s3);
+ break;
+ }
+}
+
+static void s3_accel_out_fifo_w(s3_t *s3, uint16_t port, uint16_t val)
+{
+// pclog("Accel out w %04X %04X\n", port, val);
+ if (s3->accel.cmd & 0x100)
+ {
+ if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80)
+ {
+ if (s3->accel.cmd & 0x1000)
+ val = (val >> 8) | (val << 8);
+ if ((s3->accel.cmd & 0x600) == 0x600 && s3->chip == S3_TRIO32)
+ {
+ s3_accel_start(8, 1, (val >> 8) & 0xff, 0, s3);
+ s3_accel_start(8, 1, val & 0xff, 0, s3);
+ }
+ if ((s3->accel.cmd & 0x600) == 0x000)
+ s3_accel_start(8, 1, val | (val << 16), 0, s3);
+ else
+ s3_accel_start(16, 1, val | (val << 16), 0, s3);
+ }
+ else
+ {
+ if ((s3->accel.cmd & 0x600) == 0x000)
+ s3_accel_start(1, 1, 0xffffffff, val | (val << 16), s3);
+ else
+ s3_accel_start(2, 1, 0xffffffff, val | (val << 16), s3);
+ }
+ }
+}
+
+static void s3_accel_out_fifo_l(s3_t *s3, uint16_t port, uint32_t val)
+{
+// pclog("Accel out l %04X %08X\n", port, val);
+ if (s3->accel.cmd & 0x100)
+ {
+ if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80)
+ {
+ if ((s3->accel.cmd & 0x600) == 0x600 && s3->chip == S3_TRIO32)
+ {
+ if (s3->accel.cmd & 0x1000)
+ val = ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24);
+ s3_accel_start(8, 1, (val >> 24) & 0xff, 0, s3);
+ s3_accel_start(8, 1, (val >> 16) & 0xff, 0, s3);
+ s3_accel_start(8, 1, (val >> 8) & 0xff, 0, s3);
+ s3_accel_start(8, 1, val & 0xff, 0, s3);
+ }
+ else if (s3->accel.cmd & 0x400)
+ {
+ if (s3->accel.cmd & 0x1000)
+ val = ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24);
+ s3_accel_start(32, 1, val, 0, s3);
+ }
+ else if ((s3->accel.cmd & 0x600) == 0x200)
+ {
+ if (s3->accel.cmd & 0x1000)
+ val = ((val & 0xff00ff00) >> 8) | ((val & 0x00ff00ff) << 8);
+ s3_accel_start(16, 1, val, 0, s3);
+ s3_accel_start(16, 1, val >> 16, 0, s3);
+ }
+ else
+ {
+ if (s3->accel.cmd & 0x1000)
+ val = ((val & 0xff00ff00) >> 8) | ((val & 0x00ff00ff) << 8);
+ s3_accel_start(8, 1, val, 0, s3);
+ s3_accel_start(8, 1, val >> 16, 0, s3);
+ }
+ }
+ else
+ {
+ if (s3->accel.cmd & 0x400)
+ s3_accel_start(4, 1, 0xffffffff, val, s3);
+ else if ((s3->accel.cmd & 0x600) == 0x200)
+ {
+ s3_accel_start(2, 1, 0xffffffff, val, s3);
+ s3_accel_start(2, 1, 0xffffffff, val >> 16, s3);
+ }
+ else
+ {
+ s3_accel_start(1, 1, 0xffffffff, val, s3);
+ s3_accel_start(1, 1, 0xffffffff, val >> 16, s3);
+ }
+ }
+ }
+}
+
+static void s3_accel_write_fifo(s3_t *s3, uint32_t addr, uint8_t val)
+{
+// pclog("Write S3 accel %08X %02X\n", addr, val);
+ if (s3->packed_mmio)
+ {
+ int addr_lo = addr & 1;
+ switch (addr & 0xfffe)
+ {
+ case 0x8100: addr = 0x82e8; break; /*ALT_CURXY*/
+ case 0x8102: addr = 0x86e8; break;
+
+ case 0x8104: addr = 0x82ea; break; /*ALT_CURXY2*/
+ case 0x8106: addr = 0x86ea; break;
+
+ case 0x8108: addr = 0x8ae8; break; /*ALT_STEP*/
+ case 0x810a: addr = 0x8ee8; break;
+
+ case 0x810c: addr = 0x8aea; break; /*ALT_STEP2*/
+ case 0x810e: addr = 0x8eea; break;
+
+ case 0x8110: addr = 0x92e8; break; /*ALT_ERR*/
+ case 0x8112: addr = 0x92ee; break;
+
+ case 0x8118: addr = 0x9ae8; break; /*ALT_CMD*/
+ case 0x811a: addr = 0x9aea; break;
+
+ case 0x811c: addr = 0x9ee8; break; /*SHORT_STROKE*/
+
+ case 0x8120: case 0x8122: /*BKGD_COLOR*/
+ WRITE8(addr, s3->accel.bkgd_color, val);
+ return;
+
+ case 0x8124: case 0x8126: /*FRGD_COLOR*/
+ WRITE8(addr, s3->accel.frgd_color, val);
+ return;
+
+ case 0x8128: case 0x812a: /*WRT_MASK*/
+ WRITE8(addr, s3->accel.wrt_mask, val);
+ return;
+
+ case 0x812c: case 0x812e: /*RD_MASK*/
+ WRITE8(addr, s3->accel.rd_mask, val);
+ return;
+
+ case 0x8130: case 0x8132: /*COLOR_CMP*/
+ WRITE8(addr, s3->accel.color_cmp, val);
+ return;
+
+ case 0x8134: addr = 0xb6e8; break; /*ALT_MIX*/
+ case 0x8136: addr = 0xbae8; break;
+
+ case 0x8138: /*SCISSORS_T*/
+ WRITE8(addr & 1, s3->accel.multifunc[1], val);
+ return;
+ case 0x813a: /*SCISSORS_L*/
+ WRITE8(addr & 1, s3->accel.multifunc[2], val);
+ return;
+ case 0x813c: /*SCISSORS_B*/
+ WRITE8(addr & 1, s3->accel.multifunc[3], val);
+ return;
+ case 0x813e: /*SCISSORS_R*/
+ WRITE8(addr & 1, s3->accel.multifunc[4], val);
+ return;
+
+ case 0x8140: /*PIX_CNTL*/
+ WRITE8(addr & 1, s3->accel.multifunc[0xa], val);
+ return;
+ case 0x8142: /*MULT_MISC2*/
+ WRITE8(addr & 1, s3->accel.multifunc[0xd], val);
+ return;
+ case 0x8144: /*MULT_MISC*/
+ WRITE8(addr & 1, s3->accel.multifunc[0xe], val);
+ return;
+ case 0x8146: /*READ_SEL*/
+ WRITE8(addr & 1, s3->accel.multifunc[0xf], val);
+ return;
+
+ case 0x8148: /*ALT_PCNT*/
+ WRITE8(addr & 1, s3->accel.multifunc[0], val);
+ return;
+ case 0x814a: addr = 0x96e8; break;
+ case 0x814c: addr = 0x96ea; break;
+
+ case 0x8168: addr = 0xeae8; break;
+ case 0x816a: addr = 0xeaea; break;
+ }
+ addr |= addr_lo;
+ }
+
+
+ if (addr & 0x8000)
+ {
+ s3_accel_out_fifo(s3, addr & 0xffff, val);
+ }
+ else
+ {
+ if (s3->accel.cmd & 0x100)
+ {
+ if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80)
+ s3_accel_start(8, 1, val | (val << 8) | (val << 16) | (val << 24), 0, s3);
+ else
+ s3_accel_start(1, 1, 0xffffffff, val | (val << 8) | (val << 16) | (val << 24), s3);
+ }
+ }
+}
+
+static void s3_accel_write_fifo_w(s3_t *s3, uint32_t addr, uint16_t val)
+{
+// pclog("Write S3 accel w %08X %04X\n", addr, val);
+ if (addr & 0x8000)
+ {
+ s3_accel_write_fifo(s3, addr, val);
+ s3_accel_write_fifo(s3, addr + 1, val >> 8);
+ }
+ else
+ {
+ if (s3->accel.cmd & 0x100)
+ {
+ if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80)
+ {
+ if (s3->accel.cmd & 0x1000)
+ val = (val >> 8) | (val << 8);
+ if ((s3->accel.cmd & 0x600) == 0x600 && s3->chip == S3_TRIO32)
+ {
+ s3_accel_start(8, 1, (val >> 8) & 0xff, 0, s3);
+ s3_accel_start(8, 1, val & 0xff, 0, s3);
+ }
+ else if ((s3->accel.cmd & 0x600) == 0x000)
+ s3_accel_start(8, 1, val | (val << 16), 0, s3);
+ else
+ s3_accel_start(16, 1, val | (val << 16), 0, s3);
+ }
+ else
+ {
+ if ((s3->accel.cmd & 0x600) == 0x000)
+ s3_accel_start(1, 1, 0xffffffff, val | (val << 16), s3);
+ else
+ s3_accel_start(2, 1, 0xffffffff, val | (val << 16), s3);
+ }
+ }
+ }
+}
+
+static void s3_accel_write_fifo_l(s3_t *s3, uint32_t addr, uint32_t val)
+{
+// pclog("Write S3 accel l %08X %08X\n", addr, val);
+ if (addr & 0x8000)
+ {
+ s3_accel_write_fifo(s3, addr, val);
+ s3_accel_write_fifo(s3, addr + 1, val >> 8);
+ s3_accel_write_fifo(s3, addr + 2, val >> 16);
+ s3_accel_write_fifo(s3, addr + 3, val >> 24);
+ }
+ else
+ {
+ if (s3->accel.cmd & 0x100)
+ {
+ if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80)
+ {
+ if ((s3->accel.cmd & 0x600) == 0x600 && s3->chip == S3_TRIO32)
+ {
+ if (s3->accel.cmd & 0x1000)
+ val = ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24);
+ s3_accel_start(8, 1, (val >> 24) & 0xff, 0, s3);
+ s3_accel_start(8, 1, (val >> 16) & 0xff, 0, s3);
+ s3_accel_start(8, 1, (val >> 8) & 0xff, 0, s3);
+ s3_accel_start(8, 1, val & 0xff, 0, s3);
+ }
+ else if (s3->accel.cmd & 0x400)
+ {
+ if (s3->accel.cmd & 0x1000)
+ val = ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24);
+ s3_accel_start(32, 1, val, 0, s3);
+ }
+ else if ((s3->accel.cmd & 0x600) == 0x200)
+ {
+ if (s3->accel.cmd & 0x1000)
+ val = ((val & 0xff00ff00) >> 8) | ((val & 0x00ff00ff) << 8);
+ s3_accel_start(16, 1, val, 0, s3);
+ s3_accel_start(16, 1, val >> 16, 0, s3);
+ }
+ else
+ {
+ if (s3->accel.cmd & 0x1000)
+ val = ((val & 0xff00ff00) >> 8) | ((val & 0x00ff00ff) << 8);
+ s3_accel_start(8, 1, val, 0, s3);
+ s3_accel_start(8, 1, val >> 16, 0, s3);
+ }
+ }
+ else
+ {
+ if (s3->accel.cmd & 0x400)
+ s3_accel_start(4, 1, 0xffffffff, val, s3);
+ else if ((s3->accel.cmd & 0x600) == 0x200)
+ {
+ s3_accel_start(2, 1, 0xffffffff, val, s3);
+ s3_accel_start(2, 1, 0xffffffff, val >> 16, s3);
+ }
+ else
+ {
+ s3_accel_start(1, 1, 0xffffffff, val, s3);
+ s3_accel_start(1, 1, 0xffffffff, val >> 16, s3);
+ }
+ }
+ }
+ }
+}
+
+static void fifo_thread(void *param)
+{
+ s3_t *s3 = (s3_t *)param;
+
+ while (1)
+ {
+ thread_set_event(s3->fifo_not_full_event);
+ thread_wait_event(s3->wake_fifo_thread, -1);
+ thread_reset_event(s3->wake_fifo_thread);
+ s3->blitter_busy = 1;
+ while (!FIFO_EMPTY)
+ {
+ uint64_t start_time = timer_read();
+ uint64_t end_time;
+ fifo_entry_t *fifo = &s3->fifo[s3->fifo_read_idx & FIFO_MASK];
+
+ switch (fifo->addr_type & FIFO_TYPE)
+ {
+ case FIFO_WRITE_BYTE:
+ s3_accel_write_fifo(s3, fifo->addr_type & FIFO_ADDR, fifo->val);
+ break;
+ case FIFO_WRITE_WORD:
+ s3_accel_write_fifo_w(s3, fifo->addr_type & FIFO_ADDR, fifo->val);
+ break;
+ case FIFO_WRITE_DWORD:
+ s3_accel_write_fifo_l(s3, fifo->addr_type & FIFO_ADDR, fifo->val);
+ break;
+ case FIFO_OUT_BYTE:
+ s3_accel_out_fifo(s3, fifo->addr_type & FIFO_ADDR, fifo->val);
+ break;
+ case FIFO_OUT_WORD:
+ s3_accel_out_fifo_w(s3, fifo->addr_type & FIFO_ADDR, fifo->val);
+ break;
+ case FIFO_OUT_DWORD:
+ s3_accel_out_fifo_l(s3, fifo->addr_type & FIFO_ADDR, fifo->val);
+ break;
+ }
+
+ s3->fifo_read_idx++;
+ fifo->addr_type = FIFO_INVALID;
+
+ if (FIFO_ENTRIES > 0xe000)
+ thread_set_event(s3->fifo_not_full_event);
+
+ end_time = timer_read();
+ s3->blitter_time += end_time - start_time;
+ }
+ s3->blitter_busy = 0;
+ s3->subsys_stat |= INT_FIFO_EMP;
+ s3_update_irqs(s3);
+ }
+}
+
+static void s3_vblank_start(svga_t *svga)
+{
+ s3_t *s3 = (s3_t *)svga->p;
+
+ s3->subsys_stat |= INT_VSY;
+ s3_update_irqs(s3);
+}
+
+static void s3_queue(s3_t *s3, uint32_t addr, uint32_t val, uint32_t type)
+{
+ fifo_entry_t *fifo = &s3->fifo[s3->fifo_write_idx & FIFO_MASK];
+
+ if (FIFO_FULL)
+ {
+ thread_reset_event(s3->fifo_not_full_event);
+ if (FIFO_FULL)
+ {
+ thread_wait_event(s3->fifo_not_full_event, -1); /*Wait for room in ringbuffer*/
+ }
+ }
+
+ fifo->val = val;
+ fifo->addr_type = (addr & FIFO_ADDR) | type;
+
+ s3->fifo_write_idx++;
+
+ if (FIFO_ENTRIES > 0xe000 || FIFO_ENTRIES < 8)
+ wake_fifo_thread(s3);
+}
+
+void s3_out(uint16_t addr, uint8_t val, void *p)
+{
+ s3_t *s3 = (s3_t *)p;
+ svga_t *svga = &s3->svga;
+ uint8_t old;
+
+ if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1))
+ addr ^= 0x60;
+
+// pclog("S3 out %04X %02X %04x:%08x\n", addr, val, CS, pc);
+
+ switch (addr)
+ {
+ case 0x3c5:
+ if (svga->seqaddr >= 0x10 && svga->seqaddr < 0x20)
+ {
+ svga->seqregs[svga->seqaddr] = val;
+ switch (svga->seqaddr)
+ {
+ case 0x12: case 0x13:
+ svga_recalctimings(svga);
+ return;
+ }
+ }
+ if (svga->seqaddr == 4) /*Chain-4 - update banking*/
+ {
+ if (val & 8) svga->write_bank = svga->read_bank = s3->bank << 16;
+ else svga->write_bank = svga->read_bank = s3->bank << 14;
+ }
+ break;
+
+ case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9:
+// pclog("Write RAMDAC %04X %02X %04X:%04X\n", addr, val, CS, pc);
+ if (s3->chip == S3_TRIO32 || s3->chip == S3_TRIO64)
+ svga_out(addr, val, svga);
+ else
+ {
+ if ((svga->crtc[0x55] & 1) || (svga->crtc[0x43] & 2))
+ sdac_ramdac_out((addr & 3) | 4, val, &s3->ramdac, svga);
+ else
+ sdac_ramdac_out(addr & 3, val, &s3->ramdac, svga);
+ }
+ return;
+
+ case 0x3D4:
+ svga->crtcreg = val & 0x7f;
+ return;
+ case 0x3D5:
+ if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80))
+ return;
+ if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80))
+ val = (svga->crtc[7] & ~0x10) | (val & 0x10);
+ if (svga->crtcreg >= 0x20 && svga->crtcreg != 0x38 && (svga->crtc[0x38] & 0xcc) != 0x48) return;
+ old = svga->crtc[svga->crtcreg];
+ svga->crtc[svga->crtcreg] = val;
+ switch (svga->crtcreg)
+ {
+ case 0x31:
+ s3->ma_ext = (s3->ma_ext & 0x1c) | ((val & 0x30) >> 4);
+ break;
+ case 0x32:
+ svga->vram_display_mask = (val & 0x40) ? 0x3ffff : s3->vram_mask;
+ break;
+
+ case 0x50:
+ switch (svga->crtc[0x50] & 0xc1)
+ {
+ case 0x00: s3->width = (svga->crtc[0x31] & 2) ? 2048 : 1024; break;
+ case 0x01: s3->width = 1152; break;
+ case 0x40: s3->width = 640; break;
+ case 0x80: s3->width = 800; break;
+ case 0x81: s3->width = 1600; break;
+ case 0xc0: s3->width = 1280; break;
+ }
+ s3->bpp = (svga->crtc[0x50] >> 4) & 3;
+ break;
+ case 0x69:
+ s3->ma_ext = val & 0x1f;
+ break;
+
+ case 0x35:
+ s3->bank = (s3->bank & 0x70) | (val & 0xf);
+// pclog("CRTC write R35 %02X\n", val);
+ if (svga->chain4) svga->write_bank = svga->read_bank = s3->bank << 16;
+ else svga->write_bank = svga->read_bank = s3->bank << 14;
+ break;
+ case 0x51:
+ s3->bank = (s3->bank & 0x4f) | ((val & 0xc) << 2);
+// pclog("CRTC write R51 %02X\n", val);
+ if (svga->chain4) svga->write_bank = svga->read_bank = s3->bank << 16;
+ else svga->write_bank = svga->read_bank = s3->bank << 14;
+ s3->ma_ext = (s3->ma_ext & ~0xc) | ((val & 3) << 2);
+ break;
+ case 0x6a:
+ s3->bank = val;
+// pclog("CRTC write R6a %02X\n", val);
+ if (svga->chain4) svga->write_bank = svga->read_bank = s3->bank << 16;
+ else svga->write_bank = svga->read_bank = s3->bank << 14;
+ break;
+
+ case 0x3a:
+ if (val & 0x10)
+ svga->gdcreg[5] |= 0x40; /*Horrible cheat*/
+ break;
+
+ case 0x45:
+ svga->hwcursor.ena = val & 1;
+ break;
+ case 0x48:
+ svga->hwcursor.x = ((svga->crtc[0x46] << 8) | svga->crtc[0x47]) & 0x7ff;
+ if (svga->bpp == 32) svga->hwcursor.x >>= 1;
+ svga->hwcursor.y = ((svga->crtc[0x48] << 8) | svga->crtc[0x49]) & 0x7ff;
+ svga->hwcursor.xoff = svga->crtc[0x4e] & 63;
+ svga->hwcursor.yoff = svga->crtc[0x4f] & 63;
+ svga->hwcursor.addr = ((((svga->crtc[0x4c] << 8) | svga->crtc[0x4d]) & 0xfff) * 1024) + (svga->hwcursor.yoff * 16);
+ if ((s3->chip == S3_TRIO32 || s3->chip == S3_TRIO64) && svga->bpp == 32)
+ svga->hwcursor.x <<= 1;
+ break;
+
+ case 0x4a:
+ switch (s3->hwc_col_stack_pos)
+ {
+ case 0:
+ s3->hwc_fg_col = (s3->hwc_fg_col & 0xffff00) | val;
+ break;
+ case 1:
+ s3->hwc_fg_col = (s3->hwc_fg_col & 0xff00ff) | (val << 8);
+ break;
+ case 2:
+ s3->hwc_fg_col = (s3->hwc_fg_col & 0x00ffff) | (val << 16);
+ break;
+ }
+ s3->hwc_col_stack_pos = (s3->hwc_col_stack_pos + 1) % 3;
+ break;
+ case 0x4b:
+ switch (s3->hwc_col_stack_pos)
+ {
+ case 0:
+ s3->hwc_bg_col = (s3->hwc_bg_col & 0xffff00) | val;
+ break;
+ case 1:
+ s3->hwc_bg_col = (s3->hwc_bg_col & 0xff00ff) | (val << 8);
+ break;
+ case 2:
+ s3->hwc_bg_col = (s3->hwc_bg_col & 0x00ffff) | (val << 16);
+ break;
+ }
+ s3->hwc_col_stack_pos = (s3->hwc_col_stack_pos + 1) % 3;
+ break;
+
+ case 0x53:
+ case 0x58: case 0x59: case 0x5a:
+ s3_updatemapping(s3);
+ break;
+
+ case 0x67:
+ if (s3->chip == S3_TRIO32 || s3->chip == S3_TRIO64)
+ {
+ switch (val >> 4)
+ {
+ case 3: svga->bpp = 15; break;
+ case 5: svga->bpp = 16; break;
+ case 7: svga->bpp = 24; break;
+ case 13: svga->bpp = 32; break;
+ default: svga->bpp = 8; break;
+ }
+ }
+ break;
+ //case 0x55: case 0x43:
+// pclog("Write CRTC R%02X %02X\n", crtcreg, val);
+ }
+ if (old != val)
+ {
+ if (svga->crtcreg < 0xe || svga->crtcreg > 0x10)
+ {
+ svga->fullchange = changeframecount;
+ svga_recalctimings(svga);
+ }
+ }
+ break;
+ }
+ svga_out(addr, val, svga);
+}
+
+uint8_t s3_in(uint16_t addr, void *p)
+{
+ s3_t *s3 = (s3_t *)p;
+ svga_t *svga = &s3->svga;
+
+ if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1))
+ addr ^= 0x60;
+
+// if (addr != 0x3da) pclog("S3 in %04X %08x:%02x\n", addr, CS, pc);
+ switch (addr)
+ {
+ case 0x3c1:
+ if (svga->attraddr > 0x14)
+ return 0xff;
+ break;
+
+ case 0x3c5:
+ if (svga->seqaddr >= 0x10 && svga->seqaddr < 0x20)
+ return svga->seqregs[svga->seqaddr];
+ break;
+
+ case 0x3c6: case 0x3c7: case 0x3c8: case 0x3c9:
+// pclog("Read RAMDAC %04X %04X:%04X\n", addr, CS, pc);
+ if (s3->chip == S3_TRIO32 || s3->chip == S3_TRIO64)
+ return svga_in(addr, svga);
+ if ((svga->crtc[0x55] & 1) || (svga->crtc[0x43] & 2))
+ return sdac_ramdac_in((addr & 3) | 4, &s3->ramdac, svga);
+ return sdac_ramdac_in(addr & 3, &s3->ramdac, svga);
+
+ case 0x3d4:
+ return svga->crtcreg;
+ case 0x3d5:
+// pclog("Read CRTC R%02X %02x %04X:%04X\n", svga->crtcreg, svga->crtc[svga->crtcreg], CS, pc);
+ switch (svga->crtcreg)
+ {
+ case 0x2d: return 0x88; /*Extended chip ID*/
+ case 0x2e: return s3->id_ext; /*New chip ID*/
+ case 0x2f: return 0; /*Revision level*/
+ case 0x30: return s3->id; /*Chip ID*/
+ case 0x31: return (svga->crtc[0x31] & 0xcf) | ((s3->ma_ext & 3) << 4);
+ case 0x35: return (svga->crtc[0x35] & 0xf0) | (s3->bank & 0xf);
+ case 0x45: s3->hwc_col_stack_pos = 0; break;
+ case 0x51: return (svga->crtc[0x51] & 0xf0) | ((s3->bank >> 2) & 0xc) | ((s3->ma_ext >> 2) & 3);
+ case 0x69: return s3->ma_ext;
+ case 0x6a: return s3->bank;
+ }
+ return svga->crtc[svga->crtcreg];
+ }
+ return svga_in(addr, svga);
+}
+
+void s3_recalctimings(svga_t *svga)
+{
+ s3_t *s3 = (s3_t *)svga->p;
+ svga->hdisp = svga->hdisp_old;
+ int clk_sel = (svga->miscout >> 2) & 3;
+
+ if (clk_sel == 3 && s3->chip == S3_VISION864)
+ clk_sel = svga->crtc[0x42] & 0xf;
+
+// pclog("%i %i\n", svga->hdisp, svga->hdisp_time);
+// pclog("recalctimings\n");
+ svga->ma_latch |= (s3->ma_ext << 16);
+// pclog("SVGA_MA %08X\n", svga_ma);
+ if (svga->crtc[0x5d] & 0x01) svga->htotal += 0x100;
+ if (svga->crtc[0x5d] & 0x02)
+ {
+ svga->hdisp_time += 0x100;
+ svga->hdisp += 0x100 * ((svga->seqregs[1] & 8) ? 16 : 8);
+ }
+ if (svga->crtc[0x5e] & 0x01) svga->vtotal += 0x400;
+ if (svga->crtc[0x5e] & 0x02) svga->dispend += 0x400;
+ if (svga->crtc[0x5e] & 0x04) svga->vblankstart += 0x400;
+ if (svga->crtc[0x5e] & 0x10) svga->vsyncstart += 0x400;
+ if (svga->crtc[0x5e] & 0x40) svga->split += 0x400;
+ if (svga->crtc[0x51] & 0x30) svga->rowoffset += (svga->crtc[0x51] & 0x30) << 4;
+ else if (svga->crtc[0x43] & 0x04) svga->rowoffset += 0x100;
+ if (!svga->rowoffset) svga->rowoffset = 256;
+ svga->interlace = svga->crtc[0x42] & 0x20;
+ svga->clock = (cpuclock * (float)(1ull << 32)) / s3->getclock(clk_sel, s3->getclock_p);
+
+ switch (svga->crtc[0x67] >> 4)
+ {
+ case 3: case 5: case 7:
+ svga->clock /= 2;
+ break;
+ }
+
+ svga->lowres = !((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10));
+ if ((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10))
+ {
+ switch (svga->bpp)
+ {
+ case 8:
+ svga->render = svga_render_8bpp_highres;
+ break;
+ case 15:
+ svga->render = svga_render_15bpp_highres;
+ svga->hdisp /= 2;
+ break;
+ case 16:
+ svga->render = svga_render_16bpp_highres;
+ svga->hdisp /= 2;
+ break;
+ case 24:
+ svga->render = svga_render_24bpp_highres;
+ svga->hdisp /= 3;
+ break;
+ case 32:
+ svga->render = svga_render_32bpp_highres;
+ if (s3->chip != S3_TRIO32 && s3->chip != S3_TRIO64)
+ svga->hdisp /= 4;
+ break;
+ }
+ }
+}
+
+void s3_updatemapping(s3_t *s3)
+{
+ svga_t *svga = &s3->svga;
+
+// video_write_a000_w = video_write_a000_l = NULL;
+
+ if (!(s3->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_MEM))
+ {
+// pclog("Update mapping - PCI disabled\n");
+ mem_mapping_disable(&svga->mapping);
+ mem_mapping_disable(&s3->linear_mapping);
+ mem_mapping_disable(&s3->mmio_mapping);
+ return;
+ }
+
+// pclog("Update mapping - bank %02X ", svga->gdcreg[6] & 0xc);
+ /*Banked framebuffer*/
+ if (svga->crtc[0x31] & 0x08) /*Enhanced mode mappings*/
+ {
+ /*Enhanced mapping forces 64kb at 0xa0000*/
+ mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000);
+ svga->banked_mask = 0xffff;
+ }
+ else switch (svga->gdcreg[6] & 0xc) /*VGA mapping*/
+ {
+ case 0x0: /*128k at A0000*/
+ mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000);
+ svga->banked_mask = 0xffff;
+ break;
+ case 0x4: /*64k at A0000*/
+ mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000);
+ svga->banked_mask = 0xffff;
+ break;
+ case 0x8: /*32k at B0000*/
+ mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000);
+ svga->banked_mask = 0x7fff;
+ break;
+ case 0xC: /*32k at B8000*/
+ mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000);
+ svga->banked_mask = 0x7fff;
+ break;
+ }
+
+// pclog("Linear framebuffer %02X ", svga->crtc[0x58] & 0x10);
+ if (svga->crtc[0x58] & 0x10) /*Linear framebuffer*/
+ {
+ mem_mapping_disable(&svga->mapping);
+
+ s3->linear_base = (svga->crtc[0x5a] << 16) | (svga->crtc[0x59] << 24);
+ switch (svga->crtc[0x58] & 3)
+ {
+ case 0: /*64k*/
+ s3->linear_size = 0x10000;
+ break;
+ case 1: /*1mb*/
+ s3->linear_size = 0x100000;
+ break;
+ case 2: /*2mb*/
+ s3->linear_size = 0x200000;
+ break;
+ case 3: /*8mb*/
+ s3->linear_size = 0x800000;
+ break;
+ }
+ s3->linear_base &= ~(s3->linear_size - 1);
+// pclog("%08X %08X %02X %02X %02X\n", linear_base, linear_size, crtc[0x58], crtc[0x59], crtc[0x5a]);
+// pclog("Linear framebuffer at %08X size %08X\n", s3->linear_base, s3->linear_size);
+ if (s3->linear_base == 0xa0000)
+ {
+ mem_mapping_disable(&s3->linear_mapping);
+ if (!(svga->crtc[0x53] & 0x10))
+ {
+ mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000);
+ svga->banked_mask = 0xffff;
+ }
+// mem_mapping_set_addr(&s3->linear_mapping, 0xa0000, 0x10000);
+ }
+ else
+ mem_mapping_set_addr(&s3->linear_mapping, s3->linear_base, s3->linear_size);
+ }
+ else
+ mem_mapping_disable(&s3->linear_mapping);
+
+// pclog("Memory mapped IO %02X\n", svga->crtc[0x53] & 0x10);
+ if (svga->crtc[0x53] & 0x10) /*Memory mapped IO*/
+ {
+ mem_mapping_disable(&svga->mapping);
+ mem_mapping_enable(&s3->mmio_mapping);
+ }
+ else
+ mem_mapping_disable(&s3->mmio_mapping);
+}
+
+static float s3_trio64_getclock(int clock, void *p)
+{
+ s3_t *s3 = (s3_t *)p;
+ svga_t *svga = &s3->svga;
+ float t;
+ int m, n1, n2;
+// pclog("Trio64_getclock %i %02X %02X\n", clock, svga->seqregs[0x13], svga->seqregs[0x12]);
+ if (clock == 0) return 25175000.0;
+ if (clock == 1) return 28322000.0;
+ m = svga->seqregs[0x13] + 2;
+ n1 = (svga->seqregs[0x12] & 0x1f) + 2;
+ n2 = ((svga->seqregs[0x12] >> 5) & 0x07);
+ t = (14318184.0 * ((float)m / (float)n1)) / (float)(1 << n2);
+// pclog("TRIO64 clock %i %i %i %f %f %i\n", m, n1, n2, t, 14318184.0 * ((float)m / (float)n1), 1 << n2);
+ return t;
+}
+
+
+void s3_accel_out(uint16_t port, uint8_t val, void *p)
+{
+ s3_t *s3 = (s3_t *)p;
+// pclog("Accel out %04X %02X\n", port, val);
+
+ if (port >= 0x8000)
+ {
+ s3_queue(s3, port, val, FIFO_OUT_BYTE);
+ }
+ else switch (port)
+ {
+ case 0x42e8:
+ s3->subsys_stat &= ~val;
+ s3_update_irqs(s3);
+ break;
+ case 0x42e9:
+ s3->subsys_cntl = val;
+ s3_update_irqs(s3);
+ break;
+ case 0x46e8:
+ s3->accel.setup_md = val;
+ break;
+ case 0x4ae8:
+ s3->accel.advfunc_cntl = val;
+ break;
+ }
+}
+
+void s3_accel_out_w(uint16_t port, uint16_t val, void *p)
+{
+ s3_t *s3 = (s3_t *)p;
+// pclog("Accel out w %04X %04X\n", port, val);
+ s3_queue(s3, port, val, FIFO_OUT_WORD);
+}
+
+void s3_accel_out_l(uint16_t port, uint32_t val, void *p)
+{
+ s3_t *s3 = (s3_t *)p;
+// pclog("Accel out l %04X %08X\n", port, val);
+ s3_queue(s3, port, val, FIFO_OUT_DWORD);
+}
+
+uint8_t s3_accel_in(uint16_t port, void *p)
+{
+ s3_t *s3 = (s3_t *)p;
+ int temp;
+// pclog("Accel in %04X\n", port);
+ switch (port)
+ {
+ case 0x42e8:
+ return s3->subsys_stat;
+ case 0x42e9:
+ return s3->subsys_cntl;
+
+ case 0x82e8:
+ s3_wait_fifo_idle(s3);
+ return s3->accel.cur_y & 0xff;
+ case 0x82e9:
+ s3_wait_fifo_idle(s3);
+ return s3->accel.cur_y >> 8;
+
+ case 0x86e8:
+ s3_wait_fifo_idle(s3);
+ return s3->accel.cur_x & 0xff;
+ case 0x86e9:
+ s3_wait_fifo_idle(s3);
+ return s3->accel.cur_x >> 8;
+
+ case 0x8ae8:
+ s3_wait_fifo_idle(s3);
+ return s3->accel.desty_axstp & 0xff;
+ case 0x8ae9:
+ s3_wait_fifo_idle(s3);
+ return s3->accel.desty_axstp >> 8;
+
+ case 0x8ee8:
+ s3_wait_fifo_idle(s3);
+ return s3->accel.destx_distp & 0xff;
+ case 0x8ee9:
+ s3_wait_fifo_idle(s3);
+ return s3->accel.destx_distp >> 8;
+
+ case 0x92e8:
+ s3_wait_fifo_idle(s3);
+ return s3->accel.err_term & 0xff;
+ case 0x92e9:
+ s3_wait_fifo_idle(s3);
+ return s3->accel.err_term >> 8;
+
+ case 0x96e8:
+ s3_wait_fifo_idle(s3);
+ return s3->accel.maj_axis_pcnt & 0xff;
+ case 0x96e9:
+ s3_wait_fifo_idle(s3);
+ return s3->accel.maj_axis_pcnt >> 8;
+
+ case 0x9ae8:
+ if (!s3->blitter_busy)
+ wake_fifo_thread(s3);
+ if (FIFO_FULL)
+ return 0xff; /*FIFO full*/
+ return 0; /*FIFO empty*/
+ case 0x9ae9:
+ if (!s3->blitter_busy)
+ wake_fifo_thread(s3);
+ temp = 0;
+ if (!FIFO_EMPTY || s3->force_busy)
+ temp |= 0x02; /*Hardware busy*/
+ else
+ temp |= 0x04; /*FIFO empty*/
+ s3->force_busy = 0;
+ if (FIFO_FULL)
+ temp |= 0xf8; /*FIFO full*/
+ return temp;
+
+ case 0xa2e8:
+ s3_wait_fifo_idle(s3);
+ return s3->accel.bkgd_color & 0xff;
+ case 0xa2e9:
+ s3_wait_fifo_idle(s3);
+ return s3->accel.bkgd_color >> 8;
+ case 0xa2ea:
+ s3_wait_fifo_idle(s3);
+ return s3->accel.bkgd_color >> 16;
+ case 0xa2eb:
+ s3_wait_fifo_idle(s3);
+ return s3->accel.bkgd_color >> 24;
+
+ case 0xa6e8:
+ s3_wait_fifo_idle(s3);
+ return s3->accel.frgd_color & 0xff;
+ case 0xa6e9:
+ s3_wait_fifo_idle(s3);
+ return s3->accel.frgd_color >> 8;
+ case 0xa6ea:
+ s3_wait_fifo_idle(s3);
+ return s3->accel.frgd_color >> 16;
+ case 0xa6eb:
+ s3_wait_fifo_idle(s3);
+ return s3->accel.frgd_color >> 24;
+
+ case 0xaae8:
+ s3_wait_fifo_idle(s3);
+ return s3->accel.wrt_mask & 0xff;
+ case 0xaae9:
+ s3_wait_fifo_idle(s3);
+ return s3->accel.wrt_mask >> 8;
+ case 0xaaea:
+ s3_wait_fifo_idle(s3);
+ return s3->accel.wrt_mask >> 16;
+ case 0xaaeb:
+ s3_wait_fifo_idle(s3);
+ return s3->accel.wrt_mask >> 24;
+
+ case 0xaee8:
+ s3_wait_fifo_idle(s3);
+ return s3->accel.rd_mask & 0xff;
+ case 0xaee9:
+ s3_wait_fifo_idle(s3);
+ return s3->accel.rd_mask >> 8;
+ case 0xaeea:
+ s3_wait_fifo_idle(s3);
+ return s3->accel.rd_mask >> 16;
+ case 0xaeeb:
+ s3_wait_fifo_idle(s3);
+ return s3->accel.rd_mask >> 24;
+
+ case 0xb2e8:
+ s3_wait_fifo_idle(s3);
+ return s3->accel.color_cmp & 0xff;
+ case 0xb2e9:
+ s3_wait_fifo_idle(s3);
+ return s3->accel.color_cmp >> 8;
+ case 0xb2ea:
+ s3_wait_fifo_idle(s3);
+ return s3->accel.color_cmp >> 16;
+ case 0xb2eb:
+ s3_wait_fifo_idle(s3);
+ return s3->accel.color_cmp >> 24;
+
+ case 0xb6e8:
+ s3_wait_fifo_idle(s3);
+ return s3->accel.bkgd_mix;
+
+ case 0xbae8:
+ s3_wait_fifo_idle(s3);
+ return s3->accel.frgd_mix;
+
+ case 0xbee8:
+ s3_wait_fifo_idle(s3);
+ temp = s3->accel.multifunc[0xf] & 0xf;
+ switch (temp)
+ {
+ case 0x0: return s3->accel.multifunc[0x0] & 0xff;
+ case 0x1: return s3->accel.multifunc[0x1] & 0xff;
+ case 0x2: return s3->accel.multifunc[0x2] & 0xff;
+ case 0x3: return s3->accel.multifunc[0x3] & 0xff;
+ case 0x4: return s3->accel.multifunc[0x4] & 0xff;
+ case 0x5: return s3->accel.multifunc[0xa] & 0xff;
+ case 0x6: return s3->accel.multifunc[0xe] & 0xff;
+ case 0x7: return s3->accel.cmd & 0xff;
+ case 0x8: return s3->accel.subsys_cntl & 0xff;
+ case 0x9: return s3->accel.setup_md & 0xff;
+ case 0xa: return s3->accel.multifunc[0xd] & 0xff;
+ }
+ return 0xff;
+ case 0xbee9:
+ s3_wait_fifo_idle(s3);
+ temp = s3->accel.multifunc[0xf] & 0xf;
+ s3->accel.multifunc[0xf]++;
+ switch (temp)
+ {
+ case 0x0: return s3->accel.multifunc[0x0] >> 8;
+ case 0x1: return s3->accel.multifunc[0x1] >> 8;
+ case 0x2: return s3->accel.multifunc[0x2] >> 8;
+ case 0x3: return s3->accel.multifunc[0x3] >> 8;
+ case 0x4: return s3->accel.multifunc[0x4] >> 8;
+ case 0x5: return s3->accel.multifunc[0xa] >> 8;
+ case 0x6: return s3->accel.multifunc[0xe] >> 8;
+ case 0x7: return s3->accel.cmd >> 8;
+ case 0x8: return (s3->accel.subsys_cntl >> 8) & ~0xe000;
+ case 0x9: return (s3->accel.setup_md >> 8) & ~0xf000;
+ case 0xa: return s3->accel.multifunc[0xd] >> 8;
+ }
+ return 0xff;
+
+ case 0xe2e8: case 0xe2e9: case 0xe2ea: case 0xe2eb: /*PIX_TRANS*/
+ break;
+ }
+ return 0;
+}
+
+void s3_accel_write(uint32_t addr, uint8_t val, void *p)
+{
+ s3_t *s3 = (s3_t *)p;
+// pclog("s3_accel_write %08x %02x\n", addr, val);
+ s3_queue(s3, addr & 0xffff, val, FIFO_WRITE_BYTE);
+}
+void s3_accel_write_w(uint32_t addr, uint16_t val, void *p)
+{
+ s3_t *s3 = (s3_t *)p;
+// pclog("s3_accel_write_w %08x %04x\n", addr, val);
+ s3_queue(s3, addr & 0xffff, val, FIFO_WRITE_WORD);
+}
+void s3_accel_write_l(uint32_t addr, uint32_t val, void *p)
+{
+ s3_t *s3 = (s3_t *)p;
+// pclog("s3_accel_write_l %08x %08x\n", addr, val);
+ s3_queue(s3, addr & 0xffff, val, FIFO_WRITE_DWORD);
+}
+
+uint8_t s3_accel_read(uint32_t addr, void *p)
+{
+ if (addr & 0x8000)
+ return s3_accel_in(addr & 0xffff, p);
+ return 0;
+}
+
+static void polygon_setup(s3_t *s3)
+{
+ if (s3->accel.point_1_updated)
+ {
+ int start_x = s3->accel.poly_cx;
+ int start_y = s3->accel.poly_cy;
+ int end_x = s3->accel.destx_distp << 20;
+ int end_y = s3->accel.desty_axstp;
+
+ if (end_y - start_y)
+ s3->accel.poly_dx1 = (end_x - start_x) / (end_y - start_y);
+ else
+ s3->accel.poly_dx1 = 0;
+
+ s3->accel.point_1_updated = 0;
+
+ if (end_y == s3->accel.poly_cy)
+ {
+ s3->accel.poly_cx = end_x;
+ s3->accel.poly_x = end_x >> 20;
+ }
+ }
+ if (s3->accel.point_2_updated)
+ {
+ int start_x = s3->accel.poly_cx2;
+ int start_y = s3->accel.poly_cy2;
+ int end_x = s3->accel.x2 << 20;
+ int end_y = s3->accel.desty_axstp2;
+
+ if (end_y - start_y)
+ s3->accel.poly_dx2 = (end_x - start_x) / (end_y - start_y);
+ else
+ s3->accel.poly_dx2 = 0;
+
+ s3->accel.point_2_updated = 0;
+
+ if (end_y == s3->accel.poly_cy)
+ s3->accel.poly_cx2 = end_x;
+ }
+}
+
+#define READ_SRC(addr, dat) if (s3->bpp == 0) dat = svga->vram[ (addr) & s3->vram_mask]; \
+ else if (s3->bpp == 1) dat = vram_w[(addr) & (s3->vram_mask >> 1)]; \
+ else dat = vram_l[(addr) & (s3->vram_mask >> 2)]; \
+ if (vram_mask) \
+ dat = ((dat & rd_mask) == rd_mask);
+
+#define READ_DST(addr, dat) if (s3->bpp == 0) dat = svga->vram[ (addr) & s3->vram_mask]; \
+ else if (s3->bpp == 1) dat = vram_w[(addr) & (s3->vram_mask >> 1)]; \
+ else dat = vram_l[(addr) & (s3->vram_mask >> 2)];
+
+#define MIX { \
+ uint32_t old_dest_dat = dest_dat; \
+ switch ((mix_dat & mix_mask) ? (s3->accel.frgd_mix & 0xf) : (s3->accel.bkgd_mix & 0xf)) \
+ { \
+ case 0x0: dest_dat = ~dest_dat; break; \
+ case 0x1: dest_dat = 0; break; \
+ case 0x2: dest_dat = ~0; break; \
+ case 0x3: dest_dat = dest_dat; break; \
+ case 0x4: dest_dat = ~src_dat; break; \
+ case 0x5: dest_dat = src_dat ^ dest_dat; break; \
+ case 0x6: dest_dat = ~(src_dat ^ dest_dat); break; \
+ case 0x7: dest_dat = src_dat; break; \
+ case 0x8: dest_dat = ~(src_dat & dest_dat); break; \
+ case 0x9: dest_dat = ~src_dat | dest_dat; break; \
+ case 0xa: dest_dat = src_dat | ~dest_dat; break; \
+ case 0xb: dest_dat = src_dat | dest_dat; break; \
+ case 0xc: dest_dat = src_dat & dest_dat; break; \
+ case 0xd: dest_dat = src_dat & ~dest_dat; break; \
+ case 0xe: dest_dat = ~src_dat & dest_dat; break; \
+ case 0xf: dest_dat = ~(src_dat | dest_dat); break; \
+ } \
+ dest_dat = (dest_dat & s3->accel.wrt_mask) | (old_dest_dat & ~s3->accel.wrt_mask); \
+ }
+
+
+#define WRITE(addr) if (s3->bpp == 0) \
+ { \
+ svga->vram[(addr) & s3->vram_mask] = dest_dat; \
+ svga->changedvram[((addr) & s3->vram_mask) >> 12] = changeframecount; \
+ } \
+ else if (s3->bpp == 1) \
+ { \
+ vram_w[(addr) & (s3->vram_mask >> 1)] = dest_dat; \
+ svga->changedvram[((addr) & (s3->vram_mask >> 1)) >> 11] = changeframecount; \
+ } \
+ else \
+ { \
+ vram_l[(addr) & (s3->vram_mask >> 2)] = dest_dat; \
+ svga->changedvram[((addr) & (s3->vram_mask >> 2)) >> 10] = changeframecount; \
+ }
+
+void s3_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat, s3_t *s3)
+{
+ svga_t *svga = &s3->svga;
+ uint32_t src_dat, dest_dat;
+ int frgd_mix, bkgd_mix;
+ int clip_t = s3->accel.multifunc[1] & 0xfff;
+ int clip_l = s3->accel.multifunc[2] & 0xfff;
+ int clip_b = s3->accel.multifunc[3] & 0xfff;
+ int clip_r = s3->accel.multifunc[4] & 0xfff;
+ int vram_mask = (s3->accel.multifunc[0xa] & 0xc0) == 0xc0;
+ uint32_t mix_mask = 0;
+ uint16_t *vram_w = (uint16_t *)svga->vram;
+ uint32_t *vram_l = (uint32_t *)svga->vram;
+ uint32_t compare = s3->accel.color_cmp;
+ int compare_mode = (s3->accel.multifunc[0xe] >> 7) & 3;
+ uint32_t rd_mask = s3->accel.rd_mask;
+ int cmd = s3->accel.cmd >> 13;
+
+ if ((s3->chip == S3_TRIO64) && (s3->accel.cmd & (1 << 11)))
+ cmd |= 8;
+
+ s3->force_busy = 1;
+//return;
+// if (!cpu_input) pclog("Start S3 command %i %i, %i %i, %i (clip %i, %i to %i, %i %i)\n", s3->accel.cmd >> 13, s3->accel.cur_x, s3->accel.cur_y, s3->accel.maj_axis_pcnt & 0xfff, s3->accel.multifunc[0] & 0xfff, clip_l, clip_t, clip_r, clip_b, s3->accel.multifunc[0xe] & 0x20);
+// else pclog(" S3 command %i, %i, %08x %08x\n", s3->accel.cmd >> 13, count, mix_dat, cpu_dat);
+
+ if (!cpu_input) s3->accel.dat_count = 0;
+ if (cpu_input && (s3->accel.multifunc[0xa] & 0xc0) != 0x80)
+ {
+ if (s3->bpp == 3 && count == 2)
+ {
+ if (s3->accel.dat_count)
+ {
+ cpu_dat = ((cpu_dat & 0xffff) << 16) | s3->accel.dat_buf;
+ count = 4;
+ s3->accel.dat_count = 0;
+ }
+ else
+ {
+ s3->accel.dat_buf = cpu_dat & 0xffff;
+ s3->accel.dat_count = 1;
+ }
+ }
+ if (s3->bpp == 1) count >>= 1;
+ if (s3->bpp == 3) count >>= 2;
+ }
+
+ if (s3->bpp == 0)
+ rd_mask &= 0xff;
+ else if (s3->bpp == 1)
+ rd_mask &= 0xffff;
+
+ switch (s3->accel.cmd & 0x600)
+ {
+ case 0x000: mix_mask = 0x80; break;
+ case 0x200: mix_mask = 0x8000; break;
+ case 0x400: mix_mask = 0x80000000; break;
+ case 0x600: mix_mask = (s3->chip == S3_TRIO32) ? 0x80 : 0x80000000; break;
+ }
+
+ if (s3->bpp == 0) compare &= 0xff;
+ if (s3->bpp == 1) compare &= 0xffff;
+ switch (cmd)
+ {
+ case 1: /*Draw line*/
+ if (!cpu_input) /*!cpu_input is trigger to start operation*/
+ {
+ s3->accel.cx = s3->accel.cur_x;
+ if (s3->accel.cur_x & 0x1000) s3->accel.cx |= ~0xfff;
+ s3->accel.cy = s3->accel.cur_y;
+ if (s3->accel.cur_y & 0x1000) s3->accel.cy |= ~0xfff;
+
+ s3->accel.sy = s3->accel.maj_axis_pcnt;
+ }
+ if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/
+
+ frgd_mix = (s3->accel.frgd_mix >> 5) & 3;
+ bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3;
+
+ if (s3->accel.cmd & 8) /*Radial*/
+ {
+ while (count-- && s3->accel.sy >= 0)
+ {
+ if (s3->accel.cx >= clip_l && s3->accel.cx <= clip_r &&
+ s3->accel.cy >= clip_t && s3->accel.cy <= clip_b)
+ {
+ switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix)
+ {
+ case 0: src_dat = s3->accel.bkgd_color; break;
+ case 1: src_dat = s3->accel.frgd_color; break;
+ case 2: src_dat = cpu_dat; break;
+ case 3: src_dat = 0; break;
+ }
+
+ if ((compare_mode == 2 && src_dat != compare) ||
+ (compare_mode == 3 && src_dat == compare) ||
+ compare_mode < 2)
+ {
+ READ_DST((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat);
+
+ MIX
+
+ WRITE((s3->accel.cy * s3->width) + s3->accel.cx);
+ }
+ }
+
+ mix_dat <<= 1;
+ mix_dat |= 1;
+ if (s3->bpp == 0) cpu_dat >>= 8;
+ else cpu_dat >>= 16;
+ if (!s3->accel.sy)
+ break;
+
+ switch (s3->accel.cmd & 0xe0)
+ {
+ case 0x00: s3->accel.cx++; break;
+ case 0x20: s3->accel.cx++; s3->accel.cy--; break;
+ case 0x40: s3->accel.cy--; break;
+ case 0x60: s3->accel.cx--; s3->accel.cy--; break;
+ case 0x80: s3->accel.cx--; break;
+ case 0xa0: s3->accel.cx--; s3->accel.cy++; break;
+ case 0xc0: s3->accel.cy++; break;
+ case 0xe0: s3->accel.cx++; s3->accel.cy++; break;
+ }
+ s3->accel.sy--;
+ }
+ s3->accel.cur_x = s3->accel.cx;
+ s3->accel.cur_y = s3->accel.cy;
+ }
+ else /*Bresenham*/
+ {
+ while (count-- && s3->accel.sy >= 0)
+ {
+ if (s3->accel.cx >= clip_l && s3->accel.cx <= clip_r &&
+ s3->accel.cy >= clip_t && s3->accel.cy <= clip_b)
+ {
+ switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix)
+ {
+ case 0: src_dat = s3->accel.bkgd_color; break;
+ case 1: src_dat = s3->accel.frgd_color; break;
+ case 2: src_dat = cpu_dat; break;
+ case 3: src_dat = 0; break;
+ }
+
+ if ((compare_mode == 2 && src_dat != compare) ||
+ (compare_mode == 3 && src_dat == compare) ||
+ compare_mode < 2)
+ {
+ READ_DST((s3->accel.cy * s3->width) + s3->accel.cx, dest_dat);
+
+// pclog("Line : %04i, %04i (%06X) - %02X (%02X %04X %05X) %02X (%02X %02X) ", s3->accel.cx, s3->accel.cy, s3->accel.dest + s3->accel.cx, src_dat, vram[s3->accel.src + s3->accel.cx], mix_dat & mix_mask, s3->accel.src + s3->accel.cx, dest_dat, s3->accel.frgd_color, s3->accel.bkgd_color);
+
+ MIX
+
+// pclog("%02X\n", dest_dat);
+
+ WRITE((s3->accel.cy * s3->width) + s3->accel.cx);
+ }
+ }
+
+ mix_dat <<= 1;
+ mix_dat |= 1;
+ if (s3->bpp == 0) cpu_dat >>= 8;
+ else cpu_dat >>= 16;
+
+// pclog("%i, %i - %i %i %i %i\n", s3->accel.cx, s3->accel.cy, s3->accel.err_term, s3->accel.maj_axis_pcnt, s3->accel.desty_axstp, s3->accel.destx_distp);
+
+ if (!s3->accel.sy)
+ break;
+
+ if (s3->accel.err_term >= s3->accel.maj_axis_pcnt)
+ {
+ s3->accel.err_term += s3->accel.destx_distp;
+ /*Step minor axis*/
+ switch (s3->accel.cmd & 0xe0)
+ {
+ case 0x00: s3->accel.cy--; break;
+ case 0x20: s3->accel.cy--; break;
+ case 0x40: s3->accel.cx--; break;
+ case 0x60: s3->accel.cx++; break;
+ case 0x80: s3->accel.cy++; break;
+ case 0xa0: s3->accel.cy++; break;
+ case 0xc0: s3->accel.cx--; break;
+ case 0xe0: s3->accel.cx++; break;
+ }
+ }
+ else
+ s3->accel.err_term += s3->accel.desty_axstp;
+
+ /*Step major axis*/
+ switch (s3->accel.cmd & 0xe0)
+ {
+ case 0x00: s3->accel.cx--; break;
+ case 0x20: s3->accel.cx++; break;
+ case 0x40: s3->accel.cy--; break;
+ case 0x60: s3->accel.cy--; break;
+ case 0x80: s3->accel.cx--; break;
+ case 0xa0: s3->accel.cx++; break;
+ case 0xc0: s3->accel.cy++; break;
+ case 0xe0: s3->accel.cy++; break;
+ }
+ s3->accel.sy--;
+ }
+ s3->accel.cur_x = s3->accel.cx;
+ s3->accel.cur_y = s3->accel.cy;
+ }
+ break;
+
+ case 2: /*Rectangle fill*/
+ if (!cpu_input) /*!cpu_input is trigger to start operation*/
+ {
+ s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff;
+ s3->accel.sy = s3->accel.multifunc[0] & 0xfff;
+ s3->accel.cx = s3->accel.cur_x;
+ if (s3->accel.cur_x & 0x1000) s3->accel.cx |= ~0xfff;
+ s3->accel.cy = s3->accel.cur_y;
+ if (s3->accel.cur_y & 0x1000) s3->accel.cy |= ~0xfff;
+
+ s3->accel.dest = s3->accel.cy * s3->width;
+
+// pclog("Dest %08X (%i, %i) %04X %04X\n", s3->accel.dest, s3->accel.cx, s3->accel.cy, s3->accel.cur_x, s3->accel.cur_x & 0x1000);
+ }
+ if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/
+// if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && !cpu_input) /*Mix data from CPU*/
+// return;
+
+ frgd_mix = (s3->accel.frgd_mix >> 5) & 3;
+ bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3;
+
+ while (count-- && s3->accel.sy >= 0)
+ {
+ if (s3->accel.cx >= clip_l && s3->accel.cx <= clip_r &&
+ s3->accel.cy >= clip_t && s3->accel.cy <= clip_b)
+ {
+ switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix)
+ {
+ case 0: src_dat = s3->accel.bkgd_color; break;
+ case 1: src_dat = s3->accel.frgd_color; break;
+ case 2: src_dat = cpu_dat; break;
+ case 3: src_dat = 0; break;
+ }
+
+ if ((compare_mode == 2 && src_dat != compare) ||
+ (compare_mode == 3 && src_dat == compare) ||
+ compare_mode < 2)
+ {
+ READ_DST(s3->accel.dest + s3->accel.cx, dest_dat);
+
+
+// if (CS != 0xc000) pclog("Write %05X %02X %02X %04X (%02X %02X) ", s3->accel.dest + s3->accel.cx, src_dat, dest_dat, mix_dat, s3->accel.frgd_mix, s3->accel.bkgd_mix);
+
+ MIX
+
+// if (CS != 0xc000) pclog("%02X\n", dest_dat);
+
+ WRITE(s3->accel.dest + s3->accel.cx);
+ }
+ }
+
+ mix_dat <<= 1;
+ mix_dat |= 1;
+ if (s3->bpp == 0) cpu_dat >>= 8;
+ else cpu_dat >>= 16;
+
+ if (s3->accel.cmd & 0x20) s3->accel.cx++;
+ else s3->accel.cx--;
+ s3->accel.sx--;
+ if (s3->accel.sx < 0)
+ {
+ if (s3->accel.cmd & 0x20) s3->accel.cx -= (s3->accel.maj_axis_pcnt & 0xfff) + 1;
+ else s3->accel.cx += (s3->accel.maj_axis_pcnt & 0xfff) + 1;
+// s3->accel.dest -= (s3->accel.maj_axis_pcnt & 0xfff) + 1;
+ s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff;
+
+// s3->accel.dest += s3_width;
+ if (s3->accel.cmd & 0x80) s3->accel.cy++;
+ else s3->accel.cy--;
+
+ s3->accel.dest = s3->accel.cy * s3->width;
+ s3->accel.sy--;
+
+ if (cpu_input/* && (s3->accel.multifunc[0xa] & 0xc0) == 0x80*/) return;
+ if (s3->accel.sy < 0)
+ {
+ s3->accel.cur_x = s3->accel.cx;
+ s3->accel.cur_y = s3->accel.cy;
+ return;
+ }
+ }
+ }
+ break;
+
+ case 6: /*BitBlt*/
+ if (!cpu_input) /*!cpu_input is trigger to start operation*/
+ {
+ s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff;
+ s3->accel.sy = s3->accel.multifunc[0] & 0xfff;
+
+ s3->accel.dx = s3->accel.destx_distp & 0xfff;
+ if (s3->accel.destx_distp & 0x1000) s3->accel.dx |= ~0xfff;
+ s3->accel.dy = s3->accel.desty_axstp & 0xfff;
+ if (s3->accel.desty_axstp & 0x1000) s3->accel.dy |= ~0xfff;
+
+ s3->accel.cx = s3->accel.cur_x & 0xfff;
+ if (s3->accel.cur_x & 0x1000) s3->accel.cx |= ~0xfff;
+ s3->accel.cy = s3->accel.cur_y & 0xfff;
+ if (s3->accel.cur_y & 0x1000) s3->accel.cy |= ~0xfff;
+
+ s3->accel.src = s3->accel.cy * s3->width;
+ s3->accel.dest = s3->accel.dy * s3->width;
+
+// pclog("Source %08X Dest %08X (%i, %i) - (%i, %i)\n", s3->accel.src, s3->accel.dest, s3->accel.cx, s3->accel.cy, s3->accel.dx, s3->accel.dy);
+ }
+ if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/
+// if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && !cpu_input) /*Mix data from CPU*/
+// return;
+
+ if (s3->accel.sy < 0)
+ return;
+
+ frgd_mix = (s3->accel.frgd_mix >> 5) & 3;
+ bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3;
+
+ if (!cpu_input && frgd_mix == 3 && !vram_mask && !compare_mode &&
+ (s3->accel.cmd & 0xa0) == 0xa0 && (s3->accel.frgd_mix & 0xf) == 7)
+ {
+ while (1)
+ {
+ if (s3->accel.dx >= clip_l && s3->accel.dx <= clip_r &&
+ s3->accel.dy >= clip_t && s3->accel.dy <= clip_b)
+ {
+ READ_SRC(s3->accel.src + s3->accel.cx, src_dat);
+ READ_DST(s3->accel.dest + s3->accel.dx, dest_dat);
+
+ dest_dat = (src_dat & s3->accel.wrt_mask) | (dest_dat & ~s3->accel.wrt_mask);
+
+ WRITE(s3->accel.dest + s3->accel.dx);
+ }
+
+ s3->accel.cx++;
+ s3->accel.dx++;
+ s3->accel.sx--;
+ if (s3->accel.sx < 0)
+ {
+ s3->accel.cx -= (s3->accel.maj_axis_pcnt & 0xfff) + 1;
+ s3->accel.dx -= (s3->accel.maj_axis_pcnt & 0xfff) + 1;
+ s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff;
+
+ s3->accel.cy++;
+ s3->accel.dy++;
+
+ s3->accel.src = s3->accel.cy * s3->width;
+ s3->accel.dest = s3->accel.dy * s3->width;
+
+ s3->accel.sy--;
+
+ if (s3->accel.sy < 0)
+ return;
+ }
+ }
+ }
+ else
+ {
+ while (count-- && s3->accel.sy >= 0)
+ {
+ if (s3->accel.dx >= clip_l && s3->accel.dx <= clip_r &&
+ s3->accel.dy >= clip_t && s3->accel.dy <= clip_b)
+ {
+ if (vram_mask)
+ {
+ READ_SRC(s3->accel.src + s3->accel.cx, mix_dat)
+
+ mix_dat = mix_dat ? mix_mask : 0;
+ }
+ switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix)
+ {
+ case 0: src_dat = s3->accel.bkgd_color; break;
+ case 1: src_dat = s3->accel.frgd_color; break;
+ case 2: src_dat = cpu_dat; break;
+ case 3: READ_SRC(s3->accel.src + s3->accel.cx, src_dat); break;
+ }
+
+ if ((compare_mode == 2 && src_dat != compare) ||
+ (compare_mode == 3 && src_dat == compare) ||
+ compare_mode < 2)
+ {
+ READ_DST(s3->accel.dest + s3->accel.dx, dest_dat);
+
+// pclog("BitBlt : %04i, %04i (%06X) - %02X (%02X %04X %05X) %02X ", s3->accel.dx, s3->accel.dy, s3->accel.dest + s3->accel.dx, src_dat, vram[s3->accel.src + s3->accel.cx], mix_dat, s3->accel.src + s3->accel.cx, dest_dat);
+
+ MIX
+
+// pclog("%02X\n", dest_dat);
+
+ WRITE(s3->accel.dest + s3->accel.dx);
+ }
+ }
+
+ mix_dat <<= 1;
+ mix_dat |= 1;
+ if (s3->bpp == 0) cpu_dat >>= 8;
+ else cpu_dat >>= 16;
+
+ if (s3->accel.cmd & 0x20)
+ {
+ s3->accel.cx++;
+ s3->accel.dx++;
+ }
+ else
+ {
+ s3->accel.cx--;
+ s3->accel.dx--;
+ }
+ s3->accel.sx--;
+ if (s3->accel.sx < 0)
+ {
+ if (s3->accel.cmd & 0x20)
+ {
+ s3->accel.cx -= (s3->accel.maj_axis_pcnt & 0xfff) + 1;
+ s3->accel.dx -= (s3->accel.maj_axis_pcnt & 0xfff) + 1;
+ }
+ else
+ {
+ s3->accel.cx += (s3->accel.maj_axis_pcnt & 0xfff) + 1;
+ s3->accel.dx += (s3->accel.maj_axis_pcnt & 0xfff) + 1;
+ }
+ s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff;
+
+ if (s3->accel.cmd & 0x80)
+ {
+ s3->accel.cy++;
+ s3->accel.dy++;
+ }
+ else
+ {
+ s3->accel.cy--;
+ s3->accel.dy--;
+ }
+
+ s3->accel.src = s3->accel.cy * s3->width;
+ s3->accel.dest = s3->accel.dy * s3->width;
+
+ s3->accel.sy--;
+
+ if (cpu_input/* && (s3->accel.multifunc[0xa] & 0xc0) == 0x80*/) return;
+ if (s3->accel.sy < 0)
+ return;
+ }
+ }
+ }
+ break;
+
+ case 7: /*Pattern fill - BitBlt but with source limited to 8x8*/
+ if (!cpu_input) /*!cpu_input is trigger to start operation*/
+ {
+ s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff;
+ s3->accel.sy = s3->accel.multifunc[0] & 0xfff;
+
+ s3->accel.dx = s3->accel.destx_distp & 0xfff;
+ if (s3->accel.destx_distp & 0x1000) s3->accel.dx |= ~0xfff;
+ s3->accel.dy = s3->accel.desty_axstp & 0xfff;
+ if (s3->accel.desty_axstp & 0x1000) s3->accel.dy |= ~0xfff;
+
+ s3->accel.cx = s3->accel.cur_x & 0xfff;
+ if (s3->accel.cur_x & 0x1000) s3->accel.cx |= ~0xfff;
+ s3->accel.cy = s3->accel.cur_y & 0xfff;
+ if (s3->accel.cur_y & 0x1000) s3->accel.cy |= ~0xfff;
+
+ /*Align source with destination*/
+// s3->accel.cx = (s3->accel.cx & ~7) | (s3->accel.dx & 7);
+// s3->accel.cy = (s3->accel.cy & ~7) | (s3->accel.dy & 7);
+
+ s3->accel.pattern = (s3->accel.cy * s3->width) + s3->accel.cx;
+ s3->accel.dest = s3->accel.dy * s3->width;
+
+ s3->accel.cx = s3->accel.dx & 7;
+ s3->accel.cy = s3->accel.dy & 7;
+
+ s3->accel.src = s3->accel.pattern + (s3->accel.cy * s3->width);
+
+// pclog("Source %08X Dest %08X (%i, %i) - (%i, %i)\n", s3->accel.src, s3->accel.dest, s3->accel.cx, s3->accel.cy, s3->accel.dx, s3->accel.dy);
+// dumpregs();
+// exit(-1);
+ }
+ if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/
+// if ((s3->accel.multifunc[0xa] & 0xc0) == 0x80 && !cpu_input) /*Mix data from CPU*/
+// return;
+
+ frgd_mix = (s3->accel.frgd_mix >> 5) & 3;
+ bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3;
+
+ while (count-- && s3->accel.sy >= 0)
+ {
+ if (s3->accel.dx >= clip_l && s3->accel.dx <= clip_r &&
+ s3->accel.dy >= clip_t && s3->accel.dy <= clip_b)
+ {
+ if (vram_mask)
+ {
+ READ_SRC(s3->accel.src + s3->accel.cx, mix_dat)
+ mix_dat = mix_dat ? mix_mask : 0;
+ }
+ switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix)
+ {
+ case 0: src_dat = s3->accel.bkgd_color; break;
+ case 1: src_dat = s3->accel.frgd_color; break;
+ case 2: src_dat = cpu_dat; break;
+ case 3: READ_SRC(s3->accel.src + s3->accel.cx, src_dat); break;
+ }
+
+ if ((compare_mode == 2 && src_dat != compare) ||
+ (compare_mode == 3 && src_dat == compare) ||
+ compare_mode < 2)
+ {
+ READ_DST(s3->accel.dest + s3->accel.dx, dest_dat);
+
+// pclog("Pattern fill : %04i, %04i (%06X) - %02X (%02X %04X %05X) %02X ", s3->accel.dx, s3->accel.dy, s3->accel.dest + s3->accel.dx, src_dat, vram[s3->accel.src + s3->accel.cx], mix_dat, s3->accel.src + s3->accel.cx, dest_dat);
+
+ MIX
+
+// pclog("%02X\n", dest_dat);
+
+ WRITE(s3->accel.dest + s3->accel.dx);
+ }
+ }
+
+ mix_dat <<= 1;
+ mix_dat |= 1;
+ if (s3->bpp == 0) cpu_dat >>= 8;
+ else cpu_dat >>= 16;
+
+ if (s3->accel.cmd & 0x20)
+ {
+ s3->accel.cx = ((s3->accel.cx + 1) & 7) | (s3->accel.cx & ~7);
+ s3->accel.dx++;
+ }
+ else
+ {
+ s3->accel.cx = ((s3->accel.cx - 1) & 7) | (s3->accel.cx & ~7);
+ s3->accel.dx--;
+ }
+ s3->accel.sx--;
+ if (s3->accel.sx < 0)
+ {
+ if (s3->accel.cmd & 0x20)
+ {
+ s3->accel.cx = ((s3->accel.cx - ((s3->accel.maj_axis_pcnt & 0xfff) + 1)) & 7) | (s3->accel.cx & ~7);
+ s3->accel.dx -= (s3->accel.maj_axis_pcnt & 0xfff) + 1;
+ }
+ else
+ {
+ s3->accel.cx = ((s3->accel.cx + ((s3->accel.maj_axis_pcnt & 0xfff) + 1)) & 7) | (s3->accel.cx & ~7);
+ s3->accel.dx += (s3->accel.maj_axis_pcnt & 0xfff) + 1;
+ }
+ s3->accel.sx = s3->accel.maj_axis_pcnt & 0xfff;
+
+ if (s3->accel.cmd & 0x80)
+ {
+ s3->accel.cy = ((s3->accel.cy + 1) & 7) | (s3->accel.cy & ~7);
+ s3->accel.dy++;
+ }
+ else
+ {
+ s3->accel.cy = ((s3->accel.cy - 1) & 7) | (s3->accel.cy & ~7);
+ s3->accel.dy--;
+ }
+
+ s3->accel.src = s3->accel.pattern + (s3->accel.cy * s3->width);
+ s3->accel.dest = s3->accel.dy * s3->width;
+
+ s3->accel.sy--;
+
+ if (cpu_input/* && (s3->accel.multifunc[0xa] & 0xc0) == 0x80*/) return;
+ if (s3->accel.sy < 0)
+ return;
+ }
+ }
+ break;
+
+ case 3: /*Polygon Fill Solid (Trio64 only)*/
+ {
+ int end_y1, end_y2;
+
+ if (s3->chip != S3_TRIO64)
+ break;
+
+ polygon_setup(s3);
+
+ if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/
+
+ end_y1 = s3->accel.desty_axstp;
+ end_y2 = s3->accel.desty_axstp2;
+
+ frgd_mix = (s3->accel.frgd_mix >> 5) & 3;
+
+
+ while ((s3->accel.poly_cy < end_y1) && (s3->accel.poly_cy2 < end_y2))
+ {
+ int y = s3->accel.poly_cy;
+ int x_count = ABS((s3->accel.poly_cx2 >> 20) - s3->accel.poly_x) + 1;
+
+ s3->accel.dest = y * s3->width;
+
+ while (x_count-- && count--)
+ {
+ if (s3->accel.poly_x >= clip_l && s3->accel.poly_x <= clip_r &&
+ s3->accel.poly_cy >= clip_t && s3->accel.poly_cy <= clip_b)
+ {
+ switch (frgd_mix)
+ {
+ case 0: src_dat = s3->accel.bkgd_color; break;
+ case 1: src_dat = s3->accel.frgd_color; break;
+ case 2: src_dat = cpu_dat; break;
+ case 3: src_dat = 0; /*Nor supported?*/ break;
+ }
+
+ if ((compare_mode == 2 && src_dat != compare) ||
+ (compare_mode == 3 && src_dat == compare) ||
+ compare_mode < 2)
+ {
+ READ_DST(s3->accel.dest + s3->accel.poly_x, dest_dat);
+
+ MIX
+
+ WRITE(s3->accel.dest + s3->accel.poly_x);
+ }
+ }
+ if (s3->bpp == 0) cpu_dat >>= 8;
+ else cpu_dat >>= 16;
+
+ if (s3->accel.poly_x < (s3->accel.poly_cx2 >> 20))
+ s3->accel.poly_x++;
+ else
+ s3->accel.poly_x--;
+ }
+
+ s3->accel.poly_cx += s3->accel.poly_dx1;
+ s3->accel.poly_cx2 += s3->accel.poly_dx2;
+ s3->accel.poly_x = s3->accel.poly_cx >> 20;
+
+ s3->accel.poly_cy++;
+ s3->accel.poly_cy2++;
+
+ if (!count)
+ break;
+ }
+
+ s3->accel.cur_x = s3->accel.poly_cx & 0xfff;
+ s3->accel.cur_y = s3->accel.poly_cy & 0xfff;
+ s3->accel.cur_x2 = s3->accel.poly_cx2 & 0xfff;
+ s3->accel.cur_y2 = s3->accel.poly_cy & 0xfff;
+ }
+ break;
+
+ case 11: /*Polygon Fill Pattern (Trio64 only)*/
+ {
+ int end_y1, end_y2;
+
+ if (s3->chip != S3_TRIO64)
+ break;
+
+ polygon_setup(s3);
+
+ if ((s3->accel.cmd & 0x100) && !cpu_input) return; /*Wait for data from CPU*/
+
+ end_y1 = s3->accel.desty_axstp;
+ end_y2 = s3->accel.desty_axstp2;
+
+ frgd_mix = (s3->accel.frgd_mix >> 5) & 3;
+ bkgd_mix = (s3->accel.bkgd_mix >> 5) & 3;
+
+ while ((s3->accel.poly_cy < end_y1) && (s3->accel.poly_cy2 < end_y2))
+ {
+ int y = s3->accel.poly_cy;
+ int x_count = ABS((s3->accel.poly_cx2 >> 20) - s3->accel.poly_x) + 1;
+
+ s3->accel.src = s3->accel.pattern + ((y & 7) * s3->width);
+ s3->accel.dest = y * s3->width;
+
+ while (x_count-- && count--)
+ {
+ int pat_x = s3->accel.poly_x & 7;
+
+ if (s3->accel.poly_x >= clip_l && s3->accel.poly_x <= clip_r &&
+ s3->accel.poly_cy >= clip_t && s3->accel.poly_cy <= clip_b)
+ {
+ if (vram_mask)
+ {
+ READ_SRC(s3->accel.src + pat_x, mix_dat)
+ mix_dat = mix_dat ? mix_mask : 0;
+ }
+ switch ((mix_dat & mix_mask) ? frgd_mix : bkgd_mix)
+ {
+ case 0: src_dat = s3->accel.bkgd_color; break;
+ case 1: src_dat = s3->accel.frgd_color; break;
+ case 2: src_dat = cpu_dat; break;
+ case 3: READ_SRC(s3->accel.src + pat_x, src_dat); break;
+ }
+
+ if ((compare_mode == 2 && src_dat != compare) ||
+ (compare_mode == 3 && src_dat == compare) ||
+ compare_mode < 2)
+ {
+ READ_DST(s3->accel.dest + s3->accel.poly_x, dest_dat);
+
+ MIX
+
+ WRITE(s3->accel.dest + s3->accel.poly_x);
+ }
+ }
+ if (s3->bpp == 0) cpu_dat >>= 8;
+ else cpu_dat >>= 16;
+
+ mix_dat <<= 1;
+ mix_dat |= 1;
+
+ if (s3->accel.poly_x < (s3->accel.poly_cx2 >> 20))
+ s3->accel.poly_x++;
+ else
+ s3->accel.poly_x--;
+ }
+
+ s3->accel.poly_cx += s3->accel.poly_dx1;
+ s3->accel.poly_cx2 += s3->accel.poly_dx2;
+ s3->accel.poly_x = s3->accel.poly_cx >> 20;
+
+ s3->accel.poly_cy++;
+ s3->accel.poly_cy2++;
+
+ if (!count)
+ break;
+ }
+
+ s3->accel.cur_x = s3->accel.poly_cx & 0xfff;
+ s3->accel.cur_y = s3->accel.poly_cy & 0xfff;
+ s3->accel.cur_x2 = s3->accel.poly_cx2 & 0xfff;
+ s3->accel.cur_y2 = s3->accel.poly_cy & 0xfff;
+ }
+ break;
+ }
+}
+
+void s3_hwcursor_draw(svga_t *svga, int displine)
+{
+ s3_t *s3 = (s3_t *)svga->p;
+ int x;
+ uint16_t dat[2];
+ int xx;
+ int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff;
+ uint32_t fg = 0, bg = 0;
+
+ switch (svga->bpp)
+ {
+ case 15:
+ fg = video_15to32[s3->hwc_fg_col & 0xffff];
+ bg = video_15to32[s3->hwc_bg_col & 0xffff];
+ break;
+
+ case 16:
+ fg = video_16to32[s3->hwc_fg_col & 0xffff];
+ bg = video_16to32[s3->hwc_bg_col & 0xffff];
+ break;
+
+ case 24: case 32:
+ fg = s3->hwc_fg_col;
+ bg = s3->hwc_bg_col;
+ break;
+
+ default:
+ if (s3->chip == S3_TRIO32 || s3->chip == S3_TRIO64)
+ {
+ fg = svga->pallook[s3->hwc_fg_col & 0xff];
+ bg = svga->pallook[s3->hwc_bg_col & 0xff];
+ }
+ else
+ {
+ fg = svga->pallook[svga->crtc[0xe]];
+ bg = svga->pallook[svga->crtc[0xf]];
+ }
+ break;
+ }
+
+ if (svga->interlace && svga->hwcursor_oddeven)
+ svga->hwcursor_latch.addr += 16;
+
+// pclog("HWcursor %i %i\n", svga->hwcursor_latch.x, svga->hwcursor_latch.y);
+ for (x = 0; x < 64; x += 16)
+ {
+ dat[0] = (svga->vram[svga->hwcursor_latch.addr] << 8) | svga->vram[svga->hwcursor_latch.addr + 1];
+ dat[1] = (svga->vram[svga->hwcursor_latch.addr + 2] << 8) | svga->vram[svga->hwcursor_latch.addr + 3];
+ for (xx = 0; xx < 16; xx++)
+ {
+ if (offset >= svga->hwcursor_latch.x)
+ {
+ if (!(dat[0] & 0x8000))
+ ((uint32_t *)buffer32->line[displine])[offset + 32] = (dat[1] & 0x8000) ? fg : bg;
+ else if (dat[1] & 0x8000)
+ ((uint32_t *)buffer32->line[displine])[offset + 32] ^= 0xffffff;
+// pclog("Plot %i, %i (%i %i) %04X %04X\n", offset, displine, x+xx, svga_hwcursor_on, dat[0], dat[1]);
+ }
+
+ offset++;
+ dat[0] <<= 1;
+ dat[1] <<= 1;
+ }
+ svga->hwcursor_latch.addr += 4;
+ }
+ if (svga->interlace && !svga->hwcursor_oddeven)
+ svga->hwcursor_latch.addr += 16;
+}
+
+
+static void s3_io_remove(s3_t *s3)
+{
+ io_removehandler(0x03c0, 0x0020, s3_in, NULL, NULL, s3_out, NULL, NULL, s3);
+
+ io_removehandler(0x42e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
+ io_removehandler(0x46e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
+ io_removehandler(0x4ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
+ io_removehandler(0x82e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
+ io_removehandler(0x86e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
+ io_removehandler(0x8ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
+ io_removehandler(0x8ee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
+ io_removehandler(0x92e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
+ io_removehandler(0x96e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
+ io_removehandler(0x9ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
+ io_removehandler(0x9ee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
+ io_removehandler(0xa2e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
+ io_removehandler(0xa6e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
+ io_removehandler(0xaae8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
+ io_removehandler(0xaee8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
+ io_removehandler(0xb2e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
+ io_removehandler(0xb6e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
+ io_removehandler(0xbae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
+ io_removehandler(0xbee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
+ io_removehandler(0xe2e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, s3_accel_out_w, s3_accel_out_l, s3);
+}
+
+static void s3_io_set(s3_t *s3)
+{
+ s3_io_remove(s3);
+
+ io_sethandler(0x03c0, 0x0020, s3_in, NULL, NULL, s3_out, NULL, NULL, s3);
+
+ io_sethandler(0x42e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
+ io_sethandler(0x46e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
+ io_sethandler(0x4ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
+ if (s3->chip == S3_TRIO64)
+ {
+ io_sethandler(0x82e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
+ io_sethandler(0x86e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
+ io_sethandler(0x8ae8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
+ io_sethandler(0x8ee8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
+ io_sethandler(0x92e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
+ io_sethandler(0x96e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
+ }
+ else
+ {
+ io_sethandler(0x82e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
+ io_sethandler(0x86e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
+ io_sethandler(0x8ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
+ io_sethandler(0x8ee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
+ io_sethandler(0x92e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
+ io_sethandler(0x96e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
+ }
+ io_sethandler(0x9ae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
+ io_sethandler(0x9ee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
+ io_sethandler(0xa2e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
+ io_sethandler(0xa6e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
+ io_sethandler(0xaae8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
+ io_sethandler(0xaee8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
+ io_sethandler(0xb2e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
+ io_sethandler(0xb6e8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
+ io_sethandler(0xbae8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
+ io_sethandler(0xbee8, 0x0002, s3_accel_in, NULL, NULL, s3_accel_out, NULL, NULL, s3);
+ io_sethandler(0xe2e8, 0x0004, s3_accel_in, NULL, NULL, s3_accel_out, s3_accel_out_w, s3_accel_out_l, s3);
+}
+
+
+uint8_t s3_pci_read(int func, int addr, void *p)
+{
+ s3_t *s3 = (s3_t *)p;
+ svga_t *svga = &s3->svga;
+// pclog("S3 PCI read %08X\n", addr);
+ switch (addr)
+ {
+ case 0x00: return 0x33; /*'S3'*/
+ case 0x01: return 0x53;
+
+ case 0x02: return s3->id_ext_pci;
+ case 0x03: return 0x88;
+
+ case PCI_REG_COMMAND:
+ return s3->pci_regs[PCI_REG_COMMAND]; /*Respond to IO and memory accesses*/
+
+ case 0x07: return 1 << 1; /*Medium DEVSEL timing*/
+
+ case 0x08: return 0; /*Revision ID*/
+ case 0x09: return 0; /*Programming interface*/
+
+ case 0x0a: return 0x00; /*Supports VGA interface*/
+ case 0x0b: return 0x03;
+
+ case 0x10: return 0x00; /*Linear frame buffer address*/
+ case 0x11: return 0x00;
+ case 0x12: return svga->crtc[0x5a] & 0x80;
+ case 0x13: return svga->crtc[0x59];
+
+ case 0x30: return s3->pci_regs[0x30] & 0x01; /*BIOS ROM address*/
+ case 0x31: return 0x00;
+ case 0x32: return s3->pci_regs[0x32];
+ case 0x33: return s3->pci_regs[0x33];
+
+ case 0x3c: return s3->int_line;
+ case 0x3d: return PCI_INTA;
+ }
+ return 0;
+}
+
+void s3_pci_write(int func, int addr, uint8_t val, void *p)
+{
+ s3_t *s3 = (s3_t *)p;
+ svga_t *svga = &s3->svga;
+// pclog("s3_pci_write: addr=%02x val=%02x\n", addr, val);
+ switch (addr)
+ {
+ case PCI_REG_COMMAND:
+ s3->pci_regs[PCI_REG_COMMAND] = val & 0x23;
+ if (val & PCI_COMMAND_IO)
+ s3_io_set(s3);
+ else
+ s3_io_remove(s3);
+ s3_updatemapping(s3);
+ break;
+
+ case 0x12:
+ svga->crtc[0x5a] = val & 0x80;
+ s3_updatemapping(s3);
+ break;
+ case 0x13:
+ svga->crtc[0x59] = val;
+ s3_updatemapping(s3);
+ break;
+
+ case 0x30: case 0x32: case 0x33:
+ s3->pci_regs[addr] = val;
+ if (s3->pci_regs[0x30] & 0x01)
+ {
+ uint32_t addr = (s3->pci_regs[0x32] << 16) | (s3->pci_regs[0x33] << 24);
+// pclog("S3 bios_rom enabled at %08x\n", addr);
+ mem_mapping_set_addr(&s3->bios_rom.mapping, addr, 0x8000);
+ }
+ else
+ {
+// pclog("S3 bios_rom disabled\n");
+ mem_mapping_disable(&s3->bios_rom.mapping);
+ }
+ return;
+
+ case 0x3c:
+ s3->int_line = val;
+ return;
+ }
+}
+
+static int vram_sizes[] =
+{
+ 7, /*512 kB*/
+ 6, /*1 MB*/
+ 4, /*2 MB*/
+ 0,
+ 0, /*4 MB*/
+ 0,
+ 0,
+ 0,
+ 3 /*8 MB*/
+};
+
+static void *s3_init(char *bios_fn, int chip)
+{
+ s3_t *s3 = malloc(sizeof(s3_t));
+ svga_t *svga = &s3->svga;
+ int vram;
+ uint32_t vram_size;
+
+ memset(s3, 0, sizeof(s3_t));
+
+ vram = device_get_config_int("memory");
+ if (vram)
+ vram_size = vram << 20;
+ else
+ vram_size = 512 << 10;
+ s3->vram_mask = vram_size - 1;
+
+ rom_init(&s3->bios_rom, bios_fn, 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
+ if (PCI)
+ mem_mapping_disable(&s3->bios_rom.mapping);
+
+ mem_mapping_add(&s3->linear_mapping, 0, 0, svga_read_linear, svga_readw_linear, svga_readl_linear, svga_write_linear, svga_writew_linear, svga_writel_linear, NULL, MEM_MAPPING_EXTERNAL, &s3->svga);
+ mem_mapping_add(&s3->mmio_mapping, 0xa0000, 0x10000, s3_accel_read, NULL, NULL, s3_accel_write, s3_accel_write_w, s3_accel_write_l, NULL, MEM_MAPPING_EXTERNAL, s3);
+ mem_mapping_disable(&s3->mmio_mapping);
+
+ svga_init(&s3->svga, s3, vram_size, /*4mb - 864 supports 8mb but buggy VESA driver reports 0mb*/
+ s3_recalctimings,
+ s3_in, s3_out,
+ s3_hwcursor_draw,
+ NULL);
+
+ svga->decode_mask = (4 << 20) - 1;
+ switch (vram)
+ {
+ case 0: /*512kb*/
+ svga->vram_mask = (1 << 19) - 1;
+ svga->vram_max = 2 << 20;
+ break;
+ case 1: /*1MB*/
+ /*VRAM in first MB, mirrored in 2nd MB, 3rd and 4th MBs are open bus*/
+ /*This works with the #9 9FX BIOS, and matches how my real Trio64 behaves,
+ but does not work with the Phoenix EDO BIOS. Possibly an FPM/EDO difference?*/
+ svga->vram_mask = (1 << 20) - 1;
+ svga->vram_max = 2 << 20;
+ break;
+ case 2: default: /*2MB*/
+ /*VRAM in first 2 MB, 3rd and 4th MBs are open bus*/
+ svga->vram_mask = (2 << 20) - 1;
+ svga->vram_max = 2 << 20;
+ break;
+ case 4: /*4MB*/
+ svga->vram_mask = (4 << 20) - 1;
+ svga->vram_max = 4 << 20;
+ break;
+ }
+
+ if (PCI)
+ svga->crtc[0x36] = 2 | (3 << 2) | (1 << 4) | (vram_sizes[vram] << 5);
+ else
+ svga->crtc[0x36] = 1 | (3 << 2) | (1 << 4) | (vram_sizes[vram] << 5);
+ svga->crtc[0x37] = 1 | (7 << 5);
+
+ svga->vblank_start = s3_vblank_start;
+
+ s3_io_set(s3);
+
+ s3->card = pci_add(s3_pci_read, s3_pci_write, s3);
+
+ s3->pci_regs[0x04] = 7;
+
+ s3->pci_regs[0x30] = 0x00;
+ s3->pci_regs[0x32] = 0x0c;
+ s3->pci_regs[0x33] = 0x00;
+
+ s3->chip = chip;
+
+ s3->wake_fifo_thread = thread_create_event();
+ s3->fifo_not_full_event = thread_create_event();
+ s3->fifo_thread = thread_create(fifo_thread, s3);
+
+ s3->int_line = 0;
+
+ return s3;
+}
+
+void *s3_bahamas64_init()
+{
+ s3_t *s3 = s3_init("bahamas64.bin", S3_VISION864);
+
+ s3->id = 0xc0; /*Vision864P*/
+ s3->id_ext = s3->id_ext_pci = 0xc0;
+ s3->packed_mmio = 0;
+
+ s3->getclock = sdac_getclock;
+ s3->getclock_p = &s3->ramdac;
+ sdac_init(&s3->ramdac);
+
+ return s3;
+}
+
+int s3_bahamas64_available()
+{
+ return rom_present("bahamas64.bin");
+}
+
+void *s3_9fx_init()
+{
+ s3_t *s3 = s3_init("s3_764.bin", S3_TRIO64);
+
+ s3->id = 0xe1; /*Trio64*/
+ s3->id_ext = s3->id_ext_pci = 0x11;
+ s3->packed_mmio = 1;
+
+ s3->getclock = s3_trio64_getclock;
+ s3->getclock_p = s3;
+
+ return s3;
+}
+
+int s3_9fx_available()
+{
+ return rom_present("s3_764.bin");
+}
+
+void *s3_phoenix_trio32_init()
+{
+ s3_t *s3 = s3_init("86c732p.bin", S3_TRIO32);
+
+ s3->id = 0xe1; /*Trio32*/
+ s3->id_ext = 0x10;
+ s3->id_ext_pci = 0x11;
+ s3->packed_mmio = 1;
+
+ s3->getclock = s3_trio64_getclock;
+ s3->getclock_p = s3;
+
+ return s3;
+}
+
+int s3_phoenix_trio32_available()
+{
+ return rom_present("86c732p.bin");
+}
+
+void *s3_phoenix_trio64_init()
+{
+ s3_t *s3 = s3_init("86c764x1.bin", S3_TRIO64);
+
+ s3->id = 0xe1; /*Trio64*/
+ s3->id_ext = s3->id_ext_pci = 0x11;
+ s3->packed_mmio = 1;
+ if (device_get_config_int("memory") == 1)
+ s3->svga.vram_max = 1 << 20; /*Phoenix BIOS does not expect VRAM to be mirrored*/
+
+ s3->getclock = s3_trio64_getclock;
+ s3->getclock_p = s3;
+
+ return s3;
+}
+
+int s3_phoenix_trio64_available()
+{
+ return rom_present("86c764x1.bin");
+}
+
+void s3_close(void *p)
+{
+ s3_t *s3 = (s3_t *)p;
+
+ svga_close(&s3->svga);
+
+ thread_kill(s3->fifo_thread);
+ thread_destroy_event(s3->wake_fifo_thread);
+ thread_destroy_event(s3->fifo_not_full_event);
+
+ free(s3);
+}
+
+void s3_speed_changed(void *p)
+{
+ s3_t *s3 = (s3_t *)p;
+
+ svga_recalctimings(&s3->svga);
+}
+
+void s3_force_redraw(void *p)
+{
+ s3_t *s3 = (s3_t *)p;
+
+ s3->svga.fullchange = changeframecount;
+}
+
+void s3_add_status_info(char *s, int max_len, void *p)
+{
+ s3_t *s3 = (s3_t *)p;
+ char temps[256];
+ uint64_t new_time = timer_read();
+ uint64_t status_diff = new_time - s3->status_time;
+ s3->status_time = new_time;
+
+ if (!status_diff)
+ status_diff = 1;
+
+ svga_add_status_info(s, max_len, &s3->svga);
+ sprintf(temps, "%f%% CPU\n%f%% CPU (real)\n\n", ((double)s3->blitter_time * 100.0) / timer_freq, ((double)s3->blitter_time * 100.0) / status_diff);
+ strncat(s, temps, max_len);
+
+ s3->blitter_time = 0;
+}
+
+static device_config_t s3_bahamas64_config[] =
+{
+ {
+ .name = "memory",
+ .description = "Memory size",
+ .type = CONFIG_SELECTION,
+ .selection =
+ {
+ {
+ .description = "1 MB",
+ .value = 1
+ },
+ {
+ .description = "2 MB",
+ .value = 2
+ },
+ /*Vision864 also supports 4 and 8 MB, however the Paradise
+ BIOS is buggy (VESA modes don't work correctly), and UNIVBE and
+ OS/2 Warp misdetect the VRAM size. Bahamas 64 only supports
+ up to 2 MB on the board anyway. */
+ {
+ .description = ""
+ }
+ },
+ .default_int = 4
+ },
+ {
+ .type = -1
+ }
+};
+
+static device_config_t s3_9fx_config[] =
+{
+ {
+ .name = "memory",
+ .description = "Memory size",
+ .type = CONFIG_SELECTION,
+ .selection =
+ {
+ {
+ .description = "1 MB",
+ .value = 1
+ },
+ {
+ .description = "2 MB",
+ .value = 2
+ },
+ /*Trio64 also supports 4 MB, however the Number Nine BIOS does not*/
+ {
+ .description = ""
+ }
+ },
+ .default_int = 2
+ },
+ {
+ .type = -1
+ }
+};
+
+static device_config_t s3_phoenix_trio32_config[] =
+{
+ {
+ .name = "memory",
+ .description = "Memory size",
+ .type = CONFIG_SELECTION,
+ .selection =
+ {
+ {
+ .description = "512 KB",
+ .value = 0
+ },
+ {
+ .description = "1 MB",
+ .value = 1
+ },
+ {
+ .description = "2 MB",
+ .value = 2
+ },
+ {
+ .description = ""
+ }
+ },
+ .default_int = 2
+ },
+ {
+ .type = -1
+ }
+};
+
+static device_config_t s3_phoenix_trio64_config[] =
+{
+ {
+ .name = "memory",
+ .description = "Memory size",
+ .type = CONFIG_SELECTION,
+ .selection =
+ {
+ {
+ .description = "1 MB",
+ .value = 1
+ },
+ {
+ .description = "2 MB",
+ .value = 2
+ },
+ {
+ .description = "4 MB",
+ .value = 4
+ },
+ {
+ .description = ""
+ }
+ },
+ .default_int = 2
+ },
+ {
+ .type = -1
+ }
+};
+
+device_t s3_bahamas64_device =
+{
+ "Paradise Bahamas 64 (S3 Vision864)",
+ 0,
+ s3_bahamas64_init,
+ s3_close,
+ s3_bahamas64_available,
+ s3_speed_changed,
+ s3_force_redraw,
+ s3_add_status_info,
+ s3_bahamas64_config
+};
+
+device_t s3_9fx_device =
+{
+ "Number 9 9FX (S3 Trio64)",
+ 0,
+ s3_9fx_init,
+ s3_close,
+ s3_9fx_available,
+ s3_speed_changed,
+ s3_force_redraw,
+ s3_add_status_info,
+ s3_9fx_config
+};
+
+device_t s3_phoenix_trio32_device =
+{
+ "Phoenix S3 Trio32",
+ 0,
+ s3_phoenix_trio32_init,
+ s3_close,
+ s3_phoenix_trio32_available,
+ s3_speed_changed,
+ s3_force_redraw,
+ s3_add_status_info,
+ s3_phoenix_trio32_config
+};
+
+device_t s3_phoenix_trio64_device =
+{
+ "Phoenix S3 Trio64",
+ 0,
+ s3_phoenix_trio64_init,
+ s3_close,
+ s3_phoenix_trio64_available,
+ s3_speed_changed,
+ s3_force_redraw,
+ s3_add_status_info,
+ s3_phoenix_trio64_config
+};
--- /dev/null
+device_t s3_bahamas64_device;
+device_t s3_9fx_device;
+device_t s3_phoenix_trio32_device;
+device_t s3_phoenix_trio64_device;
--- /dev/null
+/*S3 ViRGE emulation*/
+#include <stdlib.h>
+#include "ibm.h"
+#include "device.h"
+#include "io.h"
+#include "mem.h"
+#include "pci.h"
+#include "rom.h"
+#include "thread.h"
+#include "video.h"
+#include "vid_s3_virge.h"
+#include "vid_svga.h"
+#include "vid_svga_render.h"
+
+#ifdef MIN
+#undef MIN
+#endif
+#ifdef MAX
+#undef MAX
+#endif
+#ifdef CLAMP
+#undef CLAMP
+#endif
+
+static uint64_t virge_time = 0;
+static uint64_t status_time = 0;
+static int reg_writes = 0, reg_reads = 0;
+
+static int dither[4][4] =
+{
+ {0, 4, 1, 5},
+ {6, 2, 7, 3},
+ {1, 5, 0, 4},
+ {7, 3, 6, 2},
+};
+
+#define RB_SIZE 256
+#define RB_MASK (RB_SIZE - 1)
+
+#define RB_ENTRIES (virge->s3d_write_idx - virge->s3d_read_idx)
+#define RB_FULL (RB_ENTRIES == RB_SIZE)
+#define RB_EMPTY (!RB_ENTRIES)
+
+#define FIFO_SIZE 65536
+#define FIFO_MASK (FIFO_SIZE - 1)
+#define FIFO_ENTRY_SIZE (1 << 31)
+
+#define FIFO_ENTRIES (virge->fifo_write_idx - virge->fifo_read_idx)
+#define FIFO_FULL ((virge->fifo_write_idx - virge->fifo_read_idx) >= FIFO_SIZE)
+#define FIFO_EMPTY (virge->fifo_read_idx == virge->fifo_write_idx)
+
+#define FIFO_TYPE 0xff000000
+#define FIFO_ADDR 0x00ffffff
+
+enum
+{
+ FIFO_INVALID = (0x00 << 24),
+ FIFO_WRITE_BYTE = (0x01 << 24),
+ FIFO_WRITE_WORD = (0x02 << 24),
+ FIFO_WRITE_DWORD = (0x03 << 24),
+};
+
+typedef struct
+{
+ uint32_t addr_type;
+ uint32_t val;
+} fifo_entry_t;
+
+typedef struct s3d_t
+{
+ uint32_t cmd_set;
+ int clip_l, clip_r, clip_t, clip_b;
+
+ uint32_t dest_base;
+ uint32_t dest_str;
+
+ uint32_t z_base;
+ uint32_t z_str;
+
+ uint32_t tex_base;
+ uint32_t tex_bdr_clr;
+ uint32_t tbv, tbu;
+ int32_t TdVdX, TdUdX;
+ int32_t TdVdY, TdUdY;
+ uint32_t tus, tvs;
+
+ int32_t TdZdX, TdZdY;
+ uint32_t tzs;
+
+ int32_t TdWdX, TdWdY;
+ uint32_t tws;
+
+ int32_t TdDdX, TdDdY;
+ uint32_t tds;
+
+ int16_t TdGdX, TdBdX, TdRdX, TdAdX;
+ int16_t TdGdY, TdBdY, TdRdY, TdAdY;
+ uint32_t tgs, tbs, trs, tas;
+
+ uint32_t TdXdY12;
+ uint32_t txend12;
+ uint32_t TdXdY01;
+ uint32_t txend01;
+ uint32_t TdXdY02;
+ uint32_t txs;
+ uint32_t tys;
+ int ty01, ty12, tlr;
+} s3d_t;
+
+typedef struct virge_t
+{
+ mem_mapping_t linear_mapping;
+ mem_mapping_t mmio_mapping;
+ mem_mapping_t new_mmio_mapping;
+
+ rom_t bios_rom;
+
+ svga_t svga;
+
+ uint8_t bank;
+ uint8_t ma_ext;
+
+ uint8_t virge_id, virge_id_high, virge_id_low, virge_rev;
+
+ uint32_t linear_base, linear_size;
+
+ uint8_t pci_regs[256];
+ int card;
+
+ int is_375;
+
+ int bilinear_enabled;
+ int dithering_enabled;
+ int memory_size;
+
+ int pixel_count, tri_count;
+
+ thread_t *render_thread;
+ event_t *wake_render_thread;
+ event_t *wake_main_thread;
+ event_t *not_full_event;
+
+ uint32_t hwc_fg_col, hwc_bg_col;
+ int hwc_col_stack_pos;
+
+ struct
+ {
+ uint32_t src_base;
+ uint32_t dest_base;
+ int clip_l, clip_r, clip_t, clip_b;
+ int dest_str, src_str;
+ uint32_t mono_pat_0;
+ uint32_t mono_pat_1;
+ uint32_t pat_bg_clr;
+ uint32_t pat_fg_clr;
+ uint32_t src_bg_clr;
+ uint32_t src_fg_clr;
+ uint32_t cmd_set;
+ int r_width, r_height;
+ int rsrc_x, rsrc_y;
+ int rdest_x, rdest_y;
+
+ int lxend0, lxend1;
+ int32_t ldx;
+ uint32_t lxstart, lystart;
+ int lycnt;
+ int line_dir;
+
+ int src_x, src_y;
+ int dest_x, dest_y;
+ int w, h;
+ uint8_t rop;
+
+ int data_left_count;
+ uint32_t data_left;
+
+ uint32_t pattern_8[8*8];
+ uint32_t pattern_16[8*8];
+ uint32_t pattern_32[8*8];
+
+ uint32_t prdx;
+ uint32_t prxstart;
+ uint32_t pldx;
+ uint32_t plxstart;
+ uint32_t pystart;
+ uint32_t pycnt;
+ uint32_t dest_l, dest_r;
+ } s3d;
+
+ s3d_t s3d_tri;
+
+ s3d_t s3d_buffer[RB_SIZE];
+ int s3d_read_idx, s3d_write_idx;
+ int s3d_busy;
+
+ struct
+ {
+ uint32_t pri_ctrl;
+ uint32_t chroma_ctrl;
+ uint32_t sec_ctrl;
+ uint32_t chroma_upper_bound;
+ uint32_t sec_filter;
+ uint32_t blend_ctrl;
+ uint32_t pri_fb0, pri_fb1;
+ uint32_t pri_stride;
+ uint32_t buffer_ctrl;
+ uint32_t sec_fb0, sec_fb1;
+ uint32_t sec_stride;
+ uint32_t overlay_ctrl;
+ int32_t k1_vert_scale;
+ int32_t k2_vert_scale;
+ int32_t dda_vert_accumulator;
+ int32_t k1_horiz_scale;
+ int32_t k2_horiz_scale;
+ int32_t dda_horiz_accumulator;
+ uint32_t fifo_ctrl;
+ uint32_t pri_start;
+ uint32_t pri_size;
+ uint32_t sec_start;
+ uint32_t sec_size;
+
+ int sdif;
+
+ int pri_x, pri_y, pri_w, pri_h;
+ int sec_x, sec_y, sec_w, sec_h;
+ } streams;
+
+ fifo_entry_t fifo[FIFO_SIZE];
+ volatile int fifo_read_idx, fifo_write_idx;
+
+ thread_t *fifo_thread;
+ event_t *wake_fifo_thread;
+ event_t *fifo_not_full_event;
+
+ int virge_busy;
+
+ uint8_t subsys_stat, subsys_cntl;
+} virge_t;
+
+static inline void wake_fifo_thread(virge_t *virge)
+{
+ thread_set_event(virge->wake_fifo_thread); /*Wake up FIFO thread if moving from idle*/
+}
+
+static void queue_triangle(virge_t *virge);
+
+static void s3_virge_recalctimings(svga_t *svga);
+static void s3_virge_updatemapping(virge_t *virge);
+
+static void s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat);
+
+static uint8_t s3_virge_mmio_read(uint32_t addr, void *p);
+static uint16_t s3_virge_mmio_read_w(uint32_t addr, void *p);
+static uint32_t s3_virge_mmio_read_l(uint32_t addr, void *p);
+static void s3_virge_mmio_write(uint32_t addr, uint8_t val, void *p);
+static void s3_virge_mmio_write_w(uint32_t addr, uint16_t val, void *p);
+static void s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *p);
+
+enum
+{
+ CMD_SET_AE = 1,
+ CMD_SET_HC = (1 << 1),
+
+ CMD_SET_FORMAT_MASK = (7 << 2),
+ CMD_SET_FORMAT_8 = (0 << 2),
+ CMD_SET_FORMAT_16 = (1 << 2),
+ CMD_SET_FORMAT_24 = (2 << 2),
+
+ CMD_SET_MS = (1 << 6),
+ CMD_SET_IDS = (1 << 7),
+ CMD_SET_MP = (1 << 8),
+ CMD_SET_TP = (1 << 9),
+
+ CMD_SET_ITA_MASK = (3 << 10),
+ CMD_SET_ITA_BYTE = (0 << 10),
+ CMD_SET_ITA_WORD = (1 << 10),
+ CMD_SET_ITA_DWORD = (2 << 10),
+
+ CMD_SET_ZUP = (1 << 23),
+
+ CMD_SET_ZB_MODE = (3 << 24),
+
+ CMD_SET_XP = (1 << 25),
+ CMD_SET_YP = (1 << 26),
+
+ CMD_SET_COMMAND_MASK = (15 << 27)
+};
+
+#define CMD_SET_ABC_SRC (1 << 18)
+#define CMD_SET_ABC_ENABLE (1 << 19)
+#define CMD_SET_TWE (1 << 26)
+
+enum
+{
+ CMD_SET_COMMAND_BITBLT = (0 << 27),
+ CMD_SET_COMMAND_RECTFILL = (2 << 27),
+ CMD_SET_COMMAND_LINE = (3 << 27),
+ CMD_SET_COMMAND_POLY = (5 << 27),
+ CMD_SET_COMMAND_NOP = (15 << 27)
+};
+
+#define INT_VSY (1 << 0)
+#define INT_S3D_DONE (1 << 1)
+#define INT_FIFO_OVF (1 << 2)
+#define INT_FIFO_EMP (1 << 3)
+#define INT_3DF_EMP (1 << 6)
+#define INT_MASK 0xff
+
+static void s3_virge_update_irqs(virge_t *virge)
+{
+ if ((virge->svga.crtc[0x32] & 0x10) && (virge->subsys_stat & virge->subsys_cntl & INT_MASK))
+ pci_set_irq(virge->card, PCI_INTA);
+ else
+ pci_clear_irq(virge->card, PCI_INTA);
+}
+
+static void s3_virge_out(uint16_t addr, uint8_t val, void *p)
+{
+ virge_t *virge = (virge_t *)p;
+ svga_t *svga = &virge->svga;
+ uint8_t old;
+
+ if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1))
+ addr ^= 0x60;
+
+// pclog("S3 out %04X %02X %04X:%08X %04X %04X %i\n", addr, val, CS, pc, ES, BX, ins);
+
+ switch (addr)
+ {
+ case 0x3c5:
+ if (svga->seqaddr >= 0x10)
+ {
+ svga->seqregs[svga->seqaddr & 0x1f]=val;
+ svga_recalctimings(svga);
+ return;
+ }
+ if (svga->seqaddr == 4) /*Chain-4 - update banking*/
+ {
+ if (val & 8) svga->write_bank = svga->read_bank = virge->bank << 16;
+ else svga->write_bank = svga->read_bank = virge->bank << 14;
+ }
+ break;
+
+ //case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9:
+// pclog("Write RAMDAC %04X %02X %04X:%04X\n", addr, val, CS, pc);
+ //sdac_ramdac_out(addr,val);
+ //return;
+
+ case 0x3d4:
+ svga->crtcreg = val;// & 0x7f;
+ return;
+ case 0x3d5:
+ //pclog("Write CRTC R%02X %02X %04x(%08x):%08x\n", svga->crtcreg, val, CS, cs, pc);
+ if ((svga->crtcreg < 7) && (svga->crtc[0x11] & 0x80))
+ return;
+ if ((svga->crtcreg == 7) && (svga->crtc[0x11] & 0x80))
+ val = (svga->crtc[7] & ~0x10) | (val & 0x10);
+ if (svga->crtcreg >= 0x20 && svga->crtcreg != 0x38 && (svga->crtc[0x38] & 0xcc) != 0x48)
+ return;
+ if (svga->crtcreg >= 0x80)
+ return;
+ old = svga->crtc[svga->crtcreg];
+ svga->crtc[svga->crtcreg] = val;
+ switch (svga->crtcreg)
+ {
+ case 0x31:
+ virge->ma_ext = (virge->ma_ext & 0x1c) | ((val & 0x30) >> 4);
+ break;
+ case 0x32:
+ s3_virge_update_irqs(virge);
+ break;
+
+ case 0x69:
+ virge->ma_ext = val & 0x1f;
+ break;
+
+ case 0x35:
+ virge->bank = (virge->bank & 0x70) | (val & 0xf);
+// pclog("CRTC write R35 %02X\n", val);
+ if (svga->chain4) svga->write_bank = svga->read_bank = virge->bank << 16;
+ else svga->write_bank = svga->read_bank = virge->bank << 14;
+ break;
+ case 0x51:
+ virge->bank = (virge->bank & 0x4f) | ((val & 0xc) << 2);
+ if (svga->chain4) svga->write_bank = svga->read_bank = virge->bank << 16;
+ else svga->write_bank = svga->read_bank = virge->bank << 14;
+ virge->ma_ext = (virge->ma_ext & ~0xc) | ((val & 3) << 2);
+ break;
+ case 0x6a:
+ virge->bank = val;
+// pclog("CRTC write R6a %02X\n", val);
+ if (svga->chain4) svga->write_bank = svga->read_bank = virge->bank << 16;
+ else svga->write_bank = svga->read_bank = virge->bank << 14;
+ break;
+
+ case 0x3a:
+ if (val & 0x10) svga->gdcreg[5] |= 0x40; /*Horrible cheat*/
+ break;
+
+ case 0x45:
+ svga->hwcursor.ena = val & 1;
+ break;
+ case 0x46: case 0x47: case 0x48: case 0x49:
+ case 0x4c: case 0x4d: case 0x4e: case 0x4f:
+ svga->hwcursor.x = ((svga->crtc[0x46] << 8) | svga->crtc[0x47]) & 0x7ff;
+ svga->hwcursor.y = ((svga->crtc[0x48] << 8) | svga->crtc[0x49]) & 0x7ff;
+ svga->hwcursor.xoff = svga->crtc[0x4e] & 63;
+ svga->hwcursor.yoff = svga->crtc[0x4f] & 63;
+ svga->hwcursor.addr = ((((svga->crtc[0x4c] << 8) | svga->crtc[0x4d]) & 0xfff) * 1024) + (svga->hwcursor.yoff * 16);
+ break;
+
+ case 0x4a:
+ switch (virge->hwc_col_stack_pos)
+ {
+ case 0:
+ virge->hwc_fg_col = (virge->hwc_fg_col & 0xffff00) | val;
+ break;
+ case 1:
+ virge->hwc_fg_col = (virge->hwc_fg_col & 0xff00ff) | (val << 8);
+ break;
+ case 2:
+ virge->hwc_fg_col = (virge->hwc_fg_col & 0x00ffff) | (val << 16);
+ break;
+ }
+ virge->hwc_col_stack_pos = (virge->hwc_col_stack_pos + 1) & 3;
+ break;
+ case 0x4b:
+ switch (virge->hwc_col_stack_pos)
+ {
+ case 0:
+ virge->hwc_bg_col = (virge->hwc_bg_col & 0xffff00) | val;
+ break;
+ case 1:
+ virge->hwc_bg_col = (virge->hwc_bg_col & 0xff00ff) | (val << 8);
+ break;
+ case 2:
+ virge->hwc_bg_col = (virge->hwc_bg_col & 0x00ffff) | (val << 16);
+ break;
+ }
+ virge->hwc_col_stack_pos = (virge->hwc_col_stack_pos + 1) & 3;
+ break;
+
+ case 0x53:
+ case 0x58: case 0x59: case 0x5a:
+ s3_virge_updatemapping(virge);
+ break;
+
+ case 0x67:
+ switch (val >> 4)
+ {
+ case 3: svga->bpp = 15; break;
+ case 5: svga->bpp = 16; break;
+ case 7: svga->bpp = 24; break;
+ case 13: svga->bpp = 32; break;
+ default: svga->bpp = 8; break;
+ }
+ break;
+ //case 0x55: case 0x43:
+// pclog("Write CRTC R%02X %02X\n", crtcreg, val);
+ }
+ if (old != val)
+ {
+ if (svga->crtcreg < 0xe || svga->crtcreg > 0x10)
+ {
+ svga->fullchange = changeframecount;
+ svga_recalctimings(svga);
+ }
+ }
+ break;
+ }
+ svga_out(addr, val, svga);
+}
+
+static uint8_t s3_virge_in(uint16_t addr, void *p)
+{
+ virge_t *virge = (virge_t *)p;
+ svga_t *svga = &virge->svga;
+ uint8_t ret;
+
+ if (((addr & 0xfff0) == 0x3d0 || (addr & 0xfff0) == 0x3b0) && !(svga->miscout & 1))
+ addr ^= 0x60;
+
+// if (addr != 0x3da) pclog("S3 in %04X %04X:%08X ", addr, CS, pc);
+ switch (addr)
+ {
+ case 0x3c1:
+ if (svga->attraddr > 0x14)
+ ret = 0xff;
+ else
+ ret = svga_in(addr, svga);
+ break;
+ //case 0x3C6: case 0x3C7: case 0x3C8: case 0x3C9:
+// pclog("Read RAMDAC %04X %04X:%04X\n", addr, CS, pc);
+ //return sdac_ramdac_in(addr);
+
+ case 0x3c5:
+ if (svga->seqaddr >= 8)
+ ret = svga->seqregs[svga->seqaddr & 0x1f];
+ else if (svga->seqaddr <= 4)
+ ret = svga_in(addr, svga);
+ else
+ ret = 0xff;
+ break;
+
+ case 0x3D4:
+ ret = svga->crtcreg;
+ break;
+ case 0x3D5:
+ //pclog("Read CRTC R%02X %04X:%04X (%02x)\n", svga->crtcreg, CS, pc, svga->crtc[svga->crtcreg]);
+ switch (svga->crtcreg)
+ {
+ case 0x2d: ret = virge->virge_id_high; break; /*Extended chip ID*/
+ case 0x2e: ret = virge->virge_id_low; break; /*New chip ID*/
+ case 0x2f: ret = virge->virge_rev; break;
+ case 0x30: ret = virge->virge_id; break; /*Chip ID*/
+ case 0x31: ret = (svga->crtc[0x31] & 0xcf) | ((virge->ma_ext & 3) << 4); break;
+ case 0x35: ret = (svga->crtc[0x35] & 0xf0) | (virge->bank & 0xf); break;
+ case 0x36: ret = (svga->crtc[0x36] & 0xfc) | 2; break; /*PCI bus*/
+ case 0x45: virge->hwc_col_stack_pos = 0; ret = svga->crtc[0x45]; break;
+ case 0x51: ret = (svga->crtc[0x51] & 0xf0) | ((virge->bank >> 2) & 0xc) | ((virge->ma_ext >> 2) & 3); break;
+ case 0x69: ret = virge->ma_ext; break;
+ case 0x6a: ret = virge->bank; break;
+ default: ret = svga->crtc[svga->crtcreg]; break;
+ }
+ break;
+
+ default:
+ ret = svga_in(addr, svga);
+ break;
+ }
+// if (addr != 0x3da) pclog("%02X\n", ret);
+ return ret;
+}
+
+static void s3_virge_recalctimings(svga_t *svga)
+{
+ virge_t *virge = (virge_t *)svga->p;
+
+ if (svga->crtc[0x5d] & 0x01) svga->htotal += 0x100;
+ if (svga->crtc[0x5d] & 0x02) svga->hdisp += 0x100;
+ if (svga->crtc[0x5e] & 0x01) svga->vtotal += 0x400;
+ if (svga->crtc[0x5e] & 0x02) svga->dispend += 0x400;
+ if (svga->crtc[0x5e] & 0x04) svga->vblankstart += 0x400;
+ if (svga->crtc[0x5e] & 0x10) svga->vsyncstart += 0x400;
+ if (svga->crtc[0x5e] & 0x40) svga->split += 0x400;
+ svga->interlace = svga->crtc[0x42] & 0x20;
+
+ if ((svga->crtc[0x67] & 0xc) != 0xc) /*VGA mode*/
+ {
+ svga->ma_latch |= (virge->ma_ext << 16);
+//pclog("VGA mode\n");
+ if (svga->crtc[0x51] & 0x30) svga->rowoffset += (svga->crtc[0x51] & 0x30) << 4;
+ else if (svga->crtc[0x43] & 0x04) svga->rowoffset += 0x100;
+ if (!svga->rowoffset) svga->rowoffset = 256;
+
+ if ((svga->gdcreg[5] & 0x40) && (svga->crtc[0x3a] & 0x10))
+ {
+ switch (svga->bpp)
+ {
+ case 8:
+ svga->render = svga_render_8bpp_highres;
+ break;
+ case 15:
+ svga->render = svga_render_15bpp_highres;
+ break;
+ case 16:
+ svga->render = svga_render_16bpp_highres;
+ break;
+ case 24:
+ svga->render = svga_render_24bpp_highres;
+ break;
+ case 32:
+ svga->render = svga_render_32bpp_highres;
+ break;
+ }
+ }
+
+// pclog("svga->rowoffset = %i bpp=%i\n", svga->rowoffset, svga->bpp);
+ if (svga->bpp == 15 || svga->bpp == 16)
+ {
+ svga->htotal >>= 1;
+ svga->hdisp >>= 1;
+ }
+ if (svga->bpp == 24)
+ {
+ svga->rowoffset = (svga->rowoffset * 3) / 4; /*Hack*/
+ }
+ svga->vram_display_mask = (!(svga->crtc[0x31] & 0x08) && (svga->crtc[0x32] & 0x40)) ? 0x3ffff : ((virge->memory_size << 20) - 1);
+//pclog("VGA mode x_disp=%i dispend=%i vtotal=%i\n", svga->hdisp, svga->dispend, svga->vtotal);
+ }
+ else /*Streams mode*/
+ {
+ if (virge->streams.buffer_ctrl & 1)
+ svga->ma_latch = virge->streams.pri_fb1 >> 2;
+ else
+ svga->ma_latch = virge->streams.pri_fb0 >> 2;
+
+ svga->hdisp = virge->streams.pri_w + 1;
+ if (virge->streams.pri_h < svga->dispend)
+ svga->dispend = virge->streams.pri_h;
+
+ svga->overlay.x = virge->streams.sec_x - virge->streams.pri_x;
+ svga->overlay.y = virge->streams.sec_y - virge->streams.pri_y;
+ svga->overlay.ysize = virge->streams.sec_h;
+
+ if (virge->streams.buffer_ctrl & 2)
+ svga->overlay.addr = virge->streams.sec_fb1;
+ else
+ svga->overlay.addr = virge->streams.sec_fb0;
+
+ svga->overlay.ena = (svga->overlay.x >= 0);
+ svga->overlay.v_acc = virge->streams.dda_vert_accumulator;
+//pclog("Streams mode x_disp=%i dispend=%i vtotal=%i x=%i y=%i ysize=%i\n", svga->hdisp, svga->dispend, svga->vtotal, svga->overlay.x, svga->overlay.y, svga->overlay.ysize);
+ svga->rowoffset = virge->streams.pri_stride >> 3;
+
+ switch ((virge->streams.pri_ctrl >> 24) & 0x7)
+ {
+ case 0: /*RGB-8 (CLUT)*/
+ svga->render = svga_render_8bpp_highres;
+ break;
+ case 3: /*KRGB-16 (1.5.5.5)*/
+ svga->htotal >>= 1;
+ svga->render = svga_render_15bpp_highres;
+ break;
+ case 5: /*RGB-16 (5.6.5)*/
+ svga->htotal >>= 1;
+ svga->render = svga_render_16bpp_highres;
+ break;
+ case 6: /*RGB-24 (8.8.8)*/
+ svga->render = svga_render_24bpp_highres;
+ break;
+ case 7: /*XRGB-32 (X.8.8.8)*/
+ svga->render = svga_render_32bpp_highres;
+ break;
+ }
+ svga->vram_display_mask = (virge->memory_size << 20) - 1;
+ }
+
+ if (((svga->miscout >> 2) & 3) == 3)
+ {
+ int n = svga->seqregs[0x12] & 0x1f;
+ int r = (svga->seqregs[0x12] >> 5) & (virge->is_375 ? 7 : 3);
+ int m = svga->seqregs[0x13] & 0x7f;
+ double freq = (((double)m + 2) / (((double)n + 2) * (double)(1 << r))) * 14318184.0;
+
+ svga->clock = (cpuclock * (float)(1ull << 32)) / freq;
+ }
+}
+
+static void s3_virge_updatemapping(virge_t *virge)
+{
+ svga_t *svga = &virge->svga;
+
+ if (!(virge->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_MEM))
+ {
+// pclog("Update mapping - PCI disabled\n");
+ mem_mapping_disable(&svga->mapping);
+ mem_mapping_disable(&virge->linear_mapping);
+ mem_mapping_disable(&virge->mmio_mapping);
+ mem_mapping_disable(&virge->new_mmio_mapping);
+ return;
+ }
+
+ pclog("Update mapping - bank %02X ", svga->gdcreg[6] & 0xc);
+ switch (svga->gdcreg[6] & 0xc) /*Banked framebuffer*/
+ {
+ case 0x0: /*128k at A0000*/
+ mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000);
+ svga->banked_mask = 0xffff;
+ break;
+ case 0x4: /*64k at A0000*/
+ mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000);
+ svga->banked_mask = 0xffff;
+ break;
+ case 0x8: /*32k at B0000*/
+ mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000);
+ svga->banked_mask = 0x7fff;
+ break;
+ case 0xC: /*32k at B8000*/
+ mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000);
+ svga->banked_mask = 0x7fff;
+ break;
+ }
+
+ virge->linear_base = (svga->crtc[0x5a] << 16) | (svga->crtc[0x59] << 24);
+
+ pclog("Linear framebuffer %02X ", svga->crtc[0x58] & 0x10);
+ if (svga->crtc[0x58] & 0x10) /*Linear framebuffer*/
+ {
+ switch (svga->crtc[0x58] & 3)
+ {
+ case 0: /*64k*/
+ virge->linear_size = 0x10000;
+ break;
+ case 1: /*1mb*/
+ virge->linear_size = 0x100000;
+ break;
+ case 2: /*2mb*/
+ virge->linear_size = 0x200000;
+ break;
+ case 3: /*8mb*/
+ virge->linear_size = 0x400000;
+ break;
+ }
+ virge->linear_base &= ~(virge->linear_size - 1);
+// pclog("%08X %08X %02X %02X %02X\n", linear_base, linear_size, crtc[0x58], crtc[0x59], crtc[0x5a]);
+ pclog("Linear framebuffer at %08X size %08X\n", virge->linear_base, virge->linear_size);
+ if (virge->linear_base == 0xa0000)
+ {
+ mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000);
+ mem_mapping_disable(&virge->linear_mapping);
+ }
+ else
+ mem_mapping_set_addr(&virge->linear_mapping, virge->linear_base, virge->linear_size);
+ svga->fb_only = 1;
+ }
+ else
+ {
+ mem_mapping_disable(&virge->linear_mapping);
+ svga->fb_only = 0;
+ }
+
+ pclog("Memory mapped IO %02X\n", svga->crtc[0x53] & 0x18);
+ if (svga->crtc[0x53] & 0x10) /*Old MMIO*/
+ {
+ if (svga->crtc[0x53] & 0x20)
+ mem_mapping_set_addr(&virge->mmio_mapping, 0xb8000, 0x8000);
+ else
+ mem_mapping_set_addr(&virge->mmio_mapping, 0xa0000, 0x10000);
+ }
+ else
+ mem_mapping_disable(&virge->mmio_mapping);
+
+ if (svga->crtc[0x53] & 0x08) /*New MMIO*/
+ mem_mapping_set_addr(&virge->new_mmio_mapping, virge->linear_base + 0x1000000, 0x10000);
+ else
+ mem_mapping_disable(&virge->new_mmio_mapping);
+
+}
+
+static void s3_virge_vblank_start(svga_t *svga)
+{
+ virge_t *virge = (virge_t *)svga->p;
+
+ virge->subsys_stat |= INT_VSY;
+ s3_virge_update_irqs(virge);
+}
+
+static void s3_virge_wait_fifo_idle(virge_t *virge)
+{
+ while (!FIFO_EMPTY)
+ {
+ wake_fifo_thread(virge);
+ thread_wait_event(virge->fifo_not_full_event, 1);
+ }
+}
+
+static uint8_t s3_virge_mmio_read(uint32_t addr, void *p)
+{
+ virge_t *virge = (virge_t *)p;
+ uint8_t ret;
+
+ reg_reads++;
+// pclog("New MMIO readb %08X\n", addr);
+ switch (addr & 0xffff)
+ {
+ case 0x8505:
+ if (virge->s3d_busy || virge->virge_busy || !FIFO_EMPTY)
+ ret = 0x10;
+ else
+ ret = 0x10 | (1 << 5);
+ if (!virge->virge_busy)
+ wake_fifo_thread(virge);
+ return ret;
+
+ case 0x83b0: case 0x83b1: case 0x83b2: case 0x83b3:
+ case 0x83b4: case 0x83b5: case 0x83b6: case 0x83b7:
+ case 0x83b8: case 0x83b9: case 0x83ba: case 0x83bb:
+ case 0x83bc: case 0x83bd: case 0x83be: case 0x83bf:
+ case 0x83c0: case 0x83c1: case 0x83c2: case 0x83c3:
+ case 0x83c4: case 0x83c5: case 0x83c6: case 0x83c7:
+ case 0x83c8: case 0x83c9: case 0x83ca: case 0x83cb:
+ case 0x83cc: case 0x83cd: case 0x83ce: case 0x83cf:
+ case 0x83d0: case 0x83d1: case 0x83d2: case 0x83d3:
+ case 0x83d4: case 0x83d5: case 0x83d6: case 0x83d7:
+ case 0x83d8: case 0x83d9: case 0x83da: case 0x83db:
+ case 0x83dc: case 0x83dd: case 0x83de: case 0x83df:
+ return s3_virge_in(addr & 0x3ff, p);
+ }
+ return 0xff;
+}
+static uint16_t s3_virge_mmio_read_w(uint32_t addr, void *p)
+{
+ reg_reads++;
+// pclog("New MMIO readw %08X\n", addr);
+ switch (addr & 0xfffe)
+ {
+ default:
+ return s3_virge_mmio_read(addr, p) | (s3_virge_mmio_read(addr + 1, p) << 8);
+ }
+ return 0xffff;
+}
+static uint32_t s3_virge_mmio_read_l(uint32_t addr, void *p)
+{
+ virge_t *virge = (virge_t *)p;
+ uint32_t ret = 0xffffffff;
+ reg_reads++;
+// pclog("New MMIO readl %08X %04X(%08X):%08X ", addr, CS, cs, pc);
+ switch (addr & 0xfffc)
+ {
+ case 0x8180:
+ ret = virge->streams.pri_ctrl;
+ break;
+ case 0x8184:
+ ret = virge->streams.chroma_ctrl;
+ break;
+ case 0x8190:
+ ret = virge->streams.sec_ctrl;
+ break;
+ case 0x8194:
+ ret = virge->streams.chroma_upper_bound;
+ break;
+ case 0x8198:
+ ret = virge->streams.sec_filter;
+ break;
+ case 0x81a0:
+ ret = virge->streams.blend_ctrl;
+ break;
+ case 0x81c0:
+ ret = virge->streams.pri_fb0;
+ break;
+ case 0x81c4:
+ ret = virge->streams.pri_fb1;
+ break;
+ case 0x81c8:
+ ret = virge->streams.pri_stride;
+ break;
+ case 0x81cc:
+ ret = virge->streams.buffer_ctrl;
+ break;
+ case 0x81d0:
+ ret = virge->streams.sec_fb0;
+ break;
+ case 0x81d4:
+ ret = virge->streams.sec_fb1;
+ break;
+ case 0x81d8:
+ ret = virge->streams.sec_stride;
+ break;
+ case 0x81dc:
+ ret = virge->streams.overlay_ctrl;
+ break;
+ case 0x81e0:
+ ret = virge->streams.k1_vert_scale;
+ break;
+ case 0x81e4:
+ ret = virge->streams.k2_vert_scale;
+ break;
+ case 0x81e8:
+ ret = virge->streams.dda_vert_accumulator;
+ break;
+ case 0x81ec:
+ ret = virge->streams.fifo_ctrl;
+ break;
+ case 0x81f0:
+ ret = virge->streams.pri_start;
+ break;
+ case 0x81f4:
+ ret = virge->streams.pri_size;
+ break;
+ case 0x81f8:
+ ret = virge->streams.sec_start;
+ break;
+ case 0x81fc:
+ ret = virge->streams.sec_size;
+ break;
+
+ case 0x8504:
+ if (virge->s3d_busy || virge->virge_busy || !FIFO_EMPTY)
+ ret = (0x10 << 8);
+ else
+ ret = (0x10 << 8) | (1 << 13);
+ ret |= virge->subsys_stat;
+ if (!virge->virge_busy)
+ wake_fifo_thread(virge);
+// pclog("Read status %04x %i\n", ret, virge->s3d_busy);
+ break;
+ case 0xa4d4:
+ s3_virge_wait_fifo_idle(virge);
+ ret = virge->s3d.src_base;
+ break;
+ case 0xa4d8:
+ s3_virge_wait_fifo_idle(virge);
+ ret = virge->s3d.dest_base;
+ break;
+ case 0xa4dc:
+ s3_virge_wait_fifo_idle(virge);
+ ret = (virge->s3d.clip_l << 16) | virge->s3d.clip_r;
+ break;
+ case 0xa4e0:
+ s3_virge_wait_fifo_idle(virge);
+ ret = (virge->s3d.clip_t << 16) | virge->s3d.clip_b;
+ break;
+ case 0xa4e4:
+ s3_virge_wait_fifo_idle(virge);
+ ret = (virge->s3d.dest_str << 16) | virge->s3d.src_str;
+ break;
+ case 0xa4e8: case 0xace8:
+ s3_virge_wait_fifo_idle(virge);
+ ret = virge->s3d.mono_pat_0;
+ break;
+ case 0xa4ec: case 0xacec:
+ s3_virge_wait_fifo_idle(virge);
+ ret = virge->s3d.mono_pat_1;
+ break;
+ case 0xa4f0:
+ s3_virge_wait_fifo_idle(virge);
+ ret = virge->s3d.pat_bg_clr;
+ break;
+ case 0xa4f4:
+ s3_virge_wait_fifo_idle(virge);
+ ret = virge->s3d.pat_fg_clr;
+ break;
+ case 0xa4f8:
+ s3_virge_wait_fifo_idle(virge);
+ ret = virge->s3d.src_bg_clr;
+ break;
+ case 0xa4fc:
+ s3_virge_wait_fifo_idle(virge);
+ ret = virge->s3d.src_fg_clr;
+ break;
+ case 0xa500:
+ s3_virge_wait_fifo_idle(virge);
+ ret = virge->s3d.cmd_set;
+ break;
+ case 0xa504:
+ s3_virge_wait_fifo_idle(virge);
+ ret = (virge->s3d.r_width << 16) | virge->s3d.r_height;
+ break;
+ case 0xa508:
+ s3_virge_wait_fifo_idle(virge);
+ ret = (virge->s3d.rsrc_x << 16) | virge->s3d.rsrc_y;
+ break;
+ case 0xa50c:
+ s3_virge_wait_fifo_idle(virge);
+ ret = (virge->s3d.rdest_x << 16) | virge->s3d.rdest_y;
+ break;
+
+ default:
+ ret = s3_virge_mmio_read_w(addr, p) | (s3_virge_mmio_read_w(addr + 2, p) << 16);
+ }
+// /*if ((addr & 0xfffc) != 0x8504) */pclog("%02x\n", ret);
+ return ret;
+}
+
+static void fifo_thread(void *param)
+{
+ virge_t *virge = (virge_t *)param;
+
+ while (1)
+ {
+ thread_set_event(virge->fifo_not_full_event);
+ thread_wait_event(virge->wake_fifo_thread, -1);
+ thread_reset_event(virge->wake_fifo_thread);
+ virge->virge_busy = 1;
+ while (!FIFO_EMPTY)
+ {
+ uint64_t start_time = timer_read();
+ uint64_t end_time;
+ fifo_entry_t *fifo = &virge->fifo[virge->fifo_read_idx & FIFO_MASK];
+ uint32_t val = fifo->val;
+
+ switch (fifo->addr_type & FIFO_TYPE)
+ {
+ case FIFO_WRITE_BYTE:
+ if (((fifo->addr_type & FIFO_ADDR) & 0xfffc) < 0x8000)
+ s3_virge_bitblt(virge, 8, val);
+ break;
+ case FIFO_WRITE_WORD:
+ if (((fifo->addr_type & FIFO_ADDR) & 0xfffc) < 0x8000)
+ {
+ if (virge->s3d.cmd_set & CMD_SET_MS)
+ s3_virge_bitblt(virge, 16, ((val >> 8) | (val << 8)) << 16);
+ else
+ s3_virge_bitblt(virge, 16, val);
+ }
+ break;
+ case FIFO_WRITE_DWORD:
+ if (((fifo->addr_type & FIFO_ADDR) & 0xfffc) < 0x8000)
+ {
+ if (virge->s3d.cmd_set & CMD_SET_MS)
+ s3_virge_bitblt(virge, 32, ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) | ((val & 0x000000ff) << 24));
+ else
+ s3_virge_bitblt(virge, 32, val);
+ }
+ else
+ {
+ switch ((fifo->addr_type & FIFO_ADDR) & 0xfffc)
+ {
+ case 0xa000: case 0xa004: case 0xa008: case 0xa00c:
+ case 0xa010: case 0xa014: case 0xa018: case 0xa01c:
+ case 0xa020: case 0xa024: case 0xa028: case 0xa02c:
+ case 0xa030: case 0xa034: case 0xa038: case 0xa03c:
+ case 0xa040: case 0xa044: case 0xa048: case 0xa04c:
+ case 0xa050: case 0xa054: case 0xa058: case 0xa05c:
+ case 0xa060: case 0xa064: case 0xa068: case 0xa06c:
+ case 0xa070: case 0xa074: case 0xa078: case 0xa07c:
+ case 0xa080: case 0xa084: case 0xa088: case 0xa08c:
+ case 0xa090: case 0xa094: case 0xa098: case 0xa09c:
+ case 0xa0a0: case 0xa0a4: case 0xa0a8: case 0xa0ac:
+ case 0xa0b0: case 0xa0b4: case 0xa0b8: case 0xa0bc:
+ case 0xa0c0: case 0xa0c4: case 0xa0c8: case 0xa0cc:
+ case 0xa0d0: case 0xa0d4: case 0xa0d8: case 0xa0dc:
+ case 0xa0e0: case 0xa0e4: case 0xa0e8: case 0xa0ec:
+ case 0xa0f0: case 0xa0f4: case 0xa0f8: case 0xa0fc:
+ case 0xa100: case 0xa104: case 0xa108: case 0xa10c:
+ case 0xa110: case 0xa114: case 0xa118: case 0xa11c:
+ case 0xa120: case 0xa124: case 0xa128: case 0xa12c:
+ case 0xa130: case 0xa134: case 0xa138: case 0xa13c:
+ case 0xa140: case 0xa144: case 0xa148: case 0xa14c:
+ case 0xa150: case 0xa154: case 0xa158: case 0xa15c:
+ case 0xa160: case 0xa164: case 0xa168: case 0xa16c:
+ case 0xa170: case 0xa174: case 0xa178: case 0xa17c:
+ case 0xa180: case 0xa184: case 0xa188: case 0xa18c:
+ case 0xa190: case 0xa194: case 0xa198: case 0xa19c:
+ case 0xa1a0: case 0xa1a4: case 0xa1a8: case 0xa1ac:
+ case 0xa1b0: case 0xa1b4: case 0xa1b8: case 0xa1bc:
+ case 0xa1c0: case 0xa1c4: case 0xa1c8: case 0xa1cc:
+ case 0xa1d0: case 0xa1d4: case 0xa1d8: case 0xa1dc:
+ case 0xa1e0: case 0xa1e4: case 0xa1e8: case 0xa1ec:
+ case 0xa1f0: case 0xa1f4: case 0xa1f8: case 0xa1fc:
+ {
+ int x = (fifo->addr_type & FIFO_ADDR) & 4;
+ int y = ((fifo->addr_type & FIFO_ADDR) >> 3) & 7;
+ virge->s3d.pattern_8[y*8 + x] = val & 0xff;
+ virge->s3d.pattern_8[y*8 + x + 1] = val >> 8;
+ virge->s3d.pattern_8[y*8 + x + 2] = val >> 16;
+ virge->s3d.pattern_8[y*8 + x + 3] = val >> 24;
+
+ x = ((fifo->addr_type & FIFO_ADDR) >> 1) & 6;
+ y = ((fifo->addr_type & FIFO_ADDR) >> 4) & 7;
+ virge->s3d.pattern_16[y*8 + x] = val & 0xffff;
+ virge->s3d.pattern_16[y*8 + x + 1] = val >> 16;
+
+ x = ((fifo->addr_type & FIFO_ADDR) >> 2) & 7;
+ y = ((fifo->addr_type & FIFO_ADDR) >> 5) & 7;
+ virge->s3d.pattern_32[y*8 + x] = val & 0xffffff;
+ }
+ break;
+
+ case 0xa4d4: case 0xa8d4:
+ virge->s3d.src_base = val & 0x3ffff8;
+ break;
+ case 0xa4d8: case 0xa8d8:
+ virge->s3d.dest_base = val & 0x3ffff8;
+ break;
+ case 0xa4dc: case 0xa8dc:
+ virge->s3d.clip_l = (val >> 16) & 0x7ff;
+ virge->s3d.clip_r = val & 0x7ff;
+ break;
+ case 0xa4e0: case 0xa8e0:
+ virge->s3d.clip_t = (val >> 16) & 0x7ff;
+ virge->s3d.clip_b = val & 0x7ff;
+ break;
+ case 0xa4e4: case 0xa8e4:
+ virge->s3d.dest_str = (val >> 16) & 0xff8;
+ virge->s3d.src_str = val & 0xff8;
+ break;
+ case 0xa4e8: case 0xace8:
+ virge->s3d.mono_pat_0 = val;
+ break;
+ case 0xa4ec: case 0xacec:
+ virge->s3d.mono_pat_1 = val;
+ break;
+ case 0xa4f0: case 0xacf0:
+ virge->s3d.pat_bg_clr = val;
+ break;
+ case 0xa4f4: case 0xa8f4: case 0xacf4:
+ virge->s3d.pat_fg_clr = val;
+ break;
+ case 0xa4f8:
+ virge->s3d.src_bg_clr = val;
+ break;
+ case 0xa4fc:
+ virge->s3d.src_fg_clr = val;
+ break;
+ case 0xa500: case 0xa900:
+ virge->s3d.cmd_set = val;
+ if (!(val & CMD_SET_AE))
+ s3_virge_bitblt(virge, -1, 0);
+ break;
+ case 0xa504:
+ virge->s3d.r_width = (val >> 16) & 0x7ff;
+ virge->s3d.r_height = val & 0x7ff;
+ break;
+ case 0xa508:
+ virge->s3d.rsrc_x = (val >> 16) & 0x7ff;
+ virge->s3d.rsrc_y = val & 0x7ff;
+ break;
+ case 0xa50c:
+ virge->s3d.rdest_x = (val >> 16) & 0x7ff;
+ virge->s3d.rdest_y = val & 0x7ff;
+ if (virge->s3d.cmd_set & CMD_SET_AE)
+ s3_virge_bitblt(virge, -1, 0);
+ break;
+ case 0xa96c:
+ virge->s3d.lxend0 = (val >> 16) & 0x7ff;
+ virge->s3d.lxend1 = val & 0x7ff;
+ break;
+ case 0xa970:
+ virge->s3d.ldx = (int32_t)val;
+ break;
+ case 0xa974:
+ virge->s3d.lxstart = val;
+ break;
+ case 0xa978:
+ virge->s3d.lystart = val & 0x7ff;
+ break;
+ case 0xa97c:
+ virge->s3d.lycnt = val & 0x7ff;
+ virge->s3d.line_dir = val >> 31;
+ if (virge->s3d.cmd_set & CMD_SET_AE)
+ s3_virge_bitblt(virge, -1, 0);
+ break;
+
+ case 0xad00:
+ virge->s3d.cmd_set = val;
+ if (!(val & CMD_SET_AE))
+ s3_virge_bitblt(virge, -1, 0);
+ break;
+ case 0xad68:
+ virge->s3d.prdx = val;
+ break;
+ case 0xad6c:
+ virge->s3d.prxstart = val;
+ break;
+ case 0xad70:
+ virge->s3d.pldx = val;
+ break;
+ case 0xad74:
+ virge->s3d.plxstart = val;
+ break;
+ case 0xad78:
+ virge->s3d.pystart = val & 0x7ff;
+ break;
+ case 0xad7c:
+ virge->s3d.pycnt = val & 0x300007ff;
+ if (virge->s3d.cmd_set & CMD_SET_AE)
+ s3_virge_bitblt(virge, -1, 0);
+ break;
+
+ case 0xb4d4:
+ virge->s3d_tri.z_base = val & 0x3ffff8;
+ break;
+ case 0xb4d8:
+ virge->s3d_tri.dest_base = val & 0x3ffff8;
+ break;
+ case 0xb4dc:
+ virge->s3d_tri.clip_l = (val >> 16) & 0x7ff;
+ virge->s3d_tri.clip_r = val & 0x7ff;
+ break;
+ case 0xb4e0:
+ virge->s3d_tri.clip_t = (val >> 16) & 0x7ff;
+ virge->s3d_tri.clip_b = val & 0x7ff;
+ break;
+ case 0xb4e4:
+ virge->s3d_tri.dest_str = (val >> 16) & 0xff8;
+ virge->s3d.src_str = val & 0xff8;
+ break;
+ case 0xb4e8:
+ virge->s3d_tri.z_str = val & 0xff8;
+ break;
+ case 0xb4ec:
+ virge->s3d_tri.tex_base = val & 0x3ffff8;
+ break;
+ case 0xb4f0:
+ virge->s3d_tri.tex_bdr_clr = val & 0xffffff;
+ break;
+ case 0xb500:
+ virge->s3d_tri.cmd_set = val;
+ if (!(val & CMD_SET_AE))
+ queue_triangle(virge);
+ break;
+ case 0xb504:
+ virge->s3d_tri.tbv = val & 0xfffff;
+ break;
+ case 0xb508:
+ virge->s3d_tri.tbu = val & 0xfffff;
+ break;
+ case 0xb50c:
+ virge->s3d_tri.TdWdX = val;
+ break;
+ case 0xb510:
+ virge->s3d_tri.TdWdY = val;
+ break;
+ case 0xb514:
+ virge->s3d_tri.tws = val;
+ break;
+ case 0xb518:
+ virge->s3d_tri.TdDdX = val;
+ break;
+ case 0xb51c:
+ virge->s3d_tri.TdVdX = val;
+ break;
+ case 0xb520:
+ virge->s3d_tri.TdUdX = val;
+ break;
+ case 0xb524:
+ virge->s3d_tri.TdDdY = val;
+ break;
+ case 0xb528:
+ virge->s3d_tri.TdVdY = val;
+ break;
+ case 0xb52c:
+ virge->s3d_tri.TdUdY = val;
+ break;
+ case 0xb530:
+ virge->s3d_tri.tds = val;
+ break;
+ case 0xb534:
+ virge->s3d_tri.tvs = val;
+ break;
+ case 0xb538:
+ virge->s3d_tri.tus = val;
+ break;
+ case 0xb53c:
+ virge->s3d_tri.TdGdX = val >> 16;
+ virge->s3d_tri.TdBdX = val & 0xffff;
+ break;
+ case 0xb540:
+ virge->s3d_tri.TdAdX = val >> 16;
+ virge->s3d_tri.TdRdX = val & 0xffff;
+ break;
+ case 0xb544:
+ virge->s3d_tri.TdGdY = val >> 16;
+ virge->s3d_tri.TdBdY = val & 0xffff;
+ break;
+ case 0xb548:
+ virge->s3d_tri.TdAdY = val >> 16;
+ virge->s3d_tri.TdRdY = val & 0xffff;
+ break;
+ case 0xb54c:
+ virge->s3d_tri.tgs = (val >> 16) & 0xffff;
+ virge->s3d_tri.tbs = val & 0xffff;
+ break;
+ case 0xb550:
+ virge->s3d_tri.tas = (val >> 16) & 0xffff;
+ virge->s3d_tri.trs = val & 0xffff;
+ break;
+
+ case 0xb554:
+ virge->s3d_tri.TdZdX = val;
+ break;
+ case 0xb558:
+ virge->s3d_tri.TdZdY = val;
+ break;
+ case 0xb55c:
+ virge->s3d_tri.tzs = val;
+ break;
+ case 0xb560:
+ virge->s3d_tri.TdXdY12 = val;
+ break;
+ case 0xb564:
+ virge->s3d_tri.txend12 = val;
+ break;
+ case 0xb568:
+ virge->s3d_tri.TdXdY01 = val;
+ break;
+ case 0xb56c:
+ virge->s3d_tri.txend01 = val;
+ break;
+ case 0xb570:
+ virge->s3d_tri.TdXdY02 = val;
+ break;
+ case 0xb574:
+ virge->s3d_tri.txs = val;
+ break;
+ case 0xb578:
+ virge->s3d_tri.tys = val;
+ break;
+ case 0xb57c:
+ virge->s3d_tri.ty01 = (val >> 16) & 0x7ff;
+ virge->s3d_tri.ty12 = val & 0x7ff;
+ virge->s3d_tri.tlr = val >> 31;
+ if (virge->s3d_tri.cmd_set & CMD_SET_AE)
+ queue_triangle(virge);
+ break;
+ }
+ }
+ break;
+ }
+
+ virge->fifo_read_idx++;
+ fifo->addr_type = FIFO_INVALID;
+
+ if (FIFO_ENTRIES > 0xe000)
+ thread_set_event(virge->fifo_not_full_event);
+
+ end_time = timer_read();
+ virge_time += end_time - start_time;
+ }
+ virge->virge_busy = 0;
+ virge->subsys_stat |= INT_FIFO_EMP | INT_3DF_EMP;
+ s3_virge_update_irqs(virge);
+ }
+}
+
+static void s3_virge_queue(virge_t *virge, uint32_t addr, uint32_t val, uint32_t type)
+{
+ fifo_entry_t *fifo = &virge->fifo[virge->fifo_write_idx & FIFO_MASK];
+
+ if (FIFO_FULL)
+ {
+ thread_reset_event(virge->fifo_not_full_event);
+ if (FIFO_FULL)
+ {
+ thread_wait_event(virge->fifo_not_full_event, -1); /*Wait for room in ringbuffer*/
+ }
+ }
+
+ fifo->val = val;
+ fifo->addr_type = (addr & FIFO_ADDR) | type;
+
+ virge->fifo_write_idx++;
+
+ if (FIFO_ENTRIES > 0xe000)
+ wake_fifo_thread(virge);
+ if (FIFO_ENTRIES > 0xe000 || FIFO_ENTRIES < 8)
+ wake_fifo_thread(virge);
+}
+
+static void s3_virge_mmio_write(uint32_t addr, uint8_t val, void *p)
+{
+ virge_t *virge = (virge_t *)p;
+
+// pclog("New MMIO writeb %08X %02X %04x(%08x):%08x\n", addr, val, CS, cs, pc);
+ reg_writes++;
+ if ((addr & 0xfffc) < 0x8000)
+ {
+ s3_virge_queue(virge, addr, val, FIFO_WRITE_BYTE);
+ }
+ else switch (addr & 0xffff)
+ {
+ case 0x83b0: case 0x83b1: case 0x83b2: case 0x83b3:
+ case 0x83b4: case 0x83b5: case 0x83b6: case 0x83b7:
+ case 0x83b8: case 0x83b9: case 0x83ba: case 0x83bb:
+ case 0x83bc: case 0x83bd: case 0x83be: case 0x83bf:
+ case 0x83c0: case 0x83c1: case 0x83c2: case 0x83c3:
+ case 0x83c4: case 0x83c5: case 0x83c6: case 0x83c7:
+ case 0x83c8: case 0x83c9: case 0x83ca: case 0x83cb:
+ case 0x83cc: case 0x83cd: case 0x83ce: case 0x83cf:
+ case 0x83d0: case 0x83d1: case 0x83d2: case 0x83d3:
+ case 0x83d4: case 0x83d5: case 0x83d6: case 0x83d7:
+ case 0x83d8: case 0x83d9: case 0x83da: case 0x83db:
+ case 0x83dc: case 0x83dd: case 0x83de: case 0x83df:
+ s3_virge_out(addr & 0x3ff, val, p);
+ break;
+ }
+
+
+}
+static void s3_virge_mmio_write_w(uint32_t addr, uint16_t val, void *p)
+{
+ virge_t *virge = (virge_t *)p;
+ reg_writes++;
+// pclog("New MMIO writew %08X %04X %04x(%08x):%08x\n", addr, val, CS, cs, pc);
+ if ((addr & 0xfffc) < 0x8000)
+ {
+ s3_virge_queue(virge, addr, val, FIFO_WRITE_WORD);
+ }
+ else switch (addr & 0xfffe)
+ {
+ case 0x83d4:
+ s3_virge_mmio_write(addr, val, p);
+ s3_virge_mmio_write(addr + 1, val >> 8, p);
+ break;
+ }
+}
+static void s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *p)
+{
+ virge_t *virge = (virge_t *)p;
+ svga_t *svga = &virge->svga;
+ reg_writes++;
+// if ((addr & 0xfffc) >= 0xb400 && (addr & 0xfffc) < 0xb800)
+// pclog("New MMIO writel %08X %08X %04x(%08x):%08x\n", addr, val, CS, cs, pc);
+
+ if ((addr & 0xfffc) < 0x8000)
+ {
+ s3_virge_queue(virge, addr, val, FIFO_WRITE_DWORD);
+ }
+ else if ((addr & 0xe000) == 0xa000)
+ {
+ s3_virge_queue(virge, addr, val, FIFO_WRITE_DWORD);
+ }
+ else switch (addr & 0xfffc)
+ {
+ case 0x8180:
+ virge->streams.pri_ctrl = val;
+ svga_recalctimings(svga);
+ svga->fullchange = changeframecount;
+ break;
+ case 0x8184:
+ virge->streams.chroma_ctrl = val;
+ break;
+ case 0x8190:
+ virge->streams.sec_ctrl = val;
+ virge->streams.dda_horiz_accumulator = val & 0xfff;
+ if (val & (1 << 11))
+ virge->streams.dda_horiz_accumulator |= 0xfffff800;
+ virge->streams.sdif = (val >> 24) & 7;
+ break;
+ case 0x8194:
+ virge->streams.chroma_upper_bound = val;
+ break;
+ case 0x8198:
+ virge->streams.sec_filter = val;
+ virge->streams.k1_horiz_scale = val & 0x7ff;
+ if (val & (1 << 10))
+ virge->streams.k1_horiz_scale |= 0xfffff800;
+ virge->streams.k2_horiz_scale = (val >> 16) & 0x7ff;
+ if ((val >> 16) & (1 << 10))
+ virge->streams.k2_horiz_scale |= 0xfffff800;
+ break;
+ case 0x81a0:
+ virge->streams.blend_ctrl = val;
+ break;
+ case 0x81c0:
+// pclog("Write pri_fb0 %08x\n", val);
+ virge->streams.pri_fb0 = val & 0x3fffff;
+ svga_recalctimings(svga);
+ svga->fullchange = changeframecount;
+ break;
+ case 0x81c4:
+// pclog("Write pri_fb1 %08x\n", val);
+ virge->streams.pri_fb1 = val & 0x3fffff;
+ svga_recalctimings(svga);
+ svga->fullchange = changeframecount;
+ break;
+ case 0x81c8:
+ virge->streams.pri_stride = val & 0xfff;
+ svga_recalctimings(svga);
+ svga->fullchange = changeframecount;
+ break;
+ case 0x81cc:
+// pclog("Write buffer_ctrl %08x\n", val);
+ virge->streams.buffer_ctrl = val;
+ svga_recalctimings(svga);
+ svga->fullchange = changeframecount;
+ break;
+ case 0x81d0:
+ virge->streams.sec_fb0 = val;
+ svga_recalctimings(svga);
+ svga->fullchange = changeframecount;
+ break;
+ case 0x81d4:
+ virge->streams.sec_fb1 = val;
+ svga_recalctimings(svga);
+ svga->fullchange = changeframecount;
+ break;
+ case 0x81d8:
+ virge->streams.sec_stride = val;
+ svga_recalctimings(svga);
+ svga->fullchange = changeframecount;
+ break;
+ case 0x81dc:
+ virge->streams.overlay_ctrl = val;
+ break;
+ case 0x81e0:
+ virge->streams.k1_vert_scale = val & 0x7ff;
+ if (val & (1 << 10))
+ virge->streams.k1_vert_scale |= 0xfffff800;
+ break;
+ case 0x81e4:
+ virge->streams.k2_vert_scale = val & 0x7ff;
+ if (val & (1 << 10))
+ virge->streams.k2_vert_scale |= 0xfffff800;
+ break;
+ case 0x81e8:
+ virge->streams.dda_vert_accumulator = val & 0xfff;
+ if (val & (1 << 11))
+ virge->streams.dda_vert_accumulator |= 0xfffff800;
+ break;
+ case 0x81ec:
+ virge->streams.fifo_ctrl = val;
+ break;
+ case 0x81f0:
+ virge->streams.pri_start = val;
+ virge->streams.pri_x = (val >> 16) & 0x7ff;
+ virge->streams.pri_y = val & 0x7ff;
+ svga_recalctimings(svga);
+ svga->fullchange = changeframecount;
+ break;
+ case 0x81f4:
+ virge->streams.pri_size = val;
+ virge->streams.pri_w = (val >> 16) & 0x7ff;
+ virge->streams.pri_h = val & 0x7ff;
+ svga_recalctimings(svga);
+ svga->fullchange = changeframecount;
+ break;
+ case 0x81f8:
+ virge->streams.sec_start = val;
+ virge->streams.sec_x = (val >> 16) & 0x7ff;
+ virge->streams.sec_y = val & 0x7ff;
+ svga_recalctimings(svga);
+ svga->fullchange = changeframecount;
+ break;
+ case 0x81fc:
+ virge->streams.sec_size = val;
+ virge->streams.sec_w = (val >> 16) & 0x7ff;
+ virge->streams.sec_h = val & 0x7ff;
+ svga_recalctimings(svga);
+ svga->fullchange = changeframecount;
+ break;
+
+ case 0x8504:
+ virge->subsys_stat &= ~(val & 0xff);
+ virge->subsys_cntl = (val >> 8);
+ s3_virge_update_irqs(virge);
+ break;
+
+ case 0xa000: case 0xa004: case 0xa008: case 0xa00c:
+ case 0xa010: case 0xa014: case 0xa018: case 0xa01c:
+ case 0xa020: case 0xa024: case 0xa028: case 0xa02c:
+ case 0xa030: case 0xa034: case 0xa038: case 0xa03c:
+ case 0xa040: case 0xa044: case 0xa048: case 0xa04c:
+ case 0xa050: case 0xa054: case 0xa058: case 0xa05c:
+ case 0xa060: case 0xa064: case 0xa068: case 0xa06c:
+ case 0xa070: case 0xa074: case 0xa078: case 0xa07c:
+ case 0xa080: case 0xa084: case 0xa088: case 0xa08c:
+ case 0xa090: case 0xa094: case 0xa098: case 0xa09c:
+ case 0xa0a0: case 0xa0a4: case 0xa0a8: case 0xa0ac:
+ case 0xa0b0: case 0xa0b4: case 0xa0b8: case 0xa0bc:
+ case 0xa0c0: case 0xa0c4: case 0xa0c8: case 0xa0cc:
+ case 0xa0d0: case 0xa0d4: case 0xa0d8: case 0xa0dc:
+ case 0xa0e0: case 0xa0e4: case 0xa0e8: case 0xa0ec:
+ case 0xa0f0: case 0xa0f4: case 0xa0f8: case 0xa0fc:
+ case 0xa100: case 0xa104: case 0xa108: case 0xa10c:
+ case 0xa110: case 0xa114: case 0xa118: case 0xa11c:
+ case 0xa120: case 0xa124: case 0xa128: case 0xa12c:
+ case 0xa130: case 0xa134: case 0xa138: case 0xa13c:
+ case 0xa140: case 0xa144: case 0xa148: case 0xa14c:
+ case 0xa150: case 0xa154: case 0xa158: case 0xa15c:
+ case 0xa160: case 0xa164: case 0xa168: case 0xa16c:
+ case 0xa170: case 0xa174: case 0xa178: case 0xa17c:
+ case 0xa180: case 0xa184: case 0xa188: case 0xa18c:
+ case 0xa190: case 0xa194: case 0xa198: case 0xa19c:
+ case 0xa1a0: case 0xa1a4: case 0xa1a8: case 0xa1ac:
+ case 0xa1b0: case 0xa1b4: case 0xa1b8: case 0xa1bc:
+ case 0xa1c0: case 0xa1c4: case 0xa1c8: case 0xa1cc:
+ case 0xa1d0: case 0xa1d4: case 0xa1d8: case 0xa1dc:
+ case 0xa1e0: case 0xa1e4: case 0xa1e8: case 0xa1ec:
+ case 0xa1f0: case 0xa1f4: case 0xa1f8: case 0xa1fc:
+ {
+ int x = addr & 4;
+ int y = (addr >> 3) & 7;
+ virge->s3d.pattern_8[y*8 + x] = val & 0xff;
+ virge->s3d.pattern_8[y*8 + x + 1] = val >> 8;
+ virge->s3d.pattern_8[y*8 + x + 2] = val >> 16;
+ virge->s3d.pattern_8[y*8 + x + 3] = val >> 24;
+
+ x = (addr >> 1) & 6;
+ y = (addr >> 4) & 7;
+ virge->s3d.pattern_16[y*8 + x] = val & 0xffff;
+ virge->s3d.pattern_16[y*8 + x + 1] = val >> 16;
+
+ x = (addr >> 2) & 7;
+ y = (addr >> 5) & 7;
+ virge->s3d.pattern_32[y*8 + x] = val & 0xffffff;
+ }
+ break;
+
+ case 0xa4d4: case 0xa8d4:
+ virge->s3d.src_base = val & 0x3ffff8;
+ break;
+ case 0xa4d8: case 0xa8d8:
+ virge->s3d.dest_base = val & 0x3ffff8;
+ break;
+ case 0xa4dc: case 0xa8dc:
+ virge->s3d.clip_l = (val >> 16) & 0x7ff;
+ virge->s3d.clip_r = val & 0x7ff;
+ break;
+ case 0xa4e0: case 0xa8e0:
+ virge->s3d.clip_t = (val >> 16) & 0x7ff;
+ virge->s3d.clip_b = val & 0x7ff;
+ break;
+ case 0xa4e4: case 0xa8e4:
+ virge->s3d.dest_str = (val >> 16) & 0xff8;
+ virge->s3d.src_str = val & 0xff8;
+ break;
+ case 0xa4e8: case 0xace8:
+ virge->s3d.mono_pat_0 = val;
+ break;
+ case 0xa4ec: case 0xacec:
+ virge->s3d.mono_pat_1 = val;
+ break;
+ case 0xa4f0: case 0xacf0:
+ virge->s3d.pat_bg_clr = val;
+ break;
+ case 0xa4f4: case 0xa8f4: case 0xacf4:
+ virge->s3d.pat_fg_clr = val;
+ break;
+ case 0xa4f8:
+ virge->s3d.src_bg_clr = val;
+ break;
+ case 0xa4fc:
+ virge->s3d.src_fg_clr = val;
+ break;
+ case 0xa500: case 0xa900:
+ virge->s3d.cmd_set = val;
+ if (!(val & CMD_SET_AE))
+ s3_virge_bitblt(virge, -1, 0);
+ break;
+ case 0xa504:
+ virge->s3d.r_width = (val >> 16) & 0x7ff;
+ virge->s3d.r_height = val & 0x7ff;
+ break;
+ case 0xa508:
+ virge->s3d.rsrc_x = (val >> 16) & 0x7ff;
+ virge->s3d.rsrc_y = val & 0x7ff;
+ break;
+ case 0xa50c:
+ virge->s3d.rdest_x = (val >> 16) & 0x7ff;
+ virge->s3d.rdest_y = val & 0x7ff;
+ if (virge->s3d.cmd_set & CMD_SET_AE)
+ s3_virge_bitblt(virge, -1, 0);
+ break;
+ case 0xa96c:
+ virge->s3d.lxend0 = (val >> 16) & 0x7ff;
+ virge->s3d.lxend1 = val & 0x7ff;
+ break;
+ case 0xa970:
+ virge->s3d.ldx = (int32_t)val;
+ break;
+ case 0xa974:
+ virge->s3d.lxstart = val;
+ break;
+ case 0xa978:
+ virge->s3d.lystart = val & 0x7ff;
+ break;
+ case 0xa97c:
+ virge->s3d.lycnt = val & 0x7ff;
+ virge->s3d.line_dir = val >> 31;
+ if (virge->s3d.cmd_set & CMD_SET_AE)
+ s3_virge_bitblt(virge, -1, 0);
+ break;
+
+ case 0xad00:
+ virge->s3d.cmd_set = val;
+ if (!(val & CMD_SET_AE))
+ s3_virge_bitblt(virge, -1, 0);
+ break;
+ case 0xad68:
+ virge->s3d.prdx = val;
+ break;
+ case 0xad6c:
+ virge->s3d.prxstart = val;
+ break;
+ case 0xad70:
+ virge->s3d.pldx = val;
+ break;
+ case 0xad74:
+ virge->s3d.plxstart = val;
+ break;
+ case 0xad78:
+ virge->s3d.pystart = val & 0x7ff;
+ break;
+ case 0xad7c:
+ virge->s3d.pycnt = val & 0x300007ff;
+ if (virge->s3d.cmd_set & CMD_SET_AE)
+ s3_virge_bitblt(virge, -1, 0);
+ break;
+
+ case 0xb4d4:
+ virge->s3d_tri.z_base = val & 0x3ffff8;
+ break;
+ case 0xb4d8:
+ virge->s3d_tri.dest_base = val & 0x3ffff8;
+ break;
+ case 0xb4dc:
+ virge->s3d_tri.clip_l = (val >> 16) & 0x7ff;
+ virge->s3d_tri.clip_r = val & 0x7ff;
+ break;
+ case 0xb4e0:
+ virge->s3d_tri.clip_t = (val >> 16) & 0x7ff;
+ virge->s3d_tri.clip_b = val & 0x7ff;
+ break;
+ case 0xb4e4:
+ virge->s3d_tri.dest_str = (val >> 16) & 0xff8;
+ virge->s3d.src_str = val & 0xff8;
+ break;
+ case 0xb4e8:
+ virge->s3d_tri.z_str = val & 0xff8;
+ break;
+ case 0xb4ec:
+ virge->s3d_tri.tex_base = val & 0x3ffff8;
+ break;
+ case 0xb4f0:
+ virge->s3d_tri.tex_bdr_clr = val & 0xffffff;
+ break;
+ case 0xb500:
+ virge->s3d_tri.cmd_set = val;
+ if (!(val & CMD_SET_AE))
+ queue_triangle(virge);
+/* {
+ thread_set_event(virge->wake_render_thread);
+ thread_wait_event(virge->wake_main_thread, -1);
+ } */
+// s3_virge_triangle(virge);
+ break;
+ case 0xb504:
+ virge->s3d_tri.tbv = val & 0xfffff;
+ break;
+ case 0xb508:
+ virge->s3d_tri.tbu = val & 0xfffff;
+ break;
+ case 0xb50c:
+ virge->s3d_tri.TdWdX = val;
+ break;
+ case 0xb510:
+ virge->s3d_tri.TdWdY = val;
+ break;
+ case 0xb514:
+ virge->s3d_tri.tws = val;
+ break;
+ case 0xb518:
+ virge->s3d_tri.TdDdX = val;
+ break;
+ case 0xb51c:
+ virge->s3d_tri.TdVdX = val;
+ break;
+ case 0xb520:
+ virge->s3d_tri.TdUdX = val;
+ break;
+ case 0xb524:
+ virge->s3d_tri.TdDdY = val;
+ break;
+ case 0xb528:
+ virge->s3d_tri.TdVdY = val;
+ break;
+ case 0xb52c:
+ virge->s3d_tri.TdUdY = val;
+ break;
+ case 0xb530:
+ virge->s3d_tri.tds = val;
+ break;
+ case 0xb534:
+ virge->s3d_tri.tvs = val;
+ break;
+ case 0xb538:
+ virge->s3d_tri.tus = val;
+ break;
+ case 0xb53c:
+ virge->s3d_tri.TdGdX = val >> 16;
+ virge->s3d_tri.TdBdX = val & 0xffff;
+ break;
+ case 0xb540:
+ virge->s3d_tri.TdAdX = val >> 16;
+ virge->s3d_tri.TdRdX = val & 0xffff;
+ break;
+ case 0xb544:
+ virge->s3d_tri.TdGdY = val >> 16;
+ virge->s3d_tri.TdBdY = val & 0xffff;
+ break;
+ case 0xb548:
+ virge->s3d_tri.TdAdY = val >> 16;
+ virge->s3d_tri.TdRdY = val & 0xffff;
+ break;
+ case 0xb54c:
+ virge->s3d_tri.tgs = (val >> 16) & 0xffff;
+ virge->s3d_tri.tbs = val & 0xffff;
+ break;
+ case 0xb550:
+ virge->s3d_tri.tas = (val >> 16) & 0xffff;
+ virge->s3d_tri.trs = val & 0xffff;
+ break;
+
+ case 0xb554:
+ virge->s3d_tri.TdZdX = val;
+ break;
+ case 0xb558:
+ virge->s3d_tri.TdZdY = val;
+ break;
+ case 0xb55c:
+ virge->s3d_tri.tzs = val;
+ break;
+ case 0xb560:
+ virge->s3d_tri.TdXdY12 = val;
+ break;
+ case 0xb564:
+ virge->s3d_tri.txend12 = val;
+ break;
+ case 0xb568:
+ virge->s3d_tri.TdXdY01 = val;
+ break;
+ case 0xb56c:
+ virge->s3d_tri.txend01 = val;
+ break;
+ case 0xb570:
+ virge->s3d_tri.TdXdY02 = val;
+ break;
+ case 0xb574:
+ virge->s3d_tri.txs = val;
+ break;
+ case 0xb578:
+ virge->s3d_tri.tys = val;
+ break;
+ case 0xb57c:
+ virge->s3d_tri.ty01 = (val >> 16) & 0x7ff;
+ virge->s3d_tri.ty12 = val & 0x7ff;
+ virge->s3d_tri.tlr = val >> 31;
+ if (virge->s3d_tri.cmd_set & CMD_SET_AE)
+ queue_triangle(virge);
+/* {
+ thread_set_event(virge->wake_render_thread);
+ thread_wait_event(virge->wake_main_thread, -1);
+ }*/
+
+// s3_virge_triangle(virge);
+ break;
+ }
+}
+
+#define READ(addr, val) \
+ do \
+ { \
+ switch (bpp) \
+ { \
+ case 0: /*8 bpp*/ \
+ val = vram[addr & svga->vram_mask]; \
+ break; \
+ case 1: /*16 bpp*/ \
+ val = *(uint16_t *)&vram[addr & svga->vram_mask]; \
+ break; \
+ case 2: /*24 bpp*/ \
+ val = (*(uint32_t *)&vram[addr & svga->vram_mask]) & 0xffffff; \
+ break; \
+ } \
+ } while (0)
+
+#define Z_READ(addr) *(uint16_t *)&vram[addr & svga->vram_mask]
+
+#define Z_WRITE(addr, val) if (!(s3d_tri->cmd_set & CMD_SET_ZB_MODE)) *(uint16_t *)&vram[addr & svga->vram_mask] = val
+
+#define CLIP(x, y) \
+ do \
+ { \
+ if ((virge->s3d.cmd_set & CMD_SET_HC) && \
+ (x < virge->s3d.clip_l || \
+ x > virge->s3d.clip_r || \
+ y < virge->s3d.clip_t || \
+ y > virge->s3d.clip_b)) \
+ update = 0; \
+ } while (0)
+
+#define CLIP_3D(x, y) \
+ do \
+ { \
+ if ((s3d_tri->cmd_set & CMD_SET_HC) && \
+ (x < s3d_tri->clip_l || \
+ x > s3d_tri->clip_r || \
+ y < s3d_tri->clip_t || \
+ y > s3d_tri->clip_b)) \
+ update = 0; \
+ } while (0)
+
+#define Z_CLIP(Zzb, Zs) \
+ do \
+ { \
+ if (!(s3d_tri->cmd_set & CMD_SET_ZB_MODE)) \
+ switch ((s3d_tri->cmd_set >> 20) & 7) \
+ { \
+ case 0: update = 0; break; \
+ case 1: if (Zs <= Zzb) update = 0; else Zzb = Zs; break; \
+ case 2: if (Zs != Zzb) update = 0; else Zzb = Zs; break; \
+ case 3: if (Zs < Zzb) update = 0; else Zzb = Zs; break; \
+ case 4: if (Zs >= Zzb) update = 0; else Zzb = Zs; break; \
+ case 5: if (Zs == Zzb) update = 0; else Zzb = Zs; break; \
+ case 6: if (Zs > Zzb) update = 0; else Zzb = Zs; break; \
+ case 7: update = 1; Zzb = Zs; break; \
+ } \
+ } while (0)
+
+#define MIX() \
+ do \
+ { \
+ int c; \
+ for (c = 0; c < 24; c++) \
+ { \
+ int d = (dest & (1 << c)) ? 1 : 0; \
+ if (source & (1 << c)) d |= 2; \
+ if (pattern & (1 << c)) d |= 4; \
+ if (virge->s3d.rop & (1 << d)) out |= (1 << c); \
+ } \
+ } while (0)
+
+#define WRITE(addr, val) \
+ do \
+ { \
+ switch (bpp) \
+ { \
+ case 0: /*8 bpp*/ \
+ vram[addr & svga->vram_mask] = val; \
+ virge->svga.changedvram[(addr & svga->vram_mask) >> 12] = changeframecount; \
+ break; \
+ case 1: /*16 bpp*/ \
+ *(uint16_t *)&vram[addr & svga->vram_mask] = val; \
+ virge->svga.changedvram[(addr & svga->vram_mask) >> 12] = changeframecount; \
+ break; \
+ case 2: /*24 bpp*/ \
+ *(uint32_t *)&vram[addr & svga->vram_mask] = (val & 0xffffff) | \
+ (vram[(addr + 3) & svga->vram_mask] << 24); \
+ virge->svga.changedvram[(addr & svga->vram_mask) >> 12] = changeframecount; \
+ break; \
+ } \
+ } while (0)
+
+static void s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat)
+{
+ svga_t *svga = &virge->svga;
+ uint8_t *vram = virge->svga.vram;
+ uint32_t mono_pattern[64];
+ int count_mask;
+ int x_inc = (virge->s3d.cmd_set & CMD_SET_XP) ? 1 : -1;
+ int y_inc = (virge->s3d.cmd_set & CMD_SET_YP) ? 1 : -1;
+ int bpp;
+ int x_mul;
+ int cpu_dat_shift;
+ uint32_t *pattern_data;
+ uint32_t src_fg_clr, src_bg_clr;
+
+ switch (virge->s3d.cmd_set & CMD_SET_FORMAT_MASK)
+ {
+ case CMD_SET_FORMAT_8:
+ bpp = 0;
+ x_mul = 1;
+ cpu_dat_shift = 8;
+ pattern_data = virge->s3d.pattern_8;
+ src_fg_clr = virge->s3d.src_fg_clr & 0xff;
+ src_bg_clr = virge->s3d.src_bg_clr & 0xff;
+ break;
+ case CMD_SET_FORMAT_16:
+ bpp = 1;
+ x_mul = 2;
+ cpu_dat_shift = 16;
+ pattern_data = virge->s3d.pattern_16;
+ src_fg_clr = virge->s3d.src_fg_clr & 0xffff;
+ src_bg_clr = virge->s3d.src_bg_clr & 0xffff;
+ break;
+ case CMD_SET_FORMAT_24:
+ default:
+ bpp = 2;
+ x_mul = 3;
+ cpu_dat_shift = 24;
+ pattern_data = virge->s3d.pattern_32;
+ src_fg_clr = virge->s3d.src_fg_clr;
+ src_bg_clr = virge->s3d.src_bg_clr;
+ break;
+ }
+ if (virge->s3d.cmd_set & CMD_SET_MP)
+ pattern_data = mono_pattern;
+
+ switch (virge->s3d.cmd_set & CMD_SET_ITA_MASK)
+ {
+ case CMD_SET_ITA_BYTE:
+ count_mask = ~0x7;
+ break;
+ case CMD_SET_ITA_WORD:
+ count_mask = ~0xf;
+ break;
+ case CMD_SET_ITA_DWORD:
+ default:
+ count_mask = ~0x1f;
+ break;
+ }
+ if (virge->s3d.cmd_set & CMD_SET_MP)
+ {
+ int x, y;
+ for (y = 0; y < 4; y++)
+ {
+ for (x = 0; x < 8; x++)
+ {
+ if (virge->s3d.mono_pat_0 & (1 << (x + y*8)))
+ mono_pattern[y*8 + x] = virge->s3d.pat_fg_clr;
+ else
+ mono_pattern[y*8 + x] = virge->s3d.pat_bg_clr;
+ if (virge->s3d.mono_pat_1 & (1 << (x + y*8)))
+ mono_pattern[(y+4)*8 + x] = virge->s3d.pat_fg_clr;
+ else
+ mono_pattern[(y+4)*8 + x] = virge->s3d.pat_bg_clr;
+ }
+ }
+ }
+ switch (virge->s3d.cmd_set & CMD_SET_COMMAND_MASK)
+ {
+ case CMD_SET_COMMAND_NOP:
+ break;
+
+ case CMD_SET_COMMAND_BITBLT:
+ if (count == -1)
+ {
+ virge->s3d.src_x = virge->s3d.rsrc_x;
+ virge->s3d.src_y = virge->s3d.rsrc_y;
+ virge->s3d.dest_x = virge->s3d.rdest_x;
+ virge->s3d.dest_y = virge->s3d.rdest_y;
+ virge->s3d.w = virge->s3d.r_width;
+ virge->s3d.h = virge->s3d.r_height;
+ virge->s3d.rop = (virge->s3d.cmd_set >> 17) & 0xff;
+ virge->s3d.data_left_count = 0;
+
+/* pclog("BitBlt start %i,%i %i,%i %i,%i %02X %x %x\n",
+ virge->s3d.src_x,
+ virge->s3d.src_y,
+ virge->s3d.dest_x,
+ virge->s3d.dest_y,
+ virge->s3d.w,
+ virge->s3d.h,
+ virge->s3d.rop,
+ virge->s3d.src_base,
+ virge->s3d.dest_base);*/
+
+ if (virge->s3d.cmd_set & CMD_SET_IDS)
+ return;
+ }
+ if (!virge->s3d.h)
+ return;
+ while (count)
+ {
+ uint32_t src_addr = virge->s3d.src_base + (virge->s3d.src_x * x_mul) + (virge->s3d.src_y * virge->s3d.src_str);
+ uint32_t dest_addr = virge->s3d.dest_base + (virge->s3d.dest_x * x_mul) + (virge->s3d.dest_y * virge->s3d.dest_str);
+ uint32_t source = 0, dest, pattern;
+ uint32_t out = 0;
+ int update = 1;
+
+ switch (virge->s3d.cmd_set & (CMD_SET_MS | CMD_SET_IDS))
+ {
+ case 0:
+ case CMD_SET_MS:
+ READ(src_addr, source);
+ if ((virge->s3d.cmd_set & CMD_SET_TP) && source == src_fg_clr)
+ update = 0;
+ break;
+ case CMD_SET_IDS:
+ if (virge->s3d.data_left_count)
+ {
+ /*Handle shifting for 24-bit data*/
+ source = virge->s3d.data_left;
+ source |= ((cpu_dat << virge->s3d.data_left_count) & ~0xff000000);
+ cpu_dat >>= (cpu_dat_shift - virge->s3d.data_left_count);
+ count -= (cpu_dat_shift - virge->s3d.data_left_count);
+ virge->s3d.data_left_count = 0;
+ if (count < cpu_dat_shift)
+ {
+ virge->s3d.data_left = cpu_dat;
+ virge->s3d.data_left_count = count;
+ count = 0;
+ }
+ }
+ else
+ {
+ source = cpu_dat;
+ cpu_dat >>= cpu_dat_shift;
+ count -= cpu_dat_shift;
+ if (count < cpu_dat_shift)
+ {
+ virge->s3d.data_left = cpu_dat;
+ virge->s3d.data_left_count = count;
+ count = 0;
+ }
+ }
+ if ((virge->s3d.cmd_set & CMD_SET_TP) && source == src_fg_clr)
+ update = 0;
+ break;
+ case CMD_SET_IDS | CMD_SET_MS:
+ source = (cpu_dat & (1 << 31)) ? src_fg_clr : src_bg_clr;
+ if ((virge->s3d.cmd_set & CMD_SET_TP) && !(cpu_dat & (1 << 31)))
+ update = 0;
+ cpu_dat <<= 1;
+ count--;
+ break;
+ }
+
+ CLIP(virge->s3d.dest_x, virge->s3d.dest_y);
+
+ if (update)
+ {
+ READ(dest_addr, dest);
+ pattern = pattern_data[(virge->s3d.dest_y & 7)*8 + (virge->s3d.dest_x & 7)];
+ MIX();
+
+ WRITE(dest_addr, out);
+ }
+
+ virge->s3d.src_x += x_inc;
+ virge->s3d.src_x &= 0x7ff;
+ virge->s3d.dest_x += x_inc;
+ virge->s3d.dest_x &= 0x7ff;
+ if (!virge->s3d.w)
+ {
+ virge->s3d.src_x = virge->s3d.rsrc_x;
+ virge->s3d.dest_x = virge->s3d.rdest_x;
+ virge->s3d.w = virge->s3d.r_width;
+
+ virge->s3d.src_y += y_inc;
+ virge->s3d.dest_y += y_inc;
+ virge->s3d.h--;
+
+ switch (virge->s3d.cmd_set & (CMD_SET_MS | CMD_SET_IDS))
+ {
+ case CMD_SET_IDS:
+ cpu_dat >>= (count - (count & count_mask));
+ count &= count_mask;
+ virge->s3d.data_left_count = 0;
+ break;
+
+ case CMD_SET_IDS | CMD_SET_MS:
+ cpu_dat <<= (count - (count & count_mask));
+ count &= count_mask;
+ break;
+ }
+ if (!virge->s3d.h)
+ {
+ return;
+ }
+ }
+ else
+ virge->s3d.w--;
+ }
+ break;
+
+ case CMD_SET_COMMAND_RECTFILL:
+ /*No source, pattern = pat_fg_clr*/
+ if (count == -1)
+ {
+ virge->s3d.src_x = virge->s3d.rsrc_x;
+ virge->s3d.src_y = virge->s3d.rsrc_y;
+ virge->s3d.dest_x = virge->s3d.rdest_x;
+ virge->s3d.dest_y = virge->s3d.rdest_y;
+ virge->s3d.w = virge->s3d.r_width;
+ virge->s3d.h = virge->s3d.r_height;
+ virge->s3d.rop = (virge->s3d.cmd_set >> 17) & 0xff;
+
+/* pclog("RctFll start %i,%i %i,%i %02X %08x\n", virge->s3d.dest_x,
+ virge->s3d.dest_y,
+ virge->s3d.w,
+ virge->s3d.h,
+ virge->s3d.rop, virge->s3d.dest_base);*/
+ }
+
+ while (count && virge->s3d.h)
+ {
+ uint32_t dest_addr = virge->s3d.dest_base + (virge->s3d.dest_x * x_mul) + (virge->s3d.dest_y * virge->s3d.dest_str);
+ uint32_t source = 0, dest, pattern = virge->s3d.pat_fg_clr;
+ uint32_t out = 0;
+ int update = 1;
+
+ CLIP(virge->s3d.dest_x, virge->s3d.dest_y);
+
+ if (update)
+ {
+ READ(dest_addr, dest);
+
+ MIX();
+
+ WRITE(dest_addr, out);
+ }
+
+ virge->s3d.src_x += x_inc;
+ virge->s3d.src_x &= 0x7ff;
+ virge->s3d.dest_x += x_inc;
+ virge->s3d.dest_x &= 0x7ff;
+ if (!virge->s3d.w)
+ {
+ virge->s3d.src_x = virge->s3d.rsrc_x;
+ virge->s3d.dest_x = virge->s3d.rdest_x;
+ virge->s3d.w = virge->s3d.r_width;
+
+ virge->s3d.src_y += y_inc;
+ virge->s3d.dest_y += y_inc;
+ virge->s3d.h--;
+ if (!virge->s3d.h)
+ {
+ return;
+ }
+ }
+ else
+ virge->s3d.w--;
+ count--;
+ }
+ break;
+
+ case CMD_SET_COMMAND_LINE:
+ if (count == -1)
+ {
+ virge->s3d.dest_x = virge->s3d.lxstart;
+ virge->s3d.dest_y = virge->s3d.lystart;
+ virge->s3d.h = virge->s3d.lycnt;
+ virge->s3d.rop = (virge->s3d.cmd_set >> 17) & 0xff;
+ }
+ while (virge->s3d.h)
+ {
+ int x;
+ int new_x;
+ int first_pixel = 1;
+
+ x = virge->s3d.dest_x >> 20;
+
+ if (virge->s3d.h == virge->s3d.lycnt &&
+ ((virge->s3d.line_dir && x > virge->s3d.lxend0) ||
+ (!virge->s3d.line_dir && x < virge->s3d.lxend0)))
+ x = virge->s3d.lxend0;
+
+ if (virge->s3d.h == 1)
+ new_x = virge->s3d.lxend1 + (virge->s3d.line_dir ? 1 : -1);
+ else
+ new_x = (virge->s3d.dest_x + virge->s3d.ldx) >> 20;
+
+
+ if ((virge->s3d.line_dir && x > new_x) ||
+ (!virge->s3d.line_dir && x < new_x))
+ goto skip_line;
+
+ do
+ {
+ uint32_t dest_addr = virge->s3d.dest_base + (x * x_mul) + (virge->s3d.dest_y * virge->s3d.dest_str);
+ uint32_t source = 0, dest, pattern;
+ uint32_t out = 0;
+ int update = 1;
+
+ if ((virge->s3d.h == virge->s3d.lycnt || !first_pixel) &&
+ ((virge->s3d.line_dir && x < virge->s3d.lxend0) ||
+ (!virge->s3d.line_dir && x > virge->s3d.lxend0)))
+ update = 0;
+
+ if ((virge->s3d.h == 1 || !first_pixel) &&
+ ((virge->s3d.line_dir && x > virge->s3d.lxend1) ||
+ (!virge->s3d.line_dir && x < virge->s3d.lxend1)))
+ update = 0;
+
+ CLIP(x, virge->s3d.dest_y);
+
+ if (update)
+ {
+ READ(dest_addr, dest);
+ pattern = virge->s3d.pat_fg_clr;
+
+ MIX();
+
+ WRITE(dest_addr, out);
+ }
+
+ if (x < new_x)
+ x++;
+ else if (x > new_x)
+ x--;
+ first_pixel = 0;
+ } while (x != new_x);
+
+skip_line:
+ virge->s3d.dest_x += virge->s3d.ldx;
+ virge->s3d.dest_y--;
+ virge->s3d.h--;
+ }
+ break;
+
+ case CMD_SET_COMMAND_POLY:
+ /*No source*/
+ if (virge->s3d.pycnt & (1 << 28))
+ virge->s3d.dest_r = virge->s3d.prxstart;
+ if (virge->s3d.pycnt & (1 << 29))
+ virge->s3d.dest_l = virge->s3d.plxstart;
+ virge->s3d.h = virge->s3d.pycnt & 0x7ff;
+ virge->s3d.rop = (virge->s3d.cmd_set >> 17) & 0xff;
+ //pclog("Start poly - l=%08x r=%08x h=%i rop=%02x\n", virge->s3d.dest_l, virge->s3d.dest_r, virge->s3d.h, virge->s3d.rop);
+ while (virge->s3d.h)
+ {
+ int x = virge->s3d.dest_l >> 20;
+ int xend = virge->s3d.dest_r >> 20;
+ int y = virge->s3d.pystart & 0x7ff;
+ int xdir = (x < xend) ? 1 : -1;
+ //pclog(" %03i: %i - %i %08x-%08x\n", y, x, xend, virge->s3d.dest_l, virge->s3d.dest_r);
+ do
+ {
+ uint32_t dest_addr = virge->s3d.dest_base + (x * x_mul) + (y * virge->s3d.dest_str);
+ uint32_t source = 0, dest, pattern;
+ uint32_t out = 0;
+ int update = 1;
+
+ CLIP(x, y);
+
+ if (update)
+ {
+ READ(dest_addr, dest);
+ pattern = pattern_data[(y & 7)*8 + (x & 7)];
+ MIX();
+
+ WRITE(dest_addr, out);
+ }
+
+ x = (x + xdir) & 0x7ff;
+ }
+ while (x != (xend + xdir));
+
+ virge->s3d.dest_l += virge->s3d.pldx;
+ virge->s3d.dest_r += virge->s3d.prdx;
+ virge->s3d.h--;
+ virge->s3d.pystart = (virge->s3d.pystart - 1) & 0x7ff;
+ }
+ break;
+
+ default:
+ fatal("s3_virge_bitblt : blit command %i %08x\n", (virge->s3d.cmd_set >> 27) & 0xf, virge->s3d.cmd_set);
+ }
+}
+
+#define RGB15_TO_24(val, r, g, b) b = ((val & 0x001f) << 3) | ((val & 0x001f) >> 2); \
+ g = ((val & 0x03e0) >> 2) | ((val & 0x03e0) >> 7); \
+ r = ((val & 0x7c00) >> 7) | ((val & 0x7c00) >> 12);
+
+#define RGB24_TO_24(val, r, g, b) b = val & 0xff; \
+ g = (val & 0xff00) >> 8; \
+ r = (val & 0xff0000) >> 16
+
+#define RGB15(r, g, b, dest) \
+ if (virge->dithering_enabled) \
+ { \
+ int add = dither[_y & 3][_x & 3]; \
+ int _r = (r > 248) ? 248 : r+add; \
+ int _g = (g > 248) ? 248 : g+add; \
+ int _b = (b > 248) ? 248 : b+add; \
+ dest = ((_b >> 3) & 0x1f) | (((_g >> 3) & 0x1f) << 5) | (((_r >> 3) & 0x1f) << 10); \
+ } \
+ else \
+ dest = ((b >> 3) & 0x1f) | (((g >> 3) & 0x1f) << 5) | (((r >> 3) & 0x1f) << 10)
+
+#define RGB24(r, g, b) ((b) | ((g) << 8) | ((r) << 16))
+
+typedef struct rgba_t
+{
+ int r, g, b, a;
+} rgba_t;
+
+typedef struct s3d_state_t
+{
+ int32_t r, g, b, a, u, v, d, w;
+
+ int32_t base_r, base_g, base_b, base_a, base_u, base_v, base_d, base_w;
+
+ uint32_t base_z;
+
+ uint32_t tbu, tbv;
+
+ uint32_t cmd_set;
+ int max_d;
+
+ uint16_t *texture[10];
+
+ uint32_t tex_bdr_clr;
+
+ int32_t x1, x2;
+ int y;
+
+ rgba_t dest_rgba;
+} s3d_state_t;
+
+typedef struct s3d_texture_state_t
+{
+ int level;
+ int texture_shift;
+
+ int32_t u, v;
+} s3d_texture_state_t;
+
+static void (*tex_read)(s3d_state_t *state, s3d_texture_state_t *texture_state, rgba_t *out);
+static void (*tex_sample)(s3d_state_t *state);
+static void (*dest_pixel)(s3d_state_t *state);
+
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+
+static int _x, _y;
+
+static void tex_ARGB1555(s3d_state_t *state, s3d_texture_state_t *texture_state, rgba_t *out)
+{
+ int offset = ((texture_state->u & 0x7fc0000) >> texture_state->texture_shift) +
+ (((texture_state->v & 0x7fc0000) >> texture_state->texture_shift) << texture_state->level);
+ uint16_t val = state->texture[texture_state->level][offset];
+
+ out->r = ((val & 0x7c00) >> 7) | ((val & 0x7000) >> 12);
+ out->g = ((val & 0x03e0) >> 2) | ((val & 0x0380) >> 7);
+ out->b = ((val & 0x001f) << 3) | ((val & 0x001c) >> 2);
+ out->a = (val & 0x8000) ? 0xff : 0;
+}
+
+static void tex_ARGB1555_nowrap(s3d_state_t *state, s3d_texture_state_t *texture_state, rgba_t *out)
+{
+ int offset = ((texture_state->u & 0x7fc0000) >> texture_state->texture_shift) +
+ (((texture_state->v & 0x7fc0000) >> texture_state->texture_shift) << texture_state->level);
+ uint16_t val = state->texture[texture_state->level][offset];
+
+ if (((texture_state->u | texture_state->v) & 0xf8000000) == 0xf8000000)
+ val = state->tex_bdr_clr;
+
+ out->r = ((val & 0x7c00) >> 7) | ((val & 0x7000) >> 12);
+ out->g = ((val & 0x03e0) >> 2) | ((val & 0x0380) >> 7);
+ out->b = ((val & 0x001f) << 3) | ((val & 0x001c) >> 2);
+ out->a = (val & 0x8000) ? 0xff : 0;
+}
+
+static void tex_ARGB4444(s3d_state_t *state, s3d_texture_state_t *texture_state, rgba_t *out)
+{
+ int offset = ((texture_state->u & 0x7fc0000) >> texture_state->texture_shift) +
+ (((texture_state->v & 0x7fc0000) >> texture_state->texture_shift) << texture_state->level);
+ uint16_t val = state->texture[texture_state->level][offset];
+
+ out->r = ((val & 0x0f00) >> 4) | ((val & 0x0f00) >> 8);
+ out->g = (val & 0x00f0) | ((val & 0x00f0) >> 4);
+ out->b = ((val & 0x000f) << 4) | (val & 0x000f);
+ out->a = ((val & 0xf000) >> 8) | ((val & 0xf000) >> 12);
+}
+
+static void tex_ARGB4444_nowrap(s3d_state_t *state, s3d_texture_state_t *texture_state, rgba_t *out)
+{
+ int offset = ((texture_state->u & 0x7fc0000) >> texture_state->texture_shift) +
+ (((texture_state->v & 0x7fc0000) >> texture_state->texture_shift) << texture_state->level);
+ uint16_t val = state->texture[texture_state->level][offset];
+
+ if (((texture_state->u | texture_state->v) & 0xf8000000) == 0xf8000000)
+ val = state->tex_bdr_clr;
+
+ out->r = ((val & 0x0f00) >> 4) | ((val & 0x0f00) >> 8);
+ out->g = (val & 0x00f0) | ((val & 0x00f0) >> 4);
+ out->b = ((val & 0x000f) << 4) | (val & 0x000f);
+ out->a = ((val & 0xf000) >> 8) | ((val & 0xf000) >> 12);
+}
+
+static void tex_ARGB8888(s3d_state_t *state, s3d_texture_state_t *texture_state, rgba_t *out)
+{
+ int offset = ((texture_state->u & 0x7fc0000) >> texture_state->texture_shift) +
+ (((texture_state->v & 0x7fc0000) >> texture_state->texture_shift) << texture_state->level);
+ uint32_t val = ((uint32_t *)state->texture[texture_state->level])[offset];
+
+ out->r = (val >> 16) & 0xff;
+ out->g = (val >> 8) & 0xff;
+ out->b = val & 0xff;
+ out->a = (val >> 24) & 0xff;
+}
+static void tex_ARGB8888_nowrap(s3d_state_t *state, s3d_texture_state_t *texture_state, rgba_t *out)
+{
+ int offset = ((texture_state->u & 0x7fc0000) >> texture_state->texture_shift) +
+ (((texture_state->v & 0x7fc0000) >> texture_state->texture_shift) << texture_state->level);
+ uint32_t val = ((uint32_t *)state->texture[texture_state->level])[offset];
+
+ if (((texture_state->u | texture_state->v) & 0xf8000000) == 0xf8000000)
+ val = state->tex_bdr_clr;
+
+ out->r = (val >> 16) & 0xff;
+ out->g = (val >> 8) & 0xff;
+ out->b = val & 0xff;
+ out->a = (val >> 24) & 0xff;
+}
+
+static void tex_sample_normal(s3d_state_t *state)
+{
+ s3d_texture_state_t texture_state;
+
+ texture_state.level = state->max_d;
+ texture_state.texture_shift = 18 + (9 - texture_state.level);
+ texture_state.u = state->u + state->tbu;
+ texture_state.v = state->v + state->tbv;
+
+ tex_read(state, &texture_state, &state->dest_rgba);
+}
+
+static void tex_sample_normal_filter(s3d_state_t *state)
+{
+ s3d_texture_state_t texture_state;
+ int tex_offset;
+ rgba_t tex_samples[4];
+ int du, dv;
+ int d[4];
+
+ texture_state.level = state->max_d;
+ texture_state.texture_shift = 18 + (9 - texture_state.level);
+ tex_offset = 1 << texture_state.texture_shift;
+
+ texture_state.u = state->u + state->tbu;
+ texture_state.v = state->v + state->tbv;
+ tex_read(state, &texture_state, &tex_samples[0]);
+ du = (texture_state.u >> (texture_state.texture_shift - 8)) & 0xff;
+ dv = (texture_state.v >> (texture_state.texture_shift - 8)) & 0xff;
+
+ texture_state.u = state->u + state->tbu + tex_offset;
+ texture_state.v = state->v + state->tbv;
+ tex_read(state, &texture_state, &tex_samples[1]);
+
+ texture_state.u = state->u + state->tbu;
+ texture_state.v = state->v + state->tbv + tex_offset;
+ tex_read(state, &texture_state, &tex_samples[2]);
+
+ texture_state.u = state->u + state->tbu + tex_offset;
+ texture_state.v = state->v + state->tbv + tex_offset;
+ tex_read(state, &texture_state, &tex_samples[3]);
+
+ d[0] = (256 - du) * (256 - dv);
+ d[1] = du * (256 - dv);
+ d[2] = (256 - du) * dv;
+ d[3] = du * dv;
+
+ state->dest_rgba.r = (tex_samples[0].r * d[0] + tex_samples[1].r * d[1] + tex_samples[2].r * d[2] + tex_samples[3].r * d[3]) >> 16;
+ state->dest_rgba.g = (tex_samples[0].g * d[0] + tex_samples[1].g * d[1] + tex_samples[2].g * d[2] + tex_samples[3].g * d[3]) >> 16;
+ state->dest_rgba.b = (tex_samples[0].b * d[0] + tex_samples[1].b * d[1] + tex_samples[2].b * d[2] + tex_samples[3].b * d[3]) >> 16;
+ state->dest_rgba.a = (tex_samples[0].a * d[0] + tex_samples[1].a * d[1] + tex_samples[2].a * d[2] + tex_samples[3].a * d[3]) >> 16;
+}
+
+static void tex_sample_mipmap(s3d_state_t *state)
+{
+ s3d_texture_state_t texture_state;
+
+ texture_state.level = (state->d < 0) ? state->max_d : state->max_d - ((state->d >> 27) & 0xf);
+ if (texture_state.level < 0)
+ texture_state.level = 0;
+ texture_state.texture_shift = 18 + (9 - texture_state.level);
+ texture_state.u = state->u + state->tbu;
+ texture_state.v = state->v + state->tbv;
+
+ tex_read(state, &texture_state, &state->dest_rgba);
+}
+
+static void tex_sample_mipmap_filter(s3d_state_t *state)
+{
+ s3d_texture_state_t texture_state;
+ int tex_offset;
+ rgba_t tex_samples[4];
+ int du, dv;
+ int d[4];
+
+ texture_state.level = (state->d < 0) ? state->max_d : state->max_d - ((state->d >> 27) & 0xf);
+ if (texture_state.level < 0)
+ texture_state.level = 0;
+ texture_state.texture_shift = 18 + (9 - texture_state.level);
+ tex_offset = 1 << texture_state.texture_shift;
+
+ texture_state.u = state->u + state->tbu;
+ texture_state.v = state->v + state->tbv;
+ tex_read(state, &texture_state, &tex_samples[0]);
+ du = (texture_state.u >> (texture_state.texture_shift - 8)) & 0xff;
+ dv = (texture_state.v >> (texture_state.texture_shift - 8)) & 0xff;
+
+ texture_state.u = state->u + state->tbu + tex_offset;
+ texture_state.v = state->v + state->tbv;
+ tex_read(state, &texture_state, &tex_samples[1]);
+
+ texture_state.u = state->u + state->tbu;
+ texture_state.v = state->v + state->tbv + tex_offset;
+ tex_read(state, &texture_state, &tex_samples[2]);
+
+ texture_state.u = state->u + state->tbu + tex_offset;
+ texture_state.v = state->v + state->tbv + tex_offset;
+ tex_read(state, &texture_state, &tex_samples[3]);
+
+ d[0] = (256 - du) * (256 - dv);
+ d[1] = du * (256 - dv);
+ d[2] = (256 - du) * dv;
+ d[3] = du * dv;
+
+ state->dest_rgba.r = (tex_samples[0].r * d[0] + tex_samples[1].r * d[1] + tex_samples[2].r * d[2] + tex_samples[3].r * d[3]) >> 16;
+ state->dest_rgba.g = (tex_samples[0].g * d[0] + tex_samples[1].g * d[1] + tex_samples[2].g * d[2] + tex_samples[3].g * d[3]) >> 16;
+ state->dest_rgba.b = (tex_samples[0].b * d[0] + tex_samples[1].b * d[1] + tex_samples[2].b * d[2] + tex_samples[3].b * d[3]) >> 16;
+ state->dest_rgba.a = (tex_samples[0].a * d[0] + tex_samples[1].a * d[1] + tex_samples[2].a * d[2] + tex_samples[3].a * d[3]) >> 16;
+}
+
+static void tex_sample_persp_normal(s3d_state_t *state)
+{
+ s3d_texture_state_t texture_state;
+ int32_t w = 0;
+
+ if (state->w)
+ w = (int32_t)(((1ULL << 27) << 19) / (int64_t)state->w);
+
+ texture_state.level = state->max_d;
+ texture_state.texture_shift = 18 + (9 - texture_state.level);
+ texture_state.u = (int32_t)(((int64_t)state->u * (int64_t)w) >> (12 + state->max_d)) + state->tbu;
+ texture_state.v = (int32_t)(((int64_t)state->v * (int64_t)w) >> (12 + state->max_d)) + state->tbv;
+
+ tex_read(state, &texture_state, &state->dest_rgba);
+}
+
+static void tex_sample_persp_normal_filter(s3d_state_t *state)
+{
+ s3d_texture_state_t texture_state;
+ int32_t w = 0, u, v;
+ int tex_offset;
+ rgba_t tex_samples[4];
+ int du, dv;
+ int d[4];
+
+ if (state->w)
+ w = (int32_t)(((1ULL << 27) << 19) / (int64_t)state->w);
+
+ u = (int32_t)(((int64_t)state->u * (int64_t)w) >> (12 + state->max_d)) + state->tbu;
+ v = (int32_t)(((int64_t)state->v * (int64_t)w) >> (12 + state->max_d)) + state->tbv;
+
+ texture_state.level = state->max_d;
+ texture_state.texture_shift = 18 + (9 - texture_state.level);
+ tex_offset = 1 << texture_state.texture_shift;
+
+ texture_state.u = u;
+ texture_state.v = v;
+ tex_read(state, &texture_state, &tex_samples[0]);
+ du = (u >> (texture_state.texture_shift - 8)) & 0xff;
+ dv = (v >> (texture_state.texture_shift - 8)) & 0xff;
+
+ texture_state.u = u + tex_offset;
+ texture_state.v = v;
+ tex_read(state, &texture_state, &tex_samples[1]);
+
+ texture_state.u = u;
+ texture_state.v = v + tex_offset;
+ tex_read(state, &texture_state, &tex_samples[2]);
+
+ texture_state.u = u + tex_offset;
+ texture_state.v = v + tex_offset;
+ tex_read(state, &texture_state, &tex_samples[3]);
+
+ d[0] = (256 - du) * (256 - dv);
+ d[1] = du * (256 - dv);
+ d[2] = (256 - du) * dv;
+ d[3] = du * dv;
+
+ state->dest_rgba.r = (tex_samples[0].r * d[0] + tex_samples[1].r * d[1] + tex_samples[2].r * d[2] + tex_samples[3].r * d[3]) >> 16;
+ state->dest_rgba.g = (tex_samples[0].g * d[0] + tex_samples[1].g * d[1] + tex_samples[2].g * d[2] + tex_samples[3].g * d[3]) >> 16;
+ state->dest_rgba.b = (tex_samples[0].b * d[0] + tex_samples[1].b * d[1] + tex_samples[2].b * d[2] + tex_samples[3].b * d[3]) >> 16;
+ state->dest_rgba.a = (tex_samples[0].a * d[0] + tex_samples[1].a * d[1] + tex_samples[2].a * d[2] + tex_samples[3].a * d[3]) >> 16;
+}
+
+static void tex_sample_persp_normal_375(s3d_state_t *state)
+{
+ s3d_texture_state_t texture_state;
+ int32_t w = 0;
+
+ if (state->w)
+ w = (int32_t)(((1ULL << 27) << 19) / (int64_t)state->w);
+
+ texture_state.level = state->max_d;
+ texture_state.texture_shift = 18 + (9 - texture_state.level);
+ texture_state.u = (int32_t)(((int64_t)state->u * (int64_t)w) >> (8 + state->max_d)) + state->tbu;
+ texture_state.v = (int32_t)(((int64_t)state->v * (int64_t)w) >> (8 + state->max_d)) + state->tbv;
+
+ tex_read(state, &texture_state, &state->dest_rgba);
+}
+
+static void tex_sample_persp_normal_filter_375(s3d_state_t *state)
+{
+ s3d_texture_state_t texture_state;
+ int32_t w = 0, u, v;
+ int tex_offset;
+ rgba_t tex_samples[4];
+ int du, dv;
+ int d[4];
+
+ if (state->w)
+ w = (int32_t)(((1ULL << 27) << 19) / (int64_t)state->w);
+
+ u = (int32_t)(((int64_t)state->u * (int64_t)w) >> (8 + state->max_d)) + state->tbu;
+ v = (int32_t)(((int64_t)state->v * (int64_t)w) >> (8 + state->max_d)) + state->tbv;
+
+ texture_state.level = state->max_d;
+ texture_state.texture_shift = 18 + (9 - texture_state.level);
+ tex_offset = 1 << texture_state.texture_shift;
+
+ texture_state.u = u;
+ texture_state.v = v;
+ tex_read(state, &texture_state, &tex_samples[0]);
+ du = (u >> (texture_state.texture_shift - 8)) & 0xff;
+ dv = (v >> (texture_state.texture_shift - 8)) & 0xff;
+
+ texture_state.u = u + tex_offset;
+ texture_state.v = v;
+ tex_read(state, &texture_state, &tex_samples[1]);
+
+ texture_state.u = u;
+ texture_state.v = v + tex_offset;
+ tex_read(state, &texture_state, &tex_samples[2]);
+
+ texture_state.u = u + tex_offset;
+ texture_state.v = v + tex_offset;
+ tex_read(state, &texture_state, &tex_samples[3]);
+
+ d[0] = (256 - du) * (256 - dv);
+ d[1] = du * (256 - dv);
+ d[2] = (256 - du) * dv;
+ d[3] = du * dv;
+
+ state->dest_rgba.r = (tex_samples[0].r * d[0] + tex_samples[1].r * d[1] + tex_samples[2].r * d[2] + tex_samples[3].r * d[3]) >> 16;
+ state->dest_rgba.g = (tex_samples[0].g * d[0] + tex_samples[1].g * d[1] + tex_samples[2].g * d[2] + tex_samples[3].g * d[3]) >> 16;
+ state->dest_rgba.b = (tex_samples[0].b * d[0] + tex_samples[1].b * d[1] + tex_samples[2].b * d[2] + tex_samples[3].b * d[3]) >> 16;
+ state->dest_rgba.a = (tex_samples[0].a * d[0] + tex_samples[1].a * d[1] + tex_samples[2].a * d[2] + tex_samples[3].a * d[3]) >> 16;
+}
+
+
+static void tex_sample_persp_mipmap(s3d_state_t *state)
+{
+ s3d_texture_state_t texture_state;
+ int32_t w = 0;
+
+ if (state->w)
+ w = (int32_t)(((1ULL << 27) << 19) / (int64_t)state->w);
+
+ texture_state.level = (state->d < 0) ? state->max_d : state->max_d - ((state->d >> 27) & 0xf);
+ if (texture_state.level < 0)
+ texture_state.level = 0;
+ texture_state.texture_shift = 18 + (9 - texture_state.level);
+ texture_state.u = (int32_t)(((int64_t)state->u * (int64_t)w) >> (12 + state->max_d)) + state->tbu;
+ texture_state.v = (int32_t)(((int64_t)state->v * (int64_t)w) >> (12 + state->max_d)) + state->tbv;
+
+ tex_read(state, &texture_state, &state->dest_rgba);
+}
+
+static void tex_sample_persp_mipmap_filter(s3d_state_t *state)
+{
+ s3d_texture_state_t texture_state;
+ int32_t w = 0, u, v;
+ int tex_offset;
+ rgba_t tex_samples[4];
+ int du, dv;
+ int d[4];
+
+ if (state->w)
+ w = (int32_t)(((1ULL << 27) << 19) / (int64_t)state->w);
+
+ u = (int32_t)(((int64_t)state->u * (int64_t)w) >> (12 + state->max_d)) + state->tbu;
+ v = (int32_t)(((int64_t)state->v * (int64_t)w) >> (12 + state->max_d)) + state->tbv;
+
+ texture_state.level = (state->d < 0) ? state->max_d : state->max_d - ((state->d >> 27) & 0xf);
+ if (texture_state.level < 0)
+ texture_state.level = 0;
+ texture_state.texture_shift = 18 + (9 - texture_state.level);
+ tex_offset = 1 << texture_state.texture_shift;
+
+ texture_state.u = u;
+ texture_state.v = v;
+ tex_read(state, &texture_state, &tex_samples[0]);
+ du = (u >> (texture_state.texture_shift - 8)) & 0xff;
+ dv = (v >> (texture_state.texture_shift - 8)) & 0xff;
+
+ texture_state.u = u + tex_offset;
+ texture_state.v = v;
+ tex_read(state, &texture_state, &tex_samples[1]);
+
+ texture_state.u = u;
+ texture_state.v = v + tex_offset;
+ tex_read(state, &texture_state, &tex_samples[2]);
+
+ texture_state.u = u + tex_offset;
+ texture_state.v = v + tex_offset;
+ tex_read(state, &texture_state, &tex_samples[3]);
+
+ d[0] = (256 - du) * (256 - dv);
+ d[1] = du * (256 - dv);
+ d[2] = (256 - du) * dv;
+ d[3] = du * dv;
+
+ state->dest_rgba.r = (tex_samples[0].r * d[0] + tex_samples[1].r * d[1] + tex_samples[2].r * d[2] + tex_samples[3].r * d[3]) >> 16;
+ state->dest_rgba.g = (tex_samples[0].g * d[0] + tex_samples[1].g * d[1] + tex_samples[2].g * d[2] + tex_samples[3].g * d[3]) >> 16;
+ state->dest_rgba.b = (tex_samples[0].b * d[0] + tex_samples[1].b * d[1] + tex_samples[2].b * d[2] + tex_samples[3].b * d[3]) >> 16;
+ state->dest_rgba.a = (tex_samples[0].a * d[0] + tex_samples[1].a * d[1] + tex_samples[2].a * d[2] + tex_samples[3].a * d[3]) >> 16;
+}
+
+static void tex_sample_persp_mipmap_375(s3d_state_t *state)
+{
+ s3d_texture_state_t texture_state;
+ int32_t w = 0;
+
+ if (state->w)
+ w = (int32_t)(((1ULL << 27) << 19) / (int64_t)state->w);
+
+ texture_state.level = (state->d < 0) ? state->max_d : state->max_d - ((state->d >> 27) & 0xf);
+ if (texture_state.level < 0)
+ texture_state.level = 0;
+ texture_state.texture_shift = 18 + (9 - texture_state.level);
+ texture_state.u = (int32_t)(((int64_t)state->u * (int64_t)w) >> (8 + state->max_d)) + state->tbu;
+ texture_state.v = (int32_t)(((int64_t)state->v * (int64_t)w) >> (8 + state->max_d)) + state->tbv;
+
+ tex_read(state, &texture_state, &state->dest_rgba);
+}
+
+static void tex_sample_persp_mipmap_filter_375(s3d_state_t *state)
+{
+ s3d_texture_state_t texture_state;
+ int32_t w = 0, u, v;
+ int tex_offset;
+ rgba_t tex_samples[4];
+ int du, dv;
+ int d[4];
+
+ if (state->w)
+ w = (int32_t)(((1ULL << 27) << 19) / (int64_t)state->w);
+
+ u = (int32_t)(((int64_t)state->u * (int64_t)w) >> (8 + state->max_d)) + state->tbu;
+ v = (int32_t)(((int64_t)state->v * (int64_t)w) >> (8 + state->max_d)) + state->tbv;
+
+ texture_state.level = (state->d < 0) ? state->max_d : state->max_d - ((state->d >> 27) & 0xf);
+ if (texture_state.level < 0)
+ texture_state.level = 0;
+ texture_state.texture_shift = 18 + (9 - texture_state.level);
+ tex_offset = 1 << texture_state.texture_shift;
+
+ texture_state.u = u;
+ texture_state.v = v;
+ tex_read(state, &texture_state, &tex_samples[0]);
+ du = (u >> (texture_state.texture_shift - 8)) & 0xff;
+ dv = (v >> (texture_state.texture_shift - 8)) & 0xff;
+
+ texture_state.u = u + tex_offset;
+ texture_state.v = v;
+ tex_read(state, &texture_state, &tex_samples[1]);
+
+ texture_state.u = u;
+ texture_state.v = v + tex_offset;
+ tex_read(state, &texture_state, &tex_samples[2]);
+
+ texture_state.u = u + tex_offset;
+ texture_state.v = v + tex_offset;
+ tex_read(state, &texture_state, &tex_samples[3]);
+
+ d[0] = (256 - du) * (256 - dv);
+ d[1] = du * (256 - dv);
+ d[2] = (256 - du) * dv;
+ d[3] = du * dv;
+
+ state->dest_rgba.r = (tex_samples[0].r * d[0] + tex_samples[1].r * d[1] + tex_samples[2].r * d[2] + tex_samples[3].r * d[3]) >> 16;
+ state->dest_rgba.g = (tex_samples[0].g * d[0] + tex_samples[1].g * d[1] + tex_samples[2].g * d[2] + tex_samples[3].g * d[3]) >> 16;
+ state->dest_rgba.b = (tex_samples[0].b * d[0] + tex_samples[1].b * d[1] + tex_samples[2].b * d[2] + tex_samples[3].b * d[3]) >> 16;
+ state->dest_rgba.a = (tex_samples[0].a * d[0] + tex_samples[1].a * d[1] + tex_samples[2].a * d[2] + tex_samples[3].a * d[3]) >> 16;
+}
+
+
+#define CLAMP(x) do \
+ { \
+ if ((x) & ~0xff) \
+ x = ((x) < 0) ? 0 : 0xff; \
+ } \
+ while (0)
+
+#define CLAMP_RGBA(r, g, b, a) \
+ if ((r) & ~0xff) \
+ r = ((r) < 0) ? 0 : 0xff; \
+ if ((g) & ~0xff) \
+ g = ((g) < 0) ? 0 : 0xff; \
+ if ((b) & ~0xff) \
+ b = ((b) < 0) ? 0 : 0xff; \
+ if ((a) & ~0xff) \
+ a = ((a) < 0) ? 0 : 0xff;
+
+#define CLAMP_RGB(r, g, b) do \
+ { \
+ if ((r) < 0) \
+ r = 0; \
+ if ((r) > 0xff) \
+ r = 0xff; \
+ if ((g) < 0) \
+ g = 0; \
+ if ((g) > 0xff) \
+ g = 0xff; \
+ if ((b) < 0) \
+ b = 0; \
+ if ((b) > 0xff) \
+ b = 0xff; \
+ } \
+ while (0)
+
+static void dest_pixel_gouraud_shaded_triangle(s3d_state_t *state)
+{
+ state->dest_rgba.r = state->r >> 7;
+ CLAMP(state->dest_rgba.r);
+
+ state->dest_rgba.g = state->g >> 7;
+ CLAMP(state->dest_rgba.g);
+
+ state->dest_rgba.b = state->b >> 7;
+ CLAMP(state->dest_rgba.b);
+
+ state->dest_rgba.a = state->a >> 7;
+ CLAMP(state->dest_rgba.a);
+}
+
+static void dest_pixel_unlit_texture_triangle(s3d_state_t *state)
+{
+ tex_sample(state);
+
+ if (state->cmd_set & CMD_SET_ABC_SRC)
+ state->dest_rgba.a = state->a >> 7;
+}
+
+static void dest_pixel_lit_texture_decal(s3d_state_t *state)
+{
+ tex_sample(state);
+
+ if (state->cmd_set & CMD_SET_ABC_SRC)
+ state->dest_rgba.a = state->a >> 7;
+}
+
+static void dest_pixel_lit_texture_reflection(s3d_state_t *state)
+{
+ tex_sample(state);
+
+ state->dest_rgba.r += (state->r >> 7);
+ state->dest_rgba.g += (state->g >> 7);
+ state->dest_rgba.b += (state->b >> 7);
+ if (state->cmd_set & CMD_SET_ABC_SRC)
+ state->dest_rgba.a += (state->a >> 7);
+
+ CLAMP_RGBA(state->dest_rgba.r, state->dest_rgba.g, state->dest_rgba.b, state->dest_rgba.a);
+}
+
+static void dest_pixel_lit_texture_modulate(s3d_state_t *state)
+{
+ int r = state->r >> 7, g = state->g >> 7, b = state->b >> 7, a = state->a >> 7;
+
+ tex_sample(state);
+
+ CLAMP_RGBA(r, g, b, a);
+
+ state->dest_rgba.r = ((state->dest_rgba.r) * r) >> 8;
+ state->dest_rgba.g = ((state->dest_rgba.g) * g) >> 8;
+ state->dest_rgba.b = ((state->dest_rgba.b) * b) >> 8;
+
+ if (state->cmd_set & CMD_SET_ABC_SRC)
+ state->dest_rgba.a = a;
+}
+
+static void tri(virge_t *virge, s3d_t *s3d_tri, s3d_state_t *state, int yc, int32_t dx1, int32_t dx2)
+{
+ svga_t *svga = &virge->svga;
+ uint8_t *vram = virge->svga.vram;
+
+ int x_dir = s3d_tri->tlr ? 1 : -1;
+
+ int use_z = !(s3d_tri->cmd_set & CMD_SET_ZB_MODE);
+
+ int y_count = yc;
+
+ int bpp = (s3d_tri->cmd_set >> 2) & 7;
+
+ uint32_t dest_offset, z_offset;
+
+ dest_offset = s3d_tri->dest_base + (state->y * s3d_tri->dest_str);
+ z_offset = s3d_tri->z_base + (state->y * s3d_tri->z_str);
+
+ if (s3d_tri->cmd_set & CMD_SET_HC)
+ {
+ if (state->y < s3d_tri->clip_t)
+ return;
+ if (state->y > s3d_tri->clip_b)
+ {
+ int diff_y = state->y - s3d_tri->clip_b;
+
+ if (diff_y > y_count)
+ diff_y = y_count;
+
+ state->base_u += (s3d_tri->TdUdY * diff_y);
+ state->base_v += (s3d_tri->TdVdY * diff_y);
+ state->base_z += (s3d_tri->TdZdY * diff_y);
+ state->base_r += (s3d_tri->TdRdY * diff_y);
+ state->base_g += (s3d_tri->TdGdY * diff_y);
+ state->base_b += (s3d_tri->TdBdY * diff_y);
+ state->base_a += (s3d_tri->TdAdY * diff_y);
+ state->base_d += (s3d_tri->TdDdY * diff_y);
+ state->base_w += (s3d_tri->TdWdY * diff_y);
+ state->x1 += (dx1 * diff_y);
+ state->x2 += (dx2 * diff_y);
+ state->y -= diff_y;
+ dest_offset -= s3d_tri->dest_str;
+ z_offset -= s3d_tri->z_str;
+ y_count -= diff_y;
+ }
+ if ((state->y - y_count) < s3d_tri->clip_t)
+ y_count = (state->y - s3d_tri->clip_t) + 1;
+ }
+
+ for (; y_count > 0; y_count--)
+ {
+ int x = (state->x1 + ((1 << 20) - 1)) >> 20;
+ int xe = (state->x2 + ((1 << 20) - 1)) >> 20;
+ uint32_t z = (state->base_z > 0) ? (state->base_z << 1) : 0;
+ if (x_dir < 0)
+ {
+ x--;
+ xe--;
+ }
+
+ if (x != xe && ((x_dir > 0 && x < xe) || (x_dir < 0 && x > xe)))
+ {
+ uint32_t dest_addr, z_addr;
+ int dx = (x_dir > 0) ? ((31 - ((state->x1-1) >> 15)) & 0x1f) : (((state->x1-1) >> 15) & 0x1f);
+ int x_offset = x_dir * (bpp + 1);
+ int xz_offset = x_dir << 1;
+ if (x_dir > 0)
+ dx += 1;
+ state->r = state->base_r + ((s3d_tri->TdRdX * dx) >> 5);
+ state->g = state->base_g + ((s3d_tri->TdGdX * dx) >> 5);
+ state->b = state->base_b + ((s3d_tri->TdBdX * dx) >> 5);
+ state->a = state->base_a + ((s3d_tri->TdAdX * dx) >> 5);
+ state->u = state->base_u + ((s3d_tri->TdUdX * dx) >> 5);
+ state->v = state->base_v + ((s3d_tri->TdVdX * dx) >> 5);
+ state->w = state->base_w + ((s3d_tri->TdWdX * dx) >> 5);
+ state->d = state->base_d + ((s3d_tri->TdDdX * dx) >> 5);
+ z += ((s3d_tri->TdZdX * dx) >> 5);
+
+// pclog("Draw Y=%i X=%i to XE=%i %i %08x %08x %08x %08x %08x %08x %08x %08x %i %08x\n", state->y, x, xe, dx, state->x1, state->x2, dx1, virge->s3d.TdWdX, state->u, state->v, virge->s3d.TdUdX, virge->s3d.TdUdY, dx, (virge->s3d.TdUdX * dx) >> 4);
+
+ if (s3d_tri->cmd_set & CMD_SET_HC)
+ {
+ if (x_dir > 0)
+ {
+ if (x > s3d_tri->clip_r)
+ goto tri_skip_line;
+ if (xe < s3d_tri->clip_l)
+ goto tri_skip_line;
+ if (xe > s3d_tri->clip_r)
+ xe = s3d_tri->clip_r + 1;
+ if (x < s3d_tri->clip_l)
+ {
+ int diff_x = s3d_tri->clip_l - x;
+
+ z += (s3d_tri->TdZdX * diff_x);
+ state->u += (s3d_tri->TdUdX * diff_x);
+ state->v += (s3d_tri->TdVdX * diff_x);
+ state->r += (s3d_tri->TdRdX * diff_x);
+ state->g += (s3d_tri->TdGdX * diff_x);
+ state->b += (s3d_tri->TdBdX * diff_x);
+ state->a += (s3d_tri->TdAdX * diff_x);
+ state->d += (s3d_tri->TdDdX * diff_x);
+ state->w += (s3d_tri->TdWdX * diff_x);
+
+ x = s3d_tri->clip_l;
+ }
+ }
+ else
+ {
+ if (x < s3d_tri->clip_l)
+ goto tri_skip_line;
+ if (xe > s3d_tri->clip_r)
+ goto tri_skip_line;
+ if (xe < s3d_tri->clip_l)
+ xe = s3d_tri->clip_l - 1;
+ if (x > s3d_tri->clip_r)
+ {
+ int diff_x = x - s3d_tri->clip_r;
+
+ z += (s3d_tri->TdZdX * diff_x);
+ state->u += (s3d_tri->TdUdX * diff_x);
+ state->v += (s3d_tri->TdVdX * diff_x);
+ state->r += (s3d_tri->TdRdX * diff_x);
+ state->g += (s3d_tri->TdGdX * diff_x);
+ state->b += (s3d_tri->TdBdX * diff_x);
+ state->a += (s3d_tri->TdAdX * diff_x);
+ state->d += (s3d_tri->TdDdX * diff_x);
+ state->w += (s3d_tri->TdWdX * diff_x);
+
+ x = s3d_tri->clip_r;
+ }
+ }
+ }
+
+ virge->svga.changedvram[(dest_offset & svga->vram_mask) >> 12] = changeframecount;
+
+ dest_addr = dest_offset + (x * (bpp + 1));
+ z_addr = z_offset + (x << 1);
+
+ x &= 0xfff;
+ xe &= 0xfff;
+
+ for (; x != xe; x = (x + x_dir) & 0xfff)
+ {
+ int update = 1;
+ uint16_t src_z = 0;
+ _x = x; _y = state->y;
+
+ if (use_z)
+ {
+ src_z = Z_READ(z_addr);
+ Z_CLIP(src_z, z >> 16);
+ }
+
+ if (update)
+ {
+ uint32_t dest_col;
+
+ dest_pixel(state);
+
+ if (s3d_tri->cmd_set & CMD_SET_ABC_ENABLE)
+ {
+ uint32_t src_col;
+ int src_r = 0, src_g = 0, src_b = 0;
+
+ switch (bpp)
+ {
+ case 0: /*8 bpp*/
+ /*Not implemented yet*/
+ break;
+ case 1: /*16 bpp*/
+ src_col = *(uint16_t *)&vram[dest_addr & svga->vram_mask];
+ RGB15_TO_24(src_col, src_r, src_g, src_b);
+ break;
+ case 2: /*24 bpp*/
+ src_col = (*(uint32_t *)&vram[dest_addr & svga->vram_mask]) & 0xffffff;
+ RGB24_TO_24(src_col, src_r, src_g, src_b);
+ break;
+ }
+
+ state->dest_rgba.r = ((state->dest_rgba.r * state->dest_rgba.a) + (src_r * (255 - state->dest_rgba.a))) / 255;
+ state->dest_rgba.g = ((state->dest_rgba.g * state->dest_rgba.a) + (src_g * (255 - state->dest_rgba.a))) / 255;
+ state->dest_rgba.b = ((state->dest_rgba.b * state->dest_rgba.a) + (src_b * (255 - state->dest_rgba.a))) / 255;
+ }
+
+ switch (bpp)
+ {
+ case 0: /*8 bpp*/
+ /*Not implemented yet*/
+ break;
+ case 1: /*16 bpp*/
+ RGB15(state->dest_rgba.r, state->dest_rgba.g, state->dest_rgba.b, dest_col);
+ *(uint16_t *)&vram[dest_addr] = dest_col;
+ break;
+ case 2: /*24 bpp*/
+ dest_col = RGB24(state->dest_rgba.r, state->dest_rgba.g, state->dest_rgba.b);
+ *(uint8_t *)&vram[dest_addr] = dest_col & 0xff;
+ *(uint8_t *)&vram[dest_addr + 1] = (dest_col >> 8) & 0xff;
+ *(uint8_t *)&vram[dest_addr + 2] = (dest_col >> 16) & 0xff;
+ break;
+ }
+
+ if (use_z && (s3d_tri->cmd_set & CMD_SET_ZUP))
+ Z_WRITE(z_addr, src_z);
+ }
+
+ z += s3d_tri->TdZdX;
+ state->u += s3d_tri->TdUdX;
+ state->v += s3d_tri->TdVdX;
+ state->r += s3d_tri->TdRdX;
+ state->g += s3d_tri->TdGdX;
+ state->b += s3d_tri->TdBdX;
+ state->a += s3d_tri->TdAdX;
+ state->d += s3d_tri->TdDdX;
+ state->w += s3d_tri->TdWdX;
+ dest_addr += x_offset;
+ z_addr += xz_offset;
+ virge->pixel_count++;
+ }
+ }
+tri_skip_line:
+ state->x1 += dx1;
+ state->x2 += dx2;
+ state->base_u += s3d_tri->TdUdY;
+ state->base_v += s3d_tri->TdVdY;
+ state->base_z += s3d_tri->TdZdY;
+ state->base_r += s3d_tri->TdRdY;
+ state->base_g += s3d_tri->TdGdY;
+ state->base_b += s3d_tri->TdBdY;
+ state->base_a += s3d_tri->TdAdY;
+ state->base_d += s3d_tri->TdDdY;
+ state->base_w += s3d_tri->TdWdY;
+ state->y--;
+ dest_offset -= s3d_tri->dest_str;
+ z_offset -= s3d_tri->z_str;
+ }
+}
+
+static int tex_size[8] =
+{
+ 4*2,
+ 2*2,
+ 2*2,
+ 1*2,
+ 2/1,
+ 2/1,
+ 1*2,
+ 1*2
+};
+
+static void s3_virge_triangle(virge_t *virge, s3d_t *s3d_tri)
+{
+ s3d_state_t state;
+
+ uint32_t tex_base;
+ int c;
+
+ uint64_t start_time = timer_read();
+ uint64_t end_time;
+
+ state.tbu = s3d_tri->tbu << 11;
+ state.tbv = s3d_tri->tbv << 11;
+
+ state.max_d = (s3d_tri->cmd_set >> 8) & 15;
+
+ state.tex_bdr_clr = s3d_tri->tex_bdr_clr;
+
+ state.cmd_set = s3d_tri->cmd_set;
+
+ state.base_u = s3d_tri->tus;
+ state.base_v = s3d_tri->tvs;
+ state.base_z = s3d_tri->tzs;
+ state.base_r = (int32_t)s3d_tri->trs;
+ state.base_g = (int32_t)s3d_tri->tgs;
+ state.base_b = (int32_t)s3d_tri->tbs;
+ state.base_a = (int32_t)s3d_tri->tas;
+ state.base_d = s3d_tri->tds;
+ state.base_w = s3d_tri->tws;
+
+ tex_base = s3d_tri->tex_base;
+ for (c = 9; c >= 0; c--)
+ {
+ state.texture[c] = (uint16_t *)&virge->svga.vram[tex_base];
+ if (c <= state.max_d)
+ tex_base += ((1 << (c*2)) * tex_size[(s3d_tri->cmd_set >> 5) & 7]) / 2;
+ }
+
+ switch ((s3d_tri->cmd_set >> 27) & 0xf)
+ {
+ case 0:
+ dest_pixel = dest_pixel_gouraud_shaded_triangle;
+// pclog("dest_pixel_gouraud_shaded_triangle\n");
+ break;
+ case 1:
+ case 5:
+ switch ((s3d_tri->cmd_set >> 15) & 0x3)
+ {
+ case 0:
+ dest_pixel = dest_pixel_lit_texture_reflection;
+// pclog("dest_pixel_lit_texture_reflection\n");
+ break;
+ case 1:
+ dest_pixel = dest_pixel_lit_texture_modulate;
+// pclog("dest_pixel_lit_texture_modulate\n");
+ break;
+ case 2:
+ dest_pixel = dest_pixel_lit_texture_decal;
+// pclog("dest_pixel_lit_texture_decal\n");
+ break;
+ default:
+ pclog("bad triangle type %x\n", (s3d_tri->cmd_set >> 27) & 0xf);
+ return;
+ }
+ break;
+ case 2:
+ case 6:
+ dest_pixel = dest_pixel_unlit_texture_triangle;
+// pclog("dest_pixel_unlit_texture_triangle\n");
+ break;
+ default:
+ pclog("bad triangle type %x\n", (s3d_tri->cmd_set >> 27) & 0xf);
+ return;
+ }
+
+ switch (((s3d_tri->cmd_set >> 12) & 7) | ((s3d_tri->cmd_set & (1 << 29)) ? 8 : 0))
+ {
+ case 0: case 1:
+ tex_sample = tex_sample_mipmap;
+// pclog("use tex_sample_mipmap\n");
+ break;
+ case 2: case 3:
+ tex_sample = virge->bilinear_enabled ? tex_sample_mipmap_filter : tex_sample_mipmap;
+// pclog("use tex_sample_mipmap_filter\n");
+ break;
+ case 4: case 5:
+ tex_sample = tex_sample_normal;
+// pclog("use tex_sample_normal\n");
+ break;
+ case 6: case 7:
+ tex_sample = virge->bilinear_enabled ? tex_sample_normal_filter : tex_sample_normal;
+// pclog("use tex_sample_normal_filter\n");
+ break;
+ case (0 | 8): case (1 | 8):
+ if (virge->is_375)
+ tex_sample = tex_sample_persp_mipmap_375;
+ else
+ tex_sample = tex_sample_persp_mipmap;
+// pclog("use tex_sample_persp_mipmap\n");
+ break;
+ case (2 | 8): case (3 | 8):
+ if (virge->is_375)
+ tex_sample = virge->bilinear_enabled ? tex_sample_persp_mipmap_filter_375 : tex_sample_persp_mipmap_375;
+ else
+ tex_sample = virge->bilinear_enabled ? tex_sample_persp_mipmap_filter : tex_sample_persp_mipmap;
+// pclog("use tex_sample_persp_mipmap_filter\n");
+ break;
+ case (4 | 8): case (5 | 8):
+ if (virge->is_375)
+ tex_sample = tex_sample_persp_normal_375;
+ else
+ tex_sample = tex_sample_persp_normal;
+// pclog("use tex_sample_persp_normal\n");
+ break;
+ case (6 | 8): case (7 | 8):
+ if (virge->is_375)
+ tex_sample = virge->bilinear_enabled ? tex_sample_persp_normal_filter_375 : tex_sample_persp_normal_375;
+ else
+ tex_sample = virge->bilinear_enabled ? tex_sample_persp_normal_filter : tex_sample_persp_normal;
+// pclog("use tex_sample_persp_normal_filter\n");
+ break;
+ }
+
+ switch ((s3d_tri->cmd_set >> 5) & 7)
+ {
+ case 0:
+ tex_read = (s3d_tri->cmd_set & CMD_SET_TWE) ? tex_ARGB8888 : tex_ARGB8888_nowrap;
+ break;
+ case 1:
+ tex_read = (s3d_tri->cmd_set & CMD_SET_TWE) ? tex_ARGB4444 : tex_ARGB4444_nowrap;
+// pclog("tex_ARGB4444\n");
+ break;
+ case 2:
+ tex_read = (s3d_tri->cmd_set & CMD_SET_TWE) ? tex_ARGB1555 : tex_ARGB1555_nowrap;
+// pclog("tex_ARGB1555 %i\n", (s3d_tri->cmd_set >> 5) & 7);
+ break;
+ default:
+ pclog("bad texture type %i\n", (s3d_tri->cmd_set >> 5) & 7);
+ tex_read = (s3d_tri->cmd_set & CMD_SET_TWE) ? tex_ARGB1555 : tex_ARGB1555_nowrap;
+ break;
+ }
+
+// pclog("Triangle %i %i,%i to %i,%i %08x\n", y, x1 >> 20, y, s3d_tri->txend01 >> 20, y - (s3d_tri->ty01 + s3d_tri->ty12), state.cmd_set);
+
+ state.y = s3d_tri->tys;
+ state.x1 = s3d_tri->txs;
+ state.x2 = s3d_tri->txend01;
+ tri(virge, s3d_tri, &state, s3d_tri->ty01, s3d_tri->TdXdY02, s3d_tri->TdXdY01);
+ state.x2 = s3d_tri->txend12;
+ tri(virge, s3d_tri, &state, s3d_tri->ty12, s3d_tri->TdXdY02, s3d_tri->TdXdY12);
+
+ virge->tri_count++;
+
+ end_time = timer_read();
+
+ virge_time += end_time - start_time;
+}
+
+static void render_thread(void *param)
+{
+ virge_t *virge = (virge_t *)param;
+
+ while (1)
+ {
+ thread_wait_event(virge->wake_render_thread, -1);
+ thread_reset_event(virge->wake_render_thread);
+ virge->s3d_busy = 1;
+ while (!RB_EMPTY)
+ {
+ s3_virge_triangle(virge, &virge->s3d_buffer[virge->s3d_read_idx & RB_MASK]);
+ virge->s3d_read_idx++;
+
+ if (RB_ENTRIES == RB_SIZE - 1)
+ thread_set_event(virge->not_full_event);
+ }
+ virge->s3d_busy = 0;
+ virge->subsys_stat |= INT_S3D_DONE;
+ s3_virge_update_irqs(virge);
+ }
+}
+
+static void queue_triangle(virge_t *virge)
+{
+// pclog("queue_triangle: read=%i write=%i RB_ENTRIES=%i RB_FULL=%i\n", virge->s3d_read_idx, virge->s3d_write_idx, RB_ENTRIES, RB_FULL);
+ if (RB_FULL)
+ {
+ thread_reset_event(virge->not_full_event);
+ if (RB_FULL)
+ thread_wait_event(virge->not_full_event, -1); /*Wait for room in ringbuffer*/
+ }
+// pclog(" add at read=%i write=%i %i\n", virge->s3d_read_idx, virge->s3d_write_idx, virge->s3d_write_idx & RB_MASK);
+ virge->s3d_buffer[virge->s3d_write_idx & RB_MASK] = virge->s3d_tri;
+ virge->s3d_write_idx++;
+ if (!virge->s3d_busy)
+ thread_set_event(virge->wake_render_thread); /*Wake up render thread if moving from idle*/
+}
+
+static void s3_virge_hwcursor_draw(svga_t *svga, int displine)
+{
+ virge_t *virge = (virge_t *)svga->p;
+ int x;
+ uint16_t dat[2];
+ int xx;
+ int offset = svga->hwcursor_latch.x - svga->hwcursor_latch.xoff;
+ uint32_t fg, bg;
+
+// pclog("HWcursor %i %i %08x %08x\n", svga->hwcursor_latch.x, svga->hwcursor_latch.y, virge->hwcursor_col[0],virge->hwcursor_col[1]);
+ switch (svga->bpp)
+ {
+ case 15:
+ fg = video_15to32[virge->hwc_fg_col & 0xffff];
+ bg = video_15to32[virge->hwc_bg_col & 0xffff];
+ break;
+
+ case 16:
+ fg = video_16to32[virge->hwc_fg_col & 0xffff];
+ bg = video_16to32[virge->hwc_bg_col & 0xffff];
+ break;
+
+ case 24: case 32:
+ fg = virge->hwc_fg_col;
+ bg = virge->hwc_bg_col;
+ break;
+
+ default:
+ fg = svga->pallook[virge->hwc_fg_col & 0xff];
+ bg = svga->pallook[virge->hwc_bg_col & 0xff];
+ break;
+ }
+
+ for (x = 0; x < 64; x += 16)
+ {
+ dat[0] = (svga->vram[svga->hwcursor_latch.addr] << 8) | svga->vram[svga->hwcursor_latch.addr + 1];
+ dat[1] = (svga->vram[svga->hwcursor_latch.addr + 2] << 8) | svga->vram[svga->hwcursor_latch.addr + 3];
+ if (svga->crtc[0x55] & 0x10)
+ {
+ /*X11*/
+ for (xx = 0; xx < 16; xx++)
+ {
+ if (offset >= svga->hwcursor_latch.x)
+ {
+ if (dat[0] & 0x8000)
+ ((uint32_t *)buffer32->line[displine])[offset + 32] = (dat[1] & 0x8000) ? fg : bg;
+ }
+
+ offset++;
+ dat[0] <<= 1;
+ dat[1] <<= 1;
+ }
+ }
+ else
+ {
+ /*Windows*/
+ for (xx = 0; xx < 16; xx++)
+ {
+ if (offset >= svga->hwcursor_latch.x)
+ {
+ if (!(dat[0] & 0x8000))
+ ((uint32_t *)buffer32->line[displine])[offset + 32] = (dat[1] & 0x8000) ? fg : bg;
+ else if (dat[1] & 0x8000)
+ ((uint32_t *)buffer32->line[displine])[offset + 32] ^= 0xffffff;
+// pclog("Plot %i, %i (%i %i) %04X %04X\n", offset, displine, x+xx, svga->hwcursor_on, dat[0], dat[1]);
+ }
+
+ offset++;
+ dat[0] <<= 1;
+ dat[1] <<= 1;
+ }
+ }
+ svga->hwcursor_latch.addr += 4;
+ }
+}
+
+#define DECODE_YCbCr() \
+ do \
+ { \
+ int c; \
+ \
+ for (c = 0; c < 2; c++) \
+ { \
+ uint8_t y1, y2; \
+ int8_t Cr, Cb; \
+ int dR, dG, dB; \
+ \
+ y1 = src[0]; \
+ Cr = src[1] - 0x80; \
+ y2 = src[2]; \
+ Cb = src[3] - 0x80; \
+ src += 4; \
+ \
+ dR = (359*Cr) >> 8; \
+ dG = (88*Cb + 183*Cr) >> 8; \
+ dB = (453*Cb) >> 8; \
+ \
+ r[x_write] = y1 + dR; \
+ CLAMP(r[x_write]); \
+ g[x_write] = y1 - dG; \
+ CLAMP(g[x_write]); \
+ b[x_write] = y1 + dB; \
+ CLAMP(b[x_write]); \
+ \
+ r[x_write+1] = y2 + dR; \
+ CLAMP(r[x_write+1]); \
+ g[x_write+1] = y2 - dG; \
+ CLAMP(g[x_write+1]); \
+ b[x_write+1] = y2 + dB; \
+ CLAMP(b[x_write+1]); \
+ \
+ x_write = (x_write + 2) & 7; \
+ } \
+ } while (0)
+
+/*Both YUV formats are untested*/
+#define DECODE_YUV211() \
+ do \
+ { \
+ uint8_t y1, y2, y3, y4; \
+ int8_t U, V; \
+ int dR, dG, dB; \
+ \
+ U = src[0] - 0x80; \
+ y1 = (298 * (src[1] - 16)) >> 8; \
+ y2 = (298 * (src[2] - 16)) >> 8; \
+ V = src[3] - 0x80; \
+ y3 = (298 * (src[4] - 16)) >> 8; \
+ y4 = (298 * (src[5] - 16)) >> 8; \
+ src += 6; \
+ \
+ dR = (309*V) >> 8; \
+ dG = (100*U + 208*V) >> 8; \
+ dB = (516*U) >> 8; \
+ \
+ r[x_write] = y1 + dR; \
+ CLAMP(r[x_write]); \
+ g[x_write] = y1 - dG; \
+ CLAMP(g[x_write]); \
+ b[x_write] = y1 + dB; \
+ CLAMP(b[x_write]); \
+ \
+ r[x_write+1] = y2 + dR; \
+ CLAMP(r[x_write+1]); \
+ g[x_write+1] = y2 - dG; \
+ CLAMP(g[x_write+1]); \
+ b[x_write+1] = y2 + dB; \
+ CLAMP(b[x_write+1]); \
+ \
+ r[x_write+2] = y3 + dR; \
+ CLAMP(r[x_write+2]); \
+ g[x_write+2] = y3 - dG; \
+ CLAMP(g[x_write+2]); \
+ b[x_write+2] = y3 + dB; \
+ CLAMP(b[x_write+2]); \
+ \
+ r[x_write+3] = y4 + dR; \
+ CLAMP(r[x_write+3]); \
+ g[x_write+3] = y4 - dG; \
+ CLAMP(g[x_write+3]); \
+ b[x_write+3] = y4 + dB; \
+ CLAMP(b[x_write+3]); \
+ \
+ x_write = (x_write + 4) & 7; \
+ } while (0)
+
+#define DECODE_YUV422() \
+ do \
+ { \
+ int c; \
+ \
+ for (c = 0; c < 2; c++) \
+ { \
+ uint8_t y1, y2; \
+ int8_t U, V; \
+ int dR, dG, dB; \
+ \
+ U = src[0] - 0x80; \
+ y1 = (298 * (src[1] - 16)) >> 8; \
+ V = src[2] - 0x80; \
+ y2 = (298 * (src[3] - 16)) >> 8; \
+ src += 4; \
+ \
+ dR = (309*V) >> 8; \
+ dG = (100*U + 208*V) >> 8; \
+ dB = (516*U) >> 8; \
+ \
+ r[x_write] = y1 + dR; \
+ CLAMP(r[x_write]); \
+ g[x_write] = y1 - dG; \
+ CLAMP(g[x_write]); \
+ b[x_write] = y1 + dB; \
+ CLAMP(b[x_write]); \
+ \
+ r[x_write+1] = y2 + dR; \
+ CLAMP(r[x_write+1]); \
+ g[x_write+1] = y2 - dG; \
+ CLAMP(g[x_write+1]); \
+ b[x_write+1] = y2 + dB; \
+ CLAMP(b[x_write+1]); \
+ \
+ x_write = (x_write + 2) & 7; \
+ } \
+ } while (0)
+
+#define DECODE_RGB555() \
+ do \
+ { \
+ int c; \
+ \
+ for (c = 0; c < 4; c++) \
+ { \
+ uint16_t dat; \
+ \
+ dat = *(uint16_t *)src; \
+ src += 2; \
+ \
+ r[x_write + c] = ((dat & 0x001f) << 3) | ((dat & 0x001f) >> 2); \
+ g[x_write + c] = ((dat & 0x03e0) >> 2) | ((dat & 0x03e0) >> 7); \
+ b[x_write + c] = ((dat & 0x7c00) >> 7) | ((dat & 0x7c00) >> 12); \
+ } \
+ x_write = (x_write + 4) & 7; \
+ } while (0)
+
+#define DECODE_RGB565() \
+ do \
+ { \
+ int c; \
+ \
+ for (c = 0; c < 4; c++) \
+ { \
+ uint16_t dat; \
+ \
+ dat = *(uint16_t *)src; \
+ src += 2; \
+ \
+ r[x_write + c] = ((dat & 0x001f) << 3) | ((dat & 0x001f) >> 2); \
+ g[x_write + c] = ((dat & 0x07e0) >> 3) | ((dat & 0x07e0) >> 9); \
+ b[x_write + c] = ((dat & 0xf800) >> 8) | ((dat & 0xf800) >> 13); \
+ } \
+ x_write = (x_write + 4) & 7; \
+ } while (0)
+
+#define DECODE_RGB888() \
+ do \
+ { \
+ int c; \
+ \
+ for (c = 0; c < 4; c++) \
+ { \
+ r[x_write + c] = src[0]; \
+ g[x_write + c] = src[1]; \
+ b[x_write + c] = src[2]; \
+ src += 3; \
+ } \
+ x_write = (x_write + 4) & 7; \
+ } while (0)
+
+#define DECODE_XRGB8888() \
+ do \
+ { \
+ int c; \
+ \
+ for (c = 0; c < 4; c++) \
+ { \
+ r[x_write + c] = src[0]; \
+ g[x_write + c] = src[1]; \
+ b[x_write + c] = src[2]; \
+ src += 4; \
+ } \
+ x_write = (x_write + 4) & 7; \
+ } while (0)
+
+#define OVERLAY_SAMPLE() \
+ do \
+ { \
+ switch (virge->streams.sdif) \
+ { \
+ case 1: \
+ DECODE_YCbCr(); \
+ break; \
+ case 2: \
+ DECODE_YUV422(); \
+ break; \
+ case 3: \
+ DECODE_RGB555(); \
+ break; \
+ case 4: \
+ DECODE_YUV211(); \
+ break; \
+ case 5: \
+ DECODE_RGB565(); \
+ break; \
+ case 6: \
+ DECODE_RGB888(); \
+ break; \
+ case 7: \
+ default: \
+ DECODE_XRGB8888(); \
+ break; \
+ } \
+ } while (0)
+
+static void s3_virge_overlay_draw(svga_t *svga, int displine)
+{
+ virge_t *virge = (virge_t *)svga->p;
+ int offset = (virge->streams.sec_x - virge->streams.pri_x) + 1;
+ int h_acc = virge->streams.dda_horiz_accumulator;
+ int r[8], g[8], b[8];
+ int x_size, x_read = 4, x_write = 4;
+ int x;
+ uint32_t *p;
+ uint8_t *src = &svga->vram[svga->overlay_latch.addr];
+
+ p = &((uint32_t *)buffer32->line[displine])[offset + 32];
+
+ if ((offset + virge->streams.sec_w) > virge->streams.pri_w)
+ x_size = (virge->streams.pri_w - virge->streams.sec_x) + 1;
+ else
+ x_size = virge->streams.sec_w + 1;
+
+ OVERLAY_SAMPLE();
+
+ for (x = 0; x < x_size; x++)
+ {
+ *p++ = r[x_read] | (g[x_read] << 8) | (b[x_read] << 16);
+
+ h_acc += virge->streams.k1_horiz_scale;
+ if (h_acc >= 0)
+ {
+ if ((x_read ^ (x_read + 1)) & ~3)
+ OVERLAY_SAMPLE();
+ x_read = (x_read + 1) & 7;
+
+ h_acc += (virge->streams.k2_horiz_scale - virge->streams.k1_horiz_scale);
+ }
+ }
+
+ svga->overlay_latch.v_acc += virge->streams.k1_vert_scale;
+ if (svga->overlay_latch.v_acc >= 0)
+ {
+ svga->overlay_latch.v_acc += (virge->streams.k2_vert_scale - virge->streams.k1_vert_scale);
+ svga->overlay_latch.addr += virge->streams.sec_stride;
+ }
+}
+
+static uint8_t s3_virge_pci_read(int func, int addr, void *p)
+{
+ virge_t *virge = (virge_t *)p;
+ svga_t *svga = &virge->svga;
+ uint8_t ret = 0;
+// pclog("S3 PCI read %08X ", addr);
+ switch (addr)
+ {
+ case 0x00: ret = 0x33; break; /*'S3'*/
+ case 0x01: ret = 0x53; break;
+
+ case 0x02: ret = virge->virge_id_low; break;
+ case 0x03: ret = virge->virge_id_high; break;
+
+ case 0x04: ret = virge->pci_regs[0x04] & 0x27; break;
+
+ case 0x07: ret = virge->pci_regs[0x07] & 0x36; break;
+
+ case 0x08: ret = 0; break; /*Revision ID*/
+ case 0x09: ret = 0; break; /*Programming interface*/
+
+ case 0x0a: ret = 0x00; break; /*Supports VGA interface*/
+ case 0x0b: ret = 0x03; /*output = 3; */break;
+
+ case 0x0d: ret = virge->pci_regs[0x0d] & 0xf8; break;
+
+ case 0x10: ret = 0x00; break;/*Linear frame buffer address*/
+ case 0x11: ret = 0x00; break;
+ case 0x12: ret = 0x00; break;
+ case 0x13: ret = svga->crtc[0x59] & 0xfc; break;
+
+ case 0x30: ret = virge->pci_regs[0x30] & 0x01; break; /*BIOS ROM address*/
+ case 0x31: ret = 0x00; break;
+ case 0x32: ret = virge->pci_regs[0x32]; break;
+ case 0x33: ret = virge->pci_regs[0x33]; break;
+
+ case 0x3c: ret = virge->pci_regs[0x3c]; break;
+
+ case 0x3d: ret = 0x01; break; /*INTA*/
+
+ case 0x3e: ret = 0x04; break;
+ case 0x3f: ret = 0xff; break;
+
+ }
+// pclog("%02X\n", ret);
+ return ret;
+}
+
+static void s3_virge_pci_write(int func, int addr, uint8_t val, void *p)
+{
+ virge_t *virge = (virge_t *)p;
+ svga_t *svga = &virge->svga;
+// pclog("S3 PCI write %08X %02X %04X:%08X\n", addr, val, CS, pc);
+ switch (addr)
+ {
+ case 0x00: case 0x01: case 0x02: case 0x03:
+ case 0x08: case 0x09: case 0x0a: case 0x0b:
+ case 0x3d: case 0x3e: case 0x3f:
+ return;
+
+ case PCI_REG_COMMAND:
+ if (val & PCI_COMMAND_IO)
+ {
+ io_removehandler(0x03c0, 0x0020, s3_virge_in, NULL, NULL, s3_virge_out, NULL, NULL, virge);
+ io_sethandler(0x03c0, 0x0020, s3_virge_in, NULL, NULL, s3_virge_out, NULL, NULL, virge);
+ }
+ else
+ io_removehandler(0x03c0, 0x0020, s3_virge_in, NULL, NULL, s3_virge_out, NULL, NULL, virge);
+ virge->pci_regs[PCI_REG_COMMAND] = val & 0x27;
+ s3_virge_updatemapping(virge);
+ return;
+ case 0x07:
+ virge->pci_regs[0x07] = val & 0x3e;
+ return;
+ case 0x0d:
+ virge->pci_regs[0x0d] = val & 0xf8;
+ return;
+
+ case 0x13:
+ svga->crtc[0x59] = val & 0xfc;
+ s3_virge_updatemapping(virge);
+ return;
+
+ case 0x30: case 0x32: case 0x33:
+ virge->pci_regs[addr] = val;
+ if (virge->pci_regs[0x30] & 0x01)
+ {
+ uint32_t addr = (virge->pci_regs[0x32] << 16) | (virge->pci_regs[0x33] << 24);
+// pclog("Virge bios_rom enabled at %08x\n", addr);
+ mem_mapping_set_addr(&virge->bios_rom.mapping, addr, 0x8000);
+ mem_mapping_enable(&virge->bios_rom.mapping);
+ }
+ else
+ {
+// pclog("Virge bios_rom disabled\n");
+ mem_mapping_disable(&virge->bios_rom.mapping);
+ }
+ return;
+ case 0x3c:
+ virge->pci_regs[0x3c] = val;
+ return;
+ }
+}
+
+static void *s3_virge_init()
+{
+ virge_t *virge = malloc(sizeof(virge_t));
+ memset(virge, 0, sizeof(virge_t));
+
+ virge->bilinear_enabled = device_get_config_int("bilinear");
+ virge->dithering_enabled = device_get_config_int("dithering");
+ virge->memory_size = device_get_config_int("memory");
+
+ svga_init(&virge->svga, virge, virge->memory_size << 20,
+ s3_virge_recalctimings,
+ s3_virge_in, s3_virge_out,
+ s3_virge_hwcursor_draw,
+ s3_virge_overlay_draw);
+
+ rom_init(&virge->bios_rom, "s3virge.bin", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
+ if (PCI)
+ mem_mapping_disable(&virge->bios_rom.mapping);
+
+ mem_mapping_add(&virge->mmio_mapping, 0, 0, s3_virge_mmio_read,
+ s3_virge_mmio_read_w,
+ s3_virge_mmio_read_l,
+ s3_virge_mmio_write,
+ s3_virge_mmio_write_w,
+ s3_virge_mmio_write_l,
+ NULL,
+ 0,
+ virge);
+ mem_mapping_add(&virge->new_mmio_mapping, 0, 0, s3_virge_mmio_read,
+ s3_virge_mmio_read_w,
+ s3_virge_mmio_read_l,
+ s3_virge_mmio_write,
+ s3_virge_mmio_write_w,
+ s3_virge_mmio_write_l,
+ NULL,
+ 0,
+ virge);
+ mem_mapping_add(&virge->linear_mapping, 0, 0, svga_read_linear,
+ svga_readw_linear,
+ svga_readl_linear,
+ svga_write_linear,
+ svga_writew_linear,
+ svga_writel_linear,
+ NULL,
+ 0,
+ &virge->svga);
+
+ io_sethandler(0x03c0, 0x0020, s3_virge_in, NULL, NULL, s3_virge_out, NULL, NULL, virge);
+
+ virge->pci_regs[4] = 3;
+ virge->pci_regs[5] = 0;
+ virge->pci_regs[6] = 0;
+ virge->pci_regs[7] = 2;
+ virge->pci_regs[0x32] = 0x0c;
+ virge->pci_regs[0x3d] = 1;
+ virge->pci_regs[0x3e] = 4;
+ virge->pci_regs[0x3f] = 0xff;
+
+ virge->virge_id_high = 0x56;
+ virge->virge_id_low = 0x31;
+ virge->virge_rev = 0;
+ virge->virge_id = 0xe1;
+
+ switch (virge->memory_size)
+ {
+ case 2:
+ virge->svga.crtc[0x36] = 2 | (0 << 2) | (1 << 4) | (4 << 5);
+ break;
+ case 4:
+ default:
+ virge->svga.crtc[0x36] = 2 | (0 << 2) | (1 << 4) | (0 << 5);
+ break;
+ }
+
+ virge->svga.crtc[0x37] = 1;// | (7 << 5);
+ virge->svga.crtc[0x53] = 1 << 3;
+ virge->svga.crtc[0x59] = 0x70;
+
+ virge->is_375 = 0;
+
+ pci_add(s3_virge_pci_read, s3_virge_pci_write, virge);
+
+ virge->wake_render_thread = thread_create_event();
+ virge->wake_main_thread = thread_create_event();
+ virge->not_full_event = thread_create_event();
+ virge->render_thread = thread_create(render_thread, virge);
+
+ virge->wake_fifo_thread = thread_create_event();
+ virge->fifo_not_full_event = thread_create_event();
+ virge->fifo_thread = thread_create(fifo_thread, virge);
+
+ return virge;
+}
+
+static void *s3_virge_375_init()
+{
+ virge_t *virge = malloc(sizeof(virge_t));
+ memset(virge, 0, sizeof(virge_t));
+
+ virge->bilinear_enabled = device_get_config_int("bilinear");
+ virge->dithering_enabled = device_get_config_int("dithering");
+ virge->memory_size = device_get_config_int("memory");
+
+ svga_init(&virge->svga, virge, virge->memory_size << 20,
+ s3_virge_recalctimings,
+ s3_virge_in, s3_virge_out,
+ s3_virge_hwcursor_draw,
+ s3_virge_overlay_draw);
+ virge->svga.vblank_start = s3_virge_vblank_start;
+
+ rom_init(&virge->bios_rom, "86c375_1.bin", 0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
+ if (PCI)
+ mem_mapping_disable(&virge->bios_rom.mapping);
+
+ mem_mapping_add(&virge->mmio_mapping, 0, 0, s3_virge_mmio_read,
+ s3_virge_mmio_read_w,
+ s3_virge_mmio_read_l,
+ s3_virge_mmio_write,
+ s3_virge_mmio_write_w,
+ s3_virge_mmio_write_l,
+ NULL,
+ 0,
+ virge);
+ mem_mapping_add(&virge->new_mmio_mapping, 0, 0, s3_virge_mmio_read,
+ s3_virge_mmio_read_w,
+ s3_virge_mmio_read_l,
+ s3_virge_mmio_write,
+ s3_virge_mmio_write_w,
+ s3_virge_mmio_write_l,
+ NULL,
+ 0,
+ virge);
+ mem_mapping_add(&virge->linear_mapping, 0, 0, svga_read_linear,
+ svga_readw_linear,
+ svga_readl_linear,
+ svga_write_linear,
+ svga_writew_linear,
+ svga_writel_linear,
+ NULL,
+ 0,
+ &virge->svga);
+
+ io_sethandler(0x03c0, 0x0020, s3_virge_in, NULL, NULL, s3_virge_out, NULL, NULL, virge);
+
+ virge->pci_regs[4] = 3;
+ virge->pci_regs[5] = 0;
+ virge->pci_regs[6] = 0;
+ virge->pci_regs[7] = 2;
+ virge->pci_regs[0x32] = 0x0c;
+ virge->pci_regs[0x3d] = 1;
+ virge->pci_regs[0x3e] = 4;
+ virge->pci_regs[0x3f] = 0xff;
+
+ virge->virge_id_high = 0x8a;
+ virge->virge_id_low = 0x01;
+ virge->virge_rev = 0;
+ virge->virge_id = 0xe1;
+
+ switch (virge->memory_size)
+ {
+ case 2:
+ virge->svga.crtc[0x36] = 2 | (0 << 2) | (1 << 4) | (4 << 5);
+ break;
+ case 4:
+ default:
+ virge->svga.crtc[0x36] = 2 | (0 << 2) | (1 << 4) | (0 << 5);
+ break;
+ }
+// virge->svga.crtc[0x36] = 2 | (0 << 2) | (1 << 4);
+ virge->svga.crtc[0x37] = 1;// | (7 << 5);
+ virge->svga.crtc[0x53] = 1 << 3;
+ virge->svga.crtc[0x59] = 0x70;
+
+ virge->svga.crtc[0x6c] = 0x01;
+
+ virge->is_375 = 1;
+
+ virge->card = pci_add(s3_virge_pci_read, s3_virge_pci_write, virge);
+
+ virge->wake_render_thread = thread_create_event();
+ virge->wake_main_thread = thread_create_event();
+ virge->not_full_event = thread_create_event();
+ virge->render_thread = thread_create(render_thread, virge);
+
+ virge->wake_fifo_thread = thread_create_event();
+ virge->fifo_not_full_event = thread_create_event();
+ virge->fifo_thread = thread_create(fifo_thread, virge);
+
+ return virge;
+}
+
+static void s3_virge_close(void *p)
+{
+ virge_t *virge = (virge_t *)p;
+#ifndef RELEASE_BUILD
+ FILE *f = fopen("vram.dmp", "wb");
+ fwrite(virge->svga.vram, 4 << 20, 1, f);
+ fclose(f);
+#endif
+
+ thread_kill(virge->render_thread);
+ thread_destroy_event(virge->not_full_event);
+ thread_destroy_event(virge->wake_main_thread);
+ thread_destroy_event(virge->wake_render_thread);
+
+ thread_kill(virge->fifo_thread);
+ thread_destroy_event(virge->wake_fifo_thread);
+ thread_destroy_event(virge->fifo_not_full_event);
+
+ svga_close(&virge->svga);
+
+ free(virge);
+}
+
+static int s3_virge_available()
+{
+ return rom_present("s3virge.bin");
+}
+
+static int s3_virge_375_available()
+{
+ return rom_present("86c375_1.bin");
+}
+
+static void s3_virge_speed_changed(void *p)
+{
+ virge_t *virge = (virge_t *)p;
+
+ svga_recalctimings(&virge->svga);
+}
+
+static void s3_virge_force_redraw(void *p)
+{
+ virge_t *virge = (virge_t *)p;
+
+ virge->svga.fullchange = changeframecount;
+}
+
+static void s3_virge_add_status_info(char *s, int max_len, void *p)
+{
+ virge_t *virge = (virge_t *)p;
+ char temps[256];
+ uint64_t new_time = timer_read();
+ uint64_t status_diff = new_time - status_time;
+ status_time = new_time;
+
+ if (!status_diff)
+ status_diff = 1;
+
+ svga_add_status_info(s, max_len, &virge->svga);
+ sprintf(temps, "%f Mpixels/sec\n%f ktris/sec\n%f%% CPU\n%f%% CPU (real)\n%d writes %i reads\n\n", (double)virge->pixel_count/1000000.0, (double)virge->tri_count/1000.0, ((double)virge_time * 100.0) / timer_freq, ((double)virge_time * 100.0) / status_diff, reg_writes, reg_reads);
+ strncat(s, temps, max_len);
+
+ virge->pixel_count = virge->tri_count = 0;
+ virge_time = 0;
+ reg_reads = 0;
+ reg_writes = 0;
+}
+
+static device_config_t s3_virge_config[] =
+{
+ {
+ .name = "memory",
+ .description = "Memory size",
+ .type = CONFIG_SELECTION,
+ .selection =
+ {
+ {
+ .description = "2 MB",
+ .value = 2
+ },
+ {
+ .description = "4 MB",
+ .value = 4
+ },
+ {
+ .description = ""
+ }
+ },
+ .default_int = 4
+ },
+ {
+ .name = "bilinear",
+ .description = "Bilinear filtering",
+ .type = CONFIG_BINARY,
+ .default_int = 1
+ },
+ {
+ .name = "dithering",
+ .description = "Dithering",
+ .type = CONFIG_BINARY,
+ .default_int = 1
+ },
+ {
+ .type = -1
+ }
+};
+
+device_t s3_virge_device =
+{
+ "Diamond Stealth 3D 2000 (S3 ViRGE)",
+ 0,
+ s3_virge_init,
+ s3_virge_close,
+ s3_virge_available,
+ s3_virge_speed_changed,
+ s3_virge_force_redraw,
+ s3_virge_add_status_info,
+ s3_virge_config
+};
+
+device_t s3_virge_375_device =
+{
+ "S3 ViRGE/DX",
+ 0,
+ s3_virge_375_init,
+ s3_virge_close,
+ s3_virge_375_available,
+ s3_virge_speed_changed,
+ s3_virge_force_redraw,
+ s3_virge_add_status_info,
+ s3_virge_config
+};
--- /dev/null
+extern device_t s3_virge_device;
+extern device_t s3_virge_375_device;
--- /dev/null
+/*87C716 'SDAC' true colour RAMDAC emulation*/
+#include "ibm.h"
+#include "mem.h"
+#include "video.h"
+#include "vid_svga.h"
+#include "vid_sdac_ramdac.h"
+
+static void sdac_control_write(sdac_ramdac_t *ramdac, svga_t *svga, uint8_t val)
+{
+ ramdac->command = val;
+// pclog("RAMDAC command reg now %02X\n", val);
+ switch (val & 0xf0)
+ {
+ case 0x00: case 0x10:
+ svga->bpp = 8;
+ break;
+
+ case 0x20: case 0x30: case 0x80: case 0xa0:
+ svga->bpp = 15;
+ break;
+
+ case 0x50: case 0x60: case 0xc0:
+ svga->bpp = 16;
+ break;
+
+ case 0x40: case 0x90: case 0xe0:
+ svga->bpp = 24;
+ break;
+
+ case 0x70:
+ svga->bpp = 32;
+ break;
+
+ default:
+ svga->bpp = 8;
+ break;
+ }
+}
+
+static void sdac_reg_write(sdac_ramdac_t *ramdac, int reg, uint8_t val)
+{
+ if ((reg >= 2 && reg <= 7) || (reg == 0xa) || (reg == 0xe))
+ {
+ if (!ramdac->reg_ff)
+ ramdac->regs[reg] = (ramdac->regs[reg] & 0xff00) | val;
+ else
+ ramdac->regs[reg] = (ramdac->regs[reg] & 0x00ff) | (val << 8);
+ }
+ ramdac->reg_ff = !ramdac->reg_ff;
+ if (!ramdac->reg_ff)
+ ramdac->windex++;
+}
+
+static uint8_t sdac_reg_read(sdac_ramdac_t *ramdac, int reg)
+{
+ uint8_t temp;
+
+ if (!ramdac->reg_ff)
+ temp = ramdac->regs[reg] & 0xff;
+ else
+ temp = ramdac->regs[reg] >> 8;
+ ramdac->reg_ff = !ramdac->reg_ff;
+ if (!ramdac->reg_ff)
+ ramdac->rindex++;
+
+ return temp;
+}
+
+void sdac_ramdac_out(uint16_t addr, uint8_t val, sdac_ramdac_t *ramdac, svga_t *svga)
+{
+// /*if (CS!=0xC000) */pclog("OUT RAMDAC %04X %02X %i %04X:%04X %i %i %i\n",addr,val,ramdac->magic_count,CS,cpu_state.pc, ramdac->rs2, ramdac->rindex, ramdac->windex);
+ switch (addr)
+ {
+ case 2:
+ if (ramdac->magic_count == 4)
+ sdac_control_write(ramdac, svga, val);
+ ramdac->magic_count = 0;
+ break;
+
+ case 3:
+ ramdac->magic_count = 0;
+ break;
+ case 0:
+ ramdac->magic_count = 0;
+ break;
+ case 1:
+ ramdac->magic_count = 0;
+ break;
+
+ case 4:
+ ramdac->windex = val;
+ ramdac->reg_ff = 0;
+ break;
+ case 5:
+ sdac_reg_write(ramdac, ramdac->windex & 0xff, val);
+ break;
+ case 6:
+ sdac_control_write(ramdac, svga, val);
+ break;
+ case 7:
+ ramdac->rindex = val;
+ ramdac->reg_ff = 0;
+ break;
+ }
+ if (!(addr & 4))
+ {
+ if (addr < 2)
+ svga_out(addr + 0x3c8, val, svga);
+ else
+ svga_out(addr + 0x3c4, val, svga);
+ }
+}
+
+uint8_t sdac_ramdac_in(uint16_t addr, sdac_ramdac_t *ramdac, svga_t *svga)
+{
+// /*if (CS!=0xC000) */pclog("IN RAMDAC %04X %04X:%04X %i %i %i\n",addr,CS,cpu_state.pc, ramdac->rs2, ramdac->rindex, ramdac->windex);
+ switch (addr)
+ {
+ case 2:
+ if (ramdac->magic_count < 5)
+ ramdac->magic_count++;
+ if (ramdac->magic_count == 4)
+ {
+ ramdac->rs2 = 1;
+ return 0x70; /*SDAC ID*/
+ }
+ if (ramdac->magic_count == 5)
+ {
+ ramdac->magic_count = 0;
+ return ramdac->command;
+ }
+ break;
+ case 3:
+ ramdac->magic_count=0;
+ break;
+ case 0:
+ ramdac->magic_count=0;
+ break;
+ case 1:
+ ramdac->magic_count=0;
+ break;
+
+ case 4:
+ return ramdac->windex;
+ case 5:
+ return sdac_reg_read(ramdac, ramdac->rindex & 0xff);
+ case 6:
+ return ramdac->command;
+ case 7:
+ return ramdac->rindex;
+ }
+ if (!(addr & 4))
+ {
+ if (addr < 2)
+ return svga_in(addr + 0x3c8, svga);
+ else
+ return svga_in(addr + 0x3c4, svga);
+ }
+ return 0xff;
+}
+
+float sdac_getclock(int clock, void *p)
+{
+ sdac_ramdac_t *ramdac = (sdac_ramdac_t *)p;
+ float t;
+ int m, n1, n2;
+
+ if (ramdac->regs[0xe] & (1 << 5))
+ clock = ramdac->regs[0xe] & 7;
+
+// pclog("SDAC_Getclock %i %04X\n", clock, ramdac->regs[clock]);
+ clock &= 7;
+ if (clock == 0) return 25175000.0;
+ if (clock == 1) return 28322000.0;
+ m = (ramdac->regs[clock] & 0x7f) + 2;
+ n1 = ((ramdac->regs[clock] >> 8) & 0x1f) + 2;
+ n2 = ((ramdac->regs[clock] >> 13) & 0x07);
+ t = (14318184.0 * ((float)m / (float)n1)) / (float)(1 << n2);
+// pclog("SDAC clock %i %i %i %f %04X %f %i\n", m, n1, n2, t, ramdac->regs[2], 14318184.0 * ((float)m / (float)n1), 1 << n2);
+ return t;
+}
+
+void sdac_init(sdac_ramdac_t *ramdac)
+{
+ ramdac->regs[0] = 0x6128;
+ ramdac->regs[1] = 0x623d;
+}
--- /dev/null
+typedef struct sdac_ramdac_t
+{
+ int magic_count;
+ uint8_t command;
+ int windex, rindex;
+ uint16_t regs[256];
+ int reg_ff;
+ int rs2;
+} sdac_ramdac_t;
+
+void sdac_init(sdac_ramdac_t *ramdac);
+
+void sdac_ramdac_out(uint16_t addr, uint8_t val, sdac_ramdac_t *ramdac, svga_t *svga);
+uint8_t sdac_ramdac_in(uint16_t addr, sdac_ramdac_t *ramdac, svga_t *svga);
+
+float sdac_getclock(int clock, void *p);
--- /dev/null
+/*Generic SVGA handling*/
+/*This is intended to be used by another SVGA driver, and not as a card in it's own right*/
+#include <stdlib.h>
+#include "ibm.h"
+#include "mem.h"
+#include "video.h"
+#include "vid_svga.h"
+#include "vid_svga_render.h"
+#include "io.h"
+#include "timer.h"
+
+#define svga_output 0
+
+void svga_doblit(int y1, int y2, int wx, int wy, svga_t *svga);
+
+extern uint8_t edatlookup[4][4];
+
+uint8_t svga_rotate[8][256];
+
+/*Primary SVGA device. As multiple video cards are not yet supported this is the
+ only SVGA device.*/
+static svga_t *svga_pri;
+
+svga_t *svga_get_pri()
+{
+ return svga_pri;
+}
+void svga_set_override(svga_t *svga, int val)
+{
+ if (svga->override && !val)
+ svga->fullchange = changeframecount;
+ svga->override = val;
+}
+
+void svga_out(uint16_t addr, uint8_t val, void *p)
+{
+ svga_t *svga = (svga_t *)p;
+ int c;
+ uint8_t o;
+// printf("OUT SVGA %03X %02X %04X:%04X\n",addr,val,CS,pc);
+ switch (addr)
+ {
+ case 0x3C0:
+ if (!svga->attrff)
+ {
+ svga->attraddr = val & 31;
+ if ((val & 0x20) != svga->attr_palette_enable)
+ {
+ svga->fullchange = 3;
+ svga->attr_palette_enable = val & 0x20;
+ svga_recalctimings(svga);
+ }
+ }
+ else
+ {
+ if ((svga->attraddr == 0x13) && (svga->attrregs[0x13] != val))
+ svga->fullchange = changeframecount;
+ svga->attrregs[svga->attraddr & 31] = val;
+ if (svga->attraddr < 16)
+ svga->fullchange = changeframecount;
+ if (svga->attraddr == 0x10 || svga->attraddr == 0x14 || svga->attraddr < 0x10)
+ {
+ for (c = 0; c < 16; c++)
+ {
+ if (svga->attrregs[0x10] & 0x80) svga->egapal[c] = (svga->attrregs[c] & 0xf) | ((svga->attrregs[0x14] & 0xf) << 4);
+ else svga->egapal[c] = (svga->attrregs[c] & 0x3f) | ((svga->attrregs[0x14] & 0xc) << 4);
+ }
+ }
+ if (svga->attraddr == 0x10)
+ svga_recalctimings(svga);
+ if (svga->attraddr == 0x12)
+ {
+ if ((val & 0xf) != svga->plane_mask)
+ svga->fullchange = changeframecount;
+ svga->plane_mask = val & 0xf;
+ }
+ }
+ svga->attrff ^= 1;
+ break;
+ case 0x3C2:
+ svga->miscout = val;
+ svga->vidclock = val & 4;// printf("3C2 write %02X\n",val);
+ io_removehandler(0x03a0, 0x0020, svga->video_in, NULL, NULL, svga->video_out, NULL, NULL, svga->p);
+ if (!(val & 1))
+ io_sethandler(0x03a0, 0x0020, svga->video_in, NULL, NULL, svga->video_out, NULL, NULL, svga->p);
+ svga_recalctimings(svga);
+ break;
+ case 0x3C4:
+ svga->seqaddr = val;
+ break;
+ case 0x3C5:
+ if (svga->seqaddr > 0xf) return;
+ o = svga->seqregs[svga->seqaddr & 0xf];
+ svga->seqregs[svga->seqaddr & 0xf] = val;
+ if (o != val && (svga->seqaddr & 0xf) == 1)
+ svga_recalctimings(svga);
+ switch (svga->seqaddr & 0xf)
+ {
+ case 1:
+ if (svga->scrblank && !(val & 0x20))
+ svga->fullchange = 3;
+ svga->scrblank = (svga->scrblank & ~0x20) | (val & 0x20);
+ svga_recalctimings(svga);
+ break;
+ case 2:
+ svga->writemask = val & 0xf;
+ break;
+ case 3:
+ svga->charsetb = (((val >> 2) & 3) * 0x10000) + 2;
+ svga->charseta = ((val & 3) * 0x10000) + 2;
+ if (val & 0x10)
+ svga->charseta += 0x8000;
+ if (val & 0x20)
+ svga->charsetb += 0x8000;
+ break;
+ case 4:
+ svga->chain2_write = !(val & 4);
+ svga->chain4 = val & 8;
+ svga->fast = (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && !svga->gdcreg[1]) && svga->chain4;
+ break;
+ }
+ break;
+ case 0x3c6:
+ svga->dac_mask = val;
+ break;
+ case 0x3C7:
+ svga->dac_read = val;
+ svga->dac_pos = 0;
+ break;
+ case 0x3C8:
+ svga->dac_write = val;
+ svga->dac_read = val - 1;
+ svga->dac_pos = 0;
+ break;
+ case 0x3C9:
+ svga->dac_status = 0;
+ svga->fullchange = changeframecount;
+ switch (svga->dac_pos)
+ {
+ case 0:
+ svga->dac_r = val;
+ svga->dac_pos++;
+ break;
+ case 1:
+ svga->dac_g = val;
+ svga->dac_pos++;
+ break;
+ case 2:
+ svga->vgapal[svga->dac_write].r = svga->dac_r;
+ svga->vgapal[svga->dac_write].g = svga->dac_g;
+ svga->vgapal[svga->dac_write].b = val;
+ if (svga->ramdac_type == RAMDAC_8BIT)
+ svga->pallook[svga->dac_write] = makecol32(svga->vgapal[svga->dac_write].r, svga->vgapal[svga->dac_write].g, svga->vgapal[svga->dac_write].b);
+ else
+ svga->pallook[svga->dac_write] = makecol32((svga->vgapal[svga->dac_write].r & 0x3f) * 4, (svga->vgapal[svga->dac_write].g & 0x3f) * 4, (svga->vgapal[svga->dac_write].b & 0x3f) * 4);
+ svga->dac_pos = 0;
+ svga->dac_write = (svga->dac_write + 1) & 255;
+ break;
+ }
+ break;
+ case 0x3CE:
+ svga->gdcaddr = val;
+ break;
+ case 0x3CF:
+ o = svga->gdcreg[svga->gdcaddr & 15];
+ switch (svga->gdcaddr & 15)
+ {
+ case 2: svga->colourcompare=val; break;
+ case 4: svga->readplane=val&3; break;
+ case 5:
+ svga->writemode = val & 3;
+ svga->readmode = val & 8;
+ svga->chain2_read = val & 0x10;
+ break;
+ case 6:
+// pclog("svga_out recalcmapping %p\n", svga);
+ if ((svga->gdcreg[6] & 0xc) != (val & 0xc))
+ {
+// pclog("Write mapping %02X\n", val);
+ switch (val&0xC)
+ {
+ case 0x0: /*128k at A0000*/
+ mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x20000);
+ svga->banked_mask = 0xffff;
+ break;
+ case 0x4: /*64k at A0000*/
+ mem_mapping_set_addr(&svga->mapping, 0xa0000, 0x10000);
+ svga->banked_mask = 0xffff;
+ break;
+ case 0x8: /*32k at B0000*/
+ mem_mapping_set_addr(&svga->mapping, 0xb0000, 0x08000);
+ svga->banked_mask = 0x7fff;
+ break;
+ case 0xC: /*32k at B8000*/
+ mem_mapping_set_addr(&svga->mapping, 0xb8000, 0x08000);
+ svga->banked_mask = 0x7fff;
+ break;
+ }
+ }
+ break;
+ case 7: svga->colournocare=val; break;
+ }
+ svga->gdcreg[svga->gdcaddr & 15] = val;
+ svga->fast = (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && !svga->gdcreg[1]) && svga->chain4;
+ if (((svga->gdcaddr & 15) == 5 && (val ^ o) & 0x70) || ((svga->gdcaddr & 15) == 6 && (val ^ o) & 1))
+ svga_recalctimings(svga);
+ break;
+ }
+}
+
+uint8_t svga_in(uint16_t addr, void *p)
+{
+ svga_t *svga = (svga_t *)p;
+ uint8_t temp;
+// if (addr!=0x3da) pclog("Read port %04X\n",addr);
+ switch (addr)
+ {
+ case 0x3C0:
+ return svga->attraddr | svga->attr_palette_enable;
+ case 0x3C1:
+ return svga->attrregs[svga->attraddr];
+ case 0x3c2:
+ if ((svga->vgapal[0].r + svga->vgapal[0].g + svga->vgapal[0].b) >= 0x50)
+ temp = 0;
+ else
+ temp = 0x10;
+ return temp;
+ case 0x3C4:
+ return svga->seqaddr;
+ case 0x3C5:
+ return svga->seqregs[svga->seqaddr & 0xF];
+ case 0x3c6: return svga->dac_mask;
+ case 0x3c7: return svga->dac_status;
+ case 0x3c8: return svga->dac_write;
+ case 0x3c9:
+ svga->dac_status = 3;
+ switch (svga->dac_pos)
+ {
+ case 0:
+ svga->dac_pos++;
+ if (svga->ramdac_type == RAMDAC_8BIT)
+ return svga->vgapal[svga->dac_read].r;
+ return svga->vgapal[svga->dac_read].r & 0x3f;
+ case 1:
+ svga->dac_pos++;
+ if (svga->ramdac_type == RAMDAC_8BIT)
+ return svga->vgapal[svga->dac_read].g;
+ return svga->vgapal[svga->dac_read].g & 0x3f;
+ case 2:
+ svga->dac_pos=0;
+ svga->dac_read = (svga->dac_read + 1) & 255;
+ if (svga->ramdac_type == RAMDAC_8BIT)
+ return svga->vgapal[(svga->dac_read - 1) & 255].b;
+ return svga->vgapal[(svga->dac_read - 1) & 255].b & 0x3f;
+ }
+ break;
+ case 0x3CC:
+ return svga->miscout;
+ case 0x3CE:
+ return svga->gdcaddr;
+ case 0x3CF:
+ return svga->gdcreg[svga->gdcaddr & 0xf];
+ case 0x3DA:
+ svga->attrff = 0;
+
+ if (svga->cgastat & 0x01)
+ svga->cgastat &= ~0x30;
+ else
+ svga->cgastat ^= 0x30;
+ return svga->cgastat;
+ }
+// printf("Bad EGA read %04X %04X:%04X\n",addr,cs>>4,pc);
+ return 0xFF;
+}
+
+void svga_set_ramdac_type(svga_t *svga, int type)
+{
+ int c;
+
+ if (svga->ramdac_type != type)
+ {
+ svga->ramdac_type = type;
+
+ for (c = 0; c < 256; c++)
+ {
+ if (svga->ramdac_type == RAMDAC_8BIT)
+ svga->pallook[c] = makecol32(svga->vgapal[c].r, svga->vgapal[c].g, svga->vgapal[c].b);
+ else
+ svga->pallook[c] = makecol32((svga->vgapal[c].r & 0x3f) * 4, (svga->vgapal[c].g & 0x3f) * 4, (svga->vgapal[c].b & 0x3f) * 4);
+ }
+ }
+}
+
+void svga_recalctimings(svga_t *svga)
+{
+ double crtcconst;
+ double _dispontime, _dispofftime, disptime;
+
+ svga->vtotal = svga->crtc[6];
+ svga->dispend = svga->crtc[0x12];
+ svga->vsyncstart = svga->crtc[0x10];
+ svga->split = svga->crtc[0x18];
+ svga->vblankstart = svga->crtc[0x15];
+
+ if (svga->crtc[7] & 1) svga->vtotal |= 0x100;
+ if (svga->crtc[7] & 32) svga->vtotal |= 0x200;
+ svga->vtotal += 2;
+
+ if (svga->crtc[7] & 2) svga->dispend |= 0x100;
+ if (svga->crtc[7] & 64) svga->dispend |= 0x200;
+ svga->dispend++;
+
+ if (svga->crtc[7] & 4) svga->vsyncstart |= 0x100;
+ if (svga->crtc[7] & 128) svga->vsyncstart |= 0x200;
+ svga->vsyncstart++;
+
+ if (svga->crtc[7] & 0x10) svga->split|=0x100;
+ if (svga->crtc[9] & 0x40) svga->split|=0x200;
+ svga->split++;
+
+ if (svga->crtc[7] & 0x08) svga->vblankstart |= 0x100;
+ if (svga->crtc[9] & 0x20) svga->vblankstart |= 0x200;
+ svga->vblankstart++;
+
+ svga->hdisp = svga->crtc[1];
+ svga->hdisp++;
+
+ svga->htotal = svga->crtc[0];
+ svga->htotal += 6; /*+6 is required for Tyrian*/
+
+ svga->rowoffset = svga->crtc[0x13];
+
+ svga->clock = (svga->vidclock) ? VGACONST2 : VGACONST1;
+
+ svga->lowres = svga->attrregs[0x10] & 0x40;
+
+ svga->interlace = 0;
+
+ svga->ma_latch = (svga->crtc[0xc] << 8) | svga->crtc[0xd];
+
+ svga->hdisp_time = svga->hdisp;
+ svga->render = svga_render_blank;
+ if (!svga->scrblank && svga->attr_palette_enable)
+ {
+ if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) /*Text mode*/
+ {
+ if (svga->seqregs[1] & 8) /*40 column*/
+ {
+ svga->render = svga_render_text_40;
+ svga->hdisp *= (svga->seqregs[1] & 1) ? 16 : 18;
+ }
+ else
+ {
+ svga->render = svga_render_text_80;
+ svga->hdisp *= (svga->seqregs[1] & 1) ? 8 : 9;
+ }
+ svga->hdisp_old = svga->hdisp;
+ }
+ else
+ {
+ svga->hdisp *= (svga->seqregs[1] & 8) ? 16 : 8;
+ svga->hdisp_old = svga->hdisp;
+
+ switch (svga->gdcreg[5] & 0x60)
+ {
+ case 0x00: /*16 colours*/
+ if (svga->seqregs[1] & 8) /*Low res (320)*/
+ svga->render = svga_render_4bpp_lowres;
+ else
+ svga->render = svga_render_4bpp_highres;
+ break;
+ case 0x20: /*4 colours*/
+ if (svga->seqregs[1] & 8) /*Low res (320)*/
+ svga->render = svga_render_2bpp_lowres;
+ else
+ svga->render = svga_render_2bpp_highres;
+ break;
+ case 0x40: case 0x60: /*256+ colours*/
+ switch (svga->bpp)
+ {
+ case 8:
+ if (svga->lowres)
+ svga->render = svga_render_8bpp_lowres;
+ else
+ svga->render = svga_render_8bpp_highres;
+ break;
+ case 15:
+ if (svga->lowres)
+ svga->render = svga_render_15bpp_lowres;
+ else
+ svga->render = svga_render_15bpp_highres;
+ break;
+ case 16:
+ if (svga->lowres)
+ svga->render = svga_render_16bpp_lowres;
+ else
+ svga->render = svga_render_16bpp_highres;
+ break;
+ case 24:
+ if (svga->lowres)
+ svga->render = svga_render_24bpp_lowres;
+ else
+ svga->render = svga_render_24bpp_highres;
+ break;
+ case 32:
+ if (svga->lowres)
+ svga->render = svga_render_32bpp_lowres;
+ else
+ svga->render = svga_render_32bpp_highres;
+ break;
+ }
+ break;
+ }
+ }
+ }
+
+// pclog("svga_render %08X : %08X %08X %08X %08X %08X %i %i %02X %i %i\n", svga_render, svga_render_text_40, svga_render_text_80, svga_render_8bpp_lowres, svga_render_8bpp_highres, svga_render_blank, scrblank,gdcreg[6]&1,gdcreg[5]&0x60,bpp,seqregs[1]&8);
+
+ svga->linedbl = svga->crtc[9] & 0x80;
+ svga->rowcount = svga->crtc[9] & 31;
+ svga->char_width = (svga->seqregs[1] & 1) ? 8 : 9;
+ if (svga->recalctimings_ex)
+ svga->recalctimings_ex(svga);
+
+ if (svga->vblankstart < svga->dispend)
+ svga->dispend = svga->vblankstart;
+
+ crtcconst = svga->clock * svga->char_width;
+
+ disptime = svga->htotal;
+ _dispontime = svga->hdisp_time;
+
+// printf("Disptime %f dispontime %f hdisp %i\n",disptime,dispontime,crtc[1]*8);
+ if (svga->seqregs[1] & 8) { disptime *= 2; _dispontime *= 2; }
+ _dispofftime = disptime - _dispontime;
+ _dispontime *= crtcconst;
+ _dispofftime *= crtcconst;
+
+ svga->dispontime = (uint64_t)_dispontime;
+ svga->dispofftime = (uint64_t)_dispofftime;
+ if (svga->dispontime < TIMER_USEC)
+ svga->dispontime = TIMER_USEC;
+ if (svga->dispofftime < TIMER_USEC)
+ svga->dispofftime = TIMER_USEC;
+/* printf("SVGA horiz total %i display end %i vidclock %f\n",svga->crtc[0],svga->crtc[1],svga->clock);
+ printf("SVGA vert total %i display end %i max row %i vsync %i\n",svga->vtotal,svga->dispend,(svga->crtc[9]&31)+1,svga->vsyncstart);
+ printf("total %f on %i cycles off %i cycles frame %i sec %i %02X\n",disptime*crtcconst,svga->dispontime,svga->dispofftime,(svga->dispontime+svga->dispofftime)*svga->vtotal,(svga->dispontime+svga->dispofftime)*svga->vtotal*70,svga->seqregs[1]);
+
+ pclog("svga->render %08X\n", svga->render);*/
+}
+
+extern int cyc_total;
+void svga_poll(void *p)
+{
+ svga_t *svga = (svga_t *)p;
+ int x;
+
+ if (!svga->linepos)
+ {
+// if (!(vc & 15)) pclog("VC %i %i\n", vc, GetTickCount());
+ if (svga->displine == svga->hwcursor_latch.y && svga->hwcursor_latch.ena)
+ {
+ svga->hwcursor_on = svga->hwcursor.ysize - svga->hwcursor_latch.yoff;
+ if (svga->hwcursor_on < 0)
+ svga->hwcursor_on = 0;
+ svga->hwcursor_oddeven = 0;
+ }
+
+ if (svga->displine == svga->hwcursor_latch.y+1 && svga->hwcursor_latch.ena && svga->interlace)
+ {
+ svga->hwcursor_on = svga->hwcursor.ysize - svga->hwcursor_latch.yoff;
+ if (svga->hwcursor_on < 0)
+ svga->hwcursor_on = 0;
+ svga->hwcursor_oddeven = 1;
+ }
+
+ if (svga->displine == svga->overlay_latch.y && svga->overlay_latch.ena)
+ {
+ svga->overlay_on = svga->overlay_latch.ysize - svga->overlay_latch.yoff;
+ svga->overlay_oddeven = 0;
+ }
+ if (svga->displine == svga->overlay_latch.y+1 && svga->overlay_latch.ena && svga->interlace)
+ {
+ svga->overlay_on = svga->overlay_latch.ysize - svga->overlay_latch.yoff;
+ svga->overlay_oddeven = 1;
+ }
+
+ timer_advance_u64(&svga->timer, svga->dispofftime);
+// if (output) printf("Display off %f\n",vidtime);
+ svga->cgastat |= 1;
+ svga->linepos = 1;
+
+ if (svga->dispon)
+ {
+ svga->hdisp_on=1;
+
+ svga->ma &= svga->vram_display_mask;
+ if (svga->firstline == 2000)
+ {
+ svga->firstline = svga->displine;
+ video_wait_for_buffer();
+ }
+
+ if (svga->hwcursor_on || svga->overlay_on)
+ svga->changedvram[svga->ma >> 12] = svga->changedvram[(svga->ma >> 12) + 1] = svga->interlace ? 3 : 2;
+
+ if (!svga->override)
+ svga->render(svga);
+
+ if (svga->overlay_on)
+ {
+ if (!svga->override)
+ svga->overlay_draw(svga, svga->displine);
+ svga->overlay_on--;
+ if (svga->overlay_on && svga->interlace)
+ svga->overlay_on--;
+ }
+
+ if (svga->hwcursor_on)
+ {
+ if (!svga->override)
+ svga->hwcursor_draw(svga, svga->displine);
+ svga->hwcursor_on--;
+ if (svga->hwcursor_on && svga->interlace)
+ svga->hwcursor_on--;
+ }
+
+ if (svga->lastline < svga->displine)
+ svga->lastline = svga->displine;
+ }
+
+// pclog("%03i %06X %06X\n",displine,ma,vrammask);
+ svga->displine++;
+ if (svga->interlace)
+ svga->displine++;
+ if ((svga->cgastat & 8) && ((svga->displine & 15) == (svga->crtc[0x11] & 15)) && svga->vslines)
+ {
+// printf("Vsync off at line %i\n",displine);
+ svga->cgastat &= ~8;
+ }
+ svga->vslines++;
+ if (svga->displine > 1500)
+ svga->displine = 0;
+// pclog("Col is %08X %08X %08X %i %i %08X\n",((uint32_t *)buffer32->line[displine])[320],((uint32_t *)buffer32->line[displine])[321],((uint32_t *)buffer32->line[displine])[322],
+// displine, vc, ma);
+ }
+ else
+ {
+// pclog("VC %i ma %05X\n", svga->vc, svga->ma);
+ timer_advance_u64(&svga->timer, svga->dispontime);
+
+// if (output) printf("Display on %f\n",vidtime);
+ if (svga->dispon)
+ svga->cgastat &= ~1;
+ svga->hdisp_on = 0;
+
+ svga->linepos = 0;
+ if (svga->sc == (svga->crtc[11] & 31))
+ svga->con = 0;
+ if (svga->dispon)
+ {
+ if (svga->linedbl && !svga->linecountff)
+ {
+ svga->linecountff = 1;
+ svga->ma = svga->maback;
+ }
+ else if (svga->sc == svga->rowcount)
+ {
+ svga->linecountff = 0;
+ svga->sc = 0;
+
+ svga->maback += (svga->rowoffset << 3);
+ if (svga->interlace)
+ svga->maback += (svga->rowoffset << 3);
+ svga->maback &= svga->vram_display_mask;
+ svga->ma = svga->maback;
+ }
+ else
+ {
+ svga->linecountff = 0;
+ svga->sc++;
+ svga->sc &= 31;
+ svga->ma = svga->maback;
+ }
+ }
+ svga->hsync_divisor = !svga->hsync_divisor;
+
+ if (svga->hsync_divisor && (svga->crtc[0x17] & 4))
+ return;
+
+ svga->vc++;
+ svga->vc &= 2047;
+
+ if (svga->vc == svga->split)
+ {
+ int ret = 1;
+
+ if (svga->line_compare)
+ ret = svga->line_compare(svga);
+
+ if (ret)
+ {
+// pclog("VC split\n");
+ svga->ma = svga->maback = 0;
+ svga->sc = 0;
+ if (svga->attrregs[0x10] & 0x20)
+ svga->scrollcache = 0;
+ }
+ }
+ if (svga->vc == svga->dispend)
+ {
+ if (svga->vblank_start)
+ svga->vblank_start(svga);
+// pclog("VC dispend\n");
+ svga->dispon=0;
+ if (svga->crtc[10] & 0x20) svga->cursoron = 0;
+ else svga->cursoron = svga->blink & 16;
+ if (!(svga->gdcreg[6] & 1) && !(svga->blink & 15))
+ svga->fullchange = 2;
+ svga->blink++;
+
+ for (x = 0; x < ((svga->vram_mask+1) >> 12); x++)
+ {
+ if (svga->changedvram[x])
+ svga->changedvram[x]--;
+ }
+// memset(changedvram,0,2048);
+ if (svga->fullchange)
+ svga->fullchange--;
+ }
+ if (svga->vc == svga->vsyncstart)
+ {
+ int wx, wy;
+// pclog("VC vsync %i %i\n", svga->firstline_draw, svga->lastline_draw);
+ svga->dispon=0;
+ svga->cgastat |= 8;
+ x = svga->hdisp;
+
+ if (svga->interlace && !svga->oddeven) svga->lastline++;
+ if (svga->interlace && svga->oddeven) svga->firstline--;
+
+ wx = x;
+ wy = svga->lastline - svga->firstline;
+
+ if (!svga->override)
+ svga_doblit(svga->firstline_draw, svga->lastline_draw + 1, wx, wy, svga);
+
+ readflash = 0;
+
+ svga->firstline = 2000;
+ svga->lastline = 0;
+
+ svga->firstline_draw = 2000;
+ svga->lastline_draw = 0;
+
+ svga->oddeven ^= 1;
+
+ changeframecount = svga->interlace ? 3 : 2;
+ svga->vslines = 0;
+
+ if (svga->interlace && svga->oddeven) svga->ma = svga->maback = svga->ma_latch + (svga->rowoffset << 1);
+ else svga->ma = svga->maback = svga->ma_latch;
+ svga->ca = (svga->crtc[0xe] << 8) | svga->crtc[0xf];
+
+ svga->ma <<= 2;
+ svga->maback <<= 2;
+ svga->ca <<= 2;
+
+ svga->video_res_x = wx;
+ svga->video_res_y = wy + 1;
+// pclog("%i %i %i\n", svga->video_res_x, svga->video_res_y, svga->lowres);
+ if (!(svga->gdcreg[6] & 1) && !(svga->attrregs[0x10] & 1)) /*Text mode*/
+ {
+ svga->video_res_x /= svga->char_width;
+ svga->video_res_y /= (svga->crtc[9] & 31) + 1;
+ svga->video_bpp = 0;
+ }
+ else
+ {
+ if (svga->crtc[9] & 0x80)
+ svga->video_res_y /= 2;
+ if (!(svga->crtc[0x17] & 2))
+ svga->video_res_y *= 4;
+ else if (!(svga->crtc[0x17] & 1))
+ svga->video_res_y *= 2;
+ svga->video_res_y /= (svga->crtc[9] & 31) + 1;
+ if (svga->render == svga_render_8bpp_lowres ||
+ svga->render == svga_render_15bpp_lowres ||
+ svga->render == svga_render_16bpp_lowres ||
+ svga->render == svga_render_24bpp_lowres ||
+ svga->render == svga_render_32bpp_lowres)
+ svga->video_res_x /= 2;
+
+ switch (svga->gdcreg[5] & 0x60)
+ {
+ case 0x00: svga->video_bpp = 4; break;
+ case 0x20: svga->video_bpp = 2; break;
+ case 0x40: case 0x60: svga->video_bpp = svga->bpp; break;
+ }
+ }
+// if (svga_interlace && oddeven) ma=maback=ma+(svga_rowoffset<<2);
+
+// pclog("Addr %08X vson %03X vsoff %01X %02X %02X %02X %i %i\n",ma,svga_vsyncstart,crtc[0x11]&0xF,crtc[0xD],crtc[0xC],crtc[0x33], svga_interlace, oddeven);
+
+ if (svga->vsync_callback)
+ svga->vsync_callback(svga);
+ }
+ if (svga->vc == svga->vtotal)
+ {
+// pclog("VC vtotal\n");
+
+
+// printf("Frame over at line %i %i %i %i\n",displine,vc,svga_vsyncstart,svga_dispend);
+ svga->vc = 0;
+ svga->sc = svga->crtc[8] & 0x1f;
+ svga->dispon = 1;
+ svga->displine = (svga->interlace && svga->oddeven) ? 1 : 0;
+ svga->scrollcache = svga->attrregs[0x13] & 7;
+ svga->linecountff = 0;
+
+ svga->hwcursor_on = 0;
+ svga->hwcursor_latch = svga->hwcursor;
+
+ svga->overlay_on = 0;
+ svga->overlay_latch = svga->overlay;
+// pclog("Latch HWcursor addr %08X\n", svga_hwcursor_latch.addr);
+
+// pclog("ADDR %08X\n",hwcursor_addr);
+ }
+ if (svga->sc == (svga->crtc[10] & 31))
+ svga->con = 1;
+ }
+// printf("2 %i\n",svga_vsyncstart);
+//pclog("svga_poll %i %i %i %i %i %i %i\n", ins, svga->dispofftime, svga->dispontime, svga->vidtime, cyc_total, svga->linepos, svga->vc);
+}
+
+int svga_init(svga_t *svga, void *p, int memsize,
+ void (*recalctimings_ex)(struct svga_t *svga),
+ uint8_t (*video_in) (uint16_t addr, void *p),
+ void (*video_out)(uint16_t addr, uint8_t val, void *p),
+ void (*hwcursor_draw)(struct svga_t *svga, int displine),
+ void (*overlay_draw)(struct svga_t *svga, int displine))
+{
+ int c, d, e;
+
+ svga->p = p;
+
+ for (c = 0; c < 256; c++)
+ {
+ e = c;
+ for (d = 0; d < 8; d++)
+ {
+ svga_rotate[d][c] = e;
+ e = (e >> 1) | ((e & 1) ? 0x80 : 0);
+ }
+ }
+ svga->readmode = 0;
+
+ svga->crtc[0] = 63;
+ svga->crtc[6] = 255;
+ svga->dispontime = 1000ull << 32;
+ svga->dispofftime = 1000ull << 32;
+ svga->bpp = 8;
+ svga->vram = malloc(memsize);
+ svga->vram_max = memsize;
+ svga->vram_display_mask = memsize - 1;
+ svga->vram_mask = memsize - 1;
+ svga->decode_mask = 0x7fffff;
+ svga->changedvram = malloc(/*(memsize >> 12) << 1*/0x800000 >> 12);
+ svga->recalctimings_ex = recalctimings_ex;
+ svga->video_in = video_in;
+ svga->video_out = video_out;
+ svga->hwcursor_draw = hwcursor_draw;
+ svga->overlay_draw = overlay_draw;
+ svga->hwcursor.ysize = 64;
+// _svga_recalctimings(svga);
+
+ mem_mapping_add(&svga->mapping, 0xa0000, 0x20000, svga_read, svga_readw, svga_readl, svga_write, svga_writew, svga_writel, NULL, MEM_MAPPING_EXTERNAL, svga);
+
+ timer_add(&svga->timer, svga_poll, svga, 1);
+
+ svga_pri = svga;
+
+ svga->ramdac_type = RAMDAC_6BIT;
+
+ return 0;
+}
+
+void svga_close(svga_t *svga)
+{
+ free(svga->changedvram);
+ free(svga->vram);
+
+ svga_pri = NULL;
+}
+
+void svga_write(uint32_t addr, uint8_t val, void *p)
+{
+ svga_t *svga = (svga_t *)p;
+ uint8_t vala, valb, valc, vald, wm = svga->writemask;
+ int writemask2 = svga->writemask;
+
+ egawrites++;
+
+ cycles -= video_timing_write_b;
+ cycles_lost += video_timing_write_b;
+
+ if (svga_output) pclog("Writeega %06X ",addr);
+ addr &= svga->banked_mask;
+ addr += svga->write_bank;
+
+ if (!(svga->gdcreg[6] & 1)) svga->fullchange=2;
+ if (svga->chain4 || svga->fb_only)
+ {
+ writemask2=1<<(addr&3);
+ addr&=~3;
+ }
+ else if (svga->chain2_write)
+ {
+ writemask2 &= ~0xa;
+ if (addr & 1)
+ writemask2 <<= 1;
+ addr &= ~1;
+ addr <<= 2;
+ }
+ else
+ {
+ addr<<=2;
+ }
+ addr &= svga->decode_mask;
+
+ if (addr >= svga->vram_max)
+ return;
+
+ addr &= svga->vram_mask;
+
+ if (svga_output) pclog("%08X (%i, %i) %02X %i %i %i %02X\n", addr, addr & 1023, addr >> 10, val, writemask2, svga->writemode, svga->chain4, svga->gdcreg[8]);
+ svga->changedvram[addr >> 12] = changeframecount;
+
+ switch (svga->writemode)
+ {
+ case 1:
+ if (writemask2 & 1) svga->vram[addr] = svga->la;
+ if (writemask2 & 2) svga->vram[addr | 0x1] = svga->lb;
+ if (writemask2 & 4) svga->vram[addr | 0x2] = svga->lc;
+ if (writemask2 & 8) svga->vram[addr | 0x3] = svga->ld;
+ break;
+ case 0:
+ if (svga->gdcreg[3] & 7)
+ val = svga_rotate[svga->gdcreg[3] & 7][val];
+ if (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && (!svga->gdcreg[1] || svga->set_reset_disabled))
+ {
+ if (writemask2 & 1) svga->vram[addr] = val;
+ if (writemask2 & 2) svga->vram[addr | 0x1] = val;
+ if (writemask2 & 4) svga->vram[addr | 0x2] = val;
+ if (writemask2 & 8) svga->vram[addr | 0x3] = val;
+ }
+ else
+ {
+ if (svga->gdcreg[1] & 1) vala = (svga->gdcreg[0] & 1) ? 0xff : 0;
+ else vala = val;
+ if (svga->gdcreg[1] & 2) valb = (svga->gdcreg[0] & 2) ? 0xff : 0;
+ else valb = val;
+ if (svga->gdcreg[1] & 4) valc = (svga->gdcreg[0] & 4) ? 0xff : 0;
+ else valc = val;
+ if (svga->gdcreg[1] & 8) vald = (svga->gdcreg[0] & 8) ? 0xff : 0;
+ else vald = val;
+
+ switch (svga->gdcreg[3] & 0x18)
+ {
+ case 0: /*Set*/
+ if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]);
+ if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]);
+ if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | (svga->lc & ~svga->gdcreg[8]);
+ if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | (svga->ld & ~svga->gdcreg[8]);
+ break;
+ case 8: /*AND*/
+ if (writemask2 & 1) svga->vram[addr] = (vala | ~svga->gdcreg[8]) & svga->la;
+ if (writemask2 & 2) svga->vram[addr | 0x1] = (valb | ~svga->gdcreg[8]) & svga->lb;
+ if (writemask2 & 4) svga->vram[addr | 0x2] = (valc | ~svga->gdcreg[8]) & svga->lc;
+ if (writemask2 & 8) svga->vram[addr | 0x3] = (vald | ~svga->gdcreg[8]) & svga->ld;
+ break;
+ case 0x10: /*OR*/
+ if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | svga->la;
+ if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | svga->lb;
+ if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | svga->lc;
+ if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | svga->ld;
+ break;
+ case 0x18: /*XOR*/
+ if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) ^ svga->la;
+ if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) ^ svga->lb;
+ if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) ^ svga->lc;
+ if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) ^ svga->ld;
+ break;
+ }
+// pclog("- %02X %02X %02X %02X %08X\n",vram[addr],vram[addr|0x1],vram[addr|0x2],vram[addr|0x3],addr);
+ }
+ break;
+ case 2:
+ if (!(svga->gdcreg[3] & 0x18) && (!svga->gdcreg[1] || svga->set_reset_disabled))
+ {
+ if (writemask2 & 1) svga->vram[addr] = (((val & 1) ? 0xff : 0) & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]);
+ if (writemask2 & 2) svga->vram[addr | 0x1] = (((val & 2) ? 0xff : 0) & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]);
+ if (writemask2 & 4) svga->vram[addr | 0x2] = (((val & 4) ? 0xff : 0) & svga->gdcreg[8]) | (svga->lc & ~svga->gdcreg[8]);
+ if (writemask2 & 8) svga->vram[addr | 0x3] = (((val & 8) ? 0xff : 0) & svga->gdcreg[8]) | (svga->ld & ~svga->gdcreg[8]);
+ }
+ else
+ {
+ vala = ((val & 1) ? 0xff : 0);
+ valb = ((val & 2) ? 0xff : 0);
+ valc = ((val & 4) ? 0xff : 0);
+ vald = ((val & 8) ? 0xff : 0);
+ switch (svga->gdcreg[3] & 0x18)
+ {
+ case 0: /*Set*/
+ if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]);
+ if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]);
+ if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | (svga->lc & ~svga->gdcreg[8]);
+ if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | (svga->ld & ~svga->gdcreg[8]);
+ break;
+ case 8: /*AND*/
+ if (writemask2 & 1) svga->vram[addr] = (vala | ~svga->gdcreg[8]) & svga->la;
+ if (writemask2 & 2) svga->vram[addr | 0x1] = (valb | ~svga->gdcreg[8]) & svga->lb;
+ if (writemask2 & 4) svga->vram[addr | 0x2] = (valc | ~svga->gdcreg[8]) & svga->lc;
+ if (writemask2 & 8) svga->vram[addr | 0x3] = (vald | ~svga->gdcreg[8]) & svga->ld;
+ break;
+ case 0x10: /*OR*/
+ if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | svga->la;
+ if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | svga->lb;
+ if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | svga->lc;
+ if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | svga->ld;
+ break;
+ case 0x18: /*XOR*/
+ if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) ^ svga->la;
+ if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) ^ svga->lb;
+ if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) ^ svga->lc;
+ if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) ^ svga->ld;
+ break;
+ }
+ }
+ break;
+ case 3:
+ if (svga->gdcreg[3] & 7)
+ val = svga_rotate[svga->gdcreg[3] & 7][val];
+ wm = svga->gdcreg[8];
+ svga->gdcreg[8] &= val;
+
+ vala = (svga->gdcreg[0] & 1) ? 0xff : 0;
+ valb = (svga->gdcreg[0] & 2) ? 0xff : 0;
+ valc = (svga->gdcreg[0] & 4) ? 0xff : 0;
+ vald = (svga->gdcreg[0] & 8) ? 0xff : 0;
+ switch (svga->gdcreg[3] & 0x18)
+ {
+ case 0: /*Set*/
+ if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]);
+ if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]);
+ if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | (svga->lc & ~svga->gdcreg[8]);
+ if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | (svga->ld & ~svga->gdcreg[8]);
+ break;
+ case 8: /*AND*/
+ if (writemask2 & 1) svga->vram[addr] = (vala | ~svga->gdcreg[8]) & svga->la;
+ if (writemask2 & 2) svga->vram[addr | 0x1] = (valb | ~svga->gdcreg[8]) & svga->lb;
+ if (writemask2 & 4) svga->vram[addr | 0x2] = (valc | ~svga->gdcreg[8]) & svga->lc;
+ if (writemask2 & 8) svga->vram[addr | 0x3] = (vald | ~svga->gdcreg[8]) & svga->ld;
+ break;
+ case 0x10: /*OR*/
+ if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | svga->la;
+ if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | svga->lb;
+ if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | svga->lc;
+ if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | svga->ld;
+ break;
+ case 0x18: /*XOR*/
+ if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) ^ svga->la;
+ if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) ^ svga->lb;
+ if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) ^ svga->lc;
+ if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) ^ svga->ld;
+ break;
+ }
+ svga->gdcreg[8] = wm;
+ break;
+ }
+}
+
+uint8_t svga_read(uint32_t addr, void *p)
+{
+ svga_t *svga = (svga_t *)p;
+ uint8_t temp, temp2, temp3, temp4;
+ uint32_t latch_addr;
+ int readplane = svga->readplane;
+
+ cycles -= video_timing_read_b;
+ cycles_lost += video_timing_read_b;
+
+ egareads++;
+// pclog("Readega %06X ",addr);
+
+ addr &= svga->banked_mask;
+ addr += svga->read_bank;
+
+ latch_addr = (addr << 2) & svga->decode_mask;
+
+// pclog("%05X %i %04X:%04X %02X %02X %i\n",addr,svga->chain4,CS,pc, vram[addr & 0x7fffff], vram[(addr << 2) & 0x7fffff], svga->readmode);
+// pclog("%i\n", svga->readmode);
+ if (svga->chain4 || svga->fb_only)
+ {
+ addr &= svga->decode_mask;
+ if (addr >= svga->vram_max)
+ return 0xff;
+ return svga->vram[addr & svga->vram_mask];
+ }
+ else if (svga->chain2_read)
+ {
+ readplane = (readplane & 2) | (addr & 1);
+ addr &= ~1;
+ addr <<= 2;
+ }
+ else
+ addr<<=2;
+
+ addr &= svga->decode_mask;
+
+ if (latch_addr >= svga->vram_max)
+ {
+ svga->la = svga->lb = svga->lc = svga->ld = 0xff;
+ }
+ else
+ {
+ latch_addr &= svga->vram_mask;
+ svga->la = svga->vram[latch_addr];
+ svga->lb = svga->vram[latch_addr | 0x1];
+ svga->lc = svga->vram[latch_addr | 0x2];
+ svga->ld = svga->vram[latch_addr | 0x3];
+ }
+
+ if (addr >= svga->vram_max)
+ return 0xff;
+
+ addr &= svga->vram_mask;
+
+ if (svga->readmode)
+ {
+ temp = svga->la;
+ temp ^= (svga->colourcompare & 1) ? 0xff : 0;
+ temp &= (svga->colournocare & 1) ? 0xff : 0;
+ temp2 = svga->lb;
+ temp2 ^= (svga->colourcompare & 2) ? 0xff : 0;
+ temp2 &= (svga->colournocare & 2) ? 0xff : 0;
+ temp3 = svga->lc;
+ temp3 ^= (svga->colourcompare & 4) ? 0xff : 0;
+ temp3 &= (svga->colournocare & 4) ? 0xff : 0;
+ temp4 = svga->ld;
+ temp4 ^= (svga->colourcompare & 8) ? 0xff : 0;
+ temp4 &= (svga->colournocare & 8) ? 0xff : 0;
+ return ~(temp | temp2 | temp3 | temp4);
+ }
+//pclog("Read %02X %04X %04X\n",vram[addr|svga->readplane],addr,svga->readplane);
+
+ return svga->vram[addr | readplane];
+}
+
+void svga_write_linear(uint32_t addr, uint8_t val, void *p)
+{
+ svga_t *svga = (svga_t *)p;
+ uint8_t vala, valb, valc, vald, wm = svga->writemask;
+ int writemask2 = svga->writemask;
+
+ cycles -= video_timing_write_b;
+ cycles_lost += video_timing_write_b;
+
+ egawrites++;
+
+ if (svga_output) pclog("Write LFB %08X %02X ", addr, val);
+ if (!(svga->gdcreg[6] & 1))
+ svga->fullchange = 2;
+ if (svga->chain4 || svga->fb_only)
+ {
+ writemask2=1<<(addr&3);
+ addr&=~3;
+ }
+ else if (svga->chain2_write)
+ {
+ writemask2 &= ~0xa;
+ if (addr & 1)
+ writemask2 <<= 1;
+ addr &= ~1;
+ addr <<= 2;
+ }
+ else
+ {
+ addr<<=2;
+ }
+ addr &= svga->decode_mask;
+ if (addr >= svga->vram_max)
+ return;
+ addr &= svga->vram_mask;
+ if (svga_output) pclog("%08X\n", addr);
+ svga->changedvram[addr >> 12]=changeframecount;
+
+ switch (svga->writemode)
+ {
+ case 1:
+ if (writemask2 & 1) svga->vram[addr] = svga->la;
+ if (writemask2 & 2) svga->vram[addr | 0x1] = svga->lb;
+ if (writemask2 & 4) svga->vram[addr | 0x2] = svga->lc;
+ if (writemask2 & 8) svga->vram[addr | 0x3] = svga->ld;
+ break;
+ case 0:
+ if (svga->gdcreg[3] & 7)
+ val = svga_rotate[svga->gdcreg[3] & 7][val];
+ if (svga->gdcreg[8] == 0xff && !(svga->gdcreg[3] & 0x18) && (!svga->gdcreg[1] || svga->set_reset_disabled))
+ {
+ if (writemask2 & 1) svga->vram[addr] = val;
+ if (writemask2 & 2) svga->vram[addr | 0x1] = val;
+ if (writemask2 & 4) svga->vram[addr | 0x2] = val;
+ if (writemask2 & 8) svga->vram[addr | 0x3] = val;
+ }
+ else
+ {
+ if (svga->gdcreg[1] & 1) vala = (svga->gdcreg[0] & 1) ? 0xff : 0;
+ else vala = val;
+ if (svga->gdcreg[1] & 2) valb = (svga->gdcreg[0] & 2) ? 0xff : 0;
+ else valb = val;
+ if (svga->gdcreg[1] & 4) valc = (svga->gdcreg[0] & 4) ? 0xff : 0;
+ else valc = val;
+ if (svga->gdcreg[1] & 8) vald = (svga->gdcreg[0] & 8) ? 0xff : 0;
+ else vald = val;
+
+ switch (svga->gdcreg[3] & 0x18)
+ {
+ case 0: /*Set*/
+ if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]);
+ if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]);
+ if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | (svga->lc & ~svga->gdcreg[8]);
+ if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | (svga->ld & ~svga->gdcreg[8]);
+ break;
+ case 8: /*AND*/
+ if (writemask2 & 1) svga->vram[addr] = (vala | ~svga->gdcreg[8]) & svga->la;
+ if (writemask2 & 2) svga->vram[addr | 0x1] = (valb | ~svga->gdcreg[8]) & svga->lb;
+ if (writemask2 & 4) svga->vram[addr | 0x2] = (valc | ~svga->gdcreg[8]) & svga->lc;
+ if (writemask2 & 8) svga->vram[addr | 0x3] = (vald | ~svga->gdcreg[8]) & svga->ld;
+ break;
+ case 0x10: /*OR*/
+ if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | svga->la;
+ if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | svga->lb;
+ if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | svga->lc;
+ if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | svga->ld;
+ break;
+ case 0x18: /*XOR*/
+ if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) ^ svga->la;
+ if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) ^ svga->lb;
+ if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) ^ svga->lc;
+ if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) ^ svga->ld;
+ break;
+ }
+// pclog("- %02X %02X %02X %02X %08X\n",vram[addr],vram[addr|0x1],vram[addr|0x2],vram[addr|0x3],addr);
+ }
+ break;
+ case 2:
+ if (!(svga->gdcreg[3] & 0x18) && (!svga->gdcreg[1] || svga->set_reset_disabled))
+ {
+ if (writemask2 & 1) svga->vram[addr] = (((val & 1) ? 0xff : 0) & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]);
+ if (writemask2 & 2) svga->vram[addr | 0x1] = (((val & 2) ? 0xff : 0) & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]);
+ if (writemask2 & 4) svga->vram[addr | 0x2] = (((val & 4) ? 0xff : 0) & svga->gdcreg[8]) | (svga->lc & ~svga->gdcreg[8]);
+ if (writemask2 & 8) svga->vram[addr | 0x3] = (((val & 8) ? 0xff : 0) & svga->gdcreg[8]) | (svga->ld & ~svga->gdcreg[8]);
+ }
+ else
+ {
+ vala = ((val & 1) ? 0xff : 0);
+ valb = ((val & 2) ? 0xff : 0);
+ valc = ((val & 4) ? 0xff : 0);
+ vald = ((val & 8) ? 0xff : 0);
+ switch (svga->gdcreg[3] & 0x18)
+ {
+ case 0: /*Set*/
+ if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]);
+ if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]);
+ if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | (svga->lc & ~svga->gdcreg[8]);
+ if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | (svga->ld & ~svga->gdcreg[8]);
+ break;
+ case 8: /*AND*/
+ if (writemask2 & 1) svga->vram[addr] = (vala | ~svga->gdcreg[8]) & svga->la;
+ if (writemask2 & 2) svga->vram[addr | 0x1] = (valb | ~svga->gdcreg[8]) & svga->lb;
+ if (writemask2 & 4) svga->vram[addr | 0x2] = (valc | ~svga->gdcreg[8]) & svga->lc;
+ if (writemask2 & 8) svga->vram[addr | 0x3] = (vald | ~svga->gdcreg[8]) & svga->ld;
+ break;
+ case 0x10: /*OR*/
+ if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | svga->la;
+ if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | svga->lb;
+ if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | svga->lc;
+ if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | svga->ld;
+ break;
+ case 0x18: /*XOR*/
+ if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) ^ svga->la;
+ if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) ^ svga->lb;
+ if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) ^ svga->lc;
+ if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) ^ svga->ld;
+ break;
+ }
+ }
+ break;
+ case 3:
+ if (svga->gdcreg[3] & 7)
+ val = svga_rotate[svga->gdcreg[3] & 7][val];
+ wm = svga->gdcreg[8];
+ svga->gdcreg[8] &= val;
+
+ vala = (svga->gdcreg[0] & 1) ? 0xff : 0;
+ valb = (svga->gdcreg[0] & 2) ? 0xff : 0;
+ valc = (svga->gdcreg[0] & 4) ? 0xff : 0;
+ vald = (svga->gdcreg[0] & 8) ? 0xff : 0;
+ switch (svga->gdcreg[3] & 0x18)
+ {
+ case 0: /*Set*/
+ if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | (svga->la & ~svga->gdcreg[8]);
+ if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | (svga->lb & ~svga->gdcreg[8]);
+ if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | (svga->lc & ~svga->gdcreg[8]);
+ if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | (svga->ld & ~svga->gdcreg[8]);
+ break;
+ case 8: /*AND*/
+ if (writemask2 & 1) svga->vram[addr] = (vala | ~svga->gdcreg[8]) & svga->la;
+ if (writemask2 & 2) svga->vram[addr | 0x1] = (valb | ~svga->gdcreg[8]) & svga->lb;
+ if (writemask2 & 4) svga->vram[addr | 0x2] = (valc | ~svga->gdcreg[8]) & svga->lc;
+ if (writemask2 & 8) svga->vram[addr | 0x3] = (vald | ~svga->gdcreg[8]) & svga->ld;
+ break;
+ case 0x10: /*OR*/
+ if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) | svga->la;
+ if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) | svga->lb;
+ if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) | svga->lc;
+ if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) | svga->ld;
+ break;
+ case 0x18: /*XOR*/
+ if (writemask2 & 1) svga->vram[addr] = (vala & svga->gdcreg[8]) ^ svga->la;
+ if (writemask2 & 2) svga->vram[addr | 0x1] = (valb & svga->gdcreg[8]) ^ svga->lb;
+ if (writemask2 & 4) svga->vram[addr | 0x2] = (valc & svga->gdcreg[8]) ^ svga->lc;
+ if (writemask2 & 8) svga->vram[addr | 0x3] = (vald & svga->gdcreg[8]) ^ svga->ld;
+ break;
+ }
+ svga->gdcreg[8] = wm;
+ break;
+ }
+}
+
+uint8_t svga_read_linear(uint32_t addr, void *p)
+{
+ svga_t *svga = (svga_t *)p;
+ uint8_t temp, temp2, temp3, temp4;
+ int readplane = svga->readplane;
+ uint32_t latch_addr = (addr << 2) & svga->decode_mask;
+
+ cycles -= video_timing_read_b;
+ cycles_lost += video_timing_read_b;
+
+ egareads++;
+
+ if (svga->chain4 || svga->fb_only)
+ {
+ addr &= svga->decode_mask;
+ if (addr >= svga->vram_max)
+ return 0xff;
+ return svga->vram[addr & svga->vram_mask];
+ }
+ else if (svga->chain2_read)
+ {
+ readplane = (readplane & 2) | (addr & 1);
+ addr &= ~1;
+ addr <<= 2;
+ }
+ else
+ addr<<=2;
+
+ addr &= svga->decode_mask;
+
+ if (latch_addr >= svga->vram_max)
+ {
+ svga->la = svga->lb = svga->lc = svga->ld = 0xff;
+ }
+ else
+ {
+ latch_addr &= svga->vram_mask;
+ svga->la = svga->vram[latch_addr];
+ svga->lb = svga->vram[latch_addr | 0x1];
+ svga->lc = svga->vram[latch_addr | 0x2];
+ svga->ld = svga->vram[latch_addr | 0x3];
+ }
+
+ if (addr >= svga->vram_max)
+ return 0xff;
+
+ addr &= svga->vram_mask;
+
+ if (svga->readmode)
+ {
+ temp = svga->la;
+ temp ^= (svga->colourcompare & 1) ? 0xff : 0;
+ temp &= (svga->colournocare & 1) ? 0xff : 0;
+ temp2 = svga->lb;
+ temp2 ^= (svga->colourcompare & 2) ? 0xff : 0;
+ temp2 &= (svga->colournocare & 2) ? 0xff : 0;
+ temp3 = svga->lc;
+ temp3 ^= (svga->colourcompare & 4) ? 0xff : 0;
+ temp3 &= (svga->colournocare & 4) ? 0xff : 0;
+ temp4 = svga->ld;
+ temp4 ^= (svga->colourcompare & 8) ? 0xff : 0;
+ temp4 &= (svga->colournocare & 8) ? 0xff : 0;
+ return ~(temp | temp2 | temp3 | temp4);
+ }
+//printf("Read %02X %04X %04X\n",vram[addr|svga->readplane],addr,svga->readplane);
+ return svga->vram[addr | readplane];
+}
+
+void svga_doblit(int y1, int y2, int wx, int wy, svga_t *svga)
+{
+// pclog("svga_doblit start\n");
+ svga->frames++;
+// pclog("doblit %i %i\n", y1, y2);
+// pclog("svga_doblit %i %i\n", wx, svga->hdisp);
+ if (y1 > y2)
+ {
+ video_blit_memtoscreen(32, 0, 0, 0, xsize, ysize);
+ return;
+ }
+
+ if ((wx!=xsize || wy!=ysize) && !vid_resize)
+ {
+ xsize=wx;
+ ysize=wy+1;
+ if (xsize<64) xsize=656;
+ if (ysize<32) ysize=200;
+
+ if (svga->vertical_linedbl)
+ updatewindowsize(xsize,ysize*2);
+ else
+ updatewindowsize(xsize,ysize);
+ }
+ if (vid_resize)
+ {
+ xsize = wx;
+ ysize = wy + 1;
+ }
+ video_blit_memtoscreen(32, 0, y1, y2, xsize, ysize);
+// pclog("svga_doblit end\n");
+}
+
+void svga_writew(uint32_t addr, uint16_t val, void *p)
+{
+ svga_t *svga = (svga_t *)p;
+ if (!svga->fast)
+ {
+ svga_write(addr, val, p);
+ svga_write(addr + 1, val >> 8, p);
+ return;
+ }
+
+ egawrites += 2;
+
+ cycles -= video_timing_write_w;
+ cycles_lost += video_timing_write_w;
+
+ if (svga_output) pclog("svga_writew: %05X ", addr);
+ addr = (addr & svga->banked_mask) + svga->write_bank;
+ addr &= svga->decode_mask;
+ if (addr >= svga->vram_max)
+ return;
+ addr &= svga->vram_mask;
+ if (svga_output) pclog("%08X (%i, %i) %04X\n", addr, addr & 1023, addr >> 10, val);
+ svga->changedvram[addr >> 12] = changeframecount;
+ *(uint16_t *)&svga->vram[addr] = val;
+}
+
+void svga_writel(uint32_t addr, uint32_t val, void *p)
+{
+ svga_t *svga = (svga_t *)p;
+
+ if (!svga->fast)
+ {
+ svga_write(addr, val, p);
+ svga_write(addr + 1, val >> 8, p);
+ svga_write(addr + 2, val >> 16, p);
+ svga_write(addr + 3, val >> 24, p);
+ return;
+ }
+
+ egawrites += 4;
+
+ cycles -= video_timing_write_l;
+ cycles_lost += video_timing_write_l;
+
+ if (svga_output) pclog("svga_writel: %05X ", addr);
+ addr = (addr & svga->banked_mask) + svga->write_bank;
+ addr &= svga->decode_mask;
+ if (addr >= svga->vram_max)
+ return;
+ addr &= svga->vram_mask;
+ if (svga_output) pclog("%08X (%i, %i) %08X\n", addr, addr & 1023, addr >> 10, val);
+
+ svga->changedvram[addr >> 12] = changeframecount;
+ *(uint32_t *)&svga->vram[addr] = val;
+}
+
+uint16_t svga_readw(uint32_t addr, void *p)
+{
+ svga_t *svga = (svga_t *)p;
+
+ if (!svga->fast)
+ return svga_read(addr, p) | (svga_read(addr + 1, p) << 8);
+
+ egareads += 2;
+
+ cycles -= video_timing_read_w;
+ cycles_lost += video_timing_read_w;
+
+// pclog("Readw %05X ", addr);
+ addr = (addr & svga->banked_mask) + svga->read_bank;
+ addr &= svga->decode_mask;
+// pclog("%08X %04X\n", addr, *(uint16_t *)&vram[addr]);
+ if (addr >= svga->vram_max)
+ return 0xffff;
+
+ return *(uint16_t *)&svga->vram[addr & svga->vram_mask];
+}
+
+uint32_t svga_readl(uint32_t addr, void *p)
+{
+ svga_t *svga = (svga_t *)p;
+
+ if (!svga->fast)
+ return svga_read(addr, p) | (svga_read(addr + 1, p) << 8) | (svga_read(addr + 2, p) << 16) | (svga_read(addr + 3, p) << 24);
+
+ egareads += 4;
+
+ cycles -= video_timing_read_l;
+ cycles_lost += video_timing_read_l;
+
+// pclog("Readl %05X ", addr);
+ addr = (addr & svga->banked_mask) + svga->read_bank;
+ addr &= svga->decode_mask;
+// pclog("%08X %08X\n", addr, *(uint32_t *)&vram[addr]);
+ if (addr >= svga->vram_max)
+ return 0xffffffff;
+
+ return *(uint32_t *)&svga->vram[addr & svga->vram_mask];
+}
+
+void svga_writew_linear(uint32_t addr, uint16_t val, void *p)
+{
+ svga_t *svga = (svga_t *)p;
+
+ if (!svga->fast)
+ {
+ svga_write_linear(addr, val, p);
+ svga_write_linear(addr + 1, val >> 8, p);
+ return;
+ }
+
+ egawrites += 2;
+
+ cycles -= video_timing_write_w;
+ cycles_lost += video_timing_write_w;
+
+ if (svga_output) pclog("Write LFBw %08X %04X\n", addr, val);
+ addr &= svga->decode_mask;
+ if (addr >= svga->vram_max)
+ return;
+ addr &= svga->vram_mask;
+ svga->changedvram[addr >> 12] = changeframecount;
+ *(uint16_t *)&svga->vram[addr] = val;
+}
+
+void svga_writel_linear(uint32_t addr, uint32_t val, void *p)
+{
+ svga_t *svga = (svga_t *)p;
+
+ if (!svga->fast)
+ {
+ svga_write_linear(addr, val, p);
+ svga_write_linear(addr + 1, val >> 8, p);
+ svga_write_linear(addr + 2, val >> 16, p);
+ svga_write_linear(addr + 3, val >> 24, p);
+ return;
+ }
+
+ egawrites += 4;
+
+ cycles -= video_timing_write_l;
+ cycles_lost += video_timing_write_l;
+
+ if (svga_output) pclog("Write LFBl %08X %08X\n", addr, val);
+ addr &= svga->decode_mask;
+ if (addr >= svga->vram_max)
+ return;
+ addr &= svga->vram_mask;
+ svga->changedvram[addr >> 12] = changeframecount;
+ *(uint32_t *)&svga->vram[addr] = val;
+}
+
+uint16_t svga_readw_linear(uint32_t addr, void *p)
+{
+ svga_t *svga = (svga_t *)p;
+
+ if (!svga->fast)
+ return svga_read_linear(addr, p) | (svga_read_linear(addr + 1, p) << 8);
+
+ egareads += 2;
+
+ cycles -= video_timing_read_w;
+ cycles_lost += video_timing_read_w;
+
+ addr &= svga->decode_mask;
+ if (addr >= svga->vram_max)
+ return 0xffff;
+
+ return *(uint16_t *)&svga->vram[addr & svga->vram_mask];
+}
+
+uint32_t svga_readl_linear(uint32_t addr, void *p)
+{
+ svga_t *svga = (svga_t *)p;
+
+ if (!svga->fast)
+ return svga_read_linear(addr, p) | (svga_read_linear(addr + 1, p) << 8) | (svga_read_linear(addr + 2, p) << 16) | (svga_read_linear(addr + 3, p) << 24);
+
+ egareads += 4;
+
+ cycles -= video_timing_read_l;
+ cycles_lost += video_timing_read_l;
+
+ addr &= svga->decode_mask;
+ if (addr >= svga->vram_max)
+ return 0xffffffff;
+
+ return *(uint32_t *)&svga->vram[addr & svga->vram_mask];
+}
+
+
+void svga_add_status_info(char *s, int max_len, void *p)
+{
+ svga_t *svga = (svga_t *)p;
+ char temps[128];
+
+ if (svga->chain4) strcpy(temps, "SVGA chained (possibly mode 13h)\n");
+ else strcpy(temps, "SVGA unchained (possibly mode-X)\n");
+ strncat(s, temps, max_len);
+
+ if (!svga->video_bpp) strcpy(temps, "SVGA in text mode\n");
+ else sprintf(temps, "SVGA colour depth : %i bpp\n", svga->video_bpp);
+ strncat(s, temps, max_len);
+
+ sprintf(temps, "SVGA resolution : %i x %i\n", svga->video_res_x, svga->video_res_y);
+ strncat(s, temps, max_len);
+
+ sprintf(temps, "SVGA refresh rate : %i Hz\n\n", svga->frames);
+ svga->frames = 0;
+ strncat(s, temps, max_len);
+}
--- /dev/null
+typedef struct svga_t
+{
+ mem_mapping_t mapping;
+
+ uint8_t crtcreg;
+ uint8_t crtc[128];
+ uint8_t gdcreg[64];
+ int gdcaddr;
+ uint8_t attrregs[32];
+ int attraddr, attrff;
+ int attr_palette_enable;
+ uint8_t seqregs[64];
+ int seqaddr;
+
+ uint8_t miscout;
+ int vidclock;
+
+ /*The three variables below allow us to implement memory maps like that seen on a 1MB Trio64 :
+ 0MB-1MB - VRAM
+ 1MB-2MB - VRAM mirror
+ 2MB-4MB - open bus
+ 4MB-xMB - mirror of above
+
+ For the example memory map, decode_mask would be 4MB-1 (4MB address space), vram_max would be 2MB
+ (present video memory only responds to first 2MB), vram_mask would be 1MB-1 (video memory wraps at 1MB)
+ */
+ uint32_t decode_mask;
+ uint32_t vram_max;
+ uint32_t vram_mask;
+
+ uint8_t la, lb, lc, ld;
+
+ uint8_t dac_mask, dac_status;
+ int dac_read, dac_write, dac_pos;
+ int dac_r, dac_g;
+
+ uint8_t cgastat;
+
+ uint8_t plane_mask;
+
+ int fb_only;
+
+ int fast;
+ uint8_t colourcompare, colournocare;
+ int readmode, writemode, readplane;
+ int chain4, chain2_write, chain2_read;
+ uint8_t writemask;
+ uint32_t charseta, charsetb;
+
+ int set_reset_disabled;
+
+ uint8_t egapal[16];
+ uint32_t pallook[256];
+ PALETTE vgapal;
+
+ int ramdac_type;
+
+ int vtotal, dispend, vsyncstart, split, vblankstart;
+ int hdisp, hdisp_old, htotal, hdisp_time, rowoffset;
+ int lowres, interlace;
+ int linedbl, rowcount;
+ double clock;
+ uint32_t ma_latch;
+ int bpp;
+
+ uint64_t dispontime, dispofftime;
+ pc_timer_t timer;
+
+ uint8_t scrblank;
+
+ int dispon;
+ int hdisp_on;
+
+ uint32_t ma, maback, ca;
+ int vc;
+ int sc;
+ int linepos, vslines, linecountff, oddeven;
+ int con, cursoron, blink;
+ int scrollcache;
+ int char_width;
+
+ int firstline, lastline;
+ int firstline_draw, lastline_draw;
+ int displine;
+
+ uint8_t *vram;
+ uint8_t *changedvram;
+ uint32_t vram_display_mask;
+ uint32_t banked_mask;
+
+ uint32_t write_bank, read_bank;
+
+ int fullchange;
+
+ int video_res_x, video_res_y, video_bpp;
+ int frames, fps;
+
+ struct
+ {
+ int ena;
+ int x, y;
+ int xoff, yoff;
+ int xsize, ysize;
+ uint32_t addr;
+ uint32_t pitch;
+ int v_acc, h_acc;
+ } hwcursor, hwcursor_latch, overlay, overlay_latch;
+
+ int hwcursor_on;
+ int overlay_on;
+
+ int hwcursor_oddeven;
+ int overlay_oddeven;
+
+ void (*render)(struct svga_t *svga);
+ void (*recalctimings_ex)(struct svga_t *svga);
+
+ void (*video_out)(uint16_t addr, uint8_t val, void *p);
+ uint8_t (*video_in) (uint16_t addr, void *p);
+
+ void (*hwcursor_draw)(struct svga_t *svga, int displine);
+
+ void (*overlay_draw)(struct svga_t *svga, int displine);
+
+ void (*vblank_start)(struct svga_t *svga);
+
+ /*Called when VC=R18 and friends. If this returns zero then MA resetting
+ is skipped. Matrox Mystique in Power mode reuses this counter for
+ vertical line interrupt*/
+ int (*line_compare)(struct svga_t *svga);
+
+ /*Called at the start of vertical sync*/
+ void (*vsync_callback)(struct svga_t *svga);
+
+ /*If set then another device is driving the monitor output and the SVGA
+ card should not attempt to display anything */
+ int override;
+ void *p;
+
+ uint8_t ksc5601_sbyte_mask;
+
+ int vertical_linedbl;
+
+ /*Used to implement CRTC[0x17] bit 2 hsync divisor*/
+ int hsync_divisor;
+} svga_t;
+
+extern int svga_init(svga_t *svga, void *p, int memsize,
+ void (*recalctimings_ex)(struct svga_t *svga),
+ uint8_t (*video_in) (uint16_t addr, void *p),
+ void (*video_out)(uint16_t addr, uint8_t val, void *p),
+ void (*hwcursor_draw)(struct svga_t *svga, int displine),
+ void (*overlay_draw)(struct svga_t *svga, int displine));
+void svga_close(svga_t *svga);
+extern void svga_recalctimings(svga_t *svga);
+
+
+uint8_t svga_read(uint32_t addr, void *p);
+uint16_t svga_readw(uint32_t addr, void *p);
+uint32_t svga_readl(uint32_t addr, void *p);
+void svga_write(uint32_t addr, uint8_t val, void *p);
+void svga_writew(uint32_t addr, uint16_t val, void *p);
+void svga_writel(uint32_t addr, uint32_t val, void *p);
+uint8_t svga_read_linear(uint32_t addr, void *p);
+uint16_t svga_readw_linear(uint32_t addr, void *p);
+uint32_t svga_readl_linear(uint32_t addr, void *p);
+void svga_write_linear(uint32_t addr, uint8_t val, void *p);
+void svga_writew_linear(uint32_t addr, uint16_t val, void *p);
+void svga_writel_linear(uint32_t addr, uint32_t val, void *p);
+
+void svga_add_status_info(char *s, int max_len, void *p);
+
+extern uint8_t svga_rotate[8][256];
+
+void svga_out(uint16_t addr, uint8_t val, void *p);
+uint8_t svga_in(uint16_t addr, void *p);
+
+svga_t *svga_get_pri();
+void svga_set_override(svga_t *svga, int val);
+
+#define RAMDAC_6BIT 0
+#define RAMDAC_8BIT 1
+void svga_set_ramdac_type(svga_t *svga, int type);
+
+void svga_doblit(int y1, int y2, int wx, int wy, svga_t *svga);
--- /dev/null
+#include "ibm.h"
+#include "mem.h"
+#include "video.h"
+#include "vid_svga.h"
+#include "vid_svga_render.h"
+
+void svga_render_blank(svga_t *svga)
+{
+ int x, xx;
+
+ if (svga->firstline_draw == 2000)
+ svga->firstline_draw = svga->displine;
+ svga->lastline_draw = svga->displine;
+
+ for (x = 0; x < svga->hdisp; x++)
+ {
+ switch (svga->seqregs[1] & 9)
+ {
+ case 0:
+ for (xx = 0; xx < 9; xx++) ((uint32_t *)buffer32->line[svga->displine])[(x * 9) + xx + 32] = 0;
+ break;
+ case 1:
+ for (xx = 0; xx < 8; xx++) ((uint32_t *)buffer32->line[svga->displine])[(x * 8) + xx + 32] = 0;
+ break;
+ case 8:
+ for (xx = 0; xx < 18; xx++) ((uint32_t *)buffer32->line[svga->displine])[(x * 18) + xx + 32] = 0;
+ break;
+ case 9:
+ for (xx = 0; xx < 16; xx++) ((uint32_t *)buffer32->line[svga->displine])[(x * 16) + xx + 32] = 0;
+ break;
+ }
+ }
+}
+
+void svga_render_text_40(svga_t *svga)
+{
+ if (svga->firstline_draw == 2000)
+ svga->firstline_draw = svga->displine;
+ svga->lastline_draw = svga->displine;
+
+ if (svga->fullchange)
+ {
+ int offset = ((8 - svga->scrollcache) << 1) + 16;
+ uint32_t *p = &((uint32_t *)buffer32->line[svga->displine])[offset];
+ int x, xx;
+ int drawcursor;
+ uint8_t chr, attr, dat;
+ uint32_t charaddr;
+ int fg, bg;
+ int xinc = (svga->seqregs[1] & 1) ? 16 : 18;
+
+ for (x = 0; x < svga->hdisp; x += xinc)
+ {
+ drawcursor = ((svga->ma == svga->ca) && svga->con && svga->cursoron);
+ chr = svga->vram[(svga->ma << 1) & svga->vram_display_mask];
+ attr = svga->vram[((svga->ma << 1) + 1) & svga->vram_display_mask];
+ if (attr & 8) charaddr = svga->charsetb + (chr * 128);
+ else charaddr = svga->charseta + (chr * 128);
+
+ if (drawcursor)
+ {
+ bg = svga->pallook[svga->egapal[attr & 15]];
+ fg = svga->pallook[svga->egapal[attr >> 4]];
+ }
+ else
+ {
+ fg = svga->pallook[svga->egapal[attr & 15]];
+ bg = svga->pallook[svga->egapal[attr >> 4]];
+ if (attr & 0x80 && svga->attrregs[0x10] & 8)
+ {
+ bg = svga->pallook[svga->egapal[(attr >> 4) & 7]];
+ if (svga->blink & 16)
+ fg = bg;
+ }
+ }
+
+ dat = svga->vram[charaddr + (svga->sc << 2)];
+ if (svga->seqregs[1] & 1)
+ {
+ for (xx = 0; xx < 16; xx += 2)
+ p[xx] = p[xx + 1] = (dat & (0x80 >> (xx >> 1))) ? fg : bg;
+ }
+ else
+ {
+ for (xx = 0; xx < 16; xx += 2)
+ p[xx] = p[xx + 1] = (dat & (0x80 >> (xx >> 1))) ? fg : bg;
+ if ((chr & ~0x1F) != 0xC0 || !(svga->attrregs[0x10] & 4))
+ p[16] = p[17] = bg;
+ else
+ p[16] = p[17] = (dat & 1) ? fg : bg;
+ }
+ svga->ma += 4;
+ p += xinc;
+ }
+ svga->ma &= svga->vram_display_mask;
+ }
+}
+
+void svga_render_text_80(svga_t *svga)
+{
+ if (svga->firstline_draw == 2000)
+ svga->firstline_draw = svga->displine;
+ svga->lastline_draw = svga->displine;
+
+ if (svga->fullchange)
+ {
+ int offset = (8 - svga->scrollcache) + 24;
+ uint32_t *p = &((uint32_t *)buffer32->line[svga->displine])[offset];
+ int x, xx;
+ int drawcursor;
+ uint8_t chr, attr, dat;
+ uint32_t charaddr;
+ int fg, bg;
+ int xinc = (svga->seqregs[1] & 1) ? 8 : 9;
+
+ for (x = 0; x < svga->hdisp; x += xinc)
+ {
+ drawcursor = ((svga->ma == svga->ca) && svga->con && svga->cursoron);
+ chr = svga->vram[(svga->ma << 1) & svga->vram_display_mask];
+ attr = svga->vram[((svga->ma << 1) + 1) & svga->vram_display_mask];
+ if (attr & 8) charaddr = svga->charsetb + (chr * 128);
+ else charaddr = svga->charseta + (chr * 128);
+
+ if (drawcursor)
+ {
+ bg = svga->pallook[svga->egapal[attr & 15]];
+ fg = svga->pallook[svga->egapal[attr >> 4]];
+ }
+ else
+ {
+ fg = svga->pallook[svga->egapal[attr & 15]];
+ bg = svga->pallook[svga->egapal[attr >> 4]];
+ if (attr & 0x80 && svga->attrregs[0x10] & 8)
+ {
+ bg = svga->pallook[svga->egapal[(attr >> 4) & 7]];
+ if (svga->blink & 16)
+ fg = bg;
+ }
+ }
+
+ dat = svga->vram[charaddr + (svga->sc << 2)];
+ if (svga->seqregs[1] & 1)
+ {
+ for (xx = 0; xx < 8; xx++)
+ p[xx] = (dat & (0x80 >> xx)) ? fg : bg;
+ }
+ else
+ {
+ for (xx = 0; xx < 8; xx++)
+ p[xx] = (dat & (0x80 >> xx)) ? fg : bg;
+ if ((chr & ~0x1F) != 0xC0 || !(svga->attrregs[0x10] & 4))
+ p[8] = bg;
+ else
+ p[8] = (dat & 1) ? fg : bg;
+ }
+ svga->ma += 4;
+ p += xinc;
+ }
+ svga->ma &= svga->vram_display_mask;
+ }
+}
+
+void svga_render_text_80_ksc5601(svga_t *svga)
+{
+ if (svga->firstline_draw == 2000)
+ svga->firstline_draw = svga->displine;
+ svga->lastline_draw = svga->displine;
+
+ if (svga->fullchange)
+ {
+ int offset = (8 - svga->scrollcache) + 24;
+ uint32_t *p = &((uint32_t *)buffer32->line[svga->displine])[offset];
+ int x, xx;
+ int drawcursor;
+ uint8_t chr, attr, dat, nextchr;
+ uint32_t charaddr;
+ int fg, bg;
+ int xinc = (svga->seqregs[1] & 1) ? 8 : 9;
+
+ for (x = 0; x < svga->hdisp; x += xinc)
+ {
+ drawcursor = ((svga->ma == svga->ca) && svga->con && svga->cursoron);
+ chr = svga->vram[(svga->ma << 1) & svga->vram_display_mask];
+ nextchr = svga->vram[((svga->ma + 4) << 1) & svga->vram_display_mask];
+ attr = svga->vram[((svga->ma << 1) + 1) & svga->vram_display_mask];
+
+ if (drawcursor)
+ {
+ bg = svga->pallook[svga->egapal[attr & 15]];
+ fg = svga->pallook[svga->egapal[attr >> 4]];
+ }
+ else
+ {
+ fg = svga->pallook[svga->egapal[attr & 15]];
+ bg = svga->pallook[svga->egapal[attr >> 4]];
+ if (attr & 0x80 && svga->attrregs[0x10] & 8)
+ {
+ bg = svga->pallook[svga->egapal[(attr >> 4) & 7]];
+ if (svga->blink & 16)
+ fg = bg;
+ }
+ }
+
+ if(x + xinc < svga->hdisp && (chr & (nextchr | svga->ksc5601_sbyte_mask) & 0x80))
+ {
+ if((chr == 0xc9 || chr == 0xfe) && (nextchr > 0xa0 && nextchr < 0xff))
+ dat = fontdatksc5601_user[(chr == 0xfe ? 96 : 0) + (nextchr & 0x7F) - 0x20][svga->sc];
+ else if(nextchr & 0x80)
+ dat = fontdatksc5601[((chr & 0x7F) << 7) | (nextchr & 0x7F)][svga->sc];
+ else
+ dat = 0xFF;
+ }
+ else
+ {
+ if (attr & 8) charaddr = svga->charsetb + (chr * 128);
+ else charaddr = svga->charseta + (chr * 128);
+
+ dat = svga->vram[charaddr + (svga->sc << 2)];
+ }
+ if (svga->seqregs[1] & 1)
+ {
+ for (xx = 0; xx < 8; xx++)
+ p[xx] = (dat & (0x80 >> xx)) ? fg : bg;
+ }
+ else
+ {
+ for (xx = 0; xx < 8; xx++)
+ p[xx] = (dat & (0x80 >> xx)) ? fg : bg;
+ if ((chr & ~0x1F) != 0xC0 || !(svga->attrregs[0x10] & 4))
+ p[8] = bg;
+ else
+ p[8] = (dat & 1) ? fg : bg;
+ }
+ svga->ma += 4;
+ p += xinc;
+
+ if(x + xinc < svga->hdisp && (chr & (nextchr | svga->ksc5601_sbyte_mask) & 0x80))
+ {
+ attr = svga->vram[((svga->ma << 1) + 1) & svga->vram_display_mask];
+
+ if (drawcursor)
+ {
+ bg = svga->pallook[svga->egapal[attr & 15]];
+ fg = svga->pallook[svga->egapal[attr >> 4]];
+ }
+ else
+ {
+ fg = svga->pallook[svga->egapal[attr & 15]];
+ bg = svga->pallook[svga->egapal[attr >> 4]];
+ if (attr & 0x80 && svga->attrregs[0x10] & 8)
+ {
+ bg = svga->pallook[svga->egapal[(attr >> 4) & 7]];
+ if (svga->blink & 16)
+ fg = bg;
+ }
+ }
+
+ if((chr == 0xc9 || chr == 0xfe) && (nextchr > 0xa0 && nextchr < 0xff))
+ dat = fontdatksc5601_user[(chr == 0xfe ? 96 : 0) + (nextchr & 0x7F) - 0x20][svga->sc + 16];
+ else if(nextchr & 0x80)
+ dat = fontdatksc5601[((chr & 0x7F) << 7) | (nextchr & 0x7F)][svga->sc + 16];
+ else
+ dat = 0xFF;
+ if (svga->seqregs[1] & 1)
+ {
+ for (xx = 0; xx < 8; xx++)
+ p[xx] = (dat & (0x80 >> xx)) ? fg : bg;
+ }
+ else
+ {
+ for (xx = 0; xx < 8; xx++)
+ p[xx] = (dat & (0x80 >> xx)) ? fg : bg;
+ if ((chr & ~0x1F) != 0xC0 || !(svga->attrregs[0x10] & 4))
+ p[8] = bg;
+ else
+ p[8] = (dat & 1) ? fg : bg;
+ }
+
+ svga->ma += 4;
+ p += xinc;
+ x += xinc;
+ }
+ }
+ svga->ma &= svga->vram_display_mask;
+ }
+}
+
+void svga_render_2bpp_lowres(svga_t *svga)
+{
+ int changed_offset;
+
+ changed_offset = ((svga->ma << 1) + (svga->sc & ~svga->crtc[0x17] & 3) * 0x8000) >> 12;
+
+ if (svga->changedvram[changed_offset] || svga->changedvram[changed_offset + 1] || svga->fullchange)
+ {
+ int x;
+ int offset = ((8 - svga->scrollcache) << 1) + 16;
+ uint32_t *p = &((uint32_t *)buffer32->line[svga->displine])[offset];
+
+ if (svga->firstline_draw == 2000)
+ svga->firstline_draw = svga->displine;
+ svga->lastline_draw = svga->displine;
+
+ for (x = 0; x <= svga->hdisp; x += 16)
+ {
+ uint8_t dat[2];
+
+ dat[0] = svga->vram[(svga->ma << 1) + ((svga->sc & ~svga->crtc[0x17] & 3)) * 0x8000];
+ dat[1] = svga->vram[(svga->ma << 1) + ((svga->sc & ~svga->crtc[0x17] & 3)) * 0x8000 + 1];
+ svga->ma += 4;
+ svga->ma &= svga->vram_display_mask;
+
+ p[0] = p[1] = svga->pallook[svga->egapal[(dat[0] >> 6) & 3]];
+ p[2] = p[3] = svga->pallook[svga->egapal[(dat[0] >> 4) & 3]];
+ p[4] = p[5] = svga->pallook[svga->egapal[(dat[0] >> 2) & 3]];
+ p[6] = p[7] = svga->pallook[svga->egapal[dat[0] & 3]];
+ p[8] = p[9] = svga->pallook[svga->egapal[(dat[1] >> 6) & 3]];
+ p[10] = p[11] = svga->pallook[svga->egapal[(dat[1] >> 4) & 3]];
+ p[12] = p[13] = svga->pallook[svga->egapal[(dat[1] >> 2) & 3]];
+ p[14] = p[15] = svga->pallook[svga->egapal[dat[1] & 3]];
+
+ p += 16;
+ }
+ }
+}
+
+void svga_render_2bpp_highres(svga_t *svga)
+{
+ int changed_offset;
+
+ changed_offset = ((svga->ma << 1) + (svga->sc & ~svga->crtc[0x17] & 3) * 0x8000) >> 12;
+
+ if (svga->changedvram[changed_offset] || svga->changedvram[changed_offset + 1] || svga->fullchange)
+ {
+ int x;
+ int offset = (8 - svga->scrollcache) + 24;
+ uint32_t *p = &((uint32_t *)buffer32->line[svga->displine])[offset];
+
+ if (svga->firstline_draw == 2000)
+ svga->firstline_draw = svga->displine;
+ svga->lastline_draw = svga->displine;
+
+ for (x = 0; x <= svga->hdisp; x += 8)
+ {
+ uint8_t dat[2];
+
+ dat[0] = svga->vram[(svga->ma << 1) + ((svga->sc & ~svga->crtc[0x17] & 3)) * 0x8000];
+ dat[1] = svga->vram[(svga->ma << 1) + ((svga->sc & ~svga->crtc[0x17] & 3)) * 0x8000 + 1];
+ svga->ma += 4;
+ svga->ma &= svga->vram_display_mask;
+
+ p[0] = svga->pallook[svga->egapal[(dat[0] >> 6) & 3]];
+ p[1] = svga->pallook[svga->egapal[(dat[0] >> 4) & 3]];
+ p[2] = svga->pallook[svga->egapal[(dat[0] >> 2) & 3]];
+ p[3] = svga->pallook[svga->egapal[dat[0] & 3]];
+ p[4] = svga->pallook[svga->egapal[(dat[1] >> 6) & 3]];
+ p[5] = svga->pallook[svga->egapal[(dat[1] >> 4) & 3]];
+ p[6] = svga->pallook[svga->egapal[(dat[1] >> 2) & 3]];
+ p[7] = svga->pallook[svga->egapal[dat[1] & 3]];
+
+ p += 8;
+ }
+ }
+}
+
+void svga_render_4bpp_lowres(svga_t *svga)
+{
+ if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange)
+ {
+ int x;
+ int offset = ((8 - svga->scrollcache) << 1) + 16;
+ uint32_t *p = &((uint32_t *)buffer32->line[svga->displine])[offset];
+
+ if (svga->firstline_draw == 2000)
+ svga->firstline_draw = svga->displine;
+ svga->lastline_draw = svga->displine;
+
+ for (x = 0; x <= svga->hdisp; x += 16)
+ {
+ uint8_t edat[4];
+ uint8_t dat;
+
+ *(uint32_t *)(&edat[0]) = *(uint32_t *)(&svga->vram[svga->ma]);
+ svga->ma += 4;
+ svga->ma &= svga->vram_display_mask;
+
+ dat = edatlookup[edat[0] >> 6][edat[1] >> 6] | (edatlookup[edat[2] >> 6][edat[3] >> 6] << 2);
+ p[0] = p[1] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]];
+ p[2] = p[3] = svga->pallook[svga->egapal[dat & svga->plane_mask]];
+ dat = edatlookup[(edat[0] >> 4) & 3][(edat[1] >> 4) & 3] | (edatlookup[(edat[2] >> 4) & 3][(edat[3] >> 4) & 3] << 2);
+ p[4] = p[5] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]];
+ p[6] = p[7] = svga->pallook[svga->egapal[dat & svga->plane_mask]];
+ dat = edatlookup[(edat[0] >> 2) & 3][(edat[1] >> 2) & 3] | (edatlookup[(edat[2] >> 2) & 3][(edat[3] >> 2) & 3] << 2);
+ p[8] = p[9] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]];
+ p[10] = p[11] = svga->pallook[svga->egapal[dat & svga->plane_mask]];
+ dat = edatlookup[edat[0] & 3][edat[1] & 3] | (edatlookup[edat[2] & 3][edat[3] & 3] << 2);
+ p[12] = p[13] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]];
+ p[14] = p[15] = svga->pallook[svga->egapal[dat & svga->plane_mask]];
+
+ p += 16;
+ }
+ }
+}
+
+void svga_render_4bpp_highres(svga_t *svga)
+{
+ int changed_offset;
+
+ changed_offset = (svga->ma + (svga->sc & ~svga->crtc[0x17] & 3) * 0x8000) >> 12;
+
+ if (svga->changedvram[changed_offset] || svga->changedvram[changed_offset + 1] || svga->fullchange)
+ {
+ int x;
+ int offset = (8 - svga->scrollcache) + 24;
+ uint32_t *p = &((uint32_t *)buffer32->line[svga->displine])[offset];
+
+ if (svga->firstline_draw == 2000)
+ svga->firstline_draw = svga->displine;
+ svga->lastline_draw = svga->displine;
+
+ for (x = 0; x <= svga->hdisp; x += 8)
+ {
+ uint8_t edat[4];
+ uint8_t dat;
+
+ *(uint32_t *)(&edat[0]) = *(uint32_t *)(&svga->vram[svga->ma | ((svga->sc & ~svga->crtc[0x17] & 3)) * 0x8000]);
+ svga->ma += 4;
+ svga->ma &= svga->vram_display_mask;
+
+ dat = edatlookup[edat[0] >> 6][edat[1] >> 6] | (edatlookup[edat[2] >> 6][edat[3] >> 6] << 2);
+ p[0] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]];
+ p[1] = svga->pallook[svga->egapal[dat & svga->plane_mask]];
+ dat = edatlookup[(edat[0] >> 4) & 3][(edat[1] >> 4) & 3] | (edatlookup[(edat[2] >> 4) & 3][(edat[3] >> 4) & 3] << 2);
+ p[2] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]];
+ p[3] = svga->pallook[svga->egapal[dat & svga->plane_mask]];
+ dat = edatlookup[(edat[0] >> 2) & 3][(edat[1] >> 2) & 3] | (edatlookup[(edat[2] >> 2) & 3][(edat[3] >> 2) & 3] << 2);
+ p[4] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]];
+ p[5] = svga->pallook[svga->egapal[dat & svga->plane_mask]];
+ dat = edatlookup[edat[0] & 3][edat[1] & 3] | (edatlookup[edat[2] & 3][edat[3] & 3] << 2);
+ p[6] = svga->pallook[svga->egapal[(dat >> 4) & svga->plane_mask]];
+ p[7] = svga->pallook[svga->egapal[dat & svga->plane_mask]];
+
+ p += 8;
+ }
+ }
+}
+
+void svga_render_8bpp_lowres(svga_t *svga)
+{
+ if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange)
+ {
+ int x;
+ int offset = (8 - (svga->scrollcache & 6)) + 24;
+ uint32_t *p = &((uint32_t *)buffer32->line[svga->displine])[offset];
+
+ if (svga->firstline_draw == 2000)
+ svga->firstline_draw = svga->displine;
+ svga->lastline_draw = svga->displine;
+
+ for (x = 0; x <= svga->hdisp; x += 8)
+ {
+ uint32_t dat = *(uint32_t *)(&svga->vram[svga->ma & svga->vram_display_mask]);
+
+ p[0] = p[1] = svga->pallook[dat & 0xff];
+ p[2] = p[3] = svga->pallook[(dat >> 8) & 0xff];
+ p[4] = p[5] = svga->pallook[(dat >> 16) & 0xff];
+ p[6] = p[7] = svga->pallook[(dat >> 24) & 0xff];
+
+ svga->ma += 4;
+ p += 8;
+ }
+ svga->ma &= svga->vram_display_mask;
+ }
+}
+
+void svga_render_8bpp_highres(svga_t *svga)
+{
+ if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange)
+ {
+ int x;
+ int offset = (8 - ((svga->scrollcache & 6) >> 1)) + 24;
+ uint32_t *p = &((uint32_t *)buffer32->line[svga->displine])[offset];
+
+ if (svga->firstline_draw == 2000)
+ svga->firstline_draw = svga->displine;
+ svga->lastline_draw = svga->displine;
+
+ for (x = 0; x <= svga->hdisp; x += 8)
+ {
+ uint32_t dat;
+ dat = *(uint32_t *)(&svga->vram[svga->ma & svga->vram_display_mask]);
+ p[0] = svga->pallook[dat & 0xff];
+ p[1] = svga->pallook[(dat >> 8) & 0xff];
+ p[2] = svga->pallook[(dat >> 16) & 0xff];
+ p[3] = svga->pallook[(dat >> 24) & 0xff];
+
+ dat = *(uint32_t *)(&svga->vram[(svga->ma + 4) & svga->vram_display_mask]);
+ p[4] = svga->pallook[dat & 0xff];
+ p[5] = svga->pallook[(dat >> 8) & 0xff];
+ p[6] = svga->pallook[(dat >> 16) & 0xff];
+ p[7] = svga->pallook[(dat >> 24) & 0xff];
+
+ svga->ma += 8;
+ p += 8;
+ }
+ svga->ma &= svga->vram_display_mask;
+ }
+}
+
+void svga_render_15bpp_lowres(svga_t *svga)
+{
+ if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange)
+ {
+ int x;
+ int offset = (8 - (svga->scrollcache & 6)) + 24;
+ uint32_t *p = &((uint32_t *)buffer32->line[svga->displine])[offset];
+
+ if (svga->firstline_draw == 2000)
+ svga->firstline_draw = svga->displine;
+ svga->lastline_draw = svga->displine;
+
+ for (x = 0; x <= svga->hdisp; x += 4)
+ {
+ uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]);
+
+ p[x] = video_15to32[dat & 0xffff];
+ p[x + 1] = video_15to32[dat >> 16];
+
+ dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]);
+
+ p[x] = video_15to32[dat & 0xffff];
+ p[x + 1] = video_15to32[dat >> 16];
+ }
+ svga->ma += x << 1;
+ svga->ma &= svga->vram_display_mask;
+ }
+}
+
+void svga_render_15bpp_highres(svga_t *svga)
+{
+ if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange)
+ {
+ int x;
+ int offset = (8 - ((svga->scrollcache & 6) >> 1)) + 24;
+ uint32_t *p = &((uint32_t *)buffer32->line[svga->displine])[offset];
+
+ if (svga->firstline_draw == 2000)
+ svga->firstline_draw = svga->displine;
+ svga->lastline_draw = svga->displine;
+
+ for (x = 0; x <= svga->hdisp; x += 8)
+ {
+ uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]);
+ p[x] = video_15to32[dat & 0xffff];
+ p[x + 1] = video_15to32[dat >> 16];
+
+ dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]);
+ p[x + 2] = video_15to32[dat & 0xffff];
+ p[x + 3] = video_15to32[dat >> 16];
+
+ dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 8) & svga->vram_display_mask]);
+ p[x + 4] = video_15to32[dat & 0xffff];
+ p[x + 5] = video_15to32[dat >> 16];
+
+ dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 12) & svga->vram_display_mask]);
+ p[x + 6] = video_15to32[dat & 0xffff];
+ p[x + 7] = video_15to32[dat >> 16];
+ }
+ svga->ma += x << 1;
+ svga->ma &= svga->vram_display_mask;
+ }
+}
+
+void svga_render_16bpp_lowres(svga_t *svga)
+{
+ if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange)
+ {
+ int x;
+ int offset = (8 - (svga->scrollcache & 6)) + 24;
+ uint32_t *p = &((uint32_t *)buffer32->line[svga->displine])[offset];
+
+ if (svga->firstline_draw == 2000)
+ svga->firstline_draw = svga->displine;
+ svga->lastline_draw = svga->displine;
+
+ for (x = 0; x <= svga->hdisp; x += 4)
+ {
+ uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]);
+
+ p[x] = video_16to32[dat & 0xffff];
+ p[x + 1] = video_16to32[dat >> 16];
+
+ dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]);
+
+ p[x] = video_16to32[dat & 0xffff];
+ p[x + 1] = video_16to32[dat >> 16];
+ }
+ svga->ma += x << 1;
+ svga->ma &= svga->vram_display_mask;
+ }
+}
+
+void svga_render_16bpp_highres(svga_t *svga)
+{
+ if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange)
+ {
+ int x;
+ int offset = (8 - ((svga->scrollcache & 6) >> 1)) + 24;
+ uint32_t *p = &((uint32_t *)buffer32->line[svga->displine])[offset];
+
+ if (svga->firstline_draw == 2000)
+ svga->firstline_draw = svga->displine;
+ svga->lastline_draw = svga->displine;
+
+ for (x = 0; x <= svga->hdisp; x += 8)
+ {
+ uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1)) & svga->vram_display_mask]);
+ p[x] = video_16to32[dat & 0xffff];
+ p[x + 1] = video_16to32[dat >> 16];
+
+ dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 4) & svga->vram_display_mask]);
+ p[x + 2] = video_16to32[dat & 0xffff];
+ p[x + 3] = video_16to32[dat >> 16];
+
+ dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 8) & svga->vram_display_mask]);
+ p[x + 4] = video_16to32[dat & 0xffff];
+ p[x + 5] = video_16to32[dat >> 16];
+
+ dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 1) + 12) & svga->vram_display_mask]);
+ p[x + 6] = video_16to32[dat & 0xffff];
+ p[x + 7] = video_16to32[dat >> 16];
+ }
+ svga->ma += x << 1;
+ svga->ma &= svga->vram_display_mask;
+ }
+}
+
+void svga_render_24bpp_lowres(svga_t *svga)
+{
+ int x, offset;
+ uint32_t fg;
+
+ if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange)
+ {
+ if (svga->firstline_draw == 2000)
+ svga->firstline_draw = svga->displine;
+ svga->lastline_draw = svga->displine;
+
+ offset = (8 - (svga->scrollcache & 6)) + 24;
+
+ for (x = 0; x <= svga->hdisp; x++)
+ {
+ fg = svga->vram[svga->ma] | (svga->vram[svga->ma + 1] << 8) | (svga->vram[svga->ma + 2] << 16);
+ svga->ma += 3;
+ svga->ma &= svga->vram_display_mask;
+ ((uint32_t *)buffer32->line[svga->displine])[(x << 1) + offset] = ((uint32_t *)buffer32->line[svga->displine])[(x << 1) + 1 + offset] = fg;
+ }
+ }
+}
+
+void svga_render_24bpp_highres(svga_t *svga)
+{
+ if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange)
+ {
+ int x;
+ int offset = (8 - ((svga->scrollcache & 6) >> 1)) + 24;
+ uint32_t *p = &((uint32_t *)buffer32->line[svga->displine])[offset];
+
+ if (svga->firstline_draw == 2000)
+ svga->firstline_draw = svga->displine;
+ svga->lastline_draw = svga->displine;
+
+ for (x = 0; x <= svga->hdisp; x += 4)
+ {
+ uint32_t dat = *(uint32_t *)(&svga->vram[svga->ma & svga->vram_display_mask]);
+ p[x] = dat & 0xffffff;
+
+ dat = *(uint32_t *)(&svga->vram[(svga->ma + 3) & svga->vram_display_mask]);
+ p[x + 1] = dat & 0xffffff;
+
+ dat = *(uint32_t *)(&svga->vram[(svga->ma + 6) & svga->vram_display_mask]);
+ p[x + 2] = dat & 0xffffff;
+
+ dat = *(uint32_t *)(&svga->vram[(svga->ma + 9) & svga->vram_display_mask]);
+ p[x + 3] = dat & 0xffffff;
+
+ svga->ma += 12;
+ }
+ svga->ma &= svga->vram_display_mask;
+ }
+}
+
+void svga_render_32bpp_lowres(svga_t *svga)
+{
+ int x, offset;
+ uint32_t fg;
+
+ if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->fullchange)
+ {
+ if (svga->firstline_draw == 2000)
+ svga->firstline_draw = svga->displine;
+ svga->lastline_draw = svga->displine;
+
+ offset = (8 - (svga->scrollcache & 6)) + 24;
+
+ for (x = 0; x <= svga->hdisp; x++)
+ {
+ fg = svga->vram[svga->ma] | (svga->vram[svga->ma + 1] << 8) | (svga->vram[svga->ma + 2] << 16);
+ svga->ma += 4;
+ svga->ma &= svga->vram_display_mask;
+ ((uint32_t *)buffer32->line[svga->displine])[(x << 1) + offset] = ((uint32_t *)buffer32->line[svga->displine])[(x << 1) + 1 + offset] = fg;
+ }
+ }
+}
+
+/*72%
+ 91%*/
+void svga_render_32bpp_highres(svga_t *svga)
+{
+ if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->changedvram[(svga->ma >> 12) + 2] || svga->fullchange)
+ {
+ int x;
+ int offset = (8 - ((svga->scrollcache & 6) >> 1)) + 24;
+ uint32_t *p = &((uint32_t *)buffer32->line[svga->displine])[offset];
+
+ if (svga->firstline_draw == 2000)
+ svga->firstline_draw = svga->displine;
+ svga->lastline_draw = svga->displine;
+
+ for (x = 0; x <= svga->hdisp; x++)
+ {
+ uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 2)) & svga->vram_display_mask]);
+ p[x] = dat & 0xffffff;
+ }
+ svga->ma += 4;
+ svga->ma &= svga->vram_display_mask;
+ }
+}
+
+void svga_render_ABGR8888_highres(svga_t *svga)
+{
+ if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->changedvram[(svga->ma >> 12) + 2] || svga->fullchange)
+ {
+ int x;
+ int offset = (8 - ((svga->scrollcache & 6) >> 1)) + 24;
+ uint32_t *p = &((uint32_t *)buffer32->line[svga->displine])[offset];
+
+ if (svga->firstline_draw == 2000)
+ svga->firstline_draw = svga->displine;
+ svga->lastline_draw = svga->displine;
+
+ for (x = 0; x <= svga->hdisp; x++)
+ {
+ uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 2)) & svga->vram_display_mask]);
+ p[x] = ((dat & 0xff0000) >> 16) | (dat & 0x00ff00) | ((dat & 0x0000ff) << 16);
+ }
+ svga->ma += 4;
+ svga->ma &= svga->vram_display_mask;
+ }
+}
+
+void svga_render_RGBA8888_highres(svga_t *svga)
+{
+ if (svga->changedvram[svga->ma >> 12] || svga->changedvram[(svga->ma >> 12) + 1] || svga->changedvram[(svga->ma >> 12) + 2] || svga->fullchange)
+ {
+ int x;
+ int offset = (8 - ((svga->scrollcache & 6) >> 1)) + 24;
+ uint32_t *p = &((uint32_t *)buffer32->line[svga->displine])[offset];
+
+ if (svga->firstline_draw == 2000)
+ svga->firstline_draw = svga->displine;
+ svga->lastline_draw = svga->displine;
+
+ for (x = 0; x <= svga->hdisp; x++)
+ {
+ uint32_t dat = *(uint32_t *)(&svga->vram[(svga->ma + (x << 2)) & svga->vram_display_mask]);
+ p[x] = dat >> 8;
+ }
+ svga->ma += 4;
+ svga->ma &= svga->vram_display_mask;
+ }
+}
--- /dev/null
+extern int firstline_draw, lastline_draw;
+extern int displine;
+extern int sc;
+
+extern uint32_t ma, ca;
+extern int con, cursoron, cgablink;
+
+extern int scrollcache;
+
+extern uint8_t edatlookup[4][4];
+
+void svga_render_blank(svga_t *svga);
+void svga_render_text_40(svga_t *svga);
+void svga_render_text_80(svga_t *svga);
+void svga_render_text_80_ksc5601(svga_t *svga);
+
+void svga_render_2bpp_lowres(svga_t *svga);
+void svga_render_2bpp_highres(svga_t *svga);
+void svga_render_4bpp_lowres(svga_t *svga);
+void svga_render_4bpp_highres(svga_t *svga);
+void svga_render_8bpp_lowres(svga_t *svga);
+void svga_render_8bpp_highres(svga_t *svga);
+void svga_render_15bpp_lowres(svga_t *svga);
+void svga_render_15bpp_highres(svga_t *svga);
+void svga_render_16bpp_lowres(svga_t *svga);
+void svga_render_16bpp_highres(svga_t *svga);
+void svga_render_24bpp_lowres(svga_t *svga);
+void svga_render_24bpp_highres(svga_t *svga);
+void svga_render_32bpp_lowres(svga_t *svga);
+void svga_render_32bpp_highres(svga_t *svga);
+void svga_render_ABGR8888_highres(svga_t *svga);
+void svga_render_RGBA8888_highres(svga_t *svga);
+
+extern void (*svga_render)(svga_t *svga);
--- /dev/null
+typedef struct unk_ramdac_t
+{
+ int state;
+ uint8_t ctrl;
+} unk_ramdac_t;
+
+void unk_ramdac_out(uint16_t addr, uint8_t val, unk_ramdac_t *ramdac, svga_t *svga);
+uint8_t unk_ramdac_in(uint16_t addr, unk_ramdac_t *ramdac, svga_t *svga);
--- /dev/null
+extern device_t vga_device;
+extern device_t ps1vga_device;
+
+void vga_disable(void *p);
+void vga_enable(void *p);
+
+struct svga_t;
+extern struct svga_t *mb_vga;
int video_card_available(int card);
char *video_card_getname(int card);
-struct device_t *video_card_getdevice(int card);
-int video_card_has_config(int card);
+struct device_t *video_card_getdevice(int card, int romset);
+int video_card_has_config(int card, int romset);
int video_card_getid(char *s);
int video_old_to_new(int card);
int video_new_to_old(int card);
void video_wait_for_blit();
void video_wait_for_buffer();
-void loadfont(char *s, int format);
+
+typedef enum
+{
+ FONT_MDA, /* MDA 8x14 */
+ FONT_PC200, /* MDA 8x14 and CGA 8x8, four fonts */
+ FONT_CGA, /* CGA 8x8, two fonts */
+ FONT_WY700, /* Wy700 16x16, two fonts */
+ FONT_MDSI, /* MDSI Genius 8x12 */
+ FONT_T3100E, /* Toshiba T3100e, four fonts */
+ FONT_KSC5601, /* Korean KSC-5601 */
+ FONT_SIGMA400, /* Sigma Color 400, 8x8 and 8x16 */
+ FONT_IM1024, /* Image Manager 1024 */
+} fontformat_t;
+
+void loadfont(char *s, fontformat_t format);
void initvideo();
void video_init();
-extern uint16_t oldcs;
-extern uint32_t rmdat32;
+#ifndef _X86_H_
+#define _X86_H_
+
+#define EAX cpu_state.regs[0].l
+#define ECX cpu_state.regs[1].l
+#define EDX cpu_state.regs[2].l
+#define EBX cpu_state.regs[3].l
+#define ESP cpu_state.regs[4].l
+#define EBP cpu_state.regs[5].l
+#define ESI cpu_state.regs[6].l
+#define EDI cpu_state.regs[7].l
+#define AX cpu_state.regs[0].w
+#define CX cpu_state.regs[1].w
+#define DX cpu_state.regs[2].w
+#define BX cpu_state.regs[3].w
+#define SP cpu_state.regs[4].w
+#define BP cpu_state.regs[5].w
+#define SI cpu_state.regs[6].w
+#define DI cpu_state.regs[7].w
+#define AL cpu_state.regs[0].b.l
+#define AH cpu_state.regs[0].b.h
+#define CL cpu_state.regs[1].b.l
+#define CH cpu_state.regs[1].b.h
+#define DL cpu_state.regs[2].b.l
+#define DH cpu_state.regs[2].b.h
+#define BL cpu_state.regs[3].b.l
+#define BH cpu_state.regs[3].b.h
+
+typedef union
+{
+ uint32_t l;
+ uint16_t w;
+ struct
+ {
+ uint8_t l,h;
+ } b;
+} x86reg;
+
+typedef struct
+{
+ uint32_t base;
+ uint32_t limit;
+ uint8_t access;
+ uint16_t seg;
+ uint32_t limit_low, limit_high;
+ int checked; /*Non-zero if selector is known to be valid*/
+} x86seg;
+
+typedef union MMX_REG
+{
+ uint64_t q;
+ int64_t sq;
+ uint32_t l[2];
+ int32_t sl[2];
+ uint16_t w[4];
+ int16_t sw[4];
+ uint8_t b[8];
+ int8_t sb[8];
+ float f[2];
+} MMX_REG;
+
+struct
+{
+ x86reg regs[8];
+
+ uint8_t tag[8];
+
+ x86seg *ea_seg;
+ uint32_t eaaddr;
+
+ int flags_op;
+ uint32_t flags_res;
+ uint32_t flags_op1, flags_op2;
+
+ uint32_t pc;
+ uint32_t oldpc;
+ uint32_t op32;
+
+ int TOP;
+
+ union
+ {
+ struct
+ {
+ int8_t rm, mod, reg;
+ } rm_mod_reg;
+ uint32_t rm_mod_reg_data;
+ } rm_data;
+
+ int8_t ssegs;
+ int8_t ismmx;
+ int8_t abrt;
+
+ int _cycles;
+ int cpu_recomp_ins;
+
+ uint16_t npxs, npxc;
+
+ double ST[8];
+
+ uint16_t MM_w4[8];
+
+ MMX_REG MM[8];
+
+ uint32_t old_fp_control, new_fp_control;
+#if defined i386 || defined __i386 || defined __i386__ || defined _X86_
+ uint16_t old_fp_control2, new_fp_control2;
+#endif
+#if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined __amd64__
+ uint32_t trunc_fp_control;
+#endif
+ x86seg seg_cs,seg_ds,seg_es,seg_ss,seg_fs,seg_gs;
+
+ union
+ {
+ uint32_t l;
+ uint16_t w;
+ } CR0;
+
+ uint16_t flags, eflags;
+} cpu_state;
+
+#define cpu_state_offset(MEMBER) ((uintptr_t)&cpu_state.MEMBER - (uintptr_t)&cpu_state - 128)
+
+#define cycles cpu_state._cycles
+
+#define cr0 cpu_state.CR0.l
+#define msw cpu_state.CR0.w
+
+/*Segments -
+ _cs,_ds,_es,_ss are the segment structures
+ CS,DS,ES,SS is the 16-bit data
+ cs,ds,es,ss are defines to the bases*/
+#define CS cpu_state.seg_cs.seg
+#define DS cpu_state.seg_ds.seg
+#define ES cpu_state.seg_es.seg
+#define SS cpu_state.seg_ss.seg
+#define FS cpu_state.seg_fs.seg
+#define GS cpu_state.seg_gs.seg
+#define cs cpu_state.seg_cs.base
+#define ds cpu_state.seg_ds.base
+#define es cpu_state.seg_es.base
+#define ss cpu_state.seg_ss.base
+//#define seg_fs _fs.base
+#define gs cpu_state.seg_gs.base
+
+#define CPL ((cpu_state.seg_cs.access>>5)&3)
+
+#define C_FLAG 0x0001
+#define P_FLAG 0x0004
+#define A_FLAG 0x0010
+#define Z_FLAG 0x0040
+#define N_FLAG 0x0080
+#define T_FLAG 0x0100
+#define I_FLAG 0x0200
+#define D_FLAG 0x0400
+#define V_FLAG 0x0800
+#define NT_FLAG 0x4000
+#define VM_FLAG 0x0002 /*In EFLAGS*/
+#define VIF_FLAG 0x0008 /*In EFLAGS*/
+#define VIP_FLAG 0x0010 /*In EFLAGS*/
+
+#define WP_FLAG 0x10000 /*In CR0*/
+
+#define CR4_VME (1 << 0)
+#define CR4_PVI (1 << 1)
+#define CR4_PSE (1 << 4)
+
+#define IOPL ((cpu_state.flags >> 12) & 3)
+
+#define IOPLp ((!(msw&1)) || (CPL<=IOPL))
+
+extern x86seg gdt, ldt, idt, tr;
+
+extern uint32_t cr2, cr3, cr4;
+extern uint32_t dr[8];
+
+
+extern uint16_t cpu_cur_status;
+
+/*The flags below must match in both cpu_cur_status and block->status for a block
+ to be valid*/
+#define CPU_STATUS_USE32 (1 << 0)
+#define CPU_STATUS_STACK32 (1 << 1)
+#define CPU_STATUS_PMODE (1 << 2)
+#define CPU_STATUS_V86 (1 << 3)
+#define CPU_STATUS_FLAGS 0xff
+
+/*If the flags below are set in cpu_cur_status, they must be set in block->status.
+ Otherwise they are ignored*/
+#define CPU_STATUS_NOTFLATDS (1 << 8)
+#define CPU_STATUS_NOTFLATSS (1 << 9)
+#define CPU_STATUS_MASK 0xff00
+
+
+extern uint32_t rmdat;
+#define fetchdat rmdat
+
+extern uint32_t easeg;
+extern uint32_t *eal_r, *eal_w;
+
extern int oldcpl;
+extern uint32_t oldss;
extern int nmi_enable;
-extern int tempc;
-extern int output;
-extern int firstrepcycle;
+extern int trap;
-extern uint32_t easeg,ealimit,ealimitw;
+extern uint32_t use32;
+extern int stack32;
-extern int skipnextprint;
-extern int inhlt;
+extern uint8_t znptable8[256];
+extern uint16_t *mod1add[2][8];
+extern uint32_t *mod1seg[8];
-extern uint8_t opcode;
-extern int noint;
+extern int cgate16, cgate32;
+extern int cpl_override;
+
+extern int x86_was_reset;
-extern uint16_t lastcs,lastpc;
-extern int timetolive,keyboardtimer;
+extern int insc;
+extern int fpucount;
+extern float mips,flops;
#define setznp168 setznp16
#define setr16(r,v) cpu_state.regs[r].w=v
#define setr32(r,v) cpu_state.regs[r].l=v
-extern uint8_t znptable8[256];
-extern uint16_t znptable16[65536];
-
-extern int use32;
-extern int stack32;
-
#define fetchea() { rmdat=readmemb(cs+pc); pc++; \
reg=(rmdat>>3)&7; \
mod=(rmdat>>6)&3; \
#define IRET 3
#define OPTYPE_INT 4
-extern uint32_t oxpc;
-
-extern uint16_t *mod1add[2][8];
-extern uint32_t *mod1seg[8];
-
-
-#define IRQTEST ((flags&I_FLAG) && (pic.pend&~pic.mask) && !noint)
-
-extern int cgate32;
-
-
-extern uint32_t *eal_r, *eal_w;
-
-
-extern uint32_t flags_zn;
-extern uint8_t flags_p;
-#define FLAG_N (flags_zn>>31)
-#define FLAG_Z (flags_zn)
-#define FLAG_P (znptable8[flags_p]&P_FLAG)
-
-extern int gpf;
-
enum
{
void x86_doabrt(int x86_abrt);
-extern uint8_t opcode2;
-
-extern uint16_t rds;
-extern uint32_t rmdat32;
+extern int codegen_flat_ds;
+extern int codegen_flat_ss;
-extern int inscounts[256];
+extern uint32_t pccache;
+extern uint8_t *pccache2;
void x86illegal();
void x86seg_reset();
void x86gpf(char *s, uint16_t error);
-extern uint16_t zero;
-
-extern int x86_was_reset;
-
void resetx86();
void softresetx86();
void refreshread();
void exec386(int cycs);
void exec386_dynarec(int cycs);
-extern int codegen_flat_ds;
-extern int codegen_flat_ss;
+void pmodeint(int num, int soft);
+int loadseg(uint16_t seg, x86seg *s);
+void loadcs(uint16_t seg);
+void loadcscall(uint16_t seg, uint32_t old_pc);
+void loadcsjmp(uint16_t seg, uint32_t old_pc);
+void pmoderetf(int is32, uint16_t off);
+void pmodeiret(int is32);
+
+void x86_int(int num);
+void x86_int_sw(int num);
+int x86_int_sw_rm(int num);
+
+int divl(uint32_t val);
+int idivl(int32_t val);
+
+#endif
+extern int tempc;
+
enum
{
FLAGS_UNKNOWN,
FLAGS_SAR16,
FLAGS_SAR32,
+ FLAGS_ROL8,
+ FLAGS_ROL16,
+ FLAGS_ROL32,
+
+ FLAGS_ROR8,
+ FLAGS_ROR16,
+ FLAGS_ROR32,
+
FLAGS_INC8,
FLAGS_INC16,
FLAGS_INC32,
FLAGS_DEC8,
FLAGS_DEC16,
FLAGS_DEC32,
+
+ FLAGS_ADC8,
+ FLAGS_ADC16,
+ FLAGS_ADC32,
+
+ FLAGS_SBC8,
+ FLAGS_SBC16,
+ FLAGS_SBC32
};
static inline int ZF_SET()
case FLAGS_DEC8:
case FLAGS_DEC16:
case FLAGS_DEC32:
+ case FLAGS_ADC8:
+ case FLAGS_ADC16:
+ case FLAGS_ADC32:
+ case FLAGS_SBC8:
+ case FLAGS_SBC16:
+ case FLAGS_SBC32:
return !cpu_state.flags_res;
+ case FLAGS_ROL8:
+ case FLAGS_ROL16:
+ case FLAGS_ROL32:
+ case FLAGS_ROR8:
+ case FLAGS_ROR16:
+ case FLAGS_ROR32:
case FLAGS_UNKNOWN:
- return flags & Z_FLAG;
+ return cpu_state.flags & Z_FLAG;
}
return 0;
}
case FLAGS_SAR8:
case FLAGS_INC8:
case FLAGS_DEC8:
+ case FLAGS_ADC8:
+ case FLAGS_SBC8:
return cpu_state.flags_res & 0x80;
case FLAGS_ZN16:
case FLAGS_SAR16:
case FLAGS_INC16:
case FLAGS_DEC16:
+ case FLAGS_ADC16:
+ case FLAGS_SBC16:
return cpu_state.flags_res & 0x8000;
case FLAGS_ZN32:
case FLAGS_SAR32:
case FLAGS_INC32:
case FLAGS_DEC32:
+ case FLAGS_ADC32:
+ case FLAGS_SBC32:
return cpu_state.flags_res & 0x80000000;
+ case FLAGS_ROL8:
+ case FLAGS_ROL16:
+ case FLAGS_ROL32:
+ case FLAGS_ROR8:
+ case FLAGS_ROR16:
+ case FLAGS_ROR32:
case FLAGS_UNKNOWN:
- return flags & N_FLAG;
+ return cpu_state.flags & N_FLAG;
}
return 0;
}
case FLAGS_DEC8:
case FLAGS_DEC16:
case FLAGS_DEC32:
+ case FLAGS_ADC8:
+ case FLAGS_ADC16:
+ case FLAGS_ADC32:
+ case FLAGS_SBC8:
+ case FLAGS_SBC16:
+ case FLAGS_SBC32:
return znptable8[cpu_state.flags_res & 0xff] & P_FLAG;
+ case FLAGS_ROL8:
+ case FLAGS_ROL16:
+ case FLAGS_ROL32:
+ case FLAGS_ROR8:
+ case FLAGS_ROR16:
+ case FLAGS_ROR32:
case FLAGS_UNKNOWN:
- return flags & P_FLAG;
+ return cpu_state.flags & P_FLAG;
}
return 0;
}
case FLAGS_SAR32:
return 0;
+ case FLAGS_ADC8:
case FLAGS_ADD8:
case FLAGS_INC8:
return !((cpu_state.flags_op1 ^ cpu_state.flags_op2) & 0x80) && ((cpu_state.flags_op1 ^ cpu_state.flags_res) & 0x80);
+ case FLAGS_ADC16:
case FLAGS_ADD16:
case FLAGS_INC16:
return !((cpu_state.flags_op1 ^ cpu_state.flags_op2) & 0x8000) && ((cpu_state.flags_op1 ^ cpu_state.flags_res) & 0x8000);
+ case FLAGS_ADC32:
case FLAGS_ADD32:
case FLAGS_INC32:
return !((cpu_state.flags_op1 ^ cpu_state.flags_op2) & 0x80000000) && ((cpu_state.flags_op1 ^ cpu_state.flags_res) & 0x80000000);
+ case FLAGS_SBC8:
case FLAGS_SUB8:
case FLAGS_DEC8:
return ((cpu_state.flags_op1 ^ cpu_state.flags_op2) & (cpu_state.flags_op1 ^ cpu_state.flags_res) & 0x80);
+ case FLAGS_SBC16:
case FLAGS_SUB16:
case FLAGS_DEC16:
return ((cpu_state.flags_op1 ^ cpu_state.flags_op2) & (cpu_state.flags_op1 ^ cpu_state.flags_res) & 0x8000);
+ case FLAGS_SBC32:
case FLAGS_SUB32:
case FLAGS_DEC32:
return ((cpu_state.flags_op1 ^ cpu_state.flags_op2) & (cpu_state.flags_op1 ^ cpu_state.flags_res) & 0x80000000);
return ((cpu_state.flags_op2 == 1) && (cpu_state.flags_op1 & 0x8000));
case FLAGS_SHR32:
return ((cpu_state.flags_op2 == 1) && (cpu_state.flags_op1 & 0x80000000));
-
+
+ case FLAGS_ROL8:
+ return (cpu_state.flags_res ^ (cpu_state.flags_res >> 7)) & 1;
+ case FLAGS_ROL16:
+ return (cpu_state.flags_res ^ (cpu_state.flags_res >> 15)) & 1;
+ case FLAGS_ROL32:
+ return (cpu_state.flags_res ^ (cpu_state.flags_res >> 31)) & 1;
+
+ case FLAGS_ROR8:
+ return (cpu_state.flags_res ^ (cpu_state.flags_res >> 1)) & 0x40;
+ case FLAGS_ROR16:
+ return (cpu_state.flags_res ^ (cpu_state.flags_res >> 1)) & 0x4000;
+ case FLAGS_ROR32:
+ return (cpu_state.flags_res ^ (cpu_state.flags_res >> 1)) & 0x40000000;
+
case FLAGS_UNKNOWN:
- return flags & V_FLAG;
+ return cpu_state.flags & V_FLAG;
}
return 0;
}
case FLAGS_INC32:
return ((cpu_state.flags_op1 & 0xF) + (cpu_state.flags_op2 & 0xF)) & 0x10;
+ case FLAGS_ADC8:
+ return ((cpu_state.flags_res & 0xf) < (cpu_state.flags_op1 & 0xf)) ||
+ ((cpu_state.flags_res & 0xf) == (cpu_state.flags_op1 & 0xf) && cpu_state.flags_op2 == 0xff);
+ case FLAGS_ADC16:
+ return ((cpu_state.flags_res & 0xf) < (cpu_state.flags_op1 & 0xf)) ||
+ ((cpu_state.flags_res & 0xf) == (cpu_state.flags_op1 & 0xf) && cpu_state.flags_op2 == 0xffff);
+ case FLAGS_ADC32:
+ return ((cpu_state.flags_res & 0xf) < (cpu_state.flags_op1 & 0xf)) ||
+ ((cpu_state.flags_res & 0xf) == (cpu_state.flags_op1 & 0xf) && cpu_state.flags_op2 == 0xffffffff);
+
case FLAGS_SUB8:
case FLAGS_SUB16:
case FLAGS_SUB32:
case FLAGS_DEC16:
case FLAGS_DEC32:
return ((cpu_state.flags_op1 & 0xF) - (cpu_state.flags_op2 & 0xF)) & 0x10;
+
+ case FLAGS_SBC8:
+ case FLAGS_SBC16:
+ case FLAGS_SBC32:
+ return ((cpu_state.flags_op1 & 0xf) < (cpu_state.flags_op2 & 0xf)) ||
+ ((cpu_state.flags_op1 & 0xf) == (cpu_state.flags_op2 & 0xf) && (cpu_state.flags_res & 0xf) != 0);
+ case FLAGS_ROL8:
+ case FLAGS_ROL16:
+ case FLAGS_ROL32:
+ case FLAGS_ROR8:
+ case FLAGS_ROR16:
+ case FLAGS_ROR32:
case FLAGS_UNKNOWN:
- return flags & A_FLAG;
+ return cpu_state.flags & A_FLAG;
}
return 0;
}
switch (cpu_state.flags_op)
{
case FLAGS_ADD8:
- return (cpu_state.flags_op1 + cpu_state.flags_op2) & 0x100;
+ return ((cpu_state.flags_op1 + cpu_state.flags_op2) & 0x100) ? 1 : 0;
case FLAGS_ADD16:
- return (cpu_state.flags_op1 + cpu_state.flags_op2) & 0x10000;
+ return ((cpu_state.flags_op1 + cpu_state.flags_op2) & 0x10000) ? 1 : 0;
case FLAGS_ADD32:
return (cpu_state.flags_res < cpu_state.flags_op1);
+ case FLAGS_ADC8:
+ return (cpu_state.flags_res < cpu_state.flags_op1) ||
+ (cpu_state.flags_res == cpu_state.flags_op1 && cpu_state.flags_op2 == 0xff);
+ case FLAGS_ADC16:
+ return (cpu_state.flags_res < cpu_state.flags_op1) ||
+ (cpu_state.flags_res == cpu_state.flags_op1 && cpu_state.flags_op2 == 0xffff);
+ case FLAGS_ADC32:
+ return (cpu_state.flags_res < cpu_state.flags_op1) ||
+ (cpu_state.flags_res == cpu_state.flags_op1 && cpu_state.flags_op2 == 0xffffffff);
+
case FLAGS_SUB8:
case FLAGS_SUB16:
case FLAGS_SUB32:
return (cpu_state.flags_op1 < cpu_state.flags_op2);
-
+
+ case FLAGS_SBC8:
+ case FLAGS_SBC16:
+ case FLAGS_SBC32:
+ return (cpu_state.flags_op1 < cpu_state.flags_op2) ||
+ (cpu_state.flags_op1 == cpu_state.flags_op2 && cpu_state.flags_res != 0);
+
case FLAGS_SHL8:
- return (cpu_state.flags_op1 << (cpu_state.flags_op2 - 1)) & 0x80;
+ return ((cpu_state.flags_op1 << (cpu_state.flags_op2 - 1)) & 0x80) ? 1 : 0;
case FLAGS_SHL16:
- return (cpu_state.flags_op1 << (cpu_state.flags_op2 - 1)) & 0x8000;
+ return ((cpu_state.flags_op1 << (cpu_state.flags_op2 - 1)) & 0x8000) ? 1 : 0;
case FLAGS_SHL32:
- return (cpu_state.flags_op1 << (cpu_state.flags_op2 - 1)) & 0x80000000;
+ return ((cpu_state.flags_op1 << (cpu_state.flags_op2 - 1)) & 0x80000000) ? 1 : 0;
case FLAGS_SHR8:
case FLAGS_SHR16:
case FLAGS_ZN16:
case FLAGS_ZN32:
return 0;
+
+ case FLAGS_ROL8:
+ case FLAGS_ROL16:
+ case FLAGS_ROL32:
+ return cpu_state.flags_res & 1;
+
+ case FLAGS_ROR8:
+ return (cpu_state.flags_res & 0x80) ? 1 : 0;
+ case FLAGS_ROR16:
+ return (cpu_state.flags_res & 0x8000) ? 1 :0;
+ case FLAGS_ROR32:
+ return (cpu_state.flags_res & 0x80000000) ? 1 : 0;
case FLAGS_DEC8:
case FLAGS_DEC16:
case FLAGS_INC16:
case FLAGS_INC32:
case FLAGS_UNKNOWN:
- return flags & C_FLAG;
+ return cpu_state.flags & C_FLAG;
}
return 0;
}
if (ZF_SET()) tempf |= Z_FLAG;
if (NF_SET()) tempf |= N_FLAG;
if (VF_SET()) tempf |= V_FLAG;
- flags = (flags & ~0x8d5) | tempf;
+ cpu_state.flags = (cpu_state.flags & ~0x8d5) | tempf;
cpu_state.flags_op = FLAGS_UNKNOWN;
}
}
if (cpu_state.flags_op != FLAGS_UNKNOWN)
{
if (CF_SET())
- flags |= C_FLAG;
+ cpu_state.flags |= C_FLAG;
else
- flags &= ~C_FLAG;
+ cpu_state.flags &= ~C_FLAG;
}
}
+static inline int flags_res_valid()
+{
+ if (cpu_state.flags_op == FLAGS_UNKNOWN ||
+ (cpu_state.flags_op >= FLAGS_ROL8 && cpu_state.flags_op <= FLAGS_ROR32))
+ return 0;
+
+ return 1;
+}
+
static inline void setznp8(uint8_t val)
{
cpu_state.flags_op = FLAGS_ZN8;
cpu_state.flags_op1 = orig; \
cpu_state.flags_op2 = shift;
+#define set_flags_rotate(op, res) \
+ cpu_state.flags_op = op; \
+ cpu_state.flags_res = res;
+
static inline void setadd8(uint8_t a, uint8_t b)
{
cpu_state.flags_op1 = a;
static inline void setadc8(uint8_t a, uint8_t b)
{
- uint16_t c=(uint16_t)a+(uint16_t)b+tempc;
- cpu_state.flags_op = FLAGS_UNKNOWN;
- flags&=~0x8D5;
- flags|=znptable8[c&0xFF];
- if (c&0x100) flags|=C_FLAG;
- if (!((a^b)&0x80)&&((a^c)&0x80)) flags|=V_FLAG;
- if (((a&0xF)+(b&0xF))&0x10) flags|=A_FLAG;
+ cpu_state.flags_op1 = a;
+ cpu_state.flags_op2 = b;
+ cpu_state.flags_res = (a + b + tempc) & 0xff;
+ cpu_state.flags_op = FLAGS_ADC8;
}
static inline void setadc16(uint16_t a, uint16_t b)
{
- uint32_t c=(uint32_t)a+(uint32_t)b+tempc;
- cpu_state.flags_op = FLAGS_UNKNOWN;
- flags&=~0x8D5;
- flags|=znptable16[c&0xFFFF];
- if (c&0x10000) flags|=C_FLAG;
- if (!((a^b)&0x8000)&&((a^c)&0x8000)) flags|=V_FLAG;
- if (((a&0xF)+(b&0xF))&0x10) flags|=A_FLAG;
+ cpu_state.flags_op1 = a;
+ cpu_state.flags_op2 = b;
+ cpu_state.flags_res = (a + b + tempc) & 0xffff;
+ cpu_state.flags_op = FLAGS_ADC16;
+}
+static inline void setadc32(uint32_t a, uint32_t b)
+{
+ cpu_state.flags_op1 = a;
+ cpu_state.flags_op2 = b;
+ cpu_state.flags_res = a + b + tempc;
+ cpu_state.flags_op = FLAGS_ADC32;
}
static inline void setsbc8(uint8_t a, uint8_t b)
{
- uint16_t c=(uint16_t)a-(((uint16_t)b)+tempc);
- cpu_state.flags_op = FLAGS_UNKNOWN;
- flags&=~0x8D5;
- flags|=znptable8[c&0xFF];
- if (c&0x100) flags|=C_FLAG;
- if ((a^b)&(a^c)&0x80) flags|=V_FLAG;
- if (((a&0xF)-(b&0xF))&0x10) flags|=A_FLAG;
+ cpu_state.flags_op1 = a;
+ cpu_state.flags_op2 = b;
+ cpu_state.flags_res = (a - (b + tempc)) & 0xff;
+ cpu_state.flags_op = FLAGS_SBC8;
}
static inline void setsbc16(uint16_t a, uint16_t b)
{
- uint32_t c=(uint32_t)a-(((uint32_t)b)+tempc);
- cpu_state.flags_op = FLAGS_UNKNOWN;
- flags&=~0x8D5;
- flags|=(znptable16[c&0xFFFF]&~4);
- flags|=(znptable8[c&0xFF]&4);
- if (c&0x10000) flags|=C_FLAG;
- if ((a^b)&(a^c)&0x8000) flags|=V_FLAG;
- if (((a&0xF)-(b&0xF))&0x10) flags|=A_FLAG;
-}
-
-static inline void setadc32(uint32_t a, uint32_t b)
-{
- uint32_t c=(uint32_t)a+(uint32_t)b+tempc;
- cpu_state.flags_op = FLAGS_UNKNOWN;
- flags&=~0x8D5;
- flags|=((c&0x80000000)?N_FLAG:((!c)?Z_FLAG:0));
- flags|=(znptable8[c&0xFF]&P_FLAG);
- if ((c<a) || (c==a && tempc)) flags|=C_FLAG;
- if (!((a^b)&0x80000000)&&((a^c)&0x80000000)) flags|=V_FLAG;
- if (((a&0xF)+(b&0xF)+tempc)&0x10) flags|=A_FLAG;
+ cpu_state.flags_op1 = a;
+ cpu_state.flags_op2 = b;
+ cpu_state.flags_res = (a - (b + tempc)) & 0xffff;
+ cpu_state.flags_op = FLAGS_SBC16;
}
static inline void setsbc32(uint32_t a, uint32_t b)
{
- uint32_t c=(uint32_t)a-(((uint32_t)b)+tempc);
- cpu_state.flags_op = FLAGS_UNKNOWN;
- flags&=~0x8D5;
- flags|=((c&0x80000000)?N_FLAG:((!c)?Z_FLAG:0));
- flags|=(znptable8[c&0xFF]&P_FLAG);
- if ((c>a) || (c==a && tempc)) flags|=C_FLAG;
- if ((a^b)&(a^c)&0x80000000) flags|=V_FLAG;
- if (((a&0xF)-((b&0xF)+tempc))&0x10) flags|=A_FLAG;
+ cpu_state.flags_op1 = a;
+ cpu_state.flags_op2 = b;
+ cpu_state.flags_res = a - (b + tempc);
+ cpu_state.flags_op = FLAGS_SBC32;
}
+extern void cpu_386_flags_extract();
+extern void cpu_386_flags_rebuild();
extern OpFn *x86_dynarec_opcodes_df_a32;
extern OpFn *x86_dynarec_opcodes_REPE;
extern OpFn *x86_dynarec_opcodes_REPNE;
+extern OpFn *x86_dynarec_opcodes_3DNOW;
extern OpFn dynarec_ops_286[1024];
extern OpFn dynarec_ops_286_0f[1024];
extern OpFn dynarec_ops_386_0f[1024];
extern OpFn dynarec_ops_winchip_0f[1024];
+extern OpFn dynarec_ops_winchip2_0f[1024];
extern OpFn dynarec_ops_pentium_0f[1024];
extern OpFn dynarec_ops_pentiummmx_0f[1024];
extern OpFn dynarec_ops_REPE[1024];
extern OpFn dynarec_ops_REPNE[1024];
+extern OpFn dynarec_ops_3DNOW[256];
+
extern OpFn *x86_opcodes;
extern OpFn *x86_opcodes_0f;
extern OpFn *x86_opcodes_d8_a16;
extern OpFn *x86_opcodes_df_a32;
extern OpFn *x86_opcodes_REPE;
extern OpFn *x86_opcodes_REPNE;
+extern OpFn *x86_opcodes_3DNOW;
extern OpFn ops_286[1024];
extern OpFn ops_286_0f[1024];
extern OpFn ops_386_0f[1024];
extern OpFn ops_winchip_0f[1024];
+extern OpFn ops_winchip2_0f[1024];
extern OpFn ops_pentium_0f[1024];
extern OpFn ops_pentiummmx_0f[1024];
extern OpFn ops_REPE[1024];
extern OpFn ops_REPNE[1024];
+extern OpFn ops_3DNOW[256];
+
#endif /*_X86_OPS_H*/
--- /dev/null
+#include <math.h>
+
+static int opPREFETCH_a16(uint32_t fetchdat)
+{
+ fetch_ea_16(fetchdat);
+ ILLEGAL_ON(cpu_mod == 3);
+
+ CLOCK_CYCLES(1);
+ return 0;
+}
+static int opPREFETCH_a32(uint32_t fetchdat)
+{
+ fetch_ea_32(fetchdat);
+ ILLEGAL_ON(cpu_mod == 3);
+
+ CLOCK_CYCLES(1);
+ return 0;
+}
+
+static int opFEMMS(uint32_t fetchdat)
+{
+ ILLEGAL_ON(!cpu_has_feature(CPU_FEATURE_MMX));
+ if (cr0 & 0xc)
+ {
+ x86_int(7);
+ return 1;
+ }
+ x87_emms();
+ CLOCK_CYCLES(1);
+ return 0;
+}
+
+static int opPAVGUSB(uint32_t fetchdat)
+{
+ MMX_REG src;
+
+ MMX_GETSRC();
+
+ cpu_state.MM[cpu_reg].b[0] = (cpu_state.MM[cpu_reg].b[0] + src.b[0] + 1) >> 1;
+ cpu_state.MM[cpu_reg].b[1] = (cpu_state.MM[cpu_reg].b[1] + src.b[1] + 1) >> 1;
+ cpu_state.MM[cpu_reg].b[2] = (cpu_state.MM[cpu_reg].b[2] + src.b[2] + 1) >> 1;
+ cpu_state.MM[cpu_reg].b[3] = (cpu_state.MM[cpu_reg].b[3] + src.b[3] + 1) >> 1;
+ cpu_state.MM[cpu_reg].b[4] = (cpu_state.MM[cpu_reg].b[4] + src.b[4] + 1) >> 1;
+ cpu_state.MM[cpu_reg].b[5] = (cpu_state.MM[cpu_reg].b[5] + src.b[5] + 1) >> 1;
+ cpu_state.MM[cpu_reg].b[6] = (cpu_state.MM[cpu_reg].b[6] + src.b[6] + 1) >> 1;
+ cpu_state.MM[cpu_reg].b[7] = (cpu_state.MM[cpu_reg].b[7] + src.b[7] + 1) >> 1;
+
+ return 0;
+}
+static int opPF2ID(uint32_t fetchdat)
+{
+ MMX_REG src;
+
+ MMX_GETSRC();
+
+ cpu_state.MM[cpu_reg].sl[0] = (int32_t)src.f[0];
+ cpu_state.MM[cpu_reg].sl[1] = (int32_t)src.f[1];
+
+ return 0;
+}
+static int opPFACC(uint32_t fetchdat)
+{
+ MMX_REG src;
+ float tempf;
+
+ MMX_GETSRC();
+
+ tempf = cpu_state.MM[cpu_reg].f[0] + cpu_state.MM[cpu_reg].f[1];
+ cpu_state.MM[cpu_reg].f[1] = src.f[0] + src.f[1];
+ cpu_state.MM[cpu_reg].f[0] = tempf;
+
+ return 0;
+}
+static int opPFADD(uint32_t fetchdat)
+{
+ MMX_REG src;
+
+ MMX_GETSRC();
+
+ cpu_state.MM[cpu_reg].f[0] += src.f[0];
+ cpu_state.MM[cpu_reg].f[1] += src.f[1];
+
+ return 0;
+}
+static int opPFCMPEQ(uint32_t fetchdat)
+{
+ MMX_REG src;
+
+ MMX_GETSRC();
+
+ cpu_state.MM[cpu_reg].l[0] = (cpu_state.MM[cpu_reg].f[0] == src.f[0]) ? 0xffffffff : 0;
+ cpu_state.MM[cpu_reg].l[1] = (cpu_state.MM[cpu_reg].f[1] == src.f[1]) ? 0xffffffff : 0;
+
+ return 0;
+}
+static int opPFCMPGE(uint32_t fetchdat)
+{
+ MMX_REG src;
+
+ MMX_GETSRC();
+
+ cpu_state.MM[cpu_reg].l[0] = (cpu_state.MM[cpu_reg].f[0] >= src.f[0]) ? 0xffffffff : 0;
+ cpu_state.MM[cpu_reg].l[1] = (cpu_state.MM[cpu_reg].f[1] >= src.f[1]) ? 0xffffffff : 0;
+
+ return 0;
+}
+static int opPFCMPGT(uint32_t fetchdat)
+{
+ MMX_REG src;
+
+ MMX_GETSRC();
+
+ cpu_state.MM[cpu_reg].l[0] = (cpu_state.MM[cpu_reg].f[0] > src.f[0]) ? 0xffffffff : 0;
+ cpu_state.MM[cpu_reg].l[1] = (cpu_state.MM[cpu_reg].f[1] > src.f[1]) ? 0xffffffff : 0;
+
+ return 0;
+}
+static int opPFMAX(uint32_t fetchdat)
+{
+ MMX_REG src;
+
+ MMX_GETSRC();
+
+ if (src.f[0] > cpu_state.MM[cpu_reg].f[0])
+ cpu_state.MM[cpu_reg].f[0] = src.f[0];
+ if (src.f[1] > cpu_state.MM[cpu_reg].f[1])
+ cpu_state.MM[cpu_reg].f[1] = src.f[1];
+
+ return 0;
+}
+static int opPFMIN(uint32_t fetchdat)
+{
+ MMX_REG src;
+
+ MMX_GETSRC();
+
+ if (src.f[0] < cpu_state.MM[cpu_reg].f[0])
+ cpu_state.MM[cpu_reg].f[0] = src.f[0];
+ if (src.f[1] < cpu_state.MM[cpu_reg].f[1])
+ cpu_state.MM[cpu_reg].f[1] = src.f[1];
+
+ return 0;
+}
+static int opPFMUL(uint32_t fetchdat)
+{
+ MMX_REG src;
+
+ MMX_GETSRC();
+
+ cpu_state.MM[cpu_reg].f[0] *= src.f[0];
+ cpu_state.MM[cpu_reg].f[1] *= src.f[1];
+
+ return 0;
+}
+static int opPFRCP(uint32_t fetchdat)
+{
+ union
+ {
+ uint32_t i;
+ float f;
+ } src;
+
+ if (cpu_mod == 3)
+ {
+ src.f = cpu_state.MM[cpu_rm].f[0];
+ CLOCK_CYCLES(1);
+ }
+ else
+ {
+ SEG_CHECK_READ(cpu_state.ea_seg);
+ src.i = readmeml(easeg, cpu_state.eaaddr); if (cpu_state.abrt) return 1;
+ CLOCK_CYCLES(2);
+ }
+
+ cpu_state.MM[cpu_reg].f[0] = 1.0/src.f;
+ cpu_state.MM[cpu_reg].f[1] = cpu_state.MM[cpu_reg].f[0];
+
+ return 0;
+}
+/*Since opPFRCP() calculates a full precision reciprocal, treat the followup iterations as MOVs*/
+static int opPFRCPIT1(uint32_t fetchdat)
+{
+ MMX_REG src;
+
+ MMX_GETSRC();
+
+ cpu_state.MM[cpu_reg].f[0] = src.f[0];
+ cpu_state.MM[cpu_reg].f[1] = src.f[1];
+
+ return 0;
+}
+static int opPFRCPIT2(uint32_t fetchdat)
+{
+ MMX_REG src;
+
+ MMX_GETSRC();
+
+ cpu_state.MM[cpu_reg].f[0] = src.f[0];
+ cpu_state.MM[cpu_reg].f[1] = src.f[1];
+
+ return 0;
+}
+static int opPFRSQRT(uint32_t fetchdat)
+{
+ union
+ {
+ uint32_t i;
+ float f;
+ } src;
+
+ if (cpu_mod == 3)
+ {
+ src.f = cpu_state.MM[cpu_rm].f[0];
+ CLOCK_CYCLES(1);
+ }
+ else
+ {
+ SEG_CHECK_READ(cpu_state.ea_seg);
+ src.i = readmeml(easeg, cpu_state.eaaddr); if (cpu_state.abrt) return 1;
+ CLOCK_CYCLES(2);
+ }
+
+ cpu_state.MM[cpu_reg].f[0] = 1.0/sqrt(src.f);
+ cpu_state.MM[cpu_reg].f[1] = cpu_state.MM[cpu_reg].f[0];
+
+ return 0;
+}
+/*Since opPFRSQRT() calculates a full precision inverse square root, treat the followup iteration as a NOP*/
+static int opPFRSQIT1(uint32_t fetchdat)
+{
+ MMX_REG src;
+
+ MMX_GETSRC();
+ UNUSED(src);
+
+ return 0;
+}
+static int opPFSUB(uint32_t fetchdat)
+{
+ MMX_REG src;
+
+ MMX_GETSRC();
+
+ cpu_state.MM[cpu_reg].f[0] -= src.f[0];
+ cpu_state.MM[cpu_reg].f[1] -= src.f[1];
+
+ return 0;
+}
+static int opPFSUBR(uint32_t fetchdat)
+{
+ MMX_REG src;
+
+ MMX_GETSRC();
+
+ cpu_state.MM[cpu_reg].f[0] = src.f[0] - cpu_state.MM[cpu_reg].f[0];
+ cpu_state.MM[cpu_reg].f[1] = src.f[1] - cpu_state.MM[cpu_reg].f[1];
+
+ return 0;
+}
+static int opPI2FD(uint32_t fetchdat)
+{
+ MMX_REG src;
+
+ MMX_GETSRC();
+
+ cpu_state.MM[cpu_reg].f[0] = (float)src.sl[0];
+ cpu_state.MM[cpu_reg].f[1] = (float)src.sl[1];
+
+ return 0;
+}
+static int opPMULHRW(uint32_t fetchdat)
+{
+ if (cpu_mod == 3)
+ {
+ cpu_state.MM[cpu_reg].w[0] = (((int32_t)cpu_state.MM[cpu_reg].sw[0] * (int32_t)cpu_state.MM[cpu_rm].sw[0]) + 0x8000) >> 16;
+ cpu_state.MM[cpu_reg].w[1] = (((int32_t)cpu_state.MM[cpu_reg].sw[1] * (int32_t)cpu_state.MM[cpu_rm].sw[1]) + 0x8000) >> 16;
+ cpu_state.MM[cpu_reg].w[2] = (((int32_t)cpu_state.MM[cpu_reg].sw[2] * (int32_t)cpu_state.MM[cpu_rm].sw[2]) + 0x8000) >> 16;
+ cpu_state.MM[cpu_reg].w[3] = (((int32_t)cpu_state.MM[cpu_reg].sw[3] * (int32_t)cpu_state.MM[cpu_rm].sw[3]) + 0x8000) >> 16;
+ CLOCK_CYCLES(1);
+ }
+ else
+ {
+ MMX_REG src;
+
+ SEG_CHECK_READ(cpu_state.ea_seg);
+ src.l[0] = readmeml(easeg, cpu_state.eaaddr);
+ src.l[1] = readmeml(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 0;
+ cpu_state.MM[cpu_reg].w[0] = ((int32_t)(cpu_state.MM[cpu_reg].sw[0] * (int32_t)src.sw[0]) + 0x8000) >> 16;
+ cpu_state.MM[cpu_reg].w[1] = ((int32_t)(cpu_state.MM[cpu_reg].sw[1] * (int32_t)src.sw[1]) + 0x8000) >> 16;
+ cpu_state.MM[cpu_reg].w[2] = ((int32_t)(cpu_state.MM[cpu_reg].sw[2] * (int32_t)src.sw[2]) + 0x8000) >> 16;
+ cpu_state.MM[cpu_reg].w[3] = ((int32_t)(cpu_state.MM[cpu_reg].sw[3] * (int32_t)src.sw[3]) + 0x8000) >> 16;
+ CLOCK_CYCLES(2);
+ }
+ return 0;
+}
+
+OpFn OP_TABLE(3DNOW)[256] =
+{
+/* 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f*/
+/*00*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opPI2FD, ILLEGAL, ILLEGAL,
+/*10*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opPF2ID, ILLEGAL, ILLEGAL,
+/*20*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*30*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+
+/*40*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*50*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*60*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*70*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+
+/*80*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*90*/ opPFCMPGE, ILLEGAL, ILLEGAL, ILLEGAL, opPFMIN, ILLEGAL, opPFRCP, opPFRSQRT, ILLEGAL, ILLEGAL, opPFSUB, ILLEGAL, ILLEGAL, ILLEGAL, opPFADD, ILLEGAL,
+/*a0*/ opPFCMPGT, ILLEGAL, ILLEGAL, ILLEGAL, opPFMAX, ILLEGAL, opPFRCPIT1, opPFRSQIT1, ILLEGAL, ILLEGAL, opPFSUBR, ILLEGAL, ILLEGAL, ILLEGAL, opPFACC, ILLEGAL,
+/*b0*/ opPFCMPEQ, ILLEGAL, ILLEGAL, ILLEGAL, opPFMUL, ILLEGAL, opPFRCPIT2, opPMULHRW, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, opPAVGUSB,
+
+/*c0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*d0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*e0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
+};
+
+static int op3DNOW_a16(uint32_t fetchdat)
+{
+ uint8_t opcode;
+
+ MMX_ENTER();
+
+ fetch_ea_16(fetchdat);
+ opcode = fastreadb(cs + cpu_state.pc);
+ if (cpu_state.abrt) return 1;
+ cpu_state.pc++;
+
+ return x86_opcodes_3DNOW[opcode](0);
+}
+static int op3DNOW_a32(uint32_t fetchdat)
+{
+ uint8_t opcode;
+
+ MMX_ENTER();
+
+ fetch_ea_32(fetchdat);
+ opcode = fastreadb(cs + cpu_state.pc);
+ if (cpu_state.abrt) return 1;
+ cpu_state.pc++;
+
+ return x86_opcodes_3DNOW[opcode](0);
+}
} \
else \
{ \
- uint8_t dst = geteab(); if (cpu_state.abrt) return 1; \
+ uint8_t dst; \
+ SEG_CHECK_WRITE(cpu_state.ea_seg); \
+ dst = geteab(); if (cpu_state.abrt) return 1; \
uint8_t src = getr8(cpu_reg); \
- seteab(operation); if (cpu_state.abrt) return 1; \
+ seteab(operation); if (cpu_state.abrt) return 1; \
setflags ## 8 flagops; \
CLOCK_CYCLES(timing_mr); \
PREFETCH_RUN(timing_mr, 2, rmdat, 1,0,1,0, 0); \
} \
else \
{ \
- uint8_t dst = geteab(); if (cpu_state.abrt) return 1; \
+ uint8_t dst; \
+ SEG_CHECK_WRITE(cpu_state.ea_seg); \
+ dst = geteab(); if (cpu_state.abrt) return 1; \
uint8_t src = getr8(cpu_reg); \
seteab(operation); if (cpu_state.abrt) return 1; \
setflags ## 8 flagops; \
} \
else \
{ \
- uint16_t dst = geteaw(); if (cpu_state.abrt) return 1; \
+ uint16_t dst; \
+ SEG_CHECK_WRITE(cpu_state.ea_seg); \
+ dst = geteaw(); if (cpu_state.abrt) return 1; \
uint16_t src = cpu_state.regs[cpu_reg].w; \
seteaw(operation); if (cpu_state.abrt) return 1; \
setflags ## 16 flagops; \
} \
else \
{ \
- uint16_t dst = geteaw(); if (cpu_state.abrt) return 1; \
+ uint16_t dst; \
+ SEG_CHECK_WRITE(cpu_state.ea_seg); \
+ dst = geteaw(); if (cpu_state.abrt) return 1; \
uint16_t src = cpu_state.regs[cpu_reg].w; \
seteaw(operation); if (cpu_state.abrt) return 1; \
setflags ## 16 flagops; \
} \
else \
{ \
- uint32_t dst = geteal(); if (cpu_state.abrt) return 1; \
+ uint32_t dst; \
+ SEG_CHECK_WRITE(cpu_state.ea_seg); \
+ dst = geteal(); if (cpu_state.abrt) return 1; \
uint32_t src = cpu_state.regs[cpu_reg].l; \
seteal(operation); if (cpu_state.abrt) return 1; \
setflags ## 32 flagops; \
} \
else \
{ \
- uint32_t dst = geteal(); if (cpu_state.abrt) return 1; \
+ uint32_t dst; \
+ SEG_CHECK_WRITE(cpu_state.ea_seg); \
+ dst = geteal(); if (cpu_state.abrt) return 1; \
uint32_t src = cpu_state.regs[cpu_reg].l; \
seteal(operation); if (cpu_state.abrt) return 1; \
setflags ## 32 flagops; \
uint8_t dst, src; \
if (gettempc) tempc = CF_SET() ? 1 : 0; \
fetch_ea_16(fetchdat); \
+ if (cpu_mod != 3) \
+ SEG_CHECK_READ(cpu_state.ea_seg); \
dst = getr8(cpu_reg); \
src = geteab(); if (cpu_state.abrt) return 1; \
setflags ## 8 flagops; \
uint8_t dst, src; \
if (gettempc) tempc = CF_SET() ? 1 : 0; \
fetch_ea_32(fetchdat); \
+ if (cpu_mod != 3) \
+ SEG_CHECK_READ(cpu_state.ea_seg); \
dst = getr8(cpu_reg); \
src = geteab(); if (cpu_state.abrt) return 1; \
setflags ## 8 flagops; \
uint16_t dst, src; \
if (gettempc) tempc = CF_SET() ? 1 : 0; \
fetch_ea_16(fetchdat); \
+ if (cpu_mod != 3) \
+ SEG_CHECK_READ(cpu_state.ea_seg); \
dst = cpu_state.regs[cpu_reg].w; \
src = geteaw(); if (cpu_state.abrt) return 1; \
setflags ## 16 flagops; \
uint16_t dst, src; \
if (gettempc) tempc = CF_SET() ? 1 : 0; \
fetch_ea_32(fetchdat); \
+ if (cpu_mod != 3) \
+ SEG_CHECK_READ(cpu_state.ea_seg); \
dst = cpu_state.regs[cpu_reg].w; \
src = geteaw(); if (cpu_state.abrt) return 1; \
setflags ## 16 flagops; \
uint32_t dst, src; \
if (gettempc) tempc = CF_SET() ? 1 : 0; \
fetch_ea_16(fetchdat); \
+ if (cpu_mod != 3) \
+ SEG_CHECK_READ(cpu_state.ea_seg); \
dst = cpu_state.regs[cpu_reg].l; \
src = geteal(); if (cpu_state.abrt) return 1; \
setflags ## 32 flagops; \
uint32_t dst, src; \
if (gettempc) tempc = CF_SET() ? 1 : 0; \
fetch_ea_32(fetchdat); \
+ if (cpu_mod != 3) \
+ SEG_CHECK_READ(cpu_state.ea_seg); \
dst = cpu_state.regs[cpu_reg].l; \
src = geteal(); if (cpu_state.abrt) return 1; \
setflags ## 32 flagops; \
{
uint8_t dst;
fetch_ea_16(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
dst = geteab(); if (cpu_state.abrt) return 1;
setsub8(dst, getr8(cpu_reg));
if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2);
{
uint8_t dst;
fetch_ea_32(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
dst = geteab(); if (cpu_state.abrt) return 1;
setsub8(dst, getr8(cpu_reg));
if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2);
{
uint16_t dst;
fetch_ea_16(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
dst = geteaw(); if (cpu_state.abrt) return 1;
setsub16(dst, cpu_state.regs[cpu_reg].w);
if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2);
{
uint16_t dst;
fetch_ea_32(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
dst = geteaw(); if (cpu_state.abrt) return 1;
setsub16(dst, cpu_state.regs[cpu_reg].w);
if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2);
{
uint32_t dst;
fetch_ea_16(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
dst = geteal(); if (cpu_state.abrt) return 1;
setsub32(dst, cpu_state.regs[cpu_reg].l);
if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2);
{
uint32_t dst;
fetch_ea_32(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
dst = geteal(); if (cpu_state.abrt) return 1;
setsub32(dst, cpu_state.regs[cpu_reg].l);
if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2);
{
uint8_t src;
fetch_ea_16(fetchdat);
- src = geteab(); if (cpu_state.abrt) return 1;
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
+ src = geteab(); if (cpu_state.abrt) return 1;
setsub8(getr8(cpu_reg), src);
CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_rm);
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 0);
{
uint8_t src;
fetch_ea_32(fetchdat);
- src = geteab(); if (cpu_state.abrt) return 1;
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
+ src = geteab(); if (cpu_state.abrt) return 1;
setsub8(getr8(cpu_reg), src);
CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_rm);
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 1);
{
uint16_t src;
fetch_ea_16(fetchdat);
- src = geteaw(); if (cpu_state.abrt) return 1;
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
+ src = geteaw(); if (cpu_state.abrt) return 1;
setsub16(cpu_state.regs[cpu_reg].w, src);
CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_rm);
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 0);
{
uint16_t src;
fetch_ea_32(fetchdat);
- src = geteaw(); if (cpu_state.abrt) return 1;
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
+ src = geteaw(); if (cpu_state.abrt) return 1;
setsub16(cpu_state.regs[cpu_reg].w, src);
CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_rm);
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 1);
{
uint32_t src;
fetch_ea_16(fetchdat);
- src = geteal(); if (cpu_state.abrt) return 1;
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
+ src = geteal(); if (cpu_state.abrt) return 1;
setsub32(cpu_state.regs[cpu_reg].l, src);
CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_rml);
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1,0,0, 0);
{
uint32_t src;
fetch_ea_32(fetchdat);
- src = geteal(); if (cpu_state.abrt) return 1;
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
+ src = geteal(); if (cpu_state.abrt) return 1;
setsub32(cpu_state.regs[cpu_reg].l, src);
CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_rml);
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1,0,0, 1);
{
uint8_t temp, temp2;
fetch_ea_16(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
temp = geteab(); if (cpu_state.abrt) return 1;
temp2 = getr8(cpu_reg);
setznp8(temp & temp2);
{
uint8_t temp, temp2;
fetch_ea_32(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
temp = geteab(); if (cpu_state.abrt) return 1;
temp2 = getr8(cpu_reg);
setznp8(temp & temp2);
{
uint16_t temp, temp2;
fetch_ea_16(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
temp = geteaw(); if (cpu_state.abrt) return 1;
temp2 = cpu_state.regs[cpu_reg].w;
setznp16(temp & temp2);
{
uint16_t temp, temp2;
fetch_ea_32(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
temp = geteaw(); if (cpu_state.abrt) return 1;
temp2 = cpu_state.regs[cpu_reg].w;
setznp16(temp & temp2);
{
uint32_t temp, temp2;
fetch_ea_16(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
temp = geteal(); if (cpu_state.abrt) return 1;
temp2 = cpu_state.regs[cpu_reg].l;
setznp32(temp & temp2);
{
uint32_t temp, temp2;
fetch_ea_32(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
temp = geteal(); if (cpu_state.abrt) return 1;
temp2 = cpu_state.regs[cpu_reg].l;
setznp32(temp & temp2);
uint8_t src, dst;
fetch_ea_16(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
src = getbyte(); if (cpu_state.abrt) return 1;
ARITH_MULTI(b, 8);
if ((rmdat & 0x38) == 0x38)
uint8_t src, dst;
fetch_ea_32(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
src = getbyte(); if (cpu_state.abrt) return 1;
ARITH_MULTI(b, 8);
if ((rmdat & 0x38) == 0x38)
uint16_t src, dst;
fetch_ea_16(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
src = getword(); if (cpu_state.abrt) return 1;
ARITH_MULTI(w, 16);
if ((rmdat & 0x38) == 0x38)
uint16_t src, dst;
fetch_ea_32(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
src = getword(); if (cpu_state.abrt) return 1;
ARITH_MULTI(w, 16);
if ((rmdat & 0x38) == 0x38)
uint32_t src, dst;
fetch_ea_16(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
src = getlong(); if (cpu_state.abrt) return 1;
ARITH_MULTI(l, 32);
if ((rmdat & 0x38) == 0x38)
uint32_t src, dst;
fetch_ea_32(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
src = getlong(); if (cpu_state.abrt) return 1;
ARITH_MULTI(l, 32);
if ((rmdat & 0x38) == 0x38)
uint16_t src, dst;
fetch_ea_16(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
src = getbyte(); if (cpu_state.abrt) return 1;
if (src & 0x80) src |= 0xff00;
ARITH_MULTI(w, 16);
uint16_t src, dst;
fetch_ea_32(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
src = getbyte(); if (cpu_state.abrt) return 1;
if (src & 0x80) src |= 0xff00;
ARITH_MULTI(w, 16);
uint32_t src, dst;
fetch_ea_16(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
src = getbyte(); if (cpu_state.abrt) return 1;
if (src & 0x80) src |= 0xffffff00;
ARITH_MULTI(l, 32);
uint32_t src, dst;
fetch_ea_32(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
src = getbyte(); if (cpu_state.abrt) return 1;
if (src & 0x80) src |= 0xffffff00;
ARITH_MULTI(l, 32);
return 1;
}
fetch_ea_16(fetchdat);
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = geteab(); if (cpu_state.abrt) return 1;
if (AL == temp) seteab(getr8(cpu_reg));
else AL = temp;
return 1;
}
fetch_ea_32(fetchdat);
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = geteab(); if (cpu_state.abrt) return 1;
if (AL == temp) seteab(getr8(cpu_reg));
else AL = temp;
return 1;
}
fetch_ea_16(fetchdat);
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = geteaw(); if (cpu_state.abrt) return 1;
if (AX == temp) seteaw(cpu_state.regs[cpu_reg].w);
else AX = temp;
return 1;
}
fetch_ea_32(fetchdat);
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = geteaw(); if (cpu_state.abrt) return 1;
if (AX == temp) seteaw(cpu_state.regs[cpu_reg].w);
else AX = temp;
return 1;
}
fetch_ea_16(fetchdat);
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = geteal(); if (cpu_state.abrt) return 1;
if (EAX == temp) seteal(cpu_state.regs[cpu_reg].l);
else EAX = temp;
return 1;
}
fetch_ea_32(fetchdat);
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = geteal(); if (cpu_state.abrt) return 1;
if (EAX == temp) seteal(cpu_state.regs[cpu_reg].l);
else EAX = temp;
return 0;
}
fetch_ea_16(fetchdat);
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = geteal();
temp_hi = readmeml(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 0;
if (EAX == temp && EDX == temp_hi)
if (cpu_state.abrt) return 0;
flags_rebuild();
if (temp == temp2 && temp_hi == temp2_hi)
- flags |= Z_FLAG;
+ cpu_state.flags |= Z_FLAG;
else
- flags &= ~Z_FLAG;
+ cpu_state.flags &= ~Z_FLAG;
cycles -= (cpu_mod == 3) ? 6 : 10;
return 0;
}
return 0;
}
fetch_ea_32(fetchdat);
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = geteal();
temp_hi = readmeml(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 0;
if (EAX == temp && EDX == temp_hi)
if (cpu_state.abrt) return 0;
flags_rebuild();
if (temp == temp2 && temp_hi == temp2_hi)
- flags |= Z_FLAG;
+ cpu_state.flags |= Z_FLAG;
else
- flags &= ~Z_FLAG;
+ cpu_state.flags &= ~Z_FLAG;
cycles -= (cpu_mod == 3) ? 6 : 10;
return 0;
}
return 1;
}
fetch_ea_16(fetchdat);
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = geteab(); if (cpu_state.abrt) return 1;
seteab(temp + getr8(cpu_reg)); if (cpu_state.abrt) return 1;
setadd8(temp, getr8(cpu_reg));
return 1;
}
fetch_ea_32(fetchdat);
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = geteab(); if (cpu_state.abrt) return 1;
seteab(temp + getr8(cpu_reg)); if (cpu_state.abrt) return 1;
setadd8(temp, getr8(cpu_reg));
return 1;
}
fetch_ea_16(fetchdat);
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = geteaw(); if (cpu_state.abrt) return 1;
seteaw(temp + cpu_state.regs[cpu_reg].w); if (cpu_state.abrt) return 1;
setadd16(temp, cpu_state.regs[cpu_reg].w);
return 1;
}
fetch_ea_32(fetchdat);
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = geteaw(); if (cpu_state.abrt) return 1;
seteaw(temp + cpu_state.regs[cpu_reg].w); if (cpu_state.abrt) return 1;
setadd16(temp, cpu_state.regs[cpu_reg].w);
return 1;
}
fetch_ea_16(fetchdat);
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = geteal(); if (cpu_state.abrt) return 1;
seteal(temp + cpu_state.regs[cpu_reg].l); if (cpu_state.abrt) return 1;
setadd32(temp, cpu_state.regs[cpu_reg].l);
return 1;
}
fetch_ea_32(fetchdat);
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = geteal(); if (cpu_state.abrt) return 1;
seteal(temp + cpu_state.regs[cpu_reg].l); if (cpu_state.abrt) return 1;
setadd32(temp, cpu_state.regs[cpu_reg].l);
static int opAAA(uint32_t fetchdat)
{
flags_rebuild();
- if ((flags & A_FLAG) || ((AL & 0xF) > 9))
+ if ((cpu_state.flags & A_FLAG) || ((AL & 0xF) > 9))
{
AL += 6;
AH++;
- flags |= (A_FLAG | C_FLAG);
+ cpu_state.flags |= (A_FLAG | C_FLAG);
}
else
- flags &= ~(A_FLAG | C_FLAG);
+ cpu_state.flags &= ~(A_FLAG | C_FLAG);
AL &= 0xF;
CLOCK_CYCLES(is486 ? 3 : 4);
PREFETCH_RUN(is486 ? 3 : 4, 1, -1, 0,0,0,0, 0);
static int opAAS(uint32_t fetchdat)
{
flags_rebuild();
- if ((flags & A_FLAG) || ((AL & 0xF) > 9))
+ if ((cpu_state.flags & A_FLAG) || ((AL & 0xF) > 9))
{
AL -= 6;
AH--;
- flags |= (A_FLAG | C_FLAG);
+ cpu_state.flags |= (A_FLAG | C_FLAG);
}
else
- flags &= ~(A_FLAG | C_FLAG);
+ cpu_state.flags &= ~(A_FLAG | C_FLAG);
AL &= 0xF;
CLOCK_CYCLES(is486 ? 3 : 4);
PREFETCH_RUN(is486 ? 3 : 4, 1, -1, 0,0,0,0, 0);
uint16_t tempw;
flags_rebuild();
- if ((flags & A_FLAG) || ((AL & 0xf) > 9))
+ if ((cpu_state.flags & A_FLAG) || ((AL & 0xf) > 9))
{
int tempi = ((uint16_t)AL) + 6;
AL += 6;
- flags |= A_FLAG;
- if (tempi & 0x100) flags |= C_FLAG;
+ cpu_state.flags |= A_FLAG;
+ if (tempi & 0x100) cpu_state.flags |= C_FLAG;
}
- if ((flags & C_FLAG) || (AL > 0x9f))
+ if ((cpu_state.flags & C_FLAG) || (AL > 0x9f))
{
AL += 0x60;
- flags |= C_FLAG;
+ cpu_state.flags |= C_FLAG;
}
- tempw = flags & (C_FLAG | A_FLAG);
+ tempw = cpu_state.flags & (C_FLAG | A_FLAG);
setznp8(AL);
flags_rebuild();
- flags |= tempw;
+ cpu_state.flags |= tempw;
CLOCK_CYCLES(4);
PREFETCH_RUN(4, 1, -1, 0,0,0,0, 0);
uint16_t tempw;
flags_rebuild();
- if ((flags & A_FLAG) || ((AL & 0xf) > 9))
+ if ((cpu_state.flags & A_FLAG) || ((AL & 0xf) > 9))
{
int tempi = ((uint16_t)AL) - 6;
AL -= 6;
- flags |= A_FLAG;
- if (tempi & 0x100) flags |= C_FLAG;
+ cpu_state.flags |= A_FLAG;
+ if (tempi & 0x100) cpu_state.flags |= C_FLAG;
}
- if ((flags & C_FLAG) || (AL > 0x9f))
+ if ((cpu_state.flags & C_FLAG) || (AL > 0x9f))
{
AL -= 0x60;
- flags |= C_FLAG;
+ cpu_state.flags |= C_FLAG;
}
- tempw = flags & (C_FLAG | A_FLAG);
+ tempw = cpu_state.flags & (C_FLAG | A_FLAG);
setznp8(AL);
flags_rebuild();
- flags |= tempw;
+ cpu_state.flags |= tempw;
CLOCK_CYCLES(4);
PREFETCH_RUN(4, 1, -1, 0,0,0,0, 0);
uint16_t temp;
fetch_ea_16(fetchdat);
+ SEG_CHECK_READ(cpu_state.ea_seg);
cpu_state.eaaddr += ((cpu_state.regs[cpu_reg].w / 16) * 2); eal_r = 0;
temp = geteaw(); if (cpu_state.abrt) return 1;
flags_rebuild();
- if (temp & (1 << (cpu_state.regs[cpu_reg].w & 15))) flags |= C_FLAG;
- else flags &= ~C_FLAG;
+ if (temp & (1 << (cpu_state.regs[cpu_reg].w & 15))) cpu_state.flags |= C_FLAG;
+ else cpu_state.flags &= ~C_FLAG;
CLOCK_CYCLES(3);
PREFETCH_RUN(3, 2, rmdat, 1,0,0,0, 0);
uint16_t temp;
fetch_ea_32(fetchdat);
+ SEG_CHECK_READ(cpu_state.ea_seg);
cpu_state.eaaddr += ((cpu_state.regs[cpu_reg].w / 16) * 2); eal_r = 0;
temp = geteaw(); if (cpu_state.abrt) return 1;
flags_rebuild();
- if (temp & (1 << (cpu_state.regs[cpu_reg].w & 15))) flags |= C_FLAG;
- else flags &= ~C_FLAG;
+ if (temp & (1 << (cpu_state.regs[cpu_reg].w & 15))) cpu_state.flags |= C_FLAG;
+ else cpu_state.flags &= ~C_FLAG;
CLOCK_CYCLES(3);
PREFETCH_RUN(3, 2, rmdat, 1,0,0,0, 1);
uint32_t temp;
fetch_ea_16(fetchdat);
+ SEG_CHECK_READ(cpu_state.ea_seg);
cpu_state.eaaddr += ((cpu_state.regs[cpu_reg].l / 32) * 4); eal_r = 0;
temp = geteal(); if (cpu_state.abrt) return 1;
flags_rebuild();
- if (temp & (1 << (cpu_state.regs[cpu_reg].l & 31))) flags |= C_FLAG;
- else flags &= ~C_FLAG;
+ if (temp & (1 << (cpu_state.regs[cpu_reg].l & 31))) cpu_state.flags |= C_FLAG;
+ else cpu_state.flags &= ~C_FLAG;
CLOCK_CYCLES(3);
PREFETCH_RUN(3, 2, rmdat, 0,1,0,0, 0);
uint32_t temp;
fetch_ea_32(fetchdat);
+ SEG_CHECK_READ(cpu_state.ea_seg);
cpu_state.eaaddr += ((cpu_state.regs[cpu_reg].l / 32) * 4); eal_r = 0;
temp = geteal(); if (cpu_state.abrt) return 1;
flags_rebuild();
- if (temp & (1 << (cpu_state.regs[cpu_reg].l & 31))) flags |= C_FLAG;
- else flags &= ~C_FLAG;
+ if (temp & (1 << (cpu_state.regs[cpu_reg].l & 31))) cpu_state.flags |= C_FLAG;
+ else cpu_state.flags &= ~C_FLAG;
CLOCK_CYCLES(3);
PREFETCH_RUN(3, 2, rmdat, 0,1,0,0, 1);
uint16_t temp; \
\
fetch_ea_16(fetchdat); \
+ if (cpu_mod != 3) \
+ SEG_CHECK_WRITE(cpu_state.ea_seg); \
cpu_state.eaaddr += ((cpu_state.regs[cpu_reg].w / 16) * 2); eal_r = eal_w = 0; \
temp = geteaw(); if (cpu_state.abrt) return 1; \
tempc = (temp & (1 << (cpu_state.regs[cpu_reg].w & 15))) ? 1 : 0; \
temp operation (1 << (cpu_state.regs[cpu_reg].w & 15)); \
seteaw(temp); if (cpu_state.abrt) return 1; \
flags_rebuild(); \
- if (tempc) flags |= C_FLAG; \
- else flags &= ~C_FLAG; \
+ if (tempc) cpu_state.flags |= C_FLAG; \
+ else cpu_state.flags &= ~C_FLAG; \
\
CLOCK_CYCLES(6); \
PREFETCH_RUN(6, 2, rmdat, 1,0,1,0, 0); \
uint16_t temp; \
\
fetch_ea_32(fetchdat); \
+ if (cpu_mod != 3) \
+ SEG_CHECK_WRITE(cpu_state.ea_seg); \
cpu_state.eaaddr += ((cpu_state.regs[cpu_reg].w / 16) * 2); eal_r = eal_w = 0; \
temp = geteaw(); if (cpu_state.abrt) return 1; \
tempc = (temp & (1 << (cpu_state.regs[cpu_reg].w & 15))) ? 1 : 0; \
temp operation (1 << (cpu_state.regs[cpu_reg].w & 15)); \
seteaw(temp); if (cpu_state.abrt) return 1; \
flags_rebuild(); \
- if (tempc) flags |= C_FLAG; \
- else flags &= ~C_FLAG; \
+ if (tempc) cpu_state.flags |= C_FLAG; \
+ else cpu_state.flags &= ~C_FLAG; \
\
CLOCK_CYCLES(6); \
PREFETCH_RUN(6, 2, rmdat, 1,0,1,0, 1); \
uint32_t temp; \
\
fetch_ea_16(fetchdat); \
+ if (cpu_mod != 3) \
+ SEG_CHECK_WRITE(cpu_state.ea_seg); \
cpu_state.eaaddr += ((cpu_state.regs[cpu_reg].l / 32) * 4); eal_r = eal_w = 0; \
temp = geteal(); if (cpu_state.abrt) return 1; \
tempc = (temp & (1 << (cpu_state.regs[cpu_reg].l & 31))) ? 1 : 0; \
temp operation (1 << (cpu_state.regs[cpu_reg].l & 31)); \
seteal(temp); if (cpu_state.abrt) return 1; \
flags_rebuild(); \
- if (tempc) flags |= C_FLAG; \
- else flags &= ~C_FLAG; \
+ if (tempc) cpu_state.flags |= C_FLAG; \
+ else cpu_state.flags &= ~C_FLAG; \
\
CLOCK_CYCLES(6); \
PREFETCH_RUN(6, 2, rmdat, 0,1,0,1, 0); \
uint32_t temp; \
\
fetch_ea_32(fetchdat); \
+ if (cpu_mod != 3) \
+ SEG_CHECK_WRITE(cpu_state.ea_seg); \
cpu_state.eaaddr += ((cpu_state.regs[cpu_reg].l / 32) * 4); eal_r = eal_w = 0; \
temp = geteal(); if (cpu_state.abrt) return 1; \
tempc = (temp & (1 << (cpu_state.regs[cpu_reg].l & 31))) ? 1 : 0; \
temp operation (1 << (cpu_state.regs[cpu_reg].l & 31)); \
seteal(temp); if (cpu_state.abrt) return 1; \
flags_rebuild(); \
- if (tempc) flags |= C_FLAG; \
- else flags &= ~C_FLAG; \
+ if (tempc) cpu_state.flags |= C_FLAG; \
+ else cpu_state.flags &= ~C_FLAG; \
\
CLOCK_CYCLES(6); \
PREFETCH_RUN(6, 2, rmdat, 0,1,0,1, 1); \
uint16_t temp;
fetch_ea_16(fetchdat);
-
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
+
temp = geteaw();
count = getbyte(); if (cpu_state.abrt) return 1;
tempc = temp & (1 << count);
switch (rmdat & 0x38)
{
case 0x20: /*BT w,imm*/
- if (tempc) flags |= C_FLAG;
- else flags &= ~C_FLAG;
+ if (tempc) cpu_state.flags |= C_FLAG;
+ else cpu_state.flags &= ~C_FLAG;
CLOCK_CYCLES(3);
PREFETCH_RUN(3, 3, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0);
return 0;
break;
}
seteaw(temp); if (cpu_state.abrt) return 1;
- if (tempc) flags |= C_FLAG;
- else flags &= ~C_FLAG;
+ if (tempc) cpu_state.flags |= C_FLAG;
+ else cpu_state.flags &= ~C_FLAG;
CLOCK_CYCLES(6);
PREFETCH_RUN(6, 3, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 0);
return 0;
uint16_t temp;
fetch_ea_32(fetchdat);
-
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
+
temp = geteaw();
count = getbyte(); if (cpu_state.abrt) return 1;
tempc = temp & (1 << count);
switch (rmdat & 0x38)
{
case 0x20: /*BT w,imm*/
- if (tempc) flags |= C_FLAG;
- else flags &= ~C_FLAG;
+ if (tempc) cpu_state.flags |= C_FLAG;
+ else cpu_state.flags &= ~C_FLAG;
CLOCK_CYCLES(3);
PREFETCH_RUN(3, 3, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1);
return 0;
break;
}
seteaw(temp); if (cpu_state.abrt) return 1;
- if (tempc) flags |= C_FLAG;
- else flags &= ~C_FLAG;
+ if (tempc) cpu_state.flags |= C_FLAG;
+ else cpu_state.flags &= ~C_FLAG;
CLOCK_CYCLES(6);
PREFETCH_RUN(6, 3, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 0);
return 0;
uint32_t temp;
fetch_ea_16(fetchdat);
-
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
+
temp = geteal();
count = getbyte(); if (cpu_state.abrt) return 1;
tempc = temp & (1 << count);
switch (rmdat & 0x38)
{
case 0x20: /*BT w,imm*/
- if (tempc) flags |= C_FLAG;
- else flags &= ~C_FLAG;
+ if (tempc) cpu_state.flags |= C_FLAG;
+ else cpu_state.flags &= ~C_FLAG;
CLOCK_CYCLES(3);
PREFETCH_RUN(3, 3, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 0);
return 0;
break;
}
seteal(temp); if (cpu_state.abrt) return 1;
- if (tempc) flags |= C_FLAG;
- else flags &= ~C_FLAG;
+ if (tempc) cpu_state.flags |= C_FLAG;
+ else cpu_state.flags &= ~C_FLAG;
CLOCK_CYCLES(6);
PREFETCH_RUN(6, 3, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 0);
return 0;
uint32_t temp;
fetch_ea_32(fetchdat);
-
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
+
temp = geteal();
count = getbyte(); if (cpu_state.abrt) return 1;
tempc = temp & (1 << count);
switch (rmdat & 0x38)
{
case 0x20: /*BT w,imm*/
- if (tempc) flags |= C_FLAG;
- else flags &= ~C_FLAG;
+ if (tempc) cpu_state.flags |= C_FLAG;
+ else cpu_state.flags &= ~C_FLAG;
CLOCK_CYCLES(3);
PREFETCH_RUN(3, 3, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 1);
return 0;
break;
}
seteal(temp); if (cpu_state.abrt) return 1;
- if (tempc) flags |= C_FLAG;
- else flags &= ~C_FLAG;
+ if (tempc) cpu_state.flags |= C_FLAG;
+ else cpu_state.flags &= ~C_FLAG;
CLOCK_CYCLES(6);
PREFETCH_RUN(6, 3, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 1);
return 0;
if (temp) \
{ \
int c; \
- flags &= ~Z_FLAG; \
+ cpu_state.flags &= ~Z_FLAG; \
for (c = start; c != end; c += dir) \
{ \
CLOCK_CYCLES(time); \
} \
} \
else \
- flags |= Z_FLAG;
+ cpu_state.flags |= Z_FLAG;
static int opBSF_w_a16(uint32_t fetchdat)
{
int instr_cycles;
fetch_ea_16(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
temp = geteaw(); if (cpu_state.abrt) return 1;
BS_common(0, 16, 1, cpu_state.regs[cpu_reg].w, (is486) ? 1 : 3);
int instr_cycles;
fetch_ea_32(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
temp = geteaw(); if (cpu_state.abrt) return 1;
BS_common(0, 16, 1, cpu_state.regs[cpu_reg].w, (is486) ? 1 : 3);
int instr_cycles;
fetch_ea_16(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
temp = geteal(); if (cpu_state.abrt) return 1;
BS_common(0, 32, 1, cpu_state.regs[cpu_reg].l, (is486) ? 1 : 3);
int instr_cycles;
fetch_ea_32(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
temp = geteal(); if (cpu_state.abrt) return 1;
BS_common(0, 32, 1, cpu_state.regs[cpu_reg].l, (is486) ? 1 : 3);
int instr_cycles;
fetch_ea_16(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
temp = geteaw(); if (cpu_state.abrt) return 1;
BS_common(15, -1, -1, cpu_state.regs[cpu_reg].w, 3);
int instr_cycles;
fetch_ea_32(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
temp = geteaw(); if (cpu_state.abrt) return 1;
BS_common(15, -1, -1, cpu_state.regs[cpu_reg].w, 3);
int instr_cycles;
fetch_ea_16(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
temp = geteal(); if (cpu_state.abrt) return 1;
BS_common(31, -1, -1, cpu_state.regs[cpu_reg].l, 3);
int instr_cycles;
fetch_ea_32(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
temp = geteal(); if (cpu_state.abrt) return 1;
BS_common(31, -1, -1, cpu_state.regs[cpu_reg].l, 3);
#define CALL_FAR_w(new_seg, new_pc) \
old_cs = CS; \
old_pc = cpu_state.pc; \
- oxpc = cpu_state.pc; \
cpu_state.pc = new_pc; \
optype = CALL; \
cgate16 = cgate32 = 0; \
- if (msw & 1) loadcscall(new_seg); \
+ if (msw & 1) loadcscall(new_seg, old_pc); \
else \
{ \
loadcs(new_seg); \
if (cgate32) \
{ \
uint32_t old_esp = ESP; \
- PUSH_L(old_cs); if (cpu_state.abrt) { cgate16 = cgate32 = 0; return 1; } \
- PUSH_L(old_pc); if (cpu_state.abrt) { ESP = old_esp; return 1; } \
+ PUSH_L(old_cs); if (cpu_state.abrt) { CS = old_cs; cgate16 = cgate32 = 0; return 1; } \
+ PUSH_L(old_pc); if (cpu_state.abrt) { CS = old_cs; ESP = old_esp; return 1; } \
} \
else \
{ \
uint32_t old_esp = ESP; \
- PUSH_W(old_cs); if (cpu_state.abrt) { cgate16 = cgate32 = 0; return 1; } \
- PUSH_W(old_pc); if (cpu_state.abrt) { ESP = old_esp; return 1; } \
+ PUSH_W(old_cs); if (cpu_state.abrt) { CS = old_cs; cgate16 = cgate32 = 0; return 1; } \
+ PUSH_W(old_pc); if (cpu_state.abrt) { CS = old_cs; ESP = old_esp; return 1; } \
}
#define CALL_FAR_l(new_seg, new_pc) \
old_cs = CS; \
old_pc = cpu_state.pc; \
- oxpc = cpu_state.pc; \
cpu_state.pc = new_pc; \
optype = CALL; \
cgate16 = cgate32 = 0; \
- if (msw & 1) loadcscall(new_seg); \
+ if (msw & 1) loadcscall(new_seg, old_pc); \
else \
{ \
loadcs(new_seg); \
if (cgate16) \
{ \
uint32_t old_esp = ESP; \
- PUSH_W(old_cs); if (cpu_state.abrt) { cgate16 = cgate32 = 0; return 1; } \
- PUSH_W(old_pc); if (cpu_state.abrt) { ESP = old_esp; return 1; } \
+ PUSH_W(old_cs); if (cpu_state.abrt) { CS = old_cs; cgate16 = cgate32 = 0; return 1; } \
+ PUSH_W(old_pc); if (cpu_state.abrt) { CS = old_cs; ESP = old_esp; return 1; } \
} \
else \
{ \
uint32_t old_esp = ESP; \
- PUSH_L(old_cs); if (cpu_state.abrt) { cgate16 = cgate32 = 0; return 1; } \
- PUSH_L(old_pc); if (cpu_state.abrt) { ESP = old_esp; return 1; } \
+ PUSH_L(old_cs); if (cpu_state.abrt) { CS = old_cs; cgate16 = cgate32 = 0; return 1; } \
+ PUSH_L(old_pc); if (cpu_state.abrt) { CS = old_cs; ESP = old_esp; return 1; } \
}
switch (rmdat & 0x38)
{
case 0x00: /*INC w*/
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = geteaw(); if (cpu_state.abrt) return 1;
seteaw(temp + 1); if (cpu_state.abrt) return 1;
setadd16nc(temp, 1);
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 0);
break;
case 0x08: /*DEC w*/
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = geteaw(); if (cpu_state.abrt) return 1;
seteaw(temp - 1); if (cpu_state.abrt) return 1;
setsub16nc(temp, 1);
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 0);
break;
case 0x10: /*CALL*/
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
new_pc = geteaw(); if (cpu_state.abrt) return 1;
PUSH_W(cpu_state.pc);
cpu_state.pc = new_pc;
PREFETCH_FLUSH();
break;
case 0x18: /*CALL far*/
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
new_pc = readmemw(easeg, cpu_state.eaaddr);
new_cs = readmemw(easeg, (cpu_state.eaaddr + 2)); if (cpu_state.abrt) return 1;
PREFETCH_FLUSH();
break;
case 0x20: /*JMP*/
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
new_pc = geteaw(); if (cpu_state.abrt) return 1;
cpu_state.pc = new_pc;
CPU_BLOCK_END();
PREFETCH_FLUSH();
break;
case 0x28: /*JMP far*/
- oxpc = cpu_state.pc;
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
+ old_pc = cpu_state.pc;
new_pc = readmemw(easeg, cpu_state.eaaddr);
new_cs = readmemw(easeg, cpu_state.eaaddr + 2); if (cpu_state.abrt) return 1;
cpu_state.pc = new_pc;
- loadcsjmp(new_cs, oxpc); if (cpu_state.abrt) return 1;
+ loadcsjmp(new_cs, old_pc); if (cpu_state.abrt) return 1;
CPU_BLOCK_END();
PREFETCH_RUN(cycles_old-cycles, 2, rmdat, 2,0,0,0, 0);
PREFETCH_FLUSH();
break;
case 0x30: /*PUSH w*/
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
temp = geteaw(); if (cpu_state.abrt) return 1;
PUSH_W(temp);
CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5);
switch (rmdat & 0x38)
{
case 0x00: /*INC w*/
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = geteaw(); if (cpu_state.abrt) return 1;
seteaw(temp + 1); if (cpu_state.abrt) return 1;
setadd16nc(temp, 1);
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 1);
break;
case 0x08: /*DEC w*/
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = geteaw(); if (cpu_state.abrt) return 1;
seteaw(temp - 1); if (cpu_state.abrt) return 1;
setsub16nc(temp, 1);
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 1);
break;
case 0x10: /*CALL*/
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
new_pc = geteaw(); if (cpu_state.abrt) return 1;
PUSH_W(cpu_state.pc);
cpu_state.pc = new_pc;
PREFETCH_FLUSH();
break;
case 0x18: /*CALL far*/
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
new_pc = readmemw(easeg, cpu_state.eaaddr);
new_cs = readmemw(easeg, (cpu_state.eaaddr + 2)); if (cpu_state.abrt) return 1;
PREFETCH_FLUSH();
break;
case 0x20: /*JMP*/
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
new_pc = geteaw(); if (cpu_state.abrt) return 1;
cpu_state.pc = new_pc;
CPU_BLOCK_END();
PREFETCH_FLUSH();
break;
case 0x28: /*JMP far*/
- oxpc = cpu_state.pc;
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
+ old_pc = cpu_state.pc;
new_pc = readmemw(easeg, cpu_state.eaaddr);
new_cs = readmemw(easeg, cpu_state.eaaddr + 2); if (cpu_state.abrt) return 1;
cpu_state.pc = new_pc;
- loadcsjmp(new_cs, oxpc); if (cpu_state.abrt) return 1;
+ loadcsjmp(new_cs, old_pc); if (cpu_state.abrt) return 1;
CPU_BLOCK_END();
PREFETCH_RUN(cycles_old-cycles, 2, rmdat, 2,0,0,0, 1);
PREFETCH_FLUSH();
break;
case 0x30: /*PUSH w*/
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
temp = geteaw(); if (cpu_state.abrt) return 1;
PUSH_W(temp);
CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5);
switch (rmdat & 0x38)
{
case 0x00: /*INC l*/
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = geteal(); if (cpu_state.abrt) return 1;
seteal(temp + 1); if (cpu_state.abrt) return 1;
setadd32nc(temp, 1);
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 0);
break;
case 0x08: /*DEC l*/
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = geteal(); if (cpu_state.abrt) return 1;
seteal(temp - 1); if (cpu_state.abrt) return 1;
setsub32nc(temp, 1);
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 0);
break;
case 0x10: /*CALL*/
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
new_pc = geteal(); if (cpu_state.abrt) return 1;
PUSH_L(cpu_state.pc);
cpu_state.pc = new_pc;
PREFETCH_FLUSH();
break;
case 0x18: /*CALL far*/
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
new_pc = readmeml(easeg, cpu_state.eaaddr);
new_cs = readmemw(easeg, (cpu_state.eaaddr + 4)); if (cpu_state.abrt) return 1;
PREFETCH_FLUSH();
break;
case 0x20: /*JMP*/
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
new_pc = geteal(); if (cpu_state.abrt) return 1;
cpu_state.pc = new_pc;
CPU_BLOCK_END();
PREFETCH_FLUSH();
break;
case 0x28: /*JMP far*/
- oxpc = cpu_state.pc;
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
+ old_pc = cpu_state.pc;
new_pc = readmeml(easeg, cpu_state.eaaddr);
new_cs = readmemw(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 1;
cpu_state.pc = new_pc;
- loadcsjmp(new_cs, oxpc); if (cpu_state.abrt) return 1;
+ loadcsjmp(new_cs, old_pc); if (cpu_state.abrt) return 1;
CPU_BLOCK_END();
PREFETCH_RUN(cycles_old-cycles, 2, rmdat, 1,1,0,0, 0);
PREFETCH_FLUSH();
break;
case 0x30: /*PUSH l*/
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
temp = geteal(); if (cpu_state.abrt) return 1;
PUSH_L(temp);
CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5);
switch (rmdat & 0x38)
{
case 0x00: /*INC l*/
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = geteal(); if (cpu_state.abrt) return 1;
seteal(temp + 1); if (cpu_state.abrt) return 1;
setadd32nc(temp, 1);
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 1);
break;
case 0x08: /*DEC l*/
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = geteal(); if (cpu_state.abrt) return 1;
seteal(temp - 1); if (cpu_state.abrt) return 1;
setsub32nc(temp, 1);
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 1);
break;
case 0x10: /*CALL*/
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
new_pc = geteal(); if (cpu_state.abrt) return 1;
PUSH_L(cpu_state.pc); if (cpu_state.abrt) return 1;
cpu_state.pc = new_pc;
PREFETCH_FLUSH();
break;
case 0x18: /*CALL far*/
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
new_pc = readmeml(easeg, cpu_state.eaaddr);
new_cs = readmemw(easeg, (cpu_state.eaaddr + 4)); if (cpu_state.abrt) return 1;
PREFETCH_FLUSH();
break;
case 0x20: /*JMP*/
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
new_pc = geteal(); if (cpu_state.abrt) return 1;
cpu_state.pc = new_pc;
CPU_BLOCK_END();
PREFETCH_FLUSH();
break;
case 0x28: /*JMP far*/
- oxpc = cpu_state.pc;
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
+ old_pc = cpu_state.pc;
new_pc = readmeml(easeg, cpu_state.eaaddr);
new_cs = readmemw(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 1;
cpu_state.pc = new_pc;
- loadcsjmp(new_cs, oxpc); if (cpu_state.abrt) return 1;
+ loadcsjmp(new_cs, old_pc); if (cpu_state.abrt) return 1;
CPU_BLOCK_END();
PREFETCH_RUN(cycles_old-cycles, 2, rmdat, 1,1,0,0, 1);
PREFETCH_FLUSH();
break;
case 0x30: /*PUSH l*/
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
temp = geteal(); if (cpu_state.abrt) return 1;
PUSH_L(temp);
PREFETCH_RUN((cpu_mod == 3) ? 2 : 5, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,1, 1);
static int opCMC(uint32_t fetchdat)
{
flags_rebuild();
- flags ^= C_FLAG;
+ cpu_state.flags ^= C_FLAG;
CLOCK_CYCLES(2);
PREFETCH_RUN(2, 1, -1, 0,0,0,0, 0);
return 0;
static int opCLC(uint32_t fetchdat)
{
flags_rebuild();
- flags &= ~C_FLAG;
+ cpu_state.flags &= ~C_FLAG;
CLOCK_CYCLES(2);
PREFETCH_RUN(2, 1, -1, 0,0,0,0, 0);
return 0;
}
static int opCLD(uint32_t fetchdat)
{
- flags &= ~D_FLAG;
+ cpu_state.flags &= ~D_FLAG;
CLOCK_CYCLES(2);
PREFETCH_RUN(2, 1, -1, 0,0,0,0, 0);
return 0;
{
if (!IOPLp)
{
- if ((!(eflags & VM_FLAG) && (cr4 & CR4_PVI)) ||
- ((eflags & VM_FLAG) && (cr4 & CR4_VME)))
+ if ((!(cpu_state.eflags & VM_FLAG) && (cr4 & CR4_PVI)) ||
+ ((cpu_state.eflags & VM_FLAG) && (cr4 & CR4_VME)))
{
- eflags &= ~VIF_FLAG;
+ cpu_state.eflags &= ~VIF_FLAG;
}
else
{
}
}
else
- flags &= ~I_FLAG;
+ cpu_state.flags &= ~I_FLAG;
CLOCK_CYCLES(3);
PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0);
static int opSTC(uint32_t fetchdat)
{
flags_rebuild();
- flags |= C_FLAG;
+ cpu_state.flags |= C_FLAG;
CLOCK_CYCLES(2);
PREFETCH_RUN(2, 1, -1, 0,0,0,0, 0);
return 0;
}
static int opSTD(uint32_t fetchdat)
{
- flags |= D_FLAG;
+ cpu_state.flags |= D_FLAG;
CLOCK_CYCLES(2);
PREFETCH_RUN(2, 1, -1, 0,0,0,0, 0);
return 0;
{
if (!IOPLp)
{
- if ((!(eflags & VM_FLAG) && (cr4 & CR4_PVI)) ||
- ((eflags & VM_FLAG) && (cr4 & CR4_VME)))
+ if ((!(cpu_state.eflags & VM_FLAG) && (cr4 & CR4_PVI)) ||
+ ((cpu_state.eflags & VM_FLAG) && (cr4 & CR4_VME)))
{
- if (eflags & VIP_FLAG)
+ if (cpu_state.eflags & VIP_FLAG)
{
x86gpf(NULL,0);
return 1;
}
else
- eflags |= VIF_FLAG;
+ cpu_state.eflags |= VIF_FLAG;
}
else
{
}
}
else
- flags |= I_FLAG;
+ cpu_state.flags |= I_FLAG;
CPU_BLOCK_END();
static int opSAHF(uint32_t fetchdat)
{
flags_rebuild();
- flags = (flags & 0xff00) | (AH & 0xd5) | 2;
+ cpu_state.flags = (cpu_state.flags & 0xff00) | (AH & 0xd5) | 2;
CLOCK_CYCLES(3);
PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0);
static int opLAHF(uint32_t fetchdat)
{
flags_rebuild();
- AH = flags & 0xff;
+ AH = cpu_state.flags & 0xff;
CLOCK_CYCLES(3);
PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0);
return 0;
static int opPUSHF(uint32_t fetchdat)
{
- if ((eflags & VM_FLAG) && (IOPL < 3))
+ if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3))
{
if (cr4 & CR4_VME)
{
uint16_t temp;
flags_rebuild();
- temp = (flags & ~I_FLAG) | 0x3000;
- if (eflags & VIF_FLAG)
+ temp = (cpu_state.flags & ~I_FLAG) | 0x3000;
+ if (cpu_state.eflags & VIF_FLAG)
temp |= I_FLAG;
PUSH_W(temp);
}
else
{
flags_rebuild();
- PUSH_W(flags);
+ PUSH_W(cpu_state.flags);
}
CLOCK_CYCLES(4);
PREFETCH_RUN(4, 1, -1, 0,0,1,0, 0);
static int opPUSHFD(uint32_t fetchdat)
{
uint16_t tempw;
- if ((eflags & VM_FLAG) && (IOPL < 3))
+ if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3))
{
x86gpf(NULL, 0);
return 1;
}
- if (cpu_CR4_mask & CR4_VME) tempw = eflags & 0x3c;
- else if (CPUID) tempw = eflags & 0x24;
- else tempw = eflags & 4;
+ if (cpu_CR4_mask & CR4_VME) tempw = cpu_state.eflags & 0x3c;
+ else if (CPUID) tempw = cpu_state.eflags & 0x24;
+ else tempw = cpu_state.eflags & 4;
flags_rebuild();
- PUSH_L(flags | (tempw << 16));
+ PUSH_L(cpu_state.flags | (tempw << 16));
CLOCK_CYCLES(4);
PREFETCH_RUN(4, 1, -1, 0,0,0,1, 0);
return cpu_state.abrt;
{
uint16_t tempw;
- if ((eflags & VM_FLAG) && (IOPL < 3))
+ if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3))
{
x86gpf(NULL, 0);
return 1;
tempw = POP_W(); if (cpu_state.abrt) return 1;
- if (!(msw & 1)) flags = (flags & 0x7000) | (tempw & 0x0fd5) | 2;
- else if (!(CPL)) flags = (tempw & 0x7fd5) | 2;
- else if (IOPLp) flags = (flags & 0x3000) | (tempw & 0x4fd5) | 2;
- else flags = (flags & 0x3200) | (tempw & 0x4dd5) | 2;
+ if (!(msw & 1)) cpu_state.flags = (cpu_state.flags & 0x7000) | (tempw & 0x0fd5) | 2;
+ else if (!(CPL)) cpu_state.flags = (tempw & 0x7fd5) | 2;
+ else if (IOPLp) cpu_state.flags = (cpu_state.flags & 0x3000) | (tempw & 0x4fd5) | 2;
+ else cpu_state.flags = (cpu_state.flags & 0x3200) | (tempw & 0x4dd5) | 2;
flags_extract();
CLOCK_CYCLES(5);
{
uint16_t tempw;
- if ((eflags & VM_FLAG) && (IOPL < 3))
+ if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3))
{
if (cr4 & CR4_VME)
{
return 1;
}
- if ((tempw & T_FLAG) || ((tempw & I_FLAG) && (eflags & VIP_FLAG)))
+ if ((tempw & T_FLAG) || ((tempw & I_FLAG) && (cpu_state.eflags & VIP_FLAG)))
{
ESP = old_esp;
x86gpf(NULL, 0);
return 1;
}
if (tempw & I_FLAG)
- eflags |= VIF_FLAG;
+ cpu_state.eflags |= VIF_FLAG;
else
- eflags &= ~VIF_FLAG;
- flags = (flags & 0x3200) | (tempw & 0x4dd5) | 2;
+ cpu_state.eflags &= ~VIF_FLAG;
+ cpu_state.flags = (cpu_state.flags & 0x3200) | (tempw & 0x4dd5) | 2;
}
else
{
return 1;
if (!(CPL) || !(msw & 1))
- flags = (tempw & 0x7fd5) | 2;
+ cpu_state.flags = (tempw & 0x7fd5) | 2;
else if (IOPLp)
- flags = (flags & 0x3000) | (tempw & 0x4fd5) | 2;
+ cpu_state.flags = (cpu_state.flags & 0x3000) | (tempw & 0x4fd5) | 2;
else
- flags = (flags & 0x3200) | (tempw & 0x4dd5) | 2;
+ cpu_state.flags = (cpu_state.flags & 0x3200) | (tempw & 0x4dd5) | 2;
}
flags_extract();
{
uint32_t templ;
- if ((eflags & VM_FLAG) && (IOPL < 3))
+ if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3))
{
x86gpf(NULL, 0);
return 1;
templ = POP_L(); if (cpu_state.abrt) return 1;
- if (!(CPL) || !(msw & 1)) flags = (templ & 0x7fd5) | 2;
- else if (IOPLp) flags = (flags & 0x3000) | (templ & 0x4fd5) | 2;
- else flags = (flags & 0x3200) | (templ & 0x4dd5) | 2;
+ if (!(CPL) || !(msw & 1)) cpu_state.flags = (templ & 0x7fd5) | 2;
+ else if (IOPLp) cpu_state.flags = (cpu_state.flags & 0x3000) | (templ & 0x4fd5) | 2;
+ else cpu_state.flags = (cpu_state.flags & 0x3200) | (templ & 0x4dd5) | 2;
templ &= is486 ? 0x3c0000 : 0;
- templ |= ((eflags&3) << 16);
- if (cpu_CR4_mask & CR4_VME) eflags = (templ >> 16) & 0x3f;
- else if (CPUID) eflags = (templ >> 16) & 0x27;
- else if (is486) eflags = (templ >> 16) & 7;
- else eflags = (templ >> 16) & 3;
+ templ |= ((cpu_state.eflags&3) << 16);
+ if (cpu_CR4_mask & CR4_VME) cpu_state.eflags = (templ >> 16) & 0x3f;
+ else if (CPUID) cpu_state.eflags = (templ >> 16) & 0x27;
+ else if (is486) cpu_state.eflags = (templ >> 16) & 7;
+ else cpu_state.eflags = (templ >> 16) & 3;
flags_extract();
uint8_t temp;
fetch_ea_16(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
temp=geteab(); if (cpu_state.abrt) return 1;
if (rmdat&0x38)
uint8_t temp;
fetch_ea_32(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
temp=geteab(); if (cpu_state.abrt) return 1;
if (rmdat&0x38)
static int opINT3(uint32_t fetchdat)
{
int cycles_old = cycles; UNUSED(cycles_old);
- if ((cr0 & 1) && (eflags & VM_FLAG) && (IOPL != 3))
+ if ((cr0 & 1) && (cpu_state.eflags & VM_FLAG) && (IOPL != 3))
{
x86gpf(NULL,0);
return 1;
static int opINT1(uint32_t fetchdat)
{
int cycles_old = cycles; UNUSED(cycles_old);
- if ((cr0 & 1) && (eflags & VM_FLAG) && (IOPL != 3))
+ if ((cr0 & 1) && (cpu_state.eflags & VM_FLAG) && (IOPL != 3))
{
x86gpf(NULL,0);
return 1;
int cycles_old = cycles; UNUSED(cycles_old);
uint8_t temp = getbytef();
- if ((cr0 & 1) && (eflags & VM_FLAG) && (IOPL != 3))
+ if ((cr0 & 1) && (cpu_state.eflags & VM_FLAG) && (IOPL != 3))
{
if (cr4 & CR4_VME)
{
{
int cycles_old = cycles; UNUSED(cycles_old);
- if ((cr0 & 1) && (eflags & VM_FLAG) && (IOPL != 3))
+ if ((cr0 & 1) && (cpu_state.eflags & VM_FLAG) && (IOPL != 3))
{
x86gpf(NULL,0);
return 1;
if (cond_ ## condition) \
{ \
cpu_state.pc += offset; \
+ if (!(cpu_state.op32 & 0x100)) \
+ cpu_state.pc &= 0xffff; \
CLOCK_CYCLES_ALWAYS(timing_bt); \
CPU_BLOCK_END(); \
PREFETCH_RUN(timing_bt+timing_bnt, 2, -1, 0,0,0,0, 0); \
if (cond_ ## condition) \
{ \
cpu_state.pc += offset; \
+ cpu_state.pc &= 0xffff; \
CLOCK_CYCLES_ALWAYS(timing_bt); \
CPU_BLOCK_END(); \
PREFETCH_RUN(timing_bt+timing_bnt, 3, -1, 0,0,0,0, 0); \
if (CX && !ZF_SET())
{
cpu_state.pc += offset;
+ if (!(cpu_state.op32 & 0x100))
+ cpu_state.pc &= 0xffff;
CPU_BLOCK_END();
PREFETCH_FLUSH();
return 1;
if (ECX && !ZF_SET())
{
cpu_state.pc += offset;
+ if (!(cpu_state.op32 & 0x100))
+ cpu_state.pc &= 0xffff;
CPU_BLOCK_END();
PREFETCH_FLUSH();
return 1;
if (CX && ZF_SET())
{
cpu_state.pc += offset;
+ if (!(cpu_state.op32 & 0x100))
+ cpu_state.pc &= 0xffff;
CPU_BLOCK_END();
PREFETCH_FLUSH();
return 1;
if (ECX && ZF_SET())
{
cpu_state.pc += offset;
+ if (!(cpu_state.op32 & 0x100))
+ cpu_state.pc &= 0xffff;
CPU_BLOCK_END();
PREFETCH_FLUSH();
return 1;
if (CX)
{
cpu_state.pc += offset;
+ if (!(cpu_state.op32 & 0x100))
+ cpu_state.pc &= 0xffff;
CPU_BLOCK_END();
PREFETCH_FLUSH();
return 1;
if (ECX)
{
cpu_state.pc += offset;
+ if (!(cpu_state.op32 & 0x100))
+ cpu_state.pc &= 0xffff;
CPU_BLOCK_END();
PREFETCH_FLUSH();
return 1;
if (!CX)
{
cpu_state.pc += offset;
+ if (!(cpu_state.op32 & 0x100))
+ cpu_state.pc &= 0xffff;
CLOCK_CYCLES(4);
CPU_BLOCK_END();
PREFETCH_RUN(9, 2, -1, 0,0,0,0, 0);
if (!ECX)
{
cpu_state.pc += offset;
+ if (!(cpu_state.op32 & 0x100))
+ cpu_state.pc &= 0xffff;
CLOCK_CYCLES(4);
CPU_BLOCK_END();
PREFETCH_RUN(9, 2, -1, 0,0,0,0, 0);
{
int8_t offset = (int8_t)getbytef();
cpu_state.pc += offset;
+ if (!(cpu_state.op32 & 0x100))
+ cpu_state.pc &= 0xffff;
CPU_BLOCK_END();
CLOCK_CYCLES((is486) ? 3 : 7);
PREFETCH_RUN(7, 2, -1, 0,0,0,0, 0);
{
int16_t offset = (int16_t)getwordf();
cpu_state.pc += offset;
+ cpu_state.pc &= 0xffff;
CPU_BLOCK_END();
CLOCK_CYCLES((is486) ? 3 : 7);
PREFETCH_RUN(7, 3, -1, 0,0,0,0, 0);
{
uint16_t addr = getwordf();
uint16_t seg = getword(); if (cpu_state.abrt) return 1;
- uint32_t oxpc = cpu_state.pc;
+ uint32_t old_pc = cpu_state.pc;
cpu_state.pc = addr;
- loadcsjmp(seg, oxpc);
+ loadcsjmp(seg, old_pc);
CPU_BLOCK_END();
PREFETCH_RUN(11, 5, -1, 0,0,0,0, 0);
PREFETCH_FLUSH();
{
uint32_t addr = getlong();
uint16_t seg = getword(); if (cpu_state.abrt) return 1;
- uint32_t oxpc = cpu_state.pc;
+ uint32_t old_pc = cpu_state.pc;
cpu_state.pc = addr;
- loadcsjmp(seg, oxpc);
+ loadcsjmp(seg, old_pc);
CPU_BLOCK_END();
PREFETCH_RUN(11, 7, -1, 0,0,0,0, 0);
PREFETCH_FLUSH();
int16_t addr = (int16_t)getwordf();
PUSH_W(cpu_state.pc);
cpu_state.pc += addr;
+ cpu_state.pc &= 0xffff;
CPU_BLOCK_END();
CLOCK_CYCLES((is486) ? 3 : 7);
PREFETCH_RUN(7, 3, -1, 0,0,1,0, 0);
fetch_ea_16(fetchdat);
if (cpu_mod != 3)
{
+ SEG_CHECK_READ(cpu_state.ea_seg);
CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr);
}
dst = geteab(); if (cpu_state.abrt) return 1;
PREFETCH_RUN((cpu_mod == 3) ? 2 : 5, 3, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0);
break;
case 0x10: /*NOT b*/
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
seteab(~dst); if (cpu_state.abrt) return 1;
CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm);
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 0);
break;
case 0x18: /*NEG b*/
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
seteab(0 - dst); if (cpu_state.abrt) return 1;
setsub8(0, dst);
CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm);
case 0x20: /*MUL AL,b*/
AX = AL * dst;
flags_rebuild();
- if (AH) flags |= (C_FLAG | V_FLAG);
- else flags &= ~(C_FLAG | V_FLAG);
+ if (AH) cpu_state.flags |= (C_FLAG | V_FLAG);
+ else cpu_state.flags &= ~(C_FLAG | V_FLAG);
CLOCK_CYCLES(13);
PREFETCH_RUN(13, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0);
break;
tempws = (int)((int8_t)AL) * (int)((int8_t)dst);
AX = tempws & 0xffff;
flags_rebuild();
- if (((int16_t)AX >> 7) != 0 && ((int16_t)AX >> 7) != -1) flags |= (C_FLAG | V_FLAG);
- else flags &= ~(C_FLAG | V_FLAG);
+ if (((int16_t)AX >> 7) != 0 && ((int16_t)AX >> 7) != -1) cpu_state.flags |= (C_FLAG | V_FLAG);
+ else cpu_state.flags &= ~(C_FLAG | V_FLAG);
CLOCK_CYCLES(14);
PREFETCH_RUN(14, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0);
break;
if (!cpu_iscyrix)
{
flags_rebuild();
- flags |= 0x8D5; /*Not a Cyrix*/
- flags &= ~1;
+ cpu_state.flags |= 0x8D5; /*Not a Cyrix*/
+ cpu_state.flags &= ~1;
}
}
else
if (!cpu_iscyrix)
{
flags_rebuild();
- flags|=0x8D5; /*Not a Cyrix*/
- flags &= ~1;
+ cpu_state.flags|=0x8D5; /*Not a Cyrix*/
+ cpu_state.flags &= ~1;
}
}
else
int8_t temps;
fetch_ea_32(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
dst = geteab(); if (cpu_state.abrt) return 1;
switch (rmdat & 0x38)
{
PREFETCH_RUN((cpu_mod == 3) ? 2 : 5, 3, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1);
break;
case 0x10: /*NOT b*/
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
seteab(~dst); if (cpu_state.abrt) return 1;
CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm);
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 1);
break;
case 0x18: /*NEG b*/
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
seteab(0 - dst); if (cpu_state.abrt) return 1;
setsub8(0, dst);
CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm);
case 0x20: /*MUL AL,b*/
AX = AL * dst;
flags_rebuild();
- if (AH) flags |= (C_FLAG | V_FLAG);
- else flags &= ~(C_FLAG | V_FLAG);
+ if (AH) cpu_state.flags |= (C_FLAG | V_FLAG);
+ else cpu_state.flags &= ~(C_FLAG | V_FLAG);
CLOCK_CYCLES(13);
PREFETCH_RUN(13, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1);
break;
tempws = (int)((int8_t)AL) * (int)((int8_t)dst);
AX = tempws & 0xffff;
flags_rebuild();
- if (((int16_t)AX >> 7) != 0 && ((int16_t)AX >> 7) != -1) flags |= (C_FLAG | V_FLAG);
- else flags &= ~(C_FLAG | V_FLAG);
+ if (((int16_t)AX >> 7) != 0 && ((int16_t)AX >> 7) != -1) cpu_state.flags |= (C_FLAG | V_FLAG);
+ else cpu_state.flags &= ~(C_FLAG | V_FLAG);
CLOCK_CYCLES(14);
PREFETCH_RUN(14, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1);
break;
if (!cpu_iscyrix)
{
flags_rebuild();
- flags |= 0x8D5; /*Not a Cyrix*/
- flags &= ~1;
+ cpu_state.flags |= 0x8D5; /*Not a Cyrix*/
+ cpu_state.flags &= ~1;
}
}
else
if (!cpu_iscyrix)
{
flags_rebuild();
- flags|=0x8D5; /*Not a Cyrix*/
- flags &= ~1;
+ cpu_state.flags |= 0x8D5; /*Not a Cyrix*/
+ cpu_state.flags &= ~1;
}
}
else
uint16_t src, dst;
fetch_ea_16(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
dst = geteaw(); if (cpu_state.abrt) return 1;
switch (rmdat & 0x38)
{
PREFETCH_RUN((cpu_mod == 3) ? 2 : 5, 4, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0);
break;
case 0x10: /*NOT w*/
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
seteaw(~dst); if (cpu_state.abrt) return 1;
CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm);
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 0);
break;
case 0x18: /*NEG w*/
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
seteaw(0 - dst); if (cpu_state.abrt) return 1;
setsub16(0, dst);
CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm);
AX = templ & 0xFFFF;
DX = templ >> 16;
flags_rebuild();
- if (DX) flags |= (C_FLAG | V_FLAG);
- else flags &= ~(C_FLAG | V_FLAG);
+ if (DX) cpu_state.flags |= (C_FLAG | V_FLAG);
+ else cpu_state.flags &= ~(C_FLAG | V_FLAG);
CLOCK_CYCLES(21);
PREFETCH_RUN(21, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0);
break;
AX = templ & 0xFFFF;
DX = templ >> 16;
flags_rebuild();
- if (((int32_t)templ >> 15) != 0 && ((int32_t)templ >> 15) != -1) flags |= (C_FLAG | V_FLAG);
- else flags &= ~(C_FLAG | V_FLAG);
+ if (((int32_t)templ >> 15) != 0 && ((int32_t)templ >> 15) != -1) cpu_state.flags |= (C_FLAG | V_FLAG);
+ else cpu_state.flags &= ~(C_FLAG | V_FLAG);
CLOCK_CYCLES(22);
PREFETCH_RUN(22, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0);
break;
uint16_t src, dst;
fetch_ea_32(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
dst = geteaw(); if (cpu_state.abrt) return 1;
switch (rmdat & 0x38)
{
PREFETCH_RUN((cpu_mod == 3) ? 2 : 5, 4, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1);
break;
case 0x10: /*NOT w*/
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
seteaw(~dst); if (cpu_state.abrt) return 1;
CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm);
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 1);
break;
case 0x18: /*NEG w*/
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
seteaw(0 - dst); if (cpu_state.abrt) return 1;
setsub16(0, dst);
CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mm);
AX = templ & 0xFFFF;
DX = templ >> 16;
flags_rebuild();
- if (DX) flags |= (C_FLAG | V_FLAG);
- else flags &= ~(C_FLAG | V_FLAG);
+ if (DX) cpu_state.flags |= (C_FLAG | V_FLAG);
+ else cpu_state.flags &= ~(C_FLAG | V_FLAG);
CLOCK_CYCLES(21);
PREFETCH_RUN(21, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1);
break;
AX = templ & 0xFFFF;
DX = templ >> 16;
flags_rebuild();
- if (((int32_t)templ >> 15) != 0 && ((int32_t)templ >> 15) != -1) flags |= (C_FLAG | V_FLAG);
- else flags &= ~(C_FLAG | V_FLAG);
+ if (((int32_t)templ >> 15) != 0 && ((int32_t)templ >> 15) != -1) cpu_state.flags |= (C_FLAG | V_FLAG);
+ else cpu_state.flags &= ~(C_FLAG | V_FLAG);
CLOCK_CYCLES(22);
PREFETCH_RUN(22, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1);
break;
uint32_t src, dst;
fetch_ea_16(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
dst = geteal(); if (cpu_state.abrt) return 1;
switch (rmdat & 0x38)
PREFETCH_RUN((cpu_mod == 3) ? 2 : 5, 5, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 0);
break;
case 0x10: /*NOT l*/
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
seteal(~dst); if (cpu_state.abrt) return 1;
CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mml);
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 0);
break;
case 0x18: /*NEG l*/
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
seteal(0 - dst); if (cpu_state.abrt) return 1;
setsub32(0, dst);
CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mml);
EAX = temp64 & 0xffffffff;
EDX = temp64 >> 32;
flags_rebuild();
- if (EDX) flags |= (C_FLAG|V_FLAG);
- else flags &= ~(C_FLAG|V_FLAG);
+ if (EDX) cpu_state.flags |= (C_FLAG|V_FLAG);
+ else cpu_state.flags &= ~(C_FLAG|V_FLAG);
CLOCK_CYCLES(21);
PREFETCH_RUN(21, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 0);
break;
EAX = temp64 & 0xffffffff;
EDX = temp64 >> 32;
flags_rebuild();
- if (((int64_t)temp64 >> 31) != 0 && ((int64_t)temp64 >> 31) != -1) flags |= (C_FLAG | V_FLAG);
- else flags &= ~(C_FLAG | V_FLAG);
+ if (((int64_t)temp64 >> 31) != 0 && ((int64_t)temp64 >> 31) != -1) cpu_state.flags |= (C_FLAG | V_FLAG);
+ else cpu_state.flags &= ~(C_FLAG | V_FLAG);
CLOCK_CYCLES(38);
PREFETCH_RUN(38, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 0);
break;
uint32_t src, dst;
fetch_ea_32(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
dst = geteal(); if (cpu_state.abrt) return 1;
switch (rmdat & 0x38)
PREFETCH_RUN((cpu_mod == 3) ? 2 : 5, 5, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 1);
break;
case 0x10: /*NOT l*/
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
seteal(~dst); if (cpu_state.abrt) return 1;
CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mml);
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mm, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 1);
break;
case 0x18: /*NEG l*/
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
seteal(0 - dst); if (cpu_state.abrt) return 1;
setsub32(0, dst);
CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mml);
EAX = temp64 & 0xffffffff;
EDX = temp64 >> 32;
flags_rebuild();
- if (EDX) flags |= (C_FLAG|V_FLAG);
- else flags &= ~(C_FLAG|V_FLAG);
+ if (EDX) cpu_state.flags |= (C_FLAG|V_FLAG);
+ else cpu_state.flags &= ~(C_FLAG|V_FLAG);
CLOCK_CYCLES(21);
PREFETCH_RUN(21, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 1);
break;
EAX = temp64 & 0xffffffff;
EDX = temp64 >> 32;
flags_rebuild();
- if (((int64_t)temp64 >> 31) != 0 && ((int64_t)temp64 >> 31) != -1) flags |= (C_FLAG | V_FLAG);
- else flags &= ~(C_FLAG | V_FLAG);
+ if (((int64_t)temp64 >> 31) != 0 && ((int64_t)temp64 >> 31) != -1) cpu_state.flags |= (C_FLAG | V_FLAG);
+ else cpu_state.flags &= ~(C_FLAG | V_FLAG);
CLOCK_CYCLES(38);
PREFETCH_RUN(38, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 1);
break;
static int opHLT(uint32_t fetchdat)
{
- if ((CPL || (eflags&VM_FLAG)) && (cr0&1))
+ if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1))
{
x86gpf(NULL,0);
return 1;
}
- if (!((flags&I_FLAG) && pic_intpending))
+ if (!((cpu_state.flags & I_FLAG) && pic_intpending))
{
CLOCK_CYCLES_ALWAYS(100);
cpu_state.pc--;
fetch_ea_16(fetchdat);
ILLEGAL_ON(cpu_mod == 3);
+ SEG_CHECK_READ(cpu_state.ea_seg);
low = geteaw();
high = readmemw(easeg, cpu_state.eaaddr + 2); if (cpu_state.abrt) return 1;
fetch_ea_32(fetchdat);
ILLEGAL_ON(cpu_mod == 3);
+ SEG_CHECK_READ(cpu_state.ea_seg);
low = geteaw();
high = readmemw(easeg, cpu_state.eaaddr + 2); if (cpu_state.abrt) return 1;
fetch_ea_16(fetchdat);
ILLEGAL_ON(cpu_mod == 3);
+ SEG_CHECK_READ(cpu_state.ea_seg);
low = geteal();
high = readmeml(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 1;
fetch_ea_32(fetchdat);
ILLEGAL_ON(cpu_mod == 3);
+ SEG_CHECK_READ(cpu_state.ea_seg);
low = geteal();
high = readmeml(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 1;
static int opCLTS(uint32_t fetchdat)
{
- if ((CPL || (eflags&VM_FLAG)) && (cr0&1))
+ if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1))
{
pclog("Can't CLTS\n");
x86gpf(NULL,0);
return 1;
}
msw = (msw & 1) | readmemw(0, 0x806);
- flags = (readmemw(0, 0x818) & 0xffd5) | 2;
+ cpu_state.flags = (readmemw(0, 0x818) & 0xffd5) | 2;
flags_extract();
tr.seg = readmemw(0, 0x816);
cpu_state.pc = readmemw(0, 0x81A);
CX = readmemw(0, 0x832);
AX = readmemw(0, 0x834);
es = readmemw(0, 0x836) | (readmemb(0, 0x838) << 16);
- _es.access = readmemb(0, 0x839);
- _es.limit = readmemw(0, 0x83A);
+ cpu_state.seg_es.access = readmemb(0, 0x839);
+ cpu_state.seg_es.limit = readmemw(0, 0x83A);
cs = readmemw(0, 0x83C) | (readmemb(0, 0x83E) << 16);
- _cs.access = readmemb(0, 0x83F);
- _cs.limit = readmemw(0, 0x840);
+ cpu_state.seg_cs.access = readmemb(0, 0x83F);
+ cpu_state.seg_cs.limit = readmemw(0, 0x840);
ss = readmemw(0, 0x842) | (readmemb(0, 0x844) << 16);
- _ss.access = readmemb(0, 0x845);
- _ss.limit = readmemw(0, 0x846);
- if (_ss.base == 0 && _ss.limit_low == 0 && _ss.limit_high == 0xffffffff)
+ cpu_state.seg_ss.access = readmemb(0, 0x845);
+ cpu_state.seg_ss.limit = readmemw(0, 0x846);
+ if (cpu_state.seg_ss.base == 0 && cpu_state.seg_ss.limit_low == 0 && cpu_state.seg_ss.limit_high == 0xffffffff)
cpu_cur_status &= ~CPU_STATUS_NOTFLATSS;
else
cpu_cur_status |= CPU_STATUS_NOTFLATSS;
ds = readmemw(0, 0x848) | (readmemb(0, 0x84A) << 16);
- _ds.access = readmemb(0, 0x84B);
- _ds.limit = readmemw(0, 0x84C);
- if (_ds.base == 0 && _ds.limit_low == 0 && _ds.limit_high == 0xffffffff)
+ cpu_state.seg_ds.access = readmemb(0, 0x84B);
+ cpu_state.seg_ds.limit = readmemw(0, 0x84C);
+ if (cpu_state.seg_ds.base == 0 && cpu_state.seg_ds.limit_low == 0 && cpu_state.seg_ds.limit_high == 0xffffffff)
cpu_cur_status &= ~CPU_STATUS_NOTFLATDS;
else
cpu_cur_status |= CPU_STATUS_NOTFLATDS;
s->base = readmeml(0, addr + 4);
s->limit = readmeml(0, addr + 8);
- if (s == &_cs) use32 = (segdat3 & 0x40) ? 0x300 : 0;
- if (s == &_ss) stack32 = (segdat3 & 0x40) ? 1 : 0;
+ if (s == &cpu_state.seg_cs)
+ use32 = (segdat3 & 0x40) ? 0x300 : 0;
+ if (s == &cpu_state.seg_ss)
+ stack32 = (segdat3 & 0x40) ? 1 : 0;
+
cpu_cur_status &= ~(CPU_STATUS_USE32 | CPU_STATUS_STACK32);
if (use32)
cpu_cur_status |= CPU_STATUS_USE32;
set_segment_limit(s, segdat3);
- if (s == &_ds)
+ if (s == &cpu_state.seg_ds)
{
if (s->base == 0 && s->limit_low == 0 && s->limit_high == 0xffffffff)
cpu_cur_status &= ~CPU_STATUS_NOTFLATDS;
else
cpu_cur_status |= CPU_STATUS_NOTFLATDS;
}
- if (s == &_ss)
+ if (s == &cpu_state.seg_ss)
{
if (s->base == 0 && s->limit_low == 0 && s->limit_high == 0xffffffff)
cpu_cur_status &= ~CPU_STATUS_NOTFLATSS;
uint32_t la_addr = es + EDI;
cr0 = readmeml(0, la_addr);
- flags = readmemw(0, la_addr + 4);
- eflags = readmemw(0, la_addr + 6);
+ cpu_state.flags = readmemw(0, la_addr + 4);
+ cpu_state.eflags = readmemw(0, la_addr + 6);
flags_extract();
cpu_state.pc = readmeml(0, la_addr + 8);
EDI = readmeml(0, la_addr + 0xC);
loadall_load_segment(la_addr + 0x60, &idt);
loadall_load_segment(la_addr + 0x6c, &gdt);
loadall_load_segment(la_addr + 0x78, &ldt);
- loadall_load_segment(la_addr + 0x84, &_gs);
- loadall_load_segment(la_addr + 0x90, &_fs);
- loadall_load_segment(la_addr + 0x9c, &_ds);
- loadall_load_segment(la_addr + 0xa8, &_ss);
- loadall_load_segment(la_addr + 0xb4, &_cs);
- loadall_load_segment(la_addr + 0xc0, &_es);
+ loadall_load_segment(la_addr + 0x84, &cpu_state.seg_gs);
+ loadall_load_segment(la_addr + 0x90, &cpu_state.seg_fs);
+ loadall_load_segment(la_addr + 0x9c, &cpu_state.seg_ds);
+ loadall_load_segment(la_addr + 0xa8, &cpu_state.seg_ss);
+ loadall_load_segment(la_addr + 0xb4, &cpu_state.seg_cs);
+ loadall_load_segment(la_addr + 0xc0, &cpu_state.seg_es);
if (CPL==3 && oldcpl!=3) flushmmucache_cr3();
+ oldcpl = CPL;
CLOCK_CYCLES(350);
return 0;
static int opRDMSR(uint32_t fetchdat)
{
- if (cpu_hasMSR)
+ if (cpu_has_feature(CPU_FEATURE_MSR))
{
cpu_RDMSR();
CLOCK_CYCLES(9);
static int opWRMSR(uint32_t fetchdat)
{
- if (cpu_hasMSR)
+ if (cpu_has_feature(CPU_FEATURE_MSR))
{
cpu_WRMSR();
CLOCK_CYCLES(9);
} \
else \
{ \
+ SEG_CHECK_READ(cpu_state.ea_seg); \
src.q = readmemq(easeg, cpu_state.eaaddr); if (cpu_state.abrt) return 1; \
CLOCK_CYCLES(2); \
}
#define MMX_ENTER() \
- if (!cpu_hasMMX) \
+ if (!cpu_has_feature(CPU_FEATURE_MMX)) \
{ \
cpu_state.pc = cpu_state.oldpc; \
x86illegal(); \
static int opEMMS(uint32_t fetchdat)
{
- if (!cpu_hasMMX)
+ if (!cpu_has_feature(CPU_FEATURE_MMX))
{
cpu_state.pc = cpu_state.oldpc;
x86illegal();
return 1;
}
- if (cr0 & 4)
+ if (cr0 & 0xc)
{
x86_int(7);
return 1;
else
{
MMX_REG src;
-
+
+ SEG_CHECK_READ(cpu_state.ea_seg);
src.l[0] = readmeml(easeg, cpu_state.eaaddr);
src.l[1] = readmeml(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 0;
cpu_state.MM[cpu_reg].w[0] *= src.w[0];
{
MMX_REG src;
+ SEG_CHECK_READ(cpu_state.ea_seg);
src.l[0] = readmeml(easeg, cpu_state.eaaddr);
src.l[1] = readmeml(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 0;
cpu_state.MM[cpu_reg].w[0] *= src.w[0];
{
MMX_REG src;
+ SEG_CHECK_READ(cpu_state.ea_seg);
src.l[0] = readmeml(easeg, cpu_state.eaaddr);
src.l[1] = readmeml(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 0;
cpu_state.MM[cpu_reg].w[0] = ((int32_t)cpu_state.MM[cpu_reg].sw[0] * (int32_t)src.sw[0]) >> 16;
{
MMX_REG src;
+ SEG_CHECK_READ(cpu_state.ea_seg);
src.l[0] = readmeml(easeg, cpu_state.eaaddr);
src.l[1] = readmeml(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 0;
cpu_state.MM[cpu_reg].w[0] = ((int32_t)cpu_state.MM[cpu_reg].sw[0] * (int32_t)src.sw[0]) >> 16;
MMX_ENTER();
- fetch_ea_16(fetchdat);
+ fetch_ea_32(fetchdat);
MMX_GETSRC();
cpu_state.MM[cpu_reg].l[0] = (cpu_state.MM[cpu_reg].l[0] == src.l[0]) ? 0xffffffff : 0;
MMX_ENTER();
- fetch_ea_16(fetchdat);
+ fetch_ea_32(fetchdat);
MMX_GETSRC();
cpu_state.MM[cpu_reg].l[0] = (cpu_state.MM[cpu_reg].sl[0] > src.sl[0]) ? 0xffffffff : 0;
else
{
uint32_t dst;
-
+
+ SEG_CHECK_READ(cpu_state.ea_seg);
dst = readmeml(easeg, cpu_state.eaaddr); if (cpu_state.abrt) return 1;
cpu_state.MM[cpu_reg].l[0] = dst;
cpu_state.MM[cpu_reg].l[1] = 0;
else
{
uint32_t dst;
-
+
+ SEG_CHECK_READ(cpu_state.ea_seg);
dst = readmeml(easeg, cpu_state.eaaddr); if (cpu_state.abrt) return 1;
cpu_state.MM[cpu_reg].l[0] = dst;
cpu_state.MM[cpu_reg].l[1] = 0;
}
else
{
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
CHECK_WRITE(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3);
writememl(easeg, cpu_state.eaaddr, cpu_state.MM[cpu_reg].l[0]); if (cpu_state.abrt) return 1;
CLOCK_CYCLES(2);
}
else
{
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
CHECK_WRITE(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3);
writememl(easeg, cpu_state.eaaddr, cpu_state.MM[cpu_reg].l[0]); if (cpu_state.abrt) return 1;
CLOCK_CYCLES(2);
{
uint64_t dst;
+ SEG_CHECK_READ(cpu_state.ea_seg);
dst = readmemq(easeg, cpu_state.eaaddr); if (cpu_state.abrt) return 1;
cpu_state.MM[cpu_reg].q = dst;
CLOCK_CYCLES(2);
{
uint64_t dst;
+ SEG_CHECK_READ(cpu_state.ea_seg);
dst = readmemq(easeg, cpu_state.eaaddr); if (cpu_state.abrt) return 1;
cpu_state.MM[cpu_reg].q = dst;
CLOCK_CYCLES(2);
}
else
{
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
CHECK_WRITE(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 7);
writememq(easeg, cpu_state.eaaddr, cpu_state.MM[cpu_reg].q); if (cpu_state.abrt) return 1;
CLOCK_CYCLES(2);
}
else
{
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
CHECK_WRITE(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 7);
writememq(easeg, cpu_state.eaaddr, cpu_state.MM[cpu_reg].q); if (cpu_state.abrt) return 1;
CLOCK_CYCLES(2);
{
uint32_t src;
+ SEG_CHECK_READ(cpu_state.ea_seg);
src = readmeml(easeg, cpu_state.eaaddr); if (cpu_state.abrt) return 0;
cpu_state.MM[cpu_reg].l[1] = src;
else
{
uint32_t src;
-
+
+ SEG_CHECK_READ(cpu_state.ea_seg);
src = readmeml(easeg, cpu_state.eaaddr); if (cpu_state.abrt) return 0;
cpu_state.MM[cpu_reg].l[1] = src;
} \
else \
{ \
+ SEG_CHECK_READ(cpu_state.ea_seg); \
shift = readmemb(easeg, cpu_state.eaaddr); if (cpu_state.abrt) return 0; \
CLOCK_CYCLES(2); \
}
uint8_t temp;
fetch_ea_16(fetchdat);
ILLEGAL_ON((rmdat & 0x38) != 0);
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = readmemb(cs,cpu_state.pc); cpu_state.pc++; if (cpu_state.abrt) return 1;
CHECK_WRITE(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr);
seteab(temp);
uint8_t temp;
fetch_ea_32(fetchdat);
ILLEGAL_ON((rmdat & 0x38) != 0);
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = getbyte(); if (cpu_state.abrt) return 1;
seteab(temp);
CLOCK_CYCLES(timing_rr);
uint16_t temp;
fetch_ea_16(fetchdat);
ILLEGAL_ON((rmdat & 0x38) != 0);
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = getword(); if (cpu_state.abrt) return 1;
seteaw(temp);
CLOCK_CYCLES(timing_rr);
uint16_t temp;
fetch_ea_32(fetchdat);
ILLEGAL_ON((rmdat & 0x38) != 0);
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = getword(); if (cpu_state.abrt) return 1;
seteaw(temp);
CLOCK_CYCLES(timing_rr);
uint32_t temp;
fetch_ea_16(fetchdat);
ILLEGAL_ON((rmdat & 0x38) != 0);
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = getlong(); if (cpu_state.abrt) return 1;
seteal(temp);
CLOCK_CYCLES(timing_rr);
uint32_t temp;
fetch_ea_32(fetchdat);
ILLEGAL_ON((rmdat & 0x38) != 0);
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = getlong(); if (cpu_state.abrt) return 1;
seteal(temp);
CLOCK_CYCLES(timing_rr);
{
uint16_t addr = getwordf();
uint8_t temp;
+ SEG_CHECK_READ(cpu_state.ea_seg);
CHECK_READ(cpu_state.ea_seg, addr, addr);
temp = readmemb(cpu_state.ea_seg->base, addr); if (cpu_state.abrt) return 1;
AL = temp;
{
uint32_t addr = getlong();
uint8_t temp;
+ SEG_CHECK_READ(cpu_state.ea_seg);
CHECK_READ(cpu_state.ea_seg, addr, addr);
temp = readmemb(cpu_state.ea_seg->base, addr); if (cpu_state.abrt) return 1;
AL = temp;
{
uint16_t addr = getwordf();
uint16_t temp;
+ SEG_CHECK_READ(cpu_state.ea_seg);
CHECK_READ(cpu_state.ea_seg, addr, addr+1);
temp = readmemw(cpu_state.ea_seg->base, addr); if (cpu_state.abrt) return 1;
AX = temp;
{
uint32_t addr = getlong();
uint16_t temp;
+ SEG_CHECK_READ(cpu_state.ea_seg);
CHECK_READ(cpu_state.ea_seg, addr, addr+1);
temp = readmemw(cpu_state.ea_seg->base, addr); if (cpu_state.abrt) return 1;
AX = temp;
{
uint16_t addr = getwordf();
uint32_t temp;
+ SEG_CHECK_READ(cpu_state.ea_seg);
CHECK_READ(cpu_state.ea_seg, addr, addr+3);
temp = readmeml(cpu_state.ea_seg->base, addr); if (cpu_state.abrt) return 1;
EAX = temp;
{
uint32_t addr = getlong();
uint32_t temp;
+ SEG_CHECK_READ(cpu_state.ea_seg);
CHECK_READ(cpu_state.ea_seg, addr, addr+3);
temp = readmeml(cpu_state.ea_seg->base, addr); if (cpu_state.abrt) return 1;
EAX = temp;
static int opMOV_a16_AL(uint32_t fetchdat)
{
uint16_t addr = getwordf();
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
writememb(cpu_state.ea_seg->base, addr, AL);
CLOCK_CYCLES((is486) ? 1 : 2);
PREFETCH_RUN(2, 3, -1, 0,0,1,0, 0);
static int opMOV_a32_AL(uint32_t fetchdat)
{
uint32_t addr = getlong();
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
writememb(cpu_state.ea_seg->base, addr, AL);
CLOCK_CYCLES((is486) ? 1 : 2);
PREFETCH_RUN(2, 5, -1, 0,0,1,0, 1);
static int opMOV_a16_AX(uint32_t fetchdat)
{
uint16_t addr = getwordf();
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
writememw(cpu_state.ea_seg->base, addr, AX);
CLOCK_CYCLES((is486) ? 1 : 2);
PREFETCH_RUN(2, 3, -1, 0,0,1,0, 0);
static int opMOV_a32_AX(uint32_t fetchdat)
{
uint32_t addr = getlong(); if (cpu_state.abrt) return 1;
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
writememw(cpu_state.ea_seg->base, addr, AX);
CLOCK_CYCLES((is486) ? 1 : 2);
PREFETCH_RUN(2, 5, -1, 0,0,1,0, 1);
static int opMOV_a16_EAX(uint32_t fetchdat)
{
uint16_t addr = getwordf();
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
writememl(cpu_state.ea_seg->base, addr, EAX);
CLOCK_CYCLES((is486) ? 1 : 2);
PREFETCH_RUN(2, 3, -1, 0,0,0,1, 0);
static int opMOV_a32_EAX(uint32_t fetchdat)
{
uint32_t addr = getlong(); if (cpu_state.abrt) return 1;
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
writememl(cpu_state.ea_seg->base, addr, EAX);
CLOCK_CYCLES((is486) ? 1 : 2);
PREFETCH_RUN(2, 5, -1, 0,0,0,1, 1);
static int opXLAT_a16(uint32_t fetchdat)
{
uint32_t addr = (BX + AL)&0xFFFF;
- uint8_t temp = readmemb(cpu_state.ea_seg->base, addr); if (cpu_state.abrt) return 1;
+ uint8_t temp;
+
+ SEG_CHECK_READ(cpu_state.ea_seg);
+ temp = readmemb(cpu_state.ea_seg->base, addr); if (cpu_state.abrt) return 1;
AL = temp;
CLOCK_CYCLES(5);
PREFETCH_RUN(5, 1, -1, 1,0,0,0, 0);
static int opXLAT_a32(uint32_t fetchdat)
{
uint32_t addr = EBX + AL;
- uint8_t temp = readmemb(cpu_state.ea_seg->base, addr); if (cpu_state.abrt) return 1;
+ uint8_t temp;
+
+ SEG_CHECK_READ(cpu_state.ea_seg);
+ temp = readmemb(cpu_state.ea_seg->base, addr); if (cpu_state.abrt) return 1;
AL = temp;
CLOCK_CYCLES(5);
PREFETCH_RUN(5, 1, -1, 1,0,0,0, 1);
}
else
{
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
CHECK_WRITE(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr);
seteab(getr8(cpu_reg));
CLOCK_CYCLES(is486 ? 1 : 2);
}
else
{
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
CHECK_WRITE(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr);
seteab(getr8(cpu_reg));
CLOCK_CYCLES(is486 ? 1 : 2);
}
else
{
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
CHECK_WRITE(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr+1);
seteaw(cpu_state.regs[cpu_reg].w);
CLOCK_CYCLES(is486 ? 1 : 2);
}
else
{
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
CHECK_WRITE(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr+1);
seteaw(cpu_state.regs[cpu_reg].w);
CLOCK_CYCLES(is486 ? 1 : 2);
}
else
{
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
CHECK_WRITE(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr+3);
seteal(cpu_state.regs[cpu_reg].l);
CLOCK_CYCLES(is486 ? 1 : 2);
}
else
{
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
CHECK_WRITE(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr+3);
seteal(cpu_state.regs[cpu_reg].l);
CLOCK_CYCLES(is486 ? 1 : 2);
else
{
uint8_t temp;
+ SEG_CHECK_READ(cpu_state.ea_seg);
CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr);
temp = geteab(); if (cpu_state.abrt) return 1;
setr8(cpu_reg, temp);
else
{
uint8_t temp;
+ SEG_CHECK_READ(cpu_state.ea_seg);
CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr);
temp = geteab(); if (cpu_state.abrt) return 1;
setr8(cpu_reg, temp);
else
{
uint16_t temp;
+ SEG_CHECK_READ(cpu_state.ea_seg);
CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr+1);
temp = geteaw(); if (cpu_state.abrt) return 1;
cpu_state.regs[cpu_reg].w = temp;
else
{
uint16_t temp;
+ SEG_CHECK_READ(cpu_state.ea_seg);
CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr+1);
temp = geteaw(); if (cpu_state.abrt) return 1;
cpu_state.regs[cpu_reg].w = temp;
else
{
uint32_t temp;
+ SEG_CHECK_READ(cpu_state.ea_seg);
CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr+3);
temp = geteal(); if (cpu_state.abrt) return 1;
cpu_state.regs[cpu_reg].l = temp;
else
{
uint32_t temp;
+ SEG_CHECK_READ(cpu_state.ea_seg);
CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr+3);
temp = geteal(); if (cpu_state.abrt) return 1;
cpu_state.regs[cpu_reg].l = temp;
else \
{ \
uint16_t temp; \
+ SEG_CHECK_READ(cpu_state.ea_seg); \
CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr+1); \
temp = geteaw(); if (cpu_state.abrt) return 1; \
cpu_state.regs[cpu_reg].w = temp; \
else \
{ \
uint16_t temp; \
+ SEG_CHECK_READ(cpu_state.ea_seg); \
CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr+1); \
temp = geteaw(); if (cpu_state.abrt) return 1; \
cpu_state.regs[cpu_reg].w = temp; \
else \
{ \
uint32_t temp; \
+ SEG_CHECK_READ(cpu_state.ea_seg); \
CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr+3); \
temp = geteal(); if (cpu_state.abrt) return 1; \
cpu_state.regs[cpu_reg].l = temp; \
{ \
uint32_t temp; \
CHECK_READ(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr+3); \
+ SEG_CHECK_READ(cpu_state.ea_seg); \
temp = geteal(); if (cpu_state.abrt) return 1; \
cpu_state.regs[cpu_reg].l = temp; \
} \
static int opMOV_r_CRx_a16(uint32_t fetchdat)
{
- if ((CPL || (eflags&VM_FLAG)) && (cr0&1))
+ if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1))
{
pclog("Can't load from CRx\n");
x86gpf(NULL, 0);
cpu_state.regs[cpu_rm].l = cr3;
break;
case 4:
- if (cpu_hasCR4)
+ if (cpu_has_feature(CPU_FEATURE_CR4))
{
cpu_state.regs[cpu_rm].l = cr4;
break;
}
static int opMOV_r_CRx_a32(uint32_t fetchdat)
{
- if ((CPL || (eflags&VM_FLAG)) && (cr0&1))
+ if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1))
{
pclog("Can't load from CRx\n");
x86gpf(NULL, 0);
cpu_state.regs[cpu_rm].l = cr3;
break;
case 4:
- if (cpu_hasCR4)
+ if (cpu_has_feature(CPU_FEATURE_CR4))
{
cpu_state.regs[cpu_rm].l = cr4;
break;
static int opMOV_r_DRx_a16(uint32_t fetchdat)
{
- if ((CPL || (eflags&VM_FLAG)) && (cr0&1))
+ if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1))
{
pclog("Can't load from DRx\n");
x86gpf(NULL, 0);
}
static int opMOV_r_DRx_a32(uint32_t fetchdat)
{
- if ((CPL || (eflags&VM_FLAG)) && (cr0&1))
+ if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1))
{
pclog("Can't load from DRx\n");
x86gpf(NULL, 0);
{
uint32_t old_cr0 = cr0;
- if ((CPL || (eflags&VM_FLAG)) && (cr0&1))
+ if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1))
{
pclog("Can't load CRx\n");
x86gpf(NULL,0);
flushmmucache();
break;
case 4:
- if (cpu_hasCR4)
+ if (cpu_has_feature(CPU_FEATURE_CR4))
{
cr4 = cpu_state.regs[cpu_rm].l & cpu_CR4_mask;
break;
{
uint32_t old_cr0 = cr0;
- if ((CPL || (eflags&VM_FLAG)) && (cr0&1))
+ if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1))
{
pclog("Can't load CRx\n");
x86gpf(NULL,0);
flushmmucache();
break;
case 4:
- if (cpu_hasCR4)
+ if (cpu_has_feature(CPU_FEATURE_CR4))
{
cr4 = cpu_state.regs[cpu_rm].l & cpu_CR4_mask;
break;
static int opMOV_DRx_r_a16(uint32_t fetchdat)
{
- if ((CPL || (eflags&VM_FLAG)) && (cr0&1))
+ if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1))
{
pclog("Can't load DRx\n");
x86gpf(NULL, 0);
}
static int opMOV_DRx_r_a32(uint32_t fetchdat)
{
- if ((CPL || (eflags&VM_FLAG)) && (cr0&1))
+ if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1))
{
pclog("Can't load DRx\n");
x86gpf(NULL, 0);
static int opMOV_r_TRx_a16(uint32_t fetchdat)
{
- if ((CPL || (eflags&VM_FLAG)) && (cr0&1))
+ if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1))
{
pclog("Can't load from TRx\n");
x86gpf(NULL, 0);
}
static int opMOV_r_TRx_a32(uint32_t fetchdat)
{
- if ((CPL || (eflags&VM_FLAG)) && (cr0&1))
+ if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1))
{
pclog("Can't load from TRx\n");
x86gpf(NULL, 0);
static int opMOV_TRx_r_a16(uint32_t fetchdat)
{
- if ((CPL || (eflags&VM_FLAG)) && (cr0&1))
+ if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1))
{
pclog("Can't load TRx\n");
x86gpf(NULL, 0);
}
static int opMOV_TRx_r_a32(uint32_t fetchdat)
{
- if ((CPL || (eflags&VM_FLAG)) && (cr0&1))
+ if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1))
{
pclog("Can't load TRx\n");
x86gpf(NULL, 0);
static int opMOV_w_seg_a16(uint32_t fetchdat)
{
fetch_ea_16(fetchdat);
-
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
+
switch (rmdat & 0x38)
{
case 0x00: /*ES*/
static int opMOV_w_seg_a32(uint32_t fetchdat)
{
fetch_ea_32(fetchdat);
-
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
+
switch (rmdat & 0x38)
{
case 0x00: /*ES*/
static int opMOV_l_seg_a16(uint32_t fetchdat)
{
fetch_ea_16(fetchdat);
-
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
+
switch (rmdat & 0x38)
{
case 0x00: /*ES*/
static int opMOV_l_seg_a32(uint32_t fetchdat)
{
fetch_ea_32(fetchdat);
-
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
+
switch (rmdat & 0x38)
{
case 0x00: /*ES*/
uint16_t new_seg;
fetch_ea_16(fetchdat);
-
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
new_seg=geteaw(); if (cpu_state.abrt) return 1;
switch (rmdat & 0x38)
{
case 0x00: /*ES*/
- loadseg(new_seg, &_es);
+ loadseg(new_seg, &cpu_state.seg_es);
break;
case 0x18: /*DS*/
- loadseg(new_seg, &_ds);
+ loadseg(new_seg, &cpu_state.seg_ds);
break;
case 0x10: /*SS*/
- loadseg(new_seg, &_ss);
+ loadseg(new_seg, &cpu_state.seg_ss);
if (cpu_state.abrt) return 1;
cpu_state.oldpc = cpu_state.pc;
cpu_state.op32 = use32;
cpu_state.ssegs = 0;
- cpu_state.ea_seg = &_ds;
+ cpu_state.ea_seg = &cpu_state.seg_ds;
fetchdat = fastreadl(cs + cpu_state.pc);
cpu_state.pc++;
if (cpu_state.abrt) return 1;
x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8);
return 1;
case 0x20: /*FS*/
- loadseg(new_seg, &_fs);
+ loadseg(new_seg, &cpu_state.seg_fs);
break;
case 0x28: /*GS*/
- loadseg(new_seg, &_gs);
+ loadseg(new_seg, &cpu_state.seg_gs);
break;
}
uint16_t new_seg;
fetch_ea_32(fetchdat);
-
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
new_seg=geteaw(); if (cpu_state.abrt) return 1;
switch (rmdat & 0x38)
{
case 0x00: /*ES*/
- loadseg(new_seg, &_es);
+ loadseg(new_seg, &cpu_state.seg_es);
break;
case 0x18: /*DS*/
- loadseg(new_seg, &_ds);
+ loadseg(new_seg, &cpu_state.seg_ds);
break;
case 0x10: /*SS*/
- loadseg(new_seg, &_ss);
+ loadseg(new_seg, &cpu_state.seg_ss);
if (cpu_state.abrt) return 1;
cpu_state.oldpc = cpu_state.pc;
cpu_state.op32 = use32;
cpu_state.ssegs = 0;
- cpu_state.ea_seg = &_ds;
+ cpu_state.ea_seg = &cpu_state.seg_ds;
fetchdat = fastreadl(cs + cpu_state.pc);
cpu_state.pc++;
if (cpu_state.abrt) return 1;
x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8);
return 1;
case 0x20: /*FS*/
- loadseg(new_seg, &_fs);
+ loadseg(new_seg, &cpu_state.seg_fs);
break;
case 0x28: /*GS*/
- loadseg(new_seg, &_gs);
+ loadseg(new_seg, &cpu_state.seg_gs);
break;
}
fetch_ea_16(fetchdat);
ILLEGAL_ON(cpu_mod == 3);
+ SEG_CHECK_READ(cpu_state.ea_seg);
addr = readmemw(easeg, cpu_state.eaaddr);
seg = readmemw(easeg, cpu_state.eaaddr + 2); if (cpu_state.abrt) return 1;
- loadseg(seg, &_ds); if (cpu_state.abrt) return 1;
+ loadseg(seg, &cpu_state.seg_ds); if (cpu_state.abrt) return 1;
cpu_state.regs[cpu_reg].w = addr;
CLOCK_CYCLES(7);
fetch_ea_32(fetchdat);
ILLEGAL_ON(cpu_mod == 3);
+ SEG_CHECK_READ(cpu_state.ea_seg);
addr = readmemw(easeg, cpu_state.eaaddr);
seg = readmemw(easeg, cpu_state.eaaddr + 2); if (cpu_state.abrt) return 1;
- loadseg(seg, &_ds); if (cpu_state.abrt) return 1;
+ loadseg(seg, &cpu_state.seg_ds); if (cpu_state.abrt) return 1;
cpu_state.regs[cpu_reg].w = addr;
CLOCK_CYCLES(7);
fetch_ea_16(fetchdat);
ILLEGAL_ON(cpu_mod == 3);
+ SEG_CHECK_READ(cpu_state.ea_seg);
addr = readmeml(easeg, cpu_state.eaaddr);
seg = readmemw(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 1;
- loadseg(seg, &_ds); if (cpu_state.abrt) return 1;
+ loadseg(seg, &cpu_state.seg_ds); if (cpu_state.abrt) return 1;
cpu_state.regs[cpu_reg].l = addr;
CLOCK_CYCLES(7);
fetch_ea_32(fetchdat);
ILLEGAL_ON(cpu_mod == 3);
+ SEG_CHECK_READ(cpu_state.ea_seg);
addr = readmeml(easeg, cpu_state.eaaddr);
seg = readmemw(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 1;
- loadseg(seg, &_ds); if (cpu_state.abrt) return 1;
+ loadseg(seg, &cpu_state.seg_ds); if (cpu_state.abrt) return 1;
cpu_state.regs[cpu_reg].l = addr;
CLOCK_CYCLES(7);
fetch_ea_16(fetchdat);
ILLEGAL_ON(cpu_mod == 3);
+ SEG_CHECK_READ(cpu_state.ea_seg);
addr = readmemw(easeg, cpu_state.eaaddr);
seg = readmemw(easeg, cpu_state.eaaddr + 2); if (cpu_state.abrt) return 1;
- loadseg(seg, &_ss); if (cpu_state.abrt) return 1;
+ loadseg(seg, &cpu_state.seg_ss); if (cpu_state.abrt) return 1;
cpu_state.regs[cpu_reg].w = addr;
CLOCK_CYCLES(7);
fetch_ea_32(fetchdat);
ILLEGAL_ON(cpu_mod == 3);
+ SEG_CHECK_READ(cpu_state.ea_seg);
addr = readmemw(easeg, cpu_state.eaaddr);
seg = readmemw(easeg, cpu_state.eaaddr + 2); if (cpu_state.abrt) return 1;
- loadseg(seg, &_ss); if (cpu_state.abrt) return 1;
+ loadseg(seg, &cpu_state.seg_ss); if (cpu_state.abrt) return 1;
cpu_state.regs[cpu_reg].w = addr;
CLOCK_CYCLES(7);
fetch_ea_16(fetchdat);
ILLEGAL_ON(cpu_mod == 3);
+ SEG_CHECK_READ(cpu_state.ea_seg);
addr = readmeml(easeg, cpu_state.eaaddr);
seg = readmemw(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 1;
- loadseg(seg, &_ss); if (cpu_state.abrt) return 1;
+ loadseg(seg, &cpu_state.seg_ss); if (cpu_state.abrt) return 1;
cpu_state.regs[cpu_reg].l = addr;
CLOCK_CYCLES(7);
fetch_ea_32(fetchdat);
ILLEGAL_ON(cpu_mod == 3);
+ SEG_CHECK_READ(cpu_state.ea_seg);
addr = readmeml(easeg, cpu_state.eaaddr);
seg = readmemw(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 1;
- loadseg(seg, &_ss); if (cpu_state.abrt) return 1;
+ loadseg(seg, &cpu_state.seg_ss); if (cpu_state.abrt) return 1;
cpu_state.regs[cpu_reg].l = addr;
CLOCK_CYCLES(7);
uint16_t addr, seg; \
\
fetch_ea_16(fetchdat); \
+ SEG_CHECK_READ(cpu_state.ea_seg); \
ILLEGAL_ON(cpu_mod == 3); \
addr = readmemw(easeg, cpu_state.eaaddr); \
seg = readmemw(easeg, cpu_state.eaaddr + 2); if (cpu_state.abrt) return 1; \
uint16_t addr, seg; \
\
fetch_ea_32(fetchdat); \
+ SEG_CHECK_READ(cpu_state.ea_seg); \
ILLEGAL_ON(cpu_mod == 3); \
addr = readmemw(easeg, cpu_state.eaaddr); \
seg = readmemw(easeg, cpu_state.eaaddr + 2); if (cpu_state.abrt) return 1; \
uint16_t seg; \
\
fetch_ea_16(fetchdat); \
+ SEG_CHECK_READ(cpu_state.ea_seg); \
ILLEGAL_ON(cpu_mod == 3); \
addr = readmeml(easeg, cpu_state.eaaddr); \
seg = readmemw(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 1; \
uint16_t seg; \
\
fetch_ea_32(fetchdat); \
+ SEG_CHECK_READ(cpu_state.ea_seg); \
ILLEGAL_ON(cpu_mod == 3); \
addr = readmeml(easeg, cpu_state.eaaddr); \
seg = readmemw(easeg, cpu_state.eaaddr + 4); if (cpu_state.abrt) return 1; \
return 0; \
}
-opLsel(ES, _es)
-opLsel(FS, _fs)
-opLsel(GS, _gs)
+opLsel(ES, cpu_state.seg_es)
+opLsel(FS, cpu_state.seg_fs)
+opLsel(GS, cpu_state.seg_gs)
uint8_t temp;
fetch_ea_16(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
temp = geteab(); if (cpu_state.abrt) return 1;
cpu_state.regs[cpu_reg].w = (uint16_t)temp;
uint8_t temp;
fetch_ea_32(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
temp = geteab(); if (cpu_state.abrt) return 1;
cpu_state.regs[cpu_reg].w = (uint16_t)temp;
uint8_t temp;
fetch_ea_16(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
temp = geteab(); if (cpu_state.abrt) return 1;
cpu_state.regs[cpu_reg].l = (uint32_t)temp;
uint8_t temp;
fetch_ea_32(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
temp = geteab(); if (cpu_state.abrt) return 1;
cpu_state.regs[cpu_reg].l = (uint32_t)temp;
uint16_t temp;
fetch_ea_16(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
temp = geteaw(); if (cpu_state.abrt) return 1;
cpu_state.regs[cpu_reg].w = temp;
uint16_t temp;
fetch_ea_32(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
temp = geteaw(); if (cpu_state.abrt) return 1;
cpu_state.regs[cpu_reg].w = temp;
uint16_t temp;
fetch_ea_16(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
temp = geteaw(); if (cpu_state.abrt) return 1;
cpu_state.regs[cpu_reg].l = (uint32_t)temp;
uint16_t temp;
fetch_ea_32(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
temp = geteaw(); if (cpu_state.abrt) return 1;
cpu_state.regs[cpu_reg].l = (uint32_t)temp;
uint8_t temp;
fetch_ea_16(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
temp = geteab(); if (cpu_state.abrt) return 1;
cpu_state.regs[cpu_reg].w = (uint16_t)temp;
if (temp & 0x80)
uint8_t temp;
fetch_ea_32(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
temp = geteab(); if (cpu_state.abrt) return 1;
cpu_state.regs[cpu_reg].w = (uint16_t)temp;
if (temp & 0x80)
uint8_t temp;
fetch_ea_16(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
temp = geteab(); if (cpu_state.abrt) return 1;
cpu_state.regs[cpu_reg].l = (uint32_t)temp;
if (temp & 0x80)
uint8_t temp;
fetch_ea_32(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
temp = geteab(); if (cpu_state.abrt) return 1;
cpu_state.regs[cpu_reg].l = (uint32_t)temp;
if (temp & 0x80)
uint16_t temp;
fetch_ea_16(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
temp = geteaw(); if (cpu_state.abrt) return 1;
cpu_state.regs[cpu_reg].l = (uint32_t)temp;
if (temp & 0x8000)
uint16_t temp;
fetch_ea_32(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
temp = geteaw(); if (cpu_state.abrt) return 1;
cpu_state.regs[cpu_reg].l = (uint32_t)temp;
if (temp & 0x8000)
static int opRDTSC(uint32_t fetchdat)
{
- if (!cpu_hasrdtsc)
+ if (!cpu_has_feature(CPU_FEATURE_RDTSC))
{
cpu_state.pc = cpu_state.oldpc;
x86illegal();
int16_t tempw, tempw2;
fetch_ea_16(fetchdat);
-
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
+
tempw = geteaw(); if (cpu_state.abrt) return 1;
tempw2 = getword(); if (cpu_state.abrt) return 1;
templ = ((int)tempw) * ((int)tempw2);
flags_rebuild();
- if ((templ >> 15) != 0 && (templ >> 15) != -1) flags |= C_FLAG | V_FLAG;
- else flags &= ~(C_FLAG | V_FLAG);
+ if ((templ >> 15) != 0 && (templ >> 15) != -1) cpu_state.flags |= C_FLAG | V_FLAG;
+ else cpu_state.flags &= ~(C_FLAG | V_FLAG);
cpu_state.regs[cpu_reg].w = templ & 0xffff;
CLOCK_CYCLES((cpu_mod == 3) ? 14 : 17);
int16_t tempw, tempw2;
fetch_ea_32(fetchdat);
-
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
+
tempw = geteaw(); if (cpu_state.abrt) return 1;
tempw2 = getword(); if (cpu_state.abrt) return 1;
templ = ((int)tempw) * ((int)tempw2);
flags_rebuild();
- if ((templ >> 15) != 0 && (templ >> 15) != -1) flags |= C_FLAG | V_FLAG;
- else flags &= ~(C_FLAG | V_FLAG);
+ if ((templ >> 15) != 0 && (templ >> 15) != -1) cpu_state.flags |= C_FLAG | V_FLAG;
+ else cpu_state.flags &= ~(C_FLAG | V_FLAG);
cpu_state.regs[cpu_reg].w = templ & 0xffff;
CLOCK_CYCLES((cpu_mod == 3) ? 14 : 17);
int32_t templ, templ2;
fetch_ea_16(fetchdat);
-
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
+
templ = geteal(); if (cpu_state.abrt) return 1;
templ2 = getlong(); if (cpu_state.abrt) return 1;
temp64 = ((int64_t)templ) * ((int64_t)templ2);
flags_rebuild();
- if ((temp64 >> 31) != 0 && (temp64 >> 31) != -1) flags |= C_FLAG | V_FLAG;
- else flags &= ~(C_FLAG | V_FLAG);
+ if ((temp64 >> 31) != 0 && (temp64 >> 31) != -1) cpu_state.flags |= C_FLAG | V_FLAG;
+ else cpu_state.flags &= ~(C_FLAG | V_FLAG);
cpu_state.regs[cpu_reg].l = temp64 & 0xffffffff;
CLOCK_CYCLES(25);
int32_t templ, templ2;
fetch_ea_32(fetchdat);
-
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
+
templ = geteal(); if (cpu_state.abrt) return 1;
templ2 = getlong(); if (cpu_state.abrt) return 1;
temp64 = ((int64_t)templ) * ((int64_t)templ2);
flags_rebuild();
- if ((temp64 >> 31) != 0 && (temp64 >> 31) != -1) flags |= C_FLAG | V_FLAG;
- else flags &= ~(C_FLAG | V_FLAG);
+ if ((temp64 >> 31) != 0 && (temp64 >> 31) != -1) cpu_state.flags |= C_FLAG | V_FLAG;
+ else cpu_state.flags &= ~(C_FLAG | V_FLAG);
cpu_state.regs[cpu_reg].l = temp64 & 0xffffffff;
CLOCK_CYCLES(25);
int16_t tempw, tempw2;
fetch_ea_16(fetchdat);
-
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
+
tempw = geteaw(); if (cpu_state.abrt) return 1;
tempw2 = getbyte(); if (cpu_state.abrt) return 1;
if (tempw2 & 0x80) tempw2 |= 0xff00;
templ = ((int)tempw) * ((int)tempw2);
flags_rebuild();
- if ((templ >> 15) != 0 && (templ >> 15) != -1) flags |= C_FLAG | V_FLAG;
- else flags &= ~(C_FLAG | V_FLAG);
+ if ((templ >> 15) != 0 && (templ >> 15) != -1) cpu_state.flags |= C_FLAG | V_FLAG;
+ else cpu_state.flags &= ~(C_FLAG | V_FLAG);
cpu_state.regs[cpu_reg].w = templ & 0xffff;
CLOCK_CYCLES((cpu_mod == 3) ? 14 : 17);
int16_t tempw, tempw2;
fetch_ea_32(fetchdat);
-
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
+
tempw = geteaw(); if (cpu_state.abrt) return 1;
tempw2 = getbyte(); if (cpu_state.abrt) return 1;
if (tempw2 & 0x80) tempw2 |= 0xff00;
templ = ((int)tempw) * ((int)tempw2);
flags_rebuild();
- if ((templ >> 15) != 0 && (templ >> 15) != -1) flags |= C_FLAG | V_FLAG;
- else flags &= ~(C_FLAG | V_FLAG);
+ if ((templ >> 15) != 0 && (templ >> 15) != -1) cpu_state.flags |= C_FLAG | V_FLAG;
+ else cpu_state.flags &= ~(C_FLAG | V_FLAG);
cpu_state.regs[cpu_reg].w = templ & 0xffff;
CLOCK_CYCLES((cpu_mod == 3) ? 14 : 17);
int32_t templ, templ2;
fetch_ea_16(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
+
templ = geteal(); if (cpu_state.abrt) return 1;
templ2 = getbyte(); if (cpu_state.abrt) return 1;
if (templ2 & 0x80) templ2 |= 0xffffff00;
temp64 = ((int64_t)templ)*((int64_t)templ2);
flags_rebuild();
- if ((temp64 >> 31) != 0 && (temp64 >> 31) != -1) flags |= C_FLAG | V_FLAG;
- else flags &= ~(C_FLAG | V_FLAG);
+ if ((temp64 >> 31) != 0 && (temp64 >> 31) != -1) cpu_state.flags |= C_FLAG | V_FLAG;
+ else cpu_state.flags &= ~(C_FLAG | V_FLAG);
cpu_state.regs[cpu_reg].l = temp64 & 0xffffffff;
CLOCK_CYCLES(20);
int32_t templ, templ2;
fetch_ea_32(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
+
templ = geteal(); if (cpu_state.abrt) return 1;
templ2 = getbyte(); if (cpu_state.abrt) return 1;
if (templ2 & 0x80) templ2 |= 0xffffff00;
temp64 = ((int64_t)templ)*((int64_t)templ2);
flags_rebuild();
- if ((temp64 >> 31) != 0 && (temp64 >> 31) != -1) flags |= C_FLAG | V_FLAG;
- else flags &= ~(C_FLAG | V_FLAG);
+ if ((temp64 >> 31) != 0 && (temp64 >> 31) != -1) cpu_state.flags |= C_FLAG | V_FLAG;
+ else cpu_state.flags &= ~(C_FLAG | V_FLAG);
cpu_state.regs[cpu_reg].l = temp64 & 0xffffffff;
CLOCK_CYCLES(20);
int32_t templ;
fetch_ea_16(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
+
templ = (int32_t)(int16_t)cpu_state.regs[cpu_reg].w * (int32_t)(int16_t)geteaw();
if (cpu_state.abrt) return 1;
cpu_state.regs[cpu_reg].w = templ & 0xFFFF;
flags_rebuild();
- if ((templ >> 15) != 0 && (templ >> 15) != -1) flags |= C_FLAG | V_FLAG;
- else flags &= ~(C_FLAG | V_FLAG);
+ if ((templ >> 15) != 0 && (templ >> 15) != -1) cpu_state.flags |= C_FLAG | V_FLAG;
+ else cpu_state.flags &= ~(C_FLAG | V_FLAG);
CLOCK_CYCLES(18);
PREFETCH_RUN(18, 2, rmdat, 1,0,0,0, 0);
int32_t templ;
fetch_ea_32(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
+
templ = (int32_t)(int16_t)cpu_state.regs[cpu_reg].w * (int32_t)(int16_t)geteaw();
if (cpu_state.abrt) return 1;
cpu_state.regs[cpu_reg].w = templ & 0xFFFF;
flags_rebuild();
- if ((templ >> 15) != 0 && (templ >> 15) != -1) flags |= C_FLAG | V_FLAG;
- else flags &= ~(C_FLAG | V_FLAG);
+ if ((templ >> 15) != 0 && (templ >> 15) != -1) cpu_state.flags |= C_FLAG | V_FLAG;
+ else cpu_state.flags &= ~(C_FLAG | V_FLAG);
CLOCK_CYCLES(18);
PREFETCH_RUN(18, 2, rmdat, 1,0,0,0, 1);
int64_t temp64;
fetch_ea_16(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
+
temp64 = (int64_t)(int32_t)cpu_state.regs[cpu_reg].l * (int64_t)(int32_t)geteal();
if (cpu_state.abrt) return 1;
cpu_state.regs[cpu_reg].l = temp64 & 0xFFFFFFFF;
flags_rebuild();
- if ((temp64 >> 31) != 0 && (temp64 >> 31) != -1) flags |= C_FLAG | V_FLAG;
- else flags &= ~(C_FLAG | V_FLAG);
+ if ((temp64 >> 31) != 0 && (temp64 >> 31) != -1) cpu_state.flags |= C_FLAG | V_FLAG;
+ else cpu_state.flags &= ~(C_FLAG | V_FLAG);
CLOCK_CYCLES(30);
PREFETCH_RUN(30, 2, rmdat, 0,1,0,0, 0);
int64_t temp64;
fetch_ea_32(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
+
temp64 = (int64_t)(int32_t)cpu_state.regs[cpu_reg].l * (int64_t)(int32_t)geteal();
if (cpu_state.abrt) return 1;
cpu_state.regs[cpu_reg].l = temp64 & 0xFFFFFFFF;
flags_rebuild();
- if ((temp64 >> 31) != 0 && (temp64 >> 31) != -1) flags |= C_FLAG | V_FLAG;
- else flags &= ~(C_FLAG | V_FLAG);
+ if ((temp64 >> 31) != 0 && (temp64 >> 31) != -1) cpu_state.flags |= C_FLAG | V_FLAG;
+ else cpu_state.flags &= ~(C_FLAG | V_FLAG);
CLOCK_CYCLES(30);
PREFETCH_RUN(30, 2, rmdat, 0,1,0,0, 1);
NOTRM
fetch_ea_16(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
pclog("ARPL_a16\n");
temp_seg = geteaw(); if (cpu_state.abrt) return 1;
{
temp_seg = (temp_seg & 0xfffc) | (cpu_state.regs[cpu_reg].w & 3);
seteaw(temp_seg); if (cpu_state.abrt) return 1;
- flags |= Z_FLAG;
+ cpu_state.flags |= Z_FLAG;
}
else
- flags &= ~Z_FLAG;
+ cpu_state.flags &= ~Z_FLAG;
CLOCK_CYCLES(is486 ? 9 : 20);
PREFETCH_RUN(is486 ? 9 : 20, 2, rmdat, 1,0,1,0, 0);
NOTRM
fetch_ea_32(fetchdat);
- pclog("ARPL_a32\n");
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
+ pclog("ARPL_a32\n");
temp_seg = geteaw(); if (cpu_state.abrt) return 1;
flags_rebuild();
{
temp_seg = (temp_seg & 0xfffc) | (cpu_state.regs[cpu_reg].w & 3);
seteaw(temp_seg); if (cpu_state.abrt) return 1;
- flags |= Z_FLAG;
+ cpu_state.flags |= Z_FLAG;
}
else
- flags &= ~Z_FLAG;
+ cpu_state.flags &= ~Z_FLAG;
CLOCK_CYCLES(is486 ? 9 : 20);
PREFETCH_RUN(is486 ? 9 : 20, 2, rmdat, 1,0,1,0, 1);
\
NOTRM \
fetch_ea(fetchdat); \
+ if (cpu_mod != 3) \
+ SEG_CHECK_READ(cpu_state.ea_seg); \
\
sel = geteaw(); if (cpu_state.abrt) return 1; \
\
flags_rebuild(); \
- if (!(sel & 0xfffc)) { flags &= ~Z_FLAG; return 0; } /*Null selector*/ \
+ if (!(sel & 0xfffc)) { cpu_state.flags &= ~Z_FLAG; return 0; } /*Null selector*/ \
valid = (sel & ~7) < ((sel & 4) ? ldt.limit : gdt.limit); \
if (valid) \
{ \
desc = readmemw(0, ((sel & 4) ? ldt.base : gdt.base) + (sel & ~7) + 4); \
cpl_override = 0; if (cpu_state.abrt) return 1; \
} \
- flags &= ~Z_FLAG; \
+ cpu_state.flags &= ~Z_FLAG; \
if ((desc & 0x1f00) == 0x000) valid = 0; \
if ((desc & 0x1f00) == 0x800) valid = 0; \
if ((desc & 0x1f00) == 0xa00) valid = 0; \
} \
if (valid) \
{ \
- flags |= Z_FLAG; \
+ cpu_state.flags |= Z_FLAG; \
cpl_override = 1; \
if (is32) \
cpu_state.regs[cpu_reg].l = readmeml(0, ((sel & 4) ? ldt.base : gdt.base) + (sel & ~7) + 4) & 0xffff00; \
\
NOTRM \
fetch_ea(fetchdat); \
+ if (cpu_mod != 3) \
+ SEG_CHECK_READ(cpu_state.ea_seg); \
\
sel = geteaw(); if (cpu_state.abrt) return 1; \
flags_rebuild(); \
- flags &= ~Z_FLAG; \
+ cpu_state.flags &= ~Z_FLAG; \
if (!(sel & 0xfffc)) return 0; /*Null selector*/ \
valid = (sel & ~7) < ((sel & 4) ? ldt.limit : gdt.limit); \
if (valid) \
} \
if (valid) \
{ \
- flags |= Z_FLAG; \
+ cpu_state.flags |= Z_FLAG; \
cpl_override = 1; \
if (is32) \
{ \
switch (rmdat & 0x38)
{
case 0x00: /*SLDT*/
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
seteaw(ldt.seg);
CLOCK_CYCLES(4);
PREFETCH_RUN(4, 2, rmdat, 0,0,(cpu_mod == 3) ? 0:1,0, ea32);
break;
case 0x08: /*STR*/
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
seteaw(tr.seg);
CLOCK_CYCLES(4);
PREFETCH_RUN(4, 2, rmdat, 0,0,(cpu_mod == 3) ? 0:1,0, ea32);
break;
case 0x10: /*LLDT*/
- if ((CPL || eflags&VM_FLAG) && (cr0&1))
+ if ((CPL || cpu_state.eflags&VM_FLAG) && (cr0&1))
{
pclog("Invalid LLDT!\n");
x86gpf(NULL,0);
return 1;
}
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
sel = geteaw(); if (cpu_state.abrt) return 1;
addr = (sel & ~7) + gdt.base;
limit = readmemw(0, addr) + ((readmemb(0, addr + 6) & 0xf) << 16);
PREFETCH_RUN(20, 2, rmdat, (cpu_mod == 3) ? 0:1,2,0,0, ea32);
break;
case 0x18: /*LTR*/
- if ((CPL || eflags&VM_FLAG) && (cr0&1))
+ if ((CPL || cpu_state.eflags&VM_FLAG) && (cr0&1))
{
pclog("Invalid LTR!\n");
x86gpf(NULL,0);
break;
}
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
sel = geteaw(); if (cpu_state.abrt) return 1;
addr = (sel & ~7) + gdt.base;
limit = readmemw(0, addr) + ((readmemb(0, addr + 6) & 0xf) << 16);
PREFETCH_RUN(20, 2, rmdat, (cpu_mod == 3) ? 0:1,2,0,0, ea32);
break;
case 0x20: /*VERR*/
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
sel = geteaw(); if (cpu_state.abrt) return 1;
flags_rebuild();
- flags &= ~Z_FLAG;
+ cpu_state.flags &= ~Z_FLAG;
if (!(sel & 0xfffc)) return 0; /*Null selector*/
cpl_override = 1;
valid = (sel & ~7) < ((sel & 4) ? ldt.limit : gdt.limit);
if (dpl < CPL || dpl < (sel & 3)) valid = 0;
}
if ((desc & 0x0800) && !(desc & 0x0200)) valid = 0; /*Non-readable code*/
- if (valid) flags |= Z_FLAG;
+ if (valid) cpu_state.flags |= Z_FLAG;
CLOCK_CYCLES(20);
PREFETCH_RUN(20, 2, rmdat, (cpu_mod == 3) ? 1:2,0,0,0, ea32);
break;
case 0x28: /*VERW*/
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
sel = geteaw(); if (cpu_state.abrt) return 1;
flags_rebuild();
- flags &= ~Z_FLAG;
+ cpu_state.flags &= ~Z_FLAG;
if (!(sel & 0xfffc)) return 0; /*Null selector*/
cpl_override = 1;
valid = (sel & ~7) < ((sel & 4) ? ldt.limit : gdt.limit);
if (dpl < CPL || dpl < (sel & 3)) valid = 0;
if (desc & 0x0800) valid = 0; /*Code*/
if (!(desc & 0x0200)) valid = 0; /*Read-only data*/
- if (valid) flags |= Z_FLAG;
+ if (valid) cpu_state.flags |= Z_FLAG;
CLOCK_CYCLES(20);
PREFETCH_RUN(20, 2, rmdat, (cpu_mod == 3) ? 1:2,0,0,0, ea32);
break;
switch (rmdat & 0x38)
{
case 0x00: /*SGDT*/
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
seteaw(gdt.limit);
base = gdt.base; //is32 ? gdt.base : (gdt.base & 0xffffff);
if (is286)
PREFETCH_RUN(7, 2, rmdat, 0,0,1,1, ea32);
break;
case 0x08: /*SIDT*/
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
seteaw(idt.limit);
base = idt.base;
if (is286)
PREFETCH_RUN(7, 2, rmdat, 0,0,1,1, ea32);
break;
case 0x10: /*LGDT*/
- if ((CPL || eflags&VM_FLAG) && (cr0&1))
+ if ((CPL || cpu_state.eflags&VM_FLAG) && (cr0&1))
{
pclog("Invalid LGDT!\n");
x86gpf(NULL,0);
break;
}
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
// pclog("LGDT %08X:%08X\n", easeg, eaaddr);
limit = geteaw();
base = readmeml(0, easeg + cpu_state.eaaddr + 2); if (cpu_state.abrt) return 1;
PREFETCH_RUN(11, 2, rmdat, 1,1,0,0, ea32);
break;
case 0x18: /*LIDT*/
- if ((CPL || eflags&VM_FLAG) && (cr0&1))
+ if ((CPL || cpu_state.eflags&VM_FLAG) && (cr0&1))
{
pclog("Invalid LIDT!\n");
x86gpf(NULL,0);
break;
}
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
// pclog("LIDT %08X:%08X\n", easeg, eaaddr);
limit = geteaw();
base = readmeml(0, easeg + cpu_state.eaaddr + 2); if (cpu_state.abrt) return 1;
break;
case 0x20: /*SMSW*/
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
if (is486) seteaw(msw);
else if (is386) seteaw(msw | 0xFF00);
else seteaw(msw | 0xFFF0);
PREFETCH_RUN(2, 2, rmdat, 0,0,(cpu_mod == 3) ? 0:1,0, ea32);
break;
case 0x30: /*LMSW*/
- if ((CPL || eflags&VM_FLAG) && (msw&1))
+ if ((CPL || cpu_state.eflags&VM_FLAG) && (msw&1))
{
pclog("LMSW - ring not zero!\n");
x86gpf(NULL, 0);
break;
}
+ if (cpu_mod != 3)
+ SEG_CHECK_READ(cpu_state.ea_seg);
tempw = geteaw(); if (cpu_state.abrt) return 1;
if (msw & 1) tempw |= 1;
if (is386)
case 0x38: /*INVLPG*/
if (is486)
{
- if ((CPL || eflags&VM_FLAG) && (cr0&1))
+ if ((CPL || cpu_state.eflags&VM_FLAG) && (cr0&1))
{
pclog("Invalid INVLPG!\n");
x86gpf(NULL, 0);
break;
}
+ SEG_CHECK_READ(cpu_state.ea_seg);
mmu_invalidate(ds + cpu_state.eaaddr);
CLOCK_CYCLES(12);
PREFETCH_RUN(12, 2, rmdat, 0,0,0,0, ea32);
return normal_opcode_table[(fetchdat & 0xff) | 0x300](fetchdat >> 8); \
}
-op_seg(CS, _cs, x86_opcodes, x86_opcodes)
-op_seg(DS, _ds, x86_opcodes, x86_opcodes)
-op_seg(ES, _es, x86_opcodes, x86_opcodes)
-op_seg(FS, _fs, x86_opcodes, x86_opcodes)
-op_seg(GS, _gs, x86_opcodes, x86_opcodes)
-op_seg(SS, _ss, x86_opcodes, x86_opcodes)
+op_seg(CS, cpu_state.seg_cs, x86_opcodes, x86_opcodes)
+op_seg(DS, cpu_state.seg_ds, x86_opcodes, x86_opcodes)
+op_seg(ES, cpu_state.seg_es, x86_opcodes, x86_opcodes)
+op_seg(FS, cpu_state.seg_fs, x86_opcodes, x86_opcodes)
+op_seg(GS, cpu_state.seg_gs, x86_opcodes, x86_opcodes)
+op_seg(SS, cpu_state.seg_ss, x86_opcodes, x86_opcodes)
-op_seg(CS_REPE, _cs, x86_opcodes_REPE, x86_opcodes)
-op_seg(DS_REPE, _ds, x86_opcodes_REPE, x86_opcodes)
-op_seg(ES_REPE, _es, x86_opcodes_REPE, x86_opcodes)
-op_seg(FS_REPE, _fs, x86_opcodes_REPE, x86_opcodes)
-op_seg(GS_REPE, _gs, x86_opcodes_REPE, x86_opcodes)
-op_seg(SS_REPE, _ss, x86_opcodes_REPE, x86_opcodes)
+op_seg(CS_REPE, cpu_state.seg_cs, x86_opcodes_REPE, x86_opcodes)
+op_seg(DS_REPE, cpu_state.seg_ds, x86_opcodes_REPE, x86_opcodes)
+op_seg(ES_REPE, cpu_state.seg_es, x86_opcodes_REPE, x86_opcodes)
+op_seg(FS_REPE, cpu_state.seg_fs, x86_opcodes_REPE, x86_opcodes)
+op_seg(GS_REPE, cpu_state.seg_gs, x86_opcodes_REPE, x86_opcodes)
+op_seg(SS_REPE, cpu_state.seg_ss, x86_opcodes_REPE, x86_opcodes)
-op_seg(CS_REPNE, _cs, x86_opcodes_REPNE, x86_opcodes)
-op_seg(DS_REPNE, _ds, x86_opcodes_REPNE, x86_opcodes)
-op_seg(ES_REPNE, _es, x86_opcodes_REPNE, x86_opcodes)
-op_seg(FS_REPNE, _fs, x86_opcodes_REPNE, x86_opcodes)
-op_seg(GS_REPNE, _gs, x86_opcodes_REPNE, x86_opcodes)
-op_seg(SS_REPNE, _ss, x86_opcodes_REPNE, x86_opcodes)
+op_seg(CS_REPNE, cpu_state.seg_cs, x86_opcodes_REPNE, x86_opcodes)
+op_seg(DS_REPNE, cpu_state.seg_ds, x86_opcodes_REPNE, x86_opcodes)
+op_seg(ES_REPNE, cpu_state.seg_es, x86_opcodes_REPNE, x86_opcodes)
+op_seg(FS_REPNE, cpu_state.seg_fs, x86_opcodes_REPNE, x86_opcodes)
+op_seg(GS_REPNE, cpu_state.seg_gs, x86_opcodes_REPNE, x86_opcodes)
+op_seg(SS_REPNE, cpu_state.seg_ss, x86_opcodes_REPNE, x86_opcodes)
static int op_66(uint32_t fetchdat) /*Data size select*/
{
-extern int trap;
-
#define REP_OPS(size, CNT_REG, SRC_REG, DEST_REG) \
static int opREP_INSB_ ## size(uint32_t fetchdat) \
{ \
{ \
uint8_t temp; \
\
- check_io_perm(DX); \
+ SEG_CHECK_WRITE(&cpu_state.seg_es); \
+ check_io_perm(DX); \
temp = inb(DX); \
writememb(es, DEST_REG, temp); if (cpu_state.abrt) return 1; \
\
- if (flags & D_FLAG) DEST_REG--; \
- else DEST_REG++; \
+ if (cpu_state.flags & D_FLAG) DEST_REG--; \
+ else DEST_REG++; \
CNT_REG--; \
cycles -= 15; \
reads++; writes++; total_cycles += 15; \
{ \
uint16_t temp; \
\
+ SEG_CHECK_WRITE(&cpu_state.seg_es); \
check_io_perm(DX); \
check_io_perm(DX+1); \
temp = inw(DX); \
writememw(es, DEST_REG, temp); if (cpu_state.abrt) return 1; \
\
- if (flags & D_FLAG) DEST_REG -= 2; \
- else DEST_REG += 2; \
+ if (cpu_state.flags & D_FLAG) DEST_REG -= 2; \
+ else DEST_REG += 2; \
CNT_REG--; \
cycles -= 15; \
reads++; writes++; total_cycles += 15; \
{ \
uint32_t temp; \
\
+ SEG_CHECK_WRITE(&cpu_state.seg_es); \
check_io_perm(DX); \
check_io_perm(DX+1); \
check_io_perm(DX+2); \
temp = inl(DX); \
writememl(es, DEST_REG, temp); if (cpu_state.abrt) return 1; \
\
- if (flags & D_FLAG) DEST_REG -= 4; \
- else DEST_REG += 4; \
+ if (cpu_state.flags & D_FLAG) DEST_REG -= 4; \
+ else DEST_REG += 4; \
CNT_REG--; \
cycles -= 15; \
reads++; writes++; total_cycles += 15; \
\
if (CNT_REG > 0) \
{ \
- uint8_t temp = readmemb(cpu_state.ea_seg->base, SRC_REG); if (cpu_state.abrt) return 1; \
+ uint8_t temp; \
+ SEG_CHECK_READ(cpu_state.ea_seg); \
+ temp = readmemb(cpu_state.ea_seg->base, SRC_REG); if (cpu_state.abrt) return 1; \
check_io_perm(DX); \
outb(DX, temp); \
- if (flags & D_FLAG) SRC_REG--; \
- else SRC_REG++; \
+ if (cpu_state.flags & D_FLAG) SRC_REG--; \
+ else SRC_REG++; \
CNT_REG--; \
cycles -= 14; \
reads++; writes++; total_cycles += 14; \
\
if (CNT_REG > 0) \
{ \
- uint16_t temp = readmemw(cpu_state.ea_seg->base, SRC_REG); if (cpu_state.abrt) return 1; \
+ uint16_t temp; \
+ SEG_CHECK_READ(cpu_state.ea_seg); \
+ temp = readmemw(cpu_state.ea_seg->base, SRC_REG); if (cpu_state.abrt) return 1; \
check_io_perm(DX); \
check_io_perm(DX+1); \
outw(DX, temp); \
- if (flags & D_FLAG) SRC_REG -= 2; \
- else SRC_REG += 2; \
+ if (cpu_state.flags & D_FLAG) SRC_REG -= 2; \
+ else SRC_REG += 2; \
CNT_REG--; \
cycles -= 14; \
reads++; writes++; total_cycles += 14; \
\
if (CNT_REG > 0) \
{ \
- uint32_t temp = readmeml(cpu_state.ea_seg->base, SRC_REG); if (cpu_state.abrt) return 1; \
+ uint32_t temp; \
+ SEG_CHECK_READ(cpu_state.ea_seg); \
+ temp = readmeml(cpu_state.ea_seg->base, SRC_REG); if (cpu_state.abrt) return 1; \
check_io_perm(DX); \
check_io_perm(DX+1); \
check_io_perm(DX+2); \
check_io_perm(DX+3); \
outl(DX, temp); \
- if (flags & D_FLAG) SRC_REG -= 4; \
- else SRC_REG += 4; \
+ if (cpu_state.flags & D_FLAG) SRC_REG -= 4; \
+ else SRC_REG += 4; \
CNT_REG--; \
cycles -= 14; \
reads++; writes++; total_cycles += 14; \
int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \
if (trap) \
cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/ \
+ if (CNT_REG > 0) \
+ { \
+ SEG_CHECK_READ(cpu_state.ea_seg); \
+ SEG_CHECK_WRITE(&cpu_state.seg_es); \
+ } \
while (CNT_REG > 0) \
{ \
uint8_t temp; \
\
- CHECK_WRITE_REP(&_es, DEST_REG, DEST_REG); \
+ CHECK_WRITE_REP(&cpu_state.seg_es, DEST_REG, DEST_REG); \
temp = readmemb(cpu_state.ea_seg->base, SRC_REG); if (cpu_state.abrt) return 1; \
writememb(es, DEST_REG, temp); if (cpu_state.abrt) return 1; \
\
- if (flags & D_FLAG) { DEST_REG--; SRC_REG--; } \
- else { DEST_REG++; SRC_REG++; } \
+ if (cpu_state.flags & D_FLAG) { DEST_REG--; SRC_REG--; } \
+ else { DEST_REG++; SRC_REG++; } \
CNT_REG--; \
cycles -= is486 ? 3 : 4; \
ins++; \
int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \
if (trap) \
cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/ \
+ if (CNT_REG > 0) \
+ { \
+ SEG_CHECK_READ(cpu_state.ea_seg); \
+ SEG_CHECK_WRITE(&cpu_state.seg_es); \
+ } \
while (CNT_REG > 0) \
{ \
uint16_t temp; \
\
- CHECK_WRITE_REP(&_es, DEST_REG, DEST_REG); \
+ CHECK_WRITE_REP(&cpu_state.seg_es, DEST_REG, DEST_REG); \
temp = readmemw(cpu_state.ea_seg->base, SRC_REG); if (cpu_state.abrt) return 1; \
writememw(es, DEST_REG, temp); if (cpu_state.abrt) return 1; \
\
- if (flags & D_FLAG) { DEST_REG -= 2; SRC_REG -= 2; } \
- else { DEST_REG += 2; SRC_REG += 2; } \
+ if (cpu_state.flags & D_FLAG) { DEST_REG -= 2; SRC_REG -= 2; } \
+ else { DEST_REG += 2; SRC_REG += 2; } \
CNT_REG--; \
cycles -= is486 ? 3 : 4; \
ins++; \
int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \
if (trap) \
cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/ \
+ if (CNT_REG > 0) \
+ { \
+ SEG_CHECK_READ(cpu_state.ea_seg); \
+ SEG_CHECK_WRITE(&cpu_state.seg_es); \
+ } \
while (CNT_REG > 0) \
{ \
uint32_t temp; \
\
- CHECK_WRITE_REP(&_es, DEST_REG, DEST_REG); \
+ CHECK_WRITE_REP(&cpu_state.seg_es, DEST_REG, DEST_REG); \
temp = readmeml(cpu_state.ea_seg->base, SRC_REG); if (cpu_state.abrt) return 1; \
writememl(es, DEST_REG, temp); if (cpu_state.abrt) return 1; \
\
- if (flags & D_FLAG) { DEST_REG -= 4; SRC_REG -= 4; } \
- else { DEST_REG += 4; SRC_REG += 4; } \
+ if (cpu_state.flags & D_FLAG) { DEST_REG -= 4; SRC_REG -= 4; } \
+ else { DEST_REG += 4; SRC_REG += 4; } \
CNT_REG--; \
cycles -= is486 ? 3 : 4; \
ins++; \
int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \
if (trap) \
cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/ \
+ if (CNT_REG > 0) \
+ SEG_CHECK_WRITE(&cpu_state.seg_es); \
while (CNT_REG > 0) \
{ \
- CHECK_WRITE_REP(&_es, DEST_REG, DEST_REG); \
+ CHECK_WRITE_REP(&cpu_state.seg_es, DEST_REG, DEST_REG); \
writememb(es, DEST_REG, AL); if (cpu_state.abrt) return 1; \
- if (flags & D_FLAG) DEST_REG--; \
- else DEST_REG++; \
+ if (cpu_state.flags & D_FLAG) DEST_REG--; \
+ else DEST_REG++; \
CNT_REG--; \
cycles -= is486 ? 4 : 5; \
writes++; total_cycles += is486 ? 4 : 5; \
int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \
if (trap) \
cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/ \
+ if (CNT_REG > 0) \
+ SEG_CHECK_WRITE(&cpu_state.seg_es); \
while (CNT_REG > 0) \
{ \
- CHECK_WRITE_REP(&_es, DEST_REG, DEST_REG+1); \
+ CHECK_WRITE_REP(&cpu_state.seg_es, DEST_REG, DEST_REG+1); \
writememw(es, DEST_REG, AX); if (cpu_state.abrt) return 1; \
- if (flags & D_FLAG) DEST_REG -= 2; \
- else DEST_REG += 2; \
+ if (cpu_state.flags & D_FLAG) DEST_REG -= 2; \
+ else DEST_REG += 2; \
CNT_REG--; \
cycles -= is486 ? 4 : 5; \
writes++; total_cycles += is486 ? 4 : 5; \
int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \
if (trap) \
cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/ \
+ if (CNT_REG > 0) \
+ SEG_CHECK_WRITE(&cpu_state.seg_es); \
while (CNT_REG > 0) \
{ \
- CHECK_WRITE_REP(&_es, DEST_REG, DEST_REG+3); \
+ CHECK_WRITE_REP(&cpu_state.seg_es, DEST_REG, DEST_REG+3); \
writememl(es, DEST_REG, EAX); if (cpu_state.abrt) return 1; \
- if (flags & D_FLAG) DEST_REG -= 4; \
- else DEST_REG += 4; \
+ if (cpu_state.flags & D_FLAG) DEST_REG -= 4; \
+ else DEST_REG += 4; \
CNT_REG--; \
cycles -= is486 ? 4 : 5; \
writes++; total_cycles += is486 ? 4 : 5; \
int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \
if (trap) \
cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/ \
+ if (CNT_REG > 0) \
+ SEG_CHECK_READ(cpu_state.ea_seg); \
while (CNT_REG > 0) \
{ \
AL = readmemb(cpu_state.ea_seg->base, SRC_REG); if (cpu_state.abrt) return 1; \
- if (flags & D_FLAG) SRC_REG--; \
- else SRC_REG++; \
+ if (cpu_state.flags & D_FLAG) SRC_REG--; \
+ else SRC_REG++; \
CNT_REG--; \
cycles -= is486 ? 4 : 5; \
reads++; total_cycles += is486 ? 4 : 5; \
int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \
if (trap) \
cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/ \
+ if (CNT_REG > 0) \
+ SEG_CHECK_READ(cpu_state.ea_seg); \
while (CNT_REG > 0) \
{ \
AX = readmemw(cpu_state.ea_seg->base, SRC_REG); if (cpu_state.abrt) return 1; \
- if (flags & D_FLAG) SRC_REG -= 2; \
- else SRC_REG += 2; \
+ if (cpu_state.flags & D_FLAG) SRC_REG -= 2; \
+ else SRC_REG += 2; \
CNT_REG--; \
cycles -= is486 ? 4 : 5; \
reads++; total_cycles += is486 ? 4 : 5; \
int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \
if (trap) \
cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/ \
+ if (CNT_REG > 0) \
+ SEG_CHECK_READ(cpu_state.ea_seg); \
while (CNT_REG > 0) \
{ \
EAX = readmeml(cpu_state.ea_seg->base, SRC_REG); if (cpu_state.abrt) return 1; \
- if (flags & D_FLAG) SRC_REG -= 4; \
- else SRC_REG += 4; \
+ if (cpu_state.flags & D_FLAG) SRC_REG -= 4; \
+ else SRC_REG += 4; \
CNT_REG--; \
cycles -= is486 ? 4 : 5; \
reads++; total_cycles += is486 ? 4 : 5; \
tempz = FV; \
if ((CNT_REG > 0) && (FV == tempz)) \
{ \
- uint8_t temp = readmemb(cpu_state.ea_seg->base, SRC_REG); \
- uint8_t temp2 = readmemb(es, DEST_REG); if (cpu_state.abrt) return 1; \
+ uint8_t temp, temp2; \
+ SEG_CHECK_READ(cpu_state.ea_seg); \
+ SEG_CHECK_READ(&cpu_state.seg_es); \
+ temp = readmemb(cpu_state.ea_seg->base, SRC_REG); \
+ temp2 = readmemb(es, DEST_REG); if (cpu_state.abrt) return 1; \
\
- if (flags & D_FLAG) { DEST_REG--; SRC_REG--; } \
- else { DEST_REG++; SRC_REG++; } \
+ if (cpu_state.flags & D_FLAG) { DEST_REG--; SRC_REG--; } \
+ else { DEST_REG++; SRC_REG++; } \
CNT_REG--; \
cycles -= is486 ? 7 : 9; \
reads += 2; total_cycles += is486 ? 7 : 9; \
tempz = FV; \
if ((CNT_REG > 0) && (FV == tempz)) \
{ \
- uint16_t temp = readmemw(cpu_state.ea_seg->base, SRC_REG); \
- uint16_t temp2 = readmemw(es, DEST_REG); if (cpu_state.abrt) return 1; \
+ uint16_t temp, temp2; \
+ SEG_CHECK_READ(cpu_state.ea_seg); \
+ SEG_CHECK_READ(&cpu_state.seg_es); \
+ temp = readmemw(cpu_state.ea_seg->base, SRC_REG); \
+ temp2 = readmemw(es, DEST_REG); if (cpu_state.abrt) return 1; \
\
- if (flags & D_FLAG) { DEST_REG -= 2; SRC_REG -= 2; } \
- else { DEST_REG += 2; SRC_REG += 2; } \
+ if (cpu_state.flags & D_FLAG) { DEST_REG -= 2; SRC_REG -= 2; } \
+ else { DEST_REG += 2; SRC_REG += 2; } \
CNT_REG--; \
cycles -= is486 ? 7 : 9; \
reads += 2; total_cycles += is486 ? 7 : 9; \
tempz = FV; \
if ((CNT_REG > 0) && (FV == tempz)) \
{ \
- uint32_t temp = readmeml(cpu_state.ea_seg->base, SRC_REG); \
- uint32_t temp2 = readmeml(es, DEST_REG); if (cpu_state.abrt) return 1; \
+ uint32_t temp, temp2; \
+ SEG_CHECK_READ(cpu_state.ea_seg); \
+ SEG_CHECK_READ(&cpu_state.seg_es); \
+ temp = readmeml(cpu_state.ea_seg->base, SRC_REG); \
+ temp2 = readmeml(es, DEST_REG); if (cpu_state.abrt) return 1; \
\
- if (flags & D_FLAG) { DEST_REG -= 4; SRC_REG -= 4; } \
- else { DEST_REG += 4; SRC_REG += 4; } \
+ if (cpu_state.flags & D_FLAG) { DEST_REG -= 4; SRC_REG -= 4; } \
+ else { DEST_REG += 4; SRC_REG += 4; } \
CNT_REG--; \
cycles -= is486 ? 7 : 9; \
reads += 2; total_cycles += is486 ? 7 : 9; \
if (trap) \
cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/ \
tempz = FV; \
+ if ((CNT_REG > 0) && (FV == tempz)) \
+ SEG_CHECK_READ(&cpu_state.seg_es); \
while ((CNT_REG > 0) && (FV == tempz)) \
{ \
uint8_t temp = readmemb(es, DEST_REG); if (cpu_state.abrt) break;\
setsub8(AL, temp); \
tempz = (ZF_SET()) ? 1 : 0; \
- if (flags & D_FLAG) DEST_REG--; \
- else DEST_REG++; \
+ if (cpu_state.flags & D_FLAG) DEST_REG--; \
+ else DEST_REG++; \
CNT_REG--; \
cycles -= is486 ? 5 : 8; \
reads++; total_cycles += is486 ? 5 : 8; \
if (trap) \
cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/ \
tempz = FV; \
+ if ((CNT_REG > 0) && (FV == tempz)) \
+ SEG_CHECK_READ(&cpu_state.seg_es); \
while ((CNT_REG > 0) && (FV == tempz)) \
{ \
uint16_t temp = readmemw(es, DEST_REG); if (cpu_state.abrt) break;\
setsub16(AX, temp); \
tempz = (ZF_SET()) ? 1 : 0; \
- if (flags & D_FLAG) DEST_REG -= 2; \
- else DEST_REG += 2; \
+ if (cpu_state.flags & D_FLAG) DEST_REG -= 2; \
+ else DEST_REG += 2; \
CNT_REG--; \
cycles -= is486 ? 5 : 8; \
reads++; total_cycles += is486 ? 5 : 8; \
if (trap) \
cycles_end = cycles+1; /*Force the instruction to end after only one iteration when trap flag set*/ \
tempz = FV; \
+ if ((CNT_REG > 0) && (FV == tempz)) \
+ SEG_CHECK_READ(&cpu_state.seg_es); \
while ((CNT_REG > 0) && (FV == tempz)) \
{ \
uint32_t temp = readmeml(es, DEST_REG); if (cpu_state.abrt) break;\
setsub32(EAX, temp); \
tempz = (ZF_SET()) ? 1 : 0; \
- if (flags & D_FLAG) DEST_REG -= 4; \
- else DEST_REG += 4; \
+ if (cpu_state.flags & D_FLAG) DEST_REG -= 4; \
+ else DEST_REG += 4; \
CNT_REG--; \
cycles -= is486 ? 5 : 8; \
reads++; total_cycles += is486 ? 5 : 8; \
#define RETF_a16(stack_offset) \
- if ((msw&1) && !(eflags&VM_FLAG)) \
+ if ((msw&1) && !(cpu_state.eflags&VM_FLAG)) \
{ \
pmoderetf(0, stack_offset); \
return 1; \
} \
- oxpc = cpu_state.pc; \
if (stack32) \
{ \
cpu_state.pc = readmemw(ss, ESP); \
cycles -= timing_retf_rm;
#define RETF_a32(stack_offset) \
- if ((msw&1) && !(eflags&VM_FLAG)) \
+ if ((msw&1) && !(cpu_state.eflags&VM_FLAG)) \
{ \
pmoderetf(1, stack_offset); \
return 1; \
} \
- oxpc = cpu_state.pc; \
if (stack32) \
{ \
cpu_state.pc = readmeml(ss, ESP); \
{
int cycles_old = cycles; UNUSED(cycles_old);
- if ((cr0 & 1) && (eflags & VM_FLAG) && (IOPL != 3))
+ if ((cr0 & 1) && (cpu_state.eflags & VM_FLAG) && (IOPL != 3))
{
x86gpf(NULL,0);
return 1;
else
{
uint16_t new_cs;
- oxpc = cpu_state.pc;
if (stack32)
{
cpu_state.pc = readmemw(ss, ESP);
new_cs = readmemw(ss, ESP + 2);
- flags = (flags & 0x7000) | (readmemw(ss, ESP + 4) & 0xffd5) | 2;
+ cpu_state.flags = (cpu_state.flags & 0x7000) | (readmemw(ss, ESP + 4) & 0xffd5) | 2;
ESP += 6;
}
else
{
cpu_state.pc = readmemw(ss, SP);
new_cs = readmemw(ss, ((SP + 2) & 0xffff));
- flags = (flags & 0x7000) | (readmemw(ss, ((SP + 4) & 0xffff)) & 0x0fd5) | 2;
+ cpu_state.flags = (cpu_state.flags & 0x7000) | (readmemw(ss, ((SP + 4) & 0xffff)) & 0x0fd5) | 2;
SP += 6;
}
loadcs(new_cs);
{
int cycles_old = cycles; UNUSED(cycles_old);
- if ((cr0 & 1) && (eflags & VM_FLAG) && (IOPL != 3))
+ if ((cr0 & 1) && (cpu_state.eflags & VM_FLAG) && (IOPL != 3))
{
if (cr4 & CR4_VME)
{
if (cpu_state.abrt)
return 1;
- if ((new_flags & T_FLAG) || ((new_flags & I_FLAG) && (eflags & VIP_FLAG)))
+ if ((new_flags & T_FLAG) || ((new_flags & I_FLAG) && (cpu_state.eflags & VIP_FLAG)))
{
x86gpf(NULL, 0);
return 1;
}
SP += 6;
if (new_flags & I_FLAG)
- eflags |= VIF_FLAG;
+ cpu_state.eflags |= VIF_FLAG;
else
- eflags &= ~VIF_FLAG;
- flags = (flags & 0x3300) | (new_flags & 0x4cd5) | 2;
+ cpu_state.eflags &= ~VIF_FLAG;
+ cpu_state.flags = (cpu_state.flags & 0x3300) | (new_flags & 0x4cd5) | 2;
loadcs(new_cs);
cpu_state.pc = new_pc;
else
{
uint16_t new_cs;
- oxpc = cpu_state.pc;
if (stack32)
{
cpu_state.pc = readmemw(ss, ESP);
new_cs = readmemw(ss, ESP + 2);
- flags = (readmemw(ss, ESP + 4) & 0xffd5) | 2;
+ cpu_state.flags = (readmemw(ss, ESP + 4) & 0xffd5) | 2;
ESP += 6;
}
else
{
cpu_state.pc = readmemw(ss, SP);
new_cs = readmemw(ss, ((SP + 2) & 0xffff));
- flags = (readmemw(ss, ((SP + 4) & 0xffff)) & 0xffd5) | 2;
+ cpu_state.flags = (readmemw(ss, ((SP + 4) & 0xffff)) & 0xffd5) | 2;
SP += 6;
}
loadcs(new_cs);
{
int cycles_old = cycles; UNUSED(cycles_old);
- if ((cr0 & 1) && (eflags & VM_FLAG) && (IOPL != 3))
+ if ((cr0 & 1) && (cpu_state.eflags & VM_FLAG) && (IOPL != 3))
{
x86gpf(NULL,0);
return 1;
else
{
uint16_t new_cs;
- oxpc = cpu_state.pc;
if (stack32)
{
cpu_state.pc = readmeml(ss, ESP);
new_cs = readmemw(ss, ESP + 4);
- flags = (readmemw(ss, ESP + 8) & 0xffd5) | 2;
- eflags = readmemw(ss, ESP + 10);
+ cpu_state.flags = (readmemw(ss, ESP + 8) & 0xffd5) | 2;
+ cpu_state.eflags = readmemw(ss, ESP + 10);
ESP += 12;
}
else
{
cpu_state.pc = readmeml(ss, SP);
new_cs = readmemw(ss, ((SP + 4) & 0xffff));
- flags = (readmemw(ss,(SP + 8) & 0xffff) & 0xffd5) | 2;
- eflags = readmemw(ss, (SP + 10) & 0xffff);
+ cpu_state.flags = (readmemw(ss,(SP + 8) & 0xffff) & 0xffd5) | 2;
+ cpu_state.eflags = readmemw(ss, (SP + 10) & 0xffff);
SP += 12;
}
loadcs(new_cs);
static int opSET ## condition ## _a16(uint32_t fetchdat) \
{ \
fetch_ea_16(fetchdat); \
+ if (cpu_mod != 3) \
+ SEG_CHECK_READ(cpu_state.ea_seg); \
seteab((cond_ ## condition) ? 1 : 0); \
CLOCK_CYCLES(4); \
return cpu_state.abrt; \
static int opSET ## condition ## _a32(uint32_t fetchdat) \
{ \
fetch_ea_32(fetchdat); \
+ if (cpu_mod != 3) \
+ SEG_CHECK_READ(cpu_state.ea_seg); \
seteab((cond_ ## condition) ? 1 : 0); \
CLOCK_CYCLES(4); \
return cpu_state.abrt; \
switch (rmdat & 0x38) \
{ \
case 0x00: /*ROL b, c*/ \
- while (c > 0) \
- { \
- temp2 = (temp & 0x80) ? 1 : 0; \
- temp = (temp << 1) | temp2; \
- c--; \
- } \
- seteab(temp); if (cpu_state.abrt) return 1; \
- flags &= ~(C_FLAG | V_FLAG); \
- if (temp2) flags |= C_FLAG; \
- if ((flags & C_FLAG) ^ (temp >> 7)) flags |= V_FLAG; \
+ temp = (temp << (c & 7)) | (temp >> (8-(c & 7))); \
+ seteab(temp); if (cpu_state.abrt) return 1; \
+ set_flags_rotate(FLAGS_ROL8, temp); \
CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \
PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \
break; \
case 0x08: /*ROR b,CL*/ \
- while (c > 0) \
- { \
- temp2 = temp & 1; \
- temp >>= 1; \
- if (temp2) temp |= 0x80; \
- c--; \
- } \
- seteab(temp); if (cpu_state.abrt) return 1; \
- flags &= ~(C_FLAG | V_FLAG); \
- if (temp2) flags |= C_FLAG; \
- if ((temp ^ (temp >> 1)) & 0x40) flags |= V_FLAG; \
+ temp = (temp >> (c & 7)) | (temp << (8-(c & 7))); \
+ seteab(temp); if (cpu_state.abrt) return 1; \
+ set_flags_rotate(FLAGS_ROR8, temp); \
CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \
PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \
break; \
case 0x10: /*RCL b,CL*/ \
- temp2 = flags & C_FLAG; \
+ temp2 = cpu_state.flags & C_FLAG; \
if (is486) CLOCK_CYCLES_ALWAYS(c); \
while (c > 0) \
{ \
c--; \
} \
seteab(temp); if (cpu_state.abrt) return 1; \
- flags &= ~(C_FLAG | V_FLAG); \
- if (temp2) flags |= C_FLAG; \
- if ((flags & C_FLAG) ^ (temp >> 7)) flags |= V_FLAG; \
+ cpu_state.flags &= ~(C_FLAG | V_FLAG); \
+ if (temp2) cpu_state.flags |= C_FLAG; \
+ if ((cpu_state.flags & C_FLAG) ^ (temp >> 7)) cpu_state.flags |= V_FLAG; \
CLOCK_CYCLES((cpu_mod == 3) ? 9 : 10); \
PREFETCH_RUN((cpu_mod == 3) ? 9 : 10, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \
break; \
case 0x18: /*RCR b,CL*/ \
- temp2 = flags & C_FLAG; \
+ temp2 = cpu_state.flags & C_FLAG; \
if (is486) CLOCK_CYCLES_ALWAYS(c); \
while (c > 0) \
{ \
c--; \
} \
seteab(temp); if (cpu_state.abrt) return 1; \
- flags &= ~(C_FLAG | V_FLAG); \
- if (temp2) flags |= C_FLAG; \
- if ((temp ^ (temp >> 1)) & 0x40) flags |= V_FLAG; \
+ cpu_state.flags &= ~(C_FLAG | V_FLAG); \
+ if (temp2) cpu_state.flags |= C_FLAG; \
+ if ((temp ^ (temp >> 1)) & 0x40) cpu_state.flags |= V_FLAG; \
CLOCK_CYCLES((cpu_mod == 3) ? 9 : 10); \
PREFETCH_RUN((cpu_mod == 3) ? 9 : 10, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \
break; \
switch (rmdat & 0x38) \
{ \
case 0x00: /*ROL w, c*/ \
- while (c > 0) \
- { \
- temp2 = (temp & 0x8000) ? 1 : 0; \
- temp = (temp << 1) | temp2; \
- c--; \
- } \
- seteaw(temp); if (cpu_state.abrt) return 1; \
- flags &= ~(C_FLAG | V_FLAG); \
- if (temp2) flags |= C_FLAG; \
- if ((flags & C_FLAG) ^ (temp >> 15)) flags |= V_FLAG; \
- CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \
+ temp = (temp << (c & 15)) | (temp >> (16-(c & 15))); \
+ seteaw(temp); if (cpu_state.abrt) return 1; \
+ set_flags_rotate(FLAGS_ROL16, temp); \
+ CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \
PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \
break; \
- case 0x08: /*ROR w, c*/ \
- while (c > 0) \
- { \
- temp2 = temp & 1; \
- temp >>= 1; \
- if (temp2) temp |= 0x8000; \
- c--; \
- } \
- seteaw(temp); if (cpu_state.abrt) return 1; \
- flags &= ~(C_FLAG | V_FLAG); \
- if (temp2) flags |= C_FLAG; \
- if ((temp ^ (temp >> 1)) & 0x4000) flags |= V_FLAG; \
- CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \
+ case 0x08: /*ROR w,CL*/ \
+ temp = (temp >> (c & 15)) | (temp << (16-(c & 15))); \
+ seteaw(temp); if (cpu_state.abrt) return 1; \
+ set_flags_rotate(FLAGS_ROR16, temp); \
+ CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \
PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \
break; \
case 0x10: /*RCL w, c*/ \
- temp2 = flags & C_FLAG; \
+ temp2 = cpu_state.flags & C_FLAG; \
if (is486) CLOCK_CYCLES_ALWAYS(c); \
while (c > 0) \
{ \
c--; \
} \
seteaw(temp); if (cpu_state.abrt) return 1; \
- flags &= ~(C_FLAG | V_FLAG); \
- if (temp2) flags |= C_FLAG; \
- if ((flags & C_FLAG) ^ (temp >> 15)) flags |= V_FLAG; \
+ cpu_state.flags &= ~(C_FLAG | V_FLAG); \
+ if (temp2) cpu_state.flags |= C_FLAG; \
+ if ((cpu_state.flags & C_FLAG) ^ (temp >> 15)) cpu_state.flags |= V_FLAG; \
CLOCK_CYCLES((cpu_mod == 3) ? 9 : 10); \
PREFETCH_RUN((cpu_mod == 3) ? 9 : 10, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \
break; \
case 0x18: /*RCR w, c*/ \
- temp2 = flags & C_FLAG; \
+ temp2 = cpu_state.flags & C_FLAG; \
if (is486) CLOCK_CYCLES_ALWAYS(c); \
while (c > 0) \
{ \
c--; \
} \
seteaw(temp); if (cpu_state.abrt) return 1; \
- flags &= ~(C_FLAG | V_FLAG); \
- if (temp2) flags |= C_FLAG; \
- if ((temp ^ (temp >> 1)) & 0x4000) flags |= V_FLAG; \
+ cpu_state.flags &= ~(C_FLAG | V_FLAG); \
+ if (temp2) cpu_state.flags |= C_FLAG; \
+ if ((temp ^ (temp >> 1)) & 0x4000) cpu_state.flags |= V_FLAG; \
CLOCK_CYCLES((cpu_mod == 3) ? 9 : 10); \
PREFETCH_RUN((cpu_mod == 3) ? 9 : 10, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \
break; \
switch (rmdat & 0x38) \
{ \
case 0x00: /*ROL l, c*/ \
- while (c > 0) \
- { \
- temp2 = (temp & 0x80000000) ? 1 : 0; \
- temp = (temp << 1) | temp2; \
- c--; \
- } \
- seteal(temp); if (cpu_state.abrt) return 1; \
- flags &= ~(C_FLAG | V_FLAG); \
- if (temp2) flags |= C_FLAG; \
- if ((flags & C_FLAG) ^ (temp >> 31)) flags |= V_FLAG; \
- CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \
- PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, ea32); \
+ temp = (temp << c) | (temp >> (32-c)); \
+ seteal(temp); if (cpu_state.abrt) return 1; \
+ set_flags_rotate(FLAGS_ROL32, temp); \
+ CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \
+ PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \
break; \
- case 0x08: /*ROR l, c*/ \
- while (c > 0) \
- { \
- temp2 = temp & 1; \
- temp >>= 1; \
- if (temp2) temp |= 0x80000000; \
- c--; \
- } \
- seteal(temp); if (cpu_state.abrt) return 1; \
- flags &= ~(C_FLAG | V_FLAG); \
- if (temp2) flags |= C_FLAG; \
- if ((temp ^ (temp >> 1)) & 0x40000000) flags |= V_FLAG; \
- CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \
- PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, ea32); \
+ case 0x08: /*ROR l,CL*/ \
+ temp = (temp >> c) | (temp << (32-c)); \
+ seteal(temp); if (cpu_state.abrt) return 1; \
+ set_flags_rotate(FLAGS_ROR32, temp); \
+ CLOCK_CYCLES((cpu_mod == 3) ? 3 : 7); \
+ PREFETCH_RUN((cpu_mod == 3) ? 3 : 7, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, ea32); \
break; \
case 0x10: /*RCL l, c*/ \
temp2 = CF_SET(); \
c--; \
} \
seteal(temp); if (cpu_state.abrt) return 1; \
- flags &= ~(C_FLAG | V_FLAG); \
- if (temp2) flags |= C_FLAG; \
- if ((flags & C_FLAG) ^ (temp >> 31)) flags |= V_FLAG; \
+ cpu_state.flags &= ~(C_FLAG | V_FLAG); \
+ if (temp2) cpu_state.flags |= C_FLAG; \
+ if ((cpu_state.flags & C_FLAG) ^ (temp >> 31)) cpu_state.flags |= V_FLAG; \
CLOCK_CYCLES((cpu_mod == 3) ? 9 : 10); \
PREFETCH_RUN((cpu_mod == 3) ? 9 : 10, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, ea32); \
break; \
case 0x18: /*RCR l, c*/ \
- temp2 = flags & C_FLAG; \
+ temp2 = cpu_state.flags & C_FLAG; \
if (is486) CLOCK_CYCLES_ALWAYS(c); \
while (c > 0) \
{ \
c--; \
} \
seteal(temp); if (cpu_state.abrt) return 1; \
- flags &= ~(C_FLAG | V_FLAG); \
- if (temp2) flags |= C_FLAG; \
- if ((temp ^ (temp >> 1)) & 0x40000000) flags |= V_FLAG; \
+ cpu_state.flags &= ~(C_FLAG | V_FLAG); \
+ if (temp2) cpu_state.flags |= C_FLAG; \
+ if ((temp ^ (temp >> 1)) & 0x40000000) cpu_state.flags |= V_FLAG; \
CLOCK_CYCLES((cpu_mod == 3) ? 9 : 10); \
PREFETCH_RUN((cpu_mod == 3) ? 9 : 10, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, ea32); \
break; \
uint8_t temp, temp2;
fetch_ea_16(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
c = readmemb(cs, cpu_state.pc) & 31; cpu_state.pc++;
PREFETCH_PREFIX();
temp = geteab(); if (cpu_state.abrt) return 1;
uint8_t temp, temp2;
fetch_ea_32(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
c = readmemb(cs, cpu_state.pc) & 31; cpu_state.pc++;
PREFETCH_PREFIX();
temp = geteab(); if (cpu_state.abrt) return 1;
uint16_t temp, temp2;
fetch_ea_16(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
c = readmemb(cs, cpu_state.pc) & 31; cpu_state.pc++;
PREFETCH_PREFIX();
temp = geteaw(); if (cpu_state.abrt) return 1;
uint16_t temp, temp2;
fetch_ea_32(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
c = readmemb(cs, cpu_state.pc) & 31; cpu_state.pc++;
PREFETCH_PREFIX();
temp = geteaw(); if (cpu_state.abrt) return 1;
uint32_t temp, temp2;
fetch_ea_16(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
c = readmemb(cs, cpu_state.pc) & 31; cpu_state.pc++;
PREFETCH_PREFIX();
temp = geteal(); if (cpu_state.abrt) return 1;
uint32_t temp, temp2;
fetch_ea_32(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
c = readmemb(cs, cpu_state.pc) & 31; cpu_state.pc++;
PREFETCH_PREFIX();
temp = geteal(); if (cpu_state.abrt) return 1;
uint8_t temp, temp2;
fetch_ea_16(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = geteab(); if (cpu_state.abrt) return 1;
OP_SHIFT_b(c, 0);
return 0;
uint8_t temp, temp2;
fetch_ea_32(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = geteab(); if (cpu_state.abrt) return 1;
OP_SHIFT_b(c, 1);
return 0;
uint16_t temp, temp2;
fetch_ea_16(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = geteaw(); if (cpu_state.abrt) return 1;
OP_SHIFT_w(c, 0);
return 0;
uint16_t temp, temp2;
fetch_ea_32(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = geteaw(); if (cpu_state.abrt) return 1;
OP_SHIFT_w(c, 1);
return 0;
uint32_t temp, temp2;
fetch_ea_16(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = geteal(); if (cpu_state.abrt) return 1;
OP_SHIFT_l(c, 0);
return 0;
uint32_t temp, temp2;
fetch_ea_32(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = geteal(); if (cpu_state.abrt) return 1;
OP_SHIFT_l(c, 1);
return 0;
uint8_t temp, temp2;
fetch_ea_16(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
c = CL & 31;
temp = geteab(); if (cpu_state.abrt) return 1;
OP_SHIFT_b(c, 0);
uint8_t temp, temp2;
fetch_ea_32(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
c = CL & 31;
temp = geteab(); if (cpu_state.abrt) return 1;
OP_SHIFT_b(c, 1);
uint16_t temp, temp2;
fetch_ea_16(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
c = CL & 31;
temp = geteaw(); if (cpu_state.abrt) return 1;
OP_SHIFT_w(c, 0);
uint16_t temp, temp2;
fetch_ea_32(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
c = CL & 31;
temp = geteaw(); if (cpu_state.abrt) return 1;
OP_SHIFT_w(c, 1);
uint32_t temp, temp2;
fetch_ea_16(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
c = CL & 31;
temp = geteal(); if (cpu_state.abrt) return 1;
OP_SHIFT_l(c, 0);
uint32_t temp, temp2;
fetch_ea_32(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
c = CL & 31;
temp = geteal(); if (cpu_state.abrt) return 1;
OP_SHIFT_l(c, 1);
seteaw(tempw); if (cpu_state.abrt) return 1; \
setznp16(tempw); \
flags_rebuild(); \
- if (tempc) flags |= C_FLAG; \
+ if (tempc) cpu_state.flags |= C_FLAG; \
}
#define SHLD_l() \
seteal(templ); if (cpu_state.abrt) return 1; \
setznp32(templ); \
flags_rebuild(); \
- if (tempc) flags |= C_FLAG; \
+ if (tempc) cpu_state.flags |= C_FLAG; \
}
seteaw(tempw); if (cpu_state.abrt) return 1; \
setznp16(tempw); \
flags_rebuild(); \
- if (tempc) flags |= C_FLAG; \
+ if (tempc) cpu_state.flags |= C_FLAG; \
}
#define SHRD_l() \
seteal(templ); if (cpu_state.abrt) return 1; \
setznp32(templ); \
flags_rebuild(); \
- if (tempc) flags |= C_FLAG; \
+ if (tempc) cpu_state.flags |= C_FLAG; \
}
#define opSHxD(operation) \
int count; \
\
fetch_ea_16(fetchdat); \
+ if (cpu_mod != 3) \
+ SEG_CHECK_WRITE(cpu_state.ea_seg); \
count = getbyte() & 31; \
operation(); \
\
int count; \
\
fetch_ea_16(fetchdat); \
+ if (cpu_mod != 3) \
+ SEG_CHECK_WRITE(cpu_state.ea_seg); \
count = CL & 31; \
operation(); \
\
int count; \
\
fetch_ea_32(fetchdat); \
+ if (cpu_mod != 3) \
+ SEG_CHECK_WRITE(cpu_state.ea_seg); \
count = getbyte() & 31; \
operation(); \
\
int count; \
\
fetch_ea_32(fetchdat); \
+ if (cpu_mod != 3) \
+ SEG_CHECK_WRITE(cpu_state.ea_seg); \
count = CL & 31; \
operation(); \
\
temp = POP_W(); if (cpu_state.abrt) return 1;
fetch_ea_16(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
seteaw(temp);
if (cpu_state.abrt)
{
temp = POP_W(); if (cpu_state.abrt) return 1;
fetch_ea_32(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
seteaw(temp);
if (cpu_state.abrt)
{
temp = POP_L(); if (cpu_state.abrt) return 1;
fetch_ea_16(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
seteal(temp);
if (cpu_state.abrt)
{
temp = POP_L(); if (cpu_state.abrt) return 1;
fetch_ea_32(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
seteal(temp);
if (cpu_state.abrt)
{
PUSH_SEG_OPS(GS);
PUSH_SEG_OPS(SS);
-POP_SEG_OPS(DS, &_ds);
-POP_SEG_OPS(ES, &_es);
-POP_SEG_OPS(FS, &_fs);
-POP_SEG_OPS(GS, &_gs);
+POP_SEG_OPS(DS, &cpu_state.seg_ds);
+POP_SEG_OPS(ES, &cpu_state.seg_es);
+POP_SEG_OPS(FS, &cpu_state.seg_fs);
+POP_SEG_OPS(GS, &cpu_state.seg_gs);
static int opPOP_SS_w(uint32_t fetchdat)
uint16_t temp_seg;
uint32_t temp_esp = ESP;
temp_seg = POP_W(); if (cpu_state.abrt) return 1;
- loadseg(temp_seg, &_ss); if (cpu_state.abrt) { ESP = temp_esp; return 1; }
+ loadseg(temp_seg, &cpu_state.seg_ss); if (cpu_state.abrt) { ESP = temp_esp; return 1; }
CLOCK_CYCLES(is486 ? 3 : 7);
PREFETCH_RUN(is486 ? 3 : 7, 1, -1, 0,0,1,0, 0);
cpu_state.oldpc = cpu_state.pc;
cpu_state.op32 = use32;
cpu_state.ssegs = 0;
- cpu_state.ea_seg = &_ds;
+ cpu_state.ea_seg = &cpu_state.seg_ds;
fetchdat = fastreadl(cs + cpu_state.pc);
cpu_state.pc++;
if (cpu_state.abrt) return 1;
uint32_t temp_seg;
uint32_t temp_esp = ESP;
temp_seg = POP_L(); if (cpu_state.abrt) return 1;
- loadseg(temp_seg & 0xffff, &_ss); if (cpu_state.abrt) { ESP = temp_esp; return 1; }
+ loadseg(temp_seg & 0xffff, &cpu_state.seg_ss); if (cpu_state.abrt) { ESP = temp_esp; return 1; }
CLOCK_CYCLES(is486 ? 3 : 7);
PREFETCH_RUN(is486 ? 3 : 7, 1, -1, 0,0,1,0, 0);
cpu_state.oldpc = cpu_state.pc;
cpu_state.op32 = use32;
cpu_state.ssegs = 0;
- cpu_state.ea_seg = &_ds;
+ cpu_state.ea_seg = &cpu_state.seg_ds;
fetchdat = fastreadl(cs + cpu_state.pc);
cpu_state.pc++;
if (cpu_state.abrt) return 1;
static int opMOVSB_a16(uint32_t fetchdat)
{
- uint8_t temp = readmemb(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) return 1;
+ uint8_t temp;
+
+ SEG_CHECK_READ(cpu_state.ea_seg);
+ SEG_CHECK_WRITE(&cpu_state.seg_es);
+ temp = readmemb(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) return 1;
writememb(es, DI, temp); if (cpu_state.abrt) return 1;
- if (flags & D_FLAG) { DI--; SI--; }
- else { DI++; SI++; }
+ if (cpu_state.flags & D_FLAG) { DI--; SI--; }
+ else { DI++; SI++; }
CLOCK_CYCLES(7);
PREFETCH_RUN(7, 1, -1, 1,0,1,0, 0);
return 0;
}
static int opMOVSB_a32(uint32_t fetchdat)
{
- uint8_t temp = readmemb(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) return 1;
+ uint8_t temp;
+
+ SEG_CHECK_READ(cpu_state.ea_seg);
+ SEG_CHECK_WRITE(&cpu_state.seg_es);
+ temp = readmemb(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) return 1;
writememb(es, EDI, temp); if (cpu_state.abrt) return 1;
- if (flags & D_FLAG) { EDI--; ESI--; }
- else { EDI++; ESI++; }
+ if (cpu_state.flags & D_FLAG) { EDI--; ESI--; }
+ else { EDI++; ESI++; }
CLOCK_CYCLES(7);
PREFETCH_RUN(7, 1, -1, 1,0,1,0, 1);
return 0;
static int opMOVSW_a16(uint32_t fetchdat)
{
- uint16_t temp = readmemw(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) return 1;
+ uint16_t temp;
+
+ SEG_CHECK_READ(cpu_state.ea_seg);
+ SEG_CHECK_WRITE(&cpu_state.seg_es);
+ temp = readmemw(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) return 1;
writememw(es, DI, temp); if (cpu_state.abrt) return 1;
- if (flags & D_FLAG) { DI -= 2; SI -= 2; }
- else { DI += 2; SI += 2; }
+ if (cpu_state.flags & D_FLAG) { DI -= 2; SI -= 2; }
+ else { DI += 2; SI += 2; }
CLOCK_CYCLES(7);
PREFETCH_RUN(7, 1, -1, 1,0,1,0, 0);
return 0;
}
static int opMOVSW_a32(uint32_t fetchdat)
{
- uint16_t temp = readmemw(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) return 1;
+ uint16_t temp;
+
+ SEG_CHECK_READ(cpu_state.ea_seg);
+ SEG_CHECK_WRITE(&cpu_state.seg_es);
+ temp = readmemw(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) return 1;
writememw(es, EDI, temp); if (cpu_state.abrt) return 1;
- if (flags & D_FLAG) { EDI -= 2; ESI -= 2; }
- else { EDI += 2; ESI += 2; }
+ if (cpu_state.flags & D_FLAG) { EDI -= 2; ESI -= 2; }
+ else { EDI += 2; ESI += 2; }
CLOCK_CYCLES(7);
PREFETCH_RUN(7, 1, -1, 1,0,1,0, 1);
return 0;
static int opMOVSL_a16(uint32_t fetchdat)
{
- uint32_t temp = readmeml(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) return 1;
+ uint32_t temp;
+
+ SEG_CHECK_READ(cpu_state.ea_seg);
+ SEG_CHECK_WRITE(&cpu_state.seg_es);
+ temp = readmeml(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) return 1;
writememl(es, DI, temp); if (cpu_state.abrt) return 1;
- if (flags & D_FLAG) { DI -= 4; SI -= 4; }
- else { DI += 4; SI += 4; }
+ if (cpu_state.flags & D_FLAG) { DI -= 4; SI -= 4; }
+ else { DI += 4; SI += 4; }
CLOCK_CYCLES(7);
PREFETCH_RUN(7, 1, -1, 0,1,0,1, 0);
return 0;
}
static int opMOVSL_a32(uint32_t fetchdat)
{
- uint32_t temp = readmeml(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) return 1;
+ uint32_t temp;
+
+ SEG_CHECK_READ(cpu_state.ea_seg);
+ SEG_CHECK_WRITE(&cpu_state.seg_es);
+ temp = readmeml(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) return 1;
writememl(es, EDI, temp); if (cpu_state.abrt) return 1;
- if (flags & D_FLAG) { EDI -= 4; ESI -= 4; }
- else { EDI += 4; ESI += 4; }
+ if (cpu_state.flags & D_FLAG) { EDI -= 4; ESI -= 4; }
+ else { EDI += 4; ESI += 4; }
CLOCK_CYCLES(7);
PREFETCH_RUN(7, 1, -1, 0,1,0,1, 1);
return 0;
static int opCMPSB_a16(uint32_t fetchdat)
{
- uint8_t src = readmemb(cpu_state.ea_seg->base, SI);
- uint8_t dst = readmemb(es, DI); if (cpu_state.abrt) return 1;
+ uint8_t src, dst;
+
+ SEG_CHECK_READ(cpu_state.ea_seg);
+ SEG_CHECK_READ(&cpu_state.seg_es);
+ src = readmemb(cpu_state.ea_seg->base, SI);
+ dst = readmemb(es, DI); if (cpu_state.abrt) return 1;
setsub8(src, dst);
- if (flags & D_FLAG) { DI--; SI--; }
- else { DI++; SI++; }
+ if (cpu_state.flags & D_FLAG) { DI--; SI--; }
+ else { DI++; SI++; }
CLOCK_CYCLES((is486) ? 8 : 10);
PREFETCH_RUN((is486) ? 8 : 10, 1, -1, 2,0,0,0, 0);
return 0;
}
static int opCMPSB_a32(uint32_t fetchdat)
{
- uint8_t src = readmemb(cpu_state.ea_seg->base, ESI);
- uint8_t dst = readmemb(es, EDI); if (cpu_state.abrt) return 1;
+ uint8_t src, dst;
+
+ SEG_CHECK_READ(cpu_state.ea_seg);
+ SEG_CHECK_READ(&cpu_state.seg_es);
+ src = readmemb(cpu_state.ea_seg->base, ESI);
+ dst = readmemb(es, EDI); if (cpu_state.abrt) return 1;
setsub8(src, dst);
- if (flags & D_FLAG) { EDI--; ESI--; }
- else { EDI++; ESI++; }
+ if (cpu_state.flags & D_FLAG) { EDI--; ESI--; }
+ else { EDI++; ESI++; }
CLOCK_CYCLES((is486) ? 8 : 10);
PREFETCH_RUN((is486) ? 8 : 10, 1, -1, 2,0,0,0, 1);
return 0;
static int opCMPSW_a16(uint32_t fetchdat)
{
- uint16_t src = readmemw(cpu_state.ea_seg->base, SI);
- uint16_t dst = readmemw(es, DI); if (cpu_state.abrt) return 1;
+ uint16_t src, dst;
+
+ SEG_CHECK_READ(cpu_state.ea_seg);
+ SEG_CHECK_READ(&cpu_state.seg_es);
+ src = readmemw(cpu_state.ea_seg->base, SI);
+ dst = readmemw(es, DI); if (cpu_state.abrt) return 1;
setsub16(src, dst);
- if (flags & D_FLAG) { DI -= 2; SI -= 2; }
- else { DI += 2; SI += 2; }
+ if (cpu_state.flags & D_FLAG) { DI -= 2; SI -= 2; }
+ else { DI += 2; SI += 2; }
CLOCK_CYCLES((is486) ? 8 : 10);
PREFETCH_RUN((is486) ? 8 : 10, 1, -1, 2,0,0,0, 0);
return 0;
}
static int opCMPSW_a32(uint32_t fetchdat)
{
- uint16_t src = readmemw(cpu_state.ea_seg->base, ESI);
- uint16_t dst = readmemw(es, EDI); if (cpu_state.abrt) return 1;
+ uint16_t src, dst;
+
+ SEG_CHECK_READ(cpu_state.ea_seg);
+ SEG_CHECK_READ(&cpu_state.seg_es);
+ src = readmemw(cpu_state.ea_seg->base, ESI);
+ dst = readmemw(es, EDI); if (cpu_state.abrt) return 1;
setsub16(src, dst);
- if (flags & D_FLAG) { EDI -= 2; ESI -= 2; }
- else { EDI += 2; ESI += 2; }
+ if (cpu_state.flags & D_FLAG) { EDI -= 2; ESI -= 2; }
+ else { EDI += 2; ESI += 2; }
CLOCK_CYCLES((is486) ? 8 : 10);
PREFETCH_RUN((is486) ? 8 : 10, 1, -1, 2,0,0,0, 1);
return 0;
static int opCMPSL_a16(uint32_t fetchdat)
{
- uint32_t src = readmeml(cpu_state.ea_seg->base, SI);
- uint32_t dst = readmeml(es, DI); if (cpu_state.abrt) return 1;
+ uint32_t src, dst;
+
+ SEG_CHECK_READ(cpu_state.ea_seg);
+ SEG_CHECK_READ(&cpu_state.seg_es);
+ src = readmeml(cpu_state.ea_seg->base, SI);
+ dst = readmeml(es, DI); if (cpu_state.abrt) return 1;
setsub32(src, dst);
- if (flags & D_FLAG) { DI -= 4; SI -= 4; }
- else { DI += 4; SI += 4; }
+ if (cpu_state.flags & D_FLAG) { DI -= 4; SI -= 4; }
+ else { DI += 4; SI += 4; }
CLOCK_CYCLES((is486) ? 8 : 10);
PREFETCH_RUN((is486) ? 8 : 10, 1, -1, 0,2,0,0, 0);
return 0;
}
static int opCMPSL_a32(uint32_t fetchdat)
{
- uint32_t src = readmeml(cpu_state.ea_seg->base, ESI);
- uint32_t dst = readmeml(es, EDI); if (cpu_state.abrt) return 1;
+ uint32_t src, dst;
+
+ SEG_CHECK_READ(cpu_state.ea_seg);
+ SEG_CHECK_READ(&cpu_state.seg_es);
+ src = readmeml(cpu_state.ea_seg->base, ESI);
+ dst = readmeml(es, EDI); if (cpu_state.abrt) return 1;
setsub32(src, dst);
- if (flags & D_FLAG) { EDI -= 4; ESI -= 4; }
- else { EDI += 4; ESI += 4; }
+ if (cpu_state.flags & D_FLAG) { EDI -= 4; ESI -= 4; }
+ else { EDI += 4; ESI += 4; }
CLOCK_CYCLES((is486) ? 8 : 10);
PREFETCH_RUN((is486) ? 8 : 10, 1, -1, 0,2,0,0, 1);
return 0;
static int opSTOSB_a16(uint32_t fetchdat)
{
+ SEG_CHECK_WRITE(&cpu_state.seg_es);
writememb(es, DI, AL); if (cpu_state.abrt) return 1;
- if (flags & D_FLAG) DI--;
- else DI++;
+ if (cpu_state.flags & D_FLAG) DI--;
+ else DI++;
CLOCK_CYCLES(4);
PREFETCH_RUN(4, 1, -1, 0,0,1,0, 0);
return 0;
}
static int opSTOSB_a32(uint32_t fetchdat)
{
+ SEG_CHECK_WRITE(&cpu_state.seg_es);
writememb(es, EDI, AL); if (cpu_state.abrt) return 1;
- if (flags & D_FLAG) EDI--;
- else EDI++;
+ if (cpu_state.flags & D_FLAG) EDI--;
+ else EDI++;
CLOCK_CYCLES(4);
PREFETCH_RUN(4, 1, -1, 0,0,1,0, 1);
return 0;
static int opSTOSW_a16(uint32_t fetchdat)
{
+ SEG_CHECK_WRITE(&cpu_state.seg_es);
writememw(es, DI, AX); if (cpu_state.abrt) return 1;
- if (flags & D_FLAG) DI -= 2;
- else DI += 2;
+ if (cpu_state.flags & D_FLAG) DI -= 2;
+ else DI += 2;
CLOCK_CYCLES(4);
PREFETCH_RUN(4, 1, -1, 0,0,1,0, 0);
return 0;
}
static int opSTOSW_a32(uint32_t fetchdat)
{
+ SEG_CHECK_WRITE(&cpu_state.seg_es);
writememw(es, EDI, AX); if (cpu_state.abrt) return 1;
- if (flags & D_FLAG) EDI -= 2;
- else EDI += 2;
+ if (cpu_state.flags & D_FLAG) EDI -= 2;
+ else EDI += 2;
CLOCK_CYCLES(4);
PREFETCH_RUN(4, 1, -1, 0,0,1,0, 1);
return 0;
static int opSTOSL_a16(uint32_t fetchdat)
{
+ SEG_CHECK_WRITE(&cpu_state.seg_es);
writememl(es, DI, EAX); if (cpu_state.abrt) return 1;
- if (flags & D_FLAG) DI -= 4;
- else DI += 4;
+ if (cpu_state.flags & D_FLAG) DI -= 4;
+ else DI += 4;
CLOCK_CYCLES(4);
PREFETCH_RUN(4, 1, -1, 0,0,0,1, 0);
return 0;
}
static int opSTOSL_a32(uint32_t fetchdat)
{
+ SEG_CHECK_WRITE(&cpu_state.seg_es);
writememl(es, EDI, EAX); if (cpu_state.abrt) return 1;
- if (flags & D_FLAG) EDI -= 4;
- else EDI += 4;
+ if (cpu_state.flags & D_FLAG) EDI -= 4;
+ else EDI += 4;
CLOCK_CYCLES(4);
PREFETCH_RUN(4, 1, -1, 0,0,0,1, 1);
return 0;
static int opLODSB_a16(uint32_t fetchdat)
{
- uint8_t temp = readmemb(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) return 1;
+ uint8_t temp;
+
+ SEG_CHECK_READ(cpu_state.ea_seg);
+ temp = readmemb(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) return 1;
AL = temp;
- if (flags & D_FLAG) SI--;
- else SI++;
+ if (cpu_state.flags & D_FLAG) SI--;
+ else SI++;
CLOCK_CYCLES(5);
PREFETCH_RUN(5, 1, -1, 1,0,0,0, 0);
return 0;
}
static int opLODSB_a32(uint32_t fetchdat)
{
- uint8_t temp = readmemb(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) return 1;
+ uint8_t temp;
+
+ SEG_CHECK_READ(cpu_state.ea_seg);
+ temp = readmemb(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) return 1;
AL = temp;
- if (flags & D_FLAG) ESI--;
- else ESI++;
+ if (cpu_state.flags & D_FLAG) ESI--;
+ else ESI++;
CLOCK_CYCLES(5);
PREFETCH_RUN(5, 1, -1, 1,0,0,0, 1);
return 0;
static int opLODSW_a16(uint32_t fetchdat)
{
- uint16_t temp = readmemw(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) return 1;
+ uint16_t temp;
+
+ SEG_CHECK_READ(cpu_state.ea_seg);
+ temp = readmemw(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) return 1;
AX = temp;
- if (flags & D_FLAG) SI -= 2;
- else SI += 2;
+ if (cpu_state.flags & D_FLAG) SI -= 2;
+ else SI += 2;
CLOCK_CYCLES(5);
PREFETCH_RUN(5, 1, -1, 1,0,0,0, 0);
return 0;
}
static int opLODSW_a32(uint32_t fetchdat)
{
- uint16_t temp = readmemw(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) return 1;
+ uint16_t temp;
+
+ SEG_CHECK_READ(cpu_state.ea_seg);
+ temp = readmemw(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) return 1;
AX = temp;
- if (flags & D_FLAG) ESI -= 2;
- else ESI += 2;
+ if (cpu_state.flags & D_FLAG) ESI -= 2;
+ else ESI += 2;
CLOCK_CYCLES(5);
PREFETCH_RUN(5, 1, -1, 1,0,0,0, 1);
return 0;
static int opLODSL_a16(uint32_t fetchdat)
{
- uint32_t temp = readmeml(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) return 1;
+ uint32_t temp;
+
+ SEG_CHECK_READ(cpu_state.ea_seg);
+ temp = readmeml(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) return 1;
EAX = temp;
- if (flags & D_FLAG) SI -= 4;
- else SI += 4;
+ if (cpu_state.flags & D_FLAG) SI -= 4;
+ else SI += 4;
CLOCK_CYCLES(5);
PREFETCH_RUN(5, 1, -1, 0,1,0,0, 0);
return 0;
}
static int opLODSL_a32(uint32_t fetchdat)
{
- uint32_t temp = readmeml(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) return 1;
+ uint32_t temp;
+
+ SEG_CHECK_READ(cpu_state.ea_seg);
+ temp = readmeml(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) return 1;
EAX = temp;
- if (flags & D_FLAG) ESI -= 4;
- else ESI += 4;
+ if (cpu_state.flags & D_FLAG) ESI -= 4;
+ else ESI += 4;
CLOCK_CYCLES(5);
PREFETCH_RUN(5, 1, -1, 0,1,0,0, 1);
return 0;
static int opSCASB_a16(uint32_t fetchdat)
{
- uint8_t temp = readmemb(es, DI); if (cpu_state.abrt) return 1;
+ uint8_t temp;
+
+ SEG_CHECK_READ(&cpu_state.seg_es);
+ temp = readmemb(es, DI); if (cpu_state.abrt) return 1;
setsub8(AL, temp);
- if (flags & D_FLAG) DI--;
- else DI++;
+ if (cpu_state.flags & D_FLAG) DI--;
+ else DI++;
CLOCK_CYCLES(7);
PREFETCH_RUN(7, 1, -1, 1,0,0,0, 0);
return 0;
}
static int opSCASB_a32(uint32_t fetchdat)
{
- uint8_t temp = readmemb(es, EDI); if (cpu_state.abrt) return 1;
+ uint8_t temp;
+
+ SEG_CHECK_READ(&cpu_state.seg_es);
+ temp = readmemb(es, EDI); if (cpu_state.abrt) return 1;
setsub8(AL, temp);
- if (flags & D_FLAG) EDI--;
- else EDI++;
+ if (cpu_state.flags & D_FLAG) EDI--;
+ else EDI++;
CLOCK_CYCLES(7);
PREFETCH_RUN(7, 1, -1, 1,0,0,0, 1);
return 0;
static int opSCASW_a16(uint32_t fetchdat)
{
- uint16_t temp = readmemw(es, DI); if (cpu_state.abrt) return 1;
+ uint16_t temp;
+
+ SEG_CHECK_READ(&cpu_state.seg_es);
+ temp = readmemw(es, DI); if (cpu_state.abrt) return 1;
setsub16(AX, temp);
- if (flags & D_FLAG) DI -= 2;
- else DI += 2;
+ if (cpu_state.flags & D_FLAG) DI -= 2;
+ else DI += 2;
CLOCK_CYCLES(7);
PREFETCH_RUN(7, 1, -1, 1,0,0,0, 0);
return 0;
}
static int opSCASW_a32(uint32_t fetchdat)
{
- uint16_t temp = readmemw(es, EDI); if (cpu_state.abrt) return 1;
+ uint16_t temp;
+
+ SEG_CHECK_READ(&cpu_state.seg_es);
+ temp = readmemw(es, EDI); if (cpu_state.abrt) return 1;
setsub16(AX, temp);
- if (flags & D_FLAG) EDI -= 2;
- else EDI += 2;
+ if (cpu_state.flags & D_FLAG) EDI -= 2;
+ else EDI += 2;
CLOCK_CYCLES(7);
PREFETCH_RUN(7, 1, -1, 1,0,0,0, 1);
return 0;
static int opSCASL_a16(uint32_t fetchdat)
{
- uint32_t temp = readmeml(es, DI); if (cpu_state.abrt) return 1;
+ uint32_t temp;
+
+ SEG_CHECK_READ(&cpu_state.seg_es);
+ temp = readmeml(es, DI); if (cpu_state.abrt) return 1;
setsub32(EAX, temp);
- if (flags & D_FLAG) DI -= 4;
- else DI += 4;
+ if (cpu_state.flags & D_FLAG) DI -= 4;
+ else DI += 4;
CLOCK_CYCLES(7);
PREFETCH_RUN(7, 1, -1, 0,1,0,0, 0);
return 0;
}
static int opSCASL_a32(uint32_t fetchdat)
{
- uint32_t temp = readmeml(es, EDI); if (cpu_state.abrt) return 1;
+ uint32_t temp;
+
+ SEG_CHECK_READ(&cpu_state.seg_es);
+ temp = readmeml(es, EDI); if (cpu_state.abrt) return 1;
setsub32(EAX, temp);
- if (flags & D_FLAG) EDI -= 4;
- else EDI += 4;
+ if (cpu_state.flags & D_FLAG) EDI -= 4;
+ else EDI += 4;
CLOCK_CYCLES(7);
PREFETCH_RUN(7, 1, -1, 0,1,0,0, 1);
return 0;
static int opINSB_a16(uint32_t fetchdat)
{
uint8_t temp;
+
+ SEG_CHECK_WRITE(&cpu_state.seg_es);
check_io_perm(DX);
temp = inb(DX);
writememb(es, DI, temp); if (cpu_state.abrt) return 1;
- if (flags & D_FLAG) DI--;
- else DI++;
+ if (cpu_state.flags & D_FLAG) DI--;
+ else DI++;
CLOCK_CYCLES(15);
PREFETCH_RUN(15, 1, -1, 1,0,1,0, 0);
return 0;
static int opINSB_a32(uint32_t fetchdat)
{
uint8_t temp;
+
+ SEG_CHECK_WRITE(&cpu_state.seg_es);
check_io_perm(DX);
temp = inb(DX);
writememb(es, EDI, temp); if (cpu_state.abrt) return 1;
- if (flags & D_FLAG) EDI--;
- else EDI++;
+ if (cpu_state.flags & D_FLAG) EDI--;
+ else EDI++;
CLOCK_CYCLES(15);
PREFETCH_RUN(15, 1, -1, 1,0,1,0, 1);
return 0;
static int opINSW_a16(uint32_t fetchdat)
{
uint16_t temp;
+
+ SEG_CHECK_WRITE(&cpu_state.seg_es);
check_io_perm(DX);
check_io_perm(DX + 1);
temp = inw(DX);
writememw(es, DI, temp); if (cpu_state.abrt) return 1;
- if (flags & D_FLAG) DI -= 2;
- else DI += 2;
+ if (cpu_state.flags & D_FLAG) DI -= 2;
+ else DI += 2;
CLOCK_CYCLES(15);
PREFETCH_RUN(15, 1, -1, 1,0,1,0, 0);
return 0;
static int opINSW_a32(uint32_t fetchdat)
{
uint16_t temp;
+
+ SEG_CHECK_WRITE(&cpu_state.seg_es);
check_io_perm(DX);
check_io_perm(DX + 1);
temp = inw(DX);
writememw(es, EDI, temp); if (cpu_state.abrt) return 1;
- if (flags & D_FLAG) EDI -= 2;
- else EDI += 2;
+ if (cpu_state.flags & D_FLAG) EDI -= 2;
+ else EDI += 2;
CLOCK_CYCLES(15);
PREFETCH_RUN(15, 1, -1, 1,0,1,0, 1);
return 0;
static int opINSL_a16(uint32_t fetchdat)
{
uint32_t temp;
+
+ SEG_CHECK_WRITE(&cpu_state.seg_es);
check_io_perm(DX);
check_io_perm(DX + 1);
check_io_perm(DX + 2);
check_io_perm(DX + 3);
temp = inl(DX);
writememl(es, DI, temp); if (cpu_state.abrt) return 1;
- if (flags & D_FLAG) DI -= 4;
- else DI += 4;
+ if (cpu_state.flags & D_FLAG) DI -= 4;
+ else DI += 4;
CLOCK_CYCLES(15);
PREFETCH_RUN(15, 1, -1, 0,1,0,1, 0);
return 0;
static int opINSL_a32(uint32_t fetchdat)
{
uint32_t temp;
+
+ SEG_CHECK_WRITE(&cpu_state.seg_es);
check_io_perm(DX);
check_io_perm(DX + 1);
check_io_perm(DX + 2);
check_io_perm(DX + 3);
temp = inl(DX);
writememl(es, EDI, temp); if (cpu_state.abrt) return 1;
- if (flags & D_FLAG) EDI -= 4;
- else EDI += 4;
+ if (cpu_state.flags & D_FLAG) EDI -= 4;
+ else EDI += 4;
CLOCK_CYCLES(15);
PREFETCH_RUN(15, 1, -1, 0,1,0,1, 1);
return 0;
static int opOUTSB_a16(uint32_t fetchdat)
{
- uint8_t temp = readmemb(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) return 1;
+ uint8_t temp;
+
+ SEG_CHECK_READ(cpu_state.ea_seg);
+ temp = readmemb(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) return 1;
check_io_perm(DX);
- if (flags & D_FLAG) SI--;
- else SI++;
+ if (cpu_state.flags & D_FLAG) SI--;
+ else SI++;
outb(DX, temp);
CLOCK_CYCLES(14);
PREFETCH_RUN(14, 1, -1, 1,0,1,0, 0);
}
static int opOUTSB_a32(uint32_t fetchdat)
{
- uint8_t temp = readmemb(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) return 1;
+ uint8_t temp;
+
+ SEG_CHECK_READ(cpu_state.ea_seg);
+ temp = readmemb(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) return 1;
check_io_perm(DX);
- if (flags & D_FLAG) ESI--;
- else ESI++;
+ if (cpu_state.flags & D_FLAG) ESI--;
+ else ESI++;
outb(DX, temp);
CLOCK_CYCLES(14);
PREFETCH_RUN(14, 1, -1, 1,0,1,0, 1);
static int opOUTSW_a16(uint32_t fetchdat)
{
- uint16_t temp = readmemw(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) return 1;
+ uint16_t temp;
+
+ SEG_CHECK_READ(cpu_state.ea_seg);
+ temp = readmemw(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) return 1;
check_io_perm(DX);
check_io_perm(DX + 1);
- if (flags & D_FLAG) SI -= 2;
- else SI += 2;
+ if (cpu_state.flags & D_FLAG) SI -= 2;
+ else SI += 2;
outw(DX, temp);
CLOCK_CYCLES(14);
PREFETCH_RUN(14, 1, -1, 1,0,1,0, 0);
}
static int opOUTSW_a32(uint32_t fetchdat)
{
- uint16_t temp = readmemw(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) return 1;
+ uint16_t temp;
+
+ SEG_CHECK_READ(cpu_state.ea_seg);
+ temp = readmemw(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) return 1;
check_io_perm(DX);
check_io_perm(DX + 1);
- if (flags & D_FLAG) ESI -= 2;
- else ESI += 2;
+ if (cpu_state.flags & D_FLAG) ESI -= 2;
+ else ESI += 2;
outw(DX, temp);
CLOCK_CYCLES(14);
PREFETCH_RUN(14, 1, -1, 1,0,1,0, 1);
static int opOUTSL_a16(uint32_t fetchdat)
{
- uint32_t temp = readmeml(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) return 1;
+ uint32_t temp;
+
+ SEG_CHECK_READ(cpu_state.ea_seg);
+ temp = readmeml(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) return 1;
check_io_perm(DX);
check_io_perm(DX + 1);
check_io_perm(DX + 2);
check_io_perm(DX + 3);
- if (flags & D_FLAG) SI -= 4;
- else SI += 4;
+ if (cpu_state.flags & D_FLAG) SI -= 4;
+ else SI += 4;
outl(EDX, temp);
CLOCK_CYCLES(14);
PREFETCH_RUN(14, 1, -1, 0,1,0,1, 0);
}
static int opOUTSL_a32(uint32_t fetchdat)
{
- uint32_t temp = readmeml(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) return 1;
+ uint32_t temp;
+
+ SEG_CHECK_READ(cpu_state.ea_seg);
+ temp = readmeml(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) return 1;
check_io_perm(DX);
check_io_perm(DX + 1);
check_io_perm(DX + 2);
check_io_perm(DX + 3);
- if (flags & D_FLAG) ESI -= 4;
- else ESI += 4;
+ if (cpu_state.flags & D_FLAG) ESI -= 4;
+ else ESI += 4;
outl(EDX, temp);
CLOCK_CYCLES(14);
PREFETCH_RUN(14, 1, -1, 0,1,0,1, 1);
static int opXCHG_b_a16(uint32_t fetchdat)
{
uint8_t temp;
+
fetch_ea_16(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = geteab(); if (cpu_state.abrt) return 1;
seteab(getr8(cpu_reg)); if (cpu_state.abrt) return 1;
setr8(cpu_reg, temp);
static int opXCHG_b_a32(uint32_t fetchdat)
{
uint8_t temp;
+
fetch_ea_32(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = geteab(); if (cpu_state.abrt) return 1;
seteab(getr8(cpu_reg)); if (cpu_state.abrt) return 1;
setr8(cpu_reg, temp);
static int opXCHG_w_a16(uint32_t fetchdat)
{
uint16_t temp;
+
fetch_ea_16(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = geteaw(); if (cpu_state.abrt) return 1;
seteaw(cpu_state.regs[cpu_reg].w); if (cpu_state.abrt) return 1;
cpu_state.regs[cpu_reg].w = temp;
static int opXCHG_w_a32(uint32_t fetchdat)
{
uint16_t temp;
+
fetch_ea_32(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = geteaw(); if (cpu_state.abrt) return 1;
seteaw(cpu_state.regs[cpu_reg].w); if (cpu_state.abrt) return 1;
cpu_state.regs[cpu_reg].w = temp;
static int opXCHG_l_a16(uint32_t fetchdat)
{
uint32_t temp;
+
fetch_ea_16(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = geteal(); if (cpu_state.abrt) return 1;
seteal(cpu_state.regs[cpu_reg].l); if (cpu_state.abrt) return 1;
cpu_state.regs[cpu_reg].l = temp;
static int opXCHG_l_a32(uint32_t fetchdat)
{
uint32_t temp;
+
fetch_ea_32(fetchdat);
+ if (cpu_mod != 3)
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
temp = geteal(); if (cpu_state.abrt) return 1;
seteal(cpu_state.regs[cpu_reg].l); if (cpu_state.abrt) return 1;
cpu_state.regs[cpu_reg].l = temp;
#include "ibm.h"
#include "mem.h"
#include "x86.h"
-#include "386.h"
+#include "x86_flags.h"
#include "386_common.h"
#include "cpu.h"
#include "config.h"
void taskswitch286(uint16_t seg, uint16_t *segdat, int is32);
void taskswitch386(uint16_t seg, uint16_t *segdat);
-extern int output;
-
/*NOT PRESENT is INT 0B
GPF is INT 0D*/
if (!pclogf)
{
strcpy(buf, logs_path);
- //put_backslash(buf);
+ put_backslash(buf);
strcat(buf, "pcem.log");
pclogf=fopen(buf, "wt");
}
exit(-1);
}
-uint8_t opcode2;
-
static void seg_reset(x86seg *s)
{
s->access = (0 << 5) | 2;
s->limit = 0xFFFF;
s->limit_low = 0;
s->limit_high = 0xffff;
- if (s == &_cs)
+ if (s == &cpu_state.seg_cs)
{
// TODO - When the PC is reset, initialization of the CS descriptor must be like the annotated line below.
//s->base = AT ? (cpu_16bitbus ? 0xFF0000 : 0xFFFF0000) : 0xFFFF0;
void x86seg_reset()
{
- seg_reset(&_cs);
- seg_reset(&_ds);
- seg_reset(&_es);
- seg_reset(&_fs);
- seg_reset(&_gs);
- seg_reset(&_ss);
+ seg_reset(&cpu_state.seg_cs);
+ seg_reset(&cpu_state.seg_ds);
+ seg_reset(&cpu_state.seg_es);
+ seg_reset(&cpu_state.seg_fs);
+ seg_reset(&cpu_state.seg_gs);
+ seg_reset(&cpu_state.seg_ss);
}
void x86_doabrt(int x86_abrt)
{
// ingpf = 1;
- CS = oldcs;
cpu_state.pc = cpu_state.oldpc;
- _cs.access = oldcpl << 5;
+ cpu_state.seg_cs.access = oldcpl << 5;
// pclog("x86_doabrt - %02X %08X %04X:%08X %i\n", x86_abrt, abrt_error, CS, pc, ins);
/* if (CS == 0x3433 && pc == 0x000006B0)
uint32_t addr = (x86_abrt << 2) + idt.base;
if (stack32)
{
- writememw(ss,ESP-2,flags);
+ writememw(ss,ESP-2,cpu_state.flags);
writememw(ss,ESP-4,CS);
writememw(ss,ESP-6,cpu_state.pc);
ESP-=6;
}
else
{
- writememw(ss,((SP-2)&0xFFFF),flags);
+ writememw(ss,((SP-2)&0xFFFF),cpu_state.flags);
writememw(ss,((SP-4)&0xFFFF),CS);
writememw(ss,((SP-6)&0xFFFF),cpu_state.pc);
SP-=6;
}
- flags&=~I_FLAG;
- flags&=~T_FLAG;
- oxpc=cpu_state.pc;
+ cpu_state.flags &= ~I_FLAG;
+ cpu_state.flags &= ~T_FLAG;
cpu_state.pc=readmemw(0,addr);
loadcs(readmemw(0,addr+2));
return;
SP-=4;
}
}
-// ingpf = 0;
-// abrt = gpf = 1;
}
void x86gpf(char *s, uint16_t error)
{
}
// if (output) pclog("SEG : base=%08x limit=%08x low=%08x high=%08x\n", s->base, s->limit, s->limit_low, s->limit_high);
- if (s == &_ds)
+ if (s == &cpu_state.seg_ds)
{
if (s->base == 0 && s->limit_low == 0 && s->limit_high == 0xffffffff)
cpu_cur_status &= ~CPU_STATUS_NOTFLATDS;
else
cpu_cur_status |= CPU_STATUS_NOTFLATDS;
}
- if (s == &_ss)
+ if (s == &cpu_state.seg_ss)
{
if (s->base == 0 && s->limit_low == 0 && s->limit_high == 0xffffffff)
cpu_cur_status &= ~CPU_STATUS_NOTFLATSS;
loadseg(0, s);
}
-void loadseg(uint16_t seg, x86seg *s)
+int loadseg(uint16_t seg, x86seg *s)
{
uint16_t segdat[4];
uint32_t addr;
int dpl;
- if (msw&1 && !(eflags&VM_FLAG))
+ if (msw&1 && !(cpu_state.eflags&VM_FLAG))
{
// intcount++;
if (!(seg&~3))
{
- if (s==&_ss)
+ if (s==&cpu_state.seg_ss)
{
pclog("SS selector = NULL!\n");
x86ss(NULL,0);
- return;
+ return 1;
// dumpregs();
// exit(-1);
}
s->seg=0;
s->access = 0;
s->base=-1;
- if (s == &_ds)
+ if (s == &cpu_state.seg_ds)
cpu_cur_status |= CPU_STATUS_NOTFLATDS;
// pclog("NULL selector %s%s%s%s %04X(%06X):%06X\n",(s==&_ds)?"DS":"",(s==&_es)?"ES":"",(s==&_fs)?"FS":"",(s==&_gs)?"GS":"",CS,cs,pc);
- return;
+ return 0;
}
// if (s==&_ss) pclog("Load SS %04X\n",seg);
// pclog("Protected mode seg load!\n");
{
if (addr>=ldt.limit)
{
- pclog("Bigger than LDT limit %04X %04X %02X %02X %02X\n",seg,ldt.limit, opcode, opcode2, 0/*rmdat*/);
+ pclog("Bigger than LDT limit %04X %04X %02X\n",seg,ldt.limit, 0/*rmdat*/);
// dumppic();
// dumpregs();
// exit(-1);
x86gpf(NULL,seg&~3);
- return;
+ return 1;
}
addr+=ldt.base;
}
// dumpregs();
// exit(-1);
x86gpf(NULL,seg&~3);
- return;
+ return 1;
}
addr+=gdt.base;
}
segdat[0]=readmemw(0,addr);
segdat[1]=readmemw(0,addr+2);
segdat[2]=readmemw(0,addr+4);
- segdat[3]=readmemw(0,addr+6); cpl_override=0; if (cpu_state.abrt) return;
+ segdat[3]=readmemw(0,addr+6); cpl_override=0; if (cpu_state.abrt) return 1;
dpl=(segdat[2]>>13)&3;
- if (s==&_ss)
+ if (s==&cpu_state.seg_ss)
{
if (!(seg&~3))
{
pclog("Load SS null selector\n");
x86gpf(NULL,seg&~3);
- return;
+ return 1;
}
if ((seg&3)!=CPL || dpl!=CPL)
{
pclog("Invalid SS permiss\n");
x86gpf(NULL,seg&~3);
// x86abort("Invalid SS permiss for %04X!\n",seg&0xFFFC);
- return;
+ return 1;
}
switch ((segdat[2]>>8)&0x1F)
{
pclog("Invalid SS type\n");
x86gpf(NULL,seg&~3);
// x86abort("Invalid SS segment type for %04X!\n",seg&0xFFFC);
- return;
+ return 1;
}
if (!(segdat[2]&0x8000))
{
pclog("Load SS not present!\n");
x86ss(NULL,seg&~3);
- return;
+ return 1;
}
set_stack32((segdat[3] & 0x40) ? 1 : 0);
// pclog("Load SS %04x %04x %04x %04x\n", segdat[0], segdat[1], segdat[2], segdat[3]);
}
- else if (s!=&_cs)
+ else if (s!=&cpu_state.seg_cs)
{
if (output) pclog("Seg data %04X %04X %04X %04X\n", segdat[0], segdat[1], segdat[2], segdat[3]);
if (output) pclog("Seg type %03X\n",segdat[2]&0x1F00);
pclog("Data seg fail - %04X:%08X %04X %i %04X\n",CS,cpu_state.pc,seg,dpl,segdat[2]);
x86gpf(NULL,seg&~3);
// x86abort("Data segment load - level too low!\n",seg&0xFFFC);
- return;
+ return 1;
}
break;
case 0x1E: case 0x1F: /*Readable conforming code*/
default:
pclog("Invalid segment type for %04X! %04X\n",seg&0xFFFC,segdat[2]);
x86gpf(NULL,seg&~3);
- return;
+ return 1;
}
}
if (!(segdat[2] & 0x8000))
{
x86np("Load data seg not present", seg & 0xfffc);
- return;
+ return 1;
}
s->seg = seg;
do_seg_load(s, segdat);
}
#endif
s->checked = 0;
- if (s == &_ds)
+ if (s == &cpu_state.seg_ds)
codegen_flat_ds = 0;
- if (s == &_ss)
+ if (s == &cpu_state.seg_ss)
codegen_flat_ss = 0;
}
else
s->access = (3 << 5) | 2;
s->base = seg << 4;
s->seg = seg;
- if (s == &_ss)
- set_stack32(0);
s->checked = 1;
- if (s == &_ds)
+ if (s == &cpu_state.seg_ds)
codegen_flat_ds = 0;
- if (s == &_ss)
+ if (s == &cpu_state.seg_ss)
codegen_flat_ss = 0;
+ if (s == &cpu_state.seg_ss && (cpu_state.eflags & VM_FLAG))
+ set_stack32(0);
}
- if (s == &_ds)
+ if (s == &cpu_state.seg_ds)
{
if (s->base == 0 && s->limit_low == 0 && s->limit_high == 0xffffffff)
cpu_cur_status &= ~CPU_STATUS_NOTFLATDS;
else
cpu_cur_status |= CPU_STATUS_NOTFLATDS;
}
- if (s == &_ss)
+ if (s == &cpu_state.seg_ss)
{
if (s->base == 0 && s->limit_low == 0 && s->limit_high == 0xffffffff)
cpu_cur_status &= ~CPU_STATUS_NOTFLATSS;
else
cpu_cur_status |= CPU_STATUS_NOTFLATSS;
}
+
+ return cpu_state.abrt;
}
#define DPL ((segdat[2]>>13)&3)
uint16_t segdat[4];
uint32_t addr;
if (output) pclog("Load CS %04X\n",seg);
- if (msw&1 && !(eflags&VM_FLAG))
+ if (msw&1 && !(cpu_state.eflags&VM_FLAG))
{
// intcount++;
// flushmmucache();
if ((seg&3)>CPL)
{
x86gpf(NULL,seg&~3);
- pclog("loadcs RPL > CPL %04X %04X %i %02X\n",segdat[2],seg,CPL,opcode);
+ pclog("loadcs RPL > CPL %04X %04X %i\n",segdat[2],seg,CPL);
return;
}
if (CPL != DPL)
}
set_use32(segdat[3] & 0x40);
CS=(seg&~3)|CPL;
- do_seg_load(&_cs, segdat);
+ do_seg_load(&cpu_state.seg_cs, segdat);
use32=(segdat[3]&0x40)?0x300:0;
if (CPL==3 && oldcpl!=3) flushmmucache_cr3();
+ oldcpl = CPL;
#ifdef CS_ACCESSED
cpl_override = 1;
switch (segdat[2]&0xF00)
{
default:
- pclog("Bad CS %02X %02X %i special descriptor %03X %04X\n",opcode,0/*rmdat*/,optype,segdat[2]&0xF00,seg);
+ pclog("Bad CS %02X %i special descriptor %03X %04X\n",0/*rmdat*/,optype,segdat[2]&0xF00,seg);
x86gpf(NULL,seg&~3);
return;
}
}
else
{
- _cs.base=seg<<4;
- _cs.limit=0xFFFF;
- _cs.limit_low = 0;
- _cs.limit_high = 0xffff;
+ cpu_state.seg_cs.base=seg<<4;
+ cpu_state.seg_cs.limit=0xFFFF;
+ cpu_state.seg_cs.limit_low = 0;
+ cpu_state.seg_cs.limit_high = 0xffff;
CS=seg;
- if (eflags&VM_FLAG) _cs.access=(3<<5) | 2;
- else _cs.access=(0<<5) | 2;
+ if (cpu_state.eflags&VM_FLAG) cpu_state.seg_cs.access=(3<<5) | 2;
+ else cpu_state.seg_cs.access=(0<<5) | 2;
if (CPL==3 && oldcpl!=3) flushmmucache_cr3();
+ oldcpl = CPL;
}
}
-void loadcsjmp(uint16_t seg, uint32_t oxpc)
+void loadcsjmp(uint16_t seg, uint32_t old_pc)
{
uint16_t segdat[4];
uint32_t addr;
uint16_t type,seg2;
uint32_t newpc;
// pclog("Load CS JMP %04X\n",seg);
- if (msw&1 && !(eflags&VM_FLAG))
+ if (msw&1 && !(cpu_state.eflags&VM_FLAG))
{
if (!(seg&~3))
{
CS = (seg & ~3) | CPL;
segdat[2] = (segdat[2] & ~(3 << (5+8))) | (CPL << (5+8));
- do_seg_load(&_cs, segdat);
+ do_seg_load(&cpu_state.seg_cs, segdat);
if (CPL==3 && oldcpl!=3) flushmmucache_cr3();
+ oldcpl = CPL;
/* if (segdat[3]&0x40)
{
use32=0x300;
// pclog("Call gate\n");
cgate32=(type&0x800);
cgate16=!cgate32;
- oldcs=CS;
cpu_state.oldpc = cpu_state.pc;
if ((DPL < CPL) || (DPL < (seg&3)))
{
}
case 0x1C00: case 0x1D00: case 0x1E00: case 0x1F00: /*Conforming*/
CS=seg2;
- do_seg_load(&_cs, segdat);
+ do_seg_load(&cpu_state.seg_cs, segdat);
if (CPL==3 && oldcpl!=3) flushmmucache_cr3();
+ oldcpl = CPL;
set_use32(segdat[3]&0x40);
cpu_state.pc=newpc;
case 0x100: /*286 Task gate*/
case 0x900: /*386 Task gate*/
// pclog("Task gate\n");
- cpu_state.pc=oxpc;
+ cpu_state.pc = old_pc;
optype=JMP;
cpl_override=1;
taskswitch286(seg,segdat,segdat[2]&0x800);
- flags &= ~NT_FLAG;
+ cpu_state.flags &= ~NT_FLAG;
cpl_override=0;
// case 0xB00: /*386 Busy task gate*/
// if (optype==JMP) pclog("Task switch!\n");
return;
default:
- pclog("Bad JMP CS %02X %02X %i special descriptor %03X %04X\n",opcode,0/*rmdat*/,optype,segdat[2]&0xF00,seg);
+ pclog("Bad JMP CS %02X %i special descriptor %03X %04X\n",0/*rmdat*/,optype,segdat[2]&0xF00,seg);
x86gpf(NULL,0);
return;
// dumpregs();
}
else
{
- _cs.base=seg<<4;
- _cs.limit=0xFFFF;
- _cs.limit_low = 0;
- _cs.limit_high = 0xffff;
+ cpu_state.seg_cs.base=seg<<4;
+ cpu_state.seg_cs.limit=0xFFFF;
+ cpu_state.seg_cs.limit_low = 0;
+ cpu_state.seg_cs.limit_high = 0xffff;
CS=seg;
- if (eflags&VM_FLAG) _cs.access=(3<<5) | 2;
- else _cs.access=(0<<5) | 2;
+ if (cpu_state.eflags&VM_FLAG) cpu_state.seg_cs.access=(3<<5) | 2;
+ else cpu_state.seg_cs.access=(0<<5) | 2;
if (CPL==3 && oldcpl!=3) flushmmucache_cr3();
+ oldcpl = CPL;
cycles -= timing_jmp_rm;
}
}
return templ;
}
-void loadcscall(uint16_t seg)
+void loadcscall(uint16_t seg, uint32_t old_pc)
{
uint16_t seg2;
uint16_t segdat[4],segdat2[4],newss;
int csout = output;
- if (msw&1 && !(eflags&VM_FLAG))
+ if (msw&1 && !(cpu_state.eflags&VM_FLAG))
{
//flushmmucache();
if (csout) pclog("Protected mode CS load! %04X\n",seg);
else /*On non-conforming segments, set RPL = CPL*/
seg = (seg & ~3) | CPL;
CS=seg;
- do_seg_load(&_cs, segdat);
+ do_seg_load(&cpu_state.seg_cs, segdat);
if (CPL==3 && oldcpl!=3) flushmmucache_cr3();
+ oldcpl = CPL;
/* if (segdat[3]&0x40)
{
use32=0x300;
case 0x1800: case 0x1900: case 0x1A00: case 0x1B00: /*Non-conforming code*/
if (DPL < CPL)
{
+ uint16_t oldcs = CS;
oaddr = addr;
/*Load new stack*/
oldss=SS;
if (stack32) ESP=newsp;
else SP=newsp;
- do_seg_load(&_ss, segdat2);
+ do_seg_load(&cpu_state.seg_ss, segdat2);
if (output) pclog("Set access 1\n");
#endif
CS=seg2;
- do_seg_load(&_cs, segdat);
+ do_seg_load(&cpu_state.seg_cs, segdat);
if (CPL==3 && oldcpl!=3) flushmmucache_cr3();
+ oldcpl = CPL;
set_use32(segdat[3]&0x40);
cpu_state.pc=newpc;
pclog("ABRT PUSHL\n");
SS = oldss;
ESP = oldsp2;
+ CS = oldcs;
return;
}
// if (output) pclog("Stack now %04X:%08X\n",SS,ESP);
pclog("ABRT COPYL\n");
SS = oldss;
ESP = oldsp2;
+ CS = oldcs;
return;
}
}
}
// x86abort("Call gate with count %i\n",count);
-// PUSHL(oldcs);
-// PUSHL(oldpc); if (cpu_state.abrt) return;
}
else
{
pclog("ABRT PUSHW\n");
SS = oldss;
ESP = oldsp2;
+ CS = oldcs;
return;
}
if (output) pclog("Write SP to %04X:%04X\n",SS,SP);
pclog("ABRT COPYW\n");
SS = oldss;
ESP = oldsp2;
+ CS = oldcs;
return;
}
}
}
// if (output) pclog("Stack %04X\n",SP);
// if (count) x86abort("Call gate with count\n");
-// PUSHW(oldcs);
-// PUSHW(oldpc); if (cpu_state.abrt) return;
}
cycles -= timing_call_pm_gate_inner;
break;
return;
}
case 0x1C00: case 0x1D00: case 0x1E00: case 0x1F00: /*Conforming*/
-/* if (type==0xC00)
- {
- PUSHL(oldcs);
- PUSHL(oldpc); if (cpu_state.abrt) return;
- }
- else
- {
- PUSHW(oldcs);
- PUSHW(oldpc); if (cpu_state.abrt) return;
- }*/
CS=seg2;
- do_seg_load(&_cs, segdat);
+ do_seg_load(&cpu_state.seg_cs, segdat);
if (CPL==3 && oldcpl!=3) flushmmucache_cr3();
+ oldcpl = CPL;
set_use32(segdat[3]&0x40);
cpu_state.pc=newpc;
case 0x100: /*286 Task gate*/
case 0x900: /*386 Task gate*/
// pclog("Task gate\n");
- cpu_state.pc=oxpc;
+ cpu_state.pc = old_pc;
cpl_override=1;
taskswitch286(seg,segdat,segdat[2]&0x800);
cpl_override=0;
}
else
{
- _cs.base=seg<<4;
- _cs.limit=0xFFFF;
- _cs.limit_low = 0;
- _cs.limit_high = 0xffff;
+ cpu_state.seg_cs.base=seg<<4;
+ cpu_state.seg_cs.limit=0xFFFF;
+ cpu_state.seg_cs.limit_low = 0;
+ cpu_state.seg_cs.limit_high = 0xffff;
CS=seg;
- if (eflags&VM_FLAG) _cs.access=(3<<5) | 2;
- else _cs.access=(0<<5) | 2;
+ if (cpu_state.eflags&VM_FLAG) cpu_state.seg_cs.access=(3<<5) | 2;
+ else cpu_state.seg_cs.access=(0<<5) | 2;
if (CPL==3 && oldcpl!=3) flushmmucache_cr3();
+ oldcpl = CPL;
}
}
uint32_t addr, oaddr;
uint16_t segdat[4],segdat2[4],seg,newss;
uint32_t oldsp=ESP;
- if (output) pclog("RETF %i %04X:%04X %08X %04X\n",is32,CS,cpu_state.pc,cr0,eflags);
+ if (output) pclog("RETF %i %04X:%04X %08X %04X\n",is32,CS,cpu_state.pc,cr0,cpu_state.eflags);
if (is32)
{
newpc=POPL();
if (segdat[2] & 0x400)
segdat[2] = (segdat[2] & ~(3 << (5+8))) | ((seg & 3) << (5+8));
CS = seg;
- do_seg_load(&_cs, segdat);
- _cs.access = (_cs.access & ~(3 << 5)) | ((CS & 3) << 5);
+ do_seg_load(&cpu_state.seg_cs, segdat);
+ cpu_state.seg_cs.access = (cpu_state.seg_cs.access & ~(3 << 5)) | ((CS & 3) << 5);
if (CPL==3 && oldcpl!=3) flushmmucache_cr3();
+ oldcpl = CPL;
set_use32(segdat[3] & 0x40);
// pclog("CPL=RPL return to %04X:%08X\n",CS,pc);
set_stack32((segdat2[3] & 0x40) ? 1 : 0);
if (stack32) ESP=newsp;
else SP=newsp;
- do_seg_load(&_ss, segdat2);
+ do_seg_load(&cpu_state.seg_ss, segdat2);
#ifdef SEL_ACCESSED
cpl_override = 1;
cpu_state.pc=newpc;
CS=seg;
- do_seg_load(&_cs, segdat);
+ do_seg_load(&cpu_state.seg_cs, segdat);
if (CPL==3 && oldcpl!=3) flushmmucache_cr3();
+ oldcpl = CPL;
set_use32(segdat[3] & 0x40);
if (stack32) ESP+=off;
else SP+=off;
- check_seg_valid(&_ds);
- check_seg_valid(&_es);
- check_seg_valid(&_fs);
- check_seg_valid(&_gs);
+ check_seg_valid(&cpu_state.seg_ds);
+ check_seg_valid(&cpu_state.seg_es);
+ check_seg_valid(&cpu_state.seg_fs);
+ check_seg_valid(&cpu_state.seg_gs);
// pclog("CPL<RPL return to %04X:%08X %04X:%08X\n",CS,pc,SS,ESP);
cycles -= timing_retf_pm_outer;
}
}
-void restore_stack()
-{
- ss=oldss; _ss.limit=oldsslimit;
-}
-
void pmodeint(int num, int soft)
{
uint16_t segdat[4],segdat2[4],segdat3[4];
// if (!num) pclog("Pmode int 0 at %04X(%06X):%08X\n",CS,cs,pc);
// pclog("Pmode int %02X %i %04X:%08X %04X:%08X %i\n",num,soft,CS,pc, SS, ESP, abrt);
- if (eflags&VM_FLAG && IOPL!=3 && soft)
+ if (cpu_state.eflags&VM_FLAG && IOPL!=3 && soft)
{
if (output) pclog("V86 banned int\n");
pclog("V86 banned int!\n");
x86np("Int gate CS not present\n", segdat[1] & 0xfffc);
return;
}
- if ((eflags&VM_FLAG) && DPL2)
+ if ((cpu_state.eflags & VM_FLAG) && DPL2)
{
pclog("V86 calling int gate, DPL != 0\n");
x86gpf(NULL,segdat[1]&0xFFFC);
set_stack32((segdat3[3] & 0x40) ? 1 : 0);
if (stack32) ESP=newsp;
else SP=newsp;
- do_seg_load(&_ss, segdat3);
+ do_seg_load(&cpu_state.seg_ss, segdat3);
#ifdef CS_ACCESSED
cpl_override = 1;
if (type>=0x800)
{
// if (output) pclog("Push 32 %i\n",eflags&VM_FLAG);
- if (eflags & VM_FLAG)
+ if (cpu_state.eflags & VM_FLAG)
{
PUSHL(GS);
PUSHL(FS);
PUSHL(DS);
PUSHL(ES); if (cpu_state.abrt) return;
- loadseg(0,&_ds);
- loadseg(0,&_es);
- loadseg(0,&_fs);
- loadseg(0,&_gs);
+ loadseg(0,&cpu_state.seg_ds);
+ loadseg(0,&cpu_state.seg_es);
+ loadseg(0,&cpu_state.seg_fs);
+ loadseg(0,&cpu_state.seg_gs);
}
PUSHL(oldss);
PUSHL(oldsp);
- PUSHL(flags|(eflags<<16));
+ PUSHL(cpu_state.flags | (cpu_state.eflags << 16));
// if (soft) pclog("Pushl CS %08X\n", CS);
PUSHL(CS);
// if (soft) pclog("Pushl PC %08X\n", pc);
// if (output) pclog("Push 16\n");
PUSHW(oldss);
PUSHW(oldsp);
- PUSHW(flags);
+ PUSHW(cpu_state.flags);
// if (soft) pclog("Pushw CS %04X\n", CS);
PUSHW(CS);
// if (soft) pclog("Pushw pc %04X\n", pc);
// if (output) pclog("16Stack %04X:%08X\n",SS,ESP);
}
cpl_override=0;
- _cs.access=0;
+ cpu_state.seg_cs.access=0;
cycles -= timing_int_pm_outer - timing_int_pm;
// pclog("Non-confirming int gate, CS = %04X\n");
break;
x86np("Int gate CS not present\n", segdat[1] & 0xfffc);
return;
}
- if ((eflags & VM_FLAG) && DPL2<CPL)
+ if ((cpu_state.eflags & VM_FLAG) && DPL2<CPL)
{
pclog("Int gate V86 mode DPL2<CPL\n");
x86gpf(NULL,seg&~3);
// if (!stack_changed && ssegs) restore_stack();
if (type>0x800)
{
- PUSHL(flags|(eflags<<16));
+ PUSHL(cpu_state.flags | (cpu_state.eflags << 16));
// if (soft) pclog("Pushlc CS %08X\n", CS);
PUSHL(CS);
// if (soft) pclog("Pushlc PC %08X\n", pc);
}
else
{
- PUSHW(flags);
+ PUSHW(cpu_state.flags);
// if (soft) pclog("Pushwc CS %04X\n", CS);
PUSHW(CS);
// if (soft) pclog("Pushwc PC %04X\n", pc);
x86gpf(NULL,seg&~3);
return;
}
- do_seg_load(&_cs, segdat2);
+ do_seg_load(&cpu_state.seg_cs, segdat2);
CS = (seg & ~3) | new_cpl;
- _cs.access = (_cs.access & ~(3 << 5)) | (new_cpl << 5);
+ cpu_state.seg_cs.access = (cpu_state.seg_cs.access & ~(3 << 5)) | (new_cpl << 5);
// pclog("New CS = %04X\n",CS);
if (CPL==3 && oldcpl!=3) flushmmucache_cr3();
+ oldcpl = CPL;
if (type>0x800) cpu_state.pc=segdat[0]|(segdat[3]<<16);
else cpu_state.pc=segdat[0];
set_use32(segdat2[3]&0x40);
cpl_override = 0;
#endif
- eflags&=~VM_FLAG;
+ cpu_state.eflags &= ~VM_FLAG;
cpu_cur_status &= ~CPU_STATUS_V86;
if (!(type&0x100))
{
- flags&=~I_FLAG;
+ cpu_state.flags &= ~I_FLAG;
// pclog("INT %02X disabling interrupts %i\n",num,soft);
}
- flags&=~(T_FLAG|NT_FLAG);
+ cpu_state.flags &= ~(T_FLAG|NT_FLAG);
// if (output) pclog("Final Stack %04X:%08X\n",SS,ESP);
cycles -= timing_int_pm;
break;
uint16_t seg = 0;
uint32_t addr, oaddr;
uint32_t oldsp=ESP;
- if (is386 && (eflags&VM_FLAG))
+ if (is386 && (cpu_state.eflags & VM_FLAG))
{
// if (output) pclog("V86 IRET\n");
if (IOPL!=3)
x86gpf(NULL,0);
return;
}
- oxpc=cpu_state.pc;
if (is32)
{
newpc=POPL();
tempflags=POPW(); if (cpu_state.abrt) return;
}
cpu_state.pc=newpc;
- _cs.base=seg<<4;
- _cs.limit=0xFFFF;
- _cs.limit_low = 0;
- _cs.limit_high = 0xffff;
+ cpu_state.seg_cs.base=seg<<4;
+ cpu_state.seg_cs.limit=0xFFFF;
+ cpu_state.seg_cs.limit_low = 0;
+ cpu_state.seg_cs.limit_high = 0xffff;
CS=seg;
- flags=(flags&0x3000)|(tempflags&0xCFD5)|2;
+ cpu_state.flags = (cpu_state.flags & 0x3000) | (tempflags & 0xCFD5) | 2;
cycles -= timing_iret_rm;
return;
}
//flushmmucache();
// if (output) pclog("Pmode IRET %04X:%04X ",CS,pc);
- if (flags&NT_FLAG)
+ if (cpu_state.flags & NT_FLAG)
{
// pclog("NT IRET\n");
seg=readmemw(tr.base,0);
cpl_override=0;
return;
}
- oxpc=cpu_state.pc;
flagmask=0xFFFF;
if (CPL) flagmask&=~0x3000;
if (IOPL<CPL) flagmask&=~0x200;
segs[2]=POPL();
segs[3]=POPL(); if (cpu_state.abrt) { ESP = oldsp; return; }
// pclog("Pop stack %04X:%04X\n",newss,newsp);
- eflags=tempflags>>16;
+ cpu_state.eflags = tempflags>>16;
cpu_cur_status |= CPU_STATUS_V86;
- loadseg(segs[0],&_es);
- do_seg_v86_init(&_es);
- loadseg(segs[1],&_ds);
- do_seg_v86_init(&_ds);
+ loadseg(segs[0],&cpu_state.seg_es);
+ do_seg_v86_init(&cpu_state.seg_es);
+ loadseg(segs[1],&cpu_state.seg_ds);
+ do_seg_v86_init(&cpu_state.seg_ds);
cpu_cur_status |= CPU_STATUS_NOTFLATDS;
- loadseg(segs[2],&_fs);
- do_seg_v86_init(&_fs);
- loadseg(segs[3],&_gs);
- do_seg_v86_init(&_gs);
+ loadseg(segs[2],&cpu_state.seg_fs);
+ do_seg_v86_init(&cpu_state.seg_fs);
+ loadseg(segs[3],&cpu_state.seg_gs);
+ do_seg_v86_init(&cpu_state.seg_gs);
// pclog("V86 IRET %04X:%08X\n",SS,ESP);
// output=3;
- cpu_state.pc=newpc;
- _cs.base=seg<<4;
- _cs.limit=0xFFFF;
- _cs.limit_low = 0;
- _cs.limit_high = 0xffff;
+ cpu_state.pc = newpc & 0xffff;
+ cpu_state.seg_cs.base=seg<<4;
+ cpu_state.seg_cs.limit=0xFFFF;
+ cpu_state.seg_cs.limit_low = 0;
+ cpu_state.seg_cs.limit_high = 0xffff;
CS=seg;
- _cs.access=(3<<5) | 2;
+ cpu_state.seg_cs.access=(3<<5) | 2;
if (CPL==3 && oldcpl!=3) flushmmucache_cr3();
+ oldcpl = CPL;
ESP=newsp;
- loadseg(newss,&_ss);
- do_seg_v86_init(&_ss);
+ loadseg(newss,&cpu_state.seg_ss);
+ do_seg_v86_init(&cpu_state.seg_ss);
cpu_cur_status |= CPU_STATUS_NOTFLATSS;
use32=0;
cpu_cur_status &= ~CPU_STATUS_USE32;
- flags=(tempflags&0xFFD5)|2;
+ cpu_state.flags = (tempflags&0xFFD5)|2;
cycles -= timing_iret_v86;
// pclog("V86 IRET to %04X:%04X %04X:%04X %04X %04X %04X %04X %i\n",CS,pc,SS,SP,DS,ES,FS,GS,abrt);
// if (CS==0xFFFF && pc==0xFFFFFFFF) timetolive=12;
{
// pclog("Same level\n");
CS=seg;
- do_seg_load(&_cs, segdat);
- _cs.access = (_cs.access & ~(3 << 5)) | ((CS & 3) << 5);
+ do_seg_load(&cpu_state.seg_cs, segdat);
+ cpu_state.seg_cs.access = (cpu_state.seg_cs.access & ~(3 << 5)) | ((CS & 3) << 5);
if (CPL==3 && oldcpl!=3) flushmmucache_cr3();
+ oldcpl = CPL;
set_use32(segdat[3]&0x40);
#ifdef CS_ACCESSED
set_stack32((segdat2[3] & 0x40) ? 1 : 0);
if (stack32) ESP=newsp;
else SP=newsp;
- do_seg_load(&_ss, segdat2);
+ do_seg_load(&cpu_state.seg_ss, segdat2);
#ifdef SEL_ACCESSED
cpl_override = 1;
segdat[2] = (segdat[2] & ~(3 << (5+8))) | ((seg & 3) << (5+8));
CS=seg;
- do_seg_load(&_cs, segdat);
- _cs.access = (_cs.access & ~(3 << 5)) | ((CS & 3) << 5);
+ do_seg_load(&cpu_state.seg_cs, segdat);
+ cpu_state.seg_cs.access = (cpu_state.seg_cs.access & ~(3 << 5)) | ((CS & 3) << 5);
if (CPL==3 && oldcpl!=3) flushmmucache_cr3();
+ oldcpl = CPL;
set_use32(segdat[3] & 0x40);
- check_seg_valid(&_ds);
- check_seg_valid(&_es);
- check_seg_valid(&_fs);
- check_seg_valid(&_gs);
+ check_seg_valid(&cpu_state.seg_ds);
+ check_seg_valid(&cpu_state.seg_es);
+ check_seg_valid(&cpu_state.seg_fs);
+ check_seg_valid(&cpu_state.seg_gs);
cycles -= timing_iret_pm_outer;
}
cpu_state.pc=newpc;
- flags=(flags&~flagmask)|(tempflags&flagmask&0xFFD5)|2;
- if (is32) eflags=tempflags>>16;
+ cpu_state.flags = (cpu_state.flags&~flagmask) | (tempflags&flagmask&0xFFD5)|2;
+ if (is32) cpu_state.eflags = tempflags>>16;
// pclog("done\n");
}
}
if (cpu_state.abrt) return;
- if (optype==IRET) flags&=~NT_FLAG;
+ if (optype==IRET) cpu_state.flags&=~NT_FLAG;
// if (output) pclog("Write PC %08X %08X\n",tr.base,pc);
cpu_386_flags_rebuild();
writememl(tr.base,0x1C,cr3);
writememl(tr.base,0x20,cpu_state.pc);
- writememl(tr.base,0x24,flags|(eflags<<16));
+ writememl(tr.base,0x24,cpu_state.flags | (cpu_state.eflags<<16));
writememl(tr.base,0x28,EAX);
writememl(tr.base,0x2C,ECX);
cpu_state.pc=new_pc;
// if (output) pclog("New pc %08X\n",new_pc);
- flags=new_flags;
- eflags=new_flags>>16;
+ cpu_state.flags = new_flags;
+ cpu_state.eflags = new_flags>>16;
cpu_386_flags_extract();
// if (output) pclog("Load LDT %04X\n",new_ldt);
// if (output) pclog("Limit %04X Base %08X\n",ldt.limit,ldt.base);
- if (eflags & VM_FLAG)
+ if (cpu_state.eflags & VM_FLAG)
{
loadcs(new_cs);
set_use32(0);
// if (output) pclog("new_cs %04X\n",new_cs);
CS=new_cs;
- do_seg_load(&_cs, segdat2);
+ do_seg_load(&cpu_state.seg_cs, segdat2);
if (CPL==3 && oldcpl!=3) flushmmucache_cr3();
+ oldcpl = CPL;
set_use32(segdat2[3] & 0x40);
cpu_cur_status &= ~CPU_STATUS_V86;
}
EDI=new_edi;
if (output) pclog("Load ES %04X\n",new_es);
- loadseg(new_es,&_es);
+ loadseg(new_es,&cpu_state.seg_es);
if (output) pclog("Load SS %04X\n",new_ss);
- loadseg(new_ss,&_ss);
+ loadseg(new_ss,&cpu_state.seg_ss);
if (output) pclog("Load DS %04X\n",new_ds);
- loadseg(new_ds,&_ds);
+ loadseg(new_ds,&cpu_state.seg_ds);
if (output) pclog("Load FS %04X\n",new_fs);
- loadseg(new_fs,&_fs);
+ loadseg(new_fs,&cpu_state.seg_fs);
if (output) pclog("Load GS %04X\n",new_gs);
- loadseg(new_gs,&_gs);
+ loadseg(new_gs,&cpu_state.seg_gs);
if (output) pclog("Resuming at %04X:%08X\n",CS,cpu_state.pc);
}
}
if (cpu_state.abrt) return;
- if (optype==IRET) flags&=~NT_FLAG;
+ if (optype == IRET)
+ cpu_state.flags &= ~NT_FLAG;
// if (output) pclog("Write PC %08X %08X\n",tr.base,pc);
cpu_386_flags_rebuild();
writememw(tr.base,0x0E,cpu_state.pc);
- writememw(tr.base,0x10,flags);
+ writememw(tr.base,0x10,cpu_state.flags);
writememw(tr.base,0x12,AX);
writememw(tr.base,0x14,CX);
cpu_state.pc=new_pc;
// if (output) pclog("New pc %08X\n",new_pc);
- flags=new_flags;
+ cpu_state.flags = new_flags;
cpu_386_flags_extract();
// if (output) pclog("Load LDT %04X\n",new_ldt);
// if (output) pclog("new_cs %04X\n",new_cs);
CS=new_cs;
- do_seg_load(&_cs, segdat2);
+ do_seg_load(&cpu_state.seg_cs, segdat2);
if (CPL==3 && oldcpl!=3) flushmmucache_cr3();
+ oldcpl = CPL;
set_use32(0);
EAX=new_eax | 0xFFFF0000;
EDI=new_edi | 0xFFFF0000;
if (output) pclog("Load ES %04X\n",new_es);
- loadseg(new_es,&_es);
+ loadseg(new_es,&cpu_state.seg_es);
if (output) pclog("Load SS %04X\n",new_ss);
- loadseg(new_ss,&_ss);
+ loadseg(new_ss,&cpu_state.seg_ss);
if (output) pclog("Load DS %04X\n",new_ds);
- loadseg(new_ds,&_ds);
+ loadseg(new_ds,&cpu_state.seg_ds);
if (is386)
{
- loadseg(0,&_fs);
- loadseg(0,&_gs);
+ loadseg(0,&cpu_state.seg_fs);
+ loadseg(0,&cpu_state.seg_gs);
}
if (output) pclog("Resuming at %04X:%08X\n",CS,cpu_state.pc);
#include "x87.h"
#include "386_common.h"
+#define X87_TAG_VALID 0
+#define X87_TAG_ZERO 1
+#define X87_TAG_INVALID 2
+#define X87_TAG_EMPTY 3
+
uint16_t x87_gettag()
{
uint16_t ret = 0;
for (c = 0; c < 8; c++)
{
- if (cpu_state.tag[c] & TAG_UINT64)
+ if (cpu_state.tag[c] == TAG_EMPTY)
+ ret |= X87_TAG_EMPTY << (c * 2);
+ else if (cpu_state.tag[c] & TAG_UINT64)
ret |= 2 << (c*2);
+ else if (cpu_state.ST[c] == 0.0 && !cpu_state.ismmx)
+ ret |= X87_TAG_ZERO << (c * 2);
else
- ret |= (cpu_state.tag[c] << (c*2));
+ ret |= X87_TAG_VALID << (c * 2);
}
return ret;
void x87_settag(uint16_t new_tag)
{
- cpu_state.tag[0] = new_tag & 3;
- cpu_state.tag[1] = (new_tag >> 2) & 3;
- cpu_state.tag[2] = (new_tag >> 4) & 3;
- cpu_state.tag[3] = (new_tag >> 6) & 3;
- cpu_state.tag[4] = (new_tag >> 8) & 3;
- cpu_state.tag[5] = (new_tag >> 10) & 3;
- cpu_state.tag[6] = (new_tag >> 12) & 3;
- cpu_state.tag[7] = (new_tag >> 14) & 3;
+ int c;
+
+ for (c = 0; c < 8; c++)
+ {
+ int tag = (new_tag >> (c * 2)) & 3;
+
+ if (tag == X87_TAG_EMPTY)
+ cpu_state.tag[c] = TAG_EMPTY;
+ else if (tag == 2)
+ cpu_state.tag[c] = TAG_VALID | TAG_UINT64;
+ else
+ cpu_state.tag[c] = TAG_VALID;
+ }
}
void x87_dumpregs()
}
else
{
- pclog("ST(0)=%f\tST(1)=%f\tST(2)=%f\tST(3)=%f\t\n",cpu_state.ST[cpu_state.TOP],cpu_state.ST[(cpu_state.TOP+1)&7],cpu_state.ST[(cpu_state.TOP+2)&7],cpu_state.ST[(cpu_state.TOP+3)&7]);
+ pclog("ST(0)=%f\tST(1)=%f\tST(2)=%f\tST(3)=%f\t\n",cpu_state.ST[cpu_state.TOP&7],cpu_state.ST[(cpu_state.TOP+1)&7],cpu_state.ST[(cpu_state.TOP+2)&7],cpu_state.ST[(cpu_state.TOP+3)&7]);
pclog("ST(4)=%f\tST(5)=%f\tST(6)=%f\tST(7)=%f\t\n",cpu_state.ST[(cpu_state.TOP+4)&7],cpu_state.ST[(cpu_state.TOP+5)&7],cpu_state.ST[(cpu_state.TOP+6)&7],cpu_state.ST[(cpu_state.TOP+7)&7]);
}
pclog("Status = %04X Control = %04X Tag = %04X\n", cpu_state.npxs, cpu_state.npxc, x87_gettag());
-extern uint32_t x87_pc_off,x87_op_off;
-extern uint16_t x87_pc_seg,x87_op_seg;
+#define C0 (1<<8)
+#define C1 (1<<9)
+#define C2 (1<<10)
+#define C3 (1<<14)
+
+uint32_t x87_pc_off,x87_op_off;
+uint16_t x87_pc_seg,x87_op_seg;
static inline void x87_set_mmx()
{
cpu_state.TOP = 0;
- *(uint64_t *)cpu_state.tag = 0;
+ *(uint64_t *)cpu_state.tag = 0x0101010101010101ull;
cpu_state.ismmx = 1;
}
static inline void x87_emms()
{
- *(uint64_t *)cpu_state.tag = 0x0303030303030303ll;
+ *(uint64_t *)cpu_state.tag = 0;
cpu_state.ismmx = 0;
}
void x87_dumpregs();
void x87_reset();
+#define TAG_EMPTY 0
+#define TAG_VALID (1 << 0)
/*Hack for FPU copy. If set then MM[].q contains the 64-bit integer loaded by FILD*/
-#define TAG_UINT64 (1 << 2)
+#define TAG_UINT64 (1 << 7)
+
+#define X87_ROUNDING_NEAREST 0
+#define X87_ROUNDING_DOWN 1
+#define X87_ROUNDING_UP 2
+#define X87_ROUNDING_CHOP 3
+
+void codegen_set_rounding_mode(int mode);
#include <math.h>
#include <fenv.h>
+#include "x87_timings.h"
#define fplog 0
#define ST(x) cpu_state.ST[((cpu_state.TOP+(x))&7)]
-#define C0 (1<<8)
-#define C1 (1<<9)
-#define C2 (1<<10)
-#define C3 (1<<14)
-
#define STATUS_ZERODIVIDE 4
+#define FPCW_DISI (1 << 7)
+
#define x87_div(dst, src1, src2) do \
{ \
if (((double)src2) == 0.0) \
{ \
- cpu_state.npxs |= STATUS_ZERODIVIDE; \
- if (cpu_state.npxc & STATUS_ZERODIVIDE) \
+ cpu_state.npxs |= STATUS_ZERODIVIDE; \
+ if (cpu_state.npxc & STATUS_ZERODIVIDE) \
dst = src1 / (double)src2; \
else \
{ \
pclog("FPU : divide by zero\n"); \
picint(1 << 13); \
+ return 1; \
} \
- return 1; \
} \
else \
dst = src1 / (double)src2; \
static inline void x87_push(double i)
{
- cpu_state.TOP=(cpu_state.TOP-1)&7;
- cpu_state.ST[cpu_state.TOP] = i;
- cpu_state.tag[cpu_state.TOP&7] = (i == 0.0) ? 1 : 0;
+ cpu_state.TOP--;
+ cpu_state.ST[cpu_state.TOP&7] = i;
+ cpu_state.tag[cpu_state.TOP&7] = TAG_VALID;
}
static inline void x87_push_u64(uint64_t i)
td.ll = i;
- cpu_state.TOP=(cpu_state.TOP-1)&7;
- cpu_state.ST[cpu_state.TOP] = td.d;
- cpu_state.tag[cpu_state.TOP&7] = (td.d == 0.0) ? 1 : 0;
+ cpu_state.TOP--;
+ cpu_state.ST[cpu_state.TOP&7] = td.d;
+ cpu_state.tag[cpu_state.TOP&7] = TAG_VALID;
}
static inline double x87_pop()
{
- double t = cpu_state.ST[cpu_state.TOP];
- cpu_state.tag[cpu_state.TOP&7] = 3;
- cpu_state.TOP=(cpu_state.TOP+1)&7;
+ double t = cpu_state.ST[cpu_state.TOP&7];
+ cpu_state.tag[cpu_state.TOP&7] = TAG_EMPTY;
+ cpu_state.TOP++;
return t;
}
cpu_state.MM[reg].q = readmemq(easeg, cpu_state.eaaddr);
cpu_state.MM_w4[reg] = readmemw(easeg, cpu_state.eaaddr + 8);
- if (cpu_state.MM_w4[reg] == 0x5555 && cpu_state.tag[reg] == 2)
+ if ((cpu_state.MM_w4[reg] == 0x5555) && (cpu_state.tag[reg] & TAG_UINT64))
{
- cpu_state.tag[reg] = TAG_UINT64;
cpu_state.ST[reg] = (double)cpu_state.MM[reg].q;
}
else
+ {
+ cpu_state.tag[reg] &= ~TAG_UINT64;
cpu_state.ST[reg] = x87_ld80();
+ }
}
static inline void x87_ldmmx(MMX_REG *r, uint16_t *w4)
static inline uint16_t x87_compare(double a, double b)
{
-#if 0 //defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined WIN32 || defined _WIN32 || defined _WIN32
+#if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined WIN32 || defined _WIN32 || defined _WIN32 || defined __amd64__
uint32_t out;
/* Memory barrier, to force GCC to write to the input parameters
static inline uint16_t x87_ucompare(double a, double b)
{
-#if 0 //defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined WIN32 || defined _WIN32 || defined _WIN32
+#if defined i386 || defined __i386 || defined __i386__ || defined _X86_ || defined WIN32 || defined _WIN32 || defined _WIN32 || defined __amd64__
uint32_t out;
/* Memory barrier, to force GCC to write to the input parameters
uint64_t i;
} x87_td;
+#ifdef X8087
+#define FP_ENTER() fpucount++
+#else
#define FP_ENTER() do \
{ \
if (cr0 & 0xc) \
} \
fpucount++; \
} while (0)
+#endif
#include "x87_ops_arith.h"
#include "x87_ops_misc.h"
ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
- ILLEGAL, opFNOP, opFCLEX, opFINIT, opFNOP, opFNOP, ILLEGAL, ILLEGAL,
+ opFENI, opFDISI, opFCLEX, opFINIT, opFNOP, opFNOP, ILLEGAL, ILLEGAL,
ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
- ILLEGAL, opFNOP, opFCLEX, opFINIT, opFNOP, opFNOP, ILLEGAL, ILLEGAL,
+ opFENI, opFDISI, opFCLEX, opFINIT, opFNOP, opFNOP, ILLEGAL, ILLEGAL,
ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
-#define opFPU(name, optype, a_size, load_var, get, use_var) \
+#define opFPU(name, optype, a_size, load_var, get, use_var, cycle_postfix) \
static int opFADD ## name ## _a ## a_size(uint32_t fetchdat) \
{ \
optype t; \
FP_ENTER(); \
fetch_ea_ ## a_size(fetchdat); \
+ SEG_CHECK_READ(cpu_state.ea_seg); \
load_var = get(); if (cpu_state.abrt) return 1; \
if ((cpu_state.npxc >> 10) & 3) \
fesetround(rounding_modes[(cpu_state.npxc >> 10) & 3]); \
ST(0) += use_var; \
if ((cpu_state.npxc >> 10) & 3) \
fesetround(FE_TONEAREST); \
- cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; \
- CLOCK_CYCLES(8); \
+ cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; \
+ CLOCK_CYCLES(x87_timings.fadd ## cycle_postfix); \
return 0; \
} \
static int opFCOM ## name ## _a ## a_size(uint32_t fetchdat) \
optype t; \
FP_ENTER(); \
fetch_ea_ ## a_size(fetchdat); \
+ SEG_CHECK_READ(cpu_state.ea_seg); \
load_var = get(); if (cpu_state.abrt) return 1; \
cpu_state.npxs &= ~(C0|C2|C3); \
cpu_state.npxs |= x87_compare(ST(0), (double)use_var); \
- CLOCK_CYCLES(4); \
+ CLOCK_CYCLES(x87_timings.fcom ## cycle_postfix); \
return 0; \
} \
static int opFCOMP ## name ## _a ## a_size(uint32_t fetchdat) \
optype t; \
FP_ENTER(); \
fetch_ea_ ## a_size(fetchdat); \
+ SEG_CHECK_READ(cpu_state.ea_seg); \
load_var = get(); if (cpu_state.abrt) return 1; \
cpu_state.npxs &= ~(C0|C2|C3); \
cpu_state.npxs |= x87_compare(ST(0), (double)use_var); \
x87_pop(); \
- CLOCK_CYCLES(4); \
+ CLOCK_CYCLES(x87_timings.fcom ## cycle_postfix); \
return 0; \
} \
static int opFDIV ## name ## _a ## a_size(uint32_t fetchdat) \
optype t; \
FP_ENTER(); \
fetch_ea_ ## a_size(fetchdat); \
+ SEG_CHECK_READ(cpu_state.ea_seg); \
load_var = get(); if (cpu_state.abrt) return 1; \
x87_div(ST(0), ST(0), use_var); \
- cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; \
- CLOCK_CYCLES(73); \
+ cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; \
+ CLOCK_CYCLES(x87_timings.fdiv ## cycle_postfix); \
return 0; \
} \
static int opFDIVR ## name ## _a ## a_size(uint32_t fetchdat) \
optype t; \
FP_ENTER(); \
fetch_ea_ ## a_size(fetchdat); \
+ SEG_CHECK_READ(cpu_state.ea_seg); \
load_var = get(); if (cpu_state.abrt) return 1; \
x87_div(ST(0), use_var, ST(0)); \
- cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; \
- CLOCK_CYCLES(73); \
+ cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; \
+ CLOCK_CYCLES(x87_timings.fdiv ## cycle_postfix); \
return 0; \
} \
static int opFMUL ## name ## _a ## a_size(uint32_t fetchdat) \
optype t; \
FP_ENTER(); \
fetch_ea_ ## a_size(fetchdat); \
+ SEG_CHECK_READ(cpu_state.ea_seg); \
load_var = get(); if (cpu_state.abrt) return 1; \
ST(0) *= use_var; \
- cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; \
- CLOCK_CYCLES(11); \
+ cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; \
+ CLOCK_CYCLES(x87_timings.fmul ## cycle_postfix); \
return 0; \
} \
static int opFSUB ## name ## _a ## a_size(uint32_t fetchdat) \
optype t; \
FP_ENTER(); \
fetch_ea_ ## a_size(fetchdat); \
+ SEG_CHECK_READ(cpu_state.ea_seg); \
load_var = get(); if (cpu_state.abrt) return 1; \
ST(0) -= use_var; \
- cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; \
- CLOCK_CYCLES(8); \
+ cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; \
+ CLOCK_CYCLES(x87_timings.fadd ## cycle_postfix); \
return 0; \
} \
static int opFSUBR ## name ## _a ## a_size(uint32_t fetchdat) \
optype t; \
FP_ENTER(); \
fetch_ea_ ## a_size(fetchdat); \
+ SEG_CHECK_READ(cpu_state.ea_seg); \
load_var = get(); if (cpu_state.abrt) return 1; \
ST(0) = use_var - ST(0); \
- cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64; \
- CLOCK_CYCLES(8); \
+ cpu_state.tag[cpu_state.TOP&7] = TAG_VALID; \
+ CLOCK_CYCLES(x87_timings.fadd ## cycle_postfix); \
return 0; \
}
-opFPU(s, x87_ts, 16, t.i, geteal, t.s)
-opFPU(s, x87_ts, 32, t.i, geteal, t.s)
-opFPU(d, x87_td, 16, t.i, geteaq, t.d)
-opFPU(d, x87_td, 32, t.i, geteaq, t.d)
+opFPU(s, x87_ts, 16, t.i, geteal, t.s, _32)
+opFPU(s, x87_ts, 32, t.i, geteal, t.s, _32)
+opFPU(d, x87_td, 16, t.i, geteaq, t.d, _64)
+opFPU(d, x87_td, 32, t.i, geteaq, t.d, _64)
-opFPU(iw, uint16_t, 16, t, geteaw, (double)(int16_t)t)
-opFPU(iw, uint16_t, 32, t, geteaw, (double)(int16_t)t)
-opFPU(il, uint32_t, 16, t, geteal, (double)(int32_t)t)
-opFPU(il, uint32_t, 32, t, geteal, (double)(int32_t)t)
+opFPU(iw, uint16_t, 16, t, geteaw, (double)(int16_t)t, _i16)
+opFPU(iw, uint16_t, 32, t, geteaw, (double)(int16_t)t, _i16)
+opFPU(il, uint32_t, 16, t, geteal, (double)(int32_t)t, _i32)
+opFPU(il, uint32_t, 32, t, geteal, (double)(int32_t)t, _i32)
cpu_state.pc++;
if (fplog) pclog("FADD\n");
ST(0) = ST(0) + ST(fetchdat & 7);
- cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64;
- CLOCK_CYCLES(8);
+ cpu_state.tag[cpu_state.TOP&7] = TAG_VALID;
+ CLOCK_CYCLES(x87_timings.fadd);
return 0;
}
static int opFADDr(uint32_t fetchdat)
cpu_state.pc++;
if (fplog) pclog("FADD\n");
ST(fetchdat & 7) = ST(fetchdat & 7) + ST(0);
- cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] &= ~TAG_UINT64;
- CLOCK_CYCLES(8);
+ cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID;
+ CLOCK_CYCLES(x87_timings.fadd);
return 0;
}
static int opFADDP(uint32_t fetchdat)
cpu_state.pc++;
if (fplog) pclog("FADDP\n");
ST(fetchdat & 7) = ST(fetchdat & 7) + ST(0);
- cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] &= ~TAG_UINT64;
+ cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID;
x87_pop();
- CLOCK_CYCLES(8);
+ CLOCK_CYCLES(x87_timings.fadd);
return 0;
}
cpu_state.npxs &= ~(C0|C2|C3);
if (ST(0) == ST(fetchdat & 7)) cpu_state.npxs |= C3;
else if (ST(0) < ST(fetchdat & 7)) cpu_state.npxs |= C0;
- CLOCK_CYCLES(4);
+ CLOCK_CYCLES(x87_timings.fadd);
return 0;
}
cpu_state.npxs &= ~(C0|C2|C3);
cpu_state.npxs |= x87_compare(ST(0), ST(fetchdat & 7));
x87_pop();
- CLOCK_CYCLES(4);
+ CLOCK_CYCLES(x87_timings.fadd);
return 0;
}
x87_pop();
x87_pop();
- CLOCK_CYCLES(4);
+ CLOCK_CYCLES(x87_timings.fadd);
return 0;
}
static int opFUCOMPP(uint32_t fetchdat)
cpu_state.npxs |= x87_ucompare(ST(0), ST(1));
x87_pop();
x87_pop();
- CLOCK_CYCLES(5);
+ CLOCK_CYCLES(x87_timings.fucom);
return 0;
}
cpu_state.pc++;
if (fplog) pclog("FICOM\n");
flags_rebuild();
- flags &= ~(Z_FLAG | P_FLAG | C_FLAG);
- if (ST(0) == ST(fetchdat & 7)) flags |= Z_FLAG;
- else if (ST(0) < ST(fetchdat & 7)) flags |= C_FLAG;
- CLOCK_CYCLES(4);
+ cpu_state.flags &= ~(Z_FLAG | P_FLAG | C_FLAG);
+ if (ST(0) == ST(fetchdat & 7)) cpu_state.flags |= Z_FLAG;
+ else if (ST(0) < ST(fetchdat & 7)) cpu_state.flags |= C_FLAG;
+ CLOCK_CYCLES(x87_timings.fcom);
return 0;
}
static int opFCOMIP(uint32_t fetchdat)
cpu_state.pc++;
if (fplog) pclog("FICOMP\n");
flags_rebuild();
- flags &= ~(Z_FLAG | P_FLAG | C_FLAG);
- if (ST(0) == ST(fetchdat & 7)) flags |= Z_FLAG;
- else if (ST(0) < ST(fetchdat & 7)) flags |= C_FLAG;
+ cpu_state.flags &= ~(Z_FLAG | P_FLAG | C_FLAG);
+ if (ST(0) == ST(fetchdat & 7)) cpu_state.flags |= Z_FLAG;
+ else if (ST(0) < ST(fetchdat & 7)) cpu_state.flags |= C_FLAG;
x87_pop();
- CLOCK_CYCLES(4);
+ CLOCK_CYCLES(x87_timings.fcom);
return 0;
}
cpu_state.pc++;
if (fplog) pclog("FDIV\n");
x87_div(ST(0), ST(0), ST(fetchdat & 7));
- cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64;
- CLOCK_CYCLES(73);
+ cpu_state.tag[cpu_state.TOP&7] = TAG_VALID;
+ CLOCK_CYCLES(x87_timings.fdiv);
return 0;
}
static int opFDIVr(uint32_t fetchdat)
cpu_state.pc++;
if (fplog) pclog("FDIV\n");
x87_div(ST(fetchdat & 7), ST(fetchdat & 7), ST(0));
- cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] &= ~TAG_UINT64;
- CLOCK_CYCLES(73);
+ cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID;
+ CLOCK_CYCLES(x87_timings.fdiv);
return 0;
}
static int opFDIVP(uint32_t fetchdat)
cpu_state.pc++;
if (fplog) pclog("FDIVP\n");
x87_div(ST(fetchdat & 7), ST(fetchdat & 7), ST(0));
- cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] &= ~TAG_UINT64;
+ cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID;
x87_pop();
- CLOCK_CYCLES(73);
+ CLOCK_CYCLES(x87_timings.fdiv);
return 0;
}
cpu_state.pc++;
if (fplog) pclog("FDIVR\n");
x87_div(ST(0), ST(fetchdat&7), ST(0));
- cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64;
- CLOCK_CYCLES(73);
+ cpu_state.tag[cpu_state.TOP&7] = TAG_VALID;
+ CLOCK_CYCLES(x87_timings.fdiv);
return 0;
}
static int opFDIVRr(uint32_t fetchdat)
cpu_state.pc++;
if (fplog) pclog("FDIVR\n");
x87_div(ST(fetchdat & 7), ST(0), ST(fetchdat & 7));
- cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] &= ~TAG_UINT64;
- CLOCK_CYCLES(73);
+ cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID;
+ CLOCK_CYCLES(x87_timings.fdiv);
return 0;
}
static int opFDIVRP(uint32_t fetchdat)
cpu_state.pc++;
if (fplog) pclog("FDIVR\n");
x87_div(ST(fetchdat & 7), ST(0), ST(fetchdat & 7));
- cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] &= ~TAG_UINT64;
+ cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID;
x87_pop();
- CLOCK_CYCLES(73);
+ CLOCK_CYCLES(x87_timings.fdiv);
return 0;
}
cpu_state.pc++;
if (fplog) pclog("FMUL\n");
ST(0) = ST(0) * ST(fetchdat & 7);
- cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64;
- CLOCK_CYCLES(16);
+ cpu_state.tag[cpu_state.TOP&7] = TAG_VALID;
+ CLOCK_CYCLES(x87_timings.fmul);
return 0;
}
static int opFMULr(uint32_t fetchdat)
cpu_state.pc++;
if (fplog) pclog("FMUL\n");
ST(fetchdat & 7) = ST(0) * ST(fetchdat & 7);
- cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] &= ~TAG_UINT64;
- CLOCK_CYCLES(16);
+ cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID;
+ CLOCK_CYCLES(x87_timings.fmul);
return 0;
}
static int opFMULP(uint32_t fetchdat)
cpu_state.pc++;
if (fplog) pclog("FMULP\n");
ST(fetchdat & 7) = ST(0) * ST(fetchdat & 7);
- cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] &= ~TAG_UINT64;
+ cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID;
x87_pop();
- CLOCK_CYCLES(16);
+ CLOCK_CYCLES(x87_timings.fmul);
return 0;
}
cpu_state.pc++;
if (fplog) pclog("FSUB\n");
ST(0) = ST(0) - ST(fetchdat & 7);
- cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64;
- CLOCK_CYCLES(8);
+ cpu_state.tag[cpu_state.TOP&7] = TAG_VALID;
+ CLOCK_CYCLES(x87_timings.fadd);
return 0;
}
static int opFSUBr(uint32_t fetchdat)
cpu_state.pc++;
if (fplog) pclog("FSUB\n");
ST(fetchdat & 7) = ST(fetchdat & 7) - ST(0);
- cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] &= ~TAG_UINT64;
- CLOCK_CYCLES(8);
+ cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID;
+ CLOCK_CYCLES(x87_timings.fadd);
return 0;
}
static int opFSUBP(uint32_t fetchdat)
cpu_state.pc++;
if (fplog) pclog("FSUBP\n");
ST(fetchdat & 7) = ST(fetchdat & 7) - ST(0);
- cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] &= ~TAG_UINT64;
+ cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID;
x87_pop();
- CLOCK_CYCLES(8);
+ CLOCK_CYCLES(x87_timings.fadd);
return 0;
}
cpu_state.pc++;
if (fplog) pclog("FSUBR\n");
ST(0) = ST(fetchdat & 7) - ST(0);
- cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64;
- CLOCK_CYCLES(8);
+ cpu_state.tag[cpu_state.TOP&7] = TAG_VALID;
+ CLOCK_CYCLES(x87_timings.fadd);
return 0;
}
static int opFSUBRr(uint32_t fetchdat)
cpu_state.pc++;
if (fplog) pclog("FSUBR\n");
ST(fetchdat & 7) = ST(0) - ST(fetchdat & 7);
- cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] &= ~TAG_UINT64;
- CLOCK_CYCLES(8);
+ cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID;
+ CLOCK_CYCLES(x87_timings.fadd);
return 0;
}
static int opFSUBRP(uint32_t fetchdat)
cpu_state.pc++;
if (fplog) pclog("FSUBRP\n");
ST(fetchdat & 7) = ST(0) - ST(fetchdat & 7);
- cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] &= ~TAG_UINT64;
+ cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_VALID;
x87_pop();
- CLOCK_CYCLES(8);
+ CLOCK_CYCLES(x87_timings.fadd);
return 0;
}
if (fplog) pclog("FUCOM\n");
cpu_state.npxs &= ~(C0|C2|C3);
cpu_state.npxs |= x87_ucompare(ST(0), ST(fetchdat & 7));
- CLOCK_CYCLES(4);
+ CLOCK_CYCLES(x87_timings.fucom);
return 0;
}
cpu_state.npxs &= ~(C0|C2|C3);
cpu_state.npxs |= x87_ucompare(ST(0), ST(fetchdat & 7));
x87_pop();
- CLOCK_CYCLES(4);
+ CLOCK_CYCLES(x87_timings.fucom);
return 0;
}
cpu_state.pc++;
if (fplog) pclog("FUCOMI\n");
flags_rebuild();
- flags &= ~(Z_FLAG | P_FLAG | C_FLAG);
- if (ST(0) == ST(fetchdat & 7)) flags |= Z_FLAG;
- else if (ST(0) < ST(fetchdat & 7)) flags |= C_FLAG;
- CLOCK_CYCLES(4);
+ cpu_state.flags &= ~(Z_FLAG | P_FLAG | C_FLAG);
+ if (ST(0) == ST(fetchdat & 7)) cpu_state.flags |= Z_FLAG;
+ else if (ST(0) < ST(fetchdat & 7)) cpu_state.flags |= C_FLAG;
+ CLOCK_CYCLES(x87_timings.fucom);
return 0;
}
static int opFUCOMIP(uint32_t fetchdat)
cpu_state.pc++;
if (fplog) pclog("FUCOMIP\n");
flags_rebuild();
- flags &= ~(Z_FLAG | P_FLAG | C_FLAG);
- if (ST(0) == ST(fetchdat & 7)) flags |= Z_FLAG;
- else if (ST(0) < ST(fetchdat & 7)) flags |= C_FLAG;
+ cpu_state.flags &= ~(Z_FLAG | P_FLAG | C_FLAG);
+ if (ST(0) == ST(fetchdat & 7)) cpu_state.flags |= Z_FLAG;
+ else if (ST(0) < ST(fetchdat & 7)) cpu_state.flags |= C_FLAG;
x87_pop();
- CLOCK_CYCLES(4);
+ CLOCK_CYCLES(x87_timings.fucom);
return 0;
}
int16_t temp;
FP_ENTER();
fetch_ea_16(fetchdat);
+ SEG_CHECK_READ(cpu_state.ea_seg);
if (fplog) pclog("FILDw %08X:%08X\n", easeg, cpu_state.eaaddr);
temp = geteaw(); if (cpu_state.abrt) return 1;
if (fplog) pclog(" %f\n", (double)temp);
x87_push((double)temp);
- CLOCK_CYCLES(13);
+ CLOCK_CYCLES(x87_timings.fild_16);
return 0;
}
static int opFILDiw_a32(uint32_t fetchdat)
int16_t temp;
FP_ENTER();
fetch_ea_32(fetchdat);
+ SEG_CHECK_READ(cpu_state.ea_seg);
if (fplog) pclog("FILDw %08X:%08X\n", easeg, cpu_state.eaaddr);
temp = geteaw(); if (cpu_state.abrt) return 1;
if (fplog) pclog(" %f\n", (double)temp);
x87_push((double)temp);
- CLOCK_CYCLES(13);
+ CLOCK_CYCLES(x87_timings.fild_16);
return 0;
}
int64_t temp64;
FP_ENTER();
fetch_ea_16(fetchdat);
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
if (fplog) pclog("FISTw %08X:%08X\n", easeg, cpu_state.eaaddr);
temp64 = x87_fround(ST(0));
/* if (temp64 > 32767 || temp64 < -32768)
fatal("FISTw overflow %i\n", temp64);*/
seteaw((int16_t)temp64);
- CLOCK_CYCLES(29);
+ CLOCK_CYCLES(x87_timings.fist_16);
return cpu_state.abrt;
}
static int opFISTiw_a32(uint32_t fetchdat)
int64_t temp64;
FP_ENTER();
fetch_ea_32(fetchdat);
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
if (fplog) pclog("FISTw %08X:%08X\n", easeg, cpu_state.eaaddr);
temp64 = x87_fround(ST(0));
/* if (temp64 > 32767 || temp64 < -32768)
fatal("FISTw overflow %i\n", temp64);*/
seteaw((int16_t)temp64);
- CLOCK_CYCLES(29);
+ CLOCK_CYCLES(x87_timings.fist_16);
return cpu_state.abrt;
}
int64_t temp64;
FP_ENTER();
fetch_ea_16(fetchdat);
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
if (fplog) pclog("FISTw %08X:%08X\n", easeg, cpu_state.eaaddr);
temp64 = x87_fround(ST(0));
/* if (temp64 > 32767 || temp64 < -32768)
fatal("FISTw overflow %i\n", temp64);*/
seteaw((int16_t)temp64); if (cpu_state.abrt) return 1;
x87_pop();
- CLOCK_CYCLES(29);
+ CLOCK_CYCLES(x87_timings.fist_16);
return 0;
}
static int opFISTPiw_a32(uint32_t fetchdat)
int64_t temp64;
FP_ENTER();
fetch_ea_32(fetchdat);
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
if (fplog) pclog("FISTw %08X:%08X\n", easeg, cpu_state.eaaddr);
temp64 = x87_fround(ST(0));
/* if (temp64 > 32767 || temp64 < -32768)
fatal("FISTw overflow %i\n", temp64);*/
seteaw((int16_t)temp64); if (cpu_state.abrt) return 1;
x87_pop();
- CLOCK_CYCLES(29);
+ CLOCK_CYCLES(x87_timings.fist_16);
return 0;
}
int64_t temp64;
FP_ENTER();
fetch_ea_16(fetchdat);
+ SEG_CHECK_READ(cpu_state.ea_seg);
if (fplog) pclog("FILDl %08X:%08X\n", easeg, cpu_state.eaaddr);
temp64 = geteaq(); if (cpu_state.abrt) return 1;
if (fplog) pclog(" %f %08X %08X\n", (double)temp64, readmeml(easeg,cpu_state.eaaddr), readmeml(easeg,cpu_state.eaaddr+4));
x87_push((double)temp64);
- cpu_state.MM[cpu_state.TOP].q = temp64;
- cpu_state.tag[cpu_state.TOP] |= TAG_UINT64;
+ cpu_state.MM[cpu_state.TOP&7].q = temp64;
+ cpu_state.tag[cpu_state.TOP&7] = TAG_VALID | TAG_UINT64;
- CLOCK_CYCLES(10);
+ CLOCK_CYCLES(x87_timings.fild_64);
return 0;
}
static int opFILDiq_a32(uint32_t fetchdat)
int64_t temp64;
FP_ENTER();
fetch_ea_32(fetchdat);
+ SEG_CHECK_READ(cpu_state.ea_seg);
if (fplog) pclog("FILDl %08X:%08X\n", easeg, cpu_state.eaaddr);
temp64 = geteaq(); if (cpu_state.abrt) return 1;
if (fplog) pclog(" %f %08X %08X\n", (double)temp64, readmeml(easeg,cpu_state.eaaddr), readmeml(easeg,cpu_state.eaaddr+4));
x87_push((double)temp64);
- cpu_state.MM[cpu_state.TOP].q = temp64;
- cpu_state.tag[cpu_state.TOP] |= TAG_UINT64;
+ cpu_state.MM[cpu_state.TOP&7].q = temp64;
+ cpu_state.tag[cpu_state.TOP&7] = TAG_VALID | TAG_UINT64;
- CLOCK_CYCLES(10);
+ CLOCK_CYCLES(x87_timings.fild_64);
return 0;
}
int c;
FP_ENTER();
fetch_ea_16(fetchdat);
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
if (fplog) pclog("FBSTP %08X:%08X\n", easeg, cpu_state.eaaddr);
tempd = ST(0);
if (tempd < 0.0)
if (ST(0) < 0.0) tempc |= 0x80;
writememb(easeg, cpu_state.eaaddr + 9, tempc); if (cpu_state.abrt) return 1;
x87_pop();
+ CLOCK_CYCLES(x87_timings.fbstp);
return 0;
}
static int FBSTP_a32(uint32_t fetchdat)
int c;
FP_ENTER();
fetch_ea_32(fetchdat);
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
if (fplog) pclog("FBSTP %08X:%08X\n", easeg, cpu_state.eaaddr);
tempd = ST(0);
if (tempd < 0.0)
if (ST(0) < 0.0) tempc |= 0x80;
writememb(easeg, cpu_state.eaaddr + 9, tempc); if (cpu_state.abrt) return 1;
x87_pop();
+ CLOCK_CYCLES(x87_timings.fbstp);
return 0;
}
int64_t temp64;
FP_ENTER();
fetch_ea_16(fetchdat);
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
if (fplog) pclog("FISTPl %08X:%08X\n", easeg, cpu_state.eaaddr);
- if (cpu_state.tag[cpu_state.TOP] & TAG_UINT64)
- temp64 = cpu_state.MM[cpu_state.TOP].q;
+ if (cpu_state.tag[cpu_state.TOP&7] & TAG_UINT64)
+ temp64 = cpu_state.MM[cpu_state.TOP&7].q;
else
temp64 = x87_fround(ST(0));
seteaq(temp64); if (cpu_state.abrt) return 1;
x87_pop();
- CLOCK_CYCLES(29);
+ CLOCK_CYCLES(x87_timings.fist_64);
return 0;
}
static int FISTPiq_a32(uint32_t fetchdat)
int64_t temp64;
FP_ENTER();
fetch_ea_32(fetchdat);
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
if (fplog) pclog("FISTPl %08X:%08X\n", easeg, cpu_state.eaaddr);
- if (cpu_state.tag[cpu_state.TOP] & TAG_UINT64)
- temp64 = cpu_state.MM[cpu_state.TOP].q;
+ if (cpu_state.tag[cpu_state.TOP&7] & TAG_UINT64)
+ temp64 = cpu_state.MM[cpu_state.TOP&7].q;
else
temp64 = x87_fround(ST(0));
seteaq(temp64); if (cpu_state.abrt) return 1;
x87_pop();
- CLOCK_CYCLES(29);
+ CLOCK_CYCLES(x87_timings.fist_64);
return 0;
}
int32_t templ;
FP_ENTER();
fetch_ea_16(fetchdat);
+ SEG_CHECK_READ(cpu_state.ea_seg);
if (fplog) pclog("FILDs %08X:%08X\n", easeg, cpu_state.eaaddr);
templ = geteal(); if (cpu_state.abrt) return 1;
if (fplog) pclog(" %f %08X %i\n", (double)templ, templ, templ);
x87_push((double)templ);
- CLOCK_CYCLES(9);
+ CLOCK_CYCLES(x87_timings.fild_32);
return 0;
}
static int opFILDil_a32(uint32_t fetchdat)
int32_t templ;
FP_ENTER();
fetch_ea_32(fetchdat);
+ SEG_CHECK_READ(cpu_state.ea_seg);
if (fplog) pclog("FILDs %08X:%08X\n", easeg, cpu_state.eaaddr);
templ = geteal(); if (cpu_state.abrt) return 1;
if (fplog) pclog(" %f %08X %i\n", (double)templ, templ, templ);
x87_push((double)templ);
- CLOCK_CYCLES(9);
+ CLOCK_CYCLES(x87_timings.fild_32);
return 0;
}
int64_t temp64;
FP_ENTER();
fetch_ea_16(fetchdat);
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
if (fplog) pclog("FISTs %08X:%08X\n", easeg, cpu_state.eaaddr);
temp64 = x87_fround(ST(0));
/* if (temp64 > 2147483647 || temp64 < -2147483647)
fatal("FISTl out of range! %i\n", temp64);*/
seteal((int32_t)temp64);
- CLOCK_CYCLES(28);
+ CLOCK_CYCLES(x87_timings.fist_32);
return cpu_state.abrt;
}
static int opFISTil_a32(uint32_t fetchdat)
int64_t temp64;
FP_ENTER();
fetch_ea_32(fetchdat);
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
if (fplog) pclog("FISTs %08X:%08X\n", easeg, cpu_state.eaaddr);
temp64 = x87_fround(ST(0));
/* if (temp64 > 2147483647 || temp64 < -2147483647)
fatal("FISTl out of range! %i\n", temp64);*/
seteal((int32_t)temp64);
- CLOCK_CYCLES(28);
+ CLOCK_CYCLES(x87_timings.fist_32);
return cpu_state.abrt;
}
int64_t temp64;
FP_ENTER();
fetch_ea_16(fetchdat);
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
if (fplog) pclog("FISTs %08X:%08X\n", easeg, cpu_state.eaaddr);
temp64 = x87_fround(ST(0));
/* if (temp64 > 2147483647 || temp64 < -2147483647)
fatal("FISTl out of range! %i\n", temp64);*/
seteal((int32_t)temp64); if (cpu_state.abrt) return 1;
x87_pop();
- CLOCK_CYCLES(28);
+ CLOCK_CYCLES(x87_timings.fist_32);
return 0;
}
static int opFISTPil_a32(uint32_t fetchdat)
int64_t temp64;
FP_ENTER();
fetch_ea_32(fetchdat);
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
if (fplog) pclog("FISTs %08X:%08X\n", easeg, cpu_state.eaaddr);
temp64 = x87_fround(ST(0));
/* if (temp64 > 2147483647 || temp64 < -2147483647)
fatal("FISTl out of range! %i\n", temp64);*/
seteal((int32_t)temp64); if (cpu_state.abrt) return 1;
x87_pop();
- CLOCK_CYCLES(28);
+ CLOCK_CYCLES(x87_timings.fist_32);
return 0;
}
double t;
FP_ENTER();
fetch_ea_16(fetchdat);
+ SEG_CHECK_READ(cpu_state.ea_seg);
if (fplog) pclog("FLDe %08X:%08X\n", easeg, cpu_state.eaaddr);
t=x87_ld80(); if (cpu_state.abrt) return 1;
if (fplog) pclog(" %f\n", t);
x87_push(t);
- CLOCK_CYCLES(6);
+ CLOCK_CYCLES(x87_timings.fld_80);
return 0;
}
static int opFLDe_a32(uint32_t fetchdat)
double t;
FP_ENTER();
fetch_ea_32(fetchdat);
+ SEG_CHECK_READ(cpu_state.ea_seg);
if (fplog) pclog("FLDe %08X:%08X\n", easeg, cpu_state.eaaddr);
t=x87_ld80(); if (cpu_state.abrt) return 1;
if (fplog) pclog(" %f\n", t);
x87_push(t);
- CLOCK_CYCLES(6);
+ CLOCK_CYCLES(x87_timings.fld_80);
return 0;
}
{
FP_ENTER();
fetch_ea_16(fetchdat);
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
if (fplog) pclog("FSTPe %08X:%08X\n", easeg, cpu_state.eaaddr);
x87_st80(ST(0)); if (cpu_state.abrt) return 1;
x87_pop();
- CLOCK_CYCLES(6);
+ CLOCK_CYCLES(x87_timings.fst_80);
return 0;
}
static int opFSTPe_a32(uint32_t fetchdat)
{
FP_ENTER();
fetch_ea_32(fetchdat);
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
if (fplog) pclog("FSTPe %08X:%08X\n", easeg, cpu_state.eaaddr);
x87_st80(ST(0)); if (cpu_state.abrt) return 1;
x87_pop();
- CLOCK_CYCLES(6);
+ CLOCK_CYCLES(x87_timings.fst_80);
return 0;
}
x87_td t;
FP_ENTER();
fetch_ea_16(fetchdat);
+ SEG_CHECK_READ(cpu_state.ea_seg);
if (fplog) pclog("FLDd %08X:%08X\n", easeg, cpu_state.eaaddr);
t.i = geteaq(); if (cpu_state.abrt) return 1;
if (fplog) pclog(" %f\n", t.d);
x87_push(t.d);
- CLOCK_CYCLES(3);
+ CLOCK_CYCLES(x87_timings.fld_64);
return 0;
}
static int opFLDd_a32(uint32_t fetchdat)
x87_td t;
FP_ENTER();
fetch_ea_32(fetchdat);
+ SEG_CHECK_READ(cpu_state.ea_seg);
if (fplog) pclog("FLDd %08X:%08X\n", easeg, cpu_state.eaaddr);
t.i = geteaq(); if (cpu_state.abrt) return 1;
if (fplog) pclog(" %f\n", t.d);
x87_push(t.d);
- CLOCK_CYCLES(3);
+ CLOCK_CYCLES(x87_timings.fld_64);
return 0;
}
x87_td t;
FP_ENTER();
fetch_ea_16(fetchdat);
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
if (fplog) pclog("FSTd %08X:%08X\n", easeg, cpu_state.eaaddr);
t.d = ST(0);
seteaq(t.i);
- CLOCK_CYCLES(8);
+ CLOCK_CYCLES(x87_timings.fst_64);
return cpu_state.abrt;
}
static int opFSTd_a32(uint32_t fetchdat)
x87_td t;
FP_ENTER();
fetch_ea_32(fetchdat);
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
if (fplog) pclog("FSTd %08X:%08X\n", easeg, cpu_state.eaaddr);
t.d = ST(0);
seteaq(t.i);
- CLOCK_CYCLES(8);
+ CLOCK_CYCLES(x87_timings.fst_64);
return cpu_state.abrt;
}
x87_td t;
FP_ENTER();
fetch_ea_16(fetchdat);
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
CHECK_WRITE(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 7);
if (fplog) pclog("FSTd %08X:%08X\n", easeg, cpu_state.eaaddr);
t.d = ST(0);
seteaq(t.i); if (cpu_state.abrt) return 1;
x87_pop();
- CLOCK_CYCLES(8);
+ CLOCK_CYCLES(x87_timings.fst_64);
return 0;
}
static int opFSTPd_a32(uint32_t fetchdat)
x87_td t;
FP_ENTER();
fetch_ea_32(fetchdat);
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
CHECK_WRITE(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 7);
if (fplog) pclog("FSTd %08X:%08X\n", easeg, cpu_state.eaaddr);
t.d = ST(0);
seteaq(t.i); if (cpu_state.abrt) return 1;
x87_pop();
- CLOCK_CYCLES(8);
+ CLOCK_CYCLES(x87_timings.fst_64);
return 0;
}
x87_ts ts;
FP_ENTER();
fetch_ea_16(fetchdat);
+ SEG_CHECK_READ(cpu_state.ea_seg);
if (fplog) pclog("FLDs %08X:%08X\n", easeg, cpu_state.eaaddr);
ts.i = geteal(); if (cpu_state.abrt) return 1;
if (fplog) pclog(" %f\n", ts.s);
x87_push((double)ts.s);
- CLOCK_CYCLES(3);
+ CLOCK_CYCLES(x87_timings.fld_32);
return 0;
}
static int opFLDs_a32(uint32_t fetchdat)
x87_ts ts;
FP_ENTER();
fetch_ea_32(fetchdat);
+ SEG_CHECK_READ(cpu_state.ea_seg);
if (fplog) pclog("FLDs %08X:%08X\n", easeg, cpu_state.eaaddr);
ts.i = geteal(); if (cpu_state.abrt) return 1;
if (fplog) pclog(" %f\n", ts.s);
x87_push((double)ts.s);
- CLOCK_CYCLES(3);
+ CLOCK_CYCLES(x87_timings.fld_32);
return 0;
}
x87_ts ts;
FP_ENTER();
fetch_ea_16(fetchdat);
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
if (fplog) pclog("FSTs %08X:%08X\n", easeg, cpu_state.eaaddr);
ts.s = (float)ST(0);
seteal(ts.i);
- CLOCK_CYCLES(7);
+ CLOCK_CYCLES(x87_timings.fst_32);
return cpu_state.abrt;
}
static int opFSTs_a32(uint32_t fetchdat)
x87_ts ts;
FP_ENTER();
fetch_ea_32(fetchdat);
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
if (fplog) pclog("FSTs %08X:%08X\n", easeg, cpu_state.eaaddr);
ts.s = (float)ST(0);
seteal(ts.i);
- CLOCK_CYCLES(7);
+ CLOCK_CYCLES(x87_timings.fst_32);
return cpu_state.abrt;
}
x87_ts ts;
FP_ENTER();
fetch_ea_16(fetchdat);
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
if (fplog) pclog("FSTs %08X:%08X\n", easeg, cpu_state.eaaddr);
ts.s = (float)ST(0);
seteal(ts.i); if (cpu_state.abrt) return 1;
x87_pop();
- CLOCK_CYCLES(7);
+ CLOCK_CYCLES(x87_timings.fst_32);
return 0;
}
static int opFSTPs_a32(uint32_t fetchdat)
x87_ts ts;
FP_ENTER();
fetch_ea_32(fetchdat);
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
if (fplog) pclog("FSTs %08X:%08X\n", easeg, cpu_state.eaaddr);
ts.s = (float)ST(0);
seteal(ts.i); if (cpu_state.abrt) return 1;
x87_pop();
- CLOCK_CYCLES(7);
+ CLOCK_CYCLES(x87_timings.fst_32);
return 0;
}
+static int opFDISI(uint32_t fetchdat)
+{
+ FP_ENTER();
+ cpu_state.pc++;
+ if (fpu_type == FPU_8087)
+ {
+ cpu_state.npxc |= FPCW_DISI;
+ CLOCK_CYCLES(x87_timings.fdisi_eni);
+ }
+ else
+ CLOCK_CYCLES(x87_timings.fnop);
+ return 0;
+}
+static int opFENI(uint32_t fetchdat)
+{
+ FP_ENTER();
+ cpu_state.pc++;
+ if (fpu_type == FPU_8087)
+ {
+ cpu_state.npxc &= ~FPCW_DISI;
+ CLOCK_CYCLES(x87_timings.fdisi_eni);
+ }
+ else
+ CLOCK_CYCLES(x87_timings.fnop);
+ return 0;
+}
+
static int opFSTSW_AX(uint32_t fetchdat)
{
FP_ENTER();
cpu_state.pc++;
if (fplog) pclog("FSTSW\n");
AX = cpu_state.npxs;
- CLOCK_CYCLES(3);
+ CLOCK_CYCLES(x87_timings.fstcw_sw);
return 0;
}
{
FP_ENTER();
cpu_state.pc++;
- CLOCK_CYCLES(4);
+ CLOCK_CYCLES(x87_timings.fnop);
return 0;
}
FP_ENTER();
cpu_state.pc++;
cpu_state.npxs &= 0xff00;
- CLOCK_CYCLES(4);
+ CLOCK_CYCLES(x87_timings.fclex);
return 0;
}
{
FP_ENTER();
cpu_state.pc++;
- cpu_state.npxc = 0x37F;
- cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00);
+ if (fpu_type == FPU_8087)
+ cpu_state.npxc = 0x3ff;
+ else
+ cpu_state.npxc = 0x37f;
+ codegen_set_rounding_mode(X87_ROUNDING_NEAREST);
cpu_state.npxs = 0;
- *(uint64_t *)cpu_state.tag = 0x0303030303030303ll;
+ *(uint64_t *)cpu_state.tag = 0;
cpu_state.TOP = 0;
cpu_state.ismmx = 0;
- CLOCK_CYCLES(17);
+ CLOCK_CYCLES(x87_timings.finit);
+ CPU_BLOCK_END();
return 0;
}
FP_ENTER();
cpu_state.pc++;
if (fplog) pclog("FFREE\n");
- cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = 3;
- CLOCK_CYCLES(3);
+ cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = TAG_EMPTY;
+ CLOCK_CYCLES(x87_timings.ffree);
return 0;
}
if (fplog) pclog("FST\n");
ST(fetchdat & 7) = ST(0);
cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = cpu_state.tag[cpu_state.TOP & 7];
- CLOCK_CYCLES(3);
+ CLOCK_CYCLES(x87_timings.fst);
return 0;
}
ST(fetchdat & 7) = ST(0);
cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = cpu_state.tag[cpu_state.TOP & 7];
x87_pop();
- CLOCK_CYCLES(3);
+ CLOCK_CYCLES(x87_timings.fst);
return 0;
}
case 0x000: /*16-bit real mode*/
case 0x001: /*16-bit protected mode*/
cpu_state.npxc = readmemw(easeg, cpu_state.eaaddr);
- cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00) | (cpu_state.npxc & 0xc00);
+ codegen_set_rounding_mode((cpu_state.npxc >> 10) & 3);
cpu_state.npxs = readmemw(easeg, cpu_state.eaaddr+2);
x87_settag(readmemw(easeg, cpu_state.eaaddr+4));
cpu_state.TOP = (cpu_state.npxs >> 11) & 7;
case 0x100: /*32-bit real mode*/
case 0x101: /*32-bit protected mode*/
cpu_state.npxc = readmemw(easeg, cpu_state.eaaddr);
- cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00) | (cpu_state.npxc & 0xc00);
+ codegen_set_rounding_mode((cpu_state.npxc >> 10) & 3);
cpu_state.npxs = readmemw(easeg, cpu_state.eaaddr+4);
x87_settag(readmemw(easeg, cpu_state.eaaddr+8));
cpu_state.TOP = (cpu_state.npxs >> 11) & 7;
something like this is needed*/
if (cpu_state.MM_w4[0] == 0xffff && cpu_state.MM_w4[1] == 0xffff && cpu_state.MM_w4[2] == 0xffff && cpu_state.MM_w4[3] == 0xffff &&
cpu_state.MM_w4[4] == 0xffff && cpu_state.MM_w4[5] == 0xffff && cpu_state.MM_w4[6] == 0xffff && cpu_state.MM_w4[7] == 0xffff &&
- !cpu_state.TOP && !(*(uint64_t *)cpu_state.tag))
- cpu_state.ismmx = 1;
+ !cpu_state.TOP && (*(uint64_t *)cpu_state.tag == 0x0101010101010101ull))
+ cpu_state.ismmx = 1;
- CLOCK_CYCLES((cr0 & 1) ? 34 : 44);
+ CLOCK_CYCLES(x87_timings.frstor);
if (fplog) pclog("FRSTOR %08X:%08X %i %i %04X\n", easeg, cpu_state.eaaddr, cpu_state.ismmx, cpu_state.TOP, x87_gettag());
return cpu_state.abrt;
}
{
FP_ENTER();
fetch_ea_16(fetchdat);
+ SEG_CHECK_READ(cpu_state.ea_seg);
FSTOR();
return cpu_state.abrt;
}
{
FP_ENTER();
fetch_ea_32(fetchdat);
+ SEG_CHECK_READ(cpu_state.ea_seg);
FSTOR();
return cpu_state.abrt;
}
{
FP_ENTER();
if (fplog) pclog("FSAVE %08X:%08X %i\n", easeg, cpu_state.eaaddr, cpu_state.ismmx);
- cpu_state.npxs = (cpu_state.npxs & ~(7 << 11)) | (cpu_state.TOP << 11);
+ cpu_state.npxs = (cpu_state.npxs & ~(7 << 11)) | ((cpu_state.TOP & 7) << 11);
switch ((cr0 & 1) | (cpu_state.op32 & 0x100))
{
}
cpu_state.npxc = 0x37F;
- cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00);
+ codegen_set_rounding_mode(X87_ROUNDING_NEAREST);
cpu_state.npxs = 0;
- *(uint64_t *)cpu_state.tag = 0x0303030303030303ll;
+ *(uint64_t *)cpu_state.tag = 0;
cpu_state.TOP = 0;
cpu_state.ismmx = 0;
- CLOCK_CYCLES((cr0 & 1) ? 56 : 67);
+ CLOCK_CYCLES(x87_timings.fsave);
return cpu_state.abrt;
}
static int opFSAVE_a16(uint32_t fetchdat)
{
FP_ENTER();
fetch_ea_16(fetchdat);
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
FSAVE();
return cpu_state.abrt;
}
{
FP_ENTER();
fetch_ea_32(fetchdat);
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
FSAVE();
return cpu_state.abrt;
}
{
FP_ENTER();
fetch_ea_16(fetchdat);
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
if (fplog) pclog("FSTSW %08X:%08X\n", easeg, cpu_state.eaaddr);
- seteaw((cpu_state.npxs & 0xC7FF) | (cpu_state.TOP << 11));
- CLOCK_CYCLES(3);
+ seteaw((cpu_state.npxs & 0xC7FF) | ((cpu_state.TOP & 7) << 11));
+ CLOCK_CYCLES(x87_timings.fstcw_sw);
return cpu_state.abrt;
}
static int opFSTSW_a32(uint32_t fetchdat)
{
FP_ENTER();
fetch_ea_32(fetchdat);
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
if (fplog) pclog("FSTSW %08X:%08X\n", easeg, cpu_state.eaaddr);
- seteaw((cpu_state.npxs & 0xC7FF) | (cpu_state.TOP << 11));
- CLOCK_CYCLES(3);
+ seteaw((cpu_state.npxs & 0xC7FF) | ((cpu_state.TOP & 7) << 11));
+ CLOCK_CYCLES(x87_timings.fstcw_sw);
return cpu_state.abrt;
}
old_tag = cpu_state.tag[(cpu_state.TOP + fetchdat) & 7];
old_i64 = cpu_state.MM[(cpu_state.TOP + fetchdat) & 7].q;
x87_push(ST(fetchdat&7));
- cpu_state.tag[cpu_state.TOP] = old_tag;
- cpu_state.MM[cpu_state.TOP].q = old_i64;
- CLOCK_CYCLES(4);
+ cpu_state.tag[cpu_state.TOP&7] = old_tag;
+ cpu_state.MM[cpu_state.TOP&7].q = old_i64;
+ CLOCK_CYCLES(x87_timings.fld);
return 0;
}
td = ST(0);
ST(0) = ST(fetchdat&7);
ST(fetchdat&7) = td;
- old_tag = cpu_state.tag[cpu_state.TOP];
- cpu_state.tag[cpu_state.TOP] = cpu_state.tag[(cpu_state.TOP + fetchdat) & 7];
+ old_tag = cpu_state.tag[cpu_state.TOP&7];
+ cpu_state.tag[cpu_state.TOP&7] = cpu_state.tag[(cpu_state.TOP + fetchdat) & 7];
cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = old_tag;
- old_i64 = cpu_state.MM[cpu_state.TOP].q;
- cpu_state.MM[cpu_state.TOP].q = cpu_state.MM[(cpu_state.TOP + fetchdat) & 7].q;
+ old_i64 = cpu_state.MM[cpu_state.TOP&7].q;
+ cpu_state.MM[cpu_state.TOP&7].q = cpu_state.MM[(cpu_state.TOP + fetchdat) & 7].q;
cpu_state.MM[(cpu_state.TOP + fetchdat) & 7].q = old_i64;
- CLOCK_CYCLES(4);
+ CLOCK_CYCLES(x87_timings.fxch);
return 0;
}
cpu_state.pc++;
if (fplog) pclog("FCHS\n");
ST(0) = -ST(0);
- cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64;
- CLOCK_CYCLES(6);
+ cpu_state.tag[cpu_state.TOP&7] = TAG_VALID;
+ CLOCK_CYCLES(x87_timings.fchs);
return 0;
}
cpu_state.pc++;
if (fplog) pclog("FABS %f\n", ST(0));
ST(0) = fabs(ST(0));
- cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64;
- CLOCK_CYCLES(3);
+ cpu_state.tag[cpu_state.TOP&7] = TAG_VALID;
+ CLOCK_CYCLES(x87_timings.fabs);
return 0;
}
cpu_state.npxs &= ~(C0|C2|C3);
if (ST(0) == 0.0) cpu_state.npxs |= C3;
else if (ST(0) < 0.0) cpu_state.npxs |= C0;
- CLOCK_CYCLES(4);
+ CLOCK_CYCLES(x87_timings.ftst);
return 0;
}
cpu_state.pc++;
if (fplog) pclog("FXAM %i %f\n", cpu_state.tag[cpu_state.TOP&7], ST(0));
cpu_state.npxs &= ~(C0|C1|C2|C3);
- if (cpu_state.tag[cpu_state.TOP&7] == 3) cpu_state.npxs |= (C0|C3);
+ if (cpu_state.tag[cpu_state.TOP&7] == TAG_EMPTY) cpu_state.npxs |= (C0|C3);
else if (ST(0) == 0.0) cpu_state.npxs |= C3;
else cpu_state.npxs |= C2;
if (ST(0) < 0.0) cpu_state.npxs |= C1;
- CLOCK_CYCLES(8);
+ CLOCK_CYCLES(x87_timings.fxam);
return 0;
}
cpu_state.pc++;
if (fplog) pclog("FLD1\n");
x87_push(1.0);
- CLOCK_CYCLES(4);
+ CLOCK_CYCLES(x87_timings.fld_z1);
return 0;
}
cpu_state.pc++;
if (fplog) pclog("FLDL2T\n");
x87_push(3.3219280948873623);
- CLOCK_CYCLES(8);
+ CLOCK_CYCLES(x87_timings.fld_const);
return 0;
}
cpu_state.pc++;
if (fplog) pclog("FLDL2E\n");
x87_push(1.4426950408889634);
- CLOCK_CYCLES(8);
+ CLOCK_CYCLES(x87_timings.fld_const);
return 0;
}
cpu_state.pc++;
if (fplog) pclog("FLDPI\n");
x87_push(3.141592653589793);
- CLOCK_CYCLES(8);
+ CLOCK_CYCLES(x87_timings.fld_const);
return 0;
}
cpu_state.pc++;
if (fplog) pclog("FLDEG2\n");
x87_push(0.3010299956639812);
- CLOCK_CYCLES(8);
+ CLOCK_CYCLES(x87_timings.fld_const);
return 0;
}
cpu_state.pc++;
if (fplog) pclog("FLDLN2\n");
x87_push_u64(0x3fe62e42fefa39f0ull);
- CLOCK_CYCLES(8);
+ CLOCK_CYCLES(x87_timings.fld_const);
return 0;
}
cpu_state.pc++;
if (fplog) pclog("FLDZ\n");
x87_push(0.0);
- cpu_state.tag[cpu_state.TOP&7] = 1;
- CLOCK_CYCLES(4);
+ cpu_state.tag[cpu_state.TOP&7] = TAG_VALID;
+ CLOCK_CYCLES(x87_timings.fld_z1);
return 0;
}
cpu_state.pc++;
if (fplog) pclog("F2XM1\n");
ST(0) = pow(2.0, ST(0)) - 1.0;
- cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64;
- CLOCK_CYCLES(200);
+ cpu_state.tag[cpu_state.TOP&7] = TAG_VALID;
+ CLOCK_CYCLES(x87_timings.f2xm1);
return 0;
}
cpu_state.pc++;
if (fplog) pclog("FYL2X\n");
ST(1) = ST(1) * (log(ST(0)) / log(2.0));
- cpu_state.tag[(cpu_state.TOP + 1) & 7] &= ~TAG_UINT64;
+ cpu_state.tag[(cpu_state.TOP + 1) & 7] = TAG_VALID;
x87_pop();
- CLOCK_CYCLES(250);
+ CLOCK_CYCLES(x87_timings.fyl2x);
return 0;
}
cpu_state.pc++;
if (fplog) pclog("FYL2XP1\n");
ST(1) = ST(1) * (log(ST(0)+1.0) / log(2.0));
- cpu_state.tag[(cpu_state.TOP + 1) & 7] &= ~TAG_UINT64;
+ cpu_state.tag[(cpu_state.TOP + 1) & 7] = TAG_VALID;
x87_pop();
- CLOCK_CYCLES(250);
+ CLOCK_CYCLES(x87_timings.fyl2xp1);
return 0;
}
cpu_state.pc++;
if (fplog) pclog("FPTAN\n");
ST(0) = tan(ST(0));
- cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64;
+ cpu_state.tag[cpu_state.TOP&7] = TAG_VALID;
x87_push(1.0);
cpu_state.npxs &= ~C2;
- CLOCK_CYCLES(235);
+ CLOCK_CYCLES(x87_timings.fptan);
return 0;
}
cpu_state.pc++;
if (fplog) pclog("FPATAN\n");
ST(1) = atan2(ST(1), ST(0));
- cpu_state.tag[(cpu_state.TOP + 1) & 7] &= ~TAG_UINT64;
+ cpu_state.tag[(cpu_state.TOP + 1) & 7] = TAG_VALID;
x87_pop();
- CLOCK_CYCLES(250);
+ CLOCK_CYCLES(x87_timings.fpatan);
return 0;
}
FP_ENTER();
cpu_state.pc++;
if (fplog) pclog("FDECSTP\n");
- cpu_state.TOP = (cpu_state.TOP - 1) & 7;
- CLOCK_CYCLES(4);
+ cpu_state.TOP--;
+ CLOCK_CYCLES(x87_timings.fincdecstp);
return 0;
}
FP_ENTER();
cpu_state.pc++;
if (fplog) pclog("FDECSTP\n");
- cpu_state.TOP = (cpu_state.TOP + 1) & 7;
- CLOCK_CYCLES(4);
+ cpu_state.TOP++;
+ CLOCK_CYCLES(x87_timings.fincdecstp);
return 0;
}
if (fplog) pclog("FPREM %f %f ", ST(0), ST(1));
temp64 = (int64_t)(ST(0) / ST(1));
ST(0) = ST(0) - (ST(1) * (double)temp64);
- cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64;
+ cpu_state.tag[cpu_state.TOP&7] = TAG_VALID;
if (fplog) pclog("%f\n", ST(0));
cpu_state.npxs &= ~(C0|C1|C2|C3);
if (temp64 & 4) cpu_state.npxs|=C0;
if (temp64 & 2) cpu_state.npxs|=C3;
if (temp64 & 1) cpu_state.npxs|=C1;
- CLOCK_CYCLES(100);
+ CLOCK_CYCLES(x87_timings.fprem);
return 0;
}
static int opFPREM1(uint32_t fetchdat)
if (fplog) pclog("FPREM1 %f %f ", ST(0), ST(1));
temp64 = (int64_t)(ST(0) / ST(1));
ST(0) = ST(0) - (ST(1) * (double)temp64);
- cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64;
+ cpu_state.tag[cpu_state.TOP&7] = TAG_VALID;
if (fplog) pclog("%f\n", ST(0));
cpu_state.npxs &= ~(C0|C1|C2|C3);
if (temp64 & 4) cpu_state.npxs|=C0;
if (temp64 & 2) cpu_state.npxs|=C3;
if (temp64 & 1) cpu_state.npxs|=C1;
- CLOCK_CYCLES(100);
+ CLOCK_CYCLES(x87_timings.fprem1);
return 0;
}
cpu_state.pc++;
if (fplog) pclog("FSQRT\n");
ST(0) = sqrt(ST(0));
- cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64;
- CLOCK_CYCLES(83);
+ cpu_state.tag[cpu_state.TOP&7] = TAG_VALID;
+ CLOCK_CYCLES(x87_timings.fsqrt);
return 0;
}
if (fplog) pclog("FSINCOS\n");
td = ST(0);
ST(0) = sin(td);
- cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64;
+ cpu_state.tag[cpu_state.TOP&7] = TAG_VALID;
x87_push(cos(td));
cpu_state.npxs &= ~C2;
- CLOCK_CYCLES(330);
+ CLOCK_CYCLES(x87_timings.fsincos);
return 0;
}
cpu_state.pc++;
if (fplog) pclog("FRNDINT %g ", ST(0));
ST(0) = (double)x87_fround(ST(0));
- cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64;
+ cpu_state.tag[cpu_state.TOP&7] = TAG_VALID;
if (fplog) pclog("%g\n", ST(0));
- CLOCK_CYCLES(21);
+ CLOCK_CYCLES(x87_timings.frndint);
return 0;
}
if (fplog) pclog("FSCALE\n");
temp64 = (int64_t)ST(1);
ST(0) = ST(0) * pow(2.0, (double)temp64);
- cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64;
- CLOCK_CYCLES(30);
+ cpu_state.tag[cpu_state.TOP&7] = TAG_VALID;
+ CLOCK_CYCLES(x87_timings.fscale);
return 0;
}
cpu_state.pc++;
if (fplog) pclog("FSIN\n");
ST(0) = sin(ST(0));
- cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64;
+ cpu_state.tag[cpu_state.TOP&7] = TAG_VALID;
cpu_state.npxs &= ~C2;
- CLOCK_CYCLES(300);
+ CLOCK_CYCLES(x87_timings.fsin_cos);
return 0;
}
cpu_state.pc++;
if (fplog) pclog("FCOS\n");
ST(0) = cos(ST(0));
- cpu_state.tag[cpu_state.TOP] &= ~TAG_UINT64;
+ cpu_state.tag[cpu_state.TOP&7] = TAG_VALID;
cpu_state.npxs &= ~C2;
- CLOCK_CYCLES(300);
+ CLOCK_CYCLES(x87_timings.fsin_cos);
return 0;
}
case 0x000: /*16-bit real mode*/
case 0x001: /*16-bit protected mode*/
cpu_state.npxc = readmemw(easeg, cpu_state.eaaddr);
- cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00) | (cpu_state.npxc & 0xc00);
+ codegen_set_rounding_mode((cpu_state.npxc >> 10) & 3);
cpu_state.npxs = readmemw(easeg, cpu_state.eaaddr+2);
x87_settag(readmemw(easeg, cpu_state.eaaddr+4));
cpu_state.TOP = (cpu_state.npxs >> 11) & 7;
case 0x100: /*32-bit real mode*/
case 0x101: /*32-bit protected mode*/
cpu_state.npxc = readmemw(easeg, cpu_state.eaaddr);
- cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00) | (cpu_state.npxc & 0xc00);
+ codegen_set_rounding_mode((cpu_state.npxc >> 10) & 3);
cpu_state.npxs = readmemw(easeg, cpu_state.eaaddr+4);
x87_settag(readmemw(easeg, cpu_state.eaaddr+8));
cpu_state.TOP = (cpu_state.npxs >> 11) & 7;
break;
}
- CLOCK_CYCLES((cr0 & 1) ? 34 : 44);
+ CLOCK_CYCLES(x87_timings.fldenv);
return cpu_state.abrt;
}
{
FP_ENTER();
fetch_ea_16(fetchdat);
+ SEG_CHECK_READ(cpu_state.ea_seg);
FLDENV();
return cpu_state.abrt;
}
{
FP_ENTER();
fetch_ea_32(fetchdat);
+ SEG_CHECK_READ(cpu_state.ea_seg);
FLDENV();
return cpu_state.abrt;
}
uint16_t tempw;
FP_ENTER();
fetch_ea_16(fetchdat);
+ SEG_CHECK_READ(cpu_state.ea_seg);
if (fplog) pclog("FLDCW %08X:%08X\n", easeg, cpu_state.eaaddr);
tempw = geteaw();
if (cpu_state.abrt) return 1;
cpu_state.npxc = tempw;
- cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00) | (cpu_state.npxc & 0xc00);
- CLOCK_CYCLES(4);
+ codegen_set_rounding_mode((cpu_state.npxc >> 10) & 3);
+ CLOCK_CYCLES(x87_timings.fldcw);
return 0;
}
static int opFLDCW_a32(uint32_t fetchdat)
uint16_t tempw;
FP_ENTER();
fetch_ea_32(fetchdat);
+ SEG_CHECK_READ(cpu_state.ea_seg);
if (fplog) pclog("FLDCW %08X:%08X\n", easeg, cpu_state.eaaddr);
tempw = geteaw();
if (cpu_state.abrt) return 1;
cpu_state.npxc = tempw;
- cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00) | (cpu_state.npxc & 0xc00);
- CLOCK_CYCLES(4);
+ codegen_set_rounding_mode((cpu_state.npxc >> 10) & 3);
+ CLOCK_CYCLES(x87_timings.fldcw);
return 0;
}
writememl(easeg,cpu_state.eaaddr+24,x87_op_seg);
break;
}
- CLOCK_CYCLES((cr0 & 1) ? 56 : 67);
+ CLOCK_CYCLES(x87_timings.fstenv);
return cpu_state.abrt;
}
{
FP_ENTER();
fetch_ea_16(fetchdat);
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
FSTENV();
return cpu_state.abrt;
}
{
FP_ENTER();
fetch_ea_32(fetchdat);
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
FSTENV();
return cpu_state.abrt;
}
{
FP_ENTER();
fetch_ea_16(fetchdat);
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
if (fplog) pclog("FSTCW %08X:%08X\n", easeg, cpu_state.eaaddr);
seteaw(cpu_state.npxc);
- CLOCK_CYCLES(3);
+ CLOCK_CYCLES(x87_timings.fstcw_sw);
return cpu_state.abrt;
}
static int opFSTCW_a32(uint32_t fetchdat)
{
FP_ENTER();
fetch_ea_32(fetchdat);
+ SEG_CHECK_WRITE(cpu_state.ea_seg);
if (fplog) pclog("FSTCW %08X:%08X\n", easeg, cpu_state.eaaddr);
seteaw(cpu_state.npxc);
- CLOCK_CYCLES(3);
+ CLOCK_CYCLES(x87_timings.fstcw_sw);
return cpu_state.abrt;
}
if (fplog) pclog("FCMOV %f\n", ST(fetchdat & 7)); \
if (cond_ ## condition) \
{ \
- cpu_state.tag[cpu_state.TOP] = cpu_state.tag[(cpu_state.TOP + fetchdat) & 7]; \
- cpu_state.MM[cpu_state.TOP].q = cpu_state.MM[(cpu_state.TOP + fetchdat) & 7].q; \
+ cpu_state.tag[cpu_state.TOP&7] = cpu_state.tag[(cpu_state.TOP + fetchdat) & 7]; \
+ cpu_state.MM[cpu_state.TOP&7].q = cpu_state.MM[(cpu_state.TOP + fetchdat) & 7].q; \
ST(0) = ST(fetchdat & 7); \
} \
CLOCK_CYCLES(4); \
--- /dev/null
+#include "ibm.h"
+#include "x87_timings.h"
+
+x87_timings_t x87_timings;
+
+const x87_timings_t x87_timings_8087 =
+{
+ .f2xm1 = (310 + 630) / 2,
+ .fabs = (10 + 17) / 2,
+ .fadd = (70 + 100) / 2,
+ .fadd_32 = (90 + 120) / 2,
+ .fadd_64 = (95 + 125) / 2,
+ .fbld = (290 + 310) / 2,
+ .fbstp = (520 + 540) / 2,
+ .fchs = (10 + 17) / 2,
+ .fclex = (2 + 8) / 2,
+ .fcom = (40 + 50) / 2,
+ .fcom_32 = (60 + 70) / 2,
+ .fcom_64 = (65 + 75) / 2,
+ .fcos = 0, /*387+*/
+ .fincdecstp = (6 + 12) / 2,
+ .fdisi_eni = (6 + 12) / 2,
+ .fdiv = (193 + 203) / 2,
+ .fdiv_32 = (215 + 225) / 2,
+ .fdiv_64 = (220 + 230) / 2,
+ .ffree = (9 + 16) / 2,
+ .fadd_i16 = (102 + 137) / 2,
+ .fadd_i32 = (108 + 143) / 2,
+ .fcom_i16 = (72 + 86) / 2,
+ .fcom_i32 = (78 + 91) / 2,
+ .fdiv_i16 = (224 + 238) / 2,
+ .fdiv_i32 = (230 + 243) / 2,
+ .fild_16 = (46 + 54) / 2,
+ .fild_32 = (50 + 60) / 2,
+ .fild_64 = (60 + 68) / 2,
+ .fmul_i16 = (124 + 138) / 2,
+ .fmul_i32 = (130 + 144) / 2,
+ .finit = (2 + 8) / 2,
+ .fist_16 = (80 + 90) / 2,
+ .fist_32 = (82 + 92) / 2,
+ .fist_64 = (94 + 105) / 2,
+ .fld = (17 + 22) / 2,
+ .fld_32 = (38 + 56) / 2,
+ .fld_64 = (40 + 60) / 2,
+ .fld_80 = (53 + 65) / 2,
+ .fld_z1 = (11 + 21) / 2,
+ .fld_const = (15 + 24) / 2,
+ .fldcw = (7 + 14) / 2,
+ .fldenv = (35 + 45) / 2,
+ .fmul = (90 + 145) / 2,
+ .fmul_32 = (110 + 125) / 2,
+ .fmul_64 = (154 + 168) / 2,
+ .fnop = (10 + 16) / 2,
+ .fpatan = (250 + 800) / 2,
+ .fprem = (15 + 190) / 2,
+ .fprem1 = 0, /*387+*/
+ .fptan = (30 + 540) / 2,
+ .frndint = (16 + 50) / 2,
+ .frstor = (197 + 207) / 2,
+ .fsave = (197 + 207) / 2,
+ .fscale = (32 + 38) / 2,
+ .fsetpm = 0, /*287+*/
+ .fsin_cos = 0, /*387+*/
+ .fsincos = 0, /*387+*/
+ .fsqrt = (180 + 186) / 2,
+ .fst = (15 + 22) / 2,
+ .fst_32 = (84 + 90) / 2,
+ .fst_64 = (96 + 104) / 2,
+ .fst_80 = (52 + 58) / 2,
+ .fstcw_sw = (12 + 18) / 2,
+ .fstenv = (40 + 50) / 2,
+ .ftst = (38 + 48) / 2,
+ .fucom = 0, /*387+*/
+ .fwait = 4,
+ .fxam = (12 + 23) / 2,
+ .fxch = (10 + 15) / 2,
+ .fxtract = (27 + 55) / 2,
+ .fyl2x = (900 + 1100) / 2,
+ .fyl2xp1 = (700 + 1000) / 2
+};
+
+/*Mostly the same as 8087*/
+const x87_timings_t x87_timings_287 =
+{
+ .f2xm1 = (310 + 630) / 2,
+ .fabs = (10 + 17) / 2,
+ .fadd = (70 + 100) / 2,
+ .fadd_32 = (90 + 120) / 2,
+ .fadd_64 = (95 + 125) / 2,
+ .fbld = (290 + 310) / 2,
+ .fbstp = (520 + 540) / 2,
+ .fchs = (10 + 17) / 2,
+ .fclex = (2 + 8) / 2,
+ .fcom = (40 + 50) / 2,
+ .fcom_32 = (60 + 70) / 2,
+ .fcom_64 = (65 + 75) / 2,
+ .fcos = 0, /*387+*/
+ .fincdecstp = (6 + 12) / 2,
+ .fdisi_eni = 2,
+ .fdiv = (193 + 203) / 2,
+ .fdiv_32 = (215 + 225) / 2,
+ .fdiv_64 = (220 + 230) / 2,
+ .ffree = (9 + 16) / 2,
+ .fadd_i16 = (102 + 137) / 2,
+ .fadd_i32 = (108 + 143) / 2,
+ .fcom_i16 = (72 + 86) / 2,
+ .fcom_i32 = (78 + 91) / 2,
+ .fdiv_i16 = (224 + 238) / 2,
+ .fdiv_i32 = (230 + 243) / 2,
+ .fild_16 = (46 + 54) / 2,
+ .fild_32 = (50 + 60) / 2,
+ .fild_64 = (60 + 68) / 2,
+ .fmul_i16 = (124 + 138) / 2,
+ .fmul_i32 = (130 + 144) / 2,
+ .finit = (2 + 8) / 2,
+ .fist_16 = (80 + 90) / 2,
+ .fist_32 = (82 + 92) / 2,
+ .fist_64 = (94 + 105) / 2,
+ .fld = (17 + 22) / 2,
+ .fld_32 = (38 + 56) / 2,
+ .fld_64 = (40 + 60) / 2,
+ .fld_80 = (53 + 65) / 2,
+ .fld_z1 = (11 + 21) / 2,
+ .fld_const = (15 + 24) / 2,
+ .fldcw = (7 + 14) / 2,
+ .fldenv = (35 + 45) / 2,
+ .fmul = (90 + 145) / 2,
+ .fmul_32 = (110 + 125) / 2,
+ .fmul_64 = (154 + 168) / 2,
+ .fnop = (10 + 16) / 2,
+ .fpatan = (250 + 800) / 2,
+ .fprem = (15 + 190) / 2,
+ .fprem1 = 0, /*387+*/
+ .fptan = (30 + 540) / 2,
+ .frndint = (16 + 50) / 2,
+ .frstor = (197 + 207) / 2,
+ .fsave = (197 + 207) / 2,
+ .fscale = (32 + 38) / 2,
+ .fsetpm = (2 + 8) / 2, /*287+*/
+ .fsin_cos = 0, /*387+*/
+ .fsincos = 0, /*387+*/
+ .fsqrt = (180 + 186) / 2,
+ .fst = (15 + 22) / 2,
+ .fst_32 = (84 + 90) / 2,
+ .fst_64 = (96 + 104) / 2,
+ .fst_80 = (52 + 58) / 2,
+ .fstcw_sw = (12 + 18) / 2,
+ .fstenv = (40 + 50) / 2,
+ .ftst = (38 + 48) / 2,
+ .fucom = 0, /*387+*/
+ .fwait = 3,
+ .fxam = (12 + 23) / 2,
+ .fxch = (10 + 15) / 2,
+ .fxtract = (27 + 55) / 2,
+ .fyl2x = (900 + 1100) / 2,
+ .fyl2xp1 = (700 + 1000) / 2
+};
+
+const x87_timings_t x87_timings_387 =
+{
+ .f2xm1 = (211 + 476) / 2,
+ .fabs = 22,
+ .fadd = (23 + 34) / 2,
+ .fadd_32 = (24 + 32) / 2,
+ .fadd_64 = (29 + 37) / 2,
+ .fbld = (266 + 275) / 2,
+ .fbstp = (512 + 534) / 2,
+ .fchs = (24 + 25) / 2,
+ .fclex = 11,
+ .fcom = 24,
+ .fcom_32 = 26,
+ .fcom_64 = 31,
+ .fcos = (122 + 772) / 2,
+ .fincdecstp = 22,
+ .fdisi_eni = 2,
+ .fdiv = (88 + 91) / 2,
+ .fdiv_32 = 89,
+ .fdiv_64 = 94,
+ .ffree = 18,
+ .fadd_i16 = (71 + 85) / 2,
+ .fadd_i32 = (57 + 72) / 2,
+ .fcom_i16 = (71 + 75) / 2,
+ .fcom_i32 = (56 + 63) / 2,
+ .fdiv_i16 = (136 + 140) / 2,
+ .fdiv_i32 = (120 + 127) / 2,
+ .fild_16 = (61 + 65) / 2,
+ .fild_32 = (45 + 52) / 2,
+ .fild_64 = (56 + 67) / 2,
+ .fmul_i16 = (76 + 87) / 2,
+ .fmul_i32 = (61 + 82) / 2,
+ .finit = 33,
+ .fist_16 = (82 + 95) / 2,
+ .fist_32 = (79 + 93) / 2,
+ .fist_64 = (80 + 97) / 2,
+ .fld = 14,
+ .fld_32 = 20,
+ .fld_64 = 25,
+ .fld_80 = 44,
+ .fld_z1 = (20 + 24) / 2,
+ .fld_const = 40,
+ .fldcw = 19,
+ .fldenv = 71,
+ .fmul = (29 + 57) / 2,
+ .fmul_32 = (27 + 35) / 2,
+ .fmul_64 = (32 + 57) / 2,
+ .fnop = 12,
+ .fpatan = (314 + 487) / 2,
+ .fprem = (74 + 155) / 2,
+ .fprem1 = (95 + 185) / 2,
+ .fptan = (191 + 497) / 2,
+ .frndint = (66 + 80) / 2,
+ .frstor = 308,
+ .fsave = 375,
+ .fscale = (67 + 86) / 2,
+ .fsetpm = 12,
+ .fsin_cos = (122 + 771) / 2,
+ .fsincos = (194 + 809) / 2,
+ .fsqrt = (122 + 129) / 2,
+ .fst = 11,
+ .fst_32 = 44,
+ .fst_64 = 45,
+ .fst_80 = 53,
+ .fstcw_sw = 15,
+ .fstenv = 103,
+ .ftst = 28,
+ .fucom = 24,
+ .fwait = 6,
+ .fxam = (30 + 38) / 2,
+ .fxch = 18,
+ .fxtract = (70 + 76) / 2,
+ .fyl2x = (120 + 538) / 2,
+ .fyl2xp1 = (257 + 547) / 2
+};
+
+const x87_timings_t x87_timings_486 =
+{
+ .f2xm1 = (140 + 270) / 2,
+ .fabs = 3,
+ .fadd = (8 + 20) / 2,
+ .fadd_32 = (8 + 20) / 2,
+ .fadd_64 = (8 + 20) / 2,
+ .fbld = (70 + 103) / 2,
+ .fbstp = (172 + 176) / 2,
+ .fchs = 6,
+ .fclex = 7,
+ .fcom = 4,
+ .fcom_32 = 4,
+ .fcom_64 = 4,
+ .fcos = (257 + 354) / 2,
+ .fincdecstp = 3,
+ .fdisi_eni = 3,
+ .fdiv = 73,
+ .fdiv_32 = 73,
+ .fdiv_64 = 73,
+ .ffree = 3,
+ .fadd_i16 = (20 + 35) / 2,
+ .fadd_i32 = (19 + 32) / 2,
+ .fcom_i16 = (16 + 20) / 2,
+ .fcom_i32 = (15 + 17) / 2,
+ .fdiv_i16 = (85 + 89) / 2,
+ .fdiv_i32 = (84 + 86) / 2,
+ .fild_16 = (13 + 16) / 2,
+ .fild_32 = (9 + 12) / 2,
+ .fild_64 = (10 + 18) / 2,
+ .fmul_i16 = (23 + 27) / 2,
+ .fmul_i32 = (22 + 24) / 2,
+ .finit = 17,
+ .fist_16 = (29 + 34) / 2,
+ .fist_32 = (28 + 34) / 2,
+ .fist_64 = (29 + 34) / 2,
+ .fld = 4,
+ .fld_32 = 3,
+ .fld_64 = 3,
+ .fld_80 = 6,
+ .fld_z1 = 4,
+ .fld_const = 8,
+ .fldcw = 4,
+ .fldenv = 34,
+ .fmul = 16,
+ .fmul_32 = 11,
+ .fmul_64 = 14,
+ .fnop = 3,
+ .fpatan = (218 + 303) / 2,
+ .fprem = (70 + 138) / 2,
+ .fprem1 = (72 + 167) / 2,
+ .fptan = (200 + 273) / 2,
+ .frndint = (21 + 30) / 2,
+ .frstor = 120,
+ .fsave = 143,
+ .fscale = (30 + 32) / 2,
+ .fsetpm = 3,
+ .fsin_cos = (257 + 354) / 2,
+ .fsincos = (292 + 365) / 2,
+ .fsqrt = (83 + 87) / 2,
+ .fst = 3,
+ .fst_32 = 7,
+ .fst_64 = 8,
+ .fst_80 = 6,
+ .fstcw_sw = 3,
+ .fstenv = 56,
+ .ftst = 4,
+ .fucom = 4,
+ .fwait = (1 + 3) / 2,
+ .fxam = 8,
+ .fxch = 4,
+ .fxtract = (16 + 20) / 2,
+ .fyl2x = (196 + 329) / 2,
+ .fyl2xp1 = (171 + 326) / 2
+};
--- /dev/null
+typedef struct
+{
+ int f2xm1;
+ int fabs;
+ int fadd, fadd_32, fadd_64;
+ int fbld;
+ int fbstp;
+ int fchs;
+ int fclex;
+ int fcom, fcom_32, fcom_64;
+ int fcos;
+ int fincdecstp;
+ int fdisi_eni;
+ int fdiv, fdiv_32, fdiv_64;
+ int ffree;
+ int fadd_i16, fadd_i32;
+ int fcom_i16, fcom_i32;
+ int fdiv_i16, fdiv_i32;
+ int fild_16, fild_32, fild_64;
+ int fmul_i16, fmul_i32;
+ int finit;
+ int fist_16, fist_32, fist_64;
+ int fld, fld_32, fld_64, fld_80;
+ int fld_z1, fld_const;
+ int fldcw;
+ int fldenv;
+ int fmul, fmul_32, fmul_64;
+ int fnop;
+ int fpatan;
+ int fprem, fprem1;
+ int fptan;
+ int frndint;
+ int frstor;
+ int fsave;
+ int fscale;
+ int fsetpm;
+ int fsin_cos, fsincos;
+ int fsqrt;
+ int fst, fst_32, fst_64, fst_80;
+ int fstcw_sw;
+ int fstenv;
+ int ftst;
+ int fucom;
+ int fwait;
+ int fxam;
+ int fxch;
+ int fxtract;
+ int fyl2x, fyl2xp1;
+} x87_timings_t;
+
+extern const x87_timings_t x87_timings_8087;
+extern const x87_timings_t x87_timings_287;
+extern const x87_timings_t x87_timings_387;
+extern const x87_timings_t x87_timings_486;
+
+extern x87_timings_t x87_timings;