Downgraded emulated UAE cpu
This commit is contained in:
parent
023251dee1
commit
1bf6e93461
|
@ -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})
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
|
@ -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
|
|
@ -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 */
|
|
@ -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
|
|
@ -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 */
|
|
@ -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
|
@ -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 */
|
|
@ -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 */
|
|
@ -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
|
@ -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
|
|
@ -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 */
|
|
@ -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
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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(®s.prefetch);
|
||||
return (do_get_mem_word (((uae_u16 *)®s.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 (®s.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 */
|
||||
|
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue