The 286/386 interpreter now has its own variant of x86seg.c.
This commit is contained in:
221
src/cpu/x86seg.c
221
src/cpu/x86seg.c
@@ -36,17 +36,25 @@
|
||||
|
||||
#include "x86.h"
|
||||
#include "x86_flags.h"
|
||||
#include "x86seg.h"
|
||||
#include "x86seg_common.h"
|
||||
#include "386_common.h"
|
||||
|
||||
uint8_t opcode2;
|
||||
|
||||
int cgate16;
|
||||
int cgate32;
|
||||
int intgatesize;
|
||||
|
||||
void taskswitch286(uint16_t seg, uint16_t *segdat, int is32);
|
||||
|
||||
void pmodeint(int num, int soft);
|
||||
#ifdef OPS_286_386
|
||||
#define seg_readmembl readmembl_2386
|
||||
#define seg_readmemwl readmemwl_2386
|
||||
#define seg_readmemll readmemll_2386
|
||||
#define seg_writemembl writemembl_2386
|
||||
#define seg_writememwl writememwl_2386
|
||||
#define seg_writememll writememll_2386
|
||||
#else
|
||||
#define seg_readmembl readmembl_2386
|
||||
#define seg_readmemwl readmemwl_2386
|
||||
#define seg_readmemll readmemll_2386
|
||||
#define seg_writemembl writemembl_2386
|
||||
#define seg_writememwl writememwl_2386
|
||||
#define seg_writememll writememll_2386
|
||||
#endif
|
||||
|
||||
#define DPL ((segdat[2] >> 13) & 3)
|
||||
#define DPL2 ((segdat2[2] >> 13) & 3)
|
||||
@@ -70,41 +78,12 @@ x86seg_log(const char *fmt, ...)
|
||||
# define x86seg_log(fmt, ...)
|
||||
#endif
|
||||
|
||||
static void
|
||||
seg_reset(x86seg *s)
|
||||
{
|
||||
s->access = 0x82;
|
||||
s->ar_high = 0x10;
|
||||
s->limit = 0xffff;
|
||||
s->limit_low = 0;
|
||||
s->limit_high = 0xffff;
|
||||
if (s == &cpu_state.seg_cs) {
|
||||
if (!cpu_inited)
|
||||
fatal("seg_reset(&cpu_state.seg.cs) without an initialized CPU\n");
|
||||
if (is6117)
|
||||
s->base = 0x03ff0000;
|
||||
else
|
||||
s->base = is286 ? (cpu_16bitbus ? 0x00ff0000 : 0xffff0000) : 0x000ffff0;
|
||||
s->seg = is286 ? 0xf000 : 0xffff;
|
||||
} else {
|
||||
s->base = 0;
|
||||
s->seg = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
x86seg_reset(void)
|
||||
{
|
||||
seg_reset(&cpu_state.seg_cs);
|
||||
seg_reset(&cpu_state.seg_ds);
|
||||
seg_reset(&cpu_state.seg_es);
|
||||
seg_reset(&cpu_state.seg_fs);
|
||||
seg_reset(&cpu_state.seg_gs);
|
||||
seg_reset(&cpu_state.seg_ss);
|
||||
}
|
||||
|
||||
void
|
||||
#ifdef OPS_286_386
|
||||
x86_doabrt_2386(int x86_abrt)
|
||||
#else
|
||||
x86_doabrt(int x86_abrt)
|
||||
#endif
|
||||
{
|
||||
#ifndef USE_NEW_DYNAREC
|
||||
CS = oldcs;
|
||||
@@ -114,7 +93,7 @@ x86_doabrt(int x86_abrt)
|
||||
cpu_state.seg_cs.ar_high = 0x10;
|
||||
|
||||
if (msw & 1)
|
||||
pmodeint(x86_abrt, 0);
|
||||
op_pmodeint(x86_abrt, 0);
|
||||
else {
|
||||
uint32_t addr = (x86_abrt << 2) + idt.base;
|
||||
if (stack32) {
|
||||
@@ -134,7 +113,7 @@ x86_doabrt(int x86_abrt)
|
||||
oxpc = cpu_state.pc;
|
||||
#endif
|
||||
cpu_state.pc = readmemw(0, addr);
|
||||
loadcs(readmemw(0, addr + 2));
|
||||
op_loadcs(readmemw(0, addr + 2));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -160,52 +139,6 @@ x86_doabrt(int x86_abrt)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
x86de(UNUSED(char *s), UNUSED(uint16_t error))
|
||||
{
|
||||
#ifdef BAD_CODE
|
||||
cpu_state.abrt = ABRT_DE;
|
||||
abrt_error = error;
|
||||
#else
|
||||
x86_int(0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
x86gpf(UNUSED(char *s), uint16_t error)
|
||||
{
|
||||
cpu_state.abrt = ABRT_GPF;
|
||||
abrt_error = error;
|
||||
}
|
||||
|
||||
void
|
||||
x86gpf_expected(UNUSED(char *s), uint16_t error)
|
||||
{
|
||||
cpu_state.abrt = ABRT_GPF | ABRT_EXPECTED;
|
||||
abrt_error = error;
|
||||
}
|
||||
|
||||
void
|
||||
x86ss(UNUSED(char *s), uint16_t error)
|
||||
{
|
||||
cpu_state.abrt = ABRT_SS;
|
||||
abrt_error = error;
|
||||
}
|
||||
|
||||
void
|
||||
x86ts(UNUSED(char *s), uint16_t error)
|
||||
{
|
||||
cpu_state.abrt = ABRT_TS;
|
||||
abrt_error = error;
|
||||
}
|
||||
|
||||
void
|
||||
x86np(UNUSED(char *s), uint16_t error)
|
||||
{
|
||||
cpu_state.abrt = ABRT_NP;
|
||||
abrt_error = error;
|
||||
}
|
||||
|
||||
static void
|
||||
set_stack32(int s)
|
||||
{
|
||||
@@ -228,6 +161,7 @@ set_use32(int u)
|
||||
cpu_cur_status &= ~CPU_STATUS_USE32;
|
||||
}
|
||||
|
||||
#ifndef OPS_286_386
|
||||
void
|
||||
do_seg_load(x86seg *s, uint16_t *segdat)
|
||||
{
|
||||
@@ -262,6 +196,7 @@ do_seg_load(x86seg *s, uint16_t *segdat)
|
||||
cpu_cur_status |= CPU_STATUS_NOTFLATSS;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
do_seg_v86_init(x86seg *s)
|
||||
@@ -310,7 +245,7 @@ check_seg_valid(x86seg *s)
|
||||
}
|
||||
|
||||
if (!valid)
|
||||
loadseg(0, s);
|
||||
op_loadseg(0, s);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -336,7 +271,11 @@ int
|
||||
#else
|
||||
void
|
||||
#endif
|
||||
#ifdef OPS_286_386
|
||||
loadseg_2386(uint16_t seg, x86seg *s)
|
||||
#else
|
||||
loadseg(uint16_t seg, x86seg *s)
|
||||
#endif
|
||||
{
|
||||
uint16_t segdat[4];
|
||||
uint32_t addr;
|
||||
@@ -534,7 +473,11 @@ loadseg(uint16_t seg, x86seg *s)
|
||||
}
|
||||
|
||||
void
|
||||
#ifdef OPS_286_386
|
||||
loadcs_2386(uint16_t seg)
|
||||
#else
|
||||
loadcs(uint16_t seg)
|
||||
#endif
|
||||
{
|
||||
uint16_t segdat[4];
|
||||
uint32_t addr;
|
||||
@@ -623,7 +566,11 @@ loadcs(uint16_t seg)
|
||||
}
|
||||
|
||||
void
|
||||
#ifdef OPS_286_386
|
||||
loadcsjmp_2386(uint16_t seg, uint32_t old_pc)
|
||||
#else
|
||||
loadcsjmp(uint16_t seg, uint32_t old_pc)
|
||||
#endif
|
||||
{
|
||||
uint16_t type;
|
||||
uint16_t seg2;
|
||||
@@ -783,7 +730,7 @@ loadcsjmp(uint16_t seg, uint32_t old_pc)
|
||||
cpu_state.pc = old_pc;
|
||||
optype = JMP;
|
||||
cpl_override = 1;
|
||||
taskswitch286(seg, segdat, segdat[2] & 0x800);
|
||||
op_taskswitch286(seg, segdat, segdat[2] & 0x800);
|
||||
cpu_state.flags &= ~NT_FLAG;
|
||||
cpl_override = 0;
|
||||
return;
|
||||
@@ -810,7 +757,7 @@ loadcsjmp(uint16_t seg, uint32_t old_pc)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
PUSHW(uint16_t v)
|
||||
{
|
||||
if (stack32) {
|
||||
@@ -826,7 +773,7 @@ PUSHW(uint16_t v)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
PUSHL(uint32_t v)
|
||||
{
|
||||
if (cpu_16bitbus) {
|
||||
@@ -847,7 +794,7 @@ PUSHL(uint32_t v)
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t
|
||||
static uint16_t
|
||||
POPW(void)
|
||||
{
|
||||
uint16_t tempw;
|
||||
@@ -865,7 +812,7 @@ POPW(void)
|
||||
return tempw;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
static uint32_t
|
||||
POPL(void)
|
||||
{
|
||||
uint32_t templ;
|
||||
@@ -890,6 +837,15 @@ POPL(void)
|
||||
return templ;
|
||||
}
|
||||
|
||||
#ifdef OPS_286_386
|
||||
#ifdef USE_NEW_DYNAREC
|
||||
void
|
||||
loadcscall_2386(uint16_t seg, uint32_t old_pc)
|
||||
#else
|
||||
void
|
||||
loadcscall_2386(uint16_t seg)
|
||||
#endif
|
||||
#else
|
||||
#ifdef USE_NEW_DYNAREC
|
||||
void
|
||||
loadcscall(uint16_t seg, uint32_t old_pc)
|
||||
@@ -897,6 +853,7 @@ loadcscall(uint16_t seg, uint32_t old_pc)
|
||||
void
|
||||
loadcscall(uint16_t seg)
|
||||
#endif
|
||||
#endif
|
||||
{
|
||||
uint16_t seg2;
|
||||
uint16_t newss;
|
||||
@@ -1225,7 +1182,7 @@ loadcscall(uint16_t seg)
|
||||
cpu_state.pc = oxpc;
|
||||
#endif
|
||||
cpl_override = 1;
|
||||
taskswitch286(seg, segdat, segdat[2] & 0x0800);
|
||||
op_taskswitch286(seg, segdat, segdat[2] & 0x0800);
|
||||
cpl_override = 0;
|
||||
break;
|
||||
|
||||
@@ -1251,7 +1208,11 @@ loadcscall(uint16_t seg)
|
||||
}
|
||||
|
||||
void
|
||||
#ifdef OPS_286_386
|
||||
pmoderetf_2386(int is32, uint16_t off)
|
||||
#else
|
||||
pmoderetf(int is32, uint16_t off)
|
||||
#endif
|
||||
{
|
||||
uint16_t segdat[4];
|
||||
uint16_t segdat2[4];
|
||||
@@ -1487,7 +1448,11 @@ pmoderetf(int is32, uint16_t off)
|
||||
}
|
||||
|
||||
void
|
||||
#ifdef OPS_286_386
|
||||
pmodeint_2386(int num, int soft)
|
||||
#else
|
||||
pmodeint(int num, int soft)
|
||||
#endif
|
||||
{
|
||||
uint16_t segdat[4];
|
||||
uint16_t segdat2[4];
|
||||
@@ -1518,7 +1483,7 @@ pmodeint(int num, int soft)
|
||||
softresetx86();
|
||||
cpu_set_edx();
|
||||
} else if (num == 0x0d)
|
||||
pmodeint(8, 0);
|
||||
op_pmodeint(8, 0);
|
||||
else
|
||||
x86gpf("pmodeint(): Vector > IDT limit", (num << 3) + 2 + !soft);
|
||||
x86seg_log("addr >= IDT.limit\n");
|
||||
@@ -1659,10 +1624,10 @@ pmodeint(int num, int soft)
|
||||
PUSHL(ES);
|
||||
if (cpu_state.abrt)
|
||||
return;
|
||||
loadseg(0, &cpu_state.seg_ds);
|
||||
loadseg(0, &cpu_state.seg_es);
|
||||
loadseg(0, &cpu_state.seg_fs);
|
||||
loadseg(0, &cpu_state.seg_gs);
|
||||
op_loadseg(0, &cpu_state.seg_ds);
|
||||
op_loadseg(0, &cpu_state.seg_es);
|
||||
op_loadseg(0, &cpu_state.seg_fs);
|
||||
op_loadseg(0, &cpu_state.seg_gs);
|
||||
}
|
||||
PUSHL(oldss);
|
||||
PUSHL(oldsp);
|
||||
@@ -1764,7 +1729,7 @@ pmodeint(int num, int soft)
|
||||
}
|
||||
optype = OPTYPE_INT;
|
||||
cpl_override = 1;
|
||||
taskswitch286(seg, segdat2, segdat2[2] & 0x0800);
|
||||
op_taskswitch286(seg, segdat2, segdat2[2] & 0x0800);
|
||||
cpl_override = 0;
|
||||
break;
|
||||
|
||||
@@ -1775,7 +1740,11 @@ pmodeint(int num, int soft)
|
||||
}
|
||||
|
||||
void
|
||||
#ifdef OPS_286_386
|
||||
pmodeiret_2386(int is32)
|
||||
#else
|
||||
pmodeiret(int is32)
|
||||
#endif
|
||||
{
|
||||
uint16_t newss;
|
||||
uint16_t seg = 0;
|
||||
@@ -1842,7 +1811,7 @@ pmodeiret(int is32)
|
||||
}
|
||||
cpl_override = 1;
|
||||
read_descriptor(addr, segdat, segdat32, 1);
|
||||
taskswitch286(seg, segdat, segdat[2] & 0x0800);
|
||||
op_taskswitch286(seg, segdat, segdat[2] & 0x0800);
|
||||
cpl_override = 0;
|
||||
return;
|
||||
}
|
||||
@@ -1876,14 +1845,14 @@ pmodeiret(int is32)
|
||||
}
|
||||
cpu_state.eflags = tempflags >> 16;
|
||||
cpu_cur_status |= CPU_STATUS_V86;
|
||||
loadseg(segs[0], &cpu_state.seg_es);
|
||||
op_loadseg(segs[0], &cpu_state.seg_es);
|
||||
do_seg_v86_init(&cpu_state.seg_es);
|
||||
loadseg(segs[1], &cpu_state.seg_ds);
|
||||
op_loadseg(segs[1], &cpu_state.seg_ds);
|
||||
do_seg_v86_init(&cpu_state.seg_ds);
|
||||
cpu_cur_status |= CPU_STATUS_NOTFLATDS;
|
||||
loadseg(segs[2], &cpu_state.seg_fs);
|
||||
op_loadseg(segs[2], &cpu_state.seg_fs);
|
||||
do_seg_v86_init(&cpu_state.seg_fs);
|
||||
loadseg(segs[3], &cpu_state.seg_gs);
|
||||
op_loadseg(segs[3], &cpu_state.seg_gs);
|
||||
do_seg_v86_init(&cpu_state.seg_gs);
|
||||
|
||||
cpu_state.pc = newpc & 0xffff;
|
||||
@@ -1901,7 +1870,7 @@ pmodeiret(int is32)
|
||||
#endif
|
||||
|
||||
ESP = newsp;
|
||||
loadseg(newss, &cpu_state.seg_ss);
|
||||
op_loadseg(newss, &cpu_state.seg_ss);
|
||||
do_seg_v86_init(&cpu_state.seg_ss);
|
||||
cpu_cur_status |= CPU_STATUS_NOTFLATSS;
|
||||
use32 = 0;
|
||||
@@ -2088,7 +2057,11 @@ pmodeiret(int is32)
|
||||
}
|
||||
|
||||
void
|
||||
#ifdef OPS_286_386
|
||||
taskswitch286_2386(uint16_t seg, uint16_t *segdat, int is32)
|
||||
#else
|
||||
taskswitch286(uint16_t seg, uint16_t *segdat, int is32)
|
||||
#endif
|
||||
{
|
||||
uint16_t tempw;
|
||||
uint16_t new_ldt;
|
||||
@@ -2235,7 +2208,7 @@ taskswitch286(uint16_t seg, uint16_t *segdat, int is32)
|
||||
ldt.base = (readmemw(0, templ + 2)) | (readmemb(0, templ + 4) << 16) | (readmemb(0, templ + 7) << 24);
|
||||
|
||||
if (cpu_state.eflags & VM_FLAG) {
|
||||
loadcs(new_cs);
|
||||
op_loadcs(new_cs);
|
||||
set_use32(0);
|
||||
cpu_cur_status |= CPU_STATUS_V86;
|
||||
} else {
|
||||
@@ -2299,11 +2272,11 @@ taskswitch286(uint16_t seg, uint16_t *segdat, int is32)
|
||||
ESI = new_esi;
|
||||
EDI = new_edi;
|
||||
|
||||
loadseg(new_es, &cpu_state.seg_es);
|
||||
loadseg(new_ss, &cpu_state.seg_ss);
|
||||
loadseg(new_ds, &cpu_state.seg_ds);
|
||||
loadseg(new_fs, &cpu_state.seg_fs);
|
||||
loadseg(new_gs, &cpu_state.seg_gs);
|
||||
op_loadseg(new_es, &cpu_state.seg_es);
|
||||
op_loadseg(new_ss, &cpu_state.seg_ss);
|
||||
op_loadseg(new_ds, &cpu_state.seg_ds);
|
||||
op_loadseg(new_fs, &cpu_state.seg_fs);
|
||||
op_loadseg(new_gs, &cpu_state.seg_gs);
|
||||
} else {
|
||||
if (limit < 43) {
|
||||
x86ts(NULL, seg);
|
||||
@@ -2465,12 +2438,12 @@ taskswitch286(uint16_t seg, uint16_t *segdat, int is32)
|
||||
ESI = new_esi | 0xffff0000;
|
||||
EDI = new_edi | 0xffff0000;
|
||||
|
||||
loadseg(new_es, &cpu_state.seg_es);
|
||||
loadseg(new_ss, &cpu_state.seg_ss);
|
||||
loadseg(new_ds, &cpu_state.seg_ds);
|
||||
op_loadseg(new_es, &cpu_state.seg_es);
|
||||
op_loadseg(new_ss, &cpu_state.seg_ss);
|
||||
op_loadseg(new_ds, &cpu_state.seg_ds);
|
||||
if (is386) {
|
||||
loadseg(0, &cpu_state.seg_fs);
|
||||
loadseg(0, &cpu_state.seg_gs);
|
||||
op_loadseg(0, &cpu_state.seg_fs);
|
||||
op_loadseg(0, &cpu_state.seg_gs);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2482,7 +2455,11 @@ taskswitch286(uint16_t seg, uint16_t *segdat, int is32)
|
||||
}
|
||||
|
||||
void
|
||||
#ifdef OPS_286_386
|
||||
cyrix_write_seg_descriptor_2386(uint32_t addr, x86seg *seg)
|
||||
#else
|
||||
cyrix_write_seg_descriptor(uint32_t addr, x86seg *seg)
|
||||
#endif
|
||||
{
|
||||
uint32_t limit_raw = seg->limit;
|
||||
|
||||
@@ -2494,7 +2471,11 @@ cyrix_write_seg_descriptor(uint32_t addr, x86seg *seg)
|
||||
}
|
||||
|
||||
void
|
||||
#ifdef OPS_286_386
|
||||
cyrix_load_seg_descriptor_2386(uint32_t addr, x86seg *seg)
|
||||
#else
|
||||
cyrix_load_seg_descriptor(uint32_t addr, x86seg *seg)
|
||||
#endif
|
||||
{
|
||||
uint16_t segdat[4];
|
||||
uint16_t selector;
|
||||
|
||||
Reference in New Issue
Block a user