Keyboard reset fixes and the two files I forgot in the previous commit.

This commit is contained in:
OBattler
2021-04-10 07:22:49 +02:00
parent 976f6edc9d
commit 5990663881
3 changed files with 418 additions and 1 deletions

101
src/cpu/fpu.c Normal file
View File

@@ -0,0 +1,101 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* FPU type handler.
*
* Authors: Sarah Walker, <tommowalker@tommowalker.co.uk>
* Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2008-2018 Sarah Walker.
* Copyright 2016-2018 Miran Grca.
*/
#include <math.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include "cpu.h"
#ifdef ENABLE_FPU_LOG
int fpu_do_log = ENABLE_FPU_LOG;
void
fpu_log(const char *fmt, ...)
{
va_list ap;
if (fpu_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define fpu_log(fmt, ...)
#endif
int
fpu_get_type(const cpu_family_t *cpu_family, int cpu, const char *internal_name)
{
const CPU *cpu_s = &cpu_family->cpus[cpu];
const FPU *fpus = cpu_s->fpus;
int fpu_type = fpus[0].type;
int c = 0;
while (fpus[c].internal_name) {
if (!strcmp(internal_name, fpus[c].internal_name))
fpu_type = fpus[c].type;
c++;
}
return fpu_type;
}
const char *
fpu_get_internal_name(const cpu_family_t *cpu_family, int cpu, int type)
{
const CPU *cpu_s = &cpu_family->cpus[cpu];
const FPU *fpus = cpu_s->fpus;
int c = 0;
while (fpus[c].internal_name) {
if (fpus[c].type == type)
return fpus[c].internal_name;
c++;
}
return fpus[0].internal_name;
}
const char *
fpu_get_name_from_index(const cpu_family_t *cpu_family, int cpu, int c)
{
const CPU *cpu_s = &cpu_family->cpus[cpu];
const FPU *fpus = cpu_s->fpus;
return fpus[c].name;
}
int
fpu_get_type_from_index(const cpu_family_t *cpu_family, int cpu, int c)
{
const CPU *cpu_s = &cpu_family->cpus[cpu];
const FPU *fpus = cpu_s->fpus;
return fpus[c].type;
}

315
src/cpu/x86.c Normal file
View File

@@ -0,0 +1,315 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Functions common to all emulated x86 CPU's.
*
* Authors: Andrew Jenner, <https://www.reenigne.org>
* Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2015-2020 Andrew Jenner.
* Copyright 2016-2020 Miran Grca.
*/
#include <math.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include "cpu.h"
#include "x86.h"
#include <86box/machine.h>
#include <86box/io.h>
#include <86box/mem.h>
#include <86box/rom.h>
#include <86box/nmi.h>
#include <86box/pic.h>
#include <86box/ppi.h>
#include <86box/timer.h>
/* The opcode of the instruction currently being executed. */
uint8_t opcode;
/* The tables to speed up the setting of the Z, N, and P cpu_state.flags. */
uint8_t znptable8[256];
uint16_t znptable16[65536];
/* A 16-bit zero, needed because some speed-up arrays contain pointers to it. */
uint16_t zero = 0;
/* MOD and R/M stuff. */
uint16_t *mod1add[2][8];
uint32_t *mod1seg[8];
uint32_t rmdat;
/* XT CPU multiplier. */
uint64_t xt_cpu_multi;
/* Variables for handling the non-maskable interrupts. */
int nmi = 0, nmi_auto_clear = 0;
/* Was the CPU ever reset? */
int x86_was_reset = 0;
/* Is the TRAP flag on? */
int trap = 0;
/* The current effective address's segment. */
uint32_t easeg;
#ifdef ENABLE_X86_LOG
void dumpregs(int);
int x86_do_log = ENABLE_X86_LOG;
int indump = 0;
static void
x808x_log(const char *fmt, ...)
{
va_list ap;
if (x808x_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
void
dumpregs(int force)
{
int c;
char *seg_names[4] = { "ES", "CS", "SS", "DS" };
/* Only dump when needed, and only once.. */
if (indump || (!force && !dump_on_exit))
return;
x808x_log("EIP=%08X CS=%04X DS=%04X ES=%04X SS=%04X FLAGS=%04X\n",
cpu_state.pc, CS, DS, ES, SS, cpu_state.flags);
x808x_log("Old CS:EIP: %04X:%08X; %i ins\n", oldcs, cpu_state.oldpc, ins);
for (c = 0; c < 4; c++) {
x808x_log("%s : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",
seg_names[c], _opseg[c]->base, _opseg[c]->limit,
_opseg[c]->access, _opseg[c]->limit_low, _opseg[c]->limit_high);
}
if (is386) {
x808x_log("FS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",
seg_fs, cpu_state.seg_fs.limit, cpu_state.seg_fs.access, cpu_state.seg_fs.limit_low, cpu_state.seg_fs.limit_high);
x808x_log("GS : base=%06X limit=%08X access=%02X limit_low=%08X limit_high=%08X\n",
gs, cpu_state.seg_gs.limit, cpu_state.seg_gs.access, cpu_state.seg_gs.limit_low, cpu_state.seg_gs.limit_high);
x808x_log("GDT : base=%06X limit=%04X\n", gdt.base, gdt.limit);
x808x_log("LDT : base=%06X limit=%04X\n", ldt.base, ldt.limit);
x808x_log("IDT : base=%06X limit=%04X\n", idt.base, idt.limit);
x808x_log("TR : base=%06X limit=%04X\n", tr.base, tr.limit);
x808x_log("386 in %s mode: %i-bit data, %-i-bit stack\n",
(msw & 1) ? ((cpu_state.eflags & VM_FLAG) ? "V86" : "protected") : "real",
(use32) ? 32 : 16, (stack32) ? 32 : 16);
x808x_log("CR0=%08X CR2=%08X CR3=%08X CR4=%08x\n", cr0, cr2, cr3, cr4);
x808x_log("EAX=%08X EBX=%08X ECX=%08X EDX=%08X\nEDI=%08X ESI=%08X EBP=%08X ESP=%08X\n",
EAX, EBX, ECX, EDX, EDI, ESI, EBP, ESP);
} else {
x808x_log("808x/286 in %s mode\n", (msw & 1) ? "protected" : "real");
x808x_log("AX=%04X BX=%04X CX=%04X DX=%04X DI=%04X SI=%04X BP=%04X SP=%04X\n",
AX, BX, CX, DX, DI, SI, BP, SP);
}
x808x_log("Entries in readlookup : %i writelookup : %i\n", readlnum, writelnum);
x87_dumpregs();
indump = 0;
}
#else
#define x808x_log(fmt, ...)
#endif
/* Preparation of the various arrays needed to speed up the MOD and R/M work. */
static void
makemod1table(void)
{
mod1add[0][0] = &BX;
mod1add[0][1] = &BX;
mod1add[0][2] = &BP;
mod1add[0][3] = &BP;
mod1add[0][4] = &SI;
mod1add[0][5] = &DI;
mod1add[0][6] = &BP;
mod1add[0][7] = &BX;
mod1add[1][0] = &SI;
mod1add[1][1] = &DI;
mod1add[1][2] = &SI;
mod1add[1][3] = &DI;
mod1add[1][4] = &zero;
mod1add[1][5] = &zero;
mod1add[1][6] = &zero;
mod1add[1][7] = &zero;
mod1seg[0] = &ds;
mod1seg[1] = &ds;
mod1seg[2] = &ss;
mod1seg[3] = &ss;
mod1seg[4] = &ds;
mod1seg[5] = &ds;
mod1seg[6] = &ss;
mod1seg[7] = &ds;
}
/* Prepare the ZNP table needed to speed up the setting of the Z, N, and P cpu_state.flags. */
static void
makeznptable(void)
{
int c, d, e;
for (c = 0; c < 256; c++) {
d = 0;
for (e = 0; e < 8; e++) {
if (c & (1 << e))
d++;
}
if (d & 1)
znptable8[c] = 0;
else
znptable8[c] = P_FLAG;
#ifdef ENABLE_808X_LOG
if (c == 0xb1)
x808x_log("znp8 b1 = %i %02X\n", d, znptable8[c]);
#endif
if (!c)
znptable8[c] |= Z_FLAG;
if (c & 0x80)
znptable8[c] |= N_FLAG;
}
for (c = 0; c < 65536; c++) {
d = 0;
for (e = 0; e < 8; e++) {
if (c & (1 << e))
d++;
}
if (d & 1)
znptable16[c] = 0;
else
znptable16[c] = P_FLAG;
#ifdef ENABLE_808X_LOG
if (c == 0xb1)
x808x_log("znp16 b1 = %i %02X\n", d, znptable16[c]);
if (c == 0x65b1)
x808x_log("znp16 65b1 = %i %02X\n", d, znptable16[c]);
#endif
if (!c)
znptable16[c] |= Z_FLAG;
if (c & 0x8000)
znptable16[c] |= N_FLAG;
}
}
/* Common reset function. */
static void
reset_common(int hard)
{
/* Make sure to gracefully leave SMM. */
if (in_smm)
leave_smm();
#ifdef ENABLE_808X_LOG
if (hard)
x808x_log("x86 reset\n");
#endif
use32 = 0;
cpu_cur_status = 0;
stack32 = 0;
msr.fcr = (1 << 8) | (1 << 9) | (1 << 12) | (1 << 16) | (1 << 19) | (1 << 21);
msw = 0;
if (hascache)
cr0 = 1 << 30;
else
cr0 = 0;
cpu_cache_int_enabled = 0;
cpu_update_waitstates();
cr4 = 0;
cpu_state.eflags = 0;
cgate32 = 0;
if (is286) {
if (AT) {
loadcs(0xF000);
cpu_state.pc = 0xFFF0;
rammask = cpu_16bitbus ? 0xFFFFFF : 0xFFFFFFFF;
} else {
loadcs(0xFFFF);
cpu_state.pc = 0;
rammask = 0xfffff;
}
}
idt.base = 0;
idt.limit = is386 ? 0x03FF : 0xFFFF;
cpu_state.flags = 2;
trap = 0;
EAX = EBX = ECX = EDX = ESI = EDI = EBP = ESP = 0;
if (hard) {
makeznptable();
resetreadlookup();
makemod1table();
cpu_set_edx();
mmu_perm = 4;
}
x86seg_reset();
#ifdef USE_DYNAREC
if (hard)
codegen_reset();
#endif
if (!hard)
flushmmucache();
x86_was_reset = 1;
cpu_alt_reset = 0;
cpu_ven_reset();
in_smm = smi_latched = 0;
smi_line = smm_in_hlt = 0;
smi_block = 0;
if (hard) {
smbase = is_am486 ? 0x00060000 : 0x00030000;
ppi_reset();
}
in_sys = 0;
shadowbios = shadowbios_write = 0;
alt_access = cpu_end_block_after_ins = 0;
if (!is286)
reset_808x(hard);
}
/* Hard reset. */
void
resetx86(void)
{
reset_common(1);
soft_reset_mask = 0;
}
/* Soft reset. */
void
softresetx86(void)
{
if (soft_reset_mask)
return;
reset_common(0);
}

View File

@@ -1059,8 +1059,9 @@ write_output(atkbd_t *dev, uint8_t val)
if ((dev->output_port ^ val) & 0x01) { /*Reset*/
if (! (val & 0x01)) {
/* Pin 0 selected. */
resetx86(); /*Pulse reset!*/
softresetx86(); /*Pulse reset!*/
cpu_set_edx();
smbase = is_am486 ? 0x00060000 : 0x00030000;
}
}
/* Mask off the A20 stuff because we use mem_a20_key directly for that. */