Port of CPU code from ARAnyM (currently hangs)

This commit is contained in:
uyjulian 2018-04-15 20:23:12 -05:00
parent 1bf6e93461
commit 1758ef58b5
No known key found for this signature in database
GPG Key ID: FEA459A8CA14685B
95 changed files with 63979 additions and 2376 deletions

View File

@ -15,7 +15,7 @@ add_custom_command(OUTPUT cpudefs.cpp
add_executable(gencpu ../uae_cpu/gencpu.c ../uae_cpu/readcpu.cpp cpudefs.cpp)
add_custom_command(OUTPUT cpuemu.cpp cpustbl.cpp COMMAND gencpu DEPENDS gencpu)
add_custom_command(OUTPUT cpuemu.cpp cpustbl.cpp cpufunctbl.cpp COMMAND gencpu DEPENDS gencpu)
set(BasiliskII_SRCS
../main.cpp
@ -76,10 +76,11 @@ set(BasiliskII_SRCS
../uae_cpu/basilisk_glue.cpp
../uae_cpu/newcpu.cpp
../uae_cpu/readcpu.cpp
# ../uae_cpu/fpp.cpp
../uae_cpu/fpu/fpu_uae.cpp
cpustbl.cpp
cpudefs.cpp
cpuemu.cpp
cpufunctbl.cpp
#addressing mode =direct -DDIRECT_ADDRESSING
#includes
)
@ -87,8 +88,10 @@ set(BasiliskII_SRCS
add_executable(BasiliskII ${BasiliskII_SRCS})
set_source_files_properties(${BasiliskII_SRCS}
PROPERTIES COMPILE_FLAGS "-DDIRECT_ADDRESSING -DDATADIR=\\\".\\\"")
PROPERTIES COMPILE_FLAGS "-DDIRECT_ADDRESSING -DFPU_UAE -DDATADIR=\\\".\\\"")
target_link_libraries(BasiliskII ${COREFOUNDATION_LIBRARY} ${IOKIT_LIBRARY} ${SDL_LIBRARY})
#keycodes -> ../SDL/keycodes

View File

@ -199,9 +199,8 @@ static void sigsegv_dump_state(sigsegv_info_t *sip)
fprintf(stderr, " [IP=%p]", fault_instruction);
fprintf(stderr, "\n");
#if EMULATED_68K
uaecptr nextpc;
extern void m68k_dumpstate(uaecptr *nextpc);
m68k_dumpstate(&nextpc);
extern void m68k_dumpstate (FILE *, uaecptr *);
m68k_dumpstate(stderr, 0);
#endif
VideoQuitFullScreen();

View File

@ -712,6 +712,17 @@ static inline uae_u32 do_byteswap_16(uae_u32 v)
#endif
#define REGPARAM2
#if __GNUC__ < 3
# define __builtin_expect(foo,bar) (foo)
#endif
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
#define ALWAYS_INLINE inline __attribute__((always_inline))
#define memptr uint32
#endif /* NEED_CONFIG_H_ONLY */
#endif

View File

@ -31,13 +31,6 @@ extern int FPUType;
// Flag: 24-bit-addressing?
extern bool TwentyFourBitAddressing;
// 68k register structure (for Execute68k())
struct M68kRegisters {
uint32 d[8];
uint32 a[8];
uint16 sr;
};
// General functions
extern bool InitAll(const char *vmdir);
extern void ExitAll(void);

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
./build68k <$(srcdir)/table68k > $@
cpuemu.cpp: gencpu$(EXEEXT)
./gencpu$(EXEEXT)
cpustbl.cpp cpufunctbl.cpp cputbl.h: cpuemu.cpp
compemu.cpp: gencomp$(EXEEXT)
./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,327 @@
/*
* 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 "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
// From newcpu.cpp
extern int quit_program;
#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

@ -1,7 +1,7 @@
/*
* basilisk_glue.cpp - Glue UAE CPU to Basilisk II CPU engine interface
*
* Basilisk II (C) 1997-1999 Christian Bauer
* 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
@ -19,8 +19,10 @@
*/
#include "sysdeps.h"
#include "cpu_emulation.h"
#include "main.h"
#include "prefs.h"
#include "emul_op.h"
#include "rom_patches.h"
#include "timer.h"
@ -28,9 +30,11 @@
#include "memory.h"
#include "readcpu.h"
#include "newcpu.h"
#include "compiler/compemu.h"
// RAM and ROM pointers
uint32 RAMBaseMac; // RAM base (Mac address space)
uint32 RAMBaseMac = 0; // RAM base (Mac address space) gb-- initializer is important
uint8 *RAMBaseHost; // RAM base (host address space)
uint32 RAMSize; // Size of RAM
uint32 ROMBaseMac; // ROM base (Mac address space)
@ -48,8 +52,12 @@ int MacFrameLayout; // Frame buffer layout
uintptr MEMBaseDiff; // Global offset between a Mac address and its Host equivalent
#endif
#if USE_JIT
bool UseJIT = false;
#endif
// From newcpu.cpp
extern int quit_program;
extern bool quit_program;
/*
@ -59,13 +67,41 @@ extern int quit_program;
bool Init680x0(void)
{
#if REAL_ADDRESSING
// Mac address space = host address space
RAMBaseMac = (uintptr)RAMBaseHost;
ROMBaseMac = (uintptr)ROMBaseHost;
#elif DIRECT_ADDRESSING
// Mac address space = host address space minus constant offset (MEMBaseDiff)
// NOTE: MEMBaseDiff is set up in main_unix.cpp/main()
RAMBaseMac = 0;
ROMBaseMac = Host2MacAddr(ROMBaseHost);
#else
// Initialize UAE memory banks
RAMBaseMac = 0;
switch (ROMVersion) {
case ROM_VERSION_64K:
case ROM_VERSION_PLUS:
case ROM_VERSION_CLASSIC:
ROMBaseMac = 0x00400000;
break;
case ROM_VERSION_II:
ROMBaseMac = 0x00a00000;
break;
case ROM_VERSION_32:
ROMBaseMac = 0x40800000;
break;
default:
return false;
}
memory_init();
#endif
init_m68k();
#if USE_JIT
UseJIT = compiler_use_jit();
if (UseJIT)
compiler_init();
#endif
return true;
}
@ -76,9 +112,25 @@ bool Init680x0(void)
void Exit680x0(void)
{
#if USE_JIT
if (UseJIT)
compiler_exit();
#endif
exit_m68k();
}
/*
* Initialize memory mapping of frame buffer (called upon video mode change)
*/
void InitFrameBufferMapping(void)
{
#if !REAL_ADDRESSING && !DIRECT_ADDRESSING
memory_init();
#endif
}
/*
* Reset and start 680x0 emulation (doesn't return)
*/
@ -86,7 +138,12 @@ void Exit680x0(void)
void Start680x0(void)
{
m68k_reset();
m68k_go(true);
#if USE_JIT
if (UseJIT)
m68k_compile_execute();
else
#endif
m68k_execute();
}
@ -97,7 +154,7 @@ void Start680x0(void)
void TriggerInterrupt(void)
{
idle_resume();
regs.spcflags |= SPCFLAG_INT;
SPCFLAGS_SET( SPCFLAG_INT );
}
void TriggerNMI(void)
@ -143,8 +200,8 @@ void Execute68kTrap(uint16 trap, struct M68kRegisters *r)
// Execute trap
m68k_setpc(m68k_areg(regs, 7));
fill_prefetch_0();
quit_program = 0;
m68k_go(true);
quit_program = false;
m68k_execute();
// Clean up stack
m68k_areg(regs, 7) += 4;
@ -158,7 +215,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 = 0;
quit_program = false;
}
@ -190,8 +247,8 @@ void Execute68k(uint32 addr, struct M68kRegisters *r)
// Execute routine
m68k_setpc(addr);
fill_prefetch_0();
quit_program = 0;
m68k_go(true);
quit_program = false;
m68k_execute();
// Clean up stack
m68k_areg(regs, 7) += 2;
@ -205,5 +262,7 @@ 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 = 0;
quit_program = false;
}
void report_double_bus_error() {}

View File

@ -1,3 +1,27 @@
/*
* 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
*
@ -6,13 +30,15 @@
* Copyright 1995,1996 Bernd Schmidt
*/
#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;
@ -51,7 +77,7 @@ static int nextchtohex(void)
}
}
int main(int argc, char **argv)
int main()
{
int no_insns = 0;
@ -76,6 +102,7 @@ int main(int argc, char **argv)
char opcstr[256];
int bitpos[16];
int flagset[5], flaguse[5];
char cflow;
unsigned int bitmask,bitpattern;
int n_variable;
@ -107,6 +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;
default: abort();
}
if (!(bitmask & 1)) {
@ -121,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();
@ -156,6 +186,7 @@ int main(int argc, char **argv)
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;
@ -182,6 +213,26 @@ int main(int argc, char **argv)
}
}
getnextch();
while (isspace(nextch))
getnextch();
if (nextch != ':') /* Get control flow information */
abort();
cflow = 0;
for(i = 0; i < 2; i++) {
getnextch();
switch(nextch){
case '-': break;
case 'R': cflow |= fl_return; break;
case 'B': cflow |= fl_branch; break;
case 'J': cflow |= fl_jump; break;
case 'T': cflow |= fl_trap; break;
default: abort();
}
}
getnextch();
while (isspace(nextch))
getnextch();
@ -201,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;
@ -209,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++;
}
@ -233,7 +284,7 @@ int main(int argc, char **argv)
for(i = 0; i < 5; i++) {
printf("{ %d, %d }%c ", flaguse[i], flagset[i], i == 4 ? ' ' : ',');
}
printf("}, %d, \"%s\"}", sduse, opstrp);
printf("}, %d, %d, \"%s\"}", cflow, sduse, opstrp);
}
}
printf("};\nint n_defs68k = %d;\n", no_insns);

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

@ -0,0 +1,543 @@
/*
* compiler/compemu.h - Public interface and definitions
*
* 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.
*
* JIT compiler m68k -> IA-32 and AMD64
*
* 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"
#ifdef UAE
#ifdef CPU_64_BIT
typedef uae_u64 uintptr;
#else
typedef uae_u32 uintptr;
#endif
/* FIXME: cpummu.cpp also checks for USE_JIT, possibly others */
// #define USE_JIT
#endif
#ifdef USE_JIT
#ifdef JIT_DEBUG
/* dump some information (m68k block, x86 block addresses) about the compiler state */
extern void compiler_dumpstate(void);
#endif
/* Now that we do block chaining, and also have linked lists on each tag,
TAGMASK can be much smaller and still do its job. Saves several megs
of memory! */
#define TAGMASK 0x0000ffff
#define TAGSIZE (TAGMASK+1)
#define MAXRUN 1024
#define cacheline(x) (((uintptr)x)&TAGMASK)
extern uae_u8* start_pc_p;
extern uae_u32 start_pc;
struct blockinfo_t;
struct cpu_history {
uae_u16* location;
#ifdef UAE
uae_u8 specmem;
#endif
};
union cacheline {
cpuop_func* handler;
blockinfo_t * bi;
};
/* Use new spill/reload strategy when calling external functions */
#define USE_OPTIMIZED_CALLS 0
#if USE_OPTIMIZED_CALLS
#error implementation in progress
#endif
/* (gb) When on, this option can save save up to 30% compilation time
* when many lazy flushes occur (e.g. apps in MacOS 8.x).
*/
#define USE_SEPARATE_BIA 1
/* Use chain of checksum_info_t to compute the block checksum */
#define USE_CHECKSUM_INFO 1
/* Use code inlining, aka follow-up of constant jumps */
#define USE_INLINING 1
/* Inlining requires the chained checksuming information */
#if USE_INLINING
#undef USE_CHECKSUM_INFO
#define USE_CHECKSUM_INFO 1
#endif
/* Does flush_icache_range() only check for blocks falling in the requested range? */
#define LAZY_FLUSH_ICACHE_RANGE 0
#define USE_F_ALIAS 1
#define USE_OFFSET 1
#define COMP_DEBUG 1
#if COMP_DEBUG
#define Dif(x) if (x)
#else
#define Dif(x) if (0)
#endif
#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 */
#define MAX_HOLD_BI 3 /* One for the current block, and up to two
for jump targets */
#define INDIVIDUAL_INST 0
#define FLAG_X 0x0010
#define FLAG_N 0x0008
#define FLAG_Z 0x0004
#define FLAG_V 0x0002
#define FLAG_C 0x0001
#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(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);
#endif
extern void init_comp(void);
extern void flush(int save_regs);
extern void small_flush(int save_regs);
extern void set_target(uae_u8* t);
extern uae_u8* get_target(void);
extern void freescratch(void);
extern void build_comp(void);
extern void set_cache_state(int enabled);
extern int get_cache_state(void);
extern uae_u32 get_jitted_size(void);
#ifdef JIT
#ifdef WINUAE_ARANYM
extern void (*flush_icache)(int n);
#else
extern void flush_icache(int n);
#endif
#endif
extern void alloc_cache(void);
extern int check_for_cache_miss(void);
/* JIT FPU compilation */
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 uae_u8* comp_pc_p;
extern void* pushall_call_handler;
#define VREGS 32
#define VFREGS 16
#define INMEM 1
#define CLEAN 2
#define DIRTY 3
#define UNDEF 4
#define ISCONST 5
typedef struct {
uae_u32* mem;
uae_u32 val;
uae_u8 is_swapped;
uae_u8 status;
uae_s8 realreg; /* gb-- realreg can hold -1 */
uae_u8 realind; /* The index in the holds[] array */
uae_u8 needflush;
uae_u8 validsize;
uae_u8 dirtysize;
uae_u8 dummy;
} reg_status;
typedef struct {
uae_u32* mem;
double val;
uae_u8 status;
uae_s8 realreg; /* gb-- realreg can hold -1 */
uae_u8 realind;
uae_u8 needflush;
} freg_status;
#define PC_P 16
#define FLAGX 17
#define FLAGTMP 18
#define NEXT_HANDLER 19
#define S1 20
#define S2 21
#define S3 22
#define S4 23
#define S5 24
#define S6 25
#define S7 26
#define S8 27
#define S9 28
#define S10 29
#define S11 30
#define S12 31
#define FP_RESULT 8
#define FS1 9
#define FS2 10
#define FS3 11
typedef struct {
uae_u32 touched;
uae_s8 holds[VREGS];
uae_u8 nholds;
uae_u8 canbyte;
uae_u8 canword;
uae_u8 locked;
} n_status;
typedef struct {
uae_u32 touched;
uae_s8 holds[VFREGS];
uae_u8 nholds;
uae_u8 locked;
} fn_status;
/* For flag handling */
#define NADA 1
#define TRASH 2
#define VALID 3
/* needflush values */
#define NF_SCRATCH 0
#define NF_TOMEM 1
#define NF_HANDLER 2
typedef struct {
/* Integer part */
reg_status state[VREGS];
n_status nat[N_REGS];
uae_u32 flags_on_stack;
uae_u32 flags_in_flags;
uae_u32 flags_are_important;
/* FPU part */
freg_status fate[VFREGS];
fn_status fat[N_FREGS];
/* x86 FPU part */
uae_s8 spos[N_FREGS];
uae_s8 onstack[6];
uae_s8 tos;
} bigstate;
typedef struct {
/* Integer part */
uae_s8 virt[VREGS];
uae_s8 nat[N_REGS];
} smallstate;
extern int touchcnt;
#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
#define RW1 uae_u32
#define RW2 uae_u32
#define RW4 uae_u32
#define MEMR uae_u32
#define MEMW uae_u32
#define MEMRW uae_u32
#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)
/* What we expose to the outside */
#define DECLARE_MIDFUNC(func) extern void func
#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;
#define FAIL(x) do { failure|=x; } while (0)
/* Convenience functions exposed to gencomp */
extern uae_u32 m68k_pc_offset;
extern void readbyte(int address, int dest, int tmp);
extern void readword(int address, int dest, int tmp);
extern void readlong(int address, int dest, int tmp);
extern void writebyte(int address, int source, int tmp);
extern void writeword(int address, int source, int tmp);
extern void writelong(int address, int source, int tmp);
extern void writeword_clobber(int address, int source, int tmp);
extern void writelong_clobber(int address, int source, int tmp);
extern void get_n_addr(int address, int dest, int tmp);
extern void get_n_addr_jmp(int address, int dest, int tmp);
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);
#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)))
#define comp_get_ilong(o) do_get_mem_long((uae_u32 *)(comp_pc_p + (o)))
struct blockinfo_t;
typedef struct dep_t {
uae_u32* jmp_off;
struct blockinfo_t* target;
struct blockinfo_t* source;
struct dep_t** prev_p;
struct dep_t* next;
} dependency;
typedef struct checksum_info_t {
uae_u8 *start_p;
uae_u32 length;
struct checksum_info_t *next;
} checksum_info;
typedef struct blockinfo_t {
uae_s32 count;
cpuop_func* direct_handler_to_use;
cpuop_func* handler_to_use;
/* The direct handler does not check for the correct address */
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 c2;
#if USE_CHECKSUM_INFO
checksum_info *csi;
#else
uae_u32 len;
uae_u32 min_pcp;
#endif
struct blockinfo_t* next_same_cl;
struct blockinfo_t** prev_same_cl_p;
struct blockinfo_t* next;
struct blockinfo_t** prev_p;
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;
#ifdef JIT_DEBUG
/* (gb) size of the compiled block (direct handler) */
uae_u32 direct_handler_size;
#endif
} blockinfo;
#define BI_INVALID 0
#define BI_ACTIVE 1
#define BI_NEED_RECOMP 2
#define BI_NEED_CHECK 3
#define BI_CHECKING 4
#define BI_COMPILING 5
#define BI_FINALIZING 6
void execute_normal(void);
void exec_nostats(void);
void do_nothing(void);
#else
static inline void flush_icache(int) { }
static inline void build_comp() { }
#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,184 @@
/*
* 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(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(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,252 @@
/*
* 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(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(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, MEMR m));
DECLARE_MIDFUNC(fmov_mr(MEMW m, FR r));
DECLARE_MIDFUNC(fmovi_rm(FW r, MEMR m));
DECLARE_MIDFUNC(fmovi_mr(MEMW m, FR r));
DECLARE_MIDFUNC(fmovi_mrb(MEMW m, FR r, double *bounds));
DECLARE_MIDFUNC(fmovs_rm(FW r, MEMR m));
DECLARE_MIDFUNC(fmovs_mr(MEMW m, FR r));
DECLARE_MIDFUNC(fcuts_r(FRW r));
DECLARE_MIDFUNC(fcut_r(FRW 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(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

@ -0,0 +1,52 @@
/*
* compiler/flags_x86.h - Native flags definitions for IA-32
*
* 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_X86_H
#define NATIVE_FLAGS_X86_H
/* Native integer code conditions */
enum {
NATIVE_CC_HI = 7,
NATIVE_CC_LS = 6,
NATIVE_CC_CC = 3,
NATIVE_CC_CS = 2,
NATIVE_CC_NE = 5,
NATIVE_CC_EQ = 4,
NATIVE_CC_VC = 1,
NATIVE_CC_VS = 0,
NATIVE_CC_PL = 9,
NATIVE_CC_MI = 8,
NATIVE_CC_GE = 13,
NATIVE_CC_LT = 12,
NATIVE_CC_GT = 15,
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

@ -80,7 +80,13 @@ extern bool Init680x0(void); // This routine may want to look at CPUType/FPUType
extern void Exit680x0(void);
// 680x0 emulation functions
struct M68kRegisters;
struct M68kRegisters {
uint32 d[8];
memptr a[8];
uint16 sr;
memptr usp, isp, msp;
memptr pc;
};
extern void Start680x0(void); // Reset and start 680x0
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
@ -89,4 +95,12 @@ extern "C" void Execute68kTrap(uint16 trap, M68kRegisters *r); // Execute MacOS
extern void TriggerInterrupt(void); // Trigger interrupt level 1 (InterruptFlag must be set first)
extern void TriggerNMI(void); // Trigger interrupt level 7
// CPU looping handlers
void check_eps_limit(uaecptr);
void report_double_bus_error(void);
extern int intlev(void);
static inline void AtariReset(void) {}
#endif

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

@ -1,298 +0,0 @@
/*
* UAE - The Un*x Amiga Emulator
*
* cpuopti.c - Small optimizer for cpu*.s files
* Based on work by Tauno Taipaleenmaki
*
* Copyright 1996 Bernd Schmidt
*/
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include "sysdeps.h"
struct line {
struct line *next, *prev;
int delet;
char *data;
};
struct func {
struct line *first_line, *last_line;
int initial_offset;
};
static void oops(void)
{
fprintf(stderr, "Don't know how to optimize this file.\n");
abort();
}
static char * match(struct line *l, const char *m)
{
char *str = l->data;
int len = strlen(m);
while (isspace(*str))
str++;
if (strncmp(str, m, len) != 0)
return NULL;
return str + len;
}
static int insn_references_reg (struct line *l, char *reg)
{
if (reg[0] != 'e') {
fprintf(stderr, "Unknown register?!?\n");
abort();
}
if (strstr (l->data, reg) != 0)
return 1;
if (strstr (l->data, reg+1) != 0)
return 1;
if (strcmp (reg, "eax") == 0
&& (strstr (l->data, "%al") != 0 || strstr (l->data, "%ah") != 0))
return 1;
if (strcmp (reg, "ebx") == 0
&& (strstr (l->data, "%bl") != 0 || strstr (l->data, "%bh") != 0))
return 1;
if (strcmp (reg, "ecx") == 0
&& (strstr (l->data, "%cl") != 0 || strstr (l->data, "%ch") != 0))
return 1;
if (strcmp (reg, "edx") == 0
&& (strstr (l->data, "%dl") != 0 || strstr (l->data, "%dh") != 0))
return 1;
return 0;
}
static void do_function(struct func *f)
{
int v;
int pops_at_end = 0;
struct line *l, *l1, *fl, *l2;
char *s, *s2;
int in_pop_area = 1;
f->initial_offset = 0;
l = f->last_line;
fl = f->first_line;
if (match(l,".LFE"))
l = l->prev;
if (!match(l,"ret"))
oops();
while (!match(fl, "op_"))
fl = fl->next;
fl = fl->next;
/* Try reordering the insns at the end of the function so that the
* pops are all at the end. */
l2 = l->prev;
/* Tolerate one stack adjustment */
if (match (l2, "addl $") && strstr(l2->data, "esp") != 0)
l2 = l2->prev;
for (;;) {
char *forbidden_reg;
struct line *l3, *l4;
while (match (l2, "popl %"))
l2 = l2->prev;
l3 = l2;
for (;;) {
forbidden_reg = match (l3, "popl %");
if (forbidden_reg)
break;
if (l3 == fl)
goto reordered;
/* Jumps and labels put an end to our attempts... */
if (strstr (l3->data, ".L") != 0)
goto reordered;
/* Likewise accesses to the stack pointer... */
if (strstr (l3->data, "esp") != 0)
goto reordered;
/* Function calls... */
if (strstr (l3->data, "call") != 0)
goto reordered;
l3 = l3->prev;
}
if (l3 == l2)
abort();
for (l4 = l2; l4 != l3; l4 = l4->prev) {
/* The register may not be referenced by any of the insns that we
* move the popl past */
if (insn_references_reg (l4, forbidden_reg))
goto reordered;
}
l3->prev->next = l3->next;
l3->next->prev = l3->prev;
l2->next->prev = l3;
l3->next = l2->next;
l2->next = l3;
l3->prev = l2;
}
reordered:
l = l->prev;
s = match (l, "addl $");
s2 = match (fl, "subl $");
l1 = l;
if (s == 0) {
char *t = match (l, "popl %");
if (t != 0 && (strcmp (t, "ecx") == 0 || strcmp (t, "edx") == 0)) {
s = "4,%esp";
l = l->prev;
t = match (l, "popl %");
if (t != 0 && (strcmp (t, "ecx") == 0 || strcmp (t, "edx") == 0)) {
s = "8,%esp";
l = l->prev;
}
}
} else {
l = l->prev;
}
if (s && s2) {
int v = 0;
if (strcmp (s, s2) != 0) {
fprintf (stderr, "Stack adjustment not matching.\n");
return;
}
while (isdigit(*s)) {
v = v * 10 + (*s) - '0';
s++;
}
if (strcmp (s, ",%esp") != 0) {
fprintf (stderr, "Not adjusting the stack pointer.\n");
return;
}
f->initial_offset = v;
fl->delet = 3;
fl = fl->next;
l1->delet = 2;
l1 = l1->prev;
while (l1 != l) {
l1->delet = 1;
l1 = l1->prev;
}
}
while (in_pop_area) {
char *popm, *pushm;
popm = match (l, "popl %");
pushm = match (fl, "pushl %");
if (popm && pushm && strcmp(pushm, popm) == 0) {
pops_at_end++;
fl->delet = l->delet = 1;
} else
in_pop_area = 0;
l = l->prev;
fl = fl->next;
}
if (f->initial_offset)
f->initial_offset += 4 * pops_at_end;
}
static void output_function(struct func *f)
{
struct line *l = f->first_line;
while (l) {
switch (l->delet) {
case 1:
break;
case 0:
printf("%s\n", l->data);
break;
case 2:
if (f->initial_offset)
printf("\taddl $%d,%%esp\n", f->initial_offset);
break;
case 3:
if (f->initial_offset)
printf("\tsubl $%d,%%esp\n", f->initial_offset);
break;
}
l = l->next;
}
}
int main(int argc, char **argv)
{
FILE *infile = stdin;
char tmp[4096];
#ifdef __mc68000__
if(system("perl machdep/cpuopti")==-1) {
perror("perl machdep/cpuopti");
return 10;
} else return 0;
#endif
/* For debugging... */
if (argc == 2)
infile = fopen (argv[1], "r");
for(;;) {
char *s;
if ((fgets(tmp, 4095, infile)) == NULL)
break;
s = strchr (tmp, '\n');
if (s != NULL)
*s = 0;
if (strncmp(tmp, ".globl op_", 10) == 0) {
struct line *first_line = NULL, *prev = NULL;
struct line **nextp = &first_line;
struct func f;
int nr_rets = 0;
int can_opt = 1;
do {
struct line *current;
if (strcmp (tmp, "#APP") != 0 && strcmp (tmp, "#NO_APP") != 0) {
current = *nextp = (struct line *)malloc(sizeof (struct line));
nextp = &current->next;
current->prev = prev; prev = current;
current->next = NULL;
current->delet = 0;
current->data = strdup (tmp);
if (match (current, "movl %esp,%ebp") || match (current, "enter")) {
fprintf (stderr, "GCC failed to eliminate fp: %s\n", first_line->data);
can_opt = 0;
}
if (match (current, "ret"))
nr_rets++;
}
if ((fgets(tmp, 4095, infile)) == NULL)
oops();
s = strchr (tmp, '\n');
if (s != NULL)
*s = 0;
} while (strncmp (tmp,".Lfe", 4) != 0);
f.first_line = first_line;
f.last_line = prev;
if (nr_rets == 1 && can_opt)
do_function(&f);
/*else
fprintf(stderr, "Too many RET instructions: %s\n", first_line->data);*/
output_function(&f);
}
printf("%s\n", tmp);
}
return 0;
}

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

@ -0,0 +1,268 @@
/*
* fpu/core.h - base fpu context definition
*
* 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
*/
#ifndef FPU_CORE_H
#define FPU_CORE_H
#include "sysdeps.h"
#include "fpu/types.h"
/* 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) && defined(USE_LONG_DOUBLE)
#define USE_X87_ASSEMBLY 1
#define ACCURATE_SIN_COS_TAN 1
#endif
/* ========================================================================== */
/* ========================= FPU CONTEXT DEFINITION ========================= */
/* ========================================================================== */
/* We don't use all features of the C++ language so that we may still
* easily backport that code to C.
*/
struct fpu_t {
/* ---------------------------------------------------------------------- */
/* --- Floating-Point Data Registers --- */
/* ---------------------------------------------------------------------- */
/* The eight %fp0 .. %fp7 registers */
fpu_register registers[8];
/* Used for lazy evalualation of FPU flags */
fpu_register result;
/* ---------------------------------------------------------------------- */
/* --- 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
#define FPCR_EXCEPTION_OPERR 0x00002000
#define FPCR_EXCEPTION_OVFL 0x00001000
#define FPCR_EXCEPTION_UNFL 0x00000800
#define FPCR_EXCEPTION_DZ 0x00000400
#define FPCR_EXCEPTION_INEX2 0x00000200
#define FPCR_EXCEPTION_INEX1 0x00000100
/* Mode Control Byte Mask */
#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;
/* ---------------------------------------------------------------------- */
/* --- Floating-Point Status Register --- */
/* ---------------------------------------------------------------------- */
struct {
/* Floating-Point Condition Code Byte */
uae_u32 condition_codes;
#define FPSR_CCB 0x0f000000
#define FPSR_CCB_NEGATIVE 0x08000000
#define FPSR_CCB_ZERO 0x04000000
#define FPSR_CCB_INFINITY 0x02000000
#define FPSR_CCB_NAN 0x01000000
/* Quotient Byte */
uae_u32 quotient;
#define FPSR_QUOTIENT 0x00ff0000
#define FPSR_QUOTIENT_SIGN 0x00800000
#define FPSR_QUOTIENT_VALUE 0x007f0000
/* Exception Status Byte */
uae_u32 exception_status;
#define FPSR_EXCEPTION_STATUS FPCR_EXCEPTION_ENABLE
#define FPSR_EXCEPTION_BSUN FPCR_EXCEPTION_BSUN
#define FPSR_EXCEPTION_SNAN FPCR_EXCEPTION_SNAN
#define FPSR_EXCEPTION_OPERR FPCR_EXCEPTION_OPERR
#define FPSR_EXCEPTION_OVFL FPCR_EXCEPTION_OVFL
#define FPSR_EXCEPTION_UNFL FPCR_EXCEPTION_UNFL
#define FPSR_EXCEPTION_DZ FPCR_EXCEPTION_DZ
#define FPSR_EXCEPTION_INEX2 FPCR_EXCEPTION_INEX2
#define FPSR_EXCEPTION_INEX1 FPCR_EXCEPTION_INEX1
/* Accrued Exception Byte */
uae_u32 accrued_exception;
#define FPSR_ACCRUED_EXCEPTION 0x000000ff
#define FPSR_ACCR_IOP 0x00000080
#define FPSR_ACCR_OVFL 0x00000040
#define FPSR_ACCR_UNFL 0x00000020
#define FPSR_ACCR_DZ 0x00000010
#define FPSR_ACCR_INEX 0x00000008
} fpsr;
/* ---------------------------------------------------------------------- */
/* --- Floating-Point Instruction Address Register --- */
/* ---------------------------------------------------------------------- */
uae_u32 instruction_address;
/* ---------------------------------------------------------------------- */
/* --- Initialization / Finalization --- */
/* ---------------------------------------------------------------------- */
/* Flag set if we emulate an integral 68040 FPU */
bool is_integral;
/* ---------------------------------------------------------------------- */
/* --- Extra FPE-dependant defines --- */
/* ---------------------------------------------------------------------- */
#if defined(FPU_X86) \
|| (defined(FPU_UAE) && defined(USE_X87_ASSEMBLY)) \
|| (defined(FPU_IEEE) && defined(USE_X87_ASSEMBLY))
#define CW_RESET 0x0040 // initial CW value after RESET
#define CW_FINIT 0x037F // initial CW value after FINIT
#define SW_RESET 0x0000 // initial SW value after RESET
#define SW_FINIT 0x0000 // initial SW value after FINIT
#define TW_RESET 0x5555 // initial TW value after RESET
#define TW_FINIT 0x0FFF // initial TW value after FINIT
#define CW_X 0x1000 // infinity control
#define CW_RC_ZERO 0x0C00 // rounding control toward zero
#define CW_RC_UP 0x0800 // rounding control toward +
#define CW_RC_DOWN 0x0400 // rounding control toward -
#define CW_RC_NEAR 0x0000 // rounding control toward even
#define CW_PC_EXTENDED 0x0300 // precision control 64bit
#define CW_PC_DOUBLE 0x0200 // precision control 53bit
#define CW_PC_RESERVED 0x0100 // precision control reserved
#define CW_PC_SINGLE 0x0000 // precision control 24bit
#define CW_PM 0x0020 // precision exception mask
#define CW_UM 0x0010 // underflow exception mask
#define CW_OM 0x0008 // overflow exception mask
#define CW_ZM 0x0004 // zero divide exception mask
#define CW_DM 0x0002 // denormalized operand exception mask
#define CW_IM 0x0001 // invalid operation exception mask
#define SW_B 0x8000 // busy flag
#define SW_C3 0x4000 // condition code flag 3
#define SW_TOP_7 0x3800 // top of stack = ST(7)
#define SW_TOP_6 0x3000 // top of stack = ST(6)
#define SW_TOP_5 0x2800 // top of stack = ST(5)
#define SW_TOP_4 0x2000 // top of stack = ST(4)
#define SW_TOP_3 0x1800 // top of stack = ST(3)
#define SW_TOP_2 0x1000 // top of stack = ST(2)
#define SW_TOP_1 0x0800 // top of stack = ST(1)
#define SW_TOP_0 0x0000 // top of stack = ST(0)
#define SW_C2 0x0400 // condition code flag 2
#define SW_C1 0x0200 // condition code flag 1
#define SW_C0 0x0100 // condition code flag 0
#define SW_ES 0x0080 // error summary status flag
#define SW_SF 0x0040 // stack fault flag
#define SW_PE 0x0020 // precision exception flag
#define SW_UE 0x0010 // underflow exception flag
#define SW_OE 0x0008 // overflow exception flag
#define SW_ZE 0x0004 // zero divide exception flag
#define SW_DE 0x0002 // denormalized operand exception flag
#define SW_IE 0x0001 // invalid operation exception flag
#define X86_ROUNDING_MODE 0x0C00
#define X86_ROUNDING_PRECISION 0x0300
#endif /* FPU_X86 */
};
/* We handle only one global fpu */
extern fpu_t fpu;
/* Return the address of a particular register */
inline fpu_register * fpu_register_address(int i)
{ return &fpu.registers[i]; }
/* Dump functions for m68k_dumpstate */
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);
/* Accessors to FPU Status Register */
//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);
/* Initialization / Finalization */
extern void fpu_init(bool integral_68040);
extern void fpu_exit(void);
extern void fpu_reset(void);
/* Floating-point arithmetic instructions */
void fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) REGPARAM;
/* Floating-point program control operations */
void fpuop_bcc(uae_u32 opcode, uaecptr pc, uae_u32 extra) REGPARAM;
void fpuop_dbcc(uae_u32 opcode, uae_u32 extra) REGPARAM;
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, uae_u32 extra) REGPARAM;
#endif /* FPU_CORE_H */

View File

@ -0,0 +1,193 @@
/*
* fpu/exceptions.cpp - system-dependant FPU exceptions management
*
* 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
*/
#undef PRIVATE
#define PRIVATE /**/
#undef PUBLIC
#define PUBLIC /**/
#undef FFPU
#define FFPU /**/
#undef FPU
#define FPU fpu.
/* -------------------------------------------------------------------------- */
/* --- Native X86 exceptions --- */
/* -------------------------------------------------------------------------- */
#ifdef FPU_USE_X86_EXCEPTIONS
void FFPU fpu_init_native_exceptions(void)
{
// Mapping for "sw" -> fpsr exception byte
for (uae_u32 i = 0; i < 0x80; i++) {
exception_host2mac[i] = 0;
if(i & SW_FAKE_BSUN) {
exception_host2mac[i] |= FPSR_EXCEPTION_BSUN;
}
// precision exception
if(i & SW_PE) {
exception_host2mac[i] |= FPSR_EXCEPTION_INEX2;
}
// underflow exception
if(i & SW_UE) {
exception_host2mac[i] |= FPSR_EXCEPTION_UNFL;
}
// overflow exception
if(i & SW_OE) {
exception_host2mac[i] |= FPSR_EXCEPTION_OVFL;
}
// zero divide exception
if(i & SW_ZE) {
exception_host2mac[i] |= FPSR_EXCEPTION_DZ;
}
// denormalized operand exception.
// wrong, but should not get here, normalization is done in elsewhere
if(i & SW_DE) {
exception_host2mac[i] |= FPSR_EXCEPTION_SNAN;
}
// invalid operation exception
if(i & SW_IE) {
exception_host2mac[i] |= FPSR_EXCEPTION_OPERR;
}
}
// Mapping for fpsr exception byte -> "sw"
for (uae_u32 i = 0; i < 0x100; i++) {
uae_u32 fpsr = (i << 8);
exception_mac2host[i] = 0;
// BSUN; make sure that you don't generate FPU stack faults.
if(fpsr & FPSR_EXCEPTION_BSUN) {
exception_mac2host[i] |= SW_FAKE_BSUN;
}
// precision exception
if(fpsr & FPSR_EXCEPTION_INEX2) {
exception_mac2host[i] |= SW_PE;
}
// underflow exception
if(fpsr & FPSR_EXCEPTION_UNFL) {
exception_mac2host[i] |= SW_UE;
}
// overflow exception
if(fpsr & FPSR_EXCEPTION_OVFL) {
exception_mac2host[i] |= SW_OE;
}
// zero divide exception
if(fpsr & FPSR_EXCEPTION_DZ) {
exception_mac2host[i] |= SW_ZE;
}
// denormalized operand exception
if(fpsr & FPSR_EXCEPTION_SNAN) {
exception_mac2host[i] |= SW_DE; //Wrong
}
// invalid operation exception
if(fpsr & FPSR_EXCEPTION_OPERR) {
exception_mac2host[i] |= SW_IE;
}
}
}
#endif
#ifdef FPU_USE_X86_ACCRUED_EXCEPTIONS
void FFPU fpu_init_native_accrued_exceptions(void)
{
/*
68881/68040 accrued exceptions accumulate as follows:
Accrued.IOP |= (Exception.SNAN | Exception.OPERR)
Accrued.OVFL |= (Exception.OVFL)
Accrued.UNFL |= (Exception.UNFL | Exception.INEX2)
Accrued.DZ |= (Exception.DZ)
Accrued.INEX |= (Exception.INEX1 | Exception.INEX2 | Exception.OVFL)
*/
// Mapping for "fpsr.accrued_exception" -> fpsr accrued exception byte
for (uae_u32 i = 0; i < 0x40; i++ ) {
accrued_exception_host2mac[i] = 0;
// precision exception
if(i & SW_PE) {
accrued_exception_host2mac[i] |= FPSR_ACCR_INEX;
}
// underflow exception
if(i & SW_UE) {
accrued_exception_host2mac[i] |= FPSR_ACCR_UNFL;
}
// overflow exception
if(i & SW_OE) {
accrued_exception_host2mac[i] |= FPSR_ACCR_OVFL;
}
// zero divide exception
if(i & SW_ZE) {
accrued_exception_host2mac[i] |= FPSR_ACCR_DZ;
}
// denormalized operand exception
if(i & SW_DE) {
accrued_exception_host2mac[i] |= FPSR_ACCR_IOP; //??????
}
// invalid operation exception
if(i & SW_IE) {
accrued_exception_host2mac[i] |= FPSR_ACCR_IOP;
}
}
// Mapping for fpsr accrued exception byte -> "fpsr.accrued_exception"
for (uae_u32 i = 0; i < 0x20; i++) {
int fpsr = (i << 3);
accrued_exception_mac2host[i] = 0;
// precision exception
if(fpsr & FPSR_ACCR_INEX) {
accrued_exception_mac2host[i] |= SW_PE;
}
// underflow exception
if(fpsr & FPSR_ACCR_UNFL) {
accrued_exception_mac2host[i] |= SW_UE;
}
// overflow exception
if(fpsr & FPSR_ACCR_OVFL) {
accrued_exception_mac2host[i] |= SW_OE;
}
// zero divide exception
if(fpsr & FPSR_ACCR_DZ) {
accrued_exception_mac2host[i] |= SW_ZE;
}
// What about SW_DE; //??????
// invalid operation exception
if(fpsr & FPSR_ACCR_IOP) {
accrued_exception_mac2host[i] |= SW_IE;
}
}
}
#endif

View File

@ -0,0 +1,154 @@
/*
* fpu/exceptions.h - system-dependant FPU exceptions management
*
* 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
*/
#ifndef FPU_EXCEPTIONS_H
#define FPU_EXCEPTIONS_H
/* NOTE: this file shall be included only from fpu/fpu_*.cpp */
#undef PUBLIC
#define PUBLIC extern
#undef PRIVATE
#define PRIVATE static
#undef FFPU
#define FFPU /**/
#undef FPU
#define FPU fpu.
/* Defaults to generic exceptions */
#define FPU_USE_GENERIC_EXCEPTIONS
#define FPU_USE_GENERIC_ACCRUED_EXCEPTIONS
/* -------------------------------------------------------------------------- */
/* --- Selection of floating-point exceptions handling mode --- */
/* -------------------------------------------------------------------------- */
/* Optimized i386 fpu core must use native exceptions */
#if defined(FPU_X86) && defined(USE_X87_ASSEMBLY)
# undef FPU_USE_GENERIC_EXCEPTIONS
# define FPU_USE_X86_EXCEPTIONS
#endif
/* Optimized i386 fpu core must use native accrued exceptions */
#if defined(FPU_X86) && defined(USE_X87_ASSEMBLY)
# undef FPU_USE_GENERIC_ACCRUED_EXCEPTIONS
# define FPU_USE_X86_ACCRUED_EXCEPTIONS
#endif
/* -------------------------------------------------------------------------- */
/* --- Native X86 Exceptions --- */
/* -------------------------------------------------------------------------- */
#ifdef FPU_USE_X86_EXCEPTIONS
/* Extend the SW_* codes */
#define SW_FAKE_BSUN SW_SF
/* Shorthand */
#define SW_EXCEPTION_MASK (SW_ES|SW_SF|SW_PE|SW_UE|SW_OE|SW_ZE|SW_DE|SW_IE)
// #define SW_EXCEPTION_MASK (SW_SF|SW_PE|SW_UE|SW_OE|SW_ZE|SW_DE|SW_IE)
/* Lookup tables */
PRIVATE uae_u32 exception_host2mac[ 0x80 ];
PRIVATE uae_u32 exception_mac2host[ 0x100 ];
/* Initialize native exception management */
PUBLIC void FFPU fpu_init_native_exceptions(void);
/* Return m68k floating-point exception status */
PRIVATE inline uae_u32 FFPU get_exception_status(void)
{ return exception_host2mac[FPU fpsr.exception_status & (SW_FAKE_BSUN|SW_PE|SW_UE|SW_OE|SW_ZE|SW_DE|SW_IE)]; }
/* Set new exception status. Assumes mask against FPSR_EXCEPTION to be already performed */
PRIVATE inline void FFPU set_exception_status(uae_u32 new_status)
{ FPU fpsr.exception_status = exception_mac2host[new_status >> 8]; }
#endif /* FPU_USE_X86_EXCEPTIONS */
#ifdef FPU_USE_X86_ACCRUED_EXCEPTIONS
/* Lookup tables */
PRIVATE uae_u32 accrued_exception_host2mac[ 0x40 ];
PRIVATE uae_u32 accrued_exception_mac2host[ 0x20 ];
/* Initialize native accrued exception management */
PUBLIC void FFPU fpu_init_native_accrued_exceptions(void);
/* Return m68k accrued exception byte */
PRIVATE inline uae_u32 FFPU get_accrued_exception(void)
{ return accrued_exception_host2mac[FPU fpsr.accrued_exception & (SW_PE|SW_UE|SW_OE|SW_ZE|SW_DE|SW_IE)]; }
/* Set new accrued exception byte */
PRIVATE inline void FFPU set_accrued_exception(uae_u32 new_status)
{ FPU fpsr.accrued_exception = accrued_exception_mac2host[(new_status & 0xF8) >> 3]; }
#endif /* FPU_USE_X86_ACCRUED_EXCEPTIONS */
/* -------------------------------------------------------------------------- */
/* --- Default Exceptions Handling --- */
/* -------------------------------------------------------------------------- */
#ifdef FPU_USE_GENERIC_EXCEPTIONS
/* Initialize native exception management */
static inline void FFPU fpu_init_native_exceptions(void)
{ }
/* Return m68k floating-point exception status */
PRIVATE inline uae_u32 FFPU get_exception_status(void)
{ return FPU fpsr.exception_status; }
/* Set new exception status. Assumes mask against FPSR_EXCEPTION to be already performed */
PRIVATE inline void FFPU set_exception_status(uae_u32 new_status)
{ FPU fpsr.exception_status = new_status; }
#endif /* FPU_USE_GENERIC_EXCEPTIONS */
#ifdef FPU_USE_GENERIC_ACCRUED_EXCEPTIONS
/* Initialize native accrued exception management */
PRIVATE inline void FFPU fpu_init_native_accrued_exceptions(void)
{ }
/* Return m68k accrued exception byte */
PRIVATE inline uae_u32 FFPU get_accrued_exception(void)
{ return FPU fpsr.accrued_exception; }
/* Set new accrued exception byte */
PRIVATE inline void FFPU set_accrued_exception(uae_u32 new_status)
{ FPU fpsr.accrued_exception = new_status; }
#endif /* FPU_USE_GENERIC_ACCRUED_EXCEPTIONS */
#endif /* FPU_EXCEPTIONS_H */

View File

@ -0,0 +1,174 @@
/*
* fpu/flags.cpp - Floating-point flags
*
* 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
*/
/* NOTE: this file shall be included only from fpu/fpu_*.cpp */
#undef PRIVATE
#define PRIVATE /**/
#undef PUBLIC
#define PUBLIC /**/
#undef FFPU
#define FFPU /**/
#undef FPU
#define FPU fpu.
/* -------------------------------------------------------------------------- */
/* --- Native X86 floating-point flags --- */
/* -------------------------------------------------------------------------- */
#ifdef FPU_USE_X86_FLAGS
/* Initialization */
void FFPU fpu_init_native_fflags(void)
{
// Adapted from fpu_x86.cpp
#define SW_Z_I_NAN_MASK (SW_C0|SW_C2|SW_C3)
#define SW_Z (SW_C3)
#define SW_I (SW_C0|SW_C2)
#define SW_NAN (SW_C0)
#define SW_FINITE (SW_C2)
#define SW_EMPTY_REGISTER (SW_C0|SW_C3)
#define SW_DENORMAL (SW_C2|SW_C3)
#define SW_UNSUPPORTED (0)
#define SW_N (SW_C1)
// Sanity checks
#if (SW_Z != NATIVE_FFLAG_ZERO)
#error "Incorrect X86 Z fflag"
#endif
#if (SW_I != NATIVE_FFLAG_INFINITY)
#error "Incorrect X86 I fflag"
#endif
#if (SW_N != NATIVE_FFLAG_NEGATIVE)
#error "Incorrect X86 N fflag"
#endif
#if (SW_NAN != NATIVE_FFLAG_NAN)
#error "Incorrect X86 NAN fflag"
#endif
// Native status word to m68k mappings
for (uae_u32 i = 0; i < 0x48; i++) {
to_m68k_fpcond[i] = 0;
const uae_u32 native_fpcond = i << 8;
switch (native_fpcond & SW_Z_I_NAN_MASK) {
#ifndef FPU_UAE
// gb-- enabling it would lead to incorrect drawing of digits
// in Speedometer Performance Test
case SW_UNSUPPORTED:
#endif
case SW_NAN:
case SW_EMPTY_REGISTER:
to_m68k_fpcond[i] |= FPSR_CCB_NAN;
break;
case SW_FINITE:
case SW_DENORMAL:
break;
case SW_I:
to_m68k_fpcond[i] |= FPSR_CCB_INFINITY;
break;
case SW_Z:
to_m68k_fpcond[i] |= FPSR_CCB_ZERO;
break;
}
if (native_fpcond & SW_N)
to_m68k_fpcond[i] |= FPSR_CCB_NEGATIVE;
}
// m68k to native status word mappings
for (uae_u32 i = 0; i < 0x10; i++) {
const uae_u32 m68k_fpcond = i << 24;
if (m68k_fpcond & FPSR_CCB_NAN)
to_host_fpcond[i] = SW_NAN;
else if (m68k_fpcond & FPSR_CCB_ZERO)
to_host_fpcond[i] = SW_Z;
else if (m68k_fpcond & FPSR_CCB_INFINITY)
to_host_fpcond[i] = SW_I;
else
to_host_fpcond[i] = SW_FINITE;
if (m68k_fpcond & FPSR_CCB_NEGATIVE)
to_host_fpcond[i] |= SW_N;
}
// truth-table for FPU conditions
for (uae_u32 host_fpcond = 0; host_fpcond < 0x08; host_fpcond++) {
// host_fpcond: C3 on bit 2, C1 and C0 are respectively on bits 1 and 0
const uae_u32 real_host_fpcond = ((host_fpcond & 4) << 12) | ((host_fpcond & 3) << 8);
const bool N = ((real_host_fpcond & NATIVE_FFLAG_NEGATIVE) == NATIVE_FFLAG_NEGATIVE);
const bool Z = ((real_host_fpcond & NATIVE_FFLAG_ZERO) == NATIVE_FFLAG_ZERO);
const bool NaN = ((real_host_fpcond & NATIVE_FFLAG_NAN) == NATIVE_FFLAG_NAN);
int value;
for (uae_u32 m68k_fpcond = 0; m68k_fpcond < 0x20; m68k_fpcond++) {
switch (m68k_fpcond) {
case 0x00: value = 0; break; // False
case 0x01: value = Z; break; // Equal
case 0x02: value = !(NaN || Z || N); break; // Ordered Greater Than
case 0x03: value = Z || !(NaN || N); break; // Ordered Greater Than or Equal
case 0x04: value = N && !(NaN || Z); break; // Ordered Less Than
case 0x05: value = Z || (N && !NaN); break; // Ordered Less Than or Equal
case 0x06: value = !(NaN || Z); break; // Ordered Greater or Less Than
case 0x07: value = !NaN; break; // Ordered
case 0x08: value = NaN; break; // Unordered
case 0x09: value = NaN || Z; break; // Unordered or Equal
case 0x0a: value = NaN || !(N || Z); break; // Unordered or Greater Than
case 0x0b: value = NaN || Z || !N; break; // Unordered or Greater or Equal
case 0x0c: value = NaN || (N && !Z); break; // Unordered or Less Than
case 0x0d: value = NaN || Z || N; break; // Unordered or Less or Equal
case 0x0e: value = !Z; break; // Not Equal
case 0x0f: value = 1; break; // True
case 0x10: value = 0; break; // Signaling False
case 0x11: value = Z; break; // Signaling Equal
case 0x12: value = !(NaN || Z || N); break; // Greater Than
case 0x13: value = Z || !(NaN || N); break; // Greater Than or Equal
case 0x14: value = N && !(NaN || Z); break; // Less Than
case 0x15: value = Z || (N && !NaN); break; // Less Than or Equal
case 0x16: value = !(NaN || Z); break; // Greater or Less Than
case 0x17: value = !NaN; break; // Greater, Less or Equal
case 0x18: value = NaN; break; // Not Greater, Less or Equal
case 0x19: value = NaN || Z; break; // Not Greater or Less Than
case 0x1a: value = NaN || !(N || Z); break; // Not Less Than or Equal
case 0x1b: value = NaN || Z || !N; break; // Not Less Than
case 0x1c: value = NaN || (N && !Z); break; // Not Greater Than or Equal
// case 0x1c: value = !Z && (NaN || N); break; // Not Greater Than or Equal
case 0x1d: value = NaN || Z || N; break; // Not Greater Than
case 0x1e: value = !Z; break; // Signaling Not Equal
case 0x1f: value = 1; break; // Signaling True
default: value = -1;
}
fpcond_truth_table[m68k_fpcond][host_fpcond] = value;
}
}
}
#endif

View File

@ -0,0 +1,228 @@
/*
* fpu/flags.h - Floating-point flags
*
* 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
*/
#ifndef FPU_FLAGS_H
#define FPU_FLAGS_H
/* NOTE: this file shall be included only from fpu/fpu_*.cpp */
#undef PUBLIC
#define PUBLIC extern
#undef PRIVATE
#define PRIVATE static
#undef FFPU
#define FFPU /**/
#undef FPU
#define FPU fpu.
/* Defaults to generic flags */
#define FPU_USE_GENERIC_FLAGS
/* -------------------------------------------------------------------------- */
/* --- Selection of floating-point flags handling mode --- */
/* -------------------------------------------------------------------------- */
/* Optimized i386 fpu core must use native flags */
#if defined(FPU_X86) && defined(USE_X87_ASSEMBLY)
# undef FPU_USE_GENERIC_FLAGS
# define FPU_USE_X86_FLAGS
#endif
/* Old UAE FPU core can use native flags */
#if defined(FPU_UAE) && defined(USE_X87_ASSEMBLY)
# undef FPU_USE_GENERIC_FLAGS
# define FPU_USE_X86_FLAGS
#endif
/* IEEE-based implementation must use lazy flag evaluation */
#if defined(FPU_IEEE)
# undef FPU_USE_GENERIC_FLAGS
# define FPU_USE_LAZY_FLAGS
#endif
/* JIT Compilation for FPU only works with lazy evaluation of FPU flags */
#if defined(FPU_IEEE) && defined(USE_X87_ASSEMBLY) && defined(USE_JIT_FPU)
# undef FPU_USE_GENERIC_FLAGS
# define FPU_USE_LAZY_FLAGS
#endif
#ifdef FPU_IMPLEMENTATION
/* -------------------------------------------------------------------------- */
/* --- Native X86 Floating-Point Flags --- */
/* -------------------------------------------------------------------------- */
/* FPU_X86 has its own set of lookup functions */
#ifdef FPU_USE_X86_FLAGS
#define FPU_USE_NATIVE_FLAGS
#define NATIVE_FFLAG_NEGATIVE 0x0200
#define NATIVE_FFLAG_ZERO 0x4000
#define NATIVE_FFLAG_INFINITY 0x0500
#define NATIVE_FFLAG_NAN 0x0100
/* Translation tables between native and m68k floating-point flags */
PRIVATE uae_u32 to_m68k_fpcond[0x48];
PRIVATE uae_u32 to_host_fpcond[0x10];
/* Truth table for floating-point condition codes */
PRIVATE uae_u32 fpcond_truth_table[32][8]; // 32 m68k conditions x 8 host condition codes
/* Initialization */
PUBLIC void FFPU fpu_init_native_fflags(void);
#ifdef FPU_UAE
/* Native to m68k floating-point condition codes */
PRIVATE inline uae_u32 FFPU get_fpccr(void)
{ return to_m68k_fpcond[(FPU fpsr.condition_codes >> 8) & 0x47]; }
/* M68k to native floating-point condition codes */
PRIVATE inline void FFPU set_fpccr(uae_u32 new_fpcond)
/* Precondition: new_fpcond is only valid for floating-point condition codes */
{ FPU fpsr.condition_codes = to_host_fpcond[new_fpcond >> 24]; }
/* 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" : "=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 */
PRIVATE inline int FFPU host_fpcond_id(void)
{ return ((FPU fpsr.condition_codes >> 12) & 4) | ((FPU fpsr.condition_codes >> 8) & 3); }
/* Return true if the floating-point condition is satisfied */
PRIVATE inline bool FFPU fpcctrue(int condition)
{ return fpcond_truth_table[condition][host_fpcond_id()]; }
#endif /* FPU_UAE */
/* Return the address of the floating-point condition codes truth table */
static inline uae_u8 * const FFPU address_of_fpcond_truth_table(void)
{ return ((uae_u8*)&fpcond_truth_table[0][0]); }
#endif /* FPU_X86_USE_NATIVE_FLAGS */
/* -------------------------------------------------------------------------- */
/* --- Use Original M68K FPU Mappings --- */
/* -------------------------------------------------------------------------- */
#ifdef FPU_USE_GENERIC_FLAGS
#undef FPU_USE_NATIVE_FLAGS
#define NATIVE_FFLAG_NEGATIVE 0x08000000
#define NATIVE_FFLAG_ZERO 0x04000000
#define NATIVE_FFLAG_INFINITY 0x02000000
#define NATIVE_FFLAG_NAN 0x01000000
/* Initialization - NONE */
PRIVATE inline void FFPU fpu_init_native_fflags(void)
{ }
/* Native to m68k floating-point condition codes - SELF */
PRIVATE inline uae_u32 FFPU get_fpccr(void)
{ return FPU fpsr.condition_codes; }
/* M68k to native floating-point condition codes - SELF */
PRIVATE inline void FFPU set_fpccr(uae_u32 new_fpcond)
{ FPU fpsr.condition_codes = new_fpcond; }
#endif /* FPU_USE_GENERIC_FLAGS */
/* -------------------------------------------------------------------------- */
/* --- Use Lazy Flags Evaluation --- */
/* -------------------------------------------------------------------------- */
#ifdef FPU_USE_LAZY_FLAGS
#undef FPU_USE_NATIVE_FLAGS
#define NATIVE_FFLAG_NEGATIVE 0x08000000
#define NATIVE_FFLAG_ZERO 0x04000000
#define NATIVE_FFLAG_INFINITY 0x02000000
#define NATIVE_FFLAG_NAN 0x01000000
/* Initialization - NONE */
PRIVATE inline void FFPU fpu_init_native_fflags(void)
{ }
/* Native to m68k floating-point condition codes - SELF */
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))
fpccr |= FPSR_CCB_INFINITY;
return fpccr;
}
/* M68k to native floating-point condition codes - SELF */
PRIVATE inline void FFPU set_fpccr(uae_u32 new_fpcond)
{
if (new_fpcond & FPSR_CCB_NAN)
make_nan(FPU result);
else if (new_fpcond & FPSR_CCB_ZERO)
FPU result = 0.0;
else if (new_fpcond & FPSR_CCB_NEGATIVE)
FPU result = -1.0;
else
FPU result = +1.0;
/* gb-- where is Infinity ? */
}
/* Make FPSR according to the value passed in argument */
PRIVATE inline void FFPU make_fpsr(fpu_register const & r)
{ FPU result = r; }
#endif /* FPU_USE_LAZY_FLAGS */
#endif
/* -------------------------------------------------------------------------- */
/* --- Common methods --- */
/* -------------------------------------------------------------------------- */
/* Return the address of the floating-point condition codes register */
static inline uae_u32 * FFPU address_of_fpccr(void)
{ return ((uae_u32 *)& FPU fpsr.condition_codes); }
#endif /* FPU_FLAGS_H */

View File

@ -0,0 +1,59 @@
/*
* fpu/fpu.h - public header
*
* 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
*/
#ifndef FPU_PUBLIC_HEADER_H
#define FPU_PUBLIC_HEADER_H
#ifndef FPU_DEBUG
#define FPU_DEBUG 0
#endif
#if FPU_DEBUG
#define fpu_debug(args) printf args;
#define FPU_DUMP_REGISTERS 0
#define FPU_DUMP_FIRST_BYTES 0
#else
#define fpu_debug(args) ;
#undef FPU_DUMP_REGISTERS
#undef FPU_DUMP_FIRST_BYTES
#endif
#include "sysdeps.h"
#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

@ -0,0 +1,154 @@
/*
* fpu/fpu_ieee.h - Extra Definitions for the IEEE 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
*/
#ifndef FPU_IEEE_H
#define FPU_IEEE_H
/* NOTE: this file shall be included from fpu/fpu_uae.cpp */
#undef PUBLIC
#define PUBLIC extern
#undef PRIVATE
#define PRIVATE static
#undef FFPU
#define FFPU /**/
#undef FPU
#define FPU fpu.
// Lauri-- full words to avoid partial register stalls.
struct double_flags {
uae_u32 in_range;
uae_u32 zero;
uae_u32 infinity;
uae_u32 nan;
uae_u32 negative;
};
PRIVATE double_flags fl_source;
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);
// 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
#ifndef FPU_USE_NATIVE_FLAGS
PRIVATE inline void FFPU make_fpsr(fpu_register const & r);
#endif
// Normalize to range 1..2
PRIVATE inline void FFPU fast_remove_exponent(fpu_register & r);
// 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
);
// Quotient Byte is loaded with the sign and least significant
// seven bits of the quotient.
PRIVATE inline void FFPU make_quotient(
fpu_register const & quotient, uae_u32 sign
);
// to_single
PRIVATE inline fpu_register FFPU make_single(
uae_u32 value
);
// from_single
PRIVATE inline uae_u32 FFPU extract_single(
fpu_register const & src
);
// to_exten
PRIVATE inline fpu_register FFPU make_extended(
uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3
);
/*
Would be so much easier with full size floats :(
... this is so vague.
*/
// to_exten_no_normalize
PRIVATE inline void FFPU make_extended_no_normalize(
uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3, fpu_register & result
);
// from_exten
PRIVATE inline void FFPU extract_extended(fpu_register const & src,
uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3
);
// to_double
PRIVATE inline fpu_register FFPU make_double(
uae_u32 wrd1, uae_u32 wrd2
);
// from_double
PRIVATE inline void FFPU extract_double(fpu_register const & src,
uae_u32 * wrd1, uae_u32 * wrd2
);
PRIVATE inline fpu_register FFPU make_packed(
uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3
);
PRIVATE inline void FFPU extract_packed(
fpu_register const & src, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3
);
PRIVATE inline int FFPU get_fp_value(
uae_u32 opcode, uae_u16 extra, fpu_register & src
);
PRIVATE inline int FFPU put_fp_value(
uae_u32 opcode, uae_u16 extra, fpu_register const & value
);
PRIVATE inline int FFPU get_fp_ad(
uae_u32 opcode, uae_u32 * ad
);
PRIVATE inline int FFPU fpp_cond(
int condition
);
#endif /* FPU_IEEE_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,217 @@
/*
* fpu/fpu_uae.h - Extra Definitions for the old UAE 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
*/
#ifndef FPU_UAE_H
#define FPU_UAE_H
// Only define if you have IEEE 64 bit doubles.
#define FPU_HAVE_IEEE_DOUBLE 1
/* NOTE: this file shall be included from fpu/fpu_uae.cpp */
#undef PUBLIC
#define PUBLIC extern
#undef PRIVATE
#define PRIVATE static
#undef FFPU
#define FFPU /**/
#undef FPU
#define FPU fpu.
enum {
#ifdef WORDS_BIGENDIAN
FHI = 0,
FLO = 1
#else
FHI = 1,
FLO = 0
#endif
};
// Floating-point rounding support
PRIVATE inline fpu_register round_to_zero(fpu_register const & x);
PRIVATE inline fpu_register round_to_nearest(fpu_register const & x);
#if FPU_HAVE_IEEE_DOUBLE
// Lauri-- full words to avoid partial register stalls.
struct double_flags {
uae_u32 in_range;
uae_u32 zero;
uae_u32 infinity;
uae_u32 nan;
uae_u32 negative;
};
PRIVATE double_flags fl_source;
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 bool FFPU do_isnan(fpu_register const & r);
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 fast_scale(fpu_register & r, int add);
PRIVATE inline fpu_register FFPU fast_fgetexp(fpu_register const & r);
// May be optimized for particular processors
#ifndef FPU_USE_NATIVE_FLAGS
PRIVATE inline void FFPU make_fpsr(fpu_register const & r);
#endif
// Normalize to range 1..2
PRIVATE inline void FFPU fast_remove_exponent(fpu_register & r);
// 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
);
// Quotient Byte is loaded with the sign and least significant
// seven bits of the quotient.
PRIVATE inline void FFPU make_quotient(
fpu_register const & quotient, uae_u32 sign
);
// to_single
PRIVATE inline fpu_register FFPU make_single(
uae_u32 value
);
// from_single
PRIVATE inline uae_u32 FFPU extract_single(
fpu_register const & src
);
// to_exten
PRIVATE inline fpu_register FFPU make_extended(
uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3
);
/*
Would be so much easier with full size floats :(
... this is so vague.
*/
// to_exten_no_normalize
PRIVATE inline void FFPU make_extended_no_normalize(
uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3, fpu_register & result
);
// from_exten
PRIVATE inline void FFPU extract_extended(fpu_register const & src,
uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3
);
// to_double
PRIVATE inline fpu_register FFPU make_double(
uae_u32 wrd1, uae_u32 wrd2
);
// from_double
PRIVATE inline void FFPU extract_double(fpu_register const & src,
uae_u32 * wrd1, uae_u32 * wrd2
);
#else /* !FPU_HAVE_IEEE_DOUBLE */
// FIXME: may be optimized for particular processors
#ifndef FPU_USE_NATIVE_FLAGS
PRIVATE inline void FFPU make_fpsr(fpu_register const & r);
#endif
// to_single
PRIVATE inline fpu_register make_single(
uae_u32 value
);
// from_single
PRIVATE inline uae_u32 FFPU extract_single(
fpu_register const & src
);
// to exten
PRIVATE inline fpu_register FFPU make_extended(
uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3
);
// from_exten
PRIVATE inline void FFPU extract_extended(
fpu_register const & src, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3
);
// to_double
PRIVATE inline fpu_register FFPU make_double(
uae_u32 wrd1, uae_u32 wrd2
);
// from_double
PRIVATE inline void FFPU extract_double(
fpu_register const & src, uae_u32 * wrd1, uae_u32 * wrd2
);
#endif /* FPU_HAVE_IEEE_DOUBLE */
PRIVATE inline fpu_register FFPU make_packed(
uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3
);
PRIVATE inline void FFPU extract_packed(
fpu_register const & src, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3
);
PRIVATE inline int FFPU get_fp_value(
uae_u32 opcode, uae_u16 extra, fpu_register & src
);
PRIVATE inline int FFPU put_fp_value(
uae_u32 opcode, uae_u16 extra, fpu_register const & value
);
PRIVATE inline int FFPU get_fp_ad(
uae_u32 opcode, uae_u32 * ad
);
PRIVATE inline int FFPU fpp_cond(
int condition
);
#endif /* FPU_UAE_H */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,384 @@
/*
* fpu/fpu_x86.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
*/
#ifndef FPU_X86_H
#define FPU_X86_H
/* NOTE: this file shall be included from fpu/fpu_x86.cpp */
#undef PUBLIC
#define PUBLIC extern
#undef PRIVATE
#define PRIVATE static
#undef FFPU
#define FFPU /**/
#undef FPU
#define FPU fpu.
// Status word
PRIVATE uae_u32 x86_status_word;
PRIVATE uae_u32 x86_status_word_accrued;
// FPU jump table
typedef void REGPARAM2 ( *fpuop_func )( uae_u32, uae_u32 );
PRIVATE fpuop_func fpufunctbl[65536];
// FPU consistency
PRIVATE uae_u32 checked_sw_atstart;
// FMOVECR constants supported byt x86 FPU
PRIVATE fpu_register const_pi;
PRIVATE fpu_register const_lg2;
PRIVATE fpu_register const_l2e;
PRIVATE fpu_register const_z;
PRIVATE fpu_register const_ln2;
PRIVATE fpu_register const_1;
// FMOVECR constants not not suported by x86 FPU
PRIVATE fpu_register const_e;
PRIVATE fpu_register const_log_10_e;
PRIVATE fpu_register const_ln_10;
PRIVATE fpu_register const_1e1;
PRIVATE fpu_register const_1e2;
PRIVATE fpu_register const_1e4;
PRIVATE fpu_register const_1e8;
PRIVATE fpu_register const_1e16;
PRIVATE fpu_register const_1e32;
PRIVATE fpu_register const_1e64;
PRIVATE fpu_register const_1e128;
PRIVATE fpu_register const_1e256;
PRIVATE fpu_register const_1e512;
PRIVATE fpu_register const_1e1024;
PRIVATE fpu_register const_1e2048;
PRIVATE fpu_register const_1e4096;
// Saved host FPU state
PRIVATE uae_u8 m_fpu_state_original[108]; // 90/94/108
/* -------------------------------------------------------------------------- */
/* --- Methods --- */
/* -------------------------------------------------------------------------- */
// Debug support functions
PRIVATE void FFPU dump_first_bytes_buf(char *b, uae_u8* buf, uae_s32 actual);
PRIVATE char * FFPU etos(fpu_register const & e) REGPARAM;
// FPU consistency
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);
// 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);
// Conversion from extended floating-point values
PRIVATE uae_s32 FFPU extended_to_signed_32 ( fpu_register const & f ) REGPARAM;
PRIVATE uae_s16 FFPU extended_to_signed_16 ( fpu_register const & f ) REGPARAM;
PRIVATE uae_s8 FFPU extended_to_signed_8 ( fpu_register const & f ) REGPARAM;
PRIVATE fpu_double FFPU extended_to_double( fpu_register const & f ) REGPARAM;
PRIVATE uae_u32 FFPU from_single ( fpu_register const & f ) REGPARAM;
PRIVATE void FFPU from_exten ( fpu_register const & f, uae_u32 *wrd1, uae_u32 *wrd2, uae_u32 *wrd3 ) REGPARAM;
PRIVATE void FFPU from_double ( fpu_register const & f, uae_u32 *wrd1, uae_u32 *wrd2 ) REGPARAM;
PRIVATE void FFPU from_pack (fpu_double src, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3) REGPARAM;
// Conversion to extended floating-point values
PRIVATE void FFPU signed_to_extended ( uae_s32 x, fpu_register & f ) REGPARAM;
PRIVATE void FFPU double_to_extended ( double x, fpu_register & f ) REGPARAM;
PRIVATE void FFPU to_single ( uae_u32 src, fpu_register & f ) REGPARAM;
PRIVATE void FFPU to_exten_no_normalize ( uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3, fpu_register & f ) REGPARAM;
PRIVATE void FFPU to_exten ( uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3, fpu_register & f ) REGPARAM;
PRIVATE void FFPU to_double ( uae_u32 wrd1, uae_u32 wrd2, fpu_register & f ) REGPARAM;
PRIVATE fpu_double FFPU to_pack(uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3) REGPARAM;
// Atomic floating-point arithmetic operations
PRIVATE void FFPU do_fmove ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fmove_no_status ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fint ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fintrz ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fsqrt ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_ftst ( fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fsinh ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_flognp1 ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fetoxm1 ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_ftanh ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fatan ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fasin ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fatanh ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fetox ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_ftwotox ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_ftentox ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_flogn ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_flog10 ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_flog2 ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_facos ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fcosh ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fsin ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_ftan ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fabs ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fneg ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fcos ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fgetexp ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fgetman ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fdiv ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fmod ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_frem ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fmod_dont_set_cw ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_frem_dont_set_cw ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fadd ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fmul ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fsgldiv ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fscale ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fsglmul ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fsub ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fsincos ( fpu_register & dest_sin, fpu_register & dest_cos, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fcmp ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fldpi ( fpu_register & dest ) REGPARAM;
PRIVATE void FFPU do_fldlg2 ( fpu_register & dest ) REGPARAM;
PRIVATE void FFPU do_fldl2e ( fpu_register & dest ) REGPARAM;
PRIVATE void FFPU do_fldz ( fpu_register & dest ) REGPARAM;
PRIVATE void FFPU do_fldln2 ( fpu_register & dest ) REGPARAM;
PRIVATE void FFPU do_fld1 ( fpu_register & dest ) REGPARAM;
// Instructions handlers
PRIVATE void REGPARAM2 FFPU fpuop_illg( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmove_2_ea( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_none_2_Dreg( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpiar_2_Dreg( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_2_Dreg( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_2_Dreg( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_fpiar_2_Dreg( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpiar_2_Dreg( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_2_Dreg( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_fpiar_2_Dreg( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Dreg_2_none( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Dreg_2_fpiar( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Dreg_2_fpsr( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Dreg_2_fpsr_fpiar( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Dreg_2_fpcr( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Dreg_2_fpcr_fpiar( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Dreg_2_fpcr_fpsr( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Dreg_2_fpcr_fpsr_fpiar( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_none_2_Areg( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpiar_2_Areg( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_2_Areg( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_2_Areg( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_fpiar_2_Areg( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpiar_2_Areg( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_2_Areg( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_fpiar_2_Areg( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Areg_2_none( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Areg_2_fpiar( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Areg_2_fpsr( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Areg_2_fpsr_fpiar( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Areg_2_fpcr( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Areg_2_fpcr_fpiar( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Areg_2_fpcr_fpsr( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Areg_2_fpcr_fpsr_fpiar( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_none_2_Mem_predecrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpiar_2_Mem_predecrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_2_Mem_predecrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_fpiar_2_Mem_predecrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_2_Mem_predecrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpiar_2_Mem_predecrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_2_Mem_predecrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_fpiar_2_Mem_predecrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_none_2_Mem_postincrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpiar_2_Mem_postincrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_2_Mem_postincrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_fpiar_2_Mem_postincrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_2_Mem_postincrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpiar_2_Mem_postincrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_2_Mem_postincrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_fpiar_2_Mem_postincrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_none_2_Mem( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpiar_2_Mem( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_2_Mem( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_fpiar_2_Mem( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_2_Mem( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpiar_2_Mem( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_2_Mem( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_fpiar_2_Mem( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_none_predecrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpiar_predecrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpsr_predecrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpsr_fpiar_predecrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_predecrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpiar_predecrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_predecrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_fpiar_predecrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_none_postincrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpiar_postincrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpsr_postincrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpsr_fpiar_postincrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_postincrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpiar_postincrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_postincrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_fpiar_postincrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_none_2_Mem( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpiar_2_Mem( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpsr_2_Mem( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpsr_fpiar_2_Mem( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_2_Mem( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpiar_2_Mem( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_2_Mem( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_fpiar_2_Mem( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_static_pred_postincrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_static_pred_predecrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_static_pred( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_dynamic_pred_postincrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_dynamic_pred_predecrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_dynamic_pred( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_static_postinc_postincrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_static_postinc_predecrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_static_postinc( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_dynamic_postinc_postincrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_dynamic_postinc_predecrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_dynamic_postinc( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_static_pred_postincrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_static_pred_predecrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_static_pred( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_dynamic_pred_postincrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_dynamic_pred_predecrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_dynamic_pred( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_static_postinc_postincrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_static_postinc_predecrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_static_postinc( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_dynamic_postinc_postincrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_dynamic_postinc_predecrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_dynamic_postinc( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fldpi( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fldlg2( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_e( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fldl2e( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_log_10_e( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fldz( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fldln2( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_ln_10( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fld1( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e1( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e2( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e4( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e8( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e16( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e32( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e64( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e128( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e256( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e512( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e1024( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e2048( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e4096( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fmove( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fint( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fsinh( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fintrz( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fsqrt( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_flognp1( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fetoxm1( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_ftanh( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fatan( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fasin( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fatanh( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fsin( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_ftan( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fetox( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_ftwotox( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_ftentox( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_flogn( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_flog10( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_flog2( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fabs( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fcosh( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fneg( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_facos( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fcos( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fgetexp( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fgetman( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fdiv( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fmod( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_frem( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fadd( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fmul( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fsgldiv( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fscale( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fsglmul( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fsub( uae_u32 opcode, uae_u32 extra );
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;
PRIVATE int FFPU get_fp_ad(uae_u32 opcode, uae_u32 * ad) REGPARAM;
// Floating-point condition-based instruction handlers
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 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 );
#endif /* FPU_X86_H */

View File

@ -0,0 +1,104 @@
/*
* 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)
DEFINE_X86_MACRO(BSUN, 0x00008000);
DEFINE_X86_MACRO(SNAN, 0x00004000);
DEFINE_X86_MACRO(OPERR, 0x00002000);
DEFINE_X86_MACRO(OVFL, 0x00001000);
DEFINE_X86_MACRO(UNFL, 0x00000800);
DEFINE_X86_MACRO(DZ, 0x00000400);
DEFINE_X86_MACRO(INEX2, 0x00000200);
DEFINE_X86_MACRO(INEX1, 0x00000100);
DEFINE_X86_MACRO(ACCR_IOP, 0x80);
DEFINE_X86_MACRO(ACCR_OVFL, 0x40);
DEFINE_X86_MACRO(ACCR_UNFL, 0x20);
DEFINE_X86_MACRO(ACCR_DZ, 0x10);
DEFINE_X86_MACRO(ACCR_INEX, 0x08);
DEFINE_X86_MACRO(ROUND_CONTROL_MASK, 0x30);
DEFINE_X86_MACRO(ROUND_TO_NEAREST, 0);
DEFINE_X86_MACRO(ROUND_TO_ZERO, 0x10);
DEFINE_X86_MACRO(ROUND_TO_NEGATIVE_INFINITY, 0x20);
DEFINE_X86_MACRO(ROUND_TO_POSITIVE_INFINITY, 0x30);
DEFINE_X86_MACRO(PRECISION_CONTROL_MASK, 0xC0);
DEFINE_X86_MACRO(PRECISION_CONTROL_EXTENDED, 0);
DEFINE_X86_MACRO(PRECISION_CONTROL_DOUBLE, 0x80);
DEFINE_X86_MACRO(PRECISION_CONTROL_SINGLE, 0x40);
DEFINE_X86_MACRO(PRECISION_CONTROL_UNDEFINED, 0xC0);
DEFINE_X86_MACRO(CW_RESET, 0x0040);
DEFINE_X86_MACRO(CW_FINIT, 0x037F);
DEFINE_X86_MACRO(SW_RESET, 0x0000);
DEFINE_X86_MACRO(SW_FINIT, 0x0000);
DEFINE_X86_MACRO(TW_RESET, 0x5555);
DEFINE_X86_MACRO(TW_FINIT, 0x0FFF);
DEFINE_X86_MACRO(CW_X, 0x1000);
DEFINE_X86_MACRO(CW_RC_ZERO, 0x0C00);
DEFINE_X86_MACRO(CW_RC_UP, 0x0800);
DEFINE_X86_MACRO(CW_RC_DOWN, 0x0400);
DEFINE_X86_MACRO(CW_RC_NEAR, 0x0000);
DEFINE_X86_MACRO(CW_PC_EXTENDED, 0x0300);
DEFINE_X86_MACRO(CW_PC_DOUBLE, 0x0200);
DEFINE_X86_MACRO(CW_PC_RESERVED, 0x0100);
DEFINE_X86_MACRO(CW_PC_SINGLE, 0x0000);
DEFINE_X86_MACRO(CW_PM, 0x0020);
DEFINE_X86_MACRO(CW_UM, 0x0010);
DEFINE_X86_MACRO(CW_OM, 0x0008);
DEFINE_X86_MACRO(CW_ZM, 0x0004);
DEFINE_X86_MACRO(CW_DM, 0x0002);
DEFINE_X86_MACRO(CW_IM, 0x0001);
DEFINE_X86_MACRO(SW_B, 0x8000);
DEFINE_X86_MACRO(SW_C3, 0x4000);
DEFINE_X86_MACRO(SW_TOP_7, 0x3800);
DEFINE_X86_MACRO(SW_TOP_6, 0x3000);
DEFINE_X86_MACRO(SW_TOP_5, 0x2800);
DEFINE_X86_MACRO(SW_TOP_4, 0x2000);
DEFINE_X86_MACRO(SW_TOP_3, 0x1800);
DEFINE_X86_MACRO(SW_TOP_2, 0x1000);
DEFINE_X86_MACRO(SW_TOP_1, 0x0800);
DEFINE_X86_MACRO(SW_TOP_0, 0x0000);
DEFINE_X86_MACRO(SW_C2, 0x0400);
DEFINE_X86_MACRO(SW_C1, 0x0200);
DEFINE_X86_MACRO(SW_C0, 0x0100);
DEFINE_X86_MACRO(SW_ES, 0x0080);
DEFINE_X86_MACRO(SW_SF, 0x0040);
DEFINE_X86_MACRO(SW_PE, 0x0020);
DEFINE_X86_MACRO(SW_UE, 0x0010);
DEFINE_X86_MACRO(SW_OE, 0x0008);
DEFINE_X86_MACRO(SW_ZE, 0x0004);
DEFINE_X86_MACRO(SW_DE, 0x0002);
DEFINE_X86_MACRO(SW_IE, 0x0001);
DEFINE_X86_MACRO(X86_ROUNDING_MODE, 0x0C00);
DEFINE_X86_MACRO(X86_ROUNDING_PRECISION, 0x0300);
#undef DEFINE_X86_MACRO

View File

@ -0,0 +1,159 @@
/*
* fpu/impl.h - extra functions and inline implementations
*
* 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
*
* 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
#define FPU_IMPL_H
/* NOTE: this file shall be included from fpu/core.h */
#undef PUBLIC
#define PUBLIC /**/
#undef PRIVATE
#define PRIVATE /**/
#undef FFPU
#define FFPU /**/
#undef FPU
#define FPU fpu.
/* -------------------------------------------------------------------------- */
/* --- X86 assembly fpu specific methods --- */
/* -------------------------------------------------------------------------- */
#ifdef FPU_X86
/* Return the floating-point status register in m68k format */
static inline uae_u32 FFPU get_fpsr(void)
{
return to_m68k_fpcond[(x86_status_word & 0x4700) >> 8]
| FPU fpsr.quotient
| exception_host2mac[x86_status_word & (SW_FAKE_BSUN|SW_PE|SW_UE|SW_OE|SW_ZE|SW_DE|SW_IE)]
| accrued_exception_host2mac[x86_status_word_accrued & (SW_PE|SW_UE|SW_OE|SW_ZE|SW_DE|SW_IE)]
;
}
/* Set the floating-point status register from an m68k format */
static inline void FFPU set_fpsr(uae_u32 new_fpsr)
{
x86_status_word = to_host_fpcond[(new_fpsr & FPSR_CCB) >> 24 ]
| exception_mac2host[(new_fpsr & FPSR_EXCEPTION_STATUS) >> 8];
x86_status_word_accrued = accrued_exception_mac2host[(new_fpsr & FPSR_ACCRUED_EXCEPTION) >> 3];
}
#endif
/* -------------------------------------------------------------------------- */
/* --- Original UAE and IEEE FPU core methods --- */
/* -------------------------------------------------------------------------- */
#ifndef FPU_X86
/* Return the floating-point status register in m68k format */
static inline uae_u32 FFPU get_fpsr(void)
{
uae_u32 condition_codes = get_fpccr();
uae_u32 exception_status = get_exception_status();
uae_u32 accrued_exception = get_accrued_exception();
uae_u32 quotient = FPU fpsr.quotient;
return (condition_codes | quotient | exception_status | accrued_exception);
}
/* Set the floating-point status register from an m68k format */
static inline void FFPU set_fpsr(uae_u32 new_fpsr)
{
set_fpccr ( new_fpsr & FPSR_CCB );
set_exception_status ( new_fpsr & FPSR_EXCEPTION_STATUS );
set_accrued_exception ( new_fpsr & FPSR_ACCRUED_EXCEPTION );
FPU fpsr.quotient = new_fpsr & FPSR_QUOTIENT;
}
#endif
/* -------------------------------------------------------------------------- */
/* --- Common routines for control word --- */
/* -------------------------------------------------------------------------- */
/* 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();
uae_u32 exception_enable = FPU fpcr.exception_enable;
return (rounding_precision | rounding_mode | exception_enable);
}
/* Set the floating-point control register from an m68k format */
static inline void FFPU set_fpcr(uae_u32 new_fpcr)
{
set_rounding_precision ( new_fpcr & FPCR_ROUNDING_PRECISION);
set_rounding_mode ( new_fpcr & FPCR_ROUNDING_MODE );
set_host_control_word();
FPU fpcr.exception_enable = new_fpcr & FPCR_EXCEPTION_ENABLE;
}
/* -------------------------------------------------------------------------- */
/* --- Specific part to X86 assembly FPU --- */
/* -------------------------------------------------------------------------- */
#ifdef FPU_X86
/* 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;
}
#endif
/* -------------------------------------------------------------------------- */
/* --- Specific to original UAE or new IEEE-based FPU core --- */
/* -------------------------------------------------------------------------- */
#if defined(FPU_UAE) || defined(FPU_IEEE)
/* Retrieve a floating-point register value and convert it to double precision */
static inline double FFPU fpu_get_register(int r)
{
return FPU registers[r];
}
#endif
#endif /* FPU_IMPL_H */

View File

@ -0,0 +1,105 @@
/*
* fpu/mathlib.cpp - Floating-point math support library
*
* 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
*/
/* NOTE: this file shall be included only from fpu/fpu_*.cpp */
#undef PRIVATE
#define PRIVATE static
#undef PUBLIC
#define PUBLIC /**/
#undef FFPU
#define FFPU /**/
#undef FPU
#define FPU fpu.
#if defined(FPU_IEEE) && defined(USE_X87_ASSEMBLY)
PRIVATE fpu_extended fp_do_pow(fpu_extended x, fpu_extended y)
{
fpu_extended value, exponent;
uae_s64 p = (uae_s64)y;
if (x == 0.0) {
if (y > 0.0)
return (y == (double) p && (p & 1) != 0 ? x : 0.0);
else if (y < 0.0)
return (y == (double) p && (-p & 1) != 0 ? 1.0 / x : 1.0 / fp_fabs (x));
}
if (y == (double) p) {
fpu_extended r = 1.0;
if (p == 0)
return 1.0;
if (p < 0) {
p = -p;
x = 1.0 / x;
}
while (1) {
if (p & 1)
r *= x;
p >>= 1;
if (p == 0)
return r;
x *= x;
}
}
__asm__ __volatile__("fyl2x" : "=t" (value) : "0" (x), "u" (1.0) : "st(1)");
__asm__ __volatile__("fmul %%st(1) # y * log2(x)\n\t"
"fst %%st(1)\n\t"
"frndint # int(y * log2(x))\n\t"
"fxch\n\t"
"fsub %%st(1) # fract(y * log2(x))\n\t"
"f2xm1 # 2^(fract(y * log2(x))) - 1\n\t"
: "=t" (value), "=u" (exponent) : "0" (y), "1" (value));
value += 1.0;
__asm__ __volatile__("fscale" : "=t" (value) : "0" (value), "u" (exponent));
return value;
}
PRIVATE fpu_extended fp_do_log1p(fpu_extended x)
{
// TODO: handle NaN and +inf/-inf
fpu_extended value;
// The fyl2xp1 can only be used for values in
// -1 + sqrt(2) / 2 <= x <= 1 - sqrt(2) / 2
// 0.29 is a safe value.
if (fp_fabs(x) <= 0.29)
__asm__ __volatile__("fldln2; fxch; fyl2xp1" : "=t" (value) : "0" (x));
else
__asm__ __volatile__("fldln2; fxch; fyl2x" : "=t" (value) : "0" (x + 1.0));
return value;
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,69 @@
/*
* fpu/rounding.cpp - system-dependant FPU rounding mode and precision
*
* 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
*/
#undef PRIVATE
#define PRIVATE /**/
#undef PUBLIC
#define PUBLIC /**/
#undef FFPU
#define FFPU /**/
#undef FPU
#define FPU fpu.
/* -------------------------------------------------------------------------- */
/* --- Native X86 Rounding Mode --- */
/* -------------------------------------------------------------------------- */
#ifdef FPU_USE_X86_ROUNDING_MODE
const uae_u32 FFPU x86_control_word_rm_mac2host[] = {
CW_RC_NEAR,
CW_RC_ZERO,
CW_RC_DOWN,
CW_RC_UP
};
#endif
/* -------------------------------------------------------------------------- */
/* --- Native X86 Rounding Precision --- */
/* -------------------------------------------------------------------------- */
#ifdef FPU_USE_X86_ROUNDING_PRECISION
const uae_u32 FFPU x86_control_word_rp_mac2host[] = {
CW_PC_EXTENDED,
CW_PC_SINGLE,
CW_PC_DOUBLE,
CW_PC_RESERVED
};
#endif

View File

@ -0,0 +1,159 @@
/*
* fpu/rounding.h - system-dependant FPU rounding mode and precision
*
* 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
*/
#ifndef FPU_ROUNDING_H
#define FPU_ROUNDING_H
/* NOTE: this file shall be included from fpu/fpu_*.cpp */
#undef PUBLIC
#define PUBLIC extern
#undef PRIVATE
#define PRIVATE static
#undef FFPU
#define FFPU /**/
#undef FPU
#define FPU fpu.
/* Defaults to generic rounding mode and precision handling */
#define FPU_USE_GENERIC_ROUNDING_MODE
#define FPU_USE_GENERIC_ROUNDING_PRECISION
/* -------------------------------------------------------------------------- */
/* --- Selection of floating-point rounding mode and precision --- */
/* -------------------------------------------------------------------------- */
/* Optimized i386 fpu core must use native rounding mode */
#if defined(FPU_X86) && defined(USE_X87_ASSEMBLY)
# undef FPU_USE_GENERIC_ROUNDING_MODE
# define FPU_USE_X86_ROUNDING_MODE
#endif
/* Optimized i386 fpu core must use native rounding precision */
#if defined(FPU_X86) && defined(USE_X87_ASSEMBLY)
# undef FPU_USE_GENERIC_ROUNDING_PRECISION
# define FPU_USE_X86_ROUNDING_PRECISION
#endif
#if 0 // gb-- FIXME: that doesn't work
/* IEEE-based fpu core can have native rounding mode on i386 */
#if defined(FPU_IEEE) && defined(USE_X87_ASSEMBLY)
# undef FPU_USE_GENERIC_ROUNDING_MODE
# define FPU_USE_X86_ROUNDING_MODE
#endif
/* IEEE-based fpu core can have native rounding precision on i386 */
#if defined(FPU_IEEE) && defined(USE_X87_ASSEMBLY)
# undef FPU_USE_GENERIC_ROUNDING_PRECISION
# define FPU_USE_X86_ROUNDING_PRECISION
#endif
#endif
/* -------------------------------------------------------------------------- */
/* --- Sanity checks --- */
/* -------------------------------------------------------------------------- */
/* X86 rounding mode and precision work together */
#if defined(FPU_USE_X86_ROUNDING_MODE) && defined(FPU_USE_X86_ROUNDING_PRECISION)
# define FPU_USE_X86_ROUNDING
# define CW_INITIAL (CW_RESET|CW_X|CW_PC_EXTENDED|CW_RC_NEAR|CW_PM|CW_UM|CW_OM|CW_ZM|CW_DM|CW_IM)
PRIVATE uae_u32 x86_control_word;
#endif
/* Control word -- rounding mode */
#ifdef FPU_USE_X86_ROUNDING_MODE
PUBLIC const uae_u32 x86_control_word_rm_mac2host[];
#endif
/* Control word -- rounding precision */
#ifdef FPU_USE_X86_ROUNDING_PRECISION
PUBLIC const uae_u32 x86_control_word_rp_mac2host[];
#endif
#if defined(FPU_USE_X86_ROUNDING_MODE) && defined(FPU_USE_X86_ROUNDING_PRECISION)
/* Set host control word for rounding mode and rounding precision */
PRIVATE inline void set_host_control_word(void)
{
/*
Exception enable byte is ignored, but the same value is returned
that was previously set.
*/
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]
;
__asm__ __volatile__("fldcw %0" : : "m" (x86_control_word));
}
#endif
/* -------------------------------------------------------------------------- */
/* --- Generic rounding mode and precision --- */
/* -------------------------------------------------------------------------- */
#if defined(FPU_USE_GENERIC_ROUNDING_MODE) && defined(FPU_USE_GENERIC_ROUNDING_PRECISION)
/* Set host control word for rounding mode and rounding precision */
PRIVATE inline void set_host_control_word(void)
{ }
#endif
/* -------------------------------------------------------------------------- */
/* --- Common rounding mode and precision --- */
/* -------------------------------------------------------------------------- */
#if defined(FPU_USE_GENERIC_ROUNDING_MODE) || defined(FPU_USE_X86_ROUNDING_MODE)
/* Return the current rounding mode in m68k format */
static inline uae_u32 FFPU get_rounding_mode(void)
{ return FPU 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; }
#endif
#if defined(FPU_USE_GENERIC_ROUNDING_PRECISION) || defined(FPU_USE_X86_ROUNDING_PRECISION)
/* Return the current rounding precision in m68k format */
static inline uae_u32 FFPU get_rounding_precision(void)
{ return FPU 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; }
#endif
#endif /* FPU_ROUNDING_H */

View File

@ -0,0 +1,181 @@
/*
* fpu/types.h - basic types for fpu registers
*
* 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
*/
#ifndef FPU_TYPES_H
#define FPU_TYPES_H
#include "sysdeps.h"
/* Default behavior is *not* to use long doubles */
#undef USE_LONG_DOUBLE
#undef USE_QUAD_DOUBLE
/* -------------------------------------------------------------------------- */
/* --- Original UAE fpu core --- */
/* -------------------------------------------------------------------------- */
#if defined(FPU_UAE)
/* 4-byte floats */
#if SIZEOF_FLOAT == 4
typedef float uae_f32;
#elif SIZEOF_DOUBLE == 4
typedef double uae_f32;
#else
#error "No 4 byte float type, you lose."
#endif
/* 8-byte floats */
#if SIZEOF_DOUBLE == 8
typedef double uae_f64;
#elif SIZEOF_LONG_DOUBLE == 8
typedef long double uae_f64;
#else
#error "No 8 byte float type, you lose."
#endif
/* Original UAE FPU registers are only 8 bytes long */
typedef uae_f64 fpu_register;
typedef fpu_register fpu_extended;
typedef uae_f64 fpu_double;
typedef uae_f32 fpu_single;
/* -------------------------------------------------------------------------- */
/* --- Optimized core for x86 --- */
/* -------------------------------------------------------------------------- */
#elif defined(FPU_X86)
/* 4-byte floats */
#if SIZEOF_FLOAT == 4
typedef float uae_f32;
#elif SIZEOF_DOUBLE == 4
typedef double uae_f32;
#else
#error "No 4 byte float type, you lose."
#endif
/* 8-byte floats */
#if SIZEOF_DOUBLE == 8
typedef float uae_f64;
#elif SIZEOF_LONG_DOUBLE == 8
typedef double uae_f64;
#else
#error "No 8 byte float type, you lose."
#endif
/* At least 10-byte floats are required */
#if SIZEOF_LONG_DOUBLE >= 10
typedef long double fpu_register;
#else
#error "No float type at least 10 bytes long, you lose."
#endif
/* X86 FPU has a custom register type that maps to a native X86 register */
typedef fpu_register fpu_extended;
typedef uae_f64 fpu_double;
typedef uae_f32 fpu_single;
/* -------------------------------------------------------------------------- */
/* --- C99 implementation --- */
/* -------------------------------------------------------------------------- */
#elif defined(FPU_IEEE)
#if HOST_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
#error "No IEEE float format, you lose."
#endif
/* 4-byte floats */
#if SIZEOF_FLOAT == 4
typedef float uae_f32;
#elif SIZEOF_DOUBLE == 4
typedef double uae_f32;
#else
#error "No 4 byte float type, you lose."
#endif
/* 8-byte floats */
#if SIZEOF_DOUBLE == 8
typedef double uae_f64;
#elif SIZEOF_LONG_DOUBLE == 8
typedef long double uae_f64;
#else
#error "No 8 byte float type, you lose."
#endif
/* 12-byte or 16-byte floats */
#if SIZEOF_LONG_DOUBLE == 12
typedef long double uae_f96;
typedef uae_f96 fpu_register;
#define USE_LONG_DOUBLE 1
#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;
#define USE_LONG_DOUBLE 1
#elif 0
/* Disable for now and probably for good as (i) the emulator
implementation is not correct, (ii) I don't know of any CPU which
handles this kind of format *natively* with conformance to IEEE. */
typedef long double uae_f128;
typedef uae_f128 fpu_register;
#define USE_QUAD_DOUBLE 1
#else
typedef uae_f64 fpu_register;
#endif
/* We need all those floating-point types */
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,36 +1,85 @@
/*
* m68k.h - machine dependent bits
*
* 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
*
* MC68000 emulation - machine dependent bits
*
* Copyright 1996 Bernd Schmidt
*
*/
#if defined(__i386__) && defined(X86_ASSEMBLY)
#ifndef M68K_FLAGS_H
#define M68K_FLAGS_H
#ifdef OPTIMIZED_FLAGS
#if (defined(CPU_i386) && defined(X86_ASSEMBLY)) || (defined(CPU_x86_64) && defined(X86_64_ASSEMBLY))
# include <cstdlib>
#ifndef SAHF_SETO_PROFITABLE
/* 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 int cznv;
unsigned int x;
#if defined(CPU_x86_64)
uint64 cznv;
uint64 x;
#else
uint32 cznv;
uint32 x;
#endif
};
#define SET_ZFLG(y) (regflags.cznv = (regflags.cznv & ~0x40) | (((y) & 1) << 6))
#define SET_CFLG(y) (regflags.cznv = (regflags.cznv & ~1) | ((y) & 1))
#define SET_VFLG(y) (regflags.cznv = (regflags.cznv & ~0x800) | (((y) & 1) << 11))
#define SET_NFLG(y) (regflags.cznv = (regflags.cznv & ~0x80) | (((y) & 1) << 7))
#define SET_XFLG(y) (regflags.x = (y))
#define FLAGVAL_Z 0x40
#define FLAGVAL_N 0x80
#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 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 CLEAR_CZNV (regflags.cznv = 0)
#define COPY_CARRY (regflags.x = regflags.cznv)
#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 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)
extern struct flag_struct regflags __asm__ ("regflags");
static __inline__ int cctrue(int cc)
static inline int cctrue(int cc)
{
uae_u32 cznv = regflags.cznv;
switch(cc){
@ -58,91 +107,553 @@ static __inline__ int cctrue(int cc)
return 0;
}
#define x86_flag_testl(v) \
__asm__ __volatile__ ("testl %1,%1\n\t" \
"pushfl\n\t" \
"popl %0\n\t" \
: "=r" (regflags.cznv) : "r" (v) : "cc")
#define optflag_testl(v) \
__asm__ __volatile__ ("andl %1,%1\n\t" \
"pushf\n\t" \
"pop %0\n\t" \
: "=rm" (regflags.cznv) : "r" (v) : "memory", "cc")
#define x86_flag_testw(v) \
__asm__ __volatile__ ("testw %w1,%w1\n\t" \
"pushfl\n\t" \
"popl %0\n\t" \
: "=r" (regflags.cznv) : "r" (v) : "cc")
#define optflag_testw(v) \
__asm__ __volatile__ ("andw %w1,%w1\n\t" \
"pushf\n\t" \
"pop %0\n\t" \
: "=rm" (regflags.cznv) : "r" (v) : "memory", "cc")
#define x86_flag_testb(v) \
__asm__ __volatile__ ("testb %b1,%b1\n\t" \
"pushfl\n\t" \
"popl %0\n\t" \
: "=r" (regflags.cznv) : "q" (v) : "cc")
#define optflag_testb(v) \
__asm__ __volatile__ ("andb %b1,%b1\n\t" \
"pushf\n\t" \
"pop %0\n\t" \
: "=rm" (regflags.cznv) : "q" (v) : "memory", "cc")
#define x86_flag_addl(v, s, d) do { \
#define optflag_addl(v, s, d) do { \
__asm__ __volatile__ ("addl %k2,%k1\n\t" \
"pushfl\n\t" \
"popl %0\n\t" \
: "=r" (regflags.cznv), "=r" (v) : "rmi" (s), "1" (d) : "cc"); \
"pushf\n\t" \
"pop %0\n\t" \
: "=rm" (regflags.cznv), "=r" (v) : "rmi" (s), "1" (d) : "memory", "cc"); \
COPY_CARRY; \
} while (0)
#define x86_flag_addw(v, s, d) do { \
#define optflag_addw(v, s, d) do { \
__asm__ __volatile__ ("addw %w2,%w1\n\t" \
"pushfl\n\t" \
"popl %0\n\t" \
: "=r" (regflags.cznv), "=r" (v) : "rmi" (s), "1" (d) : "cc"); \
"pushf\n\t" \
"pop %0\n\t" \
: "=rm" (regflags.cznv), "=r" (v) : "rmi" (s), "1" (d) : "memory", "cc"); \
COPY_CARRY; \
} while (0)
#define x86_flag_addb(v, s, d) do { \
#define optflag_addb(v, s, d) do { \
__asm__ __volatile__ ("addb %b2,%b1\n\t" \
"pushfl\n\t" \
"popl %0\n\t" \
"pushf\n\t" \
"pop %0\n\t" \
: "=r" (regflags.cznv), "=q" (v) : "qmi" (s), "1" (d) : "cc"); \
COPY_CARRY; \
} while (0)
#define x86_flag_subl(v, s, d) do { \
#define optflag_subl(v, s, d) do { \
__asm__ __volatile__ ("subl %k2,%k1\n\t" \
"pushfl\n\t" \
"popl %0\n\t" \
: "=r" (regflags.cznv), "=r" (v) : "rmi" (s), "1" (d) : "cc"); \
"pushf\n\t" \
"pop %0\n\t" \
: "=rm" (regflags.cznv), "=r" (v) : "rmi" (s), "1" (d) : "memory", "cc"); \
COPY_CARRY; \
} while (0)
#define x86_flag_subw(v, s, d) do { \
#define optflag_subw(v, s, d) do { \
__asm__ __volatile__ ("subw %w2,%w1\n\t" \
"pushfl\n\t" \
"popl %0\n\t" \
: "=r" (regflags.cznv), "=r" (v) : "rmi" (s), "1" (d) : "cc"); \
"pushf\n\t" \
"pop %0\n\t" \
: "=rm" (regflags.cznv), "=r" (v) : "rmi" (s), "1" (d) : "memory", "cc"); \
COPY_CARRY; \
} while (0)
#define x86_flag_subb(v, s, d) do { \
#define optflag_subb(v, s, d) do { \
__asm__ __volatile__ ("subb %b2,%b1\n\t" \
"pushfl\n\t" \
"popl %0\n\t" \
: "=r" (regflags.cznv), "=q" (v) : "qmi" (s), "1" (d) : "cc"); \
"pushf\n\t" \
"pop %0\n\t" \
: "=rm" (regflags.cznv), "=q" (v) : "qmi" (s), "1" (d) : "memory", "cc"); \
COPY_CARRY; \
} while (0)
#define x86_flag_cmpl(s, d) \
#define optflag_cmpl(s, d) \
__asm__ __volatile__ ("cmpl %k1,%k2\n\t" \
"pushfl\n\t" \
"popl %0\n\t" \
: "=r" (regflags.cznv) : "rmi" (s), "r" (d) : "cc")
"pushf\n\t" \
"pop %0\n\t" \
: "=rm" (regflags.cznv) : "rmi" (s), "r" (d) : "memory", "cc")
#define x86_flag_cmpw(s, d) \
#define optflag_cmpw(s, d) \
__asm__ __volatile__ ("cmpw %w1,%w2\n\t" \
"pushfl\n\t" \
"popl %0\n\t" \
: "=r" (regflags.cznv) : "rmi" (s), "r" (d) : "cc")
"pushf\n\t" \
"pop %0\n\t" \
: "=rm" (regflags.cznv) : "rmi" (s), "r" (d) : "memory", "cc")
#define x86_flag_cmpb(s, d) \
#define optflag_cmpb(s, d) \
__asm__ __volatile__ ("cmpb %b1,%b2\n\t" \
"pushfl\n\t" \
"popl %0\n\t" \
: "=r" (regflags.cznv) : "qmi" (s), "q" (d) : "cc")
"pushf\n\t" \
"pop %0\n\t" \
: "=rm" (regflags.cznv) : "qmi" (s), "q" (d) : "memory", "cc")
#elif defined(__sparc__) && (defined(SPARC_V8_ASSEMBLY) || defined(SPARC_V9_ASSEMBLY))
#else
struct flag_struct {
uae_u32 cznv;
uae_u32 x;
};
#define FLAGVAL_Z 0x4000
#define FLAGVAL_N 0x8000
#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))
#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 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)>>8)
extern struct flag_struct regflags __asm__ ("regflags");
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 */
}
abort();
return 0;
}
/* Manually emit LAHF instruction so that 64-bit assemblers can grok it */
#if defined CPU_x86_64 && defined __GNUC__
#define ASM_LAHF ".byte 0x9f"
#else
#define ASM_LAHF "lahf"
#endif
/* Is there any way to do this without declaring *all* memory clobbered?
I.e. any way to tell gcc that some byte-sized value is in %al? */
#define optflag_testl(v) \
__asm__ __volatile__ ("andl %0,%0\n\t" \
ASM_LAHF "\n\t" \
"seto %%al\n\t" \
"movb %%al,regflags\n\t" \
"movb %%ah,regflags+1\n\t" \
: : "r" (v) : "%eax","cc","memory")
#define optflag_testw(v) \
__asm__ __volatile__ ("andw %w0,%w0\n\t" \
ASM_LAHF "\n\t" \
"seto %%al\n\t" \
"movb %%al,regflags\n\t" \
"movb %%ah,regflags+1\n\t" \
: : "r" (v) : "%eax","cc","memory")
#define optflag_testb(v) \
__asm__ __volatile__ ("andb %b0,%b0\n\t" \
ASM_LAHF "\n\t" \
"seto %%al\n\t" \
"movb %%al,regflags\n\t" \
"movb %%ah,regflags+1\n\t" \
: : "q" (v) : "%eax","cc","memory")
#define optflag_addl(v, s, d) do { \
__asm__ __volatile__ ("addl %k1,%k0\n\t" \
ASM_LAHF "\n\t" \
"seto %%al\n\t" \
"movb %%al,regflags\n\t" \
"movb %%ah,regflags+1\n\t" \
: "=r" (v) : "rmi" (s), "0" (d) : "%eax","cc","memory"); \
COPY_CARRY; \
} while (0)
#define optflag_addw(v, s, d) do { \
__asm__ __volatile__ ("addw %w1,%w0\n\t" \
ASM_LAHF "\n\t" \
"seto %%al\n\t" \
"movb %%al,regflags\n\t" \
"movb %%ah,regflags+1\n\t" \
: "=r" (v) : "rmi" (s), "0" (d) : "%eax","cc","memory"); \
COPY_CARRY; \
} while (0)
#define optflag_addb(v, s, d) do { \
__asm__ __volatile__ ("addb %b1,%b0\n\t" \
ASM_LAHF "\n\t" \
"seto %%al\n\t" \
"movb %%al,regflags\n\t" \
"movb %%ah,regflags+1\n\t" \
: "=q" (v) : "qmi" (s), "0" (d) : "%eax","cc","memory"); \
COPY_CARRY; \
} while (0)
#define optflag_subl(v, s, d) do { \
__asm__ __volatile__ ("subl %k1,%k0\n\t" \
ASM_LAHF "\n\t" \
"seto %%al\n\t" \
"movb %%al,regflags\n\t" \
"movb %%ah,regflags+1\n\t" \
: "=r" (v) : "rmi" (s), "0" (d) : "%eax","cc","memory"); \
COPY_CARRY; \
} while (0)
#define optflag_subw(v, s, d) do { \
__asm__ __volatile__ ("subw %w1,%w0\n\t" \
ASM_LAHF "\n\t" \
"seto %%al\n\t" \
"movb %%al,regflags\n\t" \
"movb %%ah,regflags+1\n\t" \
: "=r" (v) : "rmi" (s), "0" (d) : "%eax","cc","memory"); \
COPY_CARRY; \
} while (0)
#define optflag_subb(v, s, d) do { \
__asm__ __volatile__ ("subb %b1,%b0\n\t" \
ASM_LAHF "\n\t" \
"seto %%al\n\t" \
"movb %%al,regflags\n\t" \
"movb %%ah,regflags+1\n\t" \
: "=q" (v) : "qmi" (s), "0" (d) : "%eax","cc","memory"); \
COPY_CARRY; \
} while (0)
#define optflag_cmpl(s, d) \
__asm__ __volatile__ ("cmpl %k0,%k1\n\t" \
ASM_LAHF "\n\t" \
"seto %%al\n\t" \
"movb %%al,regflags\n\t" \
"movb %%ah,regflags+1\n\t" \
: : "rmi" (s), "r" (d) : "%eax","cc","memory")
#define optflag_cmpw(s, d) \
__asm__ __volatile__ ("cmpw %w0,%w1\n\t" \
ASM_LAHF "\n\t" \
"seto %%al\n\t" \
"movb %%al,regflags\n\t" \
"movb %%ah,regflags+1\n\t" \
: : "rmi" (s), "r" (d) : "%eax","cc","memory")
#define optflag_cmpb(s, d) \
__asm__ __volatile__ ("cmpb %b0,%b1\n\t" \
ASM_LAHF "\n\t" \
"seto %%al\n\t" \
"movb %%al,regflags\n\t" \
"movb %%ah,regflags+1\n\t" \
: : "qmi" (s), "q" (d) : "%eax","cc","memory")
#endif
#elif defined(CPU_arm) && defined(ARM_ASSEMBLY)
struct flag_struct {
uae_u32 nzcv;
uae_u32 x;
};
#define FLAGVAL_Q 0x08000000
#define FLAGVAL_V 0x10000000
#define FLAGVAL_C 0x20000000
#define FLAGVAL_Z 0x40000000
#define FLAGVAL_N 0x80000000
#define SET_NFLG(y) (regflags.nzcv = (regflags.nzcv & ~0x80000000) | (((y) & 1) << 31))
#define SET_ZFLG(y) (regflags.nzcv = (regflags.nzcv & ~0x40000000) | (((y) & 1) << 30))
#define SET_CFLG(y) (regflags.nzcv = (regflags.nzcv & ~0x20000000) | (((y) & 1) << 29))
#define SET_VFLG(y) (regflags.nzcv = (regflags.nzcv & ~0x10000000) | (((y) & 1) << 28))
#define SET_XFLG(y) (regflags.x = (y))
#define GET_NFLG ((regflags.nzcv >> 31) & 1)
#define GET_ZFLG ((regflags.nzcv >> 30) & 1)
#define GET_CFLG ((regflags.nzcv >> 29) & 1)
#define GET_VFLG ((regflags.nzcv >> 28) & 1)
#define GET_XFLG (regflags.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)>>29)
extern struct flag_struct regflags __asm__ ("regflags");
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 & 0x60000000) == 0; /* !GET_CFLG && !GET_ZFLG; HI */
case 3: return (nzcv & 0x60000000) != 0; /* GET_CFLG || GET_ZFLG; LS */
case 4: return (nzcv & 0x20000000) == 0; /* !GET_CFLG; CC */
case 5: return (nzcv & 0x20000000) != 0; /* GET_CFLG; CS */
case 6: return (nzcv & 0x40000000) == 0; /* !GET_ZFLG; NE */
case 7: return (nzcv & 0x40000000) != 0; /* GET_ZFLG; EQ */
case 8: return (nzcv & 0x10000000) == 0; /* !GET_VFLG; VC */
case 9: return (nzcv & 0x10000000) != 0; /* GET_VFLG; VS */
case 10:return (nzcv & 0x80000000) == 0; /* !GET_NFLG; PL */
case 11:return (nzcv & 0x80000000) != 0; /* GET_NFLG; MI */
case 12:return (((nzcv << 3) ^ nzcv) & 0x80000000) == 0; /* GET_NFLG == GET_VFLG; GE */
case 13:return (((nzcv << 3) ^ nzcv) & 0x80000000) != 0; /* GET_NFLG != GET_VFLG; LT */
case 14:
nzcv &= 0xd0000000;
return (((nzcv << 3) ^ nzcv) & 0xc0000000) == 0; /* !GET_ZFLG && (GET_NFLG == GET_VFLG); GT */
case 15:
nzcv &= 0xd0000000;
return (((nzcv << 3) ^ nzcv) & 0xc0000000) != 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(CPU_sparc) && (defined(SPARC_V8_ASSEMBLY) || defined(SPARC_V9_ASSEMBLY))
struct flag_struct {
unsigned char nzvc;
@ -151,22 +662,29 @@ struct flag_struct {
extern struct flag_struct regflags;
#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_Z 0x04
#define FLAGVAL_N 0x08
#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 & ~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 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 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 CLEAR_CZNV (regflags.nzvc = 0)
#define COPY_CARRY (regflags.x = regflags.nzvc)
static __inline__ int cctrue(int cc)
static inline int cctrue(int cc)
{
uae_u32 nzvc = regflags.nzvc;
switch(cc){
@ -787,6 +1305,8 @@ static inline uae_u32 sparc_v9_flag_addx_32(flag_struct *flags, uae_u32 src, uae
#endif /* SPARC_V9_ASSEMBLY */
#endif
#else
struct flag_struct {
@ -805,7 +1325,28 @@ extern struct flag_struct regflags;
#define VFLG (regflags.v)
#define XFLG (regflags.x)
static __inline__ int cctrue(const int cc)
#define SET_CFLG(x) (CFLG = (x))
#define SET_NFLG(x) (NFLG = (x))
#define SET_VFLG(x) (VFLG = (x))
#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 CLEAR_CZNV do { \
SET_CFLG (0); \
SET_ZFLG (0); \
SET_NFLG (0); \
SET_VFLG (0); \
} while (0)
#define COPY_CARRY (SET_XFLG (GET_CFLG))
static inline int cctrue(const int cc)
{
switch(cc){
case 0: return 1; /* T */
@ -828,4 +1369,6 @@ static __inline__ int cctrue(const int cc)
return 0;
}
#endif
#endif /* OPTIMIZED_FLAGS */
#endif /* M68K_FLAGS_H */

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

@ -0,0 +1,59 @@
/*
* memory.cpp - memory management
*
* 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
*
* Memory management
*
* (c) 1995 Bernd Schmidt
*/
#include "sysdeps.h"
#include "memory.h"
#define DEBUG 0
#include "debug.h"
#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
extern "C" void breakpt(void)
{
// bug("bus err: pc=%08x, sp=%08x, addr=%08x", m68k_getpc(), regs.regs[15], regs.mmu_fault_addr);
}
#if !KNOWN_ALLOC && !NORMAL_ADDRESSING
// This part need rewrite for ARAnyM !!
// It can be taken from hatari.
#error Not prepared for your platform, maybe you need memory banks from hatari
#endif /* !KNOWN_ALLOC && !NORMAL_ADDRESSING */

View File

@ -27,6 +27,34 @@
extern uintptr MEMBaseDiff;
#endif
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)
{
@ -41,40 +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);
}
#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,3 +1,27 @@
/*
* newcpu.h - CPU emulation
*
* Copyright (c) 2009 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
*
@ -6,41 +30,22 @@
* Copyright 1995 Bernd Schmidt
*/
#define SPCFLAG_STOP 2
#define SPCFLAG_DISK 4
#define SPCFLAG_INT 8
#define SPCFLAG_BRK 16
#define SPCFLAG_EXTRA_CYCLES 32
#define SPCFLAG_TRACE 64
#define SPCFLAG_DOTRACE 128
#define SPCFLAG_DOINT 256
#define SPCFLAG_BLTNASTY 512
#define SPCFLAG_EXEC 1024
#define SPCFLAG_MODE_CHANGE 8192
#ifndef NEWCPU_H
#define NEWCPU_H
#ifndef SET_CFLG
#include "sysdeps.h"
#include "registers.h"
#include "spcflags.h"
#include "m68k.h"
#include "memory.h"
#define SET_CFLG(x) (CFLG = (x))
#define SET_NFLG(x) (NFLG = (x))
#define SET_VFLG(x) (VFLG = (x))
#define SET_ZFLG(x) (ZFLG = (x))
#define SET_XFLG(x) (XFLG = (x))
# include <csetjmp>
#define GET_CFLG CFLG
#define GET_NFLG NFLG
#define GET_VFLG VFLG
#define GET_ZFLG ZFLG
#define GET_XFLG XFLG
#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))
#endif
extern struct fixup {
int flag;
uae_u32 reg;
uaecptr value;
}fixup;
extern int areg_byteinc[];
extern int imm8_table[];
@ -49,112 +54,126 @@ extern int movem_index1[256];
extern int movem_index2[256];
extern int movem_next[256];
extern int fpp_movem_index1[256];
extern int fpp_movem_index2[256];
extern int fpp_movem_next[256];
extern int broken_in;
#ifdef X86_ASSEMBLY
/* This hack seems to force all register saves (pushl %reg) to be moved to the
begining of the function, thus making it possible to cpuopti to remove them
since m68k_run_1 will save those registers before calling the instruction
handler */
# define cpuop_tag(tag) __asm__ __volatile__ ( "#cpuop_" tag )
#else
# define cpuop_tag(tag) ;
#endif
#define cpuop_begin() do { cpuop_tag("begin"); } while (0)
#define cpuop_end() do { cpuop_tag("end"); } while (0)
typedef void REGPARAM2 cpuop_func (uae_u32) REGPARAM;
struct cputbl {
cpuop_func *handler;
int specific;
uae_u16 specific;
uae_u16 opcode;
};
extern cpuop_func *cpufunctbl[65536];
#ifdef USE_JIT
typedef void compop_func (uae_u32) REGPARAM;
struct comptbl {
compop_func *handler;
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;
typedef char flagtype;
extern struct regstruct
{
uae_u32 regs[16];
uaecptr usp,isp,msp;
uae_u16 sr;
flagtype t1;
flagtype t0;
flagtype s;
flagtype m;
flagtype x;
flagtype stopped;
int intmask;
uae_u32 pc;
uae_u8 *pc_p;
uae_u8 *pc_oldp;
uae_u32 vbr,sfc,dfc;
double fp[8];
uae_u32 fpcr,fpsr,fpiar;
uae_u32 spcflags;
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;
} 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
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
#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)
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);
}
@ -164,103 +183,114 @@ static __inline__ void fill_prefetch_2 (void)
/* 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)
static inline void m68k_setpc (uaecptr newpc)
{
regs.pc_p = regs.pc_oldp = get_real_address(newpc);
regs.pc = newpc;
}
static __inline__ uaecptr m68k_getpc (void)
{
return regs.pc + ((char *)regs.pc_p - (char *)regs.pc_oldp);
}
static __inline__ uaecptr m68k_getpc_p (uae_u8 *p)
{
return regs.pc + ((char *)p - (char *)regs.pc_oldp);
}
static __inline__ void m68k_do_rts(void)
{
m68k_setpc(get_long(m68k_areg(regs, 7)));
m68k_areg(regs, 7) += 4;
}
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);
}
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);
#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_setstopped (int stop)
static inline void m68k_do_rts(void)
{
regs.stopped = stop;
if (stop)
regs.spcflags |= SPCFLAG_STOP;
m68k_setpc(get_long(m68k_areg(regs, 7)));
m68k_areg(regs, 7) += 4;
}
static inline void m68k_do_bsr(uaecptr oldpc, uae_s32 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)
{
put_long(m68k_areg(regs, 7) - 4, oldpc);
m68k_areg(regs, 7) -= 4;
m68k_setpc(dest);
}
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);
static inline void m68k_setstopped (int stop)
{
regs.stopped = stop;
/* A traced STOP instruction drops through immediately without
actually stopping. */
if (stop && !( SPCFLAGS_TEST( SPCFLAG_DOTRACE )))
SPCFLAGS_SET( SPCFLAG_STOP );
}
#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 dump_counts (void);
extern void m68k_move2c (int, uae_u32 *);
extern void m68k_movec2 (int, uae_u32 *);
extern int m68k_move2c (int, uae_u32 *);
extern int m68k_movec2 (int, uae_u32 *);
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 m68k_go (int);
extern void m68k_dumpstate (uaecptr *);
extern void m68k_disasm (uaecptr, uaecptr *, int);
extern void exit_m68k (void);
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 void mmu_op (uae_u32, uae_u16);
extern void fpp_opp (uae_u32, uae_u16);
extern void fdbcc_opp (uae_u32, uae_u16);
extern void fscc_opp (uae_u32, uae_u16);
extern void ftrapcc_opp (uae_u32,uaecptr);
extern void fbcc_opp (uae_u32, uaecptr, uae_u32);
extern void fsave_opp (uae_u32);
extern void frestore_opp (uae_u32);
extern int m68k_do_specialties(void);
extern void m68k_instr_set(void);
uae_u32 linea68000(uae_u16 opcode);
/* Opcode of faulting instruction */
extern uae_u16 last_op_for_exception_3;
@ -271,16 +301,34 @@ extern uaecptr last_fault_for_exception_3;
#define CPU_OP_NAME(a) op ## a
/* 68020 + 68881 */
extern struct cputbl op_smalltbl_0[];
/* 68020 */
extern struct cputbl op_smalltbl_1[];
/* 68010 */
extern struct cputbl op_smalltbl_2[];
/* 68000 */
extern struct cputbl op_smalltbl_3[];
/* 68000 slow but compatible. */
extern struct cputbl op_smalltbl_4[];
/* 68040+ 68881 */
extern const struct cputbl op_smalltbl_0_ff[];
extern const struct cputbl op_smalltbl_0_nf[];
extern cpuop_func *cpufunctbl[65536];
#ifdef FLIGHT_RECORDER
extern void m68k_record_step(uaecptr, int);
#endif
extern void m68k_do_execute(void);
extern void m68k_execute(void);
#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;
extern void cpu_do_check_ticks(void);
static inline void cpu_check_ticks(void)
{
if (--emulated_ticks <= 0)
cpu_do_check_ticks();
}
#else
#define cpu_check_ticks()
#define cpu_do_check_ticks()
#endif
cpuop_func op_illg_1;
#endif /* NEWCPU_H */

View File

@ -0,0 +1,142 @@
#ifndef NOFLAGS_H
#define NOFLAGS_H
/* Undefine everything that will *set* flags. Note: Leave *reading*
flags alone ;-). We assume that nobody does something like
SET_ZFLG(a=b+c), i.e. expect side effects of the macros. That would
be a stupid thing to do when using macros.
*/
/* Gwenole Beauchesne pointed out that CAS and CAS2 use flag_cmp to set
flags that are then used internally, and that thus the noflags versions
of those instructions were broken. Oops!
Easy fix: Leave flag_cmp alone. It is only used by CMP* and CAS*
instructions. For CAS*, noflags is a bad idea. For CMP*, which has
setting flags as its only function, the noflags version is kinda pointless,
anyway.
Note that this will only work while using the optflag_* routines ---
as we do on all (one ;-) platforms that will ever use the noflags
versions, anyway.
However, if you try to compile without optimized flags, the "SET_ZFLAG"
macro will be left unchanged, to make CAS and CAS2 work right. Of course,
this is contrary to the whole idea of noflags, but better be right than
be fast.
Another problem exists with one of the bitfield operations. Once again,
one of the operations sets a flag, and looks at it later. And the CHK2
instruction does so as well. For those, a different solution is possible.
the *_ALWAYS versions of the SET_?FLG macros shall remain untouched by
the redefinitions in this file.
Unfortunately, they are defined in terms of the macros we *do* redefine.
So here comes a bit of trickery....
*/
#define NOFLAGS_CMP 0
#undef SET_NFLG_ALWAYS
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)
{
SET_CFLG(x); /* This has not yet been redefined */
}
#undef CPUFUNC
#define CPUFUNC(x) x##_nf
#ifndef OPTIMIZED_FLAGS
#undef SET_ZFLG
#define SET_ZFLG(y) do {uae_u32 dummy=(y); } while (0)
#endif
#undef SET_CFLG
#define SET_CFLG(y) do {uae_u32 dummy=(y); } while (0)
#undef SET_VFLG
#define SET_VFLG(y) do {uae_u32 dummy=(y); } while (0)
#undef SET_NFLG
#define SET_NFLG(y) do {uae_u32 dummy=(y); } while (0)
#undef SET_XFLG
#define SET_XFLG(y) do {uae_u32 dummy=(y); } while (0)
#undef 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
#ifdef optflag_testl
#undef optflag_testl
#endif
#ifdef optflag_testw
#undef optflag_testw
#endif
#ifdef optflag_testb
#undef optflag_testb
#endif
#ifdef optflag_addl
#undef optflag_addl
#endif
#ifdef optflag_addw
#undef optflag_addw
#endif
#ifdef optflag_addb
#undef optflag_addb
#endif
#ifdef optflag_subl
#undef optflag_subl
#endif
#ifdef optflag_subw
#undef optflag_subw
#endif
#ifdef optflag_subb
#undef optflag_subb
#endif
#if NOFLAGS_CMP
#ifdef optflag_cmpl
#undef optflag_cmpl
#endif
#ifdef optflag_cmpw
#undef optflag_cmpw
#endif
#ifdef optflag_cmpb
#undef optflag_cmpb
#endif
#endif
#define optflag_testl(v) do { } while (0)
#define optflag_testw(v) do { } while (0)
#define optflag_testb(v) do { } while (0)
#define optflag_addl(v, s, d) (v = (uae_s32)(d) + (uae_s32)(s))
#define optflag_addw(v, s, d) (v = (uae_s16)(d) + (uae_s16)(s))
#define optflag_addb(v, s, d) (v = (uae_s8)(d) + (uae_s8)(s))
#define optflag_subl(v, s, d) (v = (uae_s32)(d) - (uae_s32)(s))
#define optflag_subw(v, s, d) (v = (uae_s16)(d) - (uae_s16)(s))
#define optflag_subb(v, s, d) (v = (uae_s8)(d) - (uae_s8)(s))
#if NOFLAGS_CMP
/* These are just for completeness sake */
#define optflag_cmpl(s, d) do { } while (0)
#define optflag_cmpw(s, d) do { } while (0)
#define optflag_cmpb(s, d) do { } while (0)
#endif
#endif

View File

@ -1,3 +1,4 @@
/* 2002 MJ */
/*
* UAE - The Un*x Amiga Emulator
*
@ -6,14 +7,21 @@
* Copyright 1995,1996 Bernd Schmidt
*/
#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 mnemolookup lookuptab[] = {
@ -139,13 +147,20 @@ struct mnemolookup lookuptab[] = {
{ i_CPUSHA, "CPUSHA" },
{ i_MOVE16, "MOVE16" },
{ 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;
@ -163,7 +178,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;
@ -195,12 +210,31 @@ static void build_insn (int insn)
int variants;
struct instr_def id;
const char *opcstr;
int i;
int i, n;
int flaglive = 0, flagdead = 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);
}
}
for (i = 0; i < 5; i++) {
switch (id.flaginfo[i].flagset){
case fa_unset: break;
@ -236,7 +270,7 @@ static void build_insn (int insn)
int pos = 0;
int mnp = 0;
int bitno = 0;
char mnemonic[10];
char mnemonic[64];
wordsizes sz = sz_long;
int srcgather = 0, dstgather = 0;
@ -274,6 +308,9 @@ static void build_insn (int insn)
if (bitcnt[bitI] && (bitval[bitI] == 0x00 || bitval[bitI] == 0xff))
continue;
if (bitcnt[bitE] && (bitval[bitE] == 0x00))
continue;
/* bitI and bitC get copied to biti and bitc */
if (bitcnt[bitI]) {
bitval[biti] = bitval[bitI]; bitpos[biti] = bitpos[bitI];
@ -311,6 +348,11 @@ static void build_insn (int insn)
}
}
mnp++;
if ((unsigned)mnp >= (sizeof(mnemonic)-1)) {
mnemonic[sizeof(mnemonic)-1] = '\0';
fprintf(stderr, "WTF!!! Instruction '%s' overflow\n", mnemonic);
abort();
}
}
pos++;
}
@ -339,6 +381,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();
@ -348,6 +391,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;
@ -393,6 +441,22 @@ static void build_insn (int insn)
srcpos = bitpos[bitK];
}
break;
case 'E': srcmode = immi; srcreg = bitval[bitE];
if (CPU_EMU_SIZE < 5) { // gb-- what is CPU_EMU_SIZE used for ??
/* 1..255 */
srcgather = 1;
srctype = 6;
srcpos = bitpos[bitE];
}
break;
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;
srcpos = bitpos[bitp];
}
break;
default: abort();
}
break;
@ -517,12 +581,16 @@ static void build_insn (int insn)
case 'R': destreg = bitval[bitR]; dstgather = 1; dstpos = bitpos[bitR]; break;
default: abort();
}
if (dstpos < 0 || dstpos >= 32)
abort();
break;
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;
default: abort();
}
switch (opcstr[pos]) {
@ -530,6 +598,11 @@ static void build_insn (int insn)
case 'P': destmode = Aipi; pos++; break;
}
break;
#if 0
case 'L':
destmode = absl;
break;
#endif
case '#':
switch (opcstr[pos++]) {
case 'z': destmode = imm; break;
@ -700,8 +773,44 @@ 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
|| table68k[opc].mnemo == i_DBcc
|| table68k[opc].mnemo == i_TRAPcc
) {
switch (table68k[opc].cc) {
// CC mask: XNZVC
// 8421
case 0: flags_used = 0x00; break; /* T */
case 1: flags_used = 0x00; break; /* F */
case 2: flags_used = 0x05; break; /* HI */
case 3: flags_used = 0x05; break; /* LS */
case 4: flags_used = 0x01; break; /* CC */
case 5: flags_used = 0x01; break; /* CS */
case 6: flags_used = 0x04; break; /* NE */
case 7: flags_used = 0x04; break; /* EQ */
case 8: flags_used = 0x02; break; /* VC */
case 9: flags_used = 0x02; break; /* VS */
case 10:flags_used = 0x08; break; /* PL */
case 11:flags_used = 0x08; break; /* MI */
case 12:flags_used = 0x0A; break; /* GE */
case 13:flags_used = 0x0A; break; /* LT */
case 14:flags_used = 0x0E; break; /* GT */
case 15:flags_used = 0x0E; break; /* LE */
}
}
#if 1
/* gb-- flagdead and flaglive would not have correct information */
table68k[opc].flagdead = flags_set;
table68k[opc].flaglive = flags_used;
#else
table68k[opc].flagdead = flagdead;
table68k[opc].flaglive = flaglive;
#endif
table68k[opc].cflow = cflow;
nomatch:
/* FOO! */;
}
@ -722,7 +831,7 @@ void read_table68k (void)
}
}
static int mismatch;
static int readcpu_mismatch;
static void handle_merges (long int opcode)
{
@ -747,6 +856,10 @@ static void handle_merges (long int opcode)
smsk = 7; sbitdst = 8; break;
case 5:
smsk = 63; sbitdst = 64; break;
case 6:
smsk = 255; sbitdst = 256; break;
case 7:
smsk = 3; sbitdst = 4; break;
default:
smsk = 0; sbitdst = 0;
abort();
@ -775,20 +888,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)
@ -801,7 +914,7 @@ 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;
@ -813,5 +926,5 @@ void do_merges (void)
int get_no_mismatches (void)
{
return mismatch;
return readcpu_mismatch;
}

View File

@ -1,13 +1,17 @@
/* 2002 MJ */
#ifndef READCPU_H
#define 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,
@ -32,30 +36,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
} 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 {
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
} cflow_t;
typedef enum {
bit0, bit1, bitc, bitC, bitf, biti, bitI, bitj, bitJ, bitk, bitK,
bits, bitS, bitd, bitD, bitr, bitR, bitz, lastbit
} ENUMNAME (bitvals);
bits, bitS, bitd, bitD, bitr, bitR, bitz, bitE, bitp, lastbit
} bitvals;
struct instr_def {
unsigned int bits;
@ -68,6 +84,7 @@ struct instr_def {
unsigned int flaguse:3;
unsigned int flagset:3;
} flaginfo[5];
unsigned char cflow;
unsigned char sduse;
const char *opcstr;
};
@ -86,22 +103,16 @@ extern struct instr {
unsigned int mnemo:8;
unsigned int cc:4;
unsigned int plev:2;
#ifdef sgi
wordsizes size:2;
amodes smode:5;
unsigned int stype:3;
amodes dmode:5;
#else
unsigned int size:2;
unsigned int smode:5;
unsigned int stype:3;
unsigned int dmode:5;
#endif
unsigned int suse:1;
unsigned int duse:1;
unsigned int unused1:1;
unsigned int clev:3;
unsigned int unused2:5;
unsigned int cflow:3;
unsigned int unused2:2;
} *table68k;
extern void read_table68k (void);
@ -112,3 +123,5 @@ extern int nr_cpuop_funcs;
#ifdef __cplusplus
}
#endif
#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,116 @@
/* 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 x;
flagtype stopped;
int 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, lastint_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

@ -0,0 +1,104 @@
/*
* UAE - The Un*x Amiga Emulator
*
* MC68000 emulation
*
* Copyright 1995 Bernd Schmidt
*/
#ifndef SPCFLAGS_H
#define SPCFLAGS_H
typedef uae_u32 spcflags_t;
enum {
SPCFLAG_STOP = 0x01,
SPCFLAG_INT = 0x02,
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
| SPCFLAG_INT
| 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
};
#define SPCFLAGS_TEST(m) \
((regs.spcflags & (m)) != 0)
/* 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;
#define SPCFLAGS_SET(m) do { \
B2_lock_mutex(spcflags_lock); \
regs.spcflags |= (m); \
B2_unlock_mutex(spcflags_lock); \
} while (0)
#define SPCFLAGS_CLEAR(m) do { \
B2_lock_mutex(spcflags_lock); \
regs.spcflags &= ~(m); \
B2_unlock_mutex(spcflags_lock); \
} while (0)
#endif
#endif /* SPCFLAGS_H */

View File

@ -4,11 +4,13 @@
% C: condition codes, except F
% f: direction
% i: immediate
% E: immediate, except 00 (for EmulOp instructions)
% I: immediate, except 00 and ff
% j: immediate 1..8
% J: immediate 0..15
% k: immediate 0..7
% K: immediate 0..63
% p: immediate 0..3 (CINV and CPUSH: cache field)
% s: source mode
% S: source reg
% d: dest mode
@ -24,15 +26,17 @@
%
% Arp: --> -(Ar)
% 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)
@ -43,10 +47,19 @@
% 0 means flag reset
% 1 means flag set
% ? means programmer was too lazy to check or instruction may trap
% + means instruction is conditional branch
% everything else means flag set/used
% / means instruction is unconditional branch/call
% + 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
% - nothing
% T the instruction may trap or cause an exception
% B branch instruction
% J jump instruction
% R return instruction
%
% srcaddr status destaddr status :
% bitmasks of
% 1 means fetched
@ -56,197 +69,218 @@
% instruction
%
0000 0000 0011 1100:00:XNZVC:XNZVC:10: ORSR.B #1
0000 0000 0111 1100:02:?????:?????:10: ORSR.W #1
0000 0zz0 11ss sSSS:20:?????:?????:11: CHK2.z #1,s[!Dreg,Areg,Aipi,Apdi,Immd]
0000 0000 zzdd dDDD:00:-NZ00:-----:13: OR.z #z,d[!Areg]
0000 0010 0011 1100:00:XNZVC:XNZVC:10: ANDSR.B #1
0000 0010 0111 1100:02:?????:?????:10: ANDSR.W #1
0000 0010 zzdd dDDD:00:-NZ00:-----:13: AND.z #z,d[!Areg]
0000 0100 zzdd dDDD:00:XNZVC:-----:13: SUB.z #z,d[!Areg]
0000 0110 zzdd dDDD:00:XNZVC:-----:13: ADD.z #z,d[!Areg]
0000 0110 11ss sSSS:20:?????:?????:10: CALLM s[!Dreg,Areg,Aipi,Apdi,Immd]
0000 0110 11ss sSSS:20:?????:?????:10: RTM s[Dreg,Areg]
0000 1000 00ss sSSS:00:--Z--:-----:11: BTST #1,s[!Areg]
0000 1000 01ss sSSS:00:--Z--:-----:13: BCHG #1,s[!Areg,Immd]
0000 1000 10ss sSSS:00:--Z--:-----:13: BCLR #1,s[!Areg,Immd]
0000 1000 11ss sSSS:00:--Z--:-----:13: BSET #1,s[!Areg,Immd]
0000 1010 0011 1100:00:XNZVC:XNZVC:10: EORSR.B #1
0000 1010 0111 1100:02:?????:?????:10: EORSR.W #1
0000 1010 zzdd dDDD:00:-NZ00:-----:13: EOR.z #z,d[!Areg]
0000 1100 zzss sSSS:00:-NZVC:-----:11: CMP.z #z,s[!Areg,Immd]
0000 0000 0011 1100:00:XNZVC:XNZVC:--:10: ORSR.B #1
0000 0000 0111 1100:02:XNZVC:XNZVC:T-:10: ORSR.W #1
0000 0zz0 11ss sSSS:20:-?Z?C:-----:T-:11: CHK2.z #1,s[!Dreg,Areg,Aipi,Apdi,Immd]
0000 0000 zzdd dDDD:00:-NZ00:-----:--:13: OR.z #z,d[!Areg]
0000 0010 0011 1100:00:XNZVC:XNZVC:--:10: ANDSR.B #1
0000 0010 0111 1100:02:XNZVC:XNZVC:T-:10: ANDSR.W #1
0000 0010 zzdd dDDD:00:-NZ00:-----:--:13: AND.z #z,d[!Areg]
0000 0100 zzdd dDDD:00:XNZVC:-----:--:13: SUB.z #z,d[!Areg]
0000 0110 zzdd dDDD:00:XNZVC:-----:--:13: ADD.z #z,d[!Areg]
0000 0110 11ss sSSS:20:-----:XNZVC:--:10: CALLM s[!Dreg,Areg,Aipi,Apdi,Immd]
0000 0110 11ss sSSS:20:XNZVC:-----:-R:10: RTM s[Dreg,Areg]
0000 1000 00ss sSSS:00:--Z--:-----:--:11: BTST #1,s[!Areg]
0000 1000 01ss sSSS:00:--Z--:-----:--:13: BCHG #1,s[!Areg,Immd]
0000 1000 10ss sSSS:00:--Z--:-----:--:13: BCLR #1,s[!Areg,Immd]
0000 1000 11ss sSSS:00:--Z--:-----:--:13: BSET #1,s[!Areg,Immd]
0000 1010 0011 1100:00:XNZVC:XNZVC:--:10: EORSR.B #1
0000 1010 0111 1100:02:XNZVC:XNZVC:T-:10: EORSR.W #1
0000 1010 zzdd dDDD:00:-NZ00:-----:--:13: EOR.z #z,d[!Areg]
0000 1100 zzss sSSS:00:-NZVC:-----:--:11: CMP.z #z,s[!Areg,Immd]
0000 1010 11ss sSSS:20:?????:?????:13: CAS.B #1,s[!Dreg,Areg,Immd,PC8r,PC16]
0000 1100 11ss sSSS:20:?????:?????:13: CAS.W #1,s[!Dreg,Areg,Immd,PC8r,PC16]
0000 1100 1111 1100:20:?????:?????:10: CAS2.W #2
0000 1110 zzss sSSS:22:?????:?????:13: MOVES.z #1,s[!Dreg,Areg,Immd,PC8r,PC16]
0000 1110 11ss sSSS:20:?????:?????:13: CAS.L #1,s[!Dreg,Areg,Immd,PC8r,PC16]
0000 1110 1111 1100:20:?????:?????:10: CAS2.L #2
0000 1010 11ss sSSS:20:-NZVC:-----:--:13: CAS.B #1,s[!Dreg,Areg,Immd,PC8r,PC16]
0000 1100 11ss sSSS:20:-NZVC:-----:--:13: CAS.W #1,s[!Dreg,Areg,Immd,PC8r,PC16]
0000 1100 1111 1100:20:-NZVC:-----:--:10: CAS2.W #2
0000 1110 zzss sSSS:22:-----:-----:T-:13: MOVES.z #1,s[!Dreg,Areg,Immd,PC8r,PC16]
0000 1110 11ss sSSS:20:-NZVC:-----:--:13: CAS.L #1,s[!Dreg,Areg,Immd,PC8r,PC16]
0000 1110 1111 1100:20:-NZVC:-----:--:10: CAS2.L #2
0000 rrr1 00dd dDDD:00:-----:-----:12: MVPMR.W d[Areg-Ad16],Dr
0000 rrr1 01dd dDDD:00:-----:-----:12: MVPMR.L d[Areg-Ad16],Dr
0000 rrr1 10dd dDDD:00:-----:-----:12: MVPRM.W Dr,d[Areg-Ad16]
0000 rrr1 11dd dDDD:00:-----:-----:12: MVPRM.L Dr,d[Areg-Ad16]
0000 rrr1 00ss sSSS:00:--Z--:-----:11: BTST Dr,s[!Areg]
0000 rrr1 01ss sSSS:00:--Z--:-----:13: BCHG Dr,s[!Areg,Immd]
0000 rrr1 10ss sSSS:00:--Z--:-----:13: BCLR Dr,s[!Areg,Immd]
0000 rrr1 11ss sSSS:00:--Z--:-----:13: BSET Dr,s[!Areg,Immd]
0000 rrr1 00dd dDDD:00:-----:-----:--:12: MVPMR.W d[Areg-Ad16],Dr
0000 rrr1 01dd dDDD:00:-----:-----:--:12: MVPMR.L d[Areg-Ad16],Dr
0000 rrr1 10dd dDDD:00:-----:-----:--:12: MVPRM.W Dr,d[Areg-Ad16]
0000 rrr1 11dd dDDD:00:-----:-----:--:12: MVPRM.L Dr,d[Areg-Ad16]
0000 rrr1 00ss sSSS:00:--Z--:-----:--:11: BTST Dr,s[!Areg]
0000 rrr1 01ss sSSS:00:--Z--:-----:--:13: BCHG Dr,s[!Areg,Immd]
0000 rrr1 10ss sSSS:00:--Z--:-----:--:13: BCLR Dr,s[!Areg,Immd]
0000 rrr1 11ss sSSS:00:--Z--:-----:--:13: BSET Dr,s[!Areg,Immd]
0001 DDDd ddss sSSS:00:-NZ00:-----:12: MOVE.B s,d[!Areg]
0010 DDDd ddss sSSS:00:-----:-----:12: MOVEA.L s,d[Areg]
0010 DDDd ddss sSSS:00:-NZ00:-----:12: MOVE.L s,d[!Areg]
0011 DDDd ddss sSSS:00:-----:-----:12: MOVEA.W s,d[Areg]
0011 DDDd ddss sSSS:00:-NZ00:-----:12: MOVE.W s,d[!Areg]
0001 DDDd ddss sSSS:00:-NZ00:-----:--:12: MOVE.B s,d[!Areg]
0010 DDDd ddss sSSS:00:-----:-----:--:12: MOVEA.L s,d[Areg]
0010 DDDd ddss sSSS:00:-NZ00:-----:--:12: MOVE.L s,d[!Areg]
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:-----:30: NEGX.z d[!Areg]
0100 0000 11dd dDDD:01:?????:?????:10: MVSR2.W d[!Areg]
0100 0010 zzdd dDDD:00:-0100:-----:20: CLR.z d[!Areg]
0100 0010 11dd dDDD:10:?????:?????:10: MVSR2.B d[!Areg]
0100 0100 zzdd dDDD:00:XNZVC:-----:30: NEG.z d[!Areg]
0100 0100 11ss sSSS:00:XNZVC:-----:10: MV2SR.B s[!Areg]
0100 0110 zzdd dDDD:00:-NZ00:-----:30: NOT.z d[!Areg]
0100 0110 11ss sSSS:02:?????:?????:10: MV2SR.W s[!Areg]
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:?????:?????:10: BKPT #k
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:-----:-----:02: MVMLE.W #1,d[!Dreg,Areg,Aipi]
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 1010 zzss sSSS:00:-NZ00:-----:10: TST.z s
0100 1010 11dd dDDD:00:?????:?????:30: TAS.B d[!Areg]
0100 1010 1111 1100:00:?????:?????:00: ILLEGAL
0100 1100 00ss sSSS:20:-NZVC:-----:13: MULL.L #1,s[!Areg]
0100 1100 01ss sSSS:20:?????:?????:13: DIVL.L #1,s[!Areg]
0100 1100 10ss sSSS:00:-----:-----:01: MVMEL.W #1,s[!Dreg,Areg,Apdi,Immd]
0100 1100 11ss sSSS:00:-----:-----:01: MVMEL.L #1,s[!Dreg,Areg,Apdi,Immd]
0100 1110 0100 JJJJ:00:-----:XNZVC:10: TRAP #J
0100 1110 0101 0rrr:00:-----:-----:31: LINK.W Ar,#1
0100 1110 0101 1rrr:00:-----:-----:30: UNLK.L Ar
0100 1110 0110 0rrr:02:-----:-----:10: MVR2USP.L Ar
0100 1110 0110 1rrr:02:-----:-----:20: MVUSP2R.L Ar
0100 1110 0111 0000:02:-----:-----:00: RESET
0100 1110 0111 0001:00:-----:-----:00: NOP
0100 1110 0111 0010:02:XNZVC:-----:10: STOP #1
0100 1110 0111 0011:02:XNZVC:-----:00: RTE
0100 1110 0111 0100:00:?????:?????:10: RTD #1
0100 1110 0111 0101:00:-----:-----:00: RTS
0100 1110 0111 0110:00:-----:XNZVC:00: TRAPV
0100 1110 0111 0111:00:XNZVC:-----:00: RTR
0100 1110 0111 1010:12:?????:?????:10: MOVEC2 #1
0100 1110 0111 1011:12:?????:?????:10: MOVE2C #1
0100 1110 10ss sSSS:00://///://///:80: JSR.L s[!Dreg,Areg,Aipi,Apdi,Immd]
0100 rrr1 00ss sSSS:00:?????:?????:11: CHK.L s[!Areg],Dr
0100 rrr1 10ss sSSS:00:?????:?????:11: CHK.W s[!Areg],Dr
0100 1110 11ss sSSS:00://///://///:80: JMP.L s[!Dreg,Areg,Aipi,Apdi,Immd]
0100 rrr1 11ss sSSS:00:-----:-----:02: LEA.L s[!Dreg,Areg,Aipi,Apdi,Immd],Ar
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]
0100 0100 zzdd dDDD:00:XNZVC:-----:--:30: NEG.z d[!Areg]
0100 0100 11ss sSSS:00:XNZVC:-----:--:10: MV2SR.B s[!Areg]
0100 0110 zzdd dDDD:00:-NZ00:-----:--:30: NOT.z d[!Areg]
0100 0110 11ss sSSS:02:XNZVC:XNZVC:T-:10: MV2SR.W s[!Areg]
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:-----:-----:--: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:-----:-----:--:02: MVMLE.W #1,d[!Dreg,Areg,Aipi]
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 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
0100 1100 00ss sSSS:20:-NZVC:-----:--:13: MULL.L #1,s[!Areg]
0100 1100 01ss sSSS:20:-NZV0:-----:T-:13: DIVL.L #1,s[!Areg]
0100 1100 10ss sSSS:00:-----:-----:--:01: MVMEL.W #1,s[!Dreg,Areg,Apdi,Immd]
0100 1100 11ss sSSS:00:-----:-----:--:01: MVMEL.L #1,s[!Dreg,Areg,Apdi,Immd]
0100 1110 0100 JJJJ:00:-----:XNZVC:--:10: TRAP #J
0100 1110 0101 0rrr:00:-----:-----:--:31: LINK.W Ar,#1
0100 1110 0101 1rrr:00:-----:-----:--:30: UNLK.L Ar
0100 1110 0110 0rrr:02:-----:-----:T-:10: MVR2USP.L Ar
0100 1110 0110 1rrr:02:-----:-----:T-:20: MVUSP2R.L Ar
0100 1110 0111 0000:02:-----:-----:T-:00: RESET
0100 1110 0111 0001:00:-----:-----:--:00: NOP
0100 1110 0111 0010:02:XNZVC:-----:T-:10: STOP #1
0100 1110 0111 0011:02:XNZVC:-----:TR:00: RTE
0100 1110 0111 0100:00:-----:-----:-R:10: RTD #1
0100 1110 0111 0101:00:-----:-----:-R:00: RTS
0100 1110 0111 0110:00:-----:XNZVC:T-:00: TRAPV
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 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 rrr1 11ss sSSS:00:-----:-----:--:02: LEA.L s[!Dreg,Areg,Aipi,Apdi,Immd],Ar
0101 jjj0 zzdd dDDD:00:-----:-----:13: ADDA.z #j,d[Areg]
0101 jjj0 zzdd dDDD:00:XNZVC:-----:13: ADD.z #j,d[!Areg]
0101 jjj1 zzdd dDDD:00:-----:-----:13: SUBA.z #j,d[Areg]
0101 jjj1 zzdd dDDD:00:XNZVC:-----:13: SUB.z #j,d[!Areg]
0101 cccc 1100 1rrr:00:-----:+++++:31: DBcc.W Dr,#1
0101 cccc 11dd dDDD:00:-----:+++++:20: Scc.B d[!Areg]
0101 cccc 1111 1010:20:?????:?????:10: TRAPcc #1
0101 cccc 1111 1011:20:?????:?????:10: TRAPcc #2
0101 cccc 1111 1100:20:?????:?????:00: TRAPcc
% 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]
% 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 1111 1010:20:-----:-????:T-:10: TRAPcc #1
0101 cccc 1111 1011:20:-----:-????:T-:10: TRAPcc #2
0101 cccc 1111 1100:20:-----:-????:T-:00: TRAPcc
% 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://///://///:40: BSR.W #1
0110 0001 IIII IIII:00://///://///:40: BSR.B #i
0110 0001 1111 1111:00://///://///:40: BSR.L #2
0110 CCCC 0000 0000:00:-----:+++++:40: Bcc.W #1
0110 CCCC IIII IIII:00:-----:+++++:40: Bcc.B #i
0110 CCCC 1111 1111:00:-----:+++++: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
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:?????:?????: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 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 11ss sSSS:00:?????:?????:13: DIVS.W s[!Areg],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: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 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:-----:13: SUB.z Dr,d[!Areg,Dreg]
1001 rrr1 11ss sSSS:00:-----:-----:13: SUBA.L s,Ar
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:-----:--:13: SUB.z Dr,d[!Areg,Dreg]
1001 rrr1 11ss sSSS:00:-----:-----:--:13: SUBA.L s,Ar
1011 rrr0 zzss sSSS:00:-NZVC:-----:11: CMP.z s,Dr
1011 rrr0 11ss sSSS:00:-NZVC:-----:11: CMPA.W s,Ar
1011 rrr1 11ss sSSS:00:-NZVC:-----:11: CMPA.L s,Ar
1011 rrr1 zzdd dDDD:00:-NZVC:-----:11: CMPM.z d[Areg-Aipi],ArP
1011 rrr1 zzdd dDDD:00:-NZ00:-----:13: EOR.z Dr,d[!Areg]
1011 rrr0 zzss sSSS:00:-NZVC:-----:--:11: CMP.z s,Dr
1011 rrr0 11ss sSSS:00:-NZVC:-----:--:11: CMPA.W s,Ar
1011 rrr1 11ss sSSS:00:-NZVC:-----:--:11: CMPA.L s,Ar
1011 rrr1 zzdd dDDD:00:-NZVC:-----:--:11: CMPM.z d[Areg-Aipi],ArP
1011 rrr1 zzdd dDDD:00:-NZ00:-----:--:13: EOR.z Dr,d[!Areg]
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 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 11ss sSSS:00:-NZ00:-----:13: MULS.W s[!Areg],Dr
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: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 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:-----:13: ADD.z Dr,d[!Areg,Dreg]
1101 rrr1 11ss sSSS:00:-----:-----:13: ADDA.L s,Ar
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:-----:--:13: ADD.z Dr,d[!Areg,Dreg]
1101 rrr1 11ss sSSS:00:-----:-----:--:13: ADDA.L s,Ar
1110 jjjf zz00 0RRR:00:XNZVC:-----:13: ASf.z #j,DR
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: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]
1110 001f 11dd dDDD:00:XNZ0C:-----:13: LSfW.W d[!Dreg,Areg]
1110 010f 11dd dDDD:00:XNZ0C:X----:13: ROXfW.W d[!Dreg,Areg]
1110 011f 11dd dDDD:00:-NZ0C:-----:13: ROfW.W d[!Dreg,Areg]
1110 jjjf zz00 0RRR:00:XNZVC:-----:--:13: ASf.z #j,DR
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: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]
1110 001f 11dd dDDD:00:XNZ0C:-----:--:13: LSfW.W d[!Dreg,Areg]
1110 010f 11dd dDDD:00:XNZ0C:X----:--:13: ROXfW.W d[!Dreg,Areg]
1110 011f 11dd dDDD:00:-NZ0C:-----:--:13: ROfW.W d[!Dreg,Areg]
1110 1000 11ss sSSS:20:?????:?????:11: BFTST #1,s[!Areg,Apdi,Aipi,Immd]
1110 1001 11ss sSSS:20:?????:?????:11: BFEXTU #1,s[!Areg,Apdi,Aipi,Immd]
1110 1010 11ss sSSS:20:?????:?????:13: BFCHG #1,s[!Areg,Apdi,Aipi,Immd,PC8r,PC16]
1110 1011 11ss sSSS:20:?????:?????:11: BFEXTS #1,s[!Areg,Apdi,Aipi,Immd]
1110 1100 11ss sSSS:20:?????:?????:13: BFCLR #1,s[!Areg,Apdi,Aipi,Immd,PC8r,PC16]
1110 1101 11ss sSSS:20:?????:?????:11: BFFFO #1,s[!Areg,Apdi,Aipi,Immd]
1110 1110 11ss sSSS:20:?????:?????:13: BFSET #1,s[!Areg,Apdi,Aipi,Immd,PC8r,PC16]
1110 1111 11ss sSSS:20:?????:?????:13: BFINS #1,s[!Areg,Apdi,Aipi,Immd,PC8r,PC16]
1110 1000 11ss sSSS:20:-NZ00:-----:--:11: BFTST #1,s[!Areg,Apdi,Aipi,Immd]
1110 1001 11ss sSSS:20:-NZ00:-----:--:11: BFEXTU #1,s[!Areg,Apdi,Aipi,Immd]
1110 1010 11ss sSSS:20:-NZ00:-----:--:13: BFCHG #1,s[!Areg,Apdi,Aipi,Immd,PC8r,PC16]
1110 1011 11ss sSSS:20:-NZ00:-----:--:11: BFEXTS #1,s[!Areg,Apdi,Aipi,Immd]
1110 1100 11ss sSSS:20:-NZ00:-----:--:13: BFCLR #1,s[!Areg,Apdi,Aipi,Immd,PC8r,PC16]
1110 1101 11ss sSSS:20:-NZ00:-----:--:11: BFFFO #1,s[!Areg,Apdi,Aipi,Immd]
1110 1110 11ss sSSS:20:-NZ00:-----:--:13: BFSET #1,s[!Areg,Apdi,Aipi,Immd,PC8r,PC16]
1110 1111 11ss sSSS:20:-NZ00:-----:--:13: BFINS #1,s[!Areg,Apdi,Aipi,Immd,PC8r,PC16]
% floating point co processor
% TODO: FPU is currently commented out
% 1111 0010 00ss sSSS:30:?????:?????:11: FPP #1,s
% 1111 0010 01ss sSSS:30:?????:?????:11: FDBcc #1,s[Areg-Dreg]
% 1111 0010 01ss sSSS:30:?????:?????:11: FScc #1,s[!Areg,Immd,PC8r,PC16]
% 1111 0010 0111 1010:30:?????:?????:10: FTRAPcc #1
% 1111 0010 0111 1011:30:?????:?????:10: FTRAPcc #2
% 1111 0010 0111 1100:30:?????:?????:00: FTRAPcc
% 1111 0010 10KK KKKK:30:?????:?????:11: FBcc #K,#1
% 1111 0010 11KK KKKK:30:?????:?????:11: FBcc #K,#2
% 1111 0011 00ss sSSS:32:?????:?????:20: FSAVE s[!Dreg,Areg,Aipi,Immd,PC8r,PC16]
% 1111 0011 01ss sSSS:32:?????:?????:10: FRESTORE s[!Dreg,Areg,Apdi,Immd]
1111 0010 00ss sSSS:30:-----:-----:--:11: FPP #1,s
1111 0010 01ss sSSS:30:-----:-----:-B:11: FDBcc #1,s[Areg-Dreg]
1111 0010 01ss sSSS:30:-----:-----:--:11: FScc #1,s[!Areg,Immd,PC8r,PC16]
1111 0010 0111 1010:30:-----:-----:T-:10: FTRAPcc #1
1111 0010 0111 1011:30:-----:-----:T-:10: FTRAPcc #2
1111 0010 0111 1100:30:-----:-----:T-:00: FTRAPcc
1111 0010 10KK KKKK:30:-----:-----:-B:11: FBcc #K,#1
1111 0010 11KK KKKK:30:-----:-----:-B:11: FBcc #K,#2
1111 0011 00ss sSSS:32:-----:-----:--:20: FSAVE s[!Dreg,Areg,Aipi,Immd,PC8r,PC16]
1111 0011 01ss sSSS:32:-----:-----:--:10: FRESTORE s[!Dreg,Areg,Apdi,Immd]
% 68040 instructions
1111 0100 ii00 1rrr:42:-----:-----:02: CINVL #i,Ar
1111 0100 ii01 0rrr:42:-----:-----:02: CINVP #i,Ar
1111 0100 ii01 1rrr:42:-----:-----:00: CINVA #i
1111 0100 ii10 1rrr:42:-----:-----:02: CPUSHL #i,Ar
1111 0100 ii11 0rrr:42:-----:-----:02: CPUSHP #i,Ar
1111 0100 ii11 1rrr:42:-----:-----:00: CPUSHA #i
1111 0110 0010 0rrr:40:-----:-----:12: MOVE16 ArP,ARP
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
1111 0100 pp10 1rrr:42:-----:-----:T-:02: CPUSHL #p,Ar
1111 0100 pp11 0rrr:42:-----:-----:T-:02: CPUSHP #p,Ar
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],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]
% MMU disabled
% 1111 0101 iiii iSSS:42:?????:?????:T-:11: MMUOP #i,s
% EmulOp instructions (deprecated, to be removed)
0111 0001 0000 0000:02:-----:-----:-R:00: EMULOP_RETURN
0111 0001 EEEE EEEE:02:-----:-----:-J:10: EMULOP #E
% NatFea instructions (do I have the srcaddr correct?) disabled
% 0111 0011 0000 0000:00:-----:-----:-J:00: NATFEAT_ID
% 0111 0011 0000 0001:00:-----:-----:-J:00: NATFEAT_CALL