uboot/cpu/mpc8xx/start.S
<<
>>
Prefs
   1/*
   2 *  Copyright (C) 1998  Dan Malek <dmalek@jlc.net>
   3 *  Copyright (C) 1999  Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
   4 *  Copyright (C) 2000,2001,2002 Wolfgang Denk <wd@denx.de>
   5 *
   6 * See file CREDITS for list of people who contributed to this
   7 * project.
   8 *
   9 * This program is free software; you can redistribute it and/or
  10 * modify it under the terms of the GNU General Public License as
  11 * published by the Free Software Foundation; either version 2 of
  12 * the License, or (at your option) any later version.
  13 *
  14 * This program is distributed in the hope that it will be useful,
  15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17 * GNU General Public License for more details.
  18 *
  19 * You should have received a copy of the GNU General Public License
  20 * along with this program; if not, write to the Free Software
  21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  22 * MA 02111-1307 USA
  23 */
  24
  25/*  U-Boot - Startup Code for PowerPC based Embedded Boards
  26 *
  27 *
  28 *  The processor starts at 0x00000100 and the code is executed
  29 *  from flash. The code is organized to be at an other address
  30 *  in memory, but as long we don't jump around before relocating,
  31 *  board_init lies at a quite high address and when the cpu has
  32 *  jumped there, everything is ok.
  33 *  This works because the cpu gives the FLASH (CS0) the whole
  34 *  address space at startup, and board_init lies as a echo of
  35 *  the flash somewhere up there in the memory map.
  36 *
  37 *  board_init will change CS0 to be positioned at the correct
  38 *  address and (s)dram will be positioned at address 0
  39 */
  40#include <config.h>
  41#include <mpc8xx.h>
  42#include <timestamp.h>
  43#include <version.h>
  44
  45#define CONFIG_8xx 1            /* needed for Linux kernel header files */
  46#define _LINUX_CONFIG_H 1       /* avoid reading Linux autoconf.h file  */
  47
  48#include <ppc_asm.tmpl>
  49#include <ppc_defs.h>
  50
  51#include <asm/cache.h>
  52#include <asm/mmu.h>
  53
  54#ifndef  CONFIG_IDENT_STRING
  55#define  CONFIG_IDENT_STRING ""
  56#endif
  57
  58/* We don't want the  MMU yet.
  59*/
  60#undef  MSR_KERNEL
  61#define MSR_KERNEL ( MSR_ME | MSR_RI )  /* Machine Check and Recoverable Interr. */
  62
  63/*
  64 * Set up GOT: Global Offset Table
  65 *
  66 * Use r14 to access the GOT
  67 */
  68        START_GOT
  69        GOT_ENTRY(_GOT2_TABLE_)
  70        GOT_ENTRY(_FIXUP_TABLE_)
  71
  72        GOT_ENTRY(_start)
  73        GOT_ENTRY(_start_of_vectors)
  74        GOT_ENTRY(_end_of_vectors)
  75        GOT_ENTRY(transfer_to_handler)
  76
  77        GOT_ENTRY(__init_end)
  78        GOT_ENTRY(_end)
  79        GOT_ENTRY(__bss_start)
  80        END_GOT
  81
  82/*
  83 * r3 - 1st arg to board_init(): IMMP pointer
  84 * r4 - 2nd arg to board_init(): boot flag
  85 */
  86        .text
  87        .long   0x27051956              /* U-Boot Magic Number                  */
  88        .globl  version_string
  89version_string:
  90        .ascii U_BOOT_VERSION
  91        .ascii " (", U_BOOT_DATE, " - ", U_BOOT_TIME, ")"
  92        .ascii CONFIG_IDENT_STRING, "\0"
  93
  94        . = EXC_OFF_SYS_RESET
  95        .globl  _start
  96_start:
  97        lis     r3, CONFIG_SYS_IMMR@h           /* position IMMR */
  98        mtspr   638, r3
  99        li      r21, BOOTFLAG_COLD      /* Normal Power-On: Boot from FLASH     */
 100        b       boot_cold
 101
 102        . = EXC_OFF_SYS_RESET + 0x10
 103
 104        .globl  _start_warm
 105_start_warm:
 106        li      r21, BOOTFLAG_WARM      /* Software reboot                      */
 107        b       boot_warm
 108
 109boot_cold:
 110boot_warm:
 111
 112        /* Initialize machine status; enable machine check interrupt            */
 113        /*----------------------------------------------------------------------*/
 114        li      r3, MSR_KERNEL          /* Set ME, RI flags */
 115        mtmsr   r3
 116        mtspr   SRR1, r3                /* Make SRR1 match MSR */
 117
 118        mfspr   r3, ICR                 /* clear Interrupt Cause Register */
 119
 120        /* Initialize debug port registers                                      */
 121        /*----------------------------------------------------------------------*/
 122        xor     r0, r0, r0              /* Clear R0 */
 123        mtspr   LCTRL1, r0              /* Initialize debug port regs */
 124        mtspr   LCTRL2, r0
 125        mtspr   COUNTA, r0
 126        mtspr   COUNTB, r0
 127
 128        /* Reset the caches                                                     */
 129        /*----------------------------------------------------------------------*/
 130
 131        mfspr   r3, IC_CST              /* Clear error bits */
 132        mfspr   r3, DC_CST
 133
 134        lis     r3, IDC_UNALL@h         /* Unlock all */
 135        mtspr   IC_CST, r3
 136        mtspr   DC_CST, r3
 137
 138        lis     r3, IDC_INVALL@h        /* Invalidate all */
 139        mtspr   IC_CST, r3
 140        mtspr   DC_CST, r3
 141
 142        lis     r3, IDC_DISABLE@h       /* Disable data cache */
 143        mtspr   DC_CST, r3
 144
 145#if !defined(CONFIG_SYS_DELAYED_ICACHE)
 146                                        /* On IP860 and PCU E,
 147                                         * we cannot enable IC yet
 148                                         */
 149        lis     r3, IDC_ENABLE@h        /* Enable instruction cache */
 150#endif
 151        mtspr   IC_CST, r3
 152
 153        /* invalidate all tlb's                                                 */
 154        /*----------------------------------------------------------------------*/
 155
 156        tlbia
 157        isync
 158
 159        /*
 160         * Calculate absolute address in FLASH and jump there
 161         *----------------------------------------------------------------------*/
 162
 163        lis     r3, CONFIG_SYS_MONITOR_BASE@h
 164        ori     r3, r3, CONFIG_SYS_MONITOR_BASE@l
 165        addi    r3, r3, in_flash - _start + EXC_OFF_SYS_RESET
 166        mtlr    r3
 167        blr
 168
 169in_flash:
 170
 171        /* initialize some SPRs that are hard to access from C                  */
 172        /*----------------------------------------------------------------------*/
 173
 174        lis     r3, CONFIG_SYS_IMMR@h           /* pass IMMR as arg1 to C routine */
 175        ori     r1, r3, CONFIG_SYS_INIT_SP_OFFSET /* set up the stack in internal DPRAM */
 176        /* Note: R0 is still 0 here */
 177        stwu    r0, -4(r1)              /* clear final stack frame so that      */
 178        stwu    r0, -4(r1)              /* stack backtraces terminate cleanly   */
 179
 180        /*
 181         * Disable serialized ifetch and show cycles
 182         * (i.e. set processor to normal mode).
 183         * This is also a silicon bug workaround, see errata
 184         */
 185
 186        li      r2, 0x0007
 187        mtspr   ICTRL, r2
 188
 189        /* Set up debug mode entry */
 190
 191        lis     r2, CONFIG_SYS_DER@h
 192        ori     r2, r2, CONFIG_SYS_DER@l
 193        mtspr   DER, r2
 194
 195        /* let the C-code set up the rest                                       */
 196        /*                                                                      */
 197        /* Be careful to keep code relocatable !                                */
 198        /*----------------------------------------------------------------------*/
 199
 200        GET_GOT                 /* initialize GOT access                        */
 201
 202        /* r3: IMMR */
 203        bl      cpu_init_f      /* run low-level CPU init code     (from Flash) */
 204
 205        mr      r3, r21
 206        /* r3: BOOTFLAG */
 207        bl      board_init_f    /* run 1st part of board init code (from Flash) */
 208
 209
 210        .globl  _start_of_vectors
 211_start_of_vectors:
 212
 213/* Machine check */
 214        STD_EXCEPTION(0x200, MachineCheck, MachineCheckException)
 215
 216/* Data Storage exception.  "Never" generated on the 860. */
 217        STD_EXCEPTION(0x300, DataStorage, UnknownException)
 218
 219/* Instruction Storage exception.  "Never" generated on the 860. */
 220        STD_EXCEPTION(0x400, InstStorage, UnknownException)
 221
 222/* External Interrupt exception. */
 223        STD_EXCEPTION(0x500, ExtInterrupt, external_interrupt)
 224
 225/* Alignment exception. */
 226        . = 0x600
 227Alignment:
 228        EXCEPTION_PROLOG(SRR0, SRR1)
 229        mfspr   r4,DAR
 230        stw     r4,_DAR(r21)
 231        mfspr   r5,DSISR
 232        stw     r5,_DSISR(r21)
 233        addi    r3,r1,STACK_FRAME_OVERHEAD
 234        li      r20,MSR_KERNEL
 235        rlwimi  r20,r23,0,16,16         /* copy EE bit from saved MSR */
 236        lwz     r6,GOT(transfer_to_handler)
 237        mtlr    r6
 238        blrl
 239.L_Alignment:
 240        .long   AlignmentException - _start + EXC_OFF_SYS_RESET
 241        .long   int_return - _start + EXC_OFF_SYS_RESET
 242
 243/* Program check exception */
 244        . = 0x700
 245ProgramCheck:
 246        EXCEPTION_PROLOG(SRR0, SRR1)
 247        addi    r3,r1,STACK_FRAME_OVERHEAD
 248        li      r20,MSR_KERNEL
 249        rlwimi  r20,r23,0,16,16         /* copy EE bit from saved MSR */
 250        lwz     r6,GOT(transfer_to_handler)
 251        mtlr    r6
 252        blrl
 253.L_ProgramCheck:
 254        .long   ProgramCheckException - _start + EXC_OFF_SYS_RESET
 255        .long   int_return - _start + EXC_OFF_SYS_RESET
 256
 257        /* No FPU on MPC8xx.  This exception is not supposed to happen.
 258        */
 259        STD_EXCEPTION(0x800, FPUnavailable, UnknownException)
 260
 261        /* I guess we could implement decrementer, and may have
 262         * to someday for timekeeping.
 263         */
 264        STD_EXCEPTION(0x900, Decrementer, timer_interrupt)
 265        STD_EXCEPTION(0xa00, Trap_0a, UnknownException)
 266        STD_EXCEPTION(0xb00, Trap_0b, UnknownException)
 267        STD_EXCEPTION(0xc00, SystemCall, UnknownException)
 268        STD_EXCEPTION(0xd00, SingleStep, UnknownException)
 269
 270        STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
 271        STD_EXCEPTION(0xf00, Trap_0f, UnknownException)
 272
 273        /* On the MPC8xx, this is a software emulation interrupt.  It occurs
 274         * for all unimplemented and illegal instructions.
 275         */
 276        STD_EXCEPTION(0x1000, SoftEmu, SoftEmuException)
 277
 278        STD_EXCEPTION(0x1100, InstructionTLBMiss, UnknownException)
 279        STD_EXCEPTION(0x1200, DataTLBMiss, UnknownException)
 280        STD_EXCEPTION(0x1300, InstructionTLBError, UnknownException)
 281        STD_EXCEPTION(0x1400, DataTLBError, UnknownException)
 282
 283        STD_EXCEPTION(0x1500, Reserved5, UnknownException)
 284        STD_EXCEPTION(0x1600, Reserved6, UnknownException)
 285        STD_EXCEPTION(0x1700, Reserved7, UnknownException)
 286        STD_EXCEPTION(0x1800, Reserved8, UnknownException)
 287        STD_EXCEPTION(0x1900, Reserved9, UnknownException)
 288        STD_EXCEPTION(0x1a00, ReservedA, UnknownException)
 289        STD_EXCEPTION(0x1b00, ReservedB, UnknownException)
 290
 291        STD_EXCEPTION(0x1c00, DataBreakpoint, UnknownException)
 292        STD_EXCEPTION(0x1d00, InstructionBreakpoint, DebugException)
 293        STD_EXCEPTION(0x1e00, PeripheralBreakpoint, UnknownException)
 294        STD_EXCEPTION(0x1f00, DevPortBreakpoint, UnknownException)
 295
 296
 297        .globl  _end_of_vectors
 298_end_of_vectors:
 299
 300
 301        . = 0x2000
 302
 303/*
 304 * This code finishes saving the registers to the exception frame
 305 * and jumps to the appropriate handler for the exception.
 306 * Register r21 is pointer into trap frame, r1 has new stack pointer.
 307 */
 308        .globl  transfer_to_handler
 309transfer_to_handler:
 310        stw     r22,_NIP(r21)
 311        lis     r22,MSR_POW@h
 312        andc    r23,r23,r22
 313        stw     r23,_MSR(r21)
 314        SAVE_GPR(7, r21)
 315        SAVE_4GPRS(8, r21)
 316        SAVE_8GPRS(12, r21)
 317        SAVE_8GPRS(24, r21)
 318        mflr    r23
 319        andi.   r24,r23,0x3f00          /* get vector offset */
 320        stw     r24,TRAP(r21)
 321        li      r22,0
 322        stw     r22,RESULT(r21)
 323        mtspr   SPRG2,r22               /* r1 is now kernel sp */
 324        lwz     r24,0(r23)              /* virtual address of handler */
 325        lwz     r23,4(r23)              /* where to go when done */
 326        mtspr   SRR0,r24
 327        mtspr   SRR1,r20
 328        mtlr    r23
 329        SYNC
 330        rfi                             /* jump to handler, enable MMU */
 331
 332int_return:
 333        mfmsr   r28                     /* Disable interrupts */
 334        li      r4,0
 335        ori     r4,r4,MSR_EE
 336        andc    r28,r28,r4
 337        SYNC                            /* Some chip revs need this... */
 338        mtmsr   r28
 339        SYNC
 340        lwz     r2,_CTR(r1)
 341        lwz     r0,_LINK(r1)
 342        mtctr   r2
 343        mtlr    r0
 344        lwz     r2,_XER(r1)
 345        lwz     r0,_CCR(r1)
 346        mtspr   XER,r2
 347        mtcrf   0xFF,r0
 348        REST_10GPRS(3, r1)
 349        REST_10GPRS(13, r1)
 350        REST_8GPRS(23, r1)
 351        REST_GPR(31, r1)
 352        lwz     r2,_NIP(r1)             /* Restore environment */
 353        lwz     r0,_MSR(r1)
 354        mtspr   SRR0,r2
 355        mtspr   SRR1,r0
 356        lwz     r0,GPR0(r1)
 357        lwz     r2,GPR2(r1)
 358        lwz     r1,GPR1(r1)
 359        SYNC
 360        rfi
 361
 362/* Cache functions.
 363*/
 364        .globl  icache_enable
 365icache_enable:
 366        SYNC
 367        lis     r3, IDC_INVALL@h
 368        mtspr   IC_CST, r3
 369        lis     r3, IDC_ENABLE@h
 370        mtspr   IC_CST, r3
 371        blr
 372
 373        .globl  icache_disable
 374icache_disable:
 375        SYNC
 376        lis     r3, IDC_DISABLE@h
 377        mtspr   IC_CST, r3
 378        blr
 379
 380        .globl  icache_status
 381icache_status:
 382        mfspr   r3, IC_CST
 383        srwi    r3, r3, 31      /* >>31 => select bit 0 */
 384        blr
 385
 386        .globl  dcache_enable
 387dcache_enable:
 388#if 0
 389        SYNC
 390#endif
 391#if 1
 392        lis     r3, 0x0400              /* Set cache mode with MMU off */
 393        mtspr   MD_CTR, r3
 394#endif
 395
 396        lis     r3, IDC_INVALL@h
 397        mtspr   DC_CST, r3
 398#if 0
 399        lis     r3, DC_SFWT@h
 400        mtspr   DC_CST, r3
 401#endif
 402        lis     r3, IDC_ENABLE@h
 403        mtspr   DC_CST, r3
 404        blr
 405
 406        .globl  dcache_disable
 407dcache_disable:
 408        SYNC
 409        lis     r3, IDC_DISABLE@h
 410        mtspr   DC_CST, r3
 411        lis     r3, IDC_INVALL@h
 412        mtspr   DC_CST, r3
 413        blr
 414
 415        .globl  dcache_status
 416dcache_status:
 417        mfspr   r3, DC_CST
 418        srwi    r3, r3, 31      /* >>31 => select bit 0 */
 419        blr
 420
 421        .globl  dc_read
 422dc_read:
 423        mtspr   DC_ADR, r3
 424        mfspr   r3, DC_DAT
 425        blr
 426
 427/*
 428 * unsigned int get_immr (unsigned int mask)
 429 *
 430 * return (mask ? (IMMR & mask) : IMMR);
 431 */
 432        .globl  get_immr
 433get_immr:
 434        mr      r4,r3           /* save mask */
 435        mfspr   r3, IMMR        /* IMMR */
 436        cmpwi   0,r4,0          /* mask != 0 ? */
 437        beq     4f
 438        and     r3,r3,r4        /* IMMR & mask */
 4394:
 440        blr
 441
 442        .globl get_pvr
 443get_pvr:
 444        mfspr   r3, PVR
 445        blr
 446
 447
 448        .globl wr_ic_cst
 449wr_ic_cst:
 450        mtspr   IC_CST, r3
 451        blr
 452
 453        .globl rd_ic_cst
 454rd_ic_cst:
 455        mfspr   r3, IC_CST
 456        blr
 457
 458        .globl wr_ic_adr
 459wr_ic_adr:
 460        mtspr   IC_ADR, r3
 461        blr
 462
 463
 464        .globl wr_dc_cst
 465wr_dc_cst:
 466        mtspr   DC_CST, r3
 467        blr
 468
 469        .globl rd_dc_cst
 470rd_dc_cst:
 471        mfspr   r3, DC_CST
 472        blr
 473
 474        .globl wr_dc_adr
 475wr_dc_adr:
 476        mtspr   DC_ADR, r3
 477        blr
 478
 479/*------------------------------------------------------------------------------*/
 480
 481/*
 482 * void relocate_code (addr_sp, gd, addr_moni)
 483 *
 484 * This "function" does not return, instead it continues in RAM
 485 * after relocating the monitor code.
 486 *
 487 * r3 = dest
 488 * r4 = src
 489 * r5 = length in bytes
 490 * r6 = cachelinesize
 491 */
 492        .globl  relocate_code
 493relocate_code:
 494        mr      r1,  r3         /* Set new stack pointer                */
 495        mr      r9,  r4         /* Save copy of Global Data pointer     */
 496        mr      r10, r5         /* Save copy of Destination Address     */
 497
 498        mr      r3,  r5                         /* Destination Address  */
 499        lis     r4, CONFIG_SYS_MONITOR_BASE@h           /* Source      Address  */
 500        ori     r4, r4, CONFIG_SYS_MONITOR_BASE@l
 501        lwz     r5, GOT(__init_end)
 502        sub     r5, r5, r4
 503        li      r6, CONFIG_SYS_CACHELINE_SIZE           /* Cache Line Size      */
 504
 505        /*
 506         * Fix GOT pointer:
 507         *
 508         * New GOT-PTR = (old GOT-PTR - CONFIG_SYS_MONITOR_BASE) + Destination Address
 509         *
 510         * Offset:
 511         */
 512        sub     r15, r10, r4
 513
 514        /* First our own GOT */
 515        add     r14, r14, r15
 516        /* then the one used by the C code */
 517        add     r30, r30, r15
 518
 519        /*
 520         * Now relocate code
 521         */
 522
 523        cmplw   cr1,r3,r4
 524        addi    r0,r5,3
 525        srwi.   r0,r0,2
 526        beq     cr1,4f          /* In place copy is not necessary       */
 527        beq     7f              /* Protect against 0 count              */
 528        mtctr   r0
 529        bge     cr1,2f
 530
 531        la      r8,-4(r4)
 532        la      r7,-4(r3)
 5331:      lwzu    r0,4(r8)
 534        stwu    r0,4(r7)
 535        bdnz    1b
 536        b       4f
 537
 5382:      slwi    r0,r0,2
 539        add     r8,r4,r0
 540        add     r7,r3,r0
 5413:      lwzu    r0,-4(r8)
 542        stwu    r0,-4(r7)
 543        bdnz    3b
 544
 545/*
 546 * Now flush the cache: note that we must start from a cache aligned
 547 * address. Otherwise we might miss one cache line.
 548 */
 5494:      cmpwi   r6,0
 550        add     r5,r3,r5
 551        beq     7f              /* Always flush prefetch queue in any case */
 552        subi    r0,r6,1
 553        andc    r3,r3,r0
 554        mr      r4,r3
 5555:      dcbst   0,r4
 556        add     r4,r4,r6
 557        cmplw   r4,r5
 558        blt     5b
 559        sync                    /* Wait for all dcbst to complete on bus */
 560        mr      r4,r3
 5616:      icbi    0,r4
 562        add     r4,r4,r6
 563        cmplw   r4,r5
 564        blt     6b
 5657:      sync                    /* Wait for all icbi to complete on bus */
 566        isync
 567
 568/*
 569 * We are done. Do not return, instead branch to second part of board
 570 * initialization, now running from RAM.
 571 */
 572
 573        addi    r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
 574        mtlr    r0
 575        blr
 576
 577in_ram:
 578
 579        /*
 580         * Relocation Function, r14 point to got2+0x8000
 581         *
 582         * Adjust got2 pointers, no need to check for 0, this code
 583         * already puts a few entries in the table.
 584         */
 585        li      r0,__got2_entries@sectoff@l
 586        la      r3,GOT(_GOT2_TABLE_)
 587        lwz     r11,GOT(_GOT2_TABLE_)
 588        mtctr   r0
 589        sub     r11,r3,r11
 590        addi    r3,r3,-4
 5911:      lwzu    r0,4(r3)
 592        add     r0,r0,r11
 593        stw     r0,0(r3)
 594        bdnz    1b
 595
 596        /*
 597         * Now adjust the fixups and the pointers to the fixups
 598         * in case we need to move ourselves again.
 599         */
 6002:      li      r0,__fixup_entries@sectoff@l
 601        lwz     r3,GOT(_FIXUP_TABLE_)
 602        cmpwi   r0,0
 603        mtctr   r0
 604        addi    r3,r3,-4
 605        beq     4f
 6063:      lwzu    r4,4(r3)
 607        lwzux   r0,r4,r11
 608        add     r0,r0,r11
 609        stw     r10,0(r3)
 610        stw     r0,0(r4)
 611        bdnz    3b
 6124:
 613clear_bss:
 614        /*
 615         * Now clear BSS segment
 616         */
 617        lwz     r3,GOT(__bss_start)
 618        lwz     r4,GOT(_end)
 619
 620        cmplw   0, r3, r4
 621        beq     6f
 622
 623        li      r0, 0
 6245:
 625        stw     r0, 0(r3)
 626        addi    r3, r3, 4
 627        cmplw   0, r3, r4
 628        bne     5b
 6296:
 630
 631        mr      r3, r9          /* Global Data pointer          */
 632        mr      r4, r10         /* Destination Address          */
 633        bl      board_init_r
 634
 635        /*
 636         * Copy exception vector code to low memory
 637         *
 638         * r3: dest_addr
 639         * r7: source address, r8: end address, r9: target address
 640         */
 641        .globl  trap_init
 642trap_init:
 643        lwz     r7, GOT(_start)
 644        lwz     r8, GOT(_end_of_vectors)
 645
 646        li      r9, 0x100               /* reset vector always at 0x100 */
 647
 648        cmplw   0, r7, r8
 649        bgelr                           /* return if r7>=r8 - just in case */
 650
 651        mflr    r4                      /* save link register           */
 6521:
 653        lwz     r0, 0(r7)
 654        stw     r0, 0(r9)
 655        addi    r7, r7, 4
 656        addi    r9, r9, 4
 657        cmplw   0, r7, r8
 658        bne     1b
 659
 660        /*
 661         * relocate `hdlr' and `int_return' entries
 662         */
 663        li      r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
 664        li      r8, Alignment - _start + EXC_OFF_SYS_RESET
 6652:
 666        bl      trap_reloc
 667        addi    r7, r7, 0x100           /* next exception vector        */
 668        cmplw   0, r7, r8
 669        blt     2b
 670
 671        li      r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
 672        bl      trap_reloc
 673
 674        li      r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
 675        bl      trap_reloc
 676
 677        li      r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
 678        li      r8, SystemCall - _start + EXC_OFF_SYS_RESET
 6793:
 680        bl      trap_reloc
 681        addi    r7, r7, 0x100           /* next exception vector        */
 682        cmplw   0, r7, r8
 683        blt     3b
 684
 685        li      r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
 686        li      r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
 6874:
 688        bl      trap_reloc
 689        addi    r7, r7, 0x100           /* next exception vector        */
 690        cmplw   0, r7, r8
 691        blt     4b
 692
 693        mtlr    r4                      /* restore link register        */
 694        blr
 695
 696        /*
 697         * Function: relocate entries for one exception vector
 698         */
 699trap_reloc:
 700        lwz     r0, 0(r7)               /* hdlr ...                     */
 701        add     r0, r0, r3              /*  ... += dest_addr            */
 702        stw     r0, 0(r7)
 703
 704        lwz     r0, 4(r7)               /* int_return ...               */
 705        add     r0, r0, r3              /*  ... += dest_addr            */
 706        stw     r0, 4(r7)
 707
 708        sync
 709        isync
 710
 711        blr
 712