This page provides a more verbose description of each instruction and what it does, which is more useful when it actually comes to writing assembly, rather than implementing the CPU in hardware. There’s nothing in here that isn’t already covered in the ISA Document as far as building the CPU is concerned.
Machine Code Lookup#
| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| MOVL | 0 | 0 | 0 | 0 | cond |
rd |
imm8 |
|||||||||
| SETH | 0 | 0 | 1 | 0 | cond |
rd |
imm8 |
|||||||||
| LDR | 0 | 1 | 0 | 0 | cond |
rd |
0 | ra |
0 | 0 | 0 | 0 | ||||
| STR | 0 | 1 | 1 | 1 | cond |
rd |
0 | ra |
0 | 0 | 0 | 0 | ||||
| AND | 1 | 0 | 0 | 0 | cond |
rd |
0 | ra |
0 | rb |
||||||
| ORR | 1 | 0 | 0 | 1 | cond |
rd |
0 | ra |
0 | rb |
||||||
| ADD | 1 | 0 | 1 | 0 | cond |
rd |
0 | ra |
0 | rb |
||||||
| SUB | 1 | 0 | 1 | 1 | cond |
rd |
0 | ra |
0 | rb |
||||||
Hardware Instructions#
-
ra,rb, etc. denote the register index in machine code tables, and the register contents in descriptions. This may seem like it can cause confusion, but in practice the register index is never used in calculations, so it’s always obvious in context which interpretation to use. For example,rd ≔ ra + rbis adding the contents ofraandrband storing into the register indexed byrd, because it does not make sense to add the register indices (values between 0 and 7) nor ‘overwrite’ the register indexrditself. -
{x}Denotes that the contentsxare optionally allowed. -
[x]Denotes the data stored in memory at addressx. For example,[r1]refers to the contents in memory, located at the address stored inr1. -
The value of
condin the machine code is determined by the suffix on the instruction (see Conditions).
ADD#
Syntax#
add {rd,} ra, rb
rddefaults toraif not present.
Machine code#
| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 0 | 1 | 0 | cond |
rd |
0 | ra |
0 | rb |
||||||
Description#
rd ≔ ra + rb
The add instruction adds the value of ra to a second operand value in rb, and stores the result in rd.
Modifies the flags as follows
| Flag | Condition |
|---|---|
| Z | 1 if the result is zero, else 0 |
| N | 1 if the result (viewed as a 2's complement integer) is negative, else 0 |
| V | 1 if an overflow occurred (the inputs have the same sign, but the result has the opposite sign), else 0 |
| C | 1 if a carry occurred (the result would have the 17th bit set if it existed), else 0 |
Examples#
@ r1 == 0xFFFF (-1)
@ r2 == 0x0006
add r3, r1, r2
@ r1 == 0x0005
@ CVNZ == 0b1000 @ no overflow (different input signs)
@ r1 == 0x7FFF
@ r2 == 0x0005
add rz, r1, r2
@ rz == 0x0000 @ rz is always read as 0
@ CVNZ == 0b0110 @ result 0x8004 has opposite sign
@ to inputs and is negative
AND#
Syntax#
and {rd,} ra, rb
rddefaults toraif not present.
Machine Code#
| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 0 | 0 | 0 | cond |
rd |
0 | ra |
0 | rb |
||||||
Description#
rd ≔ ra & rb
The and instruction computes the bitwise AND of ra and rb and stores the
result in rd.
Modifies the flags as follows
| Flag | Condition |
|---|---|
| Z | 1 if the result is zero, else 0 |
| N | 1 if the result (viewed as a 2's complement integer) is negative, else 0 |
| V | Always 0 |
| C | Always 0 |
Examples#
@ r1 == 0b1100 (12) @ leading 12 bits are all 0
@ r2 == 0b1010 (10)
and r3, r1, r2
@ r3 == 0b1000 (8)
@ CVNZ == 0b0000
MOVL#
Syntax#
movl rd, imm8
imm8is an integer between \(0\) and \(255\) (inclusive)
Machine Code#
| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 0 | 0 | 0 | cond |
rd |
imm8 |
|||||||||
Description#
rd ≔ imm8
The movl instruction loads an 8-bit immediate, extends it with zeros, and writes it to register rd. The low byte of rd contains imm8, and the high byte of rd contains zero after executing this instruction.
The flags are unchanged.
Examples#
@ r1 == 0x1234
movl r1, 0xAB
@ r1 == 0x00AB @ upper byte got cleared to 0x00
LDR#
Syntax#
ldr rd, [ra]
Machine Code#
| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 1 | 0 | 0 | cond |
rd |
0 | ra |
0 | 0 | 0 | 0 | ||||
Description#
rd ≔ [ra]
The ldr instruction loads a word from memory specified by the memory address in ra, and stores the result into rd.
The flags are unchanged.
Examples#
@ r1 == 0
ldr r2, [r1]
@ r2 == 0x4210 @ it loaded its own machine code!
movl r2, 0x45 @ what happens if we change r2?
ldr r2, [r1] @ did we change what's in memory?
@ r2 == 0x4210 @ ...changing r2 does not change memory
movl r1, 1 @ let's try a different address
ldr r3, [r1]
@ r3 == 0x0245 @ we read the `movl r2, 0x45`
@ instructions machine code!
ORR#
Syntax#
orr {rd,} ra, rb
rddefaults toraif not present.
Machine Code#
| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 0 | 0 | 1 | cond |
rd |
0 | ra |
0 | rb |
||||||
Description#
rd ≔ ra | rb
The orr instruction computes the bitwise ORR of ra and rb, and stores the result in rd.
Modifies the flags as follows
| Flag | Condition |
|---|---|
| Z | 1 if the result is zero, else 0 |
| N | 1 if the result (viewed as a 2's complement integer) is negative, else 0 |
| V | Always 0 |
| C | Always 0 |
Examples#
@ r1 == 0b1100 (12) @ leading 12 bits are all 0
@ r2 == 0b1010 (10)
orr r3, r1, r2
@ r3 == 0b1110 (14)
@ CVNZ == 0b0000
SETH#
Syntax#
seth rd, imm8
Machine Code#
| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 0 | 1 | 0 | cond |
rd |
imm8 |
|||||||||
Description#
rd = (imm8 << 8) | (rd & 0xff)
The seth instruction moves an 8-bit immediate into the high byte of the destination register rd, leaving the low byte of rd unchanged.
Contrast with movl, which moves an 8-bit immediate into the low byte of a register, and zeros out the high byte.
The flags are unchanged.
Examples#
@ r1 == 0x1234
seth r1, 0xAB
@ r1 == 0xAB34 @ note the lower byte is left unchanged
STR#
Syntax#
str rd, [ra]
Machine Code#
| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 1 | 1 | 1 | cond |
rd |
0 | ra |
0 | 0 | 0 | 0 | ||||
Description#
[ra] ≔ rd
The str instruction stores a word from memory contained in rd to the memory address ra.
The flags are unchanged.
Examples#
@ r1 == 1
@ r2 == 0x0385
str r2, [r1]
movl r3, 0xFF
@ r3 == ??? @ we modified memory in the location the
@ second instruction lives at. What will
@ actually be in r3 now?
SUB#
Syntax#
sub {rd,} ra, rb
rddefaults toraif not present.
Machine Code#
| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 0 | 1 | 1 | cond |
rd |
0 | ra |
0 | rb |
||||||
Description#
rd ≔ ra - rb
The sub instruction subtracts the value in rb from the value in ra and stores the result in rd.
Modifies the flags as follows
| Flag | Condition |
|---|---|
| Z | 1 if the result is zero, else 0 |
| N | 1 if the result (viewed as a 2's complement integer) is negative, else 0 |
| V | 1 if an overflow occurred (the inputs have opposite signs, and the result has the same sign as rb), else 0. (Equivalently, invert the sign of rb and apply the add overflow rule). |
| C | 1 if a carry occurred (when calculated as ra + ~rb + 1), else 0 |
Examples#
@ r1 == 0x0005
@ r2 == 0x0008
sub r3, r1, r2
@ r3 == 0xFFFD @ (-3) Check by adding 3. What do you get?
@ CVNZ == 0b1010 @ carry because we actually
@ added 0x0005 + 0xFFF7 + 1
@ r1 == 0x0001
@ r2 == 0x8000
sub r3, r1, r2
@ r3 == 0x8001
@ CVNZ == 0b0110 @ overflow because r1 and r2 have
@ different signs, but the result
@ has the same sign as r2.