From 6f22e7679b54606c8d5163a5016df71b93a1e541 Mon Sep 17 00:00:00 2001 From: espes Date: Sun, 5 Apr 2015 13:55:22 -0700 Subject: [PATCH] import hatari dsp --- hw/xbox/dsp/dsp.c | 799 ++++ hw/xbox/dsp/dsp.h | 77 + hw/xbox/dsp/dsp_core.c | 704 +++ hw/xbox/dsp/dsp_core.h | 275 ++ hw/xbox/dsp/dsp_cpu.c | 8984 ++++++++++++++++++++++++++++++++++++++ hw/xbox/dsp/dsp_cpu.h | 125 + hw/xbox/dsp/dsp_disasm.c | 2341 ++++++++++ hw/xbox/dsp/dsp_disasm.h | 47 + 8 files changed, 13352 insertions(+) create mode 100644 hw/xbox/dsp/dsp.c create mode 100644 hw/xbox/dsp/dsp.h create mode 100644 hw/xbox/dsp/dsp_core.c create mode 100644 hw/xbox/dsp/dsp_core.h create mode 100644 hw/xbox/dsp/dsp_cpu.c create mode 100644 hw/xbox/dsp/dsp_cpu.h create mode 100644 hw/xbox/dsp/dsp_disasm.c create mode 100644 hw/xbox/dsp/dsp_disasm.h diff --git a/hw/xbox/dsp/dsp.c b/hw/xbox/dsp/dsp.c new file mode 100644 index 0000000000..51a082446d --- /dev/null +++ b/hw/xbox/dsp/dsp.c @@ -0,0 +1,799 @@ +/* + DSP M56001 emulation + Dummy emulation, Hatari glue + + (C) 2001-2008 ARAnyM developer team + Adaption to Hatari (C) 2008 by Thomas Huth + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include + +#include "main.h" +#include "sysdeps.h" +#include "newcpu.h" +#include "memorySnapShot.h" +#include "ioMem.h" +#include "dsp.h" +#include "crossbar.h" +#include "configuration.h" +#include "cycInt.h" +#include "m68000.h" + +#if ENABLE_DSP_EMU +#include "debugdsp.h" +#include "dsp_cpu.h" +#include "dsp_disasm.h" +#endif + +#define DEBUG 0 +#if DEBUG +#define Dprintf(a) printf a +#else +#define Dprintf(a) +#endif + +#define DSP_HW_OFFSET 0xFFA200 + + +#if ENABLE_DSP_EMU +static const char* x_ext_memory_addr_name[] = { + "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", + "PBC", "PCC", "PBDDR", "PCDDR", "PBD", "PCD", "", "", + "HCR", "HSR", "", "HRX/HTX", "CRA", "CRB", "SSISR/TSR", "RX/TX", + "SCR", "SSR", "SCCR", "STXA", "SRX/STX", "SRX/STX", "SRX/STX", "", + "", "", "", "", "", "", "BCR", "IPR" +}; + +static Sint32 save_cycles; +#endif + +static bool bDspDebugging; + +bool bDspEnabled = false; +bool bDspHostInterruptPending = false; + + +/** + * Trigger HREQ interrupt at the host CPU. + */ +#if ENABLE_DSP_EMU +static void DSP_TriggerHostInterrupt(void) +{ + bDspHostInterruptPending = true; + M68000_SetSpecial(SPCFLAG_DSP); +} +#endif + + +/** + * This function is called from the CPU emulation part when SPCFLAG_DSP is set. + * If the DSP's IRQ signal is set, we check that SR allows a level 6 interrupt, + * and if so, we call M68000_Exception. + */ +#if ENABLE_DSP_EMU +bool DSP_ProcessIRQ(void) +{ + if (bDspHostInterruptPending && regs.intmask < 6) + { + M68000_Exception(IoMem_ReadByte(0xffa203)*4, M68000_EXC_SRC_INT_DSP); + bDspHostInterruptPending = false; + M68000_UnsetSpecial(SPCFLAG_DSP); + return true; + } + + return false; +} +#endif + + +/** + * Initialize the DSP emulation + */ +void DSP_Init(void) +{ +#if ENABLE_DSP_EMU + if (bDspEnabled || ConfigureParams.System.nDSPType != DSP_TYPE_EMU) + return; + dsp_core_init(DSP_TriggerHostInterrupt); + dsp56k_init_cpu(); + bDspEnabled = true; + save_cycles = 0; +#endif +} + + +/** + * Shut down the DSP emulation + */ +void DSP_UnInit(void) +{ +#if ENABLE_DSP_EMU + if (!bDspEnabled) + return; + dsp_core_shutdown(); + bDspEnabled = false; +#endif +} + + +/** + * Reset the DSP emulation + */ +void DSP_Reset(void) +{ +#if ENABLE_DSP_EMU + dsp_core_reset(); + bDspHostInterruptPending = false; + save_cycles = 0; +#endif +} + + +/** + * Save/Restore snapshot of CPU variables ('MemorySnapShot_Store' handles type) + */ +void DSP_MemorySnapShot_Capture(bool bSave) +{ +#if ENABLE_DSP_EMU + if (!bSave) + DSP_Reset(); + + MemorySnapShot_Store(&bDspEnabled, sizeof(bDspEnabled)); + MemorySnapShot_Store(&dsp_core, sizeof(dsp_core)); + MemorySnapShot_Store(&save_cycles, sizeof(save_cycles)); +#endif +} + +/** + * Run DSP for certain cycles + */ +void DSP_Run(int nHostCycles) +{ +#if ENABLE_DSP_EMU + save_cycles += nHostCycles * 2; + + if (dsp_core.running == 0) + return; + + if (save_cycles <= 0) + return; + + if (unlikely(bDspDebugging)) { + while (save_cycles > 0) + { + dsp56k_execute_instruction(); + save_cycles -= dsp_core.instr_cycle; + DebugDsp_Check(); + } + } else { + // fprintf(stderr, "--> %d\n", save_cycles); + while (save_cycles > 0) + { + dsp56k_execute_instruction(); + save_cycles -= dsp_core.instr_cycle; + } + } + +#endif +} + +/** + * Enable/disable DSP debugging mode + */ +void DSP_SetDebugging(bool enabled) +{ + bDspDebugging = enabled; +} + +/** + * Get DSP program counter (for debugging) + */ +Uint16 DSP_GetPC(void) +{ +#if ENABLE_DSP_EMU + if (bDspEnabled) + return dsp_core.pc; + else +#endif + return 0; +} + +/** + * Get next DSP PC without output (for debugging) + */ +Uint16 DSP_GetNextPC(Uint16 pc) +{ +#if ENABLE_DSP_EMU + /* code is reduced copy from dsp56k_execute_one_disasm_instruction() */ + dsp_core_t dsp_core_save; + Uint16 instruction_length; + + if (!bDspEnabled) + return 0; + + /* Save DSP context */ + memcpy(&dsp_core_save, &dsp_core, sizeof(dsp_core)); + + /* Disasm instruction */ + dsp_core.pc = pc; + /* why dsp56k_execute_one_disasm_instruction() does "-1" + * for this value, that doesn't seem right??? + */ + instruction_length = dsp56k_disasm(DSP_DISASM_MODE); + + /* Restore DSP context */ + memcpy(&dsp_core, &dsp_core_save, sizeof(dsp_core)); + + return pc + instruction_length; +#else + return 0; +#endif +} + +/** + * Get current DSP instruction cycles (for profiling) + */ +Uint16 DSP_GetInstrCycles(void) +{ +#if ENABLE_DSP_EMU + if (bDspEnabled) + return dsp_core.instr_cycle; + else +#endif + return 0; +} + + +/** + * Disassemble DSP code between given addresses, return next PC address + */ +Uint16 DSP_DisasmAddress(FILE *out, Uint16 lowerAdr, Uint16 UpperAdr) +{ +#if ENABLE_DSP_EMU + Uint16 dsp_pc; + + for (dsp_pc=lowerAdr; dsp_pc<=UpperAdr; dsp_pc++) { + dsp_pc += dsp56k_execute_one_disasm_instruction(out, dsp_pc); + } + return dsp_pc; +#else + return 0; +#endif +} + + +/** + * Get the value from the given (16-bit) DSP memory address / space + * exactly the same way as in dsp_cpu.c::read_memory() (except for + * the host/transmit peripheral register values which access has + * side-effects). Set the mem_str to suitable string for that + * address / space. + * Return the value at given address. For valid values AND the return + * value with BITMASK(24). + */ +Uint32 DSP_ReadMemory(Uint16 address, char space_id, const char **mem_str) +{ +#if ENABLE_DSP_EMU + static const char *spaces[3][4] = { + { "X ram", "X rom", "X", "X periph" }, + { "Y ram", "Y rom", "Y", "Y periph" }, + { "P ram", "P ram", "P ext memory", "P ext memory" } + }; + int idx, space; + + switch (space_id) { + case 'X': + space = DSP_SPACE_X; + idx = 0; + break; + case 'Y': + space = DSP_SPACE_Y; + idx = 1; + break; + case 'P': + space = DSP_SPACE_P; + idx = 2; + break; + default: + space = DSP_SPACE_X; + idx = 0; + } + address &= 0xFFFF; + + /* Internal RAM ? */ + if (address < 0x100) { + *mem_str = spaces[idx][0]; + return dsp_core.ramint[space][address]; + } + + if (space == DSP_SPACE_P) { + /* Internal RAM ? */ + if (address < 0x200) { + *mem_str = spaces[idx][0]; + return dsp_core.ramint[DSP_SPACE_P][address]; + } + /* External RAM, mask address to available ram size */ + *mem_str = spaces[idx][2]; + return dsp_core.ramext[address & (DSP_RAMSIZE-1)]; + } + + /* Internal ROM ? */ + if (address < 0x200) { + if (dsp_core.registers[DSP_REG_OMR] & (1<= 0xffc0) { + *mem_str = spaces[idx][3]; + /* reading host/transmit regs has side-effects, + * so just give the memory value. + */ + return dsp_core.periph[space][address-0xffc0]; + } + + /* Falcon: External RAM, map X to upper 16K of matching space in Y,P */ + address &= (DSP_RAMSIZE>>1) - 1; + if (space == DSP_SPACE_X) { + address += DSP_RAMSIZE>>1; + } + + /* Falcon: External RAM, finally map X,Y to P */ + *mem_str = spaces[idx][2]; + return dsp_core.ramext[address & (DSP_RAMSIZE-1)]; +#endif + return 0; +} + + +/** + * Output memory values between given addresses in given DSP address space. + * Return next DSP address value. + */ +Uint16 DSP_DisasmMemory(Uint16 dsp_memdump_addr, Uint16 dsp_memdump_upper, char space) +{ +#if ENABLE_DSP_EMU + Uint32 mem, mem2, value; + const char *mem_str; + + for (mem = dsp_memdump_addr; mem <= dsp_memdump_upper; mem++) { + /* special printing of host communication/transmit registers */ + if (space == 'X' && mem >= 0xffc0) { + if (mem == 0xffeb) { + fprintf(stderr,"X periph:%04x HTX : %06x RTX:%06x\n", + mem, dsp_core.dsp_host_htx, dsp_core.dsp_host_rtx); + } + else if (mem == 0xffef) { + fprintf(stderr,"X periph:%04x SSI TX : %06x SSI RX:%06x\n", + mem, dsp_core.ssi.transmit_value, dsp_core.ssi.received_value); + } + else { + value = DSP_ReadMemory(mem, space, &mem_str); + fprintf(stderr,"%s:%04x %06x\t%s\n", mem_str, mem, value, x_ext_memory_addr_name[mem-0xffc0]); + } + continue; + } + /* special printing of X & Y external RAM values */ + if ((space == 'X' || space == 'Y') && + mem >= 0x200 && mem < 0xffc0) { + mem2 = mem & ((DSP_RAMSIZE>>1)-1); + if (space == 'X') { + mem2 += (DSP_RAMSIZE>>1); + } + fprintf(stderr,"%c:%04x (P:%04x): %06x\n", space, + mem, mem2, dsp_core.ramext[mem2 & (DSP_RAMSIZE-1)]); + continue; + } + value = DSP_ReadMemory(mem, space, &mem_str); + fprintf(stderr,"%s:%04x %06x\n", mem_str, mem, value); + } +#endif + return dsp_memdump_upper+1; +} + +/** + * Show information on DSP core state which isn't + * shown by any of the other commands (dd, dm, dr). + */ +void DSP_Info(Uint32 dummy) +{ +#if ENABLE_DSP_EMU + int i, j; + const char *stackname[] = { "SSH", "SSL" }; + + fputs("DSP core information:\n", stderr); + + for (i = 0; i < ARRAYSIZE(stackname); i++) { + fprintf(stderr, "- %s stack:", stackname[i]); + for (j = 0; j < ARRAYSIZE(dsp_core.stack[0]); j++) { + fprintf(stderr, " %04hx", dsp_core.stack[i][j]); + } + fputs("\n", stderr); + } + + fprintf(stderr, "- Interrupt IPL:"); + for (i = 0; i < ARRAYSIZE(dsp_core.interrupt_ipl); i++) { + fprintf(stderr, " %04hx", dsp_core.interrupt_ipl[i]); + } + fputs("\n", stderr); + + fprintf(stderr, "- Pending ints: "); + for (i = 0; i < ARRAYSIZE(dsp_core.interrupt_isPending); i++) { + fprintf(stderr, " %04hx", dsp_core.interrupt_isPending[i]); + } + fputs("\n", stderr); + + fprintf(stderr, "- Hostport:"); + for (i = 0; i < ARRAYSIZE(dsp_core.hostport); i++) { + fprintf(stderr, " %02x", dsp_core.hostport[i]); + } + fputs("\n", stderr); +#endif +} + +/** + * Show DSP register contents + */ +void DSP_DisasmRegisters(void) +{ +#if ENABLE_DSP_EMU + Uint32 i; + + fprintf(stderr,"A: A2: %02x A1: %06x A0: %06x\n", + dsp_core.registers[DSP_REG_A2], dsp_core.registers[DSP_REG_A1], dsp_core.registers[DSP_REG_A0]); + fprintf(stderr,"B: B2: %02x B1: %06x B0: %06x\n", + dsp_core.registers[DSP_REG_B2], dsp_core.registers[DSP_REG_B1], dsp_core.registers[DSP_REG_B0]); + + fprintf(stderr,"X: X1: %06x X0: %06x\n", dsp_core.registers[DSP_REG_X1], dsp_core.registers[DSP_REG_X0]); + fprintf(stderr,"Y: Y1: %06x Y0: %06x\n", dsp_core.registers[DSP_REG_Y1], dsp_core.registers[DSP_REG_Y0]); + + for (i=0; i<8; i++) { + fprintf(stderr,"R%01x: %04x N%01x: %04x M%01x: %04x\n", + i, dsp_core.registers[DSP_REG_R0+i], + i, dsp_core.registers[DSP_REG_N0+i], + i, dsp_core.registers[DSP_REG_M0+i]); + } + + fprintf(stderr,"LA: %04x LC: %04x PC: %04x\n", dsp_core.registers[DSP_REG_LA], dsp_core.registers[DSP_REG_LC], dsp_core.pc); + fprintf(stderr,"SR: %04x OMR: %02x\n", dsp_core.registers[DSP_REG_SR], dsp_core.registers[DSP_REG_OMR]); + fprintf(stderr,"SP: %02x SSH: %04x SSL: %04x\n", + dsp_core.registers[DSP_REG_SP], dsp_core.registers[DSP_REG_SSH], dsp_core.registers[DSP_REG_SSL]); +#endif +} + + +/** + * Get given DSP register address and required bit mask. + * Works for A0-2, B0-2, LA, LC, M0-7, N0-7, R0-7, X0-1, Y0-1, PC, SR, SP, + * OMR, SSH & SSL registers, but note that the SP, SSH & SSL registers + * need special handling (in DSP*SetRegister()) when they are set. + * Return the register width in bits or zero for an error. + */ +int DSP_GetRegisterAddress(const char *regname, Uint32 **addr, Uint32 *mask) +{ +#if ENABLE_DSP_EMU +#define MAX_REGNAME_LEN 4 + typedef struct { + const char name[MAX_REGNAME_LEN]; + Uint32 *addr; + size_t bits; + Uint32 mask; + } reg_addr_t; + + /* sorted by name so that this can be bisected */ + static const reg_addr_t registers[] = { + + /* 56-bit A register */ + { "A0", &dsp_core.registers[DSP_REG_A0], 32, BITMASK(24) }, + { "A1", &dsp_core.registers[DSP_REG_A1], 32, BITMASK(24) }, + { "A2", &dsp_core.registers[DSP_REG_A2], 32, BITMASK(8) }, + + /* 56-bit B register */ + { "B0", &dsp_core.registers[DSP_REG_B0], 32, BITMASK(24) }, + { "B1", &dsp_core.registers[DSP_REG_B1], 32, BITMASK(24) }, + { "B2", &dsp_core.registers[DSP_REG_B2], 32, BITMASK(8) }, + + /* 16-bit LA & LC registers */ + { "LA", &dsp_core.registers[DSP_REG_LA], 32, BITMASK(16) }, + { "LC", &dsp_core.registers[DSP_REG_LC], 32, BITMASK(16) }, + + /* 16-bit M registers */ + { "M0", &dsp_core.registers[DSP_REG_M0], 32, BITMASK(16) }, + { "M1", &dsp_core.registers[DSP_REG_M1], 32, BITMASK(16) }, + { "M2", &dsp_core.registers[DSP_REG_M2], 32, BITMASK(16) }, + { "M3", &dsp_core.registers[DSP_REG_M3], 32, BITMASK(16) }, + { "M4", &dsp_core.registers[DSP_REG_M4], 32, BITMASK(16) }, + { "M5", &dsp_core.registers[DSP_REG_M5], 32, BITMASK(16) }, + { "M6", &dsp_core.registers[DSP_REG_M6], 32, BITMASK(16) }, + { "M7", &dsp_core.registers[DSP_REG_M7], 32, BITMASK(16) }, + + /* 16-bit N registers */ + { "N0", &dsp_core.registers[DSP_REG_N0], 32, BITMASK(16) }, + { "N1", &dsp_core.registers[DSP_REG_N1], 32, BITMASK(16) }, + { "N2", &dsp_core.registers[DSP_REG_N2], 32, BITMASK(16) }, + { "N3", &dsp_core.registers[DSP_REG_N3], 32, BITMASK(16) }, + { "N4", &dsp_core.registers[DSP_REG_N4], 32, BITMASK(16) }, + { "N5", &dsp_core.registers[DSP_REG_N5], 32, BITMASK(16) }, + { "N6", &dsp_core.registers[DSP_REG_N6], 32, BITMASK(16) }, + { "N7", &dsp_core.registers[DSP_REG_N7], 32, BITMASK(16) }, + + { "OMR", &dsp_core.registers[DSP_REG_OMR], 32, 0x5f }, + + /* 16-bit program counter */ + { "PC", (Uint32*)(&dsp_core.pc), 16, BITMASK(16) }, + + /* 16-bit DSP R (address) registers */ + { "R0", &dsp_core.registers[DSP_REG_R0], 32, BITMASK(16) }, + { "R1", &dsp_core.registers[DSP_REG_R1], 32, BITMASK(16) }, + { "R2", &dsp_core.registers[DSP_REG_R2], 32, BITMASK(16) }, + { "R3", &dsp_core.registers[DSP_REG_R3], 32, BITMASK(16) }, + { "R4", &dsp_core.registers[DSP_REG_R4], 32, BITMASK(16) }, + { "R5", &dsp_core.registers[DSP_REG_R5], 32, BITMASK(16) }, + { "R6", &dsp_core.registers[DSP_REG_R6], 32, BITMASK(16) }, + { "R7", &dsp_core.registers[DSP_REG_R7], 32, BITMASK(16) }, + + { "SSH", &dsp_core.registers[DSP_REG_SSH], 32, BITMASK(16) }, + { "SSL", &dsp_core.registers[DSP_REG_SSL], 32, BITMASK(16) }, + { "SP", &dsp_core.registers[DSP_REG_SP], 32, BITMASK(6) }, + + /* 16-bit status register */ + { "SR", &dsp_core.registers[DSP_REG_SR], 32, 0xefff }, + + /* 48-bit X register */ + { "X0", &dsp_core.registers[DSP_REG_X0], 32, BITMASK(24) }, + { "X1", &dsp_core.registers[DSP_REG_X1], 32, BITMASK(24) }, + + /* 48-bit Y register */ + { "Y0", &dsp_core.registers[DSP_REG_Y0], 32, BITMASK(24) }, + { "Y1", &dsp_core.registers[DSP_REG_Y1], 32, BITMASK(24) } + }; + /* left, right, middle, direction */ + int l, r, m, dir = 0; + unsigned int i, len; + char reg[MAX_REGNAME_LEN]; + + if (!bDspEnabled) { + return 0; + } + + for (i = 0; i < sizeof(reg) && regname[i]; i++) { + reg[i] = toupper(regname[i]); + } + if (i < 2 || regname[i]) { + /* too short or longer than any of the names */ + return 0; + } + len = i; + + /* bisect */ + l = 0; + r = ARRAYSIZE(registers) - 1; + do { + m = (l+r) >> 1; + for (i = 0; i < len; i++) { + dir = (int)reg[i] - registers[m].name[i]; + if (dir) { + break; + } + } + if (dir == 0) { + *addr = registers[m].addr; + *mask = registers[m].mask; + return registers[m].bits; + } + if (dir < 0) { + r = m-1; + } else { + l = m+1; + } + } while (l <= r); +#undef MAX_REGNAME_LEN +#endif + return 0; +} + + +/** + * Set given DSP register value, return false if unknown register given + */ +bool DSP_Disasm_SetRegister(const char *arg, Uint32 value) +{ +#if ENABLE_DSP_EMU + Uint32 *addr, mask, sp_value; + int bits; + + /* first check registers needing special handling... */ + if (arg[0]=='S' || arg[0]=='s') { + if (arg[1]=='P' || arg[1]=='p') { + dsp_core.registers[DSP_REG_SP] = value & BITMASK(6); + value &= BITMASK(4); + dsp_core.registers[DSP_REG_SSH] = dsp_core.stack[0][value]; + dsp_core.registers[DSP_REG_SSL] = dsp_core.stack[1][value]; + return true; + } + if (arg[1]=='S' || arg[1]=='s') { + sp_value = dsp_core.registers[DSP_REG_SP] & BITMASK(4); + if (arg[2]=='H' || arg[2]=='h') { + if (sp_value == 0) { + dsp_core.registers[DSP_REG_SSH] = 0; + dsp_core.stack[0][sp_value] = 0; + } else { + dsp_core.registers[DSP_REG_SSH] = value & BITMASK(16); + dsp_core.stack[0][sp_value] = value & BITMASK(16); + } + return true; + } + if (arg[2]=='L' || arg[2]=='l') { + if (sp_value == 0) { + dsp_core.registers[DSP_REG_SSL] = 0; + dsp_core.stack[1][sp_value] = 0; + } else { + dsp_core.registers[DSP_REG_SSL] = value & BITMASK(16); + dsp_core.stack[1][sp_value] = value & BITMASK(16); + } + return true; + } + } + } + + /* ...then registers where address & mask are enough */ + bits = DSP_GetRegisterAddress(arg, &addr, &mask); + switch (bits) { + case 32: + *addr = value & mask; + return true; + case 16: + *(Uint16*)addr = value & mask; + return true; + } +#endif + return false; +} + +/** + * Read SSI transmit value + */ +Uint32 DSP_SsiReadTxValue(void) +{ +#if ENABLE_DSP_EMU + return dsp_core.ssi.transmit_value; +#else + return 0; +#endif +} + +/** + * Write SSI receive value + */ +void DSP_SsiWriteRxValue(Uint32 value) +{ +#if ENABLE_DSP_EMU + dsp_core.ssi.received_value = value & 0xffffff; +#endif +} + +/** + * Signal SSI clock tick to DSP + */ + +void DSP_SsiReceive_SC0(void) +{ +#if ENABLE_DSP_EMU + dsp_core_ssi_Receive_SC0(); +#endif +} + +void DSP_SsiTransmit_SC0(void) +{ +#if ENABLE_DSP_EMU +#endif +} + +void DSP_SsiReceive_SC1(Uint32 FrameCounter) +{ +#if ENABLE_DSP_EMU + dsp_core_ssi_Receive_SC1(FrameCounter); +#endif +} + +void DSP_SsiTransmit_SC1(void) +{ +#if ENABLE_DSP_EMU + Crossbar_DmaPlayInHandShakeMode(); +#endif +} + +void DSP_SsiReceive_SC2(Uint32 FrameCounter) +{ +#if ENABLE_DSP_EMU + dsp_core_ssi_Receive_SC2(FrameCounter); +#endif +} + +void DSP_SsiTransmit_SC2(Uint32 frame) +{ +#if ENABLE_DSP_EMU + Crossbar_DmaRecordInHandShakeMode_Frame(frame); +#endif +} + +void DSP_SsiReceive_SCK(void) +{ +#if ENABLE_DSP_EMU + dsp_core_ssi_Receive_SCK(); +#endif +} + +void DSP_SsiTransmit_SCK(void) +{ +#if ENABLE_DSP_EMU +#endif +} + +/** + * Read access wrapper for ioMemTabFalcon (DSP Host port) + * DSP Host interface port is accessed by the 68030 in Byte mode. + * A move.w value,$ffA206 results in 2 bus access for the 68030. + */ +void DSP_HandleReadAccess(void) +{ + Uint32 addr; + Uint8 value; + bool multi_access = false; + + for (addr = IoAccessBaseAddress; addr < IoAccessBaseAddress+nIoMemAccessSize; addr++) + { +#if ENABLE_DSP_EMU + value = dsp_core_read_host(addr-DSP_HW_OFFSET); +#else + /* this value prevents TOS from hanging in the DSP init code */ + value = 0xff; +#endif + if (multi_access == true) + M68000_AddCycles(4); + multi_access = true; + + Dprintf(("HWget_b(0x%08x)=0x%02x at 0x%08x\n", addr, value, m68k_getpc())); + IoMem_WriteByte(addr, value); + } +} + +/** + * Write access wrapper for ioMemTabFalcon (DSP Host port) + * DSP Host interface port is accessed by the 68030 in Byte mode. + * A move.w value,$ffA206 results in 2 bus access for the 68030. + */ +void DSP_HandleWriteAccess(void) +{ + Uint32 addr; + bool multi_access = false; + + for (addr = IoAccessBaseAddress; addr < IoAccessBaseAddress+nIoMemAccessSize; addr++) + { +#if ENABLE_DSP_EMU + Uint8 value = IoMem_ReadByte(addr); + Dprintf(("HWput_b(0x%08x,0x%02x) at 0x%08x\n", addr, value, m68k_getpc())); + dsp_core_write_host(addr-DSP_HW_OFFSET, value); +#endif + if (multi_access == true) + M68000_AddCycles(4); + multi_access = true; + } +} diff --git a/hw/xbox/dsp/dsp.h b/hw/xbox/dsp/dsp.h new file mode 100644 index 0000000000..b6330b2430 --- /dev/null +++ b/hw/xbox/dsp/dsp.h @@ -0,0 +1,77 @@ +/* + DSP M56001 emulation + Dummy emulation, Hatari glue + + (C) 2001-2008 ARAnyM developer team + Adaption to Hatari (C) 2008 by Thomas Huth + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef DSP_H +#define DSP_H + +#if ENABLE_DSP_EMU +# include "dsp_core.h" +#endif + +#define DSP_FREQ (CPU_FREQ*4) + +extern bool bDspEnabled; +extern bool bDspHostInterruptPending; + +/* Dsp commands */ +extern bool DSP_ProcessIRQ(void); +extern void DSP_Init(void); +extern void DSP_UnInit(void); +extern void DSP_Reset(void); +extern void DSP_Run(int nHostCycles); + +/* Save Dsp state to snapshot */ +extern void DSP_MemorySnapShot_Capture(bool bSave); + +/* Dsp Debugger commands */ +extern void DSP_SetDebugging(bool enabled); +extern Uint16 DSP_GetPC(void); +extern Uint16 DSP_GetNextPC(Uint16 pc); +extern Uint16 DSP_GetInstrCycles(void); +extern Uint32 DSP_ReadMemory(Uint16 addr, char space, const char **mem_str); +extern Uint16 DSP_DisasmMemory(Uint16 dsp_memdump_addr, Uint16 dsp_memdump_upper, char space); +extern Uint16 DSP_DisasmAddress(FILE *out, Uint16 lowerAdr, Uint16 UpperAdr); +extern void DSP_Info(Uint32 dummy); +extern void DSP_DisasmRegisters(void); +extern int DSP_GetRegisterAddress(const char *arg, Uint32 **addr, Uint32 *mask); +extern bool DSP_Disasm_SetRegister(const char *arg, Uint32 value); + +/* Dsp SSI commands */ +extern Uint32 DSP_SsiReadTxValue(void); +extern void DSP_SsiWriteRxValue(Uint32 value); +extern void DSP_SsiReceive_SC0(void); +extern void DSP_SsiReceive_SC1(Uint32 value); +extern void DSP_SsiReceive_SC2(Uint32 value); +extern void DSP_SsiReceive_SCK(void); +extern void DSP_SsiTransmit_SC0(void); +extern void DSP_SsiTransmit_SC1(void); +extern void DSP_SsiTransmit_SC2(Uint32 frame); +extern void DSP_SsiTransmit_SCK(void); + + +/* Dsp Host interface commands */ +extern void DSP_HandleReadAccess(void); +extern void DSP_HandleWriteAccess(void); +extern Uint16 DSP_Get_HREQ(void); + + +#endif /* DSP_H */ diff --git a/hw/xbox/dsp/dsp_core.c b/hw/xbox/dsp/dsp_core.c new file mode 100644 index 0000000000..b088476b05 --- /dev/null +++ b/hw/xbox/dsp/dsp_core.c @@ -0,0 +1,704 @@ +/* + DSP M56001 emulation + Host/Emulator <-> DSP glue + + (C) 2003-2008 ARAnyM developer team + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#include "dsp_core.h" +#include "dsp_cpu.h" +#include "ioMem.h" +#include "dsp.h" +#include "log.h" + +/*--- the DSP core itself ---*/ +dsp_core_t dsp_core; + +/*--- Defines ---*/ +#ifndef M_PI +#define M_PI 3.141592653589793238462643383279502 +#endif + +/*--- Functions prototypes ---*/ +static void dsp_core_dsp2host(void); +static void dsp_core_host2dsp(void); + +static void (*dsp_host_interrupt)(void); /* Function to trigger host interrupt */ + +/* Init DSP emulation */ +void dsp_core_init(void (*host_interrupt)(void)) +{ + int i; + + LOG_TRACE(TRACE_DSP_STATE, "Dsp: core init\n"); + + dsp_host_interrupt = host_interrupt; + memset(&dsp_core, 0, sizeof(dsp_core_t)); + + /* Initialize Y:rom[0x0100-0x01ff] with a sin table */ + for (i=0;i<256;i++) { + float src = (((float) i)*M_PI)/128.0; + Sint32 dest = (Sint32) (sin(src) * 8388608.0); /* 1<<23 */ + if (dest>8388607) { + dest = 8388607; + } else if (dest<-8388608) { + dest = -8388608; + } + dsp_core.rom[DSP_SPACE_Y][0x100+i]=dest & 0x00ffffff; + } + + /* Initialize X:rom[0x0100-0x017f] with a mu-law table */ + { + const Uint16 mulaw_base[8]={ + 0x7d7c, 0x3e7c, 0x1efc, 0x0f3c, 0x075c, 0x036c, 0x0174, 0x0078 + }; + + Uint32 position = 0x0100; + Uint32 offset = 0x040000; + + for(i=0;i<8;i++) { + int j; + Uint32 value = mulaw_base[i]<<8; + + for (j=0;j<16;j++) { + dsp_core.rom[DSP_SPACE_X][position++]=value; + value -= offset; + } + + offset >>= 1; + } + } + + /* Initialize X:rom[0x0180-0x01ff] with a a-law table */ + { + const Sint32 multiply_base[8]={ + 0x1580, 0x0ac0, 0x5600, 0x2b00, + 0x1580, 0x0058, 0x0560, 0x02b0 + }; + const Sint32 multiply_col[4]={0x10, 0x01, 0x04, 0x02}; + const Sint32 multiply_line[4]={0x40, 0x04, 0x10, 0x08}; + const Sint32 base_values[4]={0, -1, 2, 1}; + Uint32 pos=0x0180; + + for (i=0;i<8;i++) { + Sint32 alawbase, j; + + alawbase = multiply_base[i]<<8; + for (j=0;j<4;j++) { + Sint32 alawbase1, k; + + alawbase1 = alawbase + ((base_values[j]*multiply_line[i & 3])<<12); + + for (k=0;k<4;k++) { + Sint32 alawbase2; + + alawbase2 = alawbase1 + ((base_values[k]*multiply_col[i & 3])<<12); + + dsp_core.rom[DSP_SPACE_X][pos++]=alawbase2; + } + } + } + } +} + +/* Shutdown DSP emulation */ +void dsp_core_shutdown(void) +{ + dsp_core.running = 0; + LOG_TRACE(TRACE_DSP_STATE, "Dsp: core shutdown\n"); +} + +/* Reset */ +void dsp_core_reset(void) +{ + int i; + + LOG_TRACE(TRACE_DSP_STATE, "Dsp: core reset\n"); + dsp_core_shutdown(); + + /* Memory */ + memset((void*)dsp_core.periph, 0, sizeof(dsp_core.periph)); + memset(dsp_core.stack, 0, sizeof(dsp_core.stack)); + memset(dsp_core.registers, 0, sizeof(dsp_core.registers)); + dsp_core.dsp_host_rtx = 0; + dsp_core.dsp_host_htx = 0; + + dsp_core.bootstrap_pos = 0; + + /* Registers */ + dsp_core.pc = 0x0000; + dsp_core.registers[DSP_REG_OMR]=0x02; + for (i=0;i<8;i++) { + dsp_core.registers[DSP_REG_M0+i]=0x00ffff; + } + + /* Interruptions */ + memset((void*)dsp_core.interrupt_isPending, 0, sizeof(dsp_core.interrupt_isPending)); + dsp_core.interrupt_state = DSP_INTERRUPT_NONE; + dsp_core.interrupt_instr_fetch = -1; + dsp_core.interrupt_save_pc = -1; + dsp_core.interrupt_counter = 0; + dsp_core.interrupt_pipeline_count = 0; + for (i=0;i<5;i++) { + dsp_core.interrupt_ipl[i] = 3; + } + for (i=5;i<12;i++) { + dsp_core.interrupt_ipl[i] = -1; + } + + /* host port init, dsp side */ + dsp_core.periph[DSP_SPACE_X][DSP_HOST_HSR]=(1<>= 1; + } + value = temp; + } + + LOG_TRACE(TRACE_DSP_HOST_SSI, "Dsp SSI received value from crossbar: 0x%06x\n", value); + + if (dsp_core.ssi.crb_re && dsp_core.ssi.waitFrameRX == 0) { + /* Send value to DSP receive */ + dsp_core.ssi.RX = value; + + /* generate interrupt ? */ + if (dsp_core.periph[DSP_SPACE_X][DSP_SSI_CRB] & (1<>= (24 - dsp_core.ssi.cra_word_length); + value &= dsp_core.ssi.cra_word_mask; + + /* if bit SHFD in CRB is set, swap data to transmit */ + if (dsp_core.ssi.crb_shifter) { + for (i=0; i>= 1; + } + value = temp; + } + + LOG_TRACE(TRACE_DSP_HOST_SSI, "Dsp SSI transmit value to crossbar: 0x%06x\n", value); + + /* Transmit the data */ + if (dsp_core.ssi.crb_te && dsp_core.ssi.waitFrameTX == 0) { + /* Send value to crossbar */ + dsp_core.ssi.transmit_value = value; + + /* generate interrupt ? */ + if (dsp_core.periph[DSP_SPACE_X][DSP_SSI_CRB] & (1<>DSP_SSI_CRA_WL0) & 3) { + case 0: + dsp_core.ssi.cra_word_length = 8; + dsp_core.ssi.cra_word_mask = 0xff; + break; + case 1: + dsp_core.ssi.cra_word_length = 12; + dsp_core.ssi.cra_word_mask = 0xfff; + break; + case 2: + dsp_core.ssi.cra_word_length = 16; + dsp_core.ssi.cra_word_mask = 0xffff; + break; + case 3: + dsp_core.ssi.cra_word_length = 24; + dsp_core.ssi.cra_word_mask = 0xffffff; + break; + } + + LOG_TRACE(TRACE_DSP_HOST_SSI, "Dsp SSI CRA write: 0x%06x\n", value); + + /* Get the Frame rate divider ( 2 < value <32) */ + dsp_core.ssi.cra_frame_rate_divider = ((value >> DSP_SSI_CRA_DC0) & 0x1f)+1; + break; + case DSP_SSI_CRB: + crb_te = dsp_core.periph[DSP_SPACE_X][DSP_SSI_CRB] & (1<>DSP_SSI_CRB_SCKD) & 1; + dsp_core.ssi.crb_shifter = (value>>DSP_SSI_CRB_SHFD) & 1; + dsp_core.ssi.crb_synchro = (value>>DSP_SSI_CRB_SYN) & 1; + dsp_core.ssi.crb_mode = (value>>DSP_SSI_CRB_MOD) & 1; + dsp_core.ssi.crb_te = (value>>DSP_SSI_CRB_TE) & 1; + dsp_core.ssi.crb_re = (value>>DSP_SSI_CRB_RE) & 1; + dsp_core.ssi.crb_tie = (value>>DSP_SSI_CRB_TIE) & 1; + dsp_core.ssi.crb_rie = (value>>DSP_SSI_CRB_RIE) & 1; + + if (crb_te == 0 && dsp_core.ssi.crb_te) { + dsp_core.ssi.waitFrameTX = 1; + } + if (crb_re == 0 && dsp_core.ssi.crb_re) { + dsp_core.ssi.waitFrameRX = 1; + } + + LOG_TRACE(TRACE_DSP_HOST_SSI, "Dsp SSI CRB write: 0x%06x\n", value); + + break; + } +} + + +/* + HOST INTERFACE processing +*/ + +static void dsp_core_hostport_update_trdy(void) +{ + int trdy; + + /* Clear/set TRDY bit */ + dsp_core.hostport[CPU_HOST_ISR] &= 0xff-(1<>CPU_HOST_ISR_TXDE) + & ~(dsp_core.periph[DSP_SPACE_X][DSP_HOST_HSR]>>DSP_HOST_HSR_HRDF); + dsp_core.hostport[CPU_HOST_ISR] |= (trdy & 1)<< CPU_HOST_ISR_TRDY; +} + +static void dsp_core_hostport_update_hreq(void) +{ + int hreq; + + hreq = (dsp_core.hostport[CPU_HOST_ICR] & dsp_core.hostport[CPU_HOST_ISR]) & 0x3; + + /* Trigger host interrupt? */ + if (hreq && (dsp_core.hostport[CPU_HOST_ISR] & (1<host) */ +static void dsp_core_dsp2host(void) +{ + /* RXDF = 1 ==> host hasn't read the last value yet */ + if (dsp_core.hostport[CPU_HOST_ISR] & (1< nothing to tranfert from DSP port */ + if (dsp_core.periph[DSP_SPACE_X][DSP_HOST_HSR] & (1<>8; + dsp_core.hostport[CPU_HOST_RXH] = dsp_core.dsp_host_htx>>16; + + /* Set HTDE bit to say that DSP can write */ + dsp_core.periph[DSP_SPACE_X][DSP_HOST_HSR] |= 1<Host): Transfer 0x%06x, Dsp HTDE=1, Host RXDF=1\n", dsp_core.dsp_host_htx); +} + +/* Host port transfer ? (host->dsp) */ +static void dsp_core_host2dsp(void) +{ + /* TXDE = 1 ==> nothing to tranfert from host port */ + if (dsp_core.hostport[CPU_HOST_ISR] & (1< DSP hasn't read the last value yet */ + if (dsp_core.periph[DSP_SPACE_X][DSP_HOST_HSR] & (1<DSP): Transfer 0x%06x, Dsp HRDF=1, Host TXDE=1\n", dsp_core.dsp_host_rtx); + + dsp_core_hostport_update_trdy(); +} + +void dsp_core_hostport_dspread(void) +{ + /* Clear HRDF bit to say that DSP has read */ + dsp_core.periph[DSP_SPACE_X][DSP_HOST_HSR] &= 0xff-(1<DSP): Dsp HRDF cleared\n"); + + dsp_core_hostport_update_trdy(); + dsp_core_host2dsp(); +} + +void dsp_core_hostport_dspwrite(void) +{ + /* Clear HTDE bit to say that DSP has written */ + dsp_core.periph[DSP_SPACE_X][DSP_HOST_HSR] &= 0xff-(1<Host): Dsp HTDE cleared\n"); + + dsp_core_dsp2host(); +} + +/* Read/writes on host port */ +Uint8 dsp_core_read_host(int addr) +{ + Uint8 value; + + value = dsp_core.hostport[addr]; + if (addr == CPU_HOST_TRXL) { + /* Clear RXDF bit to say that CPU has read */ + dsp_core.hostport[CPU_HOST_ISR] &= 0xff-(1<Host): Host RXDF=0\n"); + } + return value; +} + +void dsp_core_write_host(int addr, Uint8 value) +{ + switch(addr) { + case CPU_HOST_ICR: + dsp_core.hostport[CPU_HOST_ICR]=value & 0xfb; + /* Set HF1 and HF0 accordingly on the host side */ + dsp_core.periph[DSP_SPACE_X][DSP_HOST_HSR] &= + 0xff-((1<DSP): Host command = %06x\n", value & 0x9f); + + break; + case CPU_HOST_ISR: + case CPU_HOST_TRX0: + /* Read only */ + break; + case CPU_HOST_IVR: + dsp_core.hostport[CPU_HOST_IVR]=value; + break; + case CPU_HOST_TRXH: + dsp_core.hostport[CPU_HOST_TXH]=value; + break; + case CPU_HOST_TRXM: + dsp_core.hostport[CPU_HOST_TXM]=value; + break; + case CPU_HOST_TRXL: + dsp_core.hostport[CPU_HOST_TXL]=value; + + if (!dsp_core.running) { + dsp_core.ramint[DSP_SPACE_P][dsp_core.bootstrap_pos] = + (dsp_core.hostport[CPU_HOST_TXH]<<16) | + (dsp_core.hostport[CPU_HOST_TXM]<<8) | + dsp_core.hostport[CPU_HOST_TXL]; + + LOG_TRACE(TRACE_DSP_STATE, "Dsp: bootstrap p:0x%04x = 0x%06x\n", + dsp_core.bootstrap_pos, + dsp_core.ramint[DSP_SPACE_P][dsp_core.bootstrap_pos]); + + if (++dsp_core.bootstrap_pos == 0x200) { + LOG_TRACE(TRACE_DSP_STATE, "Dsp: wait bootstrap done\n"); + dsp_core.running = 1; + } + } else { + + /* If TRDY is set, the tranfert is direct to DSP (Burst mode) */ + if (dsp_core.hostport[CPU_HOST_ISR] & (1<DSP): Direct Transfer 0x%06x\n", dsp_core.dsp_host_rtx); + + /* Set HRDF bit to say that DSP can read */ + dsp_core.periph[DSP_SPACE_X][DSP_HOST_HSR] |= 1<DSP): Dsp HRDF set\n"); + } + else{ + /* Clear TXDE to say that CPU has written */ + dsp_core.hostport[CPU_HOST_ISR] &= 0xff-(1<DSP): Host TXDE cleared\n"); + } + dsp_core_hostport_update_trdy(); + dsp_core_host2dsp(); + } + break; + } +} + +/* +vim:ts=4:sw=4: +*/ diff --git a/hw/xbox/dsp/dsp_core.h b/hw/xbox/dsp/dsp_core.h new file mode 100644 index 0000000000..f8193c0592 --- /dev/null +++ b/hw/xbox/dsp/dsp_core.h @@ -0,0 +1,275 @@ +/* + DSP M56001 emulation + Core of DSP emulation + + (C) 2003-2008 ARAnyM developer team + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef DSP_CORE_H +#define DSP_CORE_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define DSP_RAMSIZE 32768 + +/* Host port, CPU side */ +#define CPU_HOST_ICR 0x00 +#define CPU_HOST_CVR 0x01 +#define CPU_HOST_ISR 0x02 +#define CPU_HOST_IVR 0x03 +#define CPU_HOST_TRX0 0x04 +#define CPU_HOST_TRXH 0x05 +#define CPU_HOST_TRXM 0x06 +#define CPU_HOST_TRXL 0x07 +#define CPU_HOST_RX0 0x04 +#define CPU_HOST_RXH 0x05 +#define CPU_HOST_RXM 0x06 +#define CPU_HOST_RXL 0x07 +#define CPU_HOST_TXH 0x09 +#define CPU_HOST_TXM 0x0a +#define CPU_HOST_TXL 0x0b + +#define CPU_HOST_ICR_RREQ 0x00 +#define CPU_HOST_ICR_TREQ 0x01 +#define CPU_HOST_ICR_HF0 0x03 +#define CPU_HOST_ICR_HF1 0x04 +#define CPU_HOST_ICR_HM0 0x05 +#define CPU_HOST_ICR_HM1 0x06 +#define CPU_HOST_ICR_INIT 0x07 + +#define CPU_HOST_CVR_HC 0x07 + +#define CPU_HOST_ISR_RXDF 0x00 +#define CPU_HOST_ISR_TXDE 0x01 +#define CPU_HOST_ISR_TRDY 0x02 +#define CPU_HOST_ISR_HF2 0x03 +#define CPU_HOST_ISR_HF3 0x04 +#define CPU_HOST_ISR_DMA 0x06 +#define CPU_HOST_ISR_HREQ 0x07 + +/* Host port, DSP side, DSP addresses are 0xffc0+value */ +#define DSP_PBC 0x20 /* Port B control register */ +#define DSP_PCC 0x21 /* Port C control register */ +#define DSP_PBDDR 0x22 /* Port B data direction register */ +#define DSP_PCDDR 0x23 /* Port C data direction register */ +#define DSP_PBD 0x24 /* Port B data register */ +#define DSP_PCD 0x25 /* Port C data register */ +#define DSP_HOST_HCR 0x28 /* Host control register */ +#define DSP_HOST_HSR 0x29 /* Host status register */ +#define DSP_HOST_HRX 0x2b /* Host receive register */ +#define DSP_HOST_HTX 0x2b /* Host transmit register */ +#define DSP_SSI_CRA 0x2c /* Ssi control register A */ +#define DSP_SSI_CRB 0x2d /* Ssi control register B */ +#define DSP_SSI_SR 0x2e /* Ssi status register */ +#define DSP_SSI_TSR 0x2e /* Ssi time slot register */ +#define DSP_SSI_RX 0x2f /* Ssi receive register */ +#define DSP_SSI_TX 0x2f /* Ssi transmit register */ +#define DSP_BCR 0x3e /* Port A bus control register */ +#define DSP_IPR 0x3f /* Interrupt priority register */ + +#define DSP_HOST_HCR_HRIE 0x00 +#define DSP_HOST_HCR_HTIE 0x01 +#define DSP_HOST_HCR_HCIE 0x02 +#define DSP_HOST_HCR_HF2 0x03 +#define DSP_HOST_HCR_HF3 0x04 + +#define DSP_HOST_HSR_HRDF 0x00 +#define DSP_HOST_HSR_HTDE 0x01 +#define DSP_HOST_HSR_HCP 0x02 +#define DSP_HOST_HSR_HF0 0x03 +#define DSP_HOST_HSR_HF1 0x04 +#define DSP_HOST_HSR_DMA 0x07 + +#define DSP_SSI_CRA_DC0 0x8 +#define DSP_SSI_CRA_DC1 0x9 +#define DSP_SSI_CRA_DC2 0xa +#define DSP_SSI_CRA_DC3 0xb +#define DSP_SSI_CRA_DC4 0xc +#define DSP_SSI_CRA_WL0 0xd +#define DSP_SSI_CRA_WL1 0xe + +#define DSP_SSI_CRB_OF0 0x0 +#define DSP_SSI_CRB_OF1 0x1 +#define DSP_SSI_CRB_SCD0 0x2 +#define DSP_SSI_CRB_SCD1 0x3 +#define DSP_SSI_CRB_SCD2 0x4 +#define DSP_SSI_CRB_SCKD 0x5 +#define DSP_SSI_CRB_SHFD 0x6 +#define DSP_SSI_CRB_FSL0 0x7 +#define DSP_SSI_CRB_FSL1 0x8 +#define DSP_SSI_CRB_SYN 0x9 +#define DSP_SSI_CRB_GCK 0xa +#define DSP_SSI_CRB_MOD 0xb +#define DSP_SSI_CRB_TE 0xc +#define DSP_SSI_CRB_RE 0xd +#define DSP_SSI_CRB_TIE 0xe +#define DSP_SSI_CRB_RIE 0xf + +#define DSP_SSI_SR_IF0 0x0 +#define DSP_SSI_SR_IF1 0x1 +#define DSP_SSI_SR_TFS 0x2 +#define DSP_SSI_SR_RFS 0x3 +#define DSP_SSI_SR_TUE 0x4 +#define DSP_SSI_SR_ROE 0x5 +#define DSP_SSI_SR_TDE 0x6 +#define DSP_SSI_SR_RDF 0x7 + +#define DSP_INTERRUPT_NONE 0x0 +#define DSP_INTERRUPT_DISABLED 0x1 +#define DSP_INTERRUPT_LONG 0x2 + +#define DSP_INTER_RESET 0x0 +#define DSP_INTER_ILLEGAL 0x1 +#define DSP_INTER_STACK_ERROR 0x2 +#define DSP_INTER_TRACE 0x3 +#define DSP_INTER_SWI 0x4 +#define DSP_INTER_HOST_COMMAND 0x5 +#define DSP_INTER_HOST_RCV_DATA 0x6 +#define DSP_INTER_HOST_TRX_DATA 0x7 +#define DSP_INTER_SSI_RCV_DATA_E 0x8 +#define DSP_INTER_SSI_RCV_DATA 0x9 +#define DSP_INTER_SSI_TRX_DATA_E 0xa +#define DSP_INTER_SSI_TRX_DATA 0xb + + +typedef struct dsp_core_ssi_s dsp_core_ssi_t; +typedef struct dsp_core_s dsp_core_t; +typedef struct dsp_interrupt_s dsp_interrupt_t; + +struct dsp_core_ssi_s { + Uint16 cra_word_length; + Uint32 cra_word_mask; + Uint16 cra_frame_rate_divider; + + Uint16 crb_src_clock; + Uint16 crb_shifter; + Uint16 crb_synchro; + Uint16 crb_mode; + Uint16 crb_te; + Uint16 crb_re; + Uint16 crb_tie; + Uint16 crb_rie; + + Uint32 TX; + Uint32 RX; + Uint32 transmit_value; /* DSP Transmit --> SSI */ + Uint32 received_value; /* DSP Receive --> SSI */ + Uint16 waitFrameTX; + Uint16 waitFrameRX; + Uint32 dspPlay_handshakeMode_frame; +}; + +struct dsp_interrupt_s { + const Uint16 inter; + const Uint16 vectorAddr; + const Uint16 periph; + const char *name; +}; + + +struct dsp_core_s { + + /* DSP executing instructions ? */ + volatile int running; + + /* DSP instruction Cycle counter */ + Uint16 instr_cycle; + + /* Registers */ + Uint16 pc; + Uint32 registers[64]; + + /* stack[0=ssh], stack[1=ssl] */ + Uint16 stack[2][16]; + + /* External ram[] (mapped to p:) */ + Uint32 ramext[DSP_RAMSIZE]; + + /* rom[0] is x:, rom[1] is y: */ + Uint32 rom[2][512]; + + /* Internal ram[0] is x:, ram[1] is y:, ram[2] is p: */ + Uint32 ramint[3][512]; + + /* peripheral space, [x|y]:0xffc0-0xffff */ + volatile Uint32 periph[2][64]; + volatile Uint32 dsp_host_htx; + volatile Uint32 dsp_host_rtx; + Uint16 dsp_host_isr_HREQ; + + + /* host port, CPU side */ + volatile Uint8 hostport[12]; + + /* SSI */ + dsp_core_ssi_t ssi; + + /* Misc */ + Uint32 loop_rep; /* executing rep ? */ + Uint32 pc_on_rep; /* True if PC is on REP instruction */ + + /* For bootstrap routine */ + Uint16 bootstrap_pos; + + /* Interruptions */ + Uint16 interrupt_state; /* NONE, FAST or LONG interrupt */ + Uint16 interrupt_instr_fetch; /* vector of the current interrupt */ + Uint16 interrupt_save_pc; /* save next pc value before interrupt */ + Uint16 interrupt_counter; /* count number of pending interrupts */ + Uint16 interrupt_IplToRaise; /* save the IPL level to save in the SR register */ + Uint16 interrupt_pipeline_count; /* used to prefetch correctly the 2 inter instructions */ + Sint16 interrupt_ipl[12]; /* store the current IPL for each interrupt */ + Uint16 interrupt_isPending[12]; /* store if interrupt is pending for each interrupt */ +}; + + +/* DSP */ +extern dsp_core_t dsp_core; + +/* Emulator call these to init/stop/reset DSP emulation */ +extern void dsp_core_init(void (*host_interrupt)(void)); +extern void dsp_core_shutdown(void); +extern void dsp_core_reset(void); + +/* host port read/write by emulator, addr is 0-7, not 0xffa200-0xffa207 */ +extern Uint8 dsp_core_read_host(int addr); +extern void dsp_core_write_host(int addr, Uint8 value); + +/* dsp_cpu call these to read/write host port */ +extern void dsp_core_hostport_dspread(void); +extern void dsp_core_hostport_dspwrite(void); + +/* dsp_cpu call these to read/write/configure SSI port */ +extern void dsp_core_ssi_configure(Uint32 address, Uint32 value); +extern void dsp_core_ssi_writeTX(Uint32 value); +extern void dsp_core_ssi_writeTSR(void); +extern Uint32 dsp_core_ssi_readRX(void); +extern void dsp_core_ssi_Receive_SC0(void); +extern void dsp_core_ssi_Receive_SC1(Uint32 value); +extern void dsp_core_ssi_Receive_SC2(Uint32 value); +extern void dsp_core_ssi_Receive_SCK(void); +extern void dsp_core_setPortCDataRegister(Uint32 value); + +#ifdef __cplusplus +} +#endif + +#endif /* DSP_CORE_H */ diff --git a/hw/xbox/dsp/dsp_cpu.c b/hw/xbox/dsp/dsp_cpu.c new file mode 100644 index 0000000000..b1d2573a53 --- /dev/null +++ b/hw/xbox/dsp/dsp_cpu.c @@ -0,0 +1,8984 @@ +/* + DSP M56001 emulation + Instructions interpreter + + (C) 2003-2008 ARAnyM developer team + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* + DSP memory mapping + ------------------ + + The memory map is configured as follows : + Program space P is one contiguous block of 32K dsp Words + X and Y data space are each separate 16K dsp Word blocks. + Both X and Y can be accessed as blocks starting at 0 or 16K. + Program space physically overlaps both X and Y data spaces. + Y: memory is mapped at address $0 in P memory + X: memory is mapped at address $4000 in P memory + + The DSP external RAM is zero waitstate, but there is a penalty for + accessing it twice or more in a single instruction, because there is only + one external data bus. The extra access costs 2 cycles penalty. + + The internal buses are all separate (0 waitstate) + + + X: Y: P: + $ffff |--------------+--------------+--------------| + | Int. I/O | Ext. I/O | | + $ffc0 |--------------+--------------+ | + | | | | + | Reserved | Reserved | Reserved | + | | | | + | | | | + | | | | + $8000 |--------------+--------------+--------------| + | | | | + | 16k Shadow | 16k Shadow | | + | | | 32K | + $4000 |--------------+--------------| Program | + | 16K | 16K | RAM | + | External | External | | + | RAM | RAM | | + $0200 |--------------+--------------+--------------| + | Log table or | Sin table or | | + | external mem | external mem | Internal | + $0100 |--------------+--------------+ program | + | Internal X | Internal Y | memory | + | memory | memory | | + $0000 |--------------+--------------+--------------| + + + Special Note : As the Falcon DSP is a 0 waitstate access memory, I've simplified a little the cycle counting. + If this DSP emulator code is used in another project, one should take into account the bus control register (BCR) waitstates. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include "main.h" +#include "dsp_core.h" +#include "dsp_cpu.h" +#include "dsp_disasm.h" +#include "log.h" +#include "debugui.h" + +#define DSP_COUNT_IPS 0 /* Count instruction per seconds */ + + +/********************************** + * Defines + **********************************/ + +#define SIGN_PLUS 0 +#define SIGN_MINUS 1 + +/* Defines some bits values for access to external memory (X, Y, P) */ +/* These values will set/unset the corresponding bits in the variable access_to_ext_memory */ +/* to detect how many access to the external memory were done for a single instruction */ +#define EXT_X_MEMORY 0 +#define EXT_Y_MEMORY 1 +#define EXT_P_MEMORY 2 + + +/********************************** + * Variables + **********************************/ + +/* Instructions per second */ +static Uint32 start_time; +static Uint32 num_inst; + +/* Length of current instruction */ +static Uint32 cur_inst_len; /* =0:jump, >0:increment */ + +/* Current instruction */ +static Uint32 cur_inst; + +/* Counts the number of access to the external memory for one instruction */ +static Uint16 access_to_ext_memory; + +/* DSP is in disasm mode ? */ +/* If yes, stack overflow, underflow and illegal instructions messages are not displayed */ +static bool isDsp_in_disasm_mode; + +static char str_disasm_memory[2][50]; /* Buffer for memory change text in disasm mode */ +static Uint16 disasm_memory_ptr; /* Pointer for memory change in disasm mode */ + +/********************************** + * Functions + **********************************/ + +typedef void (*dsp_emul_t)(void); + +static void dsp_postexecute_update_pc(void); +static void dsp_postexecute_interrupts(void); + +static void dsp_setInterruptIPL(Uint32 value); + +static void dsp_ccr_update_e_u_n_z(Uint32 reg0, Uint32 reg1, Uint32 reg2); + +static Uint32 read_memory(int space, Uint16 address); +static inline Uint32 read_memory_p(Uint16 address); +static Uint32 read_memory_disasm(int space, Uint16 address); + +static inline void write_memory(int space, Uint16 address, Uint32 value); +static void write_memory_raw(int space, Uint16 address, Uint32 value); +static void write_memory_disasm(int space, Uint16 address, Uint32 value); + +static void dsp_write_reg(Uint32 numreg, Uint32 value); + +static void dsp_stack_push(Uint32 curpc, Uint32 cursr, Uint16 sshOnly); +static void dsp_stack_pop(Uint32 *curpc, Uint32 *cursr); +static void dsp_compute_ssh_ssl(void); + +static void opcode8h_0(void); + +static void dsp_update_rn(Uint32 numreg, Sint16 modifier); +static void dsp_update_rn_bitreverse(Uint32 numreg); +static void dsp_update_rn_modulo(Uint32 numreg, Sint16 modifier); +static int dsp_calc_ea(Uint32 ea_mode, Uint32 *dst_addr); +static int dsp_calc_cc(Uint32 cc_code); + +static void dsp_undefined(void); + +/* Instructions without parallel moves */ +static void dsp_andi(void); +static void dsp_bchg_aa(void); +static void dsp_bchg_ea(void); +static void dsp_bchg_pp(void); +static void dsp_bchg_reg(void); +static void dsp_bclr_aa(void); +static void dsp_bclr_ea(void); +static void dsp_bclr_pp(void); +static void dsp_bclr_reg(void); +static void dsp_bset_aa(void); +static void dsp_bset_ea(void); +static void dsp_bset_pp(void); +static void dsp_bset_reg(void); +static void dsp_btst_aa(void); +static void dsp_btst_ea(void); +static void dsp_btst_pp(void); +static void dsp_btst_reg(void); +static void dsp_div(void); +static void dsp_enddo(void); +static void dsp_illegal(void); +static void dsp_jcc_imm(void); +static void dsp_jcc_ea(void); +static void dsp_jclr_aa(void); +static void dsp_jclr_ea(void); +static void dsp_jclr_pp(void); +static void dsp_jclr_reg(void); +static void dsp_jmp_ea(void); +static void dsp_jmp_imm(void); +static void dsp_jscc_ea(void); +static void dsp_jscc_imm(void); +static void dsp_jsclr_aa(void); +static void dsp_jsclr_ea(void); +static void dsp_jsclr_pp(void); +static void dsp_jsclr_reg(void); +static void dsp_jset_aa(void); +static void dsp_jset_ea(void); +static void dsp_jset_pp(void); +static void dsp_jset_reg(void); +static void dsp_jsr_ea(void); +static void dsp_jsr_imm(void); +static void dsp_jsset_aa(void); +static void dsp_jsset_ea(void); +static void dsp_jsset_pp(void); +static void dsp_jsset_reg(void); +static void dsp_lua(void); +static void dsp_movem_ea(void); +static void dsp_movem_aa(void); +static void dsp_nop(void); +static void dsp_norm(void); +static void dsp_ori(void); +static void dsp_reset(void); +static void dsp_rti(void); +static void dsp_rts(void); +static void dsp_stop(void); +static void dsp_swi(void); +static void dsp_tcc(void); +static void dsp_wait(void); + +static void dsp_do_ea(void); +static void dsp_do_aa(void); +static void dsp_do_imm(void); +static void dsp_do_reg(void); +static void dsp_rep_aa(void); +static void dsp_rep_ea(void); +static void dsp_rep_imm(void); +static void dsp_rep_reg(void); +static void dsp_movec_aa(void); +static void dsp_movec_ea(void); +static void dsp_movec_imm(void); +static void dsp_movec_reg(void); +static void dsp_movep_0(void); +static void dsp_movep_1(void); +static void dsp_movep_23(void); + +/* Parallel move analyzer */ +static int dsp_pm_read_accu24(int numreg, Uint32 *dest); +static void dsp_pm_0(void); +static void dsp_pm_1(void); +static void dsp_pm_2(void); +static void dsp_pm_2_2(void); +static void dsp_pm_3(void); +static void dsp_pm_4(void); +static void dsp_pm_4x(void); +static void dsp_pm_5(void); +static void dsp_pm_8(void); + +/* 56bits arithmetic */ +static Uint16 dsp_abs56(Uint32 *dest); +static Uint16 dsp_asl56(Uint32 *dest); +static Uint16 dsp_asr56(Uint32 *dest); +static Uint16 dsp_add56(Uint32 *source, Uint32 *dest); +static Uint16 dsp_sub56(Uint32 *source, Uint32 *dest); +static void dsp_mul56(Uint32 source1, Uint32 source2, Uint32 *dest, Uint8 signe); +static void dsp_rnd56(Uint32 *dest); + +/* Instructions with parallel moves */ +static void dsp_abs_a(void); +static void dsp_abs_b(void); +static void dsp_adc_x_a(void); +static void dsp_adc_x_b(void); +static void dsp_adc_y_a(void); +static void dsp_adc_y_b(void); +static void dsp_add_b_a(void); +static void dsp_add_a_b(void); +static void dsp_add_x_a(void); +static void dsp_add_x_b(void); +static void dsp_add_y_a(void); +static void dsp_add_y_b(void); +static void dsp_add_x0_a(void); +static void dsp_add_x0_b(void); +static void dsp_add_y0_a(void); +static void dsp_add_y0_b(void); +static void dsp_add_x1_a(void); +static void dsp_add_x1_b(void); +static void dsp_add_y1_a(void); +static void dsp_add_y1_b(void); +static void dsp_addl_b_a(void); +static void dsp_addl_b_a(void); +static void dsp_addl_a_b(void); +static void dsp_addr_b_a(void); +static void dsp_addr_a_b(void); +static void dsp_and_x0_a(void); +static void dsp_and_x0_b(void); +static void dsp_and_y0_a(void); +static void dsp_and_y0_b(void); +static void dsp_and_x1_a(void); +static void dsp_and_x1_b(void); +static void dsp_and_y1_a(void); +static void dsp_and_y1_b(void); +static void dsp_asl_a(void); +static void dsp_asl_b(void); +static void dsp_asr_a(void); +static void dsp_asr_b(void); +static void dsp_clr_a(void); +static void dsp_clr_b(void); +static void dsp_cmp_b_a(void); +static void dsp_cmp_a_b(void); +static void dsp_cmp_x0_a(void); +static void dsp_cmp_x0_b(void); +static void dsp_cmp_y0_a(void); +static void dsp_cmp_y0_b(void); +static void dsp_cmp_x1_a(void); +static void dsp_cmp_x1_b(void); +static void dsp_cmp_y1_a(void); +static void dsp_cmp_y1_b(void); +static void dsp_cmpm_b_a(void); +static void dsp_cmpm_a_b(void); +static void dsp_cmpm_x0_a(void); +static void dsp_cmpm_x0_b(void); +static void dsp_cmpm_y0_a(void); +static void dsp_cmpm_y0_b(void); +static void dsp_cmpm_x1_a(void); +static void dsp_cmpm_x1_b(void); +static void dsp_cmpm_y1_a(void); +static void dsp_cmpm_y1_b(void); +static void dsp_eor_x0_a(void); +static void dsp_eor_x0_b(void); +static void dsp_eor_y0_a(void); +static void dsp_eor_y0_b(void); +static void dsp_eor_x1_a(void); +static void dsp_eor_x1_b(void); +static void dsp_eor_y1_a(void); +static void dsp_eor_y1_b(void); +static void dsp_lsl_a(void); +static void dsp_lsl_b(void); +static void dsp_lsr_a(void); +static void dsp_lsr_b(void); +static void dsp_mac_p_x0_x0_a(void); +static void dsp_mac_m_x0_x0_a(void); +static void dsp_mac_p_x0_x0_b(void); +static void dsp_mac_m_x0_x0_b(void); +static void dsp_mac_p_y0_y0_a(void); +static void dsp_mac_m_y0_y0_a(void); +static void dsp_mac_p_y0_y0_b(void); +static void dsp_mac_m_y0_y0_b(void); +static void dsp_mac_p_x1_x0_a(void); +static void dsp_mac_m_x1_x0_a(void); +static void dsp_mac_p_x1_x0_b(void); +static void dsp_mac_m_x1_x0_b(void); +static void dsp_mac_p_y1_y0_a(void); +static void dsp_mac_m_y1_y0_a(void); +static void dsp_mac_p_y1_y0_b(void); +static void dsp_mac_m_y1_y0_b(void); +static void dsp_mac_p_x0_y1_a(void); +static void dsp_mac_m_x0_y1_a(void); +static void dsp_mac_p_x0_y1_b(void); +static void dsp_mac_m_x0_y1_b(void); +static void dsp_mac_p_y0_x0_a(void); +static void dsp_mac_m_y0_x0_a(void); +static void dsp_mac_p_y0_x0_b(void); +static void dsp_mac_m_y0_x0_b(void); +static void dsp_mac_p_x1_y0_a(void); +static void dsp_mac_m_x1_y0_a(void); +static void dsp_mac_p_x1_y0_b(void); +static void dsp_mac_m_x1_y0_b(void); +static void dsp_mac_p_y1_x1_a(void); +static void dsp_mac_m_y1_x1_a(void); +static void dsp_mac_p_y1_x1_b(void); +static void dsp_mac_m_y1_x1_b(void); +static void dsp_macr_p_x0_x0_a(void); +static void dsp_macr_m_x0_x0_a(void); +static void dsp_macr_p_x0_x0_b(void); +static void dsp_macr_m_x0_x0_b(void); +static void dsp_macr_p_y0_y0_a(void); +static void dsp_macr_m_y0_y0_a(void); +static void dsp_macr_p_y0_y0_b(void); +static void dsp_macr_m_y0_y0_b(void); +static void dsp_macr_p_x1_x0_a(void); +static void dsp_macr_m_x1_x0_a(void); +static void dsp_macr_p_x1_x0_b(void); +static void dsp_macr_m_x1_x0_b(void); +static void dsp_macr_p_y1_y0_a(void); +static void dsp_macr_m_y1_y0_a(void); +static void dsp_macr_p_y1_y0_b(void); +static void dsp_macr_m_y1_y0_b(void); +static void dsp_macr_p_x0_y1_a(void); +static void dsp_macr_m_x0_y1_a(void); +static void dsp_macr_p_x0_y1_b(void); +static void dsp_macr_m_x0_y1_b(void); +static void dsp_macr_p_y0_x0_a(void); +static void dsp_macr_m_y0_x0_a(void); +static void dsp_macr_p_y0_x0_b(void); +static void dsp_macr_m_y0_x0_b(void); +static void dsp_macr_p_x1_y0_a(void); +static void dsp_macr_m_x1_y0_a(void); +static void dsp_macr_p_x1_y0_b(void); +static void dsp_macr_m_x1_y0_b(void); +static void dsp_macr_p_y1_x1_a(void); +static void dsp_macr_m_y1_x1_a(void); +static void dsp_macr_p_y1_x1_b(void); +static void dsp_macr_m_y1_x1_b(void); +static void dsp_move(void); +static void dsp_mpy_p_x0_x0_a(void); +static void dsp_mpy_m_x0_x0_a(void); +static void dsp_mpy_p_x0_x0_b(void); +static void dsp_mpy_m_x0_x0_b(void); +static void dsp_mpy_p_y0_y0_a(void); +static void dsp_mpy_m_y0_y0_a(void); +static void dsp_mpy_p_y0_y0_b(void); +static void dsp_mpy_m_y0_y0_b(void); +static void dsp_mpy_p_x1_x0_a(void); +static void dsp_mpy_m_x1_x0_a(void); +static void dsp_mpy_p_x1_x0_b(void); +static void dsp_mpy_m_x1_x0_b(void); +static void dsp_mpy_p_y1_y0_a(void); +static void dsp_mpy_m_y1_y0_a(void); +static void dsp_mpy_p_y1_y0_b(void); +static void dsp_mpy_m_y1_y0_b(void); +static void dsp_mpy_p_x0_y1_a(void); +static void dsp_mpy_m_x0_y1_a(void); +static void dsp_mpy_p_x0_y1_b(void); +static void dsp_mpy_m_x0_y1_b(void); +static void dsp_mpy_p_y0_x0_a(void); +static void dsp_mpy_m_y0_x0_a(void); +static void dsp_mpy_p_y0_x0_b(void); +static void dsp_mpy_m_y0_x0_b(void); +static void dsp_mpy_p_x1_y0_a(void); +static void dsp_mpy_m_x1_y0_a(void); +static void dsp_mpy_p_x1_y0_b(void); +static void dsp_mpy_m_x1_y0_b(void); +static void dsp_mpy_p_y1_x1_a(void); +static void dsp_mpy_m_y1_x1_a(void); +static void dsp_mpy_p_y1_x1_b(void); +static void dsp_mpy_m_y1_x1_b(void); +static void dsp_mpyr_p_x0_x0_a(void); +static void dsp_mpyr_m_x0_x0_a(void); +static void dsp_mpyr_p_x0_x0_b(void); +static void dsp_mpyr_m_x0_x0_b(void); +static void dsp_mpyr_p_y0_y0_a(void); +static void dsp_mpyr_m_y0_y0_a(void); +static void dsp_mpyr_p_y0_y0_b(void); +static void dsp_mpyr_m_y0_y0_b(void); +static void dsp_mpyr_p_x1_x0_a(void); +static void dsp_mpyr_m_x1_x0_a(void); +static void dsp_mpyr_p_x1_x0_b(void); +static void dsp_mpyr_m_x1_x0_b(void); +static void dsp_mpyr_p_y1_y0_a(void); +static void dsp_mpyr_m_y1_y0_a(void); +static void dsp_mpyr_p_y1_y0_b(void); +static void dsp_mpyr_m_y1_y0_b(void); +static void dsp_mpyr_p_x0_y1_a(void); +static void dsp_mpyr_m_x0_y1_a(void); +static void dsp_mpyr_p_x0_y1_b(void); +static void dsp_mpyr_m_x0_y1_b(void); +static void dsp_mpyr_p_y0_x0_a(void); +static void dsp_mpyr_m_y0_x0_a(void); +static void dsp_mpyr_p_y0_x0_b(void); +static void dsp_mpyr_m_y0_x0_b(void); +static void dsp_mpyr_p_x1_y0_a(void); +static void dsp_mpyr_m_x1_y0_a(void); +static void dsp_mpyr_p_x1_y0_b(void); +static void dsp_mpyr_m_x1_y0_b(void); +static void dsp_mpyr_p_y1_x1_a(void); +static void dsp_mpyr_m_y1_x1_a(void); +static void dsp_mpyr_p_y1_x1_b(void); +static void dsp_mpyr_m_y1_x1_b(void); +static void dsp_neg_a(void); +static void dsp_neg_b(void); +static void dsp_not_a(void); +static void dsp_not_b(void); +static void dsp_or_x0_a(void); +static void dsp_or_x0_b(void); +static void dsp_or_y0_a(void); +static void dsp_or_y0_b(void); +static void dsp_or_x1_a(void); +static void dsp_or_x1_b(void); +static void dsp_or_y1_a(void); +static void dsp_or_y1_b(void); +static void dsp_rnd_a(void); +static void dsp_rnd_b(void); +static void dsp_rol_a(void); +static void dsp_rol_b(void); +static void dsp_ror_a(void); +static void dsp_ror_b(void); +static void dsp_sbc_x_a(void); +static void dsp_sbc_x_b(void); +static void dsp_sbc_y_a(void); +static void dsp_sbc_y_b(void); +static void dsp_sub_b_a(void); +static void dsp_sub_a_b(void); +static void dsp_sub_x_a(void); +static void dsp_sub_x_b(void); +static void dsp_sub_y_a(void); +static void dsp_sub_y_b(void); +static void dsp_sub_x0_a(void); +static void dsp_sub_x0_b(void); +static void dsp_sub_y0_a(void); +static void dsp_sub_y0_b(void); +static void dsp_sub_x1_a(void); +static void dsp_sub_x1_b(void); +static void dsp_sub_y1_a(void); +static void dsp_sub_y1_b(void); +static void dsp_subl_a(void); +static void dsp_subl_b(void); +static void dsp_subr_a(void); +static void dsp_subr_b(void); +static void dsp_tfr_b_a(void); +static void dsp_tfr_a_b(void); +static void dsp_tfr_x0_a(void); +static void dsp_tfr_x0_b(void); +static void dsp_tfr_y0_a(void); +static void dsp_tfr_y0_b(void); +static void dsp_tfr_x1_a(void); +static void dsp_tfr_x1_b(void); +static void dsp_tfr_y1_a(void); +static void dsp_tfr_y1_b(void); +static void dsp_tst_a(void); +static void dsp_tst_b(void); + +static const dsp_emul_t opcodes8h[512] = { + /* 0x00 - 0x3f */ + opcode8h_0, dsp_undefined, dsp_undefined, dsp_undefined, opcode8h_0, dsp_andi, dsp_undefined, dsp_ori, + dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_andi, dsp_undefined, dsp_ori, + dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_andi, dsp_undefined, dsp_ori, + dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_andi, dsp_undefined, dsp_ori, + dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, + dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, + dsp_undefined, dsp_undefined, dsp_div, dsp_div, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, + dsp_norm, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, + + /* 0x40 - 0x7f */ + dsp_tcc, dsp_tcc, dsp_tcc, dsp_tcc, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, + dsp_tcc, dsp_tcc, dsp_tcc, dsp_tcc, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, + dsp_tcc, dsp_tcc, dsp_tcc, dsp_tcc, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, + dsp_tcc, dsp_tcc, dsp_tcc, dsp_tcc, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, + dsp_tcc, dsp_tcc, dsp_tcc, dsp_tcc, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, + dsp_tcc, dsp_tcc, dsp_tcc, dsp_tcc, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, + dsp_tcc, dsp_tcc, dsp_tcc, dsp_tcc, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, + dsp_tcc, dsp_tcc, dsp_tcc, dsp_tcc, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, + + /* 0x80 - 0xbf */ + dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, + dsp_lua, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_movec_reg, dsp_undefined, dsp_undefined, + dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, + dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_movec_reg, dsp_undefined, dsp_undefined, + dsp_undefined, dsp_movec_aa, dsp_undefined, dsp_movec_aa, dsp_undefined, dsp_movec_imm, dsp_undefined, dsp_undefined, + dsp_undefined, dsp_movec_ea, dsp_undefined, dsp_movec_ea, dsp_undefined, dsp_movec_imm, dsp_undefined, dsp_undefined, + dsp_undefined, dsp_movec_aa, dsp_undefined, dsp_movec_aa, dsp_undefined, dsp_movec_imm, dsp_undefined, dsp_undefined, + dsp_undefined, dsp_movec_ea, dsp_undefined, dsp_movec_ea, dsp_undefined, dsp_movec_imm, dsp_undefined, dsp_undefined, + + /* 0xc0 - 0xff */ + dsp_do_aa, dsp_rep_aa, dsp_do_aa, dsp_rep_aa, dsp_do_imm, dsp_rep_imm, dsp_undefined, dsp_undefined, + dsp_do_ea, dsp_rep_ea, dsp_do_ea, dsp_rep_ea, dsp_do_imm, dsp_rep_imm, dsp_undefined, dsp_undefined, + dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_do_imm, dsp_rep_imm, dsp_undefined, dsp_undefined, + dsp_do_reg, dsp_rep_reg, dsp_undefined, dsp_undefined, dsp_do_imm, dsp_rep_imm, dsp_undefined, dsp_undefined, + dsp_movem_aa, dsp_movem_aa, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, + dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_movem_ea, dsp_movem_ea, dsp_undefined, dsp_undefined, + dsp_movem_aa, dsp_movem_aa, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, + dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_movem_ea, dsp_movem_ea, dsp_undefined, dsp_undefined, + + /* 0x100 - 0x13f */ + dsp_pm_0, dsp_pm_0, dsp_pm_0, dsp_pm_0, dsp_pm_0, dsp_pm_0, dsp_pm_0, dsp_pm_0, + dsp_movep_0, dsp_movep_0, dsp_movep_1, dsp_movep_1, dsp_movep_23, dsp_movep_23, dsp_movep_23, dsp_movep_23, + dsp_pm_0, dsp_pm_0, dsp_pm_0, dsp_pm_0, dsp_pm_0, dsp_pm_0, dsp_pm_0, dsp_pm_0, + dsp_movep_0, dsp_movep_0, dsp_movep_1, dsp_movep_1, dsp_movep_23, dsp_movep_23, dsp_movep_23, dsp_movep_23, + dsp_pm_0, dsp_pm_0, dsp_pm_0, dsp_pm_0, dsp_pm_0, dsp_pm_0, dsp_pm_0, dsp_pm_0, + dsp_movep_0, dsp_movep_0, dsp_movep_1, dsp_movep_1, dsp_movep_23, dsp_movep_23, dsp_movep_23, dsp_movep_23, + dsp_pm_0, dsp_pm_0, dsp_pm_0, dsp_pm_0, dsp_pm_0, dsp_pm_0, dsp_pm_0, dsp_pm_0, + dsp_movep_0, dsp_movep_0, dsp_movep_1, dsp_movep_1, dsp_movep_23, dsp_movep_23, dsp_movep_23, dsp_movep_23, + + /* 0x140 - 0x17f */ + dsp_bclr_aa, dsp_bset_aa, dsp_bclr_aa, dsp_bset_aa, dsp_jclr_aa, dsp_jset_aa, dsp_jclr_aa, dsp_jset_aa, + dsp_bclr_ea, dsp_bset_ea, dsp_bclr_ea, dsp_bset_ea, dsp_jclr_ea, dsp_jset_ea, dsp_jclr_ea, dsp_jset_ea, + dsp_bclr_pp, dsp_bset_pp, dsp_bclr_pp, dsp_bset_pp, dsp_jclr_pp, dsp_jset_pp, dsp_jclr_pp, dsp_jset_pp, + dsp_jclr_reg, dsp_jset_reg, dsp_bclr_reg, dsp_bset_reg, dsp_jmp_ea, dsp_jcc_ea, dsp_undefined, dsp_undefined, + dsp_bchg_aa, dsp_btst_aa, dsp_bchg_aa, dsp_btst_aa, dsp_jsclr_aa, dsp_jsset_aa, dsp_jsclr_aa, dsp_jsset_aa, + dsp_bchg_ea, dsp_btst_ea, dsp_bchg_ea, dsp_btst_ea, dsp_jsclr_ea, dsp_jsset_ea, dsp_jsclr_ea, dsp_jsset_ea, + dsp_bchg_pp, dsp_btst_pp, dsp_bchg_pp, dsp_btst_pp, dsp_jsclr_pp, dsp_jsset_pp, dsp_jsclr_pp, dsp_jsset_pp, + dsp_jsclr_reg, dsp_jsset_reg, dsp_bchg_reg, dsp_btst_reg, dsp_jsr_ea, dsp_jscc_ea, dsp_undefined, dsp_undefined, + + /* 0x180 - 0x1bf */ + dsp_jmp_imm, dsp_jmp_imm, dsp_jmp_imm, dsp_jmp_imm, dsp_jmp_imm, dsp_jmp_imm, dsp_jmp_imm, dsp_jmp_imm, + dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, + dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, + dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, + dsp_jsr_imm, dsp_jsr_imm, dsp_jsr_imm, dsp_jsr_imm, dsp_jsr_imm, dsp_jsr_imm, dsp_jsr_imm, dsp_jsr_imm, + dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, + dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, + dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, + + /* 0x1c0 - 0x1ff */ + dsp_jcc_imm, dsp_jcc_imm, dsp_jcc_imm, dsp_jcc_imm, dsp_jcc_imm, dsp_jcc_imm, dsp_jcc_imm, dsp_jcc_imm, + dsp_jcc_imm, dsp_jcc_imm, dsp_jcc_imm, dsp_jcc_imm, dsp_jcc_imm, dsp_jcc_imm, dsp_jcc_imm, dsp_jcc_imm, + dsp_jcc_imm, dsp_jcc_imm, dsp_jcc_imm, dsp_jcc_imm, dsp_jcc_imm, dsp_jcc_imm, dsp_jcc_imm, dsp_jcc_imm, + dsp_jcc_imm, dsp_jcc_imm, dsp_jcc_imm, dsp_jcc_imm, dsp_jcc_imm, dsp_jcc_imm, dsp_jcc_imm, dsp_jcc_imm, + dsp_jscc_imm, dsp_jscc_imm, dsp_jscc_imm, dsp_jscc_imm, dsp_jscc_imm, dsp_jscc_imm, dsp_jscc_imm, dsp_jscc_imm, + dsp_jscc_imm, dsp_jscc_imm, dsp_jscc_imm, dsp_jscc_imm, dsp_jscc_imm, dsp_jscc_imm, dsp_jscc_imm, dsp_jscc_imm, + dsp_jscc_imm, dsp_jscc_imm, dsp_jscc_imm, dsp_jscc_imm, dsp_jscc_imm, dsp_jscc_imm, dsp_jscc_imm, dsp_jscc_imm, + dsp_jscc_imm, dsp_jscc_imm, dsp_jscc_imm, dsp_jscc_imm, dsp_jscc_imm, dsp_jscc_imm, dsp_jscc_imm, dsp_jscc_imm, +}; + +static const dsp_emul_t opcodes_parmove[16] = { + dsp_pm_0, dsp_pm_1, dsp_pm_2, dsp_pm_3, dsp_pm_4, dsp_pm_5, dsp_pm_5, dsp_pm_5, + dsp_pm_8, dsp_pm_8, dsp_pm_8, dsp_pm_8, dsp_pm_8, dsp_pm_8, dsp_pm_8, dsp_pm_8 +}; + +static const dsp_emul_t opcodes_alu[256] = { + /* 0x00 - 0x3f */ + dsp_move , dsp_tfr_b_a, dsp_addr_b_a, dsp_tst_a, dsp_undefined, dsp_cmp_b_a, dsp_subr_a, dsp_cmpm_b_a, + dsp_undefined, dsp_tfr_a_b, dsp_addr_a_b, dsp_tst_b, dsp_undefined, dsp_cmp_a_b, dsp_subr_b, dsp_cmpm_a_b, + dsp_add_b_a, dsp_rnd_a, dsp_addl_b_a, dsp_clr_a, dsp_sub_b_a, dsp_undefined, dsp_subl_a, dsp_not_a, + dsp_add_a_b, dsp_rnd_b, dsp_addl_a_b, dsp_clr_b, dsp_sub_a_b, dsp_undefined, dsp_subl_b, dsp_not_b, + dsp_add_x_a, dsp_adc_x_a, dsp_asr_a, dsp_lsr_a, dsp_sub_x_a, dsp_sbc_x_a, dsp_abs_a, dsp_ror_a, + dsp_add_x_b, dsp_adc_x_b, dsp_asr_b, dsp_lsr_b, dsp_sub_x_b, dsp_sbc_x_b, dsp_abs_b, dsp_ror_b, + dsp_add_y_a, dsp_adc_y_a, dsp_asl_a, dsp_lsl_a, dsp_sub_y_a, dsp_sbc_y_a, dsp_neg_a, dsp_rol_a, + dsp_add_y_b, dsp_adc_y_b, dsp_asl_b, dsp_lsl_b, dsp_sub_y_b, dsp_sbc_y_b, dsp_neg_b, dsp_rol_b, + + /* 0x40 - 0x7f */ + dsp_add_x0_a, dsp_tfr_x0_a, dsp_or_x0_a, dsp_eor_x0_a, dsp_sub_x0_a, dsp_cmp_x0_a, dsp_and_x0_a, dsp_cmpm_x0_a, + dsp_add_x0_b, dsp_tfr_x0_b, dsp_or_x0_b, dsp_eor_x0_b, dsp_sub_x0_b, dsp_cmp_x0_b, dsp_and_x0_b, dsp_cmpm_x0_b, + dsp_add_y0_a, dsp_tfr_y0_a, dsp_or_y0_a, dsp_eor_y0_a, dsp_sub_y0_a, dsp_cmp_y0_a, dsp_and_y0_a, dsp_cmpm_y0_a, + dsp_add_y0_b, dsp_tfr_y0_b, dsp_or_y0_b, dsp_eor_y0_b, dsp_sub_y0_b, dsp_cmp_y0_b, dsp_and_y0_b, dsp_cmpm_y0_b, + dsp_add_x1_a, dsp_tfr_x1_a, dsp_or_x1_a, dsp_eor_x1_a, dsp_sub_x1_a, dsp_cmp_x1_a, dsp_and_x1_a, dsp_cmpm_x1_a, + dsp_add_x1_b, dsp_tfr_x1_b, dsp_or_x1_b, dsp_eor_x1_b, dsp_sub_x1_b, dsp_cmp_x1_b, dsp_and_x1_b, dsp_cmpm_x1_b, + dsp_add_y1_a, dsp_tfr_y1_a, dsp_or_y1_a, dsp_eor_y1_a, dsp_sub_y1_a, dsp_cmp_y1_a, dsp_and_y1_a, dsp_cmpm_y1_a, + dsp_add_y1_b, dsp_tfr_y1_b, dsp_or_y1_b, dsp_eor_y1_b, dsp_sub_y1_b, dsp_cmp_y1_b, dsp_and_y1_b, dsp_cmpm_y1_b, + + /* 0x80 - 0xbf */ + dsp_mpy_p_x0_x0_a, dsp_mpyr_p_x0_x0_a, dsp_mac_p_x0_x0_a, dsp_macr_p_x0_x0_a, dsp_mpy_m_x0_x0_a, dsp_mpyr_m_x0_x0_a, dsp_mac_m_x0_x0_a, dsp_macr_m_x0_x0_a, + dsp_mpy_p_x0_x0_b, dsp_mpyr_p_x0_x0_b, dsp_mac_p_x0_x0_b, dsp_macr_p_x0_x0_b, dsp_mpy_m_x0_x0_b, dsp_mpyr_m_x0_x0_b, dsp_mac_m_x0_x0_b, dsp_macr_m_x0_x0_b, + dsp_mpy_p_y0_y0_a, dsp_mpyr_p_y0_y0_a, dsp_mac_p_y0_y0_a, dsp_macr_p_y0_y0_a, dsp_mpy_m_y0_y0_a, dsp_mpyr_m_y0_y0_a, dsp_mac_m_y0_y0_a, dsp_macr_m_y0_y0_a, + dsp_mpy_p_y0_y0_b, dsp_mpyr_p_y0_y0_b, dsp_mac_p_y0_y0_b, dsp_macr_p_y0_y0_b, dsp_mpy_m_y0_y0_b, dsp_mpyr_m_y0_y0_b, dsp_mac_m_y0_y0_b, dsp_macr_m_y0_y0_b, + dsp_mpy_p_x1_x0_a, dsp_mpyr_p_x1_x0_a, dsp_mac_p_x1_x0_a, dsp_macr_p_x1_x0_a, dsp_mpy_m_x1_x0_a, dsp_mpyr_m_x1_x0_a, dsp_mac_m_x1_x0_a, dsp_macr_m_x1_x0_a, + dsp_mpy_p_x1_x0_b, dsp_mpyr_p_x1_x0_b, dsp_mac_p_x1_x0_b, dsp_macr_p_x1_x0_b, dsp_mpy_m_x1_x0_b, dsp_mpyr_m_x1_x0_b, dsp_mac_m_x1_x0_b, dsp_macr_m_x1_x0_b, + dsp_mpy_p_y1_y0_a, dsp_mpyr_p_y1_y0_a, dsp_mac_p_y1_y0_a, dsp_macr_p_y1_y0_a, dsp_mpy_m_y1_y0_a, dsp_mpyr_m_y1_y0_a, dsp_mac_m_y1_y0_a, dsp_macr_m_y1_y0_a, + dsp_mpy_p_y1_y0_b, dsp_mpyr_p_y1_y0_b, dsp_mac_p_y1_y0_b, dsp_macr_p_y1_y0_b, dsp_mpy_m_y1_y0_b, dsp_mpyr_m_y1_y0_b, dsp_mac_m_y1_y0_b, dsp_macr_m_y1_y0_b, + + /* 0xc0_m_ 0xff */ + dsp_mpy_p_x0_y1_a, dsp_mpyr_p_x0_y1_a, dsp_mac_p_x0_y1_a, dsp_macr_p_x0_y1_a, dsp_mpy_m_x0_y1_a, dsp_mpyr_m_x0_y1_a, dsp_mac_m_x0_y1_a, dsp_macr_m_x0_y1_a, + dsp_mpy_p_x0_y1_b, dsp_mpyr_p_x0_y1_b, dsp_mac_p_x0_y1_b, dsp_macr_p_x0_y1_b, dsp_mpy_m_x0_y1_b, dsp_mpyr_m_x0_y1_b, dsp_mac_m_x0_y1_b, dsp_macr_m_x0_y1_b, + dsp_mpy_p_y0_x0_a, dsp_mpyr_p_y0_x0_a, dsp_mac_p_y0_x0_a, dsp_macr_p_y0_x0_a, dsp_mpy_m_y0_x0_a, dsp_mpyr_m_y0_x0_a, dsp_mac_m_y0_x0_a, dsp_macr_m_y0_x0_a, + dsp_mpy_p_y0_x0_b, dsp_mpyr_p_y0_x0_b, dsp_mac_p_y0_x0_b, dsp_macr_p_y0_x0_b, dsp_mpy_m_y0_x0_b, dsp_mpyr_m_y0_x0_b, dsp_mac_m_y0_x0_b, dsp_macr_m_y0_x0_b, + dsp_mpy_p_x1_y0_a, dsp_mpyr_p_x1_y0_a, dsp_mac_p_x1_y0_a, dsp_macr_p_x1_y0_a, dsp_mpy_m_x1_y0_a, dsp_mpyr_m_x1_y0_a, dsp_mac_m_x1_y0_a, dsp_macr_m_x1_y0_a, + dsp_mpy_p_x1_y0_b, dsp_mpyr_p_x1_y0_b, dsp_mac_p_x1_y0_b, dsp_macr_p_x1_y0_b, dsp_mpy_m_x1_y0_b, dsp_mpyr_m_x1_y0_b, dsp_mac_m_x1_y0_b, dsp_macr_m_x1_y0_b, + dsp_mpy_p_y1_x1_a, dsp_mpyr_p_y1_x1_a, dsp_mac_p_y1_x1_a, dsp_macr_p_y1_x1_a, dsp_mpy_m_y1_x1_a, dsp_mpyr_m_y1_x1_a, dsp_mac_m_y1_x1_a, dsp_macr_m_y1_x1_a, + dsp_mpy_p_y1_x1_b, dsp_mpyr_p_y1_x1_b, dsp_mac_p_y1_x1_b, dsp_macr_p_y1_x1_b, dsp_mpy_m_y1_x1_b, dsp_mpyr_m_y1_x1_b, dsp_mac_m_y1_x1_b, dsp_macr_m_y1_x1_b +}; + +static const int registers_tcc[16][2] = { + {DSP_REG_B,DSP_REG_A}, + {DSP_REG_A,DSP_REG_B}, + {DSP_REG_NULL,DSP_REG_NULL}, + {DSP_REG_NULL,DSP_REG_NULL}, + + {DSP_REG_NULL,DSP_REG_NULL}, + {DSP_REG_NULL,DSP_REG_NULL}, + {DSP_REG_NULL,DSP_REG_NULL}, + {DSP_REG_NULL,DSP_REG_NULL}, + + {DSP_REG_X0,DSP_REG_A}, + {DSP_REG_X0,DSP_REG_B}, + {DSP_REG_Y0,DSP_REG_A}, + {DSP_REG_Y0,DSP_REG_B}, + + {DSP_REG_X1,DSP_REG_A}, + {DSP_REG_X1,DSP_REG_B}, + {DSP_REG_Y1,DSP_REG_A}, + {DSP_REG_Y1,DSP_REG_B} +}; + +static const int registers_mask[64] = { + 0, 0, 0, 0, + 24, 24, 24, 24, + 24, 24, 8, 8, + 24, 24, 24, 24, + + 16, 16, 16, 16, + 16, 16, 16, 16, + 16, 16, 16, 16, + 16, 16, 16, 16, + + 16, 16, 16, 16, + 16, 16, 16, 16, + 0, 0, 0, 0, + 0, 0, 0, 0, + + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 16, 8, 6, + 16, 16, 16, 16 +}; + +static const dsp_interrupt_t dsp_interrupt[12] = { + {DSP_INTER_RESET , 0x00, 0, "Reset"}, + {DSP_INTER_ILLEGAL , 0x3e, 0, "Illegal"}, + {DSP_INTER_STACK_ERROR , 0x02, 0, "Stack Error"}, + {DSP_INTER_TRACE , 0x04, 0, "Trace"}, + {DSP_INTER_SWI , 0x06, 0, "Swi"}, + {DSP_INTER_HOST_COMMAND , 0xff, 1, "Host Command"}, + {DSP_INTER_HOST_RCV_DATA, 0x20, 1, "Host receive"}, + {DSP_INTER_HOST_TRX_DATA, 0x22, 1, "Host transmit"}, + {DSP_INTER_SSI_RCV_DATA_E, 0x0e, 2, "SSI receive with exception"}, + {DSP_INTER_SSI_RCV_DATA , 0x0c, 2, "SSI receive"}, + {DSP_INTER_SSI_TRX_DATA_E, 0x12, 2, "SSI transmit with exception"}, + {DSP_INTER_SSI_TRX_DATA , 0x10, 2, "SSI tramsmit"} +}; + + +/********************************** + * Emulator kernel + **********************************/ + +void dsp56k_init_cpu(void) +{ + dsp56k_disasm_init(); + isDsp_in_disasm_mode = false; + start_time = SDL_GetTicks(); + num_inst = 0; +} + +/** + * Execute one instruction in trace mode at a given PC address. + * */ +Uint16 dsp56k_execute_one_disasm_instruction(FILE *out, Uint16 pc) +{ + dsp_core_t *ptr1, *ptr2; + static dsp_core_t dsp_core_save; + Uint16 instruction_length; + + ptr1 = &dsp_core; + ptr2 = &dsp_core_save; + + /* Set DSP in disasm mode */ + isDsp_in_disasm_mode = true; + + /* Save DSP context before executing instruction */ + memcpy(ptr2, ptr1, sizeof(dsp_core)); + + /* execute and disasm instruction */ + dsp_core.pc = pc; + + /* Disasm instruction */ + instruction_length = dsp56k_disasm(DSP_DISASM_MODE) - 1; + + /* Execute instruction at address given in parameter to get the number of cycles it takes */ + dsp56k_execute_instruction(); + + fprintf(out, "%s", dsp56k_getInstructionText()); + + /* Restore DSP context after executing instruction */ + memcpy(ptr1, ptr2, sizeof(dsp_core)); + + /* Unset DSP in disasm mode */ + isDsp_in_disasm_mode = false; + + return instruction_length; +} + +void dsp56k_execute_instruction(void) +{ + Uint32 value; + Uint32 disasm_return = 0; + disasm_memory_ptr = 0; + + /* Initialise the number of access to the external memory for this instruction */ + access_to_ext_memory = 0; + + /* Decode and execute current instruction */ + cur_inst = read_memory_p(dsp_core.pc); + + /* Initialize instruction size and cycle counter */ + cur_inst_len = 1; + dsp_core.instr_cycle = 2; + + /* Disasm current instruction ? (trace mode only) */ + if (LOG_TRACE_LEVEL(TRACE_DSP_DISASM)) { + /* Call dsp56k_disasm only when DSP is called in trace mode */ + if (isDsp_in_disasm_mode == false) { + disasm_return = dsp56k_disasm(DSP_TRACE_MODE); + + if (disasm_return != 0 && LOG_TRACE_LEVEL(TRACE_DSP_DISASM_REG)) { + /* DSP regs trace enabled only if DSP DISASM is enabled */ + dsp56k_disasm_reg_save(); + } + } + } + + if (cur_inst < 0x100000) { + value = (cur_inst >> 11) & (BITMASK(6) << 3); + value += (cur_inst >> 5) & BITMASK(3); + opcodes8h[value](); + } else { + /* Do parallel move read */ + opcodes_parmove[(cur_inst>>20) & BITMASK(4)](); + } + + /* Add the waitstate due to external memory access */ + /* (2 extra cycles per extra access to the external memory after the first one */ + if (access_to_ext_memory != 0) { + value = access_to_ext_memory & 1; + value += (access_to_ext_memory & 2) >> 1; + value += (access_to_ext_memory & 4) >> 2; + + if (value > 1) + dsp_core.instr_cycle += (value - 1) * 2; + } + + /* Disasm current instruction ? (trace mode only) */ + if (LOG_TRACE_LEVEL(TRACE_DSP_DISASM)) { + /* Display only when DSP is called in trace mode */ + if (isDsp_in_disasm_mode == false) { + if (disasm_return != 0) { + fprintf(stderr, "%s", dsp56k_getInstructionText()); + + /* DSP regs trace enabled only if DSP DISASM is enabled */ + if (LOG_TRACE_LEVEL(TRACE_DSP_DISASM_REG)) + dsp56k_disasm_reg_compare(); + + if (LOG_TRACE_LEVEL(TRACE_DSP_DISASM_MEM)) { + /* 1 memory change to display ? */ + if (disasm_memory_ptr == 1) + fprintf(stderr, "\t%s\n", str_disasm_memory[0]); + /* 2 memory changes to display ? */ + else if (disasm_memory_ptr == 2) { + fprintf(stderr, "\t%s\n", str_disasm_memory[0]); + fprintf(stderr, "\t%s\n", str_disasm_memory[1]); + } + } + } + } + } + + /* Process the PC */ + dsp_postexecute_update_pc(); + + /* Process Interrupts */ + dsp_postexecute_interrupts(); + +#if DSP_COUNT_IPS + ++num_inst; + if ((num_inst & 63) == 0) { + /* Evaluate time after instructions have been executed to avoid asking too frequently */ + Uint32 cur_time = SDL_GetTicks(); + if (cur_time-start_time>1000) { + fprintf(stderr, "Dsp: %d i/s\n", (num_inst*1000)/(cur_time-start_time)); + start_time=cur_time; + num_inst=0; + } + } +#endif +} + +/********************************** + * Update the PC +**********************************/ + +static void dsp_postexecute_update_pc(void) +{ + /* When running a REP, PC must stay on the current instruction */ + if (dsp_core.loop_rep) { + /* Is PC on the instruction to repeat ? */ + if (dsp_core.pc_on_rep==0) { + --dsp_core.registers[DSP_REG_LC]; + dsp_core.registers[DSP_REG_LC] &= BITMASK(16); + + if (dsp_core.registers[DSP_REG_LC] > 0) { + cur_inst_len = 0; /* Stay on this instruction */ + } else { + dsp_core.loop_rep = 0; + dsp_core.registers[DSP_REG_LC] = dsp_core.registers[DSP_REG_LCSAVE]; + } + } else { + /* Init LC at right value */ + if (dsp_core.registers[DSP_REG_LC] == 0) { + dsp_core.registers[DSP_REG_LC] = 0x010000; + } + dsp_core.pc_on_rep = 0; + } + } + + /* Normal execution, go to next instruction */ + dsp_core.pc += cur_inst_len; + + /* When running a DO loop, we test the end of loop with the */ + /* updated PC, pointing to last instruction of the loop */ + if (dsp_core.registers[DSP_REG_SR] & (1<> 12) & 3) - 1; + ipl_hi = ((value >> 10) & 3) - 1; + + /* set IPL_HI */ + for (i=5; i<8; i++) { + dsp_core.interrupt_ipl[i] = ipl_hi; + } + + /* set IPL_SSI */ + for (i=8; i<12; i++) { + dsp_core.interrupt_ipl[i] = ipl_ssi; + } +} + +static void dsp_postexecute_interrupts(void) +{ + Uint32 index, instr, i; + Sint32 ipl_to_raise, ipl_sr; + + /* REP is not interruptible */ + if (dsp_core.loop_rep) { + return; + } + + /* A fast interrupt can not be interrupted. */ + if (dsp_core.interrupt_state == DSP_INTERRUPT_DISABLED) { + + switch (dsp_core.interrupt_pipeline_count) { + case 5: + dsp_core.interrupt_pipeline_count --; + return; + case 4: + /* Prefetch interrupt instruction 1 */ + dsp_core.interrupt_save_pc = dsp_core.pc; + dsp_core.pc = dsp_core.interrupt_instr_fetch; + + /* is it a LONG interrupt ? */ + instr = read_memory_p(dsp_core.interrupt_instr_fetch); + if ( ((instr & 0xfff000) == 0x0d0000) || ((instr & 0xffc0ff) == 0x0bc080) ) { + dsp_core.interrupt_state = DSP_INTERRUPT_LONG; + dsp_stack_push(dsp_core.interrupt_save_pc, dsp_core.registers[DSP_REG_SR], 0); + dsp_core.registers[DSP_REG_SR] &= BITMASK(16)-((1<>DSP_SR_I0) & BITMASK(2); + index = 0xffff; + ipl_to_raise = -1; + + /* Arbitrate between all pending interrupts */ + for (i=0; i<12; i++) { + if (dsp_core.interrupt_isPending[i] == 1) { + + /* level 3 interrupt ? */ + if (dsp_core.interrupt_ipl[i] == 3) { + index = i; + break; + } + + /* level 0, 1 ,2 interrupt ? */ + /* if interrupt is masked in SR, don't process it */ + if (dsp_core.interrupt_ipl[i] < ipl_sr) + continue; + + /* if interrupt is lower or equal than current arbitrated interrupt */ + if (dsp_core.interrupt_ipl[i] <= ipl_to_raise) + continue; + + /* save current arbitrated interrupt */ + index = i; + ipl_to_raise = dsp_core.interrupt_ipl[i]; + } + } + + /* If there's no interrupt to process, return */ + if (index == 0xffff) { + return; + } + + /* remove this interrupt from the pending interrupts table */ + dsp_core.interrupt_isPending[index] = 0; + dsp_core.interrupt_counter --; + + /* process arbritrated interrupt */ + ipl_to_raise = dsp_core.interrupt_ipl[index] + 1; + if (ipl_to_raise > 3) { + ipl_to_raise = 3; + } + + dsp_core.interrupt_instr_fetch = dsp_interrupt[index].vectorAddr; + dsp_core.interrupt_pipeline_count = 5; + dsp_core.interrupt_state = DSP_INTERRUPT_DISABLED; + dsp_core.interrupt_IplToRaise = ipl_to_raise; + + LOG_TRACE(TRACE_DSP_INTERRUPT, "Dsp interrupt: %s\n", dsp_interrupt[index].name); + + /* SSI receive data with exception ? */ + if (dsp_core.interrupt_instr_fetch == 0xe) { + dsp_core.periph[DSP_SPACE_X][DSP_SSI_SR] &= 0xff-(1<>DSP_SR_S0) & BITMASK(2); + switch(scaling) { + case 0: + /* Extension Bit (E) */ + value_e = (reg0<<1) + (reg1>>23); + if ((value_e != 0) && (value_e != BITMASK(9))) + dsp_core.registers[DSP_REG_SR] |= 1 << DSP_SR_E; + + /* Unnormalized bit (U) */ + if ((reg1 & 0xc00000) == 0 || (reg1 & 0xc00000) == 0xc00000) + dsp_core.registers[DSP_REG_SR] |= 1 << DSP_SR_U; + break; + case 1: + /* Extension Bit (E) */ + if ((reg0 != 0) && (reg0 != BITMASK(8))) + dsp_core.registers[DSP_REG_SR] |= 1 << DSP_SR_E; + + /* Unnormalized bit (U) */ + value_u = ((reg0<<1) + (reg1>>23)) & 3; + if (value_u == 0 || value_u == 3) + dsp_core.registers[DSP_REG_SR] |= 1 << DSP_SR_U; + break; + case 2: + /* Extension Bit (E) */ + value_e = (reg0<<2) + (reg1>>22); + if ((value_e != 0) && (value_e != BITMASK(10))) + dsp_core.registers[DSP_REG_SR] |= 1 << DSP_SR_E; + + /* Unnormalized bit (U) */ + if ((reg1 & 0x600000) == 0 || (reg1 & 0x600000) == 0x600000) + dsp_core.registers[DSP_REG_SR] |= 1 << DSP_SR_U; + break; + default: + return; + break; + } + + /* Zero Flag (Z) */ + if ((reg1 == 0) && (reg2 == 0) && (reg0 == 0)) + dsp_core.registers[DSP_REG_SR] |= 1 << DSP_SR_Z; + + /* Negative Flag (N) */ + dsp_core.registers[DSP_REG_SR] |= (reg0>>4) & 0x8; +} + +/********************************** + * Read/Write memory functions + **********************************/ + +static Uint32 read_memory_disasm(int space, Uint16 address) +{ + /* Internal RAM ? */ + if (address<0x100) { + return dsp_core.ramint[space][address] & BITMASK(24); + } + + if (space==DSP_SPACE_P) { + return read_memory_p(address); + } + + /* Internal ROM? */ + if ((dsp_core.registers[DSP_REG_OMR] & (1<= 0xffc0) { + if ((space==DSP_SPACE_X) && (address==0xffc0+DSP_HOST_HTX)) { + return dsp_core.dsp_host_htx; + } + if ((space==DSP_SPACE_X) && (address==0xffc0+DSP_SSI_TX)) { + return dsp_core.ssi.transmit_value; + } + return dsp_core.periph[space][address-0xffc0] & BITMASK(24); + } + + /* Falcon: External RAM, map X to upper 16K of matching space in Y,P */ + address &= (DSP_RAMSIZE>>1) - 1; + if (space == DSP_SPACE_X) { + address += DSP_RAMSIZE>>1; + } + + /* Falcon: External RAM, finally map X,Y to P */ + return dsp_core.ramext[address & (DSP_RAMSIZE-1)] & BITMASK(24); +} + +static inline Uint32 read_memory_p(Uint16 address) +{ + /* Internal RAM ? */ + if (address < 0x200) { + return dsp_core.ramint[DSP_SPACE_P][address] & BITMASK(24); + } + + /* Access to the external P memory */ + access_to_ext_memory |= 1 << EXT_P_MEMORY; + + /* External RAM, mask address to available ram size */ + return dsp_core.ramext[address & (DSP_RAMSIZE-1)] & BITMASK(24); +} + +static Uint32 read_memory(int space, Uint16 address) +{ + Uint32 value; + + /* Internal RAM ? */ + if (address < 0x100) { + return dsp_core.ramint[space][address] & BITMASK(24); + } + + if (space == DSP_SPACE_P) { + return read_memory_p(address); + } + + /* Internal ROM ? */ + if (address < 0x200) { + if (dsp_core.registers[DSP_REG_OMR] & (1<= 0xffc0) { + value = dsp_core.periph[space][address-0xffc0] & BITMASK(24); + if (space == DSP_SPACE_X) { + if (address == 0xffc0+DSP_HOST_HRX) { + value = dsp_core.dsp_host_rtx; + dsp_core_hostport_dspread(); + } + else if (address == 0xffc0+DSP_SSI_RX) { + value = dsp_core_ssi_readRX(); + } + } + return value; + } + + /* Falcon: External X or Y RAM access */ + address &= (DSP_RAMSIZE>>1) - 1; + + if (space == DSP_SPACE_X) { + /* Map X to upper 16K of matching space in Y,P */ + address += DSP_RAMSIZE>>1; + + /* Set one access to the X external memory */ + access_to_ext_memory |= 1 << EXT_X_MEMORY; + } + else { + /* Access to the Y external memory */ + access_to_ext_memory |= 1 << EXT_Y_MEMORY; + } + + + /* Falcon: External RAM, finally map X,Y to P */ + return dsp_core.ramext[address & (DSP_RAMSIZE-1)] & BITMASK(24); +} + +static inline void write_memory(int space, Uint16 address, Uint32 value) +{ + if (unlikely(LOG_TRACE_LEVEL(TRACE_DSP_DISASM_MEM))) + write_memory_disasm(space, address, value); + else + write_memory_raw(space, address, value); +} + +static void write_memory_raw(int space, Uint16 address, Uint32 value) +{ + value &= BITMASK(24); + + /* Peripheral address ? */ + if (address >= 0xffc0) { + if (space == DSP_SPACE_X) { + switch(address-0xffc0) { + case DSP_HOST_HTX: + dsp_core.dsp_host_htx = value; + dsp_core_hostport_dspwrite(); + break; + case DSP_HOST_HCR: + dsp_core.periph[DSP_SPACE_X][DSP_HOST_HCR] = value; + /* Set HF3 and HF2 accordingly on the host side */ + dsp_core.hostport[CPU_HOST_ISR] &= + BITMASK(8)-((1<>1) - 1; + + if (space == DSP_SPACE_X) { + /* Access to the X external RAM */ + /* map X to upper 16K of matching space in Y,P */ + address += DSP_RAMSIZE>>1; + access_to_ext_memory |= 1; + } + else { + /* Access to the Y external RAM */ + access_to_ext_memory |= 1 << EXT_Y_MEMORY; + } + } + + /* Falcon: External RAM, map X,Y to P */ + dsp_core.ramext[address & (DSP_RAMSIZE-1)] = value; +} + +static void write_memory_disasm(int space, Uint16 address, Uint32 value) +{ + Uint32 oldvalue, curvalue; + Uint8 space_c = 'p'; + + value &= BITMASK(24); + oldvalue = read_memory_disasm(space, address); + + write_memory_raw(space,address,value); + + switch(space) { + case DSP_SPACE_X: + space_c = 'x'; + break; + case DSP_SPACE_Y: + space_c = 'y'; + break; + default: + break; + } + + curvalue = read_memory_disasm(space, address); + sprintf(str_disasm_memory[disasm_memory_ptr],"Mem: %c:0x%04x 0x%06x -> 0x%06x", space_c, address, oldvalue, curvalue); + disasm_memory_ptr ++; +} + +static void dsp_write_reg(Uint32 numreg, Uint32 value) +{ + Uint32 stack_error; + + switch (numreg) { + case DSP_REG_A: + dsp_core.registers[DSP_REG_A0] = 0; + dsp_core.registers[DSP_REG_A1] = value; + dsp_core.registers[DSP_REG_A2] = value & (1<<23) ? 0xff : 0x0; + break; + case DSP_REG_B: + dsp_core.registers[DSP_REG_B0] = 0; + dsp_core.registers[DSP_REG_B1] = value; + dsp_core.registers[DSP_REG_B2] = value & (1<<23) ? 0xff : 0x0; + break; + case DSP_REG_OMR: + dsp_core.registers[DSP_REG_OMR] = value & 0xc7; + break; + case DSP_REG_SR: + dsp_core.registers[DSP_REG_SR] = value & 0xaf7f; + break; + case DSP_REG_SP: + stack_error = dsp_core.registers[DSP_REG_SP] & (3<modulo) { + while (modifier>bufsize) { + r_reg += bufsize; + modifier -= bufsize; + } + while (modifier<-bufsize) { + r_reg -= bufsize; + modifier += bufsize; + } + } + + r_reg += modifier; + + if (orig_modifier!=modulo) { + if (r_reg>hibound) { + r_reg -= modulo; + } else if (r_reg> 3) & BITMASK(3); + numreg = ea_mode & BITMASK(3); + switch (value) { + case 0: + /* (Rx)-Nx */ + *dst_addr = dsp_core.registers[DSP_REG_R0+numreg]; + dsp_update_rn(numreg, -dsp_core.registers[DSP_REG_N0+numreg]); + break; + case 1: + /* (Rx)+Nx */ + *dst_addr = dsp_core.registers[DSP_REG_R0+numreg]; + dsp_update_rn(numreg, dsp_core.registers[DSP_REG_N0+numreg]); + break; + case 2: + /* (Rx)- */ + *dst_addr = dsp_core.registers[DSP_REG_R0+numreg]; + dsp_update_rn(numreg, -1); + break; + case 3: + /* (Rx)+ */ + *dst_addr = dsp_core.registers[DSP_REG_R0+numreg]; + dsp_update_rn(numreg, +1); + break; + case 4: + /* (Rx) */ + *dst_addr = dsp_core.registers[DSP_REG_R0+numreg]; + break; + case 5: + /* (Rx+Nx) */ + dsp_core.instr_cycle += 2; + curreg = dsp_core.registers[DSP_REG_R0+numreg]; + dsp_update_rn(numreg, dsp_core.registers[DSP_REG_N0+numreg]); + *dst_addr = dsp_core.registers[DSP_REG_R0+numreg]; + dsp_core.registers[DSP_REG_R0+numreg] = curreg; + break; + case 6: + /* aa */ + dsp_core.instr_cycle += 2; + *dst_addr = read_memory_p(dsp_core.pc+1); + cur_inst_len++; + if (numreg != 0) { + return 1; /* immediate value */ + } + break; + case 7: + /* -(Rx) */ + dsp_core.instr_cycle += 2; + dsp_update_rn(numreg, -1); + *dst_addr = dsp_core.registers[DSP_REG_R0+numreg]; + break; + } + /* address */ + return 0; +} + +/********************************** + * Condition code test + **********************************/ + +static int dsp_calc_cc(Uint32 cc_code) +{ + Uint16 value1, value2, value3; + + switch (cc_code) { + case 0: /* CC (HS) */ + value1 = dsp_core.registers[DSP_REG_SR] & (1<> DSP_SR_N) & 1; + value2 = (dsp_core.registers[DSP_REG_SR] >> DSP_SR_V) & 1; + return ((value1 ^ value2) == 0); + case 2: /* NE */ + value1 = dsp_core.registers[DSP_REG_SR] & (1<> DSP_SR_Z) & 1; + value2 = (~(dsp_core.registers[DSP_REG_SR] >> DSP_SR_U)) & 1; + value3 = (~(dsp_core.registers[DSP_REG_SR] >> DSP_SR_E)) & 1; + return ((value1 | (value2 & value3)) == 0); + case 5: /* EC */ + value1 = dsp_core.registers[DSP_REG_SR] & (1<> DSP_SR_N) & 1; + value2 = (dsp_core.registers[DSP_REG_SR] >> DSP_SR_V) & 1; + value3 = (dsp_core.registers[DSP_REG_SR] >> DSP_SR_Z) & 1; + return ((value3 | (value1 ^ value2)) == 0); + case 8: /* CS (LO) */ + value1 = dsp_core.registers[DSP_REG_SR] & (1<> DSP_SR_N) & 1; + value2 = (dsp_core.registers[DSP_REG_SR] >> DSP_SR_V) & 1; + return ((value1 ^ value2) == 1); + case 10: /* EQ */ + value1 = (dsp_core.registers[DSP_REG_SR] >> DSP_SR_Z) & 1; + return (value1==1); + case 11: /* MI */ + value1 = (dsp_core.registers[DSP_REG_SR] >> DSP_SR_N) & 1; + return (value1==1); + case 12: /* NR */ + value1 = (dsp_core.registers[DSP_REG_SR] >> DSP_SR_Z) & 1; + value2 = (~(dsp_core.registers[DSP_REG_SR] >> DSP_SR_U)) & 1; + value3 = (~(dsp_core.registers[DSP_REG_SR] >> DSP_SR_E)) & 1; + return ((value1 | (value2 & value3)) == 1); + case 13: /* ES */ + value1 = (dsp_core.registers[DSP_REG_SR] >> DSP_SR_E) & 1; + return (value1==1); + case 14: /* LS */ + value1 = (dsp_core.registers[DSP_REG_SR] >> DSP_SR_L) & 1; + return (value1==1); + case 15: /* LE */ + value1 = (dsp_core.registers[DSP_REG_SR] >> DSP_SR_N) & 1; + value2 = (dsp_core.registers[DSP_REG_SR] >> DSP_SR_V) & 1; + value3 = (dsp_core.registers[DSP_REG_SR] >> DSP_SR_Z) & 1; + return ((value3 | (value1 ^ value2)) == 1); + } + return 0; +} + +/********************************** + * Highbyte opcodes dispatchers + **********************************/ + +static void opcode8h_0(void) +{ + switch(cur_inst) { + case 0x000000: + dsp_nop(); + break; + case 0x000004: + dsp_rti(); + break; + case 0x000005: + dsp_illegal(); + break; + case 0x000006: + dsp_swi(); + break; + case 0x00000c: + dsp_rts(); + break; + case 0x000084: + dsp_reset(); + break; + case 0x000086: + dsp_wait(); + break; + case 0x000087: + dsp_stop(); + break; + case 0x00008c: + dsp_enddo(); + break; + default: + dsp_undefined(); + break; + } +} + +/********************************** + * Non-parallel moves instructions + **********************************/ + +static void dsp_undefined(void) +{ + if (isDsp_in_disasm_mode == false) { + cur_inst_len = 0; + fprintf(stderr, "Dsp: 0x%04x: 0x%06x Illegal instruction\n",dsp_core.pc, cur_inst); + /* Add some artificial CPU cycles to avoid being stuck in an infinite loop */ + dsp_core.instr_cycle += 100; + } + else { + cur_inst_len = 1; + dsp_core.instr_cycle = 0; + } + if (bExceptionDebugging) { + DebugUI(REASON_DSP_EXCEPTION); + } +} + +static void dsp_andi(void) +{ + Uint32 regnum, value; + + value = (cur_inst >> 8) & BITMASK(8); + regnum = cur_inst & BITMASK(2); + switch(regnum) { + case 0: + /* mr */ + dsp_core.registers[DSP_REG_SR] &= (value<<8)|BITMASK(8); + break; + case 1: + /* ccr */ + dsp_core.registers[DSP_REG_SR] &= (BITMASK(8)<<8)|value; + break; + case 2: + /* omr */ + dsp_core.registers[DSP_REG_OMR] &= value; + break; + } +} + +static void dsp_bchg_aa(void) +{ + Uint32 memspace, addr, value, newcarry, numbit; + + memspace = (cur_inst>>6) & 1; + value = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + + addr = value; + value = read_memory(memspace, addr); + newcarry = (value>>numbit) & 1; + if (newcarry) { + value -= (1<>6) & 1; + value = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + + dsp_calc_ea(value, &addr); + value = read_memory(memspace, addr); + newcarry = (value>>numbit) & 1; + if (newcarry) { + value -= (1<>6) & 1; + value = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + + addr = 0xffc0 + value; + value = read_memory(memspace, addr); + newcarry = (value>>numbit) & 1; + if (newcarry) { + value -= (1<>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + + if ((numreg==DSP_REG_A) || (numreg==DSP_REG_B)) { + dsp_pm_read_accu24(numreg, &value); + } else { + value = dsp_core.registers[numreg]; + } + + newcarry = (value>>numbit) & 1; + if (newcarry) { + value -= (1<>6) & 1; + addr = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + + value = read_memory(memspace, addr); + newcarry = (value>>numbit) & 1; + value &= 0xffffffff-(1<>6) & 1; + value = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + + dsp_calc_ea(value, &addr); + value = read_memory(memspace, addr); + newcarry = (value>>numbit) & 1; + value &= 0xffffffff-(1<>6) & 1; + value = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + + addr = 0xffc0 + value; + value = read_memory(memspace, addr); + newcarry = (value>>numbit) & 1; + value &= 0xffffffff-(1<>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + + if ((numreg==DSP_REG_A) || (numreg==DSP_REG_B)) { + dsp_pm_read_accu24(numreg, &value); + } else { + value = dsp_core.registers[numreg]; + } + + newcarry = (value>>numbit) & 1; + value &= 0xffffffff-(1<>6) & 1; + value = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + + addr = value; + value = read_memory(memspace, addr); + newcarry = (value>>numbit) & 1; + value |= (1<>6) & 1; + value = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + + dsp_calc_ea(value, &addr); + value = read_memory(memspace, addr); + newcarry = (value>>numbit) & 1; + value |= (1<>6) & 1; + value = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + addr = 0xffc0 + value; + value = read_memory(memspace, addr); + newcarry = (value>>numbit) & 1; + value |= (1<>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + + if ((numreg==DSP_REG_A) || (numreg==DSP_REG_B)) { + dsp_pm_read_accu24(numreg, &value); + } else { + value = dsp_core.registers[numreg]; + } + + newcarry = (value>>numbit) & 1; + value |= (1<>6) & 1; + value = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + + addr = value; + value = read_memory(memspace, addr); + newcarry = (value>>numbit) & 1; + + /* Set carry */ + dsp_core.registers[DSP_REG_SR] &= BITMASK(16)-(1<>6) & 1; + value = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + + dsp_calc_ea(value, &addr); + value = read_memory(memspace, addr); + newcarry = (value>>numbit) & 1; + + /* Set carry */ + dsp_core.registers[DSP_REG_SR] &= BITMASK(16)-(1<>6) & 1; + value = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + + addr = 0xffc0 + value; + value = read_memory(memspace, addr); + newcarry = (value>>numbit) & 1; + + /* Set carry */ + dsp_core.registers[DSP_REG_SR] &= BITMASK(16)-(1<>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + + if ((numreg==DSP_REG_A) || (numreg==DSP_REG_B)) { + dsp_pm_read_accu24(numreg, &value); + } else { + value = dsp_core.registers[numreg]; + } + + newcarry = (value>>numbit) & 1; + + /* Set carry */ + dsp_core.registers[DSP_REG_SR] &= BITMASK(16)-(1<>4) & BITMASK(2)) { + case 0: srcreg = DSP_REG_X0; break; + case 1: srcreg = DSP_REG_Y0; break; + case 2: srcreg = DSP_REG_X1; break; + case 3: srcreg = DSP_REG_Y1; break; + } + source[2] = 0; + source[1] = dsp_core.registers[srcreg]; + source[0] = source[1] & (1<<23) ? 0xff : 0x0; + + destreg = DSP_REG_A + ((cur_inst>>3) & 1); + if (destreg == DSP_REG_A) { + dest[0] = dsp_core.registers[DSP_REG_A2]; + dest[1] = dsp_core.registers[DSP_REG_A1]; + dest[2] = dsp_core.registers[DSP_REG_A0]; + } + else { + dest[0] = dsp_core.registers[DSP_REG_B2]; + dest[1] = dsp_core.registers[DSP_REG_B1]; + dest[2] = dsp_core.registers[DSP_REG_B0]; + } + + if (((dest[0]>>7) & 1) ^ ((source[1]>>23) & 1)) { + /* D += S */ + newsr = dsp_asl56(dest); + dsp_add56(source, dest); + } else { + /* D -= S */ + newsr = dsp_asl56(dest); + dsp_sub56(source, dest); + } + + dest[2] |= (dsp_core.registers[DSP_REG_SR]>>DSP_SR_C) & 1; + + if (destreg == DSP_REG_A) { + dsp_core.registers[DSP_REG_A2] = dest[0]; + dsp_core.registers[DSP_REG_A1] = dest[1]; + dsp_core.registers[DSP_REG_A0] = dest[2]; + } + else { + dsp_core.registers[DSP_REG_B2] = dest[0]; + dsp_core.registers[DSP_REG_B1] = dest[1]; + dsp_core.registers[DSP_REG_B0] = dest[2]; + } + + dsp_core.registers[DSP_REG_SR] &= BITMASK(16)-((1<>7) & 1))<>6) & 1; + addr = (cur_inst>>8) & BITMASK(6); + dsp_core.registers[DSP_REG_LC] = read_memory(memspace, addr) & BITMASK(16); + + dsp_core.instr_cycle += 4; +} + +static void dsp_do_imm(void) +{ + /* #xx */ + + dsp_stack_push(dsp_core.registers[DSP_REG_LA], dsp_core.registers[DSP_REG_LC], 0); + dsp_core.registers[DSP_REG_LA] = read_memory_p(dsp_core.pc+1) & BITMASK(16); + cur_inst_len++; + dsp_stack_push(dsp_core.pc+cur_inst_len, dsp_core.registers[DSP_REG_SR], 0); + dsp_core.registers[DSP_REG_SR] |= (1<>8) & BITMASK(8)) + + ((cur_inst & BITMASK(4))<<8); + + dsp_core.instr_cycle += 4; +} + +static void dsp_do_ea(void) +{ + Uint32 memspace, ea_mode, addr; + + /* x:ea */ + /* y:ea */ + + dsp_stack_push(dsp_core.registers[DSP_REG_LA], dsp_core.registers[DSP_REG_LC], 0); + dsp_core.registers[DSP_REG_LA] = read_memory_p(dsp_core.pc+1) & BITMASK(16); + cur_inst_len++; + dsp_stack_push(dsp_core.pc+cur_inst_len, dsp_core.registers[DSP_REG_SR], 0); + dsp_core.registers[DSP_REG_SR] |= (1<>6) & 1; + ea_mode = (cur_inst>>8) & BITMASK(6); + dsp_calc_ea(ea_mode, &addr); + dsp_core.registers[DSP_REG_LC] = read_memory(memspace, addr) & BITMASK(16); + + dsp_core.instr_cycle += 4; +} + +static void dsp_do_reg(void) +{ + Uint32 numreg; + + /* S */ + + dsp_stack_push(dsp_core.registers[DSP_REG_LA], dsp_core.registers[DSP_REG_LC], 0); + dsp_core.registers[DSP_REG_LA] = read_memory_p(dsp_core.pc+1) & BITMASK(16); + cur_inst_len++; + + numreg = (cur_inst>>8) & BITMASK(6); + if ((numreg == DSP_REG_A) || (numreg == DSP_REG_B)) { + dsp_pm_read_accu24(numreg, &dsp_core.registers[DSP_REG_LC]); + } else { + dsp_core.registers[DSP_REG_LC] = dsp_core.registers[numreg]; + } + dsp_core.registers[DSP_REG_LC] &= BITMASK(16); + + dsp_stack_push(dsp_core.pc+cur_inst_len, dsp_core.registers[DSP_REG_SR], 0); + dsp_core.registers[DSP_REG_SR] |= (1<>12) & BITMASK(4); + if (dsp_calc_cc(cc_code)) { + dsp_core.pc = newpc; + cur_inst_len = 0; + } + + dsp_core.instr_cycle += 2; +} + +static void dsp_jcc_ea(void) +{ + Uint32 newpc, cc_code; + + dsp_calc_ea((cur_inst >>8) & BITMASK(6), &newpc); + cc_code=cur_inst & BITMASK(4); + + if (dsp_calc_cc(cc_code)) { + dsp_core.pc = newpc; + cur_inst_len = 0; + } + + dsp_core.instr_cycle += 2; +} + +static void dsp_jclr_aa(void) +{ + Uint32 memspace, addr, value, numbit, newaddr; + + memspace = (cur_inst>>6) & 1; + addr = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + value = read_memory(memspace, addr); + newaddr = read_memory_p(dsp_core.pc+1); + + dsp_core.instr_cycle += 4; + + if ((value & (1<>6) & 1; + value = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + newaddr = read_memory_p(dsp_core.pc+1); + + dsp_calc_ea(value, &addr); + value = read_memory(memspace, addr); + + dsp_core.instr_cycle += 4; + + if ((value & (1<>6) & 1; + value = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + addr = 0xffc0 + value; + value = read_memory(memspace, addr); + newaddr = read_memory_p(dsp_core.pc+1); + + dsp_core.instr_cycle += 4; + + if ((value & (1<>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + newaddr = read_memory_p(dsp_core.pc+1); + + if ((numreg==DSP_REG_A) || (numreg==DSP_REG_B)) { + dsp_pm_read_accu24(numreg, &value); + } else { + value = dsp_core.registers[numreg]; + } + + dsp_core.instr_cycle += 4; + + if ((value & (1<>8) & BITMASK(6), &newpc); + cur_inst_len = 0; + dsp_core.pc = newpc; + + dsp_core.instr_cycle += 2; +} + +static void dsp_jmp_imm(void) +{ + Uint32 newpc; + + newpc = cur_inst & BITMASK(12); + cur_inst_len = 0; + dsp_core.pc = newpc; + + dsp_core.instr_cycle += 2; +} + +static void dsp_jscc_ea(void) +{ + Uint32 newpc, cc_code; + + dsp_calc_ea((cur_inst >>8) & BITMASK(6), &newpc); + cc_code=cur_inst & BITMASK(4); + + if (dsp_calc_cc(cc_code)) { + dsp_stack_push(dsp_core.pc+cur_inst_len, dsp_core.registers[DSP_REG_SR], 0); + dsp_core.pc = newpc; + cur_inst_len = 0; + } + + dsp_core.instr_cycle += 2; +} + +static void dsp_jscc_imm(void) +{ + Uint32 cc_code, newpc; + + newpc = cur_inst & BITMASK(12); + cc_code=(cur_inst>>12) & BITMASK(4); + if (dsp_calc_cc(cc_code)) { + dsp_stack_push(dsp_core.pc+cur_inst_len, dsp_core.registers[DSP_REG_SR], 0); + dsp_core.pc = newpc; + cur_inst_len = 0; + } + + dsp_core.instr_cycle += 2; +} + +static void dsp_jsclr_aa(void) +{ + Uint32 memspace, addr, value, newpc, numbit, newaddr; + + memspace = (cur_inst>>6) & 1; + addr = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + value = read_memory(memspace, addr); + newaddr = read_memory_p(dsp_core.pc+1); + + dsp_core.instr_cycle += 4; + + if ((value & (1<>6) & 1; + value = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + dsp_calc_ea(value, &addr); + value = read_memory(memspace, addr); + newaddr = read_memory_p(dsp_core.pc+1); + + dsp_core.instr_cycle += 4; + + if ((value & (1<>6) & 1; + value = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + addr = 0xffc0 + value; + value = read_memory(memspace, addr); + newaddr = read_memory_p(dsp_core.pc+1); + + dsp_core.instr_cycle += 4; + + if ((value & (1<>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + newaddr = read_memory_p(dsp_core.pc+1); + + if ((numreg==DSP_REG_A) || (numreg==DSP_REG_B)) { + dsp_pm_read_accu24(numreg, &value); + } else { + value = dsp_core.registers[numreg]; + } + + dsp_core.instr_cycle += 4; + + if ((value & (1<>6) & 1; + addr = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + value = read_memory(memspace, addr); + newaddr = read_memory_p(dsp_core.pc+1); + + dsp_core.instr_cycle += 4; + + if (value & (1<>6) & 1; + value = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + dsp_calc_ea(value, &addr); + value = read_memory(memspace, addr); + newaddr = read_memory_p(dsp_core.pc+1); + + dsp_core.instr_cycle += 4; + + if (value & (1<>6) & 1; + value = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + addr = 0xffc0 + value; + value = read_memory(memspace, addr); + newaddr = read_memory_p(dsp_core.pc+1); + + dsp_core.instr_cycle += 4; + + if (value & (1<>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + newaddr = read_memory_p(dsp_core.pc+1); + + if ((numreg==DSP_REG_A) || (numreg==DSP_REG_B)) { + dsp_pm_read_accu24(numreg, &value); + } else { + value = dsp_core.registers[numreg]; + } + + dsp_core.instr_cycle += 4; + + if (value & (1<>8) & BITMASK(6),&newpc); + + if (dsp_core.interrupt_state != DSP_INTERRUPT_LONG){ + dsp_stack_push(dsp_core.pc+cur_inst_len, dsp_core.registers[DSP_REG_SR], 0); + } + else { + dsp_core.interrupt_state = DSP_INTERRUPT_DISABLED; + } + + dsp_core.pc = newpc; + cur_inst_len = 0; + + dsp_core.instr_cycle += 2; +} + +static void dsp_jsset_aa(void) +{ + Uint32 memspace, addr, value, newpc, numbit, newaddr; + + memspace = (cur_inst>>6) & 1; + addr = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + value = read_memory(memspace, addr); + newaddr = read_memory_p(dsp_core.pc+1); + + dsp_core.instr_cycle += 4; + + if (value & (1<>6) & 1; + value = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + dsp_calc_ea(value, &addr); + value = read_memory(memspace, addr); + newaddr = read_memory_p(dsp_core.pc+1); + + dsp_core.instr_cycle += 4; + + if (value & (1<>6) & 1; + value = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + addr = 0xffc0 + value; + value = read_memory(memspace, addr); + newaddr = read_memory_p(dsp_core.pc+1); + + dsp_core.instr_cycle += 4; + + if (value & (1<>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + newaddr = read_memory_p(dsp_core.pc+1); + + if ((numreg==DSP_REG_A) || (numreg==DSP_REG_B)) { + dsp_pm_read_accu24(numreg, &value); + } else { + value = dsp_core.registers[numreg]; + } + + dsp_core.instr_cycle += 4; + + if (value & (1<>8) & BITMASK(3); + + srcsave = dsp_core.registers[DSP_REG_R0+srcreg]; + dsp_calc_ea((cur_inst>>8) & BITMASK(5), &value); + srcnew = dsp_core.registers[DSP_REG_R0+srcreg]; + dsp_core.registers[DSP_REG_R0+srcreg] = srcsave; + + dstreg = cur_inst & BITMASK(3); + + if (cur_inst & (1<<3)) { + dsp_core.registers[DSP_REG_N0+dstreg] = srcnew; + } else { + dsp_core.registers[DSP_REG_R0+dstreg] = srcnew; + } + + dsp_core.instr_cycle += 2; +} + +static void dsp_movec_reg(void) +{ + Uint32 numreg1, numreg2, value, dummy; + + /* S1,D2 */ + /* S2,D1 */ + + numreg2 = (cur_inst>>8) & BITMASK(6); + numreg1 = cur_inst & BITMASK(6); + + if (cur_inst & (1<<15)) { + /* Write D1 */ + + if ((numreg2 == DSP_REG_A) || (numreg2 == DSP_REG_B)) { + dsp_pm_read_accu24(numreg2, &value); + } else { + value = dsp_core.registers[numreg2]; + } + value &= BITMASK(registers_mask[numreg1]); + dsp_write_reg(numreg1, value); + } else { + /* Read S1 */ + if (numreg1 == DSP_REG_SSH) { + dsp_stack_pop(&value, &dummy); + } + else { + value = dsp_core.registers[numreg1]; + } + + if (numreg2 == DSP_REG_A) { + dsp_core.registers[DSP_REG_A0] = 0; + dsp_core.registers[DSP_REG_A1] = value & BITMASK(24); + dsp_core.registers[DSP_REG_A2] = value & (1<<23) ? 0xff : 0x0; + } + else if (numreg2 == DSP_REG_B) { + dsp_core.registers[DSP_REG_B0] = 0; + dsp_core.registers[DSP_REG_B1] = value & BITMASK(24); + dsp_core.registers[DSP_REG_B2] = value & (1<<23) ? 0xff : 0x0; + } + else { + dsp_core.registers[numreg2] = value & BITMASK(registers_mask[numreg2]); + } + } +} + +static void dsp_movec_aa(void) +{ + Uint32 numreg, addr, memspace, value, dummy; + + /* x:aa,D1 */ + /* S1,x:aa */ + /* y:aa,D1 */ + /* S1,y:aa */ + + numreg = cur_inst & BITMASK(6); + addr = (cur_inst>>8) & BITMASK(6); + memspace = (cur_inst>>6) & 1; + + if (cur_inst & (1<<15)) { + /* Write D1 */ + value = read_memory(memspace, addr); + value &= BITMASK(registers_mask[numreg]); + dsp_write_reg(numreg, value); + } else { + /* Read S1 */ + if (numreg == DSP_REG_SSH) { + dsp_stack_pop(&value, &dummy); + } + else { + value = dsp_core.registers[numreg]; + } + write_memory(memspace, addr, value); + } +} + +static void dsp_movec_imm(void) +{ + Uint32 numreg, value; + + /* #xx,D1 */ + numreg = cur_inst & BITMASK(6); + value = (cur_inst>>8) & BITMASK(8); + value &= BITMASK(registers_mask[numreg]); + dsp_write_reg(numreg, value); +} + +static void dsp_movec_ea(void) +{ + Uint32 numreg, addr, memspace, ea_mode, value, dummy; + int retour; + + /* x:ea,D1 */ + /* S1,x:ea */ + /* y:ea,D1 */ + /* S1,y:ea */ + /* #xxxx,D1 */ + + numreg = cur_inst & BITMASK(6); + ea_mode = (cur_inst>>8) & BITMASK(6); + memspace = (cur_inst>>6) & 1; + + if (cur_inst & (1<<15)) { + /* Write D1 */ + retour = dsp_calc_ea(ea_mode, &addr); + if (retour) { + value = addr; + } else { + value = read_memory(memspace, addr); + } + value &= BITMASK(registers_mask[numreg]); + dsp_write_reg(numreg, value); + } else { + /* Read S1 */ + dsp_calc_ea(ea_mode, &addr); + if (numreg == DSP_REG_SSH) { + dsp_stack_pop(&value, &dummy); + } + else { + value = dsp_core.registers[numreg]; + } + write_memory(memspace, addr, value); + } +} + +static void dsp_movem_aa(void) +{ + Uint32 numreg, addr, value, dummy; + + numreg = cur_inst & BITMASK(6); + addr = (cur_inst>>8) & BITMASK(6); + + if (cur_inst & (1<<15)) { + /* Write D */ + value = read_memory_p(addr); + value &= BITMASK(registers_mask[numreg]); + dsp_write_reg(numreg, value); + } else { + /* Read S */ + if (numreg == DSP_REG_SSH) { + dsp_stack_pop(&value, &dummy); + } + else if ((numreg == DSP_REG_A) || (numreg == DSP_REG_B)) { + dsp_pm_read_accu24(numreg, &value); + } + else { + value = dsp_core.registers[numreg]; + } + write_memory(DSP_SPACE_P, addr, value); + } + + dsp_core.instr_cycle += 4; +} + +static void dsp_movem_ea(void) +{ + Uint32 numreg, addr, ea_mode, value, dummy; + + numreg = cur_inst & BITMASK(6); + ea_mode = (cur_inst>>8) & BITMASK(6); + dsp_calc_ea(ea_mode, &addr); + + if (cur_inst & (1<<15)) { + /* Write D */ + value = read_memory_p(addr); + value &= BITMASK(registers_mask[numreg]); + dsp_write_reg(numreg, value); + } else { + /* Read S */ + if (numreg == DSP_REG_SSH) { + dsp_stack_pop(&value, &dummy); + } + else if ((numreg == DSP_REG_A) || (numreg == DSP_REG_B)) { + dsp_pm_read_accu24(numreg, &value); + } + else { + value = dsp_core.registers[numreg]; + } + write_memory(DSP_SPACE_P, addr, value); + } + + dsp_core.instr_cycle += 4; +} + +static void dsp_movep_0(void) +{ + /* S,x:pp */ + /* x:pp,D */ + /* S,y:pp */ + /* y:pp,D */ + + Uint32 addr, memspace, numreg, value, dummy; + + addr = 0xffc0 + (cur_inst & BITMASK(6)); + memspace = (cur_inst>>16) & 1; + numreg = (cur_inst>>8) & BITMASK(6); + + if (cur_inst & (1<<15)) { + /* Write pp */ + if ((numreg == DSP_REG_A) || (numreg == DSP_REG_B)) { + dsp_pm_read_accu24(numreg, &value); + } + else if (numreg == DSP_REG_SSH) { + dsp_stack_pop(&value, &dummy); + } + else { + value = dsp_core.registers[numreg]; + } + write_memory(memspace, addr, value); + } else { + /* Read pp */ + value = read_memory(memspace, addr); + value &= BITMASK(registers_mask[numreg]); + dsp_write_reg(numreg, value); + } + + dsp_core.instr_cycle += 2; +} + +static void dsp_movep_1(void) +{ + /* p:ea,x:pp */ + /* x:pp,p:ea */ + /* p:ea,y:pp */ + /* y:pp,p:ea */ + + Uint32 xyaddr, memspace, paddr; + + xyaddr = 0xffc0 + (cur_inst & BITMASK(6)); + dsp_calc_ea((cur_inst>>8) & BITMASK(6), &paddr); + memspace = (cur_inst>>16) & 1; + + if (cur_inst & (1<<15)) { + /* Write pp */ + write_memory(memspace, xyaddr, read_memory_p(paddr)); + } else { + /* Read pp */ + write_memory(DSP_SPACE_P, paddr, read_memory(memspace, xyaddr)); + } + + /* Movep is 4 cycles, but according to the motorola doc, */ + /* movep from p memory to x or y peripheral memory takes */ + /* 2 more cycles, so +4 cycles at total */ + dsp_core.instr_cycle += 4; +} + +static void dsp_movep_23(void) +{ + /* x:ea,x:pp */ + /* y:ea,x:pp */ + /* #xxxxxx,x:pp */ + /* x:pp,x:ea */ + /* x:pp,y:pp */ + /* x:ea,y:pp */ + /* y:ea,y:pp */ + /* #xxxxxx,y:pp */ + /* y:pp,y:ea */ + /* y:pp,x:ea */ + + Uint32 addr, peraddr, easpace, perspace, ea_mode; + int retour; + + peraddr = 0xffc0 + (cur_inst & BITMASK(6)); + perspace = (cur_inst>>16) & 1; + + ea_mode = (cur_inst>>8) & BITMASK(6); + easpace = (cur_inst>>6) & 1; + retour = dsp_calc_ea(ea_mode, &addr); + + if (cur_inst & (1<<15)) { + /* Write pp */ + + if (retour) { + write_memory(perspace, peraddr, addr); + } else { + write_memory(perspace, peraddr, read_memory(easpace, addr)); + } + } else { + /* Read pp */ + write_memory(easpace, addr, read_memory(perspace, peraddr)); + } + + dsp_core.instr_cycle += 2; +} + +static void dsp_norm(void) +{ + Uint32 cursr,cur_e, cur_euz, dest[3], numreg, rreg; + Uint16 newsr; + + cursr = dsp_core.registers[DSP_REG_SR]; + cur_e = (cursr>>DSP_SR_E) & 1; /* E */ + cur_euz = ~cur_e; /* (not E) and U and (not Z) */ + cur_euz &= (cursr>>DSP_SR_U) & 1; + cur_euz &= ~((cursr>>DSP_SR_Z) & 1); + cur_euz &= 1; + + numreg = (cur_inst>>3) & 1; + dest[0] = dsp_core.registers[DSP_REG_A2+numreg]; + dest[1] = dsp_core.registers[DSP_REG_A1+numreg]; + dest[2] = dsp_core.registers[DSP_REG_A0+numreg]; + rreg = DSP_REG_R0+((cur_inst>>8) & BITMASK(3)); + + if (cur_euz) { + newsr = dsp_asl56(dest); + --dsp_core.registers[rreg]; + dsp_core.registers[rreg] &= BITMASK(16); + } else if (cur_e) { + newsr = dsp_asr56(dest); + ++dsp_core.registers[rreg]; + dsp_core.registers[rreg] &= BITMASK(16); + } else { + newsr = 0; + } + + dsp_core.registers[DSP_REG_A2+numreg] = dest[0]; + dsp_core.registers[DSP_REG_A1+numreg] = dest[1]; + dsp_core.registers[DSP_REG_A0+numreg] = dest[2]; + + dsp_ccr_update_e_u_n_z(dest[0], dest[1], dest[2]); + + dsp_core.registers[DSP_REG_SR] &= BITMASK(16)-((1<> 8) & BITMASK(8); + regnum = cur_inst & BITMASK(2); + switch(regnum) { + case 0: + /* mr */ + dsp_core.registers[DSP_REG_SR] |= value<<8; + break; + case 1: + /* ccr */ + dsp_core.registers[DSP_REG_SR] |= value; + break; + case 2: + /* omr */ + dsp_core.registers[DSP_REG_OMR] |= value; + break; + } +} + +/* + REP instruction parameter encoding + + xxxxxxxx 00xxxxxx 0xxxxxxx aa + xxxxxxxx 01xxxxxx 0xxxxxxx ea + xxxxxxxx YYxxxxxx 1xxxxxxx imm + xxxxxxxx 11xxxxxx 0xxxxxxx reg +*/ + +static void dsp_rep_aa(void) +{ + /* x:aa */ + /* y:aa */ + dsp_core.registers[DSP_REG_LCSAVE] = dsp_core.registers[DSP_REG_LC]; + dsp_core.pc_on_rep = 1; /* Not decrement LC at first time */ + dsp_core.loop_rep = 1; /* We are now running rep */ + + dsp_core.registers[DSP_REG_LC]=read_memory((cur_inst>>6) & 1,(cur_inst>>8) & BITMASK(6)); + + dsp_core.instr_cycle += 2; +} + +static void dsp_rep_imm(void) +{ + /* #xxx */ + + dsp_core.registers[DSP_REG_LCSAVE] = dsp_core.registers[DSP_REG_LC]; + dsp_core.pc_on_rep = 1; /* Not decrement LC at first time */ + dsp_core.loop_rep = 1; /* We are now running rep */ + + dsp_core.registers[DSP_REG_LC] = ((cur_inst>>8) & BITMASK(8)) + + ((cur_inst & BITMASK(4))<<8); + + dsp_core.instr_cycle += 2; +} + +static void dsp_rep_ea(void) +{ + Uint32 value; + + /* x:ea */ + /* y:ea */ + + dsp_core.registers[DSP_REG_LCSAVE] = dsp_core.registers[DSP_REG_LC]; + dsp_core.pc_on_rep = 1; /* Not decrement LC at first time */ + dsp_core.loop_rep = 1; /* We are now running rep */ + + dsp_calc_ea((cur_inst>>8) & BITMASK(6),&value); + dsp_core.registers[DSP_REG_LC]= read_memory((cur_inst>>6) & 1, value); + + dsp_core.instr_cycle += 2; +} + +static void dsp_rep_reg(void) +{ + Uint32 numreg; + + /* R */ + + dsp_core.registers[DSP_REG_LCSAVE] = dsp_core.registers[DSP_REG_LC]; + dsp_core.pc_on_rep = 1; /* Not decrement LC at first time */ + dsp_core.loop_rep = 1; /* We are now running rep */ + + numreg = (cur_inst>>8) & BITMASK(6); + if ((numreg == DSP_REG_A) || (numreg == DSP_REG_B)) { + dsp_pm_read_accu24(numreg, &dsp_core.registers[DSP_REG_LC]); + } else { + dsp_core.registers[DSP_REG_LC] = dsp_core.registers[numreg]; + } + dsp_core.registers[DSP_REG_LC] &= BITMASK(16); + + dsp_core.instr_cycle += 2; +} + +static void dsp_reset(void) +{ + /* Reset external peripherals */ + dsp_core.instr_cycle += 2; +} + +static void dsp_rti(void) +{ + Uint32 newpc = 0, newsr = 0; + + dsp_stack_pop(&newpc, &newsr); + dsp_core.pc = newpc; + dsp_core.registers[DSP_REG_SR] = newsr; + cur_inst_len = 0; + + dsp_core.instr_cycle += 2; +} + +static void dsp_rts(void) +{ + Uint32 newpc = 0, newsr; + + dsp_stack_pop(&newpc, &newsr); + dsp_core.pc = newpc; + cur_inst_len = 0; + + dsp_core.instr_cycle += 2; +} + +static void dsp_stop(void) +{ + LOG_TRACE(TRACE_DSP_STATE, "Dsp: STOP instruction\n"); +} + +static void dsp_swi(void) +{ + /* Raise interrupt p:0x0006 */ + dsp_core.instr_cycle += 6; +} + +static void dsp_tcc(void) +{ + Uint32 cc_code, regsrc1, regdest1; + Uint32 regsrc2, regdest2; + Uint32 val0, val1, val2; + + cc_code = (cur_inst>>12) & BITMASK(4); + + if (dsp_calc_cc(cc_code)) { + regsrc1 = registers_tcc[(cur_inst>>3) & BITMASK(4)][0]; + regdest1 = registers_tcc[(cur_inst>>3) & BITMASK(4)][1]; + + /* Read S1 */ + if (regsrc1 == DSP_REG_A) { + val0 = dsp_core.registers[DSP_REG_A0]; + val1 = dsp_core.registers[DSP_REG_A1]; + val2 = dsp_core.registers[DSP_REG_A2]; + } + else if (regsrc1 == DSP_REG_B) { + val0 = dsp_core.registers[DSP_REG_B0]; + val1 = dsp_core.registers[DSP_REG_B1]; + val2 = dsp_core.registers[DSP_REG_B2]; + } + else { + val0 = 0; + val1 = dsp_core.registers[regsrc1]; + val2 = val1 & (1<<23) ? 0xff : 0x0; + } + + /* Write D1 */ + if (regdest1 == DSP_REG_A) { + dsp_core.registers[DSP_REG_A2] = val2; + dsp_core.registers[DSP_REG_A1] = val1; + dsp_core.registers[DSP_REG_A0] = val0; + } + else { + dsp_core.registers[DSP_REG_B2] = val2; + dsp_core.registers[DSP_REG_B1] = val1; + dsp_core.registers[DSP_REG_B0] = val0; + } + + /* S2,D2 transfer */ + if (cur_inst & (1<<16)) { + regsrc2 = DSP_REG_R0+((cur_inst>>8) & BITMASK(3)); + regdest2 = DSP_REG_R0+(cur_inst & BITMASK(3)); + + dsp_core.registers[regdest2] = dsp_core.registers[regsrc2]; + } + } +} + +static void dsp_wait(void) +{ + LOG_TRACE(TRACE_DSP_STATE, "Dsp: WAIT instruction\n"); +} + +static int dsp_pm_read_accu24(int numreg, Uint32 *dest) +{ + Uint32 scaling, value, reg; + int got_limited = 0; + + /* Read an accumulator, stores it limited */ + + scaling = (dsp_core.registers[DSP_REG_SR]>>DSP_SR_S0) & BITMASK(2); + reg = numreg & 1; + + value = (dsp_core.registers[DSP_REG_A2+reg]) << 24; + value += dsp_core.registers[DSP_REG_A1+reg]; + + switch(scaling) { + case 0: + /* No scaling */ + break; + case 1: + /* scaling down */ + value >>= 1; + break; + case 2: + /* scaling up */ + value <<= 1; + value |= (dsp_core.registers[DSP_REG_A0+reg]>>23) & 1; + break; + /* indeterminate */ + case 3: + break; + } + + /* limiting ? */ + value &= BITMASK(24); + + if (dsp_core.registers[DSP_REG_A2+reg] == 0) { + if (value <= 0x007fffff) { + /* No limiting */ + *dest=value; + return 0; + } + } + + if (dsp_core.registers[DSP_REG_A2+reg] == 0xff) { + if (value >= 0x00800000) { + /* No limiting */ + *dest=value; + return 0; + } + } + + if (dsp_core.registers[DSP_REG_A2+reg] & (1<<7)) { + /* Limited to maximum negative value */ + *dest=0x00800000; + dsp_core.registers[DSP_REG_SR] |= (1<>15) & 1; + numreg = (cur_inst>>16) & 1; + dsp_calc_ea((cur_inst>>8) & BITMASK(6), &addr); + + /* Save A or B */ + dsp_pm_read_accu24(numreg, &save_accu); + + /* Save X0 or Y0 */ + save_xy0 = dsp_core.registers[DSP_REG_X0+(memspace<<1)]; + + /* Execute parallel instruction */ + opcodes_alu[cur_inst & BITMASK(8)](); + + /* Move [A|B] to [x|y]:ea */ + write_memory(memspace, addr, save_accu); + + /* Move [x|y]0 to [A|B] */ + dsp_core.registers[DSP_REG_A0+numreg] = 0; + dsp_core.registers[DSP_REG_A1+numreg] = save_xy0; + dsp_core.registers[DSP_REG_A2+numreg] = save_xy0 & (1<<23) ? 0xff : 0x0; +} + +static void dsp_pm_1(void) +{ + Uint32 memspace, numreg1, numreg2, value, xy_addr, retour, save_1, save_2; +/* + 0001 ffdf w0mm mrrr x:ea,D1 S2,D2 + S1,x:ea S2,D2 + #xxxxxx,D1 S2,D2 + 0001 deff w1mm mrrr S1,D1 y:ea,D2 + S1,D1 S2,y:ea + S1,D1 #xxxxxx,D2 +*/ + value = (cur_inst>>8) & BITMASK(6); + retour = dsp_calc_ea(value, &xy_addr); + memspace = (cur_inst>>14) & 1; + numreg1 = numreg2 = DSP_REG_NULL; + + if (memspace) { + /* Y: */ + switch((cur_inst>>16) & BITMASK(2)) { + case 0: numreg1 = DSP_REG_Y0; break; + case 1: numreg1 = DSP_REG_Y1; break; + case 2: numreg1 = DSP_REG_A; break; + case 3: numreg1 = DSP_REG_B; break; + } + } else { + /* X: */ + switch((cur_inst>>18) & BITMASK(2)) { + case 0: numreg1 = DSP_REG_X0; break; + case 1: numreg1 = DSP_REG_X1; break; + case 2: numreg1 = DSP_REG_A; break; + case 3: numreg1 = DSP_REG_B; break; + } + } + + if (cur_inst & (1<<15)) { + /* Write D1 */ + if (retour) + save_1 = xy_addr; + else + save_1 = read_memory(memspace, xy_addr); + } else { + /* Read S1 */ + if ((numreg1==DSP_REG_A) || (numreg1==DSP_REG_B)) + dsp_pm_read_accu24(numreg1, &save_1); + else + save_1 = dsp_core.registers[numreg1]; + } + + /* S2 */ + if (memspace) { + /* Y: */ + numreg2 = DSP_REG_A + ((cur_inst>>19) & 1); + } else { + /* X: */ + numreg2 = DSP_REG_A + ((cur_inst>>17) & 1); + } + dsp_pm_read_accu24(numreg2, &save_2); + + + /* Execute parallel instruction */ + opcodes_alu[cur_inst & BITMASK(8)](); + + + /* Write parallel move values */ + if (cur_inst & (1<<15)) { + /* Write D1 */ + if (numreg1 == DSP_REG_A) { + dsp_core.registers[DSP_REG_A0] = 0x0; + dsp_core.registers[DSP_REG_A1] = save_1; + dsp_core.registers[DSP_REG_A2] = save_1 & (1<<23) ? 0xff : 0x0; + } + else if (numreg1 == DSP_REG_B) { + dsp_core.registers[DSP_REG_B0] = 0x0; + dsp_core.registers[DSP_REG_B1] = save_1; + dsp_core.registers[DSP_REG_B2] = save_1 & (1<<23) ? 0xff : 0x0; + } + else { + } dsp_core.registers[numreg1] = save_1; + } else { + /* Read S1 */ + write_memory(memspace, xy_addr, save_1); + } + + /* S2 -> D2 */ + if (memspace) { + /* Y: */ + numreg2 = DSP_REG_X0 + ((cur_inst>>18) & 1); + } else { + /* X: */ + numreg2 = DSP_REG_Y0 + ((cur_inst>>16) & 1); + } + dsp_core.registers[numreg2] = save_2; +} + +static void dsp_pm_2(void) +{ + Uint32 dummy; +/* + 0010 0000 0000 0000 nop + 0010 0000 010m mrrr R update + 0010 00ee eeed dddd S,D + 001d dddd iiii iiii #xx,D +*/ + if ((cur_inst & 0xffff00) == 0x200000) { + /* Execute parallel instruction */ + opcodes_alu[cur_inst & BITMASK(8)](); + return; + } + + if ((cur_inst & 0xffe000) == 0x204000) { + dsp_calc_ea((cur_inst>>8) & BITMASK(5), &dummy); + /* Execute parallel instruction */ + opcodes_alu[cur_inst & BITMASK(8)](); + return; + } + + if ((cur_inst & 0xfc0000) == 0x200000) { + dsp_pm_2_2(); + return; + } + + dsp_pm_3(); +} + +static void dsp_pm_2_2(void) +{ +/* + 0010 00ee eeed dddd S,D +*/ + Uint32 srcreg, dstreg, save_reg; + + srcreg = (cur_inst >> 13) & BITMASK(5); + dstreg = (cur_inst >> 8) & BITMASK(5); + + if ((srcreg == DSP_REG_A) || (srcreg == DSP_REG_B)) + /* Accu to register: limited 24 bits */ + dsp_pm_read_accu24(srcreg, &save_reg); + else + save_reg = dsp_core.registers[srcreg]; + + /* Execute parallel instruction */ + opcodes_alu[cur_inst & BITMASK(8)](); + + /* Write reg */ + if (dstreg == DSP_REG_A) { + dsp_core.registers[DSP_REG_A0] = 0x0; + dsp_core.registers[DSP_REG_A1] = save_reg; + dsp_core.registers[DSP_REG_A2] = save_reg & (1<<23) ? 0xff : 0x0; + } + else if (dstreg == DSP_REG_B) { + dsp_core.registers[DSP_REG_B0] = 0x0; + dsp_core.registers[DSP_REG_B1] = save_reg; + dsp_core.registers[DSP_REG_B2] = save_reg & (1<<23) ? 0xff : 0x0; + } + else { + dsp_core.registers[dstreg] = save_reg & BITMASK(registers_mask[dstreg]); + } +} + +static void dsp_pm_3(void) +{ + Uint32 dstreg, srcvalue; +/* + 001d dddd iiii iiii #xx,R +*/ + + /* Execute parallel instruction */ + opcodes_alu[cur_inst & BITMASK(8)](); + + /* Write reg */ + dstreg = (cur_inst >> 16) & BITMASK(5); + srcvalue = (cur_inst >> 8) & BITMASK(8); + + switch(dstreg) { + case DSP_REG_X0: + case DSP_REG_X1: + case DSP_REG_Y0: + case DSP_REG_Y1: + case DSP_REG_A: + case DSP_REG_B: + srcvalue <<= 16; + break; + } + + if (dstreg == DSP_REG_A) { + dsp_core.registers[DSP_REG_A0] = 0x0; + dsp_core.registers[DSP_REG_A1] = srcvalue; + dsp_core.registers[DSP_REG_A2] = srcvalue & (1<<23) ? 0xff : 0x0; + } + else if (dstreg == DSP_REG_B) { + dsp_core.registers[DSP_REG_B0] = 0x0; + dsp_core.registers[DSP_REG_B1] = srcvalue; + dsp_core.registers[DSP_REG_B2] = srcvalue & (1<<23) ? 0xff : 0x0; + } + else { + dsp_core.registers[dstreg] = srcvalue & BITMASK(registers_mask[dstreg]); + } +} + +static void dsp_pm_4(void) +{ +/* + 0100 l0ll w0aa aaaa l:aa,D + S,l:aa + 0100 l0ll w1mm mrrr l:ea,D + S,l:ea + 01dd 0ddd w0aa aaaa x:aa,D + S,x:aa + 01dd 0ddd w1mm mrrr x:ea,D + S,x:ea + #xxxxxx,D + 01dd 1ddd w0aa aaaa y:aa,D + S,y:aa + 01dd 1ddd w1mm mrrr y:ea,D + S,y:ea + #xxxxxx,D +*/ + if ((cur_inst & 0xf40000)==0x400000) { + dsp_pm_4x(); + return; + } + + dsp_pm_5(); +} + +static void dsp_pm_4x(void) +{ + Uint32 value, numreg, l_addr, save_lx, save_ly; +/* + 0100 l0ll w0aa aaaa l:aa,D + S,l:aa + 0100 l0ll w1mm mrrr l:ea,D + S,l:ea +*/ + value = (cur_inst>>8) & BITMASK(6); + if (cur_inst & (1<<14)) { + dsp_calc_ea(value, &l_addr); + } else { + l_addr = value; + } + + numreg = (cur_inst>>16) & BITMASK(2); + numreg |= (cur_inst>>17) & (1<<2); + + if (cur_inst & (1<<15)) { + /* Write D */ + save_lx = read_memory(DSP_SPACE_X,l_addr); + save_ly = read_memory(DSP_SPACE_Y,l_addr); + } + else { + /* Read S */ + switch(numreg) { + case 0: + /* A10 */ + save_lx = dsp_core.registers[DSP_REG_A1]; + save_ly = dsp_core.registers[DSP_REG_A0]; + break; + case 1: + /* B10 */ + save_lx = dsp_core.registers[DSP_REG_B1]; + save_ly = dsp_core.registers[DSP_REG_B0]; + break; + case 2: + /* X */ + save_lx = dsp_core.registers[DSP_REG_X1]; + save_ly = dsp_core.registers[DSP_REG_X0]; + break; + case 3: + /* Y */ + save_lx = dsp_core.registers[DSP_REG_Y1]; + save_ly = dsp_core.registers[DSP_REG_Y0]; + break; + case 4: + /* A */ + if (dsp_pm_read_accu24(DSP_REG_A, &save_lx)) { + /* Was limited, set lower part */ + save_ly = (save_lx & (1<<23) ? 0 : 0xffffff); + } else { + /* Not limited */ + save_ly = dsp_core.registers[DSP_REG_A0]; + } + break; + case 5: + /* B */ + if (dsp_pm_read_accu24(DSP_REG_B, &save_lx)) { + /* Was limited, set lower part */ + save_ly = (save_lx & (1<<23) ? 0 : 0xffffff); + } else { + /* Not limited */ + save_ly = dsp_core.registers[DSP_REG_B0]; + } + break; + case 6: + /* AB */ + dsp_pm_read_accu24(DSP_REG_A, &save_lx); + dsp_pm_read_accu24(DSP_REG_B, &save_ly); + break; + case 7: + /* BA */ + dsp_pm_read_accu24(DSP_REG_B, &save_lx); + dsp_pm_read_accu24(DSP_REG_A, &save_ly); + break; + } + } + + /* Execute parallel instruction */ + opcodes_alu[cur_inst & BITMASK(8)](); + + + if (cur_inst & (1<<15)) { + /* Write D */ + switch(numreg) { + case 0: /* A10 */ + dsp_core.registers[DSP_REG_A1] = save_lx; + dsp_core.registers[DSP_REG_A0] = save_ly; + break; + case 1: /* B10 */ + dsp_core.registers[DSP_REG_B1] = save_lx; + dsp_core.registers[DSP_REG_B0] = save_ly; + break; + case 2: /* X */ + dsp_core.registers[DSP_REG_X1] = save_lx; + dsp_core.registers[DSP_REG_X0] = save_ly; + break; + case 3: /* Y */ + dsp_core.registers[DSP_REG_Y1] = save_lx; + dsp_core.registers[DSP_REG_Y0] = save_ly; + break; + case 4: /* A */ + dsp_core.registers[DSP_REG_A0] = save_ly; + dsp_core.registers[DSP_REG_A1] = save_lx; + dsp_core.registers[DSP_REG_A2] = save_lx & (1<<23) ? 0xff : 0; + break; + case 5: /* B */ + dsp_core.registers[DSP_REG_B0] = save_ly; + dsp_core.registers[DSP_REG_B1] = save_lx; + dsp_core.registers[DSP_REG_B2] = save_lx & (1<<23) ? 0xff : 0; + break; + case 6: /* AB */ + dsp_core.registers[DSP_REG_A0] = 0; + dsp_core.registers[DSP_REG_A1] = save_lx; + dsp_core.registers[DSP_REG_A2] = save_lx & (1<<23) ? 0xff : 0; + dsp_core.registers[DSP_REG_B0] = 0; + dsp_core.registers[DSP_REG_B1] = save_ly; + dsp_core.registers[DSP_REG_B2] = save_ly & (1<<23) ? 0xff : 0; + break; + case 7: /* BA */ + dsp_core.registers[DSP_REG_B0] = 0; + dsp_core.registers[DSP_REG_B1] = save_lx; + dsp_core.registers[DSP_REG_B2] = save_lx & (1<<23) ? 0xff : 0; + dsp_core.registers[DSP_REG_A0] = 0; + dsp_core.registers[DSP_REG_A1] = save_ly; + dsp_core.registers[DSP_REG_A2] = save_ly & (1<<23) ? 0xff : 0; + break; + } + } + else { + /* Read S */ + write_memory(DSP_SPACE_X, l_addr, save_lx); + write_memory(DSP_SPACE_Y, l_addr, save_ly); + } +} + +static void dsp_pm_5(void) +{ + Uint32 memspace, numreg, value, xy_addr, retour; +/* + 01dd 0ddd w0aa aaaa x:aa,D + S,x:aa + 01dd 0ddd w1mm mrrr x:ea,D + S,x:ea + #xxxxxx,D + 01dd 1ddd w0aa aaaa y:aa,D + S,y:aa + 01dd 1ddd w1mm mrrr y:ea,D + S,y:ea + #xxxxxx,D +*/ + + value = (cur_inst>>8) & BITMASK(6); + + if (cur_inst & (1<<14)) { + retour = dsp_calc_ea(value, &xy_addr); + } else { + xy_addr = value; + retour = 0; + } + + memspace = (cur_inst>>19) & 1; + numreg = (cur_inst>>16) & BITMASK(3); + numreg |= (cur_inst>>17) & (BITMASK(2)<<3); + + if (cur_inst & (1<<15)) { + /* Write D */ + if (retour) + value = xy_addr; + else + value = read_memory(memspace, xy_addr); + } + else { + /* Read S */ + if ((numreg==DSP_REG_A) || (numreg==DSP_REG_B)) + dsp_pm_read_accu24(numreg, &value); + else + value = dsp_core.registers[numreg]; + } + + + /* Execute parallel instruction */ + opcodes_alu[cur_inst & BITMASK(8)](); + + if (cur_inst & (1<<15)) { + /* Write D */ + if (numreg == DSP_REG_A) { + dsp_core.registers[DSP_REG_A0] = 0x0; + dsp_core.registers[DSP_REG_A1] = value; + dsp_core.registers[DSP_REG_A2] = value & (1<<23) ? 0xff : 0x0; + } + else if (numreg == DSP_REG_B) { + dsp_core.registers[DSP_REG_B0] = 0x0; + dsp_core.registers[DSP_REG_B1] = value; + dsp_core.registers[DSP_REG_B2] = value & (1<<23) ? 0xff : 0x0; + } + else { + dsp_core.registers[numreg] = value & BITMASK(registers_mask[numreg]); + } + } + else { + /* Read S */ + write_memory(memspace, xy_addr, value); + } +} + +static void dsp_pm_8(void) +{ + Uint32 ea1, ea2; + Uint32 numreg1, numreg2; + Uint32 save_reg1, save_reg2, x_addr, y_addr; +/* + 1wmm eeff WrrM MRRR x:ea,D1 y:ea,D2 + x:ea,D1 S2,y:ea + S1,x:ea y:ea,D2 + S1,x:ea S2,y:ea +*/ + numreg1 = numreg2 = DSP_REG_NULL; + + ea1 = (cur_inst>>8) & BITMASK(5); + if ((ea1>>3) == 0) { + ea1 |= (1<<5); + } + ea2 = (cur_inst>>13) & BITMASK(2); + ea2 |= (cur_inst>>17) & (BITMASK(2)<<3); + if ((ea1 & (1<<2))==0) { + ea2 |= 1<<2; + } + if ((ea2>>3) == 0) { + ea2 |= (1<<5); + } + + dsp_calc_ea(ea1, &x_addr); + dsp_calc_ea(ea2, &y_addr); + + switch((cur_inst>>18) & BITMASK(2)) { + case 0: numreg1=DSP_REG_X0; break; + case 1: numreg1=DSP_REG_X1; break; + case 2: numreg1=DSP_REG_A; break; + case 3: numreg1=DSP_REG_B; break; + } + switch((cur_inst>>16) & BITMASK(2)) { + case 0: numreg2=DSP_REG_Y0; break; + case 1: numreg2=DSP_REG_Y1; break; + case 2: numreg2=DSP_REG_A; break; + case 3: numreg2=DSP_REG_B; break; + } + + if (cur_inst & (1<<15)) { + /* Write D1 */ + save_reg1 = read_memory(DSP_SPACE_X, x_addr); + } else { + /* Read S1 */ + if ((numreg1==DSP_REG_A) || (numreg1==DSP_REG_B)) + dsp_pm_read_accu24(numreg1, &save_reg1); + else + save_reg1 = dsp_core.registers[numreg1]; + } + + if (cur_inst & (1<<22)) { + /* Write D2 */ + save_reg2 = read_memory(DSP_SPACE_Y, y_addr); + } else { + /* Read S2 */ + if ((numreg2==DSP_REG_A) || (numreg2==DSP_REG_B)) + dsp_pm_read_accu24(numreg2, &save_reg2); + else + save_reg2 = dsp_core.registers[numreg2]; + } + + + /* Execute parallel instruction */ + opcodes_alu[cur_inst & BITMASK(8)](); + + /* Write first parallel move */ + if (cur_inst & (1<<15)) { + /* Write D1 */ + if (numreg1 == DSP_REG_A) { + dsp_core.registers[DSP_REG_A0] = 0x0; + dsp_core.registers[DSP_REG_A1] = save_reg1; + dsp_core.registers[DSP_REG_A2] = save_reg1 & (1<<23) ? 0xff : 0x0; + } + else if (numreg1 == DSP_REG_B) { + dsp_core.registers[DSP_REG_B0] = 0x0; + dsp_core.registers[DSP_REG_B1] = save_reg1; + dsp_core.registers[DSP_REG_B2] = save_reg1 & (1<<23) ? 0xff : 0x0; + } + else { + dsp_core.registers[numreg1] = save_reg1; + } + } else { + /* Read S1 */ + write_memory(DSP_SPACE_X, x_addr, save_reg1); + } + + /* Write second parallel move */ + if (cur_inst & (1<<22)) { + /* Write D2 */ + if (numreg2 == DSP_REG_A) { + dsp_core.registers[DSP_REG_A0] = 0x0; + dsp_core.registers[DSP_REG_A1] = save_reg2; + dsp_core.registers[DSP_REG_A2] = save_reg2 & (1<<23) ? 0xff : 0x0; + } + else if (numreg2 == DSP_REG_B) { + dsp_core.registers[DSP_REG_B0] = 0x0; + dsp_core.registers[DSP_REG_B1] = save_reg2; + dsp_core.registers[DSP_REG_B2] = save_reg2 & (1<<23) ? 0xff : 0x0; + } + else { + dsp_core.registers[numreg2] = save_reg2; + } + } else { + /* Read S2 */ + write_memory(DSP_SPACE_Y, y_addr, save_reg2); + } +} + +/********************************** + * 56bit arithmetic + **********************************/ + +/* source,dest[0] is 55:48 */ +/* source,dest[1] is 47:24 */ +/* source,dest[2] is 23:00 */ + +static Uint16 dsp_abs56(Uint32 *dest) +{ + Uint32 zerodest[3]; + Uint16 newsr; + + /* D=|D| */ + + if (dest[0] & (1<<7)) { + zerodest[0] = zerodest[1] = zerodest[2] = 0; + + newsr = dsp_sub56(dest, zerodest); + + dest[0] = zerodest[0]; + dest[1] = zerodest[1]; + dest[2] = zerodest[2]; + } else { + newsr = 0; + } + + return newsr; +} + +static Uint16 dsp_asl56(Uint32 *dest) +{ + Uint16 overflow, carry; + + /* Shift left dest 1 bit: D<<=1 */ + + carry = (dest[0]>>7) & 1; + + dest[0] <<= 1; + dest[0] |= (dest[1]>>23) & 1; + dest[0] &= BITMASK(8); + + dest[1] <<= 1; + dest[1] |= (dest[2]>>23) & 1; + dest[1] &= BITMASK(24); + + dest[2] <<= 1; + dest[2] &= BITMASK(24); + + overflow = (carry != ((dest[0]>>7) & 1)); + + return (overflow<>=1 */ + + carry = dest[2] & 1; + + dest[2] >>= 1; + dest[2] |= (dest[1] & 1)<<23; + + dest[1] >>= 1; + dest[1] |= (dest[0] & 1)<<23; + + dest[0] >>= 1; + dest[0] |= (dest[0] & (1<<6))<<1; + + return (carry<>7) & 1; + flg_d = (dest[0]>>7) & 1; + + /* Add source to dest: D = D+S */ + dest[2] += source[2]; + dest[1] += source[1]+((dest[2]>>24) & 1); + dest[0] += source[0]+((dest[1]>>24) & 1); + + carry = (dest[0]>>8) & 1; + + dest[2] &= BITMASK(24); + dest[1] &= BITMASK(24); + dest[0] &= BITMASK(8); + + flg_r = (dest[0]>>7) & 1; + + /*set overflow*/ + overflow = (flg_s ^ flg_r) & (flg_d ^ flg_r); + + return (overflow<>24) & 1); + dest[0] -= source[0]+((dest[1]>>24) & 1); + + carry = (dest[0]>>8) & 1; + + dest[2] &= BITMASK(24); + dest[1] &= BITMASK(24); + dest[0] &= BITMASK(8); + + flg_s = (source[0]>>7) & 1; + flg_d = (dest_save>>7) & 1; + flg_r = (dest[0]>>7) & 1; + + /* set overflow */ + overflow = (flg_s ^ flg_d) & (flg_r ^ flg_d); + + return (overflow<>12) & BITMASK(12))*(source2 & BITMASK(12)); + /* bits 0-11 * bits 12-23 */ + part[2]=(source1 & BITMASK(12))*((source2>>12) & BITMASK(12)); + /* bits 12-23 * bits 12-23 */ + part[3]=((source1>>12) & BITMASK(12))*((source2>>12) & BITMASK(12)); + + /* Calc dest 2 */ + dest[2] = part[0]; + dest[2] += (part[1] & BITMASK(12)) << 12; + dest[2] += (part[2] & BITMASK(12)) << 12; + + /* Calc dest 1 */ + dest[1] = (part[1]>>12) & BITMASK(12); + dest[1] += (part[2]>>12) & BITMASK(12); + dest[1] += part[3]; + + /* Calc dest 0 */ + dest[0] = 0; + + /* Add carries */ + value = (dest[2]>>24) & BITMASK(8); + if (value) { + dest[1] += value; + dest[2] &= BITMASK(24); + } + value = (dest[1]>>24) & BITMASK(8); + if (value) { + dest[0] += value; + dest[1] &= BITMASK(24); + } + + /* Get rid of extra sign bit */ + dsp_asl56(dest); + + if (signe) { + zerodest[0] = zerodest[1] = zerodest[2] = 0; + + dsp_sub56(dest, zerodest); + + dest[0] = zerodest[0]; + dest[1] = zerodest[1]; + dest[2] = zerodest[2]; + } +} + +static void dsp_rnd56(Uint32 *dest) +{ + Uint32 rnd_const[3]; + + rnd_const[0] = 0; + + /* Scaling mode S0 */ + if (dsp_core.registers[DSP_REG_SR] & (1<>DSP_SR_C) & 1; + + dest[0] = dsp_core.registers[DSP_REG_A2]; + dest[1] = dsp_core.registers[DSP_REG_A1]; + dest[2] = dsp_core.registers[DSP_REG_A0]; + + source[2] = dsp_core.registers[DSP_REG_X0]; + source[1] = dsp_core.registers[DSP_REG_X1]; + source[0] = source[1] & (1<<23) ? 0xff : 0x0; + + newsr = dsp_add56(source, dest); + + if (curcarry) { + source[0]=0; source[1]=0; source[2]=1; + newsr |= dsp_add56(source, dest); + } + + dsp_core.registers[DSP_REG_A2] = dest[0]; + dsp_core.registers[DSP_REG_A1] = dest[1]; + dsp_core.registers[DSP_REG_A0] = dest[2]; + + dsp_ccr_update_e_u_n_z(dest[0], dest[1], dest[2]); + + dsp_core.registers[DSP_REG_SR] &= BITMASK(16)-((1<>DSP_SR_C) & 1; + + dest[0] = dsp_core.registers[DSP_REG_B2]; + dest[1] = dsp_core.registers[DSP_REG_B1]; + dest[2] = dsp_core.registers[DSP_REG_B0]; + + source[2] = dsp_core.registers[DSP_REG_X0]; + source[1] = dsp_core.registers[DSP_REG_X1]; + source[0] = source[1] & (1<<23) ? 0xff : 0x0; + + newsr = dsp_add56(source, dest); + + if (curcarry) { + source[0]=0; source[1]=0; source[2]=1; + newsr |= dsp_add56(source, dest); + } + + dsp_core.registers[DSP_REG_B2] = dest[0]; + dsp_core.registers[DSP_REG_B1] = dest[1]; + dsp_core.registers[DSP_REG_B0] = dest[2]; + + dsp_ccr_update_e_u_n_z(dest[0], dest[1], dest[2]); + + dsp_core.registers[DSP_REG_SR] &= BITMASK(16)-((1<>DSP_SR_C) & 1; + + dest[0] = dsp_core.registers[DSP_REG_A2]; + dest[1] = dsp_core.registers[DSP_REG_A1]; + dest[2] = dsp_core.registers[DSP_REG_A0]; + + source[2] = dsp_core.registers[DSP_REG_Y0]; + source[1] = dsp_core.registers[DSP_REG_Y1]; + source[0] = source[1] & (1<<23) ? 0xff : 0x0; + + newsr = dsp_add56(source, dest); + + if (curcarry) { + source[0]=0; source[1]=0; source[2]=1; + newsr |= dsp_add56(source, dest); + } + + dsp_core.registers[DSP_REG_A2] = dest[0]; + dsp_core.registers[DSP_REG_A1] = dest[1]; + dsp_core.registers[DSP_REG_A0] = dest[2]; + + dsp_ccr_update_e_u_n_z(dest[0], dest[1], dest[2]); + + dsp_core.registers[DSP_REG_SR] &= BITMASK(16)-((1<>DSP_SR_C) & 1; + + dest[0] = dsp_core.registers[DSP_REG_B2]; + dest[1] = dsp_core.registers[DSP_REG_B1]; + dest[2] = dsp_core.registers[DSP_REG_B0]; + + source[2] = dsp_core.registers[DSP_REG_Y0]; + source[1] = dsp_core.registers[DSP_REG_Y1]; + source[0] = source[1] & (1<<23) ? 0xff : 0x0; + + newsr = dsp_add56(source, dest); + + if (curcarry) { + source[0]=0; source[1]=0; source[2]=1; + newsr |= dsp_add56(source, dest); + } + + dsp_core.registers[DSP_REG_B2] = dest[0]; + dsp_core.registers[DSP_REG_B1] = dest[1]; + dsp_core.registers[DSP_REG_B0] = dest[2]; + + dsp_ccr_update_e_u_n_z(dest[0], dest[1], dest[2]); + + dsp_core.registers[DSP_REG_SR] &= BITMASK(16)-((1<>23) & 1)<>23) & 1)<>23) & 1)<>23) & 1)<>23) & 1)<>23) & 1)<>23) & 1)<>23) & 1)<>23) & 1)<>23) & 1)<>23) & 1)<>23) & 1)<>23) & 1)<>23) & 1)<>23) & 1)<>23) & 1)<>23) & 1; + + dsp_core.registers[DSP_REG_A1] <<= 1; + dsp_core.registers[DSP_REG_A1] &= BITMASK(24); + + dsp_core.registers[DSP_REG_SR] &= BITMASK(16)-((1<>23) & 1)<>23) & 1; + + dsp_core.registers[DSP_REG_B1] <<= 1; + dsp_core.registers[DSP_REG_B1] &= BITMASK(24); + + dsp_core.registers[DSP_REG_SR] &= BITMASK(16)-((1<>23) & 1)<>= 1; + + dsp_core.registers[DSP_REG_SR] &= BITMASK(16)-((1<>= 1; + + dsp_core.registers[DSP_REG_SR] &= BITMASK(16)-((1<>23) & 1)<>23) & 1)<>23) & 1)<>23) & 1)<>23) & 1)<>23) & 1)<>23) & 1)<>23) & 1)<>23) & 1)<>23) & 1)<>23) & 1; + + dsp_core.registers[DSP_REG_A1] <<= 1; + dsp_core.registers[DSP_REG_A1] |= newcarry; + dsp_core.registers[DSP_REG_A1] &= BITMASK(24); + + dsp_core.registers[DSP_REG_SR] &= BITMASK(16)-((1<>23) & 1)<>23) & 1; + + dsp_core.registers[DSP_REG_B1] <<= 1; + dsp_core.registers[DSP_REG_B1] |= newcarry; + dsp_core.registers[DSP_REG_B1] &= BITMASK(24); + + dsp_core.registers[DSP_REG_SR] &= BITMASK(16)-((1<>23) & 1)<>= 1; + dsp_core.registers[DSP_REG_A1] |= newcarry<<23; + + dsp_core.registers[DSP_REG_SR] &= BITMASK(16)-((1<>= 1; + dsp_core.registers[DSP_REG_B1] |= newcarry<<23; + + dsp_core.registers[DSP_REG_SR] &= BITMASK(16)-((1<>(DSP_SR_C)) & 1; + + dest[2] = dsp_core.registers[DSP_REG_A0]; + dest[1] = dsp_core.registers[DSP_REG_A1]; + dest[0] = dsp_core.registers[DSP_REG_A2]; + + source[2] = dsp_core.registers[DSP_REG_X0]; + source[1] = dsp_core.registers[DSP_REG_X1]; + source[0] = source[1] & (1<<23) ? 0xff : 0x0; + + newsr = dsp_sub56(source, dest); + + if (curcarry) { + source[0]=0; source[1]=0; source[2]=1; + newsr |= dsp_sub56(source, dest); + } + + dsp_core.registers[DSP_REG_A2] = dest[0]; + dsp_core.registers[DSP_REG_A1] = dest[1]; + dsp_core.registers[DSP_REG_A0] = dest[2]; + + dsp_ccr_update_e_u_n_z(dest[0], dest[1], dest[2]); + + dsp_core.registers[DSP_REG_SR] &= BITMASK(16)-((1<>(DSP_SR_C)) & 1; + + dest[2] = dsp_core.registers[DSP_REG_B0]; + dest[1] = dsp_core.registers[DSP_REG_B1]; + dest[0] = dsp_core.registers[DSP_REG_B2]; + + source[2] = dsp_core.registers[DSP_REG_X0]; + source[1] = dsp_core.registers[DSP_REG_X1]; + source[0] = source[1] & (1<<23) ? 0xff : 0x0; + + newsr = dsp_sub56(source, dest); + + if (curcarry) { + source[0]=0; source[1]=0; source[2]=1; + newsr |= dsp_sub56(source, dest); + } + + dsp_core.registers[DSP_REG_B2] = dest[0]; + dsp_core.registers[DSP_REG_B1] = dest[1]; + dsp_core.registers[DSP_REG_B0] = dest[2]; + + dsp_ccr_update_e_u_n_z(dest[0], dest[1], dest[2]); + + dsp_core.registers[DSP_REG_SR] &= BITMASK(16)-((1<>(DSP_SR_C)) & 1; + + dest[2] = dsp_core.registers[DSP_REG_A0]; + dest[1] = dsp_core.registers[DSP_REG_A1]; + dest[0] = dsp_core.registers[DSP_REG_A2]; + + source[2] = dsp_core.registers[DSP_REG_Y0]; + source[1] = dsp_core.registers[DSP_REG_Y1]; + source[0] = source[1] & (1<<23) ? 0xff : 0x0; + + newsr = dsp_sub56(source, dest); + + if (curcarry) { + source[0]=0; source[1]=0; source[2]=1; + newsr |= dsp_sub56(source, dest); + } + + dsp_core.registers[DSP_REG_A2] = dest[0]; + dsp_core.registers[DSP_REG_A1] = dest[1]; + dsp_core.registers[DSP_REG_A0] = dest[2]; + + dsp_ccr_update_e_u_n_z(dest[0], dest[1], dest[2]); + + dsp_core.registers[DSP_REG_SR] &= BITMASK(16)-((1<>(DSP_SR_C)) & 1; + + dest[2] = dsp_core.registers[DSP_REG_B0]; + dest[1] = dsp_core.registers[DSP_REG_B1]; + dest[0] = dsp_core.registers[DSP_REG_B2]; + + source[2] = dsp_core.registers[DSP_REG_Y0]; + source[1] = dsp_core.registers[DSP_REG_Y1]; + source[0] = source[1] & (1<<23) ? 0xff : 0x0; + + newsr = dsp_sub56(source, dest); + + if (curcarry) { + source[0]=0; source[1]=0; source[2]=1; + newsr |= dsp_sub56(source, dest); + } + + dsp_core.registers[DSP_REG_B2] = dest[0]; + dsp_core.registers[DSP_REG_B1] = dest[1]; + dsp_core.registers[DSP_REG_B0] = dest[2]; + + dsp_ccr_update_e_u_n_z(dest[0], dest[1], dest[2]); + + dsp_core.registers[DSP_REG_SR] &= BITMASK(16)-((1< +#include +#include +#include + +#include "dsp_core.h" +#include "dsp_cpu.h" +#include "dsp_disasm.h" +#include "profile.h" + + +/* More disasm infos, if wanted */ +#define DSP_DISASM_REG_PC 0 + +/********************************** + * Defines + **********************************/ + +/********************************** + * Variables + **********************************/ + +/* Current instruction */ +static Uint32 cur_inst; +static Uint16 disasm_cur_inst_len; +static char str_instr[50]; +static char str_instr2[120]; +static char parallelmove_name[64]; + +/* Previous instruction */ +static Uint32 prev_inst_pc; +static bool isLooping; + +/* Used to display dc instead of unknown instruction for illegal opcodes */ +static bool isInDisasmMode; + +void dsp56k_disasm_init(void) +{ + prev_inst_pc = 0x10000; /* Init to an invalid value */ + isLooping = false; + isInDisasmMode = false; +} + +/********************************** + * Register change + **********************************/ + +static Uint32 registers_save[64]; +#if DSP_DISASM_REG_PC +static Uint32 pc_save; +#endif + +static const char *registers_name[64]={ + "","","","", + "x0","x1","y0","y1", + "a0","b0","a2","b2", + "a1","b1","a","b", + + "r0","r1","r2","r3", + "r4","r5","r6","r7", + "n0","n1","n2","n3", + "n4","n5","n6","n7", + + "m0","m1","m2","m3", + "m4","m5","m6","m7", + "","","","", + "","","","", + + "","","","", + "","","","", + "","sr","omr","sp", + "ssh","ssl","la","lc" +}; + +/********************************** + * Opcode disassembler + **********************************/ + +static Uint32 read_memory(Uint32 currPc); + +typedef void (*dsp_emul_t)(void); + +static void opcode8h_0(void); + +static int dsp_calc_ea(Uint32 ea_mode, char *dest); +static void dsp_calc_cc(Uint32 cc_mode, char *dest); +static void dsp_undefined(void); + +/* Instructions without parallel moves */ +static void dsp_andi(void); +static void dsp_bchg_aa(void); +static void dsp_bchg_ea(void); +static void dsp_bchg_pp(void); +static void dsp_bchg_reg(void); +static void dsp_bclr_aa(void); +static void dsp_bclr_ea(void); +static void dsp_bclr_pp(void); +static void dsp_bclr_reg(void); +static void dsp_bset_aa(void); +static void dsp_bset_ea(void); +static void dsp_bset_pp(void); +static void dsp_bset_reg(void); +static void dsp_btst_aa(void); +static void dsp_btst_ea(void); +static void dsp_btst_pp(void); +static void dsp_btst_reg(void); +static void dsp_div(void); +static void dsp_enddo(void); +static void dsp_illegal(void); +static void dsp_jcc_imm(void); +static void dsp_jcc_ea(void); +static void dsp_jclr_aa(void); +static void dsp_jclr_ea(void); +static void dsp_jclr_pp(void); +static void dsp_jclr_reg(void); +static void dsp_jmp_ea(void); +static void dsp_jmp_imm(void); +static void dsp_jscc_ea(void); +static void dsp_jscc_imm(void); +static void dsp_jsclr_aa(void); +static void dsp_jsclr_ea(void); +static void dsp_jsclr_pp(void); +static void dsp_jsclr_reg(void); +static void dsp_jset_aa(void); +static void dsp_jset_ea(void); +static void dsp_jset_pp(void); +static void dsp_jset_reg(void); +static void dsp_jsr_ea(void); +static void dsp_jsr_imm(void); +static void dsp_jsset_aa(void); +static void dsp_jsset_ea(void); +static void dsp_jsset_pp(void); +static void dsp_jsset_reg(void); +static void dsp_lua(void); +static void dsp_movem_ea(void); +static void dsp_movem_aa(void); +static void dsp_nop(void); +static void dsp_norm(void); +static void dsp_ori(void); +static void dsp_reset(void); +static void dsp_rti(void); +static void dsp_rts(void); +static void dsp_stop(void); +static void dsp_swi(void); +static void dsp_tcc(void); +static void dsp_wait(void); +static void dsp_do_ea(void); +static void dsp_do_aa(void); +static void dsp_do_imm(void); +static void dsp_do_reg(void); +static void dsp_rep_aa(void); +static void dsp_rep_ea(void); +static void dsp_rep_imm(void); +static void dsp_rep_reg(void); +static void dsp_movec_aa(void); +static void dsp_movec_ea(void); +static void dsp_movec_imm(void); +static void dsp_movec_reg(void); +static void dsp_movep_0(void); +static void dsp_movep_1(void); +static void dsp_movep_23(void); + +/* Parallel moves */ +static void dsp_pm_class2(void); +static void dsp_pm(void); +static void dsp_pm_0(void); +static void dsp_pm_1(void); +static void dsp_pm_2(void); +static void dsp_pm_4(void); +static void dsp_pm_8(void); + + +static const dsp_emul_t opcodes8h[512] = { + /* 0x00 - 0x3f */ + opcode8h_0, dsp_undefined, dsp_undefined, dsp_undefined, opcode8h_0, dsp_andi, dsp_undefined, dsp_ori, + dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_andi, dsp_undefined, dsp_ori, + dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_andi, dsp_undefined, dsp_ori, + dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_andi, dsp_undefined, dsp_ori, + dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, + dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, + dsp_undefined, dsp_undefined, dsp_div, dsp_div, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, + dsp_norm, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, + + /* 0x40 - 0x7f */ + dsp_tcc, dsp_tcc, dsp_tcc, dsp_tcc, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, + dsp_tcc, dsp_tcc, dsp_tcc, dsp_tcc, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, + dsp_tcc, dsp_tcc, dsp_tcc, dsp_tcc, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, + dsp_tcc, dsp_tcc, dsp_tcc, dsp_tcc, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, + dsp_tcc, dsp_tcc, dsp_tcc, dsp_tcc, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, + dsp_tcc, dsp_tcc, dsp_tcc, dsp_tcc, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, + dsp_tcc, dsp_tcc, dsp_tcc, dsp_tcc, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, + dsp_tcc, dsp_tcc, dsp_tcc, dsp_tcc, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, + + /* 0x80 - 0xbf */ + dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, + dsp_lua, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_movec_reg, dsp_undefined, dsp_undefined, + dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, + dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_movec_reg, dsp_undefined, dsp_undefined, + dsp_undefined, dsp_movec_aa, dsp_undefined, dsp_movec_aa, dsp_undefined, dsp_movec_imm, dsp_undefined, dsp_undefined, + dsp_undefined, dsp_movec_ea, dsp_undefined, dsp_movec_ea, dsp_undefined, dsp_movec_imm, dsp_undefined, dsp_undefined, + dsp_undefined, dsp_movec_aa, dsp_undefined, dsp_movec_aa, dsp_undefined, dsp_movec_imm, dsp_undefined, dsp_undefined, + dsp_undefined, dsp_movec_ea, dsp_undefined, dsp_movec_ea, dsp_undefined, dsp_movec_imm, dsp_undefined, dsp_undefined, + + /* 0xc0 - 0xff */ + dsp_do_aa, dsp_rep_aa, dsp_do_aa, dsp_rep_aa, dsp_do_imm, dsp_rep_imm, dsp_undefined, dsp_undefined, + dsp_do_ea, dsp_rep_ea, dsp_do_ea, dsp_rep_ea, dsp_do_imm, dsp_rep_imm, dsp_undefined, dsp_undefined, + dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_do_imm, dsp_rep_imm, dsp_undefined, dsp_undefined, + dsp_do_reg, dsp_rep_reg, dsp_undefined, dsp_undefined, dsp_do_imm, dsp_rep_imm, dsp_undefined, dsp_undefined, + dsp_movem_aa, dsp_movem_aa, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, + dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_movem_ea, dsp_movem_ea, dsp_undefined, dsp_undefined, + dsp_movem_aa, dsp_movem_aa, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, + dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_movem_ea, dsp_movem_ea, dsp_undefined, dsp_undefined, + + /* 0x100 - 0x13f */ + dsp_pm_class2, dsp_pm_class2, dsp_pm_class2, dsp_pm_class2, dsp_pm_class2, dsp_pm_class2, dsp_pm_class2, dsp_pm_class2, + dsp_movep_0, dsp_movep_0, dsp_movep_1, dsp_movep_1, dsp_movep_23, dsp_movep_23, dsp_movep_23, dsp_movep_23, + dsp_pm_class2, dsp_pm_class2, dsp_pm_class2, dsp_pm_class2, dsp_pm_class2, dsp_pm_class2, dsp_pm_class2, dsp_pm_class2, + dsp_movep_0, dsp_movep_0, dsp_movep_1, dsp_movep_1, dsp_movep_23, dsp_movep_23, dsp_movep_23, dsp_movep_23, + dsp_pm_class2, dsp_pm_class2, dsp_pm_class2, dsp_pm_class2, dsp_pm_class2, dsp_pm_class2, dsp_pm_class2, dsp_pm_class2, + dsp_movep_0, dsp_movep_0, dsp_movep_1, dsp_movep_1, dsp_movep_23, dsp_movep_23, dsp_movep_23, dsp_movep_23, + dsp_pm_class2, dsp_pm_class2, dsp_pm_class2, dsp_pm_class2, dsp_pm_class2, dsp_pm_class2, dsp_pm_class2, dsp_pm_class2, + dsp_movep_0, dsp_movep_0, dsp_movep_1, dsp_movep_1, dsp_movep_23, dsp_movep_23, dsp_movep_23, dsp_movep_23, + + /* 0x140 - 0x17f */ + dsp_bclr_aa, dsp_bset_aa, dsp_bclr_aa, dsp_bset_aa, dsp_jclr_aa, dsp_jset_aa, dsp_jclr_aa, dsp_jset_aa, + dsp_bclr_ea, dsp_bset_ea, dsp_bclr_ea, dsp_bset_ea, dsp_jclr_ea, dsp_jset_ea, dsp_jclr_ea, dsp_jset_ea, + dsp_bclr_pp, dsp_bset_pp, dsp_bclr_pp, dsp_bset_pp, dsp_jclr_pp, dsp_jset_pp, dsp_jclr_pp, dsp_jset_pp, + dsp_jclr_reg, dsp_jset_reg, dsp_bclr_reg, dsp_bset_reg, dsp_jmp_ea, dsp_jcc_ea, dsp_undefined, dsp_undefined, + dsp_bchg_aa, dsp_btst_aa, dsp_bchg_aa, dsp_btst_aa, dsp_jsclr_aa, dsp_jsset_aa, dsp_jsclr_aa, dsp_jsset_aa, + dsp_bchg_ea, dsp_btst_ea, dsp_bchg_ea, dsp_btst_ea, dsp_jsclr_ea, dsp_jsset_ea, dsp_jsclr_ea, dsp_jsset_ea, + dsp_bchg_pp, dsp_btst_pp, dsp_bchg_pp, dsp_btst_pp, dsp_jsclr_pp, dsp_jsset_pp, dsp_jsclr_pp, dsp_jsset_pp, + dsp_jsclr_reg, dsp_jsset_reg, dsp_bchg_reg, dsp_btst_reg, dsp_jsr_ea, dsp_jscc_ea, dsp_undefined, dsp_undefined, + + /* 0x180 - 0x1bf */ + dsp_jmp_imm, dsp_jmp_imm, dsp_jmp_imm, dsp_jmp_imm, dsp_jmp_imm, dsp_jmp_imm, dsp_jmp_imm, dsp_jmp_imm, + dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, + dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, + dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, + dsp_jsr_imm, dsp_jsr_imm, dsp_jsr_imm, dsp_jsr_imm, dsp_jsr_imm, dsp_jsr_imm, dsp_jsr_imm, dsp_jsr_imm, + dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, + dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, + dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, dsp_undefined, + + /* 0x1c0 - 0x1ff */ + dsp_jcc_imm, dsp_jcc_imm, dsp_jcc_imm, dsp_jcc_imm, dsp_jcc_imm, dsp_jcc_imm, dsp_jcc_imm, dsp_jcc_imm, + dsp_jcc_imm, dsp_jcc_imm, dsp_jcc_imm, dsp_jcc_imm, dsp_jcc_imm, dsp_jcc_imm, dsp_jcc_imm, dsp_jcc_imm, + dsp_jcc_imm, dsp_jcc_imm, dsp_jcc_imm, dsp_jcc_imm, dsp_jcc_imm, dsp_jcc_imm, dsp_jcc_imm, dsp_jcc_imm, + dsp_jcc_imm, dsp_jcc_imm, dsp_jcc_imm, dsp_jcc_imm, dsp_jcc_imm, dsp_jcc_imm, dsp_jcc_imm, dsp_jcc_imm, + dsp_jscc_imm, dsp_jscc_imm, dsp_jscc_imm, dsp_jscc_imm, dsp_jscc_imm, dsp_jscc_imm, dsp_jscc_imm, dsp_jscc_imm, + dsp_jscc_imm, dsp_jscc_imm, dsp_jscc_imm, dsp_jscc_imm, dsp_jscc_imm, dsp_jscc_imm, dsp_jscc_imm, dsp_jscc_imm, + dsp_jscc_imm, dsp_jscc_imm, dsp_jscc_imm, dsp_jscc_imm, dsp_jscc_imm, dsp_jscc_imm, dsp_jscc_imm, dsp_jscc_imm, + dsp_jscc_imm, dsp_jscc_imm, dsp_jscc_imm, dsp_jscc_imm, dsp_jscc_imm, dsp_jscc_imm, dsp_jscc_imm, dsp_jscc_imm, +}; + +static const char* opcodes_alu[256] = { + /* 0x00 - 0x3f */ + "move" , "tfr b,a", "addr b,a", "tst a", "undefined", "cmp b,a" , "subr b,a", "cmpm b,a", + "undefined", "tfr a,b", "addr a,b", "tst b", "undefined", "cmp a,b" , "subr a,b", "cmpm a,b", + "add b,a" , "rnd a" , "addl b,a", "clr a", "sub b,a" , "undefined", "subl b,a", "not a", + "add a,b" , "rnd b" , "addl a,b", "clr b", "sub a,b" , "undefined", "subl a,b", "not b", + "add x,a" , "adc x,a", "asr a" , "lsr a", "sub x,a" , "sbc x,a" , "abs a" , "ror a", + "add x,b" , "adc x,b", "asr b" , "lsr b", "sub x,b" , "sbc x,b" , "abs b" , "ror b", + "add y,a" , "adc y,a", "asl a" , "lsl a", "sub y,a" , "sbc y,a" , "neg a" , "rol a", + "add y,b" , "adc y,b", "asl b" , "lsl b", "sub y,b" , "sbc y,b" , "neg b" , "rol b", + + /* 0x40 - 0x7f */ + "add x0,a", "tfr x0,a", "or x0,a", "eor x0,a", "sub x0,a", "cmp x0,a", "and x0,a", "cmpm x0,a", + "add x0,b", "tfr x0,b", "or x0,b", "eor x0,b", "sub x0,b", "cmp x0,b", "and x0,b", "cmpm x0,b", + "add y0,a", "tfr y0,a", "or y0,a", "eor y0,a", "sub y0,a", "cmp y0,a", "and y0,a", "cmpm y0,a", + "add y0,b", "tfr y0,b", "or y0,b", "eor y0,b", "sub y0,b", "cmp y0,b", "and y0,b", "cmpm y0,b", + "add x1,a", "tfr x1,a", "or x1,a", "eor x1,a", "sub x1,a", "cmp x1,a", "and x1,a", "cmpm x1,a", + "add x1,b", "tfr x1,b", "or x1,b", "eor x1,b", "sub x1,b", "cmp x1,b", "and x1,b", "cmpm x1,b", + "add y1,a", "tfr y1,a", "or y1,a", "eor y1,a", "sub y1,a", "cmp y1,a", "and y1,a", "cmpm y1,a", + "add y1,b", "tfr y1,b", "or y1,b", "eor y1,b", "sub y1,b", "cmp y1,b", "and y1,b", "cmpm y1,b", + + /* 0x80 - 0xbf */ + "mpy +x0,x0,a", "mpyr +x0,x0,a", "mac +x0,x0,a", "macr +x0,x0,a", "mpy -x0,x0,a", "mpyr -x0,x0,a", "mac -x0,x0,a", "macr -x0,x0,a", + "mpy +x0,x0,b", "mpyr +x0,x0,b", "mac +x0,x0,b", "macr +x0,x0,b", "mpy -x0,x0,b", "mpyr -x0,x0,b", "mac -x0,x0,b", "macr -x0,x0,b", + "mpy +y0,y0,a", "mpyr +y0,y0,a", "mac +y0,y0,a", "macr +y0,y0,a", "mpy -y0,y0,a", "mpyr -y0,y0,a", "mac -y0,y0,a", "macr -y0,y0,a", + "mpy +y0,y0,b", "mpyr +y0,y0,b", "mac +y0,y0,b", "macr +y0,y0,b", "mpy -y0,y0,b", "mpyr -y0,y0,b", "mac -y0,y0,b", "macr -y0,y0,b", + "mpy +x1,x0,a", "mpyr +x1,x0,a", "mac +x1,x0,a", "macr +x1,x0,a", "mpy -x1,x0,a", "mpyr -x1,x0,a", "mac -x1,x0,a", "macr -x1,x0,a", + "mpy +x1,x0,b", "mpyr +x1,x0,b", "mac +x1,x0,b", "macr +x1,x0,b", "mpy -x1,x0,b", "mpyr -x1,x0,b", "mac -x1,x0,b", "macr -x1,x0,b", + "mpy +y1,y0,a", "mpyr +y1,y0,a", "mac +y1,y0,a", "macr +y1,y0,a", "mpy -y1,y0,a", "mpyr -y1,y0,a", "mac -y1,y0,a", "macr -y1,y0,a", + "mpy +y1,y0,b", "mpyr +y1,y0,b", "mac +y1,y0,b", "macr +y1,y0,b", "mpy -y1,y0,b", "mpyr -y1,y0,b", "mac -y1,y0,b", "macr -y1,y0,b", + + /* 0xc0 - 0xff */ + "mpy +x0,y1,a", "mpyr +x0,y1,a", "mac +x0,y1,a", "macr +x0,y1,a", "mpy -x0,y1,a", "mpyr -x0,y1,a", "mac -x0,y1,a", "macr -x0,y1,a", + "mpy +x0,y1,b", "mpyr +x0,y1,b", "mac +x0,y1,b", "macr +x0,y1,b", "mpy -x0,y1,b", "mpyr -x0,y1,b", "mac -x0,y1,b", "macr -x0,y1,b", + "mpy +y0,x0,a", "mpyr +y0,x0,a", "mac +y0,x0,a", "macr +y0,x0,a", "mpy -y0,x0,a", "mpyr -y0,x0,a", "mac -y0,x0,a", "macr -y0,x0,a", + "mpy +y0,x0,b", "mpyr +y0,x0,b", "mac +y0,x0,b", "macr +y0,x0,b", "mpy -y0,x0,b", "mpyr -y0,x0,b", "mac -y0,x0,b", "macr -y0,x0,b", + "mpy +x1,y0,a", "mpyr +x1,y0,a", "mac +x1,y0,a", "macr +x1,y0,a", "mpy -x1,y0,a", "mpyr -x1,y0,a", "mac -x1,y0,a", "macr -x1,y0,a", + "mpy +x1,y0,b", "mpyr +x1,y0,b", "mac +x1,y0,b", "macr +x1,y0,b", "mpy -x1,y0,b", "mpyr -x1,y0,b", "mac -x1,y0,b", "macr -x1,y0,b", + "mpy +y1,x1,a", "mpyr +y1,x1,a", "mac +y1,x1,a", "macr +y1,x1,a", "mpy -y1,x1,a", "mpyr -y1,x1,a", "mac -y1,x1,a", "macr -y1,x1,a", + "mpy +y1,x1,b", "mpyr +y1,x1,b", "mac +y1,x1,b", "macr +y1,x1,b", "mpy -y1,x1,b", "mpyr -y1,x1,b", "mac -y1,x1,b", "macr -y1,x1,b" +}; + + + +static const dsp_emul_t opcodes_parmove[16] = { + dsp_pm_0, + dsp_pm_1, + dsp_pm_2, + dsp_pm_2, + dsp_pm_4, + dsp_pm_4, + dsp_pm_4, + dsp_pm_4, + + dsp_pm_8, + dsp_pm_8, + dsp_pm_8, + dsp_pm_8, + dsp_pm_8, + dsp_pm_8, + dsp_pm_8, + dsp_pm_8 +}; + +static const int registers_tcc[16][2] = { + {DSP_REG_B,DSP_REG_A}, + {DSP_REG_A,DSP_REG_B}, + {DSP_REG_NULL,DSP_REG_NULL}, + {DSP_REG_NULL,DSP_REG_NULL}, + + {DSP_REG_NULL,DSP_REG_NULL}, + {DSP_REG_NULL,DSP_REG_NULL}, + {DSP_REG_NULL,DSP_REG_NULL}, + {DSP_REG_NULL,DSP_REG_NULL}, + + {DSP_REG_X0,DSP_REG_A}, + {DSP_REG_X0,DSP_REG_B}, + {DSP_REG_Y0,DSP_REG_A}, + {DSP_REG_Y0,DSP_REG_B}, + + {DSP_REG_X1,DSP_REG_A}, + {DSP_REG_X1,DSP_REG_B}, + {DSP_REG_Y1,DSP_REG_A}, + {DSP_REG_Y1,DSP_REG_B} +}; + +static const char *registers_lmove[8] = { + "a10", + "b10", + "x", + "y", + "a", + "b", + "ab", + "ba" +}; + +static const char *ea_names[9] = { + "(r%d)-n%d", /* 000xxx */ + "(r%d)+n%d", /* 001xxx */ + "(r%d)-", /* 010xxx */ + "(r%d)+", /* 011xxx */ + "(r%d)", /* 100xxx */ + "(r%d+n%d)", /* 101xxx */ + "$%04x", /* 110000 */ + "-(r%d)", /* 111xxx */ + "$%06x" /* 110100 */ +}; + +static const char *cc_name[16] = { + "cc", + "ge", + "ne", + "pl", + "nn", + "ec", + "lc", + "gt", + + "cs", + "lt", + "eq", + "mi", + "nr", + "es", + "ls", + "le" +}; + +void dsp56k_disasm_reg_save(void) +{ + memcpy(registers_save, dsp_core.registers , sizeof(registers_save)); +#if DSP_DISASM_REG_PC + pc_save = dsp_core.pc; +#endif +} + +void dsp56k_disasm_reg_compare(void) +{ + int i; + bool bRegA = false; + bool bRegB = false; + + for (i=4; i<64; i++) { + if (registers_save[i] == dsp_core.registers[i]) { + continue; + } + + switch(i) { + case DSP_REG_X0: + case DSP_REG_X1: + case DSP_REG_Y0: + case DSP_REG_Y1: + fprintf(stderr,"\tReg: %s $%06x -> $%06x\n", registers_name[i], registers_save[i], dsp_core.registers[i]); + break; + case DSP_REG_R0: + case DSP_REG_R1: + case DSP_REG_R2: + case DSP_REG_R3: + case DSP_REG_R4: + case DSP_REG_R5: + case DSP_REG_R6: + case DSP_REG_R7: + case DSP_REG_M0: + case DSP_REG_M1: + case DSP_REG_M2: + case DSP_REG_M3: + case DSP_REG_M4: + case DSP_REG_M5: + case DSP_REG_M6: + case DSP_REG_M7: + case DSP_REG_N0: + case DSP_REG_N1: + case DSP_REG_N2: + case DSP_REG_N3: + case DSP_REG_N4: + case DSP_REG_N5: + case DSP_REG_N6: + case DSP_REG_N7: + case DSP_REG_SR: + case DSP_REG_LA: + case DSP_REG_LC: + fprintf(stderr,"\tReg: %s $%04x -> $%04x\n", registers_name[i], registers_save[i], dsp_core.registers[i]); + break; + case DSP_REG_OMR: + case DSP_REG_SP: + case DSP_REG_SSH: + case DSP_REG_SSL: + fprintf(stderr,"\tReg: %s $%02x -> $%02x\n", registers_name[i], registers_save[i], dsp_core.registers[i]); + break; + case DSP_REG_A0: + case DSP_REG_A1: + case DSP_REG_A2: + if (bRegA == false) { + fprintf(stderr,"\tReg: a $%02x:%06x:%06x -> $%02x:%06x:%06x\n", + registers_save[DSP_REG_A2], registers_save[DSP_REG_A1], registers_save[DSP_REG_A0], + dsp_core.registers[DSP_REG_A2], dsp_core.registers[DSP_REG_A1], dsp_core.registers[DSP_REG_A0] + ); + bRegA = true; + } + break; + case DSP_REG_B0: + case DSP_REG_B1: + case DSP_REG_B2: + if (bRegB == false) { + fprintf(stderr,"\tReg: b $%02x:%06x:%06x -> $%02x:%06x:%06x\n", + registers_save[DSP_REG_B2], registers_save[DSP_REG_B1], registers_save[DSP_REG_B0], + dsp_core.registers[DSP_REG_B2], dsp_core.registers[DSP_REG_B1], dsp_core.registers[DSP_REG_B0] + ); + bRegB = true; + } + break; + } + } + +#if DSP_DISASM_REG_PC + if (pc_save != dsp_core.pc) { + fprintf(stderr,"\tReg: pc $%04x -> $%04x\n", pc_save, dsp_core.pc); + } +#endif +} + +Uint16 dsp56k_disasm(dsp_trace_disasm_t mode) +{ + Uint32 value; + + if (mode == DSP_TRACE_MODE) { + isInDisasmMode = false; + if (prev_inst_pc == dsp_core.pc) { + if (!isLooping) { + fprintf(stderr, "Looping on DSP instruction at PC = $%04x\n", prev_inst_pc); + isLooping = true; + } + return 0; + } + } + else { + isInDisasmMode = true; + } + + prev_inst_pc = dsp_core.pc; + isLooping = false; + + cur_inst = read_memory(dsp_core.pc); + disasm_cur_inst_len = 1; + + strcpy(parallelmove_name, ""); + + if (cur_inst < 0x100000) { + value = (cur_inst >> 11) & (BITMASK(6) << 3); + value += (cur_inst >> 5) & BITMASK(3); + opcodes8h[value](); + } else { + dsp_pm(); + sprintf(str_instr, "%s %s", opcodes_alu[cur_inst & BITMASK(8)], parallelmove_name); + } + return disasm_cur_inst_len; +} + +/** + * dsp56k_getInstrText : return the disasembled instructions + */ +const char* dsp56k_getInstructionText(void) +{ + const int len = sizeof(str_instr); + Uint64 count, cycles; + Uint16 cycle_diff; + float percentage; + int offset; + + if (isLooping) { + *str_instr2 = 0; + } + if (disasm_cur_inst_len == 1) { + offset = sprintf(str_instr2, "p:%04x %06x (%02d cyc) %-*s\n", prev_inst_pc, cur_inst, dsp_core.instr_cycle, len, str_instr); + } else { + offset = sprintf(str_instr2, "p:%04x %06x %06x (%02d cyc) %-*s\n", prev_inst_pc, cur_inst, read_memory(prev_inst_pc + 1), dsp_core.instr_cycle, len, str_instr); + } + if (offset > 2 && Profile_DspAddressData(prev_inst_pc, &percentage, &count, &cycles, &cycle_diff)) { + offset -= 2; + sprintf(str_instr2+offset, "%5.2f%% (%"PRId64", %"PRId64", %d)\n", + percentage, count, cycles, cycle_diff); + } + return str_instr2; +} + +static void dsp_pm_class2(void) { + dsp_pm(); + sprintf(str_instr, "%s %s", opcodes_alu[cur_inst & BITMASK(8)], parallelmove_name); +} + +static Uint32 read_memory(Uint32 currPc) +{ + Uint32 value; + + if (currPc<0x200) { + value = dsp_core.ramint[DSP_SPACE_P][currPc]; + } else { + value = dsp_core.ramext[currPc & (DSP_RAMSIZE-1)]; + } + + return value & BITMASK(24); +} + +/********************************** + * Conditions code calculation + **********************************/ + +static void dsp_calc_cc(Uint32 cc_mode, char *dest) +{ + strcpy(dest, cc_name[cc_mode & BITMASK(4)]); +} + +/********************************** + * Effective address calculation + **********************************/ + +static int dsp_calc_ea(Uint32 ea_mode, char *dest) +{ + int value, retour, numreg; + + value = (ea_mode >> 3) & BITMASK(3); + numreg = ea_mode & BITMASK(3); + retour = 0; + switch (value) { + case 0: + /* (Rx)-Nx */ + sprintf(dest, ea_names[value], numreg, numreg); + break; + case 1: + /* (Rx)+Nx */ + sprintf(dest, ea_names[value], numreg, numreg); + break; + case 5: + /* (Rx+Nx) */ + sprintf(dest, ea_names[value], numreg, numreg); + break; + case 2: + /* (Rx)- */ + sprintf(dest, ea_names[value], numreg); + break; + case 3: + /* (Rx)+ */ + sprintf(dest, ea_names[value], numreg); + break; + case 4: + /* (Rx) */ + sprintf(dest, ea_names[value], numreg); + break; + case 7: + /* -(Rx) */ + sprintf(dest, ea_names[value], numreg); + break; + case 6: + disasm_cur_inst_len++; + switch ((ea_mode >> 2) & 1) { + case 0: + /* Absolute address */ + sprintf(dest, ea_names[value], read_memory(dsp_core.pc+1)); + break; + case 1: + /* Immediate value */ + sprintf(dest, ea_names[8], read_memory(dsp_core.pc+1)); + retour = 1; + break; + } + break; + } + return retour; +} + +static void opcode8h_0(void) +{ + switch(cur_inst) { + case 0x000000: + dsp_nop(); + break; + case 0x000004: + dsp_rti(); + break; + case 0x000005: + dsp_illegal(); + break; + case 0x000006: + dsp_swi(); + break; + case 0x00000c: + dsp_rts(); + break; + case 0x000084: + dsp_reset(); + break; + case 0x000086: + dsp_wait(); + break; + case 0x000087: + dsp_stop(); + break; + case 0x00008c: + dsp_enddo(); + break; + } +} + +/********************************** + * Non-parallel moves instructions + **********************************/ + +static void dsp_undefined(void) +{ + /* In Disasm mode, display dc instruction_opcode */ + if (isInDisasmMode) + sprintf(str_instr, "dc $%06x", cur_inst); + /* In trace mode, display unknown instruction */ + else + sprintf(str_instr, "$%06x unknown instruction", cur_inst); +} + +static void dsp_andi(void) +{ + switch(cur_inst & BITMASK(2)) { + case 0: + sprintf(str_instr, "andi #$%02x,mr", (cur_inst>>8) & BITMASK(8)); + break; + case 1: + sprintf(str_instr, "andi #$%02x,ccr", (cur_inst>>8) & BITMASK(8)); + break; + case 2: + sprintf(str_instr, "andi #$%02x,omr", (cur_inst>>8) & BITMASK(8)); + break; + default: + break; + } +} + +static void dsp_bchg_aa(void) +{ + /* bchg #n,x:aa */ + /* bchg #n,y:aa */ + char name[16]; + Uint32 memspace, value, numbit; + + memspace = (cur_inst>>6) & 1; + value = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + + if (memspace) { + sprintf(name,"y:$%04x",value); + } else { + sprintf(name,"x:$%04x",value); + } + + sprintf(str_instr,"bchg #%d,%s", numbit, name); +} + +static void dsp_bchg_ea(void) +{ + /* bchg #n,x:ea */ + /* bchg #n,y:ea */ + char name[16], addr_name[16]; + Uint32 memspace, value, numbit; + + memspace = (cur_inst>>6) & 1; + value = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + + dsp_calc_ea(value, addr_name); + if (memspace) { + sprintf(name,"y:%s",addr_name); + } else { + sprintf(name,"x:%s",addr_name); + } + + sprintf(str_instr,"bchg #%d,%s", numbit, name); +} + +static void dsp_bchg_pp(void) +{ + /* bchg #n,x:pp */ + /* bchg #n,y:pp */ + char name[16]; + Uint32 memspace, value, numbit; + + memspace = (cur_inst>>6) & 1; + value = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + + if (memspace) { + sprintf(name,"y:$%04x",value+0xffc0); + } else { + sprintf(name,"x:$%04x",value+0xffc0); + } + + sprintf(str_instr,"bchg #%d,%s", numbit, name); +} + +static void dsp_bchg_reg(void) +{ + /* bchg #n,R */ + Uint32 value, numbit; + + value = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + + sprintf(str_instr,"bchg #%d,%s", numbit, registers_name[value]); +} + +static void dsp_bclr_aa(void) +{ + /* bclr #n,x:aa */ + /* bclr #n,y:aa */ + char name[16]; + Uint32 memspace, value, numbit; + + memspace = (cur_inst>>6) & 1; + value = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + + if (memspace) { + sprintf(name,"y:$%04x",value); + } else { + sprintf(name,"x:$%04x",value); + } + + sprintf(str_instr,"bclr #%d,%s", numbit, name); +} + +static void dsp_bclr_ea(void) +{ + /* bclr #n,x:ea */ + /* bclr #n,y:ea */ + char name[16], addr_name[16]; + Uint32 memspace, value, numbit; + + memspace = (cur_inst>>6) & 1; + value = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + + dsp_calc_ea(value, addr_name); + if (memspace) { + sprintf(name,"y:%s",addr_name); + } else { + sprintf(name,"x:%s",addr_name); + } + + sprintf(str_instr,"bclr #%d,%s", numbit, name); +} + +static void dsp_bclr_pp(void) +{ + /* bclr #n,x:pp */ + /* bclr #n,y:pp */ + char name[16]; + Uint32 memspace, value, numbit; + + memspace = (cur_inst>>6) & 1; + value = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + + if (memspace) { + sprintf(name,"y:$%04x",value+0xffc0); + } else { + sprintf(name,"x:$%04x",value+0xffc0); + } + + sprintf(str_instr,"bclr #%d,%s", numbit, name); +} + +static void dsp_bclr_reg(void) +{ + /* bclr #n,R */ + Uint32 value, numbit; + + value = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + + sprintf(str_instr,"bclr #%d,%s", numbit, registers_name[value]); +} + +static void dsp_bset_aa(void) +{ + /* bset #n,x:aa */ + /* bset #n,y:aa */ + char name[16]; + Uint32 memspace, value, numbit; + + memspace = (cur_inst>>6) & 1; + value = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + + if (memspace) { + sprintf(name,"y:$%04x",value); + } else { + sprintf(name,"x:$%04x",value); + } + + sprintf(str_instr,"bset #%d,%s", numbit, name); +} + +static void dsp_bset_ea(void) +{ + /* bset #n,x:ea */ + /* bset #n,y:ea */ + char name[16], addr_name[16]; + Uint32 memspace, value, numbit; + + memspace = (cur_inst>>6) & 1; + value = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + + dsp_calc_ea(value, addr_name); + if (memspace) { + sprintf(name,"y:%s",addr_name); + } else { + sprintf(name,"x:%s",addr_name); + } + + sprintf(str_instr,"bset #%d,%s", numbit, name); +} + +static void dsp_bset_pp(void) +{ + /* bset #n,x:pp */ + /* bset #n,y:pp */ + char name[16]; + Uint32 memspace, value, numbit; + + memspace = (cur_inst>>6) & 1; + value = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + + if (memspace) { + sprintf(name,"y:$%04x",value+0xffc0); + } else { + sprintf(name,"x:$%04x",value+0xffc0); + } + + sprintf(str_instr,"bset #%d,%s", numbit, name); +} + +static void dsp_bset_reg(void) +{ + /* bset #n,R */ + Uint32 value, numbit; + + value = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + + sprintf(str_instr,"bset #%d,%s", numbit, registers_name[value]); +} + +static void dsp_btst_aa(void) +{ + /* btst #n,x:aa */ + /* btst #n,y:aa */ + char name[16]; + Uint32 memspace, value, numbit; + + memspace = (cur_inst>>6) & 1; + value = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + + if (memspace) { + sprintf(name,"y:$%04x",value); + } else { + sprintf(name,"x:$%04x",value); + } + + sprintf(str_instr,"btst #%d,%s", numbit, name); +} + +static void dsp_btst_ea(void) +{ + /* btst #n,x:ea */ + /* btst #n,y:ea */ + char name[16], addr_name[16]; + Uint32 memspace, value, numbit; + + memspace = (cur_inst>>6) & 1; + value = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + + dsp_calc_ea(value, addr_name); + if (memspace) { + sprintf(name,"y:%s",addr_name); + } else { + sprintf(name,"x:%s",addr_name); + } + + sprintf(str_instr,"btst #%d,%s", numbit, name); +} + +static void dsp_btst_pp(void) +{ + /* btst #n,x:pp */ + /* btst #n,y:pp */ + char name[16]; + Uint32 memspace, value, numbit; + + memspace = (cur_inst>>6) & 1; + value = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + + if (memspace) { + sprintf(name,"y:$%04x",value+0xffc0); + } else { + sprintf(name,"x:$%04x",value+0xffc0); + } + + sprintf(str_instr,"btst #%d,%s", numbit, name); +} + +static void dsp_btst_reg(void) +{ + /* btst #n,R */ + Uint32 value, numbit; + + value = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + + sprintf(str_instr,"btst #%d,%s", numbit, registers_name[value]); +} + +static void dsp_div(void) +{ + Uint32 srcreg=DSP_REG_NULL, destreg; + + switch((cur_inst>>4) & BITMASK(2)) { + case 0: + srcreg = DSP_REG_X0; + break; + case 1: + srcreg = DSP_REG_Y0; + break; + case 2: + srcreg = DSP_REG_X1; + break; + case 3: + srcreg = DSP_REG_Y1; + break; + } + destreg = DSP_REG_A+((cur_inst>>3) & 1); + + sprintf(str_instr,"div %s,%s", registers_name[srcreg],registers_name[destreg]); +} + +static void dsp_do_aa(void) +{ + char name[16]; + + disasm_cur_inst_len++; + + if (cur_inst & (1<<6)) { + sprintf(name, "y:$%04x", (cur_inst>>8) & BITMASK(6)); + } else { + sprintf(name, "x:$%04x", (cur_inst>>8) & BITMASK(6)); + } + + sprintf(str_instr,"do %s,p:$%04x", + name, + read_memory(dsp_core.pc+1) + ); +} + +static void dsp_do_imm(void) +{ + disasm_cur_inst_len++; + + sprintf(str_instr,"do #$%04x,p:$%04x", + ((cur_inst>>8) & BITMASK(8))|((cur_inst & BITMASK(4))<<8), + read_memory(dsp_core.pc+1) + ); +} + +static void dsp_do_ea(void) +{ + char addr_name[16], name[16]; + Uint32 ea_mode; + + disasm_cur_inst_len++; + + ea_mode = (cur_inst>>8) & BITMASK(6); + dsp_calc_ea(ea_mode, addr_name); + + if (cur_inst & (1<<6)) { + sprintf(name, "y:%s", addr_name); + } else { + sprintf(name, "x:%s", addr_name); + } + + sprintf(str_instr,"do %s,p:$%04x", + name, + read_memory(dsp_core.pc+1) + ); +} + +static void dsp_do_reg(void) +{ + disasm_cur_inst_len++; + + sprintf(str_instr,"do %s,p:$%04x", + registers_name[(cur_inst>>8) & BITMASK(6)], + read_memory(dsp_core.pc+1) + ); +} + +static void dsp_enddo(void) +{ + sprintf(str_instr,"enddo"); +} + +static void dsp_illegal(void) +{ + sprintf(str_instr,"illegal"); +} + +static void dsp_jcc_ea(void) +{ + char cond_name[16], addr_name[16]; + Uint32 cc_code=0; + + dsp_calc_ea((cur_inst >>8) & BITMASK(6), addr_name); + cc_code=cur_inst & BITMASK(4); + dsp_calc_cc(cc_code, cond_name); + + sprintf(str_instr,"j%s p:%s", cond_name, addr_name); +} + +static void dsp_jcc_imm(void) +{ + char cond_name[16], addr_name[16]; + Uint32 cc_code=0; + + sprintf(addr_name, "$%04x", cur_inst & BITMASK(12)); + cc_code=(cur_inst>>12) & BITMASK(4); + dsp_calc_cc(cc_code, cond_name); + + sprintf(str_instr,"j%s p:%s", cond_name, addr_name); +} + +static void dsp_jclr_aa(void) +{ + /* jclr #n,x:aa,p:xx */ + /* jclr #n,y:aa,p:xx */ + char srcname[16]; + Uint32 memspace, value, numbit; + + disasm_cur_inst_len++; + + memspace = (cur_inst>>6) & 1; + value = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + + if (memspace) { + sprintf(srcname, "y:$%04x", value); + } else { + sprintf(srcname, "x:$%04x", value); + } + + sprintf(str_instr,"jclr #%d,%s,p:$%04x", + numbit, + srcname, + read_memory(dsp_core.pc+1) + ); +} + +static void dsp_jclr_ea(void) +{ + /* jclr #n,x:ea,p:xx */ + /* jclr #n,y:ea,p:xx */ + char srcname[16], addr_name[16]; + Uint32 memspace, value, numbit; + + disasm_cur_inst_len++; + + memspace = (cur_inst>>6) & 1; + value = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + + dsp_calc_ea(value, addr_name); + if (memspace) { + sprintf(srcname, "y:%s", addr_name); + } else { + sprintf(srcname, "x:%s", addr_name); + } + + sprintf(str_instr,"jclr #%d,%s,p:$%04x", + numbit, + srcname, + read_memory(dsp_core.pc+1) + ); +} + +static void dsp_jclr_pp(void) +{ + /* jclr #n,x:pp,p:xx */ + /* jclr #n,y:pp,p:xx */ + char srcname[16]; + Uint32 memspace, value, numbit; + + disasm_cur_inst_len++; + + memspace = (cur_inst>>6) & 1; + value = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + + value += 0xffc0; + if (memspace) { + sprintf(srcname, "y:$%04x", value); + } else { + sprintf(srcname, "x:$%04x", value); + } + + sprintf(str_instr,"jclr #%d,%s,p:$%04x", + numbit, + srcname, + read_memory(dsp_core.pc+1) + ); +} + +static void dsp_jclr_reg(void) +{ + /* jclr #n,R,p:xx */ + Uint32 value, numbit; + + disasm_cur_inst_len++; + + value = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + + sprintf(str_instr,"jclr #%d,%s,p:$%04x", + numbit, + registers_name[value], + read_memory(dsp_core.pc+1) + ); +} + +static void dsp_jmp_imm(void) +{ + sprintf(str_instr,"jmp p:$%04x", cur_inst & BITMASK(12)); +} + +static void dsp_jmp_ea(void) +{ + char dstname[16]; + + dsp_calc_ea((cur_inst >>8) & BITMASK(6), dstname); + + sprintf(str_instr,"jmp p:%s", dstname); +} + +static void dsp_jscc_ea(void) +{ + char cond_name[16], addr_name[16]; + Uint32 cc_code=0; + + dsp_calc_ea((cur_inst>>8) & BITMASK(6), addr_name); + cc_code=cur_inst & BITMASK(4); + dsp_calc_cc(cc_code, cond_name); + + sprintf(str_instr,"js%s p:%s", cond_name, addr_name); +} + +static void dsp_jscc_imm(void) +{ + char cond_name[16], addr_name[16]; + Uint32 cc_code=0; + + sprintf(addr_name, "$%04x", cur_inst & BITMASK(12)); + cc_code=(cur_inst>>12) & BITMASK(4); + dsp_calc_cc(cc_code, cond_name); + + sprintf(str_instr,"js%s p:%s", cond_name, addr_name); +} + +static void dsp_jsclr_aa(void) +{ + /* jsclr #n,x:aa,p:xx */ + /* jsclr #n,y:aa,p:xx */ + char srcname[16]; + Uint32 memspace, value, numbit; + + disasm_cur_inst_len++; + + memspace = (cur_inst>>6) & 1; + value = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + + if (memspace) { + sprintf(srcname, "y:$%04x", value); + } else { + sprintf(srcname, "x:$%04x", value); + } + + sprintf(str_instr,"jsclr #%d,%s,p:$%04x", + numbit, + srcname, + read_memory(dsp_core.pc+1) + ); +} + +static void dsp_jsclr_ea(void) +{ + /* jsclr #n,x:ea,p:xx */ + /* jsclr #n,y:ea,p:xx */ + char srcname[16], addr_name[16]; + Uint32 memspace, value, numbit; + + disasm_cur_inst_len++; + + memspace = (cur_inst>>6) & 1; + value = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + + dsp_calc_ea(value, addr_name); + if (memspace) { + sprintf(srcname, "y:%s", addr_name); + } else { + sprintf(srcname, "x:%s", addr_name); + } + + sprintf(str_instr,"jsclr #%d,%s,p:$%04x", + numbit, + srcname, + read_memory(dsp_core.pc+1) + ); +} + +static void dsp_jsclr_pp(void) +{ + /* jsclr #n,x:pp,p:xx */ + /* jsclr #n,y:pp,p:xx */ + char srcname[16]; + Uint32 memspace, value, numbit; + + disasm_cur_inst_len++; + + memspace = (cur_inst>>6) & 1; + value = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + + value += 0xffc0; + if (memspace) { + sprintf(srcname, "y:$%04x", value); + } else { + sprintf(srcname, "x:$%04x", value); + } + + sprintf(str_instr,"jsclr #%d,%s,p:$%04x", + numbit, + srcname, + read_memory(dsp_core.pc+1) + ); +} + +static void dsp_jsclr_reg(void) +{ + /* jsclr #n,R,p:xx */ + Uint32 value, numbit; + + disasm_cur_inst_len++; + + value = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + + sprintf(str_instr,"jsclr #%d,%s,p:$%04x", + numbit, + registers_name[value], + read_memory(dsp_core.pc+1) + ); +} + +static void dsp_jset_aa(void) +{ + /* jset #n,x:aa,p:xx */ + /* jset #n,y:aa,p:xx */ + char srcname[16]; + Uint32 memspace, value, numbit; + + disasm_cur_inst_len++; + + memspace = (cur_inst>>6) & 1; + value = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + + if (memspace) { + sprintf(srcname, "y:$%04x", value); + } else { + sprintf(srcname, "x:$%04x", value); + } + + sprintf(str_instr,"jset #%d,%s,p:$%04x", + numbit, + srcname, + read_memory(dsp_core.pc+1) + ); +} + +static void dsp_jset_ea(void) +{ + /* jset #n,x:ea,p:xx */ + /* jset #n,y:ea,p:xx */ + char srcname[16], addr_name[16]; + Uint32 memspace, value, numbit; + + disasm_cur_inst_len++; + + memspace = (cur_inst>>6) & 1; + value = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + + dsp_calc_ea(value, addr_name); + if (memspace) { + sprintf(srcname, "y:%s", addr_name); + } else { + sprintf(srcname, "x:%s", addr_name); + } + + sprintf(str_instr,"jset #%d,%s,p:$%04x", + numbit, + srcname, + read_memory(dsp_core.pc+1) + ); +} + +static void dsp_jset_pp(void) +{ + /* jset #n,x:pp,p:xx */ + /* jset #n,y:pp,p:xx */ + char srcname[16]; + Uint32 memspace, value, numbit; + + disasm_cur_inst_len++; + + memspace = (cur_inst>>6) & 1; + value = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + + value += 0xffc0; + if (memspace) { + sprintf(srcname, "y:$%04x", value); + } else { + sprintf(srcname, "x:$%04x", value); + } + + sprintf(str_instr,"jset #%d,%s,p:$%04x", + numbit, + srcname, + read_memory(dsp_core.pc+1) + ); +} + +static void dsp_jset_reg(void) +{ + /* jset #n,R,p:xx */ + Uint32 value, numbit; + + disasm_cur_inst_len++; + + value = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + + sprintf(str_instr,"jset #%d,%s,p:$%04x", + numbit, + registers_name[value], + read_memory(dsp_core.pc+1) + ); +} + +static void dsp_jsr_imm(void) +{ + sprintf(str_instr,"jsr p:$%04x", cur_inst & BITMASK(12)); +} + +static void dsp_jsr_ea(void) +{ + char dstname[16]; + + dsp_calc_ea((cur_inst>>8) & BITMASK(6),dstname); + + sprintf(str_instr,"jsr p:%s", dstname); +} + +static void dsp_jsset_aa(void) +{ + /* jsset #n,x:aa,p:xx */ + /* jsset #n,y:aa,p:xx */ + char srcname[16]; + Uint32 memspace, value, numbit; + + disasm_cur_inst_len++; + + memspace = (cur_inst>>6) & 1; + value = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + + if (memspace) { + sprintf(srcname, "y:$%04x", value); + } else { + sprintf(srcname, "x:$%04x", value); + } + + sprintf(str_instr,"jsset #%d,%s,p:$%04x", + numbit, + srcname, + read_memory(dsp_core.pc+1) + ); +} + +static void dsp_jsset_ea(void) +{ + /* jsset #n,x:ea,p:xx */ + /* jsset #n,y:ea,p:xx */ + char srcname[16], addr_name[16]; + Uint32 memspace, value, numbit; + + disasm_cur_inst_len++; + + memspace = (cur_inst>>6) & 1; + value = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + + dsp_calc_ea(value, addr_name); + if (memspace) { + sprintf(srcname, "y:%s", addr_name); + } else { + sprintf(srcname, "x:%s", addr_name); + } + + sprintf(str_instr,"jsset #%d,%s,p:$%04x", + numbit, + srcname, + read_memory(dsp_core.pc+1) + ); +} + +static void dsp_jsset_pp(void) +{ + /* jsset #n,x:pp,p:xx */ + /* jsset #n,y:pp,p:xx */ + char srcname[16]; + Uint32 memspace, value, numbit; + + disasm_cur_inst_len++; + + memspace = (cur_inst>>6) & 1; + value = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + + value += 0xffc0; + if (memspace) { + sprintf(srcname, "y:$%04x", value); + } else { + sprintf(srcname, "x:$%04x", value); + } + + sprintf(str_instr,"jsset #%d,%s,p:$%04x", + numbit, + srcname, + read_memory(dsp_core.pc+1) + ); +} + +static void dsp_jsset_reg(void) +{ + /* jsset #n,r,p:xx */ + Uint32 value, numbit; + + disasm_cur_inst_len++; + + value = (cur_inst>>8) & BITMASK(6); + numbit = cur_inst & BITMASK(5); + + sprintf(str_instr,"jsset #%d,%s,p:$%04x", + numbit, + registers_name[value], + read_memory(dsp_core.pc+1) + ); +} + +static void dsp_lua(void) +{ + char addr_name[16], numreg; + + dsp_calc_ea((cur_inst>>8) & BITMASK(5), addr_name); + numreg = cur_inst & BITMASK(3); + + if (cur_inst & (1<<3)) + sprintf(str_instr,"lua %s,n%d", addr_name, numreg); + else + sprintf(str_instr,"lua %s,r%d", addr_name, numreg); +} + +static void dsp_movec_reg(void) +{ + Uint32 numreg1, numreg2; + + /* S1,D2 */ + /* S2,D1 */ + + numreg2 = (cur_inst>>8) & BITMASK(6); + numreg1 = cur_inst & BITMASK(6); + + if (cur_inst & (1<<15)) { + /* Write D1 */ + sprintf(str_instr,"movec %s,%s", registers_name[numreg2], registers_name[numreg1]); + } else { + /* Read S1 */ + sprintf(str_instr,"movec %s,%s", registers_name[numreg1], registers_name[numreg2]); + } +} + +static void dsp_movec_aa(void) +{ + const char *spacename; + char srcname[16],dstname[16]; + Uint32 numreg, addr; + + /* x:aa,D1 */ + /* S1,x:aa */ + /* y:aa,D1 */ + /* S1,y:aa */ + + numreg = cur_inst & BITMASK(6); + addr = (cur_inst>>8) & BITMASK(6); + + if (cur_inst & (1<<6)) { + spacename="y"; + } else { + spacename="x"; + } + + if (cur_inst & (1<<15)) { + /* Write D1 */ + sprintf(srcname, "%s:$%04x", spacename, addr); + strcpy(dstname, registers_name[numreg]); + } else { + /* Read S1 */ + strcpy(srcname, registers_name[numreg]); + sprintf(dstname, "%s:$%04x", spacename, addr); + } + + sprintf(str_instr,"movec %s,%s", srcname, dstname); +} + +static void dsp_movec_imm(void) +{ + Uint32 numreg; + + /* #xx,D1 */ + + numreg = cur_inst & BITMASK(6); + + sprintf(str_instr,"movec #$%02x,%s", (cur_inst>>8) & BITMASK(8), registers_name[numreg]); +} + +static void dsp_movec_ea(void) +{ + const char *spacename; + char srcname[16], dstname[16], addr_name[16]; + Uint32 numreg, ea_mode; + int retour; + + /* x:ea,D1 */ + /* S1,x:ea */ + /* y:ea,D1 */ + /* S1,y:ea */ + /* #xxxx,D1 */ + + numreg = cur_inst & BITMASK(6); + ea_mode = (cur_inst>>8) & BITMASK(6); + retour = dsp_calc_ea(ea_mode, addr_name); + + if (cur_inst & (1<<6)) { + spacename="y"; + } else { + spacename="x"; + } + + if (cur_inst & (1<<15)) { + /* Write D1 */ + if (retour) { + sprintf(srcname, "#%s", addr_name); + } else { + sprintf(srcname, "%s:%s", spacename, addr_name); + } + strcpy(dstname, registers_name[numreg]); + } else { + /* Read S1 */ + strcpy(srcname, registers_name[numreg]); + sprintf(dstname, "%s:%s", spacename, addr_name); + } + + sprintf(str_instr,"movec %s,%s", srcname, dstname); +} + +static void dsp_movem_aa(void) +{ + /* S,p:aa */ + /* p:aa,D */ + char addr_name[16], srcname[16], dstname[16]; + Uint32 numreg; + + sprintf(addr_name, "$%04x",(cur_inst>>8) & BITMASK(6)); + numreg = cur_inst & BITMASK(6); + if (cur_inst & (1<<15)) { + /* Write D */ + sprintf(srcname, "p:%s", addr_name); + strcpy(dstname, registers_name[numreg]); + } else { + /* Read S */ + strcpy(srcname, registers_name[numreg]); + sprintf(dstname, "p:%s", addr_name); + } + + sprintf(str_instr,"movem %s,%s", srcname, dstname); +} + +static void dsp_movem_ea(void) +{ + /* S,p:ea */ + /* p:ea,D */ + char addr_name[16], srcname[16], dstname[16]; + Uint32 ea_mode, numreg; + + ea_mode = (cur_inst>>8) & BITMASK(6); + dsp_calc_ea(ea_mode, addr_name); + numreg = cur_inst & BITMASK(6); + if (cur_inst & (1<<15)) { + /* Write D */ + sprintf(srcname, "p:%s", addr_name); + strcpy(dstname, registers_name[numreg]); + } else { + /* Read S */ + strcpy(srcname, registers_name[numreg]); + sprintf(dstname, "p:%s", addr_name); + } + + sprintf(str_instr,"movem %s,%s", srcname, dstname); +} + +static void dsp_movep_0(void) +{ + char srcname[16]="",dstname[16]=""; + Uint32 addr, memspace, numreg; + + /* S,x:pp */ + /* x:pp,D */ + /* S,y:pp */ + /* y:pp,D */ + + addr = 0xffc0 + (cur_inst & BITMASK(6)); + memspace = (cur_inst>>16) & 1; + numreg = (cur_inst>>8) & BITMASK(6); + + if (cur_inst & (1<<15)) { + /* Write pp */ + + strcpy(srcname, registers_name[numreg]); + + if (memspace) { + sprintf(dstname, "y:$%04x", addr); + } else { + sprintf(dstname, "x:$%04x", addr); + } + } else { + /* Read pp */ + + if (memspace) { + sprintf(srcname, "y:$%04x", addr); + } else { + sprintf(srcname, "x:$%04x", addr); + } + + strcpy(dstname, registers_name[numreg]); + } + + sprintf(str_instr,"movep %s,%s", srcname, dstname); +} + +static void dsp_movep_1(void) +{ + char srcname[16]="",dstname[16]="",name[16]=""; + Uint32 addr, memspace; + + /* p:ea,x:pp */ + /* x:pp,p:ea */ + /* p:ea,y:pp */ + /* y:pp,p:ea */ + + addr = 0xffc0 + (cur_inst & BITMASK(6)); + dsp_calc_ea((cur_inst>>8) & BITMASK(6), name); + memspace = (cur_inst>>16) & 1; + + if (cur_inst & (1<<15)) { + /* Write pp */ + + sprintf(srcname, "p:%s", name); + + if (memspace) { + sprintf(dstname, "y:$%04x", addr); + } else { + sprintf(dstname, "x:$%04x", addr); + } + } else { + /* Read pp */ + + if (memspace) { + sprintf(srcname, "y:$%04x", addr); + } else { + sprintf(srcname, "x:$%04x", addr); + } + + sprintf(dstname, "p:%s", name); + } + + sprintf(str_instr,"movep %s,%s", srcname, dstname); +} + +static void dsp_movep_23(void) +{ + char srcname[16]="",dstname[16]="",name[16]=""; + Uint32 addr, memspace, easpace, retour; + + /* x:ea,x:pp */ + /* y:ea,x:pp */ + /* #xxxxxx,x:pp */ + /* x:pp,x:ea */ + /* x:pp,y:ea */ + + /* x:ea,y:pp */ + /* y:ea,y:pp */ + /* #xxxxxx,y:pp */ + /* y:pp,y:ea */ + /* y:pp,x:ea */ + + addr = 0xffc0 + (cur_inst & BITMASK(6)); + retour = dsp_calc_ea((cur_inst>>8) & BITMASK(6), name); + memspace = (cur_inst>>16) & 1; + easpace = (cur_inst>>6) & 1; + + if (cur_inst & (1<<15)) { + /* Write pp */ + + if (retour) { + sprintf(srcname, "#%s", name); + } else { + if (easpace) { + sprintf(srcname, "y:%s", name); + } else { + sprintf(srcname, "x:%s", name); + } + } + + if (memspace) { + sprintf(dstname, "y:$%04x", addr); + } else { + sprintf(dstname, "x:$%04x", addr); + } + } else { + /* Read pp */ + + if (memspace) { + sprintf(srcname, "y:$%04x", addr); + } else { + sprintf(srcname, "x:$%04x", addr); + } + + if (easpace) { + sprintf(dstname, "y:%s", name); + } else { + sprintf(dstname, "x:%s", name); + } + } + + sprintf(str_instr,"movep %s,%s", srcname, dstname); +} + +static void dsp_nop(void) +{ + sprintf(str_instr,"nop"); +} + +static void dsp_norm(void) +{ + Uint32 srcreg, destreg; + + srcreg = DSP_REG_R0+((cur_inst>>8) & BITMASK(3)); + destreg = DSP_REG_A+((cur_inst>>3) & 1); + + sprintf(str_instr,"norm %s,%s", registers_name[srcreg], registers_name[destreg]); +} + +static void dsp_ori(void) +{ + switch(cur_inst & BITMASK(2)) { + case 0: + sprintf(str_instr,"ori #$%02x,mr", (cur_inst>>8) & BITMASK(8)); + break; + case 1: + sprintf(str_instr,"ori #$%02x,ccr", (cur_inst>>8) & BITMASK(8)); + break; + case 2: + sprintf(str_instr,"ori #$%02x,omr", (cur_inst>>8) & BITMASK(8)); + break; + default: + break; + } + +} + +static void dsp_rep_aa(void) +{ + char name[16]; + + /* x:aa */ + /* y:aa */ + + if (cur_inst & (1<<6)) { + sprintf(name, "y:$%04x",(cur_inst>>8) & BITMASK(6)); + } else { + sprintf(name, "x:$%04x",(cur_inst>>8) & BITMASK(6)); + } + + sprintf(str_instr,"rep %s", name); +} + +static void dsp_rep_imm(void) +{ + /* #xxx */ + sprintf(str_instr,"rep #$%02x", ((cur_inst>>8) & BITMASK(8)) + + ((cur_inst & BITMASK(4))<<8)); +} + +static void dsp_rep_ea(void) +{ + char name[16],addr_name[16]; + + /* x:ea */ + /* y:ea */ + + dsp_calc_ea((cur_inst>>8) & BITMASK(6), addr_name); + if (cur_inst & (1<<6)) { + sprintf(name, "y:%s",addr_name); + } else { + sprintf(name, "x:%s",addr_name); + } + + sprintf(str_instr,"rep %s", name); +} + +static void dsp_rep_reg(void) +{ + /* R */ + + sprintf(str_instr,"rep %s", registers_name[(cur_inst>>8) & BITMASK(6)]); +} + +static void dsp_reset(void) +{ + sprintf(str_instr,"reset"); +} + +static void dsp_rti(void) +{ + sprintf(str_instr,"rti"); +} + +static void dsp_rts(void) +{ + sprintf(str_instr,"rts"); +} + +static void dsp_stop(void) +{ + sprintf(str_instr,"stop"); +} + +static void dsp_swi(void) +{ + sprintf(str_instr,"swi"); +} + +static void dsp_tcc(void) +{ + char ccname[16]; + Uint32 src1reg, dst1reg, src2reg, dst2reg; + + dsp_calc_cc((cur_inst>>12) & BITMASK(4), ccname); + src1reg = registers_tcc[(cur_inst>>3) & BITMASK(4)][0]; + dst1reg = registers_tcc[(cur_inst>>3) & BITMASK(4)][1]; + + if (cur_inst & (1<<16)) { + src2reg = DSP_REG_R0+((cur_inst>>8) & BITMASK(3)); + dst2reg = DSP_REG_R0+(cur_inst & BITMASK(3)); + + sprintf(str_instr,"t%s %s,%s %s,%s", + ccname, + registers_name[src1reg], + registers_name[dst1reg], + registers_name[src2reg], + registers_name[dst2reg] + ); + } else { + sprintf(str_instr,"t%s %s,%s", + ccname, + registers_name[src1reg], + registers_name[dst1reg] + ); + } +} + +static void dsp_wait(void) +{ + sprintf(str_instr,"wait"); +} + +/********************************** + * Parallel moves + **********************************/ + +static void dsp_pm(void) +{ + Uint32 value; + + value = (cur_inst >> 20) & BITMASK(4); + opcodes_parmove[value](); +} + +static void dsp_pm_0(void) +{ + char space_name[16], addr_name[16]; + Uint32 memspace, numreg1, numreg2; +/* + 0000 100d 00mm mrrr S,x:ea x0,D + 0000 100d 10mm mrrr S,y:ea y0,D +*/ + memspace = (cur_inst>>15) & 1; + numreg1 = DSP_REG_A+((cur_inst>>16) & 1); + dsp_calc_ea((cur_inst>>8) & BITMASK(6), addr_name); + + if (memspace) { + strcpy(space_name,"y"); + numreg2 = DSP_REG_Y0; + } else { + strcpy(space_name,"x"); + numreg2 = DSP_REG_X0; + } + + sprintf(parallelmove_name, + "%s,%s:%s %s,%s", + registers_name[numreg1], + space_name, + addr_name, + registers_name[numreg2], + registers_name[numreg1] + ); +} + +static void dsp_pm_1(void) +{ +/* + 0001 ffdf w0mm mrrr x:ea,D1 S2,D2 + S1,x:ea S2,D2 + #xxxxxx,D1 S2,D2 + 0001 deff w1mm mrrr S1,D1 y:ea,D2 + S1,D1 S2,y:ea + S1,D1 #xxxxxx,D2 +*/ + + char addr_name[16]; + Uint32 memspace, write_flag, retour, s1reg, s2reg, d1reg, d2reg; + + memspace = (cur_inst>>14) & 1; + write_flag = (cur_inst>>15) & 1; + retour = dsp_calc_ea((cur_inst>>8) & BITMASK(6), addr_name); + + if (memspace==DSP_SPACE_Y) { + s2reg = d2reg = DSP_REG_Y0; + switch((cur_inst>>16) & BITMASK(2)) { + case 0: s2reg = d2reg = DSP_REG_Y0; break; + case 1: s2reg = d2reg = DSP_REG_Y1; break; + case 2: s2reg = d2reg = DSP_REG_A; break; + case 3: s2reg = d2reg = DSP_REG_B; break; + } + + s1reg = DSP_REG_A+((cur_inst>>19) & 1); + d1reg = DSP_REG_X0+((cur_inst>>18) & 1); + + if (write_flag) { + /* Write D2 */ + + if (retour) { + sprintf(parallelmove_name,"%s,%s #%s,%s", + registers_name[s1reg], + registers_name[d1reg], + addr_name, + registers_name[d2reg] + ); + } else { + sprintf(parallelmove_name,"%s,%s y:%s,%s", + registers_name[s1reg], + registers_name[d1reg], + addr_name, + registers_name[d2reg] + ); + } + } else { + /* Read S2 */ + sprintf(parallelmove_name,"%s,%s %s,y:%s", + registers_name[s1reg], + registers_name[d1reg], + registers_name[s2reg], + addr_name + ); + } + + } else { + s1reg = d1reg = DSP_REG_X0; + switch((cur_inst>>18) & BITMASK(2)) { + case 0: s1reg = d1reg = DSP_REG_X0; break; + case 1: s1reg = d1reg = DSP_REG_X1; break; + case 2: s1reg = d1reg = DSP_REG_A; break; + case 3: s1reg = d1reg = DSP_REG_B; break; + } + + s2reg = DSP_REG_A+((cur_inst>>17) & 1); + d2reg = DSP_REG_Y0+((cur_inst>>16) & 1); + + if (write_flag) { + /* Write D1 */ + + if (retour) { + sprintf(parallelmove_name,"#%s,%s %s,%s", + addr_name, + registers_name[d1reg], + registers_name[s2reg], + registers_name[d2reg] + ); + } else { + sprintf(parallelmove_name,"x:%s,%s %s,%s", + addr_name, + registers_name[d1reg], + registers_name[s2reg], + registers_name[d2reg] + ); + } + } else { + /* Read S1 */ + sprintf(parallelmove_name,"%s,x:%s %s,%s", + registers_name[s1reg], + addr_name, + registers_name[s2reg], + registers_name[d2reg] + ); + } + + } +} + +static void dsp_pm_2(void) +{ + char addr_name[16]; + Uint32 numreg1, numreg2; +/* + 0010 0000 0000 0000 nop + 0010 0000 010m mrrr R update + 0010 00ee eeed dddd S,D + 001d dddd iiii iiii #xx,D +*/ + if (((cur_inst >> 8) & 0xffff) == 0x2000) { + return; + } + + if (((cur_inst >> 8) & 0xffe0) == 0x2040) { + dsp_calc_ea((cur_inst>>8) & BITMASK(5), addr_name); + sprintf(parallelmove_name, "%s,r%d",addr_name, (cur_inst>>8) & BITMASK(3)); + return; + } + + if (((cur_inst >> 8) & 0xfc00) == 0x2000) { + numreg1 = (cur_inst>>13) & BITMASK(5); + numreg2 = (cur_inst>>8) & BITMASK(5); + sprintf(parallelmove_name, "%s,%s", registers_name[numreg1], registers_name[numreg2]); + return; + } + + numreg1 = (cur_inst>>16) & BITMASK(5); + sprintf(parallelmove_name, "#$%02x,%s", (cur_inst >> 8) & BITMASK(8), registers_name[numreg1]); +} + +static void dsp_pm_4(void) +{ + char addr_name[16]; + Uint32 value, retour, ea_mode, memspace; +/* + 0100 l0ll w0aa aaaa l:aa,D + S,l:aa + 0100 l0ll w1mm mrrr l:ea,D + S,l:ea + 01dd 0ddd w0aa aaaa x:aa,D + S,x:aa + 01dd 0ddd w1mm mrrr x:ea,D + S,x:ea + #xxxxxx,D + 01dd 1ddd w0aa aaaa y:aa,D + S,y:aa + 01dd 1ddd w1mm mrrr y:ea,D + S,y:ea + #xxxxxx,D +*/ + value = (cur_inst>>16) & BITMASK(3); + value |= (cur_inst>>17) & (BITMASK(2)<<3); + + ea_mode = (cur_inst>>8) & BITMASK(6); + + if ((value>>2)==0) { + /* L: memory move */ + if (cur_inst & (1<<14)) { + retour = dsp_calc_ea(ea_mode, addr_name); + } else { + sprintf(addr_name,"$%04x", ea_mode); + retour = 0; + } + + value = (cur_inst>>16) & BITMASK(2); + value |= (cur_inst>>17) & (1<<2); + + if (cur_inst & (1<<15)) { + /* Write D */ + + if (retour) { + sprintf(parallelmove_name, "#%s,%s", addr_name, registers_lmove[value]); + } else { + sprintf(parallelmove_name, "l:%s,%s", addr_name, registers_lmove[value]); + } + } else { + /* Read S */ + sprintf(parallelmove_name, "%s,l:%s", registers_lmove[value], addr_name); + } + + return; + } + + memspace = (cur_inst>>19) & 1; + if (cur_inst & (1<<14)) { + retour = dsp_calc_ea(ea_mode, addr_name); + } else { + sprintf(addr_name,"$%04x", ea_mode); + retour = 0; + } + + if (memspace) { + /* Y: */ + + if (cur_inst & (1<<15)) { + /* Write D */ + + if (retour) { + sprintf(parallelmove_name, "#%s,%s", addr_name, registers_name[value]); + } else { + sprintf(parallelmove_name, "y:%s,%s", addr_name, registers_name[value]); + } + + } else { + /* Read S */ + sprintf(parallelmove_name, "%s,y:%s", registers_name[value], addr_name); + } + } else { + /* X: */ + + if (cur_inst & (1<<15)) { + /* Write D */ + + if (retour) { + sprintf(parallelmove_name, "#%s,%s", addr_name, registers_name[value]); + } else { + sprintf(parallelmove_name, "x:%s,%s", addr_name, registers_name[value]); + } + } else { + /* Read S */ + sprintf(parallelmove_name, "%s,x:%s", registers_name[value], addr_name); + } + } +} + +static void dsp_pm_8(void) +{ + char addr1_name[16], addr2_name[16]; + Uint32 ea_mode1, ea_mode2, numreg1, numreg2; +/* + 1wmm eeff WrrM MRRR x:ea,D1 y:ea,D2 + x:ea,D1 S2,y:ea + S1,x:ea y:ea,D2 + S1,x:ea S2,y:ea +*/ + numreg1 = DSP_REG_X0; + switch((cur_inst>>18) & BITMASK(2)) { + case 0: numreg1 = DSP_REG_X0; break; + case 1: numreg1 = DSP_REG_X1; break; + case 2: numreg1 = DSP_REG_A; break; + case 3: numreg1 = DSP_REG_B; break; + } + + numreg2 = DSP_REG_Y0; + switch((cur_inst>>16) & BITMASK(2)) { + case 0: numreg2 = DSP_REG_Y0; break; + case 1: numreg2 = DSP_REG_Y1; break; + case 2: numreg2 = DSP_REG_A; break; + case 3: numreg2 = DSP_REG_B; break; + } + + ea_mode1 = (cur_inst>>8) & BITMASK(5); + if ((ea_mode1>>3) == 0) { + ea_mode1 |= (1<<5); + } + ea_mode2 = (cur_inst>>13) & BITMASK(2); + ea_mode2 |= ((cur_inst>>20) & BITMASK(2))<<3; + if ((ea_mode1 & (1<<2))==0) { + ea_mode2 |= 1<<2; + } + if ((ea_mode2>>3) == 0) { + ea_mode2 |= (1<<5); + } + + dsp_calc_ea(ea_mode1, addr1_name); + dsp_calc_ea(ea_mode2, addr2_name); + + if (cur_inst & (1<<15)) { + if (cur_inst & (1<<22)) { + sprintf(parallelmove_name, "x:%s,%s y:%s,%s", + addr1_name, + registers_name[numreg1], + addr2_name, + registers_name[numreg2] + ); + } else { + sprintf(parallelmove_name, "x:%s,%s %s,y:%s", + addr1_name, + registers_name[numreg1], + registers_name[numreg2], + addr2_name + ); + } + } else { + if (cur_inst & (1<<22)) { + sprintf(parallelmove_name, "%s,x:%s y:%s,%s", + registers_name[numreg1], + addr1_name, + addr2_name, + registers_name[numreg2] + ); + } else { + sprintf(parallelmove_name, "%s,x:%s %s,y:%s", + registers_name[numreg1], + addr1_name, + registers_name[numreg2], + addr2_name + ); + } + } +} diff --git a/hw/xbox/dsp/dsp_disasm.h b/hw/xbox/dsp/dsp_disasm.h new file mode 100644 index 0000000000..890595cf63 --- /dev/null +++ b/hw/xbox/dsp/dsp_disasm.h @@ -0,0 +1,47 @@ +/* + DSP M56001 emulation + Disassembler + + (C) 2003-2008 ARAnyM developer team + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef DSP_DISASM_H +#define DSP_DISASM_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + DSP_TRACE_MODE, + DSP_DISASM_MODE +} dsp_trace_disasm_t; + +/* Functions */ +extern void dsp56k_disasm_init(void); +extern Uint16 dsp56k_disasm(dsp_trace_disasm_t value); +extern const char* dsp56k_getInstructionText(void); + +/* Registers change */ +extern void dsp56k_disasm_reg_save(void); +extern void dsp56k_disasm_reg_compare(void); + +#ifdef __cplusplus +} +#endif + +#endif /* DSP_DISASM_H */