diff --git a/Source/Core/Core/DSP/Interpreter/DSPIntArithmetic.cpp b/Source/Core/Core/DSP/Interpreter/DSPIntArithmetic.cpp index a0a8a2022f..41ff79cc67 100644 --- a/Source/Core/Core/DSP/Interpreter/DSPIntArithmetic.cpp +++ b/Source/Core/Core/DSP/Interpreter/DSPIntArithmetic.cpp @@ -47,7 +47,7 @@ void Interpreter::clrl(const UDSPInstruction opc) // 0000 001r 1100 0000 // iiii iiii iiii iiii // Set logic zero (LZ) flag in status register $sr if result of logic AND of -// accumulator mid part $acD.m with immediate value I is equal I. +// accumulator mid part $acD.m with immediate value I is equal to I. // // flags out: -x-- ---- void Interpreter::andcf(const UDSPInstruction opc) @@ -64,7 +64,7 @@ void Interpreter::andcf(const UDSPInstruction opc) // iiii iiii iiii iiii // Set logic zero (LZ) flag in status register $sr if result of logical AND // operation of accumulator mid part $acD.m with immediate value I is equal -// immediate value 0. +// to immediate value 0. // // flags out: -x-- ---- void Interpreter::andf(const UDSPInstruction opc) @@ -126,8 +126,7 @@ void Interpreter::cmp(const UDSPInstruction) // CMPAR $acS axR.h // 110r s001 xxxx xxxx -// Compares accumulator $acS with accumulator axR.h. -// Not described by Duddie's doc - at least not as a separate instruction. +// Compares accumulator $acS with accumulator $axR.h. // // flags out: x-xx xxxx void Interpreter::cmpar(const UDSPInstruction opc) @@ -794,7 +793,7 @@ void Interpreter::movr(const UDSPInstruction opc) // MOVAX $acD, $axS // 0110 10sd xxxx xxxx -// Moves secondary accumulator $axS to accumulator $axD. +// Moves secondary accumulator $axS to accumulator $acD. // // flags out: --xx xx00 void Interpreter::movax(const UDSPInstruction opc) @@ -812,7 +811,7 @@ void Interpreter::movax(const UDSPInstruction opc) // MOV $acD, $ac(1-D) // 0110 110d xxxx xxxx -// Moves accumulator $ax(1-D) to accumulator $axD. +// Moves accumulator $ac(1-D) to accumulator $acD. // // flags out: --x0 xx00 void Interpreter::mov(const UDSPInstruction opc) diff --git a/Source/Core/Core/DSP/Interpreter/DSPIntBranch.cpp b/Source/Core/Core/DSP/Interpreter/DSPIntBranch.cpp index eb556330a9..7dafeaf3d8 100644 --- a/Source/Core/Core/DSP/Interpreter/DSPIntBranch.cpp +++ b/Source/Core/Core/DSP/Interpreter/DSPIntBranch.cpp @@ -76,9 +76,10 @@ void Interpreter::jcc(const UDSPInstruction opc) } // Generic jmpr implementation -// JMPcc $R +// JRcc $R // 0001 0111 rrr0 cccc -// Jump to address; set program counter to a value from register $R. +// Jump to address if condition cc has been met. Set program counter to +// a value from register $R. void Interpreter::jmprcc(const UDSPInstruction opc) { if (!CheckCondition(opc & 0xf)) @@ -116,7 +117,7 @@ void Interpreter::rti(const UDSPInstruction) } // HALT -// 0000 0000 0020 0001 +// 0000 0000 0010 0001 // Stops execution of DSP code. Sets bit DSP_CR_HALT in register DREG_CR. void Interpreter::halt(const UDSPInstruction) { diff --git a/Source/Core/Core/DSP/Interpreter/DSPIntExtOps.cpp b/Source/Core/Core/DSP/Interpreter/DSPIntExtOps.cpp index 87bc51e06a..c271c28f33 100644 --- a/Source/Core/Core/DSP/Interpreter/DSPIntExtOps.cpp +++ b/Source/Core/Core/DSP/Interpreter/DSPIntExtOps.cpp @@ -144,7 +144,7 @@ void Interpreter::l(const UDSPInstruction opc) } // LN $axD.D, @$arS -// xxxx xxxx 01dd d0ss +// xxxx xxxx 01dd d1ss // Load $axD.D/$acD.D with value from memory pointed by register $arS. // Add indexing register $ixS to register $arS. void Interpreter::ln(const UDSPInstruction opc) @@ -327,17 +327,17 @@ void Interpreter::slnm(const UDSPInstruction opc) IncreaseAddressRegister(DSP_REG_AR0, static_cast(state.r.ix[0]))); } -// LD $ax0.d, $ax1.r, @$arS +// LD $ax0.D, $ax1.R, @$arS // xxxx xxxx 11dr 00ss -// example for "nx'ld $AX0.L, $AX1.L, @$AR3" -// Loads the word pointed by AR0 to AX0.H, then loads the word pointed by AR3 to AX0.L. -// Increments AR0 and AR3. -// If AR0 and AR3 point into the same memory page (upper 6 bits of addr are the same -> games are -// not doing that!) -// then the value pointed by AR0 is loaded to BOTH AX0.H and AX0.L. -// If AR0 points into an invalid memory page (ie 0x2000), then AX0.H keeps its old value. (not +// Load register $ax0.D (either $ax0.l or $ax0.h) with value from memory pointed by register $arS. +// Load register $ax1.R (either $ax1.l or $ax1.h) with value from memory pointed by register $ar3. +// Increment both $arS and $ar3. +// S cannot be 3, as that encodes LDAX. Thus $arS and $ar3 are known to be distinct. +// If $ar0 and $ar3 point into the same memory page (upper 6 bits of addr are the same -> games are +// not doing that!) then the value pointed by $ar0 is loaded to BOTH $ax0.D and $ax1.R. +// If $ar0 points into an invalid memory page (ie 0x2000), then $ax0.D keeps its old value. (not // implemented yet) -// If AR3 points into an invalid memory page, then AX0.L gets the same value as AX0.H. (not +// If $ar3 points into an invalid memory page, then $ax1.R gets the same value as $ax0.D. (not // implemented yet) void Interpreter::ld(const UDSPInstruction opc) { @@ -360,6 +360,9 @@ void Interpreter::ld(const UDSPInstruction opc) // LDAX $axR, @$arS // xxxx xxxx 11sr 0011 +// Load register $axR.h with value from memory pointed by register $arS. +// Load register $axR.l with value from memory pointed by register $ar3. +// Increment both $arS and $ar3. void Interpreter::ldax(const UDSPInstruction opc) { const u8 sreg = (opc >> 5) & 0x1; @@ -378,7 +381,7 @@ void Interpreter::ldax(const UDSPInstruction opc) WriteToBackLog(3, DSP_REG_AR3, IncrementAddressRegister(DSP_REG_AR3)); } -// LDN $ax0.d, $ax1.r, @$arS +// LDN $ax0.D, $ax1.R, @$arS // xxxx xxxx 11dr 01ss void Interpreter::ldn(const UDSPInstruction opc) { @@ -419,7 +422,7 @@ void Interpreter::ldaxn(const UDSPInstruction opc) WriteToBackLog(3, DSP_REG_AR3, IncrementAddressRegister(DSP_REG_AR3)); } -// LDM $ax0.d, $ax1.r, @$arS +// LDM $ax0.D, $ax1.R, @$arS // xxxx xxxx 11dr 10ss void Interpreter::ldm(const UDSPInstruction opc) { @@ -462,7 +465,7 @@ void Interpreter::ldaxm(const UDSPInstruction opc) IncreaseAddressRegister(DSP_REG_AR3, static_cast(state.r.ix[3]))); } -// LDNM $ax0.d, $ax1.r, @$arS +// LDNM $ax0.D, $ax1.R, @$arS // xxxx xxxx 11dr 11ss void Interpreter::ldnm(const UDSPInstruction opc) { diff --git a/Source/Core/Core/DSP/Interpreter/DSPIntLoadStore.cpp b/Source/Core/Core/DSP/Interpreter/DSPIntLoadStore.cpp index 30729fd956..744dffb70b 100644 --- a/Source/Core/Core/DSP/Interpreter/DSPIntLoadStore.cpp +++ b/Source/Core/Core/DSP/Interpreter/DSPIntLoadStore.cpp @@ -13,7 +13,6 @@ namespace DSP::Interpreter // Move value from register $(0x18+S) to data memory pointed by address // CR[0-7] | M. That is, the upper 8 bits of the address are the // bottom 8 bits from CR, and the lower 8 bits are from the 8-bit immediate. -// Note: pc+=2 in duddie's doc seems wrong void Interpreter::srs(const UDSPInstruction opc) { auto& state = m_dsp_core.DSPState(); @@ -86,9 +85,9 @@ void Interpreter::si(const UDSPInstruction opc) state.WriteDMEM(addr, imm); } -// LRR $D, @$S +// LRR $D, @$arS // 0001 1000 0ssd dddd -// Move value from data memory pointed by addressing register $S to register $D. +// Move value from data memory pointed by addressing register $arS to register $D. void Interpreter::lrr(const UDSPInstruction opc) { const u8 sreg = (opc >> 5) & 0x3; @@ -100,10 +99,10 @@ void Interpreter::lrr(const UDSPInstruction opc) ConditionalExtendAccum(dreg); } -// LRRD $D, @$S +// LRRD $D, @$arS // 0001 1000 1ssd dddd -// Move value from data memory pointed by addressing register $S to register $D. -// Decrement register $S. +// Move value from data memory pointed by addressing register $arS to register $D. +// Decrement register $arS. void Interpreter::lrrd(const UDSPInstruction opc) { const u8 sreg = (opc >> 5) & 0x3; @@ -116,10 +115,10 @@ void Interpreter::lrrd(const UDSPInstruction opc) state.r.ar[sreg] = DecrementAddressRegister(sreg); } -// LRRI $D, @$S +// LRRI $D, @$arS // 0001 1001 0ssd dddd -// Move value from data memory pointed by addressing register $S to register $D. -// Increment register $S. +// Move value from data memory pointed by addressing register $arS to register $D. +// Increment register $arS. void Interpreter::lrri(const UDSPInstruction opc) { const u8 sreg = (opc >> 5) & 0x3; @@ -132,10 +131,10 @@ void Interpreter::lrri(const UDSPInstruction opc) state.r.ar[sreg] = IncrementAddressRegister(sreg); } -// LRRN $D, @$S +// LRRN $D, @$arS // 0001 1001 1ssd dddd -// Move value from data memory pointed by addressing register $S to register $D. -// Add indexing register $(0x4+S) to register $S. +// Move value from data memory pointed by addressing register $arS to register $D. +// Add corresponding indexing register $ixS to register $arS. void Interpreter::lrrn(const UDSPInstruction opc) { const u8 sreg = (opc >> 5) & 0x3; @@ -148,10 +147,10 @@ void Interpreter::lrrn(const UDSPInstruction opc) state.r.ar[sreg] = IncreaseAddressRegister(sreg, static_cast(state.r.ix[sreg])); } -// SRR @$D, $S +// SRR @$arD, $S // 0001 1010 0dds ssss // Store value from source register $S to a memory location pointed by -// addressing register $D. +// addressing register $arD. void Interpreter::srr(const UDSPInstruction opc) { const u8 dreg = (opc >> 5) & 0x3; @@ -164,10 +163,10 @@ void Interpreter::srr(const UDSPInstruction opc) state.WriteDMEM(state.r.ar[dreg], OpReadRegister(sreg)); } -// SRRD @$D, $S +// SRRD @$arD, $S // 0001 1010 1dds ssss // Store value from source register $S to a memory location pointed by -// addressing register $D. Decrement register $D. +// addressing register $arD. Decrement register $arD. void Interpreter::srrd(const UDSPInstruction opc) { const u8 dreg = (opc >> 5) & 0x3; @@ -182,10 +181,10 @@ void Interpreter::srrd(const UDSPInstruction opc) state.r.ar[dreg] = DecrementAddressRegister(dreg); } -// SRRI @$D, $S +// SRRI @$arD, $S // 0001 1011 0dds ssss // Store value from source register $S to a memory location pointed by -// addressing register $D. Increment register $D. +// addressing register $arD. Increment register $arD. void Interpreter::srri(const UDSPInstruction opc) { const u8 dreg = (opc >> 5) & 0x3; @@ -200,10 +199,10 @@ void Interpreter::srri(const UDSPInstruction opc) state.r.ar[dreg] = IncrementAddressRegister(dreg); } -// SRRN @$D, $S +// SRRN @$arD, $S // 0001 1011 1dds ssss // Store value from source register $S to a memory location pointed by -// addressing register $D. Add DSP_REG_IX0 register to register $D. +// addressing register $arD. Add corresponding indexing register $ixD to register $arD. void Interpreter::srrn(const UDSPInstruction opc) { const u8 dreg = (opc >> 5) & 0x3; diff --git a/Source/Core/Core/DSP/Interpreter/DSPIntMisc.cpp b/Source/Core/Core/DSP/Interpreter/DSPIntMisc.cpp index a686bba2b5..4335bb2f69 100644 --- a/Source/Core/Core/DSP/Interpreter/DSPIntMisc.cpp +++ b/Source/Core/Core/DSP/Interpreter/DSPIntMisc.cpp @@ -122,8 +122,8 @@ void Interpreter::addarn(const UDSPInstruction opc) // SBCLR #I // 0001 0010 aaaa aiii -// bit of status register $sr. Bit number is calculated by adding 6 to -// immediate value I. +// Clear bit of status register $sr. Bit number is calculated by adding 6 to immediate value I; +// thus, bits 6 through 13 (LZ through AM) can be cleared with this instruction. void Interpreter::sbclr(const UDSPInstruction opc) { auto& state = m_dsp_core.DSPState(); @@ -134,8 +134,8 @@ void Interpreter::sbclr(const UDSPInstruction opc) // SBSET #I // 0001 0011 aaaa aiii -// Set bit of status register $sr. Bit number is calculated by adding 6 to -// immediate value I. +// Set bit of status register $sr. Bit number is calculated by adding 6 to immediate value I; +// thus, bits 6 through 13 (LZ through AM) can be set with this instruction. void Interpreter::sbset(const UDSPInstruction opc) { auto& state = m_dsp_core.DSPState(); diff --git a/Source/Core/Core/DSP/Interpreter/DSPIntMultiplier.cpp b/Source/Core/Core/DSP/Interpreter/DSPIntMultiplier.cpp index e12cf07ab1..a334f99d3e 100644 --- a/Source/Core/Core/DSP/Interpreter/DSPIntMultiplier.cpp +++ b/Source/Core/Core/DSP/Interpreter/DSPIntMultiplier.cpp @@ -247,7 +247,7 @@ void Interpreter::mulx(const UDSPInstruction opc) } // MULXAC $ax0.S, $ax1.T, $acR -// 101s t01r xxxx xxxx +// 101s t10r xxxx xxxx // Add product register to accumulator register $acR. Multiply one part // $ax0 by one part $ax1. Part is selected by S and // T bits. Zero selects low part, one selects high part. @@ -343,7 +343,7 @@ void Interpreter::mulc(const UDSPInstruction opc) } // MULCAC $acS.m, $axT.h, $acR -// 110s t10r xxxx xxxx +// 110s t10r xxxx xxxx // Multiply mid part of accumulator register $acS.m by high part $axS.h of // secondary accumulator $axS (treat them both as signed). Add product // register before multiplication to accumulator $acR. @@ -372,7 +372,6 @@ void Interpreter::mulcac(const UDSPInstruction opc) // Multiply mid part of accumulator register $acS.m by high part $axT.h of // secondary accumulator $axT (treat them both as signed). Move product // register before multiplication to accumulator $acR. -// possible mistake in duddie's doc axT.h rather than axS.h // // flags out: --xx xx0x void Interpreter::mulcmv(const UDSPInstruction opc) @@ -394,8 +393,7 @@ void Interpreter::mulcmv(const UDSPInstruction opc) } // MULCMVZ $acS.m, $axT.h, $acR -// 110s t01r xxxx xxxx -// (fixed possible bug in duddie's description, s->t) +// 110s t01r xxxx xxxx // Multiply mid part of accumulator register $acS.m by high part $axT.h of // secondary accumulator $axT (treat them both as signed). Move product // register before multiplication to accumulator $acR, set (round) low part of diff --git a/Source/Core/Core/DSP/Jit/x64/DSPJitArithmetic.cpp b/Source/Core/Core/DSP/Jit/x64/DSPJitArithmetic.cpp index 1acce79df6..633b714124 100644 --- a/Source/Core/Core/DSP/Jit/x64/DSPJitArithmetic.cpp +++ b/Source/Core/Core/DSP/Jit/x64/DSPJitArithmetic.cpp @@ -56,7 +56,7 @@ void DSPEmitter::clrl(const UDSPInstruction opc) // 0000 001r 1100 0000 // iiii iiii iiii iiii // Set logic zero (LZ) flag in status register $sr if result of logic AND of -// accumulator mid part $acD.m with immediate value I is equal I. +// accumulator mid part $acD.m with immediate value I is equal to I. // // flags out: -x-- ---- void DSPEmitter::andcf(const UDSPInstruction opc) @@ -91,7 +91,7 @@ void DSPEmitter::andcf(const UDSPInstruction opc) // iiii iiii iiii iiii // Set logic zero (LZ) flag in status register $sr if result of logical AND // operation of accumulator mid part $acD.m with immediate value I is equal -// immediate value 0. +// to immediate value 0. // // flags out: -x-- ---- void DSPEmitter::andf(const UDSPInstruction opc) @@ -185,8 +185,7 @@ void DSPEmitter::cmp(const UDSPInstruction opc) // CMPAR $acS axR.h // 110r s001 xxxx xxxx -// Compares accumulator $acS with accumulator axR.h. -// Not described by Duddie's doc - at least not as a separate instruction. +// Compares accumulator $acS with accumulator $axR.h. // // flags out: x-xx xxxx void DSPEmitter::cmpar(const UDSPInstruction opc) @@ -1090,7 +1089,7 @@ void DSPEmitter::movr(const UDSPInstruction opc) // MOVAX $acD, $axS // 0110 10sd xxxx xxxx -// Moves secondary accumulator $axS to accumulator $axD. +// Moves secondary accumulator $axS to accumulator $acD. // // flags out: --xx xx00 void DSPEmitter::movax(const UDSPInstruction opc) @@ -1111,7 +1110,7 @@ void DSPEmitter::movax(const UDSPInstruction opc) // MOV $acD, $ac(1-D) // 0110 110d xxxx xxxx -// Moves accumulator $ax(1-D) to accumulator $axD. +// Moves accumulator $ac(1-D) to accumulator $acD. // // flags out: --x0 xx00 void DSPEmitter::mov(const UDSPInstruction opc) diff --git a/Source/Core/Core/DSP/Jit/x64/DSPJitBranch.cpp b/Source/Core/Core/DSP/Jit/x64/DSPJitBranch.cpp index 05dc6e672a..ea4df2a6fd 100644 --- a/Source/Core/Core/DSP/Jit/x64/DSPJitBranch.cpp +++ b/Source/Core/Core/DSP/Jit/x64/DSPJitBranch.cpp @@ -156,9 +156,10 @@ void DSPEmitter::r_jmprcc(const UDSPInstruction opc) WriteBranchExit(); } // Generic jmpr implementation -// JMPcc $R +// JRcc $R // 0001 0111 rrr0 cccc -// Jump to address; set program counter to a value from register $R. +// Jump to address if condition cc has been met. Set program counter to +// a value from register $R. // NOTE: Cannot use FallBackToInterpreter(opc) here because of the need to write branch exit void DSPEmitter::jmprcc(const UDSPInstruction opc) { @@ -270,7 +271,7 @@ void DSPEmitter::rti(const UDSPInstruction opc) } // HALT -// 0000 0000 0020 0001 +// 0000 0000 0010 0001 // Stops execution of DSP code. Sets bit DSP_CR_HALT in register DREG_CR. void DSPEmitter::halt(const UDSPInstruction) { diff --git a/Source/Core/Core/DSP/Jit/x64/DSPJitExtOps.cpp b/Source/Core/Core/DSP/Jit/x64/DSPJitExtOps.cpp index 0df0a4037a..96147237c0 100644 --- a/Source/Core/Core/DSP/Jit/x64/DSPJitExtOps.cpp +++ b/Source/Core/Core/DSP/Jit/x64/DSPJitExtOps.cpp @@ -9,7 +9,7 @@ using namespace Gen; /* It is safe to directly write to the address registers as they are - neither read not written by any extendable opcode. The same is true + neither read nor written by any extendable opcode. The same is true for memory accesses. It probably even is safe to write to all registers except for SR, ACx.x, AXx.x and PROD, which may be modified by the main op. @@ -131,7 +131,7 @@ void DSPEmitter::l(const UDSPInstruction opc) } // LN $axD.D, @$arS -// xxxx xxxx 01dd d0ss +// xxxx xxxx 01dd d1ss // Load $axD.D/$acD.D with value from memory pointed by register $arS. // Add indexing register $ixS to register $arS. void DSPEmitter::ln(const UDSPInstruction opc) @@ -354,16 +354,18 @@ void DSPEmitter::slnm(const UDSPInstruction opc) increase_addr_reg(DSP_REG_AR0, DSP_REG_AR0); } -// LD $ax0.d, $ax1.r, @$arS +// LD $ax0.D, $ax1.R, @$arS // xxxx xxxx 11dr 00ss -// example for "nx'ld $AX0.L, $AX1.L, @$AR3" -// Loads the word pointed by AR0 to AX0.H, then loads the word pointed by AR3 -// to AX0.L. Increments AR0 and AR3. If AR0 and AR3 point into the same -// memory page (upper 6 bits of addr are the same -> games are not doing that!) -// then the value pointed by AR0 is loaded to BOTH AX0.H and AX0.L. If AR0 -// points into an invalid memory page (ie 0x2000), then AX0.H keeps its old -// value. (not implemented yet) If AR3 points into an invalid memory page, then -// AX0.L gets the same value as AX0.H. (not implemented yet) +// Load register $ax0.D (either $ax0.l or $ax0.h) with value from memory pointed by register $arS. +// Load register $ax1.R (either $ax1.l or $ax1.h) with value from memory pointed by register $ar3. +// Increment both $arS and $ar3. +// S cannot be 3, as that encodes LDAX. Thus $arS and $ar3 are known to be distinct. +// If $ar0 and $ar3 point into the same memory page (upper 6 bits of addr are the same -> games are +// not doing that!) then the value pointed by $ar0 is loaded to BOTH $ax0.D and $ax1.R. +// If $ar0 points into an invalid memory page (ie 0x2000), then $ax0.D keeps its old value. (not +// implemented yet) +// If $ar3 points into an invalid memory page, then $ax1.R gets the same value as $ax0.D. (not +// implemented yet) void DSPEmitter::ld(const UDSPInstruction opc) { u8 dreg = (opc >> 5) & 0x1; @@ -396,6 +398,9 @@ void DSPEmitter::ld(const UDSPInstruction opc) // LDAX $axR, @$arS // xxxx xxxx 11sr 0011 +// Load register $axR.h with value from memory pointed by register $arS. +// Load register $axR.l with value from memory pointed by register $ar3. +// Increment both $arS and $ar3. void DSPEmitter::ldax(const UDSPInstruction opc) { u8 sreg = (opc >> 5) & 0x1; @@ -425,7 +430,7 @@ void DSPEmitter::ldax(const UDSPInstruction opc) increment_addr_reg(DSP_REG_AR3); } -// LDN $ax0.d, $ax1.r, @$arS +// LDN $ax0.D, $ax1.R, @$arS // xxxx xxxx 11dr 01ss void DSPEmitter::ldn(const UDSPInstruction opc) { @@ -488,7 +493,7 @@ void DSPEmitter::ldaxn(const UDSPInstruction opc) increment_addr_reg(DSP_REG_AR3); } -// LDM $ax0.d, $ax1.r, @$arS +// LDM $ax0.D, $ax1.R, @$arS // xxxx xxxx 11dr 10ss void DSPEmitter::ldm(const UDSPInstruction opc) { @@ -551,7 +556,7 @@ void DSPEmitter::ldaxm(const UDSPInstruction opc) increase_addr_reg(DSP_REG_AR3, DSP_REG_AR3); } -// LDNM $ax0.d, $ax1.r, @$arS +// LDNM $ax0.D, $ax1.R, @$arS // xxxx xxxx 11dr 11ss void DSPEmitter::ldnm(const UDSPInstruction opc) { diff --git a/Source/Core/Core/DSP/Jit/x64/DSPJitLoadStore.cpp b/Source/Core/Core/DSP/Jit/x64/DSPJitLoadStore.cpp index 11b4888735..7c60d6d1d2 100644 --- a/Source/Core/Core/DSP/Jit/x64/DSPJitLoadStore.cpp +++ b/Source/Core/Core/DSP/Jit/x64/DSPJitLoadStore.cpp @@ -17,7 +17,6 @@ namespace DSP::JIT::x64 // Move value from register $(0x18+S) to data memory pointed by address // CR[0-7] | M. That is, the upper 8 bits of the address are the // bottom 8 bits from CR, and the lower 8 bits are from the 8-bit immediate. -// Note: pc+=2 in duddie's doc seems wrong void DSPEmitter::srs(const UDSPInstruction opc) { u8 reg = ((opc >> 8) & 0x7) + 0x18; @@ -105,9 +104,9 @@ void DSPEmitter::si(const UDSPInstruction opc) m_gpr.PutXReg(tmp1); } -// LRR $D, @$S +// LRR $D, @$arS // 0001 1000 0ssd dddd -// Move value from data memory pointed by addressing register $S to register $D. +// Move value from data memory pointed by addressing register $arS to register $D. void DSPEmitter::lrr(const UDSPInstruction opc) { u8 sreg = (opc >> 5) & 0x3; @@ -124,10 +123,10 @@ void DSPEmitter::lrr(const UDSPInstruction opc) dsp_conditional_extend_accum(dreg); } -// LRRD $D, @$S +// LRRD $D, @$arS // 0001 1000 1ssd dddd -// Move value from data memory pointed by addressing register $S to register $D. -// Decrement register $S. +// Move value from data memory pointed by addressing register $arS to register $D. +// Decrement register $arS. void DSPEmitter::lrrd(const UDSPInstruction opc) { u8 sreg = (opc >> 5) & 0x3; @@ -145,10 +144,10 @@ void DSPEmitter::lrrd(const UDSPInstruction opc) decrement_addr_reg(sreg); } -// LRRI $D, @$S +// LRRI $D, @$arS // 0001 1001 0ssd dddd -// Move value from data memory pointed by addressing register $S to register $D. -// Increment register $S. +// Move value from data memory pointed by addressing register $arS to register $D. +// Increment register $arS. void DSPEmitter::lrri(const UDSPInstruction opc) { u8 sreg = (opc >> 5) & 0x3; @@ -166,10 +165,10 @@ void DSPEmitter::lrri(const UDSPInstruction opc) increment_addr_reg(sreg); } -// LRRN $D, @$S +// LRRN $D, @$arS // 0001 1001 1ssd dddd -// Move value from data memory pointed by addressing register $S to register $D. -// Add indexing register $(0x4+S) to register $S. +// Move value from data memory pointed by addressing register $arS to register $D. +// Add indexing register $ixS to register $arS. void DSPEmitter::lrrn(const UDSPInstruction opc) { u8 sreg = (opc >> 5) & 0x3; @@ -187,10 +186,10 @@ void DSPEmitter::lrrn(const UDSPInstruction opc) increase_addr_reg(sreg, sreg); } -// SRR @$D, $S +// SRR @$arD, $S // 0001 1010 0dds ssss // Store value from source register $S to a memory location pointed by -// addressing register $D. +// addressing register $arD. void DSPEmitter::srr(const UDSPInstruction opc) { u8 dreg = (opc >> 5) & 0x3; @@ -205,10 +204,10 @@ void DSPEmitter::srr(const UDSPInstruction opc) m_gpr.PutXReg(tmp1); } -// SRRD @$D, $S +// SRRD @$arD, $S // 0001 1010 1dds ssss // Store value from source register $S to a memory location pointed by -// addressing register $D. Decrement register $D. +// addressing register $arD. Decrement register $arD. void DSPEmitter::srrd(const UDSPInstruction opc) { u8 dreg = (opc >> 5) & 0x3; @@ -225,10 +224,10 @@ void DSPEmitter::srrd(const UDSPInstruction opc) decrement_addr_reg(dreg); } -// SRRI @$D, $S +// SRRI @$arD, $S // 0001 1011 0dds ssss // Store value from source register $S to a memory location pointed by -// addressing register $D. Increment register $D. +// addressing register $arD. Increment register $arD. void DSPEmitter::srri(const UDSPInstruction opc) { u8 dreg = (opc >> 5) & 0x3; @@ -245,10 +244,10 @@ void DSPEmitter::srri(const UDSPInstruction opc) increment_addr_reg(dreg); } -// SRRN @$D, $S +// SRRN @$arD, $S // 0001 1011 1dds ssss // Store value from source register $S to a memory location pointed by -// addressing register $D. Add DSP_REG_IX0 register to register $D. +// addressing register $arD. Add corresponding indexing register $ixD to register $arD. void DSPEmitter::srrn(const UDSPInstruction opc) { u8 dreg = (opc >> 5) & 0x3; diff --git a/Source/Core/Core/DSP/Jit/x64/DSPJitMisc.cpp b/Source/Core/Core/DSP/Jit/x64/DSPJitMisc.cpp index 8115804b56..0e0dd087b4 100644 --- a/Source/Core/Core/DSP/Jit/x64/DSPJitMisc.cpp +++ b/Source/Core/Core/DSP/Jit/x64/DSPJitMisc.cpp @@ -130,8 +130,8 @@ void DSPEmitter::clrCompileSR(u16 bit) } // SBCLR #I // 0001 0011 aaaa aiii -// bit of status register $sr. Bit number is calculated by adding 6 to -// immediate value I. +// Clear bit of status register $sr. Bit number is calculated by adding 6 to immediate value I; +// thus, bits 6 through 13 (LZ through AM) can be cleared with this instruction. void DSPEmitter::sbclr(const UDSPInstruction opc) { u8 bit = (opc & 0x7) + 6; @@ -141,8 +141,8 @@ void DSPEmitter::sbclr(const UDSPInstruction opc) // SBSET #I // 0001 0010 aaaa aiii -// Set bit of status register $sr. Bit number is calculated by adding 6 to -// immediate value I. +// Set bit of status register $sr. Bit number is calculated by adding 6 to immediate value I; +// thus, bits 6 through 13 (LZ through AM) can be set with this instruction. void DSPEmitter::sbset(const UDSPInstruction opc) { u8 bit = (opc & 0x7) + 6; diff --git a/Source/Core/Core/DSP/Jit/x64/DSPJitMultiplier.cpp b/Source/Core/Core/DSP/Jit/x64/DSPJitMultiplier.cpp index 4b7db14823..efbd59d164 100644 --- a/Source/Core/Core/DSP/Jit/x64/DSPJitMultiplier.cpp +++ b/Source/Core/Core/DSP/Jit/x64/DSPJitMultiplier.cpp @@ -416,7 +416,7 @@ void DSPEmitter::mulx(const UDSPInstruction opc) } // MULXAC $ax0.S, $ax1.T, $acR -// 101s t01r xxxx xxxx +// 101s t10r xxxx xxxx // Add product register to accumulator register $acR. Multiply one part // $ax0 by one part $ax1. Part is selected by S and // T bits. Zero selects low part, one selects high part. @@ -487,7 +487,7 @@ void DSPEmitter::mulxmv(const UDSPInstruction opc) m_gpr.PutXReg(tmp1); } -// MULXMV $ax0.S, $ax1.T, $acR +// MULXMVZ $ax0.S, $ax1.T, $acR // 101s t01r xxxx xxxx // Move product register to accumulator register $acR and clear (round) low part // of accumulator register $acR.l. Multiply one part $ax0 by one part $ax1 @@ -545,7 +545,7 @@ void DSPEmitter::mulc(const UDSPInstruction opc) } // MULCAC $acS.m, $axT.h, $acR -// 110s t10r xxxx xxxx +// 110s t10r xxxx xxxx // Multiply mid part of accumulator register $acS.m by high part $axS.h of // secondary accumulator $axS (treat them both as signed). Add product // register before multiplication to accumulator $acR. @@ -586,7 +586,6 @@ void DSPEmitter::mulcac(const UDSPInstruction opc) // Multiply mid part of accumulator register $acS.m by high part $axT.h of // secondary accumulator $axT (treat them both as signed). Move product // register before multiplication to accumulator $acR. -// possible mistake in duddie's doc axT.h rather than axS.h // flags out: --xx xx0x void DSPEmitter::mulcmv(const UDSPInstruction opc) @@ -617,8 +616,7 @@ void DSPEmitter::mulcmv(const UDSPInstruction opc) } // MULCMVZ $acS.m, $axT.h, $acR -// 110s t01r xxxx xxxx -// (fixed possible bug in duddie's description, s->t) +// 110s t01r xxxx xxxx // Multiply mid part of accumulator register $acS.m by high part $axT.h of // secondary accumulator $axT (treat them both as signed). Move product // register before multiplication to accumulator $acR, set (round) low part of diff --git a/Source/DSPSpy/.gitignore b/Source/DSPSpy/.gitignore new file mode 100644 index 0000000000..33ae368ffb --- /dev/null +++ b/Source/DSPSpy/.gitignore @@ -0,0 +1,4 @@ +dsp_code.h +build/ +*.dol +*.elf \ No newline at end of file diff --git a/Source/DSPSpy/Config.h b/Source/DSPSpy/Config.h deleted file mode 100644 index 9790da1b56..0000000000 --- a/Source/DSPSpy/Config.h +++ /dev/null @@ -1,4 +0,0 @@ -// Copyright 2003 Dolphin Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -// Dummy file for common to compile diff --git a/Source/DSPSpy/Makefile b/Source/DSPSpy/Makefile index 6ab9c54535..df6a27aa55 100644 --- a/Source/DSPSpy/Makefile +++ b/Source/DSPSpy/Makefile @@ -23,7 +23,7 @@ include $(DEVKITPPC)/$(HW_TYPE)_rules #--------------------------------------------------------------------------------- TARGET := $(notdir $(CURDIR))_$(HW_TYPE) BUILD := build -SOURCES := . emu +SOURCES := . DATA := data INCLUDES := include ../Core/Common . diff --git a/Source/DSPSpy/README.md b/Source/DSPSpy/README.md new file mode 100644 index 0000000000..4c57915a79 --- /dev/null +++ b/Source/DSPSpy/README.md @@ -0,0 +1,39 @@ +# DSPSpy + +DSPSpy is a homebrew tool for experimenting with the GameCube/Wii DSP. It can also be used to dump the DSP ROMs. + +## Building + +DSPSpy is built using [devkitPPC](https://wiibrew.org/wiki/DevkitPPC); see the [devkitPro getting started page](https://devkitpro.org/wiki/Getting_Started) for more information. DSPSpy also requires DSPTool to be built. + +First, run DSPTool to generate `dsp_code.h`, for instance from `tests/dsp_test.ds`. The following commands assume an x64 Windows setup running in the DSPSpy directory: + +``` +../../Binary/x64/DSPTool.exe -h dsp_code tests/dsp_test.ds +``` + +To use the ROM-dumping code, run this: + +``` +../../Binary/x64/DSPTool.exe -h dsp_code util/dump_roms.ds +``` + +DSPTool can also generate a header for multiple DSP programs at the same time. First, create a file (in this example, it was named `file_list.txt`) with the following contents: + +``` +tests/dsp_test.ds +tests/mul_test.ds +tests/neg_test.ds +``` + +Then run: + +``` +../../Binary/x64/DSPTool.exe -h dsp_code -m file_list.txt +``` + +After `dsp_code.h` has been generated, simply run `make` to generate `dspspy_wii.dol`, which can be loaded by normal means. + +## Dumping DSP ROMs + +Build DSPSpy with `util/dump_roms.ds`. When launched, DSPSpy will automatically create files `dsp_rom.bin` and `dsp_coef.bin` on the SD card (only SD cards are supported); DSPSpy can be exited immediately afterwards. \ No newline at end of file diff --git a/Source/DSPSpy/build.sh b/Source/DSPSpy/build.sh deleted file mode 100644 index a6fbaf9015..0000000000 --- a/Source/DSPSpy/build.sh +++ /dev/null @@ -1,6 +0,0 @@ -../../Binary/x64/DSPTool.exe -h dsp_code tests/mul_test.ds -mkdir emu -cp ../Core/Core/DSP/*.cpp emu -cp ../Core/Core/DSP/*.h emu -make - diff --git a/Source/DSPSpy/sbuild.sh b/Source/DSPSpy/sbuild.sh deleted file mode 100644 index 80038bf9f5..0000000000 --- a/Source/DSPSpy/sbuild.sh +++ /dev/null @@ -1,4 +0,0 @@ -../../Binary/x64/DSPTool.exe -h dsp_code tests/mul_test.ds -rm -rf emu -make - diff --git a/Source/DSPSpy/tests/cr_test.ds b/Source/DSPSpy/tests/cr_test.ds new file mode 100644 index 0000000000..272e4b8c2a --- /dev/null +++ b/Source/DSPSpy/tests/cr_test.ds @@ -0,0 +1,81 @@ +incdir "tests" +include "dsp_base.inc" + +; Tests the behavior of SI, SRS, and LRS when CR is changed + +; Register that is writable but with contents that doesn't matter (COEF_A1_0) +TEST_REG: equ 0xFFA0 ; 0xFF00 (not writable) +; This is separate because SRS and SI currently require value 0..7f or ff80..ffff, +; though the actual behavior doesn't match that +TEST_ADDR: equ 0xFFA0 ; 0x0000 +; Memory addresses +TEST_MEM: equ 0x00A0 ; 0x0000 +TEST_MEM_2: equ 0x01A0 ; 0x0100 + + LRI $AC0.L, #0xf00f + SR @TEST_REG, $AC0.L + SR @TEST_MEM, $AC0.L + SR @TEST_MEM_2, $AC0.L + CALL send_regs + + ; Observed: writes to TEST_REG + SI @TEST_ADDR, #0xf11f + CALL send_regs + + LRI $AC0.L, #0xf22f + ; Observed: writes to TEST_REG + SRS @TEST_ADDR, $AC0.L + CALL send_regs + + LRI $CR, #0x0000 + ; Observed: still writes to TEST_REG + SI @TEST_ADDR, #0xf33f + CALL send_regs + + LRI $AC0.L, #0xf44f + ; Observed: writes to TEST_MEM + SRS @TEST_ADDR, $AC0.L + CALL send_regs + + LRI $CR, #0x0001 + ; Observed: still writes to TEST_REG + SI @TEST_ADDR, #0xf55f + CALL send_regs + + LRI $AC0.L, #0xf66f + ; Observed: writes to TEST_MEM_2 + SRS @TEST_ADDR, $AC0.L + CALL send_regs + + ; At this point, TEST_REG should be f55f, TEST_MEM should be f44f, + ; and TEST_MEM_2 should be f66f. Test the behavior of LRS. + ; Changes to prod.l are for display only. + LRI $CR, #0x00ff + LRI $prod.l, #0xf55f + LRS $AC0.L, @TEST_ADDR + CALL send_regs + + LRI $CR, #0x0000 + LRI $prod.l, #0xf44f + LRS $AC0.L, @TEST_ADDR + CALL send_regs + + LRI $CR, #0x0001 + LRI $prod.l, #0xf66f + LRS $AC0.L, @TEST_ADDR + CALL send_regs + +; We're done, DO NOT DELETE THIS LINE + JMP end_of_test + +send_regs: + ; For display purposes only + LRI $prod.m1, #TEST_REG + LRI $prod.h, #TEST_MEM + LRI $prod.m2, #TEST_MEM_2 + ; Actual registers + LR $AC1.L, @TEST_REG + LR $AC0.M, @TEST_MEM + LR $AC1.M, @TEST_MEM_2 + CALL send_back + RET diff --git a/docs/DSP/GameCube_DSP_Users_Manual/.gitignore b/docs/DSP/GameCube_DSP_Users_Manual/.gitignore new file mode 100644 index 0000000000..3c5955276e --- /dev/null +++ b/docs/DSP/GameCube_DSP_Users_Manual/.gitignore @@ -0,0 +1,290 @@ +GameCube_DSP_Users_Manual.pdf + +## Core latex/pdflatex auxiliary files: +*.aux +*.lof +*.log +*.lot +*.fls +*.out +*.toc +*.fmt +*.fot +*.cb +*.cb2 +.*.lb + +## Intermediate documents: +*.dvi +*.xdv +*-converted-to.* +# these rules might exclude image files for figures etc. +# *.ps +# *.eps +# *.pdf + +## Generated if empty string is given at "Please type another file name for output:" +.pdf + +## Bibliography auxiliary files (bibtex/biblatex/biber): +*.bbl +*.bcf +*.blg +*-blx.aux +*-blx.bib +*.run.xml + +## Build tool auxiliary files: +*.fdb_latexmk +*.synctex +*.synctex(busy) +*.synctex.gz +*.synctex.gz(busy) +*.pdfsync + +## Build tool directories for auxiliary files +# latexrun +latex.out/ + +## Auxiliary and intermediate files from other packages: +# algorithms +*.alg +*.loa + +# achemso +acs-*.bib + +# amsthm +*.thm + +# beamer +*.nav +*.pre +*.snm +*.vrb + +# changes +*.soc + +# comment +*.cut + +# cprotect +*.cpt + +# elsarticle (documentclass of Elsevier journals) +*.spl + +# endnotes +*.ent + +# fixme +*.lox + +# feynmf/feynmp +*.mf +*.mp +*.t[1-9] +*.t[1-9][0-9] +*.tfm + +#(r)(e)ledmac/(r)(e)ledpar +*.end +*.?end +*.[1-9] +*.[1-9][0-9] +*.[1-9][0-9][0-9] +*.[1-9]R +*.[1-9][0-9]R +*.[1-9][0-9][0-9]R +*.eledsec[1-9] +*.eledsec[1-9]R +*.eledsec[1-9][0-9] +*.eledsec[1-9][0-9]R +*.eledsec[1-9][0-9][0-9] +*.eledsec[1-9][0-9][0-9]R + +# glossaries +*.acn +*.acr +*.glg +*.glo +*.gls +*.glsdefs +*.lzo +*.lzs + +# uncomment this for glossaries-extra (will ignore makeindex's style files!) +# *.ist + +# gnuplottex +*-gnuplottex-* + +# gregoriotex +*.gaux +*.glog +*.gtex + +# htlatex +*.4ct +*.4tc +*.idv +*.lg +*.trc +*.xref + +# hyperref +*.brf + +# knitr +*-concordance.tex +# TODO Uncomment the next line if you use knitr and want to ignore its generated tikz files +# *.tikz +*-tikzDictionary + +# listings +*.lol + +# luatexja-ruby +*.ltjruby + +# makeidx +*.idx +*.ilg +*.ind + +# minitoc +*.maf +*.mlf +*.mlt +*.mtc[0-9]* +*.slf[0-9]* +*.slt[0-9]* +*.stc[0-9]* + +# minted +_minted* +*.pyg + +# morewrites +*.mw + +# newpax +*.newpax + +# nomencl +*.nlg +*.nlo +*.nls + +# pax +*.pax + +# pdfpcnotes +*.pdfpc + +# sagetex +*.sagetex.sage +*.sagetex.py +*.sagetex.scmd + +# scrwfile +*.wrt + +# sympy +*.sout +*.sympy +sympy-plots-for-*.tex/ + +# pdfcomment +*.upa +*.upb + +# pythontex +*.pytxcode +pythontex-files-*/ + +# tcolorbox +*.listing + +# thmtools +*.loe + +# TikZ & PGF +*.dpth +*.md5 +*.auxlock + +# todonotes +*.tdo + +# vhistory +*.hst +*.ver + +# easy-todo +*.lod + +# xcolor +*.xcp + +# xmpincl +*.xmpi + +# xindy +*.xdy + +# xypic precompiled matrices and outlines +*.xyc +*.xyd + +# endfloat +*.ttt +*.fff + +# Latexian +TSWLatexianTemp* + +## Editors: +# WinEdt +*.bak +*.sav + +# Texpad +.texpadtmp + +# LyX +*.lyx~ + +# Kile +*.backup + +# gummi +.*.swp + +# KBibTeX +*~[0-9]* + +# TeXnicCenter +*.tps + +# auto folder when using emacs and auctex +./auto/* +*.el + +# expex forward references with \gathertags +*-tags.tex + +# standalone packages +*.sta + +# Makeindex log files +*.lpz + +# xwatermark package +*.xwm + +# REVTeX puts footnotes in the bibliography by default, unless the nofootinbib +# option is specified. Footnotes are the stored in a file with suffix Notes.bib. +# Uncomment the next line to have this generated file ignored. +#*Notes.bib diff --git a/docs/DSP/GameCube_DSP_Users_Manual/GameCube_DSP_Users_Manual.tex b/docs/DSP/GameCube_DSP_Users_Manual/GameCube_DSP_Users_Manual.tex index 4d561d59db..582f1e96fa 100644 --- a/docs/DSP/GameCube_DSP_Users_Manual/GameCube_DSP_Users_Manual.tex +++ b/docs/DSP/GameCube_DSP_Users_Manual/GameCube_DSP_Users_Manual.tex @@ -46,10 +46,10 @@ % Document front page material \title{\textbf{\Huge GameCube DSP User's Manual}} \author{Reverse-engineered and documented by Duddie \\ \href{mailto:duddie@walla.com}{duddie@walla.com}} -\date{\today\\v0.0.6} +\date{\today\\v0.1.0} % Title formatting commands -\newcommand{\OpcodeTitle}[1]{\subsection{\textbf{\Large #1}}} +\newcommand{\OpcodeTitle}[1]{\subsection{#1}\label{instruction:#1}} % Formatting/self-documenting commands \newcommand{\Address}[1]{\texttt{#1}} @@ -58,7 +58,7 @@ \newcommand{\Flag}[1]{\texttt{#1}} \newcommand{\Function}[1]{\texttt{#1}} \newcommand{\InlineExpression}[1]{\texttt{#1}} -\newcommand{\Opcode}[1]{\texttt{#1}} +\newcommand{\Opcode}[1]{\texttt{\nameref{instruction:#1}}} \newcommand{\Register}[1]{\texttt{#1}} \newcommand{\RegisterField}[1]{\texttt{#1}} \newcommand{\Value}[1]{\texttt{#1}} @@ -72,10 +72,10 @@ \newcommand{\RegisterBitOverview}[4]{ \begin{table}[H] \centering - \begin{tabular}{|lcl|} + \begin{tabular}{|lcr|} \hline - \Address{#1} & \Register{#2} & \multicolumn{1}{r|}{#3} \\ \hline - & \texttt{#4} & \\ \hline + \Address{#1} & \Register{#2} & {#3} \\ \hline + \multicolumn{3}{|c|}{\texttt{#4}} \\ \hline \end{tabular} \end{table} } @@ -178,7 +178,7 @@ { } -% Environment for describing a not for a DSP opcode +% Environment for describing a note for a DSP opcode \newenvironment{DSPOpcodeNote} { \textbf{Note:} @@ -198,6 +198,23 @@ \end{description} } +% Command to show flags. +\newcommand{\DSPOpcodeFlags}[8] +{ + \textbf{Flags:} + \begin{description} + \item \begin{tabular}{|c|c|c|c|c|c|c|c|} + \hline + OS & LZ & TB & S32 & S & AZ & O & C \\ + \hline + #1 & #2 & #3 & #4 & #5 & #6 & #7 & #8 \\ + \hline + \end{tabular} + \end{description} +} + +\newcommand{\DSPOpcodeFlagsUnchanged}[0]{\DSPOpcodeFlags{-}{-}{-}{-}{-}{-}{-}{-}} + \makeatother \begin{document} \maketitle{} @@ -230,7 +247,7 @@ The purpose of this documentation is purely academic and it aims at understandin \begin{table}[htb] \centering -\begin{tabular}{|l|l|l|l|} +\begin{tabular}{|p{.5in}|p{.75in}|p{.75in}|p{3.5in}|} \hline \textbf{Version} & \textbf{Date} & \textbf{Author} & \textbf{Change} \\ \hline 0.0.1 & 2005.05.08 & Duddie & Initial release \\ \hline @@ -239,6 +256,8 @@ The purpose of this documentation is purely academic and it aims at understandin 0.0.4 & 2005.05.12 & Duddie & Added preliminary DSP memory map and opcode syntax. \\ \hline 0.0.5 & 2018.04.09 & Lioncache & Converted document over to LaTeX. \\ \hline 0.0.6 & 2018.04.13 & BhaaL & Updated register tables, fixed opcode operations \\ \hline +0.0.7 & Mid 2020 & Tilka & Fixed typos and register names, and improved readability. \\ \hline +0.1.0 & 2021.08.21 & Pokechu22 & Added missing instructions, improved documentation of hardware registers, documented additional behaviors, and improved formatting. \\ \hline \end{tabular} \end{table} @@ -371,13 +390,14 @@ Each version of the License is given a distinguishing version number. If the Doc \section{DSP Memory Map} -The DSP accesses memory in words, so all addresses refer to words. A DSP word is 16 bits in size. +The DSP has two address spaces, one for data and one for instructions. The DSP accesses memory in words, so all addresses refer to words. A DSP word is 16 bits in size. +\subsection{Instruction Memory} Instruction Memory (IMEM) is divided into instruction RAM (IRAM) and instruction ROM (IROM). -Exception vectors are located at the top of the RAM and occupy the first 8 words. +Exception vectors are located at the top of the RAM and occupy the first 16 words, with 2 words available for each exception (enough for a \Opcode{JMP} instruction for each exception). -DSP IRAM is mapped through as first 8KB of ARAM (Accelerator RAM), therefore the CPU can DMA DSP code to DSP IRAM. This usually occurs during boot time, as the DSP ROM is not enabled at cold reset and needs to be reenabled by a small stub executed in IRAM. +There are no DSP instructions that write to IMEM; however, the \texttt{ILLR} family of instructions can read from it. This is sometimes used for jump tables or indexing into a list of pointers (which may point into either IMEM or DMEM). \begin{table}[htb] \centering @@ -391,6 +411,42 @@ DSP IRAM is mapped through as first 8KB of ARAM (Accelerator RAM), therefore the \pagebreak{} +\subsection{Data Memory} +Data Memory (DMEM) is divided into data RAM (DRAM) and resampling coefficient data (COEF). Hardware registers (IFX) are also mapped into this space. + +It is possible to both read and write to DMEM, but coefficient data cannot be written to. + +\begin{table}[htb] +\centering +\begin{tabular}{|l|l|} +\hline +\begin{tabular}[c]{@{}l@{}}\texttt{0x0000}\\ \\ \\ \\ \\ \\ \\ \\ \texttt{0x0FFF}\end{tabular} & \texttt{DRAM} \\ \hline + & \\ \hline +\begin{tabular}[c]{@{}l@{}}\texttt{0x1000}\\ \\ \\ \\ \\ \\ \\ \\ \texttt{0x17FF}\end{tabular} & \texttt{COEF} \\ \hline + & \\ \hline +\begin{tabular}[c]{@{}l@{}}\texttt{0xFF00}\\ \\ \\ \\\\ \\ \\ \\ \texttt{0xFFFF}\end{tabular} & \texttt{IFX} \\ \hline +\end{tabular} +\end{table} + +\pagebreak{} + +\section{Initialization} + +The DSP is initialized before it is used. This is done by copying a small program to physical address \Address{0x01000000} (virtual \Address{0x81000000}) in GameCube/Wii main memory, and then writing to \Register{DSP\_CONTROL\_STATUS} at \texttt{0xCC00500A} with the 11th and 0th bits set (SDK titles write \Value{0x08ad}). The 11th bit being set appears to cause data from \Address{0x01000000} to be DMAd to the start of IMEM; at least 128 bytes of data (64 DSP words) are transferred. (None of this has been extensively hardware tested, and is instead based on libogc's \Code{\_\_dsp\_bootstrap}.) + +The program that SDK titles send does the following: +\begin{enumerate} +\item Reads all \Value{0x1000} words of IROM from \Address{0x8000} through \Address{0x8FFF} (using \Opcode{ILRRI}) +\item Writes zero to all \Value{0x1000} words of DRAM from \Address{0x0000} through \Address{0x0FFF} (using \Opcode{SRRI}) +\item Reads all \Value{0x0800} words of COEF data from \Address{0x1000} through \Address{0x17FF} (using \Opcode{LRRI}) +\item Waits for the top bit of \Register{DMBH} to be clear (indicating the CPU is ready to receive mail) +\item Writes \Value{0x0054} to \Register{DMBH} and \Value{0x4348} to \Register{DMBL}, sending \Value{0x00543448} (``TCH''?) to the CPU. The CPU does not check for this value, but it does wait for mail to be sent. +\end{enumerate} + +It is not clear why this is done, as the values read from IROM and COEF are not used; perhaps it works around a hardware bug where incorrect values are read from ROM initially. + +\pagebreak{} + \chapter{Registers} \section{Register names} @@ -442,6 +498,10 @@ The DSP has 32 16-bit registers, although their individual purpose and their fun The DSP has two long 40-bit accumulators (\Register{\$acX}) and their short 24-bit forms (\Register{\$acsX}) that reflect the upper part of 40-bit accumulator. There are additional two 32-bit accumulators (\Register{\$axX}). +The high parts of the 40-bit accumulators (\Register{acX.h}) are sign-extended 8-bit registers. Writes to the upper 8 bits are ignored, +and the upper 8 bits read the same as the 7th bit. For instance, \Value{0x007F} reads back as \Value{0x007F}, but \Value{0x0080} reads +back as \Value{0xFF80}. + \textbf{Accumulators \Register{\$acX}:} 40-bit accumulator \Register{\$acX} (\Register{\$acX.hml}) consists of registers: @@ -490,7 +550,9 @@ If the value is not zero, then the PC is modified by the value from call stack \ \section{Config register} -Its purpose is unknown at this time. It is written with \Value{0x00FF} and \Value{0x0004} values. +Serves as a base offset for \Opcode{SRS}, \Opcode{SRSH}, and \Opcode{LRS}. Zelda uCode writes it with \Value{0x0004}, but otherwise it is usually \Value{0x00FF}. + +This is an 8-bit register. Writes to the upper 8 bits are ignored and those bits always read back as 0. \pagebreak{} @@ -511,10 +573,10 @@ Furthermore, it also contains control bits to configure the flow of certain oper \texttt{11} & \texttt{EIE} & External interrupt enable \\ \hline \texttt{10} & & \\ \hline \texttt{9} & \texttt{IE} & Interrupt enable \\ \hline -\texttt{8} & \texttt{0} & Hardwired to 0? \\ \hline +\texttt{8} & & Unknown, always reads back as 0 \\ \hline \texttt{7} & \texttt{OS} & Overflow (sticky) \\ \hline -\texttt{6} & \texttt{LZ} & Logic zero \\ \hline -\texttt{5} & & Top two bits are equal \\ \hline +\texttt{6} & \texttt{LZ} & Logic zero (used by \Opcode{ANDCF} and \Opcode{ANDF}) \\ \hline +\texttt{5} & \texttt{TB} & Top two bits are equal \\ \hline \texttt{4} & \texttt{AS} & Above s32 \\ \hline \texttt{3} & \texttt{S} & Sign \\ \hline \texttt{2} & \texttt{Z} & Arithmetic zero \\ \hline @@ -528,7 +590,7 @@ Furthermore, it also contains control bits to configure the flow of certain oper \section{Product register} The product register is a register containing the intermediate product of a multiply or multiply and accumulation operation. -It's result should never be used for calculation although the register can be read or written. +Its result should never be used for calculation although the register can be read or written. It reflects the state of the internal multiply unit. The product is 40 bits with 1 bit of overflow. \begin{lstlisting}[language=C++] @@ -540,6 +602,8 @@ It needs to be noted that \InlineExpression{\$prod.m1 + \$prod.m2} overflow bit Bit \RegisterField{\$sr.AM} affects the result of the multiply unit. If \RegisterField{\$sr.AM} is equal 0 then the result of every multiply operation will be multiplied by two. +\Register{prod.h} is 8 bits. The upper 8 bits always read back as 0. + \pagebreak{} \chapter{Exceptions} @@ -586,39 +650,209 @@ Exception vectors are located at address \Address{0x0000} in Instruction RAM. \section{Hardware registers} -Hardware registers occupy the address space at \Address{0xFFxx} in DSP memory space. Each register is 16 bits in width. +Hardware registers (IFX) occupy the address space at \Address{0xFFxx} in the Data Memory space. Each register is 16 bits in width. \begin{table}[htb] \centering \begin{tabular}{|l|l|l|} \hline -\textbf{Address} & \textbf{Name} & \textbf{Description} \\ \hline -\multicolumn{3}{|l|}{\textit{Mailboxes}} \\ \hline -\Address{0xFFFE} & \Register{CMBH} & CPU Mailbox H \\ \hline -\Address{0xFFFF} & \Register{CMBL} & CPU Mailbox L \\ \hline -\Address{0xFFFC} & \Register{DMBH} & DSP Mailbox H \\ \hline -\Address{0xFFFD} & \Register{DMBL} & DSP Mailbox L \\ \hline -\multicolumn{3}{|l|}{\textit{DMA Interface}} \\ \hline -\Address{0xFFCE} & \Register{DSMAH} & Memory address H \\ \hline -\Address{0xFFCF} & \Register{DSMAL} & Memory address L \\ \hline -\Address{0xFFCD} & \Register{DSPA} & DSP memory address \\ \hline -\Address{0xFFC9} & \Register{DSCR} & DMA control \\ \hline -\Address{0xFFCB} & \Register{DSBL} & Block size \\ \hline -\multicolumn{3}{|l|}{\textit{Accelerator}} \\ \hline -\Address{0xFFD4} & \Register{ACSAH} & Accelerator start address H \\ \hline -\Address{0xFFD5} & \Register{ACSAL} & Accelerator start address L \\ \hline -\Address{0xFFD6} & \Register{ACEAH} & Accelerator end address H \\ \hline -\Address{0xFFD7} & \Register{ACEAL} & Accelerator end address L \\ \hline -\Address{0xFFD8} & \Register{ACCAH} & Accelerator current address H \\ \hline -\Address{0xFFD9} & \Register{ACCAL} & Accelerator current address L \\ \hline -\Address{0xFFDD} & \Register{ACDAT} & Accelerator data \\ \hline -\multicolumn{3}{|l|}{\textit{Interrupts}} \\ \hline -\Address{0xFFFB} & \Register{DIRQ} & IRQ request \\ \hline +\textbf{Address} & \textbf{Name} & \textbf{Description} \\ \hline +\multicolumn{3}{|l|}{\textit{ADPCM Coefficients}} \\ \hline +\Address{0xFFA0} & \Register{COEF\_A1\_0} & A1 Coefficient \# 0 \\ \hline +\Address{0xFFA1} & \Register{COEF\_A2\_0} & A2 Coefficient \# 0 \\ \hline +\multicolumn{3}{|c|}{$\vdots$} \\ \hline +\Address{0xFFAE} & \Register{COEF\_A1\_7} & A1 Coefficient \# 7 \\ \hline +\Address{0xFFAF} & \Register{COEF\_A2\_7} & A2 Coefficient \# 7 \\ \hline +\multicolumn{3}{|l|}{\textit{DMA Interface}} \\ \hline +\Address{0xFFC9} & \Register{DSCR} & DMA control \\ \hline +\Address{0xFFCB} & \Register{DSBL} & Block length \\ \hline +\Address{0xFFCD} & \Register{DSPA} & DSP memory address \\ \hline +\Address{0xFFCE} & \Register{DSMAH} & Memory address H \\ \hline +\Address{0xFFCF} & \Register{DSMAL} & Memory address L \\ \hline +\multicolumn{3}{|l|}{\textit{Accelerator}} \\ \hline +\Address{0xFFD1} & \Register{FORMAT} & Accelerator sample format \\ \hline +\Address{0xFFD2} & \Register{ACUNK1} & Unknown, usually 3 \\ \hline +\Address{0xFFD3} & \Register{ACDATA1} & Alternative ARAM interface \\ \hline +\Address{0xFFD4} & \Register{ACSAH} & Accelerator start address H \\ \hline +\Address{0xFFD5} & \Register{ACSAL} & Accelerator start address L \\ \hline +\Address{0xFFD6} & \Register{ACEAH} & Accelerator end address H \\ \hline +\Address{0xFFD7} & \Register{ACEAL} & Accelerator end address L \\ \hline +\Address{0xFFD8} & \Register{ACCAH} & Accelerator current address H \\ \hline +\Address{0xFFD9} & \Register{ACCAL} & Accelerator current address L \\ \hline +\Address{0xFFDA} & \Register{SCALE} & ADPCM predictor and scale \\ \hline +\Address{0xFFDB} & \Register{YN1} & ADPCM YN1 \\ \hline +\Address{0xFFDC} & \Register{YN2} & ADPCM YN2 \\ \hline +\Address{0xFFDD} & \Register{ACDAT} & Accelerator data \\ \hline +\Address{0xFFDE} & \Register{GAIN} & Gain \\ \hline +\Address{0xFFDF} & \Register{ACUNK2} & Unknown, usually \Value{0x0C} \\ \hline +\Address{0xFFED} & \Register{AMDM} & ARAM DMA Request Mask \\ \hline +\multicolumn{3}{|l|}{\textit{Interrupts}} \\ \hline +\Address{0xFFFB} & \Register{DIRQ} & IRQ request \\ \hline +\multicolumn{3}{|l|}{\textit{Mailboxes}} \\ \hline +\Address{0xFFFC} & \Register{DMBH} & DSP Mailbox H \\ \hline +\Address{0xFFFD} & \Register{DMBL} & DSP Mailbox L \\ \hline +\Address{0xFFFE} & \Register{CMBH} & CPU Mailbox H \\ \hline +\Address{0xFFFF} & \Register{CMBL} & CPU Mailbox L \\ \hline \end{tabular} \end{table} \pagebreak{} +\section{DMA} + +The GameCube DSP is connected to the memory bus through a DMA channel. DMA can be used to transfer data between DSP memory (both instruction and data) and main memory. + +\RegisterBitOverview{0xFFC9}{DSCR}{DMA Control}{---- ---- ---- -tid} + +\begin{RegisterBitDescriptions} +\RegisterBitDescription{2}{t}{R}{Transfer currently in progress if set} +\RegisterBitDescription{1}{i}{R/W}{\begin{tabular}[c]{@{}l@{}}\Value{1} - DMA to/from IMEM\\ \Value{0} - DMA to/from DMEM\end{tabular}} +\RegisterBitDescription{0}{d}{R/W}{\begin{tabular}[c]{@{}l@{}}\Value{1} - DMA to CPU from DSP\\ \Value{0} - DMA from CPU to DSP\end{tabular}} +\end{RegisterBitDescriptions} + +\RegisterBitOverview{0xFFCB}{DSBL}{Block length}{dddd dddd dddd dddd} + +\begin{RegisterBitDescriptions} +\RegisterBitDescription{15--0}{d}{W}{Length in bytes to transfer. Writing to this register starts a DMA transfer.} +\end{RegisterBitDescriptions} + +\RegisterBitOverview{0xFFCD}{DSPA}{DSP Address}{dddd dddd dddd dddd} + +\begin{RegisterBitDescriptions} +\RegisterBitDescription{15--0}{d}{R/W}{Bits 15--0 of the DSP memory address} +\end{RegisterBitDescriptions} + +\RegisterBitOverview{0xFFCE}{DSMAH}{Memory Address H}{dddd dddd dddd dddd} + +\begin{RegisterBitDescriptions} +\RegisterBitDescription{15--0}{d}{R/W}{Bits 31--16 of the main memory address} +\end{RegisterBitDescriptions} + +\RegisterBitOverview{0xFFCF}{DSMAL}{Memory Address L}{dddd dddd dddd dddd} + +\begin{RegisterBitDescriptions} +\RegisterBitDescription{15--0}{d}{R/W}{Bits 15--0 of the main memory address} +\end{RegisterBitDescriptions} + +\pagebreak{} + +\section{Accelerator} + +The accelerator is used to transfer data from accelerator memory (ARAM) to DSP memory. The accelerator area can be marked with \Register{ACSA} (start) and \Register{ACEA} (end) addresses. +Current address for the accelerator can be set or read from the \Register{ACCA} register. Reading from accelerator memory is done by reading from the \Register{ACDAT} register. +This register contains data from ARAM pointed to by the \Register{ACCA} register. +After reading the data, \Register{ACCA} is incremented by one. +After \Register{ACCA} grows bigger than the area pointed to by \Register{ACEA}, it gets reset to a value from \Register{ACSA} and the \Exception{ACCOV} interrupt is generated. + +\RegisterBitOverview{0xFFD1}{FORMAT}{Accelerator sample format}{dddd dddd dddd dddd} + +\begin{RegisterBitDescriptions} +\RegisterBitDescription{15--0}{d}{R/W}{\begin{tabular}[c]{@{}l@{}} +\Value{0x00} - ADPCM audio \\ +\Value{0x05} - u8 reads (D3) \\ +\Value{0x06} - u16 reads (D3) \\ +\Value{0x0A} - 16-bit PCM audio, u16 writes (D3) \\ +\Value{0x19} - 8-bit PCM audio +\end{tabular}} +\end{RegisterBitDescriptions} + +\RegisterBitOverview{0xFFD2}{ACUNK1}{Unknown 1}{dddd dddd dddd dddd} + +\begin{RegisterBitDescriptions} +\RegisterBitDescription{15--0}{d}{R/W}{Usually 3} +\end{RegisterBitDescriptions} + +\RegisterBitOverview{0xFFD3}{ACDATA1}{Alternative ARAM interface}{dddd dddd dddd dddd} + +\begin{RegisterBitDescriptions} +\RegisterBitDescription{15--0}{d}{R/W}{Reads from or writes to data pointed to by current accelerator address, and then increments the current address. It is unclear whether this respects the start and end addresses.} +\end{RegisterBitDescriptions} + +\RegisterBitOverview{0xFFD4}{ACSAH}{Accelerator Start Address H}{dddd dddd dddd dddd} + +\begin{RegisterBitDescriptions} +\RegisterBitDescription{15--0}{d}{R/W}{Bits 31--16 of the accelerator start address} +\end{RegisterBitDescriptions} + +\RegisterBitOverview{0xFFD5}{ACSAL}{Accelerator Start Address L}{dddd dddd dddd dddd} + +\begin{RegisterBitDescriptions} +\RegisterBitDescription{15--0}{d}{R/W}{Bits 15--0 of the accelerator start address} +\end{RegisterBitDescriptions} + +\pagebreak{} + +\RegisterBitOverview{0xFFD6}{ACEAH}{Accelerator End Address H}{dddd dddd dddd dddd} + +\begin{RegisterBitDescriptions} +\RegisterBitDescription{15--0}{d}{R/W}{Bits 31--16 of the accelerator end address} +\end{RegisterBitDescriptions} + +\RegisterBitOverview{0xFFD7}{ACEAL}{Accelerator End Address L}{dddd dddd dddd dddd} + +\begin{RegisterBitDescriptions} +\RegisterBitDescription{15--0}{d}{R/W}{Bits 15--0 of the accelerator end address} +\end{RegisterBitDescriptions} + +\RegisterBitOverview{0xFFD8}{ACCAH}{Accelerator Current Address H}{dddd dddd dddd dddd} + +\begin{RegisterBitDescriptions} +\RegisterBitDescription{15--0}{d}{R/W}{Bits 31--16 of the accelerator current address} +\end{RegisterBitDescriptions} + +\RegisterBitOverview{0xFFD9}{ACSAH}{Accelerator Current Address L}{dddd dddd dddd dddd} + +\begin{RegisterBitDescriptions} +\RegisterBitDescription{15--0}{d}{R/W}{Bits 15--0 of the accelerator current address} +\end{RegisterBitDescriptions} + +\RegisterBitOverview{0xFFDA}{SCALE}{ADPCM predictor and scale}{---- ---- -ppp ssss} + +\begin{RegisterBitDescriptions} +\RegisterBitDescription{6--4}{d}{R/W}{Used to decide which pair of coefficients to use (\Register{COEF\_A1\_p} and \Register{COEF\_A2\_p}, at $\Address{0xFFA0} + 2p$ and $\Address{0xFFA0} + 2p + 1$)} +\RegisterBitDescription{3--0}{s}{R/W}{The scale to use, as $2^s$} +\end{RegisterBitDescriptions} + +\pagebreak{} + +\RegisterBitOverview{0xFFDB}{YN1}{ADPCM YN1}{dddd dddd dddd dddd} + +\begin{RegisterBitDescriptions} +\RegisterBitDescription{15--0}{d}{R/W}{Last value read by the accelerator, updated to the new value of \Register{ACDAT} when \Register{ACDAT} is read. Used when calculating ADPCM, but updated for all sample formats.} +\end{RegisterBitDescriptions} + +\RegisterBitOverview{0xFFDC}{YN1}{ADPCM YN2}{dddd dddd dddd dddd} + +\begin{RegisterBitDescriptions} +\RegisterBitDescription{15--0}{d}{R/W}{Second-last value read by the accelerator, updated to the previous value of \Register{YN1} when \Register{ACDAT} is read. Used when calculating ADPCM, but updated for all sample formats. Writing this value starts the accelerator.} +\end{RegisterBitDescriptions} + +\RegisterBitOverview{0xFFDD}{ACDAT}{Accelerator data}{dddd dddd dddd dddd} + +\begin{RegisterBitDescriptions} +\RegisterBitDescription{15--0}{d}{R}{Reads new data from the accelerator. When there is no data left, returns 0.} +\end{RegisterBitDescriptions} + +\RegisterBitOverview{0xFFDE}{GAIN}{Gain}{dddd dddd dddd dddd} + +\begin{RegisterBitDescriptions} +\RegisterBitDescription{15--0}{d}{R/W}{Exact behavior unknown} +\end{RegisterBitDescriptions} + +\RegisterBitOverview{0xFFDF}{ACUNK2}{Unknown 2}{dddd dddd dddd dddd} + +\begin{RegisterBitDescriptions} +\RegisterBitDescription{15--0}{d}{R/W}{Usually \Value{0x0C}} +\end{RegisterBitDescriptions} + +\RegisterBitOverview{0xFFEF}{AMDM}{ARAM DMA Request Mask}{---- ---- ---- ---m} + +\begin{RegisterBitDescriptions} +\RegisterBitDescription{0}{m}{R/W}{\begin{tabular}[c]{@{}l@{}}\Value{0} - DMA with ARAM unmasked\\ \Value{1} - masked\end{tabular}} +\end{RegisterBitDescriptions} + +\pagebreak{} + \section{Interrupts} The DSP can raise interrupts at the CPU. Interrupts are usually used to signal that a DSP mailbox has been filled with new data. @@ -633,40 +867,6 @@ The DSP can raise interrupts at the CPU. Interrupts are usually used to signal t \section{Mailboxes} -\subsection{CPU Mailbox} - -The CPU Mailbox (CMB) is a register that allows sending 31 bits of information from the CPU to the DSP. - -\RegisterBitOverview{0xFFFE}{CMBH}{CPU Mailbox H}{Mddd dddd dddd dddd} - -\begin{RegisterBitDescriptions} -\RegisterBitDescription{15}{M}{R}{ - \begin{tabular}[c]{@{}l@{}} - \Value{1} - Mailbox contains mail from the CPU\\ \Value{0} - Mailbox empty - \end{tabular} -} -\RegisterBitDescription{14--0}{d}{R}{Bits 30--16 of the mail sent from the CPU} -\end{RegisterBitDescriptions} - -\RegisterBitOverview{0xFFFF}{CMBL}{CPU Mailbox L}{dddd dddd dddd dddd} - -\begin{RegisterBitDescriptions} -\RegisterBitDescription{15--0}{d}{R}{ - Bits 15--0 of mail sent from the CPU. Reading of this register by the DSP causes the \RegisterField{CMBH.M} - bit to be cleared. -} -\end{RegisterBitDescriptions} - -\textbf{Operation:} - -From the CPU side, software usually checks the \RegisterField{M} bit of \Register{CMBH}. It takes action only in the case that this bit is \Value{0}. -Said action is to write \Register{CMBH} first and then \Register{CMBL}. After writing to \Register{CMBL}, the mail is ready to be received by the DSP. - -From the DSP side, the DSP loops by probing the \RegisterField{M} bit. When this bit is \Value{1}, the DSP reads \Register{CMBH} first and then \Register{CMBL}. -After reading \Register{CMBL}, \RegisterField{CMBH.M} will be cleared. - -\pagebreak{} - \subsection{DSP Mailbox} The DSP mailbox (DMB) is an interface to send 31 bits of information from the DSP to the CPU. @@ -702,49 +902,37 @@ If the DSP does processing when the CPU receives a mail, then it waits for the \ \pagebreak{} -\subsection{DMA} +\subsection{CPU Mailbox} -The GameCube DSP is connected to the memory bus through a DMA channel. DMA can be used to transfer data between DSP memory (both instruction and data) and main memory. +The CPU Mailbox (CMB) is a register that allows sending 31 bits of information from the CPU to the DSP. -\RegisterBitOverview{0xFFCE}{DSMAH}{Memory Address H}{dddd dddd dddd dddd} +\RegisterBitOverview{0xFFFE}{CMBH}{CPU Mailbox H}{Mddd dddd dddd dddd} \begin{RegisterBitDescriptions} -\RegisterBitDescription{15--0}{d}{R}{Bits 31--16 of the main memory address} +\RegisterBitDescription{15}{M}{R}{ + \begin{tabular}[c]{@{}l@{}} + \Value{1} - Mailbox contains mail from the CPU\\ \Value{0} - Mailbox empty + \end{tabular} +} +\RegisterBitDescription{14--0}{d}{R}{Bits 30--16 of the mail sent from the CPU} \end{RegisterBitDescriptions} -\RegisterBitOverview{0xFFCF}{DSMAL}{Memory Address L}{dddd dddd dddd dddd} +\RegisterBitOverview{0xFFFF}{CMBL}{CPU Mailbox L}{dddd dddd dddd dddd} \begin{RegisterBitDescriptions} -\RegisterBitDescription{15--0}{d}{R}{Bits 15--0 of the main memory address} +\RegisterBitDescription{15--0}{d}{R}{ + Bits 15--0 of mail sent from the CPU. Reading of this register by the DSP causes the \RegisterField{CMBH.M} + bit to be cleared. +} \end{RegisterBitDescriptions} -\RegisterBitOverview{0xFFCD}{DSPA}{DSP Address}{dddd dddd dddd dddd} +\textbf{Operation:} -\begin{RegisterBitDescriptions} -\RegisterBitDescription{15--0}{d}{W}{Bits 15--0 of the DSP memory address} -\end{RegisterBitDescriptions} +From the CPU side, software usually checks the \RegisterField{M} bit of \Register{CMBH}. It takes action only in the case that this bit is \Value{0}. +Said action is to write \Register{CMBH} first and then \Register{CMBL}. After writing to \Register{CMBL}, the mail is ready to be received by the DSP. -\RegisterBitOverview{0xFFCB}{DSBL}{DSP Address}{dddd dddd dddd dddd} - -\begin{RegisterBitDescriptions} -\RegisterBitDescription{15--0}{d}{W}{Length in bytes to transfer. Writing to this register starts a DMA transfer.} -\end{RegisterBitDescriptions} - -\RegisterBitOverview{0xFFC9}{DSCR}{DSP Address}{---- ---- ---- ----} - -\begin{RegisterBitDescriptions} -\RegisterBitDescription{15--0}{d}{W}{} -\end{RegisterBitDescriptions} - -\pagebreak{} - -\section{Accelerator} - -The accelerator is used to transfer data from accelerator memory (ARAM) to DSP memory. The accelerator area can be marked with \Register{ACSA} (start) and \Register{ACEA} (end) addresses. -Current address for the accelerator can be set or read from the \Register{ACCA} register. Reading from accelerator memory is done by reading from the \Register{ACDAT} register. -This register contains data from ARAM pointed to by the \Register{ACCA} register. -After reading the data, \Register{ACCA} is incremented by one. -After \Register{ACCA} grows bigger than the area pointed to by \Register{ACEA}, it gets reset to a value from \Register{ACSA} and the \Exception{ACCOV} interrupt is generated. +From the DSP side, the DSP loops by probing the \RegisterField{M} bit. When this bit is \Value{1}, the DSP reads \Register{CMBH} first and then \Register{CMBL}. +After reading \Register{CMBL}, \RegisterField{CMBH.M} will be cleared. \pagebreak{} @@ -858,36 +1046,53 @@ Opcode decoding uses special naming for bits and their decimal representations t \section{Conditional opcodes} Conditional opcodes are executed only when the condition described by their encoded conditional field has been met. -The groups of conditional instructions are, \Opcode{CALL}, \Opcode{JMP}, \Opcode{IF}, and \Opcode{RET}. +The groups of conditional instructions are: \Opcode{CALLcc}, \Opcode{Jcc}, \Opcode{IFcc}, \Opcode{RETcc}, \Opcode{RTIcc}, \Opcode{JRcc}, and \Opcode{CALLRcc}. \begin{table}[H] \centering \begin{tabular}{|l|l|l|l|} \hline \textbf{Bits} & \textbf{\texttt{cc}} & \textbf{Name} & \textbf{Evaluated expression} \\ \hline -\texttt{0b0000} & \texttt{GE} & Greater than or equal & \\ \hline -\texttt{0b0001} & \texttt{L} & Less than & \\ \hline -\texttt{0b0010} & \texttt{G} & Greater than & \\ \hline -\texttt{0b0011} & \texttt{LE} & Less than or equal & \\ \hline -\texttt{0b0100} & \texttt{NE} & Not equal & \texttt{(\$sr \& 0x4) == 0} \\ \hline -\texttt{0b0101} & \texttt{EQ} & Equal & \texttt{(\$sr \& 0x4) != 0} \\ \hline -\texttt{0b0110} & \texttt{NC} & Not carry & \texttt{(\$sr \& 0x1) == 0} \\ \hline -\texttt{0b0111} & \texttt{C} & Carry & \texttt{(\$sr \& 0x1) != 0} \\ \hline -\texttt{0b1000} & & Below s32 & \texttt{(\$sr \& 0x10) == 0} \\ \hline -\texttt{0b1001} & & Above s32 & \texttt{(\$sr \& 0x10) != 0} \\ \hline -\texttt{0b1010} & & & \\ \hline -\texttt{0b1011} & & & \\ \hline -\texttt{0b1100} & \texttt{NZ} & Not zero & \texttt{(\$sr \& 0x40) == 0} \\ \hline -\texttt{0b1101} & \texttt{ZR} & Zero & \texttt{(\$sr \& 0x40) != 0} \\ \hline -\texttt{0b1110} & \texttt{O} & Overflow & \texttt{(\$sr \& 0x2) != 0} \\ \hline -\texttt{0b1111} & & \textless always\textgreater & \\ \hline +\texttt{0b0000} & \texttt{GE} & Greater than or equal & \Code{\$sr.O == \$sr.S} \\ \hline +\texttt{0b0001} & \texttt{L} & Less than & \Code{\$sr.O != \$sr.S} \\ \hline +\texttt{0b0010} & \texttt{G} & Greater than & \Code{(\$sr.O == \$sr.S) \&\& (\$sr.Z == 0)} \\ \hline +\texttt{0b0011} & \texttt{LE} & Less than or equal & \Code{(\$sr.O != \$sr.S) || (\$sr.Z != 0)} \\ \hline +\texttt{0b0100} & \texttt{NZ} & Not zero & \Code{\$sr.Z == 0} \\ \hline +\texttt{0b0101} & \texttt{Z} & Zero & \Code{\$sr.Z != 0} \\ \hline +\texttt{0b0110} & \texttt{NC} & Not carry & \Code{\$sr.C == 0} \\ \hline +\texttt{0b0111} & \texttt{C} & Carry & \Code{\$sr.C != 0} \\ \hline +\texttt{0b1000} & \texttt{x8} & Below s32 & \Code{\$sr.AS == 0} \\ \hline +\texttt{0b1001} & \texttt{x9} & Above s32 & \Code{\$sr.AS != 0} \\ \hline +\texttt{0b1010} & \texttt{xA} & & \Code{((\$sr.AS != 0) || (\$sr.TB != 0)) \&\& (\$sr.Z == 0)} \\ \hline +\texttt{0b1011} & \texttt{xB} & & \Code{((\$sr.AS == 0) \&\& (\$sr.TB == 0)) || (\$sr.Z != 0)} \\ \hline +\texttt{0b1100} & \texttt{LNZ} & Not logic zero & \Code{\$sr.LZ == 0} \\ \hline +\texttt{0b1101} & \texttt{LZ} & Logic zero & \Code{\$sr.LZ != 0} \\ \hline +\texttt{0b1110} & \texttt{O} & Overflow & \Code{\$sr.O != 0} \\ \hline +\texttt{0b1111} & & \textless always\textgreater & \\ \hline \end{tabular} \end{table} \textbf{Note:} -There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and \texttt{ZR}/\texttt{NZ}. -\texttt{EQ}/\texttt{NE} pair operates on arithmetic zero flag (arithmetic 0) while \texttt{ZR}/\texttt{NZ} pair operates on logic zero flag (logic 0). +There are two pairs of conditions that work similarly: \texttt{Z}/\texttt{NZ} and \texttt{LZ}/\texttt{LNZ}. +\texttt{Z}/\texttt{NZ} pair operates on arithmetic zero flag (arithmetic 0) while \texttt{LZ}/\texttt{LNZ} pair operates on logic zero flag (logic 0). +The logic zero flag is only set by \Opcode{ANDCF} and \Opcode{ANDF}. + +\pagebreak{} + +\section{Flags} + +Most opcodes update flags in the status register (\Register{\$sr}) based on their result. (Extended opcodes do not update flags.) + +Overflow (\texttt{O}) occurs when the result has wrapped around. The expression $C = A + B$ has overflown if $A > 0$ and $B > 0$ but $C \le 0$ or if $A < 0$ and $B < 0$ but $C \ge 0$. Any instruction that sets the \texttt{O} flag will also set the \texttt{OS} flag; when the \texttt{O} flag is set, \texttt{OS} is also set, but \texttt{OS} is not cleared when \texttt{O} is cleared. + +Carry (\texttt{C}) occurs when an arithmetic carry occurs and should be added to the next most significant word. The expression $C = A + B$ generates a carry if $A > C$. The DSP uses different logic for subtraction: the expression $C = A - B$ generates a carry if $A \ge C$ (so if $B = 0$, a carry is generated for all $A$). This is because the DSP uses a carry flag, not a borrow flag. + +Each instruction has a table showing what flags it updates, such as this: + +\DSPOpcodeFlags{-}{-}{X}{X}{X}{X}{0}{0} + +A ``-'' indicates that the flag retains its previous value, a ``0'' indicates that the flag is set to 0, and a ``X'' indicates that the value of the flag changes depending on what the instruction did. \pagebreak{} @@ -895,6 +1100,30 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and \pagebreak{} +\begin{DSPOpcode}{ABS} + \begin{DSPOpcodeBytefield}{16} + \monobitbox{4}{1010} & \monobitbox{4}{d001} & \monobitbox{4}{xxxx} & \monobitbox{4}{xxxx} + \end{DSPOpcodeBytefield} + + \begin{DSPOpcodeFormat} + ABS $acD + \end{DSPOpcodeFormat} + + \begin{DSPOpcodeDescription} + \item Sets \Register{\$acD} to the absolute value of \Register{\$acD}. + \end{DSPOpcodeDescription} + + \begin{DSPOpcodeOperation} + IF $acD < 0 + $acD = -$acD + ENDIF + FLAGS($acD) + $pc++ + \end{DSPOpcodeOperation} + + \DSPOpcodeFlags{-}{-}{X}{X}{X}{X}{0}{0} +\end{DSPOpcode} + \begin{DSPOpcode}{ADD} \begin{DSPOpcodeBytefield}{16} \monobitbox{4}{0100} & \monobitbox{4}{110d} & \monobitbox{4}{xxxx} & \monobitbox{4}{xxxx} @@ -913,6 +1142,8 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and FLAGS($acD) $pc++ \end{DSPOpcodeOperation} + + \DSPOpcodeFlags{X}{-}{X}{X}{X}{X}{X}{X} \end{DSPOpcode} \begin{DSPOpcode}{ADDARN} @@ -932,6 +1163,8 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and $arD += $ixS $pc++ \end{DSPOpcodeOperation} + + \DSPOpcodeFlagsUnchanged \end{DSPOpcode} \begin{DSPOpcode}{ADDAX} @@ -952,6 +1185,8 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and FLAGS($acD) $pc++ \end{DSPOpcodeOperation} + + \DSPOpcodeFlags{X}{-}{X}{X}{X}{X}{X}{X} \end{DSPOpcode} \begin{DSPOpcode}{ADDAXL} @@ -965,6 +1200,7 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and \begin{DSPOpcodeDescription} \item Adds secondary accumulator \Register{\$axS.l} to accumulator register \Register{\$acD}. + \Register{\$axS.l} is treated as an unsigned value. \end{DSPOpcodeDescription} \begin{DSPOpcodeOperation} @@ -972,6 +1208,8 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and FLAGS($acD) $pc++ \end{DSPOpcodeOperation} + + \DSPOpcodeFlags{X}{-}{X}{X}{X}{X}{X}{X} \end{DSPOpcode} \begin{DSPOpcode}{ADDI} @@ -993,6 +1231,8 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and FLAGS($acD) $pc += 2 \end{DSPOpcodeOperation} + + \DSPOpcodeFlags{X}{-}{X}{X}{X}{X}{X}{X} \end{DSPOpcode} \begin{DSPOpcode}{ADDIS} @@ -1013,6 +1253,8 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and FLAGS($acD) $pc++ \end{DSPOpcodeOperation} + + \DSPOpcodeFlags{X}{-}{X}{X}{X}{X}{X}{X} \end{DSPOpcode} \begin{DSPOpcode}{ADDP} @@ -1033,6 +1275,8 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and FLAGS($acD) $pc++ \end{DSPOpcodeOperation} + + \DSPOpcodeFlags{X}{-}{X}{X}{X}{X}{X}{X} \end{DSPOpcode} \begin{DSPOpcode}{ADDPAXZ} @@ -1055,6 +1299,8 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and FLAGS($acD) $pc++ \end{DSPOpcodeOperation} + + \DSPOpcodeFlags{-}{-}{X}{X}{X}{X}{0}{X} \end{DSPOpcode} \begin{DSPOpcode}{ADDR} @@ -1071,15 +1317,17 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and \end{DSPOpcodeDescription} \begin{DSPOpcodeOperation} - $acD += $(0x18+S) + $acD += ($(0x18+S) << 16) FLAGS($acD) $pc++ \end{DSPOpcodeOperation} + + \DSPOpcodeFlags{X}{-}{X}{X}{X}{X}{X}{X} \end{DSPOpcode} \begin{DSPOpcode}{ANDC} \begin{DSPOpcodeBytefield}{16} - \monobitbox{4}{0011} & \monobitbox{4}{110d} & \monobitbox{4}{xxxx} & \monobitbox{4}{xxxx} + \monobitbox{4}{0011} & \monobitbox{4}{110d} & \monobitbox{4}{0xxx} & \monobitbox{4}{xxxx} \end{DSPOpcodeBytefield} \begin{DSPOpcodeFormat} @@ -1095,11 +1343,17 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and FLAGS($acD) $pc++ \end{DSPOpcodeOperation} + + \begin{DSPOpcodeNote} + \item The main opcode is 9 bits and the extension opcode is 7 bits. The extension opcode is treated as if the 8th bit was 0 (i.e. it is \texttt{0xxxxxxx}). + \end{DSPOpcodeNote} + + \DSPOpcodeFlags{-}{-}{X}{X}{X}{X}{0}{0} \end{DSPOpcode} \begin{DSPOpcode}{ANDCF} \begin{DSPOpcodeBytefield}{16} - \monobitbox{4}{0000} & \monobitbox{4}{001r} & \monobitbox{4}{1010} & \monobitbox{4}{0000} \\ + \monobitbox{4}{0000} & \monobitbox{4}{001r} & \monobitbox{4}{1100} & \monobitbox{4}{0000} \\ \monobitbox{4}{iiii} & \monobitbox{4}{iiii} & \monobitbox{4}{iiii} & \monobitbox{4}{iiii} \end{DSPOpcodeBytefield} @@ -1121,11 +1375,13 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and ENDIF $pc += 2 \end{DSPOpcodeOperation} + + \DSPOpcodeFlags{-}{X}{-}{-}{-}{-}{-}{-} \end{DSPOpcode} \begin{DSPOpcode}{ANDF} \begin{DSPOpcodeBytefield}{16} - \monobitbox{4}{0000} & \monobitbox{4}{001r} & \monobitbox{4}{1100} & \monobitbox{4}{0000} \\ + \monobitbox{4}{0000} & \monobitbox{4}{001r} & \monobitbox{4}{1010} & \monobitbox{4}{0000} \\ \monobitbox{4}{iiii} & \monobitbox{4}{iiii} & \monobitbox{4}{iiii} & \monobitbox{4}{iiii} \end{DSPOpcodeBytefield} @@ -1147,6 +1403,8 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and ENDIF $pc += 2 \end{DSPOpcodeOperation} + + \DSPOpcodeFlags{-}{X}{-}{-}{-}{-}{-}{-} \end{DSPOpcode} \begin{DSPOpcode}{ANDI} @@ -1168,11 +1426,13 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and FLAGS($acD) $pc += 2 \end{DSPOpcodeOperation} + + \DSPOpcodeFlags{-}{-}{X}{X}{X}{X}{0}{0} \end{DSPOpcode} \begin{DSPOpcode}{ANDR} \begin{DSPOpcodeBytefield}{16} - \monobitbox{4}{0011} & \monobitbox{4}{01sd} & \monobitbox{4}{xxxx} & \monobitbox{4}{xxxx} + \monobitbox{4}{0011} & \monobitbox{4}{01sd} & \monobitbox{4}{0xxx} & \monobitbox{4}{xxxx} \end{DSPOpcodeBytefield} \begin{DSPOpcodeFormat} @@ -1188,6 +1448,12 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and FLAGS($acD) $pc++ \end{DSPOpcodeOperation} + + \begin{DSPOpcodeNote} + \item The main opcode is 9 bits and the extension opcode is 7 bits. The extension opcode is treated as if the 8th bit was 0 (i.e. it is \texttt{0xxxxxxx}). + \end{DSPOpcodeNote} + + \DSPOpcodeFlags{-}{-}{X}{X}{X}{X}{0}{0} \end{DSPOpcode} \begin{DSPOpcode}{ASL} @@ -1205,9 +1471,11 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and \begin{DSPOpcodeOperation} $acR <<= I - FLAGS($acD) + FLAGS($acR) $pc++ \end{DSPOpcodeOperation} + + \DSPOpcodeFlags{-}{-}{X}{X}{X}{X}{0}{0} \end{DSPOpcode} \begin{DSPOpcode}{ASR} @@ -1224,10 +1492,106 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and \end{DSPOpcodeDescription} \begin{DSPOpcodeOperation} - $acR >>= I + IF I != 0 + $acR >>= (64 - I) + ENDIF + FLAGS($acR) + $pc++ + \end{DSPOpcodeOperation} + + \DSPOpcodeFlags{-}{-}{X}{X}{X}{X}{0}{0} +\end{DSPOpcode} + +\begin{DSPOpcode}{ASRN} + \begin{DSPOpcodeBytefield}{16} + \monobitbox{4}{0000} & \monobitbox{4}{0010} & \monobitbox{4}{1101} & \monobitbox{4}{1011} + \end{DSPOpcodeBytefield} + + \begin{DSPOpcodeFormat} + ASRN + \end{DSPOpcodeFormat} + + \begin{DSPOpcodeDescription} + \item Arithmetically shifts accumulator \Register{\$ac0} either left or right based on \Register{\$ac1.m}: if bit 6 is set, a right by the amount calculated by negating sign-extended bits 0--5 occurs, while if bit 6 is clear, a left shift occurs by bits 0--5. + \end{DSPOpcodeDescription} + + \begin{DSPOpcodeOperation} + IF (ac1.m & 64) + IF (ac1.m & 63) != 0 + $ac0 >>= (64 - (ac1.m & 63)) + ENDIF + ELSE + $ac0 <<= ac1.m + ENDIF + FLAGS($ac0) + $pc++ + \end{DSPOpcodeOperation} + + \DSPOpcodeFlags{-}{-}{X}{X}{X}{X}{0}{0} +\end{DSPOpcode} + +\begin{DSPOpcode}{ASRNR} + \begin{DSPOpcodeBytefield}{16} + \monobitbox{4}{0011} & \monobitbox{4}{111d} & \monobitbox{4}{1xxx} & \monobitbox{4}{xxxx} + \end{DSPOpcodeBytefield} + + \begin{DSPOpcodeFormat} + ASRNR $acD + \end{DSPOpcodeFormat} + + \begin{DSPOpcodeDescription} + \item Arithmetically shifts accumulator \Register{\$acD} either left or right based on \Register{\$ac(1-D).m}: if bit 6 is set, a right by the amount calculated by negating sign-extended bits 0--5 occurs, while if bit 6 is clear, a left shift occurs by bits 0--5. + \end{DSPOpcodeDescription} + + \begin{DSPOpcodeOperation} + IF (ac(1-D).m & 64) + IF (ac(1-D).m & 63) != 0 + $acD >>= (64 - (ac(1-D).m & 63)) + ENDIF + ELSE + $acD <<= ac(1-D).m + ENDIF FLAGS($acD) $pc++ \end{DSPOpcodeOperation} + + \begin{DSPOpcodeNote} + \item The main opcode is 9 bits and the extension opcode is 7 bits. The extension opcode is treated as if the 8th bit was 0 (i.e. it is \texttt{0xxxxxxx}). + \end{DSPOpcodeNote} + + \DSPOpcodeFlags{-}{-}{X}{X}{X}{X}{0}{0} +\end{DSPOpcode} + +\begin{DSPOpcode}{ASRNRX} + \begin{DSPOpcodeBytefield}{16} + \monobitbox{4}{0011} & \monobitbox{4}{10sd} & \monobitbox{4}{1xxx} & \monobitbox{4}{xxxx} + \end{DSPOpcodeBytefield} + + \begin{DSPOpcodeFormat} + ASRNRX $acD, $axS.h + \end{DSPOpcodeFormat} + + \begin{DSPOpcodeDescription} + \item Arithmetically shifts accumulator \Register{\$acD} either left or right based on \Register{\$axS.h}: if bit 6 is set, a right by the amount calculated by negating sign-extended bits 0--5 occurs, while if bit 6 is clear, a left shift occurs by bits 0--5. + \end{DSPOpcodeDescription} + + \begin{DSPOpcodeOperation} + IF (axS.h & 64) + IF (axS.h & 63) != 0 + $acD >>= (64 - (axS.h & 63)) + ENDIF + ELSE + $acD <<= axS.h + ENDIF + FLAGS($acD) + $pc++ + \end{DSPOpcodeOperation} + + \begin{DSPOpcodeNote} + \item The main opcode is 9 bits and the extension opcode is 7 bits. The extension opcode is treated as if the 8th bit was 0 (i.e. it is \texttt{0xxxxxxx}). + \end{DSPOpcodeNote} + + \DSPOpcodeFlags{-}{-}{X}{X}{X}{X}{0}{0} \end{DSPOpcode} \begin{DSPOpcode}{ASR16} @@ -1245,9 +1609,11 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and \begin{DSPOpcodeOperation} $acR >>= 16 - FLAGS($acD) + FLAGS($acR) $pc++ \end{DSPOpcodeOperation} + + \DSPOpcodeFlags{-}{-}{X}{X}{X}{X}{0}{0} \end{DSPOpcode} \begin{DSPOpcode}{BLOOP} @@ -1284,6 +1650,8 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and $pc = addrA + 1 // Remove values from stack \end{DSPOpcodeOperation} + + \DSPOpcodeFlagsUnchanged \end{DSPOpcode} \begin{DSPOpcode}{BLOOPI} @@ -1320,6 +1688,8 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and $pc = addrA + 1 // Remove values from stack \end{DSPOpcodeOperation} + + \DSPOpcodeFlagsUnchanged \end{DSPOpcode} \begin{DSPOpcode}{CALL} @@ -1343,6 +1713,8 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and $st0 = $pc + 2 $pc = addressA \end{DSPOpcodeOperation} + + \DSPOpcodeFlagsUnchanged \end{DSPOpcode} \begin{DSPOpcode}{CALLcc} @@ -1371,6 +1743,8 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and $pc += 2 ENDIF \end{DSPOpcodeOperation} + + \DSPOpcodeFlagsUnchanged \end{DSPOpcode} \begin{DSPOpcode}{CALLR} @@ -1392,6 +1766,61 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and $st0 = $pc + 1 $pc = $R \end{DSPOpcodeOperation} + + \DSPOpcodeFlagsUnchanged +\end{DSPOpcode} + +\begin{DSPOpcode}{CALLRcc} + \begin{DSPOpcodeBytefield}{16} + \monobitbox{4}{0001} & \monobitbox{4}{0111} & \monobitbox{4}{rrr1} & \monobitbox{4}{cccc} + \end{DSPOpcodeBytefield} + + \begin{DSPOpcodeFormat} + CALLRcc $R + \end{DSPOpcodeFormat} + + \begin{DSPOpcodeDescription} + \item Call function if condition \Flag{cc} has been met. Push program counter of the instruction following ``call'' to call stack \Register{\$st0}. + Set program counter to register \Register{\$R}. + \end{DSPOpcodeDescription} + + \begin{DSPOpcodeOperation} + IF (cc) + PUSH_STACK($st0) + $st0 = $pc + 1 + $pc = $R + ELSE + $pc++ + ENDIF + \end{DSPOpcodeOperation} + + \DSPOpcodeFlagsUnchanged +\end{DSPOpcode} + + +\begin{DSPOpcode}{CLR15} + \begin{DSPOpcodeBytefield}{16} + \monobitbox{4}{1000} & \monobitbox{4}{1100} & \monobitbox{4}{xxxx} & \monobitbox{4}{xxxx} + \end{DSPOpcodeBytefield} + + \begin{DSPOpcodeFormat} + CLR15 + \end{DSPOpcodeFormat} + + \begin{DSPOpcodeDescription} + \item Sets \RegisterField{\$sr.SU} (bit 15) to 0, causing multiplication to treat its operands as signed. + \end{DSPOpcodeDescription} + + \begin{DSPOpcodeOperation} + $sr &= ~0x8000 + $pc++ + \end{DSPOpcodeOperation} + + \begin{DSPOpcodeSeeAlso} + \item \Opcode{SET15} + \end{DSPOpcodeSeeAlso} + + \DSPOpcodeFlagsUnchanged \end{DSPOpcode} \begin{DSPOpcode}{CLR} @@ -1412,6 +1841,8 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and FLAGS($acR) $pc++ \end{DSPOpcodeOperation} + + \DSPOpcodeFlags{-}{-}{1}{0}{0}{1}{0}{0} \end{DSPOpcode} \begin{DSPOpcode}{CLRL} @@ -1424,14 +1855,24 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and \end{DSPOpcodeFormat} \begin{DSPOpcodeDescription} - \item Clears \Register{\$acR.l} - low 16 bits of accumulator \Register{\$acR}. + \item Rounds \Register{\$acR} such that \Register{\$acR.l} is 0. This is a round-to-even operation. \end{DSPOpcodeDescription} \begin{DSPOpcodeOperation} - $acR.l = 0 + IF ($acR & 0x10000) != 0 + $acR = ($acR + 0x8000) & ~0xffff + ELSE + $acR = ($acR + 0x7fff) & ~0xffff + ENDIF FLAGS($acR) $pc++ \end{DSPOpcodeOperation} + + \begin{DSPOpcodeNote} + \item An alternative interpretation is that if \Register{\$acR.m} is odd, then increment \Register{\$acsR} if \Register{\$acR.l} is greater than or equal to \Value{0x8000}; if \Register{\$acR.m} is even, then increment \Register{\$acsR} if \Register{\$acR.l} is greater than or equal to \Value{0x7fff}. Afterwards set \Register{\$acR.l} to 0. + \end{DSPOpcodeNote} + + \DSPOpcodeFlags{-}{-}{X}{X}{X}{X}{0}{0} \end{DSPOpcode} \begin{DSPOpcode}{CLRP} @@ -1461,6 +1902,8 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and $prod.m2 = 0x0010 \end{lstlisting} \end{DSPOpcodeNote} + + \DSPOpcodeFlagsUnchanged \end{DSPOpcode} \begin{DSPOpcode}{CMP} @@ -1480,6 +1923,29 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and $sr = FLAGS($ac0 - $ac1) $pc++ \end{DSPOpcodeOperation} + + \DSPOpcodeFlags{X}{-}{X}{X}{X}{X}{X}{X} +\end{DSPOpcode} + +\begin{DSPOpcode}{CMPAR} + \begin{DSPOpcodeBytefield}{16} + \monobitbox{4}{110r} & \monobitbox{4}{s001} & \monobitbox{4}{xxxx} & \monobitbox{4}{xxxx} + \end{DSPOpcodeBytefield} + + \begin{DSPOpcodeFormat} + CMPAR $acS $axR.h + \end{DSPOpcodeFormat} + + \begin{DSPOpcodeDescription} + \item Compares accumulator \Register{\$acS} with accumulator \Register{\$axR.h}. + \end{DSPOpcodeDescription} + + \begin{DSPOpcodeOperation} + $sr = FLAGS($acS - ($axR.h << 16)) + $pc++ + \end{DSPOpcodeOperation} + + \DSPOpcodeFlags{X}{-}{X}{X}{X}{X}{X}{X} \end{DSPOpcode} \begin{DSPOpcode}{CMPI} @@ -1498,10 +1964,11 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and \end{DSPOpcodeDescription} \begin{DSPOpcodeOperation} - res = ($acD.hm - I) | $acD.l - FLAGS(res) + FLAGS($acD - (I << 16)) $pc += 2 \end{DSPOpcodeOperation} + + \DSPOpcodeFlags{X}{-}{X}{X}{X}{X}{X}{X} \end{DSPOpcode} \begin{DSPOpcode}{CMPIS} @@ -1519,9 +1986,11 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and \end{DSPOpcodeDescription} \begin{DSPOpcodeOperation} - FLAGS($acD - #I) + FLAGS($acD - (I << 16)) $pc++ \end{DSPOpcodeOperation} + + \DSPOpcodeFlags{X}{-}{X}{X}{X}{X}{X}{X} \end{DSPOpcode} \begin{DSPOpcode}{DAR} @@ -1541,6 +2010,8 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and $arD-- $pc++ \end{DSPOpcodeOperation} + + \DSPOpcodeFlagsUnchanged \end{DSPOpcode} \begin{DSPOpcode}{DEC} @@ -1561,6 +2032,8 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and FLAGS($acD) $pc++ \end{DSPOpcodeOperation} + + \DSPOpcodeFlags{X}{-}{X}{X}{X}{X}{X}{X} \end{DSPOpcode} \begin{DSPOpcode}{DECM} @@ -1581,11 +2054,13 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and FLAGS($acD) $pc++ \end{DSPOpcodeOperation} + + \DSPOpcodeFlags{X}{-}{X}{X}{X}{X}{X}{X} \end{DSPOpcode} \begin{DSPOpcode}{HALT} \begin{DSPOpcodeBytefield}{16} - \monobitbox{4}{0000} & \monobitbox{4}{0000} & \monobitbox{4}{0020} & \monobitbox{4}{0001} + \monobitbox{4}{0000} & \monobitbox{4}{0000} & \monobitbox{4}{0010} & \monobitbox{4}{0001} \end{DSPOpcodeBytefield} \begin{DSPOpcodeFormat} @@ -1599,6 +2074,8 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and \begin{DSPOpcodeOperation} DREG_CR |= DSP_CR_HALT; \end{DSPOpcodeOperation} + + \DSPOpcodeFlagsUnchanged \end{DSPOpcode} \begin{DSPOpcode}{IAR} @@ -1618,6 +2095,8 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and $arD++ $pc++ \end{DSPOpcodeOperation} + + \DSPOpcodeFlagsUnchanged \end{DSPOpcode} \begin{DSPOpcode}{IFcc} @@ -1640,6 +2119,8 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and $pc += 2 ENDIF \end{DSPOpcodeOperation} + + \DSPOpcodeFlagsUnchanged \end{DSPOpcode} \begin{DSPOpcode}{ILRR} @@ -1660,6 +2141,8 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and $acD.m = MEM[$arS] $pc++ \end{DSPOpcodeOperation} + + \DSPOpcodeFlagsUnchanged \end{DSPOpcode} \begin{DSPOpcode}{ILRRD} @@ -1681,6 +2164,8 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and $arS-- $pc++ \end{DSPOpcodeOperation} + + \DSPOpcodeFlagsUnchanged \end{DSPOpcode} \begin{DSPOpcode}{ILRRI} @@ -1702,6 +2187,8 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and $arS++ $pc++ \end{DSPOpcodeOperation} + + \DSPOpcodeFlagsUnchanged \end{DSPOpcode} \begin{DSPOpcode}{ILRRN} @@ -1724,6 +2211,8 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and $arS += $ixS $pc++ \end{DSPOpcodeOperation} + + \DSPOpcodeFlagsUnchanged \end{DSPOpcode} \begin{DSPOpcode}{INC} @@ -1744,6 +2233,8 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and FLAGS($acD) $pc++ \end{DSPOpcodeOperation} + + \DSPOpcodeFlags{X}{-}{X}{X}{X}{X}{X}{X} \end{DSPOpcode} \begin{DSPOpcode}{INCM} @@ -1764,6 +2255,8 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and FLAGS($acD) $pc++ \end{DSPOpcodeOperation} + + \DSPOpcodeFlags{X}{-}{X}{X}{X}{X}{X}{X} \end{DSPOpcode} \begin{DSPOpcode}{JMP} @@ -1784,6 +2277,8 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and \begin{DSPOpcodeOperation} $pc = addressA \end{DSPOpcodeOperation} + + \DSPOpcodeFlagsUnchanged \end{DSPOpcode} \begin{DSPOpcode}{Jcc} @@ -1808,6 +2303,8 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and $pc += 2 ENDIF \end{DSPOpcodeOperation} + + \DSPOpcodeFlagsUnchanged \end{DSPOpcode} \begin{DSPOpcode}{JMPR} @@ -1826,6 +2323,32 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and \begin{DSPOpcodeOperation} $pc = $R \end{DSPOpcodeOperation} + + \DSPOpcodeFlagsUnchanged +\end{DSPOpcode} + +\begin{DSPOpcode}{JRcc} + \begin{DSPOpcodeBytefield}{16} + \monobitbox{4}{0001} & \monobitbox{4}{0111} & \monobitbox{4}{rrr0} & \monobitbox{4}{cccc} + \end{DSPOpcodeBytefield} + + \begin{DSPOpcodeFormat} + JRcc $R + \end{DSPOpcodeFormat} + + \begin{DSPOpcodeDescription} + \item Jump to address if condition \Flag{cc} has been met; set program counter to a value from register \Register{\$R}. + \end{DSPOpcodeDescription} + + \begin{DSPOpcodeOperation} + IF (cc) + $pc = $R + ELSE + $pc++ + ENDIF + \end{DSPOpcodeOperation} + + \DSPOpcodeFlagsUnchanged \end{DSPOpcode} \begin{DSPOpcode}{LOOP} @@ -1850,6 +2373,8 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and END $pc += 2 \end{DSPOpcodeOperation} + + \DSPOpcodeFlagsUnchanged \end{DSPOpcode} \begin{DSPOpcode}{LOOPI} @@ -1874,6 +2399,8 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and END $pc += 2 \end{DSPOpcodeOperation} + + \DSPOpcodeFlagsUnchanged \end{DSPOpcode} \begin{DSPOpcode}{LR} @@ -1895,6 +2422,8 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and $D = MEM[M] $pc += 2 \end{DSPOpcodeOperation} + + \DSPOpcodeFlagsUnchanged \end{DSPOpcode} \begin{DSPOpcode}{LRI} @@ -1909,13 +2438,15 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and \begin{DSPOpcodeDescription} \item Load immediate value \Value{I} to register \Register{\$D}. - Perform and additional operation depending on destination register. + Perform an additional operation depending on destination register. \end{DSPOpcodeDescription} \begin{DSPOpcodeOperation} $D = I $pc += 2 \end{DSPOpcodeOperation} + + \DSPOpcodeFlagsUnchanged \end{DSPOpcode} \begin{DSPOpcode}{LRIS} @@ -1936,6 +2467,8 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and $(0x18+D) = I $pc++ \end{DSPOpcodeOperation} + + \DSPOpcodeFlagsUnchanged \end{DSPOpcode} \begin{DSPOpcode}{LRR} @@ -1956,6 +2489,8 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and $D = MEM[$arS] $pc++ \end{DSPOpcodeOperation} + + \DSPOpcodeFlagsUnchanged \end{DSPOpcode} \begin{DSPOpcode}{LRRD} @@ -1970,7 +2505,7 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and \begin{DSPOpcodeDescription} \item Move value from data memory pointed by addressing register \Register{\$arS} to register \Register{\$D}. Decrements register \Register{\$arS}. - Perform additional operation depending on destination register. + Perform an additional operation depending on destination register. \end{DSPOpcodeDescription} \begin{DSPOpcodeOperation} @@ -1978,6 +2513,8 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and $arS-- $pc++ \end{DSPOpcodeOperation} + + \DSPOpcodeFlagsUnchanged \end{DSPOpcode} \begin{DSPOpcode}{LRRI} @@ -1992,7 +2529,7 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and \begin{DSPOpcodeDescription} \item Move value from data memory pointed by addressing register \Register{\$arS} to register \Register{\$D}. Increments register \Register{\$arS}. - Perform additional operation depending on destination register. + Perform an additional operation depending on destination register. \end{DSPOpcodeDescription} \begin{DSPOpcodeOperation} @@ -2000,6 +2537,8 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and $arS++ $pc++ \end{DSPOpcodeOperation} + + \DSPOpcodeFlagsUnchanged \end{DSPOpcode} \begin{DSPOpcode}{LRRN} @@ -2014,7 +2553,7 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and \begin{DSPOpcodeDescription} \item Move value from data memory pointed by addressing register \Register{\$arS} to register \Register{\$D}. Add indexing register \Register{\$ixS} to register \Register{\$arS}. - Perform additional operation depending on destination register. + Perform an additional operation depending on destination register. \end{DSPOpcodeDescription} \begin{DSPOpcodeOperation} @@ -2022,6 +2561,8 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and $arS += $ixS $pc++ \end{DSPOpcodeOperation} + + \DSPOpcodeFlagsUnchanged \end{DSPOpcode} \begin{DSPOpcode}{LRS} @@ -2034,14 +2575,20 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and \end{DSPOpcodeFormat} \begin{DSPOpcodeDescription} - \item Move value from data memory pointed by address \Address{M} (8-bit sign-extended) to register \Register{\$(0x18+D)}. - Perform additional operation depending on destination register. + \item Move value from data memory pointed by address \Address{(\$cr << 8) | M} to register \Register{\$(0x18+D)}. + Perform an additional operation depending on destination register. \end{DSPOpcodeDescription} \begin{DSPOpcodeOperation} - $(0x18+D) = MEM[M] + $(0x18+D) = MEM[($cr << 8) | M] $pc++ \end{DSPOpcodeOperation} + + \begin{DSPOpcodeNote} + \item \Opcode{LRS} can use \Register{\$axD} and cannot use \Register{\$acS.h}, while \Opcode{SRS} and \Opcode{SRSH} only work on \Register{\$acS}. + \end{DSPOpcodeNote} + + \DSPOpcodeFlagsUnchanged \end{DSPOpcode} \begin{DSPOpcode}{LSL} @@ -2059,9 +2606,11 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and \begin{DSPOpcodeOperation} $acR <<= I - FLAGS($acD) + FLAGS($acR) $pc++ \end{DSPOpcodeOperation} + + \DSPOpcodeFlags{-}{-}{X}{X}{X}{X}{0}{0} \end{DSPOpcode} \begin{DSPOpcode}{LSL16} @@ -2079,9 +2628,11 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and \begin{DSPOpcodeOperation} $acR <<= 16 - FLAGS($acD) + FLAGS($acR) $pc++ \end{DSPOpcodeOperation} + + \DSPOpcodeFlags{-}{-}{X}{X}{X}{X}{0}{0} \end{DSPOpcode} \begin{DSPOpcode}{LSR} @@ -2098,10 +2649,106 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and \end{DSPOpcodeDescription} \begin{DSPOpcodeOperation} - $acR >>= I + IF I != 0 + $acR >>= (64 - I) + ENDIF + FLAGS($acR) + $pc++ + \end{DSPOpcodeOperation} + + \DSPOpcodeFlags{-}{-}{X}{X}{X}{X}{0}{0} +\end{DSPOpcode} + +\begin{DSPOpcode}{LSRN} + \begin{DSPOpcodeBytefield}{16} + \monobitbox{4}{0000} & \monobitbox{4}{0010} & \monobitbox{4}{1100} & \monobitbox{4}{1010} + \end{DSPOpcodeBytefield} + + \begin{DSPOpcodeFormat} + LSRN + \end{DSPOpcodeFormat} + + \begin{DSPOpcodeDescription} + \item Logically shifts accumulator \Register{\$ac0} either left or right based on \Register{\$ac1.m}: if bit 6 is set, a right by the amount calculated by negating sign-extended bits 0--5 occurs, while if bit 6 is clear, a left shift occurs by bits 0--5. + \end{DSPOpcodeDescription} + + \begin{DSPOpcodeOperation} + IF (ac1.m & 64) + IF (ac1.m & 63) != 0 + $ac0 >>= (64 - (ac1.m & 63)) + ENDIF + ELSE + $ac0 <<= ac1.m + ENDIF + FLAGS($ac0) + $pc++ + \end{DSPOpcodeOperation} + + \DSPOpcodeFlags{-}{-}{X}{X}{X}{X}{0}{0} +\end{DSPOpcode} + +\begin{DSPOpcode}{LSRNR} + \begin{DSPOpcodeBytefield}{16} + \monobitbox{4}{0011} & \monobitbox{4}{110d} & \monobitbox{4}{1xxx} & \monobitbox{4}{xxxx} + \end{DSPOpcodeBytefield} + + \begin{DSPOpcodeFormat} + LSRNR $acD + \end{DSPOpcodeFormat} + + \begin{DSPOpcodeDescription} + \item Logically shifts accumulator \Register{\$acD} either left or right based on \Register{\$ac(1-D).m}: if bit 6 is set, a right by the amount calculated by negating sign-extended bits 0--5 occurs, while if bit 6 is clear, a left shift occurs by bits 0--5. + \end{DSPOpcodeDescription} + + \begin{DSPOpcodeOperation} + IF (ac(1-D).m & 64) + IF (ac(1-D).m & 63) != 0 + $acD >>= (64 - (ac(1-D).m & 63)) + ENDIF + ELSE + $acD <<= ac(1-D).m + ENDIF FLAGS($acD) $pc++ \end{DSPOpcodeOperation} + + \begin{DSPOpcodeNote} + \item The main opcode is 9 bits and the extension opcode is 7 bits. The extension opcode is treated as if the 8th bit was 0 (i.e. it is \texttt{0xxxxxxx}). + \end{DSPOpcodeNote} + + \DSPOpcodeFlags{-}{-}{X}{X}{X}{X}{0}{0} +\end{DSPOpcode} + +\begin{DSPOpcode}{LSRNRX} + \begin{DSPOpcodeBytefield}{16} + \monobitbox{4}{0011} & \monobitbox{4}{01sd} & \monobitbox{4}{1xxx} & \monobitbox{4}{xxxx} + \end{DSPOpcodeBytefield} + + \begin{DSPOpcodeFormat} + LSRNRX $acD, $axS.h + \end{DSPOpcodeFormat} + + \begin{DSPOpcodeDescription} + \item Logically shifts accumulator \Register{\$acD} either left or right based on \Register{\$axS.h}: if bit 6 is set, a right by the amount calculated by negating sign-extended bits 0--5 occurs, while if bit 6 is clear, a left shift occurs by bits 0--5. + \end{DSPOpcodeDescription} + + \begin{DSPOpcodeOperation} + IF (axS.h & 64) + IF (axS.h & 63) != 0 + $acD >>= (64 - (axS.h & 63)) + ENDIF + ELSE + $acD <<= axS.h + ENDIF + FLAGS($acD) + $pc++ + \end{DSPOpcodeOperation} + + \begin{DSPOpcodeNote} + \item The main opcode is 9 bits and the extension opcode is 7 bits. The extension opcode is treated as if the 8th bit was 0 (i.e. it is \texttt{0xxxxxxx}). + \end{DSPOpcodeNote} + + \DSPOpcodeFlags{-}{-}{X}{X}{X}{X}{0}{0} \end{DSPOpcode} \begin{DSPOpcode}{LSR16} @@ -2119,9 +2766,61 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and \begin{DSPOpcodeOperation} $acR >>= 16 - FLAGS($acD) + FLAGS($acR) $pc++ \end{DSPOpcodeOperation} + + \DSPOpcodeFlags{-}{-}{X}{X}{X}{X}{0}{0} +\end{DSPOpcode} + +\begin{DSPOpcode}{M0} + \begin{DSPOpcodeBytefield}{16} + \monobitbox{4}{1000} & \monobitbox{4}{1011} & \monobitbox{4}{xxxx} & \monobitbox{4}{xxxx} + \end{DSPOpcodeBytefield} + + \begin{DSPOpcodeFormat} + M0 + \end{DSPOpcodeFormat} + + \begin{DSPOpcodeDescription} + \item Sets \RegisterField{\$sr.AM} (bit 13) to 1, \textbf{disabling} the functionality that doubles the result of every multiply operation. + \end{DSPOpcodeDescription} + + \begin{DSPOpcodeOperation} + $sr |= 0x2000 + $pc++ + \end{DSPOpcodeOperation} + + \begin{DSPOpcodeSeeAlso} + \item \Opcode{M2} + \end{DSPOpcodeSeeAlso} + + \DSPOpcodeFlagsUnchanged +\end{DSPOpcode} + +\begin{DSPOpcode}{M2} + \begin{DSPOpcodeBytefield}{16} + \monobitbox{4}{1000} & \monobitbox{4}{1010} & \monobitbox{4}{xxxx} & \monobitbox{4}{xxxx} + \end{DSPOpcodeBytefield} + + \begin{DSPOpcodeFormat} + M2 + \end{DSPOpcodeFormat} + + \begin{DSPOpcodeDescription} + \item Sets \RegisterField{\$sr.AM} (bit 13) to 0, \textbf{enabling} the functionality that doubles the result of every multiply operation. + \end{DSPOpcodeDescription} + + \begin{DSPOpcodeOperation} + $sr &= ~0x2000 + $pc++ + \end{DSPOpcodeOperation} + + \begin{DSPOpcodeSeeAlso} + \item \Opcode{M0} + \end{DSPOpcodeSeeAlso} + + \DSPOpcodeFlagsUnchanged \end{DSPOpcode} \begin{DSPOpcode}{MADD} @@ -2146,6 +2845,8 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and \begin{DSPOpcodeSeeAlso} \item \RegisterField{\$sr.AM} bit affects multiply result. \end{DSPOpcodeSeeAlso} + + \DSPOpcodeFlagsUnchanged \end{DSPOpcode} \begin{DSPOpcode}{MADDC} @@ -2154,7 +2855,7 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and \end{DSPOpcodeBytefield} \begin{DSPOpcodeFormat} - MADDC $acS.l, $axT.h + MADDC $acS.m, $axT.h \end{DSPOpcodeFormat} \begin{DSPOpcodeDescription} @@ -2163,13 +2864,15 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and \end{DSPOpcodeDescription} \begin{DSPOpcodeOperation} - $prod += $acS.l * $axT.h + $prod += $acS.m * $axT.h $pc++ \end{DSPOpcodeOperation} \begin{DSPOpcodeSeeAlso} \item \RegisterField{\$sr.AM} bit affects multiply result. \end{DSPOpcodeSeeAlso} + + \DSPOpcodeFlagsUnchanged \end{DSPOpcode} \begin{DSPOpcode}{MADDX} @@ -2194,6 +2897,8 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and \begin{DSPOpcodeSeeAlso} \item \RegisterField{\$sr.AM} bit affects multiply result. \end{DSPOpcodeSeeAlso} + + \DSPOpcodeFlagsUnchanged \end{DSPOpcode} \begin{DSPOpcode}{MOV} @@ -2206,14 +2911,16 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and \end{DSPOpcodeFormat} \begin{DSPOpcodeDescription} - \item Moves accumulator \Register{\$ax(1-D)} to accumulator \Register{\$axD}. + \item Moves accumulator \Register{\$ac(1-D)} to accumulator \Register{\$acD}. \end{DSPOpcodeDescription} \begin{DSPOpcodeOperation} - $acD = $ax(1-D) + $acD = $ac(1-D) FLAGS($acD) $pc++ \end{DSPOpcodeOperation} + + \DSPOpcodeFlags{-}{-}{X}{0}{X}{X}{0}{0} \end{DSPOpcode} \begin{DSPOpcode}{MOVAX} @@ -2226,7 +2933,7 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and \end{DSPOpcodeFormat} \begin{DSPOpcodeDescription} - \item Moves secondary accumulator \Register{\$axS} to accumulator \Register{\$axD}. + \item Moves secondary accumulator \Register{\$axS} to accumulator \Register{\$acD}. \end{DSPOpcodeDescription} \begin{DSPOpcodeOperation} @@ -2234,6 +2941,8 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and FLAGS($acD) $pc++ \end{DSPOpcodeOperation} + + \DSPOpcodeFlags{-}{-}{X}{X}{X}{X}{0}{0} \end{DSPOpcode} \begin{DSPOpcode}{MOVNP} @@ -2254,6 +2963,8 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and FLAGS($acD) $pc++ \end{DSPOpcodeOperation} + + \DSPOpcodeFlags{-}{-}{X}{X}{X}{X}{0}{X} \end{DSPOpcode} \begin{DSPOpcode}{MOVP} @@ -2274,6 +2985,8 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and FLAGS($acD) $pc++ \end{DSPOpcodeOperation} + + \DSPOpcodeFlags{-}{-}{X}{X}{X}{X}{0}{X} \end{DSPOpcode} \begin{DSPOpcode}{MOVPZ} @@ -2295,6 +3008,8 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and FLAGS($acD) $pc++ \end{DSPOpcodeOperation} + + \DSPOpcodeFlags{-}{-}{X}{X}{X}{X}{0}{X} \end{DSPOpcode} \begin{DSPOpcode}{MOVR} @@ -2316,6 +3031,8 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and FLAGS($acD) $pc++ \end{DSPOpcodeOperation} + + \DSPOpcodeFlags{-}{-}{X}{X}{X}{X}{0}{0} \end{DSPOpcode} \begin{DSPOpcode}{MRR} @@ -2329,13 +3046,15 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and \begin{DSPOpcodeDescription} \item Move value from register \Register{\$S} to register \Register{\$D}. - Perform additional operation depending on destination register. + Perform an additional operation depending on destination register. \end{DSPOpcodeDescription} \begin{DSPOpcodeOperation} $D = $S $pc++ \end{DSPOpcodeOperation} + + \DSPOpcodeFlagsUnchanged \end{DSPOpcode} \begin{DSPOpcode}{MSUB} @@ -2361,6 +3080,8 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and \begin{DSPOpcodeSeeAlso} \item \RegisterField{\$sr.AM} bit affects multiply result. \end{DSPOpcodeSeeAlso} + + \DSPOpcodeFlagsUnchanged \end{DSPOpcode} \begin{DSPOpcode}{MSUBC} @@ -2385,6 +3106,8 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and \begin{DSPOpcodeSeeAlso} \item \RegisterField{\$sr.AM} bit affects multiply result. \end{DSPOpcodeSeeAlso} + + \DSPOpcodeFlagsUnchanged \end{DSPOpcode} \begin{DSPOpcode}{MSUBX} @@ -2409,6 +3132,8 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and \begin{DSPOpcodeSeeAlso} \item \RegisterField{\$sr.AM} bit affects multiply result. \end{DSPOpcodeSeeAlso} + + \DSPOpcodeFlagsUnchanged \end{DSPOpcode} \begin{DSPOpcode}{MUL} @@ -2433,6 +3158,8 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and \begin{DSPOpcodeSeeAlso} \item \RegisterField{\$sr.AM} bit affects multiply result. \end{DSPOpcodeSeeAlso} + + \DSPOpcodeFlagsUnchanged \end{DSPOpcode} \begin{DSPOpcode}{MULAC} @@ -2459,6 +3186,33 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and \begin{DSPOpcodeSeeAlso} \item \RegisterField{\$sr.AM} bit affects multiply result. \end{DSPOpcodeSeeAlso} + + \DSPOpcodeFlags{-}{-}{X}{X}{X}{X}{0}{X} +\end{DSPOpcode} + +\begin{DSPOpcode}{MULAXH} + \begin{DSPOpcodeBytefield}{16} + \monobitbox{4}{1000} & \monobitbox{4}{0011} & \monobitbox{4}{xxxx} & \monobitbox{4}{xxxx} + \end{DSPOpcodeBytefield} + + \begin{DSPOpcodeFormat} + MULAXH + \end{DSPOpcodeFormat} + + \begin{DSPOpcodeDescription} + \item Multiplies \Register{\$ax0.h} by itself. + \end{DSPOpcodeDescription} + + \begin{DSPOpcodeOperation} + $prod = $ax0.h * $ax0.h + $pc++ + \end{DSPOpcodeOperation} + + \begin{DSPOpcodeSeeAlso} + \item \RegisterField{\$sr.AM} bit affects multiply result. + \end{DSPOpcodeSeeAlso} + + \DSPOpcodeFlagsUnchanged \end{DSPOpcode} \begin{DSPOpcode}{MULC} @@ -2483,6 +3237,8 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and \begin{DSPOpcodeSeeAlso} \item \RegisterField{\$sr.AM} bit affects multiply result. \end{DSPOpcodeSeeAlso} + + \DSPOpcodeFlagsUnchanged \end{DSPOpcode} \begin{DSPOpcode}{MULCAC} @@ -2510,6 +3266,8 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and \begin{DSPOpcodeSeeAlso} \item \RegisterField{\$sr.AM} bit affects multiply result. \end{DSPOpcodeSeeAlso} + + \DSPOpcodeFlags{-}{-}{X}{X}{X}{X}{0}{X} \end{DSPOpcode} \begin{DSPOpcode}{MULCMV} @@ -2522,14 +3280,14 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and \end{DSPOpcodeFormat} \begin{DSPOpcodeDescription} - \item Multiply mid part of accumulator register \Register{\$acS.m} by high part \Register{\$axS.h} of - secondary accumulator \Register{\$axS} (treat them both as signed). + \item Multiply mid part of accumulator register \Register{\$acS.m} by high part \Register{\$axT.h} of + secondary accumulator \Register{\$axT} (treat them both as signed). Move product register before multiplication to accumulator \Register{\$acR}. \end{DSPOpcodeDescription} \begin{DSPOpcodeOperation} temp = $prod - $prod = $acS.m * $axS.h + $prod = $acS.m * $axT.h $acR = temp $pc++ \end{DSPOpcodeOperation} @@ -2537,6 +3295,8 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and \begin{DSPOpcodeSeeAlso} \item \RegisterField{\$sr.AM} bit affects multiply result. \end{DSPOpcodeSeeAlso} + + \DSPOpcodeFlags{-}{-}{X}{X}{X}{X}{0}{X} \end{DSPOpcode} \begin{DSPOpcode}{MULCMVZ} @@ -2549,15 +3309,15 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and \end{DSPOpcodeFormat} \begin{DSPOpcodeDescription} - \item Multiply mid part of accumulator register \Register{\$acS.m} by high part \Register{\$axS.h} of - secondary accumulator \Register{\$axS} (treat them both as signed). + \item Multiply mid part of accumulator register \Register{\$acS.m} by high part \Register{\$aTS.h} of + secondary accumulator \Register{\$axT} (treat them both as signed). Move product register before multiplication to accumulator \Register{\$acR}. Set low part of accumulator \Register{\$acR.l} to zero. \end{DSPOpcodeDescription} \begin{DSPOpcodeOperation} temp = $prod - $prod = $acS.m * $axS.h + $prod = $acS.m * $axT.h $acR.hm = temp.hm $acR.l = 0 $pc++ @@ -2566,6 +3326,8 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and \begin{DSPOpcodeSeeAlso} \item \RegisterField{\$sr.AM} bit affects multiply result. \end{DSPOpcodeSeeAlso} + + \DSPOpcodeFlags{-}{-}{X}{X}{X}{X}{0}{X} \end{DSPOpcode} \begin{DSPOpcode}{MULMV} @@ -2592,6 +3354,8 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and \begin{DSPOpcodeSeeAlso} \item \RegisterField{\$sr.AM} bit affects multiply result. \end{DSPOpcodeSeeAlso} + + \DSPOpcodeFlags{-}{-}{X}{X}{X}{X}{0}{X} \end{DSPOpcode} \begin{DSPOpcode}{MULMVZ} @@ -2620,6 +3384,8 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and \begin{DSPOpcodeSeeAlso} \item \RegisterField{\$sr.AM} bit affects multiply result. \end{DSPOpcodeSeeAlso} + + \DSPOpcodeFlags{-}{-}{X}{X}{X}{X}{0}{X} \end{DSPOpcode} \begin{DSPOpcode}{MULX} @@ -2644,11 +3410,13 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and \begin{DSPOpcodeSeeAlso} \item \RegisterField{\$sr.AM} bit affects multiply result. \end{DSPOpcodeSeeAlso} + + \DSPOpcodeFlagsUnchanged \end{DSPOpcode} \begin{DSPOpcode}{MULXAC} \begin{DSPOpcodeBytefield}{16} - \monobitbox{4}{101s} & \monobitbox{4}{t01r} & \monobitbox{4}{xxxx} & \monobitbox{4}{xxxx} + \monobitbox{4}{101s} & \monobitbox{4}{t10r} & \monobitbox{4}{xxxx} & \monobitbox{4}{xxxx} \end{DSPOpcodeBytefield} \begin{DSPOpcodeFormat} @@ -2671,6 +3439,8 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and \begin{DSPOpcodeSeeAlso} \item \RegisterField{\$sr.AM} bit affects multiply result. \end{DSPOpcodeSeeAlso} + + \DSPOpcodeFlags{-}{-}{X}{X}{X}{X}{0}{X} \end{DSPOpcode} \begin{DSPOpcode}{MULXMV} @@ -2698,6 +3468,8 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and \begin{DSPOpcodeSeeAlso} \item \RegisterField{\$sr.AM} bit affects multiply result. \end{DSPOpcodeSeeAlso} + + \DSPOpcodeFlags{-}{-}{X}{X}{X}{X}{0}{X} \end{DSPOpcode} \begin{DSPOpcode}{MULXMVZ} @@ -2727,6 +3499,8 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and \begin{DSPOpcodeSeeAlso} \item \RegisterField{\$sr.AM} bit affects multiply result. \end{DSPOpcodeSeeAlso} + + \DSPOpcodeFlags{-}{-}{X}{X}{X}{X}{0}{X} \end{DSPOpcode} \begin{DSPOpcode}{NEG} @@ -2743,10 +3517,45 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and \end{DSPOpcodeDescription} \begin{DSPOpcodeOperation} - $acD =- $acD + $acD = 0 - $acD FLAGS($acD) $pc++ \end{DSPOpcodeOperation} + + \begin{DSPOpcodeNote} + \item The carry flag is set only if \Register{\$acD} was zero. + The overflow flag is set only if \Register{\$acD} was \Value{0x8000000000} (the minimum value), + as \Code{-INT\_MIN} is \Code{INT\_MIN} in two's complement. + In both of these cases, the value of \Register{\$acD} after the operation is the same as it was before. + \end{DSPOpcodeNote} + + \DSPOpcodeFlags{X}{-}{X}{X}{X}{X}{X}{X} +\end{DSPOpcode} + +\begin{DSPOpcode}{NOT} + \begin{DSPOpcodeBytefield}{16} + \monobitbox{4}{0011} & \monobitbox{4}{001d} & \monobitbox{4}{1xxx} & \monobitbox{4}{xxxx} + \end{DSPOpcodeBytefield} + + \begin{DSPOpcodeFormat} + NOT $acD.m + \end{DSPOpcodeFormat} + + \begin{DSPOpcodeDescription} + \item Invert all bits in the middle part of accumulator \Register{\$acD.m} (i.e. XOR with \Value{0xffff}). + \end{DSPOpcodeDescription} + + \begin{DSPOpcodeOperation} + $acD.m = ~acD.m + FLAGS($acD) + $pc++ + \end{DSPOpcodeOperation} + + \begin{DSPOpcodeNote} + \item The main opcode is 9 bits and the extension opcode is 7 bits. The extension opcode is treated as if the 8th bit was 0 (i.e. it is \texttt{0xxxxxxx}). + \end{DSPOpcodeNote} + + \DSPOpcodeFlags{-}{-}{X}{X}{X}{X}{0}{0} \end{DSPOpcode} \begin{DSPOpcode}{NOP} @@ -2765,6 +3574,8 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and \begin{DSPOpcodeOperation} $pc++ \end{DSPOpcodeOperation} + + \DSPOpcodeFlagsUnchanged \end{DSPOpcode} \begin{DSPOpcode}{NX} @@ -2783,11 +3594,13 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and \begin{DSPOpcodeOperation} $pc++ \end{DSPOpcodeOperation} + + \DSPOpcodeFlagsUnchanged \end{DSPOpcode} \begin{DSPOpcode}{ORC} \begin{DSPOpcodeBytefield}{16} - \monobitbox{4}{0011} & \monobitbox{4}{111d} & \monobitbox{4}{xxxx} & \monobitbox{4}{xxxx} + \monobitbox{4}{0011} & \monobitbox{4}{111d} & \monobitbox{4}{0xxx} & \monobitbox{4}{xxxx} \end{DSPOpcodeBytefield} \begin{DSPOpcodeFormat} @@ -2803,6 +3616,12 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and FLAGS($acD) $pc++ \end{DSPOpcodeOperation} + + \begin{DSPOpcodeNote} + \item The main opcode is 9 bits and the extension opcode is 7 bits. The extension opcode is treated as if the 8th bit was 0 (i.e. it is \texttt{0xxxxxxx}). + \end{DSPOpcodeNote} + + \DSPOpcodeFlagsUnchanged \end{DSPOpcode} \begin{DSPOpcode}{ORI} @@ -2824,11 +3643,13 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and FLAGS($acD) $pc += 2 \end{DSPOpcodeOperation} + + \DSPOpcodeFlags{-}{-}{X}{X}{X}{X}{0}{X} \end{DSPOpcode} \begin{DSPOpcode}{ORR} \begin{DSPOpcodeBytefield}{16} - \monobitbox{4}{0011} & \monobitbox{4}{10sd} & \monobitbox{4}{xxxx} & \monobitbox{4}{xxxx} + \monobitbox{4}{0011} & \monobitbox{4}{10sd} & \monobitbox{4}{0xxx} & \monobitbox{4}{xxxx} \end{DSPOpcodeBytefield} \begin{DSPOpcodeFormat} @@ -2844,6 +3665,12 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and FLAGS($acD) $pc++ \end{DSPOpcodeOperation} + + \begin{DSPOpcodeNote} + \item The main opcode is 9 bits and the extension opcode is 7 bits. The extension opcode is treated as if the 8th bit was 0 (i.e. it is \texttt{0xxxxxxx}). + \end{DSPOpcodeNote} + + \DSPOpcodeFlags{-}{-}{X}{X}{X}{X}{0}{X} \end{DSPOpcode} \begin{DSPOpcode}{RET} @@ -2863,6 +3690,8 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and $pc = $st0 POP_STACK($st0) \end{DSPOpcodeOperation} + + \DSPOpcodeFlagsUnchanged \end{DSPOpcode} \begin{DSPOpcode}{RETcc} @@ -2883,9 +3712,11 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and IF (cc) POP_STACK($st0) ELSE - $pc += 2 + $pc++ ENDIF \end{DSPOpcodeOperation} + + \DSPOpcodeFlagsUnchanged \end{DSPOpcode} \begin{DSPOpcode}{RTI} @@ -2908,30 +3739,41 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and $pc = $st0 POP_STACK($st0) \end{DSPOpcodeOperation} + + \DSPOpcodeFlagsUnchanged \end{DSPOpcode} -\begin{DSPOpcode}{SBSET} +\begin{DSPOpcode}{RTIcc} \begin{DSPOpcodeBytefield}{16} - \monobitbox{4}{0001} & \monobitbox{4}{0010} & \monobitbox{4}{0000} & \monobitbox{4}{0iii} + \monobitbox{4}{0000} & \monobitbox{4}{0010} & \monobitbox{4}{1111} & \monobitbox{4}{cccc} \end{DSPOpcodeBytefield} \begin{DSPOpcodeFormat} - SBSET #I + RTIcc \end{DSPOpcodeFormat} \begin{DSPOpcodeDescription} - \item Set bit of status register \Register{\$sr}. Bit number is calculated by adding 6 to immediate value \Value{I}. + \item Return from exception if condition \Flag{cc} has been met. Pops stored status register \Register{\$sr} from data stack \Register{\$st1} and + program counter PC from call stack \Register{\$st0} and sets \Register{\$pc} to this location. \end{DSPOpcodeDescription} \begin{DSPOpcodeOperation} - $sr |= (I + 6) - $pc++ + IF (cc) + $sr = $st1 + POP_STACK($st1) + $pc = $st0 + POP_STACK($st0) + ELSE + $pc++ + ENDIF \end{DSPOpcodeOperation} + + \DSPOpcodeFlagsUnchanged \end{DSPOpcode} \begin{DSPOpcode}{SBCLR} \begin{DSPOpcodeBytefield}{16} - \monobitbox{4}{0001} & \monobitbox{4}{0011} & \monobitbox{4}{0000} & \monobitbox{4}{0iii} + \monobitbox{4}{0001} & \monobitbox{4}{0010} & \monobitbox{4}{0000} & \monobitbox{4}{0iii} \end{DSPOpcodeBytefield} \begin{DSPOpcodeFormat} @@ -2939,13 +3781,111 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and \end{DSPOpcodeFormat} \begin{DSPOpcodeDescription} - \item Clear bit of status register \Register{\$sr}. Bit number is calculated by adding 6 to immediate value \Value{I}. + \item Clear bit of status register \Register{\$sr}. Bit number is calculated by adding 6 to immediate value \Value{I}; thus, bits 6 through 13 (\texttt{LZ} through \texttt{AM}) can be cleared with this instruction. \end{DSPOpcodeDescription} \begin{DSPOpcodeOperation} - $sr &= ~(I + 6) + $sr &= ~(1 << (I + 6)) $pc++ \end{DSPOpcodeOperation} + + \DSPOpcodeFlagsUnchanged +\end{DSPOpcode} + +\begin{DSPOpcode}{SBSET} + \begin{DSPOpcodeBytefield}{16} + \monobitbox{4}{0001} & \monobitbox{4}{0011} & \monobitbox{4}{0000} & \monobitbox{4}{0iii} + \end{DSPOpcodeBytefield} + + \begin{DSPOpcodeFormat} + SBSET #I + \end{DSPOpcodeFormat} + + \begin{DSPOpcodeDescription} + \item Set bit of status register \Register{\$sr}. Bit number is calculated by adding 6 to immediate value \Value{I}; thus, bits 6 through 13 (\texttt{LZ} through \texttt{AM}) can be set with this instruction. + \end{DSPOpcodeDescription} + + \begin{DSPOpcodeOperation} + $sr |= 1 << (I + 6) + $pc++ + \end{DSPOpcodeOperation} + + \DSPOpcodeFlagsUnchanged +\end{DSPOpcode} + +\begin{DSPOpcode}{SET15} + \begin{DSPOpcodeBytefield}{16} + \monobitbox{4}{1000} & \monobitbox{4}{1101} & \monobitbox{4}{xxxx} & \monobitbox{4}{xxxx} + \end{DSPOpcodeBytefield} + + \begin{DSPOpcodeFormat} + SET15 + \end{DSPOpcodeFormat} + + \begin{DSPOpcodeDescription} + \item Sets \RegisterField{\$sr.SU} (bit 15) to 1, causing multiplication to treat its operands as unsigned. + \end{DSPOpcodeDescription} + + \begin{DSPOpcodeOperation} + $sr |= 0x8000 + $pc++ + \end{DSPOpcodeOperation} + + \begin{DSPOpcodeSeeAlso} + \item \Opcode{CLR15} + \end{DSPOpcodeSeeAlso} + + \DSPOpcodeFlagsUnchanged +\end{DSPOpcode} + +\begin{DSPOpcode}{SET16} + \begin{DSPOpcodeBytefield}{16} + \monobitbox{4}{1000} & \monobitbox{4}{1110} & \monobitbox{4}{xxxx} & \monobitbox{4}{xxxx} + \end{DSPOpcodeBytefield} + + \begin{DSPOpcodeFormat} + SET16 + \end{DSPOpcodeFormat} + + \begin{DSPOpcodeDescription} + \item Sets \RegisterField{\$sr.SXM} (bit 14) to 0, resulting in 16-bit sign extension. + \end{DSPOpcodeDescription} + + \begin{DSPOpcodeOperation} + $sr &= ~0x4000 + $pc++ + \end{DSPOpcodeOperation} + + \begin{DSPOpcodeSeeAlso} + \item \Opcode{SET40} + \end{DSPOpcodeSeeAlso} + + \DSPOpcodeFlagsUnchanged +\end{DSPOpcode} + +\begin{DSPOpcode}{SET40} + \begin{DSPOpcodeBytefield}{16} + \monobitbox{4}{1000} & \monobitbox{4}{1111} & \monobitbox{4}{xxxx} & \monobitbox{4}{xxxx} + \end{DSPOpcodeBytefield} + + \begin{DSPOpcodeFormat} + SET40 + \end{DSPOpcodeFormat} + + \begin{DSPOpcodeDescription} + \item Sets \RegisterField{\$sr.SXM} (bit 14) to 1, resulting in 40-bit sign extension. + \end{DSPOpcodeDescription} + + \begin{DSPOpcodeOperation} + $sr |= 0x4000 + $pc++ + \end{DSPOpcodeOperation} + + \begin{DSPOpcodeSeeAlso} + \item \Opcode{SET16} + \end{DSPOpcodeSeeAlso} + + \DSPOpcodeFlagsUnchanged \end{DSPOpcode} \begin{DSPOpcode}{SI} @@ -2959,13 +3899,19 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and \end{DSPOpcodeFormat} \begin{DSPOpcodeDescription} - \item Store 16-bit immediate value \Value{I} to a memory location pointed by address \Address{M} (\Address{M} is an 8-bit sign-extended value). + \item Store 16-bit immediate value \Value{I} to a memory location pointed by address \Address{0xFF00 | M}. \end{DSPOpcodeDescription} \begin{DSPOpcodeOperation} - MEM[M] = I + MEM[0xFF00 | M] = I $pc += 2 \end{DSPOpcodeOperation} + + \begin{DSPOpcodeNote} + \item Unlike \Opcode{SRS}, \Opcode{SRSH}, and \Opcode{LRS}, \Opcode{SI} does not use \Register{\$cr} to decide the base address and instead always uses \Address{0xFF00}. + \end{DSPOpcodeNote} + + \DSPOpcodeFlagsUnchanged \end{DSPOpcode} \begin{DSPOpcode}{SR} @@ -2980,13 +3926,15 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and \begin{DSPOpcodeDescription} \item Store value from register \Register{\$S} to a memory pointed by address \Address{M}. - Perform additional operation depending on destination register. + Perform an additional operation depending on destination register. \end{DSPOpcodeDescription} \begin{DSPOpcodeOperation} MEM[M] = $S $pc += 2 \end{DSPOpcodeOperation} + + \DSPOpcodeFlagsUnchanged \end{DSPOpcode} \begin{DSPOpcode}{SRR} @@ -3000,13 +3948,15 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and \begin{DSPOpcodeDescription} \item Store value from source register \Register{\$S} to a memory location pointed by addressing - register \Register{\$arD}. Perform additional operation depending on source register. + register \Register{\$arD}. Perform an additional operation depending on source register. \end{DSPOpcodeDescription} \begin{DSPOpcodeOperation} MEM[$arD] = $S $pc++ \end{DSPOpcodeOperation} + + \DSPOpcodeFlagsUnchanged \end{DSPOpcode} \begin{DSPOpcode}{SRRD} @@ -3020,7 +3970,7 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and \begin{DSPOpcodeDescription} \item Store value from source register \Register{\$S} to a memory location pointed by addressing - register \Register{\$arD}. Decrement register \Register{\$arD}. Perform additional operation depending on source register. + register \Register{\$arD}. Decrement register \Register{\$arD}. Perform an additional operation depending on source register. \end{DSPOpcodeDescription} \begin{DSPOpcodeOperation} @@ -3028,6 +3978,8 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and $arD-- $pc++ \end{DSPOpcodeOperation} + + \DSPOpcodeFlagsUnchanged \end{DSPOpcode} \begin{DSPOpcode}{SRRI} @@ -3041,7 +3993,7 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and \begin{DSPOpcodeDescription} \item Store value from source register \Register{\$S} to a memory location pointed by addressing - register \Register{\$arD}. Increment register \Register{\$arD}. Perform additional operation depending on source register. + register \Register{\$arD}. Increment register \Register{\$arD}. Perform an additional operation depending on source register. \end{DSPOpcodeDescription} \begin{DSPOpcodeOperation} @@ -3049,6 +4001,8 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and $arD++ $pc++ \end{DSPOpcodeOperation} + + \DSPOpcodeFlagsUnchanged \end{DSPOpcode} \begin{DSPOpcode}{SRRN} @@ -3063,7 +4017,7 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and \begin{DSPOpcodeDescription} \item Store value from source register \Register{\$S} to a memory location pointed by addressing register \Register{\$arD}. Add indexing register \Register{\$ixD} to register \Register{\$arD}. - Perform additional operation depending on source register. + Perform an additional operation depending on source register. \end{DSPOpcodeDescription} \begin{DSPOpcodeOperation} @@ -3071,26 +4025,62 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and $arD += $ixD $pc++ \end{DSPOpcodeOperation} + + \DSPOpcodeFlagsUnchanged \end{DSPOpcode} \begin{DSPOpcode}{SRS} \begin{DSPOpcodeBytefield}{16} - \monobitbox{4}{0010} & \monobitbox{4}{1sss} & \monobitbox{4}{mmmm} & \monobitbox{4}{mmmm} + \monobitbox{4}{0010} & \monobitbox{4}{11ss} & \monobitbox{4}{mmmm} & \monobitbox{4}{mmmm} \end{DSPOpcodeBytefield} \begin{DSPOpcodeFormat} - SRS @M, $(0x18+S) + SRS @M, $(0x1C+S) \end{DSPOpcodeFormat} \begin{DSPOpcodeDescription} - \item Store value from register \Register{\$(0x18+S)} to a memory pointed by address \Address{M} (8-bit sign-extended). - Perform additional operation depending on destination register. + \item Store value from register \Register{\$(0x1C+S)} to a memory pointed by address \Address{(\$cr << 8) | M}. + Perform an additional operation depending on destination register. \end{DSPOpcodeDescription} \begin{DSPOpcodeOperation} - MEM[M] = $(0x18+S) + MEM[($cr << 8) | M] = $(0x1C+S) $pc++ \end{DSPOpcodeOperation} + + \begin{DSPOpcodeNote} + \item Unlike \Opcode{LRS}, \Opcode{SRS} and \Opcode{SRSH} only work on \Register{\$acS}. + The pattern \Value{101s} is unused and does not perform any write. + \end{DSPOpcodeNote} + + \DSPOpcodeFlagsUnchanged +\end{DSPOpcode} + +\begin{DSPOpcode}{SRSH} + \begin{DSPOpcodeBytefield}{16} + \monobitbox{4}{0010} & \monobitbox{4}{100s} & \monobitbox{4}{mmmm} & \monobitbox{4}{mmmm} + \end{DSPOpcodeBytefield} + + \begin{DSPOpcodeFormat} + SRSH @M, $acS.h + \end{DSPOpcodeFormat} + + \begin{DSPOpcodeDescription} + \item Store value from register \Register{\$acS.h} to a memory pointed by address \Address{(\$cr << 8) | M}. + Perform an additional operation depending on destination register. + \end{DSPOpcodeDescription} + + \begin{DSPOpcodeOperation} + MEM[($cr << 8) | M] = $acS.h + $pc++ + \end{DSPOpcodeOperation} + + \begin{DSPOpcodeNote} + \item Unlike \Opcode{LRS}, \Opcode{SRS} and \Opcode{SRSH} only work on \Register{\$acS}. + The pattern \Value{101s} is unused and does not perform any write. + \end{DSPOpcodeNote} + + \DSPOpcodeFlagsUnchanged \end{DSPOpcode} \begin{DSPOpcode}{SUB} @@ -3111,6 +4101,29 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and FLAGS($acD) $pc++ \end{DSPOpcodeOperation} + + \DSPOpcodeFlags{X}{-}{X}{X}{X}{X}{X}{X} +\end{DSPOpcode} + +\begin{DSPOpcode}{SUBARN} + \begin{DSPOpcodeBytefield}{16} + \monobitbox{4}{0000} & \monobitbox{4}{0000} & \monobitbox{4}{0000} & \monobitbox{4}{11dd} + \end{DSPOpcodeBytefield} + + \begin{DSPOpcodeFormat} + SUBARN $arD + \end{DSPOpcodeFormat} + + \begin{DSPOpcodeDescription} + \item Subtracts indexing register \Register{\$ixD} from addressing register \Register{\$arD}. + \end{DSPOpcodeDescription} + + \begin{DSPOpcodeOperation} + $arD -= $ixD + $pc++ + \end{DSPOpcodeOperation} + + \DSPOpcodeFlagsUnchanged \end{DSPOpcode} \begin{DSPOpcode}{SUBAX} @@ -3131,6 +4144,8 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and FLAGS($acD) $pc++ \end{DSPOpcodeOperation} + + \DSPOpcodeFlags{X}{-}{X}{X}{X}{X}{X}{X} \end{DSPOpcode} \begin{DSPOpcode}{SUBP} @@ -3151,6 +4166,8 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and FLAGS($acD) $pc++ \end{DSPOpcodeOperation} + + \DSPOpcodeFlags{X}{-}{X}{X}{X}{X}{X}{X} \end{DSPOpcode} \begin{DSPOpcode}{SUBR} @@ -3167,10 +4184,12 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and \end{DSPOpcodeDescription} \begin{DSPOpcodeOperation} - $acD -= $(0x18+S) + $acD -= ($(0x18+S) << 16) FLAGS($acD) $pc++ \end{DSPOpcodeOperation} + + \DSPOpcodeFlags{X}{-}{X}{X}{X}{X}{X}{X} \end{DSPOpcode} \begin{DSPOpcode}{TST} @@ -3190,6 +4209,8 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and FLAGS($acR) $pc++ \end{DSPOpcodeOperation} + + \DSPOpcodeFlags{-}{-}{X}{X}{X}{X}{0}{0} \end{DSPOpcode} \begin{DSPOpcode}{TSTAXH} @@ -3202,13 +4223,62 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and \end{DSPOpcodeFormat} \begin{DSPOpcodeDescription} - \item Test hight part of secondary accumulator \Register{\$axR.h}. + \item Test high part of secondary accumulator \Register{\$axR.h}. \end{DSPOpcodeDescription} \begin{DSPOpcodeOperation} FLAGS($axR.h) $pc++ \end{DSPOpcodeOperation} + + \DSPOpcodeFlags{-}{-}{X}{0}{X}{X}{0}{0} +\end{DSPOpcode} + +\begin{DSPOpcode}{TSTPROD} + \begin{DSPOpcodeBytefield}{16} + \monobitbox{4}{1000} & \monobitbox{4}{0101} & \monobitbox{4}{xxxx} & \monobitbox{4}{xxxx} + \end{DSPOpcodeBytefield} + + \begin{DSPOpcodeFormat} + TSTPROD + \end{DSPOpcodeFormat} + + \begin{DSPOpcodeDescription} + \item Test the product register \Register{\$prod}. + \end{DSPOpcodeDescription} + + \begin{DSPOpcodeOperation} + FLAGS($prod) + $pc++ + \end{DSPOpcodeOperation} + + \DSPOpcodeFlags{-}{-}{X}{0}{X}{X}{0}{X} +\end{DSPOpcode} + +\begin{DSPOpcode}{XORC} + \begin{DSPOpcodeBytefield}{16} + \monobitbox{4}{0011} & \monobitbox{4}{000d} & \monobitbox{4}{1xxx} & \monobitbox{4}{xxxx} + \end{DSPOpcodeBytefield} + + \begin{DSPOpcodeFormat} + XORC $acD.m, $ac(1-D).m + \end{DSPOpcodeFormat} + + \begin{DSPOpcodeDescription} + \item Logical XOR (exclusive OR) middle part of accumulator \Register{\$acD.m} with middle part of accumulator \Register{\$ac(1-D).m}. + \end{DSPOpcodeDescription} + + \begin{DSPOpcodeOperation} + $acD.m ^= $ac(1-D).m + FLAGS($acD) + $pc++ + \end{DSPOpcodeOperation} + + \begin{DSPOpcodeNote} + \item The main opcode is 9 bits and the extension opcode is 7 bits. The extension opcode is treated as if the 8th bit was 0 (i.e. it is \texttt{0xxxxxxx}). + \end{DSPOpcodeNote} + + \DSPOpcodeFlags{-}{-}{X}{X}{X}{X}{0}{0} \end{DSPOpcode} \begin{DSPOpcode}{XORI} @@ -3230,11 +4300,13 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and FLAGS($acD) $pc += 2 \end{DSPOpcodeOperation} + + \DSPOpcodeFlags{-}{-}{X}{X}{X}{X}{0}{0} \end{DSPOpcode} \begin{DSPOpcode}{XORR} \begin{DSPOpcodeBytefield}{16} - \monobitbox{4}{0011} & \monobitbox{4}{00sd} & \monobitbox{4}{xxxx} & \monobitbox{4}{xxxx} + \monobitbox{4}{0011} & \monobitbox{4}{00sd} & \monobitbox{4}{0xxx} & \monobitbox{4}{xxxx} \end{DSPOpcodeBytefield} \begin{DSPOpcodeFormat} @@ -3250,12 +4322,22 @@ There are two pairs of conditions that work similar: \texttt{EQ}/\texttt{NE} and FLAGS($acD) $pc++ \end{DSPOpcodeOperation} + + \begin{DSPOpcodeNote} + \item The main opcode is 9 bits and the extension opcode is 7 bits. The extension opcode is treated as if the 8th bit was 0 (i.e. it is \texttt{0xxxxxxx}). + \end{DSPOpcodeNote} + + \DSPOpcodeFlags{-}{-}{X}{X}{X}{X}{0}{0} \end{DSPOpcode} \section{Extended opcodes} -Extended opcodes do not exist on their own. These opcodes can only be attached to opcodes that -allow extending (8 lower bits of opcode not used by opcode). Extended opcodes do not modify the program counter (\Register{\$pc} register. +Extended opcodes do not exist on their own. These opcodes can only be attached to opcodes that allow extending. +Specifically, opcodes where the first nybble is 0, 1, or 2 cannot be extended. +Opcodes where the first nybble is 4 or higher can be extended, using the 8 lower bits. +Opcodes where the first nybble is 3 can also be extended, but the main opcode is 9 bits and the extension opcode is 7 bits. For these instructions, the extension opcode is treated as if the first bit were 0 (i.e. \texttt{0xxxxxxx}). + +Extended opcodes do not modify the program counter (\Register{\$pc} register). \pagebreak{} @@ -3339,9 +4421,227 @@ allow extending (8 lower bits of opcode not used by opcode). Extended opcodes do \end{DSPOpcodeOperation} \end{DSPOpcode} +\begin{DSPOpcode}{'LD} + \begin{DSPOpcodeBytefield}{16} + \monobitbox{4}{xxxx} & \monobitbox{4}{xxxx} & \monobitbox{4}{11dr} & \monobitbox{4}{00ss} + \end{DSPOpcodeBytefield} + + \begin{DSPOpcodeFormat} + 'LD $ax0.D, $ax1.R, @$arS + \end{DSPOpcodeFormat} + + \begin{DSPOpcodeDescription} + \item Load register \Register{\$ax0.D} (either \Register{\$ax0.l} or \Register{\$ax0.h}, as \Register{\$(0x18+D*2)}) with value from memory pointed by register \Register{\$arS}. + Load register \Register{\$ax1.R} (either \Register{\$ax1.l} or \Register{\$ax1.h}, as \Register{\$(0x19+R*2)}) with value from memory pointed by register \Register{\$ar3}. + Increment both \Register{\$arS} and \Register{\$ar3}. + \end{DSPOpcodeDescription} + + \begin{DSPOpcodeOperation} + $ax0.D = MEM[$arS] + $ax1.R = MEM[$ar3] + $arS++ + $ar3++ + \end{DSPOpcodeOperation} + + \begin{DSPOpcodeNote} + \item \texttt{S} cannot be 3, as that instead encodes \Opcode{'LDAX}. Thus, \Register{\$arS} is guaranteed to be distinct from \Register{\$ar3}. + \end{DSPOpcodeNote} +\end{DSPOpcode} + +\begin{DSPOpcode}{'LDM} + \begin{DSPOpcodeBytefield}{16} + \monobitbox{4}{xxxx} & \monobitbox{4}{xxxx} & \monobitbox{4}{11dr} & \monobitbox{4}{10ss} + \end{DSPOpcodeBytefield} + + \begin{DSPOpcodeFormat} + 'LDM $ax0.D, $ax1.R, @$arS + \end{DSPOpcodeFormat} + + \begin{DSPOpcodeDescription} + \item Load register \Register{\$ax0.D} (either \Register{\$ax0.l} or \Register{\$ax0.h}, as \Register{\$(0x18+D*2)}) with value from memory pointed by register \Register{\$arS}. + Load register \Register{\$ax1.R} (either \Register{\$ax1.l} or \Register{\$ax1.h}, as \Register{\$(0x19+R*2)}) with value from memory pointed by register \Register{\$ar3}. + Add corresponding indexing register \Register{\$ix3} to addressing register \Register{\$ar3} and increment \Register{\$arS}. + \end{DSPOpcodeDescription} + + \begin{DSPOpcodeOperation} + $ax0.D = MEM[$arS] + $ax1.R = MEM[$ar3] + $arS++ + $ar3 += $ix3 + \end{DSPOpcodeOperation} + + \begin{DSPOpcodeNote} + \item \texttt{S} cannot be 3, as that instead encodes \Opcode{'LDAXM}. Thus, \Register{\$arS} is guaranteed to be distinct from \Register{\$ar3}. + \end{DSPOpcodeNote} +\end{DSPOpcode} + +\begin{DSPOpcode}{'LDNM} + \begin{DSPOpcodeBytefield}{16} + \monobitbox{4}{xxxx} & \monobitbox{4}{xxxx} & \monobitbox{4}{11dr} & \monobitbox{4}{11ss} + \end{DSPOpcodeBytefield} + + \begin{DSPOpcodeFormat} + 'LDNM $ax0.D, $ax1.R, @$arS + \end{DSPOpcodeFormat} + + \begin{DSPOpcodeDescription} + \item Load register \Register{\$ax0.D} (either \Register{\$ax0.l} or \Register{\$ax0.h}, as \Register{\$(0x18+D*2)}) with value from memory pointed by register \Register{\$arS}. + Load register \Register{\$ax1.R} (either \Register{\$ax1.l} or \Register{\$ax1.h}, as \Register{\$(0x19+R*2)}) with value from memory pointed by register \Register{\$ar3}. + Add corresponding indexing register \Register{\$ixS} to addressing register \Register{\$arS} and add corresponding + indexing register \Register{\$ix3} to addressing register \Register{\$ar3}. + \end{DSPOpcodeDescription} + + \begin{DSPOpcodeOperation} + $ax0.D = MEM[$arS] + $ax1.R = MEM[$ar3] + $arS += $ixS + $ar3 += $ix3 + \end{DSPOpcodeOperation} + + \begin{DSPOpcodeNote} + \item \texttt{S} cannot be 3, as that instead encodes \Opcode{'LDAXNM}. Thus, \Register{\$arS} is guaranteed to be distinct from \Register{\$ar3}. + \end{DSPOpcodeNote} +\end{DSPOpcode} + +\begin{DSPOpcode}{'LDN} + \begin{DSPOpcodeBytefield}{16} + \monobitbox{4}{xxxx} & \monobitbox{4}{xxxx} & \monobitbox{4}{11dr} & \monobitbox{4}{01ss} + \end{DSPOpcodeBytefield} + + \begin{DSPOpcodeFormat} + 'LDN $ax0.D, $ax1.R, @$arS + \end{DSPOpcodeFormat} + + \begin{DSPOpcodeDescription} + \item Load register \Register{\$ax0.D} (either \Register{\$ax0.l} or \Register{\$ax0.h}, as \Register{\$(0x18+D*2)}) with value from memory pointed by register \Register{\$arS}. + Load register \Register{\$ax1.R} (either \Register{\$ax1.l} or \Register{\$ax1.h}, as \Register{\$(0x19+R*2)}) with value from memory pointed by register \Register{\$ar3}. + Add corresponding indexing register \Register{\$ixS} to addressing register \Register{\$arS} and increment \Register{\$ar3}. + \end{DSPOpcodeDescription} + + \begin{DSPOpcodeOperation} + $ax0.D = MEM[$arS] + $ax1.R = MEM[$ar3] + $arS += $ixS + $ar3++ + \end{DSPOpcodeOperation} + + \begin{DSPOpcodeNote} + \item \texttt{S} cannot be 3, as that instead encodes \Opcode{'LDAXN}. Thus, \Register{\$arS} is guaranteed to be distinct from \Register{\$ar3}. + \end{DSPOpcodeNote} +\end{DSPOpcode} + +\begin{DSPOpcode}{'LDAX} + \begin{DSPOpcodeBytefield}{16} + \monobitbox{4}{xxxx} & \monobitbox{4}{xxxx} & \monobitbox{4}{11sr} & \monobitbox{4}{0011} + \end{DSPOpcodeBytefield} + + \begin{DSPOpcodeFormat} + 'LDAX $axR, @$arS + \end{DSPOpcodeFormat} + + \begin{DSPOpcodeDescription} + \item Load register \Register{\$axR.h} with value from memory pointed by register \Register{\$arS}. + Load register \Register{\$axR.l} with value from memory pointed by register \Register{\$ar3}. + Increment both \Register{\$arS} and \Register{\$ar3}. + \end{DSPOpcodeDescription} + + \begin{DSPOpcodeOperation} + $axR.h = MEM[$arS] + $axR.l = MEM[$ar3] + $arS++ + $ar3++ + \end{DSPOpcodeOperation} + + \begin{DSPOpcodeNote} + \item \texttt{S} can be either 0 or 1, corresponding to \Register{\$ar0} or \Register{\$ar1}. Thus, \Register{\$arS} is guaranteed to be distinct from \Register{\$ar3}. \Register{\$ar2} cannot be used with this instruction. + \end{DSPOpcodeNote} +\end{DSPOpcode} + +\begin{DSPOpcode}{'LDAXM} + \begin{DSPOpcodeBytefield}{16} + \monobitbox{4}{xxxx} & \monobitbox{4}{xxxx} & \monobitbox{4}{11sr} & \monobitbox{4}{0011} + \end{DSPOpcodeBytefield} + + \begin{DSPOpcodeFormat} + 'LDAXM $axR, @$arS + \end{DSPOpcodeFormat} + + \begin{DSPOpcodeDescription} + \item Load register \Register{\$axR.h} with value from memory pointed by register \Register{\$arS}. + Load register \Register{\$axR.l} with value from memory pointed by register \Register{\$ar3}. + Add corresponding indexing register \Register{\$ix3} to addressing register \Register{\$ar3} and increment \Register{\$arS}. + \end{DSPOpcodeDescription} + + \begin{DSPOpcodeOperation} + $axR.h = MEM[$arS] + $axR.l = MEM[$ar3] + $arS++ + $ar3 += $ix3 + \end{DSPOpcodeOperation} + + \begin{DSPOpcodeNote} + \item \texttt{S} can be either 0 or 1, corresponding to \Register{\$ar0} or \Register{\$ar1}. Thus, \Register{\$arS} is guaranteed to be distinct from \Register{\$ar3}. \Register{\$ar2} cannot be used with this instruction. + \end{DSPOpcodeNote} +\end{DSPOpcode} + +\begin{DSPOpcode}{'LDAXNM} + \begin{DSPOpcodeBytefield}{16} + \monobitbox{4}{xxxx} & \monobitbox{4}{xxxx} & \monobitbox{4}{11sr} & \monobitbox{4}{0011} + \end{DSPOpcodeBytefield} + + \begin{DSPOpcodeFormat} + 'LDAXNM $axR, @$arS + \end{DSPOpcodeFormat} + + \begin{DSPOpcodeDescription} + \item Load register \Register{\$axR.h} with value from memory pointed by register \Register{\$arS}. + Load register \Register{\$axR.l} with value from memory pointed by register \Register{\$ar3}. + Add corresponding indexing register \Register{\$ixS} to addressing register \Register{\$arS} and add corresponding + indexing register \Register{\$ix3} to addressing register \Register{\$ar3}. + \end{DSPOpcodeDescription} + + \begin{DSPOpcodeOperation} + $axR.h = MEM[$arS] + $axR.l = MEM[$ar3] + $arS += $ixS + $ar3 += $ix3 + \end{DSPOpcodeOperation} + + \begin{DSPOpcodeNote} + \item \texttt{S} can be either 0 or 1, corresponding to \Register{\$ar0} or \Register{\$ar1}. Thus, \Register{\$arS} is guaranteed to be distinct from \Register{\$ar3}. \Register{\$ar2} cannot be used with this instruction. + \end{DSPOpcodeNote} +\end{DSPOpcode} + +\begin{DSPOpcode}{'LDAXN} + \begin{DSPOpcodeBytefield}{16} + \monobitbox{4}{xxxx} & \monobitbox{4}{xxxx} & \monobitbox{4}{11sr} & \monobitbox{4}{0011} + \end{DSPOpcodeBytefield} + + \begin{DSPOpcodeFormat} + 'LDAXN $axR, @$arS + \end{DSPOpcodeFormat} + + \begin{DSPOpcodeDescription} + \item Load register \Register{\$axR.h} with value from memory pointed by register \Register{\$arS}. + Load register \Register{\$axR.l} with value from memory pointed by register \Register{\$ar3}. + Add corresponding indexing register \Register{\$ixS} to addressing register \Register{\$arS} and increment \Register{\$ar3}. + \end{DSPOpcodeDescription} + + \begin{DSPOpcodeOperation} + $axR.h = MEM[$arS] + $axR.l = MEM[$ar3] + $arS += $ixS + $ar3++ + \end{DSPOpcodeOperation} + + \begin{DSPOpcodeNote} + \item \texttt{S} can be either 0 or 1, corresponding to \Register{\$ar0} or \Register{\$ar1}. Thus, \Register{\$arS} is guaranteed to be distinct from \Register{\$ar3}. \Register{\$ar2} cannot be used with this instruction. + \end{DSPOpcodeNote} +\end{DSPOpcode} + \begin{DSPOpcode}{'LS} \begin{DSPOpcodeBytefield}{16} - \monobitbox{4}{xxxx} & \monobitbox{4}{xxxx} & \monobitbox{4}{01dd} & \monobitbox{4}{d1ss} + \monobitbox{4}{xxxx} & \monobitbox{4}{xxxx} & \monobitbox{4}{10dd} & \monobitbox{4}{000s} \end{DSPOpcodeBytefield} \begin{DSPOpcodeFormat} @@ -3450,6 +4750,24 @@ allow extending (8 lower bits of opcode not used by opcode). Extended opcodes do \end{DSPOpcodeOperation} \end{DSPOpcode} +\begin{DSPOpcode}{'NOP} + \begin{DSPOpcodeBytefield}{16} + \monobitbox{4}{xxxx} & \monobitbox{4}{xxxx} & \monobitbox{4}{0000} & \monobitbox{4}{00xx} + \end{DSPOpcodeBytefield} + + \begin{DSPOpcodeFormat} + 'NOP + \end{DSPOpcodeFormat} + + \begin{DSPOpcodeDescription} + \item No operation. + \end{DSPOpcodeDescription} + + \begin{DSPOpcodeNote} + \item Generally written as by not including any extension operation, such as writing \texttt{INC \$ac0} instead of writing \texttt{INC'NOP \$ac0}. + \end{DSPOpcodeNote} +\end{DSPOpcode} + \begin{DSPOpcode}{'NR} \begin{DSPOpcodeBytefield}{16} \monobitbox{4}{xxxx} & \monobitbox{4}{xxxx} & \monobitbox{4}{0000} & \monobitbox{4}{11rr} @@ -3474,7 +4792,7 @@ allow extending (8 lower bits of opcode not used by opcode). Extended opcodes do \end{DSPOpcodeBytefield} \begin{DSPOpcodeFormat} - 'S @$D, $(0x1c+S) + 'S @$arD, $(0x1c+S) \end{DSPOpcodeFormat} \begin{DSPOpcodeDescription} @@ -3534,13 +4852,13 @@ allow extending (8 lower bits of opcode not used by opcode). Extended opcodes do \end{DSPOpcodeOperation} \end{DSPOpcode} -\begin{DSPOpcode}{'SLMN} +\begin{DSPOpcode}{'SLNM} \begin{DSPOpcodeBytefield}{16} \monobitbox{4}{xxxx} & \monobitbox{4}{xxxx} & \monobitbox{4}{10dd} & \monobitbox{4}{111s} \end{DSPOpcodeBytefield} \begin{DSPOpcodeFormat} - 'SLMN $acS.m, $(0x18+D) + 'SLNM $acS.m, $(0x18+D) \end{DSPOpcodeFormat} \begin{DSPOpcodeDescription} @@ -3603,144 +4921,201 @@ allow extending (8 lower bits of opcode not used by opcode). Extended opcodes do \section{Instructions sorted by opcode} - -\newcolumntype{T}{>{\ttfamily}l} +\newcommand{\OpcodeRow}[2]{\Opcode{#2} & \texttt{#1} & \pageref{instruction:#2} \\*} +\newcommand{\OpcodeRowUnk}[1]{Unknown & \texttt{#1} \\*} +\newcommand{\OpcodeRowSkip}[0]{\\} \begin{center} -\begin{longtable}{TllT} -NOP & & * & 0000 0000 0000 0000 \\ -DAR & & * & 0000 0000 0000 01aa \\ -IAR & & * & 0000 0000 0000 10aa \\ -XXX & NOT USED & & 0000 0000 0000 11xx \\ -ADDARN & & * & 0000 0000 0001 bbaa \\ -HALT & & * & 0000 0000 0010 0001 \\ - & & & \\ -LOOP & & * & 0000 0000 010r rrrr \\ -BLOOP & & * & 00000 0000 011r rrrr \\ - & & & \\ -LRI & & * & 0000 0000 100r rrrr iiii iiii iiii iiii \\ -XXX & NOT USED & * & 0000 0000 101x xxxx \\ -LR & & * & 0000 0000 110r rrrr mmmm mmmm mmmm mmmm \\ -SR & & * & 0000 0000 111r rrrr mmmm mmmm mmmm mmmm \\ - & & & \\ -IF cc & & * & 0000 0010 0111 cccc \\ -JMP cc & & * & 0000 0010 1001 cccc \\ -CALL cc & & * & 0000 0010 1011 cccc \\ -RET cc & & * & 0000 0010 1101 cccc \\ - & & & \\ -ADDI & & * & 0000 001r 0000 0000 iiii iiii iiii iiii \\ -XORI & & * & 0000 001r 0010 0000 iiii iiii iiii iiii \\ -ANDI & & * & 0000 001r 0100 0000 iiii iiii iiii iiii \\ -ORI & & * & 0000 001r 0110 0000 iiii iiii iiii iiii \\ -CMPI & & * & 0000 001r 1000 0000 iiii iiii iiii iiii \\ -ANDCF & & * & 0000 001r 1010 0000 iiii iiii iiii iiii \\ -ANDF & & * & 0000 001r 1100 0000 iiii iiii iiii iiii \\ - & & & \\ -ILRR & & * & 0000 001r 0001 mmaa \\ - & & & \\ -ADDIS & & * & 0000 010d iiii iiii \\ -CMPIS & & * & 0000 011d iiii iiii \\ -LRIS & & * & 0000 1rrr iiii iiii \\ - & & & \\ -LOOPI & & * & 0001 0000 iiii iiii aaaa aaaa aaaa aaaa \\ -BLOOPI & & * & 0001 0001 iiii iiii aaaa aaaa aaaa aaaa \\ -SBSET & & * & 0001 0010 ???? ?iii \\ -SBCLR & & * & 0001 0011 ???? ?iii \\ -LSL/LSR & & * & 0001 010r 0sss ssss \\ -ASL/ASR & & * & 0001 010r 1sss ssss \\ -SI & & * & 0001 0110 iiii iiii mmmm mmmm mmmm mmmm \\ -CALLR & & * & 0001 0111 rrr1 1111 \\ -JMPR & & * & 0001 0111 rrr0 1111 \\ -LRR(I|D|X) & & * & 0001 100x xaar rrrr \\ -SRR(I|D|X) & & * & 0001 101x xaar rrrr \\ -MRR & & * & 0001 11dd ddds ssss \\ - & & & \\ -LRS & & * & 0010 0rrr mmmm mmmm \\ -SRS & & * & 0010 1rrr mmmm mmmm \\ - & & & \\ -XORR & & * & 0011 00sr xxxx xxxx \\ -ANDR & & * & 0011 01sr xxxx xxxx \\ -ORR & & * & 0011 10sr xxxx xxxx \\ -ANDC & & * & 0011 110r xxxx xxxx \\ -ORC & & * & 0011 111r xxxx xxxx \\ - & & & \\ -ADDR & & * & 0100 0ssd xxxx xxxx \\ -ADDAX & & * & 0100 10sd xxxx xxxx \\ -ADD & & * & 0100 110d xxxx xxxx \\ -ADDP & & * & 0100 111d xxxx xxxx \\ - & & & \\ -SUBR & & * & 0101 0ssd xxxx xxxx \\ -SUBAX & & * & 0101 10sd xxxx xxxx \\ -SUB & & * & 0101 110d xxxx xxxx \\ -SUBP & & * & 0101 111d xxxx xxxx \\ - & & & \\ -MOVR & & * & 0110 0ssd xxxx xxxx \\ -MOVAX & & * & 0110 10sd xxxx xxxx \\ -MOV & & * & 0110 110d xxxx xxxx \\ -MOVP & & * & 0110 111d xxxx xxxx \\ - & & & \\ -ADDAXL & & * & 0111 00sr xxxx xxxx \\ -INCM & & * & 0111 010r xxxx xxxx \\ -INC & & * & 0111 011r xxxx xxxx \\ -DECM & & * & 0111 100r xxxx xxxx \\ -DEC & & * & 0111 101r xxxx xxxx \\ -NEG & & * & 0111 110r xxxx xxxx \\ -MOVNP & & * & 0111 111r xxxx xxxx \\ - & & & \\ -NX & & * & 1000 x000 xxxx xxxx \\ -CLR & & * & 1000 x001 xxxx xxxx \\ -CMP & & * & 1000 0010 xxxx xxxx \\ -??? & UNUSED & * & 1000 0011 xxxx xxxx \\ -CLRP & & * & 1000 0100 xxxx xxxx \\ -TSTAXH & & * & 1000 011x xxxx xxxx \\ -M0/M2 & & & 1000 101x xxxx xxxx \\ -CLR15/SET15 & & & 1000 110x xxxx xxxx \\ -SET40/16 & & & 1000 111x xxxx xxxx \\ - & & & \\ -MUL & & * & 1001 a000 xxxx xxxx \\ -ASR16 & & * & 1001 r001 xxxx xxxx \\ -MULMVZ & & * & 1001 a01r xxxx xxxx \\ -MULAC & & * & 1001 a10r xxxx xxxx \\ -MULMV & & * & 1001 a11r xxxx xxxx \\ - & & & \\ -MULX & & * & 101b a000 xxxx xxxx \\ -??? & & & 1010 r001 xxxx xxxx \\ -MULXMVZ & & * & 101b a01r xxxx xxxx \\ -MULXAC & & * & 101b a10r xxxx xxxx \\ -MULXMV & & * & 101b a11r xxxx xxxx \\ - & & & \\ -MULC & & * & 110s a000 xxxx xxxx \\ -CMP & & * & 110x r001 xxxx xxxx \\ -MULCMVZ & & * & 110s a01r xxxx xxxx \\ -MULCAC & & * & 110s a10r xxxx xxxx \\ -MULCMV & & * & 110s a11r xxxx xxxx \\ - & & & \\ -MADDX & & ** & 1110 00st xxxx xxxx \\ -MSUBX & & ** & 1110 01st xxxx xxxx \\ -MADDC & & ** & 1110 10st xxxx xxxx \\ -MSUBC & & ** & 1110 11st xxxx xxxx \\ - & & & \\ -LSL16 & & * & 1111 000r xxxx xxxx \\ -MADD & & * & 1111 001s xxxx xxxx \\ -LSR16 & & * & 1111 010r xxxx xxxx \\ -MSUB & & * & 1111 011s xxxx xxxx \\ -ADDPAXZ & & * & 1111 10ar xxxx xxxx \\ -CLRL & & * & 1111 110r xxxx xxxx \\ -MOVPZ & & * & 1111 111r xxxx xxxx +\begin{longtable}{llr} +Instruction & Opcode & Page \\ \hline +\endhead +\OpcodeRow{0000 0000 0000 0000}{NOP} +\OpcodeRow{0000 0000 0000 01dd}{DAR} +\OpcodeRow{0000 0000 0000 10dd}{IAR} +\OpcodeRow{0000 0000 0000 11dd}{SUBARN} +\OpcodeRow{0000 0000 0001 ssdd}{ADDARN} +\OpcodeRow{0000 0000 0010 0001}{HALT} +\OpcodeRowSkip +\OpcodeRow{0000 0000 010r rrrr}{LOOP} +\OpcodeRow{0000 0000 011r rrrr aaaa aaaa aaaa aaaa}{BLOOP} +\OpcodeRowSkip +\OpcodeRow{0000 0000 100d dddd iiii iiii iiii iiii}{LRI} +\OpcodeRowUnk{0000 0000 101x xxxx} +\OpcodeRow{0000 0000 110d dddd mmmm mmmm mmmm mmmm}{LR} +\OpcodeRow{0000 0000 111s ssss mmmm mmmm mmmm mmmm}{SR} +\OpcodeRowSkip +\OpcodeRow{0000 0010 0111 cccc}{IFcc} +\OpcodeRow{0000 0010 1001 cccc aaaa aaaa aaaa aaaa}{Jcc} +\OpcodeRow{0000 0010 1011 cccc aaaa aaaa aaaa aaaa}{CALLcc} +\OpcodeRow{0000 0010 1101 cccc}{RETcc} +\OpcodeRow{0000 0010 1111 cccc}{RTIcc} +\OpcodeRowSkip +\OpcodeRow{0000 001r 0000 0000 iiii iiii iiii iiii}{ADDI} +\OpcodeRow{0000 001r 0010 0000 iiii iiii iiii iiii}{XORI} +\OpcodeRow{0000 001r 0100 0000 iiii iiii iiii iiii}{ANDI} +\OpcodeRow{0000 001r 0110 0000 iiii iiii iiii iiii}{ORI} +\OpcodeRow{0000 001r 1000 0000 iiii iiii iiii iiii}{CMPI} +\OpcodeRow{0000 001r 1010 0000 iiii iiii iiii iiii}{ANDF} +\OpcodeRow{0000 001r 1100 0000 iiii iiii iiii iiii}{ANDCF} +\OpcodeRowSkip +\OpcodeRow{0000 0010 1100 1010}{LSRN} +\OpcodeRow{0000 0010 1100 1011}{ASRN} +\OpcodeRowSkip +\OpcodeRow{0000 001d 0001 00ss}{ILRR} +\OpcodeRow{0000 001d 0001 01ss}{ILRRD} +\OpcodeRow{0000 001d 0001 10ss}{ILRRI} +\OpcodeRow{0000 001d 0001 11ss}{ILRRN} +\OpcodeRowSkip +\OpcodeRow{0000 010d iiii iiii}{ADDIS} +\OpcodeRow{0000 011d iiii iiii}{CMPIS} +\OpcodeRow{0000 1ddd iiii iiii}{LRIS} +\OpcodeRowSkip +\OpcodeRow{0001 0000 iiii iiii}{LOOPI} +\OpcodeRow{0001 0001 iiii iiii aaaa aaaa aaaa aaaa}{BLOOPI} +\OpcodeRow{0001 0010 xxxx xiii}{SBCLR} +\OpcodeRow{0001 0011 xxxx xiii}{SBSET} +\OpcodeRowSkip +\OpcodeRow{0001 010r 00ii iiii}{LSL} +\OpcodeRow{0001 010r 01ii iiii}{LSR} +\OpcodeRow{0001 010r 10ii iiii}{ASL} +\OpcodeRow{0001 010r 11ii iiii}{ASR} +\OpcodeRow{0001 0110 mmmm mmmm iiii iiii iiii iiii}{SI} +\OpcodeRow{0001 0111 rrr0 cccc}{JRcc} +\OpcodeRow{0001 0111 rrr1 cccc}{CALLRcc} +\OpcodeRowSkip +\OpcodeRow{0001 1000 0ssd dddd}{LRR} +\OpcodeRow{0001 1000 1ssd dddd}{LRRD} +\OpcodeRow{0001 1001 0ssd dddd}{LRRI} +\OpcodeRow{0001 1001 1ssd dddd}{LRRN} +\OpcodeRow{0001 1010 0dds ssss}{SRR} +\OpcodeRow{0001 1010 1dds ssss}{SRRD} +\OpcodeRow{0001 1011 0dds ssss}{SRRI} +\OpcodeRow{0001 1011 1dds ssss}{SRRN} +\OpcodeRow{0001 11dd ddds ssss}{MRR} +\OpcodeRowSkip +\OpcodeRow{0010 0ddd mmmm mmmm}{LRS} +\OpcodeRow{0010 100s mmmm mmmm}{SRSH} +\OpcodeRowUnk{0010 101x mmmm mmmm} +\OpcodeRow{0010 11ss mmmm mmmm}{SRS} +\OpcodeRowSkip +\OpcodeRow{0011 00sd 0xxx xxxx}{XORR} +\OpcodeRow{0011 01sd 0xxx xxxx}{ANDR} +\OpcodeRow{0011 10sd 0xxx xxxx}{ORR} +\OpcodeRow{0011 110d 0xxx xxxx}{ANDC} +\OpcodeRow{0011 111d 0xxx xxxx}{ORC} +\OpcodeRowSkip +\OpcodeRow{0011 000d 1xxx xxxx}{XORC} +\OpcodeRow{0011 001d 1xxx xxxx}{NOT} +\OpcodeRow{0011 01sd 1xxx xxxx}{LSRNRX} +\OpcodeRow{0011 10sd 1xxx xxxx}{ASRNRX} +\OpcodeRow{0011 110d 1xxx xxxx}{LSRNR} +\OpcodeRow{0011 111d 1xxx xxxx}{ASRNR} +\OpcodeRowSkip +\OpcodeRow{0100 0ssd xxxx xxxx}{ADDR} +\OpcodeRow{0100 10sd xxxx xxxx}{ADDAX} +\OpcodeRow{0100 110d xxxx xxxx}{ADD} +\OpcodeRow{0100 111d xxxx xxxx}{ADDP} +\OpcodeRowSkip +\OpcodeRow{0101 0ssd xxxx xxxx}{SUBR} +\OpcodeRow{0101 10sd xxxx xxxx}{SUBAX} +\OpcodeRow{0101 110d xxxx xxxx}{SUB} +\OpcodeRow{0101 111d xxxx xxxx}{SUBP} +\OpcodeRowSkip +\OpcodeRow{0110 0ssd xxxx xxxx}{MOVR} +\OpcodeRow{0110 10sd xxxx xxxx}{MOVAX} +\OpcodeRow{0110 110d xxxx xxxx}{MOV} +\OpcodeRow{0110 111d xxxx xxxx}{MOVP} +\OpcodeRowSkip +\OpcodeRow{0111 00sd xxxx xxxx}{ADDAXL} +\OpcodeRow{0111 010d xxxx xxxx}{INCM} +\OpcodeRow{0111 011d xxxx xxxx}{INC} +\OpcodeRow{0111 100d xxxx xxxx}{DECM} +\OpcodeRow{0111 101d xxxx xxxx}{DEC} +\OpcodeRow{0111 110d xxxx xxxx}{NEG} +\OpcodeRow{0111 111d xxxx xxxx}{MOVNP} +\OpcodeRowSkip +\OpcodeRow{1000 x000 xxxx xxxx}{NX} +\OpcodeRow{1000 r001 xxxx xxxx}{CLR} +\OpcodeRow{1000 0010 xxxx xxxx}{CMP} +\OpcodeRow{1000 0011 xxxx xxxx}{MULAXH} +\OpcodeRow{1000 0100 xxxx xxxx}{CLRP} +\OpcodeRow{1000 0101 xxxx xxxx}{TSTPROD} +\OpcodeRow{1000 011r xxxx xxxx}{TSTAXH} +\OpcodeRowSkip +\OpcodeRow{1000 1010 xxxx xxxx}{M2} +\OpcodeRow{1000 1011 xxxx xxxx}{M0} +\OpcodeRow{1000 1100 xxxx xxxx}{CLR15} +\OpcodeRow{1000 1101 xxxx xxxx}{SET15} +\OpcodeRow{1000 1110 xxxx xxxx}{SET16} +\OpcodeRow{1000 1111 xxxx xxxx}{SET40} +\OpcodeRowSkip +\OpcodeRow{1001 s000 xxxx xxxx}{MUL} +\OpcodeRow{1001 r001 xxxx xxxx}{ASR16} +\OpcodeRow{1001 s01r xxxx xxxx}{MULMVZ} +\OpcodeRow{1001 s10r xxxx xxxx}{MULAC} +\OpcodeRow{1001 s11r xxxx xxxx}{MULMV} +\OpcodeRowSkip +\OpcodeRow{101s t000 xxxx xxxx}{MULX} +\OpcodeRow{1010 d001 xxxx xxxx}{ABS} +\OpcodeRow{1011 r001 xxxx xxxx}{TST} +\OpcodeRow{101s t01r xxxx xxxx}{MULXMVZ} +\OpcodeRow{101s t10r xxxx xxxx}{MULXAC} +\OpcodeRow{101s t11r xxxx xxxx}{MULXMV} +\OpcodeRowSkip +\OpcodeRow{110s t000 xxxx xxxx}{MULC} +\OpcodeRow{110r s001 xxxx xxxx}{CMPAR} +\OpcodeRow{110s t01r xxxx xxxx}{MULCMVZ} +\OpcodeRow{110s t10r xxxx xxxx}{MULCAC} +\OpcodeRow{110s t11r xxxx xxxx}{MULCMV} +\OpcodeRowSkip +\OpcodeRow{1110 00st xxxx xxxx}{MADDX} +\OpcodeRow{1110 01st xxxx xxxx}{MSUBX} +\OpcodeRow{1110 10st xxxx xxxx}{MADDC} +\OpcodeRow{1110 11st xxxx xxxx}{MSUBC} +\OpcodeRowSkip +\OpcodeRow{1111 000r xxxx xxxx}{LSL16} +\OpcodeRow{1111 001s xxxx xxxx}{MADD} +\OpcodeRow{1111 010r xxxx xxxx}{LSR16} +\OpcodeRow{1111 011s xxxx xxxx}{MSUB} +\OpcodeRow{1111 10sd xxxx xxxx}{ADDPAXZ} +\OpcodeRow{1111 110r xxxx xxxx}{CLRL} +\OpcodeRow{1111 111d xxxx xxxx}{MOVPZ} \end{longtable} \end{center} +\pagebreak + \begin{center} Extension Opcodes -\begin{longtable}{TllT} -[D|I|N]R & & * & xxxx xxxx 0000 nnaa \\ -MV & & * & xxxx xxxx 0001 ddss \\ -S[N] & & * & xxxx xxxx 001r rnaa \\ -L[N] & & * & xxxx xxxx 01dd diss \\ -LS[NM|M|N] & & * & xxxx xxxx 10dd ba0r \\ -SL & & * & xxxx xxxx 10dd ba1r \\ -LD[NM|M|N] & & & xxxx xxxx 11mn barr \\ -LD2[NM|M|N] & & & xxxx xxxx 11rm ba11 +\begin{longtable}{llr} +Instruction & Opcode & Page \\ \hline +\OpcodeRow{xxxx xxxx 0000 00xx}{'NOP} +\OpcodeRow{xxxx xxxx 0000 01rr}{'DR} +\OpcodeRow{xxxx xxxx 0000 10rr}{'IR} +\OpcodeRow{xxxx xxxx 0000 11rr}{'NR} +\OpcodeRow{xxxx xxxx 0001 ddss}{'MV} +\OpcodeRow{xxxx xxxx 001s s0dd}{'S} +\OpcodeRow{xxxx xxxx 001s s1dd}{'SN} +\OpcodeRow{xxxx xxxx 01dd d0ss}{'L} +\OpcodeRow{xxxx xxxx 01dd d1ss}{'LN} +\OpcodeRowSkip +\OpcodeRow{xxxx xxxx 10dd 000s}{'LS} +\OpcodeRow{xxxx xxxx 10dd 001s}{'SL} +\OpcodeRow{xxxx xxxx 10dd 010s}{'LSN} +\OpcodeRow{xxxx xxxx 10dd 011s}{'SLN} +\OpcodeRow{xxxx xxxx 10dd 100s}{'LSM} +\OpcodeRow{xxxx xxxx 10dd 101s}{'SLM} +\OpcodeRow{xxxx xxxx 10dd 110s}{'LSNM} +\OpcodeRow{xxxx xxxx 10dd 111s}{'SLNM} +\OpcodeRowSkip +\OpcodeRow{xxxx xxxx 11dr 00ss}{'LD} +\OpcodeRow{xxxx xxxx 11sr 0011}{'LDAX} +\OpcodeRow{xxxx xxxx 11dr 01ss}{'LDN} +\OpcodeRow{xxxx xxxx 11sr 0111}{'LDAXN} +\OpcodeRow{xxxx xxxx 11dr 10ss}{'LDM} +\OpcodeRow{xxxx xxxx 11sr 1011}{'LDAXM} +\OpcodeRow{xxxx xxxx 11dr 11ss}{'LDNM} +\OpcodeRow{xxxx xxxx 11dr 1111}{'LDAXNM} \end{longtable} \end{center}