mirror of
https://github.com/kanjitalk755/macemu.git
synced 2024-06-02 13:41:37 +00:00
Port of CPU code from ARAnyM (currently hangs)
This commit is contained in:
parent
1bf6e93461
commit
1758ef58b5
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
80
BasiliskII/src/uae_cpu/Makefile.am
Normal file
80
BasiliskII/src/uae_cpu/Makefile.am
Normal 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)
|
327
BasiliskII/src/uae_cpu/aranym_glue.cpp
Normal file
327
BasiliskII/src/uae_cpu/aranym_glue.cpp
Normal 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
|
|
@ -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() {}
|
||||
|
|
|
@ -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);
|
||||
|
|
2872
BasiliskII/src/uae_cpu/compiler/codegen_arm.cpp
Normal file
2872
BasiliskII/src/uae_cpu/compiler/codegen_arm.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1292
BasiliskII/src/uae_cpu/compiler/codegen_arm.h
Normal file
1292
BasiliskII/src/uae_cpu/compiler/codegen_arm.h
Normal file
File diff suppressed because it is too large
Load Diff
5372
BasiliskII/src/uae_cpu/compiler/codegen_x86.cpp
Normal file
5372
BasiliskII/src/uae_cpu/compiler/codegen_x86.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1996
BasiliskII/src/uae_cpu/compiler/codegen_x86.h
Normal file
1996
BasiliskII/src/uae_cpu/compiler/codegen_x86.h
Normal file
File diff suppressed because it is too large
Load Diff
543
BasiliskII/src/uae_cpu/compiler/compemu.h
Normal file
543
BasiliskII/src/uae_cpu/compiler/compemu.h
Normal 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 */
|
2
BasiliskII/src/uae_cpu/compiler/compemu1.cpp
Normal file
2
BasiliskII/src/uae_cpu/compiler/compemu1.cpp
Normal file
|
@ -0,0 +1,2 @@
|
|||
#define PART_1
|
||||
#include "compemu.cpp"
|
2
BasiliskII/src/uae_cpu/compiler/compemu2.cpp
Normal file
2
BasiliskII/src/uae_cpu/compiler/compemu2.cpp
Normal file
|
@ -0,0 +1,2 @@
|
|||
#define PART_2
|
||||
#include "compemu.cpp"
|
2
BasiliskII/src/uae_cpu/compiler/compemu3.cpp
Normal file
2
BasiliskII/src/uae_cpu/compiler/compemu3.cpp
Normal file
|
@ -0,0 +1,2 @@
|
|||
#define PART_3
|
||||
#include "compemu.cpp"
|
2
BasiliskII/src/uae_cpu/compiler/compemu4.cpp
Normal file
2
BasiliskII/src/uae_cpu/compiler/compemu4.cpp
Normal file
|
@ -0,0 +1,2 @@
|
|||
#define PART_4
|
||||
#include "compemu.cpp"
|
2
BasiliskII/src/uae_cpu/compiler/compemu5.cpp
Normal file
2
BasiliskII/src/uae_cpu/compiler/compemu5.cpp
Normal file
|
@ -0,0 +1,2 @@
|
|||
#define PART_5
|
||||
#include "compemu.cpp"
|
2
BasiliskII/src/uae_cpu/compiler/compemu6.cpp
Normal file
2
BasiliskII/src/uae_cpu/compiler/compemu6.cpp
Normal file
|
@ -0,0 +1,2 @@
|
|||
#define PART_6
|
||||
#include "compemu.cpp"
|
2
BasiliskII/src/uae_cpu/compiler/compemu7.cpp
Normal file
2
BasiliskII/src/uae_cpu/compiler/compemu7.cpp
Normal file
|
@ -0,0 +1,2 @@
|
|||
#define PART_7
|
||||
#include "compemu.cpp"
|
2
BasiliskII/src/uae_cpu/compiler/compemu8.cpp
Normal file
2
BasiliskII/src/uae_cpu/compiler/compemu8.cpp
Normal file
|
@ -0,0 +1,2 @@
|
|||
#define PART_8
|
||||
#include "compemu.cpp"
|
1638
BasiliskII/src/uae_cpu/compiler/compemu_fpp.cpp
Normal file
1638
BasiliskII/src/uae_cpu/compiler/compemu_fpp.cpp
Normal file
File diff suppressed because it is too large
Load Diff
2106
BasiliskII/src/uae_cpu/compiler/compemu_midfunc_arm.cpp
Normal file
2106
BasiliskII/src/uae_cpu/compiler/compemu_midfunc_arm.cpp
Normal file
File diff suppressed because it is too large
Load Diff
184
BasiliskII/src/uae_cpu/compiler/compemu_midfunc_arm.h
Normal file
184
BasiliskII/src/uae_cpu/compiler/compemu_midfunc_arm.h
Normal 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));
|
||||
|
||||
|
||||
|
||||
|
5428
BasiliskII/src/uae_cpu/compiler/compemu_midfunc_arm2.cpp
Normal file
5428
BasiliskII/src/uae_cpu/compiler/compemu_midfunc_arm2.cpp
Normal file
File diff suppressed because it is too large
Load Diff
348
BasiliskII/src/uae_cpu/compiler/compemu_midfunc_arm2.h
Normal file
348
BasiliskII/src/uae_cpu/compiler/compemu_midfunc_arm2.h
Normal 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));
|
||||
|
2982
BasiliskII/src/uae_cpu/compiler/compemu_midfunc_x86.cpp
Normal file
2982
BasiliskII/src/uae_cpu/compiler/compemu_midfunc_x86.cpp
Normal file
File diff suppressed because it is too large
Load Diff
252
BasiliskII/src/uae_cpu/compiler/compemu_midfunc_x86.h
Normal file
252
BasiliskII/src/uae_cpu/compiler/compemu_midfunc_x86.h
Normal 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));
|
5111
BasiliskII/src/uae_cpu/compiler/compemu_support.cpp
Normal file
5111
BasiliskII/src/uae_cpu/compiler/compemu_support.cpp
Normal file
File diff suppressed because it is too large
Load Diff
5
BasiliskII/src/uae_cpu/compiler/compstbla.cpp
Normal file
5
BasiliskII/src/uae_cpu/compiler/compstbla.cpp
Normal 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"
|
52
BasiliskII/src/uae_cpu/compiler/flags_arm.h
Normal file
52
BasiliskII/src/uae_cpu/compiler/flags_arm.h
Normal 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 */
|
52
BasiliskII/src/uae_cpu/compiler/flags_x86.h
Normal file
52
BasiliskII/src/uae_cpu/compiler/flags_x86.h
Normal 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 */
|
3619
BasiliskII/src/uae_cpu/compiler/gencomp.c
Normal file
3619
BasiliskII/src/uae_cpu/compiler/gencomp.c
Normal file
File diff suppressed because it is too large
Load Diff
4981
BasiliskII/src/uae_cpu/compiler/gencomp_arm.c
Normal file
4981
BasiliskII/src/uae_cpu/compiler/gencomp_arm.c
Normal file
File diff suppressed because it is too large
Load Diff
264
BasiliskII/src/uae_cpu/compiler/test_codegen_arm.c
Normal file
264
BasiliskII/src/uae_cpu/compiler/test_codegen_arm.c
Normal 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");
|
||||
|
||||
|
||||
}
|
||||
|
1008
BasiliskII/src/uae_cpu/compiler/test_codegen_x86.cpp
Normal file
1008
BasiliskII/src/uae_cpu/compiler/test_codegen_x86.cpp
Normal file
File diff suppressed because it is too large
Load Diff
|
@ -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
|
||||
|
|
5
BasiliskII/src/uae_cpu/cpudefsa.cpp
Normal file
5
BasiliskII/src/uae_cpu/cpudefsa.cpp
Normal 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"
|
2
BasiliskII/src/uae_cpu/cpuemu1.cpp
Normal file
2
BasiliskII/src/uae_cpu/cpuemu1.cpp
Normal file
|
@ -0,0 +1,2 @@
|
|||
#define PART_1
|
||||
#include "cpuemu.cpp"
|
3
BasiliskII/src/uae_cpu/cpuemu1_nf.cpp
Normal file
3
BasiliskII/src/uae_cpu/cpuemu1_nf.cpp
Normal file
|
@ -0,0 +1,3 @@
|
|||
#define NOFLAGS 1
|
||||
#define PART_1
|
||||
#include "cpuemu.cpp"
|
2
BasiliskII/src/uae_cpu/cpuemu2.cpp
Normal file
2
BasiliskII/src/uae_cpu/cpuemu2.cpp
Normal file
|
@ -0,0 +1,2 @@
|
|||
#define PART_2
|
||||
#include "cpuemu.cpp"
|
3
BasiliskII/src/uae_cpu/cpuemu2_nf.cpp
Normal file
3
BasiliskII/src/uae_cpu/cpuemu2_nf.cpp
Normal file
|
@ -0,0 +1,3 @@
|
|||
#define NOFLAGS 1
|
||||
#define PART_2
|
||||
#include "cpuemu.cpp"
|
2
BasiliskII/src/uae_cpu/cpuemu3.cpp
Normal file
2
BasiliskII/src/uae_cpu/cpuemu3.cpp
Normal file
|
@ -0,0 +1,2 @@
|
|||
#define PART_3
|
||||
#include "cpuemu.cpp"
|
3
BasiliskII/src/uae_cpu/cpuemu3_nf.cpp
Normal file
3
BasiliskII/src/uae_cpu/cpuemu3_nf.cpp
Normal file
|
@ -0,0 +1,3 @@
|
|||
#define NOFLAGS 1
|
||||
#define PART_3
|
||||
#include "cpuemu.cpp"
|
2
BasiliskII/src/uae_cpu/cpuemu4.cpp
Normal file
2
BasiliskII/src/uae_cpu/cpuemu4.cpp
Normal file
|
@ -0,0 +1,2 @@
|
|||
#define PART_4
|
||||
#include "cpuemu.cpp"
|
3
BasiliskII/src/uae_cpu/cpuemu4_nf.cpp
Normal file
3
BasiliskII/src/uae_cpu/cpuemu4_nf.cpp
Normal file
|
@ -0,0 +1,3 @@
|
|||
#define NOFLAGS 1
|
||||
#define PART_4
|
||||
#include "cpuemu.cpp"
|
2
BasiliskII/src/uae_cpu/cpuemu5.cpp
Normal file
2
BasiliskII/src/uae_cpu/cpuemu5.cpp
Normal file
|
@ -0,0 +1,2 @@
|
|||
#define PART_5
|
||||
#include "cpuemu.cpp"
|
4
BasiliskII/src/uae_cpu/cpuemu5_nf.cpp
Normal file
4
BasiliskII/src/uae_cpu/cpuemu5_nf.cpp
Normal file
|
@ -0,0 +1,4 @@
|
|||
#define NOFLAGS 1
|
||||
#define PART_5
|
||||
#include "cpuemu.cpp"
|
||||
|
2
BasiliskII/src/uae_cpu/cpuemu6.cpp
Normal file
2
BasiliskII/src/uae_cpu/cpuemu6.cpp
Normal file
|
@ -0,0 +1,2 @@
|
|||
#define PART_6
|
||||
#include "cpuemu.cpp"
|
3
BasiliskII/src/uae_cpu/cpuemu6_nf.cpp
Normal file
3
BasiliskII/src/uae_cpu/cpuemu6_nf.cpp
Normal file
|
@ -0,0 +1,3 @@
|
|||
#define NOFLAGS 1
|
||||
#define PART_6
|
||||
#include "cpuemu.cpp"
|
2
BasiliskII/src/uae_cpu/cpuemu7.cpp
Normal file
2
BasiliskII/src/uae_cpu/cpuemu7.cpp
Normal file
|
@ -0,0 +1,2 @@
|
|||
#define PART_7
|
||||
#include "cpuemu.cpp"
|
3
BasiliskII/src/uae_cpu/cpuemu7_nf.cpp
Normal file
3
BasiliskII/src/uae_cpu/cpuemu7_nf.cpp
Normal file
|
@ -0,0 +1,3 @@
|
|||
#define NOFLAGS 1
|
||||
#define PART_7
|
||||
#include "cpuemu.cpp"
|
2
BasiliskII/src/uae_cpu/cpuemu8.cpp
Normal file
2
BasiliskII/src/uae_cpu/cpuemu8.cpp
Normal file
|
@ -0,0 +1,2 @@
|
|||
#define PART_8
|
||||
#include "cpuemu.cpp"
|
3
BasiliskII/src/uae_cpu/cpuemu8_nf.cpp
Normal file
3
BasiliskII/src/uae_cpu/cpuemu8_nf.cpp
Normal file
|
@ -0,0 +1,3 @@
|
|||
#define NOFLAGS 1
|
||||
#define PART_8
|
||||
#include "cpuemu.cpp"
|
5
BasiliskII/src/uae_cpu/cpufunctbla.cpp
Normal file
5
BasiliskII/src/uae_cpu/cpufunctbla.cpp
Normal 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"
|
1096
BasiliskII/src/uae_cpu/cpummu.cpp
Normal file
1096
BasiliskII/src/uae_cpu/cpummu.cpp
Normal file
File diff suppressed because it is too large
Load Diff
267
BasiliskII/src/uae_cpu/cpummu.h
Normal file
267
BasiliskII/src/uae_cpu/cpummu.h
Normal 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 = ®s.itt0; break;
|
||||
case TTR_I1: ttr = ®s.itt1; break;
|
||||
case TTR_D0: ttr = ®s.dtt0; break;
|
||||
case TTR_D1: ttr = ®s.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:
|
||||
*/
|
|
@ -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 = ¤t->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;
|
||||
}
|
2
BasiliskII/src/uae_cpu/cpustbl_nf.cpp
Normal file
2
BasiliskII/src/uae_cpu/cpustbl_nf.cpp
Normal file
|
@ -0,0 +1,2 @@
|
|||
#define NOFLAGS 1
|
||||
#include "cpustbl.cpp"
|
5
BasiliskII/src/uae_cpu/cpustbla.cpp
Normal file
5
BasiliskII/src/uae_cpu/cpustbla.cpp
Normal 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"
|
82
BasiliskII/src/uae_cpu/debug.cpp
Normal file
82
BasiliskII/src/uae_cpu/debug.cpp
Normal 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:
|
||||
*/
|
268
BasiliskII/src/uae_cpu/fpu/core.h
Normal file
268
BasiliskII/src/uae_cpu/fpu/core.h
Normal 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 */
|
193
BasiliskII/src/uae_cpu/fpu/exceptions.cpp
Normal file
193
BasiliskII/src/uae_cpu/fpu/exceptions.cpp
Normal 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
|
154
BasiliskII/src/uae_cpu/fpu/exceptions.h
Normal file
154
BasiliskII/src/uae_cpu/fpu/exceptions.h
Normal 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 */
|
174
BasiliskII/src/uae_cpu/fpu/flags.cpp
Normal file
174
BasiliskII/src/uae_cpu/fpu/flags.cpp
Normal 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
|
228
BasiliskII/src/uae_cpu/fpu/flags.h
Normal file
228
BasiliskII/src/uae_cpu/fpu/flags.h
Normal 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 */
|
59
BasiliskII/src/uae_cpu/fpu/fpu.h
Normal file
59
BasiliskII/src/uae_cpu/fpu/fpu.h
Normal 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 */
|
2330
BasiliskII/src/uae_cpu/fpu/fpu_ieee.cpp
Normal file
2330
BasiliskII/src/uae_cpu/fpu/fpu_ieee.cpp
Normal file
File diff suppressed because it is too large
Load Diff
154
BasiliskII/src/uae_cpu/fpu/fpu_ieee.h
Normal file
154
BasiliskII/src/uae_cpu/fpu/fpu_ieee.h
Normal 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 */
|
2110
BasiliskII/src/uae_cpu/fpu/fpu_mpfr.cpp
Normal file
2110
BasiliskII/src/uae_cpu/fpu/fpu_mpfr.cpp
Normal file
File diff suppressed because it is too large
Load Diff
2553
BasiliskII/src/uae_cpu/fpu/fpu_uae.cpp
Normal file
2553
BasiliskII/src/uae_cpu/fpu/fpu_uae.cpp
Normal file
File diff suppressed because it is too large
Load Diff
217
BasiliskII/src/uae_cpu/fpu/fpu_uae.h
Normal file
217
BasiliskII/src/uae_cpu/fpu/fpu_uae.h
Normal 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 */
|
6791
BasiliskII/src/uae_cpu/fpu/fpu_x86.cpp
Normal file
6791
BasiliskII/src/uae_cpu/fpu/fpu_x86.cpp
Normal file
File diff suppressed because it is too large
Load Diff
384
BasiliskII/src/uae_cpu/fpu/fpu_x86.h
Normal file
384
BasiliskII/src/uae_cpu/fpu/fpu_x86.h
Normal 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 */
|
104
BasiliskII/src/uae_cpu/fpu/fpu_x86_asm.h
Normal file
104
BasiliskII/src/uae_cpu/fpu/fpu_x86_asm.h
Normal 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
|
159
BasiliskII/src/uae_cpu/fpu/impl.h
Normal file
159
BasiliskII/src/uae_cpu/fpu/impl.h
Normal 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 */
|
105
BasiliskII/src/uae_cpu/fpu/mathlib.cpp
Normal file
105
BasiliskII/src/uae_cpu/fpu/mathlib.cpp
Normal 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
|
1185
BasiliskII/src/uae_cpu/fpu/mathlib.h
Normal file
1185
BasiliskII/src/uae_cpu/fpu/mathlib.h
Normal file
File diff suppressed because it is too large
Load Diff
69
BasiliskII/src/uae_cpu/fpu/rounding.cpp
Normal file
69
BasiliskII/src/uae_cpu/fpu/rounding.cpp
Normal 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
|
159
BasiliskII/src/uae_cpu/fpu/rounding.h
Normal file
159
BasiliskII/src/uae_cpu/fpu/rounding.h
Normal 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 */
|
181
BasiliskII/src/uae_cpu/fpu/types.h
Normal file
181
BasiliskII/src/uae_cpu/fpu/types.h
Normal 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
|
@ -1,22 +1,67 @@
|
|||
/*
|
||||
* 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 FLAGVAL_Z 0x40
|
||||
#define FLAGVAL_N 0x80
|
||||
|
||||
#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 GET_ZFLG ((regflags.cznv >> 6) & 1)
|
||||
|
@ -26,11 +71,15 @@ struct flag_struct {
|
|||
#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,6 +662,9 @@ struct flag_struct {
|
|||
|
||||
extern struct flag_struct regflags;
|
||||
|
||||
#define FLAGVAL_Z 0x04
|
||||
#define FLAGVAL_N 0x08
|
||||
|
||||
#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))
|
||||
|
@ -164,9 +678,13 @@ extern struct flag_struct regflags;
|
|||
#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 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 */
|
||||
|
|
606
BasiliskII/src/uae_cpu/memory-uae.h
Normal file
606
BasiliskII/src/uae_cpu/memory-uae.h
Normal 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:
|
||||
*/
|
59
BasiliskII/src/uae_cpu/memory.cpp
Normal file
59
BasiliskII/src/uae_cpu/memory.cpp
Normal 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 */
|
|
@ -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
|
@ -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 *)®s.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 *)®s.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(®s.prefetch);
|
||||
return (do_get_mem_word (((uae_u16 *)®s.prefetch) + 1) << 16) | do_get_mem_word ((uae_u16 *)(regs.pc_p + 4));
|
||||
return (do_get_mem_word (((uae_u16 *)®s.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 (®s.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 (®s.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 (®s.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;
|
||||
}
|
||||
|
||||
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_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);
|
||||
}
|
||||
|
||||
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 */
|
||||
|
|
142
BasiliskII/src/uae_cpu/noflags.h
Normal file
142
BasiliskII/src/uae_cpu/noflags.h
Normal 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
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
5
BasiliskII/src/uae_cpu/readcpua.cpp
Normal file
5
BasiliskII/src/uae_cpu/readcpua.cpp
Normal 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"
|
116
BasiliskII/src/uae_cpu/registers.h
Normal file
116
BasiliskII/src/uae_cpu/registers.h
Normal 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
|
104
BasiliskII/src/uae_cpu/spcflags.h
Normal file
104
BasiliskII/src/uae_cpu/spcflags.h
Normal 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 */
|
|
@ -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 :
|
||||
% 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
|
||||
|
|
Loading…
Reference in New Issue
Block a user