Split the 286/386 interpreter away from the 486+ one (the 286/386 interpreter does not use the pccache's, readlookup's, and writelookup's as the emulated CPU's are too slow for them to be required, and also has more accurate FPU timings), also added a LPT status read function for future-proofing.
This commit is contained in:
206
src/cpu/386.c
206
src/cpu/386.c
@@ -12,17 +12,22 @@
|
||||
#define HAVE_STDARG_H
|
||||
#include <86box/86box.h>
|
||||
#include "cpu.h"
|
||||
#include <86box/timer.h>
|
||||
#include "x86.h"
|
||||
#include "x86_ops.h"
|
||||
#include "x87.h"
|
||||
#include <86box/io.h>
|
||||
#include <86box/nmi.h>
|
||||
#include <86box/mem.h>
|
||||
#include <86box/pic.h>
|
||||
#include <86box/timer.h>
|
||||
#include <86box/pit.h>
|
||||
#include <86box/fdd.h>
|
||||
#include <86box/fdc.h>
|
||||
#include <86box/machine.h>
|
||||
#include <86box/gdbstub.h>
|
||||
#ifndef OPS_286_386
|
||||
#define OPS_286_386
|
||||
#endif
|
||||
#include "386_common.h"
|
||||
#ifdef USE_NEW_DYNAREC
|
||||
# include "codegen.h"
|
||||
@@ -33,54 +38,7 @@
|
||||
|
||||
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;
|
||||
|
||||
#if 1
|
||||
int opcode_length[256] = { 3, 3, 3, 3, 3, 3, 1, 1, 3, 3, 3, 3, 3, 3, 1, 3, /* 0x0x */
|
||||
3, 3, 3, 3, 3, 3, 1, 1, 3, 3, 3, 3, 3, 3, 1, 1, /* 0x1x */
|
||||
3, 3, 3, 3, 3, 3, 1, 1, 3, 3, 3, 3, 3, 3, 1, 1, /* 0x2x */
|
||||
3, 3, 3, 3, 3, 3, 1, 1, 3, 3, 3, 3, 3, 3, 1, 1, /* 0x3x */
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x4x */
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x5x */
|
||||
1, 1, 3, 3, 1, 1, 1, 1, 3, 3, 2, 3, 1, 1, 1, 1, /* 0x6x */
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0x7x */
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0x8x */
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, /* 0x9x */
|
||||
3, 3, 3, 3, 1, 1, 1, 1, 2, 3, 1, 1, 1, 1, 1, 1, /* 0xax */
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, /* 0xbx */
|
||||
3, 3, 3, 1, 3, 3, 3, 3, 3, 1, 3, 1, 1, 2, 1, 1, /* 0xcx */
|
||||
3, 3, 3, 3, 2, 2, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, /* 0xdx */
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 2, 1, 1, 1, 1, /* 0xex */
|
||||
1, 1, 1, 1, 1, 1, 3, 3, 1, 1, 1, 1, 1, 1, 3, 3 }; /* 0xfx */
|
||||
#else
|
||||
int opcode_length[256] = { 3, 3, 3, 3, 3, 3, 1, 1, 3, 3, 3, 3, 3, 3, 1, 3, /* 0x0x */
|
||||
3, 3, 3, 3, 3, 3, 1, 1, 3, 3, 3, 3, 3, 3, 1, 1, /* 0x1x */
|
||||
3, 3, 3, 3, 3, 3, 3, 1, 3, 3, 3, 3, 3, 3, 3, 1, /* 0x2x */
|
||||
3, 3, 3, 3, 3, 3, 3, 1, 3, 3, 3, 3, 3, 3, 3, 1, /* 0x3x */
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x4x */
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x5x */
|
||||
1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 2, 3, 1, 1, 1, 1, /* 0x6x */
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0x7x */
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0x8x */
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, /* 0x9x */
|
||||
3, 3, 3, 3, 1, 1, 1, 1, 2, 3, 1, 1, 1, 1, 1, 1, /* 0xax */
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, /* 0xbx */
|
||||
3, 3, 3, 1, 3, 3, 3, 3, 3, 1, 3, 1, 1, 2, 1, 1, /* 0xcx */
|
||||
3, 3, 3, 3, 2, 2, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, /* 0xdx */
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 2, 1, 1, 1, 1, /* 0xex */
|
||||
3, 1, 3, 3, 1, 1, 3, 3, 1, 1, 1, 1, 1, 1, 3, 3 }; /* 0xfx */
|
||||
#endif
|
||||
static int fpu_cycles = 0;
|
||||
|
||||
#ifdef ENABLE_386_LOG
|
||||
int x386_do_log = ENABLE_386_LOG;
|
||||
@@ -103,9 +61,6 @@ x386_log(const char *fmt, ...)
|
||||
#undef CPU_BLOCK_END
|
||||
#define CPU_BLOCK_END()
|
||||
|
||||
#include "x86_flags.h"
|
||||
|
||||
/*
|
||||
#define getbytef() \
|
||||
((uint8_t) (fetchdat)); \
|
||||
cpu_state.pc++
|
||||
@@ -118,11 +73,141 @@ x386_log(const char *fmt, ...)
|
||||
#define getword2f() \
|
||||
((uint16_t) (fetchdat >> 8)); \
|
||||
cpu_state.pc += 2
|
||||
*/
|
||||
|
||||
#define OP_TABLE(name) ops_##name
|
||||
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;
|
||||
|
||||
#if 0
|
||||
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] != (uintptr_t) -1)
|
||||
eal_r = (uint32_t *) (readlookup2[addr >> 12] + addr);
|
||||
if (writelookup2[addr >> 12] != (uintptr_t) -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] != (uintptr_t) -1)
|
||||
eal_r = (uint32_t *) (readlookup2[addr >> 12] + addr);
|
||||
if (writelookup2[addr >> 12] != (uintptr_t) -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 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"
|
||||
|
||||
#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()
|
||||
|
||||
#ifndef FPU_CYCLES
|
||||
#define FPU_CYCLES
|
||||
#endif
|
||||
|
||||
#define OP_TABLE(name) ops_2386_##name
|
||||
# define CLOCK_CYCLES(c) \
|
||||
{ \
|
||||
if (fpu_cycles > 0) { \
|
||||
@@ -137,18 +222,13 @@ x386_log(const char *fmt, ...)
|
||||
|
||||
# define CLOCK_CYCLES_FPU(c) cycles -= (c)
|
||||
# define CONCURRENCY_CYCLES(c) fpu_cycles = (c)
|
||||
#else
|
||||
# define CLOCK_CYCLES(c) cycles -= (c)
|
||||
# define CLOCK_CYCLES_FPU(c) cycles -= (c)
|
||||
# define CONCURRENCY_CYCLES(c)
|
||||
#endif
|
||||
|
||||
#define CLOCK_CYCLES_ALWAYS(c) cycles -= (c)
|
||||
|
||||
#include "x86_ops.h"
|
||||
#include "386_ops.h"
|
||||
|
||||
void
|
||||
exec386(int cycs)
|
||||
exec386_2386(int cycs)
|
||||
{
|
||||
int vector, tempi, cycdiff, oldcyc;
|
||||
int cycle_period, ins_cycles;
|
||||
@@ -184,7 +264,7 @@ exec386(int cycs)
|
||||
if (!cpu_state.abrt) {
|
||||
#ifdef ENABLE_386_LOG
|
||||
if (in_smm)
|
||||
x386_log("[%04X:%08X] %08X\n", CS, cpu_state.pc, fetchdat);
|
||||
x386_2386_log("[%04X:%08X] %08X\n", CS, cpu_state.pc, fetchdat);
|
||||
#endif
|
||||
opcode = fetchdat & 0xFF;
|
||||
fetchdat >>= 8;
|
||||
|
||||
Reference in New Issue
Block a user