OpenCores

Register Usage

The 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.

Compiler Register Usage

RegisterNameFunction
R0zeroAlways contains 0
R1atAssembler temporary
R2-R3v0-v1Function return value
R4-R7a0-a3Function parameters
R8-R15t0-t7Function temporary values
R16-R23s0-s7Saved registers across function calls
R24-R25t8-t9Function temporary values
R26-R27k0-k1Reserved for interrupt handler
R28gpGlobal pointer
R29spStack Pointer
R30s8Saved register across function calls
R31raReturn address from function call
HI-LOlo-hiMultiplication/division results
PCProgram CounterPoints at 8 bytes past current instruction
EPCepcException program counter return address

Branch Delay Slot

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.

Assembly Example

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:

Opcodes

OpcodeNameActionOpcode bitfields
Arithmetic Logic Unit
ADD rd,rs,rtAddrd=rs+rt 000000rsrtrd00000100000
ADDI rt,rs,immAdd Immediatert=rs+imm 001000rsrtimm
ADDIU rt,rs,immAdd Immediate Unsignedrt=rs+imm 001001rsrtimm
ADDU rd,rs,rtAdd Unsignedrd=rs+rt 000000rsrtrd00000100001
AND rd,rs,rtAndrd=rs&rt 000000rsrtrd00000100100
ANDI rt,rs,immAnd Immediatert=rs&imm 001100rsrtimm
LUI rt,immLoad Upper Immediatert=imm<<16 001111rsrtimm
NOR rd,rs,rtNorrd=~(rs|rt) 000000rsrtrd00000100111
OR rd,rs,rtOrrd=rs|rt 000000rsrtrd00000100101
ORI rt,rs,immOr Immediatert=rs|imm 001101rsrtimm
SLT rd,rs,rtSet On Less Thanrd=rs<rt 000000rsrtrd00000101010
SLTI rt,rs,immSet On Less Than Immediatert=rs<imm 001010rsrtimm
SLTIU rt,rs,immSet On < Immediate Unsignedrt=rs<imm 001011rsrtimm
SLTU rd,rs,rtSet On Less Than Unsignedrd=rs<rt 000000rsrtrd00000101011
SUB rd,rs,rtSubtractrd=rs-rt 000000rsrtrd00000100010
SUBU rd,rs,rtSubtract Unsignedrd=rs-rt 000000rsrtrd00000100011
XOR rd,rs,rtExclusive Orrd=rs^rt 000000rsrtrd00000100110
XORI rt,rs,immExclusive Or Immediatert=rs^imm 001110rsrtimm
Shifter
SLL rd,rt,saShift Left Logicalrd=rt<<sa 000000rsrtrdsa000000
SLLV rd,rt,rsShift Left Logical Variablerd=rt<<rs 000000rsrtrd00000000100
SRA rd,rt,saShift Right Arithmeticrd=rt>>sa 00000000000rtrdsa000011
SRAV rd,rt,rsShift Right Arithmetic Variablerd=rt>>rs 000000rsrtrd00000000111
SRL rd,rt,saShift Right Logicalrd=rt>>sa 000000rsrtrdsa000010
SRLV rd,rt,rsShift Right Logical Variablerd=rt>>rs 000000rsrtrd00000000110
Multiply
DIV rs,rtDivideHI=rs%rt; LO=rs/rt 000000rsrt0000000000011010
DIVU rs,rtDivide UnsignedHI=rs%rt; LO=rs/rt 000000rsrt0000000000011011
MFHI rdMove From HIrd=HI 0000000000000000rd00000010000
MFLO rdMove From LOrd=LO 0000000000000000rd00000010010
MTHI rsMove To HIHI=rs 000000rs000000000000000010001
MTLO rsMove To LOLO=rs 000000rs000000000000000010011
MULT rs,rtMultiplyHI,LO=rs*rt 000000rsrt0000000000011000
MULTU rs,rtMultiply UnsignedHI,LO=rs*rt 000000rsrt0000000000011001
Branch
BEQ rs,rt,offsetBranch On Equalif(rs==rt) pc+=offset*4 000100rsrtoffset
BGEZ rs,offsetBranch On >= 0if(rs>=0) pc+=offset*4 000001rs00001offset
BGEZAL rs,offsetBranch On >= 0 And Linkr31=pc; if(rs>=0) pc+=offset*4 000001rs10001offset
BGTZ rs,offsetBranch On > 0if(rs>0) pc+=offset*4 000111rs00000offset
BLEZ rs,offsetBranch On if(rs<=0) pc+=offset*4 000110rs00000offset
BLTZ rs,offsetBranch On < 0if(rs<0) pc+=offset*4 000001rs00000offset
BLTZAL rs,offsetBranch On < 0 And Linkr31=pc; if(rs<0) pc+=offset*4 000001rs10000offset
BNE rs,rt,offsetBranch On Not Equalif(rs!=rt) pc+=offset*4 000101rsrtoffset
BREAKBreakpointepc=pc; pc=0x3c 000000code001101
J targetJumppc=pc_upper|(target<<2) 000010target
JAL targetJump And Linkr31=pc; pc=target<<2 000011target
JALR rsJump And Link Registerrd=pc; pc=rs 000000rs00000rd00000001001
JR rsJump Registerpc=rs 000000rs000000000000000001000
MFC0 rt,rdMove From Coprocessorrt=CPR[0,rd] 01000000000rtrd00000000000
MTC0 rt,rdMove To CoprocessorCPR[0,rd]=rt 01000000100rtrd00000000000
SYSCALLSystem Callepc=pc; pc=0x3c 00000000000000000000000000001100
Memory Access
LB rt,offset(rs)Load Bytert=*(char*)(offset+rs) 100000rsrtoffset
LBU rt,offset(rs)Load Byte Unsignedrt=*(Uchar*)(offset+rs) 100100rsrtoffset
LH rt,offset(rs)Load Halfwordrt=*(short*)(offset+rs) 100001rsrtoffset
LBU rt,offset(rs)Load Halfword Unsignedrt=*(Ushort*)(offset+rs) 100101rsrtoffset
LW rt,offset(rs)Load Wordrt=*(int*)(offset+rs) 100011rsrtoffset
SB rt,offset(rs)Store Byte*(char*)(offset+rs)=rt 101000rsrtoffset
SH rt,offset(rs)Store Halfword*(short*)(offset+rs)=rt 101001rsrtoffset
SW rt,offset(rs)Store Word*(int*)(offset+rs)=rt 101011rsrtoffset
Notes: The immediate values are normally sign extended.
The opcodes ADD and ADDU are equivalent in the Plasma CPU since ALU operations don't cause exceptions.
The program counter (pc) points to eight bytes past the currently executing instruction.