The processor uses 2-address-opcodes with the following addressing modes:
The processor has a total of 16 registers (per interrupt level) each 16 bits wide. They are called R0 to R15. Each machine instruction has at least one register as operand.
0234 MOVE R2, R3 8705 LBI R7, #5 3880 MOVE $100, R8
An immediate 8-bit value can be given to the ADD, SUB, SET, CLR, CTRL and
LBI (Load Byte Immediate) opcodes.
Attention must be given to the ADD and SUB opcodes! The range of the immediate value is from $00 to $FF because it is an 8-bit value. With ADD and SUB this value is taken with a 1 added, i.e. if an immediate value of $00 is given for an ADD or a SUB opcode it is taken as a 1, a value of $FF therefore as 256 (and not 255!). With this you can't add or subtract a zero, but instead you have a simple means of modifying the high byte by 1. As said: This only pertains to ADD and SUB!
A51F ADD R5, #32 FC00 SUB R12, #256 82C1 LBI R2, #'A' B420 SET R4, #$20 9F01 CLR R15, #$01
An I/O opcode always needs a device address which is in the range from $0 to $F (see Device addressing)
0D5E GETB R5, $D ED6F STAT R6, $D 4E78 PUTB $E, (R7) 107B CTRL $0, #$7B
The processor is capable of doing a 16-bit addressing with an 8-bit word address with the 16-bit MOVE opcodes. The byte address is therefore 9 bits with bit 15 (attention: IBM bit numbering scheme!) is equal to 0.
2850 MOVE R8, $A0 $A0 = 2 * $50 2056 MOVE R0, $AC 39A0 MOVE $140, R9
The instructions MOVE, MOVB, GETB and PUTB can have a source or destination
addressed indirectly by a register (but not both together). Optionally a
postincrement or postdecrement (abbr. postcrement) of 1, 2, 3 or 4 bytes
can be supplied.
The increment operators are +, ++, +++ and ++++, the decrement operators are -, --, --- and ----.
Word instructions modify the same way (i.e. by optionally 1 to 4 bytes) but have operators for word addressing, a 1 byte increment becomes ' (tick) and a 1 byte decrement becomes ~ (tilde), so the operators are ' + +' ++ and ~ - -~ --.
4D80 PUTB $D, (R8)+ increases R8 by 1 EDF4 GETB (R15)-, $D decreases R15 by 1 D236 MOVE R2, (R3)-~ decreases R3 by 3 (1.5 words) 7542 MOVB (R4)+++, R5 increases R4 by 3 (3 bytes) DBC8 MOVE R11, (R12) leaves R12 unmodified
Amongst the previous listed native addressing modes other means of addressing can be created by using other instructions or simple tricks. These new modes are Immediate 16-bit and PC relative.
Loading an entire register with a 16-bit value can be achieved in two different ways that have also been used by the IBM engineers. One way is to load the two bytes (low and high byte) consecutivley:
; Load R5 with $120E 8512 LBI R5, #$12 ; Load low byte 055D MLH R5, R5 ; low byte -> high byte 850E LBI R5, #$0E ; load low byteThis is not a very nice way and a costly one, too (it takes six bytes), but has to be chosen if relocatable or ROS code is to be produced.
D501 MOVE R5, (R0)+ ; R0 will point to the word after the constant 120E DW $120E ...This saved us two bytes. For this reason this construct got an own mnemonic named LWI (Load Word Immediate), the example above would then be LWI R5, #$120E.
As one can see in the opcode table there are no
special jump instructions (the IBM-named jumps are conditional test and skip
instructions). So either you load register R0 with another value (MOVE R0, ...)
or do a direct jump with a fixed destination address with LWI R0, ... In both
cases the code won't be relocatable nor ROS usable.
To jump relative to the current program counter in either direction simply do an ADD or a SUB. This way a distance of +/- 256 bytes can be reached. This will look like this:
850A LBI R5, #5 8601 LBI R6, #1 C50B SNZ R5 A005 ADD R0, #6 ; Jump to the HALT 0668 ADD R6, R6 F500 SUB R5, #1 F009 SUB R0, #10 ; Jump back to the SNZ 0000 HALT