Review of Activation Frames In general, activation frames are organized like this: HI LO Bookkeeping/preserved registers I/O parameters Locals and temps RA of caller FP of caller Y X Return value A B C Caller s responsibility Callee s responsibility
Consider the following function: int Foo(int a, int b) { int x; int y = 10; x = ay+b; return x;} This problem writes the MIPS code to implement Foo in parts. The beginning of Foo s activation frame is shown on the stack. This is the state as Foo is called. HI FP -> Caller s return value Caller of Foo s AF LO SP -> Caller s locals RA to caller FP of caller b a Return value ends here Foo s AF starts here Part A) Write MIPS code to complete Foo s activation frame by pushing locals on the stack. Be sure to update the frame pointer properly. (Answers are in bold face.) Foo: add $30, $29, $0 addi $29, $29, -8 addi $1, $0, 10 sw $1, -8($30) # set base of FP # alloc 2 ints: x, y # initialize y # push init val of y Part B) Compute the x = ay+b; statement by accessing a, y, and b from the stack. Be sure to update locals on the stack. lw $3, 4($30) # $3: a lw $2, 8($30) # $2: b lw $1, -8(30) # $1: y (optional, already in $1) mult $3, $1 # ay mflo $3 # $3: ay add $3, $3, $2 # $3: ay+b sw $3, -4($30) # update x = ax+b Part C) Finish the implementation of Foo by implementing its return to its caller. lw $3, -4($30) # $3: x (optional, already in $3) sw $3, 0($30) # store x in return value slot addi $29, $30, $0 # pop off locals
Suppose we have a function Fun which calls another function AppleFun with 2 args: int Fun(int I, J) { int x, y, z, Result; Result = AppleFun(I, J) + I + J; return Result;} Part of the MIPS implementation of Fun is given below. Part A) Fill in the MIPS code necessary before the call to AppleFun. You will need to prepare the stack and preserve registers that are needed after the function call. Part B) Write the MIPS code to restore the values from AppleFun s activation frame and assign the value of Result. Fun: add $6, $1, $2 addi $29, $29, -24 sw $31, 20($29) sw $30, 16($29) sw $6, 12($29) sw $2, 8($29) sw $1, 4($29) jal AppleFun lw $31, 20($29) lw $30, 16($29) lw $6, 12($29) lw $3, 0($29) addi $29, $29, 24 add $6, $3, $6 sw $6, -16($30) # assume Fun s locals are # allocated in its AF # assume Result is # allocated at offset -16 # relative to Fun s FP. # assume $1: I, $2: J # $6: I+J The Answer to PART A goes in these slots. Determine what should be preserved ($31, $30, $6) + allocate I/O params. The Answer to PART B goes in these slots. Restore preserved values and update Result. # deallocate Fun s locals # return
Now suppose Fun calls BerryFun, which is a function of 2 pointers to integers. int BerryFun(int *A, *B) {} int *C; int *D; int Fun(int I,J) { Result = BerryFun(&C, &D); } Suppose C and D are statically defined at addresses 5000 and 5004, respectively. Fill in the MIPS code to implement this function call. Fun: # assume Fun s locals are # allocated in its AF # assume Result is allocated at # offset -16 relative to Fun s FP. # assume $1: I, $2: J addi $29, $29, -20 sw $31, 16($29) The Answer to PART A goes in these sw $30, 12($29) slots. Determine what should be addi $1, $0, 5004 preserved ($31, $30) + allocate sw $1, 8($29) I/O params. Note that the inputs addi $1, $0, 5000 are addresses of C and D. sw $1, 4($29) jal BerryFun lw $31, 16($29) lw $30, 12($29) lw $3, 0($29) sw $3, -16($30) The Answer to PART B goes in these slots. Restore preserved values and update Result. # deallocate Fun s locals # return
Function pointer example int search (int a, int b, int ascending) { E = extreme(a, b, (ascending? maximum : minimum)); } int extreme(int x, int y, int (* compare)(int, int)) { if ((* compare)(x, y) == 1) result = x; else result = y; } Suppose the functions maximum and minimum are defined at locations 4600 and 4700, respectively. The current state of the stack at the beginning of search looks like this: HI LO FP -> SP -> RA of caller FP of caller ascending b a Return value Search s locals
Part A) Write MIPS code to set up Extreme s activation frame just before the jal to Extreme. Search: # Answer to Part A goes below. Set up Extreme s AF (preserve RA, FP, alloc I/O: F. ptr, x, y, rtn val) addi $29, $29, -24 sw $31, 20($29) sw $30, 16($29) lw $1, 12($30) # $1: read ascending input beq $1, $0, Descend addi $2, $0, 4600 # ptr to Maximum J Skip Descend: addi $2, $0, 4700 # ptr to Minimum Skip: sw $2, 12($29) # pass function pointer lw $3, 4($30) # read a lw $4, 8($30) # read b sw $3, 4($29) # pass a as x sw $4, 8($29) # pass b as y jal Extreme Part B) Fill in the missing MIPS code below to prepare the call to the function pointer: Extreme: addi $30, $29, $0 lw $7, 4($30) $7: x (read input) lw $8, 8($30) $8: y (read input) lw $6, 12($30) $6: f. ptr (read input) # Answer to Part B goes below. Prepare to call the function ptr, preserve RA, FP, allocate I/O. addi $29, $29, -20 sw $31, 16($29) sw $30, 12($29) sw $7, 4($29) # pass x sw $8, 8($29) # pass y addi $31, $0, FPtrCall # form RA (FPtrCall+4) addi $31, $31, 4 # (if > 32K, use lui+ori) FPtrCall: jr $6 # jump to addr in $6 lw $31, 16($29) # restore RA lw $30, 12($29) # restore FP lw $1, 0($29) # load rtn val addi $2, $0, 1 # if ((* compare)(x,y) ==1 beq $1, $2, Skip # then goto Skip lw $4, 8($30) # $4: y J End Skip: lw $4, 4($30) # $4: x End: sw $4, 0($30) # store return val