diff --git a/amitools/vamos/machine/machine.py b/amitools/vamos/machine/machine.py index 2084a0f..80465eb 100644 --- a/amitools/vamos/machine/machine.py +++ b/amitools/vamos/machine/machine.py @@ -1,7 +1,13 @@ import time import sys -from machine import emu -from machine.m68k import * +import logging + +try: + import machine68k +except ImportError: + logging.error("package 'machine68k' missing! please install with pip.") + sys.exit(1) + from .regs import * from .opcodes import * from .error import ErrorReporter @@ -74,10 +80,6 @@ class Machine(object): 000800 RAM begin. useable by applications """ - CPU_TYPE_68000 = M68K_CPU_TYPE_68000 - CPU_TYPE_68020 = M68K_CPU_TYPE_68020 - CPU_TYPE_68040 = M68K_CPU_TYPE_68040 - run_exit_addr = 0x400 hw_exc_addr = 0x402 ram_begin = 0x800 @@ -87,7 +89,7 @@ class Machine(object): def __init__( self, - cpu_type=M68K_CPU_TYPE_68000, + cpu_type=machine68k.CPUType.M68000, ram_size_kib=1024, use_labels=True, raise_on_main_run=True, @@ -96,13 +98,14 @@ class Machine(object): cpu_name=None, ): if cpu_name is None: - cpu_name = self._get_cpu_name(cpu_type) - # setup musashi components + cpu_name = machine68k.cpu_type_to_str(cpu_type) self.cpu_type = cpu_type self.cpu_name = cpu_name - self.cpu = emu.CPU(cpu_type) - self.mem = emu.Memory(ram_size_kib) - self.traps = emu.Traps() + # setup machine68k + self.machine = machine68k.Machine(cpu_type, ram_size_kib) + self.cpu = self.machine.cpu + self.mem = self.machine.mem + self.traps = self.machine.traps # internal state if use_labels: self.label_mgr = LabelManager() @@ -169,27 +172,9 @@ class Machine(object): @classmethod def parse_cpu_type(cls, cpu_str): - if cpu_str in ("68000", "000", "00"): - return cls.CPU_TYPE_68000, "68000" - elif cpu_str in ("68020", "020", "20"): - return cls.CPU_TYPE_68020, "68020" - elif cpu_str in ("68030", "030", "30"): - # fake 030 CPU only to set AttnFlags accordingly - return cls.CPU_TYPE_68020, "68030(fake)" - elif cpu_str in ("68040", "040", "40"): - return cls.CPU_TYPE_68040, "68040" - else: - return None, None - - def _get_cpu_name(self, cpu_type): - if cpu_type == self.CPU_TYPE_68000: - return "68000" - elif cpu_type == self.CPU_TYPE_68020: - return "68020" - elif cpu_type == self.CPU_TYPE_68040: - return "68040" - else: - return None + cpu_type = machine68k.cpu_type_from_str(cpu_str) + cpu_name = machine68k.cpu_type_to_str(cpu_type) + return cpu_type, cpu_name def _init_cpu(self): # sp and pc does not matter we will overwrite it anyway diff --git a/amitools/vamos/machine/memmap.py b/amitools/vamos/machine/memmap.py index f9c0423..059d320 100644 --- a/amitools/vamos/machine/memmap.py +++ b/amitools/vamos/machine/memmap.py @@ -1,3 +1,4 @@ +from machine68k import CPUType from .hwaccess import HWAccess from amitools.vamos.log import log_mem_map from amitools.vamos.label import LabelRange @@ -8,7 +9,7 @@ class MemoryMap(object): def __init__(self, machine): self.machine = machine self.label_mgr = machine.get_label_mgr() - self.addr_24_bit = machine.get_cpu_type() == machine.CPU_TYPE_68000 + self.addr_24_bit = machine.get_cpu_type() == CPUType.M68000 self.ram_total = machine.get_ram_total() # options self.hw_access = None diff --git a/machine/__init__.py b/machine/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/machine/emu.pyx b/machine/emu.pyx deleted file mode 100644 index 91be4e8..0000000 --- a/machine/emu.pyx +++ /dev/null @@ -1,3 +0,0 @@ -include "pycpu.pyx" -include "pymem.pyx" -include "pytraps.pyx" diff --git a/machine/emu_test.py b/machine/emu_test.py deleted file mode 100644 index 5d8b21a..0000000 --- a/machine/emu_test.py +++ /dev/null @@ -1,131 +0,0 @@ -# emu_test.py -# test the musashi binding - -from . import emu -from . import m68k - - -def run(): - print("create CPU, Memory, Traps") - # 68k with 128 KiB mem - cpu = emu.CPU(m68k.M68K_CPU_TYPE_68000) - memory = emu.Memory(128) - traps = emu.Traps() - - # get a special range - spec_addr = memory.reserve_special_range() - print("special range: %06x" % spec_addr) - - def invalid(mode, width, addr): - print("MY INVALID: %s(%d): %06x" % (chr(mode), width, addr)) - - def trace(mode, width, addr, value): - print("TRACE: %s(%d): %06x: %x" % (chr(mode), width, addr, value)) - return 0 - - memory.set_invalid_func(invalid) - memory.set_trace_func(trace) - memory.set_trace_mode(True) - - def pc_changed(addr): - print("pc %06x" % (addr)) - - def reset_handler(): - print("RESET") - - def instr_hook(): - print("INSTR HOOK") - - cpu.set_pc_changed_callback(pc_changed) - cpu.set_reset_instr_callback(reset_handler) - cpu.set_instr_hook_callback(instr_hook) - - print("resetting cpu...") - cpu.pulse_reset() - - # write mem - print("write mem...") - memory.w16(0x1000, 0x4E70) # RESET - val = memory.r16(0x1000) - print("RESET op=%04x" % val) - - # block write - print(memory.r_block(0, 4)) - memory.w_block(0, "woah") - print(memory.r_block(0, 4)) - - # string - memory.clear_block(0, 100, 11) - memory.w_cstr(0, "hello, world!") - s = memory.r_cstr(0) - print(s, type(s)) - - # string - memory.clear_block(0, 100, 11) - memory.w_bstr(0, "hello, world!") - s = memory.r_bstr(0) - print(s, type(s)) - - # copy block - memory.w_bstr(0, "hello, world!") - memory.copy_block(0, 100, 100) - txt = memory.r_bstr(100) - print(txt) - - # valid range - print("executing...") - cpu.w_reg(m68k.M68K_REG_PC, 0x1000) - print(cpu.execute(2)) - - # invalid range - print("executing invalid...") - cpu.w_reg(m68k.M68K_REG_PC, spec_addr) - print(cpu.execute(2)) - - # test traps - print("--- traps ---") - - def my_trap(op, pc): - print("MY TRAP: %04x @ %08x" % (op, pc)) - - tid = traps.setup(my_trap, auto_rts=True) - print("trap id=", tid) - - # call trap - memory.w16(0x2000, 0xA000 + tid) - cpu.w_reg(m68k.M68K_REG_PC, 0x2000) - print("call trap") - print(cpu.execute(4)) - - # free trap - traps.free(tid) - - # special read - print("special read...") - - def my_r16(addr): - print("MY RANGE: %06x" % addr) - return 0xDEAD - - memory.set_special_range_read_func(spec_addr, 1, my_r16) - v = memory.r16(spec_addr) - print("special=%0x" % v) - - # check if mem is in end mode? - is_end = memory.is_end() - print("mem is_end:", is_end) - - print("get/set register") - print("%08x" % cpu.r_reg(m68k.M68K_REG_D0)) - cpu.w_reg(m68k.M68K_REG_D0, 0xDEADBEEF) - print("%08x" % cpu.r_reg(m68k.M68K_REG_D0)) - - # disassemble - print("disassemble") - print(cpu.disassemble(0x1000)) - - print("done") - - -if __name__ == "__main__": - run() diff --git a/machine/m68k.py b/machine/m68k.py deleted file mode 100755 index c53ed5f..0000000 --- a/machine/m68k.py +++ /dev/null @@ -1,61 +0,0 @@ -#!/usr/bin/env python -# -# m68k.py -# -# constants for musashi m68k CPU emulator -# - -# cpu type -M68K_CPU_TYPE_INVALID = 0 -M68K_CPU_TYPE_68000 = 1 -M68K_CPU_TYPE_68010 = 2 -M68K_CPU_TYPE_68EC020 = 3 -M68K_CPU_TYPE_68020 = 4 -M68K_CPU_TYPE_68030 = 5 # Supported by disassembler ONLY -M68K_CPU_TYPE_68040 = 6 # Supported by disassembler ONLY - -# registers -M68K_REG_D0 = 0 -M68K_REG_D1 = 1 -M68K_REG_D2 = 2 -M68K_REG_D3 = 3 -M68K_REG_D4 = 4 -M68K_REG_D5 = 5 -M68K_REG_D6 = 6 -M68K_REG_D7 = 7 -M68K_REG_A0 = 8 -M68K_REG_A1 = 9 -M68K_REG_A2 = 10 -M68K_REG_A3 = 11 -M68K_REG_A4 = 12 -M68K_REG_A5 = 13 -M68K_REG_A6 = 14 -M68K_REG_A7 = 15 -M68K_REG_PC = 16 # Program Counter -M68K_REG_SR = 17 # Status Register -M68K_REG_SP = 18 # The current Stack Pointer (located in A7) -M68K_REG_USP = 19 # User Stack Pointer -M68K_REG_ISP = 20 # Interrupt Stack Pointer -M68K_REG_MSP = 21 # Master Stack Pointer -M68K_REG_SFC = 22 # Source Function Code -M68K_REG_DFC = 23 # Destination Function Code -M68K_REG_VBR = 24 # Vector Base Register -M68K_REG_CACR = 25 # Cache Control Register -M68K_REG_CAAR = 26 # Cache Address Register - -M68K_REG_PREF_ADDR = 27 # Virtual Reg: Last prefetch address -M68K_REG_PREF_DATA = 28 # Virtual Reg: Last prefetch data - -M68K_REG_PPC = 29 # Previous value in the program counter -M68K_REG_IR = 30 # Instruction register -M68K_REG_CPU_TYPE = 31 # Type of CPU being run - -# aline callback -M68K_ALINE_NONE = 0 -M68K_ALINE_EXCEPT = 1 -M68K_ALINE_RTS = 2 - -# traps -TRAP_DEFAULT = 0 -TRAP_ONE_SHOT = 1 -TRAP_AUTO_RTS = 2 diff --git a/machine/mem.c b/machine/mem.c deleted file mode 100644 index 5421405..0000000 --- a/machine/mem.c +++ /dev/null @@ -1,392 +0,0 @@ -/* MusashiCPU <-> vamos memory interface - * - * written by Christian Vogelgsang - * under the GNU Public License V2 - */ - -#include -#include -#include - -#include "mem.h" - -/* THOR: I need a *little* more memory than 16MB. -** This gives 256MB max. -*/ -#define NUM_PAGES 4096 - -/* ----- Data ----- */ -static uint8_t *ram_data; -static uint ram_size; -static uint ram_pages; - -static read_func_t r_func[NUM_PAGES][3]; -static write_func_t w_func[NUM_PAGES][3]; -static void * r_ctx[NUM_PAGES][3]; -static void * w_ctx[NUM_PAGES][3]; - -static invalid_func_t invalid_func; -static void *invalid_ctx; -static int mem_trace = 0; -static trace_func_t trace_func; -static void *trace_ctx; -static uint special_page = NUM_PAGES; - -/* ----- RAW Access ----- */ -extern uint8_t *mem_raw_ptr(void) -{ - return ram_data; -} - -extern uint mem_raw_size(void) -{ - return ram_size; -} - -/* ----- Default Funcs ----- */ -static void default_invalid(int mode, int width, uint addr, void *ctx) -{ - printf("INVALID: %c(%d): %06x\n",(char)mode,width,addr); -} - -static void default_trace(int mode, int width, uint addr, uint val, void *ctx) -{ - printf("%c(%d): %06x: %x\n",(char)mode,width,addr,val); -} - -static uint r8_fail(uint addr, void *ctx) -{ - invalid_func('R', 0, addr, invalid_ctx); - return 0; -} - -static uint r16_fail(uint addr, void *ctx) -{ - invalid_func('R', 1, addr, invalid_ctx); - return 0; -} - -static uint r32_fail(uint addr, void *ctx) -{ - invalid_func('R', 2, addr, invalid_ctx); - return 0; -} - -static void w8_fail(uint addr, uint val, void *ctx) -{ - invalid_func('W', 0, addr, invalid_ctx); -} - -static void w16_fail(uint addr, uint val, void *ctx) -{ - invalid_func('W', 1, addr, invalid_ctx); -} - -static void w32_fail(uint addr, uint val, void *ctx) -{ - invalid_func('W', 2, addr, invalid_ctx); -} - -/* ----- RAM access ----- */ -static uint mem_r8_ram(uint addr, void *ctx) -{ - return ram_data[addr]; -} - -static uint mem_r16_ram(uint addr, void *ctx) -{ - return (ram_data[addr] << 8) | ram_data[addr+1]; -} - -static uint mem_r32_ram(uint addr, void *ctx) -{ - return (ram_data[addr] << 24) | (ram_data[addr+1] << 16) | (ram_data[addr+2] << 8) | (ram_data[addr+3]); -} - -static void mem_w8_ram(uint addr, uint val, void *ctx) -{ - ram_data[addr] = val; -} - -static void mem_w16_ram(uint addr, uint val, void *ctx) -{ - ram_data[addr] = val >> 8; - ram_data[addr+1] = val & 0xff; -} - -static void mem_w32_ram(uint addr, uint val, void *ctx) -{ - ram_data[addr] = val >> 24; - ram_data[addr+1] = (val >> 16) & 0xff; - ram_data[addr+2] = (val >> 8) & 0xff; - ram_data[addr+3] = val & 0xff; -} - -/* ----- Musashi Interface ----- */ - -#include "m68kcpu.h" - -unsigned int m68k_read_memory_8(unsigned int address) -{ - uint page = address >> 16; - if (page < NUM_PAGES) { - uint val = r_func[page][0](address, r_ctx[page][0]); - if(mem_trace) { - trace_func('R',0,address,val,trace_ctx); - } - return val; - } else { - invalid_func('R',0,address,invalid_ctx); - return 0; - } -} - -unsigned int m68k_read_memory_16(unsigned int address) -{ - uint page = address >> 16; - if (page < NUM_PAGES) { - uint val = r_func[page][1](address, r_ctx[page][1]); - if(mem_trace) { - trace_func('R',1,address,val,trace_ctx); - } - return val; - } else { - invalid_func('R',1,address,invalid_ctx); - return 0; - } -} - -unsigned int m68k_read_memory_32(unsigned int address) -{ - uint page = address >> 16; - if (page < NUM_PAGES) { - uint val = r_func[page][2](address, r_ctx[page][2]); - if(mem_trace) { - trace_func('R',2,address,val,trace_ctx); - } - return val; - } else { - invalid_func('R',2,address,invalid_ctx); - return 0; - } -} - -void m68k_write_memory_8(unsigned int address, unsigned int value) -{ - uint page = address >> 16; - if (page < NUM_PAGES) { - w_func[page][0](address, value, w_ctx[page][0]); - if(mem_trace) { - trace_func('W',0,address,value,trace_ctx); - } - } else { - invalid_func('W',0,address,invalid_ctx); - } -} - -void m68k_write_memory_16(unsigned int address, unsigned int value) -{ - uint page = address >> 16; - if (page < NUM_PAGES) { - w_func[page][1](address, value, w_ctx[page][1]); - if(mem_trace) { - trace_func('W',1,address,value,trace_ctx); - } - } else { - invalid_func('W',1,address,invalid_ctx); - } -} - -void m68k_write_memory_32(unsigned int address, unsigned int value) -{ - uint page = address >> 16; - if (page < NUM_PAGES) { - w_func[page][2](address, value, w_ctx[page][2]); - if(mem_trace) { - trace_func('W',2,address,value,trace_ctx); - } - } else { - invalid_func('W',2,address,invalid_ctx); - } -} - -/* Disassemble support */ - -unsigned int m68k_read_disassembler_16 (unsigned int address) -{ - uint page = address >> 16; - if (page < NUM_PAGES) { - uint val = r_func[page][1](address, r_ctx[page][1]); - return val; - } else { - return 0x0; - } -} - -unsigned int m68k_read_disassembler_32 (unsigned int address) -{ - uint page = address >> 16; - if (page < NUM_PAGES) { - uint val = r_func[page][2](address, r_ctx[page][1]); - return val; - } else { - return 0x0; - } -} - -/* ----- API ----- */ - -int mem_init(uint ram_size_kib) -{ - uint i; - ram_pages = (ram_size_kib + 63) / 64; - ram_size = ram_pages * 64 * 1024; - ram_data = (uint8_t *)malloc(ram_size); - memset(ram_data, 0, ram_size); - - for(i=0;i> 16; - r_func[page][width] = func; - r_ctx[page][width] = ctx; -} - -void mem_set_special_range_write_func(uint page_addr, uint width, write_func_t func, void *ctx) -{ - uint page = page_addr >> 16; - w_func[page][width] = func; - w_ctx[page][width] = ctx; -} - -/* RAM access */ - -int mem_ram_r8(uint addr, uint *val) -{ - if(addr < ram_size) { - *val = ram_data[addr]; - return 0; - } else { - return 1; - } -} - -int mem_ram_r16(uint addr, uint *val) -{ - if(addr < (ram_size - 1)) { - *val = (ram_data[addr] << 8) | ram_data[addr+1]; - return 0; - } else { - return 1; - } -} - -int mem_ram_r32(uint addr, uint *val) -{ - if(addr < (ram_size - 3)) { - *val = (ram_data[addr] << 24) | (ram_data[addr+1] << 16) | (ram_data[addr+2] << 8) | (ram_data[addr+3]); - return 0; - } else { - return 1; - } -} - -int mem_ram_w8(uint addr, uint val) -{ - if(addr < ram_size) { - ram_data[addr] = (uint8_t)(val & 0xff); - return 0; - } else { - return 1; - } -} - -int mem_ram_w16(uint addr, uint val) -{ - if(addr < (ram_size - 1)) { - ram_data[addr] = val >> 8; - ram_data[addr+1] = val & 0xff; - return 0; - } else { - return 1; - } -} - -int mem_ram_w32(uint addr, uint val) -{ - if(addr < (ram_size - 3)) { - ram_data[addr] = val >> 24; - ram_data[addr+1] = (val >> 16) & 0xff; - ram_data[addr+2] = (val >> 8) & 0xff; - ram_data[addr+3] = val & 0xff; - return 0; - } else { - return 1; - } -} - diff --git a/machine/mem.h b/machine/mem.h deleted file mode 100644 index 143fd7e..0000000 --- a/machine/mem.h +++ /dev/null @@ -1,56 +0,0 @@ -/* MusashiCPU <-> vamos memory interface - * - * written by Christian Vogelgsang - * under the GNU Public License V2 - */ - -#ifndef _MEM_H -#define _MEM_H - -#include "m68k.h" -#include - -/* ------ Types ----- */ -#ifndef UINT_TYPE -#define UINT_TYPE -typedef unsigned int uint; -#endif - -typedef uint (*read_func_t)(uint addr, void *ctx); -typedef void (*write_func_t)(uint addr, uint value, void *ctx); - -typedef void (*invalid_func_t)(int mode, int width, uint addr, void *ctx); -typedef void (*trace_func_t)(int mode, int width, uint addr, uint val, void *ctx); - -/* ----- API ----- */ -extern int mem_init(uint ram_size_kib); -extern void mem_free(void); - -extern void mem_set_invalid_func(invalid_func_t func, void *ctx); -extern void mem_set_trace_mode(int on); -extern void mem_set_trace_func(trace_func_t func, void *ctx); - -extern uint mem_reserve_special_range(uint num_pages); -extern void mem_set_special_range_read_func(uint page_addr, uint width, read_func_t func, void *ctx); -extern void mem_set_special_range_write_func(uint page_addr, uint width, write_func_t func, void *ctx); - -extern uint8_t *mem_raw_ptr(void); -extern uint mem_raw_size(void); - -extern unsigned int m68k_read_memory_8(unsigned int address); -extern unsigned int m68k_read_memory_16(unsigned int address); -extern unsigned int m68k_read_memory_32(unsigned int address); - -extern void m68k_write_memory_8(unsigned int address, unsigned int value); -extern void m68k_write_memory_16(unsigned int address, unsigned int value); -extern void m68k_write_memory_32(unsigned int address, unsigned int value); - -extern int mem_ram_r8(uint addr, uint *val); -extern int mem_ram_r16(uint addr, uint *val); -extern int mem_ram_r32(uint addr, uint *val); - -extern int mem_ram_w8(uint addr, uint val); -extern int mem_ram_w16(uint addr, uint val); -extern int mem_ram_w32(uint addr, uint val); - -#endif diff --git a/machine/musashi/Makefile b/machine/musashi/Makefile deleted file mode 100644 index 5ab4767..0000000 --- a/machine/musashi/Makefile +++ /dev/null @@ -1,34 +0,0 @@ -# Just a basic makefile to quickly test that everyting is working, it just -# compiles the .o and the generator - -MUSASHIFILES = m68kcpu.c m68kdasm.c softfloat/softfloat.c -MUSASHIGENCFILES = m68kops.c -MUSASHIGENHFILES = m68kops.h -MUSASHIGENERATOR = m68kmake - -EXE = -EXEPATH = ./ - -.CFILES = $(MAINFILES) $(OSDFILES) $(MUSASHIFILES) $(MUSASHIGENCFILES) -.OFILES = $(.CFILES:%.c=%.o) - -CC = gcc -WARNINGS = -Wall -Wextra -pedantic -CFLAGS = $(WARNINGS) -LFLAGS = $(WARNINGS) - -DELETEFILES = $(MUSASHIGENCFILES) $(MUSASHIGENHFILES) $(.OFILES) $(TARGET) $(MUSASHIGENERATOR)$(EXE) - - -all: $(.OFILES) - -clean: - rm -f $(DELETEFILES) - -m68kcpu.o: $(MUSASHIGENHFILES) m68kfpu.c m68kmmu.h softfloat/softfloat.c softfloat/softfloat.h - -$(MUSASHIGENCFILES) $(MUSASHIGENHFILES): $(MUSASHIGENERATOR)$(EXE) - $(EXEPATH)$(MUSASHIGENERATOR)$(EXE) - -$(MUSASHIGENERATOR)$(EXE): $(MUSASHIGENERATOR).c - $(CC) -o $(MUSASHIGENERATOR)$(EXE) $(MUSASHIGENERATOR).c diff --git a/machine/musashi/history.txt b/machine/musashi/history.txt deleted file mode 100644 index e2205dc..0000000 --- a/machine/musashi/history.txt +++ /dev/null @@ -1,115 +0,0 @@ -The history of Musashi for anyone who might be interested: ---------------------------------------------------------- - -Musashi was born out of sheer boredom. -I needed something to code, and so having had fun with a few of the emulators -around, I decided to try my hand at CPU emulation. -I had owned an Amiga for many years and had done some assembly coding on it so -I figured it would be the ideal chip to cut my teeth on. -Had I known then how much work was involved in emulating a chip like this, I -may not have even started ;-) - - -15-Jul-2013: Musashi license changed to MIT. - -10-Jun-2002: Musashi 3.4 released - - Added various undocumented m68k features thanks to Bart - Trzynadlowski's experiments. - See http://dynarec.com/~bart/files/68knotes.txt for details. - - Fixed a bug that caused privilege violation and illegal - instruction exceptions to stack the wrong PC value. - - Added emulation of address errors (Note: this only works - in 68000 mode. All other CPUs require a LOT of overhead - to emulate this. I'm not sure if I'll implement them or not. - -27-Jan-2001: Musashi 3.3 released - - Fixed problem when displaying negative numbers in disassembler - - Fixed cpu type selector - was allowing 020 instructions to be - disassembled when in 000 mode. - - Fixed opcode jumptable generator (ambiguous operators in the - test for f-line ops) - - Fixed signed/unsigned problem in divl and mull opcodes (not - sure if this was causing an error but best to be sure) - - Cleaned up the naming scheme for the opcode handlers - -14-Aug-2000: Musashi 3.2 released - - Fixed RTE bug that killed the program counter when in m68020 - mode. - - Minor fixes in negx and nbcd. - - renamed d68k.c to m68kdasm.c and merged d68k.h into m68k.h. - d68k_read_xxx() instructions have been renamed to - m68k_read_xxx_disassembler(). - - Rewrote exception processing and fixed 68020 stack frame - problems. - - FINALLY fixed the mull and divl instructions. - - Added 64-bit safe code fixes. - - Added 64-bit optimizations (these will only be ANSI compliant - under c9x, and so to use them you must turn on M68K_USE_64_BIT - in m68kconf.h). - -28-May-2000: Musashi 3.1 released - - Fixed bug in m68k_get_reg() that retrieved the wrong value for - the status register. - - Fixed register bug in movec. - - Fixed cpu type comparison problem that caused indexed - addressing modes to be incorrectly interpreted when in m68ec020 - mode. - - Added code to speed up busy waiting on some branch instructions. - - Fixed some bfxxx opcode bugs. - -05-Apr-2000: Musashi 3.0 released - - Major code overhaul. - - Rewrote code generator program and changed the format of - m68k_in.c. - - Added support for m68ec020. - - Removed timing from the opcode handlers. - - Added correct timing for m68000, m68010, and m68020. - Note: 68020 timing is the cache timing from the manual. - - Removed the m68k_peek_xxx() and m68k_poke_xxx() instructions and - replaced them with m68k_get_reg() and m68k_set_reg(). - - Added support for function codes. - - Revamped m68kconf.h to be easier to configure and more powerful. - - Added option to separate immediate and normal reads. - - Added support for (undocumented) m68000 instruction prefetch. - - Rewrote indexed addressing mode handling. - - Rewrote interrupt handling. - - Fixed a masking bug for m68k_get_reg() when requesting the PC. - - Moved the instruction table sorting routine to m68kmake.c so - that it is invoked at compile time rather than at runtime. - - Rewrote the exception handling routines to support different - stack frames (needed for m68020 emulation). - - Rewrote faster status register and condition code flag handling - functions / macros. - - Fixed function code handling to fetch from program space when - using pc-relative addressing. - - Fixed initial program counter and stack pointer fetching on - reset (loads from program space now). - - A lot of code cleanup. - - LOTS of bugfixes (especially in the m68020 code). - -13-May-1999: Musashi 2.2 released - - Added support for m68020. - - Lots of bugfixes. - -25-Mar-1999: Musashi 2.1 released - - Added support for m68010. - - Many bugfixes. - -17-Mar-1999: Musashi 2.0 released - - Major code overhaul. - - Replaced monolithic codebase with a code generator program. - - Added correct m68000 timing. - - Moved timing into the opcode handlers. - -06-Jan-1999: Musashi 1.0 released - -20-Dec-1998: Beta release of Musashi v0.5 that could run Rastan Saga under MAME - (barely). - -04-Dec-1998: Final prototype v0.4 - -20-Nov-1998: First prototype v0.1 - -11-Jun-1998: Early disassembler - -12-May-1998: First outline diff --git a/machine/musashi/m68k.h b/machine/musashi/m68k.h deleted file mode 100644 index d44d7e3..0000000 --- a/machine/musashi/m68k.h +++ /dev/null @@ -1,417 +0,0 @@ -/* ======================================================================== */ -/* ========================= LICENSING & COPYRIGHT ======================== */ -/* ======================================================================== */ -/* - * MUSASHI - * Version 3.32 - * - * A portable Motorola M680x0 processor emulation engine. - * Copyright Karl Stenerud. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifndef M68K__HEADER -#define M68K__HEADER - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef ARRAY_LENGTH -#define ARRAY_LENGTH(x) (sizeof(x) / sizeof(x[0])) -#endif - -#ifndef FALSE -#define FALSE 0 -#define TRUE 1 -#endif - -/* ======================================================================== */ -/* ============================= CONFIGURATION ============================ */ -/* ======================================================================== */ - -/* Import the configuration for this build */ -#ifdef MUSASHI_CNF -#include MUSASHI_CNF -#else -#include "m68kconf.h" -#endif - -/* ======================================================================== */ -/* ============================ GENERAL DEFINES =========================== */ - -/* ======================================================================== */ - -/* There are 7 levels of interrupt to the 68K. - * A transition from < 7 to 7 will cause a non-maskable interrupt (NMI). - */ -#define M68K_IRQ_NONE 0 -#define M68K_IRQ_1 1 -#define M68K_IRQ_2 2 -#define M68K_IRQ_3 3 -#define M68K_IRQ_4 4 -#define M68K_IRQ_5 5 -#define M68K_IRQ_6 6 -#define M68K_IRQ_7 7 - - -/* Special interrupt acknowledge values. - * Use these as special returns from the interrupt acknowledge callback - * (specified later in this header). - */ - -/* Causes an interrupt autovector (0x18 + interrupt level) to be taken. - * This happens in a real 68K if VPA or AVEC is asserted during an interrupt - * acknowledge cycle instead of DTACK. - */ -#define M68K_INT_ACK_AUTOVECTOR 0xffffffff - -/* Causes the spurious interrupt vector (0x18) to be taken - * This happens in a real 68K if BERR is asserted during the interrupt - * acknowledge cycle (i.e. no devices responded to the acknowledge). - */ -#define M68K_INT_ACK_SPURIOUS 0xfffffffe - - -/* CPU types for use in m68k_set_cpu_type() */ -enum -{ - M68K_CPU_TYPE_INVALID, - M68K_CPU_TYPE_68000, - M68K_CPU_TYPE_68010, - M68K_CPU_TYPE_68EC020, - M68K_CPU_TYPE_68020, - M68K_CPU_TYPE_68EC030, - M68K_CPU_TYPE_68030, - M68K_CPU_TYPE_68EC040, - M68K_CPU_TYPE_68LC040, - M68K_CPU_TYPE_68040, - M68K_CPU_TYPE_SCC68070 -}; - -/* Registers used by m68k_get_reg() and m68k_set_reg() */ -typedef enum -{ - /* Real registers */ - M68K_REG_D0, /* Data registers */ - M68K_REG_D1, - M68K_REG_D2, - M68K_REG_D3, - M68K_REG_D4, - M68K_REG_D5, - M68K_REG_D6, - M68K_REG_D7, - M68K_REG_A0, /* Address registers */ - M68K_REG_A1, - M68K_REG_A2, - M68K_REG_A3, - M68K_REG_A4, - M68K_REG_A5, - M68K_REG_A6, - M68K_REG_A7, - M68K_REG_PC, /* Program Counter */ - M68K_REG_SR, /* Status Register */ - M68K_REG_SP, /* The current Stack Pointer (located in A7) */ - M68K_REG_USP, /* User Stack Pointer */ - M68K_REG_ISP, /* Interrupt Stack Pointer */ - M68K_REG_MSP, /* Master Stack Pointer */ - M68K_REG_SFC, /* Source Function Code */ - M68K_REG_DFC, /* Destination Function Code */ - M68K_REG_VBR, /* Vector Base Register */ - M68K_REG_CACR, /* Cache Control Register */ - M68K_REG_CAAR, /* Cache Address Register */ - - /* Assumed registers */ - /* These are cheat registers which emulate the 1-longword prefetch - * present in the 68000 and 68010. - */ - M68K_REG_PREF_ADDR, /* Last prefetch address */ - M68K_REG_PREF_DATA, /* Last prefetch data */ - - /* Convenience registers */ - M68K_REG_PPC, /* Previous value in the program counter */ - M68K_REG_IR, /* Instruction register */ - M68K_REG_CPU_TYPE /* Type of CPU being run */ -} m68k_register_t; - -/* ======================================================================== */ -/* ====================== FUNCTIONS CALLED BY THE CPU ===================== */ -/* ======================================================================== */ - -/* You will have to implement these functions */ - -/* read/write functions called by the CPU to access memory. - * while values used are 32 bits, only the appropriate number - * of bits are relevant (i.e. in write_memory_8, only the lower 8 bits - * of value should be written to memory). - * - * NOTE: I have separated the immediate and PC-relative memory fetches - * from the other memory fetches because some systems require - * differentiation between PROGRAM and DATA fetches (usually - * for security setups such as encryption). - * This separation can either be achieved by setting - * M68K_SEPARATE_READS in m68kconf.h and defining - * the read functions, or by setting M68K_EMULATE_FC and - * making a function code callback function. - * Using the callback offers better emulation coverage - * because you can also monitor whether the CPU is in SYSTEM or - * USER mode, but it is also slower. - */ - -/* Read from anywhere */ -unsigned int m68k_read_memory_8(unsigned int address); -unsigned int m68k_read_memory_16(unsigned int address); -unsigned int m68k_read_memory_32(unsigned int address); - -/* Read data immediately following the PC */ -unsigned int m68k_read_immediate_16(unsigned int address); -unsigned int m68k_read_immediate_32(unsigned int address); - -/* Read data relative to the PC */ -unsigned int m68k_read_pcrelative_8(unsigned int address); -unsigned int m68k_read_pcrelative_16(unsigned int address); -unsigned int m68k_read_pcrelative_32(unsigned int address); - -/* Memory access for the disassembler */ -unsigned int m68k_read_disassembler_8 (unsigned int address); -unsigned int m68k_read_disassembler_16 (unsigned int address); -unsigned int m68k_read_disassembler_32 (unsigned int address); - -/* Write to anywhere */ -void m68k_write_memory_8(unsigned int address, unsigned int value); -void m68k_write_memory_16(unsigned int address, unsigned int value); -void m68k_write_memory_32(unsigned int address, unsigned int value); - -/* Special call to simulate undocumented 68k behavior when move.l with a - * predecrement destination mode is executed. - * To simulate real 68k behavior, first write the high word to - * [address+2], and then write the low word to [address]. - * - * Enable this functionality with M68K_SIMULATE_PD_WRITES in m68kconf.h. - */ -void m68k_write_memory_32_pd(unsigned int address, unsigned int value); - - - -/* ======================================================================== */ -/* ============================== CALLBACKS =============================== */ -/* ======================================================================== */ - -/* These functions allow you to set callbacks to the host when specific events - * occur. Note that you must enable the corresponding value in m68kconf.h - * in order for these to do anything useful. - * Note: I have defined default callbacks which are used if you have enabled - * the corresponding #define in m68kconf.h but either haven't assigned a - * callback or have assigned a callback of NULL. - */ - -/* Set the callback for an interrupt acknowledge. - * You must enable M68K_EMULATE_INT_ACK in m68kconf.h. - * The CPU will call the callback with the interrupt level being acknowledged. - * The host program must return either a vector from 0x02-0xff, or one of the - * special interrupt acknowledge values specified earlier in this header. - * If this is not implemented, the CPU will always assume an autovectored - * interrupt, and will automatically clear the interrupt request when it - * services the interrupt. - * Default behavior: return M68K_INT_ACK_AUTOVECTOR. - */ -void m68k_set_int_ack_callback(int (*callback)(int int_level)); - - -/* Set the callback for a breakpoint acknowledge (68010+). - * You must enable M68K_EMULATE_BKPT_ACK in m68kconf.h. - * The CPU will call the callback with whatever was in the data field of the - * BKPT instruction for 68020+, or 0 for 68010. - * Default behavior: do nothing. - */ -void m68k_set_bkpt_ack_callback(void (*callback)(unsigned int data)); - - -/* Set the callback for the RESET instruction. - * You must enable M68K_EMULATE_RESET in m68kconf.h. - * The CPU calls this callback every time it encounters a RESET instruction. - * Default behavior: do nothing. - */ -void m68k_set_reset_instr_callback(void (*callback)(void)); - - -/* Set the callback for informing of a large PC change. - * You must enable M68K_MONITOR_PC in m68kconf.h. - * The CPU calls this callback with the new PC value every time the PC changes - * by a large value (currently set for changes by longwords). - * Default behavior: do nothing. - */ -void m68k_set_pc_changed_callback(void (*callback)(unsigned int new_pc)); - -/* Set the callback for the TAS instruction. - * You must enable M68K_TAS_HAS_CALLBACK in m68kconf.h. - * The CPU calls this callback every time it encounters a TAS instruction. - * Default behavior: return 1, allow writeback. - */ -void m68k_set_tas_instr_callback(int (*callback)(void)); - -/* Set the callback for illegal instructions. - * You must enable M68K_ILLG_HAS_CALLBACK in m68kconf.h. - * The CPU calls this callback every time it encounters an illegal instruction - * which must return 1 if it handles the instruction normally or 0 if it's really an illegal instruction. - * Default behavior: return 0, exception will occur. - */ -void m68k_set_illg_instr_callback(int (*callback)(int)); - -/* Set the callback for CPU function code changes. - * You must enable M68K_EMULATE_FC in m68kconf.h. - * The CPU calls this callback with the function code before every memory - * access to set the CPU's function code according to what kind of memory - * access it is (supervisor/user, program/data and such). - * Default behavior: do nothing. - */ -void m68k_set_fc_callback(void (*callback)(unsigned int new_fc)); - - -/* Set a callback for the instruction cycle of the CPU. - * You must enable M68K_INSTRUCTION_HOOK in m68kconf.h. - * The CPU calls this callback just before fetching the opcode in the - * instruction cycle. - * Default behavior: do nothing. - */ -void m68k_set_instr_hook_callback(void (*callback)(unsigned int pc)); - -/* CV: operation done after aline callback */ -#define M68K_ALINE_NONE 0 -#define M68K_ALINE_EXCEPT 1 -#define M68K_ALINE_RTS 2 - -/* CV: call callback with (opcode, pc) */ -void m68k_set_aline_hook_callback(int (*callback)(unsigned int, unsigned int)); - -/* ======================================================================== */ -/* ====================== FUNCTIONS TO ACCESS THE CPU ===================== */ -/* ======================================================================== */ - -/* Use this function to set the CPU type you want to emulate. - * Currently supported types are: M68K_CPU_TYPE_68000, M68K_CPU_TYPE_68010, - * M68K_CPU_TYPE_EC020, and M68K_CPU_TYPE_68020. - */ -void m68k_set_cpu_type(unsigned int cpu_type); - -/* Do whatever initialisations the core requires. Should be called - * at least once at init time. - */ -void m68k_init(void); - -/* Pulse the RESET pin on the CPU. - * You *MUST* reset the CPU at least once to initialize the emulation - * Note: If you didn't call m68k_set_cpu_type() before resetting - * the CPU for the first time, the CPU will be set to - * M68K_CPU_TYPE_68000. - */ -void m68k_pulse_reset(void); - -/* execute num_cycles worth of instructions. returns number of cycles used */ -int m68k_execute(int num_cycles); - -/* These functions let you read/write/modify the number of cycles left to run - * while m68k_execute() is running. - * These are useful if the 68k accesses a memory-mapped port on another device - * that requires immediate processing by another CPU. - */ -int m68k_cycles_run(void); /* Number of cycles run so far */ -int m68k_cycles_remaining(void); /* Number of cycles left */ -void m68k_modify_timeslice(int cycles); /* Modify cycles left */ -void m68k_end_timeslice(void); /* End timeslice now */ - -/* Set the IPL0-IPL2 pins on the CPU (IRQ). - * A transition from < 7 to 7 will cause a non-maskable interrupt (NMI). - * Setting IRQ to 0 will clear an interrupt request. - */ -void m68k_set_irq(unsigned int int_level); - -/* Set the virtual irq lines, where the highest level - * active line is automatically selected. If you use this function, - * do not use m68k_set_irq. - */ -void m68k_set_virq(unsigned int level, unsigned int active); -unsigned int m68k_get_virq(unsigned int level); - -/* Halt the CPU as if you pulsed the HALT pin. */ -void m68k_pulse_halt(void); - - -/* Trigger a bus error exception */ -void m68k_pulse_bus_error(void); - - -/* Context switching to allow multiple CPUs */ - -/* Get the size of the cpu context in bytes */ -unsigned int m68k_context_size(void); - -/* Get a cpu context */ -unsigned int m68k_get_context(void* dst); - -/* set the current cpu context */ -void m68k_set_context(void* dst); - -/* Register the CPU state information */ -void m68k_state_register(const char *type, int index); - - -/* Peek at the internals of a CPU context. This can either be a context - * retrieved using m68k_get_context() or the currently running context. - * If context is NULL, the currently running CPU context will be used. - */ -unsigned int m68k_get_reg(void* context, m68k_register_t reg); - -/* Poke values into the internals of the currently running CPU context */ -void m68k_set_reg(m68k_register_t reg, unsigned int value); - -/* Check if an instruction is valid for the specified CPU type */ -unsigned int m68k_is_valid_instruction(unsigned int instruction, unsigned int cpu_type); - -/* Disassemble 1 instruction using the epecified CPU type at pc. Stores - * disassembly in str_buff and returns the size of the instruction in bytes. - */ -unsigned int m68k_disassemble(char* str_buff, unsigned int pc, unsigned int cpu_type); - -/* Same as above but accepts raw opcode data directly rather than fetching - * via the read/write interfaces. - */ -unsigned int m68k_disassemble_raw(char* str_buff, unsigned int pc, const unsigned char* opdata, const unsigned char* argdata, unsigned int cpu_type); - - -/* ======================================================================== */ -/* ============================== MAME STUFF ============================== */ -/* ======================================================================== */ - -#if M68K_COMPILE_FOR_MAME == OPT_ON -#include "m68kmame.h" -#endif /* M68K_COMPILE_FOR_MAME */ - - -/* ======================================================================== */ -/* ============================== END OF FILE ============================= */ -/* ======================================================================== */ - -#ifdef __cplusplus -} -#endif - - -#endif /* M68K__HEADER */ diff --git a/machine/musashi/m68k_in.c b/machine/musashi/m68k_in.c deleted file mode 100644 index e5811b3..0000000 --- a/machine/musashi/m68k_in.c +++ /dev/null @@ -1,10653 +0,0 @@ -/* -must fix: - callm - chk -*/ -/* ======================================================================== */ -/* ========================= LICENSING & COPYRIGHT ======================== */ -/* ======================================================================== */ -/* - * MUSASHI - * Version 3.32 - * - * A portable Motorola M680x0 processor emulation engine. - * Copyright Karl Stenerud. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -/* Special thanks to Bart Trzynadlowski for his insight into the - * undocumented features of this chip: - * - * http://dynarec.com/~bart/files/68knotes.txt - */ - - -/* Input file for m68kmake - * ----------------------- - * - * All sections begin with 80 X's in a row followed by an end-of-line - * sequence. - * After this, m68kmake will expect to find one of the following section - * identifiers: - * M68KMAKE_PROTOTYPE_HEADER - header for opcode handler prototypes - * M68KMAKE_PROTOTYPE_FOOTER - footer for opcode handler prototypes - * M68KMAKE_TABLE_HEADER - header for opcode handler jumptable - * M68KMAKE_TABLE_FOOTER - footer for opcode handler jumptable - * M68KMAKE_TABLE_BODY - the table itself - * M68KMAKE_OPCODE_HANDLER_HEADER - header for opcode handler implementation - * M68KMAKE_OPCODE_HANDLER_FOOTER - footer for opcode handler implementation - * M68KMAKE_OPCODE_HANDLER_BODY - body section for opcode handler implementation - * - * NOTE: M68KMAKE_OPCODE_HANDLER_BODY must be last in the file and - * M68KMAKE_TABLE_BODY must be second last in the file. - * - * The M68KMAKE_OPHANDLER_BODY section contains the opcode handler - * primitives themselves. Each opcode handler begins with: - * M68KMAKE_OP(A, B, C, D) - * - * where A is the opcode handler name, B is the size of the operation, - * C denotes any special processing mode, and D denotes a specific - * addressing mode. - * For C and D where nothing is specified, use "." - * - * Example: - * M68KMAKE_OP(abcd, 8, rr, .) abcd, size 8, register to register, default EA - * M68KMAKE_OP(abcd, 8, mm, ax7) abcd, size 8, memory to memory, register X is A7 - * M68KMAKE_OP(tst, 16, ., pcix) tst, size 16, PCIX addressing - * - * All opcode handler primitives end with a closing curly brace "}" at column 1 - * - * NOTE: Do not place a M68KMAKE_OP() directive inside the opcode handler, - * and do not put a closing curly brace at column 1 unless it is - * marking the end of the handler! - * - * Inside the handler, m68kmake will recognize M68KMAKE_GET_OPER_xx_xx, - * M68KMAKE_GET_EA_xx_xx, and M68KMAKE_CC directives, and create multiple - * opcode handlers to handle variations in the opcode handler. - * Note: M68KMAKE_CC will only be interpreted in condition code opcodes. - * As well, M68KMAKE_GET_EA_xx_xx and M68KMAKE_GET_OPER_xx_xx will only - * be interpreted on instructions where the corresponding table entry - * specifies multiple effective addressing modes. - * Example: - * clr 32 . . 0100001010...... A+-DXWL... U U U 12 6 4 - * - * This table entry says that the clr.l opcde has 7 variations (A+-DXWL). - * It is run in user or supervisor mode for all CPUs, and uses 12 cycles for - * 68000, 6 cycles for 68010, and 4 cycles for 68020. - */ - -XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -M68KMAKE_PROTOTYPE_HEADER - -#ifndef M68KOPS__HEADER -#define M68KOPS__HEADER - -/* ======================================================================== */ -/* ============================ OPCODE HANDLERS =========================== */ -/* ======================================================================== */ - - - -XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -M68KMAKE_PROTOTYPE_FOOTER - - -/* Build the opcode handler table */ -void m68ki_build_opcode_table(void); - -extern void (*m68ki_instruction_jump_table[0x10000])(void); /* opcode handler jump table */ -extern unsigned char m68ki_cycles[][0x10000]; - - -/* ======================================================================== */ -/* ============================== END OF FILE ============================= */ -/* ======================================================================== */ - -#endif /* M68KOPS__HEADER */ - - - -XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -M68KMAKE_TABLE_HEADER - -/* ======================================================================== */ -/* ========================= OPCODE TABLE BUILDER ========================= */ -/* ======================================================================== */ - -#include -#include "m68kops.h" - -#define NUM_CPU_TYPES 5 - -void (*m68ki_instruction_jump_table[0x10000])(void); /* opcode handler jump table */ -unsigned char m68ki_cycles[NUM_CPU_TYPES][0x10000]; /* Cycles used by CPU type */ - -/* This is used to generate the opcode handler jump table */ -typedef struct -{ - void (*opcode_handler)(void); /* handler function */ - unsigned int mask; /* mask on opcode */ - unsigned int match; /* what to match after masking */ - unsigned char cycles[NUM_CPU_TYPES]; /* cycles each cpu type takes */ -} opcode_handler_struct; - - -/* Opcode handler table */ -static const opcode_handler_struct m68k_opcode_handler_table[] = -{ -/* function mask match 000 010 020 040 */ - - - -XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -M68KMAKE_TABLE_FOOTER - - {0, 0, 0, {0, 0, 0, 0, 0}} -}; - - -/* Build the opcode handler jump table */ -void m68ki_build_opcode_table(void) -{ - const opcode_handler_struct *ostruct; - int cycle_cost; - int instr; - int i; - int j; - int k; - - for(i = 0; i < 0x10000; i++) - { - /* default to illegal */ - m68ki_instruction_jump_table[i] = m68k_op_illegal; - for(k=0;kmask != 0xff00) - { - for(i = 0;i < 0x10000;i++) - { - if((i & ostruct->mask) == ostruct->match) - { - m68ki_instruction_jump_table[i] = ostruct->opcode_handler; - for(k=0;kcycles[k]; - } - } - ostruct++; - } - while(ostruct->mask == 0xff00) - { - for(i = 0;i <= 0xff;i++) - { - m68ki_instruction_jump_table[ostruct->match | i] = ostruct->opcode_handler; - for(k=0;kmatch | i] = ostruct->cycles[k]; - } - ostruct++; - } - while(ostruct->mask == 0xf1f8) - { - for(i = 0;i < 8;i++) - { - for(j = 0;j < 8;j++) - { - instr = ostruct->match | (i << 9) | j; - m68ki_instruction_jump_table[instr] = ostruct->opcode_handler; - for(k=0;kcycles[k]; - // For all shift operations with known shift distance (encoded in instruction word) - if((instr & 0xf000) == 0xe000 && (!(instr & 0x20))) - { - // On the 68000 and 68010 shift distance affect execution time. - // Add the cycle cost of shifting; 2 times the shift distance - cycle_cost = ((((i-1)&7)+1)<<1); - m68ki_cycles[0][instr] += cycle_cost; - m68ki_cycles[1][instr] += cycle_cost; - // On the 68020 shift distance does not affect execution time - m68ki_cycles[2][instr] += 0; - } - } - } - ostruct++; - } - while(ostruct->mask == 0xfff0) - { - for(i = 0;i <= 0x0f;i++) - { - m68ki_instruction_jump_table[ostruct->match | i] = ostruct->opcode_handler; - for(k=0;kmatch | i] = ostruct->cycles[k]; - } - ostruct++; - } - while(ostruct->mask == 0xf1ff) - { - for(i = 0;i <= 0x07;i++) - { - m68ki_instruction_jump_table[ostruct->match | (i << 9)] = ostruct->opcode_handler; - for(k=0;kmatch | (i << 9)] = ostruct->cycles[k]; - } - ostruct++; - } - while(ostruct->mask == 0xfff8) - { - for(i = 0;i <= 0x07;i++) - { - m68ki_instruction_jump_table[ostruct->match | i] = ostruct->opcode_handler; - for(k=0;kmatch | i] = ostruct->cycles[k]; - } - ostruct++; - } - while(ostruct->mask == 0xffff) - { - m68ki_instruction_jump_table[ostruct->match] = ostruct->opcode_handler; - for(k=0;kmatch] = ostruct->cycles[k]; - ostruct++; - } -} - - -/* ======================================================================== */ -/* ============================== END OF FILE ============================= */ -/* ======================================================================== */ - - - -XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -M68KMAKE_OPCODE_HANDLER_HEADER - -#include -#include "m68kcpu.h" -extern void m68040_fpu_op0(void); -extern void m68040_fpu_op1(void); -extern void m68881_mmu_ops(void); - -/* ======================================================================== */ -/* ========================= INSTRUCTION HANDLERS ========================= */ -/* ======================================================================== */ - - - -XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -M68KMAKE_OPCODE_HANDLER_FOOTER - -/* ======================================================================== */ -/* ============================== END OF FILE ============================= */ -/* ======================================================================== */ - - - -XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -M68KMAKE_TABLE_BODY - -The following table is arranged as follows: - -name: Opcode mnemonic - -size: Operation size - -spec proc: Special processing mode: - .: normal - s: static operand - r: register operand - rr: register to register - mm: memory to memory - er: effective address to register - re: register to effective address - dd: data register to data register - da: data register to address register - aa: address register to address register - cr: control register to register - rc: register to control register - toc: to condition code register - tos: to status register - tou: to user stack pointer - frc: from condition code register - frs: from status register - fru: from user stack pointer - * for move.x, the special processing mode is a specific - destination effective addressing mode. - -spec ea: Specific effective addressing mode: - .: normal - i: immediate - d: data register - a: address register - ai: address register indirect - pi: address register indirect with postincrement - pd: address register indirect with predecrement - di: address register indirect with displacement - ix: address register indirect with index - aw: absolute word address - al: absolute long address - pcdi: program counter relative with displacement - pcix: program counter relative with index - a7: register specified in instruction is A7 - ax7: register field X of instruction is A7 - ay7: register field Y of instruction is A7 - axy7: register fields X and Y of instruction are A7 - -bit pattern: Pattern to recognize this opcode. "." means don't care. - -allowed ea: List of allowed addressing modes: - .: not present - A: address register indirect - +: ARI (address register indirect) with postincrement - -: ARI with predecrement - D: ARI with displacement - X: ARI with index - W: absolute word address - L: absolute long address - d: program counter indirect with displacement - x: program counter indirect with index - I: immediate -mode: CPU operating mode for each cpu type. U = user or supervisor, - S = supervisor only, "." = opcode not present. - -cpu cycles: Base number of cycles required to execute this opcode on the - specified CPU type. - Use "." if CPU does not have this opcode. - - - - spec spec allowed ea mode cpu cycles -name size proc ea bit pattern A+-DXWLdxI 0 1 2 3 4 000 010 020 030 040 comments -====== ==== ==== ==== ================ ========== = = = = = === === === === === ============= -M68KMAKE_TABLE_START -1010 0 . . 1010............ .......... U U U U U 4 4 4 4 4 -1111 0 . . 1111............ .......... U U U U U 4 4 4 4 4 -040fpu0 32 . . 11110010........ .......... . . . . U . . . . 0 -040fpu1 32 . . 11110011........ .......... . . . . U . . . . 0 -abcd 8 rr . 1100...100000... .......... U U U U U 6 6 4 4 4 -abcd 8 mm ax7 1100111100001... .......... U U U U U 18 18 16 16 16 -abcd 8 mm ay7 1100...100001111 .......... U U U U U 18 18 16 16 16 -abcd 8 mm axy7 1100111100001111 .......... U U U U U 18 18 16 16 16 -abcd 8 mm . 1100...100001... .......... U U U U U 18 18 16 16 16 -add 8 er d 1101...000000... .......... U U U U U 4 4 2 2 2 -add 8 er . 1101...000...... A+-DXWLdxI U U U U U 4 4 2 2 2 -add 16 er d 1101...001000... .......... U U U U U 4 4 2 2 2 -add 16 er a 1101...001001... .......... U U U U U 4 4 2 2 2 -add 16 er . 1101...001...... A+-DXWLdxI U U U U U 4 4 2 2 2 -add 32 er d 1101...010000... .......... U U U U U 6 6 2 2 2 -add 32 er a 1101...010001... .......... U U U U U 6 6 2 2 2 -add 32 er . 1101...010...... A+-DXWLdxI U U U U U 6 6 2 2 2 -add 8 re . 1101...100...... A+-DXWL... U U U U U 8 8 4 4 4 -add 16 re . 1101...101...... A+-DXWL... U U U U U 8 8 4 4 4 -add 32 re . 1101...110...... A+-DXWL... U U U U U 12 12 4 4 4 -adda 16 . d 1101...011000... .......... U U U U U 8 8 2 2 2 -adda 16 . a 1101...011001... .......... U U U U U 8 8 2 2 2 -adda 16 . . 1101...011...... A+-DXWLdxI U U U U U 8 8 2 2 2 -adda 32 . d 1101...111000... .......... U U U U U 6 6 2 2 2 -adda 32 . a 1101...111001... .......... U U U U U 6 6 2 2 2 -adda 32 . . 1101...111...... A+-DXWLdxI U U U U U 6 6 2 2 2 -addi 8 . d 0000011000000... .......... U U U U U 8 8 2 2 2 -addi 8 . . 0000011000...... A+-DXWL... U U U U U 12 12 4 4 4 -addi 16 . d 0000011001000... .......... U U U U U 8 8 2 2 2 -addi 16 . . 0000011001...... A+-DXWL... U U U U U 12 12 4 4 4 -addi 32 . d 0000011010000... .......... U U U U U 16 14 2 2 2 -addi 32 . . 0000011010...... A+-DXWL... U U U U U 20 20 4 4 4 -addq 8 . d 0101...000000... .......... U U U U U 4 4 2 2 2 -addq 8 . . 0101...000...... A+-DXWL... U U U U U 8 8 4 4 4 -addq 16 . d 0101...001000... .......... U U U U U 4 4 2 2 2 -addq 16 . a 0101...001001... .......... U U U U U 4 4 2 2 2 -addq 16 . . 0101...001...... A+-DXWL... U U U U U 8 8 4 4 4 -addq 32 . d 0101...010000... .......... U U U U U 8 8 2 2 2 -addq 32 . a 0101...010001... .......... U U U U U 8 8 2 2 2 -addq 32 . . 0101...010...... A+-DXWL... U U U U U 12 12 4 4 4 -addx 8 rr . 1101...100000... .......... U U U U U 4 4 2 2 2 -addx 16 rr . 1101...101000... .......... U U U U U 4 4 2 2 2 -addx 32 rr . 1101...110000... .......... U U U U U 8 6 2 2 2 -addx 8 mm ax7 1101111100001... .......... U U U U U 18 18 12 12 12 -addx 8 mm ay7 1101...100001111 .......... U U U U U 18 18 12 12 12 -addx 8 mm axy7 1101111100001111 .......... U U U U U 18 18 12 12 12 -addx 8 mm . 1101...100001... .......... U U U U U 18 18 12 12 12 -addx 16 mm . 1101...101001... .......... U U U U U 18 18 12 12 12 -addx 32 mm . 1101...110001... .......... U U U U U 30 30 12 12 12 -and 8 er d 1100...000000... .......... U U U U U 4 4 2 2 2 -and 8 er . 1100...000...... A+-DXWLdxI U U U U U 4 4 2 2 2 -and 16 er d 1100...001000... .......... U U U U U 4 4 2 2 2 -and 16 er . 1100...001...... A+-DXWLdxI U U U U U 4 4 2 2 2 -and 32 er d 1100...010000... .......... U U U U U 6 6 2 2 2 -and 32 er . 1100...010...... A+-DXWLdxI U U U U U 6 6 2 2 2 -and 8 re . 1100...100...... A+-DXWL... U U U U U 8 8 4 4 4 -and 16 re . 1100...101...... A+-DXWL... U U U U U 8 8 4 4 4 -and 32 re . 1100...110...... A+-DXWL... U U U U U 12 12 4 4 4 -andi 16 toc . 0000001000111100 .......... U U U U U 20 16 12 12 12 -andi 16 tos . 0000001001111100 .......... S S S S S 20 16 12 12 12 -andi 8 . d 0000001000000... .......... U U U U U 8 8 2 2 2 -andi 8 . . 0000001000...... A+-DXWL... U U U U U 12 12 4 4 4 -andi 16 . d 0000001001000... .......... U U U U U 8 8 2 2 2 -andi 16 . . 0000001001...... A+-DXWL... U U U U U 12 12 4 4 4 -andi 32 . d 0000001010000... .......... U U U U U 14 14 2 2 2 -andi 32 . . 0000001010...... A+-DXWL... U U U U U 20 20 4 4 4 -asr 8 s . 1110...000000... .......... U U U U U 6 6 6 6 6 -asr 16 s . 1110...001000... .......... U U U U U 6 6 6 6 6 -asr 32 s . 1110...010000... .......... U U U U U 8 8 6 6 6 -asr 8 r . 1110...000100... .......... U U U U U 6 6 6 6 6 -asr 16 r . 1110...001100... .......... U U U U U 6 6 6 6 6 -asr 32 r . 1110...010100... .......... U U U U U 8 8 6 6 6 -asr 16 . . 1110000011...... A+-DXWL... U U U U U 8 8 5 5 5 -asl 8 s . 1110...100000... .......... U U U U U 6 6 8 8 8 -asl 16 s . 1110...101000... .......... U U U U U 6 6 8 8 8 -asl 32 s . 1110...110000... .......... U U U U U 8 8 8 8 8 -asl 8 r . 1110...100100... .......... U U U U U 6 6 8 8 8 -asl 16 r . 1110...101100... .......... U U U U U 6 6 8 8 8 -asl 32 r . 1110...110100... .......... U U U U U 8 8 8 8 8 -asl 16 . . 1110000111...... A+-DXWL... U U U U U 8 8 6 6 6 -bcc 8 . . 0110............ .......... U U U U U 10 10 6 6 6 -bcc 16 . . 0110....00000000 .......... U U U U U 10 10 6 6 6 -bcc 32 . . 0110....11111111 .......... U U U U U 10 10 6 6 6 -bchg 8 r . 0000...101...... A+-DXWL... U U U U U 8 8 4 4 4 -bchg 32 r d 0000...101000... .......... U U U U U 8 8 4 4 4 -bchg 8 s . 0000100001...... A+-DXWL... U U U U U 12 12 4 4 4 -bchg 32 s d 0000100001000... .......... U U U U U 12 12 4 4 4 -bclr 8 r . 0000...110...... A+-DXWL... U U U U U 8 10 4 4 4 -bclr 32 r d 0000...110000... .......... U U U U U 10 10 4 4 4 -bclr 8 s . 0000100010...... A+-DXWL... U U U U U 12 12 4 4 4 -bclr 32 s d 0000100010000... .......... U U U U U 14 14 4 4 4 -bfchg 32 . d 1110101011000... .......... . . U U U . . 12 12 12 timing not quite correct -bfchg 32 . . 1110101011...... A..DXWL... . . U U U . . 20 20 20 -bfclr 32 . d 1110110011000... .......... . . U U U . . 12 12 12 -bfclr 32 . . 1110110011...... A..DXWL... . . U U U . . 20 20 20 -bfexts 32 . d 1110101111000... .......... . . U U U . . 8 8 8 -bfexts 32 . . 1110101111...... A..DXWLdx. . . U U U . . 15 15 15 -bfextu 32 . d 1110100111000... .......... . . U U U . . 8 8 8 -bfextu 32 . . 1110100111...... A..DXWLdx. . . U U U . . 15 15 15 -bfffo 32 . d 1110110111000... .......... . . U U U . . 18 18 18 -bfffo 32 . . 1110110111...... A..DXWLdx. . . U U U . . 28 28 28 -bfins 32 . d 1110111111000... .......... . . U U U . . 10 10 10 -bfins 32 . . 1110111111...... A..DXWL... . . U U U . . 17 17 17 -bfset 32 . d 1110111011000... .......... . . U U U . . 12 12 12 -bfset 32 . . 1110111011...... A..DXWL... . . U U U . . 20 20 20 -bftst 32 . d 1110100011000... .......... . . U U U . . 6 6 6 -bftst 32 . . 1110100011...... A..DXWLdx. . . U U U . . 13 13 13 -bkpt 0 . . 0100100001001... .......... . U U U U . 10 10 10 10 -bra 8 . . 01100000........ .......... U U U U U 10 10 10 10 10 -bra 16 . . 0110000000000000 .......... U U U U U 10 10 10 10 10 -bra 32 . . 0110000011111111 .......... U U U U U 10 10 10 10 10 -bset 32 r d 0000...111000... .......... U U U U U 8 8 4 4 4 -bset 8 r . 0000...111...... A+-DXWL... U U U U U 8 8 4 4 4 -bset 8 s . 0000100011...... A+-DXWL... U U U U U 12 12 4 4 4 -bset 32 s d 0000100011000... .......... U U U U U 12 12 4 4 4 -bsr 8 . . 01100001........ .......... U U U U U 18 18 7 7 7 -bsr 16 . . 0110000100000000 .......... U U U U U 18 18 7 7 7 -bsr 32 . . 0110000111111111 .......... U U U U U 18 18 7 7 7 -btst 8 r . 0000...100...... A+-DXWLdxI U U U U U 4 4 4 4 4 -btst 32 r d 0000...100000... .......... U U U U U 6 6 4 4 4 -btst 8 s . 0000100000...... A+-DXWLdx. U U U U U 8 8 4 4 4 -btst 32 s d 0000100000000... .......... U U U U U 10 10 4 4 4 -callm 32 . . 0000011011...... A..DXWLdx. . . U U U . . 60 60 60 not properly emulated -cas 8 . . 0000101011...... A+-DXWL... . . U U U . . 12 12 12 -cas 16 . . 0000110011...... A+-DXWL... . . U U U . . 12 12 12 -cas 32 . . 0000111011...... A+-DXWL... . . U U U . . 12 12 12 -cas2 16 . . 0000110011111100 .......... . . U U U . . 12 12 12 -cas2 32 . . 0000111011111100 .......... . . U U U . . 12 12 12 -chk 16 . d 0100...110000... .......... U U U U U 10 8 8 8 8 -chk 16 . . 0100...110...... A+-DXWLdxI U U U U U 10 8 8 8 8 -chk 32 . d 0100...100000... .......... . . U U U . . 8 8 8 -chk 32 . . 0100...100...... A+-DXWLdxI . . U U U . . 8 8 8 -chk2cmp2 8 . pcdi 0000000011111010 .......... . . U U U . . 23 23 23 -chk2cmp2 8 . pcix 0000000011111011 .......... . . U U U . . 23 23 23 -chk2cmp2 8 . . 0000000011...... A..DXWL... . . U U U . . 18 18 18 -chk2cmp2 16 . pcdi 0000001011111010 .......... . . U U U . . 23 23 23 -chk2cmp2 16 . pcix 0000001011111011 .......... . . U U U . . 23 23 23 -chk2cmp2 16 . . 0000001011...... A..DXWL... . . U U U . . 18 18 18 -chk2cmp2 32 . pcdi 0000010011111010 .......... . . U U U . . 23 23 23 -chk2cmp2 32 . pcix 0000010011111011 .......... . . U U U . . 23 23 23 -chk2cmp2 32 . . 0000010011...... A..DXWL... . . U U U . . 18 18 18 -clr 8 . d 0100001000000... .......... U U U U U 4 4 2 2 2 -clr 8 . . 0100001000...... A+-DXWL... U U U U U 8 4 4 4 4 -clr 16 . d 0100001001000... .......... U U U U U 4 4 2 2 2 -clr 16 . . 0100001001...... A+-DXWL... U U U U U 8 4 4 4 4 -clr 32 . d 0100001010000... .......... U U U U U 6 6 2 2 2 -clr 32 . . 0100001010...... A+-DXWL... U U U U U 12 6 4 4 4 -cmp 8 . d 1011...000000... .......... U U U U U 4 4 2 2 2 -cmp 8 . . 1011...000...... A+-DXWLdxI U U U U U 4 4 2 2 2 -cmp 16 . d 1011...001000... .......... U U U U U 4 4 2 2 2 -cmp 16 . a 1011...001001... .......... U U U U U 4 4 2 2 2 -cmp 16 . . 1011...001...... A+-DXWLdxI U U U U U 4 4 2 2 2 -cmp 32 . d 1011...010000... .......... U U U U U 6 6 2 2 2 -cmp 32 . a 1011...010001... .......... U U U U U 6 6 2 2 2 -cmp 32 . . 1011...010...... A+-DXWLdxI U U U U U 6 6 2 2 2 -cmpa 16 . d 1011...011000... .......... U U U U U 6 6 4 4 4 -cmpa 16 . a 1011...011001... .......... U U U U U 6 6 4 4 4 -cmpa 16 . . 1011...011...... A+-DXWLdxI U U U U U 6 6 4 4 4 -cmpa 32 . d 1011...111000... .......... U U U U U 6 6 4 4 4 -cmpa 32 . a 1011...111001... .......... U U U U U 6 6 4 4 4 -cmpa 32 . . 1011...111...... A+-DXWLdxI U U U U U 6 6 4 4 4 -cmpi 8 . d 0000110000000... .......... U U U U U 8 8 2 2 2 -cmpi 8 . . 0000110000...... A+-DXWL... U U U U U 8 8 2 2 2 -cmpi 8 . pcdi 0000110000111010 .......... . . U U U . . 7 7 7 -cmpi 8 . pcix 0000110000111011 .......... . . U U U . . 9 9 9 -cmpi 16 . d 0000110001000... .......... U U U U U 8 8 2 2 2 -cmpi 16 . . 0000110001...... A+-DXWL... U U U U U 8 8 2 2 2 -cmpi 16 . pcdi 0000110001111010 .......... . . U U U . . 7 7 7 -cmpi 16 . pcix 0000110001111011 .......... . . U U U . . 9 9 9 -cmpi 32 . d 0000110010000... .......... U U U U U 14 12 2 2 2 -cmpi 32 . . 0000110010...... A+-DXWL... U U U U U 12 12 2 2 2 -cmpi 32 . pcdi 0000110010111010 .......... . . U U U . . 7 7 7 -cmpi 32 . pcix 0000110010111011 .......... . . U U U . . 9 9 9 -cmpm 8 . ax7 1011111100001... .......... U U U U U 12 12 9 9 9 -cmpm 8 . ay7 1011...100001111 .......... U U U U U 12 12 9 9 9 -cmpm 8 . axy7 1011111100001111 .......... U U U U U 12 12 9 9 9 -cmpm 8 . . 1011...100001... .......... U U U U U 12 12 9 9 9 -cmpm 16 . . 1011...101001... .......... U U U U U 12 12 9 9 9 -cmpm 32 . . 1011...110001... .......... U U U U U 20 20 9 9 9 -cpbcc 32 . . 1111...01....... .......... . . U U . . . 4 4 . unemulated -cpdbcc 32 . . 1111...001001... .......... . . U U . . . 4 4 . unemulated -cpgen 32 . . 1111...000...... .......... . . U U . . . 4 4 . unemulated -cpscc 32 . . 1111...001...... .......... . . U U . . . 4 4 . unemulated -cptrapcc 32 . . 1111...001111... .......... . . U U . . . 4 4 . unemulated -dbt 16 . . 0101000011001... .......... U U U U U 12 12 6 6 6 -dbf 16 . . 0101000111001... .......... U U U U U 12 12 6 6 6 -dbcc 16 . . 0101....11001... .......... U U U U U 12 12 6 6 6 -divs 16 . d 1000...111000... .......... U U U U U 158 122 56 56 56 -divs 16 . . 1000...111...... A+-DXWLdxI U U U U U 158 122 56 56 56 -divu 16 . d 1000...011000... .......... U U U U U 140 108 44 44 44 -divu 16 . . 1000...011...... A+-DXWLdxI U U U U U 140 108 44 44 44 -divl 32 . d 0100110001000... .......... . . U U U . . 84 84 84 -divl 32 . . 0100110001...... A+-DXWLdxI . . U U U . . 84 84 84 -eor 8 . d 1011...100000... .......... U U U U U 4 4 2 2 2 -eor 8 . . 1011...100...... A+-DXWL... U U U U U 8 8 4 4 4 -eor 16 . d 1011...101000... .......... U U U U U 4 4 2 2 2 -eor 16 . . 1011...101...... A+-DXWL... U U U U U 8 8 4 4 4 -eor 32 . d 1011...110000... .......... U U U U U 8 6 2 2 2 -eor 32 . . 1011...110...... A+-DXWL... U U U U U 12 12 4 4 4 -eori 16 toc . 0000101000111100 .......... U U U U U 20 16 12 12 12 -eori 16 tos . 0000101001111100 .......... S S S S S 20 16 12 12 12 -eori 8 . d 0000101000000... .......... U U U U U 8 8 2 2 2 -eori 8 . . 0000101000...... A+-DXWL... U U U U U 12 12 4 4 4 -eori 16 . d 0000101001000... .......... U U U U U 8 8 2 2 2 -eori 16 . . 0000101001...... A+-DXWL... U U U U U 12 12 4 4 4 -eori 32 . d 0000101010000... .......... U U U U U 16 14 2 2 2 -eori 32 . . 0000101010...... A+-DXWL... U U U U U 20 20 4 4 4 -exg 32 dd . 1100...101000... .......... U U U U U 6 6 2 2 2 -exg 32 aa . 1100...101001... .......... U U U U U 6 6 2 2 2 -exg 32 da . 1100...110001... .......... U U U U U 6 6 2 2 2 -ext 16 . . 0100100010000... .......... U U U U U 4 4 4 4 4 -ext 32 . . 0100100011000... .......... U U U U U 4 4 4 4 4 -extb 32 . . 0100100111000... .......... . . U U U . . 4 4 4 -illegal 0 . . 0100101011111100 .......... U U U U U 4 4 4 4 4 -jmp 32 . . 0100111011...... A..DXWLdx. U U U U U 4 4 0 0 0 -jsr 32 . . 0100111010...... A..DXWLdx. U U U U U 12 12 0 0 0 -lea 32 . . 0100...111...... A..DXWLdx. U U U U U 0 0 2 2 2 -link 16 . a7 0100111001010111 .......... U U U U U 16 16 5 5 5 -link 16 . . 0100111001010... .......... U U U U U 16 16 5 5 5 -link 32 . a7 0100100000001111 .......... . . U U U . . 6 6 6 -link 32 . . 0100100000001... .......... . . U U U . . 6 6 6 -lsr 8 s . 1110...000001... .......... U U U U U 6 6 4 4 4 -lsr 16 s . 1110...001001... .......... U U U U U 6 6 4 4 4 -lsr 32 s . 1110...010001... .......... U U U U U 8 8 4 4 4 -lsr 8 r . 1110...000101... .......... U U U U U 6 6 6 6 6 -lsr 16 r . 1110...001101... .......... U U U U U 6 6 6 6 6 -lsr 32 r . 1110...010101... .......... U U U U U 8 8 6 6 6 -lsr 16 . . 1110001011...... A+-DXWL... U U U U U 8 8 5 5 5 -lsl 8 s . 1110...100001... .......... U U U U U 6 6 4 4 4 -lsl 16 s . 1110...101001... .......... U U U U U 6 6 4 4 4 -lsl 32 s . 1110...110001... .......... U U U U U 8 8 4 4 4 -lsl 8 r . 1110...100101... .......... U U U U U 6 6 6 6 6 -lsl 16 r . 1110...101101... .......... U U U U U 6 6 6 6 6 -lsl 32 r . 1110...110101... .......... U U U U U 8 8 6 6 6 -lsl 16 . . 1110001111...... A+-DXWL... U U U U U 8 8 5 5 5 -move 8 d d 0001...000000... .......... U U U U U 4 4 2 2 2 -move 8 d . 0001...000...... A+-DXWLdxI U U U U U 4 4 2 2 2 -move 8 ai d 0001...010000... .......... U U U U U 8 8 4 4 4 -move 8 ai . 0001...010...... A+-DXWLdxI U U U U U 8 8 4 4 4 -move 8 pi d 0001...011000... .......... U U U U U 8 8 4 4 4 -move 8 pi . 0001...011...... A+-DXWLdxI U U U U U 8 8 4 4 4 -move 8 pi7 d 0001111011000... .......... U U U U U 8 8 4 4 4 -move 8 pi7 . 0001111011...... A+-DXWLdxI U U U U U 8 8 4 4 4 -move 8 pd d 0001...100000... .......... U U U U U 8 8 5 5 5 -move 8 pd . 0001...100...... A+-DXWLdxI U U U U U 8 8 5 5 5 -move 8 pd7 d 0001111100000... .......... U U U U U 8 8 5 5 5 -move 8 pd7 . 0001111100...... A+-DXWLdxI U U U U U 8 8 5 5 5 -move 8 di d 0001...101000... .......... U U U U U 12 12 5 5 5 -move 8 di . 0001...101...... A+-DXWLdxI U U U U U 12 12 5 5 5 -move 8 ix d 0001...110000... .......... U U U U U 14 14 7 7 7 -move 8 ix . 0001...110...... A+-DXWLdxI U U U U U 14 14 7 7 7 -move 8 aw d 0001000111000... .......... U U U U U 12 12 4 4 4 -move 8 aw . 0001000111...... A+-DXWLdxI U U U U U 12 12 4 4 4 -move 8 al d 0001001111000... .......... U U U U U 16 16 6 6 6 -move 8 al . 0001001111...... A+-DXWLdxI U U U U U 16 16 6 6 6 -move 16 d d 0011...000000... .......... U U U U U 4 4 2 2 2 -move 16 d a 0011...000001... .......... U U U U U 4 4 2 2 2 -move 16 d . 0011...000...... A+-DXWLdxI U U U U U 4 4 2 2 2 -move 16 ai d 0011...010000... .......... U U U U U 8 8 4 4 4 -move 16 ai a 0011...010001... .......... U U U U U 8 8 4 4 4 -move 16 ai . 0011...010...... A+-DXWLdxI U U U U U 8 8 4 4 4 -move 16 pi d 0011...011000... .......... U U U U U 8 8 4 4 4 -move 16 pi a 0011...011001... .......... U U U U U 8 8 4 4 4 -move 16 pi . 0011...011...... A+-DXWLdxI U U U U U 8 8 4 4 4 -move 16 pd d 0011...100000... .......... U U U U U 8 8 5 5 5 -move 16 pd a 0011...100001... .......... U U U U U 8 8 5 5 5 -move 16 pd . 0011...100...... A+-DXWLdxI U U U U U 8 8 5 5 5 -move 16 di d 0011...101000... .......... U U U U U 12 12 5 5 5 -move 16 di a 0011...101001... .......... U U U U U 12 12 5 5 5 -move 16 di . 0011...101...... A+-DXWLdxI U U U U U 12 12 5 5 5 -move 16 ix d 0011...110000... .......... U U U U U 14 14 7 7 7 -move 16 ix a 0011...110001... .......... U U U U U 14 14 7 7 7 -move 16 ix . 0011...110...... A+-DXWLdxI U U U U U 14 14 7 7 7 -move 16 aw d 0011000111000... .......... U U U U U 12 12 4 4 4 -move 16 aw a 0011000111001... .......... U U U U U 12 12 4 4 4 -move 16 aw . 0011000111...... A+-DXWLdxI U U U U U 12 12 4 4 4 -move 16 al d 0011001111000... .......... U U U U U 16 16 6 6 6 -move 16 al a 0011001111001... .......... U U U U U 16 16 6 6 6 -move 16 al . 0011001111...... A+-DXWLdxI U U U U U 16 16 6 6 6 -move 32 d d 0010...000000... .......... U U U U U 4 4 2 2 2 -move 32 d a 0010...000001... .......... U U U U U 4 4 2 2 2 -move 32 d . 0010...000...... A+-DXWLdxI U U U U U 4 4 2 2 2 -move 32 ai d 0010...010000... .......... U U U U U 12 12 4 4 4 -move 32 ai a 0010...010001... .......... U U U U U 12 12 4 4 4 -move 32 ai . 0010...010...... A+-DXWLdxI U U U U U 12 12 4 4 4 -move 32 pi d 0010...011000... .......... U U U U U 12 12 4 4 4 -move 32 pi a 0010...011001... .......... U U U U U 12 12 4 4 4 -move 32 pi . 0010...011...... A+-DXWLdxI U U U U U 12 12 4 4 4 -move 32 pd d 0010...100000... .......... U U U U U 12 14 5 5 5 -move 32 pd a 0010...100001... .......... U U U U U 12 14 5 5 5 -move 32 pd . 0010...100...... A+-DXWLdxI U U U U U 12 14 5 5 5 -move 32 di d 0010...101000... .......... U U U U U 16 16 5 5 5 -move 32 di a 0010...101001... .......... U U U U U 16 16 5 5 5 -move 32 di . 0010...101...... A+-DXWLdxI U U U U U 16 16 5 5 5 -move 32 ix d 0010...110000... .......... U U U U U 18 18 7 7 7 -move 32 ix a 0010...110001... .......... U U U U U 18 18 7 7 7 -move 32 ix . 0010...110...... A+-DXWLdxI U U U U U 18 18 7 7 7 -move 32 aw d 0010000111000... .......... U U U U U 16 16 4 4 4 -move 32 aw a 0010000111001... .......... U U U U U 16 16 4 4 4 -move 32 aw . 0010000111...... A+-DXWLdxI U U U U U 16 16 4 4 4 -move 32 al d 0010001111000... .......... U U U U U 20 20 6 6 6 -move 32 al a 0010001111001... .......... U U U U U 20 20 6 6 6 -move 32 al . 0010001111...... A+-DXWLdxI U U U U U 20 20 6 6 6 -movea 16 . d 0011...001000... .......... U U U U U 4 4 2 2 2 -movea 16 . a 0011...001001... .......... U U U U U 4 4 2 2 2 -movea 16 . . 0011...001...... A+-DXWLdxI U U U U U 4 4 2 2 2 -movea 32 . d 0010...001000... .......... U U U U U 4 4 2 2 2 -movea 32 . a 0010...001001... .......... U U U U U 4 4 2 2 2 -movea 32 . . 0010...001...... A+-DXWLdxI U U U U U 4 4 2 2 2 -move 16 frc d 0100001011000... .......... . U U U U . 4 4 4 4 -move 16 frc . 0100001011...... A+-DXWL... . U U U U . 8 4 4 4 -move 16 toc d 0100010011000... .......... U U U U U 12 12 4 4 4 -move 16 toc . 0100010011...... A+-DXWLdxI U U U U U 12 12 4 4 4 -move 16 frs d 0100000011000... .......... U S S S S 6 4 8 8 8 U only for 000 -move 16 frs . 0100000011...... A+-DXWL... U S S S S 8 8 8 8 8 U only for 000 -move 16 tos d 0100011011000... .......... S S S S S 12 12 8 8 8 -move 16 tos . 0100011011...... A+-DXWLdxI S S S S S 12 12 8 8 8 -move 32 fru . 0100111001101... .......... S S S S S 4 6 2 2 2 -move 32 tou . 0100111001100... .......... S S S S S 4 6 2 2 2 -movec 32 cr . 0100111001111010 .......... . S S S S . 12 6 6 6 -movec 32 rc . 0100111001111011 .......... . S S S S . 10 12 12 12 -movem 16 re pd 0100100010100... .......... U U U U U 8 8 4 4 4 -movem 16 re . 0100100010...... A..DXWL... U U U U U 8 8 4 4 4 -movem 32 re pd 0100100011100... .......... U U U U U 8 8 4 4 4 -movem 32 re . 0100100011...... A..DXWL... U U U U U 8 8 4 4 4 -movem 16 er pi 0100110010011... .......... U U U U U 12 12 8 8 8 -movem 16 er pcdi 0100110010111010 .......... U U U U U 16 16 9 9 9 -movem 16 er pcix 0100110010111011 .......... U U U U U 18 18 11 11 11 -movem 16 er . 0100110010...... A..DXWL... U U U U U 12 12 8 8 8 -movem 32 er pi 0100110011011... .......... U U U U U 12 12 8 8 8 -movem 32 er pcdi 0100110011111010 .......... U U U U U 16 16 9 9 9 -movem 32 er pcix 0100110011111011 .......... U U U U U 18 18 11 11 11 -movem 32 er . 0100110011...... A..DXWL... U U U U U 12 12 8 8 8 -movep 16 er . 0000...100001... .......... U U U U U 16 16 12 12 12 -movep 32 er . 0000...101001... .......... U U U U U 24 24 18 18 18 -movep 16 re . 0000...110001... .......... U U U U U 16 16 11 11 11 -movep 32 re . 0000...111001... .......... U U U U U 24 24 17 17 17 -moveq 32 . . 0111...0........ .......... U U U U U 4 4 2 2 2 -moves 8 . . 0000111000...... A+-DXWL... . S S S S . 14 5 5 5 -moves 16 . . 0000111001...... A+-DXWL... . S S S S . 14 5 5 5 -moves 32 . . 0000111010...... A+-DXWL... . S S S S . 16 5 5 5 -move16 32 . . 1111011000100... .......... . . . . U . . . . 4 TODO: correct timing -muls 16 . d 1100...111000... .......... U U U U U 54 32 27 27 27 -muls 16 . . 1100...111...... A+-DXWLdxI U U U U U 54 32 27 27 27 -mulu 16 . d 1100...011000... .......... U U U U U 54 30 27 27 27 -mulu 16 . . 1100...011...... A+-DXWLdxI U U U U U 54 30 27 27 27 -mull 32 . d 0100110000000... .......... . . U U U . . 43 43 43 -mull 32 . . 0100110000...... A+-DXWLdxI . . U U U . . 43 43 43 -nbcd 8 . d 0100100000000... .......... U U U U U 6 6 6 6 6 -nbcd 8 . . 0100100000...... A+-DXWL... U U U U U 8 8 6 6 6 -neg 8 . d 0100010000000... .......... U U U U U 4 4 2 2 2 -neg 8 . . 0100010000...... A+-DXWL... U U U U U 8 8 4 4 4 -neg 16 . d 0100010001000... .......... U U U U U 4 4 2 2 2 -neg 16 . . 0100010001...... A+-DXWL... U U U U U 8 8 4 4 4 -neg 32 . d 0100010010000... .......... U U U U U 6 6 2 2 2 -neg 32 . . 0100010010...... A+-DXWL... U U U U U 12 12 4 4 4 -negx 8 . d 0100000000000... .......... U U U U U 4 4 2 2 2 -negx 8 . . 0100000000...... A+-DXWL... U U U U U 8 8 4 4 4 -negx 16 . d 0100000001000... .......... U U U U U 4 4 2 2 2 -negx 16 . . 0100000001...... A+-DXWL... U U U U U 8 8 4 4 4 -negx 32 . d 0100000010000... .......... U U U U U 6 6 2 2 2 -negx 32 . . 0100000010...... A+-DXWL... U U U U U 12 12 4 4 4 -nop 0 . . 0100111001110001 .......... U U U U U 4 4 2 2 2 -not 8 . d 0100011000000... .......... U U U U U 4 4 2 2 2 -not 8 . . 0100011000...... A+-DXWL... U U U U U 8 8 4 4 4 -not 16 . d 0100011001000... .......... U U U U U 4 4 2 2 2 -not 16 . . 0100011001...... A+-DXWL... U U U U U 8 8 4 4 4 -not 32 . d 0100011010000... .......... U U U U U 6 6 2 2 2 -not 32 . . 0100011010...... A+-DXWL... U U U U U 12 12 4 4 4 -or 8 er d 1000...000000... .......... U U U U U 4 4 2 2 2 -or 8 er . 1000...000...... A+-DXWLdxI U U U U U 4 4 2 2 2 -or 16 er d 1000...001000... .......... U U U U U 4 4 2 2 2 -or 16 er . 1000...001...... A+-DXWLdxI U U U U U 4 4 2 2 2 -or 32 er d 1000...010000... .......... U U U U U 6 6 2 2 2 -or 32 er . 1000...010...... A+-DXWLdxI U U U U U 6 6 2 2 2 -or 8 re . 1000...100...... A+-DXWL... U U U U U 8 8 4 4 4 -or 16 re . 1000...101...... A+-DXWL... U U U U U 8 8 4 4 4 -or 32 re . 1000...110...... A+-DXWL... U U U U U 12 12 4 4 4 -ori 16 toc . 0000000000111100 .......... U U U U U 20 16 12 12 12 -ori 16 tos . 0000000001111100 .......... S S S S S 20 16 12 12 12 -ori 8 . d 0000000000000... .......... U U U U U 8 8 2 2 2 -ori 8 . . 0000000000...... A+-DXWL... U U U U U 12 12 4 4 4 -ori 16 . d 0000000001000... .......... U U U U U 8 8 2 2 2 -ori 16 . . 0000000001...... A+-DXWL... U U U U U 12 12 4 4 4 -ori 32 . d 0000000010000... .......... U U U U U 16 14 2 2 2 -ori 32 . . 0000000010...... A+-DXWL... U U U U U 20 20 4 4 4 -pack 16 rr . 1000...101000... .......... . . U U U . . 6 6 6 -pack 16 mm ax7 1000111101001... .......... . . U U U . . 13 13 13 -pack 16 mm ay7 1000...101001111 .......... . . U U U . . 13 13 13 -pack 16 mm axy7 1000111101001111 .......... . . U U U . . 13 13 13 -pack 16 mm . 1000...101001... .......... . . U U U . . 13 13 13 -pea 32 . . 0100100001...... A..DXWLdx. U U U U U 6 6 5 5 5 -pflush 32 . . 1111010100011000 .......... . . . . S . . . . 4 TODO: correct timing -pmmu 32 . . 1111000......... .......... . . S S S . . 8 8 8 -reset 0 . . 0100111001110000 .......... S S S S S 0 0 0 0 0 -ror 8 s . 1110...000011... .......... U U U U U 6 6 8 8 8 -ror 16 s . 1110...001011... .......... U U U U U 6 6 8 8 8 -ror 32 s . 1110...010011... .......... U U U U U 8 8 8 8 8 -ror 8 r . 1110...000111... .......... U U U U U 6 6 8 8 8 -ror 16 r . 1110...001111... .......... U U U U U 6 6 8 8 8 -ror 32 r . 1110...010111... .......... U U U U U 8 8 8 8 8 -ror 16 . . 1110011011...... A+-DXWL... U U U U U 8 8 7 7 7 -rol 8 s . 1110...100011... .......... U U U U U 6 6 8 8 8 -rol 16 s . 1110...101011... .......... U U U U U 6 6 8 8 8 -rol 32 s . 1110...110011... .......... U U U U U 8 8 8 8 8 -rol 8 r . 1110...100111... .......... U U U U U 6 6 8 8 8 -rol 16 r . 1110...101111... .......... U U U U U 6 6 8 8 8 -rol 32 r . 1110...110111... .......... U U U U U 8 8 8 8 8 -rol 16 . . 1110011111...... A+-DXWL... U U U U U 8 8 7 7 7 -roxr 8 s . 1110...000010... .......... U U U U U 6 6 12 12 12 -roxr 16 s . 1110...001010... .......... U U U U U 6 6 12 12 12 -roxr 32 s . 1110...010010... .......... U U U U U 8 8 12 12 12 -roxr 8 r . 1110...000110... .......... U U U U U 6 6 12 12 12 -roxr 16 r . 1110...001110... .......... U U U U U 6 6 12 12 12 -roxr 32 r . 1110...010110... .......... U U U U U 8 8 12 12 12 -roxr 16 . . 1110010011...... A+-DXWL... U U U U U 8 8 5 5 5 -roxl 8 s . 1110...100010... .......... U U U U U 6 6 12 12 12 -roxl 16 s . 1110...101010... .......... U U U U U 6 6 12 12 12 -roxl 32 s . 1110...110010... .......... U U U U U 8 8 12 12 12 -roxl 8 r . 1110...100110... .......... U U U U U 6 6 12 12 12 -roxl 16 r . 1110...101110... .......... U U U U U 6 6 12 12 12 -roxl 32 r . 1110...110110... .......... U U U U U 8 8 12 12 12 -roxl 16 . . 1110010111...... A+-DXWL... U U U U U 8 8 5 5 5 -rtd 32 . . 0100111001110100 .......... . U U U U . 16 10 10 10 -rte 32 . . 0100111001110011 .......... S S S S S 20 24 20 20 20 bus fault not emulated -rtm 32 . . 000001101100.... .......... . . U U U . . 19 19 19 not properly emulated -rtr 32 . . 0100111001110111 .......... U U U U U 20 20 14 14 14 -rts 32 . . 0100111001110101 .......... U U U U U 16 16 10 10 10 -sbcd 8 rr . 1000...100000... .......... U U U U U 6 6 4 4 4 -sbcd 8 mm ax7 1000111100001... .......... U U U U U 18 18 16 16 16 -sbcd 8 mm ay7 1000...100001111 .......... U U U U U 18 18 16 16 16 -sbcd 8 mm axy7 1000111100001111 .......... U U U U U 18 18 16 16 16 -sbcd 8 mm . 1000...100001... .......... U U U U U 18 18 16 16 16 -st 8 . d 0101000011000... .......... U U U U U 6 4 4 4 4 -st 8 . . 0101000011...... A+-DXWL... U U U U U 8 8 6 6 6 -sf 8 . d 0101000111000... .......... U U U U U 4 4 4 4 4 -sf 8 . . 0101000111...... A+-DXWL... U U U U U 8 8 6 6 6 -scc 8 . d 0101....11000... .......... U U U U U 4 4 4 4 4 -scc 8 . . 0101....11...... A+-DXWL... U U U U U 8 8 6 6 6 -stop 0 . . 0100111001110010 .......... S S S S S 4 4 8 8 8 -sub 8 er d 1001...000000... .......... U U U U U 4 4 2 2 2 -sub 8 er . 1001...000...... A+-DXWLdxI U U U U U 4 4 2 2 2 -sub 16 er d 1001...001000... .......... U U U U U 4 4 2 2 2 -sub 16 er a 1001...001001... .......... U U U U U 4 4 2 2 2 -sub 16 er . 1001...001...... A+-DXWLdxI U U U U U 4 4 2 2 2 -sub 32 er d 1001...010000... .......... U U U U U 6 6 2 2 2 -sub 32 er a 1001...010001... .......... U U U U U 6 6 2 2 2 -sub 32 er . 1001...010...... A+-DXWLdxI U U U U U 6 6 2 2 2 -sub 8 re . 1001...100...... A+-DXWL... U U U U U 8 8 4 4 4 -sub 16 re . 1001...101...... A+-DXWL... U U U U U 8 8 4 4 4 -sub 32 re . 1001...110...... A+-DXWL... U U U U U 12 12 4 4 4 -suba 16 . d 1001...011000... .......... U U U U U 8 8 2 2 2 -suba 16 . a 1001...011001... .......... U U U U U 8 8 2 2 2 -suba 16 . . 1001...011...... A+-DXWLdxI U U U U U 8 8 2 2 2 -suba 32 . d 1001...111000... .......... U U U U U 6 6 2 2 2 -suba 32 . a 1001...111001... .......... U U U U U 6 6 2 2 2 -suba 32 . . 1001...111...... A+-DXWLdxI U U U U U 6 6 2 2 2 -subi 8 . d 0000010000000... .......... U U U U U 8 8 2 2 2 -subi 8 . . 0000010000...... A+-DXWL... U U U U U 12 12 4 4 4 -subi 16 . d 0000010001000... .......... U U U U U 8 8 2 2 2 -subi 16 . . 0000010001...... A+-DXWL... U U U U U 12 12 4 4 4 -subi 32 . d 0000010010000... .......... U U U U U 16 14 2 2 2 -subi 32 . . 0000010010...... A+-DXWL... U U U U U 20 20 4 4 4 -subq 8 . d 0101...100000... .......... U U U U U 4 4 2 2 2 -subq 8 . . 0101...100...... A+-DXWL... U U U U U 8 8 4 4 4 -subq 16 . d 0101...101000... .......... U U U U U 4 4 2 2 2 -subq 16 . a 0101...101001... .......... U U U U U 8 4 2 2 2 -subq 16 . . 0101...101...... A+-DXWL... U U U U U 8 8 4 4 4 -subq 32 . d 0101...110000... .......... U U U U U 8 8 2 2 2 -subq 32 . a 0101...110001... .......... U U U U U 8 8 2 2 2 -subq 32 . . 0101...110...... A+-DXWL... U U U U U 12 12 4 4 4 -subx 8 rr . 1001...100000... .......... U U U U U 4 4 2 2 2 -subx 16 rr . 1001...101000... .......... U U U U U 4 4 2 2 2 -subx 32 rr . 1001...110000... .......... U U U U U 8 6 2 2 2 -subx 8 mm ax7 1001111100001... .......... U U U U U 18 18 12 12 12 -subx 8 mm ay7 1001...100001111 .......... U U U U U 18 18 12 12 12 -subx 8 mm axy7 1001111100001111 .......... U U U U U 18 18 12 12 12 -subx 8 mm . 1001...100001... .......... U U U U U 18 18 12 12 12 -subx 16 mm . 1001...101001... .......... U U U U U 18 18 12 12 12 -subx 32 mm . 1001...110001... .......... U U U U U 30 30 12 12 12 -swap 32 . . 0100100001000... .......... U U U U U 4 4 4 4 4 -tas 8 . d 0100101011000... .......... U U U U U 4 4 4 4 4 -tas 8 . . 0100101011...... A+-DXWL... U U U U U 14 14 12 12 12 -trap 0 . . 010011100100.... .......... U U U U U 4 4 4 4 4 -trapt 0 . . 0101000011111100 .......... . . U U U . . 4 4 4 -trapt 16 . . 0101000011111010 .......... . . U U U . . 6 6 6 -trapt 32 . . 0101000011111011 .......... . . U U U . . 8 8 8 -trapf 0 . . 0101000111111100 .......... . . U U U . . 4 4 4 -trapf 16 . . 0101000111111010 .......... . . U U U . . 6 6 6 -trapf 32 . . 0101000111111011 .......... . . U U U . . 8 8 8 -trapcc 0 . . 0101....11111100 .......... . . U U U . . 4 4 4 -trapcc 16 . . 0101....11111010 .......... . . U U U . . 6 6 6 -trapcc 32 . . 0101....11111011 .......... . . U U U . . 8 8 8 -trapv 0 . . 0100111001110110 .......... U U U U U 4 4 4 4 4 -tst 8 . d 0100101000000... .......... U U U U U 4 4 2 2 2 -tst 8 . . 0100101000...... A+-DXWL... U U U U U 4 4 2 2 2 -tst 8 . pcdi 0100101000111010 .......... . . U U U . . 7 7 7 -tst 8 . pcix 0100101000111011 .......... . . U U U . . 9 9 9 -tst 8 . i 0100101000111100 .......... . . U U U . . 6 6 6 -tst 16 . d 0100101001000... .......... U U U U U 4 4 2 2 2 -tst 16 . a 0100101001001... .......... . . U U U . . 2 2 2 -tst 16 . . 0100101001...... A+-DXWL... U U U U U 4 4 2 2 2 -tst 16 . pcdi 0100101001111010 .......... . . U U U . . 7 7 7 -tst 16 . pcix 0100101001111011 .......... . . U U U . . 9 9 9 -tst 16 . i 0100101001111100 .......... . . U U U . . 6 6 6 -tst 32 . d 0100101010000... .......... U U U U U 4 4 2 2 2 -tst 32 . a 0100101010001... .......... . . U U U . . 2 2 2 -tst 32 . . 0100101010...... A+-DXWL... U U U U U 4 4 2 2 2 -tst 32 . pcdi 0100101010111010 .......... . . U U U . . 7 7 7 -tst 32 . pcix 0100101010111011 .......... . . U U U . . 9 9 9 -tst 32 . i 0100101010111100 .......... . . U U U . . 6 6 6 -unlk 32 . a7 0100111001011111 .......... U U U U U 12 12 6 6 6 -unlk 32 . . 0100111001011... .......... U U U U U 12 12 6 6 6 -unpk 16 rr . 1000...110000... .......... . . U U U . . 8 8 8 -unpk 16 mm ax7 1000111110001... .......... . . U U U . . 13 13 13 -unpk 16 mm ay7 1000...110001111 .......... . . U U U . . 13 13 13 -unpk 16 mm axy7 1000111110001111 .......... . . U U U . . 13 13 13 -unpk 16 mm . 1000...110001... .......... . . U U U . . 13 13 13 - - - -XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -M68KMAKE_OPCODE_HANDLER_BODY - -M68KMAKE_OP(1010, 0, ., .) -{ - m68ki_exception_1010(); -} - - -M68KMAKE_OP(1111, 0, ., .) -{ - m68ki_exception_1111(); -} - - -M68KMAKE_OP(040fpu0, 32, ., .) -{ - if(CPU_TYPE_IS_030_PLUS(CPU_TYPE)) - { - m68040_fpu_op0(); - return; - } - m68ki_exception_1111(); -} - - -M68KMAKE_OP(040fpu1, 32, ., .) -{ - if(CPU_TYPE_IS_030_PLUS(CPU_TYPE)) - { - m68040_fpu_op1(); - return; - } - m68ki_exception_1111(); -} - - - -M68KMAKE_OP(abcd, 8, rr, .) -{ - uint* r_dst = &DX; - uint src = DY; - uint dst = *r_dst; - uint res = LOW_NIBBLE(src) + LOW_NIBBLE(dst) + XFLAG_AS_1(); - - FLAG_V = ~res; /* Undefined V behavior */ - - if(res > 9) - res += 6; - res += HIGH_NIBBLE(src) + HIGH_NIBBLE(dst); - FLAG_X = FLAG_C = (res > 0x99) << 8; - if(FLAG_C) - res -= 0xa0; - - FLAG_V &= res; /* Undefined V behavior part II */ - FLAG_N = NFLAG_8(res); /* Undefined N behavior */ - - res = MASK_OUT_ABOVE_8(res); - FLAG_Z |= res; - - *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; -} - - -M68KMAKE_OP(abcd, 8, mm, ax7) -{ - uint src = OPER_AY_PD_8(); - uint ea = EA_A7_PD_8(); - uint dst = m68ki_read_8(ea); - uint res = LOW_NIBBLE(src) + LOW_NIBBLE(dst) + XFLAG_AS_1(); - - FLAG_V = ~res; /* Undefined V behavior */ - - if(res > 9) - res += 6; - res += HIGH_NIBBLE(src) + HIGH_NIBBLE(dst); - FLAG_X = FLAG_C = (res > 0x99) << 8; - if(FLAG_C) - res -= 0xa0; - - FLAG_V &= res; /* Undefined V behavior part II */ - FLAG_N = NFLAG_8(res); /* Undefined N behavior */ - - res = MASK_OUT_ABOVE_8(res); - FLAG_Z |= res; - - m68ki_write_8(ea, res); -} - - -M68KMAKE_OP(abcd, 8, mm, ay7) -{ - uint src = OPER_A7_PD_8(); - uint ea = EA_AX_PD_8(); - uint dst = m68ki_read_8(ea); - uint res = LOW_NIBBLE(src) + LOW_NIBBLE(dst) + XFLAG_AS_1(); - - FLAG_V = ~res; /* Undefined V behavior */ - - if(res > 9) - res += 6; - res += HIGH_NIBBLE(src) + HIGH_NIBBLE(dst); - FLAG_X = FLAG_C = (res > 0x99) << 8; - if(FLAG_C) - res -= 0xa0; - - FLAG_V &= res; /* Undefined V behavior part II */ - FLAG_N = NFLAG_8(res); /* Undefined N behavior */ - - res = MASK_OUT_ABOVE_8(res); - FLAG_Z |= res; - - m68ki_write_8(ea, res); -} - - -M68KMAKE_OP(abcd, 8, mm, axy7) -{ - uint src = OPER_A7_PD_8(); - uint ea = EA_A7_PD_8(); - uint dst = m68ki_read_8(ea); - uint res = LOW_NIBBLE(src) + LOW_NIBBLE(dst) + XFLAG_AS_1(); - - FLAG_V = ~res; /* Undefined V behavior */ - - if(res > 9) - res += 6; - res += HIGH_NIBBLE(src) + HIGH_NIBBLE(dst); - FLAG_X = FLAG_C = (res > 0x99) << 8; - if(FLAG_C) - res -= 0xa0; - - FLAG_V &= res; /* Undefined V behavior part II */ - FLAG_N = NFLAG_8(res); /* Undefined N behavior */ - - res = MASK_OUT_ABOVE_8(res); - FLAG_Z |= res; - - m68ki_write_8(ea, res); -} - - -M68KMAKE_OP(abcd, 8, mm, .) -{ - uint src = OPER_AY_PD_8(); - uint ea = EA_AX_PD_8(); - uint dst = m68ki_read_8(ea); - uint res = LOW_NIBBLE(src) + LOW_NIBBLE(dst) + XFLAG_AS_1(); - - FLAG_V = ~res; /* Undefined V behavior */ - - if(res > 9) - res += 6; - res += HIGH_NIBBLE(src) + HIGH_NIBBLE(dst); - FLAG_X = FLAG_C = (res > 0x99) << 8; - if(FLAG_C) - res -= 0xa0; - - FLAG_V &= res; /* Undefined V behavior part II */ - FLAG_N = NFLAG_8(res); /* Undefined N behavior */ - - res = MASK_OUT_ABOVE_8(res); - FLAG_Z |= res; - - m68ki_write_8(ea, res); -} - - -M68KMAKE_OP(add, 8, er, d) -{ - uint* r_dst = &DX; - uint src = MASK_OUT_ABOVE_8(DY); - uint dst = MASK_OUT_ABOVE_8(*r_dst); - uint res = src + dst; - - FLAG_N = NFLAG_8(res); - FLAG_V = VFLAG_ADD_8(src, dst, res); - FLAG_X = FLAG_C = CFLAG_8(res); - FLAG_Z = MASK_OUT_ABOVE_8(res); - - *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; -} - - -M68KMAKE_OP(add, 8, er, .) -{ - uint* r_dst = &DX; - uint src = M68KMAKE_GET_OPER_AY_8; - uint dst = MASK_OUT_ABOVE_8(*r_dst); - uint res = src + dst; - - FLAG_N = NFLAG_8(res); - FLAG_V = VFLAG_ADD_8(src, dst, res); - FLAG_X = FLAG_C = CFLAG_8(res); - FLAG_Z = MASK_OUT_ABOVE_8(res); - - *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; -} - - -M68KMAKE_OP(add, 16, er, d) -{ - uint* r_dst = &DX; - uint src = MASK_OUT_ABOVE_16(DY); - uint dst = MASK_OUT_ABOVE_16(*r_dst); - uint res = src + dst; - - FLAG_N = NFLAG_16(res); - FLAG_V = VFLAG_ADD_16(src, dst, res); - FLAG_X = FLAG_C = CFLAG_16(res); - FLAG_Z = MASK_OUT_ABOVE_16(res); - - *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; -} - - -M68KMAKE_OP(add, 16, er, a) -{ - uint* r_dst = &DX; - uint src = MASK_OUT_ABOVE_16(AY); - uint dst = MASK_OUT_ABOVE_16(*r_dst); - uint res = src + dst; - - FLAG_N = NFLAG_16(res); - FLAG_V = VFLAG_ADD_16(src, dst, res); - FLAG_X = FLAG_C = CFLAG_16(res); - FLAG_Z = MASK_OUT_ABOVE_16(res); - - *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; -} - - -M68KMAKE_OP(add, 16, er, .) -{ - uint* r_dst = &DX; - uint src = M68KMAKE_GET_OPER_AY_16; - uint dst = MASK_OUT_ABOVE_16(*r_dst); - uint res = src + dst; - - FLAG_N = NFLAG_16(res); - FLAG_V = VFLAG_ADD_16(src, dst, res); - FLAG_X = FLAG_C = CFLAG_16(res); - FLAG_Z = MASK_OUT_ABOVE_16(res); - - *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; -} - - -M68KMAKE_OP(add, 32, er, d) -{ - uint* r_dst = &DX; - uint src = DY; - uint dst = *r_dst; - uint res = src + dst; - - FLAG_N = NFLAG_32(res); - FLAG_V = VFLAG_ADD_32(src, dst, res); - FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); - FLAG_Z = MASK_OUT_ABOVE_32(res); - - *r_dst = FLAG_Z; -} - - -M68KMAKE_OP(add, 32, er, a) -{ - uint* r_dst = &DX; - uint src = AY; - uint dst = *r_dst; - uint res = src + dst; - - FLAG_N = NFLAG_32(res); - FLAG_V = VFLAG_ADD_32(src, dst, res); - FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); - FLAG_Z = MASK_OUT_ABOVE_32(res); - - *r_dst = FLAG_Z; -} - - -M68KMAKE_OP(add, 32, er, .) -{ - uint* r_dst = &DX; - uint src = M68KMAKE_GET_OPER_AY_32; - uint dst = *r_dst; - uint res = src + dst; - - FLAG_N = NFLAG_32(res); - FLAG_V = VFLAG_ADD_32(src, dst, res); - FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); - FLAG_Z = MASK_OUT_ABOVE_32(res); - - *r_dst = FLAG_Z; -} - - -M68KMAKE_OP(add, 8, re, .) -{ - uint ea = M68KMAKE_GET_EA_AY_8; - uint src = MASK_OUT_ABOVE_8(DX); - uint dst = m68ki_read_8(ea); - uint res = src + dst; - - FLAG_N = NFLAG_8(res); - FLAG_V = VFLAG_ADD_8(src, dst, res); - FLAG_X = FLAG_C = CFLAG_8(res); - FLAG_Z = MASK_OUT_ABOVE_8(res); - - m68ki_write_8(ea, FLAG_Z); -} - - -M68KMAKE_OP(add, 16, re, .) -{ - uint ea = M68KMAKE_GET_EA_AY_16; - uint src = MASK_OUT_ABOVE_16(DX); - uint dst = m68ki_read_16(ea); - uint res = src + dst; - - FLAG_N = NFLAG_16(res); - FLAG_V = VFLAG_ADD_16(src, dst, res); - FLAG_X = FLAG_C = CFLAG_16(res); - FLAG_Z = MASK_OUT_ABOVE_16(res); - - m68ki_write_16(ea, FLAG_Z); -} - - -M68KMAKE_OP(add, 32, re, .) -{ - uint ea = M68KMAKE_GET_EA_AY_32; - uint src = DX; - uint dst = m68ki_read_32(ea); - uint res = src + dst; - - FLAG_N = NFLAG_32(res); - FLAG_V = VFLAG_ADD_32(src, dst, res); - FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); - FLAG_Z = MASK_OUT_ABOVE_32(res); - - m68ki_write_32(ea, FLAG_Z); -} - - -M68KMAKE_OP(adda, 16, ., d) -{ - uint* r_dst = &AX; - - *r_dst = MASK_OUT_ABOVE_32(*r_dst + MAKE_INT_16(DY)); -} - - -M68KMAKE_OP(adda, 16, ., a) -{ - uint* r_dst = &AX; - - *r_dst = MASK_OUT_ABOVE_32(*r_dst + MAKE_INT_16(AY)); -} - - -M68KMAKE_OP(adda, 16, ., .) -{ - uint* r_dst = &AX; - uint src = MAKE_INT_16(M68KMAKE_GET_OPER_AY_16); - - *r_dst = MASK_OUT_ABOVE_32(*r_dst + src); -} - - -M68KMAKE_OP(adda, 32, ., d) -{ - uint* r_dst = &AX; - - *r_dst = MASK_OUT_ABOVE_32(*r_dst + DY); -} - - -M68KMAKE_OP(adda, 32, ., a) -{ - uint* r_dst = &AX; - - *r_dst = MASK_OUT_ABOVE_32(*r_dst + AY); -} - - -M68KMAKE_OP(adda, 32, ., .) -{ - uint src = M68KMAKE_GET_OPER_AY_32; - uint* r_dst = &AX; - - *r_dst = MASK_OUT_ABOVE_32(*r_dst + src); -} - - -M68KMAKE_OP(addi, 8, ., d) -{ - uint* r_dst = &DY; - uint src = OPER_I_8(); - uint dst = MASK_OUT_ABOVE_8(*r_dst); - uint res = src + dst; - - FLAG_N = NFLAG_8(res); - FLAG_V = VFLAG_ADD_8(src, dst, res); - FLAG_X = FLAG_C = CFLAG_8(res); - FLAG_Z = MASK_OUT_ABOVE_8(res); - - *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; -} - - -M68KMAKE_OP(addi, 8, ., .) -{ - uint src = OPER_I_8(); - uint ea = M68KMAKE_GET_EA_AY_8; - uint dst = m68ki_read_8(ea); - uint res = src + dst; - - FLAG_N = NFLAG_8(res); - FLAG_V = VFLAG_ADD_8(src, dst, res); - FLAG_X = FLAG_C = CFLAG_8(res); - FLAG_Z = MASK_OUT_ABOVE_8(res); - - m68ki_write_8(ea, FLAG_Z); -} - - -M68KMAKE_OP(addi, 16, ., d) -{ - uint* r_dst = &DY; - uint src = OPER_I_16(); - uint dst = MASK_OUT_ABOVE_16(*r_dst); - uint res = src + dst; - - FLAG_N = NFLAG_16(res); - FLAG_V = VFLAG_ADD_16(src, dst, res); - FLAG_X = FLAG_C = CFLAG_16(res); - FLAG_Z = MASK_OUT_ABOVE_16(res); - - *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; -} - - -M68KMAKE_OP(addi, 16, ., .) -{ - uint src = OPER_I_16(); - uint ea = M68KMAKE_GET_EA_AY_16; - uint dst = m68ki_read_16(ea); - uint res = src + dst; - - FLAG_N = NFLAG_16(res); - FLAG_V = VFLAG_ADD_16(src, dst, res); - FLAG_X = FLAG_C = CFLAG_16(res); - FLAG_Z = MASK_OUT_ABOVE_16(res); - - m68ki_write_16(ea, FLAG_Z); -} - - -M68KMAKE_OP(addi, 32, ., d) -{ - uint* r_dst = &DY; - uint src = OPER_I_32(); - uint dst = *r_dst; - uint res = src + dst; - - FLAG_N = NFLAG_32(res); - FLAG_V = VFLAG_ADD_32(src, dst, res); - FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); - FLAG_Z = MASK_OUT_ABOVE_32(res); - - *r_dst = FLAG_Z; -} - - -M68KMAKE_OP(addi, 32, ., .) -{ - uint src = OPER_I_32(); - uint ea = M68KMAKE_GET_EA_AY_32; - uint dst = m68ki_read_32(ea); - uint res = src + dst; - - FLAG_N = NFLAG_32(res); - FLAG_V = VFLAG_ADD_32(src, dst, res); - FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); - FLAG_Z = MASK_OUT_ABOVE_32(res); - - m68ki_write_32(ea, FLAG_Z); -} - - -M68KMAKE_OP(addq, 8, ., d) -{ - uint* r_dst = &DY; - uint src = (((REG_IR >> 9) - 1) & 7) + 1; - uint dst = MASK_OUT_ABOVE_8(*r_dst); - uint res = src + dst; - - FLAG_N = NFLAG_8(res); - FLAG_V = VFLAG_ADD_8(src, dst, res); - FLAG_X = FLAG_C = CFLAG_8(res); - FLAG_Z = MASK_OUT_ABOVE_8(res); - - *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; -} - - -M68KMAKE_OP(addq, 8, ., .) -{ - uint src = (((REG_IR >> 9) - 1) & 7) + 1; - uint ea = M68KMAKE_GET_EA_AY_8; - uint dst = m68ki_read_8(ea); - uint res = src + dst; - - FLAG_N = NFLAG_8(res); - FLAG_V = VFLAG_ADD_8(src, dst, res); - FLAG_X = FLAG_C = CFLAG_8(res); - FLAG_Z = MASK_OUT_ABOVE_8(res); - - m68ki_write_8(ea, FLAG_Z); -} - - -M68KMAKE_OP(addq, 16, ., d) -{ - uint* r_dst = &DY; - uint src = (((REG_IR >> 9) - 1) & 7) + 1; - uint dst = MASK_OUT_ABOVE_16(*r_dst); - uint res = src + dst; - - FLAG_N = NFLAG_16(res); - FLAG_V = VFLAG_ADD_16(src, dst, res); - FLAG_X = FLAG_C = CFLAG_16(res); - FLAG_Z = MASK_OUT_ABOVE_16(res); - - *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; -} - - -M68KMAKE_OP(addq, 16, ., a) -{ - uint* r_dst = &AY; - - *r_dst = MASK_OUT_ABOVE_32(*r_dst + (((REG_IR >> 9) - 1) & 7) + 1); -} - - -M68KMAKE_OP(addq, 16, ., .) -{ - uint src = (((REG_IR >> 9) - 1) & 7) + 1; - uint ea = M68KMAKE_GET_EA_AY_16; - uint dst = m68ki_read_16(ea); - uint res = src + dst; - - FLAG_N = NFLAG_16(res); - FLAG_V = VFLAG_ADD_16(src, dst, res); - FLAG_X = FLAG_C = CFLAG_16(res); - FLAG_Z = MASK_OUT_ABOVE_16(res); - - m68ki_write_16(ea, FLAG_Z); -} - - -M68KMAKE_OP(addq, 32, ., d) -{ - uint* r_dst = &DY; - uint src = (((REG_IR >> 9) - 1) & 7) + 1; - uint dst = *r_dst; - uint res = src + dst; - - FLAG_N = NFLAG_32(res); - FLAG_V = VFLAG_ADD_32(src, dst, res); - FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); - FLAG_Z = MASK_OUT_ABOVE_32(res); - - *r_dst = FLAG_Z; -} - - -M68KMAKE_OP(addq, 32, ., a) -{ - uint* r_dst = &AY; - - *r_dst = MASK_OUT_ABOVE_32(*r_dst + (((REG_IR >> 9) - 1) & 7) + 1); -} - - -M68KMAKE_OP(addq, 32, ., .) -{ - uint src = (((REG_IR >> 9) - 1) & 7) + 1; - uint ea = M68KMAKE_GET_EA_AY_32; - uint dst = m68ki_read_32(ea); - uint res = src + dst; - - - FLAG_N = NFLAG_32(res); - FLAG_V = VFLAG_ADD_32(src, dst, res); - FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); - FLAG_Z = MASK_OUT_ABOVE_32(res); - - m68ki_write_32(ea, FLAG_Z); -} - - -M68KMAKE_OP(addx, 8, rr, .) -{ - uint* r_dst = &DX; - uint src = MASK_OUT_ABOVE_8(DY); - uint dst = MASK_OUT_ABOVE_8(*r_dst); - uint res = src + dst + XFLAG_AS_1(); - - FLAG_N = NFLAG_8(res); - FLAG_V = VFLAG_ADD_8(src, dst, res); - FLAG_X = FLAG_C = CFLAG_8(res); - - res = MASK_OUT_ABOVE_8(res); - FLAG_Z |= res; - - *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; -} - - -M68KMAKE_OP(addx, 16, rr, .) -{ - uint* r_dst = &DX; - uint src = MASK_OUT_ABOVE_16(DY); - uint dst = MASK_OUT_ABOVE_16(*r_dst); - uint res = src + dst + XFLAG_AS_1(); - - FLAG_N = NFLAG_16(res); - FLAG_V = VFLAG_ADD_16(src, dst, res); - FLAG_X = FLAG_C = CFLAG_16(res); - - res = MASK_OUT_ABOVE_16(res); - FLAG_Z |= res; - - *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; -} - - -M68KMAKE_OP(addx, 32, rr, .) -{ - uint* r_dst = &DX; - uint src = DY; - uint dst = *r_dst; - uint res = src + dst + XFLAG_AS_1(); - - FLAG_N = NFLAG_32(res); - FLAG_V = VFLAG_ADD_32(src, dst, res); - FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); - - res = MASK_OUT_ABOVE_32(res); - FLAG_Z |= res; - - *r_dst = res; -} - - -M68KMAKE_OP(addx, 8, mm, ax7) -{ - uint src = OPER_AY_PD_8(); - uint ea = EA_A7_PD_8(); - uint dst = m68ki_read_8(ea); - uint res = src + dst + XFLAG_AS_1(); - - FLAG_N = NFLAG_8(res); - FLAG_V = VFLAG_ADD_8(src, dst, res); - FLAG_X = FLAG_C = CFLAG_8(res); - - res = MASK_OUT_ABOVE_8(res); - FLAG_Z |= res; - - m68ki_write_8(ea, res); -} - - -M68KMAKE_OP(addx, 8, mm, ay7) -{ - uint src = OPER_A7_PD_8(); - uint ea = EA_AX_PD_8(); - uint dst = m68ki_read_8(ea); - uint res = src + dst + XFLAG_AS_1(); - - FLAG_N = NFLAG_8(res); - FLAG_V = VFLAG_ADD_8(src, dst, res); - FLAG_X = FLAG_C = CFLAG_8(res); - - res = MASK_OUT_ABOVE_8(res); - FLAG_Z |= res; - - m68ki_write_8(ea, res); -} - - -M68KMAKE_OP(addx, 8, mm, axy7) -{ - uint src = OPER_A7_PD_8(); - uint ea = EA_A7_PD_8(); - uint dst = m68ki_read_8(ea); - uint res = src + dst + XFLAG_AS_1(); - - FLAG_N = NFLAG_8(res); - FLAG_V = VFLAG_ADD_8(src, dst, res); - FLAG_X = FLAG_C = CFLAG_8(res); - - res = MASK_OUT_ABOVE_8(res); - FLAG_Z |= res; - - m68ki_write_8(ea, res); -} - - -M68KMAKE_OP(addx, 8, mm, .) -{ - uint src = OPER_AY_PD_8(); - uint ea = EA_AX_PD_8(); - uint dst = m68ki_read_8(ea); - uint res = src + dst + XFLAG_AS_1(); - - FLAG_N = NFLAG_8(res); - FLAG_V = VFLAG_ADD_8(src, dst, res); - FLAG_X = FLAG_C = CFLAG_8(res); - - res = MASK_OUT_ABOVE_8(res); - FLAG_Z |= res; - - m68ki_write_8(ea, res); -} - - -M68KMAKE_OP(addx, 16, mm, .) -{ - uint src = OPER_AY_PD_16(); - uint ea = EA_AX_PD_16(); - uint dst = m68ki_read_16(ea); - uint res = src + dst + XFLAG_AS_1(); - - FLAG_N = NFLAG_16(res); - FLAG_V = VFLAG_ADD_16(src, dst, res); - FLAG_X = FLAG_C = CFLAG_16(res); - - res = MASK_OUT_ABOVE_16(res); - FLAG_Z |= res; - - m68ki_write_16(ea, res); -} - - -M68KMAKE_OP(addx, 32, mm, .) -{ - uint src = OPER_AY_PD_32(); - uint ea = EA_AX_PD_32(); - uint dst = m68ki_read_32(ea); - uint res = src + dst + XFLAG_AS_1(); - - FLAG_N = NFLAG_32(res); - FLAG_V = VFLAG_ADD_32(src, dst, res); - FLAG_X = FLAG_C = CFLAG_ADD_32(src, dst, res); - - res = MASK_OUT_ABOVE_32(res); - FLAG_Z |= res; - - m68ki_write_32(ea, res); -} - - -M68KMAKE_OP(and, 8, er, d) -{ - FLAG_Z = MASK_OUT_ABOVE_8(DX &= (DY | 0xffffff00)); - - FLAG_N = NFLAG_8(FLAG_Z); - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(and, 8, er, .) -{ - FLAG_Z = MASK_OUT_ABOVE_8(DX &= (M68KMAKE_GET_OPER_AY_8 | 0xffffff00)); - - FLAG_N = NFLAG_8(FLAG_Z); - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(and, 16, er, d) -{ - FLAG_Z = MASK_OUT_ABOVE_16(DX &= (DY | 0xffff0000)); - - FLAG_N = NFLAG_16(FLAG_Z); - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(and, 16, er, .) -{ - FLAG_Z = MASK_OUT_ABOVE_16(DX &= (M68KMAKE_GET_OPER_AY_16 | 0xffff0000)); - - FLAG_N = NFLAG_16(FLAG_Z); - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(and, 32, er, d) -{ - FLAG_Z = DX &= DY; - - FLAG_N = NFLAG_32(FLAG_Z); - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(and, 32, er, .) -{ - FLAG_Z = DX &= M68KMAKE_GET_OPER_AY_32; - - FLAG_N = NFLAG_32(FLAG_Z); - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(and, 8, re, .) -{ - uint ea = M68KMAKE_GET_EA_AY_8; - uint res = DX & m68ki_read_8(ea); - - FLAG_N = NFLAG_8(res); - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; - FLAG_Z = MASK_OUT_ABOVE_8(res); - - m68ki_write_8(ea, FLAG_Z); -} - - -M68KMAKE_OP(and, 16, re, .) -{ - uint ea = M68KMAKE_GET_EA_AY_16; - uint res = DX & m68ki_read_16(ea); - - FLAG_N = NFLAG_16(res); - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; - FLAG_Z = MASK_OUT_ABOVE_16(res); - - m68ki_write_16(ea, FLAG_Z); -} - - -M68KMAKE_OP(and, 32, re, .) -{ - uint ea = M68KMAKE_GET_EA_AY_32; - uint res = DX & m68ki_read_32(ea); - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; - - m68ki_write_32(ea, res); -} - - -M68KMAKE_OP(andi, 8, ., d) -{ - FLAG_Z = MASK_OUT_ABOVE_8(DY &= (OPER_I_8() | 0xffffff00)); - - FLAG_N = NFLAG_8(FLAG_Z); - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(andi, 8, ., .) -{ - uint src = OPER_I_8(); - uint ea = M68KMAKE_GET_EA_AY_8; - uint res = src & m68ki_read_8(ea); - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; - - m68ki_write_8(ea, res); -} - - -M68KMAKE_OP(andi, 16, ., d) -{ - FLAG_Z = MASK_OUT_ABOVE_16(DY &= (OPER_I_16() | 0xffff0000)); - - FLAG_N = NFLAG_16(FLAG_Z); - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(andi, 16, ., .) -{ - uint src = OPER_I_16(); - uint ea = M68KMAKE_GET_EA_AY_16; - uint res = src & m68ki_read_16(ea); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; - - m68ki_write_16(ea, res); -} - - -M68KMAKE_OP(andi, 32, ., d) -{ - FLAG_Z = DY &= (OPER_I_32()); - - FLAG_N = NFLAG_32(FLAG_Z); - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(andi, 32, ., .) -{ - uint src = OPER_I_32(); - uint ea = M68KMAKE_GET_EA_AY_32; - uint res = src & m68ki_read_32(ea); - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; - - m68ki_write_32(ea, res); -} - - -M68KMAKE_OP(andi, 16, toc, .) -{ - m68ki_set_ccr(m68ki_get_ccr() & OPER_I_8()); -} - - -M68KMAKE_OP(andi, 16, tos, .) -{ - if(FLAG_S) - { - uint src = OPER_I_16(); - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - m68ki_set_sr(m68ki_get_sr() & src); - return; - } - m68ki_exception_privilege_violation(); -} - - -M68KMAKE_OP(asr, 8, s, .) -{ - uint* r_dst = &DY; - uint shift = (((REG_IR >> 9) - 1) & 7) + 1; - uint src = MASK_OUT_ABOVE_8(*r_dst); - uint res = src >> shift; - - if(shift != 0) - USE_CYCLES(shift<> 9) - 1) & 7) + 1; - uint src = MASK_OUT_ABOVE_16(*r_dst); - uint res = src >> shift; - - if(shift != 0) - USE_CYCLES(shift<> 9) - 1) & 7) + 1; - uint src = *r_dst; - uint res = src >> shift; - - if(shift != 0) - USE_CYCLES(shift<> shift; - - if(shift != 0) - { - USE_CYCLES(shift<> shift; - - if(shift != 0) - { - USE_CYCLES(shift<> (shift - 1))<<8; - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - return; - } - - if(GET_MSB_16(src)) - { - *r_dst |= 0xffff; - FLAG_C = CFLAG_SET; - FLAG_X = XFLAG_SET; - FLAG_N = NFLAG_SET; - FLAG_Z = ZFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; - return; - } - - *r_dst &= 0xffff0000; - FLAG_C = CFLAG_CLEAR; - FLAG_X = XFLAG_CLEAR; - FLAG_N = NFLAG_CLEAR; - FLAG_Z = ZFLAG_SET; - FLAG_V = VFLAG_CLEAR; - return; - } - - FLAG_C = CFLAG_CLEAR; - FLAG_N = NFLAG_16(src); - FLAG_Z = src; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(asr, 32, r, .) -{ - uint* r_dst = &DY; - uint shift = DX & 0x3f; - uint src = *r_dst; - uint res = src >> shift; - - if(shift != 0) - { - USE_CYCLES(shift<> (shift - 1))<<8; - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - return; - } - - if(GET_MSB_32(src)) - { - *r_dst = 0xffffffff; - FLAG_C = CFLAG_SET; - FLAG_X = XFLAG_SET; - FLAG_N = NFLAG_SET; - FLAG_Z = ZFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; - return; - } - - *r_dst = 0; - FLAG_C = CFLAG_CLEAR; - FLAG_X = XFLAG_CLEAR; - FLAG_N = NFLAG_CLEAR; - FLAG_Z = ZFLAG_SET; - FLAG_V = VFLAG_CLEAR; - return; - } - - FLAG_C = CFLAG_CLEAR; - FLAG_N = NFLAG_32(src); - FLAG_Z = src; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(asr, 16, ., .) -{ - uint ea = M68KMAKE_GET_EA_AY_16; - uint src = m68ki_read_16(ea); - uint res = src >> 1; - - if(GET_MSB_16(src)) - res |= 0x8000; - - m68ki_write_16(ea, res); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = FLAG_X = src << 8; -} - - -M68KMAKE_OP(asl, 8, s, .) -{ - uint* r_dst = &DY; - uint shift = (((REG_IR >> 9) - 1) & 7) + 1; - uint src = MASK_OUT_ABOVE_8(*r_dst); - uint res = MASK_OUT_ABOVE_8(src << shift); - - if(shift != 0) - USE_CYCLES(shift<> 9) - 1) & 7) + 1; - uint src = MASK_OUT_ABOVE_16(*r_dst); - uint res = MASK_OUT_ABOVE_16(src << shift); - - if(shift != 0) - USE_CYCLES(shift<> (8-shift); - src &= m68ki_shift_16_table[shift + 1]; - FLAG_V = (!(src == 0 || src == m68ki_shift_16_table[shift + 1]))<<7; -} - - -M68KMAKE_OP(asl, 32, s, .) -{ - uint* r_dst = &DY; - uint shift = (((REG_IR >> 9) - 1) & 7) + 1; - uint src = *r_dst; - uint res = MASK_OUT_ABOVE_32(src << shift); - - if(shift != 0) - USE_CYCLES(shift<> (24-shift); - src &= m68ki_shift_32_table[shift + 1]; - FLAG_V = (!(src == 0 || src == m68ki_shift_32_table[shift + 1]))<<7; -} - - -M68KMAKE_OP(asl, 8, r, .) -{ - uint* r_dst = &DY; - uint shift = DX & 0x3f; - uint src = MASK_OUT_ABOVE_8(*r_dst); - uint res = MASK_OUT_ABOVE_8(src << shift); - - if(shift != 0) - { - USE_CYCLES(shift<> 8; - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - src &= m68ki_shift_16_table[shift + 1]; - FLAG_V = (!(src == 0 || src == m68ki_shift_16_table[shift + 1]))<<7; - return; - } - - *r_dst &= 0xffff0000; - FLAG_X = FLAG_C = ((shift == 16 ? src & 1 : 0))<<8; - FLAG_N = NFLAG_CLEAR; - FLAG_Z = ZFLAG_SET; - FLAG_V = (!(src == 0))<<7; - return; - } - - FLAG_C = CFLAG_CLEAR; - FLAG_N = NFLAG_16(src); - FLAG_Z = src; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(asl, 32, r, .) -{ - uint* r_dst = &DY; - uint shift = DX & 0x3f; - uint src = *r_dst; - uint res = MASK_OUT_ABOVE_32(src << shift); - - if(shift != 0) - { - USE_CYCLES(shift<> (32 - shift)) << 8; - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - src &= m68ki_shift_32_table[shift + 1]; - FLAG_V = (!(src == 0 || src == m68ki_shift_32_table[shift + 1]))<<7; - return; - } - - *r_dst = 0; - FLAG_X = FLAG_C = ((shift == 32 ? src & 1 : 0))<<8; - FLAG_N = NFLAG_CLEAR; - FLAG_Z = ZFLAG_SET; - FLAG_V = (!(src == 0))<<7; - return; - } - - FLAG_C = CFLAG_CLEAR; - FLAG_N = NFLAG_32(src); - FLAG_Z = src; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(asl, 16, ., .) -{ - uint ea = M68KMAKE_GET_EA_AY_16; - uint src = m68ki_read_16(ea); - uint res = MASK_OUT_ABOVE_16(src << 1); - - m68ki_write_16(ea, res); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_X = FLAG_C = src >> 7; - src &= 0xc000; - FLAG_V = (!(src == 0 || src == 0xc000))<<7; -} - - -M68KMAKE_OP(bcc, 8, ., .) -{ - if(M68KMAKE_CC) - { - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - m68ki_branch_8(MASK_OUT_ABOVE_8(REG_IR)); - return; - } - USE_CYCLES(CYC_BCC_NOTAKE_B); -} - - -M68KMAKE_OP(bcc, 16, ., .) -{ - if(M68KMAKE_CC) - { - uint offset = OPER_I_16(); - REG_PC -= 2; - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - m68ki_branch_16(offset); - return; - } - REG_PC += 2; - USE_CYCLES(CYC_BCC_NOTAKE_W); -} - - -M68KMAKE_OP(bcc, 32, ., .) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - if(M68KMAKE_CC) - { - uint offset = OPER_I_32(); - REG_PC -= 4; - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - m68ki_branch_32(offset); - return; - } - REG_PC += 4; - return; - } - else - { - if(M68KMAKE_CC) - { - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - m68ki_branch_8(MASK_OUT_ABOVE_8(REG_IR)); - return; - } - USE_CYCLES(CYC_BCC_NOTAKE_B); - } -} - - -M68KMAKE_OP(bchg, 32, r, d) -{ - uint* r_dst = &DY; - uint mask = 1 << (DX & 0x1f); - - FLAG_Z = *r_dst & mask; - *r_dst ^= mask; -} - - -M68KMAKE_OP(bchg, 8, r, .) -{ - uint ea = M68KMAKE_GET_EA_AY_8; - uint src = m68ki_read_8(ea); - uint mask = 1 << (DX & 7); - - FLAG_Z = src & mask; - m68ki_write_8(ea, src ^ mask); -} - - -M68KMAKE_OP(bchg, 32, s, d) -{ - uint* r_dst = &DY; - uint mask = 1 << (OPER_I_8() & 0x1f); - - FLAG_Z = *r_dst & mask; - *r_dst ^= mask; -} - - -M68KMAKE_OP(bchg, 8, s, .) -{ - uint mask = 1 << (OPER_I_8() & 7); - uint ea = M68KMAKE_GET_EA_AY_8; - uint src = m68ki_read_8(ea); - - FLAG_Z = src & mask; - m68ki_write_8(ea, src ^ mask); -} - - -M68KMAKE_OP(bclr, 32, r, d) -{ - uint* r_dst = &DY; - uint mask = 1 << (DX & 0x1f); - - FLAG_Z = *r_dst & mask; - *r_dst &= ~mask; -} - - -M68KMAKE_OP(bclr, 8, r, .) -{ - uint ea = M68KMAKE_GET_EA_AY_8; - uint src = m68ki_read_8(ea); - uint mask = 1 << (DX & 7); - - FLAG_Z = src & mask; - m68ki_write_8(ea, src & ~mask); -} - - -M68KMAKE_OP(bclr, 32, s, d) -{ - uint* r_dst = &DY; - uint mask = 1 << (OPER_I_8() & 0x1f); - - FLAG_Z = *r_dst & mask; - *r_dst &= ~mask; -} - - -M68KMAKE_OP(bclr, 8, s, .) -{ - uint mask = 1 << (OPER_I_8() & 7); - uint ea = M68KMAKE_GET_EA_AY_8; - uint src = m68ki_read_8(ea); - - FLAG_Z = src & mask; - m68ki_write_8(ea, src & ~mask); -} - - -M68KMAKE_OP(bfchg, 32, ., d) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint word2 = OPER_I_16(); - uint offset = (word2>>6)&31; - uint width = word2; - uint* data = &DY; - uint64 mask; - - - if(BIT_B(word2)) - offset = REG_D[offset&7]; - if(BIT_5(word2)) - width = REG_D[width&7]; - - offset &= 31; - width = ((width-1) & 31) + 1; - - mask = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); - mask = ROR_32(mask, offset); - - FLAG_N = NFLAG_32(*data<>6)&31; - uint width = word2; - uint mask_base; - uint data_long; - uint mask_long; - uint data_byte = 0; - uint mask_byte = 0; - uint ea = M68KMAKE_GET_EA_AY_8; - - - if(BIT_B(word2)) - offset = MAKE_INT_32(REG_D[offset&7]); - if(BIT_5(word2)) - width = REG_D[width&7]; - - /* Offset is signed so we have to use ugly math =( */ - ea += offset / 8; - offset %= 8; - if(offset < 0) - { - offset += 8; - ea--; - } - width = ((width-1) & 31) + 1; - - mask_base = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); - mask_long = mask_base >> offset; - - data_long = m68ki_read_32(ea); - FLAG_N = NFLAG_32(data_long << offset); - FLAG_Z = data_long & mask_long; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - - m68ki_write_32(ea, data_long ^ mask_long); - - if((width + offset) > 32) - { - mask_byte = MASK_OUT_ABOVE_8(mask_base); - data_byte = m68ki_read_8(ea+4); - FLAG_Z |= (data_byte & mask_byte); - m68ki_write_8(ea+4, data_byte ^ mask_byte); - } - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(bfclr, 32, ., d) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint word2 = OPER_I_16(); - uint offset = (word2>>6)&31; - uint width = word2; - uint* data = &DY; - uint64 mask; - - - if(BIT_B(word2)) - offset = REG_D[offset&7]; - if(BIT_5(word2)) - width = REG_D[width&7]; - - - offset &= 31; - width = ((width-1) & 31) + 1; - - - mask = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); - mask = ROR_32(mask, offset); - - FLAG_N = NFLAG_32(*data<>6)&31; - uint width = word2; - uint mask_base; - uint data_long; - uint mask_long; - uint data_byte = 0; - uint mask_byte = 0; - uint ea = M68KMAKE_GET_EA_AY_8; - - - if(BIT_B(word2)) - offset = MAKE_INT_32(REG_D[offset&7]); - if(BIT_5(word2)) - width = REG_D[width&7]; - - /* Offset is signed so we have to use ugly math =( */ - ea += offset / 8; - offset %= 8; - if(offset < 0) - { - offset += 8; - ea--; - } - width = ((width-1) & 31) + 1; - - mask_base = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); - mask_long = mask_base >> offset; - - data_long = m68ki_read_32(ea); - FLAG_N = NFLAG_32(data_long << offset); - FLAG_Z = data_long & mask_long; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - - m68ki_write_32(ea, data_long & ~mask_long); - - if((width + offset) > 32) - { - mask_byte = MASK_OUT_ABOVE_8(mask_base); - data_byte = m68ki_read_8(ea+4); - FLAG_Z |= (data_byte & mask_byte); - m68ki_write_8(ea+4, data_byte & ~mask_byte); - } - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(bfexts, 32, ., d) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint word2 = OPER_I_16(); - uint offset = (word2>>6)&31; - uint width = word2; - uint64 data = DY; - - - if(BIT_B(word2)) - offset = REG_D[offset&7]; - if(BIT_5(word2)) - width = REG_D[width&7]; - - offset &= 31; - width = ((width-1) & 31) + 1; - - data = ROL_32(data, offset); - FLAG_N = NFLAG_32(data); - data = MAKE_INT_32(data) >> (32 - width); - - FLAG_Z = data; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - - REG_D[(word2>>12)&7] = data; - - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(bfexts, 32, ., .) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint word2 = OPER_I_16(); - sint offset = (word2>>6)&31; - uint width = word2; - uint data; - uint ea = M68KMAKE_GET_EA_AY_8; - - - if(BIT_B(word2)) - offset = MAKE_INT_32(REG_D[offset&7]); - if(BIT_5(word2)) - width = REG_D[width&7]; - - /* Offset is signed so we have to use ugly math =( */ - ea += offset / 8; - offset %= 8; - if(offset < 0) - { - offset += 8; - ea--; - } - width = ((width-1) & 31) + 1; - - data = m68ki_read_32(ea); - - data = MASK_OUT_ABOVE_32(data< 32) - data |= (m68ki_read_8(ea+4) << offset) >> 8; - - FLAG_N = NFLAG_32(data); - data = MAKE_INT_32(data) >> (32 - width); - - FLAG_Z = data; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - - REG_D[(word2 >> 12) & 7] = data; - - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(bfextu, 32, ., d) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint word2 = OPER_I_16(); - uint offset = (word2>>6)&31; - uint width = word2; - uint64 data = DY; - - - if(BIT_B(word2)) - offset = REG_D[offset&7]; - if(BIT_5(word2)) - width = REG_D[width&7]; - - offset &= 31; - width = ((width-1) & 31) + 1; - - data = ROL_32(data, offset); - FLAG_N = NFLAG_32(data); - data >>= 32 - width; - - FLAG_Z = data; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - - REG_D[(word2>>12)&7] = data; - - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(bfextu, 32, ., .) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint word2 = OPER_I_16(); - sint offset = (word2>>6)&31; - uint width = word2; - uint data; - uint ea = M68KMAKE_GET_EA_AY_8; - - - if(BIT_B(word2)) - offset = MAKE_INT_32(REG_D[offset&7]); - if(BIT_5(word2)) - width = REG_D[width&7]; - - /* Offset is signed so we have to use ugly math =( */ - ea += offset / 8; - offset %= 8; - if(offset < 0) - { - offset += 8; - ea--; - } - width = ((width-1) & 31) + 1; - - data = m68ki_read_32(ea); - data = MASK_OUT_ABOVE_32(data< 32) - data |= (m68ki_read_8(ea+4) << offset) >> 8; - - FLAG_N = NFLAG_32(data); - data >>= (32 - width); - - FLAG_Z = data; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - - REG_D[(word2 >> 12) & 7] = data; - - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(bfffo, 32, ., d) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint word2 = OPER_I_16(); - uint offset = (word2>>6)&31; - uint width = word2; - uint64 data = DY; - uint bit; - - - if(BIT_B(word2)) - offset = REG_D[offset&7]; - if(BIT_5(word2)) - width = REG_D[width&7]; - - offset &= 31; - width = ((width-1) & 31) + 1; - - data = ROL_32(data, offset); - FLAG_N = NFLAG_32(data); - data >>= 32 - width; - - FLAG_Z = data; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - - for(bit = 1<<(width-1);bit && !(data & bit);bit>>= 1) - offset++; - - REG_D[(word2>>12)&7] = offset; - - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(bfffo, 32, ., .) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint word2 = OPER_I_16(); - sint offset = (word2>>6)&31; - sint local_offset; - uint width = word2; - uint data; - uint bit; - uint ea = M68KMAKE_GET_EA_AY_8; - - - if(BIT_B(word2)) - offset = MAKE_INT_32(REG_D[offset&7]); - if(BIT_5(word2)) - width = REG_D[width&7]; - - /* Offset is signed so we have to use ugly math =( */ - ea += offset / 8; - local_offset = offset % 8; - if(local_offset < 0) - { - local_offset += 8; - ea--; - } - width = ((width-1) & 31) + 1; - - data = m68ki_read_32(ea); - data = MASK_OUT_ABOVE_32(data< 32) - data |= (m68ki_read_8(ea+4) << local_offset) >> 8; - - FLAG_N = NFLAG_32(data); - data >>= (32 - width); - - FLAG_Z = data; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - - for(bit = 1<<(width-1);bit && !(data & bit);bit>>= 1) - offset++; - - REG_D[(word2>>12)&7] = offset; - - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(bfins, 32, ., d) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint word2 = OPER_I_16(); - uint offset = (word2>>6)&31; - uint width = word2; - uint* data = &DY; - uint64 mask; - uint64 insert = REG_D[(word2>>12)&7]; - - - if(BIT_B(word2)) - offset = REG_D[offset&7]; - if(BIT_5(word2)) - width = REG_D[width&7]; - - - offset &= 31; - width = ((width-1) & 31) + 1; - - - mask = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); - mask = ROR_32(mask, offset); - - insert = MASK_OUT_ABOVE_32(insert << (32 - width)); - FLAG_N = NFLAG_32(insert); - FLAG_Z = insert; - insert = ROR_32(insert, offset); - - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - - *data &= ~mask; - *data |= insert; - - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(bfins, 32, ., .) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint word2 = OPER_I_16(); - sint offset = (word2>>6)&31; - uint width = word2; - uint insert_base = REG_D[(word2>>12)&7]; - uint insert_long; - uint insert_byte; - uint mask_base; - uint data_long; - uint mask_long; - uint data_byte = 0; - uint mask_byte = 0; - uint ea = M68KMAKE_GET_EA_AY_8; - - - if(BIT_B(word2)) - offset = MAKE_INT_32(REG_D[offset&7]); - if(BIT_5(word2)) - width = REG_D[width&7]; - - /* Offset is signed so we have to use ugly math =( */ - ea += offset / 8; - offset %= 8; - if(offset < 0) - { - offset += 8; - ea--; - } - width = ((width-1) & 31) + 1; - - mask_base = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); - mask_long = mask_base >> offset; - - insert_base = MASK_OUT_ABOVE_32(insert_base << (32 - width)); - FLAG_N = NFLAG_32(insert_base); - FLAG_Z = insert_base; - insert_long = insert_base >> offset; - - data_long = m68ki_read_32(ea); - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - - m68ki_write_32(ea, (data_long & ~mask_long) | insert_long); - - if((width + offset) > 32) - { - mask_byte = MASK_OUT_ABOVE_8(mask_base); - insert_byte = MASK_OUT_ABOVE_8(insert_base); - data_byte = m68ki_read_8(ea+4); - FLAG_Z |= (data_byte & mask_byte); - m68ki_write_8(ea+4, (data_byte & ~mask_byte) | insert_byte); - } - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(bfset, 32, ., d) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint word2 = OPER_I_16(); - uint offset = (word2>>6)&31; - uint width = word2; - uint* data = &DY; - uint64 mask; - - - if(BIT_B(word2)) - offset = REG_D[offset&7]; - if(BIT_5(word2)) - width = REG_D[width&7]; - - - offset &= 31; - width = ((width-1) & 31) + 1; - - - mask = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); - mask = ROR_32(mask, offset); - - FLAG_N = NFLAG_32(*data<>6)&31; - uint width = word2; - uint mask_base; - uint data_long; - uint mask_long; - uint data_byte = 0; - uint mask_byte = 0; - uint ea = M68KMAKE_GET_EA_AY_8; - - - if(BIT_B(word2)) - offset = MAKE_INT_32(REG_D[offset&7]); - if(BIT_5(word2)) - width = REG_D[width&7]; - - /* Offset is signed so we have to use ugly math =( */ - ea += offset / 8; - offset %= 8; - if(offset < 0) - { - offset += 8; - ea--; - } - width = ((width-1) & 31) + 1; - - - mask_base = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); - mask_long = mask_base >> offset; - - data_long = m68ki_read_32(ea); - FLAG_N = NFLAG_32(data_long << offset); - FLAG_Z = data_long & mask_long; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - - m68ki_write_32(ea, data_long | mask_long); - - if((width + offset) > 32) - { - mask_byte = MASK_OUT_ABOVE_8(mask_base); - data_byte = m68ki_read_8(ea+4); - FLAG_Z |= (data_byte & mask_byte); - m68ki_write_8(ea+4, data_byte | mask_byte); - } - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(bftst, 32, ., d) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint word2 = OPER_I_16(); - uint offset = (word2>>6)&31; - uint width = word2; - uint* data = &DY; - uint64 mask; - - - if(BIT_B(word2)) - offset = REG_D[offset&7]; - if(BIT_5(word2)) - width = REG_D[width&7]; - - - offset &= 31; - width = ((width-1) & 31) + 1; - - - mask = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); - mask = ROR_32(mask, offset); - - FLAG_N = NFLAG_32(*data<>6)&31; - uint width = word2; - uint mask_base; - uint data_long; - uint mask_long; - uint data_byte = 0; - uint mask_byte = 0; - uint ea = M68KMAKE_GET_EA_AY_8; - - if(BIT_B(word2)) - offset = MAKE_INT_32(REG_D[offset&7]); - if(BIT_5(word2)) - width = REG_D[width&7]; - - /* Offset is signed so we have to use ugly math =( */ - ea += offset / 8; - offset %= 8; - if(offset < 0) - { - offset += 8; - ea--; - } - width = ((width-1) & 31) + 1; - - - mask_base = MASK_OUT_ABOVE_32(0xffffffff << (32 - width)); - mask_long = mask_base >> offset; - - data_long = m68ki_read_32(ea); - FLAG_N = ((data_long & (0x80000000 >> offset))<>24; - FLAG_Z = data_long & mask_long; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - - if((width + offset) > 32) - { - mask_byte = MASK_OUT_ABOVE_8(mask_base); - data_byte = m68ki_read_8(ea+4); - FLAG_Z |= (data_byte & mask_byte); - } - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(bkpt, 0, ., .) -{ - if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) - { - m68ki_bkpt_ack(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE) ? REG_IR & 7 : 0); /* auto-disable (see m68kcpu.h) */ - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(bra, 8, ., .) -{ - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - m68ki_branch_8(MASK_OUT_ABOVE_8(REG_IR)); - if(REG_PC == REG_PPC) - USE_ALL_CYCLES(); -} - - -M68KMAKE_OP(bra, 16, ., .) -{ - uint offset = OPER_I_16(); - REG_PC -= 2; - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - m68ki_branch_16(offset); - if(REG_PC == REG_PPC) - USE_ALL_CYCLES(); -} - - -M68KMAKE_OP(bra, 32, ., .) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint offset = OPER_I_32(); - REG_PC -= 4; - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - m68ki_branch_32(offset); - if(REG_PC == REG_PPC) - USE_ALL_CYCLES(); - return; - } - else - { - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - m68ki_branch_8(MASK_OUT_ABOVE_8(REG_IR)); - if(REG_PC == REG_PPC) - USE_ALL_CYCLES(); - } -} - - -M68KMAKE_OP(bset, 32, r, d) -{ - uint* r_dst = &DY; - uint mask = 1 << (DX & 0x1f); - - FLAG_Z = *r_dst & mask; - *r_dst |= mask; -} - - -M68KMAKE_OP(bset, 8, r, .) -{ - uint ea = M68KMAKE_GET_EA_AY_8; - uint src = m68ki_read_8(ea); - uint mask = 1 << (DX & 7); - - FLAG_Z = src & mask; - m68ki_write_8(ea, src | mask); -} - - -M68KMAKE_OP(bset, 32, s, d) -{ - uint* r_dst = &DY; - uint mask = 1 << (OPER_I_8() & 0x1f); - - FLAG_Z = *r_dst & mask; - *r_dst |= mask; -} - - -M68KMAKE_OP(bset, 8, s, .) -{ - uint mask = 1 << (OPER_I_8() & 7); - uint ea = M68KMAKE_GET_EA_AY_8; - uint src = m68ki_read_8(ea); - - FLAG_Z = src & mask; - m68ki_write_8(ea, src | mask); -} - - -M68KMAKE_OP(bsr, 8, ., .) -{ - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - m68ki_push_32(REG_PC); - m68ki_branch_8(MASK_OUT_ABOVE_8(REG_IR)); -} - - -M68KMAKE_OP(bsr, 16, ., .) -{ - uint offset = OPER_I_16(); - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - m68ki_push_32(REG_PC); - REG_PC -= 2; - m68ki_branch_16(offset); -} - - -M68KMAKE_OP(bsr, 32, ., .) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint offset = OPER_I_32(); - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - m68ki_push_32(REG_PC); - REG_PC -= 4; - m68ki_branch_32(offset); - return; - } - else - { - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - m68ki_push_32(REG_PC); - m68ki_branch_8(MASK_OUT_ABOVE_8(REG_IR)); - } -} - - -M68KMAKE_OP(btst, 32, r, d) -{ - FLAG_Z = DY & (1 << (DX & 0x1f)); -} - - -M68KMAKE_OP(btst, 8, r, .) -{ - FLAG_Z = M68KMAKE_GET_OPER_AY_8 & (1 << (DX & 7)); -} - - -M68KMAKE_OP(btst, 32, s, d) -{ - FLAG_Z = DY & (1 << (OPER_I_8() & 0x1f)); -} - - -M68KMAKE_OP(btst, 8, s, .) -{ - uint bit = OPER_I_8() & 7; - - FLAG_Z = M68KMAKE_GET_OPER_AY_8 & (1 << bit); -} - - -M68KMAKE_OP(callm, 32, ., .) -{ - /* note: watch out for pcrelative modes */ - if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) - { - uint ea = M68KMAKE_GET_EA_AY_32; - - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - REG_PC += 2; -(void)ea; /* just to avoid an 'unused variable' warning */ - M68K_DO_LOG((M68K_LOG_FILEHANDLE "%s at %08x: called unimplemented instruction %04x (%s)\n", - m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PC - 2), REG_IR, - m68k_disassemble_quick(ADDRESS_68K(REG_PC - 2)))); - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(cas, 8, ., .) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint word2 = OPER_I_16(); - uint ea = M68KMAKE_GET_EA_AY_8; - uint dest = m68ki_read_8(ea); - uint* compare = ®_D[word2 & 7]; - uint res = dest - MASK_OUT_ABOVE_8(*compare); - - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - FLAG_N = NFLAG_8(res); - FLAG_Z = MASK_OUT_ABOVE_8(res); - FLAG_V = VFLAG_SUB_8(*compare, dest, res); - FLAG_C = CFLAG_8(res); - - if(COND_NE()) - *compare = MASK_OUT_BELOW_8(*compare) | dest; - else - { - USE_CYCLES(3); - m68ki_write_8(ea, MASK_OUT_ABOVE_8(REG_D[(word2 >> 6) & 7])); - } - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(cas, 16, ., .) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint word2 = OPER_I_16(); - uint ea = M68KMAKE_GET_EA_AY_16; - uint dest = m68ki_read_16(ea); - uint* compare = ®_D[word2 & 7]; - uint res = dest - MASK_OUT_ABOVE_16(*compare); - - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - FLAG_N = NFLAG_16(res); - FLAG_Z = MASK_OUT_ABOVE_16(res); - FLAG_V = VFLAG_SUB_16(*compare, dest, res); - FLAG_C = CFLAG_16(res); - - if(COND_NE()) - *compare = MASK_OUT_BELOW_16(*compare) | dest; - else - { - USE_CYCLES(3); - m68ki_write_16(ea, MASK_OUT_ABOVE_16(REG_D[(word2 >> 6) & 7])); - } - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(cas, 32, ., .) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint word2 = OPER_I_16(); - uint ea = M68KMAKE_GET_EA_AY_32; - uint dest = m68ki_read_32(ea); - uint* compare = ®_D[word2 & 7]; - uint res = dest - *compare; - - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - FLAG_N = NFLAG_32(res); - FLAG_Z = MASK_OUT_ABOVE_32(res); - FLAG_V = VFLAG_SUB_32(*compare, dest, res); - FLAG_C = CFLAG_SUB_32(*compare, dest, res); - - if(COND_NE()) - *compare = dest; - else - { - USE_CYCLES(3); - m68ki_write_32(ea, REG_D[(word2 >> 6) & 7]); - } - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(cas2, 16, ., .) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint word2 = OPER_I_32(); - uint* compare1 = ®_D[(word2 >> 16) & 7]; - uint ea1 = REG_DA[(word2 >> 28) & 15]; - uint dest1 = m68ki_read_16(ea1); - uint res1 = dest1 - MASK_OUT_ABOVE_16(*compare1); - uint* compare2 = ®_D[word2 & 7]; - uint ea2 = REG_DA[(word2 >> 12) & 15]; - uint dest2 = m68ki_read_16(ea2); - uint res2; - - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - FLAG_N = NFLAG_16(res1); - FLAG_Z = MASK_OUT_ABOVE_16(res1); - FLAG_V = VFLAG_SUB_16(*compare1, dest1, res1); - FLAG_C = CFLAG_16(res1); - - if(COND_EQ()) - { - res2 = dest2 - MASK_OUT_ABOVE_16(*compare2); - - FLAG_N = NFLAG_16(res2); - FLAG_Z = MASK_OUT_ABOVE_16(res2); - FLAG_V = VFLAG_SUB_16(*compare2, dest2, res2); - FLAG_C = CFLAG_16(res2); - - if(COND_EQ()) - { - USE_CYCLES(3); - m68ki_write_16(ea1, REG_D[(word2 >> 22) & 7]); - m68ki_write_16(ea2, REG_D[(word2 >> 6) & 7]); - return; - } - } - *compare1 = BIT_1F(word2) ? (uint)MAKE_INT_16(dest1) : MASK_OUT_BELOW_16(*compare1) | dest1; - *compare2 = BIT_F(word2) ? (uint)MAKE_INT_16(dest2) : MASK_OUT_BELOW_16(*compare2) | dest2; - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(cas2, 32, ., .) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint word2 = OPER_I_32(); - uint* compare1 = ®_D[(word2 >> 16) & 7]; - uint ea1 = REG_DA[(word2 >> 28) & 15]; - uint dest1 = m68ki_read_32(ea1); - uint res1 = dest1 - *compare1; - uint* compare2 = ®_D[word2 & 7]; - uint ea2 = REG_DA[(word2 >> 12) & 15]; - uint dest2 = m68ki_read_32(ea2); - uint res2; - - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - FLAG_N = NFLAG_32(res1); - FLAG_Z = MASK_OUT_ABOVE_32(res1); - FLAG_V = VFLAG_SUB_32(*compare1, dest1, res1); - FLAG_C = CFLAG_SUB_32(*compare1, dest1, res1); - - if(COND_EQ()) - { - res2 = dest2 - *compare2; - - FLAG_N = NFLAG_32(res2); - FLAG_Z = MASK_OUT_ABOVE_32(res2); - FLAG_V = VFLAG_SUB_32(*compare2, dest2, res2); - FLAG_C = CFLAG_SUB_32(*compare2, dest2, res2); - - if(COND_EQ()) - { - USE_CYCLES(3); - m68ki_write_32(ea1, REG_D[(word2 >> 22) & 7]); - m68ki_write_32(ea2, REG_D[(word2 >> 6) & 7]); - return; - } - } - *compare1 = dest1; - *compare2 = dest2; - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(chk, 16, ., d) -{ - sint src = MAKE_INT_16(DX); - sint bound = MAKE_INT_16(DY); - - FLAG_Z = ZFLAG_16(src); /* Undocumented */ - FLAG_V = VFLAG_CLEAR; /* Undocumented */ - FLAG_C = CFLAG_CLEAR; /* Undocumented */ - - if(src >= 0 && src <= bound) - { - return; - } - FLAG_N = (src < 0)<<7; - m68ki_exception_trap(EXCEPTION_CHK); -} - - -M68KMAKE_OP(chk, 16, ., .) -{ - sint src = MAKE_INT_16(DX); - sint bound = MAKE_INT_16(M68KMAKE_GET_OPER_AY_16); - - FLAG_Z = ZFLAG_16(src); /* Undocumented */ - FLAG_V = VFLAG_CLEAR; /* Undocumented */ - FLAG_C = CFLAG_CLEAR; /* Undocumented */ - - if(src >= 0 && src <= bound) - { - return; - } - FLAG_N = (src < 0)<<7; - m68ki_exception_trap(EXCEPTION_CHK); -} - - -M68KMAKE_OP(chk, 32, ., d) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - sint src = MAKE_INT_32(DX); - sint bound = MAKE_INT_32(DY); - - FLAG_Z = ZFLAG_32(src); /* Undocumented */ - FLAG_V = VFLAG_CLEAR; /* Undocumented */ - FLAG_C = CFLAG_CLEAR; /* Undocumented */ - - if(src >= 0 && src <= bound) - { - return; - } - FLAG_N = (src < 0)<<7; - m68ki_exception_trap(EXCEPTION_CHK); - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(chk, 32, ., .) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - sint src = MAKE_INT_32(DX); - sint bound = MAKE_INT_32(M68KMAKE_GET_OPER_AY_32); - - FLAG_Z = ZFLAG_32(src); /* Undocumented */ - FLAG_V = VFLAG_CLEAR; /* Undocumented */ - FLAG_C = CFLAG_CLEAR; /* Undocumented */ - - if(src >= 0 && src <= bound) - { - return; - } - FLAG_N = (src < 0)<<7; - m68ki_exception_trap(EXCEPTION_CHK); - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(chk2cmp2, 8, ., pcdi) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint word2 = OPER_I_16(); - sint compare = REG_DA[(word2 >> 12) & 15]&0xff; - uint ea = EA_PCDI_8(); - sint lower_bound = m68ki_read_pcrel_8(ea); - sint upper_bound = m68ki_read_pcrel_8(ea + 1); - - if(!BIT_F(word2)) - compare = (int32)(int8)compare; - - FLAG_Z = !((upper_bound==compare) || (lower_bound==compare)); // JFF: | => || - - FLAG_C = (lower_bound <= upper_bound ? compare < lower_bound || compare > upper_bound : compare > upper_bound || compare < lower_bound) << 8; - - if(COND_CS() && BIT_B(word2)) - m68ki_exception_trap(EXCEPTION_CHK); - return; - } - - - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(chk2cmp2, 8, ., pcix) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint word2 = OPER_I_16(); - sint compare = REG_DA[(word2 >> 12) & 15]&0xff; - uint ea = EA_PCIX_8(); - sint lower_bound = m68ki_read_pcrel_8(ea); - sint upper_bound = m68ki_read_pcrel_8(ea + 1); - - if(!BIT_F(word2)) - compare = (int32)(int8)compare; - FLAG_Z = !((upper_bound==compare) || (lower_bound==compare)); // JFF: | => ||, faster operation short circuits - - FLAG_C = (lower_bound <= upper_bound ? compare < lower_bound || compare > upper_bound : compare > upper_bound || compare < lower_bound) << 8; - - if(COND_CS() && BIT_B(word2)) - m68ki_exception_trap(EXCEPTION_CHK); - return; - - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(chk2cmp2, 8, ., .) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint word2 = OPER_I_16(); - sint compare = REG_DA[(word2 >> 12) & 15]&0xff; - uint ea = M68KMAKE_GET_EA_AY_8; - sint lower_bound = (int8)m68ki_read_8(ea); - sint upper_bound = (int8)m68ki_read_8(ea + 1); - - if(!BIT_F(word2)) - compare = (int32)(int8)compare; - - FLAG_Z = !((upper_bound==compare) || (lower_bound==compare)); // JFF: | => || - - FLAG_C = (lower_bound <= upper_bound ? compare < lower_bound || compare > upper_bound : compare > upper_bound || compare < lower_bound) << 8; - - if(COND_CS() && BIT_B(word2)) - m68ki_exception_trap(EXCEPTION_CHK); - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(chk2cmp2, 16, ., pcdi) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint word2 = OPER_I_16(); - sint compare = REG_DA[(word2 >> 12) & 15]&0xffff; - uint ea = EA_PCDI_16(); - sint lower_bound = (int16)m68ki_read_pcrel_16(ea); - sint upper_bound = (int16)m68ki_read_pcrel_16(ea + 2); - - if(!BIT_F(word2)) - compare = (int32)(int16)compare; - FLAG_Z = !((upper_bound==compare) || (lower_bound==compare)); // JFF: | => || - - FLAG_C = (lower_bound <= upper_bound ? compare < lower_bound || compare > upper_bound : compare > upper_bound || compare < lower_bound) << 8; - - if(COND_CS() && BIT_B(word2)) - m68ki_exception_trap(EXCEPTION_CHK); - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(chk2cmp2, 16, ., pcix) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint word2 = OPER_I_16(); - sint compare = REG_DA[(word2 >> 12) & 15]&0xffff; - uint ea = EA_PCIX_16(); - sint lower_bound = (int16)m68ki_read_pcrel_16(ea); - sint upper_bound = (int16)m68ki_read_pcrel_16(ea + 2); - - if(!BIT_F(word2)) - compare = (int32)(int16)compare; - FLAG_Z = !((upper_bound==compare) || (lower_bound==compare)); // JFF: | => || - - FLAG_C = (lower_bound <= upper_bound ? compare < lower_bound || compare > upper_bound : compare > upper_bound || compare < lower_bound) << 8; - - if(COND_CS() && BIT_B(word2)) - m68ki_exception_trap(EXCEPTION_CHK); - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(chk2cmp2, 16, ., .) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint word2 = OPER_I_16(); - sint compare = REG_DA[(word2 >> 12) & 15]&0xffff; - uint ea = M68KMAKE_GET_EA_AY_16; - sint lower_bound = (int16)m68ki_read_16(ea); - sint upper_bound = (int16)m68ki_read_16(ea + 2); - - if(!BIT_F(word2)) - compare = (int32)(int16)compare; - FLAG_Z = !((upper_bound==compare) || (lower_bound==compare)); // JFF: | => || - - FLAG_C = (lower_bound <= upper_bound ? compare < lower_bound || compare > upper_bound : compare > upper_bound || compare < lower_bound) << 8; - - if(COND_CS() && BIT_B(word2)) - m68ki_exception_trap(EXCEPTION_CHK); - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(chk2cmp2, 32, ., pcdi) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint word2 = OPER_I_16(); - sint compare = REG_DA[(word2 >> 12) & 15]; - uint ea = EA_PCDI_32(); - sint lower_bound = m68ki_read_pcrel_32(ea); - sint upper_bound = m68ki_read_pcrel_32(ea + 4); - - FLAG_Z = !((upper_bound==compare) || (lower_bound==compare)); // JFF: | => || - - FLAG_C = (lower_bound <= upper_bound ? compare < lower_bound || compare > upper_bound : compare > upper_bound || compare < lower_bound) << 8; - - if(COND_CS() && BIT_B(word2)) - m68ki_exception_trap(EXCEPTION_CHK); - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(chk2cmp2, 32, ., pcix) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint word2 = OPER_I_16(); - sint compare = REG_DA[(word2 >> 12) & 15]; - uint ea = EA_PCIX_32(); - sint lower_bound = m68ki_read_32(ea); - sint upper_bound = m68ki_read_32(ea + 4); - - FLAG_Z = !((upper_bound==compare) || (lower_bound==compare)); // JFF: | => || - - FLAG_C = (lower_bound <= upper_bound ? compare < lower_bound || compare > upper_bound : compare > upper_bound || compare < lower_bound) << 8; - - if(COND_CS() && BIT_B(word2)) - m68ki_exception_trap(EXCEPTION_CHK); - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(chk2cmp2, 32, ., .) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint word2 = OPER_I_16(); - // JFF changed the logic. chk2/cmp2 uses signed values, not unsigned - sint compare = REG_DA[(word2 >> 12) & 15]; - uint ea = M68KMAKE_GET_EA_AY_32; - sint lower_bound = m68ki_read_32(ea); - sint upper_bound = m68ki_read_32(ea + 4); - - FLAG_Z = !((upper_bound==compare) || (lower_bound==compare)); // JFF: | => || - - FLAG_C = (lower_bound <= upper_bound ? compare < lower_bound || compare > upper_bound : compare > upper_bound || compare < lower_bound) << 8; - - if(COND_CS() && BIT_B(word2)) - m68ki_exception_trap(EXCEPTION_CHK); - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(clr, 8, ., d) -{ - DY &= 0xffffff00; - - FLAG_N = NFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - FLAG_Z = ZFLAG_SET; -} - - -M68KMAKE_OP(clr, 8, ., .) -{ - m68ki_write_8(M68KMAKE_GET_EA_AY_8, 0); - - FLAG_N = NFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - FLAG_Z = ZFLAG_SET; -} - - -M68KMAKE_OP(clr, 16, ., d) -{ - DY &= 0xffff0000; - - FLAG_N = NFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - FLAG_Z = ZFLAG_SET; -} - - -M68KMAKE_OP(clr, 16, ., .) -{ - m68ki_write_16(M68KMAKE_GET_EA_AY_16, 0); - - FLAG_N = NFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - FLAG_Z = ZFLAG_SET; -} - - -M68KMAKE_OP(clr, 32, ., d) -{ - DY = 0; - - FLAG_N = NFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - FLAG_Z = ZFLAG_SET; -} - - -M68KMAKE_OP(clr, 32, ., .) -{ - m68ki_write_32(M68KMAKE_GET_EA_AY_32, 0); - - FLAG_N = NFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - FLAG_Z = ZFLAG_SET; -} - - -M68KMAKE_OP(cmp, 8, ., d) -{ - uint src = MASK_OUT_ABOVE_8(DY); - uint dst = MASK_OUT_ABOVE_8(DX); - uint res = dst - src; - - FLAG_N = NFLAG_8(res); - FLAG_Z = MASK_OUT_ABOVE_8(res); - FLAG_V = VFLAG_SUB_8(src, dst, res); - FLAG_C = CFLAG_8(res); -} - - -M68KMAKE_OP(cmp, 8, ., .) -{ - uint src = M68KMAKE_GET_OPER_AY_8; - uint dst = MASK_OUT_ABOVE_8(DX); - uint res = dst - src; - - FLAG_N = NFLAG_8(res); - FLAG_Z = MASK_OUT_ABOVE_8(res); - FLAG_V = VFLAG_SUB_8(src, dst, res); - FLAG_C = CFLAG_8(res); -} - - -M68KMAKE_OP(cmp, 16, ., d) -{ - uint src = MASK_OUT_ABOVE_16(DY); - uint dst = MASK_OUT_ABOVE_16(DX); - uint res = dst - src; - - FLAG_N = NFLAG_16(res); - FLAG_Z = MASK_OUT_ABOVE_16(res); - FLAG_V = VFLAG_SUB_16(src, dst, res); - FLAG_C = CFLAG_16(res); -} - - -M68KMAKE_OP(cmp, 16, ., a) -{ - uint src = MASK_OUT_ABOVE_16(AY); - uint dst = MASK_OUT_ABOVE_16(DX); - uint res = dst - src; - - FLAG_N = NFLAG_16(res); - FLAG_Z = MASK_OUT_ABOVE_16(res); - FLAG_V = VFLAG_SUB_16(src, dst, res); - FLAG_C = CFLAG_16(res); -} - - -M68KMAKE_OP(cmp, 16, ., .) -{ - uint src = M68KMAKE_GET_OPER_AY_16; - uint dst = MASK_OUT_ABOVE_16(DX); - uint res = dst - src; - - FLAG_N = NFLAG_16(res); - FLAG_Z = MASK_OUT_ABOVE_16(res); - FLAG_V = VFLAG_SUB_16(src, dst, res); - FLAG_C = CFLAG_16(res); -} - - -M68KMAKE_OP(cmp, 32, ., d) -{ - uint src = DY; - uint dst = DX; - uint res = dst - src; - - FLAG_N = NFLAG_32(res); - FLAG_Z = MASK_OUT_ABOVE_32(res); - FLAG_V = VFLAG_SUB_32(src, dst, res); - FLAG_C = CFLAG_SUB_32(src, dst, res); -} - - -M68KMAKE_OP(cmp, 32, ., a) -{ - uint src = AY; - uint dst = DX; - uint res = dst - src; - - FLAG_N = NFLAG_32(res); - FLAG_Z = MASK_OUT_ABOVE_32(res); - FLAG_V = VFLAG_SUB_32(src, dst, res); - FLAG_C = CFLAG_SUB_32(src, dst, res); -} - - -M68KMAKE_OP(cmp, 32, ., .) -{ - uint src = M68KMAKE_GET_OPER_AY_32; - uint dst = DX; - uint res = dst - src; - - FLAG_N = NFLAG_32(res); - FLAG_Z = MASK_OUT_ABOVE_32(res); - FLAG_V = VFLAG_SUB_32(src, dst, res); - FLAG_C = CFLAG_SUB_32(src, dst, res); -} - - -M68KMAKE_OP(cmpa, 16, ., d) -{ - uint src = MAKE_INT_16(DY); - uint dst = AX; - uint res = dst - src; - - FLAG_N = NFLAG_32(res); - FLAG_Z = MASK_OUT_ABOVE_32(res); - FLAG_V = VFLAG_SUB_32(src, dst, res); - FLAG_C = CFLAG_SUB_32(src, dst, res); -} - - -M68KMAKE_OP(cmpa, 16, ., a) -{ - uint src = MAKE_INT_16(AY); - uint dst = AX; - uint res = dst - src; - - FLAG_N = NFLAG_32(res); - FLAG_Z = MASK_OUT_ABOVE_32(res); - FLAG_V = VFLAG_SUB_32(src, dst, res); - FLAG_C = CFLAG_SUB_32(src, dst, res); -} - - -M68KMAKE_OP(cmpa, 16, ., .) -{ - uint src = MAKE_INT_16(M68KMAKE_GET_OPER_AY_16); - uint dst = AX; - uint res = dst - src; - - FLAG_N = NFLAG_32(res); - FLAG_Z = MASK_OUT_ABOVE_32(res); - FLAG_V = VFLAG_SUB_32(src, dst, res); - FLAG_C = CFLAG_SUB_32(src, dst, res); -} - - -M68KMAKE_OP(cmpa, 32, ., d) -{ - uint src = DY; - uint dst = AX; - uint res = dst - src; - - FLAG_N = NFLAG_32(res); - FLAG_Z = MASK_OUT_ABOVE_32(res); - FLAG_V = VFLAG_SUB_32(src, dst, res); - FLAG_C = CFLAG_SUB_32(src, dst, res); -} - - -M68KMAKE_OP(cmpa, 32, ., a) -{ - uint src = AY; - uint dst = AX; - uint res = dst - src; - - FLAG_N = NFLAG_32(res); - FLAG_Z = MASK_OUT_ABOVE_32(res); - FLAG_V = VFLAG_SUB_32(src, dst, res); - FLAG_C = CFLAG_SUB_32(src, dst, res); -} - - -M68KMAKE_OP(cmpa, 32, ., .) -{ - uint src = M68KMAKE_GET_OPER_AY_32; - uint dst = AX; - uint res = dst - src; - - FLAG_N = NFLAG_32(res); - FLAG_Z = MASK_OUT_ABOVE_32(res); - FLAG_V = VFLAG_SUB_32(src, dst, res); - FLAG_C = CFLAG_SUB_32(src, dst, res); -} - - -M68KMAKE_OP(cmpi, 8, ., d) -{ - uint src = OPER_I_8(); - uint dst = MASK_OUT_ABOVE_8(DY); - uint res = dst - src; - - FLAG_N = NFLAG_8(res); - FLAG_Z = MASK_OUT_ABOVE_8(res); - FLAG_V = VFLAG_SUB_8(src, dst, res); - FLAG_C = CFLAG_8(res); -} - - -M68KMAKE_OP(cmpi, 8, ., .) -{ - uint src = OPER_I_8(); - uint dst = M68KMAKE_GET_OPER_AY_8; - uint res = dst - src; - - FLAG_N = NFLAG_8(res); - FLAG_Z = MASK_OUT_ABOVE_8(res); - FLAG_V = VFLAG_SUB_8(src, dst, res); - FLAG_C = CFLAG_8(res); -} - - -M68KMAKE_OP(cmpi, 8, ., pcdi) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint src = OPER_I_8(); - uint dst = OPER_PCDI_8(); - uint res = dst - src; - - FLAG_N = NFLAG_8(res); - FLAG_Z = MASK_OUT_ABOVE_8(res); - FLAG_V = VFLAG_SUB_8(src, dst, res); - FLAG_C = CFLAG_8(res); - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(cmpi, 8, ., pcix) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint src = OPER_I_8(); - uint dst = OPER_PCIX_8(); - uint res = dst - src; - - FLAG_N = NFLAG_8(res); - FLAG_Z = MASK_OUT_ABOVE_8(res); - FLAG_V = VFLAG_SUB_8(src, dst, res); - FLAG_C = CFLAG_8(res); - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(cmpi, 16, ., d) -{ - uint src = OPER_I_16(); - uint dst = MASK_OUT_ABOVE_16(DY); - uint res = dst - src; - - FLAG_N = NFLAG_16(res); - FLAG_Z = MASK_OUT_ABOVE_16(res); - FLAG_V = VFLAG_SUB_16(src, dst, res); - FLAG_C = CFLAG_16(res); -} - - -M68KMAKE_OP(cmpi, 16, ., .) -{ - uint src = OPER_I_16(); - uint dst = M68KMAKE_GET_OPER_AY_16; - uint res = dst - src; - - FLAG_N = NFLAG_16(res); - FLAG_Z = MASK_OUT_ABOVE_16(res); - FLAG_V = VFLAG_SUB_16(src, dst, res); - FLAG_C = CFLAG_16(res); -} - - -M68KMAKE_OP(cmpi, 16, ., pcdi) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint src = OPER_I_16(); - uint dst = OPER_PCDI_16(); - uint res = dst - src; - - FLAG_N = NFLAG_16(res); - FLAG_Z = MASK_OUT_ABOVE_16(res); - FLAG_V = VFLAG_SUB_16(src, dst, res); - FLAG_C = CFLAG_16(res); - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(cmpi, 16, ., pcix) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint src = OPER_I_16(); - uint dst = OPER_PCIX_16(); - uint res = dst - src; - - FLAG_N = NFLAG_16(res); - FLAG_Z = MASK_OUT_ABOVE_16(res); - FLAG_V = VFLAG_SUB_16(src, dst, res); - FLAG_C = CFLAG_16(res); - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(cmpi, 32, ., d) -{ - uint src = OPER_I_32(); - uint dst = DY; - uint res = dst - src; - - m68ki_cmpild_callback(src, REG_IR & 7); /* auto-disable (see m68kcpu.h) */ - FLAG_N = NFLAG_32(res); - FLAG_Z = MASK_OUT_ABOVE_32(res); - FLAG_V = VFLAG_SUB_32(src, dst, res); - FLAG_C = CFLAG_SUB_32(src, dst, res); -} - - -M68KMAKE_OP(cmpi, 32, ., .) -{ - uint src = OPER_I_32(); - uint dst = M68KMAKE_GET_OPER_AY_32; - uint res = dst - src; - - FLAG_N = NFLAG_32(res); - FLAG_Z = MASK_OUT_ABOVE_32(res); - FLAG_V = VFLAG_SUB_32(src, dst, res); - FLAG_C = CFLAG_SUB_32(src, dst, res); -} - - -M68KMAKE_OP(cmpi, 32, ., pcdi) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint src = OPER_I_32(); - uint dst = OPER_PCDI_32(); - uint res = dst - src; - - FLAG_N = NFLAG_32(res); - FLAG_Z = MASK_OUT_ABOVE_32(res); - FLAG_V = VFLAG_SUB_32(src, dst, res); - FLAG_C = CFLAG_SUB_32(src, dst, res); - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(cmpi, 32, ., pcix) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint src = OPER_I_32(); - uint dst = OPER_PCIX_32(); - uint res = dst - src; - - FLAG_N = NFLAG_32(res); - FLAG_Z = MASK_OUT_ABOVE_32(res); - FLAG_V = VFLAG_SUB_32(src, dst, res); - FLAG_C = CFLAG_SUB_32(src, dst, res); - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(cmpm, 8, ., ax7) -{ - uint src = OPER_AY_PI_8(); - uint dst = OPER_A7_PI_8(); - uint res = dst - src; - - FLAG_N = NFLAG_8(res); - FLAG_Z = MASK_OUT_ABOVE_8(res); - FLAG_V = VFLAG_SUB_8(src, dst, res); - FLAG_C = CFLAG_8(res); -} - - -M68KMAKE_OP(cmpm, 8, ., ay7) -{ - uint src = OPER_A7_PI_8(); - uint dst = OPER_AX_PI_8(); - uint res = dst - src; - - FLAG_N = NFLAG_8(res); - FLAG_Z = MASK_OUT_ABOVE_8(res); - FLAG_V = VFLAG_SUB_8(src, dst, res); - FLAG_C = CFLAG_8(res); -} - - -M68KMAKE_OP(cmpm, 8, ., axy7) -{ - uint src = OPER_A7_PI_8(); - uint dst = OPER_A7_PI_8(); - uint res = dst - src; - - FLAG_N = NFLAG_8(res); - FLAG_Z = MASK_OUT_ABOVE_8(res); - FLAG_V = VFLAG_SUB_8(src, dst, res); - FLAG_C = CFLAG_8(res); -} - - -M68KMAKE_OP(cmpm, 8, ., .) -{ - uint src = OPER_AY_PI_8(); - uint dst = OPER_AX_PI_8(); - uint res = dst - src; - - FLAG_N = NFLAG_8(res); - FLAG_Z = MASK_OUT_ABOVE_8(res); - FLAG_V = VFLAG_SUB_8(src, dst, res); - FLAG_C = CFLAG_8(res); -} - - -M68KMAKE_OP(cmpm, 16, ., .) -{ - uint src = OPER_AY_PI_16(); - uint dst = OPER_AX_PI_16(); - uint res = dst - src; - - FLAG_N = NFLAG_16(res); - FLAG_Z = MASK_OUT_ABOVE_16(res); - FLAG_V = VFLAG_SUB_16(src, dst, res); - FLAG_C = CFLAG_16(res); -} - - -M68KMAKE_OP(cmpm, 32, ., .) -{ - uint src = OPER_AY_PI_32(); - uint dst = OPER_AX_PI_32(); - uint res = dst - src; - - FLAG_N = NFLAG_32(res); - FLAG_Z = MASK_OUT_ABOVE_32(res); - FLAG_V = VFLAG_SUB_32(src, dst, res); - FLAG_C = CFLAG_SUB_32(src, dst, res); -} - - -M68KMAKE_OP(cpbcc, 32, ., .) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - M68K_DO_LOG((M68K_LOG_FILEHANDLE "%s at %08x: called unimplemented instruction %04x (%s)\n", - m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PC - 2), REG_IR, - m68k_disassemble_quick(ADDRESS_68K(REG_PC - 2)))); - return; - } - m68ki_exception_1111(); -} - - -M68KMAKE_OP(cpdbcc, 32, ., .) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - M68K_DO_LOG((M68K_LOG_FILEHANDLE "%s at %08x: called unimplemented instruction %04x (%s)\n", - m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PC - 2), REG_IR, - m68k_disassemble_quick(ADDRESS_68K(REG_PC - 2)))); - return; - } - m68ki_exception_1111(); -} - - -M68KMAKE_OP(cpgen, 32, ., .) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - M68K_DO_LOG((M68K_LOG_FILEHANDLE "%s at %08x: called unimplemented instruction %04x (%s)\n", - m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PC - 2), REG_IR, - m68k_disassemble_quick(ADDRESS_68K(REG_PC - 2)))); - return; - } - m68ki_exception_1111(); -} - - -M68KMAKE_OP(cpscc, 32, ., .) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - M68K_DO_LOG((M68K_LOG_FILEHANDLE "%s at %08x: called unimplemented instruction %04x (%s)\n", - m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PC - 2), REG_IR, - m68k_disassemble_quick(ADDRESS_68K(REG_PC - 2)))); - return; - } - m68ki_exception_1111(); -} - - -M68KMAKE_OP(cptrapcc, 32, ., .) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - M68K_DO_LOG((M68K_LOG_FILEHANDLE "%s at %08x: called unimplemented instruction %04x (%s)\n", - m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PC - 2), REG_IR, - m68k_disassemble_quick(ADDRESS_68K(REG_PC - 2)))); - // JFF: unsupported, but at least if the trap doesn't occur, app should still work, so at least PC increase is correct - REG_PC += 4; - return; - } - m68ki_exception_1111(); -} - - -M68KMAKE_OP(dbt, 16, ., .) -{ - REG_PC += 2; -} - - -M68KMAKE_OP(dbf, 16, ., .) -{ - uint* r_dst = &DY; - uint res = MASK_OUT_ABOVE_16(*r_dst - 1); - - *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; - if(res != 0xffff) - { - uint offset = OPER_I_16(); - REG_PC -= 2; - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - m68ki_branch_16(offset); - USE_CYCLES(CYC_DBCC_F_NOEXP); - return; - } - REG_PC += 2; - USE_CYCLES(CYC_DBCC_F_EXP); -} - - -M68KMAKE_OP(dbcc, 16, ., .) -{ - if(M68KMAKE_NOT_CC) - { - uint* r_dst = &DY; - uint res = MASK_OUT_ABOVE_16(*r_dst - 1); - - *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; - if(res != 0xffff) - { - uint offset = OPER_I_16(); - REG_PC -= 2; - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - m68ki_branch_16(offset); - USE_CYCLES(CYC_DBCC_F_NOEXP); - return; - } - REG_PC += 2; - USE_CYCLES(CYC_DBCC_F_EXP); - return; - } - REG_PC += 2; -} - - -M68KMAKE_OP(divs, 16, ., d) -{ - uint* r_dst = &DX; - sint src = MAKE_INT_16(DY); - sint quotient; - sint remainder; - - if(src != 0) - { - if((uint32)*r_dst == 0x80000000 && src == -1) - { - FLAG_Z = 0; - FLAG_N = NFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - *r_dst = 0; - return; - } - - quotient = MAKE_INT_32(*r_dst) / src; - remainder = MAKE_INT_32(*r_dst) % src; - - if(quotient == MAKE_INT_16(quotient)) - { - FLAG_Z = quotient; - FLAG_N = NFLAG_16(quotient); - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - *r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16)); - return; - } - FLAG_V = VFLAG_SET; - return; - } - m68ki_exception_trap(EXCEPTION_ZERO_DIVIDE); -} - - -M68KMAKE_OP(divs, 16, ., .) -{ - uint* r_dst = &DX; - sint src = MAKE_INT_16(M68KMAKE_GET_OPER_AY_16); - sint quotient; - sint remainder; - - if(src != 0) - { - if((uint32)*r_dst == 0x80000000 && src == -1) - { - FLAG_Z = 0; - FLAG_N = NFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - *r_dst = 0; - return; - } - - quotient = MAKE_INT_32(*r_dst) / src; - remainder = MAKE_INT_32(*r_dst) % src; - - if(quotient == MAKE_INT_16(quotient)) - { - FLAG_Z = quotient; - FLAG_N = NFLAG_16(quotient); - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - *r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16)); - return; - } - FLAG_V = VFLAG_SET; - return; - } - m68ki_exception_trap(EXCEPTION_ZERO_DIVIDE); -} - - -M68KMAKE_OP(divu, 16, ., d) -{ - uint* r_dst = &DX; - uint src = MASK_OUT_ABOVE_16(DY); - - if(src != 0) - { - uint quotient = *r_dst / src; - uint remainder = *r_dst % src; - - if(quotient < 0x10000) - { - FLAG_Z = quotient; - FLAG_N = NFLAG_16(quotient); - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - *r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16)); - return; - } - FLAG_V = VFLAG_SET; - return; - } - m68ki_exception_trap(EXCEPTION_ZERO_DIVIDE); -} - - -M68KMAKE_OP(divu, 16, ., .) -{ - uint* r_dst = &DX; - uint src = M68KMAKE_GET_OPER_AY_16; - - if(src != 0) - { - uint quotient = *r_dst / src; - uint remainder = *r_dst % src; - - if(quotient < 0x10000) - { - FLAG_Z = quotient; - FLAG_N = NFLAG_16(quotient); - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - *r_dst = MASK_OUT_ABOVE_32(MASK_OUT_ABOVE_16(quotient) | (remainder << 16)); - return; - } - FLAG_V = VFLAG_SET; - return; - } - m68ki_exception_trap(EXCEPTION_ZERO_DIVIDE); -} - - -M68KMAKE_OP(divl, 32, ., d) -{ -#if M68K_USE_64_BIT - - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint word2 = OPER_I_16(); - uint64 divisor = DY; - uint64 dividend = 0; - uint64 quotient = 0; - uint64 remainder = 0; - - if(divisor != 0) - { - if(BIT_A(word2)) /* 64 bit */ - { - dividend = REG_D[word2 & 7]; - dividend <<= 32; - dividend |= REG_D[(word2 >> 12) & 7]; - - if(BIT_B(word2)) /* signed */ - { - quotient = (uint64)((sint64)dividend / (sint64)((sint32)divisor)); - remainder = (uint64)((sint64)dividend % (sint64)((sint32)divisor)); - if((sint64)quotient != (sint64)((sint32)quotient)) - { - FLAG_V = VFLAG_SET; - return; - } - } - else /* unsigned */ - { - quotient = dividend / divisor; - if(quotient > 0xffffffff) - { - FLAG_V = VFLAG_SET; - return; - } - remainder = dividend % divisor; - } - } - else /* 32 bit */ - { - dividend = REG_D[(word2 >> 12) & 7]; - if(BIT_B(word2)) /* signed */ - { - quotient = (uint64)((sint64)((sint32)dividend) / (sint64)((sint32)divisor)); - remainder = (uint64)((sint64)((sint32)dividend) % (sint64)((sint32)divisor)); - } - else /* unsigned */ - { - quotient = dividend / divisor; - remainder = dividend % divisor; - } - } - - REG_D[word2 & 7] = remainder; - REG_D[(word2 >> 12) & 7] = quotient; - - FLAG_N = NFLAG_32(quotient); - FLAG_Z = quotient; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - return; - } - m68ki_exception_trap(EXCEPTION_ZERO_DIVIDE); - return; - } - m68ki_exception_illegal(); - -#else - - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint word2 = OPER_I_16(); - uint divisor = DY; - uint dividend_hi = REG_D[word2 & 7]; - uint dividend_lo = REG_D[(word2 >> 12) & 7]; - uint quotient = 0; - uint remainder = 0; - uint dividend_neg = 0; - uint divisor_neg = 0; - sint i; - uint overflow; - - if(divisor != 0) - { - /* quad / long : long quotient, long remainder */ - if(BIT_A(word2)) - { - if(BIT_B(word2)) /* signed */ - { - /* special case in signed divide */ - if(dividend_hi == 0 && dividend_lo == 0x80000000 && divisor == 0xffffffff) - { - REG_D[word2 & 7] = 0; - REG_D[(word2 >> 12) & 7] = 0x80000000; - - FLAG_N = NFLAG_SET; - FLAG_Z = ZFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - return; - } - if(GET_MSB_32(dividend_hi)) - { - dividend_neg = 1; - dividend_hi = (uint)MASK_OUT_ABOVE_32((-(sint)dividend_hi) - (dividend_lo != 0)); - dividend_lo = (uint)MASK_OUT_ABOVE_32(-(sint)dividend_lo); - } - if(GET_MSB_32(divisor)) - { - divisor_neg = 1; - divisor = (uint)MASK_OUT_ABOVE_32(-(sint)divisor); - - } - } - - /* if the upper long is greater than the divisor, we're overflowing. */ - if(dividend_hi >= divisor) - { - FLAG_V = VFLAG_SET; - return; - } - - for(i = 31; i >= 0; i--) - { - quotient <<= 1; - remainder = (remainder << 1) + ((dividend_hi >> i) & 1); - if(remainder >= divisor) - { - remainder -= divisor; - quotient++; - } - } - for(i = 31; i >= 0; i--) - { - quotient <<= 1; - overflow = GET_MSB_32(remainder); - remainder = (remainder << 1) + ((dividend_lo >> i) & 1); - if(remainder >= divisor || overflow) - { - remainder -= divisor; - quotient++; - } - } - - if(BIT_B(word2)) /* signed */ - { - if(quotient > 0x7fffffff) - { - FLAG_V = VFLAG_SET; - return; - } - if(dividend_neg) - { - remainder = (uint)MASK_OUT_ABOVE_32(-(sint)remainder); - quotient = (uint)MASK_OUT_ABOVE_32(-(sint)quotient); - } - if(divisor_neg) - quotient = (uint)MASK_OUT_ABOVE_32(-(sint)quotient); - } - - REG_D[word2 & 7] = remainder; - REG_D[(word2 >> 12) & 7] = quotient; - - FLAG_N = NFLAG_32(quotient); - FLAG_Z = quotient; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - return; - } - - /* long / long: long quotient, maybe long remainder */ - if(BIT_B(word2)) /* signed */ - { - /* Special case in divide */ - if(dividend_lo == 0x80000000 && divisor == 0xffffffff) - { - FLAG_N = NFLAG_SET; - FLAG_Z = ZFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - REG_D[(word2 >> 12) & 7] = 0x80000000; - REG_D[word2 & 7] = 0; - return; - } - REG_D[word2 & 7] = MAKE_INT_32(dividend_lo) % MAKE_INT_32(divisor); - quotient = REG_D[(word2 >> 12) & 7] = MAKE_INT_32(dividend_lo) / MAKE_INT_32(divisor); - } - else - { - REG_D[word2 & 7] = MASK_OUT_ABOVE_32(dividend_lo) % MASK_OUT_ABOVE_32(divisor); - quotient = REG_D[(word2 >> 12) & 7] = MASK_OUT_ABOVE_32(dividend_lo) / MASK_OUT_ABOVE_32(divisor); - } - - FLAG_N = NFLAG_32(quotient); - FLAG_Z = quotient; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - return; - } - m68ki_exception_trap(EXCEPTION_ZERO_DIVIDE); - return; - } - m68ki_exception_illegal(); - -#endif -} - - -M68KMAKE_OP(divl, 32, ., .) -{ -#if M68K_USE_64_BIT - - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint word2 = OPER_I_16(); - uint64 divisor = M68KMAKE_GET_OPER_AY_32; - uint64 dividend = 0; - uint64 quotient = 0; - uint64 remainder = 0; - - if(divisor != 0) - { - if(BIT_A(word2)) /* 64 bit */ - { - dividend = REG_D[word2 & 7]; - dividend <<= 32; - dividend |= REG_D[(word2 >> 12) & 7]; - - if(BIT_B(word2)) /* signed */ - { - quotient = (uint64)((sint64)dividend / (sint64)((sint32)divisor)); - remainder = (uint64)((sint64)dividend % (sint64)((sint32)divisor)); - if((sint64)quotient != (sint64)((sint32)quotient)) - { - FLAG_V = VFLAG_SET; - return; - } - } - else /* unsigned */ - { - quotient = dividend / divisor; - if(quotient > 0xffffffff) - { - FLAG_V = VFLAG_SET; - return; - } - remainder = dividend % divisor; - } - } - else /* 32 bit */ - { - dividend = REG_D[(word2 >> 12) & 7]; - if(BIT_B(word2)) /* signed */ - { - quotient = (uint64)((sint64)((sint32)dividend) / (sint64)((sint32)divisor)); - remainder = (uint64)((sint64)((sint32)dividend) % (sint64)((sint32)divisor)); - } - else /* unsigned */ - { - quotient = dividend / divisor; - remainder = dividend % divisor; - } - } - - REG_D[word2 & 7] = remainder; - REG_D[(word2 >> 12) & 7] = quotient; - - FLAG_N = NFLAG_32(quotient); - FLAG_Z = quotient; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - return; - } - m68ki_exception_trap(EXCEPTION_ZERO_DIVIDE); - return; - } - m68ki_exception_illegal(); - -#else - - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint word2 = OPER_I_16(); - uint divisor = M68KMAKE_GET_OPER_AY_32; - uint dividend_hi = REG_D[word2 & 7]; - uint dividend_lo = REG_D[(word2 >> 12) & 7]; - uint quotient = 0; - uint remainder = 0; - uint dividend_neg = 0; - uint divisor_neg = 0; - sint i; - uint overflow; - - if(divisor != 0) - { - /* quad / long : long quotient, long remainder */ - if(BIT_A(word2)) - { - if(BIT_B(word2)) /* signed */ - { - /* special case in signed divide */ - if(dividend_hi == 0 && dividend_lo == 0x80000000 && divisor == 0xffffffff) - { - REG_D[word2 & 7] = 0; - REG_D[(word2 >> 12) & 7] = 0x80000000; - - FLAG_N = NFLAG_SET; - FLAG_Z = ZFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - return; - } - if(GET_MSB_32(dividend_hi)) - { - dividend_neg = 1; - dividend_hi = (uint)MASK_OUT_ABOVE_32((-(sint)dividend_hi) - (dividend_lo != 0)); - dividend_lo = (uint)MASK_OUT_ABOVE_32(-(sint)dividend_lo); - } - if(GET_MSB_32(divisor)) - { - divisor_neg = 1; - divisor = (uint)MASK_OUT_ABOVE_32(-(sint)divisor); - - } - } - - /* if the upper long is greater than the divisor, we're overflowing. */ - if(dividend_hi >= divisor) - { - FLAG_V = VFLAG_SET; - return; - } - - for(i = 31; i >= 0; i--) - { - quotient <<= 1; - remainder = (remainder << 1) + ((dividend_hi >> i) & 1); - if(remainder >= divisor) - { - remainder -= divisor; - quotient++; - } - } - for(i = 31; i >= 0; i--) - { - quotient <<= 1; - overflow = GET_MSB_32(remainder); - remainder = (remainder << 1) + ((dividend_lo >> i) & 1); - if(remainder >= divisor || overflow) - { - remainder -= divisor; - quotient++; - } - } - - if(BIT_B(word2)) /* signed */ - { - if(quotient > 0x7fffffff) - { - FLAG_V = VFLAG_SET; - return; - } - if(dividend_neg) - { - remainder = (uint)MASK_OUT_ABOVE_32(-(sint)remainder); - quotient = (uint)MASK_OUT_ABOVE_32(-(sint)quotient); - } - if(divisor_neg) - quotient = (uint)MASK_OUT_ABOVE_32(-(sint)quotient); - } - - REG_D[word2 & 7] = remainder; - REG_D[(word2 >> 12) & 7] = quotient; - - FLAG_N = NFLAG_32(quotient); - FLAG_Z = quotient; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - return; - } - - /* long / long: long quotient, maybe long remainder */ - if(BIT_B(word2)) /* signed */ - { - /* Special case in divide */ - if(dividend_lo == 0x80000000 && divisor == 0xffffffff) - { - FLAG_N = NFLAG_SET; - FLAG_Z = ZFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - REG_D[(word2 >> 12) & 7] = 0x80000000; - REG_D[word2 & 7] = 0; - return; - } - REG_D[word2 & 7] = MAKE_INT_32(dividend_lo) % MAKE_INT_32(divisor); - quotient = REG_D[(word2 >> 12) & 7] = MAKE_INT_32(dividend_lo) / MAKE_INT_32(divisor); - } - else - { - REG_D[word2 & 7] = MASK_OUT_ABOVE_32(dividend_lo) % MASK_OUT_ABOVE_32(divisor); - quotient = REG_D[(word2 >> 12) & 7] = MASK_OUT_ABOVE_32(dividend_lo) / MASK_OUT_ABOVE_32(divisor); - } - - FLAG_N = NFLAG_32(quotient); - FLAG_Z = quotient; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - return; - } - m68ki_exception_trap(EXCEPTION_ZERO_DIVIDE); - return; - } - m68ki_exception_illegal(); - -#endif -} - - -M68KMAKE_OP(eor, 8, ., d) -{ - uint res = MASK_OUT_ABOVE_8(DY ^= MASK_OUT_ABOVE_8(DX)); - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(eor, 8, ., .) -{ - uint ea = M68KMAKE_GET_EA_AY_8; - uint res = MASK_OUT_ABOVE_8(DX ^ m68ki_read_8(ea)); - - m68ki_write_8(ea, res); - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(eor, 16, ., d) -{ - uint res = MASK_OUT_ABOVE_16(DY ^= MASK_OUT_ABOVE_16(DX)); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(eor, 16, ., .) -{ - uint ea = M68KMAKE_GET_EA_AY_16; - uint res = MASK_OUT_ABOVE_16(DX ^ m68ki_read_16(ea)); - - m68ki_write_16(ea, res); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(eor, 32, ., d) -{ - uint res = DY ^= DX; - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(eor, 32, ., .) -{ - uint ea = M68KMAKE_GET_EA_AY_32; - uint res = DX ^ m68ki_read_32(ea); - - m68ki_write_32(ea, res); - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(eori, 8, ., d) -{ - uint res = MASK_OUT_ABOVE_8(DY ^= OPER_I_8()); - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(eori, 8, ., .) -{ - uint src = OPER_I_8(); - uint ea = M68KMAKE_GET_EA_AY_8; - uint res = src ^ m68ki_read_8(ea); - - m68ki_write_8(ea, res); - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(eori, 16, ., d) -{ - uint res = MASK_OUT_ABOVE_16(DY ^= OPER_I_16()); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(eori, 16, ., .) -{ - uint src = OPER_I_16(); - uint ea = M68KMAKE_GET_EA_AY_16; - uint res = src ^ m68ki_read_16(ea); - - m68ki_write_16(ea, res); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(eori, 32, ., d) -{ - uint res = DY ^= OPER_I_32(); - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(eori, 32, ., .) -{ - uint src = OPER_I_32(); - uint ea = M68KMAKE_GET_EA_AY_32; - uint res = src ^ m68ki_read_32(ea); - - m68ki_write_32(ea, res); - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(eori, 16, toc, .) -{ - m68ki_set_ccr(m68ki_get_ccr() ^ OPER_I_8()); -} - - -M68KMAKE_OP(eori, 16, tos, .) -{ - if(FLAG_S) - { - uint src = OPER_I_16(); - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - m68ki_set_sr(m68ki_get_sr() ^ src); - return; - } - m68ki_exception_privilege_violation(); -} - - -M68KMAKE_OP(exg, 32, dd, .) -{ - uint* reg_a = &DX; - uint* reg_b = &DY; - uint tmp = *reg_a; - *reg_a = *reg_b; - *reg_b = tmp; -} - - -M68KMAKE_OP(exg, 32, aa, .) -{ - uint* reg_a = &AX; - uint* reg_b = &AY; - uint tmp = *reg_a; - *reg_a = *reg_b; - *reg_b = tmp; -} - - -M68KMAKE_OP(exg, 32, da, .) -{ - uint* reg_a = &DX; - uint* reg_b = &AY; - uint tmp = *reg_a; - *reg_a = *reg_b; - *reg_b = tmp; -} - - -M68KMAKE_OP(ext, 16, ., .) -{ - uint* r_dst = &DY; - - *r_dst = MASK_OUT_BELOW_16(*r_dst) | MASK_OUT_ABOVE_8(*r_dst) | (GET_MSB_8(*r_dst) ? 0xff00 : 0); - - FLAG_N = NFLAG_16(*r_dst); - FLAG_Z = MASK_OUT_ABOVE_16(*r_dst); - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(ext, 32, ., .) -{ - uint* r_dst = &DY; - - *r_dst = MASK_OUT_ABOVE_16(*r_dst) | (GET_MSB_16(*r_dst) ? 0xffff0000 : 0); - - FLAG_N = NFLAG_32(*r_dst); - FLAG_Z = *r_dst; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(extb, 32, ., .) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint* r_dst = &DY; - - *r_dst = MASK_OUT_ABOVE_8(*r_dst) | (GET_MSB_8(*r_dst) ? 0xffffff00 : 0); - - FLAG_N = NFLAG_32(*r_dst); - FLAG_Z = *r_dst; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(illegal, 0, ., .) -{ - m68ki_exception_illegal(); -} - -M68KMAKE_OP(jmp, 32, ., .) -{ - m68ki_jump(M68KMAKE_GET_EA_AY_32); - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - if(REG_PC == REG_PPC) - USE_ALL_CYCLES(); -} - - -M68KMAKE_OP(jsr, 32, ., .) -{ - uint ea = M68KMAKE_GET_EA_AY_32; - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - m68ki_push_32(REG_PC); - m68ki_jump(ea); -} - - -M68KMAKE_OP(lea, 32, ., .) -{ - AX = M68KMAKE_GET_EA_AY_32; -} - - -M68KMAKE_OP(link, 16, ., a7) -{ - REG_A[7] -= 4; - m68ki_write_32(REG_A[7], REG_A[7]); - REG_A[7] = MASK_OUT_ABOVE_32(REG_A[7] + MAKE_INT_16(OPER_I_16())); -} - - -M68KMAKE_OP(link, 16, ., .) -{ - uint* r_dst = &AY; - - m68ki_push_32(*r_dst); - *r_dst = REG_A[7]; - REG_A[7] = MASK_OUT_ABOVE_32(REG_A[7] + MAKE_INT_16(OPER_I_16())); -} - - -M68KMAKE_OP(link, 32, ., a7) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - REG_A[7] -= 4; - m68ki_write_32(REG_A[7], REG_A[7]); - REG_A[7] = MASK_OUT_ABOVE_32(REG_A[7] + OPER_I_32()); - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(link, 32, ., .) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint* r_dst = &AY; - - m68ki_push_32(*r_dst); - *r_dst = REG_A[7]; - REG_A[7] = MASK_OUT_ABOVE_32(REG_A[7] + OPER_I_32()); - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(lsr, 8, s, .) -{ - uint* r_dst = &DY; - uint shift = (((REG_IR >> 9) - 1) & 7) + 1; - uint src = MASK_OUT_ABOVE_8(*r_dst); - uint res = src >> shift; - - if(shift != 0) - USE_CYCLES(shift<> 9) - 1) & 7) + 1; - uint src = MASK_OUT_ABOVE_16(*r_dst); - uint res = src >> shift; - - if(shift != 0) - USE_CYCLES(shift<> 9) - 1) & 7) + 1; - uint src = *r_dst; - uint res = src >> shift; - - if(shift != 0) - USE_CYCLES(shift<> shift; - - if(shift != 0) - { - USE_CYCLES(shift<> shift; - - if(shift != 0) - { - USE_CYCLES(shift<> (shift - 1))<<8; - FLAG_N = NFLAG_CLEAR; - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - return; - } - - *r_dst &= 0xffff0000; - FLAG_X = XFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - FLAG_N = NFLAG_CLEAR; - FLAG_Z = ZFLAG_SET; - FLAG_V = VFLAG_CLEAR; - return; - } - - FLAG_C = CFLAG_CLEAR; - FLAG_N = NFLAG_16(src); - FLAG_Z = src; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(lsr, 32, r, .) -{ - uint* r_dst = &DY; - uint shift = DX & 0x3f; - uint src = *r_dst; - uint res = src >> shift; - - if(shift != 0) - { - USE_CYCLES(shift<> (shift - 1))<<8; - FLAG_N = NFLAG_CLEAR; - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - return; - } - - *r_dst = 0; - FLAG_X = FLAG_C = (shift == 32 ? GET_MSB_32(src)>>23 : 0); - FLAG_N = NFLAG_CLEAR; - FLAG_Z = ZFLAG_SET; - FLAG_V = VFLAG_CLEAR; - return; - } - - FLAG_C = CFLAG_CLEAR; - FLAG_N = NFLAG_32(src); - FLAG_Z = src; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(lsr, 16, ., .) -{ - uint ea = M68KMAKE_GET_EA_AY_16; - uint src = m68ki_read_16(ea); - uint res = src >> 1; - - m68ki_write_16(ea, res); - - FLAG_N = NFLAG_CLEAR; - FLAG_Z = res; - FLAG_C = FLAG_X = src << 8; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(lsl, 8, s, .) -{ - uint* r_dst = &DY; - uint shift = (((REG_IR >> 9) - 1) & 7) + 1; - uint src = MASK_OUT_ABOVE_8(*r_dst); - uint res = MASK_OUT_ABOVE_8(src << shift); - - if(shift != 0) - USE_CYCLES(shift<> 9) - 1) & 7) + 1; - uint src = MASK_OUT_ABOVE_16(*r_dst); - uint res = MASK_OUT_ABOVE_16(src << shift); - - if(shift != 0) - USE_CYCLES(shift<> (8-shift); - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(lsl, 32, s, .) -{ - uint* r_dst = &DY; - uint shift = (((REG_IR >> 9) - 1) & 7) + 1; - uint src = *r_dst; - uint res = MASK_OUT_ABOVE_32(src << shift); - - if(shift != 0) - USE_CYCLES(shift<> (24-shift); - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(lsl, 8, r, .) -{ - uint* r_dst = &DY; - uint shift = DX & 0x3f; - uint src = MASK_OUT_ABOVE_8(*r_dst); - uint res = MASK_OUT_ABOVE_8(src << shift); - - if(shift != 0) - { - USE_CYCLES(shift<> 8; - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - return; - } - - *r_dst &= 0xffff0000; - FLAG_X = XFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - FLAG_N = NFLAG_CLEAR; - FLAG_Z = ZFLAG_SET; - FLAG_V = VFLAG_CLEAR; - return; - } - - FLAG_C = CFLAG_CLEAR; - FLAG_N = NFLAG_16(src); - FLAG_Z = src; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(lsl, 32, r, .) -{ - uint* r_dst = &DY; - uint shift = DX & 0x3f; - uint src = *r_dst; - uint res = MASK_OUT_ABOVE_32(src << shift); - - if(shift != 0) - { - USE_CYCLES(shift<> (32 - shift)) << 8; - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - return; - } - - *r_dst = 0; - FLAG_X = FLAG_C = ((shift == 32 ? src & 1 : 0))<<8; - FLAG_N = NFLAG_CLEAR; - FLAG_Z = ZFLAG_SET; - FLAG_V = VFLAG_CLEAR; - return; - } - - FLAG_C = CFLAG_CLEAR; - FLAG_N = NFLAG_32(src); - FLAG_Z = src; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(lsl, 16, ., .) -{ - uint ea = M68KMAKE_GET_EA_AY_16; - uint src = m68ki_read_16(ea); - uint res = MASK_OUT_ABOVE_16(src << 1); - - m68ki_write_16(ea, res); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_X = FLAG_C = src >> 7; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 8, d, d) -{ - uint res = MASK_OUT_ABOVE_8(DY); - uint* r_dst = &DX; - - *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 8, d, .) -{ - uint res = M68KMAKE_GET_OPER_AY_8; - uint* r_dst = &DX; - - *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 8, ai, d) -{ - uint res = MASK_OUT_ABOVE_8(DY); - uint ea = EA_AX_AI_8(); - - m68ki_write_8(ea, res); - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 8, ai, .) -{ - uint res = M68KMAKE_GET_OPER_AY_8; - uint ea = EA_AX_AI_8(); - - m68ki_write_8(ea, res); - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 8, pi7, d) -{ - uint res = MASK_OUT_ABOVE_8(DY); - uint ea = EA_A7_PI_8(); - - m68ki_write_8(ea, res); - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 8, pi, d) -{ - uint res = MASK_OUT_ABOVE_8(DY); - uint ea = EA_AX_PI_8(); - - m68ki_write_8(ea, res); - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 8, pi7, .) -{ - uint res = M68KMAKE_GET_OPER_AY_8; - uint ea = EA_A7_PI_8(); - - m68ki_write_8(ea, res); - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 8, pi, .) -{ - uint res = M68KMAKE_GET_OPER_AY_8; - uint ea = EA_AX_PI_8(); - - m68ki_write_8(ea, res); - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 8, pd7, d) -{ - uint res = MASK_OUT_ABOVE_8(DY); - uint ea = EA_A7_PD_8(); - - m68ki_write_8(ea, res); - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 8, pd, d) -{ - uint res = MASK_OUT_ABOVE_8(DY); - uint ea = EA_AX_PD_8(); - - m68ki_write_8(ea, res); - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 8, pd7, .) -{ - uint res = M68KMAKE_GET_OPER_AY_8; - uint ea = EA_A7_PD_8(); - - m68ki_write_8(ea, res); - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 8, pd, .) -{ - uint res = M68KMAKE_GET_OPER_AY_8; - uint ea = EA_AX_PD_8(); - - m68ki_write_8(ea, res); - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 8, di, d) -{ - uint res = MASK_OUT_ABOVE_8(DY); - uint ea = EA_AX_DI_8(); - - m68ki_write_8(ea, res); - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 8, di, .) -{ - uint res = M68KMAKE_GET_OPER_AY_8; - uint ea = EA_AX_DI_8(); - - m68ki_write_8(ea, res); - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 8, ix, d) -{ - uint res = MASK_OUT_ABOVE_8(DY); - uint ea = EA_AX_IX_8(); - - m68ki_write_8(ea, res); - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 8, ix, .) -{ - uint res = M68KMAKE_GET_OPER_AY_8; - uint ea = EA_AX_IX_8(); - - m68ki_write_8(ea, res); - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 8, aw, d) -{ - uint res = MASK_OUT_ABOVE_8(DY); - uint ea = EA_AW_8(); - - m68ki_write_8(ea, res); - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 8, aw, .) -{ - uint res = M68KMAKE_GET_OPER_AY_8; - uint ea = EA_AW_8(); - - m68ki_write_8(ea, res); - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 8, al, d) -{ - uint res = MASK_OUT_ABOVE_8(DY); - uint ea = EA_AL_8(); - - m68ki_write_8(ea, res); - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 8, al, .) -{ - uint res = M68KMAKE_GET_OPER_AY_8; - uint ea = EA_AL_8(); - - m68ki_write_8(ea, res); - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 16, d, d) -{ - uint res = MASK_OUT_ABOVE_16(DY); - uint* r_dst = &DX; - - *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 16, d, a) -{ - uint res = MASK_OUT_ABOVE_16(AY); - uint* r_dst = &DX; - - *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 16, d, .) -{ - uint res = M68KMAKE_GET_OPER_AY_16; - uint* r_dst = &DX; - - *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 16, ai, d) -{ - uint res = MASK_OUT_ABOVE_16(DY); - uint ea = EA_AX_AI_16(); - - m68ki_write_16(ea, res); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 16, ai, a) -{ - uint res = MASK_OUT_ABOVE_16(AY); - uint ea = EA_AX_AI_16(); - - m68ki_write_16(ea, res); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 16, ai, .) -{ - uint res = M68KMAKE_GET_OPER_AY_16; - uint ea = EA_AX_AI_16(); - - m68ki_write_16(ea, res); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 16, pi, d) -{ - uint res = MASK_OUT_ABOVE_16(DY); - uint ea = EA_AX_PI_16(); - - m68ki_write_16(ea, res); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 16, pi, a) -{ - uint res = MASK_OUT_ABOVE_16(AY); - uint ea = EA_AX_PI_16(); - - m68ki_write_16(ea, res); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 16, pi, .) -{ - uint res = M68KMAKE_GET_OPER_AY_16; - uint ea = EA_AX_PI_16(); - - m68ki_write_16(ea, res); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 16, pd, d) -{ - uint res = MASK_OUT_ABOVE_16(DY); - uint ea = EA_AX_PD_16(); - - m68ki_write_16(ea, res); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 16, pd, a) -{ - uint res = MASK_OUT_ABOVE_16(AY); - uint ea = EA_AX_PD_16(); - - m68ki_write_16(ea, res); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 16, pd, .) -{ - uint res = M68KMAKE_GET_OPER_AY_16; - uint ea = EA_AX_PD_16(); - - m68ki_write_16(ea, res); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 16, di, d) -{ - uint res = MASK_OUT_ABOVE_16(DY); - uint ea = EA_AX_DI_16(); - - m68ki_write_16(ea, res); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 16, di, a) -{ - uint res = MASK_OUT_ABOVE_16(AY); - uint ea = EA_AX_DI_16(); - - m68ki_write_16(ea, res); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 16, di, .) -{ - uint res = M68KMAKE_GET_OPER_AY_16; - uint ea = EA_AX_DI_16(); - - m68ki_write_16(ea, res); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 16, ix, d) -{ - uint res = MASK_OUT_ABOVE_16(DY); - uint ea = EA_AX_IX_16(); - - m68ki_write_16(ea, res); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 16, ix, a) -{ - uint res = MASK_OUT_ABOVE_16(AY); - uint ea = EA_AX_IX_16(); - - m68ki_write_16(ea, res); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 16, ix, .) -{ - uint res = M68KMAKE_GET_OPER_AY_16; - uint ea = EA_AX_IX_16(); - - m68ki_write_16(ea, res); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 16, aw, d) -{ - uint res = MASK_OUT_ABOVE_16(DY); - uint ea = EA_AW_16(); - - m68ki_write_16(ea, res); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 16, aw, a) -{ - uint res = MASK_OUT_ABOVE_16(AY); - uint ea = EA_AW_16(); - - m68ki_write_16(ea, res); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 16, aw, .) -{ - uint res = M68KMAKE_GET_OPER_AY_16; - uint ea = EA_AW_16(); - - m68ki_write_16(ea, res); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 16, al, d) -{ - uint res = MASK_OUT_ABOVE_16(DY); - uint ea = EA_AL_16(); - - m68ki_write_16(ea, res); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 16, al, a) -{ - uint res = MASK_OUT_ABOVE_16(AY); - uint ea = EA_AL_16(); - - m68ki_write_16(ea, res); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 16, al, .) -{ - uint res = M68KMAKE_GET_OPER_AY_16; - uint ea = EA_AL_16(); - - m68ki_write_16(ea, res); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 32, d, d) -{ - uint res = DY; - uint* r_dst = &DX; - - *r_dst = res; - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 32, d, a) -{ - uint res = AY; - uint* r_dst = &DX; - - *r_dst = res; - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 32, d, .) -{ - uint res = M68KMAKE_GET_OPER_AY_32; - uint* r_dst = &DX; - - *r_dst = res; - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 32, ai, d) -{ - uint res = DY; - uint ea = EA_AX_AI_32(); - - m68ki_write_32(ea, res); - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 32, ai, a) -{ - uint res = AY; - uint ea = EA_AX_AI_32(); - - m68ki_write_32(ea, res); - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 32, ai, .) -{ - uint res = M68KMAKE_GET_OPER_AY_32; - uint ea = EA_AX_AI_32(); - - m68ki_write_32(ea, res); - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 32, pi, d) -{ - uint res = DY; - uint ea = EA_AX_PI_32(); - - m68ki_write_32(ea, res); - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 32, pi, a) -{ - uint res = AY; - uint ea = EA_AX_PI_32(); - - m68ki_write_32(ea, res); - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 32, pi, .) -{ - uint res = M68KMAKE_GET_OPER_AY_32; - uint ea = EA_AX_PI_32(); - - m68ki_write_32(ea, res); - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 32, pd, d) -{ - uint res = DY; - uint ea = EA_AX_PD_32(); - - m68ki_write_16(ea+2, res & 0xFFFF ); - m68ki_write_16(ea, (res >> 16) & 0xFFFF ); - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 32, pd, a) -{ - uint res = AY; - uint ea = EA_AX_PD_32(); - - m68ki_write_16(ea+2, res & 0xFFFF ); - m68ki_write_16(ea, (res >> 16) & 0xFFFF ); - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 32, pd, .) -{ - uint res = M68KMAKE_GET_OPER_AY_32; - uint ea = EA_AX_PD_32(); - - m68ki_write_16(ea+2, res & 0xFFFF ); - m68ki_write_16(ea, (res >> 16) & 0xFFFF ); - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 32, di, d) -{ - uint res = DY; - uint ea = EA_AX_DI_32(); - - m68ki_write_32(ea, res); - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 32, di, a) -{ - uint res = AY; - uint ea = EA_AX_DI_32(); - - m68ki_write_32(ea, res); - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 32, di, .) -{ - uint res = M68KMAKE_GET_OPER_AY_32; - uint ea = EA_AX_DI_32(); - - m68ki_write_32(ea, res); - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 32, ix, d) -{ - uint res = DY; - uint ea = EA_AX_IX_32(); - - m68ki_write_32(ea, res); - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 32, ix, a) -{ - uint res = AY; - uint ea = EA_AX_IX_32(); - - m68ki_write_32(ea, res); - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 32, ix, .) -{ - uint res = M68KMAKE_GET_OPER_AY_32; - uint ea = EA_AX_IX_32(); - - m68ki_write_32(ea, res); - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 32, aw, d) -{ - uint res = DY; - uint ea = EA_AW_32(); - - m68ki_write_32(ea, res); - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 32, aw, a) -{ - uint res = AY; - uint ea = EA_AW_32(); - - m68ki_write_32(ea, res); - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 32, aw, .) -{ - uint res = M68KMAKE_GET_OPER_AY_32; - uint ea = EA_AW_32(); - - m68ki_write_32(ea, res); - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 32, al, d) -{ - uint res = DY; - uint ea = EA_AL_32(); - - m68ki_write_32(ea, res); - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 32, al, a) -{ - uint res = AY; - uint ea = EA_AL_32(); - - m68ki_write_32(ea, res); - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move, 32, al, .) -{ - uint res = M68KMAKE_GET_OPER_AY_32; - uint ea = EA_AL_32(); - - m68ki_write_32(ea, res); - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(movea, 16, ., d) -{ - AX = MAKE_INT_16(DY); -} - - -M68KMAKE_OP(movea, 16, ., a) -{ - AX = MAKE_INT_16(AY); -} - - -M68KMAKE_OP(movea, 16, ., .) -{ - AX = MAKE_INT_16(M68KMAKE_GET_OPER_AY_16); -} - - -M68KMAKE_OP(movea, 32, ., d) -{ - AX = DY; -} - - -M68KMAKE_OP(movea, 32, ., a) -{ - AX = AY; -} - - -M68KMAKE_OP(movea, 32, ., .) -{ - AX = M68KMAKE_GET_OPER_AY_32; -} - - -M68KMAKE_OP(move, 16, frc, d) -{ - if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) - { - DY = MASK_OUT_BELOW_16(DY) | m68ki_get_ccr(); - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(move, 16, frc, .) -{ - if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) - { - m68ki_write_16(M68KMAKE_GET_EA_AY_16, m68ki_get_ccr()); - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(move, 16, toc, d) -{ - m68ki_set_ccr(DY); -} - - -M68KMAKE_OP(move, 16, toc, .) -{ - m68ki_set_ccr(M68KMAKE_GET_OPER_AY_16); -} - - -M68KMAKE_OP(move, 16, frs, d) -{ - if(CPU_TYPE_IS_000(CPU_TYPE) || FLAG_S) /* NS990408 */ - { - DY = MASK_OUT_BELOW_16(DY) | m68ki_get_sr(); - return; - } - m68ki_exception_privilege_violation(); -} - - -M68KMAKE_OP(move, 16, frs, .) -{ - if(CPU_TYPE_IS_000(CPU_TYPE) || FLAG_S) /* NS990408 */ - { - uint ea = M68KMAKE_GET_EA_AY_16; - m68ki_write_16(ea, m68ki_get_sr()); - return; - } - m68ki_exception_privilege_violation(); -} - - -M68KMAKE_OP(move, 16, tos, d) -{ - if(FLAG_S) - { - m68ki_set_sr(DY); - return; - } - m68ki_exception_privilege_violation(); -} - - -M68KMAKE_OP(move, 16, tos, .) -{ - if(FLAG_S) - { - uint new_sr = M68KMAKE_GET_OPER_AY_16; - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - m68ki_set_sr(new_sr); - return; - } - m68ki_exception_privilege_violation(); -} - - -M68KMAKE_OP(move, 32, fru, .) -{ - if(FLAG_S) - { - AY = REG_USP; - return; - } - m68ki_exception_privilege_violation(); -} - - -M68KMAKE_OP(move, 32, tou, .) -{ - if(FLAG_S) - { - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - REG_USP = AY; - return; - } - m68ki_exception_privilege_violation(); -} - - -M68KMAKE_OP(movec, 32, cr, .) -{ - if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) - { - if(FLAG_S) - { - uint word2 = OPER_I_16(); - - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - switch (word2 & 0xfff) - { - case 0x000: /* SFC */ - REG_DA[(word2 >> 12) & 15] = REG_SFC; - return; - case 0x001: /* DFC */ - REG_DA[(word2 >> 12) & 15] = REG_DFC; - return; - case 0x002: /* CACR */ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - REG_DA[(word2 >> 12) & 15] = REG_CACR; - return; - } - return; - case 0x800: /* USP */ - REG_DA[(word2 >> 12) & 15] = REG_USP; - return; - case 0x801: /* VBR */ - REG_DA[(word2 >> 12) & 15] = REG_VBR; - return; - case 0x802: /* CAAR */ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - REG_DA[(word2 >> 12) & 15] = REG_CAAR; - return; - } - m68ki_exception_illegal(); - break; - case 0x803: /* MSP */ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - REG_DA[(word2 >> 12) & 15] = FLAG_M ? REG_SP : REG_MSP; - return; - } - m68ki_exception_illegal(); - return; - case 0x804: /* ISP */ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - REG_DA[(word2 >> 12) & 15] = FLAG_M ? REG_ISP : REG_SP; - return; - } - m68ki_exception_illegal(); - return; - case 0x003: /* TC */ - if(CPU_TYPE_IS_040_PLUS(CPU_TYPE)) - { - /* TODO */ - return; - } - m68ki_exception_illegal(); - return; - case 0x004: /* ITT0 */ - if(CPU_TYPE_IS_040_PLUS(CPU_TYPE)) - { - /* TODO */ - return; - } - m68ki_exception_illegal(); - return; - case 0x005: /* ITT1 */ - if(CPU_TYPE_IS_040_PLUS(CPU_TYPE)) - { - /* TODO */ - return; - } - m68ki_exception_illegal(); - return; - case 0x006: /* DTT0 */ - if(CPU_TYPE_IS_040_PLUS(CPU_TYPE)) - { - /* TODO */ - return; - } - m68ki_exception_illegal(); - return; - case 0x007: /* DTT1 */ - if(CPU_TYPE_IS_040_PLUS(CPU_TYPE)) - { - /* TODO */ - return; - } - m68ki_exception_illegal(); - return; - case 0x805: /* MMUSR */ - if(CPU_TYPE_IS_040_PLUS(CPU_TYPE)) - { - /* TODO */ - return; - } - m68ki_exception_illegal(); - return; - case 0x806: /* URP */ - if(CPU_TYPE_IS_040_PLUS(CPU_TYPE)) - { - /* TODO */ - return; - } - m68ki_exception_illegal(); - return; - case 0x807: /* SRP */ - if(CPU_TYPE_IS_040_PLUS(CPU_TYPE)) - { - /* TODO */ - return; - } - m68ki_exception_illegal(); - return; - default: - m68ki_exception_illegal(); - return; - } - } - m68ki_exception_privilege_violation(); - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(movec, 32, rc, .) -{ - if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) - { - if(FLAG_S) - { - uint word2 = OPER_I_16(); - - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - switch (word2 & 0xfff) - { - case 0x000: /* SFC */ - REG_SFC = REG_DA[(word2 >> 12) & 15] & 7; - return; - case 0x001: /* DFC */ - REG_DFC = REG_DA[(word2 >> 12) & 15] & 7; - return; - case 0x002: /* CACR */ - /* Only EC020 and later have CACR */ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - /* 68030 can write all bits except 5-7, 040 can write all */ - if (CPU_TYPE_IS_040_PLUS(CPU_TYPE)) - { - REG_CACR = REG_DA[(word2 >> 12) & 15]; - } - else if (CPU_TYPE_IS_030_PLUS(CPU_TYPE)) - { - REG_CACR = REG_DA[(word2 >> 12) & 15] & 0xff1f; - } - else - { - REG_CACR = REG_DA[(word2 >> 12) & 15] & 0x0f; - } - return; - } - m68ki_exception_illegal(); - return; - case 0x800: /* USP */ - REG_USP = REG_DA[(word2 >> 12) & 15]; - return; - case 0x801: /* VBR */ - REG_VBR = REG_DA[(word2 >> 12) & 15]; - return; - case 0x802: /* CAAR */ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - REG_CAAR = REG_DA[(word2 >> 12) & 15]; - return; - } - m68ki_exception_illegal(); - return; - case 0x803: /* MSP */ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - /* we are in supervisor mode so just check for M flag */ - if(!FLAG_M) - { - REG_MSP = REG_DA[(word2 >> 12) & 15]; - return; - } - REG_SP = REG_DA[(word2 >> 12) & 15]; - return; - } - m68ki_exception_illegal(); - return; - case 0x804: /* ISP */ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - if(!FLAG_M) - { - REG_SP = REG_DA[(word2 >> 12) & 15]; - return; - } - REG_ISP = REG_DA[(word2 >> 12) & 15]; - return; - } - m68ki_exception_illegal(); - return; - case 0x003: /* TC */ - if (CPU_TYPE_IS_040_PLUS(CPU_TYPE)) - { - /* TODO */ - return; - } - m68ki_exception_illegal(); - return; - case 0x004: /* ITT0 */ - if (CPU_TYPE_IS_040_PLUS(CPU_TYPE)) - { - /* TODO */ - return; - } - m68ki_exception_illegal(); - return; - case 0x005: /* ITT1 */ - if (CPU_TYPE_IS_040_PLUS(CPU_TYPE)) - { - /* TODO */ - return; - } - m68ki_exception_illegal(); - return; - case 0x006: /* DTT0 */ - if (CPU_TYPE_IS_040_PLUS(CPU_TYPE)) - { - /* TODO */ - return; - } - m68ki_exception_illegal(); - return; - case 0x007: /* DTT1 */ - if (CPU_TYPE_IS_040_PLUS(CPU_TYPE)) - { - /* TODO */ - return; - } - m68ki_exception_illegal(); - return; - case 0x805: /* MMUSR */ - if (CPU_TYPE_IS_040_PLUS(CPU_TYPE)) - { - /* TODO */ - return; - } - m68ki_exception_illegal(); - return; - case 0x806: /* URP */ - if (CPU_TYPE_IS_040_PLUS(CPU_TYPE)) - { - /* TODO */ - return; - } - m68ki_exception_illegal(); - return; - case 0x807: /* SRP */ - if (CPU_TYPE_IS_040_PLUS(CPU_TYPE)) - { - /* TODO */ - return; - } - m68ki_exception_illegal(); - return; - default: - m68ki_exception_illegal(); - return; - } - } - m68ki_exception_privilege_violation(); - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(movem, 16, re, pd) -{ - uint i = 0; - uint register_list = OPER_I_16(); - uint ea = AY; - uint count = 0; - - for(; i < 16; i++) - if(register_list & (1 << i)) - { - ea -= 2; - m68ki_write_16(ea, MASK_OUT_ABOVE_16(REG_DA[15-i])); - count++; - } - AY = ea; - - USE_CYCLES(count<> 16) & 0xFFFF ); - count++; - } - AY = ea; - - USE_CYCLES(count<> 8)); - m68ki_write_8(ea += 2, MASK_OUT_ABOVE_8(src)); -} - - -M68KMAKE_OP(movep, 32, re, .) -{ - uint ea = EA_AY_DI_32(); - uint src = DX; - - m68ki_write_8(ea, MASK_OUT_ABOVE_8(src >> 24)); - m68ki_write_8(ea += 2, MASK_OUT_ABOVE_8(src >> 16)); - m68ki_write_8(ea += 2, MASK_OUT_ABOVE_8(src >> 8)); - m68ki_write_8(ea += 2, MASK_OUT_ABOVE_8(src)); -} - - -M68KMAKE_OP(movep, 16, er, .) -{ - uint ea = EA_AY_DI_16(); - uint* r_dst = &DX; - - *r_dst = MASK_OUT_BELOW_16(*r_dst) | ((m68ki_read_8(ea) << 8) + m68ki_read_8(ea + 2)); -} - - -M68KMAKE_OP(movep, 32, er, .) -{ - uint ea = EA_AY_DI_32(); - - DX = (m68ki_read_8(ea) << 24) + (m68ki_read_8(ea + 2) << 16) - + (m68ki_read_8(ea + 4) << 8) + m68ki_read_8(ea + 6); -} - - -M68KMAKE_OP(moves, 8, ., .) -{ - if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) - { - if(FLAG_S) - { - uint word2 = OPER_I_16(); - uint ea = M68KMAKE_GET_EA_AY_8; - - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - if(BIT_B(word2)) /* Register to memory */ - { - m68ki_write_8_fc(ea, REG_DFC, MASK_OUT_ABOVE_8(REG_DA[(word2 >> 12) & 15])); - return; - } - if(BIT_F(word2)) /* Memory to address register */ - { - REG_A[(word2 >> 12) & 7] = MAKE_INT_8(m68ki_read_8_fc(ea, REG_SFC)); - if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) - USE_CYCLES(2); - return; - } - /* Memory to data register */ - REG_D[(word2 >> 12) & 7] = MASK_OUT_BELOW_8(REG_D[(word2 >> 12) & 7]) | m68ki_read_8_fc(ea, REG_SFC); - if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) - USE_CYCLES(2); - return; - } - m68ki_exception_privilege_violation(); - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(moves, 16, ., .) -{ - if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) - { - if(FLAG_S) - { - uint word2 = OPER_I_16(); - uint ea = M68KMAKE_GET_EA_AY_16; - - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - if(BIT_B(word2)) /* Register to memory */ - { - m68ki_write_16_fc(ea, REG_DFC, MASK_OUT_ABOVE_16(REG_DA[(word2 >> 12) & 15])); - return; - } - if(BIT_F(word2)) /* Memory to address register */ - { - REG_A[(word2 >> 12) & 7] = MAKE_INT_16(m68ki_read_16_fc(ea, REG_SFC)); - if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) - USE_CYCLES(2); - return; - } - /* Memory to data register */ - REG_D[(word2 >> 12) & 7] = MASK_OUT_BELOW_16(REG_D[(word2 >> 12) & 7]) | m68ki_read_16_fc(ea, REG_SFC); - if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) - USE_CYCLES(2); - return; - } - m68ki_exception_privilege_violation(); - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(moves, 32, ., .) -{ - if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) - { - if(FLAG_S) - { - uint word2 = OPER_I_16(); - uint ea = M68KMAKE_GET_EA_AY_32; - - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - if(BIT_B(word2)) /* Register to memory */ - { - m68ki_write_32_fc(ea, REG_DFC, REG_DA[(word2 >> 12) & 15]); - if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) - USE_CYCLES(2); - return; - } - /* Memory to register */ - REG_DA[(word2 >> 12) & 15] = m68ki_read_32_fc(ea, REG_SFC); - if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) - USE_CYCLES(2); - return; - } - m68ki_exception_privilege_violation(); - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(moveq, 32, ., .) -{ - uint res = DX = MAKE_INT_8(MASK_OUT_ABOVE_8(REG_IR)); - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(move16, 32, ., .) -{ - uint16 w2 = OPER_I_16(); - int ax = REG_IR & 7; - int ay = (w2 >> 12) & 7; - - m68ki_write_32(REG_A[ay], m68ki_read_32(REG_A[ax])); - m68ki_write_32(REG_A[ay]+4, m68ki_read_32(REG_A[ax]+4)); - m68ki_write_32(REG_A[ay]+8, m68ki_read_32(REG_A[ax]+8)); - m68ki_write_32(REG_A[ay]+12, m68ki_read_32(REG_A[ax]+12)); - - REG_A[ax] += 16; - REG_A[ay] += 16; -} - - -M68KMAKE_OP(muls, 16, ., d) -{ - uint* r_dst = &DX; - uint res = MASK_OUT_ABOVE_32(MAKE_INT_16(DY) * MAKE_INT_16(MASK_OUT_ABOVE_16(*r_dst))); - - *r_dst = res; - - FLAG_Z = res; - FLAG_N = NFLAG_32(res); - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(muls, 16, ., .) -{ - uint* r_dst = &DX; - uint res = MASK_OUT_ABOVE_32(MAKE_INT_16(M68KMAKE_GET_OPER_AY_16) * MAKE_INT_16(MASK_OUT_ABOVE_16(*r_dst))); - - *r_dst = res; - - FLAG_Z = res; - FLAG_N = NFLAG_32(res); - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(mulu, 16, ., d) -{ - uint* r_dst = &DX; - uint res = MASK_OUT_ABOVE_16(DY) * MASK_OUT_ABOVE_16(*r_dst); - - *r_dst = res; - - FLAG_Z = res; - FLAG_N = NFLAG_32(res); - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(mulu, 16, ., .) -{ - uint* r_dst = &DX; - uint res = M68KMAKE_GET_OPER_AY_16 * MASK_OUT_ABOVE_16(*r_dst); - - *r_dst = res; - - FLAG_Z = res; - FLAG_N = NFLAG_32(res); - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(mull, 32, ., d) -{ -#if M68K_USE_64_BIT - - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint word2 = OPER_I_16(); - uint64 src = DY; - uint64 dst = REG_D[(word2 >> 12) & 7]; - uint64 res; - - FLAG_C = CFLAG_CLEAR; - - if(BIT_B(word2)) /* signed */ - { - res = (sint64)((sint32)src) * (sint64)((sint32)dst); - if(!BIT_A(word2)) - { - FLAG_Z = MASK_OUT_ABOVE_32(res); - FLAG_N = NFLAG_32(res); - FLAG_V = ((sint64)res != (sint32)res)<<7; - REG_D[(word2 >> 12) & 7] = FLAG_Z; - return; - } - FLAG_Z = MASK_OUT_ABOVE_32(res) | (res>>32); - FLAG_N = NFLAG_64(res); - FLAG_V = VFLAG_CLEAR; - REG_D[word2 & 7] = (res >> 32); - REG_D[(word2 >> 12) & 7] = MASK_OUT_ABOVE_32(res); - return; - } - - res = src * dst; - if(!BIT_A(word2)) - { - FLAG_Z = MASK_OUT_ABOVE_32(res); - FLAG_N = NFLAG_32(res); - FLAG_V = (res > 0xffffffff)<<7; - REG_D[(word2 >> 12) & 7] = FLAG_Z; - return; - } - FLAG_Z = MASK_OUT_ABOVE_32(res) | (res>>32); - FLAG_N = NFLAG_64(res); - FLAG_V = VFLAG_CLEAR; - REG_D[word2 & 7] = (res >> 32); - REG_D[(word2 >> 12) & 7] = MASK_OUT_ABOVE_32(res); - return; - } - m68ki_exception_illegal(); - -#else - - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint word2 = OPER_I_16(); - uint src = DY; - uint dst = REG_D[(word2 >> 12) & 7]; - uint neg = GET_MSB_32(src ^ dst); - uint src1; - uint src2; - uint dst1; - uint dst2; - uint r1; - uint r2; - uint r3; - uint r4; - uint lo; - uint hi; - - FLAG_C = CFLAG_CLEAR; - - if(BIT_B(word2)) /* signed */ - { - if(GET_MSB_32(src)) - src = (uint)MASK_OUT_ABOVE_32(-(sint)src); - if(GET_MSB_32(dst)) - dst = (uint)MASK_OUT_ABOVE_32(-(sint)dst); - } - - src1 = MASK_OUT_ABOVE_16(src); - src2 = src>>16; - dst1 = MASK_OUT_ABOVE_16(dst); - dst2 = dst>>16; - - - r1 = src1 * dst1; - r2 = src1 * dst2; - r3 = src2 * dst1; - r4 = src2 * dst2; - - lo = r1 + (MASK_OUT_ABOVE_16(r2)<<16) + (MASK_OUT_ABOVE_16(r3)<<16); - hi = r4 + (r2>>16) + (r3>>16) + (((r1>>16) + MASK_OUT_ABOVE_16(r2) + MASK_OUT_ABOVE_16(r3)) >> 16); - - if(BIT_B(word2) && neg) - { - hi = (uint)MASK_OUT_ABOVE_32((-(sint)hi) - (lo != 0)); - lo = (uint)MASK_OUT_ABOVE_32(-(sint)lo); - } - - if(BIT_A(word2)) - { - REG_D[word2 & 7] = hi; - REG_D[(word2 >> 12) & 7] = lo; - FLAG_N = NFLAG_32(hi); - FLAG_Z = hi | lo; - FLAG_V = VFLAG_CLEAR; - return; - } - - REG_D[(word2 >> 12) & 7] = lo; - FLAG_N = NFLAG_32(lo); - FLAG_Z = lo; - if(BIT_B(word2)) - FLAG_V = (!((GET_MSB_32(lo) && hi == 0xffffffff) || (!GET_MSB_32(lo) && !hi)))<<7; - else - FLAG_V = (hi != 0) << 7; - return; - } - m68ki_exception_illegal(); - -#endif -} - - -M68KMAKE_OP(mull, 32, ., .) -{ -#if M68K_USE_64_BIT - - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint word2 = OPER_I_16(); - uint64 src = M68KMAKE_GET_OPER_AY_32; - uint64 dst = REG_D[(word2 >> 12) & 7]; - uint64 res; - - FLAG_C = CFLAG_CLEAR; - - if(BIT_B(word2)) /* signed */ - { - res = (sint64)((sint32)src) * (sint64)((sint32)dst); - if(!BIT_A(word2)) - { - FLAG_Z = MASK_OUT_ABOVE_32(res); - FLAG_N = NFLAG_32(res); - FLAG_V = ((sint64)res != (sint32)res)<<7; - REG_D[(word2 >> 12) & 7] = FLAG_Z; - return; - } - FLAG_Z = MASK_OUT_ABOVE_32(res) | (res>>32); - FLAG_N = NFLAG_64(res); - FLAG_V = VFLAG_CLEAR; - REG_D[word2 & 7] = (res >> 32); - REG_D[(word2 >> 12) & 7] = MASK_OUT_ABOVE_32(res); - return; - } - - res = src * dst; - if(!BIT_A(word2)) - { - FLAG_Z = MASK_OUT_ABOVE_32(res); - FLAG_N = NFLAG_32(res); - FLAG_V = (res > 0xffffffff)<<7; - REG_D[(word2 >> 12) & 7] = FLAG_Z; - return; - } - FLAG_Z = MASK_OUT_ABOVE_32(res) | (res>>32); - FLAG_N = NFLAG_64(res); - FLAG_V = VFLAG_CLEAR; - REG_D[word2 & 7] = (res >> 32); - REG_D[(word2 >> 12) & 7] = MASK_OUT_ABOVE_32(res); - return; - } - m68ki_exception_illegal(); - -#else - - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint word2 = OPER_I_16(); - uint src = M68KMAKE_GET_OPER_AY_32; - uint dst = REG_D[(word2 >> 12) & 7]; - uint neg = GET_MSB_32(src ^ dst); - uint src1; - uint src2; - uint dst1; - uint dst2; - uint r1; - uint r2; - uint r3; - uint r4; - uint lo; - uint hi; - - FLAG_C = CFLAG_CLEAR; - - if(BIT_B(word2)) /* signed */ - { - if(GET_MSB_32(src)) - src = (uint)MASK_OUT_ABOVE_32(-(sint)src); - if(GET_MSB_32(dst)) - dst = (uint)MASK_OUT_ABOVE_32(-(sint)dst); - } - - src1 = MASK_OUT_ABOVE_16(src); - src2 = src>>16; - dst1 = MASK_OUT_ABOVE_16(dst); - dst2 = dst>>16; - - - r1 = src1 * dst1; - r2 = src1 * dst2; - r3 = src2 * dst1; - r4 = src2 * dst2; - - lo = r1 + (MASK_OUT_ABOVE_16(r2)<<16) + (MASK_OUT_ABOVE_16(r3)<<16); - hi = r4 + (r2>>16) + (r3>>16) + (((r1>>16) + MASK_OUT_ABOVE_16(r2) + MASK_OUT_ABOVE_16(r3)) >> 16); - - if(BIT_B(word2) && neg) - { - hi = (uint)MASK_OUT_ABOVE_32((-(sint)hi) - (lo != 0)); - lo = (uint)MASK_OUT_ABOVE_32(-(sint)lo); - } - - if(BIT_A(word2)) - { - REG_D[word2 & 7] = hi; - REG_D[(word2 >> 12) & 7] = lo; - FLAG_N = NFLAG_32(hi); - FLAG_Z = hi | lo; - FLAG_V = VFLAG_CLEAR; - return; - } - - REG_D[(word2 >> 12) & 7] = lo; - FLAG_N = NFLAG_32(lo); - FLAG_Z = lo; - if(BIT_B(word2)) - FLAG_V = (!((GET_MSB_32(lo) && hi == 0xffffffff) || (!GET_MSB_32(lo) && !hi)))<<7; - else - FLAG_V = (hi != 0) << 7; - return; - } - m68ki_exception_illegal(); - -#endif -} - - -M68KMAKE_OP(nbcd, 8, ., d) -{ - uint* r_dst = &DY; - uint dst = *r_dst; - uint res = MASK_OUT_ABOVE_8(0x9a - dst - XFLAG_AS_1()); - - if(res != 0x9a) - { - FLAG_V = ~res; /* Undefined V behavior */ - - if((res & 0x0f) == 0xa) - res = (res & 0xf0) + 0x10; - - res = MASK_OUT_ABOVE_8(res); - - FLAG_V &= res; /* Undefined V behavior part II */ - - *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; - - FLAG_Z |= res; - FLAG_C = CFLAG_SET; - FLAG_X = XFLAG_SET; - } - else - { - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - FLAG_X = XFLAG_CLEAR; - } - FLAG_N = NFLAG_8(res); /* Undefined N behavior */ -} - - -M68KMAKE_OP(nbcd, 8, ., .) -{ - uint ea = M68KMAKE_GET_EA_AY_8; - uint dst = m68ki_read_8(ea); - uint res = MASK_OUT_ABOVE_8(0x9a - dst - XFLAG_AS_1()); - - if(res != 0x9a) - { - FLAG_V = ~res; /* Undefined V behavior */ - - if((res & 0x0f) == 0xa) - res = (res & 0xf0) + 0x10; - - res = MASK_OUT_ABOVE_8(res); - - FLAG_V &= res; /* Undefined V behavior part II */ - - m68ki_write_8(ea, MASK_OUT_ABOVE_8(res)); - - FLAG_Z |= res; - FLAG_C = CFLAG_SET; - FLAG_X = XFLAG_SET; - } - else - { - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - FLAG_X = XFLAG_CLEAR; - } - FLAG_N = NFLAG_8(res); /* Undefined N behavior */ -} - - -M68KMAKE_OP(neg, 8, ., d) -{ - uint* r_dst = &DY; - uint res = 0 - MASK_OUT_ABOVE_8(*r_dst); - - FLAG_N = NFLAG_8(res); - FLAG_C = FLAG_X = CFLAG_8(res); - FLAG_V = *r_dst & res; - FLAG_Z = MASK_OUT_ABOVE_8(res); - - *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; -} - - -M68KMAKE_OP(neg, 8, ., .) -{ - uint ea = M68KMAKE_GET_EA_AY_8; - uint src = m68ki_read_8(ea); - uint res = 0 - src; - - FLAG_N = NFLAG_8(res); - FLAG_C = FLAG_X = CFLAG_8(res); - FLAG_V = src & res; - FLAG_Z = MASK_OUT_ABOVE_8(res); - - m68ki_write_8(ea, FLAG_Z); -} - - -M68KMAKE_OP(neg, 16, ., d) -{ - uint* r_dst = &DY; - uint res = 0 - MASK_OUT_ABOVE_16(*r_dst); - - FLAG_N = NFLAG_16(res); - FLAG_C = FLAG_X = CFLAG_16(res); - FLAG_V = (*r_dst & res)>>8; - FLAG_Z = MASK_OUT_ABOVE_16(res); - - *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; -} - - -M68KMAKE_OP(neg, 16, ., .) -{ - uint ea = M68KMAKE_GET_EA_AY_16; - uint src = m68ki_read_16(ea); - uint res = 0 - src; - - FLAG_N = NFLAG_16(res); - FLAG_C = FLAG_X = CFLAG_16(res); - FLAG_V = (src & res)>>8; - FLAG_Z = MASK_OUT_ABOVE_16(res); - - m68ki_write_16(ea, FLAG_Z); -} - - -M68KMAKE_OP(neg, 32, ., d) -{ - uint* r_dst = &DY; - uint res = 0 - *r_dst; - - FLAG_N = NFLAG_32(res); - FLAG_C = FLAG_X = CFLAG_SUB_32(*r_dst, 0, res); - FLAG_V = (*r_dst & res)>>24; - FLAG_Z = MASK_OUT_ABOVE_32(res); - - *r_dst = FLAG_Z; -} - - -M68KMAKE_OP(neg, 32, ., .) -{ - uint ea = M68KMAKE_GET_EA_AY_32; - uint src = m68ki_read_32(ea); - uint res = 0 - src; - - FLAG_N = NFLAG_32(res); - FLAG_C = FLAG_X = CFLAG_SUB_32(src, 0, res); - FLAG_V = (src & res)>>24; - FLAG_Z = MASK_OUT_ABOVE_32(res); - - m68ki_write_32(ea, FLAG_Z); -} - - -M68KMAKE_OP(negx, 8, ., d) -{ - uint* r_dst = &DY; - uint res = 0 - MASK_OUT_ABOVE_8(*r_dst) - XFLAG_AS_1(); - - FLAG_N = NFLAG_8(res); - FLAG_X = FLAG_C = CFLAG_8(res); - FLAG_V = *r_dst & res; - - res = MASK_OUT_ABOVE_8(res); - FLAG_Z |= res; - - *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; -} - - -M68KMAKE_OP(negx, 8, ., .) -{ - uint ea = M68KMAKE_GET_EA_AY_8; - uint src = m68ki_read_8(ea); - uint res = 0 - src - XFLAG_AS_1(); - - FLAG_N = NFLAG_8(res); - FLAG_X = FLAG_C = CFLAG_8(res); - FLAG_V = src & res; - - res = MASK_OUT_ABOVE_8(res); - FLAG_Z |= res; - - m68ki_write_8(ea, res); -} - - -M68KMAKE_OP(negx, 16, ., d) -{ - uint* r_dst = &DY; - uint res = 0 - MASK_OUT_ABOVE_16(*r_dst) - XFLAG_AS_1(); - - FLAG_N = NFLAG_16(res); - FLAG_X = FLAG_C = CFLAG_16(res); - FLAG_V = (*r_dst & res)>>8; - - res = MASK_OUT_ABOVE_16(res); - FLAG_Z |= res; - - *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; -} - - -M68KMAKE_OP(negx, 16, ., .) -{ - uint ea = M68KMAKE_GET_EA_AY_16; - uint src = m68ki_read_16(ea); - uint res = 0 - MASK_OUT_ABOVE_16(src) - XFLAG_AS_1(); - - FLAG_N = NFLAG_16(res); - FLAG_X = FLAG_C = CFLAG_16(res); - FLAG_V = (src & res)>>8; - - res = MASK_OUT_ABOVE_16(res); - FLAG_Z |= res; - - m68ki_write_16(ea, res); -} - - -M68KMAKE_OP(negx, 32, ., d) -{ - uint* r_dst = &DY; - uint res = 0 - MASK_OUT_ABOVE_32(*r_dst) - XFLAG_AS_1(); - - FLAG_N = NFLAG_32(res); - FLAG_X = FLAG_C = CFLAG_SUB_32(*r_dst, 0, res); - FLAG_V = (*r_dst & res)>>24; - - res = MASK_OUT_ABOVE_32(res); - FLAG_Z |= res; - - *r_dst = res; -} - - -M68KMAKE_OP(negx, 32, ., .) -{ - uint ea = M68KMAKE_GET_EA_AY_32; - uint src = m68ki_read_32(ea); - uint res = 0 - MASK_OUT_ABOVE_32(src) - XFLAG_AS_1(); - - FLAG_N = NFLAG_32(res); - FLAG_X = FLAG_C = CFLAG_SUB_32(src, 0, res); - FLAG_V = (src & res)>>24; - - res = MASK_OUT_ABOVE_32(res); - FLAG_Z |= res; - - m68ki_write_32(ea, res); -} - - -M68KMAKE_OP(nop, 0, ., .) -{ - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ -} - - -M68KMAKE_OP(not, 8, ., d) -{ - uint* r_dst = &DY; - uint res = MASK_OUT_ABOVE_8(~*r_dst); - - *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(not, 8, ., .) -{ - uint ea = M68KMAKE_GET_EA_AY_8; - uint res = MASK_OUT_ABOVE_8(~m68ki_read_8(ea)); - - m68ki_write_8(ea, res); - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(not, 16, ., d) -{ - uint* r_dst = &DY; - uint res = MASK_OUT_ABOVE_16(~*r_dst); - - *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(not, 16, ., .) -{ - uint ea = M68KMAKE_GET_EA_AY_16; - uint res = MASK_OUT_ABOVE_16(~m68ki_read_16(ea)); - - m68ki_write_16(ea, res); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(not, 32, ., d) -{ - uint* r_dst = &DY; - uint res = *r_dst = MASK_OUT_ABOVE_32(~*r_dst); - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(not, 32, ., .) -{ - uint ea = M68KMAKE_GET_EA_AY_32; - uint res = MASK_OUT_ABOVE_32(~m68ki_read_32(ea)); - - m68ki_write_32(ea, res); - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(or, 8, er, d) -{ - uint res = MASK_OUT_ABOVE_8((DX |= MASK_OUT_ABOVE_8(DY))); - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(or, 8, er, .) -{ - uint res = MASK_OUT_ABOVE_8((DX |= M68KMAKE_GET_OPER_AY_8)); - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(or, 16, er, d) -{ - uint res = MASK_OUT_ABOVE_16((DX |= MASK_OUT_ABOVE_16(DY))); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(or, 16, er, .) -{ - uint res = MASK_OUT_ABOVE_16((DX |= M68KMAKE_GET_OPER_AY_16)); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(or, 32, er, d) -{ - uint res = DX |= DY; - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(or, 32, er, .) -{ - uint res = DX |= M68KMAKE_GET_OPER_AY_32; - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(or, 8, re, .) -{ - uint ea = M68KMAKE_GET_EA_AY_8; - uint res = MASK_OUT_ABOVE_8(DX | m68ki_read_8(ea)); - - m68ki_write_8(ea, res); - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(or, 16, re, .) -{ - uint ea = M68KMAKE_GET_EA_AY_16; - uint res = MASK_OUT_ABOVE_16(DX | m68ki_read_16(ea)); - - m68ki_write_16(ea, res); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(or, 32, re, .) -{ - uint ea = M68KMAKE_GET_EA_AY_32; - uint res = DX | m68ki_read_32(ea); - - m68ki_write_32(ea, res); - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(ori, 8, ., d) -{ - uint res = MASK_OUT_ABOVE_8((DY |= OPER_I_8())); - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(ori, 8, ., .) -{ - uint src = OPER_I_8(); - uint ea = M68KMAKE_GET_EA_AY_8; - uint res = MASK_OUT_ABOVE_8(src | m68ki_read_8(ea)); - - m68ki_write_8(ea, res); - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(ori, 16, ., d) -{ - uint res = MASK_OUT_ABOVE_16(DY |= OPER_I_16()); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(ori, 16, ., .) -{ - uint src = OPER_I_16(); - uint ea = M68KMAKE_GET_EA_AY_16; - uint res = MASK_OUT_ABOVE_16(src | m68ki_read_16(ea)); - - m68ki_write_16(ea, res); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(ori, 32, ., d) -{ - uint res = DY |= OPER_I_32(); - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(ori, 32, ., .) -{ - uint src = OPER_I_32(); - uint ea = M68KMAKE_GET_EA_AY_32; - uint res = src | m68ki_read_32(ea); - - m68ki_write_32(ea, res); - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(ori, 16, toc, .) -{ - m68ki_set_ccr(m68ki_get_ccr() | OPER_I_8()); -} - - -M68KMAKE_OP(ori, 16, tos, .) -{ - if(FLAG_S) - { - uint src = OPER_I_16(); - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - m68ki_set_sr(m68ki_get_sr() | src); - return; - } - m68ki_exception_privilege_violation(); -} - - -M68KMAKE_OP(pack, 16, rr, .) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - /* Note: DX and DY are reversed in Motorola's docs */ - uint src = DY + OPER_I_16(); - uint* r_dst = &DX; - - *r_dst = MASK_OUT_BELOW_8(*r_dst) | ((src >> 4) & 0x00f0) | (src & 0x000f); - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(pack, 16, mm, ax7) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - /* Note: AX and AY are reversed in Motorola's docs */ - uint ea_src = EA_AY_PD_8(); - uint src = m68ki_read_8(ea_src); - ea_src = EA_AY_PD_8(); - src = ((src << 8) | m68ki_read_8(ea_src)) + OPER_I_16(); - - m68ki_write_8(EA_A7_PD_8(), ((src >> 4) & 0x00f0) | (src & 0x000f)); - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(pack, 16, mm, ay7) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - /* Note: AX and AY are reversed in Motorola's docs */ - uint ea_src = EA_A7_PD_8(); - uint src = m68ki_read_8(ea_src); - ea_src = EA_A7_PD_8(); - src = ((src << 8) | m68ki_read_8(ea_src)) + OPER_I_16(); - - m68ki_write_8(EA_AX_PD_8(), ((src >> 4) & 0x00f0) | (src & 0x000f)); - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(pack, 16, mm, axy7) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint ea_src = EA_A7_PD_8(); - uint src = m68ki_read_8(ea_src); - ea_src = EA_A7_PD_8(); - src = ((src << 8) | m68ki_read_8(ea_src)) + OPER_I_16(); - - m68ki_write_8(EA_A7_PD_8(), ((src >> 4) & 0x00f0) | (src & 0x000f)); - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(pack, 16, mm, .) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - /* Note: AX and AY are reversed in Motorola's docs */ - uint ea_src = EA_AY_PD_8(); - uint src = m68ki_read_8(ea_src); - ea_src = EA_AY_PD_8(); - src = ((src << 8) | m68ki_read_8(ea_src)) + OPER_I_16(); - - m68ki_write_8(EA_AX_PD_8(), ((src >> 4) & 0x00f0) | (src & 0x000f)); - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(pea, 32, ., .) -{ - uint ea = M68KMAKE_GET_EA_AY_32; - - m68ki_push_32(ea); -} - -M68KMAKE_OP(pflush, 32, ., .) -{ - if ((CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) && (HAS_PMMU)) - { - fprintf(stderr,"68040: unhandled PFLUSH\n"); - return; - } - m68ki_exception_1111(); -} - -M68KMAKE_OP(pmmu, 32, ., .) -{ - if ((CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) && (HAS_PMMU)) - { - m68881_mmu_ops(); - } - else - { - m68ki_exception_1111(); - } -} - -M68KMAKE_OP(reset, 0, ., .) -{ - if(FLAG_S) - { - m68ki_output_reset(); /* auto-disable (see m68kcpu.h) */ - USE_CYCLES(CYC_RESET); - return; - } - m68ki_exception_privilege_violation(); -} - - -M68KMAKE_OP(ror, 8, s, .) -{ - uint* r_dst = &DY; - uint orig_shift = (((REG_IR >> 9) - 1) & 7) + 1; - uint shift = orig_shift & 7; - uint src = MASK_OUT_ABOVE_8(*r_dst); - uint res = ROR_8(src, shift); - - if(orig_shift != 0) - USE_CYCLES(orig_shift<> 9) - 1) & 7) + 1; - uint src = MASK_OUT_ABOVE_16(*r_dst); - uint res = ROR_16(src, shift); - - if(shift != 0) - USE_CYCLES(shift<> 9) - 1) & 7) + 1; - uint64 src = *r_dst; - uint res = ROR_32(src, shift); - - if(shift != 0) - USE_CYCLES(shift<> ((shift - 1) & 15)) << 8; - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - return; - } - - FLAG_C = CFLAG_CLEAR; - FLAG_N = NFLAG_16(src); - FLAG_Z = src; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(ror, 32, r, .) -{ - uint* r_dst = &DY; - uint orig_shift = DX & 0x3f; - uint shift = orig_shift & 31; - uint64 src = *r_dst; - uint res = ROR_32(src, shift); - - if(orig_shift != 0) - { - USE_CYCLES(orig_shift<> ((shift - 1) & 31)) << 8; - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - return; - } - - FLAG_C = CFLAG_CLEAR; - FLAG_N = NFLAG_32(src); - FLAG_Z = src; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(ror, 16, ., .) -{ - uint ea = M68KMAKE_GET_EA_AY_16; - uint src = m68ki_read_16(ea); - uint res = ROR_16(src, 1); - - m68ki_write_16(ea, res); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_C = src << 8; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(rol, 8, s, .) -{ - uint* r_dst = &DY; - uint orig_shift = (((REG_IR >> 9) - 1) & 7) + 1; - uint shift = orig_shift & 7; - uint src = MASK_OUT_ABOVE_8(*r_dst); - uint res = ROL_8(src, shift); - - if(orig_shift != 0) - USE_CYCLES(orig_shift<> 9) - 1) & 7) + 1; - uint src = MASK_OUT_ABOVE_16(*r_dst); - uint res = ROL_16(src, shift); - - if(shift != 0) - USE_CYCLES(shift<> (8-shift); - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(rol, 32, s, .) -{ - uint* r_dst = &DY; - uint shift = (((REG_IR >> 9) - 1) & 7) + 1; - uint64 src = *r_dst; - uint res = ROL_32(src, shift); - - if(shift != 0) - USE_CYCLES(shift<> (24-shift); - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(rol, 8, r, .) -{ - uint* r_dst = &DY; - uint orig_shift = DX & 0x3f; - uint shift = orig_shift & 7; - uint src = MASK_OUT_ABOVE_8(*r_dst); - uint res = ROL_8(src, shift); - - if(orig_shift != 0) - { - USE_CYCLES(orig_shift<> 8; - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - return; - } - FLAG_C = (src & 1)<<8; - FLAG_N = NFLAG_16(src); - FLAG_Z = src; - FLAG_V = VFLAG_CLEAR; - return; - } - - FLAG_C = CFLAG_CLEAR; - FLAG_N = NFLAG_16(src); - FLAG_Z = src; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(rol, 32, r, .) -{ - uint* r_dst = &DY; - uint orig_shift = DX & 0x3f; - uint shift = orig_shift & 31; - uint64 src = *r_dst; - uint res = ROL_32(src, shift); - - if(orig_shift != 0) - { - USE_CYCLES(orig_shift<> ((32 - shift) & 0x1f)) << 8; - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - return; - } - - FLAG_C = CFLAG_CLEAR; - FLAG_N = NFLAG_32(src); - FLAG_Z = src; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(rol, 16, ., .) -{ - uint ea = M68KMAKE_GET_EA_AY_16; - uint src = m68ki_read_16(ea); - uint res = MASK_OUT_ABOVE_16(ROL_16(src, 1)); - - m68ki_write_16(ea, res); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_C = src >> 7; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(roxr, 8, s, .) -{ - uint* r_dst = &DY; - uint shift = (((REG_IR >> 9) - 1) & 7) + 1; - uint src = MASK_OUT_ABOVE_8(*r_dst); - uint res = ROR_9(src | (XFLAG_AS_1() << 8), shift); - - if(shift != 0) - USE_CYCLES(shift<> 9) - 1) & 7) + 1; - uint src = MASK_OUT_ABOVE_16(*r_dst); - uint res = ROR_17(src | (XFLAG_AS_1() << 16), shift); - - if(shift != 0) - USE_CYCLES(shift<> 8; - res = MASK_OUT_ABOVE_16(res); - - *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(roxr, 32, s, .) -{ -#if M68K_USE_64_BIT - - uint* r_dst = &DY; - uint shift = (((REG_IR >> 9) - 1) & 7) + 1; - uint64 src = *r_dst; - uint64 res = src | (((uint64)XFLAG_AS_1()) << 32); - - if(shift != 0) - USE_CYCLES(shift<> 24; - res = MASK_OUT_ABOVE_32(res); - - *r_dst = res; - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - -#else - - uint* r_dst = &DY; - uint shift = (((REG_IR >> 9) - 1) & 7) + 1; - uint src = *r_dst; - uint res = MASK_OUT_ABOVE_32((ROR_33(src, shift) & ~(1 << (32 - shift))) | (XFLAG_AS_1() << (32 - shift))); - uint new_x_flag = src & (1 << (shift - 1)); - - if(shift != 0) - USE_CYCLES(shift<> 8; - res = MASK_OUT_ABOVE_16(res); - - *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - return; - } - - FLAG_C = FLAG_X; - FLAG_N = NFLAG_16(*r_dst); - FLAG_Z = MASK_OUT_ABOVE_16(*r_dst); - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(roxr, 32, r, .) -{ -#if M68K_USE_64_BIT - - uint* r_dst = &DY; - uint orig_shift = DX & 0x3f; - - if(orig_shift != 0) - { - uint shift = orig_shift % 33; - uint64 src = *r_dst; - uint64 res = src | (((uint64)XFLAG_AS_1()) << 32); - - res = ROR_33_64(res, shift); - - USE_CYCLES(orig_shift<> 24; - res = MASK_OUT_ABOVE_32(res); - - *r_dst = res; - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - return; - } - - FLAG_C = FLAG_X; - FLAG_N = NFLAG_32(*r_dst); - FLAG_Z = *r_dst; - FLAG_V = VFLAG_CLEAR; - -#else - - uint* r_dst = &DY; - uint orig_shift = DX & 0x3f; - uint shift = orig_shift % 33; - uint src = *r_dst; - uint res = MASK_OUT_ABOVE_32((ROR_33(src, shift) & ~(1 << (32 - shift))) | (XFLAG_AS_1() << (32 - shift))); - uint new_x_flag = src & (1 << (shift - 1)); - - if(orig_shift != 0) - USE_CYCLES(orig_shift<> 8; - res = MASK_OUT_ABOVE_16(res); - - m68ki_write_16(ea, res); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(roxl, 8, s, .) -{ - uint* r_dst = &DY; - uint shift = (((REG_IR >> 9) - 1) & 7) + 1; - uint src = MASK_OUT_ABOVE_8(*r_dst); - uint res = ROL_9(src | (XFLAG_AS_1() << 8), shift); - - if(shift != 0) - USE_CYCLES(shift<> 9) - 1) & 7) + 1; - uint src = MASK_OUT_ABOVE_16(*r_dst); - uint res = ROL_17(src | (XFLAG_AS_1() << 16), shift); - - if(shift != 0) - USE_CYCLES(shift<> 8; - res = MASK_OUT_ABOVE_16(res); - - *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(roxl, 32, s, .) -{ -#if M68K_USE_64_BIT - - uint* r_dst = &DY; - uint shift = (((REG_IR >> 9) - 1) & 7) + 1; - uint64 src = *r_dst; - uint64 res = src | (((uint64)XFLAG_AS_1()) << 32); - - if(shift != 0) - USE_CYCLES(shift<> 24; - res = MASK_OUT_ABOVE_32(res); - - *r_dst = res; - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - -#else - - uint* r_dst = &DY; - uint shift = (((REG_IR >> 9) - 1) & 7) + 1; - uint src = *r_dst; - uint res = MASK_OUT_ABOVE_32((ROL_33(src, shift) & ~(1 << (shift - 1))) | (XFLAG_AS_1() << (shift - 1))); - uint new_x_flag = src & (1 << (32 - shift)); - - if(shift != 0) - USE_CYCLES(shift<> 8; - res = MASK_OUT_ABOVE_16(res); - - *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - return; - } - - FLAG_C = FLAG_X; - FLAG_N = NFLAG_16(*r_dst); - FLAG_Z = MASK_OUT_ABOVE_16(*r_dst); - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(roxl, 32, r, .) -{ -#if M68K_USE_64_BIT - - uint* r_dst = &DY; - uint orig_shift = DX & 0x3f; - - if(orig_shift != 0) - { - uint shift = orig_shift % 33; - uint64 src = *r_dst; - uint64 res = src | (((uint64)XFLAG_AS_1()) << 32); - - res = ROL_33_64(res, shift); - - USE_CYCLES(orig_shift<> 24; - res = MASK_OUT_ABOVE_32(res); - - *r_dst = res; - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - return; - } - - FLAG_C = FLAG_X; - FLAG_N = NFLAG_32(*r_dst); - FLAG_Z = *r_dst; - FLAG_V = VFLAG_CLEAR; - -#else - - uint* r_dst = &DY; - uint orig_shift = DX & 0x3f; - uint shift = orig_shift % 33; - uint src = *r_dst; - uint res = MASK_OUT_ABOVE_32((ROL_33(src, shift) & ~(1 << (shift - 1))) | (XFLAG_AS_1() << (shift - 1))); - uint new_x_flag = src & (1 << (32 - shift)); - - if(orig_shift != 0) - USE_CYCLES(orig_shift<> 8; - res = MASK_OUT_ABOVE_16(res); - - m68ki_write_16(ea, res); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(rtd, 32, ., .) -{ - if(CPU_TYPE_IS_010_PLUS(CPU_TYPE)) - { - uint new_pc = m68ki_pull_32(); - - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - REG_A[7] = MASK_OUT_ABOVE_32(REG_A[7] + MAKE_INT_16(OPER_I_16())); - m68ki_jump(new_pc); - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(rte, 32, ., .) -{ - if(FLAG_S) - { - uint new_sr; - uint new_pc; - uint format_word; - - m68ki_rte_callback(); /* auto-disable (see m68kcpu.h) */ - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - - if(CPU_TYPE_IS_000(CPU_TYPE)) - { - new_sr = m68ki_pull_16(); - new_pc = m68ki_pull_32(); - m68ki_jump(new_pc); - m68ki_set_sr(new_sr); - - CPU_INSTR_MODE = INSTRUCTION_YES; - CPU_RUN_MODE = RUN_MODE_NORMAL; - - return; - } - - if(CPU_TYPE_IS_010(CPU_TYPE)) - { - format_word = m68ki_read_16(REG_A[7]+6) >> 12; - if(format_word == 0) - { - new_sr = m68ki_pull_16(); - new_pc = m68ki_pull_32(); - m68ki_fake_pull_16(); /* format word */ - m68ki_jump(new_pc); - m68ki_set_sr(new_sr); - CPU_INSTR_MODE = INSTRUCTION_YES; - CPU_RUN_MODE = RUN_MODE_NORMAL; - return; - } else if (format_word == 8) { - /* Format 8 stack frame -- 68010 only. 29 word bus/address error */ - new_sr = m68ki_pull_16(); - new_pc = m68ki_pull_32(); - m68ki_fake_pull_16(); /* format word */ - m68ki_fake_pull_16(); /* special status word */ - m68ki_fake_pull_32(); /* fault address */ - m68ki_fake_pull_16(); /* unused/reserved */ - m68ki_fake_pull_16(); /* data output buffer */ - m68ki_fake_pull_16(); /* unused/reserved */ - m68ki_fake_pull_16(); /* data input buffer */ - m68ki_fake_pull_16(); /* unused/reserved */ - m68ki_fake_pull_16(); /* instruction input buffer */ - m68ki_fake_pull_32(); /* internal information, 16 words */ - m68ki_fake_pull_32(); /* (actually, we use 8 DWORDs) */ - m68ki_fake_pull_32(); - m68ki_fake_pull_32(); - m68ki_fake_pull_32(); - m68ki_fake_pull_32(); - m68ki_fake_pull_32(); - m68ki_fake_pull_32(); - m68ki_jump(new_pc); - m68ki_set_sr(new_sr); - CPU_INSTR_MODE = INSTRUCTION_YES; - CPU_RUN_MODE = RUN_MODE_NORMAL; - return; - } - CPU_INSTR_MODE = INSTRUCTION_YES; - CPU_RUN_MODE = RUN_MODE_NORMAL; - /* Not handling other exception types (9) */ - m68ki_exception_format_error(); - return; - } - - /* Otherwise it's 020 */ -rte_loop: - format_word = m68ki_read_16(REG_A[7]+6) >> 12; - switch(format_word) - { - case 0: /* Normal */ - new_sr = m68ki_pull_16(); - new_pc = m68ki_pull_32(); - m68ki_fake_pull_16(); /* format word */ - m68ki_jump(new_pc); - m68ki_set_sr(new_sr); - CPU_INSTR_MODE = INSTRUCTION_YES; - CPU_RUN_MODE = RUN_MODE_NORMAL; - return; - case 1: /* Throwaway */ - new_sr = m68ki_pull_16(); - m68ki_fake_pull_32(); /* program counter */ - m68ki_fake_pull_16(); /* format word */ - m68ki_set_sr_noint(new_sr); - goto rte_loop; - case 2: /* Trap */ - new_sr = m68ki_pull_16(); - new_pc = m68ki_pull_32(); - m68ki_fake_pull_16(); /* format word */ - m68ki_fake_pull_32(); /* address */ - m68ki_jump(new_pc); - m68ki_set_sr(new_sr); - CPU_INSTR_MODE = INSTRUCTION_YES; - CPU_RUN_MODE = RUN_MODE_NORMAL; - return; - } - /* Not handling long or short bus fault */ - CPU_INSTR_MODE = INSTRUCTION_YES; - CPU_RUN_MODE = RUN_MODE_NORMAL; - m68ki_exception_format_error(); - return; - } - m68ki_exception_privilege_violation(); -} - - -M68KMAKE_OP(rtm, 32, ., .) -{ - if(CPU_TYPE_IS_020_VARIANT(CPU_TYPE)) - { - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - M68K_DO_LOG((M68K_LOG_FILEHANDLE "%s at %08x: called unimplemented instruction %04x (%s)\n", - m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PC - 2), REG_IR, - m68k_disassemble_quick(ADDRESS_68K(REG_PC - 2)))); - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(rtr, 32, ., .) -{ - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - m68ki_set_ccr(m68ki_pull_16()); - m68ki_jump(m68ki_pull_32()); -} - - -M68KMAKE_OP(rts, 32, ., .) -{ - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - m68ki_jump(m68ki_pull_32()); -} - - -M68KMAKE_OP(sbcd, 8, rr, .) -{ - uint* r_dst = &DX; - uint src = DY; - uint dst = *r_dst; - uint res = LOW_NIBBLE(dst) - LOW_NIBBLE(src) - XFLAG_AS_1(); - - FLAG_V = ~res; /* Undefined V behavior */ - - if(res > 9) - res -= 6; - res += HIGH_NIBBLE(dst) - HIGH_NIBBLE(src); - FLAG_X = FLAG_C = (res > 0x99) << 8; - if(FLAG_C) - res += 0xa0; - - res = MASK_OUT_ABOVE_8(res); - - FLAG_V &= res; /* Undefined V behavior part II */ - FLAG_N = NFLAG_8(res); /* Undefined N behavior */ - FLAG_Z |= res; - - *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; -} - - -M68KMAKE_OP(sbcd, 8, mm, ax7) -{ - uint src = OPER_AY_PD_8(); - uint ea = EA_A7_PD_8(); - uint dst = m68ki_read_8(ea); - uint res = LOW_NIBBLE(dst) - LOW_NIBBLE(src) - XFLAG_AS_1(); - - FLAG_V = ~res; /* Undefined V behavior */ - - if(res > 9) - res -= 6; - res += HIGH_NIBBLE(dst) - HIGH_NIBBLE(src); - FLAG_X = FLAG_C = (res > 0x99) << 8; - if(FLAG_C) - res += 0xa0; - - res = MASK_OUT_ABOVE_8(res); - - FLAG_V &= res; /* Undefined V behavior part II */ - FLAG_N = NFLAG_8(res); /* Undefined N behavior */ - FLAG_Z |= res; - - m68ki_write_8(ea, res); -} - - -M68KMAKE_OP(sbcd, 8, mm, ay7) -{ - uint src = OPER_A7_PD_8(); - uint ea = EA_AX_PD_8(); - uint dst = m68ki_read_8(ea); - uint res = LOW_NIBBLE(dst) - LOW_NIBBLE(src) - XFLAG_AS_1(); - - FLAG_V = ~res; /* Undefined V behavior */ - - if(res > 9) - res -= 6; - res += HIGH_NIBBLE(dst) - HIGH_NIBBLE(src); - FLAG_X = FLAG_C = (res > 0x99) << 8; - if(FLAG_C) - res += 0xa0; - - res = MASK_OUT_ABOVE_8(res); - - FLAG_V &= res; /* Undefined V behavior part II */ - FLAG_N = NFLAG_8(res); /* Undefined N behavior */ - FLAG_Z |= res; - - m68ki_write_8(ea, res); -} - - -M68KMAKE_OP(sbcd, 8, mm, axy7) -{ - uint src = OPER_A7_PD_8(); - uint ea = EA_A7_PD_8(); - uint dst = m68ki_read_8(ea); - uint res = LOW_NIBBLE(dst) - LOW_NIBBLE(src) - XFLAG_AS_1(); - - FLAG_V = ~res; /* Undefined V behavior */ - - if(res > 9) - res -= 6; - res += HIGH_NIBBLE(dst) - HIGH_NIBBLE(src); - FLAG_X = FLAG_C = (res > 0x99) << 8; - if(FLAG_C) - res += 0xa0; - - res = MASK_OUT_ABOVE_8(res); - - FLAG_V &= res; /* Undefined V behavior part II */ - FLAG_N = NFLAG_8(res); /* Undefined N behavior */ - FLAG_Z |= res; - - m68ki_write_8(ea, res); -} - - -M68KMAKE_OP(sbcd, 8, mm, .) -{ - uint src = OPER_AY_PD_8(); - uint ea = EA_AX_PD_8(); - uint dst = m68ki_read_8(ea); - uint res = LOW_NIBBLE(dst) - LOW_NIBBLE(src) - XFLAG_AS_1(); - - FLAG_V = ~res; /* Undefined V behavior */ - - if(res > 9) - res -= 6; - res += HIGH_NIBBLE(dst) - HIGH_NIBBLE(src); - FLAG_X = FLAG_C = (res > 0x99) << 8; - if(FLAG_C) - res += 0xa0; - - res = MASK_OUT_ABOVE_8(res); - - FLAG_V &= res; /* Undefined V behavior part II */ - FLAG_N = NFLAG_8(res); /* Undefined N behavior */ - FLAG_Z |= res; - - m68ki_write_8(ea, res); -} - - -M68KMAKE_OP(st, 8, ., d) -{ - DY |= 0xff; -} - - -M68KMAKE_OP(st, 8, ., .) -{ - m68ki_write_8(M68KMAKE_GET_EA_AY_8, 0xff); -} - - -M68KMAKE_OP(sf, 8, ., d) -{ - DY &= 0xffffff00; -} - - -M68KMAKE_OP(sf, 8, ., .) -{ - m68ki_write_8(M68KMAKE_GET_EA_AY_8, 0); -} - - -M68KMAKE_OP(scc, 8, ., d) -{ - if(M68KMAKE_CC) - { - DY |= 0xff; - USE_CYCLES(CYC_SCC_R_TRUE); - return; - } - DY &= 0xffffff00; -} - - -M68KMAKE_OP(scc, 8, ., .) -{ - m68ki_write_8(M68KMAKE_GET_EA_AY_8, M68KMAKE_CC ? 0xff : 0); -} - - -M68KMAKE_OP(stop, 0, ., .) -{ - if(FLAG_S) - { - uint new_sr = OPER_I_16(); - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - CPU_STOPPED |= STOP_LEVEL_STOP; - m68ki_set_sr(new_sr); - if(m68ki_remaining_cycles >= CYC_INSTRUCTION[REG_IR]) - m68ki_remaining_cycles = CYC_INSTRUCTION[REG_IR]; - else - USE_ALL_CYCLES(); - return; - } - m68ki_exception_privilege_violation(); -} - - -M68KMAKE_OP(sub, 8, er, d) -{ - uint* r_dst = &DX; - uint src = MASK_OUT_ABOVE_8(DY); - uint dst = MASK_OUT_ABOVE_8(*r_dst); - uint res = dst - src; - - FLAG_N = NFLAG_8(res); - FLAG_X = FLAG_C = CFLAG_8(res); - FLAG_V = VFLAG_SUB_8(src, dst, res); - FLAG_Z = MASK_OUT_ABOVE_8(res); - - *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; -} - - -M68KMAKE_OP(sub, 8, er, .) -{ - uint* r_dst = &DX; - uint src = M68KMAKE_GET_OPER_AY_8; - uint dst = MASK_OUT_ABOVE_8(*r_dst); - uint res = dst - src; - - FLAG_N = NFLAG_8(res); - FLAG_X = FLAG_C = CFLAG_8(res); - FLAG_V = VFLAG_SUB_8(src, dst, res); - FLAG_Z = MASK_OUT_ABOVE_8(res); - - *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; -} - - -M68KMAKE_OP(sub, 16, er, d) -{ - uint* r_dst = &DX; - uint src = MASK_OUT_ABOVE_16(DY); - uint dst = MASK_OUT_ABOVE_16(*r_dst); - uint res = dst - src; - - FLAG_N = NFLAG_16(res); - FLAG_X = FLAG_C = CFLAG_16(res); - FLAG_V = VFLAG_SUB_16(src, dst, res); - FLAG_Z = MASK_OUT_ABOVE_16(res); - - *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; -} - - -M68KMAKE_OP(sub, 16, er, a) -{ - uint* r_dst = &DX; - uint src = MASK_OUT_ABOVE_16(AY); - uint dst = MASK_OUT_ABOVE_16(*r_dst); - uint res = dst - src; - - FLAG_N = NFLAG_16(res); - FLAG_X = FLAG_C = CFLAG_16(res); - FLAG_V = VFLAG_SUB_16(src, dst, res); - FLAG_Z = MASK_OUT_ABOVE_16(res); - - *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; -} - - -M68KMAKE_OP(sub, 16, er, .) -{ - uint* r_dst = &DX; - uint src = M68KMAKE_GET_OPER_AY_16; - uint dst = MASK_OUT_ABOVE_16(*r_dst); - uint res = dst - src; - - FLAG_N = NFLAG_16(res); - FLAG_X = FLAG_C = CFLAG_16(res); - FLAG_V = VFLAG_SUB_16(src, dst, res); - FLAG_Z = MASK_OUT_ABOVE_16(res); - - *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; -} - - -M68KMAKE_OP(sub, 32, er, d) -{ - uint* r_dst = &DX; - uint src = DY; - uint dst = *r_dst; - uint res = dst - src; - - FLAG_N = NFLAG_32(res); - FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); - FLAG_V = VFLAG_SUB_32(src, dst, res); - FLAG_Z = MASK_OUT_ABOVE_32(res); - - *r_dst = FLAG_Z; -} - - -M68KMAKE_OP(sub, 32, er, a) -{ - uint* r_dst = &DX; - uint src = AY; - uint dst = *r_dst; - uint res = dst - src; - - FLAG_N = NFLAG_32(res); - FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); - FLAG_V = VFLAG_SUB_32(src, dst, res); - FLAG_Z = MASK_OUT_ABOVE_32(res); - - *r_dst = FLAG_Z; -} - - -M68KMAKE_OP(sub, 32, er, .) -{ - uint* r_dst = &DX; - uint src = M68KMAKE_GET_OPER_AY_32; - uint dst = *r_dst; - uint res = dst - src; - - FLAG_N = NFLAG_32(res); - FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); - FLAG_V = VFLAG_SUB_32(src, dst, res); - FLAG_Z = MASK_OUT_ABOVE_32(res); - - *r_dst = FLAG_Z; -} - - -M68KMAKE_OP(sub, 8, re, .) -{ - uint ea = M68KMAKE_GET_EA_AY_8; - uint src = MASK_OUT_ABOVE_8(DX); - uint dst = m68ki_read_8(ea); - uint res = dst - src; - - FLAG_N = NFLAG_8(res); - FLAG_Z = MASK_OUT_ABOVE_8(res); - FLAG_X = FLAG_C = CFLAG_8(res); - FLAG_V = VFLAG_SUB_8(src, dst, res); - - m68ki_write_8(ea, FLAG_Z); -} - - -M68KMAKE_OP(sub, 16, re, .) -{ - uint ea = M68KMAKE_GET_EA_AY_16; - uint src = MASK_OUT_ABOVE_16(DX); - uint dst = m68ki_read_16(ea); - uint res = dst - src; - - FLAG_N = NFLAG_16(res); - FLAG_Z = MASK_OUT_ABOVE_16(res); - FLAG_X = FLAG_C = CFLAG_16(res); - FLAG_V = VFLAG_SUB_16(src, dst, res); - - m68ki_write_16(ea, FLAG_Z); -} - - -M68KMAKE_OP(sub, 32, re, .) -{ - uint ea = M68KMAKE_GET_EA_AY_32; - uint src = DX; - uint dst = m68ki_read_32(ea); - uint res = dst - src; - - FLAG_N = NFLAG_32(res); - FLAG_Z = MASK_OUT_ABOVE_32(res); - FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); - FLAG_V = VFLAG_SUB_32(src, dst, res); - - m68ki_write_32(ea, FLAG_Z); -} - - -M68KMAKE_OP(suba, 16, ., d) -{ - uint* r_dst = &AX; - - *r_dst = MASK_OUT_ABOVE_32(*r_dst - MAKE_INT_16(DY)); -} - - -M68KMAKE_OP(suba, 16, ., a) -{ - uint* r_dst = &AX; - - *r_dst = MASK_OUT_ABOVE_32(*r_dst - MAKE_INT_16(AY)); -} - - -M68KMAKE_OP(suba, 16, ., .) -{ - uint* r_dst = &AX; - uint src = MAKE_INT_16(M68KMAKE_GET_OPER_AY_16); - - *r_dst = MASK_OUT_ABOVE_32(*r_dst - src); -} - - -M68KMAKE_OP(suba, 32, ., d) -{ - uint* r_dst = &AX; - - *r_dst = MASK_OUT_ABOVE_32(*r_dst - DY); -} - - -M68KMAKE_OP(suba, 32, ., a) -{ - uint* r_dst = &AX; - - *r_dst = MASK_OUT_ABOVE_32(*r_dst - AY); -} - - -M68KMAKE_OP(suba, 32, ., .) -{ - uint src = M68KMAKE_GET_OPER_AY_32; - uint* r_dst = &AX; - - *r_dst = MASK_OUT_ABOVE_32(*r_dst - src); -} - - -M68KMAKE_OP(subi, 8, ., d) -{ - uint* r_dst = &DY; - uint src = OPER_I_8(); - uint dst = MASK_OUT_ABOVE_8(*r_dst); - uint res = dst - src; - - FLAG_N = NFLAG_8(res); - FLAG_Z = MASK_OUT_ABOVE_8(res); - FLAG_X = FLAG_C = CFLAG_8(res); - FLAG_V = VFLAG_SUB_8(src, dst, res); - - *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; -} - - -M68KMAKE_OP(subi, 8, ., .) -{ - uint src = OPER_I_8(); - uint ea = M68KMAKE_GET_EA_AY_8; - uint dst = m68ki_read_8(ea); - uint res = dst - src; - - FLAG_N = NFLAG_8(res); - FLAG_Z = MASK_OUT_ABOVE_8(res); - FLAG_X = FLAG_C = CFLAG_8(res); - FLAG_V = VFLAG_SUB_8(src, dst, res); - - m68ki_write_8(ea, FLAG_Z); -} - - -M68KMAKE_OP(subi, 16, ., d) -{ - uint* r_dst = &DY; - uint src = OPER_I_16(); - uint dst = MASK_OUT_ABOVE_16(*r_dst); - uint res = dst - src; - - FLAG_N = NFLAG_16(res); - FLAG_Z = MASK_OUT_ABOVE_16(res); - FLAG_X = FLAG_C = CFLAG_16(res); - FLAG_V = VFLAG_SUB_16(src, dst, res); - - *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; -} - - -M68KMAKE_OP(subi, 16, ., .) -{ - uint src = OPER_I_16(); - uint ea = M68KMAKE_GET_EA_AY_16; - uint dst = m68ki_read_16(ea); - uint res = dst - src; - - FLAG_N = NFLAG_16(res); - FLAG_Z = MASK_OUT_ABOVE_16(res); - FLAG_X = FLAG_C = CFLAG_16(res); - FLAG_V = VFLAG_SUB_16(src, dst, res); - - m68ki_write_16(ea, FLAG_Z); -} - - -M68KMAKE_OP(subi, 32, ., d) -{ - uint* r_dst = &DY; - uint src = OPER_I_32(); - uint dst = *r_dst; - uint res = dst - src; - - FLAG_N = NFLAG_32(res); - FLAG_Z = MASK_OUT_ABOVE_32(res); - FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); - FLAG_V = VFLAG_SUB_32(src, dst, res); - - *r_dst = FLAG_Z; -} - - -M68KMAKE_OP(subi, 32, ., .) -{ - uint src = OPER_I_32(); - uint ea = M68KMAKE_GET_EA_AY_32; - uint dst = m68ki_read_32(ea); - uint res = dst - src; - - FLAG_N = NFLAG_32(res); - FLAG_Z = MASK_OUT_ABOVE_32(res); - FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); - FLAG_V = VFLAG_SUB_32(src, dst, res); - - m68ki_write_32(ea, FLAG_Z); -} - - -M68KMAKE_OP(subq, 8, ., d) -{ - uint* r_dst = &DY; - uint src = (((REG_IR >> 9) - 1) & 7) + 1; - uint dst = MASK_OUT_ABOVE_8(*r_dst); - uint res = dst - src; - - FLAG_N = NFLAG_8(res); - FLAG_Z = MASK_OUT_ABOVE_8(res); - FLAG_X = FLAG_C = CFLAG_8(res); - FLAG_V = VFLAG_SUB_8(src, dst, res); - - *r_dst = MASK_OUT_BELOW_8(*r_dst) | FLAG_Z; -} - - -M68KMAKE_OP(subq, 8, ., .) -{ - uint src = (((REG_IR >> 9) - 1) & 7) + 1; - uint ea = M68KMAKE_GET_EA_AY_8; - uint dst = m68ki_read_8(ea); - uint res = dst - src; - - FLAG_N = NFLAG_8(res); - FLAG_Z = MASK_OUT_ABOVE_8(res); - FLAG_X = FLAG_C = CFLAG_8(res); - FLAG_V = VFLAG_SUB_8(src, dst, res); - - m68ki_write_8(ea, FLAG_Z); -} - - -M68KMAKE_OP(subq, 16, ., d) -{ - uint* r_dst = &DY; - uint src = (((REG_IR >> 9) - 1) & 7) + 1; - uint dst = MASK_OUT_ABOVE_16(*r_dst); - uint res = dst - src; - - FLAG_N = NFLAG_16(res); - FLAG_Z = MASK_OUT_ABOVE_16(res); - FLAG_X = FLAG_C = CFLAG_16(res); - FLAG_V = VFLAG_SUB_16(src, dst, res); - - *r_dst = MASK_OUT_BELOW_16(*r_dst) | FLAG_Z; -} - - -M68KMAKE_OP(subq, 16, ., a) -{ - uint* r_dst = &AY; - - *r_dst = MASK_OUT_ABOVE_32(*r_dst - ((((REG_IR >> 9) - 1) & 7) + 1)); -} - - -M68KMAKE_OP(subq, 16, ., .) -{ - uint src = (((REG_IR >> 9) - 1) & 7) + 1; - uint ea = M68KMAKE_GET_EA_AY_16; - uint dst = m68ki_read_16(ea); - uint res = dst - src; - - FLAG_N = NFLAG_16(res); - FLAG_Z = MASK_OUT_ABOVE_16(res); - FLAG_X = FLAG_C = CFLAG_16(res); - FLAG_V = VFLAG_SUB_16(src, dst, res); - - m68ki_write_16(ea, FLAG_Z); -} - - -M68KMAKE_OP(subq, 32, ., d) -{ - uint* r_dst = &DY; - uint src = (((REG_IR >> 9) - 1) & 7) + 1; - uint dst = *r_dst; - uint res = dst - src; - - FLAG_N = NFLAG_32(res); - FLAG_Z = MASK_OUT_ABOVE_32(res); - FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); - FLAG_V = VFLAG_SUB_32(src, dst, res); - - *r_dst = FLAG_Z; -} - - -M68KMAKE_OP(subq, 32, ., a) -{ - uint* r_dst = &AY; - - *r_dst = MASK_OUT_ABOVE_32(*r_dst - ((((REG_IR >> 9) - 1) & 7) + 1)); -} - - -M68KMAKE_OP(subq, 32, ., .) -{ - uint src = (((REG_IR >> 9) - 1) & 7) + 1; - uint ea = M68KMAKE_GET_EA_AY_32; - uint dst = m68ki_read_32(ea); - uint res = dst - src; - - FLAG_N = NFLAG_32(res); - FLAG_Z = MASK_OUT_ABOVE_32(res); - FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); - FLAG_V = VFLAG_SUB_32(src, dst, res); - - m68ki_write_32(ea, FLAG_Z); -} - - -M68KMAKE_OP(subx, 8, rr, .) -{ - uint* r_dst = &DX; - uint src = MASK_OUT_ABOVE_8(DY); - uint dst = MASK_OUT_ABOVE_8(*r_dst); - uint res = dst - src - XFLAG_AS_1(); - - FLAG_N = NFLAG_8(res); - FLAG_X = FLAG_C = CFLAG_8(res); - FLAG_V = VFLAG_SUB_8(src, dst, res); - - res = MASK_OUT_ABOVE_8(res); - FLAG_Z |= res; - - *r_dst = MASK_OUT_BELOW_8(*r_dst) | res; -} - - -M68KMAKE_OP(subx, 16, rr, .) -{ - uint* r_dst = &DX; - uint src = MASK_OUT_ABOVE_16(DY); - uint dst = MASK_OUT_ABOVE_16(*r_dst); - uint res = dst - src - XFLAG_AS_1(); - - FLAG_N = NFLAG_16(res); - FLAG_X = FLAG_C = CFLAG_16(res); - FLAG_V = VFLAG_SUB_16(src, dst, res); - - res = MASK_OUT_ABOVE_16(res); - FLAG_Z |= res; - - *r_dst = MASK_OUT_BELOW_16(*r_dst) | res; -} - - -M68KMAKE_OP(subx, 32, rr, .) -{ - uint* r_dst = &DX; - uint src = DY; - uint dst = *r_dst; - uint res = dst - src - XFLAG_AS_1(); - - FLAG_N = NFLAG_32(res); - FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); - FLAG_V = VFLAG_SUB_32(src, dst, res); - - res = MASK_OUT_ABOVE_32(res); - FLAG_Z |= res; - - *r_dst = res; -} - - -M68KMAKE_OP(subx, 8, mm, ax7) -{ - uint src = OPER_AY_PD_8(); - uint ea = EA_A7_PD_8(); - uint dst = m68ki_read_8(ea); - uint res = dst - src - XFLAG_AS_1(); - - FLAG_N = NFLAG_8(res); - FLAG_X = FLAG_C = CFLAG_8(res); - FLAG_V = VFLAG_SUB_8(src, dst, res); - - res = MASK_OUT_ABOVE_8(res); - FLAG_Z |= res; - - m68ki_write_8(ea, res); -} - - -M68KMAKE_OP(subx, 8, mm, ay7) -{ - uint src = OPER_A7_PD_8(); - uint ea = EA_AX_PD_8(); - uint dst = m68ki_read_8(ea); - uint res = dst - src - XFLAG_AS_1(); - - FLAG_N = NFLAG_8(res); - FLAG_X = FLAG_C = CFLAG_8(res); - FLAG_V = VFLAG_SUB_8(src, dst, res); - - res = MASK_OUT_ABOVE_8(res); - FLAG_Z |= res; - - m68ki_write_8(ea, res); -} - - -M68KMAKE_OP(subx, 8, mm, axy7) -{ - uint src = OPER_A7_PD_8(); - uint ea = EA_A7_PD_8(); - uint dst = m68ki_read_8(ea); - uint res = dst - src - XFLAG_AS_1(); - - FLAG_N = NFLAG_8(res); - FLAG_X = FLAG_C = CFLAG_8(res); - FLAG_V = VFLAG_SUB_8(src, dst, res); - - res = MASK_OUT_ABOVE_8(res); - FLAG_Z |= res; - - m68ki_write_8(ea, res); -} - - -M68KMAKE_OP(subx, 8, mm, .) -{ - uint src = OPER_AY_PD_8(); - uint ea = EA_AX_PD_8(); - uint dst = m68ki_read_8(ea); - uint res = dst - src - XFLAG_AS_1(); - - FLAG_N = NFLAG_8(res); - FLAG_X = FLAG_C = CFLAG_8(res); - FLAG_V = VFLAG_SUB_8(src, dst, res); - - res = MASK_OUT_ABOVE_8(res); - FLAG_Z |= res; - - m68ki_write_8(ea, res); -} - - -M68KMAKE_OP(subx, 16, mm, .) -{ - uint src = OPER_AY_PD_16(); - uint ea = EA_AX_PD_16(); - uint dst = m68ki_read_16(ea); - uint res = dst - src - XFLAG_AS_1(); - - FLAG_N = NFLAG_16(res); - FLAG_X = FLAG_C = CFLAG_16(res); - FLAG_V = VFLAG_SUB_16(src, dst, res); - - res = MASK_OUT_ABOVE_16(res); - FLAG_Z |= res; - - m68ki_write_16(ea, res); -} - - -M68KMAKE_OP(subx, 32, mm, .) -{ - uint src = OPER_AY_PD_32(); - uint ea = EA_AX_PD_32(); - uint dst = m68ki_read_32(ea); - uint res = dst - src - XFLAG_AS_1(); - - FLAG_N = NFLAG_32(res); - FLAG_X = FLAG_C = CFLAG_SUB_32(src, dst, res); - FLAG_V = VFLAG_SUB_32(src, dst, res); - - res = MASK_OUT_ABOVE_32(res); - FLAG_Z |= res; - - m68ki_write_32(ea, res); -} - - -M68KMAKE_OP(swap, 32, ., .) -{ - uint* r_dst = &DY; - - FLAG_Z = MASK_OUT_ABOVE_32(*r_dst<<16); - *r_dst = (*r_dst>>16) | FLAG_Z; - - FLAG_Z = *r_dst; - FLAG_N = NFLAG_32(*r_dst); - FLAG_C = CFLAG_CLEAR; - FLAG_V = VFLAG_CLEAR; -} - - -M68KMAKE_OP(tas, 8, ., d) -{ - uint* r_dst = &DY; - - FLAG_Z = MASK_OUT_ABOVE_8(*r_dst); - FLAG_N = NFLAG_8(*r_dst); - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - *r_dst |= 0x80; -} - - -M68KMAKE_OP(tas, 8, ., .) -{ - uint ea = M68KMAKE_GET_EA_AY_8; - uint dst = m68ki_read_8(ea); - uint allow_writeback; - - FLAG_Z = dst; - FLAG_N = NFLAG_8(dst); - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - - /* The Genesis/Megadrive games Gargoyles and Ex-Mutants need the TAS writeback - disabled in order to function properly. Some Amiga software may also rely - on this, but only when accessing specific addresses so additional functionality - will be needed. */ - allow_writeback = m68ki_tas_callback(); - - if (allow_writeback==1) m68ki_write_8(ea, dst | 0x80); -} - - -M68KMAKE_OP(trap, 0, ., .) -{ - /* Trap#n stacks exception frame type 0 */ - m68ki_exception_trapN(EXCEPTION_TRAP_BASE + (REG_IR & 0xf)); /* HJB 990403 */ -} - - -M68KMAKE_OP(trapt, 0, ., .) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - m68ki_exception_trap(EXCEPTION_TRAPV); /* HJB 990403 */ - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(trapt, 16, ., .) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - REG_PC += 2; // JFF else stackframe & return addresses are incorrect - m68ki_exception_trap(EXCEPTION_TRAPV); /* HJB 990403 */ - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(trapt, 32, ., .) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - REG_PC += 4; // JFF else stackframe & return addresses are incorrect - m68ki_exception_trap(EXCEPTION_TRAPV); /* HJB 990403 */ - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(trapf, 0, ., .) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(trapf, 16, ., .) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - REG_PC += 2; - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(trapf, 32, ., .) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - REG_PC += 4; - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(trapcc, 0, ., .) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - if(M68KMAKE_CC) - m68ki_exception_trap(EXCEPTION_TRAPV); /* HJB 990403 */ - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(trapcc, 16, ., .) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - REG_PC += 2; /* JFF increase before or 1) stackframe is incorrect 2) RTE address is wrong if trap is taken */ - if(M68KMAKE_CC) - { - m68ki_exception_trap(EXCEPTION_TRAPV); /* HJB 990403 */ - return; - } - - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(trapcc, 32, ., .) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - REG_PC += 4; /* JFF increase before or 1) stackframe is incorrect 2) RTE address is wrong if trap is taken */ - if(M68KMAKE_CC) - { - m68ki_exception_trap(EXCEPTION_TRAPV); /* HJB 990403 */ - return; - } - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(trapv, 0, ., .) -{ - if(COND_VC()) - { - return; - } - m68ki_exception_trap(EXCEPTION_TRAPV); /* HJB 990403 */ -} - - -M68KMAKE_OP(tst, 8, ., d) -{ - uint res = MASK_OUT_ABOVE_8(DY); - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(tst, 8, ., .) -{ - uint res = M68KMAKE_GET_OPER_AY_8; - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(tst, 8, ., pcdi) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint res = OPER_PCDI_8(); - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(tst, 8, ., pcix) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint res = OPER_PCIX_8(); - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(tst, 8, ., i) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint res = OPER_I_8(); - - FLAG_N = NFLAG_8(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(tst, 16, ., d) -{ - uint res = MASK_OUT_ABOVE_16(DY); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(tst, 16, ., a) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint res = MAKE_INT_16(AY); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(tst, 16, ., .) -{ - uint res = M68KMAKE_GET_OPER_AY_16; - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(tst, 16, ., pcdi) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint res = OPER_PCDI_16(); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(tst, 16, ., pcix) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint res = OPER_PCIX_16(); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(tst, 16, ., i) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint res = OPER_I_16(); - - FLAG_N = NFLAG_16(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(tst, 32, ., d) -{ - uint res = DY; - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(tst, 32, ., a) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint res = AY; - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(tst, 32, ., .) -{ - uint res = M68KMAKE_GET_OPER_AY_32; - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; -} - - -M68KMAKE_OP(tst, 32, ., pcdi) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint res = OPER_PCDI_32(); - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(tst, 32, ., pcix) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint res = OPER_PCIX_32(); - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(tst, 32, ., i) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint res = OPER_I_32(); - - FLAG_N = NFLAG_32(res); - FLAG_Z = res; - FLAG_V = VFLAG_CLEAR; - FLAG_C = CFLAG_CLEAR; - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(unlk, 32, ., a7) -{ - REG_A[7] = m68ki_read_32(REG_A[7]); -} - - -M68KMAKE_OP(unlk, 32, ., .) -{ - uint* r_dst = &AY; - - REG_A[7] = *r_dst; - *r_dst = m68ki_pull_32(); -} - - -M68KMAKE_OP(unpk, 16, rr, .) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - /* Note: DX and DY are reversed in Motorola's docs */ - uint src = DY; - uint* r_dst = &DX; - - *r_dst = MASK_OUT_BELOW_16(*r_dst) | (((((src << 4) & 0x0f00) | (src & 0x000f)) + OPER_I_16()) & 0xffff); - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(unpk, 16, mm, ax7) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - /* Note: AX and AY are reversed in Motorola's docs */ - uint src = OPER_AY_PD_8(); - uint ea_dst; - - src = (((src << 4) & 0x0f00) | (src & 0x000f)) + OPER_I_16(); - ea_dst = EA_A7_PD_8(); - m68ki_write_8(ea_dst, (src >> 8) & 0xff); - ea_dst = EA_A7_PD_8(); - m68ki_write_8(ea_dst, src & 0xff); - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(unpk, 16, mm, ay7) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - /* Note: AX and AY are reversed in Motorola's docs */ - uint src = OPER_A7_PD_8(); - uint ea_dst; - - src = (((src << 4) & 0x0f00) | (src & 0x000f)) + OPER_I_16(); - ea_dst = EA_AX_PD_8(); - m68ki_write_8(ea_dst, (src >> 8) & 0xff); - ea_dst = EA_AX_PD_8(); - m68ki_write_8(ea_dst, src & 0xff); - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(unpk, 16, mm, axy7) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - uint src = OPER_A7_PD_8(); - uint ea_dst; - - src = (((src << 4) & 0x0f00) | (src & 0x000f)) + OPER_I_16(); - ea_dst = EA_A7_PD_8(); - m68ki_write_8(ea_dst, (src >> 8) & 0xff); - ea_dst = EA_A7_PD_8(); - m68ki_write_8(ea_dst, src & 0xff); - return; - } - m68ki_exception_illegal(); -} - - -M68KMAKE_OP(unpk, 16, mm, .) -{ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - /* Note: AX and AY are reversed in Motorola's docs */ - uint src = OPER_AY_PD_8(); - uint ea_dst; - - src = (((src << 4) & 0x0f00) | (src & 0x000f)) + OPER_I_16(); - ea_dst = EA_AX_PD_8(); - m68ki_write_8(ea_dst, (src >> 8) & 0xff); - ea_dst = EA_AX_PD_8(); - m68ki_write_8(ea_dst, src & 0xff); - return; - } - m68ki_exception_illegal(); -} - - - -XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX -M68KMAKE_END diff --git a/machine/musashi/m68kconf.h b/machine/musashi/m68kconf.h deleted file mode 100644 index 6de358b..0000000 --- a/machine/musashi/m68kconf.h +++ /dev/null @@ -1,221 +0,0 @@ -/* ======================================================================== */ -/* ========================= LICENSING & COPYRIGHT ======================== */ -/* ======================================================================== */ -/* - * MUSASHI - * Version 3.32 - * - * A portable Motorola M680x0 processor emulation engine. - * Copyright Karl Stenerud. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - - - -#ifndef M68KCONF__HEADER -#define M68KCONF__HEADER - - -/* Configuration switches. - * Use OPT_SPECIFY_HANDLER for configuration options that allow callbacks. - * OPT_SPECIFY_HANDLER causes the core to link directly to the function - * or macro you specify, rather than using callback functions whose pointer - * must be passed in using m68k_set_xxx_callback(). - */ -#define OPT_OFF 0 -#define OPT_ON 1 -#define OPT_SPECIFY_HANDLER 2 - - -/* ======================================================================== */ -/* ============================== MAME STUFF ============================== */ -/* ======================================================================== */ - -/* If you're compiling this for MAME, only change M68K_COMPILE_FOR_MAME - * to OPT_ON and use m68kmame.h to configure the 68k core. - */ -#ifndef M68K_COMPILE_FOR_MAME -#define M68K_COMPILE_FOR_MAME OPT_OFF -#endif /* M68K_COMPILE_FOR_MAME */ - - -#if M68K_COMPILE_FOR_MAME == OPT_OFF - - -/* ======================================================================== */ -/* ============================= CONFIGURATION ============================ */ -/* ======================================================================== */ - -/* Turn ON if you want to use the following M68K variants */ -#define M68K_EMULATE_010 OPT_ON -#define M68K_EMULATE_EC020 OPT_ON -#define M68K_EMULATE_020 OPT_ON -#define M68K_EMULATE_030 OPT_ON -#define M68K_EMULATE_040 OPT_ON - - -/* If ON, the CPU will call m68k_read_immediate_xx() for immediate addressing - * and m68k_read_pcrelative_xx() for PC-relative addressing. - * If off, all read requests from the CPU will be redirected to m68k_read_xx() - */ -#define M68K_SEPARATE_READS OPT_OFF - -/* If ON, the CPU will call m68k_write_32_pd() when it executes move.l with a - * predecrement destination EA mode instead of m68k_write_32(). - * To simulate real 68k behavior, m68k_write_32_pd() must first write the high - * word to [address+2], and then write the low word to [address]. - */ -#define M68K_SIMULATE_PD_WRITES OPT_OFF - -/* If ON, CPU will call the interrupt acknowledge callback when it services an - * interrupt. - * If off, all interrupts will be autovectored and all interrupt requests will - * auto-clear when the interrupt is serviced. - */ -#define M68K_EMULATE_INT_ACK OPT_OFF -#define M68K_INT_ACK_CALLBACK(A) your_int_ack_handler_function(A) - - -/* If ON, CPU will call the breakpoint acknowledge callback when it encounters - * a breakpoint instruction and it is running a 68010+. - */ -#define M68K_EMULATE_BKPT_ACK OPT_OFF -#define M68K_BKPT_ACK_CALLBACK() your_bkpt_ack_handler_function() - - -/* If ON, the CPU will monitor the trace flags and take trace exceptions - */ -#define M68K_EMULATE_TRACE OPT_OFF - - -/* If ON, CPU will call the output reset callback when it encounters a reset - * instruction. - */ - /* CV Patch */ -#define M68K_EMULATE_RESET OPT_ON -#define M68K_RESET_CALLBACK() your_reset_handler_function() - -/* If ON, CPU will call the callback when it encounters a cmpi.l #v, dn - * instruction. - */ -#define M68K_CMPILD_HAS_CALLBACK OPT_OFF -#define M68K_CMPILD_CALLBACK(v,r) your_cmpild_handler_function(v,r) - - -/* If ON, CPU will call the callback when it encounters a rte - * instruction. - */ -#define M68K_RTE_HAS_CALLBACK OPT_OFF -#define M68K_RTE_CALLBACK() your_rte_handler_function() - -/* If ON, CPU will call the callback when it encounters a tas - * instruction. - */ -#define M68K_TAS_HAS_CALLBACK OPT_OFF -#define M68K_TAS_CALLBACK() your_tas_handler_function() - -/* If ON, CPU will call the callback when it encounters an illegal instruction - * passing the opcode as argument. If the callback returns 1, then it's considered - * as a normal instruction, and the illegal exception in canceled. If it returns 0, - * the exception occurs normally. - * The callback looks like int callback(int opcode) - * You should put OPT_SPECIFY_HANDLER here if you cant to use it, otherwise it will - * use a dummy default handler and you'll have to call m68k_set_illg_instr_callback explicitely - */ -#define M68K_ILLG_HAS_CALLBACK OPT_OFF -#define M68K_ILLG_CALLBACK(opcode) op_illg(opcode) - -/* If ON, CPU will call the set fc callback on every memory access to - * differentiate between user/supervisor, program/data access like a real - * 68000 would. This should be enabled and the callback should be set if you - * want to properly emulate the m68010 or higher. (moves uses function codes - * to read/write data from different address spaces) - */ -#define M68K_EMULATE_FC OPT_OFF -#define M68K_SET_FC_CALLBACK(A) your_set_fc_handler_function(A) - -/* If ON, CPU will call the pc changed callback when it changes the PC by a - * large value. This allows host programs to be nicer when it comes to - * fetching immediate data and instructions on a banked memory system. - */ -#define M68K_MONITOR_PC OPT_OFF -#define M68K_SET_PC_CALLBACK(A) your_pc_changed_handler_function(A) - - -/* If ON, CPU will call the instruction hook callback before every - * instruction. - */ - /* CV Patch */ -#define M68K_INSTRUCTION_HOOK OPT_ON -#define M68K_INSTRUCTION_CALLBACK(pc) your_instruction_hook_function(pc) - - -/* If ON, the CPU will emulate the 4-byte prefetch queue of a real 68000 */ -#define M68K_EMULATE_PREFETCH OPT_OFF - - -/* If ON, the CPU will generate address error exceptions if it tries to - * access a word or longword at an odd address. - * NOTE: This is only emulated properly for 68000 mode. - */ -#define M68K_EMULATE_ADDRESS_ERROR OPT_OFF - -/* ---------- CV AddOns ---------- */ - -/* Intercept illegal A-Line opcodes and call hook. - Hook prototype is: int hook() - If return == 0 then normal A-Line exception handling is performed. - Otherwise nothing is done. - */ -#define M68K_ALINE_HOOK OPT_ON -#define M68K_ALINE_CALLBACK() your_aline_hook_function() - -/* Turn ON to enable logging of illegal instruction calls. - * M68K_LOG_FILEHANDLE must be #defined to a stdio file stream. - * Turn on M68K_LOG_1010_1111 to log all 1010 and 1111 calls. - */ -#define M68K_LOG_ENABLE OPT_OFF -#define M68K_LOG_1010_1111 OPT_OFF -#define M68K_LOG_FILEHANDLE some_file_handle - -/* Emulate PMMU : if you enable this, there will be a test to see if the current chip has some enabled pmmu added to every memory access, - * so enable this only if it's useful */ -#define M68K_EMULATE_PMMU OPT_ON - -/* ----------------------------- COMPATIBILITY ---------------------------- */ - -/* The following options set optimizations that violate the current ANSI - * standard, but will be compliant under the forthcoming C9X standard. - */ - - -/* If ON, the enulation core will use 64-bit integers to speed up some - * operations. -*/ -#define M68K_USE_64_BIT OPT_ON - - -#endif /* M68K_COMPILE_FOR_MAME */ - -/* ======================================================================== */ -/* ============================== END OF FILE ============================= */ -/* ======================================================================== */ - -#endif /* M68KCONF__HEADER */ diff --git a/machine/musashi/m68kcpu.c b/machine/musashi/m68kcpu.c deleted file mode 100644 index 9d7359d..0000000 --- a/machine/musashi/m68kcpu.c +++ /dev/null @@ -1,1239 +0,0 @@ -/* ======================================================================== */ -/* ========================= LICENSING & COPYRIGHT ======================== */ -/* ======================================================================== */ -/* - * MUSASHI - * Version 4.60 - * - * A portable Motorola M680x0 processor emulation engine. - * Copyright Karl Stenerud. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - - -/* ======================================================================== */ -/* ================================= NOTES ================================ */ -/* ======================================================================== */ - - - -/* ======================================================================== */ -/* ================================ INCLUDES ============================== */ -/* ======================================================================== */ - -extern void m68040_fpu_op0(void); -extern void m68040_fpu_op1(void); -extern void m68881_mmu_ops(void); -extern unsigned char m68ki_cycles[][0x10000]; -extern void (*m68ki_instruction_jump_table[0x10000])(void); /* opcode handler jump table */ -extern void m68ki_build_opcode_table(void); - -#include "m68kops.h" -#include "m68kcpu.h" - -#include "m68kfpu.c" -#include "m68kmmu.h" // uses some functions from m68kfpu.c which are static ! - -/* ======================================================================== */ -/* ================================= DATA ================================= */ -/* ======================================================================== */ - -int m68ki_initial_cycles; -int m68ki_remaining_cycles = 0; /* Number of clocks remaining */ -uint m68ki_tracing = 0; -uint m68ki_address_space; - -#ifdef M68K_LOG_ENABLE -const char *const m68ki_cpu_names[] = -{ - "Invalid CPU", - "M68000", - "M68010", - "M68EC020", - "M68020", - "M68EC030", - "M68030", - "M68EC040", - "M68LC040", - "M68040", - "SCC68070", -}; -#endif /* M68K_LOG_ENABLE */ - -/* The CPU core */ -m68ki_cpu_core m68ki_cpu = {0}; - -#if M68K_EMULATE_ADDRESS_ERROR -#ifdef _BSD_SETJMP_H -sigjmp_buf m68ki_aerr_trap; -#else -jmp_buf m68ki_aerr_trap; -#endif -#endif /* M68K_EMULATE_ADDRESS_ERROR */ - -uint m68ki_aerr_address; -uint m68ki_aerr_write_mode; -uint m68ki_aerr_fc; - -jmp_buf m68ki_bus_error_jmp_buf; - -/* Used by shift & rotate instructions */ -const uint8 m68ki_shift_8_table[65] = -{ - 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff -}; -const uint16 m68ki_shift_16_table[65] = -{ - 0x0000, 0x8000, 0xc000, 0xe000, 0xf000, 0xf800, 0xfc00, 0xfe00, 0xff00, - 0xff80, 0xffc0, 0xffe0, 0xfff0, 0xfff8, 0xfffc, 0xfffe, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, - 0xffff, 0xffff -}; -const uint m68ki_shift_32_table[65] = -{ - 0x00000000, 0x80000000, 0xc0000000, 0xe0000000, 0xf0000000, 0xf8000000, - 0xfc000000, 0xfe000000, 0xff000000, 0xff800000, 0xffc00000, 0xffe00000, - 0xfff00000, 0xfff80000, 0xfffc0000, 0xfffe0000, 0xffff0000, 0xffff8000, - 0xffffc000, 0xffffe000, 0xfffff000, 0xfffff800, 0xfffffc00, 0xfffffe00, - 0xffffff00, 0xffffff80, 0xffffffc0, 0xffffffe0, 0xfffffff0, 0xfffffff8, - 0xfffffffc, 0xfffffffe, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff -}; - - -/* Number of clock cycles to use for exception processing. - * I used 4 for any vectors that are undocumented for processing times. - */ -const uint8 m68ki_exception_cycle_table[5][256] = -{ - { /* 000 */ - 40, /* 0: Reset - Initial Stack Pointer */ - 4, /* 1: Reset - Initial Program Counter */ - 50, /* 2: Bus Error (unemulated) */ - 50, /* 3: Address Error (unemulated) */ - 34, /* 4: Illegal Instruction */ - 38, /* 5: Divide by Zero */ - 40, /* 6: CHK */ - 34, /* 7: TRAPV */ - 34, /* 8: Privilege Violation */ - 34, /* 9: Trace */ - 34, /* 10: 1010 */ - 34, /* 11: 1111 */ - 4, /* 12: RESERVED */ - 4, /* 13: Coprocessor Protocol Violation (unemulated) */ - 4, /* 14: Format Error */ - 44, /* 15: Uninitialized Interrupt */ - 4, /* 16: RESERVED */ - 4, /* 17: RESERVED */ - 4, /* 18: RESERVED */ - 4, /* 19: RESERVED */ - 4, /* 20: RESERVED */ - 4, /* 21: RESERVED */ - 4, /* 22: RESERVED */ - 4, /* 23: RESERVED */ - 44, /* 24: Spurious Interrupt */ - 44, /* 25: Level 1 Interrupt Autovector */ - 44, /* 26: Level 2 Interrupt Autovector */ - 44, /* 27: Level 3 Interrupt Autovector */ - 44, /* 28: Level 4 Interrupt Autovector */ - 44, /* 29: Level 5 Interrupt Autovector */ - 44, /* 30: Level 6 Interrupt Autovector */ - 44, /* 31: Level 7 Interrupt Autovector */ - 34, /* 32: TRAP #0 */ - 34, /* 33: TRAP #1 */ - 34, /* 34: TRAP #2 */ - 34, /* 35: TRAP #3 */ - 34, /* 36: TRAP #4 */ - 34, /* 37: TRAP #5 */ - 34, /* 38: TRAP #6 */ - 34, /* 39: TRAP #7 */ - 34, /* 40: TRAP #8 */ - 34, /* 41: TRAP #9 */ - 34, /* 42: TRAP #10 */ - 34, /* 43: TRAP #11 */ - 34, /* 44: TRAP #12 */ - 34, /* 45: TRAP #13 */ - 34, /* 46: TRAP #14 */ - 34, /* 47: TRAP #15 */ - 4, /* 48: FP Branch or Set on Unknown Condition (unemulated) */ - 4, /* 49: FP Inexact Result (unemulated) */ - 4, /* 50: FP Divide by Zero (unemulated) */ - 4, /* 51: FP Underflow (unemulated) */ - 4, /* 52: FP Operand Error (unemulated) */ - 4, /* 53: FP Overflow (unemulated) */ - 4, /* 54: FP Signaling NAN (unemulated) */ - 4, /* 55: FP Unimplemented Data Type (unemulated) */ - 4, /* 56: MMU Configuration Error (unemulated) */ - 4, /* 57: MMU Illegal Operation Error (unemulated) */ - 4, /* 58: MMU Access Level Violation Error (unemulated) */ - 4, /* 59: RESERVED */ - 4, /* 60: RESERVED */ - 4, /* 61: RESERVED */ - 4, /* 62: RESERVED */ - 4, /* 63: RESERVED */ - /* 64-255: User Defined */ - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4 - }, - { /* 010 */ - 40, /* 0: Reset - Initial Stack Pointer */ - 4, /* 1: Reset - Initial Program Counter */ - 126, /* 2: Bus Error (unemulated) */ - 126, /* 3: Address Error (unemulated) */ - 38, /* 4: Illegal Instruction */ - 44, /* 5: Divide by Zero */ - 44, /* 6: CHK */ - 34, /* 7: TRAPV */ - 38, /* 8: Privilege Violation */ - 38, /* 9: Trace */ - 4, /* 10: 1010 */ - 4, /* 11: 1111 */ - 4, /* 12: RESERVED */ - 4, /* 13: Coprocessor Protocol Violation (unemulated) */ - 4, /* 14: Format Error */ - 44, /* 15: Uninitialized Interrupt */ - 4, /* 16: RESERVED */ - 4, /* 17: RESERVED */ - 4, /* 18: RESERVED */ - 4, /* 19: RESERVED */ - 4, /* 20: RESERVED */ - 4, /* 21: RESERVED */ - 4, /* 22: RESERVED */ - 4, /* 23: RESERVED */ - 46, /* 24: Spurious Interrupt */ - 46, /* 25: Level 1 Interrupt Autovector */ - 46, /* 26: Level 2 Interrupt Autovector */ - 46, /* 27: Level 3 Interrupt Autovector */ - 46, /* 28: Level 4 Interrupt Autovector */ - 46, /* 29: Level 5 Interrupt Autovector */ - 46, /* 30: Level 6 Interrupt Autovector */ - 46, /* 31: Level 7 Interrupt Autovector */ - 38, /* 32: TRAP #0 */ - 38, /* 33: TRAP #1 */ - 38, /* 34: TRAP #2 */ - 38, /* 35: TRAP #3 */ - 38, /* 36: TRAP #4 */ - 38, /* 37: TRAP #5 */ - 38, /* 38: TRAP #6 */ - 38, /* 39: TRAP #7 */ - 38, /* 40: TRAP #8 */ - 38, /* 41: TRAP #9 */ - 38, /* 42: TRAP #10 */ - 38, /* 43: TRAP #11 */ - 38, /* 44: TRAP #12 */ - 38, /* 45: TRAP #13 */ - 38, /* 46: TRAP #14 */ - 38, /* 47: TRAP #15 */ - 4, /* 48: FP Branch or Set on Unknown Condition (unemulated) */ - 4, /* 49: FP Inexact Result (unemulated) */ - 4, /* 50: FP Divide by Zero (unemulated) */ - 4, /* 51: FP Underflow (unemulated) */ - 4, /* 52: FP Operand Error (unemulated) */ - 4, /* 53: FP Overflow (unemulated) */ - 4, /* 54: FP Signaling NAN (unemulated) */ - 4, /* 55: FP Unimplemented Data Type (unemulated) */ - 4, /* 56: MMU Configuration Error (unemulated) */ - 4, /* 57: MMU Illegal Operation Error (unemulated) */ - 4, /* 58: MMU Access Level Violation Error (unemulated) */ - 4, /* 59: RESERVED */ - 4, /* 60: RESERVED */ - 4, /* 61: RESERVED */ - 4, /* 62: RESERVED */ - 4, /* 63: RESERVED */ - /* 64-255: User Defined */ - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4 - }, - { /* 020 */ - 4, /* 0: Reset - Initial Stack Pointer */ - 4, /* 1: Reset - Initial Program Counter */ - 50, /* 2: Bus Error (unemulated) */ - 50, /* 3: Address Error (unemulated) */ - 20, /* 4: Illegal Instruction */ - 38, /* 5: Divide by Zero */ - 40, /* 6: CHK */ - 20, /* 7: TRAPV */ - 34, /* 8: Privilege Violation */ - 25, /* 9: Trace */ - 20, /* 10: 1010 */ - 20, /* 11: 1111 */ - 4, /* 12: RESERVED */ - 4, /* 13: Coprocessor Protocol Violation (unemulated) */ - 4, /* 14: Format Error */ - 30, /* 15: Uninitialized Interrupt */ - 4, /* 16: RESERVED */ - 4, /* 17: RESERVED */ - 4, /* 18: RESERVED */ - 4, /* 19: RESERVED */ - 4, /* 20: RESERVED */ - 4, /* 21: RESERVED */ - 4, /* 22: RESERVED */ - 4, /* 23: RESERVED */ - 30, /* 24: Spurious Interrupt */ - 30, /* 25: Level 1 Interrupt Autovector */ - 30, /* 26: Level 2 Interrupt Autovector */ - 30, /* 27: Level 3 Interrupt Autovector */ - 30, /* 28: Level 4 Interrupt Autovector */ - 30, /* 29: Level 5 Interrupt Autovector */ - 30, /* 30: Level 6 Interrupt Autovector */ - 30, /* 31: Level 7 Interrupt Autovector */ - 20, /* 32: TRAP #0 */ - 20, /* 33: TRAP #1 */ - 20, /* 34: TRAP #2 */ - 20, /* 35: TRAP #3 */ - 20, /* 36: TRAP #4 */ - 20, /* 37: TRAP #5 */ - 20, /* 38: TRAP #6 */ - 20, /* 39: TRAP #7 */ - 20, /* 40: TRAP #8 */ - 20, /* 41: TRAP #9 */ - 20, /* 42: TRAP #10 */ - 20, /* 43: TRAP #11 */ - 20, /* 44: TRAP #12 */ - 20, /* 45: TRAP #13 */ - 20, /* 46: TRAP #14 */ - 20, /* 47: TRAP #15 */ - 4, /* 48: FP Branch or Set on Unknown Condition (unemulated) */ - 4, /* 49: FP Inexact Result (unemulated) */ - 4, /* 50: FP Divide by Zero (unemulated) */ - 4, /* 51: FP Underflow (unemulated) */ - 4, /* 52: FP Operand Error (unemulated) */ - 4, /* 53: FP Overflow (unemulated) */ - 4, /* 54: FP Signaling NAN (unemulated) */ - 4, /* 55: FP Unimplemented Data Type (unemulated) */ - 4, /* 56: MMU Configuration Error (unemulated) */ - 4, /* 57: MMU Illegal Operation Error (unemulated) */ - 4, /* 58: MMU Access Level Violation Error (unemulated) */ - 4, /* 59: RESERVED */ - 4, /* 60: RESERVED */ - 4, /* 61: RESERVED */ - 4, /* 62: RESERVED */ - 4, /* 63: RESERVED */ - /* 64-255: User Defined */ - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4 - }, - { /* 030 - not correct */ - 4, /* 0: Reset - Initial Stack Pointer */ - 4, /* 1: Reset - Initial Program Counter */ - 50, /* 2: Bus Error (unemulated) */ - 50, /* 3: Address Error (unemulated) */ - 20, /* 4: Illegal Instruction */ - 38, /* 5: Divide by Zero */ - 40, /* 6: CHK */ - 20, /* 7: TRAPV */ - 34, /* 8: Privilege Violation */ - 25, /* 9: Trace */ - 20, /* 10: 1010 */ - 20, /* 11: 1111 */ - 4, /* 12: RESERVED */ - 4, /* 13: Coprocessor Protocol Violation (unemulated) */ - 4, /* 14: Format Error */ - 30, /* 15: Uninitialized Interrupt */ - 4, /* 16: RESERVED */ - 4, /* 17: RESERVED */ - 4, /* 18: RESERVED */ - 4, /* 19: RESERVED */ - 4, /* 20: RESERVED */ - 4, /* 21: RESERVED */ - 4, /* 22: RESERVED */ - 4, /* 23: RESERVED */ - 30, /* 24: Spurious Interrupt */ - 30, /* 25: Level 1 Interrupt Autovector */ - 30, /* 26: Level 2 Interrupt Autovector */ - 30, /* 27: Level 3 Interrupt Autovector */ - 30, /* 28: Level 4 Interrupt Autovector */ - 30, /* 29: Level 5 Interrupt Autovector */ - 30, /* 30: Level 6 Interrupt Autovector */ - 30, /* 31: Level 7 Interrupt Autovector */ - 20, /* 32: TRAP #0 */ - 20, /* 33: TRAP #1 */ - 20, /* 34: TRAP #2 */ - 20, /* 35: TRAP #3 */ - 20, /* 36: TRAP #4 */ - 20, /* 37: TRAP #5 */ - 20, /* 38: TRAP #6 */ - 20, /* 39: TRAP #7 */ - 20, /* 40: TRAP #8 */ - 20, /* 41: TRAP #9 */ - 20, /* 42: TRAP #10 */ - 20, /* 43: TRAP #11 */ - 20, /* 44: TRAP #12 */ - 20, /* 45: TRAP #13 */ - 20, /* 46: TRAP #14 */ - 20, /* 47: TRAP #15 */ - 4, /* 48: FP Branch or Set on Unknown Condition (unemulated) */ - 4, /* 49: FP Inexact Result (unemulated) */ - 4, /* 50: FP Divide by Zero (unemulated) */ - 4, /* 51: FP Underflow (unemulated) */ - 4, /* 52: FP Operand Error (unemulated) */ - 4, /* 53: FP Overflow (unemulated) */ - 4, /* 54: FP Signaling NAN (unemulated) */ - 4, /* 55: FP Unimplemented Data Type (unemulated) */ - 4, /* 56: MMU Configuration Error (unemulated) */ - 4, /* 57: MMU Illegal Operation Error (unemulated) */ - 4, /* 58: MMU Access Level Violation Error (unemulated) */ - 4, /* 59: RESERVED */ - 4, /* 60: RESERVED */ - 4, /* 61: RESERVED */ - 4, /* 62: RESERVED */ - 4, /* 63: RESERVED */ - /* 64-255: User Defined */ - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4 - }, - { /* 040 */ // TODO: these values are not correct - 4, /* 0: Reset - Initial Stack Pointer */ - 4, /* 1: Reset - Initial Program Counter */ - 50, /* 2: Bus Error (unemulated) */ - 50, /* 3: Address Error (unemulated) */ - 20, /* 4: Illegal Instruction */ - 38, /* 5: Divide by Zero */ - 40, /* 6: CHK */ - 20, /* 7: TRAPV */ - 34, /* 8: Privilege Violation */ - 25, /* 9: Trace */ - 20, /* 10: 1010 */ - 20, /* 11: 1111 */ - 4, /* 12: RESERVED */ - 4, /* 13: Coprocessor Protocol Violation (unemulated) */ - 4, /* 14: Format Error */ - 30, /* 15: Uninitialized Interrupt */ - 4, /* 16: RESERVED */ - 4, /* 17: RESERVED */ - 4, /* 18: RESERVED */ - 4, /* 19: RESERVED */ - 4, /* 20: RESERVED */ - 4, /* 21: RESERVED */ - 4, /* 22: RESERVED */ - 4, /* 23: RESERVED */ - 30, /* 24: Spurious Interrupt */ - 30, /* 25: Level 1 Interrupt Autovector */ - 30, /* 26: Level 2 Interrupt Autovector */ - 30, /* 27: Level 3 Interrupt Autovector */ - 30, /* 28: Level 4 Interrupt Autovector */ - 30, /* 29: Level 5 Interrupt Autovector */ - 30, /* 30: Level 6 Interrupt Autovector */ - 30, /* 31: Level 7 Interrupt Autovector */ - 20, /* 32: TRAP #0 */ - 20, /* 33: TRAP #1 */ - 20, /* 34: TRAP #2 */ - 20, /* 35: TRAP #3 */ - 20, /* 36: TRAP #4 */ - 20, /* 37: TRAP #5 */ - 20, /* 38: TRAP #6 */ - 20, /* 39: TRAP #7 */ - 20, /* 40: TRAP #8 */ - 20, /* 41: TRAP #9 */ - 20, /* 42: TRAP #10 */ - 20, /* 43: TRAP #11 */ - 20, /* 44: TRAP #12 */ - 20, /* 45: TRAP #13 */ - 20, /* 46: TRAP #14 */ - 20, /* 47: TRAP #15 */ - 4, /* 48: FP Branch or Set on Unknown Condition (unemulated) */ - 4, /* 49: FP Inexact Result (unemulated) */ - 4, /* 50: FP Divide by Zero (unemulated) */ - 4, /* 51: FP Underflow (unemulated) */ - 4, /* 52: FP Operand Error (unemulated) */ - 4, /* 53: FP Overflow (unemulated) */ - 4, /* 54: FP Signaling NAN (unemulated) */ - 4, /* 55: FP Unimplemented Data Type (unemulated) */ - 4, /* 56: MMU Configuration Error (unemulated) */ - 4, /* 57: MMU Illegal Operation Error (unemulated) */ - 4, /* 58: MMU Access Level Violation Error (unemulated) */ - 4, /* 59: RESERVED */ - 4, /* 60: RESERVED */ - 4, /* 61: RESERVED */ - 4, /* 62: RESERVED */ - 4, /* 63: RESERVED */ - /* 64-255: User Defined */ - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, - 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4 - } -}; - -const uint8 m68ki_ea_idx_cycle_table[64] = -{ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, /* ..01.000 no memory indirect, base NULL */ - 5, /* ..01..01 memory indirect, base NULL, outer NULL */ - 7, /* ..01..10 memory indirect, base NULL, outer 16 */ - 7, /* ..01..11 memory indirect, base NULL, outer 32 */ - 0, 5, 7, 7, 0, 5, 7, 7, 0, 5, 7, 7, - 2, /* ..10.000 no memory indirect, base 16 */ - 7, /* ..10..01 memory indirect, base 16, outer NULL */ - 9, /* ..10..10 memory indirect, base 16, outer 16 */ - 9, /* ..10..11 memory indirect, base 16, outer 32 */ - 0, 7, 9, 9, 0, 7, 9, 9, 0, 7, 9, 9, - 6, /* ..11.000 no memory indirect, base 32 */ - 11, /* ..11..01 memory indirect, base 32, outer NULL */ - 13, /* ..11..10 memory indirect, base 32, outer 16 */ - 13, /* ..11..11 memory indirect, base 32, outer 32 */ - 0, 11, 13, 13, 0, 11, 13, 13, 0, 11, 13, 13 -}; - - - -/* ======================================================================== */ -/* =============================== CALLBACKS ============================== */ -/* ======================================================================== */ - -/* Default callbacks used if the callback hasn't been set yet, or if the - * callback is set to NULL - */ - -/* Interrupt acknowledge */ -static int default_int_ack_callback_data; -static int default_int_ack_callback(int int_level) -{ - default_int_ack_callback_data = int_level; - CPU_INT_LEVEL = 0; - return M68K_INT_ACK_AUTOVECTOR; -} - -/* Breakpoint acknowledge */ -static unsigned int default_bkpt_ack_callback_data; -static void default_bkpt_ack_callback(unsigned int data) -{ - default_bkpt_ack_callback_data = data; -} - -/* Called when a reset instruction is executed */ -static void default_reset_instr_callback(void) -{ -} - -/* Called when a cmpi.l #v, dn instruction is executed */ -static void default_cmpild_instr_callback(unsigned int val, int reg) -{ - (void)val; - (void)reg; -} - -/* Called when a rte instruction is executed */ -static void default_rte_instr_callback(void) -{ -} - -/* Called when a tas instruction is executed */ -static int default_tas_instr_callback(void) -{ - return 1; // allow writeback -} - -/* Called when an illegal instruction is encountered */ -static int default_illg_instr_callback(int opcode) -{ - (void)opcode; - return 0; // not handled : exception will occur -} - -/* Called when the program counter changed by a large value */ -static unsigned int default_pc_changed_callback_data; -static void default_pc_changed_callback(unsigned int new_pc) -{ - default_pc_changed_callback_data = new_pc; -} - -/* Called every time there's bus activity (read/write to/from memory */ -static unsigned int default_set_fc_callback_data; -static void default_set_fc_callback(unsigned int new_fc) -{ - default_set_fc_callback_data = new_fc; -} - -/* Called every instruction cycle prior to execution */ -static void default_instr_hook_callback(unsigned int pc) -{ - (void)pc; -} - -/* CV */ -static int default_aline_hook_callback(unsigned int opcode, unsigned int pc) -{ - return M68K_ALINE_EXCEPT; -} - - -#if M68K_EMULATE_ADDRESS_ERROR - #include - #ifdef _BSD_SETJMP_H - sigjmp_buf m68ki_aerr_trap; - #else - jmp_buf m68ki_aerr_trap; - #endif -#endif /* M68K_EMULATE_ADDRESS_ERROR */ - -/* ======================================================================== */ -/* ================================= API ================================== */ -/* ======================================================================== */ - -/* Access the internals of the CPU */ -unsigned int m68k_get_reg(void* context, m68k_register_t regnum) -{ - m68ki_cpu_core* cpu = context != NULL ?(m68ki_cpu_core*)context : &m68ki_cpu; - - switch(regnum) - { - case M68K_REG_D0: return cpu->dar[0]; - case M68K_REG_D1: return cpu->dar[1]; - case M68K_REG_D2: return cpu->dar[2]; - case M68K_REG_D3: return cpu->dar[3]; - case M68K_REG_D4: return cpu->dar[4]; - case M68K_REG_D5: return cpu->dar[5]; - case M68K_REG_D6: return cpu->dar[6]; - case M68K_REG_D7: return cpu->dar[7]; - case M68K_REG_A0: return cpu->dar[8]; - case M68K_REG_A1: return cpu->dar[9]; - case M68K_REG_A2: return cpu->dar[10]; - case M68K_REG_A3: return cpu->dar[11]; - case M68K_REG_A4: return cpu->dar[12]; - case M68K_REG_A5: return cpu->dar[13]; - case M68K_REG_A6: return cpu->dar[14]; - case M68K_REG_A7: return cpu->dar[15]; - case M68K_REG_PC: return MASK_OUT_ABOVE_32(cpu->pc); - case M68K_REG_SR: return cpu->t1_flag | - cpu->t0_flag | - (cpu->s_flag << 11) | - (cpu->m_flag << 11) | - cpu->int_mask | - ((cpu->x_flag & XFLAG_SET) >> 4) | - ((cpu->n_flag & NFLAG_SET) >> 4) | - ((!cpu->not_z_flag) << 2) | - ((cpu->v_flag & VFLAG_SET) >> 6) | - ((cpu->c_flag & CFLAG_SET) >> 8); - case M68K_REG_SP: return cpu->dar[15]; - case M68K_REG_USP: return cpu->s_flag ? cpu->sp[0] : cpu->dar[15]; - case M68K_REG_ISP: return cpu->s_flag && !cpu->m_flag ? cpu->dar[15] : cpu->sp[4]; - case M68K_REG_MSP: return cpu->s_flag && cpu->m_flag ? cpu->dar[15] : cpu->sp[6]; - case M68K_REG_SFC: return cpu->sfc; - case M68K_REG_DFC: return cpu->dfc; - case M68K_REG_VBR: return cpu->vbr; - case M68K_REG_CACR: return cpu->cacr; - case M68K_REG_CAAR: return cpu->caar; - case M68K_REG_PREF_ADDR: return cpu->pref_addr; - case M68K_REG_PREF_DATA: return cpu->pref_data; - case M68K_REG_PPC: return MASK_OUT_ABOVE_32(cpu->ppc); - case M68K_REG_IR: return cpu->ir; - case M68K_REG_CPU_TYPE: - switch(cpu->cpu_type) - { - case CPU_TYPE_000: return (unsigned int)M68K_CPU_TYPE_68000; - case CPU_TYPE_010: return (unsigned int)M68K_CPU_TYPE_68010; - case CPU_TYPE_EC020: return (unsigned int)M68K_CPU_TYPE_68EC020; - case CPU_TYPE_020: return (unsigned int)M68K_CPU_TYPE_68020; - case CPU_TYPE_040: return (unsigned int)M68K_CPU_TYPE_68040; - } - return M68K_CPU_TYPE_INVALID; - default: return 0; - } - return 0; -} - -void m68k_set_reg(m68k_register_t regnum, unsigned int value) -{ - switch(regnum) - { - case M68K_REG_D0: REG_D[0] = MASK_OUT_ABOVE_32(value); return; - case M68K_REG_D1: REG_D[1] = MASK_OUT_ABOVE_32(value); return; - case M68K_REG_D2: REG_D[2] = MASK_OUT_ABOVE_32(value); return; - case M68K_REG_D3: REG_D[3] = MASK_OUT_ABOVE_32(value); return; - case M68K_REG_D4: REG_D[4] = MASK_OUT_ABOVE_32(value); return; - case M68K_REG_D5: REG_D[5] = MASK_OUT_ABOVE_32(value); return; - case M68K_REG_D6: REG_D[6] = MASK_OUT_ABOVE_32(value); return; - case M68K_REG_D7: REG_D[7] = MASK_OUT_ABOVE_32(value); return; - case M68K_REG_A0: REG_A[0] = MASK_OUT_ABOVE_32(value); return; - case M68K_REG_A1: REG_A[1] = MASK_OUT_ABOVE_32(value); return; - case M68K_REG_A2: REG_A[2] = MASK_OUT_ABOVE_32(value); return; - case M68K_REG_A3: REG_A[3] = MASK_OUT_ABOVE_32(value); return; - case M68K_REG_A4: REG_A[4] = MASK_OUT_ABOVE_32(value); return; - case M68K_REG_A5: REG_A[5] = MASK_OUT_ABOVE_32(value); return; - case M68K_REG_A6: REG_A[6] = MASK_OUT_ABOVE_32(value); return; - case M68K_REG_A7: REG_A[7] = MASK_OUT_ABOVE_32(value); return; - case M68K_REG_PC: m68ki_jump(MASK_OUT_ABOVE_32(value)); return; - case M68K_REG_SR: m68ki_set_sr_noint_nosp(value); return; - case M68K_REG_SP: REG_SP = MASK_OUT_ABOVE_32(value); return; - case M68K_REG_USP: if(FLAG_S) - REG_USP = MASK_OUT_ABOVE_32(value); - else - REG_SP = MASK_OUT_ABOVE_32(value); - return; - case M68K_REG_ISP: if(FLAG_S && !FLAG_M) - REG_SP = MASK_OUT_ABOVE_32(value); - else - REG_ISP = MASK_OUT_ABOVE_32(value); - return; - case M68K_REG_MSP: if(FLAG_S && FLAG_M) - REG_SP = MASK_OUT_ABOVE_32(value); - else - REG_MSP = MASK_OUT_ABOVE_32(value); - return; - case M68K_REG_VBR: REG_VBR = MASK_OUT_ABOVE_32(value); return; - case M68K_REG_SFC: REG_SFC = value & 7; return; - case M68K_REG_DFC: REG_DFC = value & 7; return; - case M68K_REG_CACR: REG_CACR = MASK_OUT_ABOVE_32(value); return; - case M68K_REG_CAAR: REG_CAAR = MASK_OUT_ABOVE_32(value); return; - case M68K_REG_PPC: REG_PPC = MASK_OUT_ABOVE_32(value); return; - case M68K_REG_IR: REG_IR = MASK_OUT_ABOVE_16(value); return; - case M68K_REG_CPU_TYPE: m68k_set_cpu_type(value); return; - default: return; - } -} - -/* Set the callbacks */ -void m68k_set_int_ack_callback(int (*callback)(int int_level)) -{ - CALLBACK_INT_ACK = callback ? callback : default_int_ack_callback; -} - -void m68k_set_bkpt_ack_callback(void (*callback)(unsigned int data)) -{ - CALLBACK_BKPT_ACK = callback ? callback : default_bkpt_ack_callback; -} - -void m68k_set_reset_instr_callback(void (*callback)(void)) -{ - CALLBACK_RESET_INSTR = callback ? callback : default_reset_instr_callback; -} - -void m68k_set_cmpild_instr_callback(void (*callback)(unsigned int, int)) -{ - CALLBACK_CMPILD_INSTR = callback ? callback : default_cmpild_instr_callback; -} - -void m68k_set_rte_instr_callback(void (*callback)(void)) -{ - CALLBACK_RTE_INSTR = callback ? callback : default_rte_instr_callback; -} - -void m68k_set_tas_instr_callback(int (*callback)(void)) -{ - CALLBACK_TAS_INSTR = callback ? callback : default_tas_instr_callback; -} - -void m68k_set_illg_instr_callback(int (*callback)(int)) -{ - CALLBACK_ILLG_INSTR = callback ? callback : default_illg_instr_callback; -} - -void m68k_set_pc_changed_callback(void (*callback)(unsigned int new_pc)) -{ - CALLBACK_PC_CHANGED = callback ? callback : default_pc_changed_callback; -} - -void m68k_set_fc_callback(void (*callback)(unsigned int new_fc)) -{ - CALLBACK_SET_FC = callback ? callback : default_set_fc_callback; -} - -void m68k_set_instr_hook_callback(void (*callback)(unsigned int pc)) -{ - CALLBACK_INSTR_HOOK = callback ? callback : default_instr_hook_callback; -} - -/* CV */ -void m68k_set_aline_hook_callback(int (*callback)(unsigned int, unsigned int)) -{ - CALLBACK_ALINE_HOOK = callback ? callback : default_aline_hook_callback; -} - -/* Set the CPU type. */ -void m68k_set_cpu_type(unsigned int cpu_type) -{ - switch(cpu_type) - { - case M68K_CPU_TYPE_68000: - CPU_TYPE = CPU_TYPE_000; - CPU_ADDRESS_MASK = 0x00ffffff; - CPU_SR_MASK = 0xa71f; /* T1 -- S -- -- I2 I1 I0 -- -- -- X N Z V C */ - CYC_INSTRUCTION = m68ki_cycles[0]; - CYC_EXCEPTION = m68ki_exception_cycle_table[0]; - CYC_BCC_NOTAKE_B = -2; - CYC_BCC_NOTAKE_W = 2; - CYC_DBCC_F_NOEXP = -2; - CYC_DBCC_F_EXP = 2; - CYC_SCC_R_TRUE = 2; - CYC_MOVEM_W = 2; - CYC_MOVEM_L = 3; - CYC_SHIFT = 1; - CYC_RESET = 132; - HAS_PMMU = 0; - return; - case M68K_CPU_TYPE_SCC68070: - m68k_set_cpu_type(M68K_CPU_TYPE_68010); - CPU_ADDRESS_MASK = 0xffffffff; - CPU_TYPE = CPU_TYPE_SCC070; - return; - case M68K_CPU_TYPE_68010: - CPU_TYPE = CPU_TYPE_010; - CPU_ADDRESS_MASK = 0x00ffffff; - CPU_SR_MASK = 0xa71f; /* T1 -- S -- -- I2 I1 I0 -- -- -- X N Z V C */ - CYC_INSTRUCTION = m68ki_cycles[1]; - CYC_EXCEPTION = m68ki_exception_cycle_table[1]; - CYC_BCC_NOTAKE_B = -4; - CYC_BCC_NOTAKE_W = 0; - CYC_DBCC_F_NOEXP = 0; - CYC_DBCC_F_EXP = 6; - CYC_SCC_R_TRUE = 0; - CYC_MOVEM_W = 2; - CYC_MOVEM_L = 3; - CYC_SHIFT = 1; - CYC_RESET = 130; - HAS_PMMU = 0; - return; - case M68K_CPU_TYPE_68EC020: - CPU_TYPE = CPU_TYPE_EC020; - CPU_ADDRESS_MASK = 0x00ffffff; - CPU_SR_MASK = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */ - CYC_INSTRUCTION = m68ki_cycles[2]; - CYC_EXCEPTION = m68ki_exception_cycle_table[2]; - CYC_BCC_NOTAKE_B = -2; - CYC_BCC_NOTAKE_W = 0; - CYC_DBCC_F_NOEXP = 0; - CYC_DBCC_F_EXP = 4; - CYC_SCC_R_TRUE = 0; - CYC_MOVEM_W = 2; - CYC_MOVEM_L = 2; - CYC_SHIFT = 0; - CYC_RESET = 518; - HAS_PMMU = 0; - return; - case M68K_CPU_TYPE_68020: - CPU_TYPE = CPU_TYPE_020; - CPU_ADDRESS_MASK = 0xffffffff; - CPU_SR_MASK = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */ - CYC_INSTRUCTION = m68ki_cycles[2]; - CYC_EXCEPTION = m68ki_exception_cycle_table[2]; - CYC_BCC_NOTAKE_B = -2; - CYC_BCC_NOTAKE_W = 0; - CYC_DBCC_F_NOEXP = 0; - CYC_DBCC_F_EXP = 4; - CYC_SCC_R_TRUE = 0; - CYC_MOVEM_W = 2; - CYC_MOVEM_L = 2; - CYC_SHIFT = 0; - CYC_RESET = 518; - HAS_PMMU = 0; - return; - case M68K_CPU_TYPE_68030: - CPU_TYPE = CPU_TYPE_030; - CPU_ADDRESS_MASK = 0xffffffff; - CPU_SR_MASK = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */ - CYC_INSTRUCTION = m68ki_cycles[3]; - CYC_EXCEPTION = m68ki_exception_cycle_table[3]; - CYC_BCC_NOTAKE_B = -2; - CYC_BCC_NOTAKE_W = 0; - CYC_DBCC_F_NOEXP = 0; - CYC_DBCC_F_EXP = 4; - CYC_SCC_R_TRUE = 0; - CYC_MOVEM_W = 2; - CYC_MOVEM_L = 2; - CYC_SHIFT = 0; - CYC_RESET = 518; - HAS_PMMU = 1; - return; - case M68K_CPU_TYPE_68EC030: - CPU_TYPE = CPU_TYPE_EC030; - CPU_ADDRESS_MASK = 0xffffffff; - CPU_SR_MASK = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */ - CYC_INSTRUCTION = m68ki_cycles[3]; - CYC_EXCEPTION = m68ki_exception_cycle_table[3]; - CYC_BCC_NOTAKE_B = -2; - CYC_BCC_NOTAKE_W = 0; - CYC_DBCC_F_NOEXP = 0; - CYC_DBCC_F_EXP = 4; - CYC_SCC_R_TRUE = 0; - CYC_MOVEM_W = 2; - CYC_MOVEM_L = 2; - CYC_SHIFT = 0; - CYC_RESET = 518; - HAS_PMMU = 0; /* EC030 lacks the PMMU and is effectively a die-shrink 68020 */ - return; - case M68K_CPU_TYPE_68040: // TODO: these values are not correct - CPU_TYPE = CPU_TYPE_040; - CPU_ADDRESS_MASK = 0xffffffff; - CPU_SR_MASK = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */ - CYC_INSTRUCTION = m68ki_cycles[4]; - CYC_EXCEPTION = m68ki_exception_cycle_table[4]; - CYC_BCC_NOTAKE_B = -2; - CYC_BCC_NOTAKE_W = 0; - CYC_DBCC_F_NOEXP = 0; - CYC_DBCC_F_EXP = 4; - CYC_SCC_R_TRUE = 0; - CYC_MOVEM_W = 2; - CYC_MOVEM_L = 2; - CYC_SHIFT = 0; - CYC_RESET = 518; - HAS_PMMU = 1; - return; - case M68K_CPU_TYPE_68EC040: // Just a 68040 without pmmu apparently... - CPU_TYPE = CPU_TYPE_EC040; - CPU_ADDRESS_MASK = 0xffffffff; - CPU_SR_MASK = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */ - CYC_INSTRUCTION = m68ki_cycles[4]; - CYC_EXCEPTION = m68ki_exception_cycle_table[4]; - CYC_BCC_NOTAKE_B = -2; - CYC_BCC_NOTAKE_W = 0; - CYC_DBCC_F_NOEXP = 0; - CYC_DBCC_F_EXP = 4; - CYC_SCC_R_TRUE = 0; - CYC_MOVEM_W = 2; - CYC_MOVEM_L = 2; - CYC_SHIFT = 0; - CYC_RESET = 518; - HAS_PMMU = 0; - return; - case M68K_CPU_TYPE_68LC040: - CPU_TYPE = CPU_TYPE_LC040; - m68ki_cpu.sr_mask = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */ - m68ki_cpu.cyc_instruction = m68ki_cycles[4]; - m68ki_cpu.cyc_exception = m68ki_exception_cycle_table[4]; - m68ki_cpu.cyc_bcc_notake_b = -2; - m68ki_cpu.cyc_bcc_notake_w = 0; - m68ki_cpu.cyc_dbcc_f_noexp = 0; - m68ki_cpu.cyc_dbcc_f_exp = 4; - m68ki_cpu.cyc_scc_r_true = 0; - m68ki_cpu.cyc_movem_w = 2; - m68ki_cpu.cyc_movem_l = 2; - m68ki_cpu.cyc_shift = 0; - m68ki_cpu.cyc_reset = 518; - HAS_PMMU = 1; - return; - } -} - -/* Execute some instructions until we use up num_cycles clock cycles */ -/* ASG: removed per-instruction interrupt checks */ -int m68k_execute(int num_cycles) -{ - /* eat up any reset cycles */ - if (RESET_CYCLES) { - int rc = RESET_CYCLES; - RESET_CYCLES = 0; - num_cycles -= rc; - if (num_cycles <= 0) - return rc; - } - - /* Set our pool of clock cycles available */ - SET_CYCLES(num_cycles); - m68ki_initial_cycles = num_cycles; - - /* See if interrupts came in */ - m68ki_check_interrupts(); - - /* Make sure we're not stopped */ - if(!CPU_STOPPED) - { - /* Return point if we had an address error */ - m68ki_set_address_error_trap(); /* auto-disable (see m68kcpu.h) */ - - m68ki_check_bus_error_trap(); - - /* Main loop. Keep going until we run out of clock cycles */ - do - { - int i; - /* Set tracing accodring to T1. (T0 is done inside instruction) */ - m68ki_trace_t1(); /* auto-disable (see m68kcpu.h) */ - - /* Set the address space for reads */ - m68ki_use_data_space(); /* auto-disable (see m68kcpu.h) */ - - /* Call external hook to peek at CPU */ - m68ki_instr_hook(REG_PC); /* auto-disable (see m68kcpu.h) */ - - /* Record previous program counter */ - REG_PPC = REG_PC; - - /* Record previous D/A register state (in case of bus error) */ - for (i = 15; i >= 0; i--){ - REG_DA_SAVE[i] = REG_DA[i]; - } - - /* Read an instruction and call its handler */ - REG_IR = m68ki_read_imm_16(); - m68ki_instruction_jump_table[REG_IR](); - USE_CYCLES(CYC_INSTRUCTION[REG_IR]); - - /* Trace m68k_exception, if necessary */ - m68ki_exception_if_trace(); /* auto-disable (see m68kcpu.h) */ - } while(GET_CYCLES() > 0); - - /* set previous PC to current PC for the next entry into the loop */ - REG_PPC = REG_PC; - } - else - SET_CYCLES(0); - - /* return how many clocks we used */ - return m68ki_initial_cycles - GET_CYCLES(); -} - - -int m68k_cycles_run(void) -{ - return m68ki_initial_cycles - GET_CYCLES(); -} - -int m68k_cycles_remaining(void) -{ - return GET_CYCLES(); -} - -/* Change the timeslice */ -void m68k_modify_timeslice(int cycles) -{ - m68ki_initial_cycles += cycles; - ADD_CYCLES(cycles); -} - - -void m68k_end_timeslice(void) -{ - m68ki_initial_cycles = GET_CYCLES(); - SET_CYCLES(0); -} - - -/* ASG: rewrote so that the int_level is a mask of the IPL0/IPL1/IPL2 bits */ -/* KS: Modified so that IPL* bits match with mask positions in the SR - * and cleaned out remenants of the interrupt controller. - */ -void m68k_set_irq(unsigned int int_level) -{ - uint old_level = CPU_INT_LEVEL; - CPU_INT_LEVEL = int_level << 8; - - /* A transition from < 7 to 7 always interrupts (NMI) */ - /* Note: Level 7 can also level trigger like a normal IRQ */ - if(old_level != 0x0700 && CPU_INT_LEVEL == 0x0700) - m68ki_cpu.nmi_pending = TRUE; -} - -void m68k_set_virq(unsigned int level, unsigned int active) -{ - uint state = m68ki_cpu.virq_state; - uint blevel; - - if(active) - state |= 1 << level; - else - state &= ~(1 << level); - m68ki_cpu.virq_state = state; - - for(blevel = 7; blevel > 0; blevel--) - if(state & (1 << blevel)) - break; - m68k_set_irq(blevel); -} - -unsigned int m68k_get_virq(unsigned int level) -{ - return (m68ki_cpu.virq_state & (1 << level)) ? 1 : 0; -} - -void m68k_init(void) -{ - static uint emulation_initialized = 0; - - /* The first call to this function initializes the opcode handler jump table */ - if(!emulation_initialized) - { - m68ki_build_opcode_table(); - emulation_initialized = 1; - } - - m68k_set_int_ack_callback(NULL); - m68k_set_bkpt_ack_callback(NULL); - m68k_set_reset_instr_callback(NULL); - m68k_set_cmpild_instr_callback(NULL); - m68k_set_rte_instr_callback(NULL); - m68k_set_tas_instr_callback(NULL); - m68k_set_illg_instr_callback(NULL); - m68k_set_pc_changed_callback(NULL); - m68k_set_fc_callback(NULL); - m68k_set_instr_hook_callback(NULL); - /* CV */ - m68k_set_aline_hook_callback(NULL); -} - -/* Trigger a Bus Error exception */ -void m68k_pulse_bus_error(void) -{ - m68ki_exception_bus_error(); -} - -/* Pulse the RESET line on the CPU */ -void m68k_pulse_reset(void) -{ - /* Disable the PMMU on reset */ - m68ki_cpu.pmmu_enabled = 0; - - /* Clear all stop levels and eat up all remaining cycles */ - CPU_STOPPED = 0; - SET_CYCLES(0); - - CPU_RUN_MODE = RUN_MODE_BERR_AERR_RESET; - CPU_INSTR_MODE = INSTRUCTION_YES; - - /* Turn off tracing */ - FLAG_T1 = FLAG_T0 = 0; - m68ki_clear_trace(); - /* Interrupt mask to level 7 */ - FLAG_INT_MASK = 0x0700; - CPU_INT_LEVEL = 0; - m68ki_cpu.virq_state = 0; - /* Reset VBR */ - REG_VBR = 0; - /* Go to supervisor mode */ - m68ki_set_sm_flag(SFLAG_SET | MFLAG_CLEAR); - - /* Invalidate the prefetch queue */ -#if M68K_EMULATE_PREFETCH - /* Set to arbitrary number since our first fetch is from 0 */ - CPU_PREF_ADDR = 0x1000; -#endif /* M68K_EMULATE_PREFETCH */ - - /* Read the initial stack pointer and program counter */ - m68ki_jump(0); - REG_SP = m68ki_read_imm_32(); - REG_PC = m68ki_read_imm_32(); - m68ki_jump(REG_PC); - - CPU_RUN_MODE = RUN_MODE_NORMAL; - - RESET_CYCLES = CYC_EXCEPTION[EXCEPTION_RESET]; -} - -/* Pulse the HALT line on the CPU */ -void m68k_pulse_halt(void) -{ - CPU_STOPPED |= STOP_LEVEL_HALT; -} - -/* Get and set the current CPU context */ -/* This is to allow for multiple CPUs */ -unsigned int m68k_context_size() -{ - return sizeof(m68ki_cpu_core); -} - -unsigned int m68k_get_context(void* dst) -{ - if(dst) *(m68ki_cpu_core*)dst = m68ki_cpu; - return sizeof(m68ki_cpu_core); -} - -void m68k_set_context(void* src) -{ - if(src) m68ki_cpu = *(m68ki_cpu_core*)src; -} - -/* ======================================================================== */ -/* ============================== MAME STUFF ============================== */ -/* ======================================================================== */ - -#if M68K_COMPILE_FOR_MAME == OPT_ON - -static struct { - UINT16 sr; - UINT8 stopped; - UINT8 halted; -} m68k_substate; - -static void m68k_prepare_substate(void) -{ - m68k_substate.sr = m68ki_get_sr(); - m68k_substate.stopped = (CPU_STOPPED & STOP_LEVEL_STOP) != 0; - m68k_substate.halted = (CPU_STOPPED & STOP_LEVEL_HALT) != 0; -} - -static void m68k_post_load(void) -{ - m68ki_set_sr_noint_nosp(m68k_substate.sr); - CPU_STOPPED = m68k_substate.stopped ? STOP_LEVEL_STOP : 0 - | m68k_substate.halted ? STOP_LEVEL_HALT : 0; - m68ki_jump(REG_PC); -} - -void m68k_state_register(const char *type, int index) -{ - /* Note, D covers A because the dar array is common, REG_A=REG_D+8 */ - state_save_register_item_array(type, index, REG_D); - state_save_register_item(type, index, REG_PPC); - state_save_register_item(type, index, REG_PC); - state_save_register_item(type, index, REG_USP); - state_save_register_item(type, index, REG_ISP); - state_save_register_item(type, index, REG_MSP); - state_save_register_item(type, index, REG_VBR); - state_save_register_item(type, index, REG_SFC); - state_save_register_item(type, index, REG_DFC); - state_save_register_item(type, index, REG_CACR); - state_save_register_item(type, index, REG_CAAR); - state_save_register_item(type, index, m68k_substate.sr); - state_save_register_item(type, index, CPU_INT_LEVEL); - state_save_register_item(type, index, m68k_substate.stopped); - state_save_register_item(type, index, m68k_substate.halted); - state_save_register_item(type, index, CPU_PREF_ADDR); - state_save_register_item(type, index, CPU_PREF_DATA); - state_save_register_func_presave(m68k_prepare_substate); - state_save_register_func_postload(m68k_post_load); -} - -#endif /* M68K_COMPILE_FOR_MAME */ - -/* ======================================================================== */ -/* ============================== END OF FILE ============================= */ -/* ======================================================================== */ diff --git a/machine/musashi/m68kcpu.h b/machine/musashi/m68kcpu.h deleted file mode 100644 index 8dab514..0000000 --- a/machine/musashi/m68kcpu.h +++ /dev/null @@ -1,2182 +0,0 @@ -/* ======================================================================== */ -/* ========================= LICENSING & COPYRIGHT ======================== */ -/* ======================================================================== */ -/* - * MUSASHI - * Version 4.5 - * - * A portable Motorola M680x0 processor emulation engine. - * Copyright Karl Stenerud. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - - - - -#ifndef M68KCPU__HEADER -#define M68KCPU__HEADER - -#ifdef __cplusplus -extern "C" { -#endif - -#include "m68k.h" - -#include - -#include - -/* ======================================================================== */ -/* ==================== ARCHITECTURE-DEPENDANT DEFINES ==================== */ -/* ======================================================================== */ - -/* Check for > 32bit sizes */ -#if UINT_MAX > 0xffffffff - #define M68K_INT_GT_32_BIT 1 -#else - #define M68K_INT_GT_32_BIT 0 -#endif - -/* Data types used in this emulation core */ -#undef sint8 -#undef sint16 -#undef sint32 -#undef sint64 -#undef uint8 -#undef uint16 -#undef uint32 -#undef uint64 -#undef sint -#undef uint - -typedef signed char sint8; /* ASG: changed from char to signed char */ -typedef signed short sint16; -typedef signed int sint32; /* AWJ: changed from long to int */ -typedef unsigned char uint8; -typedef unsigned short uint16; -typedef unsigned int uint32; /* AWJ: changed from long to int */ - -/* signed and unsigned int must be at least 32 bits wide */ -typedef signed int sint; -typedef unsigned int uint; - - -#if M68K_USE_64_BIT -typedef signed long long sint64; -typedef unsigned long long uint64; -#else -typedef sint32 sint64; -typedef uint32 uint64; -#endif /* M68K_USE_64_BIT */ - -/* U64 and S64 are used to wrap long integer constants. */ -#ifdef __GNUC__ -#define U64(val) val##ULL -#define S64(val) val##LL -#else -#define U64(val) val -#define S64(val) val -#endif - -#include "softfloat/milieu.h" -#include "softfloat/softfloat.h" - - -/* Allow for architectures that don't have 8-bit sizes */ -#if UCHAR_MAX == 0xff - #define MAKE_INT_8(A) (sint8)(A) -#else - #undef sint8 - #define sint8 signed int - #undef uint8 - #define uint8 unsigned int - static inline sint MAKE_INT_8(uint value) - { - return (value & 0x80) ? value | ~0xff : value & 0xff; - } -#endif /* UCHAR_MAX == 0xff */ - - -/* Allow for architectures that don't have 16-bit sizes */ -#if USHRT_MAX == 0xffff - #define MAKE_INT_16(A) (sint16)(A) -#else - #undef sint16 - #define sint16 signed int - #undef uint16 - #define uint16 unsigned int - static inline sint MAKE_INT_16(uint value) - { - return (value & 0x8000) ? value | ~0xffff : value & 0xffff; - } -#endif /* USHRT_MAX == 0xffff */ - - -/* Allow for architectures that don't have 32-bit sizes */ -#if UINT_MAX == 0xffffffff - #define MAKE_INT_32(A) (sint32)(A) -#else - #undef sint32 - #define sint32 signed int - #undef uint32 - #define uint32 unsigned int - static inline sint MAKE_INT_32(uint value) - { - return (value & 0x80000000) ? value | ~0xffffffff : value & 0xffffffff; - } -#endif /* UINT_MAX == 0xffffffff */ - - - - -/* ======================================================================== */ -/* ============================ GENERAL DEFINES =========================== */ -/* ======================================================================== */ - -/* Exception Vectors handled by emulation */ -#define EXCEPTION_RESET 0 -#define EXCEPTION_BUS_ERROR 2 /* This one is not emulated! */ -#define EXCEPTION_ADDRESS_ERROR 3 /* This one is partially emulated (doesn't stack a proper frame yet) */ -#define EXCEPTION_ILLEGAL_INSTRUCTION 4 -#define EXCEPTION_ZERO_DIVIDE 5 -#define EXCEPTION_CHK 6 -#define EXCEPTION_TRAPV 7 -#define EXCEPTION_PRIVILEGE_VIOLATION 8 -#define EXCEPTION_TRACE 9 -#define EXCEPTION_1010 10 -#define EXCEPTION_1111 11 -#define EXCEPTION_FORMAT_ERROR 14 -#define EXCEPTION_UNINITIALIZED_INTERRUPT 15 -#define EXCEPTION_SPURIOUS_INTERRUPT 24 -#define EXCEPTION_INTERRUPT_AUTOVECTOR 24 -#define EXCEPTION_TRAP_BASE 32 - -/* Function codes set by CPU during data/address bus activity */ -#define FUNCTION_CODE_USER_DATA 1 -#define FUNCTION_CODE_USER_PROGRAM 2 -#define FUNCTION_CODE_SUPERVISOR_DATA 5 -#define FUNCTION_CODE_SUPERVISOR_PROGRAM 6 -#define FUNCTION_CODE_CPU_SPACE 7 - -/* CPU types for deciding what to emulate */ -#define CPU_TYPE_000 (0x00000001) -#define CPU_TYPE_008 (0x00000002) -#define CPU_TYPE_010 (0x00000004) -#define CPU_TYPE_EC020 (0x00000008) -#define CPU_TYPE_020 (0x00000010) -#define CPU_TYPE_EC030 (0x00000020) -#define CPU_TYPE_030 (0x00000040) -#define CPU_TYPE_EC040 (0x00000080) -#define CPU_TYPE_LC040 (0x00000100) -#define CPU_TYPE_040 (0x00000200) -#define CPU_TYPE_SCC070 (0x00000400) - -/* Different ways to stop the CPU */ -#define STOP_LEVEL_STOP 1 -#define STOP_LEVEL_HALT 2 - -/* Used for 68000 address error processing */ -#define INSTRUCTION_YES 0 -#define INSTRUCTION_NO 0x08 -#define MODE_READ 0x10 -#define MODE_WRITE 0 - -#define RUN_MODE_NORMAL 0 -#define RUN_MODE_BERR_AERR_RESET_WSF 1 /* writing stack frame */ -#define RUN_MODE_BERR_AERR_RESET 2 /* stack frame done */ - -#ifndef NULL -#define NULL ((void*)0) -#endif - -/* ======================================================================== */ -/* ================================ MACROS ================================ */ -/* ======================================================================== */ - - -/* ---------------------------- General Macros ---------------------------- */ - -/* Bit Isolation Macros */ -#define BIT_0(A) ((A) & 0x00000001) -#define BIT_1(A) ((A) & 0x00000002) -#define BIT_2(A) ((A) & 0x00000004) -#define BIT_3(A) ((A) & 0x00000008) -#define BIT_4(A) ((A) & 0x00000010) -#define BIT_5(A) ((A) & 0x00000020) -#define BIT_6(A) ((A) & 0x00000040) -#define BIT_7(A) ((A) & 0x00000080) -#define BIT_8(A) ((A) & 0x00000100) -#define BIT_9(A) ((A) & 0x00000200) -#define BIT_A(A) ((A) & 0x00000400) -#define BIT_B(A) ((A) & 0x00000800) -#define BIT_C(A) ((A) & 0x00001000) -#define BIT_D(A) ((A) & 0x00002000) -#define BIT_E(A) ((A) & 0x00004000) -#define BIT_F(A) ((A) & 0x00008000) -#define BIT_10(A) ((A) & 0x00010000) -#define BIT_11(A) ((A) & 0x00020000) -#define BIT_12(A) ((A) & 0x00040000) -#define BIT_13(A) ((A) & 0x00080000) -#define BIT_14(A) ((A) & 0x00100000) -#define BIT_15(A) ((A) & 0x00200000) -#define BIT_16(A) ((A) & 0x00400000) -#define BIT_17(A) ((A) & 0x00800000) -#define BIT_18(A) ((A) & 0x01000000) -#define BIT_19(A) ((A) & 0x02000000) -#define BIT_1A(A) ((A) & 0x04000000) -#define BIT_1B(A) ((A) & 0x08000000) -#define BIT_1C(A) ((A) & 0x10000000) -#define BIT_1D(A) ((A) & 0x20000000) -#define BIT_1E(A) ((A) & 0x40000000) -#define BIT_1F(A) ((A) & 0x80000000) - -/* Get the most significant bit for specific sizes */ -#define GET_MSB_8(A) ((A) & 0x80) -#define GET_MSB_9(A) ((A) & 0x100) -#define GET_MSB_16(A) ((A) & 0x8000) -#define GET_MSB_17(A) ((A) & 0x10000) -#define GET_MSB_32(A) ((A) & 0x80000000) -#if M68K_USE_64_BIT -#define GET_MSB_33(A) ((A) & 0x100000000) -#endif /* M68K_USE_64_BIT */ - -/* Isolate nibbles */ -#define LOW_NIBBLE(A) ((A) & 0x0f) -#define HIGH_NIBBLE(A) ((A) & 0xf0) - -/* These are used to isolate 8, 16, and 32 bit sizes */ -#define MASK_OUT_ABOVE_2(A) ((A) & 3) -#define MASK_OUT_ABOVE_8(A) ((A) & 0xff) -#define MASK_OUT_ABOVE_16(A) ((A) & 0xffff) -#define MASK_OUT_BELOW_2(A) ((A) & ~3) -#define MASK_OUT_BELOW_8(A) ((A) & ~0xff) -#define MASK_OUT_BELOW_16(A) ((A) & ~0xffff) - -/* No need to mask if we are 32 bit */ -#if M68K_INT_GT_32_BIT || M68K_USE_64_BIT - #define MASK_OUT_ABOVE_32(A) ((A) & 0xffffffff) - #define MASK_OUT_BELOW_32(A) ((A) & ~0xffffffff) -#else - #define MASK_OUT_ABOVE_32(A) (A) - #define MASK_OUT_BELOW_32(A) 0 -#endif /* M68K_INT_GT_32_BIT || M68K_USE_64_BIT */ - -/* Simulate address lines of 68k family */ -#define ADDRESS_68K(A) ((A)&CPU_ADDRESS_MASK) - - -/* Shift & Rotate Macros. */ -#define LSL(A, C) ((A) << (C)) -#define LSR(A, C) ((A) >> (C)) - -/* Some > 32-bit optimizations */ -#if M68K_INT_GT_32_BIT - /* Shift left and right */ - #define LSR_32(A, C) ((A) >> (C)) - #define LSL_32(A, C) ((A) << (C)) -#else - /* We have to do this because the morons at ANSI decided that shifts - * by >= data size are undefined. - */ - #define LSR_32(A, C) ((C) < 32 ? (A) >> (C) : 0) - #define LSL_32(A, C) ((C) < 32 ? (A) << (C) : 0) -#endif /* M68K_INT_GT_32_BIT */ - -#if M68K_USE_64_BIT - #define LSL_32_64(A, C) ((A) << (C)) - #define LSR_32_64(A, C) ((A) >> (C)) - #define ROL_33_64(A, C) (LSL_32_64(A, C) | LSR_32_64(A, 33-(C))) - #define ROR_33_64(A, C) (LSR_32_64(A, C) | LSL_32_64(A, 33-(C))) -#endif /* M68K_USE_64_BIT */ - -#define ROL_8(A, C) MASK_OUT_ABOVE_8(LSL(A, C) | LSR(A, 8-(C))) -#define ROL_9(A, C) (LSL(A, C) | LSR(A, 9-(C))) -#define ROL_16(A, C) MASK_OUT_ABOVE_16(LSL(A, C) | LSR(A, 16-(C))) -#define ROL_17(A, C) (LSL(A, C) | LSR(A, 17-(C))) -#define ROL_32(A, C) MASK_OUT_ABOVE_32(LSL_32(A, C) | LSR_32(A, 32-(C))) -#define ROL_33(A, C) (LSL_32(A, C) | LSR_32(A, 33-(C))) - -#define ROR_8(A, C) MASK_OUT_ABOVE_8(LSR(A, C) | LSL(A, 8-(C))) -#define ROR_9(A, C) (LSR(A, C) | LSL(A, 9-(C))) -#define ROR_16(A, C) MASK_OUT_ABOVE_16(LSR(A, C) | LSL(A, 16-(C))) -#define ROR_17(A, C) (LSR(A, C) | LSL(A, 17-(C))) -#define ROR_32(A, C) MASK_OUT_ABOVE_32(LSR_32(A, C) | LSL_32(A, 32-(C))) -#define ROR_33(A, C) (LSR_32(A, C) | LSL_32(A, 33-(C))) - - - -/* ------------------------------ CPU Access ------------------------------ */ - -/* Access the CPU registers */ -#define CPU_TYPE m68ki_cpu.cpu_type - -#define REG_DA m68ki_cpu.dar /* easy access to data and address regs */ -#define REG_DA_SAVE m68ki_cpu.dar_save -#define REG_D m68ki_cpu.dar -#define REG_A (m68ki_cpu.dar+8) -#define REG_PPC m68ki_cpu.ppc -#define REG_PC m68ki_cpu.pc -#define REG_SP_BASE m68ki_cpu.sp -#define REG_USP m68ki_cpu.sp[0] -#define REG_ISP m68ki_cpu.sp[4] -#define REG_MSP m68ki_cpu.sp[6] -#define REG_SP m68ki_cpu.dar[15] -#define REG_VBR m68ki_cpu.vbr -#define REG_SFC m68ki_cpu.sfc -#define REG_DFC m68ki_cpu.dfc -#define REG_CACR m68ki_cpu.cacr -#define REG_CAAR m68ki_cpu.caar -#define REG_IR m68ki_cpu.ir - -#define REG_FP m68ki_cpu.fpr -#define REG_FPCR m68ki_cpu.fpcr -#define REG_FPSR m68ki_cpu.fpsr -#define REG_FPIAR m68ki_cpu.fpiar - -#define FLAG_T1 m68ki_cpu.t1_flag -#define FLAG_T0 m68ki_cpu.t0_flag -#define FLAG_S m68ki_cpu.s_flag -#define FLAG_M m68ki_cpu.m_flag -#define FLAG_X m68ki_cpu.x_flag -#define FLAG_N m68ki_cpu.n_flag -#define FLAG_Z m68ki_cpu.not_z_flag -#define FLAG_V m68ki_cpu.v_flag -#define FLAG_C m68ki_cpu.c_flag -#define FLAG_INT_MASK m68ki_cpu.int_mask - -#define CPU_INT_LEVEL m68ki_cpu.int_level /* ASG: changed from CPU_INTS_PENDING */ -#define CPU_STOPPED m68ki_cpu.stopped -#define CPU_PREF_ADDR m68ki_cpu.pref_addr -#define CPU_PREF_DATA m68ki_cpu.pref_data -#define CPU_ADDRESS_MASK m68ki_cpu.address_mask -#define CPU_SR_MASK m68ki_cpu.sr_mask -#define CPU_INSTR_MODE m68ki_cpu.instr_mode -#define CPU_RUN_MODE m68ki_cpu.run_mode - -#define CYC_INSTRUCTION m68ki_cpu.cyc_instruction -#define CYC_EXCEPTION m68ki_cpu.cyc_exception -#define CYC_BCC_NOTAKE_B m68ki_cpu.cyc_bcc_notake_b -#define CYC_BCC_NOTAKE_W m68ki_cpu.cyc_bcc_notake_w -#define CYC_DBCC_F_NOEXP m68ki_cpu.cyc_dbcc_f_noexp -#define CYC_DBCC_F_EXP m68ki_cpu.cyc_dbcc_f_exp -#define CYC_SCC_R_TRUE m68ki_cpu.cyc_scc_r_true -#define CYC_MOVEM_W m68ki_cpu.cyc_movem_w -#define CYC_MOVEM_L m68ki_cpu.cyc_movem_l -#define CYC_SHIFT m68ki_cpu.cyc_shift -#define CYC_RESET m68ki_cpu.cyc_reset -#define HAS_PMMU m68ki_cpu.has_pmmu -#define PMMU_ENABLED m68ki_cpu.pmmu_enabled -#define RESET_CYCLES m68ki_cpu.reset_cycles - - -#define CALLBACK_INT_ACK m68ki_cpu.int_ack_callback -#define CALLBACK_BKPT_ACK m68ki_cpu.bkpt_ack_callback -#define CALLBACK_RESET_INSTR m68ki_cpu.reset_instr_callback -#define CALLBACK_CMPILD_INSTR m68ki_cpu.cmpild_instr_callback -#define CALLBACK_RTE_INSTR m68ki_cpu.rte_instr_callback -#define CALLBACK_TAS_INSTR m68ki_cpu.tas_instr_callback -#define CALLBACK_ILLG_INSTR m68ki_cpu.illg_instr_callback -#define CALLBACK_PC_CHANGED m68ki_cpu.pc_changed_callback -#define CALLBACK_SET_FC m68ki_cpu.set_fc_callback -#define CALLBACK_INSTR_HOOK m68ki_cpu.instr_hook_callback -/* CV */ -#define CALLBACK_ALINE_HOOK m68ki_cpu.aline_hook_callback - - - -/* ----------------------------- Configuration ---------------------------- */ - -/* These defines are dependant on the configuration defines in m68kconf.h */ - -/* Disable certain comparisons if we're not using all CPU types */ -#if M68K_EMULATE_040 -#define CPU_TYPE_IS_040_PLUS(A) ((A) & (CPU_TYPE_040 | CPU_TYPE_EC040)) - #define CPU_TYPE_IS_040_LESS(A) 1 -#else - #define CPU_TYPE_IS_040_PLUS(A) 0 - #define CPU_TYPE_IS_040_LESS(A) 1 -#endif - -#if M68K_EMULATE_030 -#define CPU_TYPE_IS_030_PLUS(A) ((A) & (CPU_TYPE_030 | CPU_TYPE_EC030 | CPU_TYPE_040 | CPU_TYPE_EC040)) -#define CPU_TYPE_IS_030_LESS(A) 1 -#else -#define CPU_TYPE_IS_030_PLUS(A) 0 -#define CPU_TYPE_IS_030_LESS(A) 1 -#endif - -#if M68K_EMULATE_020 -#define CPU_TYPE_IS_020_PLUS(A) ((A) & (CPU_TYPE_020 | CPU_TYPE_030 | CPU_TYPE_EC030 | CPU_TYPE_040 | CPU_TYPE_EC040)) - #define CPU_TYPE_IS_020_LESS(A) 1 -#else - #define CPU_TYPE_IS_020_PLUS(A) 0 - #define CPU_TYPE_IS_020_LESS(A) 1 -#endif - -#if M68K_EMULATE_EC020 -#define CPU_TYPE_IS_EC020_PLUS(A) ((A) & (CPU_TYPE_EC020 | CPU_TYPE_020 | CPU_TYPE_030 | CPU_TYPE_EC030 | CPU_TYPE_040 | CPU_TYPE_EC040)) - #define CPU_TYPE_IS_EC020_LESS(A) ((A) & (CPU_TYPE_000 | CPU_TYPE_010 | CPU_TYPE_EC020)) -#else - #define CPU_TYPE_IS_EC020_PLUS(A) CPU_TYPE_IS_020_PLUS(A) - #define CPU_TYPE_IS_EC020_LESS(A) CPU_TYPE_IS_020_LESS(A) -#endif - -#if M68K_EMULATE_010 - #define CPU_TYPE_IS_010(A) ((A) == CPU_TYPE_010) -#define CPU_TYPE_IS_010_PLUS(A) ((A) & (CPU_TYPE_010 | CPU_TYPE_EC020 | CPU_TYPE_020 | CPU_TYPE_EC030 | CPU_TYPE_030 | CPU_TYPE_040 | CPU_TYPE_EC040)) -#define CPU_TYPE_IS_010_LESS(A) ((A) & (CPU_TYPE_000 | CPU_TYPE_008 | CPU_TYPE_010)) -#else - #define CPU_TYPE_IS_010(A) 0 - #define CPU_TYPE_IS_010_PLUS(A) CPU_TYPE_IS_EC020_PLUS(A) - #define CPU_TYPE_IS_010_LESS(A) CPU_TYPE_IS_EC020_LESS(A) -#endif - -#if M68K_EMULATE_020 || M68K_EMULATE_EC020 - #define CPU_TYPE_IS_020_VARIANT(A) ((A) & (CPU_TYPE_EC020 | CPU_TYPE_020)) -#else - #define CPU_TYPE_IS_020_VARIANT(A) 0 -#endif - -#if M68K_EMULATE_040 || M68K_EMULATE_020 || M68K_EMULATE_EC020 || M68K_EMULATE_010 - #define CPU_TYPE_IS_000(A) ((A) == CPU_TYPE_000) -#else - #define CPU_TYPE_IS_000(A) 1 -#endif - - -#if !M68K_SEPARATE_READS -#define m68k_read_immediate_16(A) m68ki_read_program_16(A) -#define m68k_read_immediate_32(A) m68ki_read_program_32(A) - -#define m68k_read_pcrelative_8(A) m68ki_read_program_8(A) -#define m68k_read_pcrelative_16(A) m68ki_read_program_16(A) -#define m68k_read_pcrelative_32(A) m68ki_read_program_32(A) -#endif /* M68K_SEPARATE_READS */ - - -/* Enable or disable callback functions */ -#if M68K_EMULATE_INT_ACK - #if M68K_EMULATE_INT_ACK == OPT_SPECIFY_HANDLER - #define m68ki_int_ack(A) M68K_INT_ACK_CALLBACK(A) - #else - #define m68ki_int_ack(A) CALLBACK_INT_ACK(A) - #endif -#else - /* Default action is to used autovector mode, which is most common */ - #define m68ki_int_ack(A) M68K_INT_ACK_AUTOVECTOR -#endif /* M68K_EMULATE_INT_ACK */ - -#if M68K_EMULATE_BKPT_ACK - #if M68K_EMULATE_BKPT_ACK == OPT_SPECIFY_HANDLER - #define m68ki_bkpt_ack(A) M68K_BKPT_ACK_CALLBACK(A) - #else - #define m68ki_bkpt_ack(A) CALLBACK_BKPT_ACK(A) - #endif -#else - #define m68ki_bkpt_ack(A) -#endif /* M68K_EMULATE_BKPT_ACK */ - -#if M68K_EMULATE_RESET - #if M68K_EMULATE_RESET == OPT_SPECIFY_HANDLER - #define m68ki_output_reset() M68K_RESET_CALLBACK() - #else - #define m68ki_output_reset() CALLBACK_RESET_INSTR() - #endif -#else - #define m68ki_output_reset() -#endif /* M68K_EMULATE_RESET */ - -#if M68K_CMPILD_HAS_CALLBACK - #if M68K_CMPILD_HAS_CALLBACK == OPT_SPECIFY_HANDLER - #define m68ki_cmpild_callback(v,r) M68K_CMPILD_CALLBACK(v,r) - #else - #define m68ki_cmpild_callback(v,r) CALLBACK_CMPILD_INSTR(v,r) - #endif -#else - #define m68ki_cmpild_callback(v,r) -#endif /* M68K_CMPILD_HAS_CALLBACK */ - -#if M68K_RTE_HAS_CALLBACK - #if M68K_RTE_HAS_CALLBACK == OPT_SPECIFY_HANDLER - #define m68ki_rte_callback() M68K_RTE_CALLBACK() - #else - #define m68ki_rte_callback() CALLBACK_RTE_INSTR() - #endif -#else - #define m68ki_rte_callback() -#endif /* M68K_RTE_HAS_CALLBACK */ - -#if M68K_TAS_HAS_CALLBACK - #if M68K_TAS_HAS_CALLBACK == OPT_SPECIFY_HANDLER - #define m68ki_tas_callback() M68K_TAS_CALLBACK() - #else - #define m68ki_tas_callback() CALLBACK_TAS_INSTR() - #endif -#else - #define m68ki_tas_callback() 1 -#endif /* M68K_TAS_HAS_CALLBACK */ - -#if M68K_ILLG_HAS_CALLBACK - #if M68K_ILLG_HAS_CALLBACK == OPT_SPECIFY_HANDLER - #define m68ki_illg_callback(opcode) M68K_ILLG_CALLBACK(opcode) - #else - #define m68ki_illg_callback(opcode) CALLBACK_ILLG_INSTR(opcode) - #endif -#else - #define m68ki_illg_callback(opcode) 0 // Default is 0 = not handled, exception will occur -#endif /* M68K_ILLG_HAS_CALLBACK */ - -#if M68K_INSTRUCTION_HOOK - #if M68K_INSTRUCTION_HOOK == OPT_SPECIFY_HANDLER - #define m68ki_instr_hook(pc) M68K_INSTRUCTION_CALLBACK(pc) - #else - #define m68ki_instr_hook(pc) CALLBACK_INSTR_HOOK(pc) - #endif -#else - #define m68ki_instr_hook(pc) -#endif /* M68K_INSTRUCTION_HOOK */ - -#if M68K_MONITOR_PC - #if M68K_MONITOR_PC == OPT_SPECIFY_HANDLER - #define m68ki_pc_changed(A) M68K_SET_PC_CALLBACK(ADDRESS_68K(A)) - #else - #define m68ki_pc_changed(A) CALLBACK_PC_CHANGED(ADDRESS_68K(A)) - #endif -#else - #define m68ki_pc_changed(A) -#endif /* M68K_MONITOR_PC */ - - -/* Enable or disable function code emulation */ -#if M68K_EMULATE_FC - #if M68K_EMULATE_FC == OPT_SPECIFY_HANDLER - #define m68ki_set_fc(A) M68K_SET_FC_CALLBACK(A) - #else - #define m68ki_set_fc(A) CALLBACK_SET_FC(A) - #endif - #define m68ki_use_data_space() m68ki_address_space = FUNCTION_CODE_USER_DATA - #define m68ki_use_program_space() m68ki_address_space = FUNCTION_CODE_USER_PROGRAM - #define m68ki_get_address_space() m68ki_address_space -#else - #define m68ki_set_fc(A) - #define m68ki_use_data_space() - #define m68ki_use_program_space() - #define m68ki_get_address_space() FUNCTION_CODE_USER_DATA -#endif /* M68K_EMULATE_FC */ - - -/* Enable or disable trace emulation */ -#if M68K_EMULATE_TRACE - /* Initiates trace checking before each instruction (t1) */ - #define m68ki_trace_t1() m68ki_tracing = FLAG_T1 - /* adds t0 to trace checking if we encounter change of flow */ - #define m68ki_trace_t0() m68ki_tracing |= FLAG_T0 - /* Clear all tracing */ - #define m68ki_clear_trace() m68ki_tracing = 0 - /* Cause a trace exception if we are tracing */ - #define m68ki_exception_if_trace() if(m68ki_tracing) m68ki_exception_trace() -#else - #define m68ki_trace_t1() - #define m68ki_trace_t0() - #define m68ki_clear_trace() - #define m68ki_exception_if_trace() -#endif /* M68K_EMULATE_TRACE */ - - - -/* Address error */ -#if M68K_EMULATE_ADDRESS_ERROR - #include - -/* sigjmp() on Mac OS X and *BSD in general saves signal contexts and is super-slow, use sigsetjmp() to tell it not to */ -#ifdef _BSD_SETJMP_H -extern sigjmp_buf m68ki_aerr_trap; -#define m68ki_set_address_error_trap(m68k) \ - if(sigsetjmp(m68ki_aerr_trap, 0) != 0) \ - { \ - m68ki_exception_address_error(m68k); \ - if(CPU_STOPPED) \ - { \ - if (m68ki_remaining_cycles > 0) \ - m68ki_remaining_cycles = 0; \ - return m68ki_initial_cycles; \ - } \ - } - -#define m68ki_check_address_error(ADDR, WRITE_MODE, FC) \ - if((ADDR)&1) \ - { \ - m68ki_aerr_address = ADDR; \ - m68ki_aerr_write_mode = WRITE_MODE; \ - m68ki_aerr_fc = FC; \ - siglongjmp(m68ki_aerr_trap, 1); \ - } -#else -extern jmp_buf m68ki_aerr_trap; - #define m68ki_set_address_error_trap() \ - if(setjmp(m68ki_aerr_trap) != 0) \ - { \ - m68ki_exception_address_error(); \ - if(CPU_STOPPED) \ - { \ - SET_CYCLES(0); \ - return m68ki_initial_cycles; \ - } \ - /* ensure we don't re-enter execution loop after an - address error if there's no more cycles remaining */ \ - if(GET_CYCLES() <= 0) \ - { \ - /* return how many clocks we used */ \ - return m68ki_initial_cycles - GET_CYCLES(); \ - } \ - } - - #define m68ki_check_address_error(ADDR, WRITE_MODE, FC) \ - if((ADDR)&1) \ - { \ - m68ki_aerr_address = ADDR; \ - m68ki_aerr_write_mode = WRITE_MODE; \ - m68ki_aerr_fc = FC; \ - longjmp(m68ki_aerr_trap, 1); \ - } -#endif - - #define m68ki_check_address_error_010_less(ADDR, WRITE_MODE, FC) \ - if (CPU_TYPE_IS_010_LESS(CPU_TYPE)) \ - { \ - m68ki_check_address_error(ADDR, WRITE_MODE, FC) \ - } -#else - #define m68ki_set_address_error_trap() - #define m68ki_check_address_error(ADDR, WRITE_MODE, FC) - #define m68ki_check_address_error_010_less(ADDR, WRITE_MODE, FC) -#endif /* M68K_ADDRESS_ERROR */ - -/* Logging */ -#if M68K_LOG_ENABLE - #include - extern FILE* M68K_LOG_FILEHANDLE - extern const char *const m68ki_cpu_names[]; - - #define M68K_DO_LOG(A) if(M68K_LOG_FILEHANDLE) fprintf A - #if M68K_LOG_1010_1111 - #define M68K_DO_LOG_EMU(A) if(M68K_LOG_FILEHANDLE) fprintf A - #else - #define M68K_DO_LOG_EMU(A) - #endif -#else - #define M68K_DO_LOG(A) - #define M68K_DO_LOG_EMU(A) -#endif - -/* ---------- CV AddOn ---------- */ - -#if M68K_ALINE_HOOK - #if M68K_ALINE_HOOK == OPT_SPECIFY_HANDLER - #define m68ki_aline_hook() M68K_ALINE_CALLBACK() - #else - #define m68ki_aline_hook() CALLBACK_ALINE_HOOK() - #endif -#else - #define m68ki_aline_hook() M68K_ALINE_EXCEPT -#endif /* M68K_ALINE_HOOK */ - - - -/* -------------------------- EA / Operand Access ------------------------- */ - -/* - * The general instruction format follows this pattern: - * .... XXX. .... .YYY - * where XXX is register X and YYY is register Y - */ -/* Data Register Isolation */ -#define DX (REG_D[(REG_IR >> 9) & 7]) -#define DY (REG_D[REG_IR & 7]) -/* Address Register Isolation */ -#define AX (REG_A[(REG_IR >> 9) & 7]) -#define AY (REG_A[REG_IR & 7]) - - -/* Effective Address Calculations */ -#define EA_AY_AI_8() AY /* address register indirect */ -#define EA_AY_AI_16() EA_AY_AI_8() -#define EA_AY_AI_32() EA_AY_AI_8() -#define EA_AY_PI_8() (AY++) /* postincrement (size = byte) */ -#define EA_AY_PI_16() ((AY+=2)-2) /* postincrement (size = word) */ -#define EA_AY_PI_32() ((AY+=4)-4) /* postincrement (size = long) */ -#define EA_AY_PD_8() (--AY) /* predecrement (size = byte) */ -#define EA_AY_PD_16() (AY-=2) /* predecrement (size = word) */ -#define EA_AY_PD_32() (AY-=4) /* predecrement (size = long) */ -#define EA_AY_DI_8() (AY+MAKE_INT_16(m68ki_read_imm_16())) /* displacement */ -#define EA_AY_DI_16() EA_AY_DI_8() -#define EA_AY_DI_32() EA_AY_DI_8() -#define EA_AY_IX_8() m68ki_get_ea_ix(AY) /* indirect + index */ -#define EA_AY_IX_16() EA_AY_IX_8() -#define EA_AY_IX_32() EA_AY_IX_8() - -#define EA_AX_AI_8() AX -#define EA_AX_AI_16() EA_AX_AI_8() -#define EA_AX_AI_32() EA_AX_AI_8() -#define EA_AX_PI_8() (AX++) -#define EA_AX_PI_16() ((AX+=2)-2) -#define EA_AX_PI_32() ((AX+=4)-4) -#define EA_AX_PD_8() (--AX) -#define EA_AX_PD_16() (AX-=2) -#define EA_AX_PD_32() (AX-=4) -#define EA_AX_DI_8() (AX+MAKE_INT_16(m68ki_read_imm_16())) -#define EA_AX_DI_16() EA_AX_DI_8() -#define EA_AX_DI_32() EA_AX_DI_8() -#define EA_AX_IX_8() m68ki_get_ea_ix(AX) -#define EA_AX_IX_16() EA_AX_IX_8() -#define EA_AX_IX_32() EA_AX_IX_8() - -#define EA_A7_PI_8() ((REG_A[7]+=2)-2) -#define EA_A7_PD_8() (REG_A[7]-=2) - -#define EA_AW_8() MAKE_INT_16(m68ki_read_imm_16()) /* absolute word */ -#define EA_AW_16() EA_AW_8() -#define EA_AW_32() EA_AW_8() -#define EA_AL_8() m68ki_read_imm_32() /* absolute long */ -#define EA_AL_16() EA_AL_8() -#define EA_AL_32() EA_AL_8() -#define EA_PCDI_8() m68ki_get_ea_pcdi() /* pc indirect + displacement */ -#define EA_PCDI_16() EA_PCDI_8() -#define EA_PCDI_32() EA_PCDI_8() -#define EA_PCIX_8() m68ki_get_ea_pcix() /* pc indirect + index */ -#define EA_PCIX_16() EA_PCIX_8() -#define EA_PCIX_32() EA_PCIX_8() - - -#define OPER_I_8() m68ki_read_imm_8() -#define OPER_I_16() m68ki_read_imm_16() -#define OPER_I_32() m68ki_read_imm_32() - - - -/* --------------------------- Status Register ---------------------------- */ - -/* Flag Calculation Macros */ -#define CFLAG_8(A) (A) -#define CFLAG_16(A) ((A)>>8) - -#if M68K_INT_GT_32_BIT - #define CFLAG_ADD_32(S, D, R) ((R)>>24) - #define CFLAG_SUB_32(S, D, R) ((R)>>24) -#else - #define CFLAG_ADD_32(S, D, R) (((S & D) | (~R & (S | D)))>>23) - #define CFLAG_SUB_32(S, D, R) (((S & R) | (~D & (S | R)))>>23) -#endif /* M68K_INT_GT_32_BIT */ - -#define VFLAG_ADD_8(S, D, R) ((S^R) & (D^R)) -#define VFLAG_ADD_16(S, D, R) (((S^R) & (D^R))>>8) -#define VFLAG_ADD_32(S, D, R) (((S^R) & (D^R))>>24) - -#define VFLAG_SUB_8(S, D, R) ((S^D) & (R^D)) -#define VFLAG_SUB_16(S, D, R) (((S^D) & (R^D))>>8) -#define VFLAG_SUB_32(S, D, R) (((S^D) & (R^D))>>24) - -#define NFLAG_8(A) (A) -#define NFLAG_16(A) ((A)>>8) -#define NFLAG_32(A) ((A)>>24) -#define NFLAG_64(A) ((A)>>56) - -#define ZFLAG_8(A) MASK_OUT_ABOVE_8(A) -#define ZFLAG_16(A) MASK_OUT_ABOVE_16(A) -#define ZFLAG_32(A) MASK_OUT_ABOVE_32(A) - - -/* Flag values */ -#define NFLAG_SET 0x80 -#define NFLAG_CLEAR 0 -#define CFLAG_SET 0x100 -#define CFLAG_CLEAR 0 -#define XFLAG_SET 0x100 -#define XFLAG_CLEAR 0 -#define VFLAG_SET 0x80 -#define VFLAG_CLEAR 0 -#define ZFLAG_SET 0 -#define ZFLAG_CLEAR 0xffffffff - -#define SFLAG_SET 4 -#define SFLAG_CLEAR 0 -#define MFLAG_SET 2 -#define MFLAG_CLEAR 0 - -/* Turn flag values into 1 or 0 */ -#define XFLAG_AS_1() ((FLAG_X>>8)&1) -#define NFLAG_AS_1() ((FLAG_N>>7)&1) -#define VFLAG_AS_1() ((FLAG_V>>7)&1) -#define ZFLAG_AS_1() (!FLAG_Z) -#define CFLAG_AS_1() ((FLAG_C>>8)&1) - - -/* Conditions */ -#define COND_CS() (FLAG_C&0x100) -#define COND_CC() (!COND_CS()) -#define COND_VS() (FLAG_V&0x80) -#define COND_VC() (!COND_VS()) -#define COND_NE() FLAG_Z -#define COND_EQ() (!COND_NE()) -#define COND_MI() (FLAG_N&0x80) -#define COND_PL() (!COND_MI()) -#define COND_LT() ((FLAG_N^FLAG_V)&0x80) -#define COND_GE() (!COND_LT()) -#define COND_HI() (COND_CC() && COND_NE()) -#define COND_LS() (COND_CS() || COND_EQ()) -#define COND_GT() (COND_GE() && COND_NE()) -#define COND_LE() (COND_LT() || COND_EQ()) - -/* Reversed conditions */ -#define COND_NOT_CS() COND_CC() -#define COND_NOT_CC() COND_CS() -#define COND_NOT_VS() COND_VC() -#define COND_NOT_VC() COND_VS() -#define COND_NOT_NE() COND_EQ() -#define COND_NOT_EQ() COND_NE() -#define COND_NOT_MI() COND_PL() -#define COND_NOT_PL() COND_MI() -#define COND_NOT_LT() COND_GE() -#define COND_NOT_GE() COND_LT() -#define COND_NOT_HI() COND_LS() -#define COND_NOT_LS() COND_HI() -#define COND_NOT_GT() COND_LE() -#define COND_NOT_LE() COND_GT() - -/* Not real conditions, but here for convenience */ -#define COND_XS() (FLAG_X&0x100) -#define COND_XC() (!COND_XS) - - -/* Get the condition code register */ -#define m68ki_get_ccr() ((COND_XS() >> 4) | \ - (COND_MI() >> 4) | \ - (COND_EQ() << 2) | \ - (COND_VS() >> 6) | \ - (COND_CS() >> 8)) - -/* Get the status register */ -#define m68ki_get_sr() ( FLAG_T1 | \ - FLAG_T0 | \ - (FLAG_S << 11) | \ - (FLAG_M << 11) | \ - FLAG_INT_MASK | \ - m68ki_get_ccr()) - - - -/* ---------------------------- Cycle Counting ---------------------------- */ - -#define ADD_CYCLES(A) m68ki_remaining_cycles += (A) -#define USE_CYCLES(A) m68ki_remaining_cycles -= (A) -#define SET_CYCLES(A) m68ki_remaining_cycles = A -#define GET_CYCLES() m68ki_remaining_cycles -#define USE_ALL_CYCLES() m68ki_remaining_cycles %= CYC_INSTRUCTION[REG_IR] - - - -/* ----------------------------- Read / Write ----------------------------- */ - -/* Read from the current address space */ -#define m68ki_read_8(A) m68ki_read_8_fc (A, FLAG_S | m68ki_get_address_space()) -#define m68ki_read_16(A) m68ki_read_16_fc(A, FLAG_S | m68ki_get_address_space()) -#define m68ki_read_32(A) m68ki_read_32_fc(A, FLAG_S | m68ki_get_address_space()) - -/* Write to the current data space */ -#define m68ki_write_8(A, V) m68ki_write_8_fc (A, FLAG_S | FUNCTION_CODE_USER_DATA, V) -#define m68ki_write_16(A, V) m68ki_write_16_fc(A, FLAG_S | FUNCTION_CODE_USER_DATA, V) -#define m68ki_write_32(A, V) m68ki_write_32_fc(A, FLAG_S | FUNCTION_CODE_USER_DATA, V) - -#if M68K_SIMULATE_PD_WRITES -#define m68ki_write_32_pd(A, V) m68ki_write_32_pd_fc(A, FLAG_S | FUNCTION_CODE_USER_DATA, V) -#else -#define m68ki_write_32_pd(A, V) m68ki_write_32_fc(A, FLAG_S | FUNCTION_CODE_USER_DATA, V) -#endif - -/* Map PC-relative reads */ -#define m68ki_read_pcrel_8(A) m68k_read_pcrelative_8(A) -#define m68ki_read_pcrel_16(A) m68k_read_pcrelative_16(A) -#define m68ki_read_pcrel_32(A) m68k_read_pcrelative_32(A) - -/* Read from the program space */ -#define m68ki_read_program_8(A) m68ki_read_8_fc(A, FLAG_S | FUNCTION_CODE_USER_PROGRAM) -#define m68ki_read_program_16(A) m68ki_read_16_fc(A, FLAG_S | FUNCTION_CODE_USER_PROGRAM) -#define m68ki_read_program_32(A) m68ki_read_32_fc(A, FLAG_S | FUNCTION_CODE_USER_PROGRAM) - -/* Read from the data space */ -#define m68ki_read_data_8(A) m68ki_read_8_fc(A, FLAG_S | FUNCTION_CODE_USER_DATA) -#define m68ki_read_data_16(A) m68ki_read_16_fc(A, FLAG_S | FUNCTION_CODE_USER_DATA) -#define m68ki_read_data_32(A) m68ki_read_32_fc(A, FLAG_S | FUNCTION_CODE_USER_DATA) - - - -/* ======================================================================== */ -/* =============================== PROTOTYPES ============================= */ -/* ======================================================================== */ - -typedef union -{ - uint64 i; - double f; -} fp_reg; - -typedef struct -{ - uint cpu_type; /* CPU Type: 68000, 68008, 68010, 68EC020, 68020, 68EC030, 68030, 68EC040, or 68040 */ - uint dar[16]; /* Data and Address Registers */ - uint dar_save[16]; /* Saved Data and Address Registers (pushed onto the - stack when a bus error occurs)*/ - uint ppc; /* Previous program counter */ - uint pc; /* Program Counter */ - uint sp[7]; /* User, Interrupt, and Master Stack Pointers */ - uint vbr; /* Vector Base Register (m68010+) */ - uint sfc; /* Source Function Code Register (m68010+) */ - uint dfc; /* Destination Function Code Register (m68010+) */ - uint cacr; /* Cache Control Register (m68020, unemulated) */ - uint caar; /* Cache Address Register (m68020, unemulated) */ - uint ir; /* Instruction Register */ - floatx80 fpr[8]; /* FPU Data Register (m68030/040) */ - uint fpiar; /* FPU Instruction Address Register (m68040) */ - uint fpsr; /* FPU Status Register (m68040) */ - uint fpcr; /* FPU Control Register (m68040) */ - uint t1_flag; /* Trace 1 */ - uint t0_flag; /* Trace 0 */ - uint s_flag; /* Supervisor */ - uint m_flag; /* Master/Interrupt state */ - uint x_flag; /* Extend */ - uint n_flag; /* Negative */ - uint not_z_flag; /* Zero, inverted for speedups */ - uint v_flag; /* Overflow */ - uint c_flag; /* Carry */ - uint int_mask; /* I0-I2 */ - uint int_level; /* State of interrupt pins IPL0-IPL2 -- ASG: changed from ints_pending */ - uint stopped; /* Stopped state */ - uint pref_addr; /* Last prefetch address */ - uint pref_data; /* Data in the prefetch queue */ - uint address_mask; /* Available address pins */ - uint sr_mask; /* Implemented status register bits */ - uint instr_mode; /* Stores whether we are in instruction mode or group 0/1 exception mode */ - uint run_mode; /* Stores whether we are processing a reset, bus error, address error, or something else */ - int has_pmmu; /* Indicates if a PMMU available (yes on 030, 040, no on EC030) */ - int pmmu_enabled; /* Indicates if the PMMU is enabled */ - int fpu_just_reset; /* Indicates the FPU was just reset */ - uint reset_cycles; - - /* Clocks required for instructions / exceptions */ - uint cyc_bcc_notake_b; - uint cyc_bcc_notake_w; - uint cyc_dbcc_f_noexp; - uint cyc_dbcc_f_exp; - uint cyc_scc_r_true; - uint cyc_movem_w; - uint cyc_movem_l; - uint cyc_shift; - uint cyc_reset; - - /* Virtual IRQ lines state */ - uint virq_state; - uint nmi_pending; - - /* PMMU registers */ - uint mmu_crp_aptr, mmu_crp_limit; - uint mmu_srp_aptr, mmu_srp_limit; - uint mmu_tc; - uint16 mmu_sr; - - const uint8* cyc_instruction; - const uint8* cyc_exception; - - /* Callbacks to host */ - int (*int_ack_callback)(int int_line); /* Interrupt Acknowledge */ - void (*bkpt_ack_callback)(unsigned int data); /* Breakpoint Acknowledge */ - void (*reset_instr_callback)(void); /* Called when a RESET instruction is encountered */ - void (*cmpild_instr_callback)(unsigned int, int); /* Called when a CMPI.L #v, Dn instruction is encountered */ - void (*rte_instr_callback)(void); /* Called when a RTE instruction is encountered */ - int (*tas_instr_callback)(void); /* Called when a TAS instruction is encountered, allows / disallows writeback */ - int (*illg_instr_callback)(int); /* Called when an illegal instruction is encountered, allows handling */ - void (*pc_changed_callback)(unsigned int new_pc); /* Called when the PC changes by a large amount */ - void (*set_fc_callback)(unsigned int new_fc); /* Called when the CPU function code changes */ - void (*instr_hook_callback)(unsigned int pc); /* Called every instruction cycle prior to execution */ - int (*aline_hook_callback)(unsigned int opcode, unsigned int pc); /* CV: Called if invalid a-line opcode occurred */ -} m68ki_cpu_core; - - -extern m68ki_cpu_core m68ki_cpu; -extern sint m68ki_remaining_cycles; -extern uint m68ki_tracing; -extern const uint8 m68ki_shift_8_table[]; -extern const uint16 m68ki_shift_16_table[]; -extern const uint m68ki_shift_32_table[]; -extern const uint8 m68ki_exception_cycle_table[][256]; -extern uint m68ki_address_space; -extern const uint8 m68ki_ea_idx_cycle_table[]; - -extern uint m68ki_aerr_address; -extern uint m68ki_aerr_write_mode; -extern uint m68ki_aerr_fc; - -/* Forward declarations to keep some of the macros happy */ -static inline uint m68ki_read_16_fc (uint address, uint fc); -static inline uint m68ki_read_32_fc (uint address, uint fc); -static inline uint m68ki_get_ea_ix(uint An); -static inline void m68ki_check_interrupts(void); /* ASG: check for interrupts */ - -/* quick disassembly (used for logging) */ -char* m68ki_disassemble_quick(unsigned int pc, unsigned int cpu_type); - - -/* ======================================================================== */ -/* =========================== UTILITY FUNCTIONS ========================== */ -/* ======================================================================== */ - - -/* ---------------------------- Read Immediate ---------------------------- */ - -extern uint pmmu_translate_addr(uint addr_in); - -/* Handles all immediate reads, does address error check, function code setting, - * and prefetching if they are enabled in m68kconf.h - */ -static inline uint m68ki_read_imm_16(void) -{ - m68ki_set_fc(FLAG_S | FUNCTION_CODE_USER_PROGRAM); /* auto-disable (see m68kcpu.h) */ - m68ki_check_address_error(REG_PC, MODE_READ, FLAG_S | FUNCTION_CODE_USER_PROGRAM); /* auto-disable (see m68kcpu.h) */ - -#if M68K_SEPARATE_READS -#if M68K_EMULATE_PMMU - if (PMMU_ENABLED) - address = pmmu_translate_addr(address); -#endif -#endif - -#if M68K_EMULATE_PREFETCH -{ - uint result; - if(REG_PC != CPU_PREF_ADDR) - { - CPU_PREF_ADDR = REG_PC; - CPU_PREF_DATA = m68k_read_immediate_16(ADDRESS_68K(CPU_PREF_ADDR)); - } - result = MASK_OUT_ABOVE_16(CPU_PREF_DATA); - REG_PC += 2; - CPU_PREF_ADDR = REG_PC; - CPU_PREF_DATA = m68k_read_immediate_16(ADDRESS_68K(CPU_PREF_ADDR)); - return result; -} -#else - REG_PC += 2; - return m68k_read_immediate_16(ADDRESS_68K(REG_PC-2)); -#endif /* M68K_EMULATE_PREFETCH */ -} - -static inline uint m68ki_read_imm_8(void) -{ - /* map read immediate 8 to read immediate 16 */ - return MASK_OUT_ABOVE_8(m68ki_read_imm_16()); -} - -static inline uint m68ki_read_imm_32(void) -{ -#if M68K_SEPARATE_READS -#if M68K_EMULATE_PMMU - if (PMMU_ENABLED) - address = pmmu_translate_addr(address); -#endif -#endif - -#if M68K_EMULATE_PREFETCH - uint temp_val; - - m68ki_set_fc(FLAG_S | FUNCTION_CODE_USER_PROGRAM); /* auto-disable (see m68kcpu.h) */ - m68ki_check_address_error(REG_PC, MODE_READ, FLAG_S | FUNCTION_CODE_USER_PROGRAM); /* auto-disable (see m68kcpu.h) */ - - if(REG_PC != CPU_PREF_ADDR) - { - CPU_PREF_ADDR = REG_PC; - CPU_PREF_DATA = m68k_read_immediate_16(ADDRESS_68K(CPU_PREF_ADDR)); - } - temp_val = MASK_OUT_ABOVE_16(CPU_PREF_DATA); - REG_PC += 2; - CPU_PREF_ADDR = REG_PC; - CPU_PREF_DATA = m68k_read_immediate_16(ADDRESS_68K(CPU_PREF_ADDR)); - - temp_val = MASK_OUT_ABOVE_32((temp_val << 16) | MASK_OUT_ABOVE_16(CPU_PREF_DATA)); - REG_PC += 2; - CPU_PREF_ADDR = REG_PC; - CPU_PREF_DATA = m68k_read_immediate_16(ADDRESS_68K(CPU_PREF_ADDR)); - - return temp_val; -#else - m68ki_set_fc(FLAG_S | FUNCTION_CODE_USER_PROGRAM); /* auto-disable (see m68kcpu.h) */ - m68ki_check_address_error(REG_PC, MODE_READ, FLAG_S | FUNCTION_CODE_USER_PROGRAM); /* auto-disable (see m68kcpu.h) */ - REG_PC += 4; - return m68k_read_immediate_32(ADDRESS_68K(REG_PC-4)); -#endif /* M68K_EMULATE_PREFETCH */ -} - -/* ------------------------- Top level read/write ------------------------- */ - -/* Handles all memory accesses (except for immediate reads if they are - * configured to use separate functions in m68kconf.h). - * All memory accesses must go through these top level functions. - * These functions will also check for address error and set the function - * code if they are enabled in m68kconf.h. - */ -static inline uint m68ki_read_8_fc(uint address, uint fc) -{ - (void)fc; - m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */ - -#if M68K_EMULATE_PMMU - if (PMMU_ENABLED) - address = pmmu_translate_addr(address); -#endif - - return m68k_read_memory_8(ADDRESS_68K(address)); -} -static inline uint m68ki_read_16_fc(uint address, uint fc) -{ - (void)fc; - m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */ - m68ki_check_address_error_010_less(address, MODE_READ, fc); /* auto-disable (see m68kcpu.h) */ - -#if M68K_EMULATE_PMMU - if (PMMU_ENABLED) - address = pmmu_translate_addr(address); -#endif - - return m68k_read_memory_16(ADDRESS_68K(address)); -} -static inline uint m68ki_read_32_fc(uint address, uint fc) -{ - (void)fc; - m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */ - m68ki_check_address_error_010_less(address, MODE_READ, fc); /* auto-disable (see m68kcpu.h) */ - -#if M68K_EMULATE_PMMU - if (PMMU_ENABLED) - address = pmmu_translate_addr(address); -#endif - - return m68k_read_memory_32(ADDRESS_68K(address)); -} - -static inline void m68ki_write_8_fc(uint address, uint fc, uint value) -{ - (void)fc; - m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */ - -#if M68K_EMULATE_PMMU - if (PMMU_ENABLED) - address = pmmu_translate_addr(address); -#endif - - m68k_write_memory_8(ADDRESS_68K(address), value); -} -static inline void m68ki_write_16_fc(uint address, uint fc, uint value) -{ - (void)fc; - m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */ - m68ki_check_address_error_010_less(address, MODE_WRITE, fc); /* auto-disable (see m68kcpu.h) */ - -#if M68K_EMULATE_PMMU - if (PMMU_ENABLED) - address = pmmu_translate_addr(address); -#endif - - m68k_write_memory_16(ADDRESS_68K(address), value); -} -static inline void m68ki_write_32_fc(uint address, uint fc, uint value) -{ - (void)fc; - m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */ - m68ki_check_address_error_010_less(address, MODE_WRITE, fc); /* auto-disable (see m68kcpu.h) */ - -#if M68K_EMULATE_PMMU - if (PMMU_ENABLED) - address = pmmu_translate_addr(address); -#endif - - m68k_write_memory_32(ADDRESS_68K(address), value); -} - -#if M68K_SIMULATE_PD_WRITES -static inline void m68ki_write_32_pd_fc(uint address, uint fc, uint value) -{ - (void)fc; - m68ki_set_fc(fc); /* auto-disable (see m68kcpu.h) */ - m68ki_check_address_error_010_less(address, MODE_WRITE, fc); /* auto-disable (see m68kcpu.h) */ - -#if M68K_EMULATE_PMMU - if (PMMU_ENABLED) - address = pmmu_translate_addr(address); -#endif - - m68k_write_memory_32_pd(ADDRESS_68K(address), value); -} -#endif - -/* --------------------- Effective Address Calculation -------------------- */ - -/* The program counter relative addressing modes cause operands to be - * retrieved from program space, not data space. - */ -static inline uint m68ki_get_ea_pcdi(void) -{ - uint old_pc = REG_PC; - m68ki_use_program_space(); /* auto-disable */ - return old_pc + MAKE_INT_16(m68ki_read_imm_16()); -} - - -static inline uint m68ki_get_ea_pcix(void) -{ - m68ki_use_program_space(); /* auto-disable */ - return m68ki_get_ea_ix(REG_PC); -} - -/* Indexed addressing modes are encoded as follows: - * - * Base instruction format: - * F E D C B A 9 8 7 6 | 5 4 3 | 2 1 0 - * x x x x x x x x x x | 1 1 0 | BASE REGISTER (An) - * - * Base instruction format for destination EA in move instructions: - * F E D C | B A 9 | 8 7 6 | 5 4 3 2 1 0 - * x x x x | BASE REG | 1 1 0 | X X X X X X (An) - * - * Brief extension format: - * F | E D C | B | A 9 | 8 | 7 6 5 4 3 2 1 0 - * D/A | REGISTER | W/L | SCALE | 0 | DISPLACEMENT - * - * Full extension format: - * F E D C B A 9 8 7 6 5 4 3 2 1 0 - * D/A | REGISTER | W/L | SCALE | 1 | BS | IS | BD SIZE | 0 | I/IS - * BASE DISPLACEMENT (0, 16, 32 bit) (bd) - * OUTER DISPLACEMENT (0, 16, 32 bit) (od) - * - * D/A: 0 = Dn, 1 = An (Xn) - * W/L: 0 = W (sign extend), 1 = L (.SIZE) - * SCALE: 00=1, 01=2, 10=4, 11=8 (*SCALE) - * BS: 0=add base reg, 1=suppress base reg (An suppressed) - * IS: 0=add index, 1=suppress index (Xn suppressed) - * BD SIZE: 00=reserved, 01=NULL, 10=Word, 11=Long (size of bd) - * - * IS I/IS Operation - * 0 000 No Memory Indirect - * 0 001 indir prex with null outer - * 0 010 indir prex with word outer - * 0 011 indir prex with long outer - * 0 100 reserved - * 0 101 indir postx with null outer - * 0 110 indir postx with word outer - * 0 111 indir postx with long outer - * 1 000 no memory indirect - * 1 001 mem indir with null outer - * 1 010 mem indir with word outer - * 1 011 mem indir with long outer - * 1 100-111 reserved - */ -static inline uint m68ki_get_ea_ix(uint An) -{ - /* An = base register */ - uint extension = m68ki_read_imm_16(); - uint Xn = 0; /* Index register */ - uint bd = 0; /* Base Displacement */ - uint od = 0; /* Outer Displacement */ - - if(CPU_TYPE_IS_010_LESS(CPU_TYPE)) - { - /* Calculate index */ - Xn = REG_DA[extension>>12]; /* Xn */ - if(!BIT_B(extension)) /* W/L */ - Xn = MAKE_INT_16(Xn); - - /* Add base register and displacement and return */ - return An + Xn + MAKE_INT_8(extension); - } - - /* Brief extension format */ - if(!BIT_8(extension)) - { - /* Calculate index */ - Xn = REG_DA[extension>>12]; /* Xn */ - if(!BIT_B(extension)) /* W/L */ - Xn = MAKE_INT_16(Xn); - /* Add scale if proper CPU type */ - if(CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - Xn <<= (extension>>9) & 3; /* SCALE */ - - /* Add base register and displacement and return */ - return An + Xn + MAKE_INT_8(extension); - } - - /* Full extension format */ - - USE_CYCLES(m68ki_ea_idx_cycle_table[extension&0x3f]); - - /* Check if base register is present */ - if(BIT_7(extension)) /* BS */ - An = 0; /* An */ - - /* Check if index is present */ - if(!BIT_6(extension)) /* IS */ - { - Xn = REG_DA[extension>>12]; /* Xn */ - if(!BIT_B(extension)) /* W/L */ - Xn = MAKE_INT_16(Xn); - Xn <<= (extension>>9) & 3; /* SCALE */ - } - - /* Check if base displacement is present */ - if(BIT_5(extension)) /* BD SIZE */ - bd = BIT_4(extension) ? m68ki_read_imm_32() : (uint32)MAKE_INT_16(m68ki_read_imm_16()); - - /* If no indirect action, we are done */ - if(!(extension&7)) /* No Memory Indirect */ - return An + bd + Xn; - - /* Check if outer displacement is present */ - if(BIT_1(extension)) /* I/IS: od */ - od = BIT_0(extension) ? m68ki_read_imm_32() : (uint32)MAKE_INT_16(m68ki_read_imm_16()); - - /* Postindex */ - if(BIT_2(extension)) /* I/IS: 0 = preindex, 1 = postindex */ - return m68ki_read_32(An + bd) + Xn + od; - - /* Preindex */ - return m68ki_read_32(An + bd + Xn) + od; -} - - -/* Fetch operands */ -static inline uint OPER_AY_AI_8(void) {uint ea = EA_AY_AI_8(); return m68ki_read_8(ea); } -static inline uint OPER_AY_AI_16(void) {uint ea = EA_AY_AI_16(); return m68ki_read_16(ea);} -static inline uint OPER_AY_AI_32(void) {uint ea = EA_AY_AI_32(); return m68ki_read_32(ea);} -static inline uint OPER_AY_PI_8(void) {uint ea = EA_AY_PI_8(); return m68ki_read_8(ea); } -static inline uint OPER_AY_PI_16(void) {uint ea = EA_AY_PI_16(); return m68ki_read_16(ea);} -static inline uint OPER_AY_PI_32(void) {uint ea = EA_AY_PI_32(); return m68ki_read_32(ea);} -static inline uint OPER_AY_PD_8(void) {uint ea = EA_AY_PD_8(); return m68ki_read_8(ea); } -static inline uint OPER_AY_PD_16(void) {uint ea = EA_AY_PD_16(); return m68ki_read_16(ea);} -static inline uint OPER_AY_PD_32(void) {uint ea = EA_AY_PD_32(); return m68ki_read_32(ea);} -static inline uint OPER_AY_DI_8(void) {uint ea = EA_AY_DI_8(); return m68ki_read_8(ea); } -static inline uint OPER_AY_DI_16(void) {uint ea = EA_AY_DI_16(); return m68ki_read_16(ea);} -static inline uint OPER_AY_DI_32(void) {uint ea = EA_AY_DI_32(); return m68ki_read_32(ea);} -static inline uint OPER_AY_IX_8(void) {uint ea = EA_AY_IX_8(); return m68ki_read_8(ea); } -static inline uint OPER_AY_IX_16(void) {uint ea = EA_AY_IX_16(); return m68ki_read_16(ea);} -static inline uint OPER_AY_IX_32(void) {uint ea = EA_AY_IX_32(); return m68ki_read_32(ea);} - -static inline uint OPER_AX_AI_8(void) {uint ea = EA_AX_AI_8(); return m68ki_read_8(ea); } -static inline uint OPER_AX_AI_16(void) {uint ea = EA_AX_AI_16(); return m68ki_read_16(ea);} -static inline uint OPER_AX_AI_32(void) {uint ea = EA_AX_AI_32(); return m68ki_read_32(ea);} -static inline uint OPER_AX_PI_8(void) {uint ea = EA_AX_PI_8(); return m68ki_read_8(ea); } -static inline uint OPER_AX_PI_16(void) {uint ea = EA_AX_PI_16(); return m68ki_read_16(ea);} -static inline uint OPER_AX_PI_32(void) {uint ea = EA_AX_PI_32(); return m68ki_read_32(ea);} -static inline uint OPER_AX_PD_8(void) {uint ea = EA_AX_PD_8(); return m68ki_read_8(ea); } -static inline uint OPER_AX_PD_16(void) {uint ea = EA_AX_PD_16(); return m68ki_read_16(ea);} -static inline uint OPER_AX_PD_32(void) {uint ea = EA_AX_PD_32(); return m68ki_read_32(ea);} -static inline uint OPER_AX_DI_8(void) {uint ea = EA_AX_DI_8(); return m68ki_read_8(ea); } -static inline uint OPER_AX_DI_16(void) {uint ea = EA_AX_DI_16(); return m68ki_read_16(ea);} -static inline uint OPER_AX_DI_32(void) {uint ea = EA_AX_DI_32(); return m68ki_read_32(ea);} -static inline uint OPER_AX_IX_8(void) {uint ea = EA_AX_IX_8(); return m68ki_read_8(ea); } -static inline uint OPER_AX_IX_16(void) {uint ea = EA_AX_IX_16(); return m68ki_read_16(ea);} -static inline uint OPER_AX_IX_32(void) {uint ea = EA_AX_IX_32(); return m68ki_read_32(ea);} - -static inline uint OPER_A7_PI_8(void) {uint ea = EA_A7_PI_8(); return m68ki_read_8(ea); } -static inline uint OPER_A7_PD_8(void) {uint ea = EA_A7_PD_8(); return m68ki_read_8(ea); } - -static inline uint OPER_AW_8(void) {uint ea = EA_AW_8(); return m68ki_read_8(ea); } -static inline uint OPER_AW_16(void) {uint ea = EA_AW_16(); return m68ki_read_16(ea);} -static inline uint OPER_AW_32(void) {uint ea = EA_AW_32(); return m68ki_read_32(ea);} -static inline uint OPER_AL_8(void) {uint ea = EA_AL_8(); return m68ki_read_8(ea); } -static inline uint OPER_AL_16(void) {uint ea = EA_AL_16(); return m68ki_read_16(ea);} -static inline uint OPER_AL_32(void) {uint ea = EA_AL_32(); return m68ki_read_32(ea);} -static inline uint OPER_PCDI_8(void) {uint ea = EA_PCDI_8(); return m68ki_read_pcrel_8(ea); } -static inline uint OPER_PCDI_16(void) {uint ea = EA_PCDI_16(); return m68ki_read_pcrel_16(ea);} -static inline uint OPER_PCDI_32(void) {uint ea = EA_PCDI_32(); return m68ki_read_pcrel_32(ea);} -static inline uint OPER_PCIX_8(void) {uint ea = EA_PCIX_8(); return m68ki_read_pcrel_8(ea); } -static inline uint OPER_PCIX_16(void) {uint ea = EA_PCIX_16(); return m68ki_read_pcrel_16(ea);} -static inline uint OPER_PCIX_32(void) {uint ea = EA_PCIX_32(); return m68ki_read_pcrel_32(ea);} - - - -/* ---------------------------- Stack Functions --------------------------- */ - -/* Push/pull data from the stack */ -static inline void m68ki_push_16(uint value) -{ - REG_SP = MASK_OUT_ABOVE_32(REG_SP - 2); - m68ki_write_16(REG_SP, value); -} - -static inline void m68ki_push_32(uint value) -{ - REG_SP = MASK_OUT_ABOVE_32(REG_SP - 4); - m68ki_write_32(REG_SP, value); -} - -static inline uint m68ki_pull_16(void) -{ - REG_SP = MASK_OUT_ABOVE_32(REG_SP + 2); - return m68ki_read_16(REG_SP-2); -} - -static inline uint m68ki_pull_32(void) -{ - REG_SP = MASK_OUT_ABOVE_32(REG_SP + 4); - return m68ki_read_32(REG_SP-4); -} - - -/* Increment/decrement the stack as if doing a push/pull but - * don't do any memory access. - */ -static inline void m68ki_fake_push_16(void) -{ - REG_SP = MASK_OUT_ABOVE_32(REG_SP - 2); -} - -static inline void m68ki_fake_push_32(void) -{ - REG_SP = MASK_OUT_ABOVE_32(REG_SP - 4); -} - -static inline void m68ki_fake_pull_16(void) -{ - REG_SP = MASK_OUT_ABOVE_32(REG_SP + 2); -} - -static inline void m68ki_fake_pull_32(void) -{ - REG_SP = MASK_OUT_ABOVE_32(REG_SP + 4); -} - - -/* ----------------------------- Program Flow ----------------------------- */ - -/* Jump to a new program location or vector. - * These functions will also call the pc_changed callback if it was enabled - * in m68kconf.h. - */ -static inline void m68ki_jump(uint new_pc) -{ - REG_PC = new_pc; - m68ki_pc_changed(REG_PC); -} - -static inline void m68ki_jump_vector(uint vector) -{ - REG_PC = (vector<<2) + REG_VBR; - REG_PC = m68ki_read_data_32(REG_PC); - m68ki_pc_changed(REG_PC); -} - - -/* Branch to a new memory location. - * The 32-bit branch will call pc_changed if it was enabled in m68kconf.h. - * So far I've found no problems with not calling pc_changed for 8 or 16 - * bit branches. - */ -static inline void m68ki_branch_8(uint offset) -{ - REG_PC += MAKE_INT_8(offset); -} - -static inline void m68ki_branch_16(uint offset) -{ - REG_PC += MAKE_INT_16(offset); -} - -static inline void m68ki_branch_32(uint offset) -{ - REG_PC += offset; - m68ki_pc_changed(REG_PC); -} - -/* ---------------------------- Status Register --------------------------- */ - -/* Set the S flag and change the active stack pointer. - * Note that value MUST be 4 or 0. - */ -static inline void m68ki_set_s_flag(uint value) -{ - /* Backup the old stack pointer */ - REG_SP_BASE[FLAG_S | ((FLAG_S>>1) & FLAG_M)] = REG_SP; - /* Set the S flag */ - FLAG_S = value; - /* Set the new stack pointer */ - REG_SP = REG_SP_BASE[FLAG_S | ((FLAG_S>>1) & FLAG_M)]; -} - -/* Set the S and M flags and change the active stack pointer. - * Note that value MUST be 0, 2, 4, or 6 (bit2 = S, bit1 = M). - */ -static inline void m68ki_set_sm_flag(uint value) -{ - /* Backup the old stack pointer */ - REG_SP_BASE[FLAG_S | ((FLAG_S>>1) & FLAG_M)] = REG_SP; - /* Set the S and M flags */ - FLAG_S = value & SFLAG_SET; - FLAG_M = value & MFLAG_SET; - /* Set the new stack pointer */ - REG_SP = REG_SP_BASE[FLAG_S | ((FLAG_S>>1) & FLAG_M)]; -} - -/* Set the S and M flags. Don't touch the stack pointer. */ -static inline void m68ki_set_sm_flag_nosp(uint value) -{ - /* Set the S and M flags */ - FLAG_S = value & SFLAG_SET; - FLAG_M = value & MFLAG_SET; -} - - -/* Set the condition code register */ -static inline void m68ki_set_ccr(uint value) -{ - FLAG_X = BIT_4(value) << 4; - FLAG_N = BIT_3(value) << 4; - FLAG_Z = !BIT_2(value); - FLAG_V = BIT_1(value) << 6; - FLAG_C = BIT_0(value) << 8; -} - -/* Set the status register but don't check for interrupts */ -static inline void m68ki_set_sr_noint(uint value) -{ - /* Mask out the "unimplemented" bits */ - value &= CPU_SR_MASK; - - /* Now set the status register */ - FLAG_T1 = BIT_F(value); - FLAG_T0 = BIT_E(value); - FLAG_INT_MASK = value & 0x0700; - m68ki_set_ccr(value); - m68ki_set_sm_flag((value >> 11) & 6); -} - -/* Set the status register but don't check for interrupts nor - * change the stack pointer - */ -static inline void m68ki_set_sr_noint_nosp(uint value) -{ - /* Mask out the "unimplemented" bits */ - value &= CPU_SR_MASK; - - /* Now set the status register */ - FLAG_T1 = BIT_F(value); - FLAG_T0 = BIT_E(value); - FLAG_INT_MASK = value & 0x0700; - m68ki_set_ccr(value); - m68ki_set_sm_flag_nosp((value >> 11) & 6); -} - -/* Set the status register and check for interrupts */ -static inline void m68ki_set_sr(uint value) -{ - m68ki_set_sr_noint(value); - m68ki_check_interrupts(); -} - - -/* ------------------------- Exception Processing ------------------------- */ - -/* Initiate exception processing */ -static inline uint m68ki_init_exception(void) -{ - /* Save the old status register */ - uint sr = m68ki_get_sr(); - - /* Turn off trace flag, clear pending traces */ - FLAG_T1 = FLAG_T0 = 0; - m68ki_clear_trace(); - /* Enter supervisor mode */ - m68ki_set_s_flag(SFLAG_SET); - - return sr; -} - -/* 3 word stack frame (68000 only) */ -static inline void m68ki_stack_frame_3word(uint pc, uint sr) -{ - m68ki_push_32(pc); - m68ki_push_16(sr); -} - -/* Format 0 stack frame. - * This is the standard stack frame for 68010+. - */ -static inline void m68ki_stack_frame_0000(uint pc, uint sr, uint vector) -{ - /* Stack a 3-word frame if we are 68000 */ - if(CPU_TYPE == CPU_TYPE_000) - { - m68ki_stack_frame_3word(pc, sr); - return; - } - m68ki_push_16(vector<<2); - m68ki_push_32(pc); - m68ki_push_16(sr); -} - -/* Format 1 stack frame (68020). - * For 68020, this is the 4 word throwaway frame. - */ -static inline void m68ki_stack_frame_0001(uint pc, uint sr, uint vector) -{ - m68ki_push_16(0x1000 | (vector<<2)); - m68ki_push_32(pc); - m68ki_push_16(sr); -} - -/* Format 2 stack frame. - * This is used only by 68020 for trap exceptions. - */ -static inline void m68ki_stack_frame_0010(uint sr, uint vector) -{ - m68ki_push_32(REG_PPC); - m68ki_push_16(0x2000 | (vector<<2)); - m68ki_push_32(REG_PC); - m68ki_push_16(sr); -} - - -/* Bus error stack frame (68000 only). - */ -static inline void m68ki_stack_frame_buserr(uint sr) -{ - m68ki_push_32(REG_PC); - m68ki_push_16(sr); - m68ki_push_16(REG_IR); - m68ki_push_32(m68ki_aerr_address); /* access address */ - /* 0 0 0 0 0 0 0 0 0 0 0 R/W I/N FC - * R/W 0 = write, 1 = read - * I/N 0 = instruction, 1 = not - * FC 3-bit function code - */ - m68ki_push_16(m68ki_aerr_write_mode | CPU_INSTR_MODE | m68ki_aerr_fc); -} - -/* Format 8 stack frame (68010). - * 68010 only. This is the 29 word bus/address error frame. - */ -static inline void m68ki_stack_frame_1000(uint pc, uint sr, uint vector) -{ - /* VERSION - * NUMBER - * INTERNAL INFORMATION, 16 WORDS - */ - m68ki_fake_push_32(); - m68ki_fake_push_32(); - m68ki_fake_push_32(); - m68ki_fake_push_32(); - m68ki_fake_push_32(); - m68ki_fake_push_32(); - m68ki_fake_push_32(); - m68ki_fake_push_32(); - - /* INSTRUCTION INPUT BUFFER */ - m68ki_push_16(0); - - /* UNUSED, RESERVED (not written) */ - m68ki_fake_push_16(); - - /* DATA INPUT BUFFER */ - m68ki_push_16(0); - - /* UNUSED, RESERVED (not written) */ - m68ki_fake_push_16(); - - /* DATA OUTPUT BUFFER */ - m68ki_push_16(0); - - /* UNUSED, RESERVED (not written) */ - m68ki_fake_push_16(); - - /* FAULT ADDRESS */ - m68ki_push_32(0); - - /* SPECIAL STATUS WORD */ - m68ki_push_16(0); - - /* 1000, VECTOR OFFSET */ - m68ki_push_16(0x8000 | (vector<<2)); - - /* PROGRAM COUNTER */ - m68ki_push_32(pc); - - /* STATUS REGISTER */ - m68ki_push_16(sr); -} - -/* Format A stack frame (short bus fault). - * This is used only by 68020 for bus fault and address error - * if the error happens at an instruction boundary. - * PC stacked is address of next instruction. - */ -static inline void m68ki_stack_frame_1010(uint sr, uint vector, uint pc) -{ - /* INTERNAL REGISTER */ - m68ki_push_16(0); - - /* INTERNAL REGISTER */ - m68ki_push_16(0); - - /* DATA OUTPUT BUFFER (2 words) */ - m68ki_push_32(0); - - /* INTERNAL REGISTER */ - m68ki_push_16(0); - - /* INTERNAL REGISTER */ - m68ki_push_16(0); - - /* DATA CYCLE FAULT ADDRESS (2 words) */ - m68ki_push_32(0); - - /* INSTRUCTION PIPE STAGE B */ - m68ki_push_16(0); - - /* INSTRUCTION PIPE STAGE C */ - m68ki_push_16(0); - - /* SPECIAL STATUS REGISTER */ - m68ki_push_16(0); - - /* INTERNAL REGISTER */ - m68ki_push_16(0); - - /* 1010, VECTOR OFFSET */ - m68ki_push_16(0xa000 | (vector<<2)); - - /* PROGRAM COUNTER */ - m68ki_push_32(pc); - - /* STATUS REGISTER */ - m68ki_push_16(sr); -} - -/* Format B stack frame (long bus fault). - * This is used only by 68020 for bus fault and address error - * if the error happens during instruction execution. - * PC stacked is address of instruction in progress. - */ -static inline void m68ki_stack_frame_1011(uint sr, uint vector, uint pc) -{ - /* INTERNAL REGISTERS (18 words) */ - m68ki_push_32(0); - m68ki_push_32(0); - m68ki_push_32(0); - m68ki_push_32(0); - m68ki_push_32(0); - m68ki_push_32(0); - m68ki_push_32(0); - m68ki_push_32(0); - m68ki_push_32(0); - - /* VERSION# (4 bits), INTERNAL INFORMATION */ - m68ki_push_16(0); - - /* INTERNAL REGISTERS (3 words) */ - m68ki_push_32(0); - m68ki_push_16(0); - - /* DATA INTPUT BUFFER (2 words) */ - m68ki_push_32(0); - - /* INTERNAL REGISTERS (2 words) */ - m68ki_push_32(0); - - /* STAGE B ADDRESS (2 words) */ - m68ki_push_32(0); - - /* INTERNAL REGISTER (4 words) */ - m68ki_push_32(0); - m68ki_push_32(0); - - /* DATA OUTPUT BUFFER (2 words) */ - m68ki_push_32(0); - - /* INTERNAL REGISTER */ - m68ki_push_16(0); - - /* INTERNAL REGISTER */ - m68ki_push_16(0); - - /* DATA CYCLE FAULT ADDRESS (2 words) */ - m68ki_push_32(0); - - /* INSTRUCTION PIPE STAGE B */ - m68ki_push_16(0); - - /* INSTRUCTION PIPE STAGE C */ - m68ki_push_16(0); - - /* SPECIAL STATUS REGISTER */ - m68ki_push_16(0); - - /* INTERNAL REGISTER */ - m68ki_push_16(0); - - /* 1011, VECTOR OFFSET */ - m68ki_push_16(0xb000 | (vector<<2)); - - /* PROGRAM COUNTER */ - m68ki_push_32(pc); - - /* STATUS REGISTER */ - m68ki_push_16(sr); -} - - -/* Used for Group 2 exceptions. - * These stack a type 2 frame on the 020. - */ -static inline void m68ki_exception_trap(uint vector) -{ - uint sr = m68ki_init_exception(); - - if(CPU_TYPE_IS_010_LESS(CPU_TYPE)) - m68ki_stack_frame_0000(REG_PC, sr, vector); - else - m68ki_stack_frame_0010(sr, vector); - - m68ki_jump_vector(vector); - - /* Use up some clock cycles and undo the instruction's cycles */ - USE_CYCLES(CYC_EXCEPTION[vector] - CYC_INSTRUCTION[REG_IR]); -} - -/* Trap#n stacks a 0 frame but behaves like group2 otherwise */ -static inline void m68ki_exception_trapN(uint vector) -{ - uint sr = m68ki_init_exception(); - m68ki_stack_frame_0000(REG_PC, sr, vector); - m68ki_jump_vector(vector); - - /* Use up some clock cycles and undo the instruction's cycles */ - USE_CYCLES(CYC_EXCEPTION[vector] - CYC_INSTRUCTION[REG_IR]); -} - -/* Exception for trace mode */ -static inline void m68ki_exception_trace(void) -{ - uint sr = m68ki_init_exception(); - - if(CPU_TYPE_IS_010_LESS(CPU_TYPE)) - { - #if M68K_EMULATE_ADDRESS_ERROR == OPT_ON - if(CPU_TYPE_IS_000(CPU_TYPE)) - { - CPU_INSTR_MODE = INSTRUCTION_NO; - } - #endif /* M68K_EMULATE_ADDRESS_ERROR */ - m68ki_stack_frame_0000(REG_PC, sr, EXCEPTION_TRACE); - } - else - m68ki_stack_frame_0010(sr, EXCEPTION_TRACE); - - m68ki_jump_vector(EXCEPTION_TRACE); - - /* Trace nullifies a STOP instruction */ - CPU_STOPPED &= ~STOP_LEVEL_STOP; - - /* Use up some clock cycles */ - USE_CYCLES(CYC_EXCEPTION[EXCEPTION_TRACE]); -} - -/* Exception for privilege violation */ -static inline void m68ki_exception_privilege_violation(void) -{ - uint sr = m68ki_init_exception(); - - #if M68K_EMULATE_ADDRESS_ERROR == OPT_ON - if(CPU_TYPE_IS_000(CPU_TYPE)) - { - CPU_INSTR_MODE = INSTRUCTION_NO; - } - #endif /* M68K_EMULATE_ADDRESS_ERROR */ - - m68ki_stack_frame_0000(REG_PPC, sr, EXCEPTION_PRIVILEGE_VIOLATION); - m68ki_jump_vector(EXCEPTION_PRIVILEGE_VIOLATION); - - /* Use up some clock cycles and undo the instruction's cycles */ - USE_CYCLES(CYC_EXCEPTION[EXCEPTION_PRIVILEGE_VIOLATION] - CYC_INSTRUCTION[REG_IR]); -} - -extern jmp_buf m68ki_bus_error_jmp_buf; - -#define m68ki_check_bus_error_trap() setjmp(m68ki_bus_error_jmp_buf) - -/* Exception for bus error */ -static inline void m68ki_exception_bus_error(void) -{ - int i; - - /* If we were processing a bus error, address error, or reset, - * while writing the stack frame, this is a catastrophic failure. - * Halt the CPU - */ - if(CPU_RUN_MODE == RUN_MODE_BERR_AERR_RESET_WSF) - { - m68k_read_memory_8(0x00ffff01); - CPU_STOPPED = STOP_LEVEL_HALT; - return; - } - CPU_RUN_MODE = RUN_MODE_BERR_AERR_RESET_WSF; - - /* Use up some clock cycles and undo the instruction's cycles */ - USE_CYCLES(CYC_EXCEPTION[EXCEPTION_BUS_ERROR] - CYC_INSTRUCTION[REG_IR]); - - for (i = 15; i >= 0; i--){ - REG_DA[i] = REG_DA_SAVE[i]; - } - - uint sr = m68ki_init_exception(); - - /* Note: This is implemented for 68010 only! */ - m68ki_stack_frame_1000(REG_PPC, sr, EXCEPTION_BUS_ERROR); - - m68ki_jump_vector(EXCEPTION_BUS_ERROR); - - CPU_RUN_MODE = RUN_MODE_BERR_AERR_RESET; - - longjmp(m68ki_bus_error_jmp_buf, 1); -} - -extern int cpu_log_enabled; - -/* Exception for A-Line instructions */ -static inline void m68ki_exception_1010(void) -{ -#if M68K_ALINE_HOOK - int res = CALLBACK_ALINE_HOOK(REG_IR,ADDRESS_68K(REG_PPC)); - if(res == M68K_ALINE_EXCEPT) { -#endif - uint sr; -#if M68K_LOG_1010_1111 == OPT_ON - M68K_DO_LOG_EMU((M68K_LOG_FILEHANDLE "%s at %08x: called 1010 instruction %04x (%s)\n", - m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PPC), REG_IR, - m68ki_disassemble_quick(ADDRESS_68K(REG_PPC)))); -#endif - - sr = m68ki_init_exception(); - m68ki_stack_frame_0000(REG_PPC, sr, EXCEPTION_1010); - m68ki_jump_vector(EXCEPTION_1010); - - /* Use up some clock cycles and undo the instruction's cycles */ - USE_CYCLES(CYC_EXCEPTION[EXCEPTION_1010] - CYC_INSTRUCTION[REG_IR]); -#if M68K_ALINE_HOOK - } else if(res == M68K_ALINE_RTS) { - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - m68ki_jump(m68ki_pull_32()); - } -#endif -} - -/* Exception for F-Line instructions */ -static inline void m68ki_exception_1111(void) -{ - uint sr; - -#if M68K_LOG_1010_1111 == OPT_ON - M68K_DO_LOG_EMU((M68K_LOG_FILEHANDLE "%s at %08x: called 1111 instruction %04x (%s)\n", - m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PPC), REG_IR, - m68ki_disassemble_quick(ADDRESS_68K(REG_PPC)))); -#endif - - sr = m68ki_init_exception(); - m68ki_stack_frame_0000(REG_PPC, sr, EXCEPTION_1111); - m68ki_jump_vector(EXCEPTION_1111); - - /* Use up some clock cycles and undo the instruction's cycles */ - USE_CYCLES(CYC_EXCEPTION[EXCEPTION_1111] - CYC_INSTRUCTION[REG_IR]); -} - -#if M68K_ILLG_HAS_CALLBACK == OPT_SPECIFY_HANDLER -extern int m68ki_illg_callback(int); -#endif - -/* Exception for illegal instructions */ -static inline void m68ki_exception_illegal(void) -{ - uint sr; - - M68K_DO_LOG((M68K_LOG_FILEHANDLE "%s at %08x: illegal instruction %04x (%s)\n", - m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PPC), REG_IR, - m68ki_disassemble_quick(ADDRESS_68K(REG_PPC)))); - if (m68ki_illg_callback(REG_IR)) - return; - - sr = m68ki_init_exception(); - - #if M68K_EMULATE_ADDRESS_ERROR == OPT_ON - if(CPU_TYPE_IS_000(CPU_TYPE)) - { - CPU_INSTR_MODE = INSTRUCTION_NO; - } - #endif /* M68K_EMULATE_ADDRESS_ERROR */ - - m68ki_stack_frame_0000(REG_PPC, sr, EXCEPTION_ILLEGAL_INSTRUCTION); - m68ki_jump_vector(EXCEPTION_ILLEGAL_INSTRUCTION); - - /* Use up some clock cycles and undo the instruction's cycles */ - USE_CYCLES(CYC_EXCEPTION[EXCEPTION_ILLEGAL_INSTRUCTION] - CYC_INSTRUCTION[REG_IR]); -} - -/* Exception for format errror in RTE */ -static inline void m68ki_exception_format_error(void) -{ - uint sr = m68ki_init_exception(); - m68ki_stack_frame_0000(REG_PC, sr, EXCEPTION_FORMAT_ERROR); - m68ki_jump_vector(EXCEPTION_FORMAT_ERROR); - - /* Use up some clock cycles and undo the instruction's cycles */ - USE_CYCLES(CYC_EXCEPTION[EXCEPTION_FORMAT_ERROR] - CYC_INSTRUCTION[REG_IR]); -} - -/* Exception for address error */ -static inline void m68ki_exception_address_error(void) -{ - uint sr = m68ki_init_exception(); - - /* If we were processing a bus error, address error, or reset, - * while writing the stack frame, this is a catastrophic failure. - * Halt the CPU - */ - if(CPU_RUN_MODE == RUN_MODE_BERR_AERR_RESET_WSF) - { - m68k_read_memory_8(0x00ffff01); - CPU_STOPPED = STOP_LEVEL_HALT; - return; - } - CPU_RUN_MODE = RUN_MODE_BERR_AERR_RESET_WSF; - - /* Note: This is implemented for 68000 only! */ - m68ki_stack_frame_buserr(sr); - - m68ki_jump_vector(EXCEPTION_ADDRESS_ERROR); - - CPU_RUN_MODE = RUN_MODE_BERR_AERR_RESET; - - /* Use up some clock cycles. Note that we don't need to undo the - instruction's cycles here as we've longjmp:ed directly from the - instruction handler without passing the part of the excecute loop - that deducts instruction cycles */ - USE_CYCLES(CYC_EXCEPTION[EXCEPTION_ADDRESS_ERROR]); -} - - -/* Service an interrupt request and start exception processing */ -static inline void m68ki_exception_interrupt(uint int_level) -{ - uint vector; - uint sr; - uint new_pc; - - #if M68K_EMULATE_ADDRESS_ERROR == OPT_ON - if(CPU_TYPE_IS_000(CPU_TYPE)) - { - CPU_INSTR_MODE = INSTRUCTION_NO; - } - #endif /* M68K_EMULATE_ADDRESS_ERROR */ - - /* Turn off the stopped state */ - CPU_STOPPED &= ~STOP_LEVEL_STOP; - - /* If we are halted, don't do anything */ - if(CPU_STOPPED) - return; - - /* Acknowledge the interrupt */ - vector = m68ki_int_ack(int_level); - - /* Get the interrupt vector */ - if(vector == M68K_INT_ACK_AUTOVECTOR) - /* Use the autovectors. This is the most commonly used implementation */ - vector = EXCEPTION_INTERRUPT_AUTOVECTOR+int_level; - else if(vector == M68K_INT_ACK_SPURIOUS) - /* Called if no devices respond to the interrupt acknowledge */ - vector = EXCEPTION_SPURIOUS_INTERRUPT; - else if(vector > 255) - { - M68K_DO_LOG_EMU((M68K_LOG_FILEHANDLE "%s at %08x: Interrupt acknowledge returned invalid vector $%x\n", - m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PC), vector)); - return; - } - - /* Start exception processing */ - sr = m68ki_init_exception(); - - /* Set the interrupt mask to the level of the one being serviced */ - FLAG_INT_MASK = int_level<<8; - - /* Get the new PC */ - new_pc = m68ki_read_data_32((vector<<2) + REG_VBR); - - /* If vector is uninitialized, call the uninitialized interrupt vector */ - if(new_pc == 0) - new_pc = m68ki_read_data_32((EXCEPTION_UNINITIALIZED_INTERRUPT<<2) + REG_VBR); - - /* Generate a stack frame */ - m68ki_stack_frame_0000(REG_PC, sr, vector); - if(FLAG_M && CPU_TYPE_IS_EC020_PLUS(CPU_TYPE)) - { - /* Create throwaway frame */ - m68ki_set_sm_flag(FLAG_S); /* clear M */ - sr |= 0x2000; /* Same as SR in master stack frame except S is forced high */ - m68ki_stack_frame_0001(REG_PC, sr, vector); - } - - m68ki_jump(new_pc); - - /* Defer cycle counting until later */ - USE_CYCLES(CYC_EXCEPTION[vector]); - -#if !M68K_EMULATE_INT_ACK - /* Automatically clear IRQ if we are not using an acknowledge scheme */ - CPU_INT_LEVEL = 0; -#endif /* M68K_EMULATE_INT_ACK */ -} - - -/* ASG: Check for interrupts */ -static inline void m68ki_check_interrupts(void) -{ - if(m68ki_cpu.nmi_pending) - { - m68ki_cpu.nmi_pending = FALSE; - m68ki_exception_interrupt(7); - } - else if(CPU_INT_LEVEL > FLAG_INT_MASK) - m68ki_exception_interrupt(CPU_INT_LEVEL>>8); -} - - - -/* ======================================================================== */ -/* ============================== END OF FILE ============================= */ -/* ======================================================================== */ - -#ifdef __cplusplus -} -#endif - -#endif /* M68KCPU__HEADER */ diff --git a/machine/musashi/m68kdasm.c b/machine/musashi/m68kdasm.c deleted file mode 100644 index 5671770..0000000 --- a/machine/musashi/m68kdasm.c +++ /dev/null @@ -1,4004 +0,0 @@ -/* ======================================================================== */ -/* ========================= LICENSING & COPYRIGHT ======================== */ -/* ======================================================================== */ -/* - * MUSASHI - * Version 3.32 - * - * A portable Motorola M680x0 processor emulation engine. - * Copyright Karl Stenerud. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - - - -/* ======================================================================== */ -/* ================================ INCLUDES ============================== */ -/* ======================================================================== */ - -#include -#include -#include -#include "m68k.h" - -#ifndef uint32 -#define uint32 uint -#endif - -#ifndef uint16 -#define uint16 unsigned short -#endif - -#ifndef DECL_SPEC -#define DECL_SPEC -#endif - -/* ======================================================================== */ -/* ============================ GENERAL DEFINES =========================== */ -/* ======================================================================== */ - -/* unsigned int and int must be at least 32 bits wide */ -#undef uint -#define uint unsigned int - -/* Bit Isolation Functions */ -#define BIT_0(A) ((A) & 0x00000001) -#define BIT_1(A) ((A) & 0x00000002) -#define BIT_2(A) ((A) & 0x00000004) -#define BIT_3(A) ((A) & 0x00000008) -#define BIT_4(A) ((A) & 0x00000010) -#define BIT_5(A) ((A) & 0x00000020) -#define BIT_6(A) ((A) & 0x00000040) -#define BIT_7(A) ((A) & 0x00000080) -#define BIT_8(A) ((A) & 0x00000100) -#define BIT_9(A) ((A) & 0x00000200) -#define BIT_A(A) ((A) & 0x00000400) -#define BIT_B(A) ((A) & 0x00000800) -#define BIT_C(A) ((A) & 0x00001000) -#define BIT_D(A) ((A) & 0x00002000) -#define BIT_E(A) ((A) & 0x00004000) -#define BIT_F(A) ((A) & 0x00008000) -#define BIT_10(A) ((A) & 0x00010000) -#define BIT_11(A) ((A) & 0x00020000) -#define BIT_12(A) ((A) & 0x00040000) -#define BIT_13(A) ((A) & 0x00080000) -#define BIT_14(A) ((A) & 0x00100000) -#define BIT_15(A) ((A) & 0x00200000) -#define BIT_16(A) ((A) & 0x00400000) -#define BIT_17(A) ((A) & 0x00800000) -#define BIT_18(A) ((A) & 0x01000000) -#define BIT_19(A) ((A) & 0x02000000) -#define BIT_1A(A) ((A) & 0x04000000) -#define BIT_1B(A) ((A) & 0x08000000) -#define BIT_1C(A) ((A) & 0x10000000) -#define BIT_1D(A) ((A) & 0x20000000) -#define BIT_1E(A) ((A) & 0x40000000) -#define BIT_1F(A) ((A) & 0x80000000) - -/* These are the CPU types understood by this disassembler */ -#define TYPE_68000 1 -#define TYPE_68010 2 -#define TYPE_68020 4 -#define TYPE_68030 8 -#define TYPE_68040 16 - -#define M68000_ONLY TYPE_68000 - -#define M68010_ONLY TYPE_68010 -#define M68010_LESS (TYPE_68000 | TYPE_68010) -#define M68010_PLUS (TYPE_68010 | TYPE_68020 | TYPE_68030 | TYPE_68040) - -#define M68020_ONLY TYPE_68020 -#define M68020_LESS (TYPE_68010 | TYPE_68020) -#define M68020_PLUS (TYPE_68020 | TYPE_68030 | TYPE_68040) - -#define M68030_ONLY TYPE_68030 -#define M68030_LESS (TYPE_68010 | TYPE_68020 | TYPE_68030) -#define M68030_PLUS (TYPE_68030 | TYPE_68040) - -#define M68040_PLUS TYPE_68040 - - -/* Extension word formats */ -#define EXT_8BIT_DISPLACEMENT(A) ((A)&0xff) -#define EXT_FULL(A) BIT_8(A) -#define EXT_EFFECTIVE_ZERO(A) (((A)&0xe4) == 0xc4 || ((A)&0xe2) == 0xc0) -#define EXT_BASE_REGISTER_PRESENT(A) (!BIT_7(A)) -#define EXT_INDEX_REGISTER_PRESENT(A) (!BIT_6(A)) -#define EXT_INDEX_REGISTER(A) (((A)>>12)&7) -#define EXT_INDEX_PRE_POST(A) (EXT_INDEX_PRESENT(A) && (A)&3) -#define EXT_INDEX_PRE(A) (EXT_INDEX_PRESENT(A) && ((A)&7) < 4 && ((A)&7) != 0) -#define EXT_INDEX_POST(A) (EXT_INDEX_PRESENT(A) && ((A)&7) > 4) -#define EXT_INDEX_SCALE(A) (((A)>>9)&3) -#define EXT_INDEX_LONG(A) BIT_B(A) -#define EXT_INDEX_AR(A) BIT_F(A) -#define EXT_BASE_DISPLACEMENT_PRESENT(A) (((A)&0x30) > 0x10) -#define EXT_BASE_DISPLACEMENT_WORD(A) (((A)&0x30) == 0x20) -#define EXT_BASE_DISPLACEMENT_LONG(A) (((A)&0x30) == 0x30) -#define EXT_OUTER_DISPLACEMENT_PRESENT(A) (((A)&3) > 1 && ((A)&0x47) < 0x44) -#define EXT_OUTER_DISPLACEMENT_WORD(A) (((A)&3) == 2 && ((A)&0x47) < 0x44) -#define EXT_OUTER_DISPLACEMENT_LONG(A) (((A)&3) == 3 && ((A)&0x47) < 0x44) - - -/* Opcode flags */ -#if M68K_COMPILE_FOR_MAME == OPT_ON -#define SET_OPCODE_FLAGS(x) g_opcode_type = x; -#define COMBINE_OPCODE_FLAGS(x) ((x) | g_opcode_type | DASMFLAG_SUPPORTED) -#else -#define SET_OPCODE_FLAGS(x) -#define COMBINE_OPCODE_FLAGS(X) (X) -#endif - - -/* ======================================================================== */ -/* =============================== PROTOTYPES ============================= */ -/* ======================================================================== */ - -/* Read data at the PC and increment PC */ -uint read_imm_8(void); -uint read_imm_16(void); -uint read_imm_32(void); - -/* Read data at the PC but don't imcrement the PC */ -uint peek_imm_8(void); -uint peek_imm_16(void); -uint peek_imm_32(void); - -/* make signed integers 100% portably */ -static int make_int_8(int value); -static int make_int_16(int value); -static int make_int_32(int value); - -/* make a string of a hex value */ -static char* make_signed_hex_str_8(uint val); -static char* make_signed_hex_str_16(uint val); -static char* make_signed_hex_str_32(uint val); - -/* make string of ea mode */ -static char* get_ea_mode_str(uint instruction, uint size); - -char* get_ea_mode_str_8(uint instruction); -char* get_ea_mode_str_16(uint instruction); -char* get_ea_mode_str_32(uint instruction); - -/* make string of immediate value */ -static char* get_imm_str_s(uint size); -static char* get_imm_str_u(uint size); - -char* get_imm_str_s8(void); -char* get_imm_str_s16(void); -char* get_imm_str_s32(void); - -/* Stuff to build the opcode handler jump table */ -static void build_opcode_table(void); -static int valid_ea(uint opcode, uint mask); -static int DECL_SPEC compare_nof_true_bits(const void *aptr, const void *bptr); - -/* used to build opcode handler jump table */ -typedef struct -{ - void (*opcode_handler)(void); /* handler function */ - uint mask; /* mask on opcode */ - uint match; /* what to match after masking */ - uint ea_mask; /* what ea modes are allowed */ -} opcode_struct; - - - -/* ======================================================================== */ -/* ================================= DATA ================================= */ -/* ======================================================================== */ - -/* Opcode handler jump table */ -static void (*g_instruction_table[0x10000])(void); -/* Flag if disassembler initialized */ -static int g_initialized = 0; - -/* Address mask to simulate address lines */ -static unsigned int g_address_mask = 0xffffffff; - -static char g_dasm_str[100]; /* string to hold disassembly */ -static char g_helper_str[100]; /* string to hold helpful info */ -static uint g_cpu_pc; /* program counter */ -static uint g_cpu_ir; /* instruction register */ -static uint g_cpu_type; -static uint g_opcode_type; -static const unsigned char* g_rawop; -static uint g_rawbasepc; - -/* used by ops like asr, ror, addq, etc */ -static const uint g_3bit_qdata_table[8] = {8, 1, 2, 3, 4, 5, 6, 7}; - -static const uint g_5bit_data_table[32] = -{ - 32, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 -}; - -static const char *const g_cc[16] = -{"t", "f", "hi", "ls", "cc", "cs", "ne", "eq", "vc", "vs", "pl", "mi", "ge", "lt", "gt", "le"}; - -static const char *const g_cpcc[64] = -{/* 000 001 010 011 100 101 110 111 */ - "f", "eq", "ogt", "oge", "olt", "ole", "ogl", "or", /* 000 */ - "un", "ueq", "ugt", "uge", "ult", "ule", "ne", "t", /* 001 */ - "sf", "seq", "gt", "ge", "lt", "le", "gl", "gle", /* 010 */ - "ngle", "ngl", "nle", "nlt", "nge", "ngt", "sne", "st", /* 011 */ - "?", "?", "?", "?", "?", "?", "?", "?", /* 100 */ - "?", "?", "?", "?", "?", "?", "?", "?", /* 101 */ - "?", "?", "?", "?", "?", "?", "?", "?", /* 110 */ - "?", "?", "?", "?", "?", "?", "?", "?" /* 111 */ -}; - -static const char *const g_mmuregs[8] = -{ - "tc", "drp", "srp", "crp", "cal", "val", "sccr", "acr" -}; - -static const char *const g_mmucond[16] = -{ - "bs", "bc", "ls", "lc", "ss", "sc", "as", "ac", - "ws", "wc", "is", "ic", "gs", "gc", "cs", "cc" -}; - -/* ======================================================================== */ -/* =========================== UTILITY FUNCTIONS ========================== */ -/* ======================================================================== */ - -#define LIMIT_CPU_TYPES(ALLOWED_CPU_TYPES) \ - if(!(g_cpu_type & ALLOWED_CPU_TYPES)) \ - { \ - if((g_cpu_ir & 0xf000) == 0xf000) \ - d68000_1111(); \ - else d68000_illegal(); \ - return; \ - } - -static uint dasm_read_imm_8(uint advance) -{ - uint result; - if (g_rawop) - result = g_rawop[g_cpu_pc + 1 - g_rawbasepc]; - else - result = m68k_read_disassembler_16(g_cpu_pc & g_address_mask) & 0xff; - g_cpu_pc += advance; - return result; -} - -static uint dasm_read_imm_16(uint advance) -{ - uint result; - if (g_rawop) - result = (g_rawop[g_cpu_pc + 0 - g_rawbasepc] << 8) | - g_rawop[g_cpu_pc + 1 - g_rawbasepc]; - else - result = m68k_read_disassembler_16(g_cpu_pc & g_address_mask) & 0xffff; - g_cpu_pc += advance; - return result; -} - -static uint dasm_read_imm_32(uint advance) -{ - uint result; - if (g_rawop) - result = (g_rawop[g_cpu_pc + 0 - g_rawbasepc] << 24) | - (g_rawop[g_cpu_pc + 1 - g_rawbasepc] << 16) | - (g_rawop[g_cpu_pc + 2 - g_rawbasepc] << 8) | - g_rawop[g_cpu_pc + 3 - g_rawbasepc]; - else - result = m68k_read_disassembler_32(g_cpu_pc & g_address_mask) & 0xffffffff; - g_cpu_pc += advance; - return result; -} - -#define read_imm_8() dasm_read_imm_8(2) -#define read_imm_16() dasm_read_imm_16(2) -#define read_imm_32() dasm_read_imm_32(4) - -#define peek_imm_8() dasm_read_imm_8(0) -#define peek_imm_16() dasm_read_imm_16(0) -#define peek_imm_32() dasm_read_imm_32(0) - -/* Fake a split interface */ -#define get_ea_mode_str_8(instruction) get_ea_mode_str(instruction, 0) -#define get_ea_mode_str_16(instruction) get_ea_mode_str(instruction, 1) -#define get_ea_mode_str_32(instruction) get_ea_mode_str(instruction, 2) - -#define get_imm_str_s8() get_imm_str_s(0) -#define get_imm_str_s16() get_imm_str_s(1) -#define get_imm_str_s32() get_imm_str_s(2) - -#define get_imm_str_u8() get_imm_str_u(0) -#define get_imm_str_u16() get_imm_str_u(1) -#define get_imm_str_u32() get_imm_str_u(2) - -static int sext_7bit_int(int value) -{ - return (value & 0x40) ? (value | 0xffffff80) : (value & 0x7f); -} - - -/* 100% portable signed int generators */ -static int make_int_8(int value) -{ - return (value & 0x80) ? value | ~0xff : value & 0xff; -} - -static int make_int_16(int value) -{ - return (value & 0x8000) ? value | ~0xffff : value & 0xffff; -} - -static int make_int_32(int value) -{ - return (value & 0x80000000) ? value | ~0xffffffff : value & 0xffffffff; -} - -/* Get string representation of hex values */ -static char* make_signed_hex_str_8(uint val) -{ - static char str[20]; - - val &= 0xff; - - if(val == 0x80) - sprintf(str, "-$80"); - else if(val & 0x80) - sprintf(str, "-$%x", (0-val) & 0x7f); - else - sprintf(str, "$%x", val & 0x7f); - - return str; -} - -static char* make_signed_hex_str_16(uint val) -{ - static char str[20]; - - val &= 0xffff; - - if(val == 0x8000) - sprintf(str, "-$8000"); - else if(val & 0x8000) - sprintf(str, "-$%x", (0-val) & 0x7fff); - else - sprintf(str, "$%x", val & 0x7fff); - - return str; -} - -static char* make_signed_hex_str_32(uint val) -{ - static char str[20]; - - val &= 0xffffffff; - - if(val == 0x80000000) - sprintf(str, "-$80000000"); - else if(val & 0x80000000) - sprintf(str, "-$%x", (0-val) & 0x7fffffff); - else - sprintf(str, "$%x", val & 0x7fffffff); - - return str; -} - - -/* make string of immediate value */ -static char* get_imm_str_s(uint size) -{ - static char str[15]; - if(size == 0) - sprintf(str, "#%s", make_signed_hex_str_8(read_imm_8())); - else if(size == 1) - sprintf(str, "#%s", make_signed_hex_str_16(read_imm_16())); - else - sprintf(str, "#%s", make_signed_hex_str_32(read_imm_32())); - return str; -} - -static char* get_imm_str_u(uint size) -{ - static char str[15]; - if(size == 0) - sprintf(str, "#$%x", read_imm_8() & 0xff); - else if(size == 1) - sprintf(str, "#$%x", read_imm_16() & 0xffff); - else - sprintf(str, "#$%x", read_imm_32() & 0xffffffff); - return str; -} - -/* Make string of effective address mode */ -static char* get_ea_mode_str(uint instruction, uint size) -{ - static char b1[64]; - static char b2[64]; - static char* mode = b2; - uint extension; - uint base; - uint outer; - char base_reg[4]; - char index_reg[8]; - uint preindex; - uint postindex; - uint comma = 0; - uint temp_value; - - /* Switch buffers so we don't clobber on a double-call to this function */ - mode = mode == b1 ? b2 : b1; - - switch(instruction & 0x3f) - { - case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07: - /* data register direct */ - sprintf(mode, "D%d", instruction&7); - break; - case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f: - /* address register direct */ - sprintf(mode, "A%d", instruction&7); - break; - case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17: - /* address register indirect */ - sprintf(mode, "(A%d)", instruction&7); - break; - case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f: - /* address register indirect with postincrement */ - sprintf(mode, "(A%d)+", instruction&7); - break; - case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27: - /* address register indirect with predecrement */ - sprintf(mode, "-(A%d)", instruction&7); - break; - case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f: - /* address register indirect with displacement*/ - sprintf(mode, "(%s,A%d)", make_signed_hex_str_16(read_imm_16()), instruction&7); - break; - case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37: - /* address register indirect with index */ - extension = read_imm_16(); - - if(EXT_FULL(extension)) - { - if(EXT_EFFECTIVE_ZERO(extension)) - { - strcpy(mode, "0"); - break; - } - base = EXT_BASE_DISPLACEMENT_PRESENT(extension) ? (EXT_BASE_DISPLACEMENT_LONG(extension) ? read_imm_32() : read_imm_16()) : 0; - outer = EXT_OUTER_DISPLACEMENT_PRESENT(extension) ? (EXT_OUTER_DISPLACEMENT_LONG(extension) ? read_imm_32() : read_imm_16()) : 0; - if(EXT_BASE_REGISTER_PRESENT(extension)) - sprintf(base_reg, "A%d", instruction&7); - else - *base_reg = 0; - if(EXT_INDEX_REGISTER_PRESENT(extension)) - { - sprintf(index_reg, "%c%d.%c", EXT_INDEX_AR(extension) ? 'A' : 'D', EXT_INDEX_REGISTER(extension), EXT_INDEX_LONG(extension) ? 'l' : 'w'); - if(EXT_INDEX_SCALE(extension)) - sprintf(index_reg+strlen(index_reg), "*%d", 1 << EXT_INDEX_SCALE(extension)); - } - else - *index_reg = 0; - preindex = (extension&7) > 0 && (extension&7) < 4; - postindex = (extension&7) > 4; - - strcpy(mode, "("); - if(preindex || postindex) - strcat(mode, "["); - if(base) - { - if (EXT_BASE_DISPLACEMENT_LONG(extension)) - { - strcat(mode, make_signed_hex_str_32(base)); - } - else - { - strcat(mode, make_signed_hex_str_16(base)); - } - comma = 1; - } - if(*base_reg) - { - if(comma) - strcat(mode, ","); - strcat(mode, base_reg); - comma = 1; - } - if(postindex) - { - strcat(mode, "]"); - comma = 1; - } - if(*index_reg) - { - if(comma) - strcat(mode, ","); - strcat(mode, index_reg); - comma = 1; - } - if(preindex) - { - strcat(mode, "]"); - comma = 1; - } - if(outer) - { - if(comma) - strcat(mode, ","); - strcat(mode, make_signed_hex_str_16(outer)); - } - strcat(mode, ")"); - break; - } - - if(EXT_8BIT_DISPLACEMENT(extension) == 0) - sprintf(mode, "(A%d,%c%d.%c", instruction&7, EXT_INDEX_AR(extension) ? 'A' : 'D', EXT_INDEX_REGISTER(extension), EXT_INDEX_LONG(extension) ? 'l' : 'w'); - else - sprintf(mode, "(%s,A%d,%c%d.%c", make_signed_hex_str_8(extension), instruction&7, EXT_INDEX_AR(extension) ? 'A' : 'D', EXT_INDEX_REGISTER(extension), EXT_INDEX_LONG(extension) ? 'l' : 'w'); - if(EXT_INDEX_SCALE(extension)) - sprintf(mode+strlen(mode), "*%d", 1 << EXT_INDEX_SCALE(extension)); - strcat(mode, ")"); - break; - case 0x38: - /* absolute short address */ - sprintf(mode, "$%x.w", read_imm_16()); - break; - case 0x39: - /* absolute long address */ - sprintf(mode, "$%x.l", read_imm_32()); - break; - case 0x3a: - /* program counter with displacement */ - temp_value = read_imm_16(); - sprintf(mode, "(%s,PC)", make_signed_hex_str_16(temp_value)); - sprintf(g_helper_str, "; ($%x)", (make_int_16(temp_value) + g_cpu_pc-2) & 0xffffffff); - break; - case 0x3b: - /* program counter with index */ - extension = read_imm_16(); - - if(EXT_FULL(extension)) - { - if(EXT_EFFECTIVE_ZERO(extension)) - { - strcpy(mode, "0"); - break; - } - base = EXT_BASE_DISPLACEMENT_PRESENT(extension) ? (EXT_BASE_DISPLACEMENT_LONG(extension) ? read_imm_32() : read_imm_16()) : 0; - outer = EXT_OUTER_DISPLACEMENT_PRESENT(extension) ? (EXT_OUTER_DISPLACEMENT_LONG(extension) ? read_imm_32() : read_imm_16()) : 0; - if(EXT_BASE_REGISTER_PRESENT(extension)) - strcpy(base_reg, "PC"); - else - *base_reg = 0; - if(EXT_INDEX_REGISTER_PRESENT(extension)) - { - sprintf(index_reg, "%c%d.%c", EXT_INDEX_AR(extension) ? 'A' : 'D', EXT_INDEX_REGISTER(extension), EXT_INDEX_LONG(extension) ? 'l' : 'w'); - if(EXT_INDEX_SCALE(extension)) - sprintf(index_reg+strlen(index_reg), "*%d", 1 << EXT_INDEX_SCALE(extension)); - } - else - *index_reg = 0; - preindex = (extension&7) > 0 && (extension&7) < 4; - postindex = (extension&7) > 4; - - strcpy(mode, "("); - if(preindex || postindex) - strcat(mode, "["); - if(base) - { - strcat(mode, make_signed_hex_str_16(base)); - comma = 1; - } - if(*base_reg) - { - if(comma) - strcat(mode, ","); - strcat(mode, base_reg); - comma = 1; - } - if(postindex) - { - strcat(mode, "]"); - comma = 1; - } - if(*index_reg) - { - if(comma) - strcat(mode, ","); - strcat(mode, index_reg); - comma = 1; - } - if(preindex) - { - strcat(mode, "]"); - comma = 1; - } - if(outer) - { - if(comma) - strcat(mode, ","); - strcat(mode, make_signed_hex_str_16(outer)); - } - strcat(mode, ")"); - break; - } - - if(EXT_8BIT_DISPLACEMENT(extension) == 0) - sprintf(mode, "(PC,%c%d.%c", EXT_INDEX_AR(extension) ? 'A' : 'D', EXT_INDEX_REGISTER(extension), EXT_INDEX_LONG(extension) ? 'l' : 'w'); - else - sprintf(mode, "(%s,PC,%c%d.%c", make_signed_hex_str_8(extension), EXT_INDEX_AR(extension) ? 'A' : 'D', EXT_INDEX_REGISTER(extension), EXT_INDEX_LONG(extension) ? 'l' : 'w'); - if(EXT_INDEX_SCALE(extension)) - sprintf(mode+strlen(mode), "*%d", 1 << EXT_INDEX_SCALE(extension)); - strcat(mode, ")"); - break; - case 0x3c: - /* Immediate */ - sprintf(mode, "%s", get_imm_str_u(size)); - break; - default: - sprintf(mode, "INVALID %x", instruction & 0x3f); - } - return mode; -} - - - -/* ======================================================================== */ -/* ========================= INSTRUCTION HANDLERS ========================= */ -/* ======================================================================== */ -/* Instruction handler function names follow this convention: - * - * d68000_NAME_EXTENSIONS(void) - * where NAME is the name of the opcode it handles and EXTENSIONS are any - * extensions for special instances of that opcode. - * - * Examples: - * d68000_add_er_8(): add opcode, from effective address to register, - * size = byte - * - * d68000_asr_s_8(): arithmetic shift right, static count, size = byte - * - * - * Common extensions: - * 8 : size = byte - * 16 : size = word - * 32 : size = long - * rr : register to register - * mm : memory to memory - * r : register - * s : static - * er : effective address -> register - * re : register -> effective address - * ea : using effective address mode of operation - * d : data register direct - * a : address register direct - * ai : address register indirect - * pi : address register indirect with postincrement - * pd : address register indirect with predecrement - * di : address register indirect with displacement - * ix : address register indirect with index - * aw : absolute word - * al : absolute long - */ - -static void d68000_illegal(void) -{ - sprintf(g_dasm_str, "dc.w $%04x; ILLEGAL", g_cpu_ir); -} - -static void d68000_1010(void) -{ - sprintf(g_dasm_str, "dc.w $%04x; opcode 1010", g_cpu_ir); -} - - -static void d68000_1111(void) -{ - sprintf(g_dasm_str, "dc.w $%04x; opcode 1111", g_cpu_ir); -} - - -static void d68000_abcd_rr(void) -{ - sprintf(g_dasm_str, "abcd D%d, D%d", g_cpu_ir&7, (g_cpu_ir>>9)&7); -} - - -static void d68000_abcd_mm(void) -{ - sprintf(g_dasm_str, "abcd -(A%d), -(A%d)", g_cpu_ir&7, (g_cpu_ir>>9)&7); -} - -static void d68000_add_er_8(void) -{ - sprintf(g_dasm_str, "add.b %s, D%d", get_ea_mode_str_8(g_cpu_ir), (g_cpu_ir>>9)&7); -} - - -static void d68000_add_er_16(void) -{ - sprintf(g_dasm_str, "add.w %s, D%d", get_ea_mode_str_16(g_cpu_ir), (g_cpu_ir>>9)&7); -} - -static void d68000_add_er_32(void) -{ - sprintf(g_dasm_str, "add.l %s, D%d", get_ea_mode_str_32(g_cpu_ir), (g_cpu_ir>>9)&7); -} - -static void d68000_add_re_8(void) -{ - sprintf(g_dasm_str, "add.b D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_8(g_cpu_ir)); -} - -static void d68000_add_re_16(void) -{ - sprintf(g_dasm_str, "add.w D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_16(g_cpu_ir)); -} - -static void d68000_add_re_32(void) -{ - sprintf(g_dasm_str, "add.l D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_32(g_cpu_ir)); -} - -static void d68000_adda_16(void) -{ - sprintf(g_dasm_str, "adda.w %s, A%d", get_ea_mode_str_16(g_cpu_ir), (g_cpu_ir>>9)&7); -} - -static void d68000_adda_32(void) -{ - sprintf(g_dasm_str, "adda.l %s, A%d", get_ea_mode_str_32(g_cpu_ir), (g_cpu_ir>>9)&7); -} - -static void d68000_addi_8(void) -{ - char* str = get_imm_str_s8(); - sprintf(g_dasm_str, "addi.b %s, %s", str, get_ea_mode_str_8(g_cpu_ir)); -} - -static void d68000_addi_16(void) -{ - char* str = get_imm_str_s16(); - sprintf(g_dasm_str, "addi.w %s, %s", str, get_ea_mode_str_16(g_cpu_ir)); -} - -static void d68000_addi_32(void) -{ - char* str = get_imm_str_s32(); - sprintf(g_dasm_str, "addi.l %s, %s", str, get_ea_mode_str_32(g_cpu_ir)); -} - -static void d68000_addq_8(void) -{ - sprintf(g_dasm_str, "addq.b #%d, %s", g_3bit_qdata_table[(g_cpu_ir>>9)&7], get_ea_mode_str_8(g_cpu_ir)); -} - -static void d68000_addq_16(void) -{ - sprintf(g_dasm_str, "addq.w #%d, %s", g_3bit_qdata_table[(g_cpu_ir>>9)&7], get_ea_mode_str_16(g_cpu_ir)); -} - -static void d68000_addq_32(void) -{ - sprintf(g_dasm_str, "addq.l #%d, %s", g_3bit_qdata_table[(g_cpu_ir>>9)&7], get_ea_mode_str_32(g_cpu_ir)); -} - -static void d68000_addx_rr_8(void) -{ - sprintf(g_dasm_str, "addx.b D%d, D%d", g_cpu_ir&7, (g_cpu_ir>>9)&7); -} - -static void d68000_addx_rr_16(void) -{ - sprintf(g_dasm_str, "addx.w D%d, D%d", g_cpu_ir&7, (g_cpu_ir>>9)&7); -} - -static void d68000_addx_rr_32(void) -{ - sprintf(g_dasm_str, "addx.l D%d, D%d", g_cpu_ir&7, (g_cpu_ir>>9)&7); -} - -static void d68000_addx_mm_8(void) -{ - sprintf(g_dasm_str, "addx.b -(A%d), -(A%d)", g_cpu_ir&7, (g_cpu_ir>>9)&7); -} - -static void d68000_addx_mm_16(void) -{ - sprintf(g_dasm_str, "addx.w -(A%d), -(A%d)", g_cpu_ir&7, (g_cpu_ir>>9)&7); -} - -static void d68000_addx_mm_32(void) -{ - sprintf(g_dasm_str, "addx.l -(A%d), -(A%d)", g_cpu_ir&7, (g_cpu_ir>>9)&7); -} - -static void d68000_and_er_8(void) -{ - sprintf(g_dasm_str, "and.b %s, D%d", get_ea_mode_str_8(g_cpu_ir), (g_cpu_ir>>9)&7); -} - -static void d68000_and_er_16(void) -{ - sprintf(g_dasm_str, "and.w %s, D%d", get_ea_mode_str_16(g_cpu_ir), (g_cpu_ir>>9)&7); -} - -static void d68000_and_er_32(void) -{ - sprintf(g_dasm_str, "and.l %s, D%d", get_ea_mode_str_32(g_cpu_ir), (g_cpu_ir>>9)&7); -} - -static void d68000_and_re_8(void) -{ - sprintf(g_dasm_str, "and.b D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_8(g_cpu_ir)); -} - -static void d68000_and_re_16(void) -{ - sprintf(g_dasm_str, "and.w D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_16(g_cpu_ir)); -} - -static void d68000_and_re_32(void) -{ - sprintf(g_dasm_str, "and.l D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_32(g_cpu_ir)); -} - -static void d68000_andi_8(void) -{ - char* str = get_imm_str_u8(); - sprintf(g_dasm_str, "andi.b %s, %s", str, get_ea_mode_str_8(g_cpu_ir)); -} - -static void d68000_andi_16(void) -{ - char* str = get_imm_str_u16(); - sprintf(g_dasm_str, "andi.w %s, %s", str, get_ea_mode_str_16(g_cpu_ir)); -} - -static void d68000_andi_32(void) -{ - char* str = get_imm_str_u32(); - sprintf(g_dasm_str, "andi.l %s, %s", str, get_ea_mode_str_32(g_cpu_ir)); -} - -static void d68000_andi_to_ccr(void) -{ - sprintf(g_dasm_str, "andi %s, CCR", get_imm_str_u8()); -} - -static void d68000_andi_to_sr(void) -{ - sprintf(g_dasm_str, "andi %s, SR", get_imm_str_u16()); -} - -static void d68000_asr_s_8(void) -{ - sprintf(g_dasm_str, "asr.b #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); -} - -static void d68000_asr_s_16(void) -{ - sprintf(g_dasm_str, "asr.w #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); -} - -static void d68000_asr_s_32(void) -{ - sprintf(g_dasm_str, "asr.l #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); -} - -static void d68000_asr_r_8(void) -{ - sprintf(g_dasm_str, "asr.b D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); -} - -static void d68000_asr_r_16(void) -{ - sprintf(g_dasm_str, "asr.w D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); -} - -static void d68000_asr_r_32(void) -{ - sprintf(g_dasm_str, "asr.l D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); -} - -static void d68000_asr_ea(void) -{ - sprintf(g_dasm_str, "asr.w %s", get_ea_mode_str_16(g_cpu_ir)); -} - -static void d68000_asl_s_8(void) -{ - sprintf(g_dasm_str, "asl.b #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); -} - -static void d68000_asl_s_16(void) -{ - sprintf(g_dasm_str, "asl.w #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); -} - -static void d68000_asl_s_32(void) -{ - sprintf(g_dasm_str, "asl.l #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); -} - -static void d68000_asl_r_8(void) -{ - sprintf(g_dasm_str, "asl.b D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); -} - -static void d68000_asl_r_16(void) -{ - sprintf(g_dasm_str, "asl.w D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); -} - -static void d68000_asl_r_32(void) -{ - sprintf(g_dasm_str, "asl.l D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); -} - -static void d68000_asl_ea(void) -{ - sprintf(g_dasm_str, "asl.w %s", get_ea_mode_str_16(g_cpu_ir)); -} - -static void d68000_bcc_8(void) -{ - uint temp_pc = g_cpu_pc; - sprintf(g_dasm_str, "b%-2s $%x", g_cc[(g_cpu_ir>>8)&0xf], temp_pc + make_int_8(g_cpu_ir)); -} - -static void d68000_bcc_16(void) -{ - uint temp_pc = g_cpu_pc; - sprintf(g_dasm_str, "b%-2s $%x", g_cc[(g_cpu_ir>>8)&0xf], temp_pc + make_int_16(read_imm_16())); -} - -static void d68020_bcc_32(void) -{ - uint temp_pc = g_cpu_pc; - LIMIT_CPU_TYPES(M68020_PLUS); - sprintf(g_dasm_str, "b%-2s $%x; (2+)", g_cc[(g_cpu_ir>>8)&0xf], temp_pc + read_imm_32()); -} - -static void d68000_bchg_r(void) -{ - sprintf(g_dasm_str, "bchg D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_8(g_cpu_ir)); -} - -static void d68000_bchg_s(void) -{ - char* str = get_imm_str_u8(); - sprintf(g_dasm_str, "bchg %s, %s", str, get_ea_mode_str_8(g_cpu_ir)); -} - -static void d68000_bclr_r(void) -{ - sprintf(g_dasm_str, "bclr D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_8(g_cpu_ir)); -} - -static void d68000_bclr_s(void) -{ - char* str = get_imm_str_u8(); - sprintf(g_dasm_str, "bclr %s, %s", str, get_ea_mode_str_8(g_cpu_ir)); -} - -static void d68010_bkpt(void) -{ - LIMIT_CPU_TYPES(M68010_PLUS); - sprintf(g_dasm_str, "bkpt #%d; (1+)", g_cpu_ir&7); -} - -static void d68020_bfchg(void) -{ - uint extension; - char offset[3]; - char width[3]; - - LIMIT_CPU_TYPES(M68020_PLUS); - - extension = read_imm_16(); - - if(BIT_B(extension)) - sprintf(offset, "D%d", (extension>>6)&7); - else - sprintf(offset, "%d", (extension>>6)&31); - if(BIT_5(extension)) - sprintf(width, "D%d", extension&7); - else - sprintf(width, "%d", g_5bit_data_table[extension&31]); - sprintf(g_dasm_str, "bfchg %s {%s:%s}; (2+)", get_ea_mode_str_8(g_cpu_ir), offset, width); -} - -static void d68020_bfclr(void) -{ - uint extension; - char offset[3]; - char width[3]; - - LIMIT_CPU_TYPES(M68020_PLUS); - - extension = read_imm_16(); - - if(BIT_B(extension)) - sprintf(offset, "D%d", (extension>>6)&7); - else - sprintf(offset, "%d", (extension>>6)&31); - if(BIT_5(extension)) - sprintf(width, "D%d", extension&7); - else - sprintf(width, "%d", g_5bit_data_table[extension&31]); - sprintf(g_dasm_str, "bfclr %s {%s:%s}; (2+)", get_ea_mode_str_8(g_cpu_ir), offset, width); -} - -static void d68020_bfexts(void) -{ - uint extension; - char offset[3]; - char width[3]; - - LIMIT_CPU_TYPES(M68020_PLUS); - - extension = read_imm_16(); - - if(BIT_B(extension)) - sprintf(offset, "D%d", (extension>>6)&7); - else - sprintf(offset, "%d", (extension>>6)&31); - if(BIT_5(extension)) - sprintf(width, "D%d", extension&7); - else - sprintf(width, "%d", g_5bit_data_table[extension&31]); - sprintf(g_dasm_str, "bfexts %s {%s:%s}, D%d; (2+)", get_ea_mode_str_8(g_cpu_ir), offset, width, (extension>>12)&7); -} - -static void d68020_bfextu(void) -{ - uint extension; - char offset[3]; - char width[3]; - - LIMIT_CPU_TYPES(M68020_PLUS); - - extension = read_imm_16(); - - if(BIT_B(extension)) - sprintf(offset, "D%d", (extension>>6)&7); - else - sprintf(offset, "%d", (extension>>6)&31); - if(BIT_5(extension)) - sprintf(width, "D%d", extension&7); - else - sprintf(width, "%d", g_5bit_data_table[extension&31]); - sprintf(g_dasm_str, "bfextu %s {%s:%s}, D%d; (2+)", get_ea_mode_str_8(g_cpu_ir), offset, width, (extension>>12)&7); -} - -static void d68020_bfffo(void) -{ - uint extension; - char offset[3]; - char width[3]; - - LIMIT_CPU_TYPES(M68020_PLUS); - - extension = read_imm_16(); - - if(BIT_B(extension)) - sprintf(offset, "D%d", (extension>>6)&7); - else - sprintf(offset, "%d", (extension>>6)&31); - if(BIT_5(extension)) - sprintf(width, "D%d", extension&7); - else - sprintf(width, "%d", g_5bit_data_table[extension&31]); - sprintf(g_dasm_str, "bfffo %s {%s:%s}, D%d; (2+)", get_ea_mode_str_8(g_cpu_ir), offset, width, (extension>>12)&7); -} - -static void d68020_bfins(void) -{ - uint extension; - char offset[3]; - char width[3]; - - LIMIT_CPU_TYPES(M68020_PLUS); - - extension = read_imm_16(); - - if(BIT_B(extension)) - sprintf(offset, "D%d", (extension>>6)&7); - else - sprintf(offset, "%d", (extension>>6)&31); - if(BIT_5(extension)) - sprintf(width, "D%d", extension&7); - else - sprintf(width, "%d", g_5bit_data_table[extension&31]); - sprintf(g_dasm_str, "bfins D%d, %s {%s:%s}; (2+)", (extension>>12)&7, get_ea_mode_str_8(g_cpu_ir), offset, width); -} - -static void d68020_bfset(void) -{ - uint extension; - char offset[3]; - char width[3]; - - LIMIT_CPU_TYPES(M68020_PLUS); - - extension = read_imm_16(); - - if(BIT_B(extension)) - sprintf(offset, "D%d", (extension>>6)&7); - else - sprintf(offset, "%d", (extension>>6)&31); - if(BIT_5(extension)) - sprintf(width, "D%d", extension&7); - else - sprintf(width, "%d", g_5bit_data_table[extension&31]); - sprintf(g_dasm_str, "bfset %s {%s:%s}; (2+)", get_ea_mode_str_8(g_cpu_ir), offset, width); -} - -static void d68020_bftst(void) -{ - uint extension; - char offset[3]; - char width[3]; - - LIMIT_CPU_TYPES(M68020_PLUS); - - extension = read_imm_16(); - - if(BIT_B(extension)) - sprintf(offset, "D%d", (extension>>6)&7); - else - sprintf(offset, "%d", (extension>>6)&31); - if(BIT_5(extension)) - sprintf(width, "D%d", extension&7); - else - sprintf(width, "%d", g_5bit_data_table[extension&31]); - sprintf(g_dasm_str, "bftst %s {%s:%s}; (2+)", get_ea_mode_str_8(g_cpu_ir), offset, width); -} - -static void d68000_bra_8(void) -{ - uint temp_pc = g_cpu_pc; - sprintf(g_dasm_str, "bra $%x", temp_pc + make_int_8(g_cpu_ir)); -} - -static void d68000_bra_16(void) -{ - uint temp_pc = g_cpu_pc; - sprintf(g_dasm_str, "bra $%x", temp_pc + make_int_16(read_imm_16())); -} - -static void d68020_bra_32(void) -{ - uint temp_pc = g_cpu_pc; - LIMIT_CPU_TYPES(M68020_PLUS); - sprintf(g_dasm_str, "bra $%x; (2+)", temp_pc + read_imm_32()); -} - -static void d68000_bset_r(void) -{ - sprintf(g_dasm_str, "bset D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_8(g_cpu_ir)); -} - -static void d68000_bset_s(void) -{ - char* str = get_imm_str_u8(); - sprintf(g_dasm_str, "bset %s, %s", str, get_ea_mode_str_8(g_cpu_ir)); -} - -static void d68000_bsr_8(void) -{ - uint temp_pc = g_cpu_pc; - sprintf(g_dasm_str, "bsr $%x", temp_pc + make_int_8(g_cpu_ir)); - SET_OPCODE_FLAGS(DASMFLAG_STEP_OVER); -} - -static void d68000_bsr_16(void) -{ - uint temp_pc = g_cpu_pc; - sprintf(g_dasm_str, "bsr $%x", temp_pc + make_int_16(read_imm_16())); - SET_OPCODE_FLAGS(DASMFLAG_STEP_OVER); -} - -static void d68020_bsr_32(void) -{ - uint temp_pc = g_cpu_pc; - LIMIT_CPU_TYPES(M68020_PLUS); - sprintf(g_dasm_str, "bsr $%x; (2+)", temp_pc + read_imm_32()); - SET_OPCODE_FLAGS(DASMFLAG_STEP_OVER); -} - -static void d68000_btst_r(void) -{ - sprintf(g_dasm_str, "btst D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_8(g_cpu_ir)); -} - -static void d68000_btst_s(void) -{ - char* str = get_imm_str_u8(); - sprintf(g_dasm_str, "btst %s, %s", str, get_ea_mode_str_8(g_cpu_ir)); -} - -static void d68020_callm(void) -{ - char* str; - LIMIT_CPU_TYPES(M68020_ONLY); - str = get_imm_str_u8(); - - sprintf(g_dasm_str, "callm %s, %s; (2)", str, get_ea_mode_str_8(g_cpu_ir)); -} - -static void d68020_cas_8(void) -{ - uint extension; - LIMIT_CPU_TYPES(M68020_PLUS); - extension = read_imm_16(); - sprintf(g_dasm_str, "cas.b D%d, D%d, %s; (2+)", extension&7, (extension>>6)&7, get_ea_mode_str_8(g_cpu_ir)); -} - -static void d68020_cas_16(void) -{ - uint extension; - LIMIT_CPU_TYPES(M68020_PLUS); - extension = read_imm_16(); - sprintf(g_dasm_str, "cas.w D%d, D%d, %s; (2+)", extension&7, (extension>>6)&7, get_ea_mode_str_16(g_cpu_ir)); -} - -static void d68020_cas_32(void) -{ - uint extension; - LIMIT_CPU_TYPES(M68020_PLUS); - extension = read_imm_16(); - sprintf(g_dasm_str, "cas.l D%d, D%d, %s; (2+)", extension&7, (extension>>6)&7, get_ea_mode_str_32(g_cpu_ir)); -} - -static void d68020_cas2_16(void) -{ -/* CAS2 Dc1:Dc2,Du1:Dc2:(Rn1):(Rn2) -f e d c b a 9 8 7 6 5 4 3 2 1 0 - DARn1 0 0 0 Du1 0 0 0 Dc1 - DARn2 0 0 0 Du2 0 0 0 Dc2 -*/ - - uint extension; - LIMIT_CPU_TYPES(M68020_PLUS); - extension = read_imm_32(); - sprintf(g_dasm_str, "cas2.w D%d:D%d, D%d:D%d, (%c%d):(%c%d); (2+)", - (extension>>16)&7, extension&7, (extension>>22)&7, (extension>>6)&7, - BIT_1F(extension) ? 'A' : 'D', (extension>>28)&7, - BIT_F(extension) ? 'A' : 'D', (extension>>12)&7); -} - -static void d68020_cas2_32(void) -{ - uint extension; - LIMIT_CPU_TYPES(M68020_PLUS); - extension = read_imm_32(); - sprintf(g_dasm_str, "cas2.l D%d:D%d, D%d:D%d, (%c%d):(%c%d); (2+)", - (extension>>16)&7, extension&7, (extension>>22)&7, (extension>>6)&7, - BIT_1F(extension) ? 'A' : 'D', (extension>>28)&7, - BIT_F(extension) ? 'A' : 'D', (extension>>12)&7); -} - -static void d68000_chk_16(void) -{ - sprintf(g_dasm_str, "chk.w %s, D%d", get_ea_mode_str_16(g_cpu_ir), (g_cpu_ir>>9)&7); - SET_OPCODE_FLAGS(DASMFLAG_STEP_OVER); -} - -static void d68020_chk_32(void) -{ - LIMIT_CPU_TYPES(M68020_PLUS); - sprintf(g_dasm_str, "chk.l %s, D%d; (2+)", get_ea_mode_str_32(g_cpu_ir), (g_cpu_ir>>9)&7); - SET_OPCODE_FLAGS(DASMFLAG_STEP_OVER); -} - -static void d68020_chk2_cmp2_8(void) -{ - uint extension; - LIMIT_CPU_TYPES(M68020_PLUS); - extension = read_imm_16(); - sprintf(g_dasm_str, "%s.b %s, %c%d; (2+)", BIT_B(extension) ? "chk2" : "cmp2", get_ea_mode_str_8(g_cpu_ir), BIT_F(extension) ? 'A' : 'D', (extension>>12)&7); -} - -static void d68020_chk2_cmp2_16(void) -{ - uint extension; - LIMIT_CPU_TYPES(M68020_PLUS); - extension = read_imm_16(); - sprintf(g_dasm_str, "%s.w %s, %c%d; (2+)", BIT_B(extension) ? "chk2" : "cmp2", get_ea_mode_str_16(g_cpu_ir), BIT_F(extension) ? 'A' : 'D', (extension>>12)&7); -} - -static void d68020_chk2_cmp2_32(void) -{ - uint extension; - LIMIT_CPU_TYPES(M68020_PLUS); - extension = read_imm_16(); - sprintf(g_dasm_str, "%s.l %s, %c%d; (2+)", BIT_B(extension) ? "chk2" : "cmp2", get_ea_mode_str_32(g_cpu_ir), BIT_F(extension) ? 'A' : 'D', (extension>>12)&7); -} - -static void d68040_cinv(void) -{ - LIMIT_CPU_TYPES(M68040_PLUS); - switch((g_cpu_ir>>3)&3) - { - case 0: - sprintf(g_dasm_str, "cinv (illegal scope); (4)"); - break; - case 1: - sprintf(g_dasm_str, "cinvl %d, (A%d); (4)", (g_cpu_ir>>6)&3, g_cpu_ir&7); - break; - case 2: - sprintf(g_dasm_str, "cinvp %d, (A%d); (4)", (g_cpu_ir>>6)&3, g_cpu_ir&7); - break; - case 3: - sprintf(g_dasm_str, "cinva %d; (4)", (g_cpu_ir>>6)&3); - break; - } -} - -static void d68000_clr_8(void) -{ - sprintf(g_dasm_str, "clr.b %s", get_ea_mode_str_8(g_cpu_ir)); -} - -static void d68000_clr_16(void) -{ - sprintf(g_dasm_str, "clr.w %s", get_ea_mode_str_16(g_cpu_ir)); -} - -static void d68000_clr_32(void) -{ - sprintf(g_dasm_str, "clr.l %s", get_ea_mode_str_32(g_cpu_ir)); -} - -static void d68000_cmp_8(void) -{ - sprintf(g_dasm_str, "cmp.b %s, D%d", get_ea_mode_str_8(g_cpu_ir), (g_cpu_ir>>9)&7); -} - -static void d68000_cmp_16(void) -{ - sprintf(g_dasm_str, "cmp.w %s, D%d", get_ea_mode_str_16(g_cpu_ir), (g_cpu_ir>>9)&7); -} - -static void d68000_cmp_32(void) -{ - sprintf(g_dasm_str, "cmp.l %s, D%d", get_ea_mode_str_32(g_cpu_ir), (g_cpu_ir>>9)&7); -} - -static void d68000_cmpa_16(void) -{ - sprintf(g_dasm_str, "cmpa.w %s, A%d", get_ea_mode_str_16(g_cpu_ir), (g_cpu_ir>>9)&7); -} - -static void d68000_cmpa_32(void) -{ - sprintf(g_dasm_str, "cmpa.l %s, A%d", get_ea_mode_str_32(g_cpu_ir), (g_cpu_ir>>9)&7); -} - -static void d68000_cmpi_8(void) -{ - char* str = get_imm_str_s8(); - sprintf(g_dasm_str, "cmpi.b %s, %s", str, get_ea_mode_str_8(g_cpu_ir)); -} - -static void d68020_cmpi_pcdi_8(void) -{ - char* str; - LIMIT_CPU_TYPES(M68010_PLUS); - str = get_imm_str_s8(); - sprintf(g_dasm_str, "cmpi.b %s, %s; (2+)", str, get_ea_mode_str_8(g_cpu_ir)); -} - -static void d68020_cmpi_pcix_8(void) -{ - char* str; - LIMIT_CPU_TYPES(M68010_PLUS); - str = get_imm_str_s8(); - sprintf(g_dasm_str, "cmpi.b %s, %s; (2+)", str, get_ea_mode_str_8(g_cpu_ir)); -} - -static void d68000_cmpi_16(void) -{ - char* str; - str = get_imm_str_s16(); - sprintf(g_dasm_str, "cmpi.w %s, %s", str, get_ea_mode_str_16(g_cpu_ir)); -} - -static void d68020_cmpi_pcdi_16(void) -{ - char* str; - LIMIT_CPU_TYPES(M68010_PLUS); - str = get_imm_str_s16(); - sprintf(g_dasm_str, "cmpi.w %s, %s; (2+)", str, get_ea_mode_str_16(g_cpu_ir)); -} - -static void d68020_cmpi_pcix_16(void) -{ - char* str; - LIMIT_CPU_TYPES(M68010_PLUS); - str = get_imm_str_s16(); - sprintf(g_dasm_str, "cmpi.w %s, %s; (2+)", str, get_ea_mode_str_16(g_cpu_ir)); -} - -static void d68000_cmpi_32(void) -{ - char* str; - str = get_imm_str_s32(); - sprintf(g_dasm_str, "cmpi.l %s, %s", str, get_ea_mode_str_32(g_cpu_ir)); -} - -static void d68020_cmpi_pcdi_32(void) -{ - char* str; - LIMIT_CPU_TYPES(M68010_PLUS); - str = get_imm_str_s32(); - sprintf(g_dasm_str, "cmpi.l %s, %s; (2+)", str, get_ea_mode_str_32(g_cpu_ir)); -} - -static void d68020_cmpi_pcix_32(void) -{ - char* str; - LIMIT_CPU_TYPES(M68010_PLUS); - str = get_imm_str_s32(); - sprintf(g_dasm_str, "cmpi.l %s, %s; (2+)", str, get_ea_mode_str_32(g_cpu_ir)); -} - -static void d68000_cmpm_8(void) -{ - sprintf(g_dasm_str, "cmpm.b (A%d)+, (A%d)+", g_cpu_ir&7, (g_cpu_ir>>9)&7); -} - -static void d68000_cmpm_16(void) -{ - sprintf(g_dasm_str, "cmpm.w (A%d)+, (A%d)+", g_cpu_ir&7, (g_cpu_ir>>9)&7); -} - -static void d68000_cmpm_32(void) -{ - sprintf(g_dasm_str, "cmpm.l (A%d)+, (A%d)+", g_cpu_ir&7, (g_cpu_ir>>9)&7); -} - -static void d68020_cpbcc_16(void) -{ - uint extension; - uint new_pc = g_cpu_pc; - LIMIT_CPU_TYPES(M68020_PLUS); - extension = read_imm_16(); - new_pc += make_int_16(read_imm_16()); - sprintf(g_dasm_str, "%db%-4s %s; %x (extension = %x) (2-3)", (g_cpu_ir>>9)&7, g_cpcc[g_cpu_ir&0x3f], get_imm_str_s16(), new_pc, extension); -} - -static void d68020_cpbcc_32(void) -{ - uint extension; - uint new_pc = g_cpu_pc; - LIMIT_CPU_TYPES(M68020_PLUS); - extension = read_imm_16(); - new_pc += read_imm_32(); - sprintf(g_dasm_str, "%db%-4s %s; %x (extension = %x) (2-3)", (g_cpu_ir>>9)&7, g_cpcc[g_cpu_ir&0x3f], get_imm_str_s16(), new_pc, extension); -} - -static void d68020_cpdbcc(void) -{ - uint extension1; - uint extension2; - uint new_pc = g_cpu_pc; - LIMIT_CPU_TYPES(M68020_PLUS); - extension1 = read_imm_16(); - extension2 = read_imm_16(); - new_pc += make_int_16(read_imm_16()); - sprintf(g_dasm_str, "%ddb%-4s D%d,%s; %x (extension = %x) (2-3)", (g_cpu_ir>>9)&7, g_cpcc[extension1&0x3f], g_cpu_ir&7, get_imm_str_s16(), new_pc, extension2); -} - -static void d68020_cpgen(void) -{ - LIMIT_CPU_TYPES(M68020_PLUS); - sprintf(g_dasm_str, "%dgen %s; (2-3)", (g_cpu_ir>>9)&7, get_imm_str_u32()); -} - -static void d68020_cprestore(void) -{ - LIMIT_CPU_TYPES(M68020_PLUS); - if (((g_cpu_ir>>9)&7) == 1) - { - sprintf(g_dasm_str, "frestore %s", get_ea_mode_str_8(g_cpu_ir)); - } - else - { - sprintf(g_dasm_str, "%drestore %s; (2-3)", (g_cpu_ir>>9)&7, get_ea_mode_str_8(g_cpu_ir)); - } -} - -static void d68020_cpsave(void) -{ - LIMIT_CPU_TYPES(M68020_PLUS); - if (((g_cpu_ir>>9)&7) == 1) - { - sprintf(g_dasm_str, "fsave %s", get_ea_mode_str_8(g_cpu_ir)); - } - else - { - sprintf(g_dasm_str, "%dsave %s; (2-3)", (g_cpu_ir>>9)&7, get_ea_mode_str_8(g_cpu_ir)); - } -} - -static void d68020_cpscc(void) -{ - uint extension1; - uint extension2; - LIMIT_CPU_TYPES(M68020_PLUS); - extension1 = read_imm_16(); - extension2 = read_imm_16(); - sprintf(g_dasm_str, "%ds%-4s %s; (extension = %x) (2-3)", (g_cpu_ir>>9)&7, g_cpcc[extension1&0x3f], get_ea_mode_str_8(g_cpu_ir), extension2); -} - -static void d68020_cptrapcc_0(void) -{ - uint extension1; - uint extension2; - LIMIT_CPU_TYPES(M68020_PLUS); - extension1 = read_imm_16(); - extension2 = read_imm_16(); - sprintf(g_dasm_str, "%dtrap%-4s; (extension = %x) (2-3)", (g_cpu_ir>>9)&7, g_cpcc[extension1&0x3f], extension2); -} - -static void d68020_cptrapcc_16(void) -{ - uint extension1; - uint extension2; - LIMIT_CPU_TYPES(M68020_PLUS); - extension1 = read_imm_16(); - extension2 = read_imm_16(); - sprintf(g_dasm_str, "%dtrap%-4s %s; (extension = %x) (2-3)", (g_cpu_ir>>9)&7, g_cpcc[extension1&0x3f], get_imm_str_u16(), extension2); -} - -static void d68020_cptrapcc_32(void) -{ - uint extension1; - uint extension2; - LIMIT_CPU_TYPES(M68020_PLUS); - extension1 = read_imm_16(); - extension2 = read_imm_16(); - sprintf(g_dasm_str, "%dtrap%-4s %s; (extension = %x) (2-3)", (g_cpu_ir>>9)&7, g_cpcc[extension1&0x3f], get_imm_str_u32(), extension2); -} - -static void d68040_cpush(void) -{ - LIMIT_CPU_TYPES(M68040_PLUS); - switch((g_cpu_ir>>3)&3) - { - case 0: - sprintf(g_dasm_str, "cpush (illegal scope); (4)"); - break; - case 1: - sprintf(g_dasm_str, "cpushl %d, (A%d); (4)", (g_cpu_ir>>6)&3, g_cpu_ir&7); - break; - case 2: - sprintf(g_dasm_str, "cpushp %d, (A%d); (4)", (g_cpu_ir>>6)&3, g_cpu_ir&7); - break; - case 3: - sprintf(g_dasm_str, "cpusha %d; (4)", (g_cpu_ir>>6)&3); - break; - } -} - -static void d68000_dbra(void) -{ - uint temp_pc = g_cpu_pc; - sprintf(g_dasm_str, "dbra D%d, $%x", g_cpu_ir & 7, temp_pc + make_int_16(read_imm_16())); - SET_OPCODE_FLAGS(DASMFLAG_STEP_OVER); -} - -static void d68000_dbcc(void) -{ - uint temp_pc = g_cpu_pc; - sprintf(g_dasm_str, "db%-2s D%d, $%x", g_cc[(g_cpu_ir>>8)&0xf], g_cpu_ir & 7, temp_pc + make_int_16(read_imm_16())); - SET_OPCODE_FLAGS(DASMFLAG_STEP_OVER); -} - -static void d68000_divs(void) -{ - sprintf(g_dasm_str, "divs.w %s, D%d", get_ea_mode_str_16(g_cpu_ir), (g_cpu_ir>>9)&7); -} - -static void d68000_divu(void) -{ - sprintf(g_dasm_str, "divu.w %s, D%d", get_ea_mode_str_16(g_cpu_ir), (g_cpu_ir>>9)&7); -} - -static void d68020_divl(void) -{ - uint extension; - LIMIT_CPU_TYPES(M68020_PLUS); - extension = read_imm_16(); - - if(BIT_A(extension)) - sprintf(g_dasm_str, "div%c.l %s, D%d:D%d; (2+)", BIT_B(extension) ? 's' : 'u', get_ea_mode_str_32(g_cpu_ir), extension&7, (extension>>12)&7); - else if((extension&7) == ((extension>>12)&7)) - sprintf(g_dasm_str, "div%c.l %s, D%d; (2+)", BIT_B(extension) ? 's' : 'u', get_ea_mode_str_32(g_cpu_ir), (extension>>12)&7); - else - sprintf(g_dasm_str, "div%cl.l %s, D%d:D%d; (2+)", BIT_B(extension) ? 's' : 'u', get_ea_mode_str_32(g_cpu_ir), extension&7, (extension>>12)&7); -} - -static void d68000_eor_8(void) -{ - sprintf(g_dasm_str, "eor.b D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_8(g_cpu_ir)); -} - -static void d68000_eor_16(void) -{ - sprintf(g_dasm_str, "eor.w D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_16(g_cpu_ir)); -} - -static void d68000_eor_32(void) -{ - sprintf(g_dasm_str, "eor.l D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_32(g_cpu_ir)); -} - -static void d68000_eori_8(void) -{ - char* str = get_imm_str_u8(); - sprintf(g_dasm_str, "eori.b %s, %s", str, get_ea_mode_str_8(g_cpu_ir)); -} - -static void d68000_eori_16(void) -{ - char* str = get_imm_str_u16(); - sprintf(g_dasm_str, "eori.w %s, %s", str, get_ea_mode_str_16(g_cpu_ir)); -} - -static void d68000_eori_32(void) -{ - char* str = get_imm_str_u32(); - sprintf(g_dasm_str, "eori.l %s, %s", str, get_ea_mode_str_32(g_cpu_ir)); -} - -static void d68000_eori_to_ccr(void) -{ - sprintf(g_dasm_str, "eori %s, CCR", get_imm_str_u8()); -} - -static void d68000_eori_to_sr(void) -{ - sprintf(g_dasm_str, "eori %s, SR", get_imm_str_u16()); -} - -static void d68000_exg_dd(void) -{ - sprintf(g_dasm_str, "exg D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); -} - -static void d68000_exg_aa(void) -{ - sprintf(g_dasm_str, "exg A%d, A%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); -} - -static void d68000_exg_da(void) -{ - sprintf(g_dasm_str, "exg D%d, A%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); -} - -static void d68000_ext_16(void) -{ - sprintf(g_dasm_str, "ext.w D%d", g_cpu_ir&7); -} - -static void d68000_ext_32(void) -{ - sprintf(g_dasm_str, "ext.l D%d", g_cpu_ir&7); -} - -static void d68020_extb_32(void) -{ - LIMIT_CPU_TYPES(M68020_PLUS); - sprintf(g_dasm_str, "extb.l D%d; (2+)", g_cpu_ir&7); -} - -static void d68040_fpu(void) -{ - char float_data_format[8][3] = - { - ".l", ".s", ".x", ".p", ".w", ".d", ".b", ".p" - }; - - char mnemonic[40]; - uint32 w2, src, dst_reg; - LIMIT_CPU_TYPES(M68030_PLUS); - w2 = read_imm_16(); - - src = (w2 >> 10) & 0x7; - dst_reg = (w2 >> 7) & 0x7; - - // special override for FMOVECR - if ((((w2 >> 13) & 0x7) == 2) && (((w2>>10)&0x7) == 7)) - { - sprintf(g_dasm_str, "fmovecr #$%0x, fp%d", (w2&0x7f), dst_reg); - return; - } - - switch ((w2 >> 13) & 0x7) - { - case 0x0: - case 0x2: - { - switch(w2 & 0x7f) - { - case 0x00: sprintf(mnemonic, "fmove"); break; - case 0x01: sprintf(mnemonic, "fint"); break; - case 0x02: sprintf(mnemonic, "fsinh"); break; - case 0x03: sprintf(mnemonic, "fintrz"); break; - case 0x04: sprintf(mnemonic, "fsqrt"); break; - case 0x06: sprintf(mnemonic, "flognp1"); break; - case 0x08: sprintf(mnemonic, "fetoxm1"); break; - case 0x09: sprintf(mnemonic, "ftanh1"); break; - case 0x0a: sprintf(mnemonic, "fatan"); break; - case 0x0c: sprintf(mnemonic, "fasin"); break; - case 0x0d: sprintf(mnemonic, "fatanh"); break; - case 0x0e: sprintf(mnemonic, "fsin"); break; - case 0x0f: sprintf(mnemonic, "ftan"); break; - case 0x10: sprintf(mnemonic, "fetox"); break; - case 0x11: sprintf(mnemonic, "ftwotox"); break; - case 0x12: sprintf(mnemonic, "ftentox"); break; - case 0x14: sprintf(mnemonic, "flogn"); break; - case 0x15: sprintf(mnemonic, "flog10"); break; - case 0x16: sprintf(mnemonic, "flog2"); break; - case 0x18: sprintf(mnemonic, "fabs"); break; - case 0x19: sprintf(mnemonic, "fcosh"); break; - case 0x1a: sprintf(mnemonic, "fneg"); break; - case 0x1c: sprintf(mnemonic, "facos"); break; - case 0x1d: sprintf(mnemonic, "fcos"); break; - case 0x1e: sprintf(mnemonic, "fgetexp"); break; - case 0x1f: sprintf(mnemonic, "fgetman"); break; - case 0x20: sprintf(mnemonic, "fdiv"); break; - case 0x21: sprintf(mnemonic, "fmod"); break; - case 0x22: sprintf(mnemonic, "fadd"); break; - case 0x23: sprintf(mnemonic, "fmul"); break; - case 0x24: sprintf(mnemonic, "fsgldiv"); break; - case 0x25: sprintf(mnemonic, "frem"); break; - case 0x26: sprintf(mnemonic, "fscale"); break; - case 0x27: sprintf(mnemonic, "fsglmul"); break; - case 0x28: sprintf(mnemonic, "fsub"); break; - case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37: - sprintf(mnemonic, "fsincos"); break; - case 0x38: sprintf(mnemonic, "fcmp"); break; - case 0x3a: sprintf(mnemonic, "ftst"); break; - case 0x41: sprintf(mnemonic, "fssqrt"); break; - case 0x45: sprintf(mnemonic, "fdsqrt"); break; - case 0x58: sprintf(mnemonic, "fsabs"); break; - case 0x5a: sprintf(mnemonic, "fsneg"); break; - case 0x5c: sprintf(mnemonic, "fdabs"); break; - case 0x5e: sprintf(mnemonic, "fdneg"); break; - case 0x60: sprintf(mnemonic, "fsdiv"); break; - case 0x62: sprintf(mnemonic, "fsadd"); break; - case 0x63: sprintf(mnemonic, "fsmul"); break; - case 0x64: sprintf(mnemonic, "fddiv"); break; - case 0x66: sprintf(mnemonic, "fdadd"); break; - case 0x67: sprintf(mnemonic, "fdmul"); break; - case 0x68: sprintf(mnemonic, "fssub"); break; - case 0x6c: sprintf(mnemonic, "fdsub"); break; - - default: sprintf(mnemonic, "FPU (?)"); break; - } - - if (w2 & 0x4000) - { - sprintf(g_dasm_str, "%s%s %s, FP%d", mnemonic, float_data_format[src], get_ea_mode_str_32(g_cpu_ir), dst_reg); - } - else - { - sprintf(g_dasm_str, "%s.x FP%d, FP%d", mnemonic, src, dst_reg); - } - break; - } - - case 0x3: - { - switch ((w2>>10)&7) - { - case 3: // packed decimal w/fixed k-factor - sprintf(g_dasm_str, "fmove%s FP%d, %s {#%d}", float_data_format[(w2>>10)&7], dst_reg, get_ea_mode_str_32(g_cpu_ir), sext_7bit_int(w2&0x7f)); - break; - - case 7: // packed decimal w/dynamic k-factor (register) - sprintf(g_dasm_str, "fmove%s FP%d, %s {D%d}", float_data_format[(w2>>10)&7], dst_reg, get_ea_mode_str_32(g_cpu_ir), (w2>>4)&7); - break; - - default: - sprintf(g_dasm_str, "fmove%s FP%d, %s", float_data_format[(w2>>10)&7], dst_reg, get_ea_mode_str_32(g_cpu_ir)); - break; - } - break; - } - - case 0x4: // ea to control - { - sprintf(g_dasm_str, "fmovem.l %s, ", get_ea_mode_str_32(g_cpu_ir)); - if (w2 & 0x1000) strcat(g_dasm_str, "fpcr"); - if (w2 & 0x0800) strcat(g_dasm_str, "/fpsr"); - if (w2 & 0x0400) strcat(g_dasm_str, "/fpiar"); - break; - } - - case 0x5: // control to ea - { - - strcpy(g_dasm_str, "fmovem.l "); - if (w2 & 0x1000) strcat(g_dasm_str, "fpcr"); - if (w2 & 0x0800) strcat(g_dasm_str, "/fpsr"); - if (w2 & 0x0400) strcat(g_dasm_str, "/fpiar"); - strcat(g_dasm_str, ", "); - strcat(g_dasm_str, get_ea_mode_str_32(g_cpu_ir)); - break; - } - - case 0x6: // memory to FPU, list - { - char temp[32]; - - if ((w2>>11) & 1) // dynamic register list - { - sprintf(g_dasm_str, "fmovem.x %s, D%d", get_ea_mode_str_32(g_cpu_ir), (w2>>4)&7); - } - else // static register list - { - int i; - - sprintf(g_dasm_str, "fmovem.x %s, ", get_ea_mode_str_32(g_cpu_ir)); - - for (i = 0; i < 8; i++) - { - if (w2 & (1<>12) & 1) // postincrement or control - { - sprintf(temp, "FP%d ", 7-i); - } - else // predecrement - { - sprintf(temp, "FP%d ", i); - } - strcat(g_dasm_str, temp); - } - } - } - break; - } - - case 0x7: // FPU to memory, list - { - char temp[32]; - - if ((w2>>11) & 1) // dynamic register list - { - sprintf(g_dasm_str, "fmovem.x D%d, %s", (w2>>4)&7, get_ea_mode_str_32(g_cpu_ir)); - } - else // static register list - { - int i; - - sprintf(g_dasm_str, "fmovem.x "); - - for (i = 0; i < 8; i++) - { - if (w2 & (1<>12) & 1) // postincrement or control - { - sprintf(temp, "FP%d ", 7-i); - } - else // predecrement - { - sprintf(temp, "FP%d ", i); - } - strcat(g_dasm_str, temp); - } - } - - strcat(g_dasm_str, ", "); - strcat(g_dasm_str, get_ea_mode_str_32(g_cpu_ir)); - } - break; - } - - default: - { - sprintf(g_dasm_str, "FPU (?) "); - break; - } - } -} - -static void d68000_jmp(void) -{ - sprintf(g_dasm_str, "jmp %s", get_ea_mode_str_32(g_cpu_ir)); -} - -static void d68000_jsr(void) -{ - sprintf(g_dasm_str, "jsr %s", get_ea_mode_str_32(g_cpu_ir)); - SET_OPCODE_FLAGS(DASMFLAG_STEP_OVER); -} - -static void d68000_lea(void) -{ - sprintf(g_dasm_str, "lea %s, A%d", get_ea_mode_str_32(g_cpu_ir), (g_cpu_ir>>9)&7); -} - -static void d68000_link_16(void) -{ - sprintf(g_dasm_str, "link A%d, %s", g_cpu_ir&7, get_imm_str_s16()); -} - -static void d68020_link_32(void) -{ - LIMIT_CPU_TYPES(M68020_PLUS); - sprintf(g_dasm_str, "link A%d, %s; (2+)", g_cpu_ir&7, get_imm_str_s32()); -} - -static void d68000_lsr_s_8(void) -{ - sprintf(g_dasm_str, "lsr.b #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); -} - -static void d68000_lsr_s_16(void) -{ - sprintf(g_dasm_str, "lsr.w #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); -} - -static void d68000_lsr_s_32(void) -{ - sprintf(g_dasm_str, "lsr.l #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); -} - -static void d68000_lsr_r_8(void) -{ - sprintf(g_dasm_str, "lsr.b D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); -} - -static void d68000_lsr_r_16(void) -{ - sprintf(g_dasm_str, "lsr.w D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); -} - -static void d68000_lsr_r_32(void) -{ - sprintf(g_dasm_str, "lsr.l D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); -} - -static void d68000_lsr_ea(void) -{ - sprintf(g_dasm_str, "lsr.w %s", get_ea_mode_str_32(g_cpu_ir)); -} - -static void d68000_lsl_s_8(void) -{ - sprintf(g_dasm_str, "lsl.b #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); -} - -static void d68000_lsl_s_16(void) -{ - sprintf(g_dasm_str, "lsl.w #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); -} - -static void d68000_lsl_s_32(void) -{ - sprintf(g_dasm_str, "lsl.l #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); -} - -static void d68000_lsl_r_8(void) -{ - sprintf(g_dasm_str, "lsl.b D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); -} - -static void d68000_lsl_r_16(void) -{ - sprintf(g_dasm_str, "lsl.w D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); -} - -static void d68000_lsl_r_32(void) -{ - sprintf(g_dasm_str, "lsl.l D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); -} - -static void d68000_lsl_ea(void) -{ - sprintf(g_dasm_str, "lsl.w %s", get_ea_mode_str_32(g_cpu_ir)); -} - -static void d68000_move_8(void) -{ - char* str = get_ea_mode_str_8(g_cpu_ir); - sprintf(g_dasm_str, "move.b %s, %s", str, get_ea_mode_str_8(((g_cpu_ir>>9) & 7) | ((g_cpu_ir>>3) & 0x38))); -} - -static void d68000_move_16(void) -{ - char* str = get_ea_mode_str_16(g_cpu_ir); - sprintf(g_dasm_str, "move.w %s, %s", str, get_ea_mode_str_16(((g_cpu_ir>>9) & 7) | ((g_cpu_ir>>3) & 0x38))); -} - -static void d68000_move_32(void) -{ - char* str = get_ea_mode_str_32(g_cpu_ir); - sprintf(g_dasm_str, "move.l %s, %s", str, get_ea_mode_str_32(((g_cpu_ir>>9) & 7) | ((g_cpu_ir>>3) & 0x38))); -} - -static void d68000_movea_16(void) -{ - sprintf(g_dasm_str, "movea.w %s, A%d", get_ea_mode_str_16(g_cpu_ir), (g_cpu_ir>>9)&7); -} - -static void d68000_movea_32(void) -{ - sprintf(g_dasm_str, "movea.l %s, A%d", get_ea_mode_str_32(g_cpu_ir), (g_cpu_ir>>9)&7); -} - -static void d68000_move_to_ccr(void) -{ - sprintf(g_dasm_str, "move %s, CCR", get_ea_mode_str_8(g_cpu_ir)); -} - -static void d68010_move_fr_ccr(void) -{ - LIMIT_CPU_TYPES(M68010_PLUS); - sprintf(g_dasm_str, "move CCR, %s; (1+)", get_ea_mode_str_8(g_cpu_ir)); -} - -static void d68000_move_fr_sr(void) -{ - sprintf(g_dasm_str, "move SR, %s", get_ea_mode_str_16(g_cpu_ir)); -} - -static void d68000_move_to_sr(void) -{ - sprintf(g_dasm_str, "move %s, SR", get_ea_mode_str_16(g_cpu_ir)); -} - -static void d68000_move_fr_usp(void) -{ - sprintf(g_dasm_str, "move USP, A%d", g_cpu_ir&7); -} - -static void d68000_move_to_usp(void) -{ - sprintf(g_dasm_str, "move A%d, USP", g_cpu_ir&7); -} - -static void d68010_movec(void) -{ - uint extension; - char* reg_name; - char* processor; - LIMIT_CPU_TYPES(M68010_PLUS); - extension = read_imm_16(); - - switch(extension & 0xfff) - { - case 0x000: - reg_name = "SFC"; - processor = "1+"; - break; - case 0x001: - reg_name = "DFC"; - processor = "1+"; - break; - case 0x800: - reg_name = "USP"; - processor = "1+"; - break; - case 0x801: - reg_name = "VBR"; - processor = "1+"; - break; - case 0x002: - reg_name = "CACR"; - processor = "2+"; - break; - case 0x802: - reg_name = "CAAR"; - processor = "2,3"; - break; - case 0x803: - reg_name = "MSP"; - processor = "2+"; - break; - case 0x804: - reg_name = "ISP"; - processor = "2+"; - break; - case 0x003: - reg_name = "TC"; - processor = "4+"; - break; - case 0x004: - reg_name = "ITT0"; - processor = "4+"; - break; - case 0x005: - reg_name = "ITT1"; - processor = "4+"; - break; - case 0x006: - reg_name = "DTT0"; - processor = "4+"; - break; - case 0x007: - reg_name = "DTT1"; - processor = "4+"; - break; - case 0x805: - reg_name = "MMUSR"; - processor = "4+"; - break; - case 0x806: - reg_name = "URP"; - processor = "4+"; - break; - case 0x807: - reg_name = "SRP"; - processor = "4+"; - break; - default: - reg_name = make_signed_hex_str_16(extension & 0xfff); - processor = "?"; - } - - if(BIT_0(g_cpu_ir)) - sprintf(g_dasm_str, "movec %c%d, %s; (%s)", BIT_F(extension) ? 'A' : 'D', (extension>>12)&7, reg_name, processor); - else - sprintf(g_dasm_str, "movec %s, %c%d; (%s)", reg_name, BIT_F(extension) ? 'A' : 'D', (extension>>12)&7, processor); -} - -static void d68000_movem_pd_16(void) -{ - uint data = read_imm_16(); - char buffer[40]; - uint first; - uint run_length; - uint i; - - buffer[0] = 0; - for(i=0;i<8;i++) - { - if(data&(1<<(15-i))) - { - first = i; - run_length = 0; - while(i<7 && (data&(1<<(15-(i+1))))) - { - i++; - run_length++; - } - if(buffer[0] != 0) - strcat(buffer, "/"); - sprintf(buffer+strlen(buffer), "D%d", first); - if(run_length > 0) - sprintf(buffer+strlen(buffer), "-D%d", first + run_length); - } - } - for(i=0;i<8;i++) - { - if(data&(1<<(7-i))) - { - first = i; - run_length = 0; - while(i<7 && (data&(1<<(7-(i+1))))) - { - i++; - run_length++; - } - if(buffer[0] != 0) - strcat(buffer, "/"); - sprintf(buffer+strlen(buffer), "A%d", first); - if(run_length > 0) - sprintf(buffer+strlen(buffer), "-A%d", first + run_length); - } - } - sprintf(g_dasm_str, "movem.w %s, %s", buffer, get_ea_mode_str_16(g_cpu_ir)); -} - -static void d68000_movem_pd_32(void) -{ - uint data = read_imm_16(); - char buffer[40]; - uint first; - uint run_length; - uint i; - - buffer[0] = 0; - for(i=0;i<8;i++) - { - if(data&(1<<(15-i))) - { - first = i; - run_length = 0; - while(i<7 && (data&(1<<(15-(i+1))))) - { - i++; - run_length++; - } - if(buffer[0] != 0) - strcat(buffer, "/"); - sprintf(buffer+strlen(buffer), "D%d", first); - if(run_length > 0) - sprintf(buffer+strlen(buffer), "-D%d", first + run_length); - } - } - for(i=0;i<8;i++) - { - if(data&(1<<(7-i))) - { - first = i; - run_length = 0; - while(i<7 && (data&(1<<(7-(i+1))))) - { - i++; - run_length++; - } - if(buffer[0] != 0) - strcat(buffer, "/"); - sprintf(buffer+strlen(buffer), "A%d", first); - if(run_length > 0) - sprintf(buffer+strlen(buffer), "-A%d", first + run_length); - } - } - sprintf(g_dasm_str, "movem.l %s, %s", buffer, get_ea_mode_str_32(g_cpu_ir)); -} - -static void d68000_movem_er_16(void) -{ - uint data = read_imm_16(); - char buffer[40]; - uint first; - uint run_length; - uint i; - - buffer[0] = 0; - for(i=0;i<8;i++) - { - if(data&(1< 0) - sprintf(buffer+strlen(buffer), "-D%d", first + run_length); - } - } - for(i=0;i<8;i++) - { - if(data&(1<<(i+8))) - { - first = i; - run_length = 0; - while(i<7 && (data&(1<<(i+8+1)))) - { - i++; - run_length++; - } - if(buffer[0] != 0) - strcat(buffer, "/"); - sprintf(buffer+strlen(buffer), "A%d", first); - if(run_length > 0) - sprintf(buffer+strlen(buffer), "-A%d", first + run_length); - } - } - sprintf(g_dasm_str, "movem.w %s, %s", get_ea_mode_str_16(g_cpu_ir), buffer); -} - -static void d68000_movem_er_32(void) -{ - uint data = read_imm_16(); - char buffer[40]; - uint first; - uint run_length; - uint i; - - buffer[0] = 0; - for(i=0;i<8;i++) - { - if(data&(1< 0) - sprintf(buffer+strlen(buffer), "-D%d", first + run_length); - } - } - for(i=0;i<8;i++) - { - if(data&(1<<(i+8))) - { - first = i; - run_length = 0; - while(i<7 && (data&(1<<(i+8+1)))) - { - i++; - run_length++; - } - if(buffer[0] != 0) - strcat(buffer, "/"); - sprintf(buffer+strlen(buffer), "A%d", first); - if(run_length > 0) - sprintf(buffer+strlen(buffer), "-A%d", first + run_length); - } - } - sprintf(g_dasm_str, "movem.l %s, %s", get_ea_mode_str_32(g_cpu_ir), buffer); -} - -static void d68000_movem_re_16(void) -{ - uint data = read_imm_16(); - char buffer[40]; - uint first; - uint run_length; - uint i; - - buffer[0] = 0; - for(i=0;i<8;i++) - { - if(data&(1< 0) - sprintf(buffer+strlen(buffer), "-D%d", first + run_length); - } - } - for(i=0;i<8;i++) - { - if(data&(1<<(i+8))) - { - first = i; - run_length = 0; - while(i<7 && (data&(1<<(i+8+1)))) - { - i++; - run_length++; - } - if(buffer[0] != 0) - strcat(buffer, "/"); - sprintf(buffer+strlen(buffer), "A%d", first); - if(run_length > 0) - sprintf(buffer+strlen(buffer), "-A%d", first + run_length); - } - } - sprintf(g_dasm_str, "movem.w %s, %s", buffer, get_ea_mode_str_16(g_cpu_ir)); -} - -static void d68000_movem_re_32(void) -{ - uint data = read_imm_16(); - char buffer[40]; - uint first; - uint run_length; - uint i; - - buffer[0] = 0; - for(i=0;i<8;i++) - { - if(data&(1< 0) - sprintf(buffer+strlen(buffer), "-D%d", first + run_length); - } - } - for(i=0;i<8;i++) - { - if(data&(1<<(i+8))) - { - first = i; - run_length = 0; - while(i<7 && (data&(1<<(i+8+1)))) - { - i++; - run_length++; - } - if(buffer[0] != 0) - strcat(buffer, "/"); - sprintf(buffer+strlen(buffer), "A%d", first); - if(run_length > 0) - sprintf(buffer+strlen(buffer), "-A%d", first + run_length); - } - } - sprintf(g_dasm_str, "movem.l %s, %s", buffer, get_ea_mode_str_32(g_cpu_ir)); -} - -static void d68000_movep_re_16(void) -{ - sprintf(g_dasm_str, "movep.w D%d, ($%x,A%d)", (g_cpu_ir>>9)&7, read_imm_16(), g_cpu_ir&7); -} - -static void d68000_movep_re_32(void) -{ - sprintf(g_dasm_str, "movep.l D%d, ($%x,A%d)", (g_cpu_ir>>9)&7, read_imm_16(), g_cpu_ir&7); -} - -static void d68000_movep_er_16(void) -{ - sprintf(g_dasm_str, "movep.w ($%x,A%d), D%d", read_imm_16(), g_cpu_ir&7, (g_cpu_ir>>9)&7); -} - -static void d68000_movep_er_32(void) -{ - sprintf(g_dasm_str, "movep.l ($%x,A%d), D%d", read_imm_16(), g_cpu_ir&7, (g_cpu_ir>>9)&7); -} - -static void d68010_moves_8(void) -{ - uint extension; - LIMIT_CPU_TYPES(M68010_PLUS); - extension = read_imm_16(); - if(BIT_B(extension)) - sprintf(g_dasm_str, "moves.b %c%d, %s; (1+)", BIT_F(extension) ? 'A' : 'D', (extension>>12)&7, get_ea_mode_str_8(g_cpu_ir)); - else - sprintf(g_dasm_str, "moves.b %s, %c%d; (1+)", get_ea_mode_str_8(g_cpu_ir), BIT_F(extension) ? 'A' : 'D', (extension>>12)&7); -} - -static void d68010_moves_16(void) -{ - uint extension; - LIMIT_CPU_TYPES(M68010_PLUS); - extension = read_imm_16(); - if(BIT_B(extension)) - sprintf(g_dasm_str, "moves.w %c%d, %s; (1+)", BIT_F(extension) ? 'A' : 'D', (extension>>12)&7, get_ea_mode_str_16(g_cpu_ir)); - else - sprintf(g_dasm_str, "moves.w %s, %c%d; (1+)", get_ea_mode_str_16(g_cpu_ir), BIT_F(extension) ? 'A' : 'D', (extension>>12)&7); -} - -static void d68010_moves_32(void) -{ - uint extension; - LIMIT_CPU_TYPES(M68010_PLUS); - extension = read_imm_16(); - if(BIT_B(extension)) - sprintf(g_dasm_str, "moves.l %c%d, %s; (1+)", BIT_F(extension) ? 'A' : 'D', (extension>>12)&7, get_ea_mode_str_32(g_cpu_ir)); - else - sprintf(g_dasm_str, "moves.l %s, %c%d; (1+)", get_ea_mode_str_32(g_cpu_ir), BIT_F(extension) ? 'A' : 'D', (extension>>12)&7); -} - -static void d68000_moveq(void) -{ - sprintf(g_dasm_str, "moveq #%s, D%d", make_signed_hex_str_8(g_cpu_ir), (g_cpu_ir>>9)&7); -} - -static void d68040_move16_pi_pi(void) -{ - LIMIT_CPU_TYPES(M68040_PLUS); - sprintf(g_dasm_str, "move16 (A%d)+, (A%d)+; (4)", g_cpu_ir&7, (read_imm_16()>>12)&7); -} - -static void d68040_move16_pi_al(void) -{ - LIMIT_CPU_TYPES(M68040_PLUS); - sprintf(g_dasm_str, "move16 (A%d)+, %s; (4)", g_cpu_ir&7, get_imm_str_u32()); -} - -static void d68040_move16_al_pi(void) -{ - LIMIT_CPU_TYPES(M68040_PLUS); - sprintf(g_dasm_str, "move16 %s, (A%d)+; (4)", get_imm_str_u32(), g_cpu_ir&7); -} - -static void d68040_move16_ai_al(void) -{ - LIMIT_CPU_TYPES(M68040_PLUS); - sprintf(g_dasm_str, "move16 (A%d), %s; (4)", g_cpu_ir&7, get_imm_str_u32()); -} - -static void d68040_move16_al_ai(void) -{ - LIMIT_CPU_TYPES(M68040_PLUS); - sprintf(g_dasm_str, "move16 %s, (A%d); (4)", get_imm_str_u32(), g_cpu_ir&7); -} - -static void d68000_muls(void) -{ - sprintf(g_dasm_str, "muls.w %s, D%d", get_ea_mode_str_16(g_cpu_ir), (g_cpu_ir>>9)&7); -} - -static void d68000_mulu(void) -{ - sprintf(g_dasm_str, "mulu.w %s, D%d", get_ea_mode_str_16(g_cpu_ir), (g_cpu_ir>>9)&7); -} - -static void d68020_mull(void) -{ - uint extension; - LIMIT_CPU_TYPES(M68020_PLUS); - extension = read_imm_16(); - - if(BIT_A(extension)) - sprintf(g_dasm_str, "mul%c.l %s, D%d:D%d; (2+)", BIT_B(extension) ? 's' : 'u', get_ea_mode_str_32(g_cpu_ir), extension&7, (extension>>12)&7); - else - sprintf(g_dasm_str, "mul%c.l %s, D%d; (2+)", BIT_B(extension) ? 's' : 'u', get_ea_mode_str_32(g_cpu_ir), (extension>>12)&7); -} - -static void d68000_nbcd(void) -{ - sprintf(g_dasm_str, "nbcd %s", get_ea_mode_str_8(g_cpu_ir)); -} - -static void d68000_neg_8(void) -{ - sprintf(g_dasm_str, "neg.b %s", get_ea_mode_str_8(g_cpu_ir)); -} - -static void d68000_neg_16(void) -{ - sprintf(g_dasm_str, "neg.w %s", get_ea_mode_str_16(g_cpu_ir)); -} - -static void d68000_neg_32(void) -{ - sprintf(g_dasm_str, "neg.l %s", get_ea_mode_str_32(g_cpu_ir)); -} - -static void d68000_negx_8(void) -{ - sprintf(g_dasm_str, "negx.b %s", get_ea_mode_str_8(g_cpu_ir)); -} - -static void d68000_negx_16(void) -{ - sprintf(g_dasm_str, "negx.w %s", get_ea_mode_str_16(g_cpu_ir)); -} - -static void d68000_negx_32(void) -{ - sprintf(g_dasm_str, "negx.l %s", get_ea_mode_str_32(g_cpu_ir)); -} - -static void d68000_nop(void) -{ - sprintf(g_dasm_str, "nop"); -} - -static void d68000_not_8(void) -{ - sprintf(g_dasm_str, "not.b %s", get_ea_mode_str_8(g_cpu_ir)); -} - -static void d68000_not_16(void) -{ - sprintf(g_dasm_str, "not.w %s", get_ea_mode_str_16(g_cpu_ir)); -} - -static void d68000_not_32(void) -{ - sprintf(g_dasm_str, "not.l %s", get_ea_mode_str_32(g_cpu_ir)); -} - -static void d68000_or_er_8(void) -{ - sprintf(g_dasm_str, "or.b %s, D%d", get_ea_mode_str_8(g_cpu_ir), (g_cpu_ir>>9)&7); -} - -static void d68000_or_er_16(void) -{ - sprintf(g_dasm_str, "or.w %s, D%d", get_ea_mode_str_16(g_cpu_ir), (g_cpu_ir>>9)&7); -} - -static void d68000_or_er_32(void) -{ - sprintf(g_dasm_str, "or.l %s, D%d", get_ea_mode_str_32(g_cpu_ir), (g_cpu_ir>>9)&7); -} - -static void d68000_or_re_8(void) -{ - sprintf(g_dasm_str, "or.b D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_8(g_cpu_ir)); -} - -static void d68000_or_re_16(void) -{ - sprintf(g_dasm_str, "or.w D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_16(g_cpu_ir)); -} - -static void d68000_or_re_32(void) -{ - sprintf(g_dasm_str, "or.l D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_32(g_cpu_ir)); -} - -static void d68000_ori_8(void) -{ - char* str = get_imm_str_u8(); - sprintf(g_dasm_str, "ori.b %s, %s", str, get_ea_mode_str_8(g_cpu_ir)); -} - -static void d68000_ori_16(void) -{ - char* str = get_imm_str_u16(); - sprintf(g_dasm_str, "ori.w %s, %s", str, get_ea_mode_str_16(g_cpu_ir)); -} - -static void d68000_ori_32(void) -{ - char* str = get_imm_str_u32(); - sprintf(g_dasm_str, "ori.l %s, %s", str, get_ea_mode_str_32(g_cpu_ir)); -} - -static void d68000_ori_to_ccr(void) -{ - sprintf(g_dasm_str, "ori %s, CCR", get_imm_str_u8()); -} - -static void d68000_ori_to_sr(void) -{ - sprintf(g_dasm_str, "ori %s, SR", get_imm_str_u16()); -} - -static void d68020_pack_rr(void) -{ - LIMIT_CPU_TYPES(M68020_PLUS); - sprintf(g_dasm_str, "pack D%d, D%d, %s; (2+)", g_cpu_ir&7, (g_cpu_ir>>9)&7, get_imm_str_u16()); -} - -static void d68020_pack_mm(void) -{ - LIMIT_CPU_TYPES(M68020_PLUS); - sprintf(g_dasm_str, "pack -(A%d), -(A%d), %s; (2+)", g_cpu_ir&7, (g_cpu_ir>>9)&7, get_imm_str_u16()); -} - -static void d68000_pea(void) -{ - sprintf(g_dasm_str, "pea %s", get_ea_mode_str_32(g_cpu_ir)); -} - -// this is a 68040-specific form of PFLUSH -static void d68040_pflush(void) -{ - LIMIT_CPU_TYPES(M68040_PLUS); - - if (g_cpu_ir & 0x10) - { - sprintf(g_dasm_str, "pflusha%s", (g_cpu_ir & 8) ? "" : "n"); - } - else - { - sprintf(g_dasm_str, "pflush%s(A%d)", (g_cpu_ir & 8) ? "" : "n", g_cpu_ir & 7); - } -} - -static void d68000_reset(void) -{ - sprintf(g_dasm_str, "reset"); -} - -static void d68000_ror_s_8(void) -{ - sprintf(g_dasm_str, "ror.b #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); -} - -static void d68000_ror_s_16(void) -{ - sprintf(g_dasm_str, "ror.w #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7],g_cpu_ir&7); -} - -static void d68000_ror_s_32(void) -{ - sprintf(g_dasm_str, "ror.l #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); -} - -static void d68000_ror_r_8(void) -{ - sprintf(g_dasm_str, "ror.b D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); -} - -static void d68000_ror_r_16(void) -{ - sprintf(g_dasm_str, "ror.w D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); -} - -static void d68000_ror_r_32(void) -{ - sprintf(g_dasm_str, "ror.l D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); -} - -static void d68000_ror_ea(void) -{ - sprintf(g_dasm_str, "ror.w %s", get_ea_mode_str_32(g_cpu_ir)); -} - -static void d68000_rol_s_8(void) -{ - sprintf(g_dasm_str, "rol.b #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); -} - -static void d68000_rol_s_16(void) -{ - sprintf(g_dasm_str, "rol.w #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); -} - -static void d68000_rol_s_32(void) -{ - sprintf(g_dasm_str, "rol.l #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); -} - -static void d68000_rol_r_8(void) -{ - sprintf(g_dasm_str, "rol.b D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); -} - -static void d68000_rol_r_16(void) -{ - sprintf(g_dasm_str, "rol.w D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); -} - -static void d68000_rol_r_32(void) -{ - sprintf(g_dasm_str, "rol.l D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); -} - -static void d68000_rol_ea(void) -{ - sprintf(g_dasm_str, "rol.w %s", get_ea_mode_str_32(g_cpu_ir)); -} - -static void d68000_roxr_s_8(void) -{ - sprintf(g_dasm_str, "roxr.b #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); -} - -static void d68000_roxr_s_16(void) -{ - sprintf(g_dasm_str, "roxr.w #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); -} - - -static void d68000_roxr_s_32(void) -{ - sprintf(g_dasm_str, "roxr.l #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); -} - -static void d68000_roxr_r_8(void) -{ - sprintf(g_dasm_str, "roxr.b D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); -} - -static void d68000_roxr_r_16(void) -{ - sprintf(g_dasm_str, "roxr.w D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); -} - -static void d68000_roxr_r_32(void) -{ - sprintf(g_dasm_str, "roxr.l D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); -} - -static void d68000_roxr_ea(void) -{ - sprintf(g_dasm_str, "roxr.w %s", get_ea_mode_str_32(g_cpu_ir)); -} - -static void d68000_roxl_s_8(void) -{ - sprintf(g_dasm_str, "roxl.b #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); -} - -static void d68000_roxl_s_16(void) -{ - sprintf(g_dasm_str, "roxl.w #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); -} - -static void d68000_roxl_s_32(void) -{ - sprintf(g_dasm_str, "roxl.l #%d, D%d", g_3bit_qdata_table[(g_cpu_ir>>9)&7], g_cpu_ir&7); -} - -static void d68000_roxl_r_8(void) -{ - sprintf(g_dasm_str, "roxl.b D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); -} - -static void d68000_roxl_r_16(void) -{ - sprintf(g_dasm_str, "roxl.w D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); -} - -static void d68000_roxl_r_32(void) -{ - sprintf(g_dasm_str, "roxl.l D%d, D%d", (g_cpu_ir>>9)&7, g_cpu_ir&7); -} - -static void d68000_roxl_ea(void) -{ - sprintf(g_dasm_str, "roxl.w %s", get_ea_mode_str_32(g_cpu_ir)); -} - -static void d68010_rtd(void) -{ - LIMIT_CPU_TYPES(M68010_PLUS); - sprintf(g_dasm_str, "rtd %s; (1+)", get_imm_str_s16()); - SET_OPCODE_FLAGS(DASMFLAG_STEP_OUT); -} - -static void d68000_rte(void) -{ - sprintf(g_dasm_str, "rte"); - SET_OPCODE_FLAGS(DASMFLAG_STEP_OUT); -} - -static void d68020_rtm(void) -{ - LIMIT_CPU_TYPES(M68020_ONLY); - sprintf(g_dasm_str, "rtm %c%d; (2+)", BIT_3(g_cpu_ir) ? 'A' : 'D', g_cpu_ir&7); - SET_OPCODE_FLAGS(DASMFLAG_STEP_OUT); -} - -static void d68000_rtr(void) -{ - sprintf(g_dasm_str, "rtr"); - SET_OPCODE_FLAGS(DASMFLAG_STEP_OUT); -} - -static void d68000_rts(void) -{ - sprintf(g_dasm_str, "rts"); - SET_OPCODE_FLAGS(DASMFLAG_STEP_OUT); -} - -static void d68000_sbcd_rr(void) -{ - sprintf(g_dasm_str, "sbcd D%d, D%d", g_cpu_ir&7, (g_cpu_ir>>9)&7); -} - -static void d68000_sbcd_mm(void) -{ - sprintf(g_dasm_str, "sbcd -(A%d), -(A%d)", g_cpu_ir&7, (g_cpu_ir>>9)&7); -} - -static void d68000_scc(void) -{ - sprintf(g_dasm_str, "s%-2s %s", g_cc[(g_cpu_ir>>8)&0xf], get_ea_mode_str_8(g_cpu_ir)); -} - -static void d68000_stop(void) -{ - sprintf(g_dasm_str, "stop %s", get_imm_str_s16()); -} - -static void d68000_sub_er_8(void) -{ - sprintf(g_dasm_str, "sub.b %s, D%d", get_ea_mode_str_8(g_cpu_ir), (g_cpu_ir>>9)&7); -} - -static void d68000_sub_er_16(void) -{ - sprintf(g_dasm_str, "sub.w %s, D%d", get_ea_mode_str_16(g_cpu_ir), (g_cpu_ir>>9)&7); -} - -static void d68000_sub_er_32(void) -{ - sprintf(g_dasm_str, "sub.l %s, D%d", get_ea_mode_str_32(g_cpu_ir), (g_cpu_ir>>9)&7); -} - -static void d68000_sub_re_8(void) -{ - sprintf(g_dasm_str, "sub.b D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_8(g_cpu_ir)); -} - -static void d68000_sub_re_16(void) -{ - sprintf(g_dasm_str, "sub.w D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_16(g_cpu_ir)); -} - -static void d68000_sub_re_32(void) -{ - sprintf(g_dasm_str, "sub.l D%d, %s", (g_cpu_ir>>9)&7, get_ea_mode_str_32(g_cpu_ir)); -} - -static void d68000_suba_16(void) -{ - sprintf(g_dasm_str, "suba.w %s, A%d", get_ea_mode_str_16(g_cpu_ir), (g_cpu_ir>>9)&7); -} - -static void d68000_suba_32(void) -{ - sprintf(g_dasm_str, "suba.l %s, A%d", get_ea_mode_str_32(g_cpu_ir), (g_cpu_ir>>9)&7); -} - -static void d68000_subi_8(void) -{ - char* str = get_imm_str_s8(); - sprintf(g_dasm_str, "subi.b %s, %s", str, get_ea_mode_str_8(g_cpu_ir)); -} - -static void d68000_subi_16(void) -{ - char* str = get_imm_str_s16(); - sprintf(g_dasm_str, "subi.w %s, %s", str, get_ea_mode_str_16(g_cpu_ir)); -} - -static void d68000_subi_32(void) -{ - char* str = get_imm_str_s32(); - sprintf(g_dasm_str, "subi.l %s, %s", str, get_ea_mode_str_32(g_cpu_ir)); -} - -static void d68000_subq_8(void) -{ - sprintf(g_dasm_str, "subq.b #%d, %s", g_3bit_qdata_table[(g_cpu_ir>>9)&7], get_ea_mode_str_8(g_cpu_ir)); -} - -static void d68000_subq_16(void) -{ - sprintf(g_dasm_str, "subq.w #%d, %s", g_3bit_qdata_table[(g_cpu_ir>>9)&7], get_ea_mode_str_16(g_cpu_ir)); -} - -static void d68000_subq_32(void) -{ - sprintf(g_dasm_str, "subq.l #%d, %s", g_3bit_qdata_table[(g_cpu_ir>>9)&7], get_ea_mode_str_32(g_cpu_ir)); -} - -static void d68000_subx_rr_8(void) -{ - sprintf(g_dasm_str, "subx.b D%d, D%d", g_cpu_ir&7, (g_cpu_ir>>9)&7); -} - -static void d68000_subx_rr_16(void) -{ - sprintf(g_dasm_str, "subx.w D%d, D%d", g_cpu_ir&7, (g_cpu_ir>>9)&7); -} - -static void d68000_subx_rr_32(void) -{ - sprintf(g_dasm_str, "subx.l D%d, D%d", g_cpu_ir&7, (g_cpu_ir>>9)&7); -} - -static void d68000_subx_mm_8(void) -{ - sprintf(g_dasm_str, "subx.b -(A%d), -(A%d)", g_cpu_ir&7, (g_cpu_ir>>9)&7); -} - -static void d68000_subx_mm_16(void) -{ - sprintf(g_dasm_str, "subx.w -(A%d), -(A%d)", g_cpu_ir&7, (g_cpu_ir>>9)&7); -} - -static void d68000_subx_mm_32(void) -{ - sprintf(g_dasm_str, "subx.l -(A%d), -(A%d)", g_cpu_ir&7, (g_cpu_ir>>9)&7); -} - -static void d68000_swap(void) -{ - sprintf(g_dasm_str, "swap D%d", g_cpu_ir&7); -} - -static void d68000_tas(void) -{ - sprintf(g_dasm_str, "tas %s", get_ea_mode_str_8(g_cpu_ir)); -} - -static void d68000_trap(void) -{ - sprintf(g_dasm_str, "trap #$%x", g_cpu_ir&0xf); -} - -static void d68020_trapcc_0(void) -{ - LIMIT_CPU_TYPES(M68020_PLUS); - sprintf(g_dasm_str, "trap%-2s; (2+)", g_cc[(g_cpu_ir>>8)&0xf]); - SET_OPCODE_FLAGS(DASMFLAG_STEP_OVER); -} - -static void d68020_trapcc_16(void) -{ - LIMIT_CPU_TYPES(M68020_PLUS); - sprintf(g_dasm_str, "trap%-2s %s; (2+)", g_cc[(g_cpu_ir>>8)&0xf], get_imm_str_u16()); - SET_OPCODE_FLAGS(DASMFLAG_STEP_OVER); -} - -static void d68020_trapcc_32(void) -{ - LIMIT_CPU_TYPES(M68020_PLUS); - sprintf(g_dasm_str, "trap%-2s %s; (2+)", g_cc[(g_cpu_ir>>8)&0xf], get_imm_str_u32()); - SET_OPCODE_FLAGS(DASMFLAG_STEP_OVER); -} - -static void d68000_trapv(void) -{ - sprintf(g_dasm_str, "trapv"); - SET_OPCODE_FLAGS(DASMFLAG_STEP_OVER); -} - -static void d68000_tst_8(void) -{ - sprintf(g_dasm_str, "tst.b %s", get_ea_mode_str_8(g_cpu_ir)); -} - -static void d68020_tst_pcdi_8(void) -{ - LIMIT_CPU_TYPES(M68020_PLUS); - sprintf(g_dasm_str, "tst.b %s; (2+)", get_ea_mode_str_8(g_cpu_ir)); -} - -static void d68020_tst_pcix_8(void) -{ - LIMIT_CPU_TYPES(M68020_PLUS); - sprintf(g_dasm_str, "tst.b %s; (2+)", get_ea_mode_str_8(g_cpu_ir)); -} - -static void d68020_tst_i_8(void) -{ - LIMIT_CPU_TYPES(M68020_PLUS); - sprintf(g_dasm_str, "tst.b %s; (2+)", get_ea_mode_str_8(g_cpu_ir)); -} - -static void d68000_tst_16(void) -{ - sprintf(g_dasm_str, "tst.w %s", get_ea_mode_str_16(g_cpu_ir)); -} - -static void d68020_tst_a_16(void) -{ - LIMIT_CPU_TYPES(M68020_PLUS); - sprintf(g_dasm_str, "tst.w %s; (2+)", get_ea_mode_str_16(g_cpu_ir)); -} - -static void d68020_tst_pcdi_16(void) -{ - LIMIT_CPU_TYPES(M68020_PLUS); - sprintf(g_dasm_str, "tst.w %s; (2+)", get_ea_mode_str_16(g_cpu_ir)); -} - -static void d68020_tst_pcix_16(void) -{ - LIMIT_CPU_TYPES(M68020_PLUS); - sprintf(g_dasm_str, "tst.w %s; (2+)", get_ea_mode_str_16(g_cpu_ir)); -} - -static void d68020_tst_i_16(void) -{ - LIMIT_CPU_TYPES(M68020_PLUS); - sprintf(g_dasm_str, "tst.w %s; (2+)", get_ea_mode_str_16(g_cpu_ir)); -} - -static void d68000_tst_32(void) -{ - sprintf(g_dasm_str, "tst.l %s", get_ea_mode_str_32(g_cpu_ir)); -} - -static void d68020_tst_a_32(void) -{ - LIMIT_CPU_TYPES(M68020_PLUS); - sprintf(g_dasm_str, "tst.l %s; (2+)", get_ea_mode_str_32(g_cpu_ir)); -} - -static void d68020_tst_pcdi_32(void) -{ - LIMIT_CPU_TYPES(M68020_PLUS); - sprintf(g_dasm_str, "tst.l %s; (2+)", get_ea_mode_str_32(g_cpu_ir)); -} - -static void d68020_tst_pcix_32(void) -{ - LIMIT_CPU_TYPES(M68020_PLUS); - sprintf(g_dasm_str, "tst.l %s; (2+)", get_ea_mode_str_32(g_cpu_ir)); -} - -static void d68020_tst_i_32(void) -{ - LIMIT_CPU_TYPES(M68020_PLUS); - sprintf(g_dasm_str, "tst.l %s; (2+)", get_ea_mode_str_32(g_cpu_ir)); -} - -static void d68000_unlk(void) -{ - sprintf(g_dasm_str, "unlk A%d", g_cpu_ir&7); -} - -static void d68020_unpk_rr(void) -{ - LIMIT_CPU_TYPES(M68020_PLUS); - sprintf(g_dasm_str, "unpk D%d, D%d, %s; (2+)", g_cpu_ir&7, (g_cpu_ir>>9)&7, get_imm_str_u16()); -} - -static void d68020_unpk_mm(void) -{ - LIMIT_CPU_TYPES(M68020_PLUS); - sprintf(g_dasm_str, "unpk -(A%d), -(A%d), %s; (2+)", g_cpu_ir&7, (g_cpu_ir>>9)&7, get_imm_str_u16()); -} - - -// PFLUSH: 001xxx0xxxxxxxxx -// PLOAD: 001000x0000xxxxx -// PVALID1: 0010100000000000 -// PVALID2: 0010110000000xxx -// PMOVE 1: 010xxxx000000000 -// PMOVE 2: 011xxxx0000xxx00 -// PMOVE 3: 011xxxx000000000 -// PTEST: 100xxxxxxxxxxxxx -// PFLUSHR: 1010000000000000 -static void d68851_p000(void) -{ - char* str; - uint modes = read_imm_16(); - - // do this after fetching the second PMOVE word so we properly get the 3rd if necessary - str = get_ea_mode_str_32(g_cpu_ir); - - if ((modes & 0xfde0) == 0x2000) // PLOAD - { - if (modes & 0x0200) - { - sprintf(g_dasm_str, "pload #%d, %s", (modes>>10)&7, str); - } - else - { - sprintf(g_dasm_str, "pload %s, #%d", str, (modes>>10)&7); - } - return; - } - - if ((modes & 0xe200) == 0x2000) // PFLUSH - { - sprintf(g_dasm_str, "pflushr %x, %x, %s", modes & 0x1f, (modes>>5)&0xf, str); - return; - } - - if (modes == 0xa000) // PFLUSHR - { - sprintf(g_dasm_str, "pflushr %s", str); - } - - if (modes == 0x2800) // PVALID (FORMAT 1) - { - sprintf(g_dasm_str, "pvalid VAL, %s", str); - return; - } - - if ((modes & 0xfff8) == 0x2c00) // PVALID (FORMAT 2) - { - sprintf(g_dasm_str, "pvalid A%d, %s", modes & 0xf, str); - return; - } - - if ((modes & 0xe000) == 0x8000) // PTEST - { - sprintf(g_dasm_str, "ptest #%d, %s", modes & 0x1f, str); - return; - } - - switch ((modes>>13) & 0x7) - { - case 0: // MC68030/040 form with FD bit - case 2: // MC68881 form, FD never set - if (modes & 0x0100) - { - if (modes & 0x0200) - { - sprintf(g_dasm_str, "pmovefd %s, %s", g_mmuregs[(modes>>10)&7], str); - } - else - { - sprintf(g_dasm_str, "pmovefd %s, %s", str, g_mmuregs[(modes>>10)&7]); - } - } - else - { - if (modes & 0x0200) - { - sprintf(g_dasm_str, "pmove %s, %s", g_mmuregs[(modes>>10)&7], str); - } - else - { - sprintf(g_dasm_str, "pmove %s, %s", str, g_mmuregs[(modes>>10)&7]); - } - } - break; - - case 3: // MC68030 to/from status reg - if (modes & 0x0200) - { - sprintf(g_dasm_str, "pmove mmusr, %s", str); - } - else - { - sprintf(g_dasm_str, "pmove %s, mmusr", str); - } - break; - - default: - sprintf(g_dasm_str, "pmove [unknown form] %s", str); - break; - } -} - -static void d68851_pbcc16(void) -{ - uint32 temp_pc = g_cpu_pc; - - sprintf(g_dasm_str, "pb%s %x", g_mmucond[g_cpu_ir&0xf], temp_pc + make_int_16(read_imm_16())); -} - -static void d68851_pbcc32(void) -{ - uint32 temp_pc = g_cpu_pc; - - sprintf(g_dasm_str, "pb%s %x", g_mmucond[g_cpu_ir&0xf], temp_pc + make_int_32(read_imm_32())); -} - -static void d68851_pdbcc(void) -{ - uint32 temp_pc = g_cpu_pc; - uint16 modes = read_imm_16(); - - sprintf(g_dasm_str, "pb%s %x", g_mmucond[modes&0xf], temp_pc + make_int_16(read_imm_16())); -} - -// PScc: 0000000000xxxxxx -static void d68851_p001(void) -{ - sprintf(g_dasm_str, "MMU 001 group"); -} - -/* ======================================================================== */ -/* ======================= INSTRUCTION TABLE BUILDER ====================== */ -/* ======================================================================== */ - -/* EA Masks: -800 = data register direct -400 = address register direct -200 = address register indirect -100 = ARI postincrement - 80 = ARI pre-decrement - 40 = ARI displacement - 20 = ARI index - 10 = absolute short - 8 = absolute long - 4 = immediate / sr - 2 = pc displacement - 1 = pc idx -*/ - -static const opcode_struct g_opcode_info[] = -{ -/* opcode handler mask match ea mask */ - {d68000_1010 , 0xf000, 0xa000, 0x000}, - {d68000_1111 , 0xf000, 0xf000, 0x000}, - {d68000_abcd_rr , 0xf1f8, 0xc100, 0x000}, - {d68000_abcd_mm , 0xf1f8, 0xc108, 0x000}, - {d68000_add_er_8 , 0xf1c0, 0xd000, 0xbff}, - {d68000_add_er_16 , 0xf1c0, 0xd040, 0xfff}, - {d68000_add_er_32 , 0xf1c0, 0xd080, 0xfff}, - {d68000_add_re_8 , 0xf1c0, 0xd100, 0x3f8}, - {d68000_add_re_16 , 0xf1c0, 0xd140, 0x3f8}, - {d68000_add_re_32 , 0xf1c0, 0xd180, 0x3f8}, - {d68000_adda_16 , 0xf1c0, 0xd0c0, 0xfff}, - {d68000_adda_32 , 0xf1c0, 0xd1c0, 0xfff}, - {d68000_addi_8 , 0xffc0, 0x0600, 0xbf8}, - {d68000_addi_16 , 0xffc0, 0x0640, 0xbf8}, - {d68000_addi_32 , 0xffc0, 0x0680, 0xbf8}, - {d68000_addq_8 , 0xf1c0, 0x5000, 0xbf8}, - {d68000_addq_16 , 0xf1c0, 0x5040, 0xff8}, - {d68000_addq_32 , 0xf1c0, 0x5080, 0xff8}, - {d68000_addx_rr_8 , 0xf1f8, 0xd100, 0x000}, - {d68000_addx_rr_16 , 0xf1f8, 0xd140, 0x000}, - {d68000_addx_rr_32 , 0xf1f8, 0xd180, 0x000}, - {d68000_addx_mm_8 , 0xf1f8, 0xd108, 0x000}, - {d68000_addx_mm_16 , 0xf1f8, 0xd148, 0x000}, - {d68000_addx_mm_32 , 0xf1f8, 0xd188, 0x000}, - {d68000_and_er_8 , 0xf1c0, 0xc000, 0xbff}, - {d68000_and_er_16 , 0xf1c0, 0xc040, 0xbff}, - {d68000_and_er_32 , 0xf1c0, 0xc080, 0xbff}, - {d68000_and_re_8 , 0xf1c0, 0xc100, 0x3f8}, - {d68000_and_re_16 , 0xf1c0, 0xc140, 0x3f8}, - {d68000_and_re_32 , 0xf1c0, 0xc180, 0x3f8}, - {d68000_andi_to_ccr , 0xffff, 0x023c, 0x000}, - {d68000_andi_to_sr , 0xffff, 0x027c, 0x000}, - {d68000_andi_8 , 0xffc0, 0x0200, 0xbf8}, - {d68000_andi_16 , 0xffc0, 0x0240, 0xbf8}, - {d68000_andi_32 , 0xffc0, 0x0280, 0xbf8}, - {d68000_asr_s_8 , 0xf1f8, 0xe000, 0x000}, - {d68000_asr_s_16 , 0xf1f8, 0xe040, 0x000}, - {d68000_asr_s_32 , 0xf1f8, 0xe080, 0x000}, - {d68000_asr_r_8 , 0xf1f8, 0xe020, 0x000}, - {d68000_asr_r_16 , 0xf1f8, 0xe060, 0x000}, - {d68000_asr_r_32 , 0xf1f8, 0xe0a0, 0x000}, - {d68000_asr_ea , 0xffc0, 0xe0c0, 0x3f8}, - {d68000_asl_s_8 , 0xf1f8, 0xe100, 0x000}, - {d68000_asl_s_16 , 0xf1f8, 0xe140, 0x000}, - {d68000_asl_s_32 , 0xf1f8, 0xe180, 0x000}, - {d68000_asl_r_8 , 0xf1f8, 0xe120, 0x000}, - {d68000_asl_r_16 , 0xf1f8, 0xe160, 0x000}, - {d68000_asl_r_32 , 0xf1f8, 0xe1a0, 0x000}, - {d68000_asl_ea , 0xffc0, 0xe1c0, 0x3f8}, - {d68000_bcc_8 , 0xf000, 0x6000, 0x000}, - {d68000_bcc_16 , 0xf0ff, 0x6000, 0x000}, - {d68020_bcc_32 , 0xf0ff, 0x60ff, 0x000}, - {d68000_bchg_r , 0xf1c0, 0x0140, 0xbf8}, - {d68000_bchg_s , 0xffc0, 0x0840, 0xbf8}, - {d68000_bclr_r , 0xf1c0, 0x0180, 0xbf8}, - {d68000_bclr_s , 0xffc0, 0x0880, 0xbf8}, - {d68020_bfchg , 0xffc0, 0xeac0, 0xa78}, - {d68020_bfclr , 0xffc0, 0xecc0, 0xa78}, - {d68020_bfexts , 0xffc0, 0xebc0, 0xa7b}, - {d68020_bfextu , 0xffc0, 0xe9c0, 0xa7b}, - {d68020_bfffo , 0xffc0, 0xedc0, 0xa7b}, - {d68020_bfins , 0xffc0, 0xefc0, 0xa78}, - {d68020_bfset , 0xffc0, 0xeec0, 0xa78}, - {d68020_bftst , 0xffc0, 0xe8c0, 0xa7b}, - {d68010_bkpt , 0xfff8, 0x4848, 0x000}, - {d68000_bra_8 , 0xff00, 0x6000, 0x000}, - {d68000_bra_16 , 0xffff, 0x6000, 0x000}, - {d68020_bra_32 , 0xffff, 0x60ff, 0x000}, - {d68000_bset_r , 0xf1c0, 0x01c0, 0xbf8}, - {d68000_bset_s , 0xffc0, 0x08c0, 0xbf8}, - {d68000_bsr_8 , 0xff00, 0x6100, 0x000}, - {d68000_bsr_16 , 0xffff, 0x6100, 0x000}, - {d68020_bsr_32 , 0xffff, 0x61ff, 0x000}, - {d68000_btst_r , 0xf1c0, 0x0100, 0xbff}, - {d68000_btst_s , 0xffc0, 0x0800, 0xbfb}, - {d68020_callm , 0xffc0, 0x06c0, 0x27b}, - {d68020_cas_8 , 0xffc0, 0x0ac0, 0x3f8}, - {d68020_cas_16 , 0xffc0, 0x0cc0, 0x3f8}, - {d68020_cas_32 , 0xffc0, 0x0ec0, 0x3f8}, - {d68020_cas2_16 , 0xffff, 0x0cfc, 0x000}, - {d68020_cas2_32 , 0xffff, 0x0efc, 0x000}, - {d68000_chk_16 , 0xf1c0, 0x4180, 0xbff}, - {d68020_chk_32 , 0xf1c0, 0x4100, 0xbff}, - {d68020_chk2_cmp2_8 , 0xffc0, 0x00c0, 0x27b}, - {d68020_chk2_cmp2_16 , 0xffc0, 0x02c0, 0x27b}, - {d68020_chk2_cmp2_32 , 0xffc0, 0x04c0, 0x27b}, - {d68040_cinv , 0xff20, 0xf400, 0x000}, - {d68000_clr_8 , 0xffc0, 0x4200, 0xbf8}, - {d68000_clr_16 , 0xffc0, 0x4240, 0xbf8}, - {d68000_clr_32 , 0xffc0, 0x4280, 0xbf8}, - {d68000_cmp_8 , 0xf1c0, 0xb000, 0xbff}, - {d68000_cmp_16 , 0xf1c0, 0xb040, 0xfff}, - {d68000_cmp_32 , 0xf1c0, 0xb080, 0xfff}, - {d68000_cmpa_16 , 0xf1c0, 0xb0c0, 0xfff}, - {d68000_cmpa_32 , 0xf1c0, 0xb1c0, 0xfff}, - {d68000_cmpi_8 , 0xffc0, 0x0c00, 0xbf8}, - {d68020_cmpi_pcdi_8 , 0xffff, 0x0c3a, 0x000}, - {d68020_cmpi_pcix_8 , 0xffff, 0x0c3b, 0x000}, - {d68000_cmpi_16 , 0xffc0, 0x0c40, 0xbf8}, - {d68020_cmpi_pcdi_16 , 0xffff, 0x0c7a, 0x000}, - {d68020_cmpi_pcix_16 , 0xffff, 0x0c7b, 0x000}, - {d68000_cmpi_32 , 0xffc0, 0x0c80, 0xbf8}, - {d68020_cmpi_pcdi_32 , 0xffff, 0x0cba, 0x000}, - {d68020_cmpi_pcix_32 , 0xffff, 0x0cbb, 0x000}, - {d68000_cmpm_8 , 0xf1f8, 0xb108, 0x000}, - {d68000_cmpm_16 , 0xf1f8, 0xb148, 0x000}, - {d68000_cmpm_32 , 0xf1f8, 0xb188, 0x000}, - {d68020_cpbcc_16 , 0xf1c0, 0xf080, 0x000}, - {d68020_cpbcc_32 , 0xf1c0, 0xf0c0, 0x000}, - {d68020_cpdbcc , 0xf1f8, 0xf048, 0x000}, - {d68020_cpgen , 0xf1c0, 0xf000, 0x000}, - {d68020_cprestore , 0xf1c0, 0xf140, 0x37f}, - {d68020_cpsave , 0xf1c0, 0xf100, 0x2f8}, - {d68020_cpscc , 0xf1c0, 0xf040, 0xbf8}, - {d68020_cptrapcc_0 , 0xf1ff, 0xf07c, 0x000}, - {d68020_cptrapcc_16 , 0xf1ff, 0xf07a, 0x000}, - {d68020_cptrapcc_32 , 0xf1ff, 0xf07b, 0x000}, - {d68040_cpush , 0xff20, 0xf420, 0x000}, - {d68000_dbcc , 0xf0f8, 0x50c8, 0x000}, - {d68000_dbra , 0xfff8, 0x51c8, 0x000}, - {d68000_divs , 0xf1c0, 0x81c0, 0xbff}, - {d68000_divu , 0xf1c0, 0x80c0, 0xbff}, - {d68020_divl , 0xffc0, 0x4c40, 0xbff}, - {d68000_eor_8 , 0xf1c0, 0xb100, 0xbf8}, - {d68000_eor_16 , 0xf1c0, 0xb140, 0xbf8}, - {d68000_eor_32 , 0xf1c0, 0xb180, 0xbf8}, - {d68000_eori_to_ccr , 0xffff, 0x0a3c, 0x000}, - {d68000_eori_to_sr , 0xffff, 0x0a7c, 0x000}, - {d68000_eori_8 , 0xffc0, 0x0a00, 0xbf8}, - {d68000_eori_16 , 0xffc0, 0x0a40, 0xbf8}, - {d68000_eori_32 , 0xffc0, 0x0a80, 0xbf8}, - {d68000_exg_dd , 0xf1f8, 0xc140, 0x000}, - {d68000_exg_aa , 0xf1f8, 0xc148, 0x000}, - {d68000_exg_da , 0xf1f8, 0xc188, 0x000}, - {d68020_extb_32 , 0xfff8, 0x49c0, 0x000}, - {d68000_ext_16 , 0xfff8, 0x4880, 0x000}, - {d68000_ext_32 , 0xfff8, 0x48c0, 0x000}, - {d68040_fpu , 0xffc0, 0xf200, 0x000}, - {d68000_illegal , 0xffff, 0x4afc, 0x000}, - {d68000_jmp , 0xffc0, 0x4ec0, 0x27b}, - {d68000_jsr , 0xffc0, 0x4e80, 0x27b}, - {d68000_lea , 0xf1c0, 0x41c0, 0x27b}, - {d68000_link_16 , 0xfff8, 0x4e50, 0x000}, - {d68020_link_32 , 0xfff8, 0x4808, 0x000}, - {d68000_lsr_s_8 , 0xf1f8, 0xe008, 0x000}, - {d68000_lsr_s_16 , 0xf1f8, 0xe048, 0x000}, - {d68000_lsr_s_32 , 0xf1f8, 0xe088, 0x000}, - {d68000_lsr_r_8 , 0xf1f8, 0xe028, 0x000}, - {d68000_lsr_r_16 , 0xf1f8, 0xe068, 0x000}, - {d68000_lsr_r_32 , 0xf1f8, 0xe0a8, 0x000}, - {d68000_lsr_ea , 0xffc0, 0xe2c0, 0x3f8}, - {d68000_lsl_s_8 , 0xf1f8, 0xe108, 0x000}, - {d68000_lsl_s_16 , 0xf1f8, 0xe148, 0x000}, - {d68000_lsl_s_32 , 0xf1f8, 0xe188, 0x000}, - {d68000_lsl_r_8 , 0xf1f8, 0xe128, 0x000}, - {d68000_lsl_r_16 , 0xf1f8, 0xe168, 0x000}, - {d68000_lsl_r_32 , 0xf1f8, 0xe1a8, 0x000}, - {d68000_lsl_ea , 0xffc0, 0xe3c0, 0x3f8}, - {d68000_move_8 , 0xf000, 0x1000, 0xbff}, - {d68000_move_16 , 0xf000, 0x3000, 0xfff}, - {d68000_move_32 , 0xf000, 0x2000, 0xfff}, - {d68000_movea_16 , 0xf1c0, 0x3040, 0xfff}, - {d68000_movea_32 , 0xf1c0, 0x2040, 0xfff}, - {d68000_move_to_ccr , 0xffc0, 0x44c0, 0xbff}, - {d68010_move_fr_ccr , 0xffc0, 0x42c0, 0xbf8}, - {d68000_move_to_sr , 0xffc0, 0x46c0, 0xbff}, - {d68000_move_fr_sr , 0xffc0, 0x40c0, 0xbf8}, - {d68000_move_to_usp , 0xfff8, 0x4e60, 0x000}, - {d68000_move_fr_usp , 0xfff8, 0x4e68, 0x000}, - {d68010_movec , 0xfffe, 0x4e7a, 0x000}, - {d68000_movem_pd_16 , 0xfff8, 0x48a0, 0x000}, - {d68000_movem_pd_32 , 0xfff8, 0x48e0, 0x000}, - {d68000_movem_re_16 , 0xffc0, 0x4880, 0x2f8}, - {d68000_movem_re_32 , 0xffc0, 0x48c0, 0x2f8}, - {d68000_movem_er_16 , 0xffc0, 0x4c80, 0x37b}, - {d68000_movem_er_32 , 0xffc0, 0x4cc0, 0x37b}, - {d68000_movep_er_16 , 0xf1f8, 0x0108, 0x000}, - {d68000_movep_er_32 , 0xf1f8, 0x0148, 0x000}, - {d68000_movep_re_16 , 0xf1f8, 0x0188, 0x000}, - {d68000_movep_re_32 , 0xf1f8, 0x01c8, 0x000}, - {d68010_moves_8 , 0xffc0, 0x0e00, 0x3f8}, - {d68010_moves_16 , 0xffc0, 0x0e40, 0x3f8}, - {d68010_moves_32 , 0xffc0, 0x0e80, 0x3f8}, - {d68000_moveq , 0xf100, 0x7000, 0x000}, - {d68040_move16_pi_pi , 0xfff8, 0xf620, 0x000}, - {d68040_move16_pi_al , 0xfff8, 0xf600, 0x000}, - {d68040_move16_al_pi , 0xfff8, 0xf608, 0x000}, - {d68040_move16_ai_al , 0xfff8, 0xf610, 0x000}, - {d68040_move16_al_ai , 0xfff8, 0xf618, 0x000}, - {d68000_muls , 0xf1c0, 0xc1c0, 0xbff}, - {d68000_mulu , 0xf1c0, 0xc0c0, 0xbff}, - {d68020_mull , 0xffc0, 0x4c00, 0xbff}, - {d68000_nbcd , 0xffc0, 0x4800, 0xbf8}, - {d68000_neg_8 , 0xffc0, 0x4400, 0xbf8}, - {d68000_neg_16 , 0xffc0, 0x4440, 0xbf8}, - {d68000_neg_32 , 0xffc0, 0x4480, 0xbf8}, - {d68000_negx_8 , 0xffc0, 0x4000, 0xbf8}, - {d68000_negx_16 , 0xffc0, 0x4040, 0xbf8}, - {d68000_negx_32 , 0xffc0, 0x4080, 0xbf8}, - {d68000_nop , 0xffff, 0x4e71, 0x000}, - {d68000_not_8 , 0xffc0, 0x4600, 0xbf8}, - {d68000_not_16 , 0xffc0, 0x4640, 0xbf8}, - {d68000_not_32 , 0xffc0, 0x4680, 0xbf8}, - {d68000_or_er_8 , 0xf1c0, 0x8000, 0xbff}, - {d68000_or_er_16 , 0xf1c0, 0x8040, 0xbff}, - {d68000_or_er_32 , 0xf1c0, 0x8080, 0xbff}, - {d68000_or_re_8 , 0xf1c0, 0x8100, 0x3f8}, - {d68000_or_re_16 , 0xf1c0, 0x8140, 0x3f8}, - {d68000_or_re_32 , 0xf1c0, 0x8180, 0x3f8}, - {d68000_ori_to_ccr , 0xffff, 0x003c, 0x000}, - {d68000_ori_to_sr , 0xffff, 0x007c, 0x000}, - {d68000_ori_8 , 0xffc0, 0x0000, 0xbf8}, - {d68000_ori_16 , 0xffc0, 0x0040, 0xbf8}, - {d68000_ori_32 , 0xffc0, 0x0080, 0xbf8}, - {d68020_pack_rr , 0xf1f8, 0x8140, 0x000}, - {d68020_pack_mm , 0xf1f8, 0x8148, 0x000}, - {d68000_pea , 0xffc0, 0x4840, 0x27b}, - {d68040_pflush , 0xffe0, 0xf500, 0x000}, - {d68000_reset , 0xffff, 0x4e70, 0x000}, - {d68000_ror_s_8 , 0xf1f8, 0xe018, 0x000}, - {d68000_ror_s_16 , 0xf1f8, 0xe058, 0x000}, - {d68000_ror_s_32 , 0xf1f8, 0xe098, 0x000}, - {d68000_ror_r_8 , 0xf1f8, 0xe038, 0x000}, - {d68000_ror_r_16 , 0xf1f8, 0xe078, 0x000}, - {d68000_ror_r_32 , 0xf1f8, 0xe0b8, 0x000}, - {d68000_ror_ea , 0xffc0, 0xe6c0, 0x3f8}, - {d68000_rol_s_8 , 0xf1f8, 0xe118, 0x000}, - {d68000_rol_s_16 , 0xf1f8, 0xe158, 0x000}, - {d68000_rol_s_32 , 0xf1f8, 0xe198, 0x000}, - {d68000_rol_r_8 , 0xf1f8, 0xe138, 0x000}, - {d68000_rol_r_16 , 0xf1f8, 0xe178, 0x000}, - {d68000_rol_r_32 , 0xf1f8, 0xe1b8, 0x000}, - {d68000_rol_ea , 0xffc0, 0xe7c0, 0x3f8}, - {d68000_roxr_s_8 , 0xf1f8, 0xe010, 0x000}, - {d68000_roxr_s_16 , 0xf1f8, 0xe050, 0x000}, - {d68000_roxr_s_32 , 0xf1f8, 0xe090, 0x000}, - {d68000_roxr_r_8 , 0xf1f8, 0xe030, 0x000}, - {d68000_roxr_r_16 , 0xf1f8, 0xe070, 0x000}, - {d68000_roxr_r_32 , 0xf1f8, 0xe0b0, 0x000}, - {d68000_roxr_ea , 0xffc0, 0xe4c0, 0x3f8}, - {d68000_roxl_s_8 , 0xf1f8, 0xe110, 0x000}, - {d68000_roxl_s_16 , 0xf1f8, 0xe150, 0x000}, - {d68000_roxl_s_32 , 0xf1f8, 0xe190, 0x000}, - {d68000_roxl_r_8 , 0xf1f8, 0xe130, 0x000}, - {d68000_roxl_r_16 , 0xf1f8, 0xe170, 0x000}, - {d68000_roxl_r_32 , 0xf1f8, 0xe1b0, 0x000}, - {d68000_roxl_ea , 0xffc0, 0xe5c0, 0x3f8}, - {d68010_rtd , 0xffff, 0x4e74, 0x000}, - {d68000_rte , 0xffff, 0x4e73, 0x000}, - {d68020_rtm , 0xfff0, 0x06c0, 0x000}, - {d68000_rtr , 0xffff, 0x4e77, 0x000}, - {d68000_rts , 0xffff, 0x4e75, 0x000}, - {d68000_sbcd_rr , 0xf1f8, 0x8100, 0x000}, - {d68000_sbcd_mm , 0xf1f8, 0x8108, 0x000}, - {d68000_scc , 0xf0c0, 0x50c0, 0xbf8}, - {d68000_stop , 0xffff, 0x4e72, 0x000}, - {d68000_sub_er_8 , 0xf1c0, 0x9000, 0xbff}, - {d68000_sub_er_16 , 0xf1c0, 0x9040, 0xfff}, - {d68000_sub_er_32 , 0xf1c0, 0x9080, 0xfff}, - {d68000_sub_re_8 , 0xf1c0, 0x9100, 0x3f8}, - {d68000_sub_re_16 , 0xf1c0, 0x9140, 0x3f8}, - {d68000_sub_re_32 , 0xf1c0, 0x9180, 0x3f8}, - {d68000_suba_16 , 0xf1c0, 0x90c0, 0xfff}, - {d68000_suba_32 , 0xf1c0, 0x91c0, 0xfff}, - {d68000_subi_8 , 0xffc0, 0x0400, 0xbf8}, - {d68000_subi_16 , 0xffc0, 0x0440, 0xbf8}, - {d68000_subi_32 , 0xffc0, 0x0480, 0xbf8}, - {d68000_subq_8 , 0xf1c0, 0x5100, 0xbf8}, - {d68000_subq_16 , 0xf1c0, 0x5140, 0xff8}, - {d68000_subq_32 , 0xf1c0, 0x5180, 0xff8}, - {d68000_subx_rr_8 , 0xf1f8, 0x9100, 0x000}, - {d68000_subx_rr_16 , 0xf1f8, 0x9140, 0x000}, - {d68000_subx_rr_32 , 0xf1f8, 0x9180, 0x000}, - {d68000_subx_mm_8 , 0xf1f8, 0x9108, 0x000}, - {d68000_subx_mm_16 , 0xf1f8, 0x9148, 0x000}, - {d68000_subx_mm_32 , 0xf1f8, 0x9188, 0x000}, - {d68000_swap , 0xfff8, 0x4840, 0x000}, - {d68000_tas , 0xffc0, 0x4ac0, 0xbf8}, - {d68000_trap , 0xfff0, 0x4e40, 0x000}, - {d68020_trapcc_0 , 0xf0ff, 0x50fc, 0x000}, - {d68020_trapcc_16 , 0xf0ff, 0x50fa, 0x000}, - {d68020_trapcc_32 , 0xf0ff, 0x50fb, 0x000}, - {d68000_trapv , 0xffff, 0x4e76, 0x000}, - {d68000_tst_8 , 0xffc0, 0x4a00, 0xbf8}, - {d68020_tst_pcdi_8 , 0xffff, 0x4a3a, 0x000}, - {d68020_tst_pcix_8 , 0xffff, 0x4a3b, 0x000}, - {d68020_tst_i_8 , 0xffff, 0x4a3c, 0x000}, - {d68000_tst_16 , 0xffc0, 0x4a40, 0xbf8}, - {d68020_tst_a_16 , 0xfff8, 0x4a48, 0x000}, - {d68020_tst_pcdi_16 , 0xffff, 0x4a7a, 0x000}, - {d68020_tst_pcix_16 , 0xffff, 0x4a7b, 0x000}, - {d68020_tst_i_16 , 0xffff, 0x4a7c, 0x000}, - {d68000_tst_32 , 0xffc0, 0x4a80, 0xbf8}, - {d68020_tst_a_32 , 0xfff8, 0x4a88, 0x000}, - {d68020_tst_pcdi_32 , 0xffff, 0x4aba, 0x000}, - {d68020_tst_pcix_32 , 0xffff, 0x4abb, 0x000}, - {d68020_tst_i_32 , 0xffff, 0x4abc, 0x000}, - {d68000_unlk , 0xfff8, 0x4e58, 0x000}, - {d68020_unpk_rr , 0xf1f8, 0x8180, 0x000}, - {d68020_unpk_mm , 0xf1f8, 0x8188, 0x000}, - {d68851_p000 , 0xffc0, 0xf000, 0x000}, - {d68851_pbcc16 , 0xffc0, 0xf080, 0x000}, - {d68851_pbcc32 , 0xffc0, 0xf0c0, 0x000}, - {d68851_pdbcc , 0xfff8, 0xf048, 0x000}, - {d68851_p001 , 0xffc0, 0xf040, 0x000}, - {0, 0, 0, 0} -}; - -/* Check if opcode is using a valid ea mode */ -static int valid_ea(uint opcode, uint mask) -{ - if(mask == 0) - return 1; - - switch(opcode & 0x3f) - { - case 0x00: case 0x01: case 0x02: case 0x03: - case 0x04: case 0x05: case 0x06: case 0x07: - return (mask & 0x800) != 0; - case 0x08: case 0x09: case 0x0a: case 0x0b: - case 0x0c: case 0x0d: case 0x0e: case 0x0f: - return (mask & 0x400) != 0; - case 0x10: case 0x11: case 0x12: case 0x13: - case 0x14: case 0x15: case 0x16: case 0x17: - return (mask & 0x200) != 0; - case 0x18: case 0x19: case 0x1a: case 0x1b: - case 0x1c: case 0x1d: case 0x1e: case 0x1f: - return (mask & 0x100) != 0; - case 0x20: case 0x21: case 0x22: case 0x23: - case 0x24: case 0x25: case 0x26: case 0x27: - return (mask & 0x080) != 0; - case 0x28: case 0x29: case 0x2a: case 0x2b: - case 0x2c: case 0x2d: case 0x2e: case 0x2f: - return (mask & 0x040) != 0; - case 0x30: case 0x31: case 0x32: case 0x33: - case 0x34: case 0x35: case 0x36: case 0x37: - return (mask & 0x020) != 0; - case 0x38: - return (mask & 0x010) != 0; - case 0x39: - return (mask & 0x008) != 0; - case 0x3a: - return (mask & 0x002) != 0; - case 0x3b: - return (mask & 0x001) != 0; - case 0x3c: - return (mask & 0x004) != 0; - } - return 0; - -} - -/* Used by qsort */ -static int DECL_SPEC compare_nof_true_bits(const void *aptr, const void *bptr) -{ - uint a = ((const opcode_struct*)aptr)->mask; - uint b = ((const opcode_struct*)bptr)->mask; - - a = ((a & 0xAAAA) >> 1) + (a & 0x5555); - a = ((a & 0xCCCC) >> 2) + (a & 0x3333); - a = ((a & 0xF0F0) >> 4) + (a & 0x0F0F); - a = ((a & 0xFF00) >> 8) + (a & 0x00FF); - - b = ((b & 0xAAAA) >> 1) + (b & 0x5555); - b = ((b & 0xCCCC) >> 2) + (b & 0x3333); - b = ((b & 0xF0F0) >> 4) + (b & 0x0F0F); - b = ((b & 0xFF00) >> 8) + (b & 0x00FF); - - return b - a; /* reversed to get greatest to least sorting */ -} - -/* build the opcode handler jump table */ -static void build_opcode_table(void) -{ - uint i; - uint opcode; - opcode_struct* ostruct; - opcode_struct opcode_info[ARRAY_LENGTH(g_opcode_info)]; - - memcpy(opcode_info, g_opcode_info, sizeof(g_opcode_info)); - qsort((void *)opcode_info, ARRAY_LENGTH(opcode_info)-1, sizeof(opcode_info[0]), compare_nof_true_bits); - - for(i=0;i<0x10000;i++) - { - g_instruction_table[i] = d68000_illegal; /* default to illegal */ - opcode = i; - /* search through opcode info for a match */ - for(ostruct = opcode_info;ostruct->opcode_handler != 0;ostruct++) - { - /* match opcode mask and allowed ea modes */ - if((opcode & ostruct->mask) == ostruct->match) - { - /* Handle destination ea for move instructions */ - if((ostruct->opcode_handler == d68000_move_8 || - ostruct->opcode_handler == d68000_move_16 || - ostruct->opcode_handler == d68000_move_32) && - !valid_ea(((opcode>>9)&7) | ((opcode>>3)&0x38), 0xbf8)) - continue; - if(valid_ea(opcode, ostruct->ea_mask)) - { - g_instruction_table[i] = ostruct->opcode_handler; - break; - } - } - } - } -} - - - -/* ======================================================================== */ -/* ================================= API ================================== */ -/* ======================================================================== */ - -/* Disasemble one instruction at pc and store in str_buff */ -unsigned int m68k_disassemble(char* str_buff, unsigned int pc, unsigned int cpu_type) -{ - if(!g_initialized) - { - build_opcode_table(); - g_initialized = 1; - } - switch(cpu_type) - { - case M68K_CPU_TYPE_68000: - g_cpu_type = TYPE_68000; - g_address_mask = 0x00ffffff; - break; - case M68K_CPU_TYPE_68010: - g_cpu_type = TYPE_68010; - g_address_mask = 0x00ffffff; - break; - case M68K_CPU_TYPE_68EC020: - g_cpu_type = TYPE_68020; - g_address_mask = 0x00ffffff; - break; - case M68K_CPU_TYPE_68020: - g_cpu_type = TYPE_68020; - g_address_mask = 0xffffffff; - break; - case M68K_CPU_TYPE_68EC030: - case M68K_CPU_TYPE_68030: - g_cpu_type = TYPE_68030; - g_address_mask = 0xffffffff; - break; - case M68K_CPU_TYPE_68040: - case M68K_CPU_TYPE_68EC040: - case M68K_CPU_TYPE_68LC040: - g_cpu_type = TYPE_68040; - g_address_mask = 0xffffffff; - break; - default: - return 0; - } - - g_cpu_pc = pc; - g_helper_str[0] = 0; - g_cpu_ir = read_imm_16(); - g_opcode_type = 0; - g_instruction_table[g_cpu_ir](); - sprintf(str_buff, "%s%s", g_dasm_str, g_helper_str); - return COMBINE_OPCODE_FLAGS(g_cpu_pc - pc); -} - -char* m68ki_disassemble_quick(unsigned int pc, unsigned int cpu_type) -{ - static char buff[100]; - buff[0] = 0; - m68k_disassemble(buff, pc, cpu_type); - return buff; -} - -unsigned int m68k_disassemble_raw(char* str_buff, unsigned int pc, const unsigned char* opdata, const unsigned char* argdata, unsigned int cpu_type) -{ - unsigned int result; - (void)argdata; - - g_rawop = opdata; - g_rawbasepc = pc; - result = m68k_disassemble(str_buff, pc, cpu_type); - g_rawop = NULL; - return result; -} - -/* Check if the instruction is a valid one */ -unsigned int m68k_is_valid_instruction(unsigned int instruction, unsigned int cpu_type) -{ - if(!g_initialized) - { - build_opcode_table(); - g_initialized = 1; - } - - instruction &= 0xffff; - if(g_instruction_table[instruction] == d68000_illegal) - return 0; - - switch(cpu_type) - { - case M68K_CPU_TYPE_68000: - if(g_instruction_table[instruction] == d68010_bkpt) - return 0; - if(g_instruction_table[instruction] == d68010_move_fr_ccr) - return 0; - if(g_instruction_table[instruction] == d68010_movec) - return 0; - if(g_instruction_table[instruction] == d68010_moves_8) - return 0; - if(g_instruction_table[instruction] == d68010_moves_16) - return 0; - if(g_instruction_table[instruction] == d68010_moves_32) - return 0; - if(g_instruction_table[instruction] == d68010_rtd) - return 0; - // Fallthrough - case M68K_CPU_TYPE_68010: - if(g_instruction_table[instruction] == d68020_bcc_32) - return 0; - if(g_instruction_table[instruction] == d68020_bfchg) - return 0; - if(g_instruction_table[instruction] == d68020_bfclr) - return 0; - if(g_instruction_table[instruction] == d68020_bfexts) - return 0; - if(g_instruction_table[instruction] == d68020_bfextu) - return 0; - if(g_instruction_table[instruction] == d68020_bfffo) - return 0; - if(g_instruction_table[instruction] == d68020_bfins) - return 0; - if(g_instruction_table[instruction] == d68020_bfset) - return 0; - if(g_instruction_table[instruction] == d68020_bftst) - return 0; - if(g_instruction_table[instruction] == d68020_bra_32) - return 0; - if(g_instruction_table[instruction] == d68020_bsr_32) - return 0; - if(g_instruction_table[instruction] == d68020_callm) - return 0; - if(g_instruction_table[instruction] == d68020_cas_8) - return 0; - if(g_instruction_table[instruction] == d68020_cas_16) - return 0; - if(g_instruction_table[instruction] == d68020_cas_32) - return 0; - if(g_instruction_table[instruction] == d68020_cas2_16) - return 0; - if(g_instruction_table[instruction] == d68020_cas2_32) - return 0; - if(g_instruction_table[instruction] == d68020_chk_32) - return 0; - if(g_instruction_table[instruction] == d68020_chk2_cmp2_8) - return 0; - if(g_instruction_table[instruction] == d68020_chk2_cmp2_16) - return 0; - if(g_instruction_table[instruction] == d68020_chk2_cmp2_32) - return 0; - if(g_instruction_table[instruction] == d68020_cmpi_pcdi_8) - return 0; - if(g_instruction_table[instruction] == d68020_cmpi_pcix_8) - return 0; - if(g_instruction_table[instruction] == d68020_cmpi_pcdi_16) - return 0; - if(g_instruction_table[instruction] == d68020_cmpi_pcix_16) - return 0; - if(g_instruction_table[instruction] == d68020_cmpi_pcdi_32) - return 0; - if(g_instruction_table[instruction] == d68020_cmpi_pcix_32) - return 0; - if(g_instruction_table[instruction] == d68020_cpbcc_16) - return 0; - if(g_instruction_table[instruction] == d68020_cpbcc_32) - return 0; - if(g_instruction_table[instruction] == d68020_cpdbcc) - return 0; - if(g_instruction_table[instruction] == d68020_cpgen) - return 0; - if(g_instruction_table[instruction] == d68020_cprestore) - return 0; - if(g_instruction_table[instruction] == d68020_cpsave) - return 0; - if(g_instruction_table[instruction] == d68020_cpscc) - return 0; - if(g_instruction_table[instruction] == d68020_cptrapcc_0) - return 0; - if(g_instruction_table[instruction] == d68020_cptrapcc_16) - return 0; - if(g_instruction_table[instruction] == d68020_cptrapcc_32) - return 0; - if(g_instruction_table[instruction] == d68020_divl) - return 0; - if(g_instruction_table[instruction] == d68020_extb_32) - return 0; - if(g_instruction_table[instruction] == d68020_link_32) - return 0; - if(g_instruction_table[instruction] == d68020_mull) - return 0; - if(g_instruction_table[instruction] == d68020_pack_rr) - return 0; - if(g_instruction_table[instruction] == d68020_pack_mm) - return 0; - if(g_instruction_table[instruction] == d68020_rtm) - return 0; - if(g_instruction_table[instruction] == d68020_trapcc_0) - return 0; - if(g_instruction_table[instruction] == d68020_trapcc_16) - return 0; - if(g_instruction_table[instruction] == d68020_trapcc_32) - return 0; - if(g_instruction_table[instruction] == d68020_tst_pcdi_8) - return 0; - if(g_instruction_table[instruction] == d68020_tst_pcix_8) - return 0; - if(g_instruction_table[instruction] == d68020_tst_i_8) - return 0; - if(g_instruction_table[instruction] == d68020_tst_a_16) - return 0; - if(g_instruction_table[instruction] == d68020_tst_pcdi_16) - return 0; - if(g_instruction_table[instruction] == d68020_tst_pcix_16) - return 0; - if(g_instruction_table[instruction] == d68020_tst_i_16) - return 0; - if(g_instruction_table[instruction] == d68020_tst_a_32) - return 0; - if(g_instruction_table[instruction] == d68020_tst_pcdi_32) - return 0; - if(g_instruction_table[instruction] == d68020_tst_pcix_32) - return 0; - if(g_instruction_table[instruction] == d68020_tst_i_32) - return 0; - if(g_instruction_table[instruction] == d68020_unpk_rr) - return 0; - if(g_instruction_table[instruction] == d68020_unpk_mm) - return 0; - // Fallthrough - case M68K_CPU_TYPE_68EC020: - case M68K_CPU_TYPE_68020: - case M68K_CPU_TYPE_68030: - case M68K_CPU_TYPE_68EC030: - if(g_instruction_table[instruction] == d68040_cinv) - return 0; - if(g_instruction_table[instruction] == d68040_cpush) - return 0; - if(g_instruction_table[instruction] == d68040_move16_pi_pi) - return 0; - if(g_instruction_table[instruction] == d68040_move16_pi_al) - return 0; - if(g_instruction_table[instruction] == d68040_move16_al_pi) - return 0; - if(g_instruction_table[instruction] == d68040_move16_ai_al) - return 0; - if(g_instruction_table[instruction] == d68040_move16_al_ai) - return 0; - // Fallthrough - case M68K_CPU_TYPE_68040: - case M68K_CPU_TYPE_68EC040: - case M68K_CPU_TYPE_68LC040: - if(g_instruction_table[instruction] == d68020_cpbcc_16) - return 0; - if(g_instruction_table[instruction] == d68020_cpbcc_32) - return 0; - if(g_instruction_table[instruction] == d68020_cpdbcc) - return 0; - if(g_instruction_table[instruction] == d68020_cpgen) - return 0; - if(g_instruction_table[instruction] == d68020_cprestore) - return 0; - if(g_instruction_table[instruction] == d68020_cpsave) - return 0; - if(g_instruction_table[instruction] == d68020_cpscc) - return 0; - if(g_instruction_table[instruction] == d68020_cptrapcc_0) - return 0; - if(g_instruction_table[instruction] == d68020_cptrapcc_16) - return 0; - if(g_instruction_table[instruction] == d68020_cptrapcc_32) - return 0; - if(g_instruction_table[instruction] == d68040_pflush) - return 0; - } - if(cpu_type != M68K_CPU_TYPE_68020 && cpu_type != M68K_CPU_TYPE_68EC020 && - (g_instruction_table[instruction] == d68020_callm || - g_instruction_table[instruction] == d68020_rtm)) - return 0; - - return 1; -} - -// f028 2215 0008 - -/* ======================================================================== */ -/* ============================== END OF FILE ============================= */ -/* ======================================================================== */ diff --git a/machine/musashi/m68kfpu.c b/machine/musashi/m68kfpu.c deleted file mode 100644 index dd39aa8..0000000 --- a/machine/musashi/m68kfpu.c +++ /dev/null @@ -1,1769 +0,0 @@ -#include -#include -#include - -extern void exit(int); - -static void fatalerror(const char *format, ...) { - va_list ap; - va_start(ap,format); - vfprintf(stderr,format,ap); // JFF: fixed. Was using fprintf and arguments were wrong - va_end(ap); - exit(1); -} - -#define FPCC_N 0x08000000 -#define FPCC_Z 0x04000000 -#define FPCC_I 0x02000000 -#define FPCC_NAN 0x01000000 - -#define DOUBLE_INFINITY (unsigned long long)(0x7ff0000000000000) -#define DOUBLE_EXPONENT (unsigned long long)(0x7ff0000000000000) -#define DOUBLE_MANTISSA (unsigned long long)(0x000fffffffffffff) - -extern flag floatx80_is_nan( floatx80 a ); - -// masks for packed dwords, positive k-factor -static uint32 pkmask2[18] = -{ - 0xffffffff, 0, 0xf0000000, 0xff000000, 0xfff00000, 0xffff0000, - 0xfffff000, 0xffffff00, 0xfffffff0, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, - 0xffffffff, 0xffffffff, 0xffffffff -}; - -static uint32 pkmask3[18] = -{ - 0xffffffff, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0xf0000000, 0xff000000, 0xfff00000, 0xffff0000, - 0xfffff000, 0xffffff00, 0xfffffff0, 0xffffffff, -}; - -static inline double fx80_to_double(floatx80 fx) -{ - uint64 d; - double *foo; - - foo = (double *)&d; - - d = floatx80_to_float64(fx); - - return *foo; -} - -static inline floatx80 double_to_fx80(double in) -{ - uint64 *d; - - d = (uint64 *)∈ - - return float64_to_floatx80(*d); -} - -static inline floatx80 load_extended_float80(uint32 ea) -{ - uint32 d1,d2; - uint16 d3; - floatx80 fp; - - d3 = m68ki_read_16(ea); - d1 = m68ki_read_32(ea+4); - d2 = m68ki_read_32(ea+8); - - fp.high = d3; - fp.low = ((uint64)d1<<32) | (d2 & 0xffffffff); - - return fp; -} - -static inline void store_extended_float80(uint32 ea, floatx80 fpr) -{ - m68ki_write_16(ea+0, fpr.high); - m68ki_write_16(ea+2, 0); - m68ki_write_32(ea+4, (fpr.low>>32)&0xffffffff); - m68ki_write_32(ea+8, fpr.low&0xffffffff); -} - -static inline floatx80 load_pack_float80(uint32 ea) -{ - uint32 dw1, dw2, dw3; - floatx80 result; - double tmp; - char str[128], *ch; - - dw1 = m68ki_read_32(ea); - dw2 = m68ki_read_32(ea+4); - dw3 = m68ki_read_32(ea+8); - - ch = &str[0]; - if (dw1 & 0x80000000) // mantissa sign - { - *ch++ = '-'; - } - *ch++ = (char)((dw1 & 0xf) + '0'); - *ch++ = '.'; - *ch++ = (char)(((dw2 >> 28) & 0xf) + '0'); - *ch++ = (char)(((dw2 >> 24) & 0xf) + '0'); - *ch++ = (char)(((dw2 >> 20) & 0xf) + '0'); - *ch++ = (char)(((dw2 >> 16) & 0xf) + '0'); - *ch++ = (char)(((dw2 >> 12) & 0xf) + '0'); - *ch++ = (char)(((dw2 >> 8) & 0xf) + '0'); - *ch++ = (char)(((dw2 >> 4) & 0xf) + '0'); - *ch++ = (char)(((dw2 >> 0) & 0xf) + '0'); - *ch++ = (char)(((dw3 >> 28) & 0xf) + '0'); - *ch++ = (char)(((dw3 >> 24) & 0xf) + '0'); - *ch++ = (char)(((dw3 >> 20) & 0xf) + '0'); - *ch++ = (char)(((dw3 >> 16) & 0xf) + '0'); - *ch++ = (char)(((dw3 >> 12) & 0xf) + '0'); - *ch++ = (char)(((dw3 >> 8) & 0xf) + '0'); - *ch++ = (char)(((dw3 >> 4) & 0xf) + '0'); - *ch++ = (char)(((dw3 >> 0) & 0xf) + '0'); - *ch++ = 'E'; - if (dw1 & 0x40000000) // exponent sign - { - *ch++ = '-'; - } - *ch++ = (char)(((dw1 >> 24) & 0xf) + '0'); - *ch++ = (char)(((dw1 >> 20) & 0xf) + '0'); - *ch++ = (char)(((dw1 >> 16) & 0xf) + '0'); - *ch = '\0'; - - sscanf(str, "%le", &tmp); - - result = double_to_fx80(tmp); - - return result; -} - -static inline void store_pack_float80(uint32 ea, int k, floatx80 fpr) -{ - uint32 dw1, dw2, dw3; - char str[128], *ch; - int i, j, exp; - - dw1 = dw2 = dw3 = 0; - ch = &str[0]; - - sprintf(str, "%.16e", fx80_to_double(fpr)); - - if (*ch == '-') - { - ch++; - dw1 = 0x80000000; - } - - if (*ch == '+') - { - ch++; - } - - dw1 |= (*ch++ - '0'); - - if (*ch == '.') - { - ch++; - } - - // handle negative k-factor here - if ((k <= 0) && (k >= -13)) - { - exp = 0; - for (i = 0; i < 3; i++) - { - if (ch[18+i] >= '0' && ch[18+i] <= '9') - { - exp = (exp << 4) | (ch[18+i] - '0'); - } - } - - if (ch[17] == '-') - { - exp = -exp; - } - - k = -k; - // last digit is (k + exponent - 1) - k += (exp - 1); - - // round up the last significant mantissa digit - if (ch[k+1] >= '5') - { - ch[k]++; - } - - // zero out the rest of the mantissa digits - for (j = (k+1); j < 16; j++) - { - ch[j] = '0'; - } - - // now zero out K to avoid tripping the positive K detection below - k = 0; - } - - // crack 8 digits of the mantissa - for (i = 0; i < 8; i++) - { - dw2 <<= 4; - if (*ch >= '0' && *ch <= '9') - { - dw2 |= *ch++ - '0'; - } - } - - // next 8 digits of the mantissa - for (i = 0; i < 8; i++) - { - dw3 <<= 4; - if (*ch >= '0' && *ch <= '9') - dw3 |= *ch++ - '0'; - } - - // handle masking if k is positive - if (k >= 1) - { - if (k <= 17) - { - dw2 &= pkmask2[k]; - dw3 &= pkmask3[k]; - } - else - { - dw2 &= pkmask2[17]; - dw3 &= pkmask3[17]; -// m68ki_cpu.fpcr |= (need to set OPERR bit) - } - } - - // finally, crack the exponent - if (*ch == 'e' || *ch == 'E') - { - ch++; - if (*ch == '-') - { - ch++; - dw1 |= 0x40000000; - } - - if (*ch == '+') - { - ch++; - } - - j = 0; - for (i = 0; i < 3; i++) - { - if (*ch >= '0' && *ch <= '9') - { - j = (j << 4) | (*ch++ - '0'); - } - } - - dw1 |= (j << 16); - } - - m68ki_write_32(ea, dw1); - m68ki_write_32(ea+4, dw2); - m68ki_write_32(ea+8, dw3); -} - -static inline void SET_CONDITION_CODES(floatx80 reg) -{ - REG_FPSR &= ~(FPCC_N|FPCC_Z|FPCC_I|FPCC_NAN); - - // sign flag - if (reg.high & 0x8000) - { - REG_FPSR |= FPCC_N; - } - - // zero flag - if (((reg.high & 0x7fff) == 0) && ((reg.low<<1) == 0)) - { - REG_FPSR |= FPCC_Z; - } - - // infinity flag - if (((reg.high & 0x7fff) == 0x7fff) && ((reg.low<<1) == 0)) - { - REG_FPSR |= FPCC_I; - } - - // NaN flag - if (floatx80_is_nan(reg)) - { - REG_FPSR |= FPCC_NAN; - } -} - -static inline int TEST_CONDITION(int condition) -{ - int n = (REG_FPSR & FPCC_N) != 0; - int z = (REG_FPSR & FPCC_Z) != 0; - int nan = (REG_FPSR & FPCC_NAN) != 0; - int r = 0; - switch (condition) - { - case 0x10: - case 0x00: return 0; // False - - case 0x11: - case 0x01: return (z); // Equal - - case 0x12: - case 0x02: return (!(nan || z || n)); // Greater Than - - case 0x13: - case 0x03: return (z || !(nan || n)); // Greater or Equal - - case 0x14: - case 0x04: return (n && !(nan || z)); // Less Than - - case 0x15: - case 0x05: return (z || (n && !nan)); // Less Than or Equal - - case 0x16: - case 0x06: return !nan && !z; - - case 0x17: - case 0x07: return !nan; - - case 0x18: - case 0x08: return nan; - - case 0x19: - case 0x09: return nan || z; - - case 0x1a: - case 0x0a: return (nan || !(n || z)); // Not Less Than or Equal - - case 0x1b: - case 0x0b: return (nan || z || !n); // Not Less Than - - case 0x1c: - case 0x0c: return (nan || (n && !z)); // Not Greater or Equal Than - - case 0x1d: - case 0x0d: return (nan || z || n); // Not Greater Than - - case 0x1e: - case 0x0e: return (!z); // Not Equal - - case 0x1f: - case 0x0f: return 1; // True - - default: fatalerror("M68kFPU: test_condition: unhandled condition %02X\n", condition); - } - - return r; -} - -static uint8 READ_EA_8(int ea) -{ - int mode = (ea >> 3) & 0x7; - int reg = (ea & 0x7); - - switch (mode) - { - case 0: // Dn - { - return REG_D[reg]; - } - case 2: // (An) - { - uint32 ea = REG_A[reg]; - return m68ki_read_8(ea); - } - case 5: // (d16, An) - { - uint32 ea = EA_AY_DI_8(); - return m68ki_read_8(ea); - } - case 6: // (An) + (Xn) + d8 - { - uint32 ea = EA_AY_IX_8(); - return m68ki_read_8(ea); - } - case 7: - { - switch (reg) - { - case 0: // (xxx).W - { - uint32 ea = (uint32)OPER_I_16(); - return m68ki_read_8(ea); - } - case 1: // (xxx).L - { - uint32 d1 = OPER_I_16(); - uint32 d2 = OPER_I_16(); - uint32 ea = (d1 << 16) | d2; - return m68ki_read_8(ea); - } - case 4: // # - { - return OPER_I_8(); - } - default: fatalerror("M68kFPU: READ_EA_8: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC); - } - break; - } - default: fatalerror("M68kFPU: READ_EA_8: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC); - } - - return 0; -} - -static uint16 READ_EA_16(int ea) -{ - int mode = (ea >> 3) & 0x7; - int reg = (ea & 0x7); - - switch (mode) - { - case 0: // Dn - { - return (uint16)(REG_D[reg]); - } - case 2: // (An) - { - uint32 ea = REG_A[reg]; - return m68ki_read_16(ea); - } - case 5: // (d16, An) - { - uint32 ea = EA_AY_DI_16(); - return m68ki_read_16(ea); - } - case 6: // (An) + (Xn) + d8 - { - uint32 ea = EA_AY_IX_16(); - return m68ki_read_16(ea); - } - case 7: - { - switch (reg) - { - case 0: // (xxx).W - { - uint32 ea = (uint32)OPER_I_16(); - return m68ki_read_16(ea); - } - case 1: // (xxx).L - { - uint32 d1 = OPER_I_16(); - uint32 d2 = OPER_I_16(); - uint32 ea = (d1 << 16) | d2; - return m68ki_read_16(ea); - } - case 4: // # - { - return OPER_I_16(); - } - - default: fatalerror("M68kFPU: READ_EA_16: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC); - } - break; - } - default: fatalerror("M68kFPU: READ_EA_16: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC); - } - - return 0; -} - -static uint32 READ_EA_32(int ea) -{ - int mode = (ea >> 3) & 0x7; - int reg = (ea & 0x7); - - switch (mode) - { - case 0: // Dn - { - return REG_D[reg]; - } - case 2: // (An) - { - uint32 ea = REG_A[reg]; - return m68ki_read_32(ea); - } - case 3: // (An)+ - { - uint32 ea = EA_AY_PI_32(); - return m68ki_read_32(ea); - } - case 5: // (d16, An) - { - uint32 ea = EA_AY_DI_32(); - return m68ki_read_32(ea); - } - case 6: // (An) + (Xn) + d8 - { - uint32 ea = EA_AY_IX_32(); - return m68ki_read_32(ea); - } - case 7: - { - switch (reg) - { - case 0: // (xxx).W - { - uint32 ea = (uint32)OPER_I_16(); - return m68ki_read_32(ea); - } - case 1: // (xxx).L - { - uint32 d1 = OPER_I_16(); - uint32 d2 = OPER_I_16(); - uint32 ea = (d1 << 16) | d2; - return m68ki_read_32(ea); - } - case 2: // (d16, PC) - { - uint32 ea = EA_PCDI_32(); - return m68ki_read_32(ea); - } - case 4: // # - { - return OPER_I_32(); - } - default: fatalerror("M68kFPU: READ_EA_32: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC); - } - break; - } - default: fatalerror("M68kFPU: READ_EA_32: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC); - } - return 0; -} - -static uint64 READ_EA_64(int ea) -{ - int mode = (ea >> 3) & 0x7; - int reg = (ea & 0x7); - uint32 h1, h2; - - switch (mode) - { - case 2: // (An) - { - uint32 ea = REG_A[reg]; - h1 = m68ki_read_32(ea+0); - h2 = m68ki_read_32(ea+4); - return (uint64)(h1) << 32 | (uint64)(h2); - } - case 3: // (An)+ - { - uint32 ea = REG_A[reg]; - REG_A[reg] += 8; - h1 = m68ki_read_32(ea+0); - h2 = m68ki_read_32(ea+4); - return (uint64)(h1) << 32 | (uint64)(h2); - } - case 5: // (d16, An) - { - uint32 ea = EA_AY_DI_32(); - h1 = m68ki_read_32(ea+0); - h2 = m68ki_read_32(ea+4); - return (uint64)(h1) << 32 | (uint64)(h2); - } - case 7: - { - switch (reg) - { - case 4: // # - { - h1 = OPER_I_32(); - h2 = OPER_I_32(); - return (uint64)(h1) << 32 | (uint64)(h2); - } - case 2: // (d16, PC) - { - uint32 ea = EA_PCDI_32(); - h1 = m68ki_read_32(ea+0); - h2 = m68ki_read_32(ea+4); - return (uint64)(h1) << 32 | (uint64)(h2); - } - default: fatalerror("M68kFPU: READ_EA_64: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC); - } - break; - } - default: fatalerror("M68kFPU: READ_EA_64: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC); - } - - return 0; -} - - -static floatx80 READ_EA_FPE(int mode, int reg, uint32 di_mode_ea) -{ - floatx80 fpr; - - switch (mode) - { - case 2: // (An) - { - uint32 ea = REG_A[reg]; - fpr = load_extended_float80(ea); - break; - } - - case 3: // (An)+ - { - uint32 ea = REG_A[reg]; - REG_A[reg] += 12; - fpr = load_extended_float80(ea); - break; - } - case 5: // (d16, An) (added by JFF) - { - fpr = load_extended_float80(di_mode_ea); - break; - - } - case 7: // extended modes - { - switch (reg) - { - case 2: // (d16, PC) - { - uint32 ea = EA_PCDI_32(); - fpr = load_extended_float80(ea); - } - break; - - case 3: // (d16,PC,Dx.w) - { - uint32 ea = EA_PCIX_32(); - fpr = load_extended_float80(ea); - } - break; - case 4: // immediate (JFF) - { - uint32 ea = REG_PC; - fpr = load_extended_float80(ea); - REG_PC += 12; - } - break; - default: - fatalerror("M68kFPU: READ_EA_FPE: unhandled mode %d, reg %d, at %08X\n", mode, reg, REG_PC); - break; - } - } - break; - - default: fatalerror("M68kFPU: READ_EA_FPE: unhandled mode %d, reg %d, at %08X\n", mode, reg, REG_PC); break; - } - - return fpr; -} - -static floatx80 READ_EA_PACK(int ea) -{ - floatx80 fpr; - int mode = (ea >> 3) & 0x7; - int reg = (ea & 0x7); - - switch (mode) - { - case 2: // (An) - { - uint32 ea = REG_A[reg]; - fpr = load_pack_float80(ea); - break; - } - - case 3: // (An)+ - { - uint32 ea = REG_A[reg]; - REG_A[reg] += 12; - fpr = load_pack_float80(ea); - break; - } - - case 7: // extended modes - { - switch (reg) - { - case 3: // (d16,PC,Dx.w) - { - uint32 ea = EA_PCIX_32(); - fpr = load_pack_float80(ea); - } - break; - - default: - fatalerror("M68kFPU: READ_EA_PACK: unhandled mode %d, reg %d, at %08X\n", mode, reg, REG_PC); - break; - } - } - break; - - default: fatalerror("M68kFPU: READ_EA_PACK: unhandled mode %d, reg %d, at %08X\n", mode, reg, REG_PC); break; - } - - return fpr; -} - -static void WRITE_EA_8(int ea, uint8 data) -{ - int mode = (ea >> 3) & 0x7; - int reg = (ea & 0x7); - - switch (mode) - { - case 0: // Dn - { - REG_D[reg] = data; - break; - } - case 2: // (An) - { - uint32 ea = REG_A[reg]; - m68ki_write_8(ea, data); - break; - } - case 3: // (An)+ - { - uint32 ea = EA_AY_PI_8(); - m68ki_write_8(ea, data); - break; - } - case 4: // -(An) - { - uint32 ea = EA_AY_PD_8(); - m68ki_write_8(ea, data); - break; - } - case 5: // (d16, An) - { - uint32 ea = EA_AY_DI_8(); - m68ki_write_8(ea, data); - break; - } - case 6: // (An) + (Xn) + d8 - { - uint32 ea = EA_AY_IX_8(); - m68ki_write_8(ea, data); - break; - } - case 7: - { - switch (reg) - { - case 1: // (xxx).B - { - uint32 d1 = OPER_I_16(); - uint32 d2 = OPER_I_16(); - uint32 ea = (d1 << 16) | d2; - m68ki_write_8(ea, data); - break; - } - case 2: // (d16, PC) - { - uint32 ea = EA_PCDI_16(); - m68ki_write_8(ea, data); - break; - } - default: fatalerror("M68kFPU: WRITE_EA_8: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC); - } - break; - } - default: fatalerror("M68kFPU: WRITE_EA_8: unhandled mode %d, reg %d, data %08X at %08X\n", mode, reg, data, REG_PC); - } -} - -static void WRITE_EA_16(int ea, uint16 data) -{ - int mode = (ea >> 3) & 0x7; - int reg = (ea & 0x7); - - switch (mode) - { - case 0: // Dn - { - REG_D[reg] = data; - break; - } - case 2: // (An) - { - uint32 ea = REG_A[reg]; - m68ki_write_16(ea, data); - break; - } - case 3: // (An)+ - { - uint32 ea = EA_AY_PI_16(); - m68ki_write_16(ea, data); - break; - } - case 4: // -(An) - { - uint32 ea = EA_AY_PD_16(); - m68ki_write_16(ea, data); - break; - } - case 5: // (d16, An) - { - uint32 ea = EA_AY_DI_16(); - m68ki_write_16(ea, data); - break; - } - case 6: // (An) + (Xn) + d8 - { - uint32 ea = EA_AY_IX_16(); - m68ki_write_16(ea, data); - break; - } - case 7: - { - switch (reg) - { - case 1: // (xxx).W - { - uint32 d1 = OPER_I_16(); - uint32 d2 = OPER_I_16(); - uint32 ea = (d1 << 16) | d2; - m68ki_write_16(ea, data); - break; - } - case 2: // (d16, PC) - { - uint32 ea = EA_PCDI_16(); - m68ki_write_16(ea, data); - break; - } - default: fatalerror("M68kFPU: WRITE_EA_16: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC); - } - break; - } - default: fatalerror("M68kFPU: WRITE_EA_16: unhandled mode %d, reg %d, data %08X at %08X\n", mode, reg, data, REG_PC); - } -} - -static void WRITE_EA_32(int ea, uint32 data) -{ - int mode = (ea >> 3) & 0x7; - int reg = (ea & 0x7); - - switch (mode) - { - case 0: // Dn - { - REG_D[reg] = data; - break; - } - case 1: // An - { - REG_A[reg] = data; - break; - } - case 2: // (An) - { - uint32 ea = REG_A[reg]; - m68ki_write_32(ea, data); - break; - } - case 3: // (An)+ - { - uint32 ea = EA_AY_PI_32(); - m68ki_write_32(ea, data); - break; - } - case 4: // -(An) - { - uint32 ea = EA_AY_PD_32(); - m68ki_write_32(ea, data); - break; - } - case 5: // (d16, An) - { - uint32 ea = EA_AY_DI_32(); - m68ki_write_32(ea, data); - break; - } - case 6: // (An) + (Xn) + d8 - { - uint32 ea = EA_AY_IX_32(); - m68ki_write_32(ea, data); - break; - } - case 7: - { - switch (reg) - { - case 1: // (xxx).L - { - uint32 d1 = OPER_I_16(); - uint32 d2 = OPER_I_16(); - uint32 ea = (d1 << 16) | d2; - m68ki_write_32(ea, data); - break; - } - case 2: // (d16, PC) - { - uint32 ea = EA_PCDI_32(); - m68ki_write_32(ea, data); - break; - } - default: fatalerror("M68kFPU: WRITE_EA_32: unhandled mode %d, reg %d at %08X\n", mode, reg, REG_PC); - } - break; - } - default: fatalerror("M68kFPU: WRITE_EA_32: unhandled mode %d, reg %d, data %08X at %08X\n", mode, reg, data, REG_PC); - } -} - -static void WRITE_EA_64(int ea, uint64 data) -{ - int mode = (ea >> 3) & 0x7; - int reg = (ea & 0x7); - - switch (mode) - { - case 2: // (An) - { - uint32 ea = REG_A[reg]; - m68ki_write_32(ea, (uint32)(data >> 32)); - m68ki_write_32(ea+4, (uint32)(data)); - break; - } - case 4: // -(An) - { - uint32 ea; - REG_A[reg] -= 8; - ea = REG_A[reg]; - m68ki_write_32(ea+0, (uint32)(data >> 32)); - m68ki_write_32(ea+4, (uint32)(data)); - break; - } - case 5: // (d16, An) - { - uint32 ea = EA_AY_DI_32(); - m68ki_write_32(ea+0, (uint32)(data >> 32)); - m68ki_write_32(ea+4, (uint32)(data)); - break; - } - default: fatalerror("M68kFPU: WRITE_EA_64: unhandled mode %d, reg %d, data %08X%08X at %08X\n", mode, reg, (uint32)(data >> 32), (uint32)(data), REG_PC); - } -} - -static void WRITE_EA_FPE(int mode, int reg, floatx80 fpr, uint32 di_mode_ea) -{ - - - switch (mode) - { - case 2: // (An) - { - uint32 ea; - ea = REG_A[reg]; - store_extended_float80(ea, fpr); - break; - } - - case 3: // (An)+ - { - uint32 ea; - ea = REG_A[reg]; - store_extended_float80(ea, fpr); - REG_A[reg] += 12; - break; - } - - case 4: // -(An) - { - uint32 ea; - REG_A[reg] -= 12; - ea = REG_A[reg]; - store_extended_float80(ea, fpr); - break; - } - case 5: // (d16, An) (added by JFF) - { - // EA_AY_DI_32() should not be done here because fmovem would increase - // PC each time, reading incorrect displacement & advancing PC too much - // uint32 ea = EA_AY_DI_32(); - store_extended_float80(di_mode_ea, fpr); - break; - - } - case 7: - { - switch (reg) - { - default: fatalerror("M68kFPU: WRITE_EA_FPE: unhandled mode %d, reg %d, at %08X\n", mode, reg, REG_PC); - } - break; - } - default: fatalerror("M68kFPU: WRITE_EA_FPE: unhandled mode %d, reg %d, at %08X\n", mode, reg, REG_PC); - } -} - -static void WRITE_EA_PACK(int ea, int k, floatx80 fpr) -{ - int mode = (ea >> 3) & 0x7; - int reg = (ea & 0x7); - - switch (mode) - { - case 2: // (An) - { - uint32 ea; - ea = REG_A[reg]; - store_pack_float80(ea, k, fpr); - break; - } - - case 3: // (An)+ - { - uint32 ea; - ea = REG_A[reg]; - store_pack_float80(ea, k, fpr); - REG_A[reg] += 12; - break; - } - - case 4: // -(An) - { - uint32 ea; - REG_A[reg] -= 12; - ea = REG_A[reg]; - store_pack_float80(ea, k, fpr); - break; - } - - case 7: - { - switch (reg) - { - default: fatalerror("M68kFPU: WRITE_EA_PACK: unhandled mode %d, reg %d, at %08X\n", mode, reg, REG_PC); - } - } - break; - default: fatalerror("M68kFPU: WRITE_EA_PACK: unhandled mode %d, reg %d, at %08X\n", mode, reg, REG_PC); - } -} - - -static void fpgen_rm_reg(uint16 w2) -{ - int ea = REG_IR & 0x3f; - int rm = (w2 >> 14) & 0x1; - int src = (w2 >> 10) & 0x7; - int dst = (w2 >> 7) & 0x7; - int opmode = w2 & 0x7f; - floatx80 source; - - // fmovecr #$f, fp0 f200 5c0f - - if (rm) - { - switch (src) - { - case 0: // Long-Word Integer - { - sint32 d = READ_EA_32(ea); - source = int32_to_floatx80(d); - break; - } - case 1: // Single-precision Real - { - uint32 d = READ_EA_32(ea); - source = float32_to_floatx80(d); - break; - } - case 2: // Extended-precision Real - { - int imode = (ea >> 3) & 0x7; - int reg = (ea & 0x7); - uint32 di_mode_ea = imode == 5 ? (REG_A[reg]+MAKE_INT_16(m68ki_read_imm_16())) : 0; - source = READ_EA_FPE(imode,reg,di_mode_ea); - break; - } - case 3: // Packed-decimal Real - { - source = READ_EA_PACK(ea); - break; - } - case 4: // Word Integer - { - sint16 d = READ_EA_16(ea); - source = int32_to_floatx80((sint32)d); - break; - } - case 5: // Double-precision Real - { - uint64 d = READ_EA_64(ea); - - source = float64_to_floatx80(d); - break; - } - case 6: // Byte Integer - { - sint8 d = READ_EA_8(ea); - source = int32_to_floatx80((sint32)d); - break; - } - case 7: // FMOVECR load from constant ROM - { - switch (w2 & 0x7f) - { - case 0x0: // Pi - source.high = 0x4000; - source.low = U64(0xc90fdaa22168c235); - break; - - case 0xb: // log10(2) - source.high = 0x3ffd; - source.low = U64(0x9a209a84fbcff798); - break; - - case 0xc: // e - source.high = 0x4000; - source.low = U64(0xadf85458a2bb4a9b); - break; - - case 0xd: // log2(e) - source.high = 0x3fff; - source.low = U64(0xb8aa3b295c17f0bc); - break; - - case 0xe: // log10(e) - source.high = 0x3ffd; - source.low = U64(0xde5bd8a937287195); - break; - - case 0xf: // 0.0 - source = int32_to_floatx80((sint32)0); - break; - - case 0x30: // ln(2) - source.high = 0x3ffe; - source.low = U64(0xb17217f7d1cf79ac); - break; - - case 0x31: // ln(10) - source.high = 0x4000; - source.low = U64(0x935d8dddaaa8ac17); - break; - - case 0x32: // 1 (or 100? manuals are unclear, but 1 would make more sense) - source = int32_to_floatx80((sint32)1); - break; - - case 0x33: // 10^1 - source = int32_to_floatx80((sint32)10); - break; - - case 0x34: // 10^2 - source = int32_to_floatx80((sint32)10*10); - break; - - default: - fatalerror("fmove_rm_reg: unknown constant ROM offset %x at %08x\n", w2&0x7f, REG_PC-4); - break; - } - - // handle it right here, the usual opmode bits aren't valid in the FMOVECR case - REG_FP[dst] = source; - SET_CONDITION_CODES(REG_FP[dst]); // JFF when destination is a register, we HAVE to update FPCR - USE_CYCLES(4); - return; - } - default: fatalerror("fmove_rm_reg: invalid source specifier %x at %08X\n", src, REG_PC-4); - } - } - else - { - source = REG_FP[src]; - } - - - - switch (opmode) - { - case 0x00: // FMOVE - { - REG_FP[dst] = source; - SET_CONDITION_CODES(REG_FP[dst]); // JFF needs update condition codes - USE_CYCLES(4); - break; - } - case 0x01: // Fsint - { - sint32 temp; - temp = floatx80_to_int32(source); - REG_FP[dst] = int32_to_floatx80(temp); - SET_CONDITION_CODES(REG_FP[dst]); // JFF needs update condition codes - break; - } - case 0x03: // FsintRZ - { - sint32 temp; - temp = floatx80_to_int32_round_to_zero(source); - REG_FP[dst] = int32_to_floatx80(temp); - SET_CONDITION_CODES(REG_FP[dst]); // JFF needs update condition codes - break; - } - case 0x04: // FSQRT - { - REG_FP[dst] = floatx80_sqrt(source); - SET_CONDITION_CODES(REG_FP[dst]); - USE_CYCLES(109); - break; - } - case 0x18: // FABS - { - REG_FP[dst] = source; - REG_FP[dst].high &= 0x7fff; - SET_CONDITION_CODES(REG_FP[dst]); - USE_CYCLES(3); - break; - } - case 0x1a: // FNEG - { - REG_FP[dst] = source; - REG_FP[dst].high ^= 0x8000; - SET_CONDITION_CODES(REG_FP[dst]); - USE_CYCLES(3); - break; - } - case 0x1e: // FGETEXP - { - sint16 temp; - temp = source.high; // get the exponent - temp -= 0x3fff; // take off the bias - REG_FP[dst] = double_to_fx80((double)temp); - SET_CONDITION_CODES(REG_FP[dst]); - USE_CYCLES(6); - break; - } - case 0x60: // FSDIVS (JFF) (source has already been converted to floatx80) - case 0x20: // FDIV - { - REG_FP[dst] = floatx80_div(REG_FP[dst], source); - SET_CONDITION_CODES(REG_FP[dst]); // JFF - USE_CYCLES(43); - break; - } - case 0x22: // FADD - { - REG_FP[dst] = floatx80_add(REG_FP[dst], source); - SET_CONDITION_CODES(REG_FP[dst]); - USE_CYCLES(9); - break; - } - case 0x63: // FSMULS (JFF) (source has already been converted to floatx80) - case 0x23: // FMUL - { - REG_FP[dst] = floatx80_mul(REG_FP[dst], source); - SET_CONDITION_CODES(REG_FP[dst]); - USE_CYCLES(11); - break; - } - case 0x25: // FREM - { - REG_FP[dst] = floatx80_rem(REG_FP[dst], source); - SET_CONDITION_CODES(REG_FP[dst]); - USE_CYCLES(43); // guess - break; - } - case 0x28: // FSUB - { - REG_FP[dst] = floatx80_sub(REG_FP[dst], source); - SET_CONDITION_CODES(REG_FP[dst]); - USE_CYCLES(9); - break; - } - case 0x38: // FCMP - { - floatx80 res; - res = floatx80_sub(REG_FP[dst], source); - SET_CONDITION_CODES(res); - USE_CYCLES(7); - break; - } - case 0x3a: // FTST - { - floatx80 res; - res = source; - SET_CONDITION_CODES(res); - USE_CYCLES(7); - break; - } - - default: fatalerror("fpgen_rm_reg: unimplemented opmode %02X at %08X\n", opmode, REG_PC-4); - } -} - -static void fmove_reg_mem(uint16 w2) -{ - int ea = REG_IR & 0x3f; - int src = (w2 >> 7) & 0x7; - int dst = (w2 >> 10) & 0x7; - int k = (w2 & 0x7f); - - switch (dst) - { - case 0: // Long-Word Integer - { - sint32 d = (sint32)floatx80_to_int32(REG_FP[src]); - WRITE_EA_32(ea, d); - break; - } - case 1: // Single-precision Real - { - uint32 d = floatx80_to_float32(REG_FP[src]); - WRITE_EA_32(ea, d); - break; - } - case 2: // Extended-precision Real - { - int mode = (ea >> 3) & 0x7; - int reg = (ea & 0x7); - uint32 di_mode_ea = mode == 5 ? (REG_A[reg]+MAKE_INT_16(m68ki_read_imm_16())) : 0; - WRITE_EA_FPE(mode, reg, REG_FP[src], di_mode_ea); - break; - } - case 3: // Packed-decimal Real with Static K-factor - { - // sign-extend k - k = (k & 0x40) ? (k | 0xffffff80) : (k & 0x7f); - WRITE_EA_PACK(ea, k, REG_FP[src]); - break; - } - case 4: // Word Integer - { - WRITE_EA_16(ea, (sint16)floatx80_to_int32(REG_FP[src])); - break; - } - case 5: // Double-precision Real - { - uint64 d; - - d = floatx80_to_float64(REG_FP[src]); - - WRITE_EA_64(ea, d); - break; - } - case 6: // Byte Integer - { - WRITE_EA_8(ea, (sint8)floatx80_to_int32(REG_FP[src])); - break; - } - case 7: // Packed-decimal Real with Dynamic K-factor - { - WRITE_EA_PACK(ea, REG_D[k>>4], REG_FP[src]); - break; - } - } - - USE_CYCLES(12); -} - -static void fmove_fpcr(uint16 w2) -{ - int ea = REG_IR & 0x3f; - int dir = (w2 >> 13) & 0x1; - int reg = (w2 >> 10) & 0x7; - - if (dir) // From system control reg to - { - if (reg & 4) WRITE_EA_32(ea, REG_FPCR); - if (reg & 2) WRITE_EA_32(ea, REG_FPSR); - if (reg & 1) WRITE_EA_32(ea, REG_FPIAR); - } - else // From to system control reg - { - if (reg & 4) - { - REG_FPCR = READ_EA_32(ea); - // JFF: need to update rounding mode from softfloat module - float_rounding_mode = (REG_FPCR >> 4) & 0x3; - } - if (reg & 2) REG_FPSR = READ_EA_32(ea); - if (reg & 1) REG_FPIAR = READ_EA_32(ea); - } - - USE_CYCLES(10); -} - -static void fmovem(uint16 w2) -{ - int i; - int ea = REG_IR & 0x3f; - int dir = (w2 >> 13) & 0x1; - int mode = (w2 >> 11) & 0x3; - int reglist = w2 & 0xff; - - if (dir) // From FP regs to mem - { - switch (mode) - { - case 2: // (JFF): Static register list, postincrement or control addressing mode. - { - int imode = (ea >> 3) & 0x7; - int reg = (ea & 0x7); - int di_mode = imode == 5; - uint32 di_mode_ea = di_mode ? (REG_A[reg]+MAKE_INT_16(m68ki_read_imm_16())) : 0; - for (i=0; i < 8; i++) - { - if (reglist & (1 << i)) - { - WRITE_EA_FPE(imode,reg, REG_FP[7-i],di_mode_ea); - USE_CYCLES(2); - if (di_mode) - { - di_mode_ea += 12; - } - } - } - break; - } - case 0: // Static register list, predecrement addressing mode - { - int imode = (ea >> 3) & 0x7; - int reg = (ea & 0x7); - // the "di_mode_ea" parameter kludge is required here else WRITE_EA_FPE would have - // to call EA_AY_DI_32() (that advances PC & reads displacement) each time - // when the proper behaviour is 1) read once, 2) increment ea for each matching register - // this forces to pre-read the mode (named "imode") so we can decide to read displacement, only once - int di_mode = imode == 5; - uint32 di_mode_ea = di_mode ? (REG_A[reg]+MAKE_INT_16(m68ki_read_imm_16())) : 0; - for (i=0; i < 8; i++) - { - if (reglist & (1 << i)) - { - WRITE_EA_FPE(imode,reg, REG_FP[i],di_mode_ea); - USE_CYCLES(2); - if (di_mode) - { - di_mode_ea += 12; - } - } - } - break; - } - - default: fatalerror("040fpu0: FMOVEM: mode %d unimplemented at %08X\n", mode, REG_PC-4); - } - } - else // From mem to FP regs - { - switch (mode) - { - case 2: // Static register list, postincrement addressing mode - { - int imode = (ea >> 3) & 0x7; - int reg = (ea & 0x7); - int di_mode = imode == 5; - uint32 di_mode_ea = di_mode ? (REG_A[reg]+MAKE_INT_16(m68ki_read_imm_16())) : 0; - for (i=0; i < 8; i++) - { - if (reglist & (1 << i)) - { - REG_FP[7-i] = READ_EA_FPE(imode,reg,di_mode_ea); - USE_CYCLES(2); - if (di_mode) - { - di_mode_ea += 12; - } - } - } - break; - } - - default: fatalerror("040fpu0: FMOVEM: mode %d unimplemented at %08X\n", mode, REG_PC-4); - } - } -} - -static void fscc() -{ - // added by JFF, this seems to work properly now - int condition = OPER_I_16() & 0x3f; - - int cc = TEST_CONDITION(condition); - int mode = (REG_IR & 0x38) >> 3; - int v = (cc ? 0xff : 0x00); - - switch (mode) - { - case 0: // fscc Dx - { - // If the specified floating-point condition is true, sets the byte integer operand at - // the destination to TRUE (all ones); otherwise, sets the byte to FALSE (all zeros). - - REG_D[REG_IR & 7] = (REG_D[REG_IR & 7] & 0xFFFFFF00) | v; - break; - } - case 5: // (disp,Ax) - { - int reg = REG_IR & 7; - uint32 ea = REG_A[reg]+MAKE_INT_16(m68ki_read_imm_16()); - m68ki_write_8(ea,v); - break; - } - - default: - { - // unimplemented see fpu_uae.cpp around line 1300 - fatalerror("040fpu0: fscc: mode %d not implemented at %08X\n", mode, REG_PC-4); - } - } - USE_CYCLES(7); // JFF unsure of the number of cycles!! -} -static void fbcc16(void) -{ - sint32 offset; - int condition = REG_IR & 0x3f; - - offset = (sint16)(OPER_I_16()); - - // TODO: condition and jump!!! - if (TEST_CONDITION(condition)) - { - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - m68ki_branch_16(offset-2); - } - - USE_CYCLES(7); - } - -static void fbcc32(void) -{ - sint32 offset; - int condition = REG_IR & 0x3f; - - offset = OPER_I_32(); - - // TODO: condition and jump!!! - if (TEST_CONDITION(condition)) - { - m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */ - m68ki_branch_32(offset-4); - } - - USE_CYCLES(7); -} - - -void m68040_fpu_op0() -{ - m68ki_cpu.fpu_just_reset = 0; - - switch ((REG_IR >> 6) & 0x3) - { - case 0: - { - uint16 w2 = OPER_I_16(); - switch ((w2 >> 13) & 0x7) - { - case 0x0: // FPU ALU FP, FP - case 0x2: // FPU ALU ea, FP - { - fpgen_rm_reg(w2); - break; - } - - case 0x3: // FMOVE FP, ea - { - fmove_reg_mem(w2); - break; - } - - case 0x4: // FMOVEM ea, FPCR - case 0x5: // FMOVEM FPCR, ea - { - fmove_fpcr(w2); - break; - } - - case 0x6: // FMOVEM ea, list - case 0x7: // FMOVEM list, ea - { - fmovem(w2); - break; - } - - default: fatalerror("M68kFPU: unimplemented subop %d at %08X\n", (w2 >> 13) & 0x7, REG_PC-4); - } - break; - } - - case 1: // FScc (JFF) - { - fscc(); - break; - } - case 2: // FBcc disp16 - { - fbcc16(); - break; - } - case 3: // FBcc disp32 - { - fbcc32(); - break; - } - - default: fatalerror("M68kFPU: unimplemented main op %d at %08X\n", (m68ki_cpu.ir >> 6) & 0x3, REG_PC-4); - } -} - -static void perform_fsave(uint32 addr, int inc) -{ - if (inc) - { - // 68881 IDLE, version 0x1f - m68ki_write_32(addr, 0x1f180000); - m68ki_write_32(addr+4, 0); - m68ki_write_32(addr+8, 0); - m68ki_write_32(addr+12, 0); - m68ki_write_32(addr+16, 0); - m68ki_write_32(addr+20, 0); - m68ki_write_32(addr+24, 0x70000000); - } - else - { - m68ki_write_32(addr, 0x70000000); - m68ki_write_32(addr-4, 0); - m68ki_write_32(addr-8, 0); - m68ki_write_32(addr-12, 0); - m68ki_write_32(addr-16, 0); - m68ki_write_32(addr-20, 0); - m68ki_write_32(addr-24, 0x1f180000); - } -} - -// FRESTORE on a NULL frame reboots the FPU - all registers to NaN, the 3 status regs to 0 -static void do_frestore_null() -{ - int i; - - REG_FPCR = 0; - REG_FPSR = 0; - REG_FPIAR = 0; - for (i = 0; i < 8; i++) - { - REG_FP[i].high = 0x7fff; - REG_FP[i].low = U64(0xffffffffffffffff); - } - - // Mac IIci at 408458e6 wants an FSAVE of a just-restored NULL frame to also be NULL - // The PRM says it's possible to generate a NULL frame, but not how/when/why. (need the 68881/68882 manual!) - m68ki_cpu.fpu_just_reset = 1; -} - -void m68040_fpu_op1() -{ - int ea = REG_IR & 0x3f; - int mode = (ea >> 3) & 0x7; - int reg = (ea & 0x7); - uint32 addr, temp; - - switch ((REG_IR >> 6) & 0x3) - { - case 0: // FSAVE - { - switch (mode) - { - case 3: // (An)+ - addr = EA_AY_PI_32(); - - if (m68ki_cpu.fpu_just_reset) - { - m68ki_write_32(addr, 0); - } - else - { - // we normally generate an IDLE frame - REG_A[reg] += 6*4; - perform_fsave(addr, 1); - } - break; - - case 4: // -(An) - addr = EA_AY_PD_32(); - - if (m68ki_cpu.fpu_just_reset) - { - m68ki_write_32(addr, 0); - } - else - { - // we normally generate an IDLE frame - REG_A[reg] -= 6*4; - perform_fsave(addr, 0); - } - break; - - default: - fatalerror("M68kFPU: FSAVE unhandled mode %d reg %d at %x\n", mode, reg, REG_PC); - } - break; - } - break; - - case 1: // FRESTORE - { - switch (mode) - { - case 2: // (An) - addr = REG_A[reg]; - temp = m68ki_read_32(addr); - - // check for NULL frame - if (temp & 0xff000000) - { - // we don't handle non-NULL frames and there's no pre/post inc/dec to do here - m68ki_cpu.fpu_just_reset = 0; - } - else - { - do_frestore_null(); - } - break; - - case 3: // (An)+ - addr = EA_AY_PI_32(); - temp = m68ki_read_32(addr); - - // check for NULL frame - if (temp & 0xff000000) - { - m68ki_cpu.fpu_just_reset = 0; - - // how about an IDLE frame? - if ((temp & 0x00ff0000) == 0x00180000) - { - REG_A[reg] += 6*4; - } // check UNIMP - else if ((temp & 0x00ff0000) == 0x00380000) - { - REG_A[reg] += 14*4; - } // check BUSY - else if ((temp & 0x00ff0000) == 0x00b40000) - { - REG_A[reg] += 45*4; - } - } - else - { - do_frestore_null(); - } - break; - - default: - fatalerror("M68kFPU: FRESTORE unhandled mode %d reg %d at %x\n", mode, reg, REG_PC); - } - break; - } - break; - - default: fatalerror("m68040_fpu_op1: unimplemented op %d at %08X\n", (REG_IR >> 6) & 0x3, REG_PC-2); - } -} - - - diff --git a/machine/musashi/m68kmake.c b/machine/musashi/m68kmake.c deleted file mode 100644 index 928ebd2..0000000 --- a/machine/musashi/m68kmake.c +++ /dev/null @@ -1,1408 +0,0 @@ -/* ======================================================================== */ -/* ========================= LICENSING & COPYRIGHT ======================== */ -/* ======================================================================== */ -/* - * MUSASHI - * Version 4.60 - * - * A portable Motorola M680x0 processor emulation engine. - * Copyright Karl Stenerud. All rights reserved. - * FPU and MMU by R. Belmont. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - - - -/* ======================================================================== */ -/* ============================ CODE GENERATOR ============================ */ -/* ======================================================================== */ -/* - * This is the code generator program which will generate the opcode table - * and the final opcode handlers. - * - * It requires an input file to function (default m68k_in.c), but you can - * specify your own like so: - * - * m68kmake - * - * where output path is the path where the output files should be placed, and - * input file is the file to use for input. - * - * If you modify the input file greatly from its released form, you may have - * to tweak the configuration section a bit since I'm using static allocation - * to keep things simple. - * - * - * TODO: - build a better code generator for the move instruction. - * - Add callm and rtm instructions - * - Fix RTE to handle other format words - * - Add address error (and bus error?) handling - */ - - -static const char g_version[] = "4.60"; - -/* ======================================================================== */ -/* =============================== INCLUDES =============================== */ -/* ======================================================================== */ - -#include -#include -#include -#include -#include - - - -/* ======================================================================== */ -/* ============================= CONFIGURATION ============================ */ -/* ======================================================================== */ - -#define M68K_MAX_PATH 1024 -#define M68K_MAX_DIR 1024 - -#define MAX_LINE_LENGTH 200 /* length of 1 line */ -#define MAX_BODY_LENGTH 300 /* Number of lines in 1 function */ -#define MAX_REPLACE_LENGTH 30 /* Max number of replace strings */ -#define MAX_INSERT_LENGTH 5000 /* Max size of insert piece */ -#define MAX_NAME_LENGTH 30 /* Max length of ophandler name */ -#define MAX_SPEC_PROC_LENGTH 4 /* Max length of special processing str */ -#define MAX_SPEC_EA_LENGTH 5 /* Max length of specified EA str */ -#define EA_ALLOWED_LENGTH 11 /* Max length of ea allowed str */ -#define MAX_OPCODE_INPUT_TABLE_LENGTH 1000 /* Max length of opcode handler tbl */ -#define MAX_OPCODE_OUTPUT_TABLE_LENGTH 3000 /* Max length of opcode handler tbl */ - -/* Default filenames */ -#define FILENAME_INPUT "m68k_in.c" -#define FILENAME_PROTOTYPE "m68kops.h" -#define FILENAME_TABLE "m68kops.c" - - -/* Identifier sequences recognized by this program */ - -#define ID_INPUT_SEPARATOR "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" - -#define ID_BASE "M68KMAKE" -#define ID_PROTOTYPE_HEADER ID_BASE "_PROTOTYPE_HEADER" -#define ID_PROTOTYPE_FOOTER ID_BASE "_PROTOTYPE_FOOTER" -#define ID_TABLE_HEADER ID_BASE "_TABLE_HEADER" -#define ID_TABLE_FOOTER ID_BASE "_TABLE_FOOTER" -#define ID_TABLE_BODY ID_BASE "_TABLE_BODY" -#define ID_TABLE_START ID_BASE "_TABLE_START" -#define ID_OPHANDLER_HEADER ID_BASE "_OPCODE_HANDLER_HEADER" -#define ID_OPHANDLER_FOOTER ID_BASE "_OPCODE_HANDLER_FOOTER" -#define ID_OPHANDLER_BODY ID_BASE "_OPCODE_HANDLER_BODY" -#define ID_END ID_BASE "_END" - -#define ID_OPHANDLER_NAME ID_BASE "_OP" -#define ID_OPHANDLER_EA_AY_8 ID_BASE "_GET_EA_AY_8" -#define ID_OPHANDLER_EA_AY_16 ID_BASE "_GET_EA_AY_16" -#define ID_OPHANDLER_EA_AY_32 ID_BASE "_GET_EA_AY_32" -#define ID_OPHANDLER_OPER_AY_8 ID_BASE "_GET_OPER_AY_8" -#define ID_OPHANDLER_OPER_AY_16 ID_BASE "_GET_OPER_AY_16" -#define ID_OPHANDLER_OPER_AY_32 ID_BASE "_GET_OPER_AY_32" -#define ID_OPHANDLER_CC ID_BASE "_CC" -#define ID_OPHANDLER_NOT_CC ID_BASE "_NOT_CC" - - -#ifndef DECL_SPEC -#define DECL_SPEC -#endif /* DECL_SPEC */ - - - -/* ======================================================================== */ -/* ============================== PROTOTYPES ============================== */ -/* ======================================================================== */ - -enum { - CPU_TYPE_000=0, - CPU_TYPE_010, - CPU_TYPE_020, - CPU_TYPE_030, - CPU_TYPE_040, - NUM_CPUS -}; - -#define UNSPECIFIED "." -#define UNSPECIFIED_CH '.' - -#define HAS_NO_EA_MODE(A) (strcmp(A, "..........") == 0) -#define HAS_EA_AI(A) ((A)[0] == 'A') -#define HAS_EA_PI(A) ((A)[1] == '+') -#define HAS_EA_PD(A) ((A)[2] == '-') -#define HAS_EA_DI(A) ((A)[3] == 'D') -#define HAS_EA_IX(A) ((A)[4] == 'X') -#define HAS_EA_AW(A) ((A)[5] == 'W') -#define HAS_EA_AL(A) ((A)[6] == 'L') -#define HAS_EA_PCDI(A) ((A)[7] == 'd') -#define HAS_EA_PCIX(A) ((A)[8] == 'x') -#define HAS_EA_I(A) ((A)[9] == 'I') - -enum -{ - EA_MODE_NONE, /* No special addressing mode */ - EA_MODE_AI, /* Address register indirect */ - EA_MODE_PI, /* Address register indirect with postincrement */ - EA_MODE_PI7, /* Address register 7 indirect with postincrement */ - EA_MODE_PD, /* Address register indirect with predecrement */ - EA_MODE_PD7, /* Address register 7 indirect with predecrement */ - EA_MODE_DI, /* Address register indirect with displacement */ - EA_MODE_IX, /* Address register indirect with index */ - EA_MODE_AW, /* Absolute word */ - EA_MODE_AL, /* Absolute long */ - EA_MODE_PCDI, /* Program counter indirect with displacement */ - EA_MODE_PCIX, /* Program counter indirect with index */ - EA_MODE_I /* Immediate */ -}; - - -/* Everything we need to know about an opcode */ -typedef struct -{ - char name[MAX_NAME_LENGTH]; /* opcode handler name */ - unsigned char size; /* Size of operation */ - char spec_proc[MAX_SPEC_PROC_LENGTH]; /* Special processing mode */ - char spec_ea[MAX_SPEC_EA_LENGTH]; /* Specified effective addressing mode */ - unsigned char bits; /* Number of significant bits (used for sorting the table) */ - unsigned short op_mask; /* Mask to apply for matching an opcode to a handler */ - unsigned short op_match; /* Value to match after masking */ - char ea_allowed[EA_ALLOWED_LENGTH]; /* Effective addressing modes allowed */ - char cpu_mode[NUM_CPUS]; /* User or supervisor mode */ - char cpus[NUM_CPUS+1]; /* Allowed CPUs */ - unsigned char cycles[NUM_CPUS]; /* cycles for 000, 010, 020, 030, 040 */ -} opcode_struct; - - -/* All modifications necessary for a specific EA mode of an instruction */ -typedef struct -{ - char* fname_add; - char* ea_add; - unsigned int mask_add; - unsigned int match_add; -} ea_info_struct; - - -/* Holds the body of a function */ -typedef struct -{ - char body[MAX_BODY_LENGTH][MAX_LINE_LENGTH+1]; - int length; -} body_struct; - - -/* Holds a sequence of search / replace strings */ -typedef struct -{ - char replace[MAX_REPLACE_LENGTH][2][MAX_LINE_LENGTH+1]; - int length; -} replace_struct; - - -/* Function Prototypes */ -void error_exit(const char* fmt, ...); -void perror_exit(const char* fmt, ...); -int check_strsncpy(char* dst, char* src, int maxlength); -int check_atoi(char* str, int *result); -int skip_spaces(char* str); -int num_bits(int value); -int atoh(char* buff); -int fgetline(char* buff, int nchars, FILE* file); -int get_oper_cycles(opcode_struct* op, int ea_mode, int cpu_type); -opcode_struct* find_opcode(char* name, int size, char* spec_proc, char* spec_ea); -opcode_struct* find_illegal_opcode(void); -int extract_opcode_info(char* src, char* name, int* size, char* spec_proc, char* spec_ea); -void add_replace_string(replace_struct* replace, char* search_str, char* replace_str); -void write_body(FILE* filep, body_struct* body, replace_struct* replace); -void get_base_name(char* base_name, opcode_struct* op); -void write_function_name(FILE* filep, char* base_name); -void add_opcode_output_table_entry(opcode_struct* op, char* name); -static int DECL_SPEC compare_nof_true_bits(const void* aptr, const void* bptr); -void print_opcode_output_table(FILE* filep); -void write_table_entry(FILE* filep, opcode_struct* op); -void set_opcode_struct(opcode_struct* src, opcode_struct* dst, int ea_mode); -void generate_opcode_handler(FILE* filep, body_struct* body, replace_struct* replace, opcode_struct* opinfo, int ea_mode); -void generate_opcode_ea_variants(FILE* filep, body_struct* body, replace_struct* replace, opcode_struct* op); -void generate_opcode_cc_variants(FILE* filep, body_struct* body, replace_struct* replace, opcode_struct* op_in, int offset); -void process_opcode_handlers(FILE* filep); -void populate_table(void); -void read_insert(char* insert); - - - -/* ======================================================================== */ -/* ================================= DATA ================================= */ -/* ======================================================================== */ - -/* Name of the input file */ -char g_input_filename[M68K_MAX_PATH] = FILENAME_INPUT; - -/* File handles */ -FILE* g_input_file = NULL; -FILE* g_prototype_file = NULL; -FILE* g_table_file = NULL; - -int g_num_functions = 0; /* Number of functions processed */ -int g_num_primitives = 0; /* Number of function primitives read */ -int g_line_number = 1; /* Current line number */ - -/* Opcode handler table */ -opcode_struct g_opcode_input_table[MAX_OPCODE_INPUT_TABLE_LENGTH]; - -opcode_struct g_opcode_output_table[MAX_OPCODE_OUTPUT_TABLE_LENGTH]; -int g_opcode_output_table_length = 0; - -const ea_info_struct g_ea_info_table[13] = -{/* fname ea mask match */ - {"", "", 0x00, 0x00}, /* EA_MODE_NONE */ - {"ai", "AY_AI", 0x38, 0x10}, /* EA_MODE_AI */ - {"pi", "AY_PI", 0x38, 0x18}, /* EA_MODE_PI */ - {"pi7", "A7_PI", 0x3f, 0x1f}, /* EA_MODE_PI7 */ - {"pd", "AY_PD", 0x38, 0x20}, /* EA_MODE_PD */ - {"pd7", "A7_PD", 0x3f, 0x27}, /* EA_MODE_PD7 */ - {"di", "AY_DI", 0x38, 0x28}, /* EA_MODE_DI */ - {"ix", "AY_IX", 0x38, 0x30}, /* EA_MODE_IX */ - {"aw", "AW", 0x3f, 0x38}, /* EA_MODE_AW */ - {"al", "AL", 0x3f, 0x39}, /* EA_MODE_AL */ - {"pcdi", "PCDI", 0x3f, 0x3a}, /* EA_MODE_PCDI */ - {"pcix", "PCIX", 0x3f, 0x3b}, /* EA_MODE_PCIX */ - {"i", "I", 0x3f, 0x3c}, /* EA_MODE_I */ -}; - - -const char *const g_cc_table[16][2] = -{ - { "t", "T"}, /* 0000 */ - { "f", "F"}, /* 0001 */ - {"hi", "HI"}, /* 0010 */ - {"ls", "LS"}, /* 0011 */ - {"cc", "CC"}, /* 0100 */ - {"cs", "CS"}, /* 0101 */ - {"ne", "NE"}, /* 0110 */ - {"eq", "EQ"}, /* 0111 */ - {"vc", "VC"}, /* 1000 */ - {"vs", "VS"}, /* 1001 */ - {"pl", "PL"}, /* 1010 */ - {"mi", "MI"}, /* 1011 */ - {"ge", "GE"}, /* 1100 */ - {"lt", "LT"}, /* 1101 */ - {"gt", "GT"}, /* 1110 */ - {"le", "LE"}, /* 1111 */ -}; - -/* size to index translator (0 -> 0, 8 and 16 -> 1, 32 -> 2) */ -const int g_size_select_table[33] = -{ - 0, /* unsized */ - 0, 0, 0, 0, 0, 0, 0, 1, /* 8 */ - 0, 0, 0, 0, 0, 0, 0, 1, /* 16 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 /* 32 */ -}; - -/* Extra cycles required for certain EA modes */ -/* TODO: correct timings for 030, 040 */ -const int g_ea_cycle_table[13][NUM_CPUS][3] = -{/* 000 010 020 030 040 */ - {{ 0, 0, 0}, { 0, 0, 0}, { 0, 0, 0}, { 0, 0, 0}, { 0, 0, 0}}, /* EA_MODE_NONE */ - {{ 0, 4, 8}, { 0, 4, 8}, { 0, 4, 4}, { 0, 4, 4}, { 0, 4, 4}}, /* EA_MODE_AI */ - {{ 0, 4, 8}, { 0, 4, 8}, { 0, 4, 4}, { 0, 4, 4}, { 0, 4, 4}}, /* EA_MODE_PI */ - {{ 0, 4, 8}, { 0, 4, 8}, { 0, 4, 4}, { 0, 4, 4}, { 0, 4, 4}}, /* EA_MODE_PI7 */ - {{ 0, 6, 10}, { 0, 6, 10}, { 0, 5, 5}, { 0, 5, 5}, { 0, 5, 5}}, /* EA_MODE_PD */ - {{ 0, 6, 10}, { 0, 6, 10}, { 0, 5, 5}, { 0, 5, 5}, { 0, 5, 5}}, /* EA_MODE_PD7 */ - {{ 0, 8, 12}, { 0, 8, 12}, { 0, 5, 5}, { 0, 5, 5}, { 0, 5, 5}}, /* EA_MODE_DI */ - {{ 0, 10, 14}, { 0, 10, 14}, { 0, 7, 7}, { 0, 7, 7}, { 0, 7, 7}}, /* EA_MODE_IX */ - {{ 0, 8, 12}, { 0, 8, 12}, { 0, 4, 4}, { 0, 4, 4}, { 0, 4, 4}}, /* EA_MODE_AW */ - {{ 0, 12, 16}, { 0, 12, 16}, { 0, 4, 4}, { 0, 4, 4}, { 0, 4, 4}}, /* EA_MODE_AL */ - {{ 0, 8, 12}, { 0, 8, 12}, { 0, 5, 5}, { 0, 5, 5}, { 0, 5, 5}}, /* EA_MODE_PCDI */ - {{ 0, 10, 14}, { 0, 10, 14}, { 0, 7, 7}, { 0, 7, 7}, { 0, 7, 7}}, /* EA_MODE_PCIX */ - {{ 0, 4, 8}, { 0, 4, 8}, { 0, 2, 4}, { 0, 2, 4}, { 0, 2, 4}}, /* EA_MODE_I */ -}; - -/* Extra cycles for JMP instruction (000, 010) */ -const int g_jmp_cycle_table[13] = -{ - 0, /* EA_MODE_NONE */ - 4, /* EA_MODE_AI */ - 0, /* EA_MODE_PI */ - 0, /* EA_MODE_PI7 */ - 0, /* EA_MODE_PD */ - 0, /* EA_MODE_PD7 */ - 6, /* EA_MODE_DI */ - 10, /* EA_MODE_IX */ - 6, /* EA_MODE_AW */ - 8, /* EA_MODE_AL */ - 6, /* EA_MODE_PCDI */ - 10, /* EA_MODE_PCIX */ - 0, /* EA_MODE_I */ -}; - -/* Extra cycles for JSR instruction (000, 010) */ -const int g_jsr_cycle_table[13] = -{ - 0, /* EA_MODE_NONE */ - 4, /* EA_MODE_AI */ - 0, /* EA_MODE_PI */ - 0, /* EA_MODE_PI7 */ - 0, /* EA_MODE_PD */ - 0, /* EA_MODE_PD7 */ - 6, /* EA_MODE_DI */ - 10, /* EA_MODE_IX */ - 6, /* EA_MODE_AW */ - 8, /* EA_MODE_AL */ - 6, /* EA_MODE_PCDI */ - 10, /* EA_MODE_PCIX */ - 0, /* EA_MODE_I */ -}; - -/* Extra cycles for LEA instruction (000, 010) */ -const int g_lea_cycle_table[13] = -{ - 0, /* EA_MODE_NONE */ - 4, /* EA_MODE_AI */ - 0, /* EA_MODE_PI */ - 0, /* EA_MODE_PI7 */ - 0, /* EA_MODE_PD */ - 0, /* EA_MODE_PD7 */ - 8, /* EA_MODE_DI */ - 12, /* EA_MODE_IX */ - 8, /* EA_MODE_AW */ - 12, /* EA_MODE_AL */ - 8, /* EA_MODE_PCDI */ - 12, /* EA_MODE_PCIX */ - 0, /* EA_MODE_I */ -}; - -/* Extra cycles for PEA instruction (000, 010) */ -const int g_pea_cycle_table[13] = -{ - 0, /* EA_MODE_NONE */ - 6, /* EA_MODE_AI */ - 0, /* EA_MODE_PI */ - 0, /* EA_MODE_PI7 */ - 0, /* EA_MODE_PD */ - 0, /* EA_MODE_PD7 */ - 10, /* EA_MODE_DI */ - 14, /* EA_MODE_IX */ - 10, /* EA_MODE_AW */ - 14, /* EA_MODE_AL */ - 10, /* EA_MODE_PCDI */ - 14, /* EA_MODE_PCIX */ - 0, /* EA_MODE_I */ -}; - -/* Extra cycles for MOVEM instruction (000, 010) */ -const int g_movem_cycle_table[13] = -{ - 0, /* EA_MODE_NONE */ - 0, /* EA_MODE_AI */ - 0, /* EA_MODE_PI */ - 0, /* EA_MODE_PI7 */ - 0, /* EA_MODE_PD */ - 0, /* EA_MODE_PD7 */ - 4, /* EA_MODE_DI */ - 6, /* EA_MODE_IX */ - 4, /* EA_MODE_AW */ - 8, /* EA_MODE_AL */ - 0, /* EA_MODE_PCDI */ - 0, /* EA_MODE_PCIX */ - 0, /* EA_MODE_I */ -}; - -/* Extra cycles for MOVES instruction (010) */ -const int g_moves_cycle_table[13][3] = -{ - { 0, 0, 0}, /* EA_MODE_NONE */ - { 0, 4, 6}, /* EA_MODE_AI */ - { 0, 4, 6}, /* EA_MODE_PI */ - { 0, 4, 6}, /* EA_MODE_PI7 */ - { 0, 6, 12}, /* EA_MODE_PD */ - { 0, 6, 12}, /* EA_MODE_PD7 */ - { 0, 12, 16}, /* EA_MODE_DI */ - { 0, 16, 20}, /* EA_MODE_IX */ - { 0, 12, 16}, /* EA_MODE_AW */ - { 0, 16, 20}, /* EA_MODE_AL */ - { 0, 0, 0}, /* EA_MODE_PCDI */ - { 0, 0, 0}, /* EA_MODE_PCIX */ - { 0, 0, 0}, /* EA_MODE_I */ -}; - -/* Extra cycles for CLR instruction (010) */ -const int g_clr_cycle_table[13][3] = -{ - { 0, 0, 0}, /* EA_MODE_NONE */ - { 0, 4, 6}, /* EA_MODE_AI */ - { 0, 4, 6}, /* EA_MODE_PI */ - { 0, 4, 6}, /* EA_MODE_PI7 */ - { 0, 6, 8}, /* EA_MODE_PD */ - { 0, 6, 8}, /* EA_MODE_PD7 */ - { 0, 8, 10}, /* EA_MODE_DI */ - { 0, 10, 14}, /* EA_MODE_IX */ - { 0, 8, 10}, /* EA_MODE_AW */ - { 0, 10, 14}, /* EA_MODE_AL */ - { 0, 0, 0}, /* EA_MODE_PCDI */ - { 0, 0, 0}, /* EA_MODE_PCIX */ - { 0, 0, 0}, /* EA_MODE_I */ -}; - - - -/* ======================================================================== */ -/* =========================== UTILITY FUNCTIONS ========================== */ -/* ======================================================================== */ - -/* Print an error message and exit with status error */ -void error_exit(const char* fmt, ...) -{ - va_list args; - fprintf(stderr, "In %s, near or on line %d:\n\t", g_input_filename, g_line_number); - va_start(args, fmt); - vfprintf(stderr, fmt, args); - va_end(args); - fprintf(stderr, "\n"); - - if(g_prototype_file) fclose(g_prototype_file); - if(g_table_file) fclose(g_table_file); - if(g_input_file) fclose(g_input_file); - - exit(EXIT_FAILURE); -} - -/* Print an error message, call perror(), and exit with status error */ -void perror_exit(const char* fmt, ...) -{ - va_list args; - va_start(args, fmt); - vfprintf(stderr, fmt, args); - va_end(args); - perror(""); - - if(g_prototype_file) fclose(g_prototype_file); - if(g_table_file) fclose(g_table_file); - if(g_input_file) fclose(g_input_file); - - exit(EXIT_FAILURE); -} - - -/* copy until 0 or space and exit with error if we read too far */ -int check_strsncpy(char* dst, char* src, int maxlength) -{ - char* p = dst; - while(*src && *src != ' ') - { - *p++ = *src++; - if(p - dst > maxlength) - error_exit("Field too long"); - } - *p = 0; - return p - dst; -} - -/* copy until 0 or specified character and exit with error if we read too far */ -int check_strcncpy(char* dst, char* src, char delim, int maxlength) -{ - char* p = dst; - while(*src && *src != delim) - { - *p++ = *src++; - if(p - dst > maxlength) - error_exit("Field too long"); - } - *p = 0; - return p - dst; -} - -/* convert ascii to integer and exit with error if we find invalid data */ -int check_atoi(char* str, int *result) -{ - int accum = 0; - char* p = str; - while(*p >= '0' && *p <= '9') - { - accum *= 10; - accum += *p++ - '0'; - } - if(*p != ' ' && *p != 0) - error_exit("Malformed integer value (%c)", *p); - *result = accum; - return p - str; -} - -/* Skip past spaces in a string */ -int skip_spaces(char* str) -{ - char* p = str; - - while(*p == ' ') - p++; - - return p - str; -} - -/* Count the number of set bits in a value */ -int num_bits(int value) -{ - value = ((value & 0xaaaa) >> 1) + (value & 0x5555); - value = ((value & 0xcccc) >> 2) + (value & 0x3333); - value = ((value & 0xf0f0) >> 4) + (value & 0x0f0f); - value = ((value & 0xff00) >> 8) + (value & 0x00ff); - return value; -} - -/* Convert a hex value written in ASCII */ -int atoh(char* buff) -{ - int accum = 0; - - for(;;buff++) - { - if(*buff >= '0' && *buff <= '9') - { - accum <<= 4; - accum += *buff - '0'; - } - else if(*buff >= 'a' && *buff <= 'f') - { - accum <<= 4; - accum += *buff - 'a' + 10; - } - else break; - } - return accum; -} - -/* Get a line of text from a file, discarding any end-of-line characters */ -int fgetline(char* buff, int nchars, FILE* file) -{ - int length; - - if(fgets(buff, nchars, file) == NULL) - return -1; - if(buff[0] == '\r') - memmove(buff, buff + 1, nchars - 1); - - length = strlen(buff); - while(length && (buff[length-1] == '\r' || buff[length-1] == '\n')) - length--; - buff[length] = 0; - g_line_number++; - - return length; -} - - - -/* ======================================================================== */ -/* =========================== HELPER FUNCTIONS =========================== */ -/* ======================================================================== */ - -/* Calculate the number of cycles an opcode requires */ -int get_oper_cycles(opcode_struct* op, int ea_mode, int cpu_type) -{ - int size = g_size_select_table[op->size]; - - if(op->cpus[cpu_type] == '.') - return 0; - - if(cpu_type < CPU_TYPE_020) - { - if(cpu_type == CPU_TYPE_010) - { - if(strcmp(op->name, "moves") == 0) - return op->cycles[cpu_type] + g_moves_cycle_table[ea_mode][size]; - if(strcmp(op->name, "clr") == 0) - return op->cycles[cpu_type] + g_clr_cycle_table[ea_mode][size]; - } - - /* ASG: added these cases -- immediate modes take 2 extra cycles here */ - if(cpu_type == CPU_TYPE_000 && ea_mode == EA_MODE_I && - ((strcmp(op->name, "add") == 0 && strcmp(op->spec_proc, "er") == 0) || - strcmp(op->name, "adda") == 0 || - (strcmp(op->name, "and") == 0 && strcmp(op->spec_proc, "er") == 0) || - (strcmp(op->name, "or") == 0 && strcmp(op->spec_proc, "er") == 0) || - (strcmp(op->name, "sub") == 0 && strcmp(op->spec_proc, "er") == 0) || - strcmp(op->name, "suba") == 0)) - return op->cycles[cpu_type] + g_ea_cycle_table[ea_mode][cpu_type][size] + 2; - - if(strcmp(op->name, "jmp") == 0) - return op->cycles[cpu_type] + g_jmp_cycle_table[ea_mode]; - if(strcmp(op->name, "jsr") == 0) - return op->cycles[cpu_type] + g_jsr_cycle_table[ea_mode]; - if(strcmp(op->name, "lea") == 0) - return op->cycles[cpu_type] + g_lea_cycle_table[ea_mode]; - if(strcmp(op->name, "pea") == 0) - return op->cycles[cpu_type] + g_pea_cycle_table[ea_mode]; - if(strcmp(op->name, "movem") == 0) - return op->cycles[cpu_type] + g_movem_cycle_table[ea_mode]; - } - return op->cycles[cpu_type] + g_ea_cycle_table[ea_mode][cpu_type][size]; -} - -/* Find an opcode in the opcode handler list */ -opcode_struct* find_opcode(char* name, int size, char* spec_proc, char* spec_ea) -{ - opcode_struct* op; - - - for(op = g_opcode_input_table;op < &g_opcode_input_table[MAX_OPCODE_INPUT_TABLE_LENGTH];op++) - { - if( strcmp(name, op->name) == 0 && - (size == op->size) && - strcmp(spec_proc, op->spec_proc) == 0 && - strcmp(spec_ea, op->spec_ea) == 0) - return op; - } - return NULL; -} - -/* Specifically find the illegal opcode in the list */ -opcode_struct* find_illegal_opcode(void) -{ - opcode_struct* op; - - for(op = g_opcode_input_table;op < &g_opcode_input_table[MAX_OPCODE_INPUT_TABLE_LENGTH];op++) - { - if(strcmp(op->name, "illegal") == 0) - return op; - } - return NULL; -} - -/* Parse an opcode handler name */ -int extract_opcode_info(char* src, char* name, int* size, char* spec_proc, char* spec_ea) -{ - char* ptr = strstr(src, ID_OPHANDLER_NAME); - - if(ptr == NULL) - return 0; - - ptr += strlen(ID_OPHANDLER_NAME) + 1; - - ptr += check_strcncpy(name, ptr, ',', MAX_NAME_LENGTH); - if(*ptr != ',') return 0; - ptr++; - ptr += skip_spaces(ptr); - - *size = atoi(ptr); - ptr = strstr(ptr, ","); - if(ptr == NULL) return 0; - ptr++; - ptr += skip_spaces(ptr); - - ptr += check_strcncpy(spec_proc, ptr, ',', MAX_SPEC_PROC_LENGTH); - if(*ptr != ',') return 0; - ptr++; - ptr += skip_spaces(ptr); - - ptr += check_strcncpy(spec_ea, ptr, ')', MAX_SPEC_EA_LENGTH); - if(*ptr != ')') return 0; - ptr++; - ptr += skip_spaces(ptr); - - return 1; -} - - -/* Add a search/replace pair to a replace structure */ -void add_replace_string(replace_struct* replace, char* search_str, char* replace_str) -{ - if(replace->length >= MAX_REPLACE_LENGTH) - error_exit("overflow in replace structure"); - - strcpy(replace->replace[replace->length][0], search_str); - strcpy(replace->replace[replace->length++][1], replace_str); -} - -/* Write a function body while replacing any selected strings */ -void write_body(FILE* filep, body_struct* body, replace_struct* replace) -{ - int i; - int j; - char* ptr; - char output[MAX_LINE_LENGTH+1]; - char temp_buff[MAX_LINE_LENGTH+1]; - int found; - - for(i=0;ilength;i++) - { - strcpy(output, body->body[i]); - /* Check for the base directive header */ - if(strstr(output, ID_BASE) != NULL) - { - /* Search for any text we need to replace */ - found = 0; - for(j=0;jlength;j++) - { - ptr = strstr(output, replace->replace[j][0]); - if(ptr) - { - /* We found something to replace */ - found = 1; - strcpy(temp_buff, ptr+strlen(replace->replace[j][0])); - strcpy(ptr, replace->replace[j][1]); - strcat(ptr, temp_buff); - } - } - /* Found a directive with no matching replace string */ - if(!found) - error_exit("Unknown " ID_BASE " directive [%s]", output); - } - fprintf(filep, "%s\n", output); - } - fprintf(filep, "\n\n"); -} - -/* Generate a base function name from an opcode struct */ -void get_base_name(char* base_name, opcode_struct* op) -{ - sprintf(base_name, "m68k_op_%s", op->name); - if(op->size > 0) - sprintf(base_name+strlen(base_name), "_%d", op->size); - if(strcmp(op->spec_proc, UNSPECIFIED) != 0) - sprintf(base_name+strlen(base_name), "_%s", op->spec_proc); - if(strcmp(op->spec_ea, UNSPECIFIED) != 0) - sprintf(base_name+strlen(base_name), "_%s", op->spec_ea); -} - -/* Write the name of an opcode handler function */ -void write_function_name(FILE* filep, char* base_name) -{ - fprintf(filep, "static void %s(void)\n", base_name); -} - -void add_opcode_output_table_entry(opcode_struct* op, char* name) -{ - opcode_struct* ptr; - if(g_opcode_output_table_length > MAX_OPCODE_OUTPUT_TABLE_LENGTH) - error_exit("Opcode output table overflow"); - - ptr = g_opcode_output_table + g_opcode_output_table_length++; - - *ptr = *op; - strcpy(ptr->name, name); - ptr->bits = num_bits(ptr->op_mask); -} - -/* - * Comparison function for qsort() - * For entries with an equal number of set bits in - * the mask compare the match values - */ -static int DECL_SPEC compare_nof_true_bits(const void* aptr, const void* bptr) -{ - const opcode_struct *a = aptr, *b = bptr; - if(a->bits != b->bits) - return a->bits - b->bits; - if(a->op_mask != b->op_mask) - return a->op_mask - b->op_mask; - return a->op_match - b->op_match; -} - -void print_opcode_output_table(FILE* filep) -{ - int i; - qsort((void *)g_opcode_output_table, g_opcode_output_table_length, sizeof(g_opcode_output_table[0]), compare_nof_true_bits); - - for(i=0;iname, op->op_mask, op->op_match); - - for(i=0;icycles[i]); - if(i < NUM_CPUS-1) - fprintf(filep, ", "); - } - - fprintf(filep, "}},\n"); -} - -/* Fill out an opcode struct with a specific addressing mode of the source opcode struct */ -void set_opcode_struct(opcode_struct* src, opcode_struct* dst, int ea_mode) -{ - int i; - - *dst = *src; - - for(i=0;icycles[i] = get_oper_cycles(dst, ea_mode, i); - if(strcmp(dst->spec_ea, UNSPECIFIED) == 0 && ea_mode != EA_MODE_NONE) - sprintf(dst->spec_ea, "%s", g_ea_info_table[ea_mode].fname_add); - dst->op_mask |= g_ea_info_table[ea_mode].mask_add; - dst->op_match |= g_ea_info_table[ea_mode].match_add; -} - - -/* Generate a final opcode handler from the provided data */ -void generate_opcode_handler(FILE* filep, body_struct* body, replace_struct* replace, opcode_struct* opinfo, int ea_mode) -{ - char str[MAX_LINE_LENGTH+1]; - opcode_struct* op = malloc(sizeof(opcode_struct)); - - /* Set the opcode structure and write the tables, prototypes, etc */ - set_opcode_struct(opinfo, op, ea_mode); - get_base_name(str, op); - add_opcode_output_table_entry(op, str); - write_function_name(filep, str); - - /* Add any replace strings needed */ - if(ea_mode != EA_MODE_NONE) - { - sprintf(str, "EA_%s_8()", g_ea_info_table[ea_mode].ea_add); - add_replace_string(replace, ID_OPHANDLER_EA_AY_8, str); - sprintf(str, "EA_%s_16()", g_ea_info_table[ea_mode].ea_add); - add_replace_string(replace, ID_OPHANDLER_EA_AY_16, str); - sprintf(str, "EA_%s_32()", g_ea_info_table[ea_mode].ea_add); - add_replace_string(replace, ID_OPHANDLER_EA_AY_32, str); - sprintf(str, "OPER_%s_8()", g_ea_info_table[ea_mode].ea_add); - add_replace_string(replace, ID_OPHANDLER_OPER_AY_8, str); - sprintf(str, "OPER_%s_16()", g_ea_info_table[ea_mode].ea_add); - add_replace_string(replace, ID_OPHANDLER_OPER_AY_16, str); - sprintf(str, "OPER_%s_32()", g_ea_info_table[ea_mode].ea_add); - add_replace_string(replace, ID_OPHANDLER_OPER_AY_32, str); - } - - /* Now write the function body with the selected replace strings */ - write_body(filep, body, replace); - g_num_functions++; - free(op); -} - -/* Generate opcode variants based on available addressing modes */ -void generate_opcode_ea_variants(FILE* filep, body_struct* body, replace_struct* replace, opcode_struct* op) -{ - int old_length = replace->length; - - /* No ea modes available for this opcode */ - if(HAS_NO_EA_MODE(op->ea_allowed)) - { - generate_opcode_handler(filep, body, replace, op, EA_MODE_NONE); - return; - } - - /* Check for and create specific opcodes for each available addressing mode */ - if(HAS_EA_AI(op->ea_allowed)) - generate_opcode_handler(filep, body, replace, op, EA_MODE_AI); - replace->length = old_length; - if(HAS_EA_PI(op->ea_allowed)) - { - generate_opcode_handler(filep, body, replace, op, EA_MODE_PI); - replace->length = old_length; - if(op->size == 8) - generate_opcode_handler(filep, body, replace, op, EA_MODE_PI7); - } - replace->length = old_length; - if(HAS_EA_PD(op->ea_allowed)) - { - generate_opcode_handler(filep, body, replace, op, EA_MODE_PD); - replace->length = old_length; - if(op->size == 8) - generate_opcode_handler(filep, body, replace, op, EA_MODE_PD7); - } - replace->length = old_length; - if(HAS_EA_DI(op->ea_allowed)) - generate_opcode_handler(filep, body, replace, op, EA_MODE_DI); - replace->length = old_length; - if(HAS_EA_IX(op->ea_allowed)) - generate_opcode_handler(filep, body, replace, op, EA_MODE_IX); - replace->length = old_length; - if(HAS_EA_AW(op->ea_allowed)) - generate_opcode_handler(filep, body, replace, op, EA_MODE_AW); - replace->length = old_length; - if(HAS_EA_AL(op->ea_allowed)) - generate_opcode_handler(filep, body, replace, op, EA_MODE_AL); - replace->length = old_length; - if(HAS_EA_PCDI(op->ea_allowed)) - generate_opcode_handler(filep, body, replace, op, EA_MODE_PCDI); - replace->length = old_length; - if(HAS_EA_PCIX(op->ea_allowed)) - generate_opcode_handler(filep, body, replace, op, EA_MODE_PCIX); - replace->length = old_length; - if(HAS_EA_I(op->ea_allowed)) - generate_opcode_handler(filep, body, replace, op, EA_MODE_I); - replace->length = old_length; -} - -/* Generate variants of condition code opcodes */ -void generate_opcode_cc_variants(FILE* filep, body_struct* body, replace_struct* replace, opcode_struct* op_in, int offset) -{ - char repl[20]; - char replnot[20]; - int i; - int old_length = replace->length; - opcode_struct* op = malloc(sizeof(opcode_struct)); - - *op = *op_in; - - op->op_mask |= 0x0f00; - - /* Do all condition codes except t and f */ - for(i=2;i<16;i++) - { - /* Add replace strings for this condition code */ - sprintf(repl, "COND_%s()", g_cc_table[i][1]); - sprintf(replnot, "COND_NOT_%s()", g_cc_table[i][1]); - - add_replace_string(replace, ID_OPHANDLER_CC, repl); - add_replace_string(replace, ID_OPHANDLER_NOT_CC, replnot); - - /* Set the new opcode info */ - strcpy(op->name+offset, g_cc_table[i][0]); - - op->op_match = (op->op_match & 0xf0ff) | (i<<8); - - /* Generate all opcode variants for this modified opcode */ - generate_opcode_ea_variants(filep, body, replace, op); - /* Remove the above replace strings */ - replace->length = old_length; - } - free(op); -} - -/* Process the opcode handlers section of the input file */ -void process_opcode_handlers(FILE* filep) -{ - FILE* input_file = g_input_file; - char func_name[MAX_LINE_LENGTH+1]; - char oper_name[MAX_LINE_LENGTH+1]; - int oper_size; - char oper_spec_proc[MAX_LINE_LENGTH+1]; - char oper_spec_ea[MAX_LINE_LENGTH+1]; - opcode_struct* opinfo; - replace_struct* replace = malloc(sizeof(replace_struct)); - body_struct* body = malloc(sizeof(body_struct)); - - for(;;) - { - /* Find the first line of the function */ - func_name[0] = 0; - while(strstr(func_name, ID_OPHANDLER_NAME) == NULL) - { - if(strcmp(func_name, ID_INPUT_SEPARATOR) == 0) - { - free(replace); - free(body); - return; /* all done */ - } - if(fgetline(func_name, MAX_LINE_LENGTH, input_file) < 0) - error_exit("Premature end of file when getting function name"); - } - /* Get the rest of the function */ - for(body->length=0;;body->length++) - { - if(body->length > MAX_BODY_LENGTH) - error_exit("Function too long"); - - if(fgetline(body->body[body->length], MAX_LINE_LENGTH, input_file) < 0) - error_exit("Premature end of file when getting function body"); - - if(body->body[body->length][0] == '}') - { - body->length++; - break; - } - } - - g_num_primitives++; - - /* Extract the function name information */ - if(!extract_opcode_info(func_name, oper_name, &oper_size, oper_spec_proc, oper_spec_ea)) - error_exit("Invalid " ID_OPHANDLER_NAME " format"); - - /* Find the corresponding table entry */ - opinfo = find_opcode(oper_name, oper_size, oper_spec_proc, oper_spec_ea); - if(opinfo == NULL) - error_exit("Unable to find matching table entry for %s", func_name); - - replace->length = 0; - - /* Generate opcode variants */ - if(strcmp(opinfo->name, "bcc") == 0 || strcmp(opinfo->name, "scc") == 0) - generate_opcode_cc_variants(filep, body, replace, opinfo, 1); - else if(strcmp(opinfo->name, "dbcc") == 0) - generate_opcode_cc_variants(filep, body, replace, opinfo, 2); - else if(strcmp(opinfo->name, "trapcc") == 0) - generate_opcode_cc_variants(filep, body, replace, opinfo, 4); - else - generate_opcode_ea_variants(filep, body, replace, opinfo); - } - - free(replace); - free(body); -} - - -/* Populate the opcode handler table from the input file */ -void populate_table(void) -{ - char* ptr; - char bitpattern[17]; - opcode_struct* op; - char buff[MAX_LINE_LENGTH]; - int i; - int temp; - - buff[0] = 0; - - /* Find the start of the table */ - while(strcmp(buff, ID_TABLE_START) != 0) - if(fgetline(buff, MAX_LINE_LENGTH, g_input_file) < 0) - error_exit("(table_start) Premature EOF while reading table"); - - /* Process the entire table */ - for(op = g_opcode_input_table;;op++) - { - if(fgetline(buff, MAX_LINE_LENGTH, g_input_file) < 0) - error_exit("(inline) Premature EOF while reading table"); - if(strlen(buff) == 0) - continue; - /* We finish when we find an input separator */ - if(strcmp(buff, ID_INPUT_SEPARATOR) == 0) - break; - - /* Extract the info from the table */ - ptr = buff; - - /* Name */ - ptr += skip_spaces(ptr); - ptr += check_strsncpy(op->name, ptr, MAX_NAME_LENGTH); - - /* Size */ - ptr += skip_spaces(ptr); - ptr += check_atoi(ptr, &temp); - op->size = (unsigned char)temp; - - /* Special processing */ - ptr += skip_spaces(ptr); - ptr += check_strsncpy(op->spec_proc, ptr, MAX_SPEC_PROC_LENGTH); - - /* Specified EA Mode */ - ptr += skip_spaces(ptr); - ptr += check_strsncpy(op->spec_ea, ptr, MAX_SPEC_EA_LENGTH); - - /* Bit Pattern (more processing later) */ - ptr += skip_spaces(ptr); - ptr += check_strsncpy(bitpattern, ptr, 17); - - /* Allowed Addressing Mode List */ - ptr += skip_spaces(ptr); - ptr += check_strsncpy(op->ea_allowed, ptr, EA_ALLOWED_LENGTH); - - /* CPU operating mode (U = user or supervisor, S = supervisor only */ - ptr += skip_spaces(ptr); - for(i=0;icpu_mode[i] = *ptr++; - ptr += skip_spaces(ptr); - } - - /* Allowed CPUs for this instruction */ - for(i=0;icpus[i] = UNSPECIFIED_CH; - op->cycles[i] = 0; - ptr++; - } - else - { - op->cpus[i] = '0' + i; - ptr += check_atoi(ptr, &temp); - op->cycles[i] = (unsigned char)temp; - } - } - - /* generate mask and match from bitpattern */ - op->op_mask = 0; - op->op_match = 0; - for(i=0;i<16;i++) - { - op->op_mask |= (bitpattern[i] != '.') << (15-i); - op->op_match |= (bitpattern[i] == '1') << (15-i); - } - } - /* Terminate the list */ - op->name[0] = 0; -} - -/* Read a header or footer insert from the input file */ -void read_insert(char* insert) -{ - char* ptr = insert; - char* overflow = insert + MAX_INSERT_LENGTH - MAX_LINE_LENGTH; - int length; - char* first_blank = NULL; - - first_blank = NULL; - - /* Skip any leading blank lines */ - for(length = 0;length == 0;length = fgetline(ptr, MAX_LINE_LENGTH, g_input_file)) - if(ptr >= overflow) - error_exit("Buffer overflow reading inserts"); - if(length < 0) - error_exit("Premature EOF while reading inserts"); - - /* Advance and append newline */ - ptr += length; - strcpy(ptr++, "\n"); - - /* Read until next separator */ - for(;;) - { - /* Read a new line */ - if(ptr >= overflow) - error_exit("Buffer overflow reading inserts"); - if((length = fgetline(ptr, MAX_LINE_LENGTH, g_input_file)) < 0) - error_exit("Premature EOF while reading inserts"); - - /* Stop if we read a separator */ - if(strcmp(ptr, ID_INPUT_SEPARATOR) == 0) - break; - - /* keep track in case there are trailing blanks */ - if(length == 0) - { - if(first_blank == NULL) - first_blank = ptr; - } - else - first_blank = NULL; - - /* Advance and append newline */ - ptr += length; - strcpy(ptr++, "\n"); - } - - /* kill any trailing blank lines */ - if(first_blank) - ptr = first_blank; - *ptr++ = 0; -} - - - -/* ======================================================================== */ -/* ============================= MAIN FUNCTION ============================ */ -/* ======================================================================== */ - -int main(int argc, char **argv) -{ - /* File stuff */ - char output_path[M68K_MAX_DIR] = ""; - char filename[M68K_MAX_PATH*2]; - /* Section identifier */ - char section_id[MAX_LINE_LENGTH+1]; - /* Inserts */ - char temp_insert[MAX_INSERT_LENGTH+1]; - char prototype_footer_insert[MAX_INSERT_LENGTH+1]; - char table_header_insert[MAX_INSERT_LENGTH+1]; - char table_footer_insert[MAX_INSERT_LENGTH+1]; - char ophandler_header_insert[MAX_INSERT_LENGTH+1]; - char ophandler_footer_insert[MAX_INSERT_LENGTH+1]; - /* Flags if we've processed certain parts already */ - int prototype_header_read = 0; - int prototype_footer_read = 0; - int table_header_read = 0; - int table_footer_read = 0; - int ophandler_header_read = 0; - int ophandler_footer_read = 0; - int table_body_read = 0; - int ophandler_body_read = 0; - - printf("\n\tMusashi v%s 68000, 68008, 68010, 68EC020, 68020, 68EC030, 68030, 68EC040, 68040 emulator\n", g_version); - printf("\t\tCopyright Karl Stenerud (kstenerud@gmail.com)\n\n"); - - /* Check if output path and source for the input file are given */ - if(argc > 1) - { - char *ptr; - strcpy(output_path, argv[1]); - - for(ptr = strchr(output_path, '\\'); ptr; ptr = strchr(ptr, '\\')) - *ptr = '/'; - if(output_path[strlen(output_path)-1] != '/') - strcat(output_path, "/"); - if(argc > 2) - strcpy(g_input_filename, argv[2]); - } - - - /* Open the files we need */ - sprintf(filename, "%s%s", output_path, FILENAME_PROTOTYPE); - if((g_prototype_file = fopen(filename, "wt")) == NULL) - perror_exit("Unable to create prototype file (%s)\n", filename); - - sprintf(filename, "%s%s", output_path, FILENAME_TABLE); - if((g_table_file = fopen(filename, "wt")) == NULL) - perror_exit("Unable to create table file (%s)\n", filename); - - if((g_input_file=fopen(g_input_filename, "rt")) == NULL) - perror_exit("can't open %s for input", g_input_filename); - - - /* Get to the first section of the input file */ - section_id[0] = 0; - while(strcmp(section_id, ID_INPUT_SEPARATOR) != 0) - if(fgetline(section_id, MAX_LINE_LENGTH, g_input_file) < 0) - error_exit("Premature EOF while reading input file"); - - /* Now process all sections */ - for(;;) - { - if(fgetline(section_id, MAX_LINE_LENGTH, g_input_file) < 0) - error_exit("Premature EOF while reading input file"); - if(strcmp(section_id, ID_PROTOTYPE_HEADER) == 0) - { - if(prototype_header_read) - error_exit("Duplicate prototype header"); - read_insert(temp_insert); - fprintf(g_prototype_file, "%s\n\n", temp_insert); - prototype_header_read = 1; - } - else if(strcmp(section_id, ID_TABLE_HEADER) == 0) - { - if(table_header_read) - error_exit("Duplicate table header"); - read_insert(table_header_insert); - table_header_read = 1; - } - else if(strcmp(section_id, ID_OPHANDLER_HEADER) == 0) - { - if(ophandler_header_read) - error_exit("Duplicate opcode handler header"); - read_insert(ophandler_header_insert); - ophandler_header_read = 1; - } - else if(strcmp(section_id, ID_PROTOTYPE_FOOTER) == 0) - { - if(prototype_footer_read) - error_exit("Duplicate prototype footer"); - read_insert(prototype_footer_insert); - prototype_footer_read = 1; - } - else if(strcmp(section_id, ID_TABLE_FOOTER) == 0) - { - if(table_footer_read) - error_exit("Duplicate table footer"); - read_insert(table_footer_insert); - table_footer_read = 1; - } - else if(strcmp(section_id, ID_OPHANDLER_FOOTER) == 0) - { - if(ophandler_footer_read) - error_exit("Duplicate opcode handler footer"); - read_insert(ophandler_footer_insert); - ophandler_footer_read = 1; - } - else if(strcmp(section_id, ID_TABLE_BODY) == 0) - { - if(!prototype_header_read) - error_exit("Table body encountered before prototype header"); - if(!table_header_read) - error_exit("Table body encountered before table header"); - if(!ophandler_header_read) - error_exit("Table body encountered before opcode handler header"); - - if(table_body_read) - error_exit("Duplicate table body"); - - populate_table(); - table_body_read = 1; - } - else if(strcmp(section_id, ID_OPHANDLER_BODY) == 0) - { - if(!prototype_header_read) - error_exit("Opcode handlers encountered before prototype header"); - if(!table_header_read) - error_exit("Opcode handlers encountered before table header"); - if(!ophandler_header_read) - error_exit("Opcode handlers encountered before opcode handler header"); - if(!table_body_read) - error_exit("Opcode handlers encountered before table body"); - - if(ophandler_body_read) - error_exit("Duplicate opcode handler section"); - - fprintf(g_table_file, "%s\n\n", ophandler_header_insert); - process_opcode_handlers(g_table_file); - fprintf(g_table_file, "%s\n\n", ophandler_footer_insert); - - ophandler_body_read = 1; - } - else if(strcmp(section_id, ID_END) == 0) - { - /* End of input file. Do a sanity check and then write footers */ - if(!prototype_header_read) - error_exit("Missing prototype header"); - if(!prototype_footer_read) - error_exit("Missing prototype footer"); - if(!table_header_read) - error_exit("Missing table header"); - if(!table_footer_read) - error_exit("Missing table footer"); - if(!table_body_read) - error_exit("Missing table body"); - if(!ophandler_header_read) - error_exit("Missing opcode handler header"); - if(!ophandler_footer_read) - error_exit("Missing opcode handler footer"); - if(!ophandler_body_read) - error_exit("Missing opcode handler body"); - - fprintf(g_table_file, "%s\n\n", table_header_insert); - print_opcode_output_table(g_table_file); - fprintf(g_table_file, "%s\n\n", table_footer_insert); - - fprintf(g_prototype_file, "%s\n\n", prototype_footer_insert); - - break; - } - else - { - error_exit("Unknown section identifier: %s", section_id); - } - } - - /* Close all files and exit */ - fclose(g_prototype_file); - fclose(g_table_file); - fclose(g_input_file); - - printf("Generated %d opcode handlers from %d primitives\n", g_num_functions, g_num_primitives); - - return 0; -} - - - -/* ======================================================================== */ -/* ============================== END OF FILE ============================= */ -/* ======================================================================== */ diff --git a/machine/musashi/m68kmmu.h b/machine/musashi/m68kmmu.h deleted file mode 100644 index b6d9098..0000000 --- a/machine/musashi/m68kmmu.h +++ /dev/null @@ -1,321 +0,0 @@ -/* - m68kmmu.h - PMMU implementation for 68851/68030/68040 - - By R. Belmont - - Copyright Nicola Salmoria and the MAME Team. - Visit http://mamedev.org for licensing and usage restrictions. -*/ - -/* - pmmu_translate_addr: perform 68851/68030-style PMMU address translation -*/ -uint pmmu_translate_addr(uint addr_in) -{ - uint32 addr_out, tbl_entry = 0, tbl_entry2, tamode = 0, tbmode = 0, tcmode = 0; - uint root_aptr, root_limit, tofs, is, abits, bbits, cbits; - uint resolved, tptr, shift; - - resolved = 0; - addr_out = addr_in; - - // if SRP is enabled and we're in supervisor mode, use it - if ((m68ki_cpu.mmu_tc & 0x02000000) && (m68ki_get_sr() & 0x2000)) - { - root_aptr = m68ki_cpu.mmu_srp_aptr; - root_limit = m68ki_cpu.mmu_srp_limit; - } - else // else use the CRP - { - root_aptr = m68ki_cpu.mmu_crp_aptr; - root_limit = m68ki_cpu.mmu_crp_limit; - } - - // get initial shift (# of top bits to ignore) - is = (m68ki_cpu.mmu_tc>>16) & 0xf; - abits = (m68ki_cpu.mmu_tc>>12)&0xf; - bbits = (m68ki_cpu.mmu_tc>>8)&0xf; - cbits = (m68ki_cpu.mmu_tc>>4)&0xf; - -// fprintf(stderr,"PMMU: tcr %08x limit %08x aptr %08x is %x abits %d bbits %d cbits %d\n", m68ki_cpu.mmu_tc, root_limit, root_aptr, is, abits, bbits, cbits); - - // get table A offset - tofs = (addr_in<>(32-abits); - - // find out what format table A is - switch (root_limit & 3) - { - case 0: // invalid, should cause MMU exception - case 1: // page descriptor, should cause direct mapping - fatalerror("680x0 PMMU: Unhandled root mode\n"); - break; - - case 2: // valid 4 byte descriptors - tofs *= 4; -// fprintf(stderr,"PMMU: reading table A entry at %08x\n", tofs + (root_aptr & 0xfffffffc)); - tbl_entry = m68k_read_memory_32( tofs + (root_aptr & 0xfffffffc)); - tamode = tbl_entry & 3; -// fprintf(stderr,"PMMU: addr %08x entry %08x mode %x tofs %x\n", addr_in, tbl_entry, tamode, tofs); - break; - - case 3: // valid 8 byte descriptors - tofs *= 8; -// fprintf(stderr,"PMMU: reading table A entries at %08x\n", tofs + (root_aptr & 0xfffffffc)); - tbl_entry2 = m68k_read_memory_32( tofs + (root_aptr & 0xfffffffc)); - tbl_entry = m68k_read_memory_32( tofs + (root_aptr & 0xfffffffc)+4); - tamode = tbl_entry2 & 3; -// fprintf(stderr,"PMMU: addr %08x entry %08x entry2 %08x mode %x tofs %x\n", addr_in, tbl_entry, tbl_entry2, tamode, tofs); - break; - } - - // get table B offset and pointer - tofs = (addr_in<<(is+abits))>>(32-bbits); - tptr = tbl_entry & 0xfffffff0; - - // find out what format table B is, if any - switch (tamode) - { - case 0: // invalid, should cause MMU exception - fatalerror("680x0 PMMU: Unhandled Table A mode %d (addr_in %08x)\n", tamode, addr_in); - break; - - case 2: // 4-byte table B descriptor - tofs *= 4; -// fprintf(stderr,"PMMU: reading table B entry at %08x\n", tofs + tptr); - tbl_entry = m68k_read_memory_32( tofs + tptr); - tbmode = tbl_entry & 3; -// fprintf(stderr,"PMMU: addr %08x entry %08x mode %x tofs %x\n", addr_in, tbl_entry, tbmode, tofs); - break; - - case 3: // 8-byte table B descriptor - tofs *= 8; -// fprintf(stderr,"PMMU: reading table B entries at %08x\n", tofs + tptr); - tbl_entry2 = m68k_read_memory_32( tofs + tptr); - tbl_entry = m68k_read_memory_32( tofs + tptr + 4); - tbmode = tbl_entry2 & 3; -// fprintf(stderr,"PMMU: addr %08x entry %08x entry2 %08x mode %x tofs %x\n", addr_in, tbl_entry, tbl_entry2, tbmode, tofs); - break; - - case 1: // early termination descriptor - tbl_entry &= 0xffffff00; - - shift = is+abits; - addr_out = ((addr_in<>shift) + tbl_entry; - resolved = 1; - break; - } - - // if table A wasn't early-out, continue to process table B - if (!resolved) - { - // get table C offset and pointer - tofs = (addr_in<<(is+abits+bbits))>>(32-cbits); - tptr = tbl_entry & 0xfffffff0; - - switch (tbmode) - { - case 0: // invalid, should cause MMU exception - fatalerror("680x0 PMMU: Unhandled Table B mode %d (addr_in %08x PC %x)\n", tbmode, addr_in, REG_PC); - break; - - case 2: // 4-byte table C descriptor - tofs *= 4; -// fprintf(stderr,"PMMU: reading table C entry at %08x\n", tofs + tptr); - tbl_entry = m68k_read_memory_32(tofs + tptr); - tcmode = tbl_entry & 3; -// fprintf(stderr,"PMMU: addr %08x entry %08x mode %x tofs %x\n", addr_in, tbl_entry, tbmode, tofs); - break; - - case 3: // 8-byte table C descriptor - tofs *= 8; -// fprintf(stderr,"PMMU: reading table C entries at %08x\n", tofs + tptr); - tbl_entry2 = m68k_read_memory_32(tofs + tptr); - tbl_entry = m68k_read_memory_32(tofs + tptr + 4); - tcmode = tbl_entry2 & 3; -// fprintf(stderr,"PMMU: addr %08x entry %08x entry2 %08x mode %x tofs %x\n", addr_in, tbl_entry, tbl_entry2, tbmode, tofs); - break; - - case 1: // termination descriptor - tbl_entry &= 0xffffff00; - - shift = is+abits+bbits; - addr_out = ((addr_in<>shift) + tbl_entry; - resolved = 1; - break; - } - } - - if (!resolved) - { - switch (tcmode) - { - case 0: // invalid, should cause MMU exception - case 2: // 4-byte ??? descriptor - case 3: // 8-byte ??? descriptor - fatalerror("680x0 PMMU: Unhandled Table B mode %d (addr_in %08x PC %x)\n", tbmode, addr_in, REG_PC); - break; - - case 1: // termination descriptor - tbl_entry &= 0xffffff00; - - shift = is+abits+bbits+cbits; - addr_out = ((addr_in<>shift) + tbl_entry; - resolved = 1; - break; - } - } - - -// fprintf(stderr,"PMMU: [%08x] => [%08x]\n", addr_in, addr_out); - - return addr_out; -} - -/* - - m68881_mmu_ops: COP 0 MMU opcode handling - -*/ - -void m68881_mmu_ops(void) -{ - uint16 modes; - uint32 ea = m68ki_cpu.ir & 0x3f; - uint64 temp64; - - // catch the 2 "weird" encodings up front (PBcc) - if ((m68ki_cpu.ir & 0xffc0) == 0xf0c0) - { - fprintf(stderr,"680x0: unhandled PBcc\n"); - return; - } - else if ((m68ki_cpu.ir & 0xffc0) == 0xf080) - { - fprintf(stderr,"680x0: unhandled PBcc\n"); - return; - } - else // the rest are 1111000xxxXXXXXX where xxx is the instruction family - { - switch ((m68ki_cpu.ir>>9) & 0x7) - { - case 0: - modes = OPER_I_16(); - - if ((modes & 0xfde0) == 0x2000) // PLOAD - { - fprintf(stderr,"680x0: unhandled PLOAD\n"); - return; - } - else if ((modes & 0xe200) == 0x2000) // PFLUSH - { - fprintf(stderr,"680x0: unhandled PFLUSH PC=%x\n", REG_PC); - return; - } - else if (modes == 0xa000) // PFLUSHR - { - fprintf(stderr,"680x0: unhandled PFLUSHR\n"); - return; - } - else if (modes == 0x2800) // PVALID (FORMAT 1) - { - fprintf(stderr,"680x0: unhandled PVALID1\n"); - return; - } - else if ((modes & 0xfff8) == 0x2c00) // PVALID (FORMAT 2) - { - fprintf(stderr,"680x0: unhandled PVALID2\n"); - return; - } - else if ((modes & 0xe000) == 0x8000) // PTEST - { - fprintf(stderr,"680x0: unhandled PTEST\n"); - return; - } - else - { - switch ((modes>>13) & 0x7) - { - case 0: // MC68030/040 form with FD bit - case 2: // MC68881 form, FD never set - if (modes & 0x200) - { - switch ((modes>>10) & 7) - { - case 0: // translation control register - WRITE_EA_32(ea, m68ki_cpu.mmu_tc); - break; - - case 2: // supervisor root pointer - WRITE_EA_64(ea, (uint64)m68ki_cpu.mmu_srp_limit<<32 | (uint64)m68ki_cpu.mmu_srp_aptr); - break; - - case 3: // CPU root pointer - WRITE_EA_64(ea, (uint64)m68ki_cpu.mmu_crp_limit<<32 | (uint64)m68ki_cpu.mmu_crp_aptr); - break; - - default: - fprintf(stderr,"680x0: PMOVE from unknown MMU register %x, PC %x\n", (modes>>10) & 7, REG_PC); - break; - } - } - else - { - switch ((modes>>10) & 7) - { - case 0: // translation control register - m68ki_cpu.mmu_tc = READ_EA_32(ea); - - if (m68ki_cpu.mmu_tc & 0x80000000) - { - m68ki_cpu.pmmu_enabled = 1; - } - else - { - m68ki_cpu.pmmu_enabled = 0; - } - break; - - case 2: // supervisor root pointer - temp64 = READ_EA_64(ea); - m68ki_cpu.mmu_srp_limit = (temp64>>32) & 0xffffffff; - m68ki_cpu.mmu_srp_aptr = temp64 & 0xffffffff; - break; - - case 3: // CPU root pointer - temp64 = READ_EA_64(ea); - m68ki_cpu.mmu_crp_limit = (temp64>>32) & 0xffffffff; - m68ki_cpu.mmu_crp_aptr = temp64 & 0xffffffff; - break; - - default: - fprintf(stderr,"680x0: PMOVE to unknown MMU register %x, PC %x\n", (modes>>10) & 7, REG_PC); - break; - } - } - break; - - case 3: // MC68030 to/from status reg - if (modes & 0x200) - { - WRITE_EA_32(ea, m68ki_cpu.mmu_sr); - } - else - { - m68ki_cpu.mmu_sr = READ_EA_32(ea); - } - break; - - default: - fprintf(stderr,"680x0: unknown PMOVE mode %x (modes %04x) (PC %x)\n", (modes>>13) & 0x7, modes, REG_PC); - break; - } - } - break; - - default: - fprintf(stderr,"680x0: unknown PMMU instruction group %d\n", (m68ki_cpu.ir>>9) & 0x7); - break; - } - } -} - diff --git a/machine/musashi/readme.txt b/machine/musashi/readme.txt deleted file mode 100644 index e9d878c..0000000 --- a/machine/musashi/readme.txt +++ /dev/null @@ -1,342 +0,0 @@ - MUSASHI - ======= - - Version 4.10 - - A portable Motorola M680x0 processor emulation engine. - Copyright 1998-2002 Karl Stenerud. All rights reserved. - - - -INTRODUCTION: ------------- - -Musashi is a Motorola 68000, 68010, 68EC020, 68020, 68EC030, 68030, 68EC040 and -68040 emulator written in C. This emulator was written with two goals in mind: -portability and speed. - -The emulator is written to ANSI C89 specifications. It also uses inline -functions, which are C9X compliant. - -It has been successfully running in the MAME project (www.mame.net) for years -and so has had time to mature. - - - -LICENSE AND COPYRIGHT: ---------------------- - -Copyright © 1998-2001 Karl Stenerud - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - - -AVAILABILITY: ------------- -The latest version of this code can be obtained at: -https://github.com/kstenerud/Musashi - - - -CONTACTING THE AUTHOR: ---------------------- -I can be reached at kstenerud@gmail.com - - - -BASIC CONFIGURATION: -------------------- -The basic configuration will give you a standard 68000 that has sufficient -functionality to work in a primitive environment. - -This setup assumes that you only have 1 device interrupting it, that the -device will always request an autovectored interrupt, and it will always clear -the interrupt before the interrupt service routine finishes (but could -possibly re-assert the interrupt). -You will have only one address space, no tracing, and no instruction prefetch. - -To implement the basic configuration: - -- Open m68kconf.h and verify that the settings for INLINE will work with your - compiler. (Currently set to "static __inline__", which works in gcc 2.9. - For C9X compliance, it should be "inline") - -- In your host program, implement the following functions: - unsigned int m68k_read_memory_8(unsigned int address); - unsigned int m68k_read_memory_16(unsigned int address); - unsigned int m68k_read_memory_32(unsigned int address); - void m68k_write_memory_8(unsigned int address, unsigned int value); - void m68k_write_memory_16(unsigned int address, unsigned int value); - void m68k_write_memory_32(unsigned int address, unsigned int value); - -- In your host program, be sure to call m68k_pulse_reset() once before calling - any of the other functions as this initializes the core. - -- Use m68k_execute() to execute instructions and m68k_set_irq() to cause an - interrupt. - - - -ADDING PROPER INTERRUPT HANDLING: --------------------------------- -The interrupt handling in the basic configuration doesn't emulate the -interrupt acknowledge phase of the CPU and automatically clears an interrupt -request during interrupt processing. -While this works for most systems, you may need more accurate interrupt -handling. - -To add proper interrupt handling: - -- In m68kconf.h, set M68K_EMULATE_INT_ACK to OPT_SPECIFY_HANDLER - -- In m68kconf.h, set M68K_INT_ACK_CALLBACK(A) to your interrupt acknowledge - routine - -- Your interrupt acknowledge routine must return an interrupt vector, - M68K_INT_ACK_AUTOVECTOR, or M68K_INT_ACK_SPURIOUS. most m68k - implementations just use autovectored interrupts. - -- When the interrupting device is satisfied, you must call m68k_set_irq(0) to - remove the interrupt request. - - - -MULTIPLE INTERRUPTS: -------------------- -The above system will work if you have only one device interrupting the CPU, -but if you have more than one device, you must do a bit more. - -To add multiple interrupts: - -- You must make an interrupt arbitration device that will take the highest - priority interrupt and encode it onto the IRQ pins on the CPU. - -- The interrupt arbitration device should use m68k_set_irq() to set the - highest pending interrupt, or 0 for no interrupts pending. - - - -SEPARATE IMMEDIATE READS: ------------------------- -You can write faster memory access functions if you know whether you are -fetching from ROM or RAM. Immediate reads are always from the program space -(Always in ROM unless it is running self-modifying code). - -To enable separate immediate reads: - -- In m68kconf.h, turn on M68K_SEPARATE_READ_IMM. - -- In your host program, implement the following functions: - unsigned int m68k_read_immediate_16(unsigned int address); - unsigned int m68k_read_immediate_32(unsigned int address); - - Now you also have the pcrelative stuff: - unsigned int m68k_read_pcrelative_8(unsigned int address); - unsigned int m68k_read_pcrelative_16(unsigned int address); - unsigned int m68k_read_pcrelative_32(unsigned int address); - -- If you need to know the current PC (for banking and such), set - M68K_MONITOR_PC to OPT_SPECIFY_HANDLER, and set M68K_SET_PC_CALLBACK(A) to - your routine. - -- In the unlikely case where you need to emulate some PMMU in the immediate - reads and/or pcrealtive stuff, you'll need to explicitely call the - translation address mechanism from your user functions this way : - - if (PMMU_ENABLED) - address = pmmu_translate_addr(address); - - (this is handled automatically by normal memory accesses). - -ADDRESS SPACES: --------------- -Most systems will only implement one address space, placing ROM at the lower -addresses and RAM at the higher. However, there is the possibility that a -system will implement ROM and RAM in the same address range, but in different -address spaces. - -In this case, you might get away with assuming that immediate reads are in the -program space and all other reads are in the data space, if it weren't for the -fact that the exception vectors are fetched from the data space. As a result, -anyone implementing this kind of system will have to copy the vector table -from ROM to RAM using pc-relative instructions. - -This makes things bad for emulation, because this means that a non-immediate -read is not necessarily in the data space. -The m68k deals with this by encoding the requested address space on the -function code pins: - - FC - Address Space 210 - ------------------ --- - USER DATA 001 - USER PROGRAM 010 - SUPERVISOR DATA 101 - SUPERVISOR PROGRAM 110 - CPU SPACE 111 <-- not emulated in this core since we emulate - interrupt acknowledge in another way. - -To emulate the function code pins: - -- In m68kconf.h, set M68K_EMULATE_FC to OPT_SPECIFY_HANDLER and set - M68K_SET_FC_CALLBACK(A) to your function code handler function. - -- Your function code handler should select the proper address space for - subsequent calls to m68k_read_xx (and m68k_write_xx for 68010+). - -Note: immediate reads are always done from program space, so technically you - don't need to implement the separate immediate reads, although you could - gain more speed improvements leaving them in and doing some clever - programming. - - - -USING DIFFERENT CPU TYPES: -------------------------- -The default is to enable only the 68000 cpu type. To change this, change the -settings for M68K_EMULATE_010 etc in m68kconf.h. - -To set the CPU type you want to use: - -- Make sure it is enabled in m68kconf.h. Current switches are: - M68K_EMULATE_010 - M68K_EMULATE_EC020 - M68K_EMULATE_020 - -- In your host program, call m68k_set_cpu_type() and then call - m68k_pulse_reset(). Valid CPU types are: - M68K_CPU_TYPE_68000, - M68K_CPU_TYPE_68010, - M68K_CPU_TYPE_68EC020, - M68K_CPU_TYPE_68020, - M68K_CPU_TYPE_68EC030, - M68K_CPU_TYPE_68030, - M68K_CPU_TYPE_68EC040, - M68K_CPU_TYPE_68040, - M68K_CPU_TYPE_SCC68070 (which is a 68010 with a 32 bit data bus). - -CLOCK FREQUENCY: ---------------- -In order to emulate the correct clock frequency, you will have to calculate -how long it takes the emulation to execute a certain number of "cycles" and -vary your calls to m68k_execute() accordingly. -As well, it is a good idea to take away the CPU's timeslice when it writes to -a memory-mapped port in order to give the device it wrote to a chance to -react. - -You can use the functions m68k_cycles_run(), m68k_cycles_remaining(), -m68k_modify_timeslice(), and m68k_end_timeslice() to do this. -Try to use large cycle values in your calls to m68k_execute() since it will -increase throughput. You can always take away the timeslice later. - - - -MORE CORRECT EMULATION: ----------------------- -You may need to enable these in order to properly emulate some of the more -obscure functions of the m68k: - -- M68K_EMULATE_BKPT_ACK causes the CPU to call a breakpoint handler on a BKPT - instruction - -- M68K_EMULATE_TRACE causes the CPU to generate trace exceptions when the - trace bits are set - -- M68K_EMULATE_RESET causes the CPU to call a reset handler on a RESET - instruction. - -- M68K_EMULATE_PREFETCH emulates the 4-word instruction prefetch that is part - of the 68000/68010 (needed for Amiga emulation). - NOTE: if the CPU fetches a word or longword at an odd address when this - option is on, it will yield unpredictable results, which is why a real - 68000 will generate an address error exception. - -- M68K_EMULATE_ADDRESS_ERROR will cause the CPU to generate address error - exceptions if it attempts to read a word or longword at an odd address. - -- call m68k_pulse_halt() to emulate the HALT pin. - - - -CONVENIENCE FUNCTIONS: ---------------------- -These are in here for programmer convenience: - -- M68K_INSTRUCTION_HOOK lets you call a handler before each instruction. - -- M68K_LOG_ENABLE and M68K_LOG_1010_1111 lets you log illegal and A/F-line - instructions. - - - -MULTIPLE CPU EMULATION: ----------------------- -The default is to use only one CPU. To use more than one CPU in this core, -there are some things to keep in mind: - -- To have different cpus call different functions, use OPT_ON instead of - OPT_SPECIFY_HANDLER, and use the m68k_set_xxx_callback() functions to set - your callback handlers on a per-cpu basis. - -- Be sure to call set_cpu_type() for each CPU you use. - -- Use m68k_set_context() and m68k_get_context() to switch to another CPU. - - - -LOAD AND SAVE CPU CONTEXTS FROM DISK: ------------------------------------- -You can use them68k_load_context() and m68k_save_context() functions to load -and save the CPU state to disk. - - - -GET/SET INFORMATION FROM THE CPU: --------------------------------- -You can use m68k_get_reg() and m68k_set_reg() to gain access to the internals -of the CPU. - - - -EXAMPLE: -------- - -The subdir example contains a full example (currently linux & Dos only). - -Compilation ------------ - -You can use the default Makefile in Musashi's directory, it works like this : -1st build m68kmake, which will build m68kops.c and m68kops.h based on the -contents of m68k_in.c. -Then compile m68kcpu.o and m68kops.o. Add m68kdasm.o if you want the -disassemble functions. When linking this to your project you will need libm -for the fpu emulation of the 68040. - -Using some custom m68kconf.h outside Musashi's directory --------------------------------------------------------- - -It can be useful to keep an untouched musashi directory in a project (from -git for example) and maintain a separate m68kconf.h specific to the -project. For this, pass -DMUSASHI_CNF="mycustomconfig.h" to gcc (or whatever -compiler you use). Notice that if you use an unix shell (or make which uses -the shell to launch its commands), then you need to escape the quotes like -this : -DMUSASHI_CNF=\"mycustomconfig.h\" - diff --git a/machine/musashi/softfloat/README.txt b/machine/musashi/softfloat/README.txt deleted file mode 100644 index 9500d25..0000000 --- a/machine/musashi/softfloat/README.txt +++ /dev/null @@ -1,78 +0,0 @@ -MAME note: this package is derived from the following original SoftFloat -package and has been "re-packaged" to work with MAME's conventions and -build system. The source files come from bits64/ and bits64/templates -in the original distribution as MAME requires a compiler with a 64-bit -integer type. - - -Package Overview for SoftFloat Release 2b - -John R. Hauser -2002 May 27 - - ----------------------------------------------------------------------------- -Overview - -SoftFloat is a software implementation of floating-point that conforms to -the IEC/IEEE Standard for Binary Floating-Point Arithmetic. SoftFloat is -distributed in the form of C source code. Compiling the SoftFloat sources -generates two things: - --- A SoftFloat object file (typically `softfloat.o') containing the complete - set of IEC/IEEE floating-point routines. - --- A `timesoftfloat' program for evaluating the speed of the SoftFloat - routines. (The SoftFloat module is linked into this program.) - -The SoftFloat package is documented in four text files: - - SoftFloat.txt Documentation for using the SoftFloat functions. - SoftFloat-source.txt Documentation for compiling SoftFloat. - SoftFloat-history.txt History of major changes to SoftFloat. - timesoftfloat.txt Documentation for using `timesoftfloat'. - -Other files in the package comprise the source code for SoftFloat. - -Please be aware that some work is involved in porting this software to other -targets. It is not just a matter of getting `make' to complete without -error messages. I would have written the code that way if I could, but -there are fundamental differences between systems that can't be hidden. -You should not attempt to compile SoftFloat without first reading both -`SoftFloat.txt' and `SoftFloat-source.txt'. - - ----------------------------------------------------------------------------- -Legal Notice - -SoftFloat was written by me, John R. Hauser. This work was made possible in -part by the International Computer Science Institute, located at Suite 600, -1947 Center Street, Berkeley, California 94704. Funding was partially -provided by the National Science Foundation under grant MIP-9311980. The -original version of this code was written as part of a project to build -a fixed-point vector processor in collaboration with the University of -California at Berkeley, overseen by Profs. Nelson Morgan and John Wawrzynek. - -THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort -has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT -TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO -PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL -LOSSES, COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO -FURTHERMORE EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER -SCIENCE INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, -COSTS, OR OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE -SOFTWARE. - -Derivative works are acceptable, even for commercial purposes, provided -that the minimal documentation requirements stated in the source code are -satisfied. - - ----------------------------------------------------------------------------- -Contact Information - -At the time of this writing, the most up-to-date information about -SoftFloat and the latest release can be found at the Web page `http:// -www.cs.berkeley.edu/~jhauser/arithmetic/SoftFloat.html'. - - diff --git a/machine/musashi/softfloat/mamesf.h b/machine/musashi/softfloat/mamesf.h deleted file mode 100644 index c419503..0000000 --- a/machine/musashi/softfloat/mamesf.h +++ /dev/null @@ -1,61 +0,0 @@ -/*---------------------------------------------------------------------------- -| One of the macros `BIGENDIAN' or `LITTLEENDIAN' must be defined. -*----------------------------------------------------------------------------*/ -#ifdef LSB_FIRST -#define LITTLEENDIAN -#else -#define BIGENDIAN -#endif - -/*---------------------------------------------------------------------------- -| The macro `BITS64' can be defined to indicate that 64-bit integer types are -| supported by the compiler. -*----------------------------------------------------------------------------*/ -#define BITS64 - -/*---------------------------------------------------------------------------- -| Each of the following `typedef's defines the most convenient type that holds -| integers of at least as many bits as specified. For example, `uint8' should -| be the most convenient type that can hold unsigned integers of as many as -| 8 bits. The `flag' type must be able to hold either a 0 or 1. For most -| implementations of C, `flag', `uint8', and `int8' should all be `typedef'ed -| to the same as `int'. -*----------------------------------------------------------------------------*/ - -typedef sint8 flag; -typedef sint8 int8; -typedef sint16 int16; -typedef sint32 int32; -typedef sint64 int64; - -/*---------------------------------------------------------------------------- -| Each of the following `typedef's defines a type that holds integers -| of _exactly_ the number of bits specified. For instance, for most -| implementation of C, `bits16' and `sbits16' should be `typedef'ed to -| `unsigned short int' and `signed short int' (or `short int'), respectively. -*----------------------------------------------------------------------------*/ -typedef uint8 bits8; -typedef sint8 sbits8; -typedef uint16 bits16; -typedef sint16 sbits16; -typedef uint32 bits32; -typedef sint32 sbits32; -typedef uint64 bits64; -typedef sint64 sbits64; - -/*---------------------------------------------------------------------------- -| The `LIT64' macro takes as its argument a textual integer literal and -| if necessary ``marks'' the literal as having a 64-bit integer type. -| For example, the GNU C Compiler (`gcc') requires that 64-bit literals be -| appended with the letters `LL' standing for `long long', which is `gcc's -| name for the 64-bit integer type. Some compilers may allow `LIT64' to be -| defined as the identity macro: `#define LIT64( a ) a'. -*----------------------------------------------------------------------------*/ -#define LIT64( a ) a##ULL - -/*---------------------------------------------------------------------------- -| The macro `INLINE' can be used before functions that should be inlined. If -| a compiler does not support explicit inlining, this macro should be defined -| to be `static'. -*----------------------------------------------------------------------------*/ -// MAME defines INLINE diff --git a/machine/musashi/softfloat/milieu.h b/machine/musashi/softfloat/milieu.h deleted file mode 100644 index 10687b7..0000000 --- a/machine/musashi/softfloat/milieu.h +++ /dev/null @@ -1,42 +0,0 @@ - -/*============================================================================ - -This C header file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic -Package, Release 2b. - -Written by John R. Hauser. This work was made possible in part by the -International Computer Science Institute, located at Suite 600, 1947 Center -Street, Berkeley, California 94704. Funding was partially provided by the -National Science Foundation under grant MIP-9311980. The original version -of this code was written as part of a project to build a fixed-point vector -processor in collaboration with the University of California at Berkeley, -overseen by Profs. Nelson Morgan and John Wawrzynek. More information -is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ -arithmetic/SoftFloat.html'. - -THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has -been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES -RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS -AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, -COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE -EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE -INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR -OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. - -Derivative works are acceptable, even for commercial purposes, so long as -(1) the source code for the derivative work includes prominent notice that -the work is derivative, and (2) the source code includes prominent notice with -these four paragraphs for those parts of this code that are retained. - -=============================================================================*/ - -/*---------------------------------------------------------------------------- -| Include common integer types and flags. -*----------------------------------------------------------------------------*/ -#include "mamesf.h" - -/*---------------------------------------------------------------------------- -| Symbolic Boolean literals. -*----------------------------------------------------------------------------*/ -#define FALSE 0 -#define TRUE 1 diff --git a/machine/musashi/softfloat/softfloat-macros b/machine/musashi/softfloat/softfloat-macros deleted file mode 100644 index 5de9031..0000000 --- a/machine/musashi/softfloat/softfloat-macros +++ /dev/null @@ -1,732 +0,0 @@ - -/*============================================================================ - -This C source fragment is part of the SoftFloat IEC/IEEE Floating-point -Arithmetic Package, Release 2b. - -Written by John R. Hauser. This work was made possible in part by the -International Computer Science Institute, located at Suite 600, 1947 Center -Street, Berkeley, California 94704. Funding was partially provided by the -National Science Foundation under grant MIP-9311980. The original version -of this code was written as part of a project to build a fixed-point vector -processor in collaboration with the University of California at Berkeley, -overseen by Profs. Nelson Morgan and John Wawrzynek. More information -is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ -arithmetic/SoftFloat.html'. - -THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has -been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES -RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS -AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, -COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE -EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE -INSTITUTE (possibly via similar legal notice) AGAINST ALL LOSSES, COSTS, OR -OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. - -Derivative works are acceptable, even for commercial purposes, so long as -(1) the source code for the derivative work includes prominent notice that -the work is derivative, and (2) the source code includes prominent notice with -these four paragraphs for those parts of this code that are retained. - -=============================================================================*/ - -/*---------------------------------------------------------------------------- -| Shifts `a' right by the number of bits given in `count'. If any nonzero -| bits are shifted off, they are ``jammed'' into the least significant bit of -| the result by setting the least significant bit to 1. The value of `count' -| can be arbitrarily large; in particular, if `count' is greater than 32, the -| result will be either 0 or 1, depending on whether `a' is zero or nonzero. -| The result is stored in the location pointed to by `zPtr'. -*----------------------------------------------------------------------------*/ - -static inline void shift32RightJamming( bits32 a, int16 count, bits32 *zPtr ) -{ - bits32 z; - - if ( count == 0 ) { - z = a; - } - else if ( count < 32 ) { - z = ( a>>count ) | ( ( a<<( ( - count ) & 31 ) ) != 0 ); - } - else { - z = ( a != 0 ); - } - *zPtr = z; - -} - -/*---------------------------------------------------------------------------- -| Shifts `a' right by the number of bits given in `count'. If any nonzero -| bits are shifted off, they are ``jammed'' into the least significant bit of -| the result by setting the least significant bit to 1. The value of `count' -| can be arbitrarily large; in particular, if `count' is greater than 64, the -| result will be either 0 or 1, depending on whether `a' is zero or nonzero. -| The result is stored in the location pointed to by `zPtr'. -*----------------------------------------------------------------------------*/ - -static inline void shift64RightJamming( bits64 a, int16 count, bits64 *zPtr ) -{ - bits64 z; - - if ( count == 0 ) { - z = a; - } - else if ( count < 64 ) { - z = ( a>>count ) | ( ( a<<( ( - count ) & 63 ) ) != 0 ); - } - else { - z = ( a != 0 ); - } - *zPtr = z; - -} - -/*---------------------------------------------------------------------------- -| Shifts the 128-bit value formed by concatenating `a0' and `a1' right by 64 -| _plus_ the number of bits given in `count'. The shifted result is at most -| 64 nonzero bits; this is stored at the location pointed to by `z0Ptr'. The -| bits shifted off form a second 64-bit result as follows: The _last_ bit -| shifted off is the most-significant bit of the extra result, and the other -| 63 bits of the extra result are all zero if and only if _all_but_the_last_ -| bits shifted off were all zero. This extra result is stored in the location -| pointed to by `z1Ptr'. The value of `count' can be arbitrarily large. -| (This routine makes more sense if `a0' and `a1' are considered to form -| a fixed-point value with binary point between `a0' and `a1'. This fixed- -| point value is shifted right by the number of bits given in `count', and -| the integer part of the result is returned at the location pointed to by -| `z0Ptr'. The fractional part of the result may be slightly corrupted as -| described above, and is returned at the location pointed to by `z1Ptr'.) -*----------------------------------------------------------------------------*/ - -static inline void - shift64ExtraRightJamming( - bits64 a0, bits64 a1, int16 count, bits64 *z0Ptr, bits64 *z1Ptr ) -{ - bits64 z0, z1; - int8 negCount = ( - count ) & 63; - - if ( count == 0 ) { - z1 = a1; - z0 = a0; - } - else if ( count < 64 ) { - z1 = ( a0<>count; - } - else { - if ( count == 64 ) { - z1 = a0 | ( a1 != 0 ); - } - else { - z1 = ( ( a0 | a1 ) != 0 ); - } - z0 = 0; - } - *z1Ptr = z1; - *z0Ptr = z0; - -} - -/*---------------------------------------------------------------------------- -| Shifts the 128-bit value formed by concatenating `a0' and `a1' right by the -| number of bits given in `count'. Any bits shifted off are lost. The value -| of `count' can be arbitrarily large; in particular, if `count' is greater -| than 128, the result will be 0. The result is broken into two 64-bit pieces -| which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'. -*----------------------------------------------------------------------------*/ - -static inline void - shift128Right( - bits64 a0, bits64 a1, int16 count, bits64 *z0Ptr, bits64 *z1Ptr ) -{ - bits64 z0, z1; - int8 negCount = ( - count ) & 63; - - if ( count == 0 ) { - z1 = a1; - z0 = a0; - } - else if ( count < 64 ) { - z1 = ( a0<>count ); - z0 = a0>>count; - } - else { - z1 = ( count < 64 ) ? ( a0>>( count & 63 ) ) : 0; - z0 = 0; - } - *z1Ptr = z1; - *z0Ptr = z0; - -} - -/*---------------------------------------------------------------------------- -| Shifts the 128-bit value formed by concatenating `a0' and `a1' right by the -| number of bits given in `count'. If any nonzero bits are shifted off, they -| are ``jammed'' into the least significant bit of the result by setting the -| least significant bit to 1. The value of `count' can be arbitrarily large; -| in particular, if `count' is greater than 128, the result will be either -| 0 or 1, depending on whether the concatenation of `a0' and `a1' is zero or -| nonzero. The result is broken into two 64-bit pieces which are stored at -| the locations pointed to by `z0Ptr' and `z1Ptr'. -*----------------------------------------------------------------------------*/ - -static inline void - shift128RightJamming( - bits64 a0, bits64 a1, int16 count, bits64 *z0Ptr, bits64 *z1Ptr ) -{ - bits64 z0, z1; - int8 negCount = ( - count ) & 63; - - if ( count == 0 ) { - z1 = a1; - z0 = a0; - } - else if ( count < 64 ) { - z1 = ( a0<>count ) | ( ( a1<>count; - } - else { - if ( count == 64 ) { - z1 = a0 | ( a1 != 0 ); - } - else if ( count < 128 ) { - z1 = ( a0>>( count & 63 ) ) | ( ( ( a0<>count ); - z0 = a0>>count; - } - else { - if ( count == 64 ) { - z2 = a1; - z1 = a0; - } - else { - a2 |= a1; - if ( count < 128 ) { - z2 = a0<>( count & 63 ); - } - else { - z2 = ( count == 128 ) ? a0 : ( a0 != 0 ); - z1 = 0; - } - } - z0 = 0; - } - z2 |= ( a2 != 0 ); - } - *z2Ptr = z2; - *z1Ptr = z1; - *z0Ptr = z0; - -} - -/*---------------------------------------------------------------------------- -| Shifts the 128-bit value formed by concatenating `a0' and `a1' left by the -| number of bits given in `count'. Any bits shifted off are lost. The value -| of `count' must be less than 64. The result is broken into two 64-bit -| pieces which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'. -*----------------------------------------------------------------------------*/ - -static inline void - shortShift128Left( - bits64 a0, bits64 a1, int16 count, bits64 *z0Ptr, bits64 *z1Ptr ) -{ - - *z1Ptr = a1<>( ( - count ) & 63 ) ); - -} - -/*---------------------------------------------------------------------------- -| Shifts the 192-bit value formed by concatenating `a0', `a1', and `a2' left -| by the number of bits given in `count'. Any bits shifted off are lost. -| The value of `count' must be less than 64. The result is broken into three -| 64-bit pieces which are stored at the locations pointed to by `z0Ptr', -| `z1Ptr', and `z2Ptr'. -*----------------------------------------------------------------------------*/ - -static inline void - shortShift192Left( - bits64 a0, - bits64 a1, - bits64 a2, - int16 count, - bits64 *z0Ptr, - bits64 *z1Ptr, - bits64 *z2Ptr - ) -{ - bits64 z0, z1, z2; - int8 negCount; - - z2 = a2<>negCount; - z0 |= a1>>negCount; - } - *z2Ptr = z2; - *z1Ptr = z1; - *z0Ptr = z0; - -} - -/*---------------------------------------------------------------------------- -| Adds the 128-bit value formed by concatenating `a0' and `a1' to the 128-bit -| value formed by concatenating `b0' and `b1'. Addition is modulo 2^128, so -| any carry out is lost. The result is broken into two 64-bit pieces which -| are stored at the locations pointed to by `z0Ptr' and `z1Ptr'. -*----------------------------------------------------------------------------*/ - -static inline void - add128( - bits64 a0, bits64 a1, bits64 b0, bits64 b1, bits64 *z0Ptr, bits64 *z1Ptr ) -{ - bits64 z1; - - z1 = a1 + b1; - *z1Ptr = z1; - *z0Ptr = a0 + b0 + ( z1 < a1 ); - -} - -/*---------------------------------------------------------------------------- -| Adds the 192-bit value formed by concatenating `a0', `a1', and `a2' to the -| 192-bit value formed by concatenating `b0', `b1', and `b2'. Addition is -| modulo 2^192, so any carry out is lost. The result is broken into three -| 64-bit pieces which are stored at the locations pointed to by `z0Ptr', -| `z1Ptr', and `z2Ptr'. -*----------------------------------------------------------------------------*/ - -static inline void - add192( - bits64 a0, - bits64 a1, - bits64 a2, - bits64 b0, - bits64 b1, - bits64 b2, - bits64 *z0Ptr, - bits64 *z1Ptr, - bits64 *z2Ptr - ) -{ - bits64 z0, z1, z2; - uint8 carry0, carry1; - - z2 = a2 + b2; - carry1 = ( z2 < a2 ); - z1 = a1 + b1; - carry0 = ( z1 < a1 ); - z0 = a0 + b0; - z1 += carry1; - z0 += ( z1 < carry1 ); - z0 += carry0; - *z2Ptr = z2; - *z1Ptr = z1; - *z0Ptr = z0; - -} - -/*---------------------------------------------------------------------------- -| Subtracts the 128-bit value formed by concatenating `b0' and `b1' from the -| 128-bit value formed by concatenating `a0' and `a1'. Subtraction is modulo -| 2^128, so any borrow out (carry out) is lost. The result is broken into two -| 64-bit pieces which are stored at the locations pointed to by `z0Ptr' and -| `z1Ptr'. -*----------------------------------------------------------------------------*/ - -static inline void - sub128( - bits64 a0, bits64 a1, bits64 b0, bits64 b1, bits64 *z0Ptr, bits64 *z1Ptr ) -{ - - *z1Ptr = a1 - b1; - *z0Ptr = a0 - b0 - ( a1 < b1 ); - -} - -/*---------------------------------------------------------------------------- -| Subtracts the 192-bit value formed by concatenating `b0', `b1', and `b2' -| from the 192-bit value formed by concatenating `a0', `a1', and `a2'. -| Subtraction is modulo 2^192, so any borrow out (carry out) is lost. The -| result is broken into three 64-bit pieces which are stored at the locations -| pointed to by `z0Ptr', `z1Ptr', and `z2Ptr'. -*----------------------------------------------------------------------------*/ - -static inline void - sub192( - bits64 a0, - bits64 a1, - bits64 a2, - bits64 b0, - bits64 b1, - bits64 b2, - bits64 *z0Ptr, - bits64 *z1Ptr, - bits64 *z2Ptr - ) -{ - bits64 z0, z1, z2; - uint8 borrow0, borrow1; - - z2 = a2 - b2; - borrow1 = ( a2 < b2 ); - z1 = a1 - b1; - borrow0 = ( a1 < b1 ); - z0 = a0 - b0; - z0 -= ( z1 < borrow1 ); - z1 -= borrow1; - z0 -= borrow0; - *z2Ptr = z2; - *z1Ptr = z1; - *z0Ptr = z0; - -} - -/*---------------------------------------------------------------------------- -| Multiplies `a' by `b' to obtain a 128-bit product. The product is broken -| into two 64-bit pieces which are stored at the locations pointed to by -| `z0Ptr' and `z1Ptr'. -*----------------------------------------------------------------------------*/ - -static inline void mul64To128( bits64 a, bits64 b, bits64 *z0Ptr, bits64 *z1Ptr ) -{ - bits32 aHigh, aLow, bHigh, bLow; - bits64 z0, zMiddleA, zMiddleB, z1; - - aLow = a; - aHigh = a>>32; - bLow = b; - bHigh = b>>32; - z1 = ( (bits64) aLow ) * bLow; - zMiddleA = ( (bits64) aLow ) * bHigh; - zMiddleB = ( (bits64) aHigh ) * bLow; - z0 = ( (bits64) aHigh ) * bHigh; - zMiddleA += zMiddleB; - z0 += ( ( (bits64) ( zMiddleA < zMiddleB ) )<<32 ) + ( zMiddleA>>32 ); - zMiddleA <<= 32; - z1 += zMiddleA; - z0 += ( z1 < zMiddleA ); - *z1Ptr = z1; - *z0Ptr = z0; - -} - -/*---------------------------------------------------------------------------- -| Multiplies the 128-bit value formed by concatenating `a0' and `a1' by -| `b' to obtain a 192-bit product. The product is broken into three 64-bit -| pieces which are stored at the locations pointed to by `z0Ptr', `z1Ptr', and -| `z2Ptr'. -*----------------------------------------------------------------------------*/ - -static inline void - mul128By64To192( - bits64 a0, - bits64 a1, - bits64 b, - bits64 *z0Ptr, - bits64 *z1Ptr, - bits64 *z2Ptr - ) -{ - bits64 z0, z1, z2, more1; - - mul64To128( a1, b, &z1, &z2 ); - mul64To128( a0, b, &z0, &more1 ); - add128( z0, more1, 0, z1, &z0, &z1 ); - *z2Ptr = z2; - *z1Ptr = z1; - *z0Ptr = z0; - -} - -/*---------------------------------------------------------------------------- -| Multiplies the 128-bit value formed by concatenating `a0' and `a1' to the -| 128-bit value formed by concatenating `b0' and `b1' to obtain a 256-bit -| product. The product is broken into four 64-bit pieces which are stored at -| the locations pointed to by `z0Ptr', `z1Ptr', `z2Ptr', and `z3Ptr'. -*----------------------------------------------------------------------------*/ - -static inline void - mul128To256( - bits64 a0, - bits64 a1, - bits64 b0, - bits64 b1, - bits64 *z0Ptr, - bits64 *z1Ptr, - bits64 *z2Ptr, - bits64 *z3Ptr - ) -{ - bits64 z0, z1, z2, z3; - bits64 more1, more2; - - mul64To128( a1, b1, &z2, &z3 ); - mul64To128( a1, b0, &z1, &more2 ); - add128( z1, more2, 0, z2, &z1, &z2 ); - mul64To128( a0, b0, &z0, &more1 ); - add128( z0, more1, 0, z1, &z0, &z1 ); - mul64To128( a0, b1, &more1, &more2 ); - add128( more1, more2, 0, z2, &more1, &z2 ); - add128( z0, z1, 0, more1, &z0, &z1 ); - *z3Ptr = z3; - *z2Ptr = z2; - *z1Ptr = z1; - *z0Ptr = z0; - -} - -/*---------------------------------------------------------------------------- -| Returns an approximation to the 64-bit integer quotient obtained by dividing -| `b' into the 128-bit value formed by concatenating `a0' and `a1'. The -| divisor `b' must be at least 2^63. If q is the exact quotient truncated -| toward zero, the approximation returned lies between q and q + 2 inclusive. -| If the exact quotient q is larger than 64 bits, the maximum positive 64-bit -| unsigned integer is returned. -*----------------------------------------------------------------------------*/ - -static inline bits64 estimateDiv128To64( bits64 a0, bits64 a1, bits64 b ) -{ - bits64 b0, b1; - bits64 rem0, rem1, term0, term1; - bits64 z; - - if ( b <= a0 ) return LIT64( 0xFFFFFFFFFFFFFFFF ); - b0 = b>>32; - z = ( b0<<32 <= a0 ) ? LIT64( 0xFFFFFFFF00000000 ) : ( a0 / b0 )<<32; - mul64To128( b, z, &term0, &term1 ); - sub128( a0, a1, term0, term1, &rem0, &rem1 ); - while ( ( (sbits64) rem0 ) < 0 ) { - z -= LIT64( 0x100000000 ); - b1 = b<<32; - add128( rem0, rem1, b0, b1, &rem0, &rem1 ); - } - rem0 = ( rem0<<32 ) | ( rem1>>32 ); - z |= ( b0<<32 <= rem0 ) ? 0xFFFFFFFF : rem0 / b0; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns an approximation to the square root of the 32-bit significand given -| by `a'. Considered as an integer, `a' must be at least 2^31. If bit 0 of -| `aExp' (the least significant bit) is 1, the integer returned approximates -| 2^31*sqrt(`a'/2^31), where `a' is considered an integer. If bit 0 of `aExp' -| is 0, the integer returned approximates 2^31*sqrt(`a'/2^30). In either -| case, the approximation returned lies strictly within +/-2 of the exact -| value. -*----------------------------------------------------------------------------*/ - -static inline bits32 estimateSqrt32( int16 aExp, bits32 a ) -{ - static const bits16 sqrtOddAdjustments[] = { - 0x0004, 0x0022, 0x005D, 0x00B1, 0x011D, 0x019F, 0x0236, 0x02E0, - 0x039C, 0x0468, 0x0545, 0x0631, 0x072B, 0x0832, 0x0946, 0x0A67 - }; - static const bits16 sqrtEvenAdjustments[] = { - 0x0A2D, 0x08AF, 0x075A, 0x0629, 0x051A, 0x0429, 0x0356, 0x029E, - 0x0200, 0x0179, 0x0109, 0x00AF, 0x0068, 0x0034, 0x0012, 0x0002 - }; - int8 index; - bits32 z; - - index = ( a>>27 ) & 15; - if ( aExp & 1 ) { - z = 0x4000 + ( a>>17 ) - sqrtOddAdjustments[ index ]; - z = ( ( a / z )<<14 ) + ( z<<15 ); - a >>= 1; - } - else { - z = 0x8000 + ( a>>17 ) - sqrtEvenAdjustments[ index ]; - z = a / z + z; - z = ( 0x20000 <= z ) ? 0xFFFF8000 : ( z<<15 ); - if ( z <= a ) return (bits32) ( ( (sbits32) a )>>1 ); - } - return ( (bits32) ( ( ( (bits64) a )<<31 ) / z ) ) + ( z>>1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the number of leading 0 bits before the most-significant 1 bit of -| `a'. If `a' is zero, 32 is returned. -*----------------------------------------------------------------------------*/ - -static int8 countLeadingZeros32( bits32 a ) -{ - static const int8 countLeadingZerosHigh[] = { - 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 - }; - int8 shiftCount; - - shiftCount = 0; - if ( a < 0x10000 ) { - shiftCount += 16; - a <<= 16; - } - if ( a < 0x1000000 ) { - shiftCount += 8; - a <<= 8; - } - shiftCount += countLeadingZerosHigh[ a>>24 ]; - return shiftCount; - -} - -/*---------------------------------------------------------------------------- -| Returns the number of leading 0 bits before the most-significant 1 bit of -| `a'. If `a' is zero, 64 is returned. -*----------------------------------------------------------------------------*/ - -static int8 countLeadingZeros64( bits64 a ) -{ - int8 shiftCount; - - shiftCount = 0; - if ( a < ( (bits64) 1 )<<32 ) { - shiftCount += 32; - } - else { - a >>= 32; - } - shiftCount += countLeadingZeros32( a ); - return shiftCount; - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' -| is equal to the 128-bit value formed by concatenating `b0' and `b1'. -| Otherwise, returns 0. -*----------------------------------------------------------------------------*/ - -static inline flag eq128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 ) -{ - - return ( a0 == b0 ) && ( a1 == b1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is less -| than or equal to the 128-bit value formed by concatenating `b0' and `b1'. -| Otherwise, returns 0. -*----------------------------------------------------------------------------*/ - -static inline flag le128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 ) -{ - - return ( a0 < b0 ) || ( ( a0 == b0 ) && ( a1 <= b1 ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is less -| than the 128-bit value formed by concatenating `b0' and `b1'. Otherwise, -| returns 0. -*----------------------------------------------------------------------------*/ - -static inline flag lt128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 ) -{ - - return ( a0 < b0 ) || ( ( a0 == b0 ) && ( a1 < b1 ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is -| not equal to the 128-bit value formed by concatenating `b0' and `b1'. -| Otherwise, returns 0. -*----------------------------------------------------------------------------*/ - -static inline flag ne128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 ) -{ - - return ( a0 != b0 ) || ( a1 != b1 ); - -} - -/*----------------------------------------------------------------------------- -| Changes the sign of the extended double-precision floating-point value 'a'. -| The operation is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static inline floatx80 floatx80_chs(floatx80 reg) -{ - reg.high ^= 0x8000; - return reg; -} - diff --git a/machine/musashi/softfloat/softfloat-specialize b/machine/musashi/softfloat/softfloat-specialize deleted file mode 100644 index a3113ba..0000000 --- a/machine/musashi/softfloat/softfloat-specialize +++ /dev/null @@ -1,476 +0,0 @@ - -/*============================================================================ - -This C source fragment is part of the SoftFloat IEC/IEEE Floating-point -Arithmetic Package, Release 2b. - -Written by John R. Hauser. This work was made possible in part by the -International Computer Science Institute, located at Suite 600, 1947 Center -Street, Berkeley, California 94704. Funding was partially provided by the -National Science Foundation under grant MIP-9311980. The original version -of this code was written as part of a project to build a fixed-point vector -processor in collaboration with the University of California at Berkeley, -overseen by Profs. Nelson Morgan and John Wawrzynek. More information -is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ -arithmetic/SoftFloat.html'. - -THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has -been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES -RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS -AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, -COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE -EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE -INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR -OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. - -Derivative works are acceptable, even for commercial purposes, so long as -(1) the source code for the derivative work includes prominent notice that -the work is derivative, and (2) the source code includes prominent notice with -these four paragraphs for those parts of this code that are retained. - -=============================================================================*/ - -flag float32_is_nan( float32 a ); -flag float64_is_nan( float64 a ); -flag floatx80_is_nan( floatx80 a ); -floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b ); -flag float128_is_nan( float128 a ); - -/*---------------------------------------------------------------------------- -| Underflow tininess-detection mode, statically initialized to default value. -| (The declaration in `softfloat.h' must match the `int8' type here.) -*----------------------------------------------------------------------------*/ -int8 float_detect_tininess = float_tininess_after_rounding; - -/*---------------------------------------------------------------------------- -| Raises the exceptions specified by `flags'. Floating-point traps can be -| defined here if desired. It is currently not possible for such a trap to -| substitute a result value. If traps are not implemented, this routine -| should be simply `float_exception_flags |= flags;'. -*----------------------------------------------------------------------------*/ - -void float_raise( int8 flags ) -{ - - float_exception_flags |= flags; - -} - -/*---------------------------------------------------------------------------- -| Internal canonical NaN format. -*----------------------------------------------------------------------------*/ -typedef struct { - flag sign; - bits64 high, low; -} commonNaNT; - -/*---------------------------------------------------------------------------- -| The pattern for a default generated single-precision NaN. -*----------------------------------------------------------------------------*/ -#define float32_default_nan 0xFFFFFFFF - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is a NaN; -| otherwise returns 0. -*----------------------------------------------------------------------------*/ - -flag float32_is_nan( float32 a ) -{ - - return ( 0xFF000000 < (bits32) ( a<<1 ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is a signaling -| NaN; otherwise returns 0. -*----------------------------------------------------------------------------*/ - -flag float32_is_signaling_nan( float32 a ) -{ - - return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point NaN -| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid -| exception is raised. -*----------------------------------------------------------------------------*/ - -static commonNaNT float32ToCommonNaN( float32 a ) -{ - commonNaNT z; - - if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); - z.sign = a>>31; - z.low = 0; - z.high = ( (bits64) a )<<41; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the canonical NaN `a' to the single- -| precision floating-point format. -*----------------------------------------------------------------------------*/ - -static float32 commonNaNToFloat32( commonNaNT a ) -{ - - return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 ); - -} - -/*---------------------------------------------------------------------------- -| Takes two single-precision floating-point values `a' and `b', one of which -| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a -| signaling NaN, the invalid exception is raised. -*----------------------------------------------------------------------------*/ - -static float32 propagateFloat32NaN( float32 a, float32 b ) -{ - flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; - - aIsNaN = float32_is_nan( a ); - aIsSignalingNaN = float32_is_signaling_nan( a ); - bIsNaN = float32_is_nan( b ); - bIsSignalingNaN = float32_is_signaling_nan( b ); - a |= 0x00400000; - b |= 0x00400000; - if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); - if ( aIsNaN ) { - return ( aIsSignalingNaN & bIsNaN ) ? b : a; - } - else { - return b; - } - -} - -/*---------------------------------------------------------------------------- -| The pattern for a default generated double-precision NaN. -*----------------------------------------------------------------------------*/ -#define float64_default_nan LIT64( 0xFFFFFFFFFFFFFFFF ) - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is a NaN; -| otherwise returns 0. -*----------------------------------------------------------------------------*/ - -flag float64_is_nan( float64 a ) -{ - - return ( LIT64( 0xFFE0000000000000 ) < (bits64) ( a<<1 ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is a signaling -| NaN; otherwise returns 0. -*----------------------------------------------------------------------------*/ - -flag float64_is_signaling_nan( float64 a ) -{ - - return - ( ( ( a>>51 ) & 0xFFF ) == 0xFFE ) - && ( a & LIT64( 0x0007FFFFFFFFFFFF ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-precision floating-point NaN -| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid -| exception is raised. -*----------------------------------------------------------------------------*/ - -static commonNaNT float64ToCommonNaN( float64 a ) -{ - commonNaNT z; - - if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); - z.sign = a>>63; - z.low = 0; - z.high = a<<12; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the canonical NaN `a' to the double- -| precision floating-point format. -*----------------------------------------------------------------------------*/ - -static float64 commonNaNToFloat64( commonNaNT a ) -{ - - return - ( ( (bits64) a.sign )<<63 ) - | LIT64( 0x7FF8000000000000 ) - | ( a.high>>12 ); - -} - -/*---------------------------------------------------------------------------- -| Takes two double-precision floating-point values `a' and `b', one of which -| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a -| signaling NaN, the invalid exception is raised. -*----------------------------------------------------------------------------*/ - -static float64 propagateFloat64NaN( float64 a, float64 b ) -{ - flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; - - aIsNaN = float64_is_nan( a ); - aIsSignalingNaN = float64_is_signaling_nan( a ); - bIsNaN = float64_is_nan( b ); - bIsSignalingNaN = float64_is_signaling_nan( b ); - a |= LIT64( 0x0008000000000000 ); - b |= LIT64( 0x0008000000000000 ); - if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); - if ( aIsNaN ) { - return ( aIsSignalingNaN & bIsNaN ) ? b : a; - } - else { - return b; - } - -} - -#ifdef FLOATX80 - -/*---------------------------------------------------------------------------- -| The pattern for a default generated extended double-precision NaN. The -| `high' and `low' values hold the most- and least-significant bits, -| respectively. -*----------------------------------------------------------------------------*/ -#define floatx80_default_nan_high 0xFFFF -#define floatx80_default_nan_low LIT64( 0xFFFFFFFFFFFFFFFF ) - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is a -| NaN; otherwise returns 0. -*----------------------------------------------------------------------------*/ - -flag floatx80_is_nan( floatx80 a ) -{ - - return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is a -| signaling NaN; otherwise returns 0. -*----------------------------------------------------------------------------*/ - -flag floatx80_is_signaling_nan( floatx80 a ) -{ - bits64 aLow; - - aLow = a.low & ~ LIT64( 0x4000000000000000 ); - return - ( ( a.high & 0x7FFF ) == 0x7FFF ) - && (bits64) ( aLow<<1 ) - && ( a.low == aLow ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the extended double-precision floating- -| point NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the -| invalid exception is raised. -*----------------------------------------------------------------------------*/ - -static commonNaNT floatx80ToCommonNaN( floatx80 a ) -{ - commonNaNT z; - - if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); - z.sign = a.high>>15; - z.low = 0; - z.high = a.low<<1; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the canonical NaN `a' to the extended -| double-precision floating-point format. -*----------------------------------------------------------------------------*/ - -static floatx80 commonNaNToFloatx80( commonNaNT a ) -{ - floatx80 z; - - z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 ); - z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF; - return z; - -} - -/*---------------------------------------------------------------------------- -| Takes two extended double-precision floating-point values `a' and `b', one -| of which is a NaN, and returns the appropriate NaN result. If either `a' or -| `b' is a signaling NaN, the invalid exception is raised. -*----------------------------------------------------------------------------*/ - -floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b ) -{ - flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; - - aIsNaN = floatx80_is_nan( a ); - aIsSignalingNaN = floatx80_is_signaling_nan( a ); - bIsNaN = floatx80_is_nan( b ); - bIsSignalingNaN = floatx80_is_signaling_nan( b ); - a.low |= LIT64( 0xC000000000000000 ); - b.low |= LIT64( 0xC000000000000000 ); - if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); - if ( aIsNaN ) { - return ( aIsSignalingNaN & bIsNaN ) ? b : a; - } - else { - return b; - } - -} - -#define EXP_BIAS 0x3FFF - -/*---------------------------------------------------------------------------- -| Returns the fraction bits of the extended double-precision floating-point -| value `a'. -*----------------------------------------------------------------------------*/ - -static inline bits64 extractFloatx80Frac( floatx80 a ) -{ - - return a.low; - -} - -/*---------------------------------------------------------------------------- -| Returns the exponent bits of the extended double-precision floating-point -| value `a'. -*----------------------------------------------------------------------------*/ - -static inline int32 extractFloatx80Exp( floatx80 a ) -{ - - return a.high & 0x7FFF; - -} - -/*---------------------------------------------------------------------------- -| Returns the sign bit of the extended double-precision floating-point value -| `a'. -*----------------------------------------------------------------------------*/ - -static inline flag extractFloatx80Sign( floatx80 a ) -{ - - return a.high>>15; - -} - -#endif - -#ifdef FLOAT128 - -/*---------------------------------------------------------------------------- -| The pattern for a default generated quadruple-precision NaN. The `high' and -| `low' values hold the most- and least-significant bits, respectively. -*----------------------------------------------------------------------------*/ -#define float128_default_nan_high LIT64( 0xFFFFFFFFFFFFFFFF ) -#define float128_default_nan_low LIT64( 0xFFFFFFFFFFFFFFFF ) - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is a NaN; -| otherwise returns 0. -*----------------------------------------------------------------------------*/ - -flag float128_is_nan( float128 a ) -{ - - return - ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) ) - && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is a -| signaling NaN; otherwise returns 0. -*----------------------------------------------------------------------------*/ - -flag float128_is_signaling_nan( float128 a ) -{ - - return - ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE ) - && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the quadruple-precision floating-point NaN -| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid -| exception is raised. -*----------------------------------------------------------------------------*/ - -static commonNaNT float128ToCommonNaN( float128 a ) -{ - commonNaNT z; - - if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); - z.sign = a.high>>63; - shortShift128Left( a.high, a.low, 16, &z.high, &z.low ); - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the canonical NaN `a' to the quadruple- -| precision floating-point format. -*----------------------------------------------------------------------------*/ - -static float128 commonNaNToFloat128( commonNaNT a ) -{ - float128 z; - - shift128Right( a.high, a.low, 16, &z.high, &z.low ); - z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 ); - return z; - -} - -/*---------------------------------------------------------------------------- -| Takes two quadruple-precision floating-point values `a' and `b', one of -| which is a NaN, and returns the appropriate NaN result. If either `a' or -| `b' is a signaling NaN, the invalid exception is raised. -*----------------------------------------------------------------------------*/ - -static float128 propagateFloat128NaN( float128 a, float128 b ) -{ - flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; - - aIsNaN = float128_is_nan( a ); - aIsSignalingNaN = float128_is_signaling_nan( a ); - bIsNaN = float128_is_nan( b ); - bIsSignalingNaN = float128_is_signaling_nan( b ); - a.high |= LIT64( 0x0000800000000000 ); - b.high |= LIT64( 0x0000800000000000 ); - if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); - if ( aIsNaN ) { - return ( aIsSignalingNaN & bIsNaN ) ? b : a; - } - else { - return b; - } - -} - -#endif - diff --git a/machine/musashi/softfloat/softfloat.c b/machine/musashi/softfloat/softfloat.c deleted file mode 100644 index 400fd59..0000000 --- a/machine/musashi/softfloat/softfloat.c +++ /dev/null @@ -1,4940 +0,0 @@ - -/*============================================================================ - -This C source file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic -Package, Release 2b. - -Written by John R. Hauser. This work was made possible in part by the -International Computer Science Institute, located at Suite 600, 1947 Center -Street, Berkeley, California 94704. Funding was partially provided by the -National Science Foundation under grant MIP-9311980. The original version -of this code was written as part of a project to build a fixed-point vector -processor in collaboration with the University of California at Berkeley, -overseen by Profs. Nelson Morgan and John Wawrzynek. More information -is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ -arithmetic/SoftFloat.html'. - -THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has -been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES -RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS -AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, -COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE -EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE -INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR -OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. - -Derivative works are acceptable, even for commercial purposes, so long as -(1) the source code for the derivative work includes prominent notice that -the work is derivative, and (2) the source code includes prominent notice with -these four paragraphs for those parts of this code that are retained. - -=============================================================================*/ - -#include "../m68kcpu.h" // which includes softfloat.h after defining the basic types - -/*---------------------------------------------------------------------------- -| Floating-point rounding mode, extended double-precision rounding precision, -| and exception flags. -*----------------------------------------------------------------------------*/ -int8 float_exception_flags = 0; -#ifdef FLOATX80 -int8 floatx80_rounding_precision = 80; -#endif - -int8 float_rounding_mode = float_round_nearest_even; - -/*---------------------------------------------------------------------------- -| Functions and definitions to determine: (1) whether tininess for underflow -| is detected before or after rounding by default, (2) what (if anything) -| happens when exceptions are raised, (3) how signaling NaNs are distinguished -| from quiet NaNs, (4) the default generated quiet NaNs, and (5) how NaNs -| are propagated from function inputs to output. These details are target- -| specific. -*----------------------------------------------------------------------------*/ -#include "softfloat-specialize" - -/*---------------------------------------------------------------------------- -| Takes a 64-bit fixed-point value `absZ' with binary point between bits 6 -| and 7, and returns the properly rounded 32-bit integer corresponding to the -| input. If `zSign' is 1, the input is negated before being converted to an -| integer. Bit 63 of `absZ' must be zero. Ordinarily, the fixed-point input -| is simply rounded to an integer, with the inexact exception raised if the -| input cannot be represented exactly as an integer. However, if the fixed- -| point input is too large, the invalid exception is raised and the largest -| positive or negative integer is returned. -*----------------------------------------------------------------------------*/ - -static int32 roundAndPackInt32( flag zSign, bits64 absZ ) -{ - int8 roundingMode; - flag roundNearestEven; - int8 roundIncrement, roundBits; - int32 z; - - roundingMode = float_rounding_mode; - roundNearestEven = ( roundingMode == float_round_nearest_even ); - roundIncrement = 0x40; - if ( ! roundNearestEven ) { - if ( roundingMode == float_round_to_zero ) { - roundIncrement = 0; - } - else { - roundIncrement = 0x7F; - if ( zSign ) { - if ( roundingMode == float_round_up ) roundIncrement = 0; - } - else { - if ( roundingMode == float_round_down ) roundIncrement = 0; - } - } - } - roundBits = absZ & 0x7F; - absZ = ( absZ + roundIncrement )>>7; - absZ &= ~ ( ( ( roundBits ^ 0x40 ) == 0 ) & roundNearestEven ); - z = absZ; - if ( zSign ) z = - z; - if ( ( absZ>>32 ) || ( z && ( ( z < 0 ) ^ zSign ) ) ) { - float_raise( float_flag_invalid ); - return zSign ? (sbits32) 0x80000000 : 0x7FFFFFFF; - } - if ( roundBits ) float_exception_flags |= float_flag_inexact; - return z; - -} - -/*---------------------------------------------------------------------------- -| Takes the 128-bit fixed-point value formed by concatenating `absZ0' and -| `absZ1', with binary point between bits 63 and 64 (between the input words), -| and returns the properly rounded 64-bit integer corresponding to the input. -| If `zSign' is 1, the input is negated before being converted to an integer. -| Ordinarily, the fixed-point input is simply rounded to an integer, with -| the inexact exception raised if the input cannot be represented exactly as -| an integer. However, if the fixed-point input is too large, the invalid -| exception is raised and the largest positive or negative integer is -| returned. -*----------------------------------------------------------------------------*/ - -static int64 roundAndPackInt64( flag zSign, bits64 absZ0, bits64 absZ1 ) -{ - int8 roundingMode; - flag roundNearestEven, increment; - int64 z; - - roundingMode = float_rounding_mode; - roundNearestEven = ( roundingMode == float_round_nearest_even ); - increment = ( (sbits64) absZ1 < 0 ); - if ( ! roundNearestEven ) { - if ( roundingMode == float_round_to_zero ) { - increment = 0; - } - else { - if ( zSign ) { - increment = ( roundingMode == float_round_down ) && absZ1; - } - else { - increment = ( roundingMode == float_round_up ) && absZ1; - } - } - } - if ( increment ) { - ++absZ0; - if ( absZ0 == 0 ) goto overflow; - absZ0 &= ~ ( ( (bits64) ( absZ1<<1 ) == 0 ) & roundNearestEven ); - } - z = absZ0; - if ( zSign ) z = - z; - if ( z && ( ( z < 0 ) ^ zSign ) ) { - overflow: - float_raise( float_flag_invalid ); - return - zSign ? (sbits64) LIT64( 0x8000000000000000 ) - : (sbits64) LIT64( 0x7FFFFFFFFFFFFFFF ); - } - if ( absZ1 ) float_exception_flags |= float_flag_inexact; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the fraction bits of the single-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -static inline bits32 extractFloat32Frac( float32 a ) -{ - return a & 0x007FFFFF; - -} - -/*---------------------------------------------------------------------------- -| Returns the exponent bits of the single-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -static inline int16 extractFloat32Exp( float32 a ) -{ - return ( a>>23 ) & 0xFF; - -} - -/*---------------------------------------------------------------------------- -| Returns the sign bit of the single-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -static inline flag extractFloat32Sign( float32 a ) -{ - return a>>31; - -} - -/*---------------------------------------------------------------------------- -| Normalizes the subnormal single-precision floating-point value represented -| by the denormalized significand `aSig'. The normalized exponent and -| significand are stored at the locations pointed to by `zExpPtr' and -| `zSigPtr', respectively. -*----------------------------------------------------------------------------*/ - -static void - normalizeFloat32Subnormal( bits32 aSig, int16 *zExpPtr, bits32 *zSigPtr ) -{ - int8 shiftCount; - - shiftCount = countLeadingZeros32( aSig ) - 8; - *zSigPtr = aSig<>7; - zSig &= ~ ( ( ( roundBits ^ 0x40 ) == 0 ) & roundNearestEven ); - if ( zSig == 0 ) zExp = 0; - return packFloat32( zSign, zExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Takes an abstract floating-point value having sign `zSign', exponent `zExp', -| and significand `zSig', and returns the proper single-precision floating- -| point value corresponding to the abstract input. This routine is just like -| `roundAndPackFloat32' except that `zSig' does not have to be normalized. -| Bit 31 of `zSig' must be zero, and `zExp' must be 1 less than the ``true'' -| floating-point exponent. -*----------------------------------------------------------------------------*/ - -static float32 - normalizeRoundAndPackFloat32( flag zSign, int16 zExp, bits32 zSig ) -{ - int8 shiftCount; - - shiftCount = countLeadingZeros32( zSig ) - 1; - return roundAndPackFloat32( zSign, zExp - shiftCount, zSig<>52 ) & 0x7FF; - -} - -/*---------------------------------------------------------------------------- -| Returns the sign bit of the double-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -static inline flag extractFloat64Sign( float64 a ) -{ - return a>>63; - -} - -/*---------------------------------------------------------------------------- -| Normalizes the subnormal double-precision floating-point value represented -| by the denormalized significand `aSig'. The normalized exponent and -| significand are stored at the locations pointed to by `zExpPtr' and -| `zSigPtr', respectively. -*----------------------------------------------------------------------------*/ - -static void - normalizeFloat64Subnormal( bits64 aSig, int16 *zExpPtr, bits64 *zSigPtr ) -{ - int8 shiftCount; - - shiftCount = countLeadingZeros64( aSig ) - 11; - *zSigPtr = aSig<>10; - zSig &= ~ ( ( ( roundBits ^ 0x200 ) == 0 ) & roundNearestEven ); - if ( zSig == 0 ) zExp = 0; - return packFloat64( zSign, zExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Takes an abstract floating-point value having sign `zSign', exponent `zExp', -| and significand `zSig', and returns the proper double-precision floating- -| point value corresponding to the abstract input. This routine is just like -| `roundAndPackFloat64' except that `zSig' does not have to be normalized. -| Bit 63 of `zSig' must be zero, and `zExp' must be 1 less than the ``true'' -| floating-point exponent. -*----------------------------------------------------------------------------*/ - -static float64 - normalizeRoundAndPackFloat64( flag zSign, int16 zExp, bits64 zSig ) -{ - int8 shiftCount; - - shiftCount = countLeadingZeros64( zSig ) - 1; - return roundAndPackFloat64( zSign, zExp - shiftCount, zSig<>48 ) & 0x7FFF; - -} - -/*---------------------------------------------------------------------------- -| Returns the sign bit of the quadruple-precision floating-point value `a'. -*----------------------------------------------------------------------------*/ - -static inline flag extractFloat128Sign( float128 a ) -{ - return a.high>>63; - -} - -/*---------------------------------------------------------------------------- -| Normalizes the subnormal quadruple-precision floating-point value -| represented by the denormalized significand formed by the concatenation of -| `aSig0' and `aSig1'. The normalized exponent is stored at the location -| pointed to by `zExpPtr'. The most significant 49 bits of the normalized -| significand are stored at the location pointed to by `zSig0Ptr', and the -| least significant 64 bits of the normalized significand are stored at the -| location pointed to by `zSig1Ptr'. -*----------------------------------------------------------------------------*/ - -static void - normalizeFloat128Subnormal( - bits64 aSig0, - bits64 aSig1, - int32 *zExpPtr, - bits64 *zSig0Ptr, - bits64 *zSig1Ptr - ) -{ - int8 shiftCount; - - if ( aSig0 == 0 ) { - shiftCount = countLeadingZeros64( aSig1 ) - 15; - if ( shiftCount < 0 ) { - *zSig0Ptr = aSig1>>( - shiftCount ); - *zSig1Ptr = aSig1<<( shiftCount & 63 ); - } - else { - *zSig0Ptr = aSig1<>( - shiftCount ); - if ( (bits32) ( aSig<<( shiftCount & 31 ) ) ) { - float_exception_flags |= float_flag_inexact; - } - if ( aSign ) z = - z; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point value -| `a' to the 64-bit two's complement integer format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic---which means in particular that the conversion is rounded -| according to the current rounding mode. If `a' is a NaN, the largest -| positive integer is returned. Otherwise, if the conversion overflows, the -| largest integer with the same sign as `a' is returned. -*----------------------------------------------------------------------------*/ - -int64 float32_to_int64( float32 a ) -{ - flag aSign; - int16 aExp, shiftCount; - bits32 aSig; - bits64 aSig64, aSigExtra; - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); - shiftCount = 0xBE - aExp; - if ( shiftCount < 0 ) { - float_raise( float_flag_invalid ); - if ( ! aSign || ( ( aExp == 0xFF ) && aSig ) ) { - return LIT64( 0x7FFFFFFFFFFFFFFF ); - } - return (sbits64) LIT64( 0x8000000000000000 ); - } - if ( aExp ) aSig |= 0x00800000; - aSig64 = aSig; - aSig64 <<= 40; - shift64ExtraRightJamming( aSig64, 0, shiftCount, &aSig64, &aSigExtra ); - return roundAndPackInt64( aSign, aSig64, aSigExtra ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point value -| `a' to the 64-bit two's complement integer format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic, except that the conversion is always rounded toward zero. If -| `a' is a NaN, the largest positive integer is returned. Otherwise, if the -| conversion overflows, the largest integer with the same sign as `a' is -| returned. -*----------------------------------------------------------------------------*/ - -int64 float32_to_int64_round_to_zero( float32 a ) -{ - flag aSign; - int16 aExp, shiftCount; - bits32 aSig; - bits64 aSig64; - int64 z; - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); - shiftCount = aExp - 0xBE; - if ( 0 <= shiftCount ) { - if ( a != 0xDF000000 ) { - float_raise( float_flag_invalid ); - if ( ! aSign || ( ( aExp == 0xFF ) && aSig ) ) { - return LIT64( 0x7FFFFFFFFFFFFFFF ); - } - } - return (sbits64) LIT64( 0x8000000000000000 ); - } - else if ( aExp <= 0x7E ) { - if ( aExp | aSig ) float_exception_flags |= float_flag_inexact; - return 0; - } - aSig64 = aSig | 0x00800000; - aSig64 <<= 40; - z = aSig64>>( - shiftCount ); - if ( (bits64) ( aSig64<<( shiftCount & 63 ) ) ) { - float_exception_flags |= float_flag_inexact; - } - if ( aSign ) z = - z; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point value -| `a' to the double-precision floating-point format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float32_to_float64( float32 a ) -{ - flag aSign; - int16 aExp; - bits32 aSig; - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); - if ( aExp == 0xFF ) { - if ( aSig ) return commonNaNToFloat64( float32ToCommonNaN( a ) ); - return packFloat64( aSign, 0x7FF, 0 ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloat64( aSign, 0, 0 ); - normalizeFloat32Subnormal( aSig, &aExp, &aSig ); - --aExp; - } - return packFloat64( aSign, aExp + 0x380, ( (bits64) aSig )<<29 ); - -} - -#ifdef FLOATX80 - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point value -| `a' to the extended double-precision floating-point format. The conversion -| is performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 float32_to_floatx80( float32 a ) -{ - flag aSign; - int16 aExp; - bits32 aSig; - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); - if ( aExp == 0xFF ) { - if ( aSig ) return commonNaNToFloatx80( float32ToCommonNaN( a ) ); - return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloatx80( aSign, 0, 0 ); - normalizeFloat32Subnormal( aSig, &aExp, &aSig ); - } - aSig |= 0x00800000; - return packFloatx80( aSign, aExp + 0x3F80, ( (bits64) aSig )<<40 ); - -} - -#endif - -#ifdef FLOAT128 - -/*---------------------------------------------------------------------------- -| Returns the result of converting the single-precision floating-point value -| `a' to the double-precision floating-point format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float32_to_float128( float32 a ) -{ - flag aSign; - int16 aExp; - bits32 aSig; - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); - if ( aExp == 0xFF ) { - if ( aSig ) return commonNaNToFloat128( float32ToCommonNaN( a ) ); - return packFloat128( aSign, 0x7FFF, 0, 0 ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloat128( aSign, 0, 0, 0 ); - normalizeFloat32Subnormal( aSig, &aExp, &aSig ); - --aExp; - } - return packFloat128( aSign, aExp + 0x3F80, ( (bits64) aSig )<<25, 0 ); - -} - -#endif - -/*---------------------------------------------------------------------------- -| Rounds the single-precision floating-point value `a' to an integer, and -| returns the result as a single-precision floating-point value. The -| operation is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_round_to_int( float32 a ) -{ - flag aSign; - int16 aExp; - bits32 lastBitMask, roundBitsMask; - int8 roundingMode; - float32 z; - - aExp = extractFloat32Exp( a ); - if ( 0x96 <= aExp ) { - if ( ( aExp == 0xFF ) && extractFloat32Frac( a ) ) { - return propagateFloat32NaN( a, a ); - } - return a; - } - if ( aExp <= 0x7E ) { - if ( (bits32) ( a<<1 ) == 0 ) return a; - float_exception_flags |= float_flag_inexact; - aSign = extractFloat32Sign( a ); - switch ( float_rounding_mode ) { - case float_round_nearest_even: - if ( ( aExp == 0x7E ) && extractFloat32Frac( a ) ) { - return packFloat32( aSign, 0x7F, 0 ); - } - break; - case float_round_down: - return aSign ? 0xBF800000 : 0; - case float_round_up: - return aSign ? 0x80000000 : 0x3F800000; - } - return packFloat32( aSign, 0, 0 ); - } - lastBitMask = 1; - lastBitMask <<= 0x96 - aExp; - roundBitsMask = lastBitMask - 1; - z = a; - roundingMode = float_rounding_mode; - if ( roundingMode == float_round_nearest_even ) { - z += lastBitMask>>1; - if ( ( z & roundBitsMask ) == 0 ) z &= ~ lastBitMask; - } - else if ( roundingMode != float_round_to_zero ) { - if ( extractFloat32Sign( z ) ^ ( roundingMode == float_round_up ) ) { - z += roundBitsMask; - } - } - z &= ~ roundBitsMask; - if ( z != a ) float_exception_flags |= float_flag_inexact; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the absolute values of the single-precision -| floating-point values `a' and `b'. If `zSign' is 1, the sum is negated -| before being returned. `zSign' is ignored if the result is a NaN. -| The addition is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static float32 addFloat32Sigs( float32 a, float32 b, flag zSign ) -{ - int16 aExp, bExp, zExp; - bits32 aSig, bSig, zSig; - int16 expDiff; - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - bSig = extractFloat32Frac( b ); - bExp = extractFloat32Exp( b ); - expDiff = aExp - bExp; - aSig <<= 6; - bSig <<= 6; - if ( 0 < expDiff ) { - if ( aExp == 0xFF ) { - if ( aSig ) return propagateFloat32NaN( a, b ); - return a; - } - if ( bExp == 0 ) { - --expDiff; - } - else { - bSig |= 0x20000000; - } - shift32RightJamming( bSig, expDiff, &bSig ); - zExp = aExp; - } - else if ( expDiff < 0 ) { - if ( bExp == 0xFF ) { - if ( bSig ) return propagateFloat32NaN( a, b ); - return packFloat32( zSign, 0xFF, 0 ); - } - if ( aExp == 0 ) { - ++expDiff; - } - else { - aSig |= 0x20000000; - } - shift32RightJamming( aSig, - expDiff, &aSig ); - zExp = bExp; - } - else { - if ( aExp == 0xFF ) { - if ( aSig | bSig ) return propagateFloat32NaN( a, b ); - return a; - } - if ( aExp == 0 ) return packFloat32( zSign, 0, ( aSig + bSig )>>6 ); - zSig = 0x40000000 + aSig + bSig; - zExp = aExp; - goto roundAndPack; - } - aSig |= 0x20000000; - zSig = ( aSig + bSig )<<1; - --zExp; - if ( (sbits32) zSig < 0 ) { - zSig = aSig + bSig; - ++zExp; - } - roundAndPack: - return roundAndPackFloat32( zSign, zExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the absolute values of the single- -| precision floating-point values `a' and `b'. If `zSign' is 1, the -| difference is negated before being returned. `zSign' is ignored if the -| result is a NaN. The subtraction is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static float32 subFloat32Sigs( float32 a, float32 b, flag zSign ) -{ - int16 aExp, bExp, zExp; - bits32 aSig, bSig, zSig; - int16 expDiff; - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - bSig = extractFloat32Frac( b ); - bExp = extractFloat32Exp( b ); - expDiff = aExp - bExp; - aSig <<= 7; - bSig <<= 7; - if ( 0 < expDiff ) goto aExpBigger; - if ( expDiff < 0 ) goto bExpBigger; - if ( aExp == 0xFF ) { - if ( aSig | bSig ) return propagateFloat32NaN( a, b ); - float_raise( float_flag_invalid ); - return float32_default_nan; - } - if ( aExp == 0 ) { - aExp = 1; - bExp = 1; - } - if ( bSig < aSig ) goto aBigger; - if ( aSig < bSig ) goto bBigger; - return packFloat32( float_rounding_mode == float_round_down, 0, 0 ); - bExpBigger: - if ( bExp == 0xFF ) { - if ( bSig ) return propagateFloat32NaN( a, b ); - return packFloat32( zSign ^ 1, 0xFF, 0 ); - } - if ( aExp == 0 ) { - ++expDiff; - } - else { - aSig |= 0x40000000; - } - shift32RightJamming( aSig, - expDiff, &aSig ); - bSig |= 0x40000000; - bBigger: - zSig = bSig - aSig; - zExp = bExp; - zSign ^= 1; - goto normalizeRoundAndPack; - aExpBigger: - if ( aExp == 0xFF ) { - if ( aSig ) return propagateFloat32NaN( a, b ); - return a; - } - if ( bExp == 0 ) { - --expDiff; - } - else { - bSig |= 0x40000000; - } - shift32RightJamming( bSig, expDiff, &bSig ); - aSig |= 0x40000000; - aBigger: - zSig = aSig - bSig; - zExp = aExp; - normalizeRoundAndPack: - --zExp; - return normalizeRoundAndPackFloat32( zSign, zExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the single-precision floating-point values `a' -| and `b'. The operation is performed according to the IEC/IEEE Standard for -| Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_add( float32 a, float32 b ) -{ - flag aSign, bSign; - - aSign = extractFloat32Sign( a ); - bSign = extractFloat32Sign( b ); - if ( aSign == bSign ) { - return addFloat32Sigs( a, b, aSign ); - } - else { - return subFloat32Sigs( a, b, aSign ); - } - -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the single-precision floating-point values -| `a' and `b'. The operation is performed according to the IEC/IEEE Standard -| for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_sub( float32 a, float32 b ) -{ - flag aSign, bSign; - - aSign = extractFloat32Sign( a ); - bSign = extractFloat32Sign( b ); - if ( aSign == bSign ) { - return subFloat32Sigs( a, b, aSign ); - } - else { - return addFloat32Sigs( a, b, aSign ); - } - -} - -/*---------------------------------------------------------------------------- -| Returns the result of multiplying the single-precision floating-point values -| `a' and `b'. The operation is performed according to the IEC/IEEE Standard -| for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_mul( float32 a, float32 b ) -{ - flag aSign, bSign, zSign; - int16 aExp, bExp, zExp; - bits32 aSig, bSig; - bits64 zSig64; - bits32 zSig; - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); - bSig = extractFloat32Frac( b ); - bExp = extractFloat32Exp( b ); - bSign = extractFloat32Sign( b ); - zSign = aSign ^ bSign; - if ( aExp == 0xFF ) { - if ( aSig || ( ( bExp == 0xFF ) && bSig ) ) { - return propagateFloat32NaN( a, b ); - } - if ( ( bExp | bSig ) == 0 ) { - float_raise( float_flag_invalid ); - return float32_default_nan; - } - return packFloat32( zSign, 0xFF, 0 ); - } - if ( bExp == 0xFF ) { - if ( bSig ) return propagateFloat32NaN( a, b ); - if ( ( aExp | aSig ) == 0 ) { - float_raise( float_flag_invalid ); - return float32_default_nan; - } - return packFloat32( zSign, 0xFF, 0 ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloat32( zSign, 0, 0 ); - normalizeFloat32Subnormal( aSig, &aExp, &aSig ); - } - if ( bExp == 0 ) { - if ( bSig == 0 ) return packFloat32( zSign, 0, 0 ); - normalizeFloat32Subnormal( bSig, &bExp, &bSig ); - } - zExp = aExp + bExp - 0x7F; - aSig = ( aSig | 0x00800000 )<<7; - bSig = ( bSig | 0x00800000 )<<8; - shift64RightJamming( ( (bits64) aSig ) * bSig, 32, &zSig64 ); - zSig = zSig64; - if ( 0 <= (sbits32) ( zSig<<1 ) ) { - zSig <<= 1; - --zExp; - } - return roundAndPackFloat32( zSign, zExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of dividing the single-precision floating-point value `a' -| by the corresponding value `b'. The operation is performed according to the -| IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_div( float32 a, float32 b ) -{ - flag aSign, bSign, zSign; - int16 aExp, bExp, zExp; - bits32 aSig, bSig, zSig; - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); - bSig = extractFloat32Frac( b ); - bExp = extractFloat32Exp( b ); - bSign = extractFloat32Sign( b ); - zSign = aSign ^ bSign; - if ( aExp == 0xFF ) { - if ( aSig ) return propagateFloat32NaN( a, b ); - if ( bExp == 0xFF ) { - if ( bSig ) return propagateFloat32NaN( a, b ); - float_raise( float_flag_invalid ); - return float32_default_nan; - } - return packFloat32( zSign, 0xFF, 0 ); - } - if ( bExp == 0xFF ) { - if ( bSig ) return propagateFloat32NaN( a, b ); - return packFloat32( zSign, 0, 0 ); - } - if ( bExp == 0 ) { - if ( bSig == 0 ) { - if ( ( aExp | aSig ) == 0 ) { - float_raise( float_flag_invalid ); - return float32_default_nan; - } - float_raise( float_flag_divbyzero ); - return packFloat32( zSign, 0xFF, 0 ); - } - normalizeFloat32Subnormal( bSig, &bExp, &bSig ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloat32( zSign, 0, 0 ); - normalizeFloat32Subnormal( aSig, &aExp, &aSig ); - } - zExp = aExp - bExp + 0x7D; - aSig = ( aSig | 0x00800000 )<<7; - bSig = ( bSig | 0x00800000 )<<8; - if ( bSig <= ( aSig + aSig ) ) { - aSig >>= 1; - ++zExp; - } - zSig = ( ( (bits64) aSig )<<32 ) / bSig; - if ( ( zSig & 0x3F ) == 0 ) { - zSig |= ( (bits64) bSig * zSig != ( (bits64) aSig )<<32 ); - } - return roundAndPackFloat32( zSign, zExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the remainder of the single-precision floating-point value `a' -| with respect to the corresponding value `b'. The operation is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_rem( float32 a, float32 b ) -{ - flag aSign, zSign; - int16 aExp, bExp, expDiff; - bits32 aSig, bSig; - bits32 q; - bits64 aSig64, bSig64, q64; - bits32 alternateASig; - sbits32 sigMean; - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); - bSig = extractFloat32Frac( b ); - bExp = extractFloat32Exp( b ); -// bSign = extractFloat32Sign( b ); - if ( aExp == 0xFF ) { - if ( aSig || ( ( bExp == 0xFF ) && bSig ) ) { - return propagateFloat32NaN( a, b ); - } - float_raise( float_flag_invalid ); - return float32_default_nan; - } - if ( bExp == 0xFF ) { - if ( bSig ) return propagateFloat32NaN( a, b ); - return a; - } - if ( bExp == 0 ) { - if ( bSig == 0 ) { - float_raise( float_flag_invalid ); - return float32_default_nan; - } - normalizeFloat32Subnormal( bSig, &bExp, &bSig ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return a; - normalizeFloat32Subnormal( aSig, &aExp, &aSig ); - } - expDiff = aExp - bExp; - aSig |= 0x00800000; - bSig |= 0x00800000; - if ( expDiff < 32 ) { - aSig <<= 8; - bSig <<= 8; - if ( expDiff < 0 ) { - if ( expDiff < -1 ) return a; - aSig >>= 1; - } - q = ( bSig <= aSig ); - if ( q ) aSig -= bSig; - if ( 0 < expDiff ) { - q = ( ( (bits64) aSig )<<32 ) / bSig; - q >>= 32 - expDiff; - bSig >>= 2; - aSig = ( ( aSig>>1 )<<( expDiff - 1 ) ) - bSig * q; - } - else { - aSig >>= 2; - bSig >>= 2; - } - } - else { - if ( bSig <= aSig ) aSig -= bSig; - aSig64 = ( (bits64) aSig )<<40; - bSig64 = ( (bits64) bSig )<<40; - expDiff -= 64; - while ( 0 < expDiff ) { - q64 = estimateDiv128To64( aSig64, 0, bSig64 ); - q64 = ( 2 < q64 ) ? q64 - 2 : 0; - aSig64 = - ( ( bSig * q64 )<<38 ); - expDiff -= 62; - } - expDiff += 64; - q64 = estimateDiv128To64( aSig64, 0, bSig64 ); - q64 = ( 2 < q64 ) ? q64 - 2 : 0; - q = q64>>( 64 - expDiff ); - bSig <<= 6; - aSig = ( ( aSig64>>33 )<<( expDiff - 1 ) ) - bSig * q; - } - do { - alternateASig = aSig; - ++q; - aSig -= bSig; - } while ( 0 <= (sbits32) aSig ); - sigMean = aSig + alternateASig; - if ( ( sigMean < 0 ) || ( ( sigMean == 0 ) && ( q & 1 ) ) ) { - aSig = alternateASig; - } - zSign = ( (sbits32) aSig < 0 ); - if ( zSign ) aSig = - aSig; - return normalizeRoundAndPackFloat32( aSign ^ zSign, bExp, aSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the square root of the single-precision floating-point value `a'. -| The operation is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float32_sqrt( float32 a ) -{ - flag aSign; - int16 aExp, zExp; - bits32 aSig, zSig; - bits64 rem, term; - - aSig = extractFloat32Frac( a ); - aExp = extractFloat32Exp( a ); - aSign = extractFloat32Sign( a ); - if ( aExp == 0xFF ) { - if ( aSig ) return propagateFloat32NaN( a, 0 ); - if ( ! aSign ) return a; - float_raise( float_flag_invalid ); - return float32_default_nan; - } - if ( aSign ) { - if ( ( aExp | aSig ) == 0 ) return a; - float_raise( float_flag_invalid ); - return float32_default_nan; - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return 0; - normalizeFloat32Subnormal( aSig, &aExp, &aSig ); - } - zExp = ( ( aExp - 0x7F )>>1 ) + 0x7E; - aSig = ( aSig | 0x00800000 )<<8; - zSig = estimateSqrt32( aExp, aSig ) + 2; - if ( ( zSig & 0x7F ) <= 5 ) { - if ( zSig < 2 ) { - zSig = 0x7FFFFFFF; - goto roundAndPack; - } - aSig >>= aExp & 1; - term = ( (bits64) zSig ) * zSig; - rem = ( ( (bits64) aSig )<<32 ) - term; - while ( (sbits64) rem < 0 ) { - --zSig; - rem += ( ( (bits64) zSig )<<1 ) | 1; - } - zSig |= ( rem != 0 ); - } - shift32RightJamming( zSig, 1, &zSig ); - roundAndPack: - return roundAndPackFloat32( 0, zExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is equal to -| the corresponding value `b', and 0 otherwise. The comparison is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float32_eq( float32 a, float32 b ) -{ - if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) - || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) - ) { - if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - return ( a == b ) || ( (bits32) ( ( a | b )<<1 ) == 0 ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is less than -| or equal to the corresponding value `b', and 0 otherwise. The comparison -| is performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float32_le( float32 a, float32 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) - || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - aSign = extractFloat32Sign( a ); - bSign = extractFloat32Sign( b ); - if ( aSign != bSign ) return aSign || ( (bits32) ( ( a | b )<<1 ) == 0 ); - return ( a == b ) || ( aSign ^ ( a < b ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is less than -| the corresponding value `b', and 0 otherwise. The comparison is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float32_lt( float32 a, float32 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) - || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - aSign = extractFloat32Sign( a ); - bSign = extractFloat32Sign( b ); - if ( aSign != bSign ) return aSign && ( (bits32) ( ( a | b )<<1 ) != 0 ); - return ( a != b ) && ( aSign ^ ( a < b ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is equal to -| the corresponding value `b', and 0 otherwise. The invalid exception is -| raised if either operand is a NaN. Otherwise, the comparison is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float32_eq_signaling( float32 a, float32 b ) -{ - if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) - || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - return ( a == b ) || ( (bits32) ( ( a | b )<<1 ) == 0 ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is less than or -| equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not -| cause an exception. Otherwise, the comparison is performed according to the -| IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float32_le_quiet( float32 a, float32 b ) -{ - flag aSign, bSign; -// int16 aExp, bExp; - - if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) - || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) - ) { - if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - aSign = extractFloat32Sign( a ); - bSign = extractFloat32Sign( b ); - if ( aSign != bSign ) return aSign || ( (bits32) ( ( a | b )<<1 ) == 0 ); - return ( a == b ) || ( aSign ^ ( a < b ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the single-precision floating-point value `a' is less than -| the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an -| exception. Otherwise, the comparison is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float32_lt_quiet( float32 a, float32 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) ) - || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) ) - ) { - if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - aSign = extractFloat32Sign( a ); - bSign = extractFloat32Sign( b ); - if ( aSign != bSign ) return aSign && ( (bits32) ( ( a | b )<<1 ) != 0 ); - return ( a != b ) && ( aSign ^ ( a < b ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-precision floating-point value -| `a' to the 32-bit two's complement integer format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic---which means in particular that the conversion is rounded -| according to the current rounding mode. If `a' is a NaN, the largest -| positive integer is returned. Otherwise, if the conversion overflows, the -| largest integer with the same sign as `a' is returned. -*----------------------------------------------------------------------------*/ - -int32 float64_to_int32( float64 a ) -{ - flag aSign; - int16 aExp, shiftCount; - bits64 aSig; - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); - if ( ( aExp == 0x7FF ) && aSig ) aSign = 0; - if ( aExp ) aSig |= LIT64( 0x0010000000000000 ); - shiftCount = 0x42C - aExp; - if ( 0 < shiftCount ) shift64RightJamming( aSig, shiftCount, &aSig ); - return roundAndPackInt32( aSign, aSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-precision floating-point value -| `a' to the 32-bit two's complement integer format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic, except that the conversion is always rounded toward zero. -| If `a' is a NaN, the largest positive integer is returned. Otherwise, if -| the conversion overflows, the largest integer with the same sign as `a' is -| returned. -*----------------------------------------------------------------------------*/ - -int32 float64_to_int32_round_to_zero( float64 a ) -{ - flag aSign; - int16 aExp, shiftCount; - bits64 aSig, savedASig; - int32 z; - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); - if ( 0x41E < aExp ) { - if ( ( aExp == 0x7FF ) && aSig ) aSign = 0; - goto invalid; - } - else if ( aExp < 0x3FF ) { - if ( aExp || aSig ) float_exception_flags |= float_flag_inexact; - return 0; - } - aSig |= LIT64( 0x0010000000000000 ); - shiftCount = 0x433 - aExp; - savedASig = aSig; - aSig >>= shiftCount; - z = aSig; - if ( aSign ) z = - z; - if ( ( z < 0 ) ^ aSign ) { - invalid: - float_raise( float_flag_invalid ); - return aSign ? (sbits32) 0x80000000 : 0x7FFFFFFF; - } - if ( ( aSig<>( - shiftCount ); - if ( (bits64) ( aSig<<( shiftCount & 63 ) ) ) { - float_exception_flags |= float_flag_inexact; - } - } - if ( aSign ) z = - z; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-precision floating-point value -| `a' to the single-precision floating-point format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float64_to_float32( float64 a ) -{ - flag aSign; - int16 aExp; - bits64 aSig; - bits32 zSig; - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); - if ( aExp == 0x7FF ) { - if ( aSig ) return commonNaNToFloat32( float64ToCommonNaN( a ) ); - return packFloat32( aSign, 0xFF, 0 ); - } - shift64RightJamming( aSig, 22, &aSig ); - zSig = aSig; - if ( aExp || zSig ) { - zSig |= 0x40000000; - aExp -= 0x381; - } - return roundAndPackFloat32( aSign, aExp, zSig ); - -} - -#ifdef FLOATX80 - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-precision floating-point value -| `a' to the extended double-precision floating-point format. The conversion -| is performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 float64_to_floatx80( float64 a ) -{ - flag aSign; - int16 aExp; - bits64 aSig; - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); - if ( aExp == 0x7FF ) { - if ( aSig ) return commonNaNToFloatx80( float64ToCommonNaN( a ) ); - return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloatx80( aSign, 0, 0 ); - normalizeFloat64Subnormal( aSig, &aExp, &aSig ); - } - return - packFloatx80( - aSign, aExp + 0x3C00, ( aSig | LIT64( 0x0010000000000000 ) )<<11 ); - -} - -#endif - -#ifdef FLOAT128 - -/*---------------------------------------------------------------------------- -| Returns the result of converting the double-precision floating-point value -| `a' to the quadruple-precision floating-point format. The conversion is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float64_to_float128( float64 a ) -{ - flag aSign; - int16 aExp; - bits64 aSig, zSig0, zSig1; - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); - if ( aExp == 0x7FF ) { - if ( aSig ) return commonNaNToFloat128( float64ToCommonNaN( a ) ); - return packFloat128( aSign, 0x7FFF, 0, 0 ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloat128( aSign, 0, 0, 0 ); - normalizeFloat64Subnormal( aSig, &aExp, &aSig ); - --aExp; - } - shift128Right( aSig, 0, 4, &zSig0, &zSig1 ); - return packFloat128( aSign, aExp + 0x3C00, zSig0, zSig1 ); - -} - -#endif - -/*---------------------------------------------------------------------------- -| Rounds the double-precision floating-point value `a' to an integer, and -| returns the result as a double-precision floating-point value. The -| operation is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_round_to_int( float64 a ) -{ - flag aSign; - int16 aExp; - bits64 lastBitMask, roundBitsMask; - int8 roundingMode; - float64 z; - - aExp = extractFloat64Exp( a ); - if ( 0x433 <= aExp ) { - if ( ( aExp == 0x7FF ) && extractFloat64Frac( a ) ) { - return propagateFloat64NaN( a, a ); - } - return a; - } - if ( aExp < 0x3FF ) { - if ( (bits64) ( a<<1 ) == 0 ) return a; - float_exception_flags |= float_flag_inexact; - aSign = extractFloat64Sign( a ); - switch ( float_rounding_mode ) { - case float_round_nearest_even: - if ( ( aExp == 0x3FE ) && extractFloat64Frac( a ) ) { - return packFloat64( aSign, 0x3FF, 0 ); - } - break; - case float_round_down: - return aSign ? LIT64( 0xBFF0000000000000 ) : 0; - case float_round_up: - return - aSign ? LIT64( 0x8000000000000000 ) : LIT64( 0x3FF0000000000000 ); - } - return packFloat64( aSign, 0, 0 ); - } - lastBitMask = 1; - lastBitMask <<= 0x433 - aExp; - roundBitsMask = lastBitMask - 1; - z = a; - roundingMode = float_rounding_mode; - if ( roundingMode == float_round_nearest_even ) { - z += lastBitMask>>1; - if ( ( z & roundBitsMask ) == 0 ) z &= ~ lastBitMask; - } - else if ( roundingMode != float_round_to_zero ) { - if ( extractFloat64Sign( z ) ^ ( roundingMode == float_round_up ) ) { - z += roundBitsMask; - } - } - z &= ~ roundBitsMask; - if ( z != a ) float_exception_flags |= float_flag_inexact; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the absolute values of the double-precision -| floating-point values `a' and `b'. If `zSign' is 1, the sum is negated -| before being returned. `zSign' is ignored if the result is a NaN. -| The addition is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static float64 addFloat64Sigs( float64 a, float64 b, flag zSign ) -{ - int16 aExp, bExp, zExp; - bits64 aSig, bSig, zSig; - int16 expDiff; - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - bSig = extractFloat64Frac( b ); - bExp = extractFloat64Exp( b ); - expDiff = aExp - bExp; - aSig <<= 9; - bSig <<= 9; - if ( 0 < expDiff ) { - if ( aExp == 0x7FF ) { - if ( aSig ) return propagateFloat64NaN( a, b ); - return a; - } - if ( bExp == 0 ) { - --expDiff; - } - else { - bSig |= LIT64( 0x2000000000000000 ); - } - shift64RightJamming( bSig, expDiff, &bSig ); - zExp = aExp; - } - else if ( expDiff < 0 ) { - if ( bExp == 0x7FF ) { - if ( bSig ) return propagateFloat64NaN( a, b ); - return packFloat64( zSign, 0x7FF, 0 ); - } - if ( aExp == 0 ) { - ++expDiff; - } - else { - aSig |= LIT64( 0x2000000000000000 ); - } - shift64RightJamming( aSig, - expDiff, &aSig ); - zExp = bExp; - } - else { - if ( aExp == 0x7FF ) { - if ( aSig | bSig ) return propagateFloat64NaN( a, b ); - return a; - } - if ( aExp == 0 ) return packFloat64( zSign, 0, ( aSig + bSig )>>9 ); - zSig = LIT64( 0x4000000000000000 ) + aSig + bSig; - zExp = aExp; - goto roundAndPack; - } - aSig |= LIT64( 0x2000000000000000 ); - zSig = ( aSig + bSig )<<1; - --zExp; - if ( (sbits64) zSig < 0 ) { - zSig = aSig + bSig; - ++zExp; - } - roundAndPack: - return roundAndPackFloat64( zSign, zExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the absolute values of the double- -| precision floating-point values `a' and `b'. If `zSign' is 1, the -| difference is negated before being returned. `zSign' is ignored if the -| result is a NaN. The subtraction is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static float64 subFloat64Sigs( float64 a, float64 b, flag zSign ) -{ - int16 aExp, bExp, zExp; - bits64 aSig, bSig, zSig; - int16 expDiff; - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - bSig = extractFloat64Frac( b ); - bExp = extractFloat64Exp( b ); - expDiff = aExp - bExp; - aSig <<= 10; - bSig <<= 10; - if ( 0 < expDiff ) goto aExpBigger; - if ( expDiff < 0 ) goto bExpBigger; - if ( aExp == 0x7FF ) { - if ( aSig | bSig ) return propagateFloat64NaN( a, b ); - float_raise( float_flag_invalid ); - return float64_default_nan; - } - if ( aExp == 0 ) { - aExp = 1; - bExp = 1; - } - if ( bSig < aSig ) goto aBigger; - if ( aSig < bSig ) goto bBigger; - return packFloat64( float_rounding_mode == float_round_down, 0, 0 ); - bExpBigger: - if ( bExp == 0x7FF ) { - if ( bSig ) return propagateFloat64NaN( a, b ); - return packFloat64( zSign ^ 1, 0x7FF, 0 ); - } - if ( aExp == 0 ) { - ++expDiff; - } - else { - aSig |= LIT64( 0x4000000000000000 ); - } - shift64RightJamming( aSig, - expDiff, &aSig ); - bSig |= LIT64( 0x4000000000000000 ); - bBigger: - zSig = bSig - aSig; - zExp = bExp; - zSign ^= 1; - goto normalizeRoundAndPack; - aExpBigger: - if ( aExp == 0x7FF ) { - if ( aSig ) return propagateFloat64NaN( a, b ); - return a; - } - if ( bExp == 0 ) { - --expDiff; - } - else { - bSig |= LIT64( 0x4000000000000000 ); - } - shift64RightJamming( bSig, expDiff, &bSig ); - aSig |= LIT64( 0x4000000000000000 ); - aBigger: - zSig = aSig - bSig; - zExp = aExp; - normalizeRoundAndPack: - --zExp; - return normalizeRoundAndPackFloat64( zSign, zExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the double-precision floating-point values `a' -| and `b'. The operation is performed according to the IEC/IEEE Standard for -| Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_add( float64 a, float64 b ) -{ - flag aSign, bSign; - - aSign = extractFloat64Sign( a ); - bSign = extractFloat64Sign( b ); - if ( aSign == bSign ) { - return addFloat64Sigs( a, b, aSign ); - } - else { - return subFloat64Sigs( a, b, aSign ); - } - -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the double-precision floating-point values -| `a' and `b'. The operation is performed according to the IEC/IEEE Standard -| for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_sub( float64 a, float64 b ) -{ - flag aSign, bSign; - - aSign = extractFloat64Sign( a ); - bSign = extractFloat64Sign( b ); - if ( aSign == bSign ) { - return subFloat64Sigs( a, b, aSign ); - } - else { - return addFloat64Sigs( a, b, aSign ); - } - -} - -/*---------------------------------------------------------------------------- -| Returns the result of multiplying the double-precision floating-point values -| `a' and `b'. The operation is performed according to the IEC/IEEE Standard -| for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_mul( float64 a, float64 b ) -{ - flag aSign, bSign, zSign; - int16 aExp, bExp, zExp; - bits64 aSig, bSig, zSig0, zSig1; - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); - bSig = extractFloat64Frac( b ); - bExp = extractFloat64Exp( b ); - bSign = extractFloat64Sign( b ); - zSign = aSign ^ bSign; - if ( aExp == 0x7FF ) { - if ( aSig || ( ( bExp == 0x7FF ) && bSig ) ) { - return propagateFloat64NaN( a, b ); - } - if ( ( bExp | bSig ) == 0 ) { - float_raise( float_flag_invalid ); - return float64_default_nan; - } - return packFloat64( zSign, 0x7FF, 0 ); - } - if ( bExp == 0x7FF ) { - if ( bSig ) return propagateFloat64NaN( a, b ); - if ( ( aExp | aSig ) == 0 ) { - float_raise( float_flag_invalid ); - return float64_default_nan; - } - return packFloat64( zSign, 0x7FF, 0 ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloat64( zSign, 0, 0 ); - normalizeFloat64Subnormal( aSig, &aExp, &aSig ); - } - if ( bExp == 0 ) { - if ( bSig == 0 ) return packFloat64( zSign, 0, 0 ); - normalizeFloat64Subnormal( bSig, &bExp, &bSig ); - } - zExp = aExp + bExp - 0x3FF; - aSig = ( aSig | LIT64( 0x0010000000000000 ) )<<10; - bSig = ( bSig | LIT64( 0x0010000000000000 ) )<<11; - mul64To128( aSig, bSig, &zSig0, &zSig1 ); - zSig0 |= ( zSig1 != 0 ); - if ( 0 <= (sbits64) ( zSig0<<1 ) ) { - zSig0 <<= 1; - --zExp; - } - return roundAndPackFloat64( zSign, zExp, zSig0 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of dividing the double-precision floating-point value `a' -| by the corresponding value `b'. The operation is performed according to -| the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_div( float64 a, float64 b ) -{ - flag aSign, bSign, zSign; - int16 aExp, bExp, zExp; - bits64 aSig, bSig, zSig; - bits64 rem0, rem1; - bits64 term0, term1; - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); - bSig = extractFloat64Frac( b ); - bExp = extractFloat64Exp( b ); - bSign = extractFloat64Sign( b ); - zSign = aSign ^ bSign; - if ( aExp == 0x7FF ) { - if ( aSig ) return propagateFloat64NaN( a, b ); - if ( bExp == 0x7FF ) { - if ( bSig ) return propagateFloat64NaN( a, b ); - float_raise( float_flag_invalid ); - return float64_default_nan; - } - return packFloat64( zSign, 0x7FF, 0 ); - } - if ( bExp == 0x7FF ) { - if ( bSig ) return propagateFloat64NaN( a, b ); - return packFloat64( zSign, 0, 0 ); - } - if ( bExp == 0 ) { - if ( bSig == 0 ) { - if ( ( aExp | aSig ) == 0 ) { - float_raise( float_flag_invalid ); - return float64_default_nan; - } - float_raise( float_flag_divbyzero ); - return packFloat64( zSign, 0x7FF, 0 ); - } - normalizeFloat64Subnormal( bSig, &bExp, &bSig ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloat64( zSign, 0, 0 ); - normalizeFloat64Subnormal( aSig, &aExp, &aSig ); - } - zExp = aExp - bExp + 0x3FD; - aSig = ( aSig | LIT64( 0x0010000000000000 ) )<<10; - bSig = ( bSig | LIT64( 0x0010000000000000 ) )<<11; - if ( bSig <= ( aSig + aSig ) ) { - aSig >>= 1; - ++zExp; - } - zSig = estimateDiv128To64( aSig, 0, bSig ); - if ( ( zSig & 0x1FF ) <= 2 ) { - mul64To128( bSig, zSig, &term0, &term1 ); - sub128( aSig, 0, term0, term1, &rem0, &rem1 ); - while ( (sbits64) rem0 < 0 ) { - --zSig; - add128( rem0, rem1, 0, bSig, &rem0, &rem1 ); - } - zSig |= ( rem1 != 0 ); - } - return roundAndPackFloat64( zSign, zExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the remainder of the double-precision floating-point value `a' -| with respect to the corresponding value `b'. The operation is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_rem( float64 a, float64 b ) -{ - flag aSign, zSign; - int16 aExp, bExp, expDiff; - bits64 aSig, bSig; - bits64 q, alternateASig; - sbits64 sigMean; - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); - bSig = extractFloat64Frac( b ); - bExp = extractFloat64Exp( b ); -// bSign = extractFloat64Sign( b ); - if ( aExp == 0x7FF ) { - if ( aSig || ( ( bExp == 0x7FF ) && bSig ) ) { - return propagateFloat64NaN( a, b ); - } - float_raise( float_flag_invalid ); - return float64_default_nan; - } - if ( bExp == 0x7FF ) { - if ( bSig ) return propagateFloat64NaN( a, b ); - return a; - } - if ( bExp == 0 ) { - if ( bSig == 0 ) { - float_raise( float_flag_invalid ); - return float64_default_nan; - } - normalizeFloat64Subnormal( bSig, &bExp, &bSig ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return a; - normalizeFloat64Subnormal( aSig, &aExp, &aSig ); - } - expDiff = aExp - bExp; - aSig = ( aSig | LIT64( 0x0010000000000000 ) )<<11; - bSig = ( bSig | LIT64( 0x0010000000000000 ) )<<11; - if ( expDiff < 0 ) { - if ( expDiff < -1 ) return a; - aSig >>= 1; - } - q = ( bSig <= aSig ); - if ( q ) aSig -= bSig; - expDiff -= 64; - while ( 0 < expDiff ) { - q = estimateDiv128To64( aSig, 0, bSig ); - q = ( 2 < q ) ? q - 2 : 0; - aSig = - ( ( bSig>>2 ) * q ); - expDiff -= 62; - } - expDiff += 64; - if ( 0 < expDiff ) { - q = estimateDiv128To64( aSig, 0, bSig ); - q = ( 2 < q ) ? q - 2 : 0; - q >>= 64 - expDiff; - bSig >>= 2; - aSig = ( ( aSig>>1 )<<( expDiff - 1 ) ) - bSig * q; - } - else { - aSig >>= 2; - bSig >>= 2; - } - do { - alternateASig = aSig; - ++q; - aSig -= bSig; - } while ( 0 <= (sbits64) aSig ); - sigMean = aSig + alternateASig; - if ( ( sigMean < 0 ) || ( ( sigMean == 0 ) && ( q & 1 ) ) ) { - aSig = alternateASig; - } - zSign = ( (sbits64) aSig < 0 ); - if ( zSign ) aSig = - aSig; - return normalizeRoundAndPackFloat64( aSign ^ zSign, bExp, aSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the square root of the double-precision floating-point value `a'. -| The operation is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float64_sqrt( float64 a ) -{ - flag aSign; - int16 aExp, zExp; - bits64 aSig, zSig, doubleZSig; - bits64 rem0, rem1, term0, term1; -// float64 z; - - aSig = extractFloat64Frac( a ); - aExp = extractFloat64Exp( a ); - aSign = extractFloat64Sign( a ); - if ( aExp == 0x7FF ) { - if ( aSig ) return propagateFloat64NaN( a, a ); - if ( ! aSign ) return a; - float_raise( float_flag_invalid ); - return float64_default_nan; - } - if ( aSign ) { - if ( ( aExp | aSig ) == 0 ) return a; - float_raise( float_flag_invalid ); - return float64_default_nan; - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return 0; - normalizeFloat64Subnormal( aSig, &aExp, &aSig ); - } - zExp = ( ( aExp - 0x3FF )>>1 ) + 0x3FE; - aSig |= LIT64( 0x0010000000000000 ); - zSig = estimateSqrt32( aExp, aSig>>21 ); - aSig <<= 9 - ( aExp & 1 ); - zSig = estimateDiv128To64( aSig, 0, zSig<<32 ) + ( zSig<<30 ); - if ( ( zSig & 0x1FF ) <= 5 ) { - doubleZSig = zSig<<1; - mul64To128( zSig, zSig, &term0, &term1 ); - sub128( aSig, 0, term0, term1, &rem0, &rem1 ); - while ( (sbits64) rem0 < 0 ) { - --zSig; - doubleZSig -= 2; - add128( rem0, rem1, zSig>>63, doubleZSig | 1, &rem0, &rem1 ); - } - zSig |= ( ( rem0 | rem1 ) != 0 ); - } - return roundAndPackFloat64( 0, zExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is equal to the -| corresponding value `b', and 0 otherwise. The comparison is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float64_eq( float64 a, float64 b ) -{ - if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) - || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) - ) { - if ( float64_is_signaling_nan( a ) || float64_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - return ( a == b ) || ( (bits64) ( ( a | b )<<1 ) == 0 ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is less than or -| equal to the corresponding value `b', and 0 otherwise. The comparison is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float64_le( float64 a, float64 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) - || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - aSign = extractFloat64Sign( a ); - bSign = extractFloat64Sign( b ); - if ( aSign != bSign ) return aSign || ( (bits64) ( ( a | b )<<1 ) == 0 ); - return ( a == b ) || ( aSign ^ ( a < b ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is less than -| the corresponding value `b', and 0 otherwise. The comparison is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float64_lt( float64 a, float64 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) - || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - aSign = extractFloat64Sign( a ); - bSign = extractFloat64Sign( b ); - if ( aSign != bSign ) return aSign && ( (bits64) ( ( a | b )<<1 ) != 0 ); - return ( a != b ) && ( aSign ^ ( a < b ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is equal to the -| corresponding value `b', and 0 otherwise. The invalid exception is raised -| if either operand is a NaN. Otherwise, the comparison is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float64_eq_signaling( float64 a, float64 b ) -{ - if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) - || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - return ( a == b ) || ( (bits64) ( ( a | b )<<1 ) == 0 ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is less than or -| equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not -| cause an exception. Otherwise, the comparison is performed according to the -| IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float64_le_quiet( float64 a, float64 b ) -{ - flag aSign, bSign; -// int16 aExp, bExp; - - if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) - || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) - ) { - if ( float64_is_signaling_nan( a ) || float64_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - aSign = extractFloat64Sign( a ); - bSign = extractFloat64Sign( b ); - if ( aSign != bSign ) return aSign || ( (bits64) ( ( a | b )<<1 ) == 0 ); - return ( a == b ) || ( aSign ^ ( a < b ) ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the double-precision floating-point value `a' is less than -| the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an -| exception. Otherwise, the comparison is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float64_lt_quiet( float64 a, float64 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) ) - || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) ) - ) { - if ( float64_is_signaling_nan( a ) || float64_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - aSign = extractFloat64Sign( a ); - bSign = extractFloat64Sign( b ); - if ( aSign != bSign ) return aSign && ( (bits64) ( ( a | b )<<1 ) != 0 ); - return ( a != b ) && ( aSign ^ ( a < b ) ); - -} - -#ifdef FLOATX80 - -/*---------------------------------------------------------------------------- -| Returns the result of converting the extended double-precision floating- -| point value `a' to the 32-bit two's complement integer format. The -| conversion is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic---which means in particular that the conversion -| is rounded according to the current rounding mode. If `a' is a NaN, the -| largest positive integer is returned. Otherwise, if the conversion -| overflows, the largest integer with the same sign as `a' is returned. -*----------------------------------------------------------------------------*/ - -int32 floatx80_to_int32( floatx80 a ) -{ - flag aSign; - int32 aExp, shiftCount; - bits64 aSig; - - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); - if ( ( aExp == 0x7FFF ) && (bits64) ( aSig<<1 ) ) aSign = 0; - shiftCount = 0x4037 - aExp; - if ( shiftCount <= 0 ) shiftCount = 1; - shift64RightJamming( aSig, shiftCount, &aSig ); - return roundAndPackInt32( aSign, aSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the extended double-precision floating- -| point value `a' to the 32-bit two's complement integer format. The -| conversion is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic, except that the conversion is always rounded -| toward zero. If `a' is a NaN, the largest positive integer is returned. -| Otherwise, if the conversion overflows, the largest integer with the same -| sign as `a' is returned. -*----------------------------------------------------------------------------*/ - -int32 floatx80_to_int32_round_to_zero( floatx80 a ) -{ - flag aSign; - int32 aExp, shiftCount; - bits64 aSig, savedASig; - int32 z; - - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); - if ( 0x401E < aExp ) { - if ( ( aExp == 0x7FFF ) && (bits64) ( aSig<<1 ) ) aSign = 0; - goto invalid; - } - else if ( aExp < 0x3FFF ) { - if ( aExp || aSig ) float_exception_flags |= float_flag_inexact; - return 0; - } - shiftCount = 0x403E - aExp; - savedASig = aSig; - aSig >>= shiftCount; - z = aSig; - if ( aSign ) z = - z; - if ( ( z < 0 ) ^ aSign ) { - invalid: - float_raise( float_flag_invalid ); - return aSign ? (sbits32) 0x80000000 : 0x7FFFFFFF; - } - if ( ( aSig<>( - shiftCount ); - if ( (bits64) ( aSig<<( shiftCount & 63 ) ) ) { - float_exception_flags |= float_flag_inexact; - } - if ( aSign ) z = - z; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the extended double-precision floating- -| point value `a' to the single-precision floating-point format. The -| conversion is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 floatx80_to_float32( floatx80 a ) -{ - flag aSign; - int32 aExp; - bits64 aSig; - - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); - if ( aExp == 0x7FFF ) { - if ( (bits64) ( aSig<<1 ) ) { - return commonNaNToFloat32( floatx80ToCommonNaN( a ) ); - } - return packFloat32( aSign, 0xFF, 0 ); - } - shift64RightJamming( aSig, 33, &aSig ); - if ( aExp || aSig ) aExp -= 0x3F81; - return roundAndPackFloat32( aSign, aExp, aSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the extended double-precision floating- -| point value `a' to the double-precision floating-point format. The -| conversion is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 floatx80_to_float64( floatx80 a ) -{ - flag aSign; - int32 aExp; - bits64 aSig, zSig; - - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); - if ( aExp == 0x7FFF ) { - if ( (bits64) ( aSig<<1 ) ) { - return commonNaNToFloat64( floatx80ToCommonNaN( a ) ); - } - return packFloat64( aSign, 0x7FF, 0 ); - } - shift64RightJamming( aSig, 1, &zSig ); - if ( aExp || aSig ) aExp -= 0x3C01; - return roundAndPackFloat64( aSign, aExp, zSig ); - -} - -#ifdef FLOAT128 - -/*---------------------------------------------------------------------------- -| Returns the result of converting the extended double-precision floating- -| point value `a' to the quadruple-precision floating-point format. The -| conversion is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 floatx80_to_float128( floatx80 a ) -{ - flag aSign; - int16 aExp; - bits64 aSig, zSig0, zSig1; - - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); - if ( ( aExp == 0x7FFF ) && (bits64) ( aSig<<1 ) ) { - return commonNaNToFloat128( floatx80ToCommonNaN( a ) ); - } - shift128Right( aSig<<1, 0, 16, &zSig0, &zSig1 ); - return packFloat128( aSign, aExp, zSig0, zSig1 ); - -} - -#endif - -/*---------------------------------------------------------------------------- -| Rounds the extended double-precision floating-point value `a' to an integer, -| and returns the result as an extended quadruple-precision floating-point -| value. The operation is performed according to the IEC/IEEE Standard for -| Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_round_to_int( floatx80 a ) -{ - flag aSign; - int32 aExp; - bits64 lastBitMask, roundBitsMask; - int8 roundingMode; - floatx80 z; - - aExp = extractFloatx80Exp( a ); - if ( 0x403E <= aExp ) { - if ( ( aExp == 0x7FFF ) && (bits64) ( extractFloatx80Frac( a )<<1 ) ) { - return propagateFloatx80NaN( a, a ); - } - return a; - } - if ( aExp < 0x3FFF ) { - if ( ( aExp == 0 ) - && ( (bits64) ( extractFloatx80Frac( a )<<1 ) == 0 ) ) { - return a; - } - float_exception_flags |= float_flag_inexact; - aSign = extractFloatx80Sign( a ); - switch ( float_rounding_mode ) { - case float_round_nearest_even: - if ( ( aExp == 0x3FFE ) && (bits64) ( extractFloatx80Frac( a )<<1 ) - ) { - return - packFloatx80( aSign, 0x3FFF, LIT64( 0x8000000000000000 ) ); - } - break; - case float_round_down: - return - aSign ? - packFloatx80( 1, 0x3FFF, LIT64( 0x8000000000000000 ) ) - : packFloatx80( 0, 0, 0 ); - case float_round_up: - return - aSign ? packFloatx80( 1, 0, 0 ) - : packFloatx80( 0, 0x3FFF, LIT64( 0x8000000000000000 ) ); - } - return packFloatx80( aSign, 0, 0 ); - } - lastBitMask = 1; - lastBitMask <<= 0x403E - aExp; - roundBitsMask = lastBitMask - 1; - z = a; - roundingMode = float_rounding_mode; - if ( roundingMode == float_round_nearest_even ) { - z.low += lastBitMask>>1; - if ( ( z.low & roundBitsMask ) == 0 ) z.low &= ~ lastBitMask; - } - else if ( roundingMode != float_round_to_zero ) { - if ( extractFloatx80Sign( z ) ^ ( roundingMode == float_round_up ) ) { - z.low += roundBitsMask; - } - } - z.low &= ~ roundBitsMask; - if ( z.low == 0 ) { - ++z.high; - z.low = LIT64( 0x8000000000000000 ); - } - if ( z.low != a.low ) float_exception_flags |= float_flag_inexact; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the absolute values of the extended double- -| precision floating-point values `a' and `b'. If `zSign' is 1, the sum is -| negated before being returned. `zSign' is ignored if the result is a NaN. -| The addition is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static floatx80 addFloatx80Sigs( floatx80 a, floatx80 b, flag zSign ) -{ - int32 aExp, bExp, zExp; - bits64 aSig, bSig, zSig0, zSig1; - int32 expDiff; - - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - bSig = extractFloatx80Frac( b ); - bExp = extractFloatx80Exp( b ); - expDiff = aExp - bExp; - if ( 0 < expDiff ) { - if ( aExp == 0x7FFF ) { - if ( (bits64) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b ); - return a; - } - if ( bExp == 0 ) --expDiff; - shift64ExtraRightJamming( bSig, 0, expDiff, &bSig, &zSig1 ); - zExp = aExp; - } - else if ( expDiff < 0 ) { - if ( bExp == 0x7FFF ) { - if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); - return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); - } - if ( aExp == 0 ) ++expDiff; - shift64ExtraRightJamming( aSig, 0, - expDiff, &aSig, &zSig1 ); - zExp = bExp; - } - else { - if ( aExp == 0x7FFF ) { - if ( (bits64) ( ( aSig | bSig )<<1 ) ) { - return propagateFloatx80NaN( a, b ); - } - return a; - } - zSig1 = 0; - zSig0 = aSig + bSig; - if ( aExp == 0 ) { - normalizeFloatx80Subnormal( zSig0, &zExp, &zSig0 ); - goto roundAndPack; - } - zExp = aExp; - goto shiftRight1; - } - zSig0 = aSig + bSig; - if ( (sbits64) zSig0 < 0 ) goto roundAndPack; - shiftRight1: - shift64ExtraRightJamming( zSig0, zSig1, 1, &zSig0, &zSig1 ); - zSig0 |= LIT64( 0x8000000000000000 ); - ++zExp; - roundAndPack: - return - roundAndPackFloatx80( - floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the absolute values of the extended -| double-precision floating-point values `a' and `b'. If `zSign' is 1, the -| difference is negated before being returned. `zSign' is ignored if the -| result is a NaN. The subtraction is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static floatx80 subFloatx80Sigs( floatx80 a, floatx80 b, flag zSign ) -{ - int32 aExp, bExp, zExp; - bits64 aSig, bSig, zSig0, zSig1; - int32 expDiff; - floatx80 z; - - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - bSig = extractFloatx80Frac( b ); - bExp = extractFloatx80Exp( b ); - expDiff = aExp - bExp; - if ( 0 < expDiff ) goto aExpBigger; - if ( expDiff < 0 ) goto bExpBigger; - if ( aExp == 0x7FFF ) { - if ( (bits64) ( ( aSig | bSig )<<1 ) ) { - return propagateFloatx80NaN( a, b ); - } - float_raise( float_flag_invalid ); - z.low = floatx80_default_nan_low; - z.high = floatx80_default_nan_high; - return z; - } - if ( aExp == 0 ) { - aExp = 1; - bExp = 1; - } - zSig1 = 0; - if ( bSig < aSig ) goto aBigger; - if ( aSig < bSig ) goto bBigger; - return packFloatx80( float_rounding_mode == float_round_down, 0, 0 ); - bExpBigger: - if ( bExp == 0x7FFF ) { - if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); - return packFloatx80( zSign ^ 1, 0x7FFF, LIT64( 0x8000000000000000 ) ); - } - if ( aExp == 0 ) ++expDiff; - shift128RightJamming( aSig, 0, - expDiff, &aSig, &zSig1 ); - bBigger: - sub128( bSig, 0, aSig, zSig1, &zSig0, &zSig1 ); - zExp = bExp; - zSign ^= 1; - goto normalizeRoundAndPack; - aExpBigger: - if ( aExp == 0x7FFF ) { - if ( (bits64) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b ); - return a; - } - if ( bExp == 0 ) --expDiff; - shift128RightJamming( bSig, 0, expDiff, &bSig, &zSig1 ); - aBigger: - sub128( aSig, 0, bSig, zSig1, &zSig0, &zSig1 ); - zExp = aExp; - normalizeRoundAndPack: - return - normalizeRoundAndPackFloatx80( - floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the extended double-precision floating-point -| values `a' and `b'. The operation is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_add( floatx80 a, floatx80 b ) -{ - flag aSign, bSign; - - aSign = extractFloatx80Sign( a ); - bSign = extractFloatx80Sign( b ); - if ( aSign == bSign ) { - return addFloatx80Sigs( a, b, aSign ); - } - else { - return subFloatx80Sigs( a, b, aSign ); - } - -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the extended double-precision floating- -| point values `a' and `b'. The operation is performed according to the -| IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_sub( floatx80 a, floatx80 b ) -{ - flag aSign, bSign; - - aSign = extractFloatx80Sign( a ); - bSign = extractFloatx80Sign( b ); - if ( aSign == bSign ) { - return subFloatx80Sigs( a, b, aSign ); - } - else { - return addFloatx80Sigs( a, b, aSign ); - } - -} - -/*---------------------------------------------------------------------------- -| Returns the result of multiplying the extended double-precision floating- -| point values `a' and `b'. The operation is performed according to the -| IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_mul( floatx80 a, floatx80 b ) -{ - flag aSign, bSign, zSign; - int32 aExp, bExp, zExp; - bits64 aSig, bSig, zSig0, zSig1; - floatx80 z; - - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); - bSig = extractFloatx80Frac( b ); - bExp = extractFloatx80Exp( b ); - bSign = extractFloatx80Sign( b ); - zSign = aSign ^ bSign; - if ( aExp == 0x7FFF ) { - if ( (bits64) ( aSig<<1 ) - || ( ( bExp == 0x7FFF ) && (bits64) ( bSig<<1 ) ) ) { - return propagateFloatx80NaN( a, b ); - } - if ( ( bExp | bSig ) == 0 ) goto invalid; - return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); - } - if ( bExp == 0x7FFF ) { - if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); - if ( ( aExp | aSig ) == 0 ) { - invalid: - float_raise( float_flag_invalid ); - z.low = floatx80_default_nan_low; - z.high = floatx80_default_nan_high; - return z; - } - return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloatx80( zSign, 0, 0 ); - normalizeFloatx80Subnormal( aSig, &aExp, &aSig ); - } - if ( bExp == 0 ) { - if ( bSig == 0 ) return packFloatx80( zSign, 0, 0 ); - normalizeFloatx80Subnormal( bSig, &bExp, &bSig ); - } - zExp = aExp + bExp - 0x3FFE; - mul64To128( aSig, bSig, &zSig0, &zSig1 ); - if ( 0 < (sbits64) zSig0 ) { - shortShift128Left( zSig0, zSig1, 1, &zSig0, &zSig1 ); - --zExp; - } - return - roundAndPackFloatx80( - floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of dividing the extended double-precision floating-point -| value `a' by the corresponding value `b'. The operation is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_div( floatx80 a, floatx80 b ) -{ - flag aSign, bSign, zSign; - int32 aExp, bExp, zExp; - bits64 aSig, bSig, zSig0, zSig1; - bits64 rem0, rem1, rem2, term0, term1, term2; - floatx80 z; - - aSig = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); - bSig = extractFloatx80Frac( b ); - bExp = extractFloatx80Exp( b ); - bSign = extractFloatx80Sign( b ); - zSign = aSign ^ bSign; - if ( aExp == 0x7FFF ) { - if ( (bits64) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b ); - if ( bExp == 0x7FFF ) { - if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); - goto invalid; - } - return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); - } - if ( bExp == 0x7FFF ) { - if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); - return packFloatx80( zSign, 0, 0 ); - } - if ( bExp == 0 ) { - if ( bSig == 0 ) { - if ( ( aExp | aSig ) == 0 ) { - invalid: - float_raise( float_flag_invalid ); - z.low = floatx80_default_nan_low; - z.high = floatx80_default_nan_high; - return z; - } - float_raise( float_flag_divbyzero ); - return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); - } - normalizeFloatx80Subnormal( bSig, &bExp, &bSig ); - } - if ( aExp == 0 ) { - if ( aSig == 0 ) return packFloatx80( zSign, 0, 0 ); - normalizeFloatx80Subnormal( aSig, &aExp, &aSig ); - } - zExp = aExp - bExp + 0x3FFE; - rem1 = 0; - if ( bSig <= aSig ) { - shift128Right( aSig, 0, 1, &aSig, &rem1 ); - ++zExp; - } - zSig0 = estimateDiv128To64( aSig, rem1, bSig ); - mul64To128( bSig, zSig0, &term0, &term1 ); - sub128( aSig, rem1, term0, term1, &rem0, &rem1 ); - while ( (sbits64) rem0 < 0 ) { - --zSig0; - add128( rem0, rem1, 0, bSig, &rem0, &rem1 ); - } - zSig1 = estimateDiv128To64( rem1, 0, bSig ); - if ( (bits64) ( zSig1<<1 ) <= 8 ) { - mul64To128( bSig, zSig1, &term1, &term2 ); - sub128( rem1, 0, term1, term2, &rem1, &rem2 ); - while ( (sbits64) rem1 < 0 ) { - --zSig1; - add128( rem1, rem2, 0, bSig, &rem1, &rem2 ); - } - zSig1 |= ( ( rem1 | rem2 ) != 0 ); - } - return - roundAndPackFloatx80( - floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the remainder of the extended double-precision floating-point value -| `a' with respect to the corresponding value `b'. The operation is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_rem( floatx80 a, floatx80 b ) -{ - flag aSign, zSign; - int32 aExp, bExp, expDiff; - bits64 aSig0, aSig1, bSig; - bits64 q, term0, term1, alternateASig0, alternateASig1; - floatx80 z; - - aSig0 = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); - bSig = extractFloatx80Frac( b ); - bExp = extractFloatx80Exp( b ); -// bSign = extractFloatx80Sign( b ); - if ( aExp == 0x7FFF ) { - if ( (bits64) ( aSig0<<1 ) - || ( ( bExp == 0x7FFF ) && (bits64) ( bSig<<1 ) ) ) { - return propagateFloatx80NaN( a, b ); - } - goto invalid; - } - if ( bExp == 0x7FFF ) { - if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b ); - return a; - } - if ( bExp == 0 ) { - if ( bSig == 0 ) { - invalid: - float_raise( float_flag_invalid ); - z.low = floatx80_default_nan_low; - z.high = floatx80_default_nan_high; - return z; - } - normalizeFloatx80Subnormal( bSig, &bExp, &bSig ); - } - if ( aExp == 0 ) { - if ( (bits64) ( aSig0<<1 ) == 0 ) return a; - normalizeFloatx80Subnormal( aSig0, &aExp, &aSig0 ); - } - bSig |= LIT64( 0x8000000000000000 ); - zSign = aSign; - expDiff = aExp - bExp; - aSig1 = 0; - if ( expDiff < 0 ) { - if ( expDiff < -1 ) return a; - shift128Right( aSig0, 0, 1, &aSig0, &aSig1 ); - expDiff = 0; - } - q = ( bSig <= aSig0 ); - if ( q ) aSig0 -= bSig; - expDiff -= 64; - while ( 0 < expDiff ) { - q = estimateDiv128To64( aSig0, aSig1, bSig ); - q = ( 2 < q ) ? q - 2 : 0; - mul64To128( bSig, q, &term0, &term1 ); - sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 ); - shortShift128Left( aSig0, aSig1, 62, &aSig0, &aSig1 ); - expDiff -= 62; - } - expDiff += 64; - if ( 0 < expDiff ) { - q = estimateDiv128To64( aSig0, aSig1, bSig ); - q = ( 2 < q ) ? q - 2 : 0; - q >>= 64 - expDiff; - mul64To128( bSig, q<<( 64 - expDiff ), &term0, &term1 ); - sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 ); - shortShift128Left( 0, bSig, 64 - expDiff, &term0, &term1 ); - while ( le128( term0, term1, aSig0, aSig1 ) ) { - ++q; - sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 ); - } - } - else { - term1 = 0; - term0 = bSig; - } - sub128( term0, term1, aSig0, aSig1, &alternateASig0, &alternateASig1 ); - if ( lt128( alternateASig0, alternateASig1, aSig0, aSig1 ) - || ( eq128( alternateASig0, alternateASig1, aSig0, aSig1 ) - && ( q & 1 ) ) - ) { - aSig0 = alternateASig0; - aSig1 = alternateASig1; - zSign = ! zSign; - } - return - normalizeRoundAndPackFloatx80( - 80, zSign, bExp + expDiff, aSig0, aSig1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the square root of the extended double-precision floating-point -| value `a'. The operation is performed according to the IEC/IEEE Standard -| for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 floatx80_sqrt( floatx80 a ) -{ - flag aSign; - int32 aExp, zExp; - bits64 aSig0, aSig1, zSig0, zSig1, doubleZSig0; - bits64 rem0, rem1, rem2, rem3, term0, term1, term2, term3; - floatx80 z; - - aSig0 = extractFloatx80Frac( a ); - aExp = extractFloatx80Exp( a ); - aSign = extractFloatx80Sign( a ); - if ( aExp == 0x7FFF ) { - if ( (bits64) ( aSig0<<1 ) ) return propagateFloatx80NaN( a, a ); - if ( ! aSign ) return a; - goto invalid; - } - if ( aSign ) { - if ( ( aExp | aSig0 ) == 0 ) return a; - invalid: - float_raise( float_flag_invalid ); - z.low = floatx80_default_nan_low; - z.high = floatx80_default_nan_high; - return z; - } - if ( aExp == 0 ) { - if ( aSig0 == 0 ) return packFloatx80( 0, 0, 0 ); - normalizeFloatx80Subnormal( aSig0, &aExp, &aSig0 ); - } - zExp = ( ( aExp - 0x3FFF )>>1 ) + 0x3FFF; - zSig0 = estimateSqrt32( aExp, aSig0>>32 ); - shift128Right( aSig0, 0, 2 + ( aExp & 1 ), &aSig0, &aSig1 ); - zSig0 = estimateDiv128To64( aSig0, aSig1, zSig0<<32 ) + ( zSig0<<30 ); - doubleZSig0 = zSig0<<1; - mul64To128( zSig0, zSig0, &term0, &term1 ); - sub128( aSig0, aSig1, term0, term1, &rem0, &rem1 ); - while ( (sbits64) rem0 < 0 ) { - --zSig0; - doubleZSig0 -= 2; - add128( rem0, rem1, zSig0>>63, doubleZSig0 | 1, &rem0, &rem1 ); - } - zSig1 = estimateDiv128To64( rem1, 0, doubleZSig0 ); - if ( ( zSig1 & LIT64( 0x3FFFFFFFFFFFFFFF ) ) <= 5 ) { - if ( zSig1 == 0 ) zSig1 = 1; - mul64To128( doubleZSig0, zSig1, &term1, &term2 ); - sub128( rem1, 0, term1, term2, &rem1, &rem2 ); - mul64To128( zSig1, zSig1, &term2, &term3 ); - sub192( rem1, rem2, 0, 0, term2, term3, &rem1, &rem2, &rem3 ); - while ( (sbits64) rem1 < 0 ) { - --zSig1; - shortShift128Left( 0, zSig1, 1, &term2, &term3 ); - term3 |= 1; - term2 |= doubleZSig0; - add192( rem1, rem2, rem3, 0, term2, term3, &rem1, &rem2, &rem3 ); - } - zSig1 |= ( ( rem1 | rem2 | rem3 ) != 0 ); - } - shortShift128Left( 0, zSig1, 1, &zSig0, &zSig1 ); - zSig0 |= doubleZSig0; - return - roundAndPackFloatx80( - floatx80_rounding_precision, 0, zExp, zSig0, zSig1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is -| equal to the corresponding value `b', and 0 otherwise. The comparison is -| performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -flag floatx80_eq( floatx80 a, floatx80 b ) -{ - if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( a )<<1 ) ) - || ( ( extractFloatx80Exp( b ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( b )<<1 ) ) - ) { - if ( floatx80_is_signaling_nan( a ) - || floatx80_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - return - ( a.low == b.low ) - && ( ( a.high == b.high ) - || ( ( a.low == 0 ) - && ( (bits16) ( ( a.high | b.high )<<1 ) == 0 ) ) - ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is -| less than or equal to the corresponding value `b', and 0 otherwise. The -| comparison is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag floatx80_le( floatx80 a, floatx80 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( a )<<1 ) ) - || ( ( extractFloatx80Exp( b ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( b )<<1 ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - aSign = extractFloatx80Sign( a ); - bSign = extractFloatx80Sign( b ); - if ( aSign != bSign ) { - return - aSign - || ( ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) - == 0 ); - } - return - aSign ? le128( b.high, b.low, a.high, a.low ) - : le128( a.high, a.low, b.high, b.low ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is -| less than the corresponding value `b', and 0 otherwise. The comparison -| is performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -flag floatx80_lt( floatx80 a, floatx80 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( a )<<1 ) ) - || ( ( extractFloatx80Exp( b ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( b )<<1 ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - aSign = extractFloatx80Sign( a ); - bSign = extractFloatx80Sign( b ); - if ( aSign != bSign ) { - return - aSign - && ( ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) - != 0 ); - } - return - aSign ? lt128( b.high, b.low, a.high, a.low ) - : lt128( a.high, a.low, b.high, b.low ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is equal -| to the corresponding value `b', and 0 otherwise. The invalid exception is -| raised if either operand is a NaN. Otherwise, the comparison is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag floatx80_eq_signaling( floatx80 a, floatx80 b ) -{ - if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( a )<<1 ) ) - || ( ( extractFloatx80Exp( b ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( b )<<1 ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - return - ( a.low == b.low ) - && ( ( a.high == b.high ) - || ( ( a.low == 0 ) - && ( (bits16) ( ( a.high | b.high )<<1 ) == 0 ) ) - ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is less -| than or equal to the corresponding value `b', and 0 otherwise. Quiet NaNs -| do not cause an exception. Otherwise, the comparison is performed according -| to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag floatx80_le_quiet( floatx80 a, floatx80 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( a )<<1 ) ) - || ( ( extractFloatx80Exp( b ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( b )<<1 ) ) - ) { - if ( floatx80_is_signaling_nan( a ) - || floatx80_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - aSign = extractFloatx80Sign( a ); - bSign = extractFloatx80Sign( b ); - if ( aSign != bSign ) { - return - aSign - || ( ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) - == 0 ); - } - return - aSign ? le128( b.high, b.low, a.high, a.low ) - : le128( a.high, a.low, b.high, b.low ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the extended double-precision floating-point value `a' is less -| than the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause -| an exception. Otherwise, the comparison is performed according to the -| IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag floatx80_lt_quiet( floatx80 a, floatx80 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloatx80Exp( a ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( a )<<1 ) ) - || ( ( extractFloatx80Exp( b ) == 0x7FFF ) - && (bits64) ( extractFloatx80Frac( b )<<1 ) ) - ) { - if ( floatx80_is_signaling_nan( a ) - || floatx80_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - aSign = extractFloatx80Sign( a ); - bSign = extractFloatx80Sign( b ); - if ( aSign != bSign ) { - return - aSign - && ( ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) - != 0 ); - } - return - aSign ? lt128( b.high, b.low, a.high, a.low ) - : lt128( a.high, a.low, b.high, b.low ); - -} - -#endif - -#ifdef FLOAT128 - -/*---------------------------------------------------------------------------- -| Returns the result of converting the quadruple-precision floating-point -| value `a' to the 32-bit two's complement integer format. The conversion -| is performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic---which means in particular that the conversion is rounded -| according to the current rounding mode. If `a' is a NaN, the largest -| positive integer is returned. Otherwise, if the conversion overflows, the -| largest integer with the same sign as `a' is returned. -*----------------------------------------------------------------------------*/ - -int32 float128_to_int32( float128 a ) -{ - flag aSign; - int32 aExp, shiftCount; - bits64 aSig0, aSig1; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - if ( ( aExp == 0x7FFF ) && ( aSig0 | aSig1 ) ) aSign = 0; - if ( aExp ) aSig0 |= LIT64( 0x0001000000000000 ); - aSig0 |= ( aSig1 != 0 ); - shiftCount = 0x4028 - aExp; - if ( 0 < shiftCount ) shift64RightJamming( aSig0, shiftCount, &aSig0 ); - return roundAndPackInt32( aSign, aSig0 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the quadruple-precision floating-point -| value `a' to the 32-bit two's complement integer format. The conversion -| is performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic, except that the conversion is always rounded toward zero. If -| `a' is a NaN, the largest positive integer is returned. Otherwise, if the -| conversion overflows, the largest integer with the same sign as `a' is -| returned. -*----------------------------------------------------------------------------*/ - -int32 float128_to_int32_round_to_zero( float128 a ) -{ - flag aSign; - int32 aExp, shiftCount; - bits64 aSig0, aSig1, savedASig; - int32 z; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - aSig0 |= ( aSig1 != 0 ); - if ( 0x401E < aExp ) { - if ( ( aExp == 0x7FFF ) && aSig0 ) aSign = 0; - goto invalid; - } - else if ( aExp < 0x3FFF ) { - if ( aExp || aSig0 ) float_exception_flags |= float_flag_inexact; - return 0; - } - aSig0 |= LIT64( 0x0001000000000000 ); - shiftCount = 0x402F - aExp; - savedASig = aSig0; - aSig0 >>= shiftCount; - z = aSig0; - if ( aSign ) z = - z; - if ( ( z < 0 ) ^ aSign ) { - invalid: - float_raise( float_flag_invalid ); - return aSign ? (sbits32) 0x80000000 : 0x7FFFFFFF; - } - if ( ( aSig0<>( ( - shiftCount ) & 63 ) ); - if ( (bits64) ( aSig1<>( - shiftCount ); - if ( aSig1 - || ( shiftCount && (bits64) ( aSig0<<( shiftCount & 63 ) ) ) ) { - float_exception_flags |= float_flag_inexact; - } - } - if ( aSign ) z = - z; - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the quadruple-precision floating-point -| value `a' to the single-precision floating-point format. The conversion -| is performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -float32 float128_to_float32( float128 a ) -{ - flag aSign; - int32 aExp; - bits64 aSig0, aSig1; - bits32 zSig; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 ) { - return commonNaNToFloat32( float128ToCommonNaN( a ) ); - } - return packFloat32( aSign, 0xFF, 0 ); - } - aSig0 |= ( aSig1 != 0 ); - shift64RightJamming( aSig0, 18, &aSig0 ); - zSig = aSig0; - if ( aExp || zSig ) { - zSig |= 0x40000000; - aExp -= 0x3F81; - } - return roundAndPackFloat32( aSign, aExp, zSig ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of converting the quadruple-precision floating-point -| value `a' to the double-precision floating-point format. The conversion -| is performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -float64 float128_to_float64( float128 a ) -{ - flag aSign; - int32 aExp; - bits64 aSig0, aSig1; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 ) { - return commonNaNToFloat64( float128ToCommonNaN( a ) ); - } - return packFloat64( aSign, 0x7FF, 0 ); - } - shortShift128Left( aSig0, aSig1, 14, &aSig0, &aSig1 ); - aSig0 |= ( aSig1 != 0 ); - if ( aExp || aSig0 ) { - aSig0 |= LIT64( 0x4000000000000000 ); - aExp -= 0x3C01; - } - return roundAndPackFloat64( aSign, aExp, aSig0 ); - -} - -#ifdef FLOATX80 - -/*---------------------------------------------------------------------------- -| Returns the result of converting the quadruple-precision floating-point -| value `a' to the extended double-precision floating-point format. The -| conversion is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -floatx80 float128_to_floatx80( float128 a ) -{ - flag aSign; - int32 aExp; - bits64 aSig0, aSig1; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 ) { - return commonNaNToFloatx80( float128ToCommonNaN( a ) ); - } - return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) ); - } - if ( aExp == 0 ) { - if ( ( aSig0 | aSig1 ) == 0 ) return packFloatx80( aSign, 0, 0 ); - normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 ); - } - else { - aSig0 |= LIT64( 0x0001000000000000 ); - } - shortShift128Left( aSig0, aSig1, 15, &aSig0, &aSig1 ); - return roundAndPackFloatx80( 80, aSign, aExp, aSig0, aSig1 ); - -} - -#endif - -/*---------------------------------------------------------------------------- -| Rounds the quadruple-precision floating-point value `a' to an integer, and -| returns the result as a quadruple-precision floating-point value. The -| operation is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float128_round_to_int( float128 a ) -{ - flag aSign; - int32 aExp; - bits64 lastBitMask, roundBitsMask; - int8 roundingMode; - float128 z; - - aExp = extractFloat128Exp( a ); - if ( 0x402F <= aExp ) { - if ( 0x406F <= aExp ) { - if ( ( aExp == 0x7FFF ) - && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) - ) { - return propagateFloat128NaN( a, a ); - } - return a; - } - lastBitMask = 1; - lastBitMask = ( lastBitMask<<( 0x406E - aExp ) )<<1; - roundBitsMask = lastBitMask - 1; - z = a; - roundingMode = float_rounding_mode; - if ( roundingMode == float_round_nearest_even ) { - if ( lastBitMask ) { - add128( z.high, z.low, 0, lastBitMask>>1, &z.high, &z.low ); - if ( ( z.low & roundBitsMask ) == 0 ) z.low &= ~ lastBitMask; - } - else { - if ( (sbits64) z.low < 0 ) { - ++z.high; - if ( (bits64) ( z.low<<1 ) == 0 ) z.high &= ~1; - } - } - } - else if ( roundingMode != float_round_to_zero ) { - if ( extractFloat128Sign( z ) - ^ ( roundingMode == float_round_up ) ) { - add128( z.high, z.low, 0, roundBitsMask, &z.high, &z.low ); - } - } - z.low &= ~ roundBitsMask; - } - else { - if ( aExp < 0x3FFF ) { - if ( ( ( (bits64) ( a.high<<1 ) ) | a.low ) == 0 ) return a; - float_exception_flags |= float_flag_inexact; - aSign = extractFloat128Sign( a ); - switch ( float_rounding_mode ) { - case float_round_nearest_even: - if ( ( aExp == 0x3FFE ) - && ( extractFloat128Frac0( a ) - | extractFloat128Frac1( a ) ) - ) { - return packFloat128( aSign, 0x3FFF, 0, 0 ); - } - break; - case float_round_down: - return - aSign ? packFloat128( 1, 0x3FFF, 0, 0 ) - : packFloat128( 0, 0, 0, 0 ); - case float_round_up: - return - aSign ? packFloat128( 1, 0, 0, 0 ) - : packFloat128( 0, 0x3FFF, 0, 0 ); - } - return packFloat128( aSign, 0, 0, 0 ); - } - lastBitMask = 1; - lastBitMask <<= 0x402F - aExp; - roundBitsMask = lastBitMask - 1; - z.low = 0; - z.high = a.high; - roundingMode = float_rounding_mode; - if ( roundingMode == float_round_nearest_even ) { - z.high += lastBitMask>>1; - if ( ( ( z.high & roundBitsMask ) | a.low ) == 0 ) { - z.high &= ~ lastBitMask; - } - } - else if ( roundingMode != float_round_to_zero ) { - if ( extractFloat128Sign( z ) - ^ ( roundingMode == float_round_up ) ) { - z.high |= ( a.low != 0 ); - z.high += roundBitsMask; - } - } - z.high &= ~ roundBitsMask; - } - if ( ( z.low != a.low ) || ( z.high != a.high ) ) { - float_exception_flags |= float_flag_inexact; - } - return z; - -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the absolute values of the quadruple-precision -| floating-point values `a' and `b'. If `zSign' is 1, the sum is negated -| before being returned. `zSign' is ignored if the result is a NaN. -| The addition is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static float128 addFloat128Sigs( float128 a, float128 b, flag zSign ) -{ - int32 aExp, bExp, zExp; - bits64 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2; - int32 expDiff; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - bSig1 = extractFloat128Frac1( b ); - bSig0 = extractFloat128Frac0( b ); - bExp = extractFloat128Exp( b ); - expDiff = aExp - bExp; - if ( 0 < expDiff ) { - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, b ); - return a; - } - if ( bExp == 0 ) { - --expDiff; - } - else { - bSig0 |= LIT64( 0x0001000000000000 ); - } - shift128ExtraRightJamming( - bSig0, bSig1, 0, expDiff, &bSig0, &bSig1, &zSig2 ); - zExp = aExp; - } - else if ( expDiff < 0 ) { - if ( bExp == 0x7FFF ) { - if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b ); - return packFloat128( zSign, 0x7FFF, 0, 0 ); - } - if ( aExp == 0 ) { - ++expDiff; - } - else { - aSig0 |= LIT64( 0x0001000000000000 ); - } - shift128ExtraRightJamming( - aSig0, aSig1, 0, - expDiff, &aSig0, &aSig1, &zSig2 ); - zExp = bExp; - } - else { - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 | bSig0 | bSig1 ) { - return propagateFloat128NaN( a, b ); - } - return a; - } - add128( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 ); - if ( aExp == 0 ) return packFloat128( zSign, 0, zSig0, zSig1 ); - zSig2 = 0; - zSig0 |= LIT64( 0x0002000000000000 ); - zExp = aExp; - goto shiftRight1; - } - aSig0 |= LIT64( 0x0001000000000000 ); - add128( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 ); - --zExp; - if ( zSig0 < LIT64( 0x0002000000000000 ) ) goto roundAndPack; - ++zExp; - shiftRight1: - shift128ExtraRightJamming( - zSig0, zSig1, zSig2, 1, &zSig0, &zSig1, &zSig2 ); - roundAndPack: - return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the absolute values of the quadruple- -| precision floating-point values `a' and `b'. If `zSign' is 1, the -| difference is negated before being returned. `zSign' is ignored if the -| result is a NaN. The subtraction is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static float128 subFloat128Sigs( float128 a, float128 b, flag zSign ) -{ - int32 aExp, bExp, zExp; - bits64 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1; - int32 expDiff; - float128 z; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - bSig1 = extractFloat128Frac1( b ); - bSig0 = extractFloat128Frac0( b ); - bExp = extractFloat128Exp( b ); - expDiff = aExp - bExp; - shortShift128Left( aSig0, aSig1, 14, &aSig0, &aSig1 ); - shortShift128Left( bSig0, bSig1, 14, &bSig0, &bSig1 ); - if ( 0 < expDiff ) goto aExpBigger; - if ( expDiff < 0 ) goto bExpBigger; - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 | bSig0 | bSig1 ) { - return propagateFloat128NaN( a, b ); - } - float_raise( float_flag_invalid ); - z.low = float128_default_nan_low; - z.high = float128_default_nan_high; - return z; - } - if ( aExp == 0 ) { - aExp = 1; - bExp = 1; - } - if ( bSig0 < aSig0 ) goto aBigger; - if ( aSig0 < bSig0 ) goto bBigger; - if ( bSig1 < aSig1 ) goto aBigger; - if ( aSig1 < bSig1 ) goto bBigger; - return packFloat128( float_rounding_mode == float_round_down, 0, 0, 0 ); - bExpBigger: - if ( bExp == 0x7FFF ) { - if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b ); - return packFloat128( zSign ^ 1, 0x7FFF, 0, 0 ); - } - if ( aExp == 0 ) { - ++expDiff; - } - else { - aSig0 |= LIT64( 0x4000000000000000 ); - } - shift128RightJamming( aSig0, aSig1, - expDiff, &aSig0, &aSig1 ); - bSig0 |= LIT64( 0x4000000000000000 ); - bBigger: - sub128( bSig0, bSig1, aSig0, aSig1, &zSig0, &zSig1 ); - zExp = bExp; - zSign ^= 1; - goto normalizeRoundAndPack; - aExpBigger: - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, b ); - return a; - } - if ( bExp == 0 ) { - --expDiff; - } - else { - bSig0 |= LIT64( 0x4000000000000000 ); - } - shift128RightJamming( bSig0, bSig1, expDiff, &bSig0, &bSig1 ); - aSig0 |= LIT64( 0x4000000000000000 ); - aBigger: - sub128( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 ); - zExp = aExp; - normalizeRoundAndPack: - --zExp; - return normalizeRoundAndPackFloat128( zSign, zExp - 14, zSig0, zSig1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of adding the quadruple-precision floating-point values -| `a' and `b'. The operation is performed according to the IEC/IEEE Standard -| for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float128_add( float128 a, float128 b ) -{ - flag aSign, bSign; - - aSign = extractFloat128Sign( a ); - bSign = extractFloat128Sign( b ); - if ( aSign == bSign ) { - return addFloat128Sigs( a, b, aSign ); - } - else { - return subFloat128Sigs( a, b, aSign ); - } - -} - -/*---------------------------------------------------------------------------- -| Returns the result of subtracting the quadruple-precision floating-point -| values `a' and `b'. The operation is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float128_sub( float128 a, float128 b ) -{ - flag aSign, bSign; - - aSign = extractFloat128Sign( a ); - bSign = extractFloat128Sign( b ); - if ( aSign == bSign ) { - return subFloat128Sigs( a, b, aSign ); - } - else { - return addFloat128Sigs( a, b, aSign ); - } - -} - -/*---------------------------------------------------------------------------- -| Returns the result of multiplying the quadruple-precision floating-point -| values `a' and `b'. The operation is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float128_mul( float128 a, float128 b ) -{ - flag aSign, bSign, zSign; - int32 aExp, bExp, zExp; - bits64 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2, zSig3; - float128 z; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - bSig1 = extractFloat128Frac1( b ); - bSig0 = extractFloat128Frac0( b ); - bExp = extractFloat128Exp( b ); - bSign = extractFloat128Sign( b ); - zSign = aSign ^ bSign; - if ( aExp == 0x7FFF ) { - if ( ( aSig0 | aSig1 ) - || ( ( bExp == 0x7FFF ) && ( bSig0 | bSig1 ) ) ) { - return propagateFloat128NaN( a, b ); - } - if ( ( bExp | bSig0 | bSig1 ) == 0 ) goto invalid; - return packFloat128( zSign, 0x7FFF, 0, 0 ); - } - if ( bExp == 0x7FFF ) { - if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b ); - if ( ( aExp | aSig0 | aSig1 ) == 0 ) { - invalid: - float_raise( float_flag_invalid ); - z.low = float128_default_nan_low; - z.high = float128_default_nan_high; - return z; - } - return packFloat128( zSign, 0x7FFF, 0, 0 ); - } - if ( aExp == 0 ) { - if ( ( aSig0 | aSig1 ) == 0 ) return packFloat128( zSign, 0, 0, 0 ); - normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 ); - } - if ( bExp == 0 ) { - if ( ( bSig0 | bSig1 ) == 0 ) return packFloat128( zSign, 0, 0, 0 ); - normalizeFloat128Subnormal( bSig0, bSig1, &bExp, &bSig0, &bSig1 ); - } - zExp = aExp + bExp - 0x4000; - aSig0 |= LIT64( 0x0001000000000000 ); - shortShift128Left( bSig0, bSig1, 16, &bSig0, &bSig1 ); - mul128To256( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1, &zSig2, &zSig3 ); - add128( zSig0, zSig1, aSig0, aSig1, &zSig0, &zSig1 ); - zSig2 |= ( zSig3 != 0 ); - if ( LIT64( 0x0002000000000000 ) <= zSig0 ) { - shift128ExtraRightJamming( - zSig0, zSig1, zSig2, 1, &zSig0, &zSig1, &zSig2 ); - ++zExp; - } - return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the result of dividing the quadruple-precision floating-point value -| `a' by the corresponding value `b'. The operation is performed according to -| the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float128_div( float128 a, float128 b ) -{ - flag aSign, bSign, zSign; - int32 aExp, bExp, zExp; - bits64 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2; - bits64 rem0, rem1, rem2, rem3, term0, term1, term2, term3; - float128 z; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - bSig1 = extractFloat128Frac1( b ); - bSig0 = extractFloat128Frac0( b ); - bExp = extractFloat128Exp( b ); - bSign = extractFloat128Sign( b ); - zSign = aSign ^ bSign; - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, b ); - if ( bExp == 0x7FFF ) { - if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b ); - goto invalid; - } - return packFloat128( zSign, 0x7FFF, 0, 0 ); - } - if ( bExp == 0x7FFF ) { - if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b ); - return packFloat128( zSign, 0, 0, 0 ); - } - if ( bExp == 0 ) { - if ( ( bSig0 | bSig1 ) == 0 ) { - if ( ( aExp | aSig0 | aSig1 ) == 0 ) { - invalid: - float_raise( float_flag_invalid ); - z.low = float128_default_nan_low; - z.high = float128_default_nan_high; - return z; - } - float_raise( float_flag_divbyzero ); - return packFloat128( zSign, 0x7FFF, 0, 0 ); - } - normalizeFloat128Subnormal( bSig0, bSig1, &bExp, &bSig0, &bSig1 ); - } - if ( aExp == 0 ) { - if ( ( aSig0 | aSig1 ) == 0 ) return packFloat128( zSign, 0, 0, 0 ); - normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 ); - } - zExp = aExp - bExp + 0x3FFD; - shortShift128Left( - aSig0 | LIT64( 0x0001000000000000 ), aSig1, 15, &aSig0, &aSig1 ); - shortShift128Left( - bSig0 | LIT64( 0x0001000000000000 ), bSig1, 15, &bSig0, &bSig1 ); - if ( le128( bSig0, bSig1, aSig0, aSig1 ) ) { - shift128Right( aSig0, aSig1, 1, &aSig0, &aSig1 ); - ++zExp; - } - zSig0 = estimateDiv128To64( aSig0, aSig1, bSig0 ); - mul128By64To192( bSig0, bSig1, zSig0, &term0, &term1, &term2 ); - sub192( aSig0, aSig1, 0, term0, term1, term2, &rem0, &rem1, &rem2 ); - while ( (sbits64) rem0 < 0 ) { - --zSig0; - add192( rem0, rem1, rem2, 0, bSig0, bSig1, &rem0, &rem1, &rem2 ); - } - zSig1 = estimateDiv128To64( rem1, rem2, bSig0 ); - if ( ( zSig1 & 0x3FFF ) <= 4 ) { - mul128By64To192( bSig0, bSig1, zSig1, &term1, &term2, &term3 ); - sub192( rem1, rem2, 0, term1, term2, term3, &rem1, &rem2, &rem3 ); - while ( (sbits64) rem1 < 0 ) { - --zSig1; - add192( rem1, rem2, rem3, 0, bSig0, bSig1, &rem1, &rem2, &rem3 ); - } - zSig1 |= ( ( rem1 | rem2 | rem3 ) != 0 ); - } - shift128ExtraRightJamming( zSig0, zSig1, 0, 15, &zSig0, &zSig1, &zSig2 ); - return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the remainder of the quadruple-precision floating-point value `a' -| with respect to the corresponding value `b'. The operation is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float128_rem( float128 a, float128 b ) -{ - flag aSign, zSign; - int32 aExp, bExp, expDiff; - bits64 aSig0, aSig1, bSig0, bSig1, q, term0, term1, term2; - bits64 allZero, alternateASig0, alternateASig1, sigMean1; - sbits64 sigMean0; - float128 z; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - bSig1 = extractFloat128Frac1( b ); - bSig0 = extractFloat128Frac0( b ); - bExp = extractFloat128Exp( b ); -// bSign = extractFloat128Sign( b ); - if ( aExp == 0x7FFF ) { - if ( ( aSig0 | aSig1 ) - || ( ( bExp == 0x7FFF ) && ( bSig0 | bSig1 ) ) ) { - return propagateFloat128NaN( a, b ); - } - goto invalid; - } - if ( bExp == 0x7FFF ) { - if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b ); - return a; - } - if ( bExp == 0 ) { - if ( ( bSig0 | bSig1 ) == 0 ) { - invalid: - float_raise( float_flag_invalid ); - z.low = float128_default_nan_low; - z.high = float128_default_nan_high; - return z; - } - normalizeFloat128Subnormal( bSig0, bSig1, &bExp, &bSig0, &bSig1 ); - } - if ( aExp == 0 ) { - if ( ( aSig0 | aSig1 ) == 0 ) return a; - normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 ); - } - expDiff = aExp - bExp; - if ( expDiff < -1 ) return a; - shortShift128Left( - aSig0 | LIT64( 0x0001000000000000 ), - aSig1, - 15 - ( expDiff < 0 ), - &aSig0, - &aSig1 - ); - shortShift128Left( - bSig0 | LIT64( 0x0001000000000000 ), bSig1, 15, &bSig0, &bSig1 ); - q = le128( bSig0, bSig1, aSig0, aSig1 ); - if ( q ) sub128( aSig0, aSig1, bSig0, bSig1, &aSig0, &aSig1 ); - expDiff -= 64; - while ( 0 < expDiff ) { - q = estimateDiv128To64( aSig0, aSig1, bSig0 ); - q = ( 4 < q ) ? q - 4 : 0; - mul128By64To192( bSig0, bSig1, q, &term0, &term1, &term2 ); - shortShift192Left( term0, term1, term2, 61, &term1, &term2, &allZero ); - shortShift128Left( aSig0, aSig1, 61, &aSig0, &allZero ); - sub128( aSig0, 0, term1, term2, &aSig0, &aSig1 ); - expDiff -= 61; - } - if ( -64 < expDiff ) { - q = estimateDiv128To64( aSig0, aSig1, bSig0 ); - q = ( 4 < q ) ? q - 4 : 0; - q >>= - expDiff; - shift128Right( bSig0, bSig1, 12, &bSig0, &bSig1 ); - expDiff += 52; - if ( expDiff < 0 ) { - shift128Right( aSig0, aSig1, - expDiff, &aSig0, &aSig1 ); - } - else { - shortShift128Left( aSig0, aSig1, expDiff, &aSig0, &aSig1 ); - } - mul128By64To192( bSig0, bSig1, q, &term0, &term1, &term2 ); - sub128( aSig0, aSig1, term1, term2, &aSig0, &aSig1 ); - } - else { - shift128Right( aSig0, aSig1, 12, &aSig0, &aSig1 ); - shift128Right( bSig0, bSig1, 12, &bSig0, &bSig1 ); - } - do { - alternateASig0 = aSig0; - alternateASig1 = aSig1; - ++q; - sub128( aSig0, aSig1, bSig0, bSig1, &aSig0, &aSig1 ); - } while ( 0 <= (sbits64) aSig0 ); - add128( - aSig0, aSig1, alternateASig0, alternateASig1, (bits64 *)&sigMean0, &sigMean1 ); - if ( ( sigMean0 < 0 ) - || ( ( ( sigMean0 | sigMean1 ) == 0 ) && ( q & 1 ) ) ) { - aSig0 = alternateASig0; - aSig1 = alternateASig1; - } - zSign = ( (sbits64) aSig0 < 0 ); - if ( zSign ) sub128( 0, 0, aSig0, aSig1, &aSig0, &aSig1 ); - return - normalizeRoundAndPackFloat128( aSign ^ zSign, bExp - 4, aSig0, aSig1 ); - -} - -/*---------------------------------------------------------------------------- -| Returns the square root of the quadruple-precision floating-point value `a'. -| The operation is performed according to the IEC/IEEE Standard for Binary -| Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -float128 float128_sqrt( float128 a ) -{ - flag aSign; - int32 aExp, zExp; - bits64 aSig0, aSig1, zSig0, zSig1, zSig2, doubleZSig0; - bits64 rem0, rem1, rem2, rem3, term0, term1, term2, term3; - float128 z; - - aSig1 = extractFloat128Frac1( a ); - aSig0 = extractFloat128Frac0( a ); - aExp = extractFloat128Exp( a ); - aSign = extractFloat128Sign( a ); - if ( aExp == 0x7FFF ) { - if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, a ); - if ( ! aSign ) return a; - goto invalid; - } - if ( aSign ) { - if ( ( aExp | aSig0 | aSig1 ) == 0 ) return a; - invalid: - float_raise( float_flag_invalid ); - z.low = float128_default_nan_low; - z.high = float128_default_nan_high; - return z; - } - if ( aExp == 0 ) { - if ( ( aSig0 | aSig1 ) == 0 ) return packFloat128( 0, 0, 0, 0 ); - normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 ); - } - zExp = ( ( aExp - 0x3FFF )>>1 ) + 0x3FFE; - aSig0 |= LIT64( 0x0001000000000000 ); - zSig0 = estimateSqrt32( aExp, aSig0>>17 ); - shortShift128Left( aSig0, aSig1, 13 - ( aExp & 1 ), &aSig0, &aSig1 ); - zSig0 = estimateDiv128To64( aSig0, aSig1, zSig0<<32 ) + ( zSig0<<30 ); - doubleZSig0 = zSig0<<1; - mul64To128( zSig0, zSig0, &term0, &term1 ); - sub128( aSig0, aSig1, term0, term1, &rem0, &rem1 ); - while ( (sbits64) rem0 < 0 ) { - --zSig0; - doubleZSig0 -= 2; - add128( rem0, rem1, zSig0>>63, doubleZSig0 | 1, &rem0, &rem1 ); - } - zSig1 = estimateDiv128To64( rem1, 0, doubleZSig0 ); - if ( ( zSig1 & 0x1FFF ) <= 5 ) { - if ( zSig1 == 0 ) zSig1 = 1; - mul64To128( doubleZSig0, zSig1, &term1, &term2 ); - sub128( rem1, 0, term1, term2, &rem1, &rem2 ); - mul64To128( zSig1, zSig1, &term2, &term3 ); - sub192( rem1, rem2, 0, 0, term2, term3, &rem1, &rem2, &rem3 ); - while ( (sbits64) rem1 < 0 ) { - --zSig1; - shortShift128Left( 0, zSig1, 1, &term2, &term3 ); - term3 |= 1; - term2 |= doubleZSig0; - add192( rem1, rem2, rem3, 0, term2, term3, &rem1, &rem2, &rem3 ); - } - zSig1 |= ( ( rem1 | rem2 | rem3 ) != 0 ); - } - shift128ExtraRightJamming( zSig0, zSig1, 0, 14, &zSig0, &zSig1, &zSig2 ); - return roundAndPackFloat128( 0, zExp, zSig0, zSig1, zSig2 ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is equal to -| the corresponding value `b', and 0 otherwise. The comparison is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float128_eq( float128 a, float128 b ) -{ - if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) - && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) - || ( ( extractFloat128Exp( b ) == 0x7FFF ) - && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) - ) { - if ( float128_is_signaling_nan( a ) - || float128_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - return - ( a.low == b.low ) - && ( ( a.high == b.high ) - || ( ( a.low == 0 ) - && ( (bits64) ( ( a.high | b.high )<<1 ) == 0 ) ) - ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is less than -| or equal to the corresponding value `b', and 0 otherwise. The comparison -| is performed according to the IEC/IEEE Standard for Binary Floating-Point -| Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float128_le( float128 a, float128 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) - && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) - || ( ( extractFloat128Exp( b ) == 0x7FFF ) - && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - aSign = extractFloat128Sign( a ); - bSign = extractFloat128Sign( b ); - if ( aSign != bSign ) { - return - aSign - || ( ( ( (bits64) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) - == 0 ); - } - return - aSign ? le128( b.high, b.low, a.high, a.low ) - : le128( a.high, a.low, b.high, b.low ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is less than -| the corresponding value `b', and 0 otherwise. The comparison is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float128_lt( float128 a, float128 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) - && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) - || ( ( extractFloat128Exp( b ) == 0x7FFF ) - && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - aSign = extractFloat128Sign( a ); - bSign = extractFloat128Sign( b ); - if ( aSign != bSign ) { - return - aSign - && ( ( ( (bits64) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) - != 0 ); - } - return - aSign ? lt128( b.high, b.low, a.high, a.low ) - : lt128( a.high, a.low, b.high, b.low ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is equal to -| the corresponding value `b', and 0 otherwise. The invalid exception is -| raised if either operand is a NaN. Otherwise, the comparison is performed -| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float128_eq_signaling( float128 a, float128 b ) -{ - if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) - && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) - || ( ( extractFloat128Exp( b ) == 0x7FFF ) - && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) - ) { - float_raise( float_flag_invalid ); - return 0; - } - return - ( a.low == b.low ) - && ( ( a.high == b.high ) - || ( ( a.low == 0 ) - && ( (bits64) ( ( a.high | b.high )<<1 ) == 0 ) ) - ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is less than -| or equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not -| cause an exception. Otherwise, the comparison is performed according to the -| IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float128_le_quiet( float128 a, float128 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) - && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) - || ( ( extractFloat128Exp( b ) == 0x7FFF ) - && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) - ) { - if ( float128_is_signaling_nan( a ) - || float128_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - aSign = extractFloat128Sign( a ); - bSign = extractFloat128Sign( b ); - if ( aSign != bSign ) { - return - aSign - || ( ( ( (bits64) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) - == 0 ); - } - return - aSign ? le128( b.high, b.low, a.high, a.low ) - : le128( a.high, a.low, b.high, b.low ); - -} - -/*---------------------------------------------------------------------------- -| Returns 1 if the quadruple-precision floating-point value `a' is less than -| the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an -| exception. Otherwise, the comparison is performed according to the IEC/IEEE -| Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -flag float128_lt_quiet( float128 a, float128 b ) -{ - flag aSign, bSign; - - if ( ( ( extractFloat128Exp( a ) == 0x7FFF ) - && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) ) - || ( ( extractFloat128Exp( b ) == 0x7FFF ) - && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) ) - ) { - if ( float128_is_signaling_nan( a ) - || float128_is_signaling_nan( b ) ) { - float_raise( float_flag_invalid ); - } - return 0; - } - aSign = extractFloat128Sign( a ); - bSign = extractFloat128Sign( b ); - if ( aSign != bSign ) { - return - aSign - && ( ( ( (bits64) ( ( a.high | b.high )<<1 ) ) | a.low | b.low ) - != 0 ); - } - return - aSign ? lt128( b.high, b.low, a.high, a.low ) - : lt128( a.high, a.low, b.high, b.low ); - -} - -#endif diff --git a/machine/musashi/softfloat/softfloat.h b/machine/musashi/softfloat/softfloat.h deleted file mode 100644 index 92135e6..0000000 --- a/machine/musashi/softfloat/softfloat.h +++ /dev/null @@ -1,460 +0,0 @@ - -/*============================================================================ - -This C header file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic -Package, Release 2b. - -Written by John R. Hauser. This work was made possible in part by the -International Computer Science Institute, located at Suite 600, 1947 Center -Street, Berkeley, California 94704. Funding was partially provided by the -National Science Foundation under grant MIP-9311980. The original version -of this code was written as part of a project to build a fixed-point vector -processor in collaboration with the University of California at Berkeley, -overseen by Profs. Nelson Morgan and John Wawrzynek. More information -is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ -arithmetic/SoftFloat.html'. - -THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has -been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES -RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS -AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, -COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE -EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE -INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR -OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. - -Derivative works are acceptable, even for commercial purposes, so long as -(1) the source code for the derivative work includes prominent notice that -the work is derivative, and (2) the source code includes prominent notice with -these four paragraphs for those parts of this code that are retained. - -=============================================================================*/ - -/*---------------------------------------------------------------------------- -| The macro `FLOATX80' must be defined to enable the extended double-precision -| floating-point format `floatx80'. If this macro is not defined, the -| `floatx80' type will not be defined, and none of the functions that either -| input or output the `floatx80' type will be defined. The same applies to -| the `FLOAT128' macro and the quadruple-precision format `float128'. -*----------------------------------------------------------------------------*/ -#define FLOATX80 -#define FLOAT128 - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE floating-point types. -*----------------------------------------------------------------------------*/ -typedef bits32 float32; -typedef bits64 float64; -#ifdef FLOATX80 -typedef struct { - bits16 high; - bits64 low; -} floatx80; -#endif -#ifdef FLOAT128 -typedef struct { - bits64 high, low; -} float128; -#endif - -/*---------------------------------------------------------------------------- -| Primitive arithmetic functions, including multi-word arithmetic, and -| division and square root approximations. (Can be specialized to target if -| desired.) -*----------------------------------------------------------------------------*/ -#include "softfloat-macros" - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE floating-point underflow tininess-detection mode. -*----------------------------------------------------------------------------*/ -extern int8 float_detect_tininess; -enum { - float_tininess_after_rounding = 0, - float_tininess_before_rounding = 1 -}; - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE floating-point rounding mode. -*----------------------------------------------------------------------------*/ -extern int8 float_rounding_mode; -enum { - float_round_nearest_even = 0, - float_round_to_zero = 1, - float_round_down = 2, - float_round_up = 3 -}; - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE floating-point exception flags. -*----------------------------------------------------------------------------*/ -extern int8 float_exception_flags; -enum { - float_flag_invalid = 0x01, float_flag_denormal = 0x02, float_flag_divbyzero = 0x04, float_flag_overflow = 0x08, - float_flag_underflow = 0x10, float_flag_inexact = 0x20 -}; - -/*---------------------------------------------------------------------------- -| Routine to raise any or all of the software IEC/IEEE floating-point -| exception flags. -*----------------------------------------------------------------------------*/ -void float_raise( int8 ); - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE integer-to-floating-point conversion routines. -*----------------------------------------------------------------------------*/ -float32 int32_to_float32( int32 ); -float64 int32_to_float64( int32 ); -#ifdef FLOATX80 -floatx80 int32_to_floatx80( int32 ); -#endif -#ifdef FLOAT128 -float128 int32_to_float128( int32 ); -#endif -float32 int64_to_float32( int64 ); -float64 int64_to_float64( int64 ); -#ifdef FLOATX80 -floatx80 int64_to_floatx80( int64 ); -#endif -#ifdef FLOAT128 -float128 int64_to_float128( int64 ); -#endif - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE single-precision conversion routines. -*----------------------------------------------------------------------------*/ -int32 float32_to_int32( float32 ); -int32 float32_to_int32_round_to_zero( float32 ); -int64 float32_to_int64( float32 ); -int64 float32_to_int64_round_to_zero( float32 ); -float64 float32_to_float64( float32 ); -#ifdef FLOATX80 -floatx80 float32_to_floatx80( float32 ); -#endif -#ifdef FLOAT128 -float128 float32_to_float128( float32 ); -#endif - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE single-precision operations. -*----------------------------------------------------------------------------*/ -float32 float32_round_to_int( float32 ); -float32 float32_add( float32, float32 ); -float32 float32_sub( float32, float32 ); -float32 float32_mul( float32, float32 ); -float32 float32_div( float32, float32 ); -float32 float32_rem( float32, float32 ); -float32 float32_sqrt( float32 ); -flag float32_eq( float32, float32 ); -flag float32_le( float32, float32 ); -flag float32_lt( float32, float32 ); -flag float32_eq_signaling( float32, float32 ); -flag float32_le_quiet( float32, float32 ); -flag float32_lt_quiet( float32, float32 ); -flag float32_is_signaling_nan( float32 ); - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE double-precision conversion routines. -*----------------------------------------------------------------------------*/ -int32 float64_to_int32( float64 ); -int32 float64_to_int32_round_to_zero( float64 ); -int64 float64_to_int64( float64 ); -int64 float64_to_int64_round_to_zero( float64 ); -float32 float64_to_float32( float64 ); -#ifdef FLOATX80 -floatx80 float64_to_floatx80( float64 ); -#endif -#ifdef FLOAT128 -float128 float64_to_float128( float64 ); -#endif - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE double-precision operations. -*----------------------------------------------------------------------------*/ -float64 float64_round_to_int( float64 ); -float64 float64_add( float64, float64 ); -float64 float64_sub( float64, float64 ); -float64 float64_mul( float64, float64 ); -float64 float64_div( float64, float64 ); -float64 float64_rem( float64, float64 ); -float64 float64_sqrt( float64 ); -flag float64_eq( float64, float64 ); -flag float64_le( float64, float64 ); -flag float64_lt( float64, float64 ); -flag float64_eq_signaling( float64, float64 ); -flag float64_le_quiet( float64, float64 ); -flag float64_lt_quiet( float64, float64 ); -flag float64_is_signaling_nan( float64 ); - -#ifdef FLOATX80 - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE extended double-precision conversion routines. -*----------------------------------------------------------------------------*/ -int32 floatx80_to_int32( floatx80 ); -int32 floatx80_to_int32_round_to_zero( floatx80 ); -int64 floatx80_to_int64( floatx80 ); -int64 floatx80_to_int64_round_to_zero( floatx80 ); -float32 floatx80_to_float32( floatx80 ); -float64 floatx80_to_float64( floatx80 ); -#ifdef FLOAT128 -float128 floatx80_to_float128( floatx80 ); -#endif -floatx80 floatx80_scale(floatx80 a, floatx80 b); - -/*---------------------------------------------------------------------------- -| Packs the sign `zSign', exponent `zExp', and significand `zSig' into an -| extended double-precision floating-point value, returning the result. -*----------------------------------------------------------------------------*/ - -static inline floatx80 packFloatx80( flag zSign, int32 zExp, bits64 zSig ) -{ - floatx80 z; - - z.low = zSig; - z.high = ( ( (bits16) zSign )<<15 ) + zExp; - return z; - -} - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE extended double-precision rounding precision. Valid -| values are 32, 64, and 80. -*----------------------------------------------------------------------------*/ -extern int8 floatx80_rounding_precision; - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE extended double-precision operations. -*----------------------------------------------------------------------------*/ -floatx80 floatx80_round_to_int( floatx80 ); -floatx80 floatx80_add( floatx80, floatx80 ); -floatx80 floatx80_sub( floatx80, floatx80 ); -floatx80 floatx80_mul( floatx80, floatx80 ); -floatx80 floatx80_div( floatx80, floatx80 ); -floatx80 floatx80_rem( floatx80, floatx80 ); -floatx80 floatx80_sqrt( floatx80 ); -flag floatx80_eq( floatx80, floatx80 ); -flag floatx80_le( floatx80, floatx80 ); -flag floatx80_lt( floatx80, floatx80 ); -flag floatx80_eq_signaling( floatx80, floatx80 ); -flag floatx80_le_quiet( floatx80, floatx80 ); -flag floatx80_lt_quiet( floatx80, floatx80 ); -flag floatx80_is_signaling_nan( floatx80 ); - -/* int floatx80_fsin(floatx80 &a); -int floatx80_fcos(floatx80 &a); -int floatx80_ftan(floatx80 &a); */ - -floatx80 floatx80_flognp1(floatx80 a); -floatx80 floatx80_flogn(floatx80 a); -floatx80 floatx80_flog2(floatx80 a); -floatx80 floatx80_flog10(floatx80 a); - -// roundAndPackFloatx80 used to be in softfloat-round-pack, is now in softfloat.c -floatx80 roundAndPackFloatx80(int8 roundingPrecision, flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1); - -#endif - -#ifdef FLOAT128 - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE quadruple-precision conversion routines. -*----------------------------------------------------------------------------*/ -int32 float128_to_int32( float128 ); -int32 float128_to_int32_round_to_zero( float128 ); -int64 float128_to_int64( float128 ); -int64 float128_to_int64_round_to_zero( float128 ); -float32 float128_to_float32( float128 ); -float64 float128_to_float64( float128 ); -#ifdef FLOATX80 -floatx80 float128_to_floatx80( float128 ); -#endif - -/*---------------------------------------------------------------------------- -| Software IEC/IEEE quadruple-precision operations. -*----------------------------------------------------------------------------*/ -float128 float128_round_to_int( float128 ); -float128 float128_add( float128, float128 ); -float128 float128_sub( float128, float128 ); -float128 float128_mul( float128, float128 ); -float128 float128_div( float128, float128 ); -float128 float128_rem( float128, float128 ); -float128 float128_sqrt( float128 ); -flag float128_eq( float128, float128 ); -flag float128_le( float128, float128 ); -flag float128_lt( float128, float128 ); -flag float128_eq_signaling( float128, float128 ); -flag float128_le_quiet( float128, float128 ); -flag float128_lt_quiet( float128, float128 ); -flag float128_is_signaling_nan( float128 ); - -/*---------------------------------------------------------------------------- -| Packs the sign `zSign', the exponent `zExp', and the significand formed -| by the concatenation of `zSig0' and `zSig1' into a quadruple-precision -| floating-point value, returning the result. After being shifted into the -| proper positions, the three fields `zSign', `zExp', and `zSig0' are simply -| added together to form the most significant 32 bits of the result. This -| means that any integer portion of `zSig0' will be added into the exponent. -| Since a properly normalized significand will have an integer portion equal -| to 1, the `zExp' input should be 1 less than the desired result exponent -| whenever `zSig0' and `zSig1' concatenated form a complete, normalized -| significand. -*----------------------------------------------------------------------------*/ - -static inline float128 - packFloat128( flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1 ) -{ - float128 z; - - z.low = zSig1; - z.high = ( ( (bits64) zSign )<<63 ) + ( ( (bits64) zExp )<<48 ) + zSig0; - return z; - -} - -/*---------------------------------------------------------------------------- -| Takes an abstract floating-point value having sign `zSign', exponent `zExp', -| and extended significand formed by the concatenation of `zSig0', `zSig1', -| and `zSig2', and returns the proper quadruple-precision floating-point value -| corresponding to the abstract input. Ordinarily, the abstract value is -| simply rounded and packed into the quadruple-precision format, with the -| inexact exception raised if the abstract input cannot be represented -| exactly. However, if the abstract value is too large, the overflow and -| inexact exceptions are raised and an infinity or maximal finite value is -| returned. If the abstract value is too small, the input value is rounded to -| a subnormal number, and the underflow and inexact exceptions are raised if -| the abstract input cannot be represented exactly as a subnormal quadruple- -| precision floating-point number. -| The input significand must be normalized or smaller. If the input -| significand is not normalized, `zExp' must be 0; in that case, the result -| returned is a subnormal number, and it must not require rounding. In the -| usual case that the input significand is normalized, `zExp' must be 1 less -| than the ``true'' floating-point exponent. The handling of underflow and -| overflow follows the IEC/IEEE Standard for Binary Floating-Point Arithmetic. -*----------------------------------------------------------------------------*/ - -static inline float128 - roundAndPackFloat128( - flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1, bits64 zSig2 ) -{ - int8 roundingMode; - flag roundNearestEven, increment, isTiny; - - roundingMode = float_rounding_mode; - roundNearestEven = ( roundingMode == float_round_nearest_even ); - increment = ( (sbits64) zSig2 < 0 ); - if ( ! roundNearestEven ) { - if ( roundingMode == float_round_to_zero ) { - increment = 0; - } - else { - if ( zSign ) { - increment = ( roundingMode == float_round_down ) && zSig2; - } - else { - increment = ( roundingMode == float_round_up ) && zSig2; - } - } - } - if ( 0x7FFD <= (bits32) zExp ) { - if ( ( 0x7FFD < zExp ) - || ( ( zExp == 0x7FFD ) - && eq128( - LIT64( 0x0001FFFFFFFFFFFF ), - LIT64( 0xFFFFFFFFFFFFFFFF ), - zSig0, - zSig1 - ) - && increment - ) - ) { - float_raise( float_flag_overflow | float_flag_inexact ); - if ( ( roundingMode == float_round_to_zero ) - || ( zSign && ( roundingMode == float_round_up ) ) - || ( ! zSign && ( roundingMode == float_round_down ) ) - ) { - return - packFloat128( - zSign, - 0x7FFE, - LIT64( 0x0000FFFFFFFFFFFF ), - LIT64( 0xFFFFFFFFFFFFFFFF ) - ); - } - return packFloat128( zSign, 0x7FFF, 0, 0 ); - } - if ( zExp < 0 ) { - isTiny = - ( float_detect_tininess == float_tininess_before_rounding ) - || ( zExp < -1 ) - || ! increment - || lt128( - zSig0, - zSig1, - LIT64( 0x0001FFFFFFFFFFFF ), - LIT64( 0xFFFFFFFFFFFFFFFF ) - ); - shift128ExtraRightJamming( - zSig0, zSig1, zSig2, - zExp, &zSig0, &zSig1, &zSig2 ); - zExp = 0; - if ( isTiny && zSig2 ) float_raise( float_flag_underflow ); - if ( roundNearestEven ) { - increment = ( (sbits64) zSig2 < 0 ); - } - else { - if ( zSign ) { - increment = ( roundingMode == float_round_down ) && zSig2; - } - else { - increment = ( roundingMode == float_round_up ) && zSig2; - } - } - } - } - if ( zSig2 ) float_exception_flags |= float_flag_inexact; - if ( increment ) { - add128( zSig0, zSig1, 0, 1, &zSig0, &zSig1 ); - zSig1 &= ~ ( ( zSig2 + zSig2 == 0 ) & roundNearestEven ); - } - else { - if ( ( zSig0 | zSig1 ) == 0 ) zExp = 0; - } - return packFloat128( zSign, zExp, zSig0, zSig1 ); - -} - -/*---------------------------------------------------------------------------- -| Takes an abstract floating-point value having sign `zSign', exponent `zExp', -| and significand formed by the concatenation of `zSig0' and `zSig1', and -| returns the proper quadruple-precision floating-point value corresponding -| to the abstract input. This routine is just like `roundAndPackFloat128' -| except that the input significand has fewer bits and does not have to be -| normalized. In all cases, `zExp' must be 1 less than the ``true'' floating- -| point exponent. -*----------------------------------------------------------------------------*/ - -static inline float128 - normalizeRoundAndPackFloat128( - flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1 ) -{ - int8 shiftCount; - bits64 zSig2; - - if ( zSig0 == 0 ) { - zSig0 = zSig1; - zSig1 = 0; - zExp -= 64; - } - shiftCount = countLeadingZeros64( zSig0 ) - 15; - if ( 0 <= shiftCount ) { - zSig2 = 0; - shortShift128Left( zSig0, zSig1, shiftCount, &zSig0, &zSig1 ); - } - else { - shift128ExtraRightJamming( - zSig0, zSig1, 0, - shiftCount, &zSig0, &zSig1, &zSig2 ); - } - zExp -= shiftCount; - return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 ); - -} -#endif diff --git a/machine/my_conf.h b/machine/my_conf.h deleted file mode 100644 index 0926773..0000000 --- a/machine/my_conf.h +++ /dev/null @@ -1,39 +0,0 @@ -// custom musashi config for vamos machine -#ifndef MYCONF_H -#define MYCONF_H - -#define OPT_OFF 0 -#define OPT_ON 1 -#define OPT_SPECIFY_HANDLER 2 - -#define M68K_EMULATE_010 OPT_ON -#define M68K_EMULATE_EC020 OPT_ON -#define M68K_EMULATE_020 OPT_ON -#define M68K_EMULATE_030 OPT_ON -#define M68K_EMULATE_040 OPT_ON - -#define M68K_SEPARATE_READS OPT_OFF -#define M68K_SIMULATE_PD_WRITES OPT_OFF -#define M68K_EMULATE_INT_ACK OPT_OFF -#define M68K_EMULATE_BKPT_ACK OPT_OFF -#define M68K_EMULATE_TRACE OPT_OFF -#define M68K_EMULATE_RESET OPT_ON -#define M68K_CMPILD_HAS_CALLBACK OPT_OFF -#define M68K_RTE_HAS_CALLBACK OPT_OFF -#define M68K_TAS_HAS_CALLBACK OPT_OFF -#define M68K_ILLG_HAS_CALLBACK OPT_OFF -#define M68K_EMULATE_FC OPT_OFF -#define M68K_MONITOR_PC OPT_OFF -#define M68K_INSTRUCTION_HOOK OPT_ON -#define M68K_EMULATE_PREFETCH OPT_OFF -#define M68K_EMULATE_ADDRESS_ERROR OPT_OFF -#define M68K_ALINE_HOOK OPT_ON - -#define M68K_LOG_ENABLE OPT_OFF -#define M68K_LOG_1010_1111 OPT_OFF - -#define M68K_EMULATE_PMMU OPT_ON - -#define M68K_USE_64_BIT OPT_ON - -#endif diff --git a/machine/pycpu.pyx b/machine/pycpu.pyx deleted file mode 100644 index 8fabd70..0000000 --- a/machine/pycpu.pyx +++ /dev/null @@ -1,207 +0,0 @@ -# cython binding for musashi - -from libc.stdlib cimport malloc, free - -# m68k.h -cdef extern from "m68k.h": - ctypedef enum m68k_register_t: - M68K_REG_D0, M68K_REG_D1, M68K_REG_D2, M68K_REG_D3, - M68K_REG_D4, M68K_REG_D5, M68K_REG_D6, M68K_REG_D7, - M68K_REG_A0, M68K_REG_A1, M68K_REG_A2, M68K_REG_A3, - M68K_REG_A4, M68K_REG_A5, M68K_REG_A6, M68K_REG_A7, - M68K_REG_PC, M68K_REG_SR, - M68K_REG_SP, M68K_REG_USP, M68K_REG_ISP, M68K_REG_MSP, - M68K_REG_SFC, M68K_REG_DFC, - M68K_REG_VBR, - M68K_REG_CACR, M68K_REG_CAAR, - M68K_REG_PREF_ADDR, M68K_REG_PREF_DATA, - M68K_REG_PPC, M68K_REG_IR, - M68K_REG_CPU_TYPE - - void m68k_set_cpu_type(unsigned int cpu_type) - void m68k_init() - void m68k_pulse_reset() - int m68k_execute(int num_cycles) - void m68k_end_timeslice() - - unsigned int m68k_get_reg(void* context, m68k_register_t reg) - void m68k_set_reg(m68k_register_t reg, unsigned int value) - - void m68k_set_pc_changed_callback(void (*callback)(unsigned int new_pc)) - void m68k_set_reset_instr_callback(void (*callback)()) - void m68k_set_illg_instr_callback(int (*callback)(int opcode)) - void m68k_set_instr_hook_callback(void (*callback)(unsigned int pc)) - - unsigned int m68k_disassemble(char* str_buff, unsigned int pc, unsigned int cpu_type) - unsigned int m68k_disassemble_raw(char* str_buff, unsigned int pc, const unsigned char* opdata, const unsigned char* argdata, unsigned int cpu_type) - - unsigned int m68k_context_size() - unsigned int m68k_get_context(void* dst) - void m68k_set_context(void* dst) - -# wrapper -cdef object pc_changed_func -cdef void pc_changed_func_wrapper(unsigned int new_pc) noexcept: - pc_changed_func(new_pc) - -cdef object reset_instr_func -cdef void reset_instr_func_wrapper() noexcept: - reset_instr_func() - -cdef object instr_hook_func -cdef void instr_hook_func_wrapper(unsigned int pc) noexcept: - instr_hook_func() - -# public CPUContext -cdef class CPUContext: - cdef void *data - cdef unsigned int size - - def __cinit__(self, unsigned int size): - self.data = malloc(size) - if self.data == NULL: - raise MemoryError() - self.size = size - - cdef void *get_data(self): - return self.data - - def r_reg(self, int reg): - return m68k_get_reg(self.data, reg) - - def r_pc(self): - return m68k_get_reg(self.data, M68K_REG_PC) - - def r_sp(self): - return m68k_get_reg(self.data, M68K_REG_SP) - - def r_usp(self): - return m68k_get_reg(self.data, M68K_REG_USP) - - def r_isp(self): - return m68k_get_reg(self.data, M68K_REG_ISP) - - def r_msp(self): - return m68k_get_reg(self.data, M68K_REG_MSP) - - def __dealloc__(self): - free(self.data) - -# public CPU class -cdef class CPU: - cdef unsigned int cpu_type - - def __cinit__(self, cpu_type): - m68k_set_cpu_type(cpu_type) - m68k_init() - self.cpu_type = cpu_type - - def cleanup(self): - self.set_pc_changed_callback(None) - self.set_reset_instr_callback(None) - self.set_instr_hook_callback(None) - - cdef unsigned int r_reg_internal(self, m68k_register_t reg): - return m68k_get_reg(NULL, reg) - - cdef void w_reg_internal(self, m68k_register_t reg, unsigned int v): - m68k_set_reg(reg, v) - - def w_reg(self, reg, val): - self.w_reg_internal(reg,val) - - def r_reg(self,reg): - return self.r_reg_internal(reg) - - def ws_reg(self, m68k_register_t reg, int val): - m68k_set_reg(reg, (val)) - - def rs_reg(self, m68k_register_t reg): - return m68k_get_reg(NULL, reg) - - def w_pc(self, val): - self.w_reg_internal(M68K_REG_PC,val) - - def r_pc(self): - return self.r_reg_internal(M68K_REG_PC) - - def w_sr(self, val): - self.w_reg_internal(M68K_REG_SR,val) - - def r_sr(self): - return self.r_reg_internal(M68K_REG_SR) - - def w_usp(self, val): - self.w_reg_internal(M68K_REG_USP,val) - - def r_usp(self): - return self.r_reg_internal(M68K_REG_USP) - - def w_isp(self, val): - self.w_reg_internal(M68K_REG_ISP,val) - - def r_isp(self): - return self.r_reg_internal(M68K_REG_ISP) - - def w_msp(self, val): - self.w_reg_internal(M68K_REG_MSP,val) - - def r_msp(self): - return self.r_reg_internal(M68K_REG_MSP) - - def pulse_reset(self): - m68k_pulse_reset() - - def execute(self, num_cycles): - cdef int cycles = m68k_execute(num_cycles) - check_mem_exc() - return cycles - - def end(self): - m68k_end_timeslice() - - def set_pc_changed_callback(self, py_func): - global pc_changed_func - pc_changed_func = py_func - if py_func is None: - m68k_set_pc_changed_callback(NULL) - else: - m68k_set_pc_changed_callback(pc_changed_func_wrapper) - - def set_reset_instr_callback(self, py_func): - global reset_instr_func - reset_instr_func = py_func - if py_func is None: - m68k_set_reset_instr_callback(NULL) - else: - m68k_set_reset_instr_callback(reset_instr_func_wrapper) - - def set_instr_hook_callback(self, py_func): - global instr_hook_func - instr_hook_func = py_func - if py_func is None: - m68k_set_instr_hook_callback(NULL) - else: - m68k_set_instr_hook_callback(instr_hook_func_wrapper) - - def disassemble(self, unsigned int pc): - cdef char line[80] - cdef unsigned int size - size = m68k_disassemble(line, pc, self.cpu_type) - return (size, line.decode('latin-1')) - - def disassemble_raw(self, unsigned int pc, const unsigned char[::1] raw_mem): - cdef char line[80] - cdef unsigned int size - size = m68k_disassemble_raw(line, pc, &raw_mem[0], NULL, self.cpu_type) - return (size, line.decode('latin-1')) - - def get_cpu_context(self): - cdef unsigned int size = m68k_context_size() - cdef CPUContext ctx = CPUContext(size) - cdef void *data = ctx.get_data() - m68k_get_context(data) - return ctx - - def set_cpu_context(self, CPUContext ctx): - m68k_set_context(ctx.get_data()) diff --git a/machine/pymem.pyx b/machine/pymem.pyx deleted file mode 100644 index e2db01e..0000000 --- a/machine/pymem.pyx +++ /dev/null @@ -1,441 +0,0 @@ -# mem.h -cdef extern from "mem.h": - ctypedef unsigned int uint - ctypedef uint (*read_func_t)(uint addr, void *ctx) - ctypedef void (*write_func_t)(uint addr, uint value, void *ctx) - ctypedef void (*invalid_func_t)(int mode, int width, uint addr, void *ctx) - ctypedef void (*trace_func_t)(int mode, int width, uint addr, uint val, void *ctx) - - int mem_init(uint ram_size_kib) - void mem_free() - - void mem_set_invalid_func(invalid_func_t func, void *ctx) - void mem_set_trace_mode(int on) - void mem_set_trace_func(trace_func_t func, void *ctx) - - uint mem_reserve_special_range(uint num_pages) - void mem_set_special_range_read_func(uint page_addr, uint width, read_func_t func, void *ctx) - void mem_set_special_range_write_func(uint page_addr, uint width, write_func_t func, void *ctx) - - unsigned int m68k_read_memory_8(unsigned int address) - unsigned int m68k_read_memory_16(unsigned int address) - unsigned int m68k_read_memory_32(unsigned int address) - - void m68k_write_memory_8(unsigned int address, unsigned int value) - void m68k_write_memory_16(unsigned int address, unsigned int value) - void m68k_write_memory_32(unsigned int address, unsigned int value) - - unsigned char *mem_raw_ptr() - uint mem_raw_size() - - int mem_ram_r8(uint addr, uint *val) - int mem_ram_r16(uint addr, uint *val) - int mem_ram_r32(uint addr, uint *val) - - int mem_ram_w8(uint addr, uint val) - int mem_ram_w16(uint addr, uint val) - int mem_ram_w32(uint addr, uint val) - -# string.h -from libc.string cimport memcpy, memset, strlen, strcpy -from libc.stdlib cimport malloc, free -import sys - -# wrapper functions -cdef object mem_callback_exc -cdef check_mem_exc(): - # raise a mem exception - global mem_callback_exc - if mem_callback_exc: - exc = mem_callback_exc - mem_callback_exc = None - raise exc[0], exc[1], exc[2] - -cdef void trace_func_wrapper(int mode, int width, uint addr, uint val, void *ctx) noexcept: - cdef object py_func = ctx - try: - py_func(chr(mode), width, addr, val) - except: - global mem_callback_exc - mem_callback_exc = sys.exc_info() - m68k_end_timeslice() - -cdef void invalid_func_wrapper(int mode, int width, uint addr, void *ctx) noexcept: - cdef object py_func = ctx - try: - py_func(chr(mode), width, addr) - except: - global mem_callback_exc - mem_callback_exc = sys.exc_info() - m68k_end_timeslice() - -cdef uint special_read_func_wrapper(uint addr, void *ctx) noexcept: - cdef object py_func = ctx - try: - return py_func(addr) - except: - global mem_callback_exc - mem_callback_exc = sys.exc_info() - m68k_end_timeslice() - return 0 - -cdef void special_write_func_wrapper(uint addr, uint value, void *ctx) noexcept: - cdef object py_func = ctx - try: - py_func(addr, value) - except: - global mem_callback_exc - mem_callback_exc = sys.exc_info() - m68k_end_timeslice() - -class MemoryError(Exception): - def __init__(self, addr, op, size=None): - self.addr = addr - self.op = op - self.size = size - - def __repr__(self): - return "MemoryError(%06x, %s, %s)" % (self.addr, self.op, self.size) - -# public Memory class -cdef class Memory: - cdef uint ram_size_kib - cdef uint ram_bytes - cdef unsigned char *ram_ptr - # keep python refs of callback funcs otherwise wrapper might loose the object - cdef set special_read_funcs - cdef set special_write_funcs - cdef object trace_func - cdef object invalid_func - - def __cinit__(self, ram_size_kib): - mem_init(ram_size_kib) - self.ram_size_kib = ram_size_kib - self.ram_bytes = ram_size_kib * 1024 - self.ram_ptr = mem_raw_ptr() - self.special_read_funcs = set() - self.special_write_funcs = set() - - def cleanup(self): - self.set_trace_func(None) - self.set_invalid_func(None) - self.special_read_funcs.clear() - self.special_write_funcs.clear() - mem_free() - - def get_ram_size_kib(self): - return self.ram_size_kib - - def get_ram_size_bytes(self): - return self.ram_bytes - - def reserve_special_range(self,num_pages=1): - return mem_reserve_special_range(num_pages) - - cpdef set_special_range_read_func(self, uint page_addr, uint width, func): - mem_set_special_range_read_func(page_addr, width, special_read_func_wrapper, func) - # keep func ref - self.special_read_funcs.add(func) - - cpdef set_special_range_write_func(self,uint page_addr, uint width, func): - mem_set_special_range_write_func(page_addr, width, special_write_func_wrapper, func) - # keep func ref - self.special_write_funcs.add(func) - - def set_special_range_read_funcs(self, uint addr, uint num_pages=1, r8=None, r16=None, r32=None): - for i in range(num_pages): - if r8 != None: - self.set_special_range_read_func(addr, 0, r8) - if r16 != None: - self.set_special_range_read_func(addr, 1, r16) - if r32 != None: - self.set_special_range_read_func(addr, 2, r32) - addr += 0x10000 - - def set_special_range_write_funcs(self, uint addr, uint num_pages=1, w8=None, w16=None, w32=None): - for i in range(num_pages): - if w8 != None: - self.set_special_range_write_func(addr, 0, w8) - if w16 != None: - self.set_special_range_write_func(addr, 1, w16) - if w32 != None: - self.set_special_range_write_func(addr, 2, w32) - addr += 0x10000 - - def set_trace_mode(self,on): - mem_set_trace_mode(on) - - def set_trace_func(self,func): - if func is None: - mem_set_trace_func(NULL, NULL) - else: - mem_set_trace_func(trace_func_wrapper, func) - # keep func ref - self.trace_func = func - - def set_invalid_func(self,func): - if func is None: - mem_set_invalid_func(NULL, NULL) - else: - mem_set_invalid_func(invalid_func_wrapper, func) - # keep func ref - self.invalid_func = func - - def _raise_ram_error(self, addr, op, width): - raise MemoryError(addr, op, width) - - # CPU-like memory access (not RAM only!) - cpdef cpu_r8(self, uint addr): - cdef uint val = m68k_read_memory_8(addr) - check_mem_exc() - return val - cpdef cpu_r16(self, uint addr): - cdef uint val = m68k_read_memory_16(addr) - check_mem_exc() - return val - cpdef cpu_r32(self, uint addr): - cdef uint val = m68k_read_memory_32(addr) - check_mem_exc() - return val - cpdef cpu_w8(self, uint addr, uint value): - if value > 0xff: - raise OverflowError("value does not fit into byte") - m68k_write_memory_8(addr, value) - check_mem_exc() - cpdef cpu_w16(self, uint addr, uint value): - if value > 0xffff: - raise OverflowError("value does not fit into word") - m68k_write_memory_16(addr, value) - check_mem_exc() - cpdef cpu_w32(self, uint addr, uint value): - m68k_write_memory_32(addr, value) - check_mem_exc() - - # CPU-like signed memory access (not RAM only!) - cpdef cpu_r8s(self, uint addr): - cdef uint val = m68k_read_memory_8(addr) - check_mem_exc() - # sign extend - if val & 0x80 == 0x80: - val |= 0xffffff00 - return (val) - cpdef cpu_r16s(self, uint addr): - cdef uint val = m68k_read_memory_16(addr) - check_mem_exc() - # sign extend - if val & 0x8000 == 0x8000: - val |= 0xffff0000 - return (val) - cpdef cpu_r32s(self, uint addr): - cdef uint val = m68k_read_memory_32(addr) - check_mem_exc() - return (val) - cpdef cpu_w8s(self, uint addr, int value): - if value < -0x80 or value > 0x7f: - raise OverflowError("value does not fit into byte") - cdef uint val = value & 0xff - m68k_write_memory_8(addr, val) - check_mem_exc() - cpdef cpu_w16s(self, uint addr, int value): - if value < -0x8000 or value > 0x7fff: - raise OverflowError("value does not fit into word") - cdef uint val = value & 0xffff - m68k_write_memory_16(addr, val) - check_mem_exc() - cpdef cpu_w32s(self, uint addr, int value): - cdef uint val = (value) - m68k_write_memory_32(addr, val) - check_mem_exc() - - # memory access (RAM only!) - cpdef r8(self, uint addr): - cdef uint val - if mem_ram_r8(addr, &val): - self._raise_ram_error(addr, 'R', 0) - return val - cpdef r16(self, uint addr): - cdef uint val - if mem_ram_r16(addr, &val): - self._raise_ram_error(addr, 'R', 1) - return val - cpdef r32(self, uint addr): - cdef uint val - if mem_ram_r32(addr, &val): - self._raise_ram_error(addr, 'R', 2) - return val - cpdef w8(self, uint addr, uint value): - if value > 0xff: - raise OverflowError("value does not fit into byte") - if mem_ram_w8(addr, value): - self._raise_ram_error(addr, 'W', 0) - cpdef w16(self, uint addr, uint value): - if value > 0xffff: - raise OverflowError("value does not fit into word") - if mem_ram_w16(addr, value): - self._raise_ram_error(addr, 'W', 1) - cpdef w32(self, uint addr, uint value): - if mem_ram_w32(addr, value): - self._raise_ram_error(addr, 'W', 2) - - # signed memory access (RAM only!) - cpdef r8s(self, uint addr): - cdef uint val - if mem_ram_r8(addr, &val): - self._raise_ram_error(addr, 'R', 0) - # sign extend - if val & 0x80 == 0x80: - val |= 0xffffff00 - return (val) - cpdef r16s(self, uint addr): - cdef uint val - if mem_ram_r16(addr, &val): - self._raise_ram_error(addr, 'R', 1) - # sign extend - if val & 0x8000 == 0x8000: - val |= 0xffff0000 - return (val) - cpdef r32s(self, uint addr): - cdef uint val - if mem_ram_r32(addr, &val): - self._raise_ram_error(addr, 'R', 2) - return (val) - cpdef w8s(self, uint addr, int value): - if value < -0x80 or value > 0x7f: - raise OverflowError("value does not fit into byte") - cdef uint val = value & 0xff - if mem_ram_w8(addr, val): - self._raise_ram_error(addr, 'W', 0) - cpdef w16s(self, uint addr, int value): - if value < -0x8000 or value > 0x7fff: - raise OverflowError("value does not fit into word") - cdef uint val = value & 0xffff - if mem_ram_w16(addr, val): - self._raise_ram_error(addr, 'W', 1) - cpdef w32s(self, uint addr, int value): - cdef uint val = (value) - if mem_ram_w32(addr, val): - self._raise_ram_error(addr, 'W', 2) - - # arbitrary width (full range including special) - def read(self, uint width, uint addr): - if width == 0: - return self.r8(addr) - elif width == 1: - return self.r16(addr) - elif width == 2: - return self.r32(addr) - else: - raise ValueError("invalid width!") - def write(self, uint width, uint addr, uint value): - if width == 0: - self.w8(addr, value) - elif width == 1: - self.w16(addr, value) - elif width == 2: - self.w32(addr, value) - else: - raise ValueError("invalid width!") - - # signed arbitrary width (full range including special) - def reads(self, uint width, uint addr): - if width == 0: - return self.r8s(addr) - elif width == 1: - return self.r16s(addr) - elif width == 2: - return self.r32s(addr) - else: - raise ValueError("invalid width!") - def writes(self, uint width, uint addr, int value): - if width == 0: - self.w8s(addr, value) - elif width == 1: - self.w16s(addr, value) - elif width == 2: - self.w32s(addr, value) - else: - raise ValueError("invalid width!") - - # block access via str/bytearray (only RAM!) - def r_block(self,uint addr,uint size): - if (addr+size) > self.ram_bytes: - self._raise_ram_error(addr, 'R', size) - res = bytearray(size) - cdef unsigned char *ptr = res - cdef const unsigned char *ram = self.ram_ptr + addr - memcpy(ptr, ram, size) - return res - def w_block(self,uint addr,data): - cdef uint size = len(data) - if (addr+size) > self.ram_bytes: - self._raise_ram_error(addr, 'W', size) - cdef const unsigned char *ptr = data - cdef unsigned char *ram = self.ram_ptr + addr - memcpy(ram, ptr, size) - - def clear_block(self,uint addr,uint size,unsigned char value): - if (addr+size) > self.ram_bytes: - self._raise_ram_error(addr, 'W', size) - cdef unsigned char *ram = self.ram_ptr + addr - memset(ram,value,size) - - def copy_block(self,uint from_addr, uint to_addr, uint size): - if (from_addr+size) > self.ram_bytes: - self._raise_ram_error(from_addr, 'R', size) - if (to_addr+size) > self.ram_bytes: - self._raise_ram_error(to_addr, 'W', size) - cdef unsigned char *from_ptr = self.ram_ptr + from_addr - cdef unsigned char *to_ptr = self.ram_ptr + to_addr - memcpy(to_ptr, from_ptr, size) - - # helpers for c-strings (only RAM) - cpdef r_cbytes(self,uint addr): - if addr >= self.ram_bytes: - self._raise_ram_error(addr, 'R', None) - cdef unsigned char *ram = self.ram_ptr + addr - cdef bytes result = ram - return result - - cpdef w_cbytes(self,uint addr,bytes string): - if addr >= self.ram_bytes: - self._raise_ram_error(addr, 'W', None) - cdef const char *ptr = string - cdef char *ram = self.ram_ptr + addr - strcpy(ram, ptr) - - def r_cstr(self, uint addr): - return self.r_cbytes(addr).decode("latin-1") - - def w_cstr(self, uint addr, str string): - self.w_cbytes(addr, string.encode("latin-1")) - - # helpers for bcpl-strings (only RAM) - cpdef r_bbytes(self,uint addr): - if addr >= self.ram_bytes: - self._raise_ram_error(addr, 'R', None) - cdef uint size - cdef char *data - cdef unsigned char *ram = self.ram_ptr + addr + 1 - size = self.ram_ptr[addr] - data = malloc(size+1) - memcpy(data, ram, size) - data[size] = '\0' - cdef bytes result = data - free(data) - return result - - cpdef w_bbytes(self,uint addr,bytes string): - if addr >= self.ram_bytes: - self._raise_ram_error(addr, 'W', None) - cdef uint size = len(string) - cdef unsigned char *ptr = string - cdef unsigned char *ram = self.ram_ptr + addr - ram[0] = size - ram += 1 - memcpy(ram, ptr, size) - - def r_bstr(self, uint addr): - return self.r_bbytes(addr).decode("latin-1") - - def w_bstr(self, uint addr, str string): - self.w_bbytes(addr, string.encode("latin-1")) diff --git a/machine/pytraps.pyx b/machine/pytraps.pyx deleted file mode 100644 index 0dd4c0d..0000000 --- a/machine/pytraps.pyx +++ /dev/null @@ -1,63 +0,0 @@ -# traps.h -cdef extern from "traps.h": - int TRAP_DEFAULT - int TRAP_AUTO_RTS - int TRAP_ONE_SHOT - ctypedef void (*trap_func_t)(uint opcode, uint pc, void *data) - void trap_init() - int trap_setup(trap_func_t func, int flags, void *data) - void trap_free(int id) - int trap_aline(uint opcode, uint pc) - -cdef object trap_exc_func - -from cpython.exc cimport PyErr_Print - -cdef void trap_wrapper(uint opcode, uint pc, void *data) noexcept: - cdef object py_func = data - try: - py_func(opcode, pc) - except: - if trap_exc_func is not None: - trap_exc_func(opcode, pc) - else: - raise - -cdef class Traps: - cdef dict func_map - - def __cinit__(self): - trap_init() - self.func_map = {} - - def cleanup(self): - self.set_exc_func(None) - - def set_exc_func(self, func): - global trap_exc_func - trap_exc_func = func - - def setup(self, py_func, auto_rts=False, one_shot=False): - cdef int flags - flags = TRAP_DEFAULT - if auto_rts: - flags |= TRAP_AUTO_RTS - if one_shot: - flags |= TRAP_ONE_SHOT - tid = trap_setup(trap_wrapper, flags, py_func) - if tid != -1: - # keep function reference around - self.func_map[tid] = py_func - return tid - - def free(self, tid): - trap_free(tid) - del self.func_map[tid] - - def trigger(self, uint opcode, uint pc): - return trap_aline(opcode, pc) - - def get_func(self, tid): - if tid in self.func_map: - return self.func_map[tid] - diff --git a/machine/traps.c b/machine/traps.c deleted file mode 100644 index e5cd689..0000000 --- a/machine/traps.c +++ /dev/null @@ -1,109 +0,0 @@ -/* a dispatcher for a-line opcodes to be used as traps in vamos - * - * written by Christian Vogelgsang - * under the GNU Public License V2 - */ - -#include "traps.h" -#include "m68k.h" -#include -#include - -#define NUM_TRAPS 0x1000 -#define TRAP_MASK 0x0fff - - - -struct entry { - trap_func_t trap; - struct entry *next; - void *data; - int flags; -}; -typedef struct entry entry_t; - -static entry_t traps[NUM_TRAPS]; -static entry_t *first_free; - -int trap_aline(uint opcode, uint pc) -{ - uint off = opcode & TRAP_MASK; - trap_func_t func = traps[off].trap; - void *data = traps[off].data; - int flags = traps[off].flags; - - /* unbound trap? */ - if(func == NULL) { - /* regular m68k ALINE exception */ - return M68K_ALINE_EXCEPT; - } - - /* a one shot trap is removed before it is triggered - ** otherwise, trap-functions used to capture "end-of-call"s - ** of shell processes would never be released. - */ - if(flags & TRAP_ONE_SHOT) { - trap_free(off); - } - - func(opcode, pc, data); - - if(flags & TRAP_AUTO_RTS) { - return M68K_ALINE_RTS; - } else { - return M68K_ALINE_NONE; - } -} - -void trap_init(void) -{ - int i; - - /* setup free list */ - first_free = &traps[0]; - for(i=0;i<(NUM_TRAPS-1);i++) { - traps[i].trap = NULL; - traps[i].next = &traps[i+1]; - traps[i].flags = 0; - traps[i].data = NULL; - } - traps[NUM_TRAPS-1].trap = NULL; - traps[NUM_TRAPS-1].next = NULL; - traps[NUM_TRAPS-1].flags = 0; - traps[NUM_TRAPS-1].data = NULL; - - /* setup my trap handler */ - m68k_set_aline_hook_callback(trap_aline); -} - -int trap_setup(trap_func_t func, int flags, void *data) -{ - int off; - - /* no more traps available? */ - if(first_free == NULL) { - return -1; - } - - off = (int)(first_free - traps); - - /* new first free */ - first_free = traps[off].next; - - /* store trap function */ - traps[off].trap = func; - traps[off].data = data; - traps[off].flags = flags; - - return off; -} - -void trap_free(int id) -{ - /* insert trap into free list */ - traps[id].next = first_free; - traps[id].trap = NULL; - traps[id].flags = 0; - traps[id].data = NULL; - first_free = &traps[id]; -} diff --git a/machine/traps.h b/machine/traps.h deleted file mode 100644 index e538f6a..0000000 --- a/machine/traps.h +++ /dev/null @@ -1,32 +0,0 @@ -/* a dispatcher for a-line opcodes to be used as traps in vamos - * - * written by Christian Vogelgsang - * under the GNU Public License V2 - */ - -#ifndef _TRAPS_H -#define _TRAPS_H - -#include "m68k.h" -#include - -#define TRAP_DEFAULT 0 -#define TRAP_ONE_SHOT 1 -#define TRAP_AUTO_RTS 2 - -/* ------ Types ----- */ -#ifndef UINT_TYPE -#define UINT_TYPE -typedef unsigned int uint; -#endif - -typedef void (*trap_func_t)(uint opcode, uint pc, void *data); - -/* ----- API ----- */ -extern void trap_init(void); -extern int trap_aline(uint opcode, uint pc); - -extern int trap_setup(trap_func_t func, int flags, void *data); -extern void trap_free(int id); - -#endif diff --git a/machine/win/stdint.h b/machine/win/stdint.h deleted file mode 100644 index d02608a..0000000 --- a/machine/win/stdint.h +++ /dev/null @@ -1,247 +0,0 @@ -// ISO C9x compliant stdint.h for Microsoft Visual Studio -// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 -// -// Copyright (c) 2006-2008 Alexander Chemeris -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// 3. The name of the author may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO -// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; -// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef _MSC_VER // [ -#error "Use this header only with Microsoft Visual C++ compilers!" -#endif // _MSC_VER ] - -#ifndef _MSC_STDINT_H_ // [ -#define _MSC_STDINT_H_ - -#if _MSC_VER > 1000 -#pragma once -#endif - -#include - -// For Visual Studio 6 in C++ mode and for many Visual Studio versions when -// compiling for ARM we should wrap include with 'extern "C++" {}' -// or compiler give many errors like this: -// error C2733: second C linkage of overloaded function 'wmemchr' not allowed -#ifdef __cplusplus -extern "C" { -#endif -# include -#ifdef __cplusplus -} -#endif - -// Define _W64 macros to mark types changing their size, like intptr_t. -#ifndef _W64 -# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300 -# define _W64 __w64 -# else -# define _W64 -# endif -#endif - - -// 7.18.1 Integer types - -// 7.18.1.1 Exact-width integer types - -// Visual Studio 6 and Embedded Visual C++ 4 doesn't -// realize that, e.g. char has the same size as __int8 -// so we give up on __intX for them. -#if (_MSC_VER < 1300) - typedef signed char int8_t; - typedef signed short int16_t; - typedef signed int int32_t; - typedef unsigned char uint8_t; - typedef unsigned short uint16_t; - typedef unsigned int uint32_t; -#else - typedef signed __int8 int8_t; - typedef signed __int16 int16_t; - typedef signed __int32 int32_t; - typedef unsigned __int8 uint8_t; - typedef unsigned __int16 uint16_t; - typedef unsigned __int32 uint32_t; -#endif -typedef signed __int64 int64_t; -typedef unsigned __int64 uint64_t; - - -// 7.18.1.2 Minimum-width integer types -typedef int8_t int_least8_t; -typedef int16_t int_least16_t; -typedef int32_t int_least32_t; -typedef int64_t int_least64_t; -typedef uint8_t uint_least8_t; -typedef uint16_t uint_least16_t; -typedef uint32_t uint_least32_t; -typedef uint64_t uint_least64_t; - -// 7.18.1.3 Fastest minimum-width integer types -typedef int8_t int_fast8_t; -typedef int16_t int_fast16_t; -typedef int32_t int_fast32_t; -typedef int64_t int_fast64_t; -typedef uint8_t uint_fast8_t; -typedef uint16_t uint_fast16_t; -typedef uint32_t uint_fast32_t; -typedef uint64_t uint_fast64_t; - -// 7.18.1.4 Integer types capable of holding object pointers -#ifdef _WIN64 // [ - typedef signed __int64 intptr_t; - typedef unsigned __int64 uintptr_t; -#else // _WIN64 ][ - typedef _W64 signed int intptr_t; - typedef _W64 unsigned int uintptr_t; -#endif // _WIN64 ] - -// 7.18.1.5 Greatest-width integer types -typedef int64_t intmax_t; -typedef uint64_t uintmax_t; - - -// 7.18.2 Limits of specified-width integer types - -#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259 - -// 7.18.2.1 Limits of exact-width integer types -#define INT8_MIN ((int8_t)_I8_MIN) -#define INT8_MAX _I8_MAX -#define INT16_MIN ((int16_t)_I16_MIN) -#define INT16_MAX _I16_MAX -#define INT32_MIN ((int32_t)_I32_MIN) -#define INT32_MAX _I32_MAX -#define INT64_MIN ((int64_t)_I64_MIN) -#define INT64_MAX _I64_MAX -#define UINT8_MAX _UI8_MAX -#define UINT16_MAX _UI16_MAX -#define UINT32_MAX _UI32_MAX -#define UINT64_MAX _UI64_MAX - -// 7.18.2.2 Limits of minimum-width integer types -#define INT_LEAST8_MIN INT8_MIN -#define INT_LEAST8_MAX INT8_MAX -#define INT_LEAST16_MIN INT16_MIN -#define INT_LEAST16_MAX INT16_MAX -#define INT_LEAST32_MIN INT32_MIN -#define INT_LEAST32_MAX INT32_MAX -#define INT_LEAST64_MIN INT64_MIN -#define INT_LEAST64_MAX INT64_MAX -#define UINT_LEAST8_MAX UINT8_MAX -#define UINT_LEAST16_MAX UINT16_MAX -#define UINT_LEAST32_MAX UINT32_MAX -#define UINT_LEAST64_MAX UINT64_MAX - -// 7.18.2.3 Limits of fastest minimum-width integer types -#define INT_FAST8_MIN INT8_MIN -#define INT_FAST8_MAX INT8_MAX -#define INT_FAST16_MIN INT16_MIN -#define INT_FAST16_MAX INT16_MAX -#define INT_FAST32_MIN INT32_MIN -#define INT_FAST32_MAX INT32_MAX -#define INT_FAST64_MIN INT64_MIN -#define INT_FAST64_MAX INT64_MAX -#define UINT_FAST8_MAX UINT8_MAX -#define UINT_FAST16_MAX UINT16_MAX -#define UINT_FAST32_MAX UINT32_MAX -#define UINT_FAST64_MAX UINT64_MAX - -// 7.18.2.4 Limits of integer types capable of holding object pointers -#ifdef _WIN64 // [ -# define INTPTR_MIN INT64_MIN -# define INTPTR_MAX INT64_MAX -# define UINTPTR_MAX UINT64_MAX -#else // _WIN64 ][ -# define INTPTR_MIN INT32_MIN -# define INTPTR_MAX INT32_MAX -# define UINTPTR_MAX UINT32_MAX -#endif // _WIN64 ] - -// 7.18.2.5 Limits of greatest-width integer types -#define INTMAX_MIN INT64_MIN -#define INTMAX_MAX INT64_MAX -#define UINTMAX_MAX UINT64_MAX - -// 7.18.3 Limits of other integer types - -#ifdef _WIN64 // [ -# define PTRDIFF_MIN _I64_MIN -# define PTRDIFF_MAX _I64_MAX -#else // _WIN64 ][ -# define PTRDIFF_MIN _I32_MIN -# define PTRDIFF_MAX _I32_MAX -#endif // _WIN64 ] - -#define SIG_ATOMIC_MIN INT_MIN -#define SIG_ATOMIC_MAX INT_MAX - -#ifndef SIZE_MAX // [ -# ifdef _WIN64 // [ -# define SIZE_MAX _UI64_MAX -# else // _WIN64 ][ -# define SIZE_MAX _UI32_MAX -# endif // _WIN64 ] -#endif // SIZE_MAX ] - -// WCHAR_MIN and WCHAR_MAX are also defined in -#ifndef WCHAR_MIN // [ -# define WCHAR_MIN 0 -#endif // WCHAR_MIN ] -#ifndef WCHAR_MAX // [ -# define WCHAR_MAX _UI16_MAX -#endif // WCHAR_MAX ] - -#define WINT_MIN 0 -#define WINT_MAX _UI16_MAX - -#endif // __STDC_LIMIT_MACROS ] - - -// 7.18.4 Limits of other integer types - -#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260 - -// 7.18.4.1 Macros for minimum-width integer constants - -#define INT8_C(val) val##i8 -#define INT16_C(val) val##i16 -#define INT32_C(val) val##i32 -#define INT64_C(val) val##i64 - -#define UINT8_C(val) val##ui8 -#define UINT16_C(val) val##ui16 -#define UINT32_C(val) val##ui32 -#define UINT64_C(val) val##ui64 - -// 7.18.4.2 Macros for greatest-width integer constants -#define INTMAX_C INT64_C -#define UINTMAX_C UINT64_C - -#endif // __STDC_CONSTANT_MACROS ] - - -#endif // _MSC_STDINT_H_ ] diff --git a/pyproject.toml b/pyproject.toml index 8af73fc..6f1ab81 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -19,10 +19,13 @@ classifiers = [ ] dynamic = ["version", "readme"] +[project.optional-dependencies] +vamos = ["machine68k"] + [tool.setuptools] zip-safe = false include-package-data = true -packages = ["amitools", "machine"] +packages = ["amitools"] [tool.setuptools.dynamic] readme = { file="README.md", content-type="text/markdown" } diff --git a/setup.py b/setup.py index b655bfd..b024da8 100644 --- a/setup.py +++ b/setup.py @@ -1,220 +1,4 @@ -import os -import sys -import subprocess - -from setuptools import setup, Extension -from pkg_resources import parse_version -from distutils.command.build_ext import build_ext -from distutils.command.clean import clean -from distutils.core import Command -from distutils import ccompiler -from distutils.dir_util import remove_tree -from distutils import log -from pkg_resources import parse_version - -# has cython? -try: - from Cython.Build import cythonize - - has_cython = True -except ImportError: - has_cython = False - -# use cython? -use_cython = has_cython -if "--no-cython" in sys.argv: - use_cython = False - sys.argv.remove("--no-cython") -print("use_cython:", use_cython) - -# check cython version -if use_cython: - try: - from Cython import __version__ as cyver - - print("cython version:", cyver) - if parse_version(cyver) < parse_version("3.0"): - print("cython is too old < 3.0! please update first!") - sys.exit(1) - except ImportError: - print("cython is too old! please update first!") - sys.exit(1) - -# if generated file is missing cython is required -ext_file = "machine/emu.c" -if not os.path.exists(ext_file) and not use_cython: - print("generated cython file missing! cython is essential to proceed!") - print("please install with: pip3 install cython") - sys.exit(1) +from setuptools import setup -gen_src = ["m68kopac.c", "m68kopdm.c", "m68kopnz.c", "m68kops.c"] - -gen_tool = "build/m68kmake" -gen_tool_src = "machine/musashi/m68kmake.c" -gen_tool_obj = "build/machine/musashi/m68kmake.o" -gen_input = "machine/musashi/m68k_in.c" -gen_dir = "gen" -gen_src = list([os.path.join(gen_dir, x) for x in gen_src]) -build_dir = "build" - -# check compiler -is_msvc = sys.platform == "win32" and sys.version.lower().find("msc") != -1 - - -class my_build_ext(build_ext): - """overwrite build_ext to generate code first""" - - def run(self): - self.run_command("gen") - build_ext.run(self) - - -class my_clean(clean): - """overwrite clean to clean_gen first""" - - def run(self): - self.run_command("clean_gen") - clean.run(self) - - -class GenCommand(Command): - """my custom code generation command""" - - description = "generate code for Musashi CPU emulator" - user_options = [] - - def initialize_options(self): - pass - - def finalize_options(self): - pass - - def run(self): - # ensure dir exists - if not os.path.isdir(gen_dir): - log.info("creating '{}' dir".format(gen_dir)) - os.mkdir(gen_dir) - if not os.path.isdir(build_dir): - log.info("creating '{}' dir".format(build_dir)) - os.mkdir(build_dir) - # build tool first? - if not os.path.exists(gen_tool): - cc = ccompiler.new_compiler() - log.info("building '{}' tool".format(gen_tool)) - # win fixes - src = gen_tool_src.replace("/", os.path.sep) - print("tool source:", src) - obj = gen_tool_obj.replace(".o", cc.obj_extension) - obj = obj.replace("/", os.path.sep) - print("tool object:", obj) - # compile - if is_msvc: - defines = [("_CRT_SECURE_NO_WARNINGS", None)] - else: - defines = None - cc.compile(sources=[src], output_dir=build_dir, macros=defines) - # link - if is_msvc: - ld_args = ["/MANIFEST"] - else: - ld_args = None - cc.link_executable( - objects=[obj], output_progname=gen_tool, extra_postargs=ld_args - ) - # remove - os.remove(obj) - # generate source? - if not os.path.exists(gen_src[0]): - log.info("generating source files") - cmd = [gen_tool, gen_dir, gen_input] - subprocess.check_call(cmd) - - -class CleanGenCommand(Command): - """my custom code generation cleanup command""" - - description = "remove generated code for Musashi CPU emulator" - user_options = [] - - def initialize_options(self): - pass - - def finalize_options(self): - pass - - def run(self): - if os.path.exists(gen_dir): - remove_tree(gen_dir, dry_run=self.dry_run) - # remove tool - if os.path.exists(gen_tool): - os.remove(gen_tool) - - -# my custom commands -cmdclass = { - "gen": GenCommand, - "clean_gen": CleanGenCommand, - "build_ext": my_build_ext, - "clean": my_clean, -} -command_options = {} - - -cython_file = "machine/emu.pyx" -sourcefiles = [ - "machine/traps.c", - "machine/mem.c", - "machine/musashi/m68kcpu.c", - "machine/musashi/m68kdasm.c", - "machine/musashi/softfloat/softfloat.c", - "gen/m68kops.c", -] -depends = [ - "machine/my_conf.h", - "machine/pycpu.pyx", - "machine/pymem.pyx", - "machine/pytraps.pyx", - "machine/musashi/m68k.h", - "machine/musashi/m68kcpu.h", - "machine/mem.h", - "machine/traps.h", - "machine/musashi/softfloat/mamesf.h", - "machine/musashi/softfloat/milieu.h", - "machine/musashi/softfloat/softfloat.h", - "machine/musashi/softfloat/softfloat-macros", - "machine/musashi/softfloat/softfloat-specialize", -] -inc_dirs = ["machine", "machine/musashi", "gen"] - -# add missing vc headers -if is_msvc: - inc_dirs.append("machine/win") - defines = [("_CRT_SECURE_NO_WARNINGS", None), ("_USE_MATH_DEFINES", None)] -else: - defines = [] -# use own musashi config file -defines.append(("MUSASHI_CNF", '"my_conf.h"')) - -extensions = [ - Extension( - "machine.emu", - sourcefiles, - depends=depends, - include_dirs=inc_dirs, - define_macros=defines, - ) -] - -# use cython? -if use_cython: - sourcefiles.append(cython_file) - extensions = cythonize(extensions, language_level="3str") -else: - sourcefiles.append(ext_file) - -setup( - cmdclass=cmdclass, - command_options=command_options, - ext_modules=extensions, -) +setup() diff --git a/test/unit/machine_emu_cpustate.py b/test/unit/machine_cpustate.py similarity index 78% rename from test/unit/machine_emu_cpustate.py rename to test/unit/machine_cpustate.py index 77fc4cf..beab2df 100644 --- a/test/unit/machine_emu_cpustate.py +++ b/test/unit/machine_cpustate.py @@ -1,11 +1,9 @@ -import pytest -from machine import emu -from machine.m68k import * -from amitools.vamos.machine import * +from amitools.vamos.machine import Machine, CPUState -def machine_emu_cpustate_rw_test(): - cpu = emu.CPU(M68K_CPU_TYPE_68000) +def machine_cpustate_rw_test(): + machine = Machine() + cpu = machine.cpu cpu.w_pc(0) cpu.w_sr(0x2700) for i in range(16): diff --git a/test/unit/machine_emu_cpu.py b/test/unit/machine_emu_cpu.py deleted file mode 100644 index 655193a..0000000 --- a/test/unit/machine_emu_cpu.py +++ /dev/null @@ -1,35 +0,0 @@ -import pytest -from machine import emu -from machine.m68k import * - - -def machine_emu_cpu_rw_reg_test(): - cpu = emu.CPU(M68K_CPU_TYPE_68000) - cpu.w_reg(M68K_REG_D0, 0xDEADBEEF) - assert cpu.r_reg(M68K_REG_D0) == 0xDEADBEEF - # invalid values - with pytest.raises(OverflowError): - cpu.w_reg(M68K_REG_D0, 0xDEADBEEF12) - with pytest.raises(OverflowError): - cpu.w_reg(M68K_REG_D0, -1) - with pytest.raises(TypeError): - cpu.w_reg(M68K_REG_D0, "hello") - - -def machine_emu_cpu_rws_reg_test(): - cpu = emu.CPU(M68K_CPU_TYPE_68000) - cpu.ws_reg(M68K_REG_D0, -123) - assert cpu.rs_reg(M68K_REG_D0) == -123 - # invalid values - with pytest.raises(OverflowError): - cpu.ws_reg(M68K_REG_D0, 0x80000000) - with pytest.raises(OverflowError): - cpu.ws_reg(M68K_REG_D0, -0x80000001) - with pytest.raises(TypeError): - cpu.ws_reg(M68K_REG_D0, "hello") - - -def machine_emu_cpu_rw_context_test(): - cpu = emu.CPU(M68K_CPU_TYPE_68000) - ctx = cpu.get_cpu_context() - cpu.set_cpu_context(ctx) diff --git a/test/unit/machine_emu_mem.py b/test/unit/machine_emu_mem.py deleted file mode 100644 index 1964566..0000000 --- a/test/unit/machine_emu_mem.py +++ /dev/null @@ -1,393 +0,0 @@ -import pytest -from machine import emu - - -def machine_emu_mem_rw_test(): - mem = emu.Memory(16) - assert mem.get_ram_size_kib() == 16 - - mem.w8(0x100, 42) - assert mem.r8(0x100) == 42 - - mem.w16(0x200, 0xDEAD) - assert mem.r16(0x200) == 0xDEAD - - mem.w32(0x300, 0xCAFEBABE) - assert mem.r32(0x300) == 0xCAFEBABE - - mem.write(0, 0x101, 43) - assert mem.read(0, 0x101) == 43 - - mem.write(1, 0x202, 0x1234) - assert mem.read(1, 0x202) == 0x1234 - - mem.write(2, 0x304, 0x11223344) - assert mem.read(2, 0x304) == 0x11223344 - - # invalid values - with pytest.raises(OverflowError): - mem.w8(0x100, 0x100) - with pytest.raises(OverflowError): - mem.w8(0x100, -1) - # invalid values - with pytest.raises(OverflowError): - mem.w16(0x100, 0x10000) - with pytest.raises(OverflowError): - mem.w16(0x100, -2) - # invalid values - with pytest.raises(OverflowError): - mem.w32(0x100, 0x100000000) - with pytest.raises(OverflowError): - mem.w32(0x100, -3) - # invalid type - with pytest.raises(TypeError): - mem.w8(0x100, "hello") - # invalid type - with pytest.raises(TypeError): - mem.w16(0x100, "hello") - # invalid type - with pytest.raises(TypeError): - mem.w32(0x100, "hello") - # invalid width - with pytest.raises(ValueError): - mem.write(7, 0x202, 12) - with pytest.raises(ValueError): - mem.read(7, 0x202) - - # out of range - with pytest.raises(emu.MemoryError): - mem.w8(0x10000, 0) - with pytest.raises(emu.MemoryError): - mem.w16(0x10000, 0) - with pytest.raises(emu.MemoryError): - mem.w32(0x10000, 0) - with pytest.raises(emu.MemoryError): - mem.write(0, 0x10000, 0) - with pytest.raises(emu.MemoryError): - mem.r8(0x10000) - with pytest.raises(emu.MemoryError): - mem.r16(0x10000) - with pytest.raises(emu.MemoryError): - mem.r32(0x10000) - with pytest.raises(emu.MemoryError): - mem.read(0, 0x10000) - - -def machine_emu_mem_rws_test(): - mem = emu.Memory(16) - - mem.w8s(0x100, 42) - assert mem.r8s(0x100) == 42 - mem.w8s(0x100, -23) - assert mem.r8s(0x100) == -23 - - mem.w16s(0x200, 0x7EAD) - assert mem.r16s(0x200) == 0x7EAD - mem.w16s(0x200, -0x1000) - assert mem.r16s(0x200) == -0x1000 - - mem.w32s(0x300, 0x1AFEBABE) - assert mem.r32s(0x300) == 0x1AFEBABE - mem.w32s(0x300, -0xAFEBABE) - assert mem.r32s(0x300) == -0xAFEBABE - - mem.writes(0, 0x101, -43) - assert mem.reads(0, 0x101) == -43 - mem.writes(1, 0x202, -0x1234) - assert mem.reads(1, 0x202) == -0x1234 - mem.writes(2, 0x304, -0x11223344) - assert mem.reads(2, 0x304) == -0x11223344 - - # invalid values - with pytest.raises(OverflowError): - mem.w8s(0x100, 0x80) - with pytest.raises(OverflowError): - mem.w8s(0x100, -0x81) - # invalid values - with pytest.raises(OverflowError): - mem.w16s(0x100, 0x8000) - with pytest.raises(OverflowError): - mem.w16s(0x100, -0x8001) - # invalid values - with pytest.raises(OverflowError): - mem.w32s(0x100, 0x80000000) - with pytest.raises(OverflowError): - mem.w32s(0x100, -0x80000001) - # invalid type - with pytest.raises(TypeError): - mem.w8s(0x100, "hello") - # invalid type - with pytest.raises(TypeError): - mem.w16s(0x100, "hello") - # invalid type - with pytest.raises(TypeError): - mem.w32s(0x100, "hello") - # invalid width - with pytest.raises(ValueError): - mem.writes(7, 0x202, 12) - with pytest.raises(ValueError): - mem.reads(7, 0x202) - - # out of range - with pytest.raises(emu.MemoryError): - mem.w8s(0x10000, 0) - with pytest.raises(emu.MemoryError): - mem.w16s(0x10000, 0) - with pytest.raises(emu.MemoryError): - mem.w32s(0x10000, 0) - with pytest.raises(emu.MemoryError): - mem.writes(0, 0x10000, 0) - with pytest.raises(emu.MemoryError): - mem.r8s(0x10000) - with pytest.raises(emu.MemoryError): - mem.r16s(0x10000) - with pytest.raises(emu.MemoryError): - mem.r32s(0x10000) - with pytest.raises(emu.MemoryError): - mem.reads(0, 0x10000) - - -class InvalidMemAccess(object): - def __init__(self, mem, mode, width, addr): - self.mem = mem - self.want = (mode, width, addr) - - def __enter__(self): - self.mem.set_invalid_func(self.invalid_func) - self.match = None - return self - - def __exit__(self, type, value, traceback): - self.mem.set_invalid_func(None) - assert self.match == self.want - - def invalid_func(self, mode, width, addr): - self.match = (mode, width, addr) - - -def machine_emu_mem_cpu_rw_test(): - mem = emu.Memory(16) - assert mem.get_ram_size_kib() == 16 - - mem.cpu_w8(0x100, 42) - assert mem.cpu_r8(0x100) == 42 - - mem.cpu_w16(0x200, 0xDEAD) - assert mem.cpu_r16(0x200) == 0xDEAD - - mem.cpu_w32(0x300, 0xCAFEBABE) - assert mem.cpu_r32(0x300) == 0xCAFEBABE - - # invalid values - with pytest.raises(OverflowError): - mem.cpu_w8(0x100, 0x100) - with pytest.raises(OverflowError): - mem.cpu_w8(0x100, -1) - # invalid values - with pytest.raises(OverflowError): - mem.cpu_w16(0x100, 0x10000) - with pytest.raises(OverflowError): - mem.cpu_w16(0x100, -2) - # invalid values - with pytest.raises(OverflowError): - mem.cpu_w32(0x100, 0x100000000) - with pytest.raises(OverflowError): - mem.cpu_w32(0x100, -3) - # invalid type - with pytest.raises(TypeError): - mem.cpu_w8(0x100, "hello") - # invalid type - with pytest.raises(TypeError): - mem.cpu_w16(0x100, "hello") - # invalid type - with pytest.raises(TypeError): - mem.cpu_w32(0x100, "hello") - - # out of range - with InvalidMemAccess(mem, "W", 0, 0x10000): - mem.cpu_w8(0x10000, 0) - with InvalidMemAccess(mem, "W", 1, 0x10000): - mem.cpu_w16(0x10000, 0) - with InvalidMemAccess(mem, "W", 2, 0x10000): - mem.cpu_w32(0x10000, 0) - with InvalidMemAccess(mem, "R", 0, 0x10000): - mem.cpu_r8(0x10000) - with InvalidMemAccess(mem, "R", 1, 0x10000): - mem.cpu_r16(0x10000) - with InvalidMemAccess(mem, "R", 2, 0x10000): - mem.cpu_r32(0x10000) - - -def machine_emu_mem_cpu_rws_test(): - mem = emu.Memory(16) - - mem.cpu_w8s(0x100, 42) - assert mem.cpu_r8s(0x100) == 42 - mem.cpu_w8s(0x100, -23) - assert mem.cpu_r8s(0x100) == -23 - - mem.cpu_w16s(0x200, 0x7EAD) - assert mem.cpu_r16s(0x200) == 0x7EAD - mem.cpu_w16s(0x200, -0x1000) - assert mem.cpu_r16s(0x200) == -0x1000 - - mem.cpu_w32s(0x300, 0x1AFEBABE) - assert mem.cpu_r32s(0x300) == 0x1AFEBABE - mem.cpu_w32s(0x300, -0xAFEBABE) - assert mem.cpu_r32s(0x300) == -0xAFEBABE - - # invalid values - with pytest.raises(OverflowError): - mem.cpu_w8s(0x100, 0x80) - with pytest.raises(OverflowError): - mem.cpu_w8s(0x100, -0x81) - # invalid values - with pytest.raises(OverflowError): - mem.cpu_w16s(0x100, 0x8000) - with pytest.raises(OverflowError): - mem.cpu_w16s(0x100, -0x8001) - # invalid values - with pytest.raises(OverflowError): - mem.cpu_w32s(0x100, 0x80000000) - with pytest.raises(OverflowError): - mem.cpu_w32s(0x100, -0x80000001) - # invalid type - with pytest.raises(TypeError): - mem.cpu_w8s(0x100, "hello") - # invalid type - with pytest.raises(TypeError): - mem.cpu_w16s(0x100, "hello") - # invalid type - with pytest.raises(TypeError): - mem.cpu_w32s(0x100, "hello") - - # out of range - with InvalidMemAccess(mem, "W", 0, 0x10000): - mem.cpu_w8s(0x10000, 0) - with InvalidMemAccess(mem, "W", 1, 0x10000): - mem.cpu_w16s(0x10000, 0) - with InvalidMemAccess(mem, "W", 2, 0x10000): - mem.cpu_w32s(0x10000, 0) - with InvalidMemAccess(mem, "R", 0, 0x10000): - mem.cpu_r8s(0x10000) - with InvalidMemAccess(mem, "R", 1, 0x10000): - mem.cpu_r16s(0x10000) - with InvalidMemAccess(mem, "R", 2, 0x10000): - mem.cpu_r32s(0x10000) - - -def machine_emu_mem_block_test(): - mem = emu.Memory(16) - data = b"hello, world!" - mem.w_block(0, data) - assert mem.r_block(0, len(data)) == data - bdata = bytearray(data) - mem.w_block(0x100, bdata) - assert mem.r_block(0x100, len(bdata)) == bdata - mem.clear_block(0x200, 100, 42) - assert mem.r_block(0x200, 100) == bytes([42] * 100) - mem.copy_block(0x200, 0x300, 20) - assert mem.r_block(0x300, 21) == bytes([42] * 20) + b"\0" - - -def machine_emu_mem_cstr_test(): - mem = emu.Memory(16) - data = "hello, world" - mem.w_cstr(0, data) - assert mem.r_cstr(0) == data - empty = "" - mem.w_cstr(100, empty) - assert mem.r_cstr(100) == empty - - -def machine_emu_mem_bstr_test(): - mem = emu.Memory(16) - data = "hello, world" - mem.w_bstr(0, data) - assert mem.r_bstr(0) == data - empty = "" - mem.w_bstr(100, empty) - assert mem.r_bstr(100) == empty - - -class TraceAssert(object): - def __init__(self, mem, mode, width, addr, value): - self.mem = mem - self.want = (mode, width, addr, value) - - def __enter__(self): - self.mem.set_trace_mode(True) - self.mem.set_trace_func(self.trace_func) - self.match = None - return self - - def __exit__(self, type, value, traceback): - self.mem.set_trace_mode(False) - self.mem.set_trace_func(None) - assert self.match == self.want - - def trace_func(self, mode, width, addr, value): - self.match = (mode, width, addr, value) - - -def machine_emu_mem_trace_test(): - mem = emu.Memory(16) - with TraceAssert(mem, "R", 0, 0x100, 0): - mem.cpu_r8(0x100) - with TraceAssert(mem, "R", 1, 0x100, 0): - mem.cpu_r16(0x100) - with TraceAssert(mem, "R", 2, 0x100, 0): - mem.cpu_r32(0x100) - with TraceAssert(mem, "W", 0, 0x100, 0x42): - mem.cpu_w8(0x100, 0x42) - with TraceAssert(mem, "W", 1, 0x100, 0xDEAD): - mem.cpu_w16(0x100, 0xDEAD) - with TraceAssert(mem, "W", 2, 0x100, 0xCAFEBABE): - mem.cpu_w32(0x100, 0xCAFEBABE) - - -def machine_emu_mem_trace_error_test(): - mem = emu.Memory(16) - - def trace_func(mode, width, addr, value): - raise ValueError("bonk!") - - mem.set_trace_mode(True) - mem.set_trace_func(trace_func) - with pytest.raises(ValueError): - mem.cpu_r8(0x100) - with pytest.raises(ValueError): - mem.cpu_w8(0x100, 0) - mem.set_trace_mode(False) - mem.set_trace_func(None) - - -def machine_emu_mem_invalid_access_error_test(): - mem = emu.Memory(16) - - def invalid_func(mode, width, addr): - raise ValueError("bonk!") - - mem.set_invalid_func(invalid_func) - with pytest.raises(ValueError): - mem.cpu_r8(0x100000) - with pytest.raises(ValueError): - mem.cpu_w8(0x100000, 0) - mem.set_invalid_func(None) - - -def machine_emu_mem_special_rw_error_test(): - mem = emu.Memory(16) - - def read(addr): - raise ValueError("blonk!") - - def write(addr, val): - raise ValueError("blonk!") - - mem.set_special_range_read_funcs(0xBF0000, 1, read, None, None) - mem.set_special_range_write_funcs(0xBF0000, 1, write, None, None) - with pytest.raises(ValueError): - mem.cpu_r8(0xBF0000) - with pytest.raises(ValueError): - mem.cpu_w8(0xBF0000, 42) diff --git a/test/unit/machine_emu_traps.py b/test/unit/machine_emu_traps.py deleted file mode 100644 index f57a7cc..0000000 --- a/test/unit/machine_emu_traps.py +++ /dev/null @@ -1,43 +0,0 @@ -import pytest -import traceback -import sys -from machine import emu -from machine.m68k import * - - -def machine_emu_traps_trigger_test(): - traps = emu.Traps() - a = [] - - def my_func(opcode, pc): - a.append(opcode) - a.append(pc) - - tid = traps.setup(my_func) - assert tid >= 0 - traps.trigger(tid, 23) - assert a == [tid, 23] - traps.free(tid) - - -def machine_emu_traps_raise_test(): - traps = emu.Traps() - a = [] - b = [] - - def exc_func(opcode, pc): - a.append(opcode) - a.append(pc) - b.append(sys.exc_info()) - - traps.set_exc_func(exc_func) - - def my_func(opcode, pc): - raise ValueError("bla") - - tid = traps.setup(my_func) - assert tid >= 0 - traps.trigger(tid, 23) - assert a == [tid, 23] - assert b[0][0] == ValueError - traps.free(tid) diff --git a/test/unit/machine_machine.py b/test/unit/machine_machine.py index 3aab95d..e0f3348 100644 --- a/test/unit/machine_machine.py +++ b/test/unit/machine_machine.py @@ -1,4 +1,5 @@ -from amitools.vamos.machine import Machine, CPUState +from machine68k import CPUType +from amitools.vamos.machine import Machine from amitools.vamos.machine.opcodes import * from amitools.vamos.error import * from amitools.vamos.log import log_machine @@ -9,7 +10,7 @@ import logging log_machine.setLevel(logging.DEBUG) -def create_machine(cpu_type=Machine.CPU_TYPE_68000): +def create_machine(cpu_type=CPUType.M68000): m = Machine(cpu_type, raise_on_main_run=False) cpu = m.get_cpu() mem = m.get_mem() @@ -222,7 +223,7 @@ def machine_machine_cfg_test(): ) m = Machine.from_cfg(cfg, True) assert m - assert m.get_cpu_type() == Machine.CPU_TYPE_68020 + assert m.get_cpu_type() == CPUType.M68020 assert m.get_cpu_name() == "68020" assert m.get_ram_total_kib() == 2048 assert m.max_cycles == 128