SVP Reference Guide (2008-02-06)

From Sega Retro

Logo-txt.svg
This is a copy of an "unofficial" document containing original research, for use as a source on Sega Retro. This page likely exists for historical purposes - the contents should ideally be copy-edited and wikified to make better use of Sega Retro's software.
Original source: https://web.archive.org/web/20090402221733/www.sharemation.com/TascoDLX/SVP%20Reference%20Guide%202008.02.06.txt

===================

SVP Reference Guide (annotated)

by Tasco Deluxe < tasco.deluxe @ gmail.com >

Final Update:  2008.02.06 -- fully revised, many corrections

[Previous update:  2007.02.11 -- released to the public]
[Previous update:  2007.01.10 (unpublished) -- revised and corrected]
[Previous update:  2006.04.18 (unpublished) -- revised]
[Previous update:  2005.07.18 (unpublished) -- added annotation]
[First edition:    2004.03.18 (unpublished)]

============================================

Copyright (c) 2004 - 2008, Tasco Deluxe.  Some rights reserved.

This work is licensed under the Creative Commons Attribution License.
To view a copy of this license, visit http://creativecommons.org/licenses/by/2.5/
or send a letter to Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA.

DO NOT modify or redistribute this document without reading the license.

Attribution should be in the form of name (Tasco Deluxe) AND email address (tasco.deluxe @ gmail.com).


*** Disclaimer***

All information herein was obtained by reverse engineering code from the US version of Virtua Racing
for the Sega Genesis system.  Some information may be incorrect and/or incomplete.  Use at your own risk!


### Preface ###

This documentation is based on software analysis.  No hardware tests have been performed as of yet.

SVP code in the US version and EUROPE version of Virtua Racing is identical.  However, an alternate
EUROPE version exists with slightly modified SVP code.  SVP code in the JAPAN version has not been seen.

* The changes in the alternate version's SVP code are very slight.  A function call is added to
SVP commands 0006 and 0007.  The function allows the processing of parameters written by the M68000
related to the rendering of 2D bitmaps.  This functionality hasn't been examined very closely.



### Info ###

Chip:   Sega Virtua Processor (SVP)
Part:   Sega 315-5750
Type:   DSP - custom reportedly based on Samsung SSP16xx core (!precise core model is unknown!)
Clock:  Unknown (!reported to be 23MHz, but unconfirmed!)

(!clock of 23MHz can be derived from dividing the M68000's clock [VCLK] by 3!)

The SVP includes an arithmetic-logic unit (ALU) and a 16x16->32 multiplier.

The exact architecture of the SVP is currently unconfirmed.


### SVP Memory ###

NOTES: 
= Preliminary!  Additional memory may be accessible.

* 1 Word equals 16 bits (2 bytes)

Internal
--------
RAM Bank A (RAM0)        256 Words
RAM Bank B (RAM1)        256 Words
Instruction RAM (IRAM)   1 KWord     (!may also be known as Program Memory [PRAM]!)

External
--------
ROM                      64 KWord for code and data / up to 1 MWord for data (programmable access)
Data RAM (DRAM)          64 KWord (!more may be technically possible, but VR uses 64 KWord!)


### SVP Registers ###

NOTES:
= Preliminary!  Actual register capabilities may differ.  Additional capabilities may exist.
= Explanation of registers can be found in the SVP Register Guide.
= Internal size of Accumulator register may be larger than stated.

* Unless stated otherwise, registers are 16-bit

Primary Registers
-----------------
r_0   Null Register (!a.k.a. REG0!)
r_1   Multiplier Input X
r_2   Multiplier Input Y
r_3   Accumulator (High)
r_4   Status Register (!a.k.a. ST!)
r_5   Stack Register (!in VR, used solely for function calls [return addresses]!)
r_6   Program Counter (!a.k.a. PC!)
r_7   Product Register (!a.k.a. P!) [read-only, 32 bits]
r_8   Programmable Memory Access Register 0 // External Status [r] / External Control [w]
r_9   Programmable Memory Access Register 1 // ???
r_a   Programmable Memory Access Register 2 // ???
r_b   Programmable Memory Access Register 3 // External Command Register [r/w]
r_c   Programmable Memory Access Register 4
r_d   ??? (!Not used in VR!)
r_e   Programmable Memory Access Control Register
r_f   Accumulator Low - Extension Register (!also used in connection with r_e!)

acc   Accumulator Register [alias, 32 bits, a concatenation of r_3 and r_f]


Pointer Registers
-----------------
p_A0    Pointer Register 0, RAM bank A [8-bit]
p_A1    Pointer Register 1, RAM bank A [8-bit]
p_A2    Pointer Register 2, RAM bank A [8-bit]
p_B0    Pointer Register 0, RAM bank B [8-bit]
p_B1    Pointer Register 1, RAM bank B [8-bit]
p_B2    Pointer Register 2, RAM bank B [8-bit]
dp_A0   Data Pointer Register 0, RAM bank A
dp_A1   Data Pointer Register 1, RAM bank A
dp_A2   Data Pointer Register 2, RAM bank A
dp_A3   Data Pointer Register 3, RAM bank A
dp_B0   Data Pointer Register 0, RAM bank B
dp_B1   Data Pointer Register 1, RAM bank B
dp_B2   Data Pointer Register 2, RAM bank B
dp_B3   Data Pointer Register 3, RAM bank B


### SVP Instructions ###

Addressing Modes
----------------

NOTES:
= Addressing modes are listed for reference with Instruction Encodings.
= Modes marked as ??? are not referenced in VR's SVP code.  Some modes are assumed based on pattern.

KEY
~~~~~~~~~~~~~~~~~~~~~~
'[ ]'   RAM accessed
'( )'   ROM accessed
'??++'  Post-increment 
'??--'  Post-decrement (modulo-affected -- see Register Guide)
'??+!'  Post-increment (modulo-affected -- see Register Guide)
~~~~~~~~~~~~~~~~~~~~~~

ptr_A?
======
0 = [p_A0]    1 = [p_A1]    2 = [p_A2]    3 = dp_A0
4 = [p_A0++]  5 = [p_A1++]  6 = [p_A2++]  7 = dp_A1
8 = [p_A0--]  9 = [p_A1--]  a = [p_A2--]  b = dp_A2
c = [p_A0+!]  d = [p_A1+!]  e = [p_A2+!]  f = dp_A3

ptr_B?
======
0 = [p_B0]    1 = [p_B1]    2 = [p_B2]    3 = dp_B0
4 = [p_B0++]  5 = [p_B1++]  6 = [p_B2++]  7 = dp_B1
8 = [p_B0--]  9 = [p_B1--]  a = [p_B2--]  b = dp_B2
c = [p_B0+!]  d = [p_B1+!]  e = [p_B2+!]  f = dp_B3

*ptr_A?
=======
0 = ([p_A0]++)  1 = ([p_A1]++)  2 = ([p_A2]++)  3 = (dp_A0++)
4 = ???         5 = ???         6 = ???         7 = (dp_A1++)
8 = ???         9 = ???         a = ???         b = (dp_A2++)
c = ???         d = ???         e = ???         f = (dp_A3++)

*ptr_B?
=======
0 = ([p_B0]++)  1 = ([p_B1]++)  2 = ([p_B2]++)  3 = (dp_B0++)
4 = ???         5 = ???         6 = ???         7 = (dp_B1++)
8 = ???         9 = ???         a = ???         b = (dp_B2++)
c = ???         d = ???         e = ???         f = (dp_B3++)


Condition Codes
---------------

NOTES:
= Additional condition codes (such as overflow [OV]) may exist but are not referenced by VR's SVP code.

z    result is zero 
nz   result is not zero
s    result is signed [negative]
ns   result is not signed [positive or zero]

Flags are set based on the result of an instruction.  LD instructions do not affect flags.


Instruction Set
---------------

NOTES:
= Unused instructions are not described here.  Consider this list incomplete.
= The instruction mnemonics listed are reportedly the same as those used in the SSP1610 manual.

SYNTAX:  instruction   destination, source

Operand descriptions:

reg         primary register                r_0 thru r_f [some registers may be invalid for certain instructions]
ptr         pointer register                p_?? [see Addressing Modes]
(ptr)       pointer reference               ptr_?? [see Addressing Modes]
((ptr))     pointer double-reference        *ptr_?? [see Addressing Modes]
imm         immediate word                  16-bit data [immediately follows the instruction word]
short imm   short immediate word            8-bit data, zero-extended to 16 bits where appropriate [encoded in instruction word]
RAM         indexed RAM word                16-bit RAM word, referenced by 8-bit index [encoded in instruction word]
r_3         accumulator high register       r_3 register, implied [generally for arithmetic/logic instructions]
acc         accumulator register            r_f:r_3 registers, implied [generally for multiply instructions]
(r_3)       r_3 indirect                    16-bit ROM word, referenced by 16-bit index in r_3

Instruction List:

ld      Load data

        - ld    reg, reg
        - ld    reg, (ptr)
        - ld    (ptr), reg
        - ld    r_3, RAM
        - ld    RAM, r_3
        - ld    reg, imm
        - ld    (ptr), imm
        - ld    reg, ((ptr))
        - ld    reg, ptr
        - ld    ptr, reg
        - ld    ptr, short imm
        - ld    reg, (r_3)
        
        special cases:

        - ld    acc, r_7 (encoded as ld r_3, r_7 -- value in r_7 is shifted left once before load)
        - nop            (encoded as ld r_0, r_0 -- no operation)

add     Add

        - add   r_3, reg
        - add   r_3, (ptr)
        - add   r_3, RAM
        - add   r_3, imm
        - add   r_3, ((ptr))
        - add   r_3, short imm

        special case:

        - add   acc, r_7 (encoded as add r_3, r_7 -- value in r_7 is shifted left once before add)

sub     Subtract

        - sub   r_3, reg
        - sub   r_3, (ptr)
        - sub   r_3, RAM
        - sub   r_3, imm
        - sub   r_3, ((ptr))
        - sub   r_3, short imm

and     Logical AND

        - and   r_3, reg
        - and   r_3, (ptr)
        - and   r_3, RAM
        - and   r_3, imm
        - and   r_3, short imm

        * NOTE:  and r_3, short 0x00 is used often in VR's SVP code and may be used to clear acc.

        * There is a little discrepancy about the use of . and r_3, r_3 . versus . and r_3, r_0 .
          Both instruction set the flags based on r_3.  The former instruction is used once in
          VR's SVP code but its doubtful that it has a different effect.

or      Logical OR

        - or    r_3, reg
        - or    r_3, RAM
        - or    r_3, imm
        - or    r_3, short imm

eor     Logical Exclusive OR

        - eor   r_3, reg
        - eor   r_3, (ptr)
        - eor   r_3, imm
        - eor   r_3, ((ptr))

cmp     Compare

        - cmp   r_3, (ptr)
        - cmp   r_3, RAM
        - cmp   r_3, imm
        - cmp   r_3, short imm

mld     Load multiplier

        - mld   acc, (ptr), (ptr)

        * set acc to zero
        * load X and Y registers (r_1 and r_2) with referenced values

mpya    Multiply and Accumulate
 
        - mpya  acc, (ptr), (ptr)

        * add value in product register (r_7) to acc
        * load X and Y registers (r_1 and r_2) with referenced values

        NOTE:  The value added to acc is the value previously in the product register.

mpys    Multiply and Subtract

        - mpys  acc, (ptr), (ptr)

        * subtract value in product register (r_7) from acc
        * load X and Y registers (r_1 and r_2) with referenced values

        NOTE:  The value subtracted from acc is the value previously in the product register.

bra     Branch to absolute address

        - bra   imm
        - bra   z, imm   [conditional]
        - bra   nz, imm  [conditional]
        - bra   s, imm   [conditional]
        - bra   ns, imm  [conditional]

call    Call subroutine (absolute address)

        - call  imm
        - call  z, imm   [conditional]
        - call  nz, imm  [conditional]
        - call  s, imm   [conditional]
        - call  ns, imm  [conditional]

shr     Logical shift right

        - shr   acc

shl     Logical shift left

        - shl   acc

neg     Negate (2's complement)

        - neg   acc
        - neg   nz, acc  [conditional]

abs     Absolute value

        - abs   acc

setie   Set Interrupt Enable flag

        - setie



Instruction Encodings
---------------------

In general, the encoding format (16 bits) is:

3 bits indicate the instruction type
4 bits indicate the instruction variant
1 bit indicates the RAM bank
8 bits indicate operands or variable data

* Some instructions are followed by 16 bits of immediate data, nnnn.

Operand/variable data is listed as xy.  Depending on the instruction,
x and y can either be interpreted as separate 4-bit values (referring to
registers and/or addressing modes), or a single 8-bit value (as an index
or variable data).  If either x or y do not appear in the listing, it is
considered unused and is probably ignored (commonly, the value is zero).

NOTES:
= All instructions described below are contained in VR's SVP code.
= Instructions listed as ??? without any notation are NOT referenced by VR's SVP code.
= In any case where a listed instruction is questionable, a note will follow.

Instruction Encoding List:

00xy       ld     r_x, r_y
01xy       ???
02xy       ld     r_x, ptr_Ay
03xy       ld     r_x, ptr_By
04xy       ld     ptr_Ay, r_x
05xy       ld     ptr_By, r_x
06xy       ld     r_3, A[xy]
07xy       ld     r_3, B[xy]
08xy nnnn  ld     r_x, nnnn
09xy       ???
0axy       ld     r_x, *ptr_Ay
0bxy       ld     r_x, *ptr_By
0cxy nnnn  ld     ptr_Ay, nnnn
0dxy nnnn  ld     ptr_By, nnnn
0exy       ld     A[xy], r_3
0fxy       ld     B[xy], r_3
10xy       ???
11xy       ???
12xy       ld     r_x, p_Ay
13xy       ld     r_x, p_By
14xy       ld     p_Ay, r_x
15xy       ld     p_By, r_x
16xy       ???
17xy       ???
18xy       ld     p_A0, xy
19xy       ld     p_A1, xy
1axy       ld     p_A2, xy
1bxy       ???
1cxy       ld     p_B0, xy
1dxy       ld     p_B1, xy
1exy       ld     p_B2, xy
1fxy       ???

20xy       sub    r_3, r_y
21xy       ???
22xy       sub    r_3, ptr_Ay
23xy       sub    r_3, ptr_By
24xy       ???
25xy       ???
26xy       sub    r_3, A[xy]
27xy       sub    r_3, B[xy]
28xy nnnn  sub    r_3, nnnn
29xy       ???
2axy       sub    r_3, *ptr_Ay
2bxy       sub    r_3, *ptr_By
2cxy       ???
2dxy       ???
2exy       ???
2fxy       ???
30xy       ???
31xy       ???
32xy       ???
33xy       ???
34xy       ???
35xy       ???
36xy       ???
37xy       mpys   ptr_Ay, ptr_Bx
38xy       sub    r_3, xy
39xy       ???
3axy       ???
3bxy       ???
3cxy       ???
3dxy       ???
3exy       ???
3fxy       ???

40xy       ???
41xy       ???
42xy       ???
43xy       ???
44xy       ???
45xy       ???
46xy       ???
47xy       ???
48xy nnnn  ...
      x=0  call   nnnn
      x=5  call   nz, nnnn
      x=7  call   ns, nnnn
49xy nnnn  ...
      x=5  call   z, nnnn
      x=7  call   s, nnnn
4axy       ld     r_x, (r_3)
4bxy       ???
4cxy nnnn  ...
      x=0  bra    nnnn
      x=5  bra    nz, nnnn
      x=7  bra    ns, nnnn
4dxy nnnn  ...
      x=5  bra    z, nnnn
      x=7  bra    s, nnnn
4exy       ???
4fxy       ???
50xy       ???
51xy       ???
52xy       ???
53xy       ???
54xy       ???
55xy       ???
56xy       ???
57xy       ???
58xy       ???
59xy       ???
5axy       ???
5bxy       ???
5cxy       ???
5dxy       ???
5exy       ???
5fxy       ???

60xy       cmp    r_3, r_y
61xy       ???
62xy       cmp    r_3, ptr_Ay
63xy       cmp    r_3, ptr_By
64xy       ???
65xy       ???
66xy       cmp    r_3, A[xy]
67xy       cmp    r_3, B[xy]
68xy nnnn  cmp    r_3, nnnn
69xy       ???
6axy       ???
6bxy       ???
6cxy       ???
6dxy       ???
6exy       ???
6fxy       ???
70xy       ???
71xy       ???
72xy       ???
73xy       ???
74xy       ???
75xy       ???
76xy       ???
77xy       ???
78xy       cmp    r_3, xy
79xy       ???
7axy       ???
7bxy       ???
7cxy       ???
7dxy       ???
7exy       ???
7fxy       ???

80xy       add    r_3, r_y
81xy       ???
82xy       add    r_3, ptr_Ay
83xy       add    r_3, ptr_By
84xy       ???
85xy       ???
86xy       add    r_3, A[xy]
87xy       add    r_3, B[xy]
88xy nnnn  add    r_3, nnnn
89xy       ???
8axy       add    r_3, *ptr_Ay
8bxy       add    r_3, *ptr_By
8cxy       ???
8dxy       ???
8exy       ???
8fxy       ???
90xy       ...
    xy=02  shr    acc
    xy=03  shl    acc
    xy=06  neg    acc
    xy=07  abs    acc
    xy=56  neg    nz, acc               (!not 100% on the condition, but probable!)
91xy       ???
92xy       ???
93xy       ???
94xy       ...
    xy=05  setie
95xy       ???
96xy       ???
97xy       mpya   acc, ptr_Ay, ptr_Bx
98xy       add    r_3, xy
99xy       ???
9axy       ???
9bxy       ???
9cxy       ???
9dxy       ???
9exy       ???
9fxy       ???

a0xy       and    r_3, r_y
a1xy       ???
a2xy       and    r_3, ptr_Ay
a3xy       and    r_3, ptr_By
a4xy       ???
a5xy       ???
a6xy       and    r_3, A[xy]
a7xy       and    r_3, B[xy]
a8xy nnnn  and    r_3, nnnn
a9xy       ???
aaxy       ???
abxy       ???
acxy       ???
adxy       ???
aexy       ???
afxy       ???
b0xy       ???
b1xy       ???
b2xy       ???
b3xy       ???
b4xy       ???
b5xy       ???
b6xy       ???
b7xy       mld    acc, ptr_Ay, ptr_Bx
b8xy       and    r_3, xy
b9xy       ???
baxy       ???
bbxy       ???
bcxy       ???
bdxy       ???
bexy       ???
bfxy       ???

c0xy       or     r_3, r_y
c1xy       ???
c2xy       ???
c3xy       ???
c4xy       ???
c5xy       ???
c6xy       or     r_3, A[xy]
c7xy       or     r_3, B[xy]
c8xy nnnn  or     r_3, nnnn
c9xy       ???
caxy       ???
cbxy       ???
ccxy       ???
cdxy       ???
cexy       ???
cfxy       ???
d0xy       ???
d1xy       ???
d2xy       ???
d3xy       or     r_3, p_By
d4xy       ???
d5xy       ???
d6xy       ???
d7xy       ???
d8xy       or     r_3, xy
d9xy       ???
daxy       ???
dbxy       ???
dcxy       ???
ddxy       ???
dexy       ???
dfxy       ???

e0xy       eor    r_3, r_y
e1xy       ???
e2xy       eor    r_3, ptr_Ay
e3xy       eor    r_3, ptr_By
e4xy       ???
e5xy       ???
e6xy       ???
e7xy       ???
e8xy nnnn  eor    r_3, nnnn
e9xy       ???
eaxy       eor    r_3, *ptr_Ay
ebxy       eor    r_3, *ptr_By
ecxy       ???
edxy       ???
eexy       ???
efxy       ???
f0xy       ???
f1xy       ???
f2xy       ???
f3xy       ???
f4xy       ???
f5xy       ???
f6xy       ???
f7xy       ???
f8xy       ???
f9xy       ???
faxy       ???
fbxy       ???
fcxy       ???
fdxy       ???
fexy       ???
ffxy       ???


Instruction Timings
-------------------

The timings of SVP instructions are unconfirmed, but the DSP, generally,
should be able to execute one instruction per clock cycle.

Memory timing may be significant but it has not been evaluated.