The 286/386 interpreter now has its own variant of x86seg.c.

This commit is contained in:
OBattler
2023-08-21 02:56:33 +02:00
parent 5ac598378f
commit 1d48363803
61 changed files with 596 additions and 260 deletions

View File

@@ -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;