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
|
|
|
|
|
# define INFINITY (__builtin_inff())
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#define HAVE_STDARG_H
|
2020-03-29 14:24:42 +02:00
|
|
|
#include <86box/86box.h>
|
2020-02-29 19:12:23 +01:00
|
|
|
#include "cpu.h"
|
2020-03-29 14:24:42 +02:00
|
|
|
#include <86box/timer.h>
|
2020-02-29 19:12:23 +01:00
|
|
|
#include "x86.h"
|
|
|
|
|
#include "x87.h"
|
2020-03-29 14:24:42 +02:00
|
|
|
#include <86box/nmi.h>
|
|
|
|
|
#include <86box/mem.h>
|
|
|
|
|
#include <86box/pic.h>
|
|
|
|
|
#include <86box/pit.h>
|
|
|
|
|
#include <86box/fdd.h>
|
|
|
|
|
#include <86box/fdc.h>
|
2020-04-16 21:56:19 +02:00
|
|
|
#include <86box/machine.h>
|
2020-02-29 19:12:23 +01:00
|
|
|
#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()
|
|
|
|
|
|
|
|
|
|
#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
|
|
|
|
|
|
2022-02-01 19:07:22 +01:00
|
|
|
#if 0
|
2022-01-29 07:27:45 -08:00
|
|
|
#define CLOCK_CYCLES(c) \
|
|
|
|
|
{\
|
|
|
|
|
if (fpu_cycles > 0) {\
|
|
|
|
|
fpu_cycles -= (c);\
|
|
|
|
|
if (fpu_cycles < 0) {\
|
|
|
|
|
cycles += fpu_cycles;\
|
|
|
|
|
}\
|
|
|
|
|
} else {\
|
|
|
|
|
cycles -= (c);\
|
|
|
|
|
}\
|
|
|
|
|
}
|
2022-02-02 02:46:11 +01:00
|
|
|
|
|
|
|
|
#define CLOCK_CYCLES_FPU(c) cycles -= (c)
|
|
|
|
|
#define CONCURRENCY_CYCLES(c) fpu_cycles = (c)
|
2022-02-01 19:07:22 +01:00
|
|
|
#else
|
|
|
|
|
#define CLOCK_CYCLES(c) cycles -= (c)
|
2022-02-02 02:51:18 +01:00
|
|
|
#define CLOCK_CYCLES_FPU(c) cycles -= (c)
|
|
|
|
|
#define CONCURRENCY_CYCLES(c)
|
2022-02-01 19:07:22 +01:00
|
|
|
#endif
|
2022-01-29 07:27:45 -08:00
|
|
|
|
2020-02-29 19:12:23 +01:00
|
|
|
#define CLOCK_CYCLES_ALWAYS(c) cycles -= (c)
|
|
|
|
|
|
|
|
|
|
#include "x86_ops.h"
|
|
|
|
|
|
2020-11-16 00:01:21 +01:00
|
|
|
|
2020-02-29 19:12:23 +01:00
|
|
|
void
|
|
|
|
|
exec386(int cycs)
|
|
|
|
|
{
|
|
|
|
|
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) {
|
2020-04-01 08:59:29 +02:00
|
|
|
#ifdef ENABLE_386_LOG
|
|
|
|
|
if (in_smm)
|
|
|
|
|
x386_log("[%04X:%08X] %08X\n", CS, cpu_state.pc, fetchdat);
|
|
|
|
|
#endif
|
2020-02-29 19:12:23 +01: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;
|
2020-04-10 19:45:53 +02:00
|
|
|
}
|
2020-04-01 08:59:29 +02:00
|
|
|
#ifdef ENABLE_386_LOG
|
2020-04-10 19:45:53 +02:00
|
|
|
else if (in_smm)
|
2020-04-01 08:59:29 +02:00
|
|
|
x386_log("[%04X:%08X] ABRT\n", CS, cpu_state.pc);
|
|
|
|
|
#endif
|
2020-02-29 19:12:23 +01:00
|
|
|
|
|
|
|
|
#ifndef USE_NEW_DYNAREC
|
|
|
|
|
if (!use32) cpu_state.pc &= 0xffff;
|
|
|
|
|
#endif
|
|
|
|
|
|
2020-11-21 04:02:58 +01:00
|
|
|
if (cpu_end_block_after_ins)
|
|
|
|
|
cpu_end_block_after_ins--;
|
|
|
|
|
|
2020-11-17 20:00:28 +01: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
|
|
|
|
|
CS = oldcs;
|
|
|
|
|
#endif
|
|
|
|
|
cpu_state.pc = cpu_state.oldpc;
|
2021-04-10 07:18:47 +02:00
|
|
|
x386_log("Double fault\n");
|
2020-11-17 20:00:28 +01:00
|
|
|
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
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-10 01:08:52 +02:00
|
|
|
if (smi_line)
|
|
|
|
|
enter_smm_check(0);
|
|
|
|
|
else if (trap) {
|
2020-02-29 19:12:23 +01:00
|
|
|
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) {
|
2021-12-19 20:00:27 +01:00
|
|
|
if (is486 && (cpu_fast_off_flags & 0x20000000))
|
2020-04-16 21:56:19 +02:00
|
|
|
cpu_fast_off_count = cpu_fast_off_val + 1;
|
|
|
|
|
|
2020-02-29 19:12:23 +01:00
|
|
|
cpu_state.oldpc = cpu_state.pc;
|
|
|
|
|
x86_int(2);
|
|
|
|
|
nmi_enable = 0;
|
2021-09-02 15:24:17 +02:00
|
|
|
#ifdef OLD_NMI_BEHAVIOR
|
2020-02-29 19:12:23 +01:00
|
|
|
if (nmi_auto_clear) {
|
|
|
|
|
nmi_auto_clear = 0;
|
|
|
|
|
nmi = 0;
|
|
|
|
|
}
|
2021-09-02 15:24:17 +02:00
|
|
|
#else
|
|
|
|
|
nmi = 0;
|
|
|
|
|
#endif
|
2020-11-16 00:01:21 +01:00
|
|
|
} else if ((cpu_state.flags & I_FLAG) && pic.int_pending && !cpu_end_block_after_ins) {
|
2020-02-29 19:12:23 +01:00
|
|
|
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));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-20 01:28:36 +01:00
|
|
|
ins_cycles -= cycles;
|
|
|
|
|
tsc += ins_cycles;
|
|
|
|
|
|
|
|
|
|
cycdiff = oldcyc - cycles;
|
|
|
|
|
|
2020-02-29 19:12:23 +01:00
|
|
|
if (timetolive) {
|
|
|
|
|
timetolive--;
|
|
|
|
|
if (!timetolive)
|
|
|
|
|
fatal("Life expired\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t) tsc))
|
PIC rewrite, proper SMRAM API, complete SiS 471 rewrite and addition of 40x, 460, and 461, changes to mem.c/h, disabled Voodoo memory dumping on exit, bumped SDL Hardware scale quality to 2, bumped IDE/ATAPI drives to ATA-6, finally bumped emulator version to 3.0, redid the bus type ID's to allow for planned ATAPI hard disks, made SST flash set its high mappings to the correct address if the CPU is 16-bit, and added the SiS 401 AMI 486 Clone, AOpen Vi15G, and the Soyo 4SA2 (486 with SiS 496/497 that can boot from CD-ROM), assorted 286+ protected mode fixes (for slightly more accuracy), and fixes to 808x emulation (MS Word 1.0 and 1.10 for DOS now work correctly from floppy).
2020-10-14 23:15:01 +02:00
|
|
|
timer_process_inline();
|
2020-02-29 19:12:23 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|