-
Notifications
You must be signed in to change notification settings - Fork 0
TeeRISC is a 32-bit CPU based on RISC load/store architecture.
Since TeeRISC is a 32-bit CPU, all registers are 32-bit wide. Registers are addressed using 5 bits so a total of 32 registers available. First 16 registers are available for application use and remaining are reserved for system use.
| Register | Alias | Type | Description |
|---|---|---|---|
| r0 | ZERO | RO | Read results in 0 and writes are ignored |
| r1-r13 | na | RW | Available for application use. (refer ABI for more details) |
| r14 | FP | RW | Frame Pointer |
| r15 | SP | RW | Stack Pointer |
| r16 | IP | RW | Instruction Pointer |
| r17 | LR | RW | Link Register (updated only by call instruction) |
| r18 | E_LR | SRW | Link Register (updated when an exception occurs) |
| r19 | I_LR | SRW | Link Register (updated when an interrupt occurs) |
| r20 | FLAGS | RW | ALU Status Flags (zf, of, sf, cf, etc) |
| r21 | S_FLAGS | SRW | System Flags(interrupt status etc) |
| r22 | CRO | SRW | Control Register 0(interrupt priority etc) |
| Return Value | r1 |
|---|---|
| Arguments | r2, r3, r4, r5 |
| Callee Saved | r6, r7, r8, r9, r10 |
| Not saved | r11, r12, r13, r14 |
| Stack Pointer | r15 |
TeeRISC uses 32-bit fixed length instructions for simplicity. Compacting instructions will increase the code density but decoding would be difficult.
There are 3 forms of instructions. The form of instruction is determined by the opcode. Operands can be either register or an immediate value.
| Opcode | Destination register | Source register 1 | Source register 2 | Extra register | Condition | Sign | Reserved |
|---|---|---|---|---|---|---|---|
| 6 | 5 | 5 | 5 | 5 | 4 | 1 | 1 |
| 6 | 5 | 5 | 16 bit immediate value | ||||
| 6 | 5 | 5 | 14 bit immediate value | 2 bit width | |||
Format 1 is main form of the instructions and used in arithmetic and logical instructions. Format 2 is used only by or_imm instruction to load 16 bit immediate value into registers. Format 3 is used to load/store memory values.
Extra register is used in operations where more than 3 registers are needed. Currently it is only used in MUL instruction.
Condition field is used specify the instruction should be executed only if the specified condition is met.
| Value | Condition | Usage | Value | Condition | Usage | |
|---|---|---|---|---|---|---|
| 0 | zf == 1 | `==` | 1 | zf == 0 | != | |
| 2 | sf == 1 | < 0 | 3 | sf == 0 | >= 0 | |
| 4 | cf == 1 | >= | 5 | cf == 0 | < | |
| 6 | sf == of | >= (signed) | 7 | sf != of | < (signed) | |
| 8 | of == 1 | Overflow | 9 | of == 0 | No overflow | |
| 10 | Always | Always | ||||
Encoding of bit width
| Value | Width |
|---|---|
| 0 | 8 bits |
| 1 | 16 bits |
| 2 | 32 bits |
All of the following will result in modifying status register so there is no need for separate _cmp_ instruction.
| Operation | Form | Opcode | Description /Assembly | |
|---|---|---|---|---|
| Arithmetic Operations | ||||
| add | 1 | 0 |
rD = rS1 + rS2
|
|
| sub | 1 | 1 |
rD = rS1 - rS2
|
|
| mul | 1 | 2 |
rD1, rD2 = rS1 * rS2
|
|
| div | 1 | 3 |
rD = rS1 / rS2
|
|
| mod | 1 | 4 |
rD = rS1 % rS2
|
|
| Logical operations | ||||
| and | 1 | 5 |
rD = rS1 & rS2
|
|
| or | 1 | 6 |
rD = rS1 | rS2
|
|
| xor | 1 | 7 |
rD = rS1 ^ rS2
|
|
| lshift | 1 | 8 |
rD = rS1 << rS2
|
|
| rshift | 1 | 9 |
rD = rS1 >> rS2
|
|
| Immediate operations | ||||
| add_imm | 2 | 10 |
rD = rS + i16
|
|
| and_imm | 2 | 11 |
rD = rS & i16
|
|
| or_imm | 2 | 12 |
rD = rS | i16
|
|
| lshift_imm | 2 | 13 |
rD = rS1 << imm16
|
|
| rshift_imm | 2 | 14 |
rD = rS1 >> imm16
|
|
| Load/Store instructions | ||||
| load | 3 | 20 |
rD = *(uint8_t *)(rS + imm16)
|
|
| store | 3 | 21 |
*(uint16 *)(rD + imm16) = rS
|
|
| Branch instructions | ||||
| call | 1 | 22 |
rD()
|
|
| return | 1 | 23 |
return
|
|
| Miscellaneous instructions | ||||
To load a 32bit number, compiler may use the following sequence.
r1 = r0 | Immediate_high16 r1 = r1 << 16 r1 = r1 | Immediate_low16
To perform negation on register r3
r3 = r3 XOR -1
Jump to instruction pointed by r10 if r1 is greater than or equal to r2
r0 = r1 - r2 ; write to r0 are ignored and subtract operation will update flag register if (cf == 1) goto r10 ; goto will execute only if r1 >= r2
To generate NOP use read and write to r0
r0 = r0 | r0
The following RISC designs were used as reference when designing TeeRISC.