Workflow optimised, subroutines and single operand instructions!

A project log for TMS9900 compatible CPU core in VHDL

Retro challenge 2017/04 project to create a TMS9900 compatible CPU core. Again in a month... Failure could be an option...

Erik Piehl 04/16/2017 at 19:070 Comments

Today and yesterday I had more time to work on the project. I refactored the code, learned some more VHDL. I also greatly improved my workflow by creating a python script which takes a TMS9900 binary file and spits out the definition of a 64 word ROM in VHDL with the code. This allows for very quickly (10 seconds or so) code changes and simulation reruns, without any manual work.

The TMS9900 supports a bunch of single operand instructions (i.e. the source and destination are the same, for example):


Here the R1 register is incremented, so the source is R1 and destination is also R1. I refactored the VHDL code to calculate the effective address of the source operand and also properly handling all side effects, allowing the effective address to be used twice after operand calculation (once for value read, second time for result write, in between there is computation).

Now I added support for all of the addressing modes for the single operand instructions, so all of the following work (tested with the CLR instruction, which clears the operand). The asterisk * is the comment in TMS9900 assembler, but also used to flag indirect operations:

CLR R5    * Clear R5
CLR *R5    * Clear memory word pointed to by R5
CLR *R5+    * As above, also increment R5 by 2 to point to next word
CLR @MEM1    * Clear the word with the 16-bit address MEM1
CLR @4(R5)    * Clear the word in the address R5+4
There are 14 single operand instructions, I implemented all of them except one, the BLWP instruction, which probably will be the next one. So as additional instructions I now have (with the full suite of address modes):
B    @LABEL  * Jump to 16-bit address LABEL
BL   @LABEL  * As above, but with link: PC stored to R11 first
CLR  R4      * Clear R4
SETO *R5     * Set memory word at address R5 to >FFFF
INV  R9      * Invert bits of R9
NEG  R10     * Negate R10 (i.e. 0-R10)
ABS  R10     * Take the absolute value of R10
SWPB R5      * Swap bytes of R5
INC  R1      * Increment R1 by 1
INCT R1      * Increment R1 by 2
DEC  R1      * Decrement R1 by 1
DECT R1      * Decrement R1 by 2
X    R3      * Execute the opcode in R3 (UNTESTED)
Some things to note from above: