uae_cpu is based upon ARAnyM sources
This commit is contained in:
parent
28bc58ccd2
commit
03fc337242
|
@ -1,11 +1,11 @@
|
|||
cmake_minimum_required(VERSION 3.0.0)
|
||||
project(BasiliskII)
|
||||
|
||||
if (NOT EXISTS ${CMAKE_BINARY_DIR}/CMakeCache.txt)
|
||||
if (NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE "Release" CACHE STRING "" FORCE)
|
||||
endif()
|
||||
endif()
|
||||
# if (NOT EXISTS ${CMAKE_BINARY_DIR}/CMakeCache.txt)
|
||||
# if (NOT CMAKE_BUILD_TYPE)
|
||||
# set(CMAKE_BUILD_TYPE "Release" CACHE STRING "" FORCE)
|
||||
# endif()
|
||||
# endif()
|
||||
|
||||
find_package(SDL2 REQUIRED)
|
||||
find_library(COREFOUNDATION_LIBRARY CoreFoundation)
|
||||
|
@ -21,7 +21,9 @@ 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 cpufunctbl.cpp COMMAND gencpu DEPENDS gencpu)
|
||||
add_custom_command(OUTPUT cpuemu.cpp cpuemu_nf.cpp cpustbl.cpp cpustbl_nf.cpp COMMAND gencpu DEPENDS gencpu)
|
||||
# add_custom_command(OUTPUT cpuemu.cpp cpuemu_nf.cpp cpustbl.cpp cpustbl_nf.cpp COMMAND gencpu DEPENDS gencpu)
|
||||
# add_custom_command(OUTPUT cpuemu.cpp cpuemu_nf.cpp cpustbl.cpp cpustbl_nf.cpp COMMAND gencpu DEPENDS gencpu)
|
||||
add_custom_command(OUTPUT cpuemu.cpp cpustbl.cpp cpufunctbl.cpp COMMAND gencpu DEPENDS gencpu)
|
||||
|
||||
add_executable(gencomp ../uae_cpu/compiler/gencomp.c ../uae_cpu/readcpu.cpp cpudefs.cpp)
|
||||
|
||||
|
@ -88,12 +90,11 @@ set(BasiliskII_SRCS
|
|||
cpustbl.cpp
|
||||
cpudefs.cpp
|
||||
cpuemu.cpp
|
||||
cpufunctbl.cpp
|
||||
compemu.cpp
|
||||
compstbl.cpp
|
||||
../uae_cpu/compiler/compemu_support.cpp
|
||||
../uae_cpu/compiler/compemu_fpp.cpp
|
||||
cpustbl_nf.cpp
|
||||
cpuemu_nf.cpp
|
||||
#addressing mode =direct -DDIRECT_ADDRESSING
|
||||
#includes
|
||||
)
|
||||
|
@ -101,7 +102,7 @@ set(BasiliskII_SRCS
|
|||
add_executable(BasiliskII ${BasiliskII_SRCS})
|
||||
|
||||
set_source_files_properties(${BasiliskII_SRCS}
|
||||
PROPERTIES COMPILE_FLAGS "-DDIRECT_ADDRESSING -DCPU_x86_64 -DFIXED_ADDRESSING -DCPU_64_BIT -DNOFLAGS_SUPPORT -DFPU_IEEE -DUSE_JIT -DJIT -DX86_64_ASSEMBLY -DOPTIMIZED_FLAGS -DWINUAE_ARANYM -DUSE_JIT_FPU -DUSE_INLINING -DDATADIR=\\\".\\\"")
|
||||
PROPERTIES COMPILE_FLAGS "-DDIRECT_ADDRESSING -DCPU_x86_64 -DFIXED_ADDRESSING -DCPU_64_BIT -DFPU_IEEE -DUSE_JIT -DJIT -DX86_64_ASSEMBLY -DOPTIMIZED_FLAGS -DWINUAE_ARANYM -DUSE_JIT_FPU -DUSE_INLINING -DDATADIR=\\\".\\\"")
|
||||
|
||||
# set_property(SOURCE compemu_support.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -O0 ")
|
||||
|
||||
|
|
|
@ -58,6 +58,7 @@ using std::string;
|
|||
|
||||
#if USE_JIT
|
||||
extern void (*flush_icache)(void); // from compemu_support.cpp
|
||||
extern bool UseJIT;
|
||||
#endif
|
||||
|
||||
|
||||
|
@ -181,8 +182,8 @@ static void sigsegv_dump_state(sigsegv_info_t *sip)
|
|||
fprintf(stderr, " [IP=%p]", fault_instruction);
|
||||
fprintf(stderr, "\n");
|
||||
#if EMULATED_68K
|
||||
extern void m68k_dumpstate (uaecptr *);
|
||||
m68k_dumpstate(0);
|
||||
extern void m68k_dumpstate (FILE *, uaecptr *);
|
||||
m68k_dumpstate(stderr, 0);
|
||||
#endif
|
||||
#if USE_JIT && JIT_DEBUG
|
||||
extern void compiler_dumpstate(void);
|
||||
|
|
|
@ -419,6 +419,13 @@ static inline uae_u32 do_byteswap_16(uae_u32 v)
|
|||
# define REGPARAM
|
||||
#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
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@
|
|||
* Execute EMUL_OP opcode (called by 68k emulator or Illegal Instruction trap handler)
|
||||
*/
|
||||
|
||||
void EmulOp(uint16 opcode, M68kRegisters *r)
|
||||
bool EmulOp(uint16 opcode, M68kRegisters *r)
|
||||
{
|
||||
D(bug("EmulOp %04x\n", opcode));
|
||||
switch (opcode) {
|
||||
|
@ -68,12 +68,12 @@ void EmulOp(uint16 opcode, M68kRegisters *r)
|
|||
VideoQuitFullScreen();
|
||||
|
||||
QuitEmulator();
|
||||
break;
|
||||
return false;
|
||||
}
|
||||
|
||||
case M68K_EMUL_OP_SHUTDOWN: // Quit emulator
|
||||
QuitEmulator();
|
||||
break;
|
||||
return false;
|
||||
|
||||
case M68K_EMUL_OP_RESET: { // MacOS reset
|
||||
D(bug("*** RESET ***\n"));
|
||||
|
@ -101,7 +101,7 @@ void EmulOp(uint16 opcode, M68kRegisters *r)
|
|||
r->a[1] = ROMBaseMac + UniversalInfo; // UniversalInfo
|
||||
r->a[6] = boot_globs; // BootGlobs
|
||||
r->a[7] = RAMBaseMac + 0x10000; // Boot stack
|
||||
break;
|
||||
return false;
|
||||
}
|
||||
|
||||
case M68K_EMUL_OP_CLKNOMEM: { // Clock/PRAM operations
|
||||
|
@ -570,6 +570,8 @@ void EmulOp(uint16 opcode, M68kRegisters *r)
|
|||
r->sr);
|
||||
|
||||
QuitEmulator();
|
||||
break;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -94,6 +94,6 @@ enum {
|
|||
};
|
||||
|
||||
// Functions
|
||||
extern void EmulOp(uint16 opcode, struct M68kRegisters *r); // Execute EMUL_OP opcode (called by 68k emulator or Line-F trap handler)
|
||||
extern bool EmulOp(uint16 opcode, struct M68kRegisters *r); // Execute EMUL_OP opcode (called by 68k emulator or Line-F trap handler)
|
||||
|
||||
#endif
|
||||
|
|
|
@ -34,8 +34,10 @@ extern bool TwentyFourBitAddressing;
|
|||
// 68k register structure (for Execute68k())
|
||||
struct M68kRegisters {
|
||||
uint32 d[8];
|
||||
uint32 a[8];
|
||||
memptr a[8];
|
||||
uint16 sr;
|
||||
memptr usp, isp, msp;
|
||||
memptr pc;
|
||||
};
|
||||
|
||||
// General functions
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
#
|
||||
# Note: this Makefile only contains rules for the source
|
||||
# generator tools.
|
||||
#
|
||||
|
||||
#
|
||||
# suppress warnings about overriding LDFLAGS and CPPFLAGS
|
||||
#
|
||||
AUTOMAKE_OPTIONS = -Wno-gnu
|
||||
|
||||
AM_CPPFLAGS = $(DEFINES) \
|
||||
"-I$(srcdir)/../include" \
|
||||
"-I$(srcdir)/../Unix" \
|
||||
"-I$(builddir)/.." \
|
||||
"-I$(builddir)" \
|
||||
"-I$(srcdir)"
|
||||
|
||||
CC = $(CC_FOR_BUILD)
|
||||
CXX = $(CXX_FOR_BUILD)
|
||||
|
||||
LDFLAGS = $(LDFLAGS_FOR_BUILD)
|
||||
CPPFLAGS = $(CPPFLAGS_FOR_BUILD)
|
||||
CFLAGS = $(CFLAGS_FOR_BUILD)
|
||||
CXXFLAGS = $(CXXFLAGS_FOR_BUILD)
|
||||
LIBS=-lm
|
||||
|
||||
CFLAGS_NOWARN = $(DBGSP)
|
||||
AM_CFLAGS = $(CFLAGS_NOWARN) $(WFLAGS)
|
||||
AM_CXXFLAGS = $(CFLAGS_NOWARN) $(WFLAGS)
|
||||
|
||||
noinst_PROGRAMS = build68k gencpu
|
||||
if USE_JIT
|
||||
noinst_PROGRAMS += gencomp
|
||||
endif
|
||||
|
||||
BUILT_SOURCES = \
|
||||
cpudefs.cpp \
|
||||
cpuemu.cpp \
|
||||
cpustbl.cpp \
|
||||
cpufunctbl.cpp \
|
||||
cputbl.h \
|
||||
$(empty)
|
||||
|
||||
build68k_SOURCES = build68k.c
|
||||
gencpu_SOURCES = gencpu.c m68k.h readcpu.cpp readcpu.h cpudefs.cpp
|
||||
gencomp_SOURCES =
|
||||
if GENCOMP_ARCH_X86
|
||||
gencomp_SOURCES += compiler/gencomp.c
|
||||
endif
|
||||
if GENCOMP_ARCH_ARM
|
||||
gencomp_SOURCES += compiler/gencomp_arm.c
|
||||
endif
|
||||
gencomp_SOURCES += readcpu.cpp cpudefs.cpp
|
||||
|
||||
if USE_JIT
|
||||
BUILT_SOURCES += compemu.cpp compstbl.cpp comptbl.h
|
||||
endif
|
||||
|
||||
|
||||
cpudefs.cpp: build68k$(EXEEXT) $(srcdir)/table68k
|
||||
$(AM_V_GEN)./build68k <$(srcdir)/table68k > $@
|
||||
cpuemu.cpp: gencpu$(EXEEXT)
|
||||
$(AM_V_GEN)./gencpu$(EXEEXT)
|
||||
cpustbl.cpp cpufunctbl.cpp cputbl.h: cpuemu.cpp
|
||||
compemu.cpp: gencomp$(EXEEXT)
|
||||
$(AM_V_GEN)./gencomp$(EXEEXT)
|
||||
compstbl.cpp comptbl.h: compemu.cpp
|
||||
|
||||
CLEANFILES = $(BUILT_SOURCES)
|
||||
|
||||
EXTRA_DIST = \
|
||||
table68k \
|
||||
compiler/codegen_arm.cpp compiler/codegen_arm.h \
|
||||
compiler/compemu_midfunc_arm.cpp compiler/compemu_midfunc_arm.h \
|
||||
compiler/compemu_midfunc_arm2.cpp compiler/compemu_midfunc_arm2.h \
|
||||
compiler/test_codegen_arm.c \
|
||||
compiler/codegen_x86.cpp compiler/codegen_x86.h \
|
||||
compiler/compemu_midfunc_x86.cpp compiler/compemu_midfunc_x86.h \
|
||||
compiler/test_codegen_x86.cpp \
|
||||
$(empty)
|
|
@ -0,0 +1,326 @@
|
|||
/*
|
||||
* aranym_glue.cpp - CPU interface
|
||||
*
|
||||
* Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
|
||||
*
|
||||
* Inspired by Christian Bauer's Basilisk II
|
||||
*
|
||||
* This file is part of the ARAnyM project which builds a new and powerful
|
||||
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
|
||||
*
|
||||
* ARAnyM is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ARAnyM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ARAnyM; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "sysdeps.h"
|
||||
|
||||
#include "cpu_emulation.h"
|
||||
#include "newcpu.h"
|
||||
#include "hardware.h"
|
||||
#include "scc.h"
|
||||
#include "input.h"
|
||||
#ifdef USE_JIT
|
||||
# include "compiler/compemu.h"
|
||||
#endif
|
||||
#include "nf_objs.h"
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
// RAM and ROM pointers
|
||||
memptr RAMBase = 0; // RAM base (Atari address space) gb-- init is important
|
||||
uint8 *RAMBaseHost; // RAM base (host address space)
|
||||
uint32 RAMSize = 0x00e00000; // Size of RAM
|
||||
|
||||
memptr ROMBase = 0x00e00000; // ROM base (Atari address space)
|
||||
uint8 *ROMBaseHost; // ROM base (host address space)
|
||||
uint32 ROMSize = 0x00100000; // Size of ROM
|
||||
|
||||
uint32 RealROMSize; // Real size of ROM
|
||||
|
||||
memptr HWBase = 0x00f00000; // HW base (Atari address space)
|
||||
uint8 *HWBaseHost; // HW base (host address space)
|
||||
uint32 HWSize = 0x00100000; // Size of HW space
|
||||
|
||||
memptr FastRAMBase = 0x01000000; // Fast-RAM base (Atari address space)
|
||||
uint8 *FastRAMBaseHost; // Fast-RAM base (host address space)
|
||||
|
||||
#ifdef HW_SIGSEGV
|
||||
uint8 *FakeIOBaseHost;
|
||||
#endif
|
||||
|
||||
#ifdef FIXED_VIDEORAM
|
||||
memptr VideoRAMBase = ARANYMVRAMSTART; // VideoRAM base (Atari address space)
|
||||
#else
|
||||
memptr VideoRAMBase; // VideoRAM base (Atari address space)
|
||||
#endif
|
||||
uint8 *VideoRAMBaseHost;// VideoRAM base (host address space)
|
||||
//uint32 VideoRAMSize; // Size of VideoRAM
|
||||
|
||||
#ifndef NOT_MALLOC
|
||||
uintptr MEMBaseDiff; // Global offset between a Atari address and its Host equivalent
|
||||
uintptr ROMBaseDiff;
|
||||
uintptr FastRAMBaseDiff;
|
||||
#endif
|
||||
|
||||
uintptr VMEMBaseDiff; // Global offset between a Atari VideoRAM address and /dev/fb0 mmap
|
||||
|
||||
|
||||
#if defined(ENABLE_EXCLUSIVE_SPCFLAGS) && !defined(HAVE_HARDWARE_LOCKS)
|
||||
SDL_mutex *spcflags_lock;
|
||||
#endif
|
||||
#if defined(ENABLE_REALSTOP)
|
||||
SDL_cond *stop_condition;
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Initialize 680x0 emulation
|
||||
*/
|
||||
|
||||
bool InitMEM() {
|
||||
InitMEMBaseDiff(RAMBaseHost, RAMBase);
|
||||
InitROMBaseDiff(ROMBaseHost, ROMBase);
|
||||
InitFastRAMBaseDiff(FastRAMBaseHost, FastRAMBase);
|
||||
InitVMEMBaseDiff(VideoRAMBaseHost, VideoRAMBase);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Init680x0(void)
|
||||
{
|
||||
init_m68k();
|
||||
|
||||
#if defined(ENABLE_EXCLUSIVE_SPCFLAGS) && !defined(HAVE_HARDWARE_LOCKS)
|
||||
if ((spcflags_lock = SDL_CreateMutex()) == NULL) {
|
||||
panicbug("Error by SDL_CreateMutex()");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENABLE_REALSTOP
|
||||
if ((stop_condition = SDL_CreateCond()) == NULL) {
|
||||
panicbug("Error by SDL_CreateCond()");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_JIT
|
||||
if (bx_options.jit.jit) compiler_init();
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Instr. RESET
|
||||
*/
|
||||
|
||||
void AtariReset(void)
|
||||
{
|
||||
// reset Atari hardware here
|
||||
HWReset();
|
||||
// reset NatFeats here
|
||||
NFReset();
|
||||
// reset the input devices (input.cpp)
|
||||
InputReset();
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset CPU
|
||||
*/
|
||||
|
||||
void Reset680x0(void)
|
||||
{
|
||||
m68k_reset();
|
||||
}
|
||||
|
||||
/*
|
||||
* Deinitialize 680x0 emulation
|
||||
*/
|
||||
|
||||
void Exit680x0(void)
|
||||
{
|
||||
#ifdef USE_JIT
|
||||
if (bx_options.jit.jit) compiler_exit();
|
||||
#endif
|
||||
exit_m68k();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Reset and start 680x0 emulation
|
||||
*/
|
||||
|
||||
void Start680x0(void)
|
||||
{
|
||||
m68k_reset();
|
||||
#ifdef USE_JIT
|
||||
if (bx_options.jit.jit) {
|
||||
m68k_compile_execute();
|
||||
}
|
||||
else
|
||||
#endif
|
||||
m68k_execute();
|
||||
}
|
||||
|
||||
/*
|
||||
* Restart running 680x0 emulation safely from different thread
|
||||
*/
|
||||
void Restart680x0(void)
|
||||
{
|
||||
quit_program = 2;
|
||||
TriggerNMI();
|
||||
}
|
||||
|
||||
/*
|
||||
* Quit 680x0 emulation safely from different thread
|
||||
*/
|
||||
void Quit680x0(void)
|
||||
{
|
||||
quit_program = 1;
|
||||
TriggerNMI();
|
||||
}
|
||||
|
||||
|
||||
int MFPdoInterrupt(void)
|
||||
{
|
||||
return getMFP()->doInterrupt();
|
||||
}
|
||||
|
||||
int SCCdoInterrupt(void)
|
||||
{
|
||||
return getSCC()->doInterrupt();
|
||||
}
|
||||
|
||||
/*
|
||||
* Trigger interrupts
|
||||
*/
|
||||
void TriggerInternalIRQ(void)
|
||||
{
|
||||
SPCFLAGS_SET( SPCFLAG_INTERNAL_IRQ );
|
||||
}
|
||||
|
||||
void TriggerInt3(void)
|
||||
{
|
||||
SPCFLAGS_SET( SPCFLAG_INT3 );
|
||||
}
|
||||
|
||||
void TriggerVBL(void)
|
||||
{
|
||||
SPCFLAGS_SET( SPCFLAG_VBL );
|
||||
}
|
||||
|
||||
void TriggerInt5(void)
|
||||
{
|
||||
SPCFLAGS_SET( SPCFLAG_INT5 );
|
||||
}
|
||||
|
||||
void TriggerSCC(bool enable)
|
||||
{
|
||||
if (enable)
|
||||
SPCFLAGS_SET( SPCFLAG_SCC );
|
||||
else
|
||||
SPCFLAGS_CLEAR( SPCFLAG_SCC );
|
||||
}
|
||||
|
||||
void TriggerMFP(bool enable)
|
||||
{
|
||||
if (enable)
|
||||
SPCFLAGS_SET( SPCFLAG_MFP );
|
||||
else
|
||||
SPCFLAGS_CLEAR( SPCFLAG_MFP );
|
||||
}
|
||||
|
||||
void TriggerNMI(void)
|
||||
{
|
||||
SPCFLAGS_SET( SPCFLAG_BRK ); // use _BRK for NMI
|
||||
}
|
||||
|
||||
#ifndef REBOOT_OR_HALT
|
||||
#define REBOOT_OR_HALT 0 // halt by default
|
||||
#endif
|
||||
|
||||
#if REBOOT_OR_HALT == 1
|
||||
# define CPU_MSG "CPU: Rebooting"
|
||||
# define CPU_ACTION Restart680x0()
|
||||
#else
|
||||
# define CPU_MSG "CPU: Halting"
|
||||
# define CPU_ACTION Quit680x0()
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_EPSLIMITER
|
||||
|
||||
#ifndef EPS_LIMIT
|
||||
# define EPS_LIMIT 10000 /* this might be too high if ARAnyM is slowed down by printing the bus errors on console */
|
||||
#endif
|
||||
|
||||
void check_eps_limit(uaecptr pc)
|
||||
{
|
||||
static long last_exception_time=-1;
|
||||
static long exception_per_sec=0;
|
||||
static long exception_per_sec_pc=0;
|
||||
static uaecptr prevpc = 0;
|
||||
|
||||
if (bx_options.cpu.eps_enabled) {
|
||||
if (last_exception_time == -1) {
|
||||
last_exception_time = SDL_GetTicks();
|
||||
}
|
||||
|
||||
exception_per_sec++;
|
||||
|
||||
if (pc == prevpc) {
|
||||
/* BUS ERRORs occur at the same PC - watch out! */
|
||||
exception_per_sec_pc++;
|
||||
}
|
||||
else {
|
||||
exception_per_sec_pc = 0;
|
||||
prevpc = pc;
|
||||
}
|
||||
|
||||
if (SDL_GetTicks() - last_exception_time > 1000) {
|
||||
last_exception_time = SDL_GetTicks();
|
||||
if (exception_per_sec_pc > bx_options.cpu.eps_max ||
|
||||
exception_per_sec > EPS_LIMIT /* make it configurable */) {
|
||||
panicbug("CPU: Exception per second limit reached: %ld/%ld",
|
||||
exception_per_sec_pc, exception_per_sec);
|
||||
/* would be cool to open SDL dialog here: */
|
||||
/* [Exception per seconds limit reached. XXXXX exception
|
||||
occured in the last second. The limit is set to YYYYY
|
||||
in your config file. Do you want to continue emulation,
|
||||
reset ARAnyM or quit ?][Continue] [Reset] [Quit]
|
||||
*/
|
||||
panicbug(CPU_MSG);
|
||||
CPU_ACTION;
|
||||
}
|
||||
exception_per_sec = 0;
|
||||
exception_per_sec_pc = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void report_double_bus_error()
|
||||
{
|
||||
panicbug("CPU: Double bus fault detected !");
|
||||
/* would be cool to open SDL dialog here: */
|
||||
/* [Double bus fault detected. The emulated system crashed badly.
|
||||
Do you want to reset ARAnyM or quit ?] [Reset] [Quit]"
|
||||
*/
|
||||
panicbug(CPU_MSG);
|
||||
CPU_ACTION;
|
||||
}
|
||||
|
||||
#ifdef FLIGHT_RECORDER
|
||||
extern bool cpu_flight_recorder_active;
|
||||
void cpu_flight_recorder(int activate) { cpu_flight_recorder_active = activate; }
|
||||
#endif
|
|
@ -56,8 +56,12 @@ uintptr MEMBaseDiff; // Global offset between a Mac address and its Host equiva
|
|||
bool UseJIT = false;
|
||||
#endif
|
||||
|
||||
// #if defined(ENABLE_EXCLUSIVE_SPCFLAGS) && !defined(HAVE_HARDWARE_LOCKS)
|
||||
B2_mutex *spcflags_lock = NULL;
|
||||
// #endif
|
||||
|
||||
// From newcpu.cpp
|
||||
extern bool quit_program;
|
||||
extern int quit_program;
|
||||
|
||||
|
||||
/*
|
||||
|
@ -66,6 +70,7 @@ extern bool quit_program;
|
|||
|
||||
bool Init680x0(void)
|
||||
{
|
||||
spcflags_lock = B2_create_mutex();
|
||||
#if REAL_ADDRESSING
|
||||
// Mac address space = host address space
|
||||
RAMBaseMac = (uintptr)RAMBaseHost;
|
||||
|
@ -159,7 +164,8 @@ void TriggerInterrupt(void)
|
|||
|
||||
void TriggerNMI(void)
|
||||
{
|
||||
SPCFLAGS_SET( SPCFLAG_BRK ); // use _BRK for NMI
|
||||
//!! not implemented yet
|
||||
// SPCFLAGS_SET( SPCFLAG_BRK ); // use _BRK for NMI
|
||||
}
|
||||
|
||||
|
||||
|
@ -200,7 +206,7 @@ void Execute68kTrap(uint16 trap, struct M68kRegisters *r)
|
|||
// Execute trap
|
||||
m68k_setpc(m68k_areg(regs, 7));
|
||||
fill_prefetch_0();
|
||||
quit_program = false;
|
||||
quit_program = 0;
|
||||
m68k_execute();
|
||||
|
||||
// Clean up stack
|
||||
|
@ -215,7 +221,7 @@ void Execute68kTrap(uint16 trap, struct M68kRegisters *r)
|
|||
r->d[i] = m68k_dreg(regs, i);
|
||||
for (i=0; i<7; i++)
|
||||
r->a[i] = m68k_areg(regs, i);
|
||||
quit_program = false;
|
||||
quit_program = 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -247,7 +253,7 @@ void Execute68k(uint32 addr, struct M68kRegisters *r)
|
|||
// Execute routine
|
||||
m68k_setpc(addr);
|
||||
fill_prefetch_0();
|
||||
quit_program = false;
|
||||
quit_program = 0;
|
||||
m68k_execute();
|
||||
|
||||
// Clean up stack
|
||||
|
@ -262,5 +268,18 @@ void Execute68k(uint32 addr, struct M68kRegisters *r)
|
|||
r->d[i] = m68k_dreg(regs, i);
|
||||
for (i=0; i<7; i++)
|
||||
r->a[i] = m68k_areg(regs, i);
|
||||
quit_program = false;
|
||||
quit_program = 0;
|
||||
}
|
||||
|
||||
void report_double_bus_error()
|
||||
{
|
||||
#if 0
|
||||
panicbug("CPU: Double bus fault detected !");
|
||||
/* would be cool to open SDL dialog here: */
|
||||
/* [Double bus fault detected. The emulated system crashed badly.
|
||||
Do you want to reset ARAnyM or quit ?] [Reset] [Quit]"
|
||||
*/
|
||||
panicbug(CPU_MSG);
|
||||
CPU_ACTION;
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -1,32 +1,44 @@
|
|||
/*
|
||||
* build68k.c - m68k CPU builder
|
||||
*
|
||||
* Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
|
||||
*
|
||||
* Inspired by Christian Bauer's Basilisk II
|
||||
*
|
||||
* This file is part of the ARAnyM project which builds a new and powerful
|
||||
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
|
||||
*
|
||||
* ARAnyM is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ARAnyM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ARAnyM; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
/*
|
||||
* UAE - The Un*x Amiga Emulator
|
||||
*
|
||||
* Read 68000 CPU specs from file "table68k" and build table68k.c
|
||||
*
|
||||
* Copyright 1995,1996 Bernd Schmidt
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "sysdeps.h"
|
||||
#include "readcpu.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#undef abort
|
||||
|
||||
static FILE *tablef;
|
||||
static int nextch = 0;
|
||||
|
||||
|
@ -65,15 +77,15 @@ static int nextchtohex(void)
|
|||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
int main()
|
||||
{
|
||||
int no_insns = 0;
|
||||
|
||||
printf ("#include \"sysdeps.h\"\n");
|
||||
printf ("#include \"readcpu.h\"\n");
|
||||
printf ("struct instr_def defs68k[] = {\n");
|
||||
#ifdef WIN32
|
||||
tablef = fopen(argc > 1 ? argv[1] : "table68k","r");
|
||||
#if 0
|
||||
tablef = fopen("table68k","r");
|
||||
if (tablef == NULL) {
|
||||
fprintf(stderr, "table68k not found\n");
|
||||
exit(1);
|
||||
|
@ -122,8 +134,8 @@ int main(int argc, char **argv)
|
|||
case 'r': currbit = bitr; break;
|
||||
case 'R': currbit = bitR; break;
|
||||
case 'z': currbit = bitz; break;
|
||||
case 'E': currbit = bitE; break;
|
||||
case 'p': currbit = bitp; break;
|
||||
case 'E': currbit = bitE; break;
|
||||
case 'p': currbit = bitp; break;
|
||||
default: abort();
|
||||
}
|
||||
if (!(bitmask & 1)) {
|
||||
|
@ -138,6 +150,7 @@ int main(int argc, char **argv)
|
|||
patbits[i] = nextch;
|
||||
getnextch();
|
||||
}
|
||||
(void) patbits;
|
||||
|
||||
while (isspace(nextch) || nextch == ':') /* Get CPU and privilege level */
|
||||
getnextch();
|
||||
|
@ -172,6 +185,8 @@ int main(int argc, char **argv)
|
|||
getnextch();
|
||||
switch(nextch){
|
||||
case '-': flagset[i] = fa_unset; break;
|
||||
case '/': flagset[i] = fa_isjmp; break;
|
||||
case '+': flagset[i] = fa_isbranch; break;
|
||||
case '0': flagset[i] = fa_zero; break;
|
||||
case '1': flagset[i] = fa_one; break;
|
||||
case 'x': flagset[i] = fa_dontcare; break;
|
||||
|
@ -191,6 +206,8 @@ int main(int argc, char **argv)
|
|||
getnextch();
|
||||
switch(nextch){
|
||||
case '-': flaguse[i] = fu_unused; break;
|
||||
case '/': flaguse[i] = fu_isjmp; break;
|
||||
case '+': flaguse[i] = fu_maybecc; break;
|
||||
case '?': flaguse[i] = fu_unknown; break;
|
||||
default: flaguse[i] = fu_used; break;
|
||||
}
|
||||
|
@ -235,7 +252,7 @@ int main(int argc, char **argv)
|
|||
if (nextch != ':')
|
||||
abort();
|
||||
|
||||
fgets(opcstr, 250, tablef);
|
||||
assert(fgets(opcstr, 250, tablef) != NULL);
|
||||
getnextch();
|
||||
{
|
||||
int j;
|
||||
|
@ -243,12 +260,12 @@ int main(int argc, char **argv)
|
|||
char *opstrp = opcstr, *osendp;
|
||||
int slen = 0;
|
||||
|
||||
while (isspace(*opstrp))
|
||||
while (isspace((int)*opstrp))
|
||||
opstrp++;
|
||||
|
||||
osendp = opstrp;
|
||||
while (*osendp) {
|
||||
if (!isspace (*osendp))
|
||||
if (!isspace ((int)*osendp))
|
||||
slen = osendp - opstrp + 1;
|
||||
osendp++;
|
||||
}
|
||||
|
@ -271,6 +288,5 @@ int main(int argc, char **argv)
|
|||
}
|
||||
}
|
||||
printf("};\nint n_defs68k = %d;\n", no_insns);
|
||||
fflush(stdout);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -273,7 +273,7 @@ uae_u8* comp_pc_p;
|
|||
#else
|
||||
// External variables
|
||||
// newcpu.cpp
|
||||
extern bool quit_program;
|
||||
extern int quit_program;
|
||||
#endif
|
||||
|
||||
// gb-- Extra data for Basilisk II/JIT
|
||||
|
@ -2718,8 +2718,7 @@ void compiler_init(void)
|
|||
jit_log("<JIT compiler> : separate blockinfo allocation : %s", str_on_off(USE_SEPARATE_BIA));
|
||||
|
||||
// Build compiler tables
|
||||
read_table68k();
|
||||
do_merges();
|
||||
init_table68k ();
|
||||
build_comp();
|
||||
#endif
|
||||
|
||||
|
@ -4157,7 +4156,9 @@ void build_comp(void)
|
|||
int count;
|
||||
#ifdef WINUAE_ARANYM
|
||||
unsigned int cpu_level = 4; // 68040
|
||||
#if 0
|
||||
const struct cputbl *nfctbl = op_smalltbl_0_nf;
|
||||
#endif
|
||||
#else
|
||||
#ifdef NOFLAGS_SUPPORT
|
||||
struct comptbl *nfctbl = (currprefs.cpu_level >= 5 ? op_smalltbl_0_nf
|
||||
|
|
|
@ -3228,8 +3228,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
|||
int main(void)
|
||||
#endif
|
||||
{
|
||||
read_table68k ();
|
||||
do_merges ();
|
||||
init_table68k ();
|
||||
|
||||
opcode_map = (int *) malloc (sizeof (int) * nr_cpuop_funcs);
|
||||
opcode_last_postfix = (int *) malloc (sizeof (int) * nr_cpuop_funcs);
|
||||
|
|
|
@ -5025,8 +5025,7 @@ void cygwin_mingw_abort()
|
|||
|
||||
int main(void)
|
||||
{
|
||||
read_table68k();
|
||||
do_merges();
|
||||
init_table68k ();
|
||||
|
||||
opcode_map = (int *) malloc(sizeof(int) * nr_cpuop_funcs);
|
||||
opcode_last_postfix = (int *) malloc(sizeof(int) * nr_cpuop_funcs);
|
||||
|
|
|
@ -1,52 +1,170 @@
|
|||
/*
|
||||
* cpu_emulation.h - Definitions for Basilisk II CPU emulation module (UAE 0.8.10 version)
|
||||
* cpu_emulation.h - CPU interface
|
||||
*
|
||||
* Basilisk II (C) 1997-2008 Christian Bauer
|
||||
* Copyright (c) 2001-2005 Milan Jurik of ARAnyM dev team (see AUTHORS)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
* Inspired by Christian Bauer's Basilisk II
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
* This file is part of the ARAnyM project which builds a new and powerful
|
||||
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* ARAnyM is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ARAnyM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ARAnyM; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef CPU_EMULATION_H
|
||||
#define CPU_EMULATION_H
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
||||
/*
|
||||
* Memory system
|
||||
*/
|
||||
|
||||
#if 0
|
||||
#include "sysdeps.h"
|
||||
#include "memory.h"
|
||||
#include "tools.h"
|
||||
#endif
|
||||
|
||||
// RAM and ROM pointers (allocated and set by main_*.cpp)
|
||||
#if 0
|
||||
extern memptr RAMBase; // RAM base (Atari address space), does not include Low Mem when != 0
|
||||
#else
|
||||
extern uint32 RAMBaseMac; // RAM base (Mac address space), does not include Low Mem when != 0
|
||||
extern uint8 *RAMBaseHost; // RAM base (host address space)
|
||||
extern uint32 RAMSize; // Size of RAM
|
||||
|
||||
#endif
|
||||
extern uint8 *RAMBaseHost; // RAM base (host address space)
|
||||
extern uint32 RAMSize; // Size of RAM
|
||||
#if 0
|
||||
extern memptr ROMBase; // ROM base (Atari address space)
|
||||
#else
|
||||
extern uint32 ROMBaseMac; // ROM base (Mac address space)
|
||||
extern uint8 *ROMBaseHost; // ROM base (host address space)
|
||||
extern uint32 ROMSize; // Size of ROM
|
||||
#endif
|
||||
extern uint8 *ROMBaseHost; // ROM base (host address space)
|
||||
extern uint32 ROMSize; // Size of ROM
|
||||
#if 0
|
||||
extern uint32 RealROMSize; // Real size of ROM
|
||||
extern memptr HWBase; // HW base (Atari address space)
|
||||
extern uint8 *HWBaseHost; // HW base (host address space)
|
||||
extern uint32 HWSize; // Size of HW space
|
||||
|
||||
#if !REAL_ADDRESSING && !DIRECT_ADDRESSING
|
||||
// If we are not using real or direct addressing, the Mac frame buffer gets
|
||||
// mapped to this location. The memory must be allocated by VideoInit().
|
||||
// If multiple monitors are used, they must share the frame buffer
|
||||
extern memptr FastRAMBase; // Fast-RAM base (Atari address space)
|
||||
extern uint8 *FastRAMBaseHost; // Fast-RAM base (host address space)
|
||||
extern memptr VideoRAMBase; // VideoRAM base (Atari address space)
|
||||
extern uint8 *VideoRAMBaseHost; // VideoRAM base (host address space)
|
||||
|
||||
#ifdef HW_SIGSEGV
|
||||
extern uint8 *FakeIOBaseHost;
|
||||
#endif
|
||||
|
||||
#ifdef RAMENDNEEDED
|
||||
# define RAMEnd 0x01000000 // Not accessible top of memory
|
||||
#else
|
||||
# define RAMEnd 0
|
||||
#endif
|
||||
#endif
|
||||
#if !REAL_ADDRESSING
|
||||
// If we are not using real addressing, the Mac frame buffer gets mapped to this location
|
||||
// The memory must be allocated by VideoInit(). If multiple monitors are used, they must
|
||||
// share the frame buffer
|
||||
const uint32 MacFrameBaseMac = 0xa0000000;
|
||||
extern uint8 *MacFrameBaseHost; // Frame buffer base (host address space)
|
||||
extern uint32 MacFrameSize; // Size of frame buffer
|
||||
#endif
|
||||
extern int MacFrameLayout; // Frame buffer layout (see defines below)
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
// Atari memory access functions
|
||||
// Direct access to CPU address space
|
||||
// For HW operations
|
||||
// Read/WriteAtariIntXX
|
||||
//
|
||||
static inline uint64 ReadAtariInt64(memptr addr) {return phys_get_quad(addr);}
|
||||
static inline uint32 ReadAtariInt32(memptr addr) {return phys_get_long(addr);}
|
||||
static inline uint16 ReadAtariInt16(memptr addr) {return phys_get_word(addr);}
|
||||
static inline uint8 ReadAtariInt8(memptr addr) {return phys_get_byte(addr);}
|
||||
static inline void WriteAtariInt64(memptr addr, uint64 q) {phys_put_quad(addr, q);}
|
||||
static inline void WriteAtariInt32(memptr addr, uint32 l) {phys_put_long(addr, l);}
|
||||
static inline void WriteAtariInt16(memptr addr, uint16 w) {phys_put_word(addr, w);}
|
||||
static inline void WriteAtariInt8(memptr addr, uint8 b) {phys_put_byte(addr, b);}
|
||||
|
||||
// Direct access to allocated memory
|
||||
// Ignores HW checks, so that be carefull
|
||||
// Read/WriteHWMemIntXX
|
||||
//
|
||||
static inline uint32 ReadHWMemInt32(memptr addr) {return do_get_mem_long((uae_u32 *)phys_get_real_address(addr));}
|
||||
static inline uint16 ReadHWMemInt16(memptr addr) {return do_get_mem_word((uae_u16 *)phys_get_real_address(addr));}
|
||||
static inline uint8 ReadHWMemInt8(memptr addr) {return do_get_mem_byte((uae_u8 *)phys_get_real_address(addr));}
|
||||
static inline void WriteHWMemInt32(memptr addr, uint32 l) {do_put_mem_long((uae_u32 *)phys_get_real_address(addr), l);}
|
||||
static inline void WriteHWMemInt16(memptr addr, uint16 w) {do_put_mem_word((uae_u16 *)phys_get_real_address(addr), w);}
|
||||
static inline void WriteHWMemInt8(memptr addr, uint8 b) {do_put_mem_byte((uae_u8 *)phys_get_real_address(addr), b);}
|
||||
|
||||
// Indirect access to CPU address space
|
||||
// Uses MMU if available
|
||||
// For SW operations
|
||||
// Only data space
|
||||
// Read/WriteIntXX
|
||||
//
|
||||
static inline uint64 ReadInt64(memptr addr) {return get_quad(addr);}
|
||||
static inline uint32 ReadInt32(memptr addr) {return get_long(addr);}
|
||||
static inline uint16 ReadInt16(memptr addr) {return get_word(addr);}
|
||||
static inline uint8 ReadInt8(memptr addr) {return get_byte(addr);}
|
||||
static inline void WriteInt64(memptr addr, uint64 q) {put_quad(addr, q);}
|
||||
static inline void WriteInt32(memptr addr, uint32 l) {put_long(addr, l);}
|
||||
static inline void WriteInt16(memptr addr, uint16 w) {put_word(addr, w);}
|
||||
static inline void WriteInt8(memptr addr, uint8 b) {put_byte(addr, b);}
|
||||
|
||||
#ifdef EXTENDED_SIGSEGV
|
||||
extern int in_handler;
|
||||
#ifdef NO_NESTED_SIGSEGV
|
||||
extern JMP_BUF sigsegv_env;
|
||||
# define BUS_ERROR(a) \
|
||||
{ \
|
||||
regs.mmu_fault_addr=(a); \
|
||||
if (in_handler) \
|
||||
{ \
|
||||
in_handler = 0; \
|
||||
LONGJMP(sigsegv_env, 1); \
|
||||
} \
|
||||
else { \
|
||||
breakpt(); \
|
||||
THROW(2); \
|
||||
} \
|
||||
}
|
||||
#else /* NO_NESTED_SIGSEGV */
|
||||
# define BUS_ERROR(a) \
|
||||
{ \
|
||||
regs.mmu_fault_addr=(a); \
|
||||
in_handler = 0; \
|
||||
breakpt(); \
|
||||
THROW(2); \
|
||||
}
|
||||
#endif /* NO_NESTED_SIGSEGV */
|
||||
#else /* EXTENDED_SIGSEGV */
|
||||
# define BUS_ERROR(a) \
|
||||
{ \
|
||||
regs.mmu_fault_addr=(a); \
|
||||
breakpt(); \
|
||||
THROW(2); \
|
||||
}
|
||||
#endif /* EXTENDED_SIGSEGV */
|
||||
|
||||
// For address validation
|
||||
static inline bool ValidAtariAddr(memptr addr, bool write, uint32 len) { return phys_valid_address(addr, write, len); }
|
||||
static inline bool ValidAddr(memptr addr, bool write, uint32 len) { return valid_address(addr, write, len); }
|
||||
|
||||
// Helper functions for usual memory operations
|
||||
static inline uint8 *Atari2HostAddr(memptr addr) {return phys_get_real_address(addr);}
|
||||
#endif
|
||||
// Possible frame buffer layouts
|
||||
enum {
|
||||
FLAYOUT_NONE, // No frame buffer
|
||||
|
@ -73,30 +191,73 @@ static inline void *Host2Mac_memcpy(uint32 dest, const void *src, size_t n) {ret
|
|||
static inline void *Mac2Mac_memcpy(uint32 dest, uint32 src, size_t n) {return memcpy(Mac2HostAddr(dest), Mac2HostAddr(src), n);}
|
||||
|
||||
|
||||
// From newcpu.cpp
|
||||
extern int quit_program;
|
||||
extern int exit_val;
|
||||
|
||||
/*
|
||||
* 680x0 emulation
|
||||
*/
|
||||
|
||||
// Initialization
|
||||
extern bool Init680x0(void); // This routine may want to look at CPUType/FPUType to set up the apropriate emulation
|
||||
#if 0
|
||||
extern bool InitMEM();
|
||||
#endif
|
||||
extern bool Init680x0(void);
|
||||
#if 0
|
||||
extern void Reset680x0(void);
|
||||
#endif
|
||||
extern void Exit680x0(void);
|
||||
extern void InitFrameBufferMapping(void);
|
||||
|
||||
// 680x0 dynamic recompilation activation flag
|
||||
#if USE_JIT
|
||||
extern bool UseJIT;
|
||||
#else
|
||||
const bool UseJIT = false;
|
||||
#if 0
|
||||
extern void AtariReset(void);
|
||||
#endif
|
||||
|
||||
// 680x0 emulation functions
|
||||
struct M68kRegisters;
|
||||
extern void Start680x0(void); // Reset and start 680x0
|
||||
extern void Start680x0(void); // Reset and start 680x0
|
||||
#if 0
|
||||
extern void Restart680x0(void); // Restart running 680x0
|
||||
extern void Quit680x0(void); // Quit 680x0
|
||||
#endif
|
||||
|
||||
extern "C" void Execute68k(uint32 addr, M68kRegisters *r); // Execute 68k code from EMUL_OP routine
|
||||
extern "C" void Execute68kTrap(uint16 trap, M68kRegisters *r); // Execute MacOS 68k trap from EMUL_OP routine
|
||||
|
||||
// Interrupt functions
|
||||
extern void TriggerInterrupt(void); // Trigger interrupt level 1 (InterruptFlag must be set first)
|
||||
extern void TriggerNMI(void); // Trigger interrupt level 7
|
||||
#if 0
|
||||
extern int MFPdoInterrupt(void);
|
||||
extern int SCCdoInterrupt(void);
|
||||
extern void TriggerInternalIRQ(void);
|
||||
extern void TriggerInt3(void); // Trigger interrupt level 3
|
||||
extern void TriggerVBL(void); // Trigger interrupt level 4
|
||||
extern void TriggerInt5(void); // Trigger interrupt level 5
|
||||
extern void TriggerSCC(bool); // Trigger interrupt level 5
|
||||
extern void TriggerMFP(bool); // Trigger interrupt level 6
|
||||
#endif
|
||||
extern void TriggerInterrupt(void); // Trigger interrupt level 1 (InterruptFlag must be set first)
|
||||
extern void TriggerNMI(void); // Trigger interrupt level 7
|
||||
|
||||
#if 0
|
||||
#ifdef FLIGHT_RECORDER
|
||||
extern void cpu_flight_recorder(int);
|
||||
extern void dump_flight_recorder(void);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// CPU looping handlers
|
||||
void check_eps_limit(uaecptr);
|
||||
void report_double_bus_error(void);
|
||||
|
||||
#if 0
|
||||
// This function will be removed
|
||||
static inline uaecptr showPC(void) { return m68k_getpc(); } // for debugging only
|
||||
#endif
|
||||
|
||||
extern int intlev(void);
|
||||
static inline void AtariReset(void) {}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
vim:ts=4:sw=4:
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
/*
|
||||
* cpudefs.cpp must be compiled twice, once for the generator program
|
||||
* and once for the actual executable
|
||||
*/
|
||||
#include "cpudefs.cpp"
|
|
@ -0,0 +1,2 @@
|
|||
#define PART_1
|
||||
#include "cpuemu.cpp"
|
|
@ -0,0 +1,3 @@
|
|||
#define NOFLAGS 1
|
||||
#define PART_1
|
||||
#include "cpuemu.cpp"
|
|
@ -0,0 +1,2 @@
|
|||
#define PART_2
|
||||
#include "cpuemu.cpp"
|
|
@ -0,0 +1,3 @@
|
|||
#define NOFLAGS 1
|
||||
#define PART_2
|
||||
#include "cpuemu.cpp"
|
|
@ -0,0 +1,2 @@
|
|||
#define PART_3
|
||||
#include "cpuemu.cpp"
|
|
@ -0,0 +1,3 @@
|
|||
#define NOFLAGS 1
|
||||
#define PART_3
|
||||
#include "cpuemu.cpp"
|
|
@ -0,0 +1,2 @@
|
|||
#define PART_4
|
||||
#include "cpuemu.cpp"
|
|
@ -0,0 +1,3 @@
|
|||
#define NOFLAGS 1
|
||||
#define PART_4
|
||||
#include "cpuemu.cpp"
|
|
@ -0,0 +1,2 @@
|
|||
#define PART_5
|
||||
#include "cpuemu.cpp"
|
|
@ -0,0 +1,4 @@
|
|||
#define NOFLAGS 1
|
||||
#define PART_5
|
||||
#include "cpuemu.cpp"
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
#define PART_6
|
||||
#include "cpuemu.cpp"
|
|
@ -0,0 +1,3 @@
|
|||
#define NOFLAGS 1
|
||||
#define PART_6
|
||||
#include "cpuemu.cpp"
|
|
@ -0,0 +1,2 @@
|
|||
#define PART_7
|
||||
#include "cpuemu.cpp"
|
|
@ -0,0 +1,3 @@
|
|||
#define NOFLAGS 1
|
||||
#define PART_7
|
||||
#include "cpuemu.cpp"
|
|
@ -0,0 +1,2 @@
|
|||
#define PART_8
|
||||
#include "cpuemu.cpp"
|
|
@ -0,0 +1,3 @@
|
|||
#define NOFLAGS 1
|
||||
#define PART_8
|
||||
#include "cpuemu.cpp"
|
|
@ -0,0 +1,5 @@
|
|||
/*
|
||||
* cpufunctbl.cpp must be compiled twice, once for the generator program
|
||||
* and once for the actual executable
|
||||
*/
|
||||
#include "cpufunctbl.cpp"
|
File diff suppressed because it is too large
Load Diff
|
@ -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:
|
||||
*/
|
|
@ -0,0 +1,2 @@
|
|||
#define NOFLAGS 1
|
||||
#include "cpustbl.cpp"
|
|
@ -0,0 +1,5 @@
|
|||
/*
|
||||
* cpustbl.cpp must be compiled twice, once for the generator program
|
||||
* and once for the actual executable
|
||||
*/
|
||||
#include "cpustbl.cpp"
|
|
@ -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:
|
||||
*/
|
|
@ -1,28 +1,33 @@
|
|||
/*
|
||||
* fpu/core.h - base fpu context definition
|
||||
* fpu/core.h - base fpu context definition
|
||||
*
|
||||
* Basilisk II (C) 1997-2008 Christian Bauer
|
||||
* Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
|
||||
*
|
||||
* Inspired by Christian Bauer's Basilisk II
|
||||
*
|
||||
* MC68881/68040 fpu emulation
|
||||
*
|
||||
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||
* Rewrite for x86, copyright 1999-2000 Lauri Pesonen
|
||||
* New framework, copyright 2000 Gwenole Beauchesne
|
||||
* Adapted for JIT compilation (c) Bernd Meyer, 2000
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
* This file is part of the ARAnyM project which builds a new and powerful
|
||||
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
* MC68881/68040 fpu emulation
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
|
||||
* New framework, copyright 2000-2001 Gwenole Beauchesne
|
||||
* Adapted for JIT compilation (c) Bernd Meyer, 2000-2001
|
||||
*
|
||||
* ARAnyM is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ARAnyM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ARAnyM; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef FPU_CORE_H
|
||||
|
@ -34,11 +39,15 @@
|
|||
/* Always use x87 FPU stack on IA-32. */
|
||||
#if defined(X86_ASSEMBLY)
|
||||
#define USE_X87_ASSEMBLY 1
|
||||
#ifndef USE_JIT_FPU
|
||||
#define ACCURATE_SIN_COS_TAN 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Only use x87 FPU on x86-64 if long double precision is requested. */
|
||||
#if defined(X86_64_ASSEMBLY) && USE_LONG_DOUBLE
|
||||
#if defined(X86_64_ASSEMBLY) && defined(USE_LONG_DOUBLE)
|
||||
#define USE_X87_ASSEMBLY 1
|
||||
#define ACCURATE_SIN_COS_TAN 1
|
||||
#endif
|
||||
|
||||
/* ========================================================================== */
|
||||
|
@ -65,10 +74,7 @@ struct fpu_t {
|
|||
/* --- Floating-Point Control Register --- */
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
struct {
|
||||
|
||||
/* Exception Enable Byte */
|
||||
uae_u32 exception_enable;
|
||||
#define FPCR_EXCEPTION_ENABLE 0x0000ff00
|
||||
#define FPCR_EXCEPTION_BSUN 0x00008000
|
||||
#define FPCR_EXCEPTION_SNAN 0x00004000
|
||||
|
@ -83,21 +89,19 @@ struct fpu_t {
|
|||
#define FPCR_MODE_CONTROL 0x000000ff
|
||||
|
||||
/* Rounding precision */
|
||||
uae_u32 rounding_precision;
|
||||
#define FPCR_ROUNDING_PRECISION 0x000000c0
|
||||
#define FPCR_PRECISION_SINGLE 0x00000040
|
||||
#define FPCR_PRECISION_DOUBLE 0x00000080
|
||||
#define FPCR_PRECISION_EXTENDED 0x00000000
|
||||
|
||||
/* Rounding mode */
|
||||
uae_u32 rounding_mode;
|
||||
#define FPCR_ROUNDING_MODE 0x00000030
|
||||
#define FPCR_ROUND_NEAR 0x00000000
|
||||
#define FPCR_ROUND_ZERO 0x00000010
|
||||
#define FPCR_ROUND_MINF 0x00000020
|
||||
#define FPCR_ROUND_PINF 0x00000030
|
||||
|
||||
} fpcr;
|
||||
uae_u32 fpcr;
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
/* --- Floating-Point Status Register --- */
|
||||
|
@ -107,7 +111,7 @@ struct fpu_t {
|
|||
|
||||
/* Floating-Point Condition Code Byte */
|
||||
uae_u32 condition_codes;
|
||||
#define FPSR_CCB 0xff000000
|
||||
#define FPSR_CCB 0x0f000000
|
||||
#define FPSR_CCB_NEGATIVE 0x08000000
|
||||
#define FPSR_CCB_ZERO 0x04000000
|
||||
#define FPSR_CCB_INFINITY 0x02000000
|
||||
|
@ -133,7 +137,7 @@ struct fpu_t {
|
|||
|
||||
/* Accrued Exception Byte */
|
||||
uae_u32 accrued_exception;
|
||||
#define FPSR_ACCRUED_EXCEPTION 0x000000ff
|
||||
#define FPSR_ACCRUED_EXCEPTION 0x000000f8
|
||||
#define FPSR_ACCR_IOP 0x00000080
|
||||
#define FPSR_ACCR_OVFL 0x00000040
|
||||
#define FPSR_ACCR_UNFL 0x00000020
|
||||
|
@ -219,7 +223,7 @@ struct fpu_t {
|
|||
extern fpu_t fpu;
|
||||
|
||||
/* Return the address of a particular register */
|
||||
inline fpu_register * const fpu_register_address(int i)
|
||||
inline fpu_register * fpu_register_address(int i)
|
||||
{ return &fpu.registers[i]; }
|
||||
|
||||
/* Dump functions for m68k_dumpstate */
|
||||
|
@ -227,16 +231,16 @@ extern void fpu_dump_registers(void);
|
|||
extern void fpu_dump_flags(void);
|
||||
|
||||
/* Accessors to FPU Control Register */
|
||||
static inline uae_u32 get_fpcr(void);
|
||||
static inline void set_fpcr(uae_u32 new_fpcr);
|
||||
//static inline uae_u32 get_fpcr(void);
|
||||
//static inline void set_fpcr(uae_u32 new_fpcr);
|
||||
|
||||
/* Accessors to FPU Status Register */
|
||||
static inline uae_u32 get_fpsr(void);
|
||||
static inline void set_fpsr(uae_u32 new_fpsr);
|
||||
//static inline uae_u32 get_fpsr(void);
|
||||
//static inline void set_fpsr(uae_u32 new_fpsr);
|
||||
|
||||
/* Accessors to FPU Instruction Address Register */
|
||||
static inline uae_u32 get_fpiar();
|
||||
static inline void set_fpiar(uae_u32 new_fpiar);
|
||||
//static inline uae_u32 get_fpiar();
|
||||
//static inline void set_fpiar(uae_u32 new_fpiar);
|
||||
|
||||
/* Initialization / Finalization */
|
||||
extern void fpu_init(bool integral_68040);
|
||||
|
@ -254,6 +258,6 @@ void fpuop_scc(uae_u32 opcode, uae_u32 extra) REGPARAM;
|
|||
/* Floating-point system control operations */
|
||||
void fpuop_save(uae_u32 opcode) REGPARAM;
|
||||
void fpuop_restore(uae_u32 opcode) REGPARAM;
|
||||
void fpuop_trapcc(uae_u32 opcode, uaecptr oldpc) REGPARAM;
|
||||
void fpuop_trapcc(uae_u32 opcode, uaecptr oldpc, uae_u32 extra) REGPARAM;
|
||||
|
||||
#endif /* FPU_CORE_H */
|
||||
|
|
|
@ -1,28 +1,33 @@
|
|||
/*
|
||||
* fpu/exceptions.cpp - system-dependant FPU exceptions management
|
||||
* fpu/exceptions.cpp - system-dependant FPU exceptions management
|
||||
*
|
||||
* Basilisk II (C) 1997-2008 Christian Bauer
|
||||
* Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
|
||||
*
|
||||
* Inspired by Christian Bauer's Basilisk II
|
||||
*
|
||||
* MC68881/68040 fpu emulation
|
||||
*
|
||||
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||
* Rewrite for x86, copyright 1999-2000 Lauri Pesonen
|
||||
* New framework, copyright 2000 Gwenole Beauchesne
|
||||
* Adapted for JIT compilation (c) Bernd Meyer, 2000
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
* This file is part of the ARAnyM project which builds a new and powerful
|
||||
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
* MC68881/68040 fpu emulation
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
|
||||
* New framework, copyright 2000-2001 Gwenole Beauchesne
|
||||
* Adapted for JIT compilation (c) Bernd Meyer, 2000-2001
|
||||
*
|
||||
* ARAnyM is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ARAnyM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ARAnyM; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#undef PRIVATE
|
||||
|
|
|
@ -1,28 +1,33 @@
|
|||
/*
|
||||
* fpu/exceptions.h - system-dependant FPU exceptions management
|
||||
* fpu/exceptions.h - system-dependant FPU exceptions management
|
||||
*
|
||||
* Basilisk II (C) 1997-2008 Christian Bauer
|
||||
* Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
|
||||
*
|
||||
* Inspired by Christian Bauer's Basilisk II
|
||||
*
|
||||
* MC68881/68040 fpu emulation
|
||||
*
|
||||
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||
* Rewrite for x86, copyright 1999-2000 Lauri Pesonen
|
||||
* New framework, copyright 2000 Gwenole Beauchesne
|
||||
* Adapted for JIT compilation (c) Bernd Meyer, 2000
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
* This file is part of the ARAnyM project which builds a new and powerful
|
||||
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
* MC68881/68040 fpu emulation
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
|
||||
* New framework, copyright 2000-2001 Gwenole Beauchesne
|
||||
* Adapted for JIT compilation (c) Bernd Meyer, 2000-2001
|
||||
*
|
||||
* ARAnyM is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ARAnyM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ARAnyM; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef FPU_EXCEPTIONS_H
|
||||
|
|
|
@ -1,28 +1,33 @@
|
|||
/*
|
||||
* fpu/flags.cpp - Floating-point flags
|
||||
* fpu/flags.cpp - Floating-point flags
|
||||
*
|
||||
* Basilisk II (C) 1997-2008 Christian Bauer
|
||||
* Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
|
||||
*
|
||||
* Inspired by Christian Bauer's Basilisk II
|
||||
*
|
||||
* MC68881/68040 fpu emulation
|
||||
*
|
||||
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||
* Rewrite for x86, copyright 1999-2000 Lauri Pesonen
|
||||
* New framework, copyright 2000 Gwenole Beauchesne
|
||||
* Adapted for JIT compilation (c) Bernd Meyer, 2000
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
* This file is part of the ARAnyM project which builds a new and powerful
|
||||
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
* MC68881/68040 fpu emulation
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
|
||||
* New framework, copyright 2000-2001 Gwenole Beauchesne
|
||||
* Adapted for JIT compilation (c) Bernd Meyer, 2000-2001
|
||||
*
|
||||
* ARAnyM is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ARAnyM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ARAnyM; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* NOTE: this file shall be included only from fpu/fpu_*.cpp */
|
||||
|
|
|
@ -1,28 +1,33 @@
|
|||
/*
|
||||
* fpu/flags.h - Floating-point flags
|
||||
* fpu/flags.h - Floating-point flags
|
||||
*
|
||||
* Basilisk II (C) 1997-2008 Christian Bauer
|
||||
* Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
|
||||
*
|
||||
* Inspired by Christian Bauer's Basilisk II
|
||||
*
|
||||
* MC68881/68040 fpu emulation
|
||||
*
|
||||
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||
* Rewrite for x86, copyright 1999-2000 Lauri Pesonen
|
||||
* New framework, copyright 2000 Gwenole Beauchesne
|
||||
* Adapted for JIT compilation (c) Bernd Meyer, 2000
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
* This file is part of the ARAnyM project which builds a new and powerful
|
||||
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
* MC68881/68040 fpu emulation
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
|
||||
* New framework, copyright 2000-2001 Gwenole Beauchesne
|
||||
* Adapted for JIT compilation (c) Bernd Meyer, 2000-2001
|
||||
*
|
||||
* ARAnyM is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ARAnyM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ARAnyM; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef FPU_FLAGS_H
|
||||
|
@ -112,7 +117,7 @@ PRIVATE inline void FFPU set_fpccr(uae_u32 new_fpcond)
|
|||
|
||||
/* Make FPSR according to the value passed in argument */
|
||||
PRIVATE inline void FFPU make_fpsr(fpu_register const & r)
|
||||
{ uae_u16 sw; __asm__ __volatile__ ("fxam\n\tfnstsw %0" : "=r" (sw) : "f" (r)); FPU fpsr.condition_codes = sw; }
|
||||
{ uae_u16 sw; __asm__ __volatile__ ("fxam\n\tfnstsw %0" : "=a" (sw) : "f" (r)); FPU fpsr.condition_codes = sw; }
|
||||
|
||||
/* Return the corresponding ID of the current floating-point condition codes */
|
||||
/* NOTE: only valid for evaluation of a condition */
|
||||
|
@ -181,27 +186,27 @@ PRIVATE inline uae_u32 FFPU get_fpccr(void)
|
|||
uae_u32 fpccr = 0;
|
||||
if (isnan(FPU result))
|
||||
fpccr |= FPSR_CCB_NAN;
|
||||
else if (FPU result == 0.0)
|
||||
fpccr |= FPSR_CCB_ZERO;
|
||||
else if (FPU result < 0.0)
|
||||
fpccr |= FPSR_CCB_NEGATIVE;
|
||||
if (isinf(FPU result))
|
||||
else if (isinf(FPU result))
|
||||
fpccr |= FPSR_CCB_INFINITY;
|
||||
else if (iszero(FPU result))
|
||||
fpccr |= FPSR_CCB_ZERO;
|
||||
if (isneg(FPU result))
|
||||
fpccr |= FPSR_CCB_NEGATIVE;
|
||||
return fpccr;
|
||||
}
|
||||
|
||||
/* M68k to native floating-point condition codes - SELF */
|
||||
PRIVATE inline void FFPU set_fpccr(uae_u32 new_fpcond)
|
||||
{
|
||||
bool negative = (new_fpcond & FPSR_CCB_NEGATIVE) != 0;
|
||||
if (new_fpcond & FPSR_CCB_NAN)
|
||||
make_nan(FPU result);
|
||||
make_nan(FPU result, negative);
|
||||
else if (new_fpcond & FPSR_CCB_INFINITY)
|
||||
make_inf(FPU result, negative);
|
||||
else if (new_fpcond & FPSR_CCB_ZERO)
|
||||
FPU result = 0.0;
|
||||
else if (new_fpcond & FPSR_CCB_NEGATIVE)
|
||||
FPU result = -1.0;
|
||||
make_zero(FPU result, negative);
|
||||
else
|
||||
FPU result = +1.0;
|
||||
/* gb-- where is Infinity ? */
|
||||
FPU result = negative ? -1.0 : +1.0;
|
||||
}
|
||||
|
||||
/* Make FPSR according to the value passed in argument */
|
||||
|
@ -217,7 +222,7 @@ PRIVATE inline void FFPU make_fpsr(fpu_register const & r)
|
|||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
/* Return the address of the floating-point condition codes register */
|
||||
static inline uae_u32 * const FFPU address_of_fpccr(void)
|
||||
static inline uae_u32 * FFPU address_of_fpccr(void)
|
||||
{ return ((uae_u32 *)& FPU fpsr.condition_codes); }
|
||||
|
||||
#endif /* FPU_FLAGS_H */
|
||||
|
|
|
@ -1,28 +1,33 @@
|
|||
/*
|
||||
* fpu/fpu.h - public header
|
||||
* fpu/fpu.h - public header
|
||||
*
|
||||
* Basilisk II (C) 1997-2008 Christian Bauer
|
||||
* Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
|
||||
*
|
||||
* Inspired by Christian Bauer's Basilisk II
|
||||
*
|
||||
* MC68881/68040 fpu emulation
|
||||
*
|
||||
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||
* Rewrite for x86, copyright 1999-2000 Lauri Pesonen
|
||||
* New framework, copyright 2000 Gwenole Beauchesne
|
||||
* Adapted for JIT compilation (c) Bernd Meyer, 2000
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
* This file is part of the ARAnyM project which builds a new and powerful
|
||||
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
* MC68881/68040 fpu emulation
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
|
||||
* New framework, copyright 2000-2001 Gwenole Beauchesne
|
||||
* Adapted for JIT compilation (c) Bernd Meyer, 2000-2001
|
||||
*
|
||||
* ARAnyM is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ARAnyM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ARAnyM; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef FPU_PUBLIC_HEADER_H
|
||||
|
@ -46,4 +51,9 @@
|
|||
#include "fpu/types.h"
|
||||
#include "fpu/core.h"
|
||||
|
||||
void fpu_set_fpsr(uae_u32 new_fpsr);
|
||||
uae_u32 fpu_get_fpsr(void);
|
||||
void fpu_set_fpcr(uae_u32 new_fpcr);
|
||||
uae_u32 fpu_get_fpcr(void);
|
||||
|
||||
#endif /* FPU_PUBLIC_HEADER_H */
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,28 +1,33 @@
|
|||
/*
|
||||
* fpu/fpu_uae.h - Extra Definitions for the old UAE FPU core
|
||||
* fpu/fpu_ieee.h - Extra Definitions for the IEEE FPU core
|
||||
*
|
||||
* Basilisk II (C) 1997-2008 Christian Bauer
|
||||
* Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
|
||||
*
|
||||
* Inspired by Christian Bauer's Basilisk II
|
||||
*
|
||||
* MC68881/68040 fpu emulation
|
||||
*
|
||||
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||
* Rewrite for x86, copyright 1999-2000 Lauri Pesonen
|
||||
* New framework, copyright 2000 Gwenole Beauchesne
|
||||
* Adapted for JIT compilation (c) Bernd Meyer, 2000
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
* This file is part of the ARAnyM project which builds a new and powerful
|
||||
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
* MC68881/68040 fpu emulation
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
|
||||
* New framework, copyright 2000-2001 Gwenole Beauchesne
|
||||
* Adapted for JIT compilation (c) Bernd Meyer, 2000-2001
|
||||
*
|
||||
* ARAnyM is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ARAnyM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ARAnyM; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef FPU_IEEE_H
|
||||
|
@ -54,13 +59,11 @@ PRIVATE double_flags fl_dest;
|
|||
PRIVATE inline void FFPU get_dest_flags(fpu_register const & r);
|
||||
PRIVATE inline void FFPU get_source_flags(fpu_register const & r);
|
||||
|
||||
PRIVATE inline void FFPU make_nan(fpu_register & r);
|
||||
PRIVATE inline void FFPU make_zero_positive(fpu_register & r);
|
||||
PRIVATE inline void FFPU make_zero_negative(fpu_register & r);
|
||||
PRIVATE inline void FFPU make_inf_positive(fpu_register & r);
|
||||
PRIVATE inline void FFPU make_inf_negative(fpu_register & r);
|
||||
PRIVATE inline void FFPU make_nan(fpu_register & r, bool negative);
|
||||
PRIVATE inline void FFPU make_zero(fpu_register & r, bool negative);
|
||||
PRIVATE inline void FFPU make_inf(fpu_register & r, bool negative);
|
||||
|
||||
PRIVATE inline void FFPU fast_scale(fpu_register & r, int add);
|
||||
// MJ PRIVATE inline void FFPU fast_scale(fpu_register & r, int add);
|
||||
PRIVATE inline fpu_register FFPU fast_fgetexp(fpu_register const & r);
|
||||
|
||||
// May be optimized for particular processors
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,31 +1,42 @@
|
|||
/*
|
||||
* fpu/fpu_uae.cpp
|
||||
* fpu/fpu_uae.cpp - the old UAE FPU
|
||||
*
|
||||
* Basilisk II (C) 1997-2008 Christian Bauer
|
||||
* Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
|
||||
*
|
||||
* Inspired by Christian Bauer's Basilisk II
|
||||
*
|
||||
* MC68881/68040 fpu emulation
|
||||
* This file is part of the ARAnyM project which builds a new and powerful
|
||||
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
|
||||
*
|
||||
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||
* Rewrite for x86, copyright 1999-2000 Lauri Pesonen
|
||||
* New framework, copyright 2000 Gwenole Beauchesne
|
||||
* Adapted for JIT compilation (c) Bernd Meyer, 2000
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
* MC68881/68040 fpu emulation
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
|
||||
* New framework, copyright 2000-2001 Gwenole Beauchesne
|
||||
* Adapted for JIT compilation (c) Bernd Meyer, 2000-2001
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* ARAnyM is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ARAnyM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ARAnyM; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* UAE - The Un*x Amiga Emulator
|
||||
*
|
||||
* MC68881 emulation
|
||||
*
|
||||
* Copyright 1996 Herman ten Brugge
|
||||
*
|
||||
*
|
||||
* Following fixes by Lauri Pesonen, July 1999:
|
||||
*
|
||||
* FMOVEM list handling:
|
||||
|
@ -86,9 +97,8 @@
|
|||
* - Precision rounding single/double
|
||||
*/
|
||||
|
||||
|
||||
#include "sysdeps.h"
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include "memory.h"
|
||||
#include "readcpu.h"
|
||||
#include "newcpu.h"
|
||||
|
@ -97,6 +107,17 @@
|
|||
#include "fpu/fpu.h"
|
||||
#include "fpu/fpu_uae.h"
|
||||
|
||||
#ifdef HAVE_NEW_HEADERS
|
||||
#define _GLIBCPP_USE_C99 1
|
||||
# include <cmath>
|
||||
# include <cstdio>
|
||||
using namespace __gnu_cxx;
|
||||
#undef _GLIBCPP_USE_C99
|
||||
#else
|
||||
# include <math.h>
|
||||
# include <stdio.h>
|
||||
#endif
|
||||
|
||||
/* Global FPU context */
|
||||
fpu_t fpu;
|
||||
|
||||
|
@ -166,8 +187,8 @@ PUBLIC void FFPU dump_registers(const char * str)
|
|||
|
||||
sprintf(temp_str, "%s: %.04f, %.04f, %.04f, %.04f, %.04f, %.04f, %.04f, %.04f\n",
|
||||
str,
|
||||
get_register(0), get_register(1), get_register(2), get_register(3),
|
||||
get_register(4), get_register(5), get_register(6), get_register(7) );
|
||||
fpu_get_register(0), fpu_get_register(1), fpu_get_register(2), fpu_get_register(3),
|
||||
fpu_get_register(4), fpu_get_register(5), fpu_get_register(6), fpu_get_register(7) );
|
||||
|
||||
fpu_debug((temp_str));
|
||||
}
|
||||
|
@ -195,9 +216,7 @@ PUBLIC void FFPU dump_registers(const char *)
|
|||
{
|
||||
}
|
||||
|
||||
PUBLIC void FFPU dump_first_bytes(uae_u8 *, uae_s32)
|
||||
{
|
||||
}
|
||||
#define dump_first_bytes(a,b)
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -219,10 +238,10 @@ PRIVATE inline fpu_register FFPU round_to_nearest(fpu_register const & x)
|
|||
|
||||
PRIVATE inline bool FFPU do_isnan(fpu_register const & r)
|
||||
{
|
||||
uae_u32 * p = (uae_u32 *)&r;
|
||||
if ((p[FHI] & 0x7FF00000) == 0x7FF00000) {
|
||||
fpu_register_parts const p = { r };
|
||||
if ((p.parts[FHI] & 0x7FF00000) == 0x7FF00000) {
|
||||
// logical or is faster here.
|
||||
if ((p[FHI] & 0x000FFFFF) || p[FLO]) {
|
||||
if ((p.parts[FHI] & 0x000FFFFF) || p.parts[FLO]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -235,8 +254,8 @@ PRIVATE inline bool FFPU do_isnan(fpu_register const & r)
|
|||
|
||||
PRIVATE inline bool FFPU do_isinf(fpu_register const & r)
|
||||
{
|
||||
uae_u32 * p = (uae_u32 *)&r;
|
||||
if (((p[FHI] & 0x7FF00000) == 0x7FF00000) && p[FLO] == 0) {
|
||||
fpu_register_parts const p = { r };
|
||||
if ((p.parts[FHI] & 0x7FF00000) == 0x7FF00000 && p.parts[FLO] == 0) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -248,8 +267,8 @@ PRIVATE inline bool FFPU do_isinf(fpu_register const & r)
|
|||
|
||||
PRIVATE inline bool FFPU do_isneg(fpu_register const & r)
|
||||
{
|
||||
uae_u32 * p = (uae_u32 *)&r;
|
||||
return ((p[FHI] & 0x80000000) != 0);
|
||||
fpu_register_parts const p = { r };
|
||||
return ((p.parts[FHI] & 0x80000000) != 0);
|
||||
}
|
||||
|
||||
#ifndef HAVE_ISZERO
|
||||
|
@ -258,8 +277,8 @@ PRIVATE inline bool FFPU do_isneg(fpu_register const & r)
|
|||
|
||||
PRIVATE inline bool FFPU do_iszero(fpu_register const & r)
|
||||
{
|
||||
uae_u32 * p = (uae_u32 *)&r;
|
||||
return (((p[FHI] & 0x7FF00000) == 0) && p[FLO] == 0);
|
||||
fpu_register_parts const p = { r };
|
||||
return (((p.parts[FHI] & 0x7FF00000) == 0) && p.parts[FLO] == 0);
|
||||
}
|
||||
|
||||
// May be optimized for particular processors
|
||||
|
@ -293,77 +312,70 @@ PRIVATE inline void FFPU get_source_flags(fpu_register const & r)
|
|||
fl_source.in_range = !fl_source.zero && !fl_source.infinity && !fl_source.nan;
|
||||
}
|
||||
|
||||
PRIVATE inline void FFPU make_nan(fpu_register & r)
|
||||
PRIVATE inline void FFPU make_nan(fpu_register & r, bool negative)
|
||||
{
|
||||
uae_u32 * const p = (uae_u32 *)&r;
|
||||
p[FLO] = 0xffffffff;
|
||||
p[FHI] = 0x7fffffff;
|
||||
fpu_register_parts p;
|
||||
p.parts[FLO] = 0xffffffff;
|
||||
p.parts[FHI] = negative ? 0xffffffff : 0x7fffffff;
|
||||
r = p.val;
|
||||
}
|
||||
|
||||
PRIVATE inline void FFPU make_zero_positive(fpu_register & r)
|
||||
PRIVATE inline void FFPU make_zero(fpu_register & r, bool negative)
|
||||
{
|
||||
uae_u32 * const p = (uae_u32 *)&r;
|
||||
p[FLO] = p[FHI] = 0;
|
||||
fpu_register_parts p;
|
||||
p.parts[FLO] = 0;
|
||||
p.parts[FHI] = negative ? 0x80000000 : 0;
|
||||
r = p.val;
|
||||
}
|
||||
|
||||
PRIVATE inline void FFPU make_zero_negative(fpu_register & r)
|
||||
PRIVATE inline void FFPU make_inf(fpu_register & r, bool negative)
|
||||
{
|
||||
uae_u32 * const p = (uae_u32 *)&r;
|
||||
p[FLO] = 0;
|
||||
p[FHI] = 0x80000000;
|
||||
}
|
||||
|
||||
PRIVATE inline void FFPU make_inf_positive(fpu_register & r)
|
||||
{
|
||||
uae_u32 * const p = (uae_u32 *)&r;
|
||||
p[FLO] = 0;
|
||||
p[FHI] = 0x7FF00000;
|
||||
}
|
||||
|
||||
PRIVATE inline void FFPU make_inf_negative(fpu_register & r)
|
||||
{
|
||||
uae_u32 * const p = (uae_u32 *)&r;
|
||||
p[FLO] = 0;
|
||||
p[FHI] = 0xFFF00000;
|
||||
fpu_register_parts p;
|
||||
p.parts[FLO] = 0;
|
||||
p.parts[FHI] = negative ? 0xFFF00000 : 0x7FF00000;
|
||||
r = p.val;
|
||||
}
|
||||
|
||||
PRIVATE inline void FFPU fast_scale(fpu_register & r, int add)
|
||||
{
|
||||
uae_u32 * const p = (uae_u32 *)&r;
|
||||
int exp = (p[FHI] & 0x7FF00000) >> 20;
|
||||
fpu_register_parts p = { r };
|
||||
int exp = (p.parts[FHI] & 0x7FF00000) >> 20;
|
||||
// TODO: overflow flags
|
||||
exp += add;
|
||||
if(exp >= 2047) {
|
||||
make_inf_positive(r);
|
||||
make_inf(r, false);
|
||||
return;
|
||||
} else if(exp < 0) {
|
||||
// keep sign (+/- 0)
|
||||
p[FHI] &= 0x80000000;
|
||||
p.parts[FHI] &= 0x80000000;
|
||||
} else {
|
||||
p[FHI] = (p[FHI] & 0x800FFFFF) | ((uae_u32)exp << 20);
|
||||
p.parts[FHI] = (p.parts[FHI] & 0x800FFFFF) | ((uae_u32)exp << 20);
|
||||
}
|
||||
r = p.val;
|
||||
}
|
||||
|
||||
PRIVATE inline fpu_register FFPU fast_fgetexp(fpu_register const & r)
|
||||
{
|
||||
uae_u32 * const p = (uae_u32 *)&r;
|
||||
int exp = (p[FHI] & 0x7FF00000) >> 20;
|
||||
fpu_register_parts const p = { r };
|
||||
int exp = (p.parts[FHI] & 0x7FF00000) >> 20;
|
||||
return( exp - 1023 );
|
||||
}
|
||||
|
||||
// Normalize to range 1..2
|
||||
PRIVATE inline void FFPU fast_remove_exponent(fpu_register & r)
|
||||
{
|
||||
uae_u32 * const p = (uae_u32 *)&r;
|
||||
p[FHI] = (p[FHI] & 0x800FFFFF) | 0x3FF00000;
|
||||
fpu_register_parts p = { r };
|
||||
p.parts[FHI] = (p.parts[FHI] & 0x800FFFFF) | 0x3FF00000;
|
||||
r = p.val;
|
||||
}
|
||||
|
||||
// The sign of the quotient is the exclusive-OR of the sign bits
|
||||
// of the source and destination operands.
|
||||
PRIVATE inline uae_u32 FFPU get_quotient_sign(fpu_register const & ra, fpu_register const & rb)
|
||||
{
|
||||
uae_u32 * const a = (uae_u32 *)&ra;
|
||||
uae_u32 * const b = (uae_u32 *)&rb;
|
||||
return (((a[FHI] ^ b[FHI]) & 0x80000000) ? FPSR_QUOTIENT_SIGN : 0);
|
||||
fpu_register_parts const a = { ra };
|
||||
fpu_register_parts const b = { rb };
|
||||
return (((a.parts[FHI] ^ b.parts[FHI]) & 0x80000000) ? FPSR_QUOTIENT_SIGN : 0);
|
||||
}
|
||||
|
||||
// Quotient Byte is loaded with the sign and least significant
|
||||
|
@ -381,13 +393,15 @@ PRIVATE inline fpu_register FFPU make_single(uae_u32 value)
|
|||
return (0.0);
|
||||
|
||||
fpu_register result;
|
||||
uae_u32 * p = (uae_u32 *)&result;
|
||||
fpu_register_parts p;
|
||||
|
||||
uae_u32 sign = (value & 0x80000000);
|
||||
uae_u32 exp = ((value & 0x7F800000) >> 23) + 1023 - 127;
|
||||
|
||||
p[FLO] = value << 29;
|
||||
p[FHI] = sign | (exp << 20) | ((value & 0x007FFFFF) >> 3);
|
||||
p.parts[FLO] = value << 29;
|
||||
p.parts[FHI] = sign | (exp << 20) | ((value & 0x007FFFFF) >> 3);
|
||||
|
||||
result = p.val;
|
||||
|
||||
fpu_debug(("make_single (%X) = %.04f\n",value,(double)result));
|
||||
|
||||
|
@ -401,10 +415,10 @@ PRIVATE inline uae_u32 FFPU extract_single(fpu_register const & src)
|
|||
return 0;
|
||||
|
||||
uae_u32 result;
|
||||
uae_u32 *p = (uae_u32 *)&src;
|
||||
fpu_register_parts const p = { src };
|
||||
|
||||
uae_u32 sign = (p[FHI] & 0x80000000);
|
||||
uae_u32 exp = (p[FHI] & 0x7FF00000) >> 20;
|
||||
uae_u32 sign = (p.parts[FHI] & 0x80000000);
|
||||
uae_u32 exp = (p.parts[FHI] & 0x7FF00000) >> 20;
|
||||
|
||||
if(exp + 127 < 1023) {
|
||||
exp = 0;
|
||||
|
@ -414,7 +428,7 @@ PRIVATE inline uae_u32 FFPU extract_single(fpu_register const & src)
|
|||
exp = exp + 127 - 1023;
|
||||
}
|
||||
|
||||
result = sign | (exp << 23) | ((p[FHI] & 0x000FFFFF) << 3) | (p[FLO] >> 29);
|
||||
result = sign | (exp << 23) | ((p.parts[FHI] & 0x000FFFFF) << 3) | (p.parts[FLO] >> 29);
|
||||
|
||||
fpu_debug(("extract_single (%.04f) = %X\n",(double)src,result));
|
||||
|
||||
|
@ -428,8 +442,8 @@ PRIVATE inline fpu_register FFPU make_extended(uae_u32 wrd1, uae_u32 wrd2, uae_u
|
|||
return 0.0;
|
||||
|
||||
fpu_register result;
|
||||
uae_u32 *p = (uae_u32 *)&result;
|
||||
|
||||
fpu_register_parts p;
|
||||
|
||||
uae_u32 sign = wrd1 & 0x80000000;
|
||||
uae_u32 exp = (wrd1 >> 16) & 0x7fff;
|
||||
|
||||
|
@ -466,8 +480,10 @@ PRIVATE inline fpu_register FFPU make_extended(uae_u32 wrd1, uae_u32 wrd2, uae_u
|
|||
}
|
||||
|
||||
// drop the explicit integer bit.
|
||||
p[FLO] = (wrd2 << 21) | (wrd3 >> 11);
|
||||
p[FHI] = sign | (exp << 20) | ((wrd2 & 0x7FFFFFFF) >> 11);
|
||||
p.parts[FLO] = (wrd2 << 21) | (wrd3 >> 11);
|
||||
p.parts[FHI] = sign | (exp << 20) | ((wrd2 & 0x7FFFFFFF) >> 11);
|
||||
|
||||
result = p.val;
|
||||
|
||||
fpu_debug(("make_extended (%X,%X,%X) = %.04f\n",wrd1,wrd2,wrd3,(double)result));
|
||||
|
||||
|
@ -485,14 +501,14 @@ PRIVATE inline void FFPU make_extended_no_normalize(
|
|||
{
|
||||
// Is it zero?
|
||||
if ((wrd1 & 0x7fff0000) == 0 && wrd2 == 0 && wrd3 == 0) {
|
||||
make_zero_positive(result);
|
||||
make_zero(result, false);
|
||||
return;
|
||||
}
|
||||
|
||||
// Is it NaN?
|
||||
if( (wrd1 & 0x7FFF0000) == 0x7FFF0000 ) {
|
||||
if( (wrd1 & 0x0000FFFF) || wrd2 || wrd3 ) {
|
||||
make_nan(result);
|
||||
make_nan(result, (wrd1 & 0x80000000) != 0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -511,11 +527,13 @@ PRIVATE inline void FFPU make_extended_no_normalize(
|
|||
}
|
||||
|
||||
// drop the explicit integer bit.
|
||||
uae_u32 *p = (uae_u32 *)&result;
|
||||
p[FLO] = (wrd2 << 21) | (wrd3 >> 11);
|
||||
p[FHI] = sign | (exp << 20) | ((wrd2 & 0x7FFFFFFF) >> 11);
|
||||
fpu_register_parts p;
|
||||
p.parts[FLO] = (wrd2 << 21) | (wrd3 >> 11);
|
||||
p.parts[FHI] = sign | (exp << 20) | ((wrd2 & 0x7FFFFFFF) >> 11);
|
||||
|
||||
fpu_debug(("make_extended (%X,%X,%X) = %.04f\n",wrd1,wrd2,wrd3,(float)(*(double *)p)));
|
||||
result = p.val;
|
||||
|
||||
fpu_debug(("make_extended (%X,%X,%X) = %.04f\n",wrd1,wrd2,wrd3,(double)result));
|
||||
}
|
||||
|
||||
// from_exten
|
||||
|
@ -527,14 +545,14 @@ PRIVATE inline void FFPU extract_extended(fpu_register const & src,
|
|||
*wrd1 = *wrd2 = *wrd3 = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
uae_u32 *p = (uae_u32 *)&src;
|
||||
|
||||
fpu_debug(("extract_extended (%X,%X)\n",p[FLO],p[FHI]));
|
||||
|
||||
uae_u32 sign = p[FHI] & 0x80000000;
|
||||
fpu_register_parts const p = { src };
|
||||
|
||||
fpu_debug(("extract_extended (%X,%X)\n",p.parts[FLO],p.parts[FHI]));
|
||||
|
||||
uae_u32 exp = ((p[FHI] >> 20) & 0x7ff);
|
||||
uae_u32 sign = p.parts[FHI] & 0x80000000;
|
||||
|
||||
uae_u32 exp = ((p.parts[FHI] >> 20) & 0x7ff);
|
||||
// Check for maximum
|
||||
if(exp == 0x7FF) {
|
||||
exp = 0x7FFF;
|
||||
|
@ -544,8 +562,8 @@ PRIVATE inline void FFPU extract_extended(fpu_register const & src,
|
|||
|
||||
*wrd1 = sign | (exp << 16);
|
||||
// always set the explicit integer bit.
|
||||
*wrd2 = 0x80000000 | ((p[FHI] & 0x000FFFFF) << 11) | ((p[FLO] & 0xFFE00000) >> 21);
|
||||
*wrd3 = p[FLO] << 11;
|
||||
*wrd2 = 0x80000000 | ((p.parts[FHI] & 0x000FFFFF) << 11) | ((p.parts[FLO] & 0xFFE00000) >> 21);
|
||||
*wrd3 = p.parts[FLO] << 11;
|
||||
|
||||
fpu_debug(("extract_extended (%.04f) = %X,%X,%X\n",(double)src,*wrd1,*wrd2,*wrd3));
|
||||
}
|
||||
|
@ -557,9 +575,11 @@ PRIVATE inline fpu_register FFPU make_double(uae_u32 wrd1, uae_u32 wrd2)
|
|||
return 0.0;
|
||||
|
||||
fpu_register result;
|
||||
uae_u32 *p = (uae_u32 *)&result;
|
||||
p[FLO] = wrd2;
|
||||
p[FHI] = wrd1;
|
||||
fpu_register_parts p;
|
||||
p.parts[FLO] = wrd2;
|
||||
p.parts[FHI] = wrd1;
|
||||
|
||||
result = p.val;
|
||||
|
||||
fpu_debug(("make_double (%X,%X) = %.04f\n",wrd1,wrd2,(double)result));
|
||||
|
||||
|
@ -577,9 +597,9 @@ PRIVATE inline void FFPU extract_double(fpu_register const & src,
|
|||
return;
|
||||
}
|
||||
*/
|
||||
uae_u32 *p = (uae_u32 *)&src;
|
||||
*wrd2 = p[FLO];
|
||||
*wrd1 = p[FHI];
|
||||
fpu_register_parts const p = { src };
|
||||
*wrd2 = p.parts[FLO];
|
||||
*wrd1 = p.parts[FHI];
|
||||
|
||||
fpu_debug(("extract_double (%.04f) = %X,%X\n",(double)src,*wrd1,*wrd2));
|
||||
}
|
||||
|
@ -590,8 +610,8 @@ PRIVATE inline void FFPU extract_double(fpu_register const & src,
|
|||
PRIVATE inline void FFPU make_fpsr(fpu_register const & r)
|
||||
{
|
||||
FPU fpsr.condition_codes
|
||||
= ((r == 0.0) ? NATIVE_FFLAG_ZERO : 0)
|
||||
| ((r < 0.0) ? NATIVE_FFLAG_NEGATIVE : 0)
|
||||
= (iszero(r) ? NATIVE_FFLAG_ZERO : 0)
|
||||
| (isneg(r) ? NATIVE_FFLAG_NEGATIVE : 0)
|
||||
;
|
||||
}
|
||||
#endif
|
||||
|
@ -622,25 +642,25 @@ PRIVATE inline uae_u32 FFPU extract_single(fpu_register const & src)
|
|||
fpu_register src0 = src;
|
||||
#endif
|
||||
|
||||
if (src == 0.0)
|
||||
if (src == 0.0)
|
||||
return 0;
|
||||
if (src < 0) {
|
||||
if (src < 0) {
|
||||
tmp = 0x80000000;
|
||||
src = -src;
|
||||
} else {
|
||||
} else {
|
||||
tmp = 0;
|
||||
}
|
||||
frac = frexp (src, &expon);
|
||||
frac += 0.5 / 16777216.0;
|
||||
if (frac >= 1.0) {
|
||||
}
|
||||
frac = frexp (src, &expon);
|
||||
frac += 0.5 / 16777216.0;
|
||||
if (frac >= 1.0) {
|
||||
frac /= 2.0;
|
||||
expon++;
|
||||
}
|
||||
}
|
||||
result = tmp | (((expon + 127 - 1) & 0xff) << 23) | (((int) (frac * 16777216.0)) & 0x7fffff);
|
||||
|
||||
// fpu_debug(("extract_single (%.04f) = %X\n",(float)src0,result));
|
||||
|
||||
return (result);
|
||||
return (result);
|
||||
}
|
||||
|
||||
// to exten
|
||||
|
@ -895,11 +915,9 @@ PRIVATE inline int FFPU get_fp_value (uae_u32 opcode, uae_u16 extra, fpu_registe
|
|||
break;
|
||||
case 3:
|
||||
ad = m68k_areg (regs, reg);
|
||||
m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size];
|
||||
break;
|
||||
case 4:
|
||||
m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size];
|
||||
ad = m68k_areg (regs, reg);
|
||||
ad = m68k_areg (regs, reg) - (reg == 7 ? sz2[size] : sz1[size]);
|
||||
break;
|
||||
case 5:
|
||||
ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword();
|
||||
|
@ -940,8 +958,8 @@ PRIVATE inline int FFPU get_fp_value (uae_u32 opcode, uae_u16 extra, fpu_registe
|
|||
fpu_debug(("get_fp_value m68k_getpc()=%X\n",m68k_getpc()));
|
||||
fpu_debug(("get_fp_value ad=%X\n",ad));
|
||||
fpu_debug(("get_fp_value get_long (ad)=%X\n",get_long (ad)));
|
||||
dump_first_bytes( get_real_address(ad)-64, 64 );
|
||||
dump_first_bytes( get_real_address(ad), 64 );
|
||||
dump_first_bytes( get_real_address(ad, 0, 0)-64, 64 );
|
||||
dump_first_bytes( get_real_address(ad, 0, 0), 64 );
|
||||
|
||||
switch (size) {
|
||||
case 0:
|
||||
|
@ -988,6 +1006,15 @@ PRIVATE inline int FFPU get_fp_value (uae_u32 opcode, uae_u16 extra, fpu_registe
|
|||
return 0;
|
||||
}
|
||||
|
||||
switch (mode) {
|
||||
case 3:
|
||||
m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size];
|
||||
break;
|
||||
case 4:
|
||||
m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size];
|
||||
break;
|
||||
}
|
||||
|
||||
// fpu_debug(("get_fp_value result = %.04f\n",(float)src));
|
||||
return 1;
|
||||
}
|
||||
|
@ -1204,7 +1231,7 @@ PRIVATE inline int FFPU fpp_cond(int condition)
|
|||
#if 0
|
||||
return fpcctrue(condition);
|
||||
#else
|
||||
switch (condition) {
|
||||
switch (condition & 0x1f) {
|
||||
case 0x00: CONDRET("False",0);
|
||||
case 0x01: CONDRET("Equal",Z);
|
||||
case 0x02: CONDRET("Ordered Greater Than",!(NaN || Z || N));
|
||||
|
@ -1299,11 +1326,11 @@ void FFPU fpuop_scc(uae_u32 opcode, uae_u32 extra)
|
|||
put_byte(ad, cc ? 0xff : 0x00);
|
||||
}
|
||||
|
||||
void FFPU fpuop_trapcc(uae_u32 opcode, uaecptr oldpc)
|
||||
void FFPU fpuop_trapcc(uae_u32 opcode, uaecptr oldpc, uae_u32 extra)
|
||||
{
|
||||
fpu_debug(("ftrapcc_opp %X at %08lx\n", (uae_u32)opcode, m68k_getpc ()));
|
||||
fpu_debug(("ftrapcc_opp %X, %X at %08lx\n", (uae_u32)opcode, (uae_u32)extra, m68k_getpc ()));
|
||||
|
||||
int cc = fpp_cond(opcode & 0x3f);
|
||||
int cc = fpp_cond(extra & 0x3f);
|
||||
if (cc == -1) {
|
||||
m68k_setpc (oldpc);
|
||||
op_illg (opcode);
|
||||
|
@ -1516,8 +1543,7 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra)
|
|||
if ((opcode & 0x38) == 0) {
|
||||
if (extra & 0x2000) { // dr bit
|
||||
if (extra & 0x1000) {
|
||||
// according to the manual, the msb bits are always zero.
|
||||
m68k_dreg (regs, opcode & 7) = get_fpcr() & 0xFFFF;
|
||||
m68k_dreg (regs, opcode & 7) = get_fpcr();
|
||||
fpu_debug(("FMOVEM FPU fpcr (%X) -> D%d\n", get_fpcr(), opcode & 7));
|
||||
}
|
||||
if (extra & 0x0800) {
|
||||
|
@ -1548,8 +1574,7 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra)
|
|||
else if ((opcode & 0x38) == 8) {
|
||||
if (extra & 0x2000) { // dr bit
|
||||
if (extra & 0x1000) {
|
||||
// according to the manual, the msb bits are always zero.
|
||||
m68k_areg (regs, opcode & 7) = get_fpcr() & 0xFFFF;
|
||||
m68k_areg (regs, opcode & 7) = get_fpcr();
|
||||
fpu_debug(("FMOVEM FPU fpcr (%X) -> A%d\n", get_fpcr(), opcode & 7));
|
||||
}
|
||||
if (extra & 0x0800) {
|
||||
|
@ -1612,8 +1637,7 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra)
|
|||
}
|
||||
ad -= incr;
|
||||
if (extra & 0x1000) {
|
||||
// according to the manual, the msb bits are always zero.
|
||||
put_long (ad, get_fpcr() & 0xFFFF);
|
||||
put_long (ad, get_fpcr());
|
||||
fpu_debug(("FMOVEM FPU fpcr (%X) -> mem %X\n", get_fpcr(), ad ));
|
||||
ad += 4;
|
||||
}
|
||||
|
@ -1906,6 +1930,8 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra)
|
|||
FPU registers[reg] = 1.0e256;
|
||||
fpu_debug(("FP const: 1.0e256\n"));
|
||||
break;
|
||||
|
||||
// Valid for 64 bits only (see fpu.cpp)
|
||||
#if 0
|
||||
case 0x3c:
|
||||
FPU registers[reg] = 1.0e512;
|
||||
|
@ -1942,7 +1968,114 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra)
|
|||
return;
|
||||
}
|
||||
fpu_debug(("returned from get_fp_value m68k_getpc()=%X\n",m68k_getpc()));
|
||||
#if 0 // MJ added, not tested now
|
||||
if (FPU is_integral) {
|
||||
// 68040-specific operations
|
||||
switch (extra & 0x7f) {
|
||||
case 0x40: /* FSMOVE */
|
||||
fpu_debug(("FSMOVE %.04f\n",(double)src));
|
||||
FPU registers[reg] = (float)src;
|
||||
make_fpsr(FPU registers[reg]);
|
||||
break;
|
||||
case 0x44: /* FDMOVE */
|
||||
fpu_debug(("FDMOVE %.04f\n",(double)src));
|
||||
FPU registers[reg] = (double)src;
|
||||
make_fpsr(FPU registers[reg]);
|
||||
break;
|
||||
case 0x41: /* FSSQRT */
|
||||
fpu_debug(("FSQRT %.04f\n",(double)src));
|
||||
FPU registers[reg] = (float)sqrt (src);
|
||||
make_fpsr(FPU registers[reg]);
|
||||
break;
|
||||
case 0x45: /* FDSQRT */
|
||||
fpu_debug(("FSQRT %.04f\n",(double)src));
|
||||
FPU registers[reg] = (double)sqrt (src);
|
||||
make_fpsr(FPU registers[reg]);
|
||||
break;
|
||||
case 0x58: /* FSABS */
|
||||
fpu_debug(("FSABS %.04f\n",(double)src));
|
||||
FPU registers[reg] = (float)fabs(src);
|
||||
make_fpsr(FPU registers[reg]);
|
||||
break;
|
||||
case 0x5c: /* FDABS */
|
||||
fpu_debug(("FDABS %.04f\n",(double)src));
|
||||
FPU registers[reg] = (double)fabs(src);
|
||||
make_fpsr(FPU registers[reg]);
|
||||
break;
|
||||
case 0x5a: /* FSNEG */
|
||||
fpu_debug(("FSNEG %.04f\n",(double)src));
|
||||
FPU registers[reg] = (float)-src;
|
||||
make_fpsr(FPU registers[reg]);
|
||||
break;
|
||||
case 0x5e: /* FDNEG */
|
||||
fpu_debug(("FDNEG %.04f\n",(double)src));
|
||||
FPU registers[reg] = (double)-src;
|
||||
make_fpsr(FPU registers[reg]);
|
||||
break;
|
||||
case 0x60: /* FSDIV */
|
||||
fpu_debug(("FSDIV %.04f\n",(double)src));
|
||||
FPU registers[reg] = (float)(FPU registers[reg] / src);
|
||||
make_fpsr(FPU registers[reg]);
|
||||
break;
|
||||
case 0x64: /* FDDIV */
|
||||
fpu_debug(("FDDIV %.04f\n",(double)src));
|
||||
FPU registers[reg] = (double)(FPU registers[reg] / src);
|
||||
make_fpsr(FPU registers[reg]);
|
||||
break;
|
||||
case 0x62: /* FSADD */
|
||||
fpu_debug(("FSADD %.04f\n",(double)src));
|
||||
FPU registers[reg] = (float)(FPU registers[reg] + src);
|
||||
make_fpsr(FPU registers[reg]);
|
||||
break;
|
||||
case 0x66: /* FDADD */
|
||||
fpu_debug(("FDADD %.04f\n",(double)src));
|
||||
FPU registers[reg] = (double)(FPU registers[reg] + src);
|
||||
make_fpsr(FPU registers[reg]);
|
||||
break;
|
||||
case 0x68: /* FSSUB */
|
||||
fpu_debug(("FSSUB %.04f\n",(double)src));
|
||||
FPU registers[reg] = (float)(FPU registers[reg] - src);
|
||||
make_fpsr(FPU registers[reg]);
|
||||
break;
|
||||
case 0x6c: /* FDSUB */
|
||||
fpu_debug(("FDSUB %.04f\n",(double)src));
|
||||
FPU registers[reg] = (double)(FPU registers[reg] - src);
|
||||
make_fpsr(FPU registers[reg]);
|
||||
break;
|
||||
case 0x63: /* FSMUL */
|
||||
case 0x67: /* FDMUL */
|
||||
get_dest_flags(FPU registers[reg]);
|
||||
get_source_flags(src);
|
||||
if(fl_dest.in_range && fl_source.in_range) {
|
||||
if ((extra & 0x7f) == 0x63)
|
||||
FPU registers[reg] = (float)(FPU registers[reg] * src);
|
||||
else
|
||||
FPU registers[reg] = (double)(FPU registers[reg] * src);
|
||||
}
|
||||
else if (fl_dest.nan || fl_source.nan ||
|
||||
fl_dest.zero && fl_source.infinity ||
|
||||
fl_dest.infinity && fl_source.zero ) {
|
||||
make_nan( FPU registers[reg], fl_dest.negative );
|
||||
}
|
||||
else if (fl_dest.zero || fl_source.zero ) {
|
||||
make_zero(FPU registers[reg], fl_dest.negative != fl_source.negative);
|
||||
}
|
||||
else {
|
||||
make_inf(FPU registers[reg], fl_dest.negative != fl_source.negative);
|
||||
}
|
||||
make_fpsr(FPU registers[reg]);
|
||||
break;
|
||||
default:
|
||||
// Continue decode-execute 6888x instructions below
|
||||
goto process_6888x_instructions;
|
||||
}
|
||||
fpu_debug(("END m68k_getpc()=%X\n",m68k_getpc()));
|
||||
dump_registers( "END ");
|
||||
return;
|
||||
}
|
||||
|
||||
process_6888x_instructions:
|
||||
#endif
|
||||
switch (extra & 0x7f) {
|
||||
case 0x00: /* FMOVE */
|
||||
fpu_debug(("FMOVE %.04f\n",(double)src));
|
||||
|
@ -1954,7 +2087,7 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra)
|
|||
fpu_debug(("FINT %.04f\n",(double)src));
|
||||
// FPU registers[reg] = (int) (src + 0.5);
|
||||
// FIXME: use native rounding mode flags
|
||||
switch (get_fpcr() & 0x30) {
|
||||
switch (get_fpcr() & FPCR_ROUNDING_MODE) {
|
||||
case FPCR_ROUND_ZERO:
|
||||
FPU registers[reg] = round_to_zero(src);
|
||||
break;
|
||||
|
@ -2075,7 +2208,10 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra)
|
|||
break;
|
||||
case 0x1a: /* FNEG */
|
||||
fpu_debug(("FNEG %.04f\n",(double)src));
|
||||
FPU registers[reg] = -src;
|
||||
if (iszero(src))
|
||||
make_zero(FPU registers[reg], !isneg(src));
|
||||
else
|
||||
FPU registers[reg] = -src;
|
||||
make_fpsr(FPU registers[reg]);
|
||||
break;
|
||||
case 0x1c: /* FACOS */
|
||||
|
@ -2092,7 +2228,7 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra)
|
|||
fpu_debug(("FGETEXP %.04f\n",(double)src));
|
||||
#if FPU_HAVE_IEEE_DOUBLE
|
||||
if( isinf(src) ) {
|
||||
make_nan( FPU registers[reg] );
|
||||
make_nan( FPU registers[reg], isneg(src) );
|
||||
}
|
||||
else {
|
||||
FPU registers[reg] = fast_fgetexp( src );
|
||||
|
@ -2116,7 +2252,7 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra)
|
|||
FPU registers[reg] = 0;
|
||||
}
|
||||
else if( isinf(src) ) {
|
||||
make_nan( FPU registers[reg] );
|
||||
make_nan( FPU registers[reg], isneg(src) );
|
||||
}
|
||||
else {
|
||||
FPU registers[reg] = src;
|
||||
|
@ -2166,27 +2302,15 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra)
|
|||
FPU registers[reg] *= src;
|
||||
}
|
||||
else if (fl_dest.nan || fl_source.nan ||
|
||||
fl_dest.zero && fl_source.infinity ||
|
||||
fl_dest.infinity && fl_source.zero ) {
|
||||
make_nan( FPU registers[reg] );
|
||||
(fl_dest.zero && fl_source.infinity) ||
|
||||
(fl_dest.infinity && fl_source.zero) ) {
|
||||
make_nan( FPU registers[reg], fl_dest.negative );
|
||||
}
|
||||
else if (fl_dest.zero || fl_source.zero ) {
|
||||
if (fl_dest.negative && !fl_source.negative ||
|
||||
!fl_dest.negative && fl_source.negative) {
|
||||
make_zero_negative(FPU registers[reg]);
|
||||
}
|
||||
else {
|
||||
make_zero_positive(FPU registers[reg]);
|
||||
}
|
||||
make_zero(FPU registers[reg], fl_dest.negative != fl_source.negative);
|
||||
}
|
||||
else {
|
||||
if( fl_dest.negative && !fl_source.negative ||
|
||||
!fl_dest.negative && fl_source.negative) {
|
||||
make_inf_negative(FPU registers[reg]);
|
||||
}
|
||||
else {
|
||||
make_inf_positive(FPU registers[reg]);
|
||||
}
|
||||
make_inf(FPU registers[reg], fl_dest.negative != fl_source.negative);
|
||||
}
|
||||
#else
|
||||
fpu_debug(("FMUL %.04f\n",(double)src));
|
||||
|
@ -2223,8 +2347,8 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra)
|
|||
// Overflow, underflow
|
||||
|
||||
#if FPU_HAVE_IEEE_DOUBLE
|
||||
if( isinf(FPU registers[reg]) ) {
|
||||
make_nan( FPU registers[reg] );
|
||||
if( isinf(src) ) {
|
||||
make_nan( FPU registers[reg], isneg(src) );
|
||||
}
|
||||
else {
|
||||
// When the absolute value of the source operand is >= 2^14,
|
||||
|
@ -2336,6 +2460,27 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra)
|
|||
dump_registers( "END ");
|
||||
}
|
||||
|
||||
|
||||
void fpu_set_fpsr(uae_u32 new_fpsr)
|
||||
{
|
||||
set_fpsr(new_fpsr);
|
||||
}
|
||||
|
||||
uae_u32 fpu_get_fpsr(void)
|
||||
{
|
||||
return get_fpsr();
|
||||
}
|
||||
|
||||
void fpu_set_fpcr(uae_u32 new_fpcr)
|
||||
{
|
||||
set_fpcr(new_fpcr);
|
||||
}
|
||||
|
||||
uae_u32 fpu_get_fpcr(void)
|
||||
{
|
||||
return get_fpcr();
|
||||
}
|
||||
|
||||
/* -------------------------- Initialization -------------------------- */
|
||||
|
||||
void FFPU fpu_init (bool integral_68040)
|
||||
|
|
|
@ -1,28 +1,33 @@
|
|||
/*
|
||||
* fpu/fpu_uae.h - Extra Definitions for the old UAE FPU core
|
||||
* fpu/fpu_uae.h - Extra Definitions for the old UAE FPU core
|
||||
*
|
||||
* Basilisk II (C) 1997-2008 Christian Bauer
|
||||
* Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
|
||||
*
|
||||
* Inspired by Christian Bauer's Basilisk II
|
||||
*
|
||||
* MC68881/68040 fpu emulation
|
||||
*
|
||||
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||
* Rewrite for x86, copyright 1999-2000 Lauri Pesonen
|
||||
* New framework, copyright 2000 Gwenole Beauchesne
|
||||
* Adapted for JIT compilation (c) Bernd Meyer, 2000
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
* This file is part of the ARAnyM project which builds a new and powerful
|
||||
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
* MC68881/68040 fpu emulation
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
|
||||
* New framework, copyright 2000-2001 Gwenole Beauchesne
|
||||
* Adapted for JIT compilation (c) Bernd Meyer, 2000-2001
|
||||
*
|
||||
* ARAnyM is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ARAnyM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ARAnyM; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef FPU_UAE_H
|
||||
|
@ -78,11 +83,9 @@ PRIVATE inline bool FFPU do_isinf(fpu_register const & r);
|
|||
PRIVATE inline bool FFPU do_isneg(fpu_register const & r);
|
||||
PRIVATE inline bool FFPU do_iszero(fpu_register const & r);
|
||||
|
||||
PRIVATE inline void FFPU make_nan(fpu_register & r);
|
||||
PRIVATE inline void FFPU make_zero_positive(fpu_register & r);
|
||||
PRIVATE inline void FFPU make_zero_negative(fpu_register & r);
|
||||
PRIVATE inline void FFPU make_inf_positive(fpu_register & r);
|
||||
PRIVATE inline void FFPU make_inf_negative(fpu_register & r);
|
||||
PRIVATE inline void FFPU make_nan(fpu_register & r, bool negative);
|
||||
PRIVATE inline void FFPU make_zero(fpu_register & r, bool negative);
|
||||
PRIVATE inline void FFPU make_inf(fpu_register & r, bool negative);
|
||||
|
||||
PRIVATE inline void FFPU fast_scale(fpu_register & r, int add);
|
||||
PRIVATE inline fpu_register FFPU fast_fgetexp(fpu_register const & r);
|
||||
|
|
|
@ -1,27 +1,33 @@
|
|||
/*
|
||||
* fpu_x86.cpp - 68881/68040 fpu code for x86/Windows an Linux/x86.
|
||||
* fpu/fpu_x86.cpp - 68881/68040 fpu code for x86/Windows an Linux/x86.
|
||||
*
|
||||
* Basilisk II (C) 1997-2008 Christian Bauer
|
||||
* Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
|
||||
*
|
||||
* Inspired by Christian Bauer's Basilisk II
|
||||
*
|
||||
* MC68881/68040 fpu emulation
|
||||
* This file is part of the ARAnyM project which builds a new and powerful
|
||||
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
|
||||
*
|
||||
* Based on UAE FPU, original copyright 1996 Herman ten Brugge,
|
||||
* rewritten for x86 by Lauri Pesonen 1999-2000,
|
||||
* accomodated to GCC's Extended Asm syntax by Gwenole Beauchesne 2000.
|
||||
* MC68881/68040 fpu emulation
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
|
||||
* New framework, copyright 2000-2001 Gwenole Beauchesne
|
||||
* Adapted for JIT compilation (c) Bernd Meyer, 2000-2001
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
* ARAnyM is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* ARAnyM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ARAnyM; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*
|
||||
* Interface
|
||||
|
@ -134,10 +140,8 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
# include <cmath>
|
||||
# include <cstdio>
|
||||
|
||||
#include "sysdeps.h"
|
||||
#include "memory.h"
|
||||
|
@ -238,8 +242,6 @@ PUBLIC void FFPU fpu_dump_flags(void)
|
|||
#include "debug.h"
|
||||
|
||||
#if FPU_DEBUG
|
||||
#undef __inline__
|
||||
#define __inline__
|
||||
|
||||
PRIVATE void FFPU dump_first_bytes_buf(char *b, uae_u8* buf, uae_s32 actual)
|
||||
{
|
||||
|
@ -390,7 +392,7 @@ PRIVATE void FFPU FPU_CONSISTENCY_CHECK_STOP(const char *)
|
|||
|
||||
/* ---------------------------- Status functions ---------------------------- */
|
||||
|
||||
PRIVATE void __inline__ FFPU SET_BSUN_ON_NAN ()
|
||||
PRIVATE void inline FFPU SET_BSUN_ON_NAN ()
|
||||
{
|
||||
if( (x86_status_word & (SW_Z_I_NAN_MASK)) == SW_NAN ) {
|
||||
x86_status_word |= SW_FAKE_BSUN;
|
||||
|
@ -398,7 +400,7 @@ PRIVATE void __inline__ FFPU SET_BSUN_ON_NAN ()
|
|||
}
|
||||
}
|
||||
|
||||
PRIVATE void __inline__ FFPU build_ex_status ()
|
||||
PRIVATE void inline FFPU build_ex_status ()
|
||||
{
|
||||
if(x86_status_word & SW_EXCEPTION_MASK) {
|
||||
// _asm FNCLEX
|
||||
|
@ -415,20 +417,20 @@ When the FPU creates a NAN, the NAN always contains the same bit pattern
|
|||
in the mantissa. All bits of the mantissa are ones for any precision.
|
||||
When the user creates a NAN, any nonzero bit pattern can be stored in the mantissa.
|
||||
*/
|
||||
PRIVATE __inline__ void FFPU MAKE_NAN (fpu_register & f)
|
||||
PRIVATE inline void FFPU MAKE_NAN (fpu_register & f, bool negative)
|
||||
{
|
||||
// Make it non-signaling.
|
||||
uae_u8 * p = (uae_u8 *) &f;
|
||||
memset( p, 0xFF, sizeof(fpu_register) - 1 );
|
||||
p[9] = 0x7F;
|
||||
p[9] = negative ? 0xff : 0x7F;
|
||||
}
|
||||
|
||||
/*
|
||||
For single- and double-precision infinities the fraction is a zero.
|
||||
For extended-precision infinities, the mantissa’s MSB, the explicit
|
||||
For extended-precision infinities, the mantissa<EFBFBD>s MSB, the explicit
|
||||
integer bit, can be either one or zero.
|
||||
*/
|
||||
PRIVATE __inline__ uae_u32 FFPU IS_INFINITY (fpu_register const & f)
|
||||
PRIVATE inline uae_u32 FFPU IS_INFINITY (fpu_register const & f)
|
||||
{
|
||||
uae_u8 * p = (uae_u8 *) &f;
|
||||
if( ((p[9] & 0x7F) == 0x7F) && p[8] == 0xFF ) {
|
||||
|
@ -439,7 +441,7 @@ PRIVATE __inline__ uae_u32 FFPU IS_INFINITY (fpu_register const & f)
|
|||
return(0);
|
||||
}
|
||||
|
||||
PRIVATE __inline__ uae_u32 FFPU IS_NAN (fpu_register const & f)
|
||||
PRIVATE inline uae_u32 FFPU IS_NAN (fpu_register const & f)
|
||||
{
|
||||
uae_u8 * p = (uae_u8 *) &f;
|
||||
if( ((p[9] & 0x7F) == 0x7F) && p[8] == 0xFF ) {
|
||||
|
@ -450,7 +452,7 @@ PRIVATE __inline__ uae_u32 FFPU IS_NAN (fpu_register const & f)
|
|||
return(0);
|
||||
}
|
||||
|
||||
PRIVATE __inline__ uae_u32 FFPU IS_ZERO (fpu_register const & f)
|
||||
PRIVATE inline uae_u32 FFPU IS_ZERO (fpu_register const & f)
|
||||
{
|
||||
uae_u8 * p = (uae_u8 *) &f;
|
||||
return *((uae_u32 *)p) == 0 &&
|
||||
|
@ -458,34 +460,34 @@ PRIVATE __inline__ uae_u32 FFPU IS_ZERO (fpu_register const & f)
|
|||
( *((uae_u16 *)&p[8]) & 0x7FFF ) == 0;
|
||||
}
|
||||
|
||||
PRIVATE __inline__ void FFPU MAKE_INF_POSITIVE (fpu_register & f)
|
||||
PRIVATE inline void FFPU MAKE_INF_POSITIVE (fpu_register & f)
|
||||
{
|
||||
uae_u8 * p = (uae_u8 *) &f;
|
||||
memset( p, 0, sizeof(fpu_register)-2 );
|
||||
*((uae_u16 *)&p[8]) = 0x7FFF;
|
||||
}
|
||||
|
||||
PRIVATE __inline__ void FFPU MAKE_INF_NEGATIVE (fpu_register & f)
|
||||
PRIVATE inline void FFPU MAKE_INF_NEGATIVE (fpu_register & f)
|
||||
{
|
||||
uae_u8 * p = (uae_u8 *) &f;
|
||||
memset( p, 0, sizeof(fpu_register)-2 );
|
||||
*((uae_u16 *)&p[8]) = 0xFFFF;
|
||||
}
|
||||
|
||||
PRIVATE __inline__ void FFPU MAKE_ZERO_POSITIVE (fpu_register & f)
|
||||
PRIVATE inline void FFPU MAKE_ZERO_POSITIVE (fpu_register & f)
|
||||
{
|
||||
uae_u32 * const p = (uae_u32 *) &f;
|
||||
memset( p, 0, sizeof(fpu_register) );
|
||||
}
|
||||
|
||||
PRIVATE __inline__ void FFPU MAKE_ZERO_NEGATIVE (fpu_register & f)
|
||||
PRIVATE inline void FFPU MAKE_ZERO_NEGATIVE (fpu_register & f)
|
||||
{
|
||||
uae_u32 * const p = (uae_u32 *) &f;
|
||||
memset( p, 0, sizeof(fpu_register) );
|
||||
*((uae_u32 *)&p[4]) = 0x80000000;
|
||||
}
|
||||
|
||||
PRIVATE __inline__ uae_u32 FFPU IS_NEGATIVE (fpu_register const & f)
|
||||
PRIVATE inline uae_u32 FFPU IS_NEGATIVE (fpu_register const & f)
|
||||
{
|
||||
uae_u8 * p = (uae_u8 *) &f;
|
||||
return( (p[9] & 0x80) != 0 );
|
||||
|
@ -900,6 +902,34 @@ PRIVATE void FFPU do_fmove ( fpu_register & dest, fpu_register const & src )
|
|||
FPU_CONSISTENCY_CHECK_STOP("do_fmove");
|
||||
}
|
||||
|
||||
PRIVATE void FFPU do_fsmove ( fpu_register & dest, fpu_register const & src )
|
||||
{
|
||||
FPU_CONSISTENCY_CHECK_START();
|
||||
__asm__ __volatile__(
|
||||
"fldt %2\n"
|
||||
"fxam \n"
|
||||
"fnstsw %0\n"
|
||||
"fstpt %1\n"
|
||||
: "=m" (x86_status_word), "=m" (dest)
|
||||
: "m" (src)
|
||||
);
|
||||
FPU_CONSISTENCY_CHECK_STOP("do_fsmove");
|
||||
}
|
||||
|
||||
PRIVATE void FFPU do_fdmove ( fpu_register & dest, fpu_register const & src )
|
||||
{
|
||||
FPU_CONSISTENCY_CHECK_START();
|
||||
__asm__ __volatile__(
|
||||
"fldt %2\n"
|
||||
"fxam \n"
|
||||
"fnstsw %0\n"
|
||||
"fstpt %1\n"
|
||||
: "=m" (x86_status_word), "=m" (dest)
|
||||
: "m" (src)
|
||||
);
|
||||
FPU_CONSISTENCY_CHECK_STOP("do_fdmove");
|
||||
}
|
||||
|
||||
/*
|
||||
PRIVATE void FFPU do_fmove_no_status ( fpu_register & dest, fpu_register const & src )
|
||||
{
|
||||
|
@ -1023,6 +1053,50 @@ PRIVATE void FFPU do_fsqrt ( fpu_register & dest, fpu_register const & src )
|
|||
FPU_CONSISTENCY_CHECK_STOP("do_fsqrt");
|
||||
}
|
||||
|
||||
PRIVATE void FFPU do_fssqrt ( fpu_register & dest, fpu_register const & src )
|
||||
{
|
||||
FPU_CONSISTENCY_CHECK_START();
|
||||
__asm__ __volatile__(
|
||||
"fldt %2\n"
|
||||
"fsqrt \n"
|
||||
"fxam \n"
|
||||
"fnstsw %0\n"
|
||||
"fstpt %1\n"
|
||||
: "=m" (x86_status_word), "=m" (dest)
|
||||
: "m" (src)
|
||||
);
|
||||
|
||||
if(x86_status_word & SW_EXCEPTION_MASK) {
|
||||
// _asm FNCLEX
|
||||
__asm__ __volatile__("fnclex");
|
||||
x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_PE);
|
||||
x86_status_word_accrued |= x86_status_word;
|
||||
}
|
||||
FPU_CONSISTENCY_CHECK_STOP("do_fssqrt");
|
||||
}
|
||||
|
||||
PRIVATE void FFPU do_fdsqrt ( fpu_register & dest, fpu_register const & src )
|
||||
{
|
||||
FPU_CONSISTENCY_CHECK_START();
|
||||
__asm__ __volatile__(
|
||||
"fldt %2\n"
|
||||
"fsqrt \n"
|
||||
"fxam \n"
|
||||
"fnstsw %0\n"
|
||||
"fstpt %1\n"
|
||||
: "=m" (x86_status_word), "=m" (dest)
|
||||
: "m" (src)
|
||||
);
|
||||
|
||||
if(x86_status_word & SW_EXCEPTION_MASK) {
|
||||
// _asm FNCLEX
|
||||
__asm__ __volatile__("fnclex");
|
||||
x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_PE);
|
||||
x86_status_word_accrued |= x86_status_word;
|
||||
}
|
||||
FPU_CONSISTENCY_CHECK_STOP("do_fdsqrt");
|
||||
}
|
||||
|
||||
PRIVATE void FFPU do_ftst ( fpu_register const & src )
|
||||
{
|
||||
FPU_CONSISTENCY_CHECK_START();
|
||||
|
@ -1311,6 +1385,48 @@ PRIVATE void FFPU do_fabs ( fpu_register & dest, fpu_register const & src )
|
|||
FPU_CONSISTENCY_CHECK_STOP("do_fabs");
|
||||
}
|
||||
|
||||
PRIVATE void FFPU do_fsabs ( fpu_register & dest, fpu_register const & src )
|
||||
{
|
||||
FPU_CONSISTENCY_CHECK_START();
|
||||
__asm__ __volatile__(
|
||||
"fldt %2\n"
|
||||
"fabs \n"
|
||||
"fxam \n"
|
||||
"fnstsw %0\n"
|
||||
"fstpt %1\n"
|
||||
: "=m" (x86_status_word), "=m" (dest)
|
||||
: "m" (src)
|
||||
);
|
||||
// x86 fabs should not rise any exceptions (except stack underflow)
|
||||
if(x86_status_word & SW_EXCEPTION_MASK) {
|
||||
// _asm FNCLEX
|
||||
__asm__ __volatile__("fnclex");
|
||||
x86_status_word &= ~SW_EXCEPTION_MASK;
|
||||
}
|
||||
FPU_CONSISTENCY_CHECK_STOP("do_fsabs");
|
||||
}
|
||||
|
||||
PRIVATE void FFPU do_fdabs ( fpu_register & dest, fpu_register const & src )
|
||||
{
|
||||
FPU_CONSISTENCY_CHECK_START();
|
||||
__asm__ __volatile__(
|
||||
"fldt %2\n"
|
||||
"fabs \n"
|
||||
"fxam \n"
|
||||
"fnstsw %0\n"
|
||||
"fstpt %1\n"
|
||||
: "=m" (x86_status_word), "=m" (dest)
|
||||
: "m" (src)
|
||||
);
|
||||
// x86 fabs should not rise any exceptions (except stack underflow)
|
||||
if(x86_status_word & SW_EXCEPTION_MASK) {
|
||||
// _asm FNCLEX
|
||||
__asm__ __volatile__("fnclex");
|
||||
x86_status_word &= ~SW_EXCEPTION_MASK;
|
||||
}
|
||||
FPU_CONSISTENCY_CHECK_STOP("do_fdabs");
|
||||
}
|
||||
|
||||
PRIVATE void FFPU do_fneg ( fpu_register & dest, fpu_register const & src )
|
||||
{
|
||||
FPU_CONSISTENCY_CHECK_START();
|
||||
|
@ -1341,6 +1457,48 @@ PRIVATE void FFPU do_fneg ( fpu_register & dest, fpu_register const & src )
|
|||
FPU_CONSISTENCY_CHECK_STOP("do_fneg");
|
||||
}
|
||||
|
||||
PRIVATE void FFPU do_fsneg ( fpu_register & dest, fpu_register const & src )
|
||||
{
|
||||
FPU_CONSISTENCY_CHECK_START();
|
||||
__asm__ __volatile__(
|
||||
"fldt %2\n"
|
||||
"fchs \n"
|
||||
"fxam \n"
|
||||
"fnstsw %0\n"
|
||||
"fstpt %1\n"
|
||||
: "=m" (x86_status_word), "=m" (dest)
|
||||
: "m" (src)
|
||||
);
|
||||
// x86 fchs should not rise any exceptions (except stack underflow)
|
||||
if(x86_status_word & SW_EXCEPTION_MASK) {
|
||||
// _asm FNCLEX
|
||||
__asm__ __volatile__("fnclex");
|
||||
x86_status_word &= ~SW_EXCEPTION_MASK;
|
||||
}
|
||||
FPU_CONSISTENCY_CHECK_STOP("do_fsneg");
|
||||
}
|
||||
|
||||
PRIVATE void FFPU do_fdneg ( fpu_register & dest, fpu_register const & src )
|
||||
{
|
||||
FPU_CONSISTENCY_CHECK_START();
|
||||
__asm__ __volatile__(
|
||||
"fldt %2\n"
|
||||
"fchs \n"
|
||||
"fxam \n"
|
||||
"fnstsw %0\n"
|
||||
"fstpt %1\n"
|
||||
: "=m" (x86_status_word), "=m" (dest)
|
||||
: "m" (src)
|
||||
);
|
||||
// x86 fchs should not rise any exceptions (except stack underflow)
|
||||
if(x86_status_word & SW_EXCEPTION_MASK) {
|
||||
// _asm FNCLEX
|
||||
__asm__ __volatile__("fnclex");
|
||||
x86_status_word &= ~SW_EXCEPTION_MASK;
|
||||
}
|
||||
FPU_CONSISTENCY_CHECK_STOP("do_fdneg");
|
||||
}
|
||||
|
||||
PRIVATE void FFPU do_fcos ( fpu_register & dest, fpu_register const & src )
|
||||
{
|
||||
FPU_CONSISTENCY_CHECK_START();
|
||||
|
@ -1466,6 +1624,50 @@ PRIVATE void FFPU do_fdiv ( fpu_register & dest, fpu_register const & src )
|
|||
FPU_CONSISTENCY_CHECK_STOP("do_fdiv");
|
||||
}
|
||||
|
||||
PRIVATE void FFPU do_fsdiv ( fpu_register & dest, fpu_register const & src )
|
||||
{
|
||||
FPU_CONSISTENCY_CHECK_START();
|
||||
__asm__ __volatile__(
|
||||
"fldt %2\n"
|
||||
"fldt %1\n"
|
||||
"fdiv %%st(1), %%st(0)\n"
|
||||
"fxam \n"
|
||||
"fnstsw %0\n"
|
||||
"fstpt %1\n"
|
||||
"fstp %%st(0)\n"
|
||||
: "=m" (x86_status_word), "+m" (dest)
|
||||
: "m" (src)
|
||||
);
|
||||
if(x86_status_word & SW_EXCEPTION_MASK) {
|
||||
// _asm FNCLEX
|
||||
__asm__ __volatile__("fnclex");
|
||||
x86_status_word_accrued |= x86_status_word;
|
||||
}
|
||||
FPU_CONSISTENCY_CHECK_STOP("do_fsdiv");
|
||||
}
|
||||
|
||||
PRIVATE void FFPU do_fddiv ( fpu_register & dest, fpu_register const & src )
|
||||
{
|
||||
FPU_CONSISTENCY_CHECK_START();
|
||||
__asm__ __volatile__(
|
||||
"fldt %2\n"
|
||||
"fldt %1\n"
|
||||
"fdiv %%st(1), %%st(0)\n"
|
||||
"fxam \n"
|
||||
"fnstsw %0\n"
|
||||
"fstpt %1\n"
|
||||
"fstp %%st(0)\n"
|
||||
: "=m" (x86_status_word), "+m" (dest)
|
||||
: "m" (src)
|
||||
);
|
||||
if(x86_status_word & SW_EXCEPTION_MASK) {
|
||||
// _asm FNCLEX
|
||||
__asm__ __volatile__("fnclex");
|
||||
x86_status_word_accrued |= x86_status_word;
|
||||
}
|
||||
FPU_CONSISTENCY_CHECK_STOP("do_fddiv");
|
||||
}
|
||||
|
||||
// The sign of the quotient is the exclusive-OR of the sign bits
|
||||
// of the source and destination operands.
|
||||
// Quotient Byte is loaded with the sign and least significant
|
||||
|
@ -1851,6 +2053,48 @@ PRIVATE void FFPU do_fadd ( fpu_register & dest, fpu_register const & src )
|
|||
FPU_CONSISTENCY_CHECK_STOP("do_fadd");
|
||||
}
|
||||
|
||||
PRIVATE void FFPU do_fsadd ( fpu_register & dest, fpu_register const & src )
|
||||
{
|
||||
FPU_CONSISTENCY_CHECK_START();
|
||||
__asm__ __volatile__(
|
||||
"fldt %2\n"
|
||||
"fldt %1\n"
|
||||
"fadd \n"
|
||||
"fxam \n"
|
||||
"fnstsw %0\n"
|
||||
"fstpt %1\n"
|
||||
: "=m" (x86_status_word), "+m" (dest)
|
||||
: "m" (src)
|
||||
);
|
||||
if(x86_status_word & SW_EXCEPTION_MASK) {
|
||||
// _asm FNCLEX
|
||||
x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_UE - SW_OE - SW_PE);
|
||||
x86_status_word_accrued |= x86_status_word;
|
||||
}
|
||||
FPU_CONSISTENCY_CHECK_STOP("do_fsadd");
|
||||
}
|
||||
|
||||
PRIVATE void FFPU do_fdadd ( fpu_register & dest, fpu_register const & src )
|
||||
{
|
||||
FPU_CONSISTENCY_CHECK_START();
|
||||
__asm__ __volatile__(
|
||||
"fldt %2\n"
|
||||
"fldt %1\n"
|
||||
"fadd \n"
|
||||
"fxam \n"
|
||||
"fnstsw %0\n"
|
||||
"fstpt %1\n"
|
||||
: "=m" (x86_status_word), "+m" (dest)
|
||||
: "m" (src)
|
||||
);
|
||||
if(x86_status_word & SW_EXCEPTION_MASK) {
|
||||
// _asm FNCLEX
|
||||
x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_UE - SW_OE - SW_PE);
|
||||
x86_status_word_accrued |= x86_status_word;
|
||||
}
|
||||
FPU_CONSISTENCY_CHECK_STOP("do_fdadd");
|
||||
}
|
||||
|
||||
PRIVATE void FFPU do_fmul ( fpu_register & dest, fpu_register const & src )
|
||||
{
|
||||
FPU_CONSISTENCY_CHECK_START();
|
||||
|
@ -1882,6 +2126,48 @@ PRIVATE void FFPU do_fmul ( fpu_register & dest, fpu_register const & src )
|
|||
FPU_CONSISTENCY_CHECK_STOP("do_fmul");
|
||||
}
|
||||
|
||||
PRIVATE void FFPU do_fsmul ( fpu_register & dest, fpu_register const & src )
|
||||
{
|
||||
FPU_CONSISTENCY_CHECK_START();
|
||||
__asm__ __volatile__(
|
||||
"fldt %2\n"
|
||||
"fldt %1\n"
|
||||
"fmul \n"
|
||||
"fxam \n"
|
||||
"fnstsw %0\n"
|
||||
"fstpt %1\n"
|
||||
: "=m" (x86_status_word), "+m" (dest)
|
||||
: "m" (src)
|
||||
);
|
||||
if(x86_status_word & SW_EXCEPTION_MASK) {
|
||||
// _asm FNCLEX
|
||||
__asm__ __volatile__("fnclex");
|
||||
x86_status_word_accrued |= x86_status_word;
|
||||
}
|
||||
FPU_CONSISTENCY_CHECK_STOP("do_fsmul");
|
||||
}
|
||||
|
||||
PRIVATE void FFPU do_fdmul ( fpu_register & dest, fpu_register const & src )
|
||||
{
|
||||
FPU_CONSISTENCY_CHECK_START();
|
||||
__asm__ __volatile__(
|
||||
"fldt %2\n"
|
||||
"fldt %1\n"
|
||||
"fmul \n"
|
||||
"fxam \n"
|
||||
"fnstsw %0\n"
|
||||
"fstpt %1\n"
|
||||
: "=m" (x86_status_word), "+m" (dest)
|
||||
: "m" (src)
|
||||
);
|
||||
if(x86_status_word & SW_EXCEPTION_MASK) {
|
||||
// _asm FNCLEX
|
||||
__asm__ __volatile__("fnclex");
|
||||
x86_status_word_accrued |= x86_status_word;
|
||||
}
|
||||
FPU_CONSISTENCY_CHECK_STOP("do_fdmul");
|
||||
}
|
||||
|
||||
PRIVATE void FFPU do_fsgldiv ( fpu_register & dest, fpu_register const & src )
|
||||
{
|
||||
FPU_CONSISTENCY_CHECK_START();
|
||||
|
@ -2040,6 +2326,52 @@ PRIVATE void FFPU do_fsub ( fpu_register & dest, fpu_register const & src )
|
|||
FPU_CONSISTENCY_CHECK_STOP("do_fsub");
|
||||
}
|
||||
|
||||
PRIVATE void FFPU do_fssub ( fpu_register & dest, fpu_register const & src )
|
||||
{
|
||||
FPU_CONSISTENCY_CHECK_START();
|
||||
__asm__ __volatile__(
|
||||
"fldt %2\n"
|
||||
"fldt %1\n"
|
||||
"fsub %%st(1), %%st(0)\n"
|
||||
"fxam \n"
|
||||
"fnstsw %0\n"
|
||||
"fstpt %1\n"
|
||||
"fstp %%st(0)\n"
|
||||
: "=m" (x86_status_word), "+m" (dest)
|
||||
: "m" (src)
|
||||
);
|
||||
if(x86_status_word & SW_EXCEPTION_MASK) {
|
||||
// _asm FNCLEX
|
||||
__asm__ __volatile__("fnclex");
|
||||
x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_UE - SW_OE - SW_PE);
|
||||
x86_status_word_accrued |= x86_status_word;
|
||||
}
|
||||
FPU_CONSISTENCY_CHECK_STOP("do_fssub");
|
||||
}
|
||||
|
||||
PRIVATE void FFPU do_fdsub ( fpu_register & dest, fpu_register const & src )
|
||||
{
|
||||
FPU_CONSISTENCY_CHECK_START();
|
||||
__asm__ __volatile__(
|
||||
"fldt %2\n"
|
||||
"fldt %1\n"
|
||||
"fsub %%st(1), %%st(0)\n"
|
||||
"fxam \n"
|
||||
"fnstsw %0\n"
|
||||
"fstpt %1\n"
|
||||
"fstp %%st(0)\n"
|
||||
: "=m" (x86_status_word), "+m" (dest)
|
||||
: "m" (src)
|
||||
);
|
||||
if(x86_status_word & SW_EXCEPTION_MASK) {
|
||||
// _asm FNCLEX
|
||||
__asm__ __volatile__("fnclex");
|
||||
x86_status_word &= ~(SW_EXCEPTION_MASK - SW_IE - SW_UE - SW_OE - SW_PE);
|
||||
x86_status_word_accrued |= x86_status_word;
|
||||
}
|
||||
FPU_CONSISTENCY_CHECK_STOP("do_fdsub");
|
||||
}
|
||||
|
||||
PRIVATE void FFPU do_fsincos ( fpu_register & dest_sin, fpu_register & dest_cos, fpu_register const & src )
|
||||
{
|
||||
FPU_CONSISTENCY_CHECK_START();
|
||||
|
@ -2284,11 +2616,9 @@ PRIVATE int FFPU get_fp_value (uae_u32 opcode, uae_u32 extra, fpu_register & src
|
|||
break;
|
||||
case 3:
|
||||
ad = m68k_areg (regs, reg);
|
||||
m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size];
|
||||
break;
|
||||
case 4:
|
||||
m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size];
|
||||
ad = m68k_areg (regs, reg);
|
||||
ad = m68k_areg (regs, reg) - (reg == 7 ? sz2[size] : sz1[size]);
|
||||
break;
|
||||
case 5:
|
||||
ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword();
|
||||
|
@ -2387,6 +2717,15 @@ PRIVATE int FFPU get_fp_value (uae_u32 opcode, uae_u32 extra, fpu_register & src
|
|||
return 0;
|
||||
}
|
||||
|
||||
switch (mode) {
|
||||
case 3:
|
||||
m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size];
|
||||
break;
|
||||
case 4:
|
||||
m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size];
|
||||
break;
|
||||
}
|
||||
|
||||
// D(bug("get_fp_value result = %.04f\r\n",(float)src));
|
||||
|
||||
return 1;
|
||||
|
@ -2612,7 +2951,7 @@ PRIVATE int FFPU fpp_cond(uae_u32 opcode, int condition)
|
|||
#define I ((x86_status_word & (SW_Z_I_NAN_MASK)) == (SW_I))
|
||||
#define NotANumber ((x86_status_word & (SW_Z_I_NAN_MASK)) == SW_NAN)
|
||||
|
||||
switch (condition) {
|
||||
switch (condition & 0x1f) {
|
||||
// Common Tests, no BSUN
|
||||
case 0x01:
|
||||
CONDRET("Equal",Z);
|
||||
|
@ -2757,11 +3096,11 @@ PUBLIC void REGPARAM2 FFPU fpuop_scc(uae_u32 opcode, uae_u32 extra)
|
|||
}
|
||||
}
|
||||
|
||||
PUBLIC void REGPARAM2 FFPU fpuop_trapcc(uae_u32 opcode, uaecptr oldpc)
|
||||
PUBLIC void REGPARAM2 FFPU fpuop_trapcc(uae_u32 opcode, uaecptr oldpc, uae_u32 extra)
|
||||
{
|
||||
int cc;
|
||||
|
||||
D(bug("ftrapcc_opp %X at %08lx\r\n", (uae_u32)opcode, m68k_getpc ()));
|
||||
D(bug("ftrapcc_opp %X, %X at %08lx\r\n", (uae_u32)opcode, (uae_u32)extra, m68k_getpc ()));
|
||||
|
||||
#if I3_ON_FTRAPCC
|
||||
#error "FIXME: _asm int 3"
|
||||
|
@ -2769,7 +3108,7 @@ PUBLIC void REGPARAM2 FFPU fpuop_trapcc(uae_u32 opcode, uaecptr oldpc)
|
|||
#endif
|
||||
|
||||
// This must be broken.
|
||||
cc = fpp_cond(opcode, opcode & 0x3f);
|
||||
cc = fpp_cond(opcode, extra & 0x3f);
|
||||
|
||||
if (cc < 0) {
|
||||
m68k_setpc (oldpc);
|
||||
|
@ -2856,7 +3195,7 @@ PRIVATE void FFPU do_null_frestore ()
|
|||
{
|
||||
// A null-restore operation sets FP7-FP0 positive, nonsignaling NANs.
|
||||
for( int i=0; i<8; i++ ) {
|
||||
MAKE_NAN( FPU registers[i] );
|
||||
MAKE_NAN( FPU registers[i], false );
|
||||
}
|
||||
|
||||
FPU instruction_address = 0;
|
||||
|
@ -4646,6 +4985,249 @@ PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e4096( uae_u32 opcode, uae_u32
|
|||
}
|
||||
|
||||
|
||||
/* -------------------------- 040 ALU -------------------------- */
|
||||
PRIVATE void REGPARAM2 FFPU fpuop_do_fsmove( uae_u32 opcode, uae_u32 extra )
|
||||
{
|
||||
int reg = (extra >> 7) & 7;
|
||||
fpu_register src;
|
||||
if (get_fp_value (opcode, extra, src) == 0) {
|
||||
m68k_setpc (m68k_getpc () - 4);
|
||||
op_illg (opcode);
|
||||
dump_registers( "END ");
|
||||
return;
|
||||
}
|
||||
D(bug("FSMOVE %s\r\n",etos(src)));
|
||||
do_fsmove( FPU registers[reg], src );
|
||||
build_ex_status();
|
||||
dump_registers( "END ");
|
||||
}
|
||||
|
||||
PRIVATE void REGPARAM2 FFPU fpuop_do_fdmove( uae_u32 opcode, uae_u32 extra )
|
||||
{
|
||||
int reg = (extra >> 7) & 7;
|
||||
fpu_register src;
|
||||
if (get_fp_value (opcode, extra, src) == 0) {
|
||||
m68k_setpc (m68k_getpc () - 4);
|
||||
op_illg (opcode);
|
||||
dump_registers( "END ");
|
||||
return;
|
||||
}
|
||||
D(bug("FDMOVE %s\r\n",etos(src)));
|
||||
do_fdmove( FPU registers[reg], src );
|
||||
build_ex_status();
|
||||
dump_registers( "END ");
|
||||
}
|
||||
|
||||
PRIVATE void REGPARAM2 FFPU fpuop_do_fssqrt( uae_u32 opcode, uae_u32 extra )
|
||||
{
|
||||
int reg = (extra >> 7) & 7;
|
||||
fpu_register src;
|
||||
if (get_fp_value (opcode, extra, src) == 0) {
|
||||
m68k_setpc (m68k_getpc () - 4);
|
||||
op_illg (opcode);
|
||||
dump_registers( "END ");
|
||||
return;
|
||||
}
|
||||
D(bug("FSSQRT %s\r\n",etos(src)));
|
||||
do_fssqrt( FPU registers[reg], src );
|
||||
dump_registers( "END ");
|
||||
}
|
||||
|
||||
PRIVATE void REGPARAM2 FFPU fpuop_do_fdsqrt( uae_u32 opcode, uae_u32 extra )
|
||||
{
|
||||
int reg = (extra >> 7) & 7;
|
||||
fpu_register src;
|
||||
if (get_fp_value (opcode, extra, src) == 0) {
|
||||
m68k_setpc (m68k_getpc () - 4);
|
||||
op_illg (opcode);
|
||||
dump_registers( "END ");
|
||||
return;
|
||||
}
|
||||
D(bug("FDSQRT %s\r\n",etos(src)));
|
||||
do_fdsqrt( FPU registers[reg], src );
|
||||
dump_registers( "END ");
|
||||
}
|
||||
|
||||
PRIVATE void REGPARAM2 FFPU fpuop_do_fsabs( uae_u32 opcode, uae_u32 extra )
|
||||
{
|
||||
int reg = (extra >> 7) & 7;
|
||||
fpu_register src;
|
||||
if (get_fp_value (opcode, extra, src) == 0) {
|
||||
m68k_setpc (m68k_getpc () - 4);
|
||||
op_illg (opcode);
|
||||
dump_registers( "END ");
|
||||
return;
|
||||
}
|
||||
D(bug("FSABS %s\r\n",etos(src)));
|
||||
do_fsabs( FPU registers[reg], src );
|
||||
dump_registers( "END ");
|
||||
}
|
||||
|
||||
PRIVATE void REGPARAM2 FFPU fpuop_do_fdabs( uae_u32 opcode, uae_u32 extra )
|
||||
{
|
||||
int reg = (extra >> 7) & 7;
|
||||
fpu_register src;
|
||||
if (get_fp_value (opcode, extra, src) == 0) {
|
||||
m68k_setpc (m68k_getpc () - 4);
|
||||
op_illg (opcode);
|
||||
dump_registers( "END ");
|
||||
return;
|
||||
}
|
||||
D(bug("FDABS %s\r\n",etos(src)));
|
||||
do_fdabs( FPU registers[reg], src );
|
||||
dump_registers( "END ");
|
||||
}
|
||||
|
||||
PRIVATE void REGPARAM2 FFPU fpuop_do_fsneg( uae_u32 opcode, uae_u32 extra )
|
||||
{
|
||||
int reg = (extra >> 7) & 7;
|
||||
fpu_register src;
|
||||
if (get_fp_value (opcode, extra, src) == 0) {
|
||||
m68k_setpc (m68k_getpc () - 4);
|
||||
op_illg (opcode);
|
||||
dump_registers( "END ");
|
||||
return;
|
||||
}
|
||||
D(bug("FSNEG %s\r\n",etos(src)));
|
||||
do_fsneg( FPU registers[reg], src );
|
||||
dump_registers( "END ");
|
||||
}
|
||||
|
||||
PRIVATE void REGPARAM2 FFPU fpuop_do_fdneg( uae_u32 opcode, uae_u32 extra )
|
||||
{
|
||||
int reg = (extra >> 7) & 7;
|
||||
fpu_register src;
|
||||
if (get_fp_value (opcode, extra, src) == 0) {
|
||||
m68k_setpc (m68k_getpc () - 4);
|
||||
op_illg (opcode);
|
||||
dump_registers( "END ");
|
||||
return;
|
||||
}
|
||||
D(bug("FDNEG %s\r\n",etos(src)));
|
||||
do_fdneg( FPU registers[reg], src );
|
||||
dump_registers( "END ");
|
||||
}
|
||||
|
||||
PRIVATE void REGPARAM2 FFPU fpuop_do_fsdiv( uae_u32 opcode, uae_u32 extra )
|
||||
{
|
||||
int reg = (extra >> 7) & 7;
|
||||
fpu_register src;
|
||||
if (get_fp_value (opcode, extra, src) == 0) {
|
||||
m68k_setpc (m68k_getpc () - 4);
|
||||
op_illg (opcode);
|
||||
dump_registers( "END ");
|
||||
return;
|
||||
}
|
||||
D(bug("FSDIV %s\r\n",etos(src)));
|
||||
do_fsdiv( FPU registers[reg], src );
|
||||
dump_registers( "END ");
|
||||
}
|
||||
|
||||
PRIVATE void REGPARAM2 FFPU fpuop_do_fddiv( uae_u32 opcode, uae_u32 extra )
|
||||
{
|
||||
int reg = (extra >> 7) & 7;
|
||||
fpu_register src;
|
||||
if (get_fp_value (opcode, extra, src) == 0) {
|
||||
m68k_setpc (m68k_getpc () - 4);
|
||||
op_illg (opcode);
|
||||
dump_registers( "END ");
|
||||
return;
|
||||
}
|
||||
D(bug("FDDIV %s\r\n",etos(src)));
|
||||
do_fddiv( FPU registers[reg], src );
|
||||
dump_registers( "END ");
|
||||
}
|
||||
|
||||
PRIVATE void REGPARAM2 FFPU fpuop_do_fsadd( uae_u32 opcode, uae_u32 extra )
|
||||
{
|
||||
int reg = (extra >> 7) & 7;
|
||||
fpu_register src;
|
||||
if (get_fp_value (opcode, extra, src) == 0) {
|
||||
m68k_setpc (m68k_getpc () - 4);
|
||||
op_illg (opcode);
|
||||
dump_registers( "END ");
|
||||
return;
|
||||
}
|
||||
D(bug("FSADD %s\r\n",etos(src)));
|
||||
do_fsadd( FPU registers[reg], src );
|
||||
dump_registers( "END ");
|
||||
}
|
||||
|
||||
PRIVATE void REGPARAM2 FFPU fpuop_do_fdadd( uae_u32 opcode, uae_u32 extra )
|
||||
{
|
||||
int reg = (extra >> 7) & 7;
|
||||
fpu_register src;
|
||||
if (get_fp_value (opcode, extra, src) == 0) {
|
||||
m68k_setpc (m68k_getpc () - 4);
|
||||
op_illg (opcode);
|
||||
dump_registers( "END ");
|
||||
return;
|
||||
}
|
||||
D(bug("FDADD %s\r\n",etos(src)));
|
||||
do_fdadd( FPU registers[reg], src );
|
||||
dump_registers( "END ");
|
||||
}
|
||||
|
||||
PRIVATE void REGPARAM2 FFPU fpuop_do_fssub( uae_u32 opcode, uae_u32 extra )
|
||||
{
|
||||
int reg = (extra >> 7) & 7;
|
||||
fpu_register src;
|
||||
if (get_fp_value (opcode, extra, src) == 0) {
|
||||
m68k_setpc (m68k_getpc () - 4);
|
||||
op_illg (opcode);
|
||||
dump_registers( "END ");
|
||||
return;
|
||||
}
|
||||
D(bug("FSSUB %s\r\n",etos(src)));
|
||||
do_fssub( FPU registers[reg], src );
|
||||
dump_registers( "END ");
|
||||
}
|
||||
|
||||
PRIVATE void REGPARAM2 FFPU fpuop_do_fdsub( uae_u32 opcode, uae_u32 extra )
|
||||
{
|
||||
int reg = (extra >> 7) & 7;
|
||||
fpu_register src;
|
||||
if (get_fp_value (opcode, extra, src) == 0) {
|
||||
m68k_setpc (m68k_getpc () - 4);
|
||||
op_illg (opcode);
|
||||
dump_registers( "END ");
|
||||
return;
|
||||
}
|
||||
D(bug("FDSUB %s\r\n",etos(src)));
|
||||
do_fdsub( FPU registers[reg], src );
|
||||
dump_registers( "END ");
|
||||
}
|
||||
|
||||
PRIVATE void REGPARAM2 FFPU fpuop_do_fsmul( uae_u32 opcode, uae_u32 extra )
|
||||
{
|
||||
int reg = (extra >> 7) & 7;
|
||||
fpu_register src;
|
||||
if (get_fp_value (opcode, extra, src) == 0) {
|
||||
m68k_setpc (m68k_getpc () - 4);
|
||||
op_illg (opcode);
|
||||
dump_registers( "END ");
|
||||
return;
|
||||
}
|
||||
D(bug("FSMUL %s\r\n",etos(src)));
|
||||
do_fsmul( FPU registers[reg], src );
|
||||
dump_registers( "END ");
|
||||
}
|
||||
|
||||
PRIVATE void REGPARAM2 FFPU fpuop_do_fdmul( uae_u32 opcode, uae_u32 extra )
|
||||
{
|
||||
int reg = (extra >> 7) & 7;
|
||||
fpu_register src;
|
||||
if (get_fp_value (opcode, extra, src) == 0) {
|
||||
m68k_setpc (m68k_getpc () - 4);
|
||||
op_illg (opcode);
|
||||
dump_registers( "END ");
|
||||
return;
|
||||
}
|
||||
D(bug("FSMUL %s\r\n",etos(src)));
|
||||
do_fsmul( FPU registers[reg], src );
|
||||
dump_registers( "END ");
|
||||
}
|
||||
|
||||
/* ---------------------------- ALU ---------------------------- */
|
||||
|
||||
PRIVATE void REGPARAM2 FFPU fpuop_do_fmove( uae_u32 opcode, uae_u32 extra )
|
||||
|
@ -5037,7 +5619,7 @@ PRIVATE void REGPARAM2 FFPU fpuop_do_fgetexp( uae_u32 opcode, uae_u32 extra )
|
|||
D(bug("FGETEXP %s\r\n",etos(src)));
|
||||
|
||||
if( IS_INFINITY(src) ) {
|
||||
MAKE_NAN( FPU registers[reg] );
|
||||
MAKE_NAN( FPU registers[reg], IS_NEGATIVE(src) );
|
||||
do_ftst( FPU registers[reg] );
|
||||
x86_status_word |= SW_IE;
|
||||
} else {
|
||||
|
@ -5058,7 +5640,7 @@ PRIVATE void REGPARAM2 FFPU fpuop_do_fgetman( uae_u32 opcode, uae_u32 extra )
|
|||
}
|
||||
D(bug("FGETMAN %s\r\n",etos(src)));
|
||||
if( IS_INFINITY(src) ) {
|
||||
MAKE_NAN( FPU registers[reg] );
|
||||
MAKE_NAN( FPU registers[reg], IS_NEGATIVE(src) );
|
||||
do_ftst( FPU registers[reg] );
|
||||
x86_status_word |= SW_IE;
|
||||
} else {
|
||||
|
@ -5186,7 +5768,7 @@ PRIVATE void REGPARAM2 FFPU fpuop_do_fscale( uae_u32 opcode, uae_u32 extra )
|
|||
}
|
||||
D(bug("FSCALE %s, opcode=%X, extra=%X, ta %X\r\n",etos(src),opcode,extra,m68k_getpc()));
|
||||
if( IS_INFINITY(FPU registers[reg]) ) {
|
||||
MAKE_NAN( FPU registers[reg] );
|
||||
MAKE_NAN( FPU registers[reg], IS_NEGATIVE(FPU registers[reg]) );
|
||||
do_ftst( FPU registers[reg] );
|
||||
x86_status_word |= SW_IE;
|
||||
} else {
|
||||
|
@ -5744,6 +6326,61 @@ PRIVATE void FFPU build_fpp_opp_lookup_table ()
|
|||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (FPU is_integral) {
|
||||
switch (extra & 0x7f) {
|
||||
case 0x40:
|
||||
fpufunctbl[mask] = & FFPU fpuop_do_fsmove;
|
||||
break;
|
||||
case 0x44:
|
||||
fpufunctbl[mask] = & FFPU fpuop_do_fdmove;
|
||||
break;
|
||||
case 0x41:
|
||||
fpufunctbl[mask] = & FFPU fpuop_do_fssqrt;
|
||||
break;
|
||||
case 0x45:
|
||||
fpufunctbl[mask] = & FFPU fpuop_do_fdsqrt;
|
||||
break;
|
||||
case 0x58:
|
||||
fpufunctbl[mask] = & FFPU fpuop_do_fsabs;
|
||||
break;
|
||||
case 0x5c:
|
||||
fpufunctbl[mask] = & FFPU fpuop_do_fdabs;
|
||||
break;
|
||||
case 0x5a:
|
||||
fpufunctbl[mask] = & FFPU fpuop_do_fsneg;
|
||||
break;
|
||||
case 0x5e:
|
||||
fpufunctbl[mask] = & FFPU fpuop_do_fdneg;
|
||||
break;
|
||||
case 0x60:
|
||||
fpufunctbl[mask] = & FFPU fpuop_do_fsdiv;
|
||||
break;
|
||||
case 0x64:
|
||||
fpufunctbl[mask] = & FFPU fpuop_do_fddiv;
|
||||
break;
|
||||
case 0x62:
|
||||
fpufunctbl[mask] = & FFPU fpuop_do_fsadd;
|
||||
break;
|
||||
case 0x66:
|
||||
fpufunctbl[mask] = & FFPU fpuop_do_fdadd;
|
||||
break;
|
||||
case 0x68:
|
||||
fpufunctbl[mask] = & FFPU fpuop_do_fssub;
|
||||
break;
|
||||
case 0x6c:
|
||||
fpufunctbl[mask] = & FFPU fpuop_do_fdsub;
|
||||
break;
|
||||
case 0x63:
|
||||
fpufunctbl[mask] = & FFPU fpuop_do_fsmul;
|
||||
break;
|
||||
case 0x67:
|
||||
fpufunctbl[mask] = & FFPU fpuop_do_fdmul;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (extra & 0x7f) {
|
||||
case 0x00:
|
||||
|
@ -6033,6 +6670,26 @@ PRIVATE void FFPU do_fld1 ( fpu_register & dest )
|
|||
}
|
||||
|
||||
|
||||
void fpu_set_fpsr(uae_u32 new_fpsr)
|
||||
{
|
||||
set_fpsr(new_fpsr);
|
||||
}
|
||||
|
||||
uae_u32 fpu_get_fpsr(void)
|
||||
{
|
||||
return get_fpsr();
|
||||
}
|
||||
|
||||
void fpu_set_fpcr(uae_u32 new_fpcr)
|
||||
{
|
||||
set_fpcr(new_fpcr);
|
||||
}
|
||||
|
||||
uae_u32 fpu_get_fpcr(void)
|
||||
{
|
||||
return get_fpcr();
|
||||
}
|
||||
|
||||
/* ---------------------------- MAIN INIT ---------------------------- */
|
||||
|
||||
#ifdef HAVE_SIGACTION
|
||||
|
@ -6079,11 +6736,15 @@ PUBLIC void FFPU fpu_init( bool integral_68040 )
|
|||
FPU fpsr.quotient = 0;
|
||||
|
||||
for( int i=0; i<8; i++ ) {
|
||||
MAKE_NAN( FPU registers[i] );
|
||||
MAKE_NAN( FPU registers[i], false );
|
||||
}
|
||||
|
||||
build_fpp_opp_lookup_table();
|
||||
|
||||
/* _asm {
|
||||
FNINIT
|
||||
FLDCW x86_control_word
|
||||
} */
|
||||
__asm__ __volatile__("fninit\nfldcw %0" : : "m" (x86_control_word));
|
||||
|
||||
do_fldpi( const_pi );
|
||||
|
@ -6111,6 +6772,10 @@ PUBLIC void FFPU fpu_init( bool integral_68040 )
|
|||
set_constant( const_1e4096, "1.0e4096", 1.0e256, 10000 );
|
||||
|
||||
// Just in case.
|
||||
/* _asm {
|
||||
FNINIT
|
||||
FLDCW x86_control_word
|
||||
} */
|
||||
__asm__ __volatile__("fninit\nfldcw %0" : : "m" (x86_control_word));
|
||||
}
|
||||
|
||||
|
|
|
@ -1,28 +1,33 @@
|
|||
/*
|
||||
* fpu/fpu_x86.h - Extra Definitions for the X86 assembly FPU core
|
||||
* fpu/fpu_x86.h - Extra Definitions for the X86 assembly FPU core
|
||||
*
|
||||
* Basilisk II (C) 1997-2008 Christian Bauer
|
||||
* Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
|
||||
*
|
||||
* Inspired by Christian Bauer's Basilisk II
|
||||
*
|
||||
* MC68881/68040 fpu emulation
|
||||
*
|
||||
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||
* Rewrite for x86, copyright 1999-2000 Lauri Pesonen
|
||||
* New framework, copyright 2000 Gwenole Beauchesne
|
||||
* Adapted for JIT compilation (c) Bernd Meyer, 2000
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
* This file is part of the ARAnyM project which builds a new and powerful
|
||||
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
* MC68881/68040 fpu emulation
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
|
||||
* New framework, copyright 2000-2001 Gwenole Beauchesne
|
||||
* Adapted for JIT compilation (c) Bernd Meyer, 2000-2001
|
||||
*
|
||||
* ARAnyM is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ARAnyM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ARAnyM; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef FPU_X86_H
|
||||
|
@ -94,17 +99,17 @@ PRIVATE void FFPU FPU_CONSISTENCY_CHECK_START(void);
|
|||
PRIVATE void FFPU FPU_CONSISTENCY_CHECK_STOP(const char *name);
|
||||
|
||||
// Get special floating-point value class
|
||||
PRIVATE __inline__ uae_u32 FFPU IS_INFINITY (fpu_register const & f);
|
||||
PRIVATE __inline__ uae_u32 FFPU IS_NAN (fpu_register const & f);
|
||||
PRIVATE __inline__ uae_u32 FFPU IS_ZERO (fpu_register const & f);
|
||||
PRIVATE __inline__ uae_u32 FFPU IS_NEGATIVE (fpu_register const & f);
|
||||
PRIVATE inline uae_u32 FFPU IS_INFINITY (fpu_register const & f);
|
||||
PRIVATE inline uae_u32 FFPU IS_NAN (fpu_register const & f);
|
||||
PRIVATE inline uae_u32 FFPU IS_ZERO (fpu_register const & f);
|
||||
PRIVATE inline uae_u32 FFPU IS_NEGATIVE (fpu_register const & f);
|
||||
|
||||
// Make a special floating-point value
|
||||
PRIVATE __inline__ void FFPU MAKE_NAN (fpu_register & f);
|
||||
PRIVATE __inline__ void FFPU MAKE_INF_POSITIVE (fpu_register & f);
|
||||
PRIVATE __inline__ void FFPU MAKE_INF_NEGATIVE (fpu_register & f);
|
||||
PRIVATE __inline__ void FFPU MAKE_ZERO_POSITIVE (fpu_register & f);
|
||||
PRIVATE __inline__ void FFPU MAKE_ZERO_NEGATIVE (fpu_register & f);
|
||||
PRIVATE inline void FFPU MAKE_NAN (fpu_register & f, bool negative);
|
||||
PRIVATE inline void FFPU MAKE_INF_POSITIVE (fpu_register & f);
|
||||
PRIVATE inline void FFPU MAKE_INF_NEGATIVE (fpu_register & f);
|
||||
PRIVATE inline void FFPU MAKE_ZERO_POSITIVE (fpu_register & f);
|
||||
PRIVATE inline void FFPU MAKE_ZERO_NEGATIVE (fpu_register & f);
|
||||
|
||||
// Conversion from extended floating-point values
|
||||
PRIVATE uae_s32 FFPU extended_to_signed_32 ( fpu_register const & f ) REGPARAM;
|
||||
|
@ -342,6 +347,24 @@ PRIVATE void REGPARAM2 FFPU fpuop_do_fsincos( uae_u32 opcode, uae_u32 extra );
|
|||
PRIVATE void REGPARAM2 FFPU fpuop_do_fcmp( uae_u32 opcode, uae_u32 extra );
|
||||
PRIVATE void REGPARAM2 FFPU fpuop_do_ftst( uae_u32 opcode, uae_u32 extra );
|
||||
|
||||
// 040
|
||||
PRIVATE void REGPARAM2 FFPU fpuop_do_fsmove( uae_u32 opcode, uae_u32 extra );
|
||||
PRIVATE void REGPARAM2 FFPU fpuop_do_fdmove( uae_u32 opcode, uae_u32 extra );
|
||||
PRIVATE void REGPARAM2 FFPU fpuop_do_fssqrt( uae_u32 opcode, uae_u32 extra );
|
||||
PRIVATE void REGPARAM2 FFPU fpuop_do_fdsqrt( uae_u32 opcode, uae_u32 extra );
|
||||
PRIVATE void REGPARAM2 FFPU fpuop_do_fsabs( uae_u32 opcode, uae_u32 extra );
|
||||
PRIVATE void REGPARAM2 FFPU fpuop_do_fdabs( uae_u32 opcode, uae_u32 extra );
|
||||
PRIVATE void REGPARAM2 FFPU fpuop_do_fsneg( uae_u32 opcode, uae_u32 extra );
|
||||
PRIVATE void REGPARAM2 FFPU fpuop_do_fdneg( uae_u32 opcode, uae_u32 extra );
|
||||
PRIVATE void REGPARAM2 FFPU fpuop_do_fsdiv( uae_u32 opcode, uae_u32 extra );
|
||||
PRIVATE void REGPARAM2 FFPU fpuop_do_fddiv( uae_u32 opcode, uae_u32 extra );
|
||||
PRIVATE void REGPARAM2 FFPU fpuop_do_fsadd( uae_u32 opcode, uae_u32 extra );
|
||||
PRIVATE void REGPARAM2 FFPU fpuop_do_fdadd( uae_u32 opcode, uae_u32 extra );
|
||||
PRIVATE void REGPARAM2 FFPU fpuop_do_fssub( uae_u32 opcode, uae_u32 extra );
|
||||
PRIVATE void REGPARAM2 FFPU fpuop_do_fdsub( uae_u32 opcode, uae_u32 extra );
|
||||
PRIVATE void REGPARAM2 FFPU fpuop_do_fsmul( uae_u32 opcode, uae_u32 extra );
|
||||
PRIVATE void REGPARAM2 FFPU fpuop_do_fdmul( uae_u32 opcode, uae_u32 extra );
|
||||
|
||||
// Get & Put floating-point values
|
||||
PRIVATE int FFPU get_fp_value (uae_u32 opcode, uae_u32 extra, fpu_register & src) REGPARAM;
|
||||
PRIVATE int FFPU put_fp_value (fpu_register const & value, uae_u32 opcode, uae_u32 extra) REGPARAM;
|
||||
|
@ -351,9 +374,9 @@ PRIVATE int FFPU get_fp_ad(uae_u32 opcode, uae_u32 * ad) REGPARAM;
|
|||
PRIVATE int FFPU fpp_cond(uae_u32 opcode, int condition) REGPARAM;
|
||||
|
||||
// Misc functions
|
||||
PRIVATE void __inline__ FFPU set_host_fpu_control_word ();
|
||||
PRIVATE void __inline__ FFPU SET_BSUN_ON_NAN ();
|
||||
PRIVATE void __inline__ FFPU build_ex_status ();
|
||||
PRIVATE void inline FFPU set_host_fpu_control_word ();
|
||||
PRIVATE void inline FFPU SET_BSUN_ON_NAN ();
|
||||
PRIVATE void inline FFPU build_ex_status ();
|
||||
PRIVATE void FFPU do_null_frestore ();
|
||||
PRIVATE void FFPU build_fpp_opp_lookup_table ();
|
||||
PRIVATE void FFPU set_constant ( fpu_register & f, char *name, double value, uae_s32 mult );
|
||||
|
|
|
@ -1,3 +1,35 @@
|
|||
/*
|
||||
* fpu/fpu_x86_asm.h - Extra Definitions for the X86 assembly FPU core
|
||||
*
|
||||
* Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
|
||||
*
|
||||
* Inspired by Christian Bauer's Basilisk II
|
||||
*
|
||||
* This file is part of the ARAnyM project which builds a new and powerful
|
||||
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
|
||||
*
|
||||
* MC68881/68040 fpu emulation
|
||||
*
|
||||
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
|
||||
* New framework, copyright 2000-2001 Gwenole Beauchesne
|
||||
* Adapted for JIT compilation (c) Bernd Meyer, 2000-2001
|
||||
*
|
||||
* ARAnyM is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ARAnyM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ARAnyM; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#define DEFINE_X86_MACRO(name, value) \
|
||||
asm(".local " #name "\n\t" #name " = " #value)
|
||||
|
||||
|
|
|
@ -1,28 +1,38 @@
|
|||
/*
|
||||
* fpu/impl.h - extra functions and inline implementations
|
||||
*
|
||||
* Basilisk II (C) 1997-2008 Christian Bauer
|
||||
* Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
|
||||
*
|
||||
* Inspired by Christian Bauer's Basilisk II
|
||||
*
|
||||
* MC68881/68040 fpu emulation
|
||||
*
|
||||
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||
* Rewrite for x86, copyright 1999-2000 Lauri Pesonen
|
||||
* New framework, copyright 2000 Gwenole Beauchesne
|
||||
* Adapted for JIT compilation (c) Bernd Meyer, 2000
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
* This file is part of the ARAnyM project which builds a new and powerful
|
||||
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
* MC68881/68040 fpu emulation
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
|
||||
* New framework, copyright 2000-2001 Gwenole Beauchesne
|
||||
* Adapted for JIT compilation (c) Bernd Meyer, 2000-2001
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ARAnyM is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ARAnyM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ARAnyM; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef FPU_IMPL_H
|
||||
|
@ -101,14 +111,16 @@ static inline void FFPU set_fpsr(uae_u32 new_fpsr)
|
|||
/* Return the floating-point control register in m68k format */
|
||||
static inline uae_u32 FFPU get_fpcr(void)
|
||||
{
|
||||
uae_u32 rounding_precision = get_rounding_precision();
|
||||
uae_u32 rounding_mode = get_rounding_mode();
|
||||
return (rounding_precision | rounding_mode);
|
||||
// according to the manual, the msb bits are always zero.
|
||||
// According to Toni Wilen, on '040 the least
|
||||
// significant 4 bits are not masked out
|
||||
return FPU fpcr & (CPUType == 4 ? 0xffff : 0xfff0);
|
||||
}
|
||||
|
||||
/* Set the floating-point control register from an m68k format */
|
||||
static inline void FFPU set_fpcr(uae_u32 new_fpcr)
|
||||
{
|
||||
FPU fpcr = new_fpcr;
|
||||
set_rounding_precision ( new_fpcr & FPCR_ROUNDING_PRECISION);
|
||||
set_rounding_mode ( new_fpcr & FPCR_ROUNDING_MODE );
|
||||
set_host_control_word();
|
||||
|
@ -123,9 +135,8 @@ static inline void FFPU set_fpcr(uae_u32 new_fpcr)
|
|||
/* Retrieve a floating-point register value and convert it to double precision */
|
||||
static inline double FFPU fpu_get_register(int r)
|
||||
{
|
||||
double f;
|
||||
__asm__ __volatile__("fldt %1\n\tfstpl %0" : "=m" (f) : "m" (FPU registers[r]));
|
||||
return f;
|
||||
/* only used for debug output; no need for any fancy asm here */
|
||||
return FPU registers[r];
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,28 +1,33 @@
|
|||
/*
|
||||
* fpu/mathlib.cpp - Floating-point math support library
|
||||
*
|
||||
* Basilisk II (C) 1997-2008 Christian Bauer
|
||||
* Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
|
||||
*
|
||||
* Inspired by Christian Bauer's Basilisk II
|
||||
*
|
||||
* MC68881/68040 fpu emulation
|
||||
*
|
||||
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
|
||||
* New framework, copyright 2000-2001 Gwenole Beauchesne
|
||||
* Adapted for JIT compilation (c) Bernd Meyer, 2000-2001
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
* This file is part of the ARAnyM project which builds a new and powerful
|
||||
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
* MC68881/68040 fpu emulation
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
|
||||
* New framework, copyright 2000-2001 Gwenole Beauchesne
|
||||
* Adapted for JIT compilation (c) Bernd Meyer, 2000-2001
|
||||
*
|
||||
* ARAnyM is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ARAnyM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ARAnyM; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* NOTE: this file shall be included only from fpu/fpu_*.cpp */
|
||||
|
@ -40,6 +45,7 @@
|
|||
|
||||
#if defined(FPU_IEEE) && defined(USE_X87_ASSEMBLY)
|
||||
|
||||
#if !defined(HAVE_EXP10L) && !defined(HAVE_POW10L)
|
||||
PRIVATE fpu_extended fp_do_pow(fpu_extended x, fpu_extended y)
|
||||
{
|
||||
fpu_extended value, exponent;
|
||||
|
@ -82,7 +88,9 @@ PRIVATE fpu_extended fp_do_pow(fpu_extended x, fpu_extended y)
|
|||
__asm__ __volatile__("fscale" : "=t" (value) : "0" (value), "u" (exponent));
|
||||
return value;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_LOG1PL
|
||||
PRIVATE fpu_extended fp_do_log1p(fpu_extended x)
|
||||
{
|
||||
// TODO: handle NaN and +inf/-inf
|
||||
|
@ -96,5 +104,6 @@ PRIVATE fpu_extended fp_do_log1p(fpu_extended x)
|
|||
__asm__ __volatile__("fldln2; fxch; fyl2x" : "=t" (value) : "0" (x + 1.0));
|
||||
return value;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,28 +1,33 @@
|
|||
/*
|
||||
* fpu/rounding.cpp - system-dependant FPU rounding mode and precision
|
||||
* fpu/rounding.cpp - system-dependant FPU rounding mode and precision
|
||||
*
|
||||
* Basilisk II (C) 1997-2008 Christian Bauer
|
||||
* Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
|
||||
*
|
||||
* Inspired by Christian Bauer's Basilisk II
|
||||
*
|
||||
* MC68881/68040 fpu emulation
|
||||
*
|
||||
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||
* Rewrite for x86, copyright 1999-2000 Lauri Pesonen
|
||||
* New framework, copyright 2000 Gwenole Beauchesne
|
||||
* Adapted for JIT compilation (c) Bernd Meyer, 2000
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
* This file is part of the ARAnyM project which builds a new and powerful
|
||||
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
* MC68881/68040 fpu emulation
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
|
||||
* New framework, copyright 2000-2001 Gwenole Beauchesne
|
||||
* Adapted for JIT compilation (c) Bernd Meyer, 2000-2001
|
||||
*
|
||||
* ARAnyM is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ARAnyM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ARAnyM; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#undef PRIVATE
|
||||
|
|
|
@ -1,28 +1,33 @@
|
|||
/*
|
||||
* fpu/rounding.h - system-dependant FPU rounding mode and precision
|
||||
* fpu/rounding.h - system-dependant FPU rounding mode and precision
|
||||
*
|
||||
* Basilisk II (C) 1997-2008 Christian Bauer
|
||||
* Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
|
||||
*
|
||||
* Inspired by Christian Bauer's Basilisk II
|
||||
*
|
||||
* MC68881/68040 fpu emulation
|
||||
*
|
||||
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||
* Rewrite for x86, copyright 1999-2000 Lauri Pesonen
|
||||
* New framework, copyright 2000 Gwenole Beauchesne
|
||||
* Adapted for JIT compilation (c) Bernd Meyer, 2000
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
* This file is part of the ARAnyM project which builds a new and powerful
|
||||
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
* MC68881/68040 fpu emulation
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
|
||||
* New framework, copyright 2000-2001 Gwenole Beauchesne
|
||||
* Adapted for JIT compilation (c) Bernd Meyer, 2000-2001
|
||||
*
|
||||
* ARAnyM is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ARAnyM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ARAnyM; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef FPU_ROUNDING_H
|
||||
|
@ -106,8 +111,8 @@ PRIVATE inline void set_host_control_word(void)
|
|||
*/
|
||||
x86_control_word
|
||||
= (x86_control_word & ~(X86_ROUNDING_MODE|X86_ROUNDING_PRECISION))
|
||||
| x86_control_word_rm_mac2host[(FPU fpcr.rounding_mode & FPCR_ROUNDING_MODE) >> 4]
|
||||
| x86_control_word_rp_mac2host[(FPU fpcr.rounding_precision & FPCR_ROUNDING_PRECISION) >> 6]
|
||||
| x86_control_word_rm_mac2host[(FPU fpcr & FPCR_ROUNDING_MODE) >> 4]
|
||||
| x86_control_word_rp_mac2host[(FPU fpcr & FPCR_ROUNDING_PRECISION) >> 6]
|
||||
;
|
||||
__asm__ __volatile__("fldcw %0" : : "m" (x86_control_word));
|
||||
}
|
||||
|
@ -131,11 +136,11 @@ PRIVATE inline void set_host_control_word(void)
|
|||
|
||||
/* Return the current rounding mode in m68k format */
|
||||
static inline uae_u32 FFPU get_rounding_mode(void)
|
||||
{ return FPU fpcr.rounding_mode; }
|
||||
{ return FPU fpcr & FPCR_ROUNDING_MODE; }
|
||||
|
||||
/* Convert and set to native rounding mode */
|
||||
static inline void FFPU set_rounding_mode(uae_u32 new_rounding_mode)
|
||||
{ FPU fpcr.rounding_mode = new_rounding_mode; }
|
||||
static inline void FFPU set_rounding_mode(uae_u32 /* new_rounding_mode */ )
|
||||
{ }
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -143,11 +148,11 @@ static inline void FFPU set_rounding_mode(uae_u32 new_rounding_mode)
|
|||
|
||||
/* Return the current rounding precision in m68k format */
|
||||
static inline uae_u32 FFPU get_rounding_precision(void)
|
||||
{ return FPU fpcr.rounding_precision; }
|
||||
{ return FPU fpcr & FPCR_ROUNDING_PRECISION; }
|
||||
|
||||
/* Convert and set to native rounding precision */
|
||||
static inline void FFPU set_rounding_precision(uae_u32 new_rounding_precision)
|
||||
{ FPU fpcr.rounding_precision = new_rounding_precision; }
|
||||
static inline void FFPU set_rounding_precision(uae_u32 /* new_rounding_precision */)
|
||||
{ }
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1,28 +1,33 @@
|
|||
/*
|
||||
* types.h - basic types for fpu registers
|
||||
* fpu/types.h - basic types for fpu registers
|
||||
*
|
||||
* Basilisk II (C) 1997-2008 Christian Bauer
|
||||
* Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
|
||||
*
|
||||
* Inspired by Christian Bauer's Basilisk II
|
||||
*
|
||||
* MC68881/68040 fpu emulation
|
||||
*
|
||||
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||
* Rewrite for x86, copyright 1999-2000 Lauri Pesonen
|
||||
* New framework, copyright 2000 Gwenole Beauchesne
|
||||
* Adapted for JIT compilation (c) Bernd Meyer, 2000
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
* This file is part of the ARAnyM project which builds a new and powerful
|
||||
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
* MC68881/68040 fpu emulation
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
|
||||
* New framework, copyright 2000-2001 Gwenole Beauchesne
|
||||
* Adapted for JIT compilation (c) Bernd Meyer, 2000-2001
|
||||
*
|
||||
* ARAnyM is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* ARAnyM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with ARAnyM; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef FPU_TYPES_H
|
||||
|
@ -106,9 +111,11 @@ typedef uae_f32 fpu_single;
|
|||
|
||||
#elif defined(FPU_IEEE)
|
||||
|
||||
// #if HOST_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
|
||||
// #error "No IEEE float format, you lose."
|
||||
// #endif
|
||||
#if 0
|
||||
#if HOST_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
|
||||
#error "No IEEE float format, you lose."
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* 4-byte floats */
|
||||
#if SIZEOF_FLOAT == 4
|
||||
|
@ -133,7 +140,7 @@ typedef long double uae_f64;
|
|||
typedef long double uae_f96;
|
||||
typedef uae_f96 fpu_register;
|
||||
#define USE_LONG_DOUBLE 1
|
||||
#elif SIZEOF_LONG_DOUBLE == 16 && (defined(__i386__) || defined(__x86_64__))
|
||||
#elif SIZEOF_LONG_DOUBLE == 16 && (defined(CPU_i386) || defined(CPU_x86_64) || defined(CPU_ia64))
|
||||
/* Long doubles on x86-64 are really held in old x87 FPU stack. */
|
||||
typedef long double uae_f128;
|
||||
typedef uae_f128 fpu_register;
|
||||
|
@ -154,6 +161,23 @@ typedef fpu_register fpu_extended;
|
|||
typedef uae_f64 fpu_double;
|
||||
typedef uae_f32 fpu_single;
|
||||
|
||||
#elif defined(FPU_MPFR)
|
||||
|
||||
#include <mpfr.h>
|
||||
|
||||
struct fpu_register {
|
||||
mpfr_t f;
|
||||
uae_u64 nan_bits;
|
||||
int nan_sign;
|
||||
operator long double ();
|
||||
fpu_register &operator=(long double);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
union fpu_register_parts {
|
||||
fpu_register val;
|
||||
uae_u32 parts[sizeof(fpu_register) / 4];
|
||||
};
|
||||
|
||||
#endif /* FPU_TYPES_H */
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,24 +1,35 @@
|
|||
/*
|
||||
* UAE - The Un*x Amiga Emulator
|
||||
/*
|
||||
* m68k.h - machine dependent bits
|
||||
*
|
||||
* Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
|
||||
*
|
||||
* MC68000 emulation - machine dependent bits
|
||||
* Inspired by Christian Bauer's Basilisk II
|
||||
*
|
||||
* Copyright 1996 Bernd Schmidt
|
||||
* This file is part of the ARAnyM project which builds a new and powerful
|
||||
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* ARAnyM is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* ARAnyM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* along with ARAnyM; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
/*
|
||||
* UAE - The Un*x Amiga Emulator
|
||||
*
|
||||
* MC68000 emulation - machine dependent bits
|
||||
*
|
||||
* Copyright 1996 Bernd Schmidt
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef M68K_FLAGS_H
|
||||
#define M68K_FLAGS_H
|
||||
|
|
|
@ -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:
|
||||
*/
|
|
@ -1,642 +1,59 @@
|
|||
/*
|
||||
* UAE - The Un*x Amiga Emulator
|
||||
* memory.cpp - memory management
|
||||
*
|
||||
* Memory management
|
||||
* Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
|
||||
*
|
||||
* Inspired by Christian Bauer's Basilisk II
|
||||
*
|
||||
* (c) 1995 Bernd Schmidt
|
||||
* This file is part of the ARAnyM project which builds a new and powerful
|
||||
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* ARAnyM is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* ARAnyM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* along with ARAnyM; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
/*
|
||||
* UAE - The Un*x Amiga Emulator
|
||||
*
|
||||
* Memory management
|
||||
*
|
||||
* (c) 1995 Bernd Schmidt
|
||||
*/
|
||||
|
||||
#include "sysdeps.h"
|
||||
|
||||
#include "cpu_emulation.h"
|
||||
#include "main.h"
|
||||
#include "video.h"
|
||||
|
||||
#include "m68k.h"
|
||||
#include "memory.h"
|
||||
#include "readcpu.h"
|
||||
#include "newcpu.h"
|
||||
#define DEBUG 0
|
||||
#include "debug.h"
|
||||
|
||||
#if !REAL_ADDRESSING && !DIRECT_ADDRESSING
|
||||
|
||||
static bool illegal_mem = false;
|
||||
|
||||
#ifdef SAVE_MEMORY_BANKS
|
||||
addrbank *mem_banks[65536];
|
||||
#else
|
||||
addrbank mem_banks[65536];
|
||||
#ifdef ARAM_PAGE_CHECK
|
||||
uaecptr pc_page = 0xeeeeeeee;
|
||||
uintptr pc_offset = 0;
|
||||
uaecptr read_page = 0xeeeeeeee;
|
||||
uintptr read_offset = 0;
|
||||
uaecptr write_page = 0xeeeeeeee;
|
||||
uintptr write_offset = 0;
|
||||
#endif
|
||||
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
# define swap_words(X) (X)
|
||||
#else
|
||||
# define swap_words(X) (((X) >> 16) | ((X) << 16))
|
||||
#endif
|
||||
|
||||
#ifdef NO_INLINE_MEMORY_ACCESS
|
||||
uae_u32 longget (uaecptr addr)
|
||||
extern "C" void breakpt(void)
|
||||
{
|
||||
return call_mem_get_func (get_mem_bank (addr).lget, addr);
|
||||
}
|
||||
uae_u32 wordget (uaecptr addr)
|
||||
{
|
||||
return call_mem_get_func (get_mem_bank (addr).wget, addr);
|
||||
}
|
||||
uae_u32 byteget (uaecptr addr)
|
||||
{
|
||||
return call_mem_get_func (get_mem_bank (addr).bget, addr);
|
||||
}
|
||||
void longput (uaecptr addr, uae_u32 l)
|
||||
{
|
||||
call_mem_put_func (get_mem_bank (addr).lput, addr, l);
|
||||
}
|
||||
void wordput (uaecptr addr, uae_u32 w)
|
||||
{
|
||||
call_mem_put_func (get_mem_bank (addr).wput, addr, w);
|
||||
}
|
||||
void byteput (uaecptr addr, uae_u32 b)
|
||||
{
|
||||
call_mem_put_func (get_mem_bank (addr).bput, addr, b);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* A dummy bank that only contains zeros */
|
||||
|
||||
static uae_u32 REGPARAM2 dummy_lget (uaecptr) REGPARAM;
|
||||
static uae_u32 REGPARAM2 dummy_wget (uaecptr) REGPARAM;
|
||||
static uae_u32 REGPARAM2 dummy_bget (uaecptr) REGPARAM;
|
||||
static void REGPARAM2 dummy_lput (uaecptr, uae_u32) REGPARAM;
|
||||
static void REGPARAM2 dummy_wput (uaecptr, uae_u32) REGPARAM;
|
||||
static void REGPARAM2 dummy_bput (uaecptr, uae_u32) REGPARAM;
|
||||
|
||||
uae_u32 REGPARAM2 dummy_lget (uaecptr addr)
|
||||
{
|
||||
if (illegal_mem)
|
||||
write_log ("Illegal lget at %08x\n", addr);
|
||||
|
||||
return 0;
|
||||
// bug("bus err: pc=%08x, sp=%08x, addr=%08x", m68k_getpc(), regs.regs[15], regs.mmu_fault_addr);
|
||||
}
|
||||
|
||||
uae_u32 REGPARAM2 dummy_wget (uaecptr addr)
|
||||
{
|
||||
if (illegal_mem)
|
||||
write_log ("Illegal wget at %08x\n", addr);
|
||||
#if !KNOWN_ALLOC && !NORMAL_ADDRESSING
|
||||
// This part need rewrite for ARAnyM !!
|
||||
// It can be taken from hatari.
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uae_u32 REGPARAM2 dummy_bget (uaecptr addr)
|
||||
{
|
||||
if (illegal_mem)
|
||||
write_log ("Illegal bget at %08x\n", addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void REGPARAM2 dummy_lput (uaecptr addr, uae_u32 l)
|
||||
{
|
||||
if (illegal_mem)
|
||||
write_log ("Illegal lput at %08x\n", addr);
|
||||
}
|
||||
void REGPARAM2 dummy_wput (uaecptr addr, uae_u32 w)
|
||||
{
|
||||
if (illegal_mem)
|
||||
write_log ("Illegal wput at %08x\n", addr);
|
||||
}
|
||||
void REGPARAM2 dummy_bput (uaecptr addr, uae_u32 b)
|
||||
{
|
||||
if (illegal_mem)
|
||||
write_log ("Illegal bput at %08x\n", addr);
|
||||
}
|
||||
|
||||
/* Mac RAM (32 bit addressing) */
|
||||
|
||||
static uae_u32 REGPARAM2 ram_lget(uaecptr) REGPARAM;
|
||||
static uae_u32 REGPARAM2 ram_wget(uaecptr) REGPARAM;
|
||||
static uae_u32 REGPARAM2 ram_bget(uaecptr) REGPARAM;
|
||||
static void REGPARAM2 ram_lput(uaecptr, uae_u32) REGPARAM;
|
||||
static void REGPARAM2 ram_wput(uaecptr, uae_u32) REGPARAM;
|
||||
static void REGPARAM2 ram_bput(uaecptr, uae_u32) REGPARAM;
|
||||
static uae_u8 *REGPARAM2 ram_xlate(uaecptr addr) REGPARAM;
|
||||
|
||||
static uintptr RAMBaseDiff; // RAMBaseHost - RAMBaseMac
|
||||
|
||||
uae_u32 REGPARAM2 ram_lget(uaecptr addr)
|
||||
{
|
||||
uae_u32 *m;
|
||||
m = (uae_u32 *)(RAMBaseDiff + addr);
|
||||
return do_get_mem_long(m);
|
||||
}
|
||||
|
||||
uae_u32 REGPARAM2 ram_wget(uaecptr addr)
|
||||
{
|
||||
uae_u16 *m;
|
||||
m = (uae_u16 *)(RAMBaseDiff + addr);
|
||||
return do_get_mem_word(m);
|
||||
}
|
||||
|
||||
uae_u32 REGPARAM2 ram_bget(uaecptr addr)
|
||||
{
|
||||
return (uae_u32)*(uae_u8 *)(RAMBaseDiff + addr);
|
||||
}
|
||||
|
||||
void REGPARAM2 ram_lput(uaecptr addr, uae_u32 l)
|
||||
{
|
||||
uae_u32 *m;
|
||||
m = (uae_u32 *)(RAMBaseDiff + addr);
|
||||
do_put_mem_long(m, l);
|
||||
}
|
||||
|
||||
void REGPARAM2 ram_wput(uaecptr addr, uae_u32 w)
|
||||
{
|
||||
uae_u16 *m;
|
||||
m = (uae_u16 *)(RAMBaseDiff + addr);
|
||||
do_put_mem_word(m, w);
|
||||
}
|
||||
|
||||
void REGPARAM2 ram_bput(uaecptr addr, uae_u32 b)
|
||||
{
|
||||
*(uae_u8 *)(RAMBaseDiff + addr) = b;
|
||||
}
|
||||
|
||||
uae_u8 *REGPARAM2 ram_xlate(uaecptr addr)
|
||||
{
|
||||
return (uae_u8 *)(RAMBaseDiff + addr);
|
||||
}
|
||||
|
||||
/* Mac RAM (24 bit addressing) */
|
||||
|
||||
static uae_u32 REGPARAM2 ram24_lget(uaecptr) REGPARAM;
|
||||
static uae_u32 REGPARAM2 ram24_wget(uaecptr) REGPARAM;
|
||||
static uae_u32 REGPARAM2 ram24_bget(uaecptr) REGPARAM;
|
||||
static void REGPARAM2 ram24_lput(uaecptr, uae_u32) REGPARAM;
|
||||
static void REGPARAM2 ram24_wput(uaecptr, uae_u32) REGPARAM;
|
||||
static void REGPARAM2 ram24_bput(uaecptr, uae_u32) REGPARAM;
|
||||
static uae_u8 *REGPARAM2 ram24_xlate(uaecptr addr) REGPARAM;
|
||||
|
||||
uae_u32 REGPARAM2 ram24_lget(uaecptr addr)
|
||||
{
|
||||
uae_u32 *m;
|
||||
m = (uae_u32 *)(RAMBaseDiff + (addr & 0xffffff));
|
||||
return do_get_mem_long(m);
|
||||
}
|
||||
|
||||
uae_u32 REGPARAM2 ram24_wget(uaecptr addr)
|
||||
{
|
||||
uae_u16 *m;
|
||||
m = (uae_u16 *)(RAMBaseDiff + (addr & 0xffffff));
|
||||
return do_get_mem_word(m);
|
||||
}
|
||||
|
||||
uae_u32 REGPARAM2 ram24_bget(uaecptr addr)
|
||||
{
|
||||
return (uae_u32)*(uae_u8 *)(RAMBaseDiff + (addr & 0xffffff));
|
||||
}
|
||||
|
||||
void REGPARAM2 ram24_lput(uaecptr addr, uae_u32 l)
|
||||
{
|
||||
uae_u32 *m;
|
||||
m = (uae_u32 *)(RAMBaseDiff + (addr & 0xffffff));
|
||||
do_put_mem_long(m, l);
|
||||
}
|
||||
|
||||
void REGPARAM2 ram24_wput(uaecptr addr, uae_u32 w)
|
||||
{
|
||||
uae_u16 *m;
|
||||
m = (uae_u16 *)(RAMBaseDiff + (addr & 0xffffff));
|
||||
do_put_mem_word(m, w);
|
||||
}
|
||||
|
||||
void REGPARAM2 ram24_bput(uaecptr addr, uae_u32 b)
|
||||
{
|
||||
*(uae_u8 *)(RAMBaseDiff + (addr & 0xffffff)) = b;
|
||||
}
|
||||
|
||||
uae_u8 *REGPARAM2 ram24_xlate(uaecptr addr)
|
||||
{
|
||||
return (uae_u8 *)(RAMBaseDiff + (addr & 0xffffff));
|
||||
}
|
||||
|
||||
/* Mac ROM (32 bit addressing) */
|
||||
|
||||
static uae_u32 REGPARAM2 rom_lget(uaecptr) REGPARAM;
|
||||
static uae_u32 REGPARAM2 rom_wget(uaecptr) REGPARAM;
|
||||
static uae_u32 REGPARAM2 rom_bget(uaecptr) REGPARAM;
|
||||
static void REGPARAM2 rom_lput(uaecptr, uae_u32) REGPARAM;
|
||||
static void REGPARAM2 rom_wput(uaecptr, uae_u32) REGPARAM;
|
||||
static void REGPARAM2 rom_bput(uaecptr, uae_u32) REGPARAM;
|
||||
static uae_u8 *REGPARAM2 rom_xlate(uaecptr addr) REGPARAM;
|
||||
|
||||
static uintptr ROMBaseDiff; // ROMBaseHost - ROMBaseMac
|
||||
|
||||
uae_u32 REGPARAM2 rom_lget(uaecptr addr)
|
||||
{
|
||||
uae_u32 *m;
|
||||
m = (uae_u32 *)(ROMBaseDiff + addr);
|
||||
return do_get_mem_long(m);
|
||||
}
|
||||
|
||||
uae_u32 REGPARAM2 rom_wget(uaecptr addr)
|
||||
{
|
||||
uae_u16 *m;
|
||||
m = (uae_u16 *)(ROMBaseDiff + addr);
|
||||
return do_get_mem_word(m);
|
||||
}
|
||||
|
||||
uae_u32 REGPARAM2 rom_bget(uaecptr addr)
|
||||
{
|
||||
return (uae_u32)*(uae_u8 *)(ROMBaseDiff + addr);
|
||||
}
|
||||
|
||||
void REGPARAM2 rom_lput(uaecptr addr, uae_u32 b)
|
||||
{
|
||||
if (illegal_mem)
|
||||
write_log ("Illegal ROM lput at %08x\n", addr);
|
||||
}
|
||||
|
||||
void REGPARAM2 rom_wput(uaecptr addr, uae_u32 b)
|
||||
{
|
||||
if (illegal_mem)
|
||||
write_log ("Illegal ROM wput at %08x\n", addr);
|
||||
}
|
||||
|
||||
void REGPARAM2 rom_bput(uaecptr addr, uae_u32 b)
|
||||
{
|
||||
if (illegal_mem)
|
||||
write_log ("Illegal ROM bput at %08x\n", addr);
|
||||
}
|
||||
|
||||
uae_u8 *REGPARAM2 rom_xlate(uaecptr addr)
|
||||
{
|
||||
return (uae_u8 *)(ROMBaseDiff + addr);
|
||||
}
|
||||
|
||||
/* Mac ROM (24 bit addressing) */
|
||||
|
||||
static uae_u32 REGPARAM2 rom24_lget(uaecptr) REGPARAM;
|
||||
static uae_u32 REGPARAM2 rom24_wget(uaecptr) REGPARAM;
|
||||
static uae_u32 REGPARAM2 rom24_bget(uaecptr) REGPARAM;
|
||||
static uae_u8 *REGPARAM2 rom24_xlate(uaecptr addr) REGPARAM;
|
||||
|
||||
uae_u32 REGPARAM2 rom24_lget(uaecptr addr)
|
||||
{
|
||||
uae_u32 *m;
|
||||
m = (uae_u32 *)(ROMBaseDiff + (addr & 0xffffff));
|
||||
return do_get_mem_long(m);
|
||||
}
|
||||
|
||||
uae_u32 REGPARAM2 rom24_wget(uaecptr addr)
|
||||
{
|
||||
uae_u16 *m;
|
||||
m = (uae_u16 *)(ROMBaseDiff + (addr & 0xffffff));
|
||||
return do_get_mem_word(m);
|
||||
}
|
||||
|
||||
uae_u32 REGPARAM2 rom24_bget(uaecptr addr)
|
||||
{
|
||||
return (uae_u32)*(uae_u8 *)(ROMBaseDiff + (addr & 0xffffff));
|
||||
}
|
||||
|
||||
uae_u8 *REGPARAM2 rom24_xlate(uaecptr addr)
|
||||
{
|
||||
return (uae_u8 *)(ROMBaseDiff + (addr & 0xffffff));
|
||||
}
|
||||
|
||||
/* Frame buffer */
|
||||
|
||||
static uae_u32 REGPARAM2 frame_direct_lget(uaecptr) REGPARAM;
|
||||
static uae_u32 REGPARAM2 frame_direct_wget(uaecptr) REGPARAM;
|
||||
static uae_u32 REGPARAM2 frame_direct_bget(uaecptr) REGPARAM;
|
||||
static void REGPARAM2 frame_direct_lput(uaecptr, uae_u32) REGPARAM;
|
||||
static void REGPARAM2 frame_direct_wput(uaecptr, uae_u32) REGPARAM;
|
||||
static void REGPARAM2 frame_direct_bput(uaecptr, uae_u32) REGPARAM;
|
||||
|
||||
static uae_u32 REGPARAM2 frame_host_555_lget(uaecptr) REGPARAM;
|
||||
static uae_u32 REGPARAM2 frame_host_555_wget(uaecptr) REGPARAM;
|
||||
static void REGPARAM2 frame_host_555_lput(uaecptr, uae_u32) REGPARAM;
|
||||
static void REGPARAM2 frame_host_555_wput(uaecptr, uae_u32) REGPARAM;
|
||||
|
||||
static uae_u32 REGPARAM2 frame_host_565_lget(uaecptr) REGPARAM;
|
||||
static uae_u32 REGPARAM2 frame_host_565_wget(uaecptr) REGPARAM;
|
||||
static void REGPARAM2 frame_host_565_lput(uaecptr, uae_u32) REGPARAM;
|
||||
static void REGPARAM2 frame_host_565_wput(uaecptr, uae_u32) REGPARAM;
|
||||
|
||||
static uae_u32 REGPARAM2 frame_host_888_lget(uaecptr) REGPARAM;
|
||||
static void REGPARAM2 frame_host_888_lput(uaecptr, uae_u32) REGPARAM;
|
||||
|
||||
static uae_u8 *REGPARAM2 frame_xlate(uaecptr addr) REGPARAM;
|
||||
|
||||
static uintptr FrameBaseDiff; // MacFrameBaseHost - MacFrameBaseMac
|
||||
|
||||
uae_u32 REGPARAM2 frame_direct_lget(uaecptr addr)
|
||||
{
|
||||
uae_u32 *m;
|
||||
m = (uae_u32 *)(FrameBaseDiff + addr);
|
||||
return do_get_mem_long(m);
|
||||
}
|
||||
|
||||
uae_u32 REGPARAM2 frame_direct_wget(uaecptr addr)
|
||||
{
|
||||
uae_u16 *m;
|
||||
m = (uae_u16 *)(FrameBaseDiff + addr);
|
||||
return do_get_mem_word(m);
|
||||
}
|
||||
|
||||
uae_u32 REGPARAM2 frame_direct_bget(uaecptr addr)
|
||||
{
|
||||
return (uae_u32)*(uae_u8 *)(FrameBaseDiff + addr);
|
||||
}
|
||||
|
||||
void REGPARAM2 frame_direct_lput(uaecptr addr, uae_u32 l)
|
||||
{
|
||||
uae_u32 *m;
|
||||
m = (uae_u32 *)(FrameBaseDiff + addr);
|
||||
do_put_mem_long(m, l);
|
||||
}
|
||||
|
||||
void REGPARAM2 frame_direct_wput(uaecptr addr, uae_u32 w)
|
||||
{
|
||||
uae_u16 *m;
|
||||
m = (uae_u16 *)(FrameBaseDiff + addr);
|
||||
do_put_mem_word(m, w);
|
||||
}
|
||||
|
||||
void REGPARAM2 frame_direct_bput(uaecptr addr, uae_u32 b)
|
||||
{
|
||||
*(uae_u8 *)(FrameBaseDiff + addr) = b;
|
||||
}
|
||||
|
||||
uae_u32 REGPARAM2 frame_host_555_lget(uaecptr addr)
|
||||
{
|
||||
uae_u32 *m, l;
|
||||
m = (uae_u32 *)(FrameBaseDiff + addr);
|
||||
l = *m;
|
||||
return swap_words(l);
|
||||
}
|
||||
|
||||
uae_u32 REGPARAM2 frame_host_555_wget(uaecptr addr)
|
||||
{
|
||||
uae_u16 *m;
|
||||
m = (uae_u16 *)(FrameBaseDiff + addr);
|
||||
return *m;
|
||||
}
|
||||
|
||||
void REGPARAM2 frame_host_555_lput(uaecptr addr, uae_u32 l)
|
||||
{
|
||||
uae_u32 *m;
|
||||
m = (uae_u32 *)(FrameBaseDiff + addr);
|
||||
*m = swap_words(l);
|
||||
}
|
||||
|
||||
void REGPARAM2 frame_host_555_wput(uaecptr addr, uae_u32 w)
|
||||
{
|
||||
uae_u16 *m;
|
||||
m = (uae_u16 *)(FrameBaseDiff + addr);
|
||||
*m = w;
|
||||
}
|
||||
|
||||
uae_u32 REGPARAM2 frame_host_565_lget(uaecptr addr)
|
||||
{
|
||||
uae_u32 *m, l;
|
||||
m = (uae_u32 *)(FrameBaseDiff + addr);
|
||||
l = *m;
|
||||
l = (l & 0x001f001f) | ((l >> 1) & 0x7fe07fe0);
|
||||
return swap_words(l);
|
||||
}
|
||||
|
||||
uae_u32 REGPARAM2 frame_host_565_wget(uaecptr addr)
|
||||
{
|
||||
uae_u16 *m, w;
|
||||
m = (uae_u16 *)(FrameBaseDiff + addr);
|
||||
w = *m;
|
||||
return (w & 0x1f) | ((w >> 1) & 0x7fe0);
|
||||
}
|
||||
|
||||
void REGPARAM2 frame_host_565_lput(uaecptr addr, uae_u32 l)
|
||||
{
|
||||
uae_u32 *m;
|
||||
m = (uae_u32 *)(FrameBaseDiff + addr);
|
||||
l = (l & 0x001f001f) | ((l << 1) & 0xffc0ffc0);
|
||||
*m = swap_words(l);
|
||||
}
|
||||
|
||||
void REGPARAM2 frame_host_565_wput(uaecptr addr, uae_u32 w)
|
||||
{
|
||||
uae_u16 *m;
|
||||
m = (uae_u16 *)(FrameBaseDiff + addr);
|
||||
*m = (w & 0x1f) | ((w << 1) & 0xffc0);
|
||||
}
|
||||
|
||||
uae_u32 REGPARAM2 frame_host_888_lget(uaecptr addr)
|
||||
{
|
||||
uae_u32 *m, l;
|
||||
m = (uae_u32 *)(FrameBaseDiff + addr);
|
||||
return *m;
|
||||
}
|
||||
|
||||
void REGPARAM2 frame_host_888_lput(uaecptr addr, uae_u32 l)
|
||||
{
|
||||
uae_u32 *m;
|
||||
m = (uae_u32 *)(MacFrameBaseHost + addr - MacFrameBaseMac);
|
||||
*m = l;
|
||||
}
|
||||
|
||||
uae_u8 *REGPARAM2 frame_xlate(uaecptr addr)
|
||||
{
|
||||
return (uae_u8 *)(FrameBaseDiff + addr);
|
||||
}
|
||||
|
||||
/* Mac framebuffer RAM (24 bit addressing)
|
||||
*
|
||||
* This works by duplicating appropriate writes to the 32-bit
|
||||
* address-space framebuffer.
|
||||
*/
|
||||
|
||||
static void REGPARAM2 fram24_lput(uaecptr, uae_u32) REGPARAM;
|
||||
static void REGPARAM2 fram24_wput(uaecptr, uae_u32) REGPARAM;
|
||||
static void REGPARAM2 fram24_bput(uaecptr, uae_u32) REGPARAM;
|
||||
|
||||
void REGPARAM2 fram24_lput(uaecptr addr, uae_u32 l)
|
||||
{
|
||||
uaecptr page_off = addr & 0xffff;
|
||||
if (0xa700 <= page_off && page_off < 0xfc80) {
|
||||
uae_u32 *fm;
|
||||
fm = (uae_u32 *)(MacFrameBaseHost + page_off - 0xa700);
|
||||
do_put_mem_long(fm, l);
|
||||
}
|
||||
|
||||
uae_u32 *m;
|
||||
m = (uae_u32 *)(RAMBaseDiff + (addr & 0xffffff));
|
||||
do_put_mem_long(m, l);
|
||||
}
|
||||
|
||||
void REGPARAM2 fram24_wput(uaecptr addr, uae_u32 w)
|
||||
{
|
||||
uaecptr page_off = addr & 0xffff;
|
||||
if (0xa700 <= page_off && page_off < 0xfc80) {
|
||||
uae_u16 *fm;
|
||||
fm = (uae_u16 *)(MacFrameBaseHost + page_off - 0xa700);
|
||||
do_put_mem_word(fm, w);
|
||||
}
|
||||
|
||||
uae_u16 *m;
|
||||
m = (uae_u16 *)(RAMBaseDiff + (addr & 0xffffff));
|
||||
do_put_mem_word(m, w);
|
||||
}
|
||||
|
||||
void REGPARAM2 fram24_bput(uaecptr addr, uae_u32 b)
|
||||
{
|
||||
uaecptr page_off = addr & 0xffff;
|
||||
if (0xa700 <= page_off && page_off < 0xfc80) {
|
||||
*(uae_u8 *)(MacFrameBaseHost + page_off - 0xa700) = b;
|
||||
}
|
||||
|
||||
*(uae_u8 *)(RAMBaseDiff + (addr & 0xffffff)) = b;
|
||||
}
|
||||
|
||||
/* Default memory access functions */
|
||||
|
||||
uae_u8 *REGPARAM2 default_xlate (uaecptr a)
|
||||
{
|
||||
write_log("Your Mac program just did something terribly stupid\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Address banks */
|
||||
|
||||
addrbank dummy_bank = {
|
||||
dummy_lget, dummy_wget, dummy_bget,
|
||||
dummy_lput, dummy_wput, dummy_bput,
|
||||
default_xlate
|
||||
};
|
||||
|
||||
addrbank ram_bank = {
|
||||
ram_lget, ram_wget, ram_bget,
|
||||
ram_lput, ram_wput, ram_bput,
|
||||
ram_xlate
|
||||
};
|
||||
|
||||
addrbank ram24_bank = {
|
||||
ram24_lget, ram24_wget, ram24_bget,
|
||||
ram24_lput, ram24_wput, ram24_bput,
|
||||
ram24_xlate
|
||||
};
|
||||
|
||||
addrbank rom_bank = {
|
||||
rom_lget, rom_wget, rom_bget,
|
||||
rom_lput, rom_wput, rom_bput,
|
||||
rom_xlate
|
||||
};
|
||||
|
||||
addrbank rom24_bank = {
|
||||
rom24_lget, rom24_wget, rom24_bget,
|
||||
rom_lput, rom_wput, rom_bput,
|
||||
rom24_xlate
|
||||
};
|
||||
|
||||
addrbank frame_direct_bank = {
|
||||
frame_direct_lget, frame_direct_wget, frame_direct_bget,
|
||||
frame_direct_lput, frame_direct_wput, frame_direct_bput,
|
||||
frame_xlate
|
||||
};
|
||||
|
||||
addrbank frame_host_555_bank = {
|
||||
frame_host_555_lget, frame_host_555_wget, frame_direct_bget,
|
||||
frame_host_555_lput, frame_host_555_wput, frame_direct_bput,
|
||||
frame_xlate
|
||||
};
|
||||
|
||||
addrbank frame_host_565_bank = {
|
||||
frame_host_565_lget, frame_host_565_wget, frame_direct_bget,
|
||||
frame_host_565_lput, frame_host_565_wput, frame_direct_bput,
|
||||
frame_xlate
|
||||
};
|
||||
|
||||
addrbank frame_host_888_bank = {
|
||||
frame_host_888_lget, frame_direct_wget, frame_direct_bget,
|
||||
frame_host_888_lput, frame_direct_wput, frame_direct_bput,
|
||||
frame_xlate
|
||||
};
|
||||
|
||||
addrbank fram24_bank = {
|
||||
ram24_lget, ram24_wget, ram24_bget,
|
||||
fram24_lput, fram24_wput, fram24_bput,
|
||||
ram24_xlate
|
||||
};
|
||||
|
||||
void memory_init(void)
|
||||
{
|
||||
for(long i=0; i<65536; i++)
|
||||
put_mem_bank(i<<16, &dummy_bank);
|
||||
|
||||
// Limit RAM size to not overlap ROM
|
||||
uint32 ram_size = RAMSize > ROMBaseMac ? ROMBaseMac : RAMSize;
|
||||
|
||||
RAMBaseDiff = (uintptr)RAMBaseHost - (uintptr)RAMBaseMac;
|
||||
ROMBaseDiff = (uintptr)ROMBaseHost - (uintptr)ROMBaseMac;
|
||||
FrameBaseDiff = (uintptr)MacFrameBaseHost - (uintptr)MacFrameBaseMac;
|
||||
|
||||
// Map RAM, ROM and display
|
||||
if (TwentyFourBitAddressing) {
|
||||
map_banks(&ram24_bank, RAMBaseMac >> 16, ram_size >> 16);
|
||||
map_banks(&rom24_bank, ROMBaseMac >> 16, ROMSize >> 16);
|
||||
|
||||
// Map frame buffer at end of RAM.
|
||||
map_banks(&fram24_bank, ((RAMBaseMac + ram_size) >> 16) - 1, 1);
|
||||
} else {
|
||||
map_banks(&ram_bank, RAMBaseMac >> 16, ram_size >> 16);
|
||||
map_banks(&rom_bank, ROMBaseMac >> 16, ROMSize >> 16);
|
||||
|
||||
// Map frame buffer
|
||||
switch (MacFrameLayout) {
|
||||
case FLAYOUT_DIRECT:
|
||||
map_banks(&frame_direct_bank, MacFrameBaseMac >> 16, (MacFrameSize >> 16) + 1);
|
||||
break;
|
||||
case FLAYOUT_HOST_555:
|
||||
map_banks(&frame_host_555_bank, MacFrameBaseMac >> 16, (MacFrameSize >> 16) + 1);
|
||||
break;
|
||||
case FLAYOUT_HOST_565:
|
||||
map_banks(&frame_host_565_bank, MacFrameBaseMac >> 16, (MacFrameSize >> 16) + 1);
|
||||
break;
|
||||
case FLAYOUT_HOST_888:
|
||||
map_banks(&frame_host_888_bank, MacFrameBaseMac >> 16, (MacFrameSize >> 16) + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void map_banks(addrbank *bank, int start, int size)
|
||||
{
|
||||
int bnr;
|
||||
unsigned long int hioffs = 0, endhioffs = 0x100;
|
||||
|
||||
if (start >= 0x100) {
|
||||
for (bnr = start; bnr < start + size; bnr++)
|
||||
put_mem_bank (bnr << 16, bank);
|
||||
return;
|
||||
}
|
||||
if (TwentyFourBitAddressing) endhioffs = 0x10000;
|
||||
for (hioffs = 0; hioffs < endhioffs; hioffs += 0x100)
|
||||
for (bnr = start; bnr < start+size; bnr++)
|
||||
put_mem_bank((bnr + hioffs) << 16, bank);
|
||||
}
|
||||
|
||||
#endif /* !REAL_ADDRESSING && !DIRECT_ADDRESSING */
|
||||
#error Not prepared for your platform, maybe you need memory banks from hatari
|
||||
|
||||
#endif /* !KNOWN_ALLOC && !NORMAL_ADDRESSING */
|
||||
|
|
|
@ -23,6 +23,10 @@
|
|||
#ifndef UAE_MEMORY_H
|
||||
#define UAE_MEMORY_H
|
||||
|
||||
#if DIRECT_ADDRESSING
|
||||
extern uintptr MEMBaseDiff;
|
||||
#endif
|
||||
|
||||
extern void Exception (int, uaecptr);
|
||||
#ifdef EXCEPTIONS_VIA_LONGJMP
|
||||
extern JMP_BUF excep_env;
|
||||
|
@ -50,109 +54,8 @@ extern void Exception (int, uaecptr);
|
|||
#define THROW_AGAIN(var) throw
|
||||
#define VOLATILE
|
||||
#endif /* EXCEPTIONS_VIA_LONGJMP */
|
||||
extern int in_exception_2;
|
||||
|
||||
#if !DIRECT_ADDRESSING && !REAL_ADDRESSING
|
||||
|
||||
/* Enabling this adds one additional native memory reference per 68k memory
|
||||
* access, but saves one shift (on the x86). Enabling this is probably
|
||||
* better for the cache. My favourite benchmark (PP2) doesn't show a
|
||||
* difference, so I leave this enabled. */
|
||||
|
||||
#if 1 || defined SAVE_MEMORY
|
||||
#define SAVE_MEMORY_BANKS
|
||||
#endif
|
||||
|
||||
typedef uae_u32 (REGPARAM2 *mem_get_func)(uaecptr) REGPARAM;
|
||||
typedef void (REGPARAM2 *mem_put_func)(uaecptr, uae_u32) REGPARAM;
|
||||
typedef uae_u8 *(REGPARAM2 *xlate_func)(uaecptr) REGPARAM;
|
||||
|
||||
#undef DIRECT_MEMFUNCS_SUCCESSFUL
|
||||
|
||||
#ifndef CAN_MAP_MEMORY
|
||||
#undef USE_COMPILER
|
||||
#endif
|
||||
|
||||
#if defined(USE_COMPILER) && !defined(USE_MAPPED_MEMORY)
|
||||
#define USE_MAPPED_MEMORY
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
/* These ones should be self-explanatory... */
|
||||
mem_get_func lget, wget, bget;
|
||||
mem_put_func lput, wput, bput;
|
||||
/* Use xlateaddr to translate an Amiga address to a uae_u8 * that can
|
||||
* be used to address memory without calling the wget/wput functions.
|
||||
* This doesn't work for all memory banks, so this function may call
|
||||
* abort(). */
|
||||
xlate_func xlateaddr;
|
||||
} addrbank;
|
||||
|
||||
extern uae_u8 filesysory[65536];
|
||||
|
||||
extern addrbank ram_bank; // Mac RAM
|
||||
extern addrbank rom_bank; // Mac ROM
|
||||
extern addrbank frame_bank; // Frame buffer
|
||||
|
||||
/* Default memory access functions */
|
||||
|
||||
extern uae_u8 *REGPARAM2 default_xlate(uaecptr addr) REGPARAM;
|
||||
|
||||
#define bankindex(addr) (((uaecptr)(addr)) >> 16)
|
||||
|
||||
#ifdef SAVE_MEMORY_BANKS
|
||||
extern addrbank *mem_banks[65536];
|
||||
#define get_mem_bank(addr) (*mem_banks[bankindex(addr)])
|
||||
#define put_mem_bank(addr, b) (mem_banks[bankindex(addr)] = (b))
|
||||
#else
|
||||
extern addrbank mem_banks[65536];
|
||||
#define get_mem_bank(addr) (mem_banks[bankindex(addr)])
|
||||
#define put_mem_bank(addr, b) (mem_banks[bankindex(addr)] = *(b))
|
||||
#endif
|
||||
|
||||
extern void memory_init(void);
|
||||
extern void map_banks(addrbank *bank, int first, int count);
|
||||
|
||||
#ifndef NO_INLINE_MEMORY_ACCESS
|
||||
|
||||
#define longget(addr) (call_mem_get_func(get_mem_bank(addr).lget, addr))
|
||||
#define wordget(addr) (call_mem_get_func(get_mem_bank(addr).wget, addr))
|
||||
#define byteget(addr) (call_mem_get_func(get_mem_bank(addr).bget, addr))
|
||||
#define longput(addr,l) (call_mem_put_func(get_mem_bank(addr).lput, addr, l))
|
||||
#define wordput(addr,w) (call_mem_put_func(get_mem_bank(addr).wput, addr, w))
|
||||
#define byteput(addr,b) (call_mem_put_func(get_mem_bank(addr).bput, addr, b))
|
||||
|
||||
#else
|
||||
|
||||
extern uae_u32 longget(uaecptr addr);
|
||||
extern uae_u32 wordget(uaecptr addr);
|
||||
extern uae_u32 byteget(uaecptr addr);
|
||||
extern void longput(uaecptr addr, uae_u32 l);
|
||||
extern void wordput(uaecptr addr, uae_u32 w);
|
||||
extern void byteput(uaecptr addr, uae_u32 b);
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef MD_HAVE_MEM_1_FUNCS
|
||||
|
||||
#define longget_1 longget
|
||||
#define wordget_1 wordget
|
||||
#define byteget_1 byteget
|
||||
#define longput_1 longput
|
||||
#define wordput_1 wordput
|
||||
#define byteput_1 byteput
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* !DIRECT_ADDRESSING && !REAL_ADDRESSING */
|
||||
|
||||
#if REAL_ADDRESSING
|
||||
const uintptr MEMBaseDiff = 0;
|
||||
#elif DIRECT_ADDRESSING
|
||||
extern uintptr MEMBaseDiff;
|
||||
#endif
|
||||
|
||||
#if REAL_ADDRESSING || DIRECT_ADDRESSING
|
||||
#if DIRECT_ADDRESSING
|
||||
static __inline__ uae_u8 *do_get_real_address(uaecptr addr)
|
||||
{
|
||||
return (uae_u8 *)MEMBaseDiff + addr;
|
||||
|
@ -166,71 +69,57 @@ static __inline__ uae_u32 get_long(uaecptr addr)
|
|||
uae_u32 * const m = (uae_u32 *)do_get_real_address(addr);
|
||||
return do_get_mem_long(m);
|
||||
}
|
||||
#define phys_get_long get_long
|
||||
static __inline__ uae_u32 get_word(uaecptr addr)
|
||||
{
|
||||
uae_u16 * const m = (uae_u16 *)do_get_real_address(addr);
|
||||
return do_get_mem_word(m);
|
||||
}
|
||||
#define phys_get_word get_word
|
||||
static __inline__ uae_u32 get_byte(uaecptr addr)
|
||||
{
|
||||
uae_u8 * const m = (uae_u8 *)do_get_real_address(addr);
|
||||
return do_get_mem_byte(m);
|
||||
}
|
||||
#define phys_get_byte get_byte
|
||||
static __inline__ void put_long(uaecptr addr, uae_u32 l)
|
||||
{
|
||||
uae_u32 * const m = (uae_u32 *)do_get_real_address(addr);
|
||||
do_put_mem_long(m, l);
|
||||
}
|
||||
#define phys_put_long put_long
|
||||
static __inline__ void put_word(uaecptr addr, uae_u32 w)
|
||||
{
|
||||
uae_u16 * const m = (uae_u16 *)do_get_real_address(addr);
|
||||
do_put_mem_word(m, w);
|
||||
}
|
||||
#define phys_put_word put_word
|
||||
static __inline__ void put_byte(uaecptr addr, uae_u32 b)
|
||||
{
|
||||
uae_u8 * const m = (uae_u8 *)do_get_real_address(addr);
|
||||
do_put_mem_byte(m, b);
|
||||
}
|
||||
#define phys_put_byte put_byte
|
||||
static __inline__ uae_u8 *get_real_address(uaecptr addr)
|
||||
{
|
||||
return do_get_real_address(addr);
|
||||
}
|
||||
static inline uae_u8 *get_real_address(uaecptr addr, int write, int sz)
|
||||
{
|
||||
return do_get_real_address(addr);
|
||||
}
|
||||
static inline uae_u8 *phys_get_real_address(uaecptr addr)
|
||||
{
|
||||
return do_get_real_address(addr);
|
||||
}
|
||||
static __inline__ uae_u32 get_virtual_address(uae_u8 *addr)
|
||||
{
|
||||
return do_get_virtual_address(addr);
|
||||
}
|
||||
#else
|
||||
static __inline__ uae_u32 get_long(uaecptr addr)
|
||||
{
|
||||
return longget_1(addr);
|
||||
}
|
||||
static __inline__ uae_u32 get_word(uaecptr addr)
|
||||
{
|
||||
return wordget_1(addr);
|
||||
}
|
||||
static __inline__ uae_u32 get_byte(uaecptr addr)
|
||||
{
|
||||
return byteget_1(addr);
|
||||
}
|
||||
static __inline__ void put_long(uaecptr addr, uae_u32 l)
|
||||
{
|
||||
longput_1(addr, l);
|
||||
}
|
||||
static __inline__ void put_word(uaecptr addr, uae_u32 w)
|
||||
{
|
||||
wordput_1(addr, w);
|
||||
}
|
||||
static __inline__ void put_byte(uaecptr addr, uae_u32 b)
|
||||
{
|
||||
byteput_1(addr, b);
|
||||
}
|
||||
static __inline__ uae_u8 *get_real_address(uaecptr addr)
|
||||
{
|
||||
return get_mem_bank(addr).xlateaddr(addr);
|
||||
}
|
||||
/* gb-- deliberately not implemented since it shall not be used... */
|
||||
extern uae_u32 get_virtual_address(uae_u8 *addr);
|
||||
#endif /* DIRECT_ADDRESSING || REAL_ADDRESSING */
|
||||
#endif /* DIRECT_ADDRESSING */
|
||||
|
||||
static __inline__ void check_ram_boundary(uaecptr addr, int size, bool write) {}
|
||||
static inline void flush_internals() {}
|
||||
|
||||
#endif /* MEMORY_H */
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,41 +1,51 @@
|
|||
/*
|
||||
* UAE - The Un*x Amiga Emulator
|
||||
* newcpu.h - CPU emulation
|
||||
*
|
||||
* MC68000 emulation
|
||||
* Copyright (c) 2009 ARAnyM dev team (see AUTHORS)
|
||||
*
|
||||
* Inspired by Christian Bauer's Basilisk II
|
||||
*
|
||||
* Copyright 1995 Bernd Schmidt
|
||||
* This file is part of the ARAnyM project which builds a new and powerful
|
||||
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* ARAnyM is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* ARAnyM is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* along with ARAnyM; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
/*
|
||||
* UAE - The Un*x Amiga Emulator
|
||||
*
|
||||
* MC68000 emulation
|
||||
*
|
||||
* Copyright 1995 Bernd Schmidt
|
||||
*/
|
||||
|
||||
#ifndef NEWCPU_H
|
||||
#define NEWCPU_H
|
||||
|
||||
#ifndef FLIGHT_RECORDER
|
||||
#define FLIGHT_RECORDER 0
|
||||
#endif
|
||||
|
||||
#include "m68k.h"
|
||||
#include "readcpu.h"
|
||||
#include "sysdeps.h"
|
||||
#include "registers.h"
|
||||
#include "spcflags.h"
|
||||
#include "m68k.h"
|
||||
#include "memory.h"
|
||||
|
||||
#if ENABLE_MON
|
||||
#include "mon.h"
|
||||
#include "mon_disass.h"
|
||||
#endif
|
||||
# include <csetjmp>
|
||||
|
||||
extern struct fixup {
|
||||
int flag;
|
||||
uae_u32 reg;
|
||||
uaecptr value;
|
||||
}fixup;
|
||||
|
||||
extern int areg_byteinc[];
|
||||
extern int imm8_table[];
|
||||
|
@ -57,27 +67,25 @@ extern int broken_in;
|
|||
#endif
|
||||
|
||||
#define cpuop_begin() do { cpuop_tag("begin"); } while (0)
|
||||
#define cpuop_end() do { cpuop_tag("end"); } while (0)
|
||||
#define cpuop_end() do { cpuop_tag("end"); } while (0)
|
||||
|
||||
typedef void REGPARAM2 cpuop_func (uae_u32) REGPARAM;
|
||||
|
||||
|
||||
struct cputbl {
|
||||
cpuop_func *handler;
|
||||
uae_u16 specific;
|
||||
uae_u16 opcode;
|
||||
};
|
||||
|
||||
extern cpuop_func *cpufunctbl[65536] ASM_SYM("cpufunctbl");
|
||||
extern cpuop_func *cpufunctbl[65536];
|
||||
|
||||
#if USE_JIT
|
||||
#ifdef USE_JIT
|
||||
typedef void compop_func (uae_u32) REGPARAM;
|
||||
|
||||
//NOTE: The "opcode" and "specific" fields were switched in the original source code!
|
||||
|
||||
struct comptbl {
|
||||
compop_func *handler;
|
||||
uae_u32 opcode;
|
||||
uae_u32 specific;
|
||||
uae_u32 opcode;
|
||||
uae_u32 specific;
|
||||
#define COMP_OPCODE_ISJUMP 0x0001
|
||||
#define COMP_OPCODE_LONG_OPCODE 0x0002
|
||||
#define COMP_OPCODE_CMOV 0x0004
|
||||
|
@ -88,151 +96,84 @@ struct comptbl {
|
|||
#endif
|
||||
|
||||
extern void REGPARAM2 op_illg (uae_u32) REGPARAM;
|
||||
extern void m68k_dumpstate(uaecptr *nextpc);
|
||||
|
||||
typedef char flagtype;
|
||||
|
||||
// struct regstruct {
|
||||
// uae_u32 regs[16];
|
||||
|
||||
// uae_u32 pc;
|
||||
// uae_u8 * pc_p;
|
||||
// uae_u8 * pc_oldp;
|
||||
|
||||
// spcflags_t spcflags;
|
||||
// int intmask;
|
||||
|
||||
// uae_u32 vbr, sfc, dfc;
|
||||
// uaecptr usp, isp, msp;
|
||||
// uae_u16 sr;
|
||||
// flagtype t1;
|
||||
// flagtype t0;
|
||||
// flagtype s;
|
||||
// flagtype m;
|
||||
// flagtype x;
|
||||
// flagtype stopped;
|
||||
|
||||
// #if USE_PREFETCH_BUFFER
|
||||
// /* Fellow sources say this is 4 longwords. That's impossible. It needs
|
||||
// * to be at least a longword. The HRM has some cryptic comment about two
|
||||
// * instructions being on the same longword boundary.
|
||||
// * The way this is implemented now seems like a good compromise.
|
||||
// */
|
||||
// uae_u32 prefetch;
|
||||
// #endif
|
||||
// };
|
||||
|
||||
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 1
|
||||
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;
|
||||
};
|
||||
|
||||
extern regstruct regs, lastint_regs;
|
||||
|
||||
#define m68k_dreg(r,num) ((r).regs[(num)])
|
||||
#define m68k_areg(r,num) (((r).regs + 8)[(num)])
|
||||
|
||||
#define get_ibyte(o) do_get_mem_byte((uae_u8 *)(regs.pc_p + (o) + 1))
|
||||
#define get_iword(o) do_get_mem_word((uae_u16 *)(regs.pc_p + (o)))
|
||||
#define get_ilong(o) do_get_mem_long((uae_u32 *)(regs.pc_p + (o)))
|
||||
#ifdef FULLMMU
|
||||
static ALWAYS_INLINE uae_u8 get_ibyte(uae_u32 o)
|
||||
{
|
||||
return mmu_get_byte(m68k_getpc() + o + 1, 0, sz_byte);
|
||||
}
|
||||
static ALWAYS_INLINE uae_u16 get_iword(uae_u32 o)
|
||||
{
|
||||
return mmu_get_word(m68k_getpc() + o, 0, sz_word);
|
||||
}
|
||||
static ALWAYS_INLINE uae_u32 get_ilong(uae_u32 o)
|
||||
{
|
||||
uaecptr addr = m68k_getpc() + o;
|
||||
|
||||
if (unlikely(is_unaligned(addr, 4)))
|
||||
return mmu_get_long_unaligned(addr, 0);
|
||||
return mmu_get_long(addr, 0, sz_long);
|
||||
}
|
||||
|
||||
#ifdef HAVE_GET_WORD_UNSWAPPED
|
||||
#define GET_OPCODE (do_get_mem_word_unswapped (regs.pc_p))
|
||||
#else
|
||||
#define GET_OPCODE (get_iword (0))
|
||||
#define get_ibyte(o) do_get_mem_byte((uae_u8 *)(get_real_address(m68k_getpc(), 0, sz_byte) + (o) + 1))
|
||||
#define get_iword(o) do_get_mem_word((uae_u16 *)(get_real_address(m68k_getpc(), 0, sz_word) + (o)))
|
||||
#define get_ilong(o) do_get_mem_long((uae_u32 *)(get_real_address(m68k_getpc(), 0, sz_long) + (o)))
|
||||
#endif
|
||||
|
||||
#if USE_PREFETCH_BUFFER
|
||||
static __inline__ uae_u32 get_ibyte_prefetch (uae_s32 o)
|
||||
#if 0
|
||||
static inline uae_u32 get_ibyte_prefetch (uae_s32 o)
|
||||
{
|
||||
if (o > 3 || o < 0)
|
||||
return do_get_mem_byte((uae_u8 *)(regs.pc_p + o + 1));
|
||||
return do_get_mem_byte((uae_u8 *)(do_get_real_address(regs.pcp, false, false) + o + 1));
|
||||
|
||||
return do_get_mem_byte((uae_u8 *)(((uae_u8 *)®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
|
||||
|
||||
static __inline__ void fill_prefetch_0 (void)
|
||||
#ifdef FULLMMU
|
||||
#define m68k_incpc(o) (regs.pc += (o))
|
||||
#else
|
||||
#define m68k_incpc(o) (regs.pc_p += (o))
|
||||
#endif
|
||||
|
||||
static inline void fill_prefetch_0 (void)
|
||||
{
|
||||
#if USE_PREFETCH_BUFFER
|
||||
uae_u32 r;
|
||||
#ifdef UNALIGNED_PROFITABLE
|
||||
r = *(uae_u32 *)regs.pc_p;
|
||||
r = *(uae_u32 *)do_get_real_address(m68k_getpc(), false, false);
|
||||
regs.prefetch = r;
|
||||
#else
|
||||
r = do_get_mem_long ((uae_u32 *)regs.pc_p);
|
||||
r = do_get_mem_long ((uae_u32 *)do_get_real_address(m68k_getpc(), false, false));
|
||||
do_put_mem_long (®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);
|
||||
}
|
||||
|
@ -240,115 +181,92 @@ static __inline__ void fill_prefetch_2 (void)
|
|||
#define fill_prefetch_2 fill_prefetch_0
|
||||
#endif
|
||||
|
||||
static __inline__ uaecptr m68k_getpc (void)
|
||||
{
|
||||
#if REAL_ADDRESSING || DIRECT_ADDRESSING
|
||||
return get_virtual_address(regs.pc_p);
|
||||
#else
|
||||
return regs.pc + ((char *)regs.pc_p - (char *)regs.pc_oldp);
|
||||
#endif
|
||||
}
|
||||
|
||||
static __inline__ void m68k_setpc (uaecptr newpc)
|
||||
{
|
||||
#if ENABLE_MON
|
||||
uae_u32 previous_pc = m68k_getpc();
|
||||
#endif
|
||||
|
||||
#if REAL_ADDRESSING || DIRECT_ADDRESSING
|
||||
regs.pc_p = get_real_address(newpc);
|
||||
#else
|
||||
regs.pc_p = regs.pc_oldp = get_real_address(newpc);
|
||||
regs.pc = newpc;
|
||||
#endif
|
||||
|
||||
#if ENABLE_MON
|
||||
if (IS_BREAK_POINT(newpc)) {
|
||||
printf("Stopped at break point address: %08x. Last PC: %08x\n", newpc, previous_pc);
|
||||
m68k_dumpstate(NULL);
|
||||
const char *arg[4] = {"mon", "-m", "-r", NULL};
|
||||
mon(3, arg);
|
||||
}
|
||||
#endif // end of #if ENABLE_MON
|
||||
}
|
||||
|
||||
static __inline__ void m68k_incpc (uae_s32 delta)
|
||||
{
|
||||
#if ENABLE_MON
|
||||
uae_u32 previous_pc = m68k_getpc();
|
||||
#endif
|
||||
regs.pc_p += (delta);
|
||||
#if ENABLE_MON
|
||||
uaecptr next_pc = m68k_getpc();
|
||||
if (IS_BREAK_POINT(next_pc)) {
|
||||
printf("Stopped at break point address: %08x. Last PC: %08x\n", next_pc, previous_pc);
|
||||
m68k_dumpstate(NULL);
|
||||
const char *arg[4] = {"mon", "-m", "-r", NULL};
|
||||
mon(3, arg);
|
||||
}
|
||||
#endif // end of #if ENABLE_MON
|
||||
}
|
||||
|
||||
/* These are only used by the 68020/68881 code, and therefore don't
|
||||
* need to handle prefetch. */
|
||||
static __inline__ uae_u32 next_ibyte (void)
|
||||
static inline uae_u32 next_ibyte (void)
|
||||
{
|
||||
uae_u32 r = get_ibyte (0);
|
||||
m68k_incpc (2);
|
||||
return r;
|
||||
}
|
||||
|
||||
static __inline__ uae_u32 next_iword (void)
|
||||
static inline uae_u32 next_iword (void)
|
||||
{
|
||||
uae_u32 r = get_iword (0);
|
||||
m68k_incpc (2);
|
||||
return r;
|
||||
}
|
||||
|
||||
static __inline__ uae_u32 next_ilong (void)
|
||||
static inline uae_u32 next_ilong (void)
|
||||
{
|
||||
uae_u32 r = get_ilong (0);
|
||||
m68k_incpc (4);
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline void m68k_setpc (uaecptr newpc)
|
||||
{
|
||||
#ifndef FULLMMU
|
||||
regs.pc_p = regs.pc_oldp = get_real_address(newpc, 0, sz_word);
|
||||
#endif
|
||||
regs.fault_pc = regs.pc = newpc;
|
||||
}
|
||||
|
||||
#define m68k_setpc_fast m68k_setpc
|
||||
#define m68k_setpc_bcc m68k_setpc
|
||||
#define m68k_setpc_rte m68k_setpc
|
||||
|
||||
static __inline__ void m68k_do_rts(void)
|
||||
static inline void m68k_do_rts(void)
|
||||
{
|
||||
m68k_setpc(get_long(m68k_areg(regs, 7)));
|
||||
m68k_areg(regs, 7) += 4;
|
||||
m68k_setpc(get_long(m68k_areg(regs, 7)));
|
||||
m68k_areg(regs, 7) += 4;
|
||||
}
|
||||
|
||||
static __inline__ void m68k_do_bsr(uaecptr oldpc, uae_s32 offset)
|
||||
static inline void m68k_do_bsr(uaecptr oldpc, uae_s32 offset)
|
||||
{
|
||||
m68k_areg(regs, 7) -= 4;
|
||||
put_long(m68k_areg(regs, 7), oldpc);
|
||||
m68k_incpc(offset);
|
||||
put_long(m68k_areg(regs, 7) - 4, oldpc);
|
||||
m68k_areg(regs, 7) -= 4;
|
||||
m68k_incpc(offset);
|
||||
}
|
||||
|
||||
static __inline__ void m68k_do_jsr(uaecptr oldpc, uaecptr dest)
|
||||
static inline void m68k_do_jsr(uaecptr oldpc, uaecptr dest)
|
||||
{
|
||||
m68k_areg(regs, 7) -= 4;
|
||||
put_long(m68k_areg(regs, 7), oldpc);
|
||||
m68k_setpc(dest);
|
||||
put_long(m68k_areg(regs, 7) - 4, oldpc);
|
||||
m68k_areg(regs, 7) -= 4;
|
||||
m68k_setpc(dest);
|
||||
}
|
||||
|
||||
static __inline__ void m68k_setstopped (int stop)
|
||||
static inline void m68k_setstopped (int stop)
|
||||
{
|
||||
regs.stopped = stop;
|
||||
/* A traced STOP instruction drops through immediately without
|
||||
actually stopping. */
|
||||
if (stop && (regs.spcflags & SPCFLAG_DOTRACE) == 0)
|
||||
SPCFLAGS_SET( SPCFLAG_STOP );
|
||||
if (stop && !( SPCFLAGS_TEST( SPCFLAG_DOTRACE )))
|
||||
SPCFLAGS_SET( SPCFLAG_STOP );
|
||||
}
|
||||
|
||||
extern uae_u32 get_disp_ea_020 (uae_u32 base, uae_u32 dp);
|
||||
extern uae_u32 get_disp_ea_000 (uae_u32 base, uae_u32 dp);
|
||||
#ifdef FULLMMU
|
||||
# define GET_OPCODE (get_iword (0))
|
||||
#elif defined ARAM_PAGE_CHECK
|
||||
# ifdef HAVE_GET_WORD_UNSWAPPED
|
||||
# define GET_OPCODE (do_get_mem_word_unswapped((uae_u16*)(pc + pc_offset)));
|
||||
# else
|
||||
# define GET_OPCODE (do_get_mem_word((uae_u16*)(pc + pc_offset)));
|
||||
# endif
|
||||
#else
|
||||
# ifdef HAVE_GET_WORD_UNSWAPPED
|
||||
# define GET_OPCODE (do_get_mem_word_unswapped ((uae_u16*)get_real_address(m68k_getpc(), 0, sz_word)))
|
||||
# else
|
||||
# define GET_OPCODE (get_iword (0))
|
||||
# endif
|
||||
#endif
|
||||
|
||||
extern REGPARAM uae_u32 get_disp_ea_020 (uae_u32 base, uae_u32 dp);
|
||||
extern REGPARAM uae_u32 get_disp_ea_000 (uae_u32 base, uae_u32 dp);
|
||||
extern REGPARAM uae_u32 get_bitfield(uae_u32 src, uae_u32 bdata[2], uae_s32 offset, int width);
|
||||
extern REGPARAM void put_bitfield(uae_u32 dst, uae_u32 bdata[2], uae_u32 val, uae_s32 offset, int width);
|
||||
|
||||
|
||||
extern uae_s32 ShowEA (int reg, amodes mode, wordsizes size, char *buf);
|
||||
|
||||
extern void MakeSR (void);
|
||||
extern void MakeFromSR (void);
|
||||
|
@ -360,15 +278,19 @@ extern void m68k_divl (uae_u32, uae_u32, uae_u16, uaecptr);
|
|||
extern void m68k_mull (uae_u32, uae_u32, uae_u16);
|
||||
extern void m68k_emulop (uae_u32);
|
||||
extern void m68k_emulop_return (void);
|
||||
extern void m68k_natfeat_id(void);
|
||||
extern void m68k_natfeat_call(void);
|
||||
extern void init_m68k (void);
|
||||
extern void exit_m68k (void);
|
||||
extern void m68k_dumpstate (uaecptr *);
|
||||
extern void m68k_disasm (uaecptr, uaecptr *, int);
|
||||
extern void m68k_dumpstate (FILE *, uaecptr *);
|
||||
extern void m68k_disasm (FILE *, uaecptr, uaecptr *, int);
|
||||
extern void newm68k_disasm(FILE *, uaecptr, uaecptr *, unsigned int);
|
||||
extern void showDisasm(uaecptr);
|
||||
extern void m68k_reset (void);
|
||||
extern void m68k_enter_debugger(void);
|
||||
extern int m68k_do_specialties(void);
|
||||
|
||||
extern void mmu_op (uae_u32, uae_u16);
|
||||
extern void m68k_instr_set(void);
|
||||
uae_u32 linea68000(uae_u16 opcode);
|
||||
|
||||
/* Opcode of faulting instruction */
|
||||
extern uae_u16 last_op_for_exception_3;
|
||||
|
@ -379,24 +301,19 @@ extern uaecptr last_fault_for_exception_3;
|
|||
|
||||
#define CPU_OP_NAME(a) op ## a
|
||||
|
||||
/* 68020 + 68881 */
|
||||
extern struct cputbl op_smalltbl_0_ff[];
|
||||
/* 68020 */
|
||||
extern struct cputbl op_smalltbl_1_ff[];
|
||||
/* 68010 */
|
||||
extern struct cputbl op_smalltbl_2_ff[];
|
||||
/* 68000 */
|
||||
extern struct cputbl op_smalltbl_3_ff[];
|
||||
/* 68000 slow but compatible. */
|
||||
extern struct cputbl op_smalltbl_4_ff[];
|
||||
/* 68040+ 68881 */
|
||||
extern const struct cputbl op_smalltbl_0_ff[];
|
||||
extern const struct cputbl op_smalltbl_0_nf[];
|
||||
|
||||
#if FLIGHT_RECORDER
|
||||
extern void m68k_record_step(uaecptr) REGPARAM;
|
||||
#ifdef FLIGHT_RECORDER
|
||||
extern void m68k_record_step(uaecptr, int);
|
||||
#endif
|
||||
|
||||
extern void m68k_do_execute(void);
|
||||
extern void m68k_execute(void);
|
||||
#if USE_JIT
|
||||
#ifdef USE_JIT
|
||||
extern void m68k_compile_execute(void);
|
||||
extern void m68k_do_compile_execute(void);
|
||||
#endif
|
||||
#ifdef USE_CPU_EMUL_SERVICES
|
||||
extern int32 emulated_ticks;
|
||||
|
@ -411,5 +328,7 @@ static inline void cpu_check_ticks(void)
|
|||
#define cpu_check_ticks()
|
||||
#define cpu_do_check_ticks()
|
||||
#endif
|
||||
|
||||
|
||||
cpuop_func op_illg_1;
|
||||
|
||||
#endif /* NEWCPU_H */
|
||||
|
|
|
@ -33,13 +33,13 @@
|
|||
#define NOFLAGS_CMP 0
|
||||
|
||||
#undef SET_NFLG_ALWAYS
|
||||
static __inline__ void SET_NFLG_ALWAYS(uae_u32 x)
|
||||
static inline void SET_NFLG_ALWAYS(uae_u32 x)
|
||||
{
|
||||
SET_NFLG(x); /* This has not yet been redefined */
|
||||
}
|
||||
|
||||
#undef SET_CFLG_ALWAYS
|
||||
static __inline__ void SET_CFLG_ALWAYS(uae_u32 x)
|
||||
static inline void SET_CFLG_ALWAYS(uae_u32 x)
|
||||
{
|
||||
SET_CFLG(x); /* This has not yet been redefined */
|
||||
}
|
||||
|
@ -62,13 +62,13 @@ static __inline__ void SET_CFLG_ALWAYS(uae_u32 x)
|
|||
#define SET_XFLG(y) do {uae_u32 dummy=(y); } while (0)
|
||||
|
||||
#undef CLEAR_CZNV
|
||||
#define CLEAR_CZNV() do {} while (0)
|
||||
#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() do {} while (0)
|
||||
#define COPY_CARRY()
|
||||
|
||||
#ifdef optflag_testl
|
||||
#undef optflag_testl
|
||||
|
|
|
@ -1,34 +1,30 @@
|
|||
/* 2002 MJ */
|
||||
/*
|
||||
* UAE - The Un*x Amiga Emulator
|
||||
*
|
||||
* Read 68000 CPU specs from file "table68k"
|
||||
*
|
||||
* Copyright 1995,1996 Bernd Schmidt
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "sysdeps.h"
|
||||
#include "readcpu.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <cctype>
|
||||
|
||||
using std::strncmp;
|
||||
using std::abort;
|
||||
using std::fprintf;
|
||||
using std::strcmp;
|
||||
using std::strlen;
|
||||
using std::malloc;
|
||||
|
||||
int nr_cpuop_funcs;
|
||||
struct instr *table68k;
|
||||
static int readcpu_mismatch;
|
||||
|
||||
struct mnemolookup lookuptab[] = {
|
||||
{ i_ILLG, "ILLEGAL" },
|
||||
|
@ -153,16 +149,19 @@ struct mnemolookup lookuptab[] = {
|
|||
{ i_CPUSHA, "CPUSHA" },
|
||||
{ i_MOVE16, "MOVE16" },
|
||||
|
||||
{ i_EMULOP_RETURN, "EMULOP_RETURN" },
|
||||
{ i_EMULOP, "EMULOP" },
|
||||
|
||||
{ i_EMULOP_RETURN, "EMULOP_RETURN" },
|
||||
{ i_EMULOP, "EMULOP" },
|
||||
|
||||
{ i_MMUOP, "MMUOP" },
|
||||
|
||||
{i_NATFEAT_ID, "NATFEAT_ID" },
|
||||
{i_NATFEAT_CALL, "NATFEAT_CALL" },
|
||||
|
||||
{ i_ILLG, "" },
|
||||
};
|
||||
|
||||
struct instr *table68k;
|
||||
|
||||
static __inline__ amodes mode_from_str (const char *str)
|
||||
static inline amodes mode_from_str (const char *str)
|
||||
{
|
||||
if (strncmp (str, "Dreg", 4) == 0) return Dreg;
|
||||
if (strncmp (str, "Areg", 4) == 0) return Areg;
|
||||
|
@ -180,7 +179,7 @@ static __inline__ amodes mode_from_str (const char *str)
|
|||
return (amodes)0;
|
||||
}
|
||||
|
||||
static __inline__ amodes mode_from_mr (int mode, int reg)
|
||||
static inline amodes mode_from_mr (int mode, int reg)
|
||||
{
|
||||
switch (mode) {
|
||||
case 0: return Dreg;
|
||||
|
@ -215,31 +214,32 @@ static void build_insn (int insn)
|
|||
int i, n;
|
||||
|
||||
int flaglive = 0, flagdead = 0;
|
||||
int cflow = 0;
|
||||
int cflow = 0;
|
||||
|
||||
id = defs68k[insn];
|
||||
|
||||
// Control flow information
|
||||
cflow = id.cflow;
|
||||
|
||||
// Mask of flags set/used
|
||||
unsigned char flags_set(0), flags_used(0);
|
||||
|
||||
for (i = 0, n = 4; i < 5; i++, n--) {
|
||||
switch (id.flaginfo[i].flagset) {
|
||||
case fa_unset: case fa_isjmp: break;
|
||||
default: flags_set |= (1 << n);
|
||||
}
|
||||
|
||||
switch (id.flaginfo[i].flaguse) {
|
||||
case fu_unused: case fu_isjmp: break;
|
||||
default: flags_used |= (1 << n);
|
||||
}
|
||||
// Control flow information
|
||||
cflow = id.cflow;
|
||||
|
||||
// Mask of flags set/used
|
||||
unsigned char flags_set(0), flags_used(0);
|
||||
|
||||
for (i = 0, n = 4; i < 5; i++, n--) {
|
||||
switch (id.flaginfo[i].flagset) {
|
||||
case fa_unset: case fa_isjmp: break;
|
||||
default: flags_set |= (1 << n);
|
||||
}
|
||||
|
||||
|
||||
switch (id.flaginfo[i].flaguse) {
|
||||
case fu_unused: case fu_isjmp: break;
|
||||
default: flags_used |= (1 << n);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < 5; i++) {
|
||||
switch (id.flaginfo[i].flagset){
|
||||
case fa_unset: break;
|
||||
case fa_isjmp: break;
|
||||
case fa_zero: flagdead |= 1 << i; break;
|
||||
case fa_one: flagdead |= 1 << i; break;
|
||||
case fa_dontcare: flagdead |= 1 << i; break;
|
||||
|
@ -252,6 +252,8 @@ static void build_insn (int insn)
|
|||
for (i = 0; i < 5; i++) {
|
||||
switch (id.flaginfo[i].flaguse) {
|
||||
case fu_unused: break;
|
||||
case fu_isjmp: flaglive |= 1 << i; break;
|
||||
case fu_maybecc: flaglive |= 1 << i; break;
|
||||
case fu_unknown: flaglive = -1; goto out2;
|
||||
case fu_used: flaglive |= 1 << i; break;
|
||||
}
|
||||
|
@ -306,6 +308,7 @@ static void build_insn (int insn)
|
|||
continue;
|
||||
if (bitcnt[bitI] && (bitval[bitI] == 0x00 || bitval[bitI] == 0xff))
|
||||
continue;
|
||||
|
||||
if (bitcnt[bitE] && (bitval[bitE] == 0x00))
|
||||
continue;
|
||||
|
||||
|
@ -346,9 +349,9 @@ static void build_insn (int insn)
|
|||
}
|
||||
}
|
||||
mnp++;
|
||||
if ((unsigned)mnp >= sizeof(mnemonic) - 1) {
|
||||
mnemonic[sizeof(mnemonic) - 1] = 0;
|
||||
fprintf(stderr, "Instruction %s overflow\n", mnemonic);
|
||||
if ((unsigned)mnp >= (sizeof(mnemonic)-1)) {
|
||||
mnemonic[sizeof(mnemonic)-1] = '\0';
|
||||
fprintf(stderr, "WTF!!! Instruction '%s' overflow\n", mnemonic);
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
@ -379,6 +382,7 @@ static void build_insn (int insn)
|
|||
case 'A':
|
||||
srcmode = Areg;
|
||||
switch (opcstr[pos++]) {
|
||||
case 'l': srcmode = absl; break;
|
||||
case 'r': srcreg = bitval[bitr]; srcgather = 1; srcpos = bitpos[bitr]; break;
|
||||
case 'R': srcreg = bitval[bitR]; srcgather = 1; srcpos = bitpos[bitR]; break;
|
||||
default: abort();
|
||||
|
@ -388,9 +392,11 @@ static void build_insn (int insn)
|
|||
case 'P': srcmode = Aipi; pos++; break;
|
||||
}
|
||||
break;
|
||||
#if 0
|
||||
case 'L':
|
||||
srcmode = absl;
|
||||
break;
|
||||
#endif
|
||||
case '#':
|
||||
switch (opcstr[pos++]) {
|
||||
case 'z': srcmode = imm; break;
|
||||
|
@ -436,7 +442,7 @@ static void build_insn (int insn)
|
|||
srcpos = bitpos[bitK];
|
||||
}
|
||||
break;
|
||||
case 'E': srcmode = immi; srcreg = bitval[bitE];
|
||||
case 'E': srcmode = immi; srcreg = bitval[bitE];
|
||||
if (CPU_EMU_SIZE < 5) { // gb-- what is CPU_EMU_SIZE used for ??
|
||||
/* 1..255 */
|
||||
srcgather = 1;
|
||||
|
@ -444,8 +450,8 @@ static void build_insn (int insn)
|
|||
srcpos = bitpos[bitE];
|
||||
}
|
||||
break;
|
||||
case 'p': srcmode = immi; srcreg = bitval[bitp];
|
||||
if (CPU_EMU_SIZE < 5) {
|
||||
case 'p': srcmode = immi; srcreg = bitval[bitp];
|
||||
if (CPU_EMU_SIZE < 5) { // gb-- what is CPU_EMU_SIZE used for ??
|
||||
/* 0..3 */
|
||||
srcgather = 1;
|
||||
srctype = 7;
|
||||
|
@ -582,21 +588,22 @@ static void build_insn (int insn)
|
|||
case 'A':
|
||||
destmode = Areg;
|
||||
switch (opcstr[pos++]) {
|
||||
case 'l': destmode = absl; break;
|
||||
case 'r': destreg = bitval[bitr]; dstgather = 1; dstpos = bitpos[bitr]; break;
|
||||
case 'R': destreg = bitval[bitR]; dstgather = 1; dstpos = bitpos[bitR]; break;
|
||||
case 'x': destreg = 0; dstgather = 0; dstpos = 0; break;
|
||||
case 'x': destreg = 0; dstgather = 0; dstpos = 0; break;
|
||||
default: abort();
|
||||
}
|
||||
if (dstpos < 0 || dstpos >= 32)
|
||||
abort();
|
||||
switch (opcstr[pos]) {
|
||||
case 'p': destmode = Apdi; pos++; break;
|
||||
case 'P': destmode = Aipi; pos++; break;
|
||||
}
|
||||
break;
|
||||
#if 0
|
||||
case 'L':
|
||||
destmode = absl;
|
||||
break;
|
||||
#endif
|
||||
case '#':
|
||||
switch (opcstr[pos++]) {
|
||||
case 'z': destmode = imm; break;
|
||||
|
@ -767,7 +774,7 @@ static void build_insn (int insn)
|
|||
table68k[opc].flaginfo[i].flaguse = id.flaginfo[i].flaguse;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// Fix flags used information for Scc, Bcc, TRAPcc, DBcc instructions
|
||||
if ( table68k[opc].mnemo == i_Scc
|
||||
|| table68k[opc].mnemo == i_Bcc
|
||||
|
@ -795,7 +802,7 @@ static void build_insn (int insn)
|
|||
case 15:flags_used = 0x0E; break; /* LE */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if 1
|
||||
/* gb-- flagdead and flaglive would not have correct information */
|
||||
table68k[opc].flagdead = flags_set;
|
||||
|
@ -811,22 +818,6 @@ static void build_insn (int insn)
|
|||
}
|
||||
|
||||
|
||||
void read_table68k (void)
|
||||
{
|
||||
int i;
|
||||
|
||||
table68k = (struct instr *)malloc (65536 * sizeof (struct instr));
|
||||
for (i = 0; i < 65536; i++) {
|
||||
table68k[i].mnemo = i_ILLG;
|
||||
table68k[i].handler = -1;
|
||||
}
|
||||
for (i = 0; i < n_defs68k; i++) {
|
||||
build_insn (i);
|
||||
}
|
||||
}
|
||||
|
||||
static int mismatch;
|
||||
|
||||
static void handle_merges (long int opcode)
|
||||
{
|
||||
uae_u16 smsk;
|
||||
|
@ -851,9 +842,9 @@ static void handle_merges (long int opcode)
|
|||
case 5:
|
||||
smsk = 63; sbitdst = 64; break;
|
||||
case 6:
|
||||
smsk = 255; sbitdst = 256; break;
|
||||
smsk = 255; sbitdst = 256; break;
|
||||
case 7:
|
||||
smsk = 3; sbitdst = 4; break;
|
||||
smsk = 3; sbitdst = 4; break;
|
||||
default:
|
||||
smsk = 0; sbitdst = 0;
|
||||
abort();
|
||||
|
@ -869,7 +860,7 @@ static void handle_merges (long int opcode)
|
|||
}
|
||||
for (srcreg=0; srcreg < sbitdst; srcreg++) {
|
||||
for (dstreg=0; dstreg < dstend; dstreg++) {
|
||||
uae_u16 code = uae_u16(opcode);
|
||||
uae_u16 code = opcode;
|
||||
|
||||
code = (code & ~smsk) | (srcreg << table68k[opcode].spos);
|
||||
code = (code & ~dmsk) | (dstreg << table68k[opcode].dpos);
|
||||
|
@ -882,20 +873,20 @@ static void handle_merges (long int opcode)
|
|||
|| table68k[code].suse != table68k[opcode].suse
|
||||
|| table68k[code].duse != table68k[opcode].duse)
|
||||
{
|
||||
mismatch++; continue;
|
||||
readcpu_mismatch++; continue;
|
||||
}
|
||||
if (table68k[opcode].suse
|
||||
&& (table68k[opcode].spos != table68k[code].spos
|
||||
|| table68k[opcode].smode != table68k[code].smode
|
||||
|| table68k[opcode].stype != table68k[code].stype))
|
||||
{
|
||||
mismatch++; continue;
|
||||
readcpu_mismatch++; continue;
|
||||
}
|
||||
if (table68k[opcode].duse
|
||||
&& (table68k[opcode].dpos != table68k[code].dpos
|
||||
|| table68k[opcode].dmode != table68k[code].dmode))
|
||||
{
|
||||
mismatch++; continue;
|
||||
readcpu_mismatch++; continue;
|
||||
}
|
||||
|
||||
if (code != opcode)
|
||||
|
@ -904,11 +895,11 @@ static void handle_merges (long int opcode)
|
|||
}
|
||||
}
|
||||
|
||||
void do_merges (void)
|
||||
static void do_merges (void)
|
||||
{
|
||||
long int opcode;
|
||||
int nr = 0;
|
||||
mismatch = 0;
|
||||
readcpu_mismatch = 0;
|
||||
for (opcode = 0; opcode < 65536; opcode++) {
|
||||
if (table68k[opcode].handler != -1 || table68k[opcode].mnemo == i_ILLG)
|
||||
continue;
|
||||
|
@ -918,116 +909,26 @@ void do_merges (void)
|
|||
nr_cpuop_funcs = nr;
|
||||
}
|
||||
|
||||
int get_no_mismatches (void)
|
||||
{
|
||||
return mismatch;
|
||||
}
|
||||
|
||||
const char *get_instruction_name (unsigned int opcode)
|
||||
void init_table68k (void)
|
||||
{
|
||||
struct instr *ins = &table68k[opcode];
|
||||
for (int i = 0; lookuptab[i].name[0]; i++) {
|
||||
if (ins->mnemo == lookuptab[i].mnemo)
|
||||
return lookuptab[i].name;
|
||||
int i;
|
||||
|
||||
free(table68k);
|
||||
table68k = (struct instr *)malloc (65536 * sizeof (struct instr));
|
||||
for (i = 0; i < 65536; i++) {
|
||||
table68k[i].mnemo = i_ILLG;
|
||||
table68k[i].handler = -1;
|
||||
}
|
||||
abort();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static char *get_ea_string (amodes mode, wordsizes size)
|
||||
{
|
||||
static char buffer[80];
|
||||
|
||||
buffer[0] = 0;
|
||||
switch (mode){
|
||||
case Dreg:
|
||||
strcpy (buffer,"Dn");
|
||||
break;
|
||||
case Areg:
|
||||
strcpy (buffer,"An");
|
||||
break;
|
||||
case Aind:
|
||||
strcpy (buffer,"(An)");
|
||||
break;
|
||||
case Aipi:
|
||||
strcpy (buffer,"(An)+");
|
||||
break;
|
||||
case Apdi:
|
||||
strcpy (buffer,"-(An)");
|
||||
break;
|
||||
case Ad16:
|
||||
strcpy (buffer,"(d16,An)");
|
||||
break;
|
||||
case Ad8r:
|
||||
strcpy (buffer,"(d8,An,Xn)");
|
||||
break;
|
||||
case PC16:
|
||||
strcpy (buffer,"(d16,PC)");
|
||||
break;
|
||||
case PC8r:
|
||||
strcpy (buffer,"(d8,PC,Xn)");
|
||||
break;
|
||||
case absw:
|
||||
strcpy (buffer,"(xxx).W");
|
||||
break;
|
||||
case absl:
|
||||
strcpy (buffer,"(xxx).L");
|
||||
break;
|
||||
case imm:
|
||||
switch (size){
|
||||
case sz_byte:
|
||||
strcpy (buffer,"#<data>.B");
|
||||
break;
|
||||
case sz_word:
|
||||
strcpy (buffer,"#<data>.W");
|
||||
break;
|
||||
case sz_long:
|
||||
strcpy (buffer,"#<data>.L");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case imm0:
|
||||
strcpy (buffer,"#<data>.B");
|
||||
break;
|
||||
case imm1:
|
||||
strcpy (buffer,"#<data>.W");
|
||||
break;
|
||||
case imm2:
|
||||
strcpy (buffer,"#<data>.L");
|
||||
break;
|
||||
case immi:
|
||||
strcpy (buffer,"#<data>");
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
for (i = 0; i < n_defs68k; i++) {
|
||||
build_insn (i);
|
||||
}
|
||||
return buffer;
|
||||
do_merges();
|
||||
}
|
||||
|
||||
const char *get_instruction_string (unsigned int opcode)
|
||||
|
||||
void exit_table68k (void)
|
||||
{
|
||||
static char out[100];
|
||||
struct instr *ins;
|
||||
|
||||
strcpy (out, get_instruction_name (opcode));
|
||||
|
||||
ins = &table68k[opcode];
|
||||
if (ins->size == sz_byte)
|
||||
strcat (out,".B");
|
||||
if (ins->size == sz_word)
|
||||
strcat (out,".W");
|
||||
if (ins->size == sz_long)
|
||||
strcat (out,".L");
|
||||
strcat (out," ");
|
||||
if (ins->suse)
|
||||
strcat (out, get_ea_string (amodes(ins->smode), wordsizes(ins->size)));
|
||||
if (ins->duse) {
|
||||
if (ins->suse)
|
||||
strcat (out,",");
|
||||
strcat (out, get_ea_string (amodes(ins->dmode), wordsizes(ins->size)));
|
||||
}
|
||||
return out;
|
||||
free(table68k);
|
||||
table68k = NULL;
|
||||
}
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
#ifndef READCPU_H
|
||||
#define READCPU_H
|
||||
#ifndef UAE_READCPU_H
|
||||
#define UAE_READCPU_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
ENUMDECL {
|
||||
typedef enum {
|
||||
Dreg, Areg, Aind, Aipi, Apdi, Ad16, Ad8r,
|
||||
absw, absl, PC16, PC8r, imm, imm0, imm1, imm2, immi, am_unknown, am_illg
|
||||
} ENUMNAME (amodes);
|
||||
} amodes;
|
||||
|
||||
ENUMDECL {
|
||||
typedef enum {
|
||||
i_ILLG,
|
||||
|
||||
i_OR, i_AND, i_EOR, i_ORSR, i_ANDSR, i_EORSR,
|
||||
|
@ -35,43 +35,42 @@ ENUMDECL {
|
|||
i_PACK, i_UNPK, i_TAS, i_BKPT, i_CALLM, i_RTM, i_TRAPcc, i_MOVES,
|
||||
i_FPP, i_FDBcc, i_FScc, i_FTRAPcc, i_FBcc, i_FSAVE, i_FRESTORE,
|
||||
i_CINVL, i_CINVP, i_CINVA, i_CPUSHL, i_CPUSHP, i_CPUSHA, i_MOVE16,
|
||||
i_MMUOP,
|
||||
i_EMULOP_RETURN, i_EMULOP
|
||||
} ENUMNAME (instrmnem);
|
||||
i_MMUOP, i_EMULOP_RETURN, i_EMULOP, i_NATFEAT_ID, i_NATFEAT_CALL
|
||||
} instrmnem;
|
||||
|
||||
extern struct mnemolookup {
|
||||
instrmnem mnemo;
|
||||
const char *name;
|
||||
} lookuptab[];
|
||||
|
||||
ENUMDECL {
|
||||
typedef enum {
|
||||
sz_byte, sz_word, sz_long
|
||||
} ENUMNAME (wordsizes);
|
||||
} wordsizes;
|
||||
|
||||
ENUMDECL {
|
||||
fa_set, fa_unset, fa_zero, fa_one, fa_dontcare, fa_unknown, fa_isjmp
|
||||
} ENUMNAME (flagaffect);
|
||||
typedef enum {
|
||||
fa_set, fa_unset, fa_zero, fa_one, fa_dontcare, fa_unknown, fa_isjmp,
|
||||
fa_isbranch
|
||||
} flagaffect;
|
||||
|
||||
ENUMDECL {
|
||||
typedef enum {
|
||||
fu_used, fu_unused, fu_maybecc, fu_unknown, fu_isjmp
|
||||
} ENUMNAME (flaguse);
|
||||
} flaguse;
|
||||
|
||||
ENUMDECL {
|
||||
fl_normal = 0,
|
||||
typedef enum {
|
||||
fl_normal = 0,
|
||||
fl_branch = 1,
|
||||
fl_jump = 2,
|
||||
fl_return = 3,
|
||||
fl_trap = 4,
|
||||
fl_const_jump = 8,
|
||||
|
||||
/* Instructions that can trap don't mark the end of a block */
|
||||
fl_end_block = 3
|
||||
} ENUMNAME (cflow_t);
|
||||
fl_jump = 2,
|
||||
fl_return = 3,
|
||||
fl_trap = 4,
|
||||
fl_const_jump = 8,
|
||||
/* Instructions that can trap don't mark the end of a block */
|
||||
fl_end_block = 3
|
||||
} cflow_t;
|
||||
|
||||
ENUMDECL {
|
||||
typedef enum {
|
||||
bit0, bit1, bitc, bitC, bitf, biti, bitI, bitj, bitJ, bitk, bitK,
|
||||
bits, bitS, bitd, bitD, bitr, bitR, bitz, bitE, bitp, lastbit
|
||||
} ENUMNAME (bitvals);
|
||||
} bitvals;
|
||||
|
||||
struct instr_def {
|
||||
unsigned int bits;
|
||||
|
@ -84,7 +83,7 @@ struct instr_def {
|
|||
unsigned int flaguse:3;
|
||||
unsigned int flagset:3;
|
||||
} flaginfo[5];
|
||||
unsigned char cflow;
|
||||
unsigned char cflow;
|
||||
unsigned char sduse;
|
||||
const char *opcstr;
|
||||
};
|
||||
|
@ -103,28 +102,24 @@ extern struct instr {
|
|||
unsigned int mnemo:8;
|
||||
unsigned int cc:4;
|
||||
unsigned int plev:2;
|
||||
unsigned int size:2;
|
||||
unsigned int smode:5;
|
||||
wordsizes size:2;
|
||||
amodes smode:5;
|
||||
unsigned int stype:3;
|
||||
unsigned int dmode:5;
|
||||
amodes dmode:5;
|
||||
unsigned int suse:1;
|
||||
unsigned int duse:1;
|
||||
unsigned int unused1:1;
|
||||
unsigned int clev:3;
|
||||
unsigned int cflow:3;
|
||||
unsigned int cflow:3;
|
||||
unsigned int unused2:2;
|
||||
} *table68k;
|
||||
|
||||
extern void read_table68k (void);
|
||||
extern void do_merges (void);
|
||||
extern int get_no_mismatches (void);
|
||||
extern void init_table68k(void);
|
||||
extern void exit_table68k(void);
|
||||
extern int nr_cpuop_funcs;
|
||||
|
||||
extern const char *get_instruction_name (unsigned int opcode);
|
||||
extern const char *get_instruction_string (unsigned int opcode);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* READCPU_H */
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
/*
|
||||
* readcpu.cpp must be compiled twice, once for the generator program
|
||||
* and once for the actual executable
|
||||
*/
|
||||
#include "readcpu.cpp"
|
|
@ -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;
|
||||
|
||||
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
|
|
@ -1,92 +1,78 @@
|
|||
/*
|
||||
* UAE - The Un*x Amiga Emulator
|
||||
*
|
||||
* MC68000 emulation
|
||||
*
|
||||
* Copyright 1995 Bernd Schmidt
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
/*
|
||||
* UAE - The Un*x Amiga Emulator
|
||||
*
|
||||
* MC68000 emulation
|
||||
*
|
||||
* Copyright 1995 Bernd Schmidt
|
||||
*/
|
||||
|
||||
#ifndef SPCFLAGS_H
|
||||
#define SPCFLAGS_H
|
||||
|
||||
typedef uae_u32 spcflags_t;
|
||||
#if 0
|
||||
#include "SDL_compat.h"
|
||||
#endif
|
||||
|
||||
enum {
|
||||
SPCFLAG_STOP = 0x01,
|
||||
SPCFLAG_INT = 0x02,
|
||||
SPCFLAG_BRK = 0x04,
|
||||
SPCFLAG_TRACE = 0x08,
|
||||
SPCFLAG_DOTRACE = 0x10,
|
||||
SPCFLAG_DOINT = 0x20,
|
||||
#if USE_JIT
|
||||
SPCFLAG_JIT_END_COMPILE = 0x40,
|
||||
SPCFLAG_JIT_EXEC_RETURN = 0x80,
|
||||
SPCFLAG_STOP = 0x01,
|
||||
#if 0
|
||||
SPCFLAG_INTERNAL_IRQ = 0x02,
|
||||
#else
|
||||
SPCFLAG_JIT_END_COMPILE = 0,
|
||||
SPCFLAG_JIT_EXEC_RETURN = 0,
|
||||
SPCFLAG_INT = 0x02,
|
||||
#endif
|
||||
|
||||
SPCFLAG_ALL = SPCFLAG_STOP
|
||||
| SPCFLAG_INT
|
||||
| SPCFLAG_BRK
|
||||
| SPCFLAG_TRACE
|
||||
| SPCFLAG_DOTRACE
|
||||
| SPCFLAG_DOINT
|
||||
| SPCFLAG_JIT_END_COMPILE
|
||||
| SPCFLAG_JIT_EXEC_RETURN
|
||||
,
|
||||
|
||||
SPCFLAG_BRK = 0x04,
|
||||
SPCFLAG_TRACE = 0x08,
|
||||
SPCFLAG_DOTRACE = 0x10,
|
||||
SPCFLAG_DOINT = 0x20,
|
||||
#ifdef USE_JIT
|
||||
SPCFLAG_JIT_END_COMPILE = 0x40,
|
||||
SPCFLAG_JIT_EXEC_RETURN = 0x80,
|
||||
#else
|
||||
SPCFLAG_JIT_END_COMPILE = 0,
|
||||
SPCFLAG_JIT_EXEC_RETURN = 0,
|
||||
#endif
|
||||
SPCFLAG_VBL = 0x100,
|
||||
SPCFLAG_MFP = 0x200,
|
||||
SPCFLAG_INT3 = 0x800,
|
||||
SPCFLAG_INT5 = 0x1000,
|
||||
SPCFLAG_SCC = 0x2000,
|
||||
// SPCFLAG_MODE_CHANGE = 0x4000,
|
||||
SPCFLAG_ALL = SPCFLAG_STOP
|
||||
#if 0
|
||||
| SPCFLAG_INTERNAL_IRQ
|
||||
#else
|
||||
| SPCFLAG_INT
|
||||
#endif
|
||||
| SPCFLAG_BRK
|
||||
| SPCFLAG_TRACE
|
||||
| SPCFLAG_DOTRACE
|
||||
| SPCFLAG_DOINT
|
||||
| SPCFLAG_JIT_END_COMPILE
|
||||
| SPCFLAG_JIT_EXEC_RETURN
|
||||
| SPCFLAG_INT3
|
||||
| SPCFLAG_VBL
|
||||
| SPCFLAG_INT5
|
||||
| SPCFLAG_SCC
|
||||
| SPCFLAG_MFP
|
||||
,
|
||||
|
||||
SPCFLAG_ALL_BUT_EXEC_RETURN = SPCFLAG_ALL & ~SPCFLAG_JIT_EXEC_RETURN
|
||||
|
||||
};
|
||||
|
||||
#if 0
|
||||
#define SPCFLAGS_TEST(m) \
|
||||
(regs.spcflags & (m))
|
||||
#else
|
||||
#define SPCFLAGS_TEST(m) \
|
||||
((regs.spcflags & (m)) != 0)
|
||||
#endif
|
||||
|
||||
/* Macro only used in m68k_reset() */
|
||||
#define SPCFLAGS_INIT(m) do { \
|
||||
regs.spcflags = (m); \
|
||||
} while (0)
|
||||
|
||||
#if !(ENABLE_EXCLUSIVE_SPCFLAGS)
|
||||
|
||||
#define SPCFLAGS_SET(m) do { \
|
||||
regs.spcflags |= (m); \
|
||||
} while (0)
|
||||
|
||||
#define SPCFLAGS_CLEAR(m) do { \
|
||||
regs.spcflags &= ~(m); \
|
||||
} while (0)
|
||||
|
||||
#elif defined(X86_ASSEMBLY)
|
||||
|
||||
#define HAVE_HARDWARE_LOCKS
|
||||
|
||||
#define SPCFLAGS_SET(m) do { \
|
||||
__asm__ __volatile__("lock\n\torl %1,%0" : "=m" (regs.spcflags) : "i" ((m))); \
|
||||
} while (0)
|
||||
|
||||
#define SPCFLAGS_CLEAR(m) do { \
|
||||
__asm__ __volatile__("lock\n\tandl %1,%0" : "=m" (regs.spcflags) : "i" (~(m))); \
|
||||
} while (0)
|
||||
|
||||
#else
|
||||
|
||||
#undef HAVE_HARDWARE_LOCKS
|
||||
|
||||
#include "main.h"
|
||||
extern B2_mutex *spcflags_lock;
|
||||
|
||||
|
@ -99,9 +85,91 @@ extern B2_mutex *spcflags_lock;
|
|||
#define SPCFLAGS_CLEAR(m) do { \
|
||||
B2_lock_mutex(spcflags_lock); \
|
||||
regs.spcflags &= ~(m); \
|
||||
B2_unlock_mutex(spcflags_lock); \
|
||||
B2_unlock_mutex(spcflags_lock); \
|
||||
} while (0)
|
||||
|
||||
#define SleepAndWait() usleep(1000);
|
||||
|
||||
#if 0
|
||||
#ifndef ENABLE_EXCLUSIVE_SPCFLAGS
|
||||
|
||||
#define SPCFLAGS_SET(m) do { \
|
||||
regs.spcflags |= (m); \
|
||||
} while (0)
|
||||
|
||||
#define SPCFLAGS_CLEAR(m) do { \
|
||||
regs.spcflags &= ~(m); \
|
||||
} while (0)
|
||||
|
||||
#if 0
|
||||
#define SleepAndWait() usleep(1000)
|
||||
#endif
|
||||
|
||||
#elif defined(X86_ASSEMBLY)
|
||||
// #elif (defined(CPU_i386) || defined(CPU_x86_64)) && defined(X86_ASSEMBLY) && !defined(ENABLE_REALSTOP)
|
||||
|
||||
// #define HAVE_HARDWARE_LOCKS 1
|
||||
#define HAVE_HARDWARE_LOCKS
|
||||
|
||||
#define SPCFLAGS_SET(m) do { \
|
||||
__asm__ __volatile__("lock\n\torl %1,%0" : "=m" (regs.spcflags) : "i" ((m))); \
|
||||
} while (0)
|
||||
|
||||
#define SPCFLAGS_CLEAR(m) do { \
|
||||
__asm__ __volatile__("lock\n\tandl %1,%0" : "=m" (regs.spcflags) : "i" (~(m))); \
|
||||
} while (0)
|
||||
|
||||
// #define SleepAndWait() usleep(1000)
|
||||
|
||||
// #elif !defined(ENABLE_REALSTOP)
|
||||
|
||||
// #undef HAVE_HARDWARE_LOCKS
|
||||
// extern SDL_mutex *spcflags_lock;
|
||||
|
||||
// #define SPCFLAGS_SET(m) do { \
|
||||
// SDL_LockMutex(spcflags_lock); \
|
||||
// regs.spcflags |= (m); \
|
||||
// SDL_UnlockMutex(spcflags_lock); \
|
||||
// } while (0)
|
||||
|
||||
// #define SPCFLAGS_CLEAR(m) do { \
|
||||
// SDL_LockMutex(spcflags_lock); \
|
||||
// regs.spcflags &= ~(m); \
|
||||
// SDL_UnlockMutex(spcflags_lock); \
|
||||
// } while (0)
|
||||
|
||||
// #define SleepAndWait() usleep(1000)
|
||||
|
||||
#else
|
||||
/// Full STOP instruction implementation (default configuration)
|
||||
|
||||
#undef HAVE_HARDWARE_LOCKS
|
||||
#if 0
|
||||
extern SDL_mutex *spcflags_lock;
|
||||
extern SDL_cond *stop_condition;
|
||||
|
||||
#define SPCFLAGS_SET(m) do { \
|
||||
SDL_LockMutex(spcflags_lock); \
|
||||
regs.spcflags |= (m); \
|
||||
if (regs.spcflags & SPCFLAG_STOP) \
|
||||
SDL_CondSignal(stop_condition); \
|
||||
SDL_UnlockMutex(spcflags_lock); \
|
||||
} while (0)
|
||||
|
||||
#define SPCFLAGS_CLEAR(m) do { \
|
||||
SDL_LockMutex(spcflags_lock); \
|
||||
regs.spcflags &= ~(m); \
|
||||
SDL_UnlockMutex(spcflags_lock); \
|
||||
} while (0)
|
||||
|
||||
#define SleepAndWait() do { \
|
||||
SDL_LockMutex(spcflags_lock); \
|
||||
SDL_CondWait(stop_condition, spcflags_lock); \
|
||||
SDL_UnlockMutex(spcflags_lock); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif /* SPCFLAGS_H */
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
% J: immediate 0..15
|
||||
% k: immediate 0..7
|
||||
% K: immediate 0..63
|
||||
% p: immediate 0..3 (CINV and CPUSH instructions: Cache Field)
|
||||
% p: immediate 0..3 (CINV and CPUSH: cache field)
|
||||
% s: source mode
|
||||
% S: source reg
|
||||
% d: dest mode
|
||||
|
@ -28,14 +28,15 @@
|
|||
% ArP: --> (Ar)+
|
||||
% L: --> (xxx.L)
|
||||
%
|
||||
% Fields on a line:
|
||||
% 16 chars bitpattern :
|
||||
% CPU level / privilege level :
|
||||
% Fields on a line:
|
||||
% 16 chars bitpattern :
|
||||
% CPU level / privildge level :
|
||||
% CPU level 0: 68000
|
||||
% 1: 68010
|
||||
% 2: 68020
|
||||
% 3: 68020/68881
|
||||
% 4: 68040
|
||||
% 5: 68060
|
||||
% privilege level 0: not privileged
|
||||
% 1: unprivileged only on 68000 (check regs.s)
|
||||
% 2: privileged (check regs.s)
|
||||
|
@ -46,8 +47,10 @@
|
|||
% 0 means flag reset
|
||||
% 1 means flag set
|
||||
% ? means programmer was too lazy to check or instruction may trap
|
||||
% everything else means flag set/used
|
||||
% + means instruction is conditional branch (ignored, only for sync)
|
||||
% / means instruction is unconditional branch/call (ignored, only for sync)
|
||||
% x means flag is unknown and well-behaved programs shouldn't check it
|
||||
% everything else means flag set/used
|
||||
%
|
||||
% Control flow
|
||||
% two letters, combination of
|
||||
|
@ -108,7 +111,7 @@
|
|||
0011 DDDd ddss sSSS:00:-----:-----:--:12: MOVEA.W s,d[Areg]
|
||||
0011 DDDd ddss sSSS:00:-NZ00:-----:--:12: MOVE.W s,d[!Areg]
|
||||
|
||||
0100 0000 zzdd dDDD:00:XxZxC:X-Z--:--:30: NEGX.z d[!Areg]
|
||||
0100 0000 zzdd dDDD:00:XNZVC:X-Z--:--:30: NEGX.z d[!Areg]
|
||||
0100 0000 11dd dDDD:01:-----:XNZVC:T-:10: MVSR2.W d[!Areg]
|
||||
0100 0010 zzdd dDDD:00:-0100:-----:--:20: CLR.z d[!Areg]
|
||||
0100 0010 11dd dDDD:10:-----:XNZVC:--:10: MVSR2.B d[!Areg]
|
||||
|
@ -119,13 +122,13 @@
|
|||
0100 1000 0000 1rrr:20:-----:-----:--:31: LINK.L Ar,#2
|
||||
0100 1000 00dd dDDD:00:X?Z?C:X-Z--:--:30: NBCD.B d[!Areg]
|
||||
0100 1000 0100 1kkk:20:-----:-----:T-:10: BKPT #k
|
||||
0100 1000 01ss sSSS:00:-NZ00:-----:--:30: SWAP.W s[Dreg]
|
||||
0100 1000 01ss sSSS:00:-NZ00:-----:--:30: SWAP.W s[Dreg]
|
||||
0100 1000 01ss sSSS:00:-----:-----:--:00: PEA.L s[!Dreg,Areg,Aipi,Apdi,Immd]
|
||||
0100 1000 10dd dDDD:00:-NZ00:-----:--:30: EXT.W d[Dreg]
|
||||
0100 1000 10dd dDDD:00:-NZ00:-----:--:30: EXT.W d[Dreg]
|
||||
0100 1000 10dd dDDD:00:-----:-----:--:02: MVMLE.W #1,d[!Dreg,Areg,Aipi]
|
||||
0100 1000 11dd dDDD:00:-NZ00:-----:--:30: EXT.L d[Dreg]
|
||||
0100 1000 11dd dDDD:00:-NZ00:-----:--:30: EXT.L d[Dreg]
|
||||
0100 1000 11dd dDDD:00:-----:-----:--:02: MVMLE.L #1,d[!Dreg,Areg,Aipi]
|
||||
0100 1001 11dd dDDD:00:-NZ00:-----:--:30: EXT.B d[Dreg]
|
||||
0100 1001 11dd dDDD:00:-NZ00:-----:--:30: EXT.B d[Dreg]
|
||||
0100 1010 zzss sSSS:00:-NZ00:-----:--:10: TST.z s
|
||||
0100 1010 11dd dDDD:00:-NZ00:-----:--:30: TAS.B d[!Areg]
|
||||
0100 1010 1111 1100:00:-----:-----:T-:00: ILLEGAL
|
||||
|
@ -148,21 +151,24 @@
|
|||
0100 1110 0111 0111:00:XNZVC:-----:-R:00: RTR
|
||||
0100 1110 0111 1010:12:-----:-----:T-:10: MOVEC2 #1
|
||||
0100 1110 0111 1011:12:-----:-----:T-:10: MOVE2C #1
|
||||
0100 1110 10ss sSSS:00:-----:-----:-J:80: JSR.L s[!Dreg,Areg,Aipi,Apdi,Immd]
|
||||
0100 1110 10ss sSSS:00://///://///:-J:80: JSR.L s[!Dreg,Areg,Aipi,Apdi,Immd]
|
||||
0100 rrr1 00ss sSSS:00:-N???:-----:T-:11: CHK.L s[!Areg],Dr
|
||||
0100 rrr1 10ss sSSS:00:-N???:-----:T-:11: CHK.W s[!Areg],Dr
|
||||
0100 1110 11ss sSSS:00:-----:-----:-J:80: JMP.L s[!Dreg,Areg,Aipi,Apdi,Immd]
|
||||
0100 1110 11ss sSSS:00://///://///:-J:80: JMP.L s[!Dreg,Areg,Aipi,Apdi,Immd]
|
||||
0100 rrr1 11ss sSSS:00:-----:-----:--:02: LEA.L s[!Dreg,Areg,Aipi,Apdi,Immd],Ar
|
||||
|
||||
0101 jjj0 01dd dDDD:00:-----:-----:--:13: ADDA.W #j,d[Areg]
|
||||
0101 jjj0 10dd dDDD:00:-----:-----:--:13: ADDA.L #j,d[Areg]
|
||||
% This variant of ADDQ is word and long sized only
|
||||
0101 jjj0 01dd dDDD:00:-----:-----:--:13: ADDA.W #j,d[Areg]
|
||||
0101 jjj0 10dd dDDD:00:-----:-----:--:13: ADDA.L #j,d[Areg]
|
||||
0101 jjj0 zzdd dDDD:00:XNZVC:-----:--:13: ADD.z #j,d[!Areg]
|
||||
0101 jjj1 01dd dDDD:00:-----:-----:--:13: SUBA.W #j,d[Areg]
|
||||
0101 jjj1 10dd dDDD:00:-----:-----:--:13: SUBA.L #j,d[Areg]
|
||||
|
||||
% This variant of SUBQ is word and long sized only
|
||||
0101 jjj1 01dd dDDD:00:-----:-----:--:13: SUBA.W #j,d[Areg]
|
||||
0101 jjj1 10dd dDDD:00:-----:-----:--:13: SUBA.L #j,d[Areg]
|
||||
0101 jjj1 zzdd dDDD:00:XNZVC:-----:--:13: SUB.z #j,d[!Areg]
|
||||
|
||||
0101 cccc 1100 1rrr:00:-----:-????:-B:31: DBcc.W Dr,#1
|
||||
0101 cccc 11dd dDDD:00:-----:-????:--:20: Scc.B d[!Areg]
|
||||
0101 cccc 1100 1rrr:00:-----:-++++:-B:31: DBcc.W Dr,#1
|
||||
0101 cccc 11dd dDDD:00:-----:-++++:--:20: Scc.B d[!Areg]
|
||||
0101 cccc 1111 1010:20:-----:-????:T-:10: TRAPcc #1
|
||||
0101 cccc 1111 1011:20:-----:-????:T-:10: TRAPcc #2
|
||||
0101 cccc 1111 1100:20:-----:-????:T-:00: TRAPcc
|
||||
|
@ -170,30 +176,30 @@
|
|||
% Bxx.L is 68020 only, but setting the CPU level to 2 would give illegal
|
||||
% instruction exceptions when compiling a 68000 only emulation, which isn't
|
||||
% what we want either.
|
||||
0110 0001 0000 0000:00:-----:-----:-B:40: BSR.W #1
|
||||
0110 0001 IIII IIII:00:-----:-----:-B:40: BSR.B #i
|
||||
0110 0001 1111 1111:00:-----:-----:-B:40: BSR.L #2
|
||||
0110 CCCC 0000 0000:00:-----:-????:-B:40: Bcc.W #1
|
||||
0110 CCCC IIII IIII:00:-----:-????:-B:40: Bcc.B #i
|
||||
0110 CCCC 1111 1111:00:-----:-????:-B:40: Bcc.L #2
|
||||
0110 0001 0000 0000:00://///://///:-B:40: BSR.W #1
|
||||
0110 0001 IIII IIII:00://///://///:-B:40: BSR.B #i
|
||||
0110 0001 1111 1111:00://///://///:-B:40: BSR.L #2
|
||||
0110 CCCC 0000 0000:00:-----:-++++:-B:40: Bcc.W #1
|
||||
0110 CCCC IIII IIII:00:-----:-++++:-B:40: Bcc.B #i
|
||||
0110 CCCC 1111 1111:00:-----:-++++:-B:40: Bcc.L #2
|
||||
|
||||
0111 rrr0 iiii iiii:00:-NZ00:-----:--:12: MOVE.L #i,Dr
|
||||
|
||||
1000 rrr0 zzss sSSS:00:-NZ00:-----:--:13: OR.z s[!Areg],Dr
|
||||
1000 rrr0 11ss sSSS:00:-NZV0:-----:T-:13: DIVU.W s[!Areg],Dr
|
||||
1000 rrr1 00dd dDDD:00:XxZxC:X-Z--:--:13: SBCD.B d[Dreg],Dr
|
||||
1000 rrr1 00dd dDDD:00:XxZxC:X-Z--:--:13: SBCD.B d[Areg-Apdi],Arp
|
||||
1000 rrr1 00dd dDDD:00:X?Z?C:X-Z--:--:13: SBCD.B d[Dreg],Dr
|
||||
1000 rrr1 00dd dDDD:00:X?Z?C:X-Z--:--:13: SBCD.B d[Areg-Apdi],Arp
|
||||
1000 rrr1 zzdd dDDD:00:-NZ00:-----:--:13: OR.z Dr,d[!Areg,Dreg]
|
||||
1000 rrr1 01dd dDDD:20:-----:-----:--:12: PACK d[Dreg],Dr
|
||||
1000 rrr1 01dd dDDD:20:-----:-----:--:12: PACK d[Areg-Apdi],Arp
|
||||
1000 rrr1 10dd dDDD:20:-----:-----:--:12: UNPK d[Dreg],Dr
|
||||
1000 rrr1 10dd dDDD:20:-----:-----:--:12: UNPK d[Areg-Apdi],Arp
|
||||
1000 rrr1 01dd dDDD:20:-----:-----:--:12: PACK d[Dreg],Dr
|
||||
1000 rrr1 01dd dDDD:20:-----:-----:--:12: PACK d[Areg-Apdi],Arp
|
||||
1000 rrr1 10dd dDDD:20:-----:-----:--:12: UNPK d[Dreg],Dr
|
||||
1000 rrr1 10dd dDDD:20:-----:-----:--:12: UNPK d[Areg-Apdi],Arp
|
||||
1000 rrr1 11ss sSSS:00:-NZV0:-----:T-:13: DIVS.W s[!Areg],Dr
|
||||
|
||||
1001 rrr0 zzss sSSS:00:XNZVC:-----:--:13: SUB.z s,Dr
|
||||
1001 rrr0 11ss sSSS:00:-----:-----:--:13: SUBA.W s,Ar
|
||||
1001 rrr1 zzdd dDDD:00:XNZVC:X-Z--:--:13: SUBX.z d[Dreg],Dr
|
||||
1001 rrr1 zzdd dDDD:00:XNZVC:X-Z--:--:13: SUBX.z d[Areg-Apdi],Arp
|
||||
1001 rrr1 zzdd dDDD:00:XNZVC:X-Z--:--:13: SUBX.z d[Dreg],Dr
|
||||
1001 rrr1 zzdd dDDD:00:XNZVC:X-Z--:--:13: SUBX.z d[Areg-Apdi],Arp
|
||||
1001 rrr1 zzdd dDDD:00:XNZVC:-----:--:13: SUB.z Dr,d[!Areg,Dreg]
|
||||
1001 rrr1 11ss sSSS:00:-----:-----:--:13: SUBA.L s,Ar
|
||||
|
||||
|
@ -205,18 +211,18 @@
|
|||
|
||||
1100 rrr0 zzss sSSS:00:-NZ00:-----:--:13: AND.z s[!Areg],Dr
|
||||
1100 rrr0 11ss sSSS:00:-NZ00:-----:--:13: MULU.W s[!Areg],Dr
|
||||
1100 rrr1 00dd dDDD:00:XxZxC:X-Z--:--:13: ABCD.B d[Dreg],Dr
|
||||
1100 rrr1 00dd dDDD:00:XxZxC:X-Z--:--:13: ABCD.B d[Areg-Apdi],Arp
|
||||
1100 rrr1 00dd dDDD:00:X?Z?C:X-Z--:--:13: ABCD.B d[Dreg],Dr
|
||||
1100 rrr1 00dd dDDD:00:X?Z?C:X-Z--:--:13: ABCD.B d[Areg-Apdi],Arp
|
||||
1100 rrr1 zzdd dDDD:00:-NZ00:-----:--:13: AND.z Dr,d[!Areg,Dreg]
|
||||
1100 rrr1 01dd dDDD:00:-----:-----:--:33: EXG.L Dr,d[Dreg]
|
||||
1100 rrr1 01dd dDDD:00:-----:-----:--:33: EXG.L Ar,d[Areg]
|
||||
1100 rrr1 10dd dDDD:00:-----:-----:--:33: EXG.L Dr,d[Areg]
|
||||
1100 rrr1 01dd dDDD:00:-----:-----:--:33: EXG.L Dr,d[Dreg]
|
||||
1100 rrr1 01dd dDDD:00:-----:-----:--:33: EXG.L Ar,d[Areg]
|
||||
1100 rrr1 10dd dDDD:00:-----:-----:--:33: EXG.L Dr,d[Areg]
|
||||
1100 rrr1 11ss sSSS:00:-NZ00:-----:--:13: MULS.W s[!Areg],Dr
|
||||
|
||||
1101 rrr0 zzss sSSS:00:XNZVC:-----:--:13: ADD.z s,Dr
|
||||
1101 rrr0 11ss sSSS:00:-----:-----:--:13: ADDA.W s,Ar
|
||||
1101 rrr1 zzdd dDDD:00:XNZVC:X-Z--:--:13: ADDX.z d[Dreg],Dr
|
||||
1101 rrr1 zzdd dDDD:00:XNZVC:X-Z--:--:13: ADDX.z d[Areg-Apdi],Arp
|
||||
1101 rrr1 zzdd dDDD:00:XNZVC:X-Z--:--:13: ADDX.z d[Dreg],Dr
|
||||
1101 rrr1 zzdd dDDD:00:XNZVC:X-Z--:--:13: ADDX.z d[Areg-Apdi],Arp
|
||||
1101 rrr1 zzdd dDDD:00:XNZVC:-----:--:13: ADD.z Dr,d[!Areg,Dreg]
|
||||
1101 rrr1 11ss sSSS:00:-----:-----:--:13: ADDA.L s,Ar
|
||||
|
||||
|
@ -224,8 +230,8 @@
|
|||
1110 jjjf zz00 1RRR:00:XNZ0C:-----:--:13: LSf.z #j,DR
|
||||
1110 jjjf zz01 0RRR:00:XNZ0C:X----:--:13: ROXf.z #j,DR
|
||||
1110 jjjf zz01 1RRR:00:-NZ0C:-----:--:13: ROf.z #j,DR
|
||||
1110 rrrf zz10 0RRR:00:XNZVC:-----:--:13: ASf.z Dr,DR
|
||||
1110 rrrf zz10 1RRR:00:XNZ0C:-----:--:13: LSf.z Dr,DR
|
||||
1110 rrrf zz10 0RRR:00:XNZVC:X----:--:13: ASf.z Dr,DR
|
||||
1110 rrrf zz10 1RRR:00:XNZ0C:X----:--:13: LSf.z Dr,DR
|
||||
1110 rrrf zz11 0RRR:00:XNZ0C:X----:--:13: ROXf.z Dr,DR
|
||||
1110 rrrf zz11 1RRR:00:-NZ0C:-----:--:13: ROf.z Dr,DR
|
||||
1110 000f 11dd dDDD:00:XNZVC:-----:--:13: ASfW.W d[!Dreg,Areg]
|
||||
|
@ -255,7 +261,6 @@
|
|||
1111 0011 01ss sSSS:32:-----:-----:--:10: FRESTORE s[!Dreg,Areg,Apdi,Immd]
|
||||
|
||||
% 68040 instructions
|
||||
1111 0101 iiii iSSS:40:-----:-----:T-:11: MMUOP #i,s
|
||||
1111 0100 pp00 1rrr:42:-----:-----:T-:02: CINVL #p,Ar
|
||||
1111 0100 pp01 0rrr:42:-----:-----:T-:02: CINVP #p,Ar
|
||||
1111 0100 pp01 1rrr:42:-----:-----:T-:00: CINVA #p
|
||||
|
@ -264,11 +269,19 @@
|
|||
1111 0100 pp11 1rrr:42:-----:-----:T-:00: CPUSHA #p
|
||||
% destination register number is encoded in the following word
|
||||
1111 0110 0010 0rrr:40:-----:-----:--:12: MOVE16 ArP,AxP
|
||||
1111 0110 00ss sSSS:40:-----:-----:--:12: MOVE16 s[Dreg-Aipi],L
|
||||
1111 0110 00dd dDDD:40:-----:-----:--:12: MOVE16 L,d[Areg-Aipi]
|
||||
1111 0110 00ss sSSS:40:-----:-----:--:12: MOVE16 s[Aind],L
|
||||
1111 0110 00dd dDDD:40:-----:-----:--:12: MOVE16 L,d[Aipi-Aind]
|
||||
1111 0110 00ss sSSS:40:-----:-----:--:12: MOVE16 s[Dreg-Aipi],Al
|
||||
1111 0110 00dd dDDD:40:-----:-----:--:12: MOVE16 Al,d[Areg-Aipi]
|
||||
1111 0110 00ss sSSS:40:-----:-----:--:12: MOVE16 s[Aind],Al
|
||||
1111 0110 00dd dDDD:40:-----:-----:--:12: MOVE16 Al,d[Aipi-Aind]
|
||||
|
||||
% EmulOp instructions
|
||||
0111 0001 0000 0000:00:-----:-----:-R:00: EMULOP_RETURN
|
||||
0111 0001 EEEE EEEE:00:-----:-----:-J:10: EMULOP #E
|
||||
% MMU disabled
|
||||
% 1111 0101 iiii iSSS:42:?????:?????:T-:11: MMUOP #i,s
|
||||
|
||||
% EmulOp instructions (used by linux68k)
|
||||
0111 0001 0000 0000:02:-----:XNZVC:-R:00: EMULOP_RETURN
|
||||
0111 0001 EEEE EEEE:00:-----:XNZVC:-J:10: EMULOP #E
|
||||
|
||||
% NatFea instructions (do I have the srcaddr correct?)
|
||||
% NatFeat disabled
|
||||
% 0111 0011 0000 0000:00:-----:XNZVC:-J:00: NATFEAT_ID
|
||||
% 0111 0011 0000 0001:00:-----:XNZVC:-J:00: NATFEAT_CALL
|
||||
|
|
Loading…
Reference in New Issue