Chapter 9 -- registers


REGISTERS 
---------

An introduction to the subject of registers -- from a motivational
point of view.

This lecture is an attempt to explain a bit about why computers
are designed (currently) the way they are.  Try to remember that
speed of program execution is an important goal.  Desire for increased
speed drives the design of computer hardware.


The impediment to speed (currently):  transfering data to and from
memory.

look at a SASM instruction:
    iadd  x, y

    -x and y must all be addresses of data in memory.
    -each address is 32 bits.
    -so, this instruction requires MORE than 64 bits.

    if each read from memory delivers 32 bits of data,
    then it takes a lot of reads before this instruction can
    be completed.
       3 for instruction fetch
       1 to load x
       1 to load y
       1 to store x

       that's 6 transactions with memory for 1 instruction!


How bad is the problem?
  Assume that a 32-bit 2's complement addition takes 1 time unit. 
  A read/write from/to memory takes about 10 time units.

  So we get
     fetch instruction:  30 time units
     decode               1 time unit
     load x              10 time units
     load y              10 time units
     add                  1 time unit
     store x             10 time units
     ---------------------------------
       total time:       62 time units

     60/62 = 96.7 % of the time is spent doing memory operations.



what do we do to reduce this number?
  1. transfer more data at one time
     if we transfer 2 words at one time, then it only takes 2 reads
     to get the instruction.  There is no savings in loading/storing
     the operands.  And, an extra word worth of data is transferred
     for each load, a waste of resources.
     So, this idea would give a saving of 1 memory transaction.
  
  2. modify instructions such that they are smaller.
     The Pentium ALREADY has done this!  It only has 2 operands
     for each instruction.

     Most modern machines allow 3 operands, to give instructions
     like:
	    add  x, y, z    ; x <- (y) + (z)
	    Note that this instruction makes the problem worse!
	    Add up the memory accesses for this one!
     They call a machine like this a 3-address machine.  Or, it has
     a 3-address instruction set.


    The differences between 2-address and 3-address instruction sets:
    1. the 2-address instruction set can require more instructions
       to do the same operation as the 3-address instruction set.

       example:   add  x, y, z  ; 3-address instruction set

		  move  x, y    ; 2-address instruction set
		  add   x, z

       memory accesses for this:
	 3-address instruction set: 4 instruction fetch
				    1 to load y
				    1 to load z
				    1 to store x
			   Total =  7

	 2-address instruction set: 3 instruction fetch (move)
				    1 to load y (move)
				    1 to store x (move)
	                            3 instruction fetch (add)
				    1 to load z (add)
				    1 to load x (add)
				    1 to store x (add)
			   Total = 11



  So, allow only 1 operand -- called a 1-address format.
     
     now, the instruction     add  x, y, z   will be accomplished
     by something like

     load  z
     add   y
     store x

     to facilitate this, there is an implied integer of storage
     associated with the ALU.  All results of instructions
     are placed into this integer -- called an ACCUMULATOR.

     the operation of the sequence:
	 load z --  place the contents at address z into the accumulator
		   (sort of like if you did  move accumulator, z  in SASM)
	 add  y --  implied operation is to add the contents of the
		    accumulator with the operand, and place the result
		    back into the accumulator.
	 store x--  place the contents of the accumulator into the location
		    specified by the operand.

     Notice that this 1-address instruction format implies the use
     of a variable (the accumulator).

     How many memory transactions does it take?
	3 -- (load) 2 for instruction fetch, 1 for read of z
	3 -- (add) 2 for instruction fetch, 1 for read of y
	3 -- (store) 2 for instruction fetch, 1 for write of x
       ---
	9   Not better than the 3 address machine.


  BUT, what if the operation following the add was something like
	 div x, x, 3
  then, the value for x is already in the accumulator, and the
  code on the 1 address machine could be
    load z
    add  y
    div  3
    store x
  there is only 1 extra instruction (3 memory transactions) for this
  whole sequence!  
     On the 3-address machine:   13 transactions
     On the 1-address machine:   11 transactions

REMEMBER this:  the 1 address machine uses an extra word of storage
		that is located in the CPU.

		the example shows a savings in memory transactions
		when a value is re-used.



  3.  shorten addresses.  This restricts where variables can be placed.
      First, make each address be 16 bits (instead of 32).  Then
	 add  x, y, z
      requires 2 32-bit words for instruction fetch.

      Shorten addresses even more . . . make them each 5 bits long.
      Problem:  that leaves only 32 words of data for operand storage.
      So, use extra move instructions that allow moving data from
      a 32 bit address to one of these special 32 words.

      Then, the add can fit into 1 instruction.


NOW, put a couple of these ideas together.

Use of storage in CPU (accumulator) allowed re-use of data.
Its easy to design -- put a bunch of storage in the CPU --
call them REGISTERS.  How about 32 of them?  Then, restrict
arithmetic instructions to only use registers as operands.

   add  x, y, z

   becomes something more like

   load  reg10, y
   load  reg11, z
   add   reg12, reg11, reg10
   store x, reg12

presuming that the values for x, y, and z can/will be used again,
the load operations take relatively less time.


A set up like this where arith/logical instr. use only registers
for operands is called a LOAD/STORE architecture.

A computer that allows operands to come from main memory is often
called a MEMORY TO MEMORY architecture, although that term is not
universal.


Load/store architectures are common today.  They have the advantages
  1.  instructions can be fixed length (and short)
  2.  their design allows (easily permits) pipelining, making load/store
      architectures faster
      (More about pipelining at the end of the semester)


IMPORTANT NOTE:  The Pentium architecture (and also SASM) is NOT
  a load/store architecture!  It was designed (and propagated through
  time) with different goals.




a discussion of addressing modes:
                ----------------

Once a computer has registers (and they ALL do!), then there
can be lots of interesting uses of these registers.

Many computers (including the Pentium) offer more ways of
  getting at operands.  These methods come under the classification
  of addressing modes.

   load/store architectures usually have a VERY limited set
   of addressing modes available

   memory to memory architectures (like Pentium) often offer LOTS
   of modes.  This flexibility often forces these machines to have
   variable length instructions (like Pentium).  Variable length
   instructions can make for all sorts of difficulties in making
   a processor go fast!


How to give an addressing mode?  It requires extra bits for each
operand to specify which addressing mode is used.

   We would likely see an instruction something like:


      opcode   addr.mode1  extra.stuff.for.operand1
	       addr.mode2  extra.stuff.for.operand2



Here are some addressing modes.
  An addressing mode really gives the information of where
  an operand is (its address).  An instruction decides how
  to use the address.  This address is better termed an
  EFFECTIVE ADDRESS.

  The processor generates an effective address for each
  operand.  Depending on the instruction, that effective
  address may be used directly, OR it may be used to get
  the operand.



  Register.   The operand is in the register.  The term effective
	      address is not really appropriate here, since there
	      is no address, just the designation for a register.

	      Imagine a computer that implemented SASM, but had
	      3 registers, called reg1, reg2, and reg3.
	      An addition instruction example that used a register
	      addressing mode for one of its operands could be

		 iadd   reg2, 1

	      The contents of reg2 is added to the value 1, and the
	      result is placed back into reg2.  The difference between
	      this imaginary instruction and a real one is in the
	      number of required bits for instruction encoding, and
	      in the number of memory accesses required.

  Immediate.  The operand is contained within the instruction itself.
	      So the effective address generated will be within the
	      instruction.

	      example:  iadd  count, 3  ; a SASM example

	      Often, no effective address is generated at all.  When
	      the instruction is fetched, it contains an encoding of
	      the immediate operand.  Decoding the addressing mode for
	      the operand leads to taking the operand from the instruction.


  Direct.     The effective address for an operand is in the
	      instruction.  Note that this is what SASM implies for
	      most operands.

	      example:  iadd  count, 3  ; a SASM example




  Register Direct.  The effective address for an operand is in
	      a register.


	      example:  add  [reg3], 3

	      The contents of reg3 is the effective address.  For the
	      add instruction, the contents at that address are loaded
	      and then added to the immediate value 3.  The result
	      goes back to that same effective address.

  Base Displacement.  Also called indexed or relative.
	      The effective address is the sum of the contents of a
	      register plus a small constant.

  Indirect.  Adds a level of indirection to direct mode.  An address
	      is specified within the instruction.  The contents
	      at that address is the effective address.

	      A variation might be Register Indirect.  The initial
	      address is located in a register (instead of in the
	      instruction).

  PC Relative. The effective address is calculated relative to the
	      current value of the program counter.

	      As a real life example of this, virtually every architecture
	      has conditional control instructions that work this way.

  An unnamed addressing mode for thought.  The addressing mode specifies
	      2 registers.  The effective address is calculated by adding
	      the contents of the 2 registers together.