fix for Linux and Windows
This commit is contained in:
parent
e42b8f6076
commit
5862662bc9
|
@ -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,
|
||||
);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
|
@ -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 = ¤t->next;
|
||||
current->prev = prev; prev = current;
|
||||
current->next = NULL;
|
||||
current->delet = 0;
|
||||
current->data = strdup (tmp);
|
||||
if (match (current, "movl %esp,%ebp") || match (current, "enter")) {
|
||||
fprintf (stderr, "GCC failed to eliminate fp: %s\n", first_line->data);
|
||||
can_opt = 0;
|
||||
}
|
||||
|
||||
if (match (current, "ret"))
|
||||
nr_rets++;
|
||||
}
|
||||
if ((fgets(tmp, 4095, infile)) == NULL)
|
||||
oops();
|
||||
s = strchr (tmp, '\n');
|
||||
if (s != NULL)
|
||||
*s = 0;
|
||||
} while (strncmp (tmp,".Lfe", 4) != 0);
|
||||
|
||||
f.first_line = first_line;
|
||||
f.last_line = prev;
|
||||
|
||||
if (nr_rets == 1 && can_opt)
|
||||
do_function(&f);
|
||||
/*else
|
||||
fprintf(stderr, "Too many RET instructions: %s\n", first_line->data);*/
|
||||
output_function(&f);
|
||||
}
|
||||
printf("%s\n", tmp);
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -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 */
|
|
@ -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
|
|
@ -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 */
|
|
@ -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
|
|
@ -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 */
|
|
@ -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
|
@ -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
|
@ -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
|
@ -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 */
|
|
@ -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
|
|
@ -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 */
|
|
@ -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
|
@ -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
|
|
@ -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 */
|
|
@ -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
|
@ -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 */
|
||||
|
|
@ -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
|
@ -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 *)®s.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 *)®s.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(®s.prefetch);
|
||||
return (do_get_mem_word (((uae_u16 *)®s.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 (®s.prefetch, r);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
#if 0
|
||||
static __inline__ void fill_prefetch_2 (void)
|
||||
{
|
||||
uae_u32 r = do_get_mem_long (®s.prefetch) << 16;
|
||||
uae_u32 r2 = do_get_mem_word (((uae_u16 *)regs.pc_p) + 1);
|
||||
r |= r2;
|
||||
do_put_mem_long (®s.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 */
|
|
@ -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
|
@ -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 */
|
|
@ -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 */
|
|
@ -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
|
Loading…
Reference in New Issue