Title: Chapter 3: Instructions
1Chapter 3 Instructions
2Assembly Language Instructions
- Were going to use the MIPS R2000 instruction set
for the projects in this course - Review Assembly language instructions are
English words that represent binary machine
language instructions
3Arithmetic/Logical Instructions
- Arithmetic instructions are composed of an
operation and three registers - ltopgt ltdestreggt ltoperand1gt ltoperand2gt
- There are 32 32-bit general-purpose integer
registers that we can use (R0 is hardwired to
value 0 for A/L operands) - Ex add 1, 2, 3
- When writing assembly language programs, comments
can be added after any instruction by using the
character - Some architectures only use 2 registers
- The result is stored in the first operand
register - Some of our instructions will use this convention
- Appendix A in the textbook lists all
4Immediate Arithmetic/Logical Instructions
- Most arithmetic/logical instructions have an
immediate version - Immediate instructions have an i at the end of
the instruction name - Immediate instructions allow us to specify an
immediate/constant/literal in lieu of a register
operand - Ex add 1, 2, 16
- We only have 16-bits for the immediate, so we can
only represent 216 unique values - Use decimal numbers for the immediate value in
the assembly-language instruction
5A/R Instructions
- MIPS R2000 A/L-instructions (complete)
- add, addu, addi, addiu
- and, andi
- div, divu (two registers)
- mult, multu (two registers)
- nor
- or, ori
- sll, sllv, sra, srav, srl, srlv
- sub, subu
- xor, xori
6Pseudoinstructions
- Pseudoinstructions are assembled into more than 1
machine instruction - Theres no real machine instruction for them
- Ex. abs rdest, rsrc
- Assembles into three instructions
- move the contents of rsrc into rdest
- if rdest is greater than 0, skip over the next
instruction - We havent covered conditional branches yet
- subtract rdest from 0
- Appendix A specifies which are pseudoinstructions
7Design Considerations
- Making most arithmetic instructions have 3
operands simplifies the hardware - This is a design decision
- Having a variable number of operands would
greatly complicate the hardware - Limiting ourselves to 32 registers is also a
design decision to keep things on the processor
die smaller - Influences clock cycle time
- Gives us more real estate for other things on our
core - Less registers, less decoding logic, etc.
8Registers
- MIPS assembly language also has symbolic names
for the registers - 0 gt constant 0
- 1 gt at (reserved for assembler)
- 2,3 gt v0,v1 (expression evaluation and
results of a function) - 4-7 gt a0-a3 (arguments 1-4)
- 8-15 gt t0-t7 (temporary values)
- Used when evaluating expressions that contain
more than two operands (partial solutions) - Not preserved across function calls
- 16-23 gt s0-gts7 (for local variables,
preserved across function calls) - 24, 25 gt t8, t9 (more temps)
- 26,27 gt k0, k1 (reserved for OS kernel)
- 28 gt gp (pointer to global area)
- 29 gt sp (stack pointer)
- 30 gt fp (frame pointer)
- 31 gt ra (return address, for branch-and-links)
9Memory and Load/Store Instructions
- As weve already seen, a processor can only use
data stored in its registers as operands and
targets for computation - Typically, before computation can be performed,
data must be loaded from main memory - After the computation is complete, the results
must be stored back to main memory
10Memory
- Computer memory is byte-addressed but the MIPS
architecture requires alignment of loads and
stores on the 32-bit (4 byte/word) boundary - This means that all memory references must be an
even multiple of 4 - When addressing 4-byte words, you need to provide
the address of the lowest-addressed byte in the
word
11Load/Store Instructions
- Most commonly used
- lw, sw, lh, sh, lb, sb, la
- Use
- lw ltrdestgt, address
- address can be represented as
- symbolic address (that you declare in SPIM)
- symbolic address with register index
- decimal_offset(basereg)
- This is the way that the instruction is
translated - loads/stores from contents of baseregdecimal_off
set
12Load/Store Instructions
- SPIM treats loads and stores with symbolic
addresses as pseudoinstructions - loads the address of the data segment as an
immediate into 1 - lui 1, 4097
- data starts at hex address 10010000
- If an index register is provided, adds the
contents of the index reg to 1 - addu 1, 1, rindex
- loads 0(1) into rdest
- lw rdest, offset_of_variable(1)
- This is an example of base-displacement
addressing - This is why R1 is reserved when you write your
programs
13Load/Store Instructions
- When loading or storing halfwords and bytes, the
address points to a aligned word - The halfword would be the LOWER (least
significant) halfword of the word that the
address is pointing to - The byte world be the LOWEST (least significant)
byte of the word being that the address is
pointing to
14Constant-Manipulating Instructions
- lui rt, imm
- Load the immediate imm into the upper halfword of
register rt - The lower bits are set to 0
- li rt, imm
- Load the imm into the lower halfword of register
rt - The upper bits are set to 0
15Encoding Instructions
- The MIPS architecture has a 32-bit binary
instruction format for each class of instruction - A/L, constant manip, comparison, branch, jump,
load/store, data movement, floating-point - Even though weve only covered 3 of these
classes, lets look at how we encode the
instructions weve learned
16Encoding/Translating A/L Instructions
- First (most significant, left-most) 6-bits of ALL
instructions is the op-code - The opcode defines the instruction
- Doesnt this only give us 2664 different
instructions? - Yes! But all A/L instructions, excluding the
ones which have immediates, has an opcode of 0
but has a 6-bit field at the end of the
instruction that specifies the operation
17Encoding/Translating A/L Instructions
- Non-immediate A/L instructions
- 6 bits opcode (usually 0)
- 5 bits rs (operand 1)
- 5 bits rt (operand 2)
- 5 bits rd (destination)
- 5 bits 0s or shift amount
- 6 bits operation code
18Encoding/Translating A/L Instructions
- Immediate A/L instructions
- 6 bits opcode (now unique)
- 5 bits rs (operand 1)
- 5 bits rt (destination)
- 16 bits immediate (understood to be 0-extended)
19Encoding/Translating Load/Store Instructions
- 6 bits opcode
- 5 bits rs (base register)
- 5 bits rt (load from/store to)
- Sometimes the whole register isnt used
- Half words and bytes
- 16 bits offset
20Encoding/Translating Constant-Manip. Instructions
- 6 bits opcode
- 5 bits 0s
- 5 bits rt dest. register
- Half of this register will be assigned 0s
- 16 bits immediate
21Examples
- Lets compile the following C code segment into
assembly code - z(ab)(c/d)-(efg)
- lw s0,a
- lw s1,b
- mult s0,s1
- mflo t0 new instruction
- lw s0,c
- lw s1,d
- div s0,s1
- mflo t1
- add t0,t0,t1
- lw s0,e
- lw s1,f
- lw s2,g
- mult s1,s2
- mflo t1
- add t1,s0,t1
- sub t0,t0,t1
- sw t0,z
22Examples
- Note There were many ways we could have
compiled the C statement - Now lets assemble the first three instructions
to machine code - Assume the variables are all stored as words and
are stored sequencially, starting with a, from
the start of the data segment
23Examples
- lw s0,a
- We know s0 is 16
- There are a few different ways we can do this,
too - First, we need to convert this instruction to a
small series of instructions - lui 1,4097 4097 is 1001 in hex
- lw 16,0(1) 0 offset because a is first var
-
- 00111100000000010001000000000001 gt 3C011001
- 10001100000100000000000000000000 gt 8C100000
24Examples
- mult s0, s1
- 00000010000100010000000000011000 gt 02110018
25Branch/Jump Instructions
- Branch and jump instructions are needed for
program control - if-statements (conditionals)
- loops
- procedure calls
- Most common
- b ltlabelgt -- unconditional branch
- label is a memory address (we can be symbolic
ones, of course) - beq, bgez, bgezal, bgtz, blez, etc.
- Conditional branches, where were comparing a
register to 0 or two registers to determine if
were going to branch or not - Also have al (and-link) variants, that link a
return address (instruction following branch)
into 31 so we can return - Branch targets are 16-bit immediate offset
- offset in words it is shifted to the left 2
bits to get byte length
26Branch/Jump Instructions
- j, jal
- Unconditionally branches to a 26-bit pseudodirect
address (not offset) - jalr, jr
- Unconditionally branches to an address stored in
a register
27Encoding/Translating Branch/Jump Instructions
- See Appendix A
- These are very similar to the encoding we covered
before
28Data Movement and Comparison Instructions and
Their Encoding
- Im going to leave the study of these
instructions (from Appendix A) up to you as an
exercise!
29Examples
- if ((agtb)(cd)) e0 else ef
- lw s0,a
- lw s1,b
- bgt s0,s1,next0
- b nope
- next0 lw s0,c
- lw s1,d
- beq s0,s1,yup
- nope lw s0,f
- sw s0,e
- b out
- yup xor s0,s0,s0
- sw s0,e
- out
30Examples
- Again, there are many other ways we could have
tackled this - You will eventually come up with your own
strategies for compiling the types of
constructs you want to perform
31Examples
- How about a for loop?
- for (i0iltai) bii
- lw s0,a
- xor s1,s1,s1
- loop0 blt s1,s0,loop1
- b out
- sll s2,S1,2
- loop1 sw s1,b(s2)
- addi s1,s1,1
- b loop0
- out
32Examples
- How about a pretest while loop?
- while (altb)
- a
-
- lw s0,a
- lw s1,b
- loop0 blt s0,s1,loop1
- b out
- loop1 addi s0,Ss0,1
- sw s0,a
- b loop0
- out
33Examples
- How about a posttest while loop?
- do
- a
- while (altb)
- lw s0,a
- lw s1,b
- loop0 addi s0,s0,1
- sw s0,a
- blt s0,s1,loop0
-
34Procedure Calls
- How about a procedure call?
- The full-blown C/Pascal recursive procedure call
convention is beyond the scope of this class, so
well skip it for now - This is described in detail in Appendix A
- You can arbitrarily implement your own procedure
call convention
35Procedure Calls
- Say we want to write a procedure that computes
the factorial of a number, like this - int factorial (int val)
- int tempval
- while (val)
- temp(--val)
- return temp
36Procedure Calls
- Lets adopt the following simple convention
- Well pass the arguments through a0-a3
- Only allows for up to 4 arguments
- Well set our return value in v0
- The return address will be stored in ra
- This limits us to 1-level of procedure calls
- Well assume the callee (procedure) will save
registers s0-s7 starting at memory address
FF000000 when its called, and restore the
registers before it returns - This may not be necessary for all procedures
37Procedure Calls
- So heres our procedure
- factorial lui t1,0xFF00
- sw s0,0(t1)
- sw s1,4(t1)
-
- sw s7,28(t1)
- move s0,a0 new instruction
- move s1,a0
- loop0 bgtz s0,loop1
- b out
- loop1 mult s0,s1
- mflo s1
- subi s0,s0,1
- b loop0
- out move v0,s1
- lw s0,0(t1) load back registers
-
- jr 31
38Procedure Calls
- In order to call our procedure
- load a value into a0
- bal factorial
- look in v0 for the result!
39I/O
- Doing I/O with SPIM is also described in Appendix
A, but were going to use the system calls that
are set up for us to do I/O
40I/O
- SPIM provides some operating system services
through the syscall instruction - To use the system calls
- load system call code (from pg. a49) into v0 and
argument into a0 - return values in v0 (or f0 for fp results)
41Example I/O
- str
- .asciiz the answer
- .text
- li v0,4
- la a0, str
- syscall
- li v0,1
- la a0,5
- syscall
- (Refer to page A-49)
42Lecture 3aSupplemental Notes for Chapter 3
43Review of Branch Instructions
- b ltlabelgt
- Unconditional branch
- Pseudoinstruction
- beq ltr1gt, ltr2gt, ltlabelgt
- Branch if equal
- bgez ltr1gt, label
- Branch if greater than or equal 0
- bgezal ltr1gt, label
- Branch if greater than or equal 0 and link
4 r1 r2 offset
6 5 5 16
1 r1 1 offset
6 5 5 16
4 r1 0x11 offset
6 5 5 16
44Review of Branch Instructions
- bgtz ltr1gt, ltlabelgt
- Branch if greater than zero
- blez ltr1gt, ltlabelgt
- Branch if less than or equal 0
- bltzal ltr1gt, label
- Branch if less than 0 and link
- bltz ltr1gt, label
- Branch if less than 0
7 r1 0 offset
6 5 5 16
6 r1 0 offset
6 5 5 16
1 r1 0x10 offset
6 5 5 16
1 r1 0 offset
6 5 5 16
45Review of Branch Instructions
- bne ltr1gt, ltr2gt, ltlabelgt
- Branch if not equal
- beqz ltr1gt, ltlabelgt
- Branch if equal 0
- Pseudoinstruction
- bge ltr1gt, ltr2gt, label
- Branch if greater than or equal
- Pseudoinstruction
- bgeu ltr1gt, ltr2gt, label
- Branch if greater than or equal unsigned
- Pseudoinstruction
5 r1 r2 offset
6 5 5 16
46Review of Branch Instructions
- bgt ltr1gt, ltr2gt, ltlabelgt
- Branch if greater than
- Pseudoinstruction
- bgtu ltr1gt, ltr2gt, ltlabelgt
- Branch if greater than unsigned
- Pseudoinstruction
- blte ltr1gt, ltr2gt, label
- Branch if less than or equal
- Pseudoinstruction
- blteu ltr1gt, ltr2gt, label
- Branch if less than or equal unsigned
- Pseudoinstruction
47Review of Branch Instructions
- blt ltr1gt, ltr2gt, ltlabelgt
- Branch if less than
- Pseudoinstruction
- bltu ltr1gt, ltr2gt, ltlabelgt
- Branch if less than unsigned
- Pseudoinstruction
- bnez ltr1gt, label
- Branch if not equal zero
- Pseudoinstruction
48Notes on Branch Instructions
- Offset field represents offset in instruction
words (bytes/4) - starting from the next instruction
- next instruction would be offset 0
- can be negative (as can offset in load/store)
- Branch pseudoinstructions assemble into the
equivalent comparison instruction followed by a
bgtz - And-link instructions load the address of the
next instruction into 31 (ra) if the branch is
taken
49Notes on Comparison Instructions
- There is a comparison instruction for every
conditional branch instruction - They work just like the conditional branch
instructions, but instead, if the comparison is
evaluated true, the destination register is set
to the value 1, and 0 otherwise - slt and sltu follow the R-type format
- Comparison instructions arent really useful,
except for slti and sltiu (unsigned), which are
immediate comparison instructions - They follow the I-type format
- Immediates are sign-extended!!!
- Use these, followed by a bltz to compare a
register and immediate and branch based on result - seq, sge, sgeu, sgt, sgtu, sle, sleu, sne are
pseudoinstructions
50Jump Instructions
- j ltlabelgt
- Unconditional jump (used when b instruction is
used) - jal ltlabelgt
- Jump and link (used for procedure call)
- jalr ltr1gt, ltr2gt
- Jump and link register (same as above, but links
into r2) - jr ltr1gt
- Jump register (used to return from a procedure)
2 target
6 26
3 target
6 26
0 r1 0 r2 0 9
6 5 5 5 5 6
0 r1 0 0x8
6 5 16 6
51Notes on Pseudodirect Addressing
- j and jal use pseudodirect addressing
- To compute the effective branch target address,
the MS 6 bits of the PC are added to the address
in the instruction
52A More Robust Procedure Calling Convention
- Well use a0-a3 to pass parameters to a
procedure - Well use v0 and v1 for procedure returns
- We want to save s0-s7 across procedure calls
- We want to be able to have multiple levels of
procedure calls and we want to be able to call
procedures recursively - This means we need to somehow save arguments,
state registers, and return addresses for each
procedure call
53A More Robust Procedure Calling Convention
- Solution
- Use a stack! When each procedure is called,
push arguments, return address, and saved
registers onto a stack - NOTE The stack frames can be FIXED size using
this convention -
- To create a better procedure calling convention,
we would also allow for variable numbers of
arguments and local variable storage on the
stack, but we will make this simpler
54A More Robust Procedure Calling Convention
- For calling procedures
- Caller must move arguments into argument
registers and jal to procedure - Callee must save arguments, return address, and
machine state (registers) on stack, and decrement
sp by 13452 - sp always points to next stack position
- stack grows down
- Upon completion, callee must set the return value
register(s), restore the s registers, restore
ra, increment sp by 52, and jump back to the
caller - sp is already initialized when you start your
program
55More Notes
- You can use whatever procedure calling convention
you want in your programs, but I recommend using
this one - Your programs procedures will share a static
memory space (no scope) - In order to implement scope, wed have to
allocate local space on the stack