The ALU supports the usual operations, including multiplication and division. All operations are 32 bit, and set the negative and zero flags depending on the result. There are no carry or overflow signals generated. Multiplication is also 32 bit but two different operations are provided for the upper and lower 32 bits of the 64 bit result.
# | Operation | Result | |
0 | Add | R1 + R0 | |
1 | Subtract | R1 - R0 | |
4 | Or | R1 | R0 | bitwise or |
5 | And | R1 & R0 | bitwise and |
6 | Xor | R1 ^ R0 | bitwise xor |
7 | Not | ~R1 | R0 is ignored |
8 | Cmp | sign(R1 - R0) | |
9 | Test | R1 | set flags |
12 | Shift left | R1 << R0 | |
13 | Shift right | R1 >> R0 | |
14 | Multiply (low) | R1 * R0 | lower 32 bits |
15 | Multiply (high) | R1 * R0 | upper 32 bits |
16 | Divide (unsigned) | R1 // R0 | |
17 | Divide (signed) | R1 // R0 | sign = sign(R1) ^ sign(R0) |
18 | Remainder (unsigned) | R1 - R0 * (R1 // R0) | |
19 | Remainder (signed) | R1 - R0 * (R1 // R0) | sign = sign(R1) ^ sign(R0) |
ALU operations are performed by assigning the operation number to the lower byte of register 13 and the executing the ALU instruction. For example, to subtract register 5 and 4 and assign the result to register 6,the following assembly cold be used
loadi r13,#1
alu r6,r5,r4
The assembler provides built-in mnemonics for all operations so equivalently we could have written
loadi r13,#alu_sub
alu r6,r5,r4
Additionally the macro file provided with the assembler defines many shortcuts, so a shorter notation would be
sub r6,r5,r4
Note that the latter is shorter but if you would like to perform multiple identical operations on different sets of operands it is more efficient to explicitly load the operation code only once into register 13 and then perform the operations. using the marco would load register 13 anew every time.
Addition can also be performed with move r6,r5,r4
. This example will add registers 4 and 5 but will not set any flags.