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).

This commit is contained in:
OBattler
2020-10-14 23:15:01 +02:00
parent 01362b3dc6
commit 795a6017d2
80 changed files with 2811 additions and 2163 deletions

View File

@@ -314,7 +314,7 @@ exec386(int cycs)
nmi_auto_clear = 0;
nmi = 0;
}
} else if ((cpu_state.flags & I_FLAG) && pic_intpending) {
} else if ((cpu_state.flags & I_FLAG) && pic.int_pending) {
vector = picinterrupt();
if (vector != -1) {
flags_rebuild();
@@ -341,7 +341,7 @@ exec386(int cycs)
}
if (TIMER_VAL_LESS_THAN_VAL(timer_target, (uint32_t) tsc))
timer_process();
timer_process_inline();
}
}
}

View File

@@ -16,6 +16,7 @@
#include "x87.h"
#include <86box/nmi.h>
#include <86box/mem.h>
#include <86box/smram.h>
#include <86box/pic.h>
#include <86box/pit.h>
#include <86box/fdd.h>
@@ -62,7 +63,7 @@ extern uint32_t pccache;
int in_sys = 0, unmask_a20_in_smm = 0;
uint32_t old_rammask = 0xffffffff;
smram_t temp_smram[2];
int soft_reset_mask = 0;
#define AMD_SYSCALL_EIP (star & 0xFFFFFFFF)
@@ -1026,14 +1027,8 @@ enter_smm(int in_hlt)
EAX, EBX, ECX, EDX, ESI, EDI, ESP, EBP);
in_smm = 1;
if (smram[0].size)
mem_mapping_recalc(smram[0].host_base, smram[0].size);
if (smram[1].size)
mem_mapping_recalc(smram[1].host_base, smram[1].size);
/* This is used by leave_smm() to make sure we don't keep the old mappings in SMM mode if the SMM
handler has told the chipset to change the actual mappings. */
memcpy(temp_smram, smram, sizeof(temp_smram));
flushmmucache();
smram_backup_all();
smram_recalc_all(0);
memset(saved_state, 0x00, SMM_SAVE_STATE_MAP_SIZE * sizeof(uint32_t));
@@ -1173,16 +1168,7 @@ leave_smm(void)
smram_restore_state_p6(saved_state);
in_smm = 0;
if (temp_smram[0].size)
mem_mapping_recalc(temp_smram[0].host_base, temp_smram[0].size);
if (temp_smram[1].size)
mem_mapping_recalc(temp_smram[1].host_base, temp_smram[1].size);
memset(temp_smram, 0x00, sizeof(temp_smram));
if (smram[0].size)
mem_mapping_recalc(smram[0].host_base, smram[0].size);
if (smram[1].size)
mem_mapping_recalc(smram[1].host_base, smram[1].size);
flushmmucache();
smram_recalc_all(1);
cpu_state.op32 = use32;

View File

@@ -391,7 +391,7 @@ void exec386_dynarec(int cycs)
CPU_BLOCK_END();
else if (nmi && nmi_enable && nmi_mask)
CPU_BLOCK_END();
else if ((cpu_state.flags & I_FLAG) && pic_intpending)
else if ((cpu_state.flags & I_FLAG) && pic.int_pending)
CPU_BLOCK_END();
}
}
@@ -626,7 +626,7 @@ void exec386_dynarec(int cycs)
CPU_BLOCK_END();
else if (nmi && nmi_enable && nmi_mask)
CPU_BLOCK_END();
else if ((cpu_state.flags & I_FLAG) && pic_intpending)
else if ((cpu_state.flags & I_FLAG) && pic.int_pending)
CPU_BLOCK_END();
}
@@ -715,7 +715,7 @@ void exec386_dynarec(int cycs)
CPU_BLOCK_END();
else if (nmi && nmi_enable && nmi_mask)
CPU_BLOCK_END();
else if ((cpu_state.flags & I_FLAG) && pic_intpending)
else if ((cpu_state.flags & I_FLAG) && pic.int_pending)
CPU_BLOCK_END();
}
@@ -813,7 +813,7 @@ void exec386_dynarec(int cycs)
nmi = 0;
}
}
else if ((cpu_state.flags & I_FLAG) && pic_intpending)
else if ((cpu_state.flags & I_FLAG) && pic.int_pending)
{
vector = picinterrupt();
if (vector != -1)

View File

@@ -9,13 +9,11 @@
* 808x CPU emulation, mostly ported from reenigne's XTCE, which
* is cycle-accurate.
*
*
*
* Authors: Andrew Jenner, <https://www.reenigne.org>
* Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2015-2019 Andrew Jenner.
* Copyright 2016-2019 Miran Grca.
* Copyright 2015-2020 Andrew Jenner.
* Copyright 2016-2020 Miran Grca.
*/
#include <math.h>
#include <stdarg.h>
@@ -91,15 +89,16 @@ static int noint = 0;
static int in_lock = 0;
static int cpu_alu_op, pfq_size;
static uint16_t cpu_src = 0, cpu_dest = 0;
static uint16_t cpu_data = 0, last_addr = 0x0000;
static uint32_t cpu_src = 0, cpu_dest = 0;
static uint32_t cpu_data = 0;
static uint16_t last_addr = 0x0000;
static uint32_t *ovr_seg = NULL;
static int prefetching = 1, completed = 1;
static int in_rep = 0, repeating = 0;
static int oldc, clear_lock = 0;
static int refresh = 0, takeint = 0;
static int cycdiff;
static int refresh = 0, cycdiff;
/* Various things needed for 8087. */
@@ -209,22 +208,6 @@ get_last_addr(void)
}
static int
irq_pending(void)
{
uint8_t temp;
if (takeint && !noint)
temp = 1;
else
temp = (nmi && nmi_enable && nmi_mask) || ((cpu_state.flags & T_FLAG) && !noint);
takeint = (cpu_state.flags & I_FLAG) && (pic.pend &~ pic.mask);
return temp;
}
static void
clock_start(void)
{
@@ -232,7 +215,7 @@ clock_start(void)
}
static void
static void
clock_end(void)
{
int diff = cycdiff - cycles;
@@ -294,20 +277,14 @@ sub_cycles(int c)
#undef readmeml
#undef readmemq
/* Common read function. */
static uint8_t
readmemb_common(uint32_t a)
{
uint8_t ret;
if (readlookup2 == NULL)
ret = readmembl(a);
else {
if (readlookup2[(a) >> 12] == ((uintptr_t) -1))
ret = readmembl(a);
else
ret = *(uint8_t *)(readlookup2[(a) >> 12] + (a));
}
ret = read_mem_b(a);
return ret;
}
@@ -414,14 +391,7 @@ readmemq(uint32_t s, uint16_t a)
static void
writememb_common(uint32_t a, uint8_t v)
{
if (writelookup2 == NULL)
writemembl(a, v);
else {
if (writelookup2[(a) >> 12] == ((uintptr_t) -1))
writemembl(a, v);
else
*(uint8_t *)(writelookup2[a >> 12] + a) = v;
}
write_mem_b(a, v);
if ((a >= 0xf0000) && (a <= 0xfffff))
last_addr = a & 0xffff;
@@ -896,6 +866,13 @@ makeznptable(void)
}
static void load_cs(uint16_t seg)
{
cpu_state.seg_cs.base = seg << 4;
CS = seg & 0xffff;
}
/* Common reset function. */
static void
reset_common(int hard)
@@ -933,11 +910,11 @@ reset_common(int hard)
cpu_state.eflags = 0;
cgate32 = 0;
if (AT) {
loadcs(0xF000);
load_cs(0xF000);
cpu_state.pc = 0xFFF0;
rammask = cpu_16bitbus ? 0xFFFFFF : 0xFFFFFFFF;
} else {
loadcs(0xFFFF);
load_cs(0xFFFF);
cpu_state.pc = 0;
rammask = 0xfffff;
}
@@ -969,7 +946,6 @@ reset_common(int hard)
cpu_alt_reset = 0;
prefetching = 1;
takeint = 0;
cpu_ven_reset();
@@ -994,6 +970,8 @@ void
resetx86(void)
{
reset_common(1);
soft_reset_mask = 0;
}
@@ -1001,6 +979,9 @@ resetx86(void)
void
softresetx86(void)
{
if (soft_reset_mask)
return;
reset_common(0);
}
@@ -1125,7 +1106,9 @@ interrupt(uint16_t addr)
cpu_state.eaaddr = (cpu_state.eaaddr + 2) & 0xffff;
access(6, 16);
new_cs = readmemw(0, cpu_state.eaaddr);
prefetching = 0;
pfq_clear();
ovr_seg = NULL;
access(39, 16);
tempf = cpu_state.flags & 0x0fd7;
push(&tempf);
@@ -1133,7 +1116,7 @@ interrupt(uint16_t addr)
access(40, 16);
push(&old_cs);
old_ip = cpu_state.pc;
loadcs(new_cs);
load_cs(new_cs);
access(68, 16);
set_ip(new_ip);
access(41, 16);
@@ -1141,6 +1124,20 @@ interrupt(uint16_t addr)
}
static int
irq_pending(void)
{
uint8_t temp;
if ((cpu_state.flags & I_FLAG) && pic.int_pending && !noint)
temp = 1;
else
temp = (nmi && nmi_enable && nmi_mask) || ((cpu_state.flags & T_FLAG) && !noint);
return temp;
}
static void
check_interrupts(void)
{
@@ -1156,16 +1153,24 @@ check_interrupts(void)
interrupt(2);
return;
}
temp = picinterrupt();
if (temp != -1) {
if ((cpu_state.flags & I_FLAG) && pic.int_pending && !noint) {
repeating = 0;
completed = 1;
ovr_seg = NULL;
wait(3, 0);
/* ACK to PIC */
temp = pic_irq_ack();
wait(1, 0);
/* ACK to PIC */
temp = pic_irq_ack();
wait(1, 0);
in_lock = 0;
clear_lock = 0;
ovr_seg = NULL;
wait(9, 0);
interrupt((uint16_t) (temp & 0xffff));
wait(1, 0);
/* Here is where temp should be filled, but we cheat. */
wait(3, 0);
opcode = 0x00;
interrupt(temp);
}
}
}
@@ -1511,6 +1516,7 @@ mul(uint16_t a, uint16_t b)
set_sf(bit_count);
set_pf();
set_af(0);
}
@@ -1521,12 +1527,19 @@ set_of_rotate(int bits)
}
static void
set_zf_ex(int bits, int zf)
{
cpu_state.flags = (cpu_state.flags & ~0x40) | (zf ? 0x40 : 0);
}
static void
set_zf(int bits)
{
int size_mask = (1 << bits) - 1;
cpu_state.flags = (cpu_state.flags & ~0x40) | (((cpu_data & size_mask) == 0) ? 0x40 : 0);
set_zf_ex(bits, (cpu_data & size_mask) == 0);
}
@@ -1544,6 +1557,9 @@ set_co_mul(int carry)
{
set_cf(carry);
set_of(carry);
/* NOTE: When implementing the V20, care should be taken to not change
the zero flag. */
set_zf(!carry);
if (!carry)
wait(1, 0);
}
@@ -1693,8 +1709,8 @@ stos(int bits)
static void
aa(void)
{
set_of(0);
AL &= 0x0f;
set_pzs(8);
AL = cpu_data & 0x0f;
wait(6, 0);
}
@@ -1771,6 +1787,7 @@ void
execx86(int cycs)
{
uint8_t temp = 0, temp2;
uint8_t old_af;
uint16_t addr, tempw;
uint16_t new_cs, new_ip;
uint32_t result;
@@ -1793,6 +1810,7 @@ execx86(int cycs)
}
completed = 1;
// pclog("[%04X:%04X] Opcode: %02X\n", CS, cpu_state.pc, opcode);
switch (opcode) {
case 0x06: case 0x0E: case 0x16: case 0x1E: /* PUSH seg */
access(29, 16);
@@ -1801,7 +1819,7 @@ execx86(int cycs)
case 0x07: case 0x0F: case 0x17: case 0x1F: /* POP seg */
access(22, 16);
if (opcode == 0x0F) {
loadcs(pop());
load_cs(pop());
pfq_pos = 0;
} else
loadseg(pop(), _opseg[(opcode >> 3) & 0x03]);
@@ -1878,15 +1896,15 @@ execx86(int cycs)
case 0x27: /*DAA*/
cpu_dest = AL;
set_of(0);
temp = !!(cpu_state.flags & A_FLAG);
old_af = !!(cpu_state.flags & A_FLAG);
if ((cpu_state.flags & A_FLAG) || (AL & 0x0f) > 9) {
cpu_src = 6;
cpu_data = cpu_dest + cpu_src;
set_of_add(8);
cpu_dest = cpu_data;
cpu_dest += cpu_data;
set_af(1);
}
if ((cpu_state.flags & C_FLAG) || AL > (temp ? 0x9f : 0x99)) {
if ((cpu_state.flags & C_FLAG) || AL > (old_af ? 0x9f : 0x99)) {
cpu_src = 0x60;
cpu_data = cpu_dest + cpu_src;
set_of_add(8);
@@ -1900,15 +1918,15 @@ execx86(int cycs)
case 0x2F: /*DAS*/
cpu_dest = AL;
set_of(0);
temp = !!(cpu_state.flags & A_FLAG);
if ((cpu_state.flags & A_FLAG) || ((AL & 0xf) > 9)) {
old_af = !!(cpu_state.flags & A_FLAG);
if ((cpu_state.flags & A_FLAG) || (AL & 0xf) > 9) {
cpu_src = 6;
cpu_data = cpu_dest - cpu_src;
set_of_sub(8);
cpu_dest = cpu_data;
set_af(1);
}
if ((cpu_state.flags & C_FLAG) || AL > (temp ? 0x9f : 0x99)) {
if ((cpu_state.flags & C_FLAG) || AL > (old_af ? 0x9f : 0x99)) {
cpu_src = 0x60;
cpu_data = cpu_dest - cpu_src;
set_of_sub(8);
@@ -1921,7 +1939,7 @@ execx86(int cycs)
break;
case 0x37: /*AAA*/
wait(1, 0);
if ((cpu_state.flags & A_FLAG) || ((AL & 0xf) > 9)) {
if ((cpu_state.flags & A_FLAG) || (AL & 0xf) > 9) {
cpu_src = 6;
++AH;
set_ca();
@@ -1932,13 +1950,12 @@ execx86(int cycs)
}
cpu_dest = AL;
cpu_data = cpu_dest + cpu_src;
AL = cpu_data;
set_of_add(8);
aa();
break;
case 0x3F: /*AAS*/
wait(1, 0);
if ((cpu_state.flags & A_FLAG) || ((AL & 0xf) > 9)) {
if ((cpu_state.flags & A_FLAG) || (AL & 0xf) > 9) {
cpu_src = 6;
--AH;
set_ca();
@@ -1949,7 +1966,6 @@ execx86(int cycs)
}
cpu_dest = AL;
cpu_data = cpu_dest - cpu_src;
AL = cpu_data;
set_of_sub(8);
aa();
break;
@@ -2137,7 +2153,7 @@ execx86(int cycs)
access(51, 16);
tempw = geteaw();
if ((rmdat & 0x18) == 0x08) {
loadcs(tempw);
load_cs(tempw);
pfq_pos = 0;
} else
loadseg(tempw, _opseg[(rmdat & 0x18) >> 3]);
@@ -2195,7 +2211,7 @@ execx86(int cycs)
push(&(CS));
access(60, 16);
cpu_state.oldpc = cpu_state.pc;
loadcs(new_cs);
load_cs(new_cs);
set_ip(new_ip);
access(32, 16);
push((uint16_t *) &(cpu_state.oldpc));
@@ -2407,7 +2423,7 @@ execx86(int cycs)
SP += cpu_src;
wait(1, 0);
}
loadcs(new_cs);
load_cs(new_cs);
access(72, bits);
set_ip(new_ip);
break;
@@ -2460,7 +2476,7 @@ execx86(int cycs)
wait(3, 0);
access(44, 8);
new_cs = pop();
loadcs(new_cs);
load_cs(new_cs);
access(62, 8);
set_ip(new_ip);
access(45, 8);
@@ -2494,6 +2510,7 @@ execx86(int cycs)
cpu_data <<= 1;
cpu_data |= ((cpu_state.flags & C_FLAG) ? 1 : 0);
set_of_rotate(bits);
set_af(0);
break;
case 0x08: /* ROR */
set_cf((cpu_data & 1) != 0);
@@ -2501,11 +2518,13 @@ execx86(int cycs)
if (cpu_state.flags & C_FLAG)
cpu_data |= (!(opcode & 1) ? 0x80 : 0x8000);
set_of_rotate(bits);
set_af(0);
break;
case 0x10: /* RCL */
set_cf(top_bit(cpu_data, bits));
cpu_data = (cpu_data << 1) | (oldc ? 1 : 0);
set_of_rotate(bits);
set_af(0);
break;
case 0x18: /* RCR */
set_cf((cpu_data & 1) != 0);
@@ -2514,18 +2533,20 @@ execx86(int cycs)
cpu_data |= (!(opcode & 0x01) ? 0x80 : 0x8000);
set_cf((cpu_dest & 1) != 0);
set_of_rotate(bits);
set_af(0);
break;
case 0x20: /* SHL */
set_cf(top_bit(cpu_data, bits));
cpu_data <<= 1;
set_of_rotate(bits);
set_af((cpu_data & 0x10) != 0);
set_pzs(bits);
break;
case 0x28: /* SHR */
set_cf((cpu_data & 1) != 0);
cpu_data >>= 1;
set_of_rotate(bits);
set_af(1);
set_af(0);
set_pzs(bits);
break;
case 0x30: /* SETMO - undocumented? */
@@ -2543,7 +2564,7 @@ execx86(int cycs)
else
cpu_data |= (cpu_dest & 0x8000);
set_of_rotate(bits);
set_af(1);
set_af(0);
set_pzs(bits);
break;
}
@@ -2564,9 +2585,11 @@ execx86(int cycs)
case 0xD5: /*AAD*/
wait(1, 0);
mul(pfq_fetchb(), AH);
AL += cpu_data;
cpu_dest = AL;
cpu_src = cpu_data;
add(8);
AL = cpu_data;
AH = 0x00;
set_pzs(16);
break;
case 0xD6: /*SALC*/
wait(1, 0);
@@ -2700,7 +2723,7 @@ execx86(int cycs)
addr = pfq_fetchw();
wait(1, 0);
tempw = pfq_fetchw();
loadcs(tempw);
load_cs(tempw);
access(70, 8);
pfq_clear();
set_ip(addr);
@@ -2783,25 +2806,24 @@ execx86(int cycs)
mul(AX, cpu_data);
AX = cpu_data;
DX = cpu_dest;
cpu_data |= DX;
result = ((uint32_t) DX << 16) | AX;
if ((rmdat & 0x38) == 0x20)
set_co_mul(DX != 0x0000);
else
set_co_mul(result != sign_extend32(AX));
cpu_data = DX;
} else {
mul(AL, cpu_data);
AL = (uint8_t) cpu_data;
AH = (uint8_t) cpu_dest;
cpu_data |= AH;
if ((rmdat & 0x38) == 0x20)
set_co_mul(AH != 0x00);
else
set_co_mul(AX != sign_extend(AL));
cpu_data = AH;
}
/* NOTE: When implementing the V20, care should be taken to not change
the zero flag. */
set_zf(bits);
set_sf(bits);
set_pf();
if (cpu_mod != 3)
wait(1, 0);
break;
@@ -2883,7 +2905,7 @@ execx86(int cycs)
access(64, bits);
wait(4, 0);
cpu_state.oldpc = cpu_state.pc;
loadcs(new_cs);
load_cs(new_cs);
set_ip(new_ip);
access(37, bits);
push((uint16_t *) &(cpu_state.oldpc));
@@ -2900,7 +2922,7 @@ execx86(int cycs)
if (!(opcode & 1))
cpu_data |= 0xff00;
new_cs = cpu_data;
loadcs(new_cs);
load_cs(new_cs);
access(66, bits);
set_ip(new_ip);
break;
@@ -2909,7 +2931,7 @@ execx86(int cycs)
if (cpu_mod != 3)
wait(1, 0);
access(38, bits);
push(&(cpu_data));
push((uint16_t *) &(cpu_data));
break;
}
break;

View File

@@ -492,6 +492,7 @@ extern uint32_t old_rammask;
extern int acycs;
#endif
extern int pic_pending, is_vpc;
extern int soft_reset_mask;
extern uint16_t cpu_fast_off_count, cpu_fast_off_val;
extern uint32_t cpu_fast_off_flags;

View File

@@ -614,10 +614,10 @@ static int opHLT(uint32_t fetchdat)
}
if (smi_line)
enter_smm_check(1);
else if (!((cpu_state.flags & I_FLAG) && pic_intpending))
else if (!((cpu_state.flags & I_FLAG) && pic.int_pending))
{
CLOCK_CYCLES_ALWAYS(100);
if (!((cpu_state.flags & I_FLAG) && pic_intpending))
if (!((cpu_state.flags & I_FLAG) && pic.int_pending))
cpu_state.pc--;
}
else

View File

@@ -12,6 +12,12 @@ static int opMOV_r_CRx_a16(uint32_t fetchdat)
cpu_state.regs[cpu_rm].l = cr0;
if (is486 || isibm486)
cpu_state.regs[cpu_rm].l |= 0x10; /*ET hardwired on 486*/
else {
if (is386)
cpu_state.regs[cpu_rm].l |=0x7fffffe0;
else
cpu_state.regs[cpu_rm].l |=0x7ffffff0;
}
break;
case 2:
cpu_state.regs[cpu_rm].l = cr2;
@@ -48,6 +54,12 @@ static int opMOV_r_CRx_a32(uint32_t fetchdat)
cpu_state.regs[cpu_rm].l = cr0;
if (is486 || isibm486)
cpu_state.regs[cpu_rm].l |= 0x10; /*ET hardwired on 486*/
else {
if (is386)
cpu_state.regs[cpu_rm].l |=0x7fffffe0;
else
cpu_state.regs[cpu_rm].l |=0x7ffffff0;
}
break;
case 2:
cpu_state.regs[cpu_rm].l = cr2;

View File

@@ -371,7 +371,7 @@ static int op0F01_common(uint32_t fetchdat, int is32, int is286, int ea32)
if (cpu_mod != 3)
SEG_CHECK_WRITE(cpu_state.ea_seg);
if (is486 || isibm486) seteaw(msw);
else if (is386) seteaw(msw | 0xFF00);
else if (is386) seteaw(msw | /* 0xFF00 */ 0xFFE0);
else seteaw(msw | 0xFFF0);
CLOCK_CYCLES(2);
PREFETCH_RUN(2, 2, rmdat, 0,0,(cpu_mod == 3) ? 0:1,0, ea32);