Files
86Box/src/cpu/386.c

266 lines
6.7 KiB
C
Raw Normal View History

2020-02-29 19:12:23 +01:00
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <wchar.h>
#include <math.h>
#ifndef INFINITY
2022-09-20 01:00:45 -04:00
# define INFINITY (__builtin_inff())
2020-02-29 19:12:23 +01:00
#endif
#define HAVE_STDARG_H
#include <86box/86box.h>
2020-02-29 19:12:23 +01:00
#include "cpu.h"
#include <86box/timer.h>
2020-02-29 19:12:23 +01:00
#include "x86.h"
#include "x87.h"
#include <86box/nmi.h>
#include <86box/mem.h>
#include <86box/pic.h>
#include <86box/pit.h>
#include <86box/fdd.h>
#include <86box/fdc.h>
#include <86box/machine.h>
2022-03-12 20:20:25 -03:00
#include <86box/gdbstub.h>
2020-02-29 19:12:23 +01:00
#include "386_common.h"
#ifdef USE_NEW_DYNAREC
2022-09-20 01:00:45 -04:00
# include "codegen.h"
2020-02-29 19:12:23 +01:00
#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,
2022-09-20 01:00:45 -04:00
olddslimitw, oldsslimitw;
2020-02-29 19:12:23 +01:00
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) {
2022-09-20 01:00:45 -04:00
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
2020-02-29 19:12:23 +01:00
}
}
#else
2022-09-20 01:00:45 -04:00
# define x386_log(fmt, ...)
2020-02-29 19:12:23 +01:00
#endif
#undef CPU_BLOCK_END
#define CPU_BLOCK_END()
#include "x86_flags.h"
2022-09-21 18:53:41 -04:00
/*
2022-09-20 01:00:45 -04:00
#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
2022-09-21 18:53:41 -04:00
*/
2022-09-20 01:00:45 -04:00
#define OP_TABLE(name) ops_##name
2020-02-29 19:12:23 +01:00
#if 0
2022-09-20 01:00:45 -04:00
# define CLOCK_CYCLES(c) \
{ \
if (fpu_cycles > 0) { \
fpu_cycles -= (c); \
if (fpu_cycles < 0) { \
cycles += fpu_cycles; \
} \
} else { \
cycles -= (c); \
} \
}
# define CLOCK_CYCLES_FPU(c) cycles -= (c)
# define CONCURRENCY_CYCLES(c) fpu_cycles = (c)
#else
2022-09-20 01:00:45 -04:00
# define CLOCK_CYCLES(c) cycles -= (c)
# define CLOCK_CYCLES_FPU(c) cycles -= (c)
# define CONCURRENCY_CYCLES(c)
#endif
2020-02-29 19:12:23 +01:00
#define CLOCK_CYCLES_ALWAYS(c) cycles -= (c)
#include "x86_ops.h"
void
exec386(int cycs)
{
2022-09-20 01:00:45 -04:00
int vector, tempi, cycdiff, oldcyc;
int cycle_period, ins_cycles;
2020-02-29 19:12:23 +01:00
uint32_t addr;
cycles += cycs;
while (cycles > 0) {
2022-09-20 01:00:45 -04:00
cycle_period = (timer_target - (uint32_t) tsc) + 1;
2020-02-29 19:12:23 +01:00
2022-09-20 01:00:45 -04:00
x86_was_reset = 0;
cycdiff = 0;
oldcyc = cycles;
while (cycdiff < cycle_period) {
ins_cycles = cycles;
2020-02-29 19:12:23 +01:00
#ifndef USE_NEW_DYNAREC
2022-09-20 01:00:45 -04:00
oldcs = CS;
oldcpl = CPL;
2020-02-29 19:12:23 +01:00
#endif
2022-09-20 01:00:45 -04:00
cpu_state.oldpc = cpu_state.pc;
cpu_state.op32 = use32;
2020-02-29 19:12:23 +01:00
#ifndef USE_NEW_DYNAREC
2022-09-20 01:00:45 -04:00
x86_was_reset = 0;
2020-02-29 19:12:23 +01:00
#endif
2022-09-20 01:00:45 -04:00
cpu_state.ea_seg = &cpu_state.seg_ds;
cpu_state.ssegs = 0;
2020-02-29 19:12:23 +01:00
2022-09-20 01:00:45 -04:00
fetchdat = fastreadl(cs + cpu_state.pc);
2020-02-29 19:12:23 +01:00
2022-09-20 01:00:45 -04:00
if (!cpu_state.abrt) {
#ifdef ENABLE_386_LOG
2022-09-20 01:00:45 -04:00
if (in_smm)
x386_log("[%04X:%08X] %08X\n", CS, cpu_state.pc, fetchdat);
#endif
2022-09-20 01:00:45 -04:00
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;
}
#ifdef ENABLE_386_LOG
2022-09-20 01:00:45 -04:00
else if (in_smm)
x386_log("[%04X:%08X] ABRT\n", CS, cpu_state.pc);
#endif
2020-02-29 19:12:23 +01:00
#ifndef USE_NEW_DYNAREC
2022-09-20 01:00:45 -04:00
if (!use32)
cpu_state.pc &= 0xffff;
2020-02-29 19:12:23 +01:00
#endif
2022-09-20 01:00:45 -04:00
if (cpu_end_block_after_ins)
cpu_end_block_after_ins--;
2020-11-21 04:02:58 +01:00
2022-09-20 01:00:45 -04:00
if (cpu_state.abrt) {
flags_rebuild();
tempi = cpu_state.abrt & ABRT_MASK;
cpu_state.abrt = 0;
x86_doabrt(tempi);
if (cpu_state.abrt) {
cpu_state.abrt = 0;
#ifndef USE_NEW_DYNAREC
2022-09-20 01:00:45 -04:00
CS = oldcs;
#endif
2022-09-20 01:00:45 -04:00
cpu_state.pc = cpu_state.oldpc;
x386_log("Double fault\n");
pmodeint(8, 0);
if (cpu_state.abrt) {
cpu_state.abrt = 0;
softresetx86();
cpu_set_edx();
#ifdef ENABLE_386_LOG
2022-09-20 01:00:45 -04:00
x386_log("Triple fault - reset\n");
#endif
2022-09-20 01:00:45 -04:00
}
}
} else if (trap) {
flags_rebuild();
trap = 0;
#ifndef USE_NEW_DYNAREC
oldcs = CS;
#endif
cpu_state.oldpc = cpu_state.pc;
dr[6] |= 0x4000;
x86_int(1);
2022-09-20 01:00:45 -04:00
}
if (smi_line)
enter_smm_check(0);
else if (nmi && nmi_enable && nmi_mask) {
#ifndef USE_NEW_DYNAREC
oldcs = CS;
#endif
2022-09-20 01:00:45 -04:00
cpu_state.oldpc = cpu_state.pc;
x86_int(2);
nmi_enable = 0;
#ifdef OLD_NMI_BEHAVIOR
2022-09-20 01:00:45 -04:00
if (nmi_auto_clear) {
nmi_auto_clear = 0;
nmi = 0;
}
#else
2022-09-20 01:00:45 -04:00
nmi = 0;
#endif
2022-09-20 01:00:45 -04:00
} else if ((cpu_state.flags & I_FLAG) && pic.int_pending && !cpu_end_block_after_ins) {
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_cycles -= cycles;
tsc += ins_cycles;
cycdiff = oldcyc - cycles;
if (timetolive) {
timetolive--;
if (!timetolive)
fatal("Life expired\n");
}
if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t) tsc))
timer_process_inline();
2022-03-12 20:20:25 -03:00
#ifdef USE_GDBSTUB
2022-09-20 01:00:45 -04:00
if (gdbstub_instruction())
return;
2022-03-12 20:20:25 -03:00
#endif
2022-09-20 01:00:45 -04:00
}
2020-02-29 19:12:23 +01:00
}
}