Dr. Dobb's is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.

Channels ▼

Embedded Systems

SPEW: A Fictitious Processor with 4K of Memory

Instruction Set

There are 18 instructions in the Spew CPU. The instructions are always 16-bits wide (see Table 2).

SPEW, A Fictitious Processor with 4k of Memory






Use an OS call (int 21h service)


JP xxx

Jump to new PC address



Return from a GOSUB call



Go (call) a sub-routine


PUSHB [xxx]

Push a byte onto the stack


POPB [xxx]

Pop a byte from the stack


LDA [xxx]

Load A (accumulator) from memory


STA [xxx]

Store A into memory


RDI [(xxx)]

Read an indirect byte using mem-ptr


WRI [(xxx)]

Write an indirect byte using mem-ptr


RDSYS [0000:0xxx]

Read byte from system ram[0000:0xxx]


ADDW [xxx],A

Add sign-extended A to word variable


JPcc +pp

Jump if the condition is true


ADCA [xxx]

A + mem[xxx] + CF


SBBA [xxx]

A - mem[xxx] - CF


ORA [xxx]

A OR mem[xxx]


ANDA [xxx]

A AND mem[xxx]


XORA [xxx]

A XOR mem[xxx]

Table 2

The OSCALL instruction was created so that you could call the host with limited I/O support such as character in/out, terminate application, etc. You simply used the AH value of the corresponding INT 21h service as the second byte of the instruction. Only a limited number of services were allowed.

For example, to print a string of characters to the Host screen, you would use the following example:

@label1    gosub  @writeit
           db 'This is a test program for SPU.COM '
           db #0000

@label3    oscall #0000

@writeit   popb   @Ptr      ; pop pointer
           popb   @Ptr1     ;
@NextChar  rdi    @Ptr      ; get char
           pushb  %A
           lda    #0001     ; move pointer
           addw   @Ptr
           popb   %A
           pushb  #0000     ; test if 0
           popb   %status   ;
           sbba   #0000     ;
           jpz    @Done
           oscall #0006     ; write
           jp     @NextChar
@Done      pushb  @Ptr1     ; push pointer
           pushb  @Ptr      ;

@Ptr       db #0000
@Ptr1      db #0000

Notice that when the code makes it to @writeit, it pops off the return value as the string pointer. It then reads the string, sending a character at a time to the host's screen using OSCALL #0006, until a null character is found. The code then places a new return value back on the stack and does a return. The new position for the return is now the next instruction after the string declaration, which is at @label3.

The code must do two pushes and pops since it can only push and pop a byte at a time, since the stack pointer is 16-bits wide. The ADDW instruction, however, can sign add to a word value, so the two bytes in memory to store the current PC value, PTR and PTR1, must be in consecutive bytes and in the correct order.

The SPEW CPU does not have a CLC instruction like the 80x86 to clear the carry flag, so to clear out the zero flag, it pushes a value of zero into the status register. Since there is no "dangerous" bits in the status register, like the Direction Flag of the 80x86, it is safe to write all zeros to the register. Please note that the JPZ instruction is not "jump if parity zero", it is the "JumP if Zero" instruction.

Another example of one of the instructions is the ability to read the hosts memory from 0x00000 to 0x00FFF. This was added so that a SPU app could read certain parts of the hosts BIOS data for things like the current shift state, master clock count, current screen mode, etc. This instruction, called the RDSYS instruction, is read only and does not allow you to write to this area.

Since an instruction is 16-bits wide and a memory access is only 12-bits wide, most instructions use the high nibble as the instruction and the remaining 12-bits for the memory operand.

The Jump if Condition instruction uses the high nibble for the instruction, the next nibble for the condition, and the lower byte for the signed relative displacement to jump to. This instruction works very similar to the 80x86 instruction, where as a displacement of 0x00 jumps to the next instruction. This can be used as a NOP instruction. The assembler described below allows the NOP mnemonic and simply output a JPZ 0x00 instruction.

The Assembler

To simplify the assembler, it requires all operands to start with a specific character to indicate what type of operand it is. For example, a label must start with the @ character, while an immediate value must start with the # character and be four digits long, and a register to start with the % character.

The assembler does not check for errors. It assumes that all code is valid. It also only allows 255 characters per line, 50 16-byte symbols (labels), and the total source file must be 32k or less.

Math equations are not allowed.

The following line should not be used. Multiple values on a DB line also should not be used.

db #0000+#0001

I am sure that it would be a simple task to expand these limitations, but for simplicity, I have left them as so. If you improve upon the assembler's functionality, please contact me. I would like to see your work.

As with most assemblers, the semicolon is used for comments.

Since the emulator overwrites the first 256 bytes of the SPU image, the assembler writes a comment to these 256 bytes, with the last character being an EOF character (0x1A). The reason is so that you can use the DOS TYPE command and view the comment up to the EOF character. This way, you have 255 bytes to create a specific comment for each of your SPU files. In some cases, the source code to the SPU image fits in this 255-byte area. The assembler is currently hard-coded to a specific comment, but modifying it to ask for the comment, either from stdin or a filename on the command line, shouldn't be difficult.

To use the assembler, the name of the source file must be in the second character position after the SPU on the command line; for instance, the assembler assumes the filename starts at the first byte in the command line, offset 0x82 in the PSP. The assembler also assumes the .SAM extension for the source file and the .SPU extension for the output image file. These extensions should not be used. The assembler's usage is:

SPU demo

This takes demo.sam, assembles it, and produces demo.spu.

The Emulator

One of the members of our team also included DICE, a really nice emulator/debugger that lets you single step through your code. Its usage is:

DICE /s demo.spu

The /s parameter is used to simply emulate the demo.spu image. Remove the /s parameter to use the debugger.


We had a lot of fun coding for this competition. It was exciting to see what we could come up with. To get the results and source code to this competition, visit http://www.hugi.scene.org/compo/compoold.htm#compo9. You can also view other competitions we had on that same page.

And again, you can get the SPEW assembler, source code, the debugger, and detailed information here and at www.frontiernet.net/~fys/spu.htm.

Related Reading

More Insights

Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.