// Originally by David Raingeard
// GCC/SDL port by Niels Wagenaar (Linux/WIN32) and Caz (BeOS)
// Extensive cleanups/rewrites by James L. Hammons
+// (C) 2010 Underground Software
+//
+// JLH = James L. 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 "dsp.h"
+#include <SDL.h> // Used only for SDL_GetTicks...
#include <stdlib.h>
-#include <SDL.h> // Used only for SDL_GetTicks...
-#include "memory.h"
-#include "log.h"
-#include "jaguar.h"
-#include "jerry.h"
#include "gpu.h"
#include "jagdasm.h"
+#include "jaguar.h"
+#include "jerry.h"
+#include "log.h"
#include "m68k.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
// Disassembly definitions
+#if 0
#define DSP_DIS_ABS
#define DSP_DIS_ADD
#define DSP_DIS_ADDC
//*/
bool doDSPDis = false;
//bool doDSPDis = true;
-
+#endif
/*
No dis yet:
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,
+ 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,
+ 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!)...
-/*uint8 dsp_opcode_cycles[64] =
+/*uint8 dsp_opcode_cycles[64] =
{
1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 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,
uint32 dsp_opcode_use[65];
const char * dsp_opcode_str[65]=
-{
+{
"add", "addc", "addq", "addqt",
"sub", "subc", "subq", "subqt",
"neg", "and", "or", "xor",
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 uint8 dsp_flag_z, dsp_flag_n, dsp_flag_c;
static uint32 * dsp_reg = NULL, * dsp_alternate_reg = NULL;
static uint32 dsp_reg_bank_0[32], dsp_reg_bank_1[32];
dsp_opcode_use[i] = 0;
}
-void dsp_releaseTimeslice(void)
+void DSPReleaseTimeslice(void)
{
//This does absolutely nothing!!! !!! FIX !!!
dsp_releaseTimeSlice_flag = 1;
{
// Allocate the mirror table
if (!mirror_table)
- mirror_table = (uint16 *)memory_malloc(65536 * sizeof(uint16), "DSP mirror table");
+ mirror_table = (uint16 *)malloc(65536 * sizeof(uint16));
// Fill in the mirror table
if (mirror_table)
if (!dsp_branch_condition_table)
{
- dsp_branch_condition_table = (uint8 *)memory_malloc(32 * 8 * sizeof(uint8), "DSP branch condition table");
+ dsp_branch_condition_table = (uint8 *)malloc(32 * 8 * sizeof(uint8));
// Fill in the condition table
if (dsp_branch_condition_table)
}
return JaguarReadByte(offset, who);
-}
+}
uint16 DSPReadWord(uint32 offset, uint32 who/*=UNKNOWN*/)
{
/* if (dsp_in_exec == 0)
{
m68k_end_timeslice();
- gpu_releaseTimeslice();
+ dsp_releaseTimeslice();
}*/
return;
}
{
uint32 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);
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 %.4x at 0x%.8x\n",data,offset+DSP_WORK_RAM_BASE);
m68k_end_timeslice();
- gpu_releaseTimeslice();
+ dsp_releaseTimeslice();
}*/
//CC only!
#ifdef DSP_DEBUG_CC
//!!!!!!!!
break;
case 0x14:
- {
+ {
//#ifdef DSP_DEBUG
WriteLog("Write to DSP CTRL by %s: %08X\n", whoName[who], data);
//#endif
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?
+// Why do we check for a valid handler at 64? Isn't that the Jag programmer's responsibility? (YES)
+#warning "!!! DSP IRQs that go to the 68K have to be routed thru TOM !!! FIX !!!"
if (JERRYIRQEnabled(IRQ2_DSP))// && jaguar_interrupt_handler_is_valid(64))
{
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;
}
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();
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)
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!
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)
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;
//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!
WriteLog("DSP: Stopped at PC=%08X dsp_modulo=%08X (dsp %s running)\n", dsp_pc, dsp_modulo, (DSP_RUNNING ? "was" : "wasn'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);
// memory_free(dsp_ram_8);
// memory_free(dsp_reg_bank_0);
// memory_free(dsp_reg_bank_1);
+ if (dsp_branch_condition_table)
+ free(dsp_branch_condition_table);
+
+ if (mirror_table)
+ free(mirror_table);
}
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)
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)
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);
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);
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)
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)
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);
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);
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);
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);
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));
#endif
-}
+}
static void dsp_opcode_mtoi(void)
{
static void dsp_opcode_mmult(void)
{
int count = dsp_matrix_control&0x0f;
- uint32 addr = dsp_pointer_to_matrix; // in the gpu ram
+ uint32 addr = dsp_pointer_to_matrix; // in the dsp ram
int64 accum = 0;
uint32 res;
if (!(dsp_matrix_control & 0x10))
{
for (int i = 0; i < count; i++)
- {
+ {
int16 a;
if (i&0x01)
a=(int16)((dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]>>16)&0xffff);
#endif
uint32 _Rn = RN;
uint32 res;
-
+
if (_Rn == 0x80000000)
dsp_flag_n = 1;
else
#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;
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;
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;
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;
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);
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
// Stage 2: Execute
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"));
-#ifdef DSP_DEBUG_PL2
+
if (doDSPDis)
{
WriteLog("DSPExecP: About to execute opcode %s...\n", dsp_opcode_str[pipeline[plPtrExec].opcode]);
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;
-
+
if (_Rn == 0x80000000)
dsp_flag_n = 1;
else
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));
#endif
-}
+}
static void DSP_imult(void)
{
// 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)
{
// 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)
{
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;
PRES = (mirror_table[r1 & 0xFFFF] << 16) | mirror_table[r1 >> 16];
static void DSP_mmult(void)
{
int count = dsp_matrix_control&0x0f;
- uint32 addr = dsp_pointer_to_matrix; // in the gpu ram
+ uint32 addr = dsp_pointer_to_matrix; // in the dsp ram
int64 accum = 0;
uint32 res;
if (!(dsp_matrix_control & 0x10))
{
for (int i = 0; i < count; i++)
- {
+ {
int16 a;
if (i&0x01)
a=(int16)((dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]>>16)&0xffff);
#endif
}
-static void DSP_sat16s(void)
+static void DSP_sat16s(void)
{
int32 r2 = PRN;
uint32 res = (r2 < -32768) ? -32768 : (r2 > 32767) ? 32767 : r2;
SET_ZN(res);
}
-static void DSP_sat32s(void)
+static void DSP_sat32s(void)
{
int32 r2 = (uint32)PRN;
int32 temp = dsp_acc >> 32;
#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;
#endif
}
-static void DSP_subqmod(void)
+static void DSP_subqmod(void)
{
uint32 r1 = dsp_convert_zero[PIMM1];
uint32 r2 = PRN;