sections in this module City College of San Francisco - CS270
Computer Architecture

Module: Simple Machine
module list

Advanced Operations

Now that we've covered the simple instructions for the SM and the technique of converting C code to a form that is easier to translate to assembly instructions, let's practice these skills using our SM.

Loops and if-statements require decisions. Decisions in SM involve comparing the counter register (CTR) to zero. There are two instructions for this: JLT and JEQ (JMP is not included as there is no comparison). If the comparison is true the branch is taken and the PC is changed to the address in the instruction. For example,

JLT 0x10

could be written in pseudocode

if (ctr < 0) goto 0x10

In order to perform a comparison on CTR, data must first be moved there. In SM, the CTR is only attached to the accumulator and there are two instructions that move data between them

The first code snippet we did in class was very simple

if (a < b) res =1
else res=0;

(which also could be written in C as res=(a<b) )

This comparison does not compare to zero, so we must transform it first:

if ((a-b) < 0) res = 1
else res=0;

Transforming it using the techniques of the last section:

if ((a-b) < 0) goto altb;
res=0;
goto ageb;
altb: res=1;
ageb:

Now we can write the SM code pretty easily

Instructions
Translated to hexadecimal
# if ((a-b) < 0) goto altb;
# remember SUB A is A - accum
LOAD B
SUB A
MVAC
JLT ALTB
# res=0;
LOAD ZERO
STORE RES
# goto ageb;
JMP AGEB
# altb: res=1;
ALTB: LOAD ONE # offset 7
STORE RES
# ageb:
AGEB: HALT # offset 0x9
PAD: HALT
A:     # offset 0xb
B:     # offset 0xc
RES:   # offset 0xd
ZERO:  # offset 0xe
ONE:   # offset 0xf


0x100c
0x900b
0x4000
0x6007

0x100e
0x200d

0x7009

0x100f
0x200d

0x0
0x0
0x2
0x41
0x0
0x0
0x1

This program is adv1 in the lecturenotes/sim directory of the public work area.

Arrays

In order to make loops interesting we must use arrays. From the last section

in higher-level code
in assembler
element = myarray[i]
temp=&myarray[0]; // or temp=myarray;
temp += i;
element = *temp;

This first instruction on the right requires a new instruction LA (load address), which takes the address in the instruction and places it in the accumulator (rather than the LOAD instruction which loads the data AT the address in the instruction and places it in the accumulator). Note that LA can be used to load any small unsigned constant value into the accumulator. In normal parlance this is called a load immediate.

The last statement on the right needs some more explanation. Our Simple Machine is able to perform indirection using a special-purpose register, the address register (areg for short). If you can generate an address and you want the corresponding data, you simply

This first step requires you to get the address (by LOADing it or calculating it) into the accumulator, then move it to the areg using the MVAA instruction (move accumulator to areg). The last step simply uses the address in the areg and places the data found at that address in the accumulator. Thus LIA overwrites the accumulator. Neither LIA nor MVAA use the address part of the instruction.

Now we are ready to translate our sequence:

LA MYARRAY
ADD I
MVAA
LIA

Similar to LIA is the SIA instruction. The only difference is the direction of the memory transfer. LIA loads the data using the areg's address and places it in the accumulator. SIA stores the data in the accumulator at the address specified in the areg.

Addressing Modes

Now that we have covered most of the SM instructions, we can discuss the addressing modes that our SM uses. If you remember, the addressing mode indicates how to resolve an operand. For example, in our SM, if the ADDR field is 0x10, it could mean value 0x10 or address 0x10, depending on the instruction. This is determined by the addressing mode. In SM, each instruction has set addressing modes. On most machines, some instructions have multiple addressing modes. The mode in use is determined by the binary encoding of the instruction.

The SM uses five addressing modes. Let's go through what each means in general and for our SM

addressing mode
general meaning
use in SM
Register
The value is in a register. On most machines, the register must be specified in the instruction.
In SM, the register (usually the accumulator) is implicit. This is true in instructions such as LOAD (where the destination uses the register addressing mode) and STORE (where the source uses the register addressing mode).
In the MVAC instruction, both source and destination use register addressing mode where the register is implicit.
Memory (or Memory Direct)
The value is in memory. The address of the value is encoded in the instruction.
In SM, the LOAD instruction uses Memory addressing mode for the source operand. This addressing mode is also used by STORE, ADD and SUB. Interestingly, MIPS does not use the Memory addressing mode.
Immediate
The value is a constant which is encoded into the instruction.
In SM, the LA instruction uses Immediate addressing mode.
Base
The address of the value is in a register (the "base" register). The instruction specifies which register.
The LIA instruction uses the base (or "register indirect") addressing mode
Absolute
The address to jump to is encoded in the instruction
The J instructions use Absolute addressing mode.

MIPS will have two additional addressing modes: base plus displacement and PC-relative. We will discuss those later.

Loops

The interesting thing to use loops for is to perform operations on an array. Although the abilities of the SM in that area are limited, lets look at a very basic case:

int arr[N]; sum=0 ;
for (i=0;i<N;i++) sum += arr[i];

We will first convert this to comparisons to zero and gotos:

i=0; sum=0
loop: if ((i-N)==0) goto loopdone;
sum += arr[i];
i++;
goto loop;
loopdone:

Now let's look at the code for various parts:

initialization if ((i-N)==0) goto loopdone; sum += arr[i];

i++;goto loop;

LA 0
STORE SUM
STORE I
LOAD N
SUB I
MVAC
JEQ loopdone
LA ARR
ADD I
MVAA

LIA
ADD SUM
STORE SUM
LA 1
ADD I
STORE I
JMP LOOP

Using this straightforward conversion there are 3 initialization instructions here and 14 instructions per iteration. A loop of 1000 iterations would execute 14003 instructions.

Let's rewrite the loop to take advantage of the SM's strengths, such as they are. The SM is meant to use the ctr register as a loop counter, but the only way to utilize this effectively (and avoid interfering with the accumulator) is to decrement the counter using DECR. Here is a rewrite of the loop that tries to do just that:

for (i=(N-1); i>=0; i--) sum += arr[i];

Rewriting using gotos:

i=(N-1); sum=0;
loop: if (i < 0 ) goto loopdone;
sum += arr[i];
i--;
goto loop;
loopdone:

This looks very similar to our original code - we are just going through the loop in the opposite order. However, when we convert it to SM code we get a surprise

initialization if (i < 0 ) goto loopdone; sum += arr[i]; i--; goto loop;
LA 1
SUB N
MVAC
LA 0
STORE SUM
JLT loopdone
LA ARR
ADDC
MVAA
LIA
ADD SUM
STORE SUM
DECR
JMP loop

By keeping the index in the ctr register we had a big win! We now have 5 initialization and 9 instructions/iteration, or 9005 instructions for our 1000 iteration loop! This is a big example of targeting code to the machine. Fortunately, real machines are not so limited as our SM and writing efficient code is not as "tricky"

Let's try our "convert the code to use pointers" trick and see what we get. We will find that, although this can be a win with real machines, it is not so for our SM - again because of the issue of contention between the accumulator and the counter register.

Here is the code:

int *ptr; for (ptr=&arr[N-1],sum=0; ptr>=&arr[0]; ptr--) sum += *ptr;
int * ptr = &arr[N-1];
loop: if ((ptr - &arr[0]) < 0) goto loopdone;
sum += *ptr;
ptr--;
goto loop
loopdone:

initialization if (i < 0 ) goto loopdone; sum += arr[i]; i--; goto loop;
LA 1
SUB N
STORE NM1
LA ARR
ADD NM1
STORE PTR

LA ARR
SUB PTR
MVAC
JLT loopdone
LOAD PTR
MVAA
LIA
ADD SUM
STORE SUM
LA 1
SUB PTR
STORE PTR
JMP loop

This takes 6 initialization and 13 instructions per iteration. Not a big win from the straightforward method for the SM.

Let's write the code for the winning solution here:

LA 1
SUB N
MVAC
LA 0
STORE SUM
loop: JLT loopdone
LA ARR
ADDC
MVAA
LIA
ADD SUM
STORE SUM
DECR
JMP loop
loopdone:HALT
0x0
SUM:
N:
ARR:
0xB001  #offset 0
0x9011
0x4000
0xB000
0x2010
0x600E  #offset 5
0xB012
0x3000
0xE000
0xC000
0x8010
0x2010
0xA000
0x7005   
0x0     #offset E
0x0
0x0     #offset 0x10
0x5
0x14    #offset 0x12
0xfff9
0x103
0xffe2
0x243

This program is adv2 in the lecturenotes/sim directory of the public work area. (I know this is confusing right now. We will revisit the use of pointers again when we cover loops in MIPS later.)

Another loop problem

Suppose we had a modification of our previous loop:

for (i=(N-1); i>=0; i--) arr[i] += num;

Can you write the resulting Simple Machine program? There is a solution in the file adv3 in the lecturenotes/sim directory of the public work area.

Prev This page was made entirely with free software on linux:  
Kompozer, the Mozilla Project
and Openoffice.org    
Next

Copyright 2015 Greg Boyd - All Rights Reserved.