From 0d57b7f01acb209d6472024dbca2b0fec29069df Mon Sep 17 00:00:00 2001 From: hrydgard Date: Fri, 1 May 2009 19:07:29 +0000 Subject: [PATCH] DSP: I hereby name R08-R11 WR0-WR3, standing for Wrap control Registers 0-3. Kill "CR". Document decrements a little bit. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@3126 8ced0084-cf51-0410-be5f-012b33b47a6e --- Source/Core/DSPCore/Src/DSPInterpreter.cpp | 21 ++---- Source/Core/DSPCore/Src/DSPTables.cpp | 23 ++++--- Source/Core/DSPCore/Src/gdsp_ext_op.cpp | 29 ++++---- Source/Core/DSPCore/Src/gdsp_ext_op.h | 1 - Source/Core/DSPCore/Src/gdsp_opcodes_helper.h | 68 ++++++++----------- Source/Core/DSPCore/Src/gdsp_registers.h | 29 ++++---- Source/DSPSpy/tests/dr_test.ds | 20 +++--- Source/DSPSpy/tests/ir_test.ds | 18 ++--- 8 files changed, 95 insertions(+), 114 deletions(-) diff --git a/Source/Core/DSPCore/Src/DSPInterpreter.cpp b/Source/Core/DSPCore/Src/DSPInterpreter.cpp index 774da08cbb..9c1c2640c1 100644 --- a/Source/Core/DSPCore/Src/DSPInterpreter.cpp +++ b/Source/Core/DSPCore/Src/DSPInterpreter.cpp @@ -457,6 +457,7 @@ void lri(const UDSPInstruction& opc) u8 reg = opc.hex & DSP_REG_MASK; u16 imm = dsp_fetch_code(); dsp_op_write_reg(reg, imm); + dsp_conditional_extend_accum(reg); } // LRIS $(0x18+D), #I @@ -468,6 +469,7 @@ void lris(const UDSPInstruction& opc) u8 reg = ((opc.hex >> 8) & 0x7) + DSP_REG_AXL0; u16 imm = (s8)opc.hex; dsp_op_write_reg(reg, imm); + dsp_conditional_extend_accum(reg); } // LR $D, @M @@ -481,6 +483,7 @@ void lr(const UDSPInstruction& opc) u16 addr = dsp_fetch_code(); u16 val = dsp_dmem_read(addr); dsp_op_write_reg(reg, val); + dsp_conditional_extend_accum(reg); } // SR @M, $S @@ -1392,12 +1395,7 @@ void dar(const UDSPInstruction& opc) { int reg = opc.hex & 0x3; - int temp = g_dsp.r[reg] + g_dsp.r[DSP_REG_R08]; - - if (temp <= 0x7ff) // ??? - g_dsp.r[reg] = temp; - else - g_dsp.r[reg]--; + g_dsp.r[reg]--; // TODO: Wrap properly. } @@ -1410,12 +1408,7 @@ void iar(const UDSPInstruction& opc) { int reg = opc.hex & 0x3; - int temp = g_dsp.r[reg] + g_dsp.r[DSP_REG_R08]; - - if (temp <= 0x7ff) // ??? - g_dsp.r[reg] = temp; - else - g_dsp.r[reg]++; + g_dsp.r[reg]++; // TODO: Wrap properly according to the corresponding WR register. } //------------------------------------------------------------- @@ -1476,7 +1469,7 @@ void srbith(const UDSPInstruction& opc) g_dsp.r[DSP_REG_SR] |= SR_TOP_BIT_UNK; break; - // 40-bit precision? clamping? no idea :( + // Automatic 40-bit sign extension when loading ACx.M. // 40 seems to be the default. // Confirmed these by using DSPSpy and copying the value of SR to R00 after setting. case 0xe: // SET16 (really, clear SR's 0x4000) @@ -1583,7 +1576,7 @@ void mulmvz(const UDSPInstruction& opc) dsp_set_long_acc(rreg, acc); // math prod - prod = (s64)g_dsp.r[DSP_REG_AXL0 + sreg] * (s64)g_dsp.r[DSP_REG_AXH0 + sreg] * GetMultiplyModifier(); + prod = (s64)(s16)g_dsp.r[DSP_REG_AXL0 + sreg] * (s64)(s16)g_dsp.r[DSP_REG_AXH0 + sreg] * GetMultiplyModifier(); dsp_set_long_prod(prod); Update_SR_Register64(prod); diff --git a/Source/Core/DSPCore/Src/DSPTables.cpp b/Source/Core/DSPCore/Src/DSPTables.cpp index 40aac6792d..845d414180 100644 --- a/Source/Core/DSPCore/Src/DSPTables.cpp +++ b/Source/Core/DSPCore/Src/DSPTables.cpp @@ -309,7 +309,6 @@ const DSPOPCTemplate cw = const DSPOPCTemplate opcodes_ext[] = { // FIXME: guessing this is cr need checking - {"CR", 0x0000, 0x00fc, DSPInterpreter::Ext::cr, nop, 1, 1, {{P_REG, 1, 0, 0, 0x0003}}, NULL, NULL,}, {"DR", 0x0004, 0x00fc, DSPInterpreter::Ext::dr, nop, 1, 1, {{P_REG, 1, 0, 0, 0x0003}}, NULL, NULL,}, {"IR", 0x0008, 0x00fc, DSPInterpreter::Ext::ir, nop, 1, 1, {{P_REG, 1, 0, 0, 0x0003}}, NULL, NULL,}, {"NR", 0x000c, 0x00fc, DSPInterpreter::Ext::nr, nop, 1, 1, {{P_REG, 1, 0, 0, 0x0003}}, NULL, NULL,}, @@ -401,14 +400,14 @@ const pdlabel_t regnames[] = {0x01, "AR1", "Addr Reg 01",}, {0x02, "AR2", "Addr Reg 02",}, {0x03, "AR3", "Addr Reg 03",}, - {0x04, "IX0", "Index Reg 0(04)",}, - {0x05, "IX1", "Index Reg 1(05)",}, - {0x06, "IX2", "Index Reg 2(06)",}, - {0x07, "IX3", "Indec Reg 3(07)",}, - {0x08, "R08", "Register 08",}, - {0x09, "R09", "Register 09",}, - {0x0a, "R10", "Register 10",}, - {0x0b, "R11", "Register 11",}, + {0x04, "IX0", "Index Reg 0",}, + {0x05, "IX1", "Index Reg 1",}, + {0x06, "IX2", "Index Reg 2",}, + {0x07, "IX3", "Index Reg 3",}, + {0x08, "WR0", "Wrapping Register 0",}, + {0x09, "WR1", "Wrapping Register 1",}, + {0x0a, "WR2", "Wrapping Register 2",}, + {0x0b, "WR3", "Wrapping Register 3",}, {0x0c, "ST0", "Call stack",}, {0x0d, "ST1", "Data stack",}, {0x0e, "ST2", "Loop addr stack",}, @@ -435,6 +434,12 @@ const pdlabel_t regnames[] = {0x21, "ACC1", "Accu Full 1",}, {0x22, "AX0", "Extra Accu 0",}, {0x23, "AX1", "Extra Accu 1",}, + + // Old names for the wrapping registers, for compatibility. + {0x08, "R08", "Wrapping Register 0(08)",}, + {0x09, "R09", "Wrapping Register 1(09)",}, + {0x0a, "R10", "Wrapping Register 2(10)",}, + {0x0b, "R11", "Wrapping Register 3(11)",}, }; u8 opSize[OPTABLE_SIZE]; diff --git a/Source/Core/DSPCore/Src/gdsp_ext_op.cpp b/Source/Core/DSPCore/Src/gdsp_ext_op.cpp index e8fdee0e4b..554d5a391b 100644 --- a/Source/Core/DSPCore/Src/gdsp_ext_op.cpp +++ b/Source/Core/DSPCore/Src/gdsp_ext_op.cpp @@ -29,22 +29,21 @@ // attached to opcodes that allow extending (8 lower bits of opcode not used by // opcode). Extended opcodes do not modify program counter $pc register. +// Most of the suffixes increment or decrement one or more addressing registers +// (the first four, ARx). The increment/decrement is either 1, or the corresponding +// "index" register (the second four, IXx). The addressing registers will wrap +// in odd ways, dictated by the corresponding wrapping register, WP0-3. + +// The following should be applied as a decrement: +// ar[i] = (ar[i] & wp[i]) == 0 ? ar[i] | wp[i] : ar[i] - 1; +// I have not found the corresponding algorithms for increments yet. +// It's gotta be fairly simple though. See R3123, R3125 in Google Code. namespace DSPInterpreter { namespace Ext { -// CR $arR -// xxxx xxxx 0000 00rr -// Clearing addressing register $arR. -// This is not in any doc and as such just a guess -void cr(const UDSPInstruction& opc) { - u8 reg = opc.hex & 0x3; - - g_dsp.r[reg] = 0; -} - // DR $arR // xxxx xxxx 0000 01rr // Decrement addressing register $arR. @@ -208,7 +207,6 @@ void dsp_op_ext_r_epi(const UDSPInstruction& opc) { u8 op = (opc.hex >> 2) & 0x3; u8 reg = opc.hex & 0x3; - switch (op) { case 0x00: // g_dsp.r[reg] = 0; @@ -375,7 +373,6 @@ void dsp_op_ext_ld(const UDSPInstruction& opc) // // // ================================================================================ - void dsp_op_ext_ops_pro(const UDSPInstruction& opc) { if ((opc.hex & 0xFF) == 0){return;} @@ -428,7 +425,10 @@ void dsp_op_ext_ops_pro(const UDSPInstruction& opc) void dsp_op_ext_ops_epi(const UDSPInstruction& opc) { - if ((opc.hex & 0xFF) == 0){return;} + if ((opc.hex & 0xFF) == 0) + { + return; + } switch ((opc.hex >> 4) & 0xf) { @@ -436,7 +436,6 @@ void dsp_op_ext_ops_epi(const UDSPInstruction& opc) case 0x09: case 0x0a: case 0x0b: - if (opc.hex & 0x2) { dsp_op_ext_sl_epi(opc.hex); @@ -450,5 +449,3 @@ void dsp_op_ext_ops_epi(const UDSPInstruction& opc) return; } } - - diff --git a/Source/Core/DSPCore/Src/gdsp_ext_op.h b/Source/Core/DSPCore/Src/gdsp_ext_op.h index 6601059fac..7040980bd3 100644 --- a/Source/Core/DSPCore/Src/gdsp_ext_op.h +++ b/Source/Core/DSPCore/Src/gdsp_ext_op.h @@ -62,7 +62,6 @@ void ldn(const UDSPInstruction& opc); void ldm(const UDSPInstruction& opc); void ldnm(const UDSPInstruction& opc); void mv(const UDSPInstruction& opc); -void cr(const UDSPInstruction& opc); void dr(const UDSPInstruction& opc); void ir(const UDSPInstruction& opc); void nr(const UDSPInstruction& opc); diff --git a/Source/Core/DSPCore/Src/gdsp_opcodes_helper.h b/Source/Core/DSPCore/Src/gdsp_opcodes_helper.h index 02eae01d85..e1bbc236ed 100644 --- a/Source/Core/DSPCore/Src/gdsp_opcodes_helper.h +++ b/Source/Core/DSPCore/Src/gdsp_opcodes_helper.h @@ -83,50 +83,19 @@ inline u16 dsp_op_read_reg(u8 reg) inline void dsp_op_write_reg(u8 reg, u16 val) { switch (reg & 0x1f) { - - + /* + case DSP_REG_ACH0: + case DSP_REG_ACH1: + // sign extend from the bottom 8 bits. + g_dsp.r[reg] = (u16)(s16)(s8)(u8)val; + break; +*/ case 0x0c: case 0x0d: case 0x0e: case 0x0f: dsp_reg_store_stack(reg - 0x0c, val); break; -#if 0 // FIXME - case 0x1e: // AC0.M - case 0x1f: // AC1.M - // in "s16 mode", LRI $AC0.M, xxx will set AC0.L and AC0.H to 0, - // while it won't in "s40 mode". - if (g_dsp.r[DSP_REG_SR] & SR_16_BIT) { - g_dsp.r[reg - 0x2] = 0; // L - g_dsp.r[reg - 0xe] = 0; // H - } - - g_dsp.r[reg] = val; - break; - - - case 0x1c: // AC0.L - case 0x1d: // AC1.L - - if (g_dsp.r[DSP_REG_SR] & SR_16_BIT) { - g_dsp.r[reg + 0x2] = 0; // M - g_dsp.r[reg - 0xc] = 0; // H - } - - g_dsp.r[reg] = val; - break; - - case 0x10: // AC0.H - case 0x11: // AC1.H - if (g_dsp.r[DSP_REG_SR] & SR_16_BIT) { - g_dsp.r[reg + 0xc] = 0; // L - g_dsp.r[reg + 0xe] = 0; // M - } - - g_dsp.r[reg] = val; - break; -#endif - default: g_dsp.r[reg] = val; @@ -134,6 +103,25 @@ inline void dsp_op_write_reg(u8 reg, u16 val) } } +inline void dsp_conditional_extend_accum(u8 reg) +{ +#if 0 + switch (reg) + { + case DSP_REG_ACM0: + case DSP_REG_ACM1: + if (g_dsp.r[DSP_REG_SR] & SR_40_MODE_BIT) + { + // Sign extend into whole accum. + u16 val = g_dsp.r[reg]; + g_dsp.r[reg - DSP_REG_ACM0 + DSP_REG_ACH0] = (val & 0x8000) ? 0xFFFF : 0x0000; + g_dsp.r[reg - DSP_REG_ACM0 + DSP_REG_ACL0] = 0; + } + } +#endif +} + + // --------------------------------------------------------------------------------------- // @@ -253,13 +241,13 @@ inline s64 dsp_get_long_acx(int _reg) inline s16 dsp_get_ax_l(int _reg) { _assert_(_reg < 2); - return g_dsp.r[0x18 + _reg]; + return (s16)g_dsp.r[0x18 + _reg]; } inline s16 dsp_get_ax_h(int _reg) { _assert_(_reg < 2); - return g_dsp.r[0x1a + _reg]; + return (s16)g_dsp.r[0x1a + _reg]; } #endif diff --git a/Source/Core/DSPCore/Src/gdsp_registers.h b/Source/Core/DSPCore/Src/gdsp_registers.h index 08838c2a38..473f5993b8 100644 --- a/Source/Core/DSPCore/Src/gdsp_registers.h +++ b/Source/Core/DSPCore/Src/gdsp_registers.h @@ -31,19 +31,19 @@ #define DSP_REG_AR0 0x00 // address registers #define DSP_REG_AR1 0x01 #define DSP_REG_AR2 0x02 -#define DSP_REG_AR3 0x03 // used as jump function selector +#define DSP_REG_AR3 0x03 -#define DSP_REG_IX0 0x04 // LEFT_VOLUME accel -#define DSP_REG_IX1 0x05 // RIGHT_VOLUME accel -#define DSP_REG_IX2 0x06 // ADDRH_SMP accel -#define DSP_REG_IX3 0x07 // ADDRL_SMP accel +#define DSP_REG_IX0 0x04 // indexing registers (actually, mostly used as increments) +#define DSP_REG_IX1 0x05 +#define DSP_REG_IX2 0x06 +#define DSP_REG_IX3 0x07 -#define DSP_REG_R08 0x08 // fixed to 48000 value -#define DSP_REG_R09 0x09 // problems using this -#define DSP_REG_R0A 0x0a // ADDREH_SMP accel -#define DSP_REG_R0B 0x0b // ADDREL_SMP accel +#define DSP_REG_WR0 0x08 // address wrapping registers. should be initialized to 0xFFFF if not used. +#define DSP_REG_WR1 0x09 +#define DSP_REG_WR2 0x0a +#define DSP_REG_WR3 0x0b -#define DSP_REG_ST0 0x0c +#define DSP_REG_ST0 0x0c // stacks. #define DSP_REG_ST1 0x0d #define DSP_REG_ST2 0x0e #define DSP_REG_ST3 0x0f @@ -51,15 +51,15 @@ #define DSP_REG_CONFIG 0x12 #define DSP_REG_SR 0x13 -#define DSP_REG_PRODL 0x14 +#define DSP_REG_PRODL 0x14 // product. #define DSP_REG_PRODM 0x15 #define DSP_REG_PRODH 0x16 #define DSP_REG_PRODM2 0x17 #define DSP_REG_AXL0 0x18 #define DSP_REG_AXL1 0x19 -#define DSP_REG_AXH0 0x1a // SMP_R accel -#define DSP_REG_AXH1 0x1b // SMP_L accel +#define DSP_REG_AXH0 0x1a +#define DSP_REG_AXH1 0x1b #define DSP_REG_ACC0 0x1c // accumulator (global) #define DSP_REG_ACC1 0x1d @@ -85,6 +85,7 @@ #define DSP_REG_CMBH 0xfffe // CPU Mailbox H #define DSP_REG_CMBL 0xffff // CPU Mailbox L + #define DMA_TO_DSP 0 #define DMA_TO_CPU 1 @@ -92,7 +93,6 @@ #define DSP_STACK_C 0 #define DSP_STACK_D 1 - // SR bits #define SR_CARRY 0x0001 #define SR_2 0x0002 // overflow??? @@ -107,7 +107,6 @@ #define SR_40_MODE_BIT 0x4000 // 0 = "16", 1 = "40" (SET16, SET40) Controls sign extension when loading mid accums. #define SR_TOP_BIT_UNK 0x8000 // 1 = normal. 0 = x2 (CLR15, SET15) ???????? - void dsp_reg_store_stack(u8 stack_reg, u16 val); u16 dsp_reg_load_stack(u8 stack_reg); diff --git a/Source/DSPSpy/tests/dr_test.ds b/Source/DSPSpy/tests/dr_test.ds index 03f9dabbd8..2eb3d31ec0 100644 --- a/Source/DSPSpy/tests/dr_test.ds +++ b/Source/DSPSpy/tests/dr_test.ds @@ -2,24 +2,24 @@ incdir "tests" include "dsp_base.inc" -; Tests done using AR1 = 0x0010, IX1 = 0. LP1 means R09. -; LP1 = 0 +; Tests done using AR1 = 0x0010, IX1 = 0. WR1 (wrap 1) means R09. +; WR1 = 0 ; 10, 10, 10, 10, -; LP1 = 1 +; WR1 = 1 ; 10, 11, 10, 11, -; LP1 = 2 +; WR1 = 2 ; 10, 12, 11, 13, 12, 11, 13, 12, 11, 13, 12, 11 -; LP1 = 3 +; WR1 = 3 ; 10, 13, 12, 11, 10, 13, 12... -; LP1 = 4 +; WR1 = 4 ; 10, 14, 13, 17, 16, 15, 14, 13, 17, 16, 15, 14, 13, ... -; LP1 = 5 +; WR1 = 5 ; 10, 15, 14, 13, 12, 17, 16, 15, 14, 13, 12, 17, -; LP1 = 6 +; WR1 = 6 ; 10, 16, 15, 14, 13, 12, 11, 17, 16, 15, 14, 13 -; LP1 = 7 +; WR1 = 7 ; 10, 17, 16, 15, .. normal -; LP1 = 8 +; WR1 = 8 ; 10, 18, 17, 1f, 1e, 1d, 1c, 1b, 1a, 19, 18, 17, 1f, 1e, ..... diff --git a/Source/DSPSpy/tests/ir_test.ds b/Source/DSPSpy/tests/ir_test.ds index a52fe0d63b..e7ee5e332a 100644 --- a/Source/DSPSpy/tests/ir_test.ds +++ b/Source/DSPSpy/tests/ir_test.ds @@ -8,23 +8,23 @@ include "dsp_base.inc" ; These were proven FALSE though by the following: ; Tests done using AR1 = 0x0010, IX1 = 0 -; LP1 = 0 +; WR1 = 0 ; 10, 11, 11, 11, 11...... -; LP1 = 1 +; WR1 = 1 ; 10, 11, 10, 11, 10...... -; LP1 = 2 +; WR1 = 2 ; 10, 11, 12, 13, 11, 12, 13, 11, 12, 13 ...... -; LP1 = 3 +; WR1 = 3 ; 10, 11, 12, 13, 10, 11, 12, 13, 10, 11, 12, 13....... -; LP1 = 4 +; WR1 = 4 ; 10, 11, 12, 13, 14, 15, 16, 17, 13, 14, 15, 16, 17, 13, 14, 15 ...... -; LP1 = 5 +; WR1 = 5 ; 10, 11, 12, 13, 14, 15, 16, 17, 12, 13, 14, 15 ... -; LP1 = 6 +; WR1 = 6 ; 10, 11, 12, 13, 14, 15, 16, 17, 11, 12, 13, 14... -; LP1 = 7 +; WR1 = 7 ; 10, 11, 12, 13, 14, 15, 16, 17, 10, 11, .... -; LP1 = 8 +; WR1 = 8 ; 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 1a, 1b, 1c, 1d, 1e, 1f, 17, 18, 19, 1a, 1b.....