Skip to content

Condition flags

Javier de Silóniz Sandino edited this page Mar 28, 2021 · 22 revisions

This document attempts to cover all condition flags used by the DSP, including those not used by Virtua Racing (and thus not currently emulated).

_Note: Even though the goal is to cover all information about them (including what's currently understood) in order to serve as a programming guide, I'll first focus on what unknowns I can verify by testing on real hardware.

Condition flags

The ST register contains multiple bits that toggle after some operations are run. Some of these were very well known (the "zero" and "negative" flags - used frequently in Virtua Racing) but others weren't. This section will try to cover them all. Here's what the ST register looks like (according to the current documentation available):

F E D C B A 9 8 7 6 5 4 3 2 1 0
N OV Z L USR1 USR0 MACS OP IE ST6 ST5 RB1 RB0 RPL2 RPL1 RPL0
  • N: Negative. Active when an operation causes the accumulator become negative (i.e.: 0x0000 - 0x0001).
  • OV: Overflow. When an operation causes the accumulator to cross the threshold of two's integer sign. (i.e.: 0x7FFF + 0x0001 / 0x8000 + 0x0001).
  • Z: Zero. When an operation causes the accumulator to become zero.
  • L: Integer carry. When an operation causes the accumulator to overflow beyond the 16-bit integer limit. (i.e.: 0xFFFF + 0x0001).
  • USR1 and USR0: User Inputs. Wired to an external pin in the DSP, the SVP can send signals to the DSP through these bits. USR0 toggles at every read of the ST register from the DSP side (i.e.: first ST read will yield USR0 as 0, next one will be 1, following one will be 0, etc...). I've never seen USR1 active.
  • MAC Shift: when set to 0, results from product register gets shifted left once when loaded to the accumulator register (i.e.: after executing mpya, mpys, add a, p...), LSB in the result being filled as o. Otherwise, results from the product register are copied as it is. Virtua Racing seems to keep it active (set to 0).
  • OP: Overflow protection. When toggled by the developer, operations that overflow beyond two's integer sign won't have effect (i.e.: 0x7FFF + 0x0001 = 0x7FFF). It seems that even when toggled, OV flag will become active after the operation finishes.
  • IE: when written to activates interrupts. When read, it always returns zero.
  • ST6 and ST5: User outputs. Allow the developer to send signals to the circuitry external to the DSP. In this case these are extensively used by the memory adapter logic outside the DSP, accessible through the external registers.
  • RB1/RB0: Allow extending the default address for RAM bank addressing through registers r3 and r7. i.e.: having (r3|10) together with RB[1:0]=11, that addressing will point to RAM Bank 0 address 1100, allowing 16 different addresses to be used as a "stack" or direct register of sorts.
  • RPL: Pointer Register Loop. When toggled they allow to modify the behavior of rX registers when accessed using modulo-increment/modulo-decrement address modes. When equal to 0, modulo-increment/decrement will add or substract one from the pointer address. When different than 0, a power of two will be used (i.e.: 011 will add or substract 8 to the pointer after the memory address).

Setting and resetting state flags

The MOD F instruction allows the DSP to set or reset the state flags in the ST register. The SSP16ASM assembler currently support a few of them, but more flags (and therefore instruction variations) actually exist.

What follows are some test of the instruction and unmapped opcodes that I used and what effect did they have on the ST register (every instruction was executed after manually setting ST to 0x0000):

(Note: this still requires lots of additional testing, please take the following with a heavy grain of salt)

Instruction Effect Set bits
mod f, setie set interrupt enable IE bit is not readable in ST register
mod f, resie reset interrupt enable -
mod f, setop set overflow protection 8
mod f, resop reset overflow protection -
mod f, setl set carry flag C
mod f, resl reset carry flag -
mod f, set set IE, OP, and L C, 8
mod f, res reset IE, OP and L -

Use in conditional branching

Some of these conditional flags can be used for conditional branching. Virtua Racing only uses Z and N so these are the only flags emulated for the entire branching instructions. These instructions include 5 bits in its opcode to define these conditions. i.e.:

BRA cond, addr

F E D C B A 9 8 7 6 5 4 3 2 1 0
0 1 0 0 1 1 0 F 0 C C C 0 0 0 0

The following values for F and C[2:0] have been verified:

F C[2:0] Condition Notes
0 000 always
0 001 reserved No effect.
0 010 usr0=0
0 011 usr1=0
0 100 l=0
0 101 z=0
0 110 ov=0
0 111 n=0
1 000 always Not totally verified
1 001 reserved No effect.
1 010 usr0=1
1 011 usr1=1
1 100 l=1
1 101 z=1
1 110 ov=1
1 111 n=1