Iota is a small, modified Harvard (RISC) architecture that is largely inspired by the MIPS R2000 ISA and the CPU0 teaching ISA. Iota is 32-bit register machine. Furthermore, all memory accessed must be 4 byte aligned and there is no concept of loading or storing bytes and halfwords. This was done to simplify the implementation of the memory management unit and to further reduce the number of opcodes.
Memory and Registers
As mentioned before, all memory accesses store or return 32 bits and must be 4 byte aligned. The register file contains 16 general purpose registers (denoted r[0] through r[15]) with register 0 containing the fixed value of 0 at all times. By convention, r[15] is used as the return address from subroutines, and r[14] is used for the return address from interrupt handlers. There are two special purpose registers: the program counter (PC) and the condition register (CR). The condition register is 32 bits, albeit only the lower four bits are currently utilized.
|----|------------------------|----| Condition Register
|HRRR| Reserved (24 bits) |ICZN|
- CR[Z] is set when the previous modifying instruction resulted in a zero
- CR[N] is set when the previous modifying instruction resulted in a negative value
- CR[C] is set when the previous modifying instruction resulted in a carry out
- CR[I] is set during an interrupt routine
- CR[H] is set when the processor has halted
- CR[R] is a three bit field that contains the reason for the processor halt
Instructions
Instructions come in three formats: R, I, and J. R-type instructions take all operands from registers and store it in another register. I-type instructions have two registers (source and destination) and a larger field for a 16-bit immediate value. Finally, J-type instructions have a 24-bit offset field that specifies a jump offset.
Pictorially:
|--------|------------------------| J-Type
| OP (8) | Jump offset (24) |
|--------|----|----|----------------| I-Type
| OP (8) |Rd 4|Rs 4| Immediate (16) |
|--------|----|----|----|------------| R-Type
| OP (8) |Rd 4|Ra 4|Rb 4|Secondary 12|
Type | Mnemonic | Opcode / Secondary | Description | Syntax | Operation | CR Modified? |
---|---|---|---|---|---|---|
- | TRAP | 00 / xxx | Trap operation. Raises an ‘invalid operation’ exception | TRAP | — | No |
R | RET | 01 / 000 | Return from subroutine | RET | PC <= r[15] | No |
R | J | 01 / 001 | Jump to location stored in register | J Rd | PC <= Ra | No |
R | ADD | 01 / 002 | Add | ADD Rd, Ra, Rb | Rd <= Ra + Rb | Yes |
R | ADDu | 01 / 003 | Add Unsigned | ADDu Rd, Ra, Rb | Rd <= Ra + Rb | Yes |
R | SUB | 01 / 004 | Subtract | SUB Rd, Ra, Rb | Rd <= Ra - Rb | Yes |
R | OR | 01 / 005 | Logical OR | OR Rd, Ra, Rb | Rd <= Ra | Rb | Yes |
R | XOR | 01 / 006 | Logical XOR | XOR Rd, Ra, Rb | Rd <= Ra ^ Rb | Yes |
R | AND | 01 / 007 | Logical AND | AND Rd, Ra, Rb | Rd <= Ra & Rb | Yes |
R | NOT | 01 / 008 | Logical inverse | NOT Rd, Ra | Rd <= ~Ra | Yes |
R | LSL | 01 / 009 | Logical shift left. Drop leftmost and insert zeros at right | LSL Rd, Ra, Rb | Rd <= Ra << Rb | Yes |
R | LSR | 01 / 00A | Logical shift right. Drop rightmost and insert zeros at left | LSR Rd, Ra, Rb | Rd <= Ra >> Rb | Yes |
R | ASR | 01 / 00B | Arithmetic shift right. Drop rightmost and keep sign bit of Ra | LSR Rd, Ra, Rb | Rd <= (h80000000&Ra)|Ra >> Rb | Yes |
R | CMP | 01 / 00C | Compare two registers. Sets CR[Z] if Ra, Rb equal. Sets CR[N] if Ra < Rb | CMP Ra, Rb | CR <= (Ra - Imm16)? | Yes |
R | SW | 01 / 00D | Store word (4 byte aligned) | SW Rd, Ra, Rb | MEM[Ra+Rb] <= Rd | No |
R | LW | 01 / 00E | Load Word | LSR Rd, Ra, Rb | Rd <= MEM[Ra+Rb] | No |
I | ADDi | 02 / - | Add Immediate | ADDi Rd, Ra, Imm16 | Rd <= Ra + Imm16 | Yes |
I | ADDiu | 03 / - | Add Immediate Unsigned | ADDiu Rd, Ra, Imm16 | Rd <= Ra + Imm16 | Yes |
I | — | 04 / - | Unused | — | — | — |
I | ORi | 05 / - | Logical OR with Immediate | ORi Rd, Ra, Imm16 | Rd <= Ra | Imm16 | Yes |
I | XORi | 06 / - | Logical XOR with Immediate | XORi Rd, Ra, Imm16 | Rd <= Ra ^ Imm16 | Yes |
I | ANDi | 07 / - | Logical AND with Immediate | ANDi Rd, Ra, Imm16 | Rd <= Ra & Imm16 | Yes |
I | — | 08 / - | Unused | — | — | — |
I | LSLi | 09 / - | Logical Shift Left with Immediate. Drop leftmost and insert zeros at right | LSLi Rd, Ra, Imm16 | Rd <= Ra << Imm16 | Yes |
I | LSRi | 0A / - | Logical Shift Right with Immediate. Drop rightmost and insert zeros at left | LSRi Rd, Ra, Imm16 | Rd <= Ra >> Imm16 | Yes |
I | ASRi | 0B / - | Arithmetic Shift Right with Immediate. Drop rightmost and keep sign bit of Ra | ASRi Rd, Ra, Imm16 | Rd <= (h80000000&Ra)|Ra >> Imm16 | Yes |
I | CMP | 0C / - | Compare with Immediate | CMP Ra, Imm16 | CR <= (Ra - Imm16)? | Yes |
I | SW | 0D / - | Store word (4 byte aligned) | SW Rd, Ra, Imm16 | MEM[Ra+Imm16] <= Rd | No |
I | LW | 0E / - | Load Word | LSR Rd, Ra, Imm16 | Rd <= MEM[Ra+Imm16] | No | J | JEQ | 10 / - | Jump if EQual | JEQ Off24 | if CR[Z], PC <= PC + Off24 | No |
J | JNE | 11 / - | Jump if Not Equal | JNE Off24 | if not CR[Z], PC <= PC + Off24 | No |
J | JGT | 12 / - | Jump if Greater Than | JGT Off24 | if CR[N], PC <= PC + Off24 | No |
J | JLT | 13 / - | Jump if Less Than | JLT Off24 | if not CR[N], PC <= PC + Off24 | No |
J | JLE | 14 / - | Jump if Less than or Equal | JLE Off24 | if CR[E] or CR[N], PC <= PC + Off24 | No |
J | JGE | 15 / - | Jump if Greater than or Equal | JGE Off24 | if CR[E] or not CR[N], PC <= PC + Off24 | No |
J | JAL | 16 / - | Jump to subroutine and Link | JAL Off24 | R[31] <= PC, PC <= PC + Off24 | No |
J | SWI | 20 / - | Software Interrupt | SWI Off24 | CR[I] <= 1, R[14] <= PC, PC <= PC + Off24 | Yes |
J | RTI | 21 / - | Return from Interrupt | RTI | CR[I] <= 0, PC <= R[14] | Yes |
Math Extension
Type | Mnemonic | Opcode / Secondary | Description | Syntax | Operation | CR Modified? |
---|---|---|---|---|---|---|
R | MTLO | 03 / 01 | Load a register into the lower half of the coprocessor register | MTLO Ra | R[LO] <= Ra | No |
R | MTHI | 03 / 02 | Load a register into the upper half of the coprocessor register | MTHi Ra | R[HI] <= Ra | No |
R | MFLO | 03 / 03 | Load a register from the lower portion of the coprocessor register. | MFLO Rd | Rd <= R[LO] | No |
R | MFHI | 03 / 04 | Load a register from the upper portion of the coprocessor register. | MFHI Rd | Rd <= R[HI] | No |
R | MULT | 03 / 06 | Multiply Ra and Rb, store in the coprocessor registers | MULT Ra, Rb | {LO,HI] <= Ra*Rb | No |
R | MULTU | 03 / 05 | Multiply unsigned Ra and Rb, store in the coprocessor registers | MULTU Ra, Rb | {LO,HI] <= Ra*Rb | No |
Implementation Recommendations
While Iota has an upcoming reference implementation, Taliesin, it is prudent to outline a implementation of this processor.
Baseline features:
- 5 Pipeline stages: Fetch, Decode, Execute, Memory, Writeback
- No forwarding, block on hazard
- Bubble insertion on fetch
Recommended features:
- 5 Pipeline stages
- Branch prediction (Two-level adaptive)
- Register forwarding
- Split D- and I-caches
- Multiply and divide implementation
While Taliesin is still a work in progress, it aims to fulfill all of the recommended features of the Iota architecture.