mirror of
https://github.com/kanjitalk755/macemu.git
synced 2024-06-12 19:36:33 +00:00
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)
|
cmake_minimum_required(VERSION 3.0.0)
|
||||||
project(BasiliskII)
|
project(BasiliskII)
|
||||||
|
|
||||||
if (NOT EXISTS ${CMAKE_BINARY_DIR}/CMakeCache.txt)
|
# if (NOT EXISTS ${CMAKE_BINARY_DIR}/CMakeCache.txt)
|
||||||
if (NOT CMAKE_BUILD_TYPE)
|
# if (NOT CMAKE_BUILD_TYPE)
|
||||||
set(CMAKE_BUILD_TYPE "Release" CACHE STRING "" FORCE)
|
# set(CMAKE_BUILD_TYPE "Release" CACHE STRING "" FORCE)
|
||||||
endif()
|
# endif()
|
||||||
endif()
|
# endif()
|
||||||
|
|
||||||
find_package(SDL2 REQUIRED)
|
find_package(SDL2 REQUIRED)
|
||||||
find_library(COREFOUNDATION_LIBRARY CoreFoundation)
|
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_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 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)
|
add_executable(gencomp ../uae_cpu/compiler/gencomp.c ../uae_cpu/readcpu.cpp cpudefs.cpp)
|
||||||
|
|
||||||
|
@ -88,12 +90,11 @@ set(BasiliskII_SRCS
|
||||||
cpustbl.cpp
|
cpustbl.cpp
|
||||||
cpudefs.cpp
|
cpudefs.cpp
|
||||||
cpuemu.cpp
|
cpuemu.cpp
|
||||||
|
cpufunctbl.cpp
|
||||||
compemu.cpp
|
compemu.cpp
|
||||||
compstbl.cpp
|
compstbl.cpp
|
||||||
../uae_cpu/compiler/compemu_support.cpp
|
../uae_cpu/compiler/compemu_support.cpp
|
||||||
../uae_cpu/compiler/compemu_fpp.cpp
|
../uae_cpu/compiler/compemu_fpp.cpp
|
||||||
cpustbl_nf.cpp
|
|
||||||
cpuemu_nf.cpp
|
|
||||||
#addressing mode =direct -DDIRECT_ADDRESSING
|
#addressing mode =direct -DDIRECT_ADDRESSING
|
||||||
#includes
|
#includes
|
||||||
)
|
)
|
||||||
|
@ -101,7 +102,7 @@ set(BasiliskII_SRCS
|
||||||
add_executable(BasiliskII ${BasiliskII_SRCS})
|
add_executable(BasiliskII ${BasiliskII_SRCS})
|
||||||
|
|
||||||
set_source_files_properties(${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 ")
|
# set_property(SOURCE compemu_support.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -O0 ")
|
||||||
|
|
||||||
|
|
|
@ -58,6 +58,7 @@ using std::string;
|
||||||
|
|
||||||
#if USE_JIT
|
#if USE_JIT
|
||||||
extern void (*flush_icache)(void); // from compemu_support.cpp
|
extern void (*flush_icache)(void); // from compemu_support.cpp
|
||||||
|
extern bool UseJIT;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -181,8 +182,8 @@ static void sigsegv_dump_state(sigsegv_info_t *sip)
|
||||||
fprintf(stderr, " [IP=%p]", fault_instruction);
|
fprintf(stderr, " [IP=%p]", fault_instruction);
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
#if EMULATED_68K
|
#if EMULATED_68K
|
||||||
extern void m68k_dumpstate (uaecptr *);
|
extern void m68k_dumpstate (FILE *, uaecptr *);
|
||||||
m68k_dumpstate(0);
|
m68k_dumpstate(stderr, 0);
|
||||||
#endif
|
#endif
|
||||||
#if USE_JIT && JIT_DEBUG
|
#if USE_JIT && JIT_DEBUG
|
||||||
extern void compiler_dumpstate(void);
|
extern void compiler_dumpstate(void);
|
||||||
|
|
|
@ -419,6 +419,13 @@ static inline uae_u32 do_byteswap_16(uae_u32 v)
|
||||||
# define REGPARAM
|
# define REGPARAM
|
||||||
#endif
|
#endif
|
||||||
#define REGPARAM2
|
#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
|
#define memptr uint32
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,7 @@
|
||||||
* Execute EMUL_OP opcode (called by 68k emulator or Illegal Instruction trap handler)
|
* 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));
|
D(bug("EmulOp %04x\n", opcode));
|
||||||
switch (opcode) {
|
switch (opcode) {
|
||||||
|
@ -68,12 +68,12 @@ void EmulOp(uint16 opcode, M68kRegisters *r)
|
||||||
VideoQuitFullScreen();
|
VideoQuitFullScreen();
|
||||||
|
|
||||||
QuitEmulator();
|
QuitEmulator();
|
||||||
break;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
case M68K_EMUL_OP_SHUTDOWN: // Quit emulator
|
case M68K_EMUL_OP_SHUTDOWN: // Quit emulator
|
||||||
QuitEmulator();
|
QuitEmulator();
|
||||||
break;
|
return false;
|
||||||
|
|
||||||
case M68K_EMUL_OP_RESET: { // MacOS reset
|
case M68K_EMUL_OP_RESET: { // MacOS reset
|
||||||
D(bug("*** RESET ***\n"));
|
D(bug("*** RESET ***\n"));
|
||||||
|
@ -101,7 +101,7 @@ void EmulOp(uint16 opcode, M68kRegisters *r)
|
||||||
r->a[1] = ROMBaseMac + UniversalInfo; // UniversalInfo
|
r->a[1] = ROMBaseMac + UniversalInfo; // UniversalInfo
|
||||||
r->a[6] = boot_globs; // BootGlobs
|
r->a[6] = boot_globs; // BootGlobs
|
||||||
r->a[7] = RAMBaseMac + 0x10000; // Boot stack
|
r->a[7] = RAMBaseMac + 0x10000; // Boot stack
|
||||||
break;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
case M68K_EMUL_OP_CLKNOMEM: { // Clock/PRAM operations
|
case M68K_EMUL_OP_CLKNOMEM: { // Clock/PRAM operations
|
||||||
|
@ -570,6 +570,8 @@ void EmulOp(uint16 opcode, M68kRegisters *r)
|
||||||
r->sr);
|
r->sr);
|
||||||
|
|
||||||
QuitEmulator();
|
QuitEmulator();
|
||||||
break;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,6 +94,6 @@ enum {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Functions
|
// 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
|
#endif
|
||||||
|
|
|
@ -34,8 +34,10 @@ extern bool TwentyFourBitAddressing;
|
||||||
// 68k register structure (for Execute68k())
|
// 68k register structure (for Execute68k())
|
||||||
struct M68kRegisters {
|
struct M68kRegisters {
|
||||||
uint32 d[8];
|
uint32 d[8];
|
||||||
uint32 a[8];
|
memptr a[8];
|
||||||
uint16 sr;
|
uint16 sr;
|
||||||
|
memptr usp, isp, msp;
|
||||||
|
memptr pc;
|
||||||
};
|
};
|
||||||
|
|
||||||
// General functions
|
// General functions
|
||||||
|
|
80
BasiliskII/src/uae_cpu/Makefile.am
Normal file
80
BasiliskII/src/uae_cpu/Makefile.am
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
#
|
||||||
|
# Note: this Makefile only contains rules for the source
|
||||||
|
# generator tools.
|
||||||
|
#
|
||||||
|
|
||||||
|
#
|
||||||
|
# suppress warnings about overriding LDFLAGS and CPPFLAGS
|
||||||
|
#
|
||||||
|
AUTOMAKE_OPTIONS = -Wno-gnu
|
||||||
|
|
||||||
|
AM_CPPFLAGS = $(DEFINES) \
|
||||||
|
"-I$(srcdir)/../include" \
|
||||||
|
"-I$(srcdir)/../Unix" \
|
||||||
|
"-I$(builddir)/.." \
|
||||||
|
"-I$(builddir)" \
|
||||||
|
"-I$(srcdir)"
|
||||||
|
|
||||||
|
CC = $(CC_FOR_BUILD)
|
||||||
|
CXX = $(CXX_FOR_BUILD)
|
||||||
|
|
||||||
|
LDFLAGS = $(LDFLAGS_FOR_BUILD)
|
||||||
|
CPPFLAGS = $(CPPFLAGS_FOR_BUILD)
|
||||||
|
CFLAGS = $(CFLAGS_FOR_BUILD)
|
||||||
|
CXXFLAGS = $(CXXFLAGS_FOR_BUILD)
|
||||||
|
LIBS=-lm
|
||||||
|
|
||||||
|
CFLAGS_NOWARN = $(DBGSP)
|
||||||
|
AM_CFLAGS = $(CFLAGS_NOWARN) $(WFLAGS)
|
||||||
|
AM_CXXFLAGS = $(CFLAGS_NOWARN) $(WFLAGS)
|
||||||
|
|
||||||
|
noinst_PROGRAMS = build68k gencpu
|
||||||
|
if USE_JIT
|
||||||
|
noinst_PROGRAMS += gencomp
|
||||||
|
endif
|
||||||
|
|
||||||
|
BUILT_SOURCES = \
|
||||||
|
cpudefs.cpp \
|
||||||
|
cpuemu.cpp \
|
||||||
|
cpustbl.cpp \
|
||||||
|
cpufunctbl.cpp \
|
||||||
|
cputbl.h \
|
||||||
|
$(empty)
|
||||||
|
|
||||||
|
build68k_SOURCES = build68k.c
|
||||||
|
gencpu_SOURCES = gencpu.c m68k.h readcpu.cpp readcpu.h cpudefs.cpp
|
||||||
|
gencomp_SOURCES =
|
||||||
|
if GENCOMP_ARCH_X86
|
||||||
|
gencomp_SOURCES += compiler/gencomp.c
|
||||||
|
endif
|
||||||
|
if GENCOMP_ARCH_ARM
|
||||||
|
gencomp_SOURCES += compiler/gencomp_arm.c
|
||||||
|
endif
|
||||||
|
gencomp_SOURCES += readcpu.cpp cpudefs.cpp
|
||||||
|
|
||||||
|
if USE_JIT
|
||||||
|
BUILT_SOURCES += compemu.cpp compstbl.cpp comptbl.h
|
||||||
|
endif
|
||||||
|
|
||||||
|
|
||||||
|
cpudefs.cpp: build68k$(EXEEXT) $(srcdir)/table68k
|
||||||
|
$(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)
|
326
BasiliskII/src/uae_cpu/aranym_glue.cpp
Normal file
326
BasiliskII/src/uae_cpu/aranym_glue.cpp
Normal file
|
@ -0,0 +1,326 @@
|
||||||
|
/*
|
||||||
|
* aranym_glue.cpp - CPU interface
|
||||||
|
*
|
||||||
|
* Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
|
||||||
|
*
|
||||||
|
* Inspired by Christian Bauer's Basilisk II
|
||||||
|
*
|
||||||
|
* This file is part of the ARAnyM project which builds a new and powerful
|
||||||
|
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
|
||||||
|
*
|
||||||
|
* ARAnyM is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* ARAnyM is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with ARAnyM; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "sysdeps.h"
|
||||||
|
|
||||||
|
#include "cpu_emulation.h"
|
||||||
|
#include "newcpu.h"
|
||||||
|
#include "hardware.h"
|
||||||
|
#include "scc.h"
|
||||||
|
#include "input.h"
|
||||||
|
#ifdef USE_JIT
|
||||||
|
# include "compiler/compemu.h"
|
||||||
|
#endif
|
||||||
|
#include "nf_objs.h"
|
||||||
|
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
|
// RAM and ROM pointers
|
||||||
|
memptr RAMBase = 0; // RAM base (Atari address space) gb-- init is important
|
||||||
|
uint8 *RAMBaseHost; // RAM base (host address space)
|
||||||
|
uint32 RAMSize = 0x00e00000; // Size of RAM
|
||||||
|
|
||||||
|
memptr ROMBase = 0x00e00000; // ROM base (Atari address space)
|
||||||
|
uint8 *ROMBaseHost; // ROM base (host address space)
|
||||||
|
uint32 ROMSize = 0x00100000; // Size of ROM
|
||||||
|
|
||||||
|
uint32 RealROMSize; // Real size of ROM
|
||||||
|
|
||||||
|
memptr HWBase = 0x00f00000; // HW base (Atari address space)
|
||||||
|
uint8 *HWBaseHost; // HW base (host address space)
|
||||||
|
uint32 HWSize = 0x00100000; // Size of HW space
|
||||||
|
|
||||||
|
memptr FastRAMBase = 0x01000000; // Fast-RAM base (Atari address space)
|
||||||
|
uint8 *FastRAMBaseHost; // Fast-RAM base (host address space)
|
||||||
|
|
||||||
|
#ifdef HW_SIGSEGV
|
||||||
|
uint8 *FakeIOBaseHost;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef FIXED_VIDEORAM
|
||||||
|
memptr VideoRAMBase = ARANYMVRAMSTART; // VideoRAM base (Atari address space)
|
||||||
|
#else
|
||||||
|
memptr VideoRAMBase; // VideoRAM base (Atari address space)
|
||||||
|
#endif
|
||||||
|
uint8 *VideoRAMBaseHost;// VideoRAM base (host address space)
|
||||||
|
//uint32 VideoRAMSize; // Size of VideoRAM
|
||||||
|
|
||||||
|
#ifndef NOT_MALLOC
|
||||||
|
uintptr MEMBaseDiff; // Global offset between a Atari address and its Host equivalent
|
||||||
|
uintptr ROMBaseDiff;
|
||||||
|
uintptr FastRAMBaseDiff;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uintptr VMEMBaseDiff; // Global offset between a Atari VideoRAM address and /dev/fb0 mmap
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(ENABLE_EXCLUSIVE_SPCFLAGS) && !defined(HAVE_HARDWARE_LOCKS)
|
||||||
|
SDL_mutex *spcflags_lock;
|
||||||
|
#endif
|
||||||
|
#if defined(ENABLE_REALSTOP)
|
||||||
|
SDL_cond *stop_condition;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize 680x0 emulation
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool InitMEM() {
|
||||||
|
InitMEMBaseDiff(RAMBaseHost, RAMBase);
|
||||||
|
InitROMBaseDiff(ROMBaseHost, ROMBase);
|
||||||
|
InitFastRAMBaseDiff(FastRAMBaseHost, FastRAMBase);
|
||||||
|
InitVMEMBaseDiff(VideoRAMBaseHost, VideoRAMBase);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Init680x0(void)
|
||||||
|
{
|
||||||
|
init_m68k();
|
||||||
|
|
||||||
|
#if defined(ENABLE_EXCLUSIVE_SPCFLAGS) && !defined(HAVE_HARDWARE_LOCKS)
|
||||||
|
if ((spcflags_lock = SDL_CreateMutex()) == NULL) {
|
||||||
|
panicbug("Error by SDL_CreateMutex()");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if ENABLE_REALSTOP
|
||||||
|
if ((stop_condition = SDL_CreateCond()) == NULL) {
|
||||||
|
panicbug("Error by SDL_CreateCond()");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef USE_JIT
|
||||||
|
if (bx_options.jit.jit) compiler_init();
|
||||||
|
#endif
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Instr. RESET
|
||||||
|
*/
|
||||||
|
|
||||||
|
void AtariReset(void)
|
||||||
|
{
|
||||||
|
// reset Atari hardware here
|
||||||
|
HWReset();
|
||||||
|
// reset NatFeats here
|
||||||
|
NFReset();
|
||||||
|
// reset the input devices (input.cpp)
|
||||||
|
InputReset();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reset CPU
|
||||||
|
*/
|
||||||
|
|
||||||
|
void Reset680x0(void)
|
||||||
|
{
|
||||||
|
m68k_reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Deinitialize 680x0 emulation
|
||||||
|
*/
|
||||||
|
|
||||||
|
void Exit680x0(void)
|
||||||
|
{
|
||||||
|
#ifdef USE_JIT
|
||||||
|
if (bx_options.jit.jit) compiler_exit();
|
||||||
|
#endif
|
||||||
|
exit_m68k();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reset and start 680x0 emulation
|
||||||
|
*/
|
||||||
|
|
||||||
|
void Start680x0(void)
|
||||||
|
{
|
||||||
|
m68k_reset();
|
||||||
|
#ifdef USE_JIT
|
||||||
|
if (bx_options.jit.jit) {
|
||||||
|
m68k_compile_execute();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
m68k_execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Restart running 680x0 emulation safely from different thread
|
||||||
|
*/
|
||||||
|
void Restart680x0(void)
|
||||||
|
{
|
||||||
|
quit_program = 2;
|
||||||
|
TriggerNMI();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Quit 680x0 emulation safely from different thread
|
||||||
|
*/
|
||||||
|
void Quit680x0(void)
|
||||||
|
{
|
||||||
|
quit_program = 1;
|
||||||
|
TriggerNMI();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int MFPdoInterrupt(void)
|
||||||
|
{
|
||||||
|
return getMFP()->doInterrupt();
|
||||||
|
}
|
||||||
|
|
||||||
|
int SCCdoInterrupt(void)
|
||||||
|
{
|
||||||
|
return getSCC()->doInterrupt();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Trigger interrupts
|
||||||
|
*/
|
||||||
|
void TriggerInternalIRQ(void)
|
||||||
|
{
|
||||||
|
SPCFLAGS_SET( SPCFLAG_INTERNAL_IRQ );
|
||||||
|
}
|
||||||
|
|
||||||
|
void TriggerInt3(void)
|
||||||
|
{
|
||||||
|
SPCFLAGS_SET( SPCFLAG_INT3 );
|
||||||
|
}
|
||||||
|
|
||||||
|
void TriggerVBL(void)
|
||||||
|
{
|
||||||
|
SPCFLAGS_SET( SPCFLAG_VBL );
|
||||||
|
}
|
||||||
|
|
||||||
|
void TriggerInt5(void)
|
||||||
|
{
|
||||||
|
SPCFLAGS_SET( SPCFLAG_INT5 );
|
||||||
|
}
|
||||||
|
|
||||||
|
void TriggerSCC(bool enable)
|
||||||
|
{
|
||||||
|
if (enable)
|
||||||
|
SPCFLAGS_SET( SPCFLAG_SCC );
|
||||||
|
else
|
||||||
|
SPCFLAGS_CLEAR( SPCFLAG_SCC );
|
||||||
|
}
|
||||||
|
|
||||||
|
void TriggerMFP(bool enable)
|
||||||
|
{
|
||||||
|
if (enable)
|
||||||
|
SPCFLAGS_SET( SPCFLAG_MFP );
|
||||||
|
else
|
||||||
|
SPCFLAGS_CLEAR( SPCFLAG_MFP );
|
||||||
|
}
|
||||||
|
|
||||||
|
void TriggerNMI(void)
|
||||||
|
{
|
||||||
|
SPCFLAGS_SET( SPCFLAG_BRK ); // use _BRK for NMI
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef REBOOT_OR_HALT
|
||||||
|
#define REBOOT_OR_HALT 0 // halt by default
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if REBOOT_OR_HALT == 1
|
||||||
|
# define CPU_MSG "CPU: Rebooting"
|
||||||
|
# define CPU_ACTION Restart680x0()
|
||||||
|
#else
|
||||||
|
# define CPU_MSG "CPU: Halting"
|
||||||
|
# define CPU_ACTION Quit680x0()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ENABLE_EPSLIMITER
|
||||||
|
|
||||||
|
#ifndef EPS_LIMIT
|
||||||
|
# define EPS_LIMIT 10000 /* this might be too high if ARAnyM is slowed down by printing the bus errors on console */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void check_eps_limit(uaecptr pc)
|
||||||
|
{
|
||||||
|
static long last_exception_time=-1;
|
||||||
|
static long exception_per_sec=0;
|
||||||
|
static long exception_per_sec_pc=0;
|
||||||
|
static uaecptr prevpc = 0;
|
||||||
|
|
||||||
|
if (bx_options.cpu.eps_enabled) {
|
||||||
|
if (last_exception_time == -1) {
|
||||||
|
last_exception_time = SDL_GetTicks();
|
||||||
|
}
|
||||||
|
|
||||||
|
exception_per_sec++;
|
||||||
|
|
||||||
|
if (pc == prevpc) {
|
||||||
|
/* BUS ERRORs occur at the same PC - watch out! */
|
||||||
|
exception_per_sec_pc++;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
exception_per_sec_pc = 0;
|
||||||
|
prevpc = pc;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SDL_GetTicks() - last_exception_time > 1000) {
|
||||||
|
last_exception_time = SDL_GetTicks();
|
||||||
|
if (exception_per_sec_pc > bx_options.cpu.eps_max ||
|
||||||
|
exception_per_sec > EPS_LIMIT /* make it configurable */) {
|
||||||
|
panicbug("CPU: Exception per second limit reached: %ld/%ld",
|
||||||
|
exception_per_sec_pc, exception_per_sec);
|
||||||
|
/* would be cool to open SDL dialog here: */
|
||||||
|
/* [Exception per seconds limit reached. XXXXX exception
|
||||||
|
occured in the last second. The limit is set to YYYYY
|
||||||
|
in your config file. Do you want to continue emulation,
|
||||||
|
reset ARAnyM or quit ?][Continue] [Reset] [Quit]
|
||||||
|
*/
|
||||||
|
panicbug(CPU_MSG);
|
||||||
|
CPU_ACTION;
|
||||||
|
}
|
||||||
|
exception_per_sec = 0;
|
||||||
|
exception_per_sec_pc = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void report_double_bus_error()
|
||||||
|
{
|
||||||
|
panicbug("CPU: Double bus fault detected !");
|
||||||
|
/* would be cool to open SDL dialog here: */
|
||||||
|
/* [Double bus fault detected. The emulated system crashed badly.
|
||||||
|
Do you want to reset ARAnyM or quit ?] [Reset] [Quit]"
|
||||||
|
*/
|
||||||
|
panicbug(CPU_MSG);
|
||||||
|
CPU_ACTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef FLIGHT_RECORDER
|
||||||
|
extern bool cpu_flight_recorder_active;
|
||||||
|
void cpu_flight_recorder(int activate) { cpu_flight_recorder_active = activate; }
|
||||||
|
#endif
|
|
@ -56,8 +56,12 @@ uintptr MEMBaseDiff; // Global offset between a Mac address and its Host equiva
|
||||||
bool UseJIT = false;
|
bool UseJIT = false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// #if defined(ENABLE_EXCLUSIVE_SPCFLAGS) && !defined(HAVE_HARDWARE_LOCKS)
|
||||||
|
B2_mutex *spcflags_lock = NULL;
|
||||||
|
// #endif
|
||||||
|
|
||||||
// From newcpu.cpp
|
// From newcpu.cpp
|
||||||
extern bool quit_program;
|
extern int quit_program;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -66,6 +70,7 @@ extern bool quit_program;
|
||||||
|
|
||||||
bool Init680x0(void)
|
bool Init680x0(void)
|
||||||
{
|
{
|
||||||
|
spcflags_lock = B2_create_mutex();
|
||||||
#if REAL_ADDRESSING
|
#if REAL_ADDRESSING
|
||||||
// Mac address space = host address space
|
// Mac address space = host address space
|
||||||
RAMBaseMac = (uintptr)RAMBaseHost;
|
RAMBaseMac = (uintptr)RAMBaseHost;
|
||||||
|
@ -159,7 +164,8 @@ void TriggerInterrupt(void)
|
||||||
|
|
||||||
void TriggerNMI(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
|
// Execute trap
|
||||||
m68k_setpc(m68k_areg(regs, 7));
|
m68k_setpc(m68k_areg(regs, 7));
|
||||||
fill_prefetch_0();
|
fill_prefetch_0();
|
||||||
quit_program = false;
|
quit_program = 0;
|
||||||
m68k_execute();
|
m68k_execute();
|
||||||
|
|
||||||
// Clean up stack
|
// Clean up stack
|
||||||
|
@ -215,7 +221,7 @@ void Execute68kTrap(uint16 trap, struct M68kRegisters *r)
|
||||||
r->d[i] = m68k_dreg(regs, i);
|
r->d[i] = m68k_dreg(regs, i);
|
||||||
for (i=0; i<7; i++)
|
for (i=0; i<7; i++)
|
||||||
r->a[i] = m68k_areg(regs, 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
|
// Execute routine
|
||||||
m68k_setpc(addr);
|
m68k_setpc(addr);
|
||||||
fill_prefetch_0();
|
fill_prefetch_0();
|
||||||
quit_program = false;
|
quit_program = 0;
|
||||||
m68k_execute();
|
m68k_execute();
|
||||||
|
|
||||||
// Clean up stack
|
// Clean up stack
|
||||||
|
@ -262,5 +268,18 @@ void Execute68k(uint32 addr, struct M68kRegisters *r)
|
||||||
r->d[i] = m68k_dreg(regs, i);
|
r->d[i] = m68k_dreg(regs, i);
|
||||||
for (i=0; i<7; i++)
|
for (i=0; i<7; i++)
|
||||||
r->a[i] = m68k_areg(regs, 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
|
* UAE - The Un*x Amiga Emulator
|
||||||
*
|
*
|
||||||
* Read 68000 CPU specs from file "table68k" and build table68k.c
|
* Read 68000 CPU specs from file "table68k" and build table68k.c
|
||||||
*
|
*
|
||||||
* Copyright 1995,1996 Bernd Schmidt
|
* 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 "readcpu.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#undef abort
|
||||||
|
|
||||||
static FILE *tablef;
|
static FILE *tablef;
|
||||||
static int nextch = 0;
|
static int nextch = 0;
|
||||||
|
|
||||||
|
@ -65,15 +77,15 @@ static int nextchtohex(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main()
|
||||||
{
|
{
|
||||||
int no_insns = 0;
|
int no_insns = 0;
|
||||||
|
|
||||||
printf ("#include \"sysdeps.h\"\n");
|
printf ("#include \"sysdeps.h\"\n");
|
||||||
printf ("#include \"readcpu.h\"\n");
|
printf ("#include \"readcpu.h\"\n");
|
||||||
printf ("struct instr_def defs68k[] = {\n");
|
printf ("struct instr_def defs68k[] = {\n");
|
||||||
#ifdef WIN32
|
#if 0
|
||||||
tablef = fopen(argc > 1 ? argv[1] : "table68k","r");
|
tablef = fopen("table68k","r");
|
||||||
if (tablef == NULL) {
|
if (tablef == NULL) {
|
||||||
fprintf(stderr, "table68k not found\n");
|
fprintf(stderr, "table68k not found\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
|
@ -122,8 +134,8 @@ int main(int argc, char **argv)
|
||||||
case 'r': currbit = bitr; break;
|
case 'r': currbit = bitr; break;
|
||||||
case 'R': currbit = bitR; break;
|
case 'R': currbit = bitR; break;
|
||||||
case 'z': currbit = bitz; break;
|
case 'z': currbit = bitz; break;
|
||||||
case 'E': currbit = bitE; break;
|
case 'E': currbit = bitE; break;
|
||||||
case 'p': currbit = bitp; break;
|
case 'p': currbit = bitp; break;
|
||||||
default: abort();
|
default: abort();
|
||||||
}
|
}
|
||||||
if (!(bitmask & 1)) {
|
if (!(bitmask & 1)) {
|
||||||
|
@ -138,6 +150,7 @@ int main(int argc, char **argv)
|
||||||
patbits[i] = nextch;
|
patbits[i] = nextch;
|
||||||
getnextch();
|
getnextch();
|
||||||
}
|
}
|
||||||
|
(void) patbits;
|
||||||
|
|
||||||
while (isspace(nextch) || nextch == ':') /* Get CPU and privilege level */
|
while (isspace(nextch) || nextch == ':') /* Get CPU and privilege level */
|
||||||
getnextch();
|
getnextch();
|
||||||
|
@ -172,6 +185,8 @@ int main(int argc, char **argv)
|
||||||
getnextch();
|
getnextch();
|
||||||
switch(nextch){
|
switch(nextch){
|
||||||
case '-': flagset[i] = fa_unset; break;
|
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 '0': flagset[i] = fa_zero; break;
|
||||||
case '1': flagset[i] = fa_one; break;
|
case '1': flagset[i] = fa_one; break;
|
||||||
case 'x': flagset[i] = fa_dontcare; break;
|
case 'x': flagset[i] = fa_dontcare; break;
|
||||||
|
@ -191,6 +206,8 @@ int main(int argc, char **argv)
|
||||||
getnextch();
|
getnextch();
|
||||||
switch(nextch){
|
switch(nextch){
|
||||||
case '-': flaguse[i] = fu_unused; break;
|
case '-': flaguse[i] = fu_unused; break;
|
||||||
|
case '/': flaguse[i] = fu_isjmp; break;
|
||||||
|
case '+': flaguse[i] = fu_maybecc; break;
|
||||||
case '?': flaguse[i] = fu_unknown; break;
|
case '?': flaguse[i] = fu_unknown; break;
|
||||||
default: flaguse[i] = fu_used; break;
|
default: flaguse[i] = fu_used; break;
|
||||||
}
|
}
|
||||||
|
@ -235,7 +252,7 @@ int main(int argc, char **argv)
|
||||||
if (nextch != ':')
|
if (nextch != ':')
|
||||||
abort();
|
abort();
|
||||||
|
|
||||||
fgets(opcstr, 250, tablef);
|
assert(fgets(opcstr, 250, tablef) != NULL);
|
||||||
getnextch();
|
getnextch();
|
||||||
{
|
{
|
||||||
int j;
|
int j;
|
||||||
|
@ -243,12 +260,12 @@ int main(int argc, char **argv)
|
||||||
char *opstrp = opcstr, *osendp;
|
char *opstrp = opcstr, *osendp;
|
||||||
int slen = 0;
|
int slen = 0;
|
||||||
|
|
||||||
while (isspace(*opstrp))
|
while (isspace((int)*opstrp))
|
||||||
opstrp++;
|
opstrp++;
|
||||||
|
|
||||||
osendp = opstrp;
|
osendp = opstrp;
|
||||||
while (*osendp) {
|
while (*osendp) {
|
||||||
if (!isspace (*osendp))
|
if (!isspace ((int)*osendp))
|
||||||
slen = osendp - opstrp + 1;
|
slen = osendp - opstrp + 1;
|
||||||
osendp++;
|
osendp++;
|
||||||
}
|
}
|
||||||
|
@ -271,6 +288,5 @@ int main(int argc, char **argv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
printf("};\nint n_defs68k = %d;\n", no_insns);
|
printf("};\nint n_defs68k = %d;\n", no_insns);
|
||||||
fflush(stdout);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -273,7 +273,7 @@ uae_u8* comp_pc_p;
|
||||||
#else
|
#else
|
||||||
// External variables
|
// External variables
|
||||||
// newcpu.cpp
|
// newcpu.cpp
|
||||||
extern bool quit_program;
|
extern int quit_program;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// gb-- Extra data for Basilisk II/JIT
|
// 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));
|
jit_log("<JIT compiler> : separate blockinfo allocation : %s", str_on_off(USE_SEPARATE_BIA));
|
||||||
|
|
||||||
// Build compiler tables
|
// Build compiler tables
|
||||||
read_table68k();
|
init_table68k ();
|
||||||
do_merges();
|
|
||||||
build_comp();
|
build_comp();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -4157,7 +4156,9 @@ void build_comp(void)
|
||||||
int count;
|
int count;
|
||||||
#ifdef WINUAE_ARANYM
|
#ifdef WINUAE_ARANYM
|
||||||
unsigned int cpu_level = 4; // 68040
|
unsigned int cpu_level = 4; // 68040
|
||||||
|
#if 0
|
||||||
const struct cputbl *nfctbl = op_smalltbl_0_nf;
|
const struct cputbl *nfctbl = op_smalltbl_0_nf;
|
||||||
|
#endif
|
||||||
#else
|
#else
|
||||||
#ifdef NOFLAGS_SUPPORT
|
#ifdef NOFLAGS_SUPPORT
|
||||||
struct comptbl *nfctbl = (currprefs.cpu_level >= 5 ? op_smalltbl_0_nf
|
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)
|
int main(void)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
read_table68k ();
|
init_table68k ();
|
||||||
do_merges ();
|
|
||||||
|
|
||||||
opcode_map = (int *) malloc (sizeof (int) * nr_cpuop_funcs);
|
opcode_map = (int *) malloc (sizeof (int) * nr_cpuop_funcs);
|
||||||
opcode_last_postfix = (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)
|
int main(void)
|
||||||
{
|
{
|
||||||
read_table68k();
|
init_table68k ();
|
||||||
do_merges();
|
|
||||||
|
|
||||||
opcode_map = (int *) malloc(sizeof(int) * nr_cpuop_funcs);
|
opcode_map = (int *) malloc(sizeof(int) * nr_cpuop_funcs);
|
||||||
opcode_last_postfix = (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
|
* Inspired by Christian Bauer's Basilisk II
|
||||||
* 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,
|
* This file is part of the ARAnyM project which builds a new and powerful
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
|
||||||
* 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
|
* ARAnyM is free software; you can redistribute it and/or modify
|
||||||
* along with this program; if not, write to the Free Software
|
* it under the terms of the GNU General Public License as published by
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* 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
|
#ifndef CPU_EMULATION_H
|
||||||
#define CPU_EMULATION_H
|
#define CPU_EMULATION_H
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Memory system
|
* Memory system
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
#include "sysdeps.h"
|
||||||
|
#include "memory.h"
|
||||||
|
#include "tools.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
// RAM and ROM pointers (allocated and set by main_*.cpp)
|
// 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 uint32 RAMBaseMac; // RAM base (Mac address space), does not include Low Mem when != 0
|
||||||
extern uint8 *RAMBaseHost; // RAM base (host address space)
|
#endif
|
||||||
extern uint32 RAMSize; // Size of RAM
|
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 uint32 ROMBaseMac; // ROM base (Mac address space)
|
||||||
extern uint8 *ROMBaseHost; // ROM base (host address space)
|
#endif
|
||||||
extern uint32 ROMSize; // Size of ROM
|
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
|
extern memptr FastRAMBase; // Fast-RAM base (Atari address space)
|
||||||
// If we are not using real or direct addressing, the Mac frame buffer gets
|
extern uint8 *FastRAMBaseHost; // Fast-RAM base (host address space)
|
||||||
// mapped to this location. The memory must be allocated by VideoInit().
|
extern memptr VideoRAMBase; // VideoRAM base (Atari address space)
|
||||||
// If multiple monitors are used, they must share the frame buffer
|
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;
|
const uint32 MacFrameBaseMac = 0xa0000000;
|
||||||
extern uint8 *MacFrameBaseHost; // Frame buffer base (host address space)
|
extern uint8 *MacFrameBaseHost; // Frame buffer base (host address space)
|
||||||
extern uint32 MacFrameSize; // Size of frame buffer
|
extern uint32 MacFrameSize; // Size of frame buffer
|
||||||
#endif
|
|
||||||
extern int MacFrameLayout; // Frame buffer layout (see defines below)
|
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
|
// Possible frame buffer layouts
|
||||||
enum {
|
enum {
|
||||||
FLAYOUT_NONE, // No frame buffer
|
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);}
|
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
|
* 680x0 emulation
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Initialization
|
// 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 Exit680x0(void);
|
||||||
extern void InitFrameBufferMapping(void);
|
#if 0
|
||||||
|
extern void AtariReset(void);
|
||||||
// 680x0 dynamic recompilation activation flag
|
|
||||||
#if USE_JIT
|
|
||||||
extern bool UseJIT;
|
|
||||||
#else
|
|
||||||
const bool UseJIT = false;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// 680x0 emulation functions
|
// 680x0 emulation functions
|
||||||
struct M68kRegisters;
|
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 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
|
extern "C" void Execute68kTrap(uint16 trap, M68kRegisters *r); // Execute MacOS 68k trap from EMUL_OP routine
|
||||||
|
|
||||||
// Interrupt functions
|
// Interrupt functions
|
||||||
extern void TriggerInterrupt(void); // Trigger interrupt level 1 (InterruptFlag must be set first)
|
#if 0
|
||||||
extern void TriggerNMI(void); // Trigger interrupt level 7
|
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
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
vim:ts=4:sw=4:
|
||||||
|
*/
|
||||||
|
|
5
BasiliskII/src/uae_cpu/cpudefsa.cpp
Normal file
5
BasiliskII/src/uae_cpu/cpudefsa.cpp
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
/*
|
||||||
|
* cpudefs.cpp must be compiled twice, once for the generator program
|
||||||
|
* and once for the actual executable
|
||||||
|
*/
|
||||||
|
#include "cpudefs.cpp"
|
2
BasiliskII/src/uae_cpu/cpuemu1.cpp
Normal file
2
BasiliskII/src/uae_cpu/cpuemu1.cpp
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
#define PART_1
|
||||||
|
#include "cpuemu.cpp"
|
3
BasiliskII/src/uae_cpu/cpuemu1_nf.cpp
Normal file
3
BasiliskII/src/uae_cpu/cpuemu1_nf.cpp
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
#define NOFLAGS 1
|
||||||
|
#define PART_1
|
||||||
|
#include "cpuemu.cpp"
|
2
BasiliskII/src/uae_cpu/cpuemu2.cpp
Normal file
2
BasiliskII/src/uae_cpu/cpuemu2.cpp
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
#define PART_2
|
||||||
|
#include "cpuemu.cpp"
|
3
BasiliskII/src/uae_cpu/cpuemu2_nf.cpp
Normal file
3
BasiliskII/src/uae_cpu/cpuemu2_nf.cpp
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
#define NOFLAGS 1
|
||||||
|
#define PART_2
|
||||||
|
#include "cpuemu.cpp"
|
2
BasiliskII/src/uae_cpu/cpuemu3.cpp
Normal file
2
BasiliskII/src/uae_cpu/cpuemu3.cpp
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
#define PART_3
|
||||||
|
#include "cpuemu.cpp"
|
3
BasiliskII/src/uae_cpu/cpuemu3_nf.cpp
Normal file
3
BasiliskII/src/uae_cpu/cpuemu3_nf.cpp
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
#define NOFLAGS 1
|
||||||
|
#define PART_3
|
||||||
|
#include "cpuemu.cpp"
|
2
BasiliskII/src/uae_cpu/cpuemu4.cpp
Normal file
2
BasiliskII/src/uae_cpu/cpuemu4.cpp
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
#define PART_4
|
||||||
|
#include "cpuemu.cpp"
|
3
BasiliskII/src/uae_cpu/cpuemu4_nf.cpp
Normal file
3
BasiliskII/src/uae_cpu/cpuemu4_nf.cpp
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
#define NOFLAGS 1
|
||||||
|
#define PART_4
|
||||||
|
#include "cpuemu.cpp"
|
2
BasiliskII/src/uae_cpu/cpuemu5.cpp
Normal file
2
BasiliskII/src/uae_cpu/cpuemu5.cpp
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
#define PART_5
|
||||||
|
#include "cpuemu.cpp"
|
4
BasiliskII/src/uae_cpu/cpuemu5_nf.cpp
Normal file
4
BasiliskII/src/uae_cpu/cpuemu5_nf.cpp
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
#define NOFLAGS 1
|
||||||
|
#define PART_5
|
||||||
|
#include "cpuemu.cpp"
|
||||||
|
|
2
BasiliskII/src/uae_cpu/cpuemu6.cpp
Normal file
2
BasiliskII/src/uae_cpu/cpuemu6.cpp
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
#define PART_6
|
||||||
|
#include "cpuemu.cpp"
|
3
BasiliskII/src/uae_cpu/cpuemu6_nf.cpp
Normal file
3
BasiliskII/src/uae_cpu/cpuemu6_nf.cpp
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
#define NOFLAGS 1
|
||||||
|
#define PART_6
|
||||||
|
#include "cpuemu.cpp"
|
2
BasiliskII/src/uae_cpu/cpuemu7.cpp
Normal file
2
BasiliskII/src/uae_cpu/cpuemu7.cpp
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
#define PART_7
|
||||||
|
#include "cpuemu.cpp"
|
3
BasiliskII/src/uae_cpu/cpuemu7_nf.cpp
Normal file
3
BasiliskII/src/uae_cpu/cpuemu7_nf.cpp
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
#define NOFLAGS 1
|
||||||
|
#define PART_7
|
||||||
|
#include "cpuemu.cpp"
|
2
BasiliskII/src/uae_cpu/cpuemu8.cpp
Normal file
2
BasiliskII/src/uae_cpu/cpuemu8.cpp
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
#define PART_8
|
||||||
|
#include "cpuemu.cpp"
|
3
BasiliskII/src/uae_cpu/cpuemu8_nf.cpp
Normal file
3
BasiliskII/src/uae_cpu/cpuemu8_nf.cpp
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
#define NOFLAGS 1
|
||||||
|
#define PART_8
|
||||||
|
#include "cpuemu.cpp"
|
5
BasiliskII/src/uae_cpu/cpufunctbla.cpp
Normal file
5
BasiliskII/src/uae_cpu/cpufunctbla.cpp
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
/*
|
||||||
|
* cpufunctbl.cpp must be compiled twice, once for the generator program
|
||||||
|
* and once for the actual executable
|
||||||
|
*/
|
||||||
|
#include "cpufunctbl.cpp"
|
1096
BasiliskII/src/uae_cpu/cpummu.cpp
Normal file
1096
BasiliskII/src/uae_cpu/cpummu.cpp
Normal file
File diff suppressed because it is too large
Load Diff
267
BasiliskII/src/uae_cpu/cpummu.h
Normal file
267
BasiliskII/src/uae_cpu/cpummu.h
Normal file
|
@ -0,0 +1,267 @@
|
||||||
|
/*
|
||||||
|
* cpummu.h - MMU emulation
|
||||||
|
*
|
||||||
|
* Copyright (c) 2001-2004 Milan Jurik of ARAnyM dev team (see AUTHORS)
|
||||||
|
*
|
||||||
|
* Inspired by UAE MMU patch
|
||||||
|
*
|
||||||
|
* This file is part of the ARAnyM project which builds a new and powerful
|
||||||
|
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
|
||||||
|
*
|
||||||
|
* ARAnyM is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* ARAnyM is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with ARAnyM; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CPUMMU_H
|
||||||
|
#define CPUMMU_H
|
||||||
|
|
||||||
|
#include "registers.h"
|
||||||
|
|
||||||
|
# include <cstdlib>
|
||||||
|
|
||||||
|
#define MMU_TEST_PTEST 1
|
||||||
|
#define MMU_TEST_VERBOSE 2
|
||||||
|
#define MMU_TEST_FORCE_TABLE_SEARCH 4
|
||||||
|
#define MMU_TEST_NO_BUSERR 8
|
||||||
|
|
||||||
|
extern void mmu_dump_tables(void);
|
||||||
|
|
||||||
|
#define MMU_TTR_LOGICAL_BASE 0xff000000
|
||||||
|
#define MMU_TTR_LOGICAL_MASK 0x00ff0000
|
||||||
|
#define MMU_TTR_BIT_ENABLED (1 << 15)
|
||||||
|
#define MMU_TTR_BIT_SFIELD_ENABLED (1 << 14)
|
||||||
|
#define MMU_TTR_BIT_SFIELD_SUPER (1 << 13)
|
||||||
|
#define MMU_TTR_SFIELD_SHIFT 13
|
||||||
|
#define MMU_TTR_UX_MASK ((1 << 9) | (1 << 8))
|
||||||
|
#define MMU_TTR_UX_SHIFT 8
|
||||||
|
#define MMU_TTR_CACHE_MASK ((1 << 6) | (1 << 5))
|
||||||
|
#define MMU_TTR_CACHE_SHIFT 5
|
||||||
|
#define MMU_TTR_BIT_WRITE_PROTECT (1 << 2)
|
||||||
|
|
||||||
|
#define MMU_UDT_MASK 3
|
||||||
|
#define MMU_PDT_MASK 3
|
||||||
|
|
||||||
|
#define MMU_DES_WP 4
|
||||||
|
#define MMU_DES_USED 8
|
||||||
|
|
||||||
|
/* page descriptors only */
|
||||||
|
#define MMU_DES_MODIFIED 16
|
||||||
|
#define MMU_DES_SUPER (1 << 7)
|
||||||
|
#define MMU_DES_GLOBAL (1 << 10)
|
||||||
|
|
||||||
|
#define MMU_ROOT_PTR_ADDR_MASK 0xfffffe00
|
||||||
|
#define MMU_PTR_PAGE_ADDR_MASK_8 0xffffff80
|
||||||
|
#define MMU_PTR_PAGE_ADDR_MASK_4 0xffffff00
|
||||||
|
|
||||||
|
#define MMU_PAGE_INDIRECT_MASK 0xfffffffc
|
||||||
|
#define MMU_PAGE_ADDR_MASK_8 0xffffe000
|
||||||
|
#define MMU_PAGE_ADDR_MASK_4 0xfffff000
|
||||||
|
#define MMU_PAGE_UR_MASK_8 ((1 << 12) | (1 << 11))
|
||||||
|
#define MMU_PAGE_UR_MASK_4 (1 << 11)
|
||||||
|
#define MMU_PAGE_UR_SHIFT 11
|
||||||
|
|
||||||
|
#define MMU_MMUSR_ADDR_MASK 0xfffff000
|
||||||
|
#define MMU_MMUSR_B (1 << 11)
|
||||||
|
#define MMU_MMUSR_G (1 << 10)
|
||||||
|
#define MMU_MMUSR_U1 (1 << 9)
|
||||||
|
#define MMU_MMUSR_U0 (1 << 8)
|
||||||
|
#define MMU_MMUSR_Ux (MMU_MMUSR_U1 | MMU_MMUSR_U0)
|
||||||
|
#define MMU_MMUSR_S (1 << 7)
|
||||||
|
#define MMU_MMUSR_CM ((1 << 6) | ( 1 << 5))
|
||||||
|
#define MMU_MMUSR_M (1 << 4)
|
||||||
|
#define MMU_MMUSR_W (1 << 2)
|
||||||
|
#define MMU_MMUSR_T (1 << 1)
|
||||||
|
#define MMU_MMUSR_R (1 << 0)
|
||||||
|
|
||||||
|
/* special status word (access error stack frame) */
|
||||||
|
#define MMU_SSW_TM 0x0007
|
||||||
|
#define MMU_SSW_TT 0x0018
|
||||||
|
#define MMU_SSW_SIZE 0x0060
|
||||||
|
#define MMU_SSW_SIZE_B 0x0020
|
||||||
|
#define MMU_SSW_SIZE_W 0x0040
|
||||||
|
#define MMU_SSW_SIZE_L 0x0000
|
||||||
|
#define MMU_SSW_RW 0x0100
|
||||||
|
#define MMU_SSW_LK 0x0200
|
||||||
|
#define MMU_SSW_ATC 0x0400
|
||||||
|
#define MMU_SSW_MA 0x0800
|
||||||
|
|
||||||
|
#define TTR_I0 4
|
||||||
|
#define TTR_I1 5
|
||||||
|
#define TTR_D0 6
|
||||||
|
#define TTR_D1 7
|
||||||
|
|
||||||
|
#define TTR_NO_MATCH 0
|
||||||
|
#define TTR_NO_WRITE 1
|
||||||
|
#define TTR_OK_MATCH 2
|
||||||
|
|
||||||
|
struct mmu_atc_line {
|
||||||
|
uae_u16 tag;
|
||||||
|
unsigned tt : 1;
|
||||||
|
unsigned valid_data : 1;
|
||||||
|
unsigned valid_inst : 1;
|
||||||
|
unsigned global : 1;
|
||||||
|
unsigned modified : 1;
|
||||||
|
unsigned write_protect : 1;
|
||||||
|
unsigned hw : 1;
|
||||||
|
unsigned bus_fault : 1;
|
||||||
|
uaecptr phys;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We don't need to store the whole logical address in the atc cache, as part of
|
||||||
|
* it is encoded as index into the cache. 14 bits of the address are stored in
|
||||||
|
* the tag, this means at least 6 bits must go into the index. The upper two
|
||||||
|
* bits of the tag define the type of data in the atc line:
|
||||||
|
* - 00: a normal memory address
|
||||||
|
* - 11: invalid memory address or hardware access
|
||||||
|
* (generated via ~ATC_TAG(addr) in the slow path)
|
||||||
|
* - 10: empty atc line
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define ATC_TAG_SHIFT 18
|
||||||
|
#define ATC_TAG(addr) ((uae_u32)(addr) >> ATC_TAG_SHIFT)
|
||||||
|
|
||||||
|
|
||||||
|
#define ATC_L1_SIZE_LOG 8
|
||||||
|
#define ATC_L1_SIZE (1 << ATC_L1_SIZE_LOG)
|
||||||
|
|
||||||
|
#define ATC_L1_INDEX(addr) (((addr) >> 12) % ATC_L1_SIZE)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* first level atc cache
|
||||||
|
* indexed by [super][data][rw][idx]
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct mmu_atc_line mmu_atc_l1_array[2][2][ATC_L1_SIZE];
|
||||||
|
extern mmu_atc_l1_array atc_l1[2];
|
||||||
|
extern mmu_atc_l1_array *current_atc;
|
||||||
|
|
||||||
|
#define ATC_L2_SIZE_LOG 12
|
||||||
|
#define ATC_L2_SIZE (1 << ATC_L2_SIZE_LOG)
|
||||||
|
|
||||||
|
#define ATC_L2_INDEX(addr) ((((addr) >> 12) ^ ((addr) >> (32 - ATC_L2_SIZE_LOG))) % ATC_L2_SIZE)
|
||||||
|
|
||||||
|
extern struct mmu_atc_line atc_l2[2][ATC_L2_SIZE];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* lookup address in the level 1 atc cache,
|
||||||
|
* the data and write arguments are constant in the common,
|
||||||
|
* thus allows gcc to generate a constant offset.
|
||||||
|
*/
|
||||||
|
static ALWAYS_INLINE int mmu_lookup(uaecptr addr, bool data, bool write,
|
||||||
|
struct mmu_atc_line **cl)
|
||||||
|
{
|
||||||
|
addr >>= 12;
|
||||||
|
*cl = &(*current_atc)[data][write][addr % ATC_L1_SIZE];
|
||||||
|
return (*cl)->tag == addr >> (ATC_TAG_SHIFT - 12);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* similiar to mmu_user_lookup, but for the use of the moves instruction
|
||||||
|
*/
|
||||||
|
static ALWAYS_INLINE int mmu_user_lookup(uaecptr addr, bool super, bool data,
|
||||||
|
bool write, struct mmu_atc_line **cl)
|
||||||
|
{
|
||||||
|
addr >>= 12;
|
||||||
|
*cl = &atc_l1[super][data][write][addr % ATC_L1_SIZE];
|
||||||
|
return (*cl)->tag == addr >> (ATC_TAG_SHIFT - 12);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern REGPARAM2 uae_u16 mmu_get_word_unaligned(uaecptr addr, int data);
|
||||||
|
extern REGPARAM2 uae_u32 mmu_get_long_unaligned(uaecptr addr, int data);
|
||||||
|
|
||||||
|
extern REGPARAM2 uae_u8 mmu_get_byte_slow(uaecptr addr, int super, int data,
|
||||||
|
int size, struct mmu_atc_line *cl);
|
||||||
|
extern REGPARAM2 uae_u16 mmu_get_word_slow(uaecptr addr, int super, int data,
|
||||||
|
int size, struct mmu_atc_line *cl);
|
||||||
|
extern REGPARAM2 uae_u32 mmu_get_long_slow(uaecptr addr, int super, int data,
|
||||||
|
int size, struct mmu_atc_line *cl);
|
||||||
|
extern REGPARAM2 uae_u64 mmu_get_quad_slow(uaecptr addr, int super, int data,
|
||||||
|
struct mmu_atc_line *cl);
|
||||||
|
|
||||||
|
extern REGPARAM2 void mmu_put_word_unaligned(uaecptr addr, uae_u16 val, int data);
|
||||||
|
extern REGPARAM2 void mmu_put_long_unaligned(uaecptr addr, uae_u32 val, int data);
|
||||||
|
|
||||||
|
extern REGPARAM2 void mmu_put_byte_slow(uaecptr addr, uae_u8 val, int super, int data,
|
||||||
|
int size, struct mmu_atc_line *cl);
|
||||||
|
extern REGPARAM2 void mmu_put_word_slow(uaecptr addr, uae_u16 val, int super, int data,
|
||||||
|
int size, struct mmu_atc_line *cl);
|
||||||
|
extern REGPARAM2 void mmu_put_long_slow(uaecptr addr, uae_u32 val, int super, int data,
|
||||||
|
int size, struct mmu_atc_line *cl);
|
||||||
|
extern REGPARAM2 void mmu_put_quad_slow(uaecptr addr, uae_u64 val, int super, int data,
|
||||||
|
struct mmu_atc_line *cl);
|
||||||
|
|
||||||
|
extern void mmu_make_transparent_region(uaecptr baseaddr, uae_u32 size, int datamode);
|
||||||
|
|
||||||
|
static inline void mmu_set_ttr(int regno, uae_u32 val)
|
||||||
|
{
|
||||||
|
uae_u32 * ttr;
|
||||||
|
switch(regno) {
|
||||||
|
case TTR_I0: ttr = ®s.itt0; break;
|
||||||
|
case TTR_I1: ttr = ®s.itt1; break;
|
||||||
|
case TTR_D0: ttr = ®s.dtt0; break;
|
||||||
|
case TTR_D1: ttr = ®s.dtt1; break;
|
||||||
|
default: abort();
|
||||||
|
}
|
||||||
|
*ttr = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void mmu_set_mmusr(uae_u32 val)
|
||||||
|
{
|
||||||
|
regs.mmusr = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define FC_DATA (regs.s ? 5 : 1)
|
||||||
|
#define FC_INST (regs.s ? 6 : 2)
|
||||||
|
|
||||||
|
extern uaecptr REGPARAM2 mmu_translate(uaecptr addr, int super, int data, int write);
|
||||||
|
|
||||||
|
extern uae_u32 REGPARAM2 sfc_get_long(uaecptr addr);
|
||||||
|
extern uae_u16 REGPARAM2 sfc_get_word(uaecptr addr);
|
||||||
|
extern uae_u8 REGPARAM2 sfc_get_byte(uaecptr addr);
|
||||||
|
extern void REGPARAM2 dfc_put_long(uaecptr addr, uae_u32 val);
|
||||||
|
extern void REGPARAM2 dfc_put_word(uaecptr addr, uae_u16 val);
|
||||||
|
extern void REGPARAM2 dfc_put_byte(uaecptr addr, uae_u8 val);
|
||||||
|
|
||||||
|
|
||||||
|
extern void REGPARAM2 mmu_flush_atc(uaecptr addr, bool super, bool global);
|
||||||
|
extern void REGPARAM2 mmu_flush_atc_all(bool global);
|
||||||
|
extern void REGPARAM2 mmu_op(uae_u32 opcode, uae_u16 extra);
|
||||||
|
|
||||||
|
#ifdef FULLMMU
|
||||||
|
|
||||||
|
extern void REGPARAM2 mmu_reset(void);
|
||||||
|
extern void REGPARAM2 mmu_set_tc(uae_u16 tc);
|
||||||
|
extern void REGPARAM2 mmu_set_super(bool super);
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
static inline void mmu_reset(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void mmu_set_tc(uae_u16 /*tc*/)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void mmu_set_super(bool /*super*/)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* CPUMMU_H */
|
||||||
|
/*
|
||||||
|
vim:ts=4:sw=4:
|
||||||
|
*/
|
2
BasiliskII/src/uae_cpu/cpustbl_nf.cpp
Normal file
2
BasiliskII/src/uae_cpu/cpustbl_nf.cpp
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
#define NOFLAGS 1
|
||||||
|
#include "cpustbl.cpp"
|
5
BasiliskII/src/uae_cpu/cpustbla.cpp
Normal file
5
BasiliskII/src/uae_cpu/cpustbla.cpp
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
/*
|
||||||
|
* cpustbl.cpp must be compiled twice, once for the generator program
|
||||||
|
* and once for the actual executable
|
||||||
|
*/
|
||||||
|
#include "cpustbl.cpp"
|
82
BasiliskII/src/uae_cpu/debug.cpp
Normal file
82
BasiliskII/src/uae_cpu/debug.cpp
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
/*
|
||||||
|
* debug.cpp - CPU debugger
|
||||||
|
*
|
||||||
|
* Copyright (c) 2001-2010 Milan Jurik of ARAnyM dev team (see AUTHORS)
|
||||||
|
*
|
||||||
|
* Inspired by Bernd Schmidt's UAE
|
||||||
|
*
|
||||||
|
* This file is part of the ARAnyM project which builds a new and powerful
|
||||||
|
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
|
||||||
|
*
|
||||||
|
* ARAnyM is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* ARAnyM is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with ARAnyM; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* UAE - The Un*x Amiga Emulator
|
||||||
|
*
|
||||||
|
* Debugger
|
||||||
|
*
|
||||||
|
* (c) 1995 Bernd Schmidt
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "sysdeps.h"
|
||||||
|
|
||||||
|
#include "memory.h"
|
||||||
|
#include "newcpu.h"
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
|
#include "input.h"
|
||||||
|
#include "cpu_emulation.h"
|
||||||
|
|
||||||
|
#include "main.h"
|
||||||
|
|
||||||
|
static int debugger_active = 0;
|
||||||
|
int debugging = 0;
|
||||||
|
int irqindebug = 0;
|
||||||
|
|
||||||
|
int ignore_irq = 0;
|
||||||
|
|
||||||
|
|
||||||
|
void activate_debugger (void)
|
||||||
|
{
|
||||||
|
#ifdef DEBUGGER
|
||||||
|
ndebug::do_skip = false;
|
||||||
|
#endif
|
||||||
|
debugger_active = 1;
|
||||||
|
SPCFLAGS_SET( SPCFLAG_BRK );
|
||||||
|
debugging = 1;
|
||||||
|
/* use_debugger = 1; */
|
||||||
|
}
|
||||||
|
|
||||||
|
void deactivate_debugger(void)
|
||||||
|
{
|
||||||
|
debugging = 0;
|
||||||
|
debugger_active = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void debug (void)
|
||||||
|
{
|
||||||
|
if (ignore_irq && regs.s && !regs.m ) {
|
||||||
|
SPCFLAGS_SET( SPCFLAG_BRK );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#ifdef DEBUGGER
|
||||||
|
ndebug::run();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
vim:ts=4:sw=4:
|
||||||
|
*/
|
|
@ -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
|
* 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.
|
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* MC68881/68040 fpu emulation
|
||||||
* 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
|
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||||
* along with this program; if not, write to the Free Software
|
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* 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
|
#ifndef FPU_CORE_H
|
||||||
|
@ -34,11 +39,15 @@
|
||||||
/* Always use x87 FPU stack on IA-32. */
|
/* Always use x87 FPU stack on IA-32. */
|
||||||
#if defined(X86_ASSEMBLY)
|
#if defined(X86_ASSEMBLY)
|
||||||
#define USE_X87_ASSEMBLY 1
|
#define USE_X87_ASSEMBLY 1
|
||||||
|
#ifndef USE_JIT_FPU
|
||||||
|
#define ACCURATE_SIN_COS_TAN 1
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Only use x87 FPU on x86-64 if long double precision is requested. */
|
/* 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 USE_X87_ASSEMBLY 1
|
||||||
|
#define ACCURATE_SIN_COS_TAN 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* ========================================================================== */
|
/* ========================================================================== */
|
||||||
|
@ -65,10 +74,7 @@ struct fpu_t {
|
||||||
/* --- Floating-Point Control Register --- */
|
/* --- Floating-Point Control Register --- */
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
struct {
|
|
||||||
|
|
||||||
/* Exception Enable Byte */
|
/* Exception Enable Byte */
|
||||||
uae_u32 exception_enable;
|
|
||||||
#define FPCR_EXCEPTION_ENABLE 0x0000ff00
|
#define FPCR_EXCEPTION_ENABLE 0x0000ff00
|
||||||
#define FPCR_EXCEPTION_BSUN 0x00008000
|
#define FPCR_EXCEPTION_BSUN 0x00008000
|
||||||
#define FPCR_EXCEPTION_SNAN 0x00004000
|
#define FPCR_EXCEPTION_SNAN 0x00004000
|
||||||
|
@ -83,21 +89,19 @@ struct fpu_t {
|
||||||
#define FPCR_MODE_CONTROL 0x000000ff
|
#define FPCR_MODE_CONTROL 0x000000ff
|
||||||
|
|
||||||
/* Rounding precision */
|
/* Rounding precision */
|
||||||
uae_u32 rounding_precision;
|
|
||||||
#define FPCR_ROUNDING_PRECISION 0x000000c0
|
#define FPCR_ROUNDING_PRECISION 0x000000c0
|
||||||
#define FPCR_PRECISION_SINGLE 0x00000040
|
#define FPCR_PRECISION_SINGLE 0x00000040
|
||||||
#define FPCR_PRECISION_DOUBLE 0x00000080
|
#define FPCR_PRECISION_DOUBLE 0x00000080
|
||||||
#define FPCR_PRECISION_EXTENDED 0x00000000
|
#define FPCR_PRECISION_EXTENDED 0x00000000
|
||||||
|
|
||||||
/* Rounding mode */
|
/* Rounding mode */
|
||||||
uae_u32 rounding_mode;
|
|
||||||
#define FPCR_ROUNDING_MODE 0x00000030
|
#define FPCR_ROUNDING_MODE 0x00000030
|
||||||
#define FPCR_ROUND_NEAR 0x00000000
|
#define FPCR_ROUND_NEAR 0x00000000
|
||||||
#define FPCR_ROUND_ZERO 0x00000010
|
#define FPCR_ROUND_ZERO 0x00000010
|
||||||
#define FPCR_ROUND_MINF 0x00000020
|
#define FPCR_ROUND_MINF 0x00000020
|
||||||
#define FPCR_ROUND_PINF 0x00000030
|
#define FPCR_ROUND_PINF 0x00000030
|
||||||
|
|
||||||
} fpcr;
|
uae_u32 fpcr;
|
||||||
|
|
||||||
/* ---------------------------------------------------------------------- */
|
/* ---------------------------------------------------------------------- */
|
||||||
/* --- Floating-Point Status Register --- */
|
/* --- Floating-Point Status Register --- */
|
||||||
|
@ -107,7 +111,7 @@ struct fpu_t {
|
||||||
|
|
||||||
/* Floating-Point Condition Code Byte */
|
/* Floating-Point Condition Code Byte */
|
||||||
uae_u32 condition_codes;
|
uae_u32 condition_codes;
|
||||||
#define FPSR_CCB 0xff000000
|
#define FPSR_CCB 0x0f000000
|
||||||
#define FPSR_CCB_NEGATIVE 0x08000000
|
#define FPSR_CCB_NEGATIVE 0x08000000
|
||||||
#define FPSR_CCB_ZERO 0x04000000
|
#define FPSR_CCB_ZERO 0x04000000
|
||||||
#define FPSR_CCB_INFINITY 0x02000000
|
#define FPSR_CCB_INFINITY 0x02000000
|
||||||
|
@ -133,7 +137,7 @@ struct fpu_t {
|
||||||
|
|
||||||
/* Accrued Exception Byte */
|
/* Accrued Exception Byte */
|
||||||
uae_u32 accrued_exception;
|
uae_u32 accrued_exception;
|
||||||
#define FPSR_ACCRUED_EXCEPTION 0x000000ff
|
#define FPSR_ACCRUED_EXCEPTION 0x000000f8
|
||||||
#define FPSR_ACCR_IOP 0x00000080
|
#define FPSR_ACCR_IOP 0x00000080
|
||||||
#define FPSR_ACCR_OVFL 0x00000040
|
#define FPSR_ACCR_OVFL 0x00000040
|
||||||
#define FPSR_ACCR_UNFL 0x00000020
|
#define FPSR_ACCR_UNFL 0x00000020
|
||||||
|
@ -219,7 +223,7 @@ struct fpu_t {
|
||||||
extern fpu_t fpu;
|
extern fpu_t fpu;
|
||||||
|
|
||||||
/* Return the address of a particular register */
|
/* 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]; }
|
{ return &fpu.registers[i]; }
|
||||||
|
|
||||||
/* Dump functions for m68k_dumpstate */
|
/* Dump functions for m68k_dumpstate */
|
||||||
|
@ -227,16 +231,16 @@ extern void fpu_dump_registers(void);
|
||||||
extern void fpu_dump_flags(void);
|
extern void fpu_dump_flags(void);
|
||||||
|
|
||||||
/* Accessors to FPU Control Register */
|
/* Accessors to FPU Control Register */
|
||||||
static inline uae_u32 get_fpcr(void);
|
//static inline uae_u32 get_fpcr(void);
|
||||||
static inline void set_fpcr(uae_u32 new_fpcr);
|
//static inline void set_fpcr(uae_u32 new_fpcr);
|
||||||
|
|
||||||
/* Accessors to FPU Status Register */
|
/* Accessors to FPU Status Register */
|
||||||
static inline uae_u32 get_fpsr(void);
|
//static inline uae_u32 get_fpsr(void);
|
||||||
static inline void set_fpsr(uae_u32 new_fpsr);
|
//static inline void set_fpsr(uae_u32 new_fpsr);
|
||||||
|
|
||||||
/* Accessors to FPU Instruction Address Register */
|
/* Accessors to FPU Instruction Address Register */
|
||||||
static inline uae_u32 get_fpiar();
|
//static inline uae_u32 get_fpiar();
|
||||||
static inline void set_fpiar(uae_u32 new_fpiar);
|
//static inline void set_fpiar(uae_u32 new_fpiar);
|
||||||
|
|
||||||
/* Initialization / Finalization */
|
/* Initialization / Finalization */
|
||||||
extern void fpu_init(bool integral_68040);
|
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 */
|
/* Floating-point system control operations */
|
||||||
void fpuop_save(uae_u32 opcode) REGPARAM;
|
void fpuop_save(uae_u32 opcode) REGPARAM;
|
||||||
void fpuop_restore(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 */
|
#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
|
* 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.
|
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* MC68881/68040 fpu emulation
|
||||||
* 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
|
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||||
* along with this program; if not, write to the Free Software
|
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* 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
|
#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
|
* 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.
|
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* MC68881/68040 fpu emulation
|
||||||
* 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
|
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||||
* along with this program; if not, write to the Free Software
|
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* 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
|
#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
|
* 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.
|
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* MC68881/68040 fpu emulation
|
||||||
* 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
|
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||||
* along with this program; if not, write to the Free Software
|
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* 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 */
|
/* 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
|
* 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.
|
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* MC68881/68040 fpu emulation
|
||||||
* 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
|
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||||
* along with this program; if not, write to the Free Software
|
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* 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
|
#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 */
|
/* Make FPSR according to the value passed in argument */
|
||||||
PRIVATE inline void FFPU make_fpsr(fpu_register const & r)
|
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 */
|
/* Return the corresponding ID of the current floating-point condition codes */
|
||||||
/* NOTE: only valid for evaluation of a condition */
|
/* NOTE: only valid for evaluation of a condition */
|
||||||
|
@ -181,27 +186,27 @@ PRIVATE inline uae_u32 FFPU get_fpccr(void)
|
||||||
uae_u32 fpccr = 0;
|
uae_u32 fpccr = 0;
|
||||||
if (isnan(FPU result))
|
if (isnan(FPU result))
|
||||||
fpccr |= FPSR_CCB_NAN;
|
fpccr |= FPSR_CCB_NAN;
|
||||||
else if (FPU result == 0.0)
|
else if (isinf(FPU result))
|
||||||
fpccr |= FPSR_CCB_ZERO;
|
|
||||||
else if (FPU result < 0.0)
|
|
||||||
fpccr |= FPSR_CCB_NEGATIVE;
|
|
||||||
if (isinf(FPU result))
|
|
||||||
fpccr |= FPSR_CCB_INFINITY;
|
fpccr |= FPSR_CCB_INFINITY;
|
||||||
|
else if (iszero(FPU result))
|
||||||
|
fpccr |= FPSR_CCB_ZERO;
|
||||||
|
if (isneg(FPU result))
|
||||||
|
fpccr |= FPSR_CCB_NEGATIVE;
|
||||||
return fpccr;
|
return fpccr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* M68k to native floating-point condition codes - SELF */
|
/* M68k to native floating-point condition codes - SELF */
|
||||||
PRIVATE inline void FFPU set_fpccr(uae_u32 new_fpcond)
|
PRIVATE inline void FFPU set_fpccr(uae_u32 new_fpcond)
|
||||||
{
|
{
|
||||||
|
bool negative = (new_fpcond & FPSR_CCB_NEGATIVE) != 0;
|
||||||
if (new_fpcond & FPSR_CCB_NAN)
|
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)
|
else if (new_fpcond & FPSR_CCB_ZERO)
|
||||||
FPU result = 0.0;
|
make_zero(FPU result, negative);
|
||||||
else if (new_fpcond & FPSR_CCB_NEGATIVE)
|
|
||||||
FPU result = -1.0;
|
|
||||||
else
|
else
|
||||||
FPU result = +1.0;
|
FPU result = negative ? -1.0 : +1.0;
|
||||||
/* gb-- where is Infinity ? */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make FPSR according to the value passed in argument */
|
/* 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 */
|
/* 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); }
|
{ return ((uae_u32 *)& FPU fpsr.condition_codes); }
|
||||||
|
|
||||||
#endif /* FPU_FLAGS_H */
|
#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
|
* 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.
|
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* MC68881/68040 fpu emulation
|
||||||
* 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
|
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||||
* along with this program; if not, write to the Free Software
|
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* 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
|
#ifndef FPU_PUBLIC_HEADER_H
|
||||||
|
@ -46,4 +51,9 @@
|
||||||
#include "fpu/types.h"
|
#include "fpu/types.h"
|
||||||
#include "fpu/core.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 */
|
#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
|
* 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.
|
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* MC68881/68040 fpu emulation
|
||||||
* 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
|
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||||
* along with this program; if not, write to the Free Software
|
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* 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
|
#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_dest_flags(fpu_register const & r);
|
||||||
PRIVATE inline void FFPU get_source_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_nan(fpu_register & r, bool negative);
|
||||||
PRIVATE inline void FFPU make_zero_positive(fpu_register & r);
|
PRIVATE inline void FFPU make_zero(fpu_register & r, bool negative);
|
||||||
PRIVATE inline void FFPU make_zero_negative(fpu_register & r);
|
PRIVATE inline void FFPU make_inf(fpu_register & r, bool negative);
|
||||||
PRIVATE inline void FFPU make_inf_positive(fpu_register & r);
|
|
||||||
PRIVATE inline void FFPU make_inf_negative(fpu_register & r);
|
|
||||||
|
|
||||||
PRIVATE inline void FFPU fast_scale(fpu_register & r, int add);
|
// MJ PRIVATE inline void FFPU fast_scale(fpu_register & r, int add);
|
||||||
PRIVATE inline fpu_register FFPU fast_fgetexp(fpu_register const & r);
|
PRIVATE inline fpu_register FFPU fast_fgetexp(fpu_register const & r);
|
||||||
|
|
||||||
// May be optimized for particular processors
|
// May be optimized for particular processors
|
||||||
|
|
2110
BasiliskII/src/uae_cpu/fpu/fpu_mpfr.cpp
Normal file
2110
BasiliskII/src/uae_cpu/fpu/fpu_mpfr.cpp
Normal file
File diff suppressed because it is too large
Load Diff
|
@ -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
|
* MC68881/68040 fpu emulation
|
||||||
* 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 program is distributed in the hope that it will be useful,
|
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* New framework, copyright 2000-2001 Gwenole Beauchesne
|
||||||
* GNU General Public License for more details.
|
* Adapted for JIT compilation (c) Bernd Meyer, 2000-2001
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* ARAnyM is free software; you can redistribute it and/or modify
|
||||||
* along with this program; if not, write to the Free Software
|
* it under the terms of the GNU General Public License as published by
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* 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:
|
* Following fixes by Lauri Pesonen, July 1999:
|
||||||
*
|
*
|
||||||
* FMOVEM list handling:
|
* FMOVEM list handling:
|
||||||
|
@ -86,9 +97,8 @@
|
||||||
* - Precision rounding single/double
|
* - Precision rounding single/double
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "sysdeps.h"
|
#include "sysdeps.h"
|
||||||
#include <math.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "readcpu.h"
|
#include "readcpu.h"
|
||||||
#include "newcpu.h"
|
#include "newcpu.h"
|
||||||
|
@ -97,6 +107,17 @@
|
||||||
#include "fpu/fpu.h"
|
#include "fpu/fpu.h"
|
||||||
#include "fpu/fpu_uae.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 */
|
/* Global FPU context */
|
||||||
fpu_t fpu;
|
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",
|
sprintf(temp_str, "%s: %.04f, %.04f, %.04f, %.04f, %.04f, %.04f, %.04f, %.04f\n",
|
||||||
str,
|
str,
|
||||||
get_register(0), get_register(1), get_register(2), get_register(3),
|
fpu_get_register(0), fpu_get_register(1), fpu_get_register(2), fpu_get_register(3),
|
||||||
get_register(4), get_register(5), get_register(6), get_register(7) );
|
fpu_get_register(4), fpu_get_register(5), fpu_get_register(6), fpu_get_register(7) );
|
||||||
|
|
||||||
fpu_debug((temp_str));
|
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
|
#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)
|
PRIVATE inline bool FFPU do_isnan(fpu_register const & r)
|
||||||
{
|
{
|
||||||
uae_u32 * p = (uae_u32 *)&r;
|
fpu_register_parts const p = { r };
|
||||||
if ((p[FHI] & 0x7FF00000) == 0x7FF00000) {
|
if ((p.parts[FHI] & 0x7FF00000) == 0x7FF00000) {
|
||||||
// logical or is faster here.
|
// logical or is faster here.
|
||||||
if ((p[FHI] & 0x000FFFFF) || p[FLO]) {
|
if ((p.parts[FHI] & 0x000FFFFF) || p.parts[FLO]) {
|
||||||
return true;
|
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)
|
PRIVATE inline bool FFPU do_isinf(fpu_register const & r)
|
||||||
{
|
{
|
||||||
uae_u32 * p = (uae_u32 *)&r;
|
fpu_register_parts const p = { r };
|
||||||
if (((p[FHI] & 0x7FF00000) == 0x7FF00000) && p[FLO] == 0) {
|
if ((p.parts[FHI] & 0x7FF00000) == 0x7FF00000 && p.parts[FLO] == 0) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
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)
|
PRIVATE inline bool FFPU do_isneg(fpu_register const & r)
|
||||||
{
|
{
|
||||||
uae_u32 * p = (uae_u32 *)&r;
|
fpu_register_parts const p = { r };
|
||||||
return ((p[FHI] & 0x80000000) != 0);
|
return ((p.parts[FHI] & 0x80000000) != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef HAVE_ISZERO
|
#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)
|
PRIVATE inline bool FFPU do_iszero(fpu_register const & r)
|
||||||
{
|
{
|
||||||
uae_u32 * p = (uae_u32 *)&r;
|
fpu_register_parts const p = { r };
|
||||||
return (((p[FHI] & 0x7FF00000) == 0) && p[FLO] == 0);
|
return (((p.parts[FHI] & 0x7FF00000) == 0) && p.parts[FLO] == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// May be optimized for particular processors
|
// 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;
|
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;
|
fpu_register_parts p;
|
||||||
p[FLO] = 0xffffffff;
|
p.parts[FLO] = 0xffffffff;
|
||||||
p[FHI] = 0x7fffffff;
|
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;
|
fpu_register_parts p;
|
||||||
p[FLO] = p[FHI] = 0;
|
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;
|
fpu_register_parts p;
|
||||||
p[FLO] = 0;
|
p.parts[FLO] = 0;
|
||||||
p[FHI] = 0x80000000;
|
p.parts[FHI] = negative ? 0xFFF00000 : 0x7FF00000;
|
||||||
}
|
r = p.val;
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PRIVATE inline void FFPU fast_scale(fpu_register & r, int add)
|
PRIVATE inline void FFPU fast_scale(fpu_register & r, int add)
|
||||||
{
|
{
|
||||||
uae_u32 * const p = (uae_u32 *)&r;
|
fpu_register_parts p = { r };
|
||||||
int exp = (p[FHI] & 0x7FF00000) >> 20;
|
int exp = (p.parts[FHI] & 0x7FF00000) >> 20;
|
||||||
// TODO: overflow flags
|
// TODO: overflow flags
|
||||||
exp += add;
|
exp += add;
|
||||||
if(exp >= 2047) {
|
if(exp >= 2047) {
|
||||||
make_inf_positive(r);
|
make_inf(r, false);
|
||||||
|
return;
|
||||||
} else if(exp < 0) {
|
} else if(exp < 0) {
|
||||||
// keep sign (+/- 0)
|
// keep sign (+/- 0)
|
||||||
p[FHI] &= 0x80000000;
|
p.parts[FHI] &= 0x80000000;
|
||||||
} else {
|
} 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)
|
PRIVATE inline fpu_register FFPU fast_fgetexp(fpu_register const & r)
|
||||||
{
|
{
|
||||||
uae_u32 * const p = (uae_u32 *)&r;
|
fpu_register_parts const p = { r };
|
||||||
int exp = (p[FHI] & 0x7FF00000) >> 20;
|
int exp = (p.parts[FHI] & 0x7FF00000) >> 20;
|
||||||
return( exp - 1023 );
|
return( exp - 1023 );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Normalize to range 1..2
|
// Normalize to range 1..2
|
||||||
PRIVATE inline void FFPU fast_remove_exponent(fpu_register & r)
|
PRIVATE inline void FFPU fast_remove_exponent(fpu_register & r)
|
||||||
{
|
{
|
||||||
uae_u32 * const p = (uae_u32 *)&r;
|
fpu_register_parts p = { r };
|
||||||
p[FHI] = (p[FHI] & 0x800FFFFF) | 0x3FF00000;
|
p.parts[FHI] = (p.parts[FHI] & 0x800FFFFF) | 0x3FF00000;
|
||||||
|
r = p.val;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The sign of the quotient is the exclusive-OR of the sign bits
|
// The sign of the quotient is the exclusive-OR of the sign bits
|
||||||
// of the source and destination operands.
|
// of the source and destination operands.
|
||||||
PRIVATE inline uae_u32 FFPU get_quotient_sign(fpu_register const & ra, fpu_register const & rb)
|
PRIVATE inline uae_u32 FFPU get_quotient_sign(fpu_register const & ra, fpu_register const & rb)
|
||||||
{
|
{
|
||||||
uae_u32 * const a = (uae_u32 *)&ra;
|
fpu_register_parts const a = { ra };
|
||||||
uae_u32 * const b = (uae_u32 *)&rb;
|
fpu_register_parts const b = { rb };
|
||||||
return (((a[FHI] ^ b[FHI]) & 0x80000000) ? FPSR_QUOTIENT_SIGN : 0);
|
return (((a.parts[FHI] ^ b.parts[FHI]) & 0x80000000) ? FPSR_QUOTIENT_SIGN : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Quotient Byte is loaded with the sign and least significant
|
// 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);
|
return (0.0);
|
||||||
|
|
||||||
fpu_register result;
|
fpu_register result;
|
||||||
uae_u32 * p = (uae_u32 *)&result;
|
fpu_register_parts p;
|
||||||
|
|
||||||
uae_u32 sign = (value & 0x80000000);
|
uae_u32 sign = (value & 0x80000000);
|
||||||
uae_u32 exp = ((value & 0x7F800000) >> 23) + 1023 - 127;
|
uae_u32 exp = ((value & 0x7F800000) >> 23) + 1023 - 127;
|
||||||
|
|
||||||
p[FLO] = value << 29;
|
p.parts[FLO] = value << 29;
|
||||||
p[FHI] = sign | (exp << 20) | ((value & 0x007FFFFF) >> 3);
|
p.parts[FHI] = sign | (exp << 20) | ((value & 0x007FFFFF) >> 3);
|
||||||
|
|
||||||
|
result = p.val;
|
||||||
|
|
||||||
fpu_debug(("make_single (%X) = %.04f\n",value,(double)result));
|
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;
|
return 0;
|
||||||
|
|
||||||
uae_u32 result;
|
uae_u32 result;
|
||||||
uae_u32 *p = (uae_u32 *)&src;
|
fpu_register_parts const p = { src };
|
||||||
|
|
||||||
uae_u32 sign = (p[FHI] & 0x80000000);
|
uae_u32 sign = (p.parts[FHI] & 0x80000000);
|
||||||
uae_u32 exp = (p[FHI] & 0x7FF00000) >> 20;
|
uae_u32 exp = (p.parts[FHI] & 0x7FF00000) >> 20;
|
||||||
|
|
||||||
if(exp + 127 < 1023) {
|
if(exp + 127 < 1023) {
|
||||||
exp = 0;
|
exp = 0;
|
||||||
|
@ -414,7 +428,7 @@ PRIVATE inline uae_u32 FFPU extract_single(fpu_register const & src)
|
||||||
exp = exp + 127 - 1023;
|
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));
|
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;
|
return 0.0;
|
||||||
|
|
||||||
fpu_register result;
|
fpu_register result;
|
||||||
uae_u32 *p = (uae_u32 *)&result;
|
fpu_register_parts p;
|
||||||
|
|
||||||
uae_u32 sign = wrd1 & 0x80000000;
|
uae_u32 sign = wrd1 & 0x80000000;
|
||||||
uae_u32 exp = (wrd1 >> 16) & 0x7fff;
|
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.
|
// drop the explicit integer bit.
|
||||||
p[FLO] = (wrd2 << 21) | (wrd3 >> 11);
|
p.parts[FLO] = (wrd2 << 21) | (wrd3 >> 11);
|
||||||
p[FHI] = sign | (exp << 20) | ((wrd2 & 0x7FFFFFFF) >> 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));
|
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?
|
// Is it zero?
|
||||||
if ((wrd1 & 0x7fff0000) == 0 && wrd2 == 0 && wrd3 == 0) {
|
if ((wrd1 & 0x7fff0000) == 0 && wrd2 == 0 && wrd3 == 0) {
|
||||||
make_zero_positive(result);
|
make_zero(result, false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Is it NaN?
|
// Is it NaN?
|
||||||
if( (wrd1 & 0x7FFF0000) == 0x7FFF0000 ) {
|
if( (wrd1 & 0x7FFF0000) == 0x7FFF0000 ) {
|
||||||
if( (wrd1 & 0x0000FFFF) || wrd2 || wrd3 ) {
|
if( (wrd1 & 0x0000FFFF) || wrd2 || wrd3 ) {
|
||||||
make_nan(result);
|
make_nan(result, (wrd1 & 0x80000000) != 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -511,11 +527,13 @@ PRIVATE inline void FFPU make_extended_no_normalize(
|
||||||
}
|
}
|
||||||
|
|
||||||
// drop the explicit integer bit.
|
// drop the explicit integer bit.
|
||||||
uae_u32 *p = (uae_u32 *)&result;
|
fpu_register_parts p;
|
||||||
p[FLO] = (wrd2 << 21) | (wrd3 >> 11);
|
p.parts[FLO] = (wrd2 << 21) | (wrd3 >> 11);
|
||||||
p[FHI] = sign | (exp << 20) | ((wrd2 & 0x7FFFFFFF) >> 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
|
// from_exten
|
||||||
|
@ -527,14 +545,14 @@ PRIVATE inline void FFPU extract_extended(fpu_register const & src,
|
||||||
*wrd1 = *wrd2 = *wrd3 = 0;
|
*wrd1 = *wrd2 = *wrd3 = 0;
|
||||||
return;
|
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
|
// Check for maximum
|
||||||
if(exp == 0x7FF) {
|
if(exp == 0x7FF) {
|
||||||
exp = 0x7FFF;
|
exp = 0x7FFF;
|
||||||
|
@ -544,8 +562,8 @@ PRIVATE inline void FFPU extract_extended(fpu_register const & src,
|
||||||
|
|
||||||
*wrd1 = sign | (exp << 16);
|
*wrd1 = sign | (exp << 16);
|
||||||
// always set the explicit integer bit.
|
// always set the explicit integer bit.
|
||||||
*wrd2 = 0x80000000 | ((p[FHI] & 0x000FFFFF) << 11) | ((p[FLO] & 0xFFE00000) >> 21);
|
*wrd2 = 0x80000000 | ((p.parts[FHI] & 0x000FFFFF) << 11) | ((p.parts[FLO] & 0xFFE00000) >> 21);
|
||||||
*wrd3 = p[FLO] << 11;
|
*wrd3 = p.parts[FLO] << 11;
|
||||||
|
|
||||||
fpu_debug(("extract_extended (%.04f) = %X,%X,%X\n",(double)src,*wrd1,*wrd2,*wrd3));
|
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;
|
return 0.0;
|
||||||
|
|
||||||
fpu_register result;
|
fpu_register result;
|
||||||
uae_u32 *p = (uae_u32 *)&result;
|
fpu_register_parts p;
|
||||||
p[FLO] = wrd2;
|
p.parts[FLO] = wrd2;
|
||||||
p[FHI] = wrd1;
|
p.parts[FHI] = wrd1;
|
||||||
|
|
||||||
|
result = p.val;
|
||||||
|
|
||||||
fpu_debug(("make_double (%X,%X) = %.04f\n",wrd1,wrd2,(double)result));
|
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;
|
return;
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
uae_u32 *p = (uae_u32 *)&src;
|
fpu_register_parts const p = { src };
|
||||||
*wrd2 = p[FLO];
|
*wrd2 = p.parts[FLO];
|
||||||
*wrd1 = p[FHI];
|
*wrd1 = p.parts[FHI];
|
||||||
|
|
||||||
fpu_debug(("extract_double (%.04f) = %X,%X\n",(double)src,*wrd1,*wrd2));
|
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)
|
PRIVATE inline void FFPU make_fpsr(fpu_register const & r)
|
||||||
{
|
{
|
||||||
FPU fpsr.condition_codes
|
FPU fpsr.condition_codes
|
||||||
= ((r == 0.0) ? NATIVE_FFLAG_ZERO : 0)
|
= (iszero(r) ? NATIVE_FFLAG_ZERO : 0)
|
||||||
| ((r < 0.0) ? NATIVE_FFLAG_NEGATIVE : 0)
|
| (isneg(r) ? NATIVE_FFLAG_NEGATIVE : 0)
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -622,25 +642,25 @@ PRIVATE inline uae_u32 FFPU extract_single(fpu_register const & src)
|
||||||
fpu_register src0 = src;
|
fpu_register src0 = src;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (src == 0.0)
|
if (src == 0.0)
|
||||||
return 0;
|
return 0;
|
||||||
if (src < 0) {
|
if (src < 0) {
|
||||||
tmp = 0x80000000;
|
tmp = 0x80000000;
|
||||||
src = -src;
|
src = -src;
|
||||||
} else {
|
} else {
|
||||||
tmp = 0;
|
tmp = 0;
|
||||||
}
|
}
|
||||||
frac = frexp (src, &expon);
|
frac = frexp (src, &expon);
|
||||||
frac += 0.5 / 16777216.0;
|
frac += 0.5 / 16777216.0;
|
||||||
if (frac >= 1.0) {
|
if (frac >= 1.0) {
|
||||||
frac /= 2.0;
|
frac /= 2.0;
|
||||||
expon++;
|
expon++;
|
||||||
}
|
}
|
||||||
result = tmp | (((expon + 127 - 1) & 0xff) << 23) | (((int) (frac * 16777216.0)) & 0x7fffff);
|
result = tmp | (((expon + 127 - 1) & 0xff) << 23) | (((int) (frac * 16777216.0)) & 0x7fffff);
|
||||||
|
|
||||||
// fpu_debug(("extract_single (%.04f) = %X\n",(float)src0,result));
|
// fpu_debug(("extract_single (%.04f) = %X\n",(float)src0,result));
|
||||||
|
|
||||||
return (result);
|
return (result);
|
||||||
}
|
}
|
||||||
|
|
||||||
// to exten
|
// to exten
|
||||||
|
@ -895,11 +915,9 @@ PRIVATE inline int FFPU get_fp_value (uae_u32 opcode, uae_u16 extra, fpu_registe
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
ad = m68k_areg (regs, reg);
|
ad = m68k_areg (regs, reg);
|
||||||
m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size];
|
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size];
|
ad = m68k_areg (regs, reg) - (reg == 7 ? sz2[size] : sz1[size]);
|
||||||
ad = m68k_areg (regs, reg);
|
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword();
|
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 m68k_getpc()=%X\n",m68k_getpc()));
|
||||||
fpu_debug(("get_fp_value ad=%X\n",ad));
|
fpu_debug(("get_fp_value ad=%X\n",ad));
|
||||||
fpu_debug(("get_fp_value get_long (ad)=%X\n",get_long (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, 0, 0)-64, 64 );
|
||||||
dump_first_bytes( get_real_address(ad), 64 );
|
dump_first_bytes( get_real_address(ad, 0, 0), 64 );
|
||||||
|
|
||||||
switch (size) {
|
switch (size) {
|
||||||
case 0:
|
case 0:
|
||||||
|
@ -988,6 +1006,15 @@ PRIVATE inline int FFPU get_fp_value (uae_u32 opcode, uae_u16 extra, fpu_registe
|
||||||
return 0;
|
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));
|
// fpu_debug(("get_fp_value result = %.04f\n",(float)src));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -1204,7 +1231,7 @@ PRIVATE inline int FFPU fpp_cond(int condition)
|
||||||
#if 0
|
#if 0
|
||||||
return fpcctrue(condition);
|
return fpcctrue(condition);
|
||||||
#else
|
#else
|
||||||
switch (condition) {
|
switch (condition & 0x1f) {
|
||||||
case 0x00: CONDRET("False",0);
|
case 0x00: CONDRET("False",0);
|
||||||
case 0x01: CONDRET("Equal",Z);
|
case 0x01: CONDRET("Equal",Z);
|
||||||
case 0x02: CONDRET("Ordered Greater Than",!(NaN || Z || N));
|
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);
|
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) {
|
if (cc == -1) {
|
||||||
m68k_setpc (oldpc);
|
m68k_setpc (oldpc);
|
||||||
op_illg (opcode);
|
op_illg (opcode);
|
||||||
|
@ -1516,8 +1543,7 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra)
|
||||||
if ((opcode & 0x38) == 0) {
|
if ((opcode & 0x38) == 0) {
|
||||||
if (extra & 0x2000) { // dr bit
|
if (extra & 0x2000) { // dr bit
|
||||||
if (extra & 0x1000) {
|
if (extra & 0x1000) {
|
||||||
// according to the manual, the msb bits are always zero.
|
m68k_dreg (regs, opcode & 7) = get_fpcr();
|
||||||
m68k_dreg (regs, opcode & 7) = get_fpcr() & 0xFFFF;
|
|
||||||
fpu_debug(("FMOVEM FPU fpcr (%X) -> D%d\n", get_fpcr(), opcode & 7));
|
fpu_debug(("FMOVEM FPU fpcr (%X) -> D%d\n", get_fpcr(), opcode & 7));
|
||||||
}
|
}
|
||||||
if (extra & 0x0800) {
|
if (extra & 0x0800) {
|
||||||
|
@ -1548,8 +1574,7 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra)
|
||||||
else if ((opcode & 0x38) == 8) {
|
else if ((opcode & 0x38) == 8) {
|
||||||
if (extra & 0x2000) { // dr bit
|
if (extra & 0x2000) { // dr bit
|
||||||
if (extra & 0x1000) {
|
if (extra & 0x1000) {
|
||||||
// according to the manual, the msb bits are always zero.
|
m68k_areg (regs, opcode & 7) = get_fpcr();
|
||||||
m68k_areg (regs, opcode & 7) = get_fpcr() & 0xFFFF;
|
|
||||||
fpu_debug(("FMOVEM FPU fpcr (%X) -> A%d\n", get_fpcr(), opcode & 7));
|
fpu_debug(("FMOVEM FPU fpcr (%X) -> A%d\n", get_fpcr(), opcode & 7));
|
||||||
}
|
}
|
||||||
if (extra & 0x0800) {
|
if (extra & 0x0800) {
|
||||||
|
@ -1612,8 +1637,7 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra)
|
||||||
}
|
}
|
||||||
ad -= incr;
|
ad -= incr;
|
||||||
if (extra & 0x1000) {
|
if (extra & 0x1000) {
|
||||||
// according to the manual, the msb bits are always zero.
|
put_long (ad, get_fpcr());
|
||||||
put_long (ad, get_fpcr() & 0xFFFF);
|
|
||||||
fpu_debug(("FMOVEM FPU fpcr (%X) -> mem %X\n", get_fpcr(), ad ));
|
fpu_debug(("FMOVEM FPU fpcr (%X) -> mem %X\n", get_fpcr(), ad ));
|
||||||
ad += 4;
|
ad += 4;
|
||||||
}
|
}
|
||||||
|
@ -1906,6 +1930,8 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra)
|
||||||
FPU registers[reg] = 1.0e256;
|
FPU registers[reg] = 1.0e256;
|
||||||
fpu_debug(("FP const: 1.0e256\n"));
|
fpu_debug(("FP const: 1.0e256\n"));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// Valid for 64 bits only (see fpu.cpp)
|
||||||
#if 0
|
#if 0
|
||||||
case 0x3c:
|
case 0x3c:
|
||||||
FPU registers[reg] = 1.0e512;
|
FPU registers[reg] = 1.0e512;
|
||||||
|
@ -1942,7 +1968,114 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
fpu_debug(("returned from get_fp_value m68k_getpc()=%X\n",m68k_getpc()));
|
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) {
|
switch (extra & 0x7f) {
|
||||||
case 0x00: /* FMOVE */
|
case 0x00: /* FMOVE */
|
||||||
fpu_debug(("FMOVE %.04f\n",(double)src));
|
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_debug(("FINT %.04f\n",(double)src));
|
||||||
// FPU registers[reg] = (int) (src + 0.5);
|
// FPU registers[reg] = (int) (src + 0.5);
|
||||||
// FIXME: use native rounding mode flags
|
// FIXME: use native rounding mode flags
|
||||||
switch (get_fpcr() & 0x30) {
|
switch (get_fpcr() & FPCR_ROUNDING_MODE) {
|
||||||
case FPCR_ROUND_ZERO:
|
case FPCR_ROUND_ZERO:
|
||||||
FPU registers[reg] = round_to_zero(src);
|
FPU registers[reg] = round_to_zero(src);
|
||||||
break;
|
break;
|
||||||
|
@ -2075,7 +2208,10 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra)
|
||||||
break;
|
break;
|
||||||
case 0x1a: /* FNEG */
|
case 0x1a: /* FNEG */
|
||||||
fpu_debug(("FNEG %.04f\n",(double)src));
|
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]);
|
make_fpsr(FPU registers[reg]);
|
||||||
break;
|
break;
|
||||||
case 0x1c: /* FACOS */
|
case 0x1c: /* FACOS */
|
||||||
|
@ -2092,7 +2228,7 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra)
|
||||||
fpu_debug(("FGETEXP %.04f\n",(double)src));
|
fpu_debug(("FGETEXP %.04f\n",(double)src));
|
||||||
#if FPU_HAVE_IEEE_DOUBLE
|
#if FPU_HAVE_IEEE_DOUBLE
|
||||||
if( isinf(src) ) {
|
if( isinf(src) ) {
|
||||||
make_nan( FPU registers[reg] );
|
make_nan( FPU registers[reg], isneg(src) );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
FPU registers[reg] = fast_fgetexp( src );
|
FPU registers[reg] = fast_fgetexp( src );
|
||||||
|
@ -2116,7 +2252,7 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra)
|
||||||
FPU registers[reg] = 0;
|
FPU registers[reg] = 0;
|
||||||
}
|
}
|
||||||
else if( isinf(src) ) {
|
else if( isinf(src) ) {
|
||||||
make_nan( FPU registers[reg] );
|
make_nan( FPU registers[reg], isneg(src) );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
FPU registers[reg] = src;
|
FPU registers[reg] = src;
|
||||||
|
@ -2166,27 +2302,15 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra)
|
||||||
FPU registers[reg] *= src;
|
FPU registers[reg] *= src;
|
||||||
}
|
}
|
||||||
else if (fl_dest.nan || fl_source.nan ||
|
else if (fl_dest.nan || fl_source.nan ||
|
||||||
fl_dest.zero && fl_source.infinity ||
|
(fl_dest.zero && fl_source.infinity) ||
|
||||||
fl_dest.infinity && fl_source.zero ) {
|
(fl_dest.infinity && fl_source.zero) ) {
|
||||||
make_nan( FPU registers[reg] );
|
make_nan( FPU registers[reg], fl_dest.negative );
|
||||||
}
|
}
|
||||||
else if (fl_dest.zero || fl_source.zero ) {
|
else if (fl_dest.zero || fl_source.zero ) {
|
||||||
if (fl_dest.negative && !fl_source.negative ||
|
make_zero(FPU registers[reg], 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]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if( fl_dest.negative && !fl_source.negative ||
|
make_inf(FPU registers[reg], 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]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
fpu_debug(("FMUL %.04f\n",(double)src));
|
fpu_debug(("FMUL %.04f\n",(double)src));
|
||||||
|
@ -2223,8 +2347,8 @@ void FFPU fpuop_arithmetic(uae_u32 opcode, uae_u32 extra)
|
||||||
// Overflow, underflow
|
// Overflow, underflow
|
||||||
|
|
||||||
#if FPU_HAVE_IEEE_DOUBLE
|
#if FPU_HAVE_IEEE_DOUBLE
|
||||||
if( isinf(FPU registers[reg]) ) {
|
if( isinf(src) ) {
|
||||||
make_nan( FPU registers[reg] );
|
make_nan( FPU registers[reg], isneg(src) );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// When the absolute value of the source operand is >= 2^14,
|
// 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 ");
|
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 -------------------------- */
|
/* -------------------------- Initialization -------------------------- */
|
||||||
|
|
||||||
void FFPU fpu_init (bool integral_68040)
|
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
|
* 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.
|
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* MC68881/68040 fpu emulation
|
||||||
* 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
|
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||||
* along with this program; if not, write to the Free Software
|
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* 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
|
#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_isneg(fpu_register const & r);
|
||||||
PRIVATE inline bool FFPU do_iszero(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_nan(fpu_register & r, bool negative);
|
||||||
PRIVATE inline void FFPU make_zero_positive(fpu_register & r);
|
PRIVATE inline void FFPU make_zero(fpu_register & r, bool negative);
|
||||||
PRIVATE inline void FFPU make_zero_negative(fpu_register & r);
|
PRIVATE inline void FFPU make_inf(fpu_register & r, bool negative);
|
||||||
PRIVATE inline void FFPU make_inf_positive(fpu_register & r);
|
|
||||||
PRIVATE inline void FFPU make_inf_negative(fpu_register & r);
|
|
||||||
|
|
||||||
PRIVATE inline void FFPU fast_scale(fpu_register & r, int add);
|
PRIVATE inline void FFPU fast_scale(fpu_register & r, int add);
|
||||||
PRIVATE inline fpu_register FFPU fast_fgetexp(fpu_register const & r);
|
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,
|
* MC68881/68040 fpu emulation
|
||||||
* rewritten for x86 by Lauri Pesonen 1999-2000,
|
|
||||||
* accomodated to GCC's Extended Asm syntax by Gwenole Beauchesne 2000.
|
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||||
* it under the terms of the GNU General Public License as published by
|
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
* New framework, copyright 2000-2001 Gwenole Beauchesne
|
||||||
* (at your option) any later version.
|
* Adapted for JIT compilation (c) Bernd Meyer, 2000-2001
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* ARAnyM is free software; you can redistribute it and/or modify
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* it under the terms of the GNU General Public License as published by
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
* GNU General Public License for more details.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* ARAnyM is distributed in the hope that it will be useful,
|
||||||
* along with this program; if not, write to the Free Software
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* 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
|
* Interface
|
||||||
|
@ -134,10 +140,8 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <math.h>
|
# include <cmath>
|
||||||
#include <stdio.h>
|
# include <cstdio>
|
||||||
#include <string.h>
|
|
||||||
#include <signal.h>
|
|
||||||
|
|
||||||
#include "sysdeps.h"
|
#include "sysdeps.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
|
@ -238,8 +242,6 @@ PUBLIC void FFPU fpu_dump_flags(void)
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
|
||||||
#if FPU_DEBUG
|
#if FPU_DEBUG
|
||||||
#undef __inline__
|
|
||||||
#define __inline__
|
|
||||||
|
|
||||||
PRIVATE void FFPU dump_first_bytes_buf(char *b, uae_u8* buf, uae_s32 actual)
|
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 ---------------------------- */
|
/* ---------------------------- 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 ) {
|
if( (x86_status_word & (SW_Z_I_NAN_MASK)) == SW_NAN ) {
|
||||||
x86_status_word |= SW_FAKE_BSUN;
|
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) {
|
if(x86_status_word & SW_EXCEPTION_MASK) {
|
||||||
// _asm FNCLEX
|
// _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.
|
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.
|
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.
|
// Make it non-signaling.
|
||||||
uae_u8 * p = (uae_u8 *) &f;
|
uae_u8 * p = (uae_u8 *) &f;
|
||||||
memset( p, 0xFF, sizeof(fpu_register) - 1 );
|
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 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.
|
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;
|
uae_u8 * p = (uae_u8 *) &f;
|
||||||
if( ((p[9] & 0x7F) == 0x7F) && p[8] == 0xFF ) {
|
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);
|
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;
|
uae_u8 * p = (uae_u8 *) &f;
|
||||||
if( ((p[9] & 0x7F) == 0x7F) && p[8] == 0xFF ) {
|
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);
|
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;
|
uae_u8 * p = (uae_u8 *) &f;
|
||||||
return *((uae_u32 *)p) == 0 &&
|
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;
|
( *((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;
|
uae_u8 * p = (uae_u8 *) &f;
|
||||||
memset( p, 0, sizeof(fpu_register)-2 );
|
memset( p, 0, sizeof(fpu_register)-2 );
|
||||||
*((uae_u16 *)&p[8]) = 0x7FFF;
|
*((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;
|
uae_u8 * p = (uae_u8 *) &f;
|
||||||
memset( p, 0, sizeof(fpu_register)-2 );
|
memset( p, 0, sizeof(fpu_register)-2 );
|
||||||
*((uae_u16 *)&p[8]) = 0xFFFF;
|
*((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;
|
uae_u32 * const p = (uae_u32 *) &f;
|
||||||
memset( p, 0, sizeof(fpu_register) );
|
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;
|
uae_u32 * const p = (uae_u32 *) &f;
|
||||||
memset( p, 0, sizeof(fpu_register) );
|
memset( p, 0, sizeof(fpu_register) );
|
||||||
*((uae_u32 *)&p[4]) = 0x80000000;
|
*((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;
|
uae_u8 * p = (uae_u8 *) &f;
|
||||||
return( (p[9] & 0x80) != 0 );
|
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");
|
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 )
|
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");
|
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 )
|
PRIVATE void FFPU do_ftst ( fpu_register const & src )
|
||||||
{
|
{
|
||||||
FPU_CONSISTENCY_CHECK_START();
|
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");
|
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 )
|
PRIVATE void FFPU do_fneg ( fpu_register & dest, fpu_register const & src )
|
||||||
{
|
{
|
||||||
FPU_CONSISTENCY_CHECK_START();
|
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");
|
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 )
|
PRIVATE void FFPU do_fcos ( fpu_register & dest, fpu_register const & src )
|
||||||
{
|
{
|
||||||
FPU_CONSISTENCY_CHECK_START();
|
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");
|
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
|
// The sign of the quotient is the exclusive-OR of the sign bits
|
||||||
// of the source and destination operands.
|
// of the source and destination operands.
|
||||||
// Quotient Byte is loaded with the sign and least significant
|
// 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");
|
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 )
|
PRIVATE void FFPU do_fmul ( fpu_register & dest, fpu_register const & src )
|
||||||
{
|
{
|
||||||
FPU_CONSISTENCY_CHECK_START();
|
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");
|
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 )
|
PRIVATE void FFPU do_fsgldiv ( fpu_register & dest, fpu_register const & src )
|
||||||
{
|
{
|
||||||
FPU_CONSISTENCY_CHECK_START();
|
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");
|
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 )
|
PRIVATE void FFPU do_fsincos ( fpu_register & dest_sin, fpu_register & dest_cos, fpu_register const & src )
|
||||||
{
|
{
|
||||||
FPU_CONSISTENCY_CHECK_START();
|
FPU_CONSISTENCY_CHECK_START();
|
||||||
|
@ -2284,11 +2616,9 @@ PRIVATE int FFPU get_fp_value (uae_u32 opcode, uae_u32 extra, fpu_register & src
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
ad = m68k_areg (regs, reg);
|
ad = m68k_areg (regs, reg);
|
||||||
m68k_areg (regs, reg) += reg == 7 ? sz2[size] : sz1[size];
|
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
m68k_areg (regs, reg) -= reg == 7 ? sz2[size] : sz1[size];
|
ad = m68k_areg (regs, reg) - (reg == 7 ? sz2[size] : sz1[size]);
|
||||||
ad = m68k_areg (regs, reg);
|
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
ad = m68k_areg (regs, reg) + (uae_s32) (uae_s16) next_iword();
|
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;
|
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));
|
// D(bug("get_fp_value result = %.04f\r\n",(float)src));
|
||||||
|
|
||||||
return 1;
|
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 I ((x86_status_word & (SW_Z_I_NAN_MASK)) == (SW_I))
|
||||||
#define NotANumber ((x86_status_word & (SW_Z_I_NAN_MASK)) == SW_NAN)
|
#define NotANumber ((x86_status_word & (SW_Z_I_NAN_MASK)) == SW_NAN)
|
||||||
|
|
||||||
switch (condition) {
|
switch (condition & 0x1f) {
|
||||||
// Common Tests, no BSUN
|
// Common Tests, no BSUN
|
||||||
case 0x01:
|
case 0x01:
|
||||||
CONDRET("Equal",Z);
|
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;
|
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
|
#if I3_ON_FTRAPCC
|
||||||
#error "FIXME: _asm int 3"
|
#error "FIXME: _asm int 3"
|
||||||
|
@ -2769,7 +3108,7 @@ PUBLIC void REGPARAM2 FFPU fpuop_trapcc(uae_u32 opcode, uaecptr oldpc)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// This must be broken.
|
// This must be broken.
|
||||||
cc = fpp_cond(opcode, opcode & 0x3f);
|
cc = fpp_cond(opcode, extra & 0x3f);
|
||||||
|
|
||||||
if (cc < 0) {
|
if (cc < 0) {
|
||||||
m68k_setpc (oldpc);
|
m68k_setpc (oldpc);
|
||||||
|
@ -2856,7 +3195,7 @@ PRIVATE void FFPU do_null_frestore ()
|
||||||
{
|
{
|
||||||
// A null-restore operation sets FP7-FP0 positive, nonsignaling NANs.
|
// A null-restore operation sets FP7-FP0 positive, nonsignaling NANs.
|
||||||
for( int i=0; i<8; i++ ) {
|
for( int i=0; i<8; i++ ) {
|
||||||
MAKE_NAN( FPU registers[i] );
|
MAKE_NAN( FPU registers[i], false );
|
||||||
}
|
}
|
||||||
|
|
||||||
FPU instruction_address = 0;
|
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 ---------------------------- */
|
/* ---------------------------- ALU ---------------------------- */
|
||||||
|
|
||||||
PRIVATE void REGPARAM2 FFPU fpuop_do_fmove( uae_u32 opcode, uae_u32 extra )
|
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)));
|
D(bug("FGETEXP %s\r\n",etos(src)));
|
||||||
|
|
||||||
if( IS_INFINITY(src) ) {
|
if( IS_INFINITY(src) ) {
|
||||||
MAKE_NAN( FPU registers[reg] );
|
MAKE_NAN( FPU registers[reg], IS_NEGATIVE(src) );
|
||||||
do_ftst( FPU registers[reg] );
|
do_ftst( FPU registers[reg] );
|
||||||
x86_status_word |= SW_IE;
|
x86_status_word |= SW_IE;
|
||||||
} else {
|
} 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)));
|
D(bug("FGETMAN %s\r\n",etos(src)));
|
||||||
if( IS_INFINITY(src) ) {
|
if( IS_INFINITY(src) ) {
|
||||||
MAKE_NAN( FPU registers[reg] );
|
MAKE_NAN( FPU registers[reg], IS_NEGATIVE(src) );
|
||||||
do_ftst( FPU registers[reg] );
|
do_ftst( FPU registers[reg] );
|
||||||
x86_status_word |= SW_IE;
|
x86_status_word |= SW_IE;
|
||||||
} else {
|
} 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()));
|
D(bug("FSCALE %s, opcode=%X, extra=%X, ta %X\r\n",etos(src),opcode,extra,m68k_getpc()));
|
||||||
if( IS_INFINITY(FPU registers[reg]) ) {
|
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] );
|
do_ftst( FPU registers[reg] );
|
||||||
x86_status_word |= SW_IE;
|
x86_status_word |= SW_IE;
|
||||||
} else {
|
} else {
|
||||||
|
@ -5744,6 +6326,61 @@ PRIVATE void FFPU build_fpp_opp_lookup_table ()
|
||||||
}
|
}
|
||||||
break;
|
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) {
|
switch (extra & 0x7f) {
|
||||||
case 0x00:
|
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 ---------------------------- */
|
/* ---------------------------- MAIN INIT ---------------------------- */
|
||||||
|
|
||||||
#ifdef HAVE_SIGACTION
|
#ifdef HAVE_SIGACTION
|
||||||
|
@ -6079,11 +6736,15 @@ PUBLIC void FFPU fpu_init( bool integral_68040 )
|
||||||
FPU fpsr.quotient = 0;
|
FPU fpsr.quotient = 0;
|
||||||
|
|
||||||
for( int i=0; i<8; i++ ) {
|
for( int i=0; i<8; i++ ) {
|
||||||
MAKE_NAN( FPU registers[i] );
|
MAKE_NAN( FPU registers[i], false );
|
||||||
}
|
}
|
||||||
|
|
||||||
build_fpp_opp_lookup_table();
|
build_fpp_opp_lookup_table();
|
||||||
|
|
||||||
|
/* _asm {
|
||||||
|
FNINIT
|
||||||
|
FLDCW x86_control_word
|
||||||
|
} */
|
||||||
__asm__ __volatile__("fninit\nfldcw %0" : : "m" (x86_control_word));
|
__asm__ __volatile__("fninit\nfldcw %0" : : "m" (x86_control_word));
|
||||||
|
|
||||||
do_fldpi( const_pi );
|
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 );
|
set_constant( const_1e4096, "1.0e4096", 1.0e256, 10000 );
|
||||||
|
|
||||||
// Just in case.
|
// Just in case.
|
||||||
|
/* _asm {
|
||||||
|
FNINIT
|
||||||
|
FLDCW x86_control_word
|
||||||
|
} */
|
||||||
__asm__ __volatile__("fninit\nfldcw %0" : : "m" (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
|
* 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.
|
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* MC68881/68040 fpu emulation
|
||||||
* 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
|
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||||
* along with this program; if not, write to the Free Software
|
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* 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
|
#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);
|
PRIVATE void FFPU FPU_CONSISTENCY_CHECK_STOP(const char *name);
|
||||||
|
|
||||||
// Get special floating-point value class
|
// Get special floating-point value class
|
||||||
PRIVATE __inline__ uae_u32 FFPU IS_INFINITY (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_NAN (fpu_register const & f);
|
||||||
PRIVATE __inline__ uae_u32 FFPU IS_ZERO (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_NEGATIVE (fpu_register const & f);
|
||||||
|
|
||||||
// Make a special floating-point value
|
// Make a special floating-point value
|
||||||
PRIVATE __inline__ void FFPU MAKE_NAN (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_POSITIVE (fpu_register & f);
|
||||||
PRIVATE __inline__ void FFPU MAKE_INF_NEGATIVE (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_POSITIVE (fpu_register & f);
|
||||||
PRIVATE __inline__ void FFPU MAKE_ZERO_NEGATIVE (fpu_register & f);
|
PRIVATE inline void FFPU MAKE_ZERO_NEGATIVE (fpu_register & f);
|
||||||
|
|
||||||
// Conversion from extended floating-point values
|
// Conversion from extended floating-point values
|
||||||
PRIVATE uae_s32 FFPU extended_to_signed_32 ( fpu_register const & f ) REGPARAM;
|
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_fcmp( uae_u32 opcode, uae_u32 extra );
|
||||||
PRIVATE void REGPARAM2 FFPU fpuop_do_ftst( 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
|
// Get & Put floating-point values
|
||||||
PRIVATE int FFPU get_fp_value (uae_u32 opcode, uae_u32 extra, fpu_register & src) REGPARAM;
|
PRIVATE int FFPU get_fp_value (uae_u32 opcode, uae_u32 extra, fpu_register & src) REGPARAM;
|
||||||
PRIVATE int FFPU put_fp_value (fpu_register const & value, uae_u32 opcode, uae_u32 extra) REGPARAM;
|
PRIVATE int FFPU 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;
|
PRIVATE int FFPU fpp_cond(uae_u32 opcode, int condition) REGPARAM;
|
||||||
|
|
||||||
// Misc functions
|
// Misc functions
|
||||||
PRIVATE void __inline__ FFPU set_host_fpu_control_word ();
|
PRIVATE void inline FFPU set_host_fpu_control_word ();
|
||||||
PRIVATE void __inline__ FFPU SET_BSUN_ON_NAN ();
|
PRIVATE void inline FFPU SET_BSUN_ON_NAN ();
|
||||||
PRIVATE void __inline__ FFPU build_ex_status ();
|
PRIVATE void inline FFPU build_ex_status ();
|
||||||
PRIVATE void FFPU do_null_frestore ();
|
PRIVATE void FFPU do_null_frestore ();
|
||||||
PRIVATE void FFPU build_fpp_opp_lookup_table ();
|
PRIVATE void FFPU build_fpp_opp_lookup_table ();
|
||||||
PRIVATE void FFPU set_constant ( fpu_register & f, char *name, double value, uae_s32 mult );
|
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) \
|
#define DEFINE_X86_MACRO(name, value) \
|
||||||
asm(".local " #name "\n\t" #name " = " #value)
|
asm(".local " #name "\n\t" #name " = " #value)
|
||||||
|
|
||||||
|
|
|
@ -1,28 +1,38 @@
|
||||||
/*
|
/*
|
||||||
* fpu/impl.h - extra functions and inline implementations
|
* 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
|
* 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.
|
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* MC68881/68040 fpu emulation
|
||||||
* 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
|
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||||
* along with this program; if not, write to the Free Software
|
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* 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
|
#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 */
|
/* Return the floating-point control register in m68k format */
|
||||||
static inline uae_u32 FFPU get_fpcr(void)
|
static inline uae_u32 FFPU get_fpcr(void)
|
||||||
{
|
{
|
||||||
uae_u32 rounding_precision = get_rounding_precision();
|
// according to the manual, the msb bits are always zero.
|
||||||
uae_u32 rounding_mode = get_rounding_mode();
|
// According to Toni Wilen, on '040 the least
|
||||||
return (rounding_precision | rounding_mode);
|
// significant 4 bits are not masked out
|
||||||
|
return FPU fpcr & (CPUType == 4 ? 0xffff : 0xfff0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set the floating-point control register from an m68k format */
|
/* Set the floating-point control register from an m68k format */
|
||||||
static inline void FFPU set_fpcr(uae_u32 new_fpcr)
|
static inline void FFPU set_fpcr(uae_u32 new_fpcr)
|
||||||
{
|
{
|
||||||
|
FPU fpcr = new_fpcr;
|
||||||
set_rounding_precision ( new_fpcr & FPCR_ROUNDING_PRECISION);
|
set_rounding_precision ( new_fpcr & FPCR_ROUNDING_PRECISION);
|
||||||
set_rounding_mode ( new_fpcr & FPCR_ROUNDING_MODE );
|
set_rounding_mode ( new_fpcr & FPCR_ROUNDING_MODE );
|
||||||
set_host_control_word();
|
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 */
|
/* Retrieve a floating-point register value and convert it to double precision */
|
||||||
static inline double FFPU fpu_get_register(int r)
|
static inline double FFPU fpu_get_register(int r)
|
||||||
{
|
{
|
||||||
double f;
|
/* only used for debug output; no need for any fancy asm here */
|
||||||
__asm__ __volatile__("fldt %1\n\tfstpl %0" : "=m" (f) : "m" (FPU registers[r]));
|
return FPU registers[r];
|
||||||
return f;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,28 +1,33 @@
|
||||||
/*
|
/*
|
||||||
* fpu/mathlib.cpp - Floating-point math support library
|
* 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
|
* 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-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 program is distributed in the hope that it will be useful,
|
* MC68881/68040 fpu emulation
|
||||||
* 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
|
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||||
* along with this program; if not, write to the Free Software
|
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* 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 */
|
/* 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(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)
|
PRIVATE fpu_extended fp_do_pow(fpu_extended x, fpu_extended y)
|
||||||
{
|
{
|
||||||
fpu_extended value, exponent;
|
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));
|
__asm__ __volatile__("fscale" : "=t" (value) : "0" (value), "u" (exponent));
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HAVE_LOG1PL
|
||||||
PRIVATE fpu_extended fp_do_log1p(fpu_extended x)
|
PRIVATE fpu_extended fp_do_log1p(fpu_extended x)
|
||||||
{
|
{
|
||||||
// TODO: handle NaN and +inf/-inf
|
// 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));
|
__asm__ __volatile__("fldln2; fxch; fyl2x" : "=t" (value) : "0" (x + 1.0));
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#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
|
* 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.
|
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* MC68881/68040 fpu emulation
|
||||||
* 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
|
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||||
* along with this program; if not, write to the Free Software
|
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* 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
|
#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
|
* 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.
|
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* MC68881/68040 fpu emulation
|
||||||
* 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
|
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||||
* along with this program; if not, write to the Free Software
|
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* 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
|
#ifndef FPU_ROUNDING_H
|
||||||
|
@ -106,8 +111,8 @@ PRIVATE inline void set_host_control_word(void)
|
||||||
*/
|
*/
|
||||||
x86_control_word
|
x86_control_word
|
||||||
= (x86_control_word & ~(X86_ROUNDING_MODE|X86_ROUNDING_PRECISION))
|
= (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_rm_mac2host[(FPU fpcr & FPCR_ROUNDING_MODE) >> 4]
|
||||||
| x86_control_word_rp_mac2host[(FPU fpcr.rounding_precision & FPCR_ROUNDING_PRECISION) >> 6]
|
| x86_control_word_rp_mac2host[(FPU fpcr & FPCR_ROUNDING_PRECISION) >> 6]
|
||||||
;
|
;
|
||||||
__asm__ __volatile__("fldcw %0" : : "m" (x86_control_word));
|
__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 */
|
/* Return the current rounding mode in m68k format */
|
||||||
static inline uae_u32 FFPU get_rounding_mode(void)
|
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 */
|
/* Convert and set to native rounding mode */
|
||||||
static inline void FFPU set_rounding_mode(uae_u32 new_rounding_mode)
|
static inline void FFPU set_rounding_mode(uae_u32 /* new_rounding_mode */ )
|
||||||
{ FPU fpcr.rounding_mode = new_rounding_mode; }
|
{ }
|
||||||
|
|
||||||
#endif
|
#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 */
|
/* Return the current rounding precision in m68k format */
|
||||||
static inline uae_u32 FFPU get_rounding_precision(void)
|
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 */
|
/* Convert and set to native rounding precision */
|
||||||
static inline void FFPU set_rounding_precision(uae_u32 new_rounding_precision)
|
static inline void FFPU set_rounding_precision(uae_u32 /* new_rounding_precision */)
|
||||||
{ FPU fpcr.rounding_precision = new_rounding_precision; }
|
{ }
|
||||||
|
|
||||||
#endif
|
#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
|
* 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.
|
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful,
|
* MC68881/68040 fpu emulation
|
||||||
* 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
|
* Original UAE FPU, copyright 1996 Herman ten Brugge
|
||||||
* along with this program; if not, write to the Free Software
|
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* 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
|
#ifndef FPU_TYPES_H
|
||||||
|
@ -106,9 +111,11 @@ typedef uae_f32 fpu_single;
|
||||||
|
|
||||||
#elif defined(FPU_IEEE)
|
#elif defined(FPU_IEEE)
|
||||||
|
|
||||||
// #if HOST_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
|
#if 0
|
||||||
// #error "No IEEE float format, you lose."
|
#if HOST_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
|
||||||
// #endif
|
#error "No IEEE float format, you lose."
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
/* 4-byte floats */
|
/* 4-byte floats */
|
||||||
#if SIZEOF_FLOAT == 4
|
#if SIZEOF_FLOAT == 4
|
||||||
|
@ -133,7 +140,7 @@ typedef long double uae_f64;
|
||||||
typedef long double uae_f96;
|
typedef long double uae_f96;
|
||||||
typedef uae_f96 fpu_register;
|
typedef uae_f96 fpu_register;
|
||||||
#define USE_LONG_DOUBLE 1
|
#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. */
|
/* Long doubles on x86-64 are really held in old x87 FPU stack. */
|
||||||
typedef long double uae_f128;
|
typedef long double uae_f128;
|
||||||
typedef uae_f128 fpu_register;
|
typedef uae_f128 fpu_register;
|
||||||
|
@ -154,6 +161,23 @@ typedef fpu_register fpu_extended;
|
||||||
typedef uae_f64 fpu_double;
|
typedef uae_f64 fpu_double;
|
||||||
typedef uae_f32 fpu_single;
|
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
|
#endif
|
||||||
|
|
||||||
|
union fpu_register_parts {
|
||||||
|
fpu_register val;
|
||||||
|
uae_u32 parts[sizeof(fpu_register) / 4];
|
||||||
|
};
|
||||||
|
|
||||||
#endif /* FPU_TYPES_H */
|
#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
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
* (at your option) any later version.
|
* (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
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* 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
|
* 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
|
#ifndef M68K_FLAGS_H
|
||||||
#define M68K_FLAGS_H
|
#define M68K_FLAGS_H
|
||||||
|
|
606
BasiliskII/src/uae_cpu/memory-uae.h
Normal file
606
BasiliskII/src/uae_cpu/memory-uae.h
Normal file
|
@ -0,0 +1,606 @@
|
||||||
|
/*
|
||||||
|
* memory.h - memory management
|
||||||
|
*
|
||||||
|
* Copyright (c) 2001-2006 Milan Jurik of ARAnyM dev team (see AUTHORS)
|
||||||
|
*
|
||||||
|
* Inspired by Christian Bauer's Basilisk II
|
||||||
|
*
|
||||||
|
* This file is part of the ARAnyM project which builds a new and powerful
|
||||||
|
* TOS/FreeMiNT compatible virtual machine running on almost any hardware.
|
||||||
|
*
|
||||||
|
* ARAnyM is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* ARAnyM is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with ARAnyM; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* UAE - The Un*x Amiga Emulator
|
||||||
|
*
|
||||||
|
* memory management
|
||||||
|
*
|
||||||
|
* Copyright 1995 Bernd Schmidt
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef UAE_MEMORY_H
|
||||||
|
#define UAE_MEMORY_H
|
||||||
|
|
||||||
|
#include "sysdeps.h"
|
||||||
|
#include "string.h"
|
||||||
|
#include "hardware.h"
|
||||||
|
#include "parameters.h"
|
||||||
|
#include "registers.h"
|
||||||
|
#include "cpummu.h"
|
||||||
|
#include "readcpu.h"
|
||||||
|
|
||||||
|
# include <csetjmp>
|
||||||
|
|
||||||
|
// newcpu.h
|
||||||
|
extern void Exception (int, uaecptr);
|
||||||
|
#ifdef EXCEPTIONS_VIA_LONGJMP
|
||||||
|
extern JMP_BUF excep_env;
|
||||||
|
#define SAVE_EXCEPTION \
|
||||||
|
JMP_BUF excep_env_old; \
|
||||||
|
memcpy(excep_env_old, excep_env, sizeof(JMP_BUF))
|
||||||
|
#define RESTORE_EXCEPTION \
|
||||||
|
memcpy(excep_env, excep_env_old, sizeof(JMP_BUF))
|
||||||
|
#define TRY(var) int var = SETJMP(excep_env); if (!var)
|
||||||
|
#define CATCH(var) else
|
||||||
|
#define THROW(n) LONGJMP(excep_env, n)
|
||||||
|
#define THROW_AGAIN(var) LONGJMP(excep_env, var)
|
||||||
|
#define VOLATILE volatile
|
||||||
|
#else
|
||||||
|
struct m68k_exception {
|
||||||
|
int prb;
|
||||||
|
m68k_exception (int exc) : prb (exc) {}
|
||||||
|
operator int() { return prb; }
|
||||||
|
};
|
||||||
|
#define SAVE_EXCEPTION
|
||||||
|
#define RESTORE_EXCEPTION
|
||||||
|
#define TRY(var) try
|
||||||
|
#define CATCH(var) catch(m68k_exception var)
|
||||||
|
#define THROW(n) throw m68k_exception(n)
|
||||||
|
#define THROW_AGAIN(var) throw
|
||||||
|
#define VOLATILE
|
||||||
|
#endif /* EXCEPTIONS_VIA_LONGJMP */
|
||||||
|
extern int in_exception_2;
|
||||||
|
|
||||||
|
#define STRAM_END 0x0e00000UL // should be replaced by global ROMBase as soon as ROMBase will be a constant
|
||||||
|
#define ROM_END 0x0e80000UL // should be replaced by ROMBase + RealROMSize if we are going to work with larger TOS ROMs than 512 kilobytes
|
||||||
|
#define FastRAM_BEGIN 0x1000000UL // should be replaced by global FastRAMBase as soon as FastRAMBase will be a constant
|
||||||
|
#ifdef FixedSizeFastRAM
|
||||||
|
#define FastRAM_SIZE (FixedSizeFastRAM * 1024 * 1024)
|
||||||
|
#else
|
||||||
|
#define FastRAM_SIZE FastRAMSize
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef FIXED_VIDEORAM
|
||||||
|
#define ARANYMVRAMSTART 0xf0000000UL
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define ARANYMVRAMSIZE 0x00100000 // should be a variable to protect VGA card offscreen memory
|
||||||
|
|
||||||
|
#ifdef FIXED_VIDEORAM
|
||||||
|
extern uintptr VMEMBaseDiff;
|
||||||
|
#else
|
||||||
|
extern uae_u32 VideoRAMBase;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ARAM_PAGE_CHECK
|
||||||
|
extern uaecptr pc_page, read_page, write_page;
|
||||||
|
extern uintptr pc_offset, read_offset, write_offset;
|
||||||
|
# ifdef PROTECT2K
|
||||||
|
# define ARAM_PAGE_MASK 0x7ff
|
||||||
|
# else
|
||||||
|
# ifdef FULLMMU
|
||||||
|
# define ARAM_PAGE_MASK 0xfff
|
||||||
|
# else
|
||||||
|
# define ARAM_PAGE_MASK 0xfffff
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern uintptr MEMBaseDiff;
|
||||||
|
extern uintptr ROMBaseDiff;
|
||||||
|
extern uintptr FastRAMBaseDiff;
|
||||||
|
# define InitMEMBaseDiff(va, ra) (MEMBaseDiff = (uintptr)(va) - (uintptr)(ra))
|
||||||
|
# define InitROMBaseDiff(va, ra) (ROMBaseDiff = (uintptr)(va) - (uintptr)(ra))
|
||||||
|
# define InitFastRAMBaseDiff(va, ra) (FastRAMBaseDiff = (uintptr)(va) - (uintptr)(ra))
|
||||||
|
|
||||||
|
#ifdef FIXED_VIDEORAM
|
||||||
|
#define InitVMEMBaseDiff(va, ra) (VMEMBaseDiff = (uintptr)(va) - (uintptr)(ra))
|
||||||
|
#else
|
||||||
|
#define InitVMEMBaseDiff(va, ra) (ra = (uintptr)(va) + MEMBaseDiff)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern "C" void breakpt(void);
|
||||||
|
|
||||||
|
|
||||||
|
static inline uae_u64 do_get_mem_quad(uae_u64 *a) {return SDL_SwapBE64(*a);}
|
||||||
|
static inline void do_put_mem_quad(uae_u64 *a, uae_u64 v) {*a = SDL_SwapBE64(v);}
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef NOCHECKBOUNDARY
|
||||||
|
static ALWAYS_INLINE bool test_ram_boundary(uaecptr addr, int size, bool super, bool write)
|
||||||
|
{
|
||||||
|
if (addr <= (FastRAM_BEGIN + FastRAM_SIZE - size)) {
|
||||||
|
#ifdef PROTECT2K
|
||||||
|
// protect first 2kB of RAM - access in supervisor mode only
|
||||||
|
if (!super && addr < 0x00000800UL)
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
// check for write access to protected areas:
|
||||||
|
// - first two longwords of ST-RAM are non-writable (ROM shadow)
|
||||||
|
// - non-writable area between end of ST-RAM and begin of FastRAM
|
||||||
|
if (!write || addr >= FastRAM_BEGIN || (addr >= 8 && addr <= (STRAM_END - size)))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#ifdef FIXED_VIDEORAM
|
||||||
|
return addr >= ARANYMVRAMSTART && addr <= (ARANYMVRAMSTART + ARANYMVRAMSIZE - size);
|
||||||
|
#else
|
||||||
|
return addr >= VideoRAMBase && addr <= (VideoRAMBase + ARANYMVRAMSIZE - size);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* "size" is the size of the memory access (byte = 1, word = 2, long = 4)
|
||||||
|
*/
|
||||||
|
static ALWAYS_INLINE void check_ram_boundary(uaecptr addr, int size, bool write)
|
||||||
|
{
|
||||||
|
if (test_ram_boundary(addr, size, regs.s, write))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// D(bug("BUS ERROR %s at $%x\n", (write ? "writing" : "reading"), addr));
|
||||||
|
regs.mmu_fault_addr = addr;
|
||||||
|
regs.mmu_ssw = ((size & 3) << 5) | (write ? 0 : (1 << 8));
|
||||||
|
breakpt();
|
||||||
|
THROW(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
static inline bool test_ram_boundary(uaecptr, int, bool, bool) { return 1; }
|
||||||
|
static inline void check_ram_boundary(uaecptr, int, bool) { }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef FIXED_VIDEORAM
|
||||||
|
# define do_get_real_address(a) ((uae_u8 *)(((uaecptr)(a) < ARANYMVRAMSTART) ? ((uaecptr)(a) + MEMBaseDiff) : ((uaecptr)(a) + VMEMBaseDiff)))
|
||||||
|
#else
|
||||||
|
# define do_get_real_address(a) ((uae_u8 *)((uintptr)(a) + MEMBaseDiff))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static inline uae_u8 *phys_get_real_address(uaecptr addr)
|
||||||
|
{
|
||||||
|
return do_get_real_address(addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef NOCHECKBOUNDARY
|
||||||
|
static inline bool phys_valid_address(uaecptr addr, bool write, int sz)
|
||||||
|
{
|
||||||
|
return test_ram_boundary(addr, sz, regs.s, write);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static inline bool phys_valid_address(uaecptr, bool, int) { return true; }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static inline uae_u64 phys_get_quad(uaecptr addr)
|
||||||
|
{
|
||||||
|
#ifdef ARAM_PAGE_CHECK
|
||||||
|
if (((addr ^ read_page) <= ARAM_PAGE_MASK))
|
||||||
|
return do_get_mem_quad((uae_u64*)(addr + read_offset));
|
||||||
|
#endif
|
||||||
|
#ifndef HW_SIGSEGV
|
||||||
|
addr = addr < 0xff000000 ? addr : addr & 0x00ffffff;
|
||||||
|
if ((addr & 0xfff00000) == 0x00f00000) return HWget_l(addr); /* TODO: must be HWget_q */
|
||||||
|
#endif
|
||||||
|
check_ram_boundary(addr, 8, false);
|
||||||
|
uae_u64 * const m = (uae_u64 *)phys_get_real_address(addr);
|
||||||
|
#ifdef ARAM_PAGE_CHECK
|
||||||
|
read_page = addr;
|
||||||
|
read_offset = (uintptr)m - (uintptr)addr;
|
||||||
|
#endif
|
||||||
|
return do_get_mem_quad(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uae_u32 phys_get_long(uaecptr addr)
|
||||||
|
{
|
||||||
|
#ifdef ARAM_PAGE_CHECK
|
||||||
|
if (((addr ^ read_page) <= ARAM_PAGE_MASK))
|
||||||
|
return do_get_mem_long((uae_u32*)(addr + read_offset));
|
||||||
|
#endif
|
||||||
|
#ifndef HW_SIGSEGV
|
||||||
|
addr = addr < 0xff000000 ? addr : addr & 0x00ffffff;
|
||||||
|
if ((addr & 0xfff00000) == 0x00f00000) return HWget_l(addr);
|
||||||
|
#endif
|
||||||
|
check_ram_boundary(addr, 4, false);
|
||||||
|
uae_u32 * const m = (uae_u32 *)phys_get_real_address(addr);
|
||||||
|
#ifdef ARAM_PAGE_CHECK
|
||||||
|
read_page = addr;
|
||||||
|
read_offset = (uintptr)m - (uintptr)addr;
|
||||||
|
#endif
|
||||||
|
return do_get_mem_long(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uae_u32 phys_get_word(uaecptr addr)
|
||||||
|
{
|
||||||
|
#ifdef ARAM_PAGE_CHECK
|
||||||
|
if (((addr ^ read_page) <= ARAM_PAGE_MASK))
|
||||||
|
return do_get_mem_word((uae_u16*)(addr + read_offset));
|
||||||
|
#endif
|
||||||
|
#ifndef HW_SIGSEGV
|
||||||
|
addr = addr < 0xff000000 ? addr : addr & 0x00ffffff;
|
||||||
|
if ((addr & 0xfff00000) == 0x00f00000) return HWget_w(addr);
|
||||||
|
#endif
|
||||||
|
check_ram_boundary(addr, 2, false);
|
||||||
|
uae_u16 * const m = (uae_u16 *)phys_get_real_address(addr);
|
||||||
|
#ifdef ARAM_PAGE_CHECK
|
||||||
|
read_page = addr;
|
||||||
|
read_offset = (uintptr)m - (uintptr)addr;
|
||||||
|
#endif
|
||||||
|
return do_get_mem_word(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uae_u32 phys_get_byte(uaecptr addr)
|
||||||
|
{
|
||||||
|
#ifdef ARAM_PAGE_CHECK
|
||||||
|
if (((addr ^ read_page) <= ARAM_PAGE_MASK))
|
||||||
|
return do_get_mem_byte((uae_u8*)(addr + read_offset));
|
||||||
|
#endif
|
||||||
|
#ifndef HW_SIGSEGV
|
||||||
|
addr = addr < 0xff000000 ? addr : addr & 0x00ffffff;
|
||||||
|
if ((addr & 0xfff00000) == 0x00f00000) return HWget_b(addr);
|
||||||
|
#endif
|
||||||
|
check_ram_boundary(addr, 1, false);
|
||||||
|
uae_u8 * const m = (uae_u8 *)phys_get_real_address(addr);
|
||||||
|
#ifdef ARAM_PAGE_CHECK
|
||||||
|
read_page = addr;
|
||||||
|
read_offset = (uintptr)m - (uintptr)addr;
|
||||||
|
#endif
|
||||||
|
return do_get_mem_byte(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void phys_put_quad(uaecptr addr, uae_u64 l)
|
||||||
|
{
|
||||||
|
#ifdef ARAM_PAGE_CHECK
|
||||||
|
if (((addr ^ write_page) <= ARAM_PAGE_MASK)) {
|
||||||
|
do_put_mem_quad((uae_u64*)(addr + write_offset), l);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifndef HW_SIGSEGV
|
||||||
|
addr = addr < 0xff000000 ? addr : addr & 0x00ffffff;
|
||||||
|
if ((addr & 0xfff00000) == 0x00f00000) {
|
||||||
|
HWput_l(addr, l); /* TODO: must be HWput_q */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
check_ram_boundary(addr, 8, true);
|
||||||
|
uae_u64 * const m = (uae_u64 *)phys_get_real_address(addr);
|
||||||
|
#ifdef ARAM_PAGE_CHECK
|
||||||
|
write_page = addr;
|
||||||
|
write_offset = (uintptr)m - (uintptr)addr;
|
||||||
|
#endif
|
||||||
|
do_put_mem_quad(m, l);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void phys_put_long(uaecptr addr, uae_u32 l)
|
||||||
|
{
|
||||||
|
#ifdef ARAM_PAGE_CHECK
|
||||||
|
if (((addr ^ write_page) <= ARAM_PAGE_MASK)) {
|
||||||
|
do_put_mem_long((uae_u32*)(addr + write_offset), l);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifndef HW_SIGSEGV
|
||||||
|
addr = addr < 0xff000000 ? addr : addr & 0x00ffffff;
|
||||||
|
if ((addr & 0xfff00000) == 0x00f00000) {
|
||||||
|
HWput_l(addr, l);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
check_ram_boundary(addr, 4, true);
|
||||||
|
uae_u32 * const m = (uae_u32 *)phys_get_real_address(addr);
|
||||||
|
#ifdef ARAM_PAGE_CHECK
|
||||||
|
write_page = addr;
|
||||||
|
write_offset = (uintptr)m - (uintptr)addr;
|
||||||
|
#endif
|
||||||
|
do_put_mem_long(m, l);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void phys_put_word(uaecptr addr, uae_u32 w)
|
||||||
|
{
|
||||||
|
#ifdef ARAM_PAGE_CHECK
|
||||||
|
if (((addr ^ write_page) <= ARAM_PAGE_MASK)) {
|
||||||
|
do_put_mem_word((uae_u16*)(addr + write_offset), w);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifndef HW_SIGSEGV
|
||||||
|
addr = addr < 0xff000000 ? addr : addr & 0x00ffffff;
|
||||||
|
if ((addr & 0xfff00000) == 0x00f00000) {
|
||||||
|
HWput_w(addr, w);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
check_ram_boundary(addr, 2, true);
|
||||||
|
uae_u16 * const m = (uae_u16 *)phys_get_real_address(addr);
|
||||||
|
#ifdef ARAM_PAGE_CHECK
|
||||||
|
write_page = addr;
|
||||||
|
write_offset = (uintptr)m - (uintptr)addr;
|
||||||
|
#endif
|
||||||
|
do_put_mem_word(m, w);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void phys_put_byte(uaecptr addr, uae_u32 b)
|
||||||
|
{
|
||||||
|
#ifdef ARAM_PAGE_CHECK
|
||||||
|
if (((addr ^ write_page) <= ARAM_PAGE_MASK)) {
|
||||||
|
do_put_mem_byte((uae_u8*)(addr + write_offset), b);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifndef HW_SIGSEGV
|
||||||
|
addr = addr < 0xff000000 ? addr : addr & 0x00ffffff;
|
||||||
|
if ((addr & 0xfff00000) == 0x00f00000) {
|
||||||
|
HWput_b(addr, b);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
check_ram_boundary(addr, 1, true);
|
||||||
|
uae_u8 * const m = (uae_u8 *)phys_get_real_address(addr);
|
||||||
|
#ifdef ARAM_PAGE_CHECK
|
||||||
|
write_page = addr;
|
||||||
|
write_offset = (uintptr)m - (uintptr)addr;
|
||||||
|
#endif
|
||||||
|
do_put_mem_byte(m, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef FULLMMU
|
||||||
|
static ALWAYS_INLINE bool is_unaligned(uaecptr addr, int size)
|
||||||
|
{
|
||||||
|
return unlikely((addr & (size - 1)) && (addr ^ (addr + size - 1)) & 0x1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ALWAYS_INLINE uae_u8 *mmu_get_real_address(uaecptr addr, struct mmu_atc_line *cl)
|
||||||
|
{
|
||||||
|
return do_get_real_address(cl->phys + addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ALWAYS_INLINE uae_u32 mmu_get_quad(uaecptr addr, int data)
|
||||||
|
{
|
||||||
|
struct mmu_atc_line *cl;
|
||||||
|
|
||||||
|
if (likely(mmu_lookup(addr, data, 0, &cl)))
|
||||||
|
return do_get_mem_quad((uae_u64 *)mmu_get_real_address(addr, cl));
|
||||||
|
return mmu_get_quad_slow(addr, regs.s, data, cl);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ALWAYS_INLINE uae_u64 get_quad(uaecptr addr)
|
||||||
|
{
|
||||||
|
return mmu_get_quad(addr, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ALWAYS_INLINE uae_u32 mmu_get_long(uaecptr addr, int data, int size)
|
||||||
|
{
|
||||||
|
struct mmu_atc_line *cl;
|
||||||
|
|
||||||
|
if (likely(mmu_lookup(addr, data, 0, &cl)))
|
||||||
|
return do_get_mem_long((uae_u32 *)mmu_get_real_address(addr, cl));
|
||||||
|
return mmu_get_long_slow(addr, regs.s, data, size, cl);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ALWAYS_INLINE uae_u32 get_long(uaecptr addr)
|
||||||
|
{
|
||||||
|
if (unlikely(is_unaligned(addr, 4)))
|
||||||
|
return mmu_get_long_unaligned(addr, 1);
|
||||||
|
return mmu_get_long(addr, 1, sz_long);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ALWAYS_INLINE uae_u16 mmu_get_word(uaecptr addr, int data, int size)
|
||||||
|
{
|
||||||
|
struct mmu_atc_line *cl;
|
||||||
|
|
||||||
|
if (likely(mmu_lookup(addr, data, 0, &cl)))
|
||||||
|
return do_get_mem_word((uae_u16 *)mmu_get_real_address(addr, cl));
|
||||||
|
return mmu_get_word_slow(addr, regs.s, data, size, cl);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ALWAYS_INLINE uae_u16 get_word(uaecptr addr)
|
||||||
|
{
|
||||||
|
if (unlikely(is_unaligned(addr, 2)))
|
||||||
|
return mmu_get_word_unaligned(addr, 1);
|
||||||
|
return mmu_get_word(addr, 1, sz_word);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ALWAYS_INLINE uae_u8 mmu_get_byte(uaecptr addr, int data, int size)
|
||||||
|
{
|
||||||
|
struct mmu_atc_line *cl;
|
||||||
|
|
||||||
|
if (likely(mmu_lookup(addr, data, 0, &cl)))
|
||||||
|
return do_get_mem_byte((uae_u8 *)mmu_get_real_address(addr, cl));
|
||||||
|
return mmu_get_byte_slow(addr, regs.s, data, size, cl);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ALWAYS_INLINE uae_u8 get_byte(uaecptr addr)
|
||||||
|
{
|
||||||
|
return mmu_get_byte(addr, 1, sz_byte);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ALWAYS_INLINE void mmu_put_quad(uaecptr addr, uae_u64 val, int data)
|
||||||
|
{
|
||||||
|
struct mmu_atc_line *cl;
|
||||||
|
|
||||||
|
if (likely(mmu_lookup(addr, data, 1, &cl)))
|
||||||
|
do_put_mem_quad((uae_u64 *)mmu_get_real_address(addr, cl), val);
|
||||||
|
else
|
||||||
|
mmu_put_quad_slow(addr, val, regs.s, data, cl);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ALWAYS_INLINE void put_quad(uaecptr addr, uae_u32 val)
|
||||||
|
{
|
||||||
|
mmu_put_quad(addr, val, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ALWAYS_INLINE void mmu_put_long(uaecptr addr, uae_u32 val, int data, int size)
|
||||||
|
{
|
||||||
|
struct mmu_atc_line *cl;
|
||||||
|
|
||||||
|
if (likely(mmu_lookup(addr, data, 1, &cl)))
|
||||||
|
do_put_mem_long((uae_u32 *)mmu_get_real_address(addr, cl), val);
|
||||||
|
else
|
||||||
|
mmu_put_long_slow(addr, val, regs.s, data, size, cl);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ALWAYS_INLINE void put_long(uaecptr addr, uae_u32 val)
|
||||||
|
{
|
||||||
|
if (unlikely(is_unaligned(addr, 4)))
|
||||||
|
mmu_put_long_unaligned(addr, val, 1);
|
||||||
|
else
|
||||||
|
mmu_put_long(addr, val, 1, sz_long);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ALWAYS_INLINE void mmu_put_word(uaecptr addr, uae_u16 val, int data, int size)
|
||||||
|
{
|
||||||
|
struct mmu_atc_line *cl;
|
||||||
|
|
||||||
|
if (likely(mmu_lookup(addr, data, 1, &cl)))
|
||||||
|
do_put_mem_word((uae_u16 *)mmu_get_real_address(addr, cl), val);
|
||||||
|
else
|
||||||
|
mmu_put_word_slow(addr, val, regs.s, data, size, cl);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ALWAYS_INLINE void put_word(uaecptr addr, uae_u16 val)
|
||||||
|
{
|
||||||
|
if (unlikely(is_unaligned(addr, 2)))
|
||||||
|
mmu_put_word_unaligned(addr, val, 1);
|
||||||
|
else
|
||||||
|
mmu_put_word(addr, val, 1, sz_word);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ALWAYS_INLINE void mmu_put_byte(uaecptr addr, uae_u8 val, int data, int size)
|
||||||
|
{
|
||||||
|
struct mmu_atc_line *cl;
|
||||||
|
|
||||||
|
if (likely(mmu_lookup(addr, data, 1, &cl)))
|
||||||
|
do_put_mem_byte((uae_u8 *)mmu_get_real_address(addr, cl), val);
|
||||||
|
else
|
||||||
|
mmu_put_byte_slow(addr, val, regs.s, data, size, cl);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ALWAYS_INLINE void put_byte(uaecptr addr, uae_u8 val)
|
||||||
|
{
|
||||||
|
mmu_put_byte(addr, val, 1, sz_byte);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uae_u8 *get_real_address(uaecptr addr, int write, int sz)
|
||||||
|
{
|
||||||
|
(void)sz;
|
||||||
|
return phys_get_real_address(mmu_translate(addr, regs.s, 1, write));
|
||||||
|
}
|
||||||
|
|
||||||
|
static ALWAYS_INLINE uae_u32 mmu_get_user_long(uaecptr addr, int super, int data, int size)
|
||||||
|
{
|
||||||
|
struct mmu_atc_line *cl;
|
||||||
|
|
||||||
|
if (likely(mmu_user_lookup(addr, super, data, 0, &cl)))
|
||||||
|
return do_get_mem_long((uae_u32 *)mmu_get_real_address(addr, cl));
|
||||||
|
return mmu_get_long_slow(addr, super, data, size, cl);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ALWAYS_INLINE uae_u16 mmu_get_user_word(uaecptr addr, int super, int data, int size)
|
||||||
|
{
|
||||||
|
struct mmu_atc_line *cl;
|
||||||
|
|
||||||
|
if (likely(mmu_user_lookup(addr, super, data, 0, &cl)))
|
||||||
|
return do_get_mem_word((uae_u16 *)mmu_get_real_address(addr, cl));
|
||||||
|
return mmu_get_word_slow(addr, super, data, size, cl);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ALWAYS_INLINE uae_u8 mmu_get_user_byte(uaecptr addr, int super, int data, int size)
|
||||||
|
{
|
||||||
|
struct mmu_atc_line *cl;
|
||||||
|
|
||||||
|
if (likely(mmu_user_lookup(addr, super, data, 0, &cl)))
|
||||||
|
return do_get_mem_byte((uae_u8 *)mmu_get_real_address(addr, cl));
|
||||||
|
return mmu_get_byte_slow(addr, super, data, size, cl);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ALWAYS_INLINE void mmu_put_user_long(uaecptr addr, uae_u32 val, int super, int data, int size)
|
||||||
|
{
|
||||||
|
struct mmu_atc_line *cl;
|
||||||
|
|
||||||
|
if (likely(mmu_user_lookup(addr, super, data, 1, &cl)))
|
||||||
|
do_put_mem_long((uae_u32 *)mmu_get_real_address(addr, cl), val);
|
||||||
|
else
|
||||||
|
mmu_put_long_slow(addr, val, super, data, size, cl);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ALWAYS_INLINE void mmu_put_user_word(uaecptr addr, uae_u16 val, int super, int data, int size)
|
||||||
|
{
|
||||||
|
struct mmu_atc_line *cl;
|
||||||
|
|
||||||
|
if (likely(mmu_user_lookup(addr, super, data, 1, &cl)))
|
||||||
|
do_put_mem_word((uae_u16 *)mmu_get_real_address(addr, cl), val);
|
||||||
|
else
|
||||||
|
mmu_put_word_slow(addr, val, super, data, size, cl);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ALWAYS_INLINE void mmu_put_user_byte(uaecptr addr, uae_u8 val, int super, int data, int size)
|
||||||
|
{
|
||||||
|
struct mmu_atc_line *cl;
|
||||||
|
|
||||||
|
if (likely(mmu_user_lookup(addr, super, data, 1, &cl)))
|
||||||
|
do_put_mem_byte((uae_u8 *)mmu_get_real_address(addr, cl), val);
|
||||||
|
else
|
||||||
|
mmu_put_byte_slow(addr, val, super, data, size, cl);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool valid_address(uaecptr addr, bool write, int sz)
|
||||||
|
{
|
||||||
|
SAVE_EXCEPTION;
|
||||||
|
TRY(prb) {
|
||||||
|
(void)sz;
|
||||||
|
check_ram_boundary(mmu_translate(addr, regs.s, 1, (write ? 1 : 0)), sz, write);
|
||||||
|
RESTORE_EXCEPTION;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
CATCH(prb) {
|
||||||
|
RESTORE_EXCEPTION;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
# define get_quad(a) phys_get_quad(a)
|
||||||
|
# define get_long(a) phys_get_long(a)
|
||||||
|
# define get_word(a) phys_get_word(a)
|
||||||
|
# define get_byte(a) phys_get_byte(a)
|
||||||
|
# define put_quad(a,b) phys_put_quad(a,b)
|
||||||
|
# define put_long(a,b) phys_put_long(a,b)
|
||||||
|
# define put_word(a,b) phys_put_word(a,b)
|
||||||
|
# define put_byte(a,b) phys_put_byte(a,b)
|
||||||
|
# define get_real_address(a,w,s) phys_get_real_address(a)
|
||||||
|
|
||||||
|
#define valid_address(a,w,s) phys_valid_address(a,w,s)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static inline void flush_internals() {
|
||||||
|
#ifdef ARAM_PAGE_CHECK
|
||||||
|
pc_page = 0xeeeeeeee;
|
||||||
|
read_page = 0xeeeeeeee;
|
||||||
|
write_page = 0xeeeeeeee;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* MEMORY_H */
|
||||||
|
|
||||||
|
/*
|
||||||
|
vim:ts=4:sw=4:
|
||||||
|
*/
|
|
@ -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
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
* (at your option) any later version.
|
* (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
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* 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
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
|
/*
|
||||||
#include <stdio.h>
|
* UAE - The Un*x Amiga Emulator
|
||||||
#include <stdlib.h>
|
*
|
||||||
|
* Memory management
|
||||||
|
*
|
||||||
|
* (c) 1995 Bernd Schmidt
|
||||||
|
*/
|
||||||
|
|
||||||
#include "sysdeps.h"
|
#include "sysdeps.h"
|
||||||
|
|
||||||
#include "cpu_emulation.h"
|
|
||||||
#include "main.h"
|
|
||||||
#include "video.h"
|
|
||||||
|
|
||||||
#include "m68k.h"
|
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "readcpu.h"
|
#define DEBUG 0
|
||||||
#include "newcpu.h"
|
#include "debug.h"
|
||||||
|
|
||||||
#if !REAL_ADDRESSING && !DIRECT_ADDRESSING
|
#ifdef ARAM_PAGE_CHECK
|
||||||
|
uaecptr pc_page = 0xeeeeeeee;
|
||||||
static bool illegal_mem = false;
|
uintptr pc_offset = 0;
|
||||||
|
uaecptr read_page = 0xeeeeeeee;
|
||||||
#ifdef SAVE_MEMORY_BANKS
|
uintptr read_offset = 0;
|
||||||
addrbank *mem_banks[65536];
|
uaecptr write_page = 0xeeeeeeee;
|
||||||
#else
|
uintptr write_offset = 0;
|
||||||
addrbank mem_banks[65536];
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef WORDS_BIGENDIAN
|
extern "C" void breakpt(void)
|
||||||
# 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)
|
|
||||||
{
|
{
|
||||||
return call_mem_get_func (get_mem_bank (addr).lget, addr);
|
// bug("bus err: pc=%08x, sp=%08x, addr=%08x", m68k_getpc(), regs.regs[15], regs.mmu_fault_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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uae_u32 REGPARAM2 dummy_wget (uaecptr addr)
|
#if !KNOWN_ALLOC && !NORMAL_ADDRESSING
|
||||||
{
|
// This part need rewrite for ARAnyM !!
|
||||||
if (illegal_mem)
|
// It can be taken from hatari.
|
||||||
write_log ("Illegal wget at %08x\n", addr);
|
|
||||||
|
|
||||||
return 0;
|
#error Not prepared for your platform, maybe you need memory banks from hatari
|
||||||
}
|
|
||||||
|
|
||||||
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 */
|
|
||||||
|
|
||||||
|
#endif /* !KNOWN_ALLOC && !NORMAL_ADDRESSING */
|
||||||
|
|
|
@ -23,6 +23,10 @@
|
||||||
#ifndef UAE_MEMORY_H
|
#ifndef UAE_MEMORY_H
|
||||||
#define UAE_MEMORY_H
|
#define UAE_MEMORY_H
|
||||||
|
|
||||||
|
#if DIRECT_ADDRESSING
|
||||||
|
extern uintptr MEMBaseDiff;
|
||||||
|
#endif
|
||||||
|
|
||||||
extern void Exception (int, uaecptr);
|
extern void Exception (int, uaecptr);
|
||||||
#ifdef EXCEPTIONS_VIA_LONGJMP
|
#ifdef EXCEPTIONS_VIA_LONGJMP
|
||||||
extern JMP_BUF excep_env;
|
extern JMP_BUF excep_env;
|
||||||
|
@ -50,109 +54,8 @@ extern void Exception (int, uaecptr);
|
||||||
#define THROW_AGAIN(var) throw
|
#define THROW_AGAIN(var) throw
|
||||||
#define VOLATILE
|
#define VOLATILE
|
||||||
#endif /* EXCEPTIONS_VIA_LONGJMP */
|
#endif /* EXCEPTIONS_VIA_LONGJMP */
|
||||||
extern int in_exception_2;
|
|
||||||
|
|
||||||
#if !DIRECT_ADDRESSING && !REAL_ADDRESSING
|
#if DIRECT_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
|
|
||||||
static __inline__ uae_u8 *do_get_real_address(uaecptr addr)
|
static __inline__ uae_u8 *do_get_real_address(uaecptr addr)
|
||||||
{
|
{
|
||||||
return (uae_u8 *)MEMBaseDiff + 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);
|
uae_u32 * const m = (uae_u32 *)do_get_real_address(addr);
|
||||||
return do_get_mem_long(m);
|
return do_get_mem_long(m);
|
||||||
}
|
}
|
||||||
|
#define phys_get_long get_long
|
||||||
static __inline__ uae_u32 get_word(uaecptr addr)
|
static __inline__ uae_u32 get_word(uaecptr addr)
|
||||||
{
|
{
|
||||||
uae_u16 * const m = (uae_u16 *)do_get_real_address(addr);
|
uae_u16 * const m = (uae_u16 *)do_get_real_address(addr);
|
||||||
return do_get_mem_word(m);
|
return do_get_mem_word(m);
|
||||||
}
|
}
|
||||||
|
#define phys_get_word get_word
|
||||||
static __inline__ uae_u32 get_byte(uaecptr addr)
|
static __inline__ uae_u32 get_byte(uaecptr addr)
|
||||||
{
|
{
|
||||||
uae_u8 * const m = (uae_u8 *)do_get_real_address(addr);
|
uae_u8 * const m = (uae_u8 *)do_get_real_address(addr);
|
||||||
return do_get_mem_byte(m);
|
return do_get_mem_byte(m);
|
||||||
}
|
}
|
||||||
|
#define phys_get_byte get_byte
|
||||||
static __inline__ void put_long(uaecptr addr, uae_u32 l)
|
static __inline__ void put_long(uaecptr addr, uae_u32 l)
|
||||||
{
|
{
|
||||||
uae_u32 * const m = (uae_u32 *)do_get_real_address(addr);
|
uae_u32 * const m = (uae_u32 *)do_get_real_address(addr);
|
||||||
do_put_mem_long(m, l);
|
do_put_mem_long(m, l);
|
||||||
}
|
}
|
||||||
|
#define phys_put_long put_long
|
||||||
static __inline__ void put_word(uaecptr addr, uae_u32 w)
|
static __inline__ void put_word(uaecptr addr, uae_u32 w)
|
||||||
{
|
{
|
||||||
uae_u16 * const m = (uae_u16 *)do_get_real_address(addr);
|
uae_u16 * const m = (uae_u16 *)do_get_real_address(addr);
|
||||||
do_put_mem_word(m, w);
|
do_put_mem_word(m, w);
|
||||||
}
|
}
|
||||||
|
#define phys_put_word put_word
|
||||||
static __inline__ void put_byte(uaecptr addr, uae_u32 b)
|
static __inline__ void put_byte(uaecptr addr, uae_u32 b)
|
||||||
{
|
{
|
||||||
uae_u8 * const m = (uae_u8 *)do_get_real_address(addr);
|
uae_u8 * const m = (uae_u8 *)do_get_real_address(addr);
|
||||||
do_put_mem_byte(m, b);
|
do_put_mem_byte(m, b);
|
||||||
}
|
}
|
||||||
|
#define phys_put_byte put_byte
|
||||||
static __inline__ uae_u8 *get_real_address(uaecptr addr)
|
static __inline__ uae_u8 *get_real_address(uaecptr addr)
|
||||||
{
|
{
|
||||||
return do_get_real_address(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)
|
static __inline__ uae_u32 get_virtual_address(uae_u8 *addr)
|
||||||
{
|
{
|
||||||
return do_get_virtual_address(addr);
|
return do_get_virtual_address(addr);
|
||||||
}
|
}
|
||||||
#else
|
#endif /* DIRECT_ADDRESSING */
|
||||||
static __inline__ uae_u32 get_long(uaecptr addr)
|
|
||||||
{
|
static __inline__ void check_ram_boundary(uaecptr addr, int size, bool write) {}
|
||||||
return longget_1(addr);
|
static inline void flush_internals() {}
|
||||||
}
|
|
||||||
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 /* MEMORY_H */
|
#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
|
* it under the terms of the GNU General Public License as published by
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
* (at your option) any later version.
|
* (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
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* GNU General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* 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
|
* 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
|
#ifndef NEWCPU_H
|
||||||
#define NEWCPU_H
|
#define NEWCPU_H
|
||||||
|
|
||||||
#ifndef FLIGHT_RECORDER
|
#include "sysdeps.h"
|
||||||
#define FLIGHT_RECORDER 0
|
#include "registers.h"
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "m68k.h"
|
|
||||||
#include "readcpu.h"
|
|
||||||
#include "spcflags.h"
|
#include "spcflags.h"
|
||||||
|
#include "m68k.h"
|
||||||
|
#include "memory.h"
|
||||||
|
|
||||||
#if ENABLE_MON
|
# include <csetjmp>
|
||||||
#include "mon.h"
|
|
||||||
#include "mon_disass.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
extern struct fixup {
|
||||||
|
int flag;
|
||||||
|
uae_u32 reg;
|
||||||
|
uaecptr value;
|
||||||
|
}fixup;
|
||||||
|
|
||||||
extern int areg_byteinc[];
|
extern int areg_byteinc[];
|
||||||
extern int imm8_table[];
|
extern int imm8_table[];
|
||||||
|
@ -57,27 +67,25 @@ extern int broken_in;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define cpuop_begin() do { cpuop_tag("begin"); } while (0)
|
#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;
|
typedef void REGPARAM2 cpuop_func (uae_u32) REGPARAM;
|
||||||
|
|
||||||
struct cputbl {
|
struct cputbl {
|
||||||
cpuop_func *handler;
|
cpuop_func *handler;
|
||||||
uae_u16 specific;
|
uae_u16 specific;
|
||||||
uae_u16 opcode;
|
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;
|
typedef void compop_func (uae_u32) REGPARAM;
|
||||||
|
|
||||||
//NOTE: The "opcode" and "specific" fields were switched in the original source code!
|
|
||||||
|
|
||||||
struct comptbl {
|
struct comptbl {
|
||||||
compop_func *handler;
|
compop_func *handler;
|
||||||
uae_u32 opcode;
|
uae_u32 opcode;
|
||||||
uae_u32 specific;
|
uae_u32 specific;
|
||||||
#define COMP_OPCODE_ISJUMP 0x0001
|
#define COMP_OPCODE_ISJUMP 0x0001
|
||||||
#define COMP_OPCODE_LONG_OPCODE 0x0002
|
#define COMP_OPCODE_LONG_OPCODE 0x0002
|
||||||
#define COMP_OPCODE_CMOV 0x0004
|
#define COMP_OPCODE_CMOV 0x0004
|
||||||
|
@ -88,151 +96,84 @@ struct comptbl {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern void REGPARAM2 op_illg (uae_u32) REGPARAM;
|
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_dreg(r,num) ((r).regs[(num)])
|
||||||
#define m68k_areg(r,num) (((r).regs + 8)[(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))
|
#ifdef FULLMMU
|
||||||
#define get_iword(o) do_get_mem_word((uae_u16 *)(regs.pc_p + (o)))
|
static ALWAYS_INLINE uae_u8 get_ibyte(uae_u32 o)
|
||||||
#define get_ilong(o) do_get_mem_long((uae_u32 *)(regs.pc_p + (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
|
#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
|
#endif
|
||||||
|
|
||||||
#if USE_PREFETCH_BUFFER
|
#if 0
|
||||||
static __inline__ uae_u32 get_ibyte_prefetch (uae_s32 o)
|
static inline uae_u32 get_ibyte_prefetch (uae_s32 o)
|
||||||
{
|
{
|
||||||
if (o > 3 || o < 0)
|
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));
|
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)
|
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));
|
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)
|
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)
|
if (o == 0)
|
||||||
return do_get_mem_long(®s.prefetch);
|
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
|
#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
|
#if USE_PREFETCH_BUFFER
|
||||||
uae_u32 r;
|
uae_u32 r;
|
||||||
#ifdef UNALIGNED_PROFITABLE
|
#ifdef UNALIGNED_PROFITABLE
|
||||||
r = *(uae_u32 *)regs.pc_p;
|
r = *(uae_u32 *)do_get_real_address(m68k_getpc(), false, false);
|
||||||
regs.prefetch = r;
|
regs.prefetch = r;
|
||||||
#else
|
#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);
|
do_put_mem_long (®s.prefetch, r);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#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 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;
|
r |= r2;
|
||||||
do_put_mem_long (®s.prefetch, r);
|
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
|
#define fill_prefetch_2 fill_prefetch_0
|
||||||
#endif
|
#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
|
/* These are only used by the 68020/68881 code, and therefore don't
|
||||||
* need to handle prefetch. */
|
* need to handle prefetch. */
|
||||||
static __inline__ uae_u32 next_ibyte (void)
|
static inline uae_u32 next_ibyte (void)
|
||||||
{
|
{
|
||||||
uae_u32 r = get_ibyte (0);
|
uae_u32 r = get_ibyte (0);
|
||||||
m68k_incpc (2);
|
m68k_incpc (2);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static __inline__ uae_u32 next_iword (void)
|
static inline uae_u32 next_iword (void)
|
||||||
{
|
{
|
||||||
uae_u32 r = get_iword (0);
|
uae_u32 r = get_iword (0);
|
||||||
m68k_incpc (2);
|
m68k_incpc (2);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static __inline__ uae_u32 next_ilong (void)
|
static inline uae_u32 next_ilong (void)
|
||||||
{
|
{
|
||||||
uae_u32 r = get_ilong (0);
|
uae_u32 r = get_ilong (0);
|
||||||
m68k_incpc (4);
|
m68k_incpc (4);
|
||||||
return r;
|
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_fast m68k_setpc
|
||||||
#define m68k_setpc_bcc m68k_setpc
|
#define m68k_setpc_bcc m68k_setpc
|
||||||
#define m68k_setpc_rte 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_setpc(get_long(m68k_areg(regs, 7)));
|
||||||
m68k_areg(regs, 7) += 4;
|
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) - 4, oldpc);
|
||||||
put_long(m68k_areg(regs, 7), oldpc);
|
m68k_areg(regs, 7) -= 4;
|
||||||
m68k_incpc(offset);
|
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) - 4, oldpc);
|
||||||
put_long(m68k_areg(regs, 7), oldpc);
|
m68k_areg(regs, 7) -= 4;
|
||||||
m68k_setpc(dest);
|
m68k_setpc(dest);
|
||||||
}
|
}
|
||||||
|
|
||||||
static __inline__ void m68k_setstopped (int stop)
|
static inline void m68k_setstopped (int stop)
|
||||||
{
|
{
|
||||||
regs.stopped = stop;
|
regs.stopped = stop;
|
||||||
/* A traced STOP instruction drops through immediately without
|
/* A traced STOP instruction drops through immediately without
|
||||||
actually stopping. */
|
actually stopping. */
|
||||||
if (stop && (regs.spcflags & SPCFLAG_DOTRACE) == 0)
|
if (stop && !( SPCFLAGS_TEST( SPCFLAG_DOTRACE )))
|
||||||
SPCFLAGS_SET( SPCFLAG_STOP );
|
SPCFLAGS_SET( SPCFLAG_STOP );
|
||||||
}
|
}
|
||||||
|
|
||||||
extern uae_u32 get_disp_ea_020 (uae_u32 base, uae_u32 dp);
|
#ifdef FULLMMU
|
||||||
extern uae_u32 get_disp_ea_000 (uae_u32 base, uae_u32 dp);
|
# 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 MakeSR (void);
|
||||||
extern void MakeFromSR (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_mull (uae_u32, uae_u32, uae_u16);
|
||||||
extern void m68k_emulop (uae_u32);
|
extern void m68k_emulop (uae_u32);
|
||||||
extern void m68k_emulop_return (void);
|
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 init_m68k (void);
|
||||||
extern void exit_m68k (void);
|
extern void exit_m68k (void);
|
||||||
extern void m68k_dumpstate (uaecptr *);
|
extern void m68k_dumpstate (FILE *, uaecptr *);
|
||||||
extern void m68k_disasm (uaecptr, uaecptr *, int);
|
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_reset (void);
|
||||||
extern void m68k_enter_debugger(void);
|
extern void m68k_enter_debugger(void);
|
||||||
extern int m68k_do_specialties(void);
|
extern int m68k_do_specialties(void);
|
||||||
|
extern void m68k_instr_set(void);
|
||||||
extern void mmu_op (uae_u32, uae_u16);
|
uae_u32 linea68000(uae_u16 opcode);
|
||||||
|
|
||||||
/* Opcode of faulting instruction */
|
/* Opcode of faulting instruction */
|
||||||
extern uae_u16 last_op_for_exception_3;
|
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
|
#define CPU_OP_NAME(a) op ## a
|
||||||
|
|
||||||
/* 68020 + 68881 */
|
/* 68040+ 68881 */
|
||||||
extern struct cputbl op_smalltbl_0_ff[];
|
extern const struct cputbl op_smalltbl_0_ff[];
|
||||||
/* 68020 */
|
extern const struct cputbl op_smalltbl_0_nf[];
|
||||||
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[];
|
|
||||||
|
|
||||||
#if FLIGHT_RECORDER
|
#ifdef FLIGHT_RECORDER
|
||||||
extern void m68k_record_step(uaecptr) REGPARAM;
|
extern void m68k_record_step(uaecptr, int);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern void m68k_do_execute(void);
|
extern void m68k_do_execute(void);
|
||||||
extern void m68k_execute(void);
|
extern void m68k_execute(void);
|
||||||
#if USE_JIT
|
#ifdef USE_JIT
|
||||||
extern void m68k_compile_execute(void);
|
extern void m68k_compile_execute(void);
|
||||||
|
extern void m68k_do_compile_execute(void);
|
||||||
#endif
|
#endif
|
||||||
#ifdef USE_CPU_EMUL_SERVICES
|
#ifdef USE_CPU_EMUL_SERVICES
|
||||||
extern int32 emulated_ticks;
|
extern int32 emulated_ticks;
|
||||||
|
@ -411,5 +328,7 @@ static inline void cpu_check_ticks(void)
|
||||||
#define cpu_check_ticks()
|
#define cpu_check_ticks()
|
||||||
#define cpu_do_check_ticks()
|
#define cpu_do_check_ticks()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
cpuop_func op_illg_1;
|
||||||
|
|
||||||
#endif /* NEWCPU_H */
|
#endif /* NEWCPU_H */
|
||||||
|
|
|
@ -33,13 +33,13 @@
|
||||||
#define NOFLAGS_CMP 0
|
#define NOFLAGS_CMP 0
|
||||||
|
|
||||||
#undef SET_NFLG_ALWAYS
|
#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 */
|
SET_NFLG(x); /* This has not yet been redefined */
|
||||||
}
|
}
|
||||||
|
|
||||||
#undef SET_CFLG_ALWAYS
|
#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 */
|
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)
|
#define SET_XFLG(y) do {uae_u32 dummy=(y); } while (0)
|
||||||
|
|
||||||
#undef CLEAR_CZNV
|
#undef CLEAR_CZNV
|
||||||
#define CLEAR_CZNV() do {} while (0)
|
#define CLEAR_CZNV()
|
||||||
#undef IOR_CZNV
|
#undef IOR_CZNV
|
||||||
#define IOR_CZNV(y) do {uae_u32 dummy=(y); } while (0)
|
#define IOR_CZNV(y) do {uae_u32 dummy=(y); } while (0)
|
||||||
#undef SET_CZNV
|
#undef SET_CZNV
|
||||||
#define SET_CZNV(y) do {uae_u32 dummy=(y); } while (0)
|
#define SET_CZNV(y) do {uae_u32 dummy=(y); } while (0)
|
||||||
#undef COPY_CARRY
|
#undef COPY_CARRY
|
||||||
#define COPY_CARRY() do {} while (0)
|
#define COPY_CARRY()
|
||||||
|
|
||||||
#ifdef optflag_testl
|
#ifdef optflag_testl
|
||||||
#undef optflag_testl
|
#undef optflag_testl
|
||||||
|
|
|
@ -1,34 +1,30 @@
|
||||||
|
/* 2002 MJ */
|
||||||
/*
|
/*
|
||||||
* UAE - The Un*x Amiga Emulator
|
* UAE - The Un*x Amiga Emulator
|
||||||
*
|
*
|
||||||
* Read 68000 CPU specs from file "table68k"
|
* Read 68000 CPU specs from file "table68k"
|
||||||
*
|
*
|
||||||
* Copyright 1995,1996 Bernd Schmidt
|
* 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 "sysdeps.h"
|
||||||
#include "readcpu.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;
|
int nr_cpuop_funcs;
|
||||||
|
struct instr *table68k;
|
||||||
|
static int readcpu_mismatch;
|
||||||
|
|
||||||
struct mnemolookup lookuptab[] = {
|
struct mnemolookup lookuptab[] = {
|
||||||
{ i_ILLG, "ILLEGAL" },
|
{ i_ILLG, "ILLEGAL" },
|
||||||
|
@ -153,16 +149,19 @@ struct mnemolookup lookuptab[] = {
|
||||||
{ i_CPUSHA, "CPUSHA" },
|
{ i_CPUSHA, "CPUSHA" },
|
||||||
{ i_MOVE16, "MOVE16" },
|
{ i_MOVE16, "MOVE16" },
|
||||||
|
|
||||||
{ i_EMULOP_RETURN, "EMULOP_RETURN" },
|
{ i_EMULOP_RETURN, "EMULOP_RETURN" },
|
||||||
{ i_EMULOP, "EMULOP" },
|
{ i_EMULOP, "EMULOP" },
|
||||||
|
|
||||||
{ i_MMUOP, "MMUOP" },
|
{ i_MMUOP, "MMUOP" },
|
||||||
|
|
||||||
|
{i_NATFEAT_ID, "NATFEAT_ID" },
|
||||||
|
{i_NATFEAT_CALL, "NATFEAT_CALL" },
|
||||||
|
|
||||||
{ i_ILLG, "" },
|
{ 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, "Dreg", 4) == 0) return Dreg;
|
||||||
if (strncmp (str, "Areg", 4) == 0) return Areg;
|
if (strncmp (str, "Areg", 4) == 0) return Areg;
|
||||||
|
@ -180,7 +179,7 @@ static __inline__ amodes mode_from_str (const char *str)
|
||||||
return (amodes)0;
|
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) {
|
switch (mode) {
|
||||||
case 0: return Dreg;
|
case 0: return Dreg;
|
||||||
|
@ -215,31 +214,32 @@ static void build_insn (int insn)
|
||||||
int i, n;
|
int i, n;
|
||||||
|
|
||||||
int flaglive = 0, flagdead = 0;
|
int flaglive = 0, flagdead = 0;
|
||||||
int cflow = 0;
|
int cflow = 0;
|
||||||
|
|
||||||
id = defs68k[insn];
|
id = defs68k[insn];
|
||||||
|
|
||||||
// Control flow information
|
// Control flow information
|
||||||
cflow = id.cflow;
|
cflow = id.cflow;
|
||||||
|
|
||||||
// Mask of flags set/used
|
// Mask of flags set/used
|
||||||
unsigned char flags_set(0), flags_used(0);
|
unsigned char flags_set(0), flags_used(0);
|
||||||
|
|
||||||
for (i = 0, n = 4; i < 5; i++, n--) {
|
for (i = 0, n = 4; i < 5; i++, n--) {
|
||||||
switch (id.flaginfo[i].flagset) {
|
switch (id.flaginfo[i].flagset) {
|
||||||
case fa_unset: case fa_isjmp: break;
|
case fa_unset: case fa_isjmp: break;
|
||||||
default: flags_set |= (1 << n);
|
default: flags_set |= (1 << n);
|
||||||
}
|
|
||||||
|
|
||||||
switch (id.flaginfo[i].flaguse) {
|
|
||||||
case fu_unused: case fu_isjmp: break;
|
|
||||||
default: flags_used |= (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++) {
|
for (i = 0; i < 5; i++) {
|
||||||
switch (id.flaginfo[i].flagset){
|
switch (id.flaginfo[i].flagset){
|
||||||
case fa_unset: break;
|
case fa_unset: break;
|
||||||
|
case fa_isjmp: break;
|
||||||
case fa_zero: flagdead |= 1 << i; break;
|
case fa_zero: flagdead |= 1 << i; break;
|
||||||
case fa_one: flagdead |= 1 << i; break;
|
case fa_one: flagdead |= 1 << i; break;
|
||||||
case fa_dontcare: 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++) {
|
for (i = 0; i < 5; i++) {
|
||||||
switch (id.flaginfo[i].flaguse) {
|
switch (id.flaginfo[i].flaguse) {
|
||||||
case fu_unused: break;
|
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_unknown: flaglive = -1; goto out2;
|
||||||
case fu_used: flaglive |= 1 << i; break;
|
case fu_used: flaglive |= 1 << i; break;
|
||||||
}
|
}
|
||||||
|
@ -306,6 +308,7 @@ static void build_insn (int insn)
|
||||||
continue;
|
continue;
|
||||||
if (bitcnt[bitI] && (bitval[bitI] == 0x00 || bitval[bitI] == 0xff))
|
if (bitcnt[bitI] && (bitval[bitI] == 0x00 || bitval[bitI] == 0xff))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (bitcnt[bitE] && (bitval[bitE] == 0x00))
|
if (bitcnt[bitE] && (bitval[bitE] == 0x00))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -346,9 +349,9 @@ static void build_insn (int insn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mnp++;
|
mnp++;
|
||||||
if ((unsigned)mnp >= sizeof(mnemonic) - 1) {
|
if ((unsigned)mnp >= (sizeof(mnemonic)-1)) {
|
||||||
mnemonic[sizeof(mnemonic) - 1] = 0;
|
mnemonic[sizeof(mnemonic)-1] = '\0';
|
||||||
fprintf(stderr, "Instruction %s overflow\n", mnemonic);
|
fprintf(stderr, "WTF!!! Instruction '%s' overflow\n", mnemonic);
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -379,6 +382,7 @@ static void build_insn (int insn)
|
||||||
case 'A':
|
case 'A':
|
||||||
srcmode = Areg;
|
srcmode = Areg;
|
||||||
switch (opcstr[pos++]) {
|
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;
|
||||||
case 'R': srcreg = bitval[bitR]; srcgather = 1; srcpos = bitpos[bitR]; break;
|
case 'R': srcreg = bitval[bitR]; srcgather = 1; srcpos = bitpos[bitR]; break;
|
||||||
default: abort();
|
default: abort();
|
||||||
|
@ -388,9 +392,11 @@ static void build_insn (int insn)
|
||||||
case 'P': srcmode = Aipi; pos++; break;
|
case 'P': srcmode = Aipi; pos++; break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
#if 0
|
||||||
case 'L':
|
case 'L':
|
||||||
srcmode = absl;
|
srcmode = absl;
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
case '#':
|
case '#':
|
||||||
switch (opcstr[pos++]) {
|
switch (opcstr[pos++]) {
|
||||||
case 'z': srcmode = imm; break;
|
case 'z': srcmode = imm; break;
|
||||||
|
@ -436,7 +442,7 @@ static void build_insn (int insn)
|
||||||
srcpos = bitpos[bitK];
|
srcpos = bitpos[bitK];
|
||||||
}
|
}
|
||||||
break;
|
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 ??
|
if (CPU_EMU_SIZE < 5) { // gb-- what is CPU_EMU_SIZE used for ??
|
||||||
/* 1..255 */
|
/* 1..255 */
|
||||||
srcgather = 1;
|
srcgather = 1;
|
||||||
|
@ -444,8 +450,8 @@ static void build_insn (int insn)
|
||||||
srcpos = bitpos[bitE];
|
srcpos = bitpos[bitE];
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'p': srcmode = immi; srcreg = bitval[bitp];
|
case 'p': srcmode = immi; srcreg = bitval[bitp];
|
||||||
if (CPU_EMU_SIZE < 5) {
|
if (CPU_EMU_SIZE < 5) { // gb-- what is CPU_EMU_SIZE used for ??
|
||||||
/* 0..3 */
|
/* 0..3 */
|
||||||
srcgather = 1;
|
srcgather = 1;
|
||||||
srctype = 7;
|
srctype = 7;
|
||||||
|
@ -582,21 +588,22 @@ static void build_insn (int insn)
|
||||||
case 'A':
|
case 'A':
|
||||||
destmode = Areg;
|
destmode = Areg;
|
||||||
switch (opcstr[pos++]) {
|
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 '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();
|
default: abort();
|
||||||
}
|
}
|
||||||
if (dstpos < 0 || dstpos >= 32)
|
|
||||||
abort();
|
|
||||||
switch (opcstr[pos]) {
|
switch (opcstr[pos]) {
|
||||||
case 'p': destmode = Apdi; pos++; break;
|
case 'p': destmode = Apdi; pos++; break;
|
||||||
case 'P': destmode = Aipi; pos++; break;
|
case 'P': destmode = Aipi; pos++; break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
#if 0
|
||||||
case 'L':
|
case 'L':
|
||||||
destmode = absl;
|
destmode = absl;
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
case '#':
|
case '#':
|
||||||
switch (opcstr[pos++]) {
|
switch (opcstr[pos++]) {
|
||||||
case 'z': destmode = imm; break;
|
case 'z': destmode = imm; break;
|
||||||
|
@ -767,7 +774,7 @@ static void build_insn (int insn)
|
||||||
table68k[opc].flaginfo[i].flaguse = id.flaginfo[i].flaguse;
|
table68k[opc].flaginfo[i].flaguse = id.flaginfo[i].flaguse;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Fix flags used information for Scc, Bcc, TRAPcc, DBcc instructions
|
// Fix flags used information for Scc, Bcc, TRAPcc, DBcc instructions
|
||||||
if ( table68k[opc].mnemo == i_Scc
|
if ( table68k[opc].mnemo == i_Scc
|
||||||
|| table68k[opc].mnemo == i_Bcc
|
|| table68k[opc].mnemo == i_Bcc
|
||||||
|
@ -795,7 +802,7 @@ static void build_insn (int insn)
|
||||||
case 15:flags_used = 0x0E; break; /* LE */
|
case 15:flags_used = 0x0E; break; /* LE */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
/* gb-- flagdead and flaglive would not have correct information */
|
/* gb-- flagdead and flaglive would not have correct information */
|
||||||
table68k[opc].flagdead = flags_set;
|
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)
|
static void handle_merges (long int opcode)
|
||||||
{
|
{
|
||||||
uae_u16 smsk;
|
uae_u16 smsk;
|
||||||
|
@ -851,9 +842,9 @@ static void handle_merges (long int opcode)
|
||||||
case 5:
|
case 5:
|
||||||
smsk = 63; sbitdst = 64; break;
|
smsk = 63; sbitdst = 64; break;
|
||||||
case 6:
|
case 6:
|
||||||
smsk = 255; sbitdst = 256; break;
|
smsk = 255; sbitdst = 256; break;
|
||||||
case 7:
|
case 7:
|
||||||
smsk = 3; sbitdst = 4; break;
|
smsk = 3; sbitdst = 4; break;
|
||||||
default:
|
default:
|
||||||
smsk = 0; sbitdst = 0;
|
smsk = 0; sbitdst = 0;
|
||||||
abort();
|
abort();
|
||||||
|
@ -869,7 +860,7 @@ static void handle_merges (long int opcode)
|
||||||
}
|
}
|
||||||
for (srcreg=0; srcreg < sbitdst; srcreg++) {
|
for (srcreg=0; srcreg < sbitdst; srcreg++) {
|
||||||
for (dstreg=0; dstreg < dstend; dstreg++) {
|
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 & ~smsk) | (srcreg << table68k[opcode].spos);
|
||||||
code = (code & ~dmsk) | (dstreg << table68k[opcode].dpos);
|
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].suse != table68k[opcode].suse
|
||||||
|| table68k[code].duse != table68k[opcode].duse)
|
|| table68k[code].duse != table68k[opcode].duse)
|
||||||
{
|
{
|
||||||
mismatch++; continue;
|
readcpu_mismatch++; continue;
|
||||||
}
|
}
|
||||||
if (table68k[opcode].suse
|
if (table68k[opcode].suse
|
||||||
&& (table68k[opcode].spos != table68k[code].spos
|
&& (table68k[opcode].spos != table68k[code].spos
|
||||||
|| table68k[opcode].smode != table68k[code].smode
|
|| table68k[opcode].smode != table68k[code].smode
|
||||||
|| table68k[opcode].stype != table68k[code].stype))
|
|| table68k[opcode].stype != table68k[code].stype))
|
||||||
{
|
{
|
||||||
mismatch++; continue;
|
readcpu_mismatch++; continue;
|
||||||
}
|
}
|
||||||
if (table68k[opcode].duse
|
if (table68k[opcode].duse
|
||||||
&& (table68k[opcode].dpos != table68k[code].dpos
|
&& (table68k[opcode].dpos != table68k[code].dpos
|
||||||
|| table68k[opcode].dmode != table68k[code].dmode))
|
|| table68k[opcode].dmode != table68k[code].dmode))
|
||||||
{
|
{
|
||||||
mismatch++; continue;
|
readcpu_mismatch++; continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (code != opcode)
|
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;
|
long int opcode;
|
||||||
int nr = 0;
|
int nr = 0;
|
||||||
mismatch = 0;
|
readcpu_mismatch = 0;
|
||||||
for (opcode = 0; opcode < 65536; opcode++) {
|
for (opcode = 0; opcode < 65536; opcode++) {
|
||||||
if (table68k[opcode].handler != -1 || table68k[opcode].mnemo == i_ILLG)
|
if (table68k[opcode].handler != -1 || table68k[opcode].mnemo == i_ILLG)
|
||||||
continue;
|
continue;
|
||||||
|
@ -918,116 +909,26 @@ void do_merges (void)
|
||||||
nr_cpuop_funcs = nr;
|
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];
|
int i;
|
||||||
for (int i = 0; lookuptab[i].name[0]; i++) {
|
|
||||||
if (ins->mnemo == lookuptab[i].mnemo)
|
free(table68k);
|
||||||
return lookuptab[i].name;
|
table68k = (struct instr *)malloc (65536 * sizeof (struct instr));
|
||||||
|
for (i = 0; i < 65536; i++) {
|
||||||
|
table68k[i].mnemo = i_ILLG;
|
||||||
|
table68k[i].handler = -1;
|
||||||
}
|
}
|
||||||
abort();
|
for (i = 0; i < n_defs68k; i++) {
|
||||||
return NULL;
|
build_insn (i);
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
return buffer;
|
do_merges();
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *get_instruction_string (unsigned int opcode)
|
|
||||||
|
void exit_table68k (void)
|
||||||
{
|
{
|
||||||
static char out[100];
|
free(table68k);
|
||||||
struct instr *ins;
|
table68k = NULL;
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
#ifndef READCPU_H
|
#ifndef UAE_READCPU_H
|
||||||
#define READCPU_H
|
#define UAE_READCPU_H
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ENUMDECL {
|
typedef enum {
|
||||||
Dreg, Areg, Aind, Aipi, Apdi, Ad16, Ad8r,
|
Dreg, Areg, Aind, Aipi, Apdi, Ad16, Ad8r,
|
||||||
absw, absl, PC16, PC8r, imm, imm0, imm1, imm2, immi, am_unknown, am_illg
|
absw, absl, PC16, PC8r, imm, imm0, imm1, imm2, immi, am_unknown, am_illg
|
||||||
} ENUMNAME (amodes);
|
} amodes;
|
||||||
|
|
||||||
ENUMDECL {
|
typedef enum {
|
||||||
i_ILLG,
|
i_ILLG,
|
||||||
|
|
||||||
i_OR, i_AND, i_EOR, i_ORSR, i_ANDSR, i_EORSR,
|
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_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_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_CINVL, i_CINVP, i_CINVA, i_CPUSHL, i_CPUSHP, i_CPUSHA, i_MOVE16,
|
||||||
i_MMUOP,
|
i_MMUOP, i_EMULOP_RETURN, i_EMULOP, i_NATFEAT_ID, i_NATFEAT_CALL
|
||||||
i_EMULOP_RETURN, i_EMULOP
|
} instrmnem;
|
||||||
} ENUMNAME (instrmnem);
|
|
||||||
|
|
||||||
extern struct mnemolookup {
|
extern struct mnemolookup {
|
||||||
instrmnem mnemo;
|
instrmnem mnemo;
|
||||||
const char *name;
|
const char *name;
|
||||||
} lookuptab[];
|
} lookuptab[];
|
||||||
|
|
||||||
ENUMDECL {
|
typedef enum {
|
||||||
sz_byte, sz_word, sz_long
|
sz_byte, sz_word, sz_long
|
||||||
} ENUMNAME (wordsizes);
|
} wordsizes;
|
||||||
|
|
||||||
ENUMDECL {
|
typedef enum {
|
||||||
fa_set, fa_unset, fa_zero, fa_one, fa_dontcare, fa_unknown, fa_isjmp
|
fa_set, fa_unset, fa_zero, fa_one, fa_dontcare, fa_unknown, fa_isjmp,
|
||||||
} ENUMNAME (flagaffect);
|
fa_isbranch
|
||||||
|
} flagaffect;
|
||||||
|
|
||||||
ENUMDECL {
|
typedef enum {
|
||||||
fu_used, fu_unused, fu_maybecc, fu_unknown, fu_isjmp
|
fu_used, fu_unused, fu_maybecc, fu_unknown, fu_isjmp
|
||||||
} ENUMNAME (flaguse);
|
} flaguse;
|
||||||
|
|
||||||
ENUMDECL {
|
typedef enum {
|
||||||
fl_normal = 0,
|
fl_normal = 0,
|
||||||
fl_branch = 1,
|
fl_branch = 1,
|
||||||
fl_jump = 2,
|
fl_jump = 2,
|
||||||
fl_return = 3,
|
fl_return = 3,
|
||||||
fl_trap = 4,
|
fl_trap = 4,
|
||||||
fl_const_jump = 8,
|
fl_const_jump = 8,
|
||||||
|
/* Instructions that can trap don't mark the end of a block */
|
||||||
/* Instructions that can trap don't mark the end of a block */
|
fl_end_block = 3
|
||||||
fl_end_block = 3
|
} cflow_t;
|
||||||
} ENUMNAME (cflow_t);
|
|
||||||
|
|
||||||
ENUMDECL {
|
typedef enum {
|
||||||
bit0, bit1, bitc, bitC, bitf, biti, bitI, bitj, bitJ, bitk, bitK,
|
bit0, bit1, bitc, bitC, bitf, biti, bitI, bitj, bitJ, bitk, bitK,
|
||||||
bits, bitS, bitd, bitD, bitr, bitR, bitz, bitE, bitp, lastbit
|
bits, bitS, bitd, bitD, bitr, bitR, bitz, bitE, bitp, lastbit
|
||||||
} ENUMNAME (bitvals);
|
} bitvals;
|
||||||
|
|
||||||
struct instr_def {
|
struct instr_def {
|
||||||
unsigned int bits;
|
unsigned int bits;
|
||||||
|
@ -84,7 +83,7 @@ struct instr_def {
|
||||||
unsigned int flaguse:3;
|
unsigned int flaguse:3;
|
||||||
unsigned int flagset:3;
|
unsigned int flagset:3;
|
||||||
} flaginfo[5];
|
} flaginfo[5];
|
||||||
unsigned char cflow;
|
unsigned char cflow;
|
||||||
unsigned char sduse;
|
unsigned char sduse;
|
||||||
const char *opcstr;
|
const char *opcstr;
|
||||||
};
|
};
|
||||||
|
@ -103,28 +102,24 @@ extern struct instr {
|
||||||
unsigned int mnemo:8;
|
unsigned int mnemo:8;
|
||||||
unsigned int cc:4;
|
unsigned int cc:4;
|
||||||
unsigned int plev:2;
|
unsigned int plev:2;
|
||||||
unsigned int size:2;
|
wordsizes size:2;
|
||||||
unsigned int smode:5;
|
amodes smode:5;
|
||||||
unsigned int stype:3;
|
unsigned int stype:3;
|
||||||
unsigned int dmode:5;
|
amodes dmode:5;
|
||||||
unsigned int suse:1;
|
unsigned int suse:1;
|
||||||
unsigned int duse:1;
|
unsigned int duse:1;
|
||||||
unsigned int unused1:1;
|
unsigned int unused1:1;
|
||||||
unsigned int clev:3;
|
unsigned int clev:3;
|
||||||
unsigned int cflow:3;
|
unsigned int cflow:3;
|
||||||
unsigned int unused2:2;
|
unsigned int unused2:2;
|
||||||
} *table68k;
|
} *table68k;
|
||||||
|
|
||||||
extern void read_table68k (void);
|
extern void init_table68k(void);
|
||||||
extern void do_merges (void);
|
extern void exit_table68k(void);
|
||||||
extern int get_no_mismatches (void);
|
|
||||||
extern int nr_cpuop_funcs;
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* READCPU_H */
|
#endif
|
||||||
|
|
5
BasiliskII/src/uae_cpu/readcpua.cpp
Normal file
5
BasiliskII/src/uae_cpu/readcpua.cpp
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
/*
|
||||||
|
* readcpu.cpp must be compiled twice, once for the generator program
|
||||||
|
* and once for the actual executable
|
||||||
|
*/
|
||||||
|
#include "readcpu.cpp"
|
116
BasiliskII/src/uae_cpu/registers.h
Normal file
116
BasiliskII/src/uae_cpu/registers.h
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
/* 2001 MJ */
|
||||||
|
|
||||||
|
#ifndef REGISTERS_H
|
||||||
|
#define REGISTERS_H
|
||||||
|
|
||||||
|
#include "sysdeps.h"
|
||||||
|
#include "spcflags.h"
|
||||||
|
typedef char flagtype;
|
||||||
|
|
||||||
|
|
||||||
|
struct xttrx {
|
||||||
|
uae_u32 log_addr_base : 8;
|
||||||
|
uae_u32 log_addr_mask : 8;
|
||||||
|
uae_u32 enable : 1;
|
||||||
|
uae_u32 s_field : 2;
|
||||||
|
uae_u32 : 3;
|
||||||
|
uae_u32 usr1 : 1;
|
||||||
|
uae_u32 usr0 : 1;
|
||||||
|
uae_u32 : 1;
|
||||||
|
uae_u32 cmode : 2;
|
||||||
|
uae_u32 : 2;
|
||||||
|
uae_u32 write : 1;
|
||||||
|
uae_u32 : 2;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mmusr_t {
|
||||||
|
uae_u32 phys_addr : 20;
|
||||||
|
uae_u32 bus_err : 1;
|
||||||
|
uae_u32 global : 1;
|
||||||
|
uae_u32 usr1 : 1;
|
||||||
|
uae_u32 usr0 : 1;
|
||||||
|
uae_u32 super : 1;
|
||||||
|
uae_u32 cmode : 2;
|
||||||
|
uae_u32 modif : 1;
|
||||||
|
uae_u32 : 1;
|
||||||
|
uae_u32 write : 1;
|
||||||
|
uae_u32 ttrhit : 1;
|
||||||
|
uae_u32 resident : 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct log_addr4 {
|
||||||
|
uae_u32 rif : 7;
|
||||||
|
uae_u32 pif : 7;
|
||||||
|
uae_u32 paif : 6;
|
||||||
|
uae_u32 poff : 12;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct log_addr8 {
|
||||||
|
uae_u32 rif : 7;
|
||||||
|
uae_u32 pif : 7;
|
||||||
|
uae_u32 paif : 5;
|
||||||
|
uae_u32 poff : 13;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct regstruct
|
||||||
|
{
|
||||||
|
uae_u32 regs[16];
|
||||||
|
uaecptr usp,isp,msp;
|
||||||
|
uae_u16 sr;
|
||||||
|
flagtype t1;
|
||||||
|
flagtype t0;
|
||||||
|
flagtype s;
|
||||||
|
flagtype m;
|
||||||
|
flagtype x;
|
||||||
|
flagtype stopped;
|
||||||
|
int intmask;
|
||||||
|
|
||||||
|
uae_u32 pc;
|
||||||
|
uae_u32 fault_pc;
|
||||||
|
uae_u8 *pc_p;
|
||||||
|
uae_u8 *pc_oldp;
|
||||||
|
|
||||||
|
uae_u32 vbr,sfc,dfc;
|
||||||
|
|
||||||
|
volatile uae_u32 spcflags;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
uae_u32 kick_mask;
|
||||||
|
|
||||||
|
/* Fellow sources say this is 4 longwords. That's impossible. It needs
|
||||||
|
* to be at least a longword. The HRM has some cryptic comment about two
|
||||||
|
* instructions being on the same longword boundary.
|
||||||
|
* The way this is implemented now seems like a good compromise.
|
||||||
|
*/
|
||||||
|
uae_u32 prefetch;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* MMU reg*/
|
||||||
|
uae_u32 urp,srp;
|
||||||
|
uae_u32 tc;
|
||||||
|
|
||||||
|
int mmu_enabled; /* flagtype tce; */
|
||||||
|
int mmu_pagesize_8k; /* flagtype tcp; */
|
||||||
|
|
||||||
|
uae_u32 dtt0,dtt1,itt0,itt1;
|
||||||
|
uae_u32 mmusr;
|
||||||
|
|
||||||
|
uae_u32 mmu_fslw, mmu_fault_addr;
|
||||||
|
uae_u16 mmu_ssw;
|
||||||
|
uae_u32 wb3_data;
|
||||||
|
uae_u16 wb3_status;
|
||||||
|
|
||||||
|
/* Cache reg*/
|
||||||
|
uae_u32 cacr,caar;
|
||||||
|
} regs;
|
||||||
|
|
||||||
|
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
|
* UAE - The Un*x Amiga Emulator
|
||||||
*
|
*
|
||||||
* MC68000 emulation
|
* MC68000 emulation
|
||||||
*
|
*
|
||||||
* Copyright 1995 Bernd Schmidt
|
* 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
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef SPCFLAGS_H
|
#ifndef SPCFLAGS_H
|
||||||
#define SPCFLAGS_H
|
#define SPCFLAGS_H
|
||||||
|
|
||||||
typedef uae_u32 spcflags_t;
|
#if 0
|
||||||
|
#include "SDL_compat.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
SPCFLAG_STOP = 0x01,
|
SPCFLAG_STOP = 0x01,
|
||||||
SPCFLAG_INT = 0x02,
|
#if 0
|
||||||
SPCFLAG_BRK = 0x04,
|
SPCFLAG_INTERNAL_IRQ = 0x02,
|
||||||
SPCFLAG_TRACE = 0x08,
|
|
||||||
SPCFLAG_DOTRACE = 0x10,
|
|
||||||
SPCFLAG_DOINT = 0x20,
|
|
||||||
#if USE_JIT
|
|
||||||
SPCFLAG_JIT_END_COMPILE = 0x40,
|
|
||||||
SPCFLAG_JIT_EXEC_RETURN = 0x80,
|
|
||||||
#else
|
#else
|
||||||
SPCFLAG_JIT_END_COMPILE = 0,
|
SPCFLAG_INT = 0x02,
|
||||||
SPCFLAG_JIT_EXEC_RETURN = 0,
|
|
||||||
#endif
|
#endif
|
||||||
|
SPCFLAG_BRK = 0x04,
|
||||||
SPCFLAG_ALL = SPCFLAG_STOP
|
SPCFLAG_TRACE = 0x08,
|
||||||
| SPCFLAG_INT
|
SPCFLAG_DOTRACE = 0x10,
|
||||||
| SPCFLAG_BRK
|
SPCFLAG_DOINT = 0x20,
|
||||||
| SPCFLAG_TRACE
|
#ifdef USE_JIT
|
||||||
| SPCFLAG_DOTRACE
|
SPCFLAG_JIT_END_COMPILE = 0x40,
|
||||||
| SPCFLAG_DOINT
|
SPCFLAG_JIT_EXEC_RETURN = 0x80,
|
||||||
| SPCFLAG_JIT_END_COMPILE
|
#else
|
||||||
| SPCFLAG_JIT_EXEC_RETURN
|
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
|
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) \
|
#define SPCFLAGS_TEST(m) \
|
||||||
((regs.spcflags & (m)) != 0)
|
((regs.spcflags & (m)) != 0)
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Macro only used in m68k_reset() */
|
/* Macro only used in m68k_reset() */
|
||||||
#define SPCFLAGS_INIT(m) do { \
|
#define SPCFLAGS_INIT(m) do { \
|
||||||
regs.spcflags = (m); \
|
regs.spcflags = (m); \
|
||||||
} while (0)
|
} 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"
|
#include "main.h"
|
||||||
extern B2_mutex *spcflags_lock;
|
extern B2_mutex *spcflags_lock;
|
||||||
|
|
||||||
|
@ -99,9 +85,91 @@ extern B2_mutex *spcflags_lock;
|
||||||
#define SPCFLAGS_CLEAR(m) do { \
|
#define SPCFLAGS_CLEAR(m) do { \
|
||||||
B2_lock_mutex(spcflags_lock); \
|
B2_lock_mutex(spcflags_lock); \
|
||||||
regs.spcflags &= ~(m); \
|
regs.spcflags &= ~(m); \
|
||||||
B2_unlock_mutex(spcflags_lock); \
|
B2_unlock_mutex(spcflags_lock); \
|
||||||
} while (0)
|
} 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
|
||||||
|
|
||||||
#endif /* SPCFLAGS_H */
|
#endif /* SPCFLAGS_H */
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
% J: immediate 0..15
|
% J: immediate 0..15
|
||||||
% k: immediate 0..7
|
% k: immediate 0..7
|
||||||
% K: immediate 0..63
|
% 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 mode
|
||||||
% S: source reg
|
% S: source reg
|
||||||
% d: dest mode
|
% d: dest mode
|
||||||
|
@ -28,14 +28,15 @@
|
||||||
% ArP: --> (Ar)+
|
% ArP: --> (Ar)+
|
||||||
% L: --> (xxx.L)
|
% L: --> (xxx.L)
|
||||||
%
|
%
|
||||||
% Fields on a line:
|
% Fields on a line:
|
||||||
% 16 chars bitpattern :
|
% 16 chars bitpattern :
|
||||||
% CPU level / privilege level :
|
% CPU level / privildge level :
|
||||||
% CPU level 0: 68000
|
% CPU level 0: 68000
|
||||||
% 1: 68010
|
% 1: 68010
|
||||||
% 2: 68020
|
% 2: 68020
|
||||||
% 3: 68020/68881
|
% 3: 68020/68881
|
||||||
% 4: 68040
|
% 4: 68040
|
||||||
|
% 5: 68060
|
||||||
% privilege level 0: not privileged
|
% privilege level 0: not privileged
|
||||||
% 1: unprivileged only on 68000 (check regs.s)
|
% 1: unprivileged only on 68000 (check regs.s)
|
||||||
% 2: privileged (check regs.s)
|
% 2: privileged (check regs.s)
|
||||||
|
@ -46,8 +47,10 @@
|
||||||
% 0 means flag reset
|
% 0 means flag reset
|
||||||
% 1 means flag set
|
% 1 means flag set
|
||||||
% ? means programmer was too lazy to check or instruction may trap
|
% ? 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
|
% x means flag is unknown and well-behaved programs shouldn't check it
|
||||||
|
% everything else means flag set/used
|
||||||
%
|
%
|
||||||
% Control flow
|
% Control flow
|
||||||
% two letters, combination of
|
% two letters, combination of
|
||||||
|
@ -108,7 +111,7 @@
|
||||||
0011 DDDd ddss sSSS:00:-----:-----:--:12: MOVEA.W s,d[Areg]
|
0011 DDDd ddss sSSS:00:-----:-----:--:12: MOVEA.W s,d[Areg]
|
||||||
0011 DDDd ddss sSSS:00:-NZ00:-----:--:12: MOVE.W s,d[!Areg]
|
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 0000 11dd dDDD:01:-----:XNZVC:T-:10: MVSR2.W d[!Areg]
|
||||||
0100 0010 zzdd dDDD:00:-0100:-----:--:20: CLR.z d[!Areg]
|
0100 0010 zzdd dDDD:00:-0100:-----:--:20: CLR.z d[!Areg]
|
||||||
0100 0010 11dd dDDD:10:-----:XNZVC:--:10: MVSR2.B d[!Areg]
|
0100 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 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 00dd dDDD:00:X?Z?C:X-Z--:--:30: NBCD.B d[!Areg]
|
||||||
0100 1000 0100 1kkk:20:-----:-----:T-:10: BKPT #k
|
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 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 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 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 zzss sSSS:00:-NZ00:-----:--:10: TST.z s
|
||||||
0100 1010 11dd dDDD:00:-NZ00:-----:--:30: TAS.B d[!Areg]
|
0100 1010 11dd dDDD:00:-NZ00:-----:--:30: TAS.B d[!Areg]
|
||||||
0100 1010 1111 1100:00:-----:-----:T-:00: ILLEGAL
|
0100 1010 1111 1100:00:-----:-----:T-:00: ILLEGAL
|
||||||
|
@ -148,21 +151,24 @@
|
||||||
0100 1110 0111 0111:00:XNZVC:-----:-R:00: RTR
|
0100 1110 0111 0111:00:XNZVC:-----:-R:00: RTR
|
||||||
0100 1110 0111 1010:12:-----:-----:T-:10: MOVEC2 #1
|
0100 1110 0111 1010:12:-----:-----:T-:10: MOVEC2 #1
|
||||||
0100 1110 0111 1011:12:-----:-----:T-:10: MOVE2C #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 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 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
|
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]
|
% This variant of ADDQ is word and long sized only
|
||||||
0101 jjj0 10dd dDDD:00:-----:-----:--:13: ADDA.L #j,d[Areg]
|
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 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 jjj1 zzdd dDDD:00:XNZVC:-----:--:13: SUB.z #j,d[!Areg]
|
||||||
|
|
||||||
0101 cccc 1100 1rrr:00:-----:-????:-B:31: DBcc.W Dr,#1
|
0101 cccc 1100 1rrr:00:-----:-++++:-B:31: DBcc.W Dr,#1
|
||||||
0101 cccc 11dd dDDD:00:-----:-????:--:20: Scc.B d[!Areg]
|
0101 cccc 11dd dDDD:00:-----:-++++:--:20: Scc.B d[!Areg]
|
||||||
0101 cccc 1111 1010:20:-----:-????:T-:10: TRAPcc #1
|
0101 cccc 1111 1010:20:-----:-????:T-:10: TRAPcc #1
|
||||||
0101 cccc 1111 1011:20:-----:-????:T-:10: TRAPcc #2
|
0101 cccc 1111 1011:20:-----:-????:T-:10: TRAPcc #2
|
||||||
0101 cccc 1111 1100:20:-----:-????:T-:00: TRAPcc
|
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
|
% 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
|
% instruction exceptions when compiling a 68000 only emulation, which isn't
|
||||||
% what we want either.
|
% what we want either.
|
||||||
0110 0001 0000 0000:00:-----:-----:-B:40: BSR.W #1
|
0110 0001 0000 0000:00://///://///:-B:40: BSR.W #1
|
||||||
0110 0001 IIII IIII:00:-----:-----:-B:40: BSR.B #i
|
0110 0001 IIII IIII:00://///://///:-B:40: BSR.B #i
|
||||||
0110 0001 1111 1111:00:-----:-----:-B:40: BSR.L #2
|
0110 0001 1111 1111:00://///://///:-B:40: BSR.L #2
|
||||||
0110 CCCC 0000 0000:00:-----:-????:-B:40: Bcc.W #1
|
0110 CCCC 0000 0000:00:-----:-++++:-B:40: Bcc.W #1
|
||||||
0110 CCCC IIII IIII:00:-----:-????:-B:40: Bcc.B #i
|
0110 CCCC IIII IIII:00:-----:-++++:-B:40: Bcc.B #i
|
||||||
0110 CCCC 1111 1111:00:-----:-????:-B:40: Bcc.L #2
|
0110 CCCC 1111 1111:00:-----:-++++:-B:40: Bcc.L #2
|
||||||
|
|
||||||
0111 rrr0 iiii iiii:00:-NZ00:-----:--:12: MOVE.L #i,Dr
|
0111 rrr0 iiii iiii:00:-NZ00:-----:--:12: MOVE.L #i,Dr
|
||||||
|
|
||||||
1000 rrr0 zzss sSSS:00:-NZ00:-----:--:13: OR.z s[!Areg],Dr
|
1000 rrr0 zzss sSSS:00:-NZ00:-----:--:13: OR.z s[!Areg],Dr
|
||||||
1000 rrr0 11ss sSSS:00:-NZV0:-----:T-:13: DIVU.W 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:X?Z?C: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[Areg-Apdi],Arp
|
||||||
1000 rrr1 zzdd dDDD:00:-NZ00:-----:--:13: OR.z Dr,d[!Areg,Dreg]
|
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[Dreg],Dr
|
||||||
1000 rrr1 01dd dDDD:20:-----:-----:--:12: PACK d[Areg-Apdi],Arp
|
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[Dreg],Dr
|
||||||
1000 rrr1 10dd dDDD:20:-----:-----:--:12: UNPK d[Areg-Apdi],Arp
|
1000 rrr1 10dd dDDD:20:-----:-----:--:12: UNPK d[Areg-Apdi],Arp
|
||||||
1000 rrr1 11ss sSSS:00:-NZV0:-----:T-:13: DIVS.W s[!Areg],Dr
|
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 zzss sSSS:00:XNZVC:-----:--:13: SUB.z s,Dr
|
||||||
1001 rrr0 11ss sSSS:00:-----:-----:--:13: SUBA.W s,Ar
|
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[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[Areg-Apdi],Arp
|
||||||
1001 rrr1 zzdd dDDD:00:XNZVC:-----:--:13: SUB.z Dr,d[!Areg,Dreg]
|
1001 rrr1 zzdd dDDD:00:XNZVC:-----:--:13: SUB.z Dr,d[!Areg,Dreg]
|
||||||
1001 rrr1 11ss sSSS:00:-----:-----:--:13: SUBA.L s,Ar
|
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 zzss sSSS:00:-NZ00:-----:--:13: AND.z s[!Areg],Dr
|
||||||
1100 rrr0 11ss sSSS:00:-NZ00:-----:--:13: MULU.W 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:X?Z?C: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[Areg-Apdi],Arp
|
||||||
1100 rrr1 zzdd dDDD:00:-NZ00:-----:--:13: AND.z Dr,d[!Areg,Dreg]
|
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 Dr,d[Dreg]
|
||||||
1100 rrr1 01dd dDDD:00:-----:-----:--:33: EXG.L Ar,d[Areg]
|
1100 rrr1 01dd dDDD:00:-----:-----:--:33: EXG.L Ar,d[Areg]
|
||||||
1100 rrr1 10dd dDDD:00:-----:-----:--:33: EXG.L Dr,d[Areg]
|
1100 rrr1 10dd dDDD:00:-----:-----:--:33: EXG.L Dr,d[Areg]
|
||||||
1100 rrr1 11ss sSSS:00:-NZ00:-----:--:13: MULS.W s[!Areg],Dr
|
1100 rrr1 11ss sSSS:00:-NZ00:-----:--:13: MULS.W s[!Areg],Dr
|
||||||
|
|
||||||
1101 rrr0 zzss sSSS:00:XNZVC:-----:--:13: ADD.z s,Dr
|
1101 rrr0 zzss sSSS:00:XNZVC:-----:--:13: ADD.z s,Dr
|
||||||
1101 rrr0 11ss sSSS:00:-----:-----:--:13: ADDA.W s,Ar
|
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[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[Areg-Apdi],Arp
|
||||||
1101 rrr1 zzdd dDDD:00:XNZVC:-----:--:13: ADD.z Dr,d[!Areg,Dreg]
|
1101 rrr1 zzdd dDDD:00:XNZVC:-----:--:13: ADD.z Dr,d[!Areg,Dreg]
|
||||||
1101 rrr1 11ss sSSS:00:-----:-----:--:13: ADDA.L s,Ar
|
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 zz00 1RRR:00:XNZ0C:-----:--:13: LSf.z #j,DR
|
||||||
1110 jjjf zz01 0RRR:00:XNZ0C:X----:--:13: ROXf.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 jjjf zz01 1RRR:00:-NZ0C:-----:--:13: ROf.z #j,DR
|
||||||
1110 rrrf zz10 0RRR:00:XNZVC:-----:--:13: ASf.z Dr,DR
|
1110 rrrf zz10 0RRR:00:XNZVC:X----:--:13: ASf.z Dr,DR
|
||||||
1110 rrrf zz10 1RRR:00:XNZ0C:-----:--:13: LSf.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 0RRR:00:XNZ0C:X----:--:13: ROXf.z Dr,DR
|
||||||
1110 rrrf zz11 1RRR:00:-NZ0C:-----:--:13: ROf.z Dr,DR
|
1110 rrrf zz11 1RRR:00:-NZ0C:-----:--:13: ROf.z Dr,DR
|
||||||
1110 000f 11dd dDDD:00:XNZVC:-----:--:13: ASfW.W d[!Dreg,Areg]
|
1110 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]
|
1111 0011 01ss sSSS:32:-----:-----:--:10: FRESTORE s[!Dreg,Areg,Apdi,Immd]
|
||||||
|
|
||||||
% 68040 instructions
|
% 68040 instructions
|
||||||
1111 0101 iiii iSSS:40:-----:-----:T-:11: MMUOP #i,s
|
|
||||||
1111 0100 pp00 1rrr:42:-----:-----:T-:02: CINVL #p,Ar
|
1111 0100 pp00 1rrr:42:-----:-----:T-:02: CINVL #p,Ar
|
||||||
1111 0100 pp01 0rrr:42:-----:-----:T-:02: CINVP #p,Ar
|
1111 0100 pp01 0rrr:42:-----:-----:T-:02: CINVP #p,Ar
|
||||||
1111 0100 pp01 1rrr:42:-----:-----:T-:00: CINVA #p
|
1111 0100 pp01 1rrr:42:-----:-----:T-:00: CINVA #p
|
||||||
|
@ -264,11 +269,19 @@
|
||||||
1111 0100 pp11 1rrr:42:-----:-----:T-:00: CPUSHA #p
|
1111 0100 pp11 1rrr:42:-----:-----:T-:00: CPUSHA #p
|
||||||
% destination register number is encoded in the following word
|
% destination register number is encoded in the following word
|
||||||
1111 0110 0010 0rrr:40:-----:-----:--:12: MOVE16 ArP,AxP
|
1111 0110 0010 0rrr:40:-----:-----:--:12: MOVE16 ArP,AxP
|
||||||
1111 0110 00ss sSSS:40:-----:-----:--:12: MOVE16 s[Dreg-Aipi],L
|
1111 0110 00ss sSSS:40:-----:-----:--:12: MOVE16 s[Dreg-Aipi],Al
|
||||||
1111 0110 00dd dDDD:40:-----:-----:--:12: MOVE16 L,d[Areg-Aipi]
|
1111 0110 00dd dDDD:40:-----:-----:--:12: MOVE16 Al,d[Areg-Aipi]
|
||||||
1111 0110 00ss sSSS:40:-----:-----:--:12: MOVE16 s[Aind],L
|
1111 0110 00ss sSSS:40:-----:-----:--:12: MOVE16 s[Aind],Al
|
||||||
1111 0110 00dd dDDD:40:-----:-----:--:12: MOVE16 L,d[Aipi-Aind]
|
1111 0110 00dd dDDD:40:-----:-----:--:12: MOVE16 Al,d[Aipi-Aind]
|
||||||
|
|
||||||
% EmulOp instructions
|
% MMU disabled
|
||||||
0111 0001 0000 0000:00:-----:-----:-R:00: EMULOP_RETURN
|
% 1111 0101 iiii iSSS:42:?????:?????:T-:11: MMUOP #i,s
|
||||||
0111 0001 EEEE EEEE:00:-----:-----:-J:10: EMULOP #E
|
|
||||||
|
% 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
Block a user