Merge remote-tracking branch 'uyjulian/core_cleanup/BasiliskII/src/uae_cpu' into update_uae

This commit is contained in:
kanjitalk755 2021-05-04 13:51:40 +09:00
commit 65028aec4a
90 changed files with 40789 additions and 18188 deletions

View File

@ -0,0 +1,80 @@
#
# Note: this Makefile only contains rules for the source
# generator tools.
#
#
# suppress warnings about overriding LDFLAGS and CPPFLAGS
#
AUTOMAKE_OPTIONS = -Wno-gnu
AM_CPPFLAGS = $(DEFINES) \
"-I$(srcdir)/../include" \
"-I$(srcdir)/../Unix" \
"-I$(builddir)/.." \
"-I$(builddir)" \
"-I$(srcdir)"
CC = $(CC_FOR_BUILD)
CXX = $(CXX_FOR_BUILD)
LDFLAGS = $(LDFLAGS_FOR_BUILD)
CPPFLAGS = $(CPPFLAGS_FOR_BUILD)
CFLAGS = $(CFLAGS_FOR_BUILD)
CXXFLAGS = $(CXXFLAGS_FOR_BUILD)
LIBS=-lm
CFLAGS_NOWARN = $(DBGSP)
AM_CFLAGS = $(CFLAGS_NOWARN) $(WFLAGS)
AM_CXXFLAGS = $(CFLAGS_NOWARN) $(WFLAGS)
noinst_PROGRAMS = build68k gencpu
if USE_JIT
noinst_PROGRAMS += gencomp
endif
BUILT_SOURCES = \
cpudefs.cpp \
cpuemu.cpp \
cpustbl.cpp \
cpufunctbl.cpp \
cputbl.h \
$(empty)
build68k_SOURCES = build68k.c
gencpu_SOURCES = gencpu.c m68k.h readcpu.cpp readcpu.h cpudefs.cpp
gencomp_SOURCES =
if GENCOMP_ARCH_X86
gencomp_SOURCES += compiler/gencomp.c
endif
if GENCOMP_ARCH_ARM
gencomp_SOURCES += compiler/gencomp_arm.c
endif
gencomp_SOURCES += readcpu.cpp cpudefs.cpp
if USE_JIT
BUILT_SOURCES += compemu.cpp compstbl.cpp comptbl.h
endif
cpudefs.cpp: build68k$(EXEEXT) $(srcdir)/table68k
$(AM_V_GEN)./build68k <$(srcdir)/table68k > $@
cpuemu.cpp: gencpu$(EXEEXT)
$(AM_V_GEN)./gencpu$(EXEEXT)
cpustbl.cpp cpufunctbl.cpp cputbl.h: cpuemu.cpp
compemu.cpp: gencomp$(EXEEXT)
$(AM_V_GEN)./gencomp$(EXEEXT)
compstbl.cpp comptbl.h: compemu.cpp
CLEANFILES = $(BUILT_SOURCES)
EXTRA_DIST = \
table68k \
compiler/codegen_arm.cpp compiler/codegen_arm.h \
compiler/compemu_midfunc_arm.cpp compiler/compemu_midfunc_arm.h \
compiler/compemu_midfunc_arm2.cpp compiler/compemu_midfunc_arm2.h \
compiler/test_codegen_arm.c \
compiler/codegen_x86.cpp compiler/codegen_x86.h \
compiler/compemu_midfunc_x86.cpp compiler/compemu_midfunc_x86.h \
compiler/test_codegen_x86.cpp \
$(empty)

View File

@ -0,0 +1,326 @@
/*
* aranym_glue.cpp - CPU interface
*
* Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
*
* Inspired by Christian Bauer's Basilisk II
*
* This file is part of the ARAnyM project which builds a new and powerful
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
*
* ARAnyM is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* ARAnyM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ARAnyM; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "sysdeps.h"
#include "cpu_emulation.h"
#include "newcpu.h"
#include "hardware.h"
#include "scc.h"
#include "input.h"
#ifdef USE_JIT
# include "compiler/compemu.h"
#endif
#include "nf_objs.h"
#include "debug.h"
// RAM and ROM pointers
memptr RAMBase = 0; // RAM base (Atari address space) gb-- init is important
uint8 *RAMBaseHost; // RAM base (host address space)
uint32 RAMSize = 0x00e00000; // Size of RAM
memptr ROMBase = 0x00e00000; // ROM base (Atari address space)
uint8 *ROMBaseHost; // ROM base (host address space)
uint32 ROMSize = 0x00100000; // Size of ROM
uint32 RealROMSize; // Real size of ROM
memptr HWBase = 0x00f00000; // HW base (Atari address space)
uint8 *HWBaseHost; // HW base (host address space)
uint32 HWSize = 0x00100000; // Size of HW space
memptr FastRAMBase = 0x01000000; // Fast-RAM base (Atari address space)
uint8 *FastRAMBaseHost; // Fast-RAM base (host address space)
#ifdef HW_SIGSEGV
uint8 *FakeIOBaseHost;
#endif
#ifdef FIXED_VIDEORAM
memptr VideoRAMBase = ARANYMVRAMSTART; // VideoRAM base (Atari address space)
#else
memptr VideoRAMBase; // VideoRAM base (Atari address space)
#endif
uint8 *VideoRAMBaseHost;// VideoRAM base (host address space)
//uint32 VideoRAMSize; // Size of VideoRAM
#ifndef NOT_MALLOC
uintptr MEMBaseDiff; // Global offset between a Atari address and its Host equivalent
uintptr ROMBaseDiff;
uintptr FastRAMBaseDiff;
#endif
uintptr VMEMBaseDiff; // Global offset between a Atari VideoRAM address and /dev/fb0 mmap
#if defined(ENABLE_EXCLUSIVE_SPCFLAGS) && !defined(HAVE_HARDWARE_LOCKS)
SDL_mutex *spcflags_lock;
#endif
#if defined(ENABLE_REALSTOP)
SDL_cond *stop_condition;
#endif
/*
* Initialize 680x0 emulation
*/
bool InitMEM() {
InitMEMBaseDiff(RAMBaseHost, RAMBase);
InitROMBaseDiff(ROMBaseHost, ROMBase);
InitFastRAMBaseDiff(FastRAMBaseHost, FastRAMBase);
InitVMEMBaseDiff(VideoRAMBaseHost, VideoRAMBase);
return true;
}
bool Init680x0(void)
{
init_m68k();
#if defined(ENABLE_EXCLUSIVE_SPCFLAGS) && !defined(HAVE_HARDWARE_LOCKS)
if ((spcflags_lock = SDL_CreateMutex()) == NULL) {
panicbug("Error by SDL_CreateMutex()");
exit(EXIT_FAILURE);
}
#endif
#if ENABLE_REALSTOP
if ((stop_condition = SDL_CreateCond()) == NULL) {
panicbug("Error by SDL_CreateCond()");
exit(EXIT_FAILURE);
}
#endif
#ifdef USE_JIT
if (bx_options.jit.jit) compiler_init();
#endif
return true;
}
/*
* Instr. RESET
*/
void AtariReset(void)
{
// reset Atari hardware here
HWReset();
// reset NatFeats here
NFReset();
// reset the input devices (input.cpp)
InputReset();
}
/*
* Reset CPU
*/
void Reset680x0(void)
{
m68k_reset();
}
/*
* Deinitialize 680x0 emulation
*/
void Exit680x0(void)
{
#ifdef USE_JIT
if (bx_options.jit.jit) compiler_exit();
#endif
exit_m68k();
}
/*
* Reset and start 680x0 emulation
*/
void Start680x0(void)
{
m68k_reset();
#ifdef USE_JIT
if (bx_options.jit.jit) {
m68k_compile_execute();
}
else
#endif
m68k_execute();
}
/*
* Restart running 680x0 emulation safely from different thread
*/
void Restart680x0(void)
{
quit_program = 2;
TriggerNMI();
}
/*
* Quit 680x0 emulation safely from different thread
*/
void Quit680x0(void)
{
quit_program = 1;
TriggerNMI();
}
int MFPdoInterrupt(void)
{
return getMFP()->doInterrupt();
}
int SCCdoInterrupt(void)
{
return getSCC()->doInterrupt();
}
/*
* Trigger interrupts
*/
void TriggerInternalIRQ(void)
{
SPCFLAGS_SET( SPCFLAG_INTERNAL_IRQ );
}
void TriggerInt3(void)
{
SPCFLAGS_SET( SPCFLAG_INT3 );
}
void TriggerVBL(void)
{
SPCFLAGS_SET( SPCFLAG_VBL );
}
void TriggerInt5(void)
{
SPCFLAGS_SET( SPCFLAG_INT5 );
}
void TriggerSCC(bool enable)
{
if (enable)
SPCFLAGS_SET( SPCFLAG_SCC );
else
SPCFLAGS_CLEAR( SPCFLAG_SCC );
}
void TriggerMFP(bool enable)
{
if (enable)
SPCFLAGS_SET( SPCFLAG_MFP );
else
SPCFLAGS_CLEAR( SPCFLAG_MFP );
}
void TriggerNMI(void)
{
SPCFLAGS_SET( SPCFLAG_BRK ); // use _BRK for NMI
}
#ifndef REBOOT_OR_HALT
#define REBOOT_OR_HALT 0 // halt by default
#endif
#if REBOOT_OR_HALT == 1
# define CPU_MSG "CPU: Rebooting"
# define CPU_ACTION Restart680x0()
#else
# define CPU_MSG "CPU: Halting"
# define CPU_ACTION Quit680x0()
#endif
#ifdef ENABLE_EPSLIMITER
#ifndef EPS_LIMIT
# define EPS_LIMIT 10000 /* this might be too high if ARAnyM is slowed down by printing the bus errors on console */
#endif
void check_eps_limit(uaecptr pc)
{
static long last_exception_time=-1;
static long exception_per_sec=0;
static long exception_per_sec_pc=0;
static uaecptr prevpc = 0;
if (bx_options.cpu.eps_enabled) {
if (last_exception_time == -1) {
last_exception_time = SDL_GetTicks();
}
exception_per_sec++;
if (pc == prevpc) {
/* BUS ERRORs occur at the same PC - watch out! */
exception_per_sec_pc++;
}
else {
exception_per_sec_pc = 0;
prevpc = pc;
}
if (SDL_GetTicks() - last_exception_time > 1000) {
last_exception_time = SDL_GetTicks();
if (exception_per_sec_pc > bx_options.cpu.eps_max ||
exception_per_sec > EPS_LIMIT /* make it configurable */) {
panicbug("CPU: Exception per second limit reached: %ld/%ld",
exception_per_sec_pc, exception_per_sec);
/* would be cool to open SDL dialog here: */
/* [Exception per seconds limit reached. XXXXX exception
occured in the last second. The limit is set to YYYYY
in your config file. Do you want to continue emulation,
reset ARAnyM or quit ?][Continue] [Reset] [Quit]
*/
panicbug(CPU_MSG);
CPU_ACTION;
}
exception_per_sec = 0;
exception_per_sec_pc = 0;
}
}
}
#endif
void report_double_bus_error()
{
panicbug("CPU: Double bus fault detected !");
/* would be cool to open SDL dialog here: */
/* [Double bus fault detected. The emulated system crashed badly.
Do you want to reset ARAnyM or quit ?] [Reset] [Quit]"
*/
panicbug(CPU_MSG);
CPU_ACTION;
}
#ifdef FLIGHT_RECORDER
extern bool cpu_flight_recorder_active;
void cpu_flight_recorder(int activate) { cpu_flight_recorder_active = activate; }
#endif

View File

@ -56,8 +56,12 @@ uintptr MEMBaseDiff; // Global offset between a Mac address and its Host equiva
bool UseJIT = false;
#endif
// #if defined(ENABLE_EXCLUSIVE_SPCFLAGS) && !defined(HAVE_HARDWARE_LOCKS)
B2_mutex *spcflags_lock = NULL;
// #endif
// From newcpu.cpp
extern bool quit_program;
extern int quit_program;
/*
@ -66,6 +70,7 @@ extern bool quit_program;
bool Init680x0(void)
{
spcflags_lock = B2_create_mutex();
#if REAL_ADDRESSING
// Mac address space = host address space
RAMBaseMac = (uintptr)RAMBaseHost;
@ -160,6 +165,7 @@ void TriggerInterrupt(void)
void TriggerNMI(void)
{
//!! not implemented yet
// SPCFLAGS_SET( SPCFLAG_BRK ); // use _BRK for NMI
}
@ -200,7 +206,7 @@ void Execute68kTrap(uint16 trap, struct M68kRegisters *r)
// Execute trap
m68k_setpc(m68k_areg(regs, 7));
fill_prefetch_0();
quit_program = false;
quit_program = 0;
m68k_execute();
// Clean up stack
@ -215,7 +221,7 @@ void Execute68kTrap(uint16 trap, struct M68kRegisters *r)
r->d[i] = m68k_dreg(regs, i);
for (i=0; i<7; i++)
r->a[i] = m68k_areg(regs, i);
quit_program = false;
quit_program = 0;
}
@ -247,7 +253,7 @@ void Execute68k(uint32 addr, struct M68kRegisters *r)
// Execute routine
m68k_setpc(addr);
fill_prefetch_0();
quit_program = false;
quit_program = 0;
m68k_execute();
// Clean up stack
@ -262,5 +268,18 @@ void Execute68k(uint32 addr, struct M68kRegisters *r)
r->d[i] = m68k_dreg(regs, i);
for (i=0; i<7; i++)
r->a[i] = m68k_areg(regs, i);
quit_program = false;
quit_program = 0;
}
void report_double_bus_error()
{
#if 0
panicbug("CPU: Double bus fault detected !");
/* would be cool to open SDL dialog here: */
/* [Double bus fault detected. The emulated system crashed badly.
Do you want to reset ARAnyM or quit ?] [Reset] [Quit]"
*/
panicbug(CPU_MSG);
CPU_ACTION;
#endif
}

View File

@ -1,32 +1,44 @@
/*
* build68k.c - m68k CPU builder
*
* Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
*
* Inspired by Christian Bauer's Basilisk II
*
* This file is part of the ARAnyM project which builds a new and powerful
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
*
* ARAnyM is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* ARAnyM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ARAnyM; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
* UAE - The Un*x Amiga Emulator
*
* Read 68000 CPU specs from file "table68k" and build table68k.c
*
* Copyright 1995,1996 Bernd Schmidt
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <assert.h>
#include <ctype.h>
#include <stdio.h>
#include "sysdeps.h"
#include "readcpu.h"
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <assert.h>
#undef abort
static FILE *tablef;
static int nextch = 0;
@ -65,15 +77,15 @@ static int nextchtohex(void)
}
}
int main(int argc, char **argv)
int main()
{
int no_insns = 0;
printf ("#include \"sysdeps.h\"\n");
printf ("#include \"readcpu.h\"\n");
printf ("struct instr_def defs68k[] = {\n");
#ifdef WIN32
tablef = fopen(argc > 1 ? argv[1] : "table68k","r");
#if 0
tablef = fopen("table68k","r");
if (tablef == NULL) {
fprintf(stderr, "table68k not found\n");
exit(1);
@ -122,8 +134,8 @@ int main(int argc, char **argv)
case 'r': currbit = bitr; break;
case 'R': currbit = bitR; break;
case 'z': currbit = bitz; break;
case 'E': currbit = bitE; break;
case 'p': currbit = bitp; break;
case 'E': currbit = bitE; break;
case 'p': currbit = bitp; break;
default: abort();
}
if (!(bitmask & 1)) {
@ -138,6 +150,7 @@ int main(int argc, char **argv)
patbits[i] = nextch;
getnextch();
}
(void) patbits;
while (isspace(nextch) || nextch == ':') /* Get CPU and privilege level */
getnextch();
@ -172,6 +185,8 @@ int main(int argc, char **argv)
getnextch();
switch(nextch){
case '-': flagset[i] = fa_unset; break;
case '/': flagset[i] = fa_isjmp; break;
case '+': flagset[i] = fa_isbranch; break;
case '0': flagset[i] = fa_zero; break;
case '1': flagset[i] = fa_one; break;
case 'x': flagset[i] = fa_dontcare; break;
@ -191,6 +206,8 @@ int main(int argc, char **argv)
getnextch();
switch(nextch){
case '-': flaguse[i] = fu_unused; break;
case '/': flaguse[i] = fu_isjmp; break;
case '+': flaguse[i] = fu_maybecc; break;
case '?': flaguse[i] = fu_unknown; break;
default: flaguse[i] = fu_used; break;
}
@ -235,7 +252,7 @@ int main(int argc, char **argv)
if (nextch != ':')
abort();
fgets(opcstr, 250, tablef);
assert(fgets(opcstr, 250, tablef) != NULL);
getnextch();
{
int j;
@ -243,12 +260,12 @@ int main(int argc, char **argv)
char *opstrp = opcstr, *osendp;
int slen = 0;
while (isspace(*opstrp))
while (isspace((int)*opstrp))
opstrp++;
osendp = opstrp;
while (*osendp) {
if (!isspace (*osendp))
if (!isspace ((int)*osendp))
slen = osendp - opstrp + 1;
osendp++;
}
@ -271,6 +288,5 @@ int main(int argc, char **argv)
}
}
printf("};\nint n_defs68k = %d;\n", no_insns);
fflush(stdout);
return 0;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,42 +1,53 @@
/*
* compiler/compemu.h - Public interface and definitions
* compiler/compemu.h - Public interface and definitions
*
* Original 68040 JIT compiler for UAE, copyright 2000-2002 Bernd Meyer
* Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
*
* Adaptation for Basilisk II and improvements, copyright 2000-2005
* Gwenole Beauchesne
* Inspired by Christian Bauer's Basilisk II
*
* Basilisk II (C) 1997-2008 Christian Bauer
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This file is part of the ARAnyM project which builds a new and powerful
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* JIT compiler m68k -> IA-32 and AMD64
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* Original 68040 JIT compiler for UAE, copyright 2000-2002 Bernd Meyer
* Adaptation for Basilisk II and improvements, copyright 2000-2004 Gwenole Beauchesne
* Portions related to CPU detection come from linux/arch/i386/kernel/setup.c
*
* ARAnyM is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* ARAnyM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ARAnyM; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef COMPEMU_H
#define COMPEMU_H
// #include "sysconfig.h"
#include "newcpu.h"
#if USE_JIT
#if defined __i386__ || defined __x86_64__
#include "flags_x86.h"
#ifdef UAE
#ifdef CPU_64_BIT
typedef uae_u64 uintptr;
#else
#error "Unsupported JIT compiler for this architecture"
typedef uae_u32 uintptr;
#endif
/* FIXME: cpummu.cpp also checks for USE_JIT, possibly others */
#define USE_JIT
#endif
#if JIT_DEBUG
#ifdef USE_JIT
#ifdef JIT_DEBUG
/* dump some information (m68k block, x86 block addresses) about the compiler state */
extern void compiler_dumpstate(void);
#endif
@ -55,11 +66,14 @@ extern uae_u32 start_pc;
struct blockinfo_t;
struct cpu_history {
uae_u16 * location;
uae_u16* location;
#ifdef UAE
uae_u8 specmem;
#endif
};
union cacheline {
cpuop_func * handler;
cpuop_func* handler;
blockinfo_t * bi;
};
@ -102,8 +116,13 @@ union cacheline {
#define SCALE 2
#define BYTES_PER_INST 10240 /* paranoid ;-) */
#if defined(CPU_arm)
#define LONGEST_68K_INST 256 /* The number of bytes the longest possible
68k instruction takes */
#else
#define LONGEST_68K_INST 16 /* The number of bytes the longest possible
68k instruction takes */
#endif
#define MAX_CHECKSUM_LEN 2048 /* The maximum size we calculate checksums
for. Anything larger will be flushed
unconditionally even with SOFT_FLUSH */
@ -111,8 +130,7 @@ union cacheline {
for jump targets */
#define INDIVIDUAL_INST 0
#if 1
// gb-- my format from readcpu.cpp is not the same
#ifdef WINUAE_ARANYM
#define FLAG_X 0x0010
#define FLAG_N 0x0008
#define FLAG_Z 0x0004
@ -126,43 +144,108 @@ union cacheline {
#define FLAG_X 0x0001
#endif
#define FLAG_CZNV (FLAG_C | FLAG_Z | FLAG_N | FLAG_V)
#define FLAG_ALL (FLAG_C | FLAG_Z | FLAG_N | FLAG_V | FLAG_X)
#define FLAG_ZNV (FLAG_Z | FLAG_N | FLAG_V)
#define KILLTHERAT 1 /* Set to 1 to avoid some partial_rat_stalls */
#if defined(__x86_64__)
#if defined(CPU_arm)
#define USE_DATA_BUFFER
#define N_REGS 13 /* really 16, but 13 to 15 are SP, LR, PC */
#else
#if defined(CPU_x86_64)
#define N_REGS 16 /* really only 15, but they are numbered 0-3,5-15 */
#else
#define N_REGS 8 /* really only 7, but they are numbered 0,1,2,3,5,6,7 */
#endif
#endif
#define N_FREGS 6 /* That leaves us two positions on the stack to play with */
/* Functions exposed to newcpu, or to what was moved from newcpu.c to
* compemu_support.c */
#ifdef WINUAE_ARANYM
extern void compiler_init(void);
extern void compiler_exit(void);
extern bool compiler_use_jit(void);
extern void init_comp(void);
#endif
extern void flush(int save_regs);
extern void small_flush(int save_regs);
void flush_reg(int reg);
extern void set_target(uae_u8* t);
extern uae_u8* get_target(void);
extern void freescratch(void);
#ifdef UAE
extern void build_comp(void);
#endif
extern void set_cache_state(int enabled);
extern int get_cache_state(void);
extern uae_u32 get_jitted_size(void);
extern void (*flush_icache)(int n);
#ifdef JIT
extern void (*flush_icache)(void);
#endif
extern void alloc_cache(void);
extern int check_for_cache_miss(void);
/* JIT FPU compilation */
struct jit_disable_opcodes {
bool fbcc;
bool fdbcc;
bool fscc;
bool ftrapcc;
bool fsave;
bool frestore;
bool fmove;
bool fmovem;
bool fmovec; /* for move control register */
bool fmovecr; /* for move from constant rom */
bool fint;
bool fsinh;
bool fintrz;
bool fsqrt;
bool flognp1;
bool fetoxm1;
bool ftanh;
bool fatan;
bool fasin;
bool fatanh;
bool fsin;
bool ftan;
bool fetox;
bool ftwotox;
bool ftentox;
bool flogn;
bool flog10;
bool flog2;
bool fabs;
bool fcosh;
bool fneg;
bool facos;
bool fcos;
bool fgetexp;
bool fgetman;
bool fdiv;
bool fmod;
bool fadd;
bool fmul;
bool fsgldiv;
bool frem;
bool fscale;
bool fsglmul;
bool fsub;
bool fsincos;
bool fcmp;
bool ftst;
};
extern struct jit_disable_opcodes jit_disable;
extern void comp_fpp_opp (uae_u32 opcode, uae_u16 extra);
extern void comp_fbcc_opp (uae_u32 opcode);
extern void comp_fscc_opp (uae_u32 opcode, uae_u16 extra);
void comp_fdbcc_opp (uae_u32 opcode, uae_u16 extra);
void comp_ftrapcc_opp (uae_u32 opcode, uaecptr oldpc);
void comp_fsave_opp (uae_u32 opcode);
void comp_frestore_opp (uae_u32 opcode);
extern uae_u32 needed_flags;
extern cacheline cache_tags[];
extern uae_u8* comp_pc_p;
extern void* pushall_call_handler;
@ -193,10 +276,11 @@ typedef struct {
double val;
uae_u8 status;
uae_s8 realreg; /* gb-- realreg can hold -1 */
uae_u8 realind;
uae_u8 realind;
uae_u8 needflush;
} freg_status;
#define SP_REG 15
#define PC_P 16
#define FLAGX 17
#define FLAGTMP 18
@ -263,19 +347,23 @@ typedef struct {
} bigstate;
typedef struct {
/* Integer part */
char virt[VREGS];
char nat[N_REGS];
/* Integer part */
uae_s8 virt[VREGS];
uae_s8 nat[N_REGS];
} smallstate;
extern bigstate live;
extern int touchcnt;
#define IMM uae_s32
#define IMM uae_s32
#define RR1 uae_u32
#define RR2 uae_u32
#define RR4 uae_u32
/*
R1, R2, R4 collides with ARM registers defined in ucontext
#define R1 uae_u32
#define R2 uae_u32
#define R4 uae_u32
*/
#define W1 uae_u32
#define W2 uae_u32
#define W4 uae_u32
@ -284,220 +372,37 @@ extern int touchcnt;
#define RW4 uae_u32
#define MEMR uae_u32
#define MEMW uae_u32
#define MEMRW uae_u32
#define MEMRW uae_u32
#define MEMPTR uintptr
#define MEMPTRR MEMPTR
#define MEMPTRW MEMPTR
#define MEMPTRRW MEMPTR
#define FW uae_u32
#define FR uae_u32
#define FRW uae_u32
#define MIDFUNC(nargs,func,args) void func args
#define MENDFUNC(nargs,func,args)
#define COMPCALL(func) func
#define LOWFUNC(flags,mem,nargs,func,args) static __inline__ void func args
#define LENDFUNC(flags,mem,nargs,func,args)
#define LOWFUNC(flags,mem,nargs,func,args) static inline void func args
/* What we expose to the outside */
#define DECLARE_MIDFUNC(func) extern void func
DECLARE_MIDFUNC(bt_l_ri(R4 r, IMM i));
DECLARE_MIDFUNC(bt_l_rr(R4 r, R4 b));
DECLARE_MIDFUNC(btc_l_ri(RW4 r, IMM i));
DECLARE_MIDFUNC(btc_l_rr(RW4 r, R4 b));
DECLARE_MIDFUNC(bts_l_ri(RW4 r, IMM i));
DECLARE_MIDFUNC(bts_l_rr(RW4 r, R4 b));
DECLARE_MIDFUNC(btr_l_ri(RW4 r, IMM i));
DECLARE_MIDFUNC(btr_l_rr(RW4 r, R4 b));
DECLARE_MIDFUNC(mov_l_rm(W4 d, IMM s));
DECLARE_MIDFUNC(call_r(R4 r));
DECLARE_MIDFUNC(sub_l_mi(IMM d, IMM s));
DECLARE_MIDFUNC(mov_l_mi(IMM d, IMM s));
DECLARE_MIDFUNC(mov_w_mi(IMM d, IMM s));
DECLARE_MIDFUNC(mov_b_mi(IMM d, IMM s));
DECLARE_MIDFUNC(rol_b_ri(RW1 r, IMM i));
DECLARE_MIDFUNC(rol_w_ri(RW2 r, IMM i));
DECLARE_MIDFUNC(rol_l_ri(RW4 r, IMM i));
DECLARE_MIDFUNC(rol_l_rr(RW4 d, R1 r));
DECLARE_MIDFUNC(rol_w_rr(RW2 d, R1 r));
DECLARE_MIDFUNC(rol_b_rr(RW1 d, R1 r));
DECLARE_MIDFUNC(shll_l_rr(RW4 d, R1 r));
DECLARE_MIDFUNC(shll_w_rr(RW2 d, R1 r));
DECLARE_MIDFUNC(shll_b_rr(RW1 d, R1 r));
DECLARE_MIDFUNC(ror_b_ri(R1 r, IMM i));
DECLARE_MIDFUNC(ror_w_ri(R2 r, IMM i));
DECLARE_MIDFUNC(ror_l_ri(R4 r, IMM i));
DECLARE_MIDFUNC(ror_l_rr(R4 d, R1 r));
DECLARE_MIDFUNC(ror_w_rr(R2 d, R1 r));
DECLARE_MIDFUNC(ror_b_rr(R1 d, R1 r));
DECLARE_MIDFUNC(shrl_l_rr(RW4 d, R1 r));
DECLARE_MIDFUNC(shrl_w_rr(RW2 d, R1 r));
DECLARE_MIDFUNC(shrl_b_rr(RW1 d, R1 r));
DECLARE_MIDFUNC(shra_l_rr(RW4 d, R1 r));
DECLARE_MIDFUNC(shra_w_rr(RW2 d, R1 r));
DECLARE_MIDFUNC(shra_b_rr(RW1 d, R1 r));
DECLARE_MIDFUNC(shll_l_ri(RW4 r, IMM i));
DECLARE_MIDFUNC(shll_w_ri(RW2 r, IMM i));
DECLARE_MIDFUNC(shll_b_ri(RW1 r, IMM i));
DECLARE_MIDFUNC(shrl_l_ri(RW4 r, IMM i));
DECLARE_MIDFUNC(shrl_w_ri(RW2 r, IMM i));
DECLARE_MIDFUNC(shrl_b_ri(RW1 r, IMM i));
DECLARE_MIDFUNC(shra_l_ri(RW4 r, IMM i));
DECLARE_MIDFUNC(shra_w_ri(RW2 r, IMM i));
DECLARE_MIDFUNC(shra_b_ri(RW1 r, IMM i));
DECLARE_MIDFUNC(setcc(W1 d, IMM cc));
DECLARE_MIDFUNC(setcc_m(IMM d, IMM cc));
DECLARE_MIDFUNC(cmov_b_rr(RW1 d, R1 s, IMM cc));
DECLARE_MIDFUNC(cmov_w_rr(RW2 d, R2 s, IMM cc));
DECLARE_MIDFUNC(cmov_l_rr(RW4 d, R4 s, IMM cc));
DECLARE_MIDFUNC(cmov_l_rm(RW4 d, IMM s, IMM cc));
DECLARE_MIDFUNC(bsf_l_rr(W4 d, R4 s));
DECLARE_MIDFUNC(pop_m(IMM d));
DECLARE_MIDFUNC(push_m(IMM d));
DECLARE_MIDFUNC(pop_l(W4 d));
DECLARE_MIDFUNC(push_l_i(IMM i));
DECLARE_MIDFUNC(push_l(R4 s));
DECLARE_MIDFUNC(clear_16(RW4 r));
DECLARE_MIDFUNC(clear_8(RW4 r));
DECLARE_MIDFUNC(sign_extend_16_rr(W4 d, R2 s));
DECLARE_MIDFUNC(sign_extend_8_rr(W4 d, R1 s));
DECLARE_MIDFUNC(zero_extend_16_rr(W4 d, R2 s));
DECLARE_MIDFUNC(zero_extend_8_rr(W4 d, R1 s));
DECLARE_MIDFUNC(imul_64_32(RW4 d, RW4 s));
DECLARE_MIDFUNC(mul_64_32(RW4 d, RW4 s));
DECLARE_MIDFUNC(imul_32_32(RW4 d, R4 s));
DECLARE_MIDFUNC(mul_32_32(RW4 d, R4 s));
DECLARE_MIDFUNC(mov_b_rr(W1 d, R1 s));
DECLARE_MIDFUNC(mov_w_rr(W2 d, R2 s));
DECLARE_MIDFUNC(mov_l_rrm_indexed(W4 d,R4 baser, R4 index, IMM factor));
DECLARE_MIDFUNC(mov_w_rrm_indexed(W2 d, R4 baser, R4 index, IMM factor));
DECLARE_MIDFUNC(mov_b_rrm_indexed(W1 d, R4 baser, R4 index, IMM factor));
DECLARE_MIDFUNC(mov_l_mrr_indexed(R4 baser, R4 index, IMM factor, R4 s));
DECLARE_MIDFUNC(mov_w_mrr_indexed(R4 baser, R4 index, IMM factor, R2 s));
DECLARE_MIDFUNC(mov_b_mrr_indexed(R4 baser, R4 index, IMM factor, R1 s));
DECLARE_MIDFUNC(mov_l_bmrr_indexed(IMM base, R4 baser, R4 index, IMM factor, R4 s));
DECLARE_MIDFUNC(mov_w_bmrr_indexed(IMM base, R4 baser, R4 index, IMM factor, R2 s));
DECLARE_MIDFUNC(mov_b_bmrr_indexed(IMM base, R4 baser, R4 index, IMM factor, R1 s));
DECLARE_MIDFUNC(mov_l_brrm_indexed(W4 d, IMM base, R4 baser, R4 index, IMM factor));
DECLARE_MIDFUNC(mov_w_brrm_indexed(W2 d, IMM base, R4 baser, R4 index, IMM factor));
DECLARE_MIDFUNC(mov_b_brrm_indexed(W1 d, IMM base, R4 baser, R4 index, IMM factor));
DECLARE_MIDFUNC(mov_l_rm_indexed(W4 d, IMM base, R4 index, IMM factor));
DECLARE_MIDFUNC(mov_l_rR(W4 d, R4 s, IMM offset));
DECLARE_MIDFUNC(mov_w_rR(W2 d, R4 s, IMM offset));
DECLARE_MIDFUNC(mov_b_rR(W1 d, R4 s, IMM offset));
DECLARE_MIDFUNC(mov_l_brR(W4 d, R4 s, IMM offset));
DECLARE_MIDFUNC(mov_w_brR(W2 d, R4 s, IMM offset));
DECLARE_MIDFUNC(mov_b_brR(W1 d, R4 s, IMM offset));
DECLARE_MIDFUNC(mov_l_Ri(R4 d, IMM i, IMM offset));
DECLARE_MIDFUNC(mov_w_Ri(R4 d, IMM i, IMM offset));
DECLARE_MIDFUNC(mov_b_Ri(R4 d, IMM i, IMM offset));
DECLARE_MIDFUNC(mov_l_Rr(R4 d, R4 s, IMM offset));
DECLARE_MIDFUNC(mov_w_Rr(R4 d, R2 s, IMM offset));
DECLARE_MIDFUNC(mov_b_Rr(R4 d, R1 s, IMM offset));
DECLARE_MIDFUNC(lea_l_brr(W4 d, R4 s, IMM offset));
DECLARE_MIDFUNC(lea_l_brr_indexed(W4 d, R4 s, R4 index, IMM factor, IMM offset));
DECLARE_MIDFUNC(lea_l_rr_indexed(W4 d, R4 s, R4 index, IMM factor));
DECLARE_MIDFUNC(mov_l_bRr(R4 d, R4 s, IMM offset));
DECLARE_MIDFUNC(mov_w_bRr(R4 d, R2 s, IMM offset));
DECLARE_MIDFUNC(mov_b_bRr(R4 d, R1 s, IMM offset));
DECLARE_MIDFUNC(bswap_32(RW4 r));
DECLARE_MIDFUNC(bswap_16(RW2 r));
DECLARE_MIDFUNC(mov_l_rr(W4 d, R4 s));
DECLARE_MIDFUNC(mov_l_mr(IMM d, R4 s));
DECLARE_MIDFUNC(mov_w_mr(IMM d, R2 s));
DECLARE_MIDFUNC(mov_w_rm(W2 d, IMM s));
DECLARE_MIDFUNC(mov_b_mr(IMM d, R1 s));
DECLARE_MIDFUNC(mov_b_rm(W1 d, IMM s));
DECLARE_MIDFUNC(mov_l_ri(W4 d, IMM s));
DECLARE_MIDFUNC(mov_w_ri(W2 d, IMM s));
DECLARE_MIDFUNC(mov_b_ri(W1 d, IMM s));
DECLARE_MIDFUNC(add_l_mi(IMM d, IMM s) );
DECLARE_MIDFUNC(add_w_mi(IMM d, IMM s) );
DECLARE_MIDFUNC(add_b_mi(IMM d, IMM s) );
DECLARE_MIDFUNC(test_l_ri(R4 d, IMM i));
DECLARE_MIDFUNC(test_l_rr(R4 d, R4 s));
DECLARE_MIDFUNC(test_w_rr(R2 d, R2 s));
DECLARE_MIDFUNC(test_b_rr(R1 d, R1 s));
DECLARE_MIDFUNC(and_l_ri(RW4 d, IMM i));
DECLARE_MIDFUNC(and_l(RW4 d, R4 s));
DECLARE_MIDFUNC(and_w(RW2 d, R2 s));
DECLARE_MIDFUNC(and_b(RW1 d, R1 s));
DECLARE_MIDFUNC(or_l_rm(RW4 d, IMM s));
DECLARE_MIDFUNC(or_l_ri(RW4 d, IMM i));
DECLARE_MIDFUNC(or_l(RW4 d, R4 s));
DECLARE_MIDFUNC(or_w(RW2 d, R2 s));
DECLARE_MIDFUNC(or_b(RW1 d, R1 s));
DECLARE_MIDFUNC(adc_l(RW4 d, R4 s));
DECLARE_MIDFUNC(adc_w(RW2 d, R2 s));
DECLARE_MIDFUNC(adc_b(RW1 d, R1 s));
DECLARE_MIDFUNC(add_l(RW4 d, R4 s));
DECLARE_MIDFUNC(add_w(RW2 d, R2 s));
DECLARE_MIDFUNC(add_b(RW1 d, R1 s));
DECLARE_MIDFUNC(sub_l_ri(RW4 d, IMM i));
DECLARE_MIDFUNC(sub_w_ri(RW2 d, IMM i));
DECLARE_MIDFUNC(sub_b_ri(RW1 d, IMM i));
DECLARE_MIDFUNC(add_l_ri(RW4 d, IMM i));
DECLARE_MIDFUNC(add_w_ri(RW2 d, IMM i));
DECLARE_MIDFUNC(add_b_ri(RW1 d, IMM i));
DECLARE_MIDFUNC(sbb_l(RW4 d, R4 s));
DECLARE_MIDFUNC(sbb_w(RW2 d, R2 s));
DECLARE_MIDFUNC(sbb_b(RW1 d, R1 s));
DECLARE_MIDFUNC(sub_l(RW4 d, R4 s));
DECLARE_MIDFUNC(sub_w(RW2 d, R2 s));
DECLARE_MIDFUNC(sub_b(RW1 d, R1 s));
DECLARE_MIDFUNC(cmp_l(R4 d, R4 s));
DECLARE_MIDFUNC(cmp_l_ri(R4 r, IMM i));
DECLARE_MIDFUNC(cmp_w(R2 d, R2 s));
DECLARE_MIDFUNC(cmp_b(R1 d, R1 s));
DECLARE_MIDFUNC(xor_l(RW4 d, R4 s));
DECLARE_MIDFUNC(xor_w(RW2 d, R2 s));
DECLARE_MIDFUNC(xor_b(RW1 d, R1 s));
DECLARE_MIDFUNC(live_flags(void));
DECLARE_MIDFUNC(dont_care_flags(void));
DECLARE_MIDFUNC(duplicate_carry(void));
DECLARE_MIDFUNC(restore_carry(void));
DECLARE_MIDFUNC(start_needflags(void));
DECLARE_MIDFUNC(end_needflags(void));
DECLARE_MIDFUNC(make_flags_live(void));
DECLARE_MIDFUNC(call_r_11(R4 r, W4 out1, R4 in1, IMM osize, IMM isize));
DECLARE_MIDFUNC(call_r_02(R4 r, R4 in1, R4 in2, IMM isize1, IMM isize2));
DECLARE_MIDFUNC(forget_about(W4 r));
DECLARE_MIDFUNC(nop(void));
DECLARE_MIDFUNC(f_forget_about(FW r));
DECLARE_MIDFUNC(fmov_pi(FW r));
DECLARE_MIDFUNC(fmov_log10_2(FW r));
DECLARE_MIDFUNC(fmov_log2_e(FW r));
DECLARE_MIDFUNC(fmov_loge_2(FW r));
DECLARE_MIDFUNC(fmov_1(FW r));
DECLARE_MIDFUNC(fmov_0(FW r));
DECLARE_MIDFUNC(fmov_rm(FW r, MEMR m));
DECLARE_MIDFUNC(fmovi_rm(FW r, MEMR m));
DECLARE_MIDFUNC(fmovi_mr(MEMW m, FR r));
DECLARE_MIDFUNC(fmovs_rm(FW r, MEMR m));
DECLARE_MIDFUNC(fmovs_mr(MEMW m, FR r));
DECLARE_MIDFUNC(fmov_mr(MEMW m, FR r));
DECLARE_MIDFUNC(fmov_ext_mr(MEMW m, FR r));
DECLARE_MIDFUNC(fmov_ext_rm(FW r, MEMR m));
DECLARE_MIDFUNC(fmov_rr(FW d, FR s));
DECLARE_MIDFUNC(fldcw_m_indexed(R4 index, IMM base));
DECLARE_MIDFUNC(ftst_r(FR r));
DECLARE_MIDFUNC(dont_care_fflags(void));
DECLARE_MIDFUNC(fsqrt_rr(FW d, FR s));
DECLARE_MIDFUNC(fabs_rr(FW d, FR s));
DECLARE_MIDFUNC(frndint_rr(FW d, FR s));
DECLARE_MIDFUNC(fsin_rr(FW d, FR s));
DECLARE_MIDFUNC(fcos_rr(FW d, FR s));
DECLARE_MIDFUNC(ftwotox_rr(FW d, FR s));
DECLARE_MIDFUNC(fetox_rr(FW d, FR s));
DECLARE_MIDFUNC(flog2_rr(FW d, FR s));
DECLARE_MIDFUNC(fneg_rr(FW d, FR s));
DECLARE_MIDFUNC(fadd_rr(FRW d, FR s));
DECLARE_MIDFUNC(fsub_rr(FRW d, FR s));
DECLARE_MIDFUNC(fmul_rr(FRW d, FR s));
DECLARE_MIDFUNC(frem_rr(FRW d, FR s));
DECLARE_MIDFUNC(frem1_rr(FRW d, FR s));
DECLARE_MIDFUNC(fdiv_rr(FRW d, FR s));
DECLARE_MIDFUNC(fcmp_rr(FR d, FR s));
DECLARE_MIDFUNC(fflags_into_flags(W2 tmp));
#if defined(CPU_arm)
#include "compemu_midfunc_arm.h"
#if defined(USE_JIT2)
#include "compemu_midfunc_arm2.h"
#endif
#endif
#if defined(CPU_i386) || defined(CPU_x86_64)
#include "compemu_midfunc_x86.h"
#endif
#undef DECLARE_MIDFUNC
extern int failure;
@ -519,10 +424,16 @@ extern void calc_disp_ea_020(int base, uae_u32 dp, int target, int tmp);
/* Set native Z flag only if register is zero */
extern void set_zero(int r, int tmp);
extern int kill_rodent(int r);
#define SYNC_PC_OFFSET 100
extern void sync_m68k_pc(void);
extern uae_u32 get_const(int r);
extern int is_const(int r);
extern void register_branch(uae_u32 not_taken, uae_u32 taken, uae_u8 cond);
void compemu_make_sr(int sr, int tmp);
void compemu_enter_super(int sr);
void compemu_exc_make_frame(int format, int sr, int currpc, int nr, int tmp);
void compemu_bkpt(void);
extern bool disasm_this_inst;
#define comp_get_ibyte(o) do_get_mem_byte((uae_u8 *)(comp_pc_p + (o) + 1))
#define comp_get_iword(o) do_get_mem_word((uae_u16 *)(comp_pc_p + (o)))
@ -550,40 +461,43 @@ typedef struct blockinfo_t {
cpuop_func* handler_to_use;
/* The direct handler does not check for the correct address */
cpuop_func* handler;
cpuop_func* handler;
cpuop_func* direct_handler;
cpuop_func* direct_pen;
cpuop_func* direct_pcc;
#ifdef UAE
uae_u8* nexthandler;
#endif
uae_u8* pc_p;
uae_u32 c1;
uae_u32 c1;
uae_u32 c2;
#if USE_CHECKSUM_INFO
checksum_info *csi;
#else
uae_u32 len;
uae_u32 min_pcp;
uae_u32 min_pcp;
#endif
struct blockinfo_t* next_same_cl;
struct blockinfo_t** prev_same_cl_p;
struct blockinfo_t** prev_same_cl_p;
struct blockinfo_t* next;
struct blockinfo_t** prev_p;
struct blockinfo_t** prev_p;
uae_u8 optlevel;
uae_u8 needed_flags;
uae_u8 status;
uae_u8 optlevel;
uae_u8 needed_flags;
uae_u8 status;
uae_u8 havestate;
dependency dep[2]; /* Holds things we depend on */
dependency* deplist; /* List of things that depend on this */
smallstate env;
#if JIT_DEBUG
/* (gb) size of the compiled block (direct handler) */
uae_u32 direct_handler_size;
#ifdef JIT_DEBUG
/* (gb) size of the compiled block (direct handler) */
uae_u32 direct_handler_size;
#endif
} blockinfo;
@ -601,9 +515,92 @@ void do_nothing(void);
#else
static __inline__ void flush_icache(int) { }
static __inline__ void build_comp() { }
static inline void flush_icache(void) { }
#endif /* !USE_JIT */
#ifdef UAE
typedef struct {
uae_u8 type;
uae_u8 reg;
uae_u32 next;
} regacc;
#define JIT_EXCEPTION_HANDLER
// #define JIT_ALWAYS_DISTRUST
/* ARAnyM uses fpu_register name, used in scratch_t */
/* FIXME: check that no ARAnyM code assumes different floating point type */
typedef fptype fpu_register;
extern void compile_block(cpu_history* pc_hist, int blocklen, int totcyles);
#define MAXCYCLES (1000 * CYCLE_UNIT)
#define scaled_cycles(x) (currprefs.m68k_speed<0?(((x)/SCALE)?(((x)/SCALE<MAXCYCLES?((x)/SCALE):MAXCYCLES)):1):(x))
/* Flags for Bernie during development/debugging. Should go away eventually */
#define DISTRUST_CONSISTENT_MEM 0
typedef struct {
uae_u8 use_flags;
uae_u8 set_flags;
uae_u8 is_jump;
uae_u8 is_addx;
uae_u8 is_const_jump;
} op_properties;
extern op_properties prop[65536];
STATIC_INLINE int end_block(uae_u16 opcode)
{
return prop[opcode].is_jump ||
(prop[opcode].is_const_jump && !currprefs.comp_constjump);
}
#ifdef _WIN32
LONG WINAPI EvalException(LPEXCEPTION_POINTERS info);
#if defined(_MSC_VER) && !defined(NO_WIN32_EXCEPTION_HANDLER)
#ifdef _WIN64
/* Structured exception handling is table based for Windows x86-64, so
* Windows will not be able to find the exception handler. */
#else
#define USE_STRUCTURED_EXCEPTION_HANDLING
#endif
#endif
#endif
void jit_abort(const char *format,...);
#if SIZEOF_TCHAR != 1
void jit_abort(const TCHAR *format, ...);
#endif
#else
#ifdef WINUAE_ARANYM
#define jit_log(format, ...) D(bug(format, ##__VA_ARGS__))
#define jit_log2(format, ...) D2(bug(format, ##__VA_ARGS__))
void jit_abort(const char *format,...) __attribute__((format(printf, 1, 2))) __attribute__((__noreturn__));
#else
#define jit_abort(...) abort()
#define jit_log panicbug
#define jit_log2(...)
#endif
#endif /* UAE */
#ifdef CPU_64_BIT
static inline uae_u32 check_uae_p32(uintptr address, const char *file, int line)
{
if (address > (uintptr_t) 0xffffffff) {
jit_abort("JIT: 64-bit pointer (0x%llx) at %s:%d (fatal)",
(unsigned long long)address, file, line);
}
return (uae_u32) address;
}
#define uae_p32(x) (check_uae_p32((uintptr)(x), __FILE__, __LINE__))
#else
#define uae_p32(x) ((uae_u32)(x))
#endif
#endif /* COMPEMU_H */

View File

@ -0,0 +1,2 @@
#define PART_1
#include "compemu.cpp"

View File

@ -0,0 +1,2 @@
#define PART_2
#include "compemu.cpp"

View File

@ -0,0 +1,2 @@
#define PART_3
#include "compemu.cpp"

View File

@ -0,0 +1,2 @@
#define PART_4
#include "compemu.cpp"

View File

@ -0,0 +1,2 @@
#define PART_5
#include "compemu.cpp"

View File

@ -0,0 +1,2 @@
#define PART_6
#include "compemu.cpp"

View File

@ -0,0 +1,2 @@
#define PART_7
#include "compemu.cpp"

View File

@ -0,0 +1,2 @@
#define PART_8
#include "compemu.cpp"

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,186 @@
/*
* compiler/compemu_midfunc_arm.h - Native MIDFUNCS for ARM
*
* Copyright (c) 2014 Jens Heitmann of ARAnyM dev team (see AUTHORS)
*
* Inspired by Christian Bauer's Basilisk II
*
* Original 68040 JIT compiler for UAE, copyright 2000-2002 Bernd Meyer
*
* Adaptation for Basilisk II and improvements, copyright 2000-2002
* Gwenole Beauchesne
*
* Basilisk II (C) 1997-2002 Christian Bauer
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Note:
* File is included by compemu.h
*
*/
// Arm optimized midfunc
DECLARE_MIDFUNC(arm_ADD_l(RW4 d, RR4 s));
DECLARE_MIDFUNC(arm_ADD_l_ri(RW4 d, IMM i));
DECLARE_MIDFUNC(arm_ADD_l_ri8(RW4 d, IMM i));
DECLARE_MIDFUNC(arm_SUB_l_ri8(RW4 d, IMM i));
DECLARE_MIDFUNC(arm_AND_b(RW1 d, RR1 s));
DECLARE_MIDFUNC(arm_AND_w(RW2 d, RR2 s));
DECLARE_MIDFUNC(arm_AND_l(RW4 d, RR4 s));
DECLARE_MIDFUNC(arm_AND_l_ri8(RW4 d, IMM i));
DECLARE_MIDFUNC(arm_EOR_b(RW1 d, RR1 s));
DECLARE_MIDFUNC(arm_EOR_l(RW4 d, RR4 s));
DECLARE_MIDFUNC(arm_EOR_w(RW2 d, RR2 s));
DECLARE_MIDFUNC(arm_ORR_b(RW1 d, RR1 s));
DECLARE_MIDFUNC(arm_ORR_l(RW4 d, RR4 s));
DECLARE_MIDFUNC(arm_ORR_w(RW2 d, RR2 s));
DECLARE_MIDFUNC(arm_ROR_l_ri8(RW4 r, IMM i));
// Emulated midfunc
DECLARE_MIDFUNC(bt_l_ri(RR4 r, IMM i));
DECLARE_MIDFUNC(bt_l_rr(RR4 r, RR4 b));
DECLARE_MIDFUNC(btc_l_rr(RW4 r, RR4 b));
DECLARE_MIDFUNC(bts_l_rr(RW4 r, RR4 b));
DECLARE_MIDFUNC(btr_l_rr(RW4 r, RR4 b));
DECLARE_MIDFUNC(mov_l_rm(W4 d, IMM s));
DECLARE_MIDFUNC(mov_l_rm_indexed(W4 d, IMM base, RR4 index, IMM factor));
DECLARE_MIDFUNC(mov_l_mi(IMM d, IMM s));
DECLARE_MIDFUNC(mov_w_mi(IMM d, IMM s));
DECLARE_MIDFUNC(mov_b_mi(IMM d, IMM s));
DECLARE_MIDFUNC(rol_b_ri(RW1 r, IMM i));
DECLARE_MIDFUNC(rol_w_ri(RW2 r, IMM i));
DECLARE_MIDFUNC(rol_l_rr(RW4 d, RR1 r));
DECLARE_MIDFUNC(rol_w_rr(RW2 d, RR1 r));
DECLARE_MIDFUNC(rol_b_rr(RW1 d, RR1 r));
DECLARE_MIDFUNC(rol_l_ri(RW4 r, IMM i));
DECLARE_MIDFUNC(shll_l_rr(RW4 d, RR1 r));
DECLARE_MIDFUNC(shll_w_rr(RW2 d, RR1 r));
DECLARE_MIDFUNC(shll_b_rr(RW1 d, RR1 r));
DECLARE_MIDFUNC(ror_b_ri(RR1 r, IMM i));
DECLARE_MIDFUNC(ror_w_ri(RR2 r, IMM i));
DECLARE_MIDFUNC(ror_l_ri(RR4 r, IMM i));
DECLARE_MIDFUNC(ror_l_rr(RR4 d, RR1 r));
DECLARE_MIDFUNC(ror_w_rr(RR2 d, RR1 r));
DECLARE_MIDFUNC(ror_b_rr(RR1 d, RR1 r));
DECLARE_MIDFUNC(shrl_l_rr(RW4 d, RR1 r));
DECLARE_MIDFUNC(shrl_w_rr(RW2 d, RR1 r));
DECLARE_MIDFUNC(shrl_b_rr(RW1 d, RR1 r));
DECLARE_MIDFUNC(shra_l_rr(RW4 d, RR1 r));
DECLARE_MIDFUNC(shra_w_rr(RW2 d, RR1 r));
DECLARE_MIDFUNC(shra_b_rr(RW1 d, RR1 r));
DECLARE_MIDFUNC(shll_l_ri(RW4 r, IMM i));
DECLARE_MIDFUNC(shll_w_ri(RW2 r, IMM i));
DECLARE_MIDFUNC(shll_b_ri(RW1 r, IMM i));
DECLARE_MIDFUNC(shrl_l_ri(RW4 r, IMM i));
DECLARE_MIDFUNC(shrl_w_ri(RW2 r, IMM i));
DECLARE_MIDFUNC(shrl_b_ri(RW1 r, IMM i));
DECLARE_MIDFUNC(shra_l_ri(RW4 r, IMM i));
DECLARE_MIDFUNC(shra_w_ri(RW2 r, IMM i));
DECLARE_MIDFUNC(shra_b_ri(RW1 r, IMM i));
DECLARE_MIDFUNC(setcc(W1 d, IMM cc));
DECLARE_MIDFUNC(setcc_m(IMM d, IMM cc));
DECLARE_MIDFUNC(cmov_l_rr(RW4 d, RR4 s, IMM cc));
DECLARE_MIDFUNC(bsf_l_rr(W4 d, RR4 s));
DECLARE_MIDFUNC(pop_l(W4 d));
DECLARE_MIDFUNC(push_l(RR4 s));
DECLARE_MIDFUNC(sign_extend_16_rr(W4 d, RR2 s));
DECLARE_MIDFUNC(sign_extend_8_rr(W4 d, RR1 s));
DECLARE_MIDFUNC(zero_extend_16_rr(W4 d, RR2 s));
DECLARE_MIDFUNC(zero_extend_8_rr(W4 d, RR1 s));
DECLARE_MIDFUNC(simulate_bsf(W4 tmp, RW4 s));
DECLARE_MIDFUNC(imul_64_32(RW4 d, RW4 s));
DECLARE_MIDFUNC(mul_64_32(RW4 d, RW4 s));
DECLARE_MIDFUNC(imul_32_32(RW4 d, RR4 s));
DECLARE_MIDFUNC(mov_b_rr(W1 d, RR1 s));
DECLARE_MIDFUNC(mov_w_rr(W2 d, RR2 s));
DECLARE_MIDFUNC(mov_l_rR(W4 d, RR4 s, IMM offset));
DECLARE_MIDFUNC(mov_w_rR(W2 d, RR4 s, IMM offset));
DECLARE_MIDFUNC(mov_l_brR(W4 d, RR4 s, IMM offset));
DECLARE_MIDFUNC(mov_w_brR(W2 d, RR4 s, IMM offset));
DECLARE_MIDFUNC(mov_b_brR(W1 d, RR4 s, IMM offset));
DECLARE_MIDFUNC(mov_l_Ri(RR4 d, IMM i, IMM offset));
DECLARE_MIDFUNC(mov_w_Ri(RR4 d, IMM i, IMM offset));
DECLARE_MIDFUNC(mov_l_Rr(RR4 d, RR4 s, IMM offset));
DECLARE_MIDFUNC(mov_w_Rr(RR4 d, RR2 s, IMM offset));
DECLARE_MIDFUNC(lea_l_brr(W4 d, RR4 s, IMM offset));
DECLARE_MIDFUNC(lea_l_brr_indexed(W4 d, RR4 s, RR4 index, IMM factor, IMM offset));
DECLARE_MIDFUNC(lea_l_rr_indexed(W4 d, RR4 s, RR4 index, IMM factor));
DECLARE_MIDFUNC(mov_l_bRr(RR4 d, RR4 s, IMM offset));
DECLARE_MIDFUNC(mov_w_bRr(RR4 d, RR2 s, IMM offset));
DECLARE_MIDFUNC(mov_b_bRr(RR4 d, RR1 s, IMM offset));
DECLARE_MIDFUNC(mid_bswap_32(RW4 r));
DECLARE_MIDFUNC(mid_bswap_16(RW2 r));
DECLARE_MIDFUNC(mov_l_rr(W4 d, RR4 s));
DECLARE_MIDFUNC(mov_l_mr(IMM d, RR4 s));
DECLARE_MIDFUNC(mov_w_mr(IMM d, RR2 s));
DECLARE_MIDFUNC(mov_w_rm(W2 d, IMM s));
DECLARE_MIDFUNC(mov_b_mr(IMM d, RR1 s));
DECLARE_MIDFUNC(mov_b_rm(W1 d, IMM s));
DECLARE_MIDFUNC(mov_l_ri(W4 d, IMM s));
DECLARE_MIDFUNC(mov_w_ri(W2 d, IMM s));
DECLARE_MIDFUNC(mov_b_ri(W1 d, IMM s));
DECLARE_MIDFUNC(test_l_ri(RR4 d, IMM i));
DECLARE_MIDFUNC(test_l_rr(RR4 d, RR4 s));
DECLARE_MIDFUNC(test_w_rr(RR2 d, RR2 s));
DECLARE_MIDFUNC(test_b_rr(RR1 d, RR1 s));
DECLARE_MIDFUNC(and_l_ri(RW4 d, IMM i));
DECLARE_MIDFUNC(and_l(RW4 d, RR4 s));
DECLARE_MIDFUNC(and_w(RW2 d, RR2 s));
DECLARE_MIDFUNC(and_b(RW1 d, RR1 s));
DECLARE_MIDFUNC(or_l_ri(RW4 d, IMM i));
DECLARE_MIDFUNC(or_l(RW4 d, RR4 s));
DECLARE_MIDFUNC(or_w(RW2 d, RR2 s));
DECLARE_MIDFUNC(or_b(RW1 d, RR1 s));
DECLARE_MIDFUNC(adc_l(RW4 d, RR4 s));
DECLARE_MIDFUNC(adc_w(RW2 d, RR2 s));
DECLARE_MIDFUNC(adc_b(RW1 d, RR1 s));
DECLARE_MIDFUNC(add_l(RW4 d, RR4 s));
DECLARE_MIDFUNC(add_w(RW2 d, RR2 s));
DECLARE_MIDFUNC(add_b(RW1 d, RR1 s));
DECLARE_MIDFUNC(sub_l_ri(RW4 d, IMM i));
DECLARE_MIDFUNC(sub_w_ri(RW2 d, IMM i));
DECLARE_MIDFUNC(sub_b_ri(RW1 d, IMM i));
DECLARE_MIDFUNC(add_l_ri(RW4 d, IMM i));
DECLARE_MIDFUNC(add_w_ri(RW2 d, IMM i));
DECLARE_MIDFUNC(add_b_ri(RW1 d, IMM i));
DECLARE_MIDFUNC(sbb_l(RW4 d, RR4 s));
DECLARE_MIDFUNC(sbb_w(RW2 d, RR2 s));
DECLARE_MIDFUNC(sbb_b(RW1 d, RR1 s));
DECLARE_MIDFUNC(sub_l(RW4 d, RR4 s));
DECLARE_MIDFUNC(sub_w(RW2 d, RR2 s));
DECLARE_MIDFUNC(sub_b(RW1 d, RR1 s));
DECLARE_MIDFUNC(cmp_l(RR4 d, RR4 s));
DECLARE_MIDFUNC(cmp_w(RR2 d, RR2 s));
DECLARE_MIDFUNC(cmp_b(RR1 d, RR1 s));
DECLARE_MIDFUNC(xor_l(RW4 d, RR4 s));
DECLARE_MIDFUNC(xor_w(RW2 d, RR2 s));
DECLARE_MIDFUNC(xor_b(RW1 d, RR1 s));
DECLARE_MIDFUNC(call_r_02(RR4 r, RR4 in1, RR4 in2, IMM isize1, IMM isize2));
DECLARE_MIDFUNC(call_r_11(W4 out1, RR4 r, RR4 in1, IMM osize, IMM isize));
DECLARE_MIDFUNC(live_flags(void));
DECLARE_MIDFUNC(dont_care_flags(void));
DECLARE_MIDFUNC(duplicate_carry(void));
DECLARE_MIDFUNC(restore_carry(void));
DECLARE_MIDFUNC(start_needflags(void));
DECLARE_MIDFUNC(end_needflags(void));
DECLARE_MIDFUNC(make_flags_live(void));
DECLARE_MIDFUNC(forget_about(W4 r));
DECLARE_MIDFUNC(nop(void));
DECLARE_MIDFUNC(f_forget_about(FW r));

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,348 @@
/*
* compiler/compemu_midfunc_arm2.h - Native MIDFUNCS for ARM (JIT v2)
*
* Copyright (c) 2014 Jens Heitmann of ARAnyM dev team (see AUTHORS)
*
* Inspired by Christian Bauer's Basilisk II
*
* Original 68040 JIT compiler for UAE, copyright 2000-2002 Bernd Meyer
*
* Adaptation for Basilisk II and improvements, copyright 2000-2002
* Gwenole Beauchesne
*
* Basilisk II (C) 1997-2002 Christian Bauer
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Note:
* File is included by compemu.h
*
*/
// Arm optimized midfunc
extern const uae_u32 ARM_CCR_MAP[];
DECLARE_MIDFUNC(restore_inverted_carry(void));
// ADD
DECLARE_MIDFUNC(jnf_ADD(W4 d, RR4 s, RR4 v));
DECLARE_MIDFUNC(jnf_ADD_imm(W4 d, RR4 s, IMM v));
DECLARE_MIDFUNC(jff_ADD_b(W4 d, RR1 s, RR1 v));
DECLARE_MIDFUNC(jff_ADD_w(W4 d, RR2 s, RR2 v));
DECLARE_MIDFUNC(jff_ADD_l(W4 d, RR4 s, RR4 v));
DECLARE_MIDFUNC(jff_ADD_b_imm(W4 d, RR1 s, IMM v));
DECLARE_MIDFUNC(jff_ADD_w_imm(W4 d, RR2 s, IMM v));
DECLARE_MIDFUNC(jff_ADD_l_imm(W4 d, RR4 s, IMM v));
// ADDA
DECLARE_MIDFUNC(jnf_ADDA_b(W4 d, RR1 s));
DECLARE_MIDFUNC(jnf_ADDA_w(W4 d, RR2 s));
DECLARE_MIDFUNC(jnf_ADDA_l(W4 d, RR4 s));
// ADDX
DECLARE_MIDFUNC(jnf_ADDX(W4 d, RR4 s, RR4 v));
DECLARE_MIDFUNC(jff_ADDX_b(W4 d, RR1 s, RR4 v));
DECLARE_MIDFUNC(jff_ADDX_w(W4 d, RR2 s, RR4 v));
DECLARE_MIDFUNC(jff_ADDX_l(W4 d, RR4 s, RR4 v));
// AND
DECLARE_MIDFUNC(jnf_AND(W4 d, RR4 s, RR4 v));
DECLARE_MIDFUNC(jff_AND_b(W4 d, RR1 s, RR1 v));
DECLARE_MIDFUNC(jff_AND_w(W4 d, RR2 s, RR2 v));
DECLARE_MIDFUNC(jff_AND_l(W4 d, RR4 s, RR4 v));
// ANDSR
DECLARE_MIDFUNC(jff_ANDSR(IMM s, IMM x));
// ASL
DECLARE_MIDFUNC(jff_ASL_b_imm(W4 d, RR4 s, IMM i));
DECLARE_MIDFUNC(jff_ASL_w_imm(W4 d, RR4 s, IMM i));
DECLARE_MIDFUNC(jff_ASL_l_imm(W4 d, RR4 s, IMM i));
DECLARE_MIDFUNC(jff_ASL_b_reg(W4 d, RR4 s, RR4 i));
DECLARE_MIDFUNC(jff_ASL_w_reg(W4 d, RR4 s, RR4 i));
DECLARE_MIDFUNC(jff_ASL_l_reg(W4 d, RR4 s, RR4 i));
// ASLW
DECLARE_MIDFUNC(jff_ASLW(W4 d, RR4 s));
DECLARE_MIDFUNC(jnf_ASLW(W4 d, RR4 s));
// ASR
DECLARE_MIDFUNC(jnf_ASR_b_imm(W4 d, RR4 s, IMM i));
DECLARE_MIDFUNC(jnf_ASR_w_imm(W4 d, RR4 s, IMM i));
DECLARE_MIDFUNC(jnf_ASR_l_imm(W4 d, RR4 s, IMM i));
DECLARE_MIDFUNC(jff_ASR_b_imm(W4 d, RR4 s, IMM i));
DECLARE_MIDFUNC(jff_ASR_w_imm(W4 d, RR4 s, IMM i));
DECLARE_MIDFUNC(jff_ASR_l_imm(W4 d, RR4 s, IMM i));
DECLARE_MIDFUNC(jnf_ASR_b_reg(W4 d, RR4 s, RR4 i));
DECLARE_MIDFUNC(jnf_ASR_w_reg(W4 d, RR4 s, RR4 i));
DECLARE_MIDFUNC(jnf_ASR_l_reg(W4 d, RR4 s, RR4 i));
DECLARE_MIDFUNC(jff_ASR_b_reg(W4 d, RR4 s, RR4 i));
DECLARE_MIDFUNC(jff_ASR_w_reg(W4 d, RR4 s, RR4 i));
DECLARE_MIDFUNC(jff_ASR_l_reg(W4 d, RR4 s, RR4 i));
// ASRW
DECLARE_MIDFUNC(jff_ASRW(W4 d, RR4 s));
DECLARE_MIDFUNC(jnf_ASRW(W4 d, RR4 s));
// BCHG
DECLARE_MIDFUNC(jnf_BCHG_b_imm(RW4 d, IMM s));
DECLARE_MIDFUNC(jnf_BCHG_l_imm(RW4 d, IMM s));
DECLARE_MIDFUNC(jff_BCHG_b_imm(RW4 d, IMM s));
DECLARE_MIDFUNC(jff_BCHG_l_imm(RW4 d, IMM s));
DECLARE_MIDFUNC(jnf_BCHG_b(RW4 d, RR4 s));
DECLARE_MIDFUNC(jnf_BCHG_l(RW4 d, RR4 s));
DECLARE_MIDFUNC(jff_BCHG_b(RW4 d, RR4 s));
DECLARE_MIDFUNC(jff_BCHG_l(RW4 d, RR4 s));
// BCLR
DECLARE_MIDFUNC(jnf_BCLR_b_imm(RW4 d, IMM s));
DECLARE_MIDFUNC(jnf_BCLR_l_imm(RW4 d, IMM s));
DECLARE_MIDFUNC(jnf_BCLR_b(RW4 d, RR4 s));
DECLARE_MIDFUNC(jnf_BCLR_l(RW4 d, RR4 s));
DECLARE_MIDFUNC(jff_BCLR_b_imm(RW4 d, IMM s));
DECLARE_MIDFUNC(jff_BCLR_l_imm(RW4 d, IMM s));
DECLARE_MIDFUNC(jff_BCLR_b(RW4 d, RR4 s));
DECLARE_MIDFUNC(jff_BCLR_l(RW4 d, RR4 s));
// BSET
DECLARE_MIDFUNC(jnf_BSET_b_imm(RW4 d, IMM s));
DECLARE_MIDFUNC(jnf_BSET_l_imm(RW4 d, IMM s));
DECLARE_MIDFUNC(jnf_BSET_b(RW4 d, RR4 s));
DECLARE_MIDFUNC(jnf_BSET_l(RW4 d, RR4 s));
DECLARE_MIDFUNC(jff_BSET_b_imm(RW4 d, IMM s));
DECLARE_MIDFUNC(jff_BSET_l_imm(RW4 d, IMM s));
DECLARE_MIDFUNC(jff_BSET_b(RW4 d, RR4 s));
DECLARE_MIDFUNC(jff_BSET_l(RW4 d, RR4 s));
// BTST
DECLARE_MIDFUNC(jff_BTST_b_imm(RR4 d, IMM s));
DECLARE_MIDFUNC(jff_BTST_l_imm(RR4 d, IMM s));
DECLARE_MIDFUNC(jff_BTST_b(RR4 d, RR4 s));
DECLARE_MIDFUNC(jff_BTST_l(RR4 d, RR4 s));
// CLR
DECLARE_MIDFUNC (jnf_CLR(W4 d));
DECLARE_MIDFUNC (jff_CLR(W4 d));
// CMP
DECLARE_MIDFUNC(jff_CMP_b(RR1 d, RR1 s));
DECLARE_MIDFUNC(jff_CMP_w(RR2 d, RR2 s));
DECLARE_MIDFUNC(jff_CMP_l(RR4 d, RR4 s));
// CMPA
DECLARE_MIDFUNC(jff_CMPA_b(RR1 d, RR1 s));
DECLARE_MIDFUNC(jff_CMPA_w(RR2 d, RR2 s));
DECLARE_MIDFUNC(jff_CMPA_l(RR4 d, RR4 s));
// EOR
DECLARE_MIDFUNC(jnf_EOR(W4 d, RR4 s, RR4 v));
DECLARE_MIDFUNC(jff_EOR_b(W4 d, RR1 s, RR1 v));
DECLARE_MIDFUNC(jff_EOR_w(W4 d, RR2 s, RR2 v));
DECLARE_MIDFUNC(jff_EOR_l(W4 d, RR4 s, RR4 v));
// EORSR
DECLARE_MIDFUNC(jff_EORSR(IMM s, IMM x));
// EXT
DECLARE_MIDFUNC(jnf_EXT_b(W4 d, RR4 s));
DECLARE_MIDFUNC(jnf_EXT_w(W4 d, RR4 s));
DECLARE_MIDFUNC(jnf_EXT_l(W4 d, RR4 s));
DECLARE_MIDFUNC(jff_EXT_b(W4 d, RR4 s));
DECLARE_MIDFUNC(jff_EXT_w(W4 d, RR4 s));
DECLARE_MIDFUNC(jff_EXT_l(W4 d, RR4 s));
// LSL
DECLARE_MIDFUNC(jnf_LSL_imm(W4 d, RR4 s, IMM i));
DECLARE_MIDFUNC(jnf_LSL_reg(W4 d, RR4 s, RR4 i));
DECLARE_MIDFUNC(jff_LSL_b_imm(W4 d, RR4 s, IMM i));
DECLARE_MIDFUNC(jff_LSL_w_imm(W4 d, RR4 s, IMM i));
DECLARE_MIDFUNC(jff_LSL_l_imm(W4 d, RR4 s, IMM i));
DECLARE_MIDFUNC(jff_LSL_b_reg(W4 d, RR4 s, RR4 i));
DECLARE_MIDFUNC(jff_LSL_w_reg(W4 d, RR4 s, RR4 i));
DECLARE_MIDFUNC(jff_LSL_l_reg(W4 d, RR4 s, RR4 i));
// LSLW
DECLARE_MIDFUNC(jff_LSLW(W4 d, RR4 s));
DECLARE_MIDFUNC(jnf_LSLW(W4 d, RR4 s));
// LSR
DECLARE_MIDFUNC(jnf_LSR_b_imm(W4 d, RR4 s, IMM i));
DECLARE_MIDFUNC(jnf_LSR_w_imm(W4 d, RR4 s, IMM i));
DECLARE_MIDFUNC(jnf_LSR_l_imm(W4 d, RR4 s, IMM i));
DECLARE_MIDFUNC(jff_LSR_b_imm(W4 d, RR4 s, IMM i));
DECLARE_MIDFUNC(jff_LSR_w_imm(W4 d, RR4 s, IMM i));
DECLARE_MIDFUNC(jff_LSR_l_imm(W4 d, RR4 s, IMM i));
DECLARE_MIDFUNC(jnf_LSR_b_reg(W4 d, RR4 s, RR4 i));
DECLARE_MIDFUNC(jnf_LSR_w_reg(W4 d, RR4 s, RR4 i));
DECLARE_MIDFUNC(jnf_LSR_l_reg(W4 d, RR4 s, RR4 i));
DECLARE_MIDFUNC(jff_LSR_b_reg(W4 d, RR4 s, RR4 i));
DECLARE_MIDFUNC(jff_LSR_w_reg(W4 d, RR4 s, RR4 i));
DECLARE_MIDFUNC(jff_LSR_l_reg(W4 d, RR4 s, RR4 i));
// LSRW
DECLARE_MIDFUNC(jff_LSRW(W4 d, RR4 s));
DECLARE_MIDFUNC(jnf_LSRW(W4 d, RR4 s));
// MOVE
DECLARE_MIDFUNC(jnf_MOVE(W4 d, RR4 s));
DECLARE_MIDFUNC(jff_MOVE_b_imm(W4 d, IMM i));
DECLARE_MIDFUNC(jff_MOVE_w_imm(W4 d, IMM i));
DECLARE_MIDFUNC(jff_MOVE_l_imm(W4 d, IMM i));
DECLARE_MIDFUNC(jff_MOVE_b(W4 d, RR1 s));
DECLARE_MIDFUNC(jff_MOVE_w(W4 d, RR2 s));
DECLARE_MIDFUNC(jff_MOVE_l(W4 d, RR4 s));
// MOVE16
DECLARE_MIDFUNC(jnf_MOVE16(RR4 d, RR4 s));
// MOVEA
DECLARE_MIDFUNC(jnf_MOVEA_w(W4 d, RR2 s));
DECLARE_MIDFUNC(jnf_MOVEA_l(W4 d, RR4 s));
// MULS
DECLARE_MIDFUNC (jnf_MULS(RW4 d, RR4 s));
DECLARE_MIDFUNC (jff_MULS(RW4 d, RR4 s));
DECLARE_MIDFUNC (jnf_MULS32(RW4 d, RR4 s));
DECLARE_MIDFUNC (jff_MULS32(RW4 d, RR4 s));
DECLARE_MIDFUNC (jnf_MULS64(RW4 d, RW4 s));
DECLARE_MIDFUNC (jff_MULS64(RW4 d, RW4 s));
// MULU
DECLARE_MIDFUNC (jnf_MULU(RW4 d, RR4 s));
DECLARE_MIDFUNC (jff_MULU(RW4 d, RR4 s));
DECLARE_MIDFUNC (jnf_MULU32(RW4 d, RR4 s));
DECLARE_MIDFUNC (jff_MULU32(RW4 d, RR4 s));
DECLARE_MIDFUNC (jnf_MULU64(RW4 d, RW4 s));
DECLARE_MIDFUNC (jff_MULU64(RW4 d, RW4 s));
// NEG
DECLARE_MIDFUNC(jnf_NEG(W4 d, RR4 s));
DECLARE_MIDFUNC(jff_NEG_b(W4 d, RR1 s));
DECLARE_MIDFUNC(jff_NEG_w(W4 d, RR2 s));
DECLARE_MIDFUNC(jff_NEG_l(W4 d, RR4 s));
// NEGX
DECLARE_MIDFUNC(jnf_NEGX(W4 d, RR4 s));
DECLARE_MIDFUNC(jff_NEGX_b(W4 d, RR1 s));
DECLARE_MIDFUNC(jff_NEGX_w(W4 d, RR2 s));
DECLARE_MIDFUNC(jff_NEGX_l(W4 d, RR4 s));
// NOT
DECLARE_MIDFUNC(jnf_NOT(W4 d, RR4 s));
DECLARE_MIDFUNC(jff_NOT_b(W4 d, RR1 s));
DECLARE_MIDFUNC(jff_NOT_w(W4 d, RR2 s));
DECLARE_MIDFUNC(jff_NOT_l(W4 d, RR4 s));
// OR
DECLARE_MIDFUNC(jnf_OR(W4 d, RR4 s, RR4 v));
DECLARE_MIDFUNC(jff_OR_b(W4 d, RR1 s, RR1 v));
DECLARE_MIDFUNC(jff_OR_w(W4 d, RR2 s, RR2 v));
DECLARE_MIDFUNC(jff_OR_l(W4 d, RR4 s, RR4 v));
// ORSR
DECLARE_MIDFUNC(jff_ORSR(IMM s, IMM x));
// ROL
DECLARE_MIDFUNC(jnf_ROL_b(W4 d, RR4 s, RR4 i));
DECLARE_MIDFUNC(jnf_ROL_w(W4 d, RR4 s, RR4 i));
DECLARE_MIDFUNC(jnf_ROL_l(W4 d, RR4 s, RR4 i));
DECLARE_MIDFUNC(jff_ROL_b(W4 d, RR4 s, RR4 i));
DECLARE_MIDFUNC(jff_ROL_w(W4 d, RR4 s, RR4 i));
DECLARE_MIDFUNC(jff_ROL_l(W4 d, RR4 s, RR4 i));
// ROLW
DECLARE_MIDFUNC(jff_ROLW(W4 d, RR4 s));
DECLARE_MIDFUNC(jnf_ROLW(W4 d, RR4 s));
// RORW
DECLARE_MIDFUNC(jff_RORW(W4 d, RR4 s));
DECLARE_MIDFUNC(jnf_RORW(W4 d, RR4 s));
// ROXL
DECLARE_MIDFUNC(jnf_ROXL_b(W4 d, RR4 s, RR4 i));
DECLARE_MIDFUNC(jnf_ROXL_w(W4 d, RR4 s, RR4 i));
DECLARE_MIDFUNC(jnf_ROXL_l(W4 d, RR4 s, RR4 i));
DECLARE_MIDFUNC(jff_ROXL_b(W4 d, RR4 s, RR4 i));
DECLARE_MIDFUNC(jff_ROXL_w(W4 d, RR4 s, RR4 i));
DECLARE_MIDFUNC(jff_ROXL_l(W4 d, RR4 s, RR4 i));
// ROXLW
DECLARE_MIDFUNC(jff_ROXLW(W4 d, RR4 s));
DECLARE_MIDFUNC(jnf_ROXLW(W4 d, RR4 s));
// ROR
DECLARE_MIDFUNC(jnf_ROR_b(W4 d, RR4 s, RR4 i));
DECLARE_MIDFUNC(jnf_ROR_w(W4 d, RR4 s, RR4 i));
DECLARE_MIDFUNC(jnf_ROR_l(W4 d, RR4 s, RR4 i));
DECLARE_MIDFUNC(jff_ROR_b(W4 d, RR4 s, RR4 i));
DECLARE_MIDFUNC(jff_ROR_w(W4 d, RR4 s, RR4 i));
DECLARE_MIDFUNC(jff_ROR_l(W4 d, RR4 s, RR4 i));
// ROXR
DECLARE_MIDFUNC(jnf_ROXR_b(W4 d, RR4 s, RR4 i));
DECLARE_MIDFUNC(jnf_ROXR_w(W4 d, RR4 s, RR4 i));
DECLARE_MIDFUNC(jnf_ROXR_l(W4 d, RR4 s, RR4 i));
DECLARE_MIDFUNC(jff_ROXR_b(W4 d, RR4 s, RR4 i));
DECLARE_MIDFUNC(jff_ROXR_w(W4 d, RR4 s, RR4 i));
DECLARE_MIDFUNC(jff_ROXR_l(W4 d, RR4 s, RR4 i));
// ROXRW
DECLARE_MIDFUNC(jff_ROXRW(W4 d, RR4 s));
DECLARE_MIDFUNC(jnf_ROXRW(W4 d, RR4 s));
// SUB
DECLARE_MIDFUNC(jnf_SUB_b_imm(W4 d, RR4 s, IMM v));
DECLARE_MIDFUNC(jnf_SUB_b(W4 d, RR4 s, RR4 v));
DECLARE_MIDFUNC(jnf_SUB_w_imm(W4 d, RR4 s, IMM v));
DECLARE_MIDFUNC(jnf_SUB_w(W4 d, RR4 s, RR4 v));
DECLARE_MIDFUNC(jnf_SUB_l_imm(W4 d, RR4 s, IMM v));
DECLARE_MIDFUNC(jnf_SUB_l(W4 d, RR4 s, RR4 v));
DECLARE_MIDFUNC(jff_SUB_b(W4 d, RR1 s, RR1 v));
DECLARE_MIDFUNC(jff_SUB_w(W4 d, RR2 s, RR2 v));
DECLARE_MIDFUNC(jff_SUB_l(W4 d, RR4 s, RR4 v));
DECLARE_MIDFUNC(jff_SUB_b_imm(W4 d, RR1 s, IMM v));
DECLARE_MIDFUNC(jff_SUB_w_imm(W4 d, RR2 s, IMM v));
DECLARE_MIDFUNC(jff_SUB_l_imm(W4 d, RR4 s, IMM v));
// SUBA
DECLARE_MIDFUNC(jnf_SUBA_b(W4 d, RR1 s));
DECLARE_MIDFUNC(jnf_SUBA_w(W4 d, RR2 s));
DECLARE_MIDFUNC(jnf_SUBA_l(W4 d, RR4 s));
// SUBX
DECLARE_MIDFUNC(jnf_SUBX(W4 d, RR4 s, RR4 v));
DECLARE_MIDFUNC(jff_SUBX_b(W4 d, RR1 s, RR4 v));
DECLARE_MIDFUNC(jff_SUBX_w(W4 d, RR2 s, RR4 v));
DECLARE_MIDFUNC(jff_SUBX_l(W4 d, RR4 s, RR4 v));
// SWAP
DECLARE_MIDFUNC (jnf_SWAP(RW4 d));
DECLARE_MIDFUNC (jff_SWAP(RW4 d));
// TST
DECLARE_MIDFUNC (jff_TST_b(RR1 s));
DECLARE_MIDFUNC (jff_TST_w(RR2 s));
DECLARE_MIDFUNC (jff_TST_l(RR4 s));

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,254 @@
/*
* compiler/compemu_midfunc_x86.h - Native MIDFUNCS for IA-32 and AMD64
*
* Copyright (c) 2014 Jens Heitmann of ARAnyM dev team (see AUTHORS)
*
* Inspired by Christian Bauer's Basilisk II
*
* Original 68040 JIT compiler for UAE, copyright 2000-2002 Bernd Meyer
*
* Adaptation for Basilisk II and improvements, copyright 2000-2002
* Gwenole Beauchesne
*
* Basilisk II (C) 1997-2002 Christian Bauer
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Note:
* File is included by compemu.h
*
*/
DECLARE_MIDFUNC(bt_l_ri(RR4 r, IMM i));
DECLARE_MIDFUNC(bt_l_rr(RR4 r, RR4 b));
DECLARE_MIDFUNC(btc_l_ri(RW4 r, IMM i));
DECLARE_MIDFUNC(btc_l_rr(RW4 r, RR4 b));
DECLARE_MIDFUNC(bts_l_ri(RW4 r, IMM i));
DECLARE_MIDFUNC(bts_l_rr(RW4 r, RR4 b));
DECLARE_MIDFUNC(btr_l_ri(RW4 r, IMM i));
DECLARE_MIDFUNC(btr_l_rr(RW4 r, RR4 b));
DECLARE_MIDFUNC(mov_l_rm(W4 d, IMM s));
DECLARE_MIDFUNC(call_r(RR4 r));
DECLARE_MIDFUNC(sub_l_mi(IMM d, IMM s));
DECLARE_MIDFUNC(mov_l_mi(IMM d, IMM s));
DECLARE_MIDFUNC(mov_w_mi(IMM d, IMM s));
DECLARE_MIDFUNC(mov_b_mi(IMM d, IMM s));
DECLARE_MIDFUNC(rol_b_ri(RW1 r, IMM i));
DECLARE_MIDFUNC(rol_w_ri(RW2 r, IMM i));
DECLARE_MIDFUNC(rol_l_ri(RW4 r, IMM i));
DECLARE_MIDFUNC(rol_l_rr(RW4 d, RR1 r));
DECLARE_MIDFUNC(rol_w_rr(RW2 d, RR1 r));
DECLARE_MIDFUNC(rol_b_rr(RW1 d, RR1 r));
DECLARE_MIDFUNC(shll_l_rr(RW4 d, RR1 r));
DECLARE_MIDFUNC(shll_w_rr(RW2 d, RR1 r));
DECLARE_MIDFUNC(shll_b_rr(RW1 d, RR1 r));
DECLARE_MIDFUNC(ror_b_ri(RR1 r, IMM i));
DECLARE_MIDFUNC(ror_w_ri(RR2 r, IMM i));
DECLARE_MIDFUNC(ror_l_ri(RR4 r, IMM i));
DECLARE_MIDFUNC(ror_l_rr(RR4 d, RR1 r));
DECLARE_MIDFUNC(ror_w_rr(RR2 d, RR1 r));
DECLARE_MIDFUNC(ror_b_rr(RR1 d, RR1 r));
DECLARE_MIDFUNC(shrl_l_rr(RW4 d, RR1 r));
DECLARE_MIDFUNC(shrl_w_rr(RW2 d, RR1 r));
DECLARE_MIDFUNC(shrl_b_rr(RW1 d, RR1 r));
DECLARE_MIDFUNC(shra_l_rr(RW4 d, RR1 r));
DECLARE_MIDFUNC(shra_w_rr(RW2 d, RR1 r));
DECLARE_MIDFUNC(shra_b_rr(RW1 d, RR1 r));
DECLARE_MIDFUNC(shll_l_ri(RW4 r, IMM i));
DECLARE_MIDFUNC(shll_w_ri(RW2 r, IMM i));
DECLARE_MIDFUNC(shll_b_ri(RW1 r, IMM i));
DECLARE_MIDFUNC(shrl_l_ri(RW4 r, IMM i));
DECLARE_MIDFUNC(shrl_w_ri(RW2 r, IMM i));
DECLARE_MIDFUNC(shrl_b_ri(RW1 r, IMM i));
DECLARE_MIDFUNC(shra_l_ri(RW4 r, IMM i));
DECLARE_MIDFUNC(shra_w_ri(RW2 r, IMM i));
DECLARE_MIDFUNC(shra_b_ri(RW1 r, IMM i));
DECLARE_MIDFUNC(setcc(W1 d, IMM cc));
DECLARE_MIDFUNC(setcc_m(IMM d, IMM cc));
DECLARE_MIDFUNC(cmov_l_rr(RW4 d, RR4 s, IMM cc));
DECLARE_MIDFUNC(cmov_l_rm(RW4 d, IMM s, IMM cc));
DECLARE_MIDFUNC(bsf_l_rr(W4 d, RR4 s));
DECLARE_MIDFUNC(pop_m(IMM d));
DECLARE_MIDFUNC(push_m(IMM d));
DECLARE_MIDFUNC(pop_l(W4 d));
DECLARE_MIDFUNC(push_l_i(IMM i));
DECLARE_MIDFUNC(push_l(RR4 s));
DECLARE_MIDFUNC(clear_16(RW4 r));
DECLARE_MIDFUNC(clear_8(RW4 r));
DECLARE_MIDFUNC(sign_extend_32_rr(W4 d, RR2 s));
DECLARE_MIDFUNC(sign_extend_16_rr(W4 d, RR2 s));
DECLARE_MIDFUNC(sign_extend_8_rr(W4 d, RR1 s));
DECLARE_MIDFUNC(zero_extend_16_rr(W4 d, RR2 s));
DECLARE_MIDFUNC(zero_extend_8_rr(W4 d, RR1 s));
DECLARE_MIDFUNC(imul_64_32(RW4 d, RW4 s));
DECLARE_MIDFUNC(mul_64_32(RW4 d, RW4 s));
DECLARE_MIDFUNC(simulate_bsf(W4 tmp, RW4 s));
DECLARE_MIDFUNC(imul_32_32(RW4 d, RR4 s));
DECLARE_MIDFUNC(mul_32_32(RW4 d, RR4 s));
DECLARE_MIDFUNC(mov_b_rr(W1 d, RR1 s));
DECLARE_MIDFUNC(mov_w_rr(W2 d, RR2 s));
DECLARE_MIDFUNC(mov_l_rrm_indexed(W4 d,RR4 baser, RR4 index, IMM factor));
DECLARE_MIDFUNC(mov_w_rrm_indexed(W2 d, RR4 baser, RR4 index, IMM factor));
DECLARE_MIDFUNC(mov_b_rrm_indexed(W1 d, RR4 baser, RR4 index, IMM factor));
DECLARE_MIDFUNC(mov_l_mrr_indexed(RR4 baser, RR4 index, IMM factor, RR4 s));
DECLARE_MIDFUNC(mov_w_mrr_indexed(RR4 baser, RR4 index, IMM factor, RR2 s));
DECLARE_MIDFUNC(mov_b_mrr_indexed(RR4 baser, RR4 index, IMM factor, RR1 s));
DECLARE_MIDFUNC(mov_l_bmrr_indexed(IMM base, RR4 baser, RR4 index, IMM factor, RR4 s));
DECLARE_MIDFUNC(mov_w_bmrr_indexed(IMM base, RR4 baser, RR4 index, IMM factor, RR2 s));
DECLARE_MIDFUNC(mov_b_bmrr_indexed(IMM base, RR4 baser, RR4 index, IMM factor, RR1 s));
DECLARE_MIDFUNC(mov_l_brrm_indexed(W4 d, IMM base, RR4 baser, RR4 index, IMM factor));
DECLARE_MIDFUNC(mov_w_brrm_indexed(W2 d, IMM base, RR4 baser, RR4 index, IMM factor));
DECLARE_MIDFUNC(mov_b_brrm_indexed(W1 d, IMM base, RR4 baser, RR4 index, IMM factor));
DECLARE_MIDFUNC(mov_l_rm_indexed(W4 d, IMM base, RR4 index, IMM factor));
DECLARE_MIDFUNC(mov_l_rR(W4 d, RR4 s, IMM offset));
DECLARE_MIDFUNC(mov_w_rR(W2 d, RR4 s, IMM offset));
DECLARE_MIDFUNC(mov_b_rR(W1 d, RR4 s, IMM offset));
DECLARE_MIDFUNC(mov_l_brR(W4 d, RR4 s, IMM offset));
DECLARE_MIDFUNC(mov_w_brR(W2 d, RR4 s, IMM offset));
DECLARE_MIDFUNC(mov_b_brR(W1 d, RR4 s, IMM offset));
DECLARE_MIDFUNC(mov_l_Ri(RR4 d, IMM i, IMM offset));
DECLARE_MIDFUNC(mov_w_Ri(RR4 d, IMM i, IMM offset));
DECLARE_MIDFUNC(mov_b_Ri(RR4 d, IMM i, IMM offset));
DECLARE_MIDFUNC(mov_l_Rr(RR4 d, RR4 s, IMM offset));
DECLARE_MIDFUNC(mov_w_Rr(RR4 d, RR2 s, IMM offset));
DECLARE_MIDFUNC(mov_b_Rr(RR4 d, RR1 s, IMM offset));
DECLARE_MIDFUNC(lea_l_brr(W4 d, RR4 s, IMM offset));
DECLARE_MIDFUNC(lea_l_brr_indexed(W4 d, RR4 s, RR4 index, IMM factor, IMM offset));
DECLARE_MIDFUNC(lea_l_rr_indexed(W4 d, RR4 s, RR4 index, IMM factor));
DECLARE_MIDFUNC(mov_l_bRr(RR4 d, RR4 s, IMM offset));
DECLARE_MIDFUNC(mov_w_bRr(RR4 d, RR2 s, IMM offset));
DECLARE_MIDFUNC(mov_b_bRr(RR4 d, RR1 s, IMM offset));
DECLARE_MIDFUNC(mid_bswap_32(RW4 r));
DECLARE_MIDFUNC(mid_bswap_16(RW2 r));
DECLARE_MIDFUNC(mov_l_rr(W4 d, RR4 s));
DECLARE_MIDFUNC(mov_l_mr(IMM d, RR4 s));
DECLARE_MIDFUNC(mov_w_mr(IMM d, RR2 s));
DECLARE_MIDFUNC(mov_w_rm(W2 d, IMM s));
DECLARE_MIDFUNC(mov_b_mr(IMM d, RR1 s));
DECLARE_MIDFUNC(mov_b_rm(W1 d, IMM s));
DECLARE_MIDFUNC(mov_l_ri(W4 d, IMM s));
DECLARE_MIDFUNC(mov_w_ri(W2 d, IMM s));
DECLARE_MIDFUNC(mov_b_ri(W1 d, IMM s));
DECLARE_MIDFUNC(add_l_mi(IMM d, IMM s));
DECLARE_MIDFUNC(add_w_mi(IMM d, IMM s));
DECLARE_MIDFUNC(add_b_mi(IMM d, IMM s));
DECLARE_MIDFUNC(test_l_ri(RR4 d, IMM i));
DECLARE_MIDFUNC(test_l_rr(RR4 d, RR4 s));
DECLARE_MIDFUNC(test_w_rr(RR2 d, RR2 s));
DECLARE_MIDFUNC(test_b_rr(RR1 d, RR1 s));
DECLARE_MIDFUNC(test_b_mi(IMM d, IMM s));
DECLARE_MIDFUNC(and_l_ri(RW4 d, IMM i));
DECLARE_MIDFUNC(and_l(RW4 d, RR4 s));
DECLARE_MIDFUNC(and_w(RW2 d, RR2 s));
DECLARE_MIDFUNC(and_b(RW1 d, RR1 s));
DECLARE_MIDFUNC(or_l_rm(RW4 d, IMM s));
DECLARE_MIDFUNC(or_l_ri(RW4 d, IMM i));
DECLARE_MIDFUNC(or_l(RW4 d, RR4 s));
DECLARE_MIDFUNC(or_w(RW2 d, RR2 s));
DECLARE_MIDFUNC(or_b(RW1 d, RR1 s));
DECLARE_MIDFUNC(adc_l(RW4 d, RR4 s));
DECLARE_MIDFUNC(adc_w(RW2 d, RR2 s));
DECLARE_MIDFUNC(adc_b(RW1 d, RR1 s));
DECLARE_MIDFUNC(add_l(RW4 d, RR4 s));
DECLARE_MIDFUNC(add_w(RW2 d, RR2 s));
DECLARE_MIDFUNC(add_b(RW1 d, RR1 s));
DECLARE_MIDFUNC(sub_l_ri(RW4 d, IMM i));
DECLARE_MIDFUNC(sub_w_ri(RW2 d, IMM i));
DECLARE_MIDFUNC(sub_b_ri(RW1 d, IMM i));
DECLARE_MIDFUNC(add_l_ri(RW4 d, IMM i));
DECLARE_MIDFUNC(add_w_ri(RW2 d, IMM i));
DECLARE_MIDFUNC(add_b_ri(RW1 d, IMM i));
DECLARE_MIDFUNC(sbb_l(RW4 d, RR4 s));
DECLARE_MIDFUNC(sbb_w(RW2 d, RR2 s));
DECLARE_MIDFUNC(sbb_b(RW1 d, RR1 s));
DECLARE_MIDFUNC(sub_l(RW4 d, RR4 s));
DECLARE_MIDFUNC(sub_w(RW2 d, RR2 s));
DECLARE_MIDFUNC(sub_b(RW1 d, RR1 s));
DECLARE_MIDFUNC(cmp_l(RR4 d, RR4 s));
DECLARE_MIDFUNC(cmp_l_ri(RR4 r, IMM i));
DECLARE_MIDFUNC(cmp_w(RR2 d, RR2 s));
DECLARE_MIDFUNC(cmp_b(RR1 d, RR1 s));
DECLARE_MIDFUNC(xor_l(RW4 d, RR4 s));
DECLARE_MIDFUNC(xor_w(RW2 d, RR2 s));
DECLARE_MIDFUNC(xor_b(RW1 d, RR1 s));
DECLARE_MIDFUNC(live_flags(void));
DECLARE_MIDFUNC(dont_care_flags(void));
DECLARE_MIDFUNC(duplicate_carry(void));
DECLARE_MIDFUNC(setcc_for_cntzero(RR4 d, RR4 data, int size));
DECLARE_MIDFUNC(restore_carry(void));
DECLARE_MIDFUNC(start_needflags(void));
DECLARE_MIDFUNC(end_needflags(void));
DECLARE_MIDFUNC(make_flags_live(void));
DECLARE_MIDFUNC(call_r_11(RR4 r, W4 out1, RR4 in1, IMM osize, IMM isize));
DECLARE_MIDFUNC(call_r_02(RR4 r, RR4 in1, RR4 in2, IMM isize1, IMM isize2));
DECLARE_MIDFUNC(forget_about(W4 r));
DECLARE_MIDFUNC(nop(void));
DECLARE_MIDFUNC(f_forget_about(FW r));
DECLARE_MIDFUNC(fmov_pi(FW r));
DECLARE_MIDFUNC(fmov_log10_2(FW r));
DECLARE_MIDFUNC(fmov_log2_e(FW r));
DECLARE_MIDFUNC(fmov_loge_2(FW r));
DECLARE_MIDFUNC(fmov_1(FW r));
DECLARE_MIDFUNC(fmov_0(FW r));
DECLARE_MIDFUNC(fmov_rm(FW r, MEMPTRR m));
DECLARE_MIDFUNC(fmov_mr(MEMPTRW m, FR r));
DECLARE_MIDFUNC(fmovi_rm(FW r, MEMPTRR m));
DECLARE_MIDFUNC(fmovi_mr(MEMPTRW m, FR r));
DECLARE_MIDFUNC(fmovi_mrb(MEMPTRW m, FR r, double *bounds));
DECLARE_MIDFUNC(fmovs_rm(FW r, MEMPTRR m));
DECLARE_MIDFUNC(fmovs_mr(MEMPTRW m, FR r));
DECLARE_MIDFUNC(fcuts_r(FRW r));
DECLARE_MIDFUNC(fcut_r(FRW r));
DECLARE_MIDFUNC(fmov_ext_mr(MEMPTRW m, FR r));
DECLARE_MIDFUNC(fmov_ext_rm(FW r, MEMPTRR m));
DECLARE_MIDFUNC(fmov_rr(FW d, FR s));
DECLARE_MIDFUNC(fldcw_m_indexed(RR4 index, IMM base));
DECLARE_MIDFUNC(ftst_r(FR r));
DECLARE_MIDFUNC(dont_care_fflags(void));
DECLARE_MIDFUNC(fsqrt_rr(FW d, FR s));
DECLARE_MIDFUNC(fabs_rr(FW d, FR s));
DECLARE_MIDFUNC(frndint_rr(FW d, FR s));
DECLARE_MIDFUNC(fgetexp_rr(FW d, FR s));
DECLARE_MIDFUNC(fgetman_rr(FW d, FR s));
DECLARE_MIDFUNC(fsin_rr(FW d, FR s));
DECLARE_MIDFUNC(fcos_rr(FW d, FR s));
DECLARE_MIDFUNC(ftan_rr(FW d, FR s));
DECLARE_MIDFUNC(fsincos_rr(FW d, FW c, FR s));
DECLARE_MIDFUNC(fscale_rr(FRW d, FR s));
DECLARE_MIDFUNC(ftwotox_rr(FW d, FR s));
DECLARE_MIDFUNC(fetox_rr(FW d, FR s));
DECLARE_MIDFUNC(fetoxM1_rr(FW d, FR s));
DECLARE_MIDFUNC(ftentox_rr(FW d, FR s));
DECLARE_MIDFUNC(flog2_rr(FW d, FR s));
DECLARE_MIDFUNC(flogN_rr(FW d, FR s));
DECLARE_MIDFUNC(flogNP1_rr(FW d, FR s));
DECLARE_MIDFUNC(flog10_rr(FW d, FR s));
DECLARE_MIDFUNC(fasin_rr(FW d, FR s));
DECLARE_MIDFUNC(facos_rr(FW d, FR s));
DECLARE_MIDFUNC(fatan_rr(FW d, FR s));
DECLARE_MIDFUNC(fatanh_rr(FW d, FR s));
DECLARE_MIDFUNC(fsinh_rr(FW d, FR s));
DECLARE_MIDFUNC(fcosh_rr(FW d, FR s));
DECLARE_MIDFUNC(ftanh_rr(FW d, FR s));
DECLARE_MIDFUNC(fneg_rr(FW d, FR s));
DECLARE_MIDFUNC(fadd_rr(FRW d, FR s));
DECLARE_MIDFUNC(fsub_rr(FRW d, FR s));
DECLARE_MIDFUNC(fmul_rr(FRW d, FR s));
DECLARE_MIDFUNC(frem_rr(FRW d, FR s));
DECLARE_MIDFUNC(frem1_rr(FRW d, FR s));
DECLARE_MIDFUNC(fdiv_rr(FRW d, FR s));
DECLARE_MIDFUNC(fcmp_rr(FR d, FR s));
DECLARE_MIDFUNC(fflags_into_flags(W2 tmp));

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,5 @@
/*
* compstbl.cpp must be compiled twice, once for the generator program
* and once for the actual executable
*/
#include "compstbl.cpp"

View File

@ -0,0 +1,52 @@
/*
* compiler/flags_arm.h - Native flags definitions for ARM
*
* Copyright (c) 2013 Jens Heitmann of ARAnyM dev team (see AUTHORS)
*
* Inspired by Christian Bauer's Basilisk II
*
* Original 68040 JIT compiler for UAE, copyright 2000-2002 Bernd Meyer
*
* Adaptation for Basilisk II and improvements, copyright 2000-2002
* Gwenole Beauchesne
*
* Basilisk II (C) 1997-2002 Christian Bauer
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef NATIVE_FLAGS_ARM_H
#define NATIVE_FLAGS_ARM_H
/* Native integer code conditions */
enum {
NATIVE_CC_EQ = 0,
NATIVE_CC_NE = 1,
NATIVE_CC_CS = 2,
NATIVE_CC_CC = 3,
NATIVE_CC_MI = 4,
NATIVE_CC_PL = 5,
NATIVE_CC_VS = 6,
NATIVE_CC_VC = 7,
NATIVE_CC_HI = 8,
NATIVE_CC_LS = 9,
NATIVE_CC_GE = 10,
NATIVE_CC_LT = 11,
NATIVE_CC_GT = 12,
NATIVE_CC_LE = 13,
NATIVE_CC_AL = 14
};
#endif /* NATIVE_FLAGS_ARM_H */

View File

@ -3,11 +3,11 @@
*
* Original 68040 JIT compiler for UAE, copyright 2000-2002 Bernd Meyer
*
* Adaptation for Basilisk II and improvements, copyright 2000-2005
* Adaptation for Basilisk II and improvements, copyright 2000-2002
* Gwenole Beauchesne
*
* Basilisk II (C) 1997-2008 Christian Bauer
*
* Basilisk II (C) 1997-2002 Christian Bauer
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
@ -34,8 +34,8 @@ enum {
NATIVE_CC_CS = 2,
NATIVE_CC_NE = 5,
NATIVE_CC_EQ = 4,
NATIVE_CC_VC = 11,
NATIVE_CC_VS = 10,
NATIVE_CC_VC = 1,
NATIVE_CC_VS = 0,
NATIVE_CC_PL = 9,
NATIVE_CC_MI = 8,
NATIVE_CC_GE = 13,
@ -44,4 +44,9 @@ enum {
NATIVE_CC_LE = 14
};
/* FIXME: include/flags_x86.h in UAE had the following values:
NATIVE_CC_VC = 11,
NATIVE_CC_VS = 10,
*/
#endif /* NATIVE_FLAGS_X86_H */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,264 @@
/* Example of using sigaction() to setup a signal handler with 3 arguments
* including siginfo_t.
*/
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
#include "flags_arm.h"
#include "codegen_arm.h"
#define TEST(c,ex,s) { c; if (opcode != ex) printf("(%s) Invalid opcode %x expected %x\n", s, opcode, ex); }
int opcode;
void emit_long(v) {
opcode = v;
}
int main (int argc, char *argv[])
{
TEST(MOV_ri(8, 15), 0xe3a0800f, "mov r8,#15");
TEST(MOV_rr(8,9), 0xe1a08009, "mov r8, r9");
TEST(MOV_rrLSLi(8,9,5), 0xe1a08289, "lsl r8, r9, #5");
TEST(MOV_rrLSLr(8,9,7), 0xe1a08719, "lsl r8, r9, r7");
TEST(MOV_rrLSRi(8,9,5), 0xe1a082a9, "lsr r8, r9, #5");
TEST(MOV_rrLSRr(8,9,7), 0xe1a08739, "lsr r8, r9, r7");
TEST(MOV_rrASRi(8,9,5), 0xe1a082c9, "asr r8, r9, #5");
TEST(MOV_rrASRr(8,9,7), 0xe1a08759, "asr r8, r9, r7");
TEST(MOV_rrRORi(8,9,5), 0xe1a082e9, "ror r8, r9, #5");
TEST(MOV_rrRORr(8,9,7), 0xe1a08779, "ror r8, r9, r7");
TEST(MOV_rrRRX(8,9), 0xe1a08069, "rrx r8, r9");
TEST(MOVS_ri(8, 15), 0xe3b0800f, "movs r8,#15");
TEST(MOVS_rr(8,9), 0xe1b08009, "movs r8, r9");
TEST(MOVS_rrLSLi(8,9,5), 0xe1b08289, "lsls r8, r9, #5");
TEST(MOVS_rrLSLr(8,9,7), 0xe1b08719, "lsls r8, r9, r7");
TEST(MOVS_rrLSRi(8,9,5), 0xe1b082a9, "lsrs r8, r9, #5");
TEST(MOVS_rrLSRr(8,9,7), 0xe1b08739, "lsrs r8, r9, r7");
TEST(MOVS_rrASRi(8,9,5), 0xe1b082c9, "asrs r8, r9, #5");
TEST(MOVS_rrASRr(8,9,7), 0xe1b08759, "asrs r8, r9, r7");
TEST(MOVS_rrRORi(8,9,5), 0xe1b082e9, "rors r8, r9, #5");
TEST(MOVS_rrRORr(8,9,7), 0xe1b08779, "rors r8, r9, r7");
TEST(MOVS_rrRRX(8,9), 0xe1b08069, "rrxs r8, r9");
TEST(MVN_ri(8, 15), 0xe3e0800f, "mvn r8,#15");
TEST(MVN_rr(8,9), 0xe1e08009, "mvn r8, r9");
TEST(MVN_rrLSLi(8,9,5), 0xe1e08289, "mvn r8, r9, lsl #5");
TEST(MVN_rrLSLr(8,9,7), 0xe1e08719, "mvn r8, r9, lsl r7");
TEST(MVN_rrLSRi(8,9,5), 0xe1e082a9, "mvn r8, r9, lsr #5");
TEST(MVN_rrLSRr(8,9,7), 0xe1e08739, "mvn r8, r9, lsr r7");
TEST(MVN_rrASRi(8,9,5), 0xe1e082c9, "mvn r8, r9, asr #5");
TEST(MVN_rrASRr(8,9,7), 0xe1e08759, "mvn r8, r9, asr r7");
TEST(MVN_rrRORi(8,9,5), 0xe1e082e9, "mvn r8, r9, ror #5");
TEST(MVN_rrRORr(8,9,7), 0xe1e08779, "mvn r8, r9, ror r7");
TEST(MVN_rrRRX(8,9), 0xe1e08069, "mvn r8, r9, rrx");
TEST(CMP_ri(8, 15), 0xe358000f, "cmp r8,#15");
TEST(CMP_rr(8,9), 0xe1580009, "cmp r8, r9");
TEST(CMP_rrLSLi(8,9,5), 0xe1580289, "cmp r8, r9, #5");
TEST(CMP_rrLSLr(8,9,7), 0xe1580719, "cmp r8, r9, r7");
TEST(CMP_rrLSRi(8,9,5), 0xe15802a9, "cmp r8, r9, #5");
TEST(CMP_rrLSRr(8,9,7), 0xe1580739, "cmp r8, r9, r7");
TEST(CMP_rrASRi(8,9,5), 0xe15802c9, "cmp r8, r9, #5");
TEST(CMP_rrASRr(8,9,7), 0xe1580759, "cmp r8, r9, r7");
TEST(CMP_rrRORi(8,9,5), 0xe15802e9, "cmp r8, r9, #5");
TEST(CMP_rrRORr(8,9,7), 0xe1580779, "cmp r8, r9, r7");
TEST(CMP_rrRRX(8,9), 0xe1580069, "cmp r8, r9");
TEST(CMP_ri(8, 0x81), 0xe3580081, "cmp r8,#0x81");
TEST(CMP_ri(8, 0x204), 0xe3580f81, "cmp r8,#0x204");
TEST(CMP_ri(8, 0x810), 0xe3580e81, "cmp r8,#0x8100");
TEST(CMP_ri(8, 0x2040), 0xe3580d81, "cmp r8,#0x2040");
TEST(CMP_ri(8, 0x8100), 0xe3580c81, "cmp r8,#0x8100");
TEST(CMP_ri(8, 0x20400), 0xe3580b81, "cmp r8,#0x20400");
TEST(CMP_ri(8, 0x81000), 0xe3580a81, "cmp r8,#0x81000");
TEST(CMP_ri(8, 0x204000), 0xe3580981, "cmp r8,#0x204000");
TEST(CMP_ri(8, 0x810000), 0xe3580881, "cmp r8,#0x810000");
TEST(CMP_ri(8, 0x2040000), 0xe3580781, "cmp r8,#0x2040000");
TEST(CMP_ri(8, 0x8100000), 0xe3580681, "cmp r8,#0x8100000");
TEST(CMP_ri(8, 0x20400000), 0xe3580581, "cmp r8,#0x20400000");
TEST(CMP_ri(8, 0x81000000), 0xe3580481, "cmp r8,#0x81000000");
TEST(CMP_ri(8, 0x04000002), 0xe3580381, "cmp r8,#0x04000002");
TEST(CMP_ri(8, 0x10000008), 0xe3580281, "cmp r8,#0x10000008");
TEST(CMP_ri(8, 0x40000020), 0xe3580181, "cmp r8,#0x40000020");
TEST(CMP_ri(8, 0x1200), 0xe3580c12, "cmp r8,#0x1200");
TEST(CMP_ri(8, 0x120000), 0xe3580812, "cmp r8,#0x120000");
TEST(CMP_ri(8, 0x12000000), 0xe3580412, "cmp r8,#0x12000000");
TEST(BEQ_i(5), 0x0a000005, "beq #5");
TEST(BNE_i(5), 0x1a000005, "bne #5");
TEST(BCS_i(5), 0x2a000005, "bcs #5");
TEST(BCC_i(5), 0x3a000005, "bcc #5");
TEST(BMI_i(5), 0x4a000005, "bmi #5");
TEST(BPL_i(5), 0x5a000005, "bpl #5");
TEST(BVS_i(5), 0x6a000005, "bvs #5");
TEST(BVC_i(5), 0x7a000005, "bvc #5");
TEST(BHI_i(5), 0x8a000005, "bhi #5");
TEST(BLS_i(5), 0x9a000005, "bls #5");
TEST(BGE_i(5), 0xaa000005, "bge #5");
TEST(BLT_i(5), 0xba000005, "blt #5");
TEST(BGT_i(5), 0xca000005, "bgt #5");
TEST(BLE_i(5), 0xda000005, "ble #5");
TEST(B_i(5), 0xea000005, "b #5");
TEST(BL_i(5), 0xeb000005, "bl #5");
TEST(BLX_r(8), 0xe12fff38, "blx r8");
TEST(BX_r(8), 0xe12fff18, "bx r8");
TEST(EOR_rri(6, 8, 15), 0xe228600f, "eor r6, r8,#15");
TEST(EOR_rrr(6, 8,9), 0xe0286009, "eor r6, r8, r9");
TEST(EOR_rrrLSLi(6,8,9,5), 0xe0286289, "eor r6, r8, r9, lsl #5");
TEST(EOR_rrrLSLr(6,8,9,7), 0xe0286719, "eor r6, r8, r9, lsl r7");
TEST(EOR_rrrLSRi(6,8,9,5), 0xe02862a9, "eor r6, r8, r9, lsr #5");
TEST(EOR_rrrLSRr(6,8,9,7), 0xe0286739, "eor r6, r8, r9, lsr r7");
TEST(EOR_rrrASRi(6,8,9,5), 0xe02862c9, "eor r6, r8, r9, asr #5");
TEST(EOR_rrrASRr(6,8,9,7), 0xe0286759, "eor r6, r8, r9, asr r7");
TEST(EOR_rrrRORi(6,8,9,5), 0xe02862e9, "eor r6, r8, r9, ror #5");
TEST(EOR_rrrRORr(6,8,9,7), 0xe0286779, "eor r6, r8, r9, ror r7");
TEST(EOR_rrrRRX(6,8,9), 0xe0286069, "eor r6, r8, r9, rrx");
TEST(EORS_rri(6, 8, 15), 0xe238600f, "eors r6, r8,#15");
TEST(EORS_rrr(6, 8,9), 0xe0386009, "eors r6, r8, r9");
TEST(EORS_rrrLSLi(6,8,9,5), 0xe0386289, "eors r6, r8, r9, lsl #5");
TEST(EORS_rrrLSLr(6,8,9,7), 0xe0386719, "eors r6, r8, r9, lsr r7");
TEST(EORS_rrrLSRi(6,8,9,5), 0xe03862a9, "eors r6, r8, r9, lsr #5");
TEST(EORS_rrrLSRr(6,8,9,7), 0xe0386739, "eors r6, r8, r9, lsr r7");
TEST(EORS_rrrASRi(6,8,9,5), 0xe03862c9, "eors r6, r8, r9, asr #5");
TEST(EORS_rrrASRr(6,8,9,7), 0xe0386759, "eors r6, r8, r9, asr r7");
TEST(EORS_rrrRORi(6,8,9,5), 0xe03862e9, "eors r6, r8, r9, ror #5");
TEST(EORS_rrrRORr(6,8,9,7), 0xe0386779, "eors r6, r8, r9, ror r7");
TEST(EORS_rrrRRX(6,8,9), 0xe0386069, "eors r6, r8, r9, rrx");
TEST(MRS_CPSR(6), 0xe10f6000, "mrs r6, CPSR");
TEST(MRS_SPSR(6), 0xe14f6000, "mrs r6, SPSR");
TEST(MSR_CPSR_i(5), 0xe329f005, "msr CPSR_fc, #5");
TEST(MSR_CPSR_r(5), 0xe129f005, "msr CPSR_fc, r5");
TEST(MSR_CPSRf_i(5), 0xe328f005, "msr CPSR_f, #5");
TEST(MSR_CPSRf_r(5), 0xe128f005, "msr CPSR_f, r5");
TEST(MSR_CPSRc_i(5), 0xe321f005, "msr CPSR_c, #5");
TEST(MSR_CPSRc_r(5), 0xe121f005, "msr CPSR_c, r5");
TEST(PUSH(6), 0xe92d0040, "push {r6}");
TEST(POP(6), 0xe8bd0040, "pop {r6}");
TEST(BIC_rri(0, 0, 0x9f000000), 0xe3c0049f, "bic r0, r0, #0x9f000000");
TEST(BIC_rri(2, 3, 0xff00), 0xe3c32cff, "bic r2, r3, #0xff00");
TEST(BIC_rri(3, 4, 0xff), 0xe3c430ff, "bic r3, r4, #0xff");
TEST(ORR_rrrLSRi(0, 1, 2, 16), 0xe1810822, "orr r0, r1, r2, lsr #16");
TEST(ORR_rrrLSRi(0, 1, 2, 24), 0xe1810c22, "orr r0, r1, r2, lsr #24");
TEST(LDR_rR(8, 9), 0xe5998000, "ldr r8, [r9]");
TEST(LDR_rRI(8, 9, 4), 0xe5998004, "ldr r8, [r9, #4]");
TEST(LDR_rRi(8, 9, 4), 0xe5198004, "ldr r8, [r9, #-4]");
TEST(LDR_rRR(8, 9, 7), 0xe7998007, "ldr r8, [r9, r7]");
TEST(LDR_rRr(8, 9, 7), 0xe7198007, "ldr r8, [r9, -r7]");
TEST(LDR_rRR_LSLi(8, 9, 7, 5), 0xe7998287, "ldr r8, [r9, r7, lsl #5]");
TEST(LDR_rRr_LSLi(8, 9, 7, 5), 0xe7198287, "ldr r8, [r9, -r7, lsl #5]");
TEST(LDR_rRR_LSRi(8, 9, 7, 5), 0xe79982a7, "ldr r8, [r9, r7, lsr #5]");
TEST(LDR_rRr_LSRi(8, 9, 7, 5), 0xe71982a7, "ldr r8, [r9, -r7, lsr #5]");
TEST(LDR_rRR_ASRi(8, 9, 7, 5), 0xe79982c7, "ldr r8, [r9, r7, asr #5]");
TEST(LDR_rRr_ASRi(8, 9, 7, 5), 0xe71982c7, "ldr r8, [r9, -r7, asr #5]");
TEST(LDR_rRR_RORi(8, 9, 7, 5), 0xe79982e7, "ldr r8, [r9, r7, ror #5]");
TEST(LDR_rRr_RORi(8, 9, 7, 5), 0xe71982e7, "ldr r8, [r9, -r7, ror #5]");
TEST(LDR_rRR_RRX(8, 9, 7), 0xe7998067, "ldr r8, [r9, r7, rrx]");
TEST(LDR_rRr_RRX(8, 9, 7), 0xe7198067, "ldr r8, [r9, -r7, rrx]");
TEST(LDRB_rR(8, 9), 0xe5d98000, "ldrb r8, [r9]");
TEST(LDRB_rRI(8, 9, 4), 0xe5d98004, "ldrb r8, [r9, #4]");
TEST(LDRB_rRi(8, 9, 4), 0xe5598004, "ldrb r8, [r9, #-4]");
TEST(LDRB_rRR(8, 9, 7), 0xe7d98007, "ldrb r8, [r9, r7]");
TEST(LDRB_rRr(8, 9, 7), 0xe7598007, "ldrb r8, [r9, -r7]");
TEST(LDRB_rRR_LSLi(8, 9, 7, 5), 0xe7d98287, "ldrb r8, [r9, r7, lsl #5]");
TEST(LDRB_rRr_LSLi(8, 9, 7, 5), 0xe7598287, "ldrb r8, [r9, -r7, lsl #5]");
TEST(LDRB_rRR_LSRi(8, 9, 7, 5), 0xe7d982a7, "ldrb r8, [r9, r7, lsr #5]");
TEST(LDRB_rRr_LSRi(8, 9, 7, 5), 0xe75982a7, "ldrb r8, [r9, -r7, lsr #5]");
TEST(LDRB_rRR_ASRi(8, 9, 7, 5), 0xe7d982c7, "ldrb r8, [r9, r7, asr #5]");
TEST(LDRB_rRr_ASRi(8, 9, 7, 5), 0xe75982c7, "ldrb r8, [r9, -r7, asr #5]");
TEST(LDRB_rRR_RORi(8, 9, 7, 5), 0xe7d982e7, "ldrb r8, [r9, r7, ror #5]");
TEST(LDRB_rRr_RORi(8, 9, 7, 5), 0xe75982e7, "ldrb r8, [r9, -r7, ror #5]");
TEST(LDRB_rRR_RRX(8, 9, 7), 0xe7d98067, "ldrb r8, [r9, r7, rrx]");
TEST(LDRB_rRr_RRX(8, 9, 7), 0xe7598067, "ldrb r8, [r9, -r7, rrx]");
TEST(LDRSB_rR(8, 9), 0xe1d980d0, "ldrsb r8, [r9]");
TEST(LDRSB_rRI(8, 9, 4), 0xe1d980d4, "ldrsb r8, [r9, #4]");
TEST(LDRSB_rRi(8, 9, 4), 0xe15980d4, "ldrsb r8, [r9, #-4]");
TEST(LDRSB_rRR(8, 9, 7), 0xe19980d7, "ldrsb r8, [r9, r7]");
TEST(LDRSB_rRr(8, 9, 7), 0xe11980d7, "ldrsb r8, [r9, -r7]");
TEST(LDRSH_rR(8, 9), 0xe1d980f0, "ldrsh r8, [r9]");
TEST(LDRSH_rRI(8, 9, 4), 0xe1d980f4, "ldrsh r8, [r9, #4]");
TEST(LDRSH_rRi(8, 9, 4), 0xe15980f4, "ldrsh r8, [r9, #-4]");
TEST(LDRSH_rRR(8, 9, 7), 0xe19980f7, "ldrsh r8, [r9, r7]");
TEST(LDRSH_rRr(8, 9, 7), 0xe11980f7, "ldrsh r8, [r9, -r7]");
TEST(LDRH_rR(8, 9), 0xe1d980b0, "ldrh r8, [r9]");
TEST(LDRH_rRI(8, 9, 4), 0xe1d980b4, "ldrh r8, [r9, #4]");
TEST(LDRH_rRi(8, 9, 4), 0xe15980b4, "ldrh r8, [r9, #-4]");
TEST(LDRH_rRR(8, 9, 7), 0xe19980b7, "ldrh r8, [r9, r7]");
TEST(LDRH_rRr(8, 9, 7), 0xe11980b7, "ldrh r8, [r9, -r7]");
TEST(STR_rRR(8,9,7), 0xe7898007, "str r8, [r9, r7]");
TEST(STR_rRr(8,9,7), 0xe7098007, "str r8, [r9, -r7]");
TEST(STRB_rR(5, 6), 0xe5c65000, "strb r5,[r6]");
TEST(STRH_rR(8, 9), 0xe1c980b0, "strh r8, [r9]");
TEST(STRH_rRI(8, 9, 4), 0xe1c980b4, "strh r8, [r9, #4]");
TEST(STRH_rRi(8, 9, 4), 0xe14980b4, "strh r8, [r9, #-4]");
TEST(STRH_rRR(8, 9, 7), 0xe18980b7, "strh r8, [r9, r7]");
TEST(STRH_rRr(8, 9, 7), 0xe10980b7, "strh r8, [r9, -r7]");
TEST(CLZ_rr(2, 3), 0xe16f2f13, "clz r2,r3");
TEST(REV_rr(2, 3), 0xe6bf2f33, "rev r2, r3");
TEST(REV16_rr(2, 3), 0xe6bf2fb3, "rev16 r2, r3");
TEST(REVSH_rr(2, 3), 0xe6ff2fb3, "revsh r2, r3");
TEST(SXTB_rr(2,3), 0xe6af2073, "sxtb r2,r3");
TEST(SXTB_rr(3,4), 0xe6af3074, "sxtb r3,r4");
TEST(SXTB_rr_ROR8(2,3), 0xe6af2473, "sxtb r2, r3, ror #8");
TEST(SXTB_rr_ROR16(2,3), 0xe6af2873, "sxtb r2, r3, ror #16");
TEST(SXTB_rr_ROR24(2,3), 0xe6af2c73, "sxtb r2, r3, ror #24");
TEST(SXTH_rr(2,3), 0xe6bf2073, "sxth r2, r3");
TEST(SXTH_rr_ROR8(2,3), 0xe6bf2473, "sxth r2, r3, ror #8");
TEST(SXTH_rr_ROR16(2,3), 0xe6bf2873, "sxth r2, r3, ror #16");
TEST(SXTH_rr_ROR24(2,3), 0xe6bf2c73, "sxth r2, r3, ror #24");
TEST(UXTB_rr(2,3), 0xe6ef2073, "uxtb r2, r3");
TEST(UXTB_rr_ROR8(2,3), 0xe6ef2473, "uxtb r2, r3, ror #8");
TEST(UXTB_rr_ROR16(2,3), 0xe6ef2873, "uxtb r2, r3, ror #16");
TEST(UXTB_rr_ROR24(2,3), 0xe6ef2c73, "uxtb r2, r3, ror #24");
TEST(UXTH_rr(2,3), 0xe6ff2073, "uxth r2, r3");
TEST(UXTH_rr_ROR8(2,3), 0xe6ff2473, "uxth r2, r3, ror #8");
TEST(UXTH_rr_ROR16(2,3), 0xe6ff2873, "uxth r2, r3, ror #16");
TEST(UXTH_rr_ROR24(2,3), 0xe6ff2c73, "uxth r2, r3, ror #24");
TEST(REV_rr(2,3), 0xe6bf2f33, "rev r2, r3");
TEST(REV16_rr(2,3), 0xe6bf2fb3, "rev16 r2, r3");
TEST(REVSH_rr(2,3), 0xe6ff2fb3, "revsh r2, r3");
TEST(CC_MOV_ri(NATIVE_CC_CS, 4,1), 0x23a04001, "movcs r4, #1");
TEST(CC_MOV_ri(NATIVE_CC_CC, 4,1), 0x33a04001, "movcc r4, #1");
int imm = 0x9f;
TEST(ADDS_rri(0, 0, imm << 24), 0xe290049f, "adds r0, r0, 0x9f000000");
TEST(PKHBT_rrr(1, 2, 3), 0xe6821013, "pkhbt r1,r2,r3");
TEST(MVN_ri8(1,2), 0xe3e01002, "mvn r1,#2");
TEST(ORR_rri8RORi(1,2,0x12,24), 0xe3821c12, "orr r1, r2, #0x1200");
TEST(PKHTB_rrrASRi(1, 2, 3, 4), 0xe6821253, "pkhtb r1,r2,r3,ASR #4");
TEST(PKHBT_rrrLSLi(1, 2, 3, 4), 0xe6821213, "pkhbt r1,r2,r3,LSL #4");
TEST(MUL_rrr(1,2,3), 0xe0010392, "mul r1, r2, r3");
TEST(MULS_rrr(1,2,3), 0xe0110392, "muls r1, r2, r3");
}

File diff suppressed because it is too large Load Diff

View File

@ -1,52 +1,170 @@
/*
* cpu_emulation.h - Definitions for Basilisk II CPU emulation module (UAE 0.8.10 version)
* cpu_emulation.h - CPU interface
*
* Basilisk II (C) 1997-2008 Christian Bauer
* Copyright (c) 2001-2005 Milan Jurik of ARAnyM dev team (see AUTHORS)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* Inspired by Christian Bauer's Basilisk II
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* This file is part of the ARAnyM project which builds a new and powerful
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* ARAnyM is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* ARAnyM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ARAnyM; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef CPU_EMULATION_H
#define CPU_EMULATION_H
#include <string.h>
/*
* Memory system
*/
#if 0
#include "sysdeps.h"
#include "memory.h"
#include "tools.h"
#endif
// RAM and ROM pointers (allocated and set by main_*.cpp)
#if 0
extern memptr RAMBase; // RAM base (Atari address space), does not include Low Mem when != 0
#else
extern uint32 RAMBaseMac; // RAM base (Mac address space), does not include Low Mem when != 0
extern uint8 *RAMBaseHost; // RAM base (host address space)
extern uint32 RAMSize; // Size of RAM
#endif
extern uint8 *RAMBaseHost; // RAM base (host address space)
extern uint32 RAMSize; // Size of RAM
#if 0
extern memptr ROMBase; // ROM base (Atari address space)
#else
extern uint32 ROMBaseMac; // ROM base (Mac address space)
extern uint8 *ROMBaseHost; // ROM base (host address space)
extern uint32 ROMSize; // Size of ROM
#endif
extern uint8 *ROMBaseHost; // ROM base (host address space)
extern uint32 ROMSize; // Size of ROM
#if 0
extern uint32 RealROMSize; // Real size of ROM
extern memptr HWBase; // HW base (Atari address space)
extern uint8 *HWBaseHost; // HW base (host address space)
extern uint32 HWSize; // Size of HW space
#if !REAL_ADDRESSING && !DIRECT_ADDRESSING
// If we are not using real or direct addressing, the Mac frame buffer gets
// mapped to this location. The memory must be allocated by VideoInit().
// If multiple monitors are used, they must share the frame buffer
extern memptr FastRAMBase; // Fast-RAM base (Atari address space)
extern uint8 *FastRAMBaseHost; // Fast-RAM base (host address space)
extern memptr VideoRAMBase; // VideoRAM base (Atari address space)
extern uint8 *VideoRAMBaseHost; // VideoRAM base (host address space)
#ifdef HW_SIGSEGV
extern uint8 *FakeIOBaseHost;
#endif
#ifdef RAMENDNEEDED
# define RAMEnd 0x01000000 // Not accessible top of memory
#else
# define RAMEnd 0
#endif
#endif
#if !REAL_ADDRESSING
// If we are not using real addressing, the Mac frame buffer gets mapped to this location
// The memory must be allocated by VideoInit(). If multiple monitors are used, they must
// share the frame buffer
const uint32 MacFrameBaseMac = 0xa0000000;
extern uint8 *MacFrameBaseHost; // Frame buffer base (host address space)
extern uint32 MacFrameSize; // Size of frame buffer
#endif
extern int MacFrameLayout; // Frame buffer layout (see defines below)
#endif
#if 0
// Atari memory access functions
// Direct access to CPU address space
// For HW operations
// Read/WriteAtariIntXX
//
static inline uint64 ReadAtariInt64(memptr addr) {return phys_get_quad(addr);}
static inline uint32 ReadAtariInt32(memptr addr) {return phys_get_long(addr);}
static inline uint16 ReadAtariInt16(memptr addr) {return phys_get_word(addr);}
static inline uint8 ReadAtariInt8(memptr addr) {return phys_get_byte(addr);}
static inline void WriteAtariInt64(memptr addr, uint64 q) {phys_put_quad(addr, q);}
static inline void WriteAtariInt32(memptr addr, uint32 l) {phys_put_long(addr, l);}
static inline void WriteAtariInt16(memptr addr, uint16 w) {phys_put_word(addr, w);}
static inline void WriteAtariInt8(memptr addr, uint8 b) {phys_put_byte(addr, b);}
// Direct access to allocated memory
// Ignores HW checks, so that be carefull
// Read/WriteHWMemIntXX
//
static inline uint32 ReadHWMemInt32(memptr addr) {return do_get_mem_long((uae_u32 *)phys_get_real_address(addr));}
static inline uint16 ReadHWMemInt16(memptr addr) {return do_get_mem_word((uae_u16 *)phys_get_real_address(addr));}
static inline uint8 ReadHWMemInt8(memptr addr) {return do_get_mem_byte((uae_u8 *)phys_get_real_address(addr));}
static inline void WriteHWMemInt32(memptr addr, uint32 l) {do_put_mem_long((uae_u32 *)phys_get_real_address(addr), l);}
static inline void WriteHWMemInt16(memptr addr, uint16 w) {do_put_mem_word((uae_u16 *)phys_get_real_address(addr), w);}
static inline void WriteHWMemInt8(memptr addr, uint8 b) {do_put_mem_byte((uae_u8 *)phys_get_real_address(addr), b);}
// Indirect access to CPU address space
// Uses MMU if available
// For SW operations
// Only data space
// Read/WriteIntXX
//
static inline uint64 ReadInt64(memptr addr) {return get_quad(addr);}
static inline uint32 ReadInt32(memptr addr) {return get_long(addr);}
static inline uint16 ReadInt16(memptr addr) {return get_word(addr);}
static inline uint8 ReadInt8(memptr addr) {return get_byte(addr);}
static inline void WriteInt64(memptr addr, uint64 q) {put_quad(addr, q);}
static inline void WriteInt32(memptr addr, uint32 l) {put_long(addr, l);}
static inline void WriteInt16(memptr addr, uint16 w) {put_word(addr, w);}
static inline void WriteInt8(memptr addr, uint8 b) {put_byte(addr, b);}
#ifdef EXTENDED_SIGSEGV
extern int in_handler;
#ifdef NO_NESTED_SIGSEGV
extern JMP_BUF sigsegv_env;
# define BUS_ERROR(a) \
{ \
regs.mmu_fault_addr=(a); \
if (in_handler) \
{ \
in_handler = 0; \
LONGJMP(sigsegv_env, 1); \
} \
else { \
breakpt(); \
THROW(2); \
} \
}
#else /* NO_NESTED_SIGSEGV */
# define BUS_ERROR(a) \
{ \
regs.mmu_fault_addr=(a); \
in_handler = 0; \
breakpt(); \
THROW(2); \
}
#endif /* NO_NESTED_SIGSEGV */
#else /* EXTENDED_SIGSEGV */
# define BUS_ERROR(a) \
{ \
regs.mmu_fault_addr=(a); \
breakpt(); \
THROW(2); \
}
#endif /* EXTENDED_SIGSEGV */
// For address validation
static inline bool ValidAtariAddr(memptr addr, bool write, uint32 len) { return phys_valid_address(addr, write, len); }
static inline bool ValidAddr(memptr addr, bool write, uint32 len) { return valid_address(addr, write, len); }
// Helper functions for usual memory operations
static inline uint8 *Atari2HostAddr(memptr addr) {return phys_get_real_address(addr);}
#endif
// Possible frame buffer layouts
enum {
FLAYOUT_NONE, // No frame buffer
@ -73,30 +191,73 @@ static inline void *Host2Mac_memcpy(uint32 dest, const void *src, size_t n) {ret
static inline void *Mac2Mac_memcpy(uint32 dest, uint32 src, size_t n) {return memcpy(Mac2HostAddr(dest), Mac2HostAddr(src), n);}
// From newcpu.cpp
extern int quit_program;
extern int exit_val;
/*
* 680x0 emulation
*/
// Initialization
extern bool Init680x0(void); // This routine may want to look at CPUType/FPUType to set up the apropriate emulation
#if 0
extern bool InitMEM();
#endif
extern bool Init680x0(void);
#if 0
extern void Reset680x0(void);
#endif
extern void Exit680x0(void);
extern void InitFrameBufferMapping(void);
// 680x0 dynamic recompilation activation flag
#if USE_JIT
extern bool UseJIT;
#else
const bool UseJIT = false;
#if 0
extern void AtariReset(void);
#endif
// 680x0 emulation functions
struct M68kRegisters;
extern void Start680x0(void); // Reset and start 680x0
extern void Start680x0(void); // Reset and start 680x0
#if 0
extern void Restart680x0(void); // Restart running 680x0
extern void Quit680x0(void); // Quit 680x0
#endif
extern "C" void Execute68k(uint32 addr, M68kRegisters *r); // Execute 68k code from EMUL_OP routine
extern "C" void Execute68kTrap(uint16 trap, M68kRegisters *r); // Execute MacOS 68k trap from EMUL_OP routine
// Interrupt functions
extern void TriggerInterrupt(void); // Trigger interrupt level 1 (InterruptFlag must be set first)
extern void TriggerNMI(void); // Trigger interrupt level 7
#if 0
extern int MFPdoInterrupt(void);
extern int SCCdoInterrupt(void);
extern void TriggerInternalIRQ(void);
extern void TriggerInt3(void); // Trigger interrupt level 3
extern void TriggerVBL(void); // Trigger interrupt level 4
extern void TriggerInt5(void); // Trigger interrupt level 5
extern void TriggerSCC(bool); // Trigger interrupt level 5
extern void TriggerMFP(bool); // Trigger interrupt level 6
#endif
extern void TriggerInterrupt(void); // Trigger interrupt level 1 (InterruptFlag must be set first)
extern void TriggerNMI(void); // Trigger interrupt level 7
#if 0
#ifdef FLIGHT_RECORDER
extern void cpu_flight_recorder(int);
extern void dump_flight_recorder(void);
#endif
#endif
// CPU looping handlers
void check_eps_limit(uaecptr);
void report_double_bus_error(void);
#if 0
// This function will be removed
static inline uaecptr showPC(void) { return m68k_getpc(); } // for debugging only
#endif
extern int intlev(void);
static inline void AtariReset(void) {}
#endif
/*
vim:ts=4:sw=4:
*/

View File

@ -0,0 +1,5 @@
/*
* cpudefs.cpp must be compiled twice, once for the generator program
* and once for the actual executable
*/
#include "cpudefs.cpp"

View File

@ -0,0 +1,2 @@
#define PART_1
#include "cpuemu.cpp"

View File

@ -0,0 +1,3 @@
#define NOFLAGS 1
#define PART_1
#include "cpuemu.cpp"

View File

@ -0,0 +1,2 @@
#define PART_2
#include "cpuemu.cpp"

View File

@ -0,0 +1,3 @@
#define NOFLAGS 1
#define PART_2
#include "cpuemu.cpp"

View File

@ -0,0 +1,2 @@
#define PART_3
#include "cpuemu.cpp"

View File

@ -0,0 +1,3 @@
#define NOFLAGS 1
#define PART_3
#include "cpuemu.cpp"

View File

@ -0,0 +1,2 @@
#define PART_4
#include "cpuemu.cpp"

View File

@ -0,0 +1,3 @@
#define NOFLAGS 1
#define PART_4
#include "cpuemu.cpp"

View File

@ -0,0 +1,2 @@
#define PART_5
#include "cpuemu.cpp"

View File

@ -0,0 +1,4 @@
#define NOFLAGS 1
#define PART_5
#include "cpuemu.cpp"

View File

@ -0,0 +1,2 @@
#define PART_6
#include "cpuemu.cpp"

View File

@ -0,0 +1,3 @@
#define NOFLAGS 1
#define PART_6
#include "cpuemu.cpp"

View File

@ -0,0 +1,2 @@
#define PART_7
#include "cpuemu.cpp"

View File

@ -0,0 +1,3 @@
#define NOFLAGS 1
#define PART_7
#include "cpuemu.cpp"

View File

@ -0,0 +1,2 @@
#define PART_8
#include "cpuemu.cpp"

View File

@ -0,0 +1,3 @@
#define NOFLAGS 1
#define PART_8
#include "cpuemu.cpp"

View File

@ -0,0 +1,5 @@
/*
* cpufunctbl.cpp must be compiled twice, once for the generator program
* and once for the actual executable
*/
#include "cpufunctbl.cpp"

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,267 @@
/*
* cpummu.h - MMU emulation
*
* Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
*
* Inspired by UAE MMU patch
*
* This file is part of the ARAnyM project which builds a new and powerful
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
*
* ARAnyM is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* ARAnyM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ARAnyM; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef CPUMMU_H
#define CPUMMU_H
#include "registers.h"
# include <cstdlib>
#define MMU_TEST_PTEST 1
#define MMU_TEST_VERBOSE 2
#define MMU_TEST_FORCE_TABLE_SEARCH 4
#define MMU_TEST_NO_BUSERR 8
extern void mmu_dump_tables(void);
#define MMU_TTR_LOGICAL_BASE 0xff000000
#define MMU_TTR_LOGICAL_MASK 0x00ff0000
#define MMU_TTR_BIT_ENABLED (1 << 15)
#define MMU_TTR_BIT_SFIELD_ENABLED (1 << 14)
#define MMU_TTR_BIT_SFIELD_SUPER (1 << 13)
#define MMU_TTR_SFIELD_SHIFT 13
#define MMU_TTR_UX_MASK ((1 << 9) | (1 << 8))
#define MMU_TTR_UX_SHIFT 8
#define MMU_TTR_CACHE_MASK ((1 << 6) | (1 << 5))
#define MMU_TTR_CACHE_SHIFT 5
#define MMU_TTR_BIT_WRITE_PROTECT (1 << 2)
#define MMU_UDT_MASK 3
#define MMU_PDT_MASK 3
#define MMU_DES_WP 4
#define MMU_DES_USED 8
/* page descriptors only */
#define MMU_DES_MODIFIED 16
#define MMU_DES_SUPER (1 << 7)
#define MMU_DES_GLOBAL (1 << 10)
#define MMU_ROOT_PTR_ADDR_MASK 0xfffffe00
#define MMU_PTR_PAGE_ADDR_MASK_8 0xffffff80
#define MMU_PTR_PAGE_ADDR_MASK_4 0xffffff00
#define MMU_PAGE_INDIRECT_MASK 0xfffffffc
#define MMU_PAGE_ADDR_MASK_8 0xffffe000
#define MMU_PAGE_ADDR_MASK_4 0xfffff000
#define MMU_PAGE_UR_MASK_8 ((1 << 12) | (1 << 11))
#define MMU_PAGE_UR_MASK_4 (1 << 11)
#define MMU_PAGE_UR_SHIFT 11
#define MMU_MMUSR_ADDR_MASK 0xfffff000
#define MMU_MMUSR_B (1 << 11)
#define MMU_MMUSR_G (1 << 10)
#define MMU_MMUSR_U1 (1 << 9)
#define MMU_MMUSR_U0 (1 << 8)
#define MMU_MMUSR_Ux (MMU_MMUSR_U1 | MMU_MMUSR_U0)
#define MMU_MMUSR_S (1 << 7)
#define MMU_MMUSR_CM ((1 << 6) | ( 1 << 5))
#define MMU_MMUSR_M (1 << 4)
#define MMU_MMUSR_W (1 << 2)
#define MMU_MMUSR_T (1 << 1)
#define MMU_MMUSR_R (1 << 0)
/* special status word (access error stack frame) */
#define MMU_SSW_TM 0x0007
#define MMU_SSW_TT 0x0018
#define MMU_SSW_SIZE 0x0060
#define MMU_SSW_SIZE_B 0x0020
#define MMU_SSW_SIZE_W 0x0040
#define MMU_SSW_SIZE_L 0x0000
#define MMU_SSW_RW 0x0100
#define MMU_SSW_LK 0x0200
#define MMU_SSW_ATC 0x0400
#define MMU_SSW_MA 0x0800
#define TTR_I0 4
#define TTR_I1 5
#define TTR_D0 6
#define TTR_D1 7
#define TTR_NO_MATCH 0
#define TTR_NO_WRITE 1
#define TTR_OK_MATCH 2
struct mmu_atc_line {
uae_u16 tag;
unsigned tt : 1;
unsigned valid_data : 1;
unsigned valid_inst : 1;
unsigned global : 1;
unsigned modified : 1;
unsigned write_protect : 1;
unsigned hw : 1;
unsigned bus_fault : 1;
uaecptr phys;
};
/*
* We don't need to store the whole logical address in the atc cache, as part of
* it is encoded as index into the cache. 14 bits of the address are stored in
* the tag, this means at least 6 bits must go into the index. The upper two
* bits of the tag define the type of data in the atc line:
* - 00: a normal memory address
* - 11: invalid memory address or hardware access
* (generated via ~ATC_TAG(addr) in the slow path)
* - 10: empty atc line
*/
#define ATC_TAG_SHIFT 18
#define ATC_TAG(addr) ((uae_u32)(addr) >> ATC_TAG_SHIFT)
#define ATC_L1_SIZE_LOG 8
#define ATC_L1_SIZE (1 << ATC_L1_SIZE_LOG)
#define ATC_L1_INDEX(addr) (((addr) >> 12) % ATC_L1_SIZE)
/*
* first level atc cache
* indexed by [super][data][rw][idx]
*/
typedef struct mmu_atc_line mmu_atc_l1_array[2][2][ATC_L1_SIZE];
extern mmu_atc_l1_array atc_l1[2];
extern mmu_atc_l1_array *current_atc;
#define ATC_L2_SIZE_LOG 12
#define ATC_L2_SIZE (1 << ATC_L2_SIZE_LOG)
#define ATC_L2_INDEX(addr) ((((addr) >> 12) ^ ((addr) >> (32 - ATC_L2_SIZE_LOG))) % ATC_L2_SIZE)
extern struct mmu_atc_line atc_l2[2][ATC_L2_SIZE];
/*
* lookup address in the level 1 atc cache,
* the data and write arguments are constant in the common,
* thus allows gcc to generate a constant offset.
*/
static ALWAYS_INLINE int mmu_lookup(uaecptr addr, bool data, bool write,
struct mmu_atc_line **cl)
{
addr >>= 12;
*cl = &(*current_atc)[data][write][addr % ATC_L1_SIZE];
return (*cl)->tag == addr >> (ATC_TAG_SHIFT - 12);
}
/*
* similiar to mmu_user_lookup, but for the use of the moves instruction
*/
static ALWAYS_INLINE int mmu_user_lookup(uaecptr addr, bool super, bool data,
bool write, struct mmu_atc_line **cl)
{
addr >>= 12;
*cl = &atc_l1[super][data][write][addr % ATC_L1_SIZE];
return (*cl)->tag == addr >> (ATC_TAG_SHIFT - 12);
}
extern REGPARAM2 uae_u16 mmu_get_word_unaligned(uaecptr addr, int data);
extern REGPARAM2 uae_u32 mmu_get_long_unaligned(uaecptr addr, int data);
extern REGPARAM2 uae_u8 mmu_get_byte_slow(uaecptr addr, int super, int data,
int size, struct mmu_atc_line *cl);
extern REGPARAM2 uae_u16 mmu_get_word_slow(uaecptr addr, int super, int data,
int size, struct mmu_atc_line *cl);
extern REGPARAM2 uae_u32 mmu_get_long_slow(uaecptr addr, int super, int data,
int size, struct mmu_atc_line *cl);
extern REGPARAM2 uae_u64 mmu_get_quad_slow(uaecptr addr, int super, int data,
struct mmu_atc_line *cl);
extern REGPARAM2 void mmu_put_word_unaligned(uaecptr addr, uae_u16 val, int data);
extern REGPARAM2 void mmu_put_long_unaligned(uaecptr addr, uae_u32 val, int data);
extern REGPARAM2 void mmu_put_byte_slow(uaecptr addr, uae_u8 val, int super, int data,
int size, struct mmu_atc_line *cl);
extern REGPARAM2 void mmu_put_word_slow(uaecptr addr, uae_u16 val, int super, int data,
int size, struct mmu_atc_line *cl);
extern REGPARAM2 void mmu_put_long_slow(uaecptr addr, uae_u32 val, int super, int data,
int size, struct mmu_atc_line *cl);
extern REGPARAM2 void mmu_put_quad_slow(uaecptr addr, uae_u64 val, int super, int data,
struct mmu_atc_line *cl);
extern void mmu_make_transparent_region(uaecptr baseaddr, uae_u32 size, int datamode);
static inline void mmu_set_ttr(int regno, uae_u32 val)
{
uae_u32 * ttr;
switch(regno) {
case TTR_I0: ttr = &regs.itt0; break;
case TTR_I1: ttr = &regs.itt1; break;
case TTR_D0: ttr = &regs.dtt0; break;
case TTR_D1: ttr = &regs.dtt1; break;
default: abort();
}
*ttr = val;
}
static inline void mmu_set_mmusr(uae_u32 val)
{
regs.mmusr = val;
}
#define FC_DATA (regs.s ? 5 : 1)
#define FC_INST (regs.s ? 6 : 2)
extern uaecptr REGPARAM2 mmu_translate(uaecptr addr, int super, int data, int write);
extern uae_u32 REGPARAM2 sfc_get_long(uaecptr addr);
extern uae_u16 REGPARAM2 sfc_get_word(uaecptr addr);
extern uae_u8 REGPARAM2 sfc_get_byte(uaecptr addr);
extern void REGPARAM2 dfc_put_long(uaecptr addr, uae_u32 val);
extern void REGPARAM2 dfc_put_word(uaecptr addr, uae_u16 val);
extern void REGPARAM2 dfc_put_byte(uaecptr addr, uae_u8 val);
extern void REGPARAM2 mmu_flush_atc(uaecptr addr, bool super, bool global);
extern void REGPARAM2 mmu_flush_atc_all(bool global);
extern void REGPARAM2 mmu_op(uae_u32 opcode, uae_u16 extra);
#ifdef FULLMMU
extern void REGPARAM2 mmu_reset(void);
extern void REGPARAM2 mmu_set_tc(uae_u16 tc);
extern void REGPARAM2 mmu_set_super(bool super);
#else
static inline void mmu_reset(void)
{
}
static inline void mmu_set_tc(uae_u16 /*tc*/)
{
}
static inline void mmu_set_super(bool /*super*/)
{
}
#endif
#endif /* CPUMMU_H */
/*
vim:ts=4:sw=4:
*/

View File

@ -0,0 +1,2 @@
#define NOFLAGS 1
#include "cpustbl.cpp"

View File

@ -0,0 +1,5 @@
/*
* cpustbl.cpp must be compiled twice, once for the generator program
* and once for the actual executable
*/
#include "cpustbl.cpp"

View File

@ -0,0 +1,82 @@
/*
* debug.cpp - CPU debugger
*
* Copyright (c) 2001-2010 Milan Jurik of ARAnyM dev team (see AUTHORS)
*
* Inspired by Bernd Schmidt's UAE
*
* This file is part of the ARAnyM project which builds a new and powerful
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
*
* ARAnyM is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* ARAnyM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ARAnyM; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
* UAE - The Un*x Amiga Emulator
*
* Debugger
*
* (c) 1995 Bernd Schmidt
*
*/
#include "sysdeps.h"
#include "memory.h"
#include "newcpu.h"
#include "debug.h"
#include "input.h"
#include "cpu_emulation.h"
#include "main.h"
static int debugger_active = 0;
int debugging = 0;
int irqindebug = 0;
int ignore_irq = 0;
void activate_debugger (void)
{
#ifdef DEBUGGER
ndebug::do_skip = false;
#endif
debugger_active = 1;
SPCFLAGS_SET( SPCFLAG_BRK );
debugging = 1;
/* use_debugger = 1; */
}
void deactivate_debugger(void)
{
debugging = 0;
debugger_active = 0;
}
void debug (void)
{
if (ignore_irq && regs.s && !regs.m ) {
SPCFLAGS_SET( SPCFLAG_BRK );
return;
}
#ifdef DEBUGGER
ndebug::run();
#endif
}
/*
vim:ts=4:sw=4:
*/

View File

@ -1,28 +1,33 @@
/*
* fpu/core.h - base fpu context definition
* fpu/core.h - base fpu context definition
*
* Basilisk II (C) 1997-2008 Christian Bauer
* Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
*
* Inspired by Christian Bauer's Basilisk II
*
* MC68881/68040 fpu emulation
*
* Original UAE FPU, copyright 1996 Herman ten Brugge
* Rewrite for x86, copyright 1999-2000 Lauri Pesonen
* New framework, copyright 2000 Gwenole Beauchesne
* Adapted for JIT compilation (c) Bernd Meyer, 2000
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This file is part of the ARAnyM project which builds a new and powerful
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* MC68881/68040 fpu emulation
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* Original UAE FPU, copyright 1996 Herman ten Brugge
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
* New framework, copyright 2000-2001 Gwenole Beauchesne
* Adapted for JIT compilation (c) Bernd Meyer, 2000-2001
*
* ARAnyM is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* ARAnyM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ARAnyM; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef FPU_CORE_H
@ -34,11 +39,15 @@
/* Always use x87 FPU stack on IA-32. */
#if defined(X86_ASSEMBLY)
#define USE_X87_ASSEMBLY 1
#ifndef USE_JIT_FPU
#define ACCURATE_SIN_COS_TAN 1
#endif
#endif
/* Only use x87 FPU on x86-64 if long double precision is requested. */
#if defined(X86_64_ASSEMBLY) && USE_LONG_DOUBLE
#if defined(X86_64_ASSEMBLY) && defined(USE_LONG_DOUBLE)
#define USE_X87_ASSEMBLY 1
#define ACCURATE_SIN_COS_TAN 1
#endif
/* ========================================================================== */
@ -65,10 +74,7 @@ struct fpu_t {
/* --- Floating-Point Control Register --- */
/* ---------------------------------------------------------------------- */
struct {
/* Exception Enable Byte */
uae_u32 exception_enable;
#define FPCR_EXCEPTION_ENABLE 0x0000ff00
#define FPCR_EXCEPTION_BSUN 0x00008000
#define FPCR_EXCEPTION_SNAN 0x00004000
@ -83,21 +89,19 @@ struct fpu_t {
#define FPCR_MODE_CONTROL 0x000000ff
/* Rounding precision */
uae_u32 rounding_precision;
#define FPCR_ROUNDING_PRECISION 0x000000c0
#define FPCR_PRECISION_SINGLE 0x00000040
#define FPCR_PRECISION_DOUBLE 0x00000080
#define FPCR_PRECISION_EXTENDED 0x00000000
/* Rounding mode */
uae_u32 rounding_mode;
#define FPCR_ROUNDING_MODE 0x00000030
#define FPCR_ROUND_NEAR 0x00000000
#define FPCR_ROUND_ZERO 0x00000010
#define FPCR_ROUND_MINF 0x00000020
#define FPCR_ROUND_PINF 0x00000030
} fpcr;
uae_u32 fpcr;
/* ---------------------------------------------------------------------- */
/* --- Floating-Point Status Register --- */
@ -107,7 +111,7 @@ struct fpu_t {
/* Floating-Point Condition Code Byte */
uae_u32 condition_codes;
#define FPSR_CCB 0xff000000
#define FPSR_CCB 0x0f000000
#define FPSR_CCB_NEGATIVE 0x08000000
#define FPSR_CCB_ZERO 0x04000000
#define FPSR_CCB_INFINITY 0x02000000
@ -133,7 +137,7 @@ struct fpu_t {
/* Accrued Exception Byte */
uae_u32 accrued_exception;
#define FPSR_ACCRUED_EXCEPTION 0x000000ff
#define FPSR_ACCRUED_EXCEPTION 0x000000f8
#define FPSR_ACCR_IOP 0x00000080
#define FPSR_ACCR_OVFL 0x00000040
#define FPSR_ACCR_UNFL 0x00000020
@ -219,7 +223,7 @@ struct fpu_t {
extern fpu_t fpu;
/* Return the address of a particular register */
inline fpu_register * const fpu_register_address(int i)
inline fpu_register * fpu_register_address(int i)
{ return &fpu.registers[i]; }
/* Dump functions for m68k_dumpstate */
@ -227,16 +231,16 @@ extern void fpu_dump_registers(void);
extern void fpu_dump_flags(void);
/* Accessors to FPU Control Register */
static inline uae_u32 get_fpcr(void);
static inline void set_fpcr(uae_u32 new_fpcr);
//static inline uae_u32 get_fpcr(void);
//static inline void set_fpcr(uae_u32 new_fpcr);
/* Accessors to FPU Status Register */
static inline uae_u32 get_fpsr(void);
static inline void set_fpsr(uae_u32 new_fpsr);
//static inline uae_u32 get_fpsr(void);
//static inline void set_fpsr(uae_u32 new_fpsr);
/* Accessors to FPU Instruction Address Register */
static inline uae_u32 get_fpiar();
static inline void set_fpiar(uae_u32 new_fpiar);
//static inline uae_u32 get_fpiar();
//static inline void set_fpiar(uae_u32 new_fpiar);
/* Initialization / Finalization */
extern void fpu_init(bool integral_68040);
@ -254,6 +258,6 @@ void fpuop_scc(uae_u32 opcode, uae_u32 extra) REGPARAM;
/* Floating-point system control operations */
void fpuop_save(uae_u32 opcode) REGPARAM;
void fpuop_restore(uae_u32 opcode) REGPARAM;
void fpuop_trapcc(uae_u32 opcode, uaecptr oldpc) REGPARAM;
void fpuop_trapcc(uae_u32 opcode, uaecptr oldpc, uae_u32 extra) REGPARAM;
#endif /* FPU_CORE_H */

View File

@ -1,28 +1,33 @@
/*
* fpu/exceptions.cpp - system-dependant FPU exceptions management
* fpu/exceptions.cpp - system-dependant FPU exceptions management
*
* Basilisk II (C) 1997-2008 Christian Bauer
* Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
*
* Inspired by Christian Bauer's Basilisk II
*
* MC68881/68040 fpu emulation
*
* Original UAE FPU, copyright 1996 Herman ten Brugge
* Rewrite for x86, copyright 1999-2000 Lauri Pesonen
* New framework, copyright 2000 Gwenole Beauchesne
* Adapted for JIT compilation (c) Bernd Meyer, 2000
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This file is part of the ARAnyM project which builds a new and powerful
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* MC68881/68040 fpu emulation
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* Original UAE FPU, copyright 1996 Herman ten Brugge
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
* New framework, copyright 2000-2001 Gwenole Beauchesne
* Adapted for JIT compilation (c) Bernd Meyer, 2000-2001
*
* ARAnyM is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* ARAnyM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ARAnyM; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#undef PRIVATE

View File

@ -1,28 +1,33 @@
/*
* fpu/exceptions.h - system-dependant FPU exceptions management
* fpu/exceptions.h - system-dependant FPU exceptions management
*
* Basilisk II (C) 1997-2008 Christian Bauer
* Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
*
* Inspired by Christian Bauer's Basilisk II
*
* MC68881/68040 fpu emulation
*
* Original UAE FPU, copyright 1996 Herman ten Brugge
* Rewrite for x86, copyright 1999-2000 Lauri Pesonen
* New framework, copyright 2000 Gwenole Beauchesne
* Adapted for JIT compilation (c) Bernd Meyer, 2000
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This file is part of the ARAnyM project which builds a new and powerful
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* MC68881/68040 fpu emulation
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* Original UAE FPU, copyright 1996 Herman ten Brugge
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
* New framework, copyright 2000-2001 Gwenole Beauchesne
* Adapted for JIT compilation (c) Bernd Meyer, 2000-2001
*
* ARAnyM is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* ARAnyM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ARAnyM; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef FPU_EXCEPTIONS_H

View File

@ -1,28 +1,33 @@
/*
* fpu/flags.cpp - Floating-point flags
* fpu/flags.cpp - Floating-point flags
*
* Basilisk II (C) 1997-2008 Christian Bauer
* Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
*
* Inspired by Christian Bauer's Basilisk II
*
* MC68881/68040 fpu emulation
*
* Original UAE FPU, copyright 1996 Herman ten Brugge
* Rewrite for x86, copyright 1999-2000 Lauri Pesonen
* New framework, copyright 2000 Gwenole Beauchesne
* Adapted for JIT compilation (c) Bernd Meyer, 2000
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This file is part of the ARAnyM project which builds a new and powerful
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* MC68881/68040 fpu emulation
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* Original UAE FPU, copyright 1996 Herman ten Brugge
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
* New framework, copyright 2000-2001 Gwenole Beauchesne
* Adapted for JIT compilation (c) Bernd Meyer, 2000-2001
*
* ARAnyM is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* ARAnyM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ARAnyM; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* NOTE: this file shall be included only from fpu/fpu_*.cpp */

View File

@ -1,28 +1,33 @@
/*
* fpu/flags.h - Floating-point flags
* fpu/flags.h - Floating-point flags
*
* Basilisk II (C) 1997-2008 Christian Bauer
* Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
*
* Inspired by Christian Bauer's Basilisk II
*
* MC68881/68040 fpu emulation
*
* Original UAE FPU, copyright 1996 Herman ten Brugge
* Rewrite for x86, copyright 1999-2000 Lauri Pesonen
* New framework, copyright 2000 Gwenole Beauchesne
* Adapted for JIT compilation (c) Bernd Meyer, 2000
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This file is part of the ARAnyM project which builds a new and powerful
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* MC68881/68040 fpu emulation
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* Original UAE FPU, copyright 1996 Herman ten Brugge
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
* New framework, copyright 2000-2001 Gwenole Beauchesne
* Adapted for JIT compilation (c) Bernd Meyer, 2000-2001
*
* ARAnyM is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* ARAnyM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ARAnyM; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef FPU_FLAGS_H
@ -112,7 +117,7 @@ PRIVATE inline void FFPU set_fpccr(uae_u32 new_fpcond)
/* Make FPSR according to the value passed in argument */
PRIVATE inline void FFPU make_fpsr(fpu_register const & r)
{ uae_u16 sw; __asm__ __volatile__ ("fxam\n\tfnstsw %0" : "=r" (sw) : "f" (r)); FPU fpsr.condition_codes = sw; }
{ uae_u16 sw; __asm__ __volatile__ ("fxam\n\tfnstsw %0" : "=a" (sw) : "f" (r)); FPU fpsr.condition_codes = sw; }
/* Return the corresponding ID of the current floating-point condition codes */
/* NOTE: only valid for evaluation of a condition */
@ -181,27 +186,27 @@ PRIVATE inline uae_u32 FFPU get_fpccr(void)
uae_u32 fpccr = 0;
if (isnan(FPU result))
fpccr |= FPSR_CCB_NAN;
else if (FPU result == 0.0)
fpccr |= FPSR_CCB_ZERO;
else if (FPU result < 0.0)
fpccr |= FPSR_CCB_NEGATIVE;
if (isinf(FPU result))
else if (isinf(FPU result))
fpccr |= FPSR_CCB_INFINITY;
else if (iszero(FPU result))
fpccr |= FPSR_CCB_ZERO;
if (isneg(FPU result))
fpccr |= FPSR_CCB_NEGATIVE;
return fpccr;
}
/* M68k to native floating-point condition codes - SELF */
PRIVATE inline void FFPU set_fpccr(uae_u32 new_fpcond)
{
bool negative = (new_fpcond & FPSR_CCB_NEGATIVE) != 0;
if (new_fpcond & FPSR_CCB_NAN)
make_nan(FPU result);
make_nan(FPU result, negative);
else if (new_fpcond & FPSR_CCB_INFINITY)
make_inf(FPU result, negative);
else if (new_fpcond & FPSR_CCB_ZERO)
FPU result = 0.0;
else if (new_fpcond & FPSR_CCB_NEGATIVE)
FPU result = -1.0;
make_zero(FPU result, negative);
else
FPU result = +1.0;
/* gb-- where is Infinity ? */
FPU result = negative ? -1.0 : +1.0;
}
/* Make FPSR according to the value passed in argument */
@ -217,7 +222,7 @@ PRIVATE inline void FFPU make_fpsr(fpu_register const & r)
/* -------------------------------------------------------------------------- */
/* Return the address of the floating-point condition codes register */
static inline uae_u32 * const FFPU address_of_fpccr(void)
static inline uae_u32 * FFPU address_of_fpccr(void)
{ return ((uae_u32 *)& FPU fpsr.condition_codes); }
#endif /* FPU_FLAGS_H */

View File

@ -1,28 +1,33 @@
/*
* fpu/fpu.h - public header
* fpu/fpu.h - public header
*
* Basilisk II (C) 1997-2008 Christian Bauer
* Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
*
* Inspired by Christian Bauer's Basilisk II
*
* MC68881/68040 fpu emulation
*
* Original UAE FPU, copyright 1996 Herman ten Brugge
* Rewrite for x86, copyright 1999-2000 Lauri Pesonen
* New framework, copyright 2000 Gwenole Beauchesne
* Adapted for JIT compilation (c) Bernd Meyer, 2000
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This file is part of the ARAnyM project which builds a new and powerful
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* MC68881/68040 fpu emulation
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* Original UAE FPU, copyright 1996 Herman ten Brugge
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
* New framework, copyright 2000-2001 Gwenole Beauchesne
* Adapted for JIT compilation (c) Bernd Meyer, 2000-2001
*
* ARAnyM is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* ARAnyM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ARAnyM; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef FPU_PUBLIC_HEADER_H
@ -46,4 +51,9 @@
#include "fpu/types.h"
#include "fpu/core.h"
void fpu_set_fpsr(uae_u32 new_fpsr);
uae_u32 fpu_get_fpsr(void);
void fpu_set_fpcr(uae_u32 new_fpcr);
uae_u32 fpu_get_fpcr(void);
#endif /* FPU_PUBLIC_HEADER_H */

File diff suppressed because it is too large Load Diff

View File

@ -1,28 +1,33 @@
/*
* fpu/fpu_uae.h - Extra Definitions for the old UAE FPU core
* fpu/fpu_ieee.h - Extra Definitions for the IEEE FPU core
*
* Basilisk II (C) 1997-2008 Christian Bauer
* Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
*
* Inspired by Christian Bauer's Basilisk II
*
* MC68881/68040 fpu emulation
*
* Original UAE FPU, copyright 1996 Herman ten Brugge
* Rewrite for x86, copyright 1999-2000 Lauri Pesonen
* New framework, copyright 2000 Gwenole Beauchesne
* Adapted for JIT compilation (c) Bernd Meyer, 2000
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This file is part of the ARAnyM project which builds a new and powerful
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* MC68881/68040 fpu emulation
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* Original UAE FPU, copyright 1996 Herman ten Brugge
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
* New framework, copyright 2000-2001 Gwenole Beauchesne
* Adapted for JIT compilation (c) Bernd Meyer, 2000-2001
*
* ARAnyM is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* ARAnyM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ARAnyM; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef FPU_IEEE_H
@ -54,13 +59,11 @@ PRIVATE double_flags fl_dest;
PRIVATE inline void FFPU get_dest_flags(fpu_register const & r);
PRIVATE inline void FFPU get_source_flags(fpu_register const & r);
PRIVATE inline void FFPU make_nan(fpu_register & r);
PRIVATE inline void FFPU make_zero_positive(fpu_register & r);
PRIVATE inline void FFPU make_zero_negative(fpu_register & r);
PRIVATE inline void FFPU make_inf_positive(fpu_register & r);
PRIVATE inline void FFPU make_inf_negative(fpu_register & r);
PRIVATE inline void FFPU make_nan(fpu_register & r, bool negative);
PRIVATE inline void FFPU make_zero(fpu_register & r, bool negative);
PRIVATE inline void FFPU make_inf(fpu_register & r, bool negative);
PRIVATE inline void FFPU fast_scale(fpu_register & r, int add);
// MJ PRIVATE inline void FFPU fast_scale(fpu_register & r, int add);
PRIVATE inline fpu_register FFPU fast_fgetexp(fpu_register const & r);
// May be optimized for particular processors

File diff suppressed because it is too large Load Diff

View File

@ -1,31 +1,42 @@
/*
* fpu/fpu_uae.cpp
* fpu/fpu_uae.cpp - the old UAE FPU
*
* Basilisk II (C) 1997-2008 Christian Bauer
* Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
*
* Inspired by Christian Bauer's Basilisk II
*
* MC68881/68040 fpu emulation
* This file is part of the ARAnyM project which builds a new and powerful
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
*
* Original UAE FPU, copyright 1996 Herman ten Brugge
* Rewrite for x86, copyright 1999-2000 Lauri Pesonen
* New framework, copyright 2000 Gwenole Beauchesne
* Adapted for JIT compilation (c) Bernd Meyer, 2000
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* MC68881/68040 fpu emulation
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* Original UAE FPU, copyright 1996 Herman ten Brugge
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
* New framework, copyright 2000-2001 Gwenole Beauchesne
* Adapted for JIT compilation (c) Bernd Meyer, 2000-2001
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* ARAnyM is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* ARAnyM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ARAnyM; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
* UAE - The Un*x Amiga Emulator
*
* MC68881 emulation
*
* Copyright 1996 Herman ten Brugge
*
*
* Following fixes by Lauri Pesonen, July 1999:
*
* FMOVEM list handling:
@ -86,9 +97,8 @@
* - Precision rounding single/double
*/
#include "sysdeps.h"
#include <math.h>
#include <stdio.h>
#include "memory.h"
#include "readcpu.h"
#include "newcpu.h"
@ -97,6 +107,17 @@
#include "fpu/fpu.h"
#include "fpu/fpu_uae.h"
#ifdef HAVE_NEW_HEADERS
#define _GLIBCPP_USE_C99 1
# include <cmath>
# include <cstdio>
using namespace __gnu_cxx;
#undef _GLIBCPP_USE_C99
#else
# include <math.h>
# include <stdio.h>
#endif
/* Global FPU context */
fpu_t fpu;
@ -166,8 +187,8 @@ PUBLIC void FFPU dump_registers(const char * str)
sprintf(temp_str, "%s: %.04f, %.04f, %.04f, %.04f, %.04f, %.04f, %.04f, %.04f\n",
str,
get_register(0), get_register(1), get_register(2), get_register(3),
get_register(4), get_register(5), get_register(6), get_register(7) );
fpu_get_register(0), fpu_get_register(1), fpu_get_register(2), fpu_get_register(3),
fpu_get_register(4), fpu_get_register(5), fpu_get_register(6), fpu_get_register(7) );
fpu_debug((temp_str));
}
@ -195,9 +216,7 @@ PUBLIC void FFPU dump_registers(const char *)
{
}
PUBLIC void FFPU dump_first_bytes(uae_u8 *, uae_s32)
{
}
#define dump_first_bytes(a,b)
#endif
@ -219,10 +238,10 @@ PRIVATE inline fpu_register FFPU round_to_nearest(fpu_register const & x)
PRIVATE inline bool FFPU do_isnan(fpu_register const & r)
{
uae_u32 * p = (uae_u32 *)&r;
if ((p[FHI] & 0x7FF00000) == 0x7FF00000) {
fpu_register_parts const p = { r };
if ((p.parts[FHI] & 0x7FF00000) == 0x7FF00000) {
// logical or is faster here.
if ((p[FHI] & 0x000FFFFF) || p[FLO]) {
if ((p.parts[FHI] & 0x000FFFFF) || p.parts[FLO]) {
return true;
}
}
@ -235,8 +254,8 @@ PRIVATE inline bool FFPU do_isnan(fpu_register const & r)
PRIVATE inline bool FFPU do_isinf(fpu_register const & r)
{
uae_u32 * p = (uae_u32 *)&r;
if (((p[FHI] & 0x7FF00000) == 0x7FF00000) && p[FLO] == 0) {
fpu_register_parts const p = { r };
if ((p.parts[FHI] & 0x7FF00000) == 0x7FF00000 && p.parts[FLO] == 0) {
return true;
}
return false;
@ -248,8 +267,8 @@ PRIVATE inline bool FFPU do_isinf(fpu_register const & r)
PRIVATE inline bool FFPU do_isneg(fpu_register const & r)
{
uae_u32 * p = (uae_u32 *)&r;
return ((p[FHI] & 0x80000000) != 0);
fpu_register_parts const p = { r };
return ((p.parts[FHI] & 0x80000000) != 0);
}
#ifndef HAVE_ISZERO
@ -258,8 +277,8 @@ PRIVATE inline bool FFPU do_isneg(fpu_register const & r)
PRIVATE inline bool FFPU do_iszero(fpu_register const & r)
{
uae_u32 * p = (uae_u32 *)&r;
return (((p[FHI] & 0x7FF00000) == 0) && p[FLO] == 0);
fpu_register_parts const p = { r };
return (((p.parts[FHI] & 0x7FF00000) == 0) && p.parts[FLO] == 0);
}
// May be optimized for particular processors
@ -293,77 +312,70 @@ PRIVATE inline void FFPU get_source_flags(fpu_register const & r)
fl_source.in_range = !fl_source.zero && !fl_source.infinity && !fl_source.nan;
}
PRIVATE inline void FFPU make_nan(fpu_register & r)
PRIVATE inline void FFPU make_nan(fpu_register & r, bool negative)
{
uae_u32 * const p = (uae_u32 *)&r;
p[FLO] = 0xffffffff;
p[FHI] = 0x7fffffff;
fpu_register_parts p;
p.parts[FLO] = 0xffffffff;
p.parts[FHI] = negative ? 0xffffffff : 0x7fffffff;
r = p.val;
}
PRIVATE inline void FFPU make_zero_positive(fpu_register & r)
PRIVATE inline void FFPU make_zero(fpu_register & r, bool negative)
{
uae_u32 * const p = (uae_u32 *)&r;
p[FLO] = p[FHI] = 0;
fpu_register_parts p;
p.parts[FLO] = 0;
p.parts[FHI] = negative ? 0x80000000 : 0;
r = p.val;
}
PRIVATE inline void FFPU make_zero_negative(fpu_register & r)
PRIVATE inline void FFPU make_inf(fpu_register & r, bool negative)
{
uae_u32 * const p = (uae_u32 *)&r;
p[FLO] = 0;
p[FHI] = 0x80000000;
}
PRIVATE inline void FFPU make_inf_positive(fpu_register & r)
{
uae_u32 * const p = (uae_u32 *)&r;
p[FLO] = 0;
p[FHI] = 0x7FF00000;
}
PRIVATE inline void FFPU make_inf_negative(fpu_register & r)
{
uae_u32 * const p = (uae_u32 *)&r;
p[FLO] = 0;
p[FHI] = 0xFFF00000;
fpu_register_parts p;
p.parts[FLO] = 0;
p.parts[FHI] = negative ? 0xFFF00000 : 0x7FF00000;
r = p.val;
}
PRIVATE inline void FFPU fast_scale(fpu_register & r, int add)
{
uae_u32 * const p = (uae_u32 *)&r;
int exp = (p[FHI] & 0x7FF00000) >> 20;
fpu_register_parts p = { r };
int exp = (p.parts[FHI] & 0x7FF00000) >> 20;
// TODO: overflow flags
exp += add;
if(exp >= 2047) {
make_inf_positive(r);
make_inf(r, false);
return;
} else if(exp < 0) {
// keep sign (+/- 0)
p[FHI] &= 0x80000000;
p.parts[FHI] &= 0x80000000;
} else {
p[FHI] = (p[FHI] & 0x800FFFFF) | ((uae_u32)exp << 20);
p.parts[FHI] = (p.parts[FHI] & 0x800FFFFF) | ((uae_u32)exp << 20);
}
r = p.val;
}
PRIVATE inline fpu_register FFPU fast_fgetexp(fpu_register const & r)
{
uae_u32 * const p = (uae_u32 *)&r;
int exp = (p[FHI] & 0x7FF00000) >> 20;
fpu_register_parts const p = { r };
int exp = (p.parts[FHI] & 0x7FF00000) >> 20;
return( exp - 1023 );
}
// Normalize to range 1..2
PRIVATE inline void FFPU fast_remove_exponent(fpu_register & r)
{
uae_u32 * const p = (uae_u32 *)&r;
p[FHI] = (p[FHI] & 0x800FFFFF) | 0x3FF00000;
fpu_register_parts p = { r };
p.parts[FHI] = (p.parts[FHI] & 0x800FFFFF) | 0x3FF00000;
r = p.val;
}
// The sign of the quotient is the exclusive-OR of the sign bits
// of the source and destination operands.
PRIVATE inline uae_u32 FFPU get_quotient_sign(fpu_register const & ra, fpu_register const & rb)
{
uae_u32 * const a = (uae_u32 *)&ra;
uae_u32 * const b = (uae_u32 *)&rb;
return (((a[FHI] ^ b[FHI]) & 0x80000000) ? FPSR_QUOTIENT_SIGN : 0);
fpu_register_parts const a = { ra };
fpu_register_parts const b = { rb };
return (((a.parts[FHI] ^ b.parts[FHI]) & 0x80000000) ? FPSR_QUOTIENT_SIGN : 0);
}
// Quotient Byte is loaded with the sign and least significant
@ -381,13 +393,15 @@ PRIVATE inline fpu_register FFPU make_single(uae_u32 value)
return (0.0);
fpu_register result;
uae_u32 * p = (uae_u32 *)&result;
fpu_register_parts p;
uae_u32 sign = (value & 0x80000000);
uae_u32 exp = ((value & 0x7F800000) >> 23) + 1023 - 127;
p[FLO] = value << 29;
p[FHI] = sign | (exp << 20) | ((value & 0x007FFFFF) >> 3);
p.parts[FLO] = value << 29;
p.parts[FHI] = sign | (exp << 20) | ((value & 0x007FFFFF) >> 3);
result = p.val;
fpu_debug(("make_single (%X) = %.04f\n",value,(double)result));
@ -401,10 +415,10 @@ PRIVATE inline uae_u32 FFPU extract_single(fpu_register const & src)
return 0;
uae_u32 result;
uae_u32 *p = (uae_u32 *)&src;
fpu_register_parts const p = { src };
uae_u32 sign = (p[FHI] & 0x80000000);
uae_u32 exp = (p[FHI] & 0x7FF00000) >> 20;
uae_u32 sign = (p.parts[FHI] & 0x80000000);
uae_u32 exp = (p.parts[FHI] & 0x7FF00000) >> 20;
if(exp + 127 < 1023) {
exp = 0;
@ -414,7 +428,7 @@ PRIVATE inline uae_u32 FFPU extract_single(fpu_register const & src)
exp = exp + 127 - 1023;
}
result = sign | (exp << 23) | ((p[FHI] & 0x000FFFFF) << 3) | (p[FLO] >> 29);
result = sign | (exp << 23) | ((p.parts[FHI] & 0x000FFFFF) << 3) | (p.parts[FLO] >> 29);
fpu_debug(("extract_single (%.04f) = %X\n",(double)src,result));
@ -428,8 +442,8 @@ PRIVATE inline fpu_register FFPU make_extended(uae_u32 wrd1, uae_u32 wrd2, uae_u
return 0.0;
fpu_register result;
uae_u32 *p = (uae_u32 *)&result;
fpu_register_parts p;
uae_u32 sign = wrd1 & 0x80000000;
uae_u32 exp = (wrd1 >> 16) & 0x7fff;
@ -466,8 +480,10 @@ PRIVATE inline fpu_register FFPU make_extended(uae_u32 wrd1, uae_u32 wrd2, uae_u
}
// drop the explicit integer bit.
p[FLO] = (wrd2 << 21) | (wrd3 >> 11);
p[FHI] = sign | (exp << 20) | ((wrd2 & 0x7FFFFFFF) >> 11);
p.parts[FLO] = (wrd2 << 21) | (wrd3 >> 11);
p.parts[FHI] = sign | (exp << 20) | ((wrd2 & 0x7FFFFFFF) >> 11);
result = p.val;
fpu_debug(("make_extended (%X,%X,%X) = %.04f\n",wrd1,wrd2,wrd3,(double)result));
@ -485,14 +501,14 @@ PRIVATE inline void FFPU make_extended_no_normalize(
{
// Is it zero?
if ((wrd1 & 0x7fff0000) == 0 && wrd2 == 0 && wrd3 == 0) {
make_zero_positive(result);
make_zero(result, false);
return;
}
// Is it NaN?
if( (wrd1 & 0x7FFF0000) == 0x7FFF0000 ) {
if( (wrd1 & 0x0000FFFF) || wrd2 || wrd3 ) {
make_nan(result);
make_nan(result, (wrd1 & 0x80000000) != 0);
return;
}
}
@ -511,11 +527,13 @@ PRIVATE inline void FFPU make_extended_no_normalize(
}
// drop the explicit integer bit.
uae_u32 *p = (uae_u32 *)&result;
p[FLO] = (wrd2 << 21) | (wrd3 >> 11);
p[FHI] = sign | (exp << 20) | ((wrd2 & 0x7FFFFFFF) >> 11);
fpu_register_parts p;
p.parts[FLO] = (wrd2 << 21) | (wrd3 >> 11);
p.parts[FHI] = sign | (exp << 20) | ((wrd2 & 0x7FFFFFFF) >> 11);
fpu_debug(("make_extended (%X,%X,%X) = %.04f\n",wrd1,wrd2,wrd3,(float)(*(double *)p)));
result = p.val;
fpu_debug(("make_extended (%X,%X,%X) = %.04f\n",wrd1,wrd2,wrd3,(double)result));
}
// from_exten
@ -527,14 +545,14 @@ PRIVATE inline void FFPU extract_extended(fpu_register const & src,
*wrd1 = *wrd2 = *wrd3 = 0;
return;
}
uae_u32 *p = (uae_u32 *)&src;
fpu_debug(("extract_extended (%X,%X)\n",p[FLO],p[FHI]));
uae_u32 sign = p[FHI] & 0x80000000;
fpu_register_parts const p = { src };
fpu_debug(("extract_extended (%X,%X)\n",p.parts[FLO],p.parts[FHI]));
uae_u32 exp = ((p[FHI] >> 20) & 0x7ff);
uae_u32 sign = p.parts[FHI] & 0x80000000;
uae_u32 exp = ((p.parts[FHI] >> 20) & 0x7ff);
// Check for maximum
if(exp == 0x7FF) {
exp = 0x7FFF;
@ -544,8 +562,8 @@ PRIVATE inline void FFPU extract_extended(fpu_register const & src,
*wrd1 = sign | (exp << 16);
// always set the explicit integer bit.
*wrd2 = 0x80000000 | ((p[FHI] & 0x000FFFFF) << 11) | ((p[FLO] & 0xFFE00000) >> 21);
*wrd3 = p[FLO] << 11;
*wrd2 = 0x80000000 | ((p.parts[FHI] & 0x000FFFFF) << 11) | ((p.parts[FLO] & 0xFFE00000) >> 21);
*wrd3 = p.parts[FLO] << 11;
fpu_debug(("extract_extended (%.04f) = %X,%X,%X\n",(double)src,*wrd1,*wrd2,*wrd3));
}
@ -557,9 +575,11 @@ PRIVATE inline fpu_register FFPU make_double(uae_u32 wrd1, uae_u32 wrd2)
return 0.0;
fpu_register result;
uae_u32 *p = (uae_u32 *)&result;
p[FLO] = wrd2;
p[FHI] = wrd1;
fpu_register_parts p;
p.parts[FLO] = wrd2;
p.parts[FHI] = wrd1;
result = p.val;
fpu_debug(("make_double (%X,%X) = %.04f\n",wrd1,wrd2,(double)result));
@ -577,9 +597,9 @@ PRIVATE inline void FFPU extract_double(fpu_register const & src,
return;
}
*/
uae_u32 *p = (uae_u32 *)&src;
*wrd2 = p[FLO];
*wrd1 = p[FHI];
fpu_register_parts const p = { src };
*wrd2 = p.parts[FLO];
*wrd1 = p.parts[FHI];
fpu_debug(("extract_double (%.04f) = %X,%X\n",(double)src,*wrd1,*wrd2));
}
@ -590,8 +610,8 @@ PRIVATE inline void FFPU extract_double(fpu_register const & src,
PRIVATE inline void FFPU make_fpsr(fpu_register const & r)
{
FPU fpsr.condition_codes
= ((r == 0.0) ? NATIVE_FFLAG_ZERO : 0)
| ((r < 0.0) ? NATIVE_FFLAG_NEGATIVE : 0)
= (iszero(r) ? NATIVE_FFLAG_ZERO : 0)
| (isneg(r) ? NATIVE_FFLAG_NEGATIVE : 0)
;
}
#endif
@ -622,25 +642,25 @@ PRIVATE inline uae_u32 FFPU extract_single(fpu_register const & src)
fpu_register src0 = src;
#endif
if (src == 0.0)
if (src == 0.0)
return 0;
if (src < 0) {
if (src < 0) {
tmp = 0x80000000;
src = -src;
} else {
} else {
tmp = 0;
}
frac = frexp (src, &expon);
frac += 0.5 / 16777216.0;
if (frac >= 1.0) {
}
frac = frexp (src, &expon);
frac += 0.5 / 16777216.0;
if (frac >= 1.0) {
frac /= 2.0;
expon++;
}
}
result = tmp | (((expon + 127 - 1) & 0xff) << 23) | (((int) (frac * 16777216.0)) & 0x7fffff);
// fpu_debug(("extract_single (%.04f) = %X\n",(float)src0,result));
return (result);
return (result);
}
// to exten
@ -895,11 +915,9 @@ PRIVATE inline int FFPU get_fp_value (uae_u32 opcode, uae_u16 extra, fpu_registe
break;
case 3:
ad = m68k_areg (regs, reg);
m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size];
break;
case 4:
m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size];
ad = m68k_areg (regs, reg);
ad = m68k_areg (regs, reg) - (reg == 7 ? sz2[size] : sz1[size]);
break;
case 5:
ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword();
@ -940,8 +958,8 @@ PRIVATE inline int FFPU get_fp_value (uae_u32 opcode, uae_u16 extra, fpu_registe
fpu_debug(("get_fp_value m68k_getpc()=%X\n",m68k_getpc()));
fpu_debug(("get_fp_value ad=%X\n",ad));
fpu_debug(("get_fp_value get_long (ad)=%X\n",get_long (ad)));
dump_first_bytes( get_real_address(ad)-64, 64 );
dump_first_bytes( get_real_address(ad), 64 );
dump_first_bytes( get_real_address(ad, 0, 0)-64, 64 );
dump_first_bytes( get_real_address(ad, 0, 0), 64 );
switch (size) {
case 0:
@ -988,6 +1006,15 @@ PRIVATE inline int FFPU get_fp_value (uae_u32 opcode, uae_u16 extra, fpu_registe
return 0;
}
switch (mode) {
case 3:
m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size];
break;
case 4:
m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size];
break;
}
// fpu_debug(("get_fp_value result = %.04f\n",(float)src));
return 1;
}
@ -1204,7 +1231,7 @@ PRIVATE inline int FFPU fpp_cond(int condition)
#if 0
return fpcctrue(condition);
#else
switch (condition) {
switch (condition & 0x1f) {
case 0x00: CONDRET("False",0);
case 0x01: CONDRET("Equal",Z);
case 0x02: CONDRET("Ordered Greater Than",!(NaN || Z || N));
@ -1299,11 +1326,11 @@ void FFPU fpuop_scc(uae_u32 opcode, uae_u32 extra)
put_byte(ad, cc ? 0xff : 0x00);
}
void FFPU fpuop_trapcc(uae_u32 opcode, uaecptr oldpc)
void FFPU fpuop_trapcc(uae_u32 opcode, uaecptr oldpc, uae_u32 extra)
{
fpu_debug(("ftrapcc_opp %X at %08lx\n", (uae_u32)opcode, m68k_getpc ()));
fpu_debug(("ftrapcc_opp %X, %X at %08lx\n", (uae_u32)opcode, (uae_u32)extra, m68k_getpc ()));
int cc = fpp_cond(opcode & 0x3f);
int cc = fpp_cond(extra & 0x3f);
if (cc == -1) {
m68k_setpc (oldpc);
op_illg (opcode);
@ -1516,8 +1543,7 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra)
if ((opcode & 0x38) == 0) {
if (extra & 0x2000) { // dr bit
if (extra & 0x1000) {
// according to the manual, the msb bits are always zero.
m68k_dreg (regs, opcode & 7) = get_fpcr() & 0xFFFF;
m68k_dreg (regs, opcode & 7) = get_fpcr();
fpu_debug(("FMOVEM FPU fpcr (%X) -> D%d\n", get_fpcr(), opcode & 7));
}
if (extra & 0x0800) {
@ -1548,8 +1574,7 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra)
else if ((opcode & 0x38) == 8) {
if (extra & 0x2000) { // dr bit
if (extra & 0x1000) {
// according to the manual, the msb bits are always zero.
m68k_areg (regs, opcode & 7) = get_fpcr() & 0xFFFF;
m68k_areg (regs, opcode & 7) = get_fpcr();
fpu_debug(("FMOVEM FPU fpcr (%X) -> A%d\n", get_fpcr(), opcode & 7));
}
if (extra & 0x0800) {
@ -1612,8 +1637,7 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra)
}
ad -= incr;
if (extra & 0x1000) {
// according to the manual, the msb bits are always zero.
put_long (ad, get_fpcr() & 0xFFFF);
put_long (ad, get_fpcr());
fpu_debug(("FMOVEM FPU fpcr (%X) -> mem %X\n", get_fpcr(), ad ));
ad += 4;
}
@ -1906,6 +1930,8 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra)
FPU registers[reg] = 1.0e256;
fpu_debug(("FP const: 1.0e256\n"));
break;
// Valid for 64 bits only (see fpu.cpp)
#if 0
case 0x3c:
FPU registers[reg] = 1.0e512;
@ -1942,7 +1968,114 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra)
return;
}
fpu_debug(("returned from get_fp_value m68k_getpc()=%X\n",m68k_getpc()));
#if 0 // MJ added, not tested now
if (FPU is_integral) {
// 68040-specific operations
switch (extra & 0x7f) {
case 0x40: /* FSMOVE */
fpu_debug(("FSMOVE %.04f\n",(double)src));
FPU registers[reg] = (float)src;
make_fpsr(FPU registers[reg]);
break;
case 0x44: /* FDMOVE */
fpu_debug(("FDMOVE %.04f\n",(double)src));
FPU registers[reg] = (double)src;
make_fpsr(FPU registers[reg]);
break;
case 0x41: /* FSSQRT */
fpu_debug(("FSQRT %.04f\n",(double)src));
FPU registers[reg] = (float)sqrt (src);
make_fpsr(FPU registers[reg]);
break;
case 0x45: /* FDSQRT */
fpu_debug(("FSQRT %.04f\n",(double)src));
FPU registers[reg] = (double)sqrt (src);
make_fpsr(FPU registers[reg]);
break;
case 0x58: /* FSABS */
fpu_debug(("FSABS %.04f\n",(double)src));
FPU registers[reg] = (float)fabs(src);
make_fpsr(FPU registers[reg]);
break;
case 0x5c: /* FDABS */
fpu_debug(("FDABS %.04f\n",(double)src));
FPU registers[reg] = (double)fabs(src);
make_fpsr(FPU registers[reg]);
break;
case 0x5a: /* FSNEG */
fpu_debug(("FSNEG %.04f\n",(double)src));
FPU registers[reg] = (float)-src;
make_fpsr(FPU registers[reg]);
break;
case 0x5e: /* FDNEG */
fpu_debug(("FDNEG %.04f\n",(double)src));
FPU registers[reg] = (double)-src;
make_fpsr(FPU registers[reg]);
break;
case 0x60: /* FSDIV */
fpu_debug(("FSDIV %.04f\n",(double)src));
FPU registers[reg] = (float)(FPU registers[reg] / src);
make_fpsr(FPU registers[reg]);
break;
case 0x64: /* FDDIV */
fpu_debug(("FDDIV %.04f\n",(double)src));
FPU registers[reg] = (double)(FPU registers[reg] / src);
make_fpsr(FPU registers[reg]);
break;
case 0x62: /* FSADD */
fpu_debug(("FSADD %.04f\n",(double)src));
FPU registers[reg] = (float)(FPU registers[reg] + src);
make_fpsr(FPU registers[reg]);
break;
case 0x66: /* FDADD */
fpu_debug(("FDADD %.04f\n",(double)src));
FPU registers[reg] = (double)(FPU registers[reg] + src);
make_fpsr(FPU registers[reg]);
break;
case 0x68: /* FSSUB */
fpu_debug(("FSSUB %.04f\n",(double)src));
FPU registers[reg] = (float)(FPU registers[reg] - src);
make_fpsr(FPU registers[reg]);
break;
case 0x6c: /* FDSUB */
fpu_debug(("FDSUB %.04f\n",(double)src));
FPU registers[reg] = (double)(FPU registers[reg] - src);
make_fpsr(FPU registers[reg]);
break;
case 0x63: /* FSMUL */
case 0x67: /* FDMUL */
get_dest_flags(FPU registers[reg]);
get_source_flags(src);
if(fl_dest.in_range && fl_source.in_range) {
if ((extra & 0x7f) == 0x63)
FPU registers[reg] = (float)(FPU registers[reg] * src);
else
FPU registers[reg] = (double)(FPU registers[reg] * src);
}
else if (fl_dest.nan || fl_source.nan ||
fl_dest.zero && fl_source.infinity ||
fl_dest.infinity && fl_source.zero ) {
make_nan( FPU registers[reg], fl_dest.negative );
}
else if (fl_dest.zero || fl_source.zero ) {
make_zero(FPU registers[reg], fl_dest.negative != fl_source.negative);
}
else {
make_inf(FPU registers[reg], fl_dest.negative != fl_source.negative);
}
make_fpsr(FPU registers[reg]);
break;
default:
// Continue decode-execute 6888x instructions below
goto process_6888x_instructions;
}
fpu_debug(("END m68k_getpc()=%X\n",m68k_getpc()));
dump_registers( "END ");
return;
}
process_6888x_instructions:
#endif
switch (extra & 0x7f) {
case 0x00: /* FMOVE */
fpu_debug(("FMOVE %.04f\n",(double)src));
@ -1954,7 +2087,7 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra)
fpu_debug(("FINT %.04f\n",(double)src));
// FPU registers[reg] = (int) (src + 0.5);
// FIXME: use native rounding mode flags
switch (get_fpcr() & 0x30) {
switch (get_fpcr() & FPCR_ROUNDING_MODE) {
case FPCR_ROUND_ZERO:
FPU registers[reg] = round_to_zero(src);
break;
@ -2075,7 +2208,10 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra)
break;
case 0x1a: /* FNEG */
fpu_debug(("FNEG %.04f\n",(double)src));
FPU registers[reg] = -src;
if (iszero(src))
make_zero(FPU registers[reg], !isneg(src));
else
FPU registers[reg] = -src;
make_fpsr(FPU registers[reg]);
break;
case 0x1c: /* FACOS */
@ -2092,7 +2228,7 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra)
fpu_debug(("FGETEXP %.04f\n",(double)src));
#if FPU_HAVE_IEEE_DOUBLE
if( isinf(src) ) {
make_nan( FPU registers[reg] );
make_nan( FPU registers[reg], isneg(src) );
}
else {
FPU registers[reg] = fast_fgetexp( src );
@ -2116,7 +2252,7 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra)
FPU registers[reg] = 0;
}
else if( isinf(src) ) {
make_nan( FPU registers[reg] );
make_nan( FPU registers[reg], isneg(src) );
}
else {
FPU registers[reg] = src;
@ -2166,27 +2302,15 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra)
FPU registers[reg] *= src;
}
else if (fl_dest.nan || fl_source.nan ||
fl_dest.zero && fl_source.infinity ||
fl_dest.infinity && fl_source.zero ) {
make_nan( FPU registers[reg] );
(fl_dest.zero && fl_source.infinity) ||
(fl_dest.infinity && fl_source.zero) ) {
make_nan( FPU registers[reg], fl_dest.negative );
}
else if (fl_dest.zero || fl_source.zero ) {
if (fl_dest.negative && !fl_source.negative ||
!fl_dest.negative && fl_source.negative) {
make_zero_negative(FPU registers[reg]);
}
else {
make_zero_positive(FPU registers[reg]);
}
make_zero(FPU registers[reg], fl_dest.negative != fl_source.negative);
}
else {
if( fl_dest.negative && !fl_source.negative ||
!fl_dest.negative && fl_source.negative) {
make_inf_negative(FPU registers[reg]);
}
else {
make_inf_positive(FPU registers[reg]);
}
make_inf(FPU registers[reg], fl_dest.negative != fl_source.negative);
}
#else
fpu_debug(("FMUL %.04f\n",(double)src));
@ -2223,8 +2347,8 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra)
// Overflow, underflow
#if FPU_HAVE_IEEE_DOUBLE
if( isinf(FPU registers[reg]) ) {
make_nan( FPU registers[reg] );
if( isinf(src) ) {
make_nan( FPU registers[reg], isneg(src) );
}
else {
// When the absolute value of the source operand is >= 2^14,
@ -2336,6 +2460,27 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra)
dump_registers( "END ");
}
void fpu_set_fpsr(uae_u32 new_fpsr)
{
set_fpsr(new_fpsr);
}
uae_u32 fpu_get_fpsr(void)
{
return get_fpsr();
}
void fpu_set_fpcr(uae_u32 new_fpcr)
{
set_fpcr(new_fpcr);
}
uae_u32 fpu_get_fpcr(void)
{
return get_fpcr();
}
/* -------------------------- Initialization -------------------------- */
void FFPU fpu_init (bool integral_68040)

View File

@ -1,28 +1,33 @@
/*
* fpu/fpu_uae.h - Extra Definitions for the old UAE FPU core
* fpu/fpu_uae.h - Extra Definitions for the old UAE FPU core
*
* Basilisk II (C) 1997-2008 Christian Bauer
* Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
*
* Inspired by Christian Bauer's Basilisk II
*
* MC68881/68040 fpu emulation
*
* Original UAE FPU, copyright 1996 Herman ten Brugge
* Rewrite for x86, copyright 1999-2000 Lauri Pesonen
* New framework, copyright 2000 Gwenole Beauchesne
* Adapted for JIT compilation (c) Bernd Meyer, 2000
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This file is part of the ARAnyM project which builds a new and powerful
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* MC68881/68040 fpu emulation
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* Original UAE FPU, copyright 1996 Herman ten Brugge
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
* New framework, copyright 2000-2001 Gwenole Beauchesne
* Adapted for JIT compilation (c) Bernd Meyer, 2000-2001
*
* ARAnyM is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* ARAnyM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ARAnyM; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef FPU_UAE_H
@ -78,11 +83,9 @@ PRIVATE inline bool FFPU do_isinf(fpu_register const & r);
PRIVATE inline bool FFPU do_isneg(fpu_register const & r);
PRIVATE inline bool FFPU do_iszero(fpu_register const & r);
PRIVATE inline void FFPU make_nan(fpu_register & r);
PRIVATE inline void FFPU make_zero_positive(fpu_register & r);
PRIVATE inline void FFPU make_zero_negative(fpu_register & r);
PRIVATE inline void FFPU make_inf_positive(fpu_register & r);
PRIVATE inline void FFPU make_inf_negative(fpu_register & r);
PRIVATE inline void FFPU make_nan(fpu_register & r, bool negative);
PRIVATE inline void FFPU make_zero(fpu_register & r, bool negative);
PRIVATE inline void FFPU make_inf(fpu_register & r, bool negative);
PRIVATE inline void FFPU fast_scale(fpu_register & r, int add);
PRIVATE inline fpu_register FFPU fast_fgetexp(fpu_register const & r);

View File

@ -1,27 +1,33 @@
/*
* fpu_x86.cpp - 68881/68040 fpu code for x86/Windows an Linux/x86.
* fpu/fpu_x86.cpp - 68881/68040 fpu code for x86/Windows an Linux/x86.
*
* Basilisk II (C) 1997-2008 Christian Bauer
* Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
*
* Inspired by Christian Bauer's Basilisk II
*
* MC68881/68040 fpu emulation
* This file is part of the ARAnyM project which builds a new and powerful
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
*
* Based on UAE FPU, original copyright 1996 Herman ten Brugge,
* rewritten for x86 by Lauri Pesonen 1999-2000,
* accomodated to GCC's Extended Asm syntax by Gwenole Beauchesne 2000.
* MC68881/68040 fpu emulation
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* Original UAE FPU, copyright 1996 Herman ten Brugge
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
* New framework, copyright 2000-2001 Gwenole Beauchesne
* Adapted for JIT compilation (c) Bernd Meyer, 2000-2001
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* ARAnyM is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* ARAnyM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ARAnyM; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*
* Interface
@ -134,10 +140,8 @@
*
*/
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
# include <cmath>
# include <cstdio>
#include "sysdeps.h"
#include "memory.h"
@ -238,8 +242,6 @@ PUBLIC void FFPU fpu_dump_flags(void)
#include "debug.h"
#if FPU_DEBUG
#undef __inline__
#define __inline__
PRIVATE void FFPU dump_first_bytes_buf(char *b, uae_u8* buf, uae_s32 actual)
{
@ -390,7 +392,7 @@ PRIVATE void FFPU FPU_CONSISTENCY_CHECK_STOP(const char *)
/* ---------------------------- Status functions ---------------------------- */
PRIVATE void __inline__ FFPU SET_BSUN_ON_NAN ()
PRIVATE void inline FFPU SET_BSUN_ON_NAN ()
{
if( (x86_status_word & (SW_Z_I_NAN_MASK)) == SW_NAN ) {
x86_status_word |= SW_FAKE_BSUN;
@ -398,7 +400,7 @@ PRIVATE void __inline__ FFPU SET_BSUN_ON_NAN ()
}
}
PRIVATE void __inline__ FFPU build_ex_status ()
PRIVATE void inline FFPU build_ex_status ()
{
if(x86_status_word & SW_EXCEPTION_MASK) {
// _asm FNCLEX
@ -415,20 +417,20 @@ When the FPU creates a NAN, the NAN always contains the same bit pattern
in the mantissa. All bits of the mantissa are ones for any precision.
When the user creates a NAN, any nonzero bit pattern can be stored in the mantissa.
*/
PRIVATE __inline__ void FFPU MAKE_NAN (fpu_register & f)
PRIVATE inline void FFPU MAKE_NAN (fpu_register & f, bool negative)
{
// Make it non-signaling.
uae_u8 * p = (uae_u8 *) &f;
memset( p, 0xFF, sizeof(fpu_register) - 1 );
p[9] = 0x7F;
p[9] = negative ? 0xff : 0x7F;
}
/*
For single- and double-precision infinities the fraction is a zero.
For extended-precision infinities, the mantissas MSB, the explicit
For extended-precision infinities, the mantissa<EFBFBD>s MSB, the explicit
integer bit, can be either one or zero.
*/
PRIVATE __inline__ uae_u32 FFPU IS_INFINITY (fpu_register const & f)
PRIVATE inline uae_u32 FFPU IS_INFINITY (fpu_register const & f)
{
uae_u8 * p = (uae_u8 *) &f;
if( ((p[9] & 0x7F) == 0x7F) && p[8] == 0xFF ) {
@ -439,7 +441,7 @@ PRIVATE __inline__ uae_u32 FFPU IS_INFINITY (fpu_register const & f)
return(0);
}
PRIVATE __inline__ uae_u32 FFPU IS_NAN (fpu_register const & f)
PRIVATE inline uae_u32 FFPU IS_NAN (fpu_register const & f)
{
uae_u8 * p = (uae_u8 *) &f;
if( ((p[9] & 0x7F) == 0x7F) && p[8] == 0xFF ) {
@ -450,7 +452,7 @@ PRIVATE __inline__ uae_u32 FFPU IS_NAN (fpu_register const & f)
return(0);
}
PRIVATE __inline__ uae_u32 FFPU IS_ZERO (fpu_register const & f)
PRIVATE inline uae_u32 FFPU IS_ZERO (fpu_register const & f)
{
uae_u8 * p = (uae_u8 *) &f;
return *((uae_u32 *)p) == 0 &&
@ -458,34 +460,34 @@ PRIVATE __inline__ uae_u32 FFPU IS_ZERO (fpu_register const & f)
( *((uae_u16 *)&p[8]) & 0x7FFF ) == 0;
}
PRIVATE __inline__ void FFPU MAKE_INF_POSITIVE (fpu_register & f)
PRIVATE inline void FFPU MAKE_INF_POSITIVE (fpu_register & f)
{
uae_u8 * p = (uae_u8 *) &f;
memset( p, 0, sizeof(fpu_register)-2 );
*((uae_u16 *)&p[8]) = 0x7FFF;
}
PRIVATE __inline__ void FFPU MAKE_INF_NEGATIVE (fpu_register & f)
PRIVATE inline void FFPU MAKE_INF_NEGATIVE (fpu_register & f)
{
uae_u8 * p = (uae_u8 *) &f;
memset( p, 0, sizeof(fpu_register)-2 );
*((uae_u16 *)&p[8]) = 0xFFFF;
}
PRIVATE __inline__ void FFPU MAKE_ZERO_POSITIVE (fpu_register & f)
PRIVATE inline void FFPU MAKE_ZERO_POSITIVE (fpu_register & f)
{
uae_u32 * const p = (uae_u32 *) &f;
memset( p, 0, sizeof(fpu_register) );
}
PRIVATE __inline__ void FFPU MAKE_ZERO_NEGATIVE (fpu_register & f)
PRIVATE inline void FFPU MAKE_ZERO_NEGATIVE (fpu_register & f)
{
uae_u32 * const p = (uae_u32 *) &f;
memset( p, 0, sizeof(fpu_register) );
*((uae_u32 *)&p[4]) = 0x80000000;
}
PRIVATE __inline__ uae_u32 FFPU IS_NEGATIVE (fpu_register const & f)
PRIVATE inline uae_u32 FFPU IS_NEGATIVE (fpu_register const & f)
{
uae_u8 * p = (uae_u8 *) &f;
return( (p[9] & 0x80) != 0 );
@ -900,6 +902,34 @@ PRIVATE void FFPU do_fmove ( fpu_register & dest, fpu_register const & src )
FPU_CONSISTENCY_CHECK_STOP("do_fmove");
}
PRIVATE void FFPU do_fsmove ( fpu_register & dest, fpu_register const & src )
{
FPU_CONSISTENCY_CHECK_START();
__asm__ __volatile__(
"fldt %2\n"
"fxam \n"
"fnstsw %0\n"
"fstpt %1\n"
: "=m" (x86_status_word), "=m" (dest)
: "m" (src)
);
FPU_CONSISTENCY_CHECK_STOP("do_fsmove");
}
PRIVATE void FFPU do_fdmove ( fpu_register & dest, fpu_register const & src )
{
FPU_CONSISTENCY_CHECK_START();
__asm__ __volatile__(
"fldt %2\n"
"fxam \n"
"fnstsw %0\n"
"fstpt %1\n"
: "=m" (x86_status_word), "=m" (dest)
: "m" (src)
);
FPU_CONSISTENCY_CHECK_STOP("do_fdmove");
}
/*
PRIVATE void FFPU do_fmove_no_status ( fpu_register & dest, fpu_register const & src )
{
@ -1023,6 +1053,50 @@ PRIVATE void FFPU do_fsqrt ( fpu_register & dest, fpu_register const & src )
FPU_CONSISTENCY_CHECK_STOP("do_fsqrt");
}
PRIVATE void FFPU do_fssqrt ( fpu_register & dest, fpu_register const & src )
{
FPU_CONSISTENCY_CHECK_START();
__asm__ __volatile__(
"fldt %2\n"
"fsqrt \n"
"fxam \n"
"fnstsw %0\n"
"fstpt %1\n"
: "=m" (x86_status_word), "=m" (dest)
: "m" (src)
);
if(x86_status_word & SW_EXCEPTION_MASK) {
// _asm FNCLEX
__asm__ __volatile__("fnclex");
x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_PE);
x86_status_word_accrued |= x86_status_word;
}
FPU_CONSISTENCY_CHECK_STOP("do_fssqrt");
}
PRIVATE void FFPU do_fdsqrt ( fpu_register & dest, fpu_register const & src )
{
FPU_CONSISTENCY_CHECK_START();
__asm__ __volatile__(
"fldt %2\n"
"fsqrt \n"
"fxam \n"
"fnstsw %0\n"
"fstpt %1\n"
: "=m" (x86_status_word), "=m" (dest)
: "m" (src)
);
if(x86_status_word & SW_EXCEPTION_MASK) {
// _asm FNCLEX
__asm__ __volatile__("fnclex");
x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_PE);
x86_status_word_accrued |= x86_status_word;
}
FPU_CONSISTENCY_CHECK_STOP("do_fdsqrt");
}
PRIVATE void FFPU do_ftst ( fpu_register const & src )
{
FPU_CONSISTENCY_CHECK_START();
@ -1311,6 +1385,48 @@ PRIVATE void FFPU do_fabs ( fpu_register & dest, fpu_register const & src )
FPU_CONSISTENCY_CHECK_STOP("do_fabs");
}
PRIVATE void FFPU do_fsabs ( fpu_register & dest, fpu_register const & src )
{
FPU_CONSISTENCY_CHECK_START();
__asm__ __volatile__(
"fldt %2\n"
"fabs \n"
"fxam \n"
"fnstsw %0\n"
"fstpt %1\n"
: "=m" (x86_status_word), "=m" (dest)
: "m" (src)
);
// x86 fabs should not rise any exceptions (except stack underflow)
if(x86_status_word & SW_EXCEPTION_MASK) {
// _asm FNCLEX
__asm__ __volatile__("fnclex");
x86_status_word &= ~SW_EXCEPTION_MASK;
}
FPU_CONSISTENCY_CHECK_STOP("do_fsabs");
}
PRIVATE void FFPU do_fdabs ( fpu_register & dest, fpu_register const & src )
{
FPU_CONSISTENCY_CHECK_START();
__asm__ __volatile__(
"fldt %2\n"
"fabs \n"
"fxam \n"
"fnstsw %0\n"
"fstpt %1\n"
: "=m" (x86_status_word), "=m" (dest)
: "m" (src)
);
// x86 fabs should not rise any exceptions (except stack underflow)
if(x86_status_word & SW_EXCEPTION_MASK) {
// _asm FNCLEX
__asm__ __volatile__("fnclex");
x86_status_word &= ~SW_EXCEPTION_MASK;
}
FPU_CONSISTENCY_CHECK_STOP("do_fdabs");
}
PRIVATE void FFPU do_fneg ( fpu_register & dest, fpu_register const & src )
{
FPU_CONSISTENCY_CHECK_START();
@ -1341,6 +1457,48 @@ PRIVATE void FFPU do_fneg ( fpu_register & dest, fpu_register const & src )
FPU_CONSISTENCY_CHECK_STOP("do_fneg");
}
PRIVATE void FFPU do_fsneg ( fpu_register & dest, fpu_register const & src )
{
FPU_CONSISTENCY_CHECK_START();
__asm__ __volatile__(
"fldt %2\n"
"fchs \n"
"fxam \n"
"fnstsw %0\n"
"fstpt %1\n"
: "=m" (x86_status_word), "=m" (dest)
: "m" (src)
);
// x86 fchs should not rise any exceptions (except stack underflow)
if(x86_status_word & SW_EXCEPTION_MASK) {
// _asm FNCLEX
__asm__ __volatile__("fnclex");
x86_status_word &= ~SW_EXCEPTION_MASK;
}
FPU_CONSISTENCY_CHECK_STOP("do_fsneg");
}
PRIVATE void FFPU do_fdneg ( fpu_register & dest, fpu_register const & src )
{
FPU_CONSISTENCY_CHECK_START();
__asm__ __volatile__(
"fldt %2\n"
"fchs \n"
"fxam \n"
"fnstsw %0\n"
"fstpt %1\n"
: "=m" (x86_status_word), "=m" (dest)
: "m" (src)
);
// x86 fchs should not rise any exceptions (except stack underflow)
if(x86_status_word & SW_EXCEPTION_MASK) {
// _asm FNCLEX
__asm__ __volatile__("fnclex");
x86_status_word &= ~SW_EXCEPTION_MASK;
}
FPU_CONSISTENCY_CHECK_STOP("do_fdneg");
}
PRIVATE void FFPU do_fcos ( fpu_register & dest, fpu_register const & src )
{
FPU_CONSISTENCY_CHECK_START();
@ -1466,6 +1624,50 @@ PRIVATE void FFPU do_fdiv ( fpu_register & dest, fpu_register const & src )
FPU_CONSISTENCY_CHECK_STOP("do_fdiv");
}
PRIVATE void FFPU do_fsdiv ( fpu_register & dest, fpu_register const & src )
{
FPU_CONSISTENCY_CHECK_START();
__asm__ __volatile__(
"fldt %2\n"
"fldt %1\n"
"fdiv %%st(1), %%st(0)\n"
"fxam \n"
"fnstsw %0\n"
"fstpt %1\n"
"fstp %%st(0)\n"
: "=m" (x86_status_word), "+m" (dest)
: "m" (src)
);
if(x86_status_word & SW_EXCEPTION_MASK) {
// _asm FNCLEX
__asm__ __volatile__("fnclex");
x86_status_word_accrued |= x86_status_word;
}
FPU_CONSISTENCY_CHECK_STOP("do_fsdiv");
}
PRIVATE void FFPU do_fddiv ( fpu_register & dest, fpu_register const & src )
{
FPU_CONSISTENCY_CHECK_START();
__asm__ __volatile__(
"fldt %2\n"
"fldt %1\n"
"fdiv %%st(1), %%st(0)\n"
"fxam \n"
"fnstsw %0\n"
"fstpt %1\n"
"fstp %%st(0)\n"
: "=m" (x86_status_word), "+m" (dest)
: "m" (src)
);
if(x86_status_word & SW_EXCEPTION_MASK) {
// _asm FNCLEX
__asm__ __volatile__("fnclex");
x86_status_word_accrued |= x86_status_word;
}
FPU_CONSISTENCY_CHECK_STOP("do_fddiv");
}
// The sign of the quotient is the exclusive-OR of the sign bits
// of the source and destination operands.
// Quotient Byte is loaded with the sign and least significant
@ -1851,6 +2053,48 @@ PRIVATE void FFPU do_fadd ( fpu_register & dest, fpu_register const & src )
FPU_CONSISTENCY_CHECK_STOP("do_fadd");
}
PRIVATE void FFPU do_fsadd ( fpu_register & dest, fpu_register const & src )
{
FPU_CONSISTENCY_CHECK_START();
__asm__ __volatile__(
"fldt %2\n"
"fldt %1\n"
"fadd \n"
"fxam \n"
"fnstsw %0\n"
"fstpt %1\n"
: "=m" (x86_status_word), "+m" (dest)
: "m" (src)
);
if(x86_status_word & SW_EXCEPTION_MASK) {
// _asm FNCLEX
x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_UE - SW_OE - SW_PE);
x86_status_word_accrued |= x86_status_word;
}
FPU_CONSISTENCY_CHECK_STOP("do_fsadd");
}
PRIVATE void FFPU do_fdadd ( fpu_register & dest, fpu_register const & src )
{
FPU_CONSISTENCY_CHECK_START();
__asm__ __volatile__(
"fldt %2\n"
"fldt %1\n"
"fadd \n"
"fxam \n"
"fnstsw %0\n"
"fstpt %1\n"
: "=m" (x86_status_word), "+m" (dest)
: "m" (src)
);
if(x86_status_word & SW_EXCEPTION_MASK) {
// _asm FNCLEX
x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_UE - SW_OE - SW_PE);
x86_status_word_accrued |= x86_status_word;
}
FPU_CONSISTENCY_CHECK_STOP("do_fdadd");
}
PRIVATE void FFPU do_fmul ( fpu_register & dest, fpu_register const & src )
{
FPU_CONSISTENCY_CHECK_START();
@ -1882,6 +2126,48 @@ PRIVATE void FFPU do_fmul ( fpu_register & dest, fpu_register const & src )
FPU_CONSISTENCY_CHECK_STOP("do_fmul");
}
PRIVATE void FFPU do_fsmul ( fpu_register & dest, fpu_register const & src )
{
FPU_CONSISTENCY_CHECK_START();
__asm__ __volatile__(
"fldt %2\n"
"fldt %1\n"
"fmul \n"
"fxam \n"
"fnstsw %0\n"
"fstpt %1\n"
: "=m" (x86_status_word), "+m" (dest)
: "m" (src)
);
if(x86_status_word & SW_EXCEPTION_MASK) {
// _asm FNCLEX
__asm__ __volatile__("fnclex");
x86_status_word_accrued |= x86_status_word;
}
FPU_CONSISTENCY_CHECK_STOP("do_fsmul");
}
PRIVATE void FFPU do_fdmul ( fpu_register & dest, fpu_register const & src )
{
FPU_CONSISTENCY_CHECK_START();
__asm__ __volatile__(
"fldt %2\n"
"fldt %1\n"
"fmul \n"
"fxam \n"
"fnstsw %0\n"
"fstpt %1\n"
: "=m" (x86_status_word), "+m" (dest)
: "m" (src)
);
if(x86_status_word & SW_EXCEPTION_MASK) {
// _asm FNCLEX
__asm__ __volatile__("fnclex");
x86_status_word_accrued |= x86_status_word;
}
FPU_CONSISTENCY_CHECK_STOP("do_fdmul");
}
PRIVATE void FFPU do_fsgldiv ( fpu_register & dest, fpu_register const & src )
{
FPU_CONSISTENCY_CHECK_START();
@ -2040,6 +2326,52 @@ PRIVATE void FFPU do_fsub ( fpu_register & dest, fpu_register const & src )
FPU_CONSISTENCY_CHECK_STOP("do_fsub");
}
PRIVATE void FFPU do_fssub ( fpu_register & dest, fpu_register const & src )
{
FPU_CONSISTENCY_CHECK_START();
__asm__ __volatile__(
"fldt %2\n"
"fldt %1\n"
"fsub %%st(1), %%st(0)\n"
"fxam \n"
"fnstsw %0\n"
"fstpt %1\n"
"fstp %%st(0)\n"
: "=m" (x86_status_word), "+m" (dest)
: "m" (src)
);
if(x86_status_word & SW_EXCEPTION_MASK) {
// _asm FNCLEX
__asm__ __volatile__("fnclex");
x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_UE - SW_OE - SW_PE);
x86_status_word_accrued |= x86_status_word;
}
FPU_CONSISTENCY_CHECK_STOP("do_fssub");
}
PRIVATE void FFPU do_fdsub ( fpu_register & dest, fpu_register const & src )
{
FPU_CONSISTENCY_CHECK_START();
__asm__ __volatile__(
"fldt %2\n"
"fldt %1\n"
"fsub %%st(1), %%st(0)\n"
"fxam \n"
"fnstsw %0\n"
"fstpt %1\n"
"fstp %%st(0)\n"
: "=m" (x86_status_word), "+m" (dest)
: "m" (src)
);
if(x86_status_word & SW_EXCEPTION_MASK) {
// _asm FNCLEX
__asm__ __volatile__("fnclex");
x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_UE - SW_OE - SW_PE);
x86_status_word_accrued |= x86_status_word;
}
FPU_CONSISTENCY_CHECK_STOP("do_fdsub");
}
PRIVATE void FFPU do_fsincos ( fpu_register & dest_sin, fpu_register & dest_cos, fpu_register const & src )
{
FPU_CONSISTENCY_CHECK_START();
@ -2284,11 +2616,9 @@ PRIVATE int FFPU get_fp_value (uae_u32 opcode, uae_u32 extra, fpu_register & src
break;
case 3:
ad = m68k_areg (regs, reg);
m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size];
break;
case 4:
m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size];
ad = m68k_areg (regs, reg);
ad = m68k_areg (regs, reg) - (reg == 7 ? sz2[size] : sz1[size]);
break;
case 5:
ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword();
@ -2387,6 +2717,15 @@ PRIVATE int FFPU get_fp_value (uae_u32 opcode, uae_u32 extra, fpu_register & src
return 0;
}
switch (mode) {
case 3:
m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size];
break;
case 4:
m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size];
break;
}
// D(bug("get_fp_value result = %.04f\r\n",(float)src));
return 1;
@ -2612,7 +2951,7 @@ PRIVATE int FFPU fpp_cond(uae_u32 opcode, int condition)
#define I ((x86_status_word & (SW_Z_I_NAN_MASK)) == (SW_I))
#define NotANumber ((x86_status_word & (SW_Z_I_NAN_MASK)) == SW_NAN)
switch (condition) {
switch (condition & 0x1f) {
// Common Tests, no BSUN
case 0x01:
CONDRET("Equal",Z);
@ -2757,11 +3096,11 @@ PUBLIC void REGPARAM2 FFPU fpuop_scc(uae_u32 opcode, uae_u32 extra)
}
}
PUBLIC void REGPARAM2 FFPU fpuop_trapcc(uae_u32 opcode, uaecptr oldpc)
PUBLIC void REGPARAM2 FFPU fpuop_trapcc(uae_u32 opcode, uaecptr oldpc, uae_u32 extra)
{
int cc;
D(bug("ftrapcc_opp %X at %08lx\r\n", (uae_u32)opcode, m68k_getpc ()));
D(bug("ftrapcc_opp %X, %X at %08lx\r\n", (uae_u32)opcode, (uae_u32)extra, m68k_getpc ()));
#if I3_ON_FTRAPCC
#error "FIXME: _asm int 3"
@ -2769,7 +3108,7 @@ PUBLIC void REGPARAM2 FFPU fpuop_trapcc(uae_u32 opcode, uaecptr oldpc)
#endif
// This must be broken.
cc = fpp_cond(opcode, opcode & 0x3f);
cc = fpp_cond(opcode, extra & 0x3f);
if (cc < 0) {
m68k_setpc (oldpc);
@ -2856,7 +3195,7 @@ PRIVATE void FFPU do_null_frestore ()
{
// A null-restore operation sets FP7-FP0 positive, nonsignaling NANs.
for( int i=0; i<8; i++ ) {
MAKE_NAN( FPU registers[i] );
MAKE_NAN( FPU registers[i], false );
}
FPU instruction_address = 0;
@ -4646,6 +4985,249 @@ PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e4096( uae_u32 opcode, uae_u32
}
/* -------------------------- 040 ALU -------------------------- */
PRIVATE void REGPARAM2 FFPU fpuop_do_fsmove( uae_u32 opcode, uae_u32 extra )
{
int reg = (extra >> 7) & 7;
fpu_register src;
if (get_fp_value (opcode, extra, src) == 0) {
m68k_setpc (m68k_getpc () - 4);
op_illg (opcode);
dump_registers( "END ");
return;
}
D(bug("FSMOVE %s\r\n",etos(src)));
do_fsmove( FPU registers[reg], src );
build_ex_status();
dump_registers( "END ");
}
PRIVATE void REGPARAM2 FFPU fpuop_do_fdmove( uae_u32 opcode, uae_u32 extra )
{
int reg = (extra >> 7) & 7;
fpu_register src;
if (get_fp_value (opcode, extra, src) == 0) {
m68k_setpc (m68k_getpc () - 4);
op_illg (opcode);
dump_registers( "END ");
return;
}
D(bug("FDMOVE %s\r\n",etos(src)));
do_fdmove( FPU registers[reg], src );
build_ex_status();
dump_registers( "END ");
}
PRIVATE void REGPARAM2 FFPU fpuop_do_fssqrt( uae_u32 opcode, uae_u32 extra )
{
int reg = (extra >> 7) & 7;
fpu_register src;
if (get_fp_value (opcode, extra, src) == 0) {
m68k_setpc (m68k_getpc () - 4);
op_illg (opcode);
dump_registers( "END ");
return;
}
D(bug("FSSQRT %s\r\n",etos(src)));
do_fssqrt( FPU registers[reg], src );
dump_registers( "END ");
}
PRIVATE void REGPARAM2 FFPU fpuop_do_fdsqrt( uae_u32 opcode, uae_u32 extra )
{
int reg = (extra >> 7) & 7;
fpu_register src;
if (get_fp_value (opcode, extra, src) == 0) {
m68k_setpc (m68k_getpc () - 4);
op_illg (opcode);
dump_registers( "END ");
return;
}
D(bug("FDSQRT %s\r\n",etos(src)));
do_fdsqrt( FPU registers[reg], src );
dump_registers( "END ");
}
PRIVATE void REGPARAM2 FFPU fpuop_do_fsabs( uae_u32 opcode, uae_u32 extra )
{
int reg = (extra >> 7) & 7;
fpu_register src;
if (get_fp_value (opcode, extra, src) == 0) {
m68k_setpc (m68k_getpc () - 4);
op_illg (opcode);
dump_registers( "END ");
return;
}
D(bug("FSABS %s\r\n",etos(src)));
do_fsabs( FPU registers[reg], src );
dump_registers( "END ");
}
PRIVATE void REGPARAM2 FFPU fpuop_do_fdabs( uae_u32 opcode, uae_u32 extra )
{
int reg = (extra >> 7) & 7;
fpu_register src;
if (get_fp_value (opcode, extra, src) == 0) {
m68k_setpc (m68k_getpc () - 4);
op_illg (opcode);
dump_registers( "END ");
return;
}
D(bug("FDABS %s\r\n",etos(src)));
do_fdabs( FPU registers[reg], src );
dump_registers( "END ");
}
PRIVATE void REGPARAM2 FFPU fpuop_do_fsneg( uae_u32 opcode, uae_u32 extra )
{
int reg = (extra >> 7) & 7;
fpu_register src;
if (get_fp_value (opcode, extra, src) == 0) {
m68k_setpc (m68k_getpc () - 4);
op_illg (opcode);
dump_registers( "END ");
return;
}
D(bug("FSNEG %s\r\n",etos(src)));
do_fsneg( FPU registers[reg], src );
dump_registers( "END ");
}
PRIVATE void REGPARAM2 FFPU fpuop_do_fdneg( uae_u32 opcode, uae_u32 extra )
{
int reg = (extra >> 7) & 7;
fpu_register src;
if (get_fp_value (opcode, extra, src) == 0) {
m68k_setpc (m68k_getpc () - 4);
op_illg (opcode);
dump_registers( "END ");
return;
}
D(bug("FDNEG %s\r\n",etos(src)));
do_fdneg( FPU registers[reg], src );
dump_registers( "END ");
}
PRIVATE void REGPARAM2 FFPU fpuop_do_fsdiv( uae_u32 opcode, uae_u32 extra )
{
int reg = (extra >> 7) & 7;
fpu_register src;
if (get_fp_value (opcode, extra, src) == 0) {
m68k_setpc (m68k_getpc () - 4);
op_illg (opcode);
dump_registers( "END ");
return;
}
D(bug("FSDIV %s\r\n",etos(src)));
do_fsdiv( FPU registers[reg], src );
dump_registers( "END ");
}
PRIVATE void REGPARAM2 FFPU fpuop_do_fddiv( uae_u32 opcode, uae_u32 extra )
{
int reg = (extra >> 7) & 7;
fpu_register src;
if (get_fp_value (opcode, extra, src) == 0) {
m68k_setpc (m68k_getpc () - 4);
op_illg (opcode);
dump_registers( "END ");
return;
}
D(bug("FDDIV %s\r\n",etos(src)));
do_fddiv( FPU registers[reg], src );
dump_registers( "END ");
}
PRIVATE void REGPARAM2 FFPU fpuop_do_fsadd( uae_u32 opcode, uae_u32 extra )
{
int reg = (extra >> 7) & 7;
fpu_register src;
if (get_fp_value (opcode, extra, src) == 0) {
m68k_setpc (m68k_getpc () - 4);
op_illg (opcode);
dump_registers( "END ");
return;
}
D(bug("FSADD %s\r\n",etos(src)));
do_fsadd( FPU registers[reg], src );
dump_registers( "END ");
}
PRIVATE void REGPARAM2 FFPU fpuop_do_fdadd( uae_u32 opcode, uae_u32 extra )
{
int reg = (extra >> 7) & 7;
fpu_register src;
if (get_fp_value (opcode, extra, src) == 0) {
m68k_setpc (m68k_getpc () - 4);
op_illg (opcode);
dump_registers( "END ");
return;
}
D(bug("FDADD %s\r\n",etos(src)));
do_fdadd( FPU registers[reg], src );
dump_registers( "END ");
}
PRIVATE void REGPARAM2 FFPU fpuop_do_fssub( uae_u32 opcode, uae_u32 extra )
{
int reg = (extra >> 7) & 7;
fpu_register src;
if (get_fp_value (opcode, extra, src) == 0) {
m68k_setpc (m68k_getpc () - 4);
op_illg (opcode);
dump_registers( "END ");
return;
}
D(bug("FSSUB %s\r\n",etos(src)));
do_fssub( FPU registers[reg], src );
dump_registers( "END ");
}
PRIVATE void REGPARAM2 FFPU fpuop_do_fdsub( uae_u32 opcode, uae_u32 extra )
{
int reg = (extra >> 7) & 7;
fpu_register src;
if (get_fp_value (opcode, extra, src) == 0) {
m68k_setpc (m68k_getpc () - 4);
op_illg (opcode);
dump_registers( "END ");
return;
}
D(bug("FDSUB %s\r\n",etos(src)));
do_fdsub( FPU registers[reg], src );
dump_registers( "END ");
}
PRIVATE void REGPARAM2 FFPU fpuop_do_fsmul( uae_u32 opcode, uae_u32 extra )
{
int reg = (extra >> 7) & 7;
fpu_register src;
if (get_fp_value (opcode, extra, src) == 0) {
m68k_setpc (m68k_getpc () - 4);
op_illg (opcode);
dump_registers( "END ");
return;
}
D(bug("FSMUL %s\r\n",etos(src)));
do_fsmul( FPU registers[reg], src );
dump_registers( "END ");
}
PRIVATE void REGPARAM2 FFPU fpuop_do_fdmul( uae_u32 opcode, uae_u32 extra )
{
int reg = (extra >> 7) & 7;
fpu_register src;
if (get_fp_value (opcode, extra, src) == 0) {
m68k_setpc (m68k_getpc () - 4);
op_illg (opcode);
dump_registers( "END ");
return;
}
D(bug("FSMUL %s\r\n",etos(src)));
do_fsmul( FPU registers[reg], src );
dump_registers( "END ");
}
/* ---------------------------- ALU ---------------------------- */
PRIVATE void REGPARAM2 FFPU fpuop_do_fmove( uae_u32 opcode, uae_u32 extra )
@ -5037,7 +5619,7 @@ PRIVATE void REGPARAM2 FFPU fpuop_do_fgetexp( uae_u32 opcode, uae_u32 extra )
D(bug("FGETEXP %s\r\n",etos(src)));
if( IS_INFINITY(src) ) {
MAKE_NAN( FPU registers[reg] );
MAKE_NAN( FPU registers[reg], IS_NEGATIVE(src) );
do_ftst( FPU registers[reg] );
x86_status_word |= SW_IE;
} else {
@ -5058,7 +5640,7 @@ PRIVATE void REGPARAM2 FFPU fpuop_do_fgetman( uae_u32 opcode, uae_u32 extra )
}
D(bug("FGETMAN %s\r\n",etos(src)));
if( IS_INFINITY(src) ) {
MAKE_NAN( FPU registers[reg] );
MAKE_NAN( FPU registers[reg], IS_NEGATIVE(src) );
do_ftst( FPU registers[reg] );
x86_status_word |= SW_IE;
} else {
@ -5186,7 +5768,7 @@ PRIVATE void REGPARAM2 FFPU fpuop_do_fscale( uae_u32 opcode, uae_u32 extra )
}
D(bug("FSCALE %s, opcode=%X, extra=%X, ta %X\r\n",etos(src),opcode,extra,m68k_getpc()));
if( IS_INFINITY(FPU registers[reg]) ) {
MAKE_NAN( FPU registers[reg] );
MAKE_NAN( FPU registers[reg], IS_NEGATIVE(FPU registers[reg]) );
do_ftst( FPU registers[reg] );
x86_status_word |= SW_IE;
} else {
@ -5744,6 +6326,61 @@ PRIVATE void FFPU build_fpp_opp_lookup_table ()
}
break;
}
if (FPU is_integral) {
switch (extra & 0x7f) {
case 0x40:
fpufunctbl[mask] = & FFPU fpuop_do_fsmove;
break;
case 0x44:
fpufunctbl[mask] = & FFPU fpuop_do_fdmove;
break;
case 0x41:
fpufunctbl[mask] = & FFPU fpuop_do_fssqrt;
break;
case 0x45:
fpufunctbl[mask] = & FFPU fpuop_do_fdsqrt;
break;
case 0x58:
fpufunctbl[mask] = & FFPU fpuop_do_fsabs;
break;
case 0x5c:
fpufunctbl[mask] = & FFPU fpuop_do_fdabs;
break;
case 0x5a:
fpufunctbl[mask] = & FFPU fpuop_do_fsneg;
break;
case 0x5e:
fpufunctbl[mask] = & FFPU fpuop_do_fdneg;
break;
case 0x60:
fpufunctbl[mask] = & FFPU fpuop_do_fsdiv;
break;
case 0x64:
fpufunctbl[mask] = & FFPU fpuop_do_fddiv;
break;
case 0x62:
fpufunctbl[mask] = & FFPU fpuop_do_fsadd;
break;
case 0x66:
fpufunctbl[mask] = & FFPU fpuop_do_fdadd;
break;
case 0x68:
fpufunctbl[mask] = & FFPU fpuop_do_fssub;
break;
case 0x6c:
fpufunctbl[mask] = & FFPU fpuop_do_fdsub;
break;
case 0x63:
fpufunctbl[mask] = & FFPU fpuop_do_fsmul;
break;
case 0x67:
fpufunctbl[mask] = & FFPU fpuop_do_fdmul;
break;
default:
break;
}
}
switch (extra & 0x7f) {
case 0x00:
@ -6033,6 +6670,26 @@ PRIVATE void FFPU do_fld1 ( fpu_register & dest )
}
void fpu_set_fpsr(uae_u32 new_fpsr)
{
set_fpsr(new_fpsr);
}
uae_u32 fpu_get_fpsr(void)
{
return get_fpsr();
}
void fpu_set_fpcr(uae_u32 new_fpcr)
{
set_fpcr(new_fpcr);
}
uae_u32 fpu_get_fpcr(void)
{
return get_fpcr();
}
/* ---------------------------- MAIN INIT ---------------------------- */
#ifdef HAVE_SIGACTION
@ -6079,11 +6736,15 @@ PUBLIC void FFPU fpu_init( bool integral_68040 )
FPU fpsr.quotient = 0;
for( int i=0; i<8; i++ ) {
MAKE_NAN( FPU registers[i] );
MAKE_NAN( FPU registers[i], false );
}
build_fpp_opp_lookup_table();
/* _asm {
FNINIT
FLDCW x86_control_word
} */
__asm__ __volatile__("fninit\nfldcw %0" : : "m" (x86_control_word));
do_fldpi( const_pi );
@ -6111,6 +6772,10 @@ PUBLIC void FFPU fpu_init( bool integral_68040 )
set_constant( const_1e4096, "1.0e4096", 1.0e256, 10000 );
// Just in case.
/* _asm {
FNINIT
FLDCW x86_control_word
} */
__asm__ __volatile__("fninit\nfldcw %0" : : "m" (x86_control_word));
}

View File

@ -1,28 +1,33 @@
/*
* fpu/fpu_x86.h - Extra Definitions for the X86 assembly FPU core
* fpu/fpu_x86.h - Extra Definitions for the X86 assembly FPU core
*
* Basilisk II (C) 1997-2008 Christian Bauer
* Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
*
* Inspired by Christian Bauer's Basilisk II
*
* MC68881/68040 fpu emulation
*
* Original UAE FPU, copyright 1996 Herman ten Brugge
* Rewrite for x86, copyright 1999-2000 Lauri Pesonen
* New framework, copyright 2000 Gwenole Beauchesne
* Adapted for JIT compilation (c) Bernd Meyer, 2000
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This file is part of the ARAnyM project which builds a new and powerful
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* MC68881/68040 fpu emulation
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* Original UAE FPU, copyright 1996 Herman ten Brugge
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
* New framework, copyright 2000-2001 Gwenole Beauchesne
* Adapted for JIT compilation (c) Bernd Meyer, 2000-2001
*
* ARAnyM is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* ARAnyM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ARAnyM; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef FPU_X86_H
@ -94,17 +99,17 @@ PRIVATE void FFPU FPU_CONSISTENCY_CHECK_START(void);
PRIVATE void FFPU FPU_CONSISTENCY_CHECK_STOP(const char *name);
// Get special floating-point value class
PRIVATE __inline__ uae_u32 FFPU IS_INFINITY (fpu_register const & f);
PRIVATE __inline__ uae_u32 FFPU IS_NAN (fpu_register const & f);
PRIVATE __inline__ uae_u32 FFPU IS_ZERO (fpu_register const & f);
PRIVATE __inline__ uae_u32 FFPU IS_NEGATIVE (fpu_register const & f);
PRIVATE inline uae_u32 FFPU IS_INFINITY (fpu_register const & f);
PRIVATE inline uae_u32 FFPU IS_NAN (fpu_register const & f);
PRIVATE inline uae_u32 FFPU IS_ZERO (fpu_register const & f);
PRIVATE inline uae_u32 FFPU IS_NEGATIVE (fpu_register const & f);
// Make a special floating-point value
PRIVATE __inline__ void FFPU MAKE_NAN (fpu_register & f);
PRIVATE __inline__ void FFPU MAKE_INF_POSITIVE (fpu_register & f);
PRIVATE __inline__ void FFPU MAKE_INF_NEGATIVE (fpu_register & f);
PRIVATE __inline__ void FFPU MAKE_ZERO_POSITIVE (fpu_register & f);
PRIVATE __inline__ void FFPU MAKE_ZERO_NEGATIVE (fpu_register & f);
PRIVATE inline void FFPU MAKE_NAN (fpu_register & f, bool negative);
PRIVATE inline void FFPU MAKE_INF_POSITIVE (fpu_register & f);
PRIVATE inline void FFPU MAKE_INF_NEGATIVE (fpu_register & f);
PRIVATE inline void FFPU MAKE_ZERO_POSITIVE (fpu_register & f);
PRIVATE inline void FFPU MAKE_ZERO_NEGATIVE (fpu_register & f);
// Conversion from extended floating-point values
PRIVATE uae_s32 FFPU extended_to_signed_32 ( fpu_register const & f ) REGPARAM;
@ -342,6 +347,24 @@ PRIVATE void REGPARAM2 FFPU fpuop_do_fsincos( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fcmp( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_ftst( uae_u32 opcode, uae_u32 extra );
// 040
PRIVATE void REGPARAM2 FFPU fpuop_do_fsmove( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fdmove( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fssqrt( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fdsqrt( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fsabs( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fdabs( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fsneg( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fdneg( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fsdiv( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fddiv( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fsadd( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fdadd( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fssub( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fdsub( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fsmul( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fdmul( uae_u32 opcode, uae_u32 extra );
// Get & Put floating-point values
PRIVATE int FFPU get_fp_value (uae_u32 opcode, uae_u32 extra, fpu_register & src) REGPARAM;
PRIVATE int FFPU put_fp_value (fpu_register const & value, uae_u32 opcode, uae_u32 extra) REGPARAM;
@ -351,9 +374,9 @@ PRIVATE int FFPU get_fp_ad(uae_u32 opcode, uae_u32 * ad) REGPARAM;
PRIVATE int FFPU fpp_cond(uae_u32 opcode, int condition) REGPARAM;
// Misc functions
PRIVATE void __inline__ FFPU set_host_fpu_control_word ();
PRIVATE void __inline__ FFPU SET_BSUN_ON_NAN ();
PRIVATE void __inline__ FFPU build_ex_status ();
PRIVATE void inline FFPU set_host_fpu_control_word ();
PRIVATE void inline FFPU SET_BSUN_ON_NAN ();
PRIVATE void inline FFPU build_ex_status ();
PRIVATE void FFPU do_null_frestore ();
PRIVATE void FFPU build_fpp_opp_lookup_table ();
PRIVATE void FFPU set_constant ( fpu_register & f, char *name, double value, uae_s32 mult );

View File

@ -1,3 +1,35 @@
/*
* fpu/fpu_x86_asm.h - Extra Definitions for the X86 assembly FPU core
*
* Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
*
* Inspired by Christian Bauer's Basilisk II
*
* This file is part of the ARAnyM project which builds a new and powerful
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
*
* MC68881/68040 fpu emulation
*
* Original UAE FPU, copyright 1996 Herman ten Brugge
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
* New framework, copyright 2000-2001 Gwenole Beauchesne
* Adapted for JIT compilation (c) Bernd Meyer, 2000-2001
*
* ARAnyM is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* ARAnyM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ARAnyM; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#define DEFINE_X86_MACRO(name, value) \
asm(".local " #name "\n\t" #name " = " #value)

View File

@ -1,28 +1,38 @@
/*
* fpu/impl.h - extra functions and inline implementations
*
* Basilisk II (C) 1997-2008 Christian Bauer
* Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
*
* Inspired by Christian Bauer's Basilisk II
*
* MC68881/68040 fpu emulation
*
* Original UAE FPU, copyright 1996 Herman ten Brugge
* Rewrite for x86, copyright 1999-2000 Lauri Pesonen
* New framework, copyright 2000 Gwenole Beauchesne
* Adapted for JIT compilation (c) Bernd Meyer, 2000
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This file is part of the ARAnyM project which builds a new and powerful
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* MC68881/68040 fpu emulation
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* Original UAE FPU, copyright 1996 Herman ten Brugge
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
* New framework, copyright 2000-2001 Gwenole Beauchesne
* Adapted for JIT compilation (c) Bernd Meyer, 2000-2001
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* ARAnyM is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* ARAnyM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ARAnyM; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef FPU_IMPL_H
@ -101,14 +111,16 @@ static inline void FFPU set_fpsr(uae_u32 new_fpsr)
/* Return the floating-point control register in m68k format */
static inline uae_u32 FFPU get_fpcr(void)
{
uae_u32 rounding_precision = get_rounding_precision();
uae_u32 rounding_mode = get_rounding_mode();
return (rounding_precision | rounding_mode);
// according to the manual, the msb bits are always zero.
// According to Toni Wilen, on '040 the least
// significant 4 bits are not masked out
return FPU fpcr & (CPUType == 4 ? 0xffff : 0xfff0);
}
/* Set the floating-point control register from an m68k format */
static inline void FFPU set_fpcr(uae_u32 new_fpcr)
{
FPU fpcr = new_fpcr;
set_rounding_precision ( new_fpcr & FPCR_ROUNDING_PRECISION);
set_rounding_mode ( new_fpcr & FPCR_ROUNDING_MODE );
set_host_control_word();
@ -123,9 +135,8 @@ static inline void FFPU set_fpcr(uae_u32 new_fpcr)
/* Retrieve a floating-point register value and convert it to double precision */
static inline double FFPU fpu_get_register(int r)
{
double f;
__asm__ __volatile__("fldt %1\n\tfstpl %0" : "=m" (f) : "m" (FPU registers[r]));
return f;
/* only used for debug output; no need for any fancy asm here */
return FPU registers[r];
}
#endif

View File

@ -1,28 +1,33 @@
/*
* fpu/mathlib.cpp - Floating-point math support library
*
* Basilisk II (C) 1997-2008 Christian Bauer
* Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
*
* Inspired by Christian Bauer's Basilisk II
*
* MC68881/68040 fpu emulation
*
* Original UAE FPU, copyright 1996 Herman ten Brugge
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
* New framework, copyright 2000-2001 Gwenole Beauchesne
* Adapted for JIT compilation (c) Bernd Meyer, 2000-2001
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This file is part of the ARAnyM project which builds a new and powerful
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* MC68881/68040 fpu emulation
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* Original UAE FPU, copyright 1996 Herman ten Brugge
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
* New framework, copyright 2000-2001 Gwenole Beauchesne
* Adapted for JIT compilation (c) Bernd Meyer, 2000-2001
*
* ARAnyM is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* ARAnyM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ARAnyM; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* NOTE: this file shall be included only from fpu/fpu_*.cpp */
@ -40,6 +45,7 @@
#if defined(FPU_IEEE) && defined(USE_X87_ASSEMBLY)
#if !defined(HAVE_EXP10L) && !defined(HAVE_POW10L)
PRIVATE fpu_extended fp_do_pow(fpu_extended x, fpu_extended y)
{
fpu_extended value, exponent;
@ -82,7 +88,9 @@ PRIVATE fpu_extended fp_do_pow(fpu_extended x, fpu_extended y)
__asm__ __volatile__("fscale" : "=t" (value) : "0" (value), "u" (exponent));
return value;
}
#endif
#ifndef HAVE_LOG1PL
PRIVATE fpu_extended fp_do_log1p(fpu_extended x)
{
// TODO: handle NaN and +inf/-inf
@ -96,5 +104,6 @@ PRIVATE fpu_extended fp_do_log1p(fpu_extended x)
__asm__ __volatile__("fldln2; fxch; fyl2x" : "=t" (value) : "0" (x + 1.0));
return value;
}
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,28 +1,33 @@
/*
* fpu/rounding.cpp - system-dependant FPU rounding mode and precision
* fpu/rounding.cpp - system-dependant FPU rounding mode and precision
*
* Basilisk II (C) 1997-2008 Christian Bauer
* Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
*
* Inspired by Christian Bauer's Basilisk II
*
* MC68881/68040 fpu emulation
*
* Original UAE FPU, copyright 1996 Herman ten Brugge
* Rewrite for x86, copyright 1999-2000 Lauri Pesonen
* New framework, copyright 2000 Gwenole Beauchesne
* Adapted for JIT compilation (c) Bernd Meyer, 2000
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This file is part of the ARAnyM project which builds a new and powerful
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* MC68881/68040 fpu emulation
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* Original UAE FPU, copyright 1996 Herman ten Brugge
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
* New framework, copyright 2000-2001 Gwenole Beauchesne
* Adapted for JIT compilation (c) Bernd Meyer, 2000-2001
*
* ARAnyM is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* ARAnyM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ARAnyM; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#undef PRIVATE

View File

@ -1,28 +1,33 @@
/*
* fpu/rounding.h - system-dependant FPU rounding mode and precision
* fpu/rounding.h - system-dependant FPU rounding mode and precision
*
* Basilisk II (C) 1997-2008 Christian Bauer
* Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
*
* Inspired by Christian Bauer's Basilisk II
*
* MC68881/68040 fpu emulation
*
* Original UAE FPU, copyright 1996 Herman ten Brugge
* Rewrite for x86, copyright 1999-2000 Lauri Pesonen
* New framework, copyright 2000 Gwenole Beauchesne
* Adapted for JIT compilation (c) Bernd Meyer, 2000
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This file is part of the ARAnyM project which builds a new and powerful
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* MC68881/68040 fpu emulation
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* Original UAE FPU, copyright 1996 Herman ten Brugge
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
* New framework, copyright 2000-2001 Gwenole Beauchesne
* Adapted for JIT compilation (c) Bernd Meyer, 2000-2001
*
* ARAnyM is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* ARAnyM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ARAnyM; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef FPU_ROUNDING_H
@ -106,8 +111,8 @@ PRIVATE inline void set_host_control_word(void)
*/
x86_control_word
= (x86_control_word & ~(X86_ROUNDING_MODE|X86_ROUNDING_PRECISION))
| x86_control_word_rm_mac2host[(FPU fpcr.rounding_mode & FPCR_ROUNDING_MODE) >> 4]
| x86_control_word_rp_mac2host[(FPU fpcr.rounding_precision & FPCR_ROUNDING_PRECISION) >> 6]
| x86_control_word_rm_mac2host[(FPU fpcr & FPCR_ROUNDING_MODE) >> 4]
| x86_control_word_rp_mac2host[(FPU fpcr & FPCR_ROUNDING_PRECISION) >> 6]
;
__asm__ __volatile__("fldcw %0" : : "m" (x86_control_word));
}
@ -131,11 +136,11 @@ PRIVATE inline void set_host_control_word(void)
/* Return the current rounding mode in m68k format */
static inline uae_u32 FFPU get_rounding_mode(void)
{ return FPU fpcr.rounding_mode; }
{ return FPU fpcr & FPCR_ROUNDING_MODE; }
/* Convert and set to native rounding mode */
static inline void FFPU set_rounding_mode(uae_u32 new_rounding_mode)
{ FPU fpcr.rounding_mode = new_rounding_mode; }
static inline void FFPU set_rounding_mode(uae_u32 /* new_rounding_mode */ )
{ }
#endif
@ -143,11 +148,11 @@ static inline void FFPU set_rounding_mode(uae_u32 new_rounding_mode)
/* Return the current rounding precision in m68k format */
static inline uae_u32 FFPU get_rounding_precision(void)
{ return FPU fpcr.rounding_precision; }
{ return FPU fpcr & FPCR_ROUNDING_PRECISION; }
/* Convert and set to native rounding precision */
static inline void FFPU set_rounding_precision(uae_u32 new_rounding_precision)
{ FPU fpcr.rounding_precision = new_rounding_precision; }
static inline void FFPU set_rounding_precision(uae_u32 /* new_rounding_precision */)
{ }
#endif

View File

@ -1,28 +1,33 @@
/*
* types.h - basic types for fpu registers
* fpu/types.h - basic types for fpu registers
*
* Basilisk II (C) 1997-2008 Christian Bauer
* Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
*
* Inspired by Christian Bauer's Basilisk II
*
* MC68881/68040 fpu emulation
*
* Original UAE FPU, copyright 1996 Herman ten Brugge
* Rewrite for x86, copyright 1999-2000 Lauri Pesonen
* New framework, copyright 2000 Gwenole Beauchesne
* Adapted for JIT compilation (c) Bernd Meyer, 2000
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* This file is part of the ARAnyM project which builds a new and powerful
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* MC68881/68040 fpu emulation
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* Original UAE FPU, copyright 1996 Herman ten Brugge
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
* New framework, copyright 2000-2001 Gwenole Beauchesne
* Adapted for JIT compilation (c) Bernd Meyer, 2000-2001
*
* ARAnyM is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* ARAnyM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ARAnyM; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef FPU_TYPES_H
@ -106,9 +111,11 @@ typedef uae_f32 fpu_single;
#elif defined(FPU_IEEE)
#if 0
#if HOST_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
#error "No IEEE float format, you lose."
#endif
#endif
/* 4-byte floats */
#if SIZEOF_FLOAT == 4
@ -133,7 +140,7 @@ typedef long double uae_f64;
typedef long double uae_f96;
typedef uae_f96 fpu_register;
#define USE_LONG_DOUBLE 1
#elif SIZEOF_LONG_DOUBLE == 16 && (defined(__i386__) || defined(__x86_64__))
#elif SIZEOF_LONG_DOUBLE == 16 && (defined(CPU_i386) || defined(CPU_x86_64) || defined(CPU_ia64))
/* Long doubles on x86-64 are really held in old x87 FPU stack. */
typedef long double uae_f128;
typedef uae_f128 fpu_register;
@ -154,6 +161,23 @@ typedef fpu_register fpu_extended;
typedef uae_f64 fpu_double;
typedef uae_f32 fpu_single;
#elif defined(FPU_MPFR)
#include <mpfr.h>
struct fpu_register {
mpfr_t f;
uae_u64 nan_bits;
int nan_sign;
operator long double ();
fpu_register &operator=(long double);
};
#endif
union fpu_register_parts {
fpu_register val;
uae_u32 parts[sizeof(fpu_register) / 4];
};
#endif /* FPU_TYPES_H */

File diff suppressed because it is too large Load Diff

View File

@ -1,91 +1,147 @@
/*
* UAE - The Un*x Amiga Emulator
/*
* m68k.h - machine dependent bits
*
* Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
*
* MC68000 emulation - machine dependent bits
* Inspired by Christian Bauer's Basilisk II
*
* Copyright 1996 Bernd Schmidt
* This file is part of the ARAnyM project which builds a new and powerful
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
*
* This program is free software; you can redistribute it and/or modify
* ARAnyM is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* ARAnyM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* along with ARAnyM; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
* UAE - The Un*x Amiga Emulator
*
* MC68000 emulation - machine dependent bits
*
* Copyright 1996 Bernd Schmidt
*
*/
#ifndef M68K_FLAGS_H
#define M68K_FLAGS_H
#ifdef OPTIMIZED_FLAGS
#if defined(X86_ASSEMBLY) || defined(X86_64_ASSEMBLY) || defined(MSVC_INTRINSICS)
#if (defined(CPU_i386) && defined(X86_ASSEMBLY)) || (defined(CPU_x86_64) && defined(X86_64_ASSEMBLY))
#ifdef __cplusplus
# include <cstdlib>
#else
# include <stdlib.h>
#endif
#ifndef SAHF_SETO_PROFITABLE
/*
* Machine dependent structure for holding the 68k CCR flags
*/
/* PUSH/POP instructions are naturally 64-bit sized on x86-64, thus
unsigned long hereunder is either 64-bit or 32-bit wide depending
on the target. */
struct flag_struct {
unsigned long cznv;
unsigned long x;
#if defined(CPU_x86_64)
uint64 cznv;
uint64 x;
#else
uint32 cznv;
uint32 x;
#endif
};
#define FLAGVAL_Z 0x40
#define FLAGVAL_N 0x80
/*
* The bits in the cznv field in the above structure are assigned to
* allow the easy mirroring of the x86 rFLAGS register.
*
* The 68k CZNV flags are thus assigned in cznv as:
*
* 76543210 FEDCBA98 --------- ---------
* SZxxxxxC xxxxVxxx xxxxxxxxx xxxxxxxxx
*/
#define SET_ZFLG(y) (regflags.cznv = (((uae_u32)regflags.cznv) & ~0x40) | (((y) & 1) << 6))
#define SET_CFLG(y) (regflags.cznv = (((uae_u32)regflags.cznv) & ~1) | ((y) & 1))
#define SET_VFLG(y) (regflags.cznv = (((uae_u32)regflags.cznv) & ~0x800) | (((y) & 1) << 11))
#define SET_NFLG(y) (regflags.cznv = (((uae_u32)regflags.cznv) & ~0x80) | (((y) & 1) << 7))
#define SET_XFLG(y) (regflags.x = (y))
#define FLAGBIT_N 7
#define FLAGBIT_Z 6
#define FLAGBIT_C 0
#define FLAGBIT_V 11
#define FLAGBIT_X 0 /* must be in position 0 for duplicate_carry() to work */
#define GET_ZFLG ((regflags.cznv >> 6) & 1)
#define GET_CFLG (regflags.cznv & 1)
#define GET_VFLG ((regflags.cznv >> 11) & 1)
#define GET_NFLG ((regflags.cznv >> 7) & 1)
#define GET_XFLG (regflags.x & 1)
#define FLAGVAL_N (1 << FLAGBIT_N)
#define FLAGVAL_Z (1 << FLAGBIT_Z)
#define FLAGVAL_C (1 << FLAGBIT_C)
#define FLAGVAL_V (1 << FLAGBIT_V)
#define FLAGVAL_X (1 << FLAGBIT_X)
#define CLEAR_CZNV (regflags.cznv = 0)
#define GET_CZNV (regflags.cznv)
#define IOR_CZNV(X) (regflags.cznv |= (X))
#define SET_CZNV(X) (regflags.cznv = (X))
#define SET_ZFLG(y) (regflags.cznv = (((uae_u32)regflags.cznv) & ~FLAGVAL_Z) | (((y) & 1) << FLAGBIT_Z))
#define SET_CFLG(y) (regflags.cznv = (((uae_u32)regflags.cznv) & ~FLAGVAL_C) | (((y) & 1) << FLAGBIT_C))
#define SET_VFLG(y) (regflags.cznv = (((uae_u32)regflags.cznv) & ~FLAGVAL_V) | (((y) & 1) << FLAGBIT_V))
#define SET_NFLG(y) (regflags.cznv = (((uae_u32)regflags.cznv) & ~FLAGVAL_N) | (((y) & 1) << FLAGBIT_N))
#define SET_XFLG(y) (regflags.x = ((y) & 1) << FLAGBIT_X)
#define COPY_CARRY (regflags.x = regflags.cznv)
#define GET_ZFLG() ((regflags.cznv >> FLAGBIT_Z) & 1)
#define GET_CFLG() ((regflags.cznv >> FLAGBIT_C) & 1)
#define GET_VFLG() ((regflags.cznv >> FLAGBIT_V) & 1)
#define GET_NFLG() ((regflags.cznv >> FLAGBIT_N) & 1)
#define GET_XFLG() ((regflags.x >> FLAGBIT_X) & 1)
extern struct flag_struct regflags ASM_SYM ("regflags");
#define CLEAR_CZNV() (regflags.cznv = 0)
#define GET_CZNV() (regflags.cznv)
#define IOR_CZNV(X) (regflags.cznv |= (X))
#define SET_CZNV(X) (regflags.cznv = (X))
static __inline__ int cctrue(int cc)
#define COPY_CARRY() (regflags.x = regflags.cznv >> (FLAGBIT_C - FLAGBIT_X))
extern struct flag_struct regflags __asm__ ("regflags");
/*
* Test CCR condition
*/
static inline int cctrue(int cc)
{
uae_u32 cznv = regflags.cznv;
switch(cc){
case 0: return 1; /* T */
case 1: return 0; /* F */
case 2: return (cznv & 0x41) == 0; /* !GET_CFLG && !GET_ZFLG; HI */
case 3: return (cznv & 0x41) != 0; /* GET_CFLG || GET_ZFLG; LS */
case 4: return (cznv & 1) == 0; /* !GET_CFLG; CC */
case 5: return (cznv & 1) != 0; /* GET_CFLG; CS */
case 6: return (cznv & 0x40) == 0; /* !GET_ZFLG; NE */
case 7: return (cznv & 0x40) != 0; /* GET_ZFLG; EQ */
case 8: return (cznv & 0x800) == 0;/* !GET_VFLG; VC */
case 9: return (cznv & 0x800) != 0;/* GET_VFLG; VS */
case 10:return (cznv & 0x80) == 0; /* !GET_NFLG; PL */
case 11:return (cznv & 0x80) != 0; /* GET_NFLG; MI */
case 12:return (((cznv << 4) ^ cznv) & 0x800) == 0; /* GET_NFLG == GET_VFLG; GE */
case 13:return (((cznv << 4) ^ cznv) & 0x800) != 0;/* GET_NFLG != GET_VFLG; LT */
case 14:
cznv &= 0x8c0;
return (((cznv << 4) ^ cznv) & 0x840) == 0; /* !GET_ZFLG && (GET_NFLG == GET_VFLG); GT */
case 15:
cznv &= 0x8c0;
return (((cznv << 4) ^ cznv) & 0x840) != 0; /* GET_ZFLG || (GET_NFLG != GET_VFLG); LE */
switch (cc) {
case 0: return 1; /* T */
case 1: return 0; /* F */
case 2: return (cznv & (FLAGVAL_C | FLAGVAL_Z)) == 0; /* !CFLG && !ZFLG HI */
case 3: return (cznv & (FLAGVAL_C | FLAGVAL_Z)) != 0; /* CFLG || ZFLG LS */
case 4: return (cznv & FLAGVAL_C) == 0; /* !CFLG CC */
case 5: return (cznv & FLAGVAL_C) != 0; /* CFLG CS */
case 6: return (cznv & FLAGVAL_Z) == 0; /* !ZFLG NE */
case 7: return (cznv & FLAGVAL_Z) != 0; /* ZFLG EQ */
case 8: return (cznv & FLAGVAL_V) == 0; /* !VFLG VC */
case 9: return (cznv & FLAGVAL_V) != 0; /* VFLG VS */
case 10: return (cznv & FLAGVAL_N) == 0; /* !NFLG PL */
case 11: return (cznv & FLAGVAL_N) != 0; /* NFLG MI */
#if FLAGBIT_N > FLAGBIT_V
case 12: return (((cznv << (FLAGBIT_N - FLAGBIT_V)) ^ cznv) & FLAGVAL_N) == 0; /* NFLG == VFLG GE */
case 13: return (((cznv << (FLAGBIT_N - FLAGBIT_V)) ^ cznv) & FLAGVAL_N) != 0; /* NFLG != VFLG LT */
case 14: cznv &= (FLAGVAL_N | FLAGVAL_Z | FLAGVAL_V); /* !ZFLG && (NFLG == VFLG) GT */
return (((cznv << (FLAGBIT_N - FLAGBIT_V)) ^ cznv) & (FLAGVAL_N | FLAGVAL_Z)) == 0;
case 15: cznv &= (FLAGVAL_N | FLAGVAL_Z | FLAGVAL_V); /* ZFLG || (NFLG != VFLG) LE */
return (((cznv << (FLAGBIT_N - FLAGBIT_V)) ^ cznv) & (FLAGVAL_N | FLAGVAL_Z)) != 0;
#else
case 12: return (((cznv << (FLAGBIT_V - FLAGBIT_N)) ^ cznv) & FLAGVAL_V) == 0; /* NFLG == VFLG GE */
case 13: return (((cznv << (FLAGBIT_V - FLAGBIT_N)) ^ cznv) & FLAGVAL_V) != 0; /* NFLG != VFLG LT */
case 14: cznv &= (FLAGVAL_N | FLAGVAL_Z | FLAGVAL_V); /* !ZFLG && (NFLG == VFLG) GT */
return (((cznv << (FLAGBIT_V - FLAGBIT_N)) ^ cznv) & (FLAGVAL_V | FLAGVAL_Z)) == 0;
case 15: cznv &= (FLAGVAL_N | FLAGVAL_Z | FLAGVAL_V); /* ZFLG || (NFLG != VFLG) LE */
return (((cznv << (FLAGBIT_V - FLAGBIT_N)) ^ cznv) & (FLAGVAL_V | FLAGVAL_Z)) != 0;
#endif
}
abort ();
return 0;
}
@ -93,34 +149,34 @@ static __inline__ int cctrue(int cc)
__asm__ __volatile__ ("andl %1,%1\n\t" \
"pushf\n\t" \
"pop %0\n\t" \
: "=r" (regflags.cznv) : "r" (v) : "cc")
: "=rm" (regflags.cznv) : "r" (v) : "memory", "cc")
#define optflag_testw(v) \
__asm__ __volatile__ ("andw %w1,%w1\n\t" \
"pushf\n\t" \
"pop %0\n\t" \
: "=r" (regflags.cznv) : "r" (v) : "cc")
: "=rm" (regflags.cznv) : "r" (v) : "memory", "cc")
#define optflag_testb(v) \
__asm__ __volatile__ ("andb %b1,%b1\n\t" \
"pushf\n\t" \
"pop %0\n\t" \
: "=r" (regflags.cznv) : "q" (v) : "cc")
: "=rm" (regflags.cznv) : "q" (v) : "memory", "cc")
#define optflag_addl(v, s, d) do { \
__asm__ __volatile__ ("addl %k2,%k1\n\t" \
"pushf\n\t" \
"pop %0\n\t" \
: "=r" (regflags.cznv), "=r" (v) : "rmi" (s), "1" (d) : "cc"); \
COPY_CARRY; \
: "=rm" (regflags.cznv), "=r" (v) : "rmi" (s), "1" (d) : "memory", "cc"); \
COPY_CARRY(); \
} while (0)
#define optflag_addw(v, s, d) do { \
__asm__ __volatile__ ("addw %w2,%w1\n\t" \
"pushf\n\t" \
"pop %0\n\t" \
: "=r" (regflags.cznv), "=r" (v) : "rmi" (s), "1" (d) : "cc"); \
COPY_CARRY; \
: "=rm" (regflags.cznv), "=r" (v) : "rmi" (s), "1" (d) : "memory", "cc"); \
COPY_CARRY(); \
} while (0)
#define optflag_addb(v, s, d) do { \
@ -128,113 +184,151 @@ static __inline__ int cctrue(int cc)
"pushf\n\t" \
"pop %0\n\t" \
: "=r" (regflags.cznv), "=q" (v) : "qmi" (s), "1" (d) : "cc"); \
COPY_CARRY; \
COPY_CARRY(); \
} while (0)
#define optflag_subl(v, s, d) do { \
__asm__ __volatile__ ("subl %k2,%k1\n\t" \
"pushf\n\t" \
"pop %0\n\t" \
: "=r" (regflags.cznv), "=r" (v) : "rmi" (s), "1" (d) : "cc"); \
COPY_CARRY; \
: "=rm" (regflags.cznv), "=r" (v) : "rmi" (s), "1" (d) : "memory", "cc"); \
COPY_CARRY(); \
} while (0)
#define optflag_subw(v, s, d) do { \
__asm__ __volatile__ ("subw %w2,%w1\n\t" \
"pushf\n\t" \
"pop %0\n\t" \
: "=r" (regflags.cznv), "=r" (v) : "rmi" (s), "1" (d) : "cc"); \
COPY_CARRY; \
: "=rm" (regflags.cznv), "=r" (v) : "rmi" (s), "1" (d) : "memory", "cc"); \
COPY_CARRY(); \
} while (0)
#define optflag_subb(v, s, d) do { \
__asm__ __volatile__ ("subb %b2,%b1\n\t" \
"pushf\n\t" \
"pop %0\n\t" \
: "=r" (regflags.cznv), "=q" (v) : "qmi" (s), "1" (d) : "cc"); \
COPY_CARRY; \
: "=rm" (regflags.cznv), "=q" (v) : "qmi" (s), "1" (d) : "memory", "cc"); \
COPY_CARRY(); \
} while (0)
#define optflag_cmpl(s, d) \
__asm__ __volatile__ ("cmpl %k1,%k2\n\t" \
"pushf\n\t" \
"pop %0\n\t" \
: "=r" (regflags.cznv) : "rmi" (s), "r" (d) : "cc")
: "=rm" (regflags.cznv) : "rmi" (s), "r" (d) : "memory", "cc")
#define optflag_cmpw(s, d) \
__asm__ __volatile__ ("cmpw %w1,%w2\n\t" \
"pushf\n\t" \
"pop %0\n\t" \
: "=r" (regflags.cznv) : "rmi" (s), "r" (d) : "cc")
: "=rm" (regflags.cznv) : "rmi" (s), "r" (d) : "memory", "cc")
#define optflag_cmpb(s, d) \
__asm__ __volatile__ ("cmpb %b1,%b2\n\t" \
"pushf\n\t" \
"pop %0\n\t" \
: "=r" (regflags.cznv) : "qmi" (s), "q" (d) : "cc")
: "=rm" (regflags.cznv) : "qmi" (s), "q" (d) : "memory", "cc")
#else
#else /* !SAHF_SETO_PROFITABLE */
/*
* Machine dependent structure for holding the 68k CCR flags
*/
struct flag_struct {
uae_u32 cznv;
uae_u32 x;
uae_u32 cznv;
uae_u32 x;
};
#define FLAGVAL_Z 0x4000
#define FLAGVAL_N 0x8000
extern struct flag_struct regflags __asm__ ("regflags");
#define SET_ZFLG(y) (regflags.cznv = (regflags.cznv & ~0x4000) | (((y) & 1) << 14))
#define SET_CFLG(y) (regflags.cznv = (regflags.cznv & ~0x100) | (((y) & 1) << 8))
#define SET_VFLG(y) (regflags.cznv = (regflags.cznv & ~0x1) | (((y) & 1)))
#define SET_NFLG(y) (regflags.cznv = (regflags.cznv & ~0x8000) | (((y) & 1) << 15))
#define SET_XFLG(y) (regflags.x = (y))
/*
* The bits in the cznv field in the above structure are assigned to
* allow the easy mirroring of the x86 condition flags. (For example,
* from the AX register - the x86 overflow flag can be copied to AL
* with a setto %AL instr and the other flags copied to AH with an
* lahf instr).
*
* The 68k CZNV flags are thus assigned in cznv as:
*
* <--AL--> <--AH-->
* 76543210 FEDCBA98 --------- ---------
* xxxxxxxV NZxxxxxC xxxxxxxxx xxxxxxxxx
*/
#define GET_ZFLG ((regflags.cznv >> 14) & 1)
#define GET_CFLG ((regflags.cznv >> 8) & 1)
#define GET_VFLG ((regflags.cznv >> 0) & 1)
#define GET_NFLG ((regflags.cznv >> 15) & 1)
#define GET_XFLG (regflags.x & 1)
#define FLAGBIT_N 15
#define FLAGBIT_Z 14
#define FLAGBIT_C 8
#define FLAGBIT_V 0
#define FLAGBIT_X 0 /* must be in position 0 for duplicate_carry() to work */
#define CLEAR_CZNV (regflags.cznv = 0)
#define GET_CZNV (regflags.cznv)
#define IOR_CZNV(X) (regflags.cznv |= (X))
#define SET_CZNV(X) (regflags.cznv = (X))
#define FLAGVAL_N (1 << FLAGBIT_N)
#define FLAGVAL_Z (1 << FLAGBIT_Z)
#define FLAGVAL_C (1 << FLAGBIT_C)
#define FLAGVAL_V (1 << FLAGBIT_V)
#define FLAGVAL_X (1 << FLAGBIT_X)
#define COPY_CARRY (regflags.x = (regflags.cznv)>>8)
#define SET_ZFLG(y) (regflags.cznv = (((uae_u32)regflags.cznv) & ~FLAGVAL_Z) | (((y) & 1) << FLAGBIT_Z))
#define SET_CFLG(y) (regflags.cznv = (((uae_u32)regflags.cznv) & ~FLAGVAL_C) | (((y) & 1) << FLAGBIT_C))
#define SET_VFLG(y) (regflags.cznv = (((uae_u32)regflags.cznv) & ~FLAGVAL_V) | (((y) & 1) << FLAGBIT_V))
#define SET_NFLG(y) (regflags.cznv = (((uae_u32)regflags.cznv) & ~FLAGVAL_N) | (((y) & 1) << FLAGBIT_N))
#define SET_XFLG(y) (regflags.x = ((y) & 1) << FLAGBIT_X)
extern struct flag_struct regflags ASM_SYM("regflags");
#define GET_ZFLG() ((regflags.cznv >> FLAGBIT_Z) & 1)
#define GET_CFLG() ((regflags.cznv >> FLAGBIT_C) & 1)
#define GET_VFLG() ((regflags.cznv >> FLAGBIT_V) & 1)
#define GET_NFLG() ((regflags.cznv >> FLAGBIT_N) & 1)
#define GET_XFLG() ((regflags.x >> FLAGBIT_X) & 1)
static __inline__ int cctrue(int cc)
#define CLEAR_CZNV() (regflags.cznv = 0)
#define GET_CZNV() (regflags.cznv)
#define IOR_CZNV(X) (regflags.cznv |= (X))
#define SET_CZNV(X) (regflags.cznv = (X))
#define COPY_CARRY() (regflags.x = regflags.cznv >> (FLAGBIT_C - FLAGBIT_X))
/*
* Test CCR condition
*/
static inline int cctrue(int cc)
{
uae_u32 cznv = regflags.cznv;
switch(cc){
case 0: return 1; /* T */
case 1: return 0; /* F */
case 2: return (cznv & 0x4100) == 0; /* !GET_CFLG && !GET_ZFLG; HI */
case 3: return (cznv & 0x4100) != 0; /* GET_CFLG || GET_ZFLG; LS */
case 4: return (cznv & 0x100) == 0; /* !GET_CFLG; CC */
case 5: return (cznv & 0x100) != 0; /* GET_CFLG; CS */
case 6: return (cznv & 0x4000) == 0; /* !GET_ZFLG; NE */
case 7: return (cznv & 0x4000) != 0; /* GET_ZFLG; EQ */
case 8: return (cznv & 0x01) == 0; /* !GET_VFLG; VC */
case 9: return (cznv & 0x01) != 0; /* GET_VFLG; VS */
case 10:return (cznv & 0x8000) == 0; /* !GET_NFLG; PL */
case 11:return (cznv & 0x8000) != 0; /* GET_NFLG; MI */
case 12:return (((cznv << 15) ^ cznv) & 0x8000) == 0; /* GET_NFLG == GET_VFLG; GE */
case 13:return (((cznv << 15) ^ cznv) & 0x8000) != 0;/* GET_NFLG != GET_VFLG; LT */
case 14:
cznv &= 0xc001;
return (((cznv << 15) ^ cznv) & 0xc000) == 0; /* !GET_ZFLG && (GET_NFLG == GET_VFLG); GT */
case 15:
cznv &= 0xc001;
return (((cznv << 15) ^ cznv) & 0xc000) != 0; /* GET_ZFLG || (GET_NFLG != GET_VFLG); LE */
switch (cc) {
case 0: return 1; /* T */
case 1: return 0; /* F */
case 2: return (cznv & (FLAGVAL_C | FLAGVAL_Z)) == 0; /* !CFLG && !ZFLG HI */
case 3: return (cznv & (FLAGVAL_C | FLAGVAL_Z)) != 0; /* CFLG || ZFLG LS */
case 4: return (cznv & FLAGVAL_C) == 0; /* !CFLG CC */
case 5: return (cznv & FLAGVAL_C) != 0; /* CFLG CS */
case 6: return (cznv & FLAGVAL_Z) == 0; /* !ZFLG NE */
case 7: return (cznv & FLAGVAL_Z) != 0; /* ZFLG EQ */
case 8: return (cznv & FLAGVAL_V) == 0; /* !VFLG VC */
case 9: return (cznv & FLAGVAL_V) != 0; /* VFLG VS */
case 10: return (cznv & FLAGVAL_N) == 0; /* !NFLG PL */
case 11: return (cznv & FLAGVAL_N) != 0; /* NFLG MI */
#if FLAGBIT_N > FLAGBIT_V
case 12: return (((cznv << (FLAGBIT_N - FLAGBIT_V)) ^ cznv) & FLAGVAL_N) == 0; /* NFLG == VFLG GE */
case 13: return (((cznv << (FLAGBIT_N - FLAGBIT_V)) ^ cznv) & FLAGVAL_N) != 0; /* NFLG != VFLG LT */
case 14: cznv &= (FLAGVAL_N | FLAGVAL_Z | FLAGVAL_V); /* !ZFLG && (NFLG == VFLG) GT */
return (((cznv << (FLAGBIT_N - FLAGBIT_V)) ^ cznv) & (FLAGVAL_N | FLAGVAL_Z)) == 0;
case 15: cznv &= (FLAGVAL_N | FLAGVAL_Z | FLAGVAL_V); /* ZFLG || (NFLG != VFLG) LE */
return (((cznv << (FLAGBIT_N - FLAGBIT_V)) ^ cznv) & (FLAGVAL_N | FLAGVAL_Z)) != 0;
#else
case 12: return (((cznv << (FLAGBIT_V - FLAGBIT_N)) ^ cznv) & FLAGVAL_V) == 0; /* NFLG == VFLG GE */
case 13: return (((cznv << (FLAGBIT_V - FLAGBIT_N)) ^ cznv) & FLAGVAL_V) != 0; /* NFLG != VFLG LT */
case 14: cznv &= (FLAGVAL_N | FLAGVAL_Z | FLAGVAL_V); /* !ZFLG && (NFLG == VFLG) GT */
return (((cznv << (FLAGBIT_V - FLAGBIT_N)) ^ cznv) & (FLAGVAL_V | FLAGVAL_Z)) == 0;
case 15: cznv &= (FLAGVAL_N | FLAGVAL_Z | FLAGVAL_V); /* ZFLG || (NFLG != VFLG) LE */
return (((cznv << (FLAGBIT_V - FLAGBIT_N)) ^ cznv) & (FLAGVAL_V | FLAGVAL_Z)) != 0;
#endif
}
abort();
abort ();
return 0;
}
/* Manually emit LAHF instruction so that 64-bit assemblers can grok it */
#if defined __x86_64__ && defined __GNUC__
#if defined CPU_x86_64 && defined __GNUC__
#define ASM_LAHF ".byte 0x9f"
#else
#define ASM_LAHF "lahf"
@ -273,7 +367,7 @@ static __inline__ int cctrue(int cc)
"movb %%al,regflags\n\t" \
"movb %%ah,regflags+1\n\t" \
: "=r" (v) : "rmi" (s), "0" (d) : "%eax","cc","memory"); \
COPY_CARRY; \
COPY_CARRY(); \
} while (0)
#define optflag_addw(v, s, d) do { \
@ -283,7 +377,7 @@ static __inline__ int cctrue(int cc)
"movb %%al,regflags\n\t" \
"movb %%ah,regflags+1\n\t" \
: "=r" (v) : "rmi" (s), "0" (d) : "%eax","cc","memory"); \
COPY_CARRY; \
COPY_CARRY(); \
} while (0)
#define optflag_addb(v, s, d) do { \
@ -293,7 +387,7 @@ static __inline__ int cctrue(int cc)
"movb %%al,regflags\n\t" \
"movb %%ah,regflags+1\n\t" \
: "=q" (v) : "qmi" (s), "0" (d) : "%eax","cc","memory"); \
COPY_CARRY; \
COPY_CARRY(); \
} while (0)
#define optflag_subl(v, s, d) do { \
@ -303,7 +397,7 @@ static __inline__ int cctrue(int cc)
"movb %%al,regflags\n\t" \
"movb %%ah,regflags+1\n\t" \
: "=r" (v) : "rmi" (s), "0" (d) : "%eax","cc","memory"); \
COPY_CARRY; \
COPY_CARRY(); \
} while (0)
#define optflag_subw(v, s, d) do { \
@ -313,7 +407,7 @@ static __inline__ int cctrue(int cc)
"movb %%al,regflags\n\t" \
"movb %%ah,regflags+1\n\t" \
: "=r" (v) : "rmi" (s), "0" (d) : "%eax","cc","memory"); \
COPY_CARRY; \
COPY_CARRY(); \
} while (0)
#define optflag_subb(v, s, d) do { \
@ -323,7 +417,7 @@ static __inline__ int cctrue(int cc)
"movb %%al,regflags\n\t" \
"movb %%ah,regflags+1\n\t" \
: "=q" (v) : "qmi" (s), "0" (d) : "%eax","cc","memory"); \
COPY_CARRY; \
COPY_CARRY(); \
} while (0)
#define optflag_cmpl(s, d) \
@ -340,7 +434,7 @@ static __inline__ int cctrue(int cc)
"seto %%al\n\t" \
"movb %%al,regflags\n\t" \
"movb %%ah,regflags+1\n\t" \
: : "rmi" (s), "r" (d) : "%eax","cc","memory");
: : "rmi" (s), "r" (d) : "%eax","cc","memory")
#define optflag_cmpb(s, d) \
__asm__ __volatile__ ("cmpb %b0,%b1\n\t" \
@ -350,10 +444,306 @@ static __inline__ int cctrue(int cc)
"movb %%ah,regflags+1\n\t" \
: : "qmi" (s), "q" (d) : "%eax","cc","memory")
#endif /* SAHF_SETO_PROFITABLE */
#elif defined(CPU_arm) && defined(ARM_ASSEMBLY)
/*
* Machine dependent structure for holding the 68k CCR flags
*/
struct flag_struct {
uae_u32 nzcv;
uae_u32 x;
};
#define FLAGBIT_N 31
#define FLAGBIT_Z 30
#define FLAGBIT_C 29
#define FLAGBIT_V 28
#define FLAGBIT_X FLAGBIT_C /* must be in the same position in as x flag */
#define FLAGVAL_N (1 << FLAGBIT_N)
#define FLAGVAL_Z (1 << FLAGBIT_Z)
#define FLAGVAL_C (1 << FLAGBIT_C)
#define FLAGVAL_V (1 << FLAGBIT_V)
#define FLAGVAL_X (1 << FLAGBIT_X)
#define SET_NFLG(y) (regflags.nzcv = (regflags.nzcv & ~FLAGVAL_N) | (((y) & 1) << FLAGBIT_N))
#define SET_ZFLG(y) (regflags.nzcv = (regflags.nzcv & ~FLAGVAL_Z) | (((y) & 1) << FLAGBIT_Z))
#define SET_CFLG(y) (regflags.nzcv = (regflags.nzcv & ~FLAGVAL_C) | (((y) & 1) << FLAGBIT_C))
#define SET_VFLG(y) (regflags.nzcv = (regflags.nzcv & ~FLAGVAL_V) | (((y) & 1) << FLAGBIT_V))
#define SET_XFLG(y) (regflags.x = ((y) & 1) << FLAGBIT_X)
#define GET_NFLG() ((regflags.nzcv >> FLAGBIT_N) & 1)
#define GET_ZFLG() ((regflags.nzcv >> FLAGBIT_Z) & 1)
#define GET_CFLG() ((regflags.nzcv >> FLAGBIT_C) & 1)
#define GET_VFLG() ((regflags.nzcv >> FLAGBIT_V) & 1)
#define GET_XFLG() ((regflags.x >> FLAGBIT_X) & 1)
#define CLEAR_CZNV() (regflags.nzcv = 0)
#define GET_CZNV() (regflags.nzcv)
#define IOR_CZNV(X) (regflags.nzcv |= (X))
#define SET_CZNV(X) (regflags.nzcv = (X))
#define COPY_CARRY() (regflags.x = regflags.nzcv >> (FLAGBIT_C - FLAGBIT_X))
extern struct flag_struct regflags __asm__ ("regflags");
/*
* Test CCR condition
*/
static inline int cctrue(int cc)
{
unsigned int nzcv = regflags.nzcv;
switch(cc){
case 0: return 1; /* T */
case 1: return 0; /* F */
case 2: return (nzcv & (FLAGVAL_C | FLAGVAL_Z)) == 0; /* !GET_CFLG && !GET_ZFLG; HI */
case 3: return (nzcv & (FLAGVAL_C | FLAGVAL_Z)) != 0; /* GET_CFLG || GET_ZFLG; LS */
case 4: return (nzcv & FLAGVAL_C) == 0; /* !GET_CFLG; CC */
case 5: return (nzcv & FLAGVAL_C) != 0; /* GET_CFLG; CS */
case 6: return (nzcv & FLAGVAL_Z) == 0; /* !GET_ZFLG; NE */
case 7: return (nzcv & FLAGVAL_Z) != 0; /* GET_ZFLG; EQ */
case 8: return (nzcv & FLAGVAL_V) == 0; /* !GET_VFLG; VC */
case 9: return (nzcv & FLAGVAL_V) != 0; /* GET_VFLG; VS */
case 10:return (nzcv & FLAGVAL_N) == 0; /* !GET_NFLG; PL */
case 11:return (nzcv & FLAGVAL_N) != 0; /* GET_NFLG; MI */
case 12:return (((nzcv << (FLAGBIT_N - FLAGBIT_V)) ^ nzcv) & FLAGVAL_N) == 0; /* GET_NFLG == GET_VFLG; GE */
case 13:return (((nzcv << (FLAGBIT_N - FLAGBIT_V)) ^ nzcv) & FLAGVAL_N) != 0; /* GET_NFLG != GET_VFLG; LT */
case 14: nzcv &= (FLAGVAL_N | FLAGVAL_Z | FLAGVAL_V);
return (((nzcv << (FLAGBIT_N - FLAGBIT_V)) ^ nzcv) & (FLAGVAL_N | FLAGVAL_Z)) == 0; /* !GET_ZFLG && (GET_NFLG == GET_VFLG); GT */
case 15: nzcv &= (FLAGVAL_N | FLAGVAL_Z | FLAGVAL_V);
return (((nzcv << (FLAGBIT_N - FLAGBIT_V)) ^ nzcv) & (FLAGVAL_N | FLAGVAL_Z)) != 0; /* GET_ZFLG || (GET_NFLG != GET_VFLG); LE */
}
return 0;
}
#define optflag_testl(v) do {\
__asm__ __volatile__ ("tst %[rv],%[rv]\n\t" \
"mrs %[nzcv],cpsr\n\t" \
"bic %[nzcv],#0x30000000\n\t" \
: [nzcv] "=r" (regflags.nzcv) \
: [rv] "r" (v) \
: "cc"); \
} while(0)
#define optflag_addl(v, s, d) do { \
__asm__ __volatile__ ("adds %[rv],%[rd],%[rs]\n\t" \
"mrs %[nzcv],cpsr\n\t" \
: [nzcv] "=r" (regflags.nzcv), [rv] "=r" (v) \
: [rs] "ri" (s), [rd] "1" (d) \
: "cc"); \
COPY_CARRY(); \
} while(0)
#define optflag_subl(v, s, d) do { \
__asm__ __volatile__ ("subs %[rv],%[rd],%[rs]\n\t" \
"mrs %[nzcv],cpsr\n\t" \
"eor %[nzcv],#0x20000000\n\t" \
: [nzcv] "=r" (regflags.nzcv), [rv] "=r" (v) \
: [rs] "ri" (s), [rd] "1" (d) \
: "cc"); \
COPY_CARRY(); \
} while(0)
#define optflag_cmpl(s, d) do { \
__asm__ __volatile__ ("cmp %[rd],%[rs]\n\t" \
"mrs %[nzcv],cpsr\n\t" \
"eor %[nzcv],#0x20000000\n\t" \
: [nzcv] "=r" (regflags.nzcv) \
: [rs] "ri" (s), [rd] "0" (d) \
: "cc"); \
} while(0)
#if defined(ARMV6_ASSEMBLY)
// #pragma message "ARM/v6 Assembly optimized flags"
#define optflag_testw(v) do { \
__asm__ __volatile__ ("sxth %[rv],%[rv]\n\t" \
"tst %[rv],%[rv]\n\t" \
"mrs %[nzcv],cpsr\n\t" \
"bic %[nzcv],#0x30000000\n\t" \
: [nzcv] "=r" (regflags.nzcv) \
: [rv] "0" (v) \
: "cc"); \
}while(0)
#define optflag_testb(v) do {\
__asm__ __volatile__ ("sxtb %[rv],%[rv]\n\t" \
"tst %[rv],%[rv]\n\t" \
"mrs %[nzcv],cpsr\n\t" \
"bic %[nzcv],#0x30000000\n\t" \
: [nzcv] "=r" (regflags.nzcv) \
: [rv] "0" (v) \
: "cc"); \
}while(0)
#define optflag_addw(v, s, d) do { \
__asm__ __volatile__ ("sxth %[rd],%[rd]\n\t" \
"sxth %[rs],%[rs]\n\t" \
"adds %[rd],%[rd],%[rs]\n\t" \
"mrs %[nzcv],cpsr\n\t" \
: [nzcv] "=r" (regflags.nzcv), [rv] "=r" (v) \
: [rs] "ri" (s), [rd] "1" (d) \
: "cc"); \
COPY_CARRY(); \
} while(0)
#define optflag_addb(v, s, d) do { \
__asm__ __volatile__ ("sxtb %[rd],%[rd]\n\t" \
"sxtb %[rs],%[rs]\n\t" \
"adds %[rd],%[rd],%[rs]\n\t" \
"mrs %[nzcv],cpsr\n\t" \
: [nzcv] "=r" (regflags.nzcv), [rv] "=r" (v) \
: [rs] "ri" (s), [rd] "1" (d) \
: "cc"); \
COPY_CARRY(); \
} while(0)
#define optflag_subw(v, s, d) do { \
__asm__ __volatile__ ("sxth %[rd],%[rd]\n\t" \
"sxth %[rs],%[rs]\n\t" \
"subs %[rd],%[rd],%[rs]\n\t" \
"mrs %[nzcv],cpsr\n\t" \
"eor %[nzcv],#0x20000000\n\t" \
: [nzcv] "=r" (regflags.nzcv), [rv] "=r" (v) \
: [rs] "ri" (s), [rd] "1" (d) \
: "cc"); \
COPY_CARRY(); \
} while(0)
#define optflag_subb(v, s, d) do { \
__asm__ __volatile__ ("sxtb %[rd],%[rd]\n\t" \
"sxtb %[rs],%[rs]\n\t" \
"subs %[rd],%[rd],%[rs]\n\t" \
"mrs %[nzcv],cpsr\n\t" \
"eor %[nzcv],#0x20000000\n\t" \
: [nzcv] "=r" (regflags.nzcv), [rv] "=r" (v) \
: [rs] "ri" (s), [rd] "1" (d) \
: "cc"); \
COPY_CARRY(); \
} while(0)
#define optflag_cmpw(s, d) do { \
__asm__ __volatile__ ("sxth %[rd],%[rd]\n\t" \
"sxth %[rs],%[rs]\n\t" \
"cmp %[rd],%[rs]\n\t" \
"mrs %[nzcv],cpsr\n\t" \
"eor %[nzcv],#0x20000000\n\t" \
: [nzcv] "=r" (regflags.nzcv) \
: [rs] "ri" (s), [rd] "0" (d) \
: "cc"); \
} while(0)
#define optflag_cmpb(s, d) do { \
__asm__ __volatile__ ("sxtb %[rd],%[rd]\n\t" \
"sxtb %[rs],%[rs]\n\t" \
"cmp %[rd],%[rs]\n\t" \
"mrs %[nzcv],cpsr\n\t" \
"eor %[nzcv],#0x20000000\n\t" \
: [nzcv] "=r" (regflags.nzcv) \
: [rs] "ri" (s), [rd] "0" (d) \
: "cc"); \
} while(0)
#else
// #pragma message "ARM/generic Assembly optimized flags"
#define optflag_testw(v) do { \
__asm__ __volatile__ ("lsl %[rv],%[rv],#16\n\t" \
"tst %[rv],%[rv]\n\t" \
"mrs %[nzcv],cpsr\n\t" \
"bic %[nzcv],#0x30000000\n\t" \
: [nzcv] "=r" (regflags.nzcv) \
: [rv] "0" (v) \
: "cc"); \
}while(0)
#define optflag_testb(v) do {\
__asm__ __volatile__ ("lsl %[rv],%[rv],#24\n\t" \
"tst %[rv],%[rv]\n\t" \
"mrs %[nzcv],cpsr\n\t" \
"bic %[nzcv],#0x30000000\n\t" \
: [nzcv] "=r" (regflags.nzcv) \
: [rv] "0" (v) \
: "cc"); \
}while(0)
#define optflag_addw(v, s, d) do { \
__asm__ __volatile__ ("lsl %[rd],%[rd],#16\n\t" \
"adds %[rd],%[rd],%[rs],lsl #16\n\t" \
"mrs %[nzcv],cpsr\n\t" \
"lsr %[rv],%[rd],#16\n\t" \
: [nzcv] "=r" (regflags.nzcv), [rv] "=r" (v) \
: [rs] "ri" (s), [rd] "1" (d) \
: "cc"); \
COPY_CARRY(); \
} while(0)
#define optflag_addb(v, s, d) do { \
__asm__ __volatile__ ("lsl %[rd],%[rd],#24\n\t" \
"adds %[rd],%[rd],%[rs],lsl #24\n\t" \
"mrs %[nzcv],cpsr\n\t" \
"lsr %[rv],%[rd],#24\n\t" \
: [nzcv] "=r" (regflags.nzcv), [rv] "=r" (v) \
: [rs] "ri" (s), [rd] "1" (d) \
: "cc"); \
COPY_CARRY(); \
} while(0)
#define optflag_subw(v, s, d) do { \
__asm__ __volatile__ ("lsl %[rd],%[rd],#16\n\t" \
"subs %[rd],%[rd],%[rs],lsl #16\n\t" \
"mrs %[nzcv],cpsr\n\t" \
"eor %[nzcv],#0x20000000\n\t" \
"lsr %[rv],%[rd],#16\n\t" \
: [nzcv] "=r" (regflags.nzcv), [rv] "=r" (v) \
: [rs] "ri" (s), [rd] "1" (d) \
: "cc"); \
COPY_CARRY(); \
} while(0)
#define optflag_subb(v, s, d) do { \
__asm__ __volatile__ ("lsl %[rd],%[rd],#24\n\t" \
"subs %[rd],%[rd],%[rs],lsl #24\n\t" \
"mrs %[nzcv],cpsr\n\t" \
"eor %[nzcv],#0x20000000\n\t" \
"lsr %[rv],%[rd],#24\n\t" \
: [nzcv] "=r" (regflags.nzcv), [rv] "=r" (v) \
: [rs] "ri" (s), [rd] "1" (d) \
: "cc"); \
COPY_CARRY(); \
} while(0)
#define optflag_cmpw(s, d) do { \
__asm__ __volatile__ ("lsl %[rd],%[rd],#16\n\t" \
"cmp %[rd],%[rs],lsl #16\n\t" \
"mrs %[nzcv],cpsr\n\t" \
"eor %[nzcv],#0x20000000\n\t" \
: [nzcv] "=r" (regflags.nzcv) \
: [rs] "ri" (s), [rd] "0" (d) \
: "cc"); \
} while(0)
#define optflag_cmpb(s, d) do { \
__asm__ __volatile__ ("lsl %[rd],%[rd],#24\n\t" \
"cmp %[rd],%[rs],lsl #24\n\t" \
"mrs %[nzcv],cpsr\n\t" \
"eor %[nzcv],#0x20000000\n\t" \
: [nzcv] "=r" (regflags.nzcv) \
: [rs] "ri" (s), [rd] "0" (d) \
: "cc"); \
} while(0)
#endif
#elif defined(SPARC_V8_ASSEMBLY) || defined(SPARC_V9_ASSEMBLY)
#elif defined(CPU_sparc) && (defined(SPARC_V8_ASSEMBLY) || defined(SPARC_V9_ASSEMBLY))
/*
* Machine dependent structure for holding the 68k CCR flags
*/
struct flag_struct {
unsigned char nzvc;
unsigned char x;
@ -361,52 +751,62 @@ struct flag_struct {
extern struct flag_struct regflags;
#define FLAGVAL_Z 0x04
#define FLAGVAL_N 0x08
#define FLAGBIT_N 3
#define FLAGBIT_Z 2
#define FLAGBIT_V 1
#define FLAGBIT_C 0
#define FLAGBIT_X FLAGBIT_C /* should be in the same position as the x flag */
#define SET_ZFLG(y) (regflags.nzvc = (regflags.nzvc & ~0x04) | (((y) & 1) << 2))
#define SET_CFLG(y) (regflags.nzvc = (regflags.nzvc & ~1) | ((y) & 1))
#define SET_VFLG(y) (regflags.nzvc = (regflags.nzvc & ~0x02) | (((y) & 1) << 1))
#define SET_NFLG(y) (regflags.nzvc = (regflags.nzvc & ~0x08) | (((y) & 1) << 3))
#define SET_XFLG(y) (regflags.x = (y))
#define FLAGVAL_N (1 << FLAGBIT_N)
#define FLAGVAL_Z (1 << FLAGBIT_Z)
#define FLAGVAL_C (1 << FLAGBIT_C)
#define FLAGVAL_V (1 << FLAGBIT_V)
#define FLAGVAL_X (1 << FLAGBIT_X)
#define GET_ZFLG ((regflags.nzvc >> 2) & 1)
#define GET_CFLG (regflags.nzvc & 1)
#define GET_VFLG ((regflags.nzvc >> 1) & 1)
#define GET_NFLG ((regflags.nzvc >> 3) & 1)
#define GET_XFLG (regflags.x & 1)
#define SET_ZFLG(y) (regflags.nzvc = (regflags.nzvc & ~FLAGVAL_Z) | (((y) & 1) << FLAGBIT_Z))
#define SET_CFLG(y) (regflags.nzvc = (regflags.nzvc & ~FLAGVAL_C) | (((y) & 1) << FLAGBIT_C))
#define SET_VFLG(y) (regflags.nzvc = (regflags.nzvc & ~FLAGVAL_V) | (((y) & 1) << FLAGBIT_V))
#define SET_NFLG(y) (regflags.nzvc = (regflags.nzvc & ~FLAGVAL_V) | (((y) & 1) << FLAGBIT_N))
#define SET_XFLG(y) (regflags.x = ((y) & 1) << FLAGBIT_X)
#define CLEAR_CZNV (regflags.nzvc = 0)
#define GET_CZNV (reflags.nzvc)
#define IOR_CZNV(X) (refglags.nzvc |= (X))
#define SET_CZNV(X) (regflags.nzvc = (X))
#define GET_ZFLG() ((regflags.nzvc >> FLAGBIT_Z) & 1)
#define GET_CFLG() ((regflags.nzvc >> FLAGBIT_C) & 1)
#define GET_VFLG() ((regflags.nzvc >> FLAGBIT_V) & 1)
#define GET_NFLG() ((regflags.nzvc >> FLAGBIT_N) & 1)
#define GET_XFLG() ((regflags.x >> FLAGBIT_X) & 1)
#define COPY_CARRY (regflags.x = regflags.nzvc)
#define CLEAR_CZNV() (regflags.nzvc = 0)
#define GET_CZNV() (regflags.nzvc)
#define IOR_CZNV(X) (regflags.nzvc |= (X))
#define SET_CZNV(X) (regflags.nzvc = (X))
static __inline__ int cctrue(int cc)
#define COPY_CARRY() (regflags.x = regflags.nzvc >> (FLAGBIT_C - FLAGBIT_X))
/*
* Test CCR condition
*/
static inline int cctrue(int cc)
{
uae_u32 nzvc = regflags.nzvc;
switch(cc){
case 0: return 1; /* T */
case 1: return 0; /* F */
case 2: return (nzvc & 0x05) == 0; /* !GET_CFLG && !GET_ZFLG; HI */
case 3: return (nzvc & 0x05) != 0; /* GET_CFLG || GET_ZFLG; LS */
case 4: return (nzvc & 1) == 0; /* !GET_CFLG; CC */
case 5: return (nzvc & 1) != 0; /* GET_CFLG; CS */
case 6: return (nzvc & 0x04) == 0; /* !GET_ZFLG; NE */
case 7: return (nzvc & 0x04) != 0; /* GET_ZFLG; EQ */
case 8: return (nzvc & 0x02) == 0;/* !GET_VFLG; VC */
case 9: return (nzvc & 0x02) != 0;/* GET_VFLG; VS */
case 10:return (nzvc & 0x08) == 0; /* !GET_NFLG; PL */
case 11:return (nzvc & 0x08) != 0; /* GET_NFLG; MI */
case 12:return (((nzvc << 2) ^ nzvc) & 0x08) == 0; /* GET_NFLG == GET_VFLG; GE */
case 13:return (((nzvc << 2) ^ nzvc) & 0x08) != 0;/* GET_NFLG != GET_VFLG; LT */
case 14:
nzvc &= 0x0e;
return (((nzvc << 2) ^ nzvc) & 0x0c) == 0; /* !GET_ZFLG && (GET_NFLG == GET_VFLG); GT */
case 15:
nzvc &= 0x0e;
return (((nzvc << 2) ^ nzvc) & 0x0c) != 0; /* GET_ZFLG || (GET_NFLG != GET_VFLG); LE */
switch (cc) {
case 0: return 1; /* T */
case 1: return 0; /* F */
case 2: return (cznv & (FLAGVAL_C | FLAGVAL_Z)) == 0; /* !CFLG && !ZFLG HI */
case 3: return (cznv & (FLAGVAL_C | FLAGVAL_Z)) != 0; /* CFLG || ZFLG LS */
case 4: return (cznv & FLAGVAL_C) == 0; /* !CFLG CC */
case 5: return (cznv & FLAGVAL_C) != 0; /* CFLG CS */
case 6: return (cznv & FLAGVAL_Z) == 0; /* !ZFLG NE */
case 7: return (cznv & FLAGVAL_Z) != 0; /* ZFLG EQ */
case 8: return (cznv & FLAGVAL_V) == 0; /* !VFLG VC */
case 9: return (cznv & FLAGVAL_V) != 0; /* VFLG VS */
case 10: return (cznv & FLAGVAL_N) == 0; /* !NFLG PL */
case 11: return (cznv & FLAGVAL_N) != 0; /* NFLG MI */
case 12: return (((cznv << (FLAGBIT_N - FLAGBIT_V)) ^ cznv) & FLAGVAL_N) == 0; /* NFLG == VFLG GE */
case 13: return (((cznv << (FLAGBIT_N - FLAGBIT_V)) ^ cznv) & FLAGVAL_N) != 0; /* NFLG != VFLG LT */
case 14: cznv &= (FLAGVAL_N | FLAGVAL_Z | FLAGVAL_V); /* ZFLG && (NFLG == VFLG) GT */
return (((cznv << (FLAGBIT_N - FLAGBIT_V)) ^ cznv) & (FLAGVAL_N | FLAGVAL_Z)) == 0;
case 15: cznv &= (FLAGVAL_N | FLAGVAL_Z | FLAGVAL_V); /* ZFLG && (NFLG != VFLG) LE */
return (((cznv << (FLAGBIT_N - FLAGBIT_V)) ^ cznv) & (FLAGVAL_N | FLAGVAL_Z)) != 0;
}
return 0;
}
@ -1008,6 +1408,9 @@ static inline uae_u32 sparc_v9_flag_addx_32(flag_struct *flags, uae_u32 src, uae
#else
/*
* Machine independent structure for holding the 68k CCR flags
*/
struct flag_struct {
unsigned int c;
unsigned int z;
@ -1030,22 +1433,25 @@ extern struct flag_struct regflags;
#define SET_ZFLG(x) (ZFLG = (x))
#define SET_XFLG(x) (XFLG = (x))
#define GET_CFLG CFLG
#define GET_NFLG NFLG
#define GET_VFLG VFLG
#define GET_ZFLG ZFLG
#define GET_XFLG XFLG
#define GET_CFLG() CFLG
#define GET_NFLG() NFLG
#define GET_VFLG() VFLG
#define GET_ZFLG() ZFLG
#define GET_XFLG() XFLG
#define CLEAR_CZNV do { \
#define CLEAR_CZNV() do { \
SET_CFLG (0); \
SET_ZFLG (0); \
SET_NFLG (0); \
SET_VFLG (0); \
} while (0)
#define COPY_CARRY (SET_XFLG (GET_CFLG))
#define COPY_CARRY() (SET_XFLG (GET_CFLG ()))
static __inline__ int cctrue(const int cc)
/*
* Test CCR condition
*/
static inline int cctrue(const int cc)
{
switch(cc){
case 0: return 1; /* T */

View File

@ -0,0 +1,606 @@
/*
* memory.h - memory management
*
* Copyright (c) 2001-2006 Milan Jurik of ARAnyM dev team (see AUTHORS)
*
* Inspired by Christian Bauer's Basilisk II
*
* This file is part of the ARAnyM project which builds a new and powerful
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
*
* ARAnyM is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* ARAnyM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with ARAnyM; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
* UAE - The Un*x Amiga Emulator
*
* memory management
*
* Copyright 1995 Bernd Schmidt
*/
#ifndef UAE_MEMORY_H
#define UAE_MEMORY_H
#include "sysdeps.h"
#include "string.h"
#include "hardware.h"
#include "parameters.h"
#include "registers.h"
#include "cpummu.h"
#include "readcpu.h"
# include <csetjmp>
// newcpu.h
extern void Exception (int, uaecptr);
#ifdef EXCEPTIONS_VIA_LONGJMP
extern JMP_BUF excep_env;
#define SAVE_EXCEPTION \
JMP_BUF excep_env_old; \
memcpy(excep_env_old, excep_env, sizeof(JMP_BUF))
#define RESTORE_EXCEPTION \
memcpy(excep_env, excep_env_old, sizeof(JMP_BUF))
#define TRY(var) int var = SETJMP(excep_env); if (!var)
#define CATCH(var) else
#define THROW(n) LONGJMP(excep_env, n)
#define THROW_AGAIN(var) LONGJMP(excep_env, var)
#define VOLATILE volatile
#else
struct m68k_exception {
int prb;
m68k_exception (int exc) : prb (exc) {}
operator int() { return prb; }
};
#define SAVE_EXCEPTION
#define RESTORE_EXCEPTION
#define TRY(var) try
#define CATCH(var) catch(m68k_exception var)
#define THROW(n) throw m68k_exception(n)
#define THROW_AGAIN(var) throw
#define VOLATILE
#endif /* EXCEPTIONS_VIA_LONGJMP */
extern int in_exception_2;
#define STRAM_END 0x0e00000UL // should be replaced by global ROMBase as soon as ROMBase will be a constant
#define ROM_END 0x0e80000UL // should be replaced by ROMBase + RealROMSize if we are going to work with larger TOS ROMs than 512 kilobytes
#define FastRAM_BEGIN 0x1000000UL // should be replaced by global FastRAMBase as soon as FastRAMBase will be a constant
#ifdef FixedSizeFastRAM
#define FastRAM_SIZE (FixedSizeFastRAM * 1024 * 1024)
#else
#define FastRAM_SIZE FastRAMSize
#endif
#ifdef FIXED_VIDEORAM
#define ARANYMVRAMSTART 0xf0000000UL
#endif
#define ARANYMVRAMSIZE 0x00100000 // should be a variable to protect VGA card offscreen memory
#ifdef FIXED_VIDEORAM
extern uintptr VMEMBaseDiff;
#else
extern uae_u32 VideoRAMBase;
#endif
#ifdef ARAM_PAGE_CHECK
extern uaecptr pc_page, read_page, write_page;
extern uintptr pc_offset, read_offset, write_offset;
# ifdef PROTECT2K
# define ARAM_PAGE_MASK 0x7ff
# else
# ifdef FULLMMU
# define ARAM_PAGE_MASK 0xfff
# else
# define ARAM_PAGE_MASK 0xfffff
# endif
# endif
#endif
extern uintptr MEMBaseDiff;
extern uintptr ROMBaseDiff;
extern uintptr FastRAMBaseDiff;
# define InitMEMBaseDiff(va, ra) (MEMBaseDiff = (uintptr)(va) - (uintptr)(ra))
# define InitROMBaseDiff(va, ra) (ROMBaseDiff = (uintptr)(va) - (uintptr)(ra))
# define InitFastRAMBaseDiff(va, ra) (FastRAMBaseDiff = (uintptr)(va) - (uintptr)(ra))
#ifdef FIXED_VIDEORAM
#define InitVMEMBaseDiff(va, ra) (VMEMBaseDiff = (uintptr)(va) - (uintptr)(ra))
#else
#define InitVMEMBaseDiff(va, ra) (ra = (uintptr)(va) + MEMBaseDiff)
#endif
extern "C" void breakpt(void);
static inline uae_u64 do_get_mem_quad(uae_u64 *a) {return SDL_SwapBE64(*a);}
static inline void do_put_mem_quad(uae_u64 *a, uae_u64 v) {*a = SDL_SwapBE64(v);}
#ifndef NOCHECKBOUNDARY
static ALWAYS_INLINE bool test_ram_boundary(uaecptr addr, int size, bool super, bool write)
{
if (addr <= (FastRAM_BEGIN + FastRAM_SIZE - size)) {
#ifdef PROTECT2K
// protect first 2kB of RAM - access in supervisor mode only
if (!super && addr < 0x00000800UL)
return false;
#endif
// check for write access to protected areas:
// - first two longwords of ST-RAM are non-writable (ROM shadow)
// - non-writable area between end of ST-RAM and begin of FastRAM
if (!write || addr >= FastRAM_BEGIN || (addr >= 8 && addr <= (STRAM_END - size)))
return true;
}
#ifdef FIXED_VIDEORAM
return addr >= ARANYMVRAMSTART && addr <= (ARANYMVRAMSTART + ARANYMVRAMSIZE - size);
#else
return addr >= VideoRAMBase && addr <= (VideoRAMBase + ARANYMVRAMSIZE - size);
#endif
}
/*
* "size" is the size of the memory access (byte = 1, word = 2, long = 4)
*/
static ALWAYS_INLINE void check_ram_boundary(uaecptr addr, int size, bool write)
{
if (test_ram_boundary(addr, size, regs.s, write))
return;
// D(bug("BUS ERROR %s at $%x\n", (write ? "writing" : "reading"), addr));
regs.mmu_fault_addr = addr;
regs.mmu_ssw = ((size & 3) << 5) | (write ? 0 : (1 << 8)); /* MMU_SW_RW */
breakpt();
THROW(2);
}
#else
static inline bool test_ram_boundary(uaecptr, int, bool, bool) { return 1; }
static inline void check_ram_boundary(uaecptr, int, bool) { }
#endif
#ifdef FIXED_VIDEORAM
# define do_get_real_address(a) ((uae_u8 *)(((uaecptr)(a) < ARANYMVRAMSTART) ? ((uaecptr)(a) + MEMBaseDiff) : ((uaecptr)(a) + VMEMBaseDiff)))
#else
# define do_get_real_address(a) ((uae_u8 *)((uintptr)(a) + MEMBaseDiff))
#endif
static inline uae_u8 *phys_get_real_address(uaecptr addr)
{
return do_get_real_address(addr);
}
#ifndef NOCHECKBOUNDARY
static inline bool phys_valid_address(uaecptr addr, bool write, int sz)
{
return test_ram_boundary(addr, sz, regs.s, write);
}
#else
static inline bool phys_valid_address(uaecptr, bool, int) { return true; }
#endif
static inline uae_u64 phys_get_quad(uaecptr addr)
{
#ifdef ARAM_PAGE_CHECK
if (((addr ^ read_page) <= ARAM_PAGE_MASK))
return do_get_mem_quad((uae_u64*)(addr + read_offset));
#endif
#ifndef HW_SIGSEGV
addr = addr < 0xff000000 ? addr : addr & 0x00ffffff;
if ((addr & 0xfff00000) == 0x00f00000) return HWget_l(addr); /* TODO: must be HWget_q */
#endif
check_ram_boundary(addr, 8, false);
uae_u64 * const m = (uae_u64 *)phys_get_real_address(addr);
#ifdef ARAM_PAGE_CHECK
read_page = addr;
read_offset = (uintptr)m - (uintptr)addr;
#endif
return do_get_mem_quad(m);
}
static inline uae_u32 phys_get_long(uaecptr addr)
{
#ifdef ARAM_PAGE_CHECK
if (((addr ^ read_page) <= ARAM_PAGE_MASK))
return do_get_mem_long((uae_u32*)(addr + read_offset));
#endif
#ifndef HW_SIGSEGV
addr = addr < 0xff000000 ? addr : addr & 0x00ffffff;
if ((addr & 0xfff00000) == 0x00f00000) return HWget_l(addr);
#endif
check_ram_boundary(addr, 4, false);
uae_u32 * const m = (uae_u32 *)phys_get_real_address(addr);
#ifdef ARAM_PAGE_CHECK
read_page = addr;
read_offset = (uintptr)m - (uintptr)addr;
#endif
return do_get_mem_long(m);
}
static inline uae_u32 phys_get_word(uaecptr addr)
{
#ifdef ARAM_PAGE_CHECK
if (((addr ^ read_page) <= ARAM_PAGE_MASK))
return do_get_mem_word((uae_u16*)(addr + read_offset));
#endif
#ifndef HW_SIGSEGV
addr = addr < 0xff000000 ? addr : addr & 0x00ffffff;
if ((addr & 0xfff00000) == 0x00f00000) return HWget_w(addr);
#endif
check_ram_boundary(addr, 2, false);
uae_u16 * const m = (uae_u16 *)phys_get_real_address(addr);
#ifdef ARAM_PAGE_CHECK
read_page = addr;
read_offset = (uintptr)m - (uintptr)addr;
#endif
return do_get_mem_word(m);
}
static inline uae_u32 phys_get_byte(uaecptr addr)
{
#ifdef ARAM_PAGE_CHECK
if (((addr ^ read_page) <= ARAM_PAGE_MASK))
return do_get_mem_byte((uae_u8*)(addr + read_offset));
#endif
#ifndef HW_SIGSEGV
addr = addr < 0xff000000 ? addr : addr & 0x00ffffff;
if ((addr & 0xfff00000) == 0x00f00000) return HWget_b(addr);
#endif
check_ram_boundary(addr, 1, false);
uae_u8 * const m = (uae_u8 *)phys_get_real_address(addr);
#ifdef ARAM_PAGE_CHECK
read_page = addr;
read_offset = (uintptr)m - (uintptr)addr;
#endif
return do_get_mem_byte(m);
}
static inline void phys_put_quad(uaecptr addr, uae_u64 l)
{
#ifdef ARAM_PAGE_CHECK
if (((addr ^ write_page) <= ARAM_PAGE_MASK)) {
do_put_mem_quad((uae_u64*)(addr + write_offset), l);
return;
}
#endif
#ifndef HW_SIGSEGV
addr = addr < 0xff000000 ? addr : addr & 0x00ffffff;
if ((addr & 0xfff00000) == 0x00f00000) {
HWput_l(addr, l); /* TODO: must be HWput_q */
return;
}
#endif
check_ram_boundary(addr, 8, true);
uae_u64 * const m = (uae_u64 *)phys_get_real_address(addr);
#ifdef ARAM_PAGE_CHECK
write_page = addr;
write_offset = (uintptr)m - (uintptr)addr;
#endif
do_put_mem_quad(m, l);
}
static inline void phys_put_long(uaecptr addr, uae_u32 l)
{
#ifdef ARAM_PAGE_CHECK
if (((addr ^ write_page) <= ARAM_PAGE_MASK)) {
do_put_mem_long((uae_u32*)(addr + write_offset), l);
return;
}
#endif
#ifndef HW_SIGSEGV
addr = addr < 0xff000000 ? addr : addr & 0x00ffffff;
if ((addr & 0xfff00000) == 0x00f00000) {
HWput_l(addr, l);
return;
}
#endif
check_ram_boundary(addr, 4, true);
uae_u32 * const m = (uae_u32 *)phys_get_real_address(addr);
#ifdef ARAM_PAGE_CHECK
write_page = addr;
write_offset = (uintptr)m - (uintptr)addr;
#endif
do_put_mem_long(m, l);
}
static inline void phys_put_word(uaecptr addr, uae_u32 w)
{
#ifdef ARAM_PAGE_CHECK
if (((addr ^ write_page) <= ARAM_PAGE_MASK)) {
do_put_mem_word((uae_u16*)(addr + write_offset), w);
return;
}
#endif
#ifndef HW_SIGSEGV
addr = addr < 0xff000000 ? addr : addr & 0x00ffffff;
if ((addr & 0xfff00000) == 0x00f00000) {
HWput_w(addr, w);
return;
}
#endif
check_ram_boundary(addr, 2, true);
uae_u16 * const m = (uae_u16 *)phys_get_real_address(addr);
#ifdef ARAM_PAGE_CHECK
write_page = addr;
write_offset = (uintptr)m - (uintptr)addr;
#endif
do_put_mem_word(m, w);
}
static inline void phys_put_byte(uaecptr addr, uae_u32 b)
{
#ifdef ARAM_PAGE_CHECK
if (((addr ^ write_page) <= ARAM_PAGE_MASK)) {
do_put_mem_byte((uae_u8*)(addr + write_offset), b);
return;
}
#endif
#ifndef HW_SIGSEGV
addr = addr < 0xff000000 ? addr : addr & 0x00ffffff;
if ((addr & 0xfff00000) == 0x00f00000) {
HWput_b(addr, b);
return;
}
#endif
check_ram_boundary(addr, 1, true);
uae_u8 * const m = (uae_u8 *)phys_get_real_address(addr);
#ifdef ARAM_PAGE_CHECK
write_page = addr;
write_offset = (uintptr)m - (uintptr)addr;
#endif
do_put_mem_byte(m, b);
}
#ifdef FULLMMU
static ALWAYS_INLINE bool is_unaligned(uaecptr addr, int size)
{
return unlikely((addr & (size - 1)) && (addr ^ (addr + size - 1)) & 0x1000);
}
static ALWAYS_INLINE uae_u8 *mmu_get_real_address(uaecptr addr, struct mmu_atc_line *cl)
{
return do_get_real_address(cl->phys + addr);
}
static ALWAYS_INLINE uae_u32 mmu_get_quad(uaecptr addr, int data)
{
struct mmu_atc_line *cl;
if (likely(mmu_lookup(addr, data, 0, &cl)))
return do_get_mem_quad((uae_u64 *)mmu_get_real_address(addr, cl));
return mmu_get_quad_slow(addr, regs.s, data, cl);
}
static ALWAYS_INLINE uae_u64 get_quad(uaecptr addr)
{
return mmu_get_quad(addr, 1);
}
static ALWAYS_INLINE uae_u32 mmu_get_long(uaecptr addr, int data, int size)
{
struct mmu_atc_line *cl;
if (likely(mmu_lookup(addr, data, 0, &cl)))
return do_get_mem_long((uae_u32 *)mmu_get_real_address(addr, cl));
return mmu_get_long_slow(addr, regs.s, data, size, cl);
}
static ALWAYS_INLINE uae_u32 get_long(uaecptr addr)
{
if (unlikely(is_unaligned(addr, 4)))
return mmu_get_long_unaligned(addr, 1);
return mmu_get_long(addr, 1, sz_long);
}
static ALWAYS_INLINE uae_u16 mmu_get_word(uaecptr addr, int data, int size)
{
struct mmu_atc_line *cl;
if (likely(mmu_lookup(addr, data, 0, &cl)))
return do_get_mem_word((uae_u16 *)mmu_get_real_address(addr, cl));
return mmu_get_word_slow(addr, regs.s, data, size, cl);
}
static ALWAYS_INLINE uae_u16 get_word(uaecptr addr)
{
if (unlikely(is_unaligned(addr, 2)))
return mmu_get_word_unaligned(addr, 1);
return mmu_get_word(addr, 1, sz_word);
}
static ALWAYS_INLINE uae_u8 mmu_get_byte(uaecptr addr, int data, int size)
{
struct mmu_atc_line *cl;
if (likely(mmu_lookup(addr, data, 0, &cl)))
return do_get_mem_byte((uae_u8 *)mmu_get_real_address(addr, cl));
return mmu_get_byte_slow(addr, regs.s, data, size, cl);
}
static ALWAYS_INLINE uae_u8 get_byte(uaecptr addr)
{
return mmu_get_byte(addr, 1, sz_byte);
}
static ALWAYS_INLINE void mmu_put_quad(uaecptr addr, uae_u64 val, int data)
{
struct mmu_atc_line *cl;
if (likely(mmu_lookup(addr, data, 1, &cl)))
do_put_mem_quad((uae_u64 *)mmu_get_real_address(addr, cl), val);
else
mmu_put_quad_slow(addr, val, regs.s, data, cl);
}
static ALWAYS_INLINE void put_quad(uaecptr addr, uae_u32 val)
{
mmu_put_quad(addr, val, 1);
}
static ALWAYS_INLINE void mmu_put_long(uaecptr addr, uae_u32 val, int data, int size)
{
struct mmu_atc_line *cl;
if (likely(mmu_lookup(addr, data, 1, &cl)))
do_put_mem_long((uae_u32 *)mmu_get_real_address(addr, cl), val);
else
mmu_put_long_slow(addr, val, regs.s, data, size, cl);
}
static ALWAYS_INLINE void put_long(uaecptr addr, uae_u32 val)
{
if (unlikely(is_unaligned(addr, 4)))
mmu_put_long_unaligned(addr, val, 1);
else
mmu_put_long(addr, val, 1, sz_long);
}
static ALWAYS_INLINE void mmu_put_word(uaecptr addr, uae_u16 val, int data, int size)
{
struct mmu_atc_line *cl;
if (likely(mmu_lookup(addr, data, 1, &cl)))
do_put_mem_word((uae_u16 *)mmu_get_real_address(addr, cl), val);
else
mmu_put_word_slow(addr, val, regs.s, data, size, cl);
}
static ALWAYS_INLINE void put_word(uaecptr addr, uae_u16 val)
{
if (unlikely(is_unaligned(addr, 2)))
mmu_put_word_unaligned(addr, val, 1);
else
mmu_put_word(addr, val, 1, sz_word);
}
static ALWAYS_INLINE void mmu_put_byte(uaecptr addr, uae_u8 val, int data, int size)
{
struct mmu_atc_line *cl;
if (likely(mmu_lookup(addr, data, 1, &cl)))
do_put_mem_byte((uae_u8 *)mmu_get_real_address(addr, cl), val);
else
mmu_put_byte_slow(addr, val, regs.s, data, size, cl);
}
static ALWAYS_INLINE void put_byte(uaecptr addr, uae_u8 val)
{
mmu_put_byte(addr, val, 1, sz_byte);
}
static inline uae_u8 *get_real_address(uaecptr addr, int write, int sz)
{
(void)sz;
return phys_get_real_address(mmu_translate(addr, regs.s, 1, write));
}
static ALWAYS_INLINE uae_u32 mmu_get_user_long(uaecptr addr, int super, int data, int size)
{
struct mmu_atc_line *cl;
if (likely(mmu_user_lookup(addr, super, data, 0, &cl)))
return do_get_mem_long((uae_u32 *)mmu_get_real_address(addr, cl));
return mmu_get_long_slow(addr, super, data, size, cl);
}
static ALWAYS_INLINE uae_u16 mmu_get_user_word(uaecptr addr, int super, int data, int size)
{
struct mmu_atc_line *cl;
if (likely(mmu_user_lookup(addr, super, data, 0, &cl)))
return do_get_mem_word((uae_u16 *)mmu_get_real_address(addr, cl));
return mmu_get_word_slow(addr, super, data, size, cl);
}
static ALWAYS_INLINE uae_u8 mmu_get_user_byte(uaecptr addr, int super, int data, int size)
{
struct mmu_atc_line *cl;
if (likely(mmu_user_lookup(addr, super, data, 0, &cl)))
return do_get_mem_byte((uae_u8 *)mmu_get_real_address(addr, cl));
return mmu_get_byte_slow(addr, super, data, size, cl);
}
static ALWAYS_INLINE void mmu_put_user_long(uaecptr addr, uae_u32 val, int super, int data, int size)
{
struct mmu_atc_line *cl;
if (likely(mmu_user_lookup(addr, super, data, 1, &cl)))
do_put_mem_long((uae_u32 *)mmu_get_real_address(addr, cl), val);
else
mmu_put_long_slow(addr, val, super, data, size, cl);
}
static ALWAYS_INLINE void mmu_put_user_word(uaecptr addr, uae_u16 val, int super, int data, int size)
{
struct mmu_atc_line *cl;
if (likely(mmu_user_lookup(addr, super, data, 1, &cl)))
do_put_mem_word((uae_u16 *)mmu_get_real_address(addr, cl), val);
else
mmu_put_word_slow(addr, val, super, data, size, cl);
}
static ALWAYS_INLINE void mmu_put_user_byte(uaecptr addr, uae_u8 val, int super, int data, int size)
{
struct mmu_atc_line *cl;
if (likely(mmu_user_lookup(addr, super, data, 1, &cl)))
do_put_mem_byte((uae_u8 *)mmu_get_real_address(addr, cl), val);
else
mmu_put_byte_slow(addr, val, super, data, size, cl);
}
static inline bool valid_address(uaecptr addr, bool write, int sz)
{
SAVE_EXCEPTION;
TRY(prb) {
(void)sz;
check_ram_boundary(mmu_translate(addr, regs.s, 1, (write ? 1 : 0)), sz, write);
RESTORE_EXCEPTION;
return true;
}
CATCH(prb) {
RESTORE_EXCEPTION;
return false;
}
}
#else
# define get_quad(a) phys_get_quad(a)
# define get_long(a) phys_get_long(a)
# define get_word(a) phys_get_word(a)
# define get_byte(a) phys_get_byte(a)
# define put_quad(a,b) phys_put_quad(a,b)
# define put_long(a,b) phys_put_long(a,b)
# define put_word(a,b) phys_put_word(a,b)
# define put_byte(a,b) phys_put_byte(a,b)
# define get_real_address(a,w,s) phys_get_real_address(a)
#define valid_address(a,w,s) phys_valid_address(a,w,s)
#endif
static inline void flush_internals() {
#ifdef ARAM_PAGE_CHECK
pc_page = 0xeeeeeeee;
read_page = 0xeeeeeeee;
write_page = 0xeeeeeeee;
#endif
}
#endif /* MEMORY_H */
/*
vim:ts=4:sw=4:
*/

View File

@ -1,642 +1,59 @@
/*
* UAE - The Un*x Amiga Emulator
* memory.cpp - memory management
*
* Memory management
* Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
*
* Inspired by Christian Bauer's Basilisk II
*
* (c) 1995 Bernd Schmidt
* This file is part of the ARAnyM project which builds a new and powerful
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
*
* This program is free software; you can redistribute it and/or modify
* ARAnyM is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* ARAnyM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* along with ARAnyM; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdio.h>
#include <stdlib.h>
/*
* UAE - The Un*x Amiga Emulator
*
* Memory management
*
* (c) 1995 Bernd Schmidt
*/
#include "sysdeps.h"
#include "cpu_emulation.h"
#include "main.h"
#include "video.h"
#include "m68k.h"
#include "memory.h"
#include "readcpu.h"
#include "newcpu.h"
#define DEBUG 0
#include "debug.h"
#if !REAL_ADDRESSING && !DIRECT_ADDRESSING
static bool illegal_mem = false;
#ifdef SAVE_MEMORY_BANKS
addrbank *mem_banks[65536];
#else
addrbank mem_banks[65536];
#ifdef ARAM_PAGE_CHECK
uaecptr pc_page = 0xeeeeeeee;
uintptr pc_offset = 0;
uaecptr read_page = 0xeeeeeeee;
uintptr read_offset = 0;
uaecptr write_page = 0xeeeeeeee;
uintptr write_offset = 0;
#endif
#ifdef WORDS_BIGENDIAN
# define swap_words(X) (X)
#else
# define swap_words(X) (((X) >> 16) | ((X) << 16))
#endif
#ifdef NO_INLINE_MEMORY_ACCESS
uae_u32 longget (uaecptr addr)
extern "C" void breakpt(void)
{
return call_mem_get_func (get_mem_bank (addr).lget, addr);
}
uae_u32 wordget (uaecptr addr)
{
return call_mem_get_func (get_mem_bank (addr).wget, addr);
}
uae_u32 byteget (uaecptr addr)
{
return call_mem_get_func (get_mem_bank (addr).bget, addr);
}
void longput (uaecptr addr, uae_u32 l)
{
call_mem_put_func (get_mem_bank (addr).lput, addr, l);
}
void wordput (uaecptr addr, uae_u32 w)
{
call_mem_put_func (get_mem_bank (addr).wput, addr, w);
}
void byteput (uaecptr addr, uae_u32 b)
{
call_mem_put_func (get_mem_bank (addr).bput, addr, b);
}
#endif
/* A dummy bank that only contains zeros */
static uae_u32 REGPARAM2 dummy_lget (uaecptr) REGPARAM;
static uae_u32 REGPARAM2 dummy_wget (uaecptr) REGPARAM;
static uae_u32 REGPARAM2 dummy_bget (uaecptr) REGPARAM;
static void REGPARAM2 dummy_lput (uaecptr, uae_u32) REGPARAM;
static void REGPARAM2 dummy_wput (uaecptr, uae_u32) REGPARAM;
static void REGPARAM2 dummy_bput (uaecptr, uae_u32) REGPARAM;
uae_u32 REGPARAM2 dummy_lget (uaecptr addr)
{
if (illegal_mem)
write_log ("Illegal lget at %08x\n", addr);
return 0;
// bug("bus err: pc=%08x, sp=%08x, addr=%08x", m68k_getpc(), regs.regs[15], regs.mmu_fault_addr);
}
uae_u32 REGPARAM2 dummy_wget (uaecptr addr)
{
if (illegal_mem)
write_log ("Illegal wget at %08x\n", addr);
#if !KNOWN_ALLOC && !NORMAL_ADDRESSING
// This part need rewrite for ARAnyM !!
// It can be taken from hatari.
return 0;
}
uae_u32 REGPARAM2 dummy_bget (uaecptr addr)
{
if (illegal_mem)
write_log ("Illegal bget at %08x\n", addr);
return 0;
}
void REGPARAM2 dummy_lput (uaecptr addr, uae_u32 l)
{
if (illegal_mem)
write_log ("Illegal lput at %08x\n", addr);
}
void REGPARAM2 dummy_wput (uaecptr addr, uae_u32 w)
{
if (illegal_mem)
write_log ("Illegal wput at %08x\n", addr);
}
void REGPARAM2 dummy_bput (uaecptr addr, uae_u32 b)
{
if (illegal_mem)
write_log ("Illegal bput at %08x\n", addr);
}
/* Mac RAM (32 bit addressing) */
static uae_u32 REGPARAM2 ram_lget(uaecptr) REGPARAM;
static uae_u32 REGPARAM2 ram_wget(uaecptr) REGPARAM;
static uae_u32 REGPARAM2 ram_bget(uaecptr) REGPARAM;
static void REGPARAM2 ram_lput(uaecptr, uae_u32) REGPARAM;
static void REGPARAM2 ram_wput(uaecptr, uae_u32) REGPARAM;
static void REGPARAM2 ram_bput(uaecptr, uae_u32) REGPARAM;
static uae_u8 *REGPARAM2 ram_xlate(uaecptr addr) REGPARAM;
static uintptr RAMBaseDiff; // RAMBaseHost - RAMBaseMac
uae_u32 REGPARAM2 ram_lget(uaecptr addr)
{
uae_u32 *m;
m = (uae_u32 *)(RAMBaseDiff + addr);
return do_get_mem_long(m);
}
uae_u32 REGPARAM2 ram_wget(uaecptr addr)
{
uae_u16 *m;
m = (uae_u16 *)(RAMBaseDiff + addr);
return do_get_mem_word(m);
}
uae_u32 REGPARAM2 ram_bget(uaecptr addr)
{
return (uae_u32)*(uae_u8 *)(RAMBaseDiff + addr);
}
void REGPARAM2 ram_lput(uaecptr addr, uae_u32 l)
{
uae_u32 *m;
m = (uae_u32 *)(RAMBaseDiff + addr);
do_put_mem_long(m, l);
}
void REGPARAM2 ram_wput(uaecptr addr, uae_u32 w)
{
uae_u16 *m;
m = (uae_u16 *)(RAMBaseDiff + addr);
do_put_mem_word(m, w);
}
void REGPARAM2 ram_bput(uaecptr addr, uae_u32 b)
{
*(uae_u8 *)(RAMBaseDiff + addr) = b;
}
uae_u8 *REGPARAM2 ram_xlate(uaecptr addr)
{
return (uae_u8 *)(RAMBaseDiff + addr);
}
/* Mac RAM (24 bit addressing) */
static uae_u32 REGPARAM2 ram24_lget(uaecptr) REGPARAM;
static uae_u32 REGPARAM2 ram24_wget(uaecptr) REGPARAM;
static uae_u32 REGPARAM2 ram24_bget(uaecptr) REGPARAM;
static void REGPARAM2 ram24_lput(uaecptr, uae_u32) REGPARAM;
static void REGPARAM2 ram24_wput(uaecptr, uae_u32) REGPARAM;
static void REGPARAM2 ram24_bput(uaecptr, uae_u32) REGPARAM;
static uae_u8 *REGPARAM2 ram24_xlate(uaecptr addr) REGPARAM;
uae_u32 REGPARAM2 ram24_lget(uaecptr addr)
{
uae_u32 *m;
m = (uae_u32 *)(RAMBaseDiff + (addr & 0xffffff));
return do_get_mem_long(m);
}
uae_u32 REGPARAM2 ram24_wget(uaecptr addr)
{
uae_u16 *m;
m = (uae_u16 *)(RAMBaseDiff + (addr & 0xffffff));
return do_get_mem_word(m);
}
uae_u32 REGPARAM2 ram24_bget(uaecptr addr)
{
return (uae_u32)*(uae_u8 *)(RAMBaseDiff + (addr & 0xffffff));
}
void REGPARAM2 ram24_lput(uaecptr addr, uae_u32 l)
{
uae_u32 *m;
m = (uae_u32 *)(RAMBaseDiff + (addr & 0xffffff));
do_put_mem_long(m, l);
}
void REGPARAM2 ram24_wput(uaecptr addr, uae_u32 w)
{
uae_u16 *m;
m = (uae_u16 *)(RAMBaseDiff + (addr & 0xffffff));
do_put_mem_word(m, w);
}
void REGPARAM2 ram24_bput(uaecptr addr, uae_u32 b)
{
*(uae_u8 *)(RAMBaseDiff + (addr & 0xffffff)) = b;
}
uae_u8 *REGPARAM2 ram24_xlate(uaecptr addr)
{
return (uae_u8 *)(RAMBaseDiff + (addr & 0xffffff));
}
/* Mac ROM (32 bit addressing) */
static uae_u32 REGPARAM2 rom_lget(uaecptr) REGPARAM;
static uae_u32 REGPARAM2 rom_wget(uaecptr) REGPARAM;
static uae_u32 REGPARAM2 rom_bget(uaecptr) REGPARAM;
static void REGPARAM2 rom_lput(uaecptr, uae_u32) REGPARAM;
static void REGPARAM2 rom_wput(uaecptr, uae_u32) REGPARAM;
static void REGPARAM2 rom_bput(uaecptr, uae_u32) REGPARAM;
static uae_u8 *REGPARAM2 rom_xlate(uaecptr addr) REGPARAM;
static uintptr ROMBaseDiff; // ROMBaseHost - ROMBaseMac
uae_u32 REGPARAM2 rom_lget(uaecptr addr)
{
uae_u32 *m;
m = (uae_u32 *)(ROMBaseDiff + addr);
return do_get_mem_long(m);
}
uae_u32 REGPARAM2 rom_wget(uaecptr addr)
{
uae_u16 *m;
m = (uae_u16 *)(ROMBaseDiff + addr);
return do_get_mem_word(m);
}
uae_u32 REGPARAM2 rom_bget(uaecptr addr)
{
return (uae_u32)*(uae_u8 *)(ROMBaseDiff + addr);
}
void REGPARAM2 rom_lput(uaecptr addr, uae_u32 b)
{
if (illegal_mem)
write_log ("Illegal ROM lput at %08x\n", addr);
}
void REGPARAM2 rom_wput(uaecptr addr, uae_u32 b)
{
if (illegal_mem)
write_log ("Illegal ROM wput at %08x\n", addr);
}
void REGPARAM2 rom_bput(uaecptr addr, uae_u32 b)
{
if (illegal_mem)
write_log ("Illegal ROM bput at %08x\n", addr);
}
uae_u8 *REGPARAM2 rom_xlate(uaecptr addr)
{
return (uae_u8 *)(ROMBaseDiff + addr);
}
/* Mac ROM (24 bit addressing) */
static uae_u32 REGPARAM2 rom24_lget(uaecptr) REGPARAM;
static uae_u32 REGPARAM2 rom24_wget(uaecptr) REGPARAM;
static uae_u32 REGPARAM2 rom24_bget(uaecptr) REGPARAM;
static uae_u8 *REGPARAM2 rom24_xlate(uaecptr addr) REGPARAM;
uae_u32 REGPARAM2 rom24_lget(uaecptr addr)
{
uae_u32 *m;
m = (uae_u32 *)(ROMBaseDiff + (addr & 0xffffff));
return do_get_mem_long(m);
}
uae_u32 REGPARAM2 rom24_wget(uaecptr addr)
{
uae_u16 *m;
m = (uae_u16 *)(ROMBaseDiff + (addr & 0xffffff));
return do_get_mem_word(m);
}
uae_u32 REGPARAM2 rom24_bget(uaecptr addr)
{
return (uae_u32)*(uae_u8 *)(ROMBaseDiff + (addr & 0xffffff));
}
uae_u8 *REGPARAM2 rom24_xlate(uaecptr addr)
{
return (uae_u8 *)(ROMBaseDiff + (addr & 0xffffff));
}
/* Frame buffer */
static uae_u32 REGPARAM2 frame_direct_lget(uaecptr) REGPARAM;
static uae_u32 REGPARAM2 frame_direct_wget(uaecptr) REGPARAM;
static uae_u32 REGPARAM2 frame_direct_bget(uaecptr) REGPARAM;
static void REGPARAM2 frame_direct_lput(uaecptr, uae_u32) REGPARAM;
static void REGPARAM2 frame_direct_wput(uaecptr, uae_u32) REGPARAM;
static void REGPARAM2 frame_direct_bput(uaecptr, uae_u32) REGPARAM;
static uae_u32 REGPARAM2 frame_host_555_lget(uaecptr) REGPARAM;
static uae_u32 REGPARAM2 frame_host_555_wget(uaecptr) REGPARAM;
static void REGPARAM2 frame_host_555_lput(uaecptr, uae_u32) REGPARAM;
static void REGPARAM2 frame_host_555_wput(uaecptr, uae_u32) REGPARAM;
static uae_u32 REGPARAM2 frame_host_565_lget(uaecptr) REGPARAM;
static uae_u32 REGPARAM2 frame_host_565_wget(uaecptr) REGPARAM;
static void REGPARAM2 frame_host_565_lput(uaecptr, uae_u32) REGPARAM;
static void REGPARAM2 frame_host_565_wput(uaecptr, uae_u32) REGPARAM;
static uae_u32 REGPARAM2 frame_host_888_lget(uaecptr) REGPARAM;
static void REGPARAM2 frame_host_888_lput(uaecptr, uae_u32) REGPARAM;
static uae_u8 *REGPARAM2 frame_xlate(uaecptr addr) REGPARAM;
static uintptr FrameBaseDiff; // MacFrameBaseHost - MacFrameBaseMac
uae_u32 REGPARAM2 frame_direct_lget(uaecptr addr)
{
uae_u32 *m;
m = (uae_u32 *)(FrameBaseDiff + addr);
return do_get_mem_long(m);
}
uae_u32 REGPARAM2 frame_direct_wget(uaecptr addr)
{
uae_u16 *m;
m = (uae_u16 *)(FrameBaseDiff + addr);
return do_get_mem_word(m);
}
uae_u32 REGPARAM2 frame_direct_bget(uaecptr addr)
{
return (uae_u32)*(uae_u8 *)(FrameBaseDiff + addr);
}
void REGPARAM2 frame_direct_lput(uaecptr addr, uae_u32 l)
{
uae_u32 *m;
m = (uae_u32 *)(FrameBaseDiff + addr);
do_put_mem_long(m, l);
}
void REGPARAM2 frame_direct_wput(uaecptr addr, uae_u32 w)
{
uae_u16 *m;
m = (uae_u16 *)(FrameBaseDiff + addr);
do_put_mem_word(m, w);
}
void REGPARAM2 frame_direct_bput(uaecptr addr, uae_u32 b)
{
*(uae_u8 *)(FrameBaseDiff + addr) = b;
}
uae_u32 REGPARAM2 frame_host_555_lget(uaecptr addr)
{
uae_u32 *m, l;
m = (uae_u32 *)(FrameBaseDiff + addr);
l = *m;
return swap_words(l);
}
uae_u32 REGPARAM2 frame_host_555_wget(uaecptr addr)
{
uae_u16 *m;
m = (uae_u16 *)(FrameBaseDiff + addr);
return *m;
}
void REGPARAM2 frame_host_555_lput(uaecptr addr, uae_u32 l)
{
uae_u32 *m;
m = (uae_u32 *)(FrameBaseDiff + addr);
*m = swap_words(l);
}
void REGPARAM2 frame_host_555_wput(uaecptr addr, uae_u32 w)
{
uae_u16 *m;
m = (uae_u16 *)(FrameBaseDiff + addr);
*m = w;
}
uae_u32 REGPARAM2 frame_host_565_lget(uaecptr addr)
{
uae_u32 *m, l;
m = (uae_u32 *)(FrameBaseDiff + addr);
l = *m;
l = (l & 0x001f001f) | ((l >> 1) & 0x7fe07fe0);
return swap_words(l);
}
uae_u32 REGPARAM2 frame_host_565_wget(uaecptr addr)
{
uae_u16 *m, w;
m = (uae_u16 *)(FrameBaseDiff + addr);
w = *m;
return (w & 0x1f) | ((w >> 1) & 0x7fe0);
}
void REGPARAM2 frame_host_565_lput(uaecptr addr, uae_u32 l)
{
uae_u32 *m;
m = (uae_u32 *)(FrameBaseDiff + addr);
l = (l & 0x001f001f) | ((l << 1) & 0xffc0ffc0);
*m = swap_words(l);
}
void REGPARAM2 frame_host_565_wput(uaecptr addr, uae_u32 w)
{
uae_u16 *m;
m = (uae_u16 *)(FrameBaseDiff + addr);
*m = (w & 0x1f) | ((w << 1) & 0xffc0);
}
uae_u32 REGPARAM2 frame_host_888_lget(uaecptr addr)
{
uae_u32 *m, l;
m = (uae_u32 *)(FrameBaseDiff + addr);
return *m;
}
void REGPARAM2 frame_host_888_lput(uaecptr addr, uae_u32 l)
{
uae_u32 *m;
m = (uae_u32 *)(MacFrameBaseHost + addr - MacFrameBaseMac);
*m = l;
}
uae_u8 *REGPARAM2 frame_xlate(uaecptr addr)
{
return (uae_u8 *)(FrameBaseDiff + addr);
}
/* Mac framebuffer RAM (24 bit addressing)
*
* This works by duplicating appropriate writes to the 32-bit
* address-space framebuffer.
*/
static void REGPARAM2 fram24_lput(uaecptr, uae_u32) REGPARAM;
static void REGPARAM2 fram24_wput(uaecptr, uae_u32) REGPARAM;
static void REGPARAM2 fram24_bput(uaecptr, uae_u32) REGPARAM;
void REGPARAM2 fram24_lput(uaecptr addr, uae_u32 l)
{
uaecptr page_off = addr & 0xffff;
if (0xa700 <= page_off && page_off < 0xfc80) {
uae_u32 *fm;
fm = (uae_u32 *)(MacFrameBaseHost + page_off - 0xa700);
do_put_mem_long(fm, l);
}
uae_u32 *m;
m = (uae_u32 *)(RAMBaseDiff + (addr & 0xffffff));
do_put_mem_long(m, l);
}
void REGPARAM2 fram24_wput(uaecptr addr, uae_u32 w)
{
uaecptr page_off = addr & 0xffff;
if (0xa700 <= page_off && page_off < 0xfc80) {
uae_u16 *fm;
fm = (uae_u16 *)(MacFrameBaseHost + page_off - 0xa700);
do_put_mem_word(fm, w);
}
uae_u16 *m;
m = (uae_u16 *)(RAMBaseDiff + (addr & 0xffffff));
do_put_mem_word(m, w);
}
void REGPARAM2 fram24_bput(uaecptr addr, uae_u32 b)
{
uaecptr page_off = addr & 0xffff;
if (0xa700 <= page_off && page_off < 0xfc80) {
*(uae_u8 *)(MacFrameBaseHost + page_off - 0xa700) = b;
}
*(uae_u8 *)(RAMBaseDiff + (addr & 0xffffff)) = b;
}
/* Default memory access functions */
uae_u8 *REGPARAM2 default_xlate (uaecptr a)
{
write_log("Your Mac program just did something terribly stupid\n");
return NULL;
}
/* Address banks */
addrbank dummy_bank = {
dummy_lget, dummy_wget, dummy_bget,
dummy_lput, dummy_wput, dummy_bput,
default_xlate
};
addrbank ram_bank = {
ram_lget, ram_wget, ram_bget,
ram_lput, ram_wput, ram_bput,
ram_xlate
};
addrbank ram24_bank = {
ram24_lget, ram24_wget, ram24_bget,
ram24_lput, ram24_wput, ram24_bput,
ram24_xlate
};
addrbank rom_bank = {
rom_lget, rom_wget, rom_bget,
rom_lput, rom_wput, rom_bput,
rom_xlate
};
addrbank rom24_bank = {
rom24_lget, rom24_wget, rom24_bget,
rom_lput, rom_wput, rom_bput,
rom24_xlate
};
addrbank frame_direct_bank = {
frame_direct_lget, frame_direct_wget, frame_direct_bget,
frame_direct_lput, frame_direct_wput, frame_direct_bput,
frame_xlate
};
addrbank frame_host_555_bank = {
frame_host_555_lget, frame_host_555_wget, frame_direct_bget,
frame_host_555_lput, frame_host_555_wput, frame_direct_bput,
frame_xlate
};
addrbank frame_host_565_bank = {
frame_host_565_lget, frame_host_565_wget, frame_direct_bget,
frame_host_565_lput, frame_host_565_wput, frame_direct_bput,
frame_xlate
};
addrbank frame_host_888_bank = {
frame_host_888_lget, frame_direct_wget, frame_direct_bget,
frame_host_888_lput, frame_direct_wput, frame_direct_bput,
frame_xlate
};
addrbank fram24_bank = {
ram24_lget, ram24_wget, ram24_bget,
fram24_lput, fram24_wput, fram24_bput,
ram24_xlate
};
void memory_init(void)
{
for(long i=0; i<65536; i++)
put_mem_bank(i<<16, &dummy_bank);
// Limit RAM size to not overlap ROM
uint32 ram_size = RAMSize > ROMBaseMac ? ROMBaseMac : RAMSize;
RAMBaseDiff = (uintptr)RAMBaseHost - (uintptr)RAMBaseMac;
ROMBaseDiff = (uintptr)ROMBaseHost - (uintptr)ROMBaseMac;
FrameBaseDiff = (uintptr)MacFrameBaseHost - (uintptr)MacFrameBaseMac;
// Map RAM, ROM and display
if (TwentyFourBitAddressing) {
map_banks(&ram24_bank, RAMBaseMac >> 16, ram_size >> 16);
map_banks(&rom24_bank, ROMBaseMac >> 16, ROMSize >> 16);
// Map frame buffer at end of RAM.
map_banks(&fram24_bank, ((RAMBaseMac + ram_size) >> 16) - 1, 1);
} else {
map_banks(&ram_bank, RAMBaseMac >> 16, ram_size >> 16);
map_banks(&rom_bank, ROMBaseMac >> 16, ROMSize >> 16);
// Map frame buffer
switch (MacFrameLayout) {
case FLAYOUT_DIRECT:
map_banks(&frame_direct_bank, MacFrameBaseMac >> 16, (MacFrameSize >> 16) + 1);
break;
case FLAYOUT_HOST_555:
map_banks(&frame_host_555_bank, MacFrameBaseMac >> 16, (MacFrameSize >> 16) + 1);
break;
case FLAYOUT_HOST_565:
map_banks(&frame_host_565_bank, MacFrameBaseMac >> 16, (MacFrameSize >> 16) + 1);
break;
case FLAYOUT_HOST_888:
map_banks(&frame_host_888_bank, MacFrameBaseMac >> 16, (MacFrameSize >> 16) + 1);
break;
}
}
}
void map_banks(addrbank *bank, int start, int size)
{
int bnr;
unsigned long int hioffs = 0, endhioffs = 0x100;
if (start >= 0x100) {
for (bnr = start; bnr < start + size; bnr++)
put_mem_bank (bnr << 16, bank);
return;
}
if (TwentyFourBitAddressing) endhioffs = 0x10000;
for (hioffs = 0; hioffs < endhioffs; hioffs += 0x100)
for (bnr = start; bnr < start+size; bnr++)
put_mem_bank((bnr + hioffs) << 16, bank);
}
#endif /* !REAL_ADDRESSING && !DIRECT_ADDRESSING */
#error Not prepared for your platform, maybe you need memory banks from hatari
#endif /* !KNOWN_ALLOC && !NORMAL_ADDRESSING */

View File

@ -23,107 +23,39 @@
#ifndef UAE_MEMORY_H
#define UAE_MEMORY_H
#if !DIRECT_ADDRESSING && !REAL_ADDRESSING
/* Enabling this adds one additional native memory reference per 68k memory
* access, but saves one shift (on the x86). Enabling this is probably
* better for the cache. My favourite benchmark (PP2) doesn't show a
* difference, so I leave this enabled. */
#if 1 || defined SAVE_MEMORY
#define SAVE_MEMORY_BANKS
#endif
typedef uae_u32 (REGPARAM2 *mem_get_func)(uaecptr) REGPARAM;
typedef void (REGPARAM2 *mem_put_func)(uaecptr, uae_u32) REGPARAM;
typedef uae_u8 *(REGPARAM2 *xlate_func)(uaecptr) REGPARAM;
#undef DIRECT_MEMFUNCS_SUCCESSFUL
#ifndef CAN_MAP_MEMORY
#undef USE_COMPILER
#endif
#if defined(USE_COMPILER) && !defined(USE_MAPPED_MEMORY)
#define USE_MAPPED_MEMORY
#endif
typedef struct {
/* These ones should be self-explanatory... */
mem_get_func lget, wget, bget;
mem_put_func lput, wput, bput;
/* Use xlateaddr to translate an Amiga address to a uae_u8 * that can
* be used to address memory without calling the wget/wput functions.
* This doesn't work for all memory banks, so this function may call
* abort(). */
xlate_func xlateaddr;
} addrbank;
extern uae_u8 filesysory[65536];
extern addrbank ram_bank; // Mac RAM
extern addrbank rom_bank; // Mac ROM
extern addrbank frame_bank; // Frame buffer
/* Default memory access functions */
extern uae_u8 *REGPARAM2 default_xlate(uaecptr addr) REGPARAM;
#define bankindex(addr) (((uaecptr)(addr)) >> 16)
#ifdef SAVE_MEMORY_BANKS
extern addrbank *mem_banks[65536];
#define get_mem_bank(addr) (*mem_banks[bankindex(addr)])
#define put_mem_bank(addr, b) (mem_banks[bankindex(addr)] = (b))
#else
extern addrbank mem_banks[65536];
#define get_mem_bank(addr) (mem_banks[bankindex(addr)])
#define put_mem_bank(addr, b) (mem_banks[bankindex(addr)] = *(b))
#endif
extern void memory_init(void);
extern void map_banks(addrbank *bank, int first, int count);
#ifndef NO_INLINE_MEMORY_ACCESS
#define longget(addr) (call_mem_get_func(get_mem_bank(addr).lget, addr))
#define wordget(addr) (call_mem_get_func(get_mem_bank(addr).wget, addr))
#define byteget(addr) (call_mem_get_func(get_mem_bank(addr).bget, addr))
#define longput(addr,l) (call_mem_put_func(get_mem_bank(addr).lput, addr, l))
#define wordput(addr,w) (call_mem_put_func(get_mem_bank(addr).wput, addr, w))
#define byteput(addr,b) (call_mem_put_func(get_mem_bank(addr).bput, addr, b))
#else
extern uae_u32 longget(uaecptr addr);
extern uae_u32 wordget(uaecptr addr);
extern uae_u32 byteget(uaecptr addr);
extern void longput(uaecptr addr, uae_u32 l);
extern void wordput(uaecptr addr, uae_u32 w);
extern void byteput(uaecptr addr, uae_u32 b);
#endif
#ifndef MD_HAVE_MEM_1_FUNCS
#define longget_1 longget
#define wordget_1 wordget
#define byteget_1 byteget
#define longput_1 longput
#define wordput_1 wordput
#define byteput_1 byteput
#endif
#endif /* !DIRECT_ADDRESSING && !REAL_ADDRESSING */
#if REAL_ADDRESSING
const uintptr MEMBaseDiff = 0;
#elif DIRECT_ADDRESSING
#if DIRECT_ADDRESSING
extern uintptr MEMBaseDiff;
#endif
#if REAL_ADDRESSING || DIRECT_ADDRESSING
extern void Exception (int, uaecptr);
#ifdef EXCEPTIONS_VIA_LONGJMP
extern JMP_BUF excep_env;
#define SAVE_EXCEPTION \
JMP_BUF excep_env_old; \
memcpy(excep_env_old, excep_env, sizeof(JMP_BUF))
#define RESTORE_EXCEPTION \
memcpy(excep_env, excep_env_old, sizeof(JMP_BUF))
#define TRY(var) int var = SETJMP(excep_env); if (!var)
#define CATCH(var) else
#define THROW(n) LONGJMP(excep_env, n)
#define THROW_AGAIN(var) LONGJMP(excep_env, var)
#define VOLATILE volatile
#else
struct m68k_exception {
int prb;
m68k_exception (int exc) : prb (exc) {}
operator int() { return prb; }
};
#define SAVE_EXCEPTION
#define RESTORE_EXCEPTION
#define TRY(var) try
#define CATCH(var) catch(m68k_exception var)
#define THROW(n) throw m68k_exception(n)
#define THROW_AGAIN(var) throw
#define VOLATILE
#endif /* EXCEPTIONS_VIA_LONGJMP */
#if DIRECT_ADDRESSING
static __inline__ uae_u8 *do_get_real_address(uaecptr addr)
{
return (uae_u8 *)MEMBaseDiff + addr;
@ -137,71 +69,57 @@ static __inline__ uae_u32 get_long(uaecptr addr)
uae_u32 * const m = (uae_u32 *)do_get_real_address(addr);
return do_get_mem_long(m);
}
#define phys_get_long get_long
static __inline__ uae_u32 get_word(uaecptr addr)
{
uae_u16 * const m = (uae_u16 *)do_get_real_address(addr);
return do_get_mem_word(m);
}
#define phys_get_word get_word
static __inline__ uae_u32 get_byte(uaecptr addr)
{
uae_u8 * const m = (uae_u8 *)do_get_real_address(addr);
return do_get_mem_byte(m);
}
#define phys_get_byte get_byte
static __inline__ void put_long(uaecptr addr, uae_u32 l)
{
uae_u32 * const m = (uae_u32 *)do_get_real_address(addr);
do_put_mem_long(m, l);
}
#define phys_put_long put_long
static __inline__ void put_word(uaecptr addr, uae_u32 w)
{
uae_u16 * const m = (uae_u16 *)do_get_real_address(addr);
do_put_mem_word(m, w);
}
#define phys_put_word put_word
static __inline__ void put_byte(uaecptr addr, uae_u32 b)
{
uae_u8 * const m = (uae_u8 *)do_get_real_address(addr);
do_put_mem_byte(m, b);
}
#define phys_put_byte put_byte
static __inline__ uae_u8 *get_real_address(uaecptr addr)
{
return do_get_real_address(addr);
}
static inline uae_u8 *get_real_address(uaecptr addr, int write, int sz)
{
return do_get_real_address(addr);
}
static inline uae_u8 *phys_get_real_address(uaecptr addr)
{
return do_get_real_address(addr);
}
static __inline__ uae_u32 get_virtual_address(uae_u8 *addr)
{
return do_get_virtual_address(addr);
}
#else
static __inline__ uae_u32 get_long(uaecptr addr)
{
return longget_1(addr);
}
static __inline__ uae_u32 get_word(uaecptr addr)
{
return wordget_1(addr);
}
static __inline__ uae_u32 get_byte(uaecptr addr)
{
return byteget_1(addr);
}
static __inline__ void put_long(uaecptr addr, uae_u32 l)
{
longput_1(addr, l);
}
static __inline__ void put_word(uaecptr addr, uae_u32 w)
{
wordput_1(addr, w);
}
static __inline__ void put_byte(uaecptr addr, uae_u32 b)
{
byteput_1(addr, b);
}
static __inline__ uae_u8 *get_real_address(uaecptr addr)
{
return get_mem_bank(addr).xlateaddr(addr);
}
/* gb-- deliberately not implemented since it shall not be used... */
extern uae_u32 get_virtual_address(uae_u8 *addr);
#endif /* DIRECT_ADDRESSING || REAL_ADDRESSING */
#endif /* DIRECT_ADDRESSING */
static __inline__ void check_ram_boundary(uaecptr addr, int size, bool write) {}
static inline void flush_internals() {}
#endif /* MEMORY_H */

File diff suppressed because it is too large Load Diff

View File

@ -1,41 +1,51 @@
/*
* UAE - The Un*x Amiga Emulator
* newcpu.h - CPU emulation
*
* MC68000 emulation
* Copyright (c) 2009 ARAnyM dev team (see AUTHORS)
*
* Inspired by Christian Bauer's Basilisk II
*
* Copyright 1995 Bernd Schmidt
* This file is part of the ARAnyM project which builds a new and powerful
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
*
* This program is free software; you can redistribute it and/or modify
* ARAnyM is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* ARAnyM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* along with ARAnyM; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
* UAE - The Un*x Amiga Emulator
*
* MC68000 emulation
*
* Copyright 1995 Bernd Schmidt
*/
#ifndef NEWCPU_H
#define NEWCPU_H
#ifndef FLIGHT_RECORDER
#define FLIGHT_RECORDER 0
#endif
#include "m68k.h"
#include "readcpu.h"
#include "sysdeps.h"
#include "registers.h"
#include "spcflags.h"
#include "m68k.h"
#include "memory.h"
#if ENABLE_MON
#include "mon.h"
#include "mon_disass.h"
#endif
# include <csetjmp>
extern struct fixup {
int flag;
uae_u32 reg;
uaecptr value;
}fixup;
extern int areg_byteinc[];
extern int imm8_table[];
@ -57,122 +67,113 @@ extern int broken_in;
#endif
#define cpuop_begin() do { cpuop_tag("begin"); } while (0)
#define cpuop_end() do { cpuop_tag("end"); } while (0)
#define cpuop_end() do { cpuop_tag("end"); } while (0)
typedef void REGPARAM2 cpuop_func (uae_u32) REGPARAM;
struct cputbl {
cpuop_func *handler;
uae_u16 specific;
uae_u16 opcode;
};
extern cpuop_func *cpufunctbl[65536] ASM_SYM("cpufunctbl");
extern cpuop_func *cpufunctbl[65536];
#if USE_JIT
#ifdef USE_JIT
typedef void compop_func (uae_u32) REGPARAM;
struct comptbl {
compop_func *handler;
uae_u32 specific;
uae_u32 opcode;
uae_u32 specific;
#define COMP_OPCODE_ISJUMP 0x0001
#define COMP_OPCODE_LONG_OPCODE 0x0002
#define COMP_OPCODE_CMOV 0x0004
#define COMP_OPCODE_ISADDX 0x0008
#define COMP_OPCODE_ISCJUMP 0x0010
#define COMP_OPCODE_USES_FPU 0x0020
};
#endif
extern void REGPARAM2 op_illg (uae_u32) REGPARAM;
extern void m68k_dumpstate(uaecptr *nextpc);
typedef char flagtype;
struct regstruct {
uae_u32 regs[16];
uae_u32 pc;
uae_u8 * pc_p;
uae_u8 * pc_oldp;
spcflags_t spcflags;
int intmask;
uae_u32 vbr, sfc, dfc;
uaecptr usp, isp, msp;
uae_u16 sr;
flagtype t1;
flagtype t0;
flagtype s;
flagtype m;
flagtype x;
flagtype stopped;
#if USE_PREFETCH_BUFFER
/* Fellow sources say this is 4 longwords. That's impossible. It needs
* to be at least a longword. The HRM has some cryptic comment about two
* instructions being on the same longword boundary.
* The way this is implemented now seems like a good compromise.
*/
uae_u32 prefetch;
#endif
};
extern regstruct regs, lastint_regs;
#define m68k_dreg(r,num) ((r).regs[(num)])
#define m68k_areg(r,num) (((r).regs + 8)[(num)])
#define get_ibyte(o) do_get_mem_byte((uae_u8 *)(regs.pc_p + (o) + 1))
#define get_iword(o) do_get_mem_word((uae_u16 *)(regs.pc_p + (o)))
#define get_ilong(o) do_get_mem_long((uae_u32 *)(regs.pc_p + (o)))
#ifdef FULLMMU
static ALWAYS_INLINE uae_u8 get_ibyte(uae_u32 o)
{
return mmu_get_byte(m68k_getpc() + o + 1, 0, sz_byte);
}
static ALWAYS_INLINE uae_u16 get_iword(uae_u32 o)
{
return mmu_get_word(m68k_getpc() + o, 0, sz_word);
}
static ALWAYS_INLINE uae_u32 get_ilong(uae_u32 o)
{
uaecptr addr = m68k_getpc() + o;
if (unlikely(is_unaligned(addr, 4)))
return mmu_get_long_unaligned(addr, 0);
return mmu_get_long(addr, 0, sz_long);
}
#ifdef HAVE_GET_WORD_UNSWAPPED
#define GET_OPCODE (do_get_mem_word_unswapped (regs.pc_p))
#else
#define GET_OPCODE (get_iword (0))
#define get_ibyte(o) do_get_mem_byte((uae_u8 *)(get_real_address(m68k_getpc(), 0, sz_byte) + (o) + 1))
#define get_iword(o) do_get_mem_word((uae_u16 *)(get_real_address(m68k_getpc(), 0, sz_word) + (o)))
#define get_ilong(o) do_get_mem_long((uae_u32 *)(get_real_address(m68k_getpc(), 0, sz_long) + (o)))
#endif
#if USE_PREFETCH_BUFFER
static __inline__ uae_u32 get_ibyte_prefetch (uae_s32 o)
#if 0
static inline uae_u32 get_ibyte_prefetch (uae_s32 o)
{
if (o > 3 || o < 0)
return do_get_mem_byte((uae_u8 *)(regs.pc_p + o + 1));
return do_get_mem_byte((uae_u8 *)(do_get_real_address(regs.pcp, false, false) + o + 1));
return do_get_mem_byte((uae_u8 *)(((uae_u8 *)&regs.prefetch) + o + 1));
}
static __inline__ uae_u32 get_iword_prefetch (uae_s32 o)
static inline uae_u32 get_iword_prefetch (uae_s32 o)
{
if (o > 3 || o < 0)
return do_get_mem_word((uae_u16 *)(regs.pc_p + o));
return do_get_mem_word((uae_u16 *)(do_get_real_address(regs.pcp, false, false) + o));
return do_get_mem_word((uae_u16 *)(((uae_u8 *)&regs.prefetch) + o));
}
static __inline__ uae_u32 get_ilong_prefetch (uae_s32 o)
static inline uae_u32 get_ilong_prefetch (uae_s32 o)
{
if (o > 3 || o < 0)
return do_get_mem_long((uae_u32 *)(regs.pc_p + o));
return do_get_mem_long((uae_u32 *)(do_get_real_address(regs.pcp, false, false) + o));
if (o == 0)
return do_get_mem_long(&regs.prefetch);
return (do_get_mem_word (((uae_u16 *)&regs.prefetch) + 1) << 16) | do_get_mem_word ((uae_u16 *)(regs.pc_p + 4));
return (do_get_mem_word (((uae_u16 *)&regs.prefetch) + 1) << 16) | do_get_mem_word ((uae_u16 *)(do_get_real_address(regs.pcp, false, false) + 4));
}
#endif
static __inline__ void fill_prefetch_0 (void)
#ifdef FULLMMU
#define m68k_incpc(o) (regs.pc += (o))
#else
#define m68k_incpc(o) (regs.pc_p += (o))
#endif
static inline void fill_prefetch_0 (void)
{
#if USE_PREFETCH_BUFFER
uae_u32 r;
#ifdef UNALIGNED_PROFITABLE
r = *(uae_u32 *)regs.pc_p;
r = *(uae_u32 *)do_get_real_address(m68k_getpc(), false, false);
regs.prefetch = r;
#else
r = do_get_mem_long ((uae_u32 *)regs.pc_p);
r = do_get_mem_long ((uae_u32 *)do_get_real_address(m68k_getpc(), false, false));
do_put_mem_long (&regs.prefetch, r);
#endif
#endif
}
#if 0
static __inline__ void fill_prefetch_2 (void)
static inline void fill_prefetch_2 (void)
{
uae_u32 r = do_get_mem_long (&regs.prefetch) << 16;
uae_u32 r2 = do_get_mem_word (((uae_u16 *)regs.pc_p) + 1);
uae_u32 r2 = do_get_mem_word (((uae_u16 *)do_get_real_address(regs.pcp, false, false)) + 1);
r |= r2;
do_put_mem_long (&regs.prefetch, r);
}
@ -180,119 +181,97 @@ static __inline__ void fill_prefetch_2 (void)
#define fill_prefetch_2 fill_prefetch_0
#endif
static __inline__ uaecptr m68k_getpc (void)
{
#if REAL_ADDRESSING || DIRECT_ADDRESSING
return get_virtual_address(regs.pc_p);
#else
return regs.pc + ((char *)regs.pc_p - (char *)regs.pc_oldp);
#endif
}
static __inline__ void m68k_setpc (uaecptr newpc)
{
#if ENABLE_MON
uae_u32 previous_pc = m68k_getpc();
#endif
#if REAL_ADDRESSING || DIRECT_ADDRESSING
regs.pc_p = get_real_address(newpc);
#else
regs.pc_p = regs.pc_oldp = get_real_address(newpc);
regs.pc = newpc;
#endif
#if ENABLE_MON
if (IS_BREAK_POINT(newpc)) {
printf("Stopped at break point address: %08x. Last PC: %08x\n", newpc, previous_pc);
m68k_dumpstate(NULL);
const char *arg[4] = {"mon", "-m", "-r", NULL};
mon(3, arg);
}
#endif // end of #if ENABLE_MON
}
static __inline__ void m68k_incpc (uae_s32 delta)
{
#if ENABLE_MON
uae_u32 previous_pc = m68k_getpc();
#endif
regs.pc_p += (delta);
#if ENABLE_MON
uaecptr next_pc = m68k_getpc();
if (IS_BREAK_POINT(next_pc)) {
printf("Stopped at break point address: %08x. Last PC: %08x\n", next_pc, previous_pc);
m68k_dumpstate(NULL);
const char *arg[4] = {"mon", "-m", "-r", NULL};
mon(3, arg);
}
#endif // end of #if ENABLE_MON
}
/* These are only used by the 68020/68881 code, and therefore don't
* need to handle prefetch. */
static __inline__ uae_u32 next_ibyte (void)
static inline uae_u32 next_ibyte (void)
{
uae_u32 r = get_ibyte (0);
m68k_incpc (2);
return r;
}
static __inline__ uae_u32 next_iword (void)
static inline uae_u32 next_iword (void)
{
uae_u32 r = get_iword (0);
m68k_incpc (2);
return r;
}
static __inline__ uae_u32 next_ilong (void)
static inline uae_u32 next_ilong (void)
{
uae_u32 r = get_ilong (0);
m68k_incpc (4);
return r;
}
static inline void m68k_setpc (uaecptr newpc)
{
#ifndef FULLMMU
regs.pc_p = regs.pc_oldp = get_real_address(newpc, 0, sz_word);
#endif
regs.fault_pc = regs.pc = newpc;
}
#define m68k_setpc_fast m68k_setpc
#define m68k_setpc_bcc m68k_setpc
#define m68k_setpc_rte m68k_setpc
static __inline__ void m68k_do_rts(void)
static inline void m68k_do_rts(void)
{
m68k_setpc(get_long(m68k_areg(regs, 7)));
m68k_areg(regs, 7) += 4;
m68k_setpc(get_long(m68k_areg(regs, 7)));
m68k_areg(regs, 7) += 4;
}
static __inline__ void m68k_do_bsr(uaecptr oldpc, uae_s32 offset)
static inline void m68k_do_bsr(uaecptr oldpc, uae_s32 offset)
{
m68k_areg(regs, 7) -= 4;
put_long(m68k_areg(regs, 7), oldpc);
m68k_incpc(offset);
put_long(m68k_areg(regs, 7) - 4, oldpc);
m68k_areg(regs, 7) -= 4;
m68k_incpc(offset);
}
static __inline__ void m68k_do_jsr(uaecptr oldpc, uaecptr dest)
static inline void m68k_do_jsr(uaecptr oldpc, uaecptr dest)
{
m68k_areg(regs, 7) -= 4;
put_long(m68k_areg(regs, 7), oldpc);
m68k_setpc(dest);
put_long(m68k_areg(regs, 7) - 4, oldpc);
m68k_areg(regs, 7) -= 4;
m68k_setpc(dest);
}
static __inline__ void m68k_setstopped (int stop)
static inline void m68k_setstopped (int stop)
{
regs.stopped = stop;
/* A traced STOP instruction drops through immediately without
actually stopping. */
if (stop && (regs.spcflags & SPCFLAG_DOTRACE) == 0)
SPCFLAGS_SET( SPCFLAG_STOP );
if (stop && !( SPCFLAGS_TEST( SPCFLAG_DOTRACE )))
SPCFLAGS_SET( SPCFLAG_STOP );
}
extern uae_u32 get_disp_ea_020 (uae_u32 base, uae_u32 dp);
extern uae_u32 get_disp_ea_000 (uae_u32 base, uae_u32 dp);
#ifdef FULLMMU
# define GET_OPCODE (get_iword (0))
#elif defined ARAM_PAGE_CHECK
# ifdef HAVE_GET_WORD_UNSWAPPED
# define GET_OPCODE (do_get_mem_word_unswapped((uae_u16*)(pc + pc_offset)));
# else
# define GET_OPCODE (do_get_mem_word((uae_u16*)(pc + pc_offset)));
# endif
#else
# ifdef HAVE_GET_WORD_UNSWAPPED
# define GET_OPCODE (do_get_mem_word_unswapped ((uae_u16*)get_real_address(m68k_getpc(), 0, sz_word)))
# else
# define GET_OPCODE (get_iword (0))
# endif
#endif
extern REGPARAM uae_u32 get_disp_ea_020 (uae_u32 base, uae_u32 dp);
extern REGPARAM uae_u32 get_disp_ea_000 (uae_u32 base, uae_u32 dp);
extern REGPARAM uae_u32 get_bitfield(uae_u32 src, uae_u32 bdata[2], uae_s32 offset, int width);
extern REGPARAM void put_bitfield(uae_u32 dst, uae_u32 bdata[2], uae_u32 val, uae_s32 offset, int width);
extern uae_s32 ShowEA (int reg, amodes mode, wordsizes size, char *buf);
extern void MakeSR (void);
extern void MakeFromSR (void);
extern void Exception (int, uaecptr);
extern void ex_rte(void);
extern void dump_counts (void);
extern int m68k_move2c (int, uae_u32 *);
extern int m68k_movec2 (int, uae_u32 *);
@ -300,15 +279,19 @@ extern void m68k_divl (uae_u32, uae_u32, uae_u16, uaecptr);
extern void m68k_mull (uae_u32, uae_u32, uae_u16);
extern void m68k_emulop (uae_u32);
extern void m68k_emulop_return (void);
extern void m68k_natfeat_id(void);
extern void m68k_natfeat_call(void);
extern void init_m68k (void);
extern void exit_m68k (void);
extern void m68k_dumpstate (uaecptr *);
extern void m68k_disasm (uaecptr, uaecptr *, int);
extern void m68k_dumpstate (FILE *, uaecptr *);
extern void m68k_disasm (FILE *, uaecptr, uaecptr *, int);
extern void newm68k_disasm(FILE *, uaecptr, uaecptr *, unsigned int);
extern void showDisasm(uaecptr);
extern void m68k_reset (void);
extern void m68k_enter_debugger(void);
extern int m68k_do_specialties(void);
extern void mmu_op (uae_u32, uae_u16);
extern void m68k_instr_set(void);
uae_u32 linea68000(uae_u16 opcode);
/* Opcode of faulting instruction */
extern uae_u16 last_op_for_exception_3;
@ -319,24 +302,19 @@ extern uaecptr last_fault_for_exception_3;
#define CPU_OP_NAME(a) op ## a
/* 68020 + 68881 */
extern struct cputbl op_smalltbl_0_ff[];
/* 68020 */
extern struct cputbl op_smalltbl_1_ff[];
/* 68010 */
extern struct cputbl op_smalltbl_2_ff[];
/* 68000 */
extern struct cputbl op_smalltbl_3_ff[];
/* 68000 slow but compatible. */
extern struct cputbl op_smalltbl_4_ff[];
/* 68040+ 68881 */
extern const struct cputbl op_smalltbl_0_ff[];
extern const struct cputbl op_smalltbl_0_nf[];
#if FLIGHT_RECORDER
extern void m68k_record_step(uaecptr) REGPARAM;
#ifdef FLIGHT_RECORDER
extern void m68k_record_step(uaecptr, int);
#endif
extern void m68k_do_execute(void);
extern void m68k_execute(void);
#if USE_JIT
#ifdef USE_JIT
extern void m68k_compile_execute(void);
extern void m68k_do_compile_execute(void);
#endif
#ifdef USE_CPU_EMUL_SERVICES
extern int32 emulated_ticks;
@ -351,5 +329,7 @@ static inline void cpu_check_ticks(void)
#define cpu_check_ticks()
#define cpu_do_check_ticks()
#endif
cpuop_func op_illg_1;
#endif /* NEWCPU_H */

View File

@ -33,13 +33,13 @@
#define NOFLAGS_CMP 0
#undef SET_NFLG_ALWAYS
static __inline__ void SET_NFLG_ALWAYS(uae_u32 x)
static inline void SET_NFLG_ALWAYS(uae_u32 x)
{
SET_NFLG(x); /* This has not yet been redefined */
}
#undef SET_CFLG_ALWAYS
static __inline__ void SET_CFLG_ALWAYS(uae_u32 x)
static inline void SET_CFLG_ALWAYS(uae_u32 x)
{
SET_CFLG(x); /* This has not yet been redefined */
}
@ -62,13 +62,13 @@ static __inline__ void SET_CFLG_ALWAYS(uae_u32 x)
#define SET_XFLG(y) do {uae_u32 dummy=(y); } while (0)
#undef CLEAR_CZNV
#define CLEAR_CZNV
#define CLEAR_CZNV()
#undef IOR_CZNV
#define IOR_CZNV(y) do {uae_u32 dummy=(y); } while (0)
#undef SET_CZNV
#define SET_CZNV(y) do {uae_u32 dummy=(y); } while (0)
#undef COPY_CARRY
#define COPY_CARRY
#define COPY_CARRY()
#ifdef optflag_testl
#undef optflag_testl

View File

@ -1,34 +1,30 @@
/* 2002 MJ */
/*
* UAE - The Un*x Amiga Emulator
*
* Read 68000 CPU specs from file "table68k"
*
* Copyright 1995,1996 Bernd Schmidt
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "sysdeps.h"
#include "readcpu.h"
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
using std::strncmp;
using std::abort;
using std::fprintf;
using std::strcmp;
using std::strlen;
using std::malloc;
int nr_cpuop_funcs;
struct instr *table68k;
static int readcpu_mismatch;
struct mnemolookup lookuptab[] = {
{ i_ILLG, "ILLEGAL" },
@ -153,16 +149,19 @@ struct mnemolookup lookuptab[] = {
{ i_CPUSHA, "CPUSHA" },
{ i_MOVE16, "MOVE16" },
{ i_EMULOP_RETURN, "EMULOP_RETURN" },
{ i_EMULOP, "EMULOP" },
{ i_EMULOP_RETURN, "EMULOP_RETURN" },
{ i_EMULOP, "EMULOP" },
{ i_MMUOP, "MMUOP" },
{i_NATFEAT_ID, "NATFEAT_ID" },
{i_NATFEAT_CALL, "NATFEAT_CALL" },
{ i_ILLG, "" },
};
struct instr *table68k;
static __inline__ amodes mode_from_str (const char *str)
static inline amodes mode_from_str (const char *str)
{
if (strncmp (str, "Dreg", 4) == 0) return Dreg;
if (strncmp (str, "Areg", 4) == 0) return Areg;
@ -180,7 +179,7 @@ static __inline__ amodes mode_from_str (const char *str)
return (amodes)0;
}
static __inline__ amodes mode_from_mr (int mode, int reg)
static inline amodes mode_from_mr (int mode, int reg)
{
switch (mode) {
case 0: return Dreg;
@ -215,31 +214,32 @@ static void build_insn (int insn)
int i, n;
int flaglive = 0, flagdead = 0;
int cflow = 0;
int cflow = 0;
id = defs68k[insn];
// Control flow information
cflow = id.cflow;
// Mask of flags set/used
unsigned char flags_set(0), flags_used(0);
for (i = 0, n = 4; i < 5; i++, n--) {
switch (id.flaginfo[i].flagset) {
case fa_unset: case fa_isjmp: break;
default: flags_set |= (1 << n);
}
switch (id.flaginfo[i].flaguse) {
case fu_unused: case fu_isjmp: break;
default: flags_used |= (1 << n);
}
// Control flow information
cflow = id.cflow;
// Mask of flags set/used
unsigned char flags_set(0), flags_used(0);
for (i = 0, n = 4; i < 5; i++, n--) {
switch (id.flaginfo[i].flagset) {
case fa_unset: case fa_isjmp: break;
default: flags_set |= (1 << n);
}
switch (id.flaginfo[i].flaguse) {
case fu_unused: case fu_isjmp: break;
default: flags_used |= (1 << n);
}
}
for (i = 0; i < 5; i++) {
switch (id.flaginfo[i].flagset){
case fa_unset: break;
case fa_isjmp: break;
case fa_zero: flagdead |= 1 << i; break;
case fa_one: flagdead |= 1 << i; break;
case fa_dontcare: flagdead |= 1 << i; break;
@ -252,6 +252,8 @@ static void build_insn (int insn)
for (i = 0; i < 5; i++) {
switch (id.flaginfo[i].flaguse) {
case fu_unused: break;
case fu_isjmp: flaglive |= 1 << i; break;
case fu_maybecc: flaglive |= 1 << i; break;
case fu_unknown: flaglive = -1; goto out2;
case fu_used: flaglive |= 1 << i; break;
}
@ -306,6 +308,7 @@ static void build_insn (int insn)
continue;
if (bitcnt[bitI] && (bitval[bitI] == 0x00 || bitval[bitI] == 0xff))
continue;
if (bitcnt[bitE] && (bitval[bitE] == 0x00))
continue;
@ -346,9 +349,9 @@ static void build_insn (int insn)
}
}
mnp++;
if ((unsigned)mnp >= sizeof(mnemonic) - 1) {
mnemonic[sizeof(mnemonic) - 1] = 0;
fprintf(stderr, "Instruction %s overflow\n", mnemonic);
if ((unsigned)mnp >= (sizeof(mnemonic)-1)) {
mnemonic[sizeof(mnemonic)-1] = '\0';
fprintf(stderr, "WTF!!! Instruction '%s' overflow\n", mnemonic);
abort();
}
}
@ -379,6 +382,7 @@ static void build_insn (int insn)
case 'A':
srcmode = Areg;
switch (opcstr[pos++]) {
case 'l': srcmode = absl; break;
case 'r': srcreg = bitval[bitr]; srcgather = 1; srcpos = bitpos[bitr]; break;
case 'R': srcreg = bitval[bitR]; srcgather = 1; srcpos = bitpos[bitR]; break;
default: abort();
@ -388,9 +392,11 @@ static void build_insn (int insn)
case 'P': srcmode = Aipi; pos++; break;
}
break;
#if 0
case 'L':
srcmode = absl;
break;
#endif
case '#':
switch (opcstr[pos++]) {
case 'z': srcmode = imm; break;
@ -436,7 +442,7 @@ static void build_insn (int insn)
srcpos = bitpos[bitK];
}
break;
case 'E': srcmode = immi; srcreg = bitval[bitE];
case 'E': srcmode = immi; srcreg = bitval[bitE];
if (CPU_EMU_SIZE < 5) { // gb-- what is CPU_EMU_SIZE used for ??
/* 1..255 */
srcgather = 1;
@ -444,8 +450,8 @@ static void build_insn (int insn)
srcpos = bitpos[bitE];
}
break;
case 'p': srcmode = immi; srcreg = bitval[bitp];
if (CPU_EMU_SIZE < 5) {
case 'p': srcmode = immi; srcreg = bitval[bitp];
if (CPU_EMU_SIZE < 5) { // gb-- what is CPU_EMU_SIZE used for ??
/* 0..3 */
srcgather = 1;
srctype = 7;
@ -582,21 +588,22 @@ static void build_insn (int insn)
case 'A':
destmode = Areg;
switch (opcstr[pos++]) {
case 'l': destmode = absl; break;
case 'r': destreg = bitval[bitr]; dstgather = 1; dstpos = bitpos[bitr]; break;
case 'R': destreg = bitval[bitR]; dstgather = 1; dstpos = bitpos[bitR]; break;
case 'x': destreg = 0; dstgather = 0; dstpos = 0; break;
case 'x': destreg = 0; dstgather = 0; dstpos = 0; break;
default: abort();
}
if (dstpos < 0 || dstpos >= 32)
abort();
switch (opcstr[pos]) {
case 'p': destmode = Apdi; pos++; break;
case 'P': destmode = Aipi; pos++; break;
}
break;
#if 0
case 'L':
destmode = absl;
break;
#endif
case '#':
switch (opcstr[pos++]) {
case 'z': destmode = imm; break;
@ -767,7 +774,7 @@ static void build_insn (int insn)
table68k[opc].flaginfo[i].flaguse = id.flaginfo[i].flaguse;
}
#endif
// Fix flags used information for Scc, Bcc, TRAPcc, DBcc instructions
if ( table68k[opc].mnemo == i_Scc
|| table68k[opc].mnemo == i_Bcc
@ -795,7 +802,7 @@ static void build_insn (int insn)
case 15:flags_used = 0x0E; break; /* LE */
}
}
#if 1
/* gb-- flagdead and flaglive would not have correct information */
table68k[opc].flagdead = flags_set;
@ -811,22 +818,6 @@ static void build_insn (int insn)
}
void read_table68k (void)
{
int i;
table68k = (struct instr *)malloc (65536 * sizeof (struct instr));
for (i = 0; i < 65536; i++) {
table68k[i].mnemo = i_ILLG;
table68k[i].handler = -1;
}
for (i = 0; i < n_defs68k; i++) {
build_insn (i);
}
}
static int mismatch;
static void handle_merges (long int opcode)
{
uae_u16 smsk;
@ -851,9 +842,9 @@ static void handle_merges (long int opcode)
case 5:
smsk = 63; sbitdst = 64; break;
case 6:
smsk = 255; sbitdst = 256; break;
smsk = 255; sbitdst = 256; break;
case 7:
smsk = 3; sbitdst = 4; break;
smsk = 3; sbitdst = 4; break;
default:
smsk = 0; sbitdst = 0;
abort();
@ -869,7 +860,7 @@ static void handle_merges (long int opcode)
}
for (srcreg=0; srcreg < sbitdst; srcreg++) {
for (dstreg=0; dstreg < dstend; dstreg++) {
uae_u16 code = uae_u16(opcode);
uae_u16 code = opcode;
code = (code & ~smsk) | (srcreg << table68k[opcode].spos);
code = (code & ~dmsk) | (dstreg << table68k[opcode].dpos);
@ -882,20 +873,20 @@ static void handle_merges (long int opcode)
|| table68k[code].suse != table68k[opcode].suse
|| table68k[code].duse != table68k[opcode].duse)
{
mismatch++; continue;
readcpu_mismatch++; continue;
}
if (table68k[opcode].suse
&& (table68k[opcode].spos != table68k[code].spos
|| table68k[opcode].smode != table68k[code].smode
|| table68k[opcode].stype != table68k[code].stype))
{
mismatch++; continue;
readcpu_mismatch++; continue;
}
if (table68k[opcode].duse
&& (table68k[opcode].dpos != table68k[code].dpos
|| table68k[opcode].dmode != table68k[code].dmode))
{
mismatch++; continue;
readcpu_mismatch++; continue;
}
if (code != opcode)
@ -904,11 +895,11 @@ static void handle_merges (long int opcode)
}
}
void do_merges (void)
static void do_merges (void)
{
long int opcode;
int nr = 0;
mismatch = 0;
readcpu_mismatch = 0;
for (opcode = 0; opcode < 65536; opcode++) {
if (table68k[opcode].handler != -1 || table68k[opcode].mnemo == i_ILLG)
continue;
@ -918,116 +909,26 @@ void do_merges (void)
nr_cpuop_funcs = nr;
}
int get_no_mismatches (void)
{
return mismatch;
}
const char *get_instruction_name (unsigned int opcode)
void init_table68k (void)
{
struct instr *ins = &table68k[opcode];
for (int i = 0; lookuptab[i].name[0]; i++) {
if (ins->mnemo == lookuptab[i].mnemo)
return lookuptab[i].name;
int i;
free(table68k);
table68k = (struct instr *)malloc (65536 * sizeof (struct instr));
for (i = 0; i < 65536; i++) {
table68k[i].mnemo = i_ILLG;
table68k[i].handler = -1;
}
abort();
return NULL;
}
static char *get_ea_string (amodes mode, wordsizes size)
{
static char buffer[80];
buffer[0] = 0;
switch (mode){
case Dreg:
strcpy (buffer,"Dn");
break;
case Areg:
strcpy (buffer,"An");
break;
case Aind:
strcpy (buffer,"(An)");
break;
case Aipi:
strcpy (buffer,"(An)+");
break;
case Apdi:
strcpy (buffer,"-(An)");
break;
case Ad16:
strcpy (buffer,"(d16,An)");
break;
case Ad8r:
strcpy (buffer,"(d8,An,Xn)");
break;
case PC16:
strcpy (buffer,"(d16,PC)");
break;
case PC8r:
strcpy (buffer,"(d8,PC,Xn)");
break;
case absw:
strcpy (buffer,"(xxx).W");
break;
case absl:
strcpy (buffer,"(xxx).L");
break;
case imm:
switch (size){
case sz_byte:
strcpy (buffer,"#<data>.B");
break;
case sz_word:
strcpy (buffer,"#<data>.W");
break;
case sz_long:
strcpy (buffer,"#<data>.L");
break;
default:
break;
}
break;
case imm0:
strcpy (buffer,"#<data>.B");
break;
case imm1:
strcpy (buffer,"#<data>.W");
break;
case imm2:
strcpy (buffer,"#<data>.L");
break;
case immi:
strcpy (buffer,"#<data>");
break;
default:
break;
for (i = 0; i < n_defs68k; i++) {
build_insn (i);
}
return buffer;
do_merges();
}
const char *get_instruction_string (unsigned int opcode)
void exit_table68k (void)
{
static char out[100];
struct instr *ins;
strcpy (out, get_instruction_name (opcode));
ins = &table68k[opcode];
if (ins->size == sz_byte)
strcat (out,".B");
if (ins->size == sz_word)
strcat (out,".W");
if (ins->size == sz_long)
strcat (out,".L");
strcat (out," ");
if (ins->suse)
strcat (out, get_ea_string (amodes(ins->smode), wordsizes(ins->size)));
if (ins->duse) {
if (ins->suse)
strcat (out,",");
strcat (out, get_ea_string (amodes(ins->dmode), wordsizes(ins->size)));
}
return out;
free(table68k);
table68k = NULL;
}

View File

@ -1,16 +1,16 @@
#ifndef READCPU_H
#define READCPU_H
#ifndef UAE_READCPU_H
#define UAE_READCPU_H
#ifdef __cplusplus
extern "C" {
#endif
ENUMDECL {
typedef enum {
Dreg, Areg, Aind, Aipi, Apdi, Ad16, Ad8r,
absw, absl, PC16, PC8r, imm, imm0, imm1, imm2, immi, am_unknown, am_illg
} ENUMNAME (amodes);
} amodes;
ENUMDECL {
typedef enum {
i_ILLG,
i_OR, i_AND, i_EOR, i_ORSR, i_ANDSR, i_EORSR,
@ -35,43 +35,42 @@ ENUMDECL {
i_PACK, i_UNPK, i_TAS, i_BKPT, i_CALLM, i_RTM, i_TRAPcc, i_MOVES,
i_FPP, i_FDBcc, i_FScc, i_FTRAPcc, i_FBcc, i_FSAVE, i_FRESTORE,
i_CINVL, i_CINVP, i_CINVA, i_CPUSHL, i_CPUSHP, i_CPUSHA, i_MOVE16,
i_MMUOP,
i_EMULOP_RETURN, i_EMULOP
} ENUMNAME (instrmnem);
i_MMUOP, i_EMULOP_RETURN, i_EMULOP, i_NATFEAT_ID, i_NATFEAT_CALL
} instrmnem;
extern struct mnemolookup {
instrmnem mnemo;
const char *name;
} lookuptab[];
ENUMDECL {
typedef enum {
sz_byte, sz_word, sz_long
} ENUMNAME (wordsizes);
} wordsizes;
ENUMDECL {
fa_set, fa_unset, fa_zero, fa_one, fa_dontcare, fa_unknown, fa_isjmp
} ENUMNAME (flagaffect);
typedef enum {
fa_set, fa_unset, fa_zero, fa_one, fa_dontcare, fa_unknown, fa_isjmp,
fa_isbranch
} flagaffect;
ENUMDECL {
typedef enum {
fu_used, fu_unused, fu_maybecc, fu_unknown, fu_isjmp
} ENUMNAME (flaguse);
} flaguse;
ENUMDECL {
fl_normal = 0,
typedef enum {
fl_normal = 0,
fl_branch = 1,
fl_jump = 2,
fl_return = 3,
fl_trap = 4,
fl_const_jump = 8,
/* Instructions that can trap don't mark the end of a block */
fl_end_block = 3
} ENUMNAME (cflow_t);
fl_jump = 2,
fl_return = 3,
fl_trap = 4,
fl_const_jump = 8,
/* Instructions that can trap don't mark the end of a block */
fl_end_block = 3
} cflow_t;
ENUMDECL {
typedef enum {
bit0, bit1, bitc, bitC, bitf, biti, bitI, bitj, bitJ, bitk, bitK,
bits, bitS, bitd, bitD, bitr, bitR, bitz, bitE, bitp, lastbit
} ENUMNAME (bitvals);
} bitvals;
struct instr_def {
unsigned int bits;
@ -84,7 +83,7 @@ struct instr_def {
unsigned int flaguse:3;
unsigned int flagset:3;
} flaginfo[5];
unsigned char cflow;
unsigned char cflow;
unsigned char sduse;
const char *opcstr;
};
@ -103,28 +102,24 @@ extern struct instr {
unsigned int mnemo:8;
unsigned int cc:4;
unsigned int plev:2;
unsigned int size:2;
unsigned int smode:5;
wordsizes size:2;
amodes smode:5;
unsigned int stype:3;
unsigned int dmode:5;
amodes dmode:5;
unsigned int suse:1;
unsigned int duse:1;
unsigned int unused1:1;
unsigned int clev:3;
unsigned int cflow:3;
unsigned int cflow:3;
unsigned int unused2:2;
} *table68k;
extern void read_table68k (void);
extern void do_merges (void);
extern int get_no_mismatches (void);
extern void init_table68k(void);
extern void exit_table68k(void);
extern int nr_cpuop_funcs;
extern const char *get_instruction_name (unsigned int opcode);
extern const char *get_instruction_string (unsigned int opcode);
#ifdef __cplusplus
}
#endif
#endif /* READCPU_H */
#endif

View File

@ -0,0 +1,5 @@
/*
* readcpu.cpp must be compiled twice, once for the generator program
* and once for the actual executable
*/
#include "readcpu.cpp"

View File

@ -0,0 +1,115 @@
/* 2001 MJ */
#ifndef REGISTERS_H
#define REGISTERS_H
#include "sysdeps.h"
#include "spcflags.h"
typedef char flagtype;
struct xttrx {
uae_u32 log_addr_base : 8;
uae_u32 log_addr_mask : 8;
uae_u32 enable : 1;
uae_u32 s_field : 2;
uae_u32 : 3;
uae_u32 usr1 : 1;
uae_u32 usr0 : 1;
uae_u32 : 1;
uae_u32 cmode : 2;
uae_u32 : 2;
uae_u32 write : 1;
uae_u32 : 2;
};
struct mmusr_t {
uae_u32 phys_addr : 20;
uae_u32 bus_err : 1;
uae_u32 global : 1;
uae_u32 usr1 : 1;
uae_u32 usr0 : 1;
uae_u32 super : 1;
uae_u32 cmode : 2;
uae_u32 modif : 1;
uae_u32 : 1;
uae_u32 write : 1;
uae_u32 ttrhit : 1;
uae_u32 resident : 1;
};
struct log_addr4 {
uae_u32 rif : 7;
uae_u32 pif : 7;
uae_u32 paif : 6;
uae_u32 poff : 12;
};
struct log_addr8 {
uae_u32 rif : 7;
uae_u32 pif : 7;
uae_u32 paif : 5;
uae_u32 poff : 13;
};
extern struct regstruct
{
uae_u32 regs[16];
uaecptr usp,isp,msp;
uae_u16 sr;
flagtype t1;
flagtype t0;
flagtype s;
flagtype m;
flagtype stopped;
uint32_t intmask;
uae_u32 pc;
uae_u32 fault_pc;
uae_u8 *pc_p;
uae_u8 *pc_oldp;
uae_u32 vbr,sfc,dfc;
volatile uae_u32 spcflags;
#if 0
uae_u32 kick_mask;
/* Fellow sources say this is 4 longwords. That's impossible. It needs
* to be at least a longword. The HRM has some cryptic comment about two
* instructions being on the same longword boundary.
* The way this is implemented now seems like a good compromise.
*/
uae_u32 prefetch;
#endif
/* MMU reg*/
uae_u32 urp,srp;
uae_u32 tc;
int mmu_enabled; /* flagtype tce; */
int mmu_pagesize_8k; /* flagtype tcp; */
uae_u32 dtt0,dtt1,itt0,itt1;
uae_u32 mmusr;
uae_u32 mmu_fslw, mmu_fault_addr;
uae_u16 mmu_ssw;
uae_u32 wb3_data;
uae_u16 wb3_status;
/* Cache reg*/
uae_u32 cacr,caar;
} regs;
static inline uaecptr m68k_getpc (void)
{
#ifdef FULLMMU
return regs.pc;
#else
return regs.pc + ((char *)regs.pc_p - (char *)regs.pc_oldp);
#endif
}
#endif

View File

@ -1,92 +1,78 @@
/*
* UAE - The Un*x Amiga Emulator
*
* MC68000 emulation
*
* Copyright 1995 Bernd Schmidt
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
* UAE - The Un*x Amiga Emulator
*
* MC68000 emulation
*
* Copyright 1995 Bernd Schmidt
*/
#ifndef SPCFLAGS_H
#define SPCFLAGS_H
typedef uae_u32 spcflags_t;
#if 0
#include "SDL_compat.h"
#endif
enum {
SPCFLAG_STOP = 0x01,
SPCFLAG_INT = 0x02,
SPCFLAG_BRK = 0x04,
SPCFLAG_TRACE = 0x08,
SPCFLAG_DOTRACE = 0x10,
SPCFLAG_DOINT = 0x20,
#if USE_JIT
SPCFLAG_JIT_END_COMPILE = 0x40,
SPCFLAG_JIT_EXEC_RETURN = 0x80,
SPCFLAG_STOP = 0x01,
#if 0
SPCFLAG_INTERNAL_IRQ = 0x02,
#else
SPCFLAG_JIT_END_COMPILE = 0,
SPCFLAG_JIT_EXEC_RETURN = 0,
SPCFLAG_INT = 0x02,
#endif
SPCFLAG_ALL = SPCFLAG_STOP
| SPCFLAG_INT
| SPCFLAG_BRK
| SPCFLAG_TRACE
| SPCFLAG_DOTRACE
| SPCFLAG_DOINT
| SPCFLAG_JIT_END_COMPILE
| SPCFLAG_JIT_EXEC_RETURN
,
SPCFLAG_BRK = 0x04,
SPCFLAG_TRACE = 0x08,
SPCFLAG_DOTRACE = 0x10,
SPCFLAG_DOINT = 0x20,
#ifdef USE_JIT
SPCFLAG_JIT_END_COMPILE = 0x40,
SPCFLAG_JIT_EXEC_RETURN = 0x80,
#else
SPCFLAG_JIT_END_COMPILE = 0,
SPCFLAG_JIT_EXEC_RETURN = 0,
#endif
SPCFLAG_VBL = 0x100,
SPCFLAG_MFP = 0x200,
SPCFLAG_INT3 = 0x800,
SPCFLAG_INT5 = 0x1000,
SPCFLAG_SCC = 0x2000,
// SPCFLAG_MODE_CHANGE = 0x4000,
SPCFLAG_ALL = SPCFLAG_STOP
#if 0
| SPCFLAG_INTERNAL_IRQ
#else
| SPCFLAG_INT
#endif
| SPCFLAG_BRK
| SPCFLAG_TRACE
| SPCFLAG_DOTRACE
| SPCFLAG_DOINT
| SPCFLAG_JIT_END_COMPILE
| SPCFLAG_JIT_EXEC_RETURN
| SPCFLAG_INT3
| SPCFLAG_VBL
| SPCFLAG_INT5
| SPCFLAG_SCC
| SPCFLAG_MFP
,
SPCFLAG_ALL_BUT_EXEC_RETURN = SPCFLAG_ALL & ~SPCFLAG_JIT_EXEC_RETURN
};
#if 0
#define SPCFLAGS_TEST(m) \
(regs.spcflags & (m))
#else
#define SPCFLAGS_TEST(m) \
((regs.spcflags & (m)) != 0)
#endif
/* Macro only used in m68k_reset() */
#define SPCFLAGS_INIT(m) do { \
regs.spcflags = (m); \
} while (0)
#if !(ENABLE_EXCLUSIVE_SPCFLAGS)
#define SPCFLAGS_SET(m) do { \
regs.spcflags |= (m); \
} while (0)
#define SPCFLAGS_CLEAR(m) do { \
regs.spcflags &= ~(m); \
} while (0)
#elif defined(X86_ASSEMBLY)
#define HAVE_HARDWARE_LOCKS
#define SPCFLAGS_SET(m) do { \
__asm__ __volatile__("lock\n\torl %1,%0" : "=m" (regs.spcflags) : "i" ((m))); \
} while (0)
#define SPCFLAGS_CLEAR(m) do { \
__asm__ __volatile__("lock\n\tandl %1,%0" : "=m" (regs.spcflags) : "i" (~(m))); \
} while (0)
#else
#undef HAVE_HARDWARE_LOCKS
#include "main.h"
extern B2_mutex *spcflags_lock;
@ -99,9 +85,91 @@ extern B2_mutex *spcflags_lock;
#define SPCFLAGS_CLEAR(m) do { \
B2_lock_mutex(spcflags_lock); \
regs.spcflags &= ~(m); \
B2_unlock_mutex(spcflags_lock); \
B2_unlock_mutex(spcflags_lock); \
} while (0)
#define SleepAndWait() usleep(1000);
#if 0
#ifndef ENABLE_EXCLUSIVE_SPCFLAGS
#define SPCFLAGS_SET(m) do { \
regs.spcflags |= (m); \
} while (0)
#define SPCFLAGS_CLEAR(m) do { \
regs.spcflags &= ~(m); \
} while (0)
#if 0
#define SleepAndWait() usleep(1000)
#endif
#elif defined(X86_ASSEMBLY)
// #elif (defined(CPU_i386) || defined(CPU_x86_64)) && defined(X86_ASSEMBLY) && !defined(ENABLE_REALSTOP)
// #define HAVE_HARDWARE_LOCKS 1
#define HAVE_HARDWARE_LOCKS
#define SPCFLAGS_SET(m) do { \
__asm__ __volatile__("lock\n\torl %1,%0" : "=m" (regs.spcflags) : "i" ((m))); \
} while (0)
#define SPCFLAGS_CLEAR(m) do { \
__asm__ __volatile__("lock\n\tandl %1,%0" : "=m" (regs.spcflags) : "i" (~(m))); \
} while (0)
// #define SleepAndWait() usleep(1000)
// #elif !defined(ENABLE_REALSTOP)
// #undef HAVE_HARDWARE_LOCKS
// extern SDL_mutex *spcflags_lock;
// #define SPCFLAGS_SET(m) do { \
// SDL_LockMutex(spcflags_lock); \
// regs.spcflags |= (m); \
// SDL_UnlockMutex(spcflags_lock); \
// } while (0)
// #define SPCFLAGS_CLEAR(m) do { \
// SDL_LockMutex(spcflags_lock); \
// regs.spcflags &= ~(m); \
// SDL_UnlockMutex(spcflags_lock); \
// } while (0)
// #define SleepAndWait() usleep(1000)
#else
/// Full STOP instruction implementation (default configuration)
#undef HAVE_HARDWARE_LOCKS
#if 0
extern SDL_mutex *spcflags_lock;
extern SDL_cond *stop_condition;
#define SPCFLAGS_SET(m) do { \
SDL_LockMutex(spcflags_lock); \
regs.spcflags |= (m); \
if (regs.spcflags & SPCFLAG_STOP) \
SDL_CondSignal(stop_condition); \
SDL_UnlockMutex(spcflags_lock); \
} while (0)
#define SPCFLAGS_CLEAR(m) do { \
SDL_LockMutex(spcflags_lock); \
regs.spcflags &= ~(m); \
SDL_UnlockMutex(spcflags_lock); \
} while (0)
#define SleepAndWait() do { \
SDL_LockMutex(spcflags_lock); \
SDL_CondWait(stop_condition, spcflags_lock); \
SDL_UnlockMutex(spcflags_lock); \
} while (0)
#endif
#endif
#endif
#endif /* SPCFLAGS_H */

View File

@ -10,7 +10,7 @@
% J: immediate 0..15
% k: immediate 0..7
% K: immediate 0..63
% p: immediate 0..3 (CINV and CPUSH instructions: Cache Field)
% p: immediate 0..3 (CINV and CPUSH: cache field)
% s: source mode
% S: source reg
% d: dest mode
@ -28,14 +28,15 @@
% ArP: --> (Ar)+
% L: --> (xxx.L)
%
% Fields on a line:
% 16 chars bitpattern :
% CPU level / privilege level :
% Fields on a line:
% 16 chars bitpattern :
% CPU level / privildge level :
% CPU level 0: 68000
% 1: 68010
% 2: 68020
% 3: 68020/68881
% 4: 68040
% 5: 68060
% privilege level 0: not privileged
% 1: unprivileged only on 68000 (check regs.s)
% 2: privileged (check regs.s)
@ -46,8 +47,10 @@
% 0 means flag reset
% 1 means flag set
% ? means programmer was too lazy to check or instruction may trap
% everything else means flag set/used
% + means instruction is conditional branch (ignored, only for sync)
% / means instruction is unconditional branch/call (ignored, only for sync)
% x means flag is unknown and well-behaved programs shouldn't check it
% everything else means flag set/used
%
% Control flow
% two letters, combination of
@ -108,7 +111,7 @@
0011 DDDd ddss sSSS:00:-----:-----:--:12: MOVEA.W s,d[Areg]
0011 DDDd ddss sSSS:00:-NZ00:-----:--:12: MOVE.W s,d[!Areg]
0100 0000 zzdd dDDD:00:XxZxC:X-Z--:--:30: NEGX.z d[!Areg]
0100 0000 zzdd dDDD:00:XNZVC:X-Z--:--:30: NEGX.z d[!Areg]
0100 0000 11dd dDDD:01:-----:XNZVC:T-:10: MVSR2.W d[!Areg]
0100 0010 zzdd dDDD:00:-0100:-----:--:20: CLR.z d[!Areg]
0100 0010 11dd dDDD:10:-----:XNZVC:--:10: MVSR2.B d[!Areg]
@ -119,13 +122,13 @@
0100 1000 0000 1rrr:20:-----:-----:--:31: LINK.L Ar,#2
0100 1000 00dd dDDD:00:X?Z?C:X-Z--:--:30: NBCD.B d[!Areg]
0100 1000 0100 1kkk:20:-----:-----:T-:10: BKPT #k
0100 1000 01ss sSSS:00:-NZ00:-----:--:30: SWAP.W s[Dreg]
0100 1000 01ss sSSS:00:-NZ00:-----:--:30: SWAP.W s[Dreg]
0100 1000 01ss sSSS:00:-----:-----:--:00: PEA.L s[!Dreg,Areg,Aipi,Apdi,Immd]
0100 1000 10dd dDDD:00:-NZ00:-----:--:30: EXT.W d[Dreg]
0100 1000 10dd dDDD:00:-NZ00:-----:--:30: EXT.W d[Dreg]
0100 1000 10dd dDDD:00:-----:-----:--:02: MVMLE.W #1,d[!Dreg,Areg,Aipi]
0100 1000 11dd dDDD:00:-NZ00:-----:--:30: EXT.L d[Dreg]
0100 1000 11dd dDDD:00:-NZ00:-----:--:30: EXT.L d[Dreg]
0100 1000 11dd dDDD:00:-----:-----:--:02: MVMLE.L #1,d[!Dreg,Areg,Aipi]
0100 1001 11dd dDDD:00:-NZ00:-----:--:30: EXT.B d[Dreg]
0100 1001 11dd dDDD:00:-NZ00:-----:--:30: EXT.B d[Dreg]
0100 1010 zzss sSSS:00:-NZ00:-----:--:10: TST.z s
0100 1010 11dd dDDD:00:-NZ00:-----:--:30: TAS.B d[!Areg]
0100 1010 1111 1100:00:-----:-----:T-:00: ILLEGAL
@ -148,21 +151,24 @@
0100 1110 0111 0111:00:XNZVC:-----:-R:00: RTR
0100 1110 0111 1010:12:-----:-----:T-:10: MOVEC2 #1
0100 1110 0111 1011:12:-----:-----:T-:10: MOVE2C #1
0100 1110 10ss sSSS:00:-----:-----:-J:80: JSR.L s[!Dreg,Areg,Aipi,Apdi,Immd]
0100 1110 10ss sSSS:00://///://///:-J:80: JSR.L s[!Dreg,Areg,Aipi,Apdi,Immd]
0100 rrr1 00ss sSSS:00:-N???:-----:T-:11: CHK.L s[!Areg],Dr
0100 rrr1 10ss sSSS:00:-N???:-----:T-:11: CHK.W s[!Areg],Dr
0100 1110 11ss sSSS:00:-----:-----:-J:80: JMP.L s[!Dreg,Areg,Aipi,Apdi,Immd]
0100 1110 11ss sSSS:00://///://///:-J:80: JMP.L s[!Dreg,Areg,Aipi,Apdi,Immd]
0100 rrr1 11ss sSSS:00:-----:-----:--:02: LEA.L s[!Dreg,Areg,Aipi,Apdi,Immd],Ar
0101 jjj0 01dd dDDD:00:-----:-----:--:13: ADDA.W #j,d[Areg]
0101 jjj0 10dd dDDD:00:-----:-----:--:13: ADDA.L #j,d[Areg]
% This variant of ADDQ is word and long sized only
0101 jjj0 01dd dDDD:00:-----:-----:--:13: ADDA.W #j,d[Areg]
0101 jjj0 10dd dDDD:00:-----:-----:--:13: ADDA.L #j,d[Areg]
0101 jjj0 zzdd dDDD:00:XNZVC:-----:--:13: ADD.z #j,d[!Areg]
0101 jjj1 01dd dDDD:00:-----:-----:--:13: SUBA.W #j,d[Areg]
0101 jjj1 10dd dDDD:00:-----:-----:--:13: SUBA.L #j,d[Areg]
% This variant of SUBQ is word and long sized only
0101 jjj1 01dd dDDD:00:-----:-----:--:13: SUBA.W #j,d[Areg]
0101 jjj1 10dd dDDD:00:-----:-----:--:13: SUBA.L #j,d[Areg]
0101 jjj1 zzdd dDDD:00:XNZVC:-----:--:13: SUB.z #j,d[!Areg]
0101 cccc 1100 1rrr:00:-----:-????:-B:31: DBcc.W Dr,#1
0101 cccc 11dd dDDD:00:-----:-????:--:20: Scc.B d[!Areg]
0101 cccc 1100 1rrr:00:-----:-++++:-B:31: DBcc.W Dr,#1
0101 cccc 11dd dDDD:00:-----:-++++:--:20: Scc.B d[!Areg]
0101 cccc 1111 1010:20:-----:-????:T-:10: TRAPcc #1
0101 cccc 1111 1011:20:-----:-????:T-:10: TRAPcc #2
0101 cccc 1111 1100:20:-----:-????:T-:00: TRAPcc
@ -170,30 +176,30 @@
% Bxx.L is 68020 only, but setting the CPU level to 2 would give illegal
% instruction exceptions when compiling a 68000 only emulation, which isn't
% what we want either.
0110 0001 0000 0000:00:-----:-----:-B:40: BSR.W #1
0110 0001 IIII IIII:00:-----:-----:-B:40: BSR.B #i
0110 0001 1111 1111:00:-----:-----:-B:40: BSR.L #2
0110 CCCC 0000 0000:00:-----:-????:-B:40: Bcc.W #1
0110 CCCC IIII IIII:00:-----:-????:-B:40: Bcc.B #i
0110 CCCC 1111 1111:00:-----:-????:-B:40: Bcc.L #2
0110 0001 0000 0000:00://///://///:-B:40: BSR.W #1
0110 0001 IIII IIII:00://///://///:-B:40: BSR.B #i
0110 0001 1111 1111:00://///://///:-B:40: BSR.L #2
0110 CCCC 0000 0000:00:-----:-++++:-B:40: Bcc.W #1
0110 CCCC IIII IIII:00:-----:-++++:-B:40: Bcc.B #i
0110 CCCC 1111 1111:00:-----:-++++:-B:40: Bcc.L #2
0111 rrr0 iiii iiii:00:-NZ00:-----:--:12: MOVE.L #i,Dr
1000 rrr0 zzss sSSS:00:-NZ00:-----:--:13: OR.z s[!Areg],Dr
1000 rrr0 11ss sSSS:00:-NZV0:-----:T-:13: DIVU.W s[!Areg],Dr
1000 rrr1 00dd dDDD:00:XxZxC:X-Z--:--:13: SBCD.B d[Dreg],Dr
1000 rrr1 00dd dDDD:00:XxZxC:X-Z--:--:13: SBCD.B d[Areg-Apdi],Arp
1000 rrr1 00dd dDDD:00:X?Z?C:X-Z--:--:13: SBCD.B d[Dreg],Dr
1000 rrr1 00dd dDDD:00:X?Z?C:X-Z--:--:13: SBCD.B d[Areg-Apdi],Arp
1000 rrr1 zzdd dDDD:00:-NZ00:-----:--:13: OR.z Dr,d[!Areg,Dreg]
1000 rrr1 01dd dDDD:20:-----:-----:--:12: PACK d[Dreg],Dr
1000 rrr1 01dd dDDD:20:-----:-----:--:12: PACK d[Areg-Apdi],Arp
1000 rrr1 10dd dDDD:20:-----:-----:--:12: UNPK d[Dreg],Dr
1000 rrr1 10dd dDDD:20:-----:-----:--:12: UNPK d[Areg-Apdi],Arp
1000 rrr1 01dd dDDD:20:-----:-----:--:12: PACK d[Dreg],Dr
1000 rrr1 01dd dDDD:20:-----:-----:--:12: PACK d[Areg-Apdi],Arp
1000 rrr1 10dd dDDD:20:-----:-----:--:12: UNPK d[Dreg],Dr
1000 rrr1 10dd dDDD:20:-----:-----:--:12: UNPK d[Areg-Apdi],Arp
1000 rrr1 11ss sSSS:00:-NZV0:-----:T-:13: DIVS.W s[!Areg],Dr
1001 rrr0 zzss sSSS:00:XNZVC:-----:--:13: SUB.z s,Dr
1001 rrr0 11ss sSSS:00:-----:-----:--:13: SUBA.W s,Ar
1001 rrr1 zzdd dDDD:00:XNZVC:X-Z--:--:13: SUBX.z d[Dreg],Dr
1001 rrr1 zzdd dDDD:00:XNZVC:X-Z--:--:13: SUBX.z d[Areg-Apdi],Arp
1001 rrr1 zzdd dDDD:00:XNZVC:X-Z--:--:13: SUBX.z d[Dreg],Dr
1001 rrr1 zzdd dDDD:00:XNZVC:X-Z--:--:13: SUBX.z d[Areg-Apdi],Arp
1001 rrr1 zzdd dDDD:00:XNZVC:-----:--:13: SUB.z Dr,d[!Areg,Dreg]
1001 rrr1 11ss sSSS:00:-----:-----:--:13: SUBA.L s,Ar
@ -205,18 +211,18 @@
1100 rrr0 zzss sSSS:00:-NZ00:-----:--:13: AND.z s[!Areg],Dr
1100 rrr0 11ss sSSS:00:-NZ00:-----:--:13: MULU.W s[!Areg],Dr
1100 rrr1 00dd dDDD:00:XxZxC:X-Z--:--:13: ABCD.B d[Dreg],Dr
1100 rrr1 00dd dDDD:00:XxZxC:X-Z--:--:13: ABCD.B d[Areg-Apdi],Arp
1100 rrr1 00dd dDDD:00:X?Z?C:X-Z--:--:13: ABCD.B d[Dreg],Dr
1100 rrr1 00dd dDDD:00:X?Z?C:X-Z--:--:13: ABCD.B d[Areg-Apdi],Arp
1100 rrr1 zzdd dDDD:00:-NZ00:-----:--:13: AND.z Dr,d[!Areg,Dreg]
1100 rrr1 01dd dDDD:00:-----:-----:--:33: EXG.L Dr,d[Dreg]
1100 rrr1 01dd dDDD:00:-----:-----:--:33: EXG.L Ar,d[Areg]
1100 rrr1 10dd dDDD:00:-----:-----:--:33: EXG.L Dr,d[Areg]
1100 rrr1 01dd dDDD:00:-----:-----:--:33: EXG.L Dr,d[Dreg]
1100 rrr1 01dd dDDD:00:-----:-----:--:33: EXG.L Ar,d[Areg]
1100 rrr1 10dd dDDD:00:-----:-----:--:33: EXG.L Dr,d[Areg]
1100 rrr1 11ss sSSS:00:-NZ00:-----:--:13: MULS.W s[!Areg],Dr
1101 rrr0 zzss sSSS:00:XNZVC:-----:--:13: ADD.z s,Dr
1101 rrr0 11ss sSSS:00:-----:-----:--:13: ADDA.W s,Ar
1101 rrr1 zzdd dDDD:00:XNZVC:X-Z--:--:13: ADDX.z d[Dreg],Dr
1101 rrr1 zzdd dDDD:00:XNZVC:X-Z--:--:13: ADDX.z d[Areg-Apdi],Arp
1101 rrr1 zzdd dDDD:00:XNZVC:X-Z--:--:13: ADDX.z d[Dreg],Dr
1101 rrr1 zzdd dDDD:00:XNZVC:X-Z--:--:13: ADDX.z d[Areg-Apdi],Arp
1101 rrr1 zzdd dDDD:00:XNZVC:-----:--:13: ADD.z Dr,d[!Areg,Dreg]
1101 rrr1 11ss sSSS:00:-----:-----:--:13: ADDA.L s,Ar
@ -224,8 +230,8 @@
1110 jjjf zz00 1RRR:00:XNZ0C:-----:--:13: LSf.z #j,DR
1110 jjjf zz01 0RRR:00:XNZ0C:X----:--:13: ROXf.z #j,DR
1110 jjjf zz01 1RRR:00:-NZ0C:-----:--:13: ROf.z #j,DR
1110 rrrf zz10 0RRR:00:XNZVC:-----:--:13: ASf.z Dr,DR
1110 rrrf zz10 1RRR:00:XNZ0C:-----:--:13: LSf.z Dr,DR
1110 rrrf zz10 0RRR:00:XNZVC:X----:--:13: ASf.z Dr,DR
1110 rrrf zz10 1RRR:00:XNZ0C:X----:--:13: LSf.z Dr,DR
1110 rrrf zz11 0RRR:00:XNZ0C:X----:--:13: ROXf.z Dr,DR
1110 rrrf zz11 1RRR:00:-NZ0C:-----:--:13: ROf.z Dr,DR
1110 000f 11dd dDDD:00:XNZVC:-----:--:13: ASfW.W d[!Dreg,Areg]
@ -255,7 +261,6 @@
1111 0011 01ss sSSS:32:-----:-----:--:10: FRESTORE s[!Dreg,Areg,Apdi,Immd]
% 68040 instructions
1111 0101 iiii iSSS:40:-----:-----:T-:11: MMUOP #i,s
1111 0100 pp00 1rrr:42:-----:-----:T-:02: CINVL #p,Ar
1111 0100 pp01 0rrr:42:-----:-----:T-:02: CINVP #p,Ar
1111 0100 pp01 1rrr:42:-----:-----:T-:00: CINVA #p
@ -264,11 +269,19 @@
1111 0100 pp11 1rrr:42:-----:-----:T-:00: CPUSHA #p
% destination register number is encoded in the following word
1111 0110 0010 0rrr:40:-----:-----:--:12: MOVE16 ArP,AxP
1111 0110 00ss sSSS:40:-----:-----:--:12: MOVE16 s[Dreg-Aipi],L
1111 0110 00dd dDDD:40:-----:-----:--:12: MOVE16 L,d[Areg-Aipi]
1111 0110 00ss sSSS:40:-----:-----:--:12: MOVE16 s[Aind],L
1111 0110 00dd dDDD:40:-----:-----:--:12: MOVE16 L,d[Aipi-Aind]
1111 0110 00ss sSSS:40:-----:-----:--:12: MOVE16 s[Dreg-Aipi],Al
1111 0110 00dd dDDD:40:-----:-----:--:12: MOVE16 Al,d[Areg-Aipi]
1111 0110 00ss sSSS:40:-----:-----:--:12: MOVE16 s[Aind],Al
1111 0110 00dd dDDD:40:-----:-----:--:12: MOVE16 Al,d[Aipi-Aind]
% EmulOp instructions
0111 0001 0000 0000:00:-----:-----:-R:00: EMULOP_RETURN
0111 0001 EEEE EEEE:00:-----:-----:-J:10: EMULOP #E
% MMU disabled
% 1111 0101 iiii iSSS:42:?????:?????:T-:11: MMUOP #i,s
% EmulOp instructions (used by linux68k)
0111 0001 0000 0000:02:-----:XNZVC:-R:00: EMULOP_RETURN
0111 0001 EEEE EEEE:00:-----:XNZVC:-J:10: EMULOP #E
% NatFea instructions (do I have the srcaddr correct?)
% NatFeat disabled
% 0111 0011 0000 0000:00:-----:XNZVC:-J:00: NATFEAT_ID
% 0111 0011 0000 0001:00:-----:XNZVC:-J:00: NATFEAT_CALL