0% found this document useful (0 votes)
80 views

Computer Architecture Lec 10

This document discusses MIPS architecture and instruction set. It covers: - MIPS uses 3-operand arithmetic instructions and fixed operand order. - MIPS is a load/store architecture where operands must be in registers before arithmetic and results stored back to memory. - Memory is organized as a single array addressed by bytes, but words are 32 bits aligned on word boundaries. - Load and store instructions use base+offset addressing to transfer data between registers and memory. - The SPIM simulator is used to execute MIPS assembly code by translating to machine language.

Uploaded by

Niaz Ahmed Khan
Copyright
© © All Rights Reserved
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
80 views

Computer Architecture Lec 10

This document discusses MIPS architecture and instruction set. It covers: - MIPS uses 3-operand arithmetic instructions and fixed operand order. - MIPS is a load/store architecture where operands must be in registers before arithmetic and results stored back to memory. - Memory is organized as a single array addressed by bytes, but words are 32 bits aligned on word boundaries. - Load and store instructions use base+offset addressing to transfer data between registers and memory. - The SPIM simulator is used to execute MIPS assembly code by translating to machine language.

Uploaded by

Niaz Ahmed Khan
Copyright
© © All Rights Reserved
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
You are on page 1/ 41

Computer Architecture

CS 283
Instructor: Sameen Fatima
Lecture 10
MIPS Arithmetic
 All MIPS arithmetic instructions have 3 operands
 Operand order is fixed (e.g., destination first)

 Example:

C code: A = B + C compiler’s job to associate


variables with registers

MIPS code: add $s0, $s1, $s2


Registers vs. Memory
 Arithmetic instructions operands must be in registers
 MIPS has 32 registers
 Compiler associates variables with registers
 What about programs with lots of variables (arrays, etc.)? Use
memory, load/store operations to transfer data from memory to
register – if not enough registers spill registers to memory
 MIPS is a load/store architecture

Control Input
Memory
Datapath Output

Processor I/O
Memory Organization
 Viewed as a large single-dimension array with access by
address
 A memory address is an index into the memory array
 Byte addressing means that the index points to a byte of
memory, and that the unit of memory accessed by a load/store
is a byte
0 8 bits of data
1 8 bits of data

2 8 bits of data

3 8 bits of data

4 8 bits of data

5 8 bits of data
6 8 bits of data

...
Memory Organization
 Bytes are load/store units, but most data items use larger words
 For MIPS, a word is 32 bits or 4 bytes.

0 32 bits of data
4 32 bits of data
Registers correspondingly hold 32 bits of data
8 32 bits of data
12 32 bits of data

...
 232 bytes with byte addresses from 0 to 2 32-1
 230 words with byte addresses 0, 4, 8, ... 2 32-4
 i.e., words are aligned
 what are the least 2 significant bits of a word address?
Load/Store Instructions
 Load and store instructions
 Example:

C code: A[8] = h + A[8];


value offset address
MIPS code (load): lw $t0, 32($s3)
(arithmetic): add $t0, $s2, $t0
(store): sw $t0, 32($s3)

 Load word has destination first, store has destination last


 Remember MIPS arithmetic operands are registers, not memory
locations
 therefore, words must first be moved from memory to registers using
loads before they can be operated on; then result can be stored back to
memory
A MIPS Example

Can we figure out the assembly code?

swap(int v[], int k);


{ int temp;
temp = v[k];
v[k] = v[k+1];
v[k+1] = temp;
}

swap:
muli $2, $5, 4
add $2, $4, $2
lw $15, 0($2)
lw $16, 4($2)
sw $16, 0($2)
sw $15, 4($2)
jr $31
So far we’ve learned:
 MIPS
 loading words but addressing bytes
 arithmetic on registers only

 Instruction Meaning

add $s1, $s2, $s3 $s1 = $s2 + $s3


sub $s1, $s2, $s3 $s1 = $s2 – $s3
lw $s1, 100($s2) $s1 = Memory[$s2+100]
sw $s1, 100($s2) Memory[$s2+100]= $s1
Machine Language

 Instructions, like registers and words of data, are also 32 bits long
 Example: add $t0, $s1, $s2
 registers are numbered, e.g., $t0 is 8, $s1 is 17, $s2 is 18

 Instruction Format R-type (“R” for aRithmetic):

000000 10001 10010 01000 00000 100000


op rs rt rd shamt funct
opcode – first second register shift function field -
operation register register destin- amount selects variant
source source ation of operation
operand operand operand

6 bits 5 bits 5 bits 5 bits 5 bits 6 bits


Machine Language
 Consider the load-word and store-word instructions,
 what would the regularity principle have us do?
 we would have only 5 or 6 bits to determine the offset from a base register - too
little…

 Design Principle 3: Good design demands a compromise


 Introduce a new type of instruction format
 I-type (“I” for Immediate) for data transfer instructions
 Example: lw $t0, 1002($s2)

100011 10010 01000 0000001111101010

op
6 bits rs 5 bits rt 5 bits 16 bit offset
16 bits
Stored Program Concept
 Instructions are bit sequences, just like data
 Programs are stored in memory
 to be read or written just like data

memory for data, programs,


Processor Memory compilers, editors, etc.

 Fetch & Execute Cycle


 instructions are fetched and put into a special register
 bits in the register control the subsequent actions (= execution)
 fetch the next instruction and repeat
SPIM – the MIPS simulator
 SPIM (MIPS spelt backwards!) is a MIPS simulator that
 reads MIPS assembly language files and translates to machine
language
 executes the machine language instructions
 shows contents of registers and memory
 works as a debugger (supports break-points and single-stepping)
 provides basic OS-like services, like simple I/O
 SPIM is freely available on-line
 An important part of our course is to actually write MIPS
assembly code and run using SPIM – the only way to learn
assembly (or any programming language) is to write lots and
lots of code!!!
 Refer to our material, including slides, on SPIM
Memory Organization:
Big/Little Endian Byte Order
 Bytes in a word can be numbered in two ways:
 byte 0 at the leftmost (most significant) to byte 3 at the rightmost
(least significant), called big-endian 0 1 2 3
 byte 3 at the leftmost (most significant) to byte 0 at the rightmost
(least significant), called little-endian 3 2 1 0

Big-endian Little-endian
Bit 31

Bit 31
Bit 0

Bit 0
Memory Memory

Byte 0 Byte 1 Byte 2 Byte 3 Word 0 Byte 3 Byte 2 Byte 1 Byte 0 Word 0

Byte 4 Byte 5 Byte 6 Byte 7 Word 1 Byte 7 Byte 6 Byte 5 Byte 4 Word 1
Memory Organization:
Big/Little Endian Byte Order
 SPIM’s memory storage depends on that of the underlying
machine
 Intel 80x86 processors are little-endian
 because SPIM always shows words from left to right a “mental
adjustment” has to be made for little-endian memory as in Intel PCs
in our labs: start at right of first word go left, start at right of next
word go left, …!
 Word placement in memory (from .data area of code) or word
access (lw, sw) is the same in big or little endian
 Byte placement and byte access (lb, lbu, sb) depend on big or
little endian because of the different numbering of bytes within a
word
 Character placement in memory (from .data area of code)
depend on big or little endian because it is equivalent to byte
placement after ASCII encoding
 Run storeWords.asm from SPIM examples!!
Control: Conditional Branch
 Decision making instructions
 alter the control flow,
 i.e., change the next instruction to be executed

 MIPS conditional branch instructions:

bne $t0, $t1, Label


beq $t0, $t1, Label
I-type instructions

beq $t0, $t1, Label


000100 01000 01001 0000000000011001 (= addr.100)
 Example: if (i==j) h = i + j;

bne $s0, $s1, Label word-relative addressing:


add $s3, $s0, $s1 25 words = 100 bytes;
Label:.... also PC-relative (more…)
Addresses in Branch
 Instructions:
bne $t4,$t5,Label Next instruction is at Label if $t4 != $t5
beq $t4,$t5,Label Next instruction is at Label if $t4 = $t5
 Format:

I op rs rt 16 bit offset

 16 bits is too small a reach in a 2 32 address space

 Solution: specify a register (as for lw and sw) and add it to offset
 use PC (= program counter), called PC-relative addressing, based on
 principle of locality: most branches are to instructions near current
instruction (e.g., loops and if statements)
Addresses in Branch
 Further extend reach of branch by observing all MIPS
instructions are a word (= 4 bytes), therefore word-relative
addressing:
 MIPS branch destination address = (PC + 4) + (4 * offset)
Because hardware typically increments PC early
in execute cycle to point to next instruction

 so offset = (branch destination address – PC – 4)/4


 but SPIM does offset = (branch destination address – PC)/4
Control: Unconditional Branch
(Jump)
 MIPS unconditional branch instructions:
j Label
 Example:
if (i!=j) beq $s4, $s5, Lab1
h=i+j; add $s3, $s4, $s5
else j Lab2
h=i-j; Lab1: sub $s3, $s4, $s5
Lab2: ...
 J-type (“J” for Jump) instruction format
word-relative
 Example: j Label # addr. Label = 100 addressing:
25 words = 100 bytes
000010 00000000000000000000011001
6 bits 26 bits
op 26 bit number
Addresses in Jump
 Word-relative addressing also for jump instructions

J op 26 bit address

 MIPS jump j instruction replaces lower 28 bits of the PC with A00


where A is the 26 bit address; it never changes upper 4 bits
 Example: if PC = 1011X (where X = 28 bits), it is replaced with
1011A00
 there are 16(=24) partitions of the 232 size address space, each partition of
size 256 MB (=228), such that, in each partition the upper 4 bits of the
address is same.
 if a program crosses an address partition, then a j that reaches a
different partition has to be replaced by jr with a full 32-bit address first
loaded into the jump register
 therefore, OS should always try to load a program inside a single partition
Constants
 Small constants are used quite frequently (50% of operands)
e.g., A = A + 5;
B = B + 1;
C = C - 18;

 Solutions? Will these work?


 create hard-wired registers (like $zero) for constants like 1
 put program constants in memory and load them as required

 MIPS Instructions:
addi $29, $29, 4
slti $8, $18, 10
andi $29, $29, 6
ori $29, $29, 4

 How to make this work?


Immediate Operands
 Make operand part of instruction itself!

 Design Principle 4: Make the common case fast

 Example: addi $sp, $sp, 4 # $sp = $sp + 4

001000 11101 11101 0000000000000100


6 bits 5 bits 5 bits 16 bits

op rs rt 16 bit number
How about larger constants?
 First we need to load a 32 bit constant into a register
 Must use two instructions for this: first new load upper immediate
instruction for upper 16 bits
lui $t0, 1010101010101010 filled with zeros

1010101010101010 0000000000000000

 Then get lower 16 bits in place:


ori $t0, $t0, 1010101010101010
1010101010101010 0000000000000000

0000000000000000 1010101010101010
ori
1010101010101010 1010101010101010

 Now the constant is in place, use register-register arithmetic


So far
 Instruction Format Meaning
add $s1,$s2,$s3 R $s1 = $s2 + $s3
sub $s1,$s2,$s3 R $s1 = $s2 – $s3
lw $s1,100($s2) I $s1 = Memory[$s2+100]
sw $s1,100($s2) I Memory[$s2+100] = $s1
bne $s4,$s5,Lab1 I Next instr. is at Lab1 if $s4 != $s5
beq $s4,$s5,Lab2 I Next instr. is at Lab2 if $s4 = $s5
j Lab3 J Next instr. is at Lab3

 Formats:
R op rs rt rd shamt funct
I op rs rt 16 bit address
J op 26 bit address
Control Flow
 We have: beq, bne. What about branch-if-less-than?

 New instruction:
if $s1 < $s2 then
$t0 = 1
slt $t0, $s1, $s2 else
$t0 = 0

 Can use this instruction to build blt $s1, $s2, Label


 how? We generate more than one instruction – pseudo-instruction
 can now build general control structures

 The assembler needs a register to manufacture instructions from pseudo-


instructions

 There is a convention (not mandatory) for use of registers


Policy-of-Use Convention for
Registers
Name Register number Usage
$zero 0 the constant value 0
$v0-$v1 2-3 values for results and expression evaluation
$a0-$a3 4-7 arguments
$t0-$t7 8-15 temporaries
$s0-$s7 16-23 saved
$t8-$t9 24-25 more temporaries
$gp 28 global pointer
$sp 29 stack pointer
$fp 30 frame pointer
$ra 31 return address

Register 1, called $at, is reserved for the assembler; registers 26-27,


called $k0 and $k1 are reserved for the operating system.
Assembly Language vs.
Machine Language
 Assembly provides convenient symbolic representation
 much easier than writing down numbers
 regular rules: e.g., destination first

 Machine language is the underlying reality


 e.g., destination is no longer first

 Assembly can provide pseudo-instructions


 e.g., move $t0, $t1 exists only in assembly
 would be implemented using add $t0, $t1, $zero

 When considering performance you should count actual number


of machine instructions that will execute
Procedures
 Example C code:

// procedure adds 10 to input parameter


int main()
{ int i, j;
i = 5;
j = add10(i);
i = j;
return 0;}

int add10(int i)
{ return (i + 10);}
Procedures
 Translated MIPS assembly
 Note more efficient use of registers possible! save register
.text in stack, see
.globl main figure below
add10:
main:
addi $s0, $0, 5 addi $sp, $sp, -4
add $a0, $s0, $0 sw $s0, 0($sp)
jal add10
addi $s0, $a0, 10
argument add $s1, $v0, $0
add $v0, $s0, $0
to callee add $s0, $s1, $0 result
control returns here to caller
jump and link
li $v0, 10 restore lw $s0, 0($sp)
syscall values addi $sp, $sp, 4

return jr $ra
system code
MEMORY High address
& call to
exit $sp
Content of $s0
Low address
Run this code with PCSpim: procCallsProg1.asm
MIPS: Software Conventions

0 for
zero Registers
constant 0 16 s0 callee saves
1 at reserved for assembler ... (caller can clobber)
2 v0 results from callee 23 s7
3 v1 returned to caller 24 t8 temporary (cont’d)
4 a0 arguments to callee 25 t9
5 a1 from caller: caller saves 26 k0 reserved for OS kernel
6 a2 27 k1
7 a3 28 gp pointer to global area
8 t0 temporary: caller saves 29 sp stack pointer
... (callee can clobber) 30 fp frame pointer
15 t7 31 ra return Address (HW):
caller saves
Procedures (recursive)
 Example C code – recursive factorial subroutine:

int main()
{ int i;
i = 4;
j = fact(i);
return 0;}

int fact(int n)
{ if (n < 1) return (1);
else return ( n*fact(n-1) );}

Procedures (recursive)
Translated MIPS assembly:
.text
.globl main

main: slti $t0, $a0, 1


addi $a0, $0, 4 branch to
beq $t0, $0, L1
jal fact L1 if n>=1
nop nop
move $a0, $v0
control li $v0, 1 addi $v0, $0, 1
returns syscall return 1
if n < 1
addi $sp, $sp, 8
from fact
li $v0, 10
jr $ra
syscall
L1:
print value
fact:
returned by addi $sp, $sp, -8 if n>=1 call addi $a0, $a0, -1
fact sw $ra, 4($sp) fact recursively jal fact
sw $a0, 0($sp)
with argument nop
n-1
exit
restore return lw $a0, 0($sp)
address, argument, lw $ra, 4($sp)
and stack pointer addi $sp, $sp, 8
save return
address and return
argument in n*fact(n-1) mul $v0, $a0, $v0
stack
Run this code with PCSpim: factorialRecursive.asmreturn control jr $ra
Using a Frame Pointer
High address
$fp $fp

$sp $sp
$fp Saved argument
registers (if any)

Saved return address

Saved saved
registers (if any)

Local arrays and


structures (if any)

$sp

Low address
a. b. c.
Variables that are local to a procedure but do not fit into registers (e.g., local arrays, struc-
tures, etc.) are also stored in the stack. This area of the stack is the frame. The frame pointer
$fp points to the top of the frame and the stack pointer to the bottom. The frame pointer does
not change during procedure execution, unlike the stack pointer, so it is a stable base
register from which to compute offsets to local variables.
Use of the frame pointer is optional. If there are no local variables to store in the stack it is
not efficient to use a frame pointer.
Using a Frame Pointer
 Example: procCallsProg1Modified.asm
This program shows code where it may be better to use $fp
 Because the stack size is changing, the offset of variables stored in
the stack w.r.t. the stack pointer $sp changes as well. However, the
offset w.r.t. $fp would remain constant.
 Why would this be better?
The compiler, when generating assembly, typically maintains a table
of program variables and their locations. If these locations are
offsets w.r.t $sp, then every entry must be updated every time the
stack size changes!
 Exercise:
Modify procCallsProg1Modified.asm to use a frame pointer
 Observe that SPIM names register 30 as s8 rather than fp. Of
course, you can use it as fp, but make sure to initialize it with the
same value as sp, i.e., 7fffeffc.
MIPS Addressing Modes
1. Immediate addressing
op rs rt Immediate

2. Register addressing
op rs rt rd ... funct Registers
Register

3. Base addressing
op rs rt Address Memor y

Register + Byte Halfword Word

4. PC-relative addressing
op rs rt Address Memor y

PC + Word

5. Pseudodirect addressing
op Address Memor y

PC Word
Overview of MIPS
 Simple instructions – all 32 bits wide
 Very structured – no unnecessary baggage
 Only three instruction formats

R op rs rt rd shamt funct

I op rs rt 16 bit address

J op 26 bit address
 Rely on compiler to achieve performance
 what are the compiler's goals?
 Help compiler where we can
Summarize MIPS:
MIPS operands
Name Example Comments
$s0-$s7, $t0-$t9, $zero, Fast locations for data. In MIPS, data must be in registers to perform
32 registers $a0-$a3, $v0-$v1, $gp, arithmetic. MIPS register $zero always equals 0. Register $at is
$fp, $sp, $ra, $at reserved for the assembler to handle large constants.
Memory[0], Accessed only by data transfer instructions. MIPS uses byte addresses, so
30
2 memory Memory[4], ..., sequential words differ by 4. Memory holds data structures, such as arrays,
words Memory[4294967292] and spilled registers, such as those saved on procedure calls.

MIPS assembly language


Category Instruction Example Meaning Comments
add add $s1, $s2, $s3 $s1 = $s2 + $s3 Three operands; data in registers

Arithmetic subtract sub $s1, $s2, $s3 $s1 = $s2 - $s3 Three operands; data in registers

add immediate addi $s1, $s2, 100 $s1 = $s2 + 100 Used to add constants
load word lw $s1, 100($s2) $s1 = Memory[$s2 + 100] Word from memory to register
store word sw $s1, 100($s2) Memory[$s2 + 100] = $s1 Word from register to memory
Data transfer load byte lb $s1, 100($s2) $s1 = Memory[$s2 + 100] Byte from memory to register
store byte sb $s1, 100($s2) Memory[$s2 + 100] = $s1 Byte from register to memory
load upper immediate lui $s1, 100 $s1 = 100 * 2
16 Loads constant in upper 16 bits

branch on equal beq $s1, $s2, 25 if ($s1 == $s2) go to Equal test; PC-relative branch
PC + 4 + 100

branch on not equal bne $s1, $s2, 25 if ($s1 != $s2) go to Not equal test; PC-relative
PC + 4 + 100
Conditional
branch set on less than slt $s1, $s2, $s3 if ($s2 < $s3) $s1 = 1; Compare less than; for beq, bne
else $s1 = 0

set less than slti $s1, $s2, 100 if ($s2 < 100) $s1 = 1; Compare less than constant
immediate else $s1 = 0

jump j 2500 go to 10000 Jump to target address


Uncondi- jump register jr $ra go to $ra For switch, procedure return
tional jump jump and link jal 2500 $ra = PC + 4; go to 10000 For procedure call
Alternative Architectures
 Design alternative:
 provide more powerful operations
 goal is to reduce number of instructions executed
 danger is a slower cycle time and/or a higher CPI

 Sometimes referred to as R(educed)ISC vs. C(omplex)ISC


 virtually all new instruction sets since 1982 have been RISC

 We’ll look at PowerPC and 80x86


PowerPC Special Instructions
 Indexed addressing
 Example: lw $t1,$a0+$s3 #$t1=Memory[$a0+$s3]
 what do we have to do in MIPS? add $t0, $a0, $s3
lw $t1, 0($t0)
 Update addressing
 update a register as part of load (for marching through arrays)
 Example: lwu $t0,4($s3) #$t0=Memory[$s3+4];$s3=$s3+4
 what do we have to do in MIPS? lw $t0, 4($s3)
addi $s3, $s3, 4
 Others:
 load multiple words/store multiple words
 a special counter register to improve loop performance:
bc Loop, ctrl != 0 # decrement counter, if not 0 goto loop
 MIPS: addi $t0, $t0, -1
bne $t0, $zero, Loop
A dominant architecture:
80x86
 1978: The Intel 8086 is announced (16 bit architecture)
 1980: The 8087 floating point coprocessor is added
 1982: The 80286 increases address space to 24 bits, +instructions
 1985: The 80386 extends to 32 bits, new addressing modes
 1989-1995: The 80486, Pentium, Pentium Pro add a few
instructions (mostly designed for higher performance)
 1997: MMX is added

“this history illustrates the impact of the “golden handcuffs” of


compatibility”

“adding new features as someone might add clothing to a packed bag”


A dominant architecture:
80x86
 Complexity
 instructions from 1 to 17 bytes long
 one operand must act as both a source and destination
 one operand may come from memory
 several complex addressing modes

 Saving grace:
 the most frequently used instructions are not too difficult to build
 compilers avoid the portions of the architecture that are slow

“an architecture that is difficult to explain and impossible to love”

“ what the 80x86 lacks in style is made up in quantity, making it beautiful from
the right perspective”
Summary
 Instruction complexity is only one variable
 lower instruction count vs. higher CPI / lower clock rate

 Design Principles:
 simplicity favors regularity
 smaller is faster
 good design demands compromise
 make the common case fast

 Instruction set architecture


 a very important abstraction indeed!

You might also like