0% found this document useful (0 votes)
30 views31 pages

Week 5 - Lecture 5 - MIPS ISA

The document discusses MIPS instruction set architecture and procedures for compiling high-level languages to MIPS assembly code. It covers procedure calls, register usage conventions, memory layout including the stack, and an example of compiling a factorial function and array summation loop. Key steps in compiling a procedure call to MIPS include placing arguments in registers, transferring control with jal, saving and restoring registers, and returning results.

Uploaded by

Việt Hưng
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
30 views31 pages

Week 5 - Lecture 5 - MIPS ISA

The document discusses MIPS instruction set architecture and procedures for compiling high-level languages to MIPS assembly code. It covers procedure calls, register usage conventions, memory layout including the stack, and an example of compiling a factorial function and array summation loop. Key steps in compiling a procedure call to MIPS include placing arguments in registers, transferring control with jal, saving and restoring registers, and returning results.

Uploaded by

Việt Hưng
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 31

ELT3047 Computer Architecture

Lecture 5: MIPS ISA (2)

Hoang Gia Hung


Faculty of Electronics and Telecommunications
University of Engineering and Technology, VNU Hanoi
Last lecture review (1)
❑ Applications of design principles to MIPS ISA
➢ Storage model, taking into account compiler consideration
➢ Addressing modes
➢ Instruction encoding

❑ MIPS instruction set examples


➢ Arithmetic & logical instructions.

R-type op rs rt rd shamt funct


6 5 5 5 5 6
➢ Data transfer & conditional branch instructions

I-type op rs rt Offset (displacement)


6 5 5 16
➢ Unconditional jump instructions

J-type op Address Field


6 26
Last lecture review (2)
❑ MIPS instruction set examples (cont.)
➢ If statement.
➢ Loops
➢ Inequalities

❑ Today’s lecture: some more complex operations and compiling


from HLL to MIPS assembly
➢ Brief introduction to compiler technology.
Procedure/function call: overview
❑ Procedure/function call
➢ Spy analogy: Leaves with a secret plan, acquires resources, performs the
task, covers their tracks & returns to the point of origin with desired result.
➢ One way to implement abstraction in software

❑ Procedure conventions:
➢ Caller:
▪ passes arguments to callee
▪ jumps to callee Factorial C Code

➢ Callee: int factorial(int n)


{
▪ performs the function if (n < 1) return (1);
▪ returns result to caller else return n * factorial(n - 1);
}
▪ returns to point of call
▪ must not overwrite registers or memory needed by caller
Compiling a procedure call in MIPS
❑ Steps required & architectural support in MIPS
Step Description MIPS implementation
1 Place parameters in registers $a0 - $a3
2 Transfer control to procedure & save return address jal, $ra
3 Acquire storage for procedure $gp, $sp, $fp
4 Perform procedure’s operations $t0 – $t9, $s0 – $s7
5 Place result in register for caller $v0, $v1
6 Return to place of call jr $ra

❑ Register usage:
➢ Caller puts arguments in $ a0– $ a3, jumps to callee & simultaneously
saves $PC + 4 in register $ra via the instruction jal &(callee)
➢ Some temporary registers (e.g. $s0 – $s7) must be restored to the values
they hold before the procedure was invoked → spill registers to stack.
➢ When the callee finishes calculations, it places the results in $v0 & $v1, and
returns control to the caller using jr $ra.
MIPS call convention: registers
❑ MIPS register file partition:
➢ $a0–$a3: arguments (reg’s 4 – 7)
➢ $v0, $v1: result values (reg’s 2 and 3)
➢ $t0–$t9: temporaries
➢ $s0–$s7: variables
➢ $gp: global pointer for static data (reg 28)
➢ $sp: stack pointer (reg 29)
➢ $fp: frame pointer (reg 30)
➢ $ra: return address (reg 31)

❑ Register preserving convention:


➢ to reduce register spilling
Preserved (callee-saved/non volatile) Not Preserved (caller-saved/volatile)
Saved registers: $s0-$s7 Temporary registers: $t0-$t9
Stack Pointer: $sp Argument registers: $a0-$a3
Return Address Register: $ra Return registers: $v0-$v1
MIPS call convention: memory layout

Stack = collection of stack frames (aka activation record), each frame


corresponds to a call to a subroutine which has not yet terminated.

❑ Memory allocation for different types of data in HLL


➢ Program code → Text segment
➢ Static/global variables → $gp
➢ Automatic/local variables → $sp, $fp (while managing complex local
variables that do not fit in registers, such as local arrays or structures).
➢ Dynamic data structures (e.g. linked lists) → heap (grows ↑, stack grows ↓)
Example: factorial procedure
0x90 factorial: addi $sp, $sp, -8 # make room (2 words) for stack
0x94 sw $a0, 4($sp) # store $a0
0x98 sw $ra, 0($sp) # store $ra
0x9C slti $t0, $a0, 1 # a < 1 ?
0xA0 beq $t0, $0, else # no: go to else
0xA4 addi $v0, $0, 1 # yes: return 1
0xA8 addi $sp, $sp, 8 # restore $sp (pop 2 words)
0xAC jr $ra # return
0xB0 else: addi $a0, $a0, -1 # n = n - 1
0xB4 jal factorial # recursive call
0xB8 lw $ra, 0($sp) # restore $ra
0xBC lw $a0, 4($sp) # restore $a0
0xC0 addi $sp, $sp, 8 # restore $sp (pop 2 words)
0xC4 mul $v0, $a0, $v0 # n * factorial(n-1)
0xC8 jr $ra # return
Stack layout during factorial execution

Don’t care $sp $v0=6
$a0 (=3) $sp
Frame A
$ra (=PC+4) $sp $v0=6
$a0 (=2) $sp
Frame B
$ra (0xB8) $sp $v0=3
$a0 (=1) $sp
Frame C
$ra (0xB8) $sp $v0=2
$a0 (=0) $sp
Frame D
$ra (0xB8) $sp $v0=1

➢ No need for $fp in the example as the stack is adjusted only on entry and exit
of the procedure → can be managed with only $sp.
➢ Stack frame (activation record) appears on the stack whether or not an explicit
frame pointer is used.
Array and Loop
❑ Access large amounts of similar data (in memory)
➢ Index vs Pointer

Element size
Accessing array elements via pointers in a loop
Initialization for result
0x12340010 array[4] variables, loop counter,
and array pointers.
0x1234800C array[3]
0x12348008 array[2]
0x12348004 array[1]
0x12348000 array[0] Label: Work by:
1. Calculating address
2. Load data
3. Perform task
Array indexing involves
▪ Multiplying index by element size Update loop counter and
▪ Adding to array base address array pointers.

Pointers correspond directly to


memory addresses Compare and branch.
▪ can avoid indexing complexity
Array and Loop: example
❑ Count the number of zeros in an array A
➢ A is word array with 40 elements
➢ Address of A[] → $t0, result → $t8

Zero count C code


result = 0;
❑ Compiling: think about
i = 0;
➢ How to perform the right
while ( i < 40 ) { comparison
if ( A[i] == 0 ) ➢ How to translate A[i] correctly
result++;
i++;
}
Array and Loop: Version 1.0
Address of A[] ➔ $t0
Result ➔ $t8 Comments
i ➔ $t1
addi $t8, $zero, 0
addi $t1, $zero, 0
addi $t2, $zero, 40 # end point
loop: bge $t1, $t2, end
sll $t3, $t1, 2 # i * 4
add $t4, $t0, $t3 # &A[i]
lw $t5, 0($t4) # $t5  A[i]
bne $t5, $zero, skip
addi $t8, $t8, 1 # result++
skip: addi $t1, $t1, 1 # i++
j loop
end:
Array and Loop: Version 2.0
Address of A[] ➔ $t0
Result ➔ $t8 Comments
&A[i] ➔ $t1
addi $t8, $zero, 0
addi $t1, $t0, 0 # pointer to &A[current]
addi $t2, $t0, 160 # end point: &A[40]
loop: bge $t1, $t2, end # comparing address!
lw $t3, 0($t1) # $t3  A[i]
bne $t3, $zero, skip
addi $t8, $t8, 1 # result++
skip: addi $t1, $t1, 4 # move to next item
j loop
end:

❑ Use of “pointers” can produce more efficient code!


➢ Reduces the instructions executed per iteration by 2
Translating and Starting a Program
Example C code
int f, g, y;//global variables Many compilers produce
int main(void) object modules directly
{
f = 2;
g = 3;
y = sum(f, g);
return y;
}
int sum(int a, int b) {
return (a + b);
} Static
linking

HLL advantages over assembly


➢ Productivity (concise, readable,
maintainable)
➢ Correctness (type checking, etc) HLL disadvantages over assembly
➢ Portability (run on different HW) ➢ Efficiency?
Compiler: overview
❑ Assembler (or compiler) translates program into machine
instructions
➢ Most assembler instructions represent machine instructions one-to-one
➢ Pseudo-instructions: figments of the assembler’s imagination, e.g.
move $t0, $t1 → add $t0, $zero, $t1

❑ Provides information for building a complete program from the


pieces
➢ Header: described contents of object module
➢ Text segment: translated instructions
➢ Static data segment: data allocated for the life of the program
➢ Relocation information: for contents that depend on absolute location of
loaded program
➢ Symbol table: global definitions and external refs
➢ Debug info: for associating with source code
Compiler: characteristics
❑ Compilation versus interpretation
HLL
HLL

Compiling Interpreting
Machine 10010100 Virtual Machine
code 11001101
Machine
Running code
Program
Hardware Outputs
outputs Hardware

❑ Characteristics
Compiler Interpreter

How it converts the input? Entire program at once Read one instruction at a time

When is it needed? Once, before the 1st run Every time the program is run

Decision made at Compile time Run time

What it slows down Program development Program execution

➢ Some languages mix both concepts, e.g. Java.


Compilation vs interpretation illustration

Compilation

Interpretation
Anatomy of a compiler
❑ Frontend (analysis phase)
➢ Read source code text & break it up into
meaningful elements (lexeme) & gen. tokens
▪ token = {type, location} of a lexeme
➢ Check correctness, report errors
▪ e.g. “3x” is an illegal token in C
➢ Translate to intermediate representation
▪ IR = machine-independent language
▪ e.g. three-address code (3AC)

❑ Backend (synthesis)
➢ Optimize IR
▪ reduces #operations to be executed
➢ Translate IR to assembly & further optimize
▪ take advantage of particular features of
the ISA
▪ e.g. mult ← sll
Front end stages: Lexical Analysis
❑ Lexical Analysis (scanning)
➢ Source → list of tokens.
Front end stages: Syntax Analysis
❑ Syntax Analysis (parsing)
➢ Tokens → syntax tree = syntactic structure of the original source code (text)
Front end stages: Semantic Analysis
❑ Semantic Analysis
➢ Mainly type checking, i.e. if types of the operands are compatible with the
requested operation.

Symbol table
Front end stages: Intermediate
representation (IR)
❑ Internal compiler language that is
➢ Language-independent
➢ Machine-independent
➢ Easy to optimize

❑ Why yet another language?


➢ Assembly does not have enough info to
optimize it well
➢ Enable modularity and reuse

❑ A common IR: Control Flow Graph


(CFG)
➢ Nodes: basic blocks = sequences of
operations that are executed as a unit
➢ Edges: branches connecting basic blocks
Backend stages: IR optimization
❑ Perform multiple passes over the CFG
➢ A pass = a specific, simple optimization.
➢ Repeatedly apply multiple passes until no further optimization can be found.
➢ Combination of multiple simple optimizations = very complex optimizations.

❑ Typical optimizations:
➢ Dead code elimination: eliminate assignments to variables that are never
used and basic blocks that are never reached.
➢ Constant propagation: identify variables that have a constant value &
substitute that constant in place of references to the variable.
➢ Constant folding: compute expressions with all constant operands.
➢ Example: optimize
IR optimization example: 1st batch of
passes
❑ First 3 passes:
1. Dead code elimination: remove the assignment to z in the first basic block.
2. Constant propagation: replace all references to x with the constant 3.
3. Constant folding: compute constant expressions: y=3+7=10 & _t1=3/2=1
IR optimization example: subsequent
batches of passes

Repetition of simple
optimizations on CFG
=
Very powerful optimizations

No further
optimization found
Backend stages: Code generation
❑ Translate IR to assembly
➢ Map variables to registers (register allocation)
▪ Code generator assigns each variable a dedicated register.
▪ If #variables > #registers, map some less frequently used variables to
Mem and load/store them when needed.
➢ Translate each assignment to instructions
▪ Some assignments requires > 1 instructions.
➢ Emit each basic block
▪ Codes + appropriate labels and branches.
➢ Reorder basic block code wherever possible
▪ to eliminate superfluous jumps.
➢ Perform ISA- and CPU-specific optimizations
▪ e.g. reorder instructions to improve performance.
Compiler output: an object file example
Object file Compiled (assembly) code
Executable
Object file header Text Size Data Size .data
f:
0x34 (52 bytes) 0xC (12 bytes) g:
y:
Text segment Address Instruction .text
0x00400000 0x23BDFFFC main:
addi $sp,addi
$sp, -4$sp, $sp, -4 #init stack
0x00400004 0xAFBF0000 sw $ra,sw 0 ($sp)$ra, 0($sp) # push $ra
0x00400008 0x20040002 addi $a0,addi
$0, 2 $a0, $0, 2 # $a0 = 2
0x0040000C 0xAF848000 sw $a0,sw 0x8000 $a0,
($gp) f # f = 2
0x00400010 0x20050003 addi $a1,addi
$0, 3 $a1, $0, 3 # $a1 = 3
0x00400014 0xAF858004 sw $a1,sw 0x8004 $a1,
($gp) g # g = 3
0x00400018 0x0C10000B jal sum
jal 0x0040002C # call sum
0x0040001C 0xAF828008 sw $v0,sw 0x8008 $v0,
($gp) y # y = sum()
0x00400020 0x8FBF0000 lw $ra,lw 0 ($sp)$ra, 0($sp) # old $ra
0x00400024 0x23BD0004 addi $sp,addi
$sp, -4$sp, $sp, 4 # pop stack
0x00400028 0x03E00008 jr $ra jr $ra # return
0x0040002C 0x00851020 sum:$v0,add
add $v0, $a0, $a1
$a0, $a1
0x00400030 0x03E00008 jr $ra jr $ra

Data segment Symbol Address


Address Data
f 0x10000000
0x10000000 f
0x10000004 g g 0x10000004
0x10000008 y y 0x10000008
main 0x00400000
sum 0x0040002C
Linker
❑ Produces an executable image
1. Merges segments (i.e. “stitches” standard library routines together)
2. Resolve labels (determine their addresses) through relocation information
and symbol table in each object module
3. Patch location-dependent and external refs

❑ Executable file has the same format as an object file, except


that it contains no unresolved references.
➢ Some location dependencies might be fixed by relocating loader, but with
virtual memory, no need to do this
➢ Program can be loaded into absolute location in virtual memory space

❑ Dynamic Linking
➢ Static linking: library routines is part of the executable code → will not be
updated with new versions. Furthermore, it loads all routines in the library
even if those are not executed (image bloat ).
➢ Dynamically linked libraries (DLLs): only link/load library procedure when it
is called → keep location of nonlocal procedures and their names.
Linking object files example
+

+
Loader
❑ Load from image file on disk into memory for execution
1. Read header to determine segment sizes
2. Create virtual address space
3. Copy text and initialized data into memory
▪ Or set page table entries so they can be faulted in
4. Set up arguments on stack
5. Initialize registers (including $sp, $fp, $gp)
6. Jump to startup routine
▪ Copies arguments to $a0, … and calls main
▪ When main returns, do exit syscall

❑ On UNIX systems, loading a program into memory is carried


out by the operating system kernel.
Summary

❑ MIPS implementation of procedure call (stack & heap), array and


❑ Translating and starting a program
❑ Next lecture: initial ISA implementation (read assignments: Ch3.1 – Ch3.4)

You might also like