Plasma - most MIPS I(TM) opcodesThe Plasma CPU is based on the MIPS I(TM) instruction set. There are 32, 32-bit general purpose registers.
- The value of register R0 is always zero.
- R31 is used as the link register to return from a subroutine.
- The program counter (pc) specifies the address of the next opcode.
- The exception program counter (epc) register remembers the program counter when there is an interrupt or exception.
- Registers LO and HI are used for multiplication and division.
There isn't a status register. Instead, the results of a comparison set a register value. The branch then tests this register value.
| Register | Name | Function |
| R0 | zero | Always contains 0 |
| R1 | at | Assembler temporary |
| R2-R3 | v0-v1 | Function return value |
| R4-R7 | a0-a3 | Function parameters |
| R8-R15 | t0-t7 | Function temporary values |
| R16-R23 | s0-s7 | Saved registers across function calls |
| R24-R25 | t8-t9 | Function temporary values |
| R26-R27 | k0-k1 | Reserved for interrupt handler |
| R28 | gp | Global pointer |
| R29 | sp | Stack Pointer |
| R30 | s8 | Saved register across function calls |
| R31 | ra | Return address from function call |
| HI-LO | lo-hi | Multiplication/division results |
| PC | Program Counter | Points at 8 bytes past current instruction |
| EPC | epc | Exception program counter return address |
There is one branch delay slot. This means that the instuction after a branch is always executed before the CPU decides to take the branch or not.
Also see opcodes.asm which tests all of the opcodes.
LUI $4, 0x1234 #i = 0x12345678; ORI $4, $4, 0x5678 BLEZ $4, NoAdd #if (i > 0) i += 9; NOP #Branch Delay Slot ADDIU $4, $4, 9 NoAdd:
| Opcode | Name | Action | Opcode bitfields | |||||
| Arithmetic Logic Unit | ||||||||
| ADD rd,rs,rt | Add | rd=rs+rt | 000000 | rs | rt | rd | 00000 | 100000 |
| ADDI rt,rs,imm | Add Immediate | rt=rs+imm | 001000 | rs | rt | imm | ||
| ADDIU rt,rs,imm | Add Immediate Unsigned | rt=rs+imm | 001001 | rs | rt | imm | ||
| ADDU rd,rs,rt | Add Unsigned | rd=rs+rt | 000000 | rs | rt | rd | 00000 | 100001 |
| AND rd,rs,rt | And | rd=rs&rt | 000000 | rs | rt | rd | 00000 | 100100 |
| ANDI rt,rs,imm | And Immediate | rt=rs&imm | 001100 | rs | rt | imm | ||
| LUI rt,imm | Load Upper Immediate | rt=imm<<16 | 001111 | rs | rt | imm | ||
| NOR rd,rs,rt | Nor | rd=~(rs|rt) | 000000 | rs | rt | rd | 00000 | 100111 |
| OR rd,rs,rt | Or | rd=rs|rt | 000000 | rs | rt | rd | 00000 | 100101 |
| ORI rt,rs,imm | Or Immediate | rt=rs|imm | 001101 | rs | rt | imm | ||
| SLT rd,rs,rt | Set On Less Than | rd=rs<rt | 000000 | rs | rt | rd | 00000 | 101010 |
| SLTI rt,rs,imm | Set On Less Than Immediate | rt=rs<imm | 001010 | rs | rt | imm | ||
| SLTIU rt,rs,imm | Set On < Immediate Unsigned | rt=rs<imm | 001011 | rs | rt | imm | ||
| SLTU rd,rs,rt | Set On Less Than Unsigned | rd=rs<rt | 000000 | rs | rt | rd | 00000 | 101011 |
| SUB rd,rs,rt | Subtract | rd=rs-rt | 000000 | rs | rt | rd | 00000 | 100010 |
| SUBU rd,rs,rt | Subtract Unsigned | rd=rs-rt | 000000 | rs | rt | rd | 00000 | 100011 |
| XOR rd,rs,rt | Exclusive Or | rd=rs^rt | 000000 | rs | rt | rd | 00000 | 100110 |
| XORI rt,rs,imm | Exclusive Or Immediate | rt=rs^imm | 001110 | rs | rt | imm | ||
| Shifter | ||||||||
| SLL rd,rt,sa | Shift Left Logical | rd=rt<<sa | 000000 | rs | rt | rd | sa | 000000 |
| SLLV rd,rt,rs | Shift Left Logical Variable | rd=rt<<rs | 000000 | rs | rt | rd | 00000 | 000100 |
| SRA rd,rt,sa | Shift Right Arithmetic | rd=rt>>sa | 000000 | 00000 | rt | rd | sa | 000011 |
| SRAV rd,rt,rs | Shift Right Arithmetic Variable | rd=rt>>rs | 000000 | rs | rt | rd | 00000 | 000111 |
| SRL rd,rt,sa | Shift Right Logical | rd=rt>>sa | 000000 | rs | rt | rd | sa | 000010 |
| SRLV rd,rt,rs | Shift Right Logical Variable | rd=rt>>rs | 000000 | rs | rt | rd | 00000 | 000110 |
| Multiply | ||||||||
| DIV rs,rt | Divide | HI=rs%rt; LO=rs/rt | 000000 | rs | rt | 0000000000 | 011010 | |
| DIVU rs,rt | Divide Unsigned | HI=rs%rt; LO=rs/rt | 000000 | rs | rt | 0000000000 | 011011 | |
| MFHI rd | Move From HI | rd=HI | 000000 | 0000000000 | rd | 00000 | 010000 | |
| MFLO rd | Move From LO | rd=LO | 000000 | 0000000000 | rd | 00000 | 010010 | |
| MTHI rs | Move To HI | HI=rs | 000000 | rs | 000000000000000 | 010001 | ||
| MTLO rs | Move To LO | LO=rs | 000000 | rs | 000000000000000 | 010011 | ||
| MULT rs,rt | Multiply | HI,LO=rs*rt | 000000 | rs | rt | 0000000000 | 011000 | |
| MULTU rs,rt | Multiply Unsigned | HI,LO=rs*rt | 000000 | rs | rt | 0000000000 | 011001 | |
| Branch | ||||||||
| BEQ rs,rt,offset | Branch On Equal | if(rs==rt) pc+=offset*4 | 000100 | rs | rt | offset | ||
| BGEZ rs,offset | Branch On >= 0 | if(rs>=0) pc+=offset*4 | 000001 | rs | 00001 | offset | ||
| BGEZAL rs,offset | Branch On >= 0 And Link | r31=pc; if(rs>=0) pc+=offset*4 | 000001 | rs | 10001 | offset | ||
| BGTZ rs,offset | Branch On > 0 | if(rs>0) pc+=offset*4 | 000111 | rs | 00000 | offset | ||
| BLEZ rs,offset | Branch On | if(rs<=0) pc+=offset*4 | 000110 | rs | 00000 | offset | ||
| BLTZ rs,offset | Branch On < 0 | if(rs<0) pc+=offset*4 | 000001 | rs | 00000 | offset | ||
| BLTZAL rs,offset | Branch On < 0 And Link | r31=pc; if(rs<0) pc+=offset*4 | 000001 | rs | 10000 | offset | ||
| BNE rs,rt,offset | Branch On Not Equal | if(rs!=rt) pc+=offset*4 | 000101 | rs | rt | offset | ||
| BREAK | Breakpoint | epc=pc; pc=0x3c | 000000 | code | 001101 | |||
| J target | Jump | pc=pc_upper|(target<<2) | 000010 | target | ||||
| JAL target | Jump And Link | r31=pc; pc=target<<2 | 000011 | target | ||||
| JALR rs | Jump And Link Register | rd=pc; pc=rs | 000000 | rs | 00000 | rd | 00000 | 001001 |
| JR rs | Jump Register | pc=rs | 000000 | rs | 000000000000000 | 001000 | ||
| MFC0 rt,rd | Move From Coprocessor | rt=CPR[0,rd] | 010000 | 00000 | rt | rd | 00000000000 | |
| MTC0 rt,rd | Move To Coprocessor | CPR[0,rd]=rt | 010000 | 00100 | rt | rd | 00000000000 | |
| SYSCALL | System Call | epc=pc; pc=0x3c | 000000 | 00000000000000000000 | 001100 | |||
| Memory Access | ||||||||
| LB rt,offset(rs) | Load Byte | rt=*(char*)(offset+rs) | 100000 | rs | rt | offset | ||
| LBU rt,offset(rs) | Load Byte Unsigned | rt=*(Uchar*)(offset+rs) | 100100 | rs | rt | offset | ||
| LH rt,offset(rs) | Load Halfword | rt=*(short*)(offset+rs) | 100001 | rs | rt | offset | ||
| LBU rt,offset(rs) | Load Halfword Unsigned | rt=*(Ushort*)(offset+rs) | 100101 | rs | rt | offset | ||
| LW rt,offset(rs) | Load Word | rt=*(int*)(offset+rs) | 100011 | rs | rt | offset | ||
| SB rt,offset(rs) | Store Byte | *(char*)(offset+rs)=rt | 101000 | rs | rt | offset | ||
| SH rt,offset(rs) | Store Halfword | *(short*)(offset+rs)=rt | 101001 | rs | rt | offset | ||
| SW rt,offset(rs) | Store Word | *(int*)(offset+rs)=rt | 101011 | rs | rt | offset | ||