I CPCS 214 Cifl Is Computer Organization and Architecture Dr. Laila Nassef 0 Overview of the MIPS Architecture ... Memory 4 bytes per word Up to 232 bytes = 230 words ... EI U 32 General Purpose Registers Arithmetic & Logic Unit $0 $1 $2 $31 AL U Execution & Integer Unit (Main proc) Integer mul/div H i Integer Multiplier/Divider L o FP U FP Arit h F 0 F 1 F 2 Floating Point Unit (Coproc 1) 32 Floating-Point Registers F31 Floating-Point Arithmetic Unit TM BadVaddr Trap & U Status Memory Unit (Coproc 0) Cause EPC 0 MIPS Processor Architecture MIPS processor consists of an integer processing unit (CPU) and a collection of coprocessors that perform ancillary tasks or operate on other types of data such as floating-point numbers. Coprocessor 0 handles exceptions, interrupts, and the virtual memory system Coprocessor 1 is the floating-point unit. MIPS is a load-store architecture, which means that only load and store instructions access memory. Computation instructions (like arithmetic & logical) operate only on values in registers. 0 MIPS General-Purpose Registers 32 General Purpose Registers (GPRs) Assembler uses the dollar notation to name registers $0 is register 0, $1 is register 1, …, and $31 is register 31 All registers are 32-bit wide in MIPS32 Register $0 is always zero Any value written to $0 is discarded Assembler can refer to registers by name or by number It is easier for you to remember registers by name Assembler converts register name to its corresponding number Software defines names to all registers To standardize their use in programs Example: $8 - $15 are called $t0 - $t7 Used for temporary values $0 = $zero $16 = $s0 $1 = $at $17 = $s1 $2 = $v0 $18 = $s2 $3 = $v1 $19 = $s3 $4 = $a0 $20 = $s4 $5 = $a1 $21 = $s5 $6 = $a2 $22 = $s6 $7 = $a3 $23 = $s7 $8 = $t0 $24 = $t8 $9 = $t1 $25 = $t9 $10 = $t2 $26 = $k0 $11 = $t3 $27 = $k1 $12 = $t4 $28 = $gp $13 = $t5 $29 = $sp $14 = $t6 $30 = $fp $15 = $t7 $31 = $ra 0 MIPS Register Conventions Name Register $zero $0 $at $1 Usage Always 0 (forced by hardware) Reserved for assembler use $v0 – $v1 $2 – $3 Result values of a function $a0 – $a3 $4 – $7 Arguments of a function $t0 – $t7 $8 – $15 $s0 – $s7 $16 – $23 $t8 – $t9 $24 – $25 More temporaries $k0 – $k1 $26 – $27 Reserved for OS kernel Temporary Values Saved registers (preserved across call) $gp $28 Global pointer (points to global data) $sp $29 Stack pointer (points to top of stack) $fp $30 Frame pointer (points to stack frame) $ra $31 Return address (used by jal for function call) MIPS CPU Registers MIPS CPU contains 32 general-purpose registers that are numbered $0. . . $31 Register $0 always contains the hardwired value 0 (constant zero and can not be overwritten). Registers also have symbolic names reflecting their conventional use (Most of these conventions concern Procedure call and return) Register $at ($1) reserved for the assembler, Registers $k0 ($26) and $k1($27) are reserved for the operating system. These registers should not be used by user programs or compilers Registers $a0 to $a3 ($4 to $7) are used to pass the first four arguments to functions (remaining arguments are passed on the stack). Registers $v0 ($2) and $v1($3) are used to return values from 0 ● ● ● ● ● ● MIPS CPU Registers Registers $t0 to $t9 ($8 to $15, $24, $25) are caller-saved registers that are used to hold temporay quantities that need not be preserved across calls Register $s0 to $s7 ($16 to $23) are callee-saved registers that hold long-lived values that should be preserved across calls. Register $gp ($28) is a global pointer that points to the middle of a 64K block of memory in the static data segment. Register $sp ($29) is the stack pointer, which points to the last location (stack top) on the stack. Register $fp ($30) is the frame pointer Registers $ra ($31) is the return address register used to hold the return address from procedure call. 0 ● ● Stored-Program Concept Computers built on 2 key principles: 1) Instructions are represented as numbers. 2) Therefore, entire programs can be stored in memory to be read or written just like numbers (data). Simplifies SW/HW of computer systems: Memory technology for data also used for programs Fetch & execute cycle Instructions are fetched and put into a special register Bits in the register "control" the subsequent actions Fetch the “next” instruction and continue 0 ● ● ● ● ● ● Consequence I: Everything Addressed Since all instructions and data are stored in memory as numbers, everything has a memory address Both branches and jumps use these C pointers are just memory addresses: they can point to anything in memory Unconstrained use of addresses can lead to nasty bugs; up to you in C; limits in Java One register keeps address of instruction being executed: Program Counter (PC) Basically a pointer to memory: Intel calls it Instruction Address Pointer, a better name 0 Consequence II: Binary Compatibility ● ● ● ● ● ● ● ● Programs are distributed in binary form Programs bound to specific instruction set Different versions for Macintoshes and PCs New machines want to run old programs/binaries as well as programs compiled to new instructions Leads to instruction set evolving over time Selection of Intel 8086 in 1981 for 1st IBM PC is major reason latest PCs still use 80x86 instruction set (Pentium 4); could still run program from 1981 PC today A stored-program machine is reprogrammable One important motivation was the need for a program to increment or otherwise modify the address portion of instructions 0 Simplicity favors regularity Important Fix the size principles of instructions (simplifies in ISA fetching &and decoding) hardware design Fix the number of operands per instruction All instructions have 3 operands One destination, two operands Operand order is fixed (destination first) Smaller is faster Limit the number of registers for faster access (typically 32 registers of 32 bits) Make the common case fast Most frequently executed instructions are the simplest operations of the ISA. Include constants inside instructions (faster than loading them) Design most instructions to be register-to-register Good design demands good compromises Keep formats as simple as possible (Different formats complicate decoding, but allow 32bit instructions uniformly) Fixed-size instructions compromise the size of constants 0 MIPS Assembly Language ● ● ● ● ● Book Sections 2.1 2.2 2.3 2.4 0 Assembly Variables: Registers ● In assembly language, each statement (called an Instruction), executes exactly one of a short list of simple commands ● Unlike in C (and most other High Level Languages), each line of assembly code contains at most 1 instruction Instructions are related to operations (=, +, -, *, /) in C or Java Unlike HLL, assembly cannot use variables Why not? Keep hardware simple ● ● ● 0 ● ● ● ● ● ● ● ● ● ● ● ● Assembly Variables: Registers Assembly Operands are registers limited number of special locations built directly into the hardware operations can only be performed on these! Benefit: Since registers are directly in hardware, they are very fast (faster than 1 billionth of a second) Different operand locations for different architectures Stack, register, memory or a mix of them Every architecture design after 1980 uses a load-store register architecture: ALU operands are all registers; memory can only be accessed with load/store Advantages of load-store register architectures Registers are faster than memory Registers are more efficient for a compiler to use Drawback: Since registers are in hardware, there are a predetermined number of them Solution: MIPS code must be very carefully put together to efficiently use registers 0 ● ● ● Assembly Variables: Registers MIPS has 32 registers Why 32? Design principle: Smaller Registers are numbered from 0 to 31 is faster ● Each MIPS register is 32 bits wide Groups of 32 bits called a word in MIPS ● Registers are numbered from 0 to 31 ● Each register can be referred to by number or name ● Number references: $0, $1, $2, … $30, $31 ● ● By convention, each register also has a name to make it easier to code $16 - $23 $s0 - $s7 for things that you want to keep around (correspond to C variables) $8 - $15 $t0 - $t7 (for temporary variables) ● In general, use names to make your code more readable ● ● (to make it easier code) 0 Comments in Assembly ● Another way to make your code more readable: comments! ● ● Hash (#) is used for MIPS comments Anything from hash mark to end of line is a comment and will be ignored Every line of your comments must start with a # Note: Different from C. C comments have format /* comment */ so they can span many lines ● ● ● 0 ● ● C, Java variables vs. registers In C (and most High Level Languages) variables declared first and given a type Example: int fahr, celsius; char a, b, c, d, e; ● Each variable can ONLY represent a value of the type it was declared as (cannot mix and match int and char variables). ● In Assembly Language, the registers have no type; operation determines how register contents are treated 0 MIPS Instruction Set ● ● ● ● ● ● ● ● ● ● ● ● MIPS Instructions can be classified into following categories Integer Arithmetic Arithmetic, logical, and shift instructions Data Transfer Load and store instructions that access memory Data movement and conversions Jump and Branch Flow-control instructions that alter the sequential sequence Floating Point Arithmetic Instructions that operate on floating-point registers Miscellaneous Instructions that transfer control to/from exception handlers Memory management instructions 0 0 0 MIPS Instruction Formats ● ● ● ● ● ● ● ● Minimum number of instructions required Information flow: load/store Logic operations: logic and/or/nor, shift Arithmetic operations: addition, subtraction, etc. Branch operations: bne, beq Jump operations: j, jal Instructions have different number of operands 32 bits representing a single instruction Name Fields Comments Field size 6 bits 5 bits 5 bits 5 bits 5 bits 6 bits All MIPS instructions 32 bits R-format op rs rt rd shamt funct Arithmetic instruction format I-format op rs rt address/immediate J-format op target address Transfer, branch, imm. format Jump instruction format 0 MIPS Addition and Subtraction(1/5) Syntax of Instructions: op dest, src1, src2 Example: add $t0, $s1, $s2 (in MIPS) where: # add rd, rs, rt Op: operation by name Dest: operand getting result (“destination”) Src1: 1st operand for operation (“source1”) Src2: 2nd operand for operation (“source2”) ● ● ● Operands must be registers in MIPS Register set of a machine is a limited number of special locations built directly into the hardware Syntax is rigid: All instructions have 3 operands One destination, two operands Operand order is fixed (destination first) Why? Keep Hardware simple via regularity Regularity makes implementation simples Simplicity enables higher performance at lower cost Each line of assembly code contains at most 1 instruction 0 Addition and Subtraction of Integers (2/5 Addition in Assembly Example:add $t0,$s1,$s2 (in MIPS) # add rd, rs, rt Equivalent to: a = b + c (in C) where MIPS registers $t0,$s1,$s2 are associated with C variables a, b, c 0 Subtraction in Assembly Example: sub $s3,$s4,$s5 (in MIPS) # sub rd, rs, rt Equivalent to: d=e-f (in C) where MIPS registers $s3,$s4,$s5 are associated with C variables d, e, f 0 Overflow in Arithmetic (1/2) Reminder: Overflow occurs when there is a mistake in arithmetic due to the limited precision in computers. Example (4-bit unsigned numbers): +15 +3 +18 1111 0011 10010 But we don’t have room for 5-bit solution, so the solution would be 0010, which is +2, and wrong. 0 Overflow in Arithmetic (2/2) ● ● ● ● ● ● ● ● ● ● ● Some languages detect overflow (Ada), some don’t (C) MIPS solution is 2 kinds of arithmetic instructions to recognize 2 choices: add (add), add immediate (addi) and subtract (sub) cause overflow to be detected addi: overflow causes an arithmetic exception In case of overflow, result is not written to destination register add unsigned (addu), add immediate unsigned (addiu) and subtract unsigned (subu) do not cause overflow detection addiu: same operation as addi but overflow is ignored Immediate constant for addi and addiu is signed No need for subi or subiu instructions Compiler selects appropriate arithmetic MIPS C compilers produce addu, addiu, subu 0 ● ● ● MIPS - Arithmetic Instructions add (add registers signed) Instruction Mnemonic : add rd, rs, rt ;where rs, rt, rd are registers, overflow detected Meaning : rd rs + rt ; signed add operation Example : add $s1, $s2, $s3 ; $s1 $s2 + $s3 addu (add registers unsigned) Instruction Mnemonic : addu rd, rs, rt ;where rs, rt, rd are registers, overflow not detected Meaning : rd rs + rt ; unsigned add operation Example : addu $s1, $s2, $s3 ; $s1 $s2 + $s3 0 ● ● ● ● ● ● MIPS - Arithmetic Instructions sub (subtract registers signed) Instruction Mnemonic : sub rd, rs, rt ;where rs, rt, rd are registers, overflow detected Meaning : rd rs - rt ; signed subtraction Example : sub $s1, $s2, $s3 ; $s1 $s2 - $s3 subu (subtract registers unsigned) Instruction Mnemonic : subu rd, rs, rt ;where rs, rt, rd are registers, overflow not detected Meaning : rd rs - rt ; unsigned subtraction Example : subu $s1, $s2, $s3 ; $s1 $s2 - $s3 0 MIPS Arithmetic with Registers Example: C code: a=b+c MIPS code: C code: add a,b,c a = b + c + d; MIPS code: add a, b, c add a, a, d Design principle: Hardware implementation is simplified via regularity 0 Addition and Subtraction of Integers (3/5) How do the following C statement? ● a = b + c + d - e; mapping a $s0 b $s1 c $s2 d $s3 e $s4 0 Addition and Subtraction of Integers (4/5) Break into multiple instructions add $t0, $s1, $s2 # temp = b + c add $t0, $t0, $s3 # temp = temp + d sub $s0, $t0, $s4 # a = temp - e Notice: A single line of C may break up into several lines of MIPS. Notice: Everything after the hash mark on each line is ignored (comments) 0 Addition/Subtraction Example (5/5) Consider the translation of: f = (g+h) – (i+j) Compiler allocates registers to variables Assume that f, g, h, i, and j are allocated registers $s0($16), $s1($17), $s2($18), $s3($19), $s4($20) i.e., $s0 f, $s1 g, $s2 h, $s3 i, $s4 j • Translation of: f = (g+h) – (i+j) addu $t0, $s1, $s2 # $t0 = g + h addu $t1, $s3, $s4 # $t1 = i + j subu $s0, $t0, $t1 # f = (g+h)–(i+j) – Temporary results are stored in $t0($8) and $t1($9) – Final result, i.e., computed f value is stored in $s0 0 Register Zero ● One particular immediate, the number zero (0), appears very often in code ● So we define register zero ($0 or $zero) to always have the value 0 Often used to move values or set constant values f = g (in C copy contenet) add $s0,$s1,$zero (in MIPS) MIPS registers $s0, $s1 are associated with C variables f, g ● ● ● ● ● ● $zero defined in hardware Instruction add $zero,$zero,$s0 will not do anything! 0 Register Immediate Instruction ● Immediates are numerical constants. ● They appear often in code, so there are special instructions for them. Add Immediate: ● ● op dest, srcA, immediate addi $s0,$s1,10 (in MIPS) f = g + 10 (in C) where MIPS registers $s0,$s1 are associated with C variables f, g Syntax similar to add instruction, except that last argument is a number instead of a register. 0 Immediates There is no Subtract Immediate in MIPS: Why? Limit types of operations that can be done to absolute minimum if an operation can be decomposed into a simpler operation, don’t include it (addi …, -X)= (subi …, X) => so no subi addi $s0,$s1,-10 (in MIPS) f = g - 10 (in C) where MIPS registers $s0,$s1 are associated with C variables f, g 0 addi (add immediate signed ) Instruction Mnemonic : addi rd, rs, const ;where rs, rd are registers, const is a 16-bit constant value ;overflow detected Meaning : rd rs + const Example : addi $s1, $s2, 100 ; $s1 $s2 + 100 addiu (add immediate unsigned) Instruction Mnemonic : addiu rd, rs, const ;where rs, rd are registers, const is a 16-bit constant value ;overflow not detected Meaning : rd rs + const Example : addiu $s1, $s2, 100 ; $s1 $s2 + 100 0 ● Different formats complicate decoding, but allow 32bit instructions uniformly Keep formats as simple as possible ● Good design demands good compromises ● 0 Assembly Operands: Memory 0 Assembly Operands: Memory ● C variables map onto registers; what about large data structures like arrays? ● Memory contains such data structures But MIPS arithmetic instructions only operate on registers, never directly on memory. Data transfer instructions transfer data between registers and memory: Memory to register Register to memory ● ● ● ● 0 Memory Organization Think of memory as a large, single-dimension array A memory address is an index into the array "Byte addressing" means that the index points to a byte of memory We can address it simply by supplying a pointer to a memory address Other times we want to be able to offset from this pointer. 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 ... 0 Memory Organization Bytes are nice, but most data items use larger "words" For MIPS, a word is 32 bits or 4 bytes 0 32 bits of data 4 8 32 bits of data 32 bits of data 12 32 bits of data MIPS register holds 32 bits of data 232 bytes with byte addresses from 0 to 232-1 ... 230 words with byte addresses 0, 4, 8, ... 232-4 Words are aligned: they must start at addresses that are multiples of 4 0 Addressing: Byte vs. word ● Every word in memory has an address, similar to an index in an array ● Early computers numbered words like C numbers elements of an array: Memory[0], Memory[1], Memory[2], … ● Called the “address” of a word • Computers needed to access 8-bit bytes as well as words (4 bytes/word) • Today machines address memory as bytes, (i.e.,“Byte Addressed”) hence 32-bit (4 byte) word addresses differ by 4 Memory[0], Memory[4], Memory[8], … • 0 More Notes about Memory: Alignment ● MIPS requires that all words start at byte addresses that are multiples of 4 bytes 0 Aligned Not Aligned • 1 2 3 Last hex digit of address is: 0, 4, 8, or Chex 1, 5, 9, or Dhex 2, 6, A, or Ehex 3, 7, B, or Fhex Called Alignment: objects must fall on address that is multiple of their size. 0 ● ● ● ● ● Notes about Memory Pitfall: forgetting that sequential word addresses in machines do not differ by 1 To transfer a word, the sum of the base address and the offset must be a multiple of 4 (to be word aligned) 0 Aligned Not Aligned 1 2 3 Last hex digit of address 0, 4, 8, or Chex 1, 5, 9, or Dhex 2, 6, A, or Ehex What if more variables than registers? 3, 7, B, or Fhex Compiler tries to keep most frequently used variable in registers Less common in memory: spilling 0 • Instructions that transfer data between memory & registers • Programs include variables such as arrays and objects • Such variables are stored in memory • Load Instruction: – Transfers data from memory to a register • Store Instruction: – Transfers data from a register to memory • Memory address must be specified by load and store 0 Data Transfer: Memory to Reg (1/4) ● ● ● ● ● To transfer a word of data, we need to specify two things: Register: specify this by # ($0 - $31) or symbolic name ($s0, …, $t0, …) Memory address: more difficult Think of memory as a single one-dimensional array, so we can address it simply by supplying a pointer to a memory address. Other times, we want to be able to offset from this pointer. 0 Data Transfer: Memory to Reg (2/4) ● ● ● ● ● ● To specify a memory address to copy from, specify two things: A register containing a pointer to memory A numerical offset (in bytes) The desired memory address is the sum of these two values. Example: 8($t0) specifies the memory address pointed to by the value in $t0, plus 8 bytes 0 ● ● ● ● ● ● Data Transfer: Memory to Reg (3/4) MIPS has two basic data transfer instructions for accessing memory lw $t0, 4($s3) #load word from memory sw $t0, 8($s3) #store word to memory Load instruction syntax: lw reg1, offset(reg2) Operator name: lw (meaning Load Word, so 32 bits or one word are loaded at a time) Reg1: register that will receive the transferred data (destination) Offset: a numerical offset in bytes Reg2: register containing pointer to memory, called base register 0 ● ● ● ● Data Transfer: Memory to Register (4/4) Data flow Example: lw $t0,32($s3) This instruction will take the pointer in $s3, add 32 bytes to it, and then load the value from the memory pointed to by this calculated sum into register $t0 Notes: $s3 is called the base register 32 is called the offset offset is generally used in accessing elements of array or structure: base register points to beginning of array or structure 0 ● ● ● ● ● Data Transfer: Register to Memory Also want to store from register into memory Store instruction syntax is identical to Load’s MIPS Instruction Name: sw (meaning Store Word, so 32 bits or one word are loaded at a time) Data flow Example: sw $t0,48($s3) This instruction will take the pointer in $s3, add 48 bytes to it, and then store the value from register $t0 into that memory address Remember: “Store INTO memory” 0 Example C code: A[12] = h + A[8]; MIPS code: lw $t0, 32($s3) # base address of array A is in $s3 # base register # 1 array element is 4-byte #alignment is multiple of 4 # index 8 requires offset of 32 # temp t0 = A[8] add $t0, $s2, $t0 # h is associated with $s2 sw $t0, 48($s3) # offset=12*4=48 Can refer to registers by name (e.g., $s2, $t2) instead of number Store word has destination last Remember arithmetic operands are registers, not memory! Can’t write: add 48($s3), $s2, 32($s3) 0 Compilation with Memory ● ● ● ● ● ● ● What offset in lw to select A[5] in C? 4x5=20 to select A[5]: byte v. word Compile by hand using registers: g = h + A[5]; g: $s1, h: $s2, $s3:base address of A 1st transfer from memory to register: lw $t0,20($s3) # $t0 gets A[5] Add 20 to $s3 to select A[5], put into $t0 Next add it to h and place in g add $s1,$s2,$t0 # $s1 = h+A[5] 0 Notes about Memory ● Many an assembly language programmer has toiled over errors made by assuming that the address of the next word can be found by incrementing the address in a register by 1 instead of by the word size in bytes. ● So remember that for both lw and sw, the sum of the base address and the offset must be a multiple of 4 (to be word aligned) 0 Role of Registers vs. Memory ● ● ● ● ● ● ● ● What if more variables than registers? Compiler tries to keep most frequently used variable in registers Less common in memory: spilling Why not keep all variables in memory? Smaller is faster: registers are faster than memory Registers more versatile: MIPS arithmetic instructions can read 2, operate on them, and write 1 per instruction MIPS data transfer only read or write 1 operand per instruction, and no operation 0 Pointers vs. Values ● ● ● ● ● Key concept: a register can hold any 32-bit value That value can be a signed int, an unsigned int, a pointer (memory address), and so on If you write add $t2,$t1,$t0, then $t0 and $t1 better contain values If you write lw $t2,0($t0), then $t0 better contains a pointer Don’t mix these up! 0 opcod e 100011 r s 01001 r t 10000 r d 00000 10010 01000 0100 0 0 101011 01001 01000 sham func t t 1200 0000 10000 0 0 1200 • Translate A[300] = A[300] + h (A is an array of words) – Assume that address of array A is stored in register $t1, h in $s2 lw $t0, 1200($t1) Add $t0, $s2, $t0 sw $t0, 1200($t1) 0 • Load Word Instruction (Word = 4 bytes in MIPS) lw Rt, imm16 (Rs) # Rt = MEMORY[Rs+ , imm16 ] • Store Word Instruction sw Rt, , imm16 (Rs) # MEMORY[Rs+ , imm16 ] = Rt • Base or Displacement addressing is used – Memory Address = Rs (base) + immediate16 (displacement) – Immediate16 is sign-extended to have a signed displacement • Base or Displacement Addressing is used – Memory Address = Rs (base) + , immediate16 (displacement) • Two variations on base addressing – If Rs = $zero = 0 then Address = , immediate16 (absolute) – If , immediate16 = 0 then Address = Rs (register indirect) 0 Data Transfer Instructions lw (Load word) Instruction Mnemonic : lw rd, const(rs) ;where rs, rd are registers, const is a 16-bit displacement lw rd, addr ; where addr is the label of the memory location to be accessed Meaning : rd Memory[rs + const] ; load word from memory to register Example : lw $s1, 100($s2) ; $s1 Memory[$s2+100] lw $s1, NUM1 ; load register $s1 with a word from memory location NUM1 0 lh (Load halfword with sign extension) ● ● ● Instruction Mnemonic : lh rd, const(rs) ;where rs, rd are registers, const is a 16-bit displacement lh rd, addr ; where addr is the label of the memory location to be accessed Meaning : rd Memory[rs + const] ; load halfword from memory to register Example : lh $s1, 100($s2) ; $s1 Memory[$s2+100] lh $s1, NUM1 ; load register $s1 with a half-word from memory location NUM1 0 ● ● ● lhu (Load halfword unsigned – without sign extension) Instruction Mnemonic : lhu rd, const(rs) ;where rs, rd are registers, const is a 16-bit displacement lhu rd, addr ; where addr is the label of the memory location to be accessed Meaning : rd Memory[rs + const] ; load halfword from memory to register Example : lhu $s1, 100($s2) ; $s1 Memory[$s2+100] lhu $s1, NUM1 ; load register $s1 with a half-word from memory location NUM1 0 lb (Load byte with sign extension) ● ● ● Instruction Mnemonic : lb rd, const(rs) ;where rs, rd are registers, const is a 16-bit displacement lb rd, addr ; where addr is the label of the memory location to be accessed Meaning : rd Memory[rs + const] ; load byte from memory to register Example : lb $s1, 100($s2) ; $s1 Memory[$s2+100] lb $s1, NUM1 ; load register $s1 with a byte from memory location NUM1 0 lbu (Load byte unsigned – without sign extension) ● ● Instruction Mnemonic : lbu rd, const(rs) ;where rs, rd are registers, const is a 16-bit displacement lbu rd, addr ; where addr is the label of the memory location to be accessed Meaning : rd Memory[rs + const] ; load unsigned byte from memory to register Example : lbu $s1, 100($s2) ; $s1 Memory[$s2+100] lbu $s1, NUM1 ; load register $s1 with a byte from memory location NUM1 0 0 Loading & Storing Bytes In addition to word data transfers, MIPS has byte data transfers for characters (char type) Load byte: lb; store byte: sb Same format as lw, sw What to do with other 24 bits in the 32 bit register? lb: sign extends to fill upper 24 bits xxxx xxxx xxxx xxxx xxxx xxxx …is copied to “sign-extend” xzzz zzzz byte This bitloaded Normally do not want to sign extend chars MIPS instruction that does not sign extend when loading bytes -- load byte unsigned: lbu 0 Load and Store Byte and Halfword • The MIPS processor supports the following data formats: – Byte = 8 bits, Halfword = 16 bits, Word = 32 bits • Load & store instructions for bytes and halfwords – lb = load byte, lbu = load byte unsigned, sb = store byte – lh = load half, lhu = load half unsigned, sh = store halfword • Load expands a memory data to fit into a 32-bit register • Store reduces a 32-bit register to fit in memory 0 Instruction Representation ● ● Book Sections 2.5 0 Instructions as Numbers (1/2) ● How do we represent instructions? Remember: Computer only understands 1s and 0s MIPS wants simplicity: since data is in words, make instructions be words too One word is 32 bits, so divide instruction word into “fields”. ● Each field tells computer something about instruction. ● ● ● 0 ● ● ● ● Instructions as Numbers (2/2) We could define different fields for each instruction, but MIPS is based on simplicity, so define 3 basic types of instruction formats: R-format I-format J-format 0 Instruction Formats I-format: immediate format Instructions with immediates lw and sw (since the offset counts as an immediate), and the branches (beq and bne), (but not the shift instructions; later) Data transfer instructions (since the offset counts as an immediate) Branches (beq and bne) J-format: jump format j and jal (more details later) R-format: used for all other instructions It will soon become clear why the instructions have been partitioned in this way 0 R-Format Instructions (1/5) ● Define “fields” of the following number of bits each: 6 + 5 + 5 + 5 + 5 + 6 = 32 6 5 5 5 5 6 • For simplicity, each field has a name: opcode rs rt rd sham t func t • Important: each field is viewed as a 5- or 6bit unsigned integer, not as part of a 32-bit integer. • Consequence: 5-bit fields can represent any number 0-31, while 6-bit fields can represent any number 0-63. 0 R-Format Instructions (2/5) What do these field integer values tell us? ● ● ● ● ● opcode: partially specifies what instruction it is Specifies the operation of the instruction Also specifies the format of the instruction Note: This number is equal to 0 for all R-Format instructions. funct: combined with opcode, this number exactly specifies the instruction Up to 26= 64 functions can be defined for the same opcode Question: Why aren’t opcode and funct a single 12-bit field? ● ● Answer: We’ll answer this later. 0 ● ● ● ● R-Format Instructions (3/5) Three Register Operands (common to many instructions): rs (Source Register): generally used to specify register containing first operand rt (Target Register): generally used to specify register containing second operand (note that name is misleading) rd (Destination Register): generally used to specify register which will receive result of computation 0 R-Format Instructions (4/5) Notes about register fields: ● Each register field is exactly 5 bits, which means that it can specify any unsigned integer in the range 0-31. Each of these fields specifies one of the 32 registers by number. The word “generally” was used because there are exceptions that we’ll see later. E.g., ● ● ● ● mult and div have nothing important in the rd field since the dest registers are hi and lo mfhi and mflo have nothing important in the rs and rt fields since the source is determined by the instruction 0 R-Format Instructions (5/5) Final field: shamt: This field contains the amount a shift instruction will shift by. Shifting a 32-bit word by more than 31 is useless, so this field is only 5 bits (so it can represent the numbers 0-31). This field is set to 0 in all but the shift instructions. 0 ● ● ● R-Format Example (1/2) MIPS Instruction: Add rd, rs, rt add $t0,$s1,$s2 opcode = 0 funct = 32 rd = 8 (destination) rs = 17 (first operand) rt = 18 (second operand) shamt = 0 (not a shift) 0 R-Format Example (2/2) MIPS Instruction: add $t0,$s1,$s2 #Add rd, rs, rt Encode to decide the value of each field opcode = 0, funct = 32 (look up in table in book) rd = 8 (destination) rs = 17(first operand), rt = 18 (second operand) shamt = 0 (not a shift) opcode rd shamt funct Decimal rs number perrt field representation 0Binary number 17 per field 18 representation 8 0 32 000000 1000 0100 Machine language1001 instruction in hexa: 0000 100000 Hex representation: 0232 1 0 4020hex0 0 he x 0 ● Translate: addu $t0,$s1,$s2 to binary code 0 I-Type Format • Constants are used quite frequently in programs The R-type shift instructions have a 5-bit shift amount constant What about other instructions that need a constant? • I-Type: Instructions with Immediate Operands • 16-bit immediate constant is specified immediately in the instruction Rs is the source register number Rt is now the destination register number (for R-type it was Rd) Examples of I-Type ALU Instructions: Add immediate: addi $s1, $s2, 10 # $s1 = $s2 + 10 OR immediate: ori $s1, $s2, 10 # $s1 = $s2 | 10 (1) may cause overflow (2) sign extension immediate 0 0 I-Format Instructions (1/4) What about instructions with immediates? 5-bit field only represents numbers up to the value 31: immediates may be much larger Ideally, MIPS would have only one instruction format for simplicity: unfortunately, we need to compromise ● ● ● ● ● ● ● ● Still, try to define new instruction format that is partially consistent with R-format The first three fields of both formats are the same size and have the same names The rest three fields in R-format are merged to form a single field for the immediate operand Define new instruction format that is partially consistent with R-format: First notice that, if instruction has immediate, then it uses at most 2 registers. 0 I-Format Instructions (2/4) ● Define “fields” of the following number of bits each: 6 + 5 + 5 + 16 = 32 bits 6 5 5 16 • Again, each field has a name: opcode rs rt immediat e • Key Concept: Only one field is inconsistent with R-format. Most importantly, opcode is still in same location. 0 I-Format Instructions (3/4) 6 opcode ● ● ● ● ● 5 rs 5 rt 16 immediat e What do these fields mean? opcode: same as before except that, since there’s no funct field, opcode uniquely specifies an instruction in I-format This also answers question of why R-format has two 6bit fields to identify instruction instead of a single 12-bit field: in order to be consistent with other formats. rs: specifies the only register operand (if there is one) rt: specifies register which will receive result of computation (this is why it’s called the target register “rt”) 0 I-Format Instructions (4/4) The immediate field Used to specify immediates for instructions with a numerical constant operands Used to specify address offset in data transfer instructions: lw, sw, etc. Used to specify branch address in bne and beq Range Both positive and negative numbers 16 bits can be used to represent immediate up to 216 different values What if the number we want to represent is out of the range? 0 ● ● ● ● ● ● ● ● ● Large Immediates Range of immediates is limited Length of immediate field is 16 bits Considered as a signed number (sign bit) Arithmetic operands or address offset can be larger 32-bit data / address in MIPS We need a way to deal with a 32-bit immediate in any Iformat instruction Solution: Handle it in software + new instruction Don’t change the current instructions: instead, add a new instruction to help out 0 long constant ● addi $s0, $0,75000 #needs more than 16 bits ● Load 32 bits into a register using load upper 16 bits than load lower 16 bits ● 0000 0000 0000 0001 0010 0100 1111 1000 lui $s0,1 0000 0000 0000 0001 0000 0000 0000 0000 ori $s0,$s0,9464 0000 0000 0000 0001 0010 0100 1111 1000 ● ● ● ● 0 I-Format Problems (1/3) ● ● ● ● Problem 1: Chances are that addi, lw, sw and slti will use immediates small enough to fit in the immediate field. …but what if it’s too big? We need a way to deal with a 32-bit immediate in any I-format instruction. I-Format Problems (2/3) ● ● ● ● ● ● ● Solution to Problem 1: Handle it in software + new instruction Don’t change the current instructions: instead, add a new instruction to help out New instruction: lui register, immediate stands for Load Upper Immediate takes 16-bit immediate and puts these bits in the upper half (high order half) of the specified register sets lower half to 0s I-Format Problems (3/3) ● ● ● Solution to Problem 2 So how does lui help us? Example: addi $t0,$t0, 0xABABCDCD becomes: lui $at, 0xABAB ori $at, $at, 0xCDCD add $t0,$t0,$at ● ● Now each I-format instruction has only a 16-bit immediate. Wouldn’t it be nice if the assembler would this for us automatically? (later) Large Immediates H W New instruction: ● lui register, immediate Load Upper Immediate Takes 16-bit immediate and puts these bits in the upper half (high order half) of the specified register; lower half is set to 0s Example: ● ● ● ● ● Want to write: addi $t0,$t0, 0xABABCDCD Need to write a sequence instead: lui $at, 0xABAB ori $at, $at, 0xCDCD add $t0,$t0,$at 0 I-Format Problems (0/3) Problem 2: Unsigned ● # sign-extended? addiu, sltiu, sign-extends immediates to 32 bits. Thus, # is a “signed” integer. ● Rationale ● addiu so that can add without overflow sltiu suffers so that we can have simple HW ● ● ● ● Does this mean we’ll get wrong answers? No, it means assembler has to handle any unsigned immediate 215 ≤ n < 216 (I.e., with a 1 in the 15th bit and 0s in the upper 2 bytes) as it does for numbers that are too large. I-Format Example MIPS Instruction: addi $21,$22,-50 ● Encode for each field ● ● ● ● ● ● ● ● opcode = 8 (look up in table in book) Negative number rs = 22 (register containing operand) encoding: 2’s complement rt = 21 (target register) immediate = -50 (by default, this is decimal) Decimal number per field representation number per 8 Binary 22 21 field representation -5 0 Hexadecimal representation: 22D5 FFCEhex 001000 1010 584,449,998ten 1111111111001110 Decimal1011 representation: 0 1 0 ● ● ● ● lui (Load upper immediate) Instruction Mnemonic : lui rd, const ;where rd is a register, const is a 16-bit number Meaning : rd const*216 ; load constant in upper 16 bits of register Example : lui $s1, 100 ; $s1 100 * 216 0 32-bit Constants ● I-Type instructions can have only 16-bit constants ● What if we want to load a 32-bit constant into a register? Can’t have a 32-bit constant in I-Type instructions We have already fixed the sizes of all instructions to 32 bits ● ● ● ● ● Solution: use two instructions instead of one Suppose we want: $s1=0xAC5165D9 (32-bit constant) lui: load upper immediate 0 Examples: I-Type ALU Instructions • Examples: assume A, B, C are allocated $s0, $s1, $s2 • No need for subi, because addi has signed immediate • Register 0 ($zero) has always the value 0 0 Peer Instruction Which instruction has same representation as 35ten? 1. add $0, $0, $0 opcod r r r sham func 2. subu $s0,$s0,$s0 e s t d t t 3. lw $0, 0($0) opcod r r r sham func 4. addi $0, $0, 35 e s t d offse t t opcod r r 5. subu $0, $0, $0 e s t t 6. Trick question! opcod r r immediat e s opcod r Instructions are not numbers Registers numbers and names: e s t r t r d e sham t func t 0: $0, .. 8: $t0, 9:$t1, ..15: $t7, 16: $s0, 17: $s1, .. 23: $s7 Opcodes and function fields (if necessary) add: opcode = 0, funct = 32 subu: opcode = 0, funct = 35 addi: opcode = 8 lw: opcode = 35 0 Peer Instruction Answer Which instruction bit pattern = number 35? 1. add $0, $0, $0 0 0 0 0 0 32 2. subu $s0,$s0,$s0 0 16 16 16 0 35 35 0 0 0 8 0 0 35 0 0 0 3. lw $0, 0($0) 4. addi $0, $0, 35 5. subu $0, $0, $0 0 0 35 6. Trick question! Instructions != numbers Registers numbers and names: 0: $0, …, 8: $t0, 9:$t1, …,16: $s0, 17: $s1, …, Opcodes and function fields add: opcode = 0, function field = 32 subu: opcode = 0, function field = 35 addi: opcode = 8 lw: opcode = 35 2/23/20 96 Immediates in Conditional Branches Branch instructions bne and beq ● opcode ● ● ● rt immediate Field rs and rt specify registers to compare Field immediate specify branch address ● ● rs ● 16 bit is too small since we have 32-bit pointer to memory Observation Branches are used for if-else, while-loop, for-loop: tend to branch to a nearby instruction We only need to know the difference between the branch target and the current instruction address, which is much smaller and 16-bit addressing might suffice in most cases 0 J-Type Format J-type format is used for unconditional jump instruction: ● j label # jump to label ... ● ● label: 26-bit immediate value is specified in the instruction Immediate constant specifies address of target instruction 0 Unconditional Jump Instructions j (jump to target address) Instruction Mnemonic : j addr ;where addr is the label of the target address Meaning : jump to the target address location specified by the label addr in the instruction Example : j loop ; goto location having the label loop 0 ● ● ● ● ● ● ● ● ● ● ● J-Format Instructions (1/5) For general jumps (j and jal), we may jump to anywhere in memory. Ideally, we could specify a 32-bit memory address to jump to. Unfortunately, we can’t fit both a 6-bit opcode and a 32-bit address into a single 32-bit word, so we compromise. For branches, we assumed that we won’t want to branch too far, so we can specify change in PC. Branch Address Boundary Branch instructions use I-Type format (16-bit immediate constant) PC-relative addressing: Count number of instructions to branch from next instruction Positive constant => Forward Branch, Negative constant => Backward branch At most ± 215 instructions to branch (most branches are near) J-Format Instructions (2/5) J-format is used by MIPS jump instructions 6-bit opcode + 26-bit jump address ● ● 6 bits 26 bits • opcode • • • j and jal As usual, each field has a name: target address • Key Concepts Keep opcode field identical to R-format and I-format for consistency. Combine all other fields to make room for large target address. Goto statements and function calls tend to have larger offsets than branches and loops J-Format Instructions (3/5) For now, we can specify 26 bits of the 32-bit bit address. Optimization: Note that, just like with branches, jumps will only jump to word aligned addresses, so last two bits are always 00 (in binary). So let’s just take this for granted and not even specify them. J-Format Instructions (4/5) ● ● ● ● ● ● Now specify 28 bits of a 32-bit address . Where do we get the other 4 bits? By definition, take the 4 highest order bits from the PC. Technically, this means that we cannot jump to anywhere in memory, but it’s adequate 99.9999…% of the time, since programs aren’t that long only if straddle a 256 MB boundary (228) If we absolutely need to specify a 32-bit address, we can always put it in a register and use the jr instruction. J-Format Instructions (5/5) ● ● New PC = { PC[31 30 29 28], target address, 00 } Note: { , , } means concatenation ● ● { 4 bits , 26 bits , 2 bits } = 32 bit address { 1010 || 11111111111111111111111111 || 00 } = 10101111111111111111111111111100 MIPS Logical & Shift Operations Book Section: 2.6 0 Bitwise Operations Up until now, we’ve done arithmetic (add, sub,addi ), memory access (lw and sw), and branches and jumps. All of these instructions view contents of register as a single quantity (such as a signed or unsigned integer) New Perspective: View register as 32 raw bits rather than as a single 32-bit number Since registers are composed of 32 bits, we may want to access individual bits (or groups of bits) rather than the whole. Introduce two new classes of instructions: Logical and Shift Operations 0 ● ● ● ● ● Bitwise manipulation Useful for extracting and inserting groups of bits in a word MIPS Logical Operators are all bitwise, meaning that bit 0 of the output is produced by the respective bit 0’s of the inputs, bit 1 by the bit 1’s, etc. C: Bitwise AND is & (e.g., z = x & y;) C: Bitwise OR is | (e.g., z = x | y;) 0 Logical Operators ● Logical bitwise operations: and, or, xor, nor Truth Table: standard table listing all possible combinations of inputs and resultant output for each. E.g., and instruction is used to clear bits: x and 0 = 0 or instruction is used to set bits: x or 1 = 1 xor instruction is used to toggle bits: x xor 1 = not x nor instruction can be used as a not, how? nor $s1,$s2,$s2 is equivalent to not $s1,$s2 0 Logical Operators Logical instruction syntax: op dest, src1, src2 and $s0,$s1,$s2 ● Op: operation name (and, or, nor) Dest: register that will receive value Src1: first operand (register) Src2: second operand (register) or immediate ● ● ● ● Accept exactly 2 inputs and produce 1 output ● Benefit: rigid syntax simpler hardware Why nor? ● ● ● ● nor $t0, $t1, $t2 # $t0 = not ($t1 or $t2) and, or: Both of these expect the third argument to be a register 0 Examples: ● ● ● ● HW Assume $s1 = 0xabcd1234 , $s2 = 0xffff0000 and $s0,$s1,$s2 # $s0 = 0xabcd0000 or $s0,$s1,$s2 # $s0 = 0xffff1234 xor $s0,$s1,$s2 # $s0 = 0x54321234 nor $s0,$s1,$s2 # $s0 = 0x0000edcb S1 1010 1011 1100 1101 0001 0010 0011 0100 S2 1111 1111 1111 1111 0000 0000 0000 0000 and 1010 1011 1100 1101 0000 0000 0000 0000 OR 1111 1111 1111 1111 0001 0010 0011 0100 XOR 0101 0100 0011 0010 0001 0010 0011 0100 NOR 0000 0000 0000 0000 1110 1101 1100 1011 0 and (logical and) Instruction Mnemonic : and rd, rs, rt where rs, rt, rd are registers, Meaning : rd rs & rt Example : and $s1, $s2, $s3 ; $s1 $s2 & $s3 0 or (logical or) Instruction Mnemonic : or rd, rs, rt ;where rs, rt, rd are registers, Meaning : rd rs | rt Example : or $s1, $s2, $s3 ; $s1 $s2 | $s3 0 xor (logical Exclusive-or) Instruction Mnemonic : xor rd, rs, rt ;where rs, rt, rd are registers, Meaning : rd rs rt Example : xor $s1, $s2, $s3 ; $s1 $s2 $s3 0 nor (logical nor) Instruction Mnemonic : nor rd, rs, rt Meaning : rd rs nor rt Example : nor $t0, $t1, $t3 ;where rs, rt, rd are registers, ; $t0 $t1 nor $t3 0 Logical Operators Immediate operands andi rd, rs, const H W andi, ori: both expect the third argument to be an immediate (3) zero extension 0 andi (logical and immediate) Instruction Mnemonic : andi rd, rs, const ;where rs, rd are registers, const is a 16-bit constant Meaning : rd rs & const Example : andi $s1, $s2, 100 ; $s1 $s2 & 100 0 ori (logical or immediate) Instruction Mnemonic : ori rd, rs, const ; where rs, rd are registers, const is a 16-bit constant Meaning : rd rs | const Example : ori $s1, $s2, 100 ; $s1 $s2 | 100 0 xori (logical Exclusive-or immediate) ● ● ● Instruction Mnemonic : xori rd, rs, const ;where rs, rd are registers, const is a 16-bit value Meaning : rd rs const Example : xori $s1, $s2, 100 ; $s1 $s2 100 0 Uses for Logical Operators (1/3) ● ● Note that anding a bit with 0 produces a 0 at the output while anding a bit with 1 produces the original bit. This can be used to create a mask. Example: andi $t0,$t0,0xFFF 1011 0110 1010 0100 0011 1101 1001 1010 mask: 0000 0000 0000 0000 0000 1111 1111 1111 ● The result of anding these: 0000 0000 0000 0000 0000 1101 1001 1010 ● mask last 12 bits 0 ● ● ● Uses for Logical Operators (2/3) The second bitstring in the example is called a mask. It is used to isolate the rightmost 12 bits of the first bitstring by masking out the rest of the string (e.g. setting it to all 0s). Thus, the and operator can be used to set certain portions of a bitstring to 0s, while leaving the rest alone. In particular, if the first bitstring in the above example were in $t0, then the following instruction would mask it: andi $t0,$t0,0xFFF 0 Uses for Logical Operators (3/3) ● ● ● ● Similarly, note that oring a bit with 1 produces a 1 at the output while oring a bit with 0 produces the original bit. This can be used to force certain bits of a string to 1s. For example, if $t0 contains 0x12345678, then after this instruction: ori $t0, $t0, 0xFFFF … $t0 contains 0x1234FFFF (e.g. the highorder 16 bits are untouched, while the low-order 16 bits are forced to 1s). 0 Shift Operations • Shifting is to move all the bits in a register left or right • Shifts by a constant amount: sll, srl, sra – sll/srl mean shift left/right logical by a constant amount – The 5-bit shift amount field is used by these instructions – sra means shift right arithmetic by a constant amount – The sign-bit (rather than 0) is shifted from the left 0 Binary Multiplication • Shift-left (sll) instruction can perform multiplication – When the multiplier is a power of 2 • You can factor any binary number into powers of 2 – Example: multiply $s1 by 36 • Factor 36 into (4 + 32) and use distributive property of multiplication – $s2 = $s1*36 = $s1*(4 + 32) = $s1*4 + $s1*32 0 Binary Multiplication Multiply $s1 by 26, using shift and add instructions ● Hint: 26 = 2 + 8 + 16 ● Multiply $s1 by 31, Hint: 31 = 32 – 1 0 ● ● ● ● ● ● ● ● ● Logical Shift Instructions (1/4) Shift instruction syntax: op dest,reg,amt Op: operation name Dest: register that will receive value Reg: register with the value to be shifted Amt: shift amount (constant < 32) MIPS logical shift instructions: sll (shift left logical): shifts left and fills emptied bits with 0s srl (shift right logical): shifts right and fills emptied bits with 0s MIPS also has arithmetic shift instructions that fills with the sign bit 0 ● ● ● Shift Instructions (2/4) Shift Instruction Syntax: 1 2,3,4 where 1) operation name 2) register that will receive value 3) first operand (register) 4) shift amount (constant < 32) MIPS shift instructions: 1. sll (shift left logical): shifts left and fills emptied bits with 0s 2. srl (shift right logical): shifts right and fills emptied bits with 0s 3. sra (shift right arithmetic): shifts right and fills emptied bits by sign extending 0 Two Logic Instructions ● Shift Left: sll $s1,$s2,2 #s1=s2<<2 ● Store in $s1 the value from $s2 shifted 2 bits to the left, inserting 0’s on right; << in C Before: 0000 0002hex 0000 0000 0000 0000 0000 0000 0000 0010two After: 0000 0008hex 0000 0000 0000 0000 0000 0000 0000 1000two What arithmetic effect does shift left have? ● ● ● ● Shift Right: srl is opposite shift; >> 0 Shift Instructions (3/4) ● Example 1: sra shift right arithmetic by 8 bits (note sign extend) 0001 0010 0011 0100 0101 0110 0111 1000 0000 0000 0001 0010 0011 0100 0101 0110 • Example 2: shift right arithmetic by 8 bits (note sign extend) 1001 0010 0011 0100 0101 0110 0111 1000 1111 1111 1001 0010 0011 0100 0101 0110 0 ● ● ● Shift Instructions (4/4) Since shifting may be faster than multiplication, a good compiler usually notices when C code multiplies by a power of 2 and compiles it to a shift instruction: a *= 8; (in C) would compile to: sll $s0,$s0,3 (in MIPS) # would multiply contents of $s0 by 8 Likewise, shift right to divide by powers of 2 remember to use sra 0 sll (shift left logical ) Instruction Mnemonic : ● sll rd, rs, const count) W ;where rs, rd are registers, const is a 5-bit constant (shift Meaning : ● rd ● H rs << const ; logical shift left rs by const bits Example : sll $s1, $s2, 10 ; $s1 $s2 << 10 0 srl (shift right logical ) ● ● ● Instruction Mnemonic : srl rd, rs, const ;where rs, rd are registers, const is a 5-bit constant (shift count) Meaning : rd rs >> const ; logical shift right rs by const bits Example : srl $s1, $s2, 10 ; $s1 $s2 >> 10 0 sra (shift right arithmetic ) ● ● ● Instruction Mnemonic : sra rd, rs, const ;where rs, rd are registers, const is a 5bit constant (shift count) Meaning : rd rs >> const ; arithmetic shift right rs by const bits Example : sra $s1, $s2, 10 ; $s1 $s2 >> 10 0 Shift Instructions • Shifts by a variable amount: sllv, srlv, srav – Same as sll, srl, sra, but a register is used for shift amount 0 sllv (shift left logical variable ) Instruction Mnemonic : sllv rd, rs, rt ;where rs, rt, rd are registers, rt contains the shift count Meaning : rd rs << rt ; logical shift left rs by rt bits Example : sllv $s1, $s2, $s3 ; $s1 $s2 << $s3 0 srlv (shift right logical variable) Instruction Mnemonic : srlv rd, rs, rt ;where rs, rt, rd are registers, rt contains the shift count Meaning : rd rs >> rt ; logical shift right rs by rt bits Example : srlv $s1, $s2, $s3 ; $s1 $s2 >> $s3 0 srav (shift right arithmetic variable ) Instruction Mnemonic : srav rd, rs, rt ;where rs, rt, rd are registers, rt contains the shift count Meaning : rd rs >> rt ; arithmetic shift right rs by rt bits Example : srav $s1, $s2, $s3 ; $s1 $s2 >> $s3 0 0 0 MIPS Control Instructions Book Section: 2.7 0 ● ● ● ● ● ● ● ● So Far... All instructions so far only manipulate data…we’ve built a calculator. In order to build a computer, we need ability to make decisions… C (and MIPS) provide labels to support “goto” jumps to places in code. Decision allows us to decide what to execute at run time rather than compile time C decisions are made using conditional statements within If ,While , Do while, For MIPS decisions making instructions are the conditional branches beq and bne and j lable In order to help conditional branches, make decisions concerning inequalities, we introduce slt, slti, sltu,sltui 0 C Decisions: if Statements ● ● ● ● ● 2 kinds of if statements in C if (condition) clause if (condition) clause1 else clause2 Rearrange 2nd if into following: if (condition) goto L1; clause2; goto L2; L1: clause1; L2: Not as elegant as if-else, but same meaning 0 MIPS Decision Instructions ● ● ● ● Decision instructions in MIPS causes control to branch to another place Called conditional branches (Branch if a condition is met) beq register1, register2, L1 beq is “branch if equal” same meaning as: if (register1==register2) goto L1 bne register1, register2, L1 bne is “branch if not equal” same meaning as: if (register1!=register2) goto L1 Can be used to implement complex control-flow constructs for high level languages 0 MIPS Goto Instruction ● In addition to conditional branches, MIPS has an unconditional branch: j ● ● ● label Called a Jump Instruction: jump (or branch) directly to the given label without needing to satisfy any condition Same meaning as (using C): goto label Technically, it’s the same as: beq $0,$0,label since it always satisfies the condition. 0 beq (branch on equal) MIPS compare and branch instructions: beq Rs,Rt,label branch to label if (Rs == Rt) bne Rs,Rt,label branch to label if (Rs != Rt) ● ● ● Instruction Mnemonic : beq rd, rs, addr ;where rs, rd are registers, addr is the label of the target location Meaning : if (rd == rs ) then branch to label i.e., goto PC + 4 + const*4 (i.e., PC = Updated PC + offset) Example : beq $s1, $s2, up ; if ($s1 = $s2) goto target location up 0 bne (branch on not equal ) ● ● ● Instruction Mnemonic : bne rd, rs, addr ;where rs, rd are registers, addr is the label of the target location Meaning : if (rd != rs ) then branch to label i.e., goto PC + 4 + const*4 (i.e., PC = Updated PC + offset) Example : bne $s1, $s2, loop ; if ($s1 != $s2) goto target location loop 0 ● Compiling C if into MIPS C code if (i == j) f=g+h; else f=g-h; Use mapping: f: $s0, g: $s1, h: $s2, i: $s3, j: $s4 Final compiled MIPS code: (true) i == j f=g+h H W (false) i == j? i != j f=g-h Exit beq $s3,$s4,True # branch i==j is It III big sub $s0,$s1,$s2 # f=g-h(false) j Exit # goto Exit True: add $s0,$s1,$s2 # f=g+h (true) Exit: Note: Compiler automatically creates labels to handle decisions (branches) Generally not found in HLL code. 0 Loops in C/Assembly (1/3) There are three types of loops in C: while do… while for Each can be rewritten as either of the other two, so the method used in the previous example can be applied to while and for loops as well. Key Concept: Though there are multiple ways of writing a loop in MIPS, the key to decision making is conditional branch 0 Loops in C/Assembly (2/3) Simple loop in C; A[] is an array of ints do { g = g + A[i]; j; } while (i != h); Rewrite this as: Loop: g = g + A[i]; i = i + j; if (i != h) goto Loop; i=i+ 0 ● ● ● Loops in C/Assembly (3/3) Use this mapping: g, h, i, j, base of A $s1, $s2, $s3, $s4, $s5 Original code: Loop: g = g + A[i]; i = i + j; if (i != h) goto Loop; Final compiled MIPS code: Loop: sll $t1,$s3,2 # $t1= 4*i add $t1,$t1,$s5 # $t1=addr A lw $t1,0($t1) # $t1=A[i] add $s1,$s1,$t1 # g=g+A[i] add $s3,$s3,$s4 # i=i+j bne $s3,$s2,Loop # goto Loop # if i!=h 0 Compound Expression with AND ● Programming languages use short-circuit evaluation ● If first expression is false, second expression is skipped 0 Better Implementation for AND The following implementation uses less code Reverse the relational operator Allow the program to fall through to the second expression Number of instructions is reduced from 5 to 3 0 Compound Expression with OR Short-circuit evaluation for logical OR If first expression is true, second expression is skipped Use fall-through to keep the code as short as possible bgt, ble are pseudo-instructions that are translated by the assembler to real instructions 0 ● ● Translating a WHILE Loop Consider the following WHILE statement: i = 0 ; while (A[i] != k) i = i+1; Where A is an array of integers (4 bytes per element) Assume address A, i, k in $s0, $s1, $s2, respectively How to translate above WHILE statement? xor $s1, $s1, $s1 # i = 0 or $t0, $s0, $0 # $t0 = address A loop: lw $t1, 0($t0) # $t1 = A[i] beq $t1, $s2, exit # exit if (A[i]== k) addiu $s1, $s1, 1 # i = i+1 sll $t0, $s1, 2 # $t0 = 4*i addu $t0, $s0, $t0 # $t0 = address A[i] j loop exit: . . . 0 Using Pointers to Traverse Arrays ● ● ● Consider the same WHILE loop: i = 0; while (A[i] != k) i = i+1; Where address of A, i, k are in $s0, $s1, $s2, respectively We can use a pointer to traverse array A Pointer is incremented by 4 (faster than indexing) or $t0, $s0, $0 # $t0 = $s0 = addr A j cond # test condition loop: addiu $s1, $s1, 1 # i = i+1 addiu $t0, $t0, 4 # point to next cond: lw $t1, 0($t0) # $t1 = A[i] bne $t1, $s2, loop # loop if A[i]!= k Only 4 instructions (rather than 6) in loop body 0 Copying a String The following code copies source string to target string Address of source in $s0 and address of target in $s1 Strings are terminated with a null character (C strings) 0 Summing an Integer Array ● Assume $s0 = array address, $s1 = array length = n 0 Inequalities in MIPS 0 Inequalities in MIPS (3/3) Now, we can implement <, but how do we implement >, ≤ and ≥ ? We could add 3 more instructions, but: MIPS goal: Simpler is Better Can we implement ≤ in one or more instructions using just slt and the branches? What about >? What about ≥? 0 Inequalities in MIPS (1/3) Create a MIPS Inequality Instruction: “Set on Less Than” Syntax: slt reg1,reg2,reg3 Meaning: reg1 = (reg2 < reg3); if (reg2 < reg3) reg1 = 1; else reg1 = 0; Same thing… In computers, “set” means “set to 1”, “reset” means “set to 0”. 0 Inequalities in MIPS (2/3) ● How do we use this? Compile by hand: if (g < h) goto Less; ● #g:$s0, h:$s1 Answer: compiled MIPS code… slt $t0,$s0,$s1 # $t0 = 1 if g<h bne $t0,$0,Less # goto Less # if $t0!=0 # (if (g<h)) Less: ● Branch if $t0 != 0 ● Register $0 always contains the value 0, so bne and beq often use it for comparison after an slt instruction. ● A slt (g < h) bne pair means if(… < …)goto… 0 Compare : Set on Less Than Instructions ● MIPS provides set on less than instructions slt rd,rs,rt if (rs < rt) rd = 1 else rd = 0 sltu rd,rs,rt unsigned < slti rt,rs, , imm16 if (rs < im16) rt = 1 else rt = 0 sltiu rt,rs, , imm16 unsigned < 0 Immediates in Inequalities ● ● C M I P S There is also an immediate version of ( set less than) slt to test against constants: slti ( set less than immediate) Helpful in for loops if (g >= 1) goto Loop Loop: . . . slti $t0,$s0,1 beq # $t0 = 1 if # $s0<1 (g<1) $t0,$0,Loop # goto Loop # if $t0==0 # (if (g>=1)) An slt beq pair means if(… ≥ …)goto… 0 branch less than greater than or equal ● ● ● ● ● ● ● ● ● ● ● ● There is no blt instead use slt $s1, $s3, $s8 bne $s1, $s0, L ble (branch if less than or equal) slt $s1, $s8, $s5 beq $s1, $s0, L bgt ( branch if greater than) slt $s1, $s8, $s5 bne $s1, $s0, L bge branch if greater than or equal slt $s1, $s3, $s8 beq $s1, $s0, L 0 What about unsigned numbers? ● ● Also unsigned inequality instructions: sltu, sltiu …which sets result to 1 or 0 depending on unsigned comparisons What is value of $t0, $t1? ($s0 = FFFF FFFAhex, $s1 = 0000 FFFAhex) slt $t0, $s0, $s1 sign sltu $t1, $s0, $s1 unsign J If Bl 0 MIPS Signed vs. Unsigned – diff meanings! ● ● ● ● MIPS Signed v. Unsigned is an “overloaded” term Do/Don't sign extend (lb, lbu) Don't overflow (addu, addiu, subu, multu, divu) Do signed/unsigned compare (slt, slti/sltu, sltiu) 0 slt (set less than) ● ● ● Instruction Mnemonic : slt rd, rs, rt ;where rs, rt, rd are registers, Meaning : if (rs < rt ) then rd = 1 else rd = 0 Example : slt $s1, $s2, $s3 ; if ($s2 < $s3) then $s1=1 else $s1=0 0 ● ● ● slti (set less than immediate) Instruction Mnemonic : slti rd, rs, const ;where rs, rd are registers, const is a 16-bit constant Meaning : if (rs < const ) then rd = 1 else rd = 0 Example : slti $s1, $s2, 100 ; if ($s2 < 100) then $s1=1 else $s1=0 0 Comparison Instructions sltu (set less than unsigned) Instruction Mnemonic : sltu rd, rs, rt ;where rs, rt, rd are registers, Meaning : if (rs < rt ) then rd = 1 else rd = 0 Example : sltu $s1, $s2, $s3 ; if ($s2 < $s3) then $s1=1 else $s1=0 0 sltiu (set less than immediate unsigned) ● ● ● Instruction Mnemonic : sltiu rd, rs, const ;where rs, rd are registers, const is a 16-bit constant Meaning : if (rs < const ) then rd = 1 else rd = 0 Example : sltiu $s1, $s2, 100 ; if ($s2 < 100) then $s1=1 else $s1=0 0 ● Signed / Unsigned Comparisons can produce different results Assume $s0 = 1 and $s1 = -1 = 0xffffffff slt $t0,$s0,$s1 results in $t0 = 0 stlu $t0,$s0,$s1 results in $t0 = 1 0 SLT Instructions 0 Conditional Branch Instructions ● ● MIPS compare to zero & branch instructions Compare to zero is used frequently and implemented efficiently bltz Rs,label branch to label if (Rs < 0) bgtz Rs,label branch to label if (Rs > 0) blez Rs,label branch to label if (Rs <= 0) bgez Rs,label branch to label if (Rs >= 0) No need for beqz and bnez instructions. 0 bgtz (branch on greater than zero) ● Instruction Mnemonic : bgtz rd, addr ;where rd is a register, addr is the label of the target location ● Meaning : if (rd > 0 ) then branch to label i.e., goto PC + 4 + const*4 (i.e., PC = Updated PC + offset) Example : bgtz $s1, up ; if ($s1 > 0) goto target location up ● 0 bltz (branch on less than zero) ● ● ● Instruction Mnemonic : bltz rd, addr ;where rd is a register, addr is the label of the target location Meaning : if (rd < 0 ) branch to label i.e., goto PC + 4 + const*4 (i.e., PC = Updated PC + offset) Example : bltz $s1, up ; if ($s1 < 0) goto target location up 0 blez (branch on less than or equal to zero) ● ● ● Instruction Mnemonic : blez rd, addr ; where rd is a register, addr is the label of the target location Meaning : if (rd <= 0 ) branch to label i.e., goto PC + 4 + const*4 (i.e., PC = Updated PC + offset) Example : blez $s1, loop ; if ($s1 <= 0) goto target location loop 0 bgez (branch on greater than or equal to zero) ● ● ● Instruction Mnemonic : bgez rd, addr ;where rd is a register, addr is the label of the target location Meaning : if (rd >= 0 ) then branch to label i.e., goto PC + 4 + const*4 (i.e., PC = Updated PC + offset) Example : bgez $s1, loop ; if ($s1 >= 0) goto target location loop 0 Branch Instructions 0 Branch Instructions MIPS hardware does NOT provide instructions for … blt, bltu branch if less than (signed/unsigned) ble, bleu branch if less or equal (signed/unsigned) bgt, bgtu branch if greater than (signed/unsigned) bge, bgeu branch if greater or equal (signed/unsigned) Can be achieved with a sequence of 2 instructions • How to implement: blt $s0,$s1,label • Solution: slt $at,$s0,$s1 bne $at,$zero,label • How to implement: ble $s2,$s3,label • Solution: slt $at,$s3,$s2 beq $at,$zero,lab 0 The C Switch Statement 220 179 c bliss 0 MIPS Addressing Modes ● Book Section 2.10 0 MIPS Addressing Modes Register addressing (R-Type) Where Operand is stored in a register Base or displacement addressing (I-Type) Where Operand at the memory location specified by a register value plus a displacement given in the instruction; Eg: lw, $t0, 25($s0) Immediate addressing (I-Type) Where Operand is a constant within the instruction itself PC-relative addressing (I-Type) Where The address is the sum of the PC and a constant in the instruction Pseudo-direct addressing (J-type) Where the jump address is the 26 bits of the instruction concatenated with the upper bits of the PC New PC = {(upper 4 bits of PC+4), 26-bit constant, 00} 0 ● ● ● ● Register addressing Source operands is in registers (R- type) Since both data and instruction line in memory, they are accessed by memory address However, address space of 32 bit MIPS is too large to address as immediate instruction format So access to data and instruction is through several addressing modes 0 Base Displacement create memory address by adding a constant to a register value (Itype) lw $s0, n($s1) Offset here we do not need more than 16 bits immediate. 0 Branches: PC-Relative Addressing ● Use I-Format opcode • rs rt opcode specifies beq , bne: immediat e beq $t2,$0,exit bne $s3,$s2,Loop • rs and rt specify registers to compare • What can immediate specify? • Immediate is only 16 bits • PC (Program Counter) has byte address of current instruction being executed; 32-bit pointer to memory • So immediate cannot specify entire address to branch to. How do we usually use branches? Answer: if-else, while, for Loops are generally small: typically up to 50 instructions Function calls and unconditional jumps are done using jump instructions (j and jal), not the branches. Conclusion: may want to branch to anywhere in memory, but a branch often changes PC by a small amount ● ● ● ● ● ● ● Branches: PC-Relative Addressing Solution to branches in a 32-bit instruction: PC-Relative Addressing Let the 16-bit immediate field be a signed two’s complement integer to be added to the PC if we take the branch. Now we can branch ± 215 bytes from the PC, which should be enough to cover almost any loop. Note: Instructions are words, so they’re word aligned (byte address is always a multiple of 4, which means it ends with 00 in binary). So the number of bytes to add to the PC will always be a multiple of 4. So specify the immediate in words. Now, we can branch ± 215 words from the PC (or ± 217 bytes), so we can handle loops 4 times as large. Branches: PC-Relative Addressing ● ● ● ● ● ● Branch Calculation: If we don’t take the branch: PC = PC + 4 PC+4 = byte address of next instruction If we do take the branch: PC = (PC + 4) + (immediate * 4) Observations Immediate field specifies the number of words to jump, which is simply the number of instructions to jump. Immediate field can be positive or negative. Pseudo-direct addressing (J-type) Pseudo-direct addressing (J-type) Where the jump address is the 26 bits of the instruction concatenated with the upper bits of the PC New PC = {(upper 4 bits of PC+4), 26-bit constant, 00} 0 Branch Example (1/3) MIPS Code: Loop: beq $9,$0,End add $8,$8,$10 addi $9,$9,-1 j Loop End: beq branch is I-Format: opcode = 4 (look up in table) rs = 9 (first operand) rt = 0 (second operand) immediate = ??? ● ● ● ● Branch Example (2/3) MIPS Code: Loop: beq $9,$0,End addi $8,$8,$10 addi $9,$9,-1 j Loop End: Immediate Field: Number of instructions to add to (or subtract from) the PC, starting at the instruction following the branch. In beq case, immediate = 3 Branch Example (3/3) ● MIPS Code: Loop: beq addi addi j $9,$0,End $8,$8,$10 $9,$9,-1 Loop End: decimal representation: 4 9 000100 0100 1 0 0000 0 3 binary representation: 0000000000000011 ● Compiling C if into MIPS C code if (i == j) f=g+h; else f=g-h; Use mapping: f: $s0, g: $s1, h: $s2, i: $s3, j: $s4 Final compiled MIPS code: (true) i == j f=g+h (false) i == j? i != j f=g-h Exit beq $s3,$s4,True # branch i==j sub $s0,$s1,$s2 # f=g-h(false) j Fin # goto Fin True: add $s0,$s1,$s2 # f=g+h (true) Fin: Note: Compiler automatically creates labels to handle decisions (branches) Generally not found in HLL code. 0 Loops in C/Assembly (1/3) There are three types of loops in C: while do… while for Each can be rewritten as either of the other two, so the method used in the previous example can be applied to while and for loops as well. Key Concept: Though there are multiple ways of writing a loop in MIPS, the key to decision making is conditional branch 0 Loops in C/Assembly (2/3) Simple loop in C; A[] is an array of integers do { g = g + A[i]; j; } while (i != h); Rewrite this as: Loop: g = g + A[i]; i = i + j; if (i != h) goto Loop; i=i+ 0 ● ● ● Loops in C/Assembly (3/3) Use this mapping: g, h, i, j, base of A $s1, $s2, $s3, $s4, $s5 Original code: Loop: g = g + A[i]; i = i + j; if (i != h) goto Loop; Final compiled MIPS code: Loop: sll $t1,$s3,2 # $t1= 4*i add $t1,$t1,$s5 # $t1=addr A lw $t1,0($t1) # $t1=A[i] add $s1,$s1,$t1 # g=g+A[i] add $s3,$s3,$s4 # i=i+j bne $s3,$s2,Loop # goto Loop # if i!=h 0 New MIPS Code Page 131 start s ● Instruction Format 15110 of Emi 33 I 26301 dong u bit egg 89 Id'd I 1s Is I If tf 0 Name Fields Comments Field size 6 bits 5 bits 5 bits 5 bits 5 bits 6 bits All MIPS instructions 32 bits R-format op rs rt rd shamt funct Arithmetic instruction format I-format op rs rt address/immediate J-format op target address Transfer, branch, imm. format Jump instruction format t.GS J 0 Decoding Machine Language ● Book page 134 0 Decoding Machine Language How do we convert 1s and 0s to C code? Machine language Assembly language C? For each 32 bits: Look at opcode: 0 means R-Format, 2 or 3 mean J-Format, otherwise IFormat Use instruction type to determine which fields exist Write out MIPS assembly code, converting each field to name, register number/name, or decimal/hex number Logically convert this MIPS code into valid C code ● ● ● ● ● ● ● R I J 0 1, 4-31 2 or 3 rs rt rs rt rd shamt funct immediate target address 0 ● ● ● Decoding Example (1/5) Here are six machine language instructions in hexadecimal: 00001025hex 0005402Ahex 11000003hex 00441020hex 20A5FFFFhex 08100001hex Let the first instruction be at address 4,194,304ten (0x00400000hex) Next step: convert hex to binary 0 Decoding Example (2/5) The six machine language instructions in binary: ● 00000000000000000001000000100101 00000000000001010100000000101010 00010001000000000000000000000011 00000000010001000001000000100000 00100000101001011111111111111111 00001000000100000000000000000001 R R I R I J Next step: identify opcode and format ● R I J 0 1, 4-31 2 or 3 rs rt rs rt rd shamt funct immediate target address 0 Decoding Example (3/5) Next: fields separated based on format / opcode: R R I R I J 0 0 0 2 0 0 0 5 8 0 4 8 0 0 2 4 2 + 3 0 8 5 5 2 1,048,577 1 3 7 4 2 3 2 Next step: translate (disassemble) to MIPS instructions 0 Decoding Example (4/5) MIPS assembly (Part 1): Address Assembly instructions 0x00400000 or $2,$0,$0 0x00400004 slt $8,$0,$5 0x00400008 beq $8,$0,3 0x0040000c add $2,$2,$4 0x00400010 addi $5,$5,-1 0x00400014 j 0x100001 loop What Better solution: translate to more meaningful MIPS instruction (fix the branch/jump, add labels and register names) 0 Decoding Example (5/5) ● ● MIPS Assembly (Part 2): or $v0,$0,$0 Loop: slt $t0,$0,$a1 beq $t0,$0,Exit $v0,$v0,$a0 $a1,$a1,-1 addi j add Loop Exit: Next step: translate to C code (be creative!) product = 0; while (multiplier > 0) { $v0: product product += multiplicand; $a0: multiplicand multiplier -= 1; $a1: multiplier } 0 ● ● ● Revisit: lui Example of lui addi $t0,$t0, 0xABABCDCD lui ori add $at, 0xABAB $at, $at, 0xCDCD $t0,$t0,$at Wouldn’t it be nice if the translation can be done automatically? If number too big, then just automatically replace addi with a sequence of lui, ori, add 0 Pseudoinstructions pseudoinstruction A MIPS instruction that doesn’t turn directly into a machine language instruction, but into other MIPS instructions Previous example: addi with a large immediate is considered as a pseudoinstruction The compiler / assembly programmer can write code with pseudoinstructions Assembler is responsible to break one pseudoinstruction into several “real” MIPS instructions (Instructions implemented by hardware) This makes assembly programming much easier 0 Pseudo-instruction If ● Instructions to simplify task ● Not implemented in Hardware Understandable by the assembler Convertible by the assembler into the machine language equivalent ● ● if I 0 ● ● ● ● ● ● ● ● ● ● ● Example Pseudoinstructions Register move Format: move reg2,reg1 Equivalent to: add reg2,$zero,reg1 Load immediate Format: li reg,value If value fits in 16 bits: addi reg,$zero,value Otherwise: lui reg, upper 16 bits of value ori reg,$zero,lower 16 bits Easy addition addu reg,reg,value # should be addiu If value fits in 16 bits: addiu reg,reg,value Otherwise: lui $at,upper 16 bits of value ori $at,$at,lower 16 bits addu reg,reg,$at 0 Pseudoinstruction Translation Problem: When breaking up a pseudoinstruction, the assembler may need to use an extra register If it uses any regular register, it’ll overwrite whatever the program has put into it Solution: Reserve a register ($1, called $at for “assembler temporary”) that assembler will use to break up pseudo-instructions Since the assembler may use this at any time, it’s not safe to code with it 0 0 Questions? 0