Native addressing modes

The processor uses 2-address-opcodes with the following addressing modes:

Register

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.

Examples:

0234    MOVE R2, R3
8705    LBI R7, #5
3880    MOVE $100, R8

Immediate 8-bit

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!

Examples:

A51F    ADD R5, #32
FC00    SUB R12, #256
82C1    LBI R2, #'A'
B420    SET R4, #$20
9F01    CLR R15, #$01

Direct 4-bit

An I/O opcode always needs a device address which is in the range from $0 to $F (see Device addressing)

Examples:

0D5E    GETB R5, $D
ED6F    STAT R6, $D
4E78    PUTB $E, (R7)
107B    CTRL $0, #$7B

Direct 8-bit

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.

Examples:

2850    MOVE R8, $A0          $A0 = 2 * $50
2056    MOVE R0, $AC
39A0    MOVE $140, R9

Register-Indirect

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

"Pseudo" addressing modes

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.

Immediate 16-bit

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 byte
This 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.
The second way is to place the constant directly after the instruction that loads the constant. You only have to increment the program counter in order to skip the constant. This only works with code running in RWS because data accesses can only be done to RWS.
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.

PC relative

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