Tools

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

instr.

mnemonic

Description

00xx

OSCALL xx

Use an OS call (int 21h service)

0xxx

JP xxx

Jump to new PC address

1000

RETURN

Return from a GOSUB call

1xxx

GOSUB xxx

Go (call) a sub-routine

2xxx

PUSHB [xxx]

Push a byte onto the stack

3xxx

POPB [xxx]

Pop a byte from the stack

4xxx

LDA [xxx]

Load A (accumulator) from memory

5xxx

STA [xxx]

Store A into memory

6xxx

RDI [(xxx)]

Read an indirect byte using mem-ptr

7xxx

WRI [(xxx)]

Write an indirect byte using mem-ptr

8xxx

RDSYS [0000:0xxx]

Read byte from system ram[0000:0xxx]

9xxx

ADDW [xxx],A

Add sign-extended A to word variable

Acpp

JPcc +pp

Jump if the condition is true

Bxxx

ADCA [xxx]

A + mem[xxx] + CF

Cxxx

SBBA [xxx]

A - mem[xxx] - CF

Dxxx

ORA [xxx]

A OR mem[xxx]

Exxx

ANDA [xxx]

A AND mem[xxx]

Fxxx

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:

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.

Conclusion

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.

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.

Video

This month's Dr. Dobb's Journal

This month,
Dr. Dobb's Journal is devoted to mobile programming. We introduce you to Apple's new Swift programming language, discuss the perils of being the third-most-popular mobile platform, revisit SQLite on Android
, and much more!