Downgraded emulated UAE cpu

This commit is contained in:
uyjulian 2018-04-15 17:33:50 -05:00
parent 023251dee1
commit 1bf6e93461
No known key found for this signature in database
GPG Key ID: FEA459A8CA14685B
28 changed files with 977 additions and 7087 deletions

View File

@ -76,7 +76,7 @@ set(BasiliskII_SRCS
../uae_cpu/basilisk_glue.cpp
../uae_cpu/newcpu.cpp
../uae_cpu/readcpu.cpp
../uae_cpu/fpu/fpu_uae.cpp
# ../uae_cpu/fpp.cpp
cpustbl.cpp
cpudefs.cpp
cpuemu.cpp
@ -87,7 +87,7 @@ set(BasiliskII_SRCS
add_executable(BasiliskII ${BasiliskII_SRCS})
set_source_files_properties(${BasiliskII_SRCS}
PROPERTIES COMPILE_FLAGS "-DDIRECT_ADDRESSING -DFPU_UAE -DDATADIR=\\\".\\\"")
PROPERTIES COMPILE_FLAGS "-DDIRECT_ADDRESSING -DDATADIR=\\\".\\\"")
target_link_libraries(BasiliskII ${COREFOUNDATION_LIBRARY} ${IOKIT_LIBRARY} ${SDL_LIBRARY})

View File

@ -1,7 +1,7 @@
/*
* basilisk_glue.cpp - Glue UAE CPU to Basilisk II CPU engine interface
*
* Basilisk II (C) 1997-2008 Christian Bauer
* Basilisk II (C) 1997-1999 Christian Bauer
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -19,10 +19,8 @@
*/
#include "sysdeps.h"
#include "cpu_emulation.h"
#include "main.h"
#include "prefs.h"
#include "emul_op.h"
#include "rom_patches.h"
#include "timer.h"
@ -31,26 +29,27 @@
#include "readcpu.h"
#include "newcpu.h"
// RAM and ROM pointers
uint32 RAMBaseMac = 0; // RAM base (Mac address space) gb-- initializer is important
uint32 RAMBaseMac; // RAM base (Mac address space)
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
// From newcpu.cpp
extern bool quit_program;
extern int quit_program;
/*
@ -59,7 +58,7 @@ extern bool quit_program;
bool Init680x0(void)
{
#if DIRECT_ADDRESSING
#if REAL_ADDRESSING
// Mac address space = host address space minus constant offset (MEMBaseDiff)
// NOTE: MEMBaseDiff is set up in main_unix.cpp/main()
RAMBaseMac = 0;
@ -67,7 +66,6 @@ bool Init680x0(void)
#endif
init_m68k();
return true;
}
@ -78,20 +76,9 @@ bool Init680x0(void)
void Exit680x0(void)
{
exit_m68k();
}
/*
* Initialize memory mapping of frame buffer (called upon video mode change)
*/
void InitFrameBufferMapping(void)
{
}
/*
* Reset and start 680x0 emulation (doesn't return)
*/
@ -99,8 +86,7 @@ void InitFrameBufferMapping(void)
void Start680x0(void)
{
m68k_reset();
m68k_execute();
m68k_go(true);
}
@ -111,7 +97,7 @@ void Start680x0(void)
void TriggerInterrupt(void)
{
idle_resume();
SPCFLAGS_SET( SPCFLAG_INT );
regs.spcflags |= SPCFLAG_INT;
}
void TriggerNMI(void)
@ -157,8 +143,8 @@ void Execute68kTrap(uint16 trap, struct M68kRegisters *r)
// Execute trap
m68k_setpc(m68k_areg(regs, 7));
fill_prefetch_0();
quit_program = false;
m68k_execute();
quit_program = 0;
m68k_go(true);
// Clean up stack
m68k_areg(regs, 7) += 4;
@ -172,7 +158,7 @@ void Execute68kTrap(uint16 trap, struct M68kRegisters *r)
r->d[i] = m68k_dreg(regs, i);
for (i=0; i<7; i++)
r->a[i] = m68k_areg(regs, i);
quit_program = false;
quit_program = 0;
}
@ -204,8 +190,8 @@ void Execute68k(uint32 addr, struct M68kRegisters *r)
// Execute routine
m68k_setpc(addr);
fill_prefetch_0();
quit_program = false;
m68k_execute();
quit_program = 0;
m68k_go(true);
// Clean up stack
m68k_areg(regs, 7) += 2;
@ -219,5 +205,5 @@ void Execute68k(uint32 addr, struct M68kRegisters *r)
r->d[i] = m68k_dreg(regs, i);
for (i=0; i<7; i++)
r->a[i] = m68k_areg(regs, i);
quit_program = false;
quit_program = 0;
}

View File

@ -4,20 +4,6 @@
* 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>
@ -72,7 +58,15 @@ int main(int argc, char **argv)
printf ("#include \"sysdeps.h\"\n");
printf ("#include \"readcpu.h\"\n");
printf ("struct instr_def defs68k[] = {\n");
#if 0
tablef = fopen("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;
@ -82,7 +76,6 @@ int main(int argc, char **argv)
char opcstr[256];
int bitpos[16];
int flagset[5], flaguse[5];
char cflow;
unsigned int bitmask,bitpattern;
int n_variable;
@ -114,8 +107,6 @@ int main(int argc, char **argv)
case 'r': currbit = bitr; break;
case 'R': currbit = bitR; break;
case 'z': currbit = bitz; break;
case 'E': currbit = bitE; break;
case 'p': currbit = bitp; break;
default: abort();
}
if (!(bitmask & 1)) {
@ -164,6 +155,7 @@ int main(int argc, char **argv)
getnextch();
switch(nextch){
case '-': flagset[i] = fa_unset; break;
case '/': flagset[i] = fa_isjmp; break;
case '0': flagset[i] = fa_zero; break;
case '1': flagset[i] = fa_one; break;
case 'x': flagset[i] = fa_dontcare; break;
@ -183,31 +175,13 @@ int main(int argc, char **argv)
getnextch();
switch(nextch){
case '-': flaguse[i] = fu_unused; break;
case '/': flaguse[i] = fu_isjmp; break;
case '+': flaguse[i] = fu_maybecc; break;
case '?': flaguse[i] = fu_unknown; break;
default: flaguse[i] = fu_used; break;
}
}
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();
@ -259,10 +233,9 @@ int main(int argc, char **argv)
for(i = 0; i < 5; i++) {
printf("{ %d, %d }%c ", flaguse[i], flagset[i], i == 4 ? ' ' : ',');
}
printf("}, %d, %d, \"%s\"}", cflow, sduse, opstrp);
printf("}, %d, \"%s\"}", sduse, opstrp);
}
}
printf("};\nint n_defs68k = %d;\n", no_insns);
fflush(stdout);
return 0;
}

View File

@ -1,7 +1,7 @@
/*
* cpu_emulation.h - Definitions for Basilisk II CPU emulation module (UAE 0.8.10 version)
* cpu_emulation.h - Definitions for Basilisk II CPU emulation module (UAE 0.8.8 version)
*
* Basilisk II (C) 1997-2008 Christian Bauer
* Basilisk II (C) 1997-1999 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
@ -21,8 +21,6 @@
#ifndef CPU_EMULATION_H
#define CPU_EMULATION_H
#include <string.h>
/*
* Memory system
@ -37,7 +35,15 @@ 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
// If we are not using real addressing, the Mac frame buffer gets mapped to this location
// The memory must be allocated by VideoInit(). If multiple monitors are used, they must
// share the frame buffer
const uint32 MacFrameBaseMac = 0xa0000000;
extern uint8 *MacFrameBaseHost; // Frame buffer base (host address space)
extern uint32 MacFrameSize; // Size of frame buffer
extern int MacFrameLayout; // Frame buffer layout (see defines below)
#endif
// Possible frame buffer layouts
enum {
@ -72,7 +78,6 @@ static inline void *Mac2Mac_memcpy(uint32 dest, uint32 src, size_t n) {return me
// 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 emulation functions
struct M68kRegisters;

View File

@ -5,20 +5,6 @@
* 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>
@ -41,7 +27,7 @@ struct func {
static void oops(void)
{
fprintf(stderr, "Don't know how to optimize this file.\n");
exit(1);
abort();
}
static char * match(struct line *l, const char *m)
@ -60,7 +46,7 @@ static int insn_references_reg (struct line *l, char *reg)
{
if (reg[0] != 'e') {
fprintf(stderr, "Unknown register?!?\n");
exit(1);
abort();
}
if (strstr (l->data, reg) != 0)
return 1;
@ -135,7 +121,7 @@ static void do_function(struct func *f)
l3 = l3->prev;
}
if (l3 == l2)
exit(1);
abort();
for (l4 = l2; l4 != l3; l4 = l4->prev) {
/* The register may not be referenced by any of the insns that we
* move the popl past */

View File

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

View File

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

View File

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

View File

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

View File

@ -1,217 +0,0 @@
/*
* 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
#ifdef FPU_IMPLEMENTATION
/* -------------------------------------------------------------------------- */
/* --- Native X86 Floating-Point Flags --- */
/* -------------------------------------------------------------------------- */
/* FPU_X86 has its own set of lookup functions */
#ifdef FPU_USE_X86_FLAGS
#define FPU_USE_NATIVE_FLAGS
#define NATIVE_FFLAG_NEGATIVE 0x0200
#define NATIVE_FFLAG_ZERO 0x4000
#define NATIVE_FFLAG_INFINITY 0x0500
#define NATIVE_FFLAG_NAN 0x0100
/* Translation tables between native and m68k floating-point flags */
PRIVATE uae_u32 to_m68k_fpcond[0x48];
PRIVATE uae_u32 to_host_fpcond[0x10];
/* Truth table for floating-point condition codes */
PRIVATE uae_u32 fpcond_truth_table[32][8]; // 32 m68k conditions x 8 host condition codes
/* Initialization */
PUBLIC void FFPU fpu_init_native_fflags(void);
#ifdef FPU_UAE
/* Native to m68k floating-point condition codes */
PRIVATE inline uae_u32 FFPU get_fpccr(void)
{ return to_m68k_fpcond[(FPU fpsr.condition_codes >> 8) & 0x47]; }
/* M68k to native floating-point condition codes */
PRIVATE inline void FFPU set_fpccr(uae_u32 new_fpcond)
/* Precondition: new_fpcond is only valid for floating-point condition codes */
{ FPU fpsr.condition_codes = to_host_fpcond[new_fpcond >> 24]; }
/* Make FPSR according to the value passed in argument */
PRIVATE inline void FFPU make_fpsr(fpu_register const & r)
{ uae_u16 sw; __asm__ __volatile__ ("fxam\n\tfnstsw %0" : "=r" (sw) : "f" (r)); FPU fpsr.condition_codes = sw; }
/* Return the corresponding ID of the current floating-point condition codes */
/* NOTE: only valid for evaluation of a condition */
PRIVATE inline int FFPU host_fpcond_id(void)
{ return ((FPU fpsr.condition_codes >> 12) & 4) | ((FPU fpsr.condition_codes >> 8) & 3); }
/* Return true if the floating-point condition is satisfied */
PRIVATE inline bool FFPU fpcctrue(int condition)
{ return fpcond_truth_table[condition][host_fpcond_id()]; }
#endif /* FPU_UAE */
/* Return the address of the floating-point condition codes truth table */
static inline uae_u8 * const FFPU address_of_fpcond_truth_table(void)
{ return ((uae_u8*)&fpcond_truth_table[0][0]); }
#endif /* FPU_X86_USE_NATIVE_FLAGS */
/* -------------------------------------------------------------------------- */
/* --- Use Original M68K FPU Mappings --- */
/* -------------------------------------------------------------------------- */
#ifdef FPU_USE_GENERIC_FLAGS
#undef FPU_USE_NATIVE_FLAGS
#define NATIVE_FFLAG_NEGATIVE 0x08000000
#define NATIVE_FFLAG_ZERO 0x04000000
#define NATIVE_FFLAG_INFINITY 0x02000000
#define NATIVE_FFLAG_NAN 0x01000000
/* Initialization - NONE */
PRIVATE inline void FFPU fpu_init_native_fflags(void)
{ }
/* Native to m68k floating-point condition codes - SELF */
PRIVATE inline uae_u32 FFPU get_fpccr(void)
{ return FPU fpsr.condition_codes; }
/* M68k to native floating-point condition codes - SELF */
PRIVATE inline void FFPU set_fpccr(uae_u32 new_fpcond)
{ FPU fpsr.condition_codes = new_fpcond; }
#endif /* FPU_USE_GENERIC_FLAGS */
/* -------------------------------------------------------------------------- */
/* --- Use Lazy Flags Evaluation --- */
/* -------------------------------------------------------------------------- */
#ifdef FPU_USE_LAZY_FLAGS
#undef FPU_USE_NATIVE_FLAGS
#define NATIVE_FFLAG_NEGATIVE 0x08000000
#define NATIVE_FFLAG_ZERO 0x04000000
#define NATIVE_FFLAG_INFINITY 0x02000000
#define NATIVE_FFLAG_NAN 0x01000000
/* Initialization - NONE */
PRIVATE inline void FFPU fpu_init_native_fflags(void)
{ }
/* Native to m68k floating-point condition codes - SELF */
PRIVATE inline uae_u32 FFPU get_fpccr(void)
{
uae_u32 fpccr = 0;
if (isnan(FPU result))
fpccr |= FPSR_CCB_NAN;
else if (FPU result == 0.0)
fpccr |= FPSR_CCB_ZERO;
else if (FPU result < 0.0)
fpccr |= FPSR_CCB_NEGATIVE;
if (isinf(FPU result))
fpccr |= FPSR_CCB_INFINITY;
return fpccr;
}
/* M68k to native floating-point condition codes - SELF */
PRIVATE inline void FFPU set_fpccr(uae_u32 new_fpcond)
{
if (new_fpcond & FPSR_CCB_NAN)
make_nan(FPU result);
else if (new_fpcond & FPSR_CCB_ZERO)
FPU result = 0.0;
else if (new_fpcond & FPSR_CCB_NEGATIVE)
FPU result = -1.0;
else
FPU result = +1.0;
/* gb-- where is Infinity ? */
}
/* Make FPSR according to the value passed in argument */
PRIVATE inline void FFPU make_fpsr(fpu_register const & r)
{ FPU result = r; }
#endif /* FPU_USE_LAZY_FLAGS */
#endif
/* -------------------------------------------------------------------------- */
/* --- Common methods --- */
/* -------------------------------------------------------------------------- */
/* Return the address of the floating-point condition codes register */
static inline uae_u32 * const FFPU address_of_fpccr(void)
{ return ((uae_u32 *)& FPU fpsr.condition_codes); }
#endif /* FPU_FLAGS_H */

View File

@ -1,49 +0,0 @@
/*
* fpu/fpu.h - public header
*
* Basilisk II (C) 1997-2008 Christian Bauer
*
* MC68881/68040 fpu emulation
*
* Original UAE FPU, copyright 1996 Herman ten Brugge
* Rewrite for x86, copyright 1999-2000 Lauri Pesonen
* New framework, copyright 2000 Gwenole Beauchesne
* Adapted for JIT compilation (c) Bernd Meyer, 2000
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef FPU_PUBLIC_HEADER_H
#define FPU_PUBLIC_HEADER_H
#ifndef FPU_DEBUG
#define FPU_DEBUG 0
#endif
#if FPU_DEBUG
#define fpu_debug(args) printf args;
#define FPU_DUMP_REGISTERS 0
#define FPU_DUMP_FIRST_BYTES 0
#else
#define fpu_debug(args) ;
#undef FPU_DUMP_REGISTERS
#undef FPU_DUMP_FIRST_BYTES
#endif
#include "sysdeps.h"
#include "fpu/types.h"
#include "fpu/core.h"
#endif /* FPU_PUBLIC_HEADER_H */

File diff suppressed because it is too large Load Diff

View File

@ -1,212 +0,0 @@
/*
* 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 */

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -1,64 +0,0 @@
/*
* fpu/rounding.cpp - system-dependant FPU rounding mode and precision
*
* Basilisk II (C) 1997-2008 Christian Bauer
*
* MC68881/68040 fpu emulation
*
* Original UAE FPU, copyright 1996 Herman ten Brugge
* Rewrite for x86, copyright 1999-2000 Lauri Pesonen
* New framework, copyright 2000 Gwenole Beauchesne
* Adapted for JIT compilation (c) Bernd Meyer, 2000
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#undef PRIVATE
#define PRIVATE /**/
#undef PUBLIC
#define PUBLIC /**/
#undef FFPU
#define FFPU /**/
#undef FPU
#define FPU fpu.
/* -------------------------------------------------------------------------- */
/* --- Native X86 Rounding Mode --- */
/* -------------------------------------------------------------------------- */
#ifdef FPU_USE_X86_ROUNDING_MODE
const uae_u32 FFPU x86_control_word_rm_mac2host[] = {
CW_RC_NEAR,
CW_RC_ZERO,
CW_RC_DOWN,
CW_RC_UP
};
#endif
/* -------------------------------------------------------------------------- */
/* --- Native X86 Rounding Precision --- */
/* -------------------------------------------------------------------------- */
#ifdef FPU_USE_X86_ROUNDING_PRECISION
const uae_u32 FFPU x86_control_word_rp_mac2host[] = {
CW_PC_EXTENDED,
CW_PC_SINGLE,
CW_PC_DOUBLE,
CW_PC_RESERVED
};
#endif

View File

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

View File

@ -1,135 +0,0 @@
/*
* 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 */
typedef float uae_f32;
/* 8-byte floats */
typedef double uae_f64;
/* 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 */
typedef float uae_f32;
/* 8-byte floats */
typedef double uae_f64;
/* 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

View File

@ -1,65 +1,34 @@
/*
* UAE - The Un*x Amiga Emulator
*
* MC68000 emulation - machine dependent bits
*
* 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
*/
/*
* UAE - The Un*x Amiga Emulator
*
* MC68000 emulation - machine dependent bits
*
* Copyright 1996 Bernd Schmidt
*/
#ifndef M68K_FLAGS_H
#define M68K_FLAGS_H
#if defined(__i386__) && defined(X86_ASSEMBLY)
#ifdef OPTIMIZED_FLAGS
#if defined(X86_ASSEMBLY) || defined(X86_64_ASSEMBLY) || defined(MSVC_INTRINSICS)
#ifndef SAHF_SETO_PROFITABLE
/* PUSH/POP instructions are naturally 64-bit sized on x86-64, thus
unsigned long hereunder is either 64-bit or 32-bit wide depending
on the target. */
struct flag_struct {
unsigned long cznv;
unsigned long x;
unsigned int cznv;
unsigned int x;
};
#define FLAGVAL_Z 0x40
#define FLAGVAL_N 0x80
#define SET_ZFLG(y) (regflags.cznv = (regflags.cznv & ~0x40) | (((y) & 1) << 6))
#define SET_CFLG(y) (regflags.cznv = (regflags.cznv & ~1) | ((y) & 1))
#define SET_VFLG(y) (regflags.cznv = (regflags.cznv & ~0x800) | (((y) & 1) << 11))
#define SET_NFLG(y) (regflags.cznv = (regflags.cznv & ~0x80) | (((y) & 1) << 7))
#define SET_XFLG(y) (regflags.x = (y))
#define SET_ZFLG(y) (regflags.cznv = (((uae_u32)regflags.cznv) & ~0x40) | (((y) & 1) << 6))
#define SET_CFLG(y) (regflags.cznv = (((uae_u32)regflags.cznv) & ~1) | ((y) & 1))
#define SET_VFLG(y) (regflags.cznv = (((uae_u32)regflags.cznv) & ~0x800) | (((y) & 1) << 11))
#define SET_NFLG(y) (regflags.cznv = (((uae_u32)regflags.cznv) & ~0x80) | (((y) & 1) << 7))
#define SET_XFLG(y) (regflags.x = (y))
#define GET_ZFLG ((regflags.cznv >> 6) & 1)
#define GET_CFLG (regflags.cznv & 1)
#define GET_VFLG ((regflags.cznv >> 11) & 1)
#define GET_NFLG ((regflags.cznv >> 7) & 1)
#define GET_XFLG (regflags.x & 1)
#define GET_ZFLG ((regflags.cznv >> 6) & 1)
#define GET_CFLG (regflags.cznv & 1)
#define GET_VFLG ((regflags.cznv >> 11) & 1)
#define GET_NFLG ((regflags.cznv >> 7) & 1)
#define GET_XFLG (regflags.x & 1)
#define CLEAR_CZNV (regflags.cznv = 0)
#define COPY_CARRY (regflags.x = regflags.cznv)
#define CLEAR_CZNV (regflags.cznv = 0)
#define GET_CZNV (regflags.cznv)
#define IOR_CZNV(X) (regflags.cznv |= (X))
#define SET_CZNV(X) (regflags.cznv = (X))
#define COPY_CARRY (regflags.x = regflags.cznv)
extern struct flag_struct regflags ASM_SYM ("regflags");
extern struct flag_struct regflags __asm__ ("regflags");
static __inline__ int cctrue(int cc)
{
@ -89,270 +58,91 @@ static __inline__ int cctrue(int cc)
return 0;
}
#define optflag_testl(v) \
__asm__ __volatile__ ("andl %1,%1\n\t" \
"pushf\n\t" \
"pop %0\n\t" \
#define x86_flag_testl(v) \
__asm__ __volatile__ ("testl %1,%1\n\t" \
"pushfl\n\t" \
"popl %0\n\t" \
: "=r" (regflags.cznv) : "r" (v) : "cc")
#define optflag_testw(v) \
__asm__ __volatile__ ("andw %w1,%w1\n\t" \
"pushf\n\t" \
"pop %0\n\t" \
#define x86_flag_testw(v) \
__asm__ __volatile__ ("testw %w1,%w1\n\t" \
"pushfl\n\t" \
"popl %0\n\t" \
: "=r" (regflags.cznv) : "r" (v) : "cc")
#define optflag_testb(v) \
__asm__ __volatile__ ("andb %b1,%b1\n\t" \
"pushf\n\t" \
"pop %0\n\t" \
#define x86_flag_testb(v) \
__asm__ __volatile__ ("testb %b1,%b1\n\t" \
"pushfl\n\t" \
"popl %0\n\t" \
: "=r" (regflags.cznv) : "q" (v) : "cc")
#define optflag_addl(v, s, d) do { \
#define x86_flag_addl(v, s, d) do { \
__asm__ __volatile__ ("addl %k2,%k1\n\t" \
"pushf\n\t" \
"pop %0\n\t" \
"pushfl\n\t" \
"popl %0\n\t" \
: "=r" (regflags.cznv), "=r" (v) : "rmi" (s), "1" (d) : "cc"); \
COPY_CARRY; \
} while (0)
#define optflag_addw(v, s, d) do { \
#define x86_flag_addw(v, s, d) do { \
__asm__ __volatile__ ("addw %w2,%w1\n\t" \
"pushf\n\t" \
"pop %0\n\t" \
"pushfl\n\t" \
"popl %0\n\t" \
: "=r" (regflags.cznv), "=r" (v) : "rmi" (s), "1" (d) : "cc"); \
COPY_CARRY; \
} while (0)
#define optflag_addb(v, s, d) do { \
#define x86_flag_addb(v, s, d) do { \
__asm__ __volatile__ ("addb %b2,%b1\n\t" \
"pushf\n\t" \
"pop %0\n\t" \
"pushfl\n\t" \
"popl %0\n\t" \
: "=r" (regflags.cznv), "=q" (v) : "qmi" (s), "1" (d) : "cc"); \
COPY_CARRY; \
} while (0)
#define optflag_subl(v, s, d) do { \
#define x86_flag_subl(v, s, d) do { \
__asm__ __volatile__ ("subl %k2,%k1\n\t" \
"pushf\n\t" \
"pop %0\n\t" \
"pushfl\n\t" \
"popl %0\n\t" \
: "=r" (regflags.cznv), "=r" (v) : "rmi" (s), "1" (d) : "cc"); \
COPY_CARRY; \
} while (0)
#define optflag_subw(v, s, d) do { \
#define x86_flag_subw(v, s, d) do { \
__asm__ __volatile__ ("subw %w2,%w1\n\t" \
"pushf\n\t" \
"pop %0\n\t" \
"pushfl\n\t" \
"popl %0\n\t" \
: "=r" (regflags.cznv), "=r" (v) : "rmi" (s), "1" (d) : "cc"); \
COPY_CARRY; \
} while (0)
#define optflag_subb(v, s, d) do { \
#define x86_flag_subb(v, s, d) do { \
__asm__ __volatile__ ("subb %b2,%b1\n\t" \
"pushf\n\t" \
"pop %0\n\t" \
"pushfl\n\t" \
"popl %0\n\t" \
: "=r" (regflags.cznv), "=q" (v) : "qmi" (s), "1" (d) : "cc"); \
COPY_CARRY; \
} while (0)
#define optflag_cmpl(s, d) \
#define x86_flag_cmpl(s, d) \
__asm__ __volatile__ ("cmpl %k1,%k2\n\t" \
"pushf\n\t" \
"pop %0\n\t" \
"pushfl\n\t" \
"popl %0\n\t" \
: "=r" (regflags.cznv) : "rmi" (s), "r" (d) : "cc")
#define optflag_cmpw(s, d) \
#define x86_flag_cmpw(s, d) \
__asm__ __volatile__ ("cmpw %w1,%w2\n\t" \
"pushf\n\t" \
"pop %0\n\t" \
"pushfl\n\t" \
"popl %0\n\t" \
: "=r" (regflags.cznv) : "rmi" (s), "r" (d) : "cc")
#define optflag_cmpb(s, d) \
#define x86_flag_cmpb(s, d) \
__asm__ __volatile__ ("cmpb %b1,%b2\n\t" \
"pushf\n\t" \
"pop %0\n\t" \
"pushfl\n\t" \
"popl %0\n\t" \
: "=r" (regflags.cznv) : "qmi" (s), "q" (d) : "cc")
#else
struct flag_struct {
uae_u32 cznv;
uae_u32 x;
};
#define FLAGVAL_Z 0x4000
#define FLAGVAL_N 0x8000
#define SET_ZFLG(y) (regflags.cznv = (regflags.cznv & ~0x4000) | (((y) & 1) << 14))
#define SET_CFLG(y) (regflags.cznv = (regflags.cznv & ~0x100) | (((y) & 1) << 8))
#define SET_VFLG(y) (regflags.cznv = (regflags.cznv & ~0x1) | (((y) & 1)))
#define SET_NFLG(y) (regflags.cznv = (regflags.cznv & ~0x8000) | (((y) & 1) << 15))
#define SET_XFLG(y) (regflags.x = (y))
#define GET_ZFLG ((regflags.cznv >> 14) & 1)
#define GET_CFLG ((regflags.cznv >> 8) & 1)
#define GET_VFLG ((regflags.cznv >> 0) & 1)
#define GET_NFLG ((regflags.cznv >> 15) & 1)
#define GET_XFLG (regflags.x & 1)
#define CLEAR_CZNV (regflags.cznv = 0)
#define GET_CZNV (regflags.cznv)
#define IOR_CZNV(X) (regflags.cznv |= (X))
#define SET_CZNV(X) (regflags.cznv = (X))
#define COPY_CARRY (regflags.x = (regflags.cznv)>>8)
extern struct flag_struct regflags ASM_SYM("regflags");
static __inline__ int cctrue(int cc)
{
uae_u32 cznv = regflags.cznv;
switch(cc){
case 0: return 1; /* T */
case 1: return 0; /* F */
case 2: return (cznv & 0x4100) == 0; /* !GET_CFLG && !GET_ZFLG; HI */
case 3: return (cznv & 0x4100) != 0; /* GET_CFLG || GET_ZFLG; LS */
case 4: return (cznv & 0x100) == 0; /* !GET_CFLG; CC */
case 5: return (cznv & 0x100) != 0; /* GET_CFLG; CS */
case 6: return (cznv & 0x4000) == 0; /* !GET_ZFLG; NE */
case 7: return (cznv & 0x4000) != 0; /* GET_ZFLG; EQ */
case 8: return (cznv & 0x01) == 0; /* !GET_VFLG; VC */
case 9: return (cznv & 0x01) != 0; /* GET_VFLG; VS */
case 10:return (cznv & 0x8000) == 0; /* !GET_NFLG; PL */
case 11:return (cznv & 0x8000) != 0; /* GET_NFLG; MI */
case 12:return (((cznv << 15) ^ cznv) & 0x8000) == 0; /* GET_NFLG == GET_VFLG; GE */
case 13:return (((cznv << 15) ^ cznv) & 0x8000) != 0;/* GET_NFLG != GET_VFLG; LT */
case 14:
cznv &= 0xc001;
return (((cznv << 15) ^ cznv) & 0xc000) == 0; /* !GET_ZFLG && (GET_NFLG == GET_VFLG); GT */
case 15:
cznv &= 0xc001;
return (((cznv << 15) ^ cznv) & 0xc000) != 0; /* GET_ZFLG || (GET_NFLG != GET_VFLG); LE */
}
abort();
return 0;
}
/* Manually emit LAHF instruction so that 64-bit assemblers can grok it */
#if defined __x86_64__ && defined __GNUC__
#define ASM_LAHF ".byte 0x9f"
#else
#define ASM_LAHF "lahf"
#endif
/* Is there any way to do this without declaring *all* memory clobbered?
I.e. any way to tell gcc that some byte-sized value is in %al? */
#define optflag_testl(v) \
__asm__ __volatile__ ("andl %0,%0\n\t" \
ASM_LAHF "\n\t" \
"seto %%al\n\t" \
"movb %%al,regflags\n\t" \
"movb %%ah,regflags+1\n\t" \
: : "r" (v) : "%eax","cc","memory")
#define optflag_testw(v) \
__asm__ __volatile__ ("andw %w0,%w0\n\t" \
ASM_LAHF "\n\t" \
"seto %%al\n\t" \
"movb %%al,regflags\n\t" \
"movb %%ah,regflags+1\n\t" \
: : "r" (v) : "%eax","cc","memory")
#define optflag_testb(v) \
__asm__ __volatile__ ("andb %b0,%b0\n\t" \
ASM_LAHF "\n\t" \
"seto %%al\n\t" \
"movb %%al,regflags\n\t" \
"movb %%ah,regflags+1\n\t" \
: : "q" (v) : "%eax","cc","memory")
#define optflag_addl(v, s, d) do { \
__asm__ __volatile__ ("addl %k1,%k0\n\t" \
ASM_LAHF "\n\t" \
"seto %%al\n\t" \
"movb %%al,regflags\n\t" \
"movb %%ah,regflags+1\n\t" \
: "=r" (v) : "rmi" (s), "0" (d) : "%eax","cc","memory"); \
COPY_CARRY; \
} while (0)
#define optflag_addw(v, s, d) do { \
__asm__ __volatile__ ("addw %w1,%w0\n\t" \
ASM_LAHF "\n\t" \
"seto %%al\n\t" \
"movb %%al,regflags\n\t" \
"movb %%ah,regflags+1\n\t" \
: "=r" (v) : "rmi" (s), "0" (d) : "%eax","cc","memory"); \
COPY_CARRY; \
} while (0)
#define optflag_addb(v, s, d) do { \
__asm__ __volatile__ ("addb %b1,%b0\n\t" \
ASM_LAHF "\n\t" \
"seto %%al\n\t" \
"movb %%al,regflags\n\t" \
"movb %%ah,regflags+1\n\t" \
: "=q" (v) : "qmi" (s), "0" (d) : "%eax","cc","memory"); \
COPY_CARRY; \
} while (0)
#define optflag_subl(v, s, d) do { \
__asm__ __volatile__ ("subl %k1,%k0\n\t" \
ASM_LAHF "\n\t" \
"seto %%al\n\t" \
"movb %%al,regflags\n\t" \
"movb %%ah,regflags+1\n\t" \
: "=r" (v) : "rmi" (s), "0" (d) : "%eax","cc","memory"); \
COPY_CARRY; \
} while (0)
#define optflag_subw(v, s, d) do { \
__asm__ __volatile__ ("subw %w1,%w0\n\t" \
ASM_LAHF "\n\t" \
"seto %%al\n\t" \
"movb %%al,regflags\n\t" \
"movb %%ah,regflags+1\n\t" \
: "=r" (v) : "rmi" (s), "0" (d) : "%eax","cc","memory"); \
COPY_CARRY; \
} while (0)
#define optflag_subb(v, s, d) do { \
__asm__ __volatile__ ("subb %b1,%b0\n\t" \
ASM_LAHF "\n\t" \
"seto %%al\n\t" \
"movb %%al,regflags\n\t" \
"movb %%ah,regflags+1\n\t" \
: "=q" (v) : "qmi" (s), "0" (d) : "%eax","cc","memory"); \
COPY_CARRY; \
} while (0)
#define optflag_cmpl(s, d) \
__asm__ __volatile__ ("cmpl %k0,%k1\n\t" \
ASM_LAHF "\n\t" \
"seto %%al\n\t" \
"movb %%al,regflags\n\t" \
"movb %%ah,regflags+1\n\t" \
: : "rmi" (s), "r" (d) : "%eax","cc","memory")
#define optflag_cmpw(s, d) \
__asm__ __volatile__ ("cmpw %w0,%w1\n\t" \
ASM_LAHF "\n\t" \
"seto %%al\n\t" \
"movb %%al,regflags\n\t" \
"movb %%ah,regflags+1\n\t" \
: : "rmi" (s), "r" (d) : "%eax","cc","memory");
#define optflag_cmpb(s, d) \
__asm__ __volatile__ ("cmpb %b0,%b1\n\t" \
ASM_LAHF "\n\t" \
"seto %%al\n\t" \
"movb %%al,regflags\n\t" \
"movb %%ah,regflags+1\n\t" \
: : "qmi" (s), "q" (d) : "%eax","cc","memory")
#endif
#elif defined(SPARC_V8_ASSEMBLY) || defined(SPARC_V9_ASSEMBLY)
#elif defined(__sparc__) && (defined(SPARC_V8_ASSEMBLY) || defined(SPARC_V9_ASSEMBLY))
struct flag_struct {
unsigned char nzvc;
@ -361,26 +151,19 @@ struct flag_struct {
extern struct flag_struct regflags;
#define FLAGVAL_Z 0x04
#define FLAGVAL_N 0x08
#define SET_ZFLG(y) (regflags.nzvc = (regflags.nzvc & ~0x04) | (((y) & 1) << 2))
#define SET_CFLG(y) (regflags.nzvc = (regflags.nzvc & ~1) | ((y) & 1))
#define SET_VFLG(y) (regflags.nzvc = (regflags.nzvc & ~0x02) | (((y) & 1) << 1))
#define SET_NFLG(y) (regflags.nzvc = (regflags.nzvc & ~0x08) | (((y) & 1) << 3))
#define SET_XFLG(y) (regflags.x = (y))
#define SET_ZFLG(y) (regflags.nzvc = (regflags.nzvc & ~0x04) | (((y) & 1) << 2))
#define SET_CFLG(y) (regflags.nzvc = (regflags.nzvc & ~1) | ((y) & 1))
#define SET_VFLG(y) (regflags.nzvc = (regflags.nzvc & ~0x02) | (((y) & 1) << 1))
#define SET_NFLG(y) (regflags.nzvc = (regflags.nzvc & ~0x08) | (((y) & 1) << 3))
#define SET_XFLG(y) (regflags.x = (y))
#define GET_ZFLG ((regflags.nzvc >> 2) & 1)
#define GET_CFLG (regflags.nzvc & 1)
#define GET_VFLG ((regflags.nzvc >> 1) & 1)
#define GET_NFLG ((regflags.nzvc >> 3) & 1)
#define GET_XFLG (regflags.x & 1)
#define CLEAR_CZNV (regflags.nzvc = 0)
#define GET_CZNV (reflags.nzvc)
#define IOR_CZNV(X) (refglags.nzvc |= (X))
#define SET_CZNV(X) (regflags.nzvc = (X))
#define GET_ZFLG ((regflags.nzvc >> 2) & 1)
#define GET_CFLG (regflags.nzvc & 1)
#define GET_VFLG ((regflags.nzvc >> 1) & 1)
#define GET_NFLG ((regflags.nzvc >> 3) & 1)
#define GET_XFLG (regflags.x & 1)
#define CLEAR_CZNV (regflags.nzvc = 0)
#define COPY_CARRY (regflags.x = regflags.nzvc)
static __inline__ int cctrue(int cc)
@ -1004,8 +787,6 @@ static inline uae_u32 sparc_v9_flag_addx_32(flag_struct *flags, uae_u32 src, uae
#endif /* SPARC_V9_ASSEMBLY */
#endif
#else
struct flag_struct {
@ -1024,27 +805,6 @@ extern struct flag_struct regflags;
#define VFLG (regflags.v)
#define XFLG (regflags.x)
#define SET_CFLG(x) (CFLG = (x))
#define SET_NFLG(x) (NFLG = (x))
#define SET_VFLG(x) (VFLG = (x))
#define SET_ZFLG(x) (ZFLG = (x))
#define SET_XFLG(x) (XFLG = (x))
#define GET_CFLG CFLG
#define GET_NFLG NFLG
#define GET_VFLG VFLG
#define GET_ZFLG ZFLG
#define GET_XFLG XFLG
#define CLEAR_CZNV do { \
SET_CFLG (0); \
SET_ZFLG (0); \
SET_NFLG (0); \
SET_VFLG (0); \
} while (0)
#define COPY_CARRY (SET_XFLG (GET_CFLG))
static __inline__ int cctrue(const int cc)
{
switch(cc){
@ -1068,6 +828,4 @@ static __inline__ int cctrue(const int cc)
return 0;
}
#endif /* OPTIMIZED_FLAGS */
#endif /* M68K_FLAGS_H */
#endif

View File

@ -1,24 +1,10 @@
/*
* UAE - The Un*x Amiga Emulator
*
* MC68000 emulation
*
* (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
*/
/*
* UAE - The Un*x Amiga Emulator
*
* MC68000 emulation
*
* (c) 1995 Bernd Schmidt
*/
#include <stdio.h>
#include <stdlib.h>
@ -36,14 +22,9 @@ extern int intlev(void); // From baisilisk_glue.cpp
#include "memory.h"
#include "readcpu.h"
#include "newcpu.h"
#include "fpu/fpu.h"
#if defined(ENABLE_EXCLUSIVE_SPCFLAGS) && !defined(HAVE_HARDWARE_LOCKS)
B2_mutex *spcflags_lock = NULL;
#endif
bool quit_program = false;
int quit_program = 0;
int debugging = 0;
struct flag_struct regflags;
/* Opcode of faulting instruction */
@ -60,70 +41,12 @@ int movem_index1[256];
int movem_index2[256];
int movem_next[256];
int fpp_movem_index1[256];
int fpp_movem_index2[256];
int fpp_movem_next[256];
cpuop_func *cpufunctbl[65536];
#if FLIGHT_RECORDER
struct rec_step {
uae_u32 pc;
#if FLIGHT_RECORDER >= 2
uae_u32 d[8];
uae_u32 a[8];
#endif
};
const int LOG_SIZE = 32768;
static rec_step log[LOG_SIZE];
static int log_ptr = -1; // First time initialization
static const char *log_filename(void)
{
const char *name = getenv("M68K_LOG_FILE");
return name ? name : "log.68k";
}
void m68k_record_step(uaecptr pc)
{
#if FLIGHT_RECORDER >= 2
/* XXX: if LSB is set, we are recording from generated code and we
don't support registers recording yet. */
if ((pc & 1) == 0) {
for (int i = 0; i < 8; i++) {
log[log_ptr].d[i] = m68k_dreg(regs, i);
log[log_ptr].a[i] = m68k_areg(regs, i);
}
}
#endif
log[log_ptr].pc = pc;
log_ptr = (log_ptr + 1) % LOG_SIZE;
}
static void dump_log(void)
{
FILE *f = fopen(log_filename(), "w");
if (f == NULL)
return;
for (int i = 0; i < LOG_SIZE; i++) {
int j = (i + log_ptr) % LOG_SIZE;
uae_u32 pc = log[j].pc & ~1;
fprintf(f, "pc %08x", pc);
#if FLIGHT_RECORDER >= 2
fprintf(f, "\n");
if ((log[j].pc & 1) == 0) {
fprintf(f, "d0 %08x d1 %08x d2 %08x d3 %08x\n", log[j].d[0], log[j].d[1], log[j].d[2], log[j].d[3]);
fprintf(f, "d4 %08x d5 %08x d6 %08x d7 %08x\n", log[j].d[4], log[j].d[5], log[j].d[6], log[j].d[7]);
fprintf(f, "a0 %08x a1 %08x a2 %08x a3 %08x\n", log[j].a[0], log[j].a[1], log[j].a[2], log[j].a[3]);
fprintf(f, "a4 %08x a5 %08x a6 %08x a7 %08x\n", log[j].a[4], log[j].a[5], log[j].a[6], log[j].a[7]);
}
#else
fprintf(f, " | ");
#endif
}
fclose(f);
}
#endif
#define COUNT_INSTRS 0
#if COUNT_INSTRS
@ -187,9 +110,9 @@ static __inline__ unsigned int cft_map (unsigned int f)
#endif
}
void REGPARAM2 op_illg_1 (uae_u32 opcode) REGPARAM;
static void REGPARAM2 op_illg_1 (uae_u32 opcode) REGPARAM;
void REGPARAM2 op_illg_1 (uae_u32 opcode)
static void REGPARAM2 op_illg_1 (uae_u32 opcode)
{
op_illg (cft_map (opcode));
}
@ -198,7 +121,7 @@ static void build_cpufunctbl (void)
{
int i;
unsigned long opcode;
unsigned int cpu_level = 0; // 68000 (default)
int cpu_level = 0; // 68000 (default)
if (CPUType == 4)
cpu_level = 4; // 68040 with FPU
else {
@ -210,11 +133,11 @@ static void build_cpufunctbl (void)
cpu_level = 1;
}
struct cputbl *tbl = (
cpu_level == 4 ? op_smalltbl_0_ff
: cpu_level == 3 ? op_smalltbl_1_ff
: cpu_level == 2 ? op_smalltbl_2_ff
: cpu_level == 1 ? op_smalltbl_3_ff
: op_smalltbl_4_ff);
cpu_level == 4 ? op_smalltbl_0
: cpu_level == 3 ? op_smalltbl_1
: cpu_level == 2 ? op_smalltbl_2
: cpu_level == 1 ? op_smalltbl_3
: op_smalltbl_4);
for (opcode = 0; opcode < 65536; opcode++)
cpufunctbl[cft_map (opcode)] = op_illg_1;
@ -254,6 +177,15 @@ void init_m68k (void)
movem_index2[i] = 7-j;
movem_next[i] = i & (~(1 << j));
}
for (i = 0 ; i < 256 ; i++) {
int j;
for (j = 7 ; j >= 0 ; j--) {
if (i & (1 << j)) break;
}
fpp_movem_index1[i] = 7-j;
fpp_movem_index2[i] = j;
fpp_movem_next[i] = i & (~(1 << j));
}
#if COUNT_INSTRS
{
FILE *f = fopen (icountfilename (), "r");
@ -274,19 +206,6 @@ void init_m68k (void)
do_merges ();
build_cpufunctbl ();
#if defined(ENABLE_EXCLUSIVE_SPCFLAGS) && !defined(HAVE_HARDWARE_LOCKS)
spcflags_lock = B2_create_mutex();
#endif
fpu_init(CPUType == 4);
}
void exit_m68k (void)
{
fpu_exit ();
#if defined(ENABLE_EXCLUSIVE_SPCFLAGS) && !defined(HAVE_HARDWARE_LOCKS)
B2_delete_mutex(spcflags_lock);
#endif
}
struct regstruct regs, lastint_regs;
@ -295,15 +214,9 @@ static int backup_pointer = 0;
static long int m68kpc_offset;
int lastint_no;
#if DIRECT_ADDRESSING
#define get_ibyte_1(o) get_byte(get_virtual_address(regs.pc_p) + (o) + 1)
#define get_iword_1(o) get_word(get_virtual_address(regs.pc_p) + (o))
#define get_ilong_1(o) get_long(get_virtual_address(regs.pc_p) + (o))
#else
#define get_ibyte_1(o) get_byte(regs.pc + (regs.pc_p - regs.pc_oldp) + (o) + 1)
#define get_iword_1(o) get_word(regs.pc + (regs.pc_p - regs.pc_oldp) + (o))
#define get_ilong_1(o) get_long(regs.pc + (regs.pc_p - regs.pc_oldp) + (o))
#endif
uae_s32 ShowEA (int reg, amodes mode, wordsizes size, char *buf)
{
@ -722,18 +635,15 @@ void MakeFromSR (void)
}
}
SPCFLAGS_SET( SPCFLAG_INT );
regs.spcflags |= SPCFLAG_INT;
if (regs.t1 || regs.t0)
SPCFLAGS_SET( SPCFLAG_TRACE );
regs.spcflags |= SPCFLAG_TRACE;
else
/* Keep SPCFLAG_DOTRACE, we still want a trace exception for
SR-modifying instructions (including STOP). */
SPCFLAGS_CLEAR( SPCFLAG_TRACE );
regs.spcflags &= ~(SPCFLAG_TRACE | SPCFLAG_DOTRACE);
}
void Exception(int nr, uaecptr oldpc)
{
uae_u32 currpc = m68k_getpc ();
MakeSR();
if (!regs.s) {
regs.usp = m68k_areg(regs, 7);
@ -762,7 +672,7 @@ void Exception(int nr, uaecptr oldpc)
m68k_areg(regs, 7) -= 2;
put_word (m68k_areg(regs, 7), nr * 4);
m68k_areg(regs, 7) -= 4;
put_long (m68k_areg(regs, 7), currpc);
put_long (m68k_areg(regs, 7), m68k_getpc ());
m68k_areg(regs, 7) -= 2;
put_word (m68k_areg(regs, 7), regs.sr);
regs.sr |= (1 << 13);
@ -788,15 +698,14 @@ void Exception(int nr, uaecptr oldpc)
}
}
m68k_areg(regs, 7) -= 4;
put_long (m68k_areg(regs, 7), currpc);
put_long (m68k_areg(regs, 7), m68k_getpc ());
kludge_me_do:
m68k_areg(regs, 7) -= 2;
put_word (m68k_areg(regs, 7), regs.sr);
m68k_setpc (get_long (regs.vbr + 4*nr));
SPCFLAGS_SET( SPCFLAG_JIT_END_COMPILE );
fill_prefetch_0 ();
regs.t1 = regs.t0 = regs.m = 0;
SPCFLAGS_CLEAR( SPCFLAG_TRACE | SPCFLAG_DOTRACE );
regs.spcflags &= ~(SPCFLAG_TRACE | SPCFLAG_DOTRACE);
}
static void Interrupt(int nr)
@ -807,48 +716,20 @@ static void Interrupt(int nr)
Exception(nr+24, 0);
regs.intmask = nr;
SPCFLAGS_SET( SPCFLAG_INT );
regs.spcflags |= SPCFLAG_INT;
}
static int caar, cacr, tc, itt0, itt1, dtt0, dtt1, mmusr, urp, srp;
static int caar, cacr, tc, itt0, itt1, dtt0, dtt1;
static int movec_illg (int regno)
void m68k_move2c (int regno, uae_u32 *regp)
{
switch (CPUType) {
case 1:
if ((regno & 0x7ff) <= 1)
return 0;
break;
case 2:
case 3:
if ((regno & 0x7ff) <= 2)
return 0;
if (regno == 3 || regno == 4)
return 0;
break;
case 4:
if ((regno & 0x7ff) <= 7) {
if (regno != 0x802)
return 0;
}
break;
}
return 1;
}
int m68k_move2c (int regno, uae_u32 *regp)
{
if (movec_illg (regno)) {
if (CPUType == 1 && (regno & 0x7FF) > 1)
op_illg (0x4E7B);
return 0;
} else {
else
switch (regno) {
case 0: regs.sfc = *regp & 7; break;
case 1: regs.dfc = *regp & 7; break;
case 2:
cacr = *regp & (CPUType < 4 ? 0x3 : 0x80008000);
break;
case 2: cacr = *regp & 0x3; break; /* ignore C and CE */
case 3: tc = *regp & 0xc000; break;
case 4: itt0 = *regp & 0xffffe364; break;
case 5: itt1 = *regp & 0xffffe364; break;
@ -859,24 +740,17 @@ int m68k_move2c (int regno, uae_u32 *regp)
case 0x802: caar = *regp &0xfc; break;
case 0x803: regs.msp = *regp; if (regs.m == 1) m68k_areg(regs, 7) = regs.msp; break;
case 0x804: regs.isp = *regp; if (regs.m == 0) m68k_areg(regs, 7) = regs.isp; break;
case 0x805: mmusr = *regp; break;
case 0x806: urp = *regp; break;
case 0x807: srp = *regp; break;
default:
op_illg (0x4E7B);
return 0;
break;
}
}
return 1;
}
int m68k_movec2 (int regno, uae_u32 *regp)
void m68k_movec2 (int regno, uae_u32 *regp)
{
if (movec_illg (regno))
{
if (CPUType == 1 && (regno & 0x7FF) > 1)
op_illg (0x4E7A);
return 0;
} else {
else
switch (regno) {
case 0: *regp = regs.sfc; break;
case 1: *regp = regs.dfc; break;
@ -891,15 +765,10 @@ int m68k_movec2 (int regno, uae_u32 *regp)
case 0x802: *regp = caar; break;
case 0x803: *regp = regs.m == 1 ? m68k_areg(regs, 7) : regs.msp; break;
case 0x804: *regp = regs.m == 0 ? m68k_areg(regs, 7) : regs.isp; break;
case 0x805: *regp = mmusr; break;
case 0x806: *regp = urp; break;
case 0x807: *regp = srp; break;
default:
op_illg (0x4E7A);
return 0;
break;
}
}
return 1;
}
static __inline__ int
@ -957,8 +826,8 @@ void m68k_divl (uae_u32 opcode, uae_u32 src, uae_u16 extra, uaecptr oldpc)
SET_CFLG (0);
SET_ZFLG (((uae_s32)quot) == 0);
SET_NFLG (((uae_s32)quot) < 0);
m68k_dreg(regs, extra & 7) = (uae_u32)rem;
m68k_dreg(regs, (extra >> 12) & 7) = (uae_u32)quot;
m68k_dreg(regs, extra & 7) = rem;
m68k_dreg(regs, (extra >> 12) & 7) = quot;
}
} else {
/* unsigned */
@ -980,8 +849,8 @@ void m68k_divl (uae_u32 opcode, uae_u32 src, uae_u16 extra, uaecptr oldpc)
SET_CFLG (0);
SET_ZFLG (((uae_s32)quot) == 0);
SET_NFLG (((uae_s32)quot) < 0);
m68k_dreg(regs, extra & 7) = (uae_u32)rem;
m68k_dreg(regs, (extra >> 12) & 7) = (uae_u32)quot;
m68k_dreg(regs, extra & 7) = rem;
m68k_dreg(regs, (extra >> 12) & 7) = quot;
}
}
#else
@ -1157,16 +1026,12 @@ static char* ccnames[] =
{ "T ","F ","HI","LS","CC","CS","NE","EQ",
"VC","VS","PL","MI","GE","LT","GT","LE" };
// If value is greater than zero, this means we are still processing an EmulOp
// because the counter is incremented only in m68k_execute(), i.e. interpretive
// execution only
static int m68k_execute_depth = 0;
void m68k_reset (void)
{
m68k_areg (regs, 7) = 0x2000;
m68k_setpc (ROMBaseMac + 0x2a);
fill_prefetch_0 ();
regs.kick_mask = 0xF80000;
regs.s = 1;
regs.m = 0;
regs.stopped = 0;
@ -1177,29 +1042,29 @@ void m68k_reset (void)
SET_CFLG (0);
SET_VFLG (0);
SET_NFLG (0);
SPCFLAGS_INIT( 0 );
regs.spcflags = 0;
regs.intmask = 7;
regs.vbr = regs.sfc = regs.dfc = 0;
fpu_reset();
#if FLIGHT_RECORDER
log_ptr = 0;
memset(log, 0, sizeof(log));
#endif
regs.fpcr = regs.fpsr = regs.fpiar = 0;
}
void m68k_emulop_return(void)
void REGPARAM2 op_illg (uae_u32 opcode)
{
SPCFLAGS_SET( SPCFLAG_BRK );
quit_program = true;
}
uaecptr pc = m68k_getpc ();
void m68k_emulop(uae_u32 opcode)
{
if ((opcode & 0xFF00) == 0x7100) {
struct M68kRegisters r;
int i;
// Return from Execute68k()?
if (opcode == M68K_EXEC_RETURN) {
regs.spcflags |= SPCFLAG_BRK;
quit_program = 1;
return;
}
// Call EMUL_OP opcode
for (i=0; i<8; i++) {
r.d[i] = m68k_dreg(regs, i);
r.a[i] = m68k_areg(regs, i);
@ -1213,17 +1078,18 @@ void m68k_emulop(uae_u32 opcode)
}
regs.sr = r.sr;
MakeFromSR();
}
void REGPARAM2 op_illg (uae_u32 opcode)
{
uaecptr pc = m68k_getpc ();
m68k_incpc(2);
fill_prefetch_0 ();
return;
}
if ((opcode & 0xF000) == 0xA000) {
Exception(0xA,0);
return;
}
// write_log ("Illegal instruction: %04x at %08lx\n", opcode, pc);
if ((opcode & 0xF000) == 0xF000) {
Exception(0xB,0);
return;
@ -1232,18 +1098,16 @@ void REGPARAM2 op_illg (uae_u32 opcode)
write_log ("Illegal instruction: %04x at %08lx\n", opcode, pc);
Exception (4,0);
return;
}
void mmu_op(uae_u32 opcode, uae_u16 extra)
{
if ((opcode & 0xFE0) == 0x0500) {
/* PFLUSH */
mmusr = 0;
} else if ((opcode & 0x0FD8) == 0x548) {
/* PTEST */
if ((extra & 0xB000) == 0) { /* PMOVE instruction */
} else if ((extra & 0xF000) == 0x2000) { /* PLOAD instruction */
} else if ((extra & 0xF000) == 0x8000) { /* PTEST instruction */
} else
op_illg (opcode);
op_illg (opcode);
}
static int n_insns = 0, n_spcinsns = 0;
@ -1252,14 +1116,14 @@ static uaecptr last_trace_ad = 0;
static void do_trace (void)
{
if (regs.t0 && CPUType >= 2) {
if (regs.t0) {
uae_u16 opcode;
/* should also include TRAP, CHK, SR modification FPcc */
/* probably never used so why bother */
/* We can afford this to be inefficient... */
m68k_setpc (m68k_getpc ());
fill_prefetch_0 ();
opcode = get_word(m68k_getpc());
opcode = get_word (regs.pc);
if (opcode == 0x4e72 /* RTE */
|| opcode == 0x4e74 /* RTD */
|| opcode == 0x4e75 /* RTS */
@ -1275,80 +1139,97 @@ static void do_trace (void)
&& (uae_s16)m68k_dreg(regs, opcode & 7) != 0))
{
last_trace_ad = m68k_getpc ();
SPCFLAGS_CLEAR( SPCFLAG_TRACE );
SPCFLAGS_SET( SPCFLAG_DOTRACE );
regs.spcflags &= ~SPCFLAG_TRACE;
regs.spcflags |= SPCFLAG_DOTRACE;
}
} else if (regs.t1) {
last_trace_ad = m68k_getpc ();
SPCFLAGS_CLEAR( SPCFLAG_TRACE );
SPCFLAGS_SET( SPCFLAG_DOTRACE );
regs.spcflags &= ~SPCFLAG_TRACE;
regs.spcflags |= SPCFLAG_DOTRACE;
}
}
int m68k_do_specialties (void)
{
if (SPCFLAGS_TEST( SPCFLAG_DOTRACE )) {
static int do_specialties (void)
{
/*n_spcinsns++;*/
if (regs.spcflags & SPCFLAG_DOTRACE) {
Exception (9,last_trace_ad);
}
while (SPCFLAGS_TEST( SPCFLAG_STOP )) {
if (SPCFLAGS_TEST( SPCFLAG_INT | SPCFLAG_DOINT )){
SPCFLAGS_CLEAR( SPCFLAG_INT | SPCFLAG_DOINT );
while (regs.spcflags & SPCFLAG_STOP) {
if (regs.spcflags & (SPCFLAG_INT | SPCFLAG_DOINT)){
int intr = intlev ();
regs.spcflags &= ~(SPCFLAG_INT | SPCFLAG_DOINT);
if (intr != -1 && intr > regs.intmask) {
Interrupt (intr);
regs.stopped = 0;
SPCFLAGS_CLEAR( SPCFLAG_STOP );
regs.spcflags &= ~SPCFLAG_STOP;
}
}
}
if (SPCFLAGS_TEST( SPCFLAG_TRACE ))
if (regs.spcflags & SPCFLAG_TRACE)
do_trace ();
if (SPCFLAGS_TEST( SPCFLAG_DOINT )) {
SPCFLAGS_CLEAR( SPCFLAG_DOINT );
if (regs.spcflags & SPCFLAG_DOINT) {
int intr = intlev ();
regs.spcflags &= ~SPCFLAG_DOINT;
if (intr != -1 && intr > regs.intmask) {
Interrupt (intr);
regs.stopped = 0;
}
}
if (SPCFLAGS_TEST( SPCFLAG_INT )) {
SPCFLAGS_CLEAR( SPCFLAG_INT );
SPCFLAGS_SET( SPCFLAG_DOINT );
if (regs.spcflags & SPCFLAG_INT) {
regs.spcflags &= ~SPCFLAG_INT;
regs.spcflags |= SPCFLAG_DOINT;
}
if (SPCFLAGS_TEST( SPCFLAG_BRK )) {
SPCFLAGS_CLEAR( SPCFLAG_BRK );
if (regs.spcflags & (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE)) {
regs.spcflags &= ~(SPCFLAG_BRK | SPCFLAG_MODE_CHANGE);
return 1;
}
return 0;
}
void m68k_do_execute (void)
static void m68k_run_1 (void)
{
for (;;) {
uae_u32 opcode = GET_OPCODE;
#if FLIGHT_RECORDER
m68k_record_step(m68k_getpc());
#endif
(*cpufunctbl[opcode])(opcode);
cpu_check_ticks();
if (SPCFLAGS_TEST(SPCFLAG_ALL_BUT_EXEC_RETURN)) {
if (m68k_do_specialties())
if (regs.spcflags) {
if (do_specialties())
return;
}
}
}
void m68k_execute (void)
#define m68k_run1 m68k_run_1
int in_m68k_go = 0;
void m68k_go (int may_quit)
{
for (;;) {
if (quit_program)
break;
m68k_do_execute();
// m68k_go() must be reentrant for Execute68k() and Execute68kTrap() to work
/*
if (in_m68k_go || !may_quit) {
write_log("Bug! m68k_go is not reentrant.\n");
abort();
}
*/
in_m68k_go++;
for (;;) {
if (quit_program > 0) {
if (quit_program == 1)
break;
quit_program = 0;
m68k_reset ();
}
m68k_run1();
}
if (debugging) {
uaecptr nextpc;
m68k_dumpstate(&nextpc);
exit(1);
}
in_m68k_go--;
}
static void m68k_verify (uaecptr addr, uaecptr *nextpc)
@ -1457,10 +1338,16 @@ void m68k_dumpstate (uaecptr *nextpc)
printf ("T=%d%d S=%d M=%d X=%d N=%d Z=%d V=%d C=%d IMASK=%d\n",
regs.t1, regs.t0, regs.s, regs.m,
GET_XFLG, GET_NFLG, GET_ZFLG, GET_VFLG, GET_CFLG, regs.intmask);
fpu_dump_registers();
fpu_dump_flags();
for (i = 0; i < 8; i++){
printf ("FP%d: %g ", i, regs.fp[i]);
if ((i & 3) == 3) printf ("\n");
}
printf ("N=%d Z=%d I=%d NAN=%d\n",
(regs.fpsr & 0x8000000) != 0,
(regs.fpsr & 0x4000000) != 0,
(regs.fpsr & 0x2000000) != 0,
(regs.fpsr & 0x1000000) != 0);
m68k_disasm(m68k_getpc (), nextpc, 1);
if (nextpc)
printf ("next PC: %08lx\n", *nextpc);

View File

@ -1,36 +1,47 @@
/*
* UAE - The Un*x Amiga Emulator
*
* MC68000 emulation
*
* Copyright 1995 Bernd Schmidt
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
* UAE - The Un*x Amiga Emulator
*
* MC68000 emulation
*
* Copyright 1995 Bernd Schmidt
*/
#ifndef NEWCPU_H
#define NEWCPU_H
#define SPCFLAG_STOP 2
#define SPCFLAG_DISK 4
#define SPCFLAG_INT 8
#define SPCFLAG_BRK 16
#define SPCFLAG_EXTRA_CYCLES 32
#define SPCFLAG_TRACE 64
#define SPCFLAG_DOTRACE 128
#define SPCFLAG_DOINT 256
#define SPCFLAG_BLTNASTY 512
#define SPCFLAG_EXEC 1024
#define SPCFLAG_MODE_CHANGE 8192
#ifndef FLIGHT_RECORDER
#define FLIGHT_RECORDER 0
#ifndef SET_CFLG
#define SET_CFLG(x) (CFLG = (x))
#define SET_NFLG(x) (NFLG = (x))
#define SET_VFLG(x) (VFLG = (x))
#define SET_ZFLG(x) (ZFLG = (x))
#define SET_XFLG(x) (XFLG = (x))
#define GET_CFLG CFLG
#define GET_NFLG NFLG
#define GET_VFLG VFLG
#define GET_ZFLG ZFLG
#define GET_XFLG XFLG
#define CLEAR_CZNV do { \
SET_CFLG (0); \
SET_ZFLG (0); \
SET_NFLG (0); \
SET_VFLG (0); \
} while (0)
#define COPY_CARRY (SET_XFLG (GET_CFLG))
#endif
#include "m68k.h"
#include "readcpu.h"
#include "spcflags.h"
extern int areg_byteinc[];
extern int imm8_table[];
@ -38,66 +49,56 @@ extern int movem_index1[256];
extern int movem_index2[256];
extern int movem_next[256];
extern int fpp_movem_index1[256];
extern int fpp_movem_index2[256];
extern int fpp_movem_next[256];
extern int broken_in;
#ifdef X86_ASSEMBLY
/* This hack seems to force all register saves (pushl %reg) to be moved to the
begining of the function, thus making it possible to cpuopti to remove them
since m68k_run_1 will save those registers before calling the instruction
handler */
# define cpuop_tag(tag) __asm__ __volatile__ ( "#cpuop_" tag )
#else
# define cpuop_tag(tag) ;
#endif
#define cpuop_begin() do { cpuop_tag("begin"); } while (0)
#define cpuop_end() do { cpuop_tag("end"); } while (0)
typedef void REGPARAM2 cpuop_func (uae_u32) REGPARAM;
struct cputbl {
cpuop_func *handler;
uae_u16 specific;
int specific;
uae_u16 opcode;
};
extern cpuop_func *cpufunctbl[65536] ASM_SYM("cpufunctbl");
extern void REGPARAM2 op_illg (uae_u32) REGPARAM;
typedef char flagtype;
struct regstruct {
uae_u32 regs[16];
extern struct regstruct
{
uae_u32 regs[16];
uaecptr usp,isp,msp;
uae_u16 sr;
flagtype t1;
flagtype t0;
flagtype s;
flagtype m;
flagtype x;
flagtype stopped;
int intmask;
uae_u32 pc;
uae_u8 * pc_p;
uae_u8 * pc_oldp;
uae_u32 pc;
uae_u8 *pc_p;
uae_u8 *pc_oldp;
spcflags_t spcflags;
int intmask;
uae_u32 vbr,sfc,dfc;
uae_u32 vbr, sfc, dfc;
uaecptr usp, isp, msp;
uae_u16 sr;
flagtype t1;
flagtype t0;
flagtype s;
flagtype m;
flagtype x;
flagtype stopped;
double fp[8];
uae_u32 fpcr,fpsr,fpiar;
uae_u32 spcflags;
uae_u32 kick_mask;
#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;
} regs, lastint_regs;
#define m68k_dreg(r,num) ((r).regs[(num)])
#define m68k_areg(r,num) (((r).regs + 8)[(num)])
@ -112,7 +113,6 @@ extern regstruct regs, lastint_regs;
#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)
@ -135,13 +135,11 @@ static __inline__ uae_u32 get_ilong_prefetch (uae_s32 o)
return do_get_mem_long(&regs.prefetch);
return (do_get_mem_word (((uae_u16 *)&regs.prefetch) + 1) << 16) | do_get_mem_word ((uae_u16 *)(regs.pc_p + 4));
}
#endif
#define m68k_incpc(o) (regs.pc_p += (o))
static __inline__ void fill_prefetch_0 (void)
{
#if USE_PREFETCH_BUFFER
uae_u32 r;
#ifdef UNALIGNED_PROFITABLE
r = *(uae_u32 *)regs.pc_p;
@ -150,7 +148,6 @@ static __inline__ void fill_prefetch_0 (void)
r = do_get_mem_long ((uae_u32 *)regs.pc_p);
do_put_mem_long (&regs.prefetch, r);
#endif
#endif
}
#if 0
@ -190,54 +187,49 @@ static __inline__ uae_u32 next_ilong (void)
static __inline__ void m68k_setpc (uaecptr newpc)
{
#if DIRECT_ADDRESSING
regs.pc_p = get_real_address(newpc);
#else
regs.pc_p = regs.pc_oldp = get_real_address(newpc);
regs.pc = newpc;
#endif
}
static __inline__ uaecptr m68k_getpc (void)
{
#if DIRECT_ADDRESSING
return get_virtual_address(regs.pc_p);
#else
return regs.pc + ((char *)regs.pc_p - (char *)regs.pc_oldp);
#endif
}
static __inline__ uaecptr m68k_getpc_p (uae_u8 *p)
{
return regs.pc + ((char *)p - (char *)regs.pc_oldp);
}
static __inline__ void m68k_do_rts(void)
{
m68k_setpc(get_long(m68k_areg(regs, 7)));
m68k_areg(regs, 7) += 4;
}
static __inline__ void m68k_do_bsr(uaecptr oldpc, uae_s32 offset)
{
m68k_areg(regs, 7) -= 4;
put_long(m68k_areg(regs, 7), oldpc);
m68k_incpc(offset);
}
static __inline__ void m68k_do_jsr(uaecptr oldpc, uaecptr dest)
{
m68k_areg(regs, 7) -= 4;
put_long(m68k_areg(regs, 7), oldpc);
m68k_setpc(dest);
}
#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 );
if (stop)
regs.spcflags |= SPCFLAG_STOP;
}
extern uae_u32 get_disp_ea_020 (uae_u32 base, uae_u32 dp);
@ -249,22 +241,27 @@ 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_move2c (int, uae_u32 *);
extern void 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_go (int);
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);
extern void fpp_opp (uae_u32, uae_u16);
extern void fdbcc_opp (uae_u32, uae_u16);
extern void fscc_opp (uae_u32, uae_u16);
extern void ftrapcc_opp (uae_u32,uaecptr);
extern void fbcc_opp (uae_u32, uaecptr, uae_u32);
extern void fsave_opp (uae_u32);
extern void frestore_opp (uae_u32);
/* Opcode of faulting instruction */
extern uae_u16 last_op_for_exception_3;
/* PC at fault time */
@ -275,34 +272,15 @@ extern uaecptr last_fault_for_exception_3;
#define CPU_OP_NAME(a) op ## a
/* 68020 + 68881 */
extern struct cputbl op_smalltbl_0_ff[];
extern struct cputbl op_smalltbl_0[];
/* 68020 */
extern struct cputbl op_smalltbl_1_ff[];
extern struct cputbl op_smalltbl_1[];
/* 68010 */
extern struct cputbl op_smalltbl_2_ff[];
extern struct cputbl op_smalltbl_2[];
/* 68000 */
extern struct cputbl op_smalltbl_3_ff[];
extern struct cputbl op_smalltbl_3[];
/* 68000 slow but compatible. */
extern struct cputbl op_smalltbl_4_ff[];
extern struct cputbl op_smalltbl_4[];
#if FLIGHT_RECORDER
extern void m68k_record_step(uaecptr) REGPARAM;
#endif
extern void m68k_do_execute(void);
extern void m68k_execute(void);
extern cpuop_func *cpufunctbl[65536];
#ifdef USE_CPU_EMUL_SERVICES
extern int32 emulated_ticks;
extern void cpu_do_check_ticks(void);
static inline void cpu_check_ticks(void)
{
if (--emulated_ticks <= 0)
cpu_do_check_ticks();
}
#else
#define cpu_check_ticks()
#define cpu_do_check_ticks()
#endif
#endif /* NEWCPU_H */

View File

@ -1,142 +0,0 @@
#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

View File

@ -4,20 +4,6 @@
* Read 68000 CPU specs from file "table68k"
*
* Copyright 1995,1996 Bernd Schmidt
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdio.h>
@ -153,9 +139,6 @@ struct mnemolookup lookuptab[] = {
{ i_CPUSHA, "CPUSHA" },
{ i_MOVE16, "MOVE16" },
{ i_EMULOP_RETURN, "EMULOP_RETURN" },
{ i_EMULOP, "EMULOP" },
{ i_MMUOP, "MMUOP" },
{ i_ILLG, "" },
};
@ -212,34 +195,16 @@ static void build_insn (int insn)
int variants;
struct instr_def id;
const char *opcstr;
int i, n;
int i;
int flaglive = 0, flagdead = 0;
int cflow = 0;
id = defs68k[insn];
// Control flow information
cflow = id.cflow;
// Mask of flags set/used
unsigned char flags_set(0), flags_used(0);
for (i = 0, n = 4; i < 5; i++, n--) {
switch (id.flaginfo[i].flagset) {
case fa_unset: case fa_isjmp: break;
default: flags_set |= (1 << n);
}
switch (id.flaginfo[i].flaguse) {
case fu_unused: case fu_isjmp: break;
default: flags_used |= (1 << n);
}
}
for (i = 0; i < 5; i++) {
switch (id.flaginfo[i].flagset){
case fa_unset: break;
case fa_isjmp: break;
case fa_zero: flagdead |= 1 << i; break;
case fa_one: flagdead |= 1 << i; break;
case fa_dontcare: flagdead |= 1 << i; break;
@ -252,6 +217,8 @@ static void build_insn (int insn)
for (i = 0; i < 5; i++) {
switch (id.flaginfo[i].flaguse) {
case fu_unused: break;
case fu_isjmp: flaglive |= 1 << i; break;
case fu_maybecc: flaglive |= 1 << i; break;
case fu_unknown: flaglive = -1; goto out2;
case fu_used: flaglive |= 1 << i; break;
}
@ -269,7 +236,7 @@ static void build_insn (int insn)
int pos = 0;
int mnp = 0;
int bitno = 0;
char mnemonic[64];
char mnemonic[10];
wordsizes sz = sz_long;
int srcgather = 0, dstgather = 0;
@ -306,8 +273,6 @@ static void build_insn (int insn)
continue;
if (bitcnt[bitI] && (bitval[bitI] == 0x00 || bitval[bitI] == 0xff))
continue;
if (bitcnt[bitE] && (bitval[bitE] == 0x00))
continue;
/* bitI and bitC get copied to biti and bitc */
if (bitcnt[bitI]) {
@ -346,11 +311,6 @@ static void build_insn (int insn)
}
}
mnp++;
if ((unsigned)mnp >= sizeof(mnemonic) - 1) {
mnemonic[sizeof(mnemonic) - 1] = 0;
fprintf(stderr, "Instruction %s overflow\n", mnemonic);
abort();
}
}
pos++;
}
@ -388,9 +348,6 @@ static void build_insn (int insn)
case 'P': srcmode = Aipi; pos++; break;
}
break;
case 'L':
srcmode = absl;
break;
case '#':
switch (opcstr[pos++]) {
case 'z': srcmode = imm; break;
@ -436,22 +393,6 @@ static void build_insn (int insn)
srcpos = bitpos[bitK];
}
break;
case 'E': srcmode = immi; srcreg = bitval[bitE];
if (CPU_EMU_SIZE < 5) { // gb-- what is CPU_EMU_SIZE used for ??
/* 1..255 */
srcgather = 1;
srctype = 6;
srcpos = bitpos[bitE];
}
break;
case 'p': srcmode = immi; srcreg = bitval[bitp];
if (CPU_EMU_SIZE < 5) {
/* 0..3 */
srcgather = 1;
srctype = 7;
srcpos = bitpos[bitp];
}
break;
default: abort();
}
break;
@ -576,27 +517,19 @@ static void build_insn (int insn)
case 'R': destreg = bitval[bitR]; dstgather = 1; dstpos = bitpos[bitR]; break;
default: abort();
}
if (dstpos < 0 || dstpos >= 32)
abort();
break;
case 'A':
destmode = Areg;
switch (opcstr[pos++]) {
case 'r': destreg = bitval[bitr]; dstgather = 1; dstpos = bitpos[bitr]; break;
case 'R': destreg = bitval[bitR]; dstgather = 1; dstpos = bitpos[bitR]; break;
case 'x': destreg = 0; dstgather = 0; dstpos = 0; break;
default: abort();
}
if (dstpos < 0 || dstpos >= 32)
abort();
switch (opcstr[pos]) {
case 'p': destmode = Apdi; pos++; break;
case 'P': destmode = Aipi; pos++; break;
}
break;
case 'L':
destmode = absl;
break;
case '#':
switch (opcstr[pos++]) {
case 'z': destmode = imm; break;
@ -767,44 +700,8 @@ static void build_insn (int insn)
table68k[opc].flaginfo[i].flaguse = id.flaginfo[i].flaguse;
}
#endif
// Fix flags used information for Scc, Bcc, TRAPcc, DBcc instructions
if ( table68k[opc].mnemo == i_Scc
|| table68k[opc].mnemo == i_Bcc
|| table68k[opc].mnemo == i_DBcc
|| table68k[opc].mnemo == i_TRAPcc
) {
switch (table68k[opc].cc) {
// CC mask: XNZVC
// 8421
case 0: flags_used = 0x00; break; /* T */
case 1: flags_used = 0x00; break; /* F */
case 2: flags_used = 0x05; break; /* HI */
case 3: flags_used = 0x05; break; /* LS */
case 4: flags_used = 0x01; break; /* CC */
case 5: flags_used = 0x01; break; /* CS */
case 6: flags_used = 0x04; break; /* NE */
case 7: flags_used = 0x04; break; /* EQ */
case 8: flags_used = 0x02; break; /* VC */
case 9: flags_used = 0x02; break; /* VS */
case 10:flags_used = 0x08; break; /* PL */
case 11:flags_used = 0x08; break; /* MI */
case 12:flags_used = 0x0A; break; /* GE */
case 13:flags_used = 0x0A; break; /* LT */
case 14:flags_used = 0x0E; break; /* GT */
case 15:flags_used = 0x0E; break; /* LE */
}
}
#if 1
/* gb-- flagdead and flaglive would not have correct information */
table68k[opc].flagdead = flags_set;
table68k[opc].flaglive = flags_used;
#else
table68k[opc].flagdead = flagdead;
table68k[opc].flaglive = flaglive;
#endif
table68k[opc].cflow = cflow;
nomatch:
/* FOO! */;
}
@ -850,10 +747,6 @@ static void handle_merges (long int opcode)
smsk = 7; sbitdst = 8; break;
case 5:
smsk = 63; sbitdst = 64; break;
case 6:
smsk = 255; sbitdst = 256; break;
case 7:
smsk = 3; sbitdst = 4; break;
default:
smsk = 0; sbitdst = 0;
abort();
@ -869,7 +762,7 @@ static void handle_merges (long int opcode)
}
for (srcreg=0; srcreg < sbitdst; srcreg++) {
for (dstreg=0; dstreg < dstend; dstreg++) {
uae_u16 code = uae_u16(opcode);
uae_u16 code = opcode;
code = (code & ~smsk) | (srcreg << table68k[opcode].spos);
code = (code & ~dmsk) | (dstreg << table68k[opcode].dpos);
@ -922,112 +815,3 @@ int get_no_mismatches (void)
{
return mismatch;
}
const char *get_instruction_name (unsigned int opcode)
{
struct instr *ins = &table68k[opcode];
for (int i = 0; lookuptab[i].name[0]; i++) {
if (ins->mnemo == lookuptab[i].mnemo)
return lookuptab[i].name;
}
abort();
return NULL;
}
static char *get_ea_string (amodes mode, wordsizes size)
{
static char buffer[80];
buffer[0] = 0;
switch (mode){
case Dreg:
strcpy (buffer,"Dn");
break;
case Areg:
strcpy (buffer,"An");
break;
case Aind:
strcpy (buffer,"(An)");
break;
case Aipi:
strcpy (buffer,"(An)+");
break;
case Apdi:
strcpy (buffer,"-(An)");
break;
case Ad16:
strcpy (buffer,"(d16,An)");
break;
case Ad8r:
strcpy (buffer,"(d8,An,Xn)");
break;
case PC16:
strcpy (buffer,"(d16,PC)");
break;
case PC8r:
strcpy (buffer,"(d8,PC,Xn)");
break;
case absw:
strcpy (buffer,"(xxx).W");
break;
case absl:
strcpy (buffer,"(xxx).L");
break;
case imm:
switch (size){
case sz_byte:
strcpy (buffer,"#<data>.B");
break;
case sz_word:
strcpy (buffer,"#<data>.W");
break;
case sz_long:
strcpy (buffer,"#<data>.L");
break;
default:
break;
}
break;
case imm0:
strcpy (buffer,"#<data>.B");
break;
case imm1:
strcpy (buffer,"#<data>.W");
break;
case imm2:
strcpy (buffer,"#<data>.L");
break;
case immi:
strcpy (buffer,"#<data>");
break;
default:
break;
}
return buffer;
}
const char *get_instruction_string (unsigned int opcode)
{
static char out[100];
struct instr *ins;
strcpy (out, get_instruction_name (opcode));
ins = &table68k[opcode];
if (ins->size == sz_byte)
strcat (out,".B");
if (ins->size == sz_word)
strcat (out,".W");
if (ins->size == sz_long)
strcat (out,".L");
strcat (out," ");
if (ins->suse)
strcat (out, get_ea_string (amodes(ins->smode), wordsizes(ins->size)));
if (ins->duse) {
if (ins->suse)
strcat (out,",");
strcat (out, get_ea_string (amodes(ins->dmode), wordsizes(ins->size)));
}
return out;
}

View File

@ -1,6 +1,3 @@
#ifndef READCPU_H
#define READCPU_H
#ifdef __cplusplus
extern "C" {
#endif
@ -35,8 +32,7 @@ ENUMDECL {
i_PACK, i_UNPK, i_TAS, i_BKPT, i_CALLM, i_RTM, i_TRAPcc, i_MOVES,
i_FPP, i_FDBcc, i_FScc, i_FTRAPcc, i_FBcc, i_FSAVE, i_FRESTORE,
i_CINVL, i_CINVP, i_CINVA, i_CPUSHL, i_CPUSHP, i_CPUSHA, i_MOVE16,
i_MMUOP,
i_EMULOP_RETURN, i_EMULOP
i_MMUOP
} ENUMNAME (instrmnem);
extern struct mnemolookup {
@ -56,21 +52,9 @@ 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
bits, bitS, bitd, bitD, bitr, bitR, bitz, lastbit
} ENUMNAME (bitvals);
struct instr_def {
@ -84,7 +68,6 @@ struct instr_def {
unsigned int flaguse:3;
unsigned int flagset:3;
} flaginfo[5];
unsigned char cflow;
unsigned char sduse;
const char *opcstr;
};
@ -103,16 +86,22 @@ extern struct instr {
unsigned int mnemo:8;
unsigned int cc:4;
unsigned int plev:2;
#ifdef sgi
wordsizes size:2;
amodes smode:5;
unsigned int stype:3;
amodes dmode:5;
#else
unsigned int size:2;
unsigned int smode:5;
unsigned int stype:3;
unsigned int dmode:5;
#endif
unsigned int suse:1;
unsigned int duse:1;
unsigned int unused1:1;
unsigned int clev:3;
unsigned int cflow:3;
unsigned int unused2:2;
unsigned int unused2:5;
} *table68k;
extern void read_table68k (void);
@ -120,11 +109,6 @@ extern void do_merges (void);
extern int get_no_mismatches (void);
extern int nr_cpuop_funcs;
extern const char *get_instruction_name (unsigned int opcode);
extern const char *get_instruction_string (unsigned int opcode);
#ifdef __cplusplus
}
#endif
#endif /* READCPU_H */

View File

@ -1,103 +0,0 @@
/*
* 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,
SPCFLAG_JIT_END_COMPILE = 0,
SPCFLAG_JIT_EXEC_RETURN = 0,
SPCFLAG_ALL = SPCFLAG_STOP
| SPCFLAG_INT
| SPCFLAG_BRK
| SPCFLAG_TRACE
| SPCFLAG_DOTRACE
| SPCFLAG_DOINT
| SPCFLAG_JIT_END_COMPILE
| SPCFLAG_JIT_EXEC_RETURN
,
SPCFLAG_ALL_BUT_EXEC_RETURN = SPCFLAG_ALL & ~SPCFLAG_JIT_EXEC_RETURN
};
#define SPCFLAGS_TEST(m) \
((regs.spcflags & (m)) != 0)
/* Macro only used in m68k_reset() */
#define SPCFLAGS_INIT(m) do { \
regs.spcflags = (m); \
} while (0)
#if !(ENABLE_EXCLUSIVE_SPCFLAGS)
#define SPCFLAGS_SET(m) do { \
regs.spcflags |= (m); \
} while (0)
#define SPCFLAGS_CLEAR(m) do { \
regs.spcflags &= ~(m); \
} while (0)
#elif defined(X86_ASSEMBLY)
#define HAVE_HARDWARE_LOCKS
#define SPCFLAGS_SET(m) do { \
__asm__ __volatile__("lock\n\torl %1,%0" : "=m" (regs.spcflags) : "i" ((m))); \
} while (0)
#define SPCFLAGS_CLEAR(m) do { \
__asm__ __volatile__("lock\n\tandl %1,%0" : "=m" (regs.spcflags) : "i" (~(m))); \
} while (0)
#else
#undef HAVE_HARDWARE_LOCKS
#include "main.h"
extern B2_mutex *spcflags_lock;
#define SPCFLAGS_SET(m) do { \
B2_lock_mutex(spcflags_lock); \
regs.spcflags |= (m); \
B2_unlock_mutex(spcflags_lock); \
} while (0)
#define SPCFLAGS_CLEAR(m) do { \
B2_lock_mutex(spcflags_lock); \
regs.spcflags &= ~(m); \
B2_unlock_mutex(spcflags_lock); \
} while (0)
#endif
#endif /* SPCFLAGS_H */

View File

@ -4,13 +4,11 @@
% 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
@ -26,7 +24,6 @@
%
% Arp: --> -(Ar)
% ArP: --> (Ar)+
% L: --> (xxx.L)
%
% Fields on a line:
% 16 chars bitpattern :
@ -46,17 +43,10 @@
% 0 means flag reset
% 1 means flag set
% ? means programmer was too lazy to check or instruction may trap
% + means instruction is conditional branch
% everything else means flag set/used
% / means instruction is unconditional branch/call
% 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
@ -66,209 +56,197 @@
% 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 0000 0011 1100:00:XNZVC:XNZVC:10: ORSR.B #1
0000 0000 0111 1100:02:?????:?????:10: ORSR.W #1
0000 0zz0 11ss sSSS:20:?????:?????:11: CHK2.z #1,s[!Dreg,Areg,Aipi,Apdi,Immd]
0000 0000 zzdd dDDD:00:-NZ00:-----:13: OR.z #z,d[!Areg]
0000 0010 0011 1100:00:XNZVC:XNZVC:10: ANDSR.B #1
0000 0010 0111 1100:02:?????:?????:10: ANDSR.W #1
0000 0010 zzdd dDDD:00:-NZ00:-----:13: AND.z #z,d[!Areg]
0000 0100 zzdd dDDD:00:XNZVC:-----:13: SUB.z #z,d[!Areg]
0000 0110 zzdd dDDD:00:XNZVC:-----:13: ADD.z #z,d[!Areg]
0000 0110 11ss sSSS:20:?????:?????:10: CALLM s[!Dreg,Areg,Aipi,Apdi,Immd]
0000 0110 11ss sSSS:20:?????:?????:10: RTM s[Dreg,Areg]
0000 1000 00ss sSSS:00:--Z--:-----:11: BTST #1,s[!Areg]
0000 1000 01ss sSSS:00:--Z--:-----:13: BCHG #1,s[!Areg,Immd]
0000 1000 10ss sSSS:00:--Z--:-----:13: BCLR #1,s[!Areg,Immd]
0000 1000 11ss sSSS:00:--Z--:-----:13: BSET #1,s[!Areg,Immd]
0000 1010 0011 1100:00:XNZVC:XNZVC:10: EORSR.B #1
0000 1010 0111 1100:02:?????:?????:10: EORSR.W #1
0000 1010 zzdd dDDD:00:-NZ00:-----:13: EOR.z #z,d[!Areg]
0000 1100 zzss sSSS:00:-NZVC:-----:11: CMP.z #z,s[!Areg,Immd]
0000 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 1010 11ss sSSS:20:?????:?????:13: CAS.B #1,s[!Dreg,Areg,Immd,PC8r,PC16]
0000 1100 11ss sSSS:20:?????:?????:13: CAS.W #1,s[!Dreg,Areg,Immd,PC8r,PC16]
0000 1100 1111 1100:20:?????:?????:10: CAS2.W #2
0000 1110 zzss sSSS:22:?????:?????:13: MOVES.z #1,s[!Dreg,Areg,Immd,PC8r,PC16]
0000 1110 11ss sSSS:20:?????:?????:13: CAS.L #1,s[!Dreg,Areg,Immd,PC8r,PC16]
0000 1110 1111 1100:20:?????:?????:10: CAS2.L #2
0000 rrr1 00dd dDDD:00:-----:-----:--:12: MVPMR.W d[Areg-Ad16],Dr
0000 rrr1 01dd dDDD:00:-----:-----:--:12: MVPMR.L d[Areg-Ad16],Dr
0000 rrr1 10dd dDDD:00:-----:-----:--:12: MVPRM.W Dr,d[Areg-Ad16]
0000 rrr1 11dd dDDD:00:-----:-----:--:12: MVPRM.L Dr,d[Areg-Ad16]
0000 rrr1 00ss sSSS:00:--Z--:-----:--:11: BTST Dr,s[!Areg]
0000 rrr1 01ss sSSS:00:--Z--:-----:--:13: BCHG Dr,s[!Areg,Immd]
0000 rrr1 10ss sSSS:00:--Z--:-----:--:13: BCLR Dr,s[!Areg,Immd]
0000 rrr1 11ss sSSS:00:--Z--:-----:--:13: BSET Dr,s[!Areg,Immd]
0000 rrr1 00dd dDDD:00:-----:-----:12: MVPMR.W d[Areg-Ad16],Dr
0000 rrr1 01dd dDDD:00:-----:-----:12: MVPMR.L d[Areg-Ad16],Dr
0000 rrr1 10dd dDDD:00:-----:-----:12: MVPRM.W Dr,d[Areg-Ad16]
0000 rrr1 11dd dDDD:00:-----:-----:12: MVPRM.L Dr,d[Areg-Ad16]
0000 rrr1 00ss sSSS:00:--Z--:-----:11: BTST Dr,s[!Areg]
0000 rrr1 01ss sSSS:00:--Z--:-----:13: BCHG Dr,s[!Areg,Immd]
0000 rrr1 10ss sSSS:00:--Z--:-----:13: BCLR Dr,s[!Areg,Immd]
0000 rrr1 11ss sSSS:00:--Z--:-----:13: BSET Dr,s[!Areg,Immd]
0001 DDDd ddss sSSS:00:-NZ00:-----:--:12: MOVE.B s,d[!Areg]
0010 DDDd ddss sSSS:00:-----:-----:--:12: MOVEA.L s,d[Areg]
0010 DDDd ddss sSSS:00:-NZ00:-----:--:12: MOVE.L s,d[!Areg]
0011 DDDd ddss sSSS:00:-----:-----:--:12: MOVEA.W s,d[Areg]
0011 DDDd ddss sSSS:00:-NZ00:-----:--:12: MOVE.W s,d[!Areg]
0001 DDDd ddss sSSS:00:-NZ00:-----:12: MOVE.B s,d[!Areg]
0010 DDDd ddss sSSS:00:-----:-----:12: MOVEA.L s,d[Areg]
0010 DDDd ddss sSSS:00:-NZ00:-----:12: MOVE.L s,d[!Areg]
0011 DDDd ddss sSSS:00:-----:-----:12: MOVEA.W s,d[Areg]
0011 DDDd ddss sSSS:00:-NZ00:-----:12: MOVE.W s,d[!Areg]
0100 0000 zzdd dDDD:00:XxZxC: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
0100 0000 zzdd dDDD:00:XxZxC:-----:30: NEGX.z d[!Areg]
0100 0000 11dd dDDD:01:?????:?????:10: MVSR2.W d[!Areg]
0100 0010 zzdd dDDD:00:-0100:-----:20: CLR.z d[!Areg]
0100 0010 11dd dDDD:10:?????:?????:10: MVSR2.B d[!Areg]
0100 0100 zzdd dDDD:00:XNZVC:-----:30: NEG.z d[!Areg]
0100 0100 11ss sSSS:00:XNZVC:-----:10: MV2SR.B s[!Areg]
0100 0110 zzdd dDDD:00:-NZ00:-----:30: NOT.z d[!Areg]
0100 0110 11ss sSSS:02:?????:?????:10: MV2SR.W s[!Areg]
0100 1000 0000 1rrr:20:-----:-----:31: LINK.L Ar,#2
0100 1000 00dd dDDD:00:X?Z?C:X-Z--:30: NBCD.B d[!Areg]
0100 1000 0100 1kkk:20:?????:?????:10: BKPT #k
0100 1000 01ss sSSS:00:-NZ00:-----:30: SWAP.W s[Dreg]
0100 1000 01ss sSSS:00:-----:-----:00: PEA.L s[!Dreg,Areg,Aipi,Apdi,Immd]
0100 1000 10dd dDDD:00:-NZ00:-----:30: EXT.W d[Dreg]
0100 1000 10dd dDDD:00:-----:-----:02: MVMLE.W #1,d[!Dreg,Areg,Aipi]
0100 1000 11dd dDDD:00:-NZ00:-----:30: EXT.L d[Dreg]
0100 1000 11dd dDDD:00:-----:-----:02: MVMLE.L #1,d[!Dreg,Areg,Aipi]
0100 1001 11dd dDDD:00:-NZ00:-----:30: EXT.B d[Dreg]
0100 1010 zzss sSSS:00:-NZ00:-----:10: TST.z s
0100 1010 11dd dDDD:00:?????:?????:30: TAS.B d[!Areg]
0100 1010 1111 1100:00:?????:?????:00: ILLEGAL
0100 1100 00ss sSSS:20:-NZVC:-----:13: MULL.L #1,s[!Areg]
0100 1100 01ss sSSS:20:?????:?????:13: DIVL.L #1,s[!Areg]
0100 1100 10ss sSSS:00:-----:-----:01: MVMEL.W #1,s[!Dreg,Areg,Apdi,Immd]
0100 1100 11ss sSSS:00:-----:-----:01: MVMEL.L #1,s[!Dreg,Areg,Apdi,Immd]
0100 1110 0100 JJJJ:00:-----:XNZVC:10: TRAP #J
0100 1110 0101 0rrr:00:-----:-----:31: LINK.W Ar,#1
0100 1110 0101 1rrr:00:-----:-----:30: UNLK.L Ar
0100 1110 0110 0rrr:02:-----:-----:10: MVR2USP.L Ar
0100 1110 0110 1rrr:02:-----:-----:20: MVUSP2R.L Ar
0100 1110 0111 0000:02:-----:-----:00: RESET
0100 1110 0111 0001:00:-----:-----:00: NOP
0100 1110 0111 0010:02:XNZVC:-----:10: STOP #1
0100 1110 0111 0011:02:XNZVC:-----:00: RTE
0100 1110 0111 0100:00:?????:?????:10: RTD #1
0100 1110 0111 0101:00:-----:-----:00: RTS
0100 1110 0111 0110:00:-----:XNZVC:00: TRAPV
0100 1110 0111 0111:00:XNZVC:-----:00: RTR
0100 1110 0111 1010:12:?????:?????:10: MOVEC2 #1
0100 1110 0111 1011:12:?????:?????:10: MOVE2C #1
0100 1110 10ss sSSS:00://///://///:80: JSR.L s[!Dreg,Areg,Aipi,Apdi,Immd]
0100 rrr1 00ss sSSS:00:?????:?????:11: CHK.L s[!Areg],Dr
0100 rrr1 10ss sSSS:00:?????:?????:11: CHK.W s[!Areg],Dr
0100 1110 11ss sSSS:00://///://///:80: JMP.L s[!Dreg,Areg,Aipi,Apdi,Immd]
0100 rrr1 11ss sSSS:00:-----:-----:02: LEA.L s[!Dreg,Areg,Aipi,Apdi,Immd],Ar
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
0101 jjj0 zzdd dDDD:00:-----:-----:13: ADDA.z #j,d[Areg]
0101 jjj0 zzdd dDDD:00:XNZVC:-----:13: ADD.z #j,d[!Areg]
0101 jjj1 zzdd dDDD:00:-----:-----:13: SUBA.z #j,d[Areg]
0101 jjj1 zzdd dDDD:00:XNZVC:-----:13: SUB.z #j,d[!Areg]
0101 cccc 1100 1rrr:00:-----:+++++:31: DBcc.W Dr,#1
0101 cccc 11dd dDDD:00:-----:+++++:20: Scc.B d[!Areg]
0101 cccc 1111 1010:20:?????:?????:10: TRAPcc #1
0101 cccc 1111 1011:20:?????:?????:10: TRAPcc #2
0101 cccc 1111 1100:20:?????:?????:00: TRAPcc
% Bxx.L is 68020 only, but setting the CPU level to 2 would give illegal
% instruction exceptions when compiling a 68000 only emulation, which isn't
% what we want either.
0110 0001 0000 0000:00:-----:-----:-B:40: BSR.W #1
0110 0001 IIII IIII:00:-----:-----:-B:40: BSR.B #i
0110 0001 1111 1111:00:-----:-----:-B:40: BSR.L #2
0110 CCCC 0000 0000:00:-----:-????:-B:40: Bcc.W #1
0110 CCCC IIII IIII:00:-----:-????:-B:40: Bcc.B #i
0110 CCCC 1111 1111:00:-----:-????:-B:40: Bcc.L #2
0110 0001 0000 0000:00://///://///:40: BSR.W #1
0110 0001 IIII IIII:00://///://///:40: BSR.B #i
0110 0001 1111 1111:00://///://///:40: BSR.L #2
0110 CCCC 0000 0000:00:-----:+++++:40: Bcc.W #1
0110 CCCC IIII IIII:00:-----:+++++:40: Bcc.B #i
0110 CCCC 1111 1111:00:-----:+++++:40: Bcc.L #2
0111 rrr0 iiii iiii:00:-NZ00:-----:--:12: MOVE.L #i,Dr
0111 rrr0 iiii iiii:00:-NZ00:-----:12: MOVE.L #i,Dr
1000 rrr0 zzss sSSS:00:-NZ00:-----:--:13: OR.z s[!Areg],Dr
1000 rrr0 11ss sSSS:00:-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
1000 rrr0 zzss sSSS:00:-NZ00:-----:13: OR.z s[!Areg],Dr
1000 rrr0 11ss sSSS:00:?????:?????:13: DIVU.W s[!Areg],Dr
1000 rrr1 00dd dDDD:00:XxZxC:X-Z--:13: SBCD.B d[Dreg],Dr
1000 rrr1 00dd dDDD:00:XxZxC:X-Z--:13: SBCD.B d[Areg-Apdi],Arp
1000 rrr1 zzdd dDDD:00:-NZ00:-----:13: OR.z Dr,d[!Areg,Dreg]
1000 rrr1 01dd dDDD:20:?????:?????:12: PACK d[Dreg],Dr
1000 rrr1 01dd dDDD:20:?????:?????:12: PACK d[Areg-Apdi],Arp
1000 rrr1 10dd dDDD:20:?????:?????:12: UNPK d[Dreg],Dr
1000 rrr1 10dd dDDD:20:?????:?????:12: UNPK d[Areg-Apdi],Arp
1000 rrr1 11ss sSSS:00:?????:?????:13: DIVS.W s[!Areg],Dr
1001 rrr0 zzss sSSS:00:XNZVC:-----:--:13: SUB.z s,Dr
1001 rrr0 11ss sSSS:00:-----:-----:--:13: SUBA.W s,Ar
1001 rrr1 zzdd dDDD:00:XNZVC:X-Z--:--:13: SUBX.z d[Dreg],Dr
1001 rrr1 zzdd dDDD:00:XNZVC:X-Z--:--:13: SUBX.z d[Areg-Apdi],Arp
1001 rrr1 zzdd dDDD:00:XNZVC:-----:--:13: SUB.z Dr,d[!Areg,Dreg]
1001 rrr1 11ss sSSS:00:-----:-----:--:13: SUBA.L s,Ar
1001 rrr0 zzss sSSS:00:XNZVC:-----:13: SUB.z s,Dr
1001 rrr0 11ss sSSS:00:-----:-----:13: SUBA.W s,Ar
1001 rrr1 zzdd dDDD:00:XNZVC:X-Z--:13: SUBX.z d[Dreg],Dr
1001 rrr1 zzdd dDDD:00:XNZVC:X-Z--:13: SUBX.z d[Areg-Apdi],Arp
1001 rrr1 zzdd dDDD:00:XNZVC:-----:13: SUB.z Dr,d[!Areg,Dreg]
1001 rrr1 11ss sSSS:00:-----:-----:13: SUBA.L s,Ar
1011 rrr0 zzss sSSS:00:-NZVC:-----:--:11: CMP.z s,Dr
1011 rrr0 11ss sSSS:00:-NZVC:-----:--:11: CMPA.W s,Ar
1011 rrr1 11ss sSSS:00:-NZVC:-----:--:11: CMPA.L s,Ar
1011 rrr1 zzdd dDDD:00:-NZVC:-----:--:11: CMPM.z d[Areg-Aipi],ArP
1011 rrr1 zzdd dDDD:00:-NZ00:-----:--:13: EOR.z Dr,d[!Areg]
1011 rrr0 zzss sSSS:00:-NZVC:-----:11: CMP.z s,Dr
1011 rrr0 11ss sSSS:00:-NZVC:-----:11: CMPA.W s,Ar
1011 rrr1 11ss sSSS:00:-NZVC:-----:11: CMPA.L s,Ar
1011 rrr1 zzdd dDDD:00:-NZVC:-----:11: CMPM.z d[Areg-Aipi],ArP
1011 rrr1 zzdd dDDD:00:-NZ00:-----:13: EOR.z Dr,d[!Areg]
1100 rrr0 zzss sSSS:00:-NZ00:-----:--:13: AND.z s[!Areg],Dr
1100 rrr0 11ss sSSS:00:-NZ00:-----:--:13: MULU.W s[!Areg],Dr
1100 rrr1 00dd dDDD:00:XxZxC:X-Z--:--:13: ABCD.B d[Dreg],Dr
1100 rrr1 00dd dDDD:00:XxZxC:X-Z--:--:13: ABCD.B d[Areg-Apdi],Arp
1100 rrr1 zzdd dDDD:00:-NZ00:-----:--:13: AND.z Dr,d[!Areg,Dreg]
1100 rrr1 01dd dDDD:00:-----:-----:--:33: EXG.L Dr,d[Dreg]
1100 rrr1 01dd dDDD:00:-----:-----:--:33: EXG.L Ar,d[Areg]
1100 rrr1 10dd dDDD:00:-----:-----:--:33: EXG.L Dr,d[Areg]
1100 rrr1 11ss sSSS:00:-NZ00:-----:--:13: MULS.W s[!Areg],Dr
1100 rrr0 zzss sSSS:00:-NZ00:-----:13: AND.z s[!Areg],Dr
1100 rrr0 11ss sSSS:00:-NZ00:-----:13: MULU.W s[!Areg],Dr
1100 rrr1 00dd dDDD:00: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
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 jjjf zz00 0RRR:00:XNZVC:-----:13: ASf.z #j,DR
1110 jjjf zz00 1RRR:00:XNZ0C:-----:13: LSf.z #j,DR
1110 jjjf zz01 0RRR:00:XNZ0C:X----:13: ROXf.z #j,DR
1110 jjjf zz01 1RRR:00:-NZ0C:-----:13: ROf.z #j,DR
1110 rrrf zz10 0RRR:00:XNZVC:X----:13: ASf.z Dr,DR
1110 rrrf zz10 1RRR:00:XNZ0C:X----:13: LSf.z Dr,DR
1110 rrrf zz11 0RRR:00:XNZ0C:X----:13: ROXf.z Dr,DR
1110 rrrf zz11 1RRR:00:-NZ0C:-----:13: ROf.z Dr,DR
1110 000f 11dd dDDD:00:XNZVC:-----:13: ASfW.W d[!Dreg,Areg]
1110 001f 11dd dDDD:00:XNZ0C:-----:13: LSfW.W d[!Dreg,Areg]
1110 010f 11dd dDDD:00:XNZ0C:X----:13: ROXfW.W d[!Dreg,Areg]
1110 011f 11dd dDDD:00:-NZ0C:-----:13: ROfW.W d[!Dreg,Areg]
1110 1000 11ss sSSS:20:-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]
1110 1000 11ss sSSS:20:?????:?????:11: BFTST #1,s[!Areg,Apdi,Aipi,Immd]
1110 1001 11ss sSSS:20:?????:?????:11: BFEXTU #1,s[!Areg,Apdi,Aipi,Immd]
1110 1010 11ss sSSS:20:?????:?????:13: BFCHG #1,s[!Areg,Apdi,Aipi,Immd,PC8r,PC16]
1110 1011 11ss sSSS:20:?????:?????:11: BFEXTS #1,s[!Areg,Apdi,Aipi,Immd]
1110 1100 11ss sSSS:20:?????:?????:13: BFCLR #1,s[!Areg,Apdi,Aipi,Immd,PC8r,PC16]
1110 1101 11ss sSSS:20:?????:?????:11: BFFFO #1,s[!Areg,Apdi,Aipi,Immd]
1110 1110 11ss sSSS:20:?????:?????:13: BFSET #1,s[!Areg,Apdi,Aipi,Immd,PC8r,PC16]
1110 1111 11ss sSSS:20:?????:?????:13: BFINS #1,s[!Areg,Apdi,Aipi,Immd,PC8r,PC16]
% 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]
% TODO: FPU is currently commented out
% 1111 0010 00ss sSSS:30:?????:?????:11: FPP #1,s
% 1111 0010 01ss sSSS:30:?????:?????:11: FDBcc #1,s[Areg-Dreg]
% 1111 0010 01ss sSSS:30:?????:?????:11: FScc #1,s[!Areg,Immd,PC8r,PC16]
% 1111 0010 0111 1010:30:?????:?????:10: FTRAPcc #1
% 1111 0010 0111 1011:30:?????:?????:10: FTRAPcc #2
% 1111 0010 0111 1100:30:?????:?????:00: FTRAPcc
% 1111 0010 10KK KKKK:30:?????:?????:11: FBcc #K,#1
% 1111 0010 11KK KKKK:30:?????:?????:11: FBcc #K,#2
% 1111 0011 00ss sSSS:32:?????:?????:20: FSAVE s[!Dreg,Areg,Aipi,Immd,PC8r,PC16]
% 1111 0011 01ss sSSS:32:?????:?????:10: FRESTORE s[!Dreg,Areg,Apdi,Immd]
% 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
1111 0100 ii00 1rrr:42:-----:-----:02: CINVL #i,Ar
1111 0100 ii01 0rrr:42:-----:-----:02: CINVP #i,Ar
1111 0100 ii01 1rrr:42:-----:-----:00: CINVA #i
1111 0100 ii10 1rrr:42:-----:-----:02: CPUSHL #i,Ar
1111 0100 ii11 0rrr:42:-----:-----:02: CPUSHP #i,Ar
1111 0100 ii11 1rrr:42:-----:-----:00: CPUSHA #i
1111 0110 0010 0rrr:40:-----:-----:12: MOVE16 ArP,ARP