fix for Linux and Windows

This commit is contained in:
kanjitalk755 2021-05-06 12:16:03 +09:00
parent e42b8f6076
commit 5862662bc9
44 changed files with 45318 additions and 8 deletions

View File

@ -574,7 +574,7 @@
path = ../SDL;
sourceTree = "<group>";
};
7539E0A51F23B25A006B2DF2 /* uae_cpu */ = {
7539E0A51F23B25A006B2DF2 /* uae_cpu_2021 */ = {
isa = PBXGroup;
children = (
7539E0A61F23B25A006B2DF2 /* basilisk_glue.cpp */,
@ -594,8 +594,8 @@
7539E0D01F23B25A006B2DF2 /* spcflags.h */,
7539E0D11F23B25A006B2DF2 /* table68k */,
);
name = uae_cpu;
path = ../uae_cpu;
name = uae_cpu_2021;
path = ../uae_cpu_2021;
sourceTree = "<group>";
};
7539E0A81F23B25A006B2DF2 /* compiler */ = {
@ -663,7 +663,7 @@
7539E0A21F23B25A006B2DF2 /* slot_rom.cpp */,
7539E0A31F23B25A006B2DF2 /* sony.cpp */,
7539E0A41F23B25A006B2DF2 /* timer.cpp */,
7539E0A51F23B25A006B2DF2 /* uae_cpu */,
7539E0A51F23B25A006B2DF2 /* uae_cpu_2021 */,
7539E1E91F23B329006B2DF2 /* Unix */,
7539E1221F23B25A006B2DF2 /* user_strings.cpp */,
7539E1231F23B25A006B2DF2 /* video.cpp */,
@ -1103,7 +1103,7 @@
/Library/Frameworks/SDL2.framework/Headers,
../MacOSX,
../include,
../uae_cpu,
../uae_cpu_2021,
../Unix,
../slirp,
);
@ -1176,7 +1176,7 @@
/Library/Frameworks/SDL2.framework/Headers,
../MacOSX,
../include,
../uae_cpu,
../uae_cpu_2021,
../Unix,
../slirp,
);

View File

@ -1,7 +1,7 @@
SRC = $(PROJECT_DIR)/../uae_cpu
SRC = $(PROJECT_DIR)/../uae_cpu_2021
DST = $(BUILT_PRODUCTS_DIR)/gencpu_output
VPATH = $(SRC) $(SRC)/compiler
CFLAGS = -DUSE_XCODE=1 -DUSE_JIT_FPU -I. -I../uae_cpu -I../UNIX
CFLAGS = -DUSE_XCODE=1 -DUSE_JIT_FPU -I. -I../uae_cpu_2021 -I../UNIX
CXXFLAGS = -stdlib=libc++ $(CFLAGS)
all: $(DST)/gencpu $(DST)/gencomp

View File

@ -0,0 +1,266 @@
/*
* basilisk_glue.cpp - Glue UAE CPU to Basilisk II CPU engine interface
*
* Basilisk II (C) 1997-2008 Christian Bauer
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This 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 "sysdeps.h"
#include "cpu_emulation.h"
#include "main.h"
#include "prefs.h"
#include "emul_op.h"
#include "rom_patches.h"
#include "timer.h"
#include "m68k.h"
#include "memory.h"
#include "readcpu.h"
#include "newcpu.h"
#include "compiler/compemu.h"
// RAM and ROM pointers
uint32 RAMBaseMac = 0; // RAM base (Mac address space) gb-- initializer is important
uint8 *RAMBaseHost; // RAM base (host address space)
uint32 RAMSize; // Size of RAM
uint32 ROMBaseMac; // ROM base (Mac address space)
uint8 *ROMBaseHost; // ROM base (host address space)
uint32 ROMSize; // Size of ROM
#if !REAL_ADDRESSING
// Mac frame buffer
uint8 *MacFrameBaseHost; // Frame buffer base (host address space)
uint32 MacFrameSize; // Size of frame buffer
int MacFrameLayout; // Frame buffer layout
#endif
#if DIRECT_ADDRESSING
uintptr MEMBaseDiff; // Global offset between a Mac address and its Host equivalent
#endif
#if USE_JIT
bool UseJIT = false;
#endif
// From newcpu.cpp
extern bool quit_program;
/*
* Initialize 680x0 emulation, CheckROM() must have been called first
*/
bool Init680x0(void)
{
#if REAL_ADDRESSING
// Mac address space = host address space
RAMBaseMac = (uintptr)RAMBaseHost;
ROMBaseMac = (uintptr)ROMBaseHost;
#elif DIRECT_ADDRESSING
// Mac address space = host address space minus constant offset (MEMBaseDiff)
// NOTE: MEMBaseDiff is set up in main_unix.cpp/main()
RAMBaseMac = 0;
ROMBaseMac = Host2MacAddr(ROMBaseHost);
#else
// Initialize UAE memory banks
RAMBaseMac = 0;
switch (ROMVersion) {
case ROM_VERSION_64K:
case ROM_VERSION_PLUS:
case ROM_VERSION_CLASSIC:
ROMBaseMac = 0x00400000;
break;
case ROM_VERSION_II:
ROMBaseMac = 0x00a00000;
break;
case ROM_VERSION_32:
ROMBaseMac = 0x40800000;
break;
default:
return false;
}
memory_init();
#endif
init_m68k();
#if USE_JIT
UseJIT = compiler_use_jit();
if (UseJIT)
compiler_init();
#endif
return true;
}
/*
* Deinitialize 680x0 emulation
*/
void Exit680x0(void)
{
#if USE_JIT
if (UseJIT)
compiler_exit();
#endif
exit_m68k();
}
/*
* Initialize memory mapping of frame buffer (called upon video mode change)
*/
void InitFrameBufferMapping(void)
{
#if !REAL_ADDRESSING && !DIRECT_ADDRESSING
memory_init();
#endif
}
/*
* Reset and start 680x0 emulation (doesn't return)
*/
void Start680x0(void)
{
m68k_reset();
#if USE_JIT
if (UseJIT)
m68k_compile_execute();
else
#endif
m68k_execute();
}
/*
* Trigger interrupt
*/
void TriggerInterrupt(void)
{
idle_resume();
SPCFLAGS_SET( SPCFLAG_INT );
}
void TriggerNMI(void)
{
//!! not implemented yet
}
/*
* Get 68k interrupt level
*/
int intlev(void)
{
return InterruptFlags ? 1 : 0;
}
/*
* Execute MacOS 68k trap
* r->a[7] and r->sr are unused!
*/
void Execute68kTrap(uint16 trap, struct M68kRegisters *r)
{
int i;
// Save old PC
uaecptr oldpc = m68k_getpc();
// Set registers
for (i=0; i<8; i++)
m68k_dreg(regs, i) = r->d[i];
for (i=0; i<7; i++)
m68k_areg(regs, i) = r->a[i];
// Push trap and EXEC_RETURN on stack
m68k_areg(regs, 7) -= 2;
put_word(m68k_areg(regs, 7), M68K_EXEC_RETURN);
m68k_areg(regs, 7) -= 2;
put_word(m68k_areg(regs, 7), trap);
// Execute trap
m68k_setpc(m68k_areg(regs, 7));
fill_prefetch_0();
quit_program = false;
m68k_execute();
// Clean up stack
m68k_areg(regs, 7) += 4;
// Restore old PC
m68k_setpc(oldpc);
fill_prefetch_0();
// Get registers
for (i=0; i<8; i++)
r->d[i] = m68k_dreg(regs, i);
for (i=0; i<7; i++)
r->a[i] = m68k_areg(regs, i);
quit_program = false;
}
/*
* Execute 68k subroutine
* The executed routine must reside in UAE memory!
* r->a[7] and r->sr are unused!
*/
void Execute68k(uint32 addr, struct M68kRegisters *r)
{
int i;
// Save old PC
uaecptr oldpc = m68k_getpc();
// Set registers
for (i=0; i<8; i++)
m68k_dreg(regs, i) = r->d[i];
for (i=0; i<7; i++)
m68k_areg(regs, i) = r->a[i];
// Push EXEC_RETURN and faked return address (points to EXEC_RETURN) on stack
m68k_areg(regs, 7) -= 2;
put_word(m68k_areg(regs, 7), M68K_EXEC_RETURN);
m68k_areg(regs, 7) -= 4;
put_long(m68k_areg(regs, 7), m68k_areg(regs, 7) + 4);
// Execute routine
m68k_setpc(addr);
fill_prefetch_0();
quit_program = false;
m68k_execute();
// Clean up stack
m68k_areg(regs, 7) += 2;
// Restore old PC
m68k_setpc(oldpc);
fill_prefetch_0();
// Get registers
for (i=0; i<8; i++)
r->d[i] = m68k_dreg(regs, i);
for (i=0; i<7; i++)
r->a[i] = m68k_areg(regs, i);
quit_program = false;
}

View File

@ -0,0 +1,276 @@
/*
* UAE - The Un*x Amiga Emulator
*
* Read 68000 CPU specs from file "table68k" and build table68k.c
*
* Copyright 1995,1996 Bernd Schmidt
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <assert.h>
#include <ctype.h>
#include <stdio.h>
#include "sysdeps.h"
#include "readcpu.h"
static FILE *tablef;
static int nextch = 0;
static void getnextch(void)
{
do {
nextch = fgetc(tablef);
if (nextch == '%') {
do {
nextch = fgetc(tablef);
} while (nextch != EOF && nextch != '\n');
}
} while (nextch != EOF && isspace(nextch));
}
static int nextchtohex(void)
{
switch (isupper (nextch) ? tolower (nextch) : nextch) {
case '0': return 0;
case '1': return 1;
case '2': return 2;
case '3': return 3;
case '4': return 4;
case '5': return 5;
case '6': return 6;
case '7': return 7;
case '8': return 8;
case '9': return 9;
case 'a': return 10;
case 'b': return 11;
case 'c': return 12;
case 'd': return 13;
case 'e': return 14;
case 'f': return 15;
default: abort();
}
}
int main(int argc, char **argv)
{
int no_insns = 0;
printf ("#include \"sysdeps.h\"\n");
printf ("#include \"readcpu.h\"\n");
printf ("struct instr_def defs68k[] = {\n");
#ifdef WIN32
tablef = fopen(argc > 1 ? argv[1] : "table68k","r");
if (tablef == NULL) {
fprintf(stderr, "table68k not found\n");
exit(1);
}
#else
tablef = stdin;
#endif
getnextch();
while (nextch != EOF) {
int cpulevel, plevel, sduse;
int i;
char patbits[16];
char opcstr[256];
int bitpos[16];
int flagset[5], flaguse[5];
char cflow;
unsigned int bitmask,bitpattern;
int n_variable;
n_variable = 0;
bitmask = bitpattern = 0;
memset (bitpos, 0, sizeof(bitpos));
for(i=0; i<16; i++) {
int currbit;
bitmask <<= 1;
bitpattern <<= 1;
switch (nextch) {
case '0': currbit = bit0; bitmask |= 1; break;
case '1': currbit = bit1; bitmask |= 1; bitpattern |= 1; break;
case 'c': currbit = bitc; break;
case 'C': currbit = bitC; break;
case 'f': currbit = bitf; break;
case 'i': currbit = biti; break;
case 'I': currbit = bitI; break;
case 'j': currbit = bitj; break;
case 'J': currbit = bitJ; break;
case 'k': currbit = bitk; break;
case 'K': currbit = bitK; break;
case 's': currbit = bits; break;
case 'S': currbit = bitS; break;
case 'd': currbit = bitd; break;
case 'D': currbit = bitD; break;
case 'r': currbit = bitr; break;
case 'R': currbit = bitR; break;
case 'z': currbit = bitz; break;
case 'E': currbit = bitE; break;
case 'p': currbit = bitp; break;
default: abort();
}
if (!(bitmask & 1)) {
bitpos[n_variable] = currbit;
n_variable++;
}
if (nextch == '0' || nextch == '1')
bitmask |= 1;
if (nextch == '1')
bitpattern |= 1;
patbits[i] = nextch;
getnextch();
}
while (isspace(nextch) || nextch == ':') /* Get CPU and privilege level */
getnextch();
switch (nextch) {
case '0': cpulevel = 0; break;
case '1': cpulevel = 1; break;
case '2': cpulevel = 2; break;
case '3': cpulevel = 3; break;
case '4': cpulevel = 4; break;
case '5': cpulevel = 5; break;
default: abort();
}
getnextch();
switch (nextch) {
case '0': plevel = 0; break;
case '1': plevel = 1; break;
case '2': plevel = 2; break;
case '3': plevel = 3; break;
default: abort();
}
getnextch();
while (isspace(nextch)) /* Get flag set information */
getnextch();
if (nextch != ':')
abort();
for(i = 0; i < 5; i++) {
getnextch();
switch(nextch){
case '-': flagset[i] = fa_unset; break;
case '0': flagset[i] = fa_zero; break;
case '1': flagset[i] = fa_one; break;
case 'x': flagset[i] = fa_dontcare; break;
case '?': flagset[i] = fa_unknown; break;
default: flagset[i] = fa_set; break;
}
}
getnextch();
while (isspace(nextch))
getnextch();
if (nextch != ':') /* Get flag used information */
abort();
for(i = 0; i < 5; i++) {
getnextch();
switch(nextch){
case '-': flaguse[i] = fu_unused; break;
case '?': flaguse[i] = fu_unknown; break;
default: flaguse[i] = fu_used; break;
}
}
getnextch();
while (isspace(nextch))
getnextch();
if (nextch != ':') /* Get control flow information */
abort();
cflow = 0;
for(i = 0; i < 2; i++) {
getnextch();
switch(nextch){
case '-': break;
case 'R': cflow |= fl_return; break;
case 'B': cflow |= fl_branch; break;
case 'J': cflow |= fl_jump; break;
case 'T': cflow |= fl_trap; break;
default: abort();
}
}
getnextch();
while (isspace(nextch))
getnextch();
if (nextch != ':') /* Get source/dest usage information */
abort();
getnextch();
sduse = nextchtohex() << 4;
getnextch();
sduse |= nextchtohex();
getnextch();
while (isspace(nextch))
getnextch();
if (nextch != ':')
abort();
fgets(opcstr, 250, tablef);
getnextch();
{
int j;
/* Remove superfluous spaces from the string */
char *opstrp = opcstr, *osendp;
int slen = 0;
while (isspace(*opstrp))
opstrp++;
osendp = opstrp;
while (*osendp) {
if (!isspace (*osendp))
slen = osendp - opstrp + 1;
osendp++;
}
opstrp[slen] = 0;
if (no_insns > 0)
printf(",\n");
no_insns++;
printf("{ %d, %d, {", bitpattern, n_variable);
for (j = 0; j < 16; j++) {
printf("%d", bitpos[j]);
if (j < 15)
printf(",");
}
printf ("}, %d, %d, %d, { ", bitmask, cpulevel, plevel);
for(i = 0; i < 5; i++) {
printf("{ %d, %d }%c ", flaguse[i], flagset[i], i == 4 ? ' ' : ',');
}
printf("}, %d, %d, \"%s\"}", cflow, sduse, opstrp);
}
}
printf("};\nint n_defs68k = %d;\n", no_insns);
fflush(stdout);
return 0;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,609 @@
/*
* compiler/compemu.h - Public interface and definitions
*
* Original 68040 JIT compiler for UAE, copyright 2000-2002 Bernd Meyer
*
* Adaptation for Basilisk II and improvements, copyright 2000-2005
* Gwenole Beauchesne
*
* Basilisk II (C) 1997-2008 Christian Bauer
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This 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 COMPEMU_H
#define COMPEMU_H
#include "newcpu.h"
#if USE_JIT
#if defined __i386__ || defined __x86_64__
#include "flags_x86.h"
#else
#error "Unsupported JIT compiler for this architecture"
#endif
#if JIT_DEBUG
/* dump some information (m68k block, x86 block addresses) about the compiler state */
extern void compiler_dumpstate(void);
#endif
/* Now that we do block chaining, and also have linked lists on each tag,
TAGMASK can be much smaller and still do its job. Saves several megs
of memory! */
#define TAGMASK 0x0000ffff
#define TAGSIZE (TAGMASK+1)
#define MAXRUN 1024
#define cacheline(x) (((uintptr)x)&TAGMASK)
extern uae_u8* start_pc_p;
extern uae_u32 start_pc;
struct blockinfo_t;
struct cpu_history {
uae_u16 * location;
};
union cacheline {
cpuop_func * handler;
blockinfo_t * bi;
};
/* Use new spill/reload strategy when calling external functions */
#define USE_OPTIMIZED_CALLS 0
#if USE_OPTIMIZED_CALLS
#error implementation in progress
#endif
/* (gb) When on, this option can save save up to 30% compilation time
* when many lazy flushes occur (e.g. apps in MacOS 8.x).
*/
#define USE_SEPARATE_BIA 1
/* Use chain of checksum_info_t to compute the block checksum */
#define USE_CHECKSUM_INFO 1
/* Use code inlining, aka follow-up of constant jumps */
#define USE_INLINING 1
/* Inlining requires the chained checksuming information */
#if USE_INLINING
#undef USE_CHECKSUM_INFO
#define USE_CHECKSUM_INFO 1
#endif
/* Does flush_icache_range() only check for blocks falling in the requested range? */
#define LAZY_FLUSH_ICACHE_RANGE 0
#define USE_F_ALIAS 1
#define USE_OFFSET 1
#define COMP_DEBUG 1
#if COMP_DEBUG
#define Dif(x) if (x)
#else
#define Dif(x) if (0)
#endif
#define SCALE 2
#define BYTES_PER_INST 10240 /* paranoid ;-) */
#define LONGEST_68K_INST 16 /* The number of bytes the longest possible
68k instruction takes */
#define MAX_CHECKSUM_LEN 2048 /* The maximum size we calculate checksums
for. Anything larger will be flushed
unconditionally even with SOFT_FLUSH */
#define MAX_HOLD_BI 3 /* One for the current block, and up to two
for jump targets */
#define INDIVIDUAL_INST 0
#if 1
// gb-- my format from readcpu.cpp is not the same
#define FLAG_X 0x0010
#define FLAG_N 0x0008
#define FLAG_Z 0x0004
#define FLAG_V 0x0002
#define FLAG_C 0x0001
#else
#define FLAG_C 0x0010
#define FLAG_V 0x0008
#define FLAG_Z 0x0004
#define FLAG_N 0x0002
#define FLAG_X 0x0001
#endif
#define FLAG_CZNV (FLAG_C | FLAG_Z | FLAG_N | FLAG_V)
#define FLAG_ZNV (FLAG_Z | FLAG_N | FLAG_V)
#define KILLTHERAT 1 /* Set to 1 to avoid some partial_rat_stalls */
#if defined(__x86_64__)
#define N_REGS 16 /* really only 15, but they are numbered 0-3,5-15 */
#else
#define N_REGS 8 /* really only 7, but they are numbered 0,1,2,3,5,6,7 */
#endif
#define N_FREGS 6 /* That leaves us two positions on the stack to play with */
/* Functions exposed to newcpu, or to what was moved from newcpu.c to
* compemu_support.c */
extern void compiler_init(void);
extern void compiler_exit(void);
extern bool compiler_use_jit(void);
extern void init_comp(void);
extern void flush(int save_regs);
extern void small_flush(int save_regs);
extern void set_target(uae_u8* t);
extern uae_u8* get_target(void);
extern void freescratch(void);
extern void build_comp(void);
extern void set_cache_state(int enabled);
extern int get_cache_state(void);
extern uae_u32 get_jitted_size(void);
extern void (*flush_icache)(int n);
extern void alloc_cache(void);
extern int check_for_cache_miss(void);
/* JIT FPU compilation */
extern void comp_fpp_opp (uae_u32 opcode, uae_u16 extra);
extern void comp_fbcc_opp (uae_u32 opcode);
extern void comp_fscc_opp (uae_u32 opcode, uae_u16 extra);
extern uae_u32 needed_flags;
extern cacheline cache_tags[];
extern uae_u8* comp_pc_p;
extern void* pushall_call_handler;
#define VREGS 32
#define VFREGS 16
#define INMEM 1
#define CLEAN 2
#define DIRTY 3
#define UNDEF 4
#define ISCONST 5
typedef struct {
uae_u32* mem;
uae_u32 val;
uae_u8 is_swapped;
uae_u8 status;
uae_s8 realreg; /* gb-- realreg can hold -1 */
uae_u8 realind; /* The index in the holds[] array */
uae_u8 needflush;
uae_u8 validsize;
uae_u8 dirtysize;
uae_u8 dummy;
} reg_status;
typedef struct {
uae_u32* mem;
double val;
uae_u8 status;
uae_s8 realreg; /* gb-- realreg can hold -1 */
uae_u8 realind;
uae_u8 needflush;
} freg_status;
#define PC_P 16
#define FLAGX 17
#define FLAGTMP 18
#define NEXT_HANDLER 19
#define S1 20
#define S2 21
#define S3 22
#define S4 23
#define S5 24
#define S6 25
#define S7 26
#define S8 27
#define S9 28
#define S10 29
#define S11 30
#define S12 31
#define FP_RESULT 8
#define FS1 9
#define FS2 10
#define FS3 11
typedef struct {
uae_u32 touched;
uae_s8 holds[VREGS];
uae_u8 nholds;
uae_u8 canbyte;
uae_u8 canword;
uae_u8 locked;
} n_status;
typedef struct {
uae_u32 touched;
uae_s8 holds[VFREGS];
uae_u8 nholds;
uae_u8 locked;
} fn_status;
/* For flag handling */
#define NADA 1
#define TRASH 2
#define VALID 3
/* needflush values */
#define NF_SCRATCH 0
#define NF_TOMEM 1
#define NF_HANDLER 2
typedef struct {
/* Integer part */
reg_status state[VREGS];
n_status nat[N_REGS];
uae_u32 flags_on_stack;
uae_u32 flags_in_flags;
uae_u32 flags_are_important;
/* FPU part */
freg_status fate[VFREGS];
fn_status fat[N_FREGS];
/* x86 FPU part */
uae_s8 spos[N_FREGS];
uae_s8 onstack[6];
uae_s8 tos;
} bigstate;
typedef struct {
/* Integer part */
char virt[VREGS];
char nat[N_REGS];
} smallstate;
extern bigstate live;
extern int touchcnt;
#define IMM uae_s32
#define R1 uae_u32
#define R2 uae_u32
#define R4 uae_u32
#define W1 uae_u32
#define W2 uae_u32
#define W4 uae_u32
#define RW1 uae_u32
#define RW2 uae_u32
#define RW4 uae_u32
#define MEMR uae_u32
#define MEMW uae_u32
#define MEMRW uae_u32
#define FW uae_u32
#define FR uae_u32
#define FRW uae_u32
#define MIDFUNC(nargs,func,args) void func args
#define MENDFUNC(nargs,func,args)
#define COMPCALL(func) func
#define LOWFUNC(flags,mem,nargs,func,args) static __inline__ void func args
#define LENDFUNC(flags,mem,nargs,func,args)
/* What we expose to the outside */
#define DECLARE_MIDFUNC(func) extern void func
DECLARE_MIDFUNC(bt_l_ri(R4 r, IMM i));
DECLARE_MIDFUNC(bt_l_rr(R4 r, R4 b));
DECLARE_MIDFUNC(btc_l_ri(RW4 r, IMM i));
DECLARE_MIDFUNC(btc_l_rr(RW4 r, R4 b));
DECLARE_MIDFUNC(bts_l_ri(RW4 r, IMM i));
DECLARE_MIDFUNC(bts_l_rr(RW4 r, R4 b));
DECLARE_MIDFUNC(btr_l_ri(RW4 r, IMM i));
DECLARE_MIDFUNC(btr_l_rr(RW4 r, R4 b));
DECLARE_MIDFUNC(mov_l_rm(W4 d, IMM s));
DECLARE_MIDFUNC(call_r(R4 r));
DECLARE_MIDFUNC(sub_l_mi(IMM d, IMM s));
DECLARE_MIDFUNC(mov_l_mi(IMM d, IMM s));
DECLARE_MIDFUNC(mov_w_mi(IMM d, IMM s));
DECLARE_MIDFUNC(mov_b_mi(IMM d, IMM s));
DECLARE_MIDFUNC(rol_b_ri(RW1 r, IMM i));
DECLARE_MIDFUNC(rol_w_ri(RW2 r, IMM i));
DECLARE_MIDFUNC(rol_l_ri(RW4 r, IMM i));
DECLARE_MIDFUNC(rol_l_rr(RW4 d, R1 r));
DECLARE_MIDFUNC(rol_w_rr(RW2 d, R1 r));
DECLARE_MIDFUNC(rol_b_rr(RW1 d, R1 r));
DECLARE_MIDFUNC(shll_l_rr(RW4 d, R1 r));
DECLARE_MIDFUNC(shll_w_rr(RW2 d, R1 r));
DECLARE_MIDFUNC(shll_b_rr(RW1 d, R1 r));
DECLARE_MIDFUNC(ror_b_ri(R1 r, IMM i));
DECLARE_MIDFUNC(ror_w_ri(R2 r, IMM i));
DECLARE_MIDFUNC(ror_l_ri(R4 r, IMM i));
DECLARE_MIDFUNC(ror_l_rr(R4 d, R1 r));
DECLARE_MIDFUNC(ror_w_rr(R2 d, R1 r));
DECLARE_MIDFUNC(ror_b_rr(R1 d, R1 r));
DECLARE_MIDFUNC(shrl_l_rr(RW4 d, R1 r));
DECLARE_MIDFUNC(shrl_w_rr(RW2 d, R1 r));
DECLARE_MIDFUNC(shrl_b_rr(RW1 d, R1 r));
DECLARE_MIDFUNC(shra_l_rr(RW4 d, R1 r));
DECLARE_MIDFUNC(shra_w_rr(RW2 d, R1 r));
DECLARE_MIDFUNC(shra_b_rr(RW1 d, R1 r));
DECLARE_MIDFUNC(shll_l_ri(RW4 r, IMM i));
DECLARE_MIDFUNC(shll_w_ri(RW2 r, IMM i));
DECLARE_MIDFUNC(shll_b_ri(RW1 r, IMM i));
DECLARE_MIDFUNC(shrl_l_ri(RW4 r, IMM i));
DECLARE_MIDFUNC(shrl_w_ri(RW2 r, IMM i));
DECLARE_MIDFUNC(shrl_b_ri(RW1 r, IMM i));
DECLARE_MIDFUNC(shra_l_ri(RW4 r, IMM i));
DECLARE_MIDFUNC(shra_w_ri(RW2 r, IMM i));
DECLARE_MIDFUNC(shra_b_ri(RW1 r, IMM i));
DECLARE_MIDFUNC(setcc(W1 d, IMM cc));
DECLARE_MIDFUNC(setcc_m(IMM d, IMM cc));
DECLARE_MIDFUNC(cmov_b_rr(RW1 d, R1 s, IMM cc));
DECLARE_MIDFUNC(cmov_w_rr(RW2 d, R2 s, IMM cc));
DECLARE_MIDFUNC(cmov_l_rr(RW4 d, R4 s, IMM cc));
DECLARE_MIDFUNC(cmov_l_rm(RW4 d, IMM s, IMM cc));
DECLARE_MIDFUNC(bsf_l_rr(W4 d, R4 s));
DECLARE_MIDFUNC(pop_m(IMM d));
DECLARE_MIDFUNC(push_m(IMM d));
DECLARE_MIDFUNC(pop_l(W4 d));
DECLARE_MIDFUNC(push_l_i(IMM i));
DECLARE_MIDFUNC(push_l(R4 s));
DECLARE_MIDFUNC(clear_16(RW4 r));
DECLARE_MIDFUNC(clear_8(RW4 r));
DECLARE_MIDFUNC(sign_extend_16_rr(W4 d, R2 s));
DECLARE_MIDFUNC(sign_extend_8_rr(W4 d, R1 s));
DECLARE_MIDFUNC(zero_extend_16_rr(W4 d, R2 s));
DECLARE_MIDFUNC(zero_extend_8_rr(W4 d, R1 s));
DECLARE_MIDFUNC(imul_64_32(RW4 d, RW4 s));
DECLARE_MIDFUNC(mul_64_32(RW4 d, RW4 s));
DECLARE_MIDFUNC(imul_32_32(RW4 d, R4 s));
DECLARE_MIDFUNC(mul_32_32(RW4 d, R4 s));
DECLARE_MIDFUNC(mov_b_rr(W1 d, R1 s));
DECLARE_MIDFUNC(mov_w_rr(W2 d, R2 s));
DECLARE_MIDFUNC(mov_l_rrm_indexed(W4 d,R4 baser, R4 index, IMM factor));
DECLARE_MIDFUNC(mov_w_rrm_indexed(W2 d, R4 baser, R4 index, IMM factor));
DECLARE_MIDFUNC(mov_b_rrm_indexed(W1 d, R4 baser, R4 index, IMM factor));
DECLARE_MIDFUNC(mov_l_mrr_indexed(R4 baser, R4 index, IMM factor, R4 s));
DECLARE_MIDFUNC(mov_w_mrr_indexed(R4 baser, R4 index, IMM factor, R2 s));
DECLARE_MIDFUNC(mov_b_mrr_indexed(R4 baser, R4 index, IMM factor, R1 s));
DECLARE_MIDFUNC(mov_l_bmrr_indexed(IMM base, R4 baser, R4 index, IMM factor, R4 s));
DECLARE_MIDFUNC(mov_w_bmrr_indexed(IMM base, R4 baser, R4 index, IMM factor, R2 s));
DECLARE_MIDFUNC(mov_b_bmrr_indexed(IMM base, R4 baser, R4 index, IMM factor, R1 s));
DECLARE_MIDFUNC(mov_l_brrm_indexed(W4 d, IMM base, R4 baser, R4 index, IMM factor));
DECLARE_MIDFUNC(mov_w_brrm_indexed(W2 d, IMM base, R4 baser, R4 index, IMM factor));
DECLARE_MIDFUNC(mov_b_brrm_indexed(W1 d, IMM base, R4 baser, R4 index, IMM factor));
DECLARE_MIDFUNC(mov_l_rm_indexed(W4 d, IMM base, R4 index, IMM factor));
DECLARE_MIDFUNC(mov_l_rR(W4 d, R4 s, IMM offset));
DECLARE_MIDFUNC(mov_w_rR(W2 d, R4 s, IMM offset));
DECLARE_MIDFUNC(mov_b_rR(W1 d, R4 s, IMM offset));
DECLARE_MIDFUNC(mov_l_brR(W4 d, R4 s, IMM offset));
DECLARE_MIDFUNC(mov_w_brR(W2 d, R4 s, IMM offset));
DECLARE_MIDFUNC(mov_b_brR(W1 d, R4 s, IMM offset));
DECLARE_MIDFUNC(mov_l_Ri(R4 d, IMM i, IMM offset));
DECLARE_MIDFUNC(mov_w_Ri(R4 d, IMM i, IMM offset));
DECLARE_MIDFUNC(mov_b_Ri(R4 d, IMM i, IMM offset));
DECLARE_MIDFUNC(mov_l_Rr(R4 d, R4 s, IMM offset));
DECLARE_MIDFUNC(mov_w_Rr(R4 d, R2 s, IMM offset));
DECLARE_MIDFUNC(mov_b_Rr(R4 d, R1 s, IMM offset));
DECLARE_MIDFUNC(lea_l_brr(W4 d, R4 s, IMM offset));
DECLARE_MIDFUNC(lea_l_brr_indexed(W4 d, R4 s, R4 index, IMM factor, IMM offset));
DECLARE_MIDFUNC(lea_l_rr_indexed(W4 d, R4 s, R4 index, IMM factor));
DECLARE_MIDFUNC(mov_l_bRr(R4 d, R4 s, IMM offset));
DECLARE_MIDFUNC(mov_w_bRr(R4 d, R2 s, IMM offset));
DECLARE_MIDFUNC(mov_b_bRr(R4 d, R1 s, IMM offset));
DECLARE_MIDFUNC(bswap_32(RW4 r));
DECLARE_MIDFUNC(bswap_16(RW2 r));
DECLARE_MIDFUNC(mov_l_rr(W4 d, R4 s));
DECLARE_MIDFUNC(mov_l_mr(IMM d, R4 s));
DECLARE_MIDFUNC(mov_w_mr(IMM d, R2 s));
DECLARE_MIDFUNC(mov_w_rm(W2 d, IMM s));
DECLARE_MIDFUNC(mov_b_mr(IMM d, R1 s));
DECLARE_MIDFUNC(mov_b_rm(W1 d, IMM s));
DECLARE_MIDFUNC(mov_l_ri(W4 d, IMM s));
DECLARE_MIDFUNC(mov_w_ri(W2 d, IMM s));
DECLARE_MIDFUNC(mov_b_ri(W1 d, IMM s));
DECLARE_MIDFUNC(add_l_mi(IMM d, IMM s) );
DECLARE_MIDFUNC(add_w_mi(IMM d, IMM s) );
DECLARE_MIDFUNC(add_b_mi(IMM d, IMM s) );
DECLARE_MIDFUNC(test_l_ri(R4 d, IMM i));
DECLARE_MIDFUNC(test_l_rr(R4 d, R4 s));
DECLARE_MIDFUNC(test_w_rr(R2 d, R2 s));
DECLARE_MIDFUNC(test_b_rr(R1 d, R1 s));
DECLARE_MIDFUNC(and_l_ri(RW4 d, IMM i));
DECLARE_MIDFUNC(and_l(RW4 d, R4 s));
DECLARE_MIDFUNC(and_w(RW2 d, R2 s));
DECLARE_MIDFUNC(and_b(RW1 d, R1 s));
DECLARE_MIDFUNC(or_l_rm(RW4 d, IMM s));
DECLARE_MIDFUNC(or_l_ri(RW4 d, IMM i));
DECLARE_MIDFUNC(or_l(RW4 d, R4 s));
DECLARE_MIDFUNC(or_w(RW2 d, R2 s));
DECLARE_MIDFUNC(or_b(RW1 d, R1 s));
DECLARE_MIDFUNC(adc_l(RW4 d, R4 s));
DECLARE_MIDFUNC(adc_w(RW2 d, R2 s));
DECLARE_MIDFUNC(adc_b(RW1 d, R1 s));
DECLARE_MIDFUNC(add_l(RW4 d, R4 s));
DECLARE_MIDFUNC(add_w(RW2 d, R2 s));
DECLARE_MIDFUNC(add_b(RW1 d, R1 s));
DECLARE_MIDFUNC(sub_l_ri(RW4 d, IMM i));
DECLARE_MIDFUNC(sub_w_ri(RW2 d, IMM i));
DECLARE_MIDFUNC(sub_b_ri(RW1 d, IMM i));
DECLARE_MIDFUNC(add_l_ri(RW4 d, IMM i));
DECLARE_MIDFUNC(add_w_ri(RW2 d, IMM i));
DECLARE_MIDFUNC(add_b_ri(RW1 d, IMM i));
DECLARE_MIDFUNC(sbb_l(RW4 d, R4 s));
DECLARE_MIDFUNC(sbb_w(RW2 d, R2 s));
DECLARE_MIDFUNC(sbb_b(RW1 d, R1 s));
DECLARE_MIDFUNC(sub_l(RW4 d, R4 s));
DECLARE_MIDFUNC(sub_w(RW2 d, R2 s));
DECLARE_MIDFUNC(sub_b(RW1 d, R1 s));
DECLARE_MIDFUNC(cmp_l(R4 d, R4 s));
DECLARE_MIDFUNC(cmp_l_ri(R4 r, IMM i));
DECLARE_MIDFUNC(cmp_w(R2 d, R2 s));
DECLARE_MIDFUNC(cmp_b(R1 d, R1 s));
DECLARE_MIDFUNC(xor_l(RW4 d, R4 s));
DECLARE_MIDFUNC(xor_w(RW2 d, R2 s));
DECLARE_MIDFUNC(xor_b(RW1 d, R1 s));
DECLARE_MIDFUNC(live_flags(void));
DECLARE_MIDFUNC(dont_care_flags(void));
DECLARE_MIDFUNC(duplicate_carry(void));
DECLARE_MIDFUNC(restore_carry(void));
DECLARE_MIDFUNC(start_needflags(void));
DECLARE_MIDFUNC(end_needflags(void));
DECLARE_MIDFUNC(make_flags_live(void));
DECLARE_MIDFUNC(call_r_11(R4 r, W4 out1, R4 in1, IMM osize, IMM isize));
DECLARE_MIDFUNC(call_r_02(R4 r, R4 in1, R4 in2, IMM isize1, IMM isize2));
DECLARE_MIDFUNC(forget_about(W4 r));
DECLARE_MIDFUNC(nop(void));
DECLARE_MIDFUNC(f_forget_about(FW r));
DECLARE_MIDFUNC(fmov_pi(FW r));
DECLARE_MIDFUNC(fmov_log10_2(FW r));
DECLARE_MIDFUNC(fmov_log2_e(FW r));
DECLARE_MIDFUNC(fmov_loge_2(FW r));
DECLARE_MIDFUNC(fmov_1(FW r));
DECLARE_MIDFUNC(fmov_0(FW r));
DECLARE_MIDFUNC(fmov_rm(FW r, MEMR m));
DECLARE_MIDFUNC(fmovi_rm(FW r, MEMR m));
DECLARE_MIDFUNC(fmovi_mr(MEMW m, FR r));
DECLARE_MIDFUNC(fmovs_rm(FW r, MEMR m));
DECLARE_MIDFUNC(fmovs_mr(MEMW m, FR r));
DECLARE_MIDFUNC(fmov_mr(MEMW m, FR r));
DECLARE_MIDFUNC(fmov_ext_mr(MEMW m, FR r));
DECLARE_MIDFUNC(fmov_ext_rm(FW r, MEMR m));
DECLARE_MIDFUNC(fmov_rr(FW d, FR s));
DECLARE_MIDFUNC(fldcw_m_indexed(R4 index, IMM base));
DECLARE_MIDFUNC(ftst_r(FR r));
DECLARE_MIDFUNC(dont_care_fflags(void));
DECLARE_MIDFUNC(fsqrt_rr(FW d, FR s));
DECLARE_MIDFUNC(fabs_rr(FW d, FR s));
DECLARE_MIDFUNC(frndint_rr(FW d, FR s));
DECLARE_MIDFUNC(fsin_rr(FW d, FR s));
DECLARE_MIDFUNC(fcos_rr(FW d, FR s));
DECLARE_MIDFUNC(ftwotox_rr(FW d, FR s));
DECLARE_MIDFUNC(fetox_rr(FW d, FR s));
DECLARE_MIDFUNC(flog2_rr(FW d, FR s));
DECLARE_MIDFUNC(fneg_rr(FW d, FR s));
DECLARE_MIDFUNC(fadd_rr(FRW d, FR s));
DECLARE_MIDFUNC(fsub_rr(FRW d, FR s));
DECLARE_MIDFUNC(fmul_rr(FRW d, FR s));
DECLARE_MIDFUNC(frem_rr(FRW d, FR s));
DECLARE_MIDFUNC(frem1_rr(FRW d, FR s));
DECLARE_MIDFUNC(fdiv_rr(FRW d, FR s));
DECLARE_MIDFUNC(fcmp_rr(FR d, FR s));
DECLARE_MIDFUNC(fflags_into_flags(W2 tmp));
#undef DECLARE_MIDFUNC
extern int failure;
#define FAIL(x) do { failure|=x; } while (0)
/* Convenience functions exposed to gencomp */
extern uae_u32 m68k_pc_offset;
extern void readbyte(int address, int dest, int tmp);
extern void readword(int address, int dest, int tmp);
extern void readlong(int address, int dest, int tmp);
extern void writebyte(int address, int source, int tmp);
extern void writeword(int address, int source, int tmp);
extern void writelong(int address, int source, int tmp);
extern void writeword_clobber(int address, int source, int tmp);
extern void writelong_clobber(int address, int source, int tmp);
extern void get_n_addr(int address, int dest, int tmp);
extern void get_n_addr_jmp(int address, int dest, int tmp);
extern void calc_disp_ea_020(int base, uae_u32 dp, int target, int tmp);
/* Set native Z flag only if register is zero */
extern void set_zero(int r, int tmp);
extern int kill_rodent(int r);
extern void sync_m68k_pc(void);
extern uae_u32 get_const(int r);
extern int is_const(int r);
extern void register_branch(uae_u32 not_taken, uae_u32 taken, uae_u8 cond);
#define comp_get_ibyte(o) do_get_mem_byte((uae_u8 *)(comp_pc_p + (o) + 1))
#define comp_get_iword(o) do_get_mem_word((uae_u16 *)(comp_pc_p + (o)))
#define comp_get_ilong(o) do_get_mem_long((uae_u32 *)(comp_pc_p + (o)))
struct blockinfo_t;
typedef struct dep_t {
uae_u32* jmp_off;
struct blockinfo_t* target;
struct blockinfo_t* source;
struct dep_t** prev_p;
struct dep_t* next;
} dependency;
typedef struct checksum_info_t {
uae_u8 *start_p;
uae_u32 length;
struct checksum_info_t *next;
} checksum_info;
typedef struct blockinfo_t {
uae_s32 count;
cpuop_func* direct_handler_to_use;
cpuop_func* handler_to_use;
/* The direct handler does not check for the correct address */
cpuop_func* handler;
cpuop_func* direct_handler;
cpuop_func* direct_pen;
cpuop_func* direct_pcc;
uae_u8* pc_p;
uae_u32 c1;
uae_u32 c2;
#if USE_CHECKSUM_INFO
checksum_info *csi;
#else
uae_u32 len;
uae_u32 min_pcp;
#endif
struct blockinfo_t* next_same_cl;
struct blockinfo_t** prev_same_cl_p;
struct blockinfo_t* next;
struct blockinfo_t** prev_p;
uae_u8 optlevel;
uae_u8 needed_flags;
uae_u8 status;
uae_u8 havestate;
dependency dep[2]; /* Holds things we depend on */
dependency* deplist; /* List of things that depend on this */
smallstate env;
#if JIT_DEBUG
/* (gb) size of the compiled block (direct handler) */
uae_u32 direct_handler_size;
#endif
} blockinfo;
#define BI_INVALID 0
#define BI_ACTIVE 1
#define BI_NEED_RECOMP 2
#define BI_NEED_CHECK 3
#define BI_CHECKING 4
#define BI_COMPILING 5
#define BI_FINALIZING 6
void execute_normal(void);
void exec_nostats(void);
void do_nothing(void);
#else
static __inline__ void flush_icache(int) { }
static __inline__ void build_comp() { }
#endif /* !USE_JIT */
#endif /* COMPEMU_H */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,102 @@
/*
* cpu_emulation.h - Definitions for Basilisk II CPU emulation module (UAE 0.8.10 version)
*
* Basilisk II (C) 1997-2008 Christian Bauer
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This 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 CPU_EMULATION_H
#define CPU_EMULATION_H
#include <string.h>
/*
* Memory system
*/
// RAM and ROM pointers (allocated and set by main_*.cpp)
extern uint32 RAMBaseMac; // RAM base (Mac address space), does not include Low Mem when != 0
extern uint8 *RAMBaseHost; // RAM base (host address space)
extern uint32 RAMSize; // Size of RAM
extern uint32 ROMBaseMac; // ROM base (Mac address space)
extern uint8 *ROMBaseHost; // ROM base (host address space)
extern uint32 ROMSize; // Size of ROM
#if !REAL_ADDRESSING && !DIRECT_ADDRESSING
// If we are not using real or direct addressing, the Mac frame buffer gets
// mapped to this location. The memory must be allocated by VideoInit().
// If multiple monitors are used, they must share the frame buffer
const uint32 MacFrameBaseMac = 0xa0000000;
extern uint8 *MacFrameBaseHost; // Frame buffer base (host address space)
extern uint32 MacFrameSize; // Size of frame buffer
#endif
extern int MacFrameLayout; // Frame buffer layout (see defines below)
// Possible frame buffer layouts
enum {
FLAYOUT_NONE, // No frame buffer
FLAYOUT_DIRECT, // Frame buffer is in MacOS layout, no conversion needed
FLAYOUT_HOST_555, // 16 bit, RGB 555, host byte order
FLAYOUT_HOST_565, // 16 bit, RGB 565, host byte order
FLAYOUT_HOST_888 // 32 bit, RGB 888, host byte order
};
// Mac memory access functions
#include "memory.h"
static inline uint32 ReadMacInt32(uint32 addr) {return get_long(addr);}
static inline uint32 ReadMacInt16(uint32 addr) {return get_word(addr);}
static inline uint32 ReadMacInt8(uint32 addr) {return get_byte(addr);}
static inline void WriteMacInt32(uint32 addr, uint32 l) {put_long(addr, l);}
static inline void WriteMacInt16(uint32 addr, uint32 w) {put_word(addr, w);}
static inline void WriteMacInt8(uint32 addr, uint32 b) {put_byte(addr, b);}
static inline uint8 *Mac2HostAddr(uint32 addr) {return get_real_address(addr);}
static inline uint32 Host2MacAddr(uint8 *addr) {return get_virtual_address(addr);}
static inline void *Mac_memset(uint32 addr, int c, size_t n) {return memset(Mac2HostAddr(addr), c, n);}
static inline void *Mac2Host_memcpy(void *dest, uint32 src, size_t n) {return memcpy(dest, Mac2HostAddr(src), n);}
static inline void *Host2Mac_memcpy(uint32 dest, const void *src, size_t n) {return memcpy(Mac2HostAddr(dest), src, n);}
static inline void *Mac2Mac_memcpy(uint32 dest, uint32 src, size_t n) {return memcpy(Mac2HostAddr(dest), Mac2HostAddr(src), n);}
/*
* 680x0 emulation
*/
// Initialization
extern bool Init680x0(void); // This routine may want to look at CPUType/FPUType to set up the apropriate emulation
extern void Exit680x0(void);
extern void InitFrameBufferMapping(void);
// 680x0 dynamic recompilation activation flag
#if USE_JIT
extern bool UseJIT;
#else
const bool UseJIT = false;
#endif
// 680x0 emulation functions
struct M68kRegisters;
extern void Start680x0(void); // Reset and start 680x0
extern "C" void Execute68k(uint32 addr, M68kRegisters *r); // Execute 68k code from EMUL_OP routine
extern "C" void Execute68kTrap(uint16 trap, M68kRegisters *r); // Execute MacOS 68k trap from EMUL_OP routine
// Interrupt functions
extern void TriggerInterrupt(void); // Trigger interrupt level 1 (InterruptFlag must be set first)
extern void TriggerNMI(void); // Trigger interrupt level 7
#endif

View File

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

View File

@ -0,0 +1,259 @@
/*
* fpu/core.h - base fpu context definition
*
* Basilisk II (C) 1997-2008 Christian Bauer
*
* MC68881/68040 fpu emulation
*
* Original UAE FPU, copyright 1996 Herman ten Brugge
* Rewrite for x86, copyright 1999-2000 Lauri Pesonen
* New framework, copyright 2000 Gwenole Beauchesne
* Adapted for JIT compilation (c) Bernd Meyer, 2000
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This 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 FPU_CORE_H
#define FPU_CORE_H
#include "sysdeps.h"
#include "fpu/types.h"
/* Always use x87 FPU stack on IA-32. */
#if defined(X86_ASSEMBLY)
#define USE_X87_ASSEMBLY 1
#endif
/* Only use x87 FPU on x86-64 if long double precision is requested. */
#if defined(X86_64_ASSEMBLY) && USE_LONG_DOUBLE
#define USE_X87_ASSEMBLY 1
#endif
/* ========================================================================== */
/* ========================= FPU CONTEXT DEFINITION ========================= */
/* ========================================================================== */
/* We don't use all features of the C++ language so that we may still
* easily backport that code to C.
*/
struct fpu_t {
/* ---------------------------------------------------------------------- */
/* --- Floating-Point Data Registers --- */
/* ---------------------------------------------------------------------- */
/* The eight %fp0 .. %fp7 registers */
fpu_register registers[8];
/* Used for lazy evalualation of FPU flags */
fpu_register result;
/* ---------------------------------------------------------------------- */
/* --- Floating-Point Control Register --- */
/* ---------------------------------------------------------------------- */
struct {
/* Exception Enable Byte */
uae_u32 exception_enable;
#define FPCR_EXCEPTION_ENABLE 0x0000ff00
#define FPCR_EXCEPTION_BSUN 0x00008000
#define FPCR_EXCEPTION_SNAN 0x00004000
#define FPCR_EXCEPTION_OPERR 0x00002000
#define FPCR_EXCEPTION_OVFL 0x00001000
#define FPCR_EXCEPTION_UNFL 0x00000800
#define FPCR_EXCEPTION_DZ 0x00000400
#define FPCR_EXCEPTION_INEX2 0x00000200
#define FPCR_EXCEPTION_INEX1 0x00000100
/* Mode Control Byte Mask */
#define FPCR_MODE_CONTROL 0x000000ff
/* Rounding precision */
uae_u32 rounding_precision;
#define FPCR_ROUNDING_PRECISION 0x000000c0
#define FPCR_PRECISION_SINGLE 0x00000040
#define FPCR_PRECISION_DOUBLE 0x00000080
#define FPCR_PRECISION_EXTENDED 0x00000000
/* Rounding mode */
uae_u32 rounding_mode;
#define FPCR_ROUNDING_MODE 0x00000030
#define FPCR_ROUND_NEAR 0x00000000
#define FPCR_ROUND_ZERO 0x00000010
#define FPCR_ROUND_MINF 0x00000020
#define FPCR_ROUND_PINF 0x00000030
} fpcr;
/* ---------------------------------------------------------------------- */
/* --- Floating-Point Status Register --- */
/* ---------------------------------------------------------------------- */
struct {
/* Floating-Point Condition Code Byte */
uae_u32 condition_codes;
#define FPSR_CCB 0xff000000
#define FPSR_CCB_NEGATIVE 0x08000000
#define FPSR_CCB_ZERO 0x04000000
#define FPSR_CCB_INFINITY 0x02000000
#define FPSR_CCB_NAN 0x01000000
/* Quotient Byte */
uae_u32 quotient;
#define FPSR_QUOTIENT 0x00ff0000
#define FPSR_QUOTIENT_SIGN 0x00800000
#define FPSR_QUOTIENT_VALUE 0x007f0000
/* Exception Status Byte */
uae_u32 exception_status;
#define FPSR_EXCEPTION_STATUS FPCR_EXCEPTION_ENABLE
#define FPSR_EXCEPTION_BSUN FPCR_EXCEPTION_BSUN
#define FPSR_EXCEPTION_SNAN FPCR_EXCEPTION_SNAN
#define FPSR_EXCEPTION_OPERR FPCR_EXCEPTION_OPERR
#define FPSR_EXCEPTION_OVFL FPCR_EXCEPTION_OVFL
#define FPSR_EXCEPTION_UNFL FPCR_EXCEPTION_UNFL
#define FPSR_EXCEPTION_DZ FPCR_EXCEPTION_DZ
#define FPSR_EXCEPTION_INEX2 FPCR_EXCEPTION_INEX2
#define FPSR_EXCEPTION_INEX1 FPCR_EXCEPTION_INEX1
/* Accrued Exception Byte */
uae_u32 accrued_exception;
#define FPSR_ACCRUED_EXCEPTION 0x000000ff
#define FPSR_ACCR_IOP 0x00000080
#define FPSR_ACCR_OVFL 0x00000040
#define FPSR_ACCR_UNFL 0x00000020
#define FPSR_ACCR_DZ 0x00000010
#define FPSR_ACCR_INEX 0x00000008
} fpsr;
/* ---------------------------------------------------------------------- */
/* --- Floating-Point Instruction Address Register --- */
/* ---------------------------------------------------------------------- */
uae_u32 instruction_address;
/* ---------------------------------------------------------------------- */
/* --- Initialization / Finalization --- */
/* ---------------------------------------------------------------------- */
/* Flag set if we emulate an integral 68040 FPU */
bool is_integral;
/* ---------------------------------------------------------------------- */
/* --- Extra FPE-dependant defines --- */
/* ---------------------------------------------------------------------- */
#if defined(FPU_X86) \
|| (defined(FPU_UAE) && defined(USE_X87_ASSEMBLY)) \
|| (defined(FPU_IEEE) && defined(USE_X87_ASSEMBLY))
#define CW_RESET 0x0040 // initial CW value after RESET
#define CW_FINIT 0x037F // initial CW value after FINIT
#define SW_RESET 0x0000 // initial SW value after RESET
#define SW_FINIT 0x0000 // initial SW value after FINIT
#define TW_RESET 0x5555 // initial TW value after RESET
#define TW_FINIT 0x0FFF // initial TW value after FINIT
#define CW_X 0x1000 // infinity control
#define CW_RC_ZERO 0x0C00 // rounding control toward zero
#define CW_RC_UP 0x0800 // rounding control toward +
#define CW_RC_DOWN 0x0400 // rounding control toward -
#define CW_RC_NEAR 0x0000 // rounding control toward even
#define CW_PC_EXTENDED 0x0300 // precision control 64bit
#define CW_PC_DOUBLE 0x0200 // precision control 53bit
#define CW_PC_RESERVED 0x0100 // precision control reserved
#define CW_PC_SINGLE 0x0000 // precision control 24bit
#define CW_PM 0x0020 // precision exception mask
#define CW_UM 0x0010 // underflow exception mask
#define CW_OM 0x0008 // overflow exception mask
#define CW_ZM 0x0004 // zero divide exception mask
#define CW_DM 0x0002 // denormalized operand exception mask
#define CW_IM 0x0001 // invalid operation exception mask
#define SW_B 0x8000 // busy flag
#define SW_C3 0x4000 // condition code flag 3
#define SW_TOP_7 0x3800 // top of stack = ST(7)
#define SW_TOP_6 0x3000 // top of stack = ST(6)
#define SW_TOP_5 0x2800 // top of stack = ST(5)
#define SW_TOP_4 0x2000 // top of stack = ST(4)
#define SW_TOP_3 0x1800 // top of stack = ST(3)
#define SW_TOP_2 0x1000 // top of stack = ST(2)
#define SW_TOP_1 0x0800 // top of stack = ST(1)
#define SW_TOP_0 0x0000 // top of stack = ST(0)
#define SW_C2 0x0400 // condition code flag 2
#define SW_C1 0x0200 // condition code flag 1
#define SW_C0 0x0100 // condition code flag 0
#define SW_ES 0x0080 // error summary status flag
#define SW_SF 0x0040 // stack fault flag
#define SW_PE 0x0020 // precision exception flag
#define SW_UE 0x0010 // underflow exception flag
#define SW_OE 0x0008 // overflow exception flag
#define SW_ZE 0x0004 // zero divide exception flag
#define SW_DE 0x0002 // denormalized operand exception flag
#define SW_IE 0x0001 // invalid operation exception flag
#define X86_ROUNDING_MODE 0x0C00
#define X86_ROUNDING_PRECISION 0x0300
#endif /* FPU_X86 */
};
/* We handle only one global fpu */
extern fpu_t fpu;
/* Return the address of a particular register */
inline fpu_register * const fpu_register_address(int i)
{ return &fpu.registers[i]; }
/* Dump functions for m68k_dumpstate */
extern void fpu_dump_registers(void);
extern void fpu_dump_flags(void);
/* Accessors to FPU Control Register */
static inline uae_u32 get_fpcr(void);
static inline void set_fpcr(uae_u32 new_fpcr);
/* Accessors to FPU Status Register */
static inline uae_u32 get_fpsr(void);
static inline void set_fpsr(uae_u32 new_fpsr);
/* Accessors to FPU Instruction Address Register */
static inline uae_u32 get_fpiar();
static inline void set_fpiar(uae_u32 new_fpiar);
/* Initialization / Finalization */
extern void fpu_init(bool integral_68040);
extern void fpu_exit(void);
extern void fpu_reset(void);
/* Floating-point arithmetic instructions */
void fpuop_arithmetic(uae_u32 opcode, uae_u32 extra) REGPARAM;
/* Floating-point program control operations */
void fpuop_bcc(uae_u32 opcode, uaecptr pc, uae_u32 extra) REGPARAM;
void fpuop_dbcc(uae_u32 opcode, uae_u32 extra) REGPARAM;
void fpuop_scc(uae_u32 opcode, uae_u32 extra) REGPARAM;
/* Floating-point system control operations */
void fpuop_save(uae_u32 opcode) REGPARAM;
void fpuop_restore(uae_u32 opcode) REGPARAM;
void fpuop_trapcc(uae_u32 opcode, uaecptr oldpc) REGPARAM;
#endif /* FPU_CORE_H */

View File

@ -0,0 +1,188 @@
/*
* fpu/exceptions.cpp - system-dependant FPU exceptions management
*
* Basilisk II (C) 1997-2008 Christian Bauer
*
* MC68881/68040 fpu emulation
*
* Original UAE FPU, copyright 1996 Herman ten Brugge
* Rewrite for x86, copyright 1999-2000 Lauri Pesonen
* New framework, copyright 2000 Gwenole Beauchesne
* Adapted for JIT compilation (c) Bernd Meyer, 2000
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This 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
*/
#undef PRIVATE
#define PRIVATE /**/
#undef PUBLIC
#define PUBLIC /**/
#undef FFPU
#define FFPU /**/
#undef FPU
#define FPU fpu.
/* -------------------------------------------------------------------------- */
/* --- Native X86 exceptions --- */
/* -------------------------------------------------------------------------- */
#ifdef FPU_USE_X86_EXCEPTIONS
void FFPU fpu_init_native_exceptions(void)
{
// Mapping for "sw" -> fpsr exception byte
for (uae_u32 i = 0; i < 0x80; i++) {
exception_host2mac[i] = 0;
if(i & SW_FAKE_BSUN) {
exception_host2mac[i] |= FPSR_EXCEPTION_BSUN;
}
// precision exception
if(i & SW_PE) {
exception_host2mac[i] |= FPSR_EXCEPTION_INEX2;
}
// underflow exception
if(i & SW_UE) {
exception_host2mac[i] |= FPSR_EXCEPTION_UNFL;
}
// overflow exception
if(i & SW_OE) {
exception_host2mac[i] |= FPSR_EXCEPTION_OVFL;
}
// zero divide exception
if(i & SW_ZE) {
exception_host2mac[i] |= FPSR_EXCEPTION_DZ;
}
// denormalized operand exception.
// wrong, but should not get here, normalization is done in elsewhere
if(i & SW_DE) {
exception_host2mac[i] |= FPSR_EXCEPTION_SNAN;
}
// invalid operation exception
if(i & SW_IE) {
exception_host2mac[i] |= FPSR_EXCEPTION_OPERR;
}
}
// Mapping for fpsr exception byte -> "sw"
for (uae_u32 i = 0; i < 0x100; i++) {
uae_u32 fpsr = (i << 8);
exception_mac2host[i] = 0;
// BSUN; make sure that you don't generate FPU stack faults.
if(fpsr & FPSR_EXCEPTION_BSUN) {
exception_mac2host[i] |= SW_FAKE_BSUN;
}
// precision exception
if(fpsr & FPSR_EXCEPTION_INEX2) {
exception_mac2host[i] |= SW_PE;
}
// underflow exception
if(fpsr & FPSR_EXCEPTION_UNFL) {
exception_mac2host[i] |= SW_UE;
}
// overflow exception
if(fpsr & FPSR_EXCEPTION_OVFL) {
exception_mac2host[i] |= SW_OE;
}
// zero divide exception
if(fpsr & FPSR_EXCEPTION_DZ) {
exception_mac2host[i] |= SW_ZE;
}
// denormalized operand exception
if(fpsr & FPSR_EXCEPTION_SNAN) {
exception_mac2host[i] |= SW_DE; //Wrong
}
// invalid operation exception
if(fpsr & FPSR_EXCEPTION_OPERR) {
exception_mac2host[i] |= SW_IE;
}
}
}
#endif
#ifdef FPU_USE_X86_ACCRUED_EXCEPTIONS
void FFPU fpu_init_native_accrued_exceptions(void)
{
/*
68881/68040 accrued exceptions accumulate as follows:
Accrued.IOP |= (Exception.SNAN | Exception.OPERR)
Accrued.OVFL |= (Exception.OVFL)
Accrued.UNFL |= (Exception.UNFL | Exception.INEX2)
Accrued.DZ |= (Exception.DZ)
Accrued.INEX |= (Exception.INEX1 | Exception.INEX2 | Exception.OVFL)
*/
// Mapping for "fpsr.accrued_exception" -> fpsr accrued exception byte
for (uae_u32 i = 0; i < 0x40; i++ ) {
accrued_exception_host2mac[i] = 0;
// precision exception
if(i & SW_PE) {
accrued_exception_host2mac[i] |= FPSR_ACCR_INEX;
}
// underflow exception
if(i & SW_UE) {
accrued_exception_host2mac[i] |= FPSR_ACCR_UNFL;
}
// overflow exception
if(i & SW_OE) {
accrued_exception_host2mac[i] |= FPSR_ACCR_OVFL;
}
// zero divide exception
if(i & SW_ZE) {
accrued_exception_host2mac[i] |= FPSR_ACCR_DZ;
}
// denormalized operand exception
if(i & SW_DE) {
accrued_exception_host2mac[i] |= FPSR_ACCR_IOP; //??????
}
// invalid operation exception
if(i & SW_IE) {
accrued_exception_host2mac[i] |= FPSR_ACCR_IOP;
}
}
// Mapping for fpsr accrued exception byte -> "fpsr.accrued_exception"
for (uae_u32 i = 0; i < 0x20; i++) {
int fpsr = (i << 3);
accrued_exception_mac2host[i] = 0;
// precision exception
if(fpsr & FPSR_ACCR_INEX) {
accrued_exception_mac2host[i] |= SW_PE;
}
// underflow exception
if(fpsr & FPSR_ACCR_UNFL) {
accrued_exception_mac2host[i] |= SW_UE;
}
// overflow exception
if(fpsr & FPSR_ACCR_OVFL) {
accrued_exception_mac2host[i] |= SW_OE;
}
// zero divide exception
if(fpsr & FPSR_ACCR_DZ) {
accrued_exception_mac2host[i] |= SW_ZE;
}
// What about SW_DE; //??????
// invalid operation exception
if(fpsr & FPSR_ACCR_IOP) {
accrued_exception_mac2host[i] |= SW_IE;
}
}
}
#endif

View File

@ -0,0 +1,149 @@
/*
* fpu/exceptions.h - system-dependant FPU exceptions management
*
* Basilisk II (C) 1997-2008 Christian Bauer
*
* MC68881/68040 fpu emulation
*
* Original UAE FPU, copyright 1996 Herman ten Brugge
* Rewrite for x86, copyright 1999-2000 Lauri Pesonen
* New framework, copyright 2000 Gwenole Beauchesne
* Adapted for JIT compilation (c) Bernd Meyer, 2000
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This 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 FPU_EXCEPTIONS_H
#define FPU_EXCEPTIONS_H
/* NOTE: this file shall be included only from fpu/fpu_*.cpp */
#undef PUBLIC
#define PUBLIC extern
#undef PRIVATE
#define PRIVATE static
#undef FFPU
#define FFPU /**/
#undef FPU
#define FPU fpu.
/* Defaults to generic exceptions */
#define FPU_USE_GENERIC_EXCEPTIONS
#define FPU_USE_GENERIC_ACCRUED_EXCEPTIONS
/* -------------------------------------------------------------------------- */
/* --- Selection of floating-point exceptions handling mode --- */
/* -------------------------------------------------------------------------- */
/* Optimized i386 fpu core must use native exceptions */
#if defined(FPU_X86) && defined(USE_X87_ASSEMBLY)
# undef FPU_USE_GENERIC_EXCEPTIONS
# define FPU_USE_X86_EXCEPTIONS
#endif
/* Optimized i386 fpu core must use native accrued exceptions */
#if defined(FPU_X86) && defined(USE_X87_ASSEMBLY)
# undef FPU_USE_GENERIC_ACCRUED_EXCEPTIONS
# define FPU_USE_X86_ACCRUED_EXCEPTIONS
#endif
/* -------------------------------------------------------------------------- */
/* --- Native X86 Exceptions --- */
/* -------------------------------------------------------------------------- */
#ifdef FPU_USE_X86_EXCEPTIONS
/* Extend the SW_* codes */
#define SW_FAKE_BSUN SW_SF
/* Shorthand */
#define SW_EXCEPTION_MASK (SW_ES|SW_SF|SW_PE|SW_UE|SW_OE|SW_ZE|SW_DE|SW_IE)
// #define SW_EXCEPTION_MASK (SW_SF|SW_PE|SW_UE|SW_OE|SW_ZE|SW_DE|SW_IE)
/* Lookup tables */
PRIVATE uae_u32 exception_host2mac[ 0x80 ];
PRIVATE uae_u32 exception_mac2host[ 0x100 ];
/* Initialize native exception management */
PUBLIC void FFPU fpu_init_native_exceptions(void);
/* Return m68k floating-point exception status */
PRIVATE inline uae_u32 FFPU get_exception_status(void)
{ return exception_host2mac[FPU fpsr.exception_status & (SW_FAKE_BSUN|SW_PE|SW_UE|SW_OE|SW_ZE|SW_DE|SW_IE)]; }
/* Set new exception status. Assumes mask against FPSR_EXCEPTION to be already performed */
PRIVATE inline void FFPU set_exception_status(uae_u32 new_status)
{ FPU fpsr.exception_status = exception_mac2host[new_status >> 8]; }
#endif /* FPU_USE_X86_EXCEPTIONS */
#ifdef FPU_USE_X86_ACCRUED_EXCEPTIONS
/* Lookup tables */
PRIVATE uae_u32 accrued_exception_host2mac[ 0x40 ];
PRIVATE uae_u32 accrued_exception_mac2host[ 0x20 ];
/* Initialize native accrued exception management */
PUBLIC void FFPU fpu_init_native_accrued_exceptions(void);
/* Return m68k accrued exception byte */
PRIVATE inline uae_u32 FFPU get_accrued_exception(void)
{ return accrued_exception_host2mac[FPU fpsr.accrued_exception & (SW_PE|SW_UE|SW_OE|SW_ZE|SW_DE|SW_IE)]; }
/* Set new accrued exception byte */
PRIVATE inline void FFPU set_accrued_exception(uae_u32 new_status)
{ FPU fpsr.accrued_exception = accrued_exception_mac2host[(new_status & 0xF8) >> 3]; }
#endif /* FPU_USE_X86_ACCRUED_EXCEPTIONS */
/* -------------------------------------------------------------------------- */
/* --- Default Exceptions Handling --- */
/* -------------------------------------------------------------------------- */
#ifdef FPU_USE_GENERIC_EXCEPTIONS
/* Initialize native exception management */
static inline void FFPU fpu_init_native_exceptions(void)
{ }
/* Return m68k floating-point exception status */
PRIVATE inline uae_u32 FFPU get_exception_status(void)
{ return FPU fpsr.exception_status; }
/* Set new exception status. Assumes mask against FPSR_EXCEPTION to be already performed */
PRIVATE inline void FFPU set_exception_status(uae_u32 new_status)
{ FPU fpsr.exception_status = new_status; }
#endif /* FPU_USE_GENERIC_EXCEPTIONS */
#ifdef FPU_USE_GENERIC_ACCRUED_EXCEPTIONS
/* Initialize native accrued exception management */
PRIVATE inline void FFPU fpu_init_native_accrued_exceptions(void)
{ }
/* Return m68k accrued exception byte */
PRIVATE inline uae_u32 FFPU get_accrued_exception(void)
{ return FPU fpsr.accrued_exception; }
/* Set new accrued exception byte */
PRIVATE inline void FFPU set_accrued_exception(uae_u32 new_status)
{ FPU fpsr.accrued_exception = new_status; }
#endif /* FPU_USE_GENERIC_ACCRUED_EXCEPTIONS */
#endif /* FPU_EXCEPTIONS_H */

View File

@ -0,0 +1,169 @@
/*
* fpu/flags.cpp - Floating-point flags
*
* Basilisk II (C) 1997-2008 Christian Bauer
*
* MC68881/68040 fpu emulation
*
* Original UAE FPU, copyright 1996 Herman ten Brugge
* Rewrite for x86, copyright 1999-2000 Lauri Pesonen
* New framework, copyright 2000 Gwenole Beauchesne
* Adapted for JIT compilation (c) Bernd Meyer, 2000
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* NOTE: this file shall be included only from fpu/fpu_*.cpp */
#undef PRIVATE
#define PRIVATE /**/
#undef PUBLIC
#define PUBLIC /**/
#undef FFPU
#define FFPU /**/
#undef FPU
#define FPU fpu.
/* -------------------------------------------------------------------------- */
/* --- Native X86 floating-point flags --- */
/* -------------------------------------------------------------------------- */
#ifdef FPU_USE_X86_FLAGS
/* Initialization */
void FFPU fpu_init_native_fflags(void)
{
// Adapted from fpu_x86.cpp
#define SW_Z_I_NAN_MASK (SW_C0|SW_C2|SW_C3)
#define SW_Z (SW_C3)
#define SW_I (SW_C0|SW_C2)
#define SW_NAN (SW_C0)
#define SW_FINITE (SW_C2)
#define SW_EMPTY_REGISTER (SW_C0|SW_C3)
#define SW_DENORMAL (SW_C2|SW_C3)
#define SW_UNSUPPORTED (0)
#define SW_N (SW_C1)
// Sanity checks
#if (SW_Z != NATIVE_FFLAG_ZERO)
#error "Incorrect X86 Z fflag"
#endif
#if (SW_I != NATIVE_FFLAG_INFINITY)
#error "Incorrect X86 I fflag"
#endif
#if (SW_N != NATIVE_FFLAG_NEGATIVE)
#error "Incorrect X86 N fflag"
#endif
#if (SW_NAN != NATIVE_FFLAG_NAN)
#error "Incorrect X86 NAN fflag"
#endif
// Native status word to m68k mappings
for (uae_u32 i = 0; i < 0x48; i++) {
to_m68k_fpcond[i] = 0;
const uae_u32 native_fpcond = i << 8;
switch (native_fpcond & SW_Z_I_NAN_MASK) {
#ifndef FPU_UAE
// gb-- enabling it would lead to incorrect drawing of digits
// in Speedometer Performance Test
case SW_UNSUPPORTED:
#endif
case SW_NAN:
case SW_EMPTY_REGISTER:
to_m68k_fpcond[i] |= FPSR_CCB_NAN;
break;
case SW_FINITE:
case SW_DENORMAL:
break;
case SW_I:
to_m68k_fpcond[i] |= FPSR_CCB_INFINITY;
break;
case SW_Z:
to_m68k_fpcond[i] |= FPSR_CCB_ZERO;
break;
}
if (native_fpcond & SW_N)
to_m68k_fpcond[i] |= FPSR_CCB_NEGATIVE;
}
// m68k to native status word mappings
for (uae_u32 i = 0; i < 0x10; i++) {
const uae_u32 m68k_fpcond = i << 24;
if (m68k_fpcond & FPSR_CCB_NAN)
to_host_fpcond[i] = SW_NAN;
else if (m68k_fpcond & FPSR_CCB_ZERO)
to_host_fpcond[i] = SW_Z;
else if (m68k_fpcond & FPSR_CCB_INFINITY)
to_host_fpcond[i] = SW_I;
else
to_host_fpcond[i] = SW_FINITE;
if (m68k_fpcond & FPSR_CCB_NEGATIVE)
to_host_fpcond[i] |= SW_N;
}
// truth-table for FPU conditions
for (uae_u32 host_fpcond = 0; host_fpcond < 0x08; host_fpcond++) {
// host_fpcond: C3 on bit 2, C1 and C0 are respectively on bits 1 and 0
const uae_u32 real_host_fpcond = ((host_fpcond & 4) << 12) | ((host_fpcond & 3) << 8);
const bool N = ((real_host_fpcond & NATIVE_FFLAG_NEGATIVE) == NATIVE_FFLAG_NEGATIVE);
const bool Z = ((real_host_fpcond & NATIVE_FFLAG_ZERO) == NATIVE_FFLAG_ZERO);
const bool NaN = ((real_host_fpcond & NATIVE_FFLAG_NAN) == NATIVE_FFLAG_NAN);
int value;
for (uae_u32 m68k_fpcond = 0; m68k_fpcond < 0x20; m68k_fpcond++) {
switch (m68k_fpcond) {
case 0x00: value = 0; break; // False
case 0x01: value = Z; break; // Equal
case 0x02: value = !(NaN || Z || N); break; // Ordered Greater Than
case 0x03: value = Z || !(NaN || N); break; // Ordered Greater Than or Equal
case 0x04: value = N && !(NaN || Z); break; // Ordered Less Than
case 0x05: value = Z || (N && !NaN); break; // Ordered Less Than or Equal
case 0x06: value = !(NaN || Z); break; // Ordered Greater or Less Than
case 0x07: value = !NaN; break; // Ordered
case 0x08: value = NaN; break; // Unordered
case 0x09: value = NaN || Z; break; // Unordered or Equal
case 0x0a: value = NaN || !(N || Z); break; // Unordered or Greater Than
case 0x0b: value = NaN || Z || !N; break; // Unordered or Greater or Equal
case 0x0c: value = NaN || (N && !Z); break; // Unordered or Less Than
case 0x0d: value = NaN || Z || N; break; // Unordered or Less or Equal
case 0x0e: value = !Z; break; // Not Equal
case 0x0f: value = 1; break; // True
case 0x10: value = 0; break; // Signaling False
case 0x11: value = Z; break; // Signaling Equal
case 0x12: value = !(NaN || Z || N); break; // Greater Than
case 0x13: value = Z || !(NaN || N); break; // Greater Than or Equal
case 0x14: value = N && !(NaN || Z); break; // Less Than
case 0x15: value = Z || (N && !NaN); break; // Less Than or Equal
case 0x16: value = !(NaN || Z); break; // Greater or Less Than
case 0x17: value = !NaN; break; // Greater, Less or Equal
case 0x18: value = NaN; break; // Not Greater, Less or Equal
case 0x19: value = NaN || Z; break; // Not Greater or Less Than
case 0x1a: value = NaN || !(N || Z); break; // Not Less Than or Equal
case 0x1b: value = NaN || Z || !N; break; // Not Less Than
case 0x1c: value = NaN || (N && !Z); break; // Not Greater Than or Equal
// case 0x1c: value = !Z && (NaN || N); break; // Not Greater Than or Equal
case 0x1d: value = NaN || Z || N; break; // Not Greater Than
case 0x1e: value = !Z; break; // Signaling Not Equal
case 0x1f: value = 1; break; // Signaling True
default: value = -1;
}
fpcond_truth_table[m68k_fpcond][host_fpcond] = value;
}
}
}
#endif

View File

@ -0,0 +1,223 @@
/*
* fpu/flags.h - Floating-point flags
*
* Basilisk II (C) 1997-2008 Christian Bauer
*
* MC68881/68040 fpu emulation
*
* Original UAE FPU, copyright 1996 Herman ten Brugge
* Rewrite for x86, copyright 1999-2000 Lauri Pesonen
* New framework, copyright 2000 Gwenole Beauchesne
* Adapted for JIT compilation (c) Bernd Meyer, 2000
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This 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 FPU_FLAGS_H
#define FPU_FLAGS_H
/* NOTE: this file shall be included only from fpu/fpu_*.cpp */
#undef PUBLIC
#define PUBLIC extern
#undef PRIVATE
#define PRIVATE static
#undef FFPU
#define FFPU /**/
#undef FPU
#define FPU fpu.
/* Defaults to generic flags */
#define FPU_USE_GENERIC_FLAGS
/* -------------------------------------------------------------------------- */
/* --- Selection of floating-point flags handling mode --- */
/* -------------------------------------------------------------------------- */
/* Optimized i386 fpu core must use native flags */
#if defined(FPU_X86) && defined(USE_X87_ASSEMBLY)
# undef FPU_USE_GENERIC_FLAGS
# define FPU_USE_X86_FLAGS
#endif
/* Old UAE FPU core can use native flags */
#if defined(FPU_UAE) && defined(USE_X87_ASSEMBLY)
# undef FPU_USE_GENERIC_FLAGS
# define FPU_USE_X86_FLAGS
#endif
/* IEEE-based implementation must use lazy flag evaluation */
#if defined(FPU_IEEE)
# undef FPU_USE_GENERIC_FLAGS
# define FPU_USE_LAZY_FLAGS
#endif
/* JIT Compilation for FPU only works with lazy evaluation of FPU flags */
#if defined(FPU_IEEE) && defined(USE_X87_ASSEMBLY) && defined(USE_JIT_FPU)
# undef FPU_USE_GENERIC_FLAGS
# define FPU_USE_LAZY_FLAGS
#endif
#ifdef FPU_IMPLEMENTATION
/* -------------------------------------------------------------------------- */
/* --- Native X86 Floating-Point Flags --- */
/* -------------------------------------------------------------------------- */
/* FPU_X86 has its own set of lookup functions */
#ifdef FPU_USE_X86_FLAGS
#define FPU_USE_NATIVE_FLAGS
#define NATIVE_FFLAG_NEGATIVE 0x0200
#define NATIVE_FFLAG_ZERO 0x4000
#define NATIVE_FFLAG_INFINITY 0x0500
#define NATIVE_FFLAG_NAN 0x0100
/* Translation tables between native and m68k floating-point flags */
PRIVATE uae_u32 to_m68k_fpcond[0x48];
PRIVATE uae_u32 to_host_fpcond[0x10];
/* Truth table for floating-point condition codes */
PRIVATE uae_u32 fpcond_truth_table[32][8]; // 32 m68k conditions x 8 host condition codes
/* Initialization */
PUBLIC void FFPU fpu_init_native_fflags(void);
#ifdef FPU_UAE
/* Native to m68k floating-point condition codes */
PRIVATE inline uae_u32 FFPU get_fpccr(void)
{ return to_m68k_fpcond[(FPU fpsr.condition_codes >> 8) & 0x47]; }
/* M68k to native floating-point condition codes */
PRIVATE inline void FFPU set_fpccr(uae_u32 new_fpcond)
/* Precondition: new_fpcond is only valid for floating-point condition codes */
{ FPU fpsr.condition_codes = to_host_fpcond[new_fpcond >> 24]; }
/* Make FPSR according to the value passed in argument */
PRIVATE inline void FFPU make_fpsr(fpu_register const & r)
{ uae_u16 sw; __asm__ __volatile__ ("fxam\n\tfnstsw %0" : "=r" (sw) : "f" (r)); FPU fpsr.condition_codes = sw; }
/* Return the corresponding ID of the current floating-point condition codes */
/* NOTE: only valid for evaluation of a condition */
PRIVATE inline int FFPU host_fpcond_id(void)
{ return ((FPU fpsr.condition_codes >> 12) & 4) | ((FPU fpsr.condition_codes >> 8) & 3); }
/* Return true if the floating-point condition is satisfied */
PRIVATE inline bool FFPU fpcctrue(int condition)
{ return fpcond_truth_table[condition][host_fpcond_id()]; }
#endif /* FPU_UAE */
/* Return the address of the floating-point condition codes truth table */
static inline uae_u8 * const FFPU address_of_fpcond_truth_table(void)
{ return ((uae_u8*)&fpcond_truth_table[0][0]); }
#endif /* FPU_X86_USE_NATIVE_FLAGS */
/* -------------------------------------------------------------------------- */
/* --- Use Original M68K FPU Mappings --- */
/* -------------------------------------------------------------------------- */
#ifdef FPU_USE_GENERIC_FLAGS
#undef FPU_USE_NATIVE_FLAGS
#define NATIVE_FFLAG_NEGATIVE 0x08000000
#define NATIVE_FFLAG_ZERO 0x04000000
#define NATIVE_FFLAG_INFINITY 0x02000000
#define NATIVE_FFLAG_NAN 0x01000000
/* Initialization - NONE */
PRIVATE inline void FFPU fpu_init_native_fflags(void)
{ }
/* Native to m68k floating-point condition codes - SELF */
PRIVATE inline uae_u32 FFPU get_fpccr(void)
{ return FPU fpsr.condition_codes; }
/* M68k to native floating-point condition codes - SELF */
PRIVATE inline void FFPU set_fpccr(uae_u32 new_fpcond)
{ FPU fpsr.condition_codes = new_fpcond; }
#endif /* FPU_USE_GENERIC_FLAGS */
/* -------------------------------------------------------------------------- */
/* --- Use Lazy Flags Evaluation --- */
/* -------------------------------------------------------------------------- */
#ifdef FPU_USE_LAZY_FLAGS
#undef FPU_USE_NATIVE_FLAGS
#define NATIVE_FFLAG_NEGATIVE 0x08000000
#define NATIVE_FFLAG_ZERO 0x04000000
#define NATIVE_FFLAG_INFINITY 0x02000000
#define NATIVE_FFLAG_NAN 0x01000000
/* Initialization - NONE */
PRIVATE inline void FFPU fpu_init_native_fflags(void)
{ }
/* Native to m68k floating-point condition codes - SELF */
PRIVATE inline uae_u32 FFPU get_fpccr(void)
{
uae_u32 fpccr = 0;
if (isnan(FPU result))
fpccr |= FPSR_CCB_NAN;
else if (FPU result == 0.0)
fpccr |= FPSR_CCB_ZERO;
else if (FPU result < 0.0)
fpccr |= FPSR_CCB_NEGATIVE;
if (isinf(FPU result))
fpccr |= FPSR_CCB_INFINITY;
return fpccr;
}
/* M68k to native floating-point condition codes - SELF */
PRIVATE inline void FFPU set_fpccr(uae_u32 new_fpcond)
{
if (new_fpcond & FPSR_CCB_NAN)
make_nan(FPU result);
else if (new_fpcond & FPSR_CCB_ZERO)
FPU result = 0.0;
else if (new_fpcond & FPSR_CCB_NEGATIVE)
FPU result = -1.0;
else
FPU result = +1.0;
/* gb-- where is Infinity ? */
}
/* Make FPSR according to the value passed in argument */
PRIVATE inline void FFPU make_fpsr(fpu_register const & r)
{ FPU result = r; }
#endif /* FPU_USE_LAZY_FLAGS */
#endif
/* -------------------------------------------------------------------------- */
/* --- Common methods --- */
/* -------------------------------------------------------------------------- */
/* Return the address of the floating-point condition codes register */
static inline uae_u32 * const FFPU address_of_fpccr(void)
{ return ((uae_u32 *)& FPU fpsr.condition_codes); }
#endif /* FPU_FLAGS_H */

View File

@ -0,0 +1,49 @@
/*
* fpu/fpu.h - public header
*
* Basilisk II (C) 1997-2008 Christian Bauer
*
* MC68881/68040 fpu emulation
*
* Original UAE FPU, copyright 1996 Herman ten Brugge
* Rewrite for x86, copyright 1999-2000 Lauri Pesonen
* New framework, copyright 2000 Gwenole Beauchesne
* Adapted for JIT compilation (c) Bernd Meyer, 2000
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This 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 FPU_PUBLIC_HEADER_H
#define FPU_PUBLIC_HEADER_H
#ifndef FPU_DEBUG
#define FPU_DEBUG 0
#endif
#if FPU_DEBUG
#define fpu_debug(args) printf args;
#define FPU_DUMP_REGISTERS 0
#define FPU_DUMP_FIRST_BYTES 0
#else
#define fpu_debug(args) ;
#undef FPU_DUMP_REGISTERS
#undef FPU_DUMP_FIRST_BYTES
#endif
#include "sysdeps.h"
#include "fpu/types.h"
#include "fpu/core.h"
#endif /* FPU_PUBLIC_HEADER_H */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,149 @@
/*
* fpu/fpu_uae.h - Extra Definitions for the old UAE FPU core
*
* Basilisk II (C) 1997-2008 Christian Bauer
*
* MC68881/68040 fpu emulation
*
* Original UAE FPU, copyright 1996 Herman ten Brugge
* Rewrite for x86, copyright 1999-2000 Lauri Pesonen
* New framework, copyright 2000 Gwenole Beauchesne
* Adapted for JIT compilation (c) Bernd Meyer, 2000
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This 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 FPU_IEEE_H
#define FPU_IEEE_H
/* NOTE: this file shall be included from fpu/fpu_uae.cpp */
#undef PUBLIC
#define PUBLIC extern
#undef PRIVATE
#define PRIVATE static
#undef FFPU
#define FFPU /**/
#undef FPU
#define FPU fpu.
// Lauri-- full words to avoid partial register stalls.
struct double_flags {
uae_u32 in_range;
uae_u32 zero;
uae_u32 infinity;
uae_u32 nan;
uae_u32 negative;
};
PRIVATE double_flags fl_source;
PRIVATE double_flags fl_dest;
PRIVATE inline void FFPU get_dest_flags(fpu_register const & r);
PRIVATE inline void FFPU get_source_flags(fpu_register const & r);
PRIVATE inline void FFPU make_nan(fpu_register & r);
PRIVATE inline void FFPU make_zero_positive(fpu_register & r);
PRIVATE inline void FFPU make_zero_negative(fpu_register & r);
PRIVATE inline void FFPU make_inf_positive(fpu_register & r);
PRIVATE inline void FFPU make_inf_negative(fpu_register & r);
PRIVATE inline void FFPU fast_scale(fpu_register & r, int add);
PRIVATE inline fpu_register FFPU fast_fgetexp(fpu_register const & r);
// May be optimized for particular processors
#ifndef FPU_USE_NATIVE_FLAGS
PRIVATE inline void FFPU make_fpsr(fpu_register const & r);
#endif
// Normalize to range 1..2
PRIVATE inline void FFPU fast_remove_exponent(fpu_register & r);
// The sign of the quotient is the exclusive-OR of the sign bits
// of the source and destination operands.
PRIVATE inline uae_u32 FFPU get_quotient_sign(
fpu_register const & ra, fpu_register const & rb
);
// Quotient Byte is loaded with the sign and least significant
// seven bits of the quotient.
PRIVATE inline void FFPU make_quotient(
fpu_register const & quotient, uae_u32 sign
);
// to_single
PRIVATE inline fpu_register FFPU make_single(
uae_u32 value
);
// from_single
PRIVATE inline uae_u32 FFPU extract_single(
fpu_register const & src
);
// to_exten
PRIVATE inline fpu_register FFPU make_extended(
uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3
);
/*
Would be so much easier with full size floats :(
... this is so vague.
*/
// to_exten_no_normalize
PRIVATE inline void FFPU make_extended_no_normalize(
uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3, fpu_register & result
);
// from_exten
PRIVATE inline void FFPU extract_extended(fpu_register const & src,
uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3
);
// to_double
PRIVATE inline fpu_register FFPU make_double(
uae_u32 wrd1, uae_u32 wrd2
);
// from_double
PRIVATE inline void FFPU extract_double(fpu_register const & src,
uae_u32 * wrd1, uae_u32 * wrd2
);
PRIVATE inline fpu_register FFPU make_packed(
uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3
);
PRIVATE inline void FFPU extract_packed(
fpu_register const & src, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3
);
PRIVATE inline int FFPU get_fp_value(
uae_u32 opcode, uae_u16 extra, fpu_register & src
);
PRIVATE inline int FFPU put_fp_value(
uae_u32 opcode, uae_u16 extra, fpu_register const & value
);
PRIVATE inline int FFPU get_fp_ad(
uae_u32 opcode, uae_u32 * ad
);
PRIVATE inline int FFPU fpp_cond(
int condition
);
#endif /* FPU_IEEE_H */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,212 @@
/*
* fpu/fpu_uae.h - Extra Definitions for the old UAE FPU core
*
* Basilisk II (C) 1997-2008 Christian Bauer
*
* MC68881/68040 fpu emulation
*
* Original UAE FPU, copyright 1996 Herman ten Brugge
* Rewrite for x86, copyright 1999-2000 Lauri Pesonen
* New framework, copyright 2000 Gwenole Beauchesne
* Adapted for JIT compilation (c) Bernd Meyer, 2000
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This 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 FPU_UAE_H
#define FPU_UAE_H
// Only define if you have IEEE 64 bit doubles.
#define FPU_HAVE_IEEE_DOUBLE 1
/* NOTE: this file shall be included from fpu/fpu_uae.cpp */
#undef PUBLIC
#define PUBLIC extern
#undef PRIVATE
#define PRIVATE static
#undef FFPU
#define FFPU /**/
#undef FPU
#define FPU fpu.
enum {
#ifdef WORDS_BIGENDIAN
FHI = 0,
FLO = 1
#else
FHI = 1,
FLO = 0
#endif
};
// Floating-point rounding support
PRIVATE inline fpu_register round_to_zero(fpu_register const & x);
PRIVATE inline fpu_register round_to_nearest(fpu_register const & x);
#if FPU_HAVE_IEEE_DOUBLE
// Lauri-- full words to avoid partial register stalls.
struct double_flags {
uae_u32 in_range;
uae_u32 zero;
uae_u32 infinity;
uae_u32 nan;
uae_u32 negative;
};
PRIVATE double_flags fl_source;
PRIVATE double_flags fl_dest;
PRIVATE inline void FFPU get_dest_flags(fpu_register const & r);
PRIVATE inline void FFPU get_source_flags(fpu_register const & r);
PRIVATE inline bool FFPU do_isnan(fpu_register const & r);
PRIVATE inline bool FFPU do_isinf(fpu_register const & r);
PRIVATE inline bool FFPU do_isneg(fpu_register const & r);
PRIVATE inline bool FFPU do_iszero(fpu_register const & r);
PRIVATE inline void FFPU make_nan(fpu_register & r);
PRIVATE inline void FFPU make_zero_positive(fpu_register & r);
PRIVATE inline void FFPU make_zero_negative(fpu_register & r);
PRIVATE inline void FFPU make_inf_positive(fpu_register & r);
PRIVATE inline void FFPU make_inf_negative(fpu_register & r);
PRIVATE inline void FFPU fast_scale(fpu_register & r, int add);
PRIVATE inline fpu_register FFPU fast_fgetexp(fpu_register const & r);
// May be optimized for particular processors
#ifndef FPU_USE_NATIVE_FLAGS
PRIVATE inline void FFPU make_fpsr(fpu_register const & r);
#endif
// Normalize to range 1..2
PRIVATE inline void FFPU fast_remove_exponent(fpu_register & r);
// The sign of the quotient is the exclusive-OR of the sign bits
// of the source and destination operands.
PRIVATE inline uae_u32 FFPU get_quotient_sign(
fpu_register const & ra, fpu_register const & rb
);
// Quotient Byte is loaded with the sign and least significant
// seven bits of the quotient.
PRIVATE inline void FFPU make_quotient(
fpu_register const & quotient, uae_u32 sign
);
// to_single
PRIVATE inline fpu_register FFPU make_single(
uae_u32 value
);
// from_single
PRIVATE inline uae_u32 FFPU extract_single(
fpu_register const & src
);
// to_exten
PRIVATE inline fpu_register FFPU make_extended(
uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3
);
/*
Would be so much easier with full size floats :(
... this is so vague.
*/
// to_exten_no_normalize
PRIVATE inline void FFPU make_extended_no_normalize(
uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3, fpu_register & result
);
// from_exten
PRIVATE inline void FFPU extract_extended(fpu_register const & src,
uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3
);
// to_double
PRIVATE inline fpu_register FFPU make_double(
uae_u32 wrd1, uae_u32 wrd2
);
// from_double
PRIVATE inline void FFPU extract_double(fpu_register const & src,
uae_u32 * wrd1, uae_u32 * wrd2
);
#else /* !FPU_HAVE_IEEE_DOUBLE */
// FIXME: may be optimized for particular processors
#ifndef FPU_USE_NATIVE_FLAGS
PRIVATE inline void FFPU make_fpsr(fpu_register const & r);
#endif
// to_single
PRIVATE inline fpu_register make_single(
uae_u32 value
);
// from_single
PRIVATE inline uae_u32 FFPU extract_single(
fpu_register const & src
);
// to exten
PRIVATE inline fpu_register FFPU make_extended(
uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3
);
// from_exten
PRIVATE inline void FFPU extract_extended(
fpu_register const & src, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3
);
// to_double
PRIVATE inline fpu_register FFPU make_double(
uae_u32 wrd1, uae_u32 wrd2
);
// from_double
PRIVATE inline void FFPU extract_double(
fpu_register const & src, uae_u32 * wrd1, uae_u32 * wrd2
);
#endif /* FPU_HAVE_IEEE_DOUBLE */
PRIVATE inline fpu_register FFPU make_packed(
uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3
);
PRIVATE inline void FFPU extract_packed(
fpu_register const & src, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3
);
PRIVATE inline int FFPU get_fp_value(
uae_u32 opcode, uae_u16 extra, fpu_register & src
);
PRIVATE inline int FFPU put_fp_value(
uae_u32 opcode, uae_u16 extra, fpu_register const & value
);
PRIVATE inline int FFPU get_fp_ad(
uae_u32 opcode, uae_u32 * ad
);
PRIVATE inline int FFPU fpp_cond(
int condition
);
#endif /* FPU_UAE_H */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,361 @@
/*
* fpu/fpu_x86.h - Extra Definitions for the X86 assembly FPU core
*
* Basilisk II (C) 1997-2008 Christian Bauer
*
* MC68881/68040 fpu emulation
*
* Original UAE FPU, copyright 1996 Herman ten Brugge
* Rewrite for x86, copyright 1999-2000 Lauri Pesonen
* New framework, copyright 2000 Gwenole Beauchesne
* Adapted for JIT compilation (c) Bernd Meyer, 2000
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This 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 FPU_X86_H
#define FPU_X86_H
/* NOTE: this file shall be included from fpu/fpu_x86.cpp */
#undef PUBLIC
#define PUBLIC extern
#undef PRIVATE
#define PRIVATE static
#undef FFPU
#define FFPU /**/
#undef FPU
#define FPU fpu.
// Status word
PRIVATE uae_u32 x86_status_word;
PRIVATE uae_u32 x86_status_word_accrued;
// FPU jump table
typedef void REGPARAM2 ( *fpuop_func )( uae_u32, uae_u32 );
PRIVATE fpuop_func fpufunctbl[65536];
// FPU consistency
PRIVATE uae_u32 checked_sw_atstart;
// FMOVECR constants supported byt x86 FPU
PRIVATE fpu_register const_pi;
PRIVATE fpu_register const_lg2;
PRIVATE fpu_register const_l2e;
PRIVATE fpu_register const_z;
PRIVATE fpu_register const_ln2;
PRIVATE fpu_register const_1;
// FMOVECR constants not not suported by x86 FPU
PRIVATE fpu_register const_e;
PRIVATE fpu_register const_log_10_e;
PRIVATE fpu_register const_ln_10;
PRIVATE fpu_register const_1e1;
PRIVATE fpu_register const_1e2;
PRIVATE fpu_register const_1e4;
PRIVATE fpu_register const_1e8;
PRIVATE fpu_register const_1e16;
PRIVATE fpu_register const_1e32;
PRIVATE fpu_register const_1e64;
PRIVATE fpu_register const_1e128;
PRIVATE fpu_register const_1e256;
PRIVATE fpu_register const_1e512;
PRIVATE fpu_register const_1e1024;
PRIVATE fpu_register const_1e2048;
PRIVATE fpu_register const_1e4096;
// Saved host FPU state
PRIVATE uae_u8 m_fpu_state_original[108]; // 90/94/108
/* -------------------------------------------------------------------------- */
/* --- Methods --- */
/* -------------------------------------------------------------------------- */
// Debug support functions
PRIVATE void FFPU dump_first_bytes_buf(char *b, uae_u8* buf, uae_s32 actual);
PRIVATE char * FFPU etos(fpu_register const & e) REGPARAM;
// FPU consistency
PRIVATE void FFPU FPU_CONSISTENCY_CHECK_START(void);
PRIVATE void FFPU FPU_CONSISTENCY_CHECK_STOP(const char *name);
// Get special floating-point value class
PRIVATE __inline__ uae_u32 FFPU IS_INFINITY (fpu_register const & f);
PRIVATE __inline__ uae_u32 FFPU IS_NAN (fpu_register const & f);
PRIVATE __inline__ uae_u32 FFPU IS_ZERO (fpu_register const & f);
PRIVATE __inline__ uae_u32 FFPU IS_NEGATIVE (fpu_register const & f);
// Make a special floating-point value
PRIVATE __inline__ void FFPU MAKE_NAN (fpu_register & f);
PRIVATE __inline__ void FFPU MAKE_INF_POSITIVE (fpu_register & f);
PRIVATE __inline__ void FFPU MAKE_INF_NEGATIVE (fpu_register & f);
PRIVATE __inline__ void FFPU MAKE_ZERO_POSITIVE (fpu_register & f);
PRIVATE __inline__ void FFPU MAKE_ZERO_NEGATIVE (fpu_register & f);
// Conversion from extended floating-point values
PRIVATE uae_s32 FFPU extended_to_signed_32 ( fpu_register const & f ) REGPARAM;
PRIVATE uae_s16 FFPU extended_to_signed_16 ( fpu_register const & f ) REGPARAM;
PRIVATE uae_s8 FFPU extended_to_signed_8 ( fpu_register const & f ) REGPARAM;
PRIVATE fpu_double FFPU extended_to_double( fpu_register const & f ) REGPARAM;
PRIVATE uae_u32 FFPU from_single ( fpu_register const & f ) REGPARAM;
PRIVATE void FFPU from_exten ( fpu_register const & f, uae_u32 *wrd1, uae_u32 *wrd2, uae_u32 *wrd3 ) REGPARAM;
PRIVATE void FFPU from_double ( fpu_register const & f, uae_u32 *wrd1, uae_u32 *wrd2 ) REGPARAM;
PRIVATE void FFPU from_pack (fpu_double src, uae_u32 * wrd1, uae_u32 * wrd2, uae_u32 * wrd3) REGPARAM;
// Conversion to extended floating-point values
PRIVATE void FFPU signed_to_extended ( uae_s32 x, fpu_register & f ) REGPARAM;
PRIVATE void FFPU double_to_extended ( double x, fpu_register & f ) REGPARAM;
PRIVATE void FFPU to_single ( uae_u32 src, fpu_register & f ) REGPARAM;
PRIVATE void FFPU to_exten_no_normalize ( uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3, fpu_register & f ) REGPARAM;
PRIVATE void FFPU to_exten ( uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3, fpu_register & f ) REGPARAM;
PRIVATE void FFPU to_double ( uae_u32 wrd1, uae_u32 wrd2, fpu_register & f ) REGPARAM;
PRIVATE fpu_double FFPU to_pack(uae_u32 wrd1, uae_u32 wrd2, uae_u32 wrd3) REGPARAM;
// Atomic floating-point arithmetic operations
PRIVATE void FFPU do_fmove ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fmove_no_status ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fint ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fintrz ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fsqrt ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_ftst ( fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fsinh ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_flognp1 ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fetoxm1 ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_ftanh ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fatan ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fasin ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fatanh ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fetox ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_ftwotox ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_ftentox ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_flogn ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_flog10 ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_flog2 ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_facos ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fcosh ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fsin ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_ftan ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fabs ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fneg ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fcos ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fgetexp ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fgetman ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fdiv ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fmod ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_frem ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fmod_dont_set_cw ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_frem_dont_set_cw ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fadd ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fmul ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fsgldiv ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fscale ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fsglmul ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fsub ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fsincos ( fpu_register & dest_sin, fpu_register & dest_cos, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fcmp ( fpu_register & dest, fpu_register const & src ) REGPARAM;
PRIVATE void FFPU do_fldpi ( fpu_register & dest ) REGPARAM;
PRIVATE void FFPU do_fldlg2 ( fpu_register & dest ) REGPARAM;
PRIVATE void FFPU do_fldl2e ( fpu_register & dest ) REGPARAM;
PRIVATE void FFPU do_fldz ( fpu_register & dest ) REGPARAM;
PRIVATE void FFPU do_fldln2 ( fpu_register & dest ) REGPARAM;
PRIVATE void FFPU do_fld1 ( fpu_register & dest ) REGPARAM;
// Instructions handlers
PRIVATE void REGPARAM2 FFPU fpuop_illg( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmove_2_ea( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_none_2_Dreg( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpiar_2_Dreg( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_2_Dreg( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_2_Dreg( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_fpiar_2_Dreg( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpiar_2_Dreg( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_2_Dreg( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_fpiar_2_Dreg( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Dreg_2_none( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Dreg_2_fpiar( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Dreg_2_fpsr( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Dreg_2_fpsr_fpiar( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Dreg_2_fpcr( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Dreg_2_fpcr_fpiar( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Dreg_2_fpcr_fpsr( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Dreg_2_fpcr_fpsr_fpiar( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_none_2_Areg( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpiar_2_Areg( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_2_Areg( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_2_Areg( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_fpiar_2_Areg( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpiar_2_Areg( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_2_Areg( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_fpiar_2_Areg( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Areg_2_none( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Areg_2_fpiar( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Areg_2_fpsr( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Areg_2_fpsr_fpiar( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Areg_2_fpcr( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Areg_2_fpcr_fpiar( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Areg_2_fpcr_fpsr( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Areg_2_fpcr_fpsr_fpiar( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_none_2_Mem_predecrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpiar_2_Mem_predecrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_2_Mem_predecrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_fpiar_2_Mem_predecrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_2_Mem_predecrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpiar_2_Mem_predecrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_2_Mem_predecrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_fpiar_2_Mem_predecrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_none_2_Mem_postincrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpiar_2_Mem_postincrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_2_Mem_postincrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_fpiar_2_Mem_postincrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_2_Mem_postincrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpiar_2_Mem_postincrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_2_Mem_postincrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_fpiar_2_Mem_postincrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_none_2_Mem( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpiar_2_Mem( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_2_Mem( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpsr_fpiar_2_Mem( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_2_Mem( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpiar_2_Mem( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_2_Mem( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpcr_fpsr_fpiar_2_Mem( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_none_predecrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpiar_predecrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpsr_predecrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpsr_fpiar_predecrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_predecrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpiar_predecrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_predecrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_fpiar_predecrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_none_postincrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpiar_postincrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpsr_postincrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpsr_fpiar_postincrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_postincrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpiar_postincrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_postincrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_fpiar_postincrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_none_2_Mem( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpiar_2_Mem( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpsr_2_Mem( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpsr_fpiar_2_Mem( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_2_Mem( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpiar_2_Mem( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_2_Mem( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpcr_fpsr_fpiar_2_Mem( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_static_pred_postincrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_static_pred_predecrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_static_pred( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_dynamic_pred_postincrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_dynamic_pred_predecrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_dynamic_pred( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_static_postinc_postincrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_static_postinc_predecrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_static_postinc( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_dynamic_postinc_postincrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_dynamic_postinc_predecrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_Mem_2_fpp_dynamic_postinc( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_static_pred_postincrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_static_pred_predecrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_static_pred( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_dynamic_pred_postincrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_dynamic_pred_predecrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_dynamic_pred( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_static_postinc_postincrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_static_postinc_predecrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_static_postinc( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_dynamic_postinc_postincrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_dynamic_postinc_predecrement( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_fmovem_fpp_2_Mem_dynamic_postinc( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fldpi( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fldlg2( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_e( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fldl2e( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_log_10_e( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fldz( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fldln2( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_ln_10( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fld1( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e1( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e2( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e4( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e8( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e16( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e32( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e64( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e128( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e256( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e512( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e1024( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e2048( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_load_const_1e4096( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fmove( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fint( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fsinh( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fintrz( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fsqrt( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_flognp1( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fetoxm1( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_ftanh( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fatan( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fasin( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fatanh( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fsin( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_ftan( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fetox( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_ftwotox( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_ftentox( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_flogn( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_flog10( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_flog2( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fabs( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fcosh( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fneg( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_facos( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fcos( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fgetexp( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fgetman( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fdiv( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fmod( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_frem( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fadd( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fmul( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fsgldiv( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fscale( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fsglmul( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fsub( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fsincos( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_fcmp( uae_u32 opcode, uae_u32 extra );
PRIVATE void REGPARAM2 FFPU fpuop_do_ftst( uae_u32 opcode, uae_u32 extra );
// Get & Put floating-point values
PRIVATE int FFPU get_fp_value (uae_u32 opcode, uae_u32 extra, fpu_register & src) REGPARAM;
PRIVATE int FFPU put_fp_value (fpu_register const & value, uae_u32 opcode, uae_u32 extra) REGPARAM;
PRIVATE int FFPU get_fp_ad(uae_u32 opcode, uae_u32 * ad) REGPARAM;
// Floating-point condition-based instruction handlers
PRIVATE int FFPU fpp_cond(uae_u32 opcode, int condition) REGPARAM;
// Misc functions
PRIVATE void __inline__ FFPU set_host_fpu_control_word ();
PRIVATE void __inline__ FFPU SET_BSUN_ON_NAN ();
PRIVATE void __inline__ FFPU build_ex_status ();
PRIVATE void FFPU do_null_frestore ();
PRIVATE void FFPU build_fpp_opp_lookup_table ();
PRIVATE void FFPU set_constant ( fpu_register & f, char *name, double value, uae_s32 mult );
#endif /* FPU_X86_H */

View File

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

View File

@ -0,0 +1,147 @@
/*
* fpu/impl.h - extra functions and inline implementations
*
* Basilisk II (C) 1997-2008 Christian Bauer
*
* MC68881/68040 fpu emulation
*
* Original UAE FPU, copyright 1996 Herman ten Brugge
* Rewrite for x86, copyright 1999-2000 Lauri Pesonen
* New framework, copyright 2000 Gwenole Beauchesne
* Adapted for JIT compilation (c) Bernd Meyer, 2000
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This 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 FPU_IMPL_H
#define FPU_IMPL_H
/* NOTE: this file shall be included from fpu/core.h */
#undef PUBLIC
#define PUBLIC /**/
#undef PRIVATE
#define PRIVATE /**/
#undef FFPU
#define FFPU /**/
#undef FPU
#define FPU fpu.
/* -------------------------------------------------------------------------- */
/* --- X86 assembly fpu specific methods --- */
/* -------------------------------------------------------------------------- */
#ifdef FPU_X86
/* Return the floating-point status register in m68k format */
static inline uae_u32 FFPU get_fpsr(void)
{
return to_m68k_fpcond[(x86_status_word & 0x4700) >> 8]
| FPU fpsr.quotient
| exception_host2mac[x86_status_word & (SW_FAKE_BSUN|SW_PE|SW_UE|SW_OE|SW_ZE|SW_DE|SW_IE)]
| accrued_exception_host2mac[x86_status_word_accrued & (SW_PE|SW_UE|SW_OE|SW_ZE|SW_DE|SW_IE)]
;
}
/* Set the floating-point status register from an m68k format */
static inline void FFPU set_fpsr(uae_u32 new_fpsr)
{
x86_status_word = to_host_fpcond[(new_fpsr & FPSR_CCB) >> 24 ]
| exception_mac2host[(new_fpsr & FPSR_EXCEPTION_STATUS) >> 8];
x86_status_word_accrued = accrued_exception_mac2host[(new_fpsr & FPSR_ACCRUED_EXCEPTION) >> 3];
}
#endif
/* -------------------------------------------------------------------------- */
/* --- Original UAE and IEEE FPU core methods --- */
/* -------------------------------------------------------------------------- */
#ifndef FPU_X86
/* Return the floating-point status register in m68k format */
static inline uae_u32 FFPU get_fpsr(void)
{
uae_u32 condition_codes = get_fpccr();
uae_u32 exception_status = get_exception_status();
uae_u32 accrued_exception = get_accrued_exception();
uae_u32 quotient = FPU fpsr.quotient;
return (condition_codes | quotient | exception_status | accrued_exception);
}
/* Set the floating-point status register from an m68k format */
static inline void FFPU set_fpsr(uae_u32 new_fpsr)
{
set_fpccr ( new_fpsr & FPSR_CCB );
set_exception_status ( new_fpsr & FPSR_EXCEPTION_STATUS );
set_accrued_exception ( new_fpsr & FPSR_ACCRUED_EXCEPTION );
FPU fpsr.quotient = new_fpsr & FPSR_QUOTIENT;
}
#endif
/* -------------------------------------------------------------------------- */
/* --- Common routines for control word --- */
/* -------------------------------------------------------------------------- */
/* Return the floating-point control register in m68k format */
static inline uae_u32 FFPU get_fpcr(void)
{
uae_u32 rounding_precision = get_rounding_precision();
uae_u32 rounding_mode = get_rounding_mode();
return (rounding_precision | rounding_mode);
}
/* Set the floating-point control register from an m68k format */
static inline void FFPU set_fpcr(uae_u32 new_fpcr)
{
set_rounding_precision ( new_fpcr & FPCR_ROUNDING_PRECISION);
set_rounding_mode ( new_fpcr & FPCR_ROUNDING_MODE );
set_host_control_word();
}
/* -------------------------------------------------------------------------- */
/* --- Specific part to X86 assembly FPU --- */
/* -------------------------------------------------------------------------- */
#ifdef FPU_X86
/* Retrieve a floating-point register value and convert it to double precision */
static inline double FFPU fpu_get_register(int r)
{
double f;
__asm__ __volatile__("fldt %1\n\tfstpl %0" : "=m" (f) : "m" (FPU registers[r]));
return f;
}
#endif
/* -------------------------------------------------------------------------- */
/* --- Specific to original UAE or new IEEE-based FPU core --- */
/* -------------------------------------------------------------------------- */
#if defined(FPU_UAE) || defined(FPU_IEEE)
/* Retrieve a floating-point register value and convert it to double precision */
static inline double FFPU fpu_get_register(int r)
{
return FPU registers[r];
}
#endif
#endif /* FPU_IMPL_H */

View File

@ -0,0 +1,100 @@
/*
* fpu/mathlib.cpp - Floating-point math support library
*
* Basilisk II (C) 1997-2008 Christian Bauer
*
* MC68881/68040 fpu emulation
*
* Original UAE FPU, copyright 1996 Herman ten Brugge
* Rewrite for x86, copyright 1999-2001 Lauri Pesonen
* New framework, copyright 2000-2001 Gwenole Beauchesne
* Adapted for JIT compilation (c) Bernd Meyer, 2000-2001
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* NOTE: this file shall be included only from fpu/fpu_*.cpp */
#undef PRIVATE
#define PRIVATE static
#undef PUBLIC
#define PUBLIC /**/
#undef FFPU
#define FFPU /**/
#undef FPU
#define FPU fpu.
#if defined(FPU_IEEE) && defined(USE_X87_ASSEMBLY)
PRIVATE fpu_extended fp_do_pow(fpu_extended x, fpu_extended y)
{
fpu_extended value, exponent;
uae_s64 p = (uae_s64)y;
if (x == 0.0) {
if (y > 0.0)
return (y == (double) p && (p & 1) != 0 ? x : 0.0);
else if (y < 0.0)
return (y == (double) p && (-p & 1) != 0 ? 1.0 / x : 1.0 / fp_fabs (x));
}
if (y == (double) p) {
fpu_extended r = 1.0;
if (p == 0)
return 1.0;
if (p < 0) {
p = -p;
x = 1.0 / x;
}
while (1) {
if (p & 1)
r *= x;
p >>= 1;
if (p == 0)
return r;
x *= x;
}
}
__asm__ __volatile__("fyl2x" : "=t" (value) : "0" (x), "u" (1.0) : "st(1)");
__asm__ __volatile__("fmul %%st(1) # y * log2(x)\n\t"
"fst %%st(1)\n\t"
"frndint # int(y * log2(x))\n\t"
"fxch\n\t"
"fsub %%st(1) # fract(y * log2(x))\n\t"
"f2xm1 # 2^(fract(y * log2(x))) - 1\n\t"
: "=t" (value), "=u" (exponent) : "0" (y), "1" (value));
value += 1.0;
__asm__ __volatile__("fscale" : "=t" (value) : "0" (value), "u" (exponent));
return value;
}
PRIVATE fpu_extended fp_do_log1p(fpu_extended x)
{
// TODO: handle NaN and +inf/-inf
fpu_extended value;
// The fyl2xp1 can only be used for values in
// -1 + sqrt(2) / 2 <= x <= 1 - sqrt(2) / 2
// 0.29 is a safe value.
if (fp_fabs(x) <= 0.29)
__asm__ __volatile__("fldln2; fxch; fyl2xp1" : "=t" (value) : "0" (x));
else
__asm__ __volatile__("fldln2; fxch; fyl2x" : "=t" (value) : "0" (x + 1.0));
return value;
}
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,64 @@
/*
* fpu/rounding.cpp - system-dependant FPU rounding mode and precision
*
* Basilisk II (C) 1997-2008 Christian Bauer
*
* MC68881/68040 fpu emulation
*
* Original UAE FPU, copyright 1996 Herman ten Brugge
* Rewrite for x86, copyright 1999-2000 Lauri Pesonen
* New framework, copyright 2000 Gwenole Beauchesne
* Adapted for JIT compilation (c) Bernd Meyer, 2000
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This 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
*/
#undef PRIVATE
#define PRIVATE /**/
#undef PUBLIC
#define PUBLIC /**/
#undef FFPU
#define FFPU /**/
#undef FPU
#define FPU fpu.
/* -------------------------------------------------------------------------- */
/* --- Native X86 Rounding Mode --- */
/* -------------------------------------------------------------------------- */
#ifdef FPU_USE_X86_ROUNDING_MODE
const uae_u32 FFPU x86_control_word_rm_mac2host[] = {
CW_RC_NEAR,
CW_RC_ZERO,
CW_RC_DOWN,
CW_RC_UP
};
#endif
/* -------------------------------------------------------------------------- */
/* --- Native X86 Rounding Precision --- */
/* -------------------------------------------------------------------------- */
#ifdef FPU_USE_X86_ROUNDING_PRECISION
const uae_u32 FFPU x86_control_word_rp_mac2host[] = {
CW_PC_EXTENDED,
CW_PC_SINGLE,
CW_PC_DOUBLE,
CW_PC_RESERVED
};
#endif

View File

@ -0,0 +1,154 @@
/*
* fpu/rounding.h - system-dependant FPU rounding mode and precision
*
* Basilisk II (C) 1997-2008 Christian Bauer
*
* MC68881/68040 fpu emulation
*
* Original UAE FPU, copyright 1996 Herman ten Brugge
* Rewrite for x86, copyright 1999-2000 Lauri Pesonen
* New framework, copyright 2000 Gwenole Beauchesne
* Adapted for JIT compilation (c) Bernd Meyer, 2000
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This 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 FPU_ROUNDING_H
#define FPU_ROUNDING_H
/* NOTE: this file shall be included from fpu/fpu_*.cpp */
#undef PUBLIC
#define PUBLIC extern
#undef PRIVATE
#define PRIVATE static
#undef FFPU
#define FFPU /**/
#undef FPU
#define FPU fpu.
/* Defaults to generic rounding mode and precision handling */
#define FPU_USE_GENERIC_ROUNDING_MODE
#define FPU_USE_GENERIC_ROUNDING_PRECISION
/* -------------------------------------------------------------------------- */
/* --- Selection of floating-point rounding mode and precision --- */
/* -------------------------------------------------------------------------- */
/* Optimized i386 fpu core must use native rounding mode */
#if defined(FPU_X86) && defined(USE_X87_ASSEMBLY)
# undef FPU_USE_GENERIC_ROUNDING_MODE
# define FPU_USE_X86_ROUNDING_MODE
#endif
/* Optimized i386 fpu core must use native rounding precision */
#if defined(FPU_X86) && defined(USE_X87_ASSEMBLY)
# undef FPU_USE_GENERIC_ROUNDING_PRECISION
# define FPU_USE_X86_ROUNDING_PRECISION
#endif
#if 0 // gb-- FIXME: that doesn't work
/* IEEE-based fpu core can have native rounding mode on i386 */
#if defined(FPU_IEEE) && defined(USE_X87_ASSEMBLY)
# undef FPU_USE_GENERIC_ROUNDING_MODE
# define FPU_USE_X86_ROUNDING_MODE
#endif
/* IEEE-based fpu core can have native rounding precision on i386 */
#if defined(FPU_IEEE) && defined(USE_X87_ASSEMBLY)
# undef FPU_USE_GENERIC_ROUNDING_PRECISION
# define FPU_USE_X86_ROUNDING_PRECISION
#endif
#endif
/* -------------------------------------------------------------------------- */
/* --- Sanity checks --- */
/* -------------------------------------------------------------------------- */
/* X86 rounding mode and precision work together */
#if defined(FPU_USE_X86_ROUNDING_MODE) && defined(FPU_USE_X86_ROUNDING_PRECISION)
# define FPU_USE_X86_ROUNDING
# define CW_INITIAL (CW_RESET|CW_X|CW_PC_EXTENDED|CW_RC_NEAR|CW_PM|CW_UM|CW_OM|CW_ZM|CW_DM|CW_IM)
PRIVATE uae_u32 x86_control_word;
#endif
/* Control word -- rounding mode */
#ifdef FPU_USE_X86_ROUNDING_MODE
PUBLIC const uae_u32 x86_control_word_rm_mac2host[];
#endif
/* Control word -- rounding precision */
#ifdef FPU_USE_X86_ROUNDING_PRECISION
PUBLIC const uae_u32 x86_control_word_rp_mac2host[];
#endif
#if defined(FPU_USE_X86_ROUNDING_MODE) && defined(FPU_USE_X86_ROUNDING_PRECISION)
/* Set host control word for rounding mode and rounding precision */
PRIVATE inline void set_host_control_word(void)
{
/*
Exception enable byte is ignored, but the same value is returned
that was previously set.
*/
x86_control_word
= (x86_control_word & ~(X86_ROUNDING_MODE|X86_ROUNDING_PRECISION))
| x86_control_word_rm_mac2host[(FPU fpcr.rounding_mode & FPCR_ROUNDING_MODE) >> 4]
| x86_control_word_rp_mac2host[(FPU fpcr.rounding_precision & FPCR_ROUNDING_PRECISION) >> 6]
;
__asm__ __volatile__("fldcw %0" : : "m" (x86_control_word));
}
#endif
/* -------------------------------------------------------------------------- */
/* --- Generic rounding mode and precision --- */
/* -------------------------------------------------------------------------- */
#if defined(FPU_USE_GENERIC_ROUNDING_MODE) && defined(FPU_USE_GENERIC_ROUNDING_PRECISION)
/* Set host control word for rounding mode and rounding precision */
PRIVATE inline void set_host_control_word(void)
{ }
#endif
/* -------------------------------------------------------------------------- */
/* --- Common rounding mode and precision --- */
/* -------------------------------------------------------------------------- */
#if defined(FPU_USE_GENERIC_ROUNDING_MODE) || defined(FPU_USE_X86_ROUNDING_MODE)
/* Return the current rounding mode in m68k format */
static inline uae_u32 FFPU get_rounding_mode(void)
{ return FPU fpcr.rounding_mode; }
/* Convert and set to native rounding mode */
static inline void FFPU set_rounding_mode(uae_u32 new_rounding_mode)
{ FPU fpcr.rounding_mode = new_rounding_mode; }
#endif
#if defined(FPU_USE_GENERIC_ROUNDING_PRECISION) || defined(FPU_USE_X86_ROUNDING_PRECISION)
/* Return the current rounding precision in m68k format */
static inline uae_u32 FFPU get_rounding_precision(void)
{ return FPU fpcr.rounding_precision; }
/* Convert and set to native rounding precision */
static inline void FFPU set_rounding_precision(uae_u32 new_rounding_precision)
{ FPU fpcr.rounding_precision = new_rounding_precision; }
#endif
#endif /* FPU_ROUNDING_H */

View File

@ -0,0 +1,159 @@
/*
* types.h - basic types for fpu registers
*
* Basilisk II (C) 1997-2008 Christian Bauer
*
* MC68881/68040 fpu emulation
*
* Original UAE FPU, copyright 1996 Herman ten Brugge
* Rewrite for x86, copyright 1999-2000 Lauri Pesonen
* New framework, copyright 2000 Gwenole Beauchesne
* Adapted for JIT compilation (c) Bernd Meyer, 2000
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This 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 FPU_TYPES_H
#define FPU_TYPES_H
#include "sysdeps.h"
/* Default behavior is *not* to use long doubles */
#undef USE_LONG_DOUBLE
#undef USE_QUAD_DOUBLE
/* -------------------------------------------------------------------------- */
/* --- Original UAE fpu core --- */
/* -------------------------------------------------------------------------- */
#if defined(FPU_UAE)
/* 4-byte floats */
#if SIZEOF_FLOAT == 4
typedef float uae_f32;
#elif SIZEOF_DOUBLE == 4
typedef double uae_f32;
#else
#error "No 4 byte float type, you lose."
#endif
/* 8-byte floats */
#if SIZEOF_DOUBLE == 8
typedef double uae_f64;
#elif SIZEOF_LONG_DOUBLE == 8
typedef long double uae_f64;
#else
#error "No 8 byte float type, you lose."
#endif
/* Original UAE FPU registers are only 8 bytes long */
typedef uae_f64 fpu_register;
typedef fpu_register fpu_extended;
typedef uae_f64 fpu_double;
typedef uae_f32 fpu_single;
/* -------------------------------------------------------------------------- */
/* --- Optimized core for x86 --- */
/* -------------------------------------------------------------------------- */
#elif defined(FPU_X86)
/* 4-byte floats */
#if SIZEOF_FLOAT == 4
typedef float uae_f32;
#elif SIZEOF_DOUBLE == 4
typedef double uae_f32;
#else
#error "No 4 byte float type, you lose."
#endif
/* 8-byte floats */
#if SIZEOF_DOUBLE == 8
typedef float uae_f64;
#elif SIZEOF_LONG_DOUBLE == 8
typedef double uae_f64;
#else
#error "No 8 byte float type, you lose."
#endif
/* At least 10-byte floats are required */
#if SIZEOF_LONG_DOUBLE >= 10
typedef long double fpu_register;
#else
#error "No float type at least 10 bytes long, you lose."
#endif
/* X86 FPU has a custom register type that maps to a native X86 register */
typedef fpu_register fpu_extended;
typedef uae_f64 fpu_double;
typedef uae_f32 fpu_single;
/* -------------------------------------------------------------------------- */
/* --- C99 implementation --- */
/* -------------------------------------------------------------------------- */
#elif defined(FPU_IEEE)
#if HOST_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
#error "No IEEE float format, you lose."
#endif
/* 4-byte floats */
#if SIZEOF_FLOAT == 4
typedef float uae_f32;
#elif SIZEOF_DOUBLE == 4
typedef double uae_f32;
#else
#error "No 4 byte float type, you lose."
#endif
/* 8-byte floats */
#if SIZEOF_DOUBLE == 8
typedef double uae_f64;
#elif SIZEOF_LONG_DOUBLE == 8
typedef long double uae_f64;
#else
#error "No 8 byte float type, you lose."
#endif
/* 12-byte or 16-byte floats */
#if SIZEOF_LONG_DOUBLE == 12
typedef long double uae_f96;
typedef uae_f96 fpu_register;
#define USE_LONG_DOUBLE 1
#elif SIZEOF_LONG_DOUBLE == 16 && (defined(__i386__) || defined(__x86_64__))
/* Long doubles on x86-64 are really held in old x87 FPU stack. */
typedef long double uae_f128;
typedef uae_f128 fpu_register;
#define USE_LONG_DOUBLE 1
#elif 0
/* Disable for now and probably for good as (i) the emulator
implementation is not correct, (ii) I don't know of any CPU which
handles this kind of format *natively* with conformance to IEEE. */
typedef long double uae_f128;
typedef uae_f128 fpu_register;
#define USE_QUAD_DOUBLE 1
#else
typedef uae_f64 fpu_register;
#endif
/* We need all those floating-point types */
typedef fpu_register fpu_extended;
typedef uae_f64 fpu_double;
typedef uae_f32 fpu_single;
#endif
#endif /* FPU_TYPES_H */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,642 @@
/*
* UAE - The Un*x Amiga Emulator
*
* Memory management
*
* (c) 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
*/
#include <stdio.h>
#include <stdlib.h>
#include "sysdeps.h"
#include "cpu_emulation.h"
#include "main.h"
#include "video.h"
#include "m68k.h"
#include "memory.h"
#include "readcpu.h"
#include "newcpu.h"
#if !REAL_ADDRESSING && !DIRECT_ADDRESSING
static bool illegal_mem = false;
#ifdef SAVE_MEMORY_BANKS
addrbank *mem_banks[65536];
#else
addrbank mem_banks[65536];
#endif
#ifdef WORDS_BIGENDIAN
# define swap_words(X) (X)
#else
# define swap_words(X) (((X) >> 16) | ((X) << 16))
#endif
#ifdef NO_INLINE_MEMORY_ACCESS
uae_u32 longget (uaecptr addr)
{
return call_mem_get_func (get_mem_bank (addr).lget, addr);
}
uae_u32 wordget (uaecptr addr)
{
return call_mem_get_func (get_mem_bank (addr).wget, addr);
}
uae_u32 byteget (uaecptr addr)
{
return call_mem_get_func (get_mem_bank (addr).bget, addr);
}
void longput (uaecptr addr, uae_u32 l)
{
call_mem_put_func (get_mem_bank (addr).lput, addr, l);
}
void wordput (uaecptr addr, uae_u32 w)
{
call_mem_put_func (get_mem_bank (addr).wput, addr, w);
}
void byteput (uaecptr addr, uae_u32 b)
{
call_mem_put_func (get_mem_bank (addr).bput, addr, b);
}
#endif
/* A dummy bank that only contains zeros */
static uae_u32 REGPARAM2 dummy_lget (uaecptr) REGPARAM;
static uae_u32 REGPARAM2 dummy_wget (uaecptr) REGPARAM;
static uae_u32 REGPARAM2 dummy_bget (uaecptr) REGPARAM;
static void REGPARAM2 dummy_lput (uaecptr, uae_u32) REGPARAM;
static void REGPARAM2 dummy_wput (uaecptr, uae_u32) REGPARAM;
static void REGPARAM2 dummy_bput (uaecptr, uae_u32) REGPARAM;
uae_u32 REGPARAM2 dummy_lget (uaecptr addr)
{
if (illegal_mem)
write_log ("Illegal lget at %08x\n", addr);
return 0;
}
uae_u32 REGPARAM2 dummy_wget (uaecptr addr)
{
if (illegal_mem)
write_log ("Illegal wget at %08x\n", addr);
return 0;
}
uae_u32 REGPARAM2 dummy_bget (uaecptr addr)
{
if (illegal_mem)
write_log ("Illegal bget at %08x\n", addr);
return 0;
}
void REGPARAM2 dummy_lput (uaecptr addr, uae_u32 l)
{
if (illegal_mem)
write_log ("Illegal lput at %08x\n", addr);
}
void REGPARAM2 dummy_wput (uaecptr addr, uae_u32 w)
{
if (illegal_mem)
write_log ("Illegal wput at %08x\n", addr);
}
void REGPARAM2 dummy_bput (uaecptr addr, uae_u32 b)
{
if (illegal_mem)
write_log ("Illegal bput at %08x\n", addr);
}
/* Mac RAM (32 bit addressing) */
static uae_u32 REGPARAM2 ram_lget(uaecptr) REGPARAM;
static uae_u32 REGPARAM2 ram_wget(uaecptr) REGPARAM;
static uae_u32 REGPARAM2 ram_bget(uaecptr) REGPARAM;
static void REGPARAM2 ram_lput(uaecptr, uae_u32) REGPARAM;
static void REGPARAM2 ram_wput(uaecptr, uae_u32) REGPARAM;
static void REGPARAM2 ram_bput(uaecptr, uae_u32) REGPARAM;
static uae_u8 *REGPARAM2 ram_xlate(uaecptr addr) REGPARAM;
static uintptr RAMBaseDiff; // RAMBaseHost - RAMBaseMac
uae_u32 REGPARAM2 ram_lget(uaecptr addr)
{
uae_u32 *m;
m = (uae_u32 *)(RAMBaseDiff + addr);
return do_get_mem_long(m);
}
uae_u32 REGPARAM2 ram_wget(uaecptr addr)
{
uae_u16 *m;
m = (uae_u16 *)(RAMBaseDiff + addr);
return do_get_mem_word(m);
}
uae_u32 REGPARAM2 ram_bget(uaecptr addr)
{
return (uae_u32)*(uae_u8 *)(RAMBaseDiff + addr);
}
void REGPARAM2 ram_lput(uaecptr addr, uae_u32 l)
{
uae_u32 *m;
m = (uae_u32 *)(RAMBaseDiff + addr);
do_put_mem_long(m, l);
}
void REGPARAM2 ram_wput(uaecptr addr, uae_u32 w)
{
uae_u16 *m;
m = (uae_u16 *)(RAMBaseDiff + addr);
do_put_mem_word(m, w);
}
void REGPARAM2 ram_bput(uaecptr addr, uae_u32 b)
{
*(uae_u8 *)(RAMBaseDiff + addr) = b;
}
uae_u8 *REGPARAM2 ram_xlate(uaecptr addr)
{
return (uae_u8 *)(RAMBaseDiff + addr);
}
/* Mac RAM (24 bit addressing) */
static uae_u32 REGPARAM2 ram24_lget(uaecptr) REGPARAM;
static uae_u32 REGPARAM2 ram24_wget(uaecptr) REGPARAM;
static uae_u32 REGPARAM2 ram24_bget(uaecptr) REGPARAM;
static void REGPARAM2 ram24_lput(uaecptr, uae_u32) REGPARAM;
static void REGPARAM2 ram24_wput(uaecptr, uae_u32) REGPARAM;
static void REGPARAM2 ram24_bput(uaecptr, uae_u32) REGPARAM;
static uae_u8 *REGPARAM2 ram24_xlate(uaecptr addr) REGPARAM;
uae_u32 REGPARAM2 ram24_lget(uaecptr addr)
{
uae_u32 *m;
m = (uae_u32 *)(RAMBaseDiff + (addr & 0xffffff));
return do_get_mem_long(m);
}
uae_u32 REGPARAM2 ram24_wget(uaecptr addr)
{
uae_u16 *m;
m = (uae_u16 *)(RAMBaseDiff + (addr & 0xffffff));
return do_get_mem_word(m);
}
uae_u32 REGPARAM2 ram24_bget(uaecptr addr)
{
return (uae_u32)*(uae_u8 *)(RAMBaseDiff + (addr & 0xffffff));
}
void REGPARAM2 ram24_lput(uaecptr addr, uae_u32 l)
{
uae_u32 *m;
m = (uae_u32 *)(RAMBaseDiff + (addr & 0xffffff));
do_put_mem_long(m, l);
}
void REGPARAM2 ram24_wput(uaecptr addr, uae_u32 w)
{
uae_u16 *m;
m = (uae_u16 *)(RAMBaseDiff + (addr & 0xffffff));
do_put_mem_word(m, w);
}
void REGPARAM2 ram24_bput(uaecptr addr, uae_u32 b)
{
*(uae_u8 *)(RAMBaseDiff + (addr & 0xffffff)) = b;
}
uae_u8 *REGPARAM2 ram24_xlate(uaecptr addr)
{
return (uae_u8 *)(RAMBaseDiff + (addr & 0xffffff));
}
/* Mac ROM (32 bit addressing) */
static uae_u32 REGPARAM2 rom_lget(uaecptr) REGPARAM;
static uae_u32 REGPARAM2 rom_wget(uaecptr) REGPARAM;
static uae_u32 REGPARAM2 rom_bget(uaecptr) REGPARAM;
static void REGPARAM2 rom_lput(uaecptr, uae_u32) REGPARAM;
static void REGPARAM2 rom_wput(uaecptr, uae_u32) REGPARAM;
static void REGPARAM2 rom_bput(uaecptr, uae_u32) REGPARAM;
static uae_u8 *REGPARAM2 rom_xlate(uaecptr addr) REGPARAM;
static uintptr ROMBaseDiff; // ROMBaseHost - ROMBaseMac
uae_u32 REGPARAM2 rom_lget(uaecptr addr)
{
uae_u32 *m;
m = (uae_u32 *)(ROMBaseDiff + addr);
return do_get_mem_long(m);
}
uae_u32 REGPARAM2 rom_wget(uaecptr addr)
{
uae_u16 *m;
m = (uae_u16 *)(ROMBaseDiff + addr);
return do_get_mem_word(m);
}
uae_u32 REGPARAM2 rom_bget(uaecptr addr)
{
return (uae_u32)*(uae_u8 *)(ROMBaseDiff + addr);
}
void REGPARAM2 rom_lput(uaecptr addr, uae_u32 b)
{
if (illegal_mem)
write_log ("Illegal ROM lput at %08x\n", addr);
}
void REGPARAM2 rom_wput(uaecptr addr, uae_u32 b)
{
if (illegal_mem)
write_log ("Illegal ROM wput at %08x\n", addr);
}
void REGPARAM2 rom_bput(uaecptr addr, uae_u32 b)
{
if (illegal_mem)
write_log ("Illegal ROM bput at %08x\n", addr);
}
uae_u8 *REGPARAM2 rom_xlate(uaecptr addr)
{
return (uae_u8 *)(ROMBaseDiff + addr);
}
/* Mac ROM (24 bit addressing) */
static uae_u32 REGPARAM2 rom24_lget(uaecptr) REGPARAM;
static uae_u32 REGPARAM2 rom24_wget(uaecptr) REGPARAM;
static uae_u32 REGPARAM2 rom24_bget(uaecptr) REGPARAM;
static uae_u8 *REGPARAM2 rom24_xlate(uaecptr addr) REGPARAM;
uae_u32 REGPARAM2 rom24_lget(uaecptr addr)
{
uae_u32 *m;
m = (uae_u32 *)(ROMBaseDiff + (addr & 0xffffff));
return do_get_mem_long(m);
}
uae_u32 REGPARAM2 rom24_wget(uaecptr addr)
{
uae_u16 *m;
m = (uae_u16 *)(ROMBaseDiff + (addr & 0xffffff));
return do_get_mem_word(m);
}
uae_u32 REGPARAM2 rom24_bget(uaecptr addr)
{
return (uae_u32)*(uae_u8 *)(ROMBaseDiff + (addr & 0xffffff));
}
uae_u8 *REGPARAM2 rom24_xlate(uaecptr addr)
{
return (uae_u8 *)(ROMBaseDiff + (addr & 0xffffff));
}
/* Frame buffer */
static uae_u32 REGPARAM2 frame_direct_lget(uaecptr) REGPARAM;
static uae_u32 REGPARAM2 frame_direct_wget(uaecptr) REGPARAM;
static uae_u32 REGPARAM2 frame_direct_bget(uaecptr) REGPARAM;
static void REGPARAM2 frame_direct_lput(uaecptr, uae_u32) REGPARAM;
static void REGPARAM2 frame_direct_wput(uaecptr, uae_u32) REGPARAM;
static void REGPARAM2 frame_direct_bput(uaecptr, uae_u32) REGPARAM;
static uae_u32 REGPARAM2 frame_host_555_lget(uaecptr) REGPARAM;
static uae_u32 REGPARAM2 frame_host_555_wget(uaecptr) REGPARAM;
static void REGPARAM2 frame_host_555_lput(uaecptr, uae_u32) REGPARAM;
static void REGPARAM2 frame_host_555_wput(uaecptr, uae_u32) REGPARAM;
static uae_u32 REGPARAM2 frame_host_565_lget(uaecptr) REGPARAM;
static uae_u32 REGPARAM2 frame_host_565_wget(uaecptr) REGPARAM;
static void REGPARAM2 frame_host_565_lput(uaecptr, uae_u32) REGPARAM;
static void REGPARAM2 frame_host_565_wput(uaecptr, uae_u32) REGPARAM;
static uae_u32 REGPARAM2 frame_host_888_lget(uaecptr) REGPARAM;
static void REGPARAM2 frame_host_888_lput(uaecptr, uae_u32) REGPARAM;
static uae_u8 *REGPARAM2 frame_xlate(uaecptr addr) REGPARAM;
static uintptr FrameBaseDiff; // MacFrameBaseHost - MacFrameBaseMac
uae_u32 REGPARAM2 frame_direct_lget(uaecptr addr)
{
uae_u32 *m;
m = (uae_u32 *)(FrameBaseDiff + addr);
return do_get_mem_long(m);
}
uae_u32 REGPARAM2 frame_direct_wget(uaecptr addr)
{
uae_u16 *m;
m = (uae_u16 *)(FrameBaseDiff + addr);
return do_get_mem_word(m);
}
uae_u32 REGPARAM2 frame_direct_bget(uaecptr addr)
{
return (uae_u32)*(uae_u8 *)(FrameBaseDiff + addr);
}
void REGPARAM2 frame_direct_lput(uaecptr addr, uae_u32 l)
{
uae_u32 *m;
m = (uae_u32 *)(FrameBaseDiff + addr);
do_put_mem_long(m, l);
}
void REGPARAM2 frame_direct_wput(uaecptr addr, uae_u32 w)
{
uae_u16 *m;
m = (uae_u16 *)(FrameBaseDiff + addr);
do_put_mem_word(m, w);
}
void REGPARAM2 frame_direct_bput(uaecptr addr, uae_u32 b)
{
*(uae_u8 *)(FrameBaseDiff + addr) = b;
}
uae_u32 REGPARAM2 frame_host_555_lget(uaecptr addr)
{
uae_u32 *m, l;
m = (uae_u32 *)(FrameBaseDiff + addr);
l = *m;
return swap_words(l);
}
uae_u32 REGPARAM2 frame_host_555_wget(uaecptr addr)
{
uae_u16 *m;
m = (uae_u16 *)(FrameBaseDiff + addr);
return *m;
}
void REGPARAM2 frame_host_555_lput(uaecptr addr, uae_u32 l)
{
uae_u32 *m;
m = (uae_u32 *)(FrameBaseDiff + addr);
*m = swap_words(l);
}
void REGPARAM2 frame_host_555_wput(uaecptr addr, uae_u32 w)
{
uae_u16 *m;
m = (uae_u16 *)(FrameBaseDiff + addr);
*m = w;
}
uae_u32 REGPARAM2 frame_host_565_lget(uaecptr addr)
{
uae_u32 *m, l;
m = (uae_u32 *)(FrameBaseDiff + addr);
l = *m;
l = (l & 0x001f001f) | ((l >> 1) & 0x7fe07fe0);
return swap_words(l);
}
uae_u32 REGPARAM2 frame_host_565_wget(uaecptr addr)
{
uae_u16 *m, w;
m = (uae_u16 *)(FrameBaseDiff + addr);
w = *m;
return (w & 0x1f) | ((w >> 1) & 0x7fe0);
}
void REGPARAM2 frame_host_565_lput(uaecptr addr, uae_u32 l)
{
uae_u32 *m;
m = (uae_u32 *)(FrameBaseDiff + addr);
l = (l & 0x001f001f) | ((l << 1) & 0xffc0ffc0);
*m = swap_words(l);
}
void REGPARAM2 frame_host_565_wput(uaecptr addr, uae_u32 w)
{
uae_u16 *m;
m = (uae_u16 *)(FrameBaseDiff + addr);
*m = (w & 0x1f) | ((w << 1) & 0xffc0);
}
uae_u32 REGPARAM2 frame_host_888_lget(uaecptr addr)
{
uae_u32 *m, l;
m = (uae_u32 *)(FrameBaseDiff + addr);
return *m;
}
void REGPARAM2 frame_host_888_lput(uaecptr addr, uae_u32 l)
{
uae_u32 *m;
m = (uae_u32 *)(MacFrameBaseHost + addr - MacFrameBaseMac);
*m = l;
}
uae_u8 *REGPARAM2 frame_xlate(uaecptr addr)
{
return (uae_u8 *)(FrameBaseDiff + addr);
}
/* Mac framebuffer RAM (24 bit addressing)
*
* This works by duplicating appropriate writes to the 32-bit
* address-space framebuffer.
*/
static void REGPARAM2 fram24_lput(uaecptr, uae_u32) REGPARAM;
static void REGPARAM2 fram24_wput(uaecptr, uae_u32) REGPARAM;
static void REGPARAM2 fram24_bput(uaecptr, uae_u32) REGPARAM;
void REGPARAM2 fram24_lput(uaecptr addr, uae_u32 l)
{
uaecptr page_off = addr & 0xffff;
if (0xa700 <= page_off && page_off < 0xfc80) {
uae_u32 *fm;
fm = (uae_u32 *)(MacFrameBaseHost + page_off - 0xa700);
do_put_mem_long(fm, l);
}
uae_u32 *m;
m = (uae_u32 *)(RAMBaseDiff + (addr & 0xffffff));
do_put_mem_long(m, l);
}
void REGPARAM2 fram24_wput(uaecptr addr, uae_u32 w)
{
uaecptr page_off = addr & 0xffff;
if (0xa700 <= page_off && page_off < 0xfc80) {
uae_u16 *fm;
fm = (uae_u16 *)(MacFrameBaseHost + page_off - 0xa700);
do_put_mem_word(fm, w);
}
uae_u16 *m;
m = (uae_u16 *)(RAMBaseDiff + (addr & 0xffffff));
do_put_mem_word(m, w);
}
void REGPARAM2 fram24_bput(uaecptr addr, uae_u32 b)
{
uaecptr page_off = addr & 0xffff;
if (0xa700 <= page_off && page_off < 0xfc80) {
*(uae_u8 *)(MacFrameBaseHost + page_off - 0xa700) = b;
}
*(uae_u8 *)(RAMBaseDiff + (addr & 0xffffff)) = b;
}
/* Default memory access functions */
uae_u8 *REGPARAM2 default_xlate (uaecptr a)
{
write_log("Your Mac program just did something terribly stupid\n");
return NULL;
}
/* Address banks */
addrbank dummy_bank = {
dummy_lget, dummy_wget, dummy_bget,
dummy_lput, dummy_wput, dummy_bput,
default_xlate
};
addrbank ram_bank = {
ram_lget, ram_wget, ram_bget,
ram_lput, ram_wput, ram_bput,
ram_xlate
};
addrbank ram24_bank = {
ram24_lget, ram24_wget, ram24_bget,
ram24_lput, ram24_wput, ram24_bput,
ram24_xlate
};
addrbank rom_bank = {
rom_lget, rom_wget, rom_bget,
rom_lput, rom_wput, rom_bput,
rom_xlate
};
addrbank rom24_bank = {
rom24_lget, rom24_wget, rom24_bget,
rom_lput, rom_wput, rom_bput,
rom24_xlate
};
addrbank frame_direct_bank = {
frame_direct_lget, frame_direct_wget, frame_direct_bget,
frame_direct_lput, frame_direct_wput, frame_direct_bput,
frame_xlate
};
addrbank frame_host_555_bank = {
frame_host_555_lget, frame_host_555_wget, frame_direct_bget,
frame_host_555_lput, frame_host_555_wput, frame_direct_bput,
frame_xlate
};
addrbank frame_host_565_bank = {
frame_host_565_lget, frame_host_565_wget, frame_direct_bget,
frame_host_565_lput, frame_host_565_wput, frame_direct_bput,
frame_xlate
};
addrbank frame_host_888_bank = {
frame_host_888_lget, frame_direct_wget, frame_direct_bget,
frame_host_888_lput, frame_direct_wput, frame_direct_bput,
frame_xlate
};
addrbank fram24_bank = {
ram24_lget, ram24_wget, ram24_bget,
fram24_lput, fram24_wput, fram24_bput,
ram24_xlate
};
void memory_init(void)
{
for(long i=0; i<65536; i++)
put_mem_bank(i<<16, &dummy_bank);
// Limit RAM size to not overlap ROM
uint32 ram_size = RAMSize > ROMBaseMac ? ROMBaseMac : RAMSize;
RAMBaseDiff = (uintptr)RAMBaseHost - (uintptr)RAMBaseMac;
ROMBaseDiff = (uintptr)ROMBaseHost - (uintptr)ROMBaseMac;
FrameBaseDiff = (uintptr)MacFrameBaseHost - (uintptr)MacFrameBaseMac;
// Map RAM, ROM and display
if (TwentyFourBitAddressing) {
map_banks(&ram24_bank, RAMBaseMac >> 16, ram_size >> 16);
map_banks(&rom24_bank, ROMBaseMac >> 16, ROMSize >> 16);
// Map frame buffer at end of RAM.
map_banks(&fram24_bank, ((RAMBaseMac + ram_size) >> 16) - 1, 1);
} else {
map_banks(&ram_bank, RAMBaseMac >> 16, ram_size >> 16);
map_banks(&rom_bank, ROMBaseMac >> 16, ROMSize >> 16);
// Map frame buffer
switch (MacFrameLayout) {
case FLAYOUT_DIRECT:
map_banks(&frame_direct_bank, MacFrameBaseMac >> 16, (MacFrameSize >> 16) + 1);
break;
case FLAYOUT_HOST_555:
map_banks(&frame_host_555_bank, MacFrameBaseMac >> 16, (MacFrameSize >> 16) + 1);
break;
case FLAYOUT_HOST_565:
map_banks(&frame_host_565_bank, MacFrameBaseMac >> 16, (MacFrameSize >> 16) + 1);
break;
case FLAYOUT_HOST_888:
map_banks(&frame_host_888_bank, MacFrameBaseMac >> 16, (MacFrameSize >> 16) + 1);
break;
}
}
}
void map_banks(addrbank *bank, int start, int size)
{
int bnr;
unsigned long int hioffs = 0, endhioffs = 0x100;
if (start >= 0x100) {
for (bnr = start; bnr < start + size; bnr++)
put_mem_bank (bnr << 16, bank);
return;
}
if (TwentyFourBitAddressing) endhioffs = 0x10000;
for (hioffs = 0; hioffs < endhioffs; hioffs += 0x100)
for (bnr = start; bnr < start+size; bnr++)
put_mem_bank((bnr + hioffs) << 16, bank);
}
#endif /* !REAL_ADDRESSING && !DIRECT_ADDRESSING */

View File

@ -0,0 +1,207 @@
/*
* UAE - The Un*x Amiga Emulator
*
* memory management
*
* 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 UAE_MEMORY_H
#define UAE_MEMORY_H
#if !DIRECT_ADDRESSING && !REAL_ADDRESSING
/* Enabling this adds one additional native memory reference per 68k memory
* access, but saves one shift (on the x86). Enabling this is probably
* better for the cache. My favourite benchmark (PP2) doesn't show a
* difference, so I leave this enabled. */
#if 1 || defined SAVE_MEMORY
#define SAVE_MEMORY_BANKS
#endif
typedef uae_u32 (REGPARAM2 *mem_get_func)(uaecptr) REGPARAM;
typedef void (REGPARAM2 *mem_put_func)(uaecptr, uae_u32) REGPARAM;
typedef uae_u8 *(REGPARAM2 *xlate_func)(uaecptr) REGPARAM;
#undef DIRECT_MEMFUNCS_SUCCESSFUL
#ifndef CAN_MAP_MEMORY
#undef USE_COMPILER
#endif
#if defined(USE_COMPILER) && !defined(USE_MAPPED_MEMORY)
#define USE_MAPPED_MEMORY
#endif
typedef struct {
/* These ones should be self-explanatory... */
mem_get_func lget, wget, bget;
mem_put_func lput, wput, bput;
/* Use xlateaddr to translate an Amiga address to a uae_u8 * that can
* be used to address memory without calling the wget/wput functions.
* This doesn't work for all memory banks, so this function may call
* abort(). */
xlate_func xlateaddr;
} addrbank;
extern uae_u8 filesysory[65536];
extern addrbank ram_bank; // Mac RAM
extern addrbank rom_bank; // Mac ROM
extern addrbank frame_bank; // Frame buffer
/* Default memory access functions */
extern uae_u8 *REGPARAM2 default_xlate(uaecptr addr) REGPARAM;
#define bankindex(addr) (((uaecptr)(addr)) >> 16)
#ifdef SAVE_MEMORY_BANKS
extern addrbank *mem_banks[65536];
#define get_mem_bank(addr) (*mem_banks[bankindex(addr)])
#define put_mem_bank(addr, b) (mem_banks[bankindex(addr)] = (b))
#else
extern addrbank mem_banks[65536];
#define get_mem_bank(addr) (mem_banks[bankindex(addr)])
#define put_mem_bank(addr, b) (mem_banks[bankindex(addr)] = *(b))
#endif
extern void memory_init(void);
extern void map_banks(addrbank *bank, int first, int count);
#ifndef NO_INLINE_MEMORY_ACCESS
#define longget(addr) (call_mem_get_func(get_mem_bank(addr).lget, addr))
#define wordget(addr) (call_mem_get_func(get_mem_bank(addr).wget, addr))
#define byteget(addr) (call_mem_get_func(get_mem_bank(addr).bget, addr))
#define longput(addr,l) (call_mem_put_func(get_mem_bank(addr).lput, addr, l))
#define wordput(addr,w) (call_mem_put_func(get_mem_bank(addr).wput, addr, w))
#define byteput(addr,b) (call_mem_put_func(get_mem_bank(addr).bput, addr, b))
#else
extern uae_u32 longget(uaecptr addr);
extern uae_u32 wordget(uaecptr addr);
extern uae_u32 byteget(uaecptr addr);
extern void longput(uaecptr addr, uae_u32 l);
extern void wordput(uaecptr addr, uae_u32 w);
extern void byteput(uaecptr addr, uae_u32 b);
#endif
#ifndef MD_HAVE_MEM_1_FUNCS
#define longget_1 longget
#define wordget_1 wordget
#define byteget_1 byteget
#define longput_1 longput
#define wordput_1 wordput
#define byteput_1 byteput
#endif
#endif /* !DIRECT_ADDRESSING && !REAL_ADDRESSING */
#if REAL_ADDRESSING
const uintptr MEMBaseDiff = 0;
#elif DIRECT_ADDRESSING
extern uintptr MEMBaseDiff;
#endif
#if REAL_ADDRESSING || DIRECT_ADDRESSING
static __inline__ uae_u8 *do_get_real_address(uaecptr addr)
{
return (uae_u8 *)MEMBaseDiff + addr;
}
static __inline__ uae_u32 do_get_virtual_address(uae_u8 *addr)
{
return (uintptr)addr - MEMBaseDiff;
}
static __inline__ uae_u32 get_long(uaecptr addr)
{
uae_u32 * const m = (uae_u32 *)do_get_real_address(addr);
return do_get_mem_long(m);
}
static __inline__ uae_u32 get_word(uaecptr addr)
{
uae_u16 * const m = (uae_u16 *)do_get_real_address(addr);
return do_get_mem_word(m);
}
static __inline__ uae_u32 get_byte(uaecptr addr)
{
uae_u8 * const m = (uae_u8 *)do_get_real_address(addr);
return do_get_mem_byte(m);
}
static __inline__ void put_long(uaecptr addr, uae_u32 l)
{
uae_u32 * const m = (uae_u32 *)do_get_real_address(addr);
do_put_mem_long(m, l);
}
static __inline__ void put_word(uaecptr addr, uae_u32 w)
{
uae_u16 * const m = (uae_u16 *)do_get_real_address(addr);
do_put_mem_word(m, w);
}
static __inline__ void put_byte(uaecptr addr, uae_u32 b)
{
uae_u8 * const m = (uae_u8 *)do_get_real_address(addr);
do_put_mem_byte(m, b);
}
static __inline__ uae_u8 *get_real_address(uaecptr addr)
{
return do_get_real_address(addr);
}
static __inline__ uae_u32 get_virtual_address(uae_u8 *addr)
{
return do_get_virtual_address(addr);
}
#else
static __inline__ uae_u32 get_long(uaecptr addr)
{
return longget_1(addr);
}
static __inline__ uae_u32 get_word(uaecptr addr)
{
return wordget_1(addr);
}
static __inline__ uae_u32 get_byte(uaecptr addr)
{
return byteget_1(addr);
}
static __inline__ void put_long(uaecptr addr, uae_u32 l)
{
longput_1(addr, l);
}
static __inline__ void put_word(uaecptr addr, uae_u32 w)
{
wordput_1(addr, w);
}
static __inline__ void put_byte(uaecptr addr, uae_u32 b)
{
byteput_1(addr, b);
}
static __inline__ uae_u8 *get_real_address(uaecptr addr)
{
return get_mem_bank(addr).xlateaddr(addr);
}
/* gb-- deliberately not implemented since it shall not be used... */
extern uae_u32 get_virtual_address(uae_u8 *addr);
#endif /* DIRECT_ADDRESSING || REAL_ADDRESSING */
#endif /* MEMORY_H */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,355 @@
/*
* UAE - The Un*x Amiga Emulator
*
* MC68000 emulation
*
* Copyright 1995 Bernd Schmidt
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef NEWCPU_H
#define NEWCPU_H
#ifndef FLIGHT_RECORDER
#define FLIGHT_RECORDER 0
#endif
#include "m68k.h"
#include "readcpu.h"
#include "spcflags.h"
#if ENABLE_MON
#include "mon.h"
#include "mon_disass.h"
#endif
extern int areg_byteinc[];
extern int imm8_table[];
extern int movem_index1[256];
extern int movem_index2[256];
extern int movem_next[256];
extern int broken_in;
#ifdef X86_ASSEMBLY
/* This hack seems to force all register saves (pushl %reg) to be moved to the
begining of the function, thus making it possible to cpuopti to remove them
since m68k_run_1 will save those registers before calling the instruction
handler */
# define cpuop_tag(tag) __asm__ __volatile__ ( "#cpuop_" tag )
#else
# define cpuop_tag(tag) ;
#endif
#define cpuop_begin() do { cpuop_tag("begin"); } while (0)
#define cpuop_end() do { cpuop_tag("end"); } while (0)
typedef void REGPARAM2 cpuop_func (uae_u32) REGPARAM;
struct cputbl {
cpuop_func *handler;
uae_u16 specific;
uae_u16 opcode;
};
extern cpuop_func *cpufunctbl[65536] ASM_SYM("cpufunctbl");
#if USE_JIT
typedef void compop_func (uae_u32) REGPARAM;
struct comptbl {
compop_func *handler;
uae_u32 specific;
uae_u32 opcode;
};
#endif
extern void REGPARAM2 op_illg (uae_u32) REGPARAM;
extern void m68k_dumpstate(uaecptr *nextpc);
typedef char flagtype;
struct regstruct {
uae_u32 regs[16];
uae_u32 pc;
uae_u8 * pc_p;
uae_u8 * pc_oldp;
spcflags_t spcflags;
int intmask;
uae_u32 vbr, sfc, dfc;
uaecptr usp, isp, msp;
uae_u16 sr;
flagtype t1;
flagtype t0;
flagtype s;
flagtype m;
flagtype x;
flagtype stopped;
#if USE_PREFETCH_BUFFER
/* Fellow sources say this is 4 longwords. That's impossible. It needs
* to be at least a longword. The HRM has some cryptic comment about two
* instructions being on the same longword boundary.
* The way this is implemented now seems like a good compromise.
*/
uae_u32 prefetch;
#endif
};
extern regstruct regs, lastint_regs;
#define m68k_dreg(r,num) ((r).regs[(num)])
#define m68k_areg(r,num) (((r).regs + 8)[(num)])
#define get_ibyte(o) do_get_mem_byte((uae_u8 *)(regs.pc_p + (o) + 1))
#define get_iword(o) do_get_mem_word((uae_u16 *)(regs.pc_p + (o)))
#define get_ilong(o) do_get_mem_long((uae_u32 *)(regs.pc_p + (o)))
#ifdef HAVE_GET_WORD_UNSWAPPED
#define GET_OPCODE (do_get_mem_word_unswapped (regs.pc_p))
#else
#define GET_OPCODE (get_iword (0))
#endif
#if USE_PREFETCH_BUFFER
static __inline__ uae_u32 get_ibyte_prefetch (uae_s32 o)
{
if (o > 3 || o < 0)
return do_get_mem_byte((uae_u8 *)(regs.pc_p + o + 1));
return do_get_mem_byte((uae_u8 *)(((uae_u8 *)&regs.prefetch) + o + 1));
}
static __inline__ uae_u32 get_iword_prefetch (uae_s32 o)
{
if (o > 3 || o < 0)
return do_get_mem_word((uae_u16 *)(regs.pc_p + o));
return do_get_mem_word((uae_u16 *)(((uae_u8 *)&regs.prefetch) + o));
}
static __inline__ uae_u32 get_ilong_prefetch (uae_s32 o)
{
if (o > 3 || o < 0)
return do_get_mem_long((uae_u32 *)(regs.pc_p + o));
if (o == 0)
return do_get_mem_long(&regs.prefetch);
return (do_get_mem_word (((uae_u16 *)&regs.prefetch) + 1) << 16) | do_get_mem_word ((uae_u16 *)(regs.pc_p + 4));
}
#endif
static __inline__ void fill_prefetch_0 (void)
{
#if USE_PREFETCH_BUFFER
uae_u32 r;
#ifdef UNALIGNED_PROFITABLE
r = *(uae_u32 *)regs.pc_p;
regs.prefetch = r;
#else
r = do_get_mem_long ((uae_u32 *)regs.pc_p);
do_put_mem_long (&regs.prefetch, r);
#endif
#endif
}
#if 0
static __inline__ void fill_prefetch_2 (void)
{
uae_u32 r = do_get_mem_long (&regs.prefetch) << 16;
uae_u32 r2 = do_get_mem_word (((uae_u16 *)regs.pc_p) + 1);
r |= r2;
do_put_mem_long (&regs.prefetch, r);
}
#else
#define fill_prefetch_2 fill_prefetch_0
#endif
static __inline__ uaecptr m68k_getpc (void)
{
#if REAL_ADDRESSING || DIRECT_ADDRESSING
return get_virtual_address(regs.pc_p);
#else
return regs.pc + ((char *)regs.pc_p - (char *)regs.pc_oldp);
#endif
}
static __inline__ void m68k_setpc (uaecptr newpc)
{
#if ENABLE_MON
uae_u32 previous_pc = m68k_getpc();
#endif
#if REAL_ADDRESSING || DIRECT_ADDRESSING
regs.pc_p = get_real_address(newpc);
#else
regs.pc_p = regs.pc_oldp = get_real_address(newpc);
regs.pc = newpc;
#endif
#if ENABLE_MON
if (IS_BREAK_POINT(newpc)) {
printf("Stopped at break point address: %08x. Last PC: %08x\n", newpc, previous_pc);
m68k_dumpstate(NULL);
const char *arg[4] = {"mon", "-m", "-r", NULL};
mon(3, arg);
}
#endif // end of #if ENABLE_MON
}
static __inline__ void m68k_incpc (uae_s32 delta)
{
#if ENABLE_MON
uae_u32 previous_pc = m68k_getpc();
#endif
regs.pc_p += (delta);
#if ENABLE_MON
uaecptr next_pc = m68k_getpc();
if (IS_BREAK_POINT(next_pc)) {
printf("Stopped at break point address: %08x. Last PC: %08x\n", next_pc, previous_pc);
m68k_dumpstate(NULL);
const char *arg[4] = {"mon", "-m", "-r", NULL};
mon(3, arg);
}
#endif // end of #if ENABLE_MON
}
/* These are only used by the 68020/68881 code, and therefore don't
* need to handle prefetch. */
static __inline__ uae_u32 next_ibyte (void)
{
uae_u32 r = get_ibyte (0);
m68k_incpc (2);
return r;
}
static __inline__ uae_u32 next_iword (void)
{
uae_u32 r = get_iword (0);
m68k_incpc (2);
return r;
}
static __inline__ uae_u32 next_ilong (void)
{
uae_u32 r = get_ilong (0);
m68k_incpc (4);
return r;
}
#define m68k_setpc_fast m68k_setpc
#define m68k_setpc_bcc m68k_setpc
#define m68k_setpc_rte m68k_setpc
static __inline__ void m68k_do_rts(void)
{
m68k_setpc(get_long(m68k_areg(regs, 7)));
m68k_areg(regs, 7) += 4;
}
static __inline__ void m68k_do_bsr(uaecptr oldpc, uae_s32 offset)
{
m68k_areg(regs, 7) -= 4;
put_long(m68k_areg(regs, 7), oldpc);
m68k_incpc(offset);
}
static __inline__ void m68k_do_jsr(uaecptr oldpc, uaecptr dest)
{
m68k_areg(regs, 7) -= 4;
put_long(m68k_areg(regs, 7), oldpc);
m68k_setpc(dest);
}
static __inline__ void m68k_setstopped (int stop)
{
regs.stopped = stop;
/* A traced STOP instruction drops through immediately without
actually stopping. */
if (stop && (regs.spcflags & SPCFLAG_DOTRACE) == 0)
SPCFLAGS_SET( SPCFLAG_STOP );
}
extern uae_u32 get_disp_ea_020 (uae_u32 base, uae_u32 dp);
extern uae_u32 get_disp_ea_000 (uae_u32 base, uae_u32 dp);
extern uae_s32 ShowEA (int reg, amodes mode, wordsizes size, char *buf);
extern void MakeSR (void);
extern void MakeFromSR (void);
extern void Exception (int, uaecptr);
extern void dump_counts (void);
extern int m68k_move2c (int, uae_u32 *);
extern int m68k_movec2 (int, uae_u32 *);
extern void m68k_divl (uae_u32, uae_u32, uae_u16, uaecptr);
extern void m68k_mull (uae_u32, uae_u32, uae_u16);
extern void m68k_emulop (uae_u32);
extern void m68k_emulop_return (void);
extern void init_m68k (void);
extern void exit_m68k (void);
extern void m68k_dumpstate (uaecptr *);
extern void m68k_disasm (uaecptr, uaecptr *, int);
extern void m68k_reset (void);
extern void m68k_enter_debugger(void);
extern int m68k_do_specialties(void);
extern void mmu_op (uae_u32, uae_u16);
/* Opcode of faulting instruction */
extern uae_u16 last_op_for_exception_3;
/* PC at fault time */
extern uaecptr last_addr_for_exception_3;
/* Address that generated the exception */
extern uaecptr last_fault_for_exception_3;
#define CPU_OP_NAME(a) op ## a
/* 68020 + 68881 */
extern struct cputbl op_smalltbl_0_ff[];
/* 68020 */
extern struct cputbl op_smalltbl_1_ff[];
/* 68010 */
extern struct cputbl op_smalltbl_2_ff[];
/* 68000 */
extern struct cputbl op_smalltbl_3_ff[];
/* 68000 slow but compatible. */
extern struct cputbl op_smalltbl_4_ff[];
#if FLIGHT_RECORDER
extern void m68k_record_step(uaecptr) REGPARAM;
#endif
extern void m68k_do_execute(void);
extern void m68k_execute(void);
#if USE_JIT
extern void m68k_compile_execute(void);
#endif
#ifdef USE_CPU_EMUL_SERVICES
extern int32 emulated_ticks;
extern void cpu_do_check_ticks(void);
static inline void cpu_check_ticks(void)
{
if (--emulated_ticks <= 0)
cpu_do_check_ticks();
}
#else
#define cpu_check_ticks()
#define cpu_do_check_ticks()
#endif
#endif /* NEWCPU_H */

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,130 @@
#ifndef READCPU_H
#define READCPU_H
#ifdef __cplusplus
extern "C" {
#endif
ENUMDECL {
Dreg, Areg, Aind, Aipi, Apdi, Ad16, Ad8r,
absw, absl, PC16, PC8r, imm, imm0, imm1, imm2, immi, am_unknown, am_illg
} ENUMNAME (amodes);
ENUMDECL {
i_ILLG,
i_OR, i_AND, i_EOR, i_ORSR, i_ANDSR, i_EORSR,
i_SUB, i_SUBA, i_SUBX, i_SBCD,
i_ADD, i_ADDA, i_ADDX, i_ABCD,
i_NEG, i_NEGX, i_NBCD, i_CLR, i_NOT, i_TST,
i_BTST, i_BCHG, i_BCLR, i_BSET,
i_CMP, i_CMPM, i_CMPA,
i_MVPRM, i_MVPMR, i_MOVE, i_MOVEA, i_MVSR2, i_MV2SR,
i_SWAP, i_EXG, i_EXT, i_MVMEL, i_MVMLE,
i_TRAP, i_MVR2USP, i_MVUSP2R, i_RESET, i_NOP, i_STOP, i_RTE, i_RTD,
i_LINK, i_UNLK,
i_RTS, i_TRAPV, i_RTR,
i_JSR, i_JMP, i_BSR, i_Bcc,
i_LEA, i_PEA, i_DBcc, i_Scc,
i_DIVU, i_DIVS, i_MULU, i_MULS,
i_ASR, i_ASL, i_LSR, i_LSL, i_ROL, i_ROR, i_ROXL, i_ROXR,
i_ASRW, i_ASLW, i_LSRW, i_LSLW, i_ROLW, i_RORW, i_ROXLW, i_ROXRW,
i_CHK,i_CHK2,
i_MOVEC2, i_MOVE2C, i_CAS, i_CAS2, i_DIVL, i_MULL,
i_BFTST,i_BFEXTU,i_BFCHG,i_BFEXTS,i_BFCLR,i_BFFFO,i_BFSET,i_BFINS,
i_PACK, i_UNPK, i_TAS, i_BKPT, i_CALLM, i_RTM, i_TRAPcc, i_MOVES,
i_FPP, i_FDBcc, i_FScc, i_FTRAPcc, i_FBcc, i_FSAVE, i_FRESTORE,
i_CINVL, i_CINVP, i_CINVA, i_CPUSHL, i_CPUSHP, i_CPUSHA, i_MOVE16,
i_MMUOP,
i_EMULOP_RETURN, i_EMULOP
} ENUMNAME (instrmnem);
extern struct mnemolookup {
instrmnem mnemo;
const char *name;
} lookuptab[];
ENUMDECL {
sz_byte, sz_word, sz_long
} ENUMNAME (wordsizes);
ENUMDECL {
fa_set, fa_unset, fa_zero, fa_one, fa_dontcare, fa_unknown, fa_isjmp
} ENUMNAME (flagaffect);
ENUMDECL {
fu_used, fu_unused, fu_maybecc, fu_unknown, fu_isjmp
} ENUMNAME (flaguse);
ENUMDECL {
fl_normal = 0,
fl_branch = 1,
fl_jump = 2,
fl_return = 3,
fl_trap = 4,
fl_const_jump = 8,
/* Instructions that can trap don't mark the end of a block */
fl_end_block = 3
} ENUMNAME (cflow_t);
ENUMDECL {
bit0, bit1, bitc, bitC, bitf, biti, bitI, bitj, bitJ, bitk, bitK,
bits, bitS, bitd, bitD, bitr, bitR, bitz, bitE, bitp, lastbit
} ENUMNAME (bitvals);
struct instr_def {
unsigned int bits;
int n_variable;
char bitpos[16];
unsigned int mask;
int cpulevel;
int plevel;
struct {
unsigned int flaguse:3;
unsigned int flagset:3;
} flaginfo[5];
unsigned char cflow;
unsigned char sduse;
const char *opcstr;
};
extern struct instr_def defs68k[];
extern int n_defs68k;
extern struct instr {
long int handler;
unsigned char dreg;
unsigned char sreg;
signed char dpos;
signed char spos;
unsigned char sduse;
int flagdead:8, flaglive:8;
unsigned int mnemo:8;
unsigned int cc:4;
unsigned int plev:2;
unsigned int size:2;
unsigned int smode:5;
unsigned int stype:3;
unsigned int dmode:5;
unsigned int suse:1;
unsigned int duse:1;
unsigned int unused1:1;
unsigned int clev:3;
unsigned int cflow:3;
unsigned int unused2:2;
} *table68k;
extern void read_table68k (void);
extern void do_merges (void);
extern int get_no_mismatches (void);
extern int nr_cpuop_funcs;
extern const char *get_instruction_name (unsigned int opcode);
extern const char *get_instruction_string (unsigned int opcode);
#ifdef __cplusplus
}
#endif
#endif /* READCPU_H */

View File

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

View File

@ -0,0 +1,274 @@
% 0: bit 0
% 1: bit 1
% c: condition code
% C: condition codes, except F
% f: direction
% i: immediate
% E: immediate, except 00 (for EmulOp instructions)
% I: immediate, except 00 and ff
% j: immediate 1..8
% J: immediate 0..15
% k: immediate 0..7
% K: immediate 0..63
% p: immediate 0..3 (CINV and CPUSH instructions: Cache Field)
% s: source mode
% S: source reg
% d: dest mode
% D: dest reg
% r: reg
% z: size
%
% Actually, a sssSSS may appear as a destination, and
% vice versa. The only difference between sssSSS and
% dddDDD are the valid addressing modes. There is
% no match for immediate and pc-rel. addressing modes
% in case of dddDDD.
%
% Arp: --> -(Ar)
% ArP: --> (Ar)+
% L: --> (xxx.L)
%
% Fields on a line:
% 16 chars bitpattern :
% CPU level / privilege level :
% CPU level 0: 68000
% 1: 68010
% 2: 68020
% 3: 68020/68881
% 4: 68040
% privilege level 0: not privileged
% 1: unprivileged only on 68000 (check regs.s)
% 2: privileged (check regs.s)
% 3: privileged if size == word (check regs.s)
% Flags set by instruction: XNZVC :
% Flags used by instruction: XNZVC :
% - means flag unaffected / unused
% 0 means flag reset
% 1 means flag set
% ? means programmer was too lazy to check or instruction may trap
% everything else means flag set/used
% x means flag is unknown and well-behaved programs shouldn't check it
%
% Control flow
% two letters, combination of
% - nothing
% T the instruction may trap or cause an exception
% B branch instruction
% J jump instruction
% R return instruction
%
% srcaddr status destaddr status :
% bitmasks of
% 1 means fetched
% 2 means stored
% 4 means jump offset
% 8 means jump address
% instruction
%
0000 0000 0011 1100:00:XNZVC:XNZVC:--:10: ORSR.B #1
0000 0000 0111 1100:02:XNZVC:XNZVC:T-:10: ORSR.W #1
0000 0zz0 11ss sSSS:20:-?Z?C:-----:T-:11: CHK2.z #1,s[!Dreg,Areg,Aipi,Apdi,Immd]
0000 0000 zzdd dDDD:00:-NZ00:-----:--:13: OR.z #z,d[!Areg]
0000 0010 0011 1100:00:XNZVC:XNZVC:--:10: ANDSR.B #1
0000 0010 0111 1100:02:XNZVC:XNZVC:T-:10: ANDSR.W #1
0000 0010 zzdd dDDD:00:-NZ00:-----:--:13: AND.z #z,d[!Areg]
0000 0100 zzdd dDDD:00:XNZVC:-----:--:13: SUB.z #z,d[!Areg]
0000 0110 zzdd dDDD:00:XNZVC:-----:--:13: ADD.z #z,d[!Areg]
0000 0110 11ss sSSS:20:-----:XNZVC:--:10: CALLM s[!Dreg,Areg,Aipi,Apdi,Immd]
0000 0110 11ss sSSS:20:XNZVC:-----:-R:10: RTM s[Dreg,Areg]
0000 1000 00ss sSSS:00:--Z--:-----:--:11: BTST #1,s[!Areg]
0000 1000 01ss sSSS:00:--Z--:-----:--:13: BCHG #1,s[!Areg,Immd]
0000 1000 10ss sSSS:00:--Z--:-----:--:13: BCLR #1,s[!Areg,Immd]
0000 1000 11ss sSSS:00:--Z--:-----:--:13: BSET #1,s[!Areg,Immd]
0000 1010 0011 1100:00:XNZVC:XNZVC:--:10: EORSR.B #1
0000 1010 0111 1100:02:XNZVC:XNZVC:T-:10: EORSR.W #1
0000 1010 zzdd dDDD:00:-NZ00:-----:--:13: EOR.z #z,d[!Areg]
0000 1100 zzss sSSS:00:-NZVC:-----:--:11: CMP.z #z,s[!Areg,Immd]
0000 1010 11ss sSSS:20:-NZVC:-----:--:13: CAS.B #1,s[!Dreg,Areg,Immd,PC8r,PC16]
0000 1100 11ss sSSS:20:-NZVC:-----:--:13: CAS.W #1,s[!Dreg,Areg,Immd,PC8r,PC16]
0000 1100 1111 1100:20:-NZVC:-----:--:10: CAS2.W #2
0000 1110 zzss sSSS:22:-----:-----:T-:13: MOVES.z #1,s[!Dreg,Areg,Immd,PC8r,PC16]
0000 1110 11ss sSSS:20:-NZVC:-----:--:13: CAS.L #1,s[!Dreg,Areg,Immd,PC8r,PC16]
0000 1110 1111 1100:20:-NZVC:-----:--:10: CAS2.L #2
0000 rrr1 00dd dDDD:00:-----:-----:--:12: MVPMR.W d[Areg-Ad16],Dr
0000 rrr1 01dd dDDD:00:-----:-----:--:12: MVPMR.L d[Areg-Ad16],Dr
0000 rrr1 10dd dDDD:00:-----:-----:--:12: MVPRM.W Dr,d[Areg-Ad16]
0000 rrr1 11dd dDDD:00:-----:-----:--:12: MVPRM.L Dr,d[Areg-Ad16]
0000 rrr1 00ss sSSS:00:--Z--:-----:--:11: BTST Dr,s[!Areg]
0000 rrr1 01ss sSSS:00:--Z--:-----:--:13: BCHG Dr,s[!Areg,Immd]
0000 rrr1 10ss sSSS:00:--Z--:-----:--:13: BCLR Dr,s[!Areg,Immd]
0000 rrr1 11ss sSSS:00:--Z--:-----:--:13: BSET Dr,s[!Areg,Immd]
0001 DDDd ddss sSSS:00:-NZ00:-----:--:12: MOVE.B s,d[!Areg]
0010 DDDd ddss sSSS:00:-----:-----:--:12: MOVEA.L s,d[Areg]
0010 DDDd ddss sSSS:00:-NZ00:-----:--:12: MOVE.L s,d[!Areg]
0011 DDDd ddss sSSS:00:-----:-----:--:12: MOVEA.W s,d[Areg]
0011 DDDd ddss sSSS:00:-NZ00:-----:--:12: MOVE.W s,d[!Areg]
0100 0000 zzdd dDDD:00:XxZxC:X-Z--:--:30: NEGX.z d[!Areg]
0100 0000 11dd dDDD:01:-----:XNZVC:T-:10: MVSR2.W d[!Areg]
0100 0010 zzdd dDDD:00:-0100:-----:--:20: CLR.z d[!Areg]
0100 0010 11dd dDDD:10:-----:XNZVC:--:10: MVSR2.B d[!Areg]
0100 0100 zzdd dDDD:00:XNZVC:-----:--:30: NEG.z d[!Areg]
0100 0100 11ss sSSS:00:XNZVC:-----:--:10: MV2SR.B s[!Areg]
0100 0110 zzdd dDDD:00:-NZ00:-----:--:30: NOT.z d[!Areg]
0100 0110 11ss sSSS:02:XNZVC:XNZVC:T-:10: MV2SR.W s[!Areg]
0100 1000 0000 1rrr:20:-----:-----:--:31: LINK.L Ar,#2
0100 1000 00dd dDDD:00:X?Z?C:X-Z--:--:30: NBCD.B d[!Areg]
0100 1000 0100 1kkk:20:-----:-----:T-:10: BKPT #k
0100 1000 01ss sSSS:00:-NZ00:-----:--:30: SWAP.W s[Dreg]
0100 1000 01ss sSSS:00:-----:-----:--:00: PEA.L s[!Dreg,Areg,Aipi,Apdi,Immd]
0100 1000 10dd dDDD:00:-NZ00:-----:--:30: EXT.W d[Dreg]
0100 1000 10dd dDDD:00:-----:-----:--:02: MVMLE.W #1,d[!Dreg,Areg,Aipi]
0100 1000 11dd dDDD:00:-NZ00:-----:--:30: EXT.L d[Dreg]
0100 1000 11dd dDDD:00:-----:-----:--:02: MVMLE.L #1,d[!Dreg,Areg,Aipi]
0100 1001 11dd dDDD:00:-NZ00:-----:--:30: EXT.B d[Dreg]
0100 1010 zzss sSSS:00:-NZ00:-----:--:10: TST.z s
0100 1010 11dd dDDD:00:-NZ00:-----:--:30: TAS.B d[!Areg]
0100 1010 1111 1100:00:-----:-----:T-:00: ILLEGAL
0100 1100 00ss sSSS:20:-NZVC:-----:--:13: MULL.L #1,s[!Areg]
0100 1100 01ss sSSS:20:-NZV0:-----:T-:13: DIVL.L #1,s[!Areg]
0100 1100 10ss sSSS:00:-----:-----:--:01: MVMEL.W #1,s[!Dreg,Areg,Apdi,Immd]
0100 1100 11ss sSSS:00:-----:-----:--:01: MVMEL.L #1,s[!Dreg,Areg,Apdi,Immd]
0100 1110 0100 JJJJ:00:-----:XNZVC:--:10: TRAP #J
0100 1110 0101 0rrr:00:-----:-----:--:31: LINK.W Ar,#1
0100 1110 0101 1rrr:00:-----:-----:--:30: UNLK.L Ar
0100 1110 0110 0rrr:02:-----:-----:T-:10: MVR2USP.L Ar
0100 1110 0110 1rrr:02:-----:-----:T-:20: MVUSP2R.L Ar
0100 1110 0111 0000:02:-----:-----:T-:00: RESET
0100 1110 0111 0001:00:-----:-----:--:00: NOP
0100 1110 0111 0010:02:XNZVC:-----:T-:10: STOP #1
0100 1110 0111 0011:02:XNZVC:-----:TR:00: RTE
0100 1110 0111 0100:00:-----:-----:-R:10: RTD #1
0100 1110 0111 0101:00:-----:-----:-R:00: RTS
0100 1110 0111 0110:00:-----:XNZVC:T-:00: TRAPV
0100 1110 0111 0111:00:XNZVC:-----:-R:00: RTR
0100 1110 0111 1010:12:-----:-----:T-:10: MOVEC2 #1
0100 1110 0111 1011:12:-----:-----:T-:10: MOVE2C #1
0100 1110 10ss sSSS:00:-----:-----:-J:80: JSR.L s[!Dreg,Areg,Aipi,Apdi,Immd]
0100 rrr1 00ss sSSS:00:-N???:-----:T-:11: CHK.L s[!Areg],Dr
0100 rrr1 10ss sSSS:00:-N???:-----:T-:11: CHK.W s[!Areg],Dr
0100 1110 11ss sSSS:00:-----:-----:-J:80: JMP.L s[!Dreg,Areg,Aipi,Apdi,Immd]
0100 rrr1 11ss sSSS:00:-----:-----:--:02: LEA.L s[!Dreg,Areg,Aipi,Apdi,Immd],Ar
0101 jjj0 01dd dDDD:00:-----:-----:--:13: ADDA.W #j,d[Areg]
0101 jjj0 10dd dDDD:00:-----:-----:--:13: ADDA.L #j,d[Areg]
0101 jjj0 zzdd dDDD:00:XNZVC:-----:--:13: ADD.z #j,d[!Areg]
0101 jjj1 01dd dDDD:00:-----:-----:--:13: SUBA.W #j,d[Areg]
0101 jjj1 10dd dDDD:00:-----:-----:--:13: SUBA.L #j,d[Areg]
0101 jjj1 zzdd dDDD:00:XNZVC:-----:--:13: SUB.z #j,d[!Areg]
0101 cccc 1100 1rrr:00:-----:-????:-B:31: DBcc.W Dr,#1
0101 cccc 11dd dDDD:00:-----:-????:--:20: Scc.B d[!Areg]
0101 cccc 1111 1010:20:-----:-????:T-:10: TRAPcc #1
0101 cccc 1111 1011:20:-----:-????:T-:10: TRAPcc #2
0101 cccc 1111 1100:20:-----:-????:T-:00: TRAPcc
% Bxx.L is 68020 only, but setting the CPU level to 2 would give illegal
% instruction exceptions when compiling a 68000 only emulation, which isn't
% what we want either.
0110 0001 0000 0000:00:-----:-----:-B:40: BSR.W #1
0110 0001 IIII IIII:00:-----:-----:-B:40: BSR.B #i
0110 0001 1111 1111:00:-----:-----:-B:40: BSR.L #2
0110 CCCC 0000 0000:00:-----:-????:-B:40: Bcc.W #1
0110 CCCC IIII IIII:00:-----:-????:-B:40: Bcc.B #i
0110 CCCC 1111 1111:00:-----:-????:-B:40: Bcc.L #2
0111 rrr0 iiii iiii:00:-NZ00:-----:--:12: MOVE.L #i,Dr
1000 rrr0 zzss sSSS:00:-NZ00:-----:--:13: OR.z s[!Areg],Dr
1000 rrr0 11ss sSSS:00:-NZV0:-----:T-:13: DIVU.W s[!Areg],Dr
1000 rrr1 00dd dDDD:00:XxZxC:X-Z--:--:13: SBCD.B d[Dreg],Dr
1000 rrr1 00dd dDDD:00:XxZxC:X-Z--:--:13: SBCD.B d[Areg-Apdi],Arp
1000 rrr1 zzdd dDDD:00:-NZ00:-----:--:13: OR.z Dr,d[!Areg,Dreg]
1000 rrr1 01dd dDDD:20:-----:-----:--:12: PACK d[Dreg],Dr
1000 rrr1 01dd dDDD:20:-----:-----:--:12: PACK d[Areg-Apdi],Arp
1000 rrr1 10dd dDDD:20:-----:-----:--:12: UNPK d[Dreg],Dr
1000 rrr1 10dd dDDD:20:-----:-----:--:12: UNPK d[Areg-Apdi],Arp
1000 rrr1 11ss sSSS:00:-NZV0:-----:T-:13: DIVS.W s[!Areg],Dr
1001 rrr0 zzss sSSS:00:XNZVC:-----:--:13: SUB.z s,Dr
1001 rrr0 11ss sSSS:00:-----:-----:--:13: SUBA.W s,Ar
1001 rrr1 zzdd dDDD:00:XNZVC:X-Z--:--:13: SUBX.z d[Dreg],Dr
1001 rrr1 zzdd dDDD:00:XNZVC:X-Z--:--:13: SUBX.z d[Areg-Apdi],Arp
1001 rrr1 zzdd dDDD:00:XNZVC:-----:--:13: SUB.z Dr,d[!Areg,Dreg]
1001 rrr1 11ss sSSS:00:-----:-----:--:13: SUBA.L s,Ar
1011 rrr0 zzss sSSS:00:-NZVC:-----:--:11: CMP.z s,Dr
1011 rrr0 11ss sSSS:00:-NZVC:-----:--:11: CMPA.W s,Ar
1011 rrr1 11ss sSSS:00:-NZVC:-----:--:11: CMPA.L s,Ar
1011 rrr1 zzdd dDDD:00:-NZVC:-----:--:11: CMPM.z d[Areg-Aipi],ArP
1011 rrr1 zzdd dDDD:00:-NZ00:-----:--:13: EOR.z Dr,d[!Areg]
1100 rrr0 zzss sSSS:00:-NZ00:-----:--:13: AND.z s[!Areg],Dr
1100 rrr0 11ss sSSS:00:-NZ00:-----:--:13: MULU.W s[!Areg],Dr
1100 rrr1 00dd dDDD:00:XxZxC:X-Z--:--:13: ABCD.B d[Dreg],Dr
1100 rrr1 00dd dDDD:00:XxZxC:X-Z--:--:13: ABCD.B d[Areg-Apdi],Arp
1100 rrr1 zzdd dDDD:00:-NZ00:-----:--:13: AND.z Dr,d[!Areg,Dreg]
1100 rrr1 01dd dDDD:00:-----:-----:--:33: EXG.L Dr,d[Dreg]
1100 rrr1 01dd dDDD:00:-----:-----:--:33: EXG.L Ar,d[Areg]
1100 rrr1 10dd dDDD:00:-----:-----:--:33: EXG.L Dr,d[Areg]
1100 rrr1 11ss sSSS:00:-NZ00:-----:--:13: MULS.W s[!Areg],Dr
1101 rrr0 zzss sSSS:00:XNZVC:-----:--:13: ADD.z s,Dr
1101 rrr0 11ss sSSS:00:-----:-----:--:13: ADDA.W s,Ar
1101 rrr1 zzdd dDDD:00:XNZVC:X-Z--:--:13: ADDX.z d[Dreg],Dr
1101 rrr1 zzdd dDDD:00:XNZVC:X-Z--:--:13: ADDX.z d[Areg-Apdi],Arp
1101 rrr1 zzdd dDDD:00:XNZVC:-----:--:13: ADD.z Dr,d[!Areg,Dreg]
1101 rrr1 11ss sSSS:00:-----:-----:--:13: ADDA.L s,Ar
1110 jjjf zz00 0RRR:00:XNZVC:-----:--:13: ASf.z #j,DR
1110 jjjf zz00 1RRR:00:XNZ0C:-----:--:13: LSf.z #j,DR
1110 jjjf zz01 0RRR:00:XNZ0C:X----:--:13: ROXf.z #j,DR
1110 jjjf zz01 1RRR:00:-NZ0C:-----:--:13: ROf.z #j,DR
1110 rrrf zz10 0RRR:00:XNZVC:-----:--:13: ASf.z Dr,DR
1110 rrrf zz10 1RRR:00:XNZ0C:-----:--:13: LSf.z Dr,DR
1110 rrrf zz11 0RRR:00:XNZ0C:X----:--:13: ROXf.z Dr,DR
1110 rrrf zz11 1RRR:00:-NZ0C:-----:--:13: ROf.z Dr,DR
1110 000f 11dd dDDD:00:XNZVC:-----:--:13: ASfW.W d[!Dreg,Areg]
1110 001f 11dd dDDD:00:XNZ0C:-----:--:13: LSfW.W d[!Dreg,Areg]
1110 010f 11dd dDDD:00:XNZ0C:X----:--:13: ROXfW.W d[!Dreg,Areg]
1110 011f 11dd dDDD:00:-NZ0C:-----:--:13: ROfW.W d[!Dreg,Areg]
1110 1000 11ss sSSS:20:-NZ00:-----:--:11: BFTST #1,s[!Areg,Apdi,Aipi,Immd]
1110 1001 11ss sSSS:20:-NZ00:-----:--:11: BFEXTU #1,s[!Areg,Apdi,Aipi,Immd]
1110 1010 11ss sSSS:20:-NZ00:-----:--:13: BFCHG #1,s[!Areg,Apdi,Aipi,Immd,PC8r,PC16]
1110 1011 11ss sSSS:20:-NZ00:-----:--:11: BFEXTS #1,s[!Areg,Apdi,Aipi,Immd]
1110 1100 11ss sSSS:20:-NZ00:-----:--:13: BFCLR #1,s[!Areg,Apdi,Aipi,Immd,PC8r,PC16]
1110 1101 11ss sSSS:20:-NZ00:-----:--:11: BFFFO #1,s[!Areg,Apdi,Aipi,Immd]
1110 1110 11ss sSSS:20:-NZ00:-----:--:13: BFSET #1,s[!Areg,Apdi,Aipi,Immd,PC8r,PC16]
1110 1111 11ss sSSS:20:-NZ00:-----:--:13: BFINS #1,s[!Areg,Apdi,Aipi,Immd,PC8r,PC16]
% floating point co processor
1111 0010 00ss sSSS:30:-----:-----:--:11: FPP #1,s
1111 0010 01ss sSSS:30:-----:-----:-B:11: FDBcc #1,s[Areg-Dreg]
1111 0010 01ss sSSS:30:-----:-----:--:11: FScc #1,s[!Areg,Immd,PC8r,PC16]
1111 0010 0111 1010:30:-----:-----:T-:10: FTRAPcc #1
1111 0010 0111 1011:30:-----:-----:T-:10: FTRAPcc #2
1111 0010 0111 1100:30:-----:-----:T-:00: FTRAPcc
1111 0010 10KK KKKK:30:-----:-----:-B:11: FBcc #K,#1
1111 0010 11KK KKKK:30:-----:-----:-B:11: FBcc #K,#2
1111 0011 00ss sSSS:32:-----:-----:--:20: FSAVE s[!Dreg,Areg,Aipi,Immd,PC8r,PC16]
1111 0011 01ss sSSS:32:-----:-----:--:10: FRESTORE s[!Dreg,Areg,Apdi,Immd]
% 68040 instructions
1111 0101 iiii iSSS:40:-----:-----:T-:11: MMUOP #i,s
1111 0100 pp00 1rrr:42:-----:-----:T-:02: CINVL #p,Ar
1111 0100 pp01 0rrr:42:-----:-----:T-:02: CINVP #p,Ar
1111 0100 pp01 1rrr:42:-----:-----:T-:00: CINVA #p
1111 0100 pp10 1rrr:42:-----:-----:T-:02: CPUSHL #p,Ar
1111 0100 pp11 0rrr:42:-----:-----:T-:02: CPUSHP #p,Ar
1111 0100 pp11 1rrr:42:-----:-----:T-:00: CPUSHA #p
% destination register number is encoded in the following word
1111 0110 0010 0rrr:40:-----:-----:--:12: MOVE16 ArP,AxP
1111 0110 00ss sSSS:40:-----:-----:--:12: MOVE16 s[Dreg-Aipi],L
1111 0110 00dd dDDD:40:-----:-----:--:12: MOVE16 L,d[Areg-Aipi]
1111 0110 00ss sSSS:40:-----:-----:--:12: MOVE16 s[Aind],L
1111 0110 00dd dDDD:40:-----:-----:--:12: MOVE16 L,d[Aipi-Aind]
% EmulOp instructions
0111 0001 0000 0000:00:-----:-----:-R:00: EMULOP_RETURN
0111 0001 EEEE EEEE:00:-----:-----:-J:10: EMULOP #E