mirror of
https://github.com/86Box/86Box.git
synced 2026-02-22 17:45:31 -07:00
Merge remote-tracking branch 'origin/master' into version/4.1
This commit is contained in:
21
.gitattributes
vendored
Normal file
21
.gitattributes
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
# Set the default behavior, in case people don't have core.autocrlf set.
|
||||
* text=auto
|
||||
|
||||
# Explicitly declare text files you want to always be normalized and converted
|
||||
# to native line endings on checkout.
|
||||
*.c text
|
||||
*.cc text
|
||||
*.cpp text
|
||||
*.h text
|
||||
*.hpp text
|
||||
*.rc text
|
||||
|
||||
|
||||
# Declare files that will always have CRLF line endings on checkout.
|
||||
*.sln text eol=crlf
|
||||
|
||||
# Denote all files that are truly binary and should not be modified.
|
||||
*.ico binary
|
||||
*.png binary
|
||||
*.jpg binary
|
||||
*.dat
|
||||
206
src/cpu/386.c
206
src/cpu/386.c
@@ -12,17 +12,22 @@
|
||||
#define HAVE_STDARG_H
|
||||
#include <86box/86box.h>
|
||||
#include "cpu.h"
|
||||
#include <86box/timer.h>
|
||||
#include "x86.h"
|
||||
#include "x86_ops.h"
|
||||
#include "x87.h"
|
||||
#include <86box/io.h>
|
||||
#include <86box/nmi.h>
|
||||
#include <86box/mem.h>
|
||||
#include <86box/pic.h>
|
||||
#include <86box/timer.h>
|
||||
#include <86box/pit.h>
|
||||
#include <86box/fdd.h>
|
||||
#include <86box/fdc.h>
|
||||
#include <86box/machine.h>
|
||||
#include <86box/gdbstub.h>
|
||||
#ifndef OPS_286_386
|
||||
#define OPS_286_386
|
||||
#endif
|
||||
#include "386_common.h"
|
||||
#ifdef USE_NEW_DYNAREC
|
||||
# include "codegen.h"
|
||||
@@ -33,54 +38,7 @@
|
||||
|
||||
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;
|
||||
|
||||
#if 1
|
||||
int opcode_length[256] = { 3, 3, 3, 3, 3, 3, 1, 1, 3, 3, 3, 3, 3, 3, 1, 3, /* 0x0x */
|
||||
3, 3, 3, 3, 3, 3, 1, 1, 3, 3, 3, 3, 3, 3, 1, 1, /* 0x1x */
|
||||
3, 3, 3, 3, 3, 3, 1, 1, 3, 3, 3, 3, 3, 3, 1, 1, /* 0x2x */
|
||||
3, 3, 3, 3, 3, 3, 1, 1, 3, 3, 3, 3, 3, 3, 1, 1, /* 0x3x */
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x4x */
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x5x */
|
||||
1, 1, 3, 3, 1, 1, 1, 1, 3, 3, 2, 3, 1, 1, 1, 1, /* 0x6x */
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0x7x */
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0x8x */
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, /* 0x9x */
|
||||
3, 3, 3, 3, 1, 1, 1, 1, 2, 3, 1, 1, 1, 1, 1, 1, /* 0xax */
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, /* 0xbx */
|
||||
3, 3, 3, 1, 3, 3, 3, 3, 3, 1, 3, 1, 1, 2, 1, 1, /* 0xcx */
|
||||
3, 3, 3, 3, 2, 2, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, /* 0xdx */
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 2, 1, 1, 1, 1, /* 0xex */
|
||||
1, 1, 1, 1, 1, 1, 3, 3, 1, 1, 1, 1, 1, 1, 3, 3 }; /* 0xfx */
|
||||
#else
|
||||
int opcode_length[256] = { 3, 3, 3, 3, 3, 3, 1, 1, 3, 3, 3, 3, 3, 3, 1, 3, /* 0x0x */
|
||||
3, 3, 3, 3, 3, 3, 1, 1, 3, 3, 3, 3, 3, 3, 1, 1, /* 0x1x */
|
||||
3, 3, 3, 3, 3, 3, 3, 1, 3, 3, 3, 3, 3, 3, 3, 1, /* 0x2x */
|
||||
3, 3, 3, 3, 3, 3, 3, 1, 3, 3, 3, 3, 3, 3, 3, 1, /* 0x3x */
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x4x */
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x5x */
|
||||
1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 2, 3, 1, 1, 1, 1, /* 0x6x */
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0x7x */
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0x8x */
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, /* 0x9x */
|
||||
3, 3, 3, 3, 1, 1, 1, 1, 2, 3, 1, 1, 1, 1, 1, 1, /* 0xax */
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, /* 0xbx */
|
||||
3, 3, 3, 1, 3, 3, 3, 3, 3, 1, 3, 1, 1, 2, 1, 1, /* 0xcx */
|
||||
3, 3, 3, 3, 2, 2, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, /* 0xdx */
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 2, 1, 1, 1, 1, /* 0xex */
|
||||
3, 1, 3, 3, 1, 1, 3, 3, 1, 1, 1, 1, 1, 1, 3, 3 }; /* 0xfx */
|
||||
#endif
|
||||
static int fpu_cycles = 0;
|
||||
|
||||
#ifdef ENABLE_386_LOG
|
||||
int x386_do_log = ENABLE_386_LOG;
|
||||
@@ -103,9 +61,6 @@ x386_log(const char *fmt, ...)
|
||||
#undef CPU_BLOCK_END
|
||||
#define CPU_BLOCK_END()
|
||||
|
||||
#include "x86_flags.h"
|
||||
|
||||
/*
|
||||
#define getbytef() \
|
||||
((uint8_t) (fetchdat)); \
|
||||
cpu_state.pc++
|
||||
@@ -118,11 +73,141 @@ x386_log(const char *fmt, ...)
|
||||
#define getword2f() \
|
||||
((uint16_t) (fetchdat >> 8)); \
|
||||
cpu_state.pc += 2
|
||||
*/
|
||||
|
||||
#define OP_TABLE(name) ops_##name
|
||||
static __inline void
|
||||
fetch_ea_32_long(uint32_t rmdat)
|
||||
{
|
||||
eal_r = eal_w = NULL;
|
||||
easeg = cpu_state.ea_seg->base;
|
||||
if (cpu_rm == 4) {
|
||||
uint8_t sib = rmdat >> 8;
|
||||
|
||||
#if 0
|
||||
switch (cpu_mod) {
|
||||
case 0:
|
||||
cpu_state.eaaddr = cpu_state.regs[sib & 7].l;
|
||||
cpu_state.pc++;
|
||||
break;
|
||||
case 1:
|
||||
cpu_state.pc++;
|
||||
cpu_state.eaaddr = ((uint32_t) (int8_t) getbyte()) + cpu_state.regs[sib & 7].l;
|
||||
break;
|
||||
case 2:
|
||||
cpu_state.eaaddr = (fastreadl(cs + cpu_state.pc + 1)) + cpu_state.regs[sib & 7].l;
|
||||
cpu_state.pc += 5;
|
||||
break;
|
||||
}
|
||||
/*SIB byte present*/
|
||||
if ((sib & 7) == 5 && !cpu_mod)
|
||||
cpu_state.eaaddr = getlong();
|
||||
else if ((sib & 6) == 4 && !cpu_state.ssegs) {
|
||||
easeg = ss;
|
||||
cpu_state.ea_seg = &cpu_state.seg_ss;
|
||||
}
|
||||
if (((sib >> 3) & 7) != 4)
|
||||
cpu_state.eaaddr += cpu_state.regs[(sib >> 3) & 7].l << (sib >> 6);
|
||||
} else {
|
||||
cpu_state.eaaddr = cpu_state.regs[cpu_rm].l;
|
||||
if (cpu_mod) {
|
||||
if (cpu_rm == 5 && !cpu_state.ssegs) {
|
||||
easeg = ss;
|
||||
cpu_state.ea_seg = &cpu_state.seg_ss;
|
||||
}
|
||||
if (cpu_mod == 1) {
|
||||
cpu_state.eaaddr += ((uint32_t) (int8_t) (rmdat >> 8));
|
||||
cpu_state.pc++;
|
||||
} else {
|
||||
cpu_state.eaaddr += getlong();
|
||||
}
|
||||
} else if (cpu_rm == 5) {
|
||||
cpu_state.eaaddr = getlong();
|
||||
}
|
||||
}
|
||||
if (easeg != 0xFFFFFFFF && ((easeg + cpu_state.eaaddr) & 0xFFF) <= 0xFFC) {
|
||||
uint32_t addr = easeg + cpu_state.eaaddr;
|
||||
if (readlookup2[addr >> 12] != (uintptr_t) -1)
|
||||
eal_r = (uint32_t *) (readlookup2[addr >> 12] + addr);
|
||||
if (writelookup2[addr >> 12] != (uintptr_t) -1)
|
||||
eal_w = (uint32_t *) (writelookup2[addr >> 12] + addr);
|
||||
}
|
||||
}
|
||||
|
||||
static __inline void
|
||||
fetch_ea_16_long(uint32_t rmdat)
|
||||
{
|
||||
eal_r = eal_w = NULL;
|
||||
easeg = cpu_state.ea_seg->base;
|
||||
if (!cpu_mod && cpu_rm == 6) {
|
||||
cpu_state.eaaddr = getword();
|
||||
} else {
|
||||
switch (cpu_mod) {
|
||||
case 0:
|
||||
cpu_state.eaaddr = 0;
|
||||
break;
|
||||
case 1:
|
||||
cpu_state.eaaddr = (uint16_t) (int8_t) (rmdat >> 8);
|
||||
cpu_state.pc++;
|
||||
break;
|
||||
case 2:
|
||||
cpu_state.eaaddr = getword();
|
||||
break;
|
||||
}
|
||||
cpu_state.eaaddr += (*mod1add[0][cpu_rm]) + (*mod1add[1][cpu_rm]);
|
||||
if (mod1seg[cpu_rm] == &ss && !cpu_state.ssegs) {
|
||||
easeg = ss;
|
||||
cpu_state.ea_seg = &cpu_state.seg_ss;
|
||||
}
|
||||
cpu_state.eaaddr &= 0xFFFF;
|
||||
}
|
||||
if (easeg != 0xFFFFFFFF && ((easeg + cpu_state.eaaddr) & 0xFFF) <= 0xFFC) {
|
||||
uint32_t addr = easeg + cpu_state.eaaddr;
|
||||
if (readlookup2[addr >> 12] != (uintptr_t) -1)
|
||||
eal_r = (uint32_t *) (readlookup2[addr >> 12] + addr);
|
||||
if (writelookup2[addr >> 12] != (uintptr_t) -1)
|
||||
eal_w = (uint32_t *) (writelookup2[addr >> 12] + addr);
|
||||
}
|
||||
}
|
||||
|
||||
#define fetch_ea_16(rmdat) \
|
||||
cpu_state.pc++; \
|
||||
cpu_mod = (rmdat >> 6) & 3; \
|
||||
cpu_reg = (rmdat >> 3) & 7; \
|
||||
cpu_rm = rmdat & 7; \
|
||||
if (cpu_mod != 3) { \
|
||||
fetch_ea_16_long(rmdat); \
|
||||
if (cpu_state.abrt) \
|
||||
return 1; \
|
||||
}
|
||||
#define fetch_ea_32(rmdat) \
|
||||
cpu_state.pc++; \
|
||||
cpu_mod = (rmdat >> 6) & 3; \
|
||||
cpu_reg = (rmdat >> 3) & 7; \
|
||||
cpu_rm = rmdat & 7; \
|
||||
if (cpu_mod != 3) { \
|
||||
fetch_ea_32_long(rmdat); \
|
||||
} \
|
||||
if (cpu_state.abrt) \
|
||||
return 1
|
||||
|
||||
#include "x86_flags.h"
|
||||
|
||||
#define PREFETCH_RUN(instr_cycles, bytes, modrm, reads, reads_l, writes, writes_l, ea32) \
|
||||
do { \
|
||||
if (cpu_prefetch_cycles) \
|
||||
prefetch_run(instr_cycles, bytes, modrm, reads, reads_l, writes, writes_l, ea32); \
|
||||
} while (0)
|
||||
|
||||
#define PREFETCH_PREFIX() \
|
||||
do { \
|
||||
if (cpu_prefetch_cycles) \
|
||||
prefetch_prefixes++; \
|
||||
} while (0)
|
||||
#define PREFETCH_FLUSH() prefetch_flush()
|
||||
|
||||
#ifndef FPU_CYCLES
|
||||
#define FPU_CYCLES
|
||||
#endif
|
||||
|
||||
#define OP_TABLE(name) ops_2386_##name
|
||||
# define CLOCK_CYCLES(c) \
|
||||
{ \
|
||||
if (fpu_cycles > 0) { \
|
||||
@@ -137,18 +222,13 @@ x386_log(const char *fmt, ...)
|
||||
|
||||
# define CLOCK_CYCLES_FPU(c) cycles -= (c)
|
||||
# define CONCURRENCY_CYCLES(c) fpu_cycles = (c)
|
||||
#else
|
||||
# define CLOCK_CYCLES(c) cycles -= (c)
|
||||
# define CLOCK_CYCLES_FPU(c) cycles -= (c)
|
||||
# define CONCURRENCY_CYCLES(c)
|
||||
#endif
|
||||
|
||||
#define CLOCK_CYCLES_ALWAYS(c) cycles -= (c)
|
||||
|
||||
#include "x86_ops.h"
|
||||
#include "386_ops.h"
|
||||
|
||||
void
|
||||
exec386(int cycs)
|
||||
exec386_2386(int cycs)
|
||||
{
|
||||
int vector, tempi, cycdiff, oldcyc;
|
||||
int cycle_period, ins_cycles;
|
||||
@@ -184,7 +264,7 @@ exec386(int cycs)
|
||||
if (!cpu_state.abrt) {
|
||||
#ifdef ENABLE_386_LOG
|
||||
if (in_smm)
|
||||
x386_log("[%04X:%08X] %08X\n", CS, cpu_state.pc, fetchdat);
|
||||
x386_2386_log("[%04X:%08X] %08X\n", CS, cpu_state.pc, fetchdat);
|
||||
#endif
|
||||
opcode = fetchdat & 0xFF;
|
||||
fetchdat >>= 8;
|
||||
|
||||
@@ -67,6 +67,38 @@ int soft_reset_mask = 0;
|
||||
int smi_latched = 0;
|
||||
int smm_in_hlt = 0, smi_block = 0;
|
||||
|
||||
int prefetch_prefixes = 0;
|
||||
|
||||
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;
|
||||
|
||||
int opcode_length[256] = { 3, 3, 3, 3, 3, 3, 1, 1, 3, 3, 3, 3, 3, 3, 1, 3, /* 0x0x */
|
||||
3, 3, 3, 3, 3, 3, 1, 1, 3, 3, 3, 3, 3, 3, 1, 1, /* 0x1x */
|
||||
3, 3, 3, 3, 3, 3, 1, 1, 3, 3, 3, 3, 3, 3, 1, 1, /* 0x2x */
|
||||
3, 3, 3, 3, 3, 3, 1, 1, 3, 3, 3, 3, 3, 3, 1, 1, /* 0x3x */
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x4x */
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0x5x */
|
||||
1, 1, 3, 3, 1, 1, 1, 1, 3, 3, 2, 3, 1, 1, 1, 1, /* 0x6x */
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0x7x */
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0x8x */
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, /* 0x9x */
|
||||
3, 3, 3, 3, 1, 1, 1, 1, 2, 3, 1, 1, 1, 1, 1, 1, /* 0xax */
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, /* 0xbx */
|
||||
3, 3, 3, 1, 3, 3, 3, 3, 3, 1, 3, 1, 1, 2, 1, 1, /* 0xcx */
|
||||
3, 3, 3, 3, 2, 2, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, /* 0xdx */
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 2, 1, 1, 1, 1, /* 0xex */
|
||||
1, 1, 1, 1, 1, 1, 3, 3, 1, 1, 1, 1, 1, 1, 3, 3 }; /* 0xfx */
|
||||
|
||||
uint32_t addr64, addr64_2;
|
||||
uint32_t addr64a[8], addr64a_2[8];
|
||||
|
||||
@@ -321,6 +353,77 @@ x386_common_log(const char *fmt, ...)
|
||||
# define x386_common_log(fmt, ...)
|
||||
#endif
|
||||
|
||||
/*Prefetch emulation is a fairly simplistic model:
|
||||
- All instruction bytes must be fetched before it starts.
|
||||
- Cycles used for non-instruction memory accesses are counted and subtracted
|
||||
from the total cycles taken
|
||||
- Any remaining cycles are used to refill the prefetch queue.
|
||||
|
||||
Note that this is only used for 286 / 386 systems. It is disabled when the
|
||||
internal cache on 486+ CPUs is enabled.
|
||||
*/
|
||||
static int prefetch_bytes = 0;
|
||||
|
||||
void
|
||||
prefetch_run(int instr_cycles, int bytes, int modrm, int reads, int reads_l, int writes, int writes_l, int ea32)
|
||||
{
|
||||
int mem_cycles = reads * cpu_cycles_read + reads_l * cpu_cycles_read_l + writes * cpu_cycles_write + writes_l * cpu_cycles_write_l;
|
||||
|
||||
if (instr_cycles < mem_cycles)
|
||||
instr_cycles = mem_cycles;
|
||||
|
||||
prefetch_bytes -= prefetch_prefixes;
|
||||
prefetch_bytes -= bytes;
|
||||
if (modrm != -1) {
|
||||
if (ea32) {
|
||||
if ((modrm & 7) == 4) {
|
||||
if ((modrm & 0x700) == 0x500)
|
||||
prefetch_bytes -= 5;
|
||||
else if ((modrm & 0xc0) == 0x40)
|
||||
prefetch_bytes -= 2;
|
||||
else if ((modrm & 0xc0) == 0x80)
|
||||
prefetch_bytes -= 5;
|
||||
} else {
|
||||
if ((modrm & 0xc7) == 0x05)
|
||||
prefetch_bytes -= 4;
|
||||
else if ((modrm & 0xc0) == 0x40)
|
||||
prefetch_bytes--;
|
||||
else if ((modrm & 0xc0) == 0x80)
|
||||
prefetch_bytes -= 4;
|
||||
}
|
||||
} else {
|
||||
if ((modrm & 0xc7) == 0x06)
|
||||
prefetch_bytes -= 2;
|
||||
else if ((modrm & 0xc0) != 0xc0)
|
||||
prefetch_bytes -= ((modrm & 0xc0) >> 6);
|
||||
}
|
||||
}
|
||||
|
||||
/* Fill up prefetch queue */
|
||||
while (prefetch_bytes < 0) {
|
||||
prefetch_bytes += cpu_prefetch_width;
|
||||
cycles -= cpu_prefetch_cycles;
|
||||
}
|
||||
|
||||
/* Subtract cycles used for memory access by instruction */
|
||||
instr_cycles -= mem_cycles;
|
||||
|
||||
while (instr_cycles >= cpu_prefetch_cycles) {
|
||||
prefetch_bytes += cpu_prefetch_width;
|
||||
instr_cycles -= cpu_prefetch_cycles;
|
||||
}
|
||||
|
||||
prefetch_prefixes = 0;
|
||||
if (prefetch_bytes > 16)
|
||||
prefetch_bytes = 16;
|
||||
}
|
||||
|
||||
void
|
||||
prefetch_flush(void)
|
||||
{
|
||||
prefetch_bytes = 0;
|
||||
}
|
||||
|
||||
static __inline void
|
||||
set_stack32(int s)
|
||||
{
|
||||
|
||||
@@ -22,6 +22,34 @@
|
||||
#include <stddef.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#ifdef OPS_286_386
|
||||
#define readmemb_n(s,a,b) readmembl_no_mmut_2386((s)+(a),b)
|
||||
#define readmemw_n(s,a,b) readmemwl_no_mmut_2386((s)+(a),b)
|
||||
#define readmeml_n(s,a,b) readmemll_no_mmut_2386((s)+(a),b)
|
||||
#define readmemb(s,a) readmembl_2386((s)+(a))
|
||||
#define readmemw(s,a) readmemwl_2386((s)+(a))
|
||||
#define readmeml(s,a) readmemll_2386((s)+(a))
|
||||
#define readmemq(s,a) readmemql_2386((s)+(a))
|
||||
|
||||
#define writememb_n(s,a,b,v) writemembl_no_mmut_2386((s)+(a),b,v)
|
||||
#define writememw_n(s,a,b,v) writememwl_no_mmut_2386((s)+(a),b,v)
|
||||
#define writememl_n(s,a,b,v) writememll_no_mmut_2386((s)+(a),b,v)
|
||||
#define writememb(s,a,v) writemembl_2386((s)+(a),v)
|
||||
#define writememw(s,a,v) writememwl_2386((s)+(a),v)
|
||||
#define writememl(s,a,v) writememll_2386((s)+(a),v)
|
||||
#define writememq(s,a,v) writememql_2386((s)+(a),v)
|
||||
|
||||
#define do_mmut_rb(s,a,b) do_mmutranslate_2386((s)+(a), b, 1, 0)
|
||||
#define do_mmut_rw(s,a,b) do_mmutranslate_2386((s)+(a), b, 2, 0)
|
||||
#define do_mmut_rl(s,a,b) do_mmutranslate_2386((s)+(a), b, 4, 0)
|
||||
#define do_mmut_rb2(s,a,b) do_mmutranslate_2386((s)+(a), b, 1, 0)
|
||||
#define do_mmut_rw2(s,a,b) do_mmutranslate_2386((s)+(a), b, 2, 0)
|
||||
#define do_mmut_rl2(s,a,b) do_mmutranslate_2386((s)+(a), b, 4, 0)
|
||||
|
||||
#define do_mmut_wb(s,a,b) do_mmutranslate_2386((s)+(a), b, 1, 1)
|
||||
#define do_mmut_ww(s,a,b) do_mmutranslate_2386((s)+(a), b, 2, 1)
|
||||
#define do_mmut_wl(s,a,b) do_mmutranslate_2386((s)+(a), b, 4, 1)
|
||||
#else
|
||||
#define readmemb_n(s, a, b) ((readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF) ? readmembl_no_mmut((s) + (a), b) : *(uint8_t *) (readlookup2[(uint32_t) ((s) + (a)) >> 12] + (uintptr_t) ((s) + (a))))
|
||||
#define readmemw_n(s, a, b) ((readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 1)) ? readmemwl_no_mmut((s) + (a), b) : *(uint16_t *) (readlookup2[(uint32_t) ((s) + (a)) >> 12] + (uint32_t) ((s) + (a))))
|
||||
#define readmeml_n(s, a, b) ((readlookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 3)) ? readmemll_no_mmut((s) + (a), b) : *(uint32_t *) (readlookup2[(uint32_t) ((s) + (a)) >> 12] + (uint32_t) ((s) + (a))))
|
||||
@@ -97,6 +125,7 @@
|
||||
#define do_mmut_wl(s, a, b) \
|
||||
if (writelookup2[(uint32_t) ((s) + (a)) >> 12] == (uintptr_t) LOOKUP_INV || (s) == 0xFFFFFFFF || (((s) + (a)) & 3)) \
|
||||
do_mmutranslate((s) + (a), b, 4, 1)
|
||||
#endif
|
||||
|
||||
int checkio(uint32_t port, int mask);
|
||||
|
||||
@@ -191,6 +220,23 @@ int checkio(uint32_t port, int mask);
|
||||
return 1; \
|
||||
}
|
||||
|
||||
#ifdef OPS_286_386
|
||||
/* TODO: Introduce functions to read exec. */
|
||||
static __inline uint8_t fastreadb(uint32_t a)
|
||||
{
|
||||
return readmembl(a);
|
||||
}
|
||||
|
||||
static __inline uint16_t fastreadw(uint32_t a)
|
||||
{
|
||||
return readmemwl(a);
|
||||
}
|
||||
|
||||
static __inline uint32_t fastreadl(uint32_t a)
|
||||
{
|
||||
return readmemll(a);
|
||||
}
|
||||
#else
|
||||
static __inline uint8_t
|
||||
fastreadb(uint32_t a)
|
||||
{
|
||||
@@ -266,6 +312,7 @@ fastreadl(uint32_t a)
|
||||
val |= (fastreadw(a + 2) << 16);
|
||||
return val;
|
||||
}
|
||||
#endif
|
||||
|
||||
static __inline void *
|
||||
get_ram_ptr(uint32_t a)
|
||||
@@ -288,6 +335,37 @@ get_ram_ptr(uint32_t a)
|
||||
|
||||
extern int opcode_length[256];
|
||||
|
||||
#ifdef OPS_286_386
|
||||
static __inline uint16_t
|
||||
fastreadw_fetch(uint32_t a)
|
||||
{
|
||||
uint16_t val;
|
||||
|
||||
if ((a & 0xFFF) > 0xFFE) {
|
||||
val = fastreadb(a);
|
||||
if (opcode_length[val & 0xff] > 1)
|
||||
val |= (fastreadb(a + 1) << 8);
|
||||
return val;
|
||||
}
|
||||
|
||||
return readmemwl(a);
|
||||
}
|
||||
|
||||
static __inline uint32_t
|
||||
fastreadl_fetch(uint32_t a)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
if ((a & 0xFFF) > 0xFFC) {
|
||||
val = fastreadw_fetch(a);
|
||||
if (opcode_length[val & 0xff] > 2)
|
||||
val |= (fastreadw(a + 2) << 16);
|
||||
return val;
|
||||
}
|
||||
|
||||
return readmemll(a);
|
||||
}
|
||||
#else
|
||||
static __inline uint16_t
|
||||
fastreadw_fetch(uint32_t a)
|
||||
{
|
||||
@@ -342,6 +420,7 @@ fastreadl_fetch(uint32_t a)
|
||||
val |= (fastreadw(a + 2) << 16);
|
||||
return val;
|
||||
}
|
||||
#endif
|
||||
|
||||
static __inline uint8_t
|
||||
getbyte(void)
|
||||
@@ -371,6 +450,67 @@ getquad(void)
|
||||
return fastreadl(cs + (cpu_state.pc - 8)) | ((uint64_t) fastreadl(cs + (cpu_state.pc - 4)) << 32);
|
||||
}
|
||||
|
||||
#ifdef OPS_286_386
|
||||
static __inline uint8_t geteab()
|
||||
{
|
||||
if (cpu_mod == 3)
|
||||
return (cpu_rm & 4) ? cpu_state.regs[cpu_rm & 3].b.h : cpu_state.regs[cpu_rm&3].b.l;
|
||||
return readmemb(easeg, cpu_state.eaaddr);
|
||||
}
|
||||
|
||||
static __inline uint16_t geteaw()
|
||||
{
|
||||
if (cpu_mod == 3)
|
||||
return cpu_state.regs[cpu_rm].w;
|
||||
return readmemw(easeg, cpu_state.eaaddr);
|
||||
}
|
||||
|
||||
static __inline uint32_t geteal()
|
||||
{
|
||||
if (cpu_mod == 3)
|
||||
return cpu_state.regs[cpu_rm].l;
|
||||
return readmeml(easeg, cpu_state.eaaddr);
|
||||
}
|
||||
|
||||
static __inline uint64_t geteaq()
|
||||
{
|
||||
return readmemq(easeg, cpu_state.eaaddr);
|
||||
}
|
||||
|
||||
static __inline uint8_t geteab_mem()
|
||||
{
|
||||
return readmemb(easeg,cpu_state.eaaddr);
|
||||
}
|
||||
static __inline uint16_t geteaw_mem()
|
||||
{
|
||||
return readmemw(easeg,cpu_state.eaaddr);
|
||||
}
|
||||
static __inline uint32_t geteal_mem()
|
||||
{
|
||||
return readmeml(easeg,cpu_state.eaaddr);
|
||||
}
|
||||
|
||||
static __inline int seteaq_cwc(void)
|
||||
{
|
||||
CHECK_WRITE_COMMON(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __inline void seteaq(uint64_t v)
|
||||
{
|
||||
if (seteaq_cwc())
|
||||
return;
|
||||
writememql(easeg + cpu_state.eaaddr, v);
|
||||
}
|
||||
|
||||
#define seteab(v) if (cpu_mod!=3) { CHECK_WRITE_COMMON(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr); writemembl_2386(easeg+cpu_state.eaaddr,v); } else if (cpu_rm&4) cpu_state.regs[cpu_rm&3].b.h=v; else cpu_state.regs[cpu_rm].b.l=v
|
||||
#define seteaw(v) if (cpu_mod!=3) { CHECK_WRITE_COMMON(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 1); writememwl_2386(easeg+cpu_state.eaaddr,v); } else cpu_state.regs[cpu_rm].w=v
|
||||
#define seteal(v) if (cpu_mod!=3) { CHECK_WRITE_COMMON(cpu_state.ea_seg, cpu_state.eaaddr, cpu_state.eaaddr + 3); writememll_2386(easeg+cpu_state.eaaddr,v); } else cpu_state.regs[cpu_rm].l=v
|
||||
|
||||
#define seteab_mem(v) writemembl_2386(easeg+cpu_state.eaaddr,v);
|
||||
#define seteaw_mem(v) writememwl_2386(easeg+cpu_state.eaaddr,v);
|
||||
#define seteal_mem(v) writememll_2386(easeg+cpu_state.eaaddr,v);
|
||||
#else
|
||||
static __inline uint8_t
|
||||
geteab(void)
|
||||
{
|
||||
@@ -489,6 +629,7 @@ seteaq(uint64_t v)
|
||||
*eal_w = v; \
|
||||
else \
|
||||
writememll(easeg + cpu_state.eaaddr, v);
|
||||
#endif
|
||||
|
||||
#define getbytef() \
|
||||
((uint8_t) (fetchdat)); \
|
||||
|
||||
@@ -183,78 +183,6 @@ fetch_ea_16_long(uint32_t rmdat)
|
||||
|
||||
#include "x86_flags.h"
|
||||
|
||||
/*Prefetch emulation is a fairly simplistic model:
|
||||
- All instruction bytes must be fetched before it starts.
|
||||
- Cycles used for non-instruction memory accesses are counted and subtracted
|
||||
from the total cycles taken
|
||||
- Any remaining cycles are used to refill the prefetch queue.
|
||||
|
||||
Note that this is only used for 286 / 386 systems. It is disabled when the
|
||||
internal cache on 486+ CPUs is enabled.
|
||||
*/
|
||||
static int prefetch_bytes = 0;
|
||||
static int prefetch_prefixes = 0;
|
||||
|
||||
static void
|
||||
prefetch_run(int instr_cycles, int bytes, int modrm, int reads, int reads_l, int writes, int writes_l, int ea32)
|
||||
{
|
||||
int mem_cycles = reads * cpu_cycles_read + reads_l * cpu_cycles_read_l + writes * cpu_cycles_write + writes_l * cpu_cycles_write_l;
|
||||
|
||||
if (instr_cycles < mem_cycles)
|
||||
instr_cycles = mem_cycles;
|
||||
|
||||
prefetch_bytes -= prefetch_prefixes;
|
||||
prefetch_bytes -= bytes;
|
||||
if (modrm != -1) {
|
||||
if (ea32) {
|
||||
if ((modrm & 7) == 4) {
|
||||
if ((modrm & 0x700) == 0x500)
|
||||
prefetch_bytes -= 5;
|
||||
else if ((modrm & 0xc0) == 0x40)
|
||||
prefetch_bytes -= 2;
|
||||
else if ((modrm & 0xc0) == 0x80)
|
||||
prefetch_bytes -= 5;
|
||||
} else {
|
||||
if ((modrm & 0xc7) == 0x05)
|
||||
prefetch_bytes -= 4;
|
||||
else if ((modrm & 0xc0) == 0x40)
|
||||
prefetch_bytes--;
|
||||
else if ((modrm & 0xc0) == 0x80)
|
||||
prefetch_bytes -= 4;
|
||||
}
|
||||
} else {
|
||||
if ((modrm & 0xc7) == 0x06)
|
||||
prefetch_bytes -= 2;
|
||||
else if ((modrm & 0xc0) != 0xc0)
|
||||
prefetch_bytes -= ((modrm & 0xc0) >> 6);
|
||||
}
|
||||
}
|
||||
|
||||
/* Fill up prefetch queue */
|
||||
while (prefetch_bytes < 0) {
|
||||
prefetch_bytes += cpu_prefetch_width;
|
||||
cycles -= cpu_prefetch_cycles;
|
||||
}
|
||||
|
||||
/* Subtract cycles used for memory access by instruction */
|
||||
instr_cycles -= mem_cycles;
|
||||
|
||||
while (instr_cycles >= cpu_prefetch_cycles) {
|
||||
prefetch_bytes += cpu_prefetch_width;
|
||||
instr_cycles -= cpu_prefetch_cycles;
|
||||
}
|
||||
|
||||
prefetch_prefixes = 0;
|
||||
if (prefetch_bytes > 16)
|
||||
prefetch_bytes = 16;
|
||||
}
|
||||
|
||||
static void
|
||||
prefetch_flush(void)
|
||||
{
|
||||
prefetch_bytes = 0;
|
||||
}
|
||||
|
||||
#define PREFETCH_RUN(instr_cycles, bytes, modrm, reads, reads_l, writes, writes_l, ea32) \
|
||||
do { \
|
||||
if (cpu_prefetch_cycles) \
|
||||
@@ -858,3 +786,156 @@ exec386_dynarec(int cycs)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
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_fetch(cs + cpu_state.pc);
|
||||
|
||||
if (!cpu_state.abrt) {
|
||||
#ifdef ENABLE_386_LOG
|
||||
if (in_smm)
|
||||
x386_dynarec_log("[%04X:%08X] %08X\n", CS, cpu_state.pc, fetchdat);
|
||||
#endif
|
||||
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
|
||||
else if (in_smm)
|
||||
x386_dynarec_log("[%04X:%08X] ABRT\n", CS, cpu_state.pc);
|
||||
#endif
|
||||
|
||||
#ifndef USE_NEW_DYNAREC
|
||||
if (!use32)
|
||||
cpu_state.pc &= 0xffff;
|
||||
#endif
|
||||
|
||||
if (cpu_end_block_after_ins)
|
||||
cpu_end_block_after_ins--;
|
||||
|
||||
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;
|
||||
x386_dynarec_log("Double fault\n");
|
||||
pmodeint(8, 0);
|
||||
if (cpu_state.abrt) {
|
||||
cpu_state.abrt = 0;
|
||||
softresetx86();
|
||||
cpu_set_edx();
|
||||
#ifdef ENABLE_386_LOG
|
||||
x386_dynarec_log("Triple fault - reset\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
} 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);
|
||||
}
|
||||
|
||||
if (smi_line)
|
||||
enter_smm_check(0);
|
||||
else if (nmi && nmi_enable && nmi_mask) {
|
||||
#ifndef USE_NEW_DYNAREC
|
||||
oldcs = CS;
|
||||
#endif
|
||||
cpu_state.oldpc = cpu_state.pc;
|
||||
x86_int(2);
|
||||
nmi_enable = 0;
|
||||
#ifdef OLD_NMI_BEHAVIOR
|
||||
if (nmi_auto_clear) {
|
||||
nmi_auto_clear = 0;
|
||||
nmi = 0;
|
||||
}
|
||||
#else
|
||||
nmi = 0;
|
||||
#endif
|
||||
} 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();
|
||||
|
||||
#ifdef USE_GDBSTUB
|
||||
if (gdbstub_instruction())
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,7 +179,9 @@ extern void x386_dynarec_log(const char *fmt, ...);
|
||||
#include "x86_ops_bcd.h"
|
||||
#include "x86_ops_bit.h"
|
||||
#include "x86_ops_bitscan.h"
|
||||
#ifndef OPS_286_386
|
||||
#include "x86_ops_cyrix.h"
|
||||
#endif
|
||||
#include "x86_ops_flag.h"
|
||||
#include "x86_ops_fpu.h"
|
||||
#include "x86_ops_inc_dec.h"
|
||||
@@ -188,6 +190,7 @@ extern void x386_dynarec_log(const char *fmt, ...);
|
||||
#include "x86_ops_jump.h"
|
||||
#include "x86_ops_misc.h"
|
||||
#include "x87_ops.h"
|
||||
#ifndef OPS_286_386
|
||||
#include "x86_ops_i686.h"
|
||||
#include "x86_ops_mmx.h"
|
||||
#include "x86_ops_mmx_arith.h"
|
||||
@@ -196,30 +199,44 @@ extern void x386_dynarec_log(const char *fmt, ...);
|
||||
#include "x86_ops_mmx_mov.h"
|
||||
#include "x86_ops_mmx_pack.h"
|
||||
#include "x86_ops_mmx_shift.h"
|
||||
#endif
|
||||
#include "x86_ops_mov.h"
|
||||
#include "x86_ops_mov_ctrl.h"
|
||||
#include "x86_ops_mov_seg.h"
|
||||
#include "x86_ops_movx.h"
|
||||
#ifndef OPS_286_386
|
||||
#include "x86_ops_msr.h"
|
||||
#endif
|
||||
#include "x86_ops_mul.h"
|
||||
#include "x86_ops_pmode.h"
|
||||
#include "x86_ops_prefix.h"
|
||||
#ifdef IS_DYNAREC
|
||||
# include "x86_ops_rep_dyn.h"
|
||||
#else
|
||||
#ifdef OPS_286_386
|
||||
# include "x86_ops_rep_2386.h"
|
||||
#else
|
||||
# include "x86_ops_rep.h"
|
||||
#endif
|
||||
#endif
|
||||
#include "x86_ops_ret.h"
|
||||
#include "x86_ops_set.h"
|
||||
#include "x86_ops_stack.h"
|
||||
#ifdef OPS_286_386
|
||||
#include "x86_ops_string_2386.h"
|
||||
#else
|
||||
#include "x86_ops_string.h"
|
||||
#endif
|
||||
#include "x86_ops_xchg.h"
|
||||
#include "x86_ops_call.h"
|
||||
#include "x86_ops_shift.h"
|
||||
#ifndef OPS_286_386
|
||||
#include "x86_ops_amd.h"
|
||||
#include "x86_ops_3dnow.h"
|
||||
#endif
|
||||
#include <time.h>
|
||||
|
||||
#ifndef OPS_286_386
|
||||
static int
|
||||
opVPCEXT(uint32_t fetchdat)
|
||||
{
|
||||
@@ -331,7 +348,50 @@ opVPCEXT(uint32_t fetchdat)
|
||||
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef OPS_286_386
|
||||
static int op0F_w_a16(uint32_t fetchdat)
|
||||
{
|
||||
int opcode = fetchdat & 0xff;
|
||||
fopcode = opcode;
|
||||
cpu_state.pc++;
|
||||
|
||||
PREFETCH_PREFIX();
|
||||
|
||||
return x86_2386_opcodes_0f[opcode](fetchdat >> 8);
|
||||
}
|
||||
static int op0F_l_a16(uint32_t fetchdat)
|
||||
{
|
||||
int opcode = fetchdat & 0xff;
|
||||
fopcode = opcode;
|
||||
cpu_state.pc++;
|
||||
|
||||
PREFETCH_PREFIX();
|
||||
|
||||
return x86_2386_opcodes_0f[opcode | 0x100](fetchdat >> 8);
|
||||
}
|
||||
static int op0F_w_a32(uint32_t fetchdat)
|
||||
{
|
||||
int opcode = fetchdat & 0xff;
|
||||
fopcode = opcode;
|
||||
cpu_state.pc++;
|
||||
|
||||
PREFETCH_PREFIX();
|
||||
|
||||
return x86_2386_opcodes_0f[opcode | 0x200](fetchdat >> 8);
|
||||
}
|
||||
static int op0F_l_a32(uint32_t fetchdat)
|
||||
{
|
||||
int opcode = fetchdat & 0xff;
|
||||
fopcode = opcode;
|
||||
cpu_state.pc++;
|
||||
|
||||
PREFETCH_PREFIX();
|
||||
|
||||
return x86_2386_opcodes_0f[opcode | 0x300](fetchdat >> 8);
|
||||
}
|
||||
#else
|
||||
static int
|
||||
op0F_w_a16(uint32_t fetchdat)
|
||||
{
|
||||
@@ -376,6 +436,7 @@ op0F_l_a32(uint32_t fetchdat)
|
||||
|
||||
return x86_opcodes_0f[opcode | 0x300](fetchdat >> 8);
|
||||
}
|
||||
#endif
|
||||
|
||||
const OpFn OP_TABLE(186_0f)[1024] = {
|
||||
// clang-format off
|
||||
@@ -745,6 +806,7 @@ const OpFn OP_TABLE(486_0f)[1024] = {
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
#ifndef OPS_286_386
|
||||
const OpFn OP_TABLE(c486_0f)[1024] = {
|
||||
// clang-format off
|
||||
/*16-bit data, 16-bit addr*/
|
||||
@@ -928,6 +990,7 @@ const OpFn OP_TABLE(stpc_0f)[1024] = {
|
||||
/*f0*/ ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL, ILLEGAL,
|
||||
// clang-format on
|
||||
};
|
||||
#endif
|
||||
|
||||
const OpFn OP_TABLE(ibm486_0f)[1024] = {
|
||||
// clang-format off
|
||||
@@ -1021,6 +1084,7 @@ const OpFn OP_TABLE(ibm486_0f)[1024] = {
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
#ifndef OPS_286_386
|
||||
const OpFn OP_TABLE(winchip_0f)[1024] = {
|
||||
// clang-format off
|
||||
/*16-bit data, 16-bit addr*/
|
||||
@@ -2128,6 +2192,7 @@ const OpFn OP_TABLE(186)[1024] = {
|
||||
/*f0*/ opLOCK, opLOCK, opREPNE, opREPE, opHLT, opCMC, opF6_a16, opF7_w_a16, opCLC, opSTC, opCLI, opSTI, opCLD, opSTD, opINCDEC_b_a16, opFF_w_a16,
|
||||
// clang-format on
|
||||
};
|
||||
#endif
|
||||
|
||||
const OpFn OP_TABLE(286)[1024] = {
|
||||
// clang-format off
|
||||
|
||||
158
src/cpu/cpu.c
158
src/cpu/cpu.c
@@ -126,6 +126,27 @@ const OpFn *x86_opcodes_REPE;
|
||||
const OpFn *x86_opcodes_REPNE;
|
||||
const OpFn *x86_opcodes_3DNOW;
|
||||
|
||||
const OpFn *x86_2386_opcodes;
|
||||
const OpFn *x86_2386_opcodes_0f;
|
||||
const OpFn *x86_2386_opcodes_d8_a16;
|
||||
const OpFn *x86_2386_opcodes_d8_a32;
|
||||
const OpFn *x86_2386_opcodes_d9_a16;
|
||||
const OpFn *x86_2386_opcodes_d9_a32;
|
||||
const OpFn *x86_2386_opcodes_da_a16;
|
||||
const OpFn *x86_2386_opcodes_da_a32;
|
||||
const OpFn *x86_2386_opcodes_db_a16;
|
||||
const OpFn *x86_2386_opcodes_db_a32;
|
||||
const OpFn *x86_2386_opcodes_dc_a16;
|
||||
const OpFn *x86_2386_opcodes_dc_a32;
|
||||
const OpFn *x86_2386_opcodes_dd_a16;
|
||||
const OpFn *x86_2386_opcodes_dd_a32;
|
||||
const OpFn *x86_2386_opcodes_de_a16;
|
||||
const OpFn *x86_2386_opcodes_de_a32;
|
||||
const OpFn *x86_2386_opcodes_df_a16;
|
||||
const OpFn *x86_2386_opcodes_df_a32;
|
||||
const OpFn *x86_2386_opcodes_REPE;
|
||||
const OpFn *x86_2386_opcodes_REPNE;
|
||||
|
||||
uint16_t cpu_fast_off_count;
|
||||
uint16_t cpu_fast_off_val;
|
||||
uint16_t temp_seg_data[4] = { 0, 0, 0, 0 };
|
||||
@@ -536,8 +557,11 @@ cpu_set(void)
|
||||
#else
|
||||
x86_setopcodes(ops_386, ops_386_0f);
|
||||
#endif
|
||||
x86_setopcodes_2386(ops_2386_386, ops_2386_386_0f);
|
||||
x86_opcodes_REPE = ops_REPE;
|
||||
x86_opcodes_REPNE = ops_REPNE;
|
||||
x86_2386_opcodes_REPE = ops_2386_REPE;
|
||||
x86_2386_opcodes_REPNE = ops_2386_REPNE;
|
||||
x86_opcodes_3DNOW = ops_3DNOW;
|
||||
#ifdef USE_DYNAREC
|
||||
x86_dynarec_opcodes_REPE = dynarec_ops_REPE;
|
||||
@@ -600,6 +624,23 @@ cpu_set(void)
|
||||
x86_opcodes_de_a32 = ops_sf_fpu_de_a32;
|
||||
x86_opcodes_df_a16 = ops_sf_fpu_df_a16;
|
||||
x86_opcodes_df_a32 = ops_sf_fpu_df_a32;
|
||||
|
||||
x86_2386_opcodes_d8_a16 = ops_2386_sf_fpu_d8_a16;
|
||||
x86_2386_opcodes_d8_a32 = ops_2386_sf_fpu_d8_a32;
|
||||
x86_2386_opcodes_d9_a16 = ops_2386_sf_fpu_d9_a16;
|
||||
x86_2386_opcodes_d9_a32 = ops_2386_sf_fpu_d9_a32;
|
||||
x86_2386_opcodes_da_a16 = ops_2386_sf_fpu_da_a16;
|
||||
x86_2386_opcodes_da_a32 = ops_2386_sf_fpu_da_a32;
|
||||
x86_2386_opcodes_db_a16 = ops_2386_sf_fpu_db_a16;
|
||||
x86_2386_opcodes_db_a32 = ops_2386_sf_fpu_db_a32;
|
||||
x86_2386_opcodes_dc_a16 = ops_2386_sf_fpu_dc_a16;
|
||||
x86_2386_opcodes_dc_a32 = ops_2386_sf_fpu_dc_a32;
|
||||
x86_2386_opcodes_dd_a16 = ops_2386_sf_fpu_dd_a16;
|
||||
x86_2386_opcodes_dd_a32 = ops_2386_sf_fpu_dd_a32;
|
||||
x86_2386_opcodes_de_a16 = ops_2386_sf_fpu_de_a16;
|
||||
x86_2386_opcodes_de_a32 = ops_2386_sf_fpu_de_a32;
|
||||
x86_2386_opcodes_df_a16 = ops_2386_sf_fpu_df_a16;
|
||||
x86_2386_opcodes_df_a32 = ops_2386_sf_fpu_df_a32;
|
||||
} else {
|
||||
x86_opcodes_d8_a16 = ops_fpu_d8_a16;
|
||||
x86_opcodes_d8_a32 = ops_fpu_d8_a32;
|
||||
@@ -617,6 +658,23 @@ cpu_set(void)
|
||||
x86_opcodes_de_a32 = ops_fpu_de_a32;
|
||||
x86_opcodes_df_a16 = ops_fpu_df_a16;
|
||||
x86_opcodes_df_a32 = ops_fpu_df_a32;
|
||||
|
||||
x86_2386_opcodes_d8_a16 = ops_2386_fpu_d8_a16;
|
||||
x86_2386_opcodes_d8_a32 = ops_2386_fpu_d8_a32;
|
||||
x86_2386_opcodes_d9_a16 = ops_2386_fpu_d9_a16;
|
||||
x86_2386_opcodes_d9_a32 = ops_2386_fpu_d9_a32;
|
||||
x86_2386_opcodes_da_a16 = ops_2386_fpu_da_a16;
|
||||
x86_2386_opcodes_da_a32 = ops_2386_fpu_da_a32;
|
||||
x86_2386_opcodes_db_a16 = ops_2386_fpu_db_a16;
|
||||
x86_2386_opcodes_db_a32 = ops_2386_fpu_db_a32;
|
||||
x86_2386_opcodes_dc_a16 = ops_2386_fpu_dc_a16;
|
||||
x86_2386_opcodes_dc_a32 = ops_2386_fpu_dc_a32;
|
||||
x86_2386_opcodes_dd_a16 = ops_2386_fpu_dd_a16;
|
||||
x86_2386_opcodes_dd_a32 = ops_2386_fpu_dd_a32;
|
||||
x86_2386_opcodes_de_a16 = ops_2386_fpu_de_a16;
|
||||
x86_2386_opcodes_de_a32 = ops_2386_fpu_de_a32;
|
||||
x86_2386_opcodes_df_a16 = ops_2386_fpu_df_a16;
|
||||
x86_2386_opcodes_df_a32 = ops_2386_fpu_df_a32;
|
||||
}
|
||||
} else {
|
||||
#ifdef USE_DYNAREC
|
||||
@@ -653,6 +711,23 @@ cpu_set(void)
|
||||
x86_opcodes_de_a32 = ops_nofpu_a32;
|
||||
x86_opcodes_df_a16 = ops_nofpu_a16;
|
||||
x86_opcodes_df_a32 = ops_nofpu_a32;
|
||||
|
||||
x86_2386_opcodes_d8_a16 = ops_2386_nofpu_a16;
|
||||
x86_2386_opcodes_d8_a32 = ops_2386_nofpu_a32;
|
||||
x86_2386_opcodes_d9_a16 = ops_2386_nofpu_a16;
|
||||
x86_2386_opcodes_d9_a32 = ops_2386_nofpu_a32;
|
||||
x86_2386_opcodes_da_a16 = ops_2386_nofpu_a16;
|
||||
x86_2386_opcodes_da_a32 = ops_2386_nofpu_a32;
|
||||
x86_2386_opcodes_db_a16 = ops_2386_nofpu_a16;
|
||||
x86_2386_opcodes_db_a32 = ops_2386_nofpu_a32;
|
||||
x86_2386_opcodes_dc_a16 = ops_2386_nofpu_a16;
|
||||
x86_2386_opcodes_dc_a32 = ops_2386_nofpu_a32;
|
||||
x86_2386_opcodes_dd_a16 = ops_2386_nofpu_a16;
|
||||
x86_2386_opcodes_dd_a32 = ops_2386_nofpu_a32;
|
||||
x86_2386_opcodes_de_a16 = ops_2386_nofpu_a16;
|
||||
x86_2386_opcodes_de_a32 = ops_2386_nofpu_a32;
|
||||
x86_2386_opcodes_df_a16 = ops_2386_nofpu_a16;
|
||||
x86_2386_opcodes_df_a32 = ops_2386_nofpu_a32;
|
||||
}
|
||||
|
||||
#ifdef USE_DYNAREC
|
||||
@@ -679,6 +754,7 @@ cpu_set(void)
|
||||
#else
|
||||
x86_setopcodes(ops_186, ops_186_0f);
|
||||
#endif
|
||||
x86_setopcodes_2386(ops_2386_286, ops_2386_286_0f);
|
||||
break;
|
||||
|
||||
case CPU_286:
|
||||
@@ -737,6 +813,21 @@ cpu_set(void)
|
||||
x86_opcodes_de_a32 = ops_sf_fpu_287_de_a32;
|
||||
x86_opcodes_df_a16 = ops_sf_fpu_287_df_a16;
|
||||
x86_opcodes_df_a32 = ops_sf_fpu_287_df_a32;
|
||||
|
||||
x86_2386_opcodes_d9_a16 = ops_2386_sf_fpu_287_d9_a16;
|
||||
x86_2386_opcodes_d9_a32 = ops_2386_sf_fpu_287_d9_a32;
|
||||
x86_2386_opcodes_da_a16 = ops_2386_sf_fpu_287_da_a16;
|
||||
x86_2386_opcodes_da_a32 = ops_2386_sf_fpu_287_da_a32;
|
||||
x86_2386_opcodes_db_a16 = ops_2386_sf_fpu_287_db_a16;
|
||||
x86_2386_opcodes_db_a32 = ops_2386_sf_fpu_287_db_a32;
|
||||
x86_2386_opcodes_dc_a16 = ops_2386_sf_fpu_287_dc_a16;
|
||||
x86_2386_opcodes_dc_a32 = ops_2386_sf_fpu_287_dc_a32;
|
||||
x86_2386_opcodes_dd_a16 = ops_2386_sf_fpu_287_dd_a16;
|
||||
x86_2386_opcodes_dd_a32 = ops_2386_sf_fpu_287_dd_a32;
|
||||
x86_2386_opcodes_de_a16 = ops_2386_sf_fpu_287_de_a16;
|
||||
x86_2386_opcodes_de_a32 = ops_2386_sf_fpu_287_de_a32;
|
||||
x86_2386_opcodes_df_a16 = ops_2386_sf_fpu_287_df_a16;
|
||||
x86_2386_opcodes_df_a32 = ops_2386_sf_fpu_287_df_a32;
|
||||
} else {
|
||||
x86_opcodes_d9_a16 = ops_fpu_287_d9_a16;
|
||||
x86_opcodes_d9_a32 = ops_fpu_287_d9_a32;
|
||||
@@ -752,6 +843,21 @@ cpu_set(void)
|
||||
x86_opcodes_de_a32 = ops_fpu_287_de_a32;
|
||||
x86_opcodes_df_a16 = ops_fpu_287_df_a16;
|
||||
x86_opcodes_df_a32 = ops_fpu_287_df_a32;
|
||||
|
||||
x86_2386_opcodes_d9_a16 = ops_2386_fpu_287_d9_a16;
|
||||
x86_2386_opcodes_d9_a32 = ops_2386_fpu_287_d9_a32;
|
||||
x86_2386_opcodes_da_a16 = ops_2386_fpu_287_da_a16;
|
||||
x86_2386_opcodes_da_a32 = ops_2386_fpu_287_da_a32;
|
||||
x86_2386_opcodes_db_a16 = ops_2386_fpu_287_db_a16;
|
||||
x86_2386_opcodes_db_a32 = ops_2386_fpu_287_db_a32;
|
||||
x86_2386_opcodes_dc_a16 = ops_2386_fpu_287_dc_a16;
|
||||
x86_2386_opcodes_dc_a32 = ops_2386_fpu_287_dc_a32;
|
||||
x86_2386_opcodes_dd_a16 = ops_2386_fpu_287_dd_a16;
|
||||
x86_2386_opcodes_dd_a32 = ops_2386_fpu_287_dd_a32;
|
||||
x86_2386_opcodes_de_a16 = ops_2386_fpu_287_de_a16;
|
||||
x86_2386_opcodes_de_a32 = ops_2386_fpu_287_de_a32;
|
||||
x86_2386_opcodes_df_a16 = ops_2386_fpu_287_df_a16;
|
||||
x86_2386_opcodes_df_a32 = ops_2386_fpu_287_df_a32;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -794,11 +900,13 @@ cpu_set(void)
|
||||
#else
|
||||
x86_setopcodes(ops_386, ops_ibm486_0f);
|
||||
#endif
|
||||
x86_setopcodes_2386(ops_2386_386, ops_2386_ibm486_0f);
|
||||
cpu_features = CPU_FEATURE_MSR;
|
||||
/* FALLTHROUGH */
|
||||
case CPU_386SX:
|
||||
case CPU_386DX:
|
||||
if (fpu_type == FPU_287) { /* In case we get Deskpro 386 emulation */
|
||||
/* In case we get Deskpro 386 emulation */
|
||||
if (fpu_type == FPU_287) {
|
||||
#ifdef USE_DYNAREC
|
||||
if (fpu_softfloat) {
|
||||
x86_dynarec_opcodes_d9_a16 = dynarec_ops_sf_fpu_287_d9_a16;
|
||||
@@ -847,6 +955,21 @@ cpu_set(void)
|
||||
x86_opcodes_de_a32 = ops_sf_fpu_287_de_a32;
|
||||
x86_opcodes_df_a16 = ops_sf_fpu_287_df_a16;
|
||||
x86_opcodes_df_a32 = ops_sf_fpu_287_df_a32;
|
||||
|
||||
x86_2386_opcodes_d9_a16 = ops_2386_sf_fpu_287_d9_a16;
|
||||
x86_2386_opcodes_d9_a32 = ops_2386_sf_fpu_287_d9_a32;
|
||||
x86_2386_opcodes_da_a16 = ops_2386_sf_fpu_287_da_a16;
|
||||
x86_2386_opcodes_da_a32 = ops_2386_sf_fpu_287_da_a32;
|
||||
x86_2386_opcodes_db_a16 = ops_2386_sf_fpu_287_db_a16;
|
||||
x86_2386_opcodes_db_a32 = ops_2386_sf_fpu_287_db_a32;
|
||||
x86_2386_opcodes_dc_a16 = ops_2386_sf_fpu_287_dc_a16;
|
||||
x86_2386_opcodes_dc_a32 = ops_2386_sf_fpu_287_dc_a32;
|
||||
x86_2386_opcodes_dd_a16 = ops_2386_sf_fpu_287_dd_a16;
|
||||
x86_2386_opcodes_dd_a32 = ops_2386_sf_fpu_287_dd_a32;
|
||||
x86_2386_opcodes_de_a16 = ops_2386_sf_fpu_287_de_a16;
|
||||
x86_2386_opcodes_de_a32 = ops_2386_sf_fpu_287_de_a32;
|
||||
x86_2386_opcodes_df_a16 = ops_2386_sf_fpu_287_df_a16;
|
||||
x86_2386_opcodes_df_a32 = ops_2386_sf_fpu_287_df_a32;
|
||||
} else {
|
||||
x86_opcodes_d9_a16 = ops_fpu_287_d9_a16;
|
||||
x86_opcodes_d9_a32 = ops_fpu_287_d9_a32;
|
||||
@@ -862,6 +985,21 @@ cpu_set(void)
|
||||
x86_opcodes_de_a32 = ops_fpu_287_de_a32;
|
||||
x86_opcodes_df_a16 = ops_fpu_287_df_a16;
|
||||
x86_opcodes_df_a32 = ops_fpu_287_df_a32;
|
||||
|
||||
x86_2386_opcodes_d9_a16 = ops_2386_fpu_287_d9_a16;
|
||||
x86_2386_opcodes_d9_a32 = ops_2386_fpu_287_d9_a32;
|
||||
x86_2386_opcodes_da_a16 = ops_2386_fpu_287_da_a16;
|
||||
x86_2386_opcodes_da_a32 = ops_2386_fpu_287_da_a32;
|
||||
x86_2386_opcodes_db_a16 = ops_2386_fpu_287_db_a16;
|
||||
x86_2386_opcodes_db_a32 = ops_2386_fpu_287_db_a32;
|
||||
x86_2386_opcodes_dc_a16 = ops_2386_fpu_287_dc_a16;
|
||||
x86_2386_opcodes_dc_a32 = ops_2386_fpu_287_dc_a32;
|
||||
x86_2386_opcodes_dd_a16 = ops_2386_fpu_287_dd_a16;
|
||||
x86_2386_opcodes_dd_a32 = ops_2386_fpu_287_dd_a32;
|
||||
x86_2386_opcodes_de_a16 = ops_2386_fpu_287_de_a16;
|
||||
x86_2386_opcodes_de_a32 = ops_2386_fpu_287_de_a32;
|
||||
x86_2386_opcodes_df_a16 = ops_2386_fpu_287_df_a16;
|
||||
x86_2386_opcodes_df_a32 = ops_2386_fpu_287_df_a32;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -908,6 +1046,7 @@ cpu_set(void)
|
||||
#else
|
||||
x86_setopcodes(ops_386, ops_486_0f);
|
||||
#endif
|
||||
x86_setopcodes_2386(ops_2386_386, ops_2386_486_0f);
|
||||
|
||||
timing_rr = 1; /* register dest - register src */
|
||||
timing_rm = 3; /* register dest - memory src */
|
||||
@@ -947,6 +1086,7 @@ cpu_set(void)
|
||||
#else
|
||||
x86_setopcodes(ops_386, ops_486_0f);
|
||||
#endif
|
||||
x86_setopcodes_2386(ops_2386_386, ops_2386_486_0f);
|
||||
|
||||
timing_rr = 1; /* register dest - register src */
|
||||
timing_rm = 3; /* register dest - memory src */
|
||||
@@ -999,6 +1139,7 @@ cpu_set(void)
|
||||
#else
|
||||
x86_setopcodes(ops_386, ops_486_0f);
|
||||
#endif
|
||||
x86_setopcodes_2386(ops_2386_386, ops_2386_486_0f);
|
||||
|
||||
timing_rr = 1; /* register dest - register src */
|
||||
timing_rm = 2; /* register dest - memory src */
|
||||
@@ -1642,9 +1783,13 @@ cpu_set(void)
|
||||
cpu_exec = exec386_dynarec;
|
||||
else
|
||||
#endif
|
||||
cpu_exec = exec386;
|
||||
/* Use exec386 for CPU_IBM486SLC because it can reach 100 MHz. */
|
||||
if ((cpu_s->cpu_type == CPU_IBM486SLC) || (cpu_s->cpu_type > CPU_486DLC))
|
||||
cpu_exec = exec386;
|
||||
else
|
||||
cpu_exec = exec386_2386;
|
||||
} else if (cpu_s->cpu_type >= CPU_286)
|
||||
cpu_exec = exec386;
|
||||
cpu_exec = exec386_2386;
|
||||
else
|
||||
cpu_exec = execx86;
|
||||
mmx_init();
|
||||
@@ -3418,6 +3563,13 @@ x86_setopcodes(const OpFn *opcodes, const OpFn *opcodes_0f)
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
x86_setopcodes_2386(const OpFn *opcodes, const OpFn *opcodes_0f)
|
||||
{
|
||||
x86_2386_opcodes = opcodes;
|
||||
x86_2386_opcodes_0f = opcodes_0f;
|
||||
}
|
||||
|
||||
void
|
||||
cpu_update_waitstates(void)
|
||||
{
|
||||
|
||||
@@ -748,6 +748,7 @@ extern void execx86(int cycs);
|
||||
extern void enter_smm(int in_hlt);
|
||||
extern void enter_smm_check(int in_hlt);
|
||||
extern void leave_smm(void);
|
||||
extern void exec386_2386(int cycs);
|
||||
extern void exec386(int cycs);
|
||||
extern void exec386_dynarec(int cycs);
|
||||
extern int idivl(int32_t val);
|
||||
@@ -831,6 +832,8 @@ extern int hlt_reset_pending;
|
||||
|
||||
extern cyrix_t cyrix;
|
||||
|
||||
extern int prefetch_prefixes;
|
||||
|
||||
extern uint8_t use_custom_nmi_vector;
|
||||
extern uint32_t custom_nmi_vector;
|
||||
|
||||
@@ -855,5 +858,8 @@ extern MMX_REG *MMP[8];
|
||||
extern uint16_t *MMEP[8];
|
||||
|
||||
extern void mmx_init(void);
|
||||
extern void prefetch_flush(void);
|
||||
|
||||
extern void prefetch_run(int instr_cycles, int bytes, int modrm, int reads, int reads_l, int writes, int writes_l, int ea32);
|
||||
|
||||
#endif /*EMU_CPU_H*/
|
||||
|
||||
@@ -330,6 +330,110 @@ extern const OpFn ops_REPNE[1024];
|
||||
extern const OpFn ops_3DNOW[256];
|
||||
extern const OpFn ops_3DNOWE[256];
|
||||
|
||||
|
||||
void x86_setopcodes_2386(const OpFn *opcodes, const OpFn *opcodes_0f);
|
||||
|
||||
extern const OpFn *x86_2386_opcodes;
|
||||
extern const OpFn *x86_2386_opcodes_0f;
|
||||
extern const OpFn *x86_2386_opcodes_d8_a16;
|
||||
extern const OpFn *x86_2386_opcodes_d8_a32;
|
||||
extern const OpFn *x86_2386_opcodes_d9_a16;
|
||||
extern const OpFn *x86_2386_opcodes_d9_a32;
|
||||
extern const OpFn *x86_2386_opcodes_da_a16;
|
||||
extern const OpFn *x86_2386_opcodes_da_a32;
|
||||
extern const OpFn *x86_2386_opcodes_db_a16;
|
||||
extern const OpFn *x86_2386_opcodes_db_a32;
|
||||
extern const OpFn *x86_2386_opcodes_dc_a16;
|
||||
extern const OpFn *x86_2386_opcodes_dc_a32;
|
||||
extern const OpFn *x86_2386_opcodes_dd_a16;
|
||||
extern const OpFn *x86_2386_opcodes_dd_a32;
|
||||
extern const OpFn *x86_2386_opcodes_de_a16;
|
||||
extern const OpFn *x86_2386_opcodes_de_a32;
|
||||
extern const OpFn *x86_2386_opcodes_df_a16;
|
||||
extern const OpFn *x86_2386_opcodes_df_a32;
|
||||
extern const OpFn *x86_2386_opcodes_REPE;
|
||||
extern const OpFn *x86_2386_opcodes_REPNE;
|
||||
|
||||
extern const OpFn ops_2386_286[1024];
|
||||
extern const OpFn ops_2386_286_0f[1024];
|
||||
|
||||
extern const OpFn ops_2386_386[1024];
|
||||
extern const OpFn ops_2386_386_0f[1024];
|
||||
|
||||
extern const OpFn ops_2386_486_0f[1024];
|
||||
extern const OpFn ops_2386_ibm486_0f[1024];
|
||||
|
||||
extern const OpFn ops_2386_sf_fpu_287_d9_a16[256];
|
||||
extern const OpFn ops_2386_sf_fpu_287_d9_a32[256];
|
||||
extern const OpFn ops_2386_sf_fpu_287_da_a16[256];
|
||||
extern const OpFn ops_2386_sf_fpu_287_da_a32[256];
|
||||
extern const OpFn ops_2386_sf_fpu_287_db_a16[256];
|
||||
extern const OpFn ops_2386_sf_fpu_287_db_a32[256];
|
||||
extern const OpFn ops_2386_sf_fpu_287_dc_a16[32];
|
||||
extern const OpFn ops_2386_sf_fpu_287_dc_a32[32];
|
||||
extern const OpFn ops_2386_sf_fpu_287_dd_a16[256];
|
||||
extern const OpFn ops_2386_sf_fpu_287_dd_a32[256];
|
||||
extern const OpFn ops_2386_sf_fpu_287_de_a16[256];
|
||||
extern const OpFn ops_2386_sf_fpu_287_de_a32[256];
|
||||
extern const OpFn ops_2386_sf_fpu_287_df_a16[256];
|
||||
extern const OpFn ops_2386_sf_fpu_287_df_a32[256];
|
||||
|
||||
extern const OpFn ops_2386_sf_fpu_d8_a16[32];
|
||||
extern const OpFn ops_2386_sf_fpu_d8_a32[32];
|
||||
extern const OpFn ops_2386_sf_fpu_d9_a16[256];
|
||||
extern const OpFn ops_2386_sf_fpu_d9_a32[256];
|
||||
extern const OpFn ops_2386_sf_fpu_da_a16[256];
|
||||
extern const OpFn ops_2386_sf_fpu_da_a32[256];
|
||||
extern const OpFn ops_2386_sf_fpu_db_a16[256];
|
||||
extern const OpFn ops_2386_sf_fpu_db_a32[256];
|
||||
extern const OpFn ops_2386_sf_fpu_dc_a16[32];
|
||||
extern const OpFn ops_2386_sf_fpu_dc_a32[32];
|
||||
extern const OpFn ops_2386_sf_fpu_dd_a16[256];
|
||||
extern const OpFn ops_2386_sf_fpu_dd_a32[256];
|
||||
extern const OpFn ops_2386_sf_fpu_de_a16[256];
|
||||
extern const OpFn ops_2386_sf_fpu_de_a32[256];
|
||||
extern const OpFn ops_2386_sf_fpu_df_a16[256];
|
||||
extern const OpFn ops_2386_sf_fpu_df_a32[256];
|
||||
|
||||
extern const OpFn ops_2386_fpu_287_d9_a16[256];
|
||||
extern const OpFn ops_2386_fpu_287_d9_a32[256];
|
||||
extern const OpFn ops_2386_fpu_287_da_a16[256];
|
||||
extern const OpFn ops_2386_fpu_287_da_a32[256];
|
||||
extern const OpFn ops_2386_fpu_287_db_a16[256];
|
||||
extern const OpFn ops_2386_fpu_287_db_a32[256];
|
||||
extern const OpFn ops_2386_fpu_287_dc_a16[32];
|
||||
extern const OpFn ops_2386_fpu_287_dc_a32[32];
|
||||
extern const OpFn ops_2386_fpu_287_dd_a16[256];
|
||||
extern const OpFn ops_2386_fpu_287_dd_a32[256];
|
||||
extern const OpFn ops_2386_fpu_287_de_a16[256];
|
||||
extern const OpFn ops_2386_fpu_287_de_a32[256];
|
||||
extern const OpFn ops_2386_fpu_287_df_a16[256];
|
||||
extern const OpFn ops_2386_fpu_287_df_a32[256];
|
||||
|
||||
extern const OpFn ops_2386_fpu_d8_a16[32];
|
||||
extern const OpFn ops_2386_fpu_d8_a32[32];
|
||||
extern const OpFn ops_2386_fpu_d9_a16[256];
|
||||
extern const OpFn ops_2386_fpu_d9_a32[256];
|
||||
extern const OpFn ops_2386_fpu_da_a16[256];
|
||||
extern const OpFn ops_2386_fpu_da_a32[256];
|
||||
extern const OpFn ops_2386_fpu_db_a16[256];
|
||||
extern const OpFn ops_2386_fpu_db_a32[256];
|
||||
extern const OpFn ops_2386_fpu_dc_a16[32];
|
||||
extern const OpFn ops_2386_fpu_dc_a32[32];
|
||||
extern const OpFn ops_2386_fpu_dd_a16[256];
|
||||
extern const OpFn ops_2386_fpu_dd_a32[256];
|
||||
extern const OpFn ops_2386_fpu_de_a16[256];
|
||||
extern const OpFn ops_2386_fpu_de_a32[256];
|
||||
extern const OpFn ops_2386_fpu_df_a16[256];
|
||||
extern const OpFn ops_2386_fpu_df_a32[256];
|
||||
extern const OpFn ops_2386_nofpu_a16[256];
|
||||
extern const OpFn ops_2386_nofpu_a32[256];
|
||||
|
||||
extern const OpFn ops_2386_REPE[1024];
|
||||
extern const OpFn ops_2386_REPNE[1024];
|
||||
extern const OpFn ops_2386_3DNOW[256];
|
||||
|
||||
|
||||
#define C0 (1 << 8)
|
||||
#define C1 (1 << 9)
|
||||
#define C2 (1 << 10)
|
||||
|
||||
@@ -115,6 +115,7 @@ opCMPXCHG_l_a32(uint32_t fetchdat)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef OPS_286_386
|
||||
static int
|
||||
opCMPXCHG8B_a16(uint32_t fetchdat)
|
||||
{
|
||||
@@ -169,6 +170,7 @@ opCMPXCHG8B_a32(uint32_t fetchdat)
|
||||
cycles -= (cpu_mod == 3) ? 6 : 10;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* dest = eab, src = r8 */
|
||||
static int
|
||||
|
||||
863
src/cpu/x86_ops_rep_2386.h
Normal file
863
src/cpu/x86_ops_rep_2386.h
Normal file
@@ -0,0 +1,863 @@
|
||||
#define REP_OPS(size, CNT_REG, SRC_REG, DEST_REG) \
|
||||
static int opREP_INSB_##size(uint32_t fetchdat) \
|
||||
{ \
|
||||
int reads = 0, writes = 0, total_cycles = 0; \
|
||||
\
|
||||
addr64 = 0x00000000; \
|
||||
\
|
||||
if (CNT_REG > 0) { \
|
||||
uint8_t temp; \
|
||||
\
|
||||
SEG_CHECK_WRITE(&cpu_state.seg_es); \
|
||||
check_io_perm(DX, 1); \
|
||||
CHECK_WRITE(&cpu_state.seg_es, DEST_REG, DEST_REG); \
|
||||
high_page = 0; \
|
||||
do_mmut_wb(es, DEST_REG, &addr64); \
|
||||
if (cpu_state.abrt) \
|
||||
return 1; \
|
||||
temp = inb(DX); \
|
||||
writememb_n(es, DEST_REG, addr64, temp); \
|
||||
if (cpu_state.abrt) \
|
||||
return 1; \
|
||||
\
|
||||
if (cpu_state.flags & D_FLAG) \
|
||||
DEST_REG--; \
|
||||
else \
|
||||
DEST_REG++; \
|
||||
CNT_REG--; \
|
||||
cycles -= 15; \
|
||||
reads++; \
|
||||
writes++; \
|
||||
total_cycles += 15; \
|
||||
} \
|
||||
PREFETCH_RUN(total_cycles, 1, -1, reads, 0, writes, 0, 0); \
|
||||
if (CNT_REG > 0) { \
|
||||
CPU_BLOCK_END(); \
|
||||
cpu_state.pc = cpu_state.oldpc; \
|
||||
return 1; \
|
||||
} \
|
||||
return cpu_state.abrt; \
|
||||
} \
|
||||
static int opREP_INSW_##size(uint32_t fetchdat) \
|
||||
{ \
|
||||
int reads = 0, writes = 0, total_cycles = 0; \
|
||||
\
|
||||
addr64a[0] = addr64a[1] = 0x00000000; \
|
||||
\
|
||||
if (CNT_REG > 0) { \
|
||||
uint16_t temp; \
|
||||
\
|
||||
SEG_CHECK_WRITE(&cpu_state.seg_es); \
|
||||
check_io_perm(DX, 2); \
|
||||
CHECK_WRITE(&cpu_state.seg_es, DEST_REG, DEST_REG + 1UL); \
|
||||
high_page = 0; \
|
||||
do_mmut_ww(es, DEST_REG, addr64a); \
|
||||
if (cpu_state.abrt) \
|
||||
return 1; \
|
||||
temp = inw(DX); \
|
||||
writememw_n(es, DEST_REG, addr64a, temp); \
|
||||
if (cpu_state.abrt) \
|
||||
return 1; \
|
||||
\
|
||||
if (cpu_state.flags & D_FLAG) \
|
||||
DEST_REG -= 2; \
|
||||
else \
|
||||
DEST_REG += 2; \
|
||||
CNT_REG--; \
|
||||
cycles -= 15; \
|
||||
reads++; \
|
||||
writes++; \
|
||||
total_cycles += 15; \
|
||||
} \
|
||||
PREFETCH_RUN(total_cycles, 1, -1, reads, 0, writes, 0, 0); \
|
||||
if (CNT_REG > 0) { \
|
||||
CPU_BLOCK_END(); \
|
||||
cpu_state.pc = cpu_state.oldpc; \
|
||||
return 1; \
|
||||
} \
|
||||
return cpu_state.abrt; \
|
||||
} \
|
||||
static int opREP_INSL_##size(uint32_t fetchdat) \
|
||||
{ \
|
||||
int reads = 0, writes = 0, total_cycles = 0; \
|
||||
\
|
||||
addr64a[0] = addr64a[1] = addr64a[2] = addr64a[3] = 0x00000000; \
|
||||
\
|
||||
if (CNT_REG > 0) { \
|
||||
uint32_t temp; \
|
||||
\
|
||||
SEG_CHECK_WRITE(&cpu_state.seg_es); \
|
||||
check_io_perm(DX, 4); \
|
||||
CHECK_WRITE(&cpu_state.seg_es, DEST_REG, DEST_REG + 3UL); \
|
||||
high_page = 0; \
|
||||
do_mmut_wl(es, DEST_REG, addr64a); \
|
||||
if (cpu_state.abrt) \
|
||||
return 1; \
|
||||
temp = inl(DX); \
|
||||
writememl_n(es, DEST_REG, addr64a, temp); \
|
||||
if (cpu_state.abrt) \
|
||||
return 1; \
|
||||
\
|
||||
if (cpu_state.flags & D_FLAG) \
|
||||
DEST_REG -= 4; \
|
||||
else \
|
||||
DEST_REG += 4; \
|
||||
CNT_REG--; \
|
||||
cycles -= 15; \
|
||||
reads++; \
|
||||
writes++; \
|
||||
total_cycles += 15; \
|
||||
} \
|
||||
PREFETCH_RUN(total_cycles, 1, -1, 0, reads, 0, writes, 0); \
|
||||
if (CNT_REG > 0) { \
|
||||
CPU_BLOCK_END(); \
|
||||
cpu_state.pc = cpu_state.oldpc; \
|
||||
return 1; \
|
||||
} \
|
||||
return cpu_state.abrt; \
|
||||
} \
|
||||
\
|
||||
static int opREP_OUTSB_##size(uint32_t fetchdat) \
|
||||
{ \
|
||||
int reads = 0, writes = 0, total_cycles = 0; \
|
||||
\
|
||||
if (CNT_REG > 0) { \
|
||||
uint8_t temp; \
|
||||
SEG_CHECK_READ(cpu_state.ea_seg); \
|
||||
CHECK_READ(cpu_state.ea_seg, SRC_REG, SRC_REG); \
|
||||
temp = readmemb(cpu_state.ea_seg->base, SRC_REG); \
|
||||
if (cpu_state.abrt) \
|
||||
return 1; \
|
||||
check_io_perm(DX, 1); \
|
||||
outb(DX, temp); \
|
||||
if (cpu_state.flags & D_FLAG) \
|
||||
SRC_REG--; \
|
||||
else \
|
||||
SRC_REG++; \
|
||||
CNT_REG--; \
|
||||
cycles -= 14; \
|
||||
reads++; \
|
||||
writes++; \
|
||||
total_cycles += 14; \
|
||||
} \
|
||||
PREFETCH_RUN(total_cycles, 1, -1, reads, 0, writes, 0, 0); \
|
||||
if (CNT_REG > 0) { \
|
||||
CPU_BLOCK_END(); \
|
||||
cpu_state.pc = cpu_state.oldpc; \
|
||||
return 1; \
|
||||
} \
|
||||
return cpu_state.abrt; \
|
||||
} \
|
||||
static int opREP_OUTSW_##size(uint32_t fetchdat) \
|
||||
{ \
|
||||
int reads = 0, writes = 0, total_cycles = 0; \
|
||||
\
|
||||
if (CNT_REG > 0) { \
|
||||
uint16_t temp; \
|
||||
SEG_CHECK_READ(cpu_state.ea_seg); \
|
||||
CHECK_READ(cpu_state.ea_seg, SRC_REG, SRC_REG + 1UL); \
|
||||
temp = readmemw(cpu_state.ea_seg->base, SRC_REG); \
|
||||
if (cpu_state.abrt) \
|
||||
return 1; \
|
||||
check_io_perm(DX, 2); \
|
||||
outw(DX, temp); \
|
||||
if (cpu_state.flags & D_FLAG) \
|
||||
SRC_REG -= 2; \
|
||||
else \
|
||||
SRC_REG += 2; \
|
||||
CNT_REG--; \
|
||||
cycles -= 14; \
|
||||
reads++; \
|
||||
writes++; \
|
||||
total_cycles += 14; \
|
||||
} \
|
||||
PREFETCH_RUN(total_cycles, 1, -1, reads, 0, writes, 0, 0); \
|
||||
if (CNT_REG > 0) { \
|
||||
CPU_BLOCK_END(); \
|
||||
cpu_state.pc = cpu_state.oldpc; \
|
||||
return 1; \
|
||||
} \
|
||||
return cpu_state.abrt; \
|
||||
} \
|
||||
static int opREP_OUTSL_##size(uint32_t fetchdat) \
|
||||
{ \
|
||||
int reads = 0, writes = 0, total_cycles = 0; \
|
||||
\
|
||||
if (CNT_REG > 0) { \
|
||||
uint32_t temp; \
|
||||
SEG_CHECK_READ(cpu_state.ea_seg); \
|
||||
CHECK_READ(cpu_state.ea_seg, SRC_REG, SRC_REG + 3UL); \
|
||||
temp = readmeml(cpu_state.ea_seg->base, SRC_REG); \
|
||||
if (cpu_state.abrt) \
|
||||
return 1; \
|
||||
check_io_perm(DX, 4); \
|
||||
outl(DX, temp); \
|
||||
if (cpu_state.flags & D_FLAG) \
|
||||
SRC_REG -= 4; \
|
||||
else \
|
||||
SRC_REG += 4; \
|
||||
CNT_REG--; \
|
||||
cycles -= 14; \
|
||||
reads++; \
|
||||
writes++; \
|
||||
total_cycles += 14; \
|
||||
} \
|
||||
PREFETCH_RUN(total_cycles, 1, -1, 0, reads, 0, writes, 0); \
|
||||
if (CNT_REG > 0) { \
|
||||
CPU_BLOCK_END(); \
|
||||
cpu_state.pc = cpu_state.oldpc; \
|
||||
return 1; \
|
||||
} \
|
||||
return cpu_state.abrt; \
|
||||
} \
|
||||
\
|
||||
static int opREP_MOVSB_##size(uint32_t fetchdat) \
|
||||
{ \
|
||||
int reads = 0, writes = 0, total_cycles = 0; \
|
||||
int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \
|
||||
addr64 = addr64_2 = 0x00000000; \
|
||||
if (trap) \
|
||||
cycles_end = cycles + 1; /*Force the instruction to end after only one iteration when trap flag set*/ \
|
||||
if (CNT_REG > 0) { \
|
||||
SEG_CHECK_READ(cpu_state.ea_seg); \
|
||||
SEG_CHECK_WRITE(&cpu_state.seg_es); \
|
||||
} \
|
||||
while (CNT_REG > 0) { \
|
||||
uint8_t temp; \
|
||||
\
|
||||
CHECK_READ_REP(cpu_state.ea_seg, SRC_REG, SRC_REG); \
|
||||
CHECK_WRITE_REP(&cpu_state.seg_es, DEST_REG, DEST_REG); \
|
||||
high_page = 0; \
|
||||
do_mmut_rb(cpu_state.ea_seg->base, SRC_REG, &addr64); \
|
||||
if (cpu_state.abrt) \
|
||||
break; \
|
||||
do_mmut_wb(es, DEST_REG, &addr64_2); \
|
||||
if (cpu_state.abrt) \
|
||||
break; \
|
||||
temp = readmemb_n(cpu_state.ea_seg->base, SRC_REG, addr64); \
|
||||
if (cpu_state.abrt) \
|
||||
return 1; \
|
||||
writememb_n(es, DEST_REG, addr64_2, temp); \
|
||||
if (cpu_state.abrt) \
|
||||
return 1; \
|
||||
\
|
||||
if (cpu_state.flags & D_FLAG) { \
|
||||
DEST_REG--; \
|
||||
SRC_REG--; \
|
||||
} else { \
|
||||
DEST_REG++; \
|
||||
SRC_REG++; \
|
||||
} \
|
||||
CNT_REG--; \
|
||||
cycles -= is486 ? 3 : 4; \
|
||||
reads++; \
|
||||
writes++; \
|
||||
total_cycles += is486 ? 3 : 4; \
|
||||
if (cycles < cycles_end) \
|
||||
break; \
|
||||
} \
|
||||
PREFETCH_RUN(total_cycles, 1, -1, reads, 0, writes, 0, 0); \
|
||||
if (CNT_REG > 0) { \
|
||||
CPU_BLOCK_END(); \
|
||||
cpu_state.pc = cpu_state.oldpc; \
|
||||
return 1; \
|
||||
} \
|
||||
return cpu_state.abrt; \
|
||||
} \
|
||||
static int opREP_MOVSW_##size(uint32_t fetchdat) \
|
||||
{ \
|
||||
int reads = 0, writes = 0, total_cycles = 0; \
|
||||
int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \
|
||||
addr64a[0] = addr64a[1] = 0x00000000; \
|
||||
addr64a_2[0] = addr64a_2[1] = 0x00000000; \
|
||||
if (trap) \
|
||||
cycles_end = cycles + 1; /*Force the instruction to end after only one iteration when trap flag set*/ \
|
||||
if (CNT_REG > 0) { \
|
||||
SEG_CHECK_READ(cpu_state.ea_seg); \
|
||||
SEG_CHECK_WRITE(&cpu_state.seg_es); \
|
||||
} \
|
||||
while (CNT_REG > 0) { \
|
||||
uint16_t temp; \
|
||||
\
|
||||
CHECK_READ_REP(cpu_state.ea_seg, SRC_REG, SRC_REG + 1UL); \
|
||||
CHECK_WRITE_REP(&cpu_state.seg_es, DEST_REG, DEST_REG + 1UL); \
|
||||
high_page = 0; \
|
||||
do_mmut_rw(cpu_state.ea_seg->base, SRC_REG, addr64a); \
|
||||
if (cpu_state.abrt) \
|
||||
break; \
|
||||
do_mmut_ww(es, DEST_REG, addr64a_2); \
|
||||
if (cpu_state.abrt) \
|
||||
break; \
|
||||
temp = readmemw_n(cpu_state.ea_seg->base, SRC_REG, addr64a); \
|
||||
if (cpu_state.abrt) \
|
||||
return 1; \
|
||||
writememw_n(es, DEST_REG, addr64a_2, temp); \
|
||||
if (cpu_state.abrt) \
|
||||
return 1; \
|
||||
\
|
||||
if (cpu_state.flags & D_FLAG) { \
|
||||
DEST_REG -= 2; \
|
||||
SRC_REG -= 2; \
|
||||
} else { \
|
||||
DEST_REG += 2; \
|
||||
SRC_REG += 2; \
|
||||
} \
|
||||
CNT_REG--; \
|
||||
cycles -= is486 ? 3 : 4; \
|
||||
reads++; \
|
||||
writes++; \
|
||||
total_cycles += is486 ? 3 : 4; \
|
||||
if (cycles < cycles_end) \
|
||||
break; \
|
||||
} \
|
||||
PREFETCH_RUN(total_cycles, 1, -1, reads, 0, writes, 0, 0); \
|
||||
if (CNT_REG > 0) { \
|
||||
CPU_BLOCK_END(); \
|
||||
cpu_state.pc = cpu_state.oldpc; \
|
||||
return 1; \
|
||||
} \
|
||||
return cpu_state.abrt; \
|
||||
} \
|
||||
static int opREP_MOVSL_##size(uint32_t fetchdat) \
|
||||
{ \
|
||||
int reads = 0, writes = 0, total_cycles = 0; \
|
||||
int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \
|
||||
addr64a[0] = addr64a[1] = addr64a[2] = addr64a[3] = 0x00000000; \
|
||||
addr64a_2[0] = addr64a_2[1] = addr64a_2[2] = addr64a_2[3] = 0x00000000; \
|
||||
if (trap) \
|
||||
cycles_end = cycles + 1; /*Force the instruction to end after only one iteration when trap flag set*/ \
|
||||
if (CNT_REG > 0) { \
|
||||
SEG_CHECK_READ(cpu_state.ea_seg); \
|
||||
SEG_CHECK_WRITE(&cpu_state.seg_es); \
|
||||
} \
|
||||
while (CNT_REG > 0) { \
|
||||
uint32_t temp; \
|
||||
\
|
||||
CHECK_READ_REP(cpu_state.ea_seg, SRC_REG, SRC_REG + 3UL); \
|
||||
CHECK_WRITE_REP(&cpu_state.seg_es, DEST_REG, DEST_REG + 3UL); \
|
||||
high_page = 0; \
|
||||
do_mmut_rl(cpu_state.ea_seg->base, SRC_REG, addr64a); \
|
||||
if (cpu_state.abrt) \
|
||||
break; \
|
||||
do_mmut_wl(es, DEST_REG, addr64a_2); \
|
||||
if (cpu_state.abrt) \
|
||||
break; \
|
||||
temp = readmeml_n(cpu_state.ea_seg->base, SRC_REG, addr64a); \
|
||||
if (cpu_state.abrt) \
|
||||
return 1; \
|
||||
writememl_n(es, DEST_REG, addr64a_2, temp); \
|
||||
if (cpu_state.abrt) \
|
||||
return 1; \
|
||||
\
|
||||
if (cpu_state.flags & D_FLAG) { \
|
||||
DEST_REG -= 4; \
|
||||
SRC_REG -= 4; \
|
||||
} else { \
|
||||
DEST_REG += 4; \
|
||||
SRC_REG += 4; \
|
||||
} \
|
||||
CNT_REG--; \
|
||||
cycles -= is486 ? 3 : 4; \
|
||||
reads++; \
|
||||
writes++; \
|
||||
total_cycles += is486 ? 3 : 4; \
|
||||
if (cycles < cycles_end) \
|
||||
break; \
|
||||
} \
|
||||
PREFETCH_RUN(total_cycles, 1, -1, reads, 0, writes, 0, 0); \
|
||||
if (CNT_REG > 0) { \
|
||||
CPU_BLOCK_END(); \
|
||||
cpu_state.pc = cpu_state.oldpc; \
|
||||
return 1; \
|
||||
} \
|
||||
return cpu_state.abrt; \
|
||||
} \
|
||||
\
|
||||
static int opREP_STOSB_##size(uint32_t fetchdat) \
|
||||
{ \
|
||||
int writes = 0, total_cycles = 0; \
|
||||
int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \
|
||||
if (trap) \
|
||||
cycles_end = cycles + 1; /*Force the instruction to end after only one iteration when trap flag set*/ \
|
||||
if (CNT_REG > 0) \
|
||||
SEG_CHECK_WRITE(&cpu_state.seg_es); \
|
||||
while (CNT_REG > 0) { \
|
||||
CHECK_WRITE_REP(&cpu_state.seg_es, DEST_REG, DEST_REG); \
|
||||
writememb(es, DEST_REG, AL); \
|
||||
if (cpu_state.abrt) \
|
||||
return 1; \
|
||||
if (cpu_state.flags & D_FLAG) \
|
||||
DEST_REG--; \
|
||||
else \
|
||||
DEST_REG++; \
|
||||
CNT_REG--; \
|
||||
cycles -= is486 ? 4 : 5; \
|
||||
writes++; \
|
||||
total_cycles += is486 ? 4 : 5; \
|
||||
if (cycles < cycles_end) \
|
||||
break; \
|
||||
} \
|
||||
PREFETCH_RUN(total_cycles, 1, -1, 0, 0, writes, 0, 0); \
|
||||
if (CNT_REG > 0) { \
|
||||
CPU_BLOCK_END(); \
|
||||
cpu_state.pc = cpu_state.oldpc; \
|
||||
return 1; \
|
||||
} \
|
||||
return cpu_state.abrt; \
|
||||
} \
|
||||
static int opREP_STOSW_##size(uint32_t fetchdat) \
|
||||
{ \
|
||||
int writes = 0, total_cycles = 0; \
|
||||
int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \
|
||||
if (trap) \
|
||||
cycles_end = cycles + 1; /*Force the instruction to end after only one iteration when trap flag set*/ \
|
||||
if (CNT_REG > 0) \
|
||||
SEG_CHECK_WRITE(&cpu_state.seg_es); \
|
||||
while (CNT_REG > 0) { \
|
||||
CHECK_WRITE_REP(&cpu_state.seg_es, DEST_REG, DEST_REG + 1UL); \
|
||||
writememw(es, DEST_REG, AX); \
|
||||
if (cpu_state.abrt) \
|
||||
return 1; \
|
||||
if (cpu_state.flags & D_FLAG) \
|
||||
DEST_REG -= 2; \
|
||||
else \
|
||||
DEST_REG += 2; \
|
||||
CNT_REG--; \
|
||||
cycles -= is486 ? 4 : 5; \
|
||||
writes++; \
|
||||
total_cycles += is486 ? 4 : 5; \
|
||||
if (cycles < cycles_end) \
|
||||
break; \
|
||||
} \
|
||||
PREFETCH_RUN(total_cycles, 1, -1, 0, 0, writes, 0, 0); \
|
||||
if (CNT_REG > 0) { \
|
||||
CPU_BLOCK_END(); \
|
||||
cpu_state.pc = cpu_state.oldpc; \
|
||||
return 1; \
|
||||
} \
|
||||
return cpu_state.abrt; \
|
||||
} \
|
||||
static int opREP_STOSL_##size(uint32_t fetchdat) \
|
||||
{ \
|
||||
int writes = 0, total_cycles = 0; \
|
||||
int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \
|
||||
if (trap) \
|
||||
cycles_end = cycles + 1; /*Force the instruction to end after only one iteration when trap flag set*/ \
|
||||
if (CNT_REG > 0) \
|
||||
SEG_CHECK_WRITE(&cpu_state.seg_es); \
|
||||
while (CNT_REG > 0) { \
|
||||
CHECK_WRITE_REP(&cpu_state.seg_es, DEST_REG, DEST_REG + 3UL); \
|
||||
writememl(es, DEST_REG, EAX); \
|
||||
if (cpu_state.abrt) \
|
||||
return 1; \
|
||||
if (cpu_state.flags & D_FLAG) \
|
||||
DEST_REG -= 4; \
|
||||
else \
|
||||
DEST_REG += 4; \
|
||||
CNT_REG--; \
|
||||
cycles -= is486 ? 4 : 5; \
|
||||
writes++; \
|
||||
total_cycles += is486 ? 4 : 5; \
|
||||
if (cycles < cycles_end) \
|
||||
break; \
|
||||
} \
|
||||
PREFETCH_RUN(total_cycles, 1, -1, 0, 0, 0, writes, 0); \
|
||||
if (CNT_REG > 0) { \
|
||||
CPU_BLOCK_END(); \
|
||||
cpu_state.pc = cpu_state.oldpc; \
|
||||
return 1; \
|
||||
} \
|
||||
return cpu_state.abrt; \
|
||||
} \
|
||||
\
|
||||
static int opREP_LODSB_##size(uint32_t fetchdat) \
|
||||
{ \
|
||||
int reads = 0, total_cycles = 0; \
|
||||
int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \
|
||||
if (trap) \
|
||||
cycles_end = cycles + 1; /*Force the instruction to end after only one iteration when trap flag set*/ \
|
||||
if (CNT_REG > 0) \
|
||||
SEG_CHECK_READ(cpu_state.ea_seg); \
|
||||
while (CNT_REG > 0) { \
|
||||
CHECK_READ_REP(cpu_state.ea_seg, SRC_REG, SRC_REG); \
|
||||
AL = readmemb(cpu_state.ea_seg->base, SRC_REG); \
|
||||
if (cpu_state.abrt) \
|
||||
return 1; \
|
||||
if (cpu_state.flags & D_FLAG) \
|
||||
SRC_REG--; \
|
||||
else \
|
||||
SRC_REG++; \
|
||||
CNT_REG--; \
|
||||
cycles -= is486 ? 4 : 5; \
|
||||
reads++; \
|
||||
total_cycles += is486 ? 4 : 5; \
|
||||
if (cycles < cycles_end) \
|
||||
break; \
|
||||
} \
|
||||
PREFETCH_RUN(total_cycles, 1, -1, reads, 0, 0, 0, 0); \
|
||||
if (CNT_REG > 0) { \
|
||||
CPU_BLOCK_END(); \
|
||||
cpu_state.pc = cpu_state.oldpc; \
|
||||
return 1; \
|
||||
} \
|
||||
return cpu_state.abrt; \
|
||||
} \
|
||||
static int opREP_LODSW_##size(uint32_t fetchdat) \
|
||||
{ \
|
||||
int reads = 0, total_cycles = 0; \
|
||||
int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \
|
||||
if (trap) \
|
||||
cycles_end = cycles + 1; /*Force the instruction to end after only one iteration when trap flag set*/ \
|
||||
if (CNT_REG > 0) \
|
||||
SEG_CHECK_READ(cpu_state.ea_seg); \
|
||||
while (CNT_REG > 0) { \
|
||||
CHECK_READ_REP(cpu_state.ea_seg, SRC_REG, SRC_REG + 1UL); \
|
||||
AX = readmemw(cpu_state.ea_seg->base, SRC_REG); \
|
||||
if (cpu_state.abrt) \
|
||||
return 1; \
|
||||
if (cpu_state.flags & D_FLAG) \
|
||||
SRC_REG -= 2; \
|
||||
else \
|
||||
SRC_REG += 2; \
|
||||
CNT_REG--; \
|
||||
cycles -= is486 ? 4 : 5; \
|
||||
reads++; \
|
||||
total_cycles += is486 ? 4 : 5; \
|
||||
if (cycles < cycles_end) \
|
||||
break; \
|
||||
} \
|
||||
PREFETCH_RUN(total_cycles, 1, -1, reads, 0, 0, 0, 0); \
|
||||
if (CNT_REG > 0) { \
|
||||
CPU_BLOCK_END(); \
|
||||
cpu_state.pc = cpu_state.oldpc; \
|
||||
return 1; \
|
||||
} \
|
||||
return cpu_state.abrt; \
|
||||
} \
|
||||
static int opREP_LODSL_##size(uint32_t fetchdat) \
|
||||
{ \
|
||||
int reads = 0, total_cycles = 0; \
|
||||
int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \
|
||||
if (trap) \
|
||||
cycles_end = cycles + 1; /*Force the instruction to end after only one iteration when trap flag set*/ \
|
||||
if (CNT_REG > 0) \
|
||||
SEG_CHECK_READ(cpu_state.ea_seg); \
|
||||
while (CNT_REG > 0) { \
|
||||
CHECK_READ_REP(cpu_state.ea_seg, SRC_REG, SRC_REG + 3UL); \
|
||||
EAX = readmeml(cpu_state.ea_seg->base, SRC_REG); \
|
||||
if (cpu_state.abrt) \
|
||||
return 1; \
|
||||
if (cpu_state.flags & D_FLAG) \
|
||||
SRC_REG -= 4; \
|
||||
else \
|
||||
SRC_REG += 4; \
|
||||
CNT_REG--; \
|
||||
cycles -= is486 ? 4 : 5; \
|
||||
reads++; \
|
||||
total_cycles += is486 ? 4 : 5; \
|
||||
if (cycles < cycles_end) \
|
||||
break; \
|
||||
} \
|
||||
PREFETCH_RUN(total_cycles, 1, -1, 0, reads, 0, 0, 0); \
|
||||
if (CNT_REG > 0) { \
|
||||
CPU_BLOCK_END(); \
|
||||
cpu_state.pc = cpu_state.oldpc; \
|
||||
return 1; \
|
||||
} \
|
||||
return cpu_state.abrt; \
|
||||
}
|
||||
|
||||
#define CHEK_READ(a, b, c)
|
||||
|
||||
#define REP_OPS_CMPS_SCAS(size, CNT_REG, SRC_REG, DEST_REG, FV) \
|
||||
static int opREP_CMPSB_##size(uint32_t fetchdat) \
|
||||
{ \
|
||||
int reads = 0, total_cycles = 0, tempz; \
|
||||
\
|
||||
addr64 = addr64_2 = 0x00000000; \
|
||||
\
|
||||
tempz = FV; \
|
||||
if ((CNT_REG > 0) && (FV == tempz)) { \
|
||||
uint8_t temp, temp2; \
|
||||
SEG_CHECK_READ(cpu_state.ea_seg); \
|
||||
SEG_CHECK_READ(&cpu_state.seg_es); \
|
||||
CHECK_READ(cpu_state.ea_seg, SRC_REG, SRC_REG); \
|
||||
CHECK_READ(&cpu_state.seg_es, DEST_REG, DEST_REG); \
|
||||
high_page = uncached = 0; \
|
||||
do_mmut_rb(cpu_state.ea_seg->base, SRC_REG, &addr64); \
|
||||
if (cpu_state.abrt) \
|
||||
return 1; \
|
||||
do_mmut_rb2(es, DEST_REG, &addr64_2); \
|
||||
if (cpu_state.abrt) \
|
||||
return 1; \
|
||||
temp = readmemb_n(cpu_state.ea_seg->base, SRC_REG, addr64); \
|
||||
if (cpu_state.abrt) \
|
||||
return 1; \
|
||||
temp2 = readmemb_n(es, DEST_REG, addr64_2); \
|
||||
if (cpu_state.abrt) \
|
||||
return 1; \
|
||||
\
|
||||
if (cpu_state.flags & D_FLAG) { \
|
||||
DEST_REG--; \
|
||||
SRC_REG--; \
|
||||
} else { \
|
||||
DEST_REG++; \
|
||||
SRC_REG++; \
|
||||
} \
|
||||
CNT_REG--; \
|
||||
cycles -= is486 ? 7 : 9; \
|
||||
reads += 2; \
|
||||
total_cycles += is486 ? 7 : 9; \
|
||||
setsub8(temp, temp2); \
|
||||
tempz = (ZF_SET()) ? 1 : 0; \
|
||||
} \
|
||||
PREFETCH_RUN(total_cycles, 1, -1, reads, 0, 0, 0, 0); \
|
||||
if ((CNT_REG > 0) && (FV == tempz)) { \
|
||||
CPU_BLOCK_END(); \
|
||||
cpu_state.pc = cpu_state.oldpc; \
|
||||
return 1; \
|
||||
} \
|
||||
return cpu_state.abrt; \
|
||||
} \
|
||||
static int opREP_CMPSW_##size(uint32_t fetchdat) \
|
||||
{ \
|
||||
int reads = 0, total_cycles = 0, tempz; \
|
||||
\
|
||||
addr64a[0] = addr64a[1] = 0x00000000; \
|
||||
addr64a_2[0] = addr64a_2[1] = 0x00000000; \
|
||||
\
|
||||
tempz = FV; \
|
||||
if ((CNT_REG > 0) && (FV == tempz)) { \
|
||||
uint16_t temp, temp2; \
|
||||
SEG_CHECK_READ(cpu_state.ea_seg); \
|
||||
SEG_CHECK_READ(&cpu_state.seg_es); \
|
||||
CHECK_READ(cpu_state.ea_seg, SRC_REG, SRC_REG + 1UL); \
|
||||
CHECK_READ(&cpu_state.seg_es, DEST_REG, DEST_REG + 1UL); \
|
||||
high_page = uncached = 0; \
|
||||
do_mmut_rw(cpu_state.ea_seg->base, SRC_REG, addr64a); \
|
||||
if (cpu_state.abrt) \
|
||||
return 1; \
|
||||
do_mmut_rw2(es, DEST_REG, addr64a_2); \
|
||||
if (cpu_state.abrt) \
|
||||
return 1; \
|
||||
temp = readmemw_n(cpu_state.ea_seg->base, SRC_REG, addr64a); \
|
||||
if (cpu_state.abrt) \
|
||||
return 1; \
|
||||
temp2 = readmemw_n(es, DEST_REG, addr64a_2); \
|
||||
if (cpu_state.abrt) \
|
||||
return 1; \
|
||||
\
|
||||
if (cpu_state.flags & D_FLAG) { \
|
||||
DEST_REG -= 2; \
|
||||
SRC_REG -= 2; \
|
||||
} else { \
|
||||
DEST_REG += 2; \
|
||||
SRC_REG += 2; \
|
||||
} \
|
||||
CNT_REG--; \
|
||||
cycles -= is486 ? 7 : 9; \
|
||||
reads += 2; \
|
||||
total_cycles += is486 ? 7 : 9; \
|
||||
setsub16(temp, temp2); \
|
||||
tempz = (ZF_SET()) ? 1 : 0; \
|
||||
} \
|
||||
PREFETCH_RUN(total_cycles, 1, -1, reads, 0, 0, 0, 0); \
|
||||
if ((CNT_REG > 0) && (FV == tempz)) { \
|
||||
CPU_BLOCK_END(); \
|
||||
cpu_state.pc = cpu_state.oldpc; \
|
||||
return 1; \
|
||||
} \
|
||||
return cpu_state.abrt; \
|
||||
} \
|
||||
static int opREP_CMPSL_##size(uint32_t fetchdat) \
|
||||
{ \
|
||||
int reads = 0, total_cycles = 0, tempz; \
|
||||
\
|
||||
addr64a[0] = addr64a[1] = addr64a[2] = addr64a[3] = 0x00000000; \
|
||||
addr64a_2[0] = addr64a_2[1] = addr64a_2[2] = addr64a_2[3] = 0x00000000; \
|
||||
\
|
||||
tempz = FV; \
|
||||
if ((CNT_REG > 0) && (FV == tempz)) { \
|
||||
uint32_t temp, temp2; \
|
||||
SEG_CHECK_READ(cpu_state.ea_seg); \
|
||||
SEG_CHECK_READ(&cpu_state.seg_es); \
|
||||
CHECK_READ(cpu_state.ea_seg, SRC_REG, SRC_REG + 3UL); \
|
||||
CHECK_READ(&cpu_state.seg_es, DEST_REG, DEST_REG + 3UL); \
|
||||
high_page = uncached = 0; \
|
||||
do_mmut_rl(cpu_state.ea_seg->base, SRC_REG, addr64a); \
|
||||
if (cpu_state.abrt) \
|
||||
return 1; \
|
||||
do_mmut_rl2(es, DEST_REG, addr64a_2); \
|
||||
if (cpu_state.abrt) \
|
||||
return 1; \
|
||||
temp = readmeml_n(cpu_state.ea_seg->base, SRC_REG, addr64a); \
|
||||
if (cpu_state.abrt) \
|
||||
return 1; \
|
||||
temp2 = readmeml_n(es, DEST_REG, addr64a_2); \
|
||||
if (cpu_state.abrt) \
|
||||
return 1; \
|
||||
\
|
||||
if (cpu_state.flags & D_FLAG) { \
|
||||
DEST_REG -= 4; \
|
||||
SRC_REG -= 4; \
|
||||
} else { \
|
||||
DEST_REG += 4; \
|
||||
SRC_REG += 4; \
|
||||
} \
|
||||
CNT_REG--; \
|
||||
cycles -= is486 ? 7 : 9; \
|
||||
reads += 2; \
|
||||
total_cycles += is486 ? 7 : 9; \
|
||||
setsub32(temp, temp2); \
|
||||
tempz = (ZF_SET()) ? 1 : 0; \
|
||||
} \
|
||||
PREFETCH_RUN(total_cycles, 1, -1, 0, reads, 0, 0, 0); \
|
||||
if ((CNT_REG > 0) && (FV == tempz)) { \
|
||||
CPU_BLOCK_END(); \
|
||||
cpu_state.pc = cpu_state.oldpc; \
|
||||
return 1; \
|
||||
} \
|
||||
return cpu_state.abrt; \
|
||||
} \
|
||||
\
|
||||
static int opREP_SCASB_##size(uint32_t fetchdat) \
|
||||
{ \
|
||||
int reads = 0, total_cycles = 0, tempz; \
|
||||
int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \
|
||||
if (trap) \
|
||||
cycles_end = cycles + 1; /*Force the instruction to end after only one iteration when trap flag set*/ \
|
||||
tempz = FV; \
|
||||
if ((CNT_REG > 0) && (FV == tempz)) \
|
||||
SEG_CHECK_READ(&cpu_state.seg_es); \
|
||||
while ((CNT_REG > 0) && (FV == tempz)) { \
|
||||
CHECK_READ_REP(&cpu_state.seg_es, DEST_REG, DEST_REG); \
|
||||
uint8_t temp = readmemb(es, DEST_REG); \
|
||||
if (cpu_state.abrt) \
|
||||
break; \
|
||||
setsub8(AL, temp); \
|
||||
tempz = (ZF_SET()) ? 1 : 0; \
|
||||
if (cpu_state.flags & D_FLAG) \
|
||||
DEST_REG--; \
|
||||
else \
|
||||
DEST_REG++; \
|
||||
CNT_REG--; \
|
||||
cycles -= is486 ? 5 : 8; \
|
||||
reads++; \
|
||||
total_cycles += is486 ? 5 : 8; \
|
||||
if (cycles < cycles_end) \
|
||||
break; \
|
||||
} \
|
||||
PREFETCH_RUN(total_cycles, 1, -1, reads, 0, 0, 0, 0); \
|
||||
if ((CNT_REG > 0) && (FV == tempz)) { \
|
||||
CPU_BLOCK_END(); \
|
||||
cpu_state.pc = cpu_state.oldpc; \
|
||||
return 1; \
|
||||
} \
|
||||
return cpu_state.abrt; \
|
||||
} \
|
||||
static int opREP_SCASW_##size(uint32_t fetchdat) \
|
||||
{ \
|
||||
int reads = 0, total_cycles = 0, tempz; \
|
||||
int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \
|
||||
if (trap) \
|
||||
cycles_end = cycles + 1; /*Force the instruction to end after only one iteration when trap flag set*/ \
|
||||
tempz = FV; \
|
||||
if ((CNT_REG > 0) && (FV == tempz)) \
|
||||
SEG_CHECK_READ(&cpu_state.seg_es); \
|
||||
while ((CNT_REG > 0) && (FV == tempz)) { \
|
||||
CHECK_READ_REP(&cpu_state.seg_es, DEST_REG, DEST_REG + 1UL); \
|
||||
uint16_t temp = readmemw(es, DEST_REG); \
|
||||
if (cpu_state.abrt) \
|
||||
break; \
|
||||
setsub16(AX, temp); \
|
||||
tempz = (ZF_SET()) ? 1 : 0; \
|
||||
if (cpu_state.flags & D_FLAG) \
|
||||
DEST_REG -= 2; \
|
||||
else \
|
||||
DEST_REG += 2; \
|
||||
CNT_REG--; \
|
||||
cycles -= is486 ? 5 : 8; \
|
||||
reads++; \
|
||||
total_cycles += is486 ? 5 : 8; \
|
||||
if (cycles < cycles_end) \
|
||||
break; \
|
||||
} \
|
||||
PREFETCH_RUN(total_cycles, 1, -1, reads, 0, 0, 0, 0); \
|
||||
if ((CNT_REG > 0) && (FV == tempz)) { \
|
||||
CPU_BLOCK_END(); \
|
||||
cpu_state.pc = cpu_state.oldpc; \
|
||||
return 1; \
|
||||
} \
|
||||
return cpu_state.abrt; \
|
||||
} \
|
||||
static int opREP_SCASL_##size(uint32_t fetchdat) \
|
||||
{ \
|
||||
int reads = 0, total_cycles = 0, tempz; \
|
||||
int cycles_end = cycles - ((is386 && cpu_use_dynarec) ? 1000 : 100); \
|
||||
if (trap) \
|
||||
cycles_end = cycles + 1; /*Force the instruction to end after only one iteration when trap flag set*/ \
|
||||
tempz = FV; \
|
||||
if ((CNT_REG > 0) && (FV == tempz)) \
|
||||
SEG_CHECK_READ(&cpu_state.seg_es); \
|
||||
while ((CNT_REG > 0) && (FV == tempz)) { \
|
||||
CHECK_READ_REP(&cpu_state.seg_es, DEST_REG, DEST_REG + 3UL); \
|
||||
uint32_t temp = readmeml(es, DEST_REG); \
|
||||
if (cpu_state.abrt) \
|
||||
break; \
|
||||
setsub32(EAX, temp); \
|
||||
tempz = (ZF_SET()) ? 1 : 0; \
|
||||
if (cpu_state.flags & D_FLAG) \
|
||||
DEST_REG -= 4; \
|
||||
else \
|
||||
DEST_REG += 4; \
|
||||
CNT_REG--; \
|
||||
cycles -= is486 ? 5 : 8; \
|
||||
reads++; \
|
||||
total_cycles += is486 ? 5 : 8; \
|
||||
if (cycles < cycles_end) \
|
||||
break; \
|
||||
} \
|
||||
PREFETCH_RUN(total_cycles, 1, -1, 0, reads, 0, 0, 0); \
|
||||
if ((CNT_REG > 0) && (FV == tempz)) { \
|
||||
CPU_BLOCK_END(); \
|
||||
cpu_state.pc = cpu_state.oldpc; \
|
||||
return 1; \
|
||||
} \
|
||||
return cpu_state.abrt; \
|
||||
}
|
||||
|
||||
REP_OPS(a16, CX, SI, DI)
|
||||
REP_OPS(a32, ECX, ESI, EDI)
|
||||
REP_OPS_CMPS_SCAS(a16_NE, CX, SI, DI, 0)
|
||||
REP_OPS_CMPS_SCAS(a16_E, CX, SI, DI, 1)
|
||||
REP_OPS_CMPS_SCAS(a32_NE, ECX, ESI, EDI, 0)
|
||||
REP_OPS_CMPS_SCAS(a32_E, ECX, ESI, EDI, 1)
|
||||
|
||||
static int
|
||||
opREPNE(uint32_t fetchdat)
|
||||
{
|
||||
fetchdat = fastreadl(cs + cpu_state.pc);
|
||||
if (cpu_state.abrt)
|
||||
return 1;
|
||||
cpu_state.pc++;
|
||||
|
||||
CLOCK_CYCLES(2);
|
||||
PREFETCH_PREFIX();
|
||||
if (x86_2386_opcodes_REPNE[(fetchdat & 0xff) | cpu_state.op32])
|
||||
return x86_2386_opcodes_REPNE[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8);
|
||||
return x86_2386_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8);
|
||||
}
|
||||
static int
|
||||
opREPE(uint32_t fetchdat)
|
||||
{
|
||||
fetchdat = fastreadl(cs + cpu_state.pc);
|
||||
if (cpu_state.abrt)
|
||||
return 1;
|
||||
cpu_state.pc++;
|
||||
|
||||
CLOCK_CYCLES(2);
|
||||
PREFETCH_PREFIX();
|
||||
if (x86_2386_opcodes_REPE[(fetchdat & 0xff) | cpu_state.op32])
|
||||
return x86_2386_opcodes_REPE[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8);
|
||||
return x86_2386_opcodes[(fetchdat & 0xff) | cpu_state.op32](fetchdat >> 8);
|
||||
}
|
||||
1055
src/cpu/x86_ops_string_2386.h
Normal file
1055
src/cpu/x86_ops_string_2386.h
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1408,6 +1408,7 @@ const OpFn OP_TABLE(sf_fpu_da_a32)[256] = {
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
#ifndef OPS_286_386
|
||||
const OpFn OP_TABLE(sf_fpu_686_da_a16)[256] = {
|
||||
// clang-format off
|
||||
sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16, sf_FADDil_a16,
|
||||
@@ -1487,6 +1488,7 @@ const OpFn OP_TABLE(sf_fpu_686_da_a32)[256] = {
|
||||
ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32,
|
||||
// clang-format on
|
||||
};
|
||||
#endif
|
||||
|
||||
const OpFn OP_TABLE(sf_fpu_287_db_a16)[256] = {
|
||||
// clang-format off
|
||||
@@ -1648,6 +1650,7 @@ const OpFn OP_TABLE(sf_fpu_db_a32)[256] = {
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
#ifndef OPS_286_386
|
||||
const OpFn OP_TABLE(sf_fpu_686_db_a16)[256] = {
|
||||
// clang-format off
|
||||
sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16, sf_FILDil_a16,
|
||||
@@ -1726,6 +1729,7 @@ const OpFn OP_TABLE(sf_fpu_686_db_a32)[256] = {
|
||||
ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32,
|
||||
// clang-format on
|
||||
};
|
||||
#endif
|
||||
|
||||
const OpFn OP_TABLE(sf_fpu_287_dc_a16)[32] = {
|
||||
// clang-format off
|
||||
@@ -2243,6 +2247,7 @@ const OpFn OP_TABLE(sf_fpu_df_a32)[256] = {
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
#ifndef OPS_286_386
|
||||
const OpFn OP_TABLE(sf_fpu_686_df_a16)[256] = {
|
||||
// clang-format off
|
||||
sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16, sf_FILDiw_a16,
|
||||
@@ -2322,6 +2327,7 @@ const OpFn OP_TABLE(sf_fpu_686_df_a32)[256] = {
|
||||
ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32,
|
||||
// clang-format on
|
||||
};
|
||||
#endif
|
||||
|
||||
const OpFn OP_TABLE(fpu_d8_a16)[32] = {
|
||||
// clang-format off
|
||||
@@ -2661,6 +2667,7 @@ const OpFn OP_TABLE(fpu_da_a32)[256] = {
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
#ifndef OPS_286_386
|
||||
const OpFn OP_TABLE(fpu_686_da_a16)[256] = {
|
||||
// clang-format off
|
||||
opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16, opFADDil_a16,
|
||||
@@ -2740,6 +2747,7 @@ const OpFn OP_TABLE(fpu_686_da_a32)[256] = {
|
||||
ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32,
|
||||
// clang-format on
|
||||
};
|
||||
#endif
|
||||
|
||||
const OpFn OP_TABLE(fpu_287_db_a16)[256] = {
|
||||
// clang-format off
|
||||
@@ -2901,6 +2909,7 @@ const OpFn OP_TABLE(fpu_db_a32)[256] = {
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
#ifndef OPS_286_386
|
||||
const OpFn OP_TABLE(fpu_686_db_a16)[256] = {
|
||||
// clang-format off
|
||||
opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16, opFILDil_a16,
|
||||
@@ -2979,6 +2988,7 @@ const OpFn OP_TABLE(fpu_686_db_a32)[256] = {
|
||||
ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32,
|
||||
// clang-format on
|
||||
};
|
||||
#endif
|
||||
|
||||
const OpFn OP_TABLE(fpu_287_dc_a16)[32] = {
|
||||
// clang-format off
|
||||
@@ -3496,6 +3506,7 @@ const OpFn OP_TABLE(fpu_df_a32)[256] = {
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
#ifndef OPS_286_386
|
||||
const OpFn OP_TABLE(fpu_686_df_a16)[256] = {
|
||||
// clang-format off
|
||||
opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16, opFILDiw_a16,
|
||||
@@ -3575,6 +3586,7 @@ const OpFn OP_TABLE(fpu_686_df_a32)[256] = {
|
||||
ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32, ILLEGAL_a32,
|
||||
// clang-format on
|
||||
};
|
||||
#endif
|
||||
|
||||
const OpFn OP_TABLE(nofpu_a16)[256] = {
|
||||
// clang-format off
|
||||
|
||||
@@ -242,6 +242,7 @@ opFUCOMPP(uint32_t fetchdat)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef OPS_286_386
|
||||
static int
|
||||
opFCOMI(uint32_t fetchdat)
|
||||
{
|
||||
@@ -274,6 +275,7 @@ opFCOMIP(uint32_t fetchdat)
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static int
|
||||
opFDIV(uint32_t fetchdat)
|
||||
@@ -476,6 +478,7 @@ opFUCOMP(uint32_t fetchdat)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef OPS_286_386
|
||||
static int
|
||||
opFUCOMI(uint32_t fetchdat)
|
||||
{
|
||||
@@ -508,3 +511,4 @@ opFUCOMIP(uint32_t fetchdat)
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -1045,6 +1045,7 @@ opFSTCW_a32(uint32_t fetchdat)
|
||||
#endif
|
||||
|
||||
#ifndef FPU_8087
|
||||
#ifndef OPS_286_386
|
||||
# define opFCMOV(condition) \
|
||||
static int opFCMOV##condition(uint32_t fetchdat) \
|
||||
{ \
|
||||
@@ -1073,3 +1074,4 @@ opFCMOV(NBE)
|
||||
opFCMOV(NU)
|
||||
// clang-format on
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -224,6 +224,7 @@ next_ins:
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef OPS_286_386
|
||||
static int
|
||||
sf_FCOMI_st0_stj(uint32_t fetchdat)
|
||||
{
|
||||
@@ -285,6 +286,7 @@ next_ins:
|
||||
CONCURRENCY_CYCLES((fpu_type >= FPU_487SX) ? (x87_concurrency.fcom) : (x87_concurrency.fcom * cpu_multi));
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
sf_FUCOM_sti(uint32_t fetchdat)
|
||||
@@ -346,6 +348,7 @@ next_ins:
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef OPS_286_386
|
||||
static int
|
||||
sf_FUCOMI_st0_stj(uint32_t fetchdat)
|
||||
{
|
||||
@@ -407,6 +410,7 @@ next_ins:
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static int
|
||||
sf_FTST(uint32_t fetchdat)
|
||||
|
||||
@@ -1279,6 +1279,7 @@ sf_FSTP_sti(uint32_t fetchdat)
|
||||
}
|
||||
|
||||
#ifndef FPU_8087
|
||||
#ifndef OPS_286_386
|
||||
# define sf_FCMOV(condition) \
|
||||
static int sf_FCMOV##condition(uint32_t fetchdat) \
|
||||
{ \
|
||||
@@ -1310,3 +1311,4 @@ sf_FCMOV(NBE)
|
||||
sf_FCMOV(NU)
|
||||
// clang-format on
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -83,7 +83,8 @@ extern lpt_port_t lpt_ports[PARALLEL_MAX];
|
||||
extern void lpt_write(uint16_t port, uint8_t val, void *priv);
|
||||
extern uint8_t lpt_read(uint16_t port, void *priv);
|
||||
|
||||
extern void lpt_irq(void *priv, int raise);
|
||||
extern uint8_t lpt_read_status(int port);
|
||||
extern void lpt_irq(void *priv, int raise);
|
||||
|
||||
extern char *lpt_device_get_name(int id);
|
||||
extern char *lpt_device_get_internal_name(int id);
|
||||
|
||||
@@ -331,6 +331,24 @@ extern void writememll_no_mmut(uint32_t addr, uint32_t *a64, uint32_t val);
|
||||
|
||||
extern void do_mmutranslate(uint32_t addr, uint32_t *a64, int num, int write);
|
||||
|
||||
extern uint8_t readmembl_2386(uint32_t addr);
|
||||
extern void writemembl_2386(uint32_t addr, uint8_t val);
|
||||
extern uint16_t readmemwl_2386(uint32_t addr);
|
||||
extern void writememwl_2386(uint32_t addr, uint16_t val);
|
||||
extern uint32_t readmemll_2386(uint32_t addr);
|
||||
extern void writememll_2386(uint32_t addr, uint32_t val);
|
||||
extern uint64_t readmemql_2386(uint32_t addr);
|
||||
extern void writememql_2386(uint32_t addr, uint64_t val);
|
||||
|
||||
extern uint8_t readmembl_no_mmut_2386(uint32_t addr, uint32_t a64);
|
||||
extern void writemembl_no_mmut_2386(uint32_t addr, uint32_t a64, uint8_t val);
|
||||
extern uint16_t readmemwl_no_mmut_2386(uint32_t addr, uint32_t *a64);
|
||||
extern void writememwl_no_mmut_2386(uint32_t addr, uint32_t *a64, uint16_t val);
|
||||
extern uint32_t readmemll_no_mmut_2386(uint32_t addr, uint32_t *a64);
|
||||
extern void writememll_no_mmut_2386(uint32_t addr, uint32_t *a64, uint32_t val);
|
||||
|
||||
extern void do_mmutranslate_2386(uint32_t addr, uint32_t *a64, int num, int write);
|
||||
|
||||
extern uint8_t *getpccache(uint32_t a);
|
||||
extern uint64_t mmutranslatereal(uint32_t addr, int rw);
|
||||
extern uint32_t mmutranslatereal32(uint32_t addr, int rw);
|
||||
@@ -429,6 +447,9 @@ extern void mem_close(void);
|
||||
extern void mem_reset(void);
|
||||
extern void mem_remap_top(int kb);
|
||||
|
||||
extern mem_mapping_t *read_mapping[MEM_MAPPINGS_NO];
|
||||
extern mem_mapping_t *write_mapping[MEM_MAPPINGS_NO];
|
||||
|
||||
#ifdef EMU_CPU_H
|
||||
static __inline uint32_t
|
||||
get_phys(uint32_t addr)
|
||||
|
||||
14
src/lpt.c
14
src/lpt.c
@@ -165,6 +165,20 @@ lpt_read(uint16_t port, void *priv)
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint8_t
|
||||
lpt_read_status(int port)
|
||||
{
|
||||
lpt_port_t *dev = &(lpt_ports[port]);
|
||||
uint8_t ret = 0xff;
|
||||
|
||||
if (dev->dt && dev->dt->read_status && dev->priv)
|
||||
ret = dev->dt->read_status(dev->priv) | 0x07;
|
||||
else
|
||||
ret = 0xdf;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
lpt_irq(void *priv, int raise)
|
||||
{
|
||||
|
||||
@@ -13,5 +13,5 @@
|
||||
# Copyright 2020-2021 David Hrdlička.
|
||||
#
|
||||
|
||||
add_library(mem OBJECT catalyst_flash.c i2c_eeprom.c intel_flash.c mem.c rom.c
|
||||
row.c smram.c spd.c sst_flash.c)
|
||||
add_library(mem OBJECT catalyst_flash.c i2c_eeprom.c intel_flash.c mem.c mmu_2386.c
|
||||
rom.c row.c smram.c spd.c sst_flash.c)
|
||||
|
||||
@@ -119,14 +119,15 @@ int purgeable_page_count = 0;
|
||||
|
||||
uint8_t high_page = 0; /* if a high (> 4 gb) page was detected */
|
||||
|
||||
mem_mapping_t *read_mapping[MEM_MAPPINGS_NO];
|
||||
mem_mapping_t *write_mapping[MEM_MAPPINGS_NO];
|
||||
|
||||
/* FIXME: re-do this with a 'mem_ops' struct. */
|
||||
static uint8_t *page_lookupp; /* pagetable mmu_perm lookup */
|
||||
static uint8_t *readlookupp;
|
||||
static uint8_t *writelookupp;
|
||||
static mem_mapping_t *base_mapping;
|
||||
static mem_mapping_t *last_mapping;
|
||||
static mem_mapping_t *read_mapping[MEM_MAPPINGS_NO];
|
||||
static mem_mapping_t *write_mapping[MEM_MAPPINGS_NO];
|
||||
static mem_mapping_t *read_mapping_bus[MEM_MAPPINGS_NO];
|
||||
static mem_mapping_t *write_mapping_bus[MEM_MAPPINGS_NO];
|
||||
static uint8_t *_mem_exec[MEM_MAPPINGS_NO];
|
||||
|
||||
901
src/mem/mmu_2386.c
Normal file
901
src/mem/mmu_2386.c
Normal file
@@ -0,0 +1,901 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* Memory handling and MMU.
|
||||
*
|
||||
* Authors: Sarah Walker, <tommowalker@tommowalker.co.uk>
|
||||
* Miran Grca, <mgrca8@gmail.com>
|
||||
* Fred N. van Kempen, <decwiz@yahoo.com>
|
||||
*
|
||||
* Copyright 2008-2020 Sarah Walker.
|
||||
* Copyright 2016-2020 Miran Grca.
|
||||
* Copyright 2017-2020 Fred N. van Kempen.
|
||||
*/
|
||||
#include <inttypes.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <wchar.h>
|
||||
#define HAVE_STDARG_H
|
||||
#include <86box/86box.h>
|
||||
#include <86box/version.h>
|
||||
#include "cpu.h"
|
||||
#include "x86_ops.h"
|
||||
#include "x86.h"
|
||||
#include <86box/machine.h>
|
||||
#include <86box/m_xt_xi8088.h>
|
||||
#include <86box/config.h>
|
||||
#include <86box/io.h>
|
||||
#include <86box/mem.h>
|
||||
#include <86box/plat.h>
|
||||
#include <86box/rom.h>
|
||||
#include <86box/gdbstub.h>
|
||||
#ifdef USE_DYNAREC
|
||||
# include "codegen_public.h"
|
||||
#else
|
||||
#ifdef USE_NEW_DYNAREC
|
||||
# define PAGE_MASK_SHIFT 6
|
||||
#else
|
||||
# define PAGE_MASK_INDEX_MASK 3
|
||||
# define PAGE_MASK_INDEX_SHIFT 10
|
||||
# define PAGE_MASK_SHIFT 4
|
||||
#endif
|
||||
# define PAGE_MASK_MASK 63
|
||||
#endif
|
||||
#if (!defined(USE_DYNAREC) && defined(USE_NEW_DYNAREC))
|
||||
#define BLOCK_PC_INVALID 0xffffffff
|
||||
#define BLOCK_INVALID 0
|
||||
#endif
|
||||
|
||||
|
||||
#define mmutranslate_read_2386(addr) mmutranslatereal_2386(addr,0)
|
||||
#define mmutranslate_write_2386(addr) mmutranslatereal_2386(addr,1)
|
||||
|
||||
|
||||
uint64_t
|
||||
mmutranslatereal_2386(uint32_t addr, int rw)
|
||||
{
|
||||
uint32_t temp, temp2, temp3;
|
||||
uint32_t addr2;
|
||||
|
||||
if (cpu_state.abrt)
|
||||
return 0xffffffffffffffffULL;
|
||||
|
||||
addr2 = ((cr3 & ~0xfff) + ((addr >> 20) & 0xffc));
|
||||
temp = temp2 = mem_readl_phys(addr2);
|
||||
if (!(temp & 1)) {
|
||||
cr2 = addr;
|
||||
temp &= 1;
|
||||
if (CPL == 3) temp |= 4;
|
||||
if (rw) temp |= 2;
|
||||
cpu_state.abrt = ABRT_PF;
|
||||
abrt_error = temp;
|
||||
return 0xffffffffffffffffULL;
|
||||
}
|
||||
|
||||
temp = mem_readl_phys((temp & ~0xfff) + ((addr >> 10) & 0xffc));
|
||||
temp3 = temp & temp2;
|
||||
if (!(temp & 1) || ((CPL == 3) && !(temp3 & 4) && !cpl_override) || (rw && !(temp3 & 2) && (((CPL == 3) && !cpl_override) || (is486 && (cr0 & WP_FLAG))))) {
|
||||
cr2 = addr;
|
||||
temp &= 1;
|
||||
if (CPL == 3)
|
||||
temp |= 4;
|
||||
if (rw)
|
||||
temp |= 2;
|
||||
cpu_state.abrt = ABRT_PF;
|
||||
abrt_error = temp;
|
||||
return 0xffffffffffffffffULL;
|
||||
}
|
||||
|
||||
mmu_perm = temp & 4;
|
||||
mem_writel_phys(addr2, mem_readl_phys(addr) | 0x20);
|
||||
mem_writel_phys((temp2 & ~0xfff) + ((addr >> 10) & 0xffc), mem_readl_phys((temp2 & ~0xfff) + ((addr >> 10) & 0xffc)) | (rw ? 0x60 : 0x20));
|
||||
|
||||
return (uint64_t) ((temp & ~0xfff) + (addr & 0xfff));
|
||||
}
|
||||
|
||||
|
||||
uint64_t
|
||||
mmutranslate_noabrt_2386(uint32_t addr, int rw)
|
||||
{
|
||||
uint32_t temp,temp2,temp3;
|
||||
uint32_t addr2;
|
||||
|
||||
if (cpu_state.abrt)
|
||||
return 0xffffffffffffffffULL;
|
||||
|
||||
addr2 = ((cr3 & ~0xfff) + ((addr >> 20) & 0xffc));
|
||||
temp = temp2 = mem_readl_phys(addr2);
|
||||
|
||||
if (! (temp & 1))
|
||||
return 0xffffffffffffffffULL;
|
||||
|
||||
temp = mem_readl_phys((temp & ~0xfff) + ((addr >> 10) & 0xffc));
|
||||
temp3 = temp & temp2;
|
||||
|
||||
if (!(temp & 1) || ((CPL == 3) && !(temp3 & 4) && !cpl_override) || (rw && !(temp3 & 2) && ((CPL == 3) || (cr0 & WP_FLAG))))
|
||||
return 0xffffffffffffffffULL;
|
||||
|
||||
return (uint64_t) ((temp & ~0xfff) + (addr & 0xfff));
|
||||
}
|
||||
|
||||
|
||||
uint8_t
|
||||
readmembl_2386(uint32_t addr)
|
||||
{
|
||||
mem_mapping_t *map;
|
||||
uint64_t a;
|
||||
|
||||
GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_READ, 1);
|
||||
|
||||
addr64 = (uint64_t) addr;
|
||||
mem_logical_addr = addr;
|
||||
|
||||
high_page = 0;
|
||||
|
||||
if (cr0 >> 31) {
|
||||
a = mmutranslate_read_2386(addr);
|
||||
addr64 = (uint32_t) a;
|
||||
|
||||
if (a > 0xffffffffULL)
|
||||
return 0xff;
|
||||
}
|
||||
addr = (uint32_t) (addr64 & rammask);
|
||||
|
||||
map = read_mapping[addr >> MEM_GRANULARITY_BITS];
|
||||
if (map && map->read_b)
|
||||
return map->read_b(addr, map->priv);
|
||||
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
writemembl_2386(uint32_t addr, uint8_t val)
|
||||
{
|
||||
mem_mapping_t *map;
|
||||
uint64_t a;
|
||||
|
||||
GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_WRITE, 1);
|
||||
|
||||
addr64 = (uint64_t) addr;
|
||||
mem_logical_addr = addr;
|
||||
|
||||
high_page = 0;
|
||||
|
||||
if (cr0 >> 31) {
|
||||
a = mmutranslate_write_2386(addr);
|
||||
addr64 = (uint32_t) a;
|
||||
|
||||
if (a > 0xffffffffULL)
|
||||
return;
|
||||
}
|
||||
addr = (uint32_t) (addr64 & rammask);
|
||||
|
||||
map = write_mapping[addr >> MEM_GRANULARITY_BITS];
|
||||
if (map && map->write_b)
|
||||
map->write_b(addr, val, map->priv);
|
||||
}
|
||||
|
||||
|
||||
/* Read a byte from memory without MMU translation - result of previous MMU translation passed as value. */
|
||||
uint8_t
|
||||
readmembl_no_mmut_2386(uint32_t addr, uint32_t a64)
|
||||
{
|
||||
mem_mapping_t *map;
|
||||
|
||||
GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_READ, 1);
|
||||
|
||||
mem_logical_addr = addr;
|
||||
|
||||
if (cr0 >> 31) {
|
||||
if (cpu_state.abrt || high_page)
|
||||
return 0xff;
|
||||
|
||||
addr = a64 & rammask;
|
||||
} else
|
||||
addr &= rammask;
|
||||
|
||||
map = read_mapping[addr >> MEM_GRANULARITY_BITS];
|
||||
if (map && map->read_b)
|
||||
return map->read_b(addr, map->priv);
|
||||
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
|
||||
/* Write a byte to memory without MMU translation - result of previous MMU translation passed as value. */
|
||||
void
|
||||
writemembl_no_mmut_2386(uint32_t addr, uint32_t a64, uint8_t val)
|
||||
{
|
||||
mem_mapping_t *map;
|
||||
|
||||
GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_WRITE, 1);
|
||||
|
||||
mem_logical_addr = addr;
|
||||
|
||||
if (cr0 >> 31) {
|
||||
if (cpu_state.abrt || high_page)
|
||||
return;
|
||||
|
||||
addr = a64 & rammask;
|
||||
} else
|
||||
addr &= rammask;
|
||||
|
||||
map = write_mapping[addr >> MEM_GRANULARITY_BITS];
|
||||
if (map && map->write_b)
|
||||
map->write_b(addr, val, map->priv);
|
||||
}
|
||||
|
||||
|
||||
uint16_t
|
||||
readmemwl_2386(uint32_t addr)
|
||||
{
|
||||
mem_mapping_t *map;
|
||||
int i;
|
||||
uint64_t a;
|
||||
|
||||
addr64a[0] = addr;
|
||||
addr64a[1] = addr + 1;
|
||||
GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_READ, 2);
|
||||
|
||||
mem_logical_addr = addr;
|
||||
|
||||
high_page = 0;
|
||||
|
||||
if (addr & 1) {
|
||||
if (!cpu_cyrix_alignment || (addr & 7) == 7)
|
||||
cycles -= timing_misaligned;
|
||||
if ((addr & 0xfff) > 0xffe) {
|
||||
if (cr0 >> 31) {
|
||||
for (i = 0; i < 2; i++) {
|
||||
a = mmutranslate_read_2386(addr + i);
|
||||
addr64a[i] = (uint32_t) a;
|
||||
|
||||
if (a > 0xffffffffULL)
|
||||
return 0xffff;
|
||||
}
|
||||
}
|
||||
|
||||
return readmembl_no_mmut(addr, addr64a[0]) |
|
||||
(((uint16_t) readmembl_no_mmut(addr + 1, addr64a[1])) << 8);
|
||||
}
|
||||
}
|
||||
|
||||
if (cr0 >> 31) {
|
||||
a = mmutranslate_read_2386(addr);
|
||||
addr64a[0] = (uint32_t) a;
|
||||
|
||||
if (a > 0xffffffffULL)
|
||||
return 0xffff;
|
||||
} else
|
||||
addr64a[0] = (uint64_t) addr;
|
||||
|
||||
addr = addr64a[0] & rammask;
|
||||
|
||||
map = read_mapping[addr >> MEM_GRANULARITY_BITS];
|
||||
|
||||
if (map && map->read_w)
|
||||
return map->read_w(addr, map->priv);
|
||||
|
||||
if (map && map->read_b) {
|
||||
return map->read_b(addr, map->priv) |
|
||||
((uint16_t) (map->read_b(addr + 1, map->priv)) << 8);
|
||||
}
|
||||
|
||||
return 0xffff;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
writememwl_2386(uint32_t addr, uint16_t val)
|
||||
{
|
||||
mem_mapping_t *map;
|
||||
int i;
|
||||
uint64_t a;
|
||||
|
||||
addr64a[0] = addr;
|
||||
addr64a[1] = addr + 1;
|
||||
GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_WRITE, 2);
|
||||
|
||||
mem_logical_addr = addr;
|
||||
|
||||
high_page = 0;
|
||||
|
||||
if (addr & 1) {
|
||||
if (!cpu_cyrix_alignment || (addr & 7) == 7)
|
||||
cycles -= timing_misaligned;
|
||||
if ((addr & 0xfff) > 0xffe) {
|
||||
if (cr0 >> 31) {
|
||||
for (i = 0; i < 2; i++) {
|
||||
a = mmutranslate_write_2386(addr + i);
|
||||
addr64a[i] = (uint32_t) a;
|
||||
|
||||
if (a > 0xffffffffULL)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* No need to waste precious CPU host cycles on mmutranslate's that were already done, just pass
|
||||
their result as a parameter to be used if needed. */
|
||||
writemembl_no_mmut(addr, addr64a[0], val);
|
||||
writemembl_no_mmut(addr + 1, addr64a[1], val >> 8);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (cr0 >> 31) {
|
||||
a = mmutranslate_write_2386(addr);
|
||||
addr64a[0] = (uint32_t) a;
|
||||
|
||||
if (a > 0xffffffffULL)
|
||||
return;
|
||||
}
|
||||
|
||||
addr = addr64a[0] & rammask;
|
||||
|
||||
map = write_mapping[addr >> MEM_GRANULARITY_BITS];
|
||||
|
||||
if (map && map->write_w) {
|
||||
map->write_w(addr, val, map->priv);
|
||||
return;
|
||||
}
|
||||
|
||||
if (map && map->write_b) {
|
||||
map->write_b(addr, val, map->priv);
|
||||
map->write_b(addr + 1, val >> 8, map->priv);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Read a word from memory without MMU translation - results of previous MMU translation passed as array. */
|
||||
uint16_t
|
||||
readmemwl_no_mmut_2386(uint32_t addr, uint32_t *a64)
|
||||
{
|
||||
mem_mapping_t *map;
|
||||
|
||||
GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_READ, 2);
|
||||
|
||||
mem_logical_addr = addr;
|
||||
|
||||
if (addr & 1) {
|
||||
if (!cpu_cyrix_alignment || (addr & 7) == 7)
|
||||
cycles -= timing_misaligned;
|
||||
if ((addr & 0xfff) > 0xffe) {
|
||||
if (cr0 >> 31) {
|
||||
if (cpu_state.abrt || high_page)
|
||||
return 0xffff;
|
||||
}
|
||||
|
||||
return readmembl_no_mmut(addr, a64[0]) |
|
||||
(((uint16_t) readmembl_no_mmut(addr + 1, a64[1])) << 8);
|
||||
}
|
||||
}
|
||||
|
||||
if (cr0 >> 31) {
|
||||
if (cpu_state.abrt || high_page)
|
||||
return 0xffff;
|
||||
|
||||
addr = (uint32_t) (a64[0] & rammask);
|
||||
} else
|
||||
addr &= rammask;
|
||||
|
||||
map = read_mapping[addr >> MEM_GRANULARITY_BITS];
|
||||
|
||||
if (map && map->read_w)
|
||||
return map->read_w(addr, map->priv);
|
||||
|
||||
if (map && map->read_b) {
|
||||
return map->read_b(addr, map->priv) |
|
||||
((uint16_t) (map->read_b(addr + 1, map->priv)) << 8);
|
||||
}
|
||||
|
||||
return 0xffff;
|
||||
}
|
||||
|
||||
|
||||
/* Write a word to memory without MMU translation - results of previous MMU translation passed as array. */
|
||||
void
|
||||
writememwl_no_mmut_2386(uint32_t addr, uint32_t *a64, uint16_t val)
|
||||
{
|
||||
mem_mapping_t *map;
|
||||
|
||||
GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_WRITE, 2);
|
||||
|
||||
mem_logical_addr = addr;
|
||||
|
||||
if (addr & 1) {
|
||||
if (!cpu_cyrix_alignment || (addr & 7) == 7)
|
||||
cycles -= timing_misaligned;
|
||||
if ((addr & 0xfff) > 0xffe) {
|
||||
if (cr0 >> 31) {
|
||||
if (cpu_state.abrt || high_page)
|
||||
return;
|
||||
}
|
||||
|
||||
writemembl_no_mmut(addr, a64[0], val);
|
||||
writemembl_no_mmut(addr + 1, a64[1], val >> 8);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (cr0 >> 31) {
|
||||
if (cpu_state.abrt || high_page)
|
||||
return;
|
||||
|
||||
addr = (uint32_t) (a64[0] & rammask);
|
||||
} else
|
||||
addr &= rammask;
|
||||
|
||||
map = write_mapping[addr >> MEM_GRANULARITY_BITS];
|
||||
|
||||
if (map && map->write_w) {
|
||||
map->write_w(addr, val, map->priv);
|
||||
return;
|
||||
}
|
||||
|
||||
if (map && map->write_b) {
|
||||
map->write_b(addr, val, map->priv);
|
||||
map->write_b(addr + 1, val >> 8, map->priv);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint32_t
|
||||
readmemll_2386(uint32_t addr)
|
||||
{
|
||||
mem_mapping_t *map;
|
||||
int i;
|
||||
uint64_t a = 0x0000000000000000ULL;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
addr64a[i] = (uint64_t) (addr + i);
|
||||
GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_READ, 4);
|
||||
|
||||
mem_logical_addr = addr;
|
||||
|
||||
high_page = 0;
|
||||
|
||||
if (addr & 3) {
|
||||
if (!cpu_cyrix_alignment || (addr & 7) > 4)
|
||||
cycles -= timing_misaligned;
|
||||
if ((addr & 0xfff) > 0xffc) {
|
||||
if (cr0 >> 31) {
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (i == 0) {
|
||||
a = mmutranslate_read_2386(addr + i);
|
||||
addr64a[i] = (uint32_t) a;
|
||||
} else if (!((addr + i) & 0xfff)) {
|
||||
a = mmutranslate_read_2386(addr + 3);
|
||||
addr64a[i] = (uint32_t) a;
|
||||
if (!cpu_state.abrt) {
|
||||
a = (a & ~0xfffLL) | ((uint64_t) ((addr + i) & 0xfff));
|
||||
addr64a[i] = (uint32_t) a;
|
||||
}
|
||||
} else {
|
||||
a = (a & ~0xfffLL) | ((uint64_t) ((addr + i) & 0xfff));
|
||||
addr64a[i] = (uint32_t) a;
|
||||
}
|
||||
|
||||
if (a > 0xffffffffULL)
|
||||
return 0xffff;
|
||||
}
|
||||
}
|
||||
|
||||
/* No need to waste precious CPU host cycles on mmutranslate's that were already done, just pass
|
||||
their result as a parameter to be used if needed. */
|
||||
return readmemwl_no_mmut(addr, addr64a) |
|
||||
(((uint32_t) readmemwl_no_mmut(addr + 2, &(addr64a[2]))) << 16);
|
||||
}
|
||||
}
|
||||
|
||||
if (cr0 >> 31) {
|
||||
a = mmutranslate_read_2386(addr);
|
||||
addr64a[0] = (uint32_t) a;
|
||||
|
||||
if (a > 0xffffffffULL)
|
||||
return 0xffffffff;
|
||||
}
|
||||
|
||||
addr = addr64a[0] & rammask;
|
||||
|
||||
map = read_mapping[addr >> MEM_GRANULARITY_BITS];
|
||||
|
||||
if (map && map->read_l)
|
||||
return map->read_l(addr, map->priv);
|
||||
|
||||
if (map && map->read_w)
|
||||
return map->read_w(addr, map->priv) |
|
||||
((uint32_t) (map->read_w(addr + 2, map->priv)) << 16);
|
||||
|
||||
if (map && map->read_b)
|
||||
return map->read_b(addr, map->priv) |
|
||||
((uint32_t) (map->read_b(addr + 1, map->priv)) << 8) |
|
||||
((uint32_t) (map->read_b(addr + 2, map->priv)) << 16) |
|
||||
((uint32_t) (map->read_b(addr + 3, map->priv)) << 24);
|
||||
|
||||
return 0xffffffff;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
writememll_2386(uint32_t addr, uint32_t val)
|
||||
{
|
||||
mem_mapping_t *map;
|
||||
int i;
|
||||
uint64_t a = 0x0000000000000000ULL;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
addr64a[i] = (uint64_t) (addr + i);
|
||||
GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_WRITE, 4);
|
||||
|
||||
mem_logical_addr = addr;
|
||||
|
||||
high_page = 0;
|
||||
|
||||
if (addr & 3) {
|
||||
if (!cpu_cyrix_alignment || (addr & 7) > 4)
|
||||
cycles -= timing_misaligned;
|
||||
if ((addr & 0xfff) > 0xffc) {
|
||||
if (cr0 >> 31) {
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (i == 0) {
|
||||
a = mmutranslate_write_2386(addr + i);
|
||||
addr64a[i] = (uint32_t) a;
|
||||
} else if (!((addr + i) & 0xfff)) {
|
||||
a = mmutranslate_write_2386(addr + 3);
|
||||
addr64a[i] = (uint32_t) a;
|
||||
if (!cpu_state.abrt) {
|
||||
a = (a & ~0xfffLL) | ((uint64_t) ((addr + i) & 0xfff));
|
||||
addr64a[i] = (uint32_t) a;
|
||||
}
|
||||
} else {
|
||||
a = (a & ~0xfffLL) | ((uint64_t) ((addr + i) & 0xfff));
|
||||
addr64a[i] = (uint32_t) a;
|
||||
}
|
||||
|
||||
if (a > 0xffffffffULL)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* No need to waste precious CPU host cycles on mmutranslate's that were already done, just pass
|
||||
their result as a parameter to be used if needed. */
|
||||
writememwl_no_mmut(addr, &(addr64a[0]), val);
|
||||
writememwl_no_mmut(addr + 2, &(addr64a[2]), val >> 16);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (cr0 >> 31) {
|
||||
a = mmutranslate_write_2386(addr);
|
||||
addr64a[0] = (uint32_t) a;
|
||||
|
||||
if (a > 0xffffffffULL)
|
||||
return;
|
||||
}
|
||||
|
||||
addr = addr64a[0] & rammask;
|
||||
|
||||
map = write_mapping[addr >> MEM_GRANULARITY_BITS];
|
||||
|
||||
if (map && map->write_l) {
|
||||
map->write_l(addr, val, map->priv);
|
||||
return;
|
||||
}
|
||||
if (map && map->write_w) {
|
||||
map->write_w(addr, val, map->priv);
|
||||
map->write_w(addr + 2, val >> 16, map->priv);
|
||||
return;
|
||||
}
|
||||
if (map && map->write_b) {
|
||||
map->write_b(addr, val, map->priv);
|
||||
map->write_b(addr + 1, val >> 8, map->priv);
|
||||
map->write_b(addr + 2, val >> 16, map->priv);
|
||||
map->write_b(addr + 3, val >> 24, map->priv);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Read a long from memory without MMU translation - results of previous MMU translation passed as array. */
|
||||
uint32_t
|
||||
readmemll_no_mmut_2386(uint32_t addr, uint32_t *a64)
|
||||
{
|
||||
mem_mapping_t *map;
|
||||
|
||||
GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_READ, 4);
|
||||
|
||||
mem_logical_addr = addr;
|
||||
|
||||
if (addr & 3) {
|
||||
if (!cpu_cyrix_alignment || (addr & 7) > 4)
|
||||
cycles -= timing_misaligned;
|
||||
if ((addr & 0xfff) > 0xffc) {
|
||||
if (cr0 >> 31) {
|
||||
if (cpu_state.abrt || high_page)
|
||||
return 0xffffffff;
|
||||
}
|
||||
|
||||
return readmemwl_no_mmut(addr, a64) |
|
||||
((uint32_t) (readmemwl_no_mmut(addr + 2, &(a64[2]))) << 16);
|
||||
}
|
||||
}
|
||||
|
||||
if (cr0 >> 31) {
|
||||
if (cpu_state.abrt || high_page)
|
||||
return 0xffffffff;
|
||||
|
||||
addr = (uint32_t) (a64[0] & rammask);
|
||||
} else
|
||||
addr &= rammask;
|
||||
|
||||
map = read_mapping[addr >> MEM_GRANULARITY_BITS];
|
||||
|
||||
if (map && map->read_l)
|
||||
return map->read_l(addr, map->priv);
|
||||
|
||||
if (map && map->read_w)
|
||||
return map->read_w(addr, map->priv) |
|
||||
((uint32_t) (map->read_w(addr + 2, map->priv)) << 16);
|
||||
|
||||
if (map && map->read_b)
|
||||
return map->read_b(addr, map->priv) |
|
||||
((uint32_t) (map->read_b(addr + 1, map->priv)) << 8) |
|
||||
((uint32_t) (map->read_b(addr + 2, map->priv)) << 16) |
|
||||
((uint32_t) (map->read_b(addr + 3, map->priv)) << 24);
|
||||
|
||||
return 0xffffffff;
|
||||
}
|
||||
|
||||
|
||||
/* Write a long to memory without MMU translation - results of previous MMU translation passed as array. */
|
||||
void
|
||||
writememll_no_mmut_2386(uint32_t addr, uint32_t *a64, uint32_t val)
|
||||
{
|
||||
mem_mapping_t *map;
|
||||
|
||||
GDBSTUB_MEM_ACCESS(addr, GDBSTUB_MEM_WRITE, 4);
|
||||
|
||||
mem_logical_addr = addr;
|
||||
|
||||
if (addr & 3) {
|
||||
if (!cpu_cyrix_alignment || (addr & 7) > 4)
|
||||
cycles -= timing_misaligned;
|
||||
if ((addr & 0xfff) > 0xffc) {
|
||||
if (cr0 >> 31) {
|
||||
if (cpu_state.abrt || high_page)
|
||||
return;
|
||||
}
|
||||
|
||||
writememwl_no_mmut(addr, &(a64[0]), val);
|
||||
writememwl_no_mmut(addr + 2, &(a64[2]), val >> 16);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (cr0 >> 31) {
|
||||
if (cpu_state.abrt || high_page)
|
||||
return;
|
||||
|
||||
addr = (uint32_t) (a64[0] & rammask);
|
||||
} else
|
||||
addr &= rammask;
|
||||
|
||||
map = write_mapping[addr >> MEM_GRANULARITY_BITS];
|
||||
|
||||
if (map && map->write_l) {
|
||||
map->write_l(addr, val, map->priv);
|
||||
return;
|
||||
}
|
||||
if (map && map->write_w) {
|
||||
map->write_w(addr, val, map->priv);
|
||||
map->write_w(addr + 2, val >> 16, map->priv);
|
||||
return;
|
||||
}
|
||||
if (map && map->write_b) {
|
||||
map->write_b(addr, val, map->priv);
|
||||
map->write_b(addr + 1, val >> 8, map->priv);
|
||||
map->write_b(addr + 2, val >> 16, map->priv);
|
||||
map->write_b(addr + 3, val >> 24, map->priv);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint64_t
|
||||
readmemql_2386(uint32_t addr)
|
||||
{
|
||||
mem_mapping_t *map;
|
||||
int i;
|
||||
uint64_t a = 0x0000000000000000ULL;
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
addr64a[i] = (uint64_t) (addr + i);
|
||||
GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_READ, 8);
|
||||
|
||||
mem_logical_addr = addr;
|
||||
|
||||
high_page = 0;
|
||||
|
||||
if (addr & 7) {
|
||||
cycles -= timing_misaligned;
|
||||
if ((addr & 0xfff) > 0xff8) {
|
||||
if (cr0 >> 31) {
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (i == 0) {
|
||||
a = mmutranslate_read_2386(addr + i);
|
||||
addr64a[i] = (uint32_t) a;
|
||||
} else if (!((addr + i) & 0xfff)) {
|
||||
a = mmutranslate_read_2386(addr + 7);
|
||||
addr64a[i] = (uint32_t) a;
|
||||
if (!cpu_state.abrt) {
|
||||
a = (a & ~0xfffLL) | ((uint64_t) ((addr + i) & 0xfff));
|
||||
addr64a[i] = (uint32_t) a;
|
||||
}
|
||||
} else {
|
||||
a = (a & ~0xfffLL) | ((uint64_t) ((addr + i) & 0xfff));
|
||||
addr64a[i] = (uint32_t) a;
|
||||
}
|
||||
|
||||
if (a > 0xffffffffULL)
|
||||
return 0xffff;
|
||||
}
|
||||
}
|
||||
|
||||
/* No need to waste precious CPU host cycles on mmutranslate's that were already done, just pass
|
||||
their result as a parameter to be used if needed. */
|
||||
return readmemll_no_mmut(addr, addr64a) |
|
||||
(((uint64_t) readmemll_no_mmut(addr + 4, &(addr64a[4]))) << 32);
|
||||
}
|
||||
}
|
||||
|
||||
if (cr0 >> 31) {
|
||||
a = mmutranslate_read_2386(addr);
|
||||
addr64a[0] = (uint32_t) a;
|
||||
|
||||
if (a > 0xffffffffULL)
|
||||
return 0xffffffffffffffffULL;
|
||||
}
|
||||
|
||||
addr = addr64a[0] & rammask;
|
||||
|
||||
map = read_mapping[addr >> MEM_GRANULARITY_BITS];
|
||||
if (map && map->read_l)
|
||||
return map->read_l(addr, map->priv) | ((uint64_t)map->read_l(addr + 4, map->priv) << 32);
|
||||
|
||||
return readmemll(addr) | ((uint64_t) readmemll(addr + 4) << 32);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
writememql_2386(uint32_t addr, uint64_t val)
|
||||
{
|
||||
mem_mapping_t *map;
|
||||
int i;
|
||||
uint64_t a = 0x0000000000000000ULL;
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
addr64a[i] = (uint64_t) (addr + i);
|
||||
GDBSTUB_MEM_ACCESS_FAST(addr64a, GDBSTUB_MEM_WRITE, 8);
|
||||
|
||||
mem_logical_addr = addr;
|
||||
|
||||
high_page = 0;
|
||||
|
||||
if (addr & 7) {
|
||||
cycles -= timing_misaligned;
|
||||
if ((addr & 0xfff) > 0xff8) {
|
||||
if (cr0 >> 31) {
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (i == 0) {
|
||||
a = mmutranslate_write_2386(addr + i);
|
||||
addr64a[i] = (uint32_t) a;
|
||||
} else if (!((addr + i) & 0xfff)) {
|
||||
a = mmutranslate_write_2386(addr + 7);
|
||||
addr64a[i] = (uint32_t) a;
|
||||
if (!cpu_state.abrt) {
|
||||
a = (a & ~0xfffLL) | ((uint64_t) ((addr + i) & 0xfff));
|
||||
addr64a[i] = (uint32_t) a;
|
||||
}
|
||||
} else {
|
||||
a = (a & ~0xfffLL) | ((uint64_t) ((addr + i) & 0xfff));
|
||||
addr64a[i] = (uint32_t) a;
|
||||
}
|
||||
|
||||
if (addr64a[i] > 0xffffffffULL)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* No need to waste precious CPU host cycles on mmutranslate's that were already done, just pass
|
||||
their result as a parameter to be used if needed. */
|
||||
writememll_no_mmut(addr, addr64a, val);
|
||||
writememll_no_mmut(addr + 4, &(addr64a[4]), val >> 32);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (cr0 >> 31) {
|
||||
addr64a[0] = mmutranslate_write_2386(addr);
|
||||
if (addr64a[0] > 0xffffffffULL)
|
||||
return;
|
||||
}
|
||||
|
||||
addr = addr64a[0] & rammask;
|
||||
|
||||
map = write_mapping[addr >> MEM_GRANULARITY_BITS];
|
||||
|
||||
if (map && map->write_l) {
|
||||
map->write_l(addr, val, map->priv);
|
||||
map->write_l(addr + 4, val >> 32, map->priv);
|
||||
return;
|
||||
}
|
||||
if (map && map->write_w) {
|
||||
map->write_w(addr, val, map->priv);
|
||||
map->write_w(addr + 2, val >> 16, map->priv);
|
||||
map->write_w(addr + 4, val >> 32, map->priv);
|
||||
map->write_w(addr + 6, val >> 48, map->priv);
|
||||
return;
|
||||
}
|
||||
if (map && map->write_b) {
|
||||
map->write_b(addr, val, map->priv);
|
||||
map->write_b(addr + 1, val >> 8, map->priv);
|
||||
map->write_b(addr + 2, val >> 16, map->priv);
|
||||
map->write_b(addr + 3, val >> 24, map->priv);
|
||||
map->write_b(addr + 4, val >> 32, map->priv);
|
||||
map->write_b(addr + 5, val >> 40, map->priv);
|
||||
map->write_b(addr + 6, val >> 48, map->priv);
|
||||
map->write_b(addr + 7, val >> 56, map->priv);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
do_mmutranslate_2386(uint32_t addr, uint32_t *a64, int num, int write)
|
||||
{
|
||||
int i;
|
||||
uint32_t last_addr = addr + (num - 1);
|
||||
uint64_t a = 0x0000000000000000ULL;
|
||||
|
||||
for (i = 0; i < num; i++)
|
||||
a64[i] = (uint64_t) addr;
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
if (cr0 >> 31) {
|
||||
/* If we have encountered at least one page fault, mark all subsequent addresses as
|
||||
having page faulted, prevents false negatives in readmem*l_no_mmut. */
|
||||
if ((i > 0) && cpu_state.abrt && !high_page)
|
||||
a64[i] = a64[i - 1];
|
||||
/* If we are on the same page, there is no need to translate again, as we can just
|
||||
reuse the previous result. */
|
||||
else if (i == 0) {
|
||||
a = mmutranslatereal_2386(addr, write);
|
||||
a64[i] = (uint32_t) a;
|
||||
} else if (!(addr & 0xfff)) {
|
||||
a = mmutranslatereal_2386(last_addr, write);
|
||||
a64[i] = (uint32_t) a;
|
||||
|
||||
if (!cpu_state.abrt) {
|
||||
a = (a & 0xfffffffffffff000ULL) | ((uint64_t) (addr & 0xfff));
|
||||
a64[i] = (uint32_t) a;
|
||||
}
|
||||
} else {
|
||||
a = (a & 0xfffffffffffff000ULL) | ((uint64_t) (addr & 0xfff));
|
||||
a64[i] = (uint32_t) a;
|
||||
}
|
||||
}
|
||||
|
||||
addr++;
|
||||
}
|
||||
}
|
||||
@@ -568,7 +568,8 @@ MAINOBJ := 86box.o config.o log.o random.o timer.o io.o acpi.o apm.o dma.o ddma.
|
||||
usb.o device.o nvr.o nvr_at.o nvr_ps2.o machine_status.o ini.o \
|
||||
$(VNCOBJ)
|
||||
|
||||
MEMOBJ := catalyst_flash.o i2c_eeprom.o intel_flash.o mem.o rom.o row.o smram.o spd.o sst_flash.o
|
||||
MEMOBJ := catalyst_flash.o i2c_eeprom.o intel_flash.o mem.o mmu_2386.o rom.o row.o \
|
||||
smram.o spd.o sst_flash.o
|
||||
|
||||
CPU808XOBJ := queue.o
|
||||
|
||||
|
||||
Reference in New Issue
Block a user