3
* Bill Hunter, Wave 7 Optics, william.hunter@mediaone.net
5
* Erik Theisen, Wave 7 Optics, etheisen@mindspring.com
7
* SPDX-License-Identifier: GPL-2.0+
11
* Routine to exercise memory for the bringing up of our boards.
14
#include <asm/ppc4xx.h>
16
#include <ppc_asm.tmpl>
19
#include <asm/cache.h>
37
/*****************************************************
38
******* Text Strings for low level printing ******
39
******* In section got2 *******
40
*****************************************************/
43
* Define the text strings for errors and warnings.
44
* Switch to .data section.
47
err_str: .asciz "*** POST ERROR = "
48
warn_str: .asciz "*** POST WARNING = "
49
end_str: .asciz "\r\n"
52
* Enter the labels in Global Entry Table (GOT).
53
* Switch to .got2 section.
62
* Switch back to .text section.
66
/****************************************
67
****************************************
68
******** LED register test ********
69
****************************************
70
***************************************/
72
/* save the return info on stack */
73
mflr r0 /* Get link register */
74
stwu r1, -12(r1) /* Save back chain and move SP */
75
stw r0, +16(r1) /* Save link register */
76
stw r4, +8(r1) /* save R4 */
78
WATCHDOG_RESET /* Reset the watchdog */
80
addi r3, 0, ERR_FF /* first test value is ffff */
81
addi r4, r3, 0 /* save copy of pattern */
82
bl set_led /* store first test value */
83
bl get_led /* read it back */
84
xor. r4, r4, r3 /* compare to original */
85
#if defined(CONFIG_W7OLMC)
86
andi. r4, r4, 0x00ff /* lmc has 8 bits */
88
andi. r4, r4, 0xffff /* lmg has 16 bits */
90
beq LED2 /* next test */
91
addi r3, 0, ERR_LED /* error code = 1 */
92
bl log_err /* display error and halt */
93
LED2: addi r3, 0, ERR_00 /* 2nd test value is 0000 */
94
addi r4, r3, 0 /* save copy of pattern */
95
bl set_led /* store first test value */
96
bl get_led /* read it back */
97
xor. r4, r4, r3 /* compare to original */
98
#if defined(CONFIG_W7OLMC)
99
andi. r4, r4, 0x00ff /* lmc has 8 bits */
101
andi. r4, r4, 0xffff /* lmg has 16 bits */
103
beq LED3 /* next test */
104
addi r3, 0, ERR_LED /* error code = 1 */
105
bl log_err /* display error and halt */
107
LED3: /* restore stack and return */
108
lwz r0, +16(r1) /* Get saved link register */
109
mtlr r0 /* Restore link register */
110
lwz r4, +8(r1) /* restore r4 */
111
addi r1, r1, +12 /* Remove frame from stack */
112
blr /* Return to calling function */
114
/****************************************
115
****************************************
116
******** SDRAM TESTS ********
117
****************************************
118
***************************************/
120
/* called with mem size in r3 */
121
/* save the return info on stack */
122
mflr r0 /* Get link register */
123
stwu r1, -16(r1) /* Save back chain and move SP */
124
stw r0, +20(r1) /* Save link register */
125
stmw r30, +8(r1) /* save R30,R31 */
126
/* r30 is log2(mem size) */
127
/* r31 is mem size */
129
/* take log2 of total mem size */
130
addi r31, r3, 0 /* save total mem size */
131
addi r30, 0, 0 /* clear r30 */
133
srwi. r31, r31, 1 /* shift right 1 */
134
addi r30, r30, 1 /* count shifts */
135
bne l2_loop /* loop till done */
136
addi r30, r30, -1 /* correct for over count */
137
addi r31, r3, 0 /* save original size */
139
/* now kick the dog and test the mem */
140
WATCHDOG_RESET /* Reset the watchdog */
141
bl Data_Buster /* test crossed/shorted data lines */
142
addi r3, r30, 0 /* get log2(memsize) */
143
addi r4, r31, 0 /* get memsize */
144
bl Ghost_Buster /* test crossed/shorted addr lines */
145
addi r3, r31, 0 /* get mem size */
146
bl Bit_Buster /* check for bad internal bits */
148
/* restore stack and return */
149
lmw r30, +8(r1) /* Restore r30, r31 */
150
lwz r0, +20(r1) /* Get saved link register */
151
mtlr r0 /* Restore link register */
152
addi r1, r1, +16 /* Remove frame from stack */
153
blr /* Return to calling function */
156
/****************************************
157
******** sdram data bus test ********
158
***************************************/
160
/* save the return info on stack */
161
mflr r0 /* Get link register */
162
stwu r1, -24(r1) /* Save back chain and move SP */
163
stw r0, +28(r1) /* Save link register */
164
stmw r28, 8(r1) /* save r28 - r31 on stack */
165
/* r31 i/o register */
166
/* r30 sdram base address */
167
/* r29 5555 syndrom */
168
/* r28 aaaa syndrom */
170
/* set up led register for this test */
171
addi r3, 0, ERR_RAMG /* set led code to 1 */
172
bl log_stat /* store test value */
173
/* now test the dram data bus */
174
xor r30, r30, r30 /* load r30 with base addr of sdram */
175
addis r31, 0, 0x5555 /* load r31 with test value */
177
stw r31,0(r30) /* sto the value */
178
lwz r29,0(r30) /* read it back */
179
xor r29,r31,r29 /* compare it to original */
180
addis r31, 0, 0xaaaa /* load r31 with test value */
182
stw r31,0(r30) /* sto the value */
183
lwz r28,0(r30) /* read it back */
184
xor r28,r31,r28 /* compare it to original */
185
or r3,r28,r29 /* or together both error terms */
187
* Now that we have the error bits,
188
* we have to decide which part they are in.
190
bl get_idx /* r5 is now index to error */
191
addi r3, r3, ERR_RAMG
192
cmpwi r3, ERR_RAMG /* check for errors */
193
beq db_done /* skip if no errors */
194
bl log_err /* log the error */
197
lmw r28, 8(r1) /* restore r28 - r31 from stack */
198
lwz r0, +28(r1) /* Get saved link register */
199
addi r1, r1, +24 /* Remove frame from stack */
200
mtlr r0 /* Restore link register */
201
blr /* Return to calling function */
204
/****************************************************
205
******** test for address ghosting in dram ********
206
***************************************************/
209
/* save the return info on stack */
210
mflr r0 /* Get link register */
211
stwu r1, -36(r1) /* Save back chain and move SP */
212
stw r0, +40(r1) /* Save link register */
213
stmw r25, 8(r1) /* save r25 - r31 on stack */
214
/* r31 = scratch register */
215
/* r30 is main referance loop counter,
217
/* r29 is ghost loop count, 0 to 22 */
218
/* r28 is referance address */
219
/* r27 is ghost address */
220
/* r26 is log2 (mem size) =
221
number of byte addr bits */
222
/* r25 is mem size */
224
/* save the log2(mem size) and mem size */
225
addi r26, r3, 0 /* r26 is number of byte addr bits */
226
addi r25, r4, 0 /* r25 is mem size in bytes */
228
/* set the leds for address ghost test */
232
/* first fill memory with zeros */
233
srwi r31, r25, 2 /* convert bytes to longs */
234
mtctr r31 /* setup byte counter */
235
addi r28, 0, 0 /* start at address at 0 */
236
addi r31, 0, 0 /* data value = 0 */
238
stw r31, 0(r28) /* Store zero value */
239
addi r28, r28, 4 /* Increment to next word */
240
andi. r27, r28, 0xffff /* check for 2^16 loops */
241
bne clr_skip /* if not there, then skip */
242
WATCHDOG_RESET /* kick the dog every now and then */
244
bdnz clr_loop /* Round and round... */
246
/* now do main test */
247
addi r30, 0, 0 /* start referance counter at 0 */
250
* Calculate the referance address
251
* the referance address is calculated by setting the (r30-1)
252
* bit of the base address
253
* when r30=0, the referance address is the base address.
254
* thus the sequence 0,1,2,4,8,..,2^(n-1)
255
* setting the bit is done with the following shift functions.
257
WATCHDOG_RESET /* Reset the watchdog */
259
addi r31, 0, 1 /* r31 = 1 */
260
slw r28, r31, r30 /* set bit coresponding to loop cnt */
261
srwi r28, r28, 1 /* then shift it right one so */
262
/* we start at location 0 */
263
/* fill referance address with Fs */
264
addi r31, 0, 0x00ff /* r31 = one byte of set bits */
265
stb r31,0(r28) /* save ff in referance address */
267
/* ghost (inner) loop, now check all posible ghosted addresses */
268
addi r29, 0, 0 /* start ghosted loop counter at 0 */
271
* Calculate the ghost address by flipping one
272
* bit of referance address. This gives the
273
* sequence 1,2,4,8,...,2^(n-1)
275
addi r31, 0, 1 /* r31 = 1 */
276
slw r27, r31, r29 /* set bit coresponding to loop cnt */
277
xor r27, r28, r27 /* ghost address = ref addr with
280
/* now check for ghosting */
281
lbz r31,0(r27) /* get content of ghost addr */
282
cmpwi r31, 0 /* compare read value to 0 */
283
bne Casper /* we found a ghost! */
285
/* now close ghost ( inner ) loop */
286
addi r29, r29, 1 /* increment inner loop counter */
287
cmpw r29, r26 /* check for last inner loop */
288
blt inside /* do more inner loops */
290
/* now close referance ( outer ) loop */
291
addi r31, 0, 0 /* r31 = zero */
292
stb r31, 0(28) /* zero out the altered address loc. */
294
* Increment and check for end, count is zero based.
295
* With the ble, this gives us one more loops than
296
* address bits for sequence 0,1,2,4,8,...2^(n-1)
298
addi r30, r30, 1 /* increment outer loop counter */
299
cmpw r30, r26 /* check for last inner loop */
300
ble outside /* do more outer loops */
302
/* were done, lets go home */
304
Casper: /* we found a ghost !! */
305
addi r3, 0, ERR_ADDF /* get indexed error message */
306
bl log_err /* log error led error code */
307
gb_done: /* pack your bags, and go home */
308
lmw r25, 8(r1) /* restore r25 - r31 from stack */
309
lwz r0, +40(r1) /* Get saved link register */
310
addi r1, r1, +36 /* Remove frame from stack */
311
mtlr r0 /* Restore link register */
312
blr /* Return to calling function */
314
/****************************************************
315
******** SDRAM data fill tests **********
316
***************************************************/
318
/* called with mem size in r3 */
319
/* save the return info on stack */
320
mflr r0 /* Get link register */
321
stwu r1, -16(r1) /* Save back chain and move SP */
322
stw r0, +20(r1) /* Save link register */
323
stw r4, +8(r1) /* save R4 */
324
stw r5, +12(r1) /* save r5 */
326
addis r5, r3, 0 /* save mem size */
329
addi r3, 0, ERR_R55G /* set up error code in case we fail */
330
bl log_stat /* store test value */
336
addi r3, 0, ERR_RAAG /* set up error code in case we fail */
337
bl log_stat /* store test value */
343
addi r3, 0, ERR_R00G /* set up error code in case we fail */
344
bl log_stat /* store test value */
349
/* restore stack and return */
350
lwz r5, +12(r1) /* restore r4 */
351
lwz r4, +8(r1) /* restore r4 */
352
lwz r0, +20(r1) /* Get saved link register */
353
addi r1, r1, +16 /* Remove frame from stack */
354
mtlr r0 /* Restore link register */
355
blr /* Return to calling function */
358
/****************************************************
359
******** fill test ********
360
***************************************************/
361
/* tests memory by filling with value, and reading back */
362
/* r5 = Size of memory in bytes */
363
/* r4 = Value to write */
364
/* r3 = Error code */
366
mflr r0 /* Get link register */
367
stwu r1, -32(r1) /* Save back chain and move SP */
368
stw r0, +36(r1) /* Save link register */
369
stmw r27, 8(r1) /* save r27 - r31 on stack */
370
/* r31 - scratch register */
371
/* r30 - memory address */
376
WATCHDOG_RESET /* Reset the watchdog */
378
/* first fill memory with Value */
379
srawi r31, r29, 2 /* convert bytes to longs */
380
mtctr r31 /* setup counter */
381
addi r30, 0, 0 /* Make r30 = addr 0 */
382
ft_0: stw r28, 0(r30) /* Store value */
383
addi r30, r30, 4 /* Increment to next word */
384
andi. r31, r30, 0xffff /* check for 2^16 loops */
385
bne ft_0a /* if not there, then skip */
386
WATCHDOG_RESET /* kick the dog every now and then */
387
ft_0a: bdnz ft_0 /* Round and round... */
389
WATCHDOG_RESET /* Reset the watchdog */
391
/* Now confirm Value is in memory */
392
srawi r31, r29, 2 /* convert bytes to longs */
393
mtctr r31 /* setup counter */
394
addi r30, 0, 0 /* Make r30 = addr 0 */
395
ft_1: lwz r31, 0(r30) /* get value from memory */
396
xor. r31, r31, r28 /* Writen = Read ? */
397
bne ft_err /* If bad, than halt */
398
addi r30, r30, 4 /* Increment to next word */
399
andi. r31, r30, 0xffff /* check for 2^16 loops*/
400
bne ft_1a /* if not there, then skip */
401
WATCHDOG_RESET /* kick the dog every now and then */
402
ft_1a: bdnz ft_1 /* Round and round... */
404
WATCHDOG_RESET /* Reset the watchdog */
406
b fill_done /* restore and return */
408
ft_err: addi r29, r27, 0 /* save current led code */
409
addi r27, r31, 0 /* get pattern in r27 */
410
bl get_idx /* get index from r27 */
411
add r27, r27, r29 /* add index to old led code */
412
bl log_err /* output led err code, halt CPU */
415
lmw r27, 8(r1) /* restore r27 - r31 from stack */
416
lwz r0, +36(r1) /* Get saved link register */
417
addi r1, r1, +32 /* Remove frame from stack */
418
mtlr r0 /* Restore link register */
419
blr /* Return to calling function */
422
/****************************************************
423
******* get error index from r3 pattern ********
424
***************************************************/
425
get_idx: /* r3 = (MSW(r3) !=0)*2 +
427
/* save the return info on stack */
428
mflr r0 /* Get link register */
429
stwu r1, -12(r1) /* Save back chain and move SP */
430
stw r0, +16(r1) /* Save link register */
431
stw r4, +8(r1) /* save R4 */
433
andi. r4, r3, 0xffff /* check for lower bits */
434
beq gi2 /* skip if no bits set */
435
andis. r4, r3, 0xffff /* check for upper bits */
436
beq gi3 /* skip if no bits set */
437
addi r3, 0, 3 /* both upper and lower bits set */
439
gi2: andis. r4, r3, 0xffff /* check for upper bits*/
440
beq gi4 /* skip if no bits set */
441
addi r3, 0, 2 /* only upper bits set */
443
gi3: addi r3, 0, 1 /* only lower bits set */
445
gi4: addi r3, 0, 0 /* no bits set */
447
/* restore stack and return */
448
lwz r0, +16(r1) /* Get saved link register */
449
mtlr r0 /* Restore link register */
450
lwz r4, +8(r1) /* restore r4 */
451
addi r1, r1, +12 /* Remove frame from stack */
452
blr /* Return to calling function */
454
/****************************************************
455
******** set LED to R5 and hang ********
456
***************************************************/
457
log_stat: /* output a led code and continue */
459
/* save the return info on stack */
460
mflr r0 /* Get link register */
461
stwu r1, -12(r1) /* Save back chain and move SP */
462
stw r0, +16(r1) /* Save link register */
463
stw r4, +8(r1) /* save R4 */
465
addis r4, 0, 0xfe00 /* LED buffer is at 0xfe000000 */
466
#if defined(CONFIG_W7OLMG) /* only on gateway, invert outputs */
467
xori r3,r3, 0xffff /* complement led code, active low */
468
sth r3, 0(r4) /* store first test value */
469
xori r3,r3, 0xffff /* complement led code, active low */
470
#else /* if not gateway, then don't invert */
471
sth r3, 0(r4) /* store first test value */
474
/* restore stack and return */
475
lwz r0, +16(r1) /* Get saved link register */
476
mtlr r0 /* Restore link register */
477
lwz r4, +8(r1) /* restore r4 */
478
addi r1, r1, +12 /* Remove frame from stack */
479
blr /* Return to calling function */
482
/* save the return info on stack */
483
mflr r0 /* Get link register */
484
stwu r1, -12(r1) /* Save back chain and move SP */
485
stw r0, +16(r1) /* Save link register */
486
stw r4, +8(r1) /* save R4 */
488
addis r4, 0, 0xfe00 /* LED buffer is at 0xfe000000 */
489
lhz r3, 0(r4) /* store first test value */
490
#if defined(CONFIG_W7OLMG) /* only on gateway, invert inputs */
491
xori r3,r3, 0xffff /* complement led code, active low */
494
/* restore stack and return */
495
lwz r0, +16(r1) /* Get saved link register */
496
mtlr r0 /* Restore link register */
497
lwz r4, +8(r1) /* restore r4 */
498
addi r1, r1, +12 /* Remove frame from stack */
499
blr /* Return to calling function */
501
log_err: /* output the error and hang the board ( for now ) */
502
/* save the return info on stack */
503
mflr r0 /* Get link register */
504
stwu r1, -12(r1) /* Save back chain and move SP */
505
stw r0, +16(r1) /* Save link register */
506
stw r3, +8(r1) /* save a copy of error code */
507
bl set_led /* set the led pattern */
508
GET_GOT /* get GOT address in r14 */
509
lwz r3,GOT(err_str) /* get address of string */
510
bl post_puts /* output the warning string */
511
lwz r3, +8(r1) /* get error code */
512
addi r4, 0, 2 /* set disp length to 2 nibbles */
513
bl disp_hex /* output the error code */
514
lwz r3,GOT(end_str) /* get address of string */
515
bl post_puts /* output the warning string */
519
/* restore stack and return */
520
lwz r0, +16(r1) /* Get saved link register */
521
mtlr r0 /* Restore link register */
522
addi r1, r1, +12 /* Remove frame from stack */
523
blr /* Return to calling function */
525
log_warn: /* output a warning, then continue with operations */
526
/* save the return info on stack */
527
mflr r0 /* Get link register */
528
stwu r1, -16(r1) /* Save back chain and move SP */
529
stw r0, +20(r1) /* Save link register */
530
stw r3, +8(r1) /* save a copy of error code */
531
stw r14, +12(r1) /* save a copy of r14 (used by GOT) */
533
bl set_led /* set the led pattern */
534
GET_GOT /* get GOT address in r14 */
535
lwz r3,GOT(warn_str) /* get address of string */
536
bl post_puts /* output the warning string */
537
lwz r3, +8(r1) /* get error code */
538
addi r4, 0, 2 /* set disp length to 2 nibbles */
539
bl disp_hex /* output the error code */
540
lwz r3,GOT(end_str) /* get address of string */
541
bl post_puts /* output the warning string */
543
addis r3, 0, 64 /* has a long delay */
546
WATCHDOG_RESET /* this keeps dog from barking, */
548
bdnz log_2 /* loop till time expires */
550
/* restore stack and return */
551
lwz r0, +20(r1) /* Get saved link register */
552
lwz r14, +12(r1) /* restore r14 */
553
mtlr r0 /* Restore link register */
554
addi r1, r1, +16 /* Remove frame from stack */
555
blr /* Return to calling function */
557
/*******************************************************************
559
* Temporary UART initialization routine
560
* Sets up UART0 to run at 9600N81 off of the internal clock.
562
******************************************************************/
564
/* save the return info on stack */
565
mflr r0 /* Get link register */
566
stwu r1, -8(r1) /* Save back chain and move SP */
567
stw r0, +12(r1) /* Save link register */
570
ori r3, r3, 0x0303 /* r3 = UART0_LCR */
571
addi r4, 0, 0x83 /* n81 format, divisor regs enabled */
574
/* set baud rate to use internal clock,
575
baud = (200e6/16)/31/42 = 9600 */
577
addis r3, 0, 0xef60 /* Address of baud divisor reg */
578
ori r3, r3, 0x0300 /* UART0_DLM */
579
addi r4, 0, +42 /* uart baud divisor LSB = 93 */
580
stb r4, 0(r3) /* baud = (200 /16)/14/93 */
582
addi r3, r3, 0x0001 /* uart baud divisor addr */
584
stb r4, 0(r3) /* Divisor Latch MSB = 0 */
587
ori r3, r3, 0x0303 /* r3 = UART0_LCR */
588
addi r4, 0, 0x03 /* n81 format, tx/rx regs enabled */
591
/* output a few line feeds */
592
addi r3, 0, '\n' /* load line feed */
593
bl post_putc /* output the char */
594
addi r3, 0, '\n' /* load line feed */
595
bl post_putc /* output the char */
597
/* restore stack and return */
598
lwz r0, +12(r1) /* Get saved link register */
599
mtlr r0 /* Restore link register */
600
addi r1, r1, +8 /* Remove frame from stack */
601
blr /* Return to calling function */
603
/**********************************************************************
605
** outputs charactor in R3
606
** r3 returns the error code ( -1 if there is an error )
607
*********************************************************************/
611
/* save the return info on stack */
612
mflr r0 /* Get link register */
613
stwu r1, -20(r1) /* Save back chain and move SP */
614
stw r0, +24(r1) /* Save link register */
615
stmw r29, 8(r1) /* save r29 - r31 on stack
616
r31 - uart base address
620
addis r31, 0, 0xef60 /* Point to uart base */
622
addis r30, 0, 152 /* Load about 10,000,000 ticks. */
624
lbz r29, 5(r31) /* Read Line Status Register */
625
andi. r29, r29, 0x20 /* Check THRE status */
626
bne thre_set /* Branch if FIFO empty */
627
addic. r30, r30, -1 /* Decrement and check if empty. */
628
bne pputc_lp /* Try, try again */
629
addi r3, 0, -1 /* Load error code for timeout */
630
b pputc_done /* Bail out with error code set */
632
stb r3, 0(r31) /* Store character to UART */
633
addi r3, 0, 0 /* clear error code */
635
lmw r29, 8(r1) /*restore r29 - r31 from stack */
636
lwz r0, +24(r1) /* Get saved link register */
637
addi r1, r1, +20 /* Remove frame from stack */
638
mtlr r0 /* Restore link register */
639
blr /* Return to calling function */
642
/****************************************************************
644
Accepts a null-terminated string pointed to by R3
645
Outputs to the serial port until 0x00 is found.
646
r3 returns the error code ( -1 if there is an error )
647
*****************************************************************/
650
/* save the return info on stack */
651
mflr r0 /* Get link register */
652
stwu r1, -12(r1) /* Save back chain and move SP */
653
stw r0, +16(r1) /* Save link register */
654
stw r31, 8(r1) /* save r31 - char pointer */
656
addi r31, r3, 0 /* move pointer to R31 */
658
lbz r3, 0(r31) /* Get next character */
659
addic. r3, r3, 0 /* Check for zero */
660
beq pputs_term /* bail out if zero */
661
bl post_putc /* output the char */
662
addic. r3, r3, 0 /* check for error */
664
addi r31, r31, 1 /* point to next char */
665
b pputs_nxt /* loop till term */
667
addi r3, 0, -1 /* set error code */
668
b pputs_end /* were outa here */
670
addi r3, 0, 1 /* set success code */
671
/* restore stack and return */
673
lwz r31, 8(r1) /* restore r27 - r31 from stack */
674
lwz r0, +16(r1) /* Get saved link register */
675
addi r1, r1, +12 /* Remove frame from stack */
676
mtlr r0 /* Restore link register */
677
blr /* Return to calling function */
680
/********************************************************************
682
***** Routine to display a hex value from a register.
683
***** R3 is value to display
684
***** R4 is number of nibbles to display ie 2 for byte 8 for (long)word
685
***** Returns -1 in R3 if there is an error ( ie serial port hangs )
686
***** Returns 0 in R3 if no error
687
*******************************************************************/
689
/* save the return info on stack */
690
mflr r0 /* Get link register */
691
stwu r1, -16(r1) /* Save back chain and move SP */
692
stw r0, +20(r1) /* Save link register */
693
stmw r30, 8(r1) /* save r30 - r31 on stack */
694
/* r31 output char */
695
/* r30 uart base address */
696
addi r30, 0, 8 /* Go through 8 nibbles. */
699
rlwinm r31, r31, 4, 0, 31 /* Rotate next nibble into position */
700
andi. r3, r31, 0x0f /* Get nibble. */
701
addi r3, r3, 0x30 /* Add zero's ASCII code. */
704
addi r3, r3, 0x07 /* 0x27 for lower case. */
709
addic. r3, r3, 0 /* check for error */
714
xor r3, r3, r3 /* Clear error code */
717
addi r3, 0, -1 /* set error code */
719
/* restore stack and return */
720
lmw r30, 8(r1) /* restore r30 - r31 from stack */
721
lwz r0, +20(r1) /* Get saved link register */
722
addi r1, r1, +16 /* Remove frame from stack */
723
mtlr r0 /* Restore link register */
724
blr /* Return to calling function */