Current WIP code.
This commit is contained in:
335
src/cpu_common/386.c
Normal file
335
src/cpu_common/386.c
Normal file
@@ -0,0 +1,335 @@
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <wchar.h>
|
||||
#include <math.h>
|
||||
#ifndef INFINITY
|
||||
# define INFINITY (__builtin_inff())
|
||||
#endif
|
||||
|
||||
#define HAVE_STDARG_H
|
||||
#include "86box.h"
|
||||
#include "cpu.h"
|
||||
#include "timer.h"
|
||||
#include "x86.h"
|
||||
#include "x87.h"
|
||||
#include "nmi.h"
|
||||
#include "mem.h"
|
||||
#include "pic.h"
|
||||
#include "pit.h"
|
||||
#include "fdd.h"
|
||||
#include "fdc.h"
|
||||
#include "386_common.h"
|
||||
#ifdef USE_NEW_DYNAREC
|
||||
#include "codegen.h"
|
||||
#endif
|
||||
|
||||
|
||||
#undef CPU_BLOCK_END
|
||||
#define CPU_BLOCK_END()
|
||||
|
||||
|
||||
extern int codegen_flags_changed;
|
||||
|
||||
int tempc, oldcpl, optype, inttype, oddeven = 0;
|
||||
int timetolive;
|
||||
|
||||
uint16_t oldcs;
|
||||
|
||||
uint32_t oldds, oldss, olddslimit, oldsslimit,
|
||||
olddslimitw, oldsslimitw;
|
||||
uint32_t oxpc;
|
||||
uint32_t rmdat32;
|
||||
uint32_t backupregs[16];
|
||||
|
||||
x86seg _oldds;
|
||||
|
||||
|
||||
#ifdef ENABLE_386_LOG
|
||||
int x386_do_log = ENABLE_386_LOG;
|
||||
|
||||
|
||||
void
|
||||
x386_log(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (x386_do_log) {
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define x386_log(fmt, ...)
|
||||
#endif
|
||||
|
||||
|
||||
#undef CPU_BLOCK_END
|
||||
#define CPU_BLOCK_END()
|
||||
|
||||
static inline void fetch_ea_32_long(uint32_t rmdat)
|
||||
{
|
||||
eal_r = eal_w = NULL;
|
||||
easeg = cpu_state.ea_seg->base;
|
||||
if (cpu_rm == 4)
|
||||
{
|
||||
uint8_t sib = rmdat >> 8;
|
||||
|
||||
switch (cpu_mod)
|
||||
{
|
||||
case 0:
|
||||
cpu_state.eaaddr = cpu_state.regs[sib & 7].l;
|
||||
cpu_state.pc++;
|
||||
break;
|
||||
case 1:
|
||||
cpu_state.pc++;
|
||||
cpu_state.eaaddr = ((uint32_t)(int8_t)getbyte()) + cpu_state.regs[sib & 7].l;
|
||||
// pc++;
|
||||
break;
|
||||
case 2:
|
||||
cpu_state.eaaddr = (fastreadl(cs + cpu_state.pc + 1)) + cpu_state.regs[sib & 7].l;
|
||||
cpu_state.pc += 5;
|
||||
break;
|
||||
}
|
||||
/*SIB byte present*/
|
||||
if ((sib & 7) == 5 && !cpu_mod)
|
||||
cpu_state.eaaddr = getlong();
|
||||
else if ((sib & 6) == 4 && !cpu_state.ssegs)
|
||||
{
|
||||
easeg = 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);
|
||||
}
|
||||
else
|
||||
{
|
||||
cpu_state.eaaddr = cpu_state.regs[cpu_rm].l;
|
||||
if (cpu_mod)
|
||||
{
|
||||
if (cpu_rm == 5 && !cpu_state.ssegs)
|
||||
{
|
||||
easeg = ss;
|
||||
cpu_state.ea_seg = &cpu_state.seg_ss;
|
||||
}
|
||||
if (cpu_mod == 1)
|
||||
{
|
||||
cpu_state.eaaddr += ((uint32_t)(int8_t)(rmdat >> 8));
|
||||
cpu_state.pc++;
|
||||
}
|
||||
else
|
||||
{
|
||||
cpu_state.eaaddr += getlong();
|
||||
}
|
||||
}
|
||||
else if (cpu_rm == 5)
|
||||
{
|
||||
cpu_state.eaaddr = getlong();
|
||||
}
|
||||
}
|
||||
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 (!cpu_mod && cpu_rm == 6)
|
||||
{
|
||||
cpu_state.eaaddr = getword();
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (cpu_mod)
|
||||
{
|
||||
case 0:
|
||||
cpu_state.eaaddr = 0;
|
||||
break;
|
||||
case 1:
|
||||
cpu_state.eaaddr = (uint16_t)(int8_t)(rmdat >> 8); cpu_state.pc++;
|
||||
break;
|
||||
case 2:
|
||||
cpu_state.eaaddr = getword();
|
||||
break;
|
||||
}
|
||||
cpu_state.eaaddr += (*mod1add[0][cpu_rm]) + (*mod1add[1][cpu_rm]);
|
||||
if (mod1seg[cpu_rm] == &ss && !cpu_state.ssegs)
|
||||
{
|
||||
easeg = ss;
|
||||
cpu_state.ea_seg = &cpu_state.seg_ss;
|
||||
}
|
||||
cpu_state.eaaddr &= 0xFFFF;
|
||||
}
|
||||
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++; cpu_mod=(rmdat >> 6) & 3; cpu_reg=(rmdat >> 3) & 7; cpu_rm = rmdat & 7; if (cpu_mod != 3) { fetch_ea_16_long(rmdat); if (cpu_state.abrt) return 0; }
|
||||
#define fetch_ea_32(rmdat) cpu_state.pc++; cpu_mod=(rmdat >> 6) & 3; cpu_reg=(rmdat >> 3) & 7; cpu_rm = rmdat & 7; if (cpu_mod != 3) { fetch_ea_32_long(rmdat); } if (cpu_state.abrt) return 0
|
||||
|
||||
#include "x86_flags.h"
|
||||
|
||||
#define getbytef() ((uint8_t)(fetchdat)); cpu_state.pc++
|
||||
#define getwordf() ((uint16_t)(fetchdat)); cpu_state.pc+=2
|
||||
#define getbyte2f() ((uint8_t)(fetchdat>>8)); cpu_state.pc++
|
||||
#define getword2f() ((uint16_t)(fetchdat>>8)); cpu_state.pc+=2
|
||||
|
||||
|
||||
#define OP_TABLE(name) ops_ ## name
|
||||
|
||||
#define CLOCK_CYCLES(c) cycles -= (c)
|
||||
#define CLOCK_CYCLES_ALWAYS(c) cycles -= (c)
|
||||
|
||||
#include "x86_ops.h"
|
||||
|
||||
void
|
||||
exec386(int cycs)
|
||||
{
|
||||
// uint8_t opcode;
|
||||
int vector, tempi, cycdiff, oldcyc;
|
||||
int cycle_period, ins_cycles;
|
||||
uint32_t addr;
|
||||
|
||||
cycles += cycs;
|
||||
|
||||
while (cycles > 0) {
|
||||
cycle_period = (timer_target - (uint32_t)tsc) + 1;
|
||||
|
||||
x86_was_reset = 0;
|
||||
cycdiff = 0;
|
||||
oldcyc = cycles;
|
||||
while (cycdiff < cycle_period) {
|
||||
ins_cycles = cycles;
|
||||
|
||||
#ifndef USE_NEW_DYNAREC
|
||||
oldcs=CS;
|
||||
oldcpl=CPL;
|
||||
#endif
|
||||
cpu_state.oldpc = cpu_state.pc;
|
||||
cpu_state.op32 = use32;
|
||||
|
||||
#ifndef USE_NEW_DYNAREC
|
||||
x86_was_reset = 0;
|
||||
#endif
|
||||
|
||||
cpu_state.ea_seg = &cpu_state.seg_ds;
|
||||
cpu_state.ssegs = 0;
|
||||
|
||||
fetchdat = fastreadl(cs + cpu_state.pc);
|
||||
|
||||
if (!cpu_state.abrt) {
|
||||
opcode = fetchdat & 0xFF;
|
||||
fetchdat >>= 8;
|
||||
trap = cpu_state.flags & T_FLAG;
|
||||
|
||||
cpu_state.pc++;
|
||||
x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat);
|
||||
if (x86_was_reset)
|
||||
break;
|
||||
}
|
||||
|
||||
#ifndef USE_NEW_DYNAREC
|
||||
if (!use32) cpu_state.pc &= 0xffff;
|
||||
#endif
|
||||
|
||||
if (cpu_state.abrt) {
|
||||
flags_rebuild();
|
||||
tempi = cpu_state.abrt;
|
||||
cpu_state.abrt = 0;
|
||||
x86_doabrt(tempi);
|
||||
if (cpu_state.abrt) {
|
||||
cpu_state.abrt = 0;
|
||||
#ifndef USE_NEW_DYNAREC
|
||||
CS = oldcs;
|
||||
#endif
|
||||
cpu_state.pc = cpu_state.oldpc;
|
||||
x386_log("Double fault %i\n", ins);
|
||||
pmodeint(8, 0);
|
||||
if (cpu_state.abrt) {
|
||||
cpu_state.abrt = 0;
|
||||
softresetx86();
|
||||
cpu_set_edx();
|
||||
#ifdef ENABLE_386_LOG
|
||||
x386_log("Triple fault - reset\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ins_cycles -= cycles;
|
||||
tsc += ins_cycles;
|
||||
|
||||
cycdiff = oldcyc - cycles;
|
||||
|
||||
if (trap) {
|
||||
flags_rebuild();
|
||||
if (msw&1)
|
||||
pmodeint(1,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 = (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;
|
||||
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) {
|
||||
vector = picinterrupt();
|
||||
if (vector != -1) {
|
||||
flags_rebuild();
|
||||
if (msw & 1)
|
||||
pmodeint(vector, 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 = (vector << 2) + idt.base;
|
||||
cpu_state.flags &= ~I_FLAG;
|
||||
cpu_state.flags &= ~T_FLAG;
|
||||
cpu_state.pc = readmemw(0, addr);
|
||||
loadcs(readmemw(0, addr + 2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ins++;
|
||||
|
||||
if (timetolive) {
|
||||
timetolive--;
|
||||
if (!timetolive)
|
||||
fatal("Life expired\n");
|
||||
}
|
||||
|
||||
if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t) tsc))
|
||||
timer_process();
|
||||
}
|
||||
}
|
||||
}
|
||||
309
src/cpu_common/386_common.c
Normal file
309
src/cpu_common/386_common.c
Normal file
@@ -0,0 +1,309 @@
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <wchar.h>
|
||||
#include <math.h>
|
||||
#ifndef INFINITY
|
||||
# define INFINITY (__builtin_inff())
|
||||
#endif
|
||||
#define HAVE_STDARG_H
|
||||
#include "86box.h"
|
||||
#include "cpu.h"
|
||||
#include "timer.h"
|
||||
#include "x86.h"
|
||||
#include "x87.h"
|
||||
#include "nmi.h"
|
||||
#include "mem.h"
|
||||
#include "pic.h"
|
||||
#include "pit.h"
|
||||
#include "fdd.h"
|
||||
#include "fdc.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;
|
||||
|
||||
#ifdef USE_NEW_DYNAREC
|
||||
uint16_t cpu_cur_status = 0;
|
||||
#else
|
||||
uint32_t cpu_cur_status = 0;
|
||||
#endif
|
||||
|
||||
uint32_t pccache;
|
||||
uint8_t *pccache2;
|
||||
|
||||
|
||||
#ifdef ENABLE_386_COMMON_LOG
|
||||
int x386_common_do_log = ENABLE_386_COMMON_LOG;
|
||||
|
||||
|
||||
void
|
||||
x386_common_log(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (x386_common_do_log) {
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define x386_common_log(fmt, ...)
|
||||
#endif
|
||||
|
||||
|
||||
void x86_int(int num)
|
||||
{
|
||||
uint32_t addr;
|
||||
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();
|
||||
#ifdef ENABLE_386_COMMON_LOG
|
||||
x386_log("Triple fault in real mode - reset\n");
|
||||
#endif
|
||||
}
|
||||
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;
|
||||
#ifndef USE_NEW_DYNAREC
|
||||
oxpc=cpu_state.pc;
|
||||
#endif
|
||||
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;
|
||||
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;
|
||||
#ifndef USE_NEW_DYNAREC
|
||||
oxpc=cpu_state.pc;
|
||||
#endif
|
||||
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)
|
||||
return 1;
|
||||
writememw(ss,((SP-4)&0xFFFF),CS);
|
||||
writememw(ss,((SP-6)&0xFFFF),cpu_state.pc);
|
||||
if (cpu_state.abrt)
|
||||
return 1;
|
||||
SP-=6;
|
||||
|
||||
cpu_state.eflags &= ~VIF_FLAG;
|
||||
cpu_state.flags &= ~T_FLAG;
|
||||
cpu_state.pc = new_pc;
|
||||
loadcs(new_cs);
|
||||
#ifndef USE_NEW_DYNAREC
|
||||
oxpc=cpu_state.pc;
|
||||
#endif
|
||||
|
||||
cycles -= timing_int_rm;
|
||||
trap = 0;
|
||||
CPU_BLOCK_END();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void x86illegal()
|
||||
{
|
||||
x86_int(6);
|
||||
}
|
||||
|
||||
int checkio(int port)
|
||||
{
|
||||
uint16_t t;
|
||||
uint8_t d;
|
||||
cpl_override = 1;
|
||||
t = readmemw(tr.base, 0x66);
|
||||
cpl_override = 0;
|
||||
if (cpu_state.abrt) return 0;
|
||||
if ((t+(port>>3))>tr.limit) return 1;
|
||||
cpl_override = 1;
|
||||
#ifdef USE_NEW_DYNAREC
|
||||
d = readmembl(tr.base + t + (port >> 3));
|
||||
#else
|
||||
d = readmemb386l(0, tr.base + t + (port >> 3));
|
||||
#endif
|
||||
cpl_override = 0;
|
||||
return d&(1<<(port&7));
|
||||
}
|
||||
|
||||
#define divexcp() { \
|
||||
x386_common_log("Divide exception at %04X(%06X):%04X\n",CS,cs,cpu_state.pc); \
|
||||
x86_int(0); \
|
||||
}
|
||||
|
||||
int divl(uint32_t val)
|
||||
{
|
||||
uint64_t num, quo;
|
||||
uint32_t rem, quo32;
|
||||
|
||||
if (val==0)
|
||||
{
|
||||
divexcp();
|
||||
return 1;
|
||||
}
|
||||
|
||||
num=(((uint64_t)EDX)<<32)|EAX;
|
||||
quo=num/val;
|
||||
rem=num%val;
|
||||
quo32=(uint32_t)(quo&0xFFFFFFFF);
|
||||
|
||||
if (quo!=(uint64_t)quo32)
|
||||
{
|
||||
divexcp();
|
||||
return 1;
|
||||
}
|
||||
EDX=rem;
|
||||
EAX=quo32;
|
||||
return 0;
|
||||
}
|
||||
int idivl(int32_t val)
|
||||
{
|
||||
int64_t num, quo;
|
||||
int32_t rem, quo32;
|
||||
|
||||
if (val==0)
|
||||
{
|
||||
divexcp();
|
||||
return 1;
|
||||
}
|
||||
|
||||
num=(((uint64_t)EDX)<<32)|EAX;
|
||||
quo=num/val;
|
||||
rem=num%val;
|
||||
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();
|
||||
}
|
||||
374
src/cpu_common/386_common.h
Normal file
374
src/cpu_common/386_common.h
Normal file
@@ -0,0 +1,374 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Common 386 CPU code.
|
||||
*
|
||||
* Version: @(#)386_common.h 1.0.1 2019/02/19
|
||||
*
|
||||
* Author: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Copyright 2008-2019 Sarah Walker.
|
||||
* Copyright 2016-2019 Miran Grca.
|
||||
*/
|
||||
|
||||
#ifndef _386_COMMON_H_
|
||||
#define _386_COMMON_H_
|
||||
|
||||
#ifdef USE_NEW_DYNAREC
|
||||
#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 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
|
||||
#else
|
||||
#undef readmemb
|
||||
#undef writememb
|
||||
|
||||
|
||||
#define readmemb(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF)?readmemb386l(s,a): *(uint8_t *)(readlookup2[(uint32_t)((s)+(a))>>12] + (uint32_t)((s) + (a))) )
|
||||
#define readmemq(s,a) ((readlookup2[(uint32_t)((s)+(a))>>12]==-1 || (s)==0xFFFFFFFF || (((s)+(a)) & 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
|
||||
#endif
|
||||
|
||||
|
||||
int checkio(int port);
|
||||
|
||||
|
||||
#ifdef USE_NEW_DYNAREC
|
||||
#define check_io_perm(port) if (!IOPLp || (cpu_state.eflags&VM_FLAG)) \
|
||||
{ \
|
||||
int tempi = checkio(port); \
|
||||
if (cpu_state.abrt) return 1; \
|
||||
if (tempi) \
|
||||
{ \
|
||||
x86gpf("check_io_perm(): no permission",0); \
|
||||
return 1; \
|
||||
} \
|
||||
}
|
||||
#else
|
||||
#define check_io_perm(port) if (msw&1 && ((CPL > IOPL) || (cpu_state.eflags&VM_FLAG))) \
|
||||
{ \
|
||||
int tempi = checkio(port); \
|
||||
if (cpu_state.abrt) return 1; \
|
||||
if (tempi) \
|
||||
{ \
|
||||
x86gpf("check_io_perm(): no permission",0); \
|
||||
return 1; \
|
||||
} \
|
||||
}
|
||||
#endif
|
||||
|
||||
#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(chseg, low, high) \
|
||||
if ((low < (chseg)->limit_low) || (high > (chseg)->limit_high) || ((msw & 1) && !(cpu_state.eflags & VM_FLAG) && (((chseg)->access & 10) == 8))) \
|
||||
{ \
|
||||
x86gpf("Limit check (READ)", 0); \
|
||||
return 1; \
|
||||
} \
|
||||
if (msw&1 && !(cpu_state.eflags&VM_FLAG) && !((chseg)->access & 0x80)) \
|
||||
{ \
|
||||
if ((chseg) == &cpu_state.seg_ss) \
|
||||
x86ss(NULL,(chseg)->seg & 0xfffc); \
|
||||
else \
|
||||
x86np("Read from seg not present", (chseg)->seg & 0xfffc); \
|
||||
return 1; \
|
||||
} \
|
||||
if (cr0 >> 31) { \
|
||||
(void) mmutranslatereal((chseg)->base + low, 0); \
|
||||
(void) mmutranslatereal((chseg)->base + high, 0); \
|
||||
if (cpu_state.abrt) \
|
||||
return 1; \
|
||||
}
|
||||
|
||||
#define CHECK_READ_REP(chseg, low, high) \
|
||||
if ((low < (chseg)->limit_low) || (high > (chseg)->limit_high)) \
|
||||
{ \
|
||||
x86gpf("Limit check (READ)", 0); \
|
||||
break; \
|
||||
} \
|
||||
if (msw&1 && !(cpu_state.eflags&VM_FLAG) && !((chseg)->access & 0x80)) \
|
||||
{ \
|
||||
if ((chseg) == &cpu_state.seg_ss) \
|
||||
x86ss(NULL,(chseg)->seg & 0xfffc); \
|
||||
else \
|
||||
x86np("Read from seg not present", (chseg)->seg & 0xfffc); \
|
||||
break; \
|
||||
} \
|
||||
if (cr0 >> 31) { \
|
||||
(void) mmutranslatereal((chseg)->base + low, 0); \
|
||||
(void) mmutranslatereal((chseg)->base + high, 0); \
|
||||
if (cpu_state.abrt) \
|
||||
break; \
|
||||
}
|
||||
|
||||
#define CHECK_WRITE_COMMON(chseg, low, high) \
|
||||
if ((low < (chseg)->limit_low) || (high > (chseg)->limit_high) || !((chseg)->access & 2) || ((msw & 1) && !(cpu_state.eflags & VM_FLAG) && ((chseg)->access & 8))) \
|
||||
{ \
|
||||
x86gpf("Limit check (WRITE)", 0); \
|
||||
return 1; \
|
||||
} \
|
||||
if (msw&1 && !(cpu_state.eflags&VM_FLAG) && !((chseg)->access & 0x80)) \
|
||||
{ \
|
||||
if ((chseg) == &cpu_state.seg_ss) \
|
||||
x86ss(NULL,(chseg)->seg & 0xfffc); \
|
||||
else \
|
||||
x86np("Write to seg not present", (chseg)->seg & 0xfffc); \
|
||||
return 1; \
|
||||
}
|
||||
|
||||
#define CHECK_WRITE(chseg, low, high) \
|
||||
CHECK_WRITE_COMMON(chseg, low, high) \
|
||||
if (cr0 >> 31) { \
|
||||
(void) mmutranslatereal((chseg)->base + low, 1); \
|
||||
(void) mmutranslatereal((chseg)->base + high, 1); \
|
||||
if (cpu_state.abrt) \
|
||||
return 1; \
|
||||
}
|
||||
|
||||
#define CHECK_WRITE_REP(chseg, low, high) \
|
||||
if ((low < (chseg)->limit_low) || (high > (chseg)->limit_high)) \
|
||||
{ \
|
||||
x86gpf("Limit check (WRITE REP)", 0); \
|
||||
break; \
|
||||
} \
|
||||
if (msw&1 && !(cpu_state.eflags&VM_FLAG) && !((chseg)->access & 0x80)) \
|
||||
{ \
|
||||
if ((chseg) == &cpu_state.seg_ss) \
|
||||
x86ss(NULL,(chseg)->seg & 0xfffc); \
|
||||
else \
|
||||
x86np("Write (REP) to seg not present", (chseg)->seg & 0xfffc); \
|
||||
break; \
|
||||
} \
|
||||
if (cr0 >> 31) { \
|
||||
(void) mmutranslatereal((chseg)->base + low, 1); \
|
||||
(void) mmutranslatereal((chseg)->base + high, 1); \
|
||||
if (cpu_state.abrt) \
|
||||
break; \
|
||||
}
|
||||
|
||||
|
||||
#define NOTRM if (!(msw & 1) || (cpu_state.eflags & VM_FLAG))\
|
||||
{ \
|
||||
x86_int(6); \
|
||||
return 1; \
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static __inline uint8_t fastreadb(uint32_t a)
|
||||
{
|
||||
uint8_t *t;
|
||||
|
||||
if ((a >> 12) == pccache)
|
||||
return *((uint8_t *)&pccache2[a]);
|
||||
t = getpccache(a);
|
||||
if (cpu_state.abrt)
|
||||
return 0;
|
||||
pccache = a >> 12;
|
||||
pccache2 = t;
|
||||
return *((uint8_t *)&pccache2[a]);
|
||||
}
|
||||
|
||||
static __inline uint16_t fastreadw(uint32_t a)
|
||||
{
|
||||
uint8_t *t;
|
||||
uint16_t val;
|
||||
if ((a&0xFFF)>0xFFE)
|
||||
{
|
||||
val = fastreadb(a);
|
||||
val |= (fastreadb(a + 1) << 8);
|
||||
return val;
|
||||
}
|
||||
if ((a>>12)==pccache) return *((uint16_t *)&pccache2[a]);
|
||||
t = getpccache(a);
|
||||
if (cpu_state.abrt)
|
||||
return 0;
|
||||
|
||||
pccache = a >> 12;
|
||||
pccache2 = t;
|
||||
return *((uint16_t *)&pccache2[a]);
|
||||
}
|
||||
|
||||
static __inline uint32_t fastreadl(uint32_t a)
|
||||
{
|
||||
uint8_t *t;
|
||||
uint32_t val;
|
||||
if ((a&0xFFF)<0xFFD)
|
||||
{
|
||||
if ((a>>12)!=pccache)
|
||||
{
|
||||
t = getpccache(a);
|
||||
if (cpu_state.abrt)
|
||||
return 0;
|
||||
pccache2 = t;
|
||||
pccache=a>>12;
|
||||
}
|
||||
return *((uint32_t *)&pccache2[a]);
|
||||
}
|
||||
val = fastreadw(a);
|
||||
val |= (fastreadw(a + 2) << 16);
|
||||
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 fastreadb(cs + (cpu_state.pc - 1));
|
||||
}
|
||||
|
||||
static __inline uint16_t getword()
|
||||
{
|
||||
cpu_state.pc+=2;
|
||||
return fastreadw(cs+(cpu_state.pc-2));
|
||||
}
|
||||
|
||||
static __inline uint32_t getlong()
|
||||
{
|
||||
cpu_state.pc+=4;
|
||||
return fastreadl(cs+(cpu_state.pc-4));
|
||||
}
|
||||
|
||||
static __inline uint64_t getquad()
|
||||
{
|
||||
cpu_state.pc+=8;
|
||||
return fastreadl(cs+(cpu_state.pc-8)) | ((uint64_t)fastreadl(cs+(cpu_state.pc-4)) << 32);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static __inline uint8_t geteab()
|
||||
{
|
||||
if (cpu_mod == 3)
|
||||
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);
|
||||
}
|
||||
|
||||
static __inline uint16_t geteaw()
|
||||
{
|
||||
if (cpu_mod == 3)
|
||||
return cpu_state.regs[cpu_rm].w;
|
||||
if (eal_r)
|
||||
return *(uint16_t *)eal_r;
|
||||
return readmemw(easeg, cpu_state.eaaddr);
|
||||
}
|
||||
|
||||
static __inline uint32_t geteal()
|
||||
{
|
||||
if (cpu_mod == 3)
|
||||
return cpu_state.regs[cpu_rm].l;
|
||||
if (eal_r)
|
||||
return *eal_r;
|
||||
return readmeml(easeg, cpu_state.eaaddr);
|
||||
}
|
||||
|
||||
static __inline uint64_t geteaq()
|
||||
{
|
||||
return readmemq(easeg, cpu_state.eaaddr);
|
||||
}
|
||||
|
||||
static __inline uint8_t geteab_mem()
|
||||
{
|
||||
if (eal_r) return *(uint8_t *)eal_r;
|
||||
return readmemb(easeg,cpu_state.eaaddr);
|
||||
}
|
||||
static __inline uint16_t geteaw_mem()
|
||||
{
|
||||
if (eal_r) return *(uint16_t *)eal_r;
|
||||
return readmemw(easeg,cpu_state.eaaddr);
|
||||
}
|
||||
static __inline uint32_t geteal_mem()
|
||||
{
|
||||
if (eal_r) return *eal_r;
|
||||
return readmeml(easeg,cpu_state.eaaddr);
|
||||
}
|
||||
|
||||
static __inline int seteaq_cwc(void)
|
||||
{
|
||||
CHECK_WRITE_COMMON(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __inline void seteaq(uint64_t v)
|
||||
{
|
||||
if (seteaq_cwc())
|
||||
return;
|
||||
#ifdef USE_NEW_DYNAREC
|
||||
writememql(easeg + cpu_state.eaaddr, v);
|
||||
#else
|
||||
writememql(easeg, cpu_state.eaaddr, v);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef USE_NEW_DYNAREC
|
||||
#define seteab(v) if (cpu_mod!=3) { CHECK_WRITE_COMMON(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr); 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) { CHECK_WRITE_COMMON(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 1); 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) { CHECK_WRITE_COMMON(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3); if (eal_w) *eal_w=v; else writememll(easeg+cpu_state.eaaddr,v); } else cpu_state.regs[cpu_rm].l=v
|
||||
#else
|
||||
#define seteab(v) if (cpu_mod!=3) { CHECK_WRITE_COMMON(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr); 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) { CHECK_WRITE_COMMON(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 1); 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) { CHECK_WRITE_COMMON(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3); if (eal_w) *eal_w=v; else { writememll(easeg,cpu_state.eaaddr,v); } } else cpu_state.regs[cpu_rm].l=v
|
||||
#endif
|
||||
|
||||
#ifdef USE_NEW_DYNAREC
|
||||
#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);
|
||||
#else
|
||||
#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);
|
||||
#endif
|
||||
|
||||
#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
|
||||
|
||||
#endif
|
||||
910
src/cpu_common/386_dynarec - Cópia (2).c
Normal file
910
src/cpu_common/386_dynarec - Cópia (2).c
Normal file
@@ -0,0 +1,910 @@
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <wchar.h>
|
||||
#include <math.h>
|
||||
#ifndef INFINITY
|
||||
# define INFINITY (__builtin_inff())
|
||||
#endif
|
||||
|
||||
#define HAVE_STDARG_H
|
||||
#include "86box.h"
|
||||
#include "cpu.h"
|
||||
#include "x86.h"
|
||||
#include "x86_ops.h"
|
||||
#include "x87.h"
|
||||
#include "86box_io.h"
|
||||
#include "mem.h"
|
||||
#include "nmi.h"
|
||||
#include "pic.h"
|
||||
#include "timer.h"
|
||||
#include "fdd.h"
|
||||
#include "fdc.h"
|
||||
#ifdef USE_DYNAREC
|
||||
#include "codegen.h"
|
||||
#ifdef USE_NEW_DYNAREC
|
||||
#include "codegen_backend.h"
|
||||
#endif
|
||||
#endif
|
||||
#include "386_common.h"
|
||||
|
||||
|
||||
#define CPU_BLOCK_END() cpu_block_end = 1
|
||||
|
||||
|
||||
int inrecomp = 0, cpu_block_end = 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;
|
||||
|
||||
|
||||
#ifdef ENABLE_386_DYNAREC_LOG
|
||||
int x386_dynarec_do_log = ENABLE_386_DYNAREC_LOG;
|
||||
|
||||
|
||||
void
|
||||
x386_dynarec_log(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (x386_dynarec_do_log) {
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define x386_dynarec_log(fmt, ...)
|
||||
#endif
|
||||
|
||||
|
||||
static __inline void fetch_ea_32_long(uint32_t rmdat)
|
||||
{
|
||||
eal_r = eal_w = NULL;
|
||||
easeg = cpu_state.ea_seg->base;
|
||||
if (cpu_rm == 4)
|
||||
{
|
||||
uint8_t sib = rmdat >> 8;
|
||||
|
||||
switch (cpu_mod)
|
||||
{
|
||||
case 0:
|
||||
cpu_state.eaaddr = cpu_state.regs[sib & 7].l;
|
||||
cpu_state.pc++;
|
||||
break;
|
||||
case 1:
|
||||
cpu_state.pc++;
|
||||
cpu_state.eaaddr = ((uint32_t)(int8_t)getbyte()) + cpu_state.regs[sib & 7].l;
|
||||
break;
|
||||
case 2:
|
||||
cpu_state.eaaddr = (fastreadl(cs + cpu_state.pc + 1)) + cpu_state.regs[sib & 7].l;
|
||||
cpu_state.pc += 5;
|
||||
break;
|
||||
}
|
||||
/*SIB byte present*/
|
||||
if ((sib & 7) == 5 && !cpu_mod)
|
||||
cpu_state.eaaddr = getlong();
|
||||
else if ((sib & 6) == 4 && !cpu_state.ssegs)
|
||||
{
|
||||
easeg = 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);
|
||||
}
|
||||
else
|
||||
{
|
||||
cpu_state.eaaddr = cpu_state.regs[cpu_rm].l;
|
||||
if (cpu_mod)
|
||||
{
|
||||
if (cpu_rm == 5 && !cpu_state.ssegs)
|
||||
{
|
||||
easeg = ss;
|
||||
cpu_state.ea_seg = &cpu_state.seg_ss;
|
||||
}
|
||||
if (cpu_mod == 1)
|
||||
{
|
||||
cpu_state.eaaddr += ((uint32_t)(int8_t)(rmdat >> 8));
|
||||
cpu_state.pc++;
|
||||
}
|
||||
else
|
||||
{
|
||||
cpu_state.eaaddr += getlong();
|
||||
}
|
||||
}
|
||||
else if (cpu_rm == 5)
|
||||
{
|
||||
cpu_state.eaaddr = getlong();
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
cpu_state.last_ea = cpu_state.eaaddr;
|
||||
}
|
||||
|
||||
static __inline void fetch_ea_16_long(uint32_t rmdat)
|
||||
{
|
||||
eal_r = eal_w = NULL;
|
||||
easeg = cpu_state.ea_seg->base;
|
||||
if (!cpu_mod && cpu_rm == 6)
|
||||
{
|
||||
cpu_state.eaaddr = getword();
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (cpu_mod)
|
||||
{
|
||||
case 0:
|
||||
cpu_state.eaaddr = 0;
|
||||
break;
|
||||
case 1:
|
||||
cpu_state.eaaddr = (uint16_t)(int8_t)(rmdat >> 8); cpu_state.pc++;
|
||||
break;
|
||||
case 2:
|
||||
cpu_state.eaaddr = getword();
|
||||
break;
|
||||
}
|
||||
cpu_state.eaaddr += (*mod1add[0][cpu_rm]) + (*mod1add[1][cpu_rm]);
|
||||
if (mod1seg[cpu_rm] == &ss && !cpu_state.ssegs)
|
||||
{
|
||||
easeg = ss;
|
||||
cpu_state.ea_seg = &cpu_state.seg_ss;
|
||||
}
|
||||
cpu_state.eaaddr &= 0xFFFF;
|
||||
}
|
||||
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);
|
||||
}
|
||||
cpu_state.last_ea = cpu_state.eaaddr;
|
||||
}
|
||||
|
||||
#define fetch_ea_16(rmdat) cpu_state.pc++; cpu_mod=(rmdat >> 6) & 3; cpu_reg=(rmdat >> 3) & 7; cpu_rm = rmdat & 7; if (cpu_mod != 3) { fetch_ea_16_long(rmdat); if (cpu_state.abrt) return 1; }
|
||||
#define fetch_ea_32(rmdat) cpu_state.pc++; cpu_mod=(rmdat >> 6) & 3; cpu_reg=(rmdat >> 3) & 7; cpu_rm = rmdat & 7; if (cpu_mod != 3) { fetch_ea_32_long(rmdat); } if (cpu_state.abrt) return 1
|
||||
|
||||
#include "x86_flags.h"
|
||||
|
||||
|
||||
/*Prefetch emulation is a fairly simplistic model:
|
||||
- All instruction bytes must be fetched before it starts.
|
||||
- Cycles used for non-instruction memory accesses are counted and subtracted
|
||||
from the total cycles taken
|
||||
- Any remaining cycles are used to refill the prefetch queue.
|
||||
|
||||
Note that this is only used for 286 / 386 systems. It is disabled when the
|
||||
internal cache on 486+ CPUs is enabled.
|
||||
*/
|
||||
static int prefetch_bytes = 0;
|
||||
static int prefetch_prefixes = 0;
|
||||
|
||||
static void prefetch_run(int instr_cycles, int bytes, int modrm, int reads, int reads_l, int writes, int writes_l, int ea32)
|
||||
{
|
||||
int mem_cycles = reads*cpu_cycles_read + reads_l*cpu_cycles_read_l + writes*cpu_cycles_write + writes_l*cpu_cycles_write_l;
|
||||
|
||||
if (instr_cycles < mem_cycles)
|
||||
instr_cycles = mem_cycles;
|
||||
|
||||
prefetch_bytes -= prefetch_prefixes;
|
||||
prefetch_bytes -= bytes;
|
||||
if (modrm != -1)
|
||||
{
|
||||
if (ea32)
|
||||
{
|
||||
if ((modrm & 7) == 4)
|
||||
{
|
||||
if ((modrm & 0x700) == 0x500)
|
||||
prefetch_bytes -= 5;
|
||||
else if ((modrm & 0xc0) == 0x40)
|
||||
prefetch_bytes -= 2;
|
||||
else if ((modrm & 0xc0) == 0x80)
|
||||
prefetch_bytes -= 5;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((modrm & 0xc7) == 0x05)
|
||||
prefetch_bytes -= 4;
|
||||
else if ((modrm & 0xc0) == 0x40)
|
||||
prefetch_bytes--;
|
||||
else if ((modrm & 0xc0) == 0x80)
|
||||
prefetch_bytes -= 4;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((modrm & 0xc7) == 0x06)
|
||||
prefetch_bytes -= 2;
|
||||
else if ((modrm & 0xc0) != 0xc0)
|
||||
prefetch_bytes -= ((modrm & 0xc0) >> 6);
|
||||
}
|
||||
}
|
||||
|
||||
/* Fill up prefetch queue */
|
||||
while (prefetch_bytes < 0)
|
||||
{
|
||||
prefetch_bytes += cpu_prefetch_width;
|
||||
cycles -= cpu_prefetch_cycles;
|
||||
}
|
||||
|
||||
/* Subtract cycles used for memory access by instruction */
|
||||
instr_cycles -= mem_cycles;
|
||||
|
||||
while (instr_cycles >= cpu_prefetch_cycles)
|
||||
{
|
||||
prefetch_bytes += cpu_prefetch_width;
|
||||
instr_cycles -= cpu_prefetch_cycles;
|
||||
}
|
||||
|
||||
prefetch_prefixes = 0;
|
||||
if (prefetch_bytes > 16)
|
||||
prefetch_bytes = 16;
|
||||
}
|
||||
|
||||
static void prefetch_flush()
|
||||
{
|
||||
prefetch_bytes = 0;
|
||||
}
|
||||
|
||||
#define PREFETCH_RUN(instr_cycles, bytes, modrm, reads, reads_l, writes, writes_l, ea32) \
|
||||
do { if (cpu_prefetch_cycles) prefetch_run(instr_cycles, bytes, modrm, reads, reads_l, writes, writes_l, ea32); } while (0)
|
||||
|
||||
#define PREFETCH_PREFIX() do { if (cpu_prefetch_cycles) prefetch_prefixes++; } while (0)
|
||||
#define PREFETCH_FLUSH() prefetch_flush()
|
||||
|
||||
|
||||
void enter_smm()
|
||||
{
|
||||
uint32_t smram_state = smbase + 0xfe00;
|
||||
uint32_t old_cr0 = cr0;
|
||||
uint32_t old_flags = cpu_state.flags | ((uint32_t)cpu_state.eflags << 16);
|
||||
|
||||
cr0 &= ~0x8000000d;
|
||||
cpu_state.flags = 2;
|
||||
cpu_state.eflags = 0;
|
||||
|
||||
in_smm = 1;
|
||||
mem_set_mem_state(smbase, 131072, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
|
||||
smi_latched = 1;
|
||||
|
||||
mem_writel_phys(smram_state + 0xf8, smbase);
|
||||
mem_writel_phys(smram_state + 0x128, cr4);
|
||||
mem_writel_phys(smram_state + 0x130, cpu_state.seg_es.limit);
|
||||
mem_writel_phys(smram_state + 0x134, cpu_state.seg_es.base);
|
||||
mem_writel_phys(smram_state + 0x138, cpu_state.seg_es.access);
|
||||
mem_writel_phys(smram_state + 0x13c, cpu_state.seg_cs.limit);
|
||||
mem_writel_phys(smram_state + 0x140, cpu_state.seg_cs.base);
|
||||
mem_writel_phys(smram_state + 0x144, cpu_state.seg_cs.access);
|
||||
mem_writel_phys(smram_state + 0x148, cpu_state.seg_ss.limit);
|
||||
mem_writel_phys(smram_state + 0x14c, cpu_state.seg_ss.base);
|
||||
mem_writel_phys(smram_state + 0x150, cpu_state.seg_ss.access);
|
||||
mem_writel_phys(smram_state + 0x154, cpu_state.seg_ds.limit);
|
||||
mem_writel_phys(smram_state + 0x158, cpu_state.seg_ds.base);
|
||||
mem_writel_phys(smram_state + 0x15c, cpu_state.seg_ds.access);
|
||||
mem_writel_phys(smram_state + 0x160, cpu_state.seg_fs.limit);
|
||||
mem_writel_phys(smram_state + 0x164, cpu_state.seg_fs.base);
|
||||
mem_writel_phys(smram_state + 0x168, cpu_state.seg_fs.access);
|
||||
mem_writel_phys(smram_state + 0x16c, cpu_state.seg_gs.limit);
|
||||
mem_writel_phys(smram_state + 0x170, cpu_state.seg_gs.base);
|
||||
mem_writel_phys(smram_state + 0x174, cpu_state.seg_gs.access);
|
||||
mem_writel_phys(smram_state + 0x178, ldt.limit);
|
||||
mem_writel_phys(smram_state + 0x17c, ldt.base);
|
||||
mem_writel_phys(smram_state + 0x180, ldt.access);
|
||||
mem_writel_phys(smram_state + 0x184, gdt.limit);
|
||||
mem_writel_phys(smram_state + 0x188, gdt.base);
|
||||
mem_writel_phys(smram_state + 0x18c, gdt.access);
|
||||
mem_writel_phys(smram_state + 0x190, idt.limit);
|
||||
mem_writel_phys(smram_state + 0x194, idt.base);
|
||||
mem_writel_phys(smram_state + 0x198, idt.access);
|
||||
mem_writel_phys(smram_state + 0x19c, tr.limit);
|
||||
mem_writel_phys(smram_state + 0x1a0, tr.base);
|
||||
mem_writel_phys(smram_state + 0x1a4, tr.access);
|
||||
|
||||
mem_writel_phys(smram_state + 0x1a8, cpu_state.seg_es.seg);
|
||||
mem_writel_phys(smram_state + 0x1ac, cpu_state.seg_cs.seg);
|
||||
mem_writel_phys(smram_state + 0x1b0, cpu_state.seg_ss.seg);
|
||||
mem_writel_phys(smram_state + 0x1b4, cpu_state.seg_ds.seg);
|
||||
mem_writel_phys(smram_state + 0x1b8, cpu_state.seg_fs.seg);
|
||||
mem_writel_phys(smram_state + 0x1bc, cpu_state.seg_gs.seg);
|
||||
mem_writel_phys(smram_state + 0x1c0, ldt.seg);
|
||||
mem_writel_phys(smram_state + 0x1c4, tr.seg);
|
||||
|
||||
mem_writel_phys(smram_state + 0x1c8, dr[7]);
|
||||
mem_writel_phys(smram_state + 0x1cc, dr[6]);
|
||||
mem_writel_phys(smram_state + 0x1d0, EAX);
|
||||
mem_writel_phys(smram_state + 0x1d4, ECX);
|
||||
mem_writel_phys(smram_state + 0x1d8, EDX);
|
||||
mem_writel_phys(smram_state + 0x1dc, EBX);
|
||||
mem_writel_phys(smram_state + 0x1e0, ESP);
|
||||
mem_writel_phys(smram_state + 0x1e4, EBP);
|
||||
mem_writel_phys(smram_state + 0x1e8, ESI);
|
||||
mem_writel_phys(smram_state + 0x1ec, EDI);
|
||||
mem_writel_phys(smram_state + 0x1f0, cpu_state.pc);
|
||||
mem_writel_phys(smram_state + 0x1d0, old_flags);
|
||||
mem_writel_phys(smram_state + 0x1f8, cr3);
|
||||
mem_writel_phys(smram_state + 0x1fc, old_cr0);
|
||||
|
||||
ds = es = fs_seg = gs = ss = 0;
|
||||
|
||||
DS = ES = FS = GS = SS = 0;
|
||||
|
||||
cpu_state.seg_ds.limit = cpu_state.seg_es.limit = cpu_state.seg_fs.limit = cpu_state.seg_gs.limit
|
||||
= cpu_state.seg_ss.limit = 0xffffffff;
|
||||
|
||||
cpu_state.seg_ds.limit_high = cpu_state.seg_es.limit_high = cpu_state.seg_fs.limit_high
|
||||
= cpu_state.seg_gs.limit_high = cpu_state.seg_ss.limit_high = 0xffffffff;
|
||||
|
||||
cpu_state.seg_ds.limit_low = cpu_state.seg_es.limit_low = cpu_state.seg_fs.limit_low
|
||||
= cpu_state.seg_gs.limit_low = cpu_state.seg_ss.limit_low = 0;
|
||||
|
||||
cpu_state.seg_ds.access = cpu_state.seg_es.access = cpu_state.seg_fs.access
|
||||
= cpu_state.seg_gs.access = cpu_state.seg_ss.access = 0x93;
|
||||
|
||||
cpu_state.seg_ds.checked = cpu_state.seg_es.checked = cpu_state.seg_fs.checked
|
||||
= cpu_state.seg_gs.checked = cpu_state.seg_ss.checked = 1;
|
||||
|
||||
CS = 0x3000;
|
||||
cs = smbase;
|
||||
cpu_state.seg_cs.limit = cpu_state.seg_cs.limit_high = 0xffffffff;
|
||||
cpu_state.seg_cs.limit_low = 0;
|
||||
cpu_state.seg_cs.access = 0x93;
|
||||
cpu_state.seg_cs.checked = 1;
|
||||
|
||||
cr4 = 0;
|
||||
dr[7] = 0x400;
|
||||
cpu_state.pc = 0x8000;
|
||||
|
||||
nmi_mask = 0;
|
||||
}
|
||||
|
||||
void leave_smm()
|
||||
{
|
||||
uint32_t smram_state = smbase + 0xfe00;
|
||||
|
||||
smbase = mem_readl_phys(smram_state + 0xf8);
|
||||
cr4 = mem_readl_phys(smram_state + 0x128);
|
||||
|
||||
cpu_state.seg_es.limit = cpu_state.seg_es.limit_high = mem_readl_phys(smram_state + 0x130);
|
||||
cpu_state.seg_es.base = mem_readl_phys(smram_state + 0x134);
|
||||
cpu_state.seg_es.limit_low = cpu_state.seg_es.base;
|
||||
cpu_state.seg_es.access = mem_readl_phys(smram_state + 0x138);
|
||||
|
||||
cpu_state.seg_cs.limit = cpu_state.seg_cs.limit_high = mem_readl_phys(smram_state + 0x13c);
|
||||
cpu_state.seg_cs.base = mem_readl_phys(smram_state + 0x140);
|
||||
cpu_state.seg_cs.limit_low = cpu_state.seg_cs.base;
|
||||
cpu_state.seg_cs.access = mem_readl_phys(smram_state + 0x144);
|
||||
|
||||
cpu_state.seg_ss.limit = cpu_state.seg_ss.limit_high = mem_readl_phys(smram_state + 0x148);
|
||||
cpu_state.seg_ss.base = mem_readl_phys(smram_state + 0x14c);
|
||||
cpu_state.seg_ss.limit_low = cpu_state.seg_ss.base;
|
||||
cpu_state.seg_ss.access = mem_readl_phys(smram_state + 0x150);
|
||||
|
||||
cpu_state.seg_ds.limit = cpu_state.seg_ds.limit_high = mem_readl_phys(smram_state + 0x154);
|
||||
cpu_state.seg_ds.base = mem_readl_phys(smram_state + 0x158);
|
||||
cpu_state.seg_ds.limit_low = cpu_state.seg_ds.base;
|
||||
cpu_state.seg_ds.access = mem_readl_phys(smram_state + 0x15c);
|
||||
|
||||
cpu_state.seg_fs.limit = cpu_state.seg_fs.limit_high = mem_readl_phys(smram_state + 0x160);
|
||||
cpu_state.seg_fs.base = mem_readl_phys(smram_state + 0x164);
|
||||
cpu_state.seg_fs.limit_low = cpu_state.seg_fs.base;
|
||||
cpu_state.seg_fs.access = mem_readl_phys(smram_state + 0x168);
|
||||
|
||||
cpu_state.seg_gs.limit = cpu_state.seg_gs.limit_high = mem_readl_phys(smram_state + 0x16c);
|
||||
cpu_state.seg_gs.base = mem_readl_phys(smram_state + 0x170);
|
||||
cpu_state.seg_gs.limit_low = cpu_state.seg_gs.base;
|
||||
cpu_state.seg_gs.access = mem_readl_phys(smram_state + 0x174);
|
||||
|
||||
ldt.limit = ldt.limit_high = mem_readl_phys(smram_state + 0x178);
|
||||
ldt.base = mem_readl_phys(smram_state + 0x17c);
|
||||
ldt.limit_low = ldt.base;
|
||||
ldt.access = mem_readl_phys(smram_state + 0x180);
|
||||
|
||||
gdt.limit = gdt.limit_high = mem_readl_phys(smram_state + 0x184);
|
||||
gdt.base = mem_readl_phys(smram_state + 0x188);
|
||||
gdt.limit_low = gdt.base;
|
||||
gdt.access = mem_readl_phys(smram_state + 0x18c);
|
||||
|
||||
idt.limit = idt.limit_high = mem_readl_phys(smram_state + 0x190);
|
||||
idt.base = mem_readl_phys(smram_state + 0x194);
|
||||
idt.limit_low = idt.base;
|
||||
idt.access = mem_readl_phys(smram_state + 0x198);
|
||||
|
||||
tr.limit = tr.limit_high = mem_readl_phys(smram_state + 0x19c);
|
||||
tr.base = mem_readl_phys(smram_state + 0x1a0);
|
||||
tr.limit_low = tr.base;
|
||||
tr.access = mem_readl_phys(smram_state + 0x1a4);
|
||||
|
||||
ES = mem_readl_phys(smram_state + 0x1a8);
|
||||
CS = mem_readl_phys(smram_state + 0x1ac);
|
||||
SS = mem_readl_phys(smram_state + 0x1b0);
|
||||
DS = mem_readl_phys(smram_state + 0x1b4);
|
||||
FS = mem_readl_phys(smram_state + 0x1b8);
|
||||
GS = mem_readl_phys(smram_state + 0x1bc);
|
||||
ldt.seg = mem_readl_phys(smram_state + 0x1c0);
|
||||
tr.seg = mem_readl_phys(smram_state + 0x1c4);
|
||||
|
||||
dr[7] = mem_readl_phys(smram_state + 0x1c8);
|
||||
dr[6] = mem_readl_phys(smram_state + 0x1cc);
|
||||
EAX = mem_readl_phys(smram_state + 0x1d0);
|
||||
ECX = mem_readl_phys(smram_state + 0x1d4);
|
||||
EDX = mem_readl_phys(smram_state + 0x1d8);
|
||||
EBX = mem_readl_phys(smram_state + 0x1dc);
|
||||
ESP = mem_readl_phys(smram_state + 0x1e0);
|
||||
EBP = mem_readl_phys(smram_state + 0x1e4);
|
||||
ESI = mem_readl_phys(smram_state + 0x1e8);
|
||||
EDI = mem_readl_phys(smram_state + 0x1ec);
|
||||
|
||||
cpu_state.pc = mem_readl_phys(smram_state + 0x1f0);
|
||||
uint32_t new_flags = mem_readl_phys(smram_state + 0x1f4);
|
||||
cpu_state.flags = new_flags & 0xffff;
|
||||
cpu_state.eflags = new_flags >> 16;
|
||||
cr3 = mem_readl_phys(smram_state + 0x1f8);
|
||||
cr0 = mem_readl_phys(smram_state + 0x1fc);
|
||||
|
||||
cpu_state.seg_cs.access &= ~0x60;
|
||||
cpu_state.seg_cs.access |= cpu_state.seg_ss.access & 0x60; //cpl is dpl of ss
|
||||
|
||||
if((cr0 & 1) && !(cpu_state.eflags&VM_FLAG))
|
||||
{
|
||||
cpu_state.seg_cs.checked = CS ? 1 : 0;
|
||||
cpu_state.seg_ds.checked = DS ? 1 : 0;
|
||||
cpu_state.seg_es.checked = ES ? 1 : 0;
|
||||
cpu_state.seg_fs.checked = FS ? 1 : 0;
|
||||
cpu_state.seg_gs.checked = GS ? 1 : 0;
|
||||
cpu_state.seg_ss.checked = SS ? 1 : 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
cpu_state.seg_cs.checked = cpu_state.seg_ds.checked = cpu_state.seg_es.checked
|
||||
= cpu_state.seg_fs.checked = cpu_state.seg_gs.checked = cpu_state.seg_ss.checked = 1;
|
||||
}
|
||||
|
||||
mem_restore_mem_state(smbase, 131072);
|
||||
in_smm = 0;
|
||||
|
||||
nmi_mask = 1;
|
||||
}
|
||||
|
||||
#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)) && !(cpu_state.flags & T_FLAG))
|
||||
|
||||
#ifdef USE_DYNAREC
|
||||
static int cycles_main = 0;
|
||||
|
||||
|
||||
void exec386_dynarec(int cycs)
|
||||
{
|
||||
int vector;
|
||||
uint32_t addr;
|
||||
int tempi;
|
||||
int cycdiff;
|
||||
int oldcyc;
|
||||
uint32_t start_pc = 0;
|
||||
|
||||
int cyc_period = cycs / 2000; /*5us*/
|
||||
|
||||
cycles_main += cycs;
|
||||
while (cycles_main > 0)
|
||||
{
|
||||
int cycles_start;
|
||||
|
||||
cycles += cyc_period;
|
||||
cycles_start = cycles;
|
||||
|
||||
while (cycles>0)
|
||||
{
|
||||
oldcs = CS;
|
||||
cpu_state.oldpc = cpu_state.pc;
|
||||
oldcpl = CPL;
|
||||
cpu_state.op32 = use32;
|
||||
|
||||
|
||||
cycdiff=0;
|
||||
oldcyc=cycles;
|
||||
if (!CACHE_ON()) /*Interpret block*/
|
||||
{
|
||||
cpu_block_end = 0;
|
||||
x86_was_reset = 0;
|
||||
while (!cpu_block_end)
|
||||
{
|
||||
oldcs=CS;
|
||||
cpu_state.oldpc = cpu_state.pc;
|
||||
oldcpl = CPL;
|
||||
cpu_state.op32 = use32;
|
||||
|
||||
cpu_state.ea_seg = &cpu_state.seg_ds;
|
||||
cpu_state.ssegs = 0;
|
||||
|
||||
fetchdat = fastreadl(cs + cpu_state.pc);
|
||||
if (!cpu_state.abrt)
|
||||
{
|
||||
opcode = fetchdat & 0xFF;
|
||||
fetchdat >>= 8;
|
||||
trap = cpu_state.flags & T_FLAG;
|
||||
|
||||
cpu_state.pc++;
|
||||
x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat);
|
||||
}
|
||||
|
||||
if (!use32) cpu_state.pc &= 0xffff;
|
||||
|
||||
if (((cs + cpu_state.pc) >> 12) != pccache)
|
||||
CPU_BLOCK_END();
|
||||
|
||||
/* if (ssegs)
|
||||
{
|
||||
ds=oldds;
|
||||
ss=oldss;
|
||||
ssegs=0;
|
||||
}*/
|
||||
|
||||
if (in_smm && smi_line && is_pentium)
|
||||
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++;
|
||||
|
||||
/* if ((cs + pc) == 4)
|
||||
fatal("4\n");*/
|
||||
/* if (ins >= 141400000)
|
||||
output = 3;*/
|
||||
}
|
||||
}
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
/*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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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->valid)
|
||||
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)
|
||||
{
|
||||
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->valid)
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
if (valid_block && block->was_recompiled)
|
||||
{
|
||||
void (*code)() = (void *)&block->data[BLOCK_START];
|
||||
|
||||
codeblock_hash[hash] = block;
|
||||
|
||||
inrecomp=1;
|
||||
code();
|
||||
inrecomp=0;
|
||||
if (!use32) cpu_state.pc &= 0xffff;
|
||||
cpu_recomp_blocks++;
|
||||
}
|
||||
else if (valid_block && !cpu_state.abrt)
|
||||
{
|
||||
start_pc = cpu_state.pc;
|
||||
|
||||
cpu_block_end = 0;
|
||||
x86_was_reset = 0;
|
||||
|
||||
cpu_new_blocks++;
|
||||
|
||||
codegen_block_start_recompile(block);
|
||||
codegen_in_recompile = 1;
|
||||
|
||||
while (!cpu_block_end)
|
||||
{
|
||||
oldcs=CS;
|
||||
cpu_state.oldpc = cpu_state.pc;
|
||||
oldcpl = CPL;
|
||||
cpu_state.op32 = use32;
|
||||
|
||||
cpu_state.ea_seg = &cpu_state.seg_ds;
|
||||
cpu_state.ssegs = 0;
|
||||
|
||||
fetchdat = fastreadl(cs + cpu_state.pc);
|
||||
if (!cpu_state.abrt)
|
||||
{
|
||||
opcode = fetchdat & 0xFF;
|
||||
fetchdat >>= 8;
|
||||
trap = cpu_state.flags & T_FLAG;
|
||||
|
||||
cpu_state.pc++;
|
||||
|
||||
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);
|
||||
|
||||
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();
|
||||
|
||||
if (in_smm && smi_line && is_pentium)
|
||||
CPU_BLOCK_END();
|
||||
|
||||
if (trap)
|
||||
CPU_BLOCK_END();
|
||||
|
||||
if (nmi && nmi_enable && nmi_mask)
|
||||
CPU_BLOCK_END();
|
||||
|
||||
|
||||
if (cpu_state.abrt)
|
||||
{
|
||||
codegen_block_remove();
|
||||
CPU_BLOCK_END();
|
||||
}
|
||||
|
||||
ins++;
|
||||
}
|
||||
|
||||
if (!cpu_state.abrt && !x86_was_reset)
|
||||
codegen_block_end_recompile(block);
|
||||
|
||||
if (x86_was_reset)
|
||||
codegen_reset();
|
||||
|
||||
codegen_in_recompile = 0;
|
||||
}
|
||||
else if (!cpu_state.abrt)
|
||||
{
|
||||
/*Mark block but do not recompile*/
|
||||
start_pc = cpu_state.pc;
|
||||
|
||||
cpu_block_end = 0;
|
||||
x86_was_reset = 0;
|
||||
|
||||
codegen_block_init(phys_addr);
|
||||
|
||||
while (!cpu_block_end)
|
||||
{
|
||||
oldcs=CS;
|
||||
cpu_state.oldpc = cpu_state.pc;
|
||||
oldcpl = CPL;
|
||||
cpu_state.op32 = use32;
|
||||
|
||||
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)
|
||||
{
|
||||
opcode = fetchdat & 0xFF;
|
||||
fetchdat >>= 8;
|
||||
trap = cpu_state.flags & T_FLAG;
|
||||
|
||||
cpu_state.pc++;
|
||||
|
||||
x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat);
|
||||
|
||||
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();
|
||||
|
||||
if (in_smm && smi_line && is_pentium)
|
||||
CPU_BLOCK_END();
|
||||
|
||||
if (trap)
|
||||
CPU_BLOCK_END();
|
||||
|
||||
if (nmi && nmi_enable && nmi_mask)
|
||||
CPU_BLOCK_END();
|
||||
|
||||
|
||||
if (cpu_state.abrt)
|
||||
{
|
||||
codegen_block_remove();
|
||||
CPU_BLOCK_END();
|
||||
}
|
||||
|
||||
ins++;
|
||||
}
|
||||
|
||||
if (!cpu_state.abrt && !x86_was_reset)
|
||||
codegen_block_end();
|
||||
|
||||
if (x86_was_reset)
|
||||
codegen_reset();
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
cpu_state.abrt = 0;
|
||||
CS = oldcs;
|
||||
cpu_state.pc = cpu_state.oldpc;
|
||||
#ifdef ENABLE_386_DYNAREC_LOG
|
||||
x386_dynarec_log("Double fault %i\n", ins);
|
||||
#endif
|
||||
pmodeint(8, 0);
|
||||
if (cpu_state.abrt)
|
||||
{
|
||||
cpu_state.abrt = 0;
|
||||
softresetx86();
|
||||
cpu_set_edx();
|
||||
#ifdef ENABLE_386_DYNAREC_LOG
|
||||
x386_dynarec_log("Triple fault - reset\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (in_smm && smi_line && is_pentium)
|
||||
{
|
||||
enter_smm();
|
||||
}
|
||||
|
||||
if (trap)
|
||||
{
|
||||
flags_rebuild();
|
||||
if (msw&1)
|
||||
{
|
||||
pmodeint(1,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 = (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;
|
||||
oldcs = CS;
|
||||
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)
|
||||
{
|
||||
vector=picinterrupt();
|
||||
if (vector!=-1)
|
||||
{
|
||||
CPU_BLOCK_END();
|
||||
flags_rebuild();
|
||||
if (msw&1)
|
||||
{
|
||||
pmodeint(vector,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=vector<<2;
|
||||
cpu_state.flags&=~I_FLAG;
|
||||
cpu_state.flags&=~T_FLAG;
|
||||
oxpc=cpu_state.pc;
|
||||
cpu_state.pc=readmemw(0,addr);
|
||||
loadcs(readmemw(0,addr+2));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t)tsc))
|
||||
timer_process();
|
||||
|
||||
cycles_main -= (cycles_start - cycles);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
1008
src/cpu_common/386_dynarec - Cópia.c
Normal file
1008
src/cpu_common/386_dynarec - Cópia.c
Normal file
File diff suppressed because it is too large
Load Diff
1007
src/cpu_common/386_dynarec.c
Normal file
1007
src/cpu_common/386_dynarec.c
Normal file
File diff suppressed because it is too large
Load Diff
900
src/cpu_common/386_dynarec.c.temp
Normal file
900
src/cpu_common/386_dynarec.c.temp
Normal file
@@ -0,0 +1,900 @@
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <wchar.h>
|
||||
#include <math.h>
|
||||
#ifndef INFINITY
|
||||
# define INFINITY (__builtin_inff())
|
||||
#endif
|
||||
|
||||
#define HAVE_STDARG_H
|
||||
#include "86box.h"
|
||||
#include "cpu.h"
|
||||
#include "x86.h"
|
||||
#include "x86_ops.h"
|
||||
#include "x87.h"
|
||||
#include "86box_io.h"
|
||||
#include "mem.h"
|
||||
#include "nmi.h"
|
||||
#include "pic.h"
|
||||
#include "timer.h"
|
||||
#include "fdd.h"
|
||||
#include "fdc.h"
|
||||
#ifdef USE_DYNAREC
|
||||
#include "codegen.h"
|
||||
#ifdef USE_NEW_DYNAREC
|
||||
#include "codegen_backend.h"
|
||||
#endif
|
||||
#endif
|
||||
#include "386_common.h"
|
||||
|
||||
|
||||
#define CPU_BLOCK_END() cpu_block_end = 1
|
||||
|
||||
|
||||
int inrecomp = 0, cpu_block_end = 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;
|
||||
|
||||
|
||||
#ifdef ENABLE_386_DYNAREC_LOG
|
||||
int x386_dynarec_do_log = ENABLE_386_DYNAREC_LOG;
|
||||
|
||||
|
||||
void
|
||||
x386_dynarec_log(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (x386_dynarec_do_log) {
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define x386_dynarec_log(fmt, ...)
|
||||
#endif
|
||||
|
||||
|
||||
static __inline void fetch_ea_32_long(uint32_t rmdat)
|
||||
{
|
||||
eal_r = eal_w = NULL;
|
||||
easeg = cpu_state.ea_seg->base;
|
||||
if (cpu_rm == 4)
|
||||
{
|
||||
uint8_t sib = rmdat >> 8;
|
||||
|
||||
switch (cpu_mod)
|
||||
{
|
||||
case 0:
|
||||
cpu_state.eaaddr = cpu_state.regs[sib & 7].l;
|
||||
cpu_state.pc++;
|
||||
break;
|
||||
case 1:
|
||||
cpu_state.pc++;
|
||||
cpu_state.eaaddr = ((uint32_t)(int8_t)getbyte()) + cpu_state.regs[sib & 7].l;
|
||||
break;
|
||||
case 2:
|
||||
cpu_state.eaaddr = (fastreadl(cs + cpu_state.pc + 1)) + cpu_state.regs[sib & 7].l;
|
||||
cpu_state.pc += 5;
|
||||
break;
|
||||
}
|
||||
/*SIB byte present*/
|
||||
if ((sib & 7) == 5 && !cpu_mod)
|
||||
cpu_state.eaaddr = getlong();
|
||||
else if ((sib & 6) == 4 && !cpu_state.ssegs)
|
||||
{
|
||||
easeg = 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);
|
||||
}
|
||||
else
|
||||
{
|
||||
cpu_state.eaaddr = cpu_state.regs[cpu_rm].l;
|
||||
if (cpu_mod)
|
||||
{
|
||||
if (cpu_rm == 5 && !cpu_state.ssegs)
|
||||
{
|
||||
easeg = ss;
|
||||
cpu_state.ea_seg = &cpu_state.seg_ss;
|
||||
}
|
||||
if (cpu_mod == 1)
|
||||
{
|
||||
cpu_state.eaaddr += ((uint32_t)(int8_t)(rmdat >> 8));
|
||||
cpu_state.pc++;
|
||||
}
|
||||
else
|
||||
{
|
||||
cpu_state.eaaddr += getlong();
|
||||
}
|
||||
}
|
||||
else if (cpu_rm == 5)
|
||||
{
|
||||
cpu_state.eaaddr = getlong();
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
cpu_state.last_ea = cpu_state.eaaddr;
|
||||
}
|
||||
|
||||
static __inline void fetch_ea_16_long(uint32_t rmdat)
|
||||
{
|
||||
eal_r = eal_w = NULL;
|
||||
easeg = cpu_state.ea_seg->base;
|
||||
if (!cpu_mod && cpu_rm == 6)
|
||||
{
|
||||
cpu_state.eaaddr = getword();
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (cpu_mod)
|
||||
{
|
||||
case 0:
|
||||
cpu_state.eaaddr = 0;
|
||||
break;
|
||||
case 1:
|
||||
cpu_state.eaaddr = (uint16_t)(int8_t)(rmdat >> 8); cpu_state.pc++;
|
||||
break;
|
||||
case 2:
|
||||
cpu_state.eaaddr = getword();
|
||||
break;
|
||||
}
|
||||
cpu_state.eaaddr += (*mod1add[0][cpu_rm]) + (*mod1add[1][cpu_rm]);
|
||||
if (mod1seg[cpu_rm] == &ss && !cpu_state.ssegs)
|
||||
{
|
||||
easeg = ss;
|
||||
cpu_state.ea_seg = &cpu_state.seg_ss;
|
||||
}
|
||||
cpu_state.eaaddr &= 0xFFFF;
|
||||
}
|
||||
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);
|
||||
}
|
||||
cpu_state.last_ea = cpu_state.eaaddr;
|
||||
}
|
||||
|
||||
#define fetch_ea_16(rmdat) cpu_state.pc++; cpu_mod=(rmdat >> 6) & 3; cpu_reg=(rmdat >> 3) & 7; cpu_rm = rmdat & 7; if (cpu_mod != 3) { fetch_ea_16_long(rmdat); if (cpu_state.abrt) return 1; }
|
||||
#define fetch_ea_32(rmdat) cpu_state.pc++; cpu_mod=(rmdat >> 6) & 3; cpu_reg=(rmdat >> 3) & 7; cpu_rm = rmdat & 7; if (cpu_mod != 3) { fetch_ea_32_long(rmdat); } if (cpu_state.abrt) return 1
|
||||
|
||||
#include "x86_flags.h"
|
||||
|
||||
|
||||
/*Prefetch emulation is a fairly simplistic model:
|
||||
- All instruction bytes must be fetched before it starts.
|
||||
- Cycles used for non-instruction memory accesses are counted and subtracted
|
||||
from the total cycles taken
|
||||
- Any remaining cycles are used to refill the prefetch queue.
|
||||
|
||||
Note that this is only used for 286 / 386 systems. It is disabled when the
|
||||
internal cache on 486+ CPUs is enabled.
|
||||
*/
|
||||
static int prefetch_bytes = 0;
|
||||
static int prefetch_prefixes = 0;
|
||||
|
||||
static void prefetch_run(int instr_cycles, int bytes, int modrm, int reads, int reads_l, int writes, int writes_l, int ea32)
|
||||
{
|
||||
int mem_cycles = reads*cpu_cycles_read + reads_l*cpu_cycles_read_l + writes*cpu_cycles_write + writes_l*cpu_cycles_write_l;
|
||||
|
||||
if (instr_cycles < mem_cycles)
|
||||
instr_cycles = mem_cycles;
|
||||
|
||||
prefetch_bytes -= prefetch_prefixes;
|
||||
prefetch_bytes -= bytes;
|
||||
if (modrm != -1)
|
||||
{
|
||||
if (ea32)
|
||||
{
|
||||
if ((modrm & 7) == 4)
|
||||
{
|
||||
if ((modrm & 0x700) == 0x500)
|
||||
prefetch_bytes -= 5;
|
||||
else if ((modrm & 0xc0) == 0x40)
|
||||
prefetch_bytes -= 2;
|
||||
else if ((modrm & 0xc0) == 0x80)
|
||||
prefetch_bytes -= 5;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((modrm & 0xc7) == 0x05)
|
||||
prefetch_bytes -= 4;
|
||||
else if ((modrm & 0xc0) == 0x40)
|
||||
prefetch_bytes--;
|
||||
else if ((modrm & 0xc0) == 0x80)
|
||||
prefetch_bytes -= 4;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((modrm & 0xc7) == 0x06)
|
||||
prefetch_bytes -= 2;
|
||||
else if ((modrm & 0xc0) != 0xc0)
|
||||
prefetch_bytes -= ((modrm & 0xc0) >> 6);
|
||||
}
|
||||
}
|
||||
|
||||
/* Fill up prefetch queue */
|
||||
while (prefetch_bytes < 0)
|
||||
{
|
||||
prefetch_bytes += cpu_prefetch_width;
|
||||
cycles -= cpu_prefetch_cycles;
|
||||
}
|
||||
|
||||
/* Subtract cycles used for memory access by instruction */
|
||||
instr_cycles -= mem_cycles;
|
||||
|
||||
while (instr_cycles >= cpu_prefetch_cycles)
|
||||
{
|
||||
prefetch_bytes += cpu_prefetch_width;
|
||||
instr_cycles -= cpu_prefetch_cycles;
|
||||
}
|
||||
|
||||
prefetch_prefixes = 0;
|
||||
if (prefetch_bytes > 16)
|
||||
prefetch_bytes = 16;
|
||||
}
|
||||
|
||||
static void prefetch_flush()
|
||||
{
|
||||
prefetch_bytes = 0;
|
||||
}
|
||||
|
||||
#define PREFETCH_RUN(instr_cycles, bytes, modrm, reads, reads_l, writes, writes_l, ea32) \
|
||||
do { if (cpu_prefetch_cycles) prefetch_run(instr_cycles, bytes, modrm, reads, reads_l, writes, writes_l, ea32); } while (0)
|
||||
|
||||
#define PREFETCH_PREFIX() do { if (cpu_prefetch_cycles) prefetch_prefixes++; } while (0)
|
||||
#define PREFETCH_FLUSH() prefetch_flush()
|
||||
|
||||
|
||||
void enter_smm()
|
||||
{
|
||||
uint32_t smram_state = smbase + 0xfe00;
|
||||
uint32_t old_cr0 = cr0;
|
||||
uint32_t old_flags = cpu_state.flags | ((uint32_t)cpu_state.eflags << 16);
|
||||
|
||||
cr0 &= ~0x8000000d;
|
||||
cpu_state.flags = 2;
|
||||
cpu_state.eflags = 0;
|
||||
|
||||
in_smm = 1;
|
||||
mem_set_mem_state(smbase, 131072, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
|
||||
smi_latched = 1;
|
||||
|
||||
mem_writel_phys(smram_state + 0xf8, smbase);
|
||||
mem_writel_phys(smram_state + 0x128, cr4);
|
||||
mem_writel_phys(smram_state + 0x130, cpu_state.seg_es.limit);
|
||||
mem_writel_phys(smram_state + 0x134, cpu_state.seg_es.base);
|
||||
mem_writel_phys(smram_state + 0x138, cpu_state.seg_es.access);
|
||||
mem_writel_phys(smram_state + 0x13c, cpu_state.seg_cs.limit);
|
||||
mem_writel_phys(smram_state + 0x140, cpu_state.seg_cs.base);
|
||||
mem_writel_phys(smram_state + 0x144, cpu_state.seg_cs.access);
|
||||
mem_writel_phys(smram_state + 0x148, cpu_state.seg_ss.limit);
|
||||
mem_writel_phys(smram_state + 0x14c, cpu_state.seg_ss.base);
|
||||
mem_writel_phys(smram_state + 0x150, cpu_state.seg_ss.access);
|
||||
mem_writel_phys(smram_state + 0x154, cpu_state.seg_ds.limit);
|
||||
mem_writel_phys(smram_state + 0x158, cpu_state.seg_ds.base);
|
||||
mem_writel_phys(smram_state + 0x15c, cpu_state.seg_ds.access);
|
||||
mem_writel_phys(smram_state + 0x160, cpu_state.seg_fs.limit);
|
||||
mem_writel_phys(smram_state + 0x164, cpu_state.seg_fs.base);
|
||||
mem_writel_phys(smram_state + 0x168, cpu_state.seg_fs.access);
|
||||
mem_writel_phys(smram_state + 0x16c, cpu_state.seg_gs.limit);
|
||||
mem_writel_phys(smram_state + 0x170, cpu_state.seg_gs.base);
|
||||
mem_writel_phys(smram_state + 0x174, cpu_state.seg_gs.access);
|
||||
mem_writel_phys(smram_state + 0x178, ldt.limit);
|
||||
mem_writel_phys(smram_state + 0x17c, ldt.base);
|
||||
mem_writel_phys(smram_state + 0x180, ldt.access);
|
||||
mem_writel_phys(smram_state + 0x184, gdt.limit);
|
||||
mem_writel_phys(smram_state + 0x188, gdt.base);
|
||||
mem_writel_phys(smram_state + 0x18c, gdt.access);
|
||||
mem_writel_phys(smram_state + 0x190, idt.limit);
|
||||
mem_writel_phys(smram_state + 0x194, idt.base);
|
||||
mem_writel_phys(smram_state + 0x198, idt.access);
|
||||
mem_writel_phys(smram_state + 0x19c, tr.limit);
|
||||
mem_writel_phys(smram_state + 0x1a0, tr.base);
|
||||
mem_writel_phys(smram_state + 0x1a4, tr.access);
|
||||
|
||||
mem_writel_phys(smram_state + 0x1a8, cpu_state.seg_es.seg);
|
||||
mem_writel_phys(smram_state + 0x1ac, cpu_state.seg_cs.seg);
|
||||
mem_writel_phys(smram_state + 0x1b0, cpu_state.seg_ss.seg);
|
||||
mem_writel_phys(smram_state + 0x1b4, cpu_state.seg_ds.seg);
|
||||
mem_writel_phys(smram_state + 0x1b8, cpu_state.seg_fs.seg);
|
||||
mem_writel_phys(smram_state + 0x1bc, cpu_state.seg_gs.seg);
|
||||
mem_writel_phys(smram_state + 0x1c0, ldt.seg);
|
||||
mem_writel_phys(smram_state + 0x1c4, tr.seg);
|
||||
|
||||
mem_writel_phys(smram_state + 0x1c8, dr[7]);
|
||||
mem_writel_phys(smram_state + 0x1cc, dr[6]);
|
||||
mem_writel_phys(smram_state + 0x1d0, EAX);
|
||||
mem_writel_phys(smram_state + 0x1d4, ECX);
|
||||
mem_writel_phys(smram_state + 0x1d8, EDX);
|
||||
mem_writel_phys(smram_state + 0x1dc, EBX);
|
||||
mem_writel_phys(smram_state + 0x1e0, ESP);
|
||||
mem_writel_phys(smram_state + 0x1e4, EBP);
|
||||
mem_writel_phys(smram_state + 0x1e8, ESI);
|
||||
mem_writel_phys(smram_state + 0x1ec, EDI);
|
||||
mem_writel_phys(smram_state + 0x1f0, cpu_state.pc);
|
||||
mem_writel_phys(smram_state + 0x1d0, old_flags);
|
||||
mem_writel_phys(smram_state + 0x1f8, cr3);
|
||||
mem_writel_phys(smram_state + 0x1fc, old_cr0);
|
||||
|
||||
ds = es = fs_seg = gs = ss = 0;
|
||||
|
||||
DS = ES = FS = GS = SS = 0;
|
||||
|
||||
cpu_state.seg_ds.limit = cpu_state.seg_es.limit = cpu_state.seg_fs.limit = cpu_state.seg_gs.limit
|
||||
= cpu_state.seg_ss.limit = 0xffffffff;
|
||||
|
||||
cpu_state.seg_ds.limit_high = cpu_state.seg_es.limit_high = cpu_state.seg_fs.limit_high
|
||||
= cpu_state.seg_gs.limit_high = cpu_state.seg_ss.limit_high = 0xffffffff;
|
||||
|
||||
cpu_state.seg_ds.limit_low = cpu_state.seg_es.limit_low = cpu_state.seg_fs.limit_low
|
||||
= cpu_state.seg_gs.limit_low = cpu_state.seg_ss.limit_low = 0;
|
||||
|
||||
cpu_state.seg_ds.access = cpu_state.seg_es.access = cpu_state.seg_fs.access
|
||||
= cpu_state.seg_gs.access = cpu_state.seg_ss.access = 0x93;
|
||||
|
||||
cpu_state.seg_ds.checked = cpu_state.seg_es.checked = cpu_state.seg_fs.checked
|
||||
= cpu_state.seg_gs.checked = cpu_state.seg_ss.checked = 1;
|
||||
|
||||
CS = 0x3000;
|
||||
cs = smbase;
|
||||
cpu_state.seg_cs.limit = cpu_state.seg_cs.limit_high = 0xffffffff;
|
||||
cpu_state.seg_cs.limit_low = 0;
|
||||
cpu_state.seg_cs.access = 0x93;
|
||||
cpu_state.seg_cs.checked = 1;
|
||||
|
||||
cr4 = 0;
|
||||
dr[7] = 0x400;
|
||||
cpu_state.pc = 0x8000;
|
||||
|
||||
nmi_mask = 0;
|
||||
}
|
||||
|
||||
void leave_smm()
|
||||
{
|
||||
uint32_t smram_state = smbase + 0xfe00;
|
||||
|
||||
smbase = mem_readl_phys(smram_state + 0xf8);
|
||||
cr4 = mem_readl_phys(smram_state + 0x128);
|
||||
|
||||
cpu_state.seg_es.limit = cpu_state.seg_es.limit_high = mem_readl_phys(smram_state + 0x130);
|
||||
cpu_state.seg_es.base = mem_readl_phys(smram_state + 0x134);
|
||||
cpu_state.seg_es.limit_low = cpu_state.seg_es.base;
|
||||
cpu_state.seg_es.access = mem_readl_phys(smram_state + 0x138);
|
||||
|
||||
cpu_state.seg_cs.limit = cpu_state.seg_cs.limit_high = mem_readl_phys(smram_state + 0x13c);
|
||||
cpu_state.seg_cs.base = mem_readl_phys(smram_state + 0x140);
|
||||
cpu_state.seg_cs.limit_low = cpu_state.seg_cs.base;
|
||||
cpu_state.seg_cs.access = mem_readl_phys(smram_state + 0x144);
|
||||
|
||||
cpu_state.seg_ss.limit = cpu_state.seg_ss.limit_high = mem_readl_phys(smram_state + 0x148);
|
||||
cpu_state.seg_ss.base = mem_readl_phys(smram_state + 0x14c);
|
||||
cpu_state.seg_ss.limit_low = cpu_state.seg_ss.base;
|
||||
cpu_state.seg_ss.access = mem_readl_phys(smram_state + 0x150);
|
||||
|
||||
cpu_state.seg_ds.limit = cpu_state.seg_ds.limit_high = mem_readl_phys(smram_state + 0x154);
|
||||
cpu_state.seg_ds.base = mem_readl_phys(smram_state + 0x158);
|
||||
cpu_state.seg_ds.limit_low = cpu_state.seg_ds.base;
|
||||
cpu_state.seg_ds.access = mem_readl_phys(smram_state + 0x15c);
|
||||
|
||||
cpu_state.seg_fs.limit = cpu_state.seg_fs.limit_high = mem_readl_phys(smram_state + 0x160);
|
||||
cpu_state.seg_fs.base = mem_readl_phys(smram_state + 0x164);
|
||||
cpu_state.seg_fs.limit_low = cpu_state.seg_fs.base;
|
||||
cpu_state.seg_fs.access = mem_readl_phys(smram_state + 0x168);
|
||||
|
||||
cpu_state.seg_gs.limit = cpu_state.seg_gs.limit_high = mem_readl_phys(smram_state + 0x16c);
|
||||
cpu_state.seg_gs.base = mem_readl_phys(smram_state + 0x170);
|
||||
cpu_state.seg_gs.limit_low = cpu_state.seg_gs.base;
|
||||
cpu_state.seg_gs.access = mem_readl_phys(smram_state + 0x174);
|
||||
|
||||
ldt.limit = ldt.limit_high = mem_readl_phys(smram_state + 0x178);
|
||||
ldt.base = mem_readl_phys(smram_state + 0x17c);
|
||||
ldt.limit_low = ldt.base;
|
||||
ldt.access = mem_readl_phys(smram_state + 0x180);
|
||||
|
||||
gdt.limit = gdt.limit_high = mem_readl_phys(smram_state + 0x184);
|
||||
gdt.base = mem_readl_phys(smram_state + 0x188);
|
||||
gdt.limit_low = gdt.base;
|
||||
gdt.access = mem_readl_phys(smram_state + 0x18c);
|
||||
|
||||
idt.limit = idt.limit_high = mem_readl_phys(smram_state + 0x190);
|
||||
idt.base = mem_readl_phys(smram_state + 0x194);
|
||||
idt.limit_low = idt.base;
|
||||
idt.access = mem_readl_phys(smram_state + 0x198);
|
||||
|
||||
tr.limit = tr.limit_high = mem_readl_phys(smram_state + 0x19c);
|
||||
tr.base = mem_readl_phys(smram_state + 0x1a0);
|
||||
tr.limit_low = tr.base;
|
||||
tr.access = mem_readl_phys(smram_state + 0x1a4);
|
||||
|
||||
ES = mem_readl_phys(smram_state + 0x1a8);
|
||||
CS = mem_readl_phys(smram_state + 0x1ac);
|
||||
SS = mem_readl_phys(smram_state + 0x1b0);
|
||||
DS = mem_readl_phys(smram_state + 0x1b4);
|
||||
FS = mem_readl_phys(smram_state + 0x1b8);
|
||||
GS = mem_readl_phys(smram_state + 0x1bc);
|
||||
ldt.seg = mem_readl_phys(smram_state + 0x1c0);
|
||||
tr.seg = mem_readl_phys(smram_state + 0x1c4);
|
||||
|
||||
dr[7] = mem_readl_phys(smram_state + 0x1c8);
|
||||
dr[6] = mem_readl_phys(smram_state + 0x1cc);
|
||||
EAX = mem_readl_phys(smram_state + 0x1d0);
|
||||
ECX = mem_readl_phys(smram_state + 0x1d4);
|
||||
EDX = mem_readl_phys(smram_state + 0x1d8);
|
||||
EBX = mem_readl_phys(smram_state + 0x1dc);
|
||||
ESP = mem_readl_phys(smram_state + 0x1e0);
|
||||
EBP = mem_readl_phys(smram_state + 0x1e4);
|
||||
ESI = mem_readl_phys(smram_state + 0x1e8);
|
||||
EDI = mem_readl_phys(smram_state + 0x1ec);
|
||||
|
||||
cpu_state.pc = mem_readl_phys(smram_state + 0x1f0);
|
||||
uint32_t new_flags = mem_readl_phys(smram_state + 0x1f4);
|
||||
cpu_state.flags = new_flags & 0xffff;
|
||||
cpu_state.eflags = new_flags >> 16;
|
||||
cr3 = mem_readl_phys(smram_state + 0x1f8);
|
||||
cr0 = mem_readl_phys(smram_state + 0x1fc);
|
||||
|
||||
cpu_state.seg_cs.access &= ~0x60;
|
||||
cpu_state.seg_cs.access |= cpu_state.seg_ss.access & 0x60; //cpl is dpl of ss
|
||||
|
||||
if((cr0 & 1) && !(cpu_state.eflags&VM_FLAG))
|
||||
{
|
||||
cpu_state.seg_cs.checked = CS ? 1 : 0;
|
||||
cpu_state.seg_ds.checked = DS ? 1 : 0;
|
||||
cpu_state.seg_es.checked = ES ? 1 : 0;
|
||||
cpu_state.seg_fs.checked = FS ? 1 : 0;
|
||||
cpu_state.seg_gs.checked = GS ? 1 : 0;
|
||||
cpu_state.seg_ss.checked = SS ? 1 : 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
cpu_state.seg_cs.checked = cpu_state.seg_ds.checked = cpu_state.seg_es.checked
|
||||
= cpu_state.seg_fs.checked = cpu_state.seg_gs.checked = cpu_state.seg_ss.checked = 1;
|
||||
}
|
||||
|
||||
mem_restore_mem_state(smbase, 131072);
|
||||
in_smm = 0;
|
||||
|
||||
nmi_mask = 1;
|
||||
}
|
||||
|
||||
#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)) && !(cpu_state.flags & T_FLAG))
|
||||
|
||||
#ifdef USE_DYNAREC
|
||||
static int cycles_main = 0;
|
||||
|
||||
|
||||
void exec386_dynarec(int cycs)
|
||||
{
|
||||
int vector;
|
||||
uint32_t addr;
|
||||
int tempi;
|
||||
int cycdiff;
|
||||
int oldcyc;
|
||||
uint32_t start_pc = 0;
|
||||
|
||||
int cyc_period = cycs / 2000; /*5us*/
|
||||
|
||||
cycles_main += cycs;
|
||||
while (cycles_main > 0)
|
||||
{
|
||||
int cycles_start;
|
||||
|
||||
cycles += cyc_period;
|
||||
cycles_start = cycles;
|
||||
|
||||
while (cycles>0)
|
||||
{
|
||||
oldcs = CS;
|
||||
cpu_state.oldpc = cpu_state.pc;
|
||||
oldcpl = CPL;
|
||||
cpu_state.op32 = use32;
|
||||
|
||||
cycdiff=0;
|
||||
oldcyc=cycles;
|
||||
if (!CACHE_ON()) /*Interpret block*/
|
||||
{
|
||||
cpu_block_end = 0;
|
||||
x86_was_reset = 0;
|
||||
while (!cpu_block_end)
|
||||
{
|
||||
oldcs = CS;
|
||||
oldcpl = CPL;
|
||||
cpu_state.oldpc = cpu_state.pc;
|
||||
cpu_state.op32 = use32;
|
||||
|
||||
cpu_state.ea_seg = &cpu_state.seg_ds;
|
||||
cpu_state.ssegs = 0;
|
||||
|
||||
fetchdat = fastreadl(cs + cpu_state.pc);
|
||||
|
||||
if (!cpu_state.abrt)
|
||||
{
|
||||
opcode = fetchdat & 0xFF;
|
||||
fetchdat >>= 8;
|
||||
trap = cpu_state.flags & T_FLAG;
|
||||
|
||||
cpu_state.pc++;
|
||||
x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat);
|
||||
}
|
||||
|
||||
if (!use32) cpu_state.pc &= 0xffff;
|
||||
|
||||
if (((cs + cpu_state.pc) >> 12) != pccache)
|
||||
CPU_BLOCK_END();
|
||||
|
||||
if (in_smm && smi_line && is_pentium)
|
||||
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++;
|
||||
}
|
||||
}
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
/*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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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->valid)
|
||||
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)
|
||||
{
|
||||
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->valid)
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
if (valid_block && block->was_recompiled)
|
||||
{
|
||||
void (*code)() = (void *)&block->data[BLOCK_START];
|
||||
|
||||
codeblock_hash[hash] = block;
|
||||
|
||||
inrecomp=1;
|
||||
code();
|
||||
inrecomp=0;
|
||||
if (!use32) cpu_state.pc &= 0xffff;
|
||||
cpu_recomp_blocks++;
|
||||
}
|
||||
else if (valid_block && !cpu_state.abrt)
|
||||
{
|
||||
start_pc = cpu_state.pc;
|
||||
|
||||
cpu_block_end = 0;
|
||||
x86_was_reset = 0;
|
||||
|
||||
cpu_new_blocks++;
|
||||
|
||||
codegen_block_start_recompile(block);
|
||||
codegen_in_recompile = 1;
|
||||
|
||||
while (!cpu_block_end)
|
||||
{
|
||||
oldcs = CS;
|
||||
oldcpl = CPL;
|
||||
cpu_state.oldpc = cpu_state.pc;
|
||||
cpu_state.op32 = use32;
|
||||
|
||||
cpu_state.ea_seg = &cpu_state.seg_ds;
|
||||
cpu_state.ssegs = 0;
|
||||
|
||||
fetchdat = fastreadl(cs + cpu_state.pc);
|
||||
|
||||
if (!cpu_state.abrt)
|
||||
{
|
||||
opcode = fetchdat & 0xFF;
|
||||
fetchdat >>= 8;
|
||||
|
||||
trap = cpu_state.flags & T_FLAG;
|
||||
|
||||
cpu_state.pc++;
|
||||
|
||||
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);
|
||||
|
||||
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();
|
||||
|
||||
if (in_smm && smi_line && is_pentium)
|
||||
CPU_BLOCK_END();
|
||||
|
||||
if (trap)
|
||||
CPU_BLOCK_END();
|
||||
|
||||
if (nmi && nmi_enable && nmi_mask)
|
||||
CPU_BLOCK_END();
|
||||
|
||||
if (cpu_state.abrt)
|
||||
{
|
||||
codegen_block_remove();
|
||||
CPU_BLOCK_END();
|
||||
}
|
||||
|
||||
ins++;
|
||||
}
|
||||
|
||||
if (!cpu_state.abrt && !x86_was_reset)
|
||||
codegen_block_end_recompile(block);
|
||||
|
||||
if (x86_was_reset)
|
||||
codegen_reset();
|
||||
|
||||
codegen_in_recompile = 0;
|
||||
}
|
||||
else if (!cpu_state.abrt)
|
||||
{
|
||||
/*Mark block but do not recompile*/
|
||||
start_pc = cpu_state.pc;
|
||||
|
||||
cpu_block_end = 0;
|
||||
x86_was_reset = 0;
|
||||
|
||||
codegen_block_init(phys_addr);
|
||||
|
||||
while (!cpu_block_end)
|
||||
{
|
||||
oldcs=CS;
|
||||
oldcpl = CPL;
|
||||
cpu_state.oldpc = cpu_state.pc;
|
||||
cpu_state.op32 = use32;
|
||||
|
||||
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)
|
||||
{
|
||||
opcode = fetchdat & 0xFF;
|
||||
fetchdat >>= 8;
|
||||
|
||||
trap = cpu_state.flags & T_FLAG;
|
||||
|
||||
cpu_state.pc++;
|
||||
|
||||
x86_opcodes[(opcode | cpu_state.op32) & 0x3ff](fetchdat);
|
||||
|
||||
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();
|
||||
|
||||
if (in_smm && smi_line && is_pentium)
|
||||
CPU_BLOCK_END();
|
||||
|
||||
if (trap)
|
||||
CPU_BLOCK_END();
|
||||
|
||||
if (nmi && nmi_enable && nmi_mask)
|
||||
CPU_BLOCK_END();
|
||||
|
||||
if (cpu_state.abrt)
|
||||
{
|
||||
codegen_block_remove();
|
||||
CPU_BLOCK_END();
|
||||
}
|
||||
|
||||
ins++;
|
||||
}
|
||||
|
||||
if (!cpu_state.abrt && !x86_was_reset)
|
||||
codegen_block_end();
|
||||
|
||||
if (x86_was_reset)
|
||||
codegen_reset();
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
cpu_state.abrt = 0;
|
||||
cpu_state.pc = cpu_state.oldpc;
|
||||
CS = oldcs;
|
||||
#ifdef ENABLE_386_DYNAREC_LOG
|
||||
x386_dynarec_log("Double fault %i\n", ins);
|
||||
#endif
|
||||
pmodeint(8, 0);
|
||||
if (cpu_state.abrt)
|
||||
{
|
||||
cpu_state.abrt = 0;
|
||||
softresetx86();
|
||||
cpu_set_edx();
|
||||
#ifdef ENABLE_386_DYNAREC_LOG
|
||||
x386_dynarec_log("Triple fault - reset\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (in_smm && smi_line && is_pentium)
|
||||
{
|
||||
enter_smm();
|
||||
}
|
||||
|
||||
else if (trap)
|
||||
{
|
||||
flags_rebuild();
|
||||
if (msw&1)
|
||||
{
|
||||
pmodeint(1,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 = (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;
|
||||
oldcs = CS;
|
||||
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)
|
||||
{
|
||||
vector = picinterrupt();
|
||||
if (vector != -1)
|
||||
{
|
||||
CPU_BLOCK_END();
|
||||
flags_rebuild();
|
||||
if (msw&1)
|
||||
{
|
||||
pmodeint(vector,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=vector<<2;
|
||||
cpu_state.flags &= ~I_FLAG;
|
||||
cpu_state.flags &= ~T_FLAG;
|
||||
oxpc=cpu_state.pc;
|
||||
cpu_state.pc=readmemw(0,addr);
|
||||
loadcs(readmemw(0,addr+2));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t)tsc))
|
||||
timer_process();
|
||||
|
||||
cycles_main -= (cycles_start - cycles);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
72
src/cpu_common/386_dynarec_ops.c
Normal file
72
src/cpu_common/386_dynarec_ops.c
Normal file
@@ -0,0 +1,72 @@
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#include <math.h>
|
||||
#ifndef INFINITY
|
||||
# define INFINITY (__builtin_inff())
|
||||
#endif
|
||||
|
||||
#include "86box.h"
|
||||
#include "cpu.h"
|
||||
#include "timer.h"
|
||||
#include "x86.h"
|
||||
#include "x86_ops.h"
|
||||
#include "x87.h"
|
||||
#include "x86_flags.h"
|
||||
#include "86box_io.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);
|
||||
}
|
||||
cpu_state.last_ea = cpu_state.eaaddr;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
cpu_state.last_ea = cpu_state.eaaddr;
|
||||
}
|
||||
|
||||
#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
|
||||
|
||||
#define CLOCK_CYCLES(c)
|
||||
#define CLOCK_CYCLES_ALWAYS(c) cycles -= (c)
|
||||
|
||||
#include "386_ops.h"
|
||||
1830
src/cpu_common/386_ops.h
Normal file
1830
src/cpu_common/386_ops.h
Normal file
File diff suppressed because it is too large
Load Diff
2913
src/cpu_common/808x.c
Normal file
2913
src/cpu_common/808x.c
Normal file
File diff suppressed because it is too large
Load Diff
64
src/cpu_common/codegen_public.h
Normal file
64
src/cpu_common/codegen_public.h
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* VARCem Virtual ARchaeological Computer EMulator.
|
||||
* An emulator of (mostly) x86-based PC systems and devices,
|
||||
* using the ISA,EISA,VLB,MCA and PCI system buses, roughly
|
||||
* spanning the era between 1981 and 1995.
|
||||
*
|
||||
* This file is part of the VARCem Project.
|
||||
*
|
||||
* Definitions for the code generator.
|
||||
*
|
||||
* Version: @(#)codegen_public.h 1.0.0 2020/01/27
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2020 Miran Grca.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the:
|
||||
*
|
||||
* Free Software Foundation, Inc.
|
||||
* 59 Temple Place - Suite 330
|
||||
* Boston, MA 02111-1307
|
||||
* USA.
|
||||
*/
|
||||
#ifndef _CODEGEN_PUBLIC_H_
|
||||
#define _CODEGEN_PUBLIC_H_
|
||||
|
||||
#ifndef USE_NEW_DYNAREC
|
||||
#define PAGE_MASK_INDEX_MASK 3
|
||||
#define PAGE_MASK_INDEX_SHIFT 10
|
||||
#define PAGE_MASK_SHIFT 4
|
||||
#else
|
||||
#define PAGE_MASK_SHIFT 6
|
||||
#endif
|
||||
#define PAGE_MASK_MASK 63
|
||||
|
||||
#ifdef USE_NEW_DYNAREC
|
||||
#define BLOCK_PC_INVALID 0xffffffff
|
||||
#define BLOCK_INVALID 0
|
||||
#endif
|
||||
|
||||
|
||||
extern void codegen_init();
|
||||
#ifdef USE_NEW_DYNAREC
|
||||
extern void codegen_close();
|
||||
#endif
|
||||
extern void codegen_flush();
|
||||
|
||||
|
||||
/*Current physical page of block being recompiled. -1 if no recompilation taking place */
|
||||
extern uint32_t recomp_page;
|
||||
extern int codegen_in_recompile;
|
||||
|
||||
#endif
|
||||
3261
src/cpu_common/cpu.c
Normal file
3261
src/cpu_common/cpu.c
Normal file
File diff suppressed because it is too large
Load Diff
566
src/cpu_common/cpu.h
Normal file
566
src/cpu_common/cpu.h
Normal file
@@ -0,0 +1,566 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* CPU type handler.
|
||||
*
|
||||
* Version: @(#)cpu.h 1.0.13 2018/11/14
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* leilei,
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2008-2018 Sarah Walker.
|
||||
* Copyright 2016-2018 leilei.
|
||||
* Copyright 2016,2018 Miran Grca.
|
||||
*/
|
||||
#ifndef EMU_CPU_H
|
||||
# define EMU_CPU_H
|
||||
enum {
|
||||
CPU_8088, /* 808x class CPUs */
|
||||
CPU_8086,
|
||||
#ifdef USE_NEC_808X
|
||||
CPU_V20, /* NEC 808x class CPUs - future proofing */
|
||||
CPU_V30,
|
||||
#endif
|
||||
CPU_286, /* 286 class CPUs */
|
||||
CPU_386SX, /* 386 class CPUs */
|
||||
CPU_386DX,
|
||||
CPU_IBM386SLC,
|
||||
CPU_IBM486SLC,
|
||||
CPU_IBM486BL,
|
||||
CPU_RAPIDCAD,
|
||||
CPU_486SLC,
|
||||
CPU_486DLC,
|
||||
CPU_i486SX, /* 486 class CPUs */
|
||||
CPU_Am486SX,
|
||||
CPU_Cx486S,
|
||||
CPU_i486SX2,
|
||||
CPU_Am486SX2,
|
||||
CPU_i486DX,
|
||||
CPU_i486DX2,
|
||||
CPU_Am486DX,
|
||||
CPU_Am486DX2,
|
||||
CPU_Cx486DX,
|
||||
CPU_Cx486DX2,
|
||||
CPU_iDX4,
|
||||
CPU_Am486DX4,
|
||||
CPU_Cx486DX4,
|
||||
CPU_Am5x86,
|
||||
CPU_Cx5x86,
|
||||
CPU_WINCHIP, /* 586 class CPUs */
|
||||
#ifdef USE_NEW_DYNAREC
|
||||
CPU_WINCHIP2,
|
||||
#endif
|
||||
CPU_PENTIUM,
|
||||
CPU_PENTIUMMMX,
|
||||
#if (defined(USE_NEW_DYNAREC) || (defined(DEV_BRANCH) && defined(USE_CYRIX_6X86)))
|
||||
CPU_Cx6x86,
|
||||
CPU_Cx6x86MX,
|
||||
CPU_Cx6x86L,
|
||||
CPU_CxGX1,
|
||||
#endif
|
||||
#if (defined(USE_NEW_DYNAREC) || (defined(DEV_BRANCH) && defined(USE_AMD_K)))
|
||||
CPU_K5,
|
||||
CPU_5K86,
|
||||
CPU_K6,
|
||||
#endif
|
||||
#ifdef USE_NEW_DYNAREC
|
||||
CPU_K6_2,
|
||||
CPU_K6_2C,
|
||||
CPU_K6_3,
|
||||
CPU_K6_2P,
|
||||
CPU_K6_3P,
|
||||
#endif
|
||||
#if defined(DEV_BRANCH) && defined(USE_I686)
|
||||
CPU_PENTIUMPRO, /* 686 class CPUs */
|
||||
CPU_PENTIUM2,
|
||||
CPU_PENTIUM2D,
|
||||
#endif
|
||||
CPU_MAX /* Only really needed to close the enum in a way independent of the #ifdef's. */
|
||||
};
|
||||
|
||||
|
||||
#define MANU_INTEL 0
|
||||
#define MANU_AMD 1
|
||||
#define MANU_CYRIX 2
|
||||
#define MANU_IDT 3
|
||||
#define MANU_NEC 4
|
||||
|
||||
#define CPU_SUPPORTS_DYNAREC 1
|
||||
#define CPU_REQUIRES_DYNAREC 2
|
||||
#define CPU_ALTERNATE_XTAL 4
|
||||
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
int cpu_type;
|
||||
int rspeed;
|
||||
double multi;
|
||||
uint32_t edx_reset;
|
||||
uint32_t cpuid_model;
|
||||
uint16_t cyrix_id;
|
||||
uint8_t cpu_flags;
|
||||
int8_t mem_read_cycles, mem_write_cycles;
|
||||
int8_t cache_read_cycles, cache_write_cycles;
|
||||
int8_t atclk_div;
|
||||
} CPU;
|
||||
|
||||
|
||||
extern CPU cpus_8088[];
|
||||
extern CPU cpus_8086[];
|
||||
extern CPU cpus_286[];
|
||||
extern CPU cpus_i386SX[];
|
||||
extern CPU cpus_i386DX[];
|
||||
extern CPU cpus_Am386SX[];
|
||||
extern CPU cpus_Am386DX[];
|
||||
extern CPU cpus_486SLC[];
|
||||
extern CPU cpus_486DLC[];
|
||||
extern CPU cpus_IBM386SLC[];
|
||||
extern CPU cpus_IBM486SLC[];
|
||||
extern CPU cpus_IBM486BL[];
|
||||
extern CPU cpus_i486S1[];
|
||||
extern CPU cpus_Am486S1[];
|
||||
extern CPU cpus_Cx486S1[];
|
||||
extern CPU cpus_i486[];
|
||||
extern CPU cpus_Am486[];
|
||||
extern CPU cpus_Cx486[];
|
||||
extern CPU cpus_WinChip[];
|
||||
#ifdef USE_NEW_DYNAREC
|
||||
extern CPU cpus_WinChip_SS7[];
|
||||
#endif
|
||||
extern CPU cpus_Pentium5V[];
|
||||
extern CPU cpus_Pentium5V50[];
|
||||
extern CPU cpus_PentiumS5[];
|
||||
extern CPU cpus_Pentium3V[];
|
||||
extern CPU cpus_Pentium[];
|
||||
#if (defined(USE_NEW_DYNAREC) || (defined(DEV_BRANCH) && defined(USE_AMD_K)))
|
||||
extern CPU cpus_K5[];
|
||||
extern CPU cpus_K56[];
|
||||
#endif
|
||||
#ifdef USE_NEW_DYNAREC
|
||||
extern CPU cpus_K56_SS7[];
|
||||
#endif
|
||||
#if (defined(USE_NEW_DYNAREC) || (defined(DEV_BRANCH) && defined(USE_CYRIX_6X86)))
|
||||
extern CPU cpus_6x863V[];
|
||||
extern CPU cpus_6x86[];
|
||||
#endif
|
||||
#ifdef USE_NEW_DYNAREC
|
||||
extern CPU cpus_6x86SS7[];
|
||||
#endif
|
||||
#if defined(DEV_BRANCH) && defined(USE_I686)
|
||||
extern CPU cpus_PentiumPro[];
|
||||
extern CPU cpus_PentiumII[];
|
||||
#endif
|
||||
|
||||
|
||||
#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 CPL ((cpu_state.seg_cs.access>>5)&3)
|
||||
|
||||
#define IOPL ((cpu_state.flags>>12)&3)
|
||||
|
||||
#define IOPLp ((!(msw&1)) || (CPL<=IOPL))
|
||||
|
||||
|
||||
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 {
|
||||
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];
|
||||
#ifdef USE_NEW_DYNAREC
|
||||
float f[2];
|
||||
#endif
|
||||
} MMX_REG;
|
||||
|
||||
typedef struct {
|
||||
uint32_t tr1, tr12;
|
||||
uint32_t cesr;
|
||||
uint32_t fcr;
|
||||
uint64_t fcr2, fcr3;
|
||||
} msr_t;
|
||||
|
||||
typedef union {
|
||||
uint32_t l;
|
||||
uint16_t w;
|
||||
} cr0_t;
|
||||
|
||||
|
||||
struct _cpustate_ {
|
||||
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;
|
||||
int32_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;
|
||||
uint32_t last_ea;
|
||||
|
||||
#ifdef USE_NEW_DYNAREC
|
||||
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
|
||||
#endif
|
||||
|
||||
x86seg seg_cs,
|
||||
seg_ds,
|
||||
seg_es,
|
||||
seg_ss,
|
||||
seg_fs,
|
||||
seg_gs;
|
||||
|
||||
uint16_t flags, eflags;
|
||||
} cpu_state;
|
||||
|
||||
/*The cpu_state.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 cpu_state.flags below are set in cpu_cur_status, they must be set in block->status.
|
||||
Otherwise they are ignored*/
|
||||
#ifdef USE_NEW_DYNAREC
|
||||
#define CPU_STATUS_NOTFLATDS (1 << 8)
|
||||
#define CPU_STATUS_NOTFLATSS (1 << 9)
|
||||
#define CPU_STATUS_MASK 0xff00
|
||||
#else
|
||||
#define CPU_STATUS_NOTFLATDS (1 << 16)
|
||||
#define CPU_STATUS_NOTFLATSS (1 << 17)
|
||||
#define CPU_STATUS_MASK 0xffff0000
|
||||
#endif
|
||||
|
||||
#ifdef __MSC__
|
||||
# define COMPILE_TIME_ASSERT(expr) /*nada*/
|
||||
#else
|
||||
# ifdef EXTREME_DEBUG
|
||||
# define COMPILE_TIME_ASSERT(expr) typedef char COMP_TIME_ASSERT[(expr) ? 1 : 0];
|
||||
# else
|
||||
# define COMPILE_TIME_ASSERT(expr) /*nada*/
|
||||
# endif
|
||||
#endif
|
||||
|
||||
COMPILE_TIME_ASSERT(sizeof(cpu_state) <= 128)
|
||||
|
||||
#define cpu_state_offset(MEMBER) ((uint8_t)((uintptr_t)&cpu_state.MEMBER - (uintptr_t)&cpu_state - 128))
|
||||
|
||||
#define EAX cpu_state.regs[0].l
|
||||
#define AX cpu_state.regs[0].w
|
||||
#define AL cpu_state.regs[0].b.l
|
||||
#define AH cpu_state.regs[0].b.h
|
||||
#define ECX cpu_state.regs[1].l
|
||||
#define CX cpu_state.regs[1].w
|
||||
#define CL cpu_state.regs[1].b.l
|
||||
#define CH cpu_state.regs[1].b.h
|
||||
#define EDX cpu_state.regs[2].l
|
||||
#define DX cpu_state.regs[2].w
|
||||
#define DL cpu_state.regs[2].b.l
|
||||
#define DH cpu_state.regs[2].b.h
|
||||
#define EBX cpu_state.regs[3].l
|
||||
#define BX cpu_state.regs[3].w
|
||||
#define BL cpu_state.regs[3].b.l
|
||||
#define BH cpu_state.regs[3].b.h
|
||||
#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 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 cycles cpu_state._cycles
|
||||
|
||||
#define cpu_rm cpu_state.rm_data.rm_mod_reg.rm
|
||||
#define cpu_mod cpu_state.rm_data.rm_mod_reg.mod
|
||||
#define cpu_reg cpu_state.rm_data.rm_mod_reg.reg
|
||||
|
||||
#define CR4_TSD (1 << 2)
|
||||
#define CR4_DE (1 << 3)
|
||||
#define CR4_MCE (1 << 6)
|
||||
#define CR4_PCE (1 << 8)
|
||||
#define CR4_OSFXSR (1 << 9)
|
||||
|
||||
|
||||
/* Global variables. */
|
||||
extern int cpu_iscyrix;
|
||||
extern int cpu_16bitbus;
|
||||
extern int cpu_busspeed, cpu_pci_speed;
|
||||
extern int cpu_multi;
|
||||
extern double cpu_dmulti;
|
||||
extern int cpu_cyrix_alignment; /*Cyrix 5x86/6x86 only has data misalignment
|
||||
penalties when crossing 8-byte boundaries*/
|
||||
|
||||
extern int is8086, is286, is386, is486, is486sx, is486dx, is486sx2, is486dx2, isdx4;
|
||||
extern int isibmcpu;
|
||||
extern int is_rapidcad;
|
||||
extern int hasfpu;
|
||||
#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;
|
||||
|
||||
extern int in_smm, smi_line, smi_latched;
|
||||
extern uint32_t smbase;
|
||||
|
||||
#ifdef USE_NEW_DYNAREC
|
||||
extern uint16_t cpu_cur_status;
|
||||
#else
|
||||
extern uint32_t cpu_cur_status;
|
||||
#endif
|
||||
extern uint64_t cpu_CR4_mask;
|
||||
extern uint64_t tsc;
|
||||
extern msr_t msr;
|
||||
extern uint8_t opcode;
|
||||
extern int insc;
|
||||
extern int fpucount;
|
||||
extern float mips,flops;
|
||||
extern int clockrate;
|
||||
extern int cgate16;
|
||||
extern int cpl_override;
|
||||
extern int CPUID;
|
||||
extern uint64_t xt_cpu_multi;
|
||||
extern int isa_cycles;
|
||||
extern uint32_t oldds,oldss,olddslimit,oldsslimit,olddslimitw,oldsslimitw;
|
||||
extern int ins,output;
|
||||
extern uint32_t pccache;
|
||||
extern uint8_t *pccache2;
|
||||
|
||||
extern double bus_timing, pci_timing;
|
||||
extern uint64_t pmc[2];
|
||||
extern uint16_t temp_seg_data[4];
|
||||
extern uint16_t cs_msr;
|
||||
extern uint32_t esp_msr;
|
||||
extern uint32_t eip_msr;
|
||||
|
||||
/* For the AMD K6. */
|
||||
extern uint64_t star;
|
||||
|
||||
#define FPU_CW_Reserved_Bits (0xe0c0)
|
||||
|
||||
extern cr0_t CR0;
|
||||
#define cr0 CR0.l
|
||||
#define msw CR0.w
|
||||
extern uint32_t cr2, cr3, cr4;
|
||||
extern uint32_t dr[8];
|
||||
|
||||
|
||||
/*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*/
|
||||
extern x86seg gdt,ldt,idt,tr;
|
||||
extern x86seg _oldds;
|
||||
#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 fs_seg cpu_state.seg_fs.base
|
||||
#define gs cpu_state.seg_gs.base
|
||||
|
||||
|
||||
#define ISA_CYCLES(x) (x * isa_cycles)
|
||||
|
||||
extern int cpu_cycles_read, cpu_cycles_read_l, cpu_cycles_write, cpu_cycles_write_l;
|
||||
extern int cpu_prefetch_cycles, cpu_prefetch_width, cpu_mem_prefetch_cycles, cpu_rom_prefetch_cycles;
|
||||
extern int cpu_waitstates;
|
||||
extern int cpu_cache_int_enabled, cpu_cache_ext_enabled;
|
||||
extern int cpu_pci_speed;
|
||||
|
||||
extern int timing_rr;
|
||||
extern int timing_mr, timing_mrl;
|
||||
extern int timing_rm, timing_rml;
|
||||
extern int timing_mm, timing_mml;
|
||||
extern int timing_bt, timing_bnt;
|
||||
extern int timing_int, timing_int_rm, timing_int_v86, timing_int_pm;
|
||||
extern int timing_int_pm_outer, timing_iret_rm, timing_iret_v86, timing_iret_pm;
|
||||
extern int timing_iret_pm_outer, timing_call_rm, timing_call_pm;
|
||||
extern int timing_call_pm_gate, timing_call_pm_gate_inner;
|
||||
extern int timing_retf_rm, timing_retf_pm, timing_retf_pm_outer;
|
||||
extern int timing_jmp_rm, timing_jmp_pm, timing_jmp_pm_gate;
|
||||
extern int timing_misaligned;
|
||||
|
||||
|
||||
extern CPU cpus_pcjr[]; // FIXME: should be in machine file!
|
||||
extern CPU cpus_europc[]; // FIXME: should be in machine file!
|
||||
extern CPU cpus_pc1512[]; // FIXME: should be in machine file!
|
||||
extern CPU cpus_ibmat[]; // FIXME: should be in machine file!
|
||||
extern CPU cpus_ibmxt286[]; // FIXME: should be in machine file!
|
||||
extern CPU cpus_ps1_m2011[]; // FIXME: should be in machine file!
|
||||
extern CPU cpus_ps2_m30_286[]; // FIXME: should be in machine file!
|
||||
#if 0
|
||||
extern CPU cpus_acer[]; // FIXME: should be in machine file!
|
||||
#endif
|
||||
|
||||
|
||||
/* Functions. */
|
||||
extern int cpu_has_feature(int feature);
|
||||
|
||||
#ifdef USE_NEW_DYNAREC
|
||||
extern void loadseg_dynarec(uint16_t seg, x86seg *s);
|
||||
extern int loadseg(uint16_t seg, x86seg *s);
|
||||
extern void loadcs(uint16_t seg);
|
||||
#else
|
||||
extern void loadseg(uint16_t seg, x86seg *s);
|
||||
extern void loadcs(uint16_t seg);
|
||||
#endif
|
||||
|
||||
extern char *cpu_current_pc(char *bufp);
|
||||
|
||||
extern void cpu_update_waitstates(void);
|
||||
extern void cpu_set(void);
|
||||
|
||||
extern void cpu_CPUID(void);
|
||||
extern void cpu_RDMSR(void);
|
||||
extern void cpu_WRMSR(void);
|
||||
|
||||
extern int checkio(int port);
|
||||
extern void codegen_block_end(void);
|
||||
extern void codegen_reset(void);
|
||||
extern void cpu_set_edx(void);
|
||||
extern int divl(uint32_t val);
|
||||
extern void execx86(int cycs);
|
||||
extern void enter_smm();
|
||||
extern void leave_smm();
|
||||
extern void exec386(int cycs);
|
||||
extern void exec386_dynarec(int cycs);
|
||||
extern int idivl(int32_t val);
|
||||
#ifdef USE_NEW_DYNAREC
|
||||
extern void loadcscall(uint16_t seg, uint32_t old_pc);
|
||||
extern void loadcsjmp(uint16_t seg, uint32_t old_pc);
|
||||
extern void pmodeint(int num, int soft);
|
||||
extern void pmoderetf(int is32, uint16_t off);
|
||||
extern void pmodeiret(int is32);
|
||||
#else
|
||||
extern void loadcscall(uint16_t seg);
|
||||
extern void loadcsjmp(uint16_t seg, uint32_t old_pc);
|
||||
extern void pmodeint(int num, int soft);
|
||||
extern void pmoderetf(int is32, uint16_t off);
|
||||
extern void pmodeiret(int is32);
|
||||
#endif
|
||||
extern void resetmcr(void);
|
||||
extern void resetx86(void);
|
||||
extern void refreshread(void);
|
||||
extern void resetreadlookup(void);
|
||||
extern void softresetx86(void);
|
||||
extern void x86_int(int num);
|
||||
extern void x86_int_sw(int num);
|
||||
extern int x86_int_sw_rm(int num);
|
||||
extern void x86gpf(char *s, uint16_t error);
|
||||
extern void x86np(char *s, uint16_t error);
|
||||
extern void x86ss(char *s, uint16_t error);
|
||||
extern void x86ts(char *s, uint16_t error);
|
||||
|
||||
#ifdef ENABLE_808X_LOG
|
||||
extern void dumpregs(int __force);
|
||||
extern void x87_dumpregs(void);
|
||||
extern void x87_reset(void);
|
||||
#endif
|
||||
|
||||
extern int cpu_effective, cpu_alt_reset;
|
||||
extern void cpu_dynamic_switch(int new_cpu);
|
||||
|
||||
extern void cpu_ven_reset(void);
|
||||
|
||||
|
||||
#endif /*EMU_CPU_H*/
|
||||
695
src/cpu_common/cpu_table - Cópia.c
Normal file
695
src/cpu_common/cpu_table - Cópia.c
Normal file
@@ -0,0 +1,695 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Define all known processor types.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* Version: @(#)cpu_table.c 1.0.7 2019/10/21
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* leilei,
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
*
|
||||
* Copyright 2008-2019 Sarah Walker.
|
||||
* Copyright 2016-2019 leilei.
|
||||
* Copyright 2016-2019 Miran Grca.
|
||||
* Copyright 2017-2019 Fred N. van Kempen.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#include "86box.h"
|
||||
#include "cpu.h"
|
||||
#include "machine.h"
|
||||
|
||||
|
||||
CPU cpus_8088[] = {
|
||||
/*8088 standard*/
|
||||
{"8088/4.77", CPU_8088, 4772728, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
|
||||
{"8088/7.16", CPU_8088, 7159092, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
|
||||
{"8088/8", CPU_8088, 8000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
|
||||
{"8088/10", CPU_8088, 10000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
|
||||
{"8088/12", CPU_8088, 12000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
|
||||
{"8088/16", CPU_8088, 16000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0}
|
||||
};
|
||||
|
||||
CPU cpus_pcjr[] = {
|
||||
/*8088 PCjr*/
|
||||
{"8088/4.77", CPU_8088, 4772728, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0}
|
||||
};
|
||||
|
||||
CPU cpus_europc[] = {
|
||||
/*8088 EuroPC*/
|
||||
{"8088/4.77", CPU_8088, 4772728, 1, 0, 0, 0, 0, CPU_ALTERNATE_XTAL, 0,0,0,0, 1},
|
||||
{"8088/7.16", CPU_8088, 7159092, 1, 0, 0, 0, 0, CPU_ALTERNATE_XTAL, 0,0,0,0, 1},
|
||||
{"8088/9.54", CPU_8088, 9545456, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0}
|
||||
};
|
||||
|
||||
CPU cpus_8086[] = {
|
||||
/*8086 standard*/
|
||||
{"8086/7.16", CPU_8086, 7159092, 1, 0, 0, 0, 0, CPU_ALTERNATE_XTAL, 0,0,0,0, 1},
|
||||
{"8086/8", CPU_8086, 8000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
|
||||
{"8086/9.54", CPU_8086, 9545456, 1, 0, 0, 0, 0, CPU_ALTERNATE_XTAL, 0,0,0,0, 1},
|
||||
{"8086/10", CPU_8086, 10000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
|
||||
{"8086/12", CPU_8086, 12000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
|
||||
{"8086/16", CPU_8086, 16000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 2},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0}
|
||||
};
|
||||
|
||||
CPU cpus_pc1512[] = {
|
||||
/*8086 Amstrad*/
|
||||
{"8086/8", CPU_8086, 8000000, 1, 0, 0, 0, 0, 0, 0,0,0,0, 1},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0}
|
||||
};
|
||||
|
||||
CPU cpus_286[] = {
|
||||
/*286*/
|
||||
{"286/6", CPU_286, 6000000, 1, 0, 0, 0, 0, 0, 2,2,2,2, 1},
|
||||
{"286/8", CPU_286, 8000000, 1, 0, 0, 0, 0, 0, 2,2,2,2, 1},
|
||||
{"286/10", CPU_286, 10000000, 1, 0, 0, 0, 0, 0, 2,2,2,2, 1},
|
||||
{"286/12", CPU_286, 12500000, 1, 0, 0, 0, 0, 0, 3,3,3,3, 2},
|
||||
{"286/16", CPU_286, 16000000, 1, 0, 0, 0, 0, 0, 3,3,3,3, 2},
|
||||
{"286/20", CPU_286, 20000000, 1, 0, 0, 0, 0, 0, 4,4,4,4, 3},
|
||||
{"286/25", CPU_286, 25000000, 1, 0, 0, 0, 0, 0, 4,4,4,4, 3},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0}
|
||||
};
|
||||
|
||||
CPU cpus_ibmat[] = {
|
||||
/*286*/
|
||||
{"286/6", CPU_286, 6000000, 1, 0, 0, 0, 0, 0, 3,3,3,3, 1},
|
||||
{"286/8", CPU_286, 8000000, 1, 0, 0, 0, 0, 0, 3,3,3,3, 1},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0}
|
||||
};
|
||||
|
||||
CPU cpus_ibmxt286[] = {
|
||||
/*286*/
|
||||
{"286/6", CPU_286, 6000000, 1, 0, 0, 0, 0, 0, 2,2,2,2, 1},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0}
|
||||
};
|
||||
|
||||
CPU cpus_ps1_m2011[] = {
|
||||
/*286*/
|
||||
{"286/10", CPU_286, 10000000, 1, 0, 0, 0, 0, 0, 2,2,2,2, 1},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0, 9}
|
||||
};
|
||||
|
||||
CPU cpus_ps2_m30_286[] = {
|
||||
/*286*/
|
||||
{"286/10", CPU_286, 10000000, 1, 0, 0, 0, 0, 0, 2,2,2,2, 1},
|
||||
{"286/12", CPU_286, 12500000, 1, 0, 0, 0, 0, 0, 3,3,3,3, 2},
|
||||
{"286/16", CPU_286, 16000000, 1, 0, 0, 0, 0, 0, 3,3,3,3, 2},
|
||||
{"286/20", CPU_286, 20000000, 1, 0, 0, 0, 0, 0, 4,4,4,4, 3},
|
||||
{"286/25", CPU_286, 25000000, 1, 0, 0, 0, 0, 0, 4,4,4,4, 3},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0}
|
||||
};
|
||||
|
||||
CPU cpus_i386SX[] = {
|
||||
/*i386SX*/
|
||||
{"i386SX/16", CPU_386SX, 16000000, 1, 0, 0x2308, 0, 0, 0, 3,3,3,3, 2},
|
||||
{"i386SX/20", CPU_386SX, 20000000, 1, 0, 0x2308, 0, 0, 0, 4,4,3,3, 3},
|
||||
{"i386SX/25", CPU_386SX, 25000000, 1, 0, 0x2308, 0, 0, 0, 4,4,3,3, 3},
|
||||
{"i386SX/33", CPU_386SX, 33333333, 1, 0, 0x2308, 0, 0, 0, 6,6,3,3, 4},
|
||||
{"i386SX/40", CPU_386SX, 40000000, 1, 0, 0x2308, 0, 0, 0, 7,7,3,3, 5},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0}
|
||||
};
|
||||
|
||||
CPU cpus_i386DX[] = {
|
||||
/*i386DX/RapidCAD*/
|
||||
{"i386DX/16", CPU_386DX, 16000000, 1, 0, 0x0308, 0, 0, 0, 3,3,3,3, 2},
|
||||
{"i386DX/20", CPU_386DX, 20000000, 1, 0, 0x0308, 0, 0, 0, 4,4,3,3, 3},
|
||||
{"i386DX/25", CPU_386DX, 25000000, 1, 0, 0x0308, 0, 0, 0, 4,4,3,3, 3},
|
||||
{"i386DX/33", CPU_386DX, 33333333, 1, 0, 0x0308, 0, 0, 0, 6,6,3,3, 4},
|
||||
{"i386DX/40", CPU_386DX, 40000000, 1, 0, 0x0308, 0, 0, 0, 7,7,3,3, 5},
|
||||
{"RapidCAD/25", CPU_RAPIDCAD, 25000000, 1, 0, 0x0430, 0, 0, CPU_SUPPORTS_DYNAREC, 4,4,3,3, 3},
|
||||
{"RapidCAD/33", CPU_RAPIDCAD, 33333333, 1, 0, 0x0430, 0, 0, CPU_SUPPORTS_DYNAREC, 6,6,3,3, 4},
|
||||
{"RapidCAD/40", CPU_RAPIDCAD, 40000000, 1, 0, 0x0430, 0, 0, CPU_SUPPORTS_DYNAREC, 7,7,3,3, 5},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0}
|
||||
};
|
||||
|
||||
CPU cpus_Am386SX[] = {
|
||||
/*Am386SX*/
|
||||
{"Am386SX/16", CPU_386SX, 16000000, 1, 0, 0x2308, 0, 0, 0, 3,3,3,3, 2},
|
||||
{"Am386SX/20", CPU_386SX, 20000000, 1, 0, 0x2308, 0, 0, 0, 4,4,3,3, 3},
|
||||
{"Am386SX/25", CPU_386SX, 25000000, 1, 0, 0x2308, 0, 0, 0, 4,4,3,3, 3},
|
||||
{"Am386SX/33", CPU_386SX, 33333333, 1, 0, 0x2308, 0, 0, 0, 6,6,3,3, 4},
|
||||
{"Am386SX/40", CPU_386SX, 40000000, 1, 0, 0x2308, 0, 0, 0, 7,7,3,3, 5},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0}
|
||||
};
|
||||
|
||||
CPU cpus_Am386DX[] = {
|
||||
/*Am386DX*/
|
||||
{"Am386DX/25", CPU_386DX, 25000000, 1, 0, 0x0308, 0, 0, 0, 4,4,3,3, 3},
|
||||
{"Am386DX/33", CPU_386DX, 33333333, 1, 0, 0x0308, 0, 0, 0, 6,6,3,3, 4},
|
||||
{"Am386DX/40", CPU_386DX, 40000000, 1, 0, 0x0308, 0, 0, 0, 7,7,3,3, 5},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0}
|
||||
};
|
||||
|
||||
CPU cpus_486SLC[] = {
|
||||
/*Cx486SLC*/
|
||||
{"Cx486SLC/20", CPU_486SLC, 20000000, 1, 0, 0x400, 0, 0x0000, 0, 4,4,3,3, 3},
|
||||
{"Cx486SLC/25", CPU_486SLC, 25000000, 1, 0, 0x400, 0, 0x0000, 0, 4,4,3,3, 3},
|
||||
{"Cx486SLC/33", CPU_486SLC, 33333333, 1, 0, 0x400, 0, 0x0000, 0, 6,6,3,3, 4},
|
||||
{"Cx486SRx2/32", CPU_486SLC, 32000000, 2, 0, 0x406, 0, 0x0006, 0, 6,6,6,6, 4},
|
||||
{"Cx486SRx2/40", CPU_486SLC, 40000000, 2, 0, 0x406, 0, 0x0006, 0, 8,8,6,6, 6},
|
||||
{"Cx486SRx2/50", CPU_486SLC, 50000000, 2, 0, 0x406, 0, 0x0006, 0, 8,8,6,6, 6},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0}
|
||||
};
|
||||
|
||||
CPU cpus_IBM386SLC[] = {
|
||||
/*IBM 386SLC*/
|
||||
{"386SLC/16", CPU_IBM386SLC, 16000000, 1, 0, 0x300, 0, 0, 0, 3,3,3,3, 2},
|
||||
{"386SLC/20", CPU_IBM386SLC, 20000000, 1, 0, 0x300, 0, 0, 0, 4,4,3,3, 3},
|
||||
{"386SLC/25", CPU_IBM386SLC, 25000000, 1, 0, 0x300, 0, 0, 0, 4,4,3,3, 3},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0}
|
||||
};
|
||||
|
||||
CPU cpus_IBM486SLC[] = {
|
||||
/*IBM 486SLC*/
|
||||
{"486SLC/33", CPU_IBM486SLC, 33333333, 1, 0, 0x400, 0, 0, 0, 6,6,3,3, 4},
|
||||
{"486SLC2/40", CPU_IBM486SLC, 40000000, 2, 0, 0x400, 0, 0, 0, 7,7,6,6, 5},
|
||||
{"486SLC2/50", CPU_IBM486SLC, 50000000, 2, 0, 0x400, 0, 0, 0, 8,8,6,6, 6},
|
||||
{"486SLC2/66", CPU_IBM486SLC, 66666666, 2, 0, 0x400, 0, 0, 0, 12,12,6,6, 8},
|
||||
{"486SLC3/60", CPU_IBM486SLC, 60000000, 3, 0, 0x400, 0, 0, 0, 12,12,9,9, 7},
|
||||
{"486SLC3/75", CPU_IBM486SLC, 75000000, 3, 0, 0x400, 0, 0, 0, 12,12,9,9, 9},
|
||||
{"486SLC3/100", CPU_IBM486SLC, 100000000, 3, 0, 0x400, 0, 0, 0, 18,18,9,9, 12},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0}
|
||||
};
|
||||
|
||||
CPU cpus_IBM486BL[] = {
|
||||
/*IBM Blue Lightning*/
|
||||
{"486BL2/50", CPU_IBM486BL, 50000000, 2, 0, 0x400, 0, 0, 0, 8,8,6,6, 6},
|
||||
{"486BL2/66", CPU_IBM486BL, 66666666, 2, 0, 0x400, 0, 0, 0, 12,12,6,6, 8},
|
||||
{"486BL3/75", CPU_IBM486BL, 75000000, 3, 0, 0x400, 0, 0, 0, 12,12,9,9, 9},
|
||||
{"486BL3/100", CPU_IBM486BL, 100000000, 3, 0, 0x400, 0, 0, 0, 18,18,9,9, 12},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0}
|
||||
};
|
||||
|
||||
CPU cpus_486DLC[] = {
|
||||
/*Cx486DLC*/
|
||||
{"Cx486DLC/25", CPU_486DLC, 25000000, 1, 0, 0x401, 0, 0x0001, 0, 4, 4,3,3, 3},
|
||||
{"Cx486DLC/33", CPU_486DLC, 33333333, 1, 0, 0x401, 0, 0x0001, 0, 6, 6,3,3, 4},
|
||||
{"Cx486DLC/40", CPU_486DLC, 40000000, 1, 0, 0x401, 0, 0x0001, 0, 7, 7,3,3, 5},
|
||||
{"Cx486DRx2/32", CPU_486DLC, 32000000, 2, 0, 0x407, 0, 0x0007, 0, 6, 6,6,6, 4},
|
||||
{"Cx486DRx2/40", CPU_486DLC, 40000000, 2, 0, 0x407, 0, 0x0007, 0, 8, 8,6,6, 6},
|
||||
{"Cx486DRx2/50", CPU_486DLC, 50000000, 2, 0, 0x407, 0, 0x0007, 0, 8, 8,6,6, 6},
|
||||
{"Cx486DRx2/66", CPU_486DLC, 66666666, 2, 0, 0x407, 0, 0x0007, 0, 12,12,6,6, 8},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0, 0}
|
||||
};
|
||||
|
||||
CPU cpus_i486S1[] = {
|
||||
/*i486*/
|
||||
{"i486SX/16", CPU_i486SX, 16000000, 1, 16000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 3, 3,3,3, 2},
|
||||
{"i486SX/20", CPU_i486SX, 20000000, 1, 20000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 4, 4,3,3, 3},
|
||||
{"i486SX/25", CPU_i486SX, 25000000, 1, 25000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 4, 4,3,3, 3},
|
||||
{"i486SX/33", CPU_i486SX, 33333333, 1, 33333333, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 6, 6,3,3, 4},
|
||||
{"i486SX2/50", CPU_i486SX, 50000000, 2, 25000000, 0x45b, 0, 0, CPU_SUPPORTS_DYNAREC, 8, 8,6,6, 6},
|
||||
{"i486SX2/66 (Q0569)", CPU_i486SX, 66666666, 2, 33333333, 0x45b, 0, 0, CPU_SUPPORTS_DYNAREC, 8, 8,6,6, 8},
|
||||
{"i486DX/25", CPU_i486DX, 25000000, 1, 25000000, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC, 4, 4,3,3, 3},
|
||||
{"i486DX/33", CPU_i486DX, 33333333, 1, 33333333, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC, 6, 6,3,3, 4},
|
||||
{"i486DX/50", CPU_i486DX, 50000000, 1, 25000000, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC, 8, 8,4,4, 6},
|
||||
{"i486DX2/40", CPU_i486DX, 40000000, 2, 20000000, 0x430, 0x430, 0, CPU_SUPPORTS_DYNAREC, 7, 7,6,6, 5},
|
||||
{"i486DX2/50", CPU_i486DX, 50000000, 2, 25000000, 0x430, 0x430, 0, CPU_SUPPORTS_DYNAREC, 8, 8,6,6, 6},
|
||||
{"i486DX2/66", CPU_i486DX, 66666666, 2, 33333333, 0x430, 0x430, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 8},
|
||||
{"iDX4 OverDrive 75", CPU_iDX4, 75000000, 3, 25000000, 0x1480, 0x1480, 0, CPU_SUPPORTS_DYNAREC, 12,12,9,9, 9}, /*Only added the DX4 OverDrive as the others would be redundant*/
|
||||
{"iDX4 OverDrive 100", CPU_iDX4, 100000000, 3, 33333333, 0x1480, 0x1480, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 12},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0, 0}
|
||||
};
|
||||
CPU cpus_Am486S1[] = {
|
||||
/*Am486*/
|
||||
{"Am486SX/33", CPU_Am486SX, 33333333, 1, 33333333, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 6, 6, 3, 3, 4},
|
||||
{"Am486SX/40", CPU_Am486SX, 40000000, 1, 40000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5},
|
||||
{"Am486SX2/50", CPU_Am486SX, 50000000, 2, 25000000, 0x45b, 0x45b, 0, CPU_SUPPORTS_DYNAREC, 8, 8, 6, 6, 6}, /*CPUID available on SX2, DX2, DX4, 5x86, >= 50 MHz*/
|
||||
{"Am486SX2/66", CPU_Am486SX, 66666666, 2, 33333333, 0x45b, 0x45b, 0, CPU_SUPPORTS_DYNAREC, 12,12, 6, 6, 8}, /*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, 33333333, 1, 33333333, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 6, 6, 3, 3, 4},
|
||||
{"Am486DX/40", CPU_Am486DX, 40000000, 1, 40000000, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5},
|
||||
{"Am486DX2/50", CPU_Am486DX, 50000000, 2, 25000000, 0x470, 0x470, 0, CPU_SUPPORTS_DYNAREC, 8, 8, 6, 6, 6},
|
||||
{"Am486DX2/66", CPU_Am486DX, 66666666, 2, 33333333, 0x470, 0x470, 0, CPU_SUPPORTS_DYNAREC, 12,12, 6, 6, 8},
|
||||
{"Am486DX2/80", CPU_Am486DX, 80000000, 2, 40000000, 0x470, 0x470, 0, CPU_SUPPORTS_DYNAREC, 14,14, 6, 6, 10},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
CPU cpus_Cx486S1[] = {
|
||||
/*Cyrix 486*/
|
||||
{"Cx486S/25", CPU_Cx486S, 25000000, 1, 25000000, 0x420, 0, 0x0010, CPU_SUPPORTS_DYNAREC, 4, 4, 3, 3, 3},
|
||||
{"Cx486S/33", CPU_Cx486S, 33333333, 1, 33333333, 0x420, 0, 0x0010, CPU_SUPPORTS_DYNAREC, 6, 6, 3, 3, 4},
|
||||
{"Cx486S/40", CPU_Cx486S, 40000000, 1, 40000000, 0x420, 0, 0x0010, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5},
|
||||
{"Cx486DX/33", CPU_Cx486DX, 33333333, 1, 33333333, 0x430, 0, 0x051a, CPU_SUPPORTS_DYNAREC, 6, 6, 3, 3, 4},
|
||||
{"Cx486DX/40", CPU_Cx486DX, 40000000, 1, 40000000, 0x430, 0, 0x051a, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5},
|
||||
{"Cx486DX2/50", CPU_Cx486DX, 50000000, 2, 25000000, 0x430, 0, 0x081b, CPU_SUPPORTS_DYNAREC, 8, 8, 6, 6, 6},
|
||||
{"Cx486DX2/66", CPU_Cx486DX, 66666666, 2, 33333333, 0x430, 0, 0x0b1b, CPU_SUPPORTS_DYNAREC, 12,12, 6, 6, 8},
|
||||
{"Cx486DX2/80", CPU_Cx486DX, 80000000, 2, 40000000, 0x430, 0, 0x311b, CPU_SUPPORTS_DYNAREC, 14,14, 6, 6, 10},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
CPU cpus_i486[] = {
|
||||
/*i486/P24T*/
|
||||
{"i486SX/16", CPU_i486SX, 16000000, 1, 16000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 3, 3,3,3, 2},
|
||||
{"i486SX/20", CPU_i486SX, 20000000, 1, 20000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 4, 4,3,3, 3},
|
||||
{"i486SX/25", CPU_i486SX, 25000000, 1, 25000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 4, 4,3,3, 3},
|
||||
{"i486SX/33", CPU_i486SX, 33333333, 1, 33333333, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 6, 6,3,3, 4},
|
||||
{"i486SX2/50", CPU_i486SX, 50000000, 2, 25000000, 0x45b, 0, 0, CPU_SUPPORTS_DYNAREC, 8, 8,6,6, 6},
|
||||
{"i486SX2/66 (Q0569)", CPU_i486SX, 66666666, 2, 33333333, 0x45b, 0, 0, CPU_SUPPORTS_DYNAREC, 8, 8,6,6, 8},
|
||||
{"i486DX/25", CPU_i486DX, 25000000, 1, 25000000, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC, 4, 4,3,3, 3},
|
||||
{"i486DX/33", CPU_i486DX, 33333333, 1, 33333333, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC, 6, 6,3,3, 4},
|
||||
{"i486DX/50", CPU_i486DX, 50000000, 1, 25000000, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC, 8, 8,4,4, 6},
|
||||
{"i486DX2/40", CPU_i486DX, 40000000, 2, 20000000, 0x430, 0x430, 0, CPU_SUPPORTS_DYNAREC, 7, 7,6,6, 5}, /*CPUID available on DX2, DX4, P24T, >= 40 MHz*/
|
||||
{"i486DX2/50", CPU_i486DX, 50000000, 2, 25000000, 0x430, 0x430, 0, CPU_SUPPORTS_DYNAREC, 8, 8,6,6, 6},
|
||||
{"i486DX2/66", CPU_i486DX, 66666666, 2, 33333333, 0x430, 0x430, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 8},
|
||||
{"iDX4/75", CPU_iDX4, 75000000, 3, 25000000, 0x481, 0x481, 0, CPU_SUPPORTS_DYNAREC, 12,12,9,9, 9}, /*CPUID available on DX4, >= 75 MHz*/
|
||||
{"iDX4/100", CPU_iDX4, 100000000, 3, 33333333, 0x481, 0x481, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 12}, /*Is on some real Intel DX2s, limit here is pretty arbitary*/
|
||||
{"iDX4 OverDrive 75", CPU_iDX4, 75000000, 3, 25000000, 0x1480, 0x1480, 0, CPU_SUPPORTS_DYNAREC, 12,12,9,9, 9},
|
||||
{"iDX4 OverDrive 100", CPU_iDX4, 100000000, 3, 33333333, 0x1480, 0x1480, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 12},
|
||||
{"Pentium OverDrive 63", CPU_PENTIUM, 62500000, 5/2, 25000000, 0x1531, 0x1531, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,7,7, 15/2},
|
||||
{"Pentium OverDrive 83", CPU_PENTIUM, 83333333, 5/2, 33333333, 0x1532, 0x1532, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,8,8, 10},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0, 0}
|
||||
};
|
||||
|
||||
CPU cpus_Am486[] = {
|
||||
/*Am486/5x86*/
|
||||
{"Am486SX/33", CPU_Am486SX, 33333333, 1, 33333333, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 6, 6, 3, 3, 4},
|
||||
{"Am486SX/40", CPU_Am486SX, 40000000, 1, 40000000, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5},
|
||||
{"Am486SX2/50", CPU_Am486SX, 50000000, 2, 25000000, 0x45b, 0x45b, 0, CPU_SUPPORTS_DYNAREC, 8, 8, 6, 6, 6}, /*CPUID available on SX2, DX2, DX4, 5x86, >= 50 MHz*/
|
||||
{"Am486SX2/66", CPU_Am486SX, 66666666, 2, 33333333, 0x45b, 0x45b, 0, CPU_SUPPORTS_DYNAREC, 12,12, 6, 6, 8},
|
||||
{"Am486DX/33", CPU_Am486DX, 33333333, 1, 33333333, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 6, 6, 3, 3, 4},
|
||||
{"Am486DX/40", CPU_Am486DX, 40000000, 1, 40000000, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5},
|
||||
{"Am486DX2/50", CPU_Am486DX, 50000000, 2, 25000000, 0x470, 0x470, 0, CPU_SUPPORTS_DYNAREC, 8, 8, 6, 6, 6},
|
||||
{"Am486DX2/66", CPU_Am486DX, 66666666, 2, 33333333, 0x470, 0x470, 0, CPU_SUPPORTS_DYNAREC, 12,12, 6, 6, 8},
|
||||
{"Am486DX2/80", CPU_Am486DX, 80000000, 2, 40000000, 0x470, 0x470, 0, CPU_SUPPORTS_DYNAREC, 14,14, 6, 6, 10},
|
||||
{"Am486DX4/75", CPU_Am486DX, 75000000, 3, 25000000, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 12,12, 9, 9, 9},
|
||||
{"Am486DX4/90", CPU_Am486DX, 90000000, 3, 30000000, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 15,15, 9, 9, 12},
|
||||
{"Am486DX4/100", CPU_Am486DX, 100000000, 3, 33333333, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 15,15, 9, 9, 12},
|
||||
{"Am486DX4/120", CPU_Am486DX, 120000000, 3, 40000000, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 21,21, 9, 9, 15},
|
||||
{"Am5x86/P75", CPU_Am486DX, 133333333, 4, 33333333, 0x4e0, 0x4e0, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 16},
|
||||
{"Am5x86/P75+", CPU_Am486DX, 150000000, 3, 25000000, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 28,28,12,12, 20},/*The rare P75+ was indeed a triple-clocked 150 MHz according to research*/
|
||||
{"Am5x86/P90", CPU_Am486DX, 160000000, 4, 40000000, 0x4e0, 0x4e0, 0, CPU_SUPPORTS_DYNAREC, 28,28,12,12, 20},/*160 MHz on a 40 MHz bus was a common overclock and "5x86/P90" was used by a number of BIOSes to refer to that configuration*/
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
CPU cpus_Cx486[] = {
|
||||
/*Cyrix 486*/
|
||||
{"Cx486S/25", CPU_Cx486S, 25000000, 1, 25000000, 0x420, 0, 0x0010, CPU_SUPPORTS_DYNAREC, 4, 4, 3, 3, 3},
|
||||
{"Cx486S/33", CPU_Cx486S, 33333333, 1, 33333333, 0x420, 0, 0x0010, CPU_SUPPORTS_DYNAREC, 6, 6, 3, 3, 4},
|
||||
{"Cx486S/40", CPU_Cx486S, 40000000, 1, 40000000, 0x420, 0, 0x0010, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5},
|
||||
{"Cx486DX/33", CPU_Cx486DX, 33333333, 1, 33333333, 0x430, 0, 0x051a, CPU_SUPPORTS_DYNAREC, 6, 6, 3, 3, 4},
|
||||
{"Cx486DX/40", CPU_Cx486DX, 40000000, 1, 40000000, 0x430, 0, 0x051a, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5},
|
||||
{"Cx486DX2/50", CPU_Cx486DX, 50000000, 2, 25000000, 0x430, 0, 0x081b, CPU_SUPPORTS_DYNAREC, 8, 8, 6, 6, 6},
|
||||
{"Cx486DX2/66", CPU_Cx486DX, 66666666, 2, 33333333, 0x430, 0, 0x0b1b, CPU_SUPPORTS_DYNAREC, 12,12, 6, 6, 8},
|
||||
{"Cx486DX2/80", CPU_Cx486DX, 80000000, 2, 40000000, 0x430, 0, 0x311b, CPU_SUPPORTS_DYNAREC, 14,14, 6, 6, 10},
|
||||
{"Cx486DX4/75", CPU_Cx486DX, 75000000, 3, 25000000, 0x480, 0, 0x361f, CPU_SUPPORTS_DYNAREC, 12,12, 9, 9, 9},
|
||||
{"Cx486DX4/100", CPU_Cx486DX, 100000000, 3, 33333333, 0x480, 0, 0x361f, CPU_SUPPORTS_DYNAREC, 15,15, 9, 9, 12},
|
||||
|
||||
/*Cyrix 5x86*/
|
||||
{"Cx5x86/80", CPU_Cx5x86, 80000000, 2, 40000000, 0x480, 0, 0x002f, CPU_SUPPORTS_DYNAREC, 14,14, 6, 6, 10}, /*If we're including the Pentium 50, might as well include this*/
|
||||
{"Cx5x86/100", CPU_Cx5x86, 100000000, 3, 33333333, 0x480, 0, 0x002f, CPU_SUPPORTS_DYNAREC, 15,15, 9, 9, 12},
|
||||
{"Cx5x86/120", CPU_Cx5x86, 120000000, 3, 40000000, 0x480, 0, 0x002f, CPU_SUPPORTS_DYNAREC, 21,21, 9, 9, 15},
|
||||
{"Cx5x86/133", CPU_Cx5x86, 133333333, 4, 33333333, 0x480, 0, 0x002f, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 16},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
#if defined(USE_NEW_DYNAREC) || (defined(DEV_BRANCH) && defined(USE_CYRIX_6X86))
|
||||
CPU cpus_6x863V[] = {
|
||||
/*Cyrix 6x86*/
|
||||
{"Cx6x86/P90", CPU_Cx6x86, 80000000, 2, 40000000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 8, 8, 6, 6, 10},
|
||||
{"Cx6x86/PR120+", CPU_Cx6x86, 100000000, 2, 25000000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 12},
|
||||
{"Cx6x86/PR133+", CPU_Cx6x86, 110000000, 2, 27500000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 14},
|
||||
{"Cx6x86/PR150+", CPU_Cx6x86, 120000000, 2, 30000000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14},
|
||||
{"Cx6x86/PR166+", CPU_Cx6x86, 133333333, 2, 33333333, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16},
|
||||
{"Cx6x86/PR200+", CPU_Cx6x86, 150000000, 2, 37500000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 18},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
CPU cpus_6x86[] = {
|
||||
/*Cyrix 6x86*/
|
||||
{"Cx6x86/P90", CPU_Cx6x86, 80000000, 2, 40000000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 8, 8, 6, 6, 10},
|
||||
{"Cx6x86/PR120+", CPU_Cx6x86, 100000000, 2, 25000000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 12},
|
||||
{"Cx6x86/PR133+", CPU_Cx6x86, 110000000, 2, 27500000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 14},
|
||||
{"Cx6x86/PR150+", CPU_Cx6x86, 120000000, 2, 30000000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14},
|
||||
{"Cx6x86/PR166+", CPU_Cx6x86, 133333333, 2, 33333333, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16},
|
||||
{"Cx6x86/PR200+", CPU_Cx6x86, 150000000, 2, 37500000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 18},
|
||||
|
||||
/*Cyrix 6x86L*/
|
||||
{"Cx6x86L/PR133+", CPU_Cx6x86L, 110000000, 2, 27500000, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 14},
|
||||
{"Cx6x86L/PR150+", CPU_Cx6x86L, 120000000, 2, 30000000, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14},
|
||||
{"Cx6x86L/PR166+", CPU_Cx6x86L, 133333333, 2, 33333333, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16},
|
||||
{"Cx6x86L/PR200+", CPU_Cx6x86L, 150000000, 2, 37500000, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 18},
|
||||
|
||||
/*Cyrix 6x86MX/MII*/
|
||||
{"Cx6x86MX/PR166", CPU_Cx6x86MX, 133333333, 2, 33333333, 0x600, 0x600, 0x0451, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16},
|
||||
{"Cx6x86MX/PR200", CPU_Cx6x86MX, 166666666, 5/2, 33333333, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20},
|
||||
{"Cx6x86MX/PR233", CPU_Cx6x86MX, 187500000, 5/2, 37500000, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 45/2},
|
||||
{"Cx6x86MX/PR266", CPU_Cx6x86MX, 208333333, 5/2, 41666666, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 17,17, 7, 7, 25},
|
||||
{"MII/PR300", CPU_Cx6x86MX, 233333333, 7/2, 33333333, 0x601, 0x601, 0x0852, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,11,11, 28},
|
||||
{"MII/PR333", CPU_Cx6x86MX, 250000000, 3, 41666666, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 23,23, 9, 9, 30},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef USE_NEW_DYNAREC
|
||||
CPU cpus_6x86SS7[] = {
|
||||
/*Cyrix 6x86*/
|
||||
{"Cx6x86/P90", CPU_Cx6x86, 80000000, 2, 40000000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 8, 8, 6, 6, 10},
|
||||
{"Cx6x86/PR120+", CPU_Cx6x86, 100000000, 2, 25000000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 12},
|
||||
{"Cx6x86/PR133+", CPU_Cx6x86, 110000000, 2, 27500000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 14},
|
||||
{"Cx6x86/PR150+", CPU_Cx6x86, 120000000, 2, 30000000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14},
|
||||
{"Cx6x86/PR166+", CPU_Cx6x86, 133333333, 2, 33333333, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16},
|
||||
{"Cx6x86/PR200+", CPU_Cx6x86, 150000000, 2, 37500000, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 18},
|
||||
|
||||
/*Cyrix 6x86L*/
|
||||
{"Cx6x86L/PR133+", CPU_Cx6x86L, 110000000, 2, 27500000, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 14},
|
||||
{"Cx6x86L/PR150+", CPU_Cx6x86L, 120000000, 2, 30000000, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14},
|
||||
{"Cx6x86L/PR166+", CPU_Cx6x86L, 133333333, 2, 33333333, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16},
|
||||
{"Cx6x86L/PR200+", CPU_Cx6x86L, 150000000, 2, 37500000, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 18},
|
||||
|
||||
/*Cyrix 6x86MX/MII*/
|
||||
{"Cx6x86MX/PR166", CPU_Cx6x86MX, 133333333, 2, 33333333, 0x600, 0x600, 0x0451, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16},
|
||||
{"Cx6x86MX/PR200", CPU_Cx6x86MX, 166666666, 5/2, 33333333, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20},
|
||||
{"Cx6x86MX/PR233", CPU_Cx6x86MX, 187500000, 5/2, 37500000, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 45/2},
|
||||
{"Cx6x86MX/PR266", CPU_Cx6x86MX, 208333333, 5/2, 41666666, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 17,17, 7, 7, 25},
|
||||
{"MII/PR300", CPU_Cx6x86MX, 233333333, 7/2, 33333333, 0x601, 0x601, 0x0852, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,11,11, 28},
|
||||
{"MII/PR333", CPU_Cx6x86MX, 250000000, 3, 41666666, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 23,23, 9, 9, 30},
|
||||
{"MII/PR366", CPU_Cx6x86MX, 250000000, 5/2, 33333333, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 23,23, 7, 7, 30},
|
||||
{"MII/PR400", CPU_Cx6x86MX, 285000000, 3, 31666666, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27, 9, 9, 34},
|
||||
{"MII/PR433", CPU_Cx6x86MX, 300000000, 3, 33333333, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27, 9, 9, 36},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
#endif
|
||||
|
||||
CPU cpus_WinChip[] = {
|
||||
/*IDT WinChip*/
|
||||
{"WinChip 75", CPU_WINCHIP, 75000000, 3/2, 25000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 8, 8, 4, 4, 9},
|
||||
{"WinChip 90", CPU_WINCHIP, 90000000, 3/2, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 9, 9, 4, 4, 21/2},
|
||||
{"WinChip 100", CPU_WINCHIP, 100000000, 3/2, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 9, 9, 4, 4, 12},
|
||||
{"WinChip 120", CPU_WINCHIP, 120000000, 2, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 12, 12, 6, 6, 14},
|
||||
{"WinChip 133", CPU_WINCHIP, 133333333, 2, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 12, 12, 6, 6, 16},
|
||||
{"WinChip 150", CPU_WINCHIP, 150000000, 5/2, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 15, 15, 7, 7, 35/2},
|
||||
{"WinChip 166", CPU_WINCHIP, 166666666, 5/2, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 15, 15, 7, 7, 40},
|
||||
{"WinChip 180", CPU_WINCHIP, 180000000, 3, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 21},
|
||||
{"WinChip 200", CPU_WINCHIP, 200000000, 3, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 24},
|
||||
{"WinChip 225", CPU_WINCHIP, 225000000, 3, 37500000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 27},
|
||||
{"WinChip 240", CPU_WINCHIP, 240000000, 4, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 24, 24, 12, 12, 28},
|
||||
#ifdef USE_NEW_DYNAREC
|
||||
{"WinChip 2/200", CPU_WINCHIP2, 200000000, 3, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 24},
|
||||
{"WinChip 2/225", CPU_WINCHIP2, 225000000, 3, 37500000, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 27},
|
||||
{"WinChip 2/240", CPU_WINCHIP2, 240000000, 4, 30000000, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 24, 24, 12, 12, 30},
|
||||
{"WinChip 2/250", CPU_WINCHIP2, 250000000, 3, 41666667, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 24, 24, 12, 12, 30},
|
||||
{"WinChip 2A/200", CPU_WINCHIP2, 200000000, 3, 33333333, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 24},
|
||||
{"WinChip 2A/233", CPU_WINCHIP2, 233333333, 7/2, 33333333, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, (7*8)/2},
|
||||
#endif
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
#ifdef USE_NEW_DYNAREC
|
||||
CPU cpus_WinChip_SS7[] = {
|
||||
/*IDT WinChip*/
|
||||
{"WinChip 75", CPU_WINCHIP, 75000000, 3/2, 25000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 8, 8, 4, 4, 9},
|
||||
{"WinChip 90", CPU_WINCHIP, 90000000, 3/2, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 9, 9, 4, 4, 21/2},
|
||||
{"WinChip 100", CPU_WINCHIP, 100000000, 3/2, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 9, 9, 4, 4, 12},
|
||||
{"WinChip 120", CPU_WINCHIP, 120000000, 2, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 12, 12, 6, 6, 14},
|
||||
{"WinChip 133", CPU_WINCHIP, 133333333, 2, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 12, 12, 6, 6, 16},
|
||||
{"WinChip 150", CPU_WINCHIP, 150000000, 5/2, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 15, 15, 7, 7, 35/2},
|
||||
{"WinChip 166", CPU_WINCHIP, 166666666, 5/2, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 15, 15, 7, 7, 40},
|
||||
{"WinChip 180", CPU_WINCHIP, 180000000, 3, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 21},
|
||||
{"WinChip 200", CPU_WINCHIP, 200000000, 3, 33333333, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 24},
|
||||
{"WinChip 225", CPU_WINCHIP, 225000000, 3, 37500000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 27},
|
||||
{"WinChip 240", CPU_WINCHIP, 240000000, 4, 30000000, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 24, 24, 12, 12, 28},
|
||||
{"WinChip 2/200", CPU_WINCHIP2, 200000000, 3, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 3*8},
|
||||
{"WinChip 2/225", CPU_WINCHIP2, 225000000, 3, 37500000, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 3*9},
|
||||
{"WinChip 2/240", CPU_WINCHIP2, 240000000, 4, 30000000, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 24, 24, 12, 12, 30},
|
||||
{"WinChip 2/250", CPU_WINCHIP2, 250000000, 3, 41666667, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 24, 24, 12, 12, 30},
|
||||
{"WinChip 2A/200", CPU_WINCHIP2, 200000000, 3, 33333333, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 3*8},
|
||||
{"WinChip 2A/233", CPU_WINCHIP2, 233333333, 7/2, 33333333, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 21, 21, 9, 9, (7*8)/2},
|
||||
{"WinChip 2A/266", CPU_WINCHIP2, 233333333, 7/3, 33333333, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 21, 21, 7, 7, 28},
|
||||
{"WinChip 2A/300", CPU_WINCHIP2, 250000000, 5/2, 33333333, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 24, 24, 8, 8, 30},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
#endif
|
||||
|
||||
CPU cpus_Pentium5V[] = {
|
||||
/*Intel Pentium (5V, socket 4)*/
|
||||
{"Pentium 60", CPU_PENTIUM, 60000000, 1, 30000000, 0x517, 0x517, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6,3,3, 7},
|
||||
{"Pentium 66", CPU_PENTIUM, 66666666, 1, 33333333, 0x517, 0x517, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6,3,3, 8},
|
||||
{"Pentium OverDrive 120", CPU_PENTIUM, 120000000, 2, 30000000, 0x51A, 0x51A, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 14},
|
||||
{"Pentium OverDrive 133", CPU_PENTIUM, 133333333, 2, 33333333, 0x51A, 0x51A, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 16},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0, 0}
|
||||
};
|
||||
|
||||
CPU cpus_Pentium5V50[] = {
|
||||
/*Intel Pentium (5V, socket 4, including 50 MHz FSB)*/
|
||||
{"Pentium 50 (Q0399)", CPU_PENTIUM, 50000000, 1, 25000000, 0x513, 0x513, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 4, 4,3,3, 6},
|
||||
{"Pentium 60", CPU_PENTIUM, 60000000, 1, 30000000, 0x517, 0x517, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6,3,3, 7},
|
||||
{"Pentium 66", CPU_PENTIUM, 66666666, 1, 33333333, 0x517, 0x517, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6,3,3, 8},
|
||||
{"Pentium OverDrive 100", CPU_PENTIUM, 100000000, 2, 25000000, 0x51A, 0x51A, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 8, 8,6,6, 12},
|
||||
{"Pentium OverDrive 120", CPU_PENTIUM, 120000000, 2, 30000000, 0x51A, 0x51A, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 14},
|
||||
{"Pentium OverDrive 133", CPU_PENTIUM, 133333333, 2, 33333333, 0x51A, 0x51A, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 16},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0, 0}
|
||||
};
|
||||
|
||||
CPU cpus_PentiumS5[] = {
|
||||
/*Intel Pentium (Socket 5)*/
|
||||
{"Pentium 75", CPU_PENTIUM, 75000000, 3/2, 25000000, 0x522, 0x522, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7,4,4, 9},
|
||||
{"Pentium OverDrive MMX 75", CPU_PENTIUMMMX, 75000000, 3/2, 25000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7,4,4, 9},
|
||||
{"Pentium 90", CPU_PENTIUM, 90000000, 3/2, 30000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 21/2},
|
||||
{"Pentium 100/50", CPU_PENTIUM, 100000000, 2, 25000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,6,6, 12},
|
||||
{"Pentium 100/66", CPU_PENTIUM, 100000000, 3/2, 33333333, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 12},
|
||||
{"Pentium 120", CPU_PENTIUM, 120000000, 2, 30000000, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 14},
|
||||
|
||||
/*Intel Pentium OverDrive*/
|
||||
{"Pentium OverDrive 125", CPU_PENTIUM, 125000000, 3, 25000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,7,7, 16},
|
||||
{"Pentium OverDrive 150", CPU_PENTIUM, 150000000, 5/2, 30000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 35/2},
|
||||
{"Pentium OverDrive 166", CPU_PENTIUM, 166666666, 5/2, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 40},
|
||||
{"Pentium OverDrive MMX 125", CPU_PENTIUMMMX, 125000000, 5/2, 25000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,7,7, 15},
|
||||
{"Pentium OverDrive MMX 150/60", CPU_PENTIUMMMX, 150000000, 5/2, 30000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 35/2},
|
||||
{"Pentium OverDrive MMX 166", CPU_PENTIUMMMX, 166000000, 5/2, 33333333, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 20},
|
||||
{"Pentium OverDrive MMX 180", CPU_PENTIUMMMX, 180000000, 3, 30000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 21},
|
||||
{"Pentium OverDrive MMX 200", CPU_PENTIUMMMX, 200000000, 3, 33333333, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 24},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0, 0}
|
||||
};
|
||||
|
||||
CPU cpus_Pentium3V[] = {
|
||||
/*Intel Pentium*/
|
||||
{"Pentium 75", CPU_PENTIUM, 75000000, 3/2, 25000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9},
|
||||
{"Pentium OverDrive MMX 75", CPU_PENTIUMMMX, 75000000, 3/2, 25000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9},
|
||||
{"Pentium 90", CPU_PENTIUM, 90000000, 3/2, 30000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 21/2},
|
||||
{"Pentium 100/50", CPU_PENTIUM, 100000000, 2, 25000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 12},
|
||||
{"Pentium 100/66", CPU_PENTIUM, 100000000, 3/2, 33333333, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 12},
|
||||
{"Pentium 120", CPU_PENTIUM, 120000000, 2, 30000000, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14},
|
||||
{"Pentium 133", CPU_PENTIUM, 133333333, 2, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16},
|
||||
{"Pentium 150", CPU_PENTIUM, 150000000, 5/2, 30000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2},
|
||||
{"Pentium 166", CPU_PENTIUM, 166666666, 5/2, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20},
|
||||
{"Pentium 200", CPU_PENTIUM, 200000000, 3, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24},
|
||||
|
||||
/*Intel Pentium OverDrive*/
|
||||
{"Pentium OverDrive 125", CPU_PENTIUM, 125000000, 5/2, 25000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 7, 7, 15},
|
||||
{"Pentium OverDrive 150", CPU_PENTIUM, 150000000, 5/2, 30000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2},
|
||||
{"Pentium OverDrive 166", CPU_PENTIUM, 166666666, 5/2, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20},
|
||||
{"Pentium OverDrive MMX 125", CPU_PENTIUMMMX, 125000000, 5/2, 25000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 7, 7, 15},
|
||||
{"Pentium OverDrive MMX 150/60", CPU_PENTIUMMMX, 150000000, 5/2, 30000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2},
|
||||
{"Pentium OverDrive MMX 166", CPU_PENTIUMMMX, 166000000, 5/2, 33333333, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20},
|
||||
{"Pentium OverDrive MMX 180", CPU_PENTIUMMMX, 180000000, 3, 30000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 21},
|
||||
{"Pentium OverDrive MMX 200", CPU_PENTIUMMMX, 200000000, 3, 33333333, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
CPU cpus_Pentium[] = {
|
||||
/*Intel Pentium*/
|
||||
{"Pentium 75", CPU_PENTIUM, 75000000, 3/2, 25000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9},
|
||||
{"Pentium OverDrive MMX 75", CPU_PENTIUMMMX, 75000000, 3/2, 25000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9},
|
||||
{"Pentium 90", CPU_PENTIUM, 90000000, 3/2, 30000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 21/2},
|
||||
{"Pentium 100/50", CPU_PENTIUM, 100000000, 2, 25000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 12},
|
||||
{"Pentium 100/66", CPU_PENTIUM, 100000000, 3/2, 33333333, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 12},
|
||||
{"Pentium 120", CPU_PENTIUM, 120000000, 2, 30000000, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14},
|
||||
{"Pentium 133", CPU_PENTIUM, 133333333, 2, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16},
|
||||
{"Pentium 150", CPU_PENTIUM, 150000000, 5/2, 30000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2},
|
||||
{"Pentium 166", CPU_PENTIUM, 166666666, 5/2, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20},
|
||||
{"Pentium 200", CPU_PENTIUM, 200000000, 3, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24},
|
||||
|
||||
/*Intel Pentium MMX*/
|
||||
{"Pentium MMX 166", CPU_PENTIUMMMX, 166666666, 5/2, 33333333, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20},
|
||||
{"Pentium MMX 200", CPU_PENTIUMMMX, 200000000, 3, 33333333, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24},
|
||||
{"Pentium MMX 233", CPU_PENTIUMMMX, 233333333, 7/2, 33333333, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28},
|
||||
|
||||
/*Mobile Pentium*/
|
||||
{"Mobile Pentium MMX 120", CPU_PENTIUMMMX, 120000000, 2, 30000000, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14},
|
||||
{"Mobile Pentium MMX 133", CPU_PENTIUMMMX, 133333333, 2, 33333333, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16},
|
||||
{"Mobile Pentium MMX 150", CPU_PENTIUMMMX, 150000000, 5/2, 30000000, 0x544, 0x544, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2},
|
||||
{"Mobile Pentium MMX 166", CPU_PENTIUMMMX, 166666666, 5/2, 33333333, 0x544, 0x544, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20},
|
||||
{"Mobile Pentium MMX 200", CPU_PENTIUMMMX, 200000000, 3, 33333333, 0x581, 0x581, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24},
|
||||
{"Mobile Pentium MMX 233", CPU_PENTIUMMMX, 233333333, 7/2, 33333333, 0x581, 0x581, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28},
|
||||
{"Mobile Pentium MMX 266", CPU_PENTIUMMMX, 266666666, 4, 33333333, 0x582, 0x582, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 32},
|
||||
{"Mobile Pentium MMX 300", CPU_PENTIUMMMX, 300000000, 9/2, 33333333, 0x582, 0x582, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 36},
|
||||
|
||||
/*Intel Pentium OverDrive*/
|
||||
{"Pentium OverDrive 125", CPU_PENTIUM, 125000000, 5/2, 25000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 7, 7, 15},
|
||||
{"Pentium OverDrive 150", CPU_PENTIUM, 150000000, 5/2, 30000000, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2},
|
||||
{"Pentium OverDrive 166", CPU_PENTIUM, 166666666, 5/2, 33333333, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20},
|
||||
{"Pentium OverDrive MMX 125", CPU_PENTIUMMMX, 125000000, 5/2, 25000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 7, 7, 15},
|
||||
{"Pentium OverDrive MMX 150/60", CPU_PENTIUMMMX, 150000000, 5/2, 30000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2},
|
||||
{"Pentium OverDrive MMX 166", CPU_PENTIUMMMX, 166000000, 5/2, 33333333, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20},
|
||||
{"Pentium OverDrive MMX 180", CPU_PENTIUMMMX, 180000000, 3, 30000000, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 21},
|
||||
{"Pentium OverDrive MMX 200", CPU_PENTIUMMMX, 200000000, 3, 33333333, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
#if defined(USE_NEW_DYNAREC) || (defined(DEV_BRANCH) && defined(USE_AMD_K))
|
||||
CPU cpus_K5[] = {
|
||||
/*AMD K5 (Socket 5)*/
|
||||
{"K5 (5k86) 75 (P75)", CPU_K5, 75000000, 3/2, 25000000, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7,4,4, 9},
|
||||
{"K5 (SSA/5) 75 (PR75)", CPU_K5, 75000000, 3/2, 25000000, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7,4,4, 9},
|
||||
{"K5 (5k86) 90 (P90)", CPU_K5, 90000000, 3/2, 30000000, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 21/2},
|
||||
{"K5 (SSA/5) 90 (PR90)", CPU_K5, 90000000, 3/2, 30000000, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 21/2},
|
||||
{"K5 (5k86) 100 (P100)", CPU_K5, 100000000, 3/2, 33333333, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 12},
|
||||
{"K5 (SSA/5) 100 (PR100)", CPU_K5, 100000000, 3/2, 33333333, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 12},
|
||||
{"K5 (5k86) 90 (PR120)", CPU_5K86, 120000000, 2, 30000000, 0x511, 0x511, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 14},
|
||||
{"K5 (5k86) 100 (PR133)", CPU_5K86, 133333333, 2, 33333333, 0x514, 0x514, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 16},
|
||||
{"K5 (5k86) 105 (PR150)", CPU_5K86, 150000000, 5/2, 30000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 35/2},
|
||||
{"K5 (5k86) 116.5 (PR166)", CPU_5K86, 166666666, 5/2, 33333333, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 20},
|
||||
{"K5 (5k86) 133 (PR200)", CPU_5K86, 200000000, 3, 33333333, 0x534, 0x534, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 24},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0, 0}
|
||||
};
|
||||
|
||||
CPU cpus_K56[] = {
|
||||
/*AMD K5 (Socket 7)*/
|
||||
{"K5 (5k86) 75 (P75)", CPU_K5, 75000000, 3/2, 25000000, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9},
|
||||
{"K5 (SSA/5) 75 (PR75)", CPU_K5, 75000000, 3/2, 25000000, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9},
|
||||
{"K5 (5k86) 90 (P90)", CPU_K5, 90000000, 3/2, 30000000, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 21/2},
|
||||
{"K5 (SSA/5) 90 (PR90)", CPU_K5, 90000000, 3/2, 30000000, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 21/2},
|
||||
{"K5 (5k86) 100 (P100)", CPU_K5, 100000000, 3/2, 33333333, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 12},
|
||||
{"K5 (SSA/5) 100 (PR100)", CPU_K5, 100000000, 3/2, 33333333, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 12},
|
||||
{"K5 (5k86) 90 (PR120)", CPU_5K86, 120000000, 2, 30000000, 0x511, 0x511, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14},
|
||||
{"K5 (5k86) 100 (PR133)", CPU_5K86, 133333333, 2, 33333333, 0x514, 0x514, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16},
|
||||
{"K5 (5k86) 105 (PR150)", CPU_5K86, 150000000, 5/2, 30000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2},
|
||||
{"K5 (5k86) 116.5 (PR166)", CPU_5K86, 166666666, 5/2, 33333333, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20},
|
||||
{"K5 (5k86) 133 (PR200)", CPU_5K86, 200000000, 3, 33333333, 0x534, 0x534, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24},
|
||||
|
||||
/*AMD K6 (Socket 7*/
|
||||
{"K6 (Model 6) 166", CPU_K6, 166666666, 5/2, 33333333, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20},
|
||||
{"K6 (Model 6) 200", CPU_K6, 200000000, 3, 33333333, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24},
|
||||
{"K6 (Model 6) 233", CPU_K6, 233333333, 7/2, 33333333, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21, 10, 10, 28},
|
||||
{"K6 (Model 7) 200", CPU_K6, 200000000, 3, 33333333, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24},
|
||||
{"K6 (Model 7) 233", CPU_K6, 233333333, 7/2, 33333333, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21, 10, 10, 28},
|
||||
{"K6 (Model 7) 266", CPU_K6, 266666666, 4, 33333333, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24, 12, 12, 32},
|
||||
{"K6 (Model 7) 300", CPU_K6, 300000000, 9/2, 33333333, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27, 13, 13, 36},
|
||||
#ifdef USE_NEW_DYNAREC
|
||||
{"K6-2/233", CPU_K6_2, 233333333, 7/2, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21, 10, 10, 28},
|
||||
{"K6-2/266", CPU_K6_2, 266666666, 4, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24, 12, 12, 32},
|
||||
{"K6-2/300 AFR-66", CPU_K6_2, 300000000, 9/2, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27, 13, 13, 36},
|
||||
{"K6-2/366", CPU_K6_2, 366666666, 11/2, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 33,33, 17, 17, 44},
|
||||
#endif
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef USE_NEW_DYNAREC
|
||||
CPU cpus_K56_SS7[] = {
|
||||
/*AMD K5 (Socket 7)*/
|
||||
{"K5 (5k86) 75 (P75)", CPU_K5, 75000000, 3/2, 25000000, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9},
|
||||
{"K5 (SSA/5) 75 (PR75)", CPU_K5, 75000000, 3/2, 25000000, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9},
|
||||
{"K5 (5k86) 90 (P90)", CPU_K5, 90000000, 3/2, 30000000, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 21/2},
|
||||
{"K5 (SSA/5) 90 (PR90)", CPU_K5, 90000000, 3/2, 30000000, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 21/2},
|
||||
{"K5 (5k86) 100 (P100)", CPU_K5, 100000000, 3/2, 33333333, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 12},
|
||||
{"K5 (SSA/5) 100 (PR100)", CPU_K5, 100000000, 3/2, 33333333, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 12},
|
||||
{"K5 (5k86) 90 (PR120)", CPU_5K86, 120000000, 2, 30000000, 0x511, 0x511, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14},
|
||||
{"K5 (5k86) 100 (PR133)", CPU_5K86, 133333333, 2, 33333333, 0x514, 0x514, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16},
|
||||
{"K5 (5k86) 105 (PR150)", CPU_5K86, 150000000, 5/2, 30000000, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2},
|
||||
{"K5 (5k86) 116.5 (PR166)", CPU_5K86, 166666666, 5/2, 33333333, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20},
|
||||
{"K5 (5k86) 133 (PR200)", CPU_5K86, 200000000, 3, 33333333, 0x534, 0x534, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24},
|
||||
|
||||
/*AMD K6 (Socket 7)*/
|
||||
{"K6 (Model 6) 166", CPU_K6, 166666666, 5/2, 33333333, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20},
|
||||
{"K6 (Model 6) 200", CPU_K6, 200000000, 3, 33333333, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24},
|
||||
{"K6 (Model 6) 233", CPU_K6, 233333333, 7/2, 33333333, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28},
|
||||
{"K6 (Model 7) 200", CPU_K6, 200000000, 3, 33333333, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24},
|
||||
{"K6 (Model 7) 233", CPU_K6, 233333333, 7/2, 33333333, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28},
|
||||
{"K6 (Model 7) 266", CPU_K6, 266666666, 4, 33333333, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 32},
|
||||
{"K6 (Model 7) 300", CPU_K6, 300000000, 9/2, 33333333, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 36},
|
||||
|
||||
/*AMD K6-2 (Socket 7/Super Socket 7)*/
|
||||
{"K6-2/233", CPU_K6_2, 233333333, 7/2, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21, 21, 10, 10, 28},
|
||||
{"K6-2/266", CPU_K6_2, 266666666, 4, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24, 24, 12, 12, 32},
|
||||
{"K6-2/300", CPU_K6_2, 300000000, 3, 33333333, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27, 27, 9, 9, 36},
|
||||
{"K6-2/333", CPU_K6_2, 332500000, 7/2, 31666667, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 30, 30, 11, 11, 40},
|
||||
{"K6-2/350", CPU_K6_2C, 350000000, 7/2, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 32, 32, 11, 11, 42},
|
||||
{"K6-2/366", CPU_K6_2C, 366666666, 11/2, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 33, 33, 17, 17, 44},
|
||||
{"K6-2/380", CPU_K6_2C, 380000000, 4, 31666667, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 34, 34, 12, 12, 46},
|
||||
{"K6-2/400", CPU_K6_2C, 400000000, 4, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 36, 36, 12, 12, 48},
|
||||
{"K6-2/450", CPU_K6_2C, 450000000, 9/2, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 41, 41, 14, 14, 54},
|
||||
{"K6-2/475", CPU_K6_2C, 475000000, 5, 31666667, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 43, 43, 15, 15, 57},
|
||||
{"K6-2/500", CPU_K6_2C, 500000000, 5, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 45, 45, 15, 15, 60},
|
||||
{"K6-2/533", CPU_K6_2C, 533333333, 11/2, 32323232, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 48, 48, 17, 17, 64},
|
||||
{"K6-2/550", CPU_K6_2C, 550000000, 11/2, 33333333, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 50, 50, 17, 17, 66},
|
||||
|
||||
/*AMD K6-2+/K6-3/K6-3+ (Super Socket 7)*/
|
||||
{"K6-2+/450", CPU_K6_2P, 450000000, 9/2, 33333333, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 41, 41, 14, 14, 54},
|
||||
{"K6-2+/475", CPU_K6_2P, 475000000, 5, 31666667, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 43, 43, 15, 15, 57},
|
||||
{"K6-2+/500", CPU_K6_2P, 500000000, 5, 33333333, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 45, 45, 15, 15, 60},
|
||||
{"K6-2+/533", CPU_K6_2P, 533333333, 11/2, 32323232, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 48, 48, 17, 17, 64},
|
||||
{"K6-2+/550", CPU_K6_2P, 550000000, 11/2, 32333333, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 50, 50, 17, 17, 66},
|
||||
{"K6-III/400", CPU_K6_3, 400000000, 4, 33333333, 0x591, 0x591, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 36, 36, 12, 12, 48},
|
||||
{"K6-III/450", CPU_K6_3, 450000000, 9/2, 33333333, 0x591, 0x591, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 41, 41, 14, 14, 54},
|
||||
{"K6-III+/400", CPU_K6_3P, 400000000, 4, 33333333, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 36, 36, 12, 12, 48},
|
||||
{"K6-III+/450", CPU_K6_3P, 450000000, 9/2, 33333333, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 41, 41, 14, 14, 54},
|
||||
{"K6-III+/475", CPU_K6_3P, 475000000, 5, 31666667, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 43, 43, 15, 15, 57},
|
||||
{"K6-III+/500", CPU_K6_3P, 500000000, 5, 33333333, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 45, 45, 15, 15, 60},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef DEV_BRANCH
|
||||
#ifdef USE_I686
|
||||
CPU cpus_PentiumPro[] = {
|
||||
/*Intel Pentium Pro*/
|
||||
{"Pentium Pro 50", CPU_PENTIUMPRO, 50000000, 1, 25000000, 0x612, 0x612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 4, 4, 3, 3, 6},
|
||||
{"Pentium Pro 60" , CPU_PENTIUMPRO, 60000000, 1, 30000000, 0x612, 0x612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6, 3, 3, 7},
|
||||
{"Pentium Pro 66" , CPU_PENTIUMPRO, 66666666, 1, 33333333, 0x612, 0x612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6, 3, 3, 8},
|
||||
{"Pentium Pro 75", CPU_PENTIUMPRO, 75000000, 3/2, 25000000, 0x612, 0x612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9},
|
||||
{"Pentium Pro 150", CPU_PENTIUMPRO, 150000000, 5/2, 30000000, 0x612, 0x612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2},
|
||||
{"Pentium Pro 166", CPU_PENTIUMPRO, 166666666, 5/2, 33333333, 0x617, 0x617, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20},
|
||||
{"Pentium Pro 180", CPU_PENTIUMPRO, 180000000, 3, 30000000, 0x617, 0x617, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 21},
|
||||
{"Pentium Pro 200", CPU_PENTIUMPRO, 200000000, 3, 33333333, 0x617, 0x617, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24},
|
||||
|
||||
/*Intel Pentium II OverDrive*/
|
||||
{"Pentium II Overdrive 50", CPU_PENTIUM2D, 50000000, 1, 25000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 4, 4, 3, 3, 6},
|
||||
{"Pentium II Overdrive 60", CPU_PENTIUM2D, 60000000, 1, 30000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6, 3, 3, 7},
|
||||
{"Pentium II Overdrive 66", CPU_PENTIUM2D, 66666666, 1, 33333333, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6, 3, 3, 8},
|
||||
{"Pentium II Overdrive 75", CPU_PENTIUM2D, 75000000, 3/2, 25000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9},
|
||||
{"Pentium II Overdrive 210", CPU_PENTIUM2D, 210000000, 7/2, 30000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 17,17, 7, 7, 25},
|
||||
{"Pentium II Overdrive 233", CPU_PENTIUM2D, 233333333, 7/2, 33333333, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28},
|
||||
{"Pentium II Overdrive 240", CPU_PENTIUM2D, 240000000, 4, 30000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 29},
|
||||
{"Pentium II Overdrive 266", CPU_PENTIUM2D, 266666666, 4, 33333333, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 32},
|
||||
{"Pentium II Overdrive 270", CPU_PENTIUM2D, 270000000, 9/2, 30000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 25,25,12,12, 33},
|
||||
{"Pentium II Overdrive 300/66", CPU_PENTIUM2D, 300000000, 9/2, 33333333, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 25,25,12,12, 36},
|
||||
{"Pentium II Overdrive 300/60", CPU_PENTIUM2D, 300000000, 5, 30000000, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 36},
|
||||
{"Pentium II Overdrive 333", CPU_PENTIUM2D, 333333333, 5, 33333333, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 40},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
719
src/cpu_common/cpu_table.c
Normal file
719
src/cpu_common/cpu_table.c
Normal file
@@ -0,0 +1,719 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Define all known processor types.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* Version: @(#)cpu_table.c 1.0.7 2019/10/21
|
||||
*
|
||||
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* leilei,
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
*
|
||||
* Copyright 2008-2019 Sarah Walker.
|
||||
* Copyright 2016-2019 leilei.
|
||||
* Copyright 2016-2019 Miran Grca.
|
||||
* Copyright 2017-2019 Fred N. van Kempen.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#include "86box.h"
|
||||
#include "cpu.h"
|
||||
#include "machine.h"
|
||||
|
||||
|
||||
CPU cpus_8088[] = {
|
||||
/*8088 standard*/
|
||||
{"8088/4.77", CPU_8088, 4772728, 1, 0, 0, 0, 0, 0,0,0,0, 1},
|
||||
{"8088/7.16", CPU_8088, 7159092, 1, 0, 0, 0, 0, 0,0,0,0, 1},
|
||||
{"8088/8", CPU_8088, 8000000, 1, 0, 0, 0, 0, 0,0,0,0, 1},
|
||||
{"8088/10", CPU_8088, 10000000, 1, 0, 0, 0, 0, 0,0,0,0, 1},
|
||||
{"8088/12", CPU_8088, 12000000, 1, 0, 0, 0, 0, 0,0,0,0, 1},
|
||||
{"8088/16", CPU_8088, 16000000, 1, 0, 0, 0, 0, 0,0,0,0, 1},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0}
|
||||
};
|
||||
|
||||
CPU cpus_pcjr[] = {
|
||||
/*8088 PCjr*/
|
||||
{"8088/4.77", CPU_8088, 4772728, 1, 0, 0, 0, 0, 0,0,0,0, 1},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0}
|
||||
};
|
||||
|
||||
CPU cpus_europc[] = {
|
||||
/*8088 EuroPC*/
|
||||
{"8088/4.77", CPU_8088, 4772728, 1, 0, 0, 0, CPU_ALTERNATE_XTAL, 0,0,0,0, 1},
|
||||
{"8088/7.16", CPU_8088, 7159092, 1, 0, 0, 0, CPU_ALTERNATE_XTAL, 0,0,0,0, 1},
|
||||
{"8088/9.54", CPU_8088, 9545456, 1, 0, 0, 0, 0, 0,0,0,0, 1},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0}
|
||||
};
|
||||
|
||||
CPU cpus_8086[] = {
|
||||
/*8086 standard*/
|
||||
{"8086/7.16", CPU_8086, 7159092, 1, 0, 0, 0, CPU_ALTERNATE_XTAL, 0,0,0,0, 1},
|
||||
{"8086/8", CPU_8086, 8000000, 1, 0, 0, 0, 0, 0,0,0,0, 1},
|
||||
{"8086/9.54", CPU_8086, 9545456, 1, 0, 0, 0, CPU_ALTERNATE_XTAL, 0,0,0,0, 1},
|
||||
{"8086/10", CPU_8086, 10000000, 1, 0, 0, 0, 0, 0,0,0,0, 1},
|
||||
{"8086/12", CPU_8086, 12000000, 1, 0, 0, 0, 0, 0,0,0,0, 1},
|
||||
{"8086/16", CPU_8086, 16000000, 1, 0, 0, 0, 0, 0,0,0,0, 2},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0}
|
||||
};
|
||||
|
||||
CPU cpus_pc1512[] = {
|
||||
/*8086 Amstrad*/
|
||||
{"8086/8", CPU_8086, 8000000, 1, 0, 0, 0, 0, 0,0,0,0, 1},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0}
|
||||
};
|
||||
|
||||
CPU cpus_286[] = {
|
||||
/*286*/
|
||||
{"286/6", CPU_286, 6000000, 1, 0, 0, 0, 0, 2,2,2,2, 1},
|
||||
{"286/8", CPU_286, 8000000, 1, 0, 0, 0, 0, 2,2,2,2, 1},
|
||||
{"286/10", CPU_286, 10000000, 1, 0, 0, 0, 0, 2,2,2,2, 1},
|
||||
{"286/12", CPU_286, 12500000, 1, 0, 0, 0, 0, 3,3,3,3, 2},
|
||||
{"286/16", CPU_286, 16000000, 1, 0, 0, 0, 0, 3,3,3,3, 2},
|
||||
{"286/20", CPU_286, 20000000, 1, 0, 0, 0, 0, 4,4,4,4, 3},
|
||||
{"286/25", CPU_286, 25000000, 1, 0, 0, 0, 0, 4,4,4,4, 3},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0}
|
||||
};
|
||||
|
||||
CPU cpus_ibmat[] = {
|
||||
/*286*/
|
||||
{"286/6", CPU_286, 6000000, 1, 0, 0, 0, 0, 3,3,3,3, 1},
|
||||
{"286/8", CPU_286, 8000000, 1, 0, 0, 0, 0, 3,3,3,3, 1},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0}
|
||||
};
|
||||
|
||||
CPU cpus_ibmxt286[] = {
|
||||
/*286*/
|
||||
{"286/6", CPU_286, 6000000, 1, 0, 0, 0, 0, 2,2,2,2, 1},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0}
|
||||
};
|
||||
|
||||
CPU cpus_ps1_m2011[] = {
|
||||
/*286*/
|
||||
{"286/10", CPU_286, 10000000, 1, 0, 0, 0, 0, 2,2,2,2, 1},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0,0,0,0, 9}
|
||||
};
|
||||
|
||||
CPU cpus_ps2_m30_286[] = {
|
||||
/*286*/
|
||||
{"286/10", CPU_286, 10000000, 1, 0, 0, 0, 0, 2,2,2,2, 1},
|
||||
{"286/12", CPU_286, 12500000, 1, 0, 0, 0, 0, 3,3,3,3, 2},
|
||||
{"286/16", CPU_286, 16000000, 1, 0, 0, 0, 0, 3,3,3,3, 2},
|
||||
{"286/20", CPU_286, 20000000, 1, 0, 0, 0, 0, 4,4,4,4, 3},
|
||||
{"286/25", CPU_286, 25000000, 1, 0, 0, 0, 0, 4,4,4,4, 3},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0}
|
||||
};
|
||||
|
||||
CPU cpus_i386SX[] = {
|
||||
/*i386SX*/
|
||||
{"i386SX/16", CPU_386SX, 16000000, 1, 0x2308, 0, 0, 0, 3,3,3,3, 2},
|
||||
{"i386SX/20", CPU_386SX, 20000000, 1, 0x2308, 0, 0, 0, 4,4,3,3, 3},
|
||||
{"i386SX/25", CPU_386SX, 25000000, 1, 0x2308, 0, 0, 0, 4,4,3,3, 3},
|
||||
{"i386SX/33", CPU_386SX, 33333333, 1, 0x2308, 0, 0, 0, 6,6,3,3, 4},
|
||||
{"i386SX/40", CPU_386SX, 40000000, 1, 0x2308, 0, 0, 0, 7,7,3,3, 5},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0}
|
||||
};
|
||||
|
||||
CPU cpus_i386DX[] = {
|
||||
/*i386DX/RapidCAD*/
|
||||
{"i386DX/16", CPU_386DX, 16000000, 1, 0x0308, 0, 0, 0, 3,3,3,3, 2},
|
||||
{"i386DX/20", CPU_386DX, 20000000, 1, 0x0308, 0, 0, 0, 4,4,3,3, 3},
|
||||
{"i386DX/25", CPU_386DX, 25000000, 1, 0x0308, 0, 0, 0, 4,4,3,3, 3},
|
||||
{"i386DX/33", CPU_386DX, 33333333, 1, 0x0308, 0, 0, 0, 6,6,3,3, 4},
|
||||
{"i386DX/40", CPU_386DX, 40000000, 1, 0x0308, 0, 0, 0, 7,7,3,3, 5},
|
||||
{"RapidCAD/25", CPU_RAPIDCAD, 25000000, 1, 0x0430, 0, 0, CPU_SUPPORTS_DYNAREC, 4,4,3,3, 3},
|
||||
{"RapidCAD/33", CPU_RAPIDCAD, 33333333, 1, 0x0430, 0, 0, CPU_SUPPORTS_DYNAREC, 6,6,3,3, 4},
|
||||
{"RapidCAD/40", CPU_RAPIDCAD, 40000000, 1, 0x0430, 0, 0, CPU_SUPPORTS_DYNAREC, 7,7,3,3, 5},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0}
|
||||
};
|
||||
|
||||
CPU cpus_Am386SX[] = {
|
||||
/*Am386SX*/
|
||||
{"Am386SX/16", CPU_386SX, 16000000, 1, 0x2308, 0, 0, 0, 3,3,3,3, 2},
|
||||
{"Am386SX/20", CPU_386SX, 20000000, 1, 0x2308, 0, 0, 0, 4,4,3,3, 3},
|
||||
{"Am386SX/25", CPU_386SX, 25000000, 1, 0x2308, 0, 0, 0, 4,4,3,3, 3},
|
||||
{"Am386SX/33", CPU_386SX, 33333333, 1, 0x2308, 0, 0, 0, 6,6,3,3, 4},
|
||||
{"Am386SX/40", CPU_386SX, 40000000, 1, 0x2308, 0, 0, 0, 7,7,3,3, 5},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0}
|
||||
};
|
||||
|
||||
CPU cpus_Am386DX[] = {
|
||||
/*Am386DX*/
|
||||
{"Am386DX/25", CPU_386DX, 25000000, 1, 0x0308, 0, 0, 0, 4,4,3,3, 3},
|
||||
{"Am386DX/33", CPU_386DX, 33333333, 1, 0x0308, 0, 0, 0, 6,6,3,3, 4},
|
||||
{"Am386DX/40", CPU_386DX, 40000000, 1, 0x0308, 0, 0, 0, 7,7,3,3, 5},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0}
|
||||
};
|
||||
|
||||
CPU cpus_486SLC[] = {
|
||||
/*Cx486SLC*/
|
||||
{"Cx486SLC/20", CPU_486SLC, 20000000, 1, 0x400, 0, 0x0000, 0, 4,4,3,3, 3},
|
||||
{"Cx486SLC/25", CPU_486SLC, 25000000, 1, 0x400, 0, 0x0000, 0, 4,4,3,3, 3},
|
||||
{"Cx486SLC/33", CPU_486SLC, 33333333, 1, 0x400, 0, 0x0000, 0, 6,6,3,3, 4},
|
||||
{"Cx486SRx2/32", CPU_486SLC, 32000000, 2, 0x406, 0, 0x0006, 0, 6,6,6,6, 4},
|
||||
{"Cx486SRx2/40", CPU_486SLC, 40000000, 2, 0x406, 0, 0x0006, 0, 8,8,6,6, 6},
|
||||
{"Cx486SRx2/50", CPU_486SLC, 50000000, 2, 0x406, 0, 0x0006, 0, 8,8,6,6, 6},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0}
|
||||
};
|
||||
|
||||
CPU cpus_IBM386SLC[] = {
|
||||
/*IBM 386SLC*/
|
||||
{"386SLC/16", CPU_IBM386SLC, 16000000, 1, 0x300, 0, 0, 0, 3,3,3,3, 2},
|
||||
{"386SLC/20", CPU_IBM386SLC, 20000000, 1, 0x300, 0, 0, 0, 4,4,3,3, 3},
|
||||
{"386SLC/25", CPU_IBM386SLC, 25000000, 1, 0x300, 0, 0, 0, 4,4,3,3, 3},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0}
|
||||
};
|
||||
|
||||
CPU cpus_IBM486SLC[] = {
|
||||
/*IBM 486SLC*/
|
||||
{"486SLC/33", CPU_IBM486SLC, 33333333, 1, 0x400, 0, 0, 0, 6,6,3,3, 4},
|
||||
{"486SLC2/40", CPU_IBM486SLC, 40000000, 2, 0x400, 0, 0, 0, 7,7,6,6, 5},
|
||||
{"486SLC2/50", CPU_IBM486SLC, 50000000, 2, 0x400, 0, 0, 0, 8,8,6,6, 6},
|
||||
{"486SLC2/66", CPU_IBM486SLC, 66666666, 2, 0x400, 0, 0, 0, 12,12,6,6, 8},
|
||||
{"486SLC3/60", CPU_IBM486SLC, 60000000, 3, 0x400, 0, 0, 0, 12,12,9,9, 7},
|
||||
{"486SLC3/75", CPU_IBM486SLC, 75000000, 3, 0x400, 0, 0, 0, 12,12,9,9, 9},
|
||||
{"486SLC3/100", CPU_IBM486SLC, 100000000, 3, 0x400, 0, 0, 0, 18,18,9,9, 12},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0}
|
||||
};
|
||||
|
||||
CPU cpus_IBM486BL[] = {
|
||||
/*IBM Blue Lightning*/
|
||||
{"486BL2/50", CPU_IBM486BL, 50000000, 2, 0x400, 0, 0, 0, 8,8,6,6, 6},
|
||||
{"486BL2/66", CPU_IBM486BL, 66666666, 2, 0x400, 0, 0, 0, 12,12,6,6, 8},
|
||||
{"486BL3/75", CPU_IBM486BL, 75000000, 3, 0x400, 0, 0, 0, 12,12,9,9, 9},
|
||||
{"486BL3/100", CPU_IBM486BL, 100000000, 3, 0x400, 0, 0, 0, 18,18,9,9, 12},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0,0,0,0, 0}
|
||||
};
|
||||
|
||||
CPU cpus_486DLC[] = {
|
||||
/*Cx486DLC*/
|
||||
{"Cx486DLC/25", CPU_486DLC, 25000000, 1, 0x401, 0, 0x0001, 0, 4, 4,3,3, 3},
|
||||
{"Cx486DLC/33", CPU_486DLC, 33333333, 1, 0x401, 0, 0x0001, 0, 6, 6,3,3, 4},
|
||||
{"Cx486DLC/40", CPU_486DLC, 40000000, 1, 0x401, 0, 0x0001, 0, 7, 7,3,3, 5},
|
||||
{"Cx486DRx2/32", CPU_486DLC, 32000000, 2, 0x407, 0, 0x0007, 0, 6, 6,6,6, 4},
|
||||
{"Cx486DRx2/40", CPU_486DLC, 40000000, 2, 0x407, 0, 0x0007, 0, 8, 8,6,6, 6},
|
||||
{"Cx486DRx2/50", CPU_486DLC, 50000000, 2, 0x407, 0, 0x0007, 0, 8, 8,6,6, 6},
|
||||
{"Cx486DRx2/66", CPU_486DLC, 66666666, 2, 0x407, 0, 0x0007, 0, 12,12,6,6, 8},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0,0,0, 0}
|
||||
};
|
||||
|
||||
CPU cpus_i486S1[] = {
|
||||
/*i486*/
|
||||
{"i486SX/16", CPU_i486SX, 16000000, 1, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 3, 3,3,3, 2},
|
||||
{"i486SX/20", CPU_i486SX, 20000000, 1, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 4, 4,3,3, 3},
|
||||
{"i486SX/25", CPU_i486SX, 25000000, 1, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 4, 4,3,3, 3},
|
||||
{"i486SX/33", CPU_i486SX, 33333333, 1, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 6, 6,3,3, 4},
|
||||
{"i486SX2/50", CPU_i486SX2, 50000000, 2, 0x45b, 0, 0, CPU_SUPPORTS_DYNAREC, 8, 8,6,6, 6},
|
||||
{"i486SX2/66 (Q0569)", CPU_i486SX2, 66666666, 2, 0x45b, 0, 0, CPU_SUPPORTS_DYNAREC, 8, 8,6,6, 8},
|
||||
{"i486DX/25", CPU_i486DX, 25000000, 1, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC, 4, 4,3,3, 3},
|
||||
{"i486DX/33", CPU_i486DX, 33333333, 1, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC, 6, 6,3,3, 4},
|
||||
{"i486DX/50", CPU_i486DX, 50000000, 1, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC, 8, 8,4,4, 6},
|
||||
{"i486DX2/40", CPU_i486DX2, 40000000, 2, 0x430, 0x430, 0, CPU_SUPPORTS_DYNAREC, 7, 7,6,6, 5},
|
||||
{"i486DX2/50", CPU_i486DX2, 50000000, 2, 0x430, 0x430, 0, CPU_SUPPORTS_DYNAREC, 8, 8,6,6, 6},
|
||||
{"i486DX2/66", CPU_i486DX2, 66666666, 2, 0x430, 0x430, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 8},
|
||||
{"iDX4 OverDrive 75", CPU_iDX4, 75000000, 3, 0x1480, 0x1480, 0, CPU_SUPPORTS_DYNAREC, 12,12,9,9, 9}, /*Only added the DX4 OverDrive as the others would be redundant*/
|
||||
{"iDX4 OverDrive 100", CPU_iDX4, 100000000, 3, 0x1480, 0x1480, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 12},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0,0,0, 0}
|
||||
};
|
||||
CPU cpus_Am486S1[] = {
|
||||
/*Am486*/
|
||||
{"Am486SX/33", CPU_Am486SX, 33333333, 1, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 6, 6, 3, 3, 4},
|
||||
{"Am486SX/40", CPU_Am486SX, 40000000, 1, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5},
|
||||
{"Am486SX2/50", CPU_Am486SX2, 50000000, 2, 0x45b, 0x45b, 0, CPU_SUPPORTS_DYNAREC, 8, 8, 6, 6, 6}, /*CPUID available on SX2, DX2, DX4, 5x86, >= 50 MHz*/
|
||||
{"Am486SX2/66", CPU_Am486SX2, 66666666, 2, 0x45b, 0x45b, 0, CPU_SUPPORTS_DYNAREC, 12,12, 6, 6, 8}, /*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, 33333333, 1, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 6, 6, 3, 3, 4},
|
||||
{"Am486DX/40", CPU_Am486DX, 40000000, 1, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5},
|
||||
{"Am486DX2/50", CPU_Am486DX2, 50000000, 2, 0x470, 0x470, 0, CPU_SUPPORTS_DYNAREC, 8, 8, 6, 6, 6},
|
||||
{"Am486DX2/66", CPU_Am486DX2, 66666666, 2, 0x470, 0x470, 0, CPU_SUPPORTS_DYNAREC, 12,12, 6, 6, 8},
|
||||
{"Am486DX2/80", CPU_Am486DX2, 80000000, 2, 0x470, 0x470, 0, CPU_SUPPORTS_DYNAREC, 14,14, 6, 6, 10},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
CPU cpus_Cx486S1[] = {
|
||||
/*Cyrix 486*/
|
||||
{"Cx486S/25", CPU_Cx486S, 25000000, 1, 0x420, 0, 0x0010, CPU_SUPPORTS_DYNAREC, 4, 4, 3, 3, 3},
|
||||
{"Cx486S/33", CPU_Cx486S, 33333333, 1, 0x420, 0, 0x0010, CPU_SUPPORTS_DYNAREC, 6, 6, 3, 3, 4},
|
||||
{"Cx486S/40", CPU_Cx486S, 40000000, 1, 0x420, 0, 0x0010, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5},
|
||||
{"Cx486DX/33", CPU_Cx486DX, 33333333, 1, 0x430, 0, 0x051a, CPU_SUPPORTS_DYNAREC, 6, 6, 3, 3, 4},
|
||||
{"Cx486DX/40", CPU_Cx486DX, 40000000, 1, 0x430, 0, 0x051a, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5},
|
||||
{"Cx486DX2/50", CPU_Cx486DX2, 50000000, 2, 0x430, 0, 0x081b, CPU_SUPPORTS_DYNAREC, 8, 8, 6, 6, 6},
|
||||
{"Cx486DX2/66", CPU_Cx486DX2, 66666666, 2, 0x430, 0, 0x0b1b, CPU_SUPPORTS_DYNAREC, 12,12, 6, 6, 8},
|
||||
{"Cx486DX2/80", CPU_Cx486DX2, 80000000, 2, 0x430, 0, 0x311b, CPU_SUPPORTS_DYNAREC, 14,14, 6, 6, 10},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
CPU cpus_i486[] = {
|
||||
/*i486/P24T*/
|
||||
{"i486SX/16", CPU_i486SX, 16000000, 1, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 3, 3,3,3, 2},
|
||||
{"i486SX/20", CPU_i486SX, 20000000, 1, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 4, 4,3,3, 3},
|
||||
{"i486SX/25", CPU_i486SX, 25000000, 1, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 4, 4,3,3, 3},
|
||||
{"i486SX/33", CPU_i486SX, 33333333, 1, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 6, 6,3,3, 4},
|
||||
{"i486SX2/50", CPU_i486SX, 50000000, 2, 0x45b, 0, 0, CPU_SUPPORTS_DYNAREC, 8, 8,6,6, 6},
|
||||
{"i486SX2/66 (Q0569)", CPU_i486SX2, 66666666, 2, 0x45b, 0, 0, CPU_SUPPORTS_DYNAREC, 8, 8,6,6, 8},
|
||||
{"i486DX/25", CPU_i486DX2, 25000000, 1, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC, 4, 4,3,3, 3},
|
||||
{"i486DX/33", CPU_i486DX, 33333333, 1, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC, 6, 6,3,3, 4},
|
||||
{"i486DX/50", CPU_i486DX, 50000000, 1, 0x404, 0, 0, CPU_SUPPORTS_DYNAREC, 8, 8,4,4, 6},
|
||||
{"i486DX2/40", CPU_i486DX2, 40000000, 2, 0x430, 0x430, 0, CPU_SUPPORTS_DYNAREC, 7, 7,6,6, 5}, /*CPUID available on DX2, DX4, P24T, >= 40 MHz*/
|
||||
{"i486DX2/50", CPU_i486DX2, 50000000, 2, 0x430, 0x430, 0, CPU_SUPPORTS_DYNAREC, 8, 8,6,6, 6},
|
||||
{"i486DX2/66", CPU_i486DX2, 66666666, 2, 0x430, 0x430, 0, CPU_SUPPORTS_DYNAREC, 12,12,6,6, 8},
|
||||
{"iDX4/75", CPU_iDX4, 75000000, 3, 0x481, 0x481, 0, CPU_SUPPORTS_DYNAREC, 12,12,9,9, 9}, /*CPUID available on DX4, >= 75 MHz*/
|
||||
{"iDX4/100", CPU_iDX4, 100000000, 3, 0x481, 0x481, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 12}, /*Is on some real Intel DX2s, limit here is pretty arbitary*/
|
||||
{"iDX4 OverDrive 75", CPU_iDX4, 75000000, 3, 0x1480, 0x1480, 0, CPU_SUPPORTS_DYNAREC, 12,12,9,9, 9},
|
||||
{"iDX4 OverDrive 100", CPU_iDX4, 100000000, 3, 0x1480, 0x1480, 0, CPU_SUPPORTS_DYNAREC, 18,18,9,9, 12},
|
||||
{"Pentium OverDrive 63", CPU_PENTIUM, 62500000, 5/2, 0x1531, 0x1531, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,7,7, 15/2},
|
||||
{"Pentium OverDrive 83", CPU_PENTIUM, 83333333, 5/2, 0x1532, 0x1532, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,8,8, 10},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0,0,0, 0}
|
||||
};
|
||||
|
||||
CPU cpus_Am486[] = {
|
||||
/*Am486/5x86*/
|
||||
{"Am486SX/33", CPU_Am486SX, 33333333, 1, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 6, 6, 3, 3, 4},
|
||||
{"Am486SX/40", CPU_Am486SX, 40000000, 1, 0x42a, 0, 0, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5},
|
||||
{"Am486SX2/50", CPU_Am486SX2, 50000000, 2, 0x45b, 0x45b, 0, CPU_SUPPORTS_DYNAREC, 8, 8, 6, 6, 6}, /*CPUID available on SX2, DX2, DX4, 5x86, >= 50 MHz*/
|
||||
{"Am486SX2/66", CPU_Am486SX2, 66666666, 2, 0x45b, 0x45b, 0, CPU_SUPPORTS_DYNAREC, 12,12, 6, 6, 8},
|
||||
{"Am486DX/33", CPU_Am486DX, 33333333, 1, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 6, 6, 3, 3, 4},
|
||||
{"Am486DX/40", CPU_Am486DX, 40000000, 1, 0x430, 0, 0, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5},
|
||||
{"Am486DX2/50", CPU_Am486DX2, 50000000, 2, 0x470, 0x470, 0, CPU_SUPPORTS_DYNAREC, 8, 8, 6, 6, 6},
|
||||
{"Am486DX2/66", CPU_Am486DX2, 66666666, 2, 0x470, 0x470, 0, CPU_SUPPORTS_DYNAREC, 12,12, 6, 6, 8},
|
||||
{"Am486DX2/80", CPU_Am486DX2, 80000000, 2, 0x470, 0x470, 0, CPU_SUPPORTS_DYNAREC, 14,14, 6, 6, 10},
|
||||
{"Am486DX4/75", CPU_Am486DX4, 75000000, 3, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 12,12, 9, 9, 9},
|
||||
{"Am486DX4/90", CPU_Am486DX4, 90000000, 3, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 15,15, 9, 9, 12},
|
||||
{"Am486DX4/100", CPU_Am486DX4, 100000000, 3, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 15,15, 9, 9, 12},
|
||||
{"Am486DX4/120", CPU_Am486DX4, 120000000, 3, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 21,21, 9, 9, 15},
|
||||
{"Am5x86/P75", CPU_Am5x86, 133333333, 4, 0x4e0, 0x4e0, 0, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 16},
|
||||
{"Am5x86/P75+", CPU_Am5x86, 150000000, 3, 0x482, 0x482, 0, CPU_SUPPORTS_DYNAREC, 28,28,12,12, 20},/*The rare P75+ was indeed a triple-clocked 150 MHz according to research*/
|
||||
{"Am5x86/P90", CPU_Am5x86, 160000000, 4, 0x4e0, 0x4e0, 0, CPU_SUPPORTS_DYNAREC, 28,28,12,12, 20},/*160 MHz on a 40 MHz bus was a common overclock and "5x86/P90" was used by a number of BIOSes to refer to that configuration*/
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
CPU cpus_Cx486[] = {
|
||||
/*Cyrix 486*/
|
||||
{"Cx486S/25", CPU_Cx486S, 25000000, 1, 0x420, 0, 0x0010, CPU_SUPPORTS_DYNAREC, 4, 4, 3, 3, 3},
|
||||
{"Cx486S/33", CPU_Cx486S, 33333333, 1, 0x420, 0, 0x0010, CPU_SUPPORTS_DYNAREC, 6, 6, 3, 3, 4},
|
||||
{"Cx486S/40", CPU_Cx486S, 40000000, 1, 0x420, 0, 0x0010, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5},
|
||||
{"Cx486DX/33", CPU_Cx486DX, 33333333, 1, 0x430, 0, 0x051a, CPU_SUPPORTS_DYNAREC, 6, 6, 3, 3, 4},
|
||||
{"Cx486DX/40", CPU_Cx486DX, 40000000, 1, 0x430, 0, 0x051a, CPU_SUPPORTS_DYNAREC, 7, 7, 3, 3, 5},
|
||||
{"Cx486DX2/50", CPU_Cx486DX2, 50000000, 2, 0x430, 0, 0x081b, CPU_SUPPORTS_DYNAREC, 8, 8, 6, 6, 6},
|
||||
{"Cx486DX2/66", CPU_Cx486DX2, 66666666, 2, 0x430, 0, 0x0b1b, CPU_SUPPORTS_DYNAREC, 12,12, 6, 6, 8},
|
||||
{"Cx486DX2/80", CPU_Cx486DX2, 80000000, 2, 0x430, 0, 0x311b, CPU_SUPPORTS_DYNAREC, 14,14, 6, 6, 10},
|
||||
{"Cx486DX4/75", CPU_Cx486DX4, 75000000, 3, 0x480, 0, 0x361f, CPU_SUPPORTS_DYNAREC, 12,12, 9, 9, 9},
|
||||
{"Cx486DX4/100", CPU_Cx486DX4, 100000000, 3, 0x480, 0, 0x361f, CPU_SUPPORTS_DYNAREC, 15,15, 9, 9, 12},
|
||||
|
||||
/*Cyrix 5x86*/
|
||||
{"Cx5x86/80", CPU_Cx5x86, 80000000, 2, 0x480, 0, 0x002f, CPU_SUPPORTS_DYNAREC, 14,14, 6, 6, 10}, /*If we're including the Pentium 50, might as well include this*/
|
||||
{"Cx5x86/100", CPU_Cx5x86, 100000000, 3, 0x480, 0, 0x002f, CPU_SUPPORTS_DYNAREC, 15,15, 9, 9, 12},
|
||||
{"Cx5x86/120", CPU_Cx5x86, 120000000, 3, 0x480, 0, 0x002f, CPU_SUPPORTS_DYNAREC, 21,21, 9, 9, 15},
|
||||
{"Cx5x86/133", CPU_Cx5x86, 133333333, 4, 0x480, 0, 0x002f, CPU_SUPPORTS_DYNAREC, 24,24,12,12, 16},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
#if defined(USE_NEW_DYNAREC) || (defined(DEV_BRANCH) && defined(USE_CYRIX_6X86))
|
||||
CPU cpus_6x863V[] = {
|
||||
/*Cyrix 6x86*/
|
||||
{"Cx6x86/P90", CPU_Cx6x86, 80000000, 2, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 8, 8, 6, 6, 10},
|
||||
{"Cx6x86/PR120+", CPU_Cx6x86, 100000000, 2, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 12},
|
||||
{"Cx6x86/PR133+", CPU_Cx6x86, 110000000, 2, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 14},
|
||||
{"Cx6x86/PR150+", CPU_Cx6x86, 120000000, 2, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14},
|
||||
{"Cx6x86/PR166+", CPU_Cx6x86, 133333333, 2, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16},
|
||||
{"Cx6x86/PR200+", CPU_Cx6x86, 150000000, 2, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 18},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
CPU cpus_6x86[] = {
|
||||
/*Cyrix 6x86*/
|
||||
{"Cx6x86/P90", CPU_Cx6x86, 80000000, 2, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 8, 8, 6, 6, 10},
|
||||
{"Cx6x86/PR120+", CPU_Cx6x86, 100000000, 2, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 12},
|
||||
{"Cx6x86/PR133+", CPU_Cx6x86, 110000000, 2, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 14},
|
||||
{"Cx6x86/PR150+", CPU_Cx6x86, 120000000, 2, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14},
|
||||
{"Cx6x86/PR166+", CPU_Cx6x86, 133333333, 2, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16},
|
||||
{"Cx6x86/PR200+", CPU_Cx6x86, 150000000, 2, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 18},
|
||||
|
||||
/*Cyrix 6x86L*/
|
||||
{"Cx6x86L/PR133+", CPU_Cx6x86L, 110000000, 2, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 14},
|
||||
{"Cx6x86L/PR150+", CPU_Cx6x86L, 120000000, 2, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14},
|
||||
{"Cx6x86L/PR166+", CPU_Cx6x86L, 133333333, 2, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16},
|
||||
{"Cx6x86L/PR200+", CPU_Cx6x86L, 150000000, 2, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 18},
|
||||
|
||||
/*Cyrix 6x86MX/MII*/
|
||||
{"Cx6x86MX/PR166", CPU_Cx6x86MX, 133333333, 2, 0x600, 0x600, 0x0451, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16},
|
||||
{"Cx6x86MX/PR200", CPU_Cx6x86MX, 166666666, 5/2, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20},
|
||||
{"Cx6x86MX/PR233", CPU_Cx6x86MX, 187500000, 5/2, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 45/2},
|
||||
{"Cx6x86MX/PR266", CPU_Cx6x86MX, 208333333, 5/2, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 17,17, 7, 7, 25},
|
||||
{"MII/PR300", CPU_Cx6x86MX, 233333333, 7/2, 0x601, 0x601, 0x0852, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,11,11, 28},
|
||||
{"MII/PR333", CPU_Cx6x86MX, 250000000, 3, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 23,23, 9, 9, 30},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef USE_NEW_DYNAREC
|
||||
CPU cpus_6x86SS7[] = {
|
||||
/*Cyrix 6x86*/
|
||||
{"Cx6x86/P90", CPU_Cx6x86, 80000000, 2, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 8, 8, 6, 6, 10},
|
||||
{"Cx6x86/PR120+", CPU_Cx6x86, 100000000, 2, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 12},
|
||||
{"Cx6x86/PR133+", CPU_Cx6x86, 110000000, 2, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 14},
|
||||
{"Cx6x86/PR150+", CPU_Cx6x86, 120000000, 2, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14},
|
||||
{"Cx6x86/PR166+", CPU_Cx6x86, 133333333, 2, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16},
|
||||
{"Cx6x86/PR200+", CPU_Cx6x86, 150000000, 2, 0x520, 0x520, 0x1731, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 18},
|
||||
|
||||
/*Cyrix 6x86L*/
|
||||
{"Cx6x86L/PR133+", CPU_Cx6x86L, 110000000, 2, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 14},
|
||||
{"Cx6x86L/PR150+", CPU_Cx6x86L, 120000000, 2, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14},
|
||||
{"Cx6x86L/PR166+", CPU_Cx6x86L, 133333333, 2, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16},
|
||||
{"Cx6x86L/PR200+", CPU_Cx6x86L, 150000000, 2, 0x540, 0x540, 0x2231, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 18},
|
||||
|
||||
/*Cyrix 6x86MX/MII*/
|
||||
{"Cx6x86MX/PR166", CPU_Cx6x86MX, 133333333, 2, 0x600, 0x600, 0x0451, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16},
|
||||
{"Cx6x86MX/PR200", CPU_Cx6x86MX, 166666666, 5/2, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20},
|
||||
{"Cx6x86MX/PR233", CPU_Cx6x86MX, 187500000, 5/2, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 45/2},
|
||||
{"Cx6x86MX/PR266", CPU_Cx6x86MX, 208333333, 5/2, 0x600, 0x600, 0x0452, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 17,17, 7, 7, 25},
|
||||
{"MII/PR300", CPU_Cx6x86MX, 233333333, 7/2, 0x601, 0x601, 0x0852, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,11,11, 28},
|
||||
{"MII/PR333", CPU_Cx6x86MX, 250000000, 3, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 23,23, 9, 9, 30},
|
||||
{"MII/PR366", CPU_Cx6x86MX, 250000000, 5/2, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 23,23, 7, 7, 30},
|
||||
{"MII/PR400", CPU_Cx6x86MX, 285000000, 3, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27, 9, 9, 34},
|
||||
{"MII/PR433", CPU_Cx6x86MX, 300000000, 3, 0x601, 0x601, 0x0853, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27, 9, 9, 36},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
#endif
|
||||
|
||||
CPU cpus_WinChip[] = {
|
||||
/*IDT WinChip*/
|
||||
{"WinChip 75", CPU_WINCHIP, 75000000, 3/2, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 8, 8, 4, 4, 9},
|
||||
{"WinChip 90", CPU_WINCHIP, 90000000, 3/2, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 9, 9, 4, 4, 21/2},
|
||||
{"WinChip 100", CPU_WINCHIP, 100000000, 3/2, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 9, 9, 4, 4, 12},
|
||||
{"WinChip 120", CPU_WINCHIP, 120000000, 2, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 12, 12, 6, 6, 14},
|
||||
{"WinChip 133", CPU_WINCHIP, 133333333, 2, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 12, 12, 6, 6, 16},
|
||||
{"WinChip 150", CPU_WINCHIP, 150000000, 5/2, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 15, 15, 7, 7, 35/2},
|
||||
{"WinChip 166", CPU_WINCHIP, 166666666, 5/2, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 15, 15, 7, 7, 40},
|
||||
{"WinChip 180", CPU_WINCHIP, 180000000, 3, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 21},
|
||||
{"WinChip 200", CPU_WINCHIP, 200000000, 3, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 24},
|
||||
{"WinChip 225", CPU_WINCHIP, 225000000, 3, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 27},
|
||||
{"WinChip 240", CPU_WINCHIP, 240000000, 4, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 24, 24, 12, 12, 28},
|
||||
#ifdef USE_NEW_DYNAREC
|
||||
{"WinChip 2/200", CPU_WINCHIP2, 200000000, 3, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 24},
|
||||
{"WinChip 2/225", CPU_WINCHIP2, 225000000, 3, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 27},
|
||||
{"WinChip 2/240", CPU_WINCHIP2, 240000000, 4, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 24, 24, 12, 12, 30},
|
||||
{"WinChip 2/250", CPU_WINCHIP2, 250000000, 3, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 24, 24, 12, 12, 30},
|
||||
{"WinChip 2A/200", CPU_WINCHIP2, 200000000, 3, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 24},
|
||||
{"WinChip 2A/233", CPU_WINCHIP2, 233333333, 7/2, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, (7*8)/2},
|
||||
#endif
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
#ifdef USE_NEW_DYNAREC
|
||||
CPU cpus_WinChip_SS7[] = {
|
||||
/*IDT WinChip*/
|
||||
{"WinChip 75", CPU_WINCHIP, 75000000, 3/2, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 8, 8, 4, 4, 9},
|
||||
{"WinChip 90", CPU_WINCHIP, 90000000, 3/2, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 9, 9, 4, 4, 21/2},
|
||||
{"WinChip 100", CPU_WINCHIP, 100000000, 3/2, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 9, 9, 4, 4, 12},
|
||||
{"WinChip 120", CPU_WINCHIP, 120000000, 2, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 12, 12, 6, 6, 14},
|
||||
{"WinChip 133", CPU_WINCHIP, 133333333, 2, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 12, 12, 6, 6, 16},
|
||||
{"WinChip 150", CPU_WINCHIP, 150000000, 5/2, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 15, 15, 7, 7, 35/2},
|
||||
{"WinChip 166", CPU_WINCHIP, 166666666, 5/2, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 15, 15, 7, 7, 40},
|
||||
{"WinChip 180", CPU_WINCHIP, 180000000, 3, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 21},
|
||||
{"WinChip 200", CPU_WINCHIP, 200000000, 3, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 24},
|
||||
{"WinChip 225", CPU_WINCHIP, 225000000, 3, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 27},
|
||||
{"WinChip 240", CPU_WINCHIP, 240000000, 4, 0x540, 0x540, 0, CPU_SUPPORTS_DYNAREC, 24, 24, 12, 12, 28},
|
||||
{"WinChip 2/200", CPU_WINCHIP2, 200000000, 3, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 3*8},
|
||||
{"WinChip 2/225", CPU_WINCHIP2, 225000000, 3, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 3*9},
|
||||
{"WinChip 2/240", CPU_WINCHIP2, 240000000, 4, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 24, 24, 12, 12, 30},
|
||||
{"WinChip 2/250", CPU_WINCHIP2, 250000000, 3, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC, 24, 24, 12, 12, 30},
|
||||
{"WinChip 2A/200", CPU_WINCHIP2, 200000000, 3, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 18, 18, 9, 9, 3*8},
|
||||
{"WinChip 2A/233", CPU_WINCHIP2, 233333333, 7/2, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 21, 21, 9, 9, (7*8)/2},
|
||||
{"WinChip 2A/266", CPU_WINCHIP2, 233333333, 7/3, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 21, 21, 7, 7, 28},
|
||||
{"WinChip 2A/300", CPU_WINCHIP2, 250000000, 5/2, 0x587, 0x587, 0, CPU_SUPPORTS_DYNAREC, 24, 24, 8, 8, 30},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
#endif
|
||||
|
||||
CPU cpus_Pentium5V[] = {
|
||||
/*Intel Pentium (5V, socket 4)*/
|
||||
{"Pentium 60", CPU_PENTIUM, 60000000, 1, 0x517, 0x517, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6,3,3, 7},
|
||||
{"Pentium 66", CPU_PENTIUM, 66666666, 1, 0x517, 0x517, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6,3,3, 8},
|
||||
{"Pentium OverDrive 120", CPU_PENTIUM, 120000000, 2, 0x51A, 0x51A, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 14},
|
||||
{"Pentium OverDrive 133", CPU_PENTIUM, 133333333, 2, 0x51A, 0x51A, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 16},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
CPU cpus_Pentium5V50[] = {
|
||||
/*Intel Pentium (5V, socket 4, including 50 MHz FSB)*/
|
||||
{"Pentium 50 (Q0399)", CPU_PENTIUM, 50000000, 1, 0x513, 0x513, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 4, 4,3,3, 6},
|
||||
{"Pentium 60", CPU_PENTIUM, 60000000, 1, 0x517, 0x517, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6,3,3, 7},
|
||||
{"Pentium 66", CPU_PENTIUM, 66666666, 1, 0x517, 0x517, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6,3,3, 8},
|
||||
{"Pentium OverDrive 100", CPU_PENTIUM, 100000000, 2, 0x51A, 0x51A, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 8, 8,6,6, 12},
|
||||
{"Pentium OverDrive 120", CPU_PENTIUM, 120000000, 2, 0x51A, 0x51A, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 14},
|
||||
{"Pentium OverDrive 133", CPU_PENTIUM, 133333333, 2, 0x51A, 0x51A, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 16},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
CPU cpus_PentiumS5[] = {
|
||||
/*Intel Pentium (Socket 5)*/
|
||||
{"Pentium 75", CPU_PENTIUM, 75000000, 3/2, 0x522, 0x522, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7,4,4, 9},
|
||||
{"Pentium OverDrive MMX 75", CPU_PENTIUMMMX, 75000000, 3/2, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7,4,4, 9},
|
||||
{"Pentium 90", CPU_PENTIUM, 90000000, 3/2, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 21/2},
|
||||
{"Pentium 100/50", CPU_PENTIUM, 100000000, 2, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,6,6, 12},
|
||||
{"Pentium 100/66", CPU_PENTIUM, 100000000, 3/2, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 12},
|
||||
{"Pentium 120", CPU_PENTIUM, 120000000, 2, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 14},
|
||||
|
||||
/*Intel Pentium OverDrive*/
|
||||
{"Pentium OverDrive 125", CPU_PENTIUM, 125000000, 3, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,7,7, 16},
|
||||
{"Pentium OverDrive 150", CPU_PENTIUM, 150000000, 5/2, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 35/2},
|
||||
{"Pentium OverDrive 166", CPU_PENTIUM, 166666666, 5/2, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 40},
|
||||
{"Pentium OverDrive MMX 125", CPU_PENTIUMMMX, 125000000, 5/2, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,7,7, 15},
|
||||
{"Pentium OverDrive MMX 150/60", CPU_PENTIUMMMX, 150000000, 5/2, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 35/2},
|
||||
{"Pentium OverDrive MMX 166", CPU_PENTIUMMMX, 166000000, 5/2, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 20},
|
||||
{"Pentium OverDrive MMX 180", CPU_PENTIUMMMX, 180000000, 3, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 21},
|
||||
{"Pentium OverDrive MMX 200", CPU_PENTIUMMMX, 200000000, 3, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 24},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
CPU cpus_Pentium3V[] = {
|
||||
/*Intel Pentium*/
|
||||
{"Pentium 75", CPU_PENTIUM, 75000000, 3/2, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9},
|
||||
{"Pentium OverDrive MMX 75", CPU_PENTIUMMMX, 75000000, 3/2, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9},
|
||||
{"Pentium 90", CPU_PENTIUM, 90000000, 3/2, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 21/2},
|
||||
{"Pentium 100/50", CPU_PENTIUM, 100000000, 2, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 12},
|
||||
{"Pentium 100/66", CPU_PENTIUM, 100000000, 3/2, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 12},
|
||||
{"Pentium 120", CPU_PENTIUM, 120000000, 2, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14},
|
||||
{"Pentium 133", CPU_PENTIUM, 133333333, 2, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16},
|
||||
{"Pentium 150", CPU_PENTIUM, 150000000, 5/2, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2},
|
||||
{"Pentium 166", CPU_PENTIUM, 166666666, 5/2, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20},
|
||||
{"Pentium 200", CPU_PENTIUM, 200000000, 3, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24},
|
||||
|
||||
/*Intel Pentium OverDrive*/
|
||||
{"Pentium OverDrive 125", CPU_PENTIUM, 125000000, 5/2, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 7, 7, 15},
|
||||
{"Pentium OverDrive 150", CPU_PENTIUM, 150000000, 5/2, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2},
|
||||
{"Pentium OverDrive 166", CPU_PENTIUM, 166666666, 5/2, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20},
|
||||
{"Pentium OverDrive MMX 125", CPU_PENTIUMMMX, 125000000, 5/2, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 7, 7, 15},
|
||||
{"Pentium OverDrive MMX 150/60", CPU_PENTIUMMMX, 150000000, 5/2, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2},
|
||||
{"Pentium OverDrive MMX 166", CPU_PENTIUMMMX, 166000000, 5/2, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20},
|
||||
{"Pentium OverDrive MMX 180", CPU_PENTIUMMMX, 180000000, 3, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 21},
|
||||
{"Pentium OverDrive MMX 200", CPU_PENTIUMMMX, 200000000, 3, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
CPU cpus_Pentium[] = {
|
||||
/*Intel Pentium*/
|
||||
{"Pentium 75", CPU_PENTIUM, 75000000, 3/2, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9},
|
||||
{"Pentium OverDrive MMX 75", CPU_PENTIUMMMX, 75000000, 3/2, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9},
|
||||
{"Pentium 90", CPU_PENTIUM, 90000000, 3/2, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 21/2},
|
||||
{"Pentium 100/50", CPU_PENTIUM, 100000000, 2, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10, 6, 6, 12},
|
||||
{"Pentium 100/66", CPU_PENTIUM, 100000000, 3/2, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 12},
|
||||
{"Pentium 120", CPU_PENTIUM, 120000000, 2, 0x526, 0x526, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14},
|
||||
{"Pentium 133", CPU_PENTIUM, 133333333, 2, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16},
|
||||
{"Pentium 150", CPU_PENTIUM, 150000000, 5/2, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2},
|
||||
{"Pentium 166", CPU_PENTIUM, 166666666, 5/2, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20},
|
||||
{"Pentium 200", CPU_PENTIUM, 200000000, 3, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24},
|
||||
|
||||
/*Intel Pentium MMX*/
|
||||
{"Pentium MMX 166", CPU_PENTIUMMMX, 166666666, 5/2, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20},
|
||||
{"Pentium MMX 200", CPU_PENTIUMMMX, 200000000, 3, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24},
|
||||
{"Pentium MMX 233", CPU_PENTIUMMMX, 233333333, 7/2, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28},
|
||||
|
||||
/*Mobile Pentium*/
|
||||
{"Mobile Pentium MMX 120", CPU_PENTIUMMMX, 120000000, 2, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14},
|
||||
{"Mobile Pentium MMX 133", CPU_PENTIUMMMX, 133333333, 2, 0x543, 0x543, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16},
|
||||
{"Mobile Pentium MMX 150", CPU_PENTIUMMMX, 150000000, 5/2, 0x544, 0x544, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2},
|
||||
{"Mobile Pentium MMX 166", CPU_PENTIUMMMX, 166666666, 5/2, 0x544, 0x544, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20},
|
||||
{"Mobile Pentium MMX 200", CPU_PENTIUMMMX, 200000000, 3, 0x581, 0x581, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24},
|
||||
{"Mobile Pentium MMX 233", CPU_PENTIUMMMX, 233333333, 7/2, 0x581, 0x581, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28},
|
||||
{"Mobile Pentium MMX 266", CPU_PENTIUMMMX, 266666666, 4, 0x582, 0x582, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 32},
|
||||
{"Mobile Pentium MMX 300", CPU_PENTIUMMMX, 300000000, 9/2, 0x582, 0x582, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 36},
|
||||
|
||||
/*Intel Pentium OverDrive*/
|
||||
{"Pentium OverDrive 125", CPU_PENTIUM, 125000000, 5/2, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 7, 7, 15},
|
||||
{"Pentium OverDrive 150", CPU_PENTIUM, 150000000, 5/2, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2},
|
||||
{"Pentium OverDrive 166", CPU_PENTIUM, 166666666, 5/2, 0x52c, 0x52c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20},
|
||||
{"Pentium OverDrive MMX 125", CPU_PENTIUMMMX, 125000000, 5/2, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 7, 7, 15},
|
||||
{"Pentium OverDrive MMX 150/60", CPU_PENTIUMMMX, 150000000, 5/2, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2},
|
||||
{"Pentium OverDrive MMX 166", CPU_PENTIUMMMX, 166000000, 5/2, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20},
|
||||
{"Pentium OverDrive MMX 180", CPU_PENTIUMMMX, 180000000, 3, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 21},
|
||||
{"Pentium OverDrive MMX 200", CPU_PENTIUMMMX, 200000000, 3, 0x1542, 0x1542, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
#if defined(USE_NEW_DYNAREC) || (defined(DEV_BRANCH) && defined(USE_AMD_K))
|
||||
CPU cpus_K5[] = {
|
||||
/*AMD K5 (Socket 5)*/
|
||||
{"K5 (5k86) 75 (P75)", CPU_K5, 75000000, 3/2, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7,4,4, 9},
|
||||
{"K5 (SSA/5) 75 (PR75)", CPU_K5, 75000000, 3/2, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7,4,4, 9},
|
||||
{"K5 (5k86) 90 (P90)", CPU_K5, 90000000, 3/2, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 21/2},
|
||||
{"K5 (SSA/5) 90 (PR90)", CPU_K5, 90000000, 3/2, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 21/2},
|
||||
{"K5 (5k86) 100 (P100)", CPU_K5, 100000000, 3/2, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 12},
|
||||
{"K5 (SSA/5) 100 (PR100)", CPU_K5, 100000000, 3/2, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9,4,4, 12},
|
||||
{"K5 (5k86) 90 (PR120)", CPU_5K86, 120000000, 2, 0x511, 0x511, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 14},
|
||||
{"K5 (5k86) 100 (PR133)", CPU_5K86, 133333333, 2, 0x514, 0x514, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12,6,6, 16},
|
||||
{"K5 (5k86) 105 (PR150)", CPU_5K86, 150000000, 5/2, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 35/2},
|
||||
{"K5 (5k86) 116.5 (PR166)", CPU_5K86, 166666666, 5/2, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,7,7, 20},
|
||||
{"K5 (5k86) 133 (PR200)", CPU_5K86, 200000000, 3, 0x534, 0x534, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18,9,9, 24},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
CPU cpus_K56[] = {
|
||||
/*AMD K5 (Socket 7)*/
|
||||
{"K5 (5k86) 75 (P75)", CPU_K5, 75000000, 3/2, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9},
|
||||
{"K5 (SSA/5) 75 (PR75)", CPU_K5, 75000000, 3/2, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9},
|
||||
{"K5 (5k86) 90 (P90)", CPU_K5, 90000000, 3/2, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 21/2},
|
||||
{"K5 (SSA/5) 90 (PR90)", CPU_K5, 90000000, 3/2, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 21/2},
|
||||
{"K5 (5k86) 100 (P100)", CPU_K5, 100000000, 3/2, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 12},
|
||||
{"K5 (SSA/5) 100 (PR100)", CPU_K5, 100000000, 3/2, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 12},
|
||||
{"K5 (5k86) 90 (PR120)", CPU_5K86, 120000000, 2, 0x511, 0x511, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14},
|
||||
{"K5 (5k86) 100 (PR133)", CPU_5K86, 133333333, 2, 0x514, 0x514, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16},
|
||||
{"K5 (5k86) 105 (PR150)", CPU_5K86, 150000000, 5/2, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2},
|
||||
{"K5 (5k86) 116.5 (PR166)", CPU_5K86, 166666666, 5/2, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20},
|
||||
{"K5 (5k86) 133 (PR200)", CPU_5K86, 200000000, 3, 0x534, 0x534, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24},
|
||||
|
||||
/*AMD K6 (Socket 7*/
|
||||
{"K6 (Model 6) 166", CPU_K6, 166666666, 5/2, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20},
|
||||
{"K6 (Model 6) 200", CPU_K6, 200000000, 3, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24},
|
||||
{"K6 (Model 6) 233", CPU_K6, 233333333, 7/2, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21, 10, 10, 28},
|
||||
{"K6 (Model 7) 200", CPU_K6, 200000000, 3, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24},
|
||||
{"K6 (Model 7) 233", CPU_K6, 233333333, 7/2, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21, 10, 10, 28},
|
||||
{"K6 (Model 7) 266", CPU_K6, 266666666, 4, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24, 12, 12, 32},
|
||||
{"K6 (Model 7) 300", CPU_K6, 300000000, 9/2, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27, 13, 13, 36},
|
||||
#ifdef USE_NEW_DYNAREC
|
||||
{"K6-2/233", CPU_K6_2, 233333333, 7/2, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21, 10, 10, 28},
|
||||
{"K6-2/266", CPU_K6_2, 266666666, 4, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24, 12, 12, 32},
|
||||
{"K6-2/300 AFR-66", CPU_K6_2, 300000000, 9/2, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27, 13, 13, 36},
|
||||
{"K6-2/366", CPU_K6_2, 366666666, 11/2, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 33,33, 17, 17, 44},
|
||||
#endif
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef USE_NEW_DYNAREC
|
||||
CPU cpus_K56_SS7[] = {
|
||||
/*AMD K5 (Socket 7)*/
|
||||
{"K5 (5k86) 75 (P75)", CPU_K5, 75000000, 3/2, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9},
|
||||
{"K5 (SSA/5) 75 (PR75)", CPU_K5, 75000000, 3/2, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9},
|
||||
{"K5 (5k86) 90 (P90)", CPU_K5, 90000000, 3/2, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 21/2},
|
||||
{"K5 (SSA/5) 90 (PR90)", CPU_K5, 90000000, 3/2, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 21/2},
|
||||
{"K5 (5k86) 100 (P100)", CPU_K5, 100000000, 3/2, 0x500, 0x500, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 12},
|
||||
{"K5 (SSA/5) 100 (PR100)", CPU_K5, 100000000, 3/2, 0x501, 0x501, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 9, 9, 4, 4, 12},
|
||||
{"K5 (5k86) 90 (PR120)", CPU_5K86, 120000000, 2, 0x511, 0x511, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 14},
|
||||
{"K5 (5k86) 100 (PR133)", CPU_5K86, 133333333, 2, 0x514, 0x514, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 12,12, 6, 6, 16},
|
||||
{"K5 (5k86) 105 (PR150)", CPU_5K86, 150000000, 5/2, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2},
|
||||
{"K5 (5k86) 116.5 (PR166)", CPU_5K86, 166666666, 5/2, 0x524, 0x524, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20},
|
||||
{"K5 (5k86) 133 (PR200)", CPU_5K86, 200000000, 3, 0x534, 0x534, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24},
|
||||
|
||||
/*AMD K6 (Socket 7)*/
|
||||
{"K6 (Model 6) 166", CPU_K6, 166666666, 5/2, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20},
|
||||
{"K6 (Model 6) 200", CPU_K6, 200000000, 3, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24},
|
||||
{"K6 (Model 6) 233", CPU_K6, 233333333, 7/2, 0x561, 0x561, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28},
|
||||
{"K6 (Model 7) 200", CPU_K6, 200000000, 3, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24},
|
||||
{"K6 (Model 7) 233", CPU_K6, 233333333, 7/2, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28},
|
||||
{"K6 (Model 7) 266", CPU_K6, 266666666, 4, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 32},
|
||||
{"K6 (Model 7) 300", CPU_K6, 300000000, 9/2, 0x570, 0x570, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 36},
|
||||
|
||||
/*AMD K6-2 (Socket 7/Super Socket 7)*/
|
||||
{"K6-2/233", CPU_K6_2, 233333333, 7/2, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21, 21, 10, 10, 28},
|
||||
{"K6-2/266", CPU_K6_2, 266666666, 4, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24, 24, 12, 12, 32},
|
||||
{"K6-2/300", CPU_K6_2, 300000000, 3, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27, 27, 9, 9, 36},
|
||||
{"K6-2/333", CPU_K6_2, 332500000, 7/2, 0x580, 0x580, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 30, 30, 11, 11, 40},
|
||||
{"K6-2/350", CPU_K6_2C, 350000000, 7/2, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 32, 32, 11, 11, 42},
|
||||
{"K6-2/366", CPU_K6_2C, 366666666, 11/2, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 33, 33, 17, 17, 44},
|
||||
{"K6-2/380", CPU_K6_2C, 380000000, 4, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 34, 34, 12, 12, 46},
|
||||
{"K6-2/400", CPU_K6_2C, 400000000, 4, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 36, 36, 12, 12, 48},
|
||||
{"K6-2/450", CPU_K6_2C, 450000000, 9/2, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 41, 41, 14, 14, 54},
|
||||
{"K6-2/475", CPU_K6_2C, 475000000, 5, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 43, 43, 15, 15, 57},
|
||||
{"K6-2/500", CPU_K6_2C, 500000000, 5, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 45, 45, 15, 15, 60},
|
||||
{"K6-2/533", CPU_K6_2C, 533333333, 11/2, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 48, 48, 17, 17, 64},
|
||||
{"K6-2/550", CPU_K6_2C, 550000000, 11/2, 0x58c, 0x58c, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 50, 50, 17, 17, 66},
|
||||
|
||||
/*AMD K6-2+/K6-3/K6-3+ (Super Socket 7)*/
|
||||
{"K6-2+/450", CPU_K6_2P, 450000000, 9/2, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 41, 41, 14, 14, 54},
|
||||
{"K6-2+/475", CPU_K6_2P, 475000000, 5, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 43, 43, 15, 15, 57},
|
||||
{"K6-2+/500", CPU_K6_2P, 500000000, 5, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 45, 45, 15, 15, 60},
|
||||
{"K6-2+/533", CPU_K6_2P, 533333333, 11/2, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 48, 48, 17, 17, 64},
|
||||
{"K6-2+/550", CPU_K6_2P, 550000000, 11/2, 0x5d4, 0x5d4, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 50, 50, 17, 17, 66},
|
||||
{"K6-III/400", CPU_K6_3, 400000000, 4, 0x591, 0x591, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 36, 36, 12, 12, 48},
|
||||
{"K6-III/450", CPU_K6_3, 450000000, 9/2, 0x591, 0x591, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 41, 41, 14, 14, 54},
|
||||
{"K6-III+/400", CPU_K6_3P, 400000000, 4, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 36, 36, 12, 12, 48},
|
||||
{"K6-III+/450", CPU_K6_3P, 450000000, 9/2, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 41, 41, 14, 14, 54},
|
||||
{"K6-III+/475", CPU_K6_3P, 475000000, 5, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 43, 43, 15, 15, 57},
|
||||
{"K6-III+/500", CPU_K6_3P, 500000000, 5, 0x5d0, 0x5d0, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 45, 45, 15, 15, 60},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef DEV_BRANCH
|
||||
#ifdef USE_I686
|
||||
CPU cpus_PentiumPro[] = {
|
||||
/*Intel Pentium Pro*/
|
||||
{"Pentium Pro 50", CPU_PENTIUMPRO, 50000000, 1, 0x612, 0x612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 4, 4, 3, 3, 6},
|
||||
{"Pentium Pro 60" , CPU_PENTIUMPRO, 60000000, 1, 0x612, 0x612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6, 3, 3, 7},
|
||||
{"Pentium Pro 66" , CPU_PENTIUMPRO, 66666666, 1, 0x612, 0x612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6, 3, 3, 8},
|
||||
{"Pentium Pro 75", CPU_PENTIUMPRO, 75000000, 3/2, 0x612, 0x612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9},
|
||||
{"Pentium Pro 150", CPU_PENTIUMPRO, 150000000, 5/2, 0x612, 0x612, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 35/2},
|
||||
{"Pentium Pro 166", CPU_PENTIUMPRO, 166666666, 5/2, 0x617, 0x617, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15, 7, 7, 20},
|
||||
{"Pentium Pro 180", CPU_PENTIUMPRO, 180000000, 3, 0x617, 0x617, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 21},
|
||||
{"Pentium Pro 200", CPU_PENTIUMPRO, 200000000, 3, 0x617, 0x617, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 18,18, 9, 9, 24},
|
||||
|
||||
/*Intel Pentium II OverDrive*/
|
||||
{"Pentium II Overdrive 50", CPU_PENTIUM2D, 50000000, 1, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 4, 4, 3, 3, 6},
|
||||
{"Pentium II Overdrive 60", CPU_PENTIUM2D, 60000000, 1, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6, 3, 3, 7},
|
||||
{"Pentium II Overdrive 66", CPU_PENTIUM2D, 66666666, 1, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6, 3, 3, 8},
|
||||
{"Pentium II Overdrive 75", CPU_PENTIUM2D, 75000000, 3/2, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9},
|
||||
{"Pentium II Overdrive 210", CPU_PENTIUM2D, 210000000, 7/2, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 17,17, 7, 7, 25},
|
||||
{"Pentium II Overdrive 233", CPU_PENTIUM2D, 233333333, 7/2, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28},
|
||||
{"Pentium II Overdrive 240", CPU_PENTIUM2D, 240000000, 4, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 29},
|
||||
{"Pentium II Overdrive 266", CPU_PENTIUM2D, 266666666, 4, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 32},
|
||||
{"Pentium II Overdrive 270", CPU_PENTIUM2D, 270000000, 9/2, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 25,25,12,12, 33},
|
||||
{"Pentium II Overdrive 300/66", CPU_PENTIUM2D, 300000000, 9/2, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 25,25,12,12, 36},
|
||||
{"Pentium II Overdrive 300/60", CPU_PENTIUM2D, 300000000, 5, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 36},
|
||||
{"Pentium II Overdrive 333", CPU_PENTIUM2D, 333333333, 5, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 40},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
CPU cpus_PentiumII[] = {
|
||||
/*Intel Pentium II Klamath*/
|
||||
{"Pentium II Klamath 50", CPU_PENTIUM2, 50000000, 1, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 4, 4, 3, 3, 6},
|
||||
{"Pentium II Klamath 60", CPU_PENTIUM2, 60000000, 1, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6, 3, 3, 7},
|
||||
{"Pentium II Klamath 66", CPU_PENTIUM2, 66666666, 1, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6, 3, 3, 8},
|
||||
{"Pentium II Klamath 75", CPU_PENTIUM2, 75000000, 3/2, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9},
|
||||
{"Pentium II Klamath 233", CPU_PENTIUM2, 233333333, 7/2, 0x634, 0x634, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 21,21,10,10, 28},
|
||||
{"Pentium II Klamath 266", CPU_PENTIUM2, 266666666, 4, 0x634, 0x634, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 29},
|
||||
{"Pentium II Klamath 300/66", CPU_PENTIUM2, 300000000, 9/2, 0x634, 0x634, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 25,25,12,12, 36},
|
||||
|
||||
/*Intel Pentium II Deschutes*/
|
||||
{"Pentium II Deschutes 50", CPU_PENTIUM2D, 50000000, 1, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 4, 4, 3, 3, 6},
|
||||
{"Pentium II Deschutes 60", CPU_PENTIUM2D, 60000000, 1, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6, 3, 3, 7},
|
||||
{"Pentium II Deschutes 66", CPU_PENTIUM2D, 66666666, 1, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 6, 6, 3, 3, 8},
|
||||
{"Pentium II Deschutes 75", CPU_PENTIUM2D, 75000000, 3/2, 0x1632, 0x1632, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 7, 7, 4, 4, 9},
|
||||
{"Pentium II Deschutes 266", CPU_PENTIUM2D, 266666666, 4, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 24,24,12,12, 29},
|
||||
{"Pentium II Deschutes 300/66", CPU_PENTIUM2D, 300000000, 9/2, 0x651, 0x651, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 25,25,12,12, 36},
|
||||
{"Pentium II Deschutes 333", CPU_PENTIUM2D, 333333333, 5, 0x651, 0x651, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 27,27,13,13, 40},
|
||||
{"Pentium II Deschutes 350", CPU_PENTIUM2D, 350000000, 7/2, 0x651, 0x651, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 32,32,11,11, 42},
|
||||
{"Pentium II Deschutes 400", CPU_PENTIUM2D, 400000000, 4, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 36,36,12,12, 48},
|
||||
{"Pentium II Deschutes 450", CPU_PENTIUM2D, 450000000, 9/2, 0x652, 0x652, 0, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 41,41,14,14, 54},
|
||||
{"", -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
70
src/cpu_common/x86.h
Normal file
70
src/cpu_common/x86.h
Normal file
@@ -0,0 +1,70 @@
|
||||
extern uint8_t opcode, opcode2;
|
||||
extern uint8_t flags_p;
|
||||
extern uint8_t znptable8[256];
|
||||
|
||||
extern uint16_t zero, oldcs;
|
||||
extern uint16_t lastcs, lastpc;
|
||||
extern uint16_t *mod1add[2][8];
|
||||
extern uint16_t znptable16[65536];
|
||||
|
||||
extern int x86_was_reset, trap;
|
||||
extern int codegen_flat_ss, codegen_flat_ds;
|
||||
extern int timetolive, keyboardtimer, trap;
|
||||
extern int optype, stack32;
|
||||
extern int oldcpl, cgate32, cpl_override, fpucount;
|
||||
extern int nmi_enable;
|
||||
extern int oddeven, inttype;
|
||||
|
||||
extern uint32_t use32;
|
||||
extern uint32_t rmdat, easeg;
|
||||
extern uint32_t oxpc, flags_zn;
|
||||
extern uint32_t abrt_error;
|
||||
extern uint32_t backupregs[16];
|
||||
extern uint32_t *mod1seg[8];
|
||||
extern uint32_t *eal_r, *eal_w;
|
||||
|
||||
#define fetchdat rmdat
|
||||
|
||||
#define setznp168 setznp16
|
||||
|
||||
#define getr8(r) ((r&4)?cpu_state.regs[r&3].b.h:cpu_state.regs[r&3].b.l)
|
||||
#define getr16(r) cpu_state.regs[r].w
|
||||
#define getr32(r) cpu_state.regs[r].l
|
||||
|
||||
#define setr8(r,v) if (r&4) cpu_state.regs[r&3].b.h=v; \
|
||||
else cpu_state.regs[r&3].b.l=v;
|
||||
#define setr16(r,v) cpu_state.regs[r].w=v
|
||||
#define setr32(r,v) cpu_state.regs[r].l=v
|
||||
|
||||
#define fetchea() { \
|
||||
rmdat = readmemb(cs + pc); \
|
||||
pc++; \
|
||||
reg = (rmdat >> 3) & 7; \
|
||||
mod = (rmdat >> 6) & 3; \
|
||||
rm = rmdat & 7; \
|
||||
if (mod!=3) \
|
||||
fetcheal(); \
|
||||
}
|
||||
|
||||
#define JMP 1
|
||||
#define CALL 2
|
||||
#define IRET 3
|
||||
#define OPTYPE_INT 4
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
ABRT_NONE = 0,
|
||||
ABRT_GEN,
|
||||
ABRT_TS = 0xA,
|
||||
ABRT_NP = 0xB,
|
||||
ABRT_SS = 0xC,
|
||||
ABRT_GPF = 0xD,
|
||||
ABRT_PF = 0xE
|
||||
};
|
||||
|
||||
|
||||
extern void x86_doabrt(int x86_abrt);
|
||||
extern void x86illegal();
|
||||
extern void x86seg_reset();
|
||||
extern void x86gpf(char *s, uint16_t error);
|
||||
265
src/cpu_common/x86_ops.h
Normal file
265
src/cpu_common/x86_ops.h
Normal file
@@ -0,0 +1,265 @@
|
||||
/*
|
||||
* VARCem Virtual ARchaeological Computer EMulator.
|
||||
* An emulator of (mostly) x86-based PC systems and devices,
|
||||
* using the ISA,EISA,VLB,MCA and PCI system buses, roughly
|
||||
* spanning the era between 1981 and 1995.
|
||||
*
|
||||
* This file is part of the VARCem Project.
|
||||
*
|
||||
* Miscellaneous x86 CPU Instructions.
|
||||
*
|
||||
* Version: @(#)x86_ops.h 1.0.2 2018/05/05
|
||||
*
|
||||
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
* Sarah Walker, <tommowalker@tommowalker.co.uk>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2018 Fred N. van Kempen.
|
||||
* Copyright 2008-2018 Sarah Walker.
|
||||
* Copyright 2016-2018 Miran Grca.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the:
|
||||
*
|
||||
* Free Software Foundation, Inc.
|
||||
* 59 Temple Place - Suite 330
|
||||
* Boston, MA 02111-1307
|
||||
* USA.
|
||||
*/
|
||||
#ifndef _X86_OPS_H
|
||||
#define _X86_OPS_H
|
||||
|
||||
|
||||
#define UN_USED(x) (void)(x)
|
||||
|
||||
|
||||
typedef int (*OpFn)(uint32_t fetchdat);
|
||||
|
||||
#ifdef USE_DYNAREC
|
||||
void x86_setopcodes(const OpFn *opcodes, const OpFn *opcodes_0f,
|
||||
const OpFn *dynarec_opcodes,
|
||||
const OpFn *dynarec_opcodes_0f);
|
||||
|
||||
extern const OpFn *x86_dynarec_opcodes;
|
||||
extern const OpFn *x86_dynarec_opcodes_0f;
|
||||
extern const OpFn *x86_dynarec_opcodes_d8_a16;
|
||||
extern const OpFn *x86_dynarec_opcodes_d8_a32;
|
||||
extern const OpFn *x86_dynarec_opcodes_d9_a16;
|
||||
extern const OpFn *x86_dynarec_opcodes_d9_a32;
|
||||
extern const OpFn *x86_dynarec_opcodes_da_a16;
|
||||
extern const OpFn *x86_dynarec_opcodes_da_a32;
|
||||
extern const OpFn *x86_dynarec_opcodes_db_a16;
|
||||
extern const OpFn *x86_dynarec_opcodes_db_a32;
|
||||
extern const OpFn *x86_dynarec_opcodes_dc_a16;
|
||||
extern const OpFn *x86_dynarec_opcodes_dc_a32;
|
||||
extern const OpFn *x86_dynarec_opcodes_dd_a16;
|
||||
extern const OpFn *x86_dynarec_opcodes_dd_a32;
|
||||
extern const OpFn *x86_dynarec_opcodes_de_a16;
|
||||
extern const OpFn *x86_dynarec_opcodes_de_a32;
|
||||
extern const OpFn *x86_dynarec_opcodes_df_a16;
|
||||
extern const OpFn *x86_dynarec_opcodes_df_a32;
|
||||
extern const OpFn *x86_dynarec_opcodes_REPE;
|
||||
extern const OpFn *x86_dynarec_opcodes_REPNE;
|
||||
#ifdef USE_NEW_DYNAREC
|
||||
extern const OpFn *x86_dynarec_opcodes_3DNOW;
|
||||
#endif
|
||||
|
||||
extern const OpFn dynarec_ops_286[1024];
|
||||
extern const OpFn dynarec_ops_286_0f[1024];
|
||||
|
||||
extern const OpFn dynarec_ops_386[1024];
|
||||
extern const OpFn dynarec_ops_386_0f[1024];
|
||||
|
||||
extern const OpFn dynarec_ops_486_0f[1024];
|
||||
|
||||
extern const OpFn dynarec_ops_winchip_0f[1024];
|
||||
#ifdef USE_NEW_DYNAREC
|
||||
extern const OpFn dynarec_ops_winchip2_0f[1024];
|
||||
#endif
|
||||
|
||||
extern const OpFn dynarec_ops_pentium_0f[1024];
|
||||
extern const OpFn dynarec_ops_pentiummmx_0f[1024];
|
||||
|
||||
#if defined(USE_NEW_DYNAREC) || (defined(DEV_BRANCH) && defined(USE_CYRIX_6X86))
|
||||
extern const OpFn dynarec_ops_c6x86mx_0f[1024];
|
||||
#endif
|
||||
|
||||
#ifdef USE_NEW_DYNAREC
|
||||
extern const OpFn dynarec_ops_k6_0f[1024];
|
||||
extern const OpFn dynarec_ops_k62_0f[1024];
|
||||
#endif
|
||||
|
||||
#if defined(DEV_BRANCH) && defined(USE_I686)
|
||||
extern const OpFn dynarec_ops_pentiumpro_0f[1024];
|
||||
extern const OpFn dynarec_ops_pentium2_0f[1024];
|
||||
extern const OpFn dynarec_ops_pentium2d_0f[1024];
|
||||
#endif
|
||||
|
||||
extern const OpFn dynarec_ops_fpu_287_d9_a16[256];
|
||||
extern const OpFn dynarec_ops_fpu_287_d9_a32[256];
|
||||
extern const OpFn dynarec_ops_fpu_287_da_a16[256];
|
||||
extern const OpFn dynarec_ops_fpu_287_da_a32[256];
|
||||
extern const OpFn dynarec_ops_fpu_287_db_a16[256];
|
||||
extern const OpFn dynarec_ops_fpu_287_db_a32[256];
|
||||
extern const OpFn dynarec_ops_fpu_287_dc_a16[32];
|
||||
extern const OpFn dynarec_ops_fpu_287_dc_a32[32];
|
||||
extern const OpFn dynarec_ops_fpu_287_dd_a16[256];
|
||||
extern const OpFn dynarec_ops_fpu_287_dd_a32[256];
|
||||
extern const OpFn dynarec_ops_fpu_287_de_a16[256];
|
||||
extern const OpFn dynarec_ops_fpu_287_de_a32[256];
|
||||
extern const OpFn dynarec_ops_fpu_287_df_a16[256];
|
||||
extern const OpFn dynarec_ops_fpu_287_df_a32[256];
|
||||
|
||||
extern const OpFn dynarec_ops_fpu_d8_a16[32];
|
||||
extern const OpFn dynarec_ops_fpu_d8_a32[32];
|
||||
extern const OpFn dynarec_ops_fpu_d9_a16[256];
|
||||
extern const OpFn dynarec_ops_fpu_d9_a32[256];
|
||||
extern const OpFn dynarec_ops_fpu_da_a16[256];
|
||||
extern const OpFn dynarec_ops_fpu_da_a32[256];
|
||||
extern const OpFn dynarec_ops_fpu_db_a16[256];
|
||||
extern const OpFn dynarec_ops_fpu_db_a32[256];
|
||||
extern const OpFn dynarec_ops_fpu_dc_a16[32];
|
||||
extern const OpFn dynarec_ops_fpu_dc_a32[32];
|
||||
extern const OpFn dynarec_ops_fpu_dd_a16[256];
|
||||
extern const OpFn dynarec_ops_fpu_dd_a32[256];
|
||||
extern const OpFn dynarec_ops_fpu_de_a16[256];
|
||||
extern const OpFn dynarec_ops_fpu_de_a32[256];
|
||||
extern const OpFn dynarec_ops_fpu_df_a16[256];
|
||||
extern const OpFn dynarec_ops_fpu_df_a32[256];
|
||||
extern const OpFn dynarec_ops_nofpu_a16[256];
|
||||
extern const OpFn dynarec_ops_nofpu_a32[256];
|
||||
|
||||
extern const OpFn dynarec_ops_fpu_686_da_a16[256];
|
||||
extern const OpFn dynarec_ops_fpu_686_da_a32[256];
|
||||
extern const OpFn dynarec_ops_fpu_686_db_a16[256];
|
||||
extern const OpFn dynarec_ops_fpu_686_db_a32[256];
|
||||
extern const OpFn dynarec_ops_fpu_686_df_a16[256];
|
||||
extern const OpFn dynarec_ops_fpu_686_df_a32[256];
|
||||
|
||||
extern const OpFn dynarec_ops_REPE[1024];
|
||||
extern const OpFn dynarec_ops_REPNE[1024];
|
||||
#ifdef USE_NEW_DYNAREC
|
||||
extern const OpFn dynarec_ops_3DNOW[256];
|
||||
#endif
|
||||
#else
|
||||
void x86_setopcodes(const OpFn *opcodes, const OpFn *opcodes_0f);
|
||||
#endif
|
||||
|
||||
extern const OpFn *x86_opcodes;
|
||||
extern const OpFn *x86_opcodes_0f;
|
||||
extern const OpFn *x86_opcodes_d8_a16;
|
||||
extern const OpFn *x86_opcodes_d8_a32;
|
||||
extern const OpFn *x86_opcodes_d9_a16;
|
||||
extern const OpFn *x86_opcodes_d9_a32;
|
||||
extern const OpFn *x86_opcodes_da_a16;
|
||||
extern const OpFn *x86_opcodes_da_a32;
|
||||
extern const OpFn *x86_opcodes_db_a16;
|
||||
extern const OpFn *x86_opcodes_db_a32;
|
||||
extern const OpFn *x86_opcodes_dc_a16;
|
||||
extern const OpFn *x86_opcodes_dc_a32;
|
||||
extern const OpFn *x86_opcodes_dd_a16;
|
||||
extern const OpFn *x86_opcodes_dd_a32;
|
||||
extern const OpFn *x86_opcodes_de_a16;
|
||||
extern const OpFn *x86_opcodes_de_a32;
|
||||
extern const OpFn *x86_opcodes_df_a16;
|
||||
extern const OpFn *x86_opcodes_df_a32;
|
||||
extern const OpFn *x86_opcodes_REPE;
|
||||
extern const OpFn *x86_opcodes_REPNE;
|
||||
#ifdef USE_NEW_DYNAREC
|
||||
extern const OpFn *x86_opcodes_3DNOW;
|
||||
#endif
|
||||
|
||||
extern const OpFn ops_286[1024];
|
||||
extern const OpFn ops_286_0f[1024];
|
||||
|
||||
extern const OpFn ops_386[1024];
|
||||
extern const OpFn ops_386_0f[1024];
|
||||
|
||||
extern const OpFn ops_486_0f[1024];
|
||||
|
||||
extern const OpFn ops_winchip_0f[1024];
|
||||
#ifdef USE_NEW_DYNAREC
|
||||
extern const OpFn ops_winchip2_0f[1024];
|
||||
#endif
|
||||
|
||||
extern const OpFn ops_pentium_0f[1024];
|
||||
extern const OpFn ops_pentiummmx_0f[1024];
|
||||
|
||||
#if defined(USE_NEW_DYNAREC) || (defined(DEV_BRANCH) && defined(USE_CYRIX_6X86))
|
||||
extern const OpFn ops_c6x86mx_0f[1024];
|
||||
#endif
|
||||
|
||||
#ifdef USE_NEW_DYNAREC
|
||||
extern const OpFn ops_k6_0f[1024];
|
||||
extern const OpFn ops_k62_0f[1024];
|
||||
#endif
|
||||
|
||||
#if defined(DEV_BRANCH) && defined(USE_I686)
|
||||
extern const OpFn ops_pentiumpro_0f[1024];
|
||||
extern const OpFn ops_pentium2_0f[1024];
|
||||
extern const OpFn ops_pentium2d_0f[1024];
|
||||
#endif
|
||||
|
||||
extern const OpFn ops_fpu_287_d9_a16[256];
|
||||
extern const OpFn ops_fpu_287_d9_a32[256];
|
||||
extern const OpFn ops_fpu_287_da_a16[256];
|
||||
extern const OpFn ops_fpu_287_da_a32[256];
|
||||
extern const OpFn ops_fpu_287_db_a16[256];
|
||||
extern const OpFn ops_fpu_287_db_a32[256];
|
||||
extern const OpFn ops_fpu_287_dc_a16[32];
|
||||
extern const OpFn ops_fpu_287_dc_a32[32];
|
||||
extern const OpFn ops_fpu_287_dd_a16[256];
|
||||
extern const OpFn ops_fpu_287_dd_a32[256];
|
||||
extern const OpFn ops_fpu_287_de_a16[256];
|
||||
extern const OpFn ops_fpu_287_de_a32[256];
|
||||
extern const OpFn ops_fpu_287_df_a16[256];
|
||||
extern const OpFn ops_fpu_287_df_a32[256];
|
||||
|
||||
extern const OpFn ops_fpu_d8_a16[32];
|
||||
extern const OpFn ops_fpu_d8_a32[32];
|
||||
extern const OpFn ops_fpu_d9_a16[256];
|
||||
extern const OpFn ops_fpu_d9_a32[256];
|
||||
extern const OpFn ops_fpu_da_a16[256];
|
||||
extern const OpFn ops_fpu_da_a32[256];
|
||||
extern const OpFn ops_fpu_db_a16[256];
|
||||
extern const OpFn ops_fpu_db_a32[256];
|
||||
extern const OpFn ops_fpu_dc_a16[32];
|
||||
extern const OpFn ops_fpu_dc_a32[32];
|
||||
extern const OpFn ops_fpu_dd_a16[256];
|
||||
extern const OpFn ops_fpu_dd_a32[256];
|
||||
extern const OpFn ops_fpu_de_a16[256];
|
||||
extern const OpFn ops_fpu_de_a32[256];
|
||||
extern const OpFn ops_fpu_df_a16[256];
|
||||
extern const OpFn ops_fpu_df_a32[256];
|
||||
extern const OpFn ops_nofpu_a16[256];
|
||||
extern const OpFn ops_nofpu_a32[256];
|
||||
|
||||
extern const OpFn ops_fpu_686_da_a16[256];
|
||||
extern const OpFn ops_fpu_686_da_a32[256];
|
||||
extern const OpFn ops_fpu_686_db_a16[256];
|
||||
extern const OpFn ops_fpu_686_db_a32[256];
|
||||
extern const OpFn ops_fpu_686_df_a16[256];
|
||||
extern const OpFn ops_fpu_686_df_a32[256];
|
||||
|
||||
extern const OpFn ops_REPE[1024];
|
||||
extern const OpFn ops_REPNE[1024];
|
||||
#ifdef USE_NEW_DYNAREC
|
||||
extern const OpFn ops_3DNOW[256];
|
||||
#endif
|
||||
|
||||
#define C0 (1<<8)
|
||||
#define C1 (1<<9)
|
||||
#define C2 (1<<10)
|
||||
#define C3 (1<<14)
|
||||
|
||||
#endif /*_X86_OPS_H*/
|
||||
346
src/cpu_common/x86_ops_3dnow.h
Normal file
346
src/cpu_common/x86_ops_3dnow.h
Normal file
@@ -0,0 +1,346 @@
|
||||
#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();
|
||||
UN_USED(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;
|
||||
}
|
||||
|
||||
const 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);
|
||||
}
|
||||
192
src/cpu_common/x86_ops_amd.h
Normal file
192
src/cpu_common/x86_ops_amd.h
Normal file
@@ -0,0 +1,192 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* AMD SYSCALL and SYSRET CPU Instructions.
|
||||
*
|
||||
* Version: @(#)x86_ops_amd.h 1.0.4 2018/10/17
|
||||
*
|
||||
* Author: Miran Grca, <mgrca8@gmail.com>
|
||||
* Copyright 2016-2018 Miran Grca.
|
||||
*/
|
||||
|
||||
/* 0 = Limit 0-15
|
||||
1 = Base 0-15
|
||||
2 = Base 16-23 (bits 0-7), Access rights
|
||||
8-11 Type
|
||||
12 S
|
||||
13, 14 DPL
|
||||
15 P
|
||||
3 = Limit 16-19 (bits 0-3), Base 24-31 (bits 8-15), granularity, etc.
|
||||
4 A
|
||||
6 DB
|
||||
7 G */
|
||||
|
||||
#define AMD_SYSCALL_EIP (star & 0xFFFFFFFF)
|
||||
#define AMD_SYSCALL_SB ((star >> 32) & 0xFFFF)
|
||||
#define AMD_SYSRET_SB ((star >> 48) & 0xFFFF)
|
||||
|
||||
/* 0F 05 */
|
||||
static int opSYSCALL(uint32_t fetchdat)
|
||||
{
|
||||
uint16_t syscall_cs_seg_data[4] = {0, 0, 0, 0};
|
||||
uint16_t syscall_ss_seg_data[4] = {0, 0, 0, 0};
|
||||
|
||||
if (!(cr0 & 1)) return internal_illegal("SYSCALL: CPU not in protected mode");
|
||||
if (!AMD_SYSCALL_SB) return internal_illegal("SYSCALL: AMD SYSCALL SB MSR is zero");
|
||||
|
||||
/* Set VM, IF, RF to 0. */
|
||||
/* cpu_state.eflags &= ~0x00030200;
|
||||
cpu_state.flags &= ~0x0200; */
|
||||
|
||||
/* Let's do this by the AMD spec. */
|
||||
ECX = cpu_state.pc;
|
||||
|
||||
cpu_state.eflags &= ~0x0002;
|
||||
cpu_state.flags &= ~0x0200;
|
||||
|
||||
/* CS */
|
||||
cpu_state.seg_cs.seg = AMD_SYSCALL_SB & ~7;
|
||||
if (AMD_SYSCALL_SB & 4)
|
||||
{
|
||||
if (cpu_state.seg_cs.seg >= ldt.limit)
|
||||
{
|
||||
x386_dynarec_log("Bigger than LDT limit %04X %04X CS\n",AMD_SYSCALL_SB,ldt.limit);
|
||||
x86gpf(NULL, AMD_SYSCALL_SB & ~3);
|
||||
return 1;
|
||||
}
|
||||
cpu_state.seg_cs.seg +=ldt.base;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cpu_state.seg_cs.seg >= gdt.limit)
|
||||
{
|
||||
x386_dynarec_log("Bigger than GDT limit %04X %04X CS\n",AMD_SYSCALL_SB,gdt.limit);
|
||||
x86gpf(NULL, AMD_SYSCALL_SB & ~3);
|
||||
return 1;
|
||||
}
|
||||
cpu_state.seg_cs.seg += gdt.base;
|
||||
}
|
||||
cpl_override = 1;
|
||||
|
||||
syscall_cs_seg_data[0] = 0xFFFF;
|
||||
syscall_cs_seg_data[1] = 0;
|
||||
syscall_cs_seg_data[2] = 0x9B00;
|
||||
syscall_cs_seg_data[3] = 0xC0;
|
||||
|
||||
cpl_override = 0;
|
||||
|
||||
use32 = 0x300;
|
||||
CS = (AMD_SYSCALL_SB & ~3) | 0;
|
||||
|
||||
do_seg_load(&cpu_state.seg_cs, syscall_cs_seg_data);
|
||||
use32 = 0x300;
|
||||
|
||||
CS = (CS & 0xFFFC) | 0;
|
||||
|
||||
cpu_state.seg_cs.limit = 0xFFFFFFFF;
|
||||
cpu_state.seg_cs.limit_high = 0xFFFFFFFF;
|
||||
|
||||
/* SS */
|
||||
syscall_ss_seg_data[0] = 0xFFFF;
|
||||
syscall_ss_seg_data[1] = 0;
|
||||
syscall_ss_seg_data[2] = 0x9300;
|
||||
syscall_ss_seg_data[3] = 0xC0;
|
||||
do_seg_load(&cpu_state.seg_ss, syscall_ss_seg_data);
|
||||
cpu_state.seg_ss.seg = (AMD_SYSCALL_SB + 8) & 0xFFFC;
|
||||
stack32 = 1;
|
||||
|
||||
cpu_state.seg_ss.limit = 0xFFFFFFFF;
|
||||
cpu_state.seg_ss.limit_high = 0xFFFFFFFF;
|
||||
|
||||
cpu_state.seg_ss.checked = 0;
|
||||
|
||||
cpu_state.pc = AMD_SYSCALL_EIP;
|
||||
|
||||
CLOCK_CYCLES(20);
|
||||
|
||||
CPU_BLOCK_END();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 0F 07 */
|
||||
static int opSYSRET(uint32_t fetchdat)
|
||||
{
|
||||
uint16_t sysret_cs_seg_data[4] = {0, 0, 0, 0};
|
||||
uint16_t sysret_ss_seg_data[4] = {0, 0, 0, 0};
|
||||
|
||||
if (!AMD_SYSRET_SB) return internal_illegal("SYSRET: CS MSR is zero");
|
||||
if (!(cr0 & 1)) return internal_illegal("SYSRET: CPU not in protected mode");
|
||||
|
||||
cpu_state.pc = ECX;
|
||||
|
||||
cpu_state.eflags |= (1 << 1);
|
||||
|
||||
/* CS */
|
||||
cpu_state.seg_cs.seg = AMD_SYSRET_SB & ~7;
|
||||
if (AMD_SYSRET_SB & 4)
|
||||
{
|
||||
if (cpu_state.seg_cs.seg >= ldt.limit)
|
||||
{
|
||||
x386_dynarec_log("Bigger than LDT limit %04X %04X CS\n",AMD_SYSRET_SB,ldt.limit);
|
||||
x86gpf(NULL, AMD_SYSRET_SB & ~3);
|
||||
return 1;
|
||||
}
|
||||
cpu_state.seg_cs.seg +=ldt.base;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cpu_state.seg_cs.seg >= gdt.limit)
|
||||
{
|
||||
x386_dynarec_log("Bigger than GDT limit %04X %04X CS\n",AMD_SYSRET_SB,gdt.limit);
|
||||
x86gpf(NULL, AMD_SYSRET_SB & ~3);
|
||||
return 1;
|
||||
}
|
||||
cpu_state.seg_cs.seg += gdt.base;
|
||||
}
|
||||
cpl_override = 1;
|
||||
|
||||
sysret_cs_seg_data[0] = 0xFFFF;
|
||||
sysret_cs_seg_data[1] = 0;
|
||||
sysret_cs_seg_data[2] = 0xFB00;
|
||||
sysret_cs_seg_data[3] = 0xC0;
|
||||
|
||||
cpl_override = 0;
|
||||
|
||||
use32 = 0x300;
|
||||
CS = (AMD_SYSRET_SB & ~3) | 3;
|
||||
|
||||
do_seg_load(&cpu_state.seg_cs, sysret_cs_seg_data);
|
||||
flushmmucache_cr3();
|
||||
use32 = 0x300;
|
||||
|
||||
CS = (CS & 0xFFFC) | 3;
|
||||
|
||||
cpu_state.seg_cs.limit = 0xFFFFFFFF;
|
||||
cpu_state.seg_cs.limit_high = 0xFFFFFFFF;
|
||||
|
||||
/* SS */
|
||||
sysret_ss_seg_data[0] = 0xFFFF;
|
||||
sysret_ss_seg_data[1] = 0;
|
||||
sysret_ss_seg_data[2] = 0xF300;
|
||||
sysret_ss_seg_data[3] = 0xC0;
|
||||
do_seg_load(&cpu_state.seg_ss, sysret_ss_seg_data);
|
||||
cpu_state.seg_ss.seg = ((AMD_SYSRET_SB + 8) & 0xFFFC) | 3;
|
||||
stack32 = 1;
|
||||
|
||||
cpu_state.seg_ss.limit = 0xFFFFFFFF;
|
||||
cpu_state.seg_ss.limit_high = 0xFFFFFFFF;
|
||||
|
||||
cpu_state.seg_ss.checked = 0;
|
||||
|
||||
CLOCK_CYCLES(20);
|
||||
|
||||
CPU_BLOCK_END();
|
||||
|
||||
return 0;
|
||||
}
|
||||
818
src/cpu_common/x86_ops_arith.h
Normal file
818
src/cpu_common/x86_ops_arith.h
Normal file
@@ -0,0 +1,818 @@
|
||||
#define OP_ARITH(name, operation, setflags, flagops, gettempc) \
|
||||
static int op ## name ## _b_rmw_a16(uint32_t fetchdat) \
|
||||
{ \
|
||||
uint8_t dst; \
|
||||
uint8_t src; \
|
||||
if (gettempc) tempc = CF_SET() ? 1 : 0; \
|
||||
fetch_ea_16(fetchdat); \
|
||||
if (cpu_mod == 3) \
|
||||
{ \
|
||||
dst = getr8(cpu_rm); \
|
||||
src = getr8(cpu_reg); \
|
||||
setflags ## 8 flagops; \
|
||||
setr8(cpu_rm, operation); \
|
||||
CLOCK_CYCLES(timing_rr); \
|
||||
PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 0); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
SEG_CHECK_WRITE(cpu_state.ea_seg); \
|
||||
dst = geteab(); if (cpu_state.abrt) return 1; \
|
||||
src = getr8(cpu_reg); \
|
||||
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); \
|
||||
} \
|
||||
return 0; \
|
||||
} \
|
||||
static int op ## name ## _b_rmw_a32(uint32_t fetchdat) \
|
||||
{ \
|
||||
uint8_t dst; \
|
||||
uint8_t src; \
|
||||
if (gettempc) tempc = CF_SET() ? 1 : 0; \
|
||||
fetch_ea_32(fetchdat); \
|
||||
if (cpu_mod == 3) \
|
||||
{ \
|
||||
dst = getr8(cpu_rm); \
|
||||
src = getr8(cpu_reg); \
|
||||
setflags ## 8 flagops; \
|
||||
setr8(cpu_rm, operation); \
|
||||
CLOCK_CYCLES(timing_rr); \
|
||||
PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 1); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
SEG_CHECK_WRITE(cpu_state.ea_seg); \
|
||||
dst = geteab(); if (cpu_state.abrt) return 1; \
|
||||
src = getr8(cpu_reg); \
|
||||
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, 1); \
|
||||
} \
|
||||
return 0; \
|
||||
} \
|
||||
\
|
||||
static int op ## name ## _w_rmw_a16(uint32_t fetchdat) \
|
||||
{ \
|
||||
uint16_t dst; \
|
||||
uint16_t src; \
|
||||
if (gettempc) tempc = CF_SET() ? 1 : 0; \
|
||||
fetch_ea_16(fetchdat); \
|
||||
if (cpu_mod == 3) \
|
||||
{ \
|
||||
dst = cpu_state.regs[cpu_rm].w; \
|
||||
src = cpu_state.regs[cpu_reg].w; \
|
||||
setflags ## 16 flagops; \
|
||||
cpu_state.regs[cpu_rm].w = operation; \
|
||||
CLOCK_CYCLES(timing_rr); \
|
||||
PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 0); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
SEG_CHECK_WRITE(cpu_state.ea_seg); \
|
||||
dst = geteaw(); if (cpu_state.abrt) return 1; \
|
||||
src = cpu_state.regs[cpu_reg].w; \
|
||||
seteaw(operation); if (cpu_state.abrt) return 1; \
|
||||
setflags ## 16 flagops; \
|
||||
CLOCK_CYCLES(timing_mr); \
|
||||
PREFETCH_RUN(timing_rr, 2, rmdat, 1,0,1,0, 0); \
|
||||
} \
|
||||
return 0; \
|
||||
} \
|
||||
static int op ## name ## _w_rmw_a32(uint32_t fetchdat) \
|
||||
{ \
|
||||
uint16_t dst; \
|
||||
uint16_t src; \
|
||||
if (gettempc) tempc = CF_SET() ? 1 : 0; \
|
||||
fetch_ea_32(fetchdat); \
|
||||
if (cpu_mod == 3) \
|
||||
{ \
|
||||
dst = cpu_state.regs[cpu_rm].w; \
|
||||
src = cpu_state.regs[cpu_reg].w; \
|
||||
setflags ## 16 flagops; \
|
||||
cpu_state.regs[cpu_rm].w = operation; \
|
||||
CLOCK_CYCLES(timing_rr); \
|
||||
PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 1); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
SEG_CHECK_WRITE(cpu_state.ea_seg); \
|
||||
dst = geteaw(); if (cpu_state.abrt) return 1; \
|
||||
src = cpu_state.regs[cpu_reg].w; \
|
||||
seteaw(operation); if (cpu_state.abrt) return 1; \
|
||||
setflags ## 16 flagops; \
|
||||
CLOCK_CYCLES(timing_mr); \
|
||||
PREFETCH_RUN(timing_rr, 2, rmdat, 1,0,1,0, 1); \
|
||||
} \
|
||||
return 0; \
|
||||
} \
|
||||
\
|
||||
static int op ## name ## _l_rmw_a16(uint32_t fetchdat) \
|
||||
{ \
|
||||
uint32_t dst; \
|
||||
uint32_t src; \
|
||||
if (gettempc) tempc = CF_SET() ? 1 : 0; \
|
||||
fetch_ea_16(fetchdat); \
|
||||
if (cpu_mod == 3) \
|
||||
{ \
|
||||
dst = cpu_state.regs[cpu_rm].l; \
|
||||
src = cpu_state.regs[cpu_reg].l; \
|
||||
setflags ## 32 flagops; \
|
||||
cpu_state.regs[cpu_rm].l = operation; \
|
||||
CLOCK_CYCLES(timing_rr); \
|
||||
PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 0); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
SEG_CHECK_WRITE(cpu_state.ea_seg); \
|
||||
dst = geteal(); if (cpu_state.abrt) return 1; \
|
||||
src = cpu_state.regs[cpu_reg].l; \
|
||||
seteal(operation); if (cpu_state.abrt) return 1; \
|
||||
setflags ## 32 flagops; \
|
||||
CLOCK_CYCLES(timing_mr); \
|
||||
PREFETCH_RUN(timing_rr, 2, rmdat, 0,1,0,1, 0); \
|
||||
} \
|
||||
return 0; \
|
||||
} \
|
||||
static int op ## name ## _l_rmw_a32(uint32_t fetchdat) \
|
||||
{ \
|
||||
uint32_t dst; \
|
||||
uint32_t src; \
|
||||
if (gettempc) tempc = CF_SET() ? 1 : 0; \
|
||||
fetch_ea_32(fetchdat); \
|
||||
if (cpu_mod == 3) \
|
||||
{ \
|
||||
dst = cpu_state.regs[cpu_rm].l; \
|
||||
src = cpu_state.regs[cpu_reg].l; \
|
||||
setflags ## 32 flagops; \
|
||||
cpu_state.regs[cpu_rm].l = operation; \
|
||||
CLOCK_CYCLES(timing_rr); \
|
||||
PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 1); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
SEG_CHECK_WRITE(cpu_state.ea_seg); \
|
||||
dst = geteal(); if (cpu_state.abrt) return 1; \
|
||||
src = cpu_state.regs[cpu_reg].l; \
|
||||
seteal(operation); if (cpu_state.abrt) return 1; \
|
||||
setflags ## 32 flagops; \
|
||||
CLOCK_CYCLES(timing_mr); \
|
||||
PREFETCH_RUN(timing_rr, 2, rmdat, 0,1,0,1, 1); \
|
||||
} \
|
||||
return 0; \
|
||||
} \
|
||||
\
|
||||
static int op ## name ## _b_rm_a16(uint32_t fetchdat) \
|
||||
{ \
|
||||
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; \
|
||||
setr8(cpu_reg, operation); \
|
||||
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); \
|
||||
return 0; \
|
||||
} \
|
||||
static int op ## name ## _b_rm_a32(uint32_t fetchdat) \
|
||||
{ \
|
||||
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; \
|
||||
setr8(cpu_reg, operation); \
|
||||
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); \
|
||||
return 0; \
|
||||
} \
|
||||
\
|
||||
static int op ## name ## _w_rm_a16(uint32_t fetchdat) \
|
||||
{ \
|
||||
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; \
|
||||
cpu_state.regs[cpu_reg].w = operation; \
|
||||
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); \
|
||||
return 0; \
|
||||
} \
|
||||
static int op ## name ## _w_rm_a32(uint32_t fetchdat) \
|
||||
{ \
|
||||
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; \
|
||||
cpu_state.regs[cpu_reg].w = operation; \
|
||||
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); \
|
||||
return 0; \
|
||||
} \
|
||||
\
|
||||
static int op ## name ## _l_rm_a16(uint32_t fetchdat) \
|
||||
{ \
|
||||
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; \
|
||||
cpu_state.regs[cpu_reg].l = operation; \
|
||||
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); \
|
||||
return 0; \
|
||||
} \
|
||||
static int op ## name ## _l_rm_a32(uint32_t fetchdat) \
|
||||
{ \
|
||||
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; \
|
||||
cpu_state.regs[cpu_reg].l = operation; \
|
||||
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); \
|
||||
return 0; \
|
||||
} \
|
||||
\
|
||||
static int op ## name ## _AL_imm(uint32_t fetchdat) \
|
||||
{ \
|
||||
uint8_t dst = AL; \
|
||||
uint8_t src = getbytef(); \
|
||||
if (gettempc) tempc = CF_SET() ? 1 : 0; \
|
||||
setflags ## 8 flagops; \
|
||||
AL = operation; \
|
||||
CLOCK_CYCLES(timing_rr); \
|
||||
PREFETCH_RUN(timing_rr, 2, -1, 0,0,0,0, 0); \
|
||||
return 0; \
|
||||
} \
|
||||
\
|
||||
static int op ## name ## _AX_imm(uint32_t fetchdat) \
|
||||
{ \
|
||||
uint16_t dst = AX; \
|
||||
uint16_t src = getwordf(); \
|
||||
if (gettempc) tempc = CF_SET() ? 1 : 0; \
|
||||
setflags ## 16 flagops; \
|
||||
AX = operation; \
|
||||
CLOCK_CYCLES(timing_rr); \
|
||||
PREFETCH_RUN(timing_rr, 3, -1, 0,0,0,0, 0); \
|
||||
return 0; \
|
||||
} \
|
||||
\
|
||||
static int op ## name ## _EAX_imm(uint32_t fetchdat) \
|
||||
{ \
|
||||
uint32_t dst = EAX; \
|
||||
uint32_t src = getlong(); if (cpu_state.abrt) return 1; \
|
||||
if (gettempc) tempc = CF_SET() ? 1 : 0; \
|
||||
setflags ## 32 flagops; \
|
||||
EAX = operation; \
|
||||
CLOCK_CYCLES(timing_rr); \
|
||||
PREFETCH_RUN(timing_rr, 5, -1, 0,0,0,0, 0); \
|
||||
return 0; \
|
||||
}
|
||||
|
||||
OP_ARITH(ADD, dst + src, setadd, (dst, src), 0)
|
||||
OP_ARITH(ADC, dst + src + tempc, setadc, (dst, src), 1)
|
||||
OP_ARITH(SUB, dst - src, setsub, (dst, src), 0)
|
||||
OP_ARITH(SBB, dst - (src + tempc), setsbc, (dst, src), 1)
|
||||
OP_ARITH(OR, dst | src, setznp, (dst | src), 0)
|
||||
OP_ARITH(AND, dst & src, setznp, (dst & src), 0)
|
||||
OP_ARITH(XOR, dst ^ src, setznp, (dst ^ src), 0)
|
||||
|
||||
static int opCMP_b_rmw_a16(uint32_t fetchdat)
|
||||
{
|
||||
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);
|
||||
else CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5);
|
||||
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opCMP_b_rmw_a32(uint32_t fetchdat)
|
||||
{
|
||||
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);
|
||||
else CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5);
|
||||
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opCMP_w_rmw_a16(uint32_t fetchdat)
|
||||
{
|
||||
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);
|
||||
else CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5);
|
||||
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opCMP_w_rmw_a32(uint32_t fetchdat)
|
||||
{
|
||||
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);
|
||||
else CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5);
|
||||
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opCMP_l_rmw_a16(uint32_t fetchdat)
|
||||
{
|
||||
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);
|
||||
else CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5);
|
||||
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opCMP_l_rmw_a32(uint32_t fetchdat)
|
||||
{
|
||||
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);
|
||||
else CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5);
|
||||
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, 0, (cpu_mod == 3) ? 0 : 1,0,0, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opCMP_b_rm_a16(uint32_t fetchdat)
|
||||
{
|
||||
uint8_t src;
|
||||
fetch_ea_16(fetchdat);
|
||||
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);
|
||||
return 0;
|
||||
}
|
||||
static int opCMP_b_rm_a32(uint32_t fetchdat)
|
||||
{
|
||||
uint8_t src;
|
||||
fetch_ea_32(fetchdat);
|
||||
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);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opCMP_w_rm_a16(uint32_t fetchdat)
|
||||
{
|
||||
uint16_t src;
|
||||
fetch_ea_16(fetchdat);
|
||||
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);
|
||||
return 0;
|
||||
}
|
||||
static int opCMP_w_rm_a32(uint32_t fetchdat)
|
||||
{
|
||||
uint16_t src;
|
||||
fetch_ea_32(fetchdat);
|
||||
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);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opCMP_l_rm_a16(uint32_t fetchdat)
|
||||
{
|
||||
uint32_t src;
|
||||
fetch_ea_16(fetchdat);
|
||||
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);
|
||||
return 0;
|
||||
}
|
||||
static int opCMP_l_rm_a32(uint32_t fetchdat)
|
||||
{
|
||||
uint32_t src;
|
||||
fetch_ea_32(fetchdat);
|
||||
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);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opCMP_AL_imm(uint32_t fetchdat)
|
||||
{
|
||||
uint8_t src = getbytef();
|
||||
setsub8(AL, src);
|
||||
CLOCK_CYCLES(timing_rr);
|
||||
PREFETCH_RUN(timing_rr, 2, -1, 0,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opCMP_AX_imm(uint32_t fetchdat)
|
||||
{
|
||||
uint16_t src = getwordf();
|
||||
setsub16(AX, src);
|
||||
CLOCK_CYCLES(timing_rr);
|
||||
PREFETCH_RUN(timing_rr, 3, -1, 0,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opCMP_EAX_imm(uint32_t fetchdat)
|
||||
{
|
||||
uint32_t src = getlong(); if (cpu_state.abrt) return 1;
|
||||
setsub32(EAX, src);
|
||||
CLOCK_CYCLES(timing_rr);
|
||||
PREFETCH_RUN(timing_rr, 5, -1, 0,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opTEST_b_a16(uint32_t fetchdat)
|
||||
{
|
||||
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);
|
||||
if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2);
|
||||
else CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5);
|
||||
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opTEST_b_a32(uint32_t fetchdat)
|
||||
{
|
||||
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);
|
||||
if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2);
|
||||
else CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5);
|
||||
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opTEST_w_a16(uint32_t fetchdat)
|
||||
{
|
||||
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);
|
||||
if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2);
|
||||
else CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5);
|
||||
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opTEST_w_a32(uint32_t fetchdat)
|
||||
{
|
||||
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);
|
||||
if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2);
|
||||
else CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5);
|
||||
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, (cpu_mod == 3) ? 0 : 1,0,0,0, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opTEST_l_a16(uint32_t fetchdat)
|
||||
{
|
||||
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);
|
||||
if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2);
|
||||
else CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5);
|
||||
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, 0,(cpu_mod == 3) ? 0 : 1,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opTEST_l_a32(uint32_t fetchdat)
|
||||
{
|
||||
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);
|
||||
if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2);
|
||||
else CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5);
|
||||
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 2, rmdat, 0,(cpu_mod == 3) ? 0 : 1,0,0, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opTEST_AL(uint32_t fetchdat)
|
||||
{
|
||||
uint8_t temp = getbytef();
|
||||
setznp8(AL & temp);
|
||||
CLOCK_CYCLES(timing_rr);
|
||||
PREFETCH_RUN(timing_rr, 2, -1, 0,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opTEST_AX(uint32_t fetchdat)
|
||||
{
|
||||
uint16_t temp = getwordf();
|
||||
setznp16(AX & temp);
|
||||
CLOCK_CYCLES(timing_rr);
|
||||
PREFETCH_RUN(timing_rr, 3, -1, 0,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opTEST_EAX(uint32_t fetchdat)
|
||||
{
|
||||
uint32_t temp = getlong(); if (cpu_state.abrt) return 1;
|
||||
setznp32(EAX & temp);
|
||||
CLOCK_CYCLES(timing_rr);
|
||||
PREFETCH_RUN(timing_rr, 5, -1, 0,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#define ARITH_MULTI(ea_width, flag_width) \
|
||||
dst = getea ## ea_width(); if (cpu_state.abrt) return 1; \
|
||||
switch (rmdat&0x38) \
|
||||
{ \
|
||||
case 0x00: /*ADD ea, #*/ \
|
||||
setea ## ea_width(dst + src); if (cpu_state.abrt) return 1; \
|
||||
setadd ## flag_width(dst, src); \
|
||||
CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mr); \
|
||||
break; \
|
||||
case 0x08: /*OR ea, #*/ \
|
||||
dst |= src; \
|
||||
setea ## ea_width(dst); if (cpu_state.abrt) return 1; \
|
||||
setznp ## flag_width(dst); \
|
||||
CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mr); \
|
||||
break; \
|
||||
case 0x10: /*ADC ea, #*/ \
|
||||
tempc = CF_SET() ? 1 : 0; \
|
||||
setea ## ea_width(dst + src + tempc); if (cpu_state.abrt) return 1; \
|
||||
setadc ## flag_width(dst, src); \
|
||||
CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mr); \
|
||||
break; \
|
||||
case 0x18: /*SBB ea, #*/ \
|
||||
tempc = CF_SET() ? 1 : 0; \
|
||||
setea ## ea_width(dst - (src + tempc)); if (cpu_state.abrt) return 1; \
|
||||
setsbc ## flag_width(dst, src); \
|
||||
CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mr); \
|
||||
break; \
|
||||
case 0x20: /*AND ea, #*/ \
|
||||
dst &= src; \
|
||||
setea ## ea_width(dst); if (cpu_state.abrt) return 1; \
|
||||
setznp ## flag_width(dst); \
|
||||
CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mr); \
|
||||
break; \
|
||||
case 0x28: /*SUB ea, #*/ \
|
||||
setea ## ea_width(dst - src); if (cpu_state.abrt) return 1; \
|
||||
setsub ## flag_width(dst, src); \
|
||||
CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mr); \
|
||||
break; \
|
||||
case 0x30: /*XOR ea, #*/ \
|
||||
dst ^= src; \
|
||||
setea ## ea_width(dst); if (cpu_state.abrt) return 1; \
|
||||
setznp ## flag_width(dst); \
|
||||
CLOCK_CYCLES((cpu_mod == 3) ? timing_rr : timing_mr); \
|
||||
break; \
|
||||
case 0x38: /*CMP ea, #*/ \
|
||||
setsub ## flag_width(dst, src); \
|
||||
if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2); \
|
||||
else CLOCK_CYCLES((cpu_mod == 3) ? 2 : 7); \
|
||||
break; \
|
||||
}
|
||||
|
||||
|
||||
static int op80_a16(uint32_t fetchdat)
|
||||
{
|
||||
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)
|
||||
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mr, 3, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0);
|
||||
else
|
||||
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 3, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int op80_a32(uint32_t fetchdat)
|
||||
{
|
||||
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)
|
||||
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mr, 3, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1);
|
||||
else
|
||||
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 3, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int op81_w_a16(uint32_t fetchdat)
|
||||
{
|
||||
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)
|
||||
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mr, 4, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0);
|
||||
else
|
||||
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 4, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int op81_w_a32(uint32_t fetchdat)
|
||||
{
|
||||
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)
|
||||
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mr, 4, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1);
|
||||
else
|
||||
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 4, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int op81_l_a16(uint32_t fetchdat)
|
||||
{
|
||||
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)
|
||||
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mr, 6, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 0);
|
||||
else
|
||||
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 6, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int op81_l_a32(uint32_t fetchdat)
|
||||
{
|
||||
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)
|
||||
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mr, 6, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 1);
|
||||
else
|
||||
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 6, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int op83_w_a16(uint32_t fetchdat)
|
||||
{
|
||||
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);
|
||||
if ((rmdat & 0x38) == 0x38)
|
||||
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mr, 3, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0);
|
||||
else
|
||||
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 3, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int op83_w_a32(uint32_t fetchdat)
|
||||
{
|
||||
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);
|
||||
if ((rmdat & 0x38) == 0x38)
|
||||
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mr, 3, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1);
|
||||
else
|
||||
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 3, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int op83_l_a16(uint32_t fetchdat)
|
||||
{
|
||||
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);
|
||||
if ((rmdat & 0x38) == 0x38)
|
||||
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mr, 3, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 0);
|
||||
else
|
||||
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 3, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int op83_l_a32(uint32_t fetchdat)
|
||||
{
|
||||
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);
|
||||
if ((rmdat & 0x38) == 0x38)
|
||||
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_mr, 3, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 1);
|
||||
else
|
||||
PREFETCH_RUN((cpu_mod == 3) ? timing_rr : timing_rm, 3, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
292
src/cpu_common/x86_ops_atomic.h
Normal file
292
src/cpu_common/x86_ops_atomic.h
Normal file
@@ -0,0 +1,292 @@
|
||||
static int opCMPXCHG_b_a16(uint32_t fetchdat)
|
||||
{
|
||||
uint8_t temp, temp2 = AL;
|
||||
if (!is486)
|
||||
{
|
||||
cpu_state.pc = cpu_state.oldpc;
|
||||
x86illegal();
|
||||
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;
|
||||
if (cpu_state.abrt) return 1;
|
||||
setsub8(temp2, temp);
|
||||
CLOCK_CYCLES((cpu_mod == 3) ? 6 : 10);
|
||||
return 0;
|
||||
}
|
||||
static int opCMPXCHG_b_a32(uint32_t fetchdat)
|
||||
{
|
||||
uint8_t temp, temp2 = AL;
|
||||
if (!is486)
|
||||
{
|
||||
cpu_state.pc = cpu_state.oldpc;
|
||||
x86illegal();
|
||||
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;
|
||||
if (cpu_state.abrt) return 1;
|
||||
setsub8(temp2, temp);
|
||||
CLOCK_CYCLES((cpu_mod == 3) ? 6 : 10);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opCMPXCHG_w_a16(uint32_t fetchdat)
|
||||
{
|
||||
uint16_t temp, temp2 = AX;
|
||||
if (!is486)
|
||||
{
|
||||
cpu_state.pc = cpu_state.oldpc;
|
||||
x86illegal();
|
||||
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;
|
||||
if (cpu_state.abrt) return 1;
|
||||
setsub16(temp2, temp);
|
||||
CLOCK_CYCLES((cpu_mod == 3) ? 6 : 10);
|
||||
return 0;
|
||||
}
|
||||
static int opCMPXCHG_w_a32(uint32_t fetchdat)
|
||||
{
|
||||
uint16_t temp, temp2 = AX;
|
||||
if (!is486)
|
||||
{
|
||||
cpu_state.pc = cpu_state.oldpc;
|
||||
x86illegal();
|
||||
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;
|
||||
if (cpu_state.abrt) return 1;
|
||||
setsub16(temp2, temp);
|
||||
CLOCK_CYCLES((cpu_mod == 3) ? 6 : 10);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opCMPXCHG_l_a16(uint32_t fetchdat)
|
||||
{
|
||||
uint32_t temp, temp2 = EAX;
|
||||
if (!is486)
|
||||
{
|
||||
cpu_state.pc = cpu_state.oldpc;
|
||||
x86illegal();
|
||||
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;
|
||||
if (cpu_state.abrt) return 1;
|
||||
setsub32(temp2, temp);
|
||||
CLOCK_CYCLES((cpu_mod == 3) ? 6 : 10);
|
||||
return 0;
|
||||
}
|
||||
static int opCMPXCHG_l_a32(uint32_t fetchdat)
|
||||
{
|
||||
uint32_t temp, temp2 = EAX;
|
||||
if (!is486)
|
||||
{
|
||||
cpu_state.pc = cpu_state.oldpc;
|
||||
x86illegal();
|
||||
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;
|
||||
if (cpu_state.abrt) return 1;
|
||||
setsub32(temp2, temp);
|
||||
CLOCK_CYCLES((cpu_mod == 3) ? 6 : 10);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opCMPXCHG8B_a16(uint32_t fetchdat)
|
||||
{
|
||||
uint32_t temp, temp_hi, temp2 = EAX, temp2_hi = EDX;
|
||||
if (!is486)
|
||||
{
|
||||
cpu_state.pc = cpu_state.oldpc;
|
||||
x86illegal();
|
||||
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)
|
||||
{
|
||||
seteal(EBX);
|
||||
writememl(easeg, cpu_state.eaaddr+4, ECX);
|
||||
}
|
||||
else
|
||||
{
|
||||
EAX = temp;
|
||||
EDX = temp_hi;
|
||||
}
|
||||
if (cpu_state.abrt) return 0;
|
||||
flags_rebuild();
|
||||
if (temp == temp2 && temp_hi == temp2_hi)
|
||||
cpu_state.flags |= Z_FLAG;
|
||||
else
|
||||
cpu_state.flags &= ~Z_FLAG;
|
||||
cycles -= (cpu_mod == 3) ? 6 : 10;
|
||||
return 0;
|
||||
}
|
||||
static int opCMPXCHG8B_a32(uint32_t fetchdat)
|
||||
{
|
||||
uint32_t temp, temp_hi, temp2 = EAX, temp2_hi = EDX;
|
||||
if (!is486)
|
||||
{
|
||||
cpu_state.pc = cpu_state.oldpc;
|
||||
x86illegal();
|
||||
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)
|
||||
{
|
||||
seteal(EBX);
|
||||
writememl(easeg, cpu_state.eaaddr+4, ECX);
|
||||
}
|
||||
else
|
||||
{
|
||||
EAX = temp;
|
||||
EDX = temp_hi;
|
||||
}
|
||||
if (cpu_state.abrt) return 0;
|
||||
flags_rebuild();
|
||||
if (temp == temp2 && temp_hi == temp2_hi)
|
||||
cpu_state.flags |= Z_FLAG;
|
||||
else
|
||||
cpu_state.flags &= ~Z_FLAG;
|
||||
cycles -= (cpu_mod == 3) ? 6 : 10;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opXADD_b_a16(uint32_t fetchdat)
|
||||
{
|
||||
uint8_t temp;
|
||||
if (!is486)
|
||||
{
|
||||
cpu_state.pc = cpu_state.oldpc;
|
||||
x86illegal();
|
||||
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));
|
||||
setr8(cpu_reg, temp);
|
||||
CLOCK_CYCLES((cpu_mod == 3) ? 3 : 4);
|
||||
return 0;
|
||||
}
|
||||
static int opXADD_b_a32(uint32_t fetchdat)
|
||||
{
|
||||
uint8_t temp;
|
||||
if (!is486)
|
||||
{
|
||||
cpu_state.pc = cpu_state.oldpc;
|
||||
x86illegal();
|
||||
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));
|
||||
setr8(cpu_reg, temp);
|
||||
CLOCK_CYCLES((cpu_mod == 3) ? 3 : 4);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opXADD_w_a16(uint32_t fetchdat)
|
||||
{
|
||||
uint16_t temp;
|
||||
if (!is486)
|
||||
{
|
||||
cpu_state.pc = cpu_state.oldpc;
|
||||
x86illegal();
|
||||
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);
|
||||
cpu_state.regs[cpu_reg].w = temp;
|
||||
CLOCK_CYCLES((cpu_mod == 3) ? 3 : 4);
|
||||
return 0;
|
||||
}
|
||||
static int opXADD_w_a32(uint32_t fetchdat)
|
||||
{
|
||||
uint16_t temp;
|
||||
if (!is486)
|
||||
{
|
||||
cpu_state.pc = cpu_state.oldpc;
|
||||
x86illegal();
|
||||
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);
|
||||
cpu_state.regs[cpu_reg].w = temp;
|
||||
CLOCK_CYCLES((cpu_mod == 3) ? 3 : 4);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opXADD_l_a16(uint32_t fetchdat)
|
||||
{
|
||||
uint32_t temp;
|
||||
if (!is486)
|
||||
{
|
||||
cpu_state.pc = cpu_state.oldpc;
|
||||
x86illegal();
|
||||
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);
|
||||
cpu_state.regs[cpu_reg].l = temp;
|
||||
CLOCK_CYCLES((cpu_mod == 3) ? 3 : 4);
|
||||
return 0;
|
||||
}
|
||||
static int opXADD_l_a32(uint32_t fetchdat)
|
||||
{
|
||||
uint32_t temp;
|
||||
if (!is486)
|
||||
{
|
||||
cpu_state.pc = cpu_state.oldpc;
|
||||
x86illegal();
|
||||
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);
|
||||
cpu_state.regs[cpu_reg].l = temp;
|
||||
CLOCK_CYCLES((cpu_mod == 3) ? 3 : 4);
|
||||
return 0;
|
||||
}
|
||||
113
src/cpu_common/x86_ops_bcd.h
Normal file
113
src/cpu_common/x86_ops_bcd.h
Normal file
@@ -0,0 +1,113 @@
|
||||
static int opAAA(uint32_t fetchdat)
|
||||
{
|
||||
flags_rebuild();
|
||||
if ((cpu_state.flags & A_FLAG) || ((AL & 0xF) > 9))
|
||||
{
|
||||
AL += 6;
|
||||
AH++;
|
||||
cpu_state.flags |= (A_FLAG | C_FLAG);
|
||||
}
|
||||
else
|
||||
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);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opAAD(uint32_t fetchdat)
|
||||
{
|
||||
int base = getbytef();
|
||||
if (cpu_manufacturer != MANU_INTEL) base = 10;
|
||||
AL = (AH * base) + AL;
|
||||
AH = 0;
|
||||
setznp16(AX);
|
||||
CLOCK_CYCLES((is486) ? 14 : 19);
|
||||
PREFETCH_RUN(is486 ? 14 : 19, 2, -1, 0,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opAAM(uint32_t fetchdat)
|
||||
{
|
||||
int base = getbytef();
|
||||
if (!base || cpu_manufacturer != MANU_INTEL) base = 10;
|
||||
AH = AL / base;
|
||||
AL %= base;
|
||||
setznp16(AX);
|
||||
CLOCK_CYCLES((is486) ? 15 : 17);
|
||||
PREFETCH_RUN(is486 ? 15 : 17, 2, -1, 0,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opAAS(uint32_t fetchdat)
|
||||
{
|
||||
flags_rebuild();
|
||||
if ((cpu_state.flags & A_FLAG) || ((AL & 0xF) > 9))
|
||||
{
|
||||
AL -= 6;
|
||||
AH--;
|
||||
cpu_state.flags |= (A_FLAG | C_FLAG);
|
||||
}
|
||||
else
|
||||
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);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opDAA(uint32_t fetchdat)
|
||||
{
|
||||
uint16_t tempw;
|
||||
|
||||
flags_rebuild();
|
||||
if ((cpu_state.flags & A_FLAG) || ((AL & 0xf) > 9))
|
||||
{
|
||||
int tempi = ((uint16_t)AL) + 6;
|
||||
AL += 6;
|
||||
cpu_state.flags |= A_FLAG;
|
||||
if (tempi & 0x100) cpu_state.flags |= C_FLAG;
|
||||
}
|
||||
if ((cpu_state.flags & C_FLAG) || (AL > 0x9f))
|
||||
{
|
||||
AL += 0x60;
|
||||
cpu_state.flags |= C_FLAG;
|
||||
}
|
||||
|
||||
tempw = cpu_state.flags & (C_FLAG | A_FLAG);
|
||||
setznp8(AL);
|
||||
flags_rebuild();
|
||||
cpu_state.flags |= tempw;
|
||||
CLOCK_CYCLES(4);
|
||||
PREFETCH_RUN(4, 1, -1, 0,0,0,0, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opDAS(uint32_t fetchdat)
|
||||
{
|
||||
uint16_t tempw;
|
||||
|
||||
flags_rebuild();
|
||||
if ((cpu_state.flags & A_FLAG) || ((AL & 0xf) > 9))
|
||||
{
|
||||
int tempi = ((uint16_t)AL) - 6;
|
||||
AL -= 6;
|
||||
cpu_state.flags |= A_FLAG;
|
||||
if (tempi & 0x100) cpu_state.flags |= C_FLAG;
|
||||
}
|
||||
if ((cpu_state.flags & C_FLAG) || (AL > 0x9f))
|
||||
{
|
||||
AL -= 0x60;
|
||||
cpu_state.flags |= C_FLAG;
|
||||
}
|
||||
|
||||
tempw = cpu_state.flags & (C_FLAG | A_FLAG);
|
||||
setznp8(AL);
|
||||
flags_rebuild();
|
||||
cpu_state.flags |= tempw;
|
||||
CLOCK_CYCLES(4);
|
||||
PREFETCH_RUN(4, 1, -1, 0,0,0,0, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
328
src/cpu_common/x86_ops_bit.h
Normal file
328
src/cpu_common/x86_ops_bit.h
Normal file
@@ -0,0 +1,328 @@
|
||||
static int opBT_w_r_a16(uint32_t fetchdat)
|
||||
{
|
||||
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))) cpu_state.flags |= C_FLAG;
|
||||
else cpu_state.flags &= ~C_FLAG;
|
||||
|
||||
CLOCK_CYCLES(3);
|
||||
PREFETCH_RUN(3, 2, rmdat, 1,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opBT_w_r_a32(uint32_t fetchdat)
|
||||
{
|
||||
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))) cpu_state.flags |= C_FLAG;
|
||||
else cpu_state.flags &= ~C_FLAG;
|
||||
|
||||
CLOCK_CYCLES(3);
|
||||
PREFETCH_RUN(3, 2, rmdat, 1,0,0,0, 1);
|
||||
return 0;
|
||||
}
|
||||
static int opBT_l_r_a16(uint32_t fetchdat)
|
||||
{
|
||||
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))) cpu_state.flags |= C_FLAG;
|
||||
else cpu_state.flags &= ~C_FLAG;
|
||||
|
||||
CLOCK_CYCLES(3);
|
||||
PREFETCH_RUN(3, 2, rmdat, 0,1,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opBT_l_r_a32(uint32_t fetchdat)
|
||||
{
|
||||
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))) cpu_state.flags |= C_FLAG;
|
||||
else cpu_state.flags &= ~C_FLAG;
|
||||
|
||||
CLOCK_CYCLES(3);
|
||||
PREFETCH_RUN(3, 2, rmdat, 0,1,0,0, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define opBT(name, operation) \
|
||||
static int opBT ## name ## _w_r_a16(uint32_t fetchdat) \
|
||||
{ \
|
||||
int tempc; \
|
||||
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) cpu_state.flags |= C_FLAG; \
|
||||
else cpu_state.flags &= ~C_FLAG; \
|
||||
\
|
||||
CLOCK_CYCLES(6); \
|
||||
PREFETCH_RUN(6, 2, rmdat, 1,0,1,0, 0); \
|
||||
return 0; \
|
||||
} \
|
||||
static int opBT ## name ## _w_r_a32(uint32_t fetchdat) \
|
||||
{ \
|
||||
int tempc; \
|
||||
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) cpu_state.flags |= C_FLAG; \
|
||||
else cpu_state.flags &= ~C_FLAG; \
|
||||
\
|
||||
CLOCK_CYCLES(6); \
|
||||
PREFETCH_RUN(6, 2, rmdat, 1,0,1,0, 1); \
|
||||
return 0; \
|
||||
} \
|
||||
static int opBT ## name ## _l_r_a16(uint32_t fetchdat) \
|
||||
{ \
|
||||
int tempc; \
|
||||
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) cpu_state.flags |= C_FLAG; \
|
||||
else cpu_state.flags &= ~C_FLAG; \
|
||||
\
|
||||
CLOCK_CYCLES(6); \
|
||||
PREFETCH_RUN(6, 2, rmdat, 0,1,0,1, 0); \
|
||||
return 0; \
|
||||
} \
|
||||
static int opBT ## name ## _l_r_a32(uint32_t fetchdat) \
|
||||
{ \
|
||||
int tempc; \
|
||||
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) cpu_state.flags |= C_FLAG; \
|
||||
else cpu_state.flags &= ~C_FLAG; \
|
||||
\
|
||||
CLOCK_CYCLES(6); \
|
||||
PREFETCH_RUN(6, 2, rmdat, 0,1,0,1, 1); \
|
||||
return 0; \
|
||||
}
|
||||
|
||||
opBT(C, ^=)
|
||||
opBT(R, &=~)
|
||||
opBT(S, |=)
|
||||
|
||||
static int opBA_w_a16(uint32_t fetchdat)
|
||||
{
|
||||
int tempc, count;
|
||||
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);
|
||||
flags_rebuild();
|
||||
switch (rmdat & 0x38)
|
||||
{
|
||||
case 0x20: /*BT w,imm*/
|
||||
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;
|
||||
case 0x28: /*BTS w,imm*/
|
||||
temp |= (1 << count);
|
||||
break;
|
||||
case 0x30: /*BTR w,imm*/
|
||||
temp &= ~(1 << count);
|
||||
break;
|
||||
case 0x38: /*BTC w,imm*/
|
||||
temp ^= (1 << count);
|
||||
break;
|
||||
|
||||
default:
|
||||
cpu_state.pc = cpu_state.oldpc;
|
||||
x86illegal();
|
||||
break;
|
||||
}
|
||||
seteaw(temp); if (cpu_state.abrt) return 1;
|
||||
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;
|
||||
}
|
||||
static int opBA_w_a32(uint32_t fetchdat)
|
||||
{
|
||||
int tempc, count;
|
||||
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);
|
||||
flags_rebuild();
|
||||
switch (rmdat & 0x38)
|
||||
{
|
||||
case 0x20: /*BT w,imm*/
|
||||
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;
|
||||
case 0x28: /*BTS w,imm*/
|
||||
temp |= (1 << count);
|
||||
break;
|
||||
case 0x30: /*BTR w,imm*/
|
||||
temp &= ~(1 << count);
|
||||
break;
|
||||
case 0x38: /*BTC w,imm*/
|
||||
temp ^= (1 << count);
|
||||
break;
|
||||
|
||||
default:
|
||||
cpu_state.pc = cpu_state.oldpc;
|
||||
x86illegal();
|
||||
break;
|
||||
}
|
||||
seteaw(temp); if (cpu_state.abrt) return 1;
|
||||
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;
|
||||
}
|
||||
|
||||
static int opBA_l_a16(uint32_t fetchdat)
|
||||
{
|
||||
int tempc, count;
|
||||
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);
|
||||
flags_rebuild();
|
||||
switch (rmdat & 0x38)
|
||||
{
|
||||
case 0x20: /*BT w,imm*/
|
||||
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;
|
||||
case 0x28: /*BTS w,imm*/
|
||||
temp |= (1 << count);
|
||||
break;
|
||||
case 0x30: /*BTR w,imm*/
|
||||
temp &= ~(1 << count);
|
||||
break;
|
||||
case 0x38: /*BTC w,imm*/
|
||||
temp ^= (1 << count);
|
||||
break;
|
||||
|
||||
default:
|
||||
cpu_state.pc = cpu_state.oldpc;
|
||||
x86illegal();
|
||||
break;
|
||||
}
|
||||
seteal(temp); if (cpu_state.abrt) return 1;
|
||||
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;
|
||||
}
|
||||
static int opBA_l_a32(uint32_t fetchdat)
|
||||
{
|
||||
int tempc, count;
|
||||
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);
|
||||
flags_rebuild();
|
||||
switch (rmdat & 0x38)
|
||||
{
|
||||
case 0x20: /*BT w,imm*/
|
||||
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;
|
||||
case 0x28: /*BTS w,imm*/
|
||||
temp |= (1 << count);
|
||||
break;
|
||||
case 0x30: /*BTR w,imm*/
|
||||
temp &= ~(1 << count);
|
||||
break;
|
||||
case 0x38: /*BTC w,imm*/
|
||||
temp ^= (1 << count);
|
||||
break;
|
||||
|
||||
default:
|
||||
cpu_state.pc = cpu_state.oldpc;
|
||||
x86illegal();
|
||||
break;
|
||||
}
|
||||
seteal(temp); if (cpu_state.abrt) return 1;
|
||||
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;
|
||||
}
|
||||
159
src/cpu_common/x86_ops_bitscan.h
Normal file
159
src/cpu_common/x86_ops_bitscan.h
Normal file
@@ -0,0 +1,159 @@
|
||||
#define BS_common(start, end, dir, dest, time) \
|
||||
flags_rebuild(); \
|
||||
instr_cycles = 0; \
|
||||
if (temp) \
|
||||
{ \
|
||||
int c; \
|
||||
cpu_state.flags &= ~Z_FLAG; \
|
||||
for (c = start; c != end; c += dir) \
|
||||
{ \
|
||||
CLOCK_CYCLES(time); \
|
||||
instr_cycles += time; \
|
||||
if (temp & (1 << c)) \
|
||||
{ \
|
||||
dest = c; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
else \
|
||||
cpu_state.flags |= Z_FLAG;
|
||||
|
||||
static int opBSF_w_a16(uint32_t fetchdat)
|
||||
{
|
||||
uint16_t temp;
|
||||
int instr_cycles = 0;
|
||||
|
||||
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);
|
||||
|
||||
CLOCK_CYCLES((is486) ? 6 : 10);
|
||||
instr_cycles += ((is486) ? 6 : 10);
|
||||
PREFETCH_RUN(instr_cycles, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opBSF_w_a32(uint32_t fetchdat)
|
||||
{
|
||||
uint16_t temp;
|
||||
int instr_cycles = 0;
|
||||
|
||||
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);
|
||||
|
||||
CLOCK_CYCLES((is486) ? 6 : 10);
|
||||
instr_cycles += ((is486) ? 6 : 10);
|
||||
PREFETCH_RUN(instr_cycles, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1);
|
||||
return 0;
|
||||
}
|
||||
static int opBSF_l_a16(uint32_t fetchdat)
|
||||
{
|
||||
uint32_t temp;
|
||||
int instr_cycles = 0;
|
||||
|
||||
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);
|
||||
|
||||
CLOCK_CYCLES((is486) ? 6 : 10);
|
||||
instr_cycles += ((is486) ? 6 : 10);
|
||||
PREFETCH_RUN(instr_cycles, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opBSF_l_a32(uint32_t fetchdat)
|
||||
{
|
||||
uint32_t temp;
|
||||
int instr_cycles = 0;
|
||||
|
||||
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);
|
||||
|
||||
CLOCK_CYCLES((is486) ? 6 : 10);
|
||||
instr_cycles += ((is486) ? 6 : 10);
|
||||
PREFETCH_RUN(instr_cycles, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opBSR_w_a16(uint32_t fetchdat)
|
||||
{
|
||||
uint16_t temp;
|
||||
int instr_cycles = 0;
|
||||
|
||||
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);
|
||||
|
||||
CLOCK_CYCLES((is486) ? 6 : 10);
|
||||
instr_cycles += ((is486) ? 6 : 10);
|
||||
PREFETCH_RUN(instr_cycles, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opBSR_w_a32(uint32_t fetchdat)
|
||||
{
|
||||
uint16_t temp;
|
||||
int instr_cycles = 0;
|
||||
|
||||
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);
|
||||
|
||||
CLOCK_CYCLES((is486) ? 6 : 10);
|
||||
instr_cycles += ((is486) ? 6 : 10);
|
||||
PREFETCH_RUN(instr_cycles, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1);
|
||||
return 0;
|
||||
}
|
||||
static int opBSR_l_a16(uint32_t fetchdat)
|
||||
{
|
||||
uint32_t temp;
|
||||
int instr_cycles = 0;
|
||||
|
||||
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);
|
||||
|
||||
CLOCK_CYCLES((is486) ? 6 : 10);
|
||||
instr_cycles += ((is486) ? 6 : 10);
|
||||
PREFETCH_RUN(instr_cycles, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opBSR_l_a32(uint32_t fetchdat)
|
||||
{
|
||||
uint32_t temp;
|
||||
int instr_cycles = 0;
|
||||
|
||||
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);
|
||||
|
||||
CLOCK_CYCLES((is486) ? 6 : 10);
|
||||
instr_cycles += ((is486) ? 6 : 10);
|
||||
PREFETCH_RUN(instr_cycles, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
284
src/cpu_common/x86_ops_flag.h
Normal file
284
src/cpu_common/x86_ops_flag.h
Normal file
@@ -0,0 +1,284 @@
|
||||
static int opCMC(uint32_t fetchdat)
|
||||
{
|
||||
flags_rebuild();
|
||||
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();
|
||||
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)
|
||||
{
|
||||
cpu_state.flags &= ~D_FLAG;
|
||||
CLOCK_CYCLES(2);
|
||||
PREFETCH_RUN(2, 1, -1, 0,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opCLI(uint32_t fetchdat)
|
||||
{
|
||||
if (!IOPLp)
|
||||
{
|
||||
if ((!(cpu_state.eflags & VM_FLAG) && (cr4 & CR4_PVI)) ||
|
||||
((cpu_state.eflags & VM_FLAG) && (cr4 & CR4_VME)))
|
||||
{
|
||||
cpu_state.eflags &= ~VIF_FLAG;
|
||||
}
|
||||
else
|
||||
{
|
||||
x86gpf(NULL,0);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
cpu_state.flags &= ~I_FLAG;
|
||||
|
||||
CLOCK_CYCLES(3);
|
||||
PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opSTC(uint32_t fetchdat)
|
||||
{
|
||||
flags_rebuild();
|
||||
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)
|
||||
{
|
||||
cpu_state.flags |= D_FLAG;
|
||||
CLOCK_CYCLES(2);
|
||||
PREFETCH_RUN(2, 1, -1, 0,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opSTI(uint32_t fetchdat)
|
||||
{
|
||||
if (!IOPLp)
|
||||
{
|
||||
if ((!(cpu_state.eflags & VM_FLAG) && (cr4 & CR4_PVI)) ||
|
||||
((cpu_state.eflags & VM_FLAG) && (cr4 & CR4_VME)))
|
||||
{
|
||||
if (cpu_state.eflags & VIP_FLAG)
|
||||
{
|
||||
x86gpf(NULL,0);
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
cpu_state.eflags |= VIF_FLAG;
|
||||
}
|
||||
else
|
||||
{
|
||||
x86gpf(NULL,0);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
cpu_state.flags |= I_FLAG;
|
||||
|
||||
CPU_BLOCK_END();
|
||||
|
||||
CLOCK_CYCLES(2);
|
||||
PREFETCH_RUN(2, 1, -1, 0,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opSAHF(uint32_t fetchdat)
|
||||
{
|
||||
flags_rebuild();
|
||||
cpu_state.flags = (cpu_state.flags & 0xff00) | (AH & 0xd5) | 2;
|
||||
CLOCK_CYCLES(3);
|
||||
PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0);
|
||||
|
||||
#ifdef USE_NEW_DYNAREC
|
||||
codegen_flags_changed = 0;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int opLAHF(uint32_t fetchdat)
|
||||
{
|
||||
flags_rebuild();
|
||||
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 ((cpu_state.eflags & VM_FLAG) && (IOPL < 3))
|
||||
{
|
||||
if (cr4 & CR4_VME)
|
||||
{
|
||||
uint16_t temp;
|
||||
|
||||
flags_rebuild();
|
||||
temp = (cpu_state.flags & ~I_FLAG) | 0x3000;
|
||||
if (cpu_state.eflags & VIF_FLAG)
|
||||
temp |= I_FLAG;
|
||||
PUSH_W(temp);
|
||||
}
|
||||
else
|
||||
{
|
||||
x86gpf(NULL,0);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
flags_rebuild();
|
||||
PUSH_W(cpu_state.flags);
|
||||
}
|
||||
CLOCK_CYCLES(4);
|
||||
PREFETCH_RUN(4, 1, -1, 0,0,1,0, 0);
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
static int opPUSHFD(uint32_t fetchdat)
|
||||
{
|
||||
uint16_t tempw;
|
||||
if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3))
|
||||
{
|
||||
x86gpf(NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
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(cpu_state.flags | (tempw << 16));
|
||||
CLOCK_CYCLES(4);
|
||||
PREFETCH_RUN(4, 1, -1, 0,0,0,1, 0);
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
|
||||
static int opPOPF_286(uint32_t fetchdat)
|
||||
{
|
||||
uint16_t tempw;
|
||||
|
||||
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)) 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);
|
||||
PREFETCH_RUN(5, 1, -1, 1,0,0,0, 0);
|
||||
|
||||
#ifdef USE_NEW_DYNAREC
|
||||
codegen_flags_changed = 0;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int opPOPF(uint32_t fetchdat)
|
||||
{
|
||||
uint16_t tempw;
|
||||
|
||||
if ((cpu_state.eflags & VM_FLAG) && (IOPL < 3))
|
||||
{
|
||||
if (cr4 & CR4_VME)
|
||||
{
|
||||
uint32_t old_esp = ESP;
|
||||
|
||||
tempw = POP_W();
|
||||
if (cpu_state.abrt)
|
||||
{
|
||||
|
||||
ESP = old_esp;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((tempw & T_FLAG) || ((tempw & I_FLAG) && (cpu_state.eflags & VIP_FLAG)))
|
||||
{
|
||||
ESP = old_esp;
|
||||
x86gpf(NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
if (tempw & I_FLAG)
|
||||
cpu_state.eflags |= VIF_FLAG;
|
||||
else
|
||||
cpu_state.eflags &= ~VIF_FLAG;
|
||||
cpu_state.flags = (cpu_state.flags & 0x3200) | (tempw & 0x4dd5) | 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
x86gpf(NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
tempw = POP_W();
|
||||
if (cpu_state.abrt)
|
||||
return 1;
|
||||
|
||||
if (!(CPL) || !(msw & 1))
|
||||
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);
|
||||
PREFETCH_RUN(5, 1, -1, 1,0,0,0, 0);
|
||||
|
||||
#ifdef USE_NEW_DYNAREC
|
||||
codegen_flags_changed = 0;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int opPOPFD(uint32_t fetchdat)
|
||||
{
|
||||
uint32_t templ;
|
||||
|
||||
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)) 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 |= ((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();
|
||||
|
||||
CLOCK_CYCLES(5);
|
||||
PREFETCH_RUN(5, 1, -1, 0,1,0,0, 0);
|
||||
|
||||
#ifdef USE_NEW_DYNAREC
|
||||
codegen_flags_changed = 0;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
101
src/cpu_common/x86_ops_fpu.h
Normal file
101
src/cpu_common/x86_ops_fpu.h
Normal file
@@ -0,0 +1,101 @@
|
||||
/* Copyright holders: Sarah Walker
|
||||
see COPYING for more details
|
||||
*/
|
||||
static int opESCAPE_d8_a16(uint32_t fetchdat)
|
||||
{
|
||||
pclog("A16: D8 %02X\n", fetchdat & 0xff);
|
||||
return x86_opcodes_d8_a16[(fetchdat >> 3) & 0x1f](fetchdat);
|
||||
}
|
||||
static int opESCAPE_d8_a32(uint32_t fetchdat)
|
||||
{
|
||||
pclog("A32: D8 %02X\n", fetchdat & 0xff);
|
||||
return x86_opcodes_d8_a32[(fetchdat >> 3) & 0x1f](fetchdat);
|
||||
}
|
||||
|
||||
static int opESCAPE_d9_a16(uint32_t fetchdat)
|
||||
{
|
||||
pclog("A16: D9 %02X\n", fetchdat & 0xff);
|
||||
return x86_opcodes_d9_a16[fetchdat & 0xff](fetchdat);
|
||||
}
|
||||
static int opESCAPE_d9_a32(uint32_t fetchdat)
|
||||
{
|
||||
pclog("A32: D9 %02X\n", fetchdat & 0xff);
|
||||
return x86_opcodes_d9_a32[fetchdat & 0xff](fetchdat);
|
||||
}
|
||||
|
||||
static int opESCAPE_da_a16(uint32_t fetchdat)
|
||||
{
|
||||
pclog("A16: DA %02X\n", fetchdat & 0xff);
|
||||
return x86_opcodes_da_a16[fetchdat & 0xff](fetchdat);
|
||||
}
|
||||
static int opESCAPE_da_a32(uint32_t fetchdat)
|
||||
{
|
||||
pclog("A32: DA %02X\n", fetchdat & 0xff);
|
||||
return x86_opcodes_da_a32[fetchdat & 0xff](fetchdat);
|
||||
}
|
||||
|
||||
static int opESCAPE_db_a16(uint32_t fetchdat)
|
||||
{
|
||||
pclog("A16: DB %02X\n", fetchdat & 0xff);
|
||||
return x86_opcodes_db_a16[fetchdat & 0xff](fetchdat);
|
||||
}
|
||||
static int opESCAPE_db_a32(uint32_t fetchdat)
|
||||
{
|
||||
pclog("A32: DB %02X\n", fetchdat & 0xff);
|
||||
return x86_opcodes_db_a32[fetchdat & 0xff](fetchdat);
|
||||
}
|
||||
|
||||
static int opESCAPE_dc_a16(uint32_t fetchdat)
|
||||
{
|
||||
pclog("A16: DC %02X\n", fetchdat & 0xff);
|
||||
return x86_opcodes_dc_a16[(fetchdat >> 3) & 0x1f](fetchdat);
|
||||
}
|
||||
static int opESCAPE_dc_a32(uint32_t fetchdat)
|
||||
{
|
||||
pclog("A32: DC %02X\n", fetchdat & 0xff);
|
||||
return x86_opcodes_dc_a32[(fetchdat >> 3) & 0x1f](fetchdat);
|
||||
}
|
||||
|
||||
static int opESCAPE_dd_a16(uint32_t fetchdat)
|
||||
{
|
||||
pclog("A16: DD %02X\n", fetchdat & 0xff);
|
||||
return x86_opcodes_dd_a16[fetchdat & 0xff](fetchdat);
|
||||
}
|
||||
static int opESCAPE_dd_a32(uint32_t fetchdat)
|
||||
{
|
||||
pclog("A32: DD %02X\n", fetchdat & 0xff);
|
||||
return x86_opcodes_dd_a32[fetchdat & 0xff](fetchdat);
|
||||
}
|
||||
|
||||
static int opESCAPE_de_a16(uint32_t fetchdat)
|
||||
{
|
||||
pclog("A16: DE %02X\n", fetchdat & 0xff);
|
||||
return x86_opcodes_de_a16[fetchdat & 0xff](fetchdat);
|
||||
}
|
||||
static int opESCAPE_de_a32(uint32_t fetchdat)
|
||||
{
|
||||
pclog("A32: DE %02X\n", fetchdat & 0xff);
|
||||
return x86_opcodes_de_a32[fetchdat & 0xff](fetchdat);
|
||||
}
|
||||
|
||||
static int opESCAPE_df_a16(uint32_t fetchdat)
|
||||
{
|
||||
pclog("A16: DF %02X\n", fetchdat & 0xff);
|
||||
return x86_opcodes_df_a16[fetchdat & 0xff](fetchdat);
|
||||
}
|
||||
static int opESCAPE_df_a32(uint32_t fetchdat)
|
||||
{
|
||||
pclog("A32: DF %02X\n", fetchdat & 0xff);
|
||||
return x86_opcodes_df_a32[fetchdat & 0xff](fetchdat);
|
||||
}
|
||||
|
||||
static int opWAIT(uint32_t fetchdat)
|
||||
{
|
||||
if ((cr0 & 0xa) == 0xa)
|
||||
{
|
||||
x86_int(7);
|
||||
return 1;
|
||||
}
|
||||
CLOCK_CYCLES(4);
|
||||
return 0;
|
||||
}
|
||||
526
src/cpu_common/x86_ops_i686.h
Normal file
526
src/cpu_common/x86_ops_i686.h
Normal file
@@ -0,0 +1,526 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* x86 i686 (Pentium Pro/Pentium II) CPU Instructions.
|
||||
*
|
||||
* Version: @(#)x86_ops_i686.h 1.0.6 2020/01/27
|
||||
*
|
||||
* Author: Miran Grca, <mgrca8@gmail.com>
|
||||
* Copyright 2016-2020 Miran Grca.
|
||||
*/
|
||||
|
||||
/* 0 = Limit 0-15
|
||||
1 = Base 0-15
|
||||
2 = Base 16-23 (bits 0-7), Access rights
|
||||
8-11 Type
|
||||
12 S
|
||||
13, 14 DPL
|
||||
15 P
|
||||
3 = Limit 16-19 (bits 0-3), Base 24-31 (bits 8-15), granularity, etc.
|
||||
4 A
|
||||
6 DB
|
||||
7 G */
|
||||
|
||||
static void make_seg_data(uint16_t *seg_data, uint32_t base, uint32_t limit, uint8_t type, uint8_t s, uint8_t dpl, uint8_t p, uint8_t g, uint8_t db, uint8_t a)
|
||||
{
|
||||
seg_data[0] = limit & 0xFFFF;
|
||||
seg_data[1] = base & 0xFFFF;
|
||||
seg_data[2] = ((base >> 16) & 0xFF) | (type << 8) | (p << 15) | (dpl << 13) | (s << 12);
|
||||
seg_data[3] = ((limit >> 16) & 0xF) | (a << 4) | (db << 6) | (g << 7) | ((base >> 16) & 0xFF00);
|
||||
}
|
||||
|
||||
static int opSYSENTER(uint32_t fetchdat)
|
||||
{
|
||||
uint16_t sysenter_cs_seg_data[4];
|
||||
uint16_t sysenter_ss_seg_data[4];
|
||||
|
||||
#ifdef SYSENTER_LOG
|
||||
x386_dynarec_log("SYSENTER called\n");
|
||||
#endif
|
||||
|
||||
if (!(msw & 1)) return internal_illegal("SYSENTER: CPU not in protected mode");
|
||||
if (!(cs_msr & 0xFFFC)) return internal_illegal("SYSENTER: CS MSR is zero");
|
||||
|
||||
#ifdef SYSENTER_LOG
|
||||
x386_dynarec_log("SYSENTER started:\n");
|
||||
x386_dynarec_log("CS (%04X): base=%08X, limit=%08X, access=%02X, seg=%04X, limit_low=%08X, limit_high=%08X, checked=%i\n", CS, cpu_state.seg_cs.base, cpu_state.seg_cs.limit, cpu_state.seg_cs.access, cpu_state.seg_cs.seg, cpu_state.seg_cs.limit_low, cpu_state.seg_cs.limit_high, cpu_state.seg_cs.checked);
|
||||
x386_dynarec_log("SS (%04X): base=%08X, limit=%08X, access=%02X, seg=%04X, limit_low=%08X, limit_high=%08X, checked=%i\n", SS, cpu_state.seg_ss.base, cpu_state.seg_ss.limit, cpu_state.seg_ss.access, cpu_state.seg_ss.seg, cpu_state.seg_ss.limit_low, cpu_state.seg_ss.limit_high, cpu_state.seg_ss.checked);
|
||||
x386_dynarec_log("Model specific registers: cs_msr=%04X, esp_msr=%08X, eip_msr=%08X\n", cs_msr, esp_msr, eip_msr);
|
||||
x386_dynarec_log("Other information: eip=%08X esp=%08X cpu_state.eflags=%04X cpu_state.flags=%04X use32=%04X stack32=%i\n", cpu_state.pc, ESP, cpu_state.eflags, cpu_state.flags, use32, stack32);
|
||||
#endif
|
||||
|
||||
if (cpu_state.abrt) return 1;
|
||||
|
||||
ESP = esp_msr;
|
||||
cpu_state.pc = eip_msr;
|
||||
|
||||
optype = CALL; \
|
||||
cgate16 = cgate32 = 0; \
|
||||
|
||||
/* Set VM, RF, and IF to 0. */
|
||||
cpu_state.eflags &= ~0x0003;
|
||||
cpu_state.flags &= ~0x0200;
|
||||
|
||||
CS = (cs_msr & 0xFFFC);
|
||||
make_seg_data(sysenter_cs_seg_data, 0, 0xFFFFF, 11, 1, 0, 1, 1, 1, 0);
|
||||
do_seg_load(&cpu_state.seg_cs, sysenter_cs_seg_data);
|
||||
use32 = 0x300;
|
||||
|
||||
SS = ((cs_msr + 8) & 0xFFFC);
|
||||
make_seg_data(sysenter_ss_seg_data, 0, 0xFFFFF, 3, 1, 0, 1, 1, 1, 0);
|
||||
do_seg_load(&cpu_state.seg_ss, sysenter_ss_seg_data);
|
||||
stack32 = 1;
|
||||
|
||||
cycles -= timing_call_pm;
|
||||
|
||||
optype = 0;
|
||||
|
||||
CPU_BLOCK_END();
|
||||
|
||||
#ifdef SYSENTER_LOG
|
||||
x386_dynarec_log("SYSENTER completed:\n");
|
||||
x386_dynarec_log("CS (%04X): base=%08X, limit=%08X, access=%02X, seg=%04X, limit_low=%08X, limit_high=%08X, checked=%i\n", CS, cpu_state.seg_cs.base, cpu_state.seg_cs.limit, cpu_state.seg_cs.access, cpu_state.seg_cs.seg, cpu_state.seg_cs.limit_low, cpu_state.seg_cs.limit_high, cpu_state.seg_cs.checked);
|
||||
x386_dynarec_log("SS (%04X): base=%08X, limit=%08X, access=%02X, seg=%04X, limit_low=%08X, limit_high=%08X, checked=%i\n", SS, cpu_state.seg_ss.base, cpu_state.seg_ss.limit, cpu_state.seg_ss.access, cpu_state.seg_ss.seg, cpu_state.seg_ss.limit_low, cpu_state.seg_ss.limit_high, cpu_state.seg_ss.checked);
|
||||
x386_dynarec_log("Model specific registers: cs_msr=%04X, esp_msr=%08X, eip_msr=%08X\n", cs_msr, esp_msr, eip_msr);
|
||||
x386_dynarec_log("Other information: eip=%08X esp=%08X cpu_state.eflags=%04X cpu_state.flags=%04X use32=%04X stack32=%i\n", cpu_state.pc, ESP, cpu_state.eflags, cpu_state.flags, use32, stack32);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opSYSEXIT(uint32_t fetchdat)
|
||||
{
|
||||
uint16_t sysexit_cs_seg_data[4];
|
||||
uint16_t sysexit_ss_seg_data[4];
|
||||
|
||||
#ifdef SYSEXIT_LOG
|
||||
x386_dynarec_log("SYSEXIT called\n");
|
||||
#endif
|
||||
|
||||
if (!(cs_msr & 0xFFFC)) return internal_illegal("SYSEXIT: CS MSR is zero");
|
||||
if (!(msw & 1)) return internal_illegal("SYSEXIT: CPU not in protected mode");
|
||||
if (CPL) return internal_illegal("SYSEXIT: CPL not 0");
|
||||
|
||||
#ifdef SYSEXIT_LOG
|
||||
x386_dynarec_log("SYSEXIT start:\n");
|
||||
x386_dynarec_log("CS (%04X): base=%08X, limit=%08X, access=%02X, seg=%04X, limit_low=%08X, limit_high=%08X, checked=%i\n", CS, cpu_state.seg_cs.base, cpu_state.seg_cs.limit, cpu_state.seg_cs.access, cpu_state.seg_cs.seg, cpu_state.seg_cs.limit_low, cpu_state.seg_cs.limit_high, cpu_state.seg_cs.checked);
|
||||
x386_dynarec_log("SS (%04X): base=%08X, limit=%08X, access=%02X, seg=%04X, limit_low=%08X, limit_high=%08X, checked=%i\n", SS, cpu_state.seg_ss.base, cpu_state.seg_ss.limit, cpu_state.seg_ss.access, cpu_state.seg_ss.seg, cpu_state.seg_ss.limit_low, cpu_state.seg_ss.limit_high, cpu_state.seg_ss.checked);
|
||||
x386_dynarec_log("Model specific registers: cs_msr=%04X, esp_msr=%08X, eip_msr=%08X\n", cs_msr, esp_msr, eip_msr);
|
||||
x386_dynarec_log("Other information: eip=%08X esp=%08X cpu_state.eflags=%04X cpu_state.flags=%04X use32=%04X stack32=%i ECX=%08X EDX=%08X\n", cpu_state.pc, ESP, cpu_state.eflags, cpu_state.flags, use32, stack32, ECX, EDX);
|
||||
#endif
|
||||
|
||||
if (cpu_state.abrt) return 1;
|
||||
|
||||
ESP = ECX;
|
||||
cpu_state.pc = EDX;
|
||||
|
||||
optype = CALL; \
|
||||
cgate16 = cgate32 = 0; \
|
||||
|
||||
CS = ((cs_msr + 16) & 0xFFFC) | 3;
|
||||
make_seg_data(sysexit_cs_seg_data, 0, 0xFFFFF, 11, 1, 3, 1, 1, 1, 0);
|
||||
do_seg_load(&cpu_state.seg_cs, sysexit_cs_seg_data);
|
||||
use32 = 0x300;
|
||||
|
||||
SS = CS + 8;
|
||||
make_seg_data(sysexit_ss_seg_data, 0, 0xFFFFF, 3, 1, 3, 1, 1, 1, 0);
|
||||
do_seg_load(&cpu_state.seg_ss, sysexit_ss_seg_data);
|
||||
stack32 = 1;
|
||||
|
||||
flushmmucache_cr3();
|
||||
|
||||
cycles -= timing_call_pm;
|
||||
|
||||
optype = 0;
|
||||
|
||||
CPU_BLOCK_END();
|
||||
|
||||
#ifdef SYSEXIT_LOG
|
||||
x386_dynarec_log("SYSEXIT completed:\n");
|
||||
x386_dynarec_log("CS (%04X): base=%08X, limit=%08X, access=%02X, seg=%04X, limit_low=%08X, limit_high=%08X, checked=%i\n", CS, cpu_state.seg_cs.base, cpu_state.seg_cs.limit, cpu_state.seg_cs.access, cpu_state.seg_cs.seg, cpu_state.seg_cs.limit_low, cpu_state.seg_cs.limit_high, cpu_state.seg_cs.checked);
|
||||
x386_dynarec_log("SS (%04X): base=%08X, limit=%08X, access=%02X, seg=%04X, limit_low=%08X, limit_high=%08X, checked=%i\n", SS, cpu_state.seg_ss.base, cpu_state.seg_ss.limit, cpu_state.seg_ss.access, cpu_state.seg_ss.seg, cpu_state.seg_ss.limit_low, cpu_state.seg_ss.limit_high, cpu_state.seg_ss.checked);
|
||||
x386_dynarec_log("Model specific registers: cs_msr=%04X, esp_msr=%08X, eip_msr=%08X\n", cs_msr, esp_msr, eip_msr);
|
||||
x386_dynarec_log("Other information: eip=%08X esp=%08X cpu_state.eflags=%04X cpu_state.flags=%04X use32=%04X stack32=%i ECX=%08X EDX=%08X\n", cpu_state.pc, ESP, cpu_state.eflags, cpu_state.flags, use32, stack32, ECX, EDX);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opFXSAVESTOR_a16(uint32_t fetchdat)
|
||||
{
|
||||
uint8_t fxinst = 0;
|
||||
uint16_t twd = x87_gettag();
|
||||
uint16_t old_eaaddr = 0;
|
||||
uint8_t ftwb = 0;
|
||||
uint16_t rec_ftw = 0;
|
||||
uint16_t fpus = 0;
|
||||
uint64_t *p;
|
||||
|
||||
if (CPUID < 0x650) return ILLEGAL(fetchdat);
|
||||
|
||||
FP_ENTER();
|
||||
|
||||
fetch_ea_16(fetchdat);
|
||||
|
||||
if (cpu_state.eaaddr & 0xf)
|
||||
{
|
||||
x386_dynarec_log("Effective address %04X not on 16-byte boundary\n", cpu_state.eaaddr);
|
||||
x86gpf(NULL, 0);
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
|
||||
fxinst = (rmdat >> 3) & 7;
|
||||
|
||||
if ((fxinst > 1) || (cpu_mod == 3))
|
||||
{
|
||||
x86illegal();
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
|
||||
FP_ENTER();
|
||||
|
||||
old_eaaddr = cpu_state.eaaddr;
|
||||
|
||||
if (fxinst == 1)
|
||||
{
|
||||
/* FXRSTOR */
|
||||
cpu_state.npxc = readmemw(easeg, cpu_state.eaaddr);
|
||||
#ifdef USE_NEW_DYNAREC
|
||||
codegen_set_rounding_mode((cpu_state.npxc >> 10) & 3);
|
||||
#endif
|
||||
fpus = readmemw(easeg, cpu_state.eaaddr + 2);
|
||||
cpu_state.npxc = (cpu_state.npxc & ~FPU_CW_Reserved_Bits) | 0x0040;
|
||||
#ifdef USE_NEW_DYNAREC
|
||||
codegen_set_rounding_mode((cpu_state.npxc >> 10) & 3);
|
||||
#endif
|
||||
cpu_state.TOP = (fpus >> 11) & 7;
|
||||
cpu_state.npxs &= fpus & ~0x3800;
|
||||
|
||||
/* foo = readmemw(easeg, cpu_state.eaaddr + 6) & 0x7FF; */
|
||||
|
||||
x87_pc_off = readmeml(easeg, cpu_state.eaaddr+8);
|
||||
x87_pc_seg = readmemw(easeg, cpu_state.eaaddr+12);
|
||||
/* if (cr0 & 1)
|
||||
{
|
||||
x87_pc_seg &= 0xFFFC;
|
||||
x87_pc_seg |= ((cpu_state.seg_cs.access >> 5) & 3);
|
||||
} */
|
||||
|
||||
ftwb = readmemb(easeg, cpu_state.eaaddr + 4);
|
||||
|
||||
if (ftwb & 0x01) rec_ftw |= 0x0003;
|
||||
if (ftwb & 0x02) rec_ftw |= 0x000C;
|
||||
if (ftwb & 0x04) rec_ftw |= 0x0030;
|
||||
if (ftwb & 0x08) rec_ftw |= 0x00C0;
|
||||
if (ftwb & 0x10) rec_ftw |= 0x0300;
|
||||
if (ftwb & 0x20) rec_ftw |= 0x0C00;
|
||||
if (ftwb & 0x40) rec_ftw |= 0x3000;
|
||||
if (ftwb & 0x80) rec_ftw |= 0xC000;
|
||||
|
||||
x87_op_off = readmeml(easeg, cpu_state.eaaddr+16);
|
||||
x87_op_off |= (readmemw(easeg, cpu_state.eaaddr + 6) >> 12) << 16;
|
||||
x87_op_seg = readmemw(easeg, cpu_state.eaaddr+20);
|
||||
/* if (cr0 & 1)
|
||||
{
|
||||
x87_op_seg &= 0xFFFC;
|
||||
x87_op_seg |= ((_ds.access >> 5) & 3);
|
||||
} */
|
||||
|
||||
cpu_state.eaaddr = old_eaaddr + 32;
|
||||
x87_ldmmx(&(cpu_state.MM[0]), &(cpu_state.MM_w4[0])); x87_ld_frstor(0);
|
||||
|
||||
cpu_state.eaaddr = old_eaaddr + 48;
|
||||
x87_ldmmx(&(cpu_state.MM[1]), &(cpu_state.MM_w4[1])); x87_ld_frstor(1);
|
||||
|
||||
cpu_state.eaaddr = old_eaaddr + 64;
|
||||
x87_ldmmx(&(cpu_state.MM[2]), &(cpu_state.MM_w4[2])); x87_ld_frstor(2);
|
||||
|
||||
cpu_state.eaaddr = old_eaaddr + 80;
|
||||
x87_ldmmx(&(cpu_state.MM[3]), &(cpu_state.MM_w4[3])); x87_ld_frstor(3);
|
||||
|
||||
cpu_state.eaaddr = old_eaaddr + 96;
|
||||
x87_ldmmx(&(cpu_state.MM[4]), &(cpu_state.MM_w4[4])); x87_ld_frstor(4);
|
||||
|
||||
cpu_state.eaaddr = old_eaaddr + 112;
|
||||
x87_ldmmx(&(cpu_state.MM[5]), &(cpu_state.MM_w4[5])); x87_ld_frstor(5);
|
||||
|
||||
cpu_state.eaaddr = old_eaaddr + 128;
|
||||
x87_ldmmx(&(cpu_state.MM[6]), &(cpu_state.MM_w4[6])); x87_ld_frstor(6);
|
||||
|
||||
cpu_state.eaaddr = old_eaaddr + 144;
|
||||
x87_ldmmx(&(cpu_state.MM[7]), &(cpu_state.MM_w4[7])); x87_ld_frstor(7);
|
||||
|
||||
cpu_state.ismmx = 0;
|
||||
/*Horrible hack, but as PCem doesn't keep the FPU stack in 80-bit precision at all times
|
||||
something like this is needed*/
|
||||
p = (uint64_t *)cpu_state.tag;
|
||||
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 && !(*p))
|
||||
cpu_state.ismmx = 1;
|
||||
|
||||
x87_settag(rec_ftw);
|
||||
|
||||
CLOCK_CYCLES((cr0 & 1) ? 34 : 44);
|
||||
|
||||
if(cpu_state.abrt) x386_dynarec_log("FXRSTOR: abrt != 0\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
/* FXSAVE */
|
||||
if ((twd & 0x0003) == 0x0003) ftwb |= 0x01;
|
||||
if ((twd & 0x000C) == 0x000C) ftwb |= 0x02;
|
||||
if ((twd & 0x0030) == 0x0030) ftwb |= 0x04;
|
||||
if ((twd & 0x00C0) == 0x00C0) ftwb |= 0x08;
|
||||
if ((twd & 0x0300) == 0x0300) ftwb |= 0x10;
|
||||
if ((twd & 0x0C00) == 0x0C00) ftwb |= 0x20;
|
||||
if ((twd & 0x3000) == 0x3000) ftwb |= 0x40;
|
||||
if ((twd & 0xC000) == 0xC000) ftwb |= 0x80;
|
||||
|
||||
writememw(easeg,cpu_state.eaaddr,cpu_state.npxc);
|
||||
writememw(easeg,cpu_state.eaaddr+2,cpu_state.npxs);
|
||||
writememb(easeg,cpu_state.eaaddr+4,ftwb);
|
||||
|
||||
writememw(easeg,cpu_state.eaaddr+6,(x87_op_off>>16)<<12);
|
||||
writememl(easeg,cpu_state.eaaddr+8,x87_pc_off);
|
||||
writememw(easeg,cpu_state.eaaddr+12,x87_pc_seg);
|
||||
|
||||
writememl(easeg,cpu_state.eaaddr+16,x87_op_off);
|
||||
writememw(easeg,cpu_state.eaaddr+20,x87_op_seg);
|
||||
|
||||
cpu_state.eaaddr = old_eaaddr + 32;
|
||||
cpu_state.ismmx ? x87_stmmx(cpu_state.MM[0]) : x87_st_fsave(0);
|
||||
|
||||
cpu_state.eaaddr = old_eaaddr + 48;
|
||||
cpu_state.ismmx ? x87_stmmx(cpu_state.MM[1]) : x87_st_fsave(1);
|
||||
|
||||
cpu_state.eaaddr = old_eaaddr + 64;
|
||||
cpu_state.ismmx ? x87_stmmx(cpu_state.MM[2]) : x87_st_fsave(2);
|
||||
|
||||
cpu_state.eaaddr = old_eaaddr + 80;
|
||||
cpu_state.ismmx ? x87_stmmx(cpu_state.MM[3]) : x87_st_fsave(3);
|
||||
|
||||
cpu_state.eaaddr = old_eaaddr + 96;
|
||||
cpu_state.ismmx ? x87_stmmx(cpu_state.MM[4]) : x87_st_fsave(4);
|
||||
|
||||
cpu_state.eaaddr = old_eaaddr + 112;
|
||||
cpu_state.ismmx ? x87_stmmx(cpu_state.MM[5]) : x87_st_fsave(5);
|
||||
|
||||
cpu_state.eaaddr = old_eaaddr + 128;
|
||||
cpu_state.ismmx ? x87_stmmx(cpu_state.MM[6]) : x87_st_fsave(6);
|
||||
|
||||
cpu_state.eaaddr = old_eaaddr + 144;
|
||||
cpu_state.ismmx ? x87_stmmx(cpu_state.MM[7]) : x87_st_fsave(7);
|
||||
|
||||
cpu_state.eaaddr = old_eaaddr;
|
||||
|
||||
cpu_state.npxc = 0x37F;
|
||||
#ifdef USE_NEW_DYNAREC
|
||||
codegen_set_rounding_mode((cpu_state.npxc >> 10) & 3);
|
||||
#endif
|
||||
cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00);
|
||||
cpu_state.npxs = 0;
|
||||
p = (uint64_t *)cpu_state.tag;
|
||||
*p = 0x0303030303030303ll;
|
||||
cpu_state.TOP = 0;
|
||||
cpu_state.ismmx = 0;
|
||||
|
||||
CLOCK_CYCLES((cr0 & 1) ? 56 : 67);
|
||||
|
||||
if(cpu_state.abrt) x386_dynarec_log("FXSAVE: abrt != 0\n");
|
||||
}
|
||||
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
|
||||
static int opFXSAVESTOR_a32(uint32_t fetchdat)
|
||||
{
|
||||
uint8_t fxinst = 0;
|
||||
uint16_t twd = x87_gettag();
|
||||
uint32_t old_eaaddr = 0;
|
||||
uint8_t ftwb = 0;
|
||||
uint16_t rec_ftw = 0;
|
||||
uint16_t fpus = 0;
|
||||
uint64_t *p;
|
||||
|
||||
if (CPUID < 0x650) return ILLEGAL(fetchdat);
|
||||
|
||||
FP_ENTER();
|
||||
|
||||
fetch_ea_32(fetchdat);
|
||||
|
||||
if (cpu_state.eaaddr & 0xf)
|
||||
{
|
||||
x386_dynarec_log("Effective address %08X not on 16-byte boundary\n", cpu_state.eaaddr);
|
||||
x86gpf(NULL, 0);
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
|
||||
fxinst = (rmdat >> 3) & 7;
|
||||
|
||||
if ((fxinst > 1) || (cpu_mod == 3))
|
||||
{
|
||||
x86illegal();
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
|
||||
FP_ENTER();
|
||||
|
||||
old_eaaddr = cpu_state.eaaddr;
|
||||
|
||||
if (fxinst == 1)
|
||||
{
|
||||
/* FXRSTOR */
|
||||
cpu_state.npxc = readmemw(easeg, cpu_state.eaaddr);
|
||||
#ifdef USE_NEW_DYNAREC
|
||||
codegen_set_rounding_mode((cpu_state.npxc >> 10) & 3);
|
||||
#endif
|
||||
fpus = readmemw(easeg, cpu_state.eaaddr + 2);
|
||||
cpu_state.npxc = (cpu_state.npxc & ~FPU_CW_Reserved_Bits) | 0x0040;
|
||||
#ifdef USE_NEW_DYNAREC
|
||||
codegen_set_rounding_mode((cpu_state.npxc >> 10) & 3);
|
||||
#endif
|
||||
cpu_state.TOP = (fpus >> 11) & 7;
|
||||
cpu_state.npxs &= fpus & ~0x3800;
|
||||
|
||||
/* foo = readmemw(easeg, cpu_state.eaaddr + 6) & 0x7FF; */
|
||||
|
||||
x87_pc_off = readmeml(easeg, cpu_state.eaaddr+8);
|
||||
x87_pc_seg = readmemw(easeg, cpu_state.eaaddr+12);
|
||||
/* if (cr0 & 1)
|
||||
{
|
||||
x87_pc_seg &= 0xFFFC;
|
||||
x87_pc_seg |= ((cpu_state.seg_cs.access >> 5) & 3);
|
||||
} */
|
||||
|
||||
ftwb = readmemb(easeg, cpu_state.eaaddr + 4);
|
||||
|
||||
if (ftwb & 0x01) rec_ftw |= 0x0003;
|
||||
if (ftwb & 0x02) rec_ftw |= 0x000C;
|
||||
if (ftwb & 0x04) rec_ftw |= 0x0030;
|
||||
if (ftwb & 0x08) rec_ftw |= 0x00C0;
|
||||
if (ftwb & 0x10) rec_ftw |= 0x0300;
|
||||
if (ftwb & 0x20) rec_ftw |= 0x0C00;
|
||||
if (ftwb & 0x40) rec_ftw |= 0x3000;
|
||||
if (ftwb & 0x80) rec_ftw |= 0xC000;
|
||||
|
||||
x87_op_off = readmeml(easeg, cpu_state.eaaddr+16);
|
||||
x87_op_off |= (readmemw(easeg, cpu_state.eaaddr + 6) >> 12) << 16;
|
||||
x87_op_seg = readmemw(easeg, cpu_state.eaaddr+20);
|
||||
/* if (cr0 & 1)
|
||||
{
|
||||
x87_op_seg &= 0xFFFC;
|
||||
x87_op_seg |= ((_ds.access >> 5) & 3);
|
||||
} */
|
||||
|
||||
cpu_state.eaaddr = old_eaaddr + 32;
|
||||
x87_ldmmx(&(cpu_state.MM[0]), &(cpu_state.MM_w4[0])); x87_ld_frstor(0);
|
||||
|
||||
cpu_state.eaaddr = old_eaaddr + 48;
|
||||
x87_ldmmx(&(cpu_state.MM[1]), &(cpu_state.MM_w4[1])); x87_ld_frstor(1);
|
||||
|
||||
cpu_state.eaaddr = old_eaaddr + 64;
|
||||
x87_ldmmx(&(cpu_state.MM[2]), &(cpu_state.MM_w4[2])); x87_ld_frstor(2);
|
||||
|
||||
cpu_state.eaaddr = old_eaaddr + 80;
|
||||
x87_ldmmx(&(cpu_state.MM[3]), &(cpu_state.MM_w4[3])); x87_ld_frstor(3);
|
||||
|
||||
cpu_state.eaaddr = old_eaaddr + 96;
|
||||
x87_ldmmx(&(cpu_state.MM[4]), &(cpu_state.MM_w4[4])); x87_ld_frstor(4);
|
||||
|
||||
cpu_state.eaaddr = old_eaaddr + 112;
|
||||
x87_ldmmx(&(cpu_state.MM[5]), &(cpu_state.MM_w4[5])); x87_ld_frstor(5);
|
||||
|
||||
cpu_state.eaaddr = old_eaaddr + 128;
|
||||
x87_ldmmx(&(cpu_state.MM[6]), &(cpu_state.MM_w4[6])); x87_ld_frstor(6);
|
||||
|
||||
cpu_state.eaaddr = old_eaaddr + 144;
|
||||
x87_ldmmx(&(cpu_state.MM[7]), &(cpu_state.MM_w4[7])); x87_ld_frstor(7);
|
||||
|
||||
cpu_state.ismmx = 0;
|
||||
/*Horrible hack, but as PCem doesn't keep the FPU stack in 80-bit precision at all times
|
||||
something like this is needed*/
|
||||
p = (uint64_t *)cpu_state.tag;
|
||||
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 && !(*p))
|
||||
cpu_state.ismmx = 1;
|
||||
|
||||
x87_settag(rec_ftw);
|
||||
|
||||
CLOCK_CYCLES((cr0 & 1) ? 34 : 44);
|
||||
|
||||
if(cpu_state.abrt) x386_dynarec_log("FXRSTOR: abrt != 0\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
/* FXSAVE */
|
||||
if ((twd & 0x0003) == 0x0003) ftwb |= 0x01;
|
||||
if ((twd & 0x000C) == 0x000C) ftwb |= 0x02;
|
||||
if ((twd & 0x0030) == 0x0030) ftwb |= 0x04;
|
||||
if ((twd & 0x00C0) == 0x00C0) ftwb |= 0x08;
|
||||
if ((twd & 0x0300) == 0x0300) ftwb |= 0x10;
|
||||
if ((twd & 0x0C00) == 0x0C00) ftwb |= 0x20;
|
||||
if ((twd & 0x3000) == 0x3000) ftwb |= 0x40;
|
||||
if ((twd & 0xC000) == 0xC000) ftwb |= 0x80;
|
||||
|
||||
writememw(easeg,cpu_state.eaaddr,cpu_state.npxc);
|
||||
writememw(easeg,cpu_state.eaaddr+2,cpu_state.npxs);
|
||||
writememb(easeg,cpu_state.eaaddr+4,ftwb);
|
||||
|
||||
writememw(easeg,cpu_state.eaaddr+6,(x87_op_off>>16)<<12);
|
||||
writememl(easeg,cpu_state.eaaddr+8,x87_pc_off);
|
||||
writememw(easeg,cpu_state.eaaddr+12,x87_pc_seg);
|
||||
|
||||
writememl(easeg,cpu_state.eaaddr+16,x87_op_off);
|
||||
writememw(easeg,cpu_state.eaaddr+20,x87_op_seg);
|
||||
|
||||
cpu_state.eaaddr = old_eaaddr + 32;
|
||||
cpu_state.ismmx ? x87_stmmx(cpu_state.MM[0]) : x87_st_fsave(0);
|
||||
|
||||
cpu_state.eaaddr = old_eaaddr + 48;
|
||||
cpu_state.ismmx ? x87_stmmx(cpu_state.MM[1]) : x87_st_fsave(1);
|
||||
|
||||
cpu_state.eaaddr = old_eaaddr + 64;
|
||||
cpu_state.ismmx ? x87_stmmx(cpu_state.MM[2]) : x87_st_fsave(2);
|
||||
|
||||
cpu_state.eaaddr = old_eaaddr + 80;
|
||||
cpu_state.ismmx ? x87_stmmx(cpu_state.MM[3]) : x87_st_fsave(3);
|
||||
|
||||
cpu_state.eaaddr = old_eaaddr + 96;
|
||||
cpu_state.ismmx ? x87_stmmx(cpu_state.MM[4]) : x87_st_fsave(4);
|
||||
|
||||
cpu_state.eaaddr = old_eaaddr + 112;
|
||||
cpu_state.ismmx ? x87_stmmx(cpu_state.MM[5]) : x87_st_fsave(5);
|
||||
|
||||
cpu_state.eaaddr = old_eaaddr + 128;
|
||||
cpu_state.ismmx ? x87_stmmx(cpu_state.MM[6]) : x87_st_fsave(6);
|
||||
|
||||
cpu_state.eaaddr = old_eaaddr + 144;
|
||||
cpu_state.ismmx ? x87_stmmx(cpu_state.MM[7]) : x87_st_fsave(7);
|
||||
|
||||
cpu_state.eaaddr = old_eaaddr;
|
||||
|
||||
cpu_state.npxc = 0x37F;
|
||||
#ifdef USE_NEW_DYNAREC
|
||||
codegen_set_rounding_mode((cpu_state.npxc >> 10) & 3);
|
||||
#endif
|
||||
cpu_state.new_npxc = (cpu_state.old_npxc & ~0xc00);
|
||||
cpu_state.npxs = 0;
|
||||
p = (uint64_t *)cpu_state.tag;
|
||||
*p = 0x0303030303030303ll;
|
||||
cpu_state.TOP = 0;
|
||||
cpu_state.ismmx = 0;
|
||||
|
||||
CLOCK_CYCLES((cr0 & 1) ? 56 : 67);
|
||||
|
||||
if(cpu_state.abrt) x386_dynarec_log("FXSAVE: abrt != 0\n");
|
||||
}
|
||||
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
93
src/cpu_common/x86_ops_inc_dec.h
Normal file
93
src/cpu_common/x86_ops_inc_dec.h
Normal file
@@ -0,0 +1,93 @@
|
||||
#define INC_DEC_OP(name, reg, inc, setflags) \
|
||||
static int op ## name (uint32_t fetchdat) \
|
||||
{ \
|
||||
setflags(reg, 1); \
|
||||
reg += inc; \
|
||||
CLOCK_CYCLES(timing_rr); \
|
||||
PREFETCH_RUN(timing_rr, 1, -1, 0,0,0,0, 0); \
|
||||
return 0; \
|
||||
}
|
||||
|
||||
INC_DEC_OP(INC_AX, AX, 1, setadd16nc)
|
||||
INC_DEC_OP(INC_BX, BX, 1, setadd16nc)
|
||||
INC_DEC_OP(INC_CX, CX, 1, setadd16nc)
|
||||
INC_DEC_OP(INC_DX, DX, 1, setadd16nc)
|
||||
INC_DEC_OP(INC_SI, SI, 1, setadd16nc)
|
||||
INC_DEC_OP(INC_DI, DI, 1, setadd16nc)
|
||||
INC_DEC_OP(INC_BP, BP, 1, setadd16nc)
|
||||
INC_DEC_OP(INC_SP, SP, 1, setadd16nc)
|
||||
|
||||
INC_DEC_OP(INC_EAX, EAX, 1, setadd32nc)
|
||||
INC_DEC_OP(INC_EBX, EBX, 1, setadd32nc)
|
||||
INC_DEC_OP(INC_ECX, ECX, 1, setadd32nc)
|
||||
INC_DEC_OP(INC_EDX, EDX, 1, setadd32nc)
|
||||
INC_DEC_OP(INC_ESI, ESI, 1, setadd32nc)
|
||||
INC_DEC_OP(INC_EDI, EDI, 1, setadd32nc)
|
||||
INC_DEC_OP(INC_EBP, EBP, 1, setadd32nc)
|
||||
INC_DEC_OP(INC_ESP, ESP, 1, setadd32nc)
|
||||
|
||||
INC_DEC_OP(DEC_AX, AX, -1, setsub16nc)
|
||||
INC_DEC_OP(DEC_BX, BX, -1, setsub16nc)
|
||||
INC_DEC_OP(DEC_CX, CX, -1, setsub16nc)
|
||||
INC_DEC_OP(DEC_DX, DX, -1, setsub16nc)
|
||||
INC_DEC_OP(DEC_SI, SI, -1, setsub16nc)
|
||||
INC_DEC_OP(DEC_DI, DI, -1, setsub16nc)
|
||||
INC_DEC_OP(DEC_BP, BP, -1, setsub16nc)
|
||||
INC_DEC_OP(DEC_SP, SP, -1, setsub16nc)
|
||||
|
||||
INC_DEC_OP(DEC_EAX, EAX, -1, setsub32nc)
|
||||
INC_DEC_OP(DEC_EBX, EBX, -1, setsub32nc)
|
||||
INC_DEC_OP(DEC_ECX, ECX, -1, setsub32nc)
|
||||
INC_DEC_OP(DEC_EDX, EDX, -1, setsub32nc)
|
||||
INC_DEC_OP(DEC_ESI, ESI, -1, setsub32nc)
|
||||
INC_DEC_OP(DEC_EDI, EDI, -1, setsub32nc)
|
||||
INC_DEC_OP(DEC_EBP, EBP, -1, setsub32nc)
|
||||
INC_DEC_OP(DEC_ESP, ESP, -1, setsub32nc)
|
||||
|
||||
|
||||
static int opINCDEC_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;
|
||||
|
||||
if (rmdat&0x38)
|
||||
{
|
||||
seteab(temp - 1); if (cpu_state.abrt) return 1;
|
||||
setsub8nc(temp, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
seteab(temp + 1); if (cpu_state.abrt) return 1;
|
||||
setadd8nc(temp, 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);
|
||||
return 0;
|
||||
}
|
||||
static int opINCDEC_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;
|
||||
|
||||
if (rmdat&0x38)
|
||||
{
|
||||
seteab(temp - 1); if (cpu_state.abrt) return 1;
|
||||
setsub8nc(temp, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
seteab(temp + 1); if (cpu_state.abrt) return 1;
|
||||
setadd8nc(temp, 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);
|
||||
return 0;
|
||||
}
|
||||
91
src/cpu_common/x86_ops_int.h
Normal file
91
src/cpu_common/x86_ops_int.h
Normal file
@@ -0,0 +1,91 @@
|
||||
static int opINT3(uint32_t fetchdat)
|
||||
{
|
||||
int cycles_old = cycles; UN_USED(cycles_old);
|
||||
if ((cr0 & 1) && (cpu_state.eflags & VM_FLAG) && (IOPL != 3))
|
||||
{
|
||||
x86gpf(NULL,0);
|
||||
return 1;
|
||||
}
|
||||
x86_int_sw(3);
|
||||
CLOCK_CYCLES((is486) ? 44 : 59);
|
||||
PREFETCH_RUN(cycles_old-cycles, 1, -1, 0,0,0,0, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int opINT1(uint32_t fetchdat)
|
||||
{
|
||||
int cycles_old = cycles; UN_USED(cycles_old);
|
||||
if ((cr0 & 1) && (cpu_state.eflags & VM_FLAG) && (IOPL != 3))
|
||||
{
|
||||
x86gpf(NULL,0);
|
||||
return 1;
|
||||
}
|
||||
x86_int_sw(1);
|
||||
CLOCK_CYCLES((is486) ? 44 : 59);
|
||||
PREFETCH_RUN(cycles_old-cycles, 1, -1, 0,0,0,0, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int opINT(uint32_t fetchdat)
|
||||
{
|
||||
int cycles_old = cycles; UN_USED(cycles_old);
|
||||
uint8_t temp = getbytef();
|
||||
|
||||
if ((cr0 & 1) && (cpu_state.eflags & VM_FLAG) && (IOPL != 3))
|
||||
{
|
||||
if (cr4 & CR4_VME)
|
||||
{
|
||||
uint16_t t;
|
||||
uint8_t d;
|
||||
|
||||
cpl_override = 1;
|
||||
t = readmemw(tr.base, 0x66) - 32;
|
||||
cpl_override = 0;
|
||||
if (cpu_state.abrt) return 1;
|
||||
|
||||
t += (temp >> 3);
|
||||
if (t <= tr.limit)
|
||||
{
|
||||
cpl_override = 1;
|
||||
d = readmemb(tr.base, t);// + (temp >> 3));
|
||||
cpl_override = 0;
|
||||
if (cpu_state.abrt) return 1;
|
||||
|
||||
if (!(d & (1 << (temp & 7))))
|
||||
{
|
||||
x86_int_sw_rm(temp);
|
||||
PREFETCH_RUN(cycles_old-cycles, 2, -1, 0,0,0,0, 0);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
x86gpf(NULL,0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
x86_int_sw(temp);
|
||||
PREFETCH_RUN(cycles_old-cycles, 2, -1, 0,0,0,0, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int opINTO(uint32_t fetchdat)
|
||||
{
|
||||
int cycles_old = cycles; UN_USED(cycles_old);
|
||||
|
||||
if ((cr0 & 1) && (cpu_state.eflags & VM_FLAG) && (IOPL != 3))
|
||||
{
|
||||
x86gpf(NULL,0);
|
||||
return 1;
|
||||
}
|
||||
if (VF_SET())
|
||||
{
|
||||
cpu_state.oldpc = cpu_state.pc;
|
||||
x86_int_sw(4);
|
||||
PREFETCH_RUN(cycles_old-cycles, 1, -1, 0,0,0,0, 0);
|
||||
return 1;
|
||||
}
|
||||
CLOCK_CYCLES(3);
|
||||
PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
146
src/cpu_common/x86_ops_io.h
Normal file
146
src/cpu_common/x86_ops_io.h
Normal file
@@ -0,0 +1,146 @@
|
||||
static int opIN_AL_imm(uint32_t fetchdat)
|
||||
{
|
||||
uint16_t port = (uint16_t)getbytef();
|
||||
check_io_perm(port);
|
||||
AL = inb(port);
|
||||
CLOCK_CYCLES(12);
|
||||
PREFETCH_RUN(12, 2, -1, 1,0,0,0, 0);
|
||||
if (nmi && nmi_enable && nmi_mask)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
static int opIN_AX_imm(uint32_t fetchdat)
|
||||
{
|
||||
uint16_t port = (uint16_t)getbytef();
|
||||
check_io_perm(port);
|
||||
check_io_perm(port + 1);
|
||||
AX = inw(port);
|
||||
CLOCK_CYCLES(12);
|
||||
PREFETCH_RUN(12, 2, -1, 1,0,0,0, 0);
|
||||
if (nmi && nmi_enable && nmi_mask)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
static int opIN_EAX_imm(uint32_t fetchdat)
|
||||
{
|
||||
uint16_t port = (uint16_t)getbytef();
|
||||
check_io_perm(port);
|
||||
check_io_perm(port + 1);
|
||||
check_io_perm(port + 2);
|
||||
check_io_perm(port + 3);
|
||||
EAX = inl(port);
|
||||
CLOCK_CYCLES(12);
|
||||
PREFETCH_RUN(12, 2, -1, 0,1,0,0, 0);
|
||||
if (nmi && nmi_enable && nmi_mask)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opOUT_AL_imm(uint32_t fetchdat)
|
||||
{
|
||||
uint16_t port = (uint16_t)getbytef();
|
||||
check_io_perm(port);
|
||||
outb(port, AL);
|
||||
CLOCK_CYCLES(10);
|
||||
PREFETCH_RUN(10, 2, -1, 0,0,1,0, 0);
|
||||
if (port == 0x64)
|
||||
return x86_was_reset;
|
||||
if (nmi && nmi_enable && nmi_mask)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
static int opOUT_AX_imm(uint32_t fetchdat)
|
||||
{
|
||||
uint16_t port = (uint16_t)getbytef();
|
||||
check_io_perm(port);
|
||||
check_io_perm(port + 1);
|
||||
outw(port, AX);
|
||||
CLOCK_CYCLES(10);
|
||||
PREFETCH_RUN(10, 2, -1, 0,0,1,0, 0);
|
||||
if (nmi && nmi_enable && nmi_mask)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
static int opOUT_EAX_imm(uint32_t fetchdat)
|
||||
{
|
||||
uint16_t port = (uint16_t)getbytef();
|
||||
check_io_perm(port);
|
||||
check_io_perm(port + 1);
|
||||
check_io_perm(port + 2);
|
||||
check_io_perm(port + 3);
|
||||
outl(port, EAX);
|
||||
CLOCK_CYCLES(10);
|
||||
PREFETCH_RUN(10, 2, -1, 0,0,0,1, 0);
|
||||
if (nmi && nmi_enable && nmi_mask)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opIN_AL_DX(uint32_t fetchdat)
|
||||
{
|
||||
check_io_perm(DX);
|
||||
AL = inb(DX);
|
||||
CLOCK_CYCLES(12);
|
||||
PREFETCH_RUN(12, 1, -1, 1,0,0,0, 0);
|
||||
if (nmi && nmi_enable && nmi_mask)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
static int opIN_AX_DX(uint32_t fetchdat)
|
||||
{
|
||||
check_io_perm(DX);
|
||||
check_io_perm(DX + 1);
|
||||
AX = inw(DX);
|
||||
CLOCK_CYCLES(12);
|
||||
PREFETCH_RUN(12, 1, -1, 1,0,0,0, 0);
|
||||
if (nmi && nmi_enable && nmi_mask)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
static int opIN_EAX_DX(uint32_t fetchdat)
|
||||
{
|
||||
check_io_perm(DX);
|
||||
check_io_perm(DX + 1);
|
||||
check_io_perm(DX + 2);
|
||||
check_io_perm(DX + 3);
|
||||
EAX = inl(DX);
|
||||
CLOCK_CYCLES(12);
|
||||
PREFETCH_RUN(12, 1, -1, 0,1,0,0, 0);
|
||||
if (nmi && nmi_enable && nmi_mask)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opOUT_AL_DX(uint32_t fetchdat)
|
||||
{
|
||||
check_io_perm(DX);
|
||||
outb(DX, AL);
|
||||
CLOCK_CYCLES(11);
|
||||
PREFETCH_RUN(11, 1, -1, 0,0,1,0, 0);
|
||||
if (nmi && nmi_enable && nmi_mask)
|
||||
return 1;
|
||||
return x86_was_reset;
|
||||
}
|
||||
static int opOUT_AX_DX(uint32_t fetchdat)
|
||||
{
|
||||
check_io_perm(DX);
|
||||
check_io_perm(DX + 1);
|
||||
outw(DX, AX);
|
||||
CLOCK_CYCLES(11);
|
||||
PREFETCH_RUN(11, 1, -1, 0,0,1,0, 0);
|
||||
if (nmi && nmi_enable && nmi_mask)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
static int opOUT_EAX_DX(uint32_t fetchdat)
|
||||
{
|
||||
check_io_perm(DX);
|
||||
check_io_perm(DX + 1);
|
||||
check_io_perm(DX + 2);
|
||||
check_io_perm(DX + 3);
|
||||
outl(DX, EAX);
|
||||
PREFETCH_RUN(11, 1, -1, 0,0,0,1, 0);
|
||||
if (nmi && nmi_enable && nmi_mask)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
381
src/cpu_common/x86_ops_jump.h
Normal file
381
src/cpu_common/x86_ops_jump.h
Normal file
@@ -0,0 +1,381 @@
|
||||
#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 opJ(condition) \
|
||||
static int opJ ## condition(uint32_t fetchdat) \
|
||||
{ \
|
||||
int8_t offset = (int8_t)getbytef(); \
|
||||
CLOCK_CYCLES(timing_bnt); \
|
||||
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); \
|
||||
PREFETCH_FLUSH(); \
|
||||
return 1; \
|
||||
} \
|
||||
PREFETCH_RUN(timing_bnt, 2, -1, 0,0,0,0, 0); \
|
||||
return 0; \
|
||||
} \
|
||||
\
|
||||
static int opJ ## condition ## _w(uint32_t fetchdat) \
|
||||
{ \
|
||||
int16_t offset = (int16_t)getwordf(); \
|
||||
CLOCK_CYCLES(timing_bnt); \
|
||||
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); \
|
||||
PREFETCH_FLUSH(); \
|
||||
return 1; \
|
||||
} \
|
||||
PREFETCH_RUN(timing_bnt, 3, -1, 0,0,0,0, 0); \
|
||||
return 0; \
|
||||
} \
|
||||
\
|
||||
static int opJ ## condition ## _l(uint32_t fetchdat) \
|
||||
{ \
|
||||
uint32_t offset = getlong(); if (cpu_state.abrt) return 1; \
|
||||
CLOCK_CYCLES(timing_bnt); \
|
||||
if (cond_ ## condition) \
|
||||
{ \
|
||||
cpu_state.pc += offset; \
|
||||
CLOCK_CYCLES_ALWAYS(timing_bt); \
|
||||
CPU_BLOCK_END(); \
|
||||
PREFETCH_RUN(timing_bt+timing_bnt, 5, -1, 0,0,0,0, 0); \
|
||||
PREFETCH_FLUSH(); \
|
||||
return 1; \
|
||||
} \
|
||||
PREFETCH_RUN(timing_bnt, 5, -1, 0,0,0,0, 0); \
|
||||
return 0; \
|
||||
} \
|
||||
|
||||
opJ(O)
|
||||
opJ(NO)
|
||||
opJ(B)
|
||||
opJ(NB)
|
||||
opJ(E)
|
||||
opJ(NE)
|
||||
opJ(BE)
|
||||
opJ(NBE)
|
||||
opJ(S)
|
||||
opJ(NS)
|
||||
opJ(P)
|
||||
opJ(NP)
|
||||
opJ(L)
|
||||
opJ(NL)
|
||||
opJ(LE)
|
||||
opJ(NLE)
|
||||
|
||||
|
||||
|
||||
static int opLOOPNE_w(uint32_t fetchdat)
|
||||
{
|
||||
int8_t offset = (int8_t)getbytef();
|
||||
CX--;
|
||||
CLOCK_CYCLES((is486) ? 7 : 11);
|
||||
PREFETCH_RUN(11, 2, -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;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static int opLOOPNE_l(uint32_t fetchdat)
|
||||
{
|
||||
int8_t offset = (int8_t)getbytef();
|
||||
ECX--;
|
||||
CLOCK_CYCLES((is486) ? 7 : 11);
|
||||
PREFETCH_RUN(11, 2, -1, 0,0,0,0, 0);
|
||||
if (ECX && !ZF_SET())
|
||||
{
|
||||
cpu_state.pc += offset;
|
||||
if (!(cpu_state.op32 & 0x100))
|
||||
cpu_state.pc &= 0xffff;
|
||||
CPU_BLOCK_END();
|
||||
PREFETCH_FLUSH();
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opLOOPE_w(uint32_t fetchdat)
|
||||
{
|
||||
int8_t offset = (int8_t)getbytef();
|
||||
CX--;
|
||||
CLOCK_CYCLES((is486) ? 7 : 11);
|
||||
PREFETCH_RUN(11, 2, -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;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static int opLOOPE_l(uint32_t fetchdat)
|
||||
{
|
||||
int8_t offset = (int8_t)getbytef();
|
||||
ECX--;
|
||||
CLOCK_CYCLES((is486) ? 7 : 11);
|
||||
PREFETCH_RUN(11, 2, -1, 0,0,0,0, 0);
|
||||
if (ECX && ZF_SET())
|
||||
{
|
||||
cpu_state.pc += offset;
|
||||
if (!(cpu_state.op32 & 0x100))
|
||||
cpu_state.pc &= 0xffff;
|
||||
CPU_BLOCK_END();
|
||||
PREFETCH_FLUSH();
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opLOOP_w(uint32_t fetchdat)
|
||||
{
|
||||
int8_t offset = (int8_t)getbytef();
|
||||
CX--;
|
||||
CLOCK_CYCLES((is486) ? 7 : 11);
|
||||
PREFETCH_RUN(11, 2, -1, 0,0,0,0, 0);
|
||||
if (CX)
|
||||
{
|
||||
cpu_state.pc += offset;
|
||||
if (!(cpu_state.op32 & 0x100))
|
||||
cpu_state.pc &= 0xffff;
|
||||
CPU_BLOCK_END();
|
||||
PREFETCH_FLUSH();
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static int opLOOP_l(uint32_t fetchdat)
|
||||
{
|
||||
int8_t offset = (int8_t)getbytef();
|
||||
ECX--;
|
||||
CLOCK_CYCLES((is486) ? 7 : 11);
|
||||
PREFETCH_RUN(11, 2, -1, 0,0,0,0, 0);
|
||||
if (ECX)
|
||||
{
|
||||
cpu_state.pc += offset;
|
||||
if (!(cpu_state.op32 & 0x100))
|
||||
cpu_state.pc &= 0xffff;
|
||||
CPU_BLOCK_END();
|
||||
PREFETCH_FLUSH();
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opJCXZ(uint32_t fetchdat)
|
||||
{
|
||||
int8_t offset = (int8_t)getbytef();
|
||||
CLOCK_CYCLES(5);
|
||||
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);
|
||||
PREFETCH_FLUSH();
|
||||
return 1;
|
||||
}
|
||||
PREFETCH_RUN(5, 2, -1, 0,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opJECXZ(uint32_t fetchdat)
|
||||
{
|
||||
int8_t offset = (int8_t)getbytef();
|
||||
CLOCK_CYCLES(5);
|
||||
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);
|
||||
PREFETCH_FLUSH();
|
||||
return 1;
|
||||
}
|
||||
PREFETCH_RUN(5, 2, -1, 0,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int opJMP_r8(uint32_t fetchdat)
|
||||
{
|
||||
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);
|
||||
PREFETCH_FLUSH();
|
||||
return 0;
|
||||
}
|
||||
static int opJMP_r16(uint32_t fetchdat)
|
||||
{
|
||||
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);
|
||||
PREFETCH_FLUSH();
|
||||
return 0;
|
||||
}
|
||||
static int opJMP_r32(uint32_t fetchdat)
|
||||
{
|
||||
int32_t offset = (int32_t)getlong(); if (cpu_state.abrt) return 1;
|
||||
cpu_state.pc += offset;
|
||||
CPU_BLOCK_END();
|
||||
CLOCK_CYCLES((is486) ? 3 : 7);
|
||||
PREFETCH_RUN(7, 5, -1, 0,0,0,0, 0);
|
||||
PREFETCH_FLUSH();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opJMP_far_a16(uint32_t fetchdat)
|
||||
{
|
||||
uint16_t addr, seg;
|
||||
uint32_t old_pc;
|
||||
addr = getwordf();
|
||||
seg = getword(); if (cpu_state.abrt) return 1;
|
||||
old_pc = cpu_state.pc;
|
||||
cpu_state.pc = addr;
|
||||
loadcsjmp(seg, old_pc);
|
||||
CPU_BLOCK_END();
|
||||
PREFETCH_RUN(11, 5, -1, 0,0,0,0, 0);
|
||||
PREFETCH_FLUSH();
|
||||
return 0;
|
||||
}
|
||||
static int opJMP_far_a32(uint32_t fetchdat)
|
||||
{
|
||||
uint16_t seg;
|
||||
uint32_t addr, old_pc;
|
||||
addr = getlong();
|
||||
seg = getword(); if (cpu_state.abrt) return 1;
|
||||
old_pc = cpu_state.pc;
|
||||
cpu_state.pc = addr;
|
||||
loadcsjmp(seg, old_pc);
|
||||
CPU_BLOCK_END();
|
||||
PREFETCH_RUN(11, 7, -1, 0,0,0,0, 0);
|
||||
PREFETCH_FLUSH();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opCALL_r16(uint32_t fetchdat)
|
||||
{
|
||||
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);
|
||||
PREFETCH_FLUSH();
|
||||
return 0;
|
||||
}
|
||||
static int opCALL_r32(uint32_t fetchdat)
|
||||
{
|
||||
int32_t addr = getlong(); if (cpu_state.abrt) return 1;
|
||||
PUSH_L(cpu_state.pc);
|
||||
cpu_state.pc += addr;
|
||||
CPU_BLOCK_END();
|
||||
CLOCK_CYCLES((is486) ? 3 : 7);
|
||||
PREFETCH_RUN(7, 5, -1, 0,0,0,1, 0);
|
||||
PREFETCH_FLUSH();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opRET_w(uint32_t fetchdat)
|
||||
{
|
||||
uint16_t ret;
|
||||
|
||||
ret = POP_W(); if (cpu_state.abrt) return 1;
|
||||
cpu_state.pc = ret;
|
||||
CPU_BLOCK_END();
|
||||
|
||||
CLOCK_CYCLES((is486) ? 5 : 10);
|
||||
PREFETCH_RUN(10, 1, -1, 1,0,0,0, 0);
|
||||
PREFETCH_FLUSH();
|
||||
return 0;
|
||||
}
|
||||
static int opRET_l(uint32_t fetchdat)
|
||||
{
|
||||
uint32_t ret;
|
||||
|
||||
ret = POP_L(); if (cpu_state.abrt) return 1;
|
||||
cpu_state.pc = ret;
|
||||
CPU_BLOCK_END();
|
||||
|
||||
CLOCK_CYCLES((is486) ? 5 : 10);
|
||||
PREFETCH_RUN(10, 1, -1, 0,1,0,0, 0);
|
||||
PREFETCH_FLUSH();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opRET_w_imm(uint32_t fetchdat)
|
||||
{
|
||||
uint16_t ret;
|
||||
uint16_t offset = getwordf();
|
||||
|
||||
ret = POP_W(); if (cpu_state.abrt) return 1;
|
||||
if (stack32) ESP += offset;
|
||||
else SP += offset;
|
||||
cpu_state.pc = ret;
|
||||
CPU_BLOCK_END();
|
||||
|
||||
CLOCK_CYCLES((is486) ? 5 : 10);
|
||||
PREFETCH_RUN(10, 5, -1, 1,0,0,0, 0);
|
||||
PREFETCH_FLUSH();
|
||||
return 0;
|
||||
}
|
||||
static int opRET_l_imm(uint32_t fetchdat)
|
||||
{
|
||||
uint32_t ret;
|
||||
uint16_t offset = getwordf();
|
||||
|
||||
ret = POP_L(); if (cpu_state.abrt) return 1;
|
||||
if (stack32) ESP += offset;
|
||||
else SP += offset;
|
||||
cpu_state.pc = ret;
|
||||
CPU_BLOCK_END();
|
||||
|
||||
CLOCK_CYCLES((is486) ? 5 : 10);
|
||||
PREFETCH_RUN(10, 5, -1, 0,1,0,0, 0);
|
||||
PREFETCH_FLUSH();
|
||||
return 0;
|
||||
}
|
||||
|
||||
973
src/cpu_common/x86_ops_misc.h
Normal file
973
src/cpu_common/x86_ops_misc.h
Normal file
@@ -0,0 +1,973 @@
|
||||
static int opCBW(uint32_t fetchdat)
|
||||
{
|
||||
AH = (AL & 0x80) ? 0xff : 0;
|
||||
CLOCK_CYCLES(3);
|
||||
PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opCWDE(uint32_t fetchdat)
|
||||
{
|
||||
EAX = (AX & 0x8000) ? (0xffff0000 | AX) : AX;
|
||||
CLOCK_CYCLES(3);
|
||||
PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opCWD(uint32_t fetchdat)
|
||||
{
|
||||
DX = (AX & 0x8000) ? 0xFFFF : 0;
|
||||
CLOCK_CYCLES(2);
|
||||
PREFETCH_RUN(2, 1, -1, 0,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opCDQ(uint32_t fetchdat)
|
||||
{
|
||||
EDX = (EAX & 0x80000000) ? 0xffffffff : 0;
|
||||
CLOCK_CYCLES(2);
|
||||
PREFETCH_RUN(2, 1, -1, 0,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opNOP(uint32_t fetchdat)
|
||||
{
|
||||
CLOCK_CYCLES((is486) ? 1 : 3);
|
||||
PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opSETALC(uint32_t fetchdat)
|
||||
{
|
||||
AL = (CF_SET()) ? 0xff : 0;
|
||||
CLOCK_CYCLES(timing_rr);
|
||||
PREFETCH_RUN(timing_rr, 1, -1, 0,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int opF6_a16(uint32_t fetchdat)
|
||||
{
|
||||
int tempws, tempws2 = 0;
|
||||
uint16_t tempw, src16;
|
||||
uint8_t src, dst;
|
||||
int8_t temps;
|
||||
|
||||
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;
|
||||
switch (rmdat & 0x38)
|
||||
{
|
||||
case 0x00: /*TEST b,#8*/
|
||||
case 0x08:
|
||||
src = readmemb(cs, cpu_state.pc); cpu_state.pc++; if (cpu_state.abrt) return 1;
|
||||
setznp8(src & dst);
|
||||
if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2);
|
||||
else CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5);
|
||||
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);
|
||||
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 0x20: /*MUL AL,b*/
|
||||
AX = AL * dst;
|
||||
flags_rebuild();
|
||||
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;
|
||||
case 0x28: /*IMUL AL,b*/
|
||||
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) 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;
|
||||
case 0x30: /*DIV AL,b*/
|
||||
src16 = AX;
|
||||
if (dst) tempw = src16 / dst;
|
||||
if (dst && !(tempw & 0xff00))
|
||||
{
|
||||
AH = src16 % dst;
|
||||
AL = (src16 / dst) &0xff;
|
||||
if (!cpu_iscyrix)
|
||||
{
|
||||
flags_rebuild();
|
||||
cpu_state.flags |= 0x8D5; /*Not a Cyrix*/
|
||||
cpu_state.flags &= ~1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
x86_int(0);
|
||||
return 1;
|
||||
}
|
||||
CLOCK_CYCLES((is486 && !cpu_iscyrix) ? 16 : 14);
|
||||
PREFETCH_RUN((is486 && !cpu_iscyrix) ? 16 : 14, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0);
|
||||
break;
|
||||
case 0x38: /*IDIV AL,b*/
|
||||
tempws = (int)(int16_t)AX;
|
||||
if (dst != 0) tempws2 = tempws / (int)((int8_t)dst);
|
||||
temps = tempws2 & 0xff;
|
||||
if (dst && ((int)temps == tempws2))
|
||||
{
|
||||
AH = (tempws % (int)((int8_t)dst)) & 0xff;
|
||||
AL = tempws2 & 0xff;
|
||||
if (!cpu_iscyrix)
|
||||
{
|
||||
flags_rebuild();
|
||||
cpu_state.flags|=0x8D5; /*Not a Cyrix*/
|
||||
cpu_state.flags &= ~1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
x86_int(0);
|
||||
return 1;
|
||||
}
|
||||
CLOCK_CYCLES(19);
|
||||
PREFETCH_RUN(19, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
x86illegal();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static int opF6_a32(uint32_t fetchdat)
|
||||
{
|
||||
int tempws, tempws2 = 0;
|
||||
uint16_t tempw, src16;
|
||||
uint8_t src, dst;
|
||||
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)
|
||||
{
|
||||
case 0x00: /*TEST b,#8*/
|
||||
case 0x08:
|
||||
src = readmemb(cs, cpu_state.pc); cpu_state.pc++; if (cpu_state.abrt) return 1;
|
||||
setznp8(src & dst);
|
||||
if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2);
|
||||
else CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5);
|
||||
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);
|
||||
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 0x20: /*MUL AL,b*/
|
||||
AX = AL * dst;
|
||||
flags_rebuild();
|
||||
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;
|
||||
case 0x28: /*IMUL AL,b*/
|
||||
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) 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;
|
||||
case 0x30: /*DIV AL,b*/
|
||||
src16 = AX;
|
||||
if (dst) tempw = src16 / dst;
|
||||
if (dst && !(tempw & 0xff00))
|
||||
{
|
||||
AH = src16 % dst;
|
||||
AL = (src16 / dst) &0xff;
|
||||
if (!cpu_iscyrix)
|
||||
{
|
||||
flags_rebuild();
|
||||
cpu_state.flags |= 0x8D5; /*Not a Cyrix*/
|
||||
cpu_state.flags &= ~1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
x86_int(0);
|
||||
return 1;
|
||||
}
|
||||
CLOCK_CYCLES((is486 && !cpu_iscyrix) ? 16 : 14);
|
||||
PREFETCH_RUN((is486 && !cpu_iscyrix) ? 16 : 14, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1);
|
||||
break;
|
||||
case 0x38: /*IDIV AL,b*/
|
||||
tempws = (int)(int16_t)AX;
|
||||
if (dst != 0) tempws2 = tempws / (int)((int8_t)dst);
|
||||
temps = tempws2 & 0xff;
|
||||
if (dst && ((int)temps == tempws2))
|
||||
{
|
||||
AH = (tempws % (int)((int8_t)dst)) & 0xff;
|
||||
AL = tempws2 & 0xff;
|
||||
if (!cpu_iscyrix)
|
||||
{
|
||||
flags_rebuild();
|
||||
cpu_state.flags |= 0x8D5; /*Not a Cyrix*/
|
||||
cpu_state.flags &= ~1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
x86_int(0);
|
||||
return 1;
|
||||
}
|
||||
CLOCK_CYCLES(19);
|
||||
PREFETCH_RUN(19, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1);
|
||||
break;
|
||||
|
||||
default:
|
||||
x86illegal();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int opF7_w_a16(uint32_t fetchdat)
|
||||
{
|
||||
uint32_t templ, templ2;
|
||||
int tempws, tempws2 = 0;
|
||||
int16_t temps16;
|
||||
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)
|
||||
{
|
||||
case 0x00: /*TEST w*/
|
||||
case 0x08:
|
||||
src = getword(); if (cpu_state.abrt) return 1;
|
||||
setznp16(src & dst);
|
||||
if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2);
|
||||
else CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5);
|
||||
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);
|
||||
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 0x20: /*MUL AX,w*/
|
||||
templ = AX * dst;
|
||||
AX = templ & 0xFFFF;
|
||||
DX = templ >> 16;
|
||||
flags_rebuild();
|
||||
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;
|
||||
case 0x28: /*IMUL AX,w*/
|
||||
templ = (int)((int16_t)AX) * (int)((int16_t)dst);
|
||||
AX = templ & 0xFFFF;
|
||||
DX = templ >> 16;
|
||||
flags_rebuild();
|
||||
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;
|
||||
case 0x30: /*DIV AX,w*/
|
||||
templ = (DX << 16) | AX;
|
||||
if (dst) templ2 = templ / dst;
|
||||
if (dst && !(templ2 & 0xffff0000))
|
||||
{
|
||||
DX = templ % dst;
|
||||
AX = (templ / dst) & 0xffff;
|
||||
if (!cpu_iscyrix) setznp16(AX); /*Not a Cyrix*/
|
||||
}
|
||||
else
|
||||
{
|
||||
x86_int(0);
|
||||
return 1;
|
||||
}
|
||||
CLOCK_CYCLES((is486 && !cpu_iscyrix) ? 24 : 22);
|
||||
PREFETCH_RUN((is486 && !cpu_iscyrix) ? 24 : 22, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0);
|
||||
break;
|
||||
case 0x38: /*IDIV AX,w*/
|
||||
tempws = (int)((DX << 16)|AX);
|
||||
if (dst) tempws2 = tempws / (int)((int16_t)dst);
|
||||
temps16 = tempws2 & 0xffff;
|
||||
if ((dst != 0) && ((int)temps16 == tempws2))
|
||||
{
|
||||
DX = tempws % (int)((int16_t)dst);
|
||||
AX = tempws2 & 0xffff;
|
||||
if (!cpu_iscyrix) setznp16(AX); /*Not a Cyrix*/
|
||||
}
|
||||
else
|
||||
{
|
||||
x86_int(0);
|
||||
return 1;
|
||||
}
|
||||
CLOCK_CYCLES(27);
|
||||
PREFETCH_RUN(27, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
x86illegal();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static int opF7_w_a32(uint32_t fetchdat)
|
||||
{
|
||||
uint32_t templ, templ2;
|
||||
int tempws, tempws2 = 1;
|
||||
int16_t temps16;
|
||||
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)
|
||||
{
|
||||
case 0x00: /*TEST w*/
|
||||
case 0x08:
|
||||
src = getword(); if (cpu_state.abrt) return 1;
|
||||
setznp16(src & dst);
|
||||
if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2);
|
||||
else CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5);
|
||||
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);
|
||||
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 0x20: /*MUL AX,w*/
|
||||
templ = AX * dst;
|
||||
AX = templ & 0xFFFF;
|
||||
DX = templ >> 16;
|
||||
flags_rebuild();
|
||||
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;
|
||||
case 0x28: /*IMUL AX,w*/
|
||||
templ = (int)((int16_t)AX) * (int)((int16_t)dst);
|
||||
AX = templ & 0xFFFF;
|
||||
DX = templ >> 16;
|
||||
flags_rebuild();
|
||||
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;
|
||||
case 0x30: /*DIV AX,w*/
|
||||
templ = (DX << 16) | AX;
|
||||
if (dst) templ2 = templ / dst;
|
||||
if (dst && !(templ2 & 0xffff0000))
|
||||
{
|
||||
DX = templ % dst;
|
||||
AX = (templ / dst) & 0xffff;
|
||||
if (!cpu_iscyrix) setznp16(AX); /*Not a Cyrix*/
|
||||
}
|
||||
else
|
||||
{
|
||||
// fatal("DIVw BY 0 %04X:%04X %i\n",cs>>4,pc,ins);
|
||||
x86_int(0);
|
||||
return 1;
|
||||
}
|
||||
CLOCK_CYCLES((is486 && !cpu_iscyrix) ? 24 : 22);
|
||||
PREFETCH_RUN((is486 && !cpu_iscyrix) ? 24 : 22, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1);
|
||||
break;
|
||||
case 0x38: /*IDIV AX,w*/
|
||||
tempws = (int)((DX << 16)|AX);
|
||||
if (dst) tempws2 = tempws / (int)((int16_t)dst);
|
||||
temps16 = tempws2 & 0xffff;
|
||||
if ((dst != 0) && ((int)temps16 == tempws2))
|
||||
{
|
||||
DX = tempws % (int)((int16_t)dst);
|
||||
AX = tempws2 & 0xffff;
|
||||
if (!cpu_iscyrix) setznp16(AX); /*Not a Cyrix*/
|
||||
}
|
||||
else
|
||||
{
|
||||
x86_int(0);
|
||||
return 1;
|
||||
}
|
||||
CLOCK_CYCLES(27);
|
||||
PREFETCH_RUN(27, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1);
|
||||
break;
|
||||
|
||||
default:
|
||||
x86illegal();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opF7_l_a16(uint32_t fetchdat)
|
||||
{
|
||||
uint64_t temp64;
|
||||
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)
|
||||
{
|
||||
case 0x00: /*TEST l*/
|
||||
case 0x08:
|
||||
src = getlong(); if (cpu_state.abrt) return 1;
|
||||
setznp32(src & dst);
|
||||
if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2);
|
||||
else CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5);
|
||||
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);
|
||||
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 0x20: /*MUL EAX,l*/
|
||||
temp64 = (uint64_t)EAX * (uint64_t)dst;
|
||||
EAX = temp64 & 0xffffffff;
|
||||
EDX = temp64 >> 32;
|
||||
flags_rebuild();
|
||||
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;
|
||||
case 0x28: /*IMUL EAX,l*/
|
||||
temp64 = (int64_t)(int32_t)EAX * (int64_t)(int32_t)dst;
|
||||
EAX = temp64 & 0xffffffff;
|
||||
EDX = temp64 >> 32;
|
||||
flags_rebuild();
|
||||
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;
|
||||
case 0x30: /*DIV EAX,l*/
|
||||
if (divl(dst))
|
||||
return 1;
|
||||
if (!cpu_iscyrix) setznp32(EAX); /*Not a Cyrix*/
|
||||
CLOCK_CYCLES((is486) ? 40 : 38);
|
||||
PREFETCH_RUN(is486 ? 40:38, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 0);
|
||||
break;
|
||||
case 0x38: /*IDIV EAX,l*/
|
||||
if (idivl((int32_t)dst))
|
||||
return 1;
|
||||
if (!cpu_iscyrix) setznp32(EAX); /*Not a Cyrix*/
|
||||
CLOCK_CYCLES(43);
|
||||
PREFETCH_RUN(43, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
x86illegal();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static int opF7_l_a32(uint32_t fetchdat)
|
||||
{
|
||||
uint64_t temp64;
|
||||
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)
|
||||
{
|
||||
case 0x00: /*TEST l*/
|
||||
case 0x08:
|
||||
src = getlong(); if (cpu_state.abrt) return 1;
|
||||
setznp32(src & dst);
|
||||
if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 2);
|
||||
else CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5);
|
||||
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);
|
||||
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 0x20: /*MUL EAX,l*/
|
||||
temp64 = (uint64_t)EAX * (uint64_t)dst;
|
||||
EAX = temp64 & 0xffffffff;
|
||||
EDX = temp64 >> 32;
|
||||
flags_rebuild();
|
||||
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;
|
||||
case 0x28: /*IMUL EAX,l*/
|
||||
temp64 = (int64_t)(int32_t)EAX * (int64_t)(int32_t)dst;
|
||||
EAX = temp64 & 0xffffffff;
|
||||
EDX = temp64 >> 32;
|
||||
flags_rebuild();
|
||||
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;
|
||||
case 0x30: /*DIV EAX,l*/
|
||||
if (divl(dst))
|
||||
return 1;
|
||||
if (!cpu_iscyrix) setznp32(EAX); /*Not a Cyrix*/
|
||||
CLOCK_CYCLES((is486) ? 40 : 38);
|
||||
PREFETCH_RUN(is486 ? 40 : 38, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 1);
|
||||
break;
|
||||
case 0x38: /*IDIV EAX,l*/
|
||||
if (idivl((int32_t)dst))
|
||||
return 1;
|
||||
if (!cpu_iscyrix) setznp32(EAX); /*Not a Cyrix*/
|
||||
CLOCK_CYCLES(43);
|
||||
PREFETCH_RUN(43, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 1);
|
||||
break;
|
||||
|
||||
default:
|
||||
x86illegal();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int opHLT(uint32_t fetchdat)
|
||||
{
|
||||
if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1))
|
||||
{
|
||||
x86gpf(NULL,0);
|
||||
return 1;
|
||||
}
|
||||
if (!((cpu_state.flags & I_FLAG) && pic_intpending))
|
||||
{
|
||||
CLOCK_CYCLES_ALWAYS(100);
|
||||
if (!((cpu_state.flags & I_FLAG) && pic_intpending))
|
||||
cpu_state.pc--;
|
||||
}
|
||||
else
|
||||
CLOCK_CYCLES(5);
|
||||
|
||||
CPU_BLOCK_END();
|
||||
PREFETCH_RUN(100, 1, -1, 0,0,0,0, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int opLOCK(uint32_t fetchdat)
|
||||
{
|
||||
fetchdat = fastreadl(cs + cpu_state.pc);
|
||||
if (cpu_state.abrt) return 0;
|
||||
cpu_state.pc++;
|
||||
|
||||
ILLEGAL_ON((fetchdat & 0xff) == 0x90);
|
||||
|
||||
CLOCK_CYCLES(4);
|
||||
PREFETCH_PREFIX();
|
||||
return x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int opBOUND_w_a16(uint32_t fetchdat)
|
||||
{
|
||||
int16_t low, high;
|
||||
|
||||
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;
|
||||
|
||||
if (((int16_t)cpu_state.regs[cpu_reg].w < low) || ((int16_t)cpu_state.regs[cpu_reg].w > high))
|
||||
{
|
||||
x86_int(5);
|
||||
return 1;
|
||||
}
|
||||
|
||||
CLOCK_CYCLES(is486 ? 7 : 10);
|
||||
PREFETCH_RUN(is486 ? 7 : 10, 2, rmdat, 2,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opBOUND_w_a32(uint32_t fetchdat)
|
||||
{
|
||||
int16_t low, high;
|
||||
|
||||
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;
|
||||
|
||||
if (((int16_t)cpu_state.regs[cpu_reg].w < low) || ((int16_t)cpu_state.regs[cpu_reg].w > high))
|
||||
{
|
||||
x86_int(5);
|
||||
return 1;
|
||||
}
|
||||
|
||||
CLOCK_CYCLES(is486 ? 7 : 10);
|
||||
PREFETCH_RUN(is486 ? 7 : 10, 2, rmdat, 2,0,0,0, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opBOUND_l_a16(uint32_t fetchdat)
|
||||
{
|
||||
int32_t low, high;
|
||||
|
||||
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;
|
||||
|
||||
if (((int32_t)cpu_state.regs[cpu_reg].l < low) || ((int32_t)cpu_state.regs[cpu_reg].l > high))
|
||||
{
|
||||
x86_int(5);
|
||||
return 1;
|
||||
}
|
||||
|
||||
CLOCK_CYCLES(is486 ? 7 : 10);
|
||||
PREFETCH_RUN(is486 ? 7 : 10, 2, rmdat, 1,1,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opBOUND_l_a32(uint32_t fetchdat)
|
||||
{
|
||||
int32_t low, high;
|
||||
|
||||
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;
|
||||
|
||||
if (((int32_t)cpu_state.regs[cpu_reg].l < low) || ((int32_t)cpu_state.regs[cpu_reg].l > high))
|
||||
{
|
||||
x86_int(5);
|
||||
return 1;
|
||||
}
|
||||
|
||||
CLOCK_CYCLES(is486 ? 7 : 10);
|
||||
PREFETCH_RUN(is486 ? 7 : 10, 2, rmdat, 1,1,0,0, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int opCLTS(uint32_t fetchdat)
|
||||
{
|
||||
if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1))
|
||||
{
|
||||
x86gpf(NULL,0);
|
||||
return 1;
|
||||
}
|
||||
cr0 &= ~8;
|
||||
CLOCK_CYCLES(5);
|
||||
PREFETCH_RUN(5, 1, -1, 0,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opINVD(uint32_t fetchdat)
|
||||
{
|
||||
if (!is486)
|
||||
{
|
||||
x86illegal();
|
||||
return 1;
|
||||
}
|
||||
CLOCK_CYCLES(1000);
|
||||
CPU_BLOCK_END();
|
||||
return 0;
|
||||
}
|
||||
static int opWBINVD(uint32_t fetchdat)
|
||||
{
|
||||
if (!is486)
|
||||
{
|
||||
x86illegal();
|
||||
return 1;
|
||||
}
|
||||
CLOCK_CYCLES(10000);
|
||||
CPU_BLOCK_END();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opLOADALL(uint32_t fetchdat)
|
||||
{
|
||||
if (CPL && (cr0&1))
|
||||
{
|
||||
x86gpf(NULL,0);
|
||||
return 1;
|
||||
}
|
||||
msw = (msw & 1) | readmemw(0, 0x806);
|
||||
cpu_state.flags = (readmemw(0, 0x818) & 0xffd5) | 2;
|
||||
flags_extract();
|
||||
tr.seg = readmemw(0, 0x816);
|
||||
cpu_state.pc = readmemw(0, 0x81A);
|
||||
ldt.seg = readmemw(0, 0x81C);
|
||||
DS = readmemw(0, 0x81E);
|
||||
SS = readmemw(0, 0x820);
|
||||
CS = readmemw(0, 0x822);
|
||||
ES = readmemw(0, 0x824);
|
||||
DI = readmemw(0, 0x826);
|
||||
SI = readmemw(0, 0x828);
|
||||
BP = readmemw(0, 0x82A);
|
||||
SP = readmemw(0, 0x82C);
|
||||
BX = readmemw(0, 0x82E);
|
||||
DX = readmemw(0, 0x830);
|
||||
CX = readmemw(0, 0x832);
|
||||
AX = readmemw(0, 0x834);
|
||||
es = readmemw(0, 0x836) | (readmemb(0, 0x838) << 16);
|
||||
cpu_state.seg_es.access = readmemb(0, 0x839);
|
||||
cpu_state.seg_es.limit = readmemw(0, 0x83A);
|
||||
cs = readmemw(0, 0x83C) | (readmemb(0, 0x83E) << 16);
|
||||
cpu_state.seg_cs.access = readmemb(0, 0x83F);
|
||||
cpu_state.seg_cs.limit = readmemw(0, 0x840);
|
||||
ss = readmemw(0, 0x842) | (readmemb(0, 0x844) << 16);
|
||||
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);
|
||||
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;
|
||||
gdt.base = readmemw(0, 0x84E) | (readmemb(0, 0x850) << 16);
|
||||
gdt.limit = readmemw(0, 0x852);
|
||||
ldt.base = readmemw(0, 0x854) | (readmemb(0, 0x856) << 16);
|
||||
ldt.access = readmemb(0, 0x857);
|
||||
ldt.limit = readmemw(0, 0x858);
|
||||
idt.base = readmemw(0, 0x85A) | (readmemb(0, 0x85C) << 16);
|
||||
idt.limit = readmemw(0, 0x85E);
|
||||
tr.base = readmemw(0, 0x860) | (readmemb(0, 0x862) << 16);
|
||||
tr.access = readmemb(0, 0x863);
|
||||
tr.limit = readmemw(0, 0x864);
|
||||
CLOCK_CYCLES(195);
|
||||
PREFETCH_RUN(195, 1, -1, 51,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void set_segment_limit(x86seg *s, uint8_t segdat3)
|
||||
{
|
||||
if ((s->access & 0x18) != 0x10 || !(s->access & (1 << 2))) /*expand-down*/
|
||||
{
|
||||
s->limit_high = s->limit;
|
||||
s->limit_low = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
s->limit_high = (segdat3 & 0x40) ? 0xffffffff : 0xffff;
|
||||
s->limit_low = s->limit + 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void loadall_load_segment(uint32_t addr, x86seg *s)
|
||||
{
|
||||
uint32_t attrib = readmeml(0, addr);
|
||||
uint32_t segdat3 = (attrib >> 16) & 0xff;
|
||||
s->access = (attrib >> 8) & 0xff;
|
||||
s->base = readmeml(0, addr + 4);
|
||||
s->limit = readmeml(0, addr + 8);
|
||||
|
||||
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;
|
||||
if (stack32)
|
||||
cpu_cur_status |= CPU_STATUS_STACK32;
|
||||
|
||||
set_segment_limit(s, segdat3);
|
||||
|
||||
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 == &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;
|
||||
}
|
||||
}
|
||||
|
||||
static int opLOADALL386(uint32_t fetchdat)
|
||||
{
|
||||
uint32_t la_addr = es + EDI;
|
||||
|
||||
cr0 = readmeml(0, la_addr);
|
||||
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);
|
||||
ESI = readmeml(0, la_addr + 0x10);
|
||||
EBP = readmeml(0, la_addr + 0x14);
|
||||
ESP = readmeml(0, la_addr + 0x18);
|
||||
EBX = readmeml(0, la_addr + 0x1C);
|
||||
EDX = readmeml(0, la_addr + 0x20);
|
||||
ECX = readmeml(0, la_addr + 0x24);
|
||||
EAX = readmeml(0, la_addr + 0x28);
|
||||
dr[6] = readmeml(0, la_addr + 0x2C);
|
||||
dr[7] = readmeml(0, la_addr + 0x30);
|
||||
tr.seg = readmemw(0, la_addr + 0x34);
|
||||
ldt.seg = readmemw(0, la_addr + 0x38);
|
||||
GS = readmemw(0, la_addr + 0x3C);
|
||||
FS = readmemw(0, la_addr + 0x40);
|
||||
DS = readmemw(0, la_addr + 0x44);
|
||||
SS = readmemw(0, la_addr + 0x48);
|
||||
CS = readmemw(0, la_addr + 0x4C);
|
||||
ES = readmemw(0, la_addr + 0x50);
|
||||
|
||||
loadall_load_segment(la_addr + 0x54, &tr);
|
||||
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, &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 opCPUID(uint32_t fetchdat)
|
||||
{
|
||||
if (CPUID)
|
||||
{
|
||||
cpu_CPUID();
|
||||
CLOCK_CYCLES(9);
|
||||
return 0;
|
||||
}
|
||||
cpu_state.pc = cpu_state.oldpc;
|
||||
x86illegal();
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int opRDMSR(uint32_t fetchdat)
|
||||
{
|
||||
if (cpu_has_feature(CPU_FEATURE_MSR))
|
||||
{
|
||||
cpu_RDMSR();
|
||||
CLOCK_CYCLES(9);
|
||||
return 0;
|
||||
}
|
||||
cpu_state.pc = cpu_state.oldpc;
|
||||
x86illegal();
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int opWRMSR(uint32_t fetchdat)
|
||||
{
|
||||
if (cpu_has_feature(CPU_FEATURE_MSR))
|
||||
{
|
||||
cpu_WRMSR();
|
||||
CLOCK_CYCLES(9);
|
||||
return 0;
|
||||
}
|
||||
cpu_state.pc = cpu_state.oldpc;
|
||||
x86illegal();
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int opRSM(uint32_t fetchdat)
|
||||
{
|
||||
if(!in_smm)
|
||||
{
|
||||
leave_smm();
|
||||
if(smi_latched) enter_smm();
|
||||
CPU_BLOCK_END();
|
||||
return 0;
|
||||
}
|
||||
cpu_state.pc = cpu_state.oldpc;
|
||||
x86illegal();
|
||||
return 1;
|
||||
}
|
||||
49
src/cpu_common/x86_ops_mmx.h
Normal file
49
src/cpu_common/x86_ops_mmx.h
Normal file
@@ -0,0 +1,49 @@
|
||||
#define SSATB(val) (((val) < -128) ? -128 : (((val) > 127) ? 127 : (val)))
|
||||
#define SSATW(val) (((val) < -32768) ? -32768 : (((val) > 32767) ? 32767 : (val)))
|
||||
#define USATB(val) (((val) < 0) ? 0 : (((val) > 255) ? 255 : (val)))
|
||||
#define USATW(val) (((val) < 0) ? 0 : (((val) > 65535) ? 65535 : (val)))
|
||||
|
||||
#define MMX_GETSRC() \
|
||||
if (cpu_mod == 3) \
|
||||
{ \
|
||||
src = cpu_state.MM[cpu_rm]; \
|
||||
CLOCK_CYCLES(1); \
|
||||
} \
|
||||
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_has_feature(CPU_FEATURE_MMX)) \
|
||||
{ \
|
||||
cpu_state.pc = cpu_state.oldpc; \
|
||||
x86illegal(); \
|
||||
return 1; \
|
||||
} \
|
||||
if (cr0 & 0xc) \
|
||||
{ \
|
||||
x86_int(7); \
|
||||
return 1; \
|
||||
} \
|
||||
x87_set_mmx()
|
||||
|
||||
static int opEMMS(uint32_t fetchdat)
|
||||
{
|
||||
if (!cpu_has_feature(CPU_FEATURE_MMX))
|
||||
{
|
||||
cpu_state.pc = cpu_state.oldpc;
|
||||
x86illegal();
|
||||
return 1;
|
||||
}
|
||||
if (cr0 & 0xc)
|
||||
{
|
||||
x86_int(7);
|
||||
return 1;
|
||||
}
|
||||
x87_emms();
|
||||
CLOCK_CYCLES(100); /*Guess*/
|
||||
return 0;
|
||||
}
|
||||
629
src/cpu_common/x86_ops_mmx_arith.h
Normal file
629
src/cpu_common/x86_ops_mmx_arith.h
Normal file
@@ -0,0 +1,629 @@
|
||||
static int opPADDB_a16(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_16(fetchdat);
|
||||
MMX_GETSRC();
|
||||
|
||||
cpu_state.MM[cpu_reg].b[0] += src.b[0];
|
||||
cpu_state.MM[cpu_reg].b[1] += src.b[1];
|
||||
cpu_state.MM[cpu_reg].b[2] += src.b[2];
|
||||
cpu_state.MM[cpu_reg].b[3] += src.b[3];
|
||||
cpu_state.MM[cpu_reg].b[4] += src.b[4];
|
||||
cpu_state.MM[cpu_reg].b[5] += src.b[5];
|
||||
cpu_state.MM[cpu_reg].b[6] += src.b[6];
|
||||
cpu_state.MM[cpu_reg].b[7] += src.b[7];
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int opPADDB_a32(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_32(fetchdat);
|
||||
MMX_GETSRC();
|
||||
|
||||
cpu_state.MM[cpu_reg].b[0] += src.b[0];
|
||||
cpu_state.MM[cpu_reg].b[1] += src.b[1];
|
||||
cpu_state.MM[cpu_reg].b[2] += src.b[2];
|
||||
cpu_state.MM[cpu_reg].b[3] += src.b[3];
|
||||
cpu_state.MM[cpu_reg].b[4] += src.b[4];
|
||||
cpu_state.MM[cpu_reg].b[5] += src.b[5];
|
||||
cpu_state.MM[cpu_reg].b[6] += src.b[6];
|
||||
cpu_state.MM[cpu_reg].b[7] += src.b[7];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opPADDW_a16(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_16(fetchdat);
|
||||
MMX_GETSRC();
|
||||
|
||||
cpu_state.MM[cpu_reg].w[0] += src.w[0];
|
||||
cpu_state.MM[cpu_reg].w[1] += src.w[1];
|
||||
cpu_state.MM[cpu_reg].w[2] += src.w[2];
|
||||
cpu_state.MM[cpu_reg].w[3] += src.w[3];
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int opPADDW_a32(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_32(fetchdat);
|
||||
MMX_GETSRC();
|
||||
|
||||
cpu_state.MM[cpu_reg].w[0] += src.w[0];
|
||||
cpu_state.MM[cpu_reg].w[1] += src.w[1];
|
||||
cpu_state.MM[cpu_reg].w[2] += src.w[2];
|
||||
cpu_state.MM[cpu_reg].w[3] += src.w[3];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opPADDD_a16(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_16(fetchdat);
|
||||
MMX_GETSRC();
|
||||
|
||||
cpu_state.MM[cpu_reg].l[0] += src.l[0];
|
||||
cpu_state.MM[cpu_reg].l[1] += src.l[1];
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int opPADDD_a32(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_32(fetchdat);
|
||||
MMX_GETSRC();
|
||||
|
||||
cpu_state.MM[cpu_reg].l[0] += src.l[0];
|
||||
cpu_state.MM[cpu_reg].l[1] += src.l[1];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opPADDSB_a16(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_16(fetchdat);
|
||||
MMX_GETSRC();
|
||||
|
||||
cpu_state.MM[cpu_reg].sb[0] = SSATB(cpu_state.MM[cpu_reg].sb[0] + src.sb[0]);
|
||||
cpu_state.MM[cpu_reg].sb[1] = SSATB(cpu_state.MM[cpu_reg].sb[1] + src.sb[1]);
|
||||
cpu_state.MM[cpu_reg].sb[2] = SSATB(cpu_state.MM[cpu_reg].sb[2] + src.sb[2]);
|
||||
cpu_state.MM[cpu_reg].sb[3] = SSATB(cpu_state.MM[cpu_reg].sb[3] + src.sb[3]);
|
||||
cpu_state.MM[cpu_reg].sb[4] = SSATB(cpu_state.MM[cpu_reg].sb[4] + src.sb[4]);
|
||||
cpu_state.MM[cpu_reg].sb[5] = SSATB(cpu_state.MM[cpu_reg].sb[5] + src.sb[5]);
|
||||
cpu_state.MM[cpu_reg].sb[6] = SSATB(cpu_state.MM[cpu_reg].sb[6] + src.sb[6]);
|
||||
cpu_state.MM[cpu_reg].sb[7] = SSATB(cpu_state.MM[cpu_reg].sb[7] + src.sb[7]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int opPADDSB_a32(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_32(fetchdat);
|
||||
MMX_GETSRC();
|
||||
|
||||
cpu_state.MM[cpu_reg].sb[0] = SSATB(cpu_state.MM[cpu_reg].sb[0] + src.sb[0]);
|
||||
cpu_state.MM[cpu_reg].sb[1] = SSATB(cpu_state.MM[cpu_reg].sb[1] + src.sb[1]);
|
||||
cpu_state.MM[cpu_reg].sb[2] = SSATB(cpu_state.MM[cpu_reg].sb[2] + src.sb[2]);
|
||||
cpu_state.MM[cpu_reg].sb[3] = SSATB(cpu_state.MM[cpu_reg].sb[3] + src.sb[3]);
|
||||
cpu_state.MM[cpu_reg].sb[4] = SSATB(cpu_state.MM[cpu_reg].sb[4] + src.sb[4]);
|
||||
cpu_state.MM[cpu_reg].sb[5] = SSATB(cpu_state.MM[cpu_reg].sb[5] + src.sb[5]);
|
||||
cpu_state.MM[cpu_reg].sb[6] = SSATB(cpu_state.MM[cpu_reg].sb[6] + src.sb[6]);
|
||||
cpu_state.MM[cpu_reg].sb[7] = SSATB(cpu_state.MM[cpu_reg].sb[7] + src.sb[7]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opPADDUSB_a16(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_16(fetchdat);
|
||||
MMX_GETSRC();
|
||||
|
||||
cpu_state.MM[cpu_reg].b[0] = USATB(cpu_state.MM[cpu_reg].b[0] + src.b[0]);
|
||||
cpu_state.MM[cpu_reg].b[1] = USATB(cpu_state.MM[cpu_reg].b[1] + src.b[1]);
|
||||
cpu_state.MM[cpu_reg].b[2] = USATB(cpu_state.MM[cpu_reg].b[2] + src.b[2]);
|
||||
cpu_state.MM[cpu_reg].b[3] = USATB(cpu_state.MM[cpu_reg].b[3] + src.b[3]);
|
||||
cpu_state.MM[cpu_reg].b[4] = USATB(cpu_state.MM[cpu_reg].b[4] + src.b[4]);
|
||||
cpu_state.MM[cpu_reg].b[5] = USATB(cpu_state.MM[cpu_reg].b[5] + src.b[5]);
|
||||
cpu_state.MM[cpu_reg].b[6] = USATB(cpu_state.MM[cpu_reg].b[6] + src.b[6]);
|
||||
cpu_state.MM[cpu_reg].b[7] = USATB(cpu_state.MM[cpu_reg].b[7] + src.b[7]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int opPADDUSB_a32(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_32(fetchdat);
|
||||
MMX_GETSRC();
|
||||
|
||||
cpu_state.MM[cpu_reg].b[0] = USATB(cpu_state.MM[cpu_reg].b[0] + src.b[0]);
|
||||
cpu_state.MM[cpu_reg].b[1] = USATB(cpu_state.MM[cpu_reg].b[1] + src.b[1]);
|
||||
cpu_state.MM[cpu_reg].b[2] = USATB(cpu_state.MM[cpu_reg].b[2] + src.b[2]);
|
||||
cpu_state.MM[cpu_reg].b[3] = USATB(cpu_state.MM[cpu_reg].b[3] + src.b[3]);
|
||||
cpu_state.MM[cpu_reg].b[4] = USATB(cpu_state.MM[cpu_reg].b[4] + src.b[4]);
|
||||
cpu_state.MM[cpu_reg].b[5] = USATB(cpu_state.MM[cpu_reg].b[5] + src.b[5]);
|
||||
cpu_state.MM[cpu_reg].b[6] = USATB(cpu_state.MM[cpu_reg].b[6] + src.b[6]);
|
||||
cpu_state.MM[cpu_reg].b[7] = USATB(cpu_state.MM[cpu_reg].b[7] + src.b[7]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opPADDSW_a16(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_16(fetchdat);
|
||||
MMX_GETSRC();
|
||||
|
||||
cpu_state.MM[cpu_reg].sw[0] = SSATW(cpu_state.MM[cpu_reg].sw[0] + src.sw[0]);
|
||||
cpu_state.MM[cpu_reg].sw[1] = SSATW(cpu_state.MM[cpu_reg].sw[1] + src.sw[1]);
|
||||
cpu_state.MM[cpu_reg].sw[2] = SSATW(cpu_state.MM[cpu_reg].sw[2] + src.sw[2]);
|
||||
cpu_state.MM[cpu_reg].sw[3] = SSATW(cpu_state.MM[cpu_reg].sw[3] + src.sw[3]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int opPADDSW_a32(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_32(fetchdat);
|
||||
MMX_GETSRC();
|
||||
|
||||
cpu_state.MM[cpu_reg].sw[0] = SSATW(cpu_state.MM[cpu_reg].sw[0] + src.sw[0]);
|
||||
cpu_state.MM[cpu_reg].sw[1] = SSATW(cpu_state.MM[cpu_reg].sw[1] + src.sw[1]);
|
||||
cpu_state.MM[cpu_reg].sw[2] = SSATW(cpu_state.MM[cpu_reg].sw[2] + src.sw[2]);
|
||||
cpu_state.MM[cpu_reg].sw[3] = SSATW(cpu_state.MM[cpu_reg].sw[3] + src.sw[3]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opPADDUSW_a16(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_16(fetchdat);
|
||||
MMX_GETSRC();
|
||||
|
||||
cpu_state.MM[cpu_reg].w[0] = USATW(cpu_state.MM[cpu_reg].w[0] + src.w[0]);
|
||||
cpu_state.MM[cpu_reg].w[1] = USATW(cpu_state.MM[cpu_reg].w[1] + src.w[1]);
|
||||
cpu_state.MM[cpu_reg].w[2] = USATW(cpu_state.MM[cpu_reg].w[2] + src.w[2]);
|
||||
cpu_state.MM[cpu_reg].w[3] = USATW(cpu_state.MM[cpu_reg].w[3] + src.w[3]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int opPADDUSW_a32(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_32(fetchdat);
|
||||
MMX_GETSRC();
|
||||
|
||||
cpu_state.MM[cpu_reg].w[0] = USATW(cpu_state.MM[cpu_reg].w[0] + src.w[0]);
|
||||
cpu_state.MM[cpu_reg].w[1] = USATW(cpu_state.MM[cpu_reg].w[1] + src.w[1]);
|
||||
cpu_state.MM[cpu_reg].w[2] = USATW(cpu_state.MM[cpu_reg].w[2] + src.w[2]);
|
||||
cpu_state.MM[cpu_reg].w[3] = USATW(cpu_state.MM[cpu_reg].w[3] + src.w[3]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opPMADDWD_a16(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_16(fetchdat);
|
||||
MMX_GETSRC();
|
||||
|
||||
if (cpu_state.MM[cpu_reg].l[0] == 0x80008000 && src.l[0] == 0x80008000)
|
||||
cpu_state.MM[cpu_reg].l[0] = 0x80000000;
|
||||
else
|
||||
cpu_state.MM[cpu_reg].sl[0] = ((int32_t)cpu_state.MM[cpu_reg].sw[0] * (int32_t)src.sw[0]) + ((int32_t)cpu_state.MM[cpu_reg].sw[1] * (int32_t)src.sw[1]);
|
||||
|
||||
if (cpu_state.MM[cpu_reg].l[1] == 0x80008000 && src.l[1] == 0x80008000)
|
||||
cpu_state.MM[cpu_reg].l[1] = 0x80000000;
|
||||
else
|
||||
cpu_state.MM[cpu_reg].sl[1] = ((int32_t)cpu_state.MM[cpu_reg].sw[2] * (int32_t)src.sw[2]) + ((int32_t)cpu_state.MM[cpu_reg].sw[3] * (int32_t)src.sw[3]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int opPMADDWD_a32(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_32(fetchdat);
|
||||
MMX_GETSRC();
|
||||
|
||||
if (cpu_state.MM[cpu_reg].l[0] == 0x80008000 && src.l[0] == 0x80008000)
|
||||
cpu_state.MM[cpu_reg].l[0] = 0x80000000;
|
||||
else
|
||||
cpu_state.MM[cpu_reg].sl[0] = ((int32_t)cpu_state.MM[cpu_reg].sw[0] * (int32_t)src.sw[0]) + ((int32_t)cpu_state.MM[cpu_reg].sw[1] * (int32_t)src.sw[1]);
|
||||
|
||||
if (cpu_state.MM[cpu_reg].l[1] == 0x80008000 && src.l[1] == 0x80008000)
|
||||
cpu_state.MM[cpu_reg].l[1] = 0x80000000;
|
||||
else
|
||||
cpu_state.MM[cpu_reg].sl[1] = ((int32_t)cpu_state.MM[cpu_reg].sw[2] * (int32_t)src.sw[2]) + ((int32_t)cpu_state.MM[cpu_reg].sw[3] * (int32_t)src.sw[3]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int opPMULLW_a16(uint32_t fetchdat)
|
||||
{
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_16(fetchdat);
|
||||
if (cpu_mod == 3)
|
||||
{
|
||||
cpu_state.MM[cpu_reg].w[0] *= cpu_state.MM[cpu_rm].w[0];
|
||||
cpu_state.MM[cpu_reg].w[1] *= cpu_state.MM[cpu_rm].w[1];
|
||||
cpu_state.MM[cpu_reg].w[2] *= cpu_state.MM[cpu_rm].w[2];
|
||||
cpu_state.MM[cpu_reg].w[3] *= cpu_state.MM[cpu_rm].w[3];
|
||||
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] *= src.w[0];
|
||||
cpu_state.MM[cpu_reg].w[1] *= src.w[1];
|
||||
cpu_state.MM[cpu_reg].w[2] *= src.w[2];
|
||||
cpu_state.MM[cpu_reg].w[3] *= src.w[3];
|
||||
CLOCK_CYCLES(2);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static int opPMULLW_a32(uint32_t fetchdat)
|
||||
{
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_32(fetchdat);
|
||||
if (cpu_mod == 3)
|
||||
{
|
||||
cpu_state.MM[cpu_reg].w[0] *= cpu_state.MM[cpu_rm].w[0];
|
||||
cpu_state.MM[cpu_reg].w[1] *= cpu_state.MM[cpu_rm].w[1];
|
||||
cpu_state.MM[cpu_reg].w[2] *= cpu_state.MM[cpu_rm].w[2];
|
||||
cpu_state.MM[cpu_reg].w[3] *= cpu_state.MM[cpu_rm].w[3];
|
||||
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] *= src.w[0];
|
||||
cpu_state.MM[cpu_reg].w[1] *= src.w[1];
|
||||
cpu_state.MM[cpu_reg].w[2] *= src.w[2];
|
||||
cpu_state.MM[cpu_reg].w[3] *= src.w[3];
|
||||
CLOCK_CYCLES(2);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opPMULHW_a16(uint32_t fetchdat)
|
||||
{
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_16(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]) >> 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]) >> 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]) >> 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]) >> 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]) >> 16;
|
||||
cpu_state.MM[cpu_reg].w[1] = ((int32_t)cpu_state.MM[cpu_reg].sw[1] * (int32_t)src.sw[1]) >> 16;
|
||||
cpu_state.MM[cpu_reg].w[2] = ((int32_t)cpu_state.MM[cpu_reg].sw[2] * (int32_t)src.sw[2]) >> 16;
|
||||
cpu_state.MM[cpu_reg].w[3] = ((int32_t)cpu_state.MM[cpu_reg].sw[3] * (int32_t)src.sw[3]) >> 16;
|
||||
CLOCK_CYCLES(2);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static int opPMULHW_a32(uint32_t fetchdat)
|
||||
{
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_32(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]) >> 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]) >> 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]) >> 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]) >> 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]) >> 16;
|
||||
cpu_state.MM[cpu_reg].w[1] = ((int32_t)cpu_state.MM[cpu_reg].sw[1] * (int32_t)src.sw[1]) >> 16;
|
||||
cpu_state.MM[cpu_reg].w[2] = ((int32_t)cpu_state.MM[cpu_reg].sw[2] * (int32_t)src.sw[2]) >> 16;
|
||||
cpu_state.MM[cpu_reg].w[3] = ((int32_t)cpu_state.MM[cpu_reg].sw[3] * (int32_t)src.sw[3]) >> 16;
|
||||
CLOCK_CYCLES(2);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opPSUBB_a16(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_16(fetchdat);
|
||||
MMX_GETSRC();
|
||||
|
||||
cpu_state.MM[cpu_reg].b[0] -= src.b[0];
|
||||
cpu_state.MM[cpu_reg].b[1] -= src.b[1];
|
||||
cpu_state.MM[cpu_reg].b[2] -= src.b[2];
|
||||
cpu_state.MM[cpu_reg].b[3] -= src.b[3];
|
||||
cpu_state.MM[cpu_reg].b[4] -= src.b[4];
|
||||
cpu_state.MM[cpu_reg].b[5] -= src.b[5];
|
||||
cpu_state.MM[cpu_reg].b[6] -= src.b[6];
|
||||
cpu_state.MM[cpu_reg].b[7] -= src.b[7];
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int opPSUBB_a32(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_32(fetchdat);
|
||||
MMX_GETSRC();
|
||||
|
||||
cpu_state.MM[cpu_reg].b[0] -= src.b[0];
|
||||
cpu_state.MM[cpu_reg].b[1] -= src.b[1];
|
||||
cpu_state.MM[cpu_reg].b[2] -= src.b[2];
|
||||
cpu_state.MM[cpu_reg].b[3] -= src.b[3];
|
||||
cpu_state.MM[cpu_reg].b[4] -= src.b[4];
|
||||
cpu_state.MM[cpu_reg].b[5] -= src.b[5];
|
||||
cpu_state.MM[cpu_reg].b[6] -= src.b[6];
|
||||
cpu_state.MM[cpu_reg].b[7] -= src.b[7];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opPSUBW_a16(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_16(fetchdat);
|
||||
MMX_GETSRC();
|
||||
|
||||
cpu_state.MM[cpu_reg].w[0] -= src.w[0];
|
||||
cpu_state.MM[cpu_reg].w[1] -= src.w[1];
|
||||
cpu_state.MM[cpu_reg].w[2] -= src.w[2];
|
||||
cpu_state.MM[cpu_reg].w[3] -= src.w[3];
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int opPSUBW_a32(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_32(fetchdat);
|
||||
MMX_GETSRC();
|
||||
|
||||
cpu_state.MM[cpu_reg].w[0] -= src.w[0];
|
||||
cpu_state.MM[cpu_reg].w[1] -= src.w[1];
|
||||
cpu_state.MM[cpu_reg].w[2] -= src.w[2];
|
||||
cpu_state.MM[cpu_reg].w[3] -= src.w[3];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opPSUBD_a16(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_16(fetchdat);
|
||||
MMX_GETSRC();
|
||||
|
||||
cpu_state.MM[cpu_reg].l[0] -= src.l[0];
|
||||
cpu_state.MM[cpu_reg].l[1] -= src.l[1];
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int opPSUBD_a32(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_32(fetchdat);
|
||||
MMX_GETSRC();
|
||||
|
||||
cpu_state.MM[cpu_reg].l[0] -= src.l[0];
|
||||
cpu_state.MM[cpu_reg].l[1] -= src.l[1];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opPSUBSB_a16(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_16(fetchdat);
|
||||
MMX_GETSRC();
|
||||
|
||||
cpu_state.MM[cpu_reg].sb[0] = SSATB(cpu_state.MM[cpu_reg].sb[0] - src.sb[0]);
|
||||
cpu_state.MM[cpu_reg].sb[1] = SSATB(cpu_state.MM[cpu_reg].sb[1] - src.sb[1]);
|
||||
cpu_state.MM[cpu_reg].sb[2] = SSATB(cpu_state.MM[cpu_reg].sb[2] - src.sb[2]);
|
||||
cpu_state.MM[cpu_reg].sb[3] = SSATB(cpu_state.MM[cpu_reg].sb[3] - src.sb[3]);
|
||||
cpu_state.MM[cpu_reg].sb[4] = SSATB(cpu_state.MM[cpu_reg].sb[4] - src.sb[4]);
|
||||
cpu_state.MM[cpu_reg].sb[5] = SSATB(cpu_state.MM[cpu_reg].sb[5] - src.sb[5]);
|
||||
cpu_state.MM[cpu_reg].sb[6] = SSATB(cpu_state.MM[cpu_reg].sb[6] - src.sb[6]);
|
||||
cpu_state.MM[cpu_reg].sb[7] = SSATB(cpu_state.MM[cpu_reg].sb[7] - src.sb[7]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int opPSUBSB_a32(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_32(fetchdat);
|
||||
MMX_GETSRC();
|
||||
|
||||
cpu_state.MM[cpu_reg].sb[0] = SSATB(cpu_state.MM[cpu_reg].sb[0] - src.sb[0]);
|
||||
cpu_state.MM[cpu_reg].sb[1] = SSATB(cpu_state.MM[cpu_reg].sb[1] - src.sb[1]);
|
||||
cpu_state.MM[cpu_reg].sb[2] = SSATB(cpu_state.MM[cpu_reg].sb[2] - src.sb[2]);
|
||||
cpu_state.MM[cpu_reg].sb[3] = SSATB(cpu_state.MM[cpu_reg].sb[3] - src.sb[3]);
|
||||
cpu_state.MM[cpu_reg].sb[4] = SSATB(cpu_state.MM[cpu_reg].sb[4] - src.sb[4]);
|
||||
cpu_state.MM[cpu_reg].sb[5] = SSATB(cpu_state.MM[cpu_reg].sb[5] - src.sb[5]);
|
||||
cpu_state.MM[cpu_reg].sb[6] = SSATB(cpu_state.MM[cpu_reg].sb[6] - src.sb[6]);
|
||||
cpu_state.MM[cpu_reg].sb[7] = SSATB(cpu_state.MM[cpu_reg].sb[7] - src.sb[7]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opPSUBUSB_a16(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_16(fetchdat);
|
||||
MMX_GETSRC();
|
||||
|
||||
cpu_state.MM[cpu_reg].b[0] = USATB(cpu_state.MM[cpu_reg].b[0] - src.b[0]);
|
||||
cpu_state.MM[cpu_reg].b[1] = USATB(cpu_state.MM[cpu_reg].b[1] - src.b[1]);
|
||||
cpu_state.MM[cpu_reg].b[2] = USATB(cpu_state.MM[cpu_reg].b[2] - src.b[2]);
|
||||
cpu_state.MM[cpu_reg].b[3] = USATB(cpu_state.MM[cpu_reg].b[3] - src.b[3]);
|
||||
cpu_state.MM[cpu_reg].b[4] = USATB(cpu_state.MM[cpu_reg].b[4] - src.b[4]);
|
||||
cpu_state.MM[cpu_reg].b[5] = USATB(cpu_state.MM[cpu_reg].b[5] - src.b[5]);
|
||||
cpu_state.MM[cpu_reg].b[6] = USATB(cpu_state.MM[cpu_reg].b[6] - src.b[6]);
|
||||
cpu_state.MM[cpu_reg].b[7] = USATB(cpu_state.MM[cpu_reg].b[7] - src.b[7]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int opPSUBUSB_a32(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_32(fetchdat);
|
||||
MMX_GETSRC();
|
||||
|
||||
cpu_state.MM[cpu_reg].b[0] = USATB(cpu_state.MM[cpu_reg].b[0] - src.b[0]);
|
||||
cpu_state.MM[cpu_reg].b[1] = USATB(cpu_state.MM[cpu_reg].b[1] - src.b[1]);
|
||||
cpu_state.MM[cpu_reg].b[2] = USATB(cpu_state.MM[cpu_reg].b[2] - src.b[2]);
|
||||
cpu_state.MM[cpu_reg].b[3] = USATB(cpu_state.MM[cpu_reg].b[3] - src.b[3]);
|
||||
cpu_state.MM[cpu_reg].b[4] = USATB(cpu_state.MM[cpu_reg].b[4] - src.b[4]);
|
||||
cpu_state.MM[cpu_reg].b[5] = USATB(cpu_state.MM[cpu_reg].b[5] - src.b[5]);
|
||||
cpu_state.MM[cpu_reg].b[6] = USATB(cpu_state.MM[cpu_reg].b[6] - src.b[6]);
|
||||
cpu_state.MM[cpu_reg].b[7] = USATB(cpu_state.MM[cpu_reg].b[7] - src.b[7]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opPSUBSW_a16(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_16(fetchdat);
|
||||
MMX_GETSRC();
|
||||
|
||||
cpu_state.MM[cpu_reg].sw[0] = SSATW(cpu_state.MM[cpu_reg].sw[0] - src.sw[0]);
|
||||
cpu_state.MM[cpu_reg].sw[1] = SSATW(cpu_state.MM[cpu_reg].sw[1] - src.sw[1]);
|
||||
cpu_state.MM[cpu_reg].sw[2] = SSATW(cpu_state.MM[cpu_reg].sw[2] - src.sw[2]);
|
||||
cpu_state.MM[cpu_reg].sw[3] = SSATW(cpu_state.MM[cpu_reg].sw[3] - src.sw[3]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int opPSUBSW_a32(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_32(fetchdat);
|
||||
MMX_GETSRC();
|
||||
|
||||
cpu_state.MM[cpu_reg].sw[0] = SSATW(cpu_state.MM[cpu_reg].sw[0] - src.sw[0]);
|
||||
cpu_state.MM[cpu_reg].sw[1] = SSATW(cpu_state.MM[cpu_reg].sw[1] - src.sw[1]);
|
||||
cpu_state.MM[cpu_reg].sw[2] = SSATW(cpu_state.MM[cpu_reg].sw[2] - src.sw[2]);
|
||||
cpu_state.MM[cpu_reg].sw[3] = SSATW(cpu_state.MM[cpu_reg].sw[3] - src.sw[3]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opPSUBUSW_a16(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_16(fetchdat);
|
||||
MMX_GETSRC();
|
||||
|
||||
cpu_state.MM[cpu_reg].w[0] = USATW(cpu_state.MM[cpu_reg].w[0] - src.w[0]);
|
||||
cpu_state.MM[cpu_reg].w[1] = USATW(cpu_state.MM[cpu_reg].w[1] - src.w[1]);
|
||||
cpu_state.MM[cpu_reg].w[2] = USATW(cpu_state.MM[cpu_reg].w[2] - src.w[2]);
|
||||
cpu_state.MM[cpu_reg].w[3] = USATW(cpu_state.MM[cpu_reg].w[3] - src.w[3]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int opPSUBUSW_a32(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_32(fetchdat);
|
||||
MMX_GETSRC();
|
||||
|
||||
cpu_state.MM[cpu_reg].w[0] = USATW(cpu_state.MM[cpu_reg].w[0] - src.w[0]);
|
||||
cpu_state.MM[cpu_reg].w[1] = USATW(cpu_state.MM[cpu_reg].w[1] - src.w[1]);
|
||||
cpu_state.MM[cpu_reg].w[2] = USATW(cpu_state.MM[cpu_reg].w[2] - src.w[2]);
|
||||
cpu_state.MM[cpu_reg].w[3] = USATW(cpu_state.MM[cpu_reg].w[3] - src.w[3]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
205
src/cpu_common/x86_ops_mmx_cmp.h
Normal file
205
src/cpu_common/x86_ops_mmx_cmp.h
Normal file
@@ -0,0 +1,205 @@
|
||||
static int opPCMPEQB_a16(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_16(fetchdat);
|
||||
MMX_GETSRC();
|
||||
|
||||
cpu_state.MM[cpu_reg].b[0] = (cpu_state.MM[cpu_reg].b[0] == src.b[0]) ? 0xff : 0;
|
||||
cpu_state.MM[cpu_reg].b[1] = (cpu_state.MM[cpu_reg].b[1] == src.b[1]) ? 0xff : 0;
|
||||
cpu_state.MM[cpu_reg].b[2] = (cpu_state.MM[cpu_reg].b[2] == src.b[2]) ? 0xff : 0;
|
||||
cpu_state.MM[cpu_reg].b[3] = (cpu_state.MM[cpu_reg].b[3] == src.b[3]) ? 0xff : 0;
|
||||
cpu_state.MM[cpu_reg].b[4] = (cpu_state.MM[cpu_reg].b[4] == src.b[4]) ? 0xff : 0;
|
||||
cpu_state.MM[cpu_reg].b[5] = (cpu_state.MM[cpu_reg].b[5] == src.b[5]) ? 0xff : 0;
|
||||
cpu_state.MM[cpu_reg].b[6] = (cpu_state.MM[cpu_reg].b[6] == src.b[6]) ? 0xff : 0;
|
||||
cpu_state.MM[cpu_reg].b[7] = (cpu_state.MM[cpu_reg].b[7] == src.b[7]) ? 0xff : 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int opPCMPEQB_a32(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_32(fetchdat);
|
||||
MMX_GETSRC();
|
||||
|
||||
cpu_state.MM[cpu_reg].b[0] = (cpu_state.MM[cpu_reg].b[0] == src.b[0]) ? 0xff : 0;
|
||||
cpu_state.MM[cpu_reg].b[1] = (cpu_state.MM[cpu_reg].b[1] == src.b[1]) ? 0xff : 0;
|
||||
cpu_state.MM[cpu_reg].b[2] = (cpu_state.MM[cpu_reg].b[2] == src.b[2]) ? 0xff : 0;
|
||||
cpu_state.MM[cpu_reg].b[3] = (cpu_state.MM[cpu_reg].b[3] == src.b[3]) ? 0xff : 0;
|
||||
cpu_state.MM[cpu_reg].b[4] = (cpu_state.MM[cpu_reg].b[4] == src.b[4]) ? 0xff : 0;
|
||||
cpu_state.MM[cpu_reg].b[5] = (cpu_state.MM[cpu_reg].b[5] == src.b[5]) ? 0xff : 0;
|
||||
cpu_state.MM[cpu_reg].b[6] = (cpu_state.MM[cpu_reg].b[6] == src.b[6]) ? 0xff : 0;
|
||||
cpu_state.MM[cpu_reg].b[7] = (cpu_state.MM[cpu_reg].b[7] == src.b[7]) ? 0xff : 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opPCMPGTB_a16(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_16(fetchdat);
|
||||
MMX_GETSRC();
|
||||
|
||||
cpu_state.MM[cpu_reg].b[0] = (cpu_state.MM[cpu_reg].sb[0] > src.sb[0]) ? 0xff : 0;
|
||||
cpu_state.MM[cpu_reg].b[1] = (cpu_state.MM[cpu_reg].sb[1] > src.sb[1]) ? 0xff : 0;
|
||||
cpu_state.MM[cpu_reg].b[2] = (cpu_state.MM[cpu_reg].sb[2] > src.sb[2]) ? 0xff : 0;
|
||||
cpu_state.MM[cpu_reg].b[3] = (cpu_state.MM[cpu_reg].sb[3] > src.sb[3]) ? 0xff : 0;
|
||||
cpu_state.MM[cpu_reg].b[4] = (cpu_state.MM[cpu_reg].sb[4] > src.sb[4]) ? 0xff : 0;
|
||||
cpu_state.MM[cpu_reg].b[5] = (cpu_state.MM[cpu_reg].sb[5] > src.sb[5]) ? 0xff : 0;
|
||||
cpu_state.MM[cpu_reg].b[6] = (cpu_state.MM[cpu_reg].sb[6] > src.sb[6]) ? 0xff : 0;
|
||||
cpu_state.MM[cpu_reg].b[7] = (cpu_state.MM[cpu_reg].sb[7] > src.sb[7]) ? 0xff : 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int opPCMPGTB_a32(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_32(fetchdat);
|
||||
MMX_GETSRC();
|
||||
|
||||
cpu_state.MM[cpu_reg].b[0] = (cpu_state.MM[cpu_reg].sb[0] > src.sb[0]) ? 0xff : 0;
|
||||
cpu_state.MM[cpu_reg].b[1] = (cpu_state.MM[cpu_reg].sb[1] > src.sb[1]) ? 0xff : 0;
|
||||
cpu_state.MM[cpu_reg].b[2] = (cpu_state.MM[cpu_reg].sb[2] > src.sb[2]) ? 0xff : 0;
|
||||
cpu_state.MM[cpu_reg].b[3] = (cpu_state.MM[cpu_reg].sb[3] > src.sb[3]) ? 0xff : 0;
|
||||
cpu_state.MM[cpu_reg].b[4] = (cpu_state.MM[cpu_reg].sb[4] > src.sb[4]) ? 0xff : 0;
|
||||
cpu_state.MM[cpu_reg].b[5] = (cpu_state.MM[cpu_reg].sb[5] > src.sb[5]) ? 0xff : 0;
|
||||
cpu_state.MM[cpu_reg].b[6] = (cpu_state.MM[cpu_reg].sb[6] > src.sb[6]) ? 0xff : 0;
|
||||
cpu_state.MM[cpu_reg].b[7] = (cpu_state.MM[cpu_reg].sb[7] > src.sb[7]) ? 0xff : 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opPCMPEQW_a16(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_16(fetchdat);
|
||||
MMX_GETSRC();
|
||||
|
||||
cpu_state.MM[cpu_reg].w[0] = (cpu_state.MM[cpu_reg].w[0] == src.w[0]) ? 0xffff : 0;
|
||||
cpu_state.MM[cpu_reg].w[1] = (cpu_state.MM[cpu_reg].w[1] == src.w[1]) ? 0xffff : 0;
|
||||
cpu_state.MM[cpu_reg].w[2] = (cpu_state.MM[cpu_reg].w[2] == src.w[2]) ? 0xffff : 0;
|
||||
cpu_state.MM[cpu_reg].w[3] = (cpu_state.MM[cpu_reg].w[3] == src.w[3]) ? 0xffff : 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int opPCMPEQW_a32(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_32(fetchdat);
|
||||
MMX_GETSRC();
|
||||
|
||||
cpu_state.MM[cpu_reg].w[0] = (cpu_state.MM[cpu_reg].w[0] == src.w[0]) ? 0xffff : 0;
|
||||
cpu_state.MM[cpu_reg].w[1] = (cpu_state.MM[cpu_reg].w[1] == src.w[1]) ? 0xffff : 0;
|
||||
cpu_state.MM[cpu_reg].w[2] = (cpu_state.MM[cpu_reg].w[2] == src.w[2]) ? 0xffff : 0;
|
||||
cpu_state.MM[cpu_reg].w[3] = (cpu_state.MM[cpu_reg].w[3] == src.w[3]) ? 0xffff : 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opPCMPGTW_a16(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_16(fetchdat);
|
||||
MMX_GETSRC();
|
||||
|
||||
cpu_state.MM[cpu_reg].w[0] = (cpu_state.MM[cpu_reg].sw[0] > src.sw[0]) ? 0xffff : 0;
|
||||
cpu_state.MM[cpu_reg].w[1] = (cpu_state.MM[cpu_reg].sw[1] > src.sw[1]) ? 0xffff : 0;
|
||||
cpu_state.MM[cpu_reg].w[2] = (cpu_state.MM[cpu_reg].sw[2] > src.sw[2]) ? 0xffff : 0;
|
||||
cpu_state.MM[cpu_reg].w[3] = (cpu_state.MM[cpu_reg].sw[3] > src.sw[3]) ? 0xffff : 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int opPCMPGTW_a32(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_32(fetchdat);
|
||||
MMX_GETSRC();
|
||||
|
||||
cpu_state.MM[cpu_reg].w[0] = (cpu_state.MM[cpu_reg].sw[0] > src.sw[0]) ? 0xffff : 0;
|
||||
cpu_state.MM[cpu_reg].w[1] = (cpu_state.MM[cpu_reg].sw[1] > src.sw[1]) ? 0xffff : 0;
|
||||
cpu_state.MM[cpu_reg].w[2] = (cpu_state.MM[cpu_reg].sw[2] > src.sw[2]) ? 0xffff : 0;
|
||||
cpu_state.MM[cpu_reg].w[3] = (cpu_state.MM[cpu_reg].sw[3] > src.sw[3]) ? 0xffff : 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opPCMPEQD_a16(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_16(fetchdat);
|
||||
MMX_GETSRC();
|
||||
|
||||
cpu_state.MM[cpu_reg].l[0] = (cpu_state.MM[cpu_reg].l[0] == src.l[0]) ? 0xffffffff : 0;
|
||||
cpu_state.MM[cpu_reg].l[1] = (cpu_state.MM[cpu_reg].l[1] == src.l[1]) ? 0xffffffff : 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int opPCMPEQD_a32(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
|
||||
MMX_ENTER();
|
||||
|
||||
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;
|
||||
cpu_state.MM[cpu_reg].l[1] = (cpu_state.MM[cpu_reg].l[1] == src.l[1]) ? 0xffffffff : 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opPCMPGTD_a16(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_16(fetchdat);
|
||||
MMX_GETSRC();
|
||||
|
||||
cpu_state.MM[cpu_reg].l[0] = (cpu_state.MM[cpu_reg].sl[0] > src.sl[0]) ? 0xffffffff : 0;
|
||||
cpu_state.MM[cpu_reg].l[1] = (cpu_state.MM[cpu_reg].sl[1] > src.sl[1]) ? 0xffffffff : 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int opPCMPGTD_a32(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
|
||||
MMX_ENTER();
|
||||
|
||||
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;
|
||||
cpu_state.MM[cpu_reg].l[1] = (cpu_state.MM[cpu_reg].sl[1] > src.sl[1]) ? 0xffffffff : 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
91
src/cpu_common/x86_ops_mmx_logic.h
Normal file
91
src/cpu_common/x86_ops_mmx_logic.h
Normal file
@@ -0,0 +1,91 @@
|
||||
static int opPAND_a16(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_16(fetchdat);
|
||||
MMX_GETSRC();
|
||||
|
||||
cpu_state.MM[cpu_reg].q &= src.q;
|
||||
return 0;
|
||||
}
|
||||
static int opPAND_a32(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_32(fetchdat);
|
||||
MMX_GETSRC();
|
||||
|
||||
cpu_state.MM[cpu_reg].q &= src.q;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opPANDN_a16(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_16(fetchdat);
|
||||
MMX_GETSRC();
|
||||
|
||||
cpu_state.MM[cpu_reg].q = ~cpu_state.MM[cpu_reg].q & src.q;
|
||||
return 0;
|
||||
}
|
||||
static int opPANDN_a32(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_32(fetchdat);
|
||||
MMX_GETSRC();
|
||||
|
||||
cpu_state.MM[cpu_reg].q = ~cpu_state.MM[cpu_reg].q & src.q;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opPOR_a16(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_16(fetchdat);
|
||||
MMX_GETSRC();
|
||||
|
||||
cpu_state.MM[cpu_reg].q |= src.q;
|
||||
return 0;
|
||||
}
|
||||
static int opPOR_a32(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_32(fetchdat);
|
||||
MMX_GETSRC();
|
||||
|
||||
cpu_state.MM[cpu_reg].q |= src.q;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opPXOR_a16(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_16(fetchdat);
|
||||
MMX_GETSRC();
|
||||
|
||||
cpu_state.MM[cpu_reg].q ^= src.q;
|
||||
return 0;
|
||||
}
|
||||
static int opPXOR_a32(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_32(fetchdat);
|
||||
MMX_GETSRC();
|
||||
|
||||
cpu_state.MM[cpu_reg].q ^= src.q;
|
||||
return 0;
|
||||
}
|
||||
169
src/cpu_common/x86_ops_mmx_mov.h
Normal file
169
src/cpu_common/x86_ops_mmx_mov.h
Normal file
@@ -0,0 +1,169 @@
|
||||
static int opMOVD_l_mm_a16(uint32_t fetchdat)
|
||||
{
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_16(fetchdat);
|
||||
if (cpu_mod == 3)
|
||||
{
|
||||
cpu_state.MM[cpu_reg].l[0] = cpu_state.regs[cpu_rm].l;
|
||||
cpu_state.MM[cpu_reg].l[1] = 0;
|
||||
CLOCK_CYCLES(1);
|
||||
}
|
||||
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;
|
||||
|
||||
CLOCK_CYCLES(2);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static int opMOVD_l_mm_a32(uint32_t fetchdat)
|
||||
{
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_32(fetchdat);
|
||||
if (cpu_mod == 3)
|
||||
{
|
||||
cpu_state.MM[cpu_reg].l[0] = cpu_state.regs[cpu_rm].l;
|
||||
cpu_state.MM[cpu_reg].l[1] = 0;
|
||||
CLOCK_CYCLES(1);
|
||||
}
|
||||
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;
|
||||
|
||||
CLOCK_CYCLES(2);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opMOVD_mm_l_a16(uint32_t fetchdat)
|
||||
{
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_16(fetchdat);
|
||||
if (cpu_mod == 3)
|
||||
{
|
||||
cpu_state.regs[cpu_rm].l = cpu_state.MM[cpu_reg].l[0];
|
||||
CLOCK_CYCLES(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
SEG_CHECK_WRITE(cpu_state.ea_seg);
|
||||
CHECK_WRITE_COMMON(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);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static int opMOVD_mm_l_a32(uint32_t fetchdat)
|
||||
{
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_32(fetchdat);
|
||||
if (cpu_mod == 3)
|
||||
{
|
||||
cpu_state.regs[cpu_rm].l = cpu_state.MM[cpu_reg].l[0];
|
||||
CLOCK_CYCLES(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
SEG_CHECK_WRITE(cpu_state.ea_seg);
|
||||
CHECK_WRITE_COMMON(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);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opMOVQ_q_mm_a16(uint32_t fetchdat)
|
||||
{
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_16(fetchdat);
|
||||
if (cpu_mod == 3)
|
||||
{
|
||||
cpu_state.MM[cpu_reg].q = cpu_state.MM[cpu_rm].q;
|
||||
CLOCK_CYCLES(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
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);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static int opMOVQ_q_mm_a32(uint32_t fetchdat)
|
||||
{
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_32(fetchdat);
|
||||
if (cpu_mod == 3)
|
||||
{
|
||||
cpu_state.MM[cpu_reg].q = cpu_state.MM[cpu_rm].q;
|
||||
CLOCK_CYCLES(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
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);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opMOVQ_mm_q_a16(uint32_t fetchdat)
|
||||
{
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_16(fetchdat);
|
||||
if (cpu_mod == 3)
|
||||
{
|
||||
cpu_state.MM[cpu_rm].q = cpu_state.MM[cpu_reg].q;
|
||||
CLOCK_CYCLES(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
SEG_CHECK_WRITE(cpu_state.ea_seg);
|
||||
CHECK_WRITE_COMMON(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);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static int opMOVQ_mm_q_a32(uint32_t fetchdat)
|
||||
{
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_32(fetchdat);
|
||||
if (cpu_mod == 3)
|
||||
{
|
||||
cpu_state.MM[cpu_rm].q = cpu_state.MM[cpu_reg].q;
|
||||
CLOCK_CYCLES(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
SEG_CHECK_WRITE(cpu_state.ea_seg);
|
||||
CHECK_WRITE_COMMON(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);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
326
src/cpu_common/x86_ops_mmx_pack.h
Normal file
326
src/cpu_common/x86_ops_mmx_pack.h
Normal file
@@ -0,0 +1,326 @@
|
||||
static int opPUNPCKLDQ_a16(uint32_t fetchdat)
|
||||
{
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_16(fetchdat);
|
||||
if (cpu_mod == 3)
|
||||
{
|
||||
cpu_state.MM[cpu_reg].l[1] = cpu_state.MM[cpu_rm].l[0];
|
||||
CLOCK_CYCLES(1);
|
||||
}
|
||||
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;
|
||||
|
||||
CLOCK_CYCLES(2);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static int opPUNPCKLDQ_a32(uint32_t fetchdat)
|
||||
{
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_32(fetchdat);
|
||||
if (cpu_mod == 3)
|
||||
{
|
||||
cpu_state.MM[cpu_reg].l[1] = cpu_state.MM[cpu_rm].l[0];
|
||||
CLOCK_CYCLES(1);
|
||||
}
|
||||
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;
|
||||
|
||||
CLOCK_CYCLES(2);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opPUNPCKHDQ_a16(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_16(fetchdat);
|
||||
MMX_GETSRC();
|
||||
|
||||
cpu_state.MM[cpu_reg].l[0] = cpu_state.MM[cpu_reg].l[1];
|
||||
cpu_state.MM[cpu_reg].l[1] = src.l[1];
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int opPUNPCKHDQ_a32(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_32(fetchdat);
|
||||
MMX_GETSRC();
|
||||
|
||||
cpu_state.MM[cpu_reg].l[0] = cpu_state.MM[cpu_reg].l[1];
|
||||
cpu_state.MM[cpu_reg].l[1] = src.l[1];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opPUNPCKLBW_a16(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_16(fetchdat);
|
||||
MMX_GETSRC();
|
||||
|
||||
cpu_state.MM[cpu_reg].b[7] = src.b[3];
|
||||
cpu_state.MM[cpu_reg].b[6] = cpu_state.MM[cpu_reg].b[3];
|
||||
cpu_state.MM[cpu_reg].b[5] = src.b[2];
|
||||
cpu_state.MM[cpu_reg].b[4] = cpu_state.MM[cpu_reg].b[2];
|
||||
cpu_state.MM[cpu_reg].b[3] = src.b[1];
|
||||
cpu_state.MM[cpu_reg].b[2] = cpu_state.MM[cpu_reg].b[1];
|
||||
cpu_state.MM[cpu_reg].b[1] = src.b[0];
|
||||
cpu_state.MM[cpu_reg].b[0] = cpu_state.MM[cpu_reg].b[0];
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int opPUNPCKLBW_a32(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_32(fetchdat);
|
||||
MMX_GETSRC();
|
||||
|
||||
cpu_state.MM[cpu_reg].b[7] = src.b[3];
|
||||
cpu_state.MM[cpu_reg].b[6] = cpu_state.MM[cpu_reg].b[3];
|
||||
cpu_state.MM[cpu_reg].b[5] = src.b[2];
|
||||
cpu_state.MM[cpu_reg].b[4] = cpu_state.MM[cpu_reg].b[2];
|
||||
cpu_state.MM[cpu_reg].b[3] = src.b[1];
|
||||
cpu_state.MM[cpu_reg].b[2] = cpu_state.MM[cpu_reg].b[1];
|
||||
cpu_state.MM[cpu_reg].b[1] = src.b[0];
|
||||
cpu_state.MM[cpu_reg].b[0] = cpu_state.MM[cpu_reg].b[0];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opPUNPCKHBW_a16(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_16(fetchdat);
|
||||
MMX_GETSRC();
|
||||
|
||||
cpu_state.MM[cpu_reg].b[0] = cpu_state.MM[cpu_reg].b[4];
|
||||
cpu_state.MM[cpu_reg].b[1] = src.b[4];
|
||||
cpu_state.MM[cpu_reg].b[2] = cpu_state.MM[cpu_reg].b[5];
|
||||
cpu_state.MM[cpu_reg].b[3] = src.b[5];
|
||||
cpu_state.MM[cpu_reg].b[4] = cpu_state.MM[cpu_reg].b[6];
|
||||
cpu_state.MM[cpu_reg].b[5] = src.b[6];
|
||||
cpu_state.MM[cpu_reg].b[6] = cpu_state.MM[cpu_reg].b[7];
|
||||
cpu_state.MM[cpu_reg].b[7] = src.b[7];
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int opPUNPCKHBW_a32(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_32(fetchdat);
|
||||
MMX_GETSRC();
|
||||
|
||||
cpu_state.MM[cpu_reg].b[0] = cpu_state.MM[cpu_reg].b[4];
|
||||
cpu_state.MM[cpu_reg].b[1] = src.b[4];
|
||||
cpu_state.MM[cpu_reg].b[2] = cpu_state.MM[cpu_reg].b[5];
|
||||
cpu_state.MM[cpu_reg].b[3] = src.b[5];
|
||||
cpu_state.MM[cpu_reg].b[4] = cpu_state.MM[cpu_reg].b[6];
|
||||
cpu_state.MM[cpu_reg].b[5] = src.b[6];
|
||||
cpu_state.MM[cpu_reg].b[6] = cpu_state.MM[cpu_reg].b[7];
|
||||
cpu_state.MM[cpu_reg].b[7] = src.b[7];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opPUNPCKLWD_a16(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_16(fetchdat);
|
||||
MMX_GETSRC();
|
||||
|
||||
cpu_state.MM[cpu_reg].w[3] = src.w[1];
|
||||
cpu_state.MM[cpu_reg].w[2] = cpu_state.MM[cpu_reg].w[1];
|
||||
cpu_state.MM[cpu_reg].w[1] = src.w[0];
|
||||
cpu_state.MM[cpu_reg].w[0] = cpu_state.MM[cpu_reg].w[0];
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int opPUNPCKLWD_a32(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_32(fetchdat);
|
||||
MMX_GETSRC();
|
||||
|
||||
cpu_state.MM[cpu_reg].w[3] = src.w[1];
|
||||
cpu_state.MM[cpu_reg].w[2] = cpu_state.MM[cpu_reg].w[1];
|
||||
cpu_state.MM[cpu_reg].w[1] = src.w[0];
|
||||
cpu_state.MM[cpu_reg].w[0] = cpu_state.MM[cpu_reg].w[0];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opPUNPCKHWD_a16(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_16(fetchdat);
|
||||
MMX_GETSRC();
|
||||
|
||||
cpu_state.MM[cpu_reg].w[0] = cpu_state.MM[cpu_reg].w[2];
|
||||
cpu_state.MM[cpu_reg].w[1] = src.w[2];
|
||||
cpu_state.MM[cpu_reg].w[2] = cpu_state.MM[cpu_reg].w[3];
|
||||
cpu_state.MM[cpu_reg].w[3] = src.w[3];
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int opPUNPCKHWD_a32(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src;
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_32(fetchdat);
|
||||
MMX_GETSRC();
|
||||
|
||||
cpu_state.MM[cpu_reg].w[0] = cpu_state.MM[cpu_reg].w[2];
|
||||
cpu_state.MM[cpu_reg].w[1] = src.w[2];
|
||||
cpu_state.MM[cpu_reg].w[2] = cpu_state.MM[cpu_reg].w[3];
|
||||
cpu_state.MM[cpu_reg].w[3] = src.w[3];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opPACKSSWB_a16(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src, dst;
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_16(fetchdat);
|
||||
MMX_GETSRC();
|
||||
dst = cpu_state.MM[cpu_reg];
|
||||
|
||||
cpu_state.MM[cpu_reg].sb[0] = SSATB(dst.sw[0]);
|
||||
cpu_state.MM[cpu_reg].sb[1] = SSATB(dst.sw[1]);
|
||||
cpu_state.MM[cpu_reg].sb[2] = SSATB(dst.sw[2]);
|
||||
cpu_state.MM[cpu_reg].sb[3] = SSATB(dst.sw[3]);
|
||||
cpu_state.MM[cpu_reg].sb[4] = SSATB(src.sw[0]);
|
||||
cpu_state.MM[cpu_reg].sb[5] = SSATB(src.sw[1]);
|
||||
cpu_state.MM[cpu_reg].sb[6] = SSATB(src.sw[2]);
|
||||
cpu_state.MM[cpu_reg].sb[7] = SSATB(src.sw[3]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int opPACKSSWB_a32(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src, dst;
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_32(fetchdat);
|
||||
MMX_GETSRC();
|
||||
dst = cpu_state.MM[cpu_reg];
|
||||
|
||||
cpu_state.MM[cpu_reg].sb[0] = SSATB(dst.sw[0]);
|
||||
cpu_state.MM[cpu_reg].sb[1] = SSATB(dst.sw[1]);
|
||||
cpu_state.MM[cpu_reg].sb[2] = SSATB(dst.sw[2]);
|
||||
cpu_state.MM[cpu_reg].sb[3] = SSATB(dst.sw[3]);
|
||||
cpu_state.MM[cpu_reg].sb[4] = SSATB(src.sw[0]);
|
||||
cpu_state.MM[cpu_reg].sb[5] = SSATB(src.sw[1]);
|
||||
cpu_state.MM[cpu_reg].sb[6] = SSATB(src.sw[2]);
|
||||
cpu_state.MM[cpu_reg].sb[7] = SSATB(src.sw[3]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opPACKUSWB_a16(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src, dst;
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_16(fetchdat);
|
||||
MMX_GETSRC();
|
||||
dst = cpu_state.MM[cpu_reg];
|
||||
|
||||
cpu_state.MM[cpu_reg].b[0] = USATB(dst.sw[0]);
|
||||
cpu_state.MM[cpu_reg].b[1] = USATB(dst.sw[1]);
|
||||
cpu_state.MM[cpu_reg].b[2] = USATB(dst.sw[2]);
|
||||
cpu_state.MM[cpu_reg].b[3] = USATB(dst.sw[3]);
|
||||
cpu_state.MM[cpu_reg].b[4] = USATB(src.sw[0]);
|
||||
cpu_state.MM[cpu_reg].b[5] = USATB(src.sw[1]);
|
||||
cpu_state.MM[cpu_reg].b[6] = USATB(src.sw[2]);
|
||||
cpu_state.MM[cpu_reg].b[7] = USATB(src.sw[3]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int opPACKUSWB_a32(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src, dst;
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_32(fetchdat);
|
||||
MMX_GETSRC();
|
||||
dst = cpu_state.MM[cpu_reg];
|
||||
|
||||
cpu_state.MM[cpu_reg].b[0] = USATB(dst.sw[0]);
|
||||
cpu_state.MM[cpu_reg].b[1] = USATB(dst.sw[1]);
|
||||
cpu_state.MM[cpu_reg].b[2] = USATB(dst.sw[2]);
|
||||
cpu_state.MM[cpu_reg].b[3] = USATB(dst.sw[3]);
|
||||
cpu_state.MM[cpu_reg].b[4] = USATB(src.sw[0]);
|
||||
cpu_state.MM[cpu_reg].b[5] = USATB(src.sw[1]);
|
||||
cpu_state.MM[cpu_reg].b[6] = USATB(src.sw[2]);
|
||||
cpu_state.MM[cpu_reg].b[7] = USATB(src.sw[3]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opPACKSSDW_a16(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src, dst;
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_16(fetchdat);
|
||||
MMX_GETSRC();
|
||||
dst = cpu_state.MM[cpu_reg];
|
||||
|
||||
cpu_state.MM[cpu_reg].sw[0] = SSATW(dst.sl[0]);
|
||||
cpu_state.MM[cpu_reg].sw[1] = SSATW(dst.sl[1]);
|
||||
cpu_state.MM[cpu_reg].sw[2] = SSATW(src.sl[0]);
|
||||
cpu_state.MM[cpu_reg].sw[3] = SSATW(src.sl[1]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int opPACKSSDW_a32(uint32_t fetchdat)
|
||||
{
|
||||
MMX_REG src, dst;
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_32(fetchdat);
|
||||
MMX_GETSRC();
|
||||
dst = cpu_state.MM[cpu_reg];
|
||||
|
||||
cpu_state.MM[cpu_reg].sw[0] = SSATW(dst.sl[0]);
|
||||
cpu_state.MM[cpu_reg].sw[1] = SSATW(dst.sl[1]);
|
||||
cpu_state.MM[cpu_reg].sw[2] = SSATW(src.sl[0]);
|
||||
cpu_state.MM[cpu_reg].sw[3] = SSATW(src.sl[1]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
450
src/cpu_common/x86_ops_mmx_shift.h
Normal file
450
src/cpu_common/x86_ops_mmx_shift.h
Normal file
@@ -0,0 +1,450 @@
|
||||
#define MMX_GETSHIFT() \
|
||||
if (cpu_mod == 3) \
|
||||
{ \
|
||||
shift = cpu_state.MM[cpu_rm].b[0]; \
|
||||
CLOCK_CYCLES(1); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
SEG_CHECK_READ(cpu_state.ea_seg); \
|
||||
shift = readmemb(easeg, cpu_state.eaaddr); if (cpu_state.abrt) return 0; \
|
||||
CLOCK_CYCLES(2); \
|
||||
}
|
||||
|
||||
static int opPSxxW_imm(uint32_t fetchdat)
|
||||
{
|
||||
int reg = fetchdat & 7;
|
||||
int op = fetchdat & 0x38;
|
||||
int shift = (fetchdat >> 8) & 0xff;
|
||||
|
||||
cpu_state.pc += 2;
|
||||
MMX_ENTER();
|
||||
|
||||
switch (op)
|
||||
{
|
||||
case 0x10: /*PSRLW*/
|
||||
if (shift > 15)
|
||||
cpu_state.MM[reg].q = 0;
|
||||
else
|
||||
{
|
||||
cpu_state.MM[reg].w[0] >>= shift;
|
||||
cpu_state.MM[reg].w[1] >>= shift;
|
||||
cpu_state.MM[reg].w[2] >>= shift;
|
||||
cpu_state.MM[reg].w[3] >>= shift;
|
||||
}
|
||||
break;
|
||||
case 0x20: /*PSRAW*/
|
||||
if (shift > 15)
|
||||
shift = 15;
|
||||
cpu_state.MM[reg].sw[0] >>= shift;
|
||||
cpu_state.MM[reg].sw[1] >>= shift;
|
||||
cpu_state.MM[reg].sw[2] >>= shift;
|
||||
cpu_state.MM[reg].sw[3] >>= shift;
|
||||
break;
|
||||
case 0x30: /*PSLLW*/
|
||||
if (shift > 15)
|
||||
cpu_state.MM[reg].q = 0;
|
||||
else
|
||||
{
|
||||
cpu_state.MM[reg].w[0] <<= shift;
|
||||
cpu_state.MM[reg].w[1] <<= shift;
|
||||
cpu_state.MM[reg].w[2] <<= shift;
|
||||
cpu_state.MM[reg].w[3] <<= shift;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
cpu_state.pc = cpu_state.oldpc;
|
||||
x86illegal();
|
||||
return 0;
|
||||
}
|
||||
|
||||
CLOCK_CYCLES(1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opPSLLW_a16(uint32_t fetchdat)
|
||||
{
|
||||
int shift;
|
||||
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_16(fetchdat);
|
||||
MMX_GETSHIFT();
|
||||
|
||||
if (shift > 15)
|
||||
cpu_state.MM[cpu_reg].q = 0;
|
||||
else
|
||||
{
|
||||
cpu_state.MM[cpu_reg].w[0] <<= shift;
|
||||
cpu_state.MM[cpu_reg].w[1] <<= shift;
|
||||
cpu_state.MM[cpu_reg].w[2] <<= shift;
|
||||
cpu_state.MM[cpu_reg].w[3] <<= shift;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int opPSLLW_a32(uint32_t fetchdat)
|
||||
{
|
||||
int shift;
|
||||
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_32(fetchdat);
|
||||
MMX_GETSHIFT();
|
||||
|
||||
if (shift > 15)
|
||||
cpu_state.MM[cpu_reg].q = 0;
|
||||
else
|
||||
{
|
||||
cpu_state.MM[cpu_reg].w[0] <<= shift;
|
||||
cpu_state.MM[cpu_reg].w[1] <<= shift;
|
||||
cpu_state.MM[cpu_reg].w[2] <<= shift;
|
||||
cpu_state.MM[cpu_reg].w[3] <<= shift;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opPSRLW_a16(uint32_t fetchdat)
|
||||
{
|
||||
int shift;
|
||||
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_16(fetchdat);
|
||||
MMX_GETSHIFT();
|
||||
|
||||
if (shift > 15)
|
||||
cpu_state.MM[cpu_reg].q = 0;
|
||||
else
|
||||
{
|
||||
cpu_state.MM[cpu_reg].w[0] >>= shift;
|
||||
cpu_state.MM[cpu_reg].w[1] >>= shift;
|
||||
cpu_state.MM[cpu_reg].w[2] >>= shift;
|
||||
cpu_state.MM[cpu_reg].w[3] >>= shift;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int opPSRLW_a32(uint32_t fetchdat)
|
||||
{
|
||||
int shift;
|
||||
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_32(fetchdat);
|
||||
MMX_GETSHIFT();
|
||||
|
||||
if (shift > 15)
|
||||
cpu_state.MM[cpu_reg].q = 0;
|
||||
else
|
||||
{
|
||||
cpu_state.MM[cpu_reg].w[0] >>= shift;
|
||||
cpu_state.MM[cpu_reg].w[1] >>= shift;
|
||||
cpu_state.MM[cpu_reg].w[2] >>= shift;
|
||||
cpu_state.MM[cpu_reg].w[3] >>= shift;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opPSRAW_a16(uint32_t fetchdat)
|
||||
{
|
||||
int shift;
|
||||
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_16(fetchdat);
|
||||
MMX_GETSHIFT();
|
||||
|
||||
if (shift > 15)
|
||||
shift = 15;
|
||||
|
||||
cpu_state.MM[cpu_reg].sw[0] >>= shift;
|
||||
cpu_state.MM[cpu_reg].sw[1] >>= shift;
|
||||
cpu_state.MM[cpu_reg].sw[2] >>= shift;
|
||||
cpu_state.MM[cpu_reg].sw[3] >>= shift;
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int opPSRAW_a32(uint32_t fetchdat)
|
||||
{
|
||||
int shift;
|
||||
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_32(fetchdat);
|
||||
MMX_GETSHIFT();
|
||||
|
||||
if (shift > 15)
|
||||
shift = 15;
|
||||
|
||||
cpu_state.MM[cpu_reg].sw[0] >>= shift;
|
||||
cpu_state.MM[cpu_reg].sw[1] >>= shift;
|
||||
cpu_state.MM[cpu_reg].sw[2] >>= shift;
|
||||
cpu_state.MM[cpu_reg].sw[3] >>= shift;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opPSxxD_imm(uint32_t fetchdat)
|
||||
{
|
||||
int reg = fetchdat & 7;
|
||||
int op = fetchdat & 0x38;
|
||||
int shift = (fetchdat >> 8) & 0xff;
|
||||
|
||||
cpu_state.pc += 2;
|
||||
MMX_ENTER();
|
||||
|
||||
switch (op)
|
||||
{
|
||||
case 0x10: /*PSRLD*/
|
||||
if (shift > 31)
|
||||
cpu_state.MM[reg].q = 0;
|
||||
else
|
||||
{
|
||||
cpu_state.MM[reg].l[0] >>= shift;
|
||||
cpu_state.MM[reg].l[1] >>= shift;
|
||||
}
|
||||
break;
|
||||
case 0x20: /*PSRAD*/
|
||||
if (shift > 31)
|
||||
shift = 31;
|
||||
cpu_state.MM[reg].sl[0] >>= shift;
|
||||
cpu_state.MM[reg].sl[1] >>= shift;
|
||||
break;
|
||||
case 0x30: /*PSLLD*/
|
||||
if (shift > 31)
|
||||
cpu_state.MM[reg].q = 0;
|
||||
else
|
||||
{
|
||||
cpu_state.MM[reg].l[0] <<= shift;
|
||||
cpu_state.MM[reg].l[1] <<= shift;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
cpu_state.pc = cpu_state.oldpc;
|
||||
x86illegal();
|
||||
return 0;
|
||||
}
|
||||
|
||||
CLOCK_CYCLES(1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opPSLLD_a16(uint32_t fetchdat)
|
||||
{
|
||||
int shift;
|
||||
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_16(fetchdat);
|
||||
MMX_GETSHIFT();
|
||||
|
||||
if (shift > 31)
|
||||
cpu_state.MM[cpu_reg].q = 0;
|
||||
else
|
||||
{
|
||||
cpu_state.MM[cpu_reg].l[0] <<= shift;
|
||||
cpu_state.MM[cpu_reg].l[1] <<= shift;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int opPSLLD_a32(uint32_t fetchdat)
|
||||
{
|
||||
int shift;
|
||||
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_32(fetchdat);
|
||||
MMX_GETSHIFT();
|
||||
|
||||
if (shift > 31)
|
||||
cpu_state.MM[cpu_reg].q = 0;
|
||||
else
|
||||
{
|
||||
cpu_state.MM[cpu_reg].l[0] <<= shift;
|
||||
cpu_state.MM[cpu_reg].l[1] <<= shift;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opPSRLD_a16(uint32_t fetchdat)
|
||||
{
|
||||
int shift;
|
||||
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_16(fetchdat);
|
||||
MMX_GETSHIFT();
|
||||
|
||||
if (shift > 31)
|
||||
cpu_state.MM[cpu_reg].q = 0;
|
||||
else
|
||||
{
|
||||
cpu_state.MM[cpu_reg].l[0] >>= shift;
|
||||
cpu_state.MM[cpu_reg].l[1] >>= shift;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int opPSRLD_a32(uint32_t fetchdat)
|
||||
{
|
||||
int shift;
|
||||
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_32(fetchdat);
|
||||
MMX_GETSHIFT();
|
||||
|
||||
if (shift > 31)
|
||||
cpu_state.MM[cpu_reg].q = 0;
|
||||
else
|
||||
{
|
||||
cpu_state.MM[cpu_reg].l[0] >>= shift;
|
||||
cpu_state.MM[cpu_reg].l[1] >>= shift;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opPSRAD_a16(uint32_t fetchdat)
|
||||
{
|
||||
int shift;
|
||||
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_16(fetchdat);
|
||||
MMX_GETSHIFT();
|
||||
|
||||
if (shift > 31)
|
||||
shift = 31;
|
||||
|
||||
cpu_state.MM[cpu_reg].sl[0] >>= shift;
|
||||
cpu_state.MM[cpu_reg].sl[1] >>= shift;
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int opPSRAD_a32(uint32_t fetchdat)
|
||||
{
|
||||
int shift;
|
||||
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_32(fetchdat);
|
||||
MMX_GETSHIFT();
|
||||
|
||||
if (shift > 31)
|
||||
shift = 31;
|
||||
|
||||
cpu_state.MM[cpu_reg].sl[0] >>= shift;
|
||||
cpu_state.MM[cpu_reg].sl[1] >>= shift;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opPSxxQ_imm(uint32_t fetchdat)
|
||||
{
|
||||
int reg = fetchdat & 7;
|
||||
int op = fetchdat & 0x38;
|
||||
int shift = (fetchdat >> 8) & 0xff;
|
||||
|
||||
cpu_state.pc += 2;
|
||||
MMX_ENTER();
|
||||
|
||||
switch (op)
|
||||
{
|
||||
case 0x10: /*PSRLW*/
|
||||
if (shift > 63)
|
||||
cpu_state.MM[reg].q = 0;
|
||||
else
|
||||
cpu_state.MM[reg].q >>= shift;
|
||||
break;
|
||||
case 0x20: /*PSRAW*/
|
||||
if (shift > 63)
|
||||
shift = 63;
|
||||
cpu_state.MM[reg].sq >>= shift;
|
||||
break;
|
||||
case 0x30: /*PSLLW*/
|
||||
if (shift > 63)
|
||||
cpu_state.MM[reg].q = 0;
|
||||
else
|
||||
cpu_state.MM[reg].q <<= shift;
|
||||
break;
|
||||
default:
|
||||
cpu_state.pc = cpu_state.oldpc;
|
||||
x86illegal();
|
||||
return 0;
|
||||
}
|
||||
|
||||
CLOCK_CYCLES(1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opPSLLQ_a16(uint32_t fetchdat)
|
||||
{
|
||||
int shift;
|
||||
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_16(fetchdat);
|
||||
MMX_GETSHIFT();
|
||||
|
||||
if (shift > 63)
|
||||
cpu_state.MM[cpu_reg].q = 0;
|
||||
else
|
||||
cpu_state.MM[cpu_reg].q <<= shift;
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int opPSLLQ_a32(uint32_t fetchdat)
|
||||
{
|
||||
int shift;
|
||||
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_32(fetchdat);
|
||||
MMX_GETSHIFT();
|
||||
|
||||
if (shift > 63)
|
||||
cpu_state.MM[cpu_reg].q = 0;
|
||||
else
|
||||
cpu_state.MM[cpu_reg].q <<= shift;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opPSRLQ_a16(uint32_t fetchdat)
|
||||
{
|
||||
int shift;
|
||||
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_16(fetchdat);
|
||||
MMX_GETSHIFT();
|
||||
|
||||
if (shift > 63)
|
||||
cpu_state.MM[cpu_reg].q = 0;
|
||||
else
|
||||
cpu_state.MM[cpu_reg].q >>= shift;
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int opPSRLQ_a32(uint32_t fetchdat)
|
||||
{
|
||||
int shift;
|
||||
|
||||
MMX_ENTER();
|
||||
|
||||
fetch_ea_32(fetchdat);
|
||||
MMX_GETSHIFT();
|
||||
|
||||
if (shift > 63)
|
||||
cpu_state.MM[cpu_reg].q = 0;
|
||||
else
|
||||
cpu_state.MM[cpu_reg].q >>= shift;
|
||||
|
||||
return 0;
|
||||
}
|
||||
786
src/cpu_common/x86_ops_mov.h
Normal file
786
src/cpu_common/x86_ops_mov.h
Normal file
@@ -0,0 +1,786 @@
|
||||
static int opMOV_AL_imm(uint32_t fetchdat)
|
||||
{
|
||||
AL = getbytef();
|
||||
CLOCK_CYCLES(timing_rr);
|
||||
PREFETCH_RUN(timing_rr, 2, -1, 0,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opMOV_AH_imm(uint32_t fetchdat)
|
||||
{
|
||||
AH = getbytef();
|
||||
CLOCK_CYCLES(timing_rr);
|
||||
PREFETCH_RUN(timing_rr, 2, -1, 0,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opMOV_BL_imm(uint32_t fetchdat)
|
||||
{
|
||||
BL = getbytef();
|
||||
CLOCK_CYCLES(timing_rr);
|
||||
PREFETCH_RUN(timing_rr, 2, -1, 0,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opMOV_BH_imm(uint32_t fetchdat)
|
||||
{
|
||||
BH = getbytef();
|
||||
CLOCK_CYCLES(timing_rr);
|
||||
PREFETCH_RUN(timing_rr, 2, -1, 0,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opMOV_CL_imm(uint32_t fetchdat)
|
||||
{
|
||||
CL = getbytef();
|
||||
CLOCK_CYCLES(timing_rr);
|
||||
PREFETCH_RUN(timing_rr, 2, -1, 0,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opMOV_CH_imm(uint32_t fetchdat)
|
||||
{
|
||||
CH = getbytef();
|
||||
CLOCK_CYCLES(timing_rr);
|
||||
PREFETCH_RUN(timing_rr, 2, -1, 0,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opMOV_DL_imm(uint32_t fetchdat)
|
||||
{
|
||||
DL = getbytef();
|
||||
CLOCK_CYCLES(timing_rr);
|
||||
PREFETCH_RUN(timing_rr, 2, -1, 0,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opMOV_DH_imm(uint32_t fetchdat)
|
||||
{
|
||||
DH = getbytef();
|
||||
CLOCK_CYCLES(timing_rr);
|
||||
PREFETCH_RUN(timing_rr, 2, -1, 0,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opMOV_AX_imm(uint32_t fetchdat)
|
||||
{
|
||||
AX = getwordf();
|
||||
CLOCK_CYCLES(timing_rr);
|
||||
PREFETCH_RUN(timing_rr, 3, -1, 0,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opMOV_BX_imm(uint32_t fetchdat)
|
||||
{
|
||||
BX = getwordf();
|
||||
CLOCK_CYCLES(timing_rr);
|
||||
PREFETCH_RUN(timing_rr, 3, -1, 0,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opMOV_CX_imm(uint32_t fetchdat)
|
||||
{
|
||||
CX = getwordf();
|
||||
CLOCK_CYCLES(timing_rr);
|
||||
PREFETCH_RUN(timing_rr, 3, -1, 0,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opMOV_DX_imm(uint32_t fetchdat)
|
||||
{
|
||||
DX = getwordf();
|
||||
CLOCK_CYCLES(timing_rr);
|
||||
PREFETCH_RUN(timing_rr, 3, -1, 0,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opMOV_SI_imm(uint32_t fetchdat)
|
||||
{
|
||||
SI = getwordf();
|
||||
CLOCK_CYCLES(timing_rr);
|
||||
PREFETCH_RUN(timing_rr, 3, -1, 0,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opMOV_DI_imm(uint32_t fetchdat)
|
||||
{
|
||||
DI = getwordf();
|
||||
CLOCK_CYCLES(timing_rr);
|
||||
PREFETCH_RUN(timing_rr, 3, -1, 0,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opMOV_BP_imm(uint32_t fetchdat)
|
||||
{
|
||||
BP = getwordf();
|
||||
CLOCK_CYCLES(timing_rr);
|
||||
PREFETCH_RUN(timing_rr, 3, -1, 0,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opMOV_SP_imm(uint32_t fetchdat)
|
||||
{
|
||||
SP = getwordf();
|
||||
CLOCK_CYCLES(timing_rr);
|
||||
PREFETCH_RUN(timing_rr, 3, -1, 0,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opMOV_EAX_imm(uint32_t fetchdat)
|
||||
{
|
||||
uint32_t templ = getlong(); if (cpu_state.abrt) return 1;
|
||||
EAX = templ;
|
||||
CLOCK_CYCLES(timing_rr);
|
||||
PREFETCH_RUN(timing_rr, 5, -1, 0,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opMOV_EBX_imm(uint32_t fetchdat)
|
||||
{
|
||||
uint32_t templ = getlong(); if (cpu_state.abrt) return 1;
|
||||
EBX = templ;
|
||||
CLOCK_CYCLES(timing_rr);
|
||||
PREFETCH_RUN(timing_rr, 5, -1, 0,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opMOV_ECX_imm(uint32_t fetchdat)
|
||||
{
|
||||
uint32_t templ = getlong(); if (cpu_state.abrt) return 1;
|
||||
ECX = templ;
|
||||
CLOCK_CYCLES(timing_rr);
|
||||
PREFETCH_RUN(timing_rr, 5, -1, 0,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opMOV_EDX_imm(uint32_t fetchdat)
|
||||
{
|
||||
uint32_t templ = getlong(); if (cpu_state.abrt) return 1;
|
||||
EDX = templ;
|
||||
CLOCK_CYCLES(timing_rr);
|
||||
PREFETCH_RUN(timing_rr, 5, -1, 0,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opMOV_ESI_imm(uint32_t fetchdat)
|
||||
{
|
||||
uint32_t templ = getlong(); if (cpu_state.abrt) return 1;
|
||||
ESI = templ;
|
||||
CLOCK_CYCLES(timing_rr);
|
||||
PREFETCH_RUN(timing_rr, 5, -1, 0,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opMOV_EDI_imm(uint32_t fetchdat)
|
||||
{
|
||||
uint32_t templ = getlong(); if (cpu_state.abrt) return 1;
|
||||
EDI = templ;
|
||||
CLOCK_CYCLES(timing_rr);
|
||||
PREFETCH_RUN(timing_rr, 5, -1, 0,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opMOV_EBP_imm(uint32_t fetchdat)
|
||||
{
|
||||
uint32_t templ = getlong(); if (cpu_state.abrt) return 1;
|
||||
EBP = templ;
|
||||
CLOCK_CYCLES(timing_rr);
|
||||
PREFETCH_RUN(timing_rr, 5, -1, 0,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opMOV_ESP_imm(uint32_t fetchdat)
|
||||
{
|
||||
uint32_t templ = getlong(); if (cpu_state.abrt) return 1;
|
||||
ESP = templ;
|
||||
CLOCK_CYCLES(timing_rr);
|
||||
PREFETCH_RUN(timing_rr, 5, -1, 0,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opMOV_b_imm_a16(uint32_t fetchdat)
|
||||
{
|
||||
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;
|
||||
seteab(temp);
|
||||
CLOCK_CYCLES(timing_rr);
|
||||
PREFETCH_RUN(timing_rr, 3, rmdat, 0,0,(cpu_mod == 3) ? 1:0,0, 0);
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
static int opMOV_b_imm_a32(uint32_t fetchdat)
|
||||
{
|
||||
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);
|
||||
PREFETCH_RUN(timing_rr, 3, rmdat, 0,0,(cpu_mod == 3) ? 1:0,0, 1);
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
|
||||
static int opMOV_w_imm_a16(uint32_t fetchdat)
|
||||
{
|
||||
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);
|
||||
PREFETCH_RUN(timing_rr, 4, rmdat, 0,0,(cpu_mod == 3) ? 1:0,0, 0);
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
static int opMOV_w_imm_a32(uint32_t fetchdat)
|
||||
{
|
||||
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);
|
||||
PREFETCH_RUN(timing_rr, 4, rmdat, 0,0,(cpu_mod == 3) ? 1:0,0, 1);
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
static int opMOV_l_imm_a16(uint32_t fetchdat)
|
||||
{
|
||||
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);
|
||||
PREFETCH_RUN(timing_rr, 6, rmdat, 0,0,0,(cpu_mod == 3) ? 1:0, 0);
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
static int opMOV_l_imm_a32(uint32_t fetchdat)
|
||||
{
|
||||
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);
|
||||
PREFETCH_RUN(timing_rr, 6, rmdat, 0,0,0,(cpu_mod == 3) ? 1:0, 1);
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
|
||||
|
||||
static int opMOV_AL_a16(uint32_t fetchdat)
|
||||
{
|
||||
uint8_t temp;
|
||||
uint16_t addr = getwordf();
|
||||
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;
|
||||
CLOCK_CYCLES((is486) ? 1 : 4);
|
||||
PREFETCH_RUN(4, 3, -1, 1,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opMOV_AL_a32(uint32_t fetchdat)
|
||||
{
|
||||
uint8_t temp;
|
||||
uint32_t addr = getlong();
|
||||
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;
|
||||
CLOCK_CYCLES((is486) ? 1 : 4);
|
||||
PREFETCH_RUN(4, 5, -1, 1,0,0,0, 1);
|
||||
return 0;
|
||||
}
|
||||
static int opMOV_AX_a16(uint32_t fetchdat)
|
||||
{
|
||||
uint16_t temp;
|
||||
uint16_t addr = getwordf();
|
||||
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;
|
||||
CLOCK_CYCLES((is486) ? 1 : 4);
|
||||
PREFETCH_RUN(4, 3, -1, 1,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opMOV_AX_a32(uint32_t fetchdat)
|
||||
{
|
||||
uint16_t temp;
|
||||
uint32_t addr = getlong();
|
||||
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;
|
||||
CLOCK_CYCLES((is486) ? 1 : 4);
|
||||
PREFETCH_RUN(4, 5, -1, 1,0,0,0, 1);
|
||||
return 0;
|
||||
}
|
||||
static int opMOV_EAX_a16(uint32_t fetchdat)
|
||||
{
|
||||
uint32_t temp;
|
||||
uint16_t addr = getwordf();
|
||||
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;
|
||||
CLOCK_CYCLES((is486) ? 1 : 4);
|
||||
PREFETCH_RUN(4, 3, -1, 0,1,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opMOV_EAX_a32(uint32_t fetchdat)
|
||||
{
|
||||
uint32_t temp;
|
||||
uint32_t addr = getlong();
|
||||
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;
|
||||
CLOCK_CYCLES((is486) ? 1 : 4);
|
||||
PREFETCH_RUN(4, 5, -1, 0,1,0,0, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opMOV_a16_AL(uint32_t fetchdat)
|
||||
{
|
||||
uint16_t addr = getwordf();
|
||||
SEG_CHECK_WRITE(cpu_state.ea_seg);
|
||||
CHECK_WRITE_COMMON(cpu_state.ea_seg, addr, addr);
|
||||
writememb(cpu_state.ea_seg->base, addr, AL);
|
||||
CLOCK_CYCLES((is486) ? 1 : 2);
|
||||
PREFETCH_RUN(2, 3, -1, 0,0,1,0, 0);
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
static int opMOV_a32_AL(uint32_t fetchdat)
|
||||
{
|
||||
uint32_t addr = getlong();
|
||||
SEG_CHECK_WRITE(cpu_state.ea_seg);
|
||||
CHECK_WRITE_COMMON(cpu_state.ea_seg, addr, addr);
|
||||
writememb(cpu_state.ea_seg->base, addr, AL);
|
||||
CLOCK_CYCLES((is486) ? 1 : 2);
|
||||
PREFETCH_RUN(2, 5, -1, 0,0,1,0, 1);
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
static int opMOV_a16_AX(uint32_t fetchdat)
|
||||
{
|
||||
uint16_t addr = getwordf();
|
||||
SEG_CHECK_WRITE(cpu_state.ea_seg);
|
||||
CHECK_WRITE_COMMON(cpu_state.ea_seg, addr, addr + 1);
|
||||
writememw(cpu_state.ea_seg->base, addr, AX);
|
||||
CLOCK_CYCLES((is486) ? 1 : 2);
|
||||
PREFETCH_RUN(2, 3, -1, 0,0,1,0, 0);
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
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);
|
||||
CHECK_WRITE_COMMON(cpu_state.ea_seg, addr, addr + 1);
|
||||
writememw(cpu_state.ea_seg->base, addr, AX);
|
||||
CLOCK_CYCLES((is486) ? 1 : 2);
|
||||
PREFETCH_RUN(2, 5, -1, 0,0,1,0, 1);
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
static int opMOV_a16_EAX(uint32_t fetchdat)
|
||||
{
|
||||
uint16_t addr = getwordf();
|
||||
SEG_CHECK_WRITE(cpu_state.ea_seg);
|
||||
CHECK_WRITE_COMMON(cpu_state.ea_seg, addr, addr + 3);
|
||||
writememl(cpu_state.ea_seg->base, addr, EAX);
|
||||
CLOCK_CYCLES((is486) ? 1 : 2);
|
||||
PREFETCH_RUN(2, 3, -1, 0,0,0,1, 0);
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
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);
|
||||
CHECK_WRITE_COMMON(cpu_state.ea_seg, addr, addr + 3);
|
||||
writememl(cpu_state.ea_seg->base, addr, EAX);
|
||||
CLOCK_CYCLES((is486) ? 1 : 2);
|
||||
PREFETCH_RUN(2, 5, -1, 0,0,0,1, 1);
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
|
||||
|
||||
static int opLEA_w_a16(uint32_t fetchdat)
|
||||
{
|
||||
fetch_ea_16(fetchdat);
|
||||
ILLEGAL_ON(cpu_mod == 3);
|
||||
cpu_state.regs[cpu_reg].w = cpu_state.eaaddr;
|
||||
CLOCK_CYCLES(timing_rr);
|
||||
PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opLEA_w_a32(uint32_t fetchdat)
|
||||
{
|
||||
fetch_ea_32(fetchdat);
|
||||
ILLEGAL_ON(cpu_mod == 3);
|
||||
cpu_state.regs[cpu_reg].w = cpu_state.eaaddr;
|
||||
CLOCK_CYCLES(timing_rr);
|
||||
PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opLEA_l_a16(uint32_t fetchdat)
|
||||
{
|
||||
fetch_ea_16(fetchdat);
|
||||
ILLEGAL_ON(cpu_mod == 3);
|
||||
cpu_state.regs[cpu_reg].l = cpu_state.eaaddr & 0xffff;
|
||||
CLOCK_CYCLES(timing_rr);
|
||||
PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opLEA_l_a32(uint32_t fetchdat)
|
||||
{
|
||||
fetch_ea_32(fetchdat);
|
||||
ILLEGAL_ON(cpu_mod == 3);
|
||||
cpu_state.regs[cpu_reg].l = cpu_state.eaaddr;
|
||||
CLOCK_CYCLES(timing_rr);
|
||||
PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int opXLAT_a16(uint32_t fetchdat)
|
||||
{
|
||||
uint32_t addr = (BX + AL)&0xFFFF;
|
||||
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);
|
||||
return 0;
|
||||
}
|
||||
static int opXLAT_a32(uint32_t fetchdat)
|
||||
{
|
||||
uint32_t addr = EBX + AL;
|
||||
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);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opMOV_b_r_a16(uint32_t fetchdat)
|
||||
{
|
||||
fetch_ea_16(fetchdat);
|
||||
if (cpu_mod == 3)
|
||||
{
|
||||
setr8(cpu_rm, getr8(cpu_reg));
|
||||
CLOCK_CYCLES(timing_rr);
|
||||
PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
SEG_CHECK_WRITE(cpu_state.ea_seg);
|
||||
seteab(getr8(cpu_reg));
|
||||
CLOCK_CYCLES(is486 ? 1 : 2);
|
||||
PREFETCH_RUN(2, 2, rmdat, 0,0,1,0, 0);
|
||||
}
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
static int opMOV_b_r_a32(uint32_t fetchdat)
|
||||
{
|
||||
fetch_ea_32(fetchdat);
|
||||
if (cpu_mod == 3)
|
||||
{
|
||||
setr8(cpu_rm, getr8(cpu_reg));
|
||||
CLOCK_CYCLES(timing_rr);
|
||||
PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
SEG_CHECK_WRITE(cpu_state.ea_seg);
|
||||
seteab(getr8(cpu_reg));
|
||||
CLOCK_CYCLES(is486 ? 1 : 2);
|
||||
PREFETCH_RUN(2, 2, rmdat, 0,0,1,0, 1);
|
||||
}
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
static int opMOV_w_r_a16(uint32_t fetchdat)
|
||||
{
|
||||
fetch_ea_16(fetchdat);
|
||||
if (cpu_mod == 3)
|
||||
{
|
||||
cpu_state.regs[cpu_rm].w = cpu_state.regs[cpu_reg].w;
|
||||
CLOCK_CYCLES(timing_rr);
|
||||
PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
SEG_CHECK_WRITE(cpu_state.ea_seg);
|
||||
seteaw(cpu_state.regs[cpu_reg].w);
|
||||
CLOCK_CYCLES(is486 ? 1 : 2);
|
||||
PREFETCH_RUN(2, 2, rmdat, 0,0,1,0, 0);
|
||||
}
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
static int opMOV_w_r_a32(uint32_t fetchdat)
|
||||
{
|
||||
fetch_ea_32(fetchdat);
|
||||
if (cpu_mod == 3)
|
||||
{
|
||||
cpu_state.regs[cpu_rm].w = cpu_state.regs[cpu_reg].w;
|
||||
CLOCK_CYCLES(timing_rr);
|
||||
PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
SEG_CHECK_WRITE(cpu_state.ea_seg);
|
||||
seteaw(cpu_state.regs[cpu_reg].w);
|
||||
CLOCK_CYCLES(is486 ? 1 : 2);
|
||||
PREFETCH_RUN(2, 2, rmdat, 0,0,1,0, 1);
|
||||
}
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
static int opMOV_l_r_a16(uint32_t fetchdat)
|
||||
{
|
||||
fetch_ea_16(fetchdat);
|
||||
if (cpu_mod == 3)
|
||||
{
|
||||
cpu_state.regs[cpu_rm].l = cpu_state.regs[cpu_reg].l;
|
||||
CLOCK_CYCLES(timing_rr);
|
||||
PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
SEG_CHECK_WRITE(cpu_state.ea_seg);
|
||||
seteal(cpu_state.regs[cpu_reg].l);
|
||||
CLOCK_CYCLES(is486 ? 1 : 2);
|
||||
PREFETCH_RUN(2, 2, rmdat, 0,0,0,1, 0);
|
||||
}
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
static int opMOV_l_r_a32(uint32_t fetchdat)
|
||||
{
|
||||
fetch_ea_32(fetchdat);
|
||||
if (cpu_mod == 3)
|
||||
{
|
||||
cpu_state.regs[cpu_rm].l = cpu_state.regs[cpu_reg].l;
|
||||
CLOCK_CYCLES(timing_rr);
|
||||
PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
SEG_CHECK_WRITE(cpu_state.ea_seg);
|
||||
seteal(cpu_state.regs[cpu_reg].l);
|
||||
CLOCK_CYCLES(is486 ? 1 : 2);
|
||||
PREFETCH_RUN(2, 2, rmdat, 0,0,0,1, 1);
|
||||
}
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
|
||||
static int opMOV_r_b_a16(uint32_t fetchdat)
|
||||
{
|
||||
fetch_ea_16(fetchdat);
|
||||
if (cpu_mod == 3)
|
||||
{
|
||||
setr8(cpu_reg, getr8(cpu_rm));
|
||||
CLOCK_CYCLES(timing_rr);
|
||||
PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 0);
|
||||
}
|
||||
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);
|
||||
CLOCK_CYCLES(is486 ? 1 : 4);
|
||||
PREFETCH_RUN(4, 2, rmdat, 1,0,0,0, 0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static int opMOV_r_b_a32(uint32_t fetchdat)
|
||||
{
|
||||
fetch_ea_32(fetchdat);
|
||||
if (cpu_mod == 3)
|
||||
{
|
||||
setr8(cpu_reg, getr8(cpu_rm));
|
||||
CLOCK_CYCLES(timing_rr);
|
||||
PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 1);
|
||||
}
|
||||
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);
|
||||
CLOCK_CYCLES(is486 ? 1 : 4);
|
||||
PREFETCH_RUN(4, 2, rmdat, 1,0,0,0, 1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static int opMOV_r_w_a16(uint32_t fetchdat)
|
||||
{
|
||||
fetch_ea_16(fetchdat);
|
||||
if (cpu_mod == 3)
|
||||
{
|
||||
cpu_state.regs[cpu_reg].w = cpu_state.regs[cpu_rm].w;
|
||||
CLOCK_CYCLES(timing_rr);
|
||||
PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 0);
|
||||
}
|
||||
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;
|
||||
CLOCK_CYCLES((is486) ? 1 : 4);
|
||||
PREFETCH_RUN(4, 2, rmdat, 1,0,0,0, 0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static int opMOV_r_w_a32(uint32_t fetchdat)
|
||||
{
|
||||
fetch_ea_32(fetchdat);
|
||||
if (cpu_mod == 3)
|
||||
{
|
||||
cpu_state.regs[cpu_reg].w = cpu_state.regs[cpu_rm].w;
|
||||
CLOCK_CYCLES(timing_rr);
|
||||
PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 1);
|
||||
}
|
||||
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;
|
||||
CLOCK_CYCLES((is486) ? 1 : 4);
|
||||
PREFETCH_RUN(4, 2, rmdat, 1,0,0,0, 1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static int opMOV_r_l_a16(uint32_t fetchdat)
|
||||
{
|
||||
fetch_ea_16(fetchdat);
|
||||
if (cpu_mod == 3)
|
||||
{
|
||||
cpu_state.regs[cpu_reg].l = cpu_state.regs[cpu_rm].l;
|
||||
CLOCK_CYCLES(timing_rr);
|
||||
PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 0);
|
||||
}
|
||||
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;
|
||||
CLOCK_CYCLES(is486 ? 1 : 4);
|
||||
PREFETCH_RUN(4, 2, rmdat, 0,1,0,0, 0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
static int opMOV_r_l_a32(uint32_t fetchdat)
|
||||
{
|
||||
fetch_ea_32(fetchdat);
|
||||
if (cpu_mod == 3)
|
||||
{
|
||||
cpu_state.regs[cpu_reg].l = cpu_state.regs[cpu_rm].l;
|
||||
CLOCK_CYCLES(timing_rr);
|
||||
PREFETCH_RUN(timing_rr, 2, rmdat, 0,0,0,0, 1);
|
||||
}
|
||||
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;
|
||||
CLOCK_CYCLES(is486 ? 1 : 4);
|
||||
PREFETCH_RUN(4, 2, rmdat, 0,1,0,0, 1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(USE_NEW_DYNAREC) || (defined(DEV_BRANCH) && (defined(USE_CYRIX_6X86) || defined(USE_I686)))
|
||||
#define opCMOV(condition) \
|
||||
static int opCMOV ## condition ## _w_a16(uint32_t fetchdat) \
|
||||
{ \
|
||||
fetch_ea_16(fetchdat); \
|
||||
if (cond_ ## condition) \
|
||||
{ \
|
||||
if (cpu_mod == 3) \
|
||||
cpu_state.regs[cpu_reg].w = cpu_state.regs[cpu_rm].w; \
|
||||
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; \
|
||||
} \
|
||||
} \
|
||||
CLOCK_CYCLES(1); \
|
||||
return 0; \
|
||||
} \
|
||||
static int opCMOV ## condition ## _w_a32(uint32_t fetchdat) \
|
||||
{ \
|
||||
fetch_ea_32(fetchdat); \
|
||||
if (cond_ ## condition) \
|
||||
{ \
|
||||
if (cpu_mod == 3) \
|
||||
cpu_state.regs[cpu_reg].w = cpu_state.regs[cpu_rm].w; \
|
||||
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; \
|
||||
} \
|
||||
} \
|
||||
CLOCK_CYCLES(1); \
|
||||
return 0; \
|
||||
} \
|
||||
static int opCMOV ## condition ## _l_a16(uint32_t fetchdat) \
|
||||
{ \
|
||||
fetch_ea_16(fetchdat); \
|
||||
if (cond_ ## condition) \
|
||||
{ \
|
||||
if (cpu_mod == 3) \
|
||||
cpu_state.regs[cpu_reg].l = cpu_state.regs[cpu_rm].l; \
|
||||
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; \
|
||||
} \
|
||||
} \
|
||||
CLOCK_CYCLES(1); \
|
||||
return 0; \
|
||||
} \
|
||||
static int opCMOV ## condition ## _l_a32(uint32_t fetchdat) \
|
||||
{ \
|
||||
fetch_ea_32(fetchdat); \
|
||||
if (cond_ ## condition) \
|
||||
{ \
|
||||
if (cpu_mod == 3) \
|
||||
cpu_state.regs[cpu_reg].l = cpu_state.regs[cpu_rm].l; \
|
||||
else \
|
||||
{ \
|
||||
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; \
|
||||
} \
|
||||
} \
|
||||
CLOCK_CYCLES(1); \
|
||||
return 0; \
|
||||
}
|
||||
|
||||
opCMOV(O)
|
||||
opCMOV(NO)
|
||||
opCMOV(B)
|
||||
opCMOV(NB)
|
||||
opCMOV(E)
|
||||
opCMOV(NE)
|
||||
opCMOV(BE)
|
||||
opCMOV(NBE)
|
||||
opCMOV(S)
|
||||
opCMOV(NS)
|
||||
opCMOV(P)
|
||||
opCMOV(NP)
|
||||
opCMOV(L)
|
||||
opCMOV(NL)
|
||||
opCMOV(LE)
|
||||
opCMOV(NLE)
|
||||
#endif
|
||||
290
src/cpu_common/x86_ops_mov_ctrl.h
Normal file
290
src/cpu_common/x86_ops_mov_ctrl.h
Normal file
@@ -0,0 +1,290 @@
|
||||
static int opMOV_r_CRx_a16(uint32_t fetchdat)
|
||||
{
|
||||
if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1))
|
||||
{
|
||||
x86gpf(NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
fetch_ea_16(fetchdat);
|
||||
switch (cpu_reg)
|
||||
{
|
||||
case 0:
|
||||
cpu_state.regs[cpu_rm].l = cr0;
|
||||
if (is486)
|
||||
cpu_state.regs[cpu_rm].l |= 0x10; /*ET hardwired on 486*/
|
||||
break;
|
||||
case 2:
|
||||
cpu_state.regs[cpu_rm].l = cr2;
|
||||
break;
|
||||
case 3:
|
||||
cpu_state.regs[cpu_rm].l = cr3;
|
||||
break;
|
||||
case 4:
|
||||
if (cpu_has_feature(CPU_FEATURE_CR4))
|
||||
{
|
||||
cpu_state.regs[cpu_rm].l = cr4;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
cpu_state.pc = cpu_state.oldpc;
|
||||
x86illegal();
|
||||
break;
|
||||
}
|
||||
CLOCK_CYCLES(6);
|
||||
PREFETCH_RUN(6, 2, rmdat, 0,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opMOV_r_CRx_a32(uint32_t fetchdat)
|
||||
{
|
||||
if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1))
|
||||
{
|
||||
x86gpf(NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
fetch_ea_32(fetchdat);
|
||||
switch (cpu_reg)
|
||||
{
|
||||
case 0:
|
||||
cpu_state.regs[cpu_rm].l = cr0;
|
||||
if (is486)
|
||||
cpu_state.regs[cpu_rm].l |= 0x10; /*ET hardwired on 486*/
|
||||
break;
|
||||
case 2:
|
||||
cpu_state.regs[cpu_rm].l = cr2;
|
||||
break;
|
||||
case 3:
|
||||
cpu_state.regs[cpu_rm].l = cr3;
|
||||
break;
|
||||
case 4:
|
||||
if (cpu_has_feature(CPU_FEATURE_CR4))
|
||||
{
|
||||
cpu_state.regs[cpu_rm].l = cr4;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
cpu_state.pc = cpu_state.oldpc;
|
||||
x86illegal();
|
||||
break;
|
||||
}
|
||||
CLOCK_CYCLES(6);
|
||||
PREFETCH_RUN(6, 2, rmdat, 0,0,0,0, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opMOV_r_DRx_a16(uint32_t fetchdat)
|
||||
{
|
||||
if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1))
|
||||
{
|
||||
x86gpf(NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
fetch_ea_16(fetchdat);
|
||||
cpu_state.regs[cpu_rm].l = dr[cpu_reg];
|
||||
CLOCK_CYCLES(6);
|
||||
PREFETCH_RUN(6, 2, rmdat, 0,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opMOV_r_DRx_a32(uint32_t fetchdat)
|
||||
{
|
||||
if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1))
|
||||
{
|
||||
x86gpf(NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
fetch_ea_32(fetchdat);
|
||||
cpu_state.regs[cpu_rm].l = dr[cpu_reg];
|
||||
CLOCK_CYCLES(6);
|
||||
PREFETCH_RUN(6, 2, rmdat, 0,0,0,0, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opMOV_CRx_r_a16(uint32_t fetchdat)
|
||||
{
|
||||
uint32_t old_cr0 = cr0;
|
||||
|
||||
if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1))
|
||||
{
|
||||
x86gpf(NULL,0);
|
||||
return 1;
|
||||
}
|
||||
fetch_ea_16(fetchdat);
|
||||
switch (cpu_reg)
|
||||
{
|
||||
case 0:
|
||||
if ((cpu_state.regs[cpu_rm].l ^ cr0) & 0x80000001)
|
||||
flushmmucache();
|
||||
cr0 = cpu_state.regs[cpu_rm].l;
|
||||
if (cpu_16bitbus)
|
||||
cr0 |= 0x10;
|
||||
if (!(cr0 & 0x80000000))
|
||||
mmu_perm=4;
|
||||
if (is486 && !(cr0 & (1 << 30)))
|
||||
cpu_cache_int_enabled = 1;
|
||||
else if (isibmcpu)
|
||||
cpu_cache_int_enabled = 1;
|
||||
else
|
||||
cpu_cache_int_enabled = 0;
|
||||
if (is486 && ((cr0 ^ old_cr0) & (1 << 30)))
|
||||
cpu_update_waitstates();
|
||||
if (cr0 & 1)
|
||||
cpu_cur_status |= CPU_STATUS_PMODE;
|
||||
else
|
||||
cpu_cur_status &= ~CPU_STATUS_PMODE;
|
||||
break;
|
||||
case 2:
|
||||
cr2 = cpu_state.regs[cpu_rm].l;
|
||||
break;
|
||||
case 3:
|
||||
cr3 = cpu_state.regs[cpu_rm].l;
|
||||
flushmmucache();
|
||||
break;
|
||||
case 4:
|
||||
if (cpu_has_feature(CPU_FEATURE_CR4))
|
||||
{
|
||||
cr4 = cpu_state.regs[cpu_rm].l & cpu_CR4_mask;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
cpu_state.pc = cpu_state.oldpc;
|
||||
x86illegal();
|
||||
break;
|
||||
}
|
||||
CLOCK_CYCLES(10);
|
||||
PREFETCH_RUN(10, 2, rmdat, 0,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opMOV_CRx_r_a32(uint32_t fetchdat)
|
||||
{
|
||||
uint32_t old_cr0 = cr0;
|
||||
|
||||
if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1))
|
||||
{
|
||||
x86gpf(NULL,0);
|
||||
return 1;
|
||||
}
|
||||
fetch_ea_32(fetchdat);
|
||||
switch (cpu_reg)
|
||||
{
|
||||
case 0:
|
||||
if ((cpu_state.regs[cpu_rm].l ^ cr0) & 0x80000001)
|
||||
flushmmucache();
|
||||
cr0 = cpu_state.regs[cpu_rm].l;
|
||||
if (cpu_16bitbus)
|
||||
cr0 |= 0x10;
|
||||
if (!(cr0 & 0x80000000))
|
||||
mmu_perm=4;
|
||||
if (is486 && !(cr0 & (1 << 30)))
|
||||
cpu_cache_int_enabled = 1;
|
||||
else
|
||||
cpu_cache_int_enabled = 0;
|
||||
if (is486 && ((cr0 ^ old_cr0) & (1 << 30)))
|
||||
cpu_update_waitstates();
|
||||
if (cr0 & 1)
|
||||
cpu_cur_status |= CPU_STATUS_PMODE;
|
||||
else
|
||||
cpu_cur_status &= ~CPU_STATUS_PMODE;
|
||||
break;
|
||||
case 2:
|
||||
cr2 = cpu_state.regs[cpu_rm].l;
|
||||
break;
|
||||
case 3:
|
||||
cr3 = cpu_state.regs[cpu_rm].l;
|
||||
flushmmucache();
|
||||
break;
|
||||
case 4:
|
||||
if (cpu_has_feature(CPU_FEATURE_CR4))
|
||||
{
|
||||
cr4 = cpu_state.regs[cpu_rm].l & cpu_CR4_mask;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
cpu_state.pc = cpu_state.oldpc;
|
||||
x86illegal();
|
||||
break;
|
||||
}
|
||||
CLOCK_CYCLES(10);
|
||||
PREFETCH_RUN(10, 2, rmdat, 0,0,0,0, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opMOV_DRx_r_a16(uint32_t fetchdat)
|
||||
{
|
||||
if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1))
|
||||
{
|
||||
x86gpf(NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
fetch_ea_16(fetchdat);
|
||||
dr[cpu_reg] = cpu_state.regs[cpu_rm].l;
|
||||
CLOCK_CYCLES(6);
|
||||
PREFETCH_RUN(6, 2, rmdat, 0,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opMOV_DRx_r_a32(uint32_t fetchdat)
|
||||
{
|
||||
if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1))
|
||||
{
|
||||
x86gpf(NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
fetch_ea_16(fetchdat);
|
||||
dr[cpu_reg] = cpu_state.regs[cpu_rm].l;
|
||||
CLOCK_CYCLES(6);
|
||||
PREFETCH_RUN(6, 2, rmdat, 0,0,0,0, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opMOV_r_TRx_a16(uint32_t fetchdat)
|
||||
{
|
||||
if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1))
|
||||
{
|
||||
x86gpf(NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
fetch_ea_16(fetchdat);
|
||||
cpu_state.regs[cpu_rm].l = 0;
|
||||
CLOCK_CYCLES(6);
|
||||
PREFETCH_RUN(6, 2, rmdat, 0,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opMOV_r_TRx_a32(uint32_t fetchdat)
|
||||
{
|
||||
if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1))
|
||||
{
|
||||
x86gpf(NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
fetch_ea_32(fetchdat);
|
||||
cpu_state.regs[cpu_rm].l = 0;
|
||||
CLOCK_CYCLES(6);
|
||||
PREFETCH_RUN(6, 2, rmdat, 0,0,0,0, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opMOV_TRx_r_a16(uint32_t fetchdat)
|
||||
{
|
||||
if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1))
|
||||
{
|
||||
x86gpf(NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
fetch_ea_16(fetchdat);
|
||||
CLOCK_CYCLES(6);
|
||||
PREFETCH_RUN(6, 2, rmdat, 0,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opMOV_TRx_r_a32(uint32_t fetchdat)
|
||||
{
|
||||
if ((CPL || (cpu_state.eflags&VM_FLAG)) && (cr0&1))
|
||||
{
|
||||
x86gpf(NULL, 0);
|
||||
return 1;
|
||||
}
|
||||
fetch_ea_16(fetchdat);
|
||||
CLOCK_CYCLES(6);
|
||||
PREFETCH_RUN(6, 2, rmdat, 0,0,0,0, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
434
src/cpu_common/x86_ops_mov_seg.h
Normal file
434
src/cpu_common/x86_ops_mov_seg.h
Normal file
@@ -0,0 +1,434 @@
|
||||
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*/
|
||||
seteaw(ES);
|
||||
break;
|
||||
case 0x08: /*CS*/
|
||||
seteaw(CS);
|
||||
break;
|
||||
case 0x18: /*DS*/
|
||||
seteaw(DS);
|
||||
break;
|
||||
case 0x10: /*SS*/
|
||||
seteaw(SS);
|
||||
break;
|
||||
case 0x20: /*FS*/
|
||||
seteaw(FS);
|
||||
break;
|
||||
case 0x28: /*GS*/
|
||||
seteaw(GS);
|
||||
break;
|
||||
}
|
||||
|
||||
CLOCK_CYCLES((cpu_mod == 3) ? 2 : 3);
|
||||
PREFETCH_RUN((cpu_mod == 3) ? 2 : 3, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 0);
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
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*/
|
||||
seteaw(ES);
|
||||
break;
|
||||
case 0x08: /*CS*/
|
||||
seteaw(CS);
|
||||
break;
|
||||
case 0x18: /*DS*/
|
||||
seteaw(DS);
|
||||
break;
|
||||
case 0x10: /*SS*/
|
||||
seteaw(SS);
|
||||
break;
|
||||
case 0x20: /*FS*/
|
||||
seteaw(FS);
|
||||
break;
|
||||
case 0x28: /*GS*/
|
||||
seteaw(GS);
|
||||
break;
|
||||
}
|
||||
|
||||
CLOCK_CYCLES((cpu_mod == 3) ? 2 : 3);
|
||||
PREFETCH_RUN((cpu_mod == 3) ? 2 : 3, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 1);
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
|
||||
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*/
|
||||
if (cpu_mod == 3) cpu_state.regs[cpu_rm].l = ES;
|
||||
else seteaw(ES);
|
||||
break;
|
||||
case 0x08: /*CS*/
|
||||
if (cpu_mod == 3) cpu_state.regs[cpu_rm].l = CS;
|
||||
else seteaw(CS);
|
||||
break;
|
||||
case 0x18: /*DS*/
|
||||
if (cpu_mod == 3) cpu_state.regs[cpu_rm].l = DS;
|
||||
else seteaw(DS);
|
||||
break;
|
||||
case 0x10: /*SS*/
|
||||
if (cpu_mod == 3) cpu_state.regs[cpu_rm].l = SS;
|
||||
else seteaw(SS);
|
||||
break;
|
||||
case 0x20: /*FS*/
|
||||
if (cpu_mod == 3) cpu_state.regs[cpu_rm].l = FS;
|
||||
else seteaw(FS);
|
||||
break;
|
||||
case 0x28: /*GS*/
|
||||
if (cpu_mod == 3) cpu_state.regs[cpu_rm].l = GS;
|
||||
else seteaw(GS);
|
||||
break;
|
||||
}
|
||||
|
||||
CLOCK_CYCLES((cpu_mod == 3) ? 2 : 3);
|
||||
PREFETCH_RUN((cpu_mod == 3) ? 2 : 3, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 0);
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
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*/
|
||||
if (cpu_mod == 3) cpu_state.regs[cpu_rm].l = ES;
|
||||
else seteaw(ES);
|
||||
break;
|
||||
case 0x08: /*CS*/
|
||||
if (cpu_mod == 3) cpu_state.regs[cpu_rm].l = CS;
|
||||
else seteaw(CS);
|
||||
break;
|
||||
case 0x18: /*DS*/
|
||||
if (cpu_mod == 3) cpu_state.regs[cpu_rm].l = DS;
|
||||
else seteaw(DS);
|
||||
break;
|
||||
case 0x10: /*SS*/
|
||||
if (cpu_mod == 3) cpu_state.regs[cpu_rm].l = SS;
|
||||
else seteaw(SS);
|
||||
break;
|
||||
case 0x20: /*FS*/
|
||||
if (cpu_mod == 3) cpu_state.regs[cpu_rm].l = FS;
|
||||
else seteaw(FS);
|
||||
break;
|
||||
case 0x28: /*GS*/
|
||||
if (cpu_mod == 3) cpu_state.regs[cpu_rm].l = GS;
|
||||
else seteaw(GS);
|
||||
break;
|
||||
}
|
||||
|
||||
CLOCK_CYCLES((cpu_mod == 3) ? 2 : 3);
|
||||
PREFETCH_RUN((cpu_mod == 3) ? 2 : 3, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 1);
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
|
||||
static int opMOV_seg_w_a16(uint32_t fetchdat)
|
||||
{
|
||||
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, &cpu_state.seg_es);
|
||||
break;
|
||||
case 0x18: /*DS*/
|
||||
loadseg(new_seg, &cpu_state.seg_ds);
|
||||
break;
|
||||
case 0x10: /*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 = &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, &cpu_state.seg_fs);
|
||||
break;
|
||||
case 0x28: /*GS*/
|
||||
loadseg(new_seg, &cpu_state.seg_gs);
|
||||
break;
|
||||
}
|
||||
|
||||
CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5);
|
||||
PREFETCH_RUN((cpu_mod == 3) ? 2 : 5, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 0);
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
static int opMOV_seg_w_a32(uint32_t fetchdat)
|
||||
{
|
||||
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, &cpu_state.seg_es);
|
||||
break;
|
||||
case 0x18: /*DS*/
|
||||
loadseg(new_seg, &cpu_state.seg_ds);
|
||||
break;
|
||||
case 0x10: /*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 = &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, &cpu_state.seg_fs);
|
||||
break;
|
||||
case 0x28: /*GS*/
|
||||
loadseg(new_seg, &cpu_state.seg_gs);
|
||||
break;
|
||||
}
|
||||
|
||||
CLOCK_CYCLES((cpu_mod == 3) ? 2 : 5);
|
||||
PREFETCH_RUN((cpu_mod == 3) ? 2 : 5, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,0, 1);
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
|
||||
|
||||
static int opLDS_w_a16(uint32_t fetchdat)
|
||||
{
|
||||
uint16_t addr, seg;
|
||||
|
||||
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, &cpu_state.seg_ds); if (cpu_state.abrt) return 1;
|
||||
cpu_state.regs[cpu_reg].w = addr;
|
||||
|
||||
CLOCK_CYCLES(7);
|
||||
PREFETCH_RUN(7, 2, rmdat, 2,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opLDS_w_a32(uint32_t fetchdat)
|
||||
{
|
||||
uint16_t addr, seg;
|
||||
|
||||
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, &cpu_state.seg_ds); if (cpu_state.abrt) return 1;
|
||||
cpu_state.regs[cpu_reg].w = addr;
|
||||
|
||||
CLOCK_CYCLES(7);
|
||||
PREFETCH_RUN(7, 2, rmdat, 2,0,0,0, 1);
|
||||
return 0;
|
||||
}
|
||||
static int opLDS_l_a16(uint32_t fetchdat)
|
||||
{
|
||||
uint32_t addr;
|
||||
uint16_t seg;
|
||||
|
||||
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, &cpu_state.seg_ds); if (cpu_state.abrt) return 1;
|
||||
cpu_state.regs[cpu_reg].l = addr;
|
||||
|
||||
CLOCK_CYCLES(7);
|
||||
PREFETCH_RUN(7, 2, rmdat, 1,1,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opLDS_l_a32(uint32_t fetchdat)
|
||||
{
|
||||
uint32_t addr;
|
||||
uint16_t seg;
|
||||
|
||||
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, &cpu_state.seg_ds); if (cpu_state.abrt) return 1;
|
||||
cpu_state.regs[cpu_reg].l = addr;
|
||||
|
||||
CLOCK_CYCLES(7);
|
||||
PREFETCH_RUN(7, 2, rmdat, 1,1,0,0, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opLSS_w_a16(uint32_t fetchdat)
|
||||
{
|
||||
uint16_t addr, seg;
|
||||
|
||||
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, &cpu_state.seg_ss); if (cpu_state.abrt) return 1;
|
||||
cpu_state.regs[cpu_reg].w = addr;
|
||||
|
||||
CLOCK_CYCLES(7);
|
||||
PREFETCH_RUN(7, 2, rmdat, 2,0,0,0, 0);
|
||||
return 1;
|
||||
}
|
||||
static int opLSS_w_a32(uint32_t fetchdat)
|
||||
{
|
||||
uint16_t addr, seg;
|
||||
|
||||
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, &cpu_state.seg_ss); if (cpu_state.abrt) return 1;
|
||||
cpu_state.regs[cpu_reg].w = addr;
|
||||
|
||||
CLOCK_CYCLES(7);
|
||||
PREFETCH_RUN(7, 2, rmdat, 2,0,0,0, 1);
|
||||
return 1;
|
||||
}
|
||||
static int opLSS_l_a16(uint32_t fetchdat)
|
||||
{
|
||||
uint32_t addr;
|
||||
uint16_t seg;
|
||||
|
||||
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, &cpu_state.seg_ss); if (cpu_state.abrt) return 1;
|
||||
cpu_state.regs[cpu_reg].l = addr;
|
||||
|
||||
CLOCK_CYCLES(7);
|
||||
PREFETCH_RUN(7, 2, rmdat, 2,0,0,0, 0);
|
||||
return 1;
|
||||
}
|
||||
static int opLSS_l_a32(uint32_t fetchdat)
|
||||
{
|
||||
uint32_t addr;
|
||||
uint16_t seg;
|
||||
|
||||
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, &cpu_state.seg_ss); if (cpu_state.abrt) return 1;
|
||||
cpu_state.regs[cpu_reg].l = addr;
|
||||
|
||||
CLOCK_CYCLES(7);
|
||||
PREFETCH_RUN(7, 2, rmdat, 2,0,0,0, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define opLsel(name, sel) \
|
||||
static int opL ## name ## _w_a16(uint32_t fetchdat) \
|
||||
{ \
|
||||
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; \
|
||||
loadseg(seg, &sel); if (cpu_state.abrt) return 1; \
|
||||
cpu_state.regs[cpu_reg].w = addr; \
|
||||
\
|
||||
CLOCK_CYCLES(7); \
|
||||
PREFETCH_RUN(7, 2, rmdat, 2,0,0,0, 0); \
|
||||
return 0; \
|
||||
} \
|
||||
\
|
||||
static int opL ## name ## _w_a32(uint32_t fetchdat) \
|
||||
{ \
|
||||
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; \
|
||||
loadseg(seg, &sel); if (cpu_state.abrt) return 1; \
|
||||
cpu_state.regs[cpu_reg].w = addr; \
|
||||
\
|
||||
CLOCK_CYCLES(7); \
|
||||
PREFETCH_RUN(7, 2, rmdat, 2,0,0,0, 1); \
|
||||
return 0; \
|
||||
} \
|
||||
\
|
||||
static int opL ## name ## _l_a16(uint32_t fetchdat) \
|
||||
{ \
|
||||
uint32_t addr; \
|
||||
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; \
|
||||
loadseg(seg, &sel); if (cpu_state.abrt) return 1; \
|
||||
cpu_state.regs[cpu_reg].l = addr; \
|
||||
\
|
||||
CLOCK_CYCLES(7); \
|
||||
PREFETCH_RUN(7, 2, rmdat, 1,1,0,0, 0); \
|
||||
return 0; \
|
||||
} \
|
||||
\
|
||||
static int opL ## name ## _l_a32(uint32_t fetchdat) \
|
||||
{ \
|
||||
uint32_t addr; \
|
||||
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; \
|
||||
loadseg(seg, &sel); if (cpu_state.abrt) return 1; \
|
||||
cpu_state.regs[cpu_reg].l = addr; \
|
||||
\
|
||||
CLOCK_CYCLES(7); \
|
||||
PREFETCH_RUN(7, 2, rmdat, 1,1,0,0, 1); \
|
||||
return 0; \
|
||||
}
|
||||
|
||||
opLsel(ES, cpu_state.seg_es)
|
||||
opLsel(FS, cpu_state.seg_fs)
|
||||
opLsel(GS, cpu_state.seg_gs)
|
||||
209
src/cpu_common/x86_ops_movx.h
Normal file
209
src/cpu_common/x86_ops_movx.h
Normal file
@@ -0,0 +1,209 @@
|
||||
static int opMOVZX_w_b_a16(uint32_t fetchdat)
|
||||
{
|
||||
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;
|
||||
|
||||
CLOCK_CYCLES(3);
|
||||
PREFETCH_RUN(3, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opMOVZX_w_b_a32(uint32_t fetchdat)
|
||||
{
|
||||
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;
|
||||
|
||||
CLOCK_CYCLES(3);
|
||||
PREFETCH_RUN(3, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1);
|
||||
return 0;
|
||||
}
|
||||
static int opMOVZX_l_b_a16(uint32_t fetchdat)
|
||||
{
|
||||
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;
|
||||
|
||||
CLOCK_CYCLES(3);
|
||||
PREFETCH_RUN(3, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opMOVZX_l_b_a32(uint32_t fetchdat)
|
||||
{
|
||||
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;
|
||||
|
||||
CLOCK_CYCLES(3);
|
||||
PREFETCH_RUN(3, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1);
|
||||
return 0;
|
||||
}
|
||||
static int opMOVZX_w_w_a16(uint32_t fetchdat)
|
||||
{
|
||||
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;
|
||||
|
||||
CLOCK_CYCLES(3);
|
||||
PREFETCH_RUN(3, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opMOVZX_w_w_a32(uint32_t fetchdat)
|
||||
{
|
||||
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;
|
||||
|
||||
CLOCK_CYCLES(3);
|
||||
PREFETCH_RUN(3, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1);
|
||||
return 0;
|
||||
}
|
||||
static int opMOVZX_l_w_a16(uint32_t fetchdat)
|
||||
{
|
||||
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;
|
||||
|
||||
CLOCK_CYCLES(3);
|
||||
PREFETCH_RUN(3, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opMOVZX_l_w_a32(uint32_t fetchdat)
|
||||
{
|
||||
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;
|
||||
|
||||
CLOCK_CYCLES(3);
|
||||
PREFETCH_RUN(3, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opMOVSX_w_b_a16(uint32_t fetchdat)
|
||||
{
|
||||
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)
|
||||
cpu_state.regs[cpu_reg].w |= 0xff00;
|
||||
|
||||
CLOCK_CYCLES(3);
|
||||
PREFETCH_RUN(3, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opMOVSX_w_b_a32(uint32_t fetchdat)
|
||||
{
|
||||
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)
|
||||
cpu_state.regs[cpu_reg].w |= 0xff00;
|
||||
|
||||
CLOCK_CYCLES(3);
|
||||
PREFETCH_RUN(3, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1);
|
||||
return 0;
|
||||
}
|
||||
static int opMOVSX_l_b_a16(uint32_t fetchdat)
|
||||
{
|
||||
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)
|
||||
cpu_state.regs[cpu_reg].l |= 0xffffff00;
|
||||
|
||||
CLOCK_CYCLES(3);
|
||||
PREFETCH_RUN(3, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opMOVSX_l_b_a32(uint32_t fetchdat)
|
||||
{
|
||||
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)
|
||||
cpu_state.regs[cpu_reg].l |= 0xffffff00;
|
||||
|
||||
CLOCK_CYCLES(3);
|
||||
PREFETCH_RUN(3, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1);
|
||||
return 0;
|
||||
}
|
||||
static int opMOVSX_l_w_a16(uint32_t fetchdat)
|
||||
{
|
||||
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)
|
||||
cpu_state.regs[cpu_reg].l |= 0xffff0000;
|
||||
|
||||
CLOCK_CYCLES(3);
|
||||
PREFETCH_RUN(3, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opMOVSX_l_w_a32(uint32_t fetchdat)
|
||||
{
|
||||
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)
|
||||
cpu_state.regs[cpu_reg].l |= 0xffff0000;
|
||||
|
||||
CLOCK_CYCLES(3);
|
||||
PREFETCH_RUN(3, 2, rmdat, (cpu_mod == 3) ? 0:1,0,0,0, 1);
|
||||
return 0;
|
||||
}
|
||||
30
src/cpu_common/x86_ops_msr.h
Normal file
30
src/cpu_common/x86_ops_msr.h
Normal file
@@ -0,0 +1,30 @@
|
||||
static int opRDTSC(uint32_t fetchdat)
|
||||
{
|
||||
if (!cpu_has_feature(CPU_FEATURE_RDTSC))
|
||||
{
|
||||
cpu_state.pc = cpu_state.oldpc;
|
||||
x86illegal();
|
||||
return 1;
|
||||
}
|
||||
if ((cr4 & CR4_TSD) && CPL)
|
||||
{
|
||||
x86gpf("RDTSC when TSD set and CPL != 0", 0);
|
||||
return 1;
|
||||
}
|
||||
EAX = tsc & 0xffffffff;
|
||||
EDX = tsc >> 32;
|
||||
CLOCK_CYCLES(1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opRDPMC(uint32_t fetchdat)
|
||||
{
|
||||
if (ECX > 1 || (!(cr4 & CR4_PCE) && (cr0 & 1) && CPL))
|
||||
{
|
||||
x86gpf("RDPMC not allowed", 0);
|
||||
return 1;
|
||||
}
|
||||
EAX = EDX = 0;
|
||||
CLOCK_CYCLES(1);
|
||||
return 0;
|
||||
}
|
||||
264
src/cpu_common/x86_ops_mul.h
Normal file
264
src/cpu_common/x86_ops_mul.h
Normal file
@@ -0,0 +1,264 @@
|
||||
static int opIMUL_w_iw_a16(uint32_t fetchdat)
|
||||
{
|
||||
int32_t templ;
|
||||
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) 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);
|
||||
PREFETCH_RUN((cpu_mod == 3) ? 14 : 17, 4, rmdat, 1,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opIMUL_w_iw_a32(uint32_t fetchdat)
|
||||
{
|
||||
int32_t templ;
|
||||
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) 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);
|
||||
PREFETCH_RUN((cpu_mod == 3) ? 14 : 17, 4, rmdat, 1,0,0,0, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opIMUL_l_il_a16(uint32_t fetchdat)
|
||||
{
|
||||
int64_t temp64;
|
||||
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) 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);
|
||||
PREFETCH_RUN(25, 6, rmdat, 0,1,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opIMUL_l_il_a32(uint32_t fetchdat)
|
||||
{
|
||||
int64_t temp64;
|
||||
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) 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);
|
||||
PREFETCH_RUN(25, 6, rmdat, 0,1,0,0, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opIMUL_w_ib_a16(uint32_t fetchdat)
|
||||
{
|
||||
int32_t templ;
|
||||
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) 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);
|
||||
PREFETCH_RUN((cpu_mod == 3) ? 14 : 17, 3, rmdat, 1,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opIMUL_w_ib_a32(uint32_t fetchdat)
|
||||
{
|
||||
int32_t templ;
|
||||
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) 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);
|
||||
PREFETCH_RUN((cpu_mod == 3) ? 14 : 17, 3, rmdat, 1,0,0,0, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opIMUL_l_ib_a16(uint32_t fetchdat)
|
||||
{
|
||||
int64_t temp64;
|
||||
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) 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);
|
||||
PREFETCH_RUN(20, 3, rmdat, 0,1,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opIMUL_l_ib_a32(uint32_t fetchdat)
|
||||
{
|
||||
int64_t temp64;
|
||||
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) 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);
|
||||
PREFETCH_RUN(20, 3, rmdat, 0,1,0,0, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int opIMUL_w_w_a16(uint32_t fetchdat)
|
||||
{
|
||||
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) 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);
|
||||
return 0;
|
||||
}
|
||||
static int opIMUL_w_w_a32(uint32_t fetchdat)
|
||||
{
|
||||
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) 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);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opIMUL_l_l_a16(uint32_t fetchdat)
|
||||
{
|
||||
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) 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);
|
||||
return 0;
|
||||
}
|
||||
static int opIMUL_l_l_a32(uint32_t fetchdat)
|
||||
{
|
||||
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) 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);
|
||||
return 0;
|
||||
}
|
||||
|
||||
456
src/cpu_common/x86_ops_pmode.h
Normal file
456
src/cpu_common/x86_ops_pmode.h
Normal file
@@ -0,0 +1,456 @@
|
||||
static int opARPL_a16(uint32_t fetchdat)
|
||||
{
|
||||
uint16_t temp_seg;
|
||||
|
||||
NOTRM
|
||||
fetch_ea_16(fetchdat);
|
||||
if (cpu_mod != 3)
|
||||
SEG_CHECK_WRITE(cpu_state.ea_seg);
|
||||
temp_seg = geteaw(); if (cpu_state.abrt) return 1;
|
||||
|
||||
flags_rebuild();
|
||||
if ((temp_seg & 3) < (cpu_state.regs[cpu_reg].w & 3))
|
||||
{
|
||||
temp_seg = (temp_seg & 0xfffc) | (cpu_state.regs[cpu_reg].w & 3);
|
||||
seteaw(temp_seg); if (cpu_state.abrt) return 1;
|
||||
cpu_state.flags |= Z_FLAG;
|
||||
}
|
||||
else
|
||||
cpu_state.flags &= ~Z_FLAG;
|
||||
|
||||
CLOCK_CYCLES(is486 ? 9 : 20);
|
||||
PREFETCH_RUN(is486 ? 9 : 20, 2, rmdat, 1,0,1,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opARPL_a32(uint32_t fetchdat)
|
||||
{
|
||||
uint16_t temp_seg;
|
||||
|
||||
NOTRM
|
||||
fetch_ea_32(fetchdat);
|
||||
if (cpu_mod != 3)
|
||||
SEG_CHECK_WRITE(cpu_state.ea_seg);
|
||||
temp_seg = geteaw(); if (cpu_state.abrt) return 1;
|
||||
|
||||
flags_rebuild();
|
||||
if ((temp_seg & 3) < (cpu_state.regs[cpu_reg].w & 3))
|
||||
{
|
||||
temp_seg = (temp_seg & 0xfffc) | (cpu_state.regs[cpu_reg].w & 3);
|
||||
seteaw(temp_seg); if (cpu_state.abrt) return 1;
|
||||
cpu_state.flags |= Z_FLAG;
|
||||
}
|
||||
else
|
||||
cpu_state.flags &= ~Z_FLAG;
|
||||
|
||||
CLOCK_CYCLES(is486 ? 9 : 20);
|
||||
PREFETCH_RUN(is486 ? 9 : 20, 2, rmdat, 1,0,1,0, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define opLAR(name, fetch_ea, is32, ea32) \
|
||||
static int opLAR_ ## name(uint32_t fetchdat) \
|
||||
{ \
|
||||
int valid; \
|
||||
uint16_t sel, desc = 0; \
|
||||
\
|
||||
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)) { cpu_state.flags &= ~Z_FLAG; return 0; } /*Null selector*/ \
|
||||
valid = (sel & ~7) < ((sel & 4) ? ldt.limit : gdt.limit); \
|
||||
if (valid) \
|
||||
{ \
|
||||
cpl_override = 1; \
|
||||
desc = readmemw(0, ((sel & 4) ? ldt.base : gdt.base) + (sel & ~7) + 4); \
|
||||
cpl_override = 0; if (cpu_state.abrt) return 1; \
|
||||
} \
|
||||
cpu_state.flags &= ~Z_FLAG; \
|
||||
if ((desc & 0x1f00) == 0x000) valid = 0; \
|
||||
if ((desc & 0x1f00) == 0x800) valid = 0; \
|
||||
if ((desc & 0x1f00) == 0xa00) valid = 0; \
|
||||
if ((desc & 0x1f00) == 0xd00) valid = 0; \
|
||||
if ((desc & 0x1c00) < 0x1c00) /*Exclude conforming code segments*/ \
|
||||
{ \
|
||||
int dpl = (desc >> 13) & 3; \
|
||||
if (dpl < CPL || dpl < (sel & 3)) valid = 0; \
|
||||
} \
|
||||
if (valid) \
|
||||
{ \
|
||||
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; \
|
||||
else \
|
||||
cpu_state.regs[cpu_reg].w = readmemw(0, ((sel & 4) ? ldt.base : gdt.base) + (sel & ~7) + 4) & 0xff00; \
|
||||
cpl_override = 0; \
|
||||
} \
|
||||
CLOCK_CYCLES(11); \
|
||||
PREFETCH_RUN(11, 2, rmdat, 2,0,0,0, ea32); \
|
||||
return cpu_state.abrt; \
|
||||
}
|
||||
|
||||
opLAR(w_a16, fetch_ea_16, 0, 0)
|
||||
opLAR(w_a32, fetch_ea_32, 0, 1)
|
||||
opLAR(l_a16, fetch_ea_16, 1, 0)
|
||||
opLAR(l_a32, fetch_ea_32, 1, 1)
|
||||
|
||||
#define opLSL(name, fetch_ea, is32, ea32) \
|
||||
static int opLSL_ ## name(uint32_t fetchdat) \
|
||||
{ \
|
||||
int valid; \
|
||||
uint16_t sel, desc = 0; \
|
||||
\
|
||||
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(); \
|
||||
cpu_state.flags &= ~Z_FLAG; \
|
||||
if (!(sel & 0xfffc)) return 0; /*Null selector*/ \
|
||||
valid = (sel & ~7) < ((sel & 4) ? ldt.limit : gdt.limit); \
|
||||
if (valid) \
|
||||
{ \
|
||||
cpl_override = 1; \
|
||||
desc = readmemw(0, ((sel & 4) ? ldt.base : gdt.base) + (sel & ~7) + 4); \
|
||||
cpl_override = 0; if (cpu_state.abrt) return 1; \
|
||||
} \
|
||||
if ((desc & 0x1400) == 0x400) valid = 0; /*Interrupt or trap or call gate*/ \
|
||||
if ((desc & 0x1f00) == 0x000) valid = 0; /*Invalid*/ \
|
||||
if ((desc & 0x1f00) == 0xa00) valid = 0; /*Invalid*/ \
|
||||
if ((desc & 0x1c00) != 0x1c00) /*Exclude conforming code segments*/ \
|
||||
{ \
|
||||
int rpl = (desc >> 13) & 3; \
|
||||
if (rpl < CPL || rpl < (sel & 3)) valid = 0; \
|
||||
} \
|
||||
if (valid) \
|
||||
{ \
|
||||
cpu_state.flags |= Z_FLAG; \
|
||||
cpl_override = 1; \
|
||||
if (is32) \
|
||||
{ \
|
||||
cpu_state.regs[cpu_reg].l = readmemw(0, ((sel & 4) ? ldt.base : gdt.base) + (sel & ~7)); \
|
||||
cpu_state.regs[cpu_reg].l |= (readmemb(0, ((sel & 4) ? ldt.base : gdt.base) + (sel & ~7) + 6) & 0xF) << 16; \
|
||||
if (readmemb(0, ((sel & 4) ? ldt.base : gdt.base) + (sel & ~7) + 6) & 0x80) \
|
||||
{ \
|
||||
cpu_state.regs[cpu_reg].l <<= 12; \
|
||||
cpu_state.regs[cpu_reg].l |= 0xFFF; \
|
||||
} \
|
||||
} \
|
||||
else \
|
||||
cpu_state.regs[cpu_reg].w = readmemw(0, ((sel & 4) ? ldt.base : gdt.base) + (sel & ~7)); \
|
||||
cpl_override = 0; \
|
||||
} \
|
||||
CLOCK_CYCLES(10); \
|
||||
PREFETCH_RUN(10, 2, rmdat, 4,0,0,0, ea32); \
|
||||
return cpu_state.abrt; \
|
||||
}
|
||||
|
||||
opLSL(w_a16, fetch_ea_16, 0, 0)
|
||||
opLSL(w_a32, fetch_ea_32, 0, 1)
|
||||
opLSL(l_a16, fetch_ea_16, 1, 0)
|
||||
opLSL(l_a32, fetch_ea_32, 1, 1)
|
||||
|
||||
|
||||
static int op0F00_common(uint32_t fetchdat, int ea32)
|
||||
{
|
||||
int dpl, valid, granularity;
|
||||
uint32_t addr, base, limit;
|
||||
uint16_t desc, sel;
|
||||
uint8_t access;
|
||||
|
||||
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 || cpu_state.eflags&VM_FLAG) && (cr0&1))
|
||||
{
|
||||
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);
|
||||
base = (readmemw(0, addr + 2)) | (readmemb(0, addr + 4) << 16) | (readmemb(0, addr + 7) << 24);
|
||||
access = readmemb(0, addr + 5);
|
||||
granularity = readmemb(0, addr + 6) & 0x80;
|
||||
if (cpu_state.abrt) return 1;
|
||||
ldt.limit = limit;
|
||||
ldt.access = access;
|
||||
if (granularity)
|
||||
{
|
||||
ldt.limit <<= 12;
|
||||
ldt.limit |= 0xfff;
|
||||
}
|
||||
ldt.base = base;
|
||||
ldt.seg = sel;
|
||||
CLOCK_CYCLES(20);
|
||||
PREFETCH_RUN(20, 2, rmdat, (cpu_mod == 3) ? 0:1,2,0,0, ea32);
|
||||
break;
|
||||
case 0x18: /*LTR*/
|
||||
if ((CPL || cpu_state.eflags&VM_FLAG) && (cr0&1))
|
||||
{
|
||||
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);
|
||||
base = (readmemw(0, addr + 2)) | (readmemb(0, addr + 4) << 16) | (readmemb(0, addr + 7) << 24);
|
||||
access = readmemb(0, addr + 5);
|
||||
granularity = readmemb(0, addr + 6) & 0x80;
|
||||
if (cpu_state.abrt) return 1;
|
||||
access |= 2;
|
||||
writememb(0, addr + 5, access);
|
||||
if (cpu_state.abrt) return 1;
|
||||
tr.seg = sel;
|
||||
tr.limit = limit;
|
||||
tr.access = access;
|
||||
if (granularity)
|
||||
{
|
||||
tr.limit <<= 12;
|
||||
tr.limit |= 0xFFF;
|
||||
}
|
||||
tr.base = base;
|
||||
CLOCK_CYCLES(20);
|
||||
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();
|
||||
cpu_state.flags &= ~Z_FLAG;
|
||||
if (!(sel & 0xfffc)) return 0; /*Null selector*/
|
||||
cpl_override = 1;
|
||||
valid = (sel & ~7) < ((sel & 4) ? ldt.limit : gdt.limit);
|
||||
desc = readmemw(0, ((sel & 4) ? ldt.base : gdt.base) + (sel & ~7) + 4);
|
||||
cpl_override = 0; if (cpu_state.abrt) return 1;
|
||||
if (!(desc & 0x1000)) valid = 0;
|
||||
if ((desc & 0xC00) != 0xC00) /*Exclude conforming code segments*/
|
||||
{
|
||||
dpl = (desc >> 13) & 3; /*Check permissions*/
|
||||
if (dpl < CPL || dpl < (sel & 3)) valid = 0;
|
||||
}
|
||||
if ((desc & 0x0800) && !(desc & 0x0200)) valid = 0; /*Non-readable code*/
|
||||
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();
|
||||
cpu_state.flags &= ~Z_FLAG;
|
||||
if (!(sel & 0xfffc)) return 0; /*Null selector*/
|
||||
cpl_override = 1;
|
||||
valid = (sel & ~7) < ((sel & 4) ? ldt.limit : gdt.limit);
|
||||
desc = readmemw(0, ((sel & 4) ? ldt.base : gdt.base) + (sel & ~7) + 4);
|
||||
cpl_override = 0; if (cpu_state.abrt) return 1;
|
||||
if (!(desc & 0x1000)) valid = 0;
|
||||
dpl = (desc >> 13) & 3; /*Check permissions*/
|
||||
if (dpl < CPL || dpl < (sel & 3)) valid = 0;
|
||||
if (desc & 0x0800) valid = 0; /*Code*/
|
||||
if (!(desc & 0x0200)) valid = 0; /*Read-only data*/
|
||||
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;
|
||||
|
||||
default:
|
||||
cpu_state.pc -= 3;
|
||||
x86illegal();
|
||||
break;
|
||||
}
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
|
||||
static int op0F00_a16(uint32_t fetchdat)
|
||||
{
|
||||
NOTRM
|
||||
|
||||
fetch_ea_16(fetchdat);
|
||||
|
||||
return op0F00_common(fetchdat, 0);
|
||||
}
|
||||
static int op0F00_a32(uint32_t fetchdat)
|
||||
{
|
||||
NOTRM
|
||||
|
||||
fetch_ea_32(fetchdat);
|
||||
|
||||
return op0F00_common(fetchdat, 1);
|
||||
}
|
||||
|
||||
static int op0F01_common(uint32_t fetchdat, int is32, int is286, int ea32)
|
||||
{
|
||||
uint32_t base;
|
||||
uint16_t limit, tempw;
|
||||
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)
|
||||
base |= 0xff000000;
|
||||
writememl(easeg, cpu_state.eaaddr + 2, base);
|
||||
CLOCK_CYCLES(7);
|
||||
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)
|
||||
base |= 0xff000000;
|
||||
writememl(easeg, cpu_state.eaaddr + 2, base);
|
||||
CLOCK_CYCLES(7);
|
||||
PREFETCH_RUN(7, 2, rmdat, 0,0,1,1, ea32);
|
||||
break;
|
||||
case 0x10: /*LGDT*/
|
||||
if ((CPL || cpu_state.eflags&VM_FLAG) && (cr0&1))
|
||||
{
|
||||
x86gpf(NULL,0);
|
||||
break;
|
||||
}
|
||||
if (cpu_mod != 3)
|
||||
SEG_CHECK_READ(cpu_state.ea_seg);
|
||||
limit = geteaw();
|
||||
base = readmeml(0, easeg + cpu_state.eaaddr + 2); if (cpu_state.abrt) return 1;
|
||||
gdt.limit = limit;
|
||||
gdt.base = base;
|
||||
if (!is32) gdt.base &= 0xffffff;
|
||||
CLOCK_CYCLES(11);
|
||||
PREFETCH_RUN(11, 2, rmdat, 1,1,0,0, ea32);
|
||||
break;
|
||||
case 0x18: /*LIDT*/
|
||||
if ((CPL || cpu_state.eflags&VM_FLAG) && (cr0&1))
|
||||
{
|
||||
x86gpf(NULL,0);
|
||||
break;
|
||||
}
|
||||
if (cpu_mod != 3)
|
||||
SEG_CHECK_READ(cpu_state.ea_seg);
|
||||
limit = geteaw();
|
||||
base = readmeml(0, easeg + cpu_state.eaaddr + 2); if (cpu_state.abrt) return 1;
|
||||
idt.limit = limit;
|
||||
idt.base = base;
|
||||
if (!is32) idt.base &= 0xffffff;
|
||||
CLOCK_CYCLES(11);
|
||||
PREFETCH_RUN(11, 2, rmdat, 1,1,0,0, ea32);
|
||||
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);
|
||||
CLOCK_CYCLES(2);
|
||||
PREFETCH_RUN(2, 2, rmdat, 0,0,(cpu_mod == 3) ? 0:1,0, ea32);
|
||||
break;
|
||||
case 0x30: /*LMSW*/
|
||||
if ((CPL || cpu_state.eflags&VM_FLAG) && (msw&1))
|
||||
{
|
||||
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)
|
||||
{
|
||||
tempw &= ~0x10;
|
||||
tempw |= (msw & 0x10);
|
||||
}
|
||||
else tempw &= 0xF;
|
||||
msw = tempw;
|
||||
if (msw & 1)
|
||||
cpu_cur_status |= CPU_STATUS_PMODE;
|
||||
else
|
||||
cpu_cur_status &= ~CPU_STATUS_PMODE;
|
||||
PREFETCH_RUN(2, 2, rmdat, 0,0,(cpu_mod == 3) ? 0:1,0, ea32);
|
||||
break;
|
||||
|
||||
case 0x38: /*INVLPG*/
|
||||
if (is486)
|
||||
{
|
||||
if ((CPL || cpu_state.eflags&VM_FLAG) && (cr0&1))
|
||||
{
|
||||
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);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
cpu_state.pc -= 3;
|
||||
x86illegal();
|
||||
break;
|
||||
}
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
|
||||
static int op0F01_w_a16(uint32_t fetchdat)
|
||||
{
|
||||
fetch_ea_16(fetchdat);
|
||||
|
||||
return op0F01_common(fetchdat, 0, 0, 0);
|
||||
}
|
||||
static int op0F01_w_a32(uint32_t fetchdat)
|
||||
{
|
||||
fetch_ea_32(fetchdat);
|
||||
|
||||
return op0F01_common(fetchdat, 0, 0, 1);
|
||||
}
|
||||
static int op0F01_l_a16(uint32_t fetchdat)
|
||||
{
|
||||
fetch_ea_16(fetchdat);
|
||||
|
||||
return op0F01_common(fetchdat, 1, 0, 0);
|
||||
}
|
||||
static int op0F01_l_a32(uint32_t fetchdat)
|
||||
{
|
||||
fetch_ea_32(fetchdat);
|
||||
|
||||
return op0F01_common(fetchdat, 1, 0, 1);
|
||||
}
|
||||
|
||||
static int op0F01_286(uint32_t fetchdat)
|
||||
{
|
||||
fetch_ea_16(fetchdat);
|
||||
|
||||
return op0F01_common(fetchdat, 0, 1, 0);
|
||||
}
|
||||
161
src/cpu_common/x86_ops_prefix.h
Normal file
161
src/cpu_common/x86_ops_prefix.h
Normal file
@@ -0,0 +1,161 @@
|
||||
#define op_seg(name, seg, opcode_table, normal_opcode_table) \
|
||||
static int op ## name ## _w_a16(uint32_t fetchdat) \
|
||||
{ \
|
||||
fetchdat = fastreadl(cs + cpu_state.pc); \
|
||||
if (cpu_state.abrt) return 1; \
|
||||
cpu_state.pc++; \
|
||||
\
|
||||
cpu_state.ea_seg = &seg; \
|
||||
cpu_state.ssegs = 1; \
|
||||
CLOCK_CYCLES(4); \
|
||||
PREFETCH_PREFIX(); \
|
||||
\
|
||||
if (opcode_table[fetchdat & 0xff]) \
|
||||
return opcode_table[fetchdat & 0xff](fetchdat >> 8); \
|
||||
return normal_opcode_table[fetchdat & 0xff](fetchdat >> 8); \
|
||||
} \
|
||||
\
|
||||
static int op ## name ## _l_a16(uint32_t fetchdat) \
|
||||
{ \
|
||||
fetchdat = fastreadl(cs + cpu_state.pc); \
|
||||
if (cpu_state.abrt) return 1; \
|
||||
cpu_state.pc++; \
|
||||
\
|
||||
cpu_state.ea_seg = &seg; \
|
||||
cpu_state.ssegs = 1; \
|
||||
CLOCK_CYCLES(4); \
|
||||
PREFETCH_PREFIX(); \
|
||||
\
|
||||
if (opcode_table[(fetchdat & 0xff) | 0x100]) \
|
||||
return opcode_table[(fetchdat & 0xff) | 0x100](fetchdat >> 8); \
|
||||
return normal_opcode_table[(fetchdat & 0xff) | 0x100](fetchdat >> 8); \
|
||||
} \
|
||||
\
|
||||
static int op ## name ## _w_a32(uint32_t fetchdat) \
|
||||
{ \
|
||||
fetchdat = fastreadl(cs + cpu_state.pc); \
|
||||
if (cpu_state.abrt) return 1; \
|
||||
cpu_state.pc++; \
|
||||
\
|
||||
cpu_state.ea_seg = &seg; \
|
||||
cpu_state.ssegs = 1; \
|
||||
CLOCK_CYCLES(4); \
|
||||
PREFETCH_PREFIX(); \
|
||||
\
|
||||
if (opcode_table[(fetchdat & 0xff) | 0x200]) \
|
||||
return opcode_table[(fetchdat & 0xff) | 0x200](fetchdat >> 8); \
|
||||
return normal_opcode_table[(fetchdat & 0xff) | 0x200](fetchdat >> 8); \
|
||||
} \
|
||||
\
|
||||
static int op ## name ## _l_a32(uint32_t fetchdat) \
|
||||
{ \
|
||||
fetchdat = fastreadl(cs + cpu_state.pc); \
|
||||
if (cpu_state.abrt) return 1; \
|
||||
cpu_state.pc++; \
|
||||
\
|
||||
cpu_state.ea_seg = &seg; \
|
||||
cpu_state.ssegs = 1; \
|
||||
CLOCK_CYCLES(4); \
|
||||
PREFETCH_PREFIX(); \
|
||||
\
|
||||
if (opcode_table[(fetchdat & 0xff) | 0x300]) \
|
||||
return opcode_table[(fetchdat & 0xff) | 0x300](fetchdat >> 8); \
|
||||
return normal_opcode_table[(fetchdat & 0xff) | 0x300](fetchdat >> 8); \
|
||||
}
|
||||
|
||||
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, 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, 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*/
|
||||
{
|
||||
fetchdat = fastreadl(cs + cpu_state.pc);
|
||||
if (cpu_state.abrt) return 1;
|
||||
cpu_state.pc++;
|
||||
|
||||
cpu_state.op32 = ((use32 & 0x100) ^ 0x100) | (cpu_state.op32 & 0x200);
|
||||
CLOCK_CYCLES(2);
|
||||
PREFETCH_PREFIX();
|
||||
return x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8);
|
||||
}
|
||||
static int op_67(uint32_t fetchdat) /*Address size select*/
|
||||
{
|
||||
fetchdat = fastreadl(cs + cpu_state.pc);
|
||||
if (cpu_state.abrt) return 1;
|
||||
cpu_state.pc++;
|
||||
|
||||
cpu_state.op32 = ((use32 & 0x200) ^ 0x200) | (cpu_state.op32 & 0x100);
|
||||
CLOCK_CYCLES(2);
|
||||
PREFETCH_PREFIX();
|
||||
return x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8);
|
||||
}
|
||||
|
||||
static int op_66_REPE(uint32_t fetchdat) /*Data size select*/
|
||||
{
|
||||
fetchdat = fastreadl(cs + cpu_state.pc);
|
||||
if (cpu_state.abrt) return 1;
|
||||
cpu_state.pc++;
|
||||
|
||||
cpu_state.op32 = ((use32 & 0x100) ^ 0x100) | (cpu_state.op32 & 0x200);
|
||||
CLOCK_CYCLES(2);
|
||||
PREFETCH_PREFIX();
|
||||
if (x86_opcodes_REPE[(fetchdat & 0xff) | cpu_state.op32])
|
||||
return x86_opcodes_REPE[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8);
|
||||
return x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8);
|
||||
}
|
||||
static int op_67_REPE(uint32_t fetchdat) /*Address size select*/
|
||||
{
|
||||
fetchdat = fastreadl(cs + cpu_state.pc);
|
||||
if (cpu_state.abrt) return 1;
|
||||
cpu_state.pc++;
|
||||
|
||||
cpu_state.op32 = ((use32 & 0x200) ^ 0x200) | (cpu_state.op32 & 0x100);
|
||||
CLOCK_CYCLES(2);
|
||||
PREFETCH_PREFIX();
|
||||
if (x86_opcodes_REPE[(fetchdat & 0xff) | cpu_state.op32])
|
||||
return x86_opcodes_REPE[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8);
|
||||
return x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8);
|
||||
}
|
||||
static int op_66_REPNE(uint32_t fetchdat) /*Data size select*/
|
||||
{
|
||||
fetchdat = fastreadl(cs + cpu_state.pc);
|
||||
if (cpu_state.abrt) return 1;
|
||||
cpu_state.pc++;
|
||||
|
||||
cpu_state.op32 = ((use32 & 0x100) ^ 0x100) | (cpu_state.op32 & 0x200);
|
||||
CLOCK_CYCLES(2);
|
||||
PREFETCH_PREFIX();
|
||||
if (x86_opcodes_REPNE[(fetchdat & 0xff) | cpu_state.op32])
|
||||
return x86_opcodes_REPNE[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8);
|
||||
return x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8);
|
||||
}
|
||||
static int op_67_REPNE(uint32_t fetchdat) /*Address size select*/
|
||||
{
|
||||
fetchdat = fastreadl(cs + cpu_state.pc);
|
||||
if (cpu_state.abrt) return 1;
|
||||
cpu_state.pc++;
|
||||
|
||||
cpu_state.op32 = ((use32 & 0x200) ^ 0x200) | (cpu_state.op32 & 0x100);
|
||||
CLOCK_CYCLES(2);
|
||||
PREFETCH_PREFIX();
|
||||
if (x86_opcodes_REPNE[(fetchdat & 0xff) | cpu_state.op32])
|
||||
return x86_opcodes_REPNE[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8);
|
||||
return x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8);
|
||||
}
|
||||
713
src/cpu_common/x86_ops_rep.h
Normal file
713
src/cpu_common/x86_ops_rep.h
Normal file
@@ -0,0 +1,713 @@
|
||||
#define REP_OPS(size, CNT_REG, SRC_REG, DEST_REG) \
|
||||
static int opREP_INSB_ ## size(uint32_t fetchdat) \
|
||||
{ \
|
||||
int reads = 0, writes = 0, total_cycles = 0; \
|
||||
\
|
||||
if (CNT_REG > 0) \
|
||||
{ \
|
||||
uint8_t temp; \
|
||||
\
|
||||
SEG_CHECK_WRITE(&cpu_state.seg_es); \
|
||||
check_io_perm(DX); \
|
||||
CHECK_WRITE(&cpu_state.seg_es, DEST_REG, DEST_REG); \
|
||||
temp = inb(DX); \
|
||||
writememb(es, DEST_REG, temp); if (cpu_state.abrt) return 1; \
|
||||
\
|
||||
if (cpu_state.flags & D_FLAG) DEST_REG--; \
|
||||
else DEST_REG++; \
|
||||
CNT_REG--; \
|
||||
cycles -= 15; \
|
||||
reads++; writes++; total_cycles += 15; \
|
||||
} \
|
||||
PREFETCH_RUN(total_cycles, 1, -1, reads, 0, writes, 0, 0); \
|
||||
if (CNT_REG > 0) \
|
||||
{ \
|
||||
CPU_BLOCK_END(); \
|
||||
cpu_state.pc = cpu_state.oldpc; \
|
||||
return 1; \
|
||||
} \
|
||||
return cpu_state.abrt; \
|
||||
} \
|
||||
static int opREP_INSW_ ## size(uint32_t fetchdat) \
|
||||
{ \
|
||||
int reads = 0, writes = 0, total_cycles = 0; \
|
||||
\
|
||||
if (CNT_REG > 0) \
|
||||
{ \
|
||||
uint16_t temp; \
|
||||
\
|
||||
SEG_CHECK_WRITE(&cpu_state.seg_es); \
|
||||
check_io_perm(DX); \
|
||||
check_io_perm(DX+1); \
|
||||
CHECK_WRITE(&cpu_state.seg_es, DEST_REG, DEST_REG + 1); \
|
||||
temp = inw(DX); \
|
||||
writememw(es, DEST_REG, temp); if (cpu_state.abrt) return 1; \
|
||||
\
|
||||
if (cpu_state.flags & D_FLAG) DEST_REG -= 2; \
|
||||
else DEST_REG += 2; \
|
||||
CNT_REG--; \
|
||||
cycles -= 15; \
|
||||
reads++; writes++; total_cycles += 15; \
|
||||
} \
|
||||
PREFETCH_RUN(total_cycles, 1, -1, reads, 0, writes, 0, 0); \
|
||||
if (CNT_REG > 0) \
|
||||
{ \
|
||||
CPU_BLOCK_END(); \
|
||||
cpu_state.pc = cpu_state.oldpc; \
|
||||
return 1; \
|
||||
} \
|
||||
return cpu_state.abrt; \
|
||||
} \
|
||||
static int opREP_INSL_ ## size(uint32_t fetchdat) \
|
||||
{ \
|
||||
int reads = 0, writes = 0, total_cycles = 0; \
|
||||
\
|
||||
if (CNT_REG > 0) \
|
||||
{ \
|
||||
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); \
|
||||
CHECK_WRITE(&cpu_state.seg_es, DEST_REG, DEST_REG + 3); \
|
||||
temp = inl(DX); \
|
||||
writememl(es, DEST_REG, temp); if (cpu_state.abrt) return 1; \
|
||||
\
|
||||
if (cpu_state.flags & D_FLAG) DEST_REG -= 4; \
|
||||
else DEST_REG += 4; \
|
||||
CNT_REG--; \
|
||||
cycles -= 15; \
|
||||
reads++; writes++; total_cycles += 15; \
|
||||
} \
|
||||
PREFETCH_RUN(total_cycles, 1, -1, 0, reads, 0, writes, 0); \
|
||||
if (CNT_REG > 0) \
|
||||
{ \
|
||||
CPU_BLOCK_END(); \
|
||||
cpu_state.pc = cpu_state.oldpc; \
|
||||
return 1; \
|
||||
} \
|
||||
return cpu_state.abrt; \
|
||||
} \
|
||||
\
|
||||
static int opREP_OUTSB_ ## size(uint32_t fetchdat) \
|
||||
{ \
|
||||
int reads = 0, writes = 0, total_cycles = 0; \
|
||||
\
|
||||
if (CNT_REG > 0) \
|
||||
{ \
|
||||
uint8_t temp; \
|
||||
SEG_CHECK_READ(cpu_state.ea_seg); \
|
||||
CHECK_READ(cpu_state.ea_seg, SRC_REG, SRC_REG); \
|
||||
temp = readmemb(cpu_state.ea_seg->base, SRC_REG); if (cpu_state.abrt) return 1; \
|
||||
check_io_perm(DX); \
|
||||
outb(DX, temp); \
|
||||
if (cpu_state.flags & D_FLAG) SRC_REG--; \
|
||||
else SRC_REG++; \
|
||||
CNT_REG--; \
|
||||
cycles -= 14; \
|
||||
reads++; writes++; total_cycles += 14; \
|
||||
} \
|
||||
PREFETCH_RUN(total_cycles, 1, -1, reads, 0, writes, 0, 0); \
|
||||
if (CNT_REG > 0) \
|
||||
{ \
|
||||
CPU_BLOCK_END(); \
|
||||
cpu_state.pc = cpu_state.oldpc; \
|
||||
return 1; \
|
||||
} \
|
||||
return cpu_state.abrt; \
|
||||
} \
|
||||
static int opREP_OUTSW_ ## size(uint32_t fetchdat) \
|
||||
{ \
|
||||
int reads = 0, writes = 0, total_cycles = 0; \
|
||||
\
|
||||
if (CNT_REG > 0) \
|
||||
{ \
|
||||
uint16_t temp; \
|
||||
SEG_CHECK_READ(cpu_state.ea_seg); \
|
||||
CHECK_READ(cpu_state.ea_seg, SRC_REG, SRC_REG + 1); \
|
||||
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 (cpu_state.flags & D_FLAG) SRC_REG -= 2; \
|
||||
else SRC_REG += 2; \
|
||||
CNT_REG--; \
|
||||
cycles -= 14; \
|
||||
reads++; writes++; total_cycles += 14; \
|
||||
} \
|
||||
PREFETCH_RUN(total_cycles, 1, -1, reads, 0, writes, 0, 0); \
|
||||
if (CNT_REG > 0) \
|
||||
{ \
|
||||
CPU_BLOCK_END(); \
|
||||
cpu_state.pc = cpu_state.oldpc; \
|
||||
return 1; \
|
||||
} \
|
||||
return cpu_state.abrt; \
|
||||
} \
|
||||
static int opREP_OUTSL_ ## size(uint32_t fetchdat) \
|
||||
{ \
|
||||
int reads = 0, writes = 0, total_cycles = 0; \
|
||||
\
|
||||
if (CNT_REG > 0) \
|
||||
{ \
|
||||
uint32_t temp; \
|
||||
SEG_CHECK_READ(cpu_state.ea_seg); \
|
||||
CHECK_READ(cpu_state.ea_seg, SRC_REG, SRC_REG + 3); \
|
||||
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 (cpu_state.flags & D_FLAG) SRC_REG -= 4; \
|
||||
else SRC_REG += 4; \
|
||||
CNT_REG--; \
|
||||
cycles -= 14; \
|
||||
reads++; writes++; total_cycles += 14; \
|
||||
} \
|
||||
PREFETCH_RUN(total_cycles, 1, -1, 0, reads, 0, writes, 0); \
|
||||
if (CNT_REG > 0) \
|
||||
{ \
|
||||
CPU_BLOCK_END(); \
|
||||
cpu_state.pc = cpu_state.oldpc; \
|
||||
return 1; \
|
||||
} \
|
||||
return cpu_state.abrt; \
|
||||
} \
|
||||
\
|
||||
static int opREP_MOVSB_ ## size(uint32_t fetchdat) \
|
||||
{ \
|
||||
int reads = 0, writes = 0, total_cycles = 0; \
|
||||
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_READ_REP(cpu_state.ea_seg, SRC_REG, SRC_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 (cpu_state.flags & D_FLAG) { DEST_REG--; SRC_REG--; } \
|
||||
else { DEST_REG++; SRC_REG++; } \
|
||||
CNT_REG--; \
|
||||
cycles -= is486 ? 3 : 4; \
|
||||
ins++; \
|
||||
reads++; writes++; total_cycles += is486 ? 3 : 4; \
|
||||
if (cycles < cycles_end) \
|
||||
break; \
|
||||
} \
|
||||
ins--; \
|
||||
PREFETCH_RUN(total_cycles, 1, -1, reads, 0, writes, 0, 0); \
|
||||
if (CNT_REG > 0) \
|
||||
{ \
|
||||
CPU_BLOCK_END(); \
|
||||
cpu_state.pc = cpu_state.oldpc; \
|
||||
return 1; \
|
||||
} \
|
||||
return cpu_state.abrt; \
|
||||
} \
|
||||
static int opREP_MOVSW_ ## size(uint32_t fetchdat) \
|
||||
{ \
|
||||
int reads = 0, writes = 0, total_cycles = 0; \
|
||||
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_READ_REP(cpu_state.ea_seg, SRC_REG, SRC_REG + 1); \
|
||||
CHECK_WRITE_REP(&cpu_state.seg_es, DEST_REG, DEST_REG + 1); \
|
||||
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 (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++; \
|
||||
reads++; writes++; total_cycles += is486 ? 3 : 4; \
|
||||
if (cycles < cycles_end) \
|
||||
break; \
|
||||
} \
|
||||
ins--; \
|
||||
PREFETCH_RUN(total_cycles, 1, -1, reads, 0, writes, 0, 0); \
|
||||
if (CNT_REG > 0) \
|
||||
{ \
|
||||
CPU_BLOCK_END(); \
|
||||
cpu_state.pc = cpu_state.oldpc; \
|
||||
return 1; \
|
||||
} \
|
||||
return cpu_state.abrt; \
|
||||
} \
|
||||
static int opREP_MOVSL_ ## size(uint32_t fetchdat) \
|
||||
{ \
|
||||
int reads = 0, writes = 0, total_cycles = 0; \
|
||||
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_READ_REP(cpu_state.ea_seg, SRC_REG, SRC_REG + 3); \
|
||||
CHECK_WRITE_REP(&cpu_state.seg_es, DEST_REG, DEST_REG + 3); \
|
||||
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 (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++; \
|
||||
reads++; writes++; total_cycles += is486 ? 3 : 4; \
|
||||
if (cycles < cycles_end) \
|
||||
break; \
|
||||
} \
|
||||
ins--; \
|
||||
PREFETCH_RUN(total_cycles, 1, -1, reads, 0, writes, 0, 0); \
|
||||
if (CNT_REG > 0) \
|
||||
{ \
|
||||
CPU_BLOCK_END(); \
|
||||
cpu_state.pc = cpu_state.oldpc; \
|
||||
return 1; \
|
||||
} \
|
||||
return cpu_state.abrt; \
|
||||
} \
|
||||
\
|
||||
\
|
||||
static int opREP_STOSB_ ## size(uint32_t fetchdat) \
|
||||
{ \
|
||||
int writes = 0, total_cycles = 0; \
|
||||
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(&cpu_state.seg_es, DEST_REG, DEST_REG); \
|
||||
writememb(es, DEST_REG, AL); if (cpu_state.abrt) return 1; \
|
||||
if (cpu_state.flags & D_FLAG) DEST_REG--; \
|
||||
else DEST_REG++; \
|
||||
CNT_REG--; \
|
||||
cycles -= is486 ? 4 : 5; \
|
||||
writes++; total_cycles += is486 ? 4 : 5; \
|
||||
ins++; \
|
||||
if (cycles < cycles_end) \
|
||||
break; \
|
||||
} \
|
||||
PREFETCH_RUN(total_cycles, 1, -1, 0, 0, writes, 0, 0); \
|
||||
if (CNT_REG > 0) \
|
||||
{ \
|
||||
CPU_BLOCK_END(); \
|
||||
cpu_state.pc = cpu_state.oldpc; \
|
||||
return 1; \
|
||||
} \
|
||||
return cpu_state.abrt; \
|
||||
} \
|
||||
static int opREP_STOSW_ ## size(uint32_t fetchdat) \
|
||||
{ \
|
||||
int writes = 0, total_cycles = 0; \
|
||||
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(&cpu_state.seg_es, DEST_REG, DEST_REG + 1); \
|
||||
writememw(es, DEST_REG, AX); if (cpu_state.abrt) return 1; \
|
||||
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; \
|
||||
ins++; \
|
||||
if (cycles < cycles_end) \
|
||||
break; \
|
||||
} \
|
||||
PREFETCH_RUN(total_cycles, 1, -1, 0, 0, writes, 0, 0); \
|
||||
if (CNT_REG > 0) \
|
||||
{ \
|
||||
CPU_BLOCK_END(); \
|
||||
cpu_state.pc = cpu_state.oldpc; \
|
||||
return 1; \
|
||||
} \
|
||||
return cpu_state.abrt; \
|
||||
} \
|
||||
static int opREP_STOSL_ ## size(uint32_t fetchdat) \
|
||||
{ \
|
||||
int writes = 0, total_cycles = 0; \
|
||||
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(&cpu_state.seg_es, DEST_REG, DEST_REG + 3); \
|
||||
writememl(es, DEST_REG, EAX); if (cpu_state.abrt) return 1; \
|
||||
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; \
|
||||
ins++; \
|
||||
if (cycles < cycles_end) \
|
||||
break; \
|
||||
} \
|
||||
PREFETCH_RUN(total_cycles, 1, -1, 0, 0, 0, writes, 0); \
|
||||
if (CNT_REG > 0) \
|
||||
{ \
|
||||
CPU_BLOCK_END(); \
|
||||
cpu_state.pc = cpu_state.oldpc; \
|
||||
return 1; \
|
||||
} \
|
||||
return cpu_state.abrt; \
|
||||
} \
|
||||
\
|
||||
static int opREP_LODSB_ ## size(uint32_t fetchdat) \
|
||||
{ \
|
||||
int reads = 0, total_cycles = 0; \
|
||||
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) \
|
||||
{ \
|
||||
CHECK_READ_REP(cpu_state.ea_seg, SRC_REG, SRC_REG); \
|
||||
AL = readmemb(cpu_state.ea_seg->base, SRC_REG); if (cpu_state.abrt) return 1; \
|
||||
if (cpu_state.flags & D_FLAG) SRC_REG--; \
|
||||
else SRC_REG++; \
|
||||
CNT_REG--; \
|
||||
cycles -= is486 ? 4 : 5; \
|
||||
reads++; total_cycles += is486 ? 4 : 5; \
|
||||
ins++; \
|
||||
if (cycles < cycles_end) \
|
||||
break; \
|
||||
} \
|
||||
PREFETCH_RUN(total_cycles, 1, -1, reads, 0, 0, 0, 0); \
|
||||
if (CNT_REG > 0) \
|
||||
{ \
|
||||
CPU_BLOCK_END(); \
|
||||
cpu_state.pc = cpu_state.oldpc; \
|
||||
return 1; \
|
||||
} \
|
||||
return cpu_state.abrt; \
|
||||
} \
|
||||
static int opREP_LODSW_ ## size(uint32_t fetchdat) \
|
||||
{ \
|
||||
int reads = 0, total_cycles = 0; \
|
||||
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) \
|
||||
{ \
|
||||
CHECK_READ_REP(cpu_state.ea_seg, SRC_REG, SRC_REG + 1); \
|
||||
AX = readmemw(cpu_state.ea_seg->base, SRC_REG); if (cpu_state.abrt) return 1; \
|
||||
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; \
|
||||
ins++; \
|
||||
if (cycles < cycles_end) \
|
||||
break; \
|
||||
} \
|
||||
PREFETCH_RUN(total_cycles, 1, -1, reads, 0, 0, 0, 0); \
|
||||
if (CNT_REG > 0) \
|
||||
{ \
|
||||
CPU_BLOCK_END(); \
|
||||
cpu_state.pc = cpu_state.oldpc; \
|
||||
return 1; \
|
||||
} \
|
||||
return cpu_state.abrt; \
|
||||
} \
|
||||
static int opREP_LODSL_ ## size(uint32_t fetchdat) \
|
||||
{ \
|
||||
int reads = 0, total_cycles = 0; \
|
||||
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) \
|
||||
{ \
|
||||
CHECK_READ_REP(cpu_state.ea_seg, SRC_REG, SRC_REG + 3); \
|
||||
EAX = readmeml(cpu_state.ea_seg->base, SRC_REG); if (cpu_state.abrt) return 1; \
|
||||
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; \
|
||||
ins++; \
|
||||
if (cycles < cycles_end) \
|
||||
break; \
|
||||
} \
|
||||
PREFETCH_RUN(total_cycles, 1, -1, 0, reads, 0, 0, 0); \
|
||||
if (CNT_REG > 0) \
|
||||
{ \
|
||||
CPU_BLOCK_END(); \
|
||||
cpu_state.pc = cpu_state.oldpc; \
|
||||
return 1; \
|
||||
} \
|
||||
return cpu_state.abrt; \
|
||||
} \
|
||||
|
||||
|
||||
#define REP_OPS_CMPS_SCAS(size, CNT_REG, SRC_REG, DEST_REG, FV) \
|
||||
static int opREP_CMPSB_ ## size(uint32_t fetchdat) \
|
||||
{ \
|
||||
int reads = 0, total_cycles = 0, tempz; \
|
||||
\
|
||||
tempz = FV; \
|
||||
if ((CNT_REG > 0) && (FV == tempz)) \
|
||||
{ \
|
||||
uint8_t temp, temp2; \
|
||||
SEG_CHECK_READ(cpu_state.ea_seg); \
|
||||
SEG_CHECK_READ(&cpu_state.seg_es); \
|
||||
CHECK_READ(cpu_state.ea_seg, SRC_REG, SRC_REG); \
|
||||
CHECK_READ(&cpu_state.seg_es, DEST_REG, DEST_REG); \
|
||||
temp = readmemb(cpu_state.ea_seg->base, SRC_REG); \
|
||||
temp2 = readmemb(es, DEST_REG); if (cpu_state.abrt) return 1; \
|
||||
\
|
||||
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; \
|
||||
setsub8(temp, temp2); \
|
||||
tempz = (ZF_SET()) ? 1 : 0; \
|
||||
} \
|
||||
PREFETCH_RUN(total_cycles, 1, -1, reads, 0, 0, 0, 0); \
|
||||
if ((CNT_REG > 0) && (FV == tempz)) \
|
||||
{ \
|
||||
CPU_BLOCK_END(); \
|
||||
cpu_state.pc = cpu_state.oldpc; \
|
||||
return 1; \
|
||||
} \
|
||||
return cpu_state.abrt; \
|
||||
} \
|
||||
static int opREP_CMPSW_ ## size(uint32_t fetchdat) \
|
||||
{ \
|
||||
int reads = 0, total_cycles = 0, tempz; \
|
||||
\
|
||||
tempz = FV; \
|
||||
if ((CNT_REG > 0) && (FV == tempz)) \
|
||||
{ \
|
||||
uint16_t temp, temp2; \
|
||||
SEG_CHECK_READ(cpu_state.ea_seg); \
|
||||
SEG_CHECK_READ(&cpu_state.seg_es); \
|
||||
CHECK_READ(cpu_state.ea_seg, SRC_REG, SRC_REG + 1); \
|
||||
CHECK_READ(&cpu_state.seg_es, DEST_REG, DEST_REG + 1); \
|
||||
temp = readmemw(cpu_state.ea_seg->base, SRC_REG); \
|
||||
temp2 = readmemw(es, DEST_REG); if (cpu_state.abrt) return 1; \
|
||||
\
|
||||
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; \
|
||||
setsub16(temp, temp2); \
|
||||
tempz = (ZF_SET()) ? 1 : 0; \
|
||||
} \
|
||||
PREFETCH_RUN(total_cycles, 1, -1, reads, 0, 0, 0, 0); \
|
||||
if ((CNT_REG > 0) && (FV == tempz)) \
|
||||
{ \
|
||||
CPU_BLOCK_END(); \
|
||||
cpu_state.pc = cpu_state.oldpc; \
|
||||
return 1; \
|
||||
} \
|
||||
return cpu_state.abrt; \
|
||||
} \
|
||||
static int opREP_CMPSL_ ## size(uint32_t fetchdat) \
|
||||
{ \
|
||||
int reads = 0, total_cycles = 0, tempz; \
|
||||
\
|
||||
tempz = FV; \
|
||||
if ((CNT_REG > 0) && (FV == tempz)) \
|
||||
{ \
|
||||
uint32_t temp, temp2; \
|
||||
SEG_CHECK_READ(cpu_state.ea_seg); \
|
||||
SEG_CHECK_READ(&cpu_state.seg_es); \
|
||||
CHECK_READ(cpu_state.ea_seg, SRC_REG, SRC_REG + 3); \
|
||||
CHECK_READ(&cpu_state.seg_es, DEST_REG, DEST_REG + 3); \
|
||||
temp = readmeml(cpu_state.ea_seg->base, SRC_REG); \
|
||||
temp2 = readmeml(es, DEST_REG); if (cpu_state.abrt) return 1; \
|
||||
\
|
||||
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; \
|
||||
setsub32(temp, temp2); \
|
||||
tempz = (ZF_SET()) ? 1 : 0; \
|
||||
} \
|
||||
PREFETCH_RUN(total_cycles, 1, -1, 0, reads, 0, 0, 0); \
|
||||
if ((CNT_REG > 0) && (FV == tempz)) \
|
||||
{ \
|
||||
CPU_BLOCK_END(); \
|
||||
cpu_state.pc = cpu_state.oldpc; \
|
||||
return 1; \
|
||||
} \
|
||||
return cpu_state.abrt; \
|
||||
} \
|
||||
\
|
||||
static int opREP_SCASB_ ## size(uint32_t fetchdat) \
|
||||
{ \
|
||||
int reads = 0, total_cycles = 0, tempz; \
|
||||
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*/ \
|
||||
tempz = FV; \
|
||||
if ((CNT_REG > 0) && (FV == tempz)) \
|
||||
SEG_CHECK_READ(&cpu_state.seg_es); \
|
||||
while ((CNT_REG > 0) && (FV == tempz)) \
|
||||
{ \
|
||||
CHECK_READ_REP(&cpu_state.seg_es, DEST_REG, DEST_REG); \
|
||||
uint8_t temp = readmemb(es, DEST_REG); if (cpu_state.abrt) break;\
|
||||
setsub8(AL, temp); \
|
||||
tempz = (ZF_SET()) ? 1 : 0; \
|
||||
if (cpu_state.flags & D_FLAG) DEST_REG--; \
|
||||
else DEST_REG++; \
|
||||
CNT_REG--; \
|
||||
cycles -= is486 ? 5 : 8; \
|
||||
reads++; total_cycles += is486 ? 5 : 8; \
|
||||
ins++; \
|
||||
if (cycles < cycles_end) \
|
||||
break; \
|
||||
} \
|
||||
ins--; \
|
||||
PREFETCH_RUN(total_cycles, 1, -1, reads, 0, 0, 0, 0); \
|
||||
if ((CNT_REG > 0) && (FV == tempz)) \
|
||||
{ \
|
||||
CPU_BLOCK_END(); \
|
||||
cpu_state.pc = cpu_state.oldpc; \
|
||||
return 1; \
|
||||
} \
|
||||
return cpu_state.abrt; \
|
||||
} \
|
||||
static int opREP_SCASW_ ## size(uint32_t fetchdat) \
|
||||
{ \
|
||||
int reads = 0, total_cycles = 0, tempz; \
|
||||
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*/ \
|
||||
tempz = FV; \
|
||||
if ((CNT_REG > 0) && (FV == tempz)) \
|
||||
SEG_CHECK_READ(&cpu_state.seg_es); \
|
||||
while ((CNT_REG > 0) && (FV == tempz)) \
|
||||
{ \
|
||||
CHECK_READ_REP(&cpu_state.seg_es, DEST_REG, DEST_REG + 1); \
|
||||
uint16_t temp = readmemw(es, DEST_REG); if (cpu_state.abrt) break;\
|
||||
setsub16(AX, temp); \
|
||||
tempz = (ZF_SET()) ? 1 : 0; \
|
||||
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; \
|
||||
ins++; \
|
||||
if (cycles < cycles_end) \
|
||||
break; \
|
||||
} \
|
||||
ins--; \
|
||||
PREFETCH_RUN(total_cycles, 1, -1, reads, 0, 0, 0, 0); \
|
||||
if ((CNT_REG > 0) && (FV == tempz)) \
|
||||
{ \
|
||||
CPU_BLOCK_END(); \
|
||||
cpu_state.pc = cpu_state.oldpc; \
|
||||
return 1; \
|
||||
} \
|
||||
return cpu_state.abrt; \
|
||||
} \
|
||||
static int opREP_SCASL_ ## size(uint32_t fetchdat) \
|
||||
{ \
|
||||
int reads = 0, total_cycles = 0, tempz; \
|
||||
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*/ \
|
||||
tempz = FV; \
|
||||
if ((CNT_REG > 0) && (FV == tempz)) \
|
||||
SEG_CHECK_READ(&cpu_state.seg_es); \
|
||||
while ((CNT_REG > 0) && (FV == tempz)) \
|
||||
{ \
|
||||
CHECK_READ_REP(&cpu_state.seg_es, DEST_REG, DEST_REG + 3); \
|
||||
uint32_t temp = readmeml(es, DEST_REG); if (cpu_state.abrt) break;\
|
||||
setsub32(EAX, temp); \
|
||||
tempz = (ZF_SET()) ? 1 : 0; \
|
||||
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; \
|
||||
ins++; \
|
||||
if (cycles < cycles_end) \
|
||||
break; \
|
||||
} \
|
||||
ins--; \
|
||||
PREFETCH_RUN(total_cycles, 1, -1, 0, reads, 0, 0, 0); \
|
||||
if ((CNT_REG > 0) && (FV == tempz)) \
|
||||
{ \
|
||||
CPU_BLOCK_END(); \
|
||||
cpu_state.pc = cpu_state.oldpc; \
|
||||
return 1; \
|
||||
} \
|
||||
return cpu_state.abrt; \
|
||||
}
|
||||
|
||||
REP_OPS(a16, CX, SI, DI)
|
||||
REP_OPS(a32, ECX, ESI, EDI)
|
||||
REP_OPS_CMPS_SCAS(a16_NE, CX, SI, DI, 0)
|
||||
REP_OPS_CMPS_SCAS(a16_E, CX, SI, DI, 1)
|
||||
REP_OPS_CMPS_SCAS(a32_NE, ECX, ESI, EDI, 0)
|
||||
REP_OPS_CMPS_SCAS(a32_E, ECX, ESI, EDI, 1)
|
||||
|
||||
static int opREPNE(uint32_t fetchdat)
|
||||
{
|
||||
fetchdat = fastreadl(cs + cpu_state.pc);
|
||||
if (cpu_state.abrt) return 1;
|
||||
cpu_state.pc++;
|
||||
|
||||
CLOCK_CYCLES(2);
|
||||
PREFETCH_PREFIX();
|
||||
if (x86_opcodes_REPNE[(fetchdat & 0xff) | cpu_state.op32])
|
||||
return x86_opcodes_REPNE[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8);
|
||||
return x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8);
|
||||
}
|
||||
static int opREPE(uint32_t fetchdat)
|
||||
{
|
||||
fetchdat = fastreadl(cs + cpu_state.pc);
|
||||
if (cpu_state.abrt) return 1;
|
||||
cpu_state.pc++;
|
||||
|
||||
CLOCK_CYCLES(2);
|
||||
PREFETCH_PREFIX();
|
||||
if (x86_opcodes_REPE[(fetchdat & 0xff) | cpu_state.op32])
|
||||
return x86_opcodes_REPE[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8);
|
||||
return x86_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8);
|
||||
}
|
||||
267
src/cpu_common/x86_ops_ret.h
Normal file
267
src/cpu_common/x86_ops_ret.h
Normal file
@@ -0,0 +1,267 @@
|
||||
#ifdef USE_NEW_DYNAREC
|
||||
#define CPU_SET_OXPC
|
||||
#else
|
||||
#define CPU_SET_OXPC oxpc = cpu_state.pc;
|
||||
#endif
|
||||
|
||||
#define RETF_a16(stack_offset) \
|
||||
if ((msw&1) && !(cpu_state.eflags&VM_FLAG)) \
|
||||
{ \
|
||||
pmoderetf(0, stack_offset); \
|
||||
return 1; \
|
||||
} \
|
||||
CPU_SET_OXPC \
|
||||
if (stack32) \
|
||||
{ \
|
||||
cpu_state.pc = readmemw(ss, ESP); \
|
||||
loadcs(readmemw(ss, ESP + 2)); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
cpu_state.pc = readmemw(ss, SP); \
|
||||
loadcs(readmemw(ss, SP + 2)); \
|
||||
} \
|
||||
if (cpu_state.abrt) return 1; \
|
||||
if (stack32) ESP += 4 + stack_offset; \
|
||||
else SP += 4 + stack_offset; \
|
||||
cycles -= timing_retf_rm;
|
||||
|
||||
#define RETF_a32(stack_offset) \
|
||||
if ((msw&1) && !(cpu_state.eflags&VM_FLAG)) \
|
||||
{ \
|
||||
pmoderetf(1, stack_offset); \
|
||||
return 1; \
|
||||
} \
|
||||
CPU_SET_OXPC \
|
||||
if (stack32) \
|
||||
{ \
|
||||
cpu_state.pc = readmeml(ss, ESP); \
|
||||
loadcs(readmeml(ss, ESP + 4) & 0xffff); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
cpu_state.pc = readmeml(ss, SP); \
|
||||
loadcs(readmeml(ss, SP + 4) & 0xffff); \
|
||||
} \
|
||||
if (cpu_state.abrt) return 1; \
|
||||
if (stack32) ESP += 8 + stack_offset; \
|
||||
else SP += 8 + stack_offset; \
|
||||
cycles -= timing_retf_rm;
|
||||
|
||||
static int opRETF_a16(uint32_t fetchdat)
|
||||
{
|
||||
int cycles_old = cycles; UN_USED(cycles_old);
|
||||
|
||||
CPU_BLOCK_END();
|
||||
RETF_a16(0);
|
||||
|
||||
PREFETCH_RUN(cycles_old-cycles, 1, -1, 2,0,0,0, 0);
|
||||
PREFETCH_FLUSH();
|
||||
return 0;
|
||||
}
|
||||
static int opRETF_a32(uint32_t fetchdat)
|
||||
{
|
||||
int cycles_old = cycles; UN_USED(cycles_old);
|
||||
|
||||
CPU_BLOCK_END();
|
||||
RETF_a32(0);
|
||||
|
||||
PREFETCH_RUN(cycles_old-cycles, 1, -1, 0,2,0,0, 1);
|
||||
PREFETCH_FLUSH();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opRETF_a16_imm(uint32_t fetchdat)
|
||||
{
|
||||
uint16_t offset = getwordf();
|
||||
int cycles_old = cycles; UN_USED(cycles_old);
|
||||
|
||||
CPU_BLOCK_END();
|
||||
RETF_a16(offset);
|
||||
|
||||
PREFETCH_RUN(cycles_old-cycles, 3, -1, 2,0,0,0, 0);
|
||||
PREFETCH_FLUSH();
|
||||
return 0;
|
||||
}
|
||||
static int opRETF_a32_imm(uint32_t fetchdat)
|
||||
{
|
||||
uint16_t offset = getwordf();
|
||||
int cycles_old = cycles; UN_USED(cycles_old);
|
||||
|
||||
CPU_BLOCK_END();
|
||||
RETF_a32(offset);
|
||||
|
||||
PREFETCH_RUN(cycles_old-cycles, 3, -1, 0,2,0,0, 1);
|
||||
PREFETCH_FLUSH();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opIRET_286(uint32_t fetchdat)
|
||||
{
|
||||
int cycles_old = cycles; UN_USED(cycles_old);
|
||||
|
||||
if ((cr0 & 1) && (cpu_state.eflags & VM_FLAG) && (IOPL != 3))
|
||||
{
|
||||
x86gpf(NULL,0);
|
||||
return 1;
|
||||
}
|
||||
if (msw&1)
|
||||
{
|
||||
optype = IRET;
|
||||
pmodeiret(0);
|
||||
optype = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint16_t new_cs;
|
||||
CPU_SET_OXPC
|
||||
if (stack32)
|
||||
{
|
||||
cpu_state.pc = readmemw(ss, ESP);
|
||||
new_cs = readmemw(ss, ESP + 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));
|
||||
cpu_state.flags = (cpu_state.flags & 0x7000) | (readmemw(ss, ((SP + 4) & 0xffff)) & 0x0fd5) | 2;
|
||||
SP += 6;
|
||||
}
|
||||
loadcs(new_cs);
|
||||
cycles -= timing_iret_rm;
|
||||
}
|
||||
flags_extract();
|
||||
nmi_enable = 1;
|
||||
CPU_BLOCK_END();
|
||||
|
||||
PREFETCH_RUN(cycles_old-cycles, 1, -1, 2,0,0,0, 0);
|
||||
PREFETCH_FLUSH();
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
|
||||
static int opIRET(uint32_t fetchdat)
|
||||
{
|
||||
int cycles_old = cycles; UN_USED(cycles_old);
|
||||
|
||||
if ((cr0 & 1) && (cpu_state.eflags & VM_FLAG) && (IOPL != 3))
|
||||
{
|
||||
if (cr4 & CR4_VME)
|
||||
{
|
||||
uint16_t new_pc, new_cs, new_flags;
|
||||
|
||||
new_pc = readmemw(ss, SP);
|
||||
new_cs = readmemw(ss, ((SP + 2) & 0xffff));
|
||||
new_flags = readmemw(ss, ((SP + 4) & 0xffff));
|
||||
if (cpu_state.abrt)
|
||||
return 1;
|
||||
|
||||
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)
|
||||
cpu_state.eflags |= VIF_FLAG;
|
||||
else
|
||||
cpu_state.eflags &= ~VIF_FLAG;
|
||||
cpu_state.flags = (cpu_state.flags & 0x3300) | (new_flags & 0x4cd5) | 2;
|
||||
loadcs(new_cs);
|
||||
cpu_state.pc = new_pc;
|
||||
|
||||
cycles -= timing_iret_rm;
|
||||
}
|
||||
else
|
||||
{
|
||||
x86gpf(NULL,0);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (msw&1)
|
||||
{
|
||||
optype = IRET;
|
||||
pmodeiret(0);
|
||||
optype = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint16_t new_cs;
|
||||
CPU_SET_OXPC
|
||||
if (stack32)
|
||||
{
|
||||
cpu_state.pc = readmemw(ss, ESP);
|
||||
new_cs = readmemw(ss, ESP + 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));
|
||||
cpu_state.flags = (readmemw(ss, ((SP + 4) & 0xffff)) & 0xffd5) | 2;
|
||||
SP += 6;
|
||||
}
|
||||
loadcs(new_cs);
|
||||
cycles -= timing_iret_rm;
|
||||
}
|
||||
}
|
||||
flags_extract();
|
||||
nmi_enable = 1;
|
||||
CPU_BLOCK_END();
|
||||
|
||||
PREFETCH_RUN(cycles_old-cycles, 1, -1, 2,0,0,0, 0);
|
||||
PREFETCH_FLUSH();
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
|
||||
static int opIRETD(uint32_t fetchdat)
|
||||
{
|
||||
int cycles_old = cycles; UN_USED(cycles_old);
|
||||
|
||||
if ((cr0 & 1) && (cpu_state.eflags & VM_FLAG) && (IOPL != 3))
|
||||
{
|
||||
x86gpf(NULL,0);
|
||||
return 1;
|
||||
}
|
||||
if (msw & 1)
|
||||
{
|
||||
optype = IRET;
|
||||
pmodeiret(1);
|
||||
optype = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint16_t new_cs;
|
||||
CPU_SET_OXPC
|
||||
if (stack32)
|
||||
{
|
||||
cpu_state.pc = readmeml(ss, ESP);
|
||||
new_cs = readmemw(ss, ESP + 4);
|
||||
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));
|
||||
cpu_state.flags = (readmemw(ss,(SP + 8) & 0xffff) & 0xffd5) | 2;
|
||||
cpu_state.eflags = readmemw(ss, (SP + 10) & 0xffff);
|
||||
SP += 12;
|
||||
}
|
||||
loadcs(new_cs);
|
||||
cycles -= timing_iret_rm;
|
||||
}
|
||||
flags_extract();
|
||||
nmi_enable = 1;
|
||||
CPU_BLOCK_END();
|
||||
|
||||
PREFETCH_RUN(cycles_old-cycles, 1, -1, 0,2,0,0, 1);
|
||||
PREFETCH_FLUSH();
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
|
||||
37
src/cpu_common/x86_ops_set.h
Normal file
37
src/cpu_common/x86_ops_set.h
Normal file
@@ -0,0 +1,37 @@
|
||||
#define opSET(condition) \
|
||||
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; \
|
||||
}
|
||||
|
||||
opSET(O)
|
||||
opSET(NO)
|
||||
opSET(B)
|
||||
opSET(NB)
|
||||
opSET(E)
|
||||
opSET(NE)
|
||||
opSET(BE)
|
||||
opSET(NBE)
|
||||
opSET(S)
|
||||
opSET(NS)
|
||||
opSET(P)
|
||||
opSET(NP)
|
||||
opSET(L)
|
||||
opSET(NL)
|
||||
opSET(LE)
|
||||
opSET(NLE)
|
||||
525
src/cpu_common/x86_ops_stack.h
Normal file
525
src/cpu_common/x86_ops_stack.h
Normal file
@@ -0,0 +1,525 @@
|
||||
#define PUSH_W_OP(reg) \
|
||||
static int opPUSH_ ## reg (uint32_t fetchdat) \
|
||||
{ \
|
||||
PUSH_W(reg); \
|
||||
CLOCK_CYCLES((is486) ? 1 : 2); \
|
||||
PREFETCH_RUN(2, 1, -1, 0,0,1,0, 0); \
|
||||
return cpu_state.abrt; \
|
||||
}
|
||||
|
||||
#define PUSH_L_OP(reg) \
|
||||
static int opPUSH_ ## reg (uint32_t fetchdat) \
|
||||
{ \
|
||||
PUSH_L(reg); \
|
||||
CLOCK_CYCLES((is486) ? 1 : 2); \
|
||||
PREFETCH_RUN(2, 1, -1, 0,0,0,1, 0); \
|
||||
return cpu_state.abrt; \
|
||||
}
|
||||
|
||||
#define POP_W_OP(reg) \
|
||||
static int opPOP_ ## reg (uint32_t fetchdat) \
|
||||
{ \
|
||||
reg = POP_W(); \
|
||||
CLOCK_CYCLES((is486) ? 1 : 4); \
|
||||
PREFETCH_RUN(4, 1, -1, 1,0,0,0, 0); \
|
||||
return cpu_state.abrt; \
|
||||
}
|
||||
|
||||
#define POP_L_OP(reg) \
|
||||
static int opPOP_ ## reg (uint32_t fetchdat) \
|
||||
{ \
|
||||
reg = POP_L(); \
|
||||
CLOCK_CYCLES((is486) ? 1 : 4); \
|
||||
PREFETCH_RUN(4, 1, -1, 0,1,0,0, 0); \
|
||||
return cpu_state.abrt; \
|
||||
}
|
||||
|
||||
PUSH_W_OP(AX)
|
||||
PUSH_W_OP(BX)
|
||||
PUSH_W_OP(CX)
|
||||
PUSH_W_OP(DX)
|
||||
PUSH_W_OP(SI)
|
||||
PUSH_W_OP(DI)
|
||||
PUSH_W_OP(BP)
|
||||
PUSH_W_OP(SP)
|
||||
|
||||
PUSH_L_OP(EAX)
|
||||
PUSH_L_OP(EBX)
|
||||
PUSH_L_OP(ECX)
|
||||
PUSH_L_OP(EDX)
|
||||
PUSH_L_OP(ESI)
|
||||
PUSH_L_OP(EDI)
|
||||
PUSH_L_OP(EBP)
|
||||
PUSH_L_OP(ESP)
|
||||
|
||||
POP_W_OP(AX)
|
||||
POP_W_OP(BX)
|
||||
POP_W_OP(CX)
|
||||
POP_W_OP(DX)
|
||||
POP_W_OP(SI)
|
||||
POP_W_OP(DI)
|
||||
POP_W_OP(BP)
|
||||
POP_W_OP(SP)
|
||||
|
||||
POP_L_OP(EAX)
|
||||
POP_L_OP(EBX)
|
||||
POP_L_OP(ECX)
|
||||
POP_L_OP(EDX)
|
||||
POP_L_OP(ESI)
|
||||
POP_L_OP(EDI)
|
||||
POP_L_OP(EBP)
|
||||
POP_L_OP(ESP)
|
||||
|
||||
|
||||
static int opPUSHA_w(uint32_t fetchdat)
|
||||
{
|
||||
if (stack32)
|
||||
{
|
||||
writememw(ss, ESP - 2, AX);
|
||||
writememw(ss, ESP - 4, CX);
|
||||
writememw(ss, ESP - 6, DX);
|
||||
writememw(ss, ESP - 8, BX);
|
||||
writememw(ss, ESP - 10, SP);
|
||||
writememw(ss, ESP - 12, BP);
|
||||
writememw(ss, ESP - 14, SI);
|
||||
writememw(ss, ESP - 16, DI);
|
||||
if (!cpu_state.abrt) ESP -= 16;
|
||||
}
|
||||
else
|
||||
{
|
||||
writememw(ss, ((SP - 2) & 0xFFFF), AX);
|
||||
writememw(ss, ((SP - 4) & 0xFFFF), CX);
|
||||
writememw(ss, ((SP - 6) & 0xFFFF), DX);
|
||||
writememw(ss, ((SP - 8) & 0xFFFF), BX);
|
||||
writememw(ss, ((SP - 10) & 0xFFFF), SP);
|
||||
writememw(ss, ((SP - 12) & 0xFFFF), BP);
|
||||
writememw(ss, ((SP - 14) & 0xFFFF), SI);
|
||||
writememw(ss, ((SP - 16) & 0xFFFF), DI);
|
||||
if (!cpu_state.abrt) SP -= 16;
|
||||
}
|
||||
CLOCK_CYCLES((is486) ? 11 : 18);
|
||||
PREFETCH_RUN(18, 1, -1, 0,0,8,0, 0);
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
static int opPUSHA_l(uint32_t fetchdat)
|
||||
{
|
||||
if (stack32)
|
||||
{
|
||||
writememl(ss, ESP - 4, EAX);
|
||||
writememl(ss, ESP - 8, ECX);
|
||||
writememl(ss, ESP - 12, EDX);
|
||||
writememl(ss, ESP - 16, EBX);
|
||||
writememl(ss, ESP - 20, ESP);
|
||||
writememl(ss, ESP - 24, EBP);
|
||||
writememl(ss, ESP - 28, ESI);
|
||||
writememl(ss, ESP - 32, EDI);
|
||||
if (!cpu_state.abrt) ESP -= 32;
|
||||
}
|
||||
else
|
||||
{
|
||||
writememl(ss, ((SP - 4) & 0xFFFF), EAX);
|
||||
writememl(ss, ((SP - 8) & 0xFFFF), ECX);
|
||||
writememl(ss, ((SP - 12) & 0xFFFF), EDX);
|
||||
writememl(ss, ((SP - 16) & 0xFFFF), EBX);
|
||||
writememl(ss, ((SP - 20) & 0xFFFF), ESP);
|
||||
writememl(ss, ((SP - 24) & 0xFFFF), EBP);
|
||||
writememl(ss, ((SP - 28) & 0xFFFF), ESI);
|
||||
writememl(ss, ((SP - 32) & 0xFFFF), EDI);
|
||||
if (!cpu_state.abrt) SP -= 32;
|
||||
}
|
||||
CLOCK_CYCLES((is486) ? 11 : 18);
|
||||
PREFETCH_RUN(18, 1, -1, 0,0,0,8, 0);
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
|
||||
static int opPOPA_w(uint32_t fetchdat)
|
||||
{
|
||||
if (stack32)
|
||||
{
|
||||
DI = readmemw(ss, ESP); if (cpu_state.abrt) return 1;
|
||||
SI = readmemw(ss, ESP + 2); if (cpu_state.abrt) return 1;
|
||||
BP = readmemw(ss, ESP + 4); if (cpu_state.abrt) return 1;
|
||||
BX = readmemw(ss, ESP + 8); if (cpu_state.abrt) return 1;
|
||||
DX = readmemw(ss, ESP + 10); if (cpu_state.abrt) return 1;
|
||||
CX = readmemw(ss, ESP + 12); if (cpu_state.abrt) return 1;
|
||||
AX = readmemw(ss, ESP + 14); if (cpu_state.abrt) return 1;
|
||||
ESP += 16;
|
||||
}
|
||||
else
|
||||
{
|
||||
DI = readmemw(ss, ((SP) & 0xFFFF)); if (cpu_state.abrt) return 1;
|
||||
SI = readmemw(ss, ((SP + 2) & 0xFFFF)); if (cpu_state.abrt) return 1;
|
||||
BP = readmemw(ss, ((SP + 4) & 0xFFFF)); if (cpu_state.abrt) return 1;
|
||||
BX = readmemw(ss, ((SP + 8) & 0xFFFF)); if (cpu_state.abrt) return 1;
|
||||
DX = readmemw(ss, ((SP + 10) & 0xFFFF)); if (cpu_state.abrt) return 1;
|
||||
CX = readmemw(ss, ((SP + 12) & 0xFFFF)); if (cpu_state.abrt) return 1;
|
||||
AX = readmemw(ss, ((SP + 14) & 0xFFFF)); if (cpu_state.abrt) return 1;
|
||||
SP += 16;
|
||||
}
|
||||
CLOCK_CYCLES((is486) ? 9 : 24);
|
||||
PREFETCH_RUN(24, 1, -1, 7,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opPOPA_l(uint32_t fetchdat)
|
||||
{
|
||||
if (stack32)
|
||||
{
|
||||
EDI = readmeml(ss, ESP); if (cpu_state.abrt) return 1;
|
||||
ESI = readmeml(ss, ESP + 4); if (cpu_state.abrt) return 1;
|
||||
EBP = readmeml(ss, ESP + 8); if (cpu_state.abrt) return 1;
|
||||
EBX = readmeml(ss, ESP + 16); if (cpu_state.abrt) return 1;
|
||||
EDX = readmeml(ss, ESP + 20); if (cpu_state.abrt) return 1;
|
||||
ECX = readmeml(ss, ESP + 24); if (cpu_state.abrt) return 1;
|
||||
EAX = readmeml(ss, ESP + 28); if (cpu_state.abrt) return 1;
|
||||
ESP += 32;
|
||||
}
|
||||
else
|
||||
{
|
||||
EDI = readmeml(ss, ((SP) & 0xFFFF)); if (cpu_state.abrt) return 1;
|
||||
ESI = readmeml(ss, ((SP + 4) & 0xFFFF)); if (cpu_state.abrt) return 1;
|
||||
EBP = readmeml(ss, ((SP + 8) & 0xFFFF)); if (cpu_state.abrt) return 1;
|
||||
EBX = readmeml(ss, ((SP + 16) & 0xFFFF)); if (cpu_state.abrt) return 1;
|
||||
EDX = readmeml(ss, ((SP + 20) & 0xFFFF)); if (cpu_state.abrt) return 1;
|
||||
ECX = readmeml(ss, ((SP + 24) & 0xFFFF)); if (cpu_state.abrt) return 1;
|
||||
EAX = readmeml(ss, ((SP + 28) & 0xFFFF)); if (cpu_state.abrt) return 1;
|
||||
SP += 32;
|
||||
}
|
||||
CLOCK_CYCLES((is486) ? 9 : 24);
|
||||
PREFETCH_RUN(24, 1, -1, 0,7,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opPUSH_imm_w(uint32_t fetchdat)
|
||||
{
|
||||
uint16_t val = getwordf();
|
||||
PUSH_W(val);
|
||||
CLOCK_CYCLES(2);
|
||||
PREFETCH_RUN(2, 3, -1, 0,0,1,0, 0);
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
static int opPUSH_imm_l(uint32_t fetchdat)
|
||||
{
|
||||
uint32_t val = getlong(); if (cpu_state.abrt) return 1;
|
||||
PUSH_L(val);
|
||||
CLOCK_CYCLES(2);
|
||||
PREFETCH_RUN(2, 3, -1, 0,0,0,1, 0);
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
|
||||
static int opPUSH_imm_bw(uint32_t fetchdat)
|
||||
{
|
||||
uint16_t tempw = getbytef();
|
||||
|
||||
if (tempw & 0x80) tempw |= 0xFF00;
|
||||
PUSH_W(tempw);
|
||||
|
||||
CLOCK_CYCLES(2);
|
||||
PREFETCH_RUN(2, 2, -1, 0,0,1,0, 0);
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
static int opPUSH_imm_bl(uint32_t fetchdat)
|
||||
{
|
||||
uint32_t templ = getbytef();
|
||||
|
||||
if (templ & 0x80) templ |= 0xFFFFFF00;
|
||||
PUSH_L(templ);
|
||||
|
||||
CLOCK_CYCLES(2);
|
||||
PREFETCH_RUN(2, 2, -1, 0,0,0,1, 0);
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
|
||||
static int opPOPW_a16(uint32_t fetchdat)
|
||||
{
|
||||
uint16_t temp;
|
||||
|
||||
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)
|
||||
{
|
||||
if (stack32) ESP -= 2;
|
||||
else SP -= 2;
|
||||
}
|
||||
|
||||
if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 6);
|
||||
else CLOCK_CYCLES((cpu_mod == 3) ? 4 : 5);
|
||||
PREFETCH_RUN((cpu_mod == 3) ? 4 : 5, 2, rmdat, 1,0,(cpu_mod == 3) ? 0:1,0, 0);
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
static int opPOPW_a32(uint32_t fetchdat)
|
||||
{
|
||||
uint16_t temp;
|
||||
|
||||
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)
|
||||
{
|
||||
if (stack32) ESP -= 2;
|
||||
else SP -= 2;
|
||||
}
|
||||
|
||||
if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 6);
|
||||
else CLOCK_CYCLES((cpu_mod == 3) ? 4 : 5);
|
||||
PREFETCH_RUN((cpu_mod == 3) ? 4 : 5, 2, rmdat, 1,0,(cpu_mod == 3) ? 0:1,0, 1);
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
|
||||
static int opPOPL_a16(uint32_t fetchdat)
|
||||
{
|
||||
uint32_t temp;
|
||||
|
||||
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)
|
||||
{
|
||||
if (stack32) ESP -= 4;
|
||||
else SP -= 4;
|
||||
}
|
||||
|
||||
if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 6);
|
||||
else CLOCK_CYCLES((cpu_mod == 3) ? 4 : 5);
|
||||
PREFETCH_RUN((cpu_mod == 3) ? 4 : 5, 2, rmdat, 0,1,0,(cpu_mod == 3) ? 0:1, 0);
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
static int opPOPL_a32(uint32_t fetchdat)
|
||||
{
|
||||
uint32_t temp;
|
||||
|
||||
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)
|
||||
{
|
||||
if (stack32) ESP -= 4;
|
||||
else SP -= 4;
|
||||
}
|
||||
|
||||
if (is486) CLOCK_CYCLES((cpu_mod == 3) ? 1 : 6);
|
||||
else CLOCK_CYCLES((cpu_mod == 3) ? 4 : 5);
|
||||
PREFETCH_RUN((cpu_mod == 3) ? 4 : 5, 2, rmdat, 0,1,0,(cpu_mod == 3) ? 0:1, 1);
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
|
||||
|
||||
static int opENTER_w(uint32_t fetchdat)
|
||||
{
|
||||
uint16_t offset;
|
||||
int count;
|
||||
uint32_t tempEBP, tempESP, frame_ptr;
|
||||
int reads = 0, writes = 1, instr_cycles = 0;
|
||||
uint16_t tempw;
|
||||
|
||||
offset = getwordf();
|
||||
count = (fetchdat >> 16) & 0xff; cpu_state.pc++;
|
||||
tempEBP = EBP;
|
||||
tempESP = ESP;
|
||||
|
||||
PUSH_W(BP); if (cpu_state.abrt) return 1;
|
||||
frame_ptr = ESP;
|
||||
|
||||
if (count > 0)
|
||||
{
|
||||
while (--count)
|
||||
{
|
||||
BP -= 2;
|
||||
tempw = readmemw(ss, BP);
|
||||
if (cpu_state.abrt) { ESP = tempESP; EBP = tempEBP; return 1; }
|
||||
PUSH_W(tempw);
|
||||
if (cpu_state.abrt) { ESP = tempESP; EBP = tempEBP; return 1; }
|
||||
CLOCK_CYCLES((is486) ? 3 : 4);
|
||||
reads++; writes++; instr_cycles += (is486) ? 3 : 4;
|
||||
}
|
||||
PUSH_W(frame_ptr);
|
||||
if (cpu_state.abrt) { ESP = tempESP; EBP = tempEBP; return 1; }
|
||||
CLOCK_CYCLES((is486) ? 3 : 5);
|
||||
writes++; instr_cycles += (is486) ? 3 : 5;
|
||||
}
|
||||
BP = frame_ptr;
|
||||
|
||||
if (stack32) ESP -= offset;
|
||||
else SP -= offset;
|
||||
CLOCK_CYCLES((is486) ? 14 : 10);
|
||||
instr_cycles += (is486) ? 14 : 10;
|
||||
PREFETCH_RUN(instr_cycles, 3, -1, reads,0,writes,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opENTER_l(uint32_t fetchdat)
|
||||
{
|
||||
uint16_t offset;
|
||||
int count;
|
||||
uint32_t tempEBP, tempESP, frame_ptr;
|
||||
int reads = 0, writes = 1, instr_cycles = 0;
|
||||
uint32_t templ;
|
||||
|
||||
offset = getwordf();
|
||||
count = (fetchdat >> 16) & 0xff; cpu_state.pc++;
|
||||
tempEBP = EBP; tempESP = ESP;
|
||||
|
||||
PUSH_L(EBP); if (cpu_state.abrt) return 1;
|
||||
frame_ptr = ESP;
|
||||
|
||||
if (count > 0)
|
||||
{
|
||||
while (--count)
|
||||
{
|
||||
EBP -= 4;
|
||||
templ = readmeml(ss, EBP);
|
||||
if (cpu_state.abrt) { ESP = tempESP; EBP = tempEBP; return 1; }
|
||||
PUSH_L(templ);
|
||||
if (cpu_state.abrt) { ESP = tempESP; EBP = tempEBP; return 1; }
|
||||
CLOCK_CYCLES((is486) ? 3 : 4);
|
||||
reads++; writes++; instr_cycles += (is486) ? 3 : 4;
|
||||
}
|
||||
PUSH_L(frame_ptr);
|
||||
if (cpu_state.abrt) { ESP = tempESP; EBP = tempEBP; return 1; }
|
||||
CLOCK_CYCLES((is486) ? 3 : 5);
|
||||
writes++; instr_cycles += (is486) ? 3 : 5;
|
||||
}
|
||||
EBP = frame_ptr;
|
||||
|
||||
if (stack32) ESP -= offset;
|
||||
else SP -= offset;
|
||||
CLOCK_CYCLES((is486) ? 14 : 10);
|
||||
instr_cycles += (is486) ? 14 : 10;
|
||||
PREFETCH_RUN(instr_cycles, 3, -1, reads,0,writes,0, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int opLEAVE_w(uint32_t fetchdat)
|
||||
{
|
||||
uint32_t tempESP = ESP;
|
||||
uint16_t temp;
|
||||
|
||||
SP = BP;
|
||||
temp = POP_W();
|
||||
if (cpu_state.abrt) { ESP = tempESP; return 1; }
|
||||
BP = temp;
|
||||
|
||||
CLOCK_CYCLES(4);
|
||||
PREFETCH_RUN(4, 1, -1, 1,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opLEAVE_l(uint32_t fetchdat)
|
||||
{
|
||||
uint32_t tempESP = ESP;
|
||||
uint32_t temp;
|
||||
|
||||
ESP = EBP;
|
||||
temp = POP_L();
|
||||
if (cpu_state.abrt) { ESP = tempESP; return 1; }
|
||||
EBP = temp;
|
||||
|
||||
CLOCK_CYCLES(4);
|
||||
PREFETCH_RUN(4, 1, -1, 0,1,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#define PUSH_SEG_OPS(seg) \
|
||||
static int opPUSH_ ## seg ## _w(uint32_t fetchdat) \
|
||||
{ \
|
||||
PUSH_W(seg); \
|
||||
CLOCK_CYCLES(2); \
|
||||
PREFETCH_RUN(2, 1, -1, 0,0,1,0, 0); \
|
||||
return cpu_state.abrt; \
|
||||
} \
|
||||
static int opPUSH_ ## seg ## _l(uint32_t fetchdat) \
|
||||
{ \
|
||||
PUSH_L(seg); \
|
||||
CLOCK_CYCLES(2); \
|
||||
PREFETCH_RUN(2, 1, -1, 0,0,0,1, 0); \
|
||||
return cpu_state.abrt; \
|
||||
}
|
||||
|
||||
#define POP_SEG_OPS(seg, realseg) \
|
||||
static int opPOP_ ## seg ## _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, realseg); if (cpu_state.abrt) ESP = temp_esp; \
|
||||
CLOCK_CYCLES(is486 ? 3 : 7); \
|
||||
PREFETCH_RUN(is486 ? 3 : 7, 1, -1, 0,0,1,0, 0); \
|
||||
return cpu_state.abrt; \
|
||||
} \
|
||||
static int opPOP_ ## seg ## _l(uint32_t fetchdat) \
|
||||
{ \
|
||||
uint32_t temp_seg; \
|
||||
uint32_t temp_esp = ESP; \
|
||||
temp_seg = POP_L(); if (cpu_state.abrt) return 1; \
|
||||
loadseg(temp_seg & 0xffff, realseg); if (cpu_state.abrt) ESP = temp_esp; \
|
||||
CLOCK_CYCLES(is486 ? 3 : 7); \
|
||||
PREFETCH_RUN(is486 ? 3 : 7, 1, -1, 0,0,1,0, 0); \
|
||||
return cpu_state.abrt; \
|
||||
}
|
||||
|
||||
|
||||
PUSH_SEG_OPS(CS);
|
||||
PUSH_SEG_OPS(DS);
|
||||
PUSH_SEG_OPS(ES);
|
||||
PUSH_SEG_OPS(FS);
|
||||
PUSH_SEG_OPS(GS);
|
||||
PUSH_SEG_OPS(SS);
|
||||
|
||||
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, &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 = &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;
|
||||
}
|
||||
static int opPOP_SS_l(uint32_t fetchdat)
|
||||
{
|
||||
uint32_t temp_seg;
|
||||
uint32_t temp_esp = ESP;
|
||||
temp_seg = POP_L(); if (cpu_state.abrt) 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 = &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;
|
||||
}
|
||||
597
src/cpu_common/x86_ops_string.h
Normal file
597
src/cpu_common/x86_ops_string.h
Normal file
@@ -0,0 +1,597 @@
|
||||
static int opMOVSB_a16(uint32_t fetchdat)
|
||||
{
|
||||
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 (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;
|
||||
|
||||
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 (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;
|
||||
|
||||
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 (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;
|
||||
|
||||
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 (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;
|
||||
|
||||
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 (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;
|
||||
|
||||
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 (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, 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 (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, 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 (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, 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 (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, 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 (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, 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 (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, 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 (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 (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 (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 (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 (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 (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 (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;
|
||||
|
||||
SEG_CHECK_READ(cpu_state.ea_seg);
|
||||
temp = readmemb(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) return 1;
|
||||
AL = temp;
|
||||
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;
|
||||
|
||||
SEG_CHECK_READ(cpu_state.ea_seg);
|
||||
temp = readmemb(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) return 1;
|
||||
AL = temp;
|
||||
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;
|
||||
|
||||
SEG_CHECK_READ(cpu_state.ea_seg);
|
||||
temp = readmemw(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) return 1;
|
||||
AX = temp;
|
||||
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;
|
||||
|
||||
SEG_CHECK_READ(cpu_state.ea_seg);
|
||||
temp = readmemw(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) return 1;
|
||||
AX = temp;
|
||||
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;
|
||||
|
||||
SEG_CHECK_READ(cpu_state.ea_seg);
|
||||
temp = readmeml(cpu_state.ea_seg->base, SI); if (cpu_state.abrt) return 1;
|
||||
EAX = temp;
|
||||
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;
|
||||
|
||||
SEG_CHECK_READ(cpu_state.ea_seg);
|
||||
temp = readmeml(cpu_state.ea_seg->base, ESI); if (cpu_state.abrt) return 1;
|
||||
EAX = temp;
|
||||
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;
|
||||
|
||||
SEG_CHECK_READ(&cpu_state.seg_es);
|
||||
temp = readmemb(es, DI); if (cpu_state.abrt) return 1;
|
||||
setsub8(AL, temp);
|
||||
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;
|
||||
|
||||
SEG_CHECK_READ(&cpu_state.seg_es);
|
||||
temp = readmemb(es, EDI); if (cpu_state.abrt) return 1;
|
||||
setsub8(AL, temp);
|
||||
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;
|
||||
|
||||
SEG_CHECK_READ(&cpu_state.seg_es);
|
||||
temp = readmemw(es, DI); if (cpu_state.abrt) return 1;
|
||||
setsub16(AX, temp);
|
||||
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;
|
||||
|
||||
SEG_CHECK_READ(&cpu_state.seg_es);
|
||||
temp = readmemw(es, EDI); if (cpu_state.abrt) return 1;
|
||||
setsub16(AX, temp);
|
||||
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;
|
||||
|
||||
SEG_CHECK_READ(&cpu_state.seg_es);
|
||||
temp = readmeml(es, DI); if (cpu_state.abrt) return 1;
|
||||
setsub32(EAX, temp);
|
||||
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;
|
||||
|
||||
SEG_CHECK_READ(&cpu_state.seg_es);
|
||||
temp = readmeml(es, EDI); if (cpu_state.abrt) return 1;
|
||||
setsub32(EAX, temp);
|
||||
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 (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 (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 (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 (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 (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 (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;
|
||||
|
||||
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 (cpu_state.flags & D_FLAG) SI--;
|
||||
else SI++;
|
||||
outb(DX, temp);
|
||||
CLOCK_CYCLES(14);
|
||||
PREFETCH_RUN(14, 1, -1, 1,0,1,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opOUTSB_a32(uint32_t fetchdat)
|
||||
{
|
||||
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 (cpu_state.flags & D_FLAG) ESI--;
|
||||
else ESI++;
|
||||
outb(DX, temp);
|
||||
CLOCK_CYCLES(14);
|
||||
PREFETCH_RUN(14, 1, -1, 1,0,1,0, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opOUTSW_a16(uint32_t fetchdat)
|
||||
{
|
||||
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 (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);
|
||||
return 0;
|
||||
}
|
||||
static int opOUTSW_a32(uint32_t fetchdat)
|
||||
{
|
||||
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 (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);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opOUTSL_a16(uint32_t fetchdat)
|
||||
{
|
||||
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 (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);
|
||||
return 0;
|
||||
}
|
||||
static int opOUTSL_a32(uint32_t fetchdat)
|
||||
{
|
||||
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 (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);
|
||||
return 0;
|
||||
}
|
||||
234
src/cpu_common/x86_ops_xchg.h
Normal file
234
src/cpu_common/x86_ops_xchg.h
Normal file
@@ -0,0 +1,234 @@
|
||||
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);
|
||||
CLOCK_CYCLES((cpu_mod == 3) ? 3 : 5);
|
||||
PREFETCH_RUN((cpu_mod == 3) ? 3 : 5, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 0);
|
||||
return 0;
|
||||
}
|
||||
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);
|
||||
CLOCK_CYCLES((cpu_mod == 3) ? 3 : 5);
|
||||
PREFETCH_RUN((cpu_mod == 3) ? 3 : 5, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
CLOCK_CYCLES((cpu_mod == 3) ? 3 : 5);
|
||||
PREFETCH_RUN((cpu_mod == 3) ? 3 : 5, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 0);
|
||||
return 0;
|
||||
}
|
||||
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;
|
||||
CLOCK_CYCLES((cpu_mod == 3) ? 3 : 5);
|
||||
PREFETCH_RUN((cpu_mod == 3) ? 3 : 5, 2, rmdat, (cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1,0, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
CLOCK_CYCLES((cpu_mod == 3) ? 3 : 5);
|
||||
PREFETCH_RUN((cpu_mod == 3) ? 3 : 5, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 0);
|
||||
return 0;
|
||||
}
|
||||
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;
|
||||
CLOCK_CYCLES((cpu_mod == 3) ? 3 : 5);
|
||||
PREFETCH_RUN((cpu_mod == 3) ? 3 : 5, 2, rmdat, 0,(cpu_mod == 3) ? 0:1,0,(cpu_mod == 3) ? 0:1, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int opXCHG_AX_BX(uint32_t fetchdat)
|
||||
{
|
||||
uint16_t temp = AX;
|
||||
AX = BX;
|
||||
BX = temp;
|
||||
CLOCK_CYCLES(3);
|
||||
PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opXCHG_AX_CX(uint32_t fetchdat)
|
||||
{
|
||||
uint16_t temp = AX;
|
||||
AX = CX;
|
||||
CX = temp;
|
||||
CLOCK_CYCLES(3);
|
||||
PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opXCHG_AX_DX(uint32_t fetchdat)
|
||||
{
|
||||
uint16_t temp = AX;
|
||||
AX = DX;
|
||||
DX = temp;
|
||||
CLOCK_CYCLES(3);
|
||||
PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opXCHG_AX_SI(uint32_t fetchdat)
|
||||
{
|
||||
uint16_t temp = AX;
|
||||
AX = SI;
|
||||
SI = temp;
|
||||
CLOCK_CYCLES(3);
|
||||
PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opXCHG_AX_DI(uint32_t fetchdat)
|
||||
{
|
||||
uint16_t temp = AX;
|
||||
AX = DI;
|
||||
DI = temp;
|
||||
CLOCK_CYCLES(3);
|
||||
PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opXCHG_AX_BP(uint32_t fetchdat)
|
||||
{
|
||||
uint16_t temp = AX;
|
||||
AX = BP;
|
||||
BP = temp;
|
||||
CLOCK_CYCLES(3);
|
||||
PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opXCHG_AX_SP(uint32_t fetchdat)
|
||||
{
|
||||
uint16_t temp = AX;
|
||||
AX = SP;
|
||||
SP = temp;
|
||||
CLOCK_CYCLES(3);
|
||||
PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opXCHG_EAX_EBX(uint32_t fetchdat)
|
||||
{
|
||||
uint32_t temp = EAX;
|
||||
EAX = EBX;
|
||||
EBX = temp;
|
||||
CLOCK_CYCLES(3);
|
||||
PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opXCHG_EAX_ECX(uint32_t fetchdat)
|
||||
{
|
||||
uint32_t temp = EAX;
|
||||
EAX = ECX;
|
||||
ECX = temp;
|
||||
CLOCK_CYCLES(3);
|
||||
PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opXCHG_EAX_EDX(uint32_t fetchdat)
|
||||
{
|
||||
uint32_t temp = EAX;
|
||||
EAX = EDX;
|
||||
EDX = temp;
|
||||
CLOCK_CYCLES(3);
|
||||
PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opXCHG_EAX_ESI(uint32_t fetchdat)
|
||||
{
|
||||
uint32_t temp = EAX;
|
||||
EAX = ESI;
|
||||
ESI = temp;
|
||||
CLOCK_CYCLES(3);
|
||||
PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opXCHG_EAX_EDI(uint32_t fetchdat)
|
||||
{
|
||||
uint32_t temp = EAX;
|
||||
EAX = EDI;
|
||||
EDI = temp;
|
||||
CLOCK_CYCLES(3);
|
||||
PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opXCHG_EAX_EBP(uint32_t fetchdat)
|
||||
{
|
||||
uint32_t temp = EAX;
|
||||
EAX = EBP;
|
||||
EBP = temp;
|
||||
CLOCK_CYCLES(3);
|
||||
PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
static int opXCHG_EAX_ESP(uint32_t fetchdat)
|
||||
{
|
||||
uint32_t temp = EAX;
|
||||
EAX = ESP;
|
||||
ESP = temp;
|
||||
CLOCK_CYCLES(3);
|
||||
PREFETCH_RUN(3, 1, -1, 0,0,0,0, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#define opBSWAP(reg) \
|
||||
static int opBSWAP_ ## reg(uint32_t fetchdat) \
|
||||
{ \
|
||||
reg = (reg >> 24) | ((reg >> 8) & 0xff00) | ((reg << 8) & 0xff0000) | ((reg << 24) & 0xff000000); \
|
||||
CLOCK_CYCLES(1); \
|
||||
PREFETCH_RUN(1, 1, -1, 0,0,0,0, 0); \
|
||||
return 0; \
|
||||
}
|
||||
|
||||
opBSWAP(EAX)
|
||||
opBSWAP(EBX)
|
||||
opBSWAP(ECX)
|
||||
opBSWAP(EDX)
|
||||
opBSWAP(ESI)
|
||||
opBSWAP(EDI)
|
||||
opBSWAP(EBP)
|
||||
opBSWAP(ESP)
|
||||
18
src/cpu_common/x86seg.h
Normal file
18
src/cpu_common/x86seg.h
Normal file
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* x86 CPU segment emulation.
|
||||
*
|
||||
* Version: @(#)x86seg.h 1.0.1 2017/10/12
|
||||
*
|
||||
* Author: Miran Grca, <mgrca8@gmail.com>
|
||||
*
|
||||
* Copyright 2016-2017 Miran Grca.
|
||||
*/
|
||||
|
||||
extern void do_seg_load(x86seg *s, uint16_t *segdat);
|
||||
128
src/cpu_common/x87.c
Normal file
128
src/cpu_common/x87.c
Normal file
@@ -0,0 +1,128 @@
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#define fplog 0
|
||||
#include <math.h>
|
||||
#define HAVE_STDARG_H
|
||||
#include "86box.h"
|
||||
#include "cpu.h"
|
||||
#include "mem.h"
|
||||
#include "pic.h"
|
||||
#include "x86.h"
|
||||
#include "x86_flags.h"
|
||||
#include "x86_ops.h"
|
||||
#include "x87.h"
|
||||
#include "386_common.h"
|
||||
|
||||
|
||||
#ifdef ENABLE_FPU_LOG
|
||||
int fpu_do_log = ENABLE_FPU_LOG;
|
||||
|
||||
|
||||
void
|
||||
fpu_log(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
if (fpu_do_log) {
|
||||
va_start(ap, fmt);
|
||||
pclog_ex(fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define fpu_log(fmt, ...)
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef USE_NEW_DYNAREC
|
||||
#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;
|
||||
int c;
|
||||
|
||||
for (c = 0; c < 8; c++)
|
||||
{
|
||||
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 |= X87_TAG_VALID << (c * 2);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void x87_settag(uint16_t new_tag)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
#else
|
||||
uint16_t x87_gettag()
|
||||
{
|
||||
uint16_t ret = 0;
|
||||
int c;
|
||||
|
||||
for (c = 0; c < 8; c++)
|
||||
{
|
||||
if (cpu_state.tag[c] & TAG_UINT64)
|
||||
ret |= 2 << (c*2);
|
||||
else
|
||||
ret |= (cpu_state.tag[c] << (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;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef ENABLE_808X_LOG
|
||||
void x87_dumpregs()
|
||||
{
|
||||
if (cpu_state.ismmx)
|
||||
{
|
||||
fpu_log("MM0=%016llX\tMM1=%016llX\tMM2=%016llX\tMM3=%016llX\n", cpu_state.MM[0].q, cpu_state.MM[1].q, cpu_state.MM[2].q, cpu_state.MM[3].q);
|
||||
fpu_log("MM4=%016llX\tMM5=%016llX\tMM6=%016llX\tMM7=%016llX\n", cpu_state.MM[4].q, cpu_state.MM[5].q, cpu_state.MM[6].q, cpu_state.MM[7].q);
|
||||
}
|
||||
else
|
||||
{
|
||||
fpu_log("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]);
|
||||
fpu_log("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]);
|
||||
}
|
||||
fpu_log("Status = %04X Control = %04X Tag = %04X\n", cpu_state.npxs, cpu_state.npxc, x87_gettag());
|
||||
}
|
||||
#endif
|
||||
58
src/cpu_common/x87.h
Normal file
58
src/cpu_common/x87.h
Normal file
@@ -0,0 +1,58 @@
|
||||
#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()
|
||||
{
|
||||
#ifdef USE_NEW_DYNAREC
|
||||
cpu_state.TOP = 0;
|
||||
*(uint64_t *)cpu_state.tag = 0x0101010101010101ull;
|
||||
cpu_state.ismmx = 1;
|
||||
#else
|
||||
uint64_t *p;
|
||||
cpu_state.TOP = 0;
|
||||
p = (uint64_t *)cpu_state.tag;
|
||||
*p = 0;
|
||||
cpu_state.ismmx = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void x87_emms()
|
||||
{
|
||||
#ifdef USE_NEW_DYNAREC
|
||||
*(uint64_t *)cpu_state.tag = 0;
|
||||
cpu_state.ismmx = 0;
|
||||
#else
|
||||
uint64_t *p;
|
||||
p = (uint64_t *)cpu_state.tag;
|
||||
*p = 0;
|
||||
cpu_state.ismmx = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
uint16_t x87_gettag();
|
||||
void x87_settag(uint16_t new_tag);
|
||||
|
||||
#ifdef USE_NEW_DYNAREC
|
||||
#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 << 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);
|
||||
#else
|
||||
#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)
|
||||
#endif
|
||||
2136
src/cpu_common/x87_ops.h
Normal file
2136
src/cpu_common/x87_ops.h
Normal file
File diff suppressed because it is too large
Load Diff
435
src/cpu_common/x87_ops_arith.h
Normal file
435
src/cpu_common/x87_ops_arith.h
Normal file
@@ -0,0 +1,435 @@
|
||||
#define opFPU(name, optype, a_size, load_var, get, use_var) \
|
||||
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; \
|
||||
x87_round_set(); \
|
||||
ST(0) += use_var; \
|
||||
x87_round_restore(); \
|
||||
FP_TAG(); \
|
||||
CLOCK_CYCLES(8); \
|
||||
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); \
|
||||
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); \
|
||||
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_round_set(); \
|
||||
x87_div(ST(0), ST(0), use_var); \
|
||||
x87_round_restore(); \
|
||||
FP_TAG(); \
|
||||
CLOCK_CYCLES(73); \
|
||||
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_round_set(); \
|
||||
x87_div(ST(0), use_var, ST(0)); \
|
||||
x87_round_restore(); \
|
||||
FP_TAG(); \
|
||||
CLOCK_CYCLES(73); \
|
||||
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; \
|
||||
x87_round_set(); \
|
||||
ST(0) *= use_var; \
|
||||
x87_round_restore(); \
|
||||
FP_TAG(); \
|
||||
CLOCK_CYCLES(11); \
|
||||
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; \
|
||||
x87_round_set(); \
|
||||
ST(0) -= use_var; \
|
||||
x87_round_restore(); \
|
||||
FP_TAG(); \
|
||||
CLOCK_CYCLES(8); \
|
||||
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; \
|
||||
x87_round_set(); \
|
||||
ST(0) = use_var - ST(0); \
|
||||
x87_round_restore(); \
|
||||
FP_TAG(); \
|
||||
CLOCK_CYCLES(8); \
|
||||
return 0; \
|
||||
}
|
||||
|
||||
|
||||
opFPU(s, x87_ts, 16, t.i, geteal, t.s)
|
||||
#ifndef FPU_8087
|
||||
opFPU(s, x87_ts, 32, t.i, geteal, t.s)
|
||||
#endif
|
||||
opFPU(d, x87_td, 16, t.i, geteaq, t.d)
|
||||
#ifndef FPU_8087
|
||||
opFPU(d, x87_td, 32, t.i, geteaq, t.d)
|
||||
#endif
|
||||
|
||||
opFPU(iw, uint16_t, 16, t, geteaw, (double)(int16_t)t)
|
||||
#ifndef FPU_8087
|
||||
opFPU(iw, uint16_t, 32, t, geteaw, (double)(int16_t)t)
|
||||
#endif
|
||||
opFPU(il, uint32_t, 16, t, geteal, (double)(int32_t)t)
|
||||
#ifndef FPU_8087
|
||||
opFPU(il, uint32_t, 32, t, geteal, (double)(int32_t)t)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
static int opFADD(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
ST(0) = ST(0) + ST(fetchdat & 7);
|
||||
FP_TAG();
|
||||
CLOCK_CYCLES(8);
|
||||
return 0;
|
||||
}
|
||||
static int opFADDr(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
ST(fetchdat & 7) = ST(fetchdat & 7) + ST(0);
|
||||
FP_FTAG();
|
||||
CLOCK_CYCLES(8);
|
||||
return 0;
|
||||
}
|
||||
static int opFADDP(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
ST(fetchdat & 7) = ST(fetchdat & 7) + ST(0);
|
||||
FP_FTAG();
|
||||
x87_pop();
|
||||
CLOCK_CYCLES(8);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opFCOM(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
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);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opFCOMP(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
cpu_state.npxs &= ~(C0|C2|C3);
|
||||
cpu_state.npxs |= x87_compare(ST(0), ST(fetchdat & 7));
|
||||
x87_pop();
|
||||
CLOCK_CYCLES(4);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opFCOMPP(uint32_t fetchdat)
|
||||
{
|
||||
uint64_t *p, *q;
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
cpu_state.npxs &= ~(C0|C2|C3);
|
||||
p = (uint64_t *)&ST(0);
|
||||
q = (uint64_t *)&ST(1);
|
||||
if ((*p == ((uint64_t)1 << 63) && *q == 0) && is386)
|
||||
cpu_state.npxs |= C0; /*Nasty hack to fix 80387 detection*/
|
||||
else
|
||||
cpu_state.npxs |= x87_compare(ST(0), ST(1));
|
||||
|
||||
x87_pop();
|
||||
x87_pop();
|
||||
CLOCK_CYCLES(4);
|
||||
return 0;
|
||||
}
|
||||
#ifndef FPU_8087
|
||||
static int opFUCOMPP(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
cpu_state.npxs &= ~(C0|C2|C3);
|
||||
cpu_state.npxs |= x87_ucompare(ST(0), ST(1));
|
||||
x87_pop();
|
||||
x87_pop();
|
||||
CLOCK_CYCLES(5);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef FP_686
|
||||
static int opFCOMI(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
flags_rebuild();
|
||||
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(4);
|
||||
return 0;
|
||||
}
|
||||
static int opFCOMIP(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
flags_rebuild();
|
||||
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);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static int opFDIV(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
x87_div(ST(0), ST(0), ST(fetchdat & 7));
|
||||
FP_TAG();
|
||||
CLOCK_CYCLES(73);
|
||||
return 0;
|
||||
}
|
||||
static int opFDIVr(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
x87_div(ST(fetchdat & 7), ST(fetchdat & 7), ST(0));
|
||||
FP_FTAG();
|
||||
CLOCK_CYCLES(73);
|
||||
return 0;
|
||||
}
|
||||
static int opFDIVP(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
x87_div(ST(fetchdat & 7), ST(fetchdat & 7), ST(0));
|
||||
FP_FTAG();
|
||||
x87_pop();
|
||||
CLOCK_CYCLES(73);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opFDIVR(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
x87_div(ST(0), ST(fetchdat&7), ST(0));
|
||||
FP_TAG();
|
||||
CLOCK_CYCLES(73);
|
||||
return 0;
|
||||
}
|
||||
static int opFDIVRr(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
x87_div(ST(fetchdat & 7), ST(0), ST(fetchdat & 7));
|
||||
FP_FTAG();
|
||||
CLOCK_CYCLES(73);
|
||||
return 0;
|
||||
}
|
||||
static int opFDIVRP(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
x87_div(ST(fetchdat & 7), ST(0), ST(fetchdat & 7));
|
||||
FP_FTAG();
|
||||
x87_pop();
|
||||
CLOCK_CYCLES(73);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opFMUL(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
ST(0) = ST(0) * ST(fetchdat & 7);
|
||||
FP_TAG();
|
||||
CLOCK_CYCLES(16);
|
||||
return 0;
|
||||
}
|
||||
static int opFMULr(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
ST(fetchdat & 7) = ST(0) * ST(fetchdat & 7);
|
||||
FP_FTAG();
|
||||
CLOCK_CYCLES(16);
|
||||
return 0;
|
||||
}
|
||||
static int opFMULP(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
ST(fetchdat & 7) = ST(0) * ST(fetchdat & 7);
|
||||
FP_FTAG();
|
||||
x87_pop();
|
||||
CLOCK_CYCLES(16);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opFSUB(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
ST(0) = ST(0) - ST(fetchdat & 7);
|
||||
FP_TAG();
|
||||
CLOCK_CYCLES(8);
|
||||
return 0;
|
||||
}
|
||||
static int opFSUBr(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
ST(fetchdat & 7) = ST(fetchdat & 7) - ST(0);
|
||||
FP_FTAG();
|
||||
CLOCK_CYCLES(8);
|
||||
return 0;
|
||||
}
|
||||
static int opFSUBP(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
ST(fetchdat & 7) = ST(fetchdat & 7) - ST(0);
|
||||
FP_FTAG();
|
||||
x87_pop();
|
||||
CLOCK_CYCLES(8);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opFSUBR(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
ST(0) = ST(fetchdat & 7) - ST(0);
|
||||
FP_TAG();
|
||||
CLOCK_CYCLES(8);
|
||||
return 0;
|
||||
}
|
||||
static int opFSUBRr(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
ST(fetchdat & 7) = ST(0) - ST(fetchdat & 7);
|
||||
FP_FTAG();
|
||||
CLOCK_CYCLES(8);
|
||||
return 0;
|
||||
}
|
||||
static int opFSUBRP(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
ST(fetchdat & 7) = ST(0) - ST(fetchdat & 7);
|
||||
FP_FTAG();
|
||||
x87_pop();
|
||||
CLOCK_CYCLES(8);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef FPU_8087
|
||||
static int opFUCOM(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
cpu_state.npxs &= ~(C0|C2|C3);
|
||||
cpu_state.npxs |= x87_ucompare(ST(0), ST(fetchdat & 7));
|
||||
CLOCK_CYCLES(4);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opFUCOMP(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
cpu_state.npxs &= ~(C0|C2|C3);
|
||||
cpu_state.npxs |= x87_ucompare(ST(0), ST(fetchdat & 7));
|
||||
x87_pop();
|
||||
CLOCK_CYCLES(4);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef FP_686
|
||||
static int opFUCOMI(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
flags_rebuild();
|
||||
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(4);
|
||||
return 0;
|
||||
}
|
||||
static int opFUCOMIP(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
flags_rebuild();
|
||||
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);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
492
src/cpu_common/x87_ops_loadstore.h
Normal file
492
src/cpu_common/x87_ops_loadstore.h
Normal file
@@ -0,0 +1,492 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* x87 FPU instructions core.
|
||||
*
|
||||
* Version: @(#)x87_ops_loadstore.h 1.0.2 2019/06/11
|
||||
*
|
||||
* Author: Sarah Walker, <http://pcem-emulator.co.uk/>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Copyright 2008-2019 Sarah Walker.
|
||||
* Copyright 2016-2019 Miran Grca.
|
||||
*/
|
||||
|
||||
static int opFILDiw_a16(uint32_t fetchdat)
|
||||
{
|
||||
int16_t temp;
|
||||
FP_ENTER();
|
||||
fetch_ea_16(fetchdat);
|
||||
SEG_CHECK_READ(cpu_state.ea_seg);
|
||||
temp = geteaw(); if (cpu_state.abrt) return 1;
|
||||
x87_push((double)temp);
|
||||
CLOCK_CYCLES(13);
|
||||
return 0;
|
||||
}
|
||||
#ifndef FPU_8087
|
||||
static int opFILDiw_a32(uint32_t fetchdat)
|
||||
{
|
||||
int16_t temp;
|
||||
FP_ENTER();
|
||||
fetch_ea_32(fetchdat);
|
||||
SEG_CHECK_READ(cpu_state.ea_seg);
|
||||
temp = geteaw(); if (cpu_state.abrt) return 1;
|
||||
x87_push((double)temp);
|
||||
CLOCK_CYCLES(13);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int opFISTiw_a16(uint32_t fetchdat)
|
||||
{
|
||||
int64_t temp64;
|
||||
FP_ENTER();
|
||||
fetch_ea_16(fetchdat);
|
||||
SEG_CHECK_WRITE(cpu_state.ea_seg);
|
||||
temp64 = x87_fround(ST(0));
|
||||
seteaw((int16_t)temp64);
|
||||
CLOCK_CYCLES(29);
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
#ifndef FPU_8087
|
||||
static int opFISTiw_a32(uint32_t fetchdat)
|
||||
{
|
||||
int64_t temp64;
|
||||
FP_ENTER();
|
||||
fetch_ea_32(fetchdat);
|
||||
SEG_CHECK_WRITE(cpu_state.ea_seg);
|
||||
temp64 = x87_fround(ST(0));
|
||||
seteaw((int16_t)temp64);
|
||||
CLOCK_CYCLES(29);
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int opFISTPiw_a16(uint32_t fetchdat)
|
||||
{
|
||||
int64_t temp64;
|
||||
FP_ENTER();
|
||||
fetch_ea_16(fetchdat);
|
||||
SEG_CHECK_WRITE(cpu_state.ea_seg);
|
||||
temp64 = x87_fround(ST(0));
|
||||
seteaw((int16_t)temp64); if (cpu_state.abrt) return 1;
|
||||
x87_pop();
|
||||
CLOCK_CYCLES(29);
|
||||
return 0;
|
||||
}
|
||||
#ifndef FPU_8087
|
||||
static int opFISTPiw_a32(uint32_t fetchdat)
|
||||
{
|
||||
int64_t temp64;
|
||||
FP_ENTER();
|
||||
fetch_ea_32(fetchdat);
|
||||
SEG_CHECK_WRITE(cpu_state.ea_seg);
|
||||
temp64 = x87_fround(ST(0));
|
||||
seteaw((int16_t)temp64); if (cpu_state.abrt) return 1;
|
||||
x87_pop();
|
||||
CLOCK_CYCLES(29);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int opFILDiq_a16(uint32_t fetchdat)
|
||||
{
|
||||
int64_t temp64;
|
||||
FP_ENTER();
|
||||
fetch_ea_16(fetchdat);
|
||||
SEG_CHECK_READ(cpu_state.ea_seg);
|
||||
temp64 = geteaq(); if (cpu_state.abrt) return 1;
|
||||
x87_push((double)temp64);
|
||||
FP_LSQ();
|
||||
FP_LSTAG();
|
||||
|
||||
CLOCK_CYCLES(10);
|
||||
return 0;
|
||||
}
|
||||
#ifndef FPU_8087
|
||||
static int opFILDiq_a32(uint32_t fetchdat)
|
||||
{
|
||||
int64_t temp64;
|
||||
FP_ENTER();
|
||||
fetch_ea_32(fetchdat);
|
||||
SEG_CHECK_READ(cpu_state.ea_seg);
|
||||
temp64 = geteaq(); if (cpu_state.abrt) return 1;
|
||||
x87_push((double)temp64);
|
||||
FP_LSQ();
|
||||
FP_LSTAG();
|
||||
|
||||
CLOCK_CYCLES(10);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int FBSTP_a16(uint32_t fetchdat)
|
||||
{
|
||||
double tempd;
|
||||
int c;
|
||||
FP_ENTER();
|
||||
fetch_ea_16(fetchdat);
|
||||
SEG_CHECK_WRITE(cpu_state.ea_seg);
|
||||
tempd = ST(0);
|
||||
if (tempd < 0.0)
|
||||
tempd = -tempd;
|
||||
for (c = 0; c < 9; c++)
|
||||
{
|
||||
uint8_t tempc = (uint8_t)floor(fmod(tempd, 10.0));
|
||||
tempd -= floor(fmod(tempd, 10.0));
|
||||
tempd /= 10.0;
|
||||
tempc |= ((uint8_t)floor(fmod(tempd, 10.0))) << 4;
|
||||
tempd -= floor(fmod(tempd, 10.0));
|
||||
tempd /= 10.0;
|
||||
writememb(easeg, cpu_state.eaaddr + c, tempc);
|
||||
}
|
||||
tempc = (uint8_t)floor(fmod(tempd, 10.0));
|
||||
if (ST(0) < 0.0) tempc |= 0x80;
|
||||
writememb(easeg, cpu_state.eaaddr + 9, tempc); if (cpu_state.abrt) return 1;
|
||||
x87_pop();
|
||||
return 0;
|
||||
}
|
||||
#ifndef FPU_8087
|
||||
static int FBSTP_a32(uint32_t fetchdat)
|
||||
{
|
||||
double tempd;
|
||||
int c;
|
||||
FP_ENTER();
|
||||
fetch_ea_32(fetchdat);
|
||||
SEG_CHECK_WRITE(cpu_state.ea_seg);
|
||||
tempd = ST(0);
|
||||
if (tempd < 0.0)
|
||||
tempd = -tempd;
|
||||
for (c = 0; c < 9; c++)
|
||||
{
|
||||
uint8_t tempc = (uint8_t)floor(fmod(tempd, 10.0));
|
||||
tempd -= floor(fmod(tempd, 10.0));
|
||||
tempd /= 10.0;
|
||||
tempc |= ((uint8_t)floor(fmod(tempd, 10.0))) << 4;
|
||||
tempd -= floor(fmod(tempd, 10.0));
|
||||
tempd /= 10.0;
|
||||
writememb(easeg, cpu_state.eaaddr + c, tempc);
|
||||
}
|
||||
tempc = (uint8_t)floor(fmod(tempd, 10.0));
|
||||
if (ST(0) < 0.0) tempc |= 0x80;
|
||||
writememb(easeg, cpu_state.eaaddr + 9, tempc); if (cpu_state.abrt) return 1;
|
||||
x87_pop();
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int FISTPiq_a16(uint32_t fetchdat)
|
||||
{
|
||||
int64_t temp64;
|
||||
FP_ENTER();
|
||||
fetch_ea_16(fetchdat);
|
||||
SEG_CHECK_WRITE(cpu_state.ea_seg);
|
||||
if (cpu_state.tag[cpu_state.TOP] & TAG_UINT64)
|
||||
FP_LSRETQ()
|
||||
else
|
||||
temp64 = x87_fround(ST(0));
|
||||
seteaq(temp64); if (cpu_state.abrt) return 1;
|
||||
x87_pop();
|
||||
CLOCK_CYCLES(29);
|
||||
return 0;
|
||||
}
|
||||
#ifndef FPU_8087
|
||||
static int FISTPiq_a32(uint32_t fetchdat)
|
||||
{
|
||||
int64_t temp64;
|
||||
FP_ENTER();
|
||||
fetch_ea_32(fetchdat);
|
||||
SEG_CHECK_WRITE(cpu_state.ea_seg);
|
||||
if (cpu_state.tag[cpu_state.TOP] & TAG_UINT64)
|
||||
FP_LSRETQ()
|
||||
else
|
||||
temp64 = x87_fround(ST(0));
|
||||
seteaq(temp64); if (cpu_state.abrt) return 1;
|
||||
x87_pop();
|
||||
CLOCK_CYCLES(29);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int opFILDil_a16(uint32_t fetchdat)
|
||||
{
|
||||
int32_t templ;
|
||||
FP_ENTER();
|
||||
fetch_ea_16(fetchdat);
|
||||
SEG_CHECK_READ(cpu_state.ea_seg);
|
||||
templ = geteal(); if (cpu_state.abrt) return 1;
|
||||
x87_push((double)templ);
|
||||
CLOCK_CYCLES(9);
|
||||
return 0;
|
||||
}
|
||||
#ifndef FPU_8087
|
||||
static int opFILDil_a32(uint32_t fetchdat)
|
||||
{
|
||||
int32_t templ;
|
||||
FP_ENTER();
|
||||
fetch_ea_32(fetchdat);
|
||||
SEG_CHECK_READ(cpu_state.ea_seg);
|
||||
templ = geteal(); if (cpu_state.abrt) return 1;
|
||||
x87_push((double)templ);
|
||||
CLOCK_CYCLES(9);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int opFISTil_a16(uint32_t fetchdat)
|
||||
{
|
||||
int64_t temp64;
|
||||
FP_ENTER();
|
||||
fetch_ea_16(fetchdat);
|
||||
SEG_CHECK_WRITE(cpu_state.ea_seg);
|
||||
temp64 = x87_fround(ST(0));
|
||||
seteal((int32_t)temp64);
|
||||
CLOCK_CYCLES(28);
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
#ifndef FPU_8087
|
||||
static int opFISTil_a32(uint32_t fetchdat)
|
||||
{
|
||||
int64_t temp64;
|
||||
FP_ENTER();
|
||||
fetch_ea_32(fetchdat);
|
||||
SEG_CHECK_WRITE(cpu_state.ea_seg);
|
||||
temp64 = x87_fround(ST(0));
|
||||
seteal((int32_t)temp64);
|
||||
CLOCK_CYCLES(28);
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int opFISTPil_a16(uint32_t fetchdat)
|
||||
{
|
||||
int64_t temp64;
|
||||
FP_ENTER();
|
||||
fetch_ea_16(fetchdat);
|
||||
SEG_CHECK_WRITE(cpu_state.ea_seg);
|
||||
temp64 = x87_fround(ST(0));
|
||||
seteal((int32_t)temp64); if (cpu_state.abrt) return 1;
|
||||
x87_pop();
|
||||
CLOCK_CYCLES(28);
|
||||
return 0;
|
||||
}
|
||||
#ifndef FPU_8087
|
||||
static int opFISTPil_a32(uint32_t fetchdat)
|
||||
{
|
||||
int64_t temp64;
|
||||
FP_ENTER();
|
||||
fetch_ea_32(fetchdat);
|
||||
SEG_CHECK_WRITE(cpu_state.ea_seg);
|
||||
temp64 = x87_fround(ST(0));
|
||||
seteal((int32_t)temp64); if (cpu_state.abrt) return 1;
|
||||
x87_pop();
|
||||
CLOCK_CYCLES(28);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int opFLDe_a16(uint32_t fetchdat)
|
||||
{
|
||||
double t;
|
||||
FP_ENTER();
|
||||
fetch_ea_16(fetchdat);
|
||||
SEG_CHECK_READ(cpu_state.ea_seg);
|
||||
t=x87_ld80(); if (cpu_state.abrt) return 1;
|
||||
x87_push(t);
|
||||
CLOCK_CYCLES(6);
|
||||
return 0;
|
||||
}
|
||||
#ifndef FPU_8087
|
||||
static int opFLDe_a32(uint32_t fetchdat)
|
||||
{
|
||||
double t;
|
||||
FP_ENTER();
|
||||
fetch_ea_32(fetchdat);
|
||||
SEG_CHECK_READ(cpu_state.ea_seg);
|
||||
t=x87_ld80(); if (cpu_state.abrt) return 1;
|
||||
x87_push(t);
|
||||
CLOCK_CYCLES(6);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int opFSTPe_a16(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
fetch_ea_16(fetchdat);
|
||||
SEG_CHECK_WRITE(cpu_state.ea_seg);
|
||||
x87_st80(ST(0)); if (cpu_state.abrt) return 1;
|
||||
x87_pop();
|
||||
CLOCK_CYCLES(6);
|
||||
return 0;
|
||||
}
|
||||
#ifndef FPU_8087
|
||||
static int opFSTPe_a32(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
fetch_ea_32(fetchdat);
|
||||
SEG_CHECK_WRITE(cpu_state.ea_seg);
|
||||
x87_st80(ST(0)); if (cpu_state.abrt) return 1;
|
||||
x87_pop();
|
||||
CLOCK_CYCLES(6);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int opFLDd_a16(uint32_t fetchdat)
|
||||
{
|
||||
x87_td t;
|
||||
FP_ENTER();
|
||||
fetch_ea_16(fetchdat);
|
||||
SEG_CHECK_READ(cpu_state.ea_seg);
|
||||
t.i = geteaq(); if (cpu_state.abrt) return 1;
|
||||
x87_push(t.d);
|
||||
CLOCK_CYCLES(3);
|
||||
return 0;
|
||||
}
|
||||
#ifndef FPU_8087
|
||||
static int opFLDd_a32(uint32_t fetchdat)
|
||||
{
|
||||
x87_td t;
|
||||
FP_ENTER();
|
||||
fetch_ea_32(fetchdat);
|
||||
SEG_CHECK_READ(cpu_state.ea_seg);
|
||||
t.i = geteaq(); if (cpu_state.abrt) return 1;
|
||||
x87_push(t.d);
|
||||
CLOCK_CYCLES(3);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int opFSTd_a16(uint32_t fetchdat)
|
||||
{
|
||||
x87_td t;
|
||||
FP_ENTER();
|
||||
fetch_ea_16(fetchdat);
|
||||
SEG_CHECK_WRITE(cpu_state.ea_seg);
|
||||
t.d = ST(0);
|
||||
seteaq(t.i);
|
||||
CLOCK_CYCLES(8);
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
#ifndef FPU_8087
|
||||
static int opFSTd_a32(uint32_t fetchdat)
|
||||
{
|
||||
x87_td t;
|
||||
FP_ENTER();
|
||||
fetch_ea_32(fetchdat);
|
||||
SEG_CHECK_WRITE(cpu_state.ea_seg);
|
||||
t.d = ST(0);
|
||||
seteaq(t.i);
|
||||
CLOCK_CYCLES(8);
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int opFSTPd_a16(uint32_t fetchdat)
|
||||
{
|
||||
x87_td t;
|
||||
FP_ENTER();
|
||||
fetch_ea_16(fetchdat);
|
||||
SEG_CHECK_WRITE(cpu_state.ea_seg);
|
||||
t.d = ST(0);
|
||||
seteaq(t.i); if (cpu_state.abrt) return 1;
|
||||
x87_pop();
|
||||
CLOCK_CYCLES(8);
|
||||
return 0;
|
||||
}
|
||||
#ifndef FPU_8087
|
||||
static int opFSTPd_a32(uint32_t fetchdat)
|
||||
{
|
||||
x87_td t;
|
||||
FP_ENTER();
|
||||
fetch_ea_32(fetchdat);
|
||||
SEG_CHECK_WRITE(cpu_state.ea_seg);
|
||||
t.d = ST(0);
|
||||
seteaq(t.i); if (cpu_state.abrt) return 1;
|
||||
x87_pop();
|
||||
CLOCK_CYCLES(8);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int opFLDs_a16(uint32_t fetchdat)
|
||||
{
|
||||
x87_ts ts;
|
||||
FP_ENTER();
|
||||
fetch_ea_16(fetchdat);
|
||||
SEG_CHECK_READ(cpu_state.ea_seg);
|
||||
ts.i = geteal(); if (cpu_state.abrt) return 1;
|
||||
x87_push((double)ts.s);
|
||||
CLOCK_CYCLES(3);
|
||||
return 0;
|
||||
}
|
||||
#ifndef FPU_8087
|
||||
static int opFLDs_a32(uint32_t fetchdat)
|
||||
{
|
||||
x87_ts ts;
|
||||
FP_ENTER();
|
||||
fetch_ea_32(fetchdat);
|
||||
SEG_CHECK_READ(cpu_state.ea_seg);
|
||||
ts.i = geteal(); if (cpu_state.abrt) return 1;
|
||||
x87_push((double)ts.s);
|
||||
CLOCK_CYCLES(3);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int opFSTs_a16(uint32_t fetchdat)
|
||||
{
|
||||
x87_ts ts;
|
||||
FP_ENTER();
|
||||
fetch_ea_16(fetchdat);
|
||||
SEG_CHECK_WRITE(cpu_state.ea_seg);
|
||||
ts.s = (float)ST(0);
|
||||
seteal(ts.i);
|
||||
CLOCK_CYCLES(7);
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
#ifndef FPU_8087
|
||||
static int opFSTs_a32(uint32_t fetchdat)
|
||||
{
|
||||
x87_ts ts;
|
||||
FP_ENTER();
|
||||
fetch_ea_32(fetchdat);
|
||||
SEG_CHECK_WRITE(cpu_state.ea_seg);
|
||||
ts.s = (float)ST(0);
|
||||
seteal(ts.i);
|
||||
CLOCK_CYCLES(7);
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int opFSTPs_a16(uint32_t fetchdat)
|
||||
{
|
||||
x87_ts ts;
|
||||
FP_ENTER();
|
||||
fetch_ea_16(fetchdat);
|
||||
SEG_CHECK_WRITE(cpu_state.ea_seg);
|
||||
ts.s = (float)ST(0);
|
||||
seteal(ts.i); if (cpu_state.abrt) return 1;
|
||||
x87_pop();
|
||||
CLOCK_CYCLES(7);
|
||||
return 0;
|
||||
}
|
||||
#ifndef FPU_8087
|
||||
static int opFSTPs_a32(uint32_t fetchdat)
|
||||
{
|
||||
x87_ts ts;
|
||||
FP_ENTER();
|
||||
fetch_ea_32(fetchdat);
|
||||
SEG_CHECK_WRITE(cpu_state.ea_seg);
|
||||
ts.s = (float)ST(0);
|
||||
seteal(ts.i); if (cpu_state.abrt) return 1;
|
||||
x87_pop();
|
||||
CLOCK_CYCLES(7);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
877
src/cpu_common/x87_ops_misc.h
Normal file
877
src/cpu_common/x87_ops_misc.h
Normal file
@@ -0,0 +1,877 @@
|
||||
#ifdef FPU_8087
|
||||
static int opFI(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
cpu_state.npxc &= ~0x80;
|
||||
if (rmdat == 0xe1)
|
||||
cpu_state.npxc |= 0x80;
|
||||
wait(3, 0);
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static int opFSTSW_AX(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
AX = cpu_state.npxs;
|
||||
CLOCK_CYCLES(3);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static int opFNOP(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
CLOCK_CYCLES(4);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opFCLEX(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
cpu_state.npxs &= 0xff00;
|
||||
CLOCK_CYCLES(4);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opFINIT(uint32_t fetchdat)
|
||||
{
|
||||
uint64_t *p;
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
#ifdef FPU_8087
|
||||
cpu_state.npxc = 0x3FF;
|
||||
#else
|
||||
cpu_state.npxc = 0x37F;
|
||||
#endif
|
||||
FP_RNPXC();
|
||||
cpu_state.npxs = 0;
|
||||
p = (uint64_t *)cpu_state.tag;
|
||||
*p = FP_DTAG;
|
||||
cpu_state.TOP = 0;
|
||||
cpu_state.ismmx = 0;
|
||||
CLOCK_CYCLES(17);
|
||||
CPU_BLOCK_END();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int opFFREE(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = FP_EMPTY;
|
||||
CLOCK_CYCLES(3);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opFFREEP(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = FP_EMPTY; if (cpu_state.abrt) return 1;
|
||||
x87_pop();
|
||||
CLOCK_CYCLES(3);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opFST(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
ST(fetchdat & 7) = ST(0);
|
||||
cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = cpu_state.tag[cpu_state.TOP & 7];
|
||||
CLOCK_CYCLES(3);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opFSTP(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
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);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static int FSTOR()
|
||||
{
|
||||
uint64_t *p;
|
||||
FP_ENTER();
|
||||
switch ((cr0 & 1) | (cpu_state.op32 & 0x100))
|
||||
{
|
||||
case 0x000: /*16-bit real mode*/
|
||||
case 0x001: /*16-bit protected mode*/
|
||||
cpu_state.npxc = readmemw(easeg, cpu_state.eaaddr);
|
||||
FP_NNPXC();
|
||||
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;
|
||||
cpu_state.eaaddr += 14;
|
||||
break;
|
||||
case 0x100: /*32-bit real mode*/
|
||||
case 0x101: /*32-bit protected mode*/
|
||||
cpu_state.npxc = readmemw(easeg, cpu_state.eaaddr);
|
||||
FP_NNPXC();
|
||||
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;
|
||||
cpu_state.eaaddr += 28;
|
||||
break;
|
||||
}
|
||||
x87_ld_frstor(0); cpu_state.eaaddr += 10;
|
||||
x87_ld_frstor(1); cpu_state.eaaddr += 10;
|
||||
x87_ld_frstor(2); cpu_state.eaaddr += 10;
|
||||
x87_ld_frstor(3); cpu_state.eaaddr += 10;
|
||||
x87_ld_frstor(4); cpu_state.eaaddr += 10;
|
||||
x87_ld_frstor(5); cpu_state.eaaddr += 10;
|
||||
x87_ld_frstor(6); cpu_state.eaaddr += 10;
|
||||
x87_ld_frstor(7);
|
||||
|
||||
cpu_state.ismmx = 0;
|
||||
/*Horrible hack, but as PCem doesn't keep the FPU stack in 80-bit precision at all times
|
||||
something like this is needed*/
|
||||
p = (uint64_t *)cpu_state.tag;
|
||||
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 && (*p == FP_CTAG))
|
||||
cpu_state.ismmx = 1;
|
||||
|
||||
CLOCK_CYCLES((cr0 & 1) ? 34 : 44);
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
static int opFSTOR_a16(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
fetch_ea_16(fetchdat);
|
||||
SEG_CHECK_READ(cpu_state.ea_seg);
|
||||
FSTOR();
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
#ifndef FPU_8087
|
||||
static int opFSTOR_a32(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
fetch_ea_32(fetchdat);
|
||||
SEG_CHECK_READ(cpu_state.ea_seg);
|
||||
FSTOR();
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int FSAVE()
|
||||
{
|
||||
uint64_t *p;
|
||||
|
||||
FP_ENTER();
|
||||
cpu_state.npxs = (cpu_state.npxs & ~(7 << 11)) | (FP_TOP(cpu_state.TOP) << 11);
|
||||
|
||||
switch ((cr0 & 1) | (cpu_state.op32 & 0x100))
|
||||
{
|
||||
case 0x000: /*16-bit real mode*/
|
||||
writememw(easeg,cpu_state.eaaddr,cpu_state.npxc);
|
||||
writememw(easeg,cpu_state.eaaddr+2,cpu_state.npxs);
|
||||
writememw(easeg,cpu_state.eaaddr+4,x87_gettag());
|
||||
writememw(easeg,cpu_state.eaaddr+6,x87_pc_off);
|
||||
writememw(easeg,cpu_state.eaaddr+10,x87_op_off);
|
||||
cpu_state.eaaddr+=14;
|
||||
if (cpu_state.ismmx)
|
||||
{
|
||||
x87_stmmx(cpu_state.MM[0]); cpu_state.eaaddr+=10;
|
||||
x87_stmmx(cpu_state.MM[1]); cpu_state.eaaddr+=10;
|
||||
x87_stmmx(cpu_state.MM[2]); cpu_state.eaaddr+=10;
|
||||
x87_stmmx(cpu_state.MM[3]); cpu_state.eaaddr+=10;
|
||||
x87_stmmx(cpu_state.MM[4]); cpu_state.eaaddr+=10;
|
||||
x87_stmmx(cpu_state.MM[5]); cpu_state.eaaddr+=10;
|
||||
x87_stmmx(cpu_state.MM[6]); cpu_state.eaaddr+=10;
|
||||
x87_stmmx(cpu_state.MM[7]);
|
||||
}
|
||||
else
|
||||
{
|
||||
x87_st_fsave(0); cpu_state.eaaddr+=10;
|
||||
x87_st_fsave(1); cpu_state.eaaddr+=10;
|
||||
x87_st_fsave(2); cpu_state.eaaddr+=10;
|
||||
x87_st_fsave(3); cpu_state.eaaddr+=10;
|
||||
x87_st_fsave(4); cpu_state.eaaddr+=10;
|
||||
x87_st_fsave(5); cpu_state.eaaddr+=10;
|
||||
x87_st_fsave(6); cpu_state.eaaddr+=10;
|
||||
x87_st_fsave(7);
|
||||
}
|
||||
break;
|
||||
case 0x001: /*16-bit protected mode*/
|
||||
writememw(easeg,cpu_state.eaaddr,cpu_state.npxc);
|
||||
writememw(easeg,cpu_state.eaaddr+2,cpu_state.npxs);
|
||||
writememw(easeg,cpu_state.eaaddr+4,x87_gettag());
|
||||
writememw(easeg,cpu_state.eaaddr+6,x87_pc_off);
|
||||
writememw(easeg,cpu_state.eaaddr+8,x87_pc_seg);
|
||||
writememw(easeg,cpu_state.eaaddr+10,x87_op_off);
|
||||
writememw(easeg,cpu_state.eaaddr+12,x87_op_seg);
|
||||
cpu_state.eaaddr+=14;
|
||||
if (cpu_state.ismmx)
|
||||
{
|
||||
x87_stmmx(cpu_state.MM[0]); cpu_state.eaaddr+=10;
|
||||
x87_stmmx(cpu_state.MM[1]); cpu_state.eaaddr+=10;
|
||||
x87_stmmx(cpu_state.MM[2]); cpu_state.eaaddr+=10;
|
||||
x87_stmmx(cpu_state.MM[3]); cpu_state.eaaddr+=10;
|
||||
x87_stmmx(cpu_state.MM[4]); cpu_state.eaaddr+=10;
|
||||
x87_stmmx(cpu_state.MM[5]); cpu_state.eaaddr+=10;
|
||||
x87_stmmx(cpu_state.MM[6]); cpu_state.eaaddr+=10;
|
||||
x87_stmmx(cpu_state.MM[7]);
|
||||
}
|
||||
else
|
||||
{
|
||||
x87_st_fsave(0); cpu_state.eaaddr+=10;
|
||||
x87_st_fsave(1); cpu_state.eaaddr+=10;
|
||||
x87_st_fsave(2); cpu_state.eaaddr+=10;
|
||||
x87_st_fsave(3); cpu_state.eaaddr+=10;
|
||||
x87_st_fsave(4); cpu_state.eaaddr+=10;
|
||||
x87_st_fsave(5); cpu_state.eaaddr+=10;
|
||||
x87_st_fsave(6); cpu_state.eaaddr+=10;
|
||||
x87_st_fsave(7);
|
||||
}
|
||||
break;
|
||||
case 0x100: /*32-bit real mode*/
|
||||
writememw(easeg,cpu_state.eaaddr,cpu_state.npxc);
|
||||
writememw(easeg,cpu_state.eaaddr+4,cpu_state.npxs);
|
||||
writememw(easeg,cpu_state.eaaddr+8,x87_gettag());
|
||||
writememw(easeg,cpu_state.eaaddr+12,x87_pc_off);
|
||||
writememw(easeg,cpu_state.eaaddr+20,x87_op_off);
|
||||
writememl(easeg,cpu_state.eaaddr+24,(x87_op_off>>16)<<12);
|
||||
cpu_state.eaaddr+=28;
|
||||
if (cpu_state.ismmx)
|
||||
{
|
||||
x87_stmmx(cpu_state.MM[0]); cpu_state.eaaddr+=10;
|
||||
x87_stmmx(cpu_state.MM[1]); cpu_state.eaaddr+=10;
|
||||
x87_stmmx(cpu_state.MM[2]); cpu_state.eaaddr+=10;
|
||||
x87_stmmx(cpu_state.MM[3]); cpu_state.eaaddr+=10;
|
||||
x87_stmmx(cpu_state.MM[4]); cpu_state.eaaddr+=10;
|
||||
x87_stmmx(cpu_state.MM[5]); cpu_state.eaaddr+=10;
|
||||
x87_stmmx(cpu_state.MM[6]); cpu_state.eaaddr+=10;
|
||||
x87_stmmx(cpu_state.MM[7]);
|
||||
}
|
||||
else
|
||||
{
|
||||
x87_st_fsave(0); cpu_state.eaaddr+=10;
|
||||
x87_st_fsave(1); cpu_state.eaaddr+=10;
|
||||
x87_st_fsave(2); cpu_state.eaaddr+=10;
|
||||
x87_st_fsave(3); cpu_state.eaaddr+=10;
|
||||
x87_st_fsave(4); cpu_state.eaaddr+=10;
|
||||
x87_st_fsave(5); cpu_state.eaaddr+=10;
|
||||
x87_st_fsave(6); cpu_state.eaaddr+=10;
|
||||
x87_st_fsave(7);
|
||||
}
|
||||
break;
|
||||
case 0x101: /*32-bit protected mode*/
|
||||
writememw(easeg,cpu_state.eaaddr,cpu_state.npxc);
|
||||
writememw(easeg,cpu_state.eaaddr+4,cpu_state.npxs);
|
||||
writememw(easeg,cpu_state.eaaddr+8,x87_gettag());
|
||||
writememl(easeg,cpu_state.eaaddr+12,x87_pc_off);
|
||||
writememl(easeg,cpu_state.eaaddr+16,x87_pc_seg);
|
||||
writememl(easeg,cpu_state.eaaddr+20,x87_op_off);
|
||||
writememl(easeg,cpu_state.eaaddr+24,x87_op_seg);
|
||||
cpu_state.eaaddr+=28;
|
||||
if (cpu_state.ismmx)
|
||||
{
|
||||
x87_stmmx(cpu_state.MM[0]); cpu_state.eaaddr+=10;
|
||||
x87_stmmx(cpu_state.MM[1]); cpu_state.eaaddr+=10;
|
||||
x87_stmmx(cpu_state.MM[2]); cpu_state.eaaddr+=10;
|
||||
x87_stmmx(cpu_state.MM[3]); cpu_state.eaaddr+=10;
|
||||
x87_stmmx(cpu_state.MM[4]); cpu_state.eaaddr+=10;
|
||||
x87_stmmx(cpu_state.MM[5]); cpu_state.eaaddr+=10;
|
||||
x87_stmmx(cpu_state.MM[6]); cpu_state.eaaddr+=10;
|
||||
x87_stmmx(cpu_state.MM[7]);
|
||||
}
|
||||
else
|
||||
{
|
||||
x87_st_fsave(0); cpu_state.eaaddr+=10;
|
||||
x87_st_fsave(1); cpu_state.eaaddr+=10;
|
||||
x87_st_fsave(2); cpu_state.eaaddr+=10;
|
||||
x87_st_fsave(3); cpu_state.eaaddr+=10;
|
||||
x87_st_fsave(4); cpu_state.eaaddr+=10;
|
||||
x87_st_fsave(5); cpu_state.eaaddr+=10;
|
||||
x87_st_fsave(6); cpu_state.eaaddr+=10;
|
||||
x87_st_fsave(7);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
cpu_state.npxc = 0x37F;
|
||||
FP_RNPXC();
|
||||
cpu_state.npxs = 0;
|
||||
p = (uint64_t *)cpu_state.tag;
|
||||
*p = FP_DTAG;
|
||||
cpu_state.TOP = 0;
|
||||
cpu_state.ismmx = 0;
|
||||
|
||||
CLOCK_CYCLES((cr0 & 1) ? 56 : 67);
|
||||
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;
|
||||
}
|
||||
#ifndef FPU_8087
|
||||
static int opFSAVE_a32(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
fetch_ea_32(fetchdat);
|
||||
SEG_CHECK_WRITE(cpu_state.ea_seg);
|
||||
FSAVE();
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int opFSTSW_a16(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
fetch_ea_16(fetchdat);
|
||||
SEG_CHECK_WRITE(cpu_state.ea_seg);
|
||||
seteaw((cpu_state.npxs & 0xC7FF) | (FP_TOP(cpu_state.TOP) << 11));
|
||||
CLOCK_CYCLES(3);
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
#ifndef FPU_8087
|
||||
static int opFSTSW_a32(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
fetch_ea_32(fetchdat);
|
||||
SEG_CHECK_WRITE(cpu_state.ea_seg);
|
||||
seteaw((cpu_state.npxs & 0xC7FF) | (FP_TOP(cpu_state.TOP) << 11));
|
||||
CLOCK_CYCLES(3);
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static int opFLD(uint32_t fetchdat)
|
||||
{
|
||||
int old_tag;
|
||||
uint64_t old_i64;
|
||||
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
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[FP_TOP(cpu_state.TOP)] = old_tag;
|
||||
cpu_state.MM[FP_TOP(cpu_state.TOP)].q = old_i64;
|
||||
CLOCK_CYCLES(4);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opFXCH(uint32_t fetchdat)
|
||||
{
|
||||
double td;
|
||||
uint8_t old_tag;
|
||||
uint64_t old_i64;
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
td = ST(0);
|
||||
ST(0) = ST(fetchdat&7);
|
||||
ST(fetchdat&7) = td;
|
||||
old_tag = cpu_state.tag[FP_TOP(cpu_state.TOP)];
|
||||
cpu_state.tag[FP_TOP(cpu_state.TOP)] = cpu_state.tag[(cpu_state.TOP + fetchdat) & 7];
|
||||
cpu_state.tag[(cpu_state.TOP + fetchdat) & 7] = old_tag;
|
||||
old_i64 = cpu_state.MM[FP_TOP(cpu_state.TOP)].q;
|
||||
cpu_state.MM[FP_TOP(cpu_state.TOP)].q = cpu_state.MM[(cpu_state.TOP + fetchdat) & 7].q;
|
||||
cpu_state.MM[(cpu_state.TOP + fetchdat) & 7].q = old_i64;
|
||||
|
||||
CLOCK_CYCLES(4);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opFCHS(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
ST(0) = -ST(0);
|
||||
FP_TAG();
|
||||
CLOCK_CYCLES(6);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opFABS(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
ST(0) = fabs(ST(0));
|
||||
FP_TAG();
|
||||
CLOCK_CYCLES(3);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opFTST(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
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);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opFXAM(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
cpu_state.npxs &= ~(C0|C1|C2|C3);
|
||||
if (cpu_state.tag[cpu_state.TOP&7] == FP_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);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opFLD1(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
x87_push(1.0);
|
||||
CLOCK_CYCLES(4);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opFLDL2T(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
x87_push(3.3219280948873623);
|
||||
CLOCK_CYCLES(8);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opFLDL2E(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
x87_push(1.4426950408889634);
|
||||
CLOCK_CYCLES(8);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opFLDPI(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
x87_push(3.141592653589793);
|
||||
CLOCK_CYCLES(8);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opFLDEG2(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
x87_push(0.3010299956639812);
|
||||
CLOCK_CYCLES(8);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opFLDLN2(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
x87_push_u64(0x3fe62e42fefa39f0ull);
|
||||
CLOCK_CYCLES(8);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opFLDZ(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
x87_push(0.0);
|
||||
FP_ZTAG();
|
||||
CLOCK_CYCLES(4);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opF2XM1(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
ST(0) = pow(2.0, ST(0)) - 1.0;
|
||||
FP_TAG();
|
||||
CLOCK_CYCLES(200);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opFYL2X(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
ST(1) = ST(1) * (log(ST(0)) / log(2.0));
|
||||
FP_NTAG();
|
||||
x87_pop();
|
||||
CLOCK_CYCLES(250);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opFYL2XP1(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
ST(1) = ST(1) * (log(ST(0)+1.0) / log(2.0));
|
||||
FP_NTAG();
|
||||
x87_pop();
|
||||
CLOCK_CYCLES(250);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opFPTAN(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
ST(0) = tan(ST(0));
|
||||
FP_TAG();
|
||||
x87_push(1.0);
|
||||
cpu_state.npxs &= ~C2;
|
||||
CLOCK_CYCLES(235);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opFPATAN(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
ST(1) = atan2(ST(1), ST(0));
|
||||
FP_NTAG();
|
||||
x87_pop();
|
||||
CLOCK_CYCLES(250);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opFDECSTP(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
FP_DECTOP();
|
||||
CLOCK_CYCLES(4);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opFINCSTP(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
FP_INCTOP();
|
||||
CLOCK_CYCLES(4);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opFPREM(uint32_t fetchdat)
|
||||
{
|
||||
int64_t temp64;
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
temp64 = (int64_t)(ST(0) / ST(1));
|
||||
ST(0) = ST(0) - (ST(1) * (double)temp64);
|
||||
FP_TAG();
|
||||
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);
|
||||
return 0;
|
||||
}
|
||||
#ifndef FPU_8087
|
||||
static int opFPREM1(uint32_t fetchdat)
|
||||
{
|
||||
int64_t temp64;
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
temp64 = (int64_t)(ST(0) / ST(1));
|
||||
ST(0) = ST(0) - (ST(1) * (double)temp64);
|
||||
FP_TAG();
|
||||
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);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int opFSQRT(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
ST(0) = sqrt(ST(0));
|
||||
FP_TAG();
|
||||
CLOCK_CYCLES(83);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef FPU_8087
|
||||
static int opFSINCOS(uint32_t fetchdat)
|
||||
{
|
||||
double td;
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
td = ST(0);
|
||||
ST(0) = sin(td);
|
||||
FP_TAG();
|
||||
x87_push(cos(td));
|
||||
cpu_state.npxs &= ~C2;
|
||||
CLOCK_CYCLES(330);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int opFRNDINT(uint32_t fetchdat)
|
||||
{
|
||||
double rounded;
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
rounded = (double) x87_fround(ST(0));
|
||||
#ifndef PCEM_CODE
|
||||
if (rounded > ST(0))
|
||||
cpu_state.npxs |= C1;
|
||||
else
|
||||
cpu_state.npxs &= ~C1;
|
||||
#endif
|
||||
ST(0) = rounded;
|
||||
FP_TAG();
|
||||
CLOCK_CYCLES(21);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opFSCALE(uint32_t fetchdat)
|
||||
{
|
||||
int64_t temp64;
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
temp64 = (int64_t)ST(1);
|
||||
ST(0) = ST(0) * pow(2.0, (double)temp64);
|
||||
FP_TAG();
|
||||
CLOCK_CYCLES(30);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef FPU_8087
|
||||
static int opFSIN(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
ST(0) = sin(ST(0));
|
||||
FP_TAG();
|
||||
cpu_state.npxs &= ~C2;
|
||||
CLOCK_CYCLES(300);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int opFCOS(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
cpu_state.pc++;
|
||||
ST(0) = cos(ST(0));
|
||||
FP_TAG();
|
||||
cpu_state.npxs &= ~C2;
|
||||
CLOCK_CYCLES(300);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static int FLDENV()
|
||||
{
|
||||
FP_ENTER();
|
||||
switch ((cr0 & 1) | (cpu_state.op32 & 0x100))
|
||||
{
|
||||
case 0x000: /*16-bit real mode*/
|
||||
case 0x001: /*16-bit protected mode*/
|
||||
cpu_state.npxc = readmemw(easeg, cpu_state.eaaddr);
|
||||
FP_NNPXC();
|
||||
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;
|
||||
break;
|
||||
case 0x100: /*32-bit real mode*/
|
||||
case 0x101: /*32-bit protected mode*/
|
||||
cpu_state.npxc = readmemw(easeg, cpu_state.eaaddr);
|
||||
FP_NNPXC();
|
||||
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);
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
|
||||
static int opFLDENV_a16(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
fetch_ea_16(fetchdat);
|
||||
SEG_CHECK_READ(cpu_state.ea_seg);
|
||||
FLDENV();
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
#ifndef FPU_8087
|
||||
static int opFLDENV_a32(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
fetch_ea_32(fetchdat);
|
||||
SEG_CHECK_READ(cpu_state.ea_seg);
|
||||
FLDENV();
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int opFLDCW_a16(uint32_t fetchdat)
|
||||
{
|
||||
uint16_t tempw;
|
||||
FP_ENTER();
|
||||
fetch_ea_16(fetchdat);
|
||||
SEG_CHECK_READ(cpu_state.ea_seg);
|
||||
tempw = geteaw();
|
||||
if (cpu_state.abrt) return 1;
|
||||
cpu_state.npxc = tempw;
|
||||
FP_NNPXC();
|
||||
CLOCK_CYCLES(4);
|
||||
return 0;
|
||||
}
|
||||
#ifndef FPU_8087
|
||||
static int opFLDCW_a32(uint32_t fetchdat)
|
||||
{
|
||||
uint16_t tempw;
|
||||
FP_ENTER();
|
||||
fetch_ea_32(fetchdat);
|
||||
SEG_CHECK_READ(cpu_state.ea_seg);
|
||||
tempw = geteaw();
|
||||
if (cpu_state.abrt) return 1;
|
||||
cpu_state.npxc = tempw;
|
||||
FP_NNPXC();
|
||||
CLOCK_CYCLES(4);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int FSTENV()
|
||||
{
|
||||
FP_ENTER();
|
||||
switch ((cr0 & 1) | (cpu_state.op32 & 0x100))
|
||||
{
|
||||
case 0x000: /*16-bit real mode*/
|
||||
writememw(easeg,cpu_state.eaaddr,cpu_state.npxc);
|
||||
writememw(easeg,cpu_state.eaaddr+2,cpu_state.npxs);
|
||||
writememw(easeg,cpu_state.eaaddr+4,x87_gettag());
|
||||
writememw(easeg,cpu_state.eaaddr+6,x87_pc_off);
|
||||
writememw(easeg,cpu_state.eaaddr+10,x87_op_off);
|
||||
break;
|
||||
case 0x001: /*16-bit protected mode*/
|
||||
writememw(easeg,cpu_state.eaaddr,cpu_state.npxc);
|
||||
writememw(easeg,cpu_state.eaaddr+2,cpu_state.npxs);
|
||||
writememw(easeg,cpu_state.eaaddr+4,x87_gettag());
|
||||
writememw(easeg,cpu_state.eaaddr+6,x87_pc_off);
|
||||
writememw(easeg,cpu_state.eaaddr+8,x87_pc_seg);
|
||||
writememw(easeg,cpu_state.eaaddr+10,x87_op_off);
|
||||
writememw(easeg,cpu_state.eaaddr+12,x87_op_seg);
|
||||
break;
|
||||
case 0x100: /*32-bit real mode*/
|
||||
writememw(easeg,cpu_state.eaaddr,cpu_state.npxc);
|
||||
writememw(easeg,cpu_state.eaaddr+4,cpu_state.npxs);
|
||||
writememw(easeg,cpu_state.eaaddr+8,x87_gettag());
|
||||
writememw(easeg,cpu_state.eaaddr+12,x87_pc_off);
|
||||
writememw(easeg,cpu_state.eaaddr+20,x87_op_off);
|
||||
writememl(easeg,cpu_state.eaaddr+24,(x87_op_off>>16)<<12);
|
||||
break;
|
||||
case 0x101: /*32-bit protected mode*/
|
||||
writememw(easeg,cpu_state.eaaddr,cpu_state.npxc);
|
||||
writememw(easeg,cpu_state.eaaddr+4,cpu_state.npxs);
|
||||
writememw(easeg,cpu_state.eaaddr+8,x87_gettag());
|
||||
writememl(easeg,cpu_state.eaaddr+12,x87_pc_off);
|
||||
writememl(easeg,cpu_state.eaaddr+16,x87_pc_seg);
|
||||
writememl(easeg,cpu_state.eaaddr+20,x87_op_off);
|
||||
writememl(easeg,cpu_state.eaaddr+24,x87_op_seg);
|
||||
break;
|
||||
}
|
||||
CLOCK_CYCLES((cr0 & 1) ? 56 : 67);
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
|
||||
static int opFSTENV_a16(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
fetch_ea_16(fetchdat);
|
||||
SEG_CHECK_WRITE(cpu_state.ea_seg);
|
||||
FSTENV();
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
#ifndef FPU_8087
|
||||
static int opFSTENV_a32(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
fetch_ea_32(fetchdat);
|
||||
SEG_CHECK_WRITE(cpu_state.ea_seg);
|
||||
FSTENV();
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int opFSTCW_a16(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
fetch_ea_16(fetchdat);
|
||||
SEG_CHECK_WRITE(cpu_state.ea_seg);
|
||||
seteaw(cpu_state.npxc);
|
||||
CLOCK_CYCLES(3);
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
#ifndef FPU_8087
|
||||
static int opFSTCW_a32(uint32_t fetchdat)
|
||||
{
|
||||
FP_ENTER();
|
||||
fetch_ea_32(fetchdat);
|
||||
SEG_CHECK_WRITE(cpu_state.ea_seg);
|
||||
seteaw(cpu_state.npxc);
|
||||
CLOCK_CYCLES(3);
|
||||
return cpu_state.abrt;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef FPU_8087
|
||||
#ifdef FP_686
|
||||
#define opFCMOV(condition) \
|
||||
static int opFCMOV ## condition(uint32_t fetchdat) \
|
||||
{ \
|
||||
FP_ENTER(); \
|
||||
cpu_state.pc++; \
|
||||
if (cond_ ## condition) \
|
||||
{ \
|
||||
cpu_state.tag[FP_TOP(cpu_state.TOP)] = cpu_state.tag[(cpu_state.TOP + fetchdat) & 7]; \
|
||||
cpu_state.MM[FP_TOP(cpu_state.TOP)].q = cpu_state.MM[(cpu_state.TOP + fetchdat) & 7].q; \
|
||||
ST(0) = ST(fetchdat & 7); \
|
||||
} \
|
||||
CLOCK_CYCLES(4); \
|
||||
return 0; \
|
||||
}
|
||||
|
||||
#define cond_U ( PF_SET())
|
||||
#define cond_NU (!PF_SET())
|
||||
|
||||
opFCMOV(B)
|
||||
opFCMOV(E)
|
||||
opFCMOV(BE)
|
||||
opFCMOV(U)
|
||||
opFCMOV(NB)
|
||||
opFCMOV(NE)
|
||||
opFCMOV(NBE)
|
||||
opFCMOV(NU)
|
||||
#endif
|
||||
#endif
|
||||
Reference in New Issue
Block a user