Super Simple ISA

Introduction

We'll look at a very simply ISA (Instruction Set Architecture) to help illustrate the most basic elements of a machine.

Instructions

This ISA provides only 3 instructions:

Opcode Operation Meaning
0ADD a, b, cMem[a] = Mem[b] + Mem[c]
1IMM a, valueMem[a] = value
2BNE target, b, cif (b != c) PC = target

Encoding

Our encoding is simple too. Every instruction is exactly 4 bytes long (one word). The opcode always lives in the first byte and the operands take up the remaining spaces.

Opcode Encoding
ADD0abc
IMM1a?value
BNE2targetab

(Note: a ? means that we don't care what's in this particular field.) If we wanted, for instance, to express the following sentiment: "Add the value in memory location 18 and the value in memory location 24 and place the result into memory location 15." We could write that in "human readable" form as follows:

ADD 15, 18, 24

The machine doesn't read instructions like that, so we could encode the above instruction as follows:
0151824

Note that we've used decimal numbers in each position. Because each location in our instruction is a byte in size, it's often nice to encode the values in hex:
0A1218

Or, even more compactly, as a single, 32-bit hex number: 0x000A1218

An Implementation

A machine to implement this instruction set is extremely simple. It has a program counter (called PC), a memory (called Mem), and adder, a comparitor and a single register for holding the fetched instruction (called IR). It just implements the following algorithm:
while (true) {
  IR = Mem[PC]
  PC = PC + 4 

  if (opcode(IR) == 0)
    Mem[a(IR)] = Mem[b(IR)] + Mem[c(IR)]
  else if (opcode(IR) == 1)
    Mem[a(IR)] = c(IR)
  else if (opcode(IR) == 2)
    if (Mem[b(IR)] != Mem[c(IR)]) PC = a(IR)
}

A Sample Program

Here is an example machine program, loaded starting at location zero in memory:
LocationValues
01100?0
41101?5
81102?-1
121103?0
160100100101
200101101102
24216101103

Now, starting with PC=0, hand simulate this program. Draw a picture of the rest of memory and how it is modified by this program. What does this program do in English?

Issues/Discussion

Now think about the limitations of this particular ISA. In particular:
  1. How many memory references are required per instruction?
  2. The IMM instruction seems to waste a byte. If we made our instructions variable length, how would this impact the implementation of our machine? How would it impact the size of our programs?
  3. Suppose that each memory reference takes 10 units of time, and that other operations take only 1 unit (like adding two numbers). The ADD instruction clearly becomes the most expensive operation we've got, because it performs 3 memory references. Computer clocks run at a fixed period, and that period has to be long enough to perform the longest unit of work the machine wants to do. This means that the ADD instruction essentially determines the length of our clock cycle.
  4. When the machine executes ADD instruction, it's busy for the entire clock cycle, but what about IMM? It's sitting around doing nothing...
  5. Think about how you might improve the situation. Hint: there are two main approaches: (1) Add more registers to the machine, and insist that the machine only operate on data in registers. (2) Change the implementation of the machine so that different instructions can take different amounts of time.
  6. Approach (1) will mean adding instructions to the ISA. What kind of instructions might you add? What is the impact on the size of the programs? Now it seems like our programs have gotten bigger (more instructions) -- if we have to execute more instructions it seems like it should take longer to run our programs. This seems to defeat the whole reason we took this approach. Or does it?
  7. Approach (2) will mean a more complicated implementation.
  8. What is the maximum size of memory in our system? How would you change the ISA to get beyond this limitation?
  9. What is the largest value we can add? Again, how would we change the ISA to handle this situation?
  10. How much work would it take for us to multiply two numbers? Would it be a good idea to add an instruction to our machine to do this?
  11. What other instructions might you add? Hint: Think about common idioms in C/C++, such as:
    i++;
    i = x * 4;
    i = a[5];
    a[13] = ...;
    a[i] = ...;
    if (x == y) ....
    while (p > 0) ...
    foo(x, 22);
    
    Can they be easily represented in machine instructions? Think about the tradeoffs of adding new instructions to an ISA, versus making do with the instructions that already exist.

dugan@cs.washington.edu