加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

MPC8349E-mITXE的U-Boot汇编start.S分析笔记(转) .

发布时间:2020-12-15 06:14:06 所属栏目:百科 来源:网络整理
导读:1 /* 2 * // MPC8349E-mITX ltib U-Boot cpu/mpc83xx/start.S --- by starby 3 * 4 * Copyright (C) 1998 Dan Malek 5 * Copyright (C) 1999 Magnus Damm 6 * Copyright (C) 2000,2001,2002 Wolfgang Denk 7 * Copyright (C) Freescale Semiconductor,Inc. 2
1 /*
   2 * // MPC8349E-mITX ltib U-Boot cpu/mpc83xx/start.S --- by starby
   3 *
   4 * Copyright (C) 1998 Dan Malek
   5 * Copyright (C) 1999 Magnus Damm
   6 * Copyright (C) 2000,2001,2002 Wolfgang Denk
   7 * Copyright (C) Freescale Semiconductor,Inc. 2004,2006. All rights reserved.
   8 *
   9 * See file CREDITS for list of people who contributed to this
   10 * project.
   11 *
   12 * This program is free software; you can redistribute it and/or
   13 * modify it under the terms of the GNU General Public License as
   14 * published by the Free Software Foundation; either version 2 of
   15 * the License,or (at your option) any later version.
   16 *
   17 * This program is distributed in the hope that it will be useful,
   18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
   19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
   20 * GNU General Public License for more details.
   21 *
   22 * You should have received a copy of the GNU General Public License
   23 * along with this program; if not,write to the Free Software
   24 * Foundation,Inc.,59 Temple Place,Suite 330,Boston,
   25 * MA 02111-1307 USA
   26 */
   27 // 采用大端模式的32位处理器(如基于e300核的MPC8349),将其寄存器的最高位(msb)定义为0,最低位(lsb)为31;
   28 // 而采用小端模式的32位处理器,将其寄存器的最高位定义位31,低位地址定义为0.
   29
   30 /*
   31 * U-Boot - Startup Code for MPC83xx PowerPC based Embedded Boards
   32 */
   33
   34 #include
   35 #include
   36 #include
   37
   38 #define CONFIG_83XX 1 /* needed for Linux kernel header files*/
   39 #define _LINUX_CONFIG_H 1 /* avoid reading Linux autoconf.h file */
   40
   41 #include // 此文件定义寄存器相关,异常相关函数等
   42 #include
   43
   44 #include
   45 #include
   46
   47 #ifndef CONFIG_IDENT_STRING
   48 #define CONFIG_IDENT_STRING "MPC83XX"
   49 #endif
   50
   51 /* We don't want the MMU yet.
   52 */
   53 #undef MSR_KERNEL
   54
   55 /*
   56 * Floating Point enable,Machine Check and Recoverable Interr.
   57 */
   58 #ifdef DEBUG
   59 #define MSR_KERNEL (MSR_FP|MSR_RI)
   60 #else
   61 #define MSR_KERNEL (MSR_FP|MSR_ME|MSR_RI) // 浮点使能 | 机器检查使能 | 可恢复中断使能
   62 #endif
   63
   64 /*
   65 * Set up GOT: Global Offset Table
   66 *
   67 * Use r14 to access the GOT
   68 */
   69 // GOT相关定义在include/ppc_asm.tmpl中定义.
   70 // #define START_GOT
   71 // .section ".got2","aw";
   72 // .LCTOC1 = .+32768 // .LCTOC1 = 当前位置(.got2) + 0x8000
   73 // #define GOT_ENTRY(NAME) .L_ ## NAME = . - .LCTOC1 ; .long NAME
   74 // #define END_GOT .text
   75 // #define GOT(NAME) .L_ ## NAME (r14)
   76 // GOT即全局偏移量表,是为了实现位置无关PIC(position-independent)的代码.
   77 // 下面的宏指令(从START_GOT到END_GOT)定义了.got2段,在这个段里定义了可供调用的
   78 // 全局表,4字节存储每个表项的值,此值其实就是"NAME" symbol对应的编译时的值(地址)。
   79 // GET_GOT宏的目的是为了初始化r14寄存器,在此宏中通过计算得到了.got2表"起始地址"
   80 // 值(.LCTOC1)并存放在r14中。
   81 // GOT(NAME)宏通过计算r14和.got2表项偏移地址得到GOT表中该表项的地址,其中存储NAME符号的值(地址)
   82 // GOT表项可修改的。在u-boot实现代码搬运后修改GOT表,实现PIC位置无关.
   83 // GOT_ENTRY添加一个表项到GOT表中.定义了一个本地label .L_(NAME)给as用。
   84 // .LCTOC1是个symbol,as中的LOCAL symbol的命名规范,理解为常值(.got2 + 0x8000)
   85 // 下面GOT_ENTRY(NAME)中的NAME值参见u-boot.lds
   86 START_GOT
   87 GOT_ENTRY(_GOT2_TABLE_)
   88 GOT_ENTRY(_FIXUP_TABLE_)
   89
   90 GOT_ENTRY(_start)
   91 GOT_ENTRY(_start_of_vectors)
   92 GOT_ENTRY(_end_of_vectors)
   93 GOT_ENTRY(transfer_to_handler)
   94
   95 GOT_ENTRY(__init_end)
   96 GOT_ENTRY(_end)
   97 GOT_ENTRY(__bss_start)
   98 END_GOT
   99
   100 /*
   101 * Version string - must be in data segment because MPC83xx uses the
   102 * first 256 bytes for the Hard Reset Configuration Word table (see
   103 * below). Similarly,can't have the U-Boot Magic Number as the first
   104 * thing in the image - don't know how this will affect the image tools,
   105 * but I guess I'll find out soon.
   106 */
   107 .data
   108 .globl version_string
   109 version_string:
   110 .ascii U_BOOT_VERSION // version.h中定义
   111 .ascii " (",__DATE__," - ",__TIME__,")"
   112 .ascii " ",CONFIG_IDENT_STRING,""
   113
   114 .text
   115 #define _HRCW_TABLE_ENTRY(w)
   116 .fill 8,1,(((w)>>24)&0xff); // 在文本段开始填入w的高8bit字节,重复8次
   117 .fill 8,(((w)>>16)&0xff);
   118 .fill 8,(((w)>> 8)&0xff);
   119 .fill 8,(((w) )&0xff)
   120
   121 _HRCW_TABLE_ENTRY(CFG_HRCW_LOW) // 在MPC8349ITX.h中定义CFG_HRCW_LOW= 0x04040000
   122 _HRCW_TABLE_ENTRY(CFG_HRCW_HIGH) // 在MPC8349ITX.h中定义CFG_HRCW_HIGH=0xA460A000
   123 // 复位配置字低字LRCW(32bit)有效字节地址为 0x00,0x08,0x10,0x18
   124 // 复位配置字高字HRCW(32bit)有效字节地址为 0x20,0x28,0x30,0x38
   125 #ifndef CONFIG_DEFAULT_IMMR // IMMR复位地址为0xFF400000
   126 #error CONFIG_DEFAULT_IMMR must be defined
   127 #endif /* CFG_DEFAULT_IMMR */
   128 #ifndef CFG_IMMRBAR // MPC8349ITX.h中定义为0xE0000000
   129 #define CFG_IMMRBAR CONFIG_DEFAULT_IMMR
   130 #endif /* CFG_IMMRBAR */
   131
   132 /*
   133 * After configuration,a system reset exception is executed using the
   134 * vector at offset 0x100 relative to the base set by MSR[IP]. If
   135 * MSR[IP] is 0,the base address is 0x00000000. If MSR[IP] is 1,the
   136 * base address is 0xfff00000. In the case of a Power On Reset or Hard
   137 * Reset,the value of MSR[IP] is determined by the CIP field in the
   138 * HRCW.
   139 * // 根据上面RCW,MSR[IP] 为 1,系统复位异常向量基地址为 0xFFF00000
   140 * // 同时 RCW[BMS] 为 1,Boot Memory Space为0xFF800000 ~ 0xFFFFFFFF
   141 * // 根据 RCW[BMS] 为 1,LBLAWBAR0复位值为0xFF800.
   142 * Other bits in the HRCW set up the Base Address and Port Size in BR0.
   143 * This determines the location of the boot ROM (flash or EPROM) in the
   144 * processor's address space at boot time. As long as the HRCW is set up
   145 * so that we eventually end up executing the code below when the
   146 * processor executes the reset exception,the actual values used should
   147 * not matter.
   148 *
   149 * Once we have got here,the address mask in OR0 is cleared so that the
   150 * bottom 32K of the boot ROM is effectively repeated all throughout the
   151 * processor's address space,after which we can jump to the absolute
   152 * address at which the boot ROM was linked at compile time,and proceed
   153 * to initialise the memory controller without worrying if the rug will
   154 * be pulled out from under us,so to speak (it will be fine as long as
   155 * we configure BR0 with the same boot ROM link address).
   156 */
   157 . = EXC_OFF_SYS_RESET /* . = 0x100 */ //当前位置定位在0x100(PowerPC复位向量地址)
   158
   159 .globl _start // 根据u-boot.lds 指定程序入口_start
   160 _start: /* time t 0 */
   161 li r21,BOOTFLAG_COLD /* Normal Power-On: Boot from FLASH*/
   162 // BOOTFLAG_COLD=1 , r21中存放启动类型
   163 nop
   164 b boot_cold // 跳转到boot_cold
   165
   166 . = EXC_OFF_SYS_RESET + 0x10 // 当前位置定位在 0x110
   167
   168 .globl _start_warm
   169 _start_warm:
   170 li r21,BOOTFLAG_WARM /* Software reboot */ // BOOTFLAG_WARM=2
   171 b boot_warm // 无条件分支跳转到boot_warm
   172
   173 boot_cold: /* time t 3 */
   174 lis r4,CONFIG_DEFAULT_IMMR@h // 将CONFIG_DEFAULT_IMMR的高16bit(bit0 ~ 15)带符号赋给r4,并左移16bit
   175 nop
   176 boot_warm: /* time t 5 */
   177 mfmsr r5 /* save msr contents */ // 将机器状态寄存器msr保存到r5
   178 // 将32位立即数赋给32位寄存器通常用如下两个命令分高低16位两步赋予
   179 lis r3,CFG_IMMRBAR@h // 将CFG_IMMRBAR的高16bit(bit0 ~ 15)带符号赋给r3,并左移16bit,r3低16bit为0
   180 ori r3,r3,CFG_IMMRBAR@l // 将r3与立即数CFG_IMMRBAR的低16bit(bit16 ~ 31)进行逻辑或,结果赋给r3
   181 stw r3,IMMRBAR(r4) // mpc83xx.h中定义IMMRBAR=0x0000. r4里的内容为CONFIG_DEFAULT_IMMR( 0xFF400000),
   182 // 有效地址为IMMRBAR+CONFIG_DEFAULT_IMMR = 0xFF400000,r3里的内容为CFG_IMMRBAR( 0xE0000000),
   183 // 将r3的内容存储到有效地址的空间中,即将内部存储映射寄存器IMMR基地址由0xFF400000改为0xE0000000
   184 // cpu复位后的内部存储映射寄存器IMMR为CONFIG_DEFAULT_IMMR,IMMR定义了内部存储映射寄存器1M空间的基地址
   185 // 这个地址对应的寄存器也即是IMMR自己
   186
   187
   188 /* Initialise the E300 processor core */
   189 /*------------------------------------------*/
   190
   191 bl init_e300_core // 跳转到init_e300_core,返回后继续向下执行
   192 // bl xxxxxx 指令是无条件相对地址跳转(当前地址加上偏移地址作目的地址)
   193
   194 #ifndef CFG_RAMBOOT // undef CFG_RAMBOOT
   195
   196 /* Inflate flash location so it appears everywhere,calculate */
   197 /* the absolute address in final location of the FLASH,jump */
   198 /* there and deflate the flash size back to minimal size */
   199 /*------------------------------------------------------------*/
   200 bl map_flash_by_law1 // 跳转到map_flash_by_law1,实现将Local BUS window映射为CFG_FLASH_BASE,16M大小
   201
   202 // uboot在RAM中的地址为CFG_MONITOR_BASE=TEXT_BASE=0xFEF00000,下面将实现跳转到直接在flash中运行代码。
   203 // 跳转到flash中会继续运行,而不是从头运行,故需计算下条指令相对地址in_flash - _start + EXC_OFF_SYS_RESET
   204 // 此相对地址和CFG_MONITOR_BASE相加就是指令代码在flash中的位置。
   205 lis r4,(CFG_MONITOR_BASE)@h // 将CFG_MONITOR_BASE=TEXT_BASE=0xFEF00000赋给r4
   206 ori r4,r4,(CFG_MONITOR_BASE)@l
   207 addi r5,in_flash - _start + EXC_OFF_SYS_RESET // r4(uboot在RAM中的基址)与立即数(指令相对地址)的和存到r5
   208 mtlr r5 // 将r5(flash中下条uboot的指令地址)复制给链接寄存器lr.
   209 blr // 跳转到链接寄存器中指向的地址(flash中下条uboot的指令地址(0xFEF00000+in_flash),即在flash中执行in_flash下面的部分
   210 in_flash: // 若MSR[BMS]=1,则之前的IP值为0xFFF*,而此后的IP值为0xFEF*
   211 #if 1 /* Remapping flash with LAW0. */
   212 bl remap_flash_by_law0 // 跳转到remap_flash_by_law0
   213 #endif
   214 #endif /* CFG_RAMBOOT */
   215
   216 bl setup_stack_in_data_cache_on_r1 // 跳转到setup_stack_in_data_cache_on_r1
   217
   218 /* let the C-code set up the rest */
   219 /* */
   220 /* Be careful to keep code relocatable & stack humble */
   221 /*------------------------------------------------------*/
   222
   223 GET_GOT /* initialize GOT access */
   224 // 在ppc_asm.tmpl中定义
   225 // #define GET_GOT
   226 // bl 1f ; // 跳转到后面的符号1处,将下条指令的地址给连接寄存器lr
   227 // .text 2 ;
   228 // 0: .long .LCTOC1-1f ; // 计算 .LCTOC1值 - 符号1处的地址,并存储
   229 // .text ;
   230 // 1: mflr r14 ; // 将链接寄存器lr值(即符号1所处的地址)赋给r14
   231 // lwz r0,0b-1b(r14) ; // 将(0b-1b) + r14处存储的值赋给r0 即将符号0处的值加载给r0
   232 // add r14,r0,r14 ; // r14 <= r0 + r14即得到.LCTOC1的值(.got2 + 0x8000)
   233 // 通过计算得到.got2段(即全局偏移表GOT)的"起始地址" .LCTOC1值,并存放在r14寄存器中。
   234
   235
   236 /* r3: IMMR */
   237 // 下面r3存放的是IMMR的值,PowerPC的ABI规定r3-r10作为函数传递参数使用,IMMR地址作为cpu_init_f的参数
   238 // 该函数在cpu/mpc83xx/cpu_init.c中,该文件还有一个函数cpu_init_r作为第二阶段的初始化函数
   239 // cpu_init_f(volatile immap_t *im)函数中设置全局数据指针gd(r29),并初始化全局数据,
   240 // 对IMMR一些寄存器设置,实现中断仲裁、复位寄存器、窗口映射和时钟模块等的设置
   241 // immap_t结构体及相关结构体在include/asm_ppc/immap_83xx.h中定义
   242 // 全局数据结构体gd_t定义在include/asm_ppc/globl_data.h中
   243 // 板子信息结构体bd_t定义在include/asm_ppc/u-boot.h中
   244 lis r3,CFG_IMMRBAR@h // r3中存储CFG_IMMRBAR(0xE0000000)
   245 /* run low-level CPU init code (in Flash)*/
   246 bl cpu_init_f // 跳转到cpu_init_f(cpu/mpc83xx.c)
   247
   248 /* r3: BOOTFLAG */
   249 // 将复位类型传递r3中作为参数值,board_init_f -> relocate_code(该函数在下面,负责把代码
   250 // 从flash搬运到sdram中) -> cpu_init_r -> 然后再执行main_loop等待输入.
   251 mr r3,r21 // 将复位模式赋给r3
   252 /* run 1st part of board init code (in Flash)*/
   253 bl board_init_f // 跳转到board_init_f(lib_ppc/board.c)
   254
   255 /*
   256 * Vector Table
   257 */
   258 // 向量表: 设置中断向量. STD_EXCEPTION是宏定义(include/ppc_asm.tmpl)
   259 // ppc_asm.tmpl中的EXCEPTION_PROLOG初始化中断堆栈,现场保存等
   260 // STD_EXCEPTION是一系列汇编代码。计算出GOT表项中transfer_to_handler的值.
   261 // 第三个参数的代码一般存在cpu/mpc83xx/traps.c中,是异常处理handler主程序代码。
   262 // 计算出异常处理主程序的代码位置,以便在执行transfer_to_handler后进入执行。
   263 // 异常: 是一个事件,可能会让处理器产生中断。异常是由来自内部和外围、指令等的信号产生的。
   264 // 中断: 是一个动作,即处理器保存现场(MSR,下条指令地址等),然后到相应的中断处理地址执行指令。
   265
   266 .globl _start_of_vectors
   267 _start_of_vectors:
   268
   269 /* Machine check */ // STD_EXCEPTION用来初始化中断处理函数MachineCheck.
   270 STD_EXCEPTION(0x200,MachineCheck,MachineCheckException)
   271
   272 /* Data Storage exception. */
   273 STD_EXCEPTION(0x300,DataStorage,UnknownException)
   274
   275 /* Instruction Storage exception. */
   276 STD_EXCEPTION(0x400,InstStorage,UnknownException)
   277
   278 /* External Interrupt exception. */
   279 #ifndef FIXME
   280 STD_EXCEPTION(0x500,ExtInterrupt,external_interrupt)
   281 #endif
   282
   283 /* Alignment exception. */ // 对齐中断
   284 . = 0x600
   285 Alignment:
   286 EXCEPTION_PROLOG // ppc_asm.tmpl的宏定义,异常入口代码,可运行在无地址转换功能时
   287 mfspr r4,DAR // r4 <= DAR,数据地址寄存器DAR(SPR 0x13)[include/asm_ppc/processor.h]
   288 stw r4,_DAR(r21) // _DAR(180) _DSISR(184) _LINK(160) 在include/ppc_defs.h中定义
   289 mfspr r5,DSISR // r5 <= DSISR,数据存储中断状态寄存器DSISR(0x012)[include/asm_ppc/processor.h]
   290 stw r5,_DSISR(r21)
   291 addi r3,r1,STACK_FRAME_OVERHEAD // r3 <= r1 + 16,STACK_FRAME_OVERHEAD(16)栈帧结构大小
   292 li r20,MSR_KERNEL
   293 rlwimi r20,r23,16,16 /* copy EE bit from saved MSR */ // 保存msr的EE和IP位以备恢复
   294 rlwimi r20,25,25 /* copy IP bit from saved MSR */
   295 lwz r6,GOT(transfer_to_handler) // lwz r6,.L_transfer_to_handler(r14) ppc_asm.tmpl定义GOT(NAME)
   296 mtlr r6 // 全局偏移表项transfer_to_handler的值 r6赋给链接寄存器lr
   297 blrl // blrl == bclrl 20,0 跳转指令。发生跳转,目标地址为链接寄存器LR || 0b00
   298 // 同时分支指令后的有效地址(当前指令地址加4)存储到链接寄存器lr中
   299 .L_Alignment:
   300 .long AlignmentException - _start + EXC_OFF_SYS_RESET // 计算异常处理程序AlignmentException的绝对地址
   301 .long int_return - _start + EXC_OFF_SYS_RESET // 异常处理返回后恢复现场程序int_return的绝对地址
   302 // 异常处理程序AlignmentException函数在cpu/mpc83xx/traps.c中。
   303 // transfer_to_handler代码进行异常处理前的现场保存工作。
   304 // int_return代码进行异常处理后的现场恢复工作。
   305
   306 /* Program check exception */
   307 . = 0x700
   308 ProgramCheck:
   309 EXCEPTION_PROLOG // ppc_asm.tmpl的宏定义,异常入口代码,可运行在无地址转换功能时
   310 addi r3,STACK_FRAME_OVERHEAD // 16
   311 li r20,MSR_KERNEL
   312 rlwimi r20,16 /* copy EE bit from saved MSR */
   313 rlwimi r20,25 /* copy IP bit from saved MSR */
   314 lwz r6,GOT(transfer_to_handler)
   315 mtlr r6
   316 blrl
   317 .L_ProgramCheck:
   318 .long ProgramCheckException - _start + EXC_OFF_SYS_RESET
   319 .long int_return - _start + EXC_OFF_SYS_RESET
   320
   321 STD_EXCEPTION(0x800,FPUnavailable,UnknownException)
   322
   323 /* I guess we could implement decrementer,and may have
   324 * to someday for timekeeping.
   325 */
   326 STD_EXCEPTION(0x900,Decrementer,timer_interrupt)
   327
   328 STD_EXCEPTION(0xa00,Trap_0a,UnknownException)
   329 STD_EXCEPTION(0xb00,Trap_0b,UnknownException)
   330 STD_EXCEPTION(0xc00,SystemCall,UnknownException)
   331 STD_EXCEPTION(0xd00,SingleStep,UnknownException)
   332
   333 STD_EXCEPTION(0xe00,Trap_0e,UnknownException)
   334 STD_EXCEPTION(0xf00,Trap_0f,UnknownException)
   335
   336 STD_EXCEPTION(0x1000,InstructionTLBMiss,UnknownException)
   337 STD_EXCEPTION(0x1100,DataLoadTLBMiss,UnknownException)
   338 STD_EXCEPTION(0x1200,DataStoreTLBMiss,UnknownException)
   339 #ifdef DEBUG
   340 . = 0x1300
   341 /*
   342 * This exception occurs when the program counter matches the
   343 * Instruction Address Breakpoint Register (IABR).
   344 *
   345 * I want the cpu to halt if this occurs so I can hunt around
   346 * with the debugger and look at things.
   347 *
   348 * When DEBUG is defined,both machine check enable (in the MSR)
   349 * and checkstop reset enable (in the reset mode register) are
   350 * turned off and so a checkstop condition will result in the cpu
   351 * halting.
   352 *
   353 * I force the cpu into a checkstop condition by putting an illegal
   354 * instruction here (at least this is the theory).
   355 *
   356 * well - that didnt work,so just do an infinite loop!
   357 */
   358 1: b 1b // 无限循环
   359 #else
   360 STD_EXCEPTION(0x1300,InstructionBreakpoint,DebugException)
   361 #endif
   362 STD_EXCEPTION(0x1400,SMI,UnknownException)
   363
   364 STD_EXCEPTION(0x1500,Trap_15,UnknownException)
   365 STD_EXCEPTION(0x1600,Trap_16,UnknownException)
   366 STD_EXCEPTION(0x1700,Trap_17,UnknownException)
   367 STD_EXCEPTION(0x1800,Trap_18,UnknownException)
   368 STD_EXCEPTION(0x1900,Trap_19,UnknownException)
   369 STD_EXCEPTION(0x1a00,Trap_1a,UnknownException)
   370 STD_EXCEPTION(0x1b00,Trap_1b,UnknownException)
   371 STD_EXCEPTION(0x1c00,Trap_1c,UnknownException)
   372 STD_EXCEPTION(0x1d00,Trap_1d,UnknownException)
   373 STD_EXCEPTION(0x1e00,Trap_1e,UnknownException)
   374 STD_EXCEPTION(0x1f00,Trap_1f,UnknownException)
   375 STD_EXCEPTION(0x2000,Trap_20,UnknownException)
   376 STD_EXCEPTION(0x2100,Trap_21,UnknownException)
   377 STD_EXCEPTION(0x2200,Trap_22,UnknownException)
   378 STD_EXCEPTION(0x2300,Trap_23,UnknownException)
   379 STD_EXCEPTION(0x2400,Trap_24,UnknownException)
   380 STD_EXCEPTION(0x2500,Trap_25,UnknownException)
   381 STD_EXCEPTION(0x2600,Trap_26,UnknownException)
   382 STD_EXCEPTION(0x2700,Trap_27,UnknownException)
   383 STD_EXCEPTION(0x2800,Trap_28,UnknownException)
   384 STD_EXCEPTION(0x2900,Trap_29,UnknownException)
   385 STD_EXCEPTION(0x2a00,Trap_2a,UnknownException)
   386 STD_EXCEPTION(0x2b00,Trap_2b,UnknownException)
   387 STD_EXCEPTION(0x2c00,Trap_2c,UnknownException)
   388 STD_EXCEPTION(0x2d00,Trap_2d,UnknownException)
   389 STD_EXCEPTION(0x2e00,Trap_2e,UnknownException)
   390 STD_EXCEPTION(0x2f00,Trap_2f,UnknownException)
   391
   392
   393 .globl _end_of_vectors
   394 _end_of_vectors: // 异常向量结束地址
   395
   396 . = 0x3000
   397
   398 /*
   399 * This code finishes saving the registers to the exception frame
   400 * and jumps to the appropriate handler for the exception.
   401 * Register r21 is pointer into trap frame,r1 has new stack pointer.
   402 */
   403 .globl transfer_to_handler // 保存现场
   404 transfer_to_handler:
   405 stw r22,_NIP(r21) // include/asm-ppc/ptrace.h中_NIP为144
   406 lis r22,MSR_POW@h // r22的第13[POW]位为1,其余为0
   407 andc r23,r22 // 保存r23的第13[POW]位,清除其余位,影响CR
   408 stw r23,_MSR(r21) // _MSR为148,保存r23
   409 SAVE_GPR(7,r21) // SAVE_?GPR定义在ppc_asm.tmpl中. #define SAVE_GPR(n,base) stw n,GPR0+4*(n)(base)
   410 SAVE_4GPRS(8,r21)
   411 SAVE_8GPRS(12,r21)
   412 SAVE_8GPRS(24,r21)
   413 mflr r23 // r23 <= lr
   414 andi. r24,0x3f00 /* get vector offset */
   415 stw r24,TRAP(r21) // TRAP=176,
   416 li r22,0 // r22 <= 0
   417 stw r22,RESULT(r21) // RESULT=188,
   418 lwz r24,0(r23) /* virtual address of handler */
   419 lwz r23,4(r23) /* where to go when done */
   420 mtspr SRR0,r24 // 为防止程序因复位或中断等跑飞,应在使能外部中断前将
   421 mtspr SRR1,r20
   422 mtlr r23 // lr <= r23
   423 SYNC // sync ; isync
   424 rfi /* jump to handler,enable MMU */
   425
   426 int_return:
   427 mfmsr r28 /* Disable interrupts */
   428 li r4,0 // 将r4清零
   429 ori r4,MSR_EE // 将r4的第16bit置1 MSR[EE]=1
   430 andc r28,r28,r4 // 保留r28的第16bit[EE]位不变
   431 SYNC /* Some chip revs need this... */
   432 mtmsr r28 // 将r28赋给msr. MSR[EE] 外部中断使能不变
   433 SYNC
   434 lwz r2,_CTR(r1)
   435 lwz r0,_LINK(r1)
   436 mtctr r2 // 将r2赋给计数寄存器ctr
   437 mtlr r0 // 将r0赋给链接寄存器lr
   438 lwz r2,_XER(r1)
   439 lwz r0,_CCR(r1)
   440 mtspr XER,r2
   441 mtcrf 0xFF,r0
   442 REST_10GPRS(3,r1)
   443 REST_10GPRS(13,r1)
   444 REST_8GPRS(23,r1)
   445 REST_GPR(31,r1)
   446 lwz r2,_NIP(r1) /* Restore environment */
   447 lwz r0,_MSR(r1)
   448 mtspr SRR0,r2
   449 mtspr SRR1,r0
   450 lwz r0,GPR0(r1)
   451 lwz r2,GPR2(r1)
   452 lwz r1,GPR1(r1)
   453 SYNC
   454 rfi // 中断返回
   455
   456 /*
   457 * This code initialises the E300 processor core
   458 * (conforms to PowerPC 603e spec)
   459 * Note: expects original MSR contents to be in r5.
   460 */
   461 .globl init_e300_core
   462 init_e300_core: /* time t 10 */
   463 /* Initialize machine status; enable machine check interrupt */
   464 /*-----------------------------------------------------------*/
   465 // 将MSR_KERNEL赋给r3,原始msr保存在r5中
   466 li r3,MSR_KERNEL /* Set ME and RI flags */
   467 // 下面这个指令将r5左旋0位,25-25bit置1,其他位置0再与左旋数据进行逻辑与,
   468 // 将此结果插入r3. (rlwimi 左旋立即数,屏蔽插入)
   469 // 此指令保证赋值后msr和原始msr的25bit[IP]保持一致。MSR[ME],MSR[RI],MSR[IP]位为1,其余为0
   470 // MSR[EE]为0,禁止外部中断,系统管理中断及decrementer中断.其余位为0,也即禁止相应的中断
   471 // MSR[IR],MSR[DR]为0,禁止指令和数据地址转换(关闭MMU)。只运行ME机器检查中断和RI可恢复中断
   472 rlwimi r3,r5,25 /* preserve IP bit set by HRCW */
   473 #ifdef DEBUG
   474 rlwimi r3,21,22 /* debugger might set SE & BE bits */ // 单步中断&跳转跟踪
   475 #endif
   476 SYNC /* Some chip revs need this... */ // 指令sync,isync
   477 mtmsr r3 // 将r3赋给机器状态寄存器msr
   478 SYNC
   479 mtspr SRR1,r3 /* Make SRR1 match MSR */
   480 // 同样将r3赋给srr1(Save and Restore Register 1)
   481
   482
   483 lis r3,CFG_IMMRBAR@h // 将CFG_IMMRBAR 赋给r3(高16bit同 CFG_IMMRBAR@h,低16bit为0)
   484 #if defined(CONFIG_WATCHDOG) // CONFIG_WATCHDOG未定义
   485 /* Initialise the Wathcdog values and reset it (if req) */
   486 /*------------------------------------------------------*/
   487 lis r4,CFG_WATCHDOG_VALUE
   488 ori r4,(SWCRR_SWEN | SWCRR_SWRI | SWCRR_SWPR) // 系统看门狗控制寄存器SWSRR(偏移0x0_0204)设置
   489 stw r4,SWCRR(r3) // r3为IMMR基地址
   490
   491 /* and reset it */
   492
   493 lis r4,0x556C
   494 sth r4,SWSRR@l(r3)
   495 lis r4,0xAA39
   496 sth r4,SWSRR@l(r3)
   497 #else
   498 /* Disable Wathcdog */
   499 /*-------------------*/
   500 xor r4,r4 // r4清零,配置系统看门狗控制寄存器,禁止看门狗
   501 stw r4,SWCRR(r3) // CFG_IMMRBAR+0x204
   502 #endif /* CONFIG_WATCHDOG */
   503
   504 /* Initialize the Hardware Implementation-dependent Registers */
   505 /* HID0 also contains cache control */
   506 /*------------------------------------------------------*/
   507
   508 lis r3,CFG_HID0_INIT@h // MPC8349ITX.h定义CFG_HID0_INIT为0x0,r3 <= CFG_HID0_INIT
   509 ori r3,CFG_HID0_INIT@l
   510 SYNC // ppc_asm.tmpl中#define SYNC sync; isync
   511 mtspr HID0,r3 // 将r3赋给专用寄存器HID0(SPR 0x3F0)
   512
   513 lis r3,CFG_HID0_FINAL@h // MPC8349ITX.h定义CFG_HID0_FINAL为0x0
   514 ori r3,CFG_HID0_FINAL@l
   515 SYNC
   516 mtspr HID0,r3 // 将r3赋给专用寄存器HID0(SPR 0x3F0)
   517
   518 lis r3,CFG_HID2@h // MPC8349ITX.h定义CFG_HID2为0x0
   519 ori r3,CFG_HID2@l
   520 SYNC
   521 mtspr HID2,r3 // 将r3赋给专用寄存器HID2(SPR 0x3F3)
   522
   523 // e300支持3中类型的地址转换: 页地址转换、块地址转换和实模式(即硬件转换机制关闭,
   524 // 比如MSR[IR]=0或MSR[DR]=0,使用有效地址EA用作物理地址). 前两者都先通过页表或BAT
   525 // 生成中间的虚拟地址,然后再通过查询将虚拟地址转换为物理地址。
   526
   527 /* clear all BAT's*/
   528 /*----------------------------------*/
   529 // 块地址转换BAT实现了大于一页的有效地址范围到一个连续物理内存的映射
   530 // 每一对BAT寄存器定义了有效地址块的起始,块大小,对应的物理内存块的起始
   531
   532 xor r0,r0 // r0清零,然后将r0赋给所有BAT's,实现清除所有BAT's
   533 mtspr DBAT0U,r0 // 清除数据块地址转换寄存器(SPR 0x218)
   534 mtspr DBAT0L,r0
   535 mtspr DBAT1U,r0
   536 mtspr DBAT1L,r0
   537 mtspr DBAT2U,r0
   538 mtspr DBAT2L,r0
   539 mtspr DBAT3U,r0
   540 mtspr DBAT3L,r0
   541 mtspr IBAT0U,r0 // 清除指令块地址转换寄存器
   542 mtspr IBAT0L,r0
   543 mtspr IBAT1U,r0
   544 mtspr IBAT1L,r0
   545 mtspr IBAT2U,r0
   546 mtspr IBAT2L,r0
   547 mtspr IBAT3U,r0
   548 mtspr IBAT3L,r0
   549 SYNC // sync; isync指令,保证了指令顺序
   550
   551 /* invalidate all tlb's
   552 *
   553 * From the 603e User Manual: "The 603e provides the ability to
   554 * invalidate a TLB entry. The TLB Invalidate Entry (tlbie)
   555 * instruction invalidates the TLB entry indexed by the EA,and
   556 * operates on both the instruction and data TLBs simultaneously
   557 * invalidating four TLB entries (both sets in each TLB). The
   558 * index corresponds to bits 15-19 of the EA. To invalidate all
   559 * entries within both TLBs,32 tlbie instructions should be
   560 * issued,incrementing this field by one each time."
   561 *
   562 * "Note that the tlbia instruction is not implemented on the
   563 * 603e."
   564 *
   565 * bits 15-19 correspond to addresses 0x00000000 to 0x0001F000
   566 * incrementing by 0x1000 each time. The code below is sort of
   567 * based on code in "flush_tlbs" from arch/ppc/kernel/head.S
   568 *
   569 */
   570
   571 // PowerPC的页地址转换机制以以由16个段寄存器(SRs)实现的段描述符和页表项(PTE)来说明,
   572 // 实现逻辑地址到物理地址的映射。(段信息将有效地址EA转换为中间的虚拟地址,页表信息
   573 // 将此虚拟地址转换为物理地址。有效地址空间被分为256M字节的段,相应的存储映射的段被
   574 // 分为4K字节的页。) 这些段描述符和页表项(PTE)分别驻留在物理内存中的段表和页表内。
   575 // TLB: 转换旁路缓冲器,是部分页表的cache,一般是最近使用的页表cache。由于地址转换表
   576 // 的不断变化,有必要保持TLB和那些更新表的一致。通过使TLB条目无效,让地址转换机构重
   577 // 新从地址转换表中读取更新TLB. tlbie是使TLB条目无效的指令
   578 li r3,32 // 将立即数赋给r3
   579 mtctr r3 // 将r3赋给计数寄存器,实现循环32次
   580 li r3,0 // r3清零
   581 1: tlbie r3 // 有效地址EA为r3,对EA的块地址转换将被忽略
   582 addi r3,0x1000 // 0x1000=4k
   583 bdnz 1b // ctr自减,如果ctr非0就跳转到目标(前向跳转到第一个目标1)
   584 SYNC
   585
   586 /* Done!*/
   587 /*------------------------------*/
   588 blr // 子例程调用返回. 返回到链接寄存器中指定的地址:调用指令的下条指令地址
   589
   590 /* Cache functions.
   591 *
   592 * Note: requires that all cache bits in
   593 * HID0 are in the low half word.
   594 */
   595 .globl icache_enable
   596 icache_enable:
   597 mfspr r3,HID0 // 将HID0(SPR 1008)赋给r3
   598 ori r3,HID0_ICE // 第16bit HID0[ICE]置1: 指令cache使能位
   599 lis r4,0 // r4清零
   600 ori r4,HID0_ILOCK // 第17bit HID0[ILOCK]置1: 指令cache锁
   601 andc r3,r4 // r3与r4的补数,保证r3的ILOCK位清零,其余不变
   602 ori r4,HID0_ICFI // 第19bit HID0[ICFI]置1,其余位不变
   603 isync // 设置HID0[ILOCK]位前,应使用isync
   604 mtspr HID0,r4 /* sets enable and invalidate,clears lock */
   605 isync
   606 mtspr HID0,r3 /* clears invalidate */
   607 blr // 返回
   608
   609 .globl icache_disable
   610 icache_disable:
   611 mfspr r3,HID0 // r3 <= HID0
   612 lis r4,0 // r4 <= 0
   613 ori r4,HID0_ICE|HID0_ILOCK // 第 16bit为1 指令cache使能位.
   614 // 19bit为1 指令cache锁,在设置HID0[ILOCK]位之前应执行一次isync指令
   615 andc r3,r4 // 清零r3的ICE和ILOCK位,其余不变
   616 ori r4,HID0_ICFI // 设置第20bit[ICFI]为1 指令cache刷新无效
   617 isync
   618 mtspr HID0,r4 /* sets invalidate,clears enable and lock*/
   619 isync
   620 mtspr HID0,r3 /* clears invalidate */
   621 blr
   622
   623 .globl icache_status
   624 icache_status:
   625 mfspr r3,HID0 // r3 <= HID0(SPR 1008)
   626 rlwinm r3,HID0_ICE_SHIFT,31,31 // r3左旋HID0_ICE_SHIFT(15)位 再与0x00000001 存入r3 //?
   627 blr
   628
   629 .globl dcache_enable
   630 dcache_enable:
   631 mfspr r3,HID0 // r3 <= HID0(SPR 1008)
   632 ori r3,HID0_ENABLE_DATA_CACHE // r3的第17bit(HID0[DCE])位为1
   633 lis r4,0 // r4 <= 0
   634 ori r4,HID0_LOCK_DATA_CACHE // r4: HID0[DLOCK]为1
   635 andc r3,r4 // r3的DLOCK位清零,其余不变
   636 ori r4,HID0_LOCK_INSTRUCTION_CACHE // r4: ILOCK位为1,其余和r3同
   637 sync
   638 mtspr HID0,clears lock */
   639 sync
   640 mtspr HID0,r3 /* clears invalidate */
   641 blr
   642
   643 .globl dcache_disable
   644 dcache_disable:
   645 mfspr r3,HID0 // r3 <= HID0
   646 lis r4,0 // r4 <= 0
   647 ori r4,HID0_ENABLE_DATA_CACHE|HID0_LOCK_DATA_CACHE // r4的HID0[DCE]和HID0[DLOCK]为1
   648 andc r3,r4 // r3的HID0[DCE]和HID0[DLOCK]清零,其余不变
   649 ori r4,HID0_INVALIDATE_DATA_CACHE // r4的DCFI为1,DCE和DLOCK为0
   650 sync
   651 mtspr HID0,clears enable and lock */
   652 sync
   653 mtspr HID0,r3 /* clears invalidate */
   654 blr
   655
   656 .globl dcache_status
   657 dcache_status:
   658 mfspr r3,HID0 // r3 <= HID0
   659 rlwinm r3,HID0_DCE_SHIFT,31 // r3左旋14bit 然后和0x00000001逻辑与
   660 blr
   661
   662 .globl get_pvr
   663 get_pvr:
   664 mfspr r3,PVR // 将处理器版本寄存器PVR(SPR 0x11F)值赋给r3
   665 blr
   666
   667 .globl ppcDWstore
   668 ppcDWstore:
   669 lfd 1,0(r4) // 有效地址r4+0,加载浮点数双字到浮点寄存器fpr1
   670 stfd 1,0(r3) // 有效地址r3+0,存储浮点数双字fpr1到有效地址
   671 sync
   672 blr
   673
   674 /*-------------------------------------------------------------------*/
   675
   676 /*
   677 * void relocate_code (addr_sp,gd,addr_moni) // 函数原型
   678 * // PowerPC ABI采用r3 ~ r10传递参数 addr_sp是新堆栈顶,gd全局数据指针,addr_moni代码搬运RAM地址
   679 * This "function" does not return,instead it continues in RAM
   680 * after relocating the monitor code.
   681 *
   682 * r3 = dest
   683 * r4 = src
   684 * r5 = length in bytes
   685 * r6 = cachelinesize
   686 */
   687 .globl relocate_code
   688 relocate_code:
   689 mr r1,r3 /* Set new stack pointer*/ // r1 <= r3
   690 mr r9,r4 /* Save copy of Global Data pointer */
   691 mr r10,r5 /* Save copy of Destination Address */
   692
   693 mr r3,r5 /* Destination Address */
   694 lis r4,CFG_MONITOR_BASE@h /* Source Address */
   695 ori r4,CFG_MONITOR_BASE@l // r4 <= 0xFEF00000
   696 lwz r5,GOT(__init_end) // 计算得到got表项中__init_end的值; __init_end值见u-boot.lds
   697 // __init_end为u-boot镜像text的结束地址
   698 sub r5,r4 // r5 <= r5 - r4,计算u-boot镜像的长度
   699 li r6,CFG_CACHELINE_SIZE /* Cache Line Size */ // r6 <= 32
   700
   701 /*
   702 * Fix GOT pointer:
   703 *
   704 * New GOT-PTR = (old GOT-PTR - CFG_MONITOR_BASE)
   705 * + Destination Address
   706 * 即: new r14 = old r14 - r4 + r10
   707 * Offset:
   708 */
   709 sub r15,r10,r4 // r15 <= r10 - r4
   710
   711 /* First our own GOT */
   712 add r14,r14,r15 // r14 <= r14 + r15
   713 /* then the one used by the C code */
   714 add r30,r30,r15 // r30 <= r30 + r15
   715
   716 /*
   717 * Now relocate code
   718 */
   719 // 此时 r3 = dest; r4 = src; r5 = len;
   720 cmplw cr1,r4 // r3和r4逻辑(无符号数)比较,比较结果存入cr1
   721 addi r0,3 // r0 <= r5 + 3
   722 srwi. r0,2 // r0 右移2bit,影响条件寄存器CR0
   723 // 以上代码实现r0 <= (r0+3)/4; 因为搬移代码是每次4个字节,这样计算出搬移次数做循环变量
   724 beq cr1,4f /* In place copy is not necessary */ // 如果相等(r3==r4)前向跳转到4
   725 beq 7f /* Protect against 0 count */
   726 mtctr r0 // ctr <= r0
   727 bge cr1,2f // 如果大于(r3>r4) 则前向跳转到2
   728 la r8,-4(r4) // 加载地址 r8 <= r4 - 4 <===> addi r8,-4
   729 la r7,-4(r3) // r7 <= r3 - 4
   730
   731 /* copy */ // 代码复制(r3 < r4 : dest < src)
   732 1: lwzu r0,4(r8) // 有效地址(EA)r8+4,将EA的字加载到r0,将EA存入r8
   733 stwu r0,4(r7) // 有效地址(EA)r7+4,将r0存入EA空间,将EA存入r7
   734 bdnz 1b // ctr减,当ctr非0时后向跳转到1,实现循环复制
   735
   736 addi r0,3 // r0 <= r5 + 3
   737 srwi. r0,2 // r0右移2bit,影响条件寄存器CR0
   738 mtctr r0 // ctr <= r0
   739 la r8,-4(r4) // r8 <= r4 - 4
   740 la r7,-4(r3) // r7 <= r3 -4
   741
   742 /* and compare */ // 复制前后校验
   743 20: lwzu r20,将EA的字(32bit)加载到r20,将EA存入r8
   744 lwzu r21,将EA的字(32bit)加载到r21,将EA存入r7
   745 xor. r22,r20,r21 // r20和r21进行逻辑异或,结果存入r22,影响条件寄存器CR0
   746 bne 30f // 如果不相等(说明复制过程中出错),则前向跳转到30
   747 bdnz 20b // ctr减,当ctr非0时后向跳转到20,实现循环校验比较
   748 b 4f // 前向跳转到4
   749
   750 /* compare failed */
   751 30: li r3,0 // r3 <= 0 清零,返回状态码0
   752 blr // 返回
   753
   754 2: slwi r0,2 /* re copy in reverse order ... y do we needed it? */
   755 // r0左移2bit,恢复
   756 add r8,r0 // r8 <= r4 + r0
   757 add r7,r0 // r7 <= r3 + r0
   758 3: lwzu r0,-4(r8) // 有效地址(EA)r8-4,将EA存入r8
   759 stwu r0,-4(r7) // 有效地址(EA)r7-4,将r0存储到EA的空间,将EA存入r7
   760 bdnz 3b // ctr减,当ctr非0时后向跳转到3,实现循环复制
   761
   762
   763
   764 /*
   765 * Now flush the cache: note that we must start from a cache aligned
   766 * address. Otherwise we might miss one cache line.
   767 */
   768 4:
   769 bl un_setup_stack_in_data_cache // 跳转到un_setup_stack_in_data_cache
   770 mr r7,r3 // r7 <= r3 保存r3,r4
   771 mr r8,r4 // r8 <= r4
   772 bl dcache_disable // 跳转到dcache_disable 使得HID0[DCE] (数据cache使能位)为0
   773 mr r3,r7 // r3 <= r7 恢复r3,r4
   774 mr r4,r8 // r4 <= r8
   775
   776 cmpwi r6,0 // r6与有符号立即数0比较,结果存入CR0
   777 add r5,r5 // r5 <= r3 + r5
   778 beq 7f /* Always flush prefetch queue in any case */ // 相等则前向跳转到7
   779 subi r0,r6,1 // r0 <= r6 - 1
   780 andc r3,r0 // r3和r0的补数逻辑与,结果存入r3
   781 mfspr r7,HID0 /* don't do dcbst if dcache is disabled*/ // r7 <= HID0
   782 rlwinm r7,r7,31 // r7左旋14bit,然后和0x00000001逻辑与,结果存入r7
   783 cmpwi r7,0 // r7与有符号立即数0比较,结果存入CR0,目的是查看HID0[DCE]是否为1
   784 beq 9f // 相等(即HID0[DCE]为0)则前向跳转到9 DCE是数据cache使能位
   785 mr r4,r3 // r4 <= r3
   786 5: dcbst 0,r4 // 有效地址EA为0+r4,该指令(数据cache块存储指令)将有效地址EA所在的cache行与内存同步。
   787 add r4,r6 // r4 <= r4 + r6
   788 cmplw r4,r5 //
   789 blt 5b
   790 sync /* Wait for all dcbst to complete on bus */
   791 9: mfspr r7,HID0 /* don't do icbi if icache is disabled */
   792 rlwinm r7,31 // r7左旋14bit,和0x00000001逻辑与,结果存入r7
   793 cmpwi r7,0 // r7与有符号立即数0比较,结果存入CR0,目的是查看HID0[DCE]是否为1
   794 beq 7f // 相等(即HID0[DCE]为0)则前向跳转到9 DCE是数据cache使能位
   795 mr r4,r3 // r4 <= r3
   796 6: icbi 0,r4 // 将有效地址0+r4所在的指令cache行置为无效
   797 add r4,r6 // r4 <= r4 + r6
   798 cmplw r4,r5 // 无符号数r4和r5逻辑比较,结果存入CR0
   799 blt 6b // 如果小于(r4 < r5)则前向跳转到6
   800 7: sync /* Wait for all icbi to complete on bus */
   801 isync
   802
   803 /*
   804 * We are done. Do not return,instead branch to second part of board
   805 * initialization,now running from RAM.
   806 */
   807
   808 addi r0,in_ram - _start + EXC_OFF_SYS_RESET // r10中存放的是代码搬运到RAM中地址,计算在RAM中in_ram的地址
   809 mtlr r0 // 将RAM中的指令地址r0赋给链接寄存器lr
   810 blr // 跳转到链接寄存器lr中存储的地址
   811
   812 in_ram: // 下面开始在RAM中执行
   813
   814 /*
   815 * Relocation Function,r14 point to got2+0x8000
   816 *
   817 * Adjust got2 pointers,no need to check for 0,this code
   818 * already puts a few entries in the table.
   819 */
   820 // 以下代码更新RAM中的GOT表和RAM里的GOT表里的内容。因为GOT表里的是全局label,存储的仍然是搬运前的地址
   821 li r0,__got2_entries@sectoff@l // sectoff段中的__got2_entries的低16bit,即GOT表项的个数,(u-boot.lds)
   822 // sectoff是section offset的缩写
   823 la r3,GOT(_GOT2_TABLE_) // <==>la r3,.L_GOT2_TABLE_(r14) <==> r3 <= .L_GOT2_TABLE_ + r14
   824 // RAM中GOT表的起始地址(new .got2 + 0x8000)
   825 lwz r11,GOT(_GOT2_TABLE_) // 有效地址为.L_GOT2_TABLE_ + r14,将有效地址的内容存入r11
   826 // 将_GOT2_TABLE_的值赋给r3,即Flash中GOT表的起始地址(old .got2 + 0x8000)
   827 mtctr r0 // ctr <= r0
   828 sub r11,r11 // r11 <= r3 - r11 ; 代码搬运前后的GOT表相对偏移
   829 addi r3,-4 // r3 <= r3 - 4
   830 1: lwzu r0,4(r3) // 有效地址(EA)r3+4,将EA的内容加载到r0,同时EA存入r3
   831 add r0,r11 // r0 <= r0 + r11 ; 利用GOT表偏移进行更新
   832 stw r0,0(r3) // 有效地址0+r3,将r0存储到有效地址; 读取,修改,写回。
   833 bdnz 1b // ctr减,当ctr非零时后向跳转到1
   834
   835 /*
   836 * Now adjust the fixups and the pointers to the fixups
   837 * in case we need to move ourselves again.
   838 */
   839 2: li r0,__fixup_entries@sectoff@l // 将__fixup_entries的值赋给r0
   840 lwz r3,GOT(_FIXUP_TABLE_) // 有效地址(EA)为.L_FIXUP_TABLE_ + r14,将EA的内容加载r3
   841 // 即更新后的RAM中的GOT表中_FIXUP_TABLE_的值赋给r3
   842 cmpwi r0,0 // 与有符号立即数0比较,结果存入CR0
   843 mtctr r0 // ctr <= r0
   844 addi r3,-4 // r3 <= r3 - 4
   845 beq 4f // 如果相等(r0和0相等),则前向跳转到4
   846 3: lwzu r4,4(r3) // 有效地址r3+4,将EA的内容存入r4,同时将EA存入r3
   847 lwzux r0,r11 // 有效地址r4+r11,将EA的内容存入r0,同时将EA存入r4
   848 add r0,r11 // r0 <= r0 + r11
   849 stw r10,0(r3) // 有效地址0+r3,将r10存储到有效地址
   850 stw r0,0(r4) // 有效地址0+r4,将r0存储到有效地址
   851 bdnz 3b // ctr减,当ctr非零时后向跳转到3
   852 4:
   853 clear_bss:
   854 /*
   855 * Now clear BSS segment
   856 */
   857 lwz r3,GOT(__bss_start) // 有效地址(EA)为.L__bss_start + r14,
   858 // 将更新后GOT表中的__bss_startz值(RAM中bss段起始地址)加载到r3
   859 #if defined(CONFIG_HYMOD)
   860 /*
   861 * For HYMOD - the environment is the very last item in flash.
   862 * The real .bss stops just before environment starts,so only
   863 * clear up to that point.
   864 *
   865 * taken from mods for FADS board
   866 */
   867 lwz r4,GOT(environment)
   868 #else
   869 lwz r4,GOT(_end) // 有效地址(EA)为.L_end + r14,将更新后的GOT表_end值(RAM中bss结束地址)载到r4
   870 #endif
   871
   872 cmplw 0,r4 // r3和r4进行逻辑比较,结果存入CR0
   873 beq 6f // 如果相等则前向跳转到6
   874
   875 li r0,0 // r0 <= 0
   876 5: // r3为bss段起始地址,r4为bss段末尾地址,下面循环实现清零
   877 stw r0,0(r3) // 有效地址为0 + r3,将r0存储到有效地址; 实现清零
   878 addi r3,4 // r3 <= r3 + 4
   879 cmplw 0,r4 // r3和r4进行逻辑比较,结果存入CR0
   880 bne 5b // 如果不相等则后向跳转到5
   881 6:
   882
   883 mr r3,r9 /* Global Data pointer */ // r3 <= r9
   884 mr r4,r10 /* Destination Address */ // r4 <= r10
   885 bl board_init_r // 跳转到lib_ppc/board.c中board_init_r(gd_t *id,ulong dest_addr)
   886 // 此时RAM中的全局数据已经可写,bss已经清零初始化,栈大小已基本不受限制,已经建立起正常的C环境,
   887 // 开始板子初始化的第二阶段,在RAM中运行.(id执行RAM中的全局数据gd_t,dest_addr为代码搬运到RAM
   888 // 中u-boot的地址
   889
   890 /*
   891 * Copy exception vector code to low memory
   892 * trap_init(dest_addr); 复制异常向量代码到存储器的开始处(低端内存)
   893 * r3: dest_addr (dest_addr为RAM中u-boot的地址)
   894 * r7: source address,r8: end address,r9: target address
   895 */
   896 .globl trap_init
   897 trap_init:
   898 lwz r7,GOT(_start) // 有效地址.L_start + r14,将有效地址的内容(RAM中_start的位置)加载到r7
   899 lwz r8,GOT(_end_of_vectors) // 有效地址.L_end_of_vectors + r14,将有效地址的内容
   900 // (_end_of_vectors值,异常向量代码结束地址)加载r8
   901 // r7: 异常向量代码的起始地址; r8: 异常向量代码的结束地址;r9: 异常向量代码拷贝的目的地址
   902
   903 li r9,0x100 /* reset vector always at 0x100 */ // 复制的目的地址: 0x100,RAM中复位向量地址
   904
   905 cmplw 0,r8 // r7 和 r8进行逻辑比较
   906 bgelr /* return if r7>=r8 - just in case */
   907 // 如果r7 > r8 则跳转到链接寄存器lr中的地址
   908
   909 mflr r4 /* save link register */ // r4 <= lr
   910 1:
   911 lwz r0,0(r7) // 有效地址0 + r7,将有效地址的内容加载到r0
   912 stw r0,0(r9) // 有效地址0 + r9,将r0存储到有效地址的空间中
   913 addi r7,4 // r7 <= r7 + 4
   914 addi r9,r9,4 // r9 <= r9 + 4
   915 cmplw 0,r8 // 将r7 和r8进行逻辑比较,比较结果存入CR0
   916 bne 1b // 如果不等(说明未复制到结尾)则后向跳转到1
   917 // 实现将_start和_end_of_vectors之间的代码复制到低端内存0x100开始的内容中
   918
   919 /*
   920 * relocate `hdlr' and `int_return' entries
   921 */
   922 li r7,.L_MachineCheck - _start + EXC_OFF_SYS_RESET
   923 li r8,Alignment - _start + EXC_OFF_SYS_RESET
   924 2:
   925 bl trap_reloc // 跳转到trap_reloc
   926 addi r7,0x100 /* next exception vector */
   927 cmplw 0,r8
   928 blt 2b
   929
   930 li r7,.L_Alignment - _start + EXC_OFF_SYS_RESET
   931 bl trap_reloc
   932
   933 li r7,.L_ProgramCheck - _start + EXC_OFF_SYS_RESET
   934 bl trap_reloc
   935
   936 li r7,.L_FPUnavailable - _start + EXC_OFF_SYS_RESET
   937 li r8,SystemCall - _start + EXC_OFF_SYS_RESET
   938 3:
   939 bl trap_reloc
   940 addi r7,0x100 /* next exception vector */
   941 cmplw 0,r8 // 将r7 和r8进行逻辑比较,比较结果存入CR0
   942 blt 3b // 如果小于(r7 < r8)则后向跳转到3
   943
   944 li r7,.L_SingleStep - _start + EXC_OFF_SYS_RESET
   945 li r8,_end_of_vectors - _start + EXC_OFF_SYS_RESET
   946 4:
   947 bl trap_reloc
   948 addi r7,0x100 /* next exception vector */
   949 cmplw 0,r8
   950 blt 4b
   951
   952 mfmsr r3 /* now that the vectors have */ // r3 <= msr
   953 lis r7,MSR_IP@h /* relocated into low memory */ // r7 <= (1 << 6)
   954 ori r7,MSR_IP@l /* MSR[IP] can be turned off */
   955 andc r3,r7 /* (if it was on) */ // 清除MSR[IP]位,其余保留
   956 SYNC /* Some chip revs need this... */
   957 mtmsr r3 // msr <= r3
   958 SYNC
   959
   960 mtlr r4 /* restore link register */ // lr <= r4
   961 blr // 跳转到链接寄存器lr中的地址
   962
   963 /*
   964 * Function: relocate entries for one exception vector
   965 */
   966 // 重定位异常向量的入口地址,即handler和int_return需加上中间的偏移(dest_addr)
   967 // 因为异常向量0x200以后的真正的异常处理(handler)函数没有复制到低端内存中,但复制到低端内存中的
   968 // 异常处理通用代码中,有其handler函数的入口地址以及异常处理结束恢复现场函数int_return的入口地址。
   969 // 此入口地址是相对地址,所以低端RAM中的这些地址需要加上多加上因重定位而需要的偏移dest_addr.
   970 trap_reloc:
   971 lwz r0,0(r7) /* hdlr ... */ // 将有效地址0 + r7的内容加载到r0
   972 add r0,r3 /* ... += dest_addr */ // r3 <= r0 + r3
   973 stw r0,0(r7) // 将r0存储到有效地址0 + r7中
   974
   975 lwz r0,4(r7) /* int_return ... */ // 将有效地址4 + r7的内容加载到r0
   976 add r0,r3 /* ... += dest_addr */ // r3 <= r0 + r3
   977 stw r0,4(r7) // 将r0存储到有效地址4 + r7中
   978
   979 blr // 返回
   980
   981 #ifdef CFG_INIT_RAM_LOCK // #define CFG_INIT_RAM_LOCK 1
   982 .globl unlock_ram_in_cache
   983 unlock_ram_in_cache:
   984 /* invalidate the INIT_RAM section */
   985 lis r3,(CFG_INIT_RAM_ADDR & ~31)@h
   986 ori r3,(CFG_INIT_RAM_ADDR & ~31)@l
   987 li r2,512 // r2 <= 512
   988 mtctr r2 // ctr <= r2
   989 1: icbi r0,r3 // 有效地址为 0+r3,icbi为指令cache块无效指令
   990 dcbi r0,dcbi为数据cache块无效指令
   991 // 该两条指令将有效地址EA所在的指令/数据cache行置为无效
   992 addi r3,32 // r3 <= r3 + 32
   993 bdnz 1b // ctr减,当ctr非零时后向跳转到1
   994 sync /* Wait for all icbi to complete on bus */
   995 isync
   996 blr // 返回
   997 #endif
   998
   999 map_flash_by_law1:
  1000 /* When booting from ROM (Flash or EPROM),clear the */
  1001 /* Address Mask in OR0 so ROM appears everywhere */
  1002 /*----------------------------------------------------*/
  1003 lis r3,(CFG_IMMRBAR)@h /* r3 <= CFG_IMMRBAR */
  1004 lwz r4,OR0@l(r3) // 将local bus OR0赋给r4.
  1005 li r5,0x7fff /* r5 <= 0x00007FFFF */
  1006 and r4,r5 // 保留r4的低15bit,其余清零
  1007 stw r4,OR0@l(r3) /* OR0 <= OR0 & 0x00007FFFF */
  1008 // OR0[AM]位0 ~ 16为0,存储bank空间为4Gbytes.
  1009
  1010 /* As MPC8349E User's Manual presented,when RCW[BMS] is set to 0,
  1011 * system will boot from 0x0000_0100,and the LBLAWBAR0[BASE_ADDR]
  1012 * reset value is 0x00000; when RCW[BMS] is set to 1,system will boot
  1013 * from 0xFFF0_0100,and the LBLAWBAR0[BASE_ADDR] reset value is
  1014 * 0xFF800. From the hard resetting to here,the processor fetched and
  1015 * executed the instructions one by one. There is not absolutely
  1016 * jumping happened. Laterly,the u-boot code has to do an absolutely
  1017 * jumping to tell the CPU instruction fetching component what the
  1018 * u-boot TEXT base address is. Because the TEXT base resides in the
  1019 * boot ROM memory space,to garantee the code can run smoothly after
  1020 * that jumping,we must map in the entire boot ROM by Local Access
  1021 * Window. Sometimes,we desire an non-0x00000 or non-0xFF800 starting
  1022 * address for boot ROM,such as 0xFE000000. In this case,the default
  1023 * LBIU Local Access Widow 0 will not cover this memory space. So,we
  1024 * need another window to map in it.
  1025 * // RCW[BMS]为1,系统复位第一条指令位于0xFFF0_0100,LBLAWBAR0[BASE_ADDR]为0xFF800,
  1026 * // 从硬复位到此,CPU按序执行指令,没有绝对跳转发生。稍后,U-Boot代码必须做绝对跳转来
  1027 * // 告诉CPU取指令单元u-boot TEXT段的基地址,因为TEXT驻留在启动ROM存储空间里(8M BMS),为了保证
  1028 * // 跳转后代码依然顺利运行,必须通过本地访问窗映射整个启动ROM (大小8M).有时使用非0x00000或0xFF800
  1029 * // 的起始地址,例如0xFE000000,这种情况下默认的LBIU 本地访问窗0不能覆盖这个存储空间。所以用
  1030 * // 其他的窗口来映射(因为本地访问窗0地址LBLAWBAR0[BASE_ADDR])
  1031 */
  1032 // 以下将Window 3(LBLAWBAR1)映射为起始地址为CFG_FLASH_BASE,大小8M的空间
  1033 lis r4,(CFG_FLASH_BASE)@h // 将CFG_FLASH_BASE(0xFE000000)赋给r4
  1034 ori r4,(CFG_FLASH_BASE)@l
  1035 stw r4,LBLAWBAR1(r3) /* LBLAWBAR1 <= CFG_FLASH_BASE */
  1036 // 设置Window 3(LBLAWBAR1)窗基地址0xFE000000
  1037 #ifdef CONFIG_MPC8349ITX
  1038 lis r4,(0x80000017)@h
  1039 ori r4,(0x80000017)@l // 窗口使能,设置窗口大小16Mbytes
  1040 #else
  1041 lis r4,(0x80000016)@h
  1042 ori r4,(0x80000016)@l
  1043 #endif
  1044 stw r4,LBLAWAR1(r3) /* LBLAWAR1 <= 16MB Flash Size */ // 窗口使能,设置窗口大小16M
  1045 blr // 返回
  1046
  1047 /* Though all the LBIU Local Access Windows and LBC Banks will be
  1048 * initialized in the C code,we'd better configure boot ROM's
  1049 * window 0 and bank 0 correctly at here.
  1050 */
  1051 remap_flash_by_law0:
  1052
  1053 #ifdef CONFIG_MPC8349ITX
  1054 /* MPC8349ITX : CS1 */
  1055 /* Initialize the BR1 with the vsc7385 starting address. */
  1056 lis r5,0xf8000801@h // r5 <= 0xf8000801
  1057 ori r5,0xf8000801@l
  1058 stw r5,BR1(r3) /* [r3+BR1] <= 0xF8000801 */
  1059 // 将r5赋给local bus BR1寄存器,设基址0xF8000000, 端口size为8bit,GPCM,valid
  1060
  1061 lis r5,0xfffe09ff@h
  1062 ori r5,0xfffe09ff@l
  1063 stw r5,OR1(r3) // 设置LBCR OR1为0xfffe09ff. 设置存储bank大小为128Kbytes
  1064 #endif
  1065
  1066 /* Initialize the BR0 with the boot ROM starting address. */
  1067 lwz r4,BR0(r3) // 将local bus BR0赋给r4
  1068 li r5,0x7FFF // r5 <= 0x7FFF
  1069 and r4,r5 // r4 <= (BR0) & 0x7FFF 低15bit不变,高17位清零
  1070 lis r5,(CFG_FLASH_BASE & 0xFFFF8000)@h // CFG_FLASH_BASE的高17bit不变,其余清零
  1071 ori r5,(CFG_FLASH_BASE & 0xFFFF8000)@l
  1072 or r5,r4
  1073 stw r5,BR0(r3) /* r5 <= (CFG_FLASH_BASE & 0xFFFF8000) | (BR0 & 0x00007FFF) */
  1074 // 设置LBCR BR0,基址为CFG_FLASH_BASE(0xFE000000),其余和复位值有关(16bit,valid)
  1075
  1076 lwz r4,OR0(r3) // 将LBCR OR0赋给r4,复位后OR[AM]=0x0,即存储bank 大小为4Gbytes.
  1077 #ifdef CONFIG_MPC8349ITX
  1078 lis r5,0xFF000ff7@h /* 16M,each flash is 8M and share the same CS0 */
  1079 ori r5,0xFF000ff7@l // r5 <= 0xFF000FF7
  1080 stw r5,OR0(r3) // 设置LBCR OR0为r5,设置存储bank大小为16M
  1081 #else
  1082 lis r5,0xFF80 /* 8M */
  1083 or r4,r5
  1084 stw r4,OR0(r3) /* OR0 <= OR0 | 0xFF800000 */
  1085 #endif
  1086
  1087 lis r4,(CFG_FLASH_BASE)@h // r4 <= CFG_FLASH_BASE(0xFE000000)
  1088 ori r4,(CFG_FLASH_BASE)@l
  1089 stw r4,LBLAWBAR0(r3) /* LBLAWBAR0 <= CFG_FLASH_BASE */
  1090 // Windows 1(LBLAWBAR0)起始地址CFG_FLASH_BASE(0xFE000000)
  1091
  1092 #ifdef CONFIG_MPC8349ITX
  1093 lis r4,(0x80000017)@h // 将0x80000017赋给r4,0x17=23,Window 1(LBLAWBAR0)有效,大小2^(23+1)=16M
  1094 ori r4,(0x80000017)@l
  1095 #else
  1096 lis r4,(0x80000016)@h
  1097 ori r4,(0x80000016)@l
  1098 #endif
  1099 stw r4,LBLAWAR0(r3) /* LBLAWAR0 <= 16MB Flash Size */
  1100 // 将0x80000017赋给LBLAWAR0,Window 1(LAW0)有效,大小2^(23+1)=16M
  1101
  1102 xor r4,r4 // r4清零
  1103 stw r4,LBLAWBAR1(r3) // Window 2(LBLAWBAR1) 起始地址0x0
  1104 stw r4,LBLAWAR1(r3) /* Off LBIU LAW1 */ // Window 2(LBLAWBAR1)无效
  1105 blr // 返回
  1106
  1107 setup_stack_in_data_cache_on_r1:
  1108 lis r3,(CFG_IMMRBAR)@h // r3存储IMMRBAR地址,Window 0(IMMR)起始地址CFG_IMMRBAR(0xE0000000)
  1109
  1110 /* setup D-BAT for the D-Cache (with out real memory backup) */
  1111
  1112 lis r4,(CFG_INIT_RAM_ADDR & 0xFFFE0000)@h // MPC8349ITX.h中CFG_INIT_RAM_ADDR为0xE4010000
  1113 // r4 <= (0xE4010000 & 0xFFFE0000) | 0x0003 ----- r4 <= 0xE4000003
  1114 ori r4,0x0003 /* 128KB block,VsVp='11' */
  1115 mtspr DBAT0U,r4 // 将r4赋给DBAT0U(SPR 0x218) 此段块地址转换基址为r4
  1116 lis r4,(CFG_INIT_RAM_ADDR & 0xFFFE0000)@h
  1117 ori r4,0x0002 /* WIMG='0000',PP='10' read/write */
  1118 mtspr DBAT0L,r4 // 将r4赋给DBAT0U(SPR 0x219)
  1119 isync
  1120
  1121 /* Enable DMMU */ // 为了使用BAT,使能数据MMU
  1122 mfmsr r4 // 将msr赋给r4
  1123 ori r4,(MSR_DR)@l // 将r4第27bit MSR[DR]置1
  1124 mtmsr r4 // r4赋给msr 数据地址转换使能位置1
  1125
  1126 /* Enable and invalidate data cache. */
  1127 mfspr r4,HID0 // 将HID0(SPR 0x3F0)赋给r4
  1128 mr r5,r4 // r5 <= r4
  1129 ori r4,HID0_DCE | HID0_DCI // r4第17bit,21bit置1 HID0[DCE]=1 HID0[DCFI]=1
  1130 ori r5,HID0_DCE // r5第17bit置1 HID0[DCE]=1
  1131 sync
  1132 mtspr HID0,r4 // 数据cache使能,数据cache刷新无效
  1133 mtspr HID0,r5 // 数据cache使能
  1134 // 对于e300,必须用两个连续的mtspr指令来设置和清楚HID0的DCFI位
  1135 sync
  1136
  1137 /* Allocate Initial RAM in data cache.*/
  1138 // mpc8349有32k数据cache,初始化数据cache作为RAM用,以后存储全局数据结构gd_t,及栈空间
  1139 li r0,0 // r0清零
  1140 lis r4,(CFG_INIT_RAM_ADDR)@h // r4 <= CFG_INIT_RAM_ADDR(0xE4010000)
  1141 ori r4,(CFG_INIT_RAM_ADDR)@l
  1142 #if defined (CONFIG_E300C1)
  1143 li r5,1024 /* 1024cacheblock * 32bytes/cacheblock = 32KB */
  1144 #elif defined (CONFIG_E300C2)
  1145 li r5,512 /* 512cacheblock * 32bytes/cacheblock = 16KB */
  1146 #else
  1147 li r5,128*8 /* 128*8*32=32Kb */ // r5 <= 0x400 (1K)
  1148 #endif
  1149 mtctr r5 // 将r5赋给ctr
  1150 1:
  1151 dcbz r0,r4 // 有效地址EA为r0(=0x0)+r4,实现data cache block清零
  1152 // 为有效地址EA分配一个cache行,然后此cache行清零,会对cache行的状态进行检查.
  1153 // 当cache行不使能或被锁或处于不能被改写的状态时,此指令会引起alignment中断
  1154 addi r4,32 // 每次增加32 (32*1000 = 32K)
  1155 bdnz 1b // ctr非0时跳转到1(前向跳转到1)
  1156 isync
  1157
  1158 /* Disable DMMU */
  1159 mfmsr r4 // 将msr赋给r4
  1160 addis r5,0xffff // r5 <= (0x0 & 0xffff) << 16 --- r5: 0xFFFF0000
  1161 ori r5,0xffcf /* turn off address translation */ // r5: 0xFFFFFFCF
  1162 and r4,r5 // 将bit 26-27清零
  1163 mtmsr r4 // MSR[IR-DR]置零,即禁止指令和数据地址转换
  1164 isync
  1165 sync /* the MMU should be off... */
  1166
  1167 /* Lock all the D-cache,basically leaving the reset of the program without dcache */
  1168 mfspr r4,HID0 // 保存HID0(SPR 0x3F0)到r4
  1169 ori r4,(HID0_DLOCK)@l // 将第19位置1 HID0[DLOCK]=1
  1170 sync // 为防止在cache访问时锁住,应该在在设置HID0[DLOCK]前使用sync指令
  1171 mtspr HID0,r4 // 将r4 赋给hid0,HID0[DLOCK]=1,整个数据cache被锁住
  1172
  1173 /* setup the stack pointer in r1 */
  1174 // PowerPC (E)ABI中用r1作堆栈指针SP. 栈向下增长
  1175 // MPC8349ITX.h中CFG_INIT_RAM_ADDR=0xE4010000. CFG_INIT_RAM_END=0x1000. CFG_GBL_DATA_SIZE=0x100
  1176 // CFG_GBL_DATA_OFFSET=(CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE) = 0x900
  1177 // CFG_INIT_RAM_ADDR + CFG_GBL_DATA_OFFSET = 0xE4010900
  1178 lis r1,(CFG_INIT_RAM_ADDR + CFG_GBL_DATA_OFFSET)@h // r1 <= 0xE4010900,r1作堆栈指针
  1179 ori r1,(CFG_INIT_RAM_ADDR + CFG_GBL_DATA_OFFSET)@l
  1180 li r0,0 /* Make room for stack frame header and */
  1181
  1182 // 下面两条指令中有效地址为-4+r1,将r0存储到有效地址,同时r1 = -4 + r1
  1183 stwu r0,-4(r1) /* clear final stack frame so that */
  1184 stwu r0,-4(r1) /* stack backtraces terminate cleanly */
  1185
  1186 blr // 返回
  1187
  1188 un_setup_stack_in_data_cache:
  1189 blr // 返回(以下实现清零data cache中的栈的代码未执行)
  1190 mr r14,r4 // 将r4赋给r14
  1191 mr r15,r5 // 将r5赋给r15
  1192
  1193
  1194 lis r4,(CFG_INIT_RAM_ADDR & 0xFFFE0000)@h // 将CFG_INIT_RAM_ADDR()的高15位赋给r4,低17bit为0
  1195 mtspr DBAT0U,r4 // DBAT0U <= r4
  1196 ori r4,0x0002 // r4的第30bit置1
  1197 mtspr DBAT0L,r4 // DBAT0L <= r4
  1198 isync
  1199
  1200 /* un lock all the D-cache */
  1201 mfspr r4,HID0 // r4 <= HID0
  1202 lis r5,(~(HID0_DLOCK))@h // r5 <=
  1203 ori r5,(~(HID0_DLOCK))@l
  1204 and r4,r5 // r4 <= r4 & r5
  1205 sync
  1206 mtspr HID0,r4 // HID0 <= r4
  1207
  1208 /* Re - Allocate Initial RAM in data cache.*/
  1209 li r0,0 // r0 <= 0
  1210 lis r4,(CFG_INIT_RAM_ADDR)@h // r4 <= CFG_INIT_RAM_ADDR()
  1211 ori r4,(CFG_INIT_RAM_ADDR)@l
  1212 li r5,128*8 /* 128*8*32=32Kb */ // r5 <= 128*8
  1213 mtctr r5 // ctr <= r5
  1214 1:
  1215 dcbz r0,r4 // 有效地址为0+r4,数据cache块中的数据清除为0
  1216 // 为有效地址EA分配一个cache行,然后此cache行清零,会对cache行的状态进行检查.
  1217 // 当cache行不使能或被锁或处于不能被改写的状态时,此指令会引起alignment中断
  1218 addi r4,32 // r4 <= r4 + 32
  1219 bdnz 1b // ctr减,当ctr非零时后向跳转到1
  1220 isync
  1221
  1222 mflr r16 // lr <= r16
  1223 bl dcache_disable // 跳转到dcache_disable
  1224 mtlr r16 // lr <= r16
  1225
  1226 blr // 返回
  1227
  1228 #if 0 // if 零
  1229 #define GREEN_LIGHT 0x2B0D4046
  1230 #define RED_LIGHT 0x250D4046
  1231 #define LIB_CNT 0x4FFF
  1232
  1233 /*
  1234 * Lib Light
  1235 */
  1236
  1237 .globl liblight
  1238 liblight:
  1239 lis r3,CFG_IMMRBAR@h // r3 <= CFG_IMMRBAR(0xE0000000)
  1240 ori r3,CFG_IMMRBAR@l
  1241 li r4,0x3002 // r4 <= 0x3002
  1242 mtmsr r4 // 将r4赋给msr
  1243 xor r4,r4 // r4清零
  1244 mtspr HID0,r4 // HID0 = 0x0
  1245 mtspr HID2,r4 // HID2 = 0x0
  1246 lis r4,0xF8000000@h // r4 <= 0xF8000000
  1247 ori r4,0xF8000000@l
  1248 stw r4,LBLAWBAR1(r3) // Window 2(LAW1)基地址0xF8000000
  1249 lis r4,0x8000000E@h // r4 <= 0x8000000E(有效,32Kbytes)
  1250 ori r4,0x8000000E@l
  1251 stw r4,LBLAWAR1(r3) // Window 2(LAW1)有效,大小32Kbytes.
  1252 lis r4,0xF8000801@h // r4 <= 0xF8000801
  1253 ori r4,0xF8000801@l
  1254 stw r4,BR1(r3) // LBS 存储bank1 基地址0xF8000000. 8bit,valid
  1255 lis r4,0xFFFFE8f0@h // r4 <= 0xFFFFE8f0
  1256 ori r4,0xFFFFE8f0@l
  1257 stw r4,OR1(r3) // LBS 存储bank1 大小32Kbytes.
  1258
  1259 lis r4,0xF8000000@h // r4 <= 0xF8000000
  1260 ori r4,0xF8000000@l
  1261 lis r5,GREEN_LIGHT@h // r5 <= GREEN_LIGHT
  1262 ori r5,GREEN_LIGHT@l
  1263 lis r6,RED_LIGHT@h // r6 <= RED_LIGHT
  1264 ori r6,RED_LIGHT@l
  1265 lis r7,LIB_CNT@h // r7 <= LIB_CNT
  1266 ori r7,LIB_CNT@l   1267   1268 1:   1269 stw r5,0(r4) // 有效地址为r4(0xF8000000),将r5存储到有效地址. 点亮绿灯.   1270 mtctr r7 // 将r7赋给计数寄存器ctr. 循环点灯次数   1271 2: bdnz 2b // 计数寄存器ctr自减,当非0时跳转到2.   1272 stw r6,将r6存储到有效地址. 点亮红灯.   1273 mtctr r7 // 将r7赋给计数寄存器ctr. 循环点灯次数   1274 3: bdnz 3b // 计数寄存器ctr自减,当非0时跳转到3.   1275 b 1b // 前向跳转到1   1276 ??????? #endif

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读