MIPS architecture

These are details of the MIPS R2000 architecture.

The purpose of this is to give the flavor of how all architectures
have been designed/specified since the early 1980s.  It is
different from Pentium.

load/store architecture
-----------------------

Memory accesses slow a processor down.  Sure, we add caches,
but that only brings the average access time down for memory
accesses.  There are still times when the processor is doing
nothing, while waiting for memory accesses to complete.

So, we define a new architecture.  In this new load/store
architecture, the addressing mode for every operand is fixed.
(So, there are no bytes for addressing mode information.)
And, for arithmetic/logical type instructions, the addressing
mode for all operands will be register mode.  We make sure
that there are enough registers, because everything ends up
in registers.  To get stuff to/from memory and into/out of registers,
we have explicit instructions that move data.

Load instructions read data from memory and copy it to a register.
Store instructions write data from a register to memory.

The MIPS R2000 is a load/store architecture.



Registers
---------

There are 32 32-bit registers (for non-floating point operands).

(Integers are 32-bit two's complement; addresses are 32-bit unsigned.)

In code, the syntax used is $x, where x is a value
in the range of 0 to 31.

   Example:  $5 is register 5.
   
Some are special purpose:
   $0     always contains the value 0.  This has the effect of
          reducing the number of instructions required in the
          instruction set.
   $1     used by the assembler
   $2-3   location for function return values
   $4-7   location for parameters
   $26-27 used exclusively by OS
   $31    return address from procedures placed here





There are also 16 64-bit registers used for floating point operands.

In code, the syntax used is $fx, where x is an even value
in the range of 0 to 30.

   Example:  $f6 is register 6.

Some of the floating point registers also have specific uses.



three-address instruction set
-----------------------------

The instruction set is considerably smaller than the Intel
instruction sets.  This is typical of a RISC processor.
There is generally one way to do a required operation, not
2 or 3 as on the Pentium.

Arithmetic and logical instructions have 3 operands.

  Example:    add  $8, $9, $10

	      The contents of registers $9 and $10 are added,
	      and the result is placed in register $8.

  To do the equivalent of this on the Pentium, you
  would end up with something more like:

	      mov  eax, var1
	      add  eax, var2    ;  eax <- var1 + var2

  or, if one addend was in ebx, and the other was in ecx,
  then the code could be
	      mov  eax, ebx
	      add  eax, ecx
  
  Note that it can take fewer instructions to get the same
  calculations done in the 3-address instruction set.

  Thought question:  What reason could there be for the Pentium
      (and earlier Intel processors) to have a 2-address
      instruction set, when the 3-address one is more
      powerful?



load and store instructions
---------------------------
The only instructions that access memory to get operands are
load and store instructions.

  Examples:   lw  $14, 4($15)

	      Effective address given by base displacement addressing
	      mode (second operand).  4 + contents of register $15
	      are the address.  Memory reference is to 1 word (32 bits)
	      at that address.  The word read is placed into register
	      $14.

	      sb  $10, 0($18)

	      Effective address given by base displacement addressing
	      mode (second operand).  0 + contents of register $18
	      are the address.  The byte in the least significant
	      byte of register $10 is written to that address.

Notes:  The first operand is always register mode.
	The second operand is always base displacement mode.



control instructions
--------------------

There are 2 types of control instructions.

 branch -- (equivalent of Pentium jumps)
	   conditional or unconditional
	   Branch decision (to take the branch or not) is based
	     on a comparison between the values in 2 registers.
	     (NOT condition codes!)
	   An offset from the instruction following the branch
	     is placed into the instruction.

 jump   -- unconditional
	   A portion of an absolute address is placed into the
	     instruction.


  Examples:   beq  $5, $13, label1
	      
	      Branch if EQual.  If the contents of registers $5
	      and $13 are the same (equal), then go to label1.


	      jal  proc4

	      Jump And Link.  A procedure call instruction very
	      much like the Pentium call instruction.  The return
	      address is placed into register $31. (Pentium
	      pushes the return address onto the stack.) Then
	      address proc4 is placed into the PC.



machine code
------------

All machine code instructions are exactly 32 bits long.
NO EXCEPTIONS!

There are just a few basic formats:

  arithmetic and logical instructions

    bits  31   26    25 21    20 16    15 11    10    0 
          6-bit      5-bit    5-bit    5-bit
          opcode      reg      reg      reg    more opcode
	             desig.   desig.   desig.


    Since there is no addressing mode information (all operands
    are register mode), an operand specification just takes 5
    bits to tell which register is used.

    Examples:  add $8, $10, $12
	       sub $12, $8, $15
	       or  $10, $11, $12



  load/store, arithmetic/logicals that have one operand as an immediate
  value, and all branch instructions

    31   26    25 21    20 16    15             0 
    6-bit      5-bit    5-bit    16-bit immediate
    opcode      reg      reg      
	       desig.   desig.   

  Note that the location of the opcode and the locations of
  the register designations are in the same location within
  this 32-bit instruction.  That makes decoding the instruction
  easier (meaning faster, with less circuitry).

    Examples:  lw   $20, 12($16)
	       addi $12, $8, -6
	       bne  $13, $14, somewhere





sample code
------------

Here is a code fragment of MIPS R2000 code.

# a MIPS code fragment to increment each element of
# an array of 100 integers.
.text

	addi   $8, $0, 0      # value 0 goes into $8 (a counter)
	addi   $9, $0, 100    # $9 is ending value of counter
	la     $11, array     # $11 is pointer into array of integers
loop_top:
	beq    $8, $9, done_loop
	lw     $10, 0($11)    # get array element
	addi   $10, $10, 1    # add one to it
	sw     $10, 0($11)    # put it back
	addi   $11, $11, 4    # update pointer
	addi   $8, $8, 1      # update counter
	beq    $0, $0, loop_top  # uncondional branch


Some notes:
  la is not really a MIPS R2000 instruction.  It is an example of
  and instruction that is allowed in assembly language code, but
  is translated into MIPS R2000 code by the assembler.  This makes
  the job of writing this assembly language code easier.

    For this la instruction, the assembler produces 

    (if symbol array is assigned address 0x00aa0bb0)

    lui  $11, 0x00aa      # $11 gets value 0x 00aa 0000
    ori  $11, $11, 0x0bb0 # $11 gets value 0x 00aa 0bb0

  The MIPS architecture does this with LOTS of instructions.