Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge pull request #10692 from Pokechu22/dsp-manual-set40-and-write-b…
…acklog

docs/DSP: Add sections on 16-bit and 40-bit modes and on main and extended opcode writing to the same register
  • Loading branch information
lioncash committed Jun 3, 2022
2 parents c8ab236 + f47dfc3 commit f7f47d3
Show file tree
Hide file tree
Showing 7 changed files with 567 additions and 102 deletions.
29 changes: 15 additions & 14 deletions Source/Core/Core/DSP/Interpreter/DSPIntArithmetic.cpp
Expand Up @@ -45,7 +45,7 @@ void Interpreter::clrl(const UDSPInstruction opc)
//----

// ANDCF $acD.m, #I
// 0000 001r 1100 0000
// 0000 001d 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 to I.
Expand All @@ -61,7 +61,7 @@ void Interpreter::andcf(const UDSPInstruction opc)
}

// ANDF $acD.m, #I
// 0000 001r 1010 0000
// 0000 001d 1010 0000
// 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
Expand All @@ -81,7 +81,7 @@ void Interpreter::andf(const UDSPInstruction opc)

// TST
// 1011 r001 xxxx xxxx
// Test accumulator %acR.
// Test accumulator $acR.
//
// flags out: --xx xx00
void Interpreter::tst(const UDSPInstruction opc)
Expand Down Expand Up @@ -143,11 +143,12 @@ void Interpreter::cmpaxh(const UDSPInstruction opc)
ZeroWriteBackLog();
}

// CMPI $amD, #I
// 0000 001r 1000 0000
// CMPI $acD, #I
// 0000 001d 1000 0000
// iiii iiii iiii iiii
// Compares mid accumulator $acD.hm ($amD) with sign extended immediate value I.
// Although flags are being set regarding whole accumulator register.
// Compares accumulator with immediate. Comparison is executed
// by subtracting the immediate (16-bit sign extended) from mid accumulator
// $acD.hm and computing flags based on whole accumulator $acD.
//
// flags out: x-xx xxxx
void Interpreter::cmpi(const UDSPInstruction opc)
Expand All @@ -166,8 +167,8 @@ void Interpreter::cmpi(const UDSPInstruction opc)

// CMPIS $acD, #I
// 0000 011d iiii iiii
// Compares accumulator with short immediate. Comaprison is executed
// by subtracting short immediate (8bit sign extended) from mid accumulator
// Compares accumulator with short immediate. Comparison is executed
// by subtracting the short immediate (8-bit sign extended) from mid accumulator
// $acD.hm and computing flags based on whole accumulator $acD.
//
// flags out: x-xx xxxx
Expand Down Expand Up @@ -320,7 +321,7 @@ void Interpreter::notc(const UDSPInstruction opc)
}

// XORI $acD.m, #I
// 0000 001r 0010 0000
// 0000 001d 0010 0000
// iiii iiii iiii iiii
// Logic exclusive or (XOR) of accumulator mid part $acD.m with
// immediate value I.
Expand All @@ -337,7 +338,7 @@ void Interpreter::xori(const UDSPInstruction opc)
}

// ANDI $acD.m, #I
// 0000 001r 0100 0000
// 0000 001d 0100 0000
// iiii iiii iiii iiii
// Logic AND of accumulator mid part $acD.m with immediate value I.
//
Expand All @@ -354,7 +355,7 @@ void Interpreter::andi(const UDSPInstruction opc)
}

// ORI $acD.m, #I
// 0000 001r 0110 0000
// 0000 001d 0110 0000
// iiii iiii iiii iiii
// Logic OR of accumulator mid part $acD.m with immediate value I.
//
Expand Down Expand Up @@ -489,8 +490,8 @@ void Interpreter::addaxl(const UDSPInstruction opc)
UpdateSR64Add(acc, acx, GetLongAcc(dreg));
}

// ADDI $amR, #I
// 0000 001r 0000 0000
// ADDI $acD, #I
// 0000 001d 0000 0000
// iiii iiii iiii iiii
// Adds immediate (16-bit sign extended) to mid accumulator $acD.hm.
//
Expand Down
28 changes: 24 additions & 4 deletions Source/Core/Core/DSP/Interpreter/DSPInterpreter.cpp
Expand Up @@ -16,8 +16,23 @@

namespace DSP::Interpreter
{
// Not needed for game ucodes (it slows down interpreter + easier to compare int VS
// dspjit64 without it)
// Correctly handle instructions such as `INC'L $ac0 : $ac0.l, @$ar0` (encoded as 0x7660) where both
// the main opcode and the extension opcode modify the same register. See the "Extended opcodes"
// section in the manual for more details. No official uCode writes to the same register twice like
// this, so we don't emulate it by default (and also don't support it in the recompiler).
//
// Dolphin only supports this behavior in the interpreter when PRECISE_BACKLOG is defined.
// In ExecuteInstruction, if an extended opcode is in use, the extended opcode's behavior is
// executed first, followed by the main opcode's behavior. The extended opcode does not directly
// write to registers, but instead records the writes into a backlog (WriteToBackLog). The main
// opcode calls ZeroWriteBackLog after it is done reading the register values; this directly
// writes zero to all registers that have pending writes in the backlog. The main opcode then is
// free to write directly to registers it changes. Afterwards, ApplyWriteBackLog bitwise-ors the
// value of the register and the value in the backlog; if the main opcode didn't write to the
// register then ZeroWriteBackLog means that the pending value is being or'd with zero, so it's
// used without changes. When PRECISE_BACKLOG is not defined, ZeroWriteBackLog does nothing and
// ApplyWriteBackLog overwrites the register value with the value from the backlog (so writes from
// extended opcodes "win" over the main opcode).
//#define PRECISE_BACKLOG

Interpreter::Interpreter(DSPCore& dsp) : m_dsp_core{dsp}
Expand Down Expand Up @@ -809,7 +824,7 @@ void Interpreter::ConditionalExtendAccum(int reg)
void Interpreter::ApplyWriteBackLog()
{
// Always make sure to have an extra entry at the end w/ -1 to avoid
// infinitive loops
// infinite loops
for (int i = 0; m_write_back_log_idx[i] != -1; i++)
{
u16 value = m_write_back_log[i];
Expand All @@ -823,6 +838,11 @@ void Interpreter::ApplyWriteBackLog()
}
}

// The ext ops are calculated in parallel with the actual op. That means that
// both the main op and the ext op see the same register state as input. The
// output is simple as long as the main and ext ops don't change the same
// register. If they do the output is the bitwise OR of the result of both the
// main and ext ops.
void Interpreter::WriteToBackLog(int i, int idx, u16 value)
{
m_write_back_log[i] = value;
Expand All @@ -840,7 +860,7 @@ void Interpreter::ZeroWriteBackLog()
{
#ifdef PRECISE_BACKLOG
// always make sure to have an extra entry at the end w/ -1 to avoid
// infinitive loops
// infinite loops
for (int i = 0; m_write_back_log_idx[i] != -1; i++)
{
OpWriteRegister(m_write_back_log_idx[i], 0);
Expand Down
5 changes: 0 additions & 5 deletions Source/Core/Core/DSP/Interpreter/DSPInterpreter.h
Expand Up @@ -235,11 +235,6 @@ class Interpreter

void ConditionalExtendAccum(int reg);

// The ext ops are calculated in parallel with the actual op. That means that
// both the main op and the ext op see the same register state as input. The
// output is simple as long as the main and ext ops don't change the same
// register. If they do the output is the bitwise OR of the result of both the
// main and ext ops.
void WriteToBackLog(int i, int idx, u16 value);
void ZeroWriteBackLog();
void ZeroWriteBackLogPreserveAcc(u8 acc);
Expand Down
27 changes: 14 additions & 13 deletions Source/Core/Core/DSP/Jit/x64/DSPJitArithmetic.cpp
Expand Up @@ -53,7 +53,7 @@ void DSPEmitter::clrl(const UDSPInstruction opc)
//----

// ANDCF $acD.m, #I
// 0000 001r 1100 0000
// 0000 001d 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 to I.
Expand Down Expand Up @@ -88,7 +88,7 @@ void DSPEmitter::andcf(const UDSPInstruction opc)
}

// ANDF $acD.m, #I
// 0000 001r 1010 0000
// 0000 001d 1010 0000
// 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
Expand Down Expand Up @@ -126,7 +126,7 @@ void DSPEmitter::andf(const UDSPInstruction opc)

// TST
// 1011 r001 xxxx xxxx
// Test accumulator %acR.
// Test accumulator $acR.
//
// flags out: --xx xx00
void DSPEmitter::tst(const UDSPInstruction opc)
Expand Down Expand Up @@ -220,11 +220,12 @@ void DSPEmitter::cmpaxh(const UDSPInstruction opc)
}
}

// CMPI $amD, #I
// 0000 001r 1000 0000
// CMPI $acD, #I
// 0000 001d 1000 0000
// iiii iiii iiii iiii
// Compares mid accumulator $acD.hm ($amD) with sign extended immediate value I.
// Although flags are being set regarding whole accumulator register.
// Compares accumulator with immediate. Comparison is executed
// by subtracting the immediate (16-bit sign extended) from mid accumulator
// $acD.hm and computing flags based on whole accumulator $acD.
//
// flags out: x-xx xxxx
void DSPEmitter::cmpi(const UDSPInstruction opc)
Expand Down Expand Up @@ -257,7 +258,7 @@ void DSPEmitter::cmpi(const UDSPInstruction opc)
// CMPIS $acD, #I
// 0000 011d iiii iiii
// Compares accumulator with short immediate. Comparison is executed
// by subtracting short immediate (8bit sign extended) from mid accumulator
// by subtracting the short immediate (8-bit sign extended) from mid accumulator
// $acD.hm and computing flags based on whole accumulator $acD.
//
// flags out: x-xx xxxx
Expand Down Expand Up @@ -472,7 +473,7 @@ void DSPEmitter::notc(const UDSPInstruction opc)
}

// XORI $acD.m, #I
// 0000 001r 0010 0000
// 0000 001d 0010 0000
// iiii iiii iiii iiii
// Logic exclusive or (XOR) of accumulator mid part $acD.m with
// immediate value I.
Expand All @@ -498,7 +499,7 @@ void DSPEmitter::xori(const UDSPInstruction opc)
}

// ANDI $acD.m, #I
// 0000 001r 0100 0000
// 0000 001d 0100 0000
// iiii iiii iiii iiii
// Logic AND of accumulator mid part $acD.m with immediate value I.
//
Expand All @@ -523,7 +524,7 @@ void DSPEmitter::andi(const UDSPInstruction opc)
}

// ORI $acD.m, #I
// 0000 001r 0110 0000
// 0000 001d 0110 0000
// iiii iiii iiii iiii
// Logic OR of accumulator mid part $acD.m with immediate value I.
//
Expand Down Expand Up @@ -706,8 +707,8 @@ void DSPEmitter::addaxl(const UDSPInstruction opc)
}
}

// ADDI $amR, #I
// 0000 001r 0000 0000
// ADDI $acD, #I
// 0000 001d 0000 0000
// iiii iiii iiii iiii
// Adds immediate (16-bit sign extended) to mid accumulator $acD.hm.
//
Expand Down

0 comments on commit f7f47d3

Please sign in to comment.