Lecture 4 section 2.4-?? MIPS Reference Data Class Participation 1. a. The following is a MIPS ML instruction: 00000010001100100100000000100000 What AL does it represent? (Use the green sheet to decode it). add $t0, $s1, $s2 b. The following is a MIPS AL instruction: add $t0, $s1, $s2 What is the ML MIPS equivalent? 00000010001100100100000000100000 Machine Language - Arithmetic Instruction Instructions, like registers and words of data, are also 32 bits long Example: registers have numbers add $t0, $s1, $s2 $t0=$8, $s1=$17, $s2=$18 Instruction Format: op rs 000000 10001 rt rd 10010 01000 shamt 00000 funct 100000 Do you know what the field names stand for? MIPS Instruction Fields op rs rt rd shamt 6 bits 5 bits 5 bits 5 bits 5 bits funct 6 bits = 32 bits op opcode indicating operation to be performed rs address of the first register source operand rt address of the second register source operand rd the register destination address shamt shift amount (for shift instructions) funct function code that selects the specific variant of the operation specified in the opcode field Machine Language - Load Instruction Consider the load-word and store-word instructions, Introduce a new type of instruction format What would the regularity principle have us do? New principle: Good design demands a compromise I-type for data transfer instructions previous format was R-type for register Example: lw $t0, 24($s2) op rs 35 18 100011 10010 rt 16 bit number 8 01000 24 0000000000011000 Where's the compromise? Memory Address Location Example: lw $t0, 24($s2) Memory 0xf f f f f f f f 2410 + $s2 = 0x00000002 . . . 1001 0100 + . . . 0001 1000 . . . 1010 1100 = 0x120040ac 0x12004094 $s2 Note that the offset can be positive or negative data 0x0000000c 0x00000008 0x00000004 0x00000000 word address (hex) Machine Language - Store Instruction Example: sw $t0, 24($s2) op rs 43 18 101011 10010 rt 16 bit number 8 01000 24 0000000000011000 A 16-bit address means access is limited to memory locations within a region of 213 or 8,192 words (215 or 32,768 bytes) of the address in the base register $s2 Assembling Code Remember the assembler code we compiled for the C statement A[8] = A[2] - b lw sub sw $t0, 8($s3) $t0, $t0, $s2 $t0, 32($s3) #load A[2] into $t0 #subtract b from A[2] #store result in A[8] Assemble the MIPS code for these three instructions lw 35 19 8 sub 0 8 18 sw 43 19 8 8 8 0 32 34 Review: MIPS Data Types Bit: 0, 1 Bit String: sequence of bits of a particular length 4 bits is a nibble 8 bits is a byte 16 bits is a half-word 32 bits is a word 64 bits is a double-word Character: ASCII 7 bit code Decimal: digits 0-9 encoded as 0000b thru 1001b two decimal digits packed per 8 bit byte Integers: 2's complement Floating Point Beyond Numbers Most computers use 8-bit bytes to represent characters with the American Std Code for Info Interchange (ASCII) ASCII Char ASCII Char ASCII Char ASCII Char ASCII Char ASCII Char 0 Null 32 space 48 0 64 @ 96 ` 112 p 1 33 ! 49 1 65 A 97 a 113 q 2 34 “ 50 2 66 B 98 b 114 r 3 35 # 51 3 67 C 99 c 115 s 36 $ 52 4 68 D 100 d 116 t 37 % 53 5 69 E 101 e 117 u 38 & 54 6 70 F 102 f 118 v 39 ‘ 55 7 71 G 103 g 119 w 4 EOT 5 6 ACK 7 8 bksp 40 ( 56 8 72 H 104 h 120 x 9 tab 41 ) 57 9 73 I 105 i 121 y 10 LF 42 * 58 : 74 J 106 j 122 z 43 + 59 ; 75 K 107 k 123 { 44 , 60 < 76 L 108 l 124 | 47 / 63 ? 79 O 111 o 127 DEL 11 12 15 FF So, we need instructions to move bytes around Loading and Storing Bytes MIPS provides special instructions to move bytes I lb $t0, 1($s3) #load byte from memory sb $t0, 6($s3) #store byte to op rs rt memory 16 bit number What 8 bits get loaded and stored? load byte places the byte from memory in the rightmost 8 bits of the destination register what happens to the other bits in the register? store byte takes the byte from the rightmost 8 bits of a register and writes it to a byte in memory MIPS Reference Data lb – load byte – loads a byte from memory, placing it in the rightmost 8 bits of a register. sb – store byte – takes a byte from the rightmost 8 bits of a register and writes it to memory Example of Loading and Storing Bytes Given following code sequence and memory state (contents are given in hexadecimal), what is the state of the memory after executing the code? add $s3, $zero, $zero lb $t0, 1($s3) #lbu $t0, 1($s0)gives sb $t0, 6($s3) #$t0 = 0x00000090 mem(4) = 0xFFFF90FF Memory 00000000 24 00000000 20 00000000 16 10000010 12 01000402 8 FFFFFFFF 4 009012A0 0 Data Questions 2 : What value is left in $t0? $t0 = 0xFFFFFF90 Questions 3: What if the machine was little Endian? Word Address (Decimal) mem(4) = 0xFF12FFFF $t0 = 0x00000012 Review: MIPS Instructions, so far Category Arithmetic (R format) Instr Op Code Example Meaning add 0 and 32 add $s1, $s2, $s3 $s1 = $s2 + $s3 subtract 0 and 34 sub $s1, $s2, $s3 $s1 = $s2 - $s3 Data load word 35 lw $s1, 100($s2) $s1 = Memory($s2+100) transfer store word 43 sw $s1, 100($s2) Memory($s2+100) = $s1 (I format) load byte 32 lb $s1, 101($s2) $s1 = Memory($s2+101) store byte 40 sb $s1, 101($s2) Memory($s2+101) = $s1 Review: MIPS R3000 ISA Instruction Categories Registers Load/Store Computational Jump and Branch Floating Point R0 - R31 coprocessor PC HI Memory Management Special LO 3 Instruction Formats: all 32 bits wide 6 bits 5 bits 5 bits 5 bits rd OP rs rt OP rs rt OP 5 bits shamt 16 bit number 26 bit jump target 6 bits funct R format I format J format Register Instructions ° Assume: g, h, i, j are stored in registers $s1 - $s4. Result f to be stored in $s0. ° Compile: f = (g + h) – (i + j) into MIPS instructions: add $t0, $s1, $s2 # register $t0 (g+h) add $t1, $s3, $s4 # $t1 (i + j) sub $s0, $t0, $t1 # $s0 $t0 - $t1 R-type OP rs rt rd shft funct Immediate format ° Immediate = small constant stored in the instruction addi $sp, $sp, const I-type 6 OP 5 rs 5 rt # $sp $sp + const 16 const ° Range of constant operand: -215 ≤ const 215-1 ° Set on less-then, immediate slti $t0, $s2, const ° # $t0 1 if $s2 < const ; 0 otherwise Operand in memory ° Let A[ ] = array whose starting (base) address is in $s3; let variable h be associated with register $s2; ° Compile: A[5] = h + A[8] 8*4 = 32 bytes (byte-addressable) into MIPS instructions: lw $t0, 32 ($s3) # $t0 A[8] add $t0, $s2, $t0 # $t0 h+$t0 sw $t0, 20 ($s3) # A[5] $t0 $s3 5*4 = 20 I-type OP rs rt immediate 8 7 6 5 4 3 2 1 Array with variable index ° A[ ] = array with base address in $s3; variables g, h, i associated with registers $s1, $s2, $s4 ° Compile: g = h + A[i] into MIPS instructions: add $t1, $s4, $s4 # $t1 i+i = 2i add $t1, $t1, $t1 # $t1 2i+2i = 4i add $t1, $t1, $s3 lw $t0, 0 ($t1) add $s1, $s2, $t0 # $t1 address of A[i] # $t0 A[i] # $s1 h + A[i] If statements ° Let variables f, g, h, i, j be associated with $s0 - $s4 ° Compile: if (i == j) go to L1; f = g + h; L1: f = f – i; into MIPS instructions: Does the following code work? L1: beq $s3, $s4, L1 # if i = j, go to L1 add $s0, $s1, $s2 sub $s0, $s0, $s3 # f = g + h (skipped if i=j) # f = f – i (always executed) Jump instructions ° Regular jump uses J-format j Label J-type # jump to Label 26 Label = jump target OP ° (the above label is not quite this simple) ° jr (jump on register address) uses R-format jr $t1 R-type OP # jump to address given in $t1 rs 0 0 OP/funct = jr 0 funct If then else statements ° Let variables f, g, h, i, j be associated with $s0 - $s4 ° Compile: if (i == j) f = g + h; else f = g –h; into MIPS instructions: bne $s3, $s4, Else add $s0, $s1, $s2 j Exit Else: sub $s0, $s1, $s2 Exit: J-type OP # if i j, go to Else # f = g + h (skipped if i j) # go to Exit # f = g – h (skipped if i = j) jump target Pseudo-instructions ° Let variables a, b be associated with $s0, $s1 ° Compile: if (a < b) go to L into MIPS instructions: slt $t0, $s0, $s1 bne $t0, $zero, L # $t0 1 if $s0 < $s1 (a < b) # if $t0 0, go to L ° We can create pseudo-instruction: blt $s0, $s1, L ° Special registers, useful in beq, bne, slt: ° $zero is a special register, holds 0 ° $at is another special register used in the blt pseudo-instruction It generates the above two instructions with $at replacing $t0 Branching further away -215 ≤ small constant offset 215-1 ° Consider a branch instruction beq $s0, $s1, L1 I-type # branch to L1 if $s0 = $s1 6 5 5 16 OP rs rt immediate ° If the offset does not fit in the above range the compiler (or programmer) changes it to the following sequence to get a larger distance. bne $s0, $s1, L2 j Large L2: J-type 6 OP # branch to L2 if $s0 $s1 # unconditional jump to “Large” 26 Large – jump target Loading large numbers ° Instruction lui: load upper immediate # $t0[31:16] const lui $t0, const 6 OP I-type 5 0 5 16 const rt 16 $to: const 31 16 0000 0000 0000 0000 16 15 0 MIPS Addressing Modes/Instruction Formats All instructions are 32-bit wide • Register (direct) op rs rt rd register • Immediate op rs rt immed • Base+index op rs rt immed + register • PC-relative op rs PC rt Memory immed Memory + Also there is pseudodirect addressing as is used by jump instructions Operation Summary Support these simple instructions, since they will dominate the number of instructions executed: load, store, add, subtract, move register-register, and, shift, compare equal, compare not equal, branch, jump, call, return; Additional MIPS Instructions MIPS instructions, formats MIPS instructions: data transfers, arithmetic, logical Pseudo-instruction example: loading large constant MIPS register organization Implementing loops Implementing switch/case statement Procedures and subroutines Stacks and pointers Running a program Compiler, Assembler, Linker, Loader MIPS: Software conventions for registers R0 $zero constant 0 R16 $s0 R1 $at reserved for assembler ... R2 $v0 value registers & R23 $s7 R3 $v1 R4 $a0 function results arguments callee saves (caller can clobber) R24 $t8 temporary (cont’d) R25 $t9 R5 $a1 R26 $k0 reserved for OS kernel R6 $a2 R27 $k1 R7 $a3 R28 $gp pointer to global area R8 $t0 temporary: caller saves R29 $sp Stack pointer ... (callee can clobber) R30 $fp Frame pointer R15 $t7 R31 $ra return Address MIPS data transfer instructions Instruction Comment sw 500($r4), $r3 Store word sh 502($r2), $r3 Store half sb 41($r3), $r2 Store byte lw $r1, 30($r2) Load word lh $r1, 40($r3) Load halfword lhu $r1, 40($r3) Load halfword unsigned lb $r1, 40($r3) Load byte lbu $r1, 40($r3) Load byte unsigned lui $r1, 40 Load Upper Immediate (16 bits shifted left by 16) LUI $r5 $r5 0000 … 0000 Loading large numbers ° Pseudo-instruction li $t0, big: load 32-bit constant lui $t0, upper ori $t0, $t0, lower # $t0[31:16] upper # $t0 ($t0 Or [0ext.lower]) upper OR 31 0000 0000 0000 0000 0000 0000 0000 0000 $to: 0 16 15 upper lower lower 32-bit constant Loop with variable array index ° Compile the following loop, with A[ ] = array with base address in $s5; variables g, h, i, j associated with registers $s1, $s2, $s3, $s4. Loop: g = g + A[i]; i = i + j; if (i h) go to Loop; MIPS instructions: Loop: add add add lw add add bne $t1, $s3, $s3 $t1, $t1, $t1 $t1, $t1, $s5 $t0, 0 ($t1) $s1, $s1, $t0 $s3, $s3, $s4 $s3, $s2, Loop # $t1 i+i = 2i # $t1 2i+2i = 4i # $t1 address of A[i] # $t0 A[i] # $s1 g + A[i] # $s3 i + j # if (i h) go to Loop While loop ° Base address of A[i] is in $s6; variables i, j, k are in $s3, $s4, $s5. ° Compile the following while loop while (A[i] == k) i = i + j; into MIPS instructions: Loop: Exit: add $t1, $s3, $s3 add $t1, $t1, $t1 add $t1, $t1, $s6 lw $t0, 0 ($t1) bne $t0, $s5, Exit add $s3, $s3, $s4 j Loop # $t1 i+i = 2i # $t1 2i+2i = 4i # $t1 address of A[i] # $t0 A[i] # if (A[I] k) go to Exit # $s3 i + j # go to Loop Switch/case statement ° Variables f - k are in $s0 - $s5. Register $t2 contains constant 4. ° Compile the following switch statement into MIPS instructions switch (k) { case 0: f = i + j; break; case 1: f = g + h; break; case 2: f = g - h; break; case 3: f = i - j; break; } /* k=0 */ /* k=1 */ /* k=2 */ /* k=3 */ ° Use the switch variable k to index the jump address table. First, test for k, if in correct range (0-3). slt bne slt beq $t3, $s5, $zero $t3, $zero, Exit $t3, $s5, $t2 $t3, $zero, Exit # test if k , 0 # if k < 0, go to Exit # test if k < 4 # if k 4, go to Exit Switch statement, cont’d ° Access jump table T [ ] with addresses L0,L1,L2,L3: $t4 is address of T add add add lw $t1, $s5, $s5 $t1, $t1, $t1 $t1, $t1, $t4 $t0, 0 ($t1) # $t1 2k # $t1 4k # $t1 address of T [k] # $t0 T [k] (loads one of L0, L1, L2, L3) ° Use jump register instruction to jump via $t0 to the right address jr $t0 # jump based on register $t0 L0: add $s0, $s3, $s4 # k = 0, so f=$s0 i + j j Exit # go to Exit L1: add $s0, $s1, $s2 # k = 1, so f=$s0 g + h j Exit # go to Exit L2: sub $s0, $s1, $s2 # k = 2, so f=$s0 g + h j Exit # go to Exit L3: sub $s0, $s3, $s4 # k = 3, so f=$s0 i - j Exit: Compiling a leaf procedure (not nested) ° int leaf_example (int g, int h, int i, int j) { int f; f = (g + h) – (i + j); return f; } ° Let parameter variables g, h, i, j, correspond to the argument registers $a0, $a1, $a2, $a3. Will use temp. registers $t0= (g + h) and $t1=(i + j). Function f will be stored in $s0. ° Steps: ° Save the old values of registers ($s0, $t0, $t1) on stack (push) ° Issue a jal sub_address instruction ($ra ret_addr, j sub_address) ° Perform the computation for $t0, $t1, $s0 using argument registers ° Copy the value of f into a return value register $v0 ° Restore the old values of the saved registers from stack (pop) ° Finally, jump back to the calling routine, jr $ra (PC return_address=PC+4) Compiling a leaf procedure, cont’d Leaf_example: # label of the procedure Save the old values of registers ($s0, $t0, $t1) on stack (push) sub $sp, $sp, 12 sw $t1, 8 ($sp) ……. # adjust stack to make room for 3 items # save reg $t1 on stack # repeat for $t0, $s0 Perform the computation for $t0, $t1, $s0 using argument registers add $t0, $a0, $a1 add $t1, $a2, $a3 sub $s0, $t0, $t1 # $t0 g + h # $t1 i + j # $s0 (g + h) – (i + j) Copy the value of f into a return value register $v0 # returns f ($v0 $s0 + 0) Restore the old values of the saved registers from stack (pop) lw $s0, 0 ($sp) # restore reg. $s0 for the caller ……. # repeat for $t0, $t1 … add $sp, $sp, 12 # adjust the stack to delete 3 items add $v0, $s0, $zero Finally, jump back to the calling routine (PC return address) jr $ra # PC $ra