SPU Mark II - Architecture

Overview

This is the documentation for the SPU Mark II instruction set architecture. It is a stack based 16 bit processor that features a highly configurable instruction set.

Table Of Contents

SPU Mark II - ArchitectureOverviewTable Of ContentsDocumentation StyleNumbersBit RangesWordingUndefined (value)Undefined behaviorCPU VariantsSPU Mark II ArchitectureBasic PropertiesWord Encoding and SignednessMemory AccessCPU RegistersStack Pointer (SP)Base Pointer (BP)Instruction Pointer (IP)Flag Register (FR)Interrupt Register (IR)Instruction EncodingConditional ExecutionArgument Input 0 and 1Flag ModificationResult OutputCommandsMemory AccessFetch-Execute-CycleInterrupt handlingMaskingInterrupt TableResetNMIBUSARITHIRQPrioritiesChip I/OsChangelogv1.8v1.7v1.6v1.5v1.4v1.3v1.2v1.1v1.0TODO

Documentation Style

Numbers

Numbers are documented in three ways:

Decimal numbers are written the usual style. Hexadecimal numbers are prefixed by a 0x. Binary numbers are postfixed with a subscript ₂. If both decimal and binary notation are given, the decimal notation is postfixed with a subscript ₁₀ to make the difference clear.

Examples:

Bit Ranges

This document uses some special notations to define bit ranges or indices.

[n] is a placeholder for the nth bit in a word.

[n:m] is a placeholder for the bit range from the nth (highest significant bit) to the mth (lowest significant bit).

So [3] means the the bit with the significance of and [7:4] is the upper nibble of a 8 bit word.

Wording

Undefined (value)

If a value is defined undefined, its initial value may be any possible value. The value may change between power cycles or even after a reset. Each bit must be considered random.

Undefined behavior

Undefined behavior is used similar to the way the C standard uses this word. It means that if a situation happens where undefined behavior would occur, the results of the operation may be anything. This can be a no-op, any state or memory change or even a CPU hang or hard reset (may even requires a power cycle).

CPU Variants

This document specifies two different variants for the SPU Mark II architecture:

The SPU Mark II-L is a reduced version of the default instruction set and features no interrupt handling, thus making an implementation of the ISA much easier.

SPU Mark II Architecture

The SPU Mark II (Stack Processing Unit Mark II) is a 16 bit processor that, in contrary to the most popular CPUs, works primarily with a stack instead of registers. It features a RISC instruction set with highly configurable instructions. Although being a stack processor it still requires some basic registers to work. These registers are either accessed indirectly (like the IP register) or by special instructions (like BP or SP register).

Each instruction is composed of a configuration part and a command part. Commands are the actual function of the instruction like STORE8 or MUL. Each command has two input variables input0 and input1 which contain the two command parameters. A command also has an output value.

In which way the command parameters are filled and the result is processed is defined by the configuration bits of the instruction. These bits allow conditional execution, input parameter modification, affect flags and define how the result of the command is processed.

As each instruction may be conditional, there are no special conditional jump commands. In fact, there isn't even a jump command at all. A jump is done by taking the output of a command to be the next instruction pointer.

Thus, the most simple COPY command can be used already for a whole set of different operations: jmp $imm, push $imm, pop and many more.

Basic Properties

Word Encoding and Signedness

The SPU Mark II uses the little endian encoding, so the less significant byte is at the lower address, the more significant byte at the higher address.

Integer arithmetic uses two-complement signed integers. This allows most arithmetic instructions to be used with signed and unsigned values.

Memory Access

The cpu only allows aligned memory access for word access. Unaligned word access must be programmed manually.

CPU Registers

Stack Pointer (SP)

16 bit register storing the address of the topmost value of the stack. The stack grows downwards, so a push operation decrements the SP by two and then stores a value to the decremented address. A pop or peek operation reads the value from SP, and for pop, SP will be incremented by 2.

Bit FieldsDescription
[0]reserved, must be zero
[15:1]aligned stack top address

Initial Value: Undefined

Base Pointer (BP)

16 bit register that may be used for indirect addressing via GET and SET commands and may be used as a frame pointer or index register.

Bit FieldsDescription
[0]reserved, must be zero
[15:1]aligned address

Initial Value: Undefined

Instruction Pointer (IP)

16 bit register pointing to the instruction to be executed next.

Bit FieldsDescription
[0]reserved, must be zero
[15:1]aligned instruction address

Initial Value: Undefined

Flag Register (FR)

16 bit register saving CPU state and interrupt system

Bit RangeNameDescription
[0]ZZero Flag
[1]NNegative Flag
[3:2]-Reserved, must be 0.
[7:4]I[3:0]Interrupt Enabled bitfield for interrupts 4 to 7
[15:8]-Reserved, must be 0.

Initial Value: 0x0000

Note: The flags I[3:0] are not available in SPU Mark II-L

Interrupt Register (IR)

16 bit register storing internal interrupt information.

Bit RangeNameDescription
[0]RSTReset was triggered
[1]NMINon-maskable interrupt triggered
[2]BUSBus error triggered
[3] Reserved, must be 0
[7:4]Interrupt I[3:0] triggered bitfield
[15:8]-Reserved (must be 0)

Initial Value: 0x0001 (Reset interrupt triggered)

Note: Not available in SPU Mark II-L

Instruction Encoding

Instructions use 16 bit opcodes organized in different bit fields defining the behaviour of the instruction.

Bit RangeDescription
[2:0]Execution Conditional
[4:3]Input 0 Behaviour
[6:5]Input 1 Behaviour
[7]Flag Modification Behaviour
[9:8]Output Behaviour
[14:10]Command
[15:15]Reserved for future use (must be 0)

Conditional Execution

This field determines when the command is executed or ignored. The execution is dependent on the current state of the flags.

This allows conditional execution of all possible opcodes.

ValueEnumerationDescription
000₂ (0₁₀)AlwaysThe command is always executed
001₂ (1₁₀)=0The command is executed when result is zero (Z=1)
010₂ (2₁₀)≠0The command is executed when result is not zero (Z=0)
011₂ (3₁₀)>0The command is executed when result is positive (Z=0 and N=0)
100₂ (4₁₀)<0The command is executed when result is less than zero (N=1)
101₂ (5₁₀)≥0The command is executed when result is zero or positive (Z=1 or N=0)
110₂ (6₁₀)≤0The command is executed when result is zero or negative (Z=1 or N=1)
111₂ (7₁₀)ReservedReserved for future use (invokes undefined behavior).

Argument Input 0 and 1

These two fields define what arguments are provided to the executed command.

ValueEnumerationDescription
00₂ (0₁₀)ZeroThe input register will be zero.
01₂ (1₁₀)ImmediateThe input registers value is located after this command.
10₂ (2₁₀)PeekThe input register will be the stack top.
11₂ (3₁₀)PopThe input register will be popped from the stack.

Zero means that the argument will be zero, Immediate means that it will be fetched from the instruction pointer (it is located behind the opcode in memory). Peek will take the argument from the stack top, but won't change the stack and Pop will take the argument from the stack top and decreases the stack pointer.

input0 is fetched before input1 so when both arguments pop a value, input0 receives the stack top and input1 receives the value one below the stack top. Likewise, when both arguments use the Immediate option, the value for input0 must located directly after the opcode, input1 directly after input0.

Flag Modification

When the flag modification is enabled, the current flags will be overwritten by this command. Otherwise the flags stay as they were before the instruction.

ValueEnumerationDescription
0₂ (0₁₀)NoThe flags won't be modified.
1₂ (1₁₀)YesThe flags will be set according to the command output.

The flags are modified according to this table:

FlagCondition
Zoutput[15:0] = 0
Noutput[15] = 1
Iunchanged

Result Output

Each command may output a value which can be processed in various ways. The output could be pushed to the stack, the command could be made into a jump or the output could be ignored.

ValueEnumerationDescription
00₂ (0₁₀)DiscardThe command output will be ignored.
01₂ (1₁₀)PushThe command output will be pushed to the stack.
10₂ (2₁₀)JumpThe instruction pointer will be set to the command output.
11₂ (3₁₀)Jump RelativeThe command output will be added to the instruction pointer.

For Jump Relative, the instruction pointer will point to the next instruction plus output words. output is considered a two-complements signed number. This differs from the Jump behavior which takes an address, not a word offset.

Commands

Commands are what define the core behaviour of the opcode. They allow arithmetics, modification of memory, changing system registers and so on.

Some hints on notation:

ValueNamePseudo-Code
00000₂ (0₁₀)COPYoutput = input0
00001₂ (1₁₀)IPGEToutput = IP + 2 * input0
00010₂ (2₁₀)GEToutput = MEM16[BP + 2 * input0]
00011₂ (3₁₀)SEToutput = input1; MEM16[BP + 2 * input0] = input1
00100₂ (4₁₀)STORE8output = input1 & 0xFF; MEM8[input0] = input1
00101₂ (5₁₀)STORE16output = input1; MEM16[input0] = input1
00110₂ (6₁₀)LOAD8output = MEM8[input0]
00111₂ (7₁₀)LOAD16output = MEM16[input0]
01000₂ (8₁₀)???Invokes undefined behavior
01001₂ (9₁₀)???Invokes undefined behavior
01010₂ (10₁₀)FRGEToutput = (FR & ~input1)
01011₂ (11₁₀)FRSEToutput = FR₀; FR₁ = (input0 & ~input1) | (FR & input1)
01100₂ (12₁₀)BPGEToutput = BP
01101₂ (13₁₀)BPSEToutput = BP₀; BP₁ = input0
01110₂ (14₁₀)SPGEToutput = SP
01111₂ (15₁₀)SPSEToutput = SP₀; SP₁ = input0
10000₂ (16₁₀)ADDoutput = input0 + input1
10001₂ (17₁₀)SUBoutput = input0 - input1
10010₂ (18₁₀)MULoutput = input0 * input1
10011₂ (19₁₀)DIVoutput = input0 / input1
10100₂ (20₁₀)MODoutput = input0 % input1
10101₂ (21₁₀)ANDoutput = input0 & input1
10110₂ (22₁₀)ORoutput = input0 | input1
10111₂ (23₁₀)XORoutput = input0 ^ input1
11000₂ (24₁₀)NOToutput = ~input0
11001₂ (25₁₀)SIGNEXToutput = if(input[7] = 1) (0xFF00 | input0) else (input0 & 0xFF)
11010₂ (26₁₀)ROLoutput = concat(input0[14:0], input0[15])
11011₂ (27₁₀)RORoutput = concat(input0[0], input0[15:1])
11100₂ (28₁₀)BSWAPoutput = concat(input0[7:0], input0[15:8])
11101₂ (29₁₀)ASRoutput = concat(input0[15], input0[15:1])
11110₂ (30₁₀)LSLoutput = concat(input0[14:0], '0')
11111₂ (31₁₀)LSRoutput = concat('0', input0[15:1])

MUL, DIV and MOD use signed values as input and output. It is not possible to get the upper 16 bit of the multiplication result.

Memory Access

Only 2-aligned access to memory is possible with code or data. Only exception are the STORE8 and LOAD8 commands which allow 1-aligned memory access.

When accessing memory with alignment, the least significant address bit is reserved and must be 0. If the bit is 1, the behavior is undefined.

Fetch-Execute-Cycle

This pseudocode documents what the CPU does in detail when execution a single instruction.

TODO: Add handling of BUS fault!

For the non-interrupt version, the state machine is simpler:

 

Interrupt handling

Note: Interrupt handling is not available in SPU Mark II-L

The SPU Mark II provides 8 possible interrupts, four unmasked and four masked interrupts.

When an interrupt is triggered the CPU pushes the current instruction pointer to the stack and fetches the new instruction Pointer from the interrupt table. Then the flag in the Interrupt Register is cleared as well as the mask bit in the Flag Register (if applicable).

The reset interrupt is a special interrupt that does not push the return address to the stack. It also resets the Interrupt Register and the Flag Register.

Masking

If an interrupt is masked via the Flag Register (corresponding bit is 0) it won't be triggered (the Interrupt Register bit can't be set).

Interrupt Table

It is possible to assign each interrupt another handler address. The entry points for those handlers are stored in the Interrupt Table at memory location 0x0000:

#InterruptRoutine Pointer
0Reset0x00
1NMI0x02
2BUS0x04
3RESERVED0x06
4ARITH0x08
5RESERVED0x0A
6RESERVED0x0C
7IRQ0x0E
Reset

This interrupt resets the CPU and defines the program entry point.

NMI

This interrupt is the non-maskable external interrupt. If the NMI pin is signalled, the interrupt will be triggered.

BUS

This interrupt is a non-maskable external interrupt.

The BUS interrupt is meant for an MMU interface and will prevent the currently executed instruction from having any side effects.

Remarks: It is required that the BUS interrupt happens while doing a memory operation. If after a memory read or write cycle the BUS pin is signalled, the CPU will assume as bus error and will trigger this interrupt.

ARITH

This interrupt is triggered when an error happens in the ALU. The reasons may be:

IRQ

This interrupt is the maskable external interrupt. If the IRQ pin is signalled, the interrupt will be triggered.

Priorities

Before execution of each instruction the cpu checks if any interrupt is triggered. The handler for the lowest interrupt triggered will then be activated.

Chip I/Os

Changelog

v1.8

v1.7

v1.6

v1.5

v1.4

v1.3

v1.2

v1.1

v1.0

TODO