Professional Documents
Culture Documents
Chapter 9 of Computer Architecture: A Minimalist Perspective
Chapter 9 of Computer Architecture: A Minimalist Perspective
OISC MAPPINGS
Simulating Real Processors with OISC
Let him that would move the world first move himself.
Socrates (469-399 B.C.), Greek philosopher who was willing to call everything into question
to find genuine knowledge.
It has been noted that one of the advantages in studying OISC is that it
can be used to benchmark existing instruction sets. In this chapter such a
process is demonstrated for the four architecture types. The strategy
involves mapping or simulating each architecture with a OISC architecture.
This is done for both MOVE and SBN OISCs.
9.1.1.1 MOVE
Alternatively, a bit could be used to indicate read or write, but then for a
MOVE it becomes:
In each case, MOVE has an associated bit, so there are really two MOVE
instructions, not one.
; x = x – y
PUSH x
; if x-y < 0
GOTO z;
GOTO z;
OISC Mappings 75
The second case illustrates that SBN can push the difference of the two
operands, but the difference is not pushed in the other variant; it is simply
part of the decision to branch or continue to the next address. SBN with a
POP means that the operandam does not contain the result of the difference
operation. The operandum could follow van der Poel’s criterion, that is, the
operandam contains the top of the stack, and the operandum contains the
difference.
Also, if van der Poel’s criterion were not used in the SBN operation, then
the difference would have to be stored in a temporary location, implying
another implicit register. Whereas with a PUSH operation, the operandam
contains the difference, and by van der Poel’s criterion, so would the
operandum. The POP operation, however, does not. Therefore, an SBN
OISC stack architecture would need an implicit stack counter, and possibly
a difference register.
Therefore, in the SBN OISC, like the MOVE OISC, two variants of the
same instruction are needed. Clearly, OISC with stack architecture is
impossible.
9.1.2 Accumulator
9.1.2.1 MOVE
MOVE <only-memory-flag>,accumulator-operandam-flag x, y
MOVE 0 0 y
MOVE 0 1 x
MOVE 1 1 x, y
With the addition of the 2-bit flags, the instruction does not consistently
take the same number of operands. The addition of the 2-bits makes for four
possible variants of the MOVE instruction, so in effect there are four
instructions based on MOVE. Therefore, MOVE no longer provides a one
instruction set computer.
The actual processor could identify from the address if the accumulator
is being accessed, and if so, as an operandam or operandum.
9.1.2.2 SBN
acc = acc – y
y = acc ; by van der Poel’s criterion
if( acc- y < 0)
goto z;
OISC Mappings 77
x = x - acc
acc = x ; by van der Poel’s criterion
if( x - acc < 0)
goto z;
SBN 1 y, z
SBN 0 x, z
So for each variant, there is a single bit version, in effect creating two
instructions based upon SBN.
There is also the problem of getting the value into the accumulator
before the SBN uses the accumulator with a memory operand. Unlike the
MOVE OISC, data must be transferred to (and possibly from) the
accumulator. A certain amount of manipulation is needed to move data
through the bottleneck of the accumulator, before the actual SBN
instruction, to process the contents of the accumulator with another operand
from memory.
SBN x, y, z
acc = acc – y
y = acc ; by van der Poel’s criterion
if( acc- y < 0)
goto z;
78 Chapter 9
x = x - acc
acc = x ; by van der Poel’s criterion
if( x - acc < 0)
goto z;
9.1.3.1 MOVE
9.1.3.2 SBN
SBN normally works on registers, and the results of the operation are
returned to registers. The problem then arises, how to load and store the
registers from main memory? Another technical problem is that SBN can
continue to the next sequence in memory, but how does the sequence
continue within the register set? In this case the next address can be in a
register, but cannot continue in a register.
80 Chapter 9
9.1.4 Register-Memory
Again, both MOVE-based OISC, and SBN-based OISC have the same
issue; the inconsistency of access to registers and memory. The solution is to
take the registers and map them as a part of the memory space, making the
accesses transparent to the instruction, but only apparent within the
software.
9.1.5 Summary
9.2.1 MOVE
MOVE has only the capability to copy, so moving to and from a memory
address creates instructions, the address of the desired operation. Operations
are accessed by memory address, and processor information to be moved to
and from the system is passed through registers accessed by memory
address.
Operation Address
Addition 0x000000FF
Subtraction 0x000000FE
Comparison 0x000000FD
Logical Exclusive Or 0x000000FC
Logical AND 0x000000FB
Register Address
Program counter 0x0000000
Processor Status 0x0000001
Accumulator 0x0000002
Most instructions are binary, taking two operands. In such a case, the
MOVE instruction must move two operands, but the processor operation is
located at only one memory address. This creates an operational
inconsistency, unless two MOVE operations to the same memory location
are required. By use of an accumulator register, a specialized area of
memory can be created that is used by all binary operations. Hence the
accumulator register is added for operational simplicity and consistency.
NOT subtrahend
ADD minuend, subtrahend, difference
NOT operand
CLR operand
DEC operand
XOR
MOVE subtrahend, 0x00000002
MOVE 0xFFFFFFFF, 0x0000FFFC
MOVE 0x0000FFFC, subtrahend
ADD
MOVE minuend, 0x00000002
MOVE subtrahend, 0x0000FFFF
MOVE 0x0000FFFF, difference
9.2.2 SBN
Register Address
Program counter 0x0000000
Processor Status 0x0000001
Accumulator 0x0000002
1. addition,
2. subtraction,
3. comparison,
4. logical exclusive OR, and
5. logical AND.
9.2.2.1 ADD
ADD(X,Y,Z)
Y := 0 – Y;
Z := X – Y or Z := X - - Y which is
Z := X + Y;
9.2.2.2 SUB
9.2.2.3 GOTO
9.2.2.4 CMP
; clear resultant
SBN resultant, resultant, resultant
; determine if GT, or LE
SBN operandam, operandum, temporary, ELSE
SBN GT_CONSTANT, #0x0000000, resultant
; jump to after compare
SBN #0x00000000, #0x0000001, FI
ELSE: SBN LE_CONSTANT, #0x0000000, resultant
FI: SBN #0x00000000, #0x0000000, temporary, 0x00000000
NOP
;clear resultant
SBN 0x00000001, 0x00000001, 0x00000001
; determine if GT, or LE
SBN operandam, operandum, temporary, ELSE
; copy constant to resultant
SBN GT_CONSTANT, #0x0000000, 0x00000001
; jump to after compare
SBN #0x00000000, #0x0000001, FI
ELSE: SBN LE_CONSTANT, #0x0000000, 0x00000001
FI: SBN #0x00000000, #0x0000000, temporary,
0x00000000
; do nothing
NOP
9.2.2.5 XOR
The XOR operation can be synthesized from the SBN, as the SBN uses
an ADD operation, which is based upon XOR.
NOT y
ADD x, y, z
Where NOT uses XOR with 0xFFFF…FFFF, and ADD is XOR. So then
it becomes:
88 Chapter 9
XOR #FFFF…FFFF, y
XOR x, y, z
9.2.2.6 AND
The alternative would be for the compiler or assembler to fill in the next-
address operand with the address of the operation. In effect, a “macro” is
preprocessed before generating machine code.
9.3.1.1 If Statement
if(Boolean expression)
{
then-statements (expression true)
}
else
{
else-statements (expression false)
}
if(x > y)
{
y = x;
}
else
{
x = y;
}
Since a while loop can be used to construct a for-loop (counted loop) the
more general form will be used to illustrate OISC.
while(1)
{
while-statements;
}
while: NOP
JMP &while
The conditional pre-test loop is a while loop. The loop will be executed
zero or greater times. The C while loop:
while(x > y)
{
x--;
}
while:
MOVE &wend, branch-target LE
MOVE $1000, accumulator
MOVE $1001, comparator
MOVE comparator, status-word
MOVE $1000, accumulator
MOVE #0x01, difference
MOVE accumulator, $1000
MOVE &while, PC;
wend: MOVE $1000, $1000;
x++;
goto label;
y++;
label:
x--;
In this example usage, the previous goto statement skips the statement
y++.
JMP &label;
NOP;
label: NOP
9.3.1.4 Expressions
j = x + 3 * (y – 1);
DEC $1000
MUL #0x03, $1000
ADD $1001, $1000
MOVE $1000, $1002
9.3.2.1 Average
The average function takes an array of integers, and an integer size, and
returns their average. The average function in C is:
#include <stdio.h>
sum = 0;
_avg NOP
MOVE &list, $1000 ; avg(list[], size)
MOVE size, $1001
MOVE #00, $1002 ; sum = 0
MOVE #00, $1003 ; x = 0
The binary search function takes an array of sorted integers, a size, and a
key, and then returns the index into the array where the key is found. If not
found, a sentinel value is returned.
OISC Mappings 99
#include <stdio.h>
while(mid != last)
{
last = mid;
_bsearch NOP
MOVE &list, $1000 ; binarysearch(list[],
MOVE size, $1001 ; size,
MOVE key, $1002 ; key)
MOVE #0, $1003 ; low = 0
MOVE $1001, $1004 ; high = size
DEC $1004 ; high-- or high = size - 1
MOVE $(1000), $1005 ; flag = list[0]
DEC $1005 ; flag-- or flag = list[0]-1
MOVE #-1, $1005 ; last = -1
MOVE $1004, $1007 ; mid = high
DIV #02, $1007 ; mid = high / 2
_do
MOVE $1007, $1006 ; last = mid
; compute list[mid]
LDA $1000 ; acc = &list
ADA $1007 ; acc = list[mid]
STA $1008 ; temp = &list[mid]
LDA $(1008) ; acc = list[mid]
CMA $1002 ; if list[mid]
BGT _keygt ; > key
BLT _keylt ; < key
MOVE $1007, $1008 ; temp = mid
JMP _end
_keygt
ADD $1003, $1007 ; mid = mid + low
DIV #02, $1007 ; mid = mid / 2
JMP _while
keylt
ADD $1004, $1007 ; mid = mid + high
DIV #02, $1007 ; mid = mid /2
JMP _while
_while
MOVE &_do, ne-target ; while(mid != last)
MOVE $1007, accumulator
MOVE $1006, comparator
MOVE &_wend, program_counter
_do
MOVE $1007, $1006 ; last = mid
; compute list[mid]
MOVE $1000, accumulator ; acc = &list
MOVE $1007, adder ; acc = list[mid]
MOVE accumulator, $1008 ; temp = &list[mid]
MOVE $(1008), accumulator ; acc = list[mid]
MOVE &_keygt, gt_target ; > key
MOVE &_keylt, lt_target ; < key
MOVE $1002, comparator ; if list[mid]
MOVE $1007, $1008 ; temp = mid
MOVE &_end, program_counter
102 Chapter 9
_keygt
MOVE $1003, accumulator ; mid = mid + low
MOVE $1007, adder
MOVE accumulator, $1007
MOVE #02, accumulator ; mid = mid / 2
MOVE $1007, divider
MOVE accumulator, $1007
MOVE &_while, program_counter
_keylt
MOVE $1004, accumulator ; mid = mid + high
MOVE $1007, adder
MOVE accumulator, $1007
MOVE #02, accumulator ; mid = mid / 2
MOVE $1007, divider
MOVE accumulator, $1007
MOVE &_while, program_counter
_wend
MOVE $1005, $1008 ; temp = flag
_end
MOVE $1008, $(param_stack_ptr) ; PUSH return
The Fibonacci function computes the nth Fibonacci number for all
numbers in the series. The Fibonacci series is recursive in nature, but here is
implemented iteratively. The function computes the desired Fibonacci
number by iteratively computing forward in the series, until the desired
number is reached, which is then returned.
OISC Mappings 103
#include <stdio.h>
fib_first = 1;
fib_next = 1;
return fib_next;
}
104 Chapter 9
fib NOP
; (int index) parameter pass by value
MOVE index, $2000
CMP #01 , $2000 ; index == 1
BEQ _basecase
CMP #02 , $2000 ; index == 2
BEQ _basecase
JMP _startfib
basecase
MOVE #01, $2002 ; return 1 or fib_next=1
JMP _endfor
startfib
MOVE #1, $2001 ; fibfirst = 1
MOVE #1, $2002 ; fibnext = 1
The bubble sort is a simple but is also one of the least efficient sorting
algorithms. The algorithm proceeds down the array, comparing and
swapping the values into sorted order. This process continues until during a
pass of the array, no exchanges of values take place. Values being sorted
seem to "bubble" up to the correct location within the array. The bubble sort
function takes a pointer to an array of integers and an integer size as its
arguments.
#include <stdio.h>
while(1)
{
swapped = 0;
for(x = 0;x < size - 1;x++)
{
if(list[x] > list[x+1])
{
swapped = 1;
temp = list[x];
list[x] = list[x+1];
list[x+1] = temp;
}
}
if(0 == swapped)
return;
}
}
OISC Mappings 107
_bsort NOP
MOVE &list, $1000 ;(int list[],
MOVE size, $1001 ;size)parameter passing
#include <stdio.h>
while(b != 0)
{
r = a % b;
a = b;
b = r;
}
return a;
}
gcd NOP
MOVE a, $3000 ;(int a
MOVE b, $3001 ;int b) parameter pass by value
while CMP #0, $3001 ;while(b != 0)
BEQ _wend
; {
MOVE $3001, $3002 ; r = b
MOD $3000, $3002 ; r = a mod r or r = a mod b
MOVE $3001, $3000 ; a = b
MOVE $3002, $3001 ; b = r
JMP _while ; }
_while
MOVE &_wend, eq_target ;while(b != 0)
MOVE #0, accumulator
MOVE $3001, comparator
; {
MOVE $3001, $3002 ; r = b
MOD $3000, $3002 ; r = a mod r or r = a mod b
MOVE $3001, $3000 ; a = b
MOVE $3002, $3001 ; b = r
MOVE &_while, program_counter ; }
_wend MOVE $3000, $(param_stack_ptr) ; return a
MOVE #1, accumulator
MOVE $param_stack_ptr, adder
MOVE accumulator, $param_stack_ptr
MOVE $run_stack_ptr, $temp ; RET
MOVE #1, accumulator
MOVE $run_stack_ptr, subtractor
MOVE accumulator, $run_stack_ptr
MOVE $temp, program_counter
NOT operandum
ADD operandam, operandum, resultant
ICMP resultant, MAGIC_CONSTANT
BEQ next-address
The constant zero is used for comparison against the result of the
subtraction. If negative, the resulting bit string in the status register will
trigger the branch, using the address in the branch target register. Another
approach is to have a register that uses the appropriate branch-target register
address (which is moved to the program counter) if the status changes.
112 Chapter 9
9.5 Exercises
5. For the algorithms that were implemented in this chapter, are any
more suitable for one instruction than not? Is there a class of algorithms that
are more suitable?