March 1, 2020

Assembly language - the Signetics N8x300

This is an old and peculiar chip (from the mid 1970s). In some ways it is simpler than modern processors, and perhaps that is an advantage for making it a first processor to study at the assembly language level. The IV bus is extremely peculiar. It handles both address and data via 8 pins. An extra pin indicates the right or left side of the bus, expanding the address space to 512 bytes.

To read or write to the IV bus requires sending the address first, then doing the data transfer in a second instruction. The following 3 instruction sequence is a typical example. It would write the value 80h to a device on the right side of IV:

	xmit    CMD_PORT,ivr
	xmit    80h,r1
	move    r1,driv
The symbol CMD_PORT (here a symbol with value 2h) is written to the ivr "register" to prepare for access to that address on the right side of IV. Then the value 80h is loaded into the r1 register. Then the value in r1 is written to "driv" which is a data access to the right side of IV.

Note that the "flow" in this disassembly is from left to right, something I warned you to be ready for in an earlier page in this writeup.

The 8 instructions are as follows:

What is the difference between MOVE and XMIT you ask? Both move data from left to right. The description says that xmit moves a "literal", i.e. a value contained in the instruction itself, into the destination. So with xmit, we will have some constant left of the comma and some destination on the right. The move instruction on the other hand transfers data from a register to a register, but as always from left to right.

The AND, ADD, and XOR instructions operate on "aux" and the register on the left, putting the result into the register on the left. In other words the following instruction adds r6+aux and puts the result into r6 replacing what was there to start with:

add     r6,r6
Note that you can't just add r5 and r6, only "aux" is allowed as the second (invisible) operand.

The JMP instruction is the simplest of all, it is just an unconditional branch someplace.

The NZT instruction is straightforward enough, it tests something and branches if it isn't zero. The branch address is an offset from where you are and has limits, but you don't know or care if you are reverse engineering code.

The XEC instruction is unique and interesting. It executes some instruction someplace else just once. Note that it doesn't jump to it, it just says, "see that instruction over there, execute it!". In most cases the instruction "over there" is indeed a JMP, but it doesn't have to be. This instruction is often used to construct jump tables that look like this:

0340: 85 41 x0340:  xec     x0341,r5
0341: e3 bf x0341:  jmp     x03bf
0342: e3 65         jmp     x0365
Here, depending on whether r5 is 0 or 1, we either jump to 03bf or 0d65. Jump tables like this can be as big as you like.

Operands

It is possible to do interesting fancy business when accessing the IV bus. Remember that first an address must be written to ivr or ivl to specify what address on the bus we want to talk to. Accesses are then done to sriv or driv.

You use "sriv" on the left side of a comma as a data source.
You use "driv" on the right side of a comma as a data destination.
So consider these instructions:

    move    sriv,r1
    move    r1,driv
The first reads from the IV bus and puts the data into register r1. The second writes the data in register r1 to the IV bus. These are the simple cases. It is possible to read or write from/to individual bits or "bit fields" in sriv and driv using a notation like this:
    move    sriv[5],r3
    move    sriv[1:0],aux
    xmit    1h,driv[4]
    xmit    6h,driv[6:4]
    nzt     sriv[7],x013e
The actual signetics documentation uses an odd bit numbering, calling the MSB bit 0, which is logical actually, but entirely different from how everything with computers has been done since then. I am not clear yet if my disassembler is going with this or is showing bit numbers in a more modern way. More on this when I figure it out. Note that it is possible to test a single bit within an 8 bit register on the IV bus using this notation with the NZT instruction, which is quite handy.

Finally, it is also possible to specify that a source operand gets shifted, so the following performs a right rotate of the contents of register r1.

    move    r1>>>5,r1

Look at some disassembled code

Now you know enough to look at some actual code for the 8x300. Take a look at the following, a disassembly and analysis of 8x300 firmware for the Convergent Technologies AWS "turbo" disk controller, which used the 8x300.
Feedback? Questions? Drop me a line!

Tom's Computer Info / tom@mmto.org