-
Notifications
You must be signed in to change notification settings - Fork 35
Home
This processor is designed for small size, high clock speed, and simplicity. There are 8 general purpose registers, each of which can contain a 16 bit value. There are also 4 condition code flags (zero, negative, carry, and overflow), which are set by arithmetic operations and can be used for conditional branches.
The pipeline does perform bypassing of intermediate arithmetic results, but it does not have any form of interlocking. As such, it has two "branch delay slots," which is a fancy way of saying it will execute the next two instructions after a branch because the instructions are already in the pipeline. NOPs can be inserted to avoid side effects, or the code can be structured to take advantage of this. Likewise, loads have 2 cycles of latency. If you attempt to access a load destination register within two instructions, it will not contain the correct value.
15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | ||
arithmetic | 0 | 0 | 0 | operation | opb | opa | dest | ||||||||||
load | 0 | 0 | 1 | offset | ptr | dest | |||||||||||
store | 0 | 1 | 0 | offset h | src | ptr | offset l | ||||||||||
addi | 0 | 1 | 1 | immediate | opa | dest | |||||||||||
lui | 1 | 0 | 0 | immediate | dest | ||||||||||||
cond branch | 1 | 0 | 1 | inv | cond | offset | |||||||||||
uncond branch | 1 | 1 | 0 | link | offset | ||||||||||||
jump to reg | 1 | 1 | 1 | link | unused | target | unused |
These operations generally take two register inputs and a destination register. They will in most cases set the condition code flags as the result of the operation. For example:
add r1, r2, r3
Arithmetic Operation field
Mnemonic | Code | Description | Flags Affected |
and | 0000 | Bitwise logical and | ZN |
or | 0001 | Bitwise logical or | ZN |
shl | 0010 | Shift left one place. Zero will be loaded into low bit. | ZNC |
shr | 0011 | Shift right once place. Zero will be loaded into high bit. | ZNC |
add | 0100 | Add | ZNCO |
sub | 0101 | Subtract | ZNCO |
xor | 0110 | Bitwise exclusive or | ZN |
not | 0111 | Logical negate | ZN |
rol | 1010 | Rotate left. Carry flag will be loaded into low bit. | ZNC |
ror | 1011 | Rotate right. Carry flag will be loaded into high bit. | ZNC |
adc | 1100 | Add with carry in | ZNC |
sbc | 1101 | Subtract with borrow(carry flag) | ZNC |
load a 16 bit value from a memory location, with optional offset
load r1, (r2) load r3, 12(r4)
Similar to load, except write back to memory
Add a 6 bit signed immediate value to a register. This can be used to fill in the low bits after a LUI instruction or for simple pointer/loop variable increment/decrement.
Load upper immediate. The 10 bits in this instruction are transferred to the upper bits of the destination register and the low 6 bits are set to 0s.
Branch conditionally to PC+signed offset encoded in instruction. If the flag indicated by the condition field is set, branch. The 'inv' field will branch if the flag is clear. Condition Flags
zero | 00 | bzc/bzs |
negative | 01 | bnc/bns |
carry | 10 | bcc/bcs |
overflow | 11 | boc/bos |
Example:
loop: addi r1, r1, -1 bzc loop
Branch unconditionally to PC+signed offset encoded in instruction. If the link bit is set, the return value will be saved in r7. Otherwise, it will not be set.
Example:
jump restart call doit
Same as unconditional branch, except use value inside register as destination instead of offset.
jump r7
ldi is a pseudo operation to load a 16 bit value into a register. The assembler will convert it into a LUI/ADDI combination.
+------------------+ 0000 | Local memory | +------------------+ 0x4000 | Global memory | +------------------+ (global memory size) | | / / | | +------------------+ FC00 | Device Registers | +------------------+ FFFF
Writing a one to a hardware mutex location will attempt to acquire it and writing a zero will release it if it is held by the owning core. A core may read the location to determine if it has acquired the mutex: it will return one if so, zero if not.