Chinaunix首页 | 论坛 | 博客
  • 博客访问: 502664
  • 博文数量: 157
  • 博客积分: 3010
  • 博客等级: 中校
  • 技术积分: 1608
  • 用 户 组: 普通用户
  • 注册时间: 2008-08-16 09:30
文章存档

2010年(155)

2008年(2)

我的朋友

分类: LINUX

2010-04-30 11:32:39

?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, "\0"
?? 113
?? 114 .text
?? 115 #define _HRCW_TABLE_ENTRY(w) \
?? 116 .fill 8,1,(((w)>>24)&0xff); \ // 在文本段开始填入w的高8bit字节,重复8次
?? 117 .fill 8,1,(((w)>>16)&0xff); \
?? 118 .fill 8,1,(((w)>> 8)&0xff); \
?? 119 .fill 8,1,(((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的高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的高16bit(bit0 ~ 15)带符号赋给r3,并左移16bit, r3低16bit为0
?? 180 ori r3, r3, // 将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, r4, 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, // 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,0,16,16 /* copy EE bit from saved MSR */ // 保存msr的EE和IP位以备恢复
?? 294 rlwimi r20,r23,0,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,r1,STACK_FRAME_OVERHEAD // 16
?? 311 li r20,MSR_KERNEL
?? 312 rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */
?? 313 rlwimi r20,r23,0,25,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,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,r23,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,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, 0, 25, 25 /* preserve IP bit set by HRCW */
?? 473 #ifdef DEBUG
?? 474 rlwimi r3, r5, 0, 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 赋给r3(高16bit同,低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, 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, )
?? 495 lis r4, 0xAA39
?? 496 sth r4, )
?? 497 #else
?? 498 /* Disable Wathcdog */
?? 499 /*-------------------*/
?? 500 xor r4, 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, // MPC8349ITX.h定义CFG_HID0_INIT为0x0, r3 <= CFG_HID0_INIT
?? 509 ori r3, r3,
?? 510 SYNC // ppc_asm.tmpl中#define SYNC sync; isync
?? 511 mtspr HID0, r3 // 将r3赋给专用寄存器HID0(SPR 0x3F0)
?? 512
?? 513 lis r3, // MPC8349ITX.h定义CFG_HID0_FINAL为0x0
?? 514 ori r3, r3,
?? 515 SYNC
?? 516 mtspr HID0, r3 // 将r3赋给专用寄存器HID0(SPR 0x3F0)
?? 517
?? 518 lis r3, // MPC8349ITX.h定义CFG_HID2为0x0
?? 519 ori r3, r3,
?? 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清零,然后将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, 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, r3, HID0_ICE // 第16bit HID0[ICE]置1: 指令cache使能位
?? 599 lis r4, 0 // r4清零
?? 600 ori r4, r4, HID0_ILOCK // 第17bit HID0[ILOCK]置1: 指令cache锁
?? 601 andc r3, r3, r4 // r3与r4的补数,保证r3的ILOCK位清零,其余不变
?? 602 ori r4, r3, 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, r4, HID0_ICE|HID0_ILOCK // 第 16bit为1 指令cache使能位.
?? 614 // 19bit为1 指令cache锁,在设置HID0[ILOCK]位之前应执行一次isync指令
?? 615 andc r3, r3, r4 // 清零r3的ICE和ILOCK位,其余不变
?? 616 ori r4, r3, 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, 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, r3, HID0_ENABLE_DATA_CACHE // r3的第17bit(HID0[DCE])位为1
?? 633 lis r4, 0 // r4 <= 0
?? 634 ori r4, r4, HID0_LOCK_DATA_CACHE // r4: HID0[DLOCK]为1
?? 635 andc r3, r3, r4 // r3的DLOCK位清零,其余不变
?? 636 ori r4, r3, HID0_LOCK_INSTRUCTION_CACHE // r4: ILOCK位为1,其余和r3同
?? 637 sync
?? 638 mtspr HID0, r4 /* sets enable and invalidate, 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, r4, HID0_ENABLE_DATA_CACHE|HID0_LOCK_DATA_CACHE // r4的HID0[DCE]和HID0[DLOCK]为1
?? 648 andc r3, r3, r4 // r3的HID0[DCE]和HID0[DLOCK]清零,其余不变
?? 649 ori r4, r3, HID0_INVALIDATE_DATA_CACHE // r4的DCFI为1, DCE和DLOCK为0
?? 650 sync
?? 651 mtspr HID0, r4 /* sets invalidate, 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, r3, HID0_DCE_SHIFT, 31, 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, /* Source Address */
?? 695 ori r4, r4, // 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, 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,r3,r4 // r3和r4逻辑(无符号数)比较,比较结果存入cr1
?? 721 addi r0,r5,3 // r0 <= r5 + 3
?? 722 srwi. r0,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, r4, -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,r5,3 // r0 <= r5 + 3
?? 737 srwi. r0,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,4(r8) // 有效地址(EA)r8+4, 将EA的字(32bit)加载到r20,将EA存入r8
?? 744 lwzu r21,4(r7) // 有效地址(EA)r7+4, 将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,r0,2 /* re copy in reverse order ... y do we needed it? */
?? 755 // r0左移2bit, 恢复
?? 756 add r8,r4,r0 // r8 <= r4 + r0
?? 757 add r7,r3,r0 // r7 <= r3 + r0
?? 758 3: lwzu r0,-4(r8) // 有效地址(EA)r8-4, 将EA的字加载到r0, 将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,r3,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,r3,r0 // r3和r0的补数逻辑与,结果存入r3
?? 781 mfspr r7,HID0 /* don't do dcbst if dcache is disabled*/ // r7 <= HID0
?? 782 rlwinm r7,r7,HID0_DCE_SHIFT,31,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,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,r7,HID0_DCE_SHIFT,31,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,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, r10, 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,r3,r11 // r11 <= r3 - r11 ; 代码搬运前后的GOT表相对偏移
?? 829 addi r3,r3,-4 // r3 <= r3 - 4
?? 830 1: lwzu r0,4(r3) // 有效地址(EA)r3+4, 将EA的内容加载到r0, 同时EA存入r3
?? 831 add r0,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,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,r4,r11 // 有效地址r4+r11, 将EA的内容存入r0, 同时将EA存入r4
?? 848 add r0,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, r3, 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, r3, 4 // r3 <= r3 + 4
?? 879 cmplw 0, r3, 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, r7, 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, r7, 4 // r7 <= r7 + 4
?? 914 addi r9, r9, 4 // r9 <= r9 + 4
?? 915 cmplw 0, r7, 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, r7, 0x100 /* next exception vector */
?? 927 cmplw 0, r7, 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, r7, 0x100 /* next exception vector */
?? 941 cmplw 0, r7, 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, r7, 0x100 /* next exception vector */
?? 949 cmplw 0, r7, r8
?? 950 blt 4b
?? 951
?? 952 mfmsr r3 /* now that the vectors have */ // r3 <= msr
?? 953 lis r7, /* relocated into low memory */ // r7 <= (1 << 6)
?? 954 ori r7, r7, /* MSR[IP] can be turned off */
?? 955 andc r3, 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, 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, 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, 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, r3 // 有效地址为 0+r3, dcbi为数据cache块无效指令
?? 991 // 该两条指令将有效地址EA所在的指令/数据cache行置为无效
?? 992 addi r3, 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, ) // 将local bus OR0赋给r4.
??1005 li r5, 0x7fff /* r5 <= 0x00007FFFF */
??1006 and r4, r4, r5 // 保留r4的低15bit,其余清零
??1007 stw r4, ) /* 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, 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, r4, (0x80000017)@l // 窗口使能,设置窗口大小16Mbytes
??1040 #else
??1041 lis r4, (0x80000016)@h
??1042 ori r4, 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, // r5 <= 0xf8000801
??1057 ori r5, r5,
??1058 stw r5, BR1(r3) /* [r3+BR1] <= 0xF8000801 */
??1059 // 将r5赋给local bus BR1寄存器,设基址0xF8000000, 端口size为8bit, GPCM, valid
??1060
??1061 lis r5,
??1062 ori r5, r5,
??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, r4, r5 // r4 <= (BR0) & 0x7FFF 低15bit不变,高17位清零
??1070 lis r5, (CFG_FLASH_BASE & 0xFFFF8000)@h // CFG_FLASH_BASE的高17bit不变,其余清零
??1071 ori r5, r5, (CFG_FLASH_BASE & 0xFFFF8000)@l
??1072 or r5, r5, r4
??1073 stw r5, BR0(r3) /* r5 <= (CFG_FLASH_BASE & 0xFFFF8000) | (BR0 & 0x00007FFF) */
??1074 // 设置LBCR BR0,基址为CFG_FLASH_BASE(0xFE000000), 其余和复位值有关(16bit, GPCM, valid)
??1075
??1076 lwz r4, OR0(r3) // 将LBCR OR0赋给r4, 复位后OR[AM]=0x0,即存储bank 大小为4Gbytes.
??1077 #ifdef CONFIG_MPC8349ITX
??1078 lis r5, /* 16M, each flash is 8M and share the same CS0 */
??1079 ori r5, r5, // r5 <= 0xFF000FF7
??1080 stw r5, OR0(r3) // 设置LBCR OR0为r5, 设置存储bank大小为16M
??1081 #else
??1082 lis r5, 0xFF80 /* 8M */
??1083 or r4, 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, 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, r4, (0x80000017)@l
??1095 #else
??1096 lis r4, (0x80000016)@h
??1097 ori r4, 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 // 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, 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, 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, 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, r4, HID0_DCE | HID0_DCI // r4第17bit, 21bit置1 HID0[DCE]=1 HID0[DCFI]=1
??1130 ori r5, 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, 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, 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, 0, 0xffff // r5 <= (0x0 & 0xffff) << 16 --- r5: 0xFFFF0000
??1161 ori r5, r5, 0xffcf /* turn off address translation */ // r5: 0xFFFFFFCF
??1162 and r4, 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, 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, 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, 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, r5, (~(HID0_DLOCK))@l
??1204 and r4, 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, 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, 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, // r3 <= CFG_IMMRBAR(0xE0000000)
??1240 ori r3, r3,
??1241 li r4, 0x3002 // r4 <= 0x3002
??1242 mtmsr r4 // 将r4赋给msr
??1243 xor r4, r4, r4 // r4清零
??1244 mtspr HID0, r4 // HID0 = 0x0
??1245 mtspr HID2, r4 // HID2 = 0x0
??1246 lis r4, // r4 <= 0xF8000000
??1247 ori r4, r4,
??1248 stw r4, LBLAWBAR1(r3) // Window 2(LAW1)基地址0xF8000000
??1249 lis r4, // r4 <= 0x8000000E(有效,32Kbytes)
??1250 ori r4, r4,
??1251 stw r4, LBLAWAR1(r3) // Window 2(LAW1)有效,大小32Kbytes.
??1252 lis r4, // r4 <= 0xF8000801
??1253 ori r4, r4,
??1254 stw r4, BR1(r3) // LBS 存储bank1 基地址0xF8000000. 8bit, GPCM, valid
??1255 lis r4, // r4 <= 0xFFFFE8f0
??1256 ori r4, r4,
??1257 stw r4, OR1(r3) // LBS 存储bank1 大小32Kbytes.
??1258
??1259 lis r4, // r4 <= 0xF8000000
??1260 ori r4, r4,
??1261 lis r5, // r5 <= GREEN_LIGHT
??1262 ori r5, r5,
??1263 lis r6, // r6 <= RED_LIGHT
??1264 ori r6, r6,
??1265 lis r7, // r7 <= LIB_CNT
??1266 ori r7, r7,
??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, 0(r4) // 有效地址为r4(0xF8000000),将r6存储到有效地址. 点亮红灯.
??1273 mtctr r7 // 将r7赋给计数寄存器ctr. 循环点灯次数
??1274 3: bdnz 3b // 计数寄存器ctr自减,当非0时跳转到3.
??1275 b 1b // 前向跳转到1
??1276
??1277 #endif
??1278
??1279
??1280 // 参考文献:
??1281 // Programming Environments Manual for 32-Bit Implementations of the PowerPC(TM) Architecture .USA: Freescale Semiconductor.Rev.3 2005.9【天涯博客】本文地址http://blog.tianya.cn/blogger/post_show.asp?idWriter=0&Key=0&BlogID=658309&PostID=23458582
阅读(3652) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~