//
// DSP core
//
-// Original source by Cal2
+// Originally by David Raingeard
// GCC/SDL port by Niels Wagenaar (Linux/WIN32) and Caz (BeOS)
-// Extensive cleanups/rewrites by James L. Hammons
+// Extensive cleanups/rewrites by James Hammons
+// (C) 2010 Underground Software
+//
+// JLH = James Hammons <jlhamm@acm.org>
+//
+// Who When What
+// --- ---------- -------------------------------------------------------------
+// JLH 01/16/2010 Created this log ;-)
+// JLH 11/26/2011 Added fixes for LOAD/STORE alignment issues
//
-#include <SDL.h> // Used only for SDL_GetTicks...
#include "dsp.h"
+#include <SDL.h> // Used only for SDL_GetTicks...
+#include <stdlib.h>
+#include "dac.h"
+#include "gpu.h"
+#include "jagdasm.h"
+#include "jaguar.h"
+#include "jerry.h"
+#include "log.h"
+#include "m68000/m68kinterface.h"
+//#include "memory.h"
+
+
+// Seems alignment in loads & stores was off...
+#define DSP_CORRECT_ALIGNMENT
+//#define DSP_CORRECT_ALIGNMENT_STORE
+
//#define DSP_DEBUG
//#define DSP_DEBUG_IRQ
//#define DSP_DEBUG_PL2
//#define DSP_DEBUG_STALL
//#define DSP_DEBUG_CC
+#define NEW_SCOREBOARD
// Disassembly definitions
-#define DSP_DIS_ABS // Pipelined only
+#if 0
+#define DSP_DIS_ABS
#define DSP_DIS_ADD
#define DSP_DIS_ADDC
#define DSP_DIS_ADDQ
#define DSP_DIS_MOVEI
#define DSP_DIS_MOVEQ
#define DSP_DIS_MOVEFA
+#define DSP_DIS_MOVEPC // Pipeline only!
#define DSP_DIS_MOVETA
#define DSP_DIS_MULT
#define DSP_DIS_NEG
//*/
bool doDSPDis = false;
//bool doDSPDis = true;
-
+#endif
+bool doDSPDis = false;
+//#define DSP_DIS_JR
+//#define DSP_DIS_JUMP
/*
No dis yet:
struct PipelineStage
{
- uint16 instruction;
- uint8 opcode, operand1, operand2;
- uint32 reg1, reg2, areg1, areg2;
- uint32 result;
- uint8 writebackRegister;
+ uint16_t instruction;
+ uint8_t opcode, operand1, operand2;
+ uint32_t reg1, reg2, areg1, areg2;
+ uint32_t result;
+ uint8_t writebackRegister;
// General memory store...
- uint32 address;
- uint32 value;
- uint8 type;
+ uint32_t address;
+ uint32_t value;
+ uint8_t type;
};
#define TYPE_BYTE 0
#define TYPE_WORD 1
#define TYPE_DWORD 2
#define PIPELINE_STALL 64 // Set to # of opcodes + 1
+#ifndef NEW_SCOREBOARD
bool scoreboard[32];
-uint8 plPtrFetch, plPtrRead, plPtrExec, plPtrWrite;
+#else
+uint8_t scoreboard[32];
+#endif
+uint8_t plPtrFetch, plPtrRead, plPtrExec, plPtrWrite;
PipelineStage pipeline[4];
bool IMASKCleared = false;
#define VERSION 0x0F000
#define INT_LAT5 0x10000
-extern uint32 jaguar_mainRom_crc32;
+extern uint32_t jaguar_mainRom_crc32;
// Is opcode 62 *really* a NOP? Seems like it...
static void dsp_opcode_abs(void);
static void dsp_opcode_add(void);
static void dsp_opcode_addc(void);
static void dsp_opcode_addq(void);
-static void dsp_opcode_addqmod(void);
+static void dsp_opcode_addqmod(void);
static void dsp_opcode_addqt(void);
static void dsp_opcode_and(void);
static void dsp_opcode_bclr(void);
static void dsp_opcode_load_r14_ri(void);
static void dsp_opcode_load_r15_indexed(void);
static void dsp_opcode_load_r15_ri(void);
-static void dsp_opcode_mirror(void);
+static void dsp_opcode_mirror(void);
static void dsp_opcode_mmult(void);
static void dsp_opcode_move(void);
static void dsp_opcode_movei(void);
static void dsp_opcode_ror(void);
static void dsp_opcode_rorq(void);
static void dsp_opcode_xor(void);
-static void dsp_opcode_sat16s(void);
-static void dsp_opcode_sat32s(void);
+static void dsp_opcode_sat16s(void);
+static void dsp_opcode_sat32s(void);
static void dsp_opcode_sh(void);
static void dsp_opcode_sha(void);
static void dsp_opcode_sharq(void);
static void dsp_opcode_sub(void);
static void dsp_opcode_subc(void);
static void dsp_opcode_subq(void);
-static void dsp_opcode_subqmod(void);
+static void dsp_opcode_subqmod(void);
static void dsp_opcode_subqt(void);
-
-uint8 dsp_opcode_cycles[64] =
-{
- 3, 3, 3, 3,
- 3, 3, 3, 3,
- 3, 3, 3, 3,
- 3, 3, 3, 3,
- 3, 3, 1, 3,
- 1, 18, 3, 3,
- 3, 3, 3, 3,
- 3, 3, 3, 3,
- 3, 3, 2, 2,
- 2, 2, 3, 4,
- 5, 4, 5, 6,
- 6, 1, 1, 1,
- 1, 2, 2, 2,
- 1, 1, 9, 3,
- 3, 1, 6, 6,
- 2, 2, 3, 3
-};
+static void dsp_opcode_illegal(void);
+
+/*uint8_t dsp_opcode_cycles[64] =
+{
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 1, 3, 1, 18, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 2, 2, 2, 2, 3, 4,
+ 5, 4, 5, 6, 6, 1, 1, 1,
+ 1, 2, 2, 2, 1, 1, 9, 3,
+ 3, 1, 6, 6, 2, 2, 3, 3
+};//*/
+//Here's a QnD kludge...
+//This is wrong, wrong, WRONG, but it seems to work for the time being...
+//(That is, it fixes Flip Out which relies on GPU timing rather than semaphores. Bad developers! Bad!)
+//What's needed here is a way to take pipeline effects into account (including pipeline stalls!)...
+// Yup, without cheating like this, the sound in things like Rayman, FACTS, &
+// Tripper Getem get starved for time and sounds like crap. So we have to figure
+// out how to fix that. :-/
+uint8_t dsp_opcode_cycles[64] =
+{
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 9, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 2,
+ 2, 2, 2, 3, 3, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 4, 1,
+ 1, 1, 3, 3, 1, 1, 1, 1
+};//*/
void (* dsp_opcode[64])() =
-{
+{
dsp_opcode_add, dsp_opcode_addc, dsp_opcode_addq, dsp_opcode_addqt,
dsp_opcode_sub, dsp_opcode_subc, dsp_opcode_subq, dsp_opcode_subqt,
dsp_opcode_neg, dsp_opcode_and, dsp_opcode_or, dsp_opcode_xor,
dsp_opcode_mirror, dsp_opcode_store_r14_indexed, dsp_opcode_store_r15_indexed, dsp_opcode_move_pc,
dsp_opcode_jump, dsp_opcode_jr, dsp_opcode_mmult, dsp_opcode_mtoi,
dsp_opcode_normi, dsp_opcode_nop, dsp_opcode_load_r14_ri, dsp_opcode_load_r15_ri,
- dsp_opcode_store_r14_ri, dsp_opcode_store_r15_ri, dsp_opcode_nop, dsp_opcode_addqmod,
+ dsp_opcode_store_r14_ri, dsp_opcode_store_r15_ri, dsp_opcode_illegal, dsp_opcode_addqmod,
};
-uint32 dsp_opcode_use[65];
+uint32_t dsp_opcode_use[65];
-char * dsp_opcode_str[65]=
-{
+const char * dsp_opcode_str[65]=
+{
"add", "addc", "addq", "addqt",
"sub", "subc", "subq", "subqt",
"neg", "and", "or", "xor",
"STALL"
};
-uint32 dsp_pc;
-static uint64 dsp_acc; // 40 bit register, NOT 32!
-static uint32 dsp_remain;
-static uint32 dsp_modulo;
-static uint32 dsp_flags;
-static uint32 dsp_matrix_control;
-static uint32 dsp_pointer_to_matrix;
-static uint32 dsp_data_organization;
-uint32 dsp_control;
-static uint32 dsp_div_control;
-static uint8 dsp_flag_z, dsp_flag_n, dsp_flag_c;
-static uint32 * dsp_reg, * dsp_alternate_reg;
-static uint32 * dsp_reg_bank_0, * dsp_reg_bank_1;
-
-static uint32 dsp_opcode_first_parameter;
-static uint32 dsp_opcode_second_parameter;
+uint32_t dsp_pc;
+static uint64_t dsp_acc; // 40 bit register, NOT 32!
+static uint32_t dsp_remain;
+static uint32_t dsp_modulo;
+static uint32_t dsp_flags;
+static uint32_t dsp_matrix_control;
+static uint32_t dsp_pointer_to_matrix;
+static uint32_t dsp_data_organization;
+uint32_t dsp_control;
+static uint32_t dsp_div_control;
+static uint8_t dsp_flag_z, dsp_flag_n, dsp_flag_c;
+static uint32_t * dsp_reg = NULL, * dsp_alternate_reg = NULL;
+uint32_t dsp_reg_bank_0[32], dsp_reg_bank_1[32];
+
+static uint32_t dsp_opcode_first_parameter;
+static uint32_t dsp_opcode_second_parameter;
#define DSP_RUNNING (dsp_control & 0x01)
#define CLR_ZN (dsp_flag_z = dsp_flag_n = 0)
#define CLR_ZNC (dsp_flag_z = dsp_flag_n = dsp_flag_c = 0)
#define SET_Z(r) (dsp_flag_z = ((r) == 0))
-#define SET_N(r) (dsp_flag_n = (((UINT32)(r) >> 31) & 0x01))
-#define SET_C_ADD(a,b) (dsp_flag_c = ((UINT32)(b) > (UINT32)(~(a))))
-#define SET_C_SUB(a,b) (dsp_flag_c = ((UINT32)(b) > (UINT32)(a)))
+#define SET_N(r) (dsp_flag_n = (((uint32_t)(r) >> 31) & 0x01))
+#define SET_C_ADD(a,b) (dsp_flag_c = ((uint32_t)(b) > (uint32_t)(~(a))))
+#define SET_C_SUB(a,b) (dsp_flag_c = ((uint32_t)(b) > (uint32_t)(a)))
#define SET_ZN(r) SET_N(r); SET_Z(r)
#define SET_ZNC_ADD(a,b,r) SET_N(r); SET_Z(r); SET_C_ADD(a,b)
#define SET_ZNC_SUB(a,b,r) SET_N(r); SET_Z(r); SET_C_SUB(a,b)
-uint32 dsp_convert_zero[32] = { 32,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31 };
-uint8 * dsp_branch_condition_table = NULL;
-static uint16 * mirror_table = NULL;
-static uint8 * dsp_ram_8 = NULL;
+uint32_t dsp_convert_zero[32] = {
+ 32, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
+};
+
+uint8_t dsp_branch_condition_table[32 * 8];
+static uint16_t mirror_table[65536];
+static uint8_t dsp_ram_8[0x2000];
#define BRANCH_CONDITION(x) dsp_branch_condition_table[(x) + ((jaguar_flags & 7) << 5)]
-static uint32 dsp_in_exec = 0;
-static uint32 dsp_releaseTimeSlice_flag = 0;
+static uint32_t dsp_in_exec = 0;
+static uint32_t dsp_releaseTimeSlice_flag = 0;
FILE * dsp_fp;
#ifdef DSP_DEBUG_CC
// Comparison core vars (used only for core comparison! :-)
-static uint64 count = 0;
-static uint8 ram1[0x2000], ram2[0x2000];
-static uint32 regs1[64], regs2[64];
-static uint32 ctrl1[14], ctrl2[14];
+static uint64_t count = 0;
+static uint8_t ram1[0x2000], ram2[0x2000];
+static uint32_t regs1[64], regs2[64];
+static uint32_t ctrl1[14], ctrl2[14];
#endif
// Private function prototypes
dsp_opcode_use[i] = 0;
}
-void dsp_releaseTimeslice(void)
+
+void DSPReleaseTimeslice(void)
{
//This does absolutely nothing!!! !!! FIX !!!
dsp_releaseTimeSlice_flag = 1;
}
+
void dsp_build_branch_condition_table(void)
{
- // Allocate the mirror table
- if (!mirror_table)
- mirror_table = (uint16 *)malloc(65536 * sizeof(mirror_table[0]));
-
// Fill in the mirror table
- if (mirror_table)
- for(int i=0; i<65536; i++)
- mirror_table[i] = ((i >> 15) & 0x0001) | ((i >> 13) & 0x0002) |
- ((i >> 11) & 0x0004) | ((i >> 9) & 0x0008) |
- ((i >> 7) & 0x0010) | ((i >> 5) & 0x0020) |
- ((i >> 3) & 0x0040) | ((i >> 1) & 0x0080) |
- ((i << 1) & 0x0100) | ((i << 3) & 0x0200) |
- ((i << 5) & 0x0400) | ((i << 7) & 0x0800) |
- ((i << 9) & 0x1000) | ((i << 11) & 0x2000) |
- ((i << 13) & 0x4000) | ((i << 15) & 0x8000);
-
- if (!dsp_branch_condition_table)
+ for(int i=0; i<65536; i++)
{
- dsp_branch_condition_table = (uint8 *)malloc(32 * 8 * sizeof(dsp_branch_condition_table[0]));
+ mirror_table[i] = ((i >> 15) & 0x0001) | ((i >> 13) & 0x0002)
+ | ((i >> 11) & 0x0004) | ((i >> 9) & 0x0008)
+ | ((i >> 7) & 0x0010) | ((i >> 5) & 0x0020)
+ | ((i >> 3) & 0x0040) | ((i >> 1) & 0x0080)
+ | ((i << 1) & 0x0100) | ((i << 3) & 0x0200)
+ | ((i << 5) & 0x0400) | ((i << 7) & 0x0800)
+ | ((i << 9) & 0x1000) | ((i << 11) & 0x2000)
+ | ((i << 13) & 0x4000) | ((i << 15) & 0x8000);
+ }
- // Fill in the condition table
- if (dsp_branch_condition_table)
+ // Fill in the condition table
+ for(int i=0; i<8; i++)
+ {
+ for(int j=0; j<32; j++)
{
- for(int i=0; i<8; i++)
- {
- for(int j=0; j<32; j++)
- {
- int result = 1;
- if (j & 1)
- if (i & ZERO_FLAG)
- result = 0;
- if (j & 2)
- if (!(i & ZERO_FLAG))
- result = 0;
- if (j & 4)
- if (i & (CARRY_FLAG << (j >> 4)))
- result = 0;
- if (j & 8)
- if (!(i & (CARRY_FLAG << (j >> 4))))
- result = 0;
- dsp_branch_condition_table[i * 32 + j] = result;
- }
- }
+ int result = 1;
+
+ if ((j & 1) && (i & ZERO_FLAG))
+ result = 0;
+
+ if ((j & 2) && (!(i & ZERO_FLAG)))
+ result = 0;
+
+ if ((j & 4) && (i & (CARRY_FLAG << (j >> 4))))
+ result = 0;
+
+ if ((j & 8) && (!(i & (CARRY_FLAG << (j >> 4)))))
+ result = 0;
+
+ dsp_branch_condition_table[i * 32 + j] = result;
}
}
}
-uint8 DSPReadByte(uint32 offset, uint32 who/*=UNKNOWN*/)
+
+uint8_t DSPReadByte(uint32_t offset, uint32_t who/*=UNKNOWN*/)
{
if (offset >= 0xF1A000 && offset <= 0xF1A0FF)
WriteLog("DSP: ReadByte--Attempt to read from DSP register file by %s!\n", whoName[who]);
if (offset >= DSP_CONTROL_RAM_BASE && offset <= (DSP_CONTROL_RAM_BASE + 0x1F))
{
- uint32 data = DSPReadLong(offset & 0xFFFFFFFC, who);
-
- if ((offset&0x03)==0)
- return(data>>24);
- else
- if ((offset&0x03)==1)
- return((data>>16)&0xff);
- else
- if ((offset&0x03)==2)
- return((data>>8)&0xff);
- else
- if ((offset&0x03)==3)
- return(data&0xff);
+ uint32_t data = DSPReadLong(offset & 0xFFFFFFFC, who);
+
+ if ((offset & 0x03) == 0)
+ return (data >> 24);
+ else if ((offset & 0x03) == 1)
+ return ((data >> 16) & 0xFF);
+ else if ((offset & 0x03) == 2)
+ return ((data >> 8) & 0xFF);
+ else if ((offset & 0x03) == 3)
+ return (data & 0xFF);
}
return JaguarReadByte(offset, who);
-}
+}
+
-uint16 DSPReadWord(uint32 offset, uint32 who/*=UNKNOWN*/)
+uint16_t DSPReadWord(uint32_t offset, uint32_t who/*=UNKNOWN*/)
{
if (offset >= 0xF1A000 && offset <= 0xF1A0FF)
WriteLog("DSP: ReadWord--Attempt to read from DSP register file by %s!\n", whoName[who]);
//???
offset &= 0xFFFFFFFE;
- // jaguar cd bios
-/* if (jaguar_mainRom_crc32==0xa74a97cd)
- {
- if (offset==0xF1A114) return(0x0000);
- if (offset==0xF1A116) return(0x0000);
- if (offset==0xF1B000) return(0x1234);
- if (offset==0xF1B002) return(0x5678);
- }*/
-/*
- if (jaguar_mainRom_crc32==0x7ae20823)
- {
- if (offset==0xF1B9D8) return(0x0000);
- if (offset==0xF1B9Da) return(0x0000);
- if (offset==0xF1B2C0) return(0x0000);
- if (offset==0xF1B2C2) return(0x0000);
- }
-*/
- // pour permettre à wolfenstein 3d de tourner sans le dsp
-/* if ((offset==0xF1B0D0)||(offset==0xF1B0D2))
- return(0);
-*/
-
- // pour permettre à nba jam de tourner sans le dsp
-/* if (jaguar_mainRom_crc32==0x4faddb18)
- {
- if (offset==0xf1b2c0) return(0);
- if (offset==0xf1b2c2) return(0);
- if (offset==0xf1b240) return(0);
- if (offset==0xf1b242) return(0);
- if (offset==0xF1B340) return(0);
- if (offset==0xF1B342) return(0);
- if (offset==0xF1BAD8) return(0);
- if (offset==0xF1BADA) return(0);
- if (offset==0xF1B040) return(0);
- if (offset==0xF1B042) return(0);
- if (offset==0xF1B0C0) return(0);
- if (offset==0xF1B0C2) return(0);
- if (offset==0xF1B140) return(0);
- if (offset==0xF1B142) return(0);
- if (offset==0xF1B1C0) return(0);
- if (offset==0xF1B1C2) return(0);
- }*/
if (offset >= DSP_WORK_RAM_BASE && offset <= DSP_WORK_RAM_BASE+0x1FFF)
{
offset -= DSP_WORK_RAM_BASE;
-/* uint16 data = (((uint16)dsp_ram_8[offset])<<8)|((uint16)dsp_ram_8[offset+1]);
+/* uint16_t data = (((uint16_t)dsp_ram_8[offset])<<8)|((uint16_t)dsp_ram_8[offset+1]);
return data;*/
return GET16(dsp_ram_8, offset);
}
else if ((offset>=DSP_CONTROL_RAM_BASE)&&(offset<DSP_CONTROL_RAM_BASE+0x20))
{
- uint32 data = DSPReadLong(offset & 0xFFFFFFFC, who);
+ uint32_t data = DSPReadLong(offset & 0xFFFFFFFC, who);
if (offset & 0x03)
return data & 0xFFFF;
return JaguarReadWord(offset, who);
}
-uint32 DSPReadLong(uint32 offset, uint32 who/*=UNKNOWN*/)
+
+uint32_t DSPReadLong(uint32_t offset, uint32_t who/*=UNKNOWN*/)
{
if (offset >= 0xF1A000 && offset <= 0xF1A0FF)
WriteLog("DSP: ReadLong--Attempt to read from DSP register file by %s!\n", whoName[who]);
offset &= 0x3F;
switch (offset)
{
- case 0x00: /*dsp_flag_c?(dsp_flag_c=1):(dsp_flag_c=0);
- dsp_flag_z?(dsp_flag_z=1):(dsp_flag_z=0);
- dsp_flag_n?(dsp_flag_n=1):(dsp_flag_n=0);*/
-
- dsp_flags = (dsp_flags & 0xFFFFFFF8) | (dsp_flag_n << 2) | (dsp_flag_c << 1) | dsp_flag_z;
- return dsp_flags & 0xFFFFC1FF;
+ case 0x00:
+ dsp_flags = (dsp_flags & 0xFFFFFFF8) | (dsp_flag_n << 2) | (dsp_flag_c << 1) | dsp_flag_z;
+ return dsp_flags & 0xFFFFC1FF;
case 0x04: return dsp_matrix_control;
case 0x08: return dsp_pointer_to_matrix;
case 0x0C: return dsp_data_organization;
case 0x18: return dsp_modulo;
case 0x1C: return dsp_remain;
case 0x20:
- return (int32)((int8)(dsp_acc >> 32)); // Top 8 bits of 40-bit accumulator, sign extended
+ return (int32_t)((int8_t)(dsp_acc >> 32)); // Top 8 bits of 40-bit accumulator, sign extended
}
// unaligned long read-- !!! FIX !!!
return 0xFFFFFFFF;
return JaguarReadLong(offset, who);
}
-void DSPWriteByte(uint32 offset, uint8 data, uint32 who/*=UNKNOWN*/)
+
+void DSPWriteByte(uint32_t offset, uint8_t data, uint32_t who/*=UNKNOWN*/)
{
if (offset >= 0xF1A000 && offset <= 0xF1A0FF)
WriteLog("DSP: WriteByte--Attempt to write to DSP register file by %s!\n", whoName[who]);
- if ((offset >= DSP_WORK_RAM_BASE) && (offset < DSP_WORK_RAM_BASE+0x2000))
+ if ((offset >= DSP_WORK_RAM_BASE) && (offset < DSP_WORK_RAM_BASE + 0x2000))
{
offset -= DSP_WORK_RAM_BASE;
dsp_ram_8[offset] = data;
/* if (dsp_in_exec == 0)
{
m68k_end_timeslice();
- gpu_releaseTimeslice();
+ dsp_releaseTimeslice();
}*/
return;
}
- if ((offset >= DSP_CONTROL_RAM_BASE) && (offset < DSP_CONTROL_RAM_BASE+0x20))
+ if ((offset >= DSP_CONTROL_RAM_BASE) && (offset < DSP_CONTROL_RAM_BASE + 0x20))
{
- uint32 reg = offset & 0x1C;
+ uint32_t reg = offset & 0x1C;
int bytenum = offset & 0x03;
-
+
if ((reg >= 0x1C) && (reg <= 0x1F))
dsp_div_control = (dsp_div_control & (~(0xFF << (bytenum << 3)))) | (data << (bytenum << 3));
else
{
//This looks funky. !!! FIX !!!
- uint32 old_data = DSPReadLong(offset&0xFFFFFFC, who);
+ uint32_t old_data = DSPReadLong(offset&0xFFFFFFC, who);
bytenum = 3 - bytenum; // convention motorola !!!
- old_data = (old_data & (~(0xFF << (bytenum << 3)))) | (data << (bytenum << 3));
+ old_data = (old_data & (~(0xFF << (bytenum << 3)))) | (data << (bytenum << 3));
DSPWriteLong(offset & 0xFFFFFFC, old_data, who);
}
return;
}
// WriteLog("dsp: writing %.2x at 0x%.8x\n",data,offset);
//Should this *ever* happen??? Shouldn't we be saying "unknown" here???
+// Well, yes, it can. There are 3 MMU users after all: 68K, GPU & DSP...!
JaguarWriteByte(offset, data, who);
}
-void DSPWriteWord(uint32 offset, uint16 data, uint32 who/*=UNKNOWN*/)
+
+void DSPWriteWord(uint32_t offset, uint16_t data, uint32_t who/*=UNKNOWN*/)
{
if (offset >= 0xF1A000 && offset <= 0xF1A0FF)
WriteLog("DSP: WriteWord--Attempt to write to DSP register file by %s!\n", whoName[who]);
// WriteLog("dsp: writing %.4x at 0x%.8x\n",data,offset);
if ((offset >= DSP_WORK_RAM_BASE) && (offset < DSP_WORK_RAM_BASE+0x2000))
{
+/*if (offset == 0xF1B2F4)
+{
+ WriteLog("DSP: %s is writing %04X at location 0xF1B2F4 (DSP_PC: %08X)...\n", whoName[who], data, dsp_pc);
+}//*/
offset -= DSP_WORK_RAM_BASE;
dsp_ram_8[offset] = data >> 8;
dsp_ram_8[offset+1] = data & 0xFF;
{
// WriteLog("dsp: writing %.4x at 0x%.8x\n",data,offset+DSP_WORK_RAM_BASE);
m68k_end_timeslice();
- gpu_releaseTimeslice();
+ dsp_releaseTimeslice();
}*/
//CC only!
#ifdef DSP_DEBUG_CC
if ((offset & 0x1C) == 0x1C)
{
if (offset & 0x03)
- dsp_div_control = (dsp_div_control&0xffff0000)|(data&0xffff);
+ dsp_div_control = (dsp_div_control & 0xFFFF0000) | (data & 0xFFFF);
else
- dsp_div_control = (dsp_div_control&0xffff)|((data&0xffff)<<16);
+ dsp_div_control = (dsp_div_control & 0xFFFF) | ((data & 0xFFFF) << 16);
}
else
{
- uint32 old_data = DSPReadLong(offset & 0xffffffc, who);
+ uint32_t old_data = DSPReadLong(offset & 0xFFFFFFC, who);
+
if (offset & 0x03)
- old_data = (old_data&0xffff0000)|(data&0xffff);
+ old_data = (old_data & 0xFFFF0000) | (data & 0xFFFF);
else
- old_data = (old_data&0xffff)|((data&0xffff)<<16);
- DSPWriteLong(offset & 0xffffffc, old_data, who);
+ old_data = (old_data & 0xFFFF) | ((data & 0xFFFF) << 16);
+
+ DSPWriteLong(offset & 0xFFFFFFC, old_data, who);
}
+
return;
}
JaguarWriteWord(offset, data, who);
}
+
//bool badWrite = false;
-void DSPWriteLong(uint32 offset, uint32 data, uint32 who/*=UNKNOWN*/)
+void DSPWriteLong(uint32_t offset, uint32_t data, uint32_t who/*=UNKNOWN*/)
{
if (offset >= 0xF1A000 && offset <= 0xF1A0FF)
WriteLog("DSP: WriteLong--Attempt to write to DSP register file by %s!\n", whoName[who]);
case 0x00:
{
#ifdef DSP_DEBUG
- WriteLog("DSP: Writing %08X to DSP_FLAGS by %s (REGPAGE is %s)...\n", data, whoName[who], (dsp_flags & REGPAGE ? "set" : "not set"));
+ WriteLog("DSP: Writing %08X to DSP_FLAGS by %s (REGPAGE is %sset)...\n", data, whoName[who], (dsp_flags & REGPAGE ? "" : "not "));
#endif
// bool IMASKCleared = (dsp_flags & IMASK) && !(data & IMASK);
IMASKCleared = (dsp_flags & IMASK) && !(data & IMASK);
- dsp_flags = data;
+ // NOTE: According to the JTRM, writing a 1 to IMASK has no effect; only the
+ // IRQ logic can set it. So we mask it out here to prevent problems...
+ dsp_flags = data & (~IMASK);
dsp_flag_z = dsp_flags & 0x01;
dsp_flag_c = (dsp_flags >> 1) & 0x01;
dsp_flag_n = (dsp_flags >> 2) & 0x01;
DSPUpdateRegisterBanks();
dsp_control &= ~((dsp_flags & CINT04FLAGS) >> 3);
dsp_control &= ~((dsp_flags & CINT5FLAG) >> 1);
-/* if (IMASKCleared) // If IMASK was cleared,
-#ifdef DSP_DEBUG_IRQ
- {
- WriteLog("DSP: Finished interrupt.\n");
-#endif
- DSPHandleIRQs(); // see if any other interrupts need servicing!
-#ifdef DSP_DEBUG_IRQ
- }
-#endif//*/
break;
}
case 0x04:
//!!!!!!!!
break;
case 0x14:
- {
-#ifdef DSP_DEBUG
-WriteLog("Write to DSP CTRL by %s: %08X\n", whoName[who], data);
-#endif
+ {
+//#ifdef DSP_DEBUG
+WriteLog("Write to DSP CTRL by %s: %08X (DSP PC=$%08X)\n", whoName[who], data, dsp_pc);
+//#endif
bool wasRunning = DSP_RUNNING;
-// uint32 dsp_was_running = DSP_RUNNING;
+// uint32_t dsp_was_running = DSP_RUNNING;
// Check for DSP -> CPU interrupt
if (data & CPUINT)
{
#ifdef DSP_DEBUG
WriteLog("DSP: DSP -> CPU interrupt\n");
#endif
-// This was WRONG
-// Why do we check for a valid handler at 64? Isn't that the Jag programmer's responsibility?
- if (JERRYIRQEnabled(IRQ2_DSP))// && jaguar_interrupt_handler_is_valid(64))
+
+#warning "!!! DSP IRQs that go to the 68K have to be routed thru TOM !!! FIX !!!"
+ if (JERRYIRQEnabled(IRQ2_DSP))
{
JERRYSetPendingIRQ(IRQ2_DSP);
- dsp_releaseTimeslice();
- m68k_set_irq(7); // Set 68000 NMI...
+ DSPReleaseTimeslice();
+ m68k_set_irq(2); // Set 68000 IPL 2...
}
data &= ~CPUINT;
}
WriteLog("DSP: CPU -> DSP interrupt\n");
#endif
m68k_end_timeslice();
- gpu_releaseTimeslice();
+ DSPReleaseTimeslice();
DSPSetIRQLine(DSPIRQ_CPU, ASSERT_LINE);
data &= ~DSPINT0;
}
}
// Protect writes to VERSION and the interrupt latches...
- uint32 mask = VERSION | INT_LAT0 | INT_LAT1 | INT_LAT2 | INT_LAT3 | INT_LAT4 | INT_LAT5;
+ uint32_t mask = VERSION | INT_LAT0 | INT_LAT1 | INT_LAT2 | INT_LAT3 | INT_LAT4 | INT_LAT5;
dsp_control = (dsp_control & mask) | (data & ~mask);
//CC only!
#ifdef DSP_DEBUG_CC
WriteLog(" --> Stopped by %s! (DSP PC: %08X)", whoName[who], dsp_pc);
WriteLog("\n");
#endif // DSP_DEBUG
-//This isn't exactly right either--we don't know if it was the M68K or the GPU writing here...
+//This isn't exactly right either--we don't know if it was the M68K or the DSP writing here...
// !!! FIX !!! [DONE]
if (DSP_RUNNING)
{
if (who == M68K)
m68k_end_timeslice();
- else if (who == GPU)
- gpu_releaseTimeslice();
+ else if (who == DSP)
+ DSPReleaseTimeslice();
if (!wasRunning)
FlushDSPPipeline();
break;
}
case 0x18:
+WriteLog("DSP: Modulo data %08X written by %s.\n", data, whoName[who]);
dsp_modulo = data;
break;
case 0x1C:
JaguarWriteLong(offset, data, who);
}
+
//
// Update the DSP register file pointers depending on REGPAGE bit
//
dsp_reg = dsp_reg_bank_1, dsp_alternate_reg = dsp_reg_bank_0;
else
dsp_reg = dsp_reg_bank_0, dsp_alternate_reg = dsp_reg_bank_1;
+
+#ifdef DSP_DEBUG_IRQ
+ WriteLog("DSP: Register bank #%s active.\n", (bank ? "1" : "0"));
+#endif
}
+
//
// Check for and handle any asserted DSP IRQs
//
return;
// Get the active interrupt bits (latches) & interrupt mask (enables)
- uint32 bits = ((dsp_control >> 10) & 0x20) | ((dsp_control >> 6) & 0x1F),
+ uint32_t bits = ((dsp_control >> 10) & 0x20) | ((dsp_control >> 6) & 0x1F),
mask = ((dsp_flags >> 11) & 0x20) | ((dsp_flags >> 4) & 0x1F);
// WriteLog("dsp: bits=%.2x mask=%.2x\n",bits,mask);
if (!bits) // Bail if nothing is enabled
return;
- int which = 0; // Determine which interrupt
+ int which = 0; // Determine which interrupt
+
if (bits & 0x01)
which = 0;
if (bits & 0x02)
}
}
+#ifndef NEW_SCOREBOARD
if (affectsScoreboard[pipeline[plPtrWrite].opcode])
scoreboard[pipeline[plPtrWrite].operand2] = false;
+#else
+//Yup, sequential MOVEQ # problem fixing (I hope!)...
+ if (affectsScoreboard[pipeline[plPtrWrite].opcode])
+ if (scoreboard[pipeline[plPtrWrite].operand2])
+ scoreboard[pipeline[plPtrWrite].operand2]--;
+#endif
}
dsp_flags |= IMASK;
WriteLog(" [PC will return to %08X, R31 = %08X]\n", dsp_pc - (pipeline[plPtrExec].opcode == 38 ? 6 : (pipeline[plPtrExec].opcode == PIPELINE_STALL ? 0 : 2)), dsp_reg[31]);
#endif
- // subqt #4,r31 ; pre-decrement stack pointer
- // move pc,r30 ; address of interrupted code
+ // subqt #4,r31 ; pre-decrement stack pointer
+ // move pc,r30 ; address of interrupted code
// store r30,(r31) ; store return address
dsp_reg[31] -= 4;
//CC only!
#endif
//!!!!!!!!
- // movei #service_address,r30 ; pointer to ISR entry
- // jump (r30) ; jump to ISR
+ // movei #service_address,r30 ; pointer to ISR entry
+ // jump (r30) ; jump to ISR
// nop
dsp_pc = dsp_reg[30] = DSP_WORK_RAM_BASE + (which * 0x10);
//CC only!
FlushDSPPipeline();
}
+
//
// Non-pipelined version...
//
return;
// Get the active interrupt bits (latches) & interrupt mask (enables)
- uint32 bits = ((dsp_control >> 10) & 0x20) | ((dsp_control >> 6) & 0x1F),
+ uint32_t bits = ((dsp_control >> 10) & 0x20) | ((dsp_control >> 6) & 0x1F),
mask = ((dsp_flags >> 11) & 0x20) | ((dsp_flags >> 4) & 0x1F);
// WriteLog("dsp: bits=%.2x mask=%.2x\n",bits,mask);
if (!bits) // Bail if nothing is enabled
return;
- int which = 0; // Determine which interrupt
+ int which = 0; // Determine which interrupt
if (bits & 0x01)
which = 0;
if (bits & 0x02)
if (bits & 0x20)
which = 5;
-#ifdef DSP_DEBUG_IRQ
- WriteLog("DSP: Generating interrupt #%i...", which);
-#endif
-
- dsp_flags |= IMASK;
+ dsp_flags |= IMASK; // Force Bank #0
//CC only!
#ifdef DSP_DEBUG_CC
ctrl1[4] = dsp_flags;
#endif
//!!!!!!!!
+#ifdef DSP_DEBUG_IRQ
+ WriteLog("DSP: Bank 0: R30=%08X, R31=%08X\n", dsp_reg_bank_0[30], dsp_reg_bank_0[31]);
+ WriteLog("DSP: Bank 1: R30=%08X, R31=%08X\n", dsp_reg_bank_1[30], dsp_reg_bank_1[31]);
+#endif
DSPUpdateRegisterBanks();
#ifdef DSP_DEBUG_IRQ
+ WriteLog("DSP: Bank 0: R30=%08X, R31=%08X\n", dsp_reg_bank_0[30], dsp_reg_bank_0[31]);
+ WriteLog("DSP: Bank 1: R30=%08X, R31=%08X\n", dsp_reg_bank_1[30], dsp_reg_bank_1[31]);
+#endif
+
+#ifdef DSP_DEBUG_IRQ
+ WriteLog("DSP: Generating interrupt #%i...", which);
WriteLog(" [PC will return to %08X, R31 = %08X]\n", dsp_pc, dsp_reg[31]);
#endif
- // subqt #4,r31 ; pre-decrement stack pointer
- // move pc,r30 ; address of interrupted code
+ // subqt #4,r31 ; pre-decrement stack pointer
+ // move pc,r30 ; address of interrupted code
// store r30,(r31) ; store return address
dsp_reg[31] -= 4;
+ dsp_reg[30] = dsp_pc - 2; // -2 because we've executed the instruction already
+
//CC only!
#ifdef DSP_DEBUG_CC
regs1[31] -= 4;
#endif
//!!!!!!!!
- DSPWriteLong(dsp_reg[31], dsp_pc - 2, DSP);
+// DSPWriteLong(dsp_reg[31], dsp_pc - 2, DSP);
+ DSPWriteLong(dsp_reg[31], dsp_reg[30], DSP);
//CC only!
#ifdef DSP_DEBUG_CC
SET32(ram1, regs1[31] - 0xF1B000, dsp_pc - 2);
#endif
//!!!!!!!!
- // movei #service_address,r30 ; pointer to ISR entry
- // jump (r30) ; jump to ISR
+ // movei #service_address,r30 ; pointer to ISR entry
+ // jump (r30) ; jump to ISR
// nop
dsp_pc = dsp_reg[30] = DSP_WORK_RAM_BASE + (which * 0x10);
//CC only!
//!!!!!!!!
}
+
//
// Set the specified DSP IRQ line to a given state
//
void DSPSetIRQLine(int irqline, int state)
{
//NOTE: This doesn't take INT_LAT5 into account. !!! FIX !!!
- uint32 mask = INT_LAT0 << irqline;
+ uint32_t mask = INT_LAT0 << irqline;
dsp_control &= ~mask; // Clear the latch bit
//CC only!
#ifdef DSP_DEBUG_CC
if (state)
{
dsp_control |= mask; // Set the latch bit
- DSPHandleIRQs();
+#warning !!! No checking done to see if we're using pipelined DSP or not !!!
+// DSPHandleIRQs();
+ DSPHandleIRQsNP();
//CC only!
#ifdef DSP_DEBUG_CC
ctrl1[8] = ctrl2[8] = dsp_control;
#endif
//!!!!!!!!
}
+
+ // Not sure if this is correct behavior, but according to JTRM,
+ // the IRQ output of JERRY is fed to this IRQ in the GPU...
+// Not sure this is right--DSP interrupts seem to be different from the JERRY interrupts!
+// GPUSetIRQLine(GPUIRQ_DSP, ASSERT_LINE);
}
+
+bool DSPIsRunning(void)
+{
+ return (DSP_RUNNING ? true : false);
+}
+
+
void DSPInit(void)
{
- memory_malloc_secure((void **)&dsp_ram_8, 0x2000, "DSP work RAM");
- memory_malloc_secure((void **)&dsp_reg_bank_0, 32 * sizeof(int32), "DSP bank 0 regs");
- memory_malloc_secure((void **)&dsp_reg_bank_1, 32 * sizeof(int32), "DSP bank 1 regs");
+// memory_malloc_secure((void **)&dsp_ram_8, 0x2000, "DSP work RAM");
+// memory_malloc_secure((void **)&dsp_reg_bank_0, 32 * sizeof(int32_t), "DSP bank 0 regs");
+// memory_malloc_secure((void **)&dsp_reg_bank_1, 32 * sizeof(int32_t), "DSP bank 1 regs");
dsp_build_branch_condition_table();
DSPReset();
}
+
void DSPReset(void)
{
dsp_pc = 0x00F1B000;
IMASKCleared = false;
FlushDSPPipeline();
dsp_reset_stats();
- memset(dsp_ram_8, 0xFF, 0x2000);
+
+ // Contents of local RAM are quasi-stable; we simulate this by randomizing RAM contents
+ for(uint32_t i=0; i<8192; i+=4)
+ *((uint32_t *)(&dsp_ram_8[i])) = rand();
}
+
void DSPDumpDisassembly(void)
{
char buffer[512];
WriteLog("\n---[DSP code at 00F1B000]---------------------------\n");
- uint32 j = 0xF1B000;
+ uint32_t j = 0xF1B000;
+
while (j <= 0xF1CFFF)
{
- uint32 oldj = j;
+ uint32_t oldj = j;
j += dasmjag(JAGUAR_DSP, buffer, j);
WriteLog("\t%08X: %s\n", oldj, buffer);
}
}
+
void DSPDumpRegisters(void)
{
//Shoud add modulus, etc to dump here...
WriteLog("\n---[DSP flags: NCZ %d%d%d, DSP PC: %08X]------------\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, dsp_pc);
WriteLog("\nRegisters bank 0\n");
+
for(int j=0; j<8; j++)
{
WriteLog("\tR%02i = %08X R%02i = %08X R%02i = %08X R%02i = %08X\n",
- (j << 2) + 0, dsp_reg_bank_0[(j << 2) + 0],
- (j << 2) + 1, dsp_reg_bank_0[(j << 2) + 1],
- (j << 2) + 2, dsp_reg_bank_0[(j << 2) + 2],
- (j << 2) + 3, dsp_reg_bank_0[(j << 2) + 3]);
+ (j << 2) + 0, dsp_reg_bank_0[(j << 2) + 0],
+ (j << 2) + 1, dsp_reg_bank_0[(j << 2) + 1],
+ (j << 2) + 2, dsp_reg_bank_0[(j << 2) + 2],
+ (j << 2) + 3, dsp_reg_bank_0[(j << 2) + 3]);
}
+
WriteLog("Registers bank 1\n");
+
for(int j=0; j<8; j++)
{
WriteLog("\tR%02i = %08X R%02i = %08X R%02i = %08X R%02i = %08X\n",
- (j << 2) + 0, dsp_reg_bank_1[(j << 2) + 0],
- (j << 2) + 1, dsp_reg_bank_1[(j << 2) + 1],
- (j << 2) + 2, dsp_reg_bank_1[(j << 2) + 2],
- (j << 2) + 3, dsp_reg_bank_1[(j << 2) + 3]);
+ (j << 2) + 0, dsp_reg_bank_1[(j << 2) + 0],
+ (j << 2) + 1, dsp_reg_bank_1[(j << 2) + 1],
+ (j << 2) + 2, dsp_reg_bank_1[(j << 2) + 2],
+ (j << 2) + 3, dsp_reg_bank_1[(j << 2) + 3]);
}
}
+
void DSPDone(void)
{
- int i, j;
- WriteLog("DSP: Stopped at PC=%08X dsp_modulo=%08X (dsp %s running)\n", dsp_pc, dsp_modulo, (DSP_RUNNING ? "was" : "wasn't"));
+ WriteLog("\n\n---------------------------------------------------------------------\n");
+ WriteLog("DSP I/O Registers\n");
+ WriteLog("---------------------------------------------------------------------\n");
+ WriteLog("F1%04X (D_FLAGS): $%06X\n", 0xA100, (dsp_flags & 0xFFFFFFF8) | (dsp_flag_n << 2) | (dsp_flag_c << 1) | dsp_flag_z);
+ WriteLog("F1%04X (D_MTXC): $%04X\n", 0xA104, dsp_matrix_control);
+ WriteLog("F1%04X (D_MTXA): $%04X\n", 0xA108, dsp_pointer_to_matrix);
+ WriteLog("F1%04X (D_END): $%02X\n", 0xA10C, dsp_data_organization);
+ WriteLog("F1%04X (D_PC): $%06X\n", 0xA110, dsp_pc);
+ WriteLog("F1%04X (D_CTRL): $%06X\n", 0xA114, dsp_control);
+ WriteLog("F1%04X (D_MOD): $%08X\n", 0xA118, dsp_modulo);
+ WriteLog("F1%04X (D_REMAIN): $%08X\n", 0xA11C, dsp_remain);
+ WriteLog("F1%04X (D_DIVCTRL): $%02X\n", 0xA11C, dsp_div_control);
+ WriteLog("F1%04X (D_MACHI): $%02X\n", 0xA120, (dsp_acc >> 32) & 0xFF);
+ WriteLog("---------------------------------------------------------------------\n\n\n");
+
+ WriteLog("DSP: Stopped at PC=%08X dsp_modulo=%08X (dsp was%s running)\n", dsp_pc, dsp_modulo, (DSP_RUNNING ? "" : "n't"));
WriteLog("DSP: %sin interrupt handler\n", (dsp_flags & IMASK ? "" : "not "));
- // get the active interrupt bits
+ // Get the active interrupt bits
int bits = ((dsp_control >> 10) & 0x20) | ((dsp_control >> 6) & 0x1F);
- // get the interrupt mask
+ // Get the interrupt mask
int mask = ((dsp_flags >> 11) & 0x20) | ((dsp_flags >> 4) & 0x1F);
- WriteLog("DSP: pending=%08X enabled=%08X\n", bits, mask);
- WriteLog("\nRegisters bank 0\n");
- for(int j=0; j<8; j++)
- {
- WriteLog("\tr%2i=0x%.8x r%2i=0x%.8x r%2i=0x%.8x r%2i=0x%.8x\n",
- (j << 2) + 0, dsp_reg_bank_0[(j << 2) + 0],
- (j << 2) + 1, dsp_reg_bank_0[(j << 2) + 1],
- (j << 2) + 2, dsp_reg_bank_0[(j << 2) + 2],
- (j << 2) + 3, dsp_reg_bank_0[(j << 2) + 3]);
- }
- WriteLog("\nRegisters bank 1\n");
- for (j=0; j<8; j++)
- {
- WriteLog("\tr%2i=0x%.8x r%2i=0x%.8x r%2i=0x%.8x r%2i=0x%.8x\n",
- (j << 2) + 0, dsp_reg_bank_1[(j << 2) + 0],
- (j << 2) + 1, dsp_reg_bank_1[(j << 2) + 1],
- (j << 2) + 2, dsp_reg_bank_1[(j << 2) + 2],
- (j << 2) + 3, dsp_reg_bank_1[(j << 2) + 3]);
-
- }
+ WriteLog("DSP: pending=$%X enabled=$%X (%s%s%s%s%s%s)\n", bits, mask,
+ (mask & 0x01 ? "CPU " : ""), (mask & 0x02 ? "I2S " : ""),
+ (mask & 0x04 ? "Timer0 " : ""), (mask & 0x08 ? "Timer1 " : ""),
+ (mask & 0x10 ? "Ext0 " : ""), (mask & 0x20 ? "Ext1" : ""));
+ DSPDumpRegisters();
+ WriteLog("\n");
static char buffer[512];
- j = DSP_WORK_RAM_BASE;
- while (j <= 0xF1BFFF)
+ int j = DSP_WORK_RAM_BASE;
+
+ while (j <= 0xF1CFFF)
{
- uint32 oldj = j;
+ uint32_t oldj = j;
j += dasmjag(JAGUAR_DSP, buffer, j);
WriteLog("\t%08X: %s\n", oldj, buffer);
- }//*/
+ }
WriteLog("DSP opcodes use:\n");
- for (i=0;i<64;i++)
+
+ for(int i=0; i<64; i++)
{
if (dsp_opcode_use[i])
WriteLog("\t%s %i\n", dsp_opcode_str[i], dsp_opcode_use[i]);
- }//*/
-
- memory_free(dsp_ram_8);
+ }
}
// DSP comparison core...
//
#ifdef DSP_DEBUG_CC
-static uint16 lastExec;
-void DSPExecComp(int32 cycles)
+static uint16_t lastExec;
+void DSPExecComp(int32_t cycles)
{
while (cycles > 0 && DSP_RUNNING)
{
DSPUpdateRegisterBanks();
// Decrement cycles based on non-pipelined core...
- uint16 instr1 = DSPReadWord(dsp_pc, DSP);
+ uint16_t instr1 = DSPReadWord(dsp_pc, DSP);
cycles -= dsp_opcode_cycles[instr1 >> 10];
-//WriteLog("\tAbout to execute non-pipelined core on tick #%u (DSP_PC=%08X)...\n", (uint32)count, dsp_pc);
+//WriteLog("\tAbout to execute non-pipelined core on tick #%u (DSP_PC=%08X)...\n", (uint32_t)count, dsp_pc);
DSPExec(1); // Do *one* instruction
// Save vars
dsp_flag_c = ctrl2[13];
DSPUpdateRegisterBanks();
-//WriteLog("\tAbout to execute pipelined core on tick #%u (DSP_PC=%08X)...\n", (uint32)count, dsp_pc);
+//WriteLog("\tAbout to execute pipelined core on tick #%u (DSP_PC=%08X)...\n", (uint32_t)count, dsp_pc);
DSPExecP2(1); // Do *one* instruction
// Save vars
{
// WriteLog("\nCores diverged at instruction tick #%u!\nAttemping to synchronize...\n\n", count);
-// uint32 ppc = ctrl2[0] - (pipeline[plPtrExec].opcode == 38 ? 6 : (pipeline[plPtrExec].opcode == PIPELINE_STALL ? 0 : 2)) - (pipeline[plPtrWrite].opcode == 38 ? 6 : (pipeline[plPtrWrite].opcode == PIPELINE_STALL ? 0 : 2));
+// uint32_t ppc = ctrl2[0] - (pipeline[plPtrExec].opcode == 38 ? 6 : (pipeline[plPtrExec].opcode == PIPELINE_STALL ? 0 : 2)) - (pipeline[plPtrWrite].opcode == 38 ? 6 : (pipeline[plPtrWrite].opcode == PIPELINE_STALL ? 0 : 2));
//WriteLog("[DSP_PC1=%08X, DSP_PC2=%08X]\n", ctrl1[0], ppc);
// if (ctrl1[0] < ppc) // P ran ahead of NP
//How to test this crap???
instr1 = DSPReadWord(dsp_pc, DSP);
cycles -= dsp_opcode_cycles[instr1 >> 10];
-//WriteLog("\tAbout to execute non-pipelined core on tick #%u (DSP_PC=%08X)...\n", (uint32)count, dsp_pc);
+//WriteLog("\tAbout to execute non-pipelined core on tick #%u (DSP_PC=%08X)...\n", (uint32_t)count, dsp_pc);
DSPExec(1); // Do *one* instruction
}
// DSP execution core
//
//static bool R20Set = false, tripwire = false;
-//static uint32 pcQueue[32], ptrPCQ = 0;
-void DSPExec(int32 cycles)
+//static uint32_t pcQueue[32], ptrPCQ = 0;
+void DSPExec(int32_t cycles)
{
-/*HACKS!!! -> if (cycles != 1 && jaguar_mainRom_crc32 == 0xba74c3ed)
- dsp_check_if_i2s_interrupt_needed();*/
-
#ifdef DSP_SINGLE_STEPPING
if (dsp_control & 0x18)
{
while (cycles > 0 && DSP_RUNNING)
{
+/*extern uint32_t totalFrames;
+//F1B2F6: LOAD (R14+$04), R24 [NCZ:001, R14+$04=00F20018, R24=FFFFFFFF] -> Jaguar: Unknown word read at 00F20018 by DSP (M68K PC=00E32E)
+//-> 43 + 1 + 24 -> $2B + $01 + $18 -> 101011 00001 11000 -> 1010 1100 0011 1000 -> AC38
+//C470 -> 1100 0100 0111 0000 -> 110001 00011 10000 -> 49, 3, 16 -> STORE R16, (R14+$0C)
+//F1B140:
+if (totalFrames >= 377 && GET16(dsp_ram_8, 0x0002F6) == 0xAC38 && dsp_pc == 0xF1B140)
+{
+ doDSPDis = true;
+ WriteLog("Starting disassembly at frame #%u...\n", totalFrames);
+}
+if (dsp_pc == 0xF1B092)
+ doDSPDis = false;//*/
+/*if (dsp_pc == 0xF1B140)
+ doDSPDis = true;//*/
+
if (IMASKCleared) // If IMASK was cleared,
{
#ifdef DSP_DEBUG_IRQ
- WriteLog("DSP: Finished interrupt.\n");
+ WriteLog("DSP: Finished interrupt. PC=$%06X\n", dsp_pc);
#endif
DSPHandleIRQsNP(); // See if any other interrupts are pending!
IMASKCleared = false;
doDSPDis = true;
pcQueue[ptrPCQ++] = dsp_pc;
ptrPCQ %= 32;*/
- uint16 opcode = DSPReadWord(dsp_pc, DSP);
- uint32 index = opcode >> 10;
+ uint16_t opcode = DSPReadWord(dsp_pc, DSP);
+ uint32_t index = opcode >> 10;
dsp_opcode_first_parameter = (opcode >> 5) & 0x1F;
dsp_opcode_second_parameter = opcode & 0x1F;
dsp_pc += 2;
dsp_in_exec--;
}
+
//
// DSP opcode handlers
//
static void dsp_opcode_jump(void)
{
#ifdef DSP_DIS_JUMP
-char * condition[32] =
+const char * condition[32] =
{ "T", "nz", "z", "???", "nc", "nc nz", "nc z", "???", "c", "c nz",
"c z", "???", "???", "???", "???", "???", "???", "???", "???",
"???", "nn", "nn nz", "nn z", "???", "n", "n nz", "n z", "???",
dsp_flag_z=dsp_flag_z?1:0;
dsp_flag_n=dsp_flag_n?1:0;*/
// KLUDGE: Used by BRANCH_CONDITION
- uint32 jaguar_flags = (dsp_flag_n << 2) | (dsp_flag_c << 1) | dsp_flag_z;
+ uint32_t jaguar_flags = (dsp_flag_n << 2) | (dsp_flag_c << 1) | dsp_flag_z;
if (BRANCH_CONDITION(IMM_2))
{
if (doDSPDis)
WriteLog("Branched!\n");
#endif
- uint32 delayed_pc = RM;
+ uint32_t delayed_pc = RM;
DSPExec(1);
dsp_pc = delayed_pc;
}
#endif
}
+
static void dsp_opcode_jr(void)
{
#ifdef DSP_DIS_JR
-char * condition[32] =
+const char * condition[32] =
{ "T", "nz", "z", "???", "nc", "nc nz", "nc z", "???", "c", "c nz",
"c z", "???", "???", "???", "???", "???", "???", "???", "???",
"???", "nn", "nn nz", "nn z", "???", "n", "n nz", "n z", "???",
dsp_flag_z=dsp_flag_z?1:0;
dsp_flag_n=dsp_flag_n?1:0;*/
// KLUDGE: Used by BRANCH_CONDITION
- uint32 jaguar_flags = (dsp_flag_n << 2) | (dsp_flag_c << 1) | dsp_flag_z;
+ uint32_t jaguar_flags = (dsp_flag_n << 2) | (dsp_flag_c << 1) | dsp_flag_z;
if (BRANCH_CONDITION(IMM_2))
{
if (doDSPDis)
WriteLog("Branched!\n");
#endif
- int32 offset = (IMM_1 & 0x10 ? 0xFFFFFFF0 | IMM_1 : IMM_1); // Sign extend IMM_1
- int32 delayed_pc = dsp_pc + (offset * 2);
+ int32_t offset = (IMM_1 & 0x10 ? 0xFFFFFFF0 | IMM_1 : IMM_1); // Sign extend IMM_1
+ int32_t delayed_pc = dsp_pc + (offset * 2);
DSPExec(1);
dsp_pc = delayed_pc;
}
#endif
}
+
static void dsp_opcode_add(void)
{
#ifdef DSP_DIS_ADD
if (doDSPDis)
WriteLog("%06X: ADD R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
#endif
- UINT32 res = RN + RM;
+ uint32_t res = RN + RM;
SET_ZNC_ADD(RN, RM, res);
RN = res;
#ifdef DSP_DIS_ADD
#endif
}
+
static void dsp_opcode_addc(void)
{
#ifdef DSP_DIS_ADDC
if (doDSPDis)
WriteLog("%06X: ADDC R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
#endif
- UINT32 res = RN + RM + dsp_flag_c;
- UINT32 carry = dsp_flag_c;
+ uint32_t res = RN + RM + dsp_flag_c;
+ uint32_t carry = dsp_flag_c;
// SET_ZNC_ADD(RN, RM, res); //???BUG??? Yes!
SET_ZNC_ADD(RN + carry, RM, res);
// SET_ZNC_ADD(RN, RM + carry, res);
#endif
}
+
static void dsp_opcode_addq(void)
{
#ifdef DSP_DIS_ADDQ
if (doDSPDis)
WriteLog("%06X: ADDQ #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, dsp_convert_zero[IMM_1], IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
#endif
- UINT32 r1 = dsp_convert_zero[IMM_1];
- UINT32 res = RN + r1;
+ uint32_t r1 = dsp_convert_zero[IMM_1];
+ uint32_t res = RN + r1;
CLR_ZNC; SET_ZNC_ADD(RN, r1, res);
RN = res;
#ifdef DSP_DIS_ADDQ
#endif
}
+
static void dsp_opcode_sub(void)
{
#ifdef DSP_DIS_SUB
if (doDSPDis)
WriteLog("%06X: SUB R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
#endif
- UINT32 res = RN - RM;
+ uint32_t res = RN - RM;
SET_ZNC_SUB(RN, RM, res);
RN = res;
#ifdef DSP_DIS_SUB
#endif
}
+
static void dsp_opcode_subc(void)
{
#ifdef DSP_DIS_SUBC
if (doDSPDis)
WriteLog("%06X: SUBC R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
#endif
- UINT32 res = RN - RM - dsp_flag_c;
- UINT32 borrow = dsp_flag_c;
- SET_ZNC_SUB(RN - borrow, RM, res);
- RN = res;
+ // This is how the DSP ALU does it--Two's complement with inverted carry
+ uint64_t res = (uint64_t)RN + (uint64_t)(RM ^ 0xFFFFFFFF) + (dsp_flag_c ^ 1);
+ // Carry out of the result is inverted too
+ dsp_flag_c = ((res >> 32) & 0x01) ^ 1;
+ RN = (res & 0xFFFFFFFF);
+ SET_ZN(RN);
#ifdef DSP_DIS_SUBC
if (doDSPDis)
WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
#endif
}
+
static void dsp_opcode_subq(void)
{
#ifdef DSP_DIS_SUBQ
if (doDSPDis)
WriteLog("%06X: SUBQ #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, dsp_convert_zero[IMM_1], IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
#endif
- UINT32 r1 = dsp_convert_zero[IMM_1];
- UINT32 res = RN - r1;
+ uint32_t r1 = dsp_convert_zero[IMM_1];
+ uint32_t res = RN - r1;
SET_ZNC_SUB(RN, r1, res);
RN = res;
#ifdef DSP_DIS_SUBQ
#endif
}
+
static void dsp_opcode_cmp(void)
{
#ifdef DSP_DIS_CMP
if (doDSPDis)
WriteLog("%06X: CMP R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
#endif
- UINT32 res = RN - RM;
+ uint32_t res = RN - RM;
SET_ZNC_SUB(RN, RM, res);
#ifdef DSP_DIS_CMP
if (doDSPDis)
#endif
}
+
static void dsp_opcode_cmpq(void)
{
- static int32 sqtable[32] =
+ static int32_t sqtable[32] =
{ 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1 };
#ifdef DSP_DIS_CMPQ
if (doDSPDis)
WriteLog("%06X: CMPQ #%d, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, sqtable[IMM_1], IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
#endif
- UINT32 r1 = sqtable[IMM_1 & 0x1F]; // I like this better -> (INT8)(jaguar.op >> 2) >> 3;
- UINT32 res = RN - r1;
+ uint32_t r1 = sqtable[IMM_1 & 0x1F]; // I like this better -> (INT8)(jaguar.op >> 2) >> 3;
+ uint32_t res = RN - r1;
SET_ZNC_SUB(RN, r1, res);
#ifdef DSP_DIS_CMPQ
if (doDSPDis)
#endif
}
+
static void dsp_opcode_and(void)
{
#ifdef DSP_DIS_AND
#endif
}
+
static void dsp_opcode_or(void)
{
#ifdef DSP_DIS_OR
#endif
}
+
static void dsp_opcode_xor(void)
{
#ifdef DSP_DIS_XOR
#endif
}
+
static void dsp_opcode_not(void)
{
#ifdef DSP_DIS_NOT
if (doDSPDis)
- WriteLog("%06X: NOT R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
+ WriteLog("%06X: NOT R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
#endif
RN = ~RN;
SET_ZN(RN);
#ifdef DSP_DIS_NOT
if (doDSPDis)
- WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
+ WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
#endif
}
+
static void dsp_opcode_move_pc(void)
{
RN = dsp_pc - 2;
}
+
static void dsp_opcode_store_r14_indexed(void)
{
#ifdef DSP_DIS_STORE14I
if (doDSPDis)
WriteLog("%06X: STORE R%02u, (R14+$%02X) [NCZ:%u%u%u, R%02u=%08X, R14+$%02X=%08X]\n", dsp_pc-2, IMM_2, dsp_convert_zero[IMM_1] << 2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN, dsp_convert_zero[IMM_1] << 2, dsp_reg[14]+(dsp_convert_zero[IMM_1] << 2));
#endif
+#ifdef DSP_CORRECT_ALIGNMENT_STORE
+ DSPWriteLong((dsp_reg[14] & 0xFFFFFFFC) + (dsp_convert_zero[IMM_1] << 2), RN, DSP);
+#else
DSPWriteLong(dsp_reg[14] + (dsp_convert_zero[IMM_1] << 2), RN, DSP);
+#endif
}
+
static void dsp_opcode_store_r15_indexed(void)
{
#ifdef DSP_DIS_STORE15I
if (doDSPDis)
WriteLog("%06X: STORE R%02u, (R15+$%02X) [NCZ:%u%u%u, R%02u=%08X, R15+$%02X=%08X]\n", dsp_pc-2, IMM_2, dsp_convert_zero[IMM_1] << 2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN, dsp_convert_zero[IMM_1] << 2, dsp_reg[15]+(dsp_convert_zero[IMM_1] << 2));
#endif
+#ifdef DSP_CORRECT_ALIGNMENT_STORE
+ DSPWriteLong((dsp_reg[15] & 0xFFFFFFFC) + (dsp_convert_zero[IMM_1] << 2), RN, DSP);
+#else
DSPWriteLong(dsp_reg[15] + (dsp_convert_zero[IMM_1] << 2), RN, DSP);
+#endif
}
+
static void dsp_opcode_load_r14_ri(void)
{
#ifdef DSP_DIS_LOAD14R
if (doDSPDis)
WriteLog("%06X: LOAD (R14+R%02u), R%02u [NCZ:%u%u%u, R14+R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM+dsp_reg[14], IMM_2, RN);
#endif
+#ifdef DSP_CORRECT_ALIGNMENT
+ RN = DSPReadLong((dsp_reg[14] + RM) & 0xFFFFFFFC, DSP);
+#else
RN = DSPReadLong(dsp_reg[14] + RM, DSP);
+#endif
#ifdef DSP_DIS_LOAD14R
if (doDSPDis)
WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
#endif
}
+
static void dsp_opcode_load_r15_ri(void)
{
#ifdef DSP_DIS_LOAD15R
if (doDSPDis)
WriteLog("%06X: LOAD (R15+R%02u), R%02u [NCZ:%u%u%u, R15+R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM+dsp_reg[15], IMM_2, RN);
#endif
+#ifdef DSP_CORRECT_ALIGNMENT
+ RN = DSPReadLong((dsp_reg[15] + RM) & 0xFFFFFFFC, DSP);
+#else
RN = DSPReadLong(dsp_reg[15] + RM, DSP);
+#endif
#ifdef DSP_DIS_LOAD15R
if (doDSPDis)
WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
#endif
}
+
static void dsp_opcode_store_r14_ri(void)
{
DSPWriteLong(dsp_reg[14] + RM, RN, DSP);
}
+
static void dsp_opcode_store_r15_ri(void)
{
DSPWriteLong(dsp_reg[15] + RM, RN, DSP);
}
+
static void dsp_opcode_nop(void)
{
#ifdef DSP_DIS_NOP
#endif
}
+
static void dsp_opcode_storeb(void)
{
#ifdef DSP_DIS_STOREB
JaguarWriteByte(RM, RN, DSP);
}
+
static void dsp_opcode_storew(void)
{
#ifdef DSP_DIS_STOREW
if (doDSPDis)
WriteLog("%06X: STOREW R%02u, (R%02u) [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_pc-2, IMM_2, IMM_1, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN, IMM_1, RM);
#endif
+#ifdef DSP_CORRECT_ALIGNMENT_STORE
+ if (RM >= DSP_WORK_RAM_BASE && RM <= (DSP_WORK_RAM_BASE + 0x1FFF))
+ DSPWriteLong(RM & 0xFFFFFFFE, RN & 0xFFFF, DSP);
+ else
+ JaguarWriteWord(RM & 0xFFFFFFFE, RN, DSP);
+#else
if (RM >= DSP_WORK_RAM_BASE && RM <= (DSP_WORK_RAM_BASE + 0x1FFF))
DSPWriteLong(RM, RN & 0xFFFF, DSP);
else
JaguarWriteWord(RM, RN, DSP);
+#endif
}
+
static void dsp_opcode_store(void)
{
#ifdef DSP_DIS_STORE
if (doDSPDis)
WriteLog("%06X: STORE R%02u, (R%02u) [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_pc-2, IMM_2, IMM_1, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN, IMM_1, RM);
#endif
+#ifdef DSP_CORRECT_ALIGNMENT_STORE
+ DSPWriteLong(RM & 0xFFFFFFFC, RN, DSP);
+#else
DSPWriteLong(RM, RN, DSP);
+#endif
}
+
static void dsp_opcode_loadb(void)
{
#ifdef DSP_DIS_LOADB
#endif
}
+
static void dsp_opcode_loadw(void)
{
#ifdef DSP_DIS_LOADW
if (doDSPDis)
WriteLog("%06X: LOADW (R%02u), R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
#endif
+#ifdef DSP_CORRECT_ALIGNMENT
+ if (RM >= DSP_WORK_RAM_BASE && RM <= (DSP_WORK_RAM_BASE + 0x1FFF))
+ RN = DSPReadLong(RM & 0xFFFFFFFE, DSP) & 0xFFFF;
+ else
+ RN = JaguarReadWord(RM & 0xFFFFFFFE, DSP);
+#else
if (RM >= DSP_WORK_RAM_BASE && RM <= (DSP_WORK_RAM_BASE + 0x1FFF))
RN = DSPReadLong(RM, DSP) & 0xFFFF;
else
RN = JaguarReadWord(RM, DSP);
+#endif
#ifdef DSP_DIS_LOADW
if (doDSPDis)
WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
#endif
}
+
static void dsp_opcode_load(void)
{
#ifdef DSP_DIS_LOAD
if (doDSPDis)
WriteLog("%06X: LOAD (R%02u), R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
#endif
+#ifdef DSP_CORRECT_ALIGNMENT
+ RN = DSPReadLong(RM & 0xFFFFFFFC, DSP);
+#else
RN = DSPReadLong(RM, DSP);
+#endif
#ifdef DSP_DIS_LOAD
if (doDSPDis)
WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
#endif
}
+
static void dsp_opcode_load_r14_indexed(void)
{
#ifdef DSP_DIS_LOAD14I
if (doDSPDis)
WriteLog("%06X: LOAD (R14+$%02X), R%02u [NCZ:%u%u%u, R14+$%02X=%08X, R%02u=%08X] -> ", dsp_pc-2, dsp_convert_zero[IMM_1] << 2, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, dsp_convert_zero[IMM_1] << 2, dsp_reg[14]+(dsp_convert_zero[IMM_1] << 2), IMM_2, RN);
#endif
+#ifdef DSP_CORRECT_ALIGNMENT
+ RN = DSPReadLong((dsp_reg[14] & 0xFFFFFFFC) + (dsp_convert_zero[IMM_1] << 2), DSP);
+#else
RN = DSPReadLong(dsp_reg[14] + (dsp_convert_zero[IMM_1] << 2), DSP);
+#endif
#ifdef DSP_DIS_LOAD14I
if (doDSPDis)
WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
#endif
}
+
static void dsp_opcode_load_r15_indexed(void)
{
#ifdef DSP_DIS_LOAD15I
if (doDSPDis)
WriteLog("%06X: LOAD (R15+$%02X), R%02u [NCZ:%u%u%u, R15+$%02X=%08X, R%02u=%08X] -> ", dsp_pc-2, dsp_convert_zero[IMM_1] << 2, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, dsp_convert_zero[IMM_1] << 2, dsp_reg[15]+(dsp_convert_zero[IMM_1] << 2), IMM_2, RN);
#endif
+#ifdef DSP_CORRECT_ALIGNMENT
+ RN = DSPReadLong((dsp_reg[15] & 0xFFFFFFFC) + (dsp_convert_zero[IMM_1] << 2), DSP);
+#else
RN = DSPReadLong(dsp_reg[15] + (dsp_convert_zero[IMM_1] << 2), DSP);
+#endif
#ifdef DSP_DIS_LOAD15I
if (doDSPDis)
WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
#endif
}
+
static void dsp_opcode_movei(void)
{
#ifdef DSP_DIS_MOVEI
if (doDSPDis)
- WriteLog("%06X: MOVEI #$%08X, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, (uint32)DSPReadWord(dsp_pc) | ((uint32)DSPReadWord(dsp_pc + 2) << 16), IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
+ WriteLog("%06X: MOVEI #$%08X, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, (uint32_t)DSPReadWord(dsp_pc) | ((uint32_t)DSPReadWord(dsp_pc + 2) << 16), IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
#endif
// This instruction is followed by 32-bit value in LSW / MSW format...
- RN = (uint32)DSPReadWord(dsp_pc, DSP) | ((uint32)DSPReadWord(dsp_pc + 2, DSP) << 16);
+ RN = (uint32_t)DSPReadWord(dsp_pc, DSP) | ((uint32_t)DSPReadWord(dsp_pc + 2, DSP) << 16);
dsp_pc += 4;
#ifdef DSP_DIS_MOVEI
if (doDSPDis)
#endif
}
+
static void dsp_opcode_moveta(void)
{
#ifdef DSP_DIS_MOVETA
#endif
}
+
static void dsp_opcode_movefa(void)
{
#ifdef DSP_DIS_MOVEFA
#endif
}
+
static void dsp_opcode_move(void)
{
#ifdef DSP_DIS_MOVE
#endif
}
+
static void dsp_opcode_moveq(void)
{
#ifdef DSP_DIS_MOVEQ
#endif
}
+
static void dsp_opcode_resmac(void)
{
#ifdef DSP_DIS_RESMAC
if (doDSPDis)
- WriteLog("%06X: RESMAC R%02u [NCZ:%u%u%u, R%02u=%08X, DSP_ACC=%02X%08X] -> ", dsp_pc-2, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN, (uint8)(dsp_acc >> 32), (uint32)(dsp_acc & 0xFFFFFFFF));
+ WriteLog("%06X: RESMAC R%02u [NCZ:%u%u%u, R%02u=%08X, DSP_ACC=%02X%08X] -> ", dsp_pc-2, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN, (uint8_t)(dsp_acc >> 32), (uint32_t)(dsp_acc & 0xFFFFFFFF));
#endif
- RN = (uint32)dsp_acc;
+ RN = (uint32_t)dsp_acc;
#ifdef DSP_DIS_RESMAC
if (doDSPDis)
WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
#endif
}
+
static void dsp_opcode_imult(void)
{
#ifdef DSP_DIS_IMULT
if (doDSPDis)
WriteLog("%06X: IMULT R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
#endif
- RN = (int16)RN * (int16)RM;
+ RN = (int16_t)RN * (int16_t)RM;
SET_ZN(RN);
#ifdef DSP_DIS_IMULT
if (doDSPDis)
#endif
}
+
static void dsp_opcode_mult(void)
{
#ifdef DSP_DIS_MULT
if (doDSPDis)
WriteLog("%06X: MULT R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
#endif
- RN = (uint16)RM * (uint16)RN;
+ RN = (uint16_t)RM * (uint16_t)RN;
SET_ZN(RN);
#ifdef DSP_DIS_MULT
if (doDSPDis)
#endif
}
+
static void dsp_opcode_bclr(void)
{
#ifdef DSP_DIS_BCLR
if (doDSPDis)
WriteLog("%06X: BCLR #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
#endif
- UINT32 res = RN & ~(1 << IMM_1);
+ uint32_t res = RN & ~(1 << IMM_1);
RN = res;
SET_ZN(res);
#ifdef DSP_DIS_BCLR
#endif
}
+
static void dsp_opcode_btst(void)
{
#ifdef DSP_DIS_BTST
#endif
}
+
static void dsp_opcode_bset(void)
{
#ifdef DSP_DIS_BSET
if (doDSPDis)
WriteLog("%06X: BSET #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
#endif
- UINT32 res = RN | (1 << IMM_1);
+ uint32_t res = RN | (1 << IMM_1);
RN = res;
SET_ZN(res);
#ifdef DSP_DIS_BSET
#endif
}
+
static void dsp_opcode_subqt(void)
{
#ifdef DSP_DIS_SUBQT
#endif
}
+
static void dsp_opcode_addqt(void)
{
#ifdef DSP_DIS_ADDQT
#endif
}
+
static void dsp_opcode_imacn(void)
{
#ifdef DSP_DIS_IMACN
if (doDSPDis)
WriteLog("%06X: IMACN R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
#endif
- int32 res = (int16)RM * (int16)RN;
- dsp_acc += (int64)res;
+ int32_t res = (int16_t)RM * (int16_t)RN;
+ dsp_acc += (int64_t)res;
//Should we AND the result to fit into 40 bits here???
#ifdef DSP_DIS_IMACN
if (doDSPDis)
- WriteLog("[NCZ:%u%u%u, DSP_ACC=%02X%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, (uint8)(dsp_acc >> 32), (uint32)(dsp_acc & 0xFFFFFFFF));
+ WriteLog("[NCZ:%u%u%u, DSP_ACC=%02X%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, (uint8_t)(dsp_acc >> 32), (uint32_t)(dsp_acc & 0xFFFFFFFF));
#endif
-}
+}
+
static void dsp_opcode_mtoi(void)
{
- RN = (((INT32)RM >> 8) & 0xFF800000) | (RM & 0x007FFFFF);
+ RN = (((int32_t)RM >> 8) & 0xFF800000) | (RM & 0x007FFFFF);
SET_ZN(RN);
}
+
static void dsp_opcode_normi(void)
{
- uint32 _Rm = RM;
- uint32 res = 0;
+ uint32_t _Rm = RM;
+ uint32_t res = 0;
if (_Rm)
{
SET_ZN(RN);
}
+
static void dsp_opcode_mmult(void)
{
int count = dsp_matrix_control&0x0f;
- uint32 addr = dsp_pointer_to_matrix; // in the gpu ram
- int64 accum = 0;
- uint32 res;
+ uint32_t addr = dsp_pointer_to_matrix; // in the dsp ram
+ int64_t accum = 0;
+ uint32_t res;
if (!(dsp_matrix_control & 0x10))
{
for (int i = 0; i < count; i++)
- {
- int16 a;
+ {
+ int16_t a;
if (i&0x01)
- a=(int16)((dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]>>16)&0xffff);
+ a=(int16_t)((dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]>>16)&0xffff);
else
- a=(int16)(dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]&0xffff);
- int16 b=((int16)DSPReadWord(addr + 2, DSP));
+ a=(int16_t)(dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]&0xffff);
+ int16_t b=((int16_t)DSPReadWord(addr + 2, DSP));
accum += a*b;
addr += 4;
}
{
for (int i = 0; i < count; i++)
{
- int16 a;
+ int16_t a;
if (i&0x01)
- a=(int16)((dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]>>16)&0xffff);
+ a=(int16_t)((dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]>>16)&0xffff);
else
- a=(int16)(dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]&0xffff);
- int16 b=((int16)DSPReadWord(addr + 2, DSP));
+ a=(int16_t)(dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]&0xffff);
+ int16_t b=((int16_t)DSPReadWord(addr + 2, DSP));
accum += a*b;
addr += 4 * count;
}
}
- RN = res = (int32)accum;
+ RN = res = (int32_t)accum;
// carry flag to do
//NOTE: The flags are set based upon the last add/multiply done...
SET_ZN(RN);
}
+
static void dsp_opcode_abs(void)
{
- uint32 _Rn = RN;
- uint32 res;
-
+#ifdef DSP_DIS_ABS
+ if (doDSPDis)
+ WriteLog("%06X: ABS R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
+#endif
+ uint32_t _Rn = RN;
+ uint32_t res;
+
if (_Rn == 0x80000000)
dsp_flag_n = 1;
else
res = RN = (_Rn & 0x80000000 ? -_Rn : _Rn);
CLR_ZN; SET_Z(res);
}
+#ifdef DSP_DIS_ABS
+ if (doDSPDis)
+ WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
+#endif
}
+
static void dsp_opcode_div(void)
{
- uint32 _Rm=RM;
- uint32 _Rn=RN;
-
- if (_Rm)
+#if 0
+ if (RM)
{
- if (dsp_div_control & 1)
+ if (dsp_div_control & 0x01) // 16.16 division
{
- dsp_remain = (((uint64)_Rn) << 16) % _Rm;
- if (dsp_remain&0x80000000)
- dsp_remain-=_Rm;
- RN = (((uint64)_Rn) << 16) / _Rm;
+ dsp_remain = ((uint64_t)RN << 16) % RM;
+ RN = ((uint64_t)RN << 16) / RM;
}
else
{
- dsp_remain = _Rn % _Rm;
- if (dsp_remain&0x80000000)
- dsp_remain-=_Rm;
- RN/=_Rm;
+ // We calculate the remainder first because we destroy RN after
+ // this by assigning it to itself.
+ dsp_remain = RN % RM;
+ RN = RN / RM;
}
+
}
else
- RN=0xffffffff;
+ {
+ // This is what happens according to SCPCD. NYAN!
+ RN = 0xFFFFFFFF;
+ dsp_remain = 0;
+ }
+#else
+ // Real algorithm, courtesy of SCPCD: NYAN!
+ uint32_t q = RN;
+ uint32_t r = 0;
+
+ // If 16.16 division, stuff top 16 bits of RN into remainder and put the
+ // bottom 16 of RN in top 16 of quotient
+ if (dsp_div_control & 0x01)
+ q <<= 16, r = RN >> 16;
+
+ for(int i=0; i<32; i++)
+ {
+// uint32_t sign = (r >> 31) & 0x01;
+ uint32_t sign = r & 0x80000000;
+ r = (r << 1) | ((q >> 31) & 0x01);
+ r += (sign ? RM : -RM);
+ q = (q << 1) | (((~r) >> 31) & 0x01);
+ }
+
+ RN = q;
+ dsp_remain = r;
+#endif
}
+
static void dsp_opcode_imultn(void)
{
#ifdef DSP_DIS_IMULTN
WriteLog("%06X: IMULTN R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
#endif
// This is OK, since this multiply won't overflow 32 bits...
- int32 res = (int32)((int16)RN * (int16)RM);
- dsp_acc = (int64)res;
+ int32_t res = (int32_t)((int16_t)RN * (int16_t)RM);
+ dsp_acc = (int64_t)res;
SET_ZN(res);
#ifdef DSP_DIS_IMULTN
if (doDSPDis)
- WriteLog("[NCZ:%u%u%u, DSP_ACC=%02X%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, (uint8)(dsp_acc >> 32), (uint32)(dsp_acc & 0xFFFFFFFF));
+ WriteLog("[NCZ:%u%u%u, DSP_ACC=%02X%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, (uint8_t)(dsp_acc >> 32), (uint32_t)(dsp_acc & 0xFFFFFFFF));
#endif
}
+
static void dsp_opcode_neg(void)
{
#ifdef DSP_DIS_NEG
if (doDSPDis)
WriteLog("%06X: NEG R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
#endif
- UINT32 res = -RN;
+ uint32_t res = -RN;
SET_ZNC_SUB(0, RN, res);
RN = res;
#ifdef DSP_DIS_NEG
#endif
}
+
static void dsp_opcode_shlq(void)
{
#ifdef DSP_DIS_SHLQ
if (doDSPDis)
WriteLog("%06X: SHLQ #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, 32 - IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
#endif
- INT32 r1 = 32 - IMM_1;
- UINT32 res = RN << r1;
+ // NB: This instruction is the *only* one that does (32 - immediate data).
+ int32_t r1 = 32 - IMM_1;
+ uint32_t res = RN << r1;
SET_ZN(res); dsp_flag_c = (RN >> 31) & 1;
RN = res;
#ifdef DSP_DIS_SHLQ
#endif
}
+
static void dsp_opcode_shrq(void)
{
#ifdef DSP_DIS_SHRQ
if (doDSPDis)
WriteLog("%06X: SHRQ #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, dsp_convert_zero[IMM_1], IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
#endif
- INT32 r1 = dsp_convert_zero[IMM_1];
- UINT32 res = RN >> r1;
+ int32_t r1 = dsp_convert_zero[IMM_1];
+ uint32_t res = RN >> r1;
SET_ZN(res); dsp_flag_c = RN & 1;
RN = res;
#ifdef DSP_DIS_SHRQ
#endif
}
+
static void dsp_opcode_ror(void)
{
#ifdef DSP_DIS_ROR
if (doDSPDis)
WriteLog("%06X: ROR R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_1, RM, IMM_2, RN);
#endif
- UINT32 r1 = RM & 0x1F;
- UINT32 res = (RN >> r1) | (RN << (32 - r1));
+ uint32_t r1 = RM & 0x1F;
+ uint32_t res = (RN >> r1) | (RN << (32 - r1));
SET_ZN(res); dsp_flag_c = (RN >> 31) & 1;
RN = res;
#ifdef DSP_DIS_ROR
#endif
}
+
static void dsp_opcode_rorq(void)
{
#ifdef DSP_DIS_RORQ
if (doDSPDis)
WriteLog("%06X: RORQ #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, dsp_convert_zero[IMM_1], IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
#endif
- UINT32 r1 = dsp_convert_zero[IMM_1 & 0x1F];
- UINT32 r2 = RN;
- UINT32 res = (r2 >> r1) | (r2 << (32 - r1));
+ uint32_t r1 = dsp_convert_zero[IMM_1 & 0x1F];
+ uint32_t r2 = RN;
+ uint32_t res = (r2 >> r1) | (r2 << (32 - r1));
RN = res;
SET_ZN(res); dsp_flag_c = (r2 >> 31) & 0x01;
#ifdef DSP_DIS_RORQ
#endif
}
+
static void dsp_opcode_sha(void)
{
- int32 sRm=(int32)RM;
- uint32 _Rn=RN;
+ int32_t sRm=(int32_t)RM;
+ uint32_t _Rn=RN;
if (sRm<0)
{
- uint32 shift=-sRm;
+ uint32_t shift=-sRm;
if (shift>=32) shift=32;
dsp_flag_c=(_Rn&0x80000000)>>31;
while (shift)
}
else
{
- uint32 shift=sRm;
+ uint32_t shift=sRm;
if (shift>=32) shift=32;
dsp_flag_c=_Rn&0x1;
while (shift)
{
- _Rn=((int32)_Rn)>>1;
+ _Rn=((int32_t)_Rn)>>1;
shift--;
}
}
SET_ZN(RN);
}
+
static void dsp_opcode_sharq(void)
{
#ifdef DSP_DIS_SHARQ
if (doDSPDis)
WriteLog("%06X: SHARQ #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", dsp_pc-2, dsp_convert_zero[IMM_1], IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN);
#endif
- UINT32 res = (INT32)RN >> dsp_convert_zero[IMM_1];
+ uint32_t res = (int32_t)RN >> dsp_convert_zero[IMM_1];
SET_ZN(res); dsp_flag_c = RN & 0x01;
RN = res;
#ifdef DSP_DIS_SHARQ
#endif
}
+
static void dsp_opcode_sh(void)
{
- int32 sRm=(int32)RM;
- uint32 _Rn=RN;
+ int32_t sRm=(int32_t)RM;
+ uint32_t _Rn=RN;
if (sRm<0)
{
- uint32 shift=(-sRm);
+ uint32_t shift=(-sRm);
if (shift>=32) shift=32;
dsp_flag_c=(_Rn&0x80000000)>>31;
while (shift)
}
else
{
- uint32 shift=sRm;
+ uint32_t shift=sRm;
if (shift>=32) shift=32;
dsp_flag_c=_Rn&0x1;
while (shift)
if (doDSPDis)
WriteLog("%06X: ADDQMOD #%u, R%02u [NCZ:%u%u%u, R%02u=%08X, DSP_MOD=%08X] -> ", dsp_pc-2, dsp_convert_zero[IMM_1], IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z, IMM_2, RN, dsp_modulo);
#endif
- UINT32 r1 = dsp_convert_zero[IMM_1];
- UINT32 r2 = RN;
- UINT32 res = r2 + r1;
+ uint32_t r1 = dsp_convert_zero[IMM_1];
+ uint32_t r2 = RN;
+ uint32_t res = r2 + r1;
res = (res & (~dsp_modulo)) | (r2 & dsp_modulo);
RN = res;
SET_ZNC_ADD(r2, r1, res);
#endif
}
-void dsp_opcode_subqmod(void)
+void dsp_opcode_subqmod(void)
{
- UINT32 r1 = dsp_convert_zero[IMM_1];
- UINT32 r2 = RN;
- UINT32 res = r2 - r1;
+ uint32_t r1 = dsp_convert_zero[IMM_1];
+ uint32_t r2 = RN;
+ uint32_t res = r2 - r1;
res = (res & (~dsp_modulo)) | (r2 & dsp_modulo);
RN = res;
-
+
SET_ZNC_SUB(r2, r1, res);
}
-void dsp_opcode_mirror(void)
+void dsp_opcode_mirror(void)
{
- UINT32 r1 = RN;
+ uint32_t r1 = RN;
RN = (mirror_table[r1 & 0xFFFF] << 16) | mirror_table[r1 >> 16];
SET_ZN(RN);
}
-void dsp_opcode_sat32s(void)
+void dsp_opcode_sat32s(void)
{
- INT32 r2 = (UINT32)RN;
- INT32 temp = dsp_acc >> 32;
- UINT32 res = (temp < -1) ? (INT32)0x80000000 : (temp > 0) ? (INT32)0x7FFFFFFF : r2;
+ int32_t r2 = (uint32_t)RN;
+ int32_t temp = dsp_acc >> 32;
+ uint32_t res = (temp < -1) ? (int32_t)0x80000000 : (temp > 0) ? (int32_t)0x7FFFFFFF : r2;
RN = res;
SET_ZN(res);
}
-void dsp_opcode_sat16s(void)
+void dsp_opcode_sat16s(void)
{
- INT32 r2 = RN;
- UINT32 res = (r2 < -32768) ? -32768 : (r2 > 32767) ? 32767 : r2;
+ int32_t r2 = RN;
+ uint32_t res = (r2 < -32768) ? -32768 : (r2 > 32767) ? 32767 : r2;
RN = res;
SET_ZN(res);
}
+void dsp_opcode_illegal(void)
+{
+ // Don't know what it does, but it does *something*...
+ WriteLog("%06X: illegal %u, %u [NCZ:%u%u%u]\n", dsp_pc-2, IMM_1, IMM_2, dsp_flag_n, dsp_flag_c, dsp_flag_z);
+}
+
//
// New pipelined DSP core
//
static void DSP_add(void);
static void DSP_addc(void);
static void DSP_addq(void);
-static void DSP_addqmod(void);
+static void DSP_addqmod(void);
static void DSP_addqt(void);
static void DSP_and(void);
static void DSP_bclr(void);
static void DSP_load_r14_r(void);
static void DSP_load_r15_i(void);
static void DSP_load_r15_r(void);
-static void DSP_mirror(void);
+static void DSP_mirror(void);
static void DSP_mmult(void);
static void DSP_move(void);
static void DSP_movefa(void);
static void DSP_resmac(void);
static void DSP_ror(void);
static void DSP_rorq(void);
-static void DSP_sat16s(void);
-static void DSP_sat32s(void);
+static void DSP_sat16s(void);
+static void DSP_sat32s(void);
static void DSP_sh(void);
static void DSP_sha(void);
static void DSP_sharq(void);
static void DSP_sub(void);
static void DSP_subc(void);
static void DSP_subq(void);
-static void DSP_subqmod(void);
+static void DSP_subqmod(void);
static void DSP_subqt(void);
static void DSP_xor(void);
{ true, true}, { true, true}, {false, false}, {false, true}
};
+bool isLoadStore[65] =
+{
+ false, false, false, false, false, false, false, false,
+ false, false, false, false, false, false, false, false,
+
+ false, false, false, false, false, false, false, false,
+ false, false, false, false, false, false, false, false,
+
+ false, false, false, false, false, false, false, true,
+ true, true, false, true, true, true, true, true,
+
+ false, true, true, false, false, false, false, false,
+ false, false, true, true, true, true, false, false, false
+};
+
void FlushDSPPipeline(void)
{
plPtrFetch = 3, plPtrRead = 2, plPtrExec = 1, plPtrWrite = 0;
pipeline[i].opcode = PIPELINE_STALL;
for(int i=0; i<32; i++)
- scoreboard[i] = false;
+ scoreboard[i] = 0;
}
//
// New pipelined DSP execution core
//
-/*void DSPExecP(int32 cycles)
+/*void DSPExecP(int32_t cycles)
{
// bool inhibitFetch = false;
pipeline[plPtrFetch].operand1 = (pipeline[plPtrFetch].instruction >> 5) & 0x1F;
pipeline[plPtrFetch].operand2 = pipeline[plPtrFetch].instruction & 0x1F;
if (pipeline[plPtrFetch].opcode == 38)
- pipeline[plPtrFetch].result = (uint32)DSPReadWord(dsp_pc + 2, DSP)
- | ((uint32)DSPReadWord(dsp_pc + 4, DSP) << 16);
+ pipeline[plPtrFetch].result = (uint32_t)DSPReadWord(dsp_pc + 2, DSP)
+ | ((uint32_t)DSPReadWord(dsp_pc + 4, DSP) << 16);
// }
// else
// inhibitFetch = false;
If it were done properly, the STORE write back would occur *after* (well, technically,
during) the execution of the the JUMP that follows it.
-!!! FIX !!!
+!!! FIX !!! [DONE]
F1B08A: JR z, F1B082 [NCZ:001] Branched!
F1B08A: NOP [NCZ:001]
F1B1FC: MOVEI #$00F1A100, R01 [NCZ:001, R01=00F1A100] -> [NCZ:001, R01=00F1A100]
*/
-uint32 pcQueue1[0x400];
-uint32 pcQPtr1 = 0;
-
+uint32_t pcQueue1[0x400];
+uint32_t pcQPtr1 = 0;
+static uint32_t prevR1;
//Let's try a 3 stage pipeline....
//Looks like 3 stage is correct, otherwise bad things happen...
-void DSPExecP2(int32 cycles)
+void DSPExecP2(int32_t cycles)
{
dsp_releaseTimeSlice_flag = 0;
dsp_in_exec++;
while (cycles > 0 && DSP_RUNNING)
{
-if (dsp_pc == 0xF1B0A0)
+/*extern uint32_t totalFrames;
+//F1B2F6: LOAD (R14+$04), R24 [NCZ:001, R14+$04=00F20018, R24=FFFFFFFF] -> Jaguar: Unknown word read at 00F20018 by DSP (M68K PC=00E32E)
+//-> 43 + 1 + 24 -> $2B + $01 + $18 -> 101011 00001 11000 -> 1010 1100 0011 1000 -> AC38
+//C470 -> 1100 0100 0111 0000 -> 110001 00011 10000 -> 49, 3, 16 -> STORE R16, (R14+$0C)
+//F1B140:
+if (totalFrames >= 377 && GET16(dsp_ram_8, 0x0002F6) == 0xAC38 && dsp_pc == 0xF1B140)
+{
doDSPDis = true;
+ WriteLog("Starting disassembly at frame #%u...\n", totalFrames);
+}
+if (dsp_pc == 0xF1B092)
+ doDSPDis = false;//*/
+/*if (totalFrames >= 373 && GET16(dsp_ram_8, 0x0002F6) == 0xAC38)
+ doDSPDis = true;//*/
+/*if (totalFrames >= 373 && dsp_pc == 0xF1B0A0)
+ doDSPDis = true;//*/
+/*if (dsp_pc == 0xF1B0A0)
+ doDSPDis = true;//*/
+/*if (dsp_pc == 0xF1B0D2) && dsp_reg[1] == 0x2140C)
+ doDSPDis = true;//*/
+//Two parter... (not sure how to write this)
+//if (dsp_pc == 0xF1B0D2)
+// prevR1 = dsp_reg[1];
+
+//F1B0D2: ADDQT #8, R01 [NCZ:000, R01=0002140C] -> [NCZ:000, R01=00021414]
+//F1B0D2: ADDQT #8, R01 [NCZ:000, R01=0002140C] -> [NCZ:000, R01=00021414]
+
pcQueue1[pcQPtr1++] = dsp_pc;
pcQPtr1 &= 0x3FF;
+#ifdef DSP_DEBUG_PL2
if ((dsp_pc < 0xF1B000 || dsp_pc > 0xF1CFFF) && !doDSPDis)
{
WriteLog("DSP: PC has stepped out of bounds...\n\nBacktrace:\n\n");
}
WriteLog("\n");
}//*/
+#endif
+
if (IMASKCleared) // If IMASK was cleared,
{
#ifdef DSP_DEBUG_IRQ
pipeline[plPtrRead].operand1 = (pipeline[plPtrRead].instruction >> 5) & 0x1F;
pipeline[plPtrRead].operand2 = pipeline[plPtrRead].instruction & 0x1F;
if (pipeline[plPtrRead].opcode == 38)
- pipeline[plPtrRead].result = (uint32)DSPReadWord(dsp_pc + 2, DSP)
- | ((uint32)DSPReadWord(dsp_pc + 4, DSP) << 16);
+ pipeline[plPtrRead].result = (uint32_t)DSPReadWord(dsp_pc + 2, DSP)
+ | ((uint32_t)DSPReadWord(dsp_pc + 4, DSP) << 16);
#ifdef DSP_DEBUG_PL2
if (doDSPDis)
{
//Small problem--when say LOAD or STORE (R14/5+$nn) is executed AFTER an instruction that
//modifies R14/5, we don't check the scoreboard for R14/5 (and we need to!)... !!! FIX !!!
//Ugly, but [DONE]
+//Another problem: Any sequential combination of LOAD and STORE operations will cause the
+//pipeline to stall, and we don't take care of that here. !!! FIX !!!
if ((scoreboard[pipeline[plPtrRead].operand1] && readAffected[pipeline[plPtrRead].opcode][0])
|| (scoreboard[pipeline[plPtrRead].operand2] && readAffected[pipeline[plPtrRead].opcode][1])
|| ((pipeline[plPtrRead].opcode == 43 || pipeline[plPtrRead].opcode == 58) && scoreboard[14])
- || ((pipeline[plPtrRead].opcode == 44 || pipeline[plPtrRead].opcode == 59) && scoreboard[15]))
+ || ((pipeline[plPtrRead].opcode == 44 || pipeline[plPtrRead].opcode == 59) && scoreboard[15])
+//Not sure that this is the best way to fix the LOAD/STORE problem... But it seems to
+//work--somewhat...
+ || (isLoadStore[pipeline[plPtrRead].opcode] && isLoadStore[pipeline[plPtrExec].opcode]))
// We have a hit in the scoreboard, so we have to stall the pipeline...
#ifdef DSP_DEBUG_PL2
{
// Shouldn't we be more selective with the register scoreboarding?
// Yes, we should. !!! FIX !!! Kinda [DONE]
+#ifndef NEW_SCOREBOARD
scoreboard[pipeline[plPtrRead].operand2] = affectsScoreboard[pipeline[plPtrRead].opcode];
+#else
+//Hopefully this will fix the dual MOVEQ # problem...
+ scoreboard[pipeline[plPtrRead].operand2] += (affectsScoreboard[pipeline[plPtrRead].opcode] ? 1 : 0);
+#endif
//Advance PC here??? Yes.
dsp_pc += (pipeline[plPtrRead].opcode == 38 ? 6 : 2);
if (pipeline[plPtrExec].opcode != PIPELINE_STALL)
{
#ifdef DSP_DEBUG_PL2
+if (doDSPDis)
+ WriteLog("\t[inst=%02u][R28=%08X, alt R28=%08X, REGPAGE=%s]\n", pipeline[plPtrExec].opcode, dsp_reg[28], dsp_alternate_reg[28], (dsp_flags & REGPAGE ? "set" : "not set"));
+
if (doDSPDis)
{
WriteLog("DSPExecP: About to execute opcode %s...\n", dsp_opcode_str[pipeline[plPtrExec].opcode]);
//Let's not, until we do the stalling correctly...
//But, we gotta while we're doing the comparison core...!
//Or do we? cycles--;
+//Really, the whole thing is wrong. When the pipeline is correctly stuffed, most instructions
+//will execute in one clock cycle (others, like DIV, will likely not). So, the challenge is
+//to model this clock cycle behavior correctly...
+//Also, the pipeline stalls too much--mostly because the transparent writebacks at stage 3
+//don't affect the reads at stage 1...
#ifdef DSP_DEBUG_STALL
if (doDSPDis)
WriteLog("[STALL... DSP_PC = %08X]\n", dsp_pc);
}
}
+#ifndef NEW_SCOREBOARD
if (affectsScoreboard[pipeline[plPtrWrite].opcode])
scoreboard[pipeline[plPtrWrite].operand2] = false;
+#else
+//Yup, sequential MOVEQ # problem fixing (I hope!)...
+ if (affectsScoreboard[pipeline[plPtrWrite].opcode])
+ if (scoreboard[pipeline[plPtrWrite].operand2])
+ scoreboard[pipeline[plPtrWrite].operand2]--;
+#endif
}
// Push instructions through the pipeline...
/*
//#define DSP_DEBUG_PL3
//Let's try a 2 stage pipeline....
-void DSPExecP3(int32 cycles)
+void DSPExecP3(int32_t cycles)
{
dsp_releaseTimeSlice_flag = 0;
dsp_in_exec++;
pipeline[plPtrRead].operand1 = (pipeline[plPtrRead].instruction >> 5) & 0x1F;
pipeline[plPtrRead].operand2 = pipeline[plPtrRead].instruction & 0x1F;
if (pipeline[plPtrRead].opcode == 38)
- pipeline[plPtrRead].result = (uint32)DSPReadWord(dsp_pc + 2, DSP)
- | ((uint32)DSPReadWord(dsp_pc + 4, DSP) << 16);
+ pipeline[plPtrRead].result = (uint32_t)DSPReadWord(dsp_pc + 2, DSP)
+ | ((uint32_t)DSPReadWord(dsp_pc + 4, DSP) << 16);
#ifdef DSP_DEBUG_PL3
WriteLog("DSPExecP: Fetching instruction (%04X) from DSP_PC = %08X...\n", pipeline[plPtrRead].instruction, dsp_pc);
WriteLog("DSPExecP: Pipeline status (after stage 1a)...\n");
if (doDSPDis)
WriteLog("%06X: ABS R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", DSP_PPC, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
#endif
- uint32 _Rn = PRN;
-
+ uint32_t _Rn = PRN;
+
if (_Rn == 0x80000000)
dsp_flag_n = 1;
else
if (doDSPDis)
WriteLog("%06X: ADD R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
#endif
- UINT32 res = PRN + PRM;
+ uint32_t res = PRN + PRM;
SET_ZNC_ADD(PRN, PRM, res);
PRES = res;
#ifdef DSP_DIS_ADD
if (doDSPDis)
WriteLog("%06X: ADDC R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
#endif
- UINT32 res = PRN + PRM + dsp_flag_c;
- UINT32 carry = dsp_flag_c;
+ uint32_t res = PRN + PRM + dsp_flag_c;
+ uint32_t carry = dsp_flag_c;
// SET_ZNC_ADD(PRN, PRM, res); //???BUG??? Yes!
SET_ZNC_ADD(PRN + carry, PRM, res);
// SET_ZNC_ADD(PRN, PRM + carry, res);
if (doDSPDis)
WriteLog("%06X: ADDQ #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", DSP_PPC, dsp_convert_zero[PIMM1], PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
#endif
- UINT32 r1 = dsp_convert_zero[PIMM1];
- UINT32 res = PRN + r1;
+ uint32_t r1 = dsp_convert_zero[PIMM1];
+ uint32_t res = PRN + r1;
CLR_ZNC; SET_ZNC_ADD(PRN, r1, res);
PRES = res;
#ifdef DSP_DIS_ADDQ
if (doDSPDis)
WriteLog("%06X: ADDQMOD #%u, R%02u [NCZ:%u%u%u, R%02u=%08X, DSP_MOD=%08X] -> ", DSP_PPC, dsp_convert_zero[PIMM1], PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN, dsp_modulo);
#endif
- UINT32 r1 = dsp_convert_zero[PIMM1];
- UINT32 r2 = PRN;
- UINT32 res = r2 + r1;
+ uint32_t r1 = dsp_convert_zero[PIMM1];
+ uint32_t r2 = PRN;
+ uint32_t res = r2 + r1;
res = (res & (~dsp_modulo)) | (r2 & dsp_modulo);
PRES = res;
SET_ZNC_ADD(r2, r1, res);
NO_WRITEBACK;
#ifdef DSP_DIS_BTST
if (doDSPDis)
- WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
+ WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
#endif
}
if (doDSPDis)
WriteLog("%06X: CMP R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
#endif
- UINT32 res = PRN - PRM;
+ uint32_t res = PRN - PRM;
SET_ZNC_SUB(PRN, PRM, res);
NO_WRITEBACK;
#ifdef DSP_DIS_CMP
static void DSP_cmpq(void)
{
- static int32 sqtable[32] =
+ static int32_t sqtable[32] =
{ 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,-16,-15,-14,-13,-12,-11,-10,-9,-8,-7,-6,-5,-4,-3,-2,-1 };
#ifdef DSP_DIS_CMPQ
if (doDSPDis)
WriteLog("%06X: CMPQ #%d, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", DSP_PPC, sqtable[PIMM1], PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
#endif
- UINT32 r1 = sqtable[PIMM1 & 0x1F]; // I like this better -> (INT8)(jaguar.op >> 2) >> 3;
- UINT32 res = PRN - r1;
+ uint32_t r1 = sqtable[PIMM1 & 0x1F]; // I like this better -> (INT8)(jaguar.op >> 2) >> 3;
+ uint32_t res = PRN - r1;
SET_ZNC_SUB(PRN, r1, res);
NO_WRITEBACK;
#ifdef DSP_DIS_CMPQ
static void DSP_div(void)
{
- uint32 _Rm = PRM, _Rn = PRN;
+ uint32_t _Rm = PRM, _Rn = PRN;
if (_Rm)
{
if (dsp_div_control & 1)
{
- dsp_remain = (((uint64)_Rn) << 16) % _Rm;
+ dsp_remain = (((uint64_t)_Rn) << 16) % _Rm;
if (dsp_remain & 0x80000000)
dsp_remain -= _Rm;
- PRES = (((uint64)_Rn) << 16) / _Rm;
+ PRES = (((uint64_t)_Rn) << 16) / _Rm;
}
else
{
if (doDSPDis)
WriteLog("%06X: IMACN R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
#endif
- int32 res = (int16)PRM * (int16)PRN;
- dsp_acc += (int64)res;
+ int32_t res = (int16_t)PRM * (int16_t)PRN;
+ dsp_acc += (int64_t)res;
//Should we AND the result to fit into 40 bits here???
NO_WRITEBACK;
#ifdef DSP_DIS_IMACN
if (doDSPDis)
- WriteLog("[NCZ:%u%u%u, DSP_ACC=%02X%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, (uint8)(dsp_acc >> 32), (uint32)(dsp_acc & 0xFFFFFFFF));
+ WriteLog("[NCZ:%u%u%u, DSP_ACC=%02X%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, (uint8_t)(dsp_acc >> 32), (uint32_t)(dsp_acc & 0xFFFFFFFF));
#endif
-}
+}
static void DSP_imult(void)
{
if (doDSPDis)
WriteLog("%06X: IMULT R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
#endif
- PRES = (int16)PRN * (int16)PRM;
+ PRES = (int16_t)PRN * (int16_t)PRM;
SET_ZN(PRES);
#ifdef DSP_DIS_IMULT
if (doDSPDis)
WriteLog("%06X: IMULTN R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
#endif
// This is OK, since this multiply won't overflow 32 bits...
- int32 res = (int32)((int16)PRN * (int16)PRM);
- dsp_acc = (int64)res;
+ int32_t res = (int32_t)((int16_t)PRN * (int16_t)PRM);
+ dsp_acc = (int64_t)res;
SET_ZN(res);
NO_WRITEBACK;
#ifdef DSP_DIS_IMULTN
if (doDSPDis)
- WriteLog("[NCZ:%u%u%u, DSP_ACC=%02X%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, (uint8)(dsp_acc >> 32), (uint32)(dsp_acc & 0xFFFFFFFF));
+ WriteLog("[NCZ:%u%u%u, DSP_ACC=%02X%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, (uint8_t)(dsp_acc >> 32), (uint32_t)(dsp_acc & 0xFFFFFFFF));
#endif
}
static void DSP_jr(void)
{
#ifdef DSP_DIS_JR
-char * condition[32] =
+const char * condition[32] =
{ "T", "nz", "z", "???", "nc", "nc nz", "nc z", "???", "c", "c nz",
"c z", "???", "???", "???", "???", "???", "???", "???", "???",
"???", "nn", "nn nz", "nn z", "???", "n", "n nz", "n z", "???",
"???", "???", "???", "F" };
if (doDSPDis)
//How come this is always off by 2???
- WriteLog("%06X: JR %s, %06X [NCZ:%u%u%u] ", DSP_PPC, condition[PIMM2], DSP_PPC+((PIMM1 & 0x10 ? 0xFFFFFFF0 | PIMM1 : PIMM1) * 2), dsp_flag_n, dsp_flag_c, dsp_flag_z);
+ WriteLog("%06X: JR %s, %06X [NCZ:%u%u%u] ", DSP_PPC, condition[PIMM2], DSP_PPC+((PIMM1 & 0x10 ? 0xFFFFFFF0 | PIMM1 : PIMM1) * 2)+2, dsp_flag_n, dsp_flag_c, dsp_flag_z);
#endif
// KLUDGE: Used by BRANCH_CONDITION macro
- uint32 jaguar_flags = (dsp_flag_n << 2) | (dsp_flag_c << 1) | dsp_flag_z;
+ uint32_t jaguar_flags = (dsp_flag_n << 2) | (dsp_flag_c << 1) | dsp_flag_z;
if (BRANCH_CONDITION(PIMM2))
{
if (doDSPDis)
WriteLog("Branched!\n");
#endif
- int32 offset = (PIMM1 & 0x10 ? 0xFFFFFFF0 | PIMM1 : PIMM1); // Sign extend PIMM1
+ int32_t offset = (PIMM1 & 0x10 ? 0xFFFFFFF0 | PIMM1 : PIMM1); // Sign extend PIMM1
//Account for pipeline effects...
- uint32 newPC = dsp_pc + (offset * 2) - (pipeline[plPtrRead].opcode == 38 ? 6 : (pipeline[plPtrRead].opcode == PIPELINE_STALL ? 0 : 2));
+ uint32_t newPC = dsp_pc + (offset * 2) - (pipeline[plPtrRead].opcode == 38 ? 6 : (pipeline[plPtrRead].opcode == PIPELINE_STALL ? 0 : 2));
//WriteLog(" --> Old PC: %08X, new PC: %08X\n", dsp_pc, newPC);
// Now that we've branched, we have to make sure that the following instruction
// is executed atomically with this one and then flush the pipeline before setting
// the new PC.
-
+
// Step 1: Handle writebacks at stage 3 of pipeline
/* if (pipeline[plPtrWrite].opcode != PIPELINE_STALL)
{
}
}
+#ifndef NEW_SCOREBOARD
if (affectsScoreboard[pipeline[plPtrWrite].opcode])
scoreboard[pipeline[plPtrWrite].operand2] = false;
+#else
+//Yup, sequential MOVEQ # problem fixing (I hope!)...
+ if (affectsScoreboard[pipeline[plPtrWrite].opcode])
+ if (scoreboard[pipeline[plPtrWrite].operand2])
+ scoreboard[pipeline[plPtrWrite].operand2]--;
+#endif
}
// Step 2: Push instruction through pipeline & execute following instruction
// remove this crap.
if (pipeline[plPtrExec].opcode == PIPELINE_STALL)
{
- uint16 instruction = DSPReadWord(dsp_pc, DSP);
+ uint16_t instruction = DSPReadWord(dsp_pc, DSP);
pipeline[plPtrExec].opcode = instruction >> 10;
pipeline[plPtrExec].operand1 = (instruction >> 5) & 0x1F;
pipeline[plPtrExec].operand2 = instruction & 0x1F;
pipeline[plPtrExec].reg2 = dsp_reg[pipeline[plPtrExec].operand2];
pipeline[plPtrExec].writebackRegister = pipeline[plPtrExec].operand2; // Set it to RN
}//*/
+ dsp_pc += 2; // For DSP_DIS_* accuracy
DSPOpcode[pipeline[plPtrExec].opcode]();
dsp_opcode_use[pipeline[plPtrExec].opcode]++;
pipeline[plPtrWrite] = pipeline[plPtrExec];
static void DSP_jump(void)
{
#ifdef DSP_DIS_JUMP
-char * condition[32] =
+const char * condition[32] =
{ "T", "nz", "z", "???", "nc", "nc nz", "nc z", "???", "c", "c nz",
"c z", "???", "???", "???", "???", "???", "???", "???", "???",
"???", "nn", "nn nz", "nn z", "???", "n", "n nz", "n z", "???",
WriteLog("%06X: JUMP %s, (R%02u) [NCZ:%u%u%u, R%02u=%08X] ", DSP_PPC, condition[PIMM2], PIMM1, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM);
#endif
// KLUDGE: Used by BRANCH_CONDITION macro
- uint32 jaguar_flags = (dsp_flag_n << 2) | (dsp_flag_c << 1) | dsp_flag_z;
+ uint32_t jaguar_flags = (dsp_flag_n << 2) | (dsp_flag_c << 1) | dsp_flag_z;
if (BRANCH_CONDITION(PIMM2))
{
if (doDSPDis)
WriteLog("Branched!\n");
#endif
- uint32 PCSave = PRM;
+ uint32_t PCSave = PRM;
// Now that we've branched, we have to make sure that the following instruction
// is executed atomically with this one and then flush the pipeline before setting
// the new PC.
-
+
// Step 1: Handle writebacks at stage 3 of pipeline
/* if (pipeline[plPtrWrite].opcode != PIPELINE_STALL)
{
}
}
+#ifndef NEW_SCOREBOARD
if (affectsScoreboard[pipeline[plPtrWrite].opcode])
scoreboard[pipeline[plPtrWrite].operand2] = false;
+#else
+//Yup, sequential MOVEQ # problem fixing (I hope!)...
+ if (affectsScoreboard[pipeline[plPtrWrite].opcode])
+ if (scoreboard[pipeline[plPtrWrite].operand2])
+ scoreboard[pipeline[plPtrWrite].operand2]--;
+#endif
}
// Step 2: Push instruction through pipeline & execute following instruction
// remove this crap.
if (pipeline[plPtrExec].opcode == PIPELINE_STALL)
{
- uint16 instruction = DSPReadWord(dsp_pc, DSP);
+ uint16_t instruction = DSPReadWord(dsp_pc, DSP);
pipeline[plPtrExec].opcode = instruction >> 10;
pipeline[plPtrExec].operand1 = (instruction >> 5) & 0x1F;
pipeline[plPtrExec].operand2 = instruction & 0x1F;
pipeline[plPtrExec].reg2 = dsp_reg[pipeline[plPtrExec].operand2];
pipeline[plPtrExec].writebackRegister = pipeline[plPtrExec].operand2; // Set it to RN
}//*/
+ dsp_pc += 2; // For DSP_DIS_* accuracy
DSPOpcode[pipeline[plPtrExec].opcode]();
dsp_opcode_use[pipeline[plPtrExec].opcode]++;
pipeline[plPtrWrite] = pipeline[plPtrExec];
if (doDSPDis)
WriteLog("%06X: LOAD (R%02u), R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
#endif
+#ifdef DSP_CORRECT_ALIGNMENT
+ PRES = DSPReadLong(PRM & 0xFFFFFFFC, DSP);
+#else
PRES = DSPReadLong(PRM, DSP);
+#endif
#ifdef DSP_DIS_LOAD
if (doDSPDis)
WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
if (doDSPDis)
WriteLog("%06X: LOADW (R%02u), R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
#endif
+#ifdef DSP_CORRECT_ALIGNMENT
+ if (PRM >= DSP_WORK_RAM_BASE && PRM <= (DSP_WORK_RAM_BASE + 0x1FFF))
+ PRES = DSPReadLong(PRM & 0xFFFFFFFE, DSP) & 0xFFFF;
+ else
+ PRES = JaguarReadWord(PRM & 0xFFFFFFFE, DSP);
+#else
if (PRM >= DSP_WORK_RAM_BASE && PRM <= (DSP_WORK_RAM_BASE + 0x1FFF))
PRES = DSPReadLong(PRM, DSP) & 0xFFFF;
else
PRES = JaguarReadWord(PRM, DSP);
+#endif
#ifdef DSP_DIS_LOADW
if (doDSPDis)
WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
if (doDSPDis)
WriteLog("%06X: LOAD (R14+$%02X), R%02u [NCZ:%u%u%u, R14+$%02X=%08X, R%02u=%08X] -> ", DSP_PPC, dsp_convert_zero[PIMM1] << 2, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, dsp_convert_zero[PIMM1] << 2, dsp_reg[14]+(dsp_convert_zero[PIMM1] << 2), PIMM2, PRN);
#endif
+#ifdef DSP_CORRECT_ALIGNMENT
+ PRES = DSPReadLong((dsp_reg[14] & 0xFFFFFFFC) + (dsp_convert_zero[PIMM1] << 2), DSP);
+#else
PRES = DSPReadLong(dsp_reg[14] + (dsp_convert_zero[PIMM1] << 2), DSP);
+#endif
#ifdef DSP_DIS_LOAD14I
if (doDSPDis)
WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
if (doDSPDis)
WriteLog("%06X: LOAD (R14+R%02u), R%02u [NCZ:%u%u%u, R14+R%02u=%08X, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM+dsp_reg[14], PIMM2, PRES);
#endif
+#ifdef DSP_CORRECT_ALIGNMENT
+ PRES = DSPReadLong((dsp_reg[14] + PRM) & 0xFFFFFFFC, DSP);
+#else
PRES = DSPReadLong(dsp_reg[14] + PRM, DSP);
+#endif
#ifdef DSP_DIS_LOAD14R
if (doDSPDis)
WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
if (doDSPDis)
WriteLog("%06X: LOAD (R15+$%02X), R%02u [NCZ:%u%u%u, R15+$%02X=%08X, R%02u=%08X] -> ", DSP_PPC, dsp_convert_zero[PIMM1] << 2, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, dsp_convert_zero[PIMM1] << 2, dsp_reg[15]+(dsp_convert_zero[PIMM1] << 2), PIMM2, PRN);
#endif
+#ifdef DSP_CORRECT_ALIGNMENT
+ PRES = DSPReadLong((dsp_reg[15] &0xFFFFFFFC) + (dsp_convert_zero[PIMM1] << 2), DSP);
+#else
PRES = DSPReadLong(dsp_reg[15] + (dsp_convert_zero[PIMM1] << 2), DSP);
+#endif
#ifdef DSP_DIS_LOAD15I
if (doDSPDis)
WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
if (doDSPDis)
WriteLog("%06X: LOAD (R15+R%02u), R%02u [NCZ:%u%u%u, R15+R%02u=%08X, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM+dsp_reg[15], PIMM2, PRN);
#endif
+#ifdef DSP_CORRECT_ALIGNMENT
+ PRES = DSPReadLong((dsp_reg[15] + PRM) & 0xFFFFFFFC, DSP);
+#else
PRES = DSPReadLong(dsp_reg[15] + PRM, DSP);
+#endif
#ifdef DSP_DIS_LOAD15R
if (doDSPDis)
WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
#endif
}
-static void DSP_mirror(void)
+static void DSP_mirror(void)
{
- UINT32 r1 = PRN;
+ uint32_t r1 = PRN;
PRES = (mirror_table[r1 & 0xFFFF] << 16) | mirror_table[r1 >> 16];
SET_ZN(PRES);
}
static void DSP_mmult(void)
{
int count = dsp_matrix_control&0x0f;
- uint32 addr = dsp_pointer_to_matrix; // in the gpu ram
- int64 accum = 0;
- uint32 res;
+ uint32_t addr = dsp_pointer_to_matrix; // in the dsp ram
+ int64_t accum = 0;
+ uint32_t res;
if (!(dsp_matrix_control & 0x10))
{
for (int i = 0; i < count; i++)
- {
- int16 a;
+ {
+ int16_t a;
if (i&0x01)
- a=(int16)((dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]>>16)&0xffff);
+ a=(int16_t)((dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]>>16)&0xffff);
else
- a=(int16)(dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]&0xffff);
- int16 b=((int16)DSPReadWord(addr + 2, DSP));
+ a=(int16_t)(dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]&0xffff);
+ int16_t b=((int16_t)DSPReadWord(addr + 2, DSP));
accum += a*b;
addr += 4;
}
{
for (int i = 0; i < count; i++)
{
- int16 a;
+ int16_t a;
if (i&0x01)
- a=(int16)((dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]>>16)&0xffff);
+ a=(int16_t)((dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]>>16)&0xffff);
else
- a=(int16)(dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]&0xffff);
- int16 b=((int16)DSPReadWord(addr + 2, DSP));
+ a=(int16_t)(dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]&0xffff);
+ int16_t b=((int16_t)DSPReadWord(addr + 2, DSP));
accum += a*b;
addr += 4 * count;
}
}
- PRES = res = (int32)accum;
+ PRES = res = (int32_t)accum;
// carry flag to do
//NOTE: The flags are set based upon the last add/multiply done...
SET_ZN(PRES);
WriteLog("%06X: MOVEI #$%08X, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", DSP_PPC, PRES, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
#endif
// // This instruction is followed by 32-bit value in LSW / MSW format...
-// PRES = (uint32)DSPReadWord(dsp_pc, DSP) | ((uint32)DSPReadWord(dsp_pc + 2, DSP) << 16);
+// PRES = (uint32_t)DSPReadWord(dsp_pc, DSP) | ((uint32_t)DSPReadWord(dsp_pc + 2, DSP) << 16);
// dsp_pc += 4;
#ifdef DSP_DIS_MOVEI
if (doDSPDis)
static void DSP_movepc(void)
{
+#ifdef DSP_DIS_MOVEPC
+ if (doDSPDis)
+ WriteLog("%06X: MOVE PC, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", DSP_PPC, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
+#endif
//Need to fix this to take into account pipelining effects... !!! FIX !!! [DONE]
// PRES = dsp_pc - 2;
//Account for pipeline effects...
- PRES = dsp_pc - (pipeline[plPtrRead].opcode == 38 ? 6 : (pipeline[plPtrRead].opcode == PIPELINE_STALL ? 0 : 2));
+ PRES = dsp_pc - 2 - (pipeline[plPtrRead].opcode == 38 ? 6 : (pipeline[plPtrRead].opcode == PIPELINE_STALL ? 0 : 2));
+#ifdef DSP_DIS_MOVEPC
+ if (doDSPDis)
+ WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
+#endif
}
static void DSP_moveq(void)
static void DSP_mtoi(void)
{
- PRES = (((INT32)PRM >> 8) & 0xFF800000) | (PRM & 0x007FFFFF);
+ PRES = (((int32_t)PRM >> 8) & 0xFF800000) | (PRM & 0x007FFFFF);
SET_ZN(PRES);
}
if (doDSPDis)
WriteLog("%06X: MULT R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
#endif
- PRES = (uint16)PRM * (uint16)PRN;
+ PRES = (uint16_t)PRM * (uint16_t)PRN;
SET_ZN(PRES);
#ifdef DSP_DIS_MULT
if (doDSPDis)
if (doDSPDis)
WriteLog("%06X: NEG R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", DSP_PPC, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
#endif
- UINT32 res = -PRN;
+ uint32_t res = -PRN;
SET_ZNC_SUB(0, PRN, res);
PRES = res;
#ifdef DSP_DIS_NEG
static void DSP_normi(void)
{
- uint32 _Rm = PRM;
- uint32 res = 0;
+ uint32_t _Rm = PRM;
+ uint32_t res = 0;
if (_Rm)
{
{
#ifdef DSP_DIS_NOT
if (doDSPDis)
- WriteLog("%06X: NOT R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
+ WriteLog("%06X: NOT R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", DSP_PPC, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
#endif
PRES = ~PRN;
SET_ZN(PRES);
#ifdef DSP_DIS_NOT
if (doDSPDis)
- WriteLog("[NCZ:%u%u%u, R%02u=%08X, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRES);
+ WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRES);
#endif
}
{
#ifdef DSP_DIS_RESMAC
if (doDSPDis)
- WriteLog("%06X: RESMAC R%02u [NCZ:%u%u%u, R%02u=%08X, DSP_ACC=%02X%08X] -> ", DSP_PPC, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN, (uint8)(dsp_acc >> 32), (uint32)(dsp_acc & 0xFFFFFFFF));
+ WriteLog("%06X: RESMAC R%02u [NCZ:%u%u%u, R%02u=%08X, DSP_ACC=%02X%08X] -> ", DSP_PPC, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN, (uint8_t)(dsp_acc >> 32), (uint32_t)(dsp_acc & 0xFFFFFFFF));
#endif
- PRES = (uint32)dsp_acc;
+ PRES = (uint32_t)dsp_acc;
#ifdef DSP_DIS_RESMAC
if (doDSPDis)
WriteLog("[NCZ:%u%u%u, R%02u=%08X]\n", dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
if (doDSPDis)
WriteLog("%06X: ROR R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
#endif
- UINT32 r1 = PRM & 0x1F;
- UINT32 res = (PRN >> r1) | (PRN << (32 - r1));
+ uint32_t r1 = PRM & 0x1F;
+ uint32_t res = (PRN >> r1) | (PRN << (32 - r1));
SET_ZN(res); dsp_flag_c = (PRN >> 31) & 1;
PRES = res;
#ifdef DSP_DIS_ROR
if (doDSPDis)
WriteLog("%06X: RORQ #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", DSP_PPC, dsp_convert_zero[PIMM1], PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
#endif
- UINT32 r1 = dsp_convert_zero[PIMM1 & 0x1F];
- UINT32 r2 = PRN;
- UINT32 res = (r2 >> r1) | (r2 << (32 - r1));
+ uint32_t r1 = dsp_convert_zero[PIMM1 & 0x1F];
+ uint32_t r2 = PRN;
+ uint32_t res = (r2 >> r1) | (r2 << (32 - r1));
PRES = res;
SET_ZN(res); dsp_flag_c = (r2 >> 31) & 0x01;
#ifdef DSP_DIS_RORQ
#endif
}
-static void DSP_sat16s(void)
+static void DSP_sat16s(void)
{
- INT32 r2 = PRN;
- UINT32 res = (r2 < -32768) ? -32768 : (r2 > 32767) ? 32767 : r2;
+ int32_t r2 = PRN;
+ uint32_t res = (r2 < -32768) ? -32768 : (r2 > 32767) ? 32767 : r2;
PRES = res;
SET_ZN(res);
}
-static void DSP_sat32s(void)
+static void DSP_sat32s(void)
{
- INT32 r2 = (UINT32)PRN;
- INT32 temp = dsp_acc >> 32;
- UINT32 res = (temp < -1) ? (INT32)0x80000000 : (temp > 0) ? (INT32)0x7FFFFFFF : r2;
+ int32_t r2 = (uint32_t)PRN;
+ int32_t temp = dsp_acc >> 32;
+ uint32_t res = (temp < -1) ? (int32_t)0x80000000 : (temp > 0) ? (int32_t)0x7FFFFFFF : r2;
PRES = res;
SET_ZN(res);
}
static void DSP_sh(void)
{
- int32 sRm = (int32)PRM;
- uint32 _Rn = PRN;
+ int32_t sRm = (int32_t)PRM;
+ uint32_t _Rn = PRN;
if (sRm < 0)
{
- uint32 shift = -sRm;
+ uint32_t shift = -sRm;
if (shift >= 32)
shift = 32;
}
else
{
- uint32 shift = sRm;
+ uint32_t shift = sRm;
if (shift >= 32)
shift = 32;
static void DSP_sha(void)
{
- int32 sRm = (int32)PRM;
- uint32 _Rn = PRN;
+ int32_t sRm = (int32_t)PRM;
+ uint32_t _Rn = PRN;
if (sRm < 0)
{
- uint32 shift = -sRm;
+ uint32_t shift = -sRm;
if (shift >= 32)
shift = 32;
}
else
{
- uint32 shift = sRm;
+ uint32_t shift = sRm;
if (shift >= 32)
shift = 32;
while (shift)
{
- _Rn = ((int32)_Rn) >> 1;
+ _Rn = ((int32_t)_Rn) >> 1;
shift--;
}
}
if (doDSPDis)
WriteLog("%06X: SHARQ #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", DSP_PPC, dsp_convert_zero[PIMM1], PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
#endif
- UINT32 res = (INT32)PRN >> dsp_convert_zero[PIMM1];
+ uint32_t res = (int32_t)PRN >> dsp_convert_zero[PIMM1];
SET_ZN(res); dsp_flag_c = PRN & 0x01;
PRES = res;
#ifdef DSP_DIS_SHARQ
if (doDSPDis)
WriteLog("%06X: SHLQ #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", DSP_PPC, 32 - PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
#endif
- INT32 r1 = 32 - PIMM1;
- UINT32 res = PRN << r1;
+ int32_t r1 = 32 - PIMM1;
+ uint32_t res = PRN << r1;
SET_ZN(res); dsp_flag_c = (PRN >> 31) & 1;
PRES = res;
#ifdef DSP_DIS_SHLQ
if (doDSPDis)
WriteLog("%06X: SHRQ #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", DSP_PPC, dsp_convert_zero[PIMM1], PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
#endif
- INT32 r1 = dsp_convert_zero[PIMM1];
- UINT32 res = PRN >> r1;
+ int32_t r1 = dsp_convert_zero[PIMM1];
+ uint32_t res = PRN >> r1;
SET_ZN(res); dsp_flag_c = PRN & 1;
PRES = res;
#ifdef DSP_DIS_SHRQ
#endif
// DSPWriteLong(PRM, PRN, DSP);
// NO_WRITEBACK;
+#ifdef DSP_CORRECT_ALIGNMENT_STORE
+ pipeline[plPtrExec].address = PRM & 0xFFFFFFFC;
+#else
pipeline[plPtrExec].address = PRM;
+#endif
pipeline[plPtrExec].value = PRN;
pipeline[plPtrExec].type = TYPE_DWORD;
WRITEBACK_ADDR;
// JaguarWriteWord(PRM, PRN, DSP);
//
// NO_WRITEBACK;
+#ifdef DSP_CORRECT_ALIGNMENT_STORE
+ pipeline[plPtrExec].address = PRM & 0xFFFFFFFE;
+#else
pipeline[plPtrExec].address = PRM;
+#endif
if (PRM >= DSP_WORK_RAM_BASE && PRM <= (DSP_WORK_RAM_BASE + 0x1FFF))
{
#endif
// DSPWriteLong(dsp_reg[14] + (dsp_convert_zero[PIMM1] << 2), PRN, DSP);
// NO_WRITEBACK;
+#ifdef DSP_CORRECT_ALIGNMENT_STORE
+ pipeline[plPtrExec].address = (dsp_reg[14] & 0xFFFFFFFC) + (dsp_convert_zero[PIMM1] << 2);
+#else
pipeline[plPtrExec].address = dsp_reg[14] + (dsp_convert_zero[PIMM1] << 2);
+#endif
pipeline[plPtrExec].value = PRN;
pipeline[plPtrExec].type = TYPE_DWORD;
WRITEBACK_ADDR;
{
// DSPWriteLong(dsp_reg[14] + PRM, PRN, DSP);
// NO_WRITEBACK;
+#ifdef DSP_CORRECT_ALIGNMENT_STORE
+ pipeline[plPtrExec].address = (dsp_reg[14] + PRM) & 0xFFFFFFFC;
+#else
pipeline[plPtrExec].address = dsp_reg[14] + PRM;
+#endif
pipeline[plPtrExec].value = PRN;
pipeline[plPtrExec].type = TYPE_DWORD;
WRITEBACK_ADDR;
#endif
// DSPWriteLong(dsp_reg[15] + (dsp_convert_zero[PIMM1] << 2), PRN, DSP);
// NO_WRITEBACK;
+#ifdef DSP_CORRECT_ALIGNMENT_STORE
+ pipeline[plPtrExec].address = (dsp_reg[15] & 0xFFFFFFFC) + (dsp_convert_zero[PIMM1] << 2);
+#else
pipeline[plPtrExec].address = dsp_reg[15] + (dsp_convert_zero[PIMM1] << 2);
+#endif
pipeline[plPtrExec].value = PRN;
pipeline[plPtrExec].type = TYPE_DWORD;
WRITEBACK_ADDR;
{
// DSPWriteLong(dsp_reg[15] + PRM, PRN, DSP);
// NO_WRITEBACK;
+#ifdef DSP_CORRECT_ALIGNMENT_STORE
+ pipeline[plPtrExec].address = (dsp_reg[15] + PRM) & 0xFFFFFFFC;
+#else
pipeline[plPtrExec].address = dsp_reg[15] + PRM;
+#endif
pipeline[plPtrExec].value = PRN;
pipeline[plPtrExec].type = TYPE_DWORD;
WRITEBACK_ADDR;
if (doDSPDis)
WriteLog("%06X: SUB R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
#endif
- UINT32 res = PRN - PRM;
+ uint32_t res = PRN - PRM;
SET_ZNC_SUB(PRN, PRM, res);
PRES = res;
#ifdef DSP_DIS_SUB
if (doDSPDis)
WriteLog("%06X: SUBC R%02u, R%02u [NCZ:%u%u%u, R%02u=%08X, R%02u=%08X] -> ", DSP_PPC, PIMM1, PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM1, PRM, PIMM2, PRN);
#endif
- UINT32 res = PRN - PRM - dsp_flag_c;
- UINT32 borrow = dsp_flag_c;
+ uint32_t res = PRN - PRM - dsp_flag_c;
+ uint32_t borrow = dsp_flag_c;
SET_ZNC_SUB(PRN - borrow, PRM, res);
PRES = res;
#ifdef DSP_DIS_SUBC
if (doDSPDis)
WriteLog("%06X: SUBQ #%u, R%02u [NCZ:%u%u%u, R%02u=%08X] -> ", DSP_PPC, dsp_convert_zero[PIMM1], PIMM2, dsp_flag_n, dsp_flag_c, dsp_flag_z, PIMM2, PRN);
#endif
- UINT32 r1 = dsp_convert_zero[PIMM1];
- UINT32 res = PRN - r1;
+ uint32_t r1 = dsp_convert_zero[PIMM1];
+ uint32_t res = PRN - r1;
SET_ZNC_SUB(PRN, r1, res);
PRES = res;
#ifdef DSP_DIS_SUBQ
#endif
}
-static void DSP_subqmod(void)
+static void DSP_subqmod(void)
{
- UINT32 r1 = dsp_convert_zero[PIMM1];
- UINT32 r2 = PRN;
- UINT32 res = r2 - r1;
+ uint32_t r1 = dsp_convert_zero[PIMM1];
+ uint32_t r2 = PRN;
+ uint32_t res = r2 - r1;
res = (res & (~dsp_modulo)) | (r2 & dsp_modulo);
PRES = res;
SET_ZNC_SUB(r2, r1, res);