1/* 2 * linux/arch/arm/boot/compressed/head.S 3 * 4 * Copyright (C) 1996-2002 Russell King 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2 as 8 * published by the Free Software Foundation. 9 */ 10#include <linux/config.h> 11#include <linux/linkage.h> 12 13/* 14 * Debugging stuff 15 * 16 * Note that these macros must not contain any code which is not 17 * 100% relocatable. Any attempt to do so will result in a crash. 18 * Please select one of the following when turning on debugging. 19 */ 20#ifdef DEBUG 21#if defined(CONFIG_DEBUG_DC21285_PORT) 22 .macro loadsp, rb 23 mov \rb, #0x42000000 24 .endm 25 .macro writeb, rb 26 str \rb, [r3, #0x160] 27 .endm 28#elif defined(CONFIG_DEBUG_ICEDCC) 29 .macro loadsp, rb 30 .endm 31 .macro writeb, rb 32 mcr p14, 0, \rb, c0, c1, 0 33 .endm 34#elif defined(CONFIG_FOOTBRIDGE) 35 .macro loadsp, rb 36 mov \rb, #0x7c000000 37 .endm 38 .macro writeb, rb 39 strb \rb, [r3, #0x3f8] 40 .endm 41#elif defined(CONFIG_ARCH_RPC) 42 .macro loadsp, rb 43 mov \rb, #0x03000000 44 orr \rb, \rb, #0x00010000 45 .endm 46 .macro writeb, rb 47 strb \rb, [r3, #0x3f8 << 2] 48 .endm 49#elif defined(CONFIG_ARCH_INTEGRATOR) 50 .macro loadsp, rb 51 mov \rb, #0x16000000 52 .endm 53 .macro writeb, rb 54 strb \rb, [r3, #0] 55 .endm 56#elif defined(CONFIG_ARCH_PXA) /* Xscale-type */ 57 .macro loadsp, rb 58 mov \rb, #0x40000000 59 orr \rb, \rb, #0x00100000 60 .endm 61 .macro writeb, rb 62 strb \rb, [r3, #0] 63 .endm 64#elif defined(CONFIG_ARCH_SA1100) 65 .macro loadsp, rb 66 mov \rb, #0x80000000 @ physical base address 67# if defined(CONFIG_DEBUG_LL_SER3) 68 add \rb, \rb, #0x00050000 @ Ser3 69# else 70 add \rb, \rb, #0x00010000 @ Ser1 71# endif 72 .endm 73 .macro writeb, rb 74 str \rb, [r3, #0x14] @ UTDR 75 .endm 76#elif defined(CONFIG_ARCH_IXP4XX) 77 .macro loadsp, rb 78 mov \rb, #0xc8000000 79 .endm 80 .macro writeb, rb 81 str \rb, [r3, #0] 82#elif defined(CONFIG_ARCH_IXP2000) 83 .macro loadsp, rb 84 mov \rb, #0xc0000000 85 orr \rb, \rb, #0x00030000 86 .endm 87 .macro writeb, rb 88 str \rb, [r3, #0] 89 .endm 90#elif defined(CONFIG_ARCH_LH7A40X) 91 .macro loadsp, rb 92 ldr \rb, =0x80000700 @ UART2 UARTBASE 93 .endm 94 .macro writeb, rb 95 strb \rb, [r3, #0] 96 .endm 97#elif defined(CONFIG_ARCH_OMAP) 98 .macro loadsp, rb 99 mov \rb, #0xff000000 @ physical base address 100 add \rb, \rb, #0x00fb0000 101#if defined(CONFIG_OMAP_LL_DEBUG_UART2) || defined(CONFIG_OMAP_LL_DEBUG_UART3) 102 add \rb, \rb, #0x00000800 103#endif 104#ifdef CONFIG_OMAP_LL_DEBUG_UART3 105 add \rb, \rb, #0x00009000 106#endif 107 .endm 108 .macro writeb, rb 109 strb \rb, [r3] 110 .endm 111#elif defined(CONFIG_ARCH_IOP331) 112 .macro loadsp, rb 113 mov \rb, #0xff000000 114 orr \rb, \rb, #0x00ff0000 115 orr \rb, \rb, #0x0000f700 @ location of the UART 116 .endm 117 .macro writeb, rb 118 str \rb, [r3, #0] 119 .endm 120#elif defined(CONFIG_ARCH_S3C2410) 121 .macro loadsp, rb 122 mov \rb, #0x50000000 123 add \rb, \rb, #0x4000 * CONFIG_S3C2410_LOWLEVEL_UART_PORT 124 .endm 125 .macro writeb, rb 126 strb \rb, [r3, #0x20] 127 .endm 128#else 129#error no serial architecture defined 130#endif 131#endif 132 133 .macro kputc,val 134 mov r0, \val 135 bl putc 136 .endm 137 138 .macro kphex,val,len 139 mov r0, \val 140 mov r1, #\len 141 bl phex 142 .endm 143 144 .macro debug_reloc_start 145#ifdef DEBUG 146 kputc #'\n' 147 kphex r6, 8 /* processor id */ 148 kputc #':' 149 kphex r7, 8 /* architecture id */ 150 kputc #':' 151 mrc p15, 0, r0, c1, c0 152 kphex r0, 8 /* control reg */ 153 kputc #'\n' 154 kphex r5, 8 /* decompressed kernel start */ 155 kputc #'-' 156 kphex r8, 8 /* decompressed kernel end */ 157 kputc #'>' 158 kphex r4, 8 /* kernel execution address */ 159 kputc #'\n' 160#endif 161 .endm 162 163 .macro debug_reloc_end 164#ifdef DEBUG 165 kphex r5, 8 /* end of kernel */ 166 kputc #'\n' 167 mov r0, r4 168 bl memdump /* dump 256 bytes at start of kernel */ 169#endif 170 .endm 171 172 .section ".start", #alloc, #execinstr 173/* 174 * sort out different calling conventions 175 */ 176 .align 177start: 178 .type start,#function 179 .rept 8 180 mov r0, r0 181 .endr 182 183 b 1f 184 .word 0x016f2818 @ Magic numbers to help the loader 185 .word start @ absolute load/run zImage address 186 .word _edata @ zImage end address 1871: mov r7, r1 @ save architecture ID 188 mov r8, #0 @ save r0 189 190#ifndef __ARM_ARCH_2__ 191 /* 192 * Booting from Angel - need to enter SVC mode and disable 193 * FIQs/IRQs (numeric definitions from angel arm.h source). 194 * We only do this if we were in user mode on entry. 195 */ 196 mrs r2, cpsr @ get current mode 197 tst r2, #3 @ not user? 198 bne not_angel 199 mov r0, #0x17 @ angel_SWIreason_EnterSVC 200 swi 0x123456 @ angel_SWI_ARM 201not_angel: 202 mrs r2, cpsr @ turn off interrupts to 203 orr r2, r2, #0xc0 @ prevent angel from running 204 msr cpsr_c, r2 205#else 206 teqp pc, #0x0c000003 @ turn off interrupts 207#endif 208 209 /* 210 * Note that some cache flushing and other stuff may 211 * be needed here - is there an Angel SWI call for this? 212 */ 213 214 /* 215 * some architecture specific code can be inserted 216 * by the linker here, but it should preserve r7 and r8. 217 */ 218 219 .text 220 adr r0, LC0 221 ldmia r0, {r1, r2, r3, r4, r5, r6, ip, sp} 222 subs r0, r0, r1 @ calculate the delta offset 223 224 @ if delta is zero, we are 225 beq not_relocated @ running at the address we 226 @ were linked at. 227 228 /* 229 * We're running at a different address. We need to fix 230 * up various pointers: 231 * r5 - zImage base address 232 * r6 - GOT start 233 * ip - GOT end 234 */ 235 add r5, r5, r0 236 add r6, r6, r0 237 add ip, ip, r0 238 239#ifndef CONFIG_ZBOOT_ROM 240 /* 241 * If we're running fully PIC === CONFIG_ZBOOT_ROM = n, 242 * we need to fix up pointers into the BSS region. 243 * r2 - BSS start 244 * r3 - BSS end 245 * sp - stack pointer 246 */ 247 add r2, r2, r0 248 add r3, r3, r0 249 add sp, sp, r0 250 251 /* 252 * Relocate all entries in the GOT table. 253 */ 2541: ldr r1, [r6, #0] @ relocate entries in the GOT 255 add r1, r1, r0 @ table. This fixes up the 256 str r1, [r6], #4 @ C references. 257 cmp r6, ip 258 blo 1b 259#else 260 261 /* 262 * Relocate entries in the GOT table. We only relocate 263 * the entries that are outside the (relocated) BSS region. 264 */ 2651: ldr r1, [r6, #0] @ relocate entries in the GOT 266 cmp r1, r2 @ entry < bss_start || 267 cmphs r3, r1 @ _end < entry 268 addlo r1, r1, r0 @ table. This fixes up the 269 str r1, [r6], #4 @ C references. 270 cmp r6, ip 271 blo 1b 272#endif 273 274not_relocated: mov r0, #0 2751: str r0, [r2], #4 @ clear bss 276 str r0, [r2], #4 277 str r0, [r2], #4 278 str r0, [r2], #4 279 cmp r2, r3 280 blo 1b 281 282 /* 283 * The C runtime environment should now be setup 284 * sufficiently. Turn the cache on, set up some 285 * pointers, and start decompressing. 286 */ 287 bl cache_on 288 289 mov r1, sp @ malloc space above stack 290 add r2, sp, #0x10000 @ 64k max 291 292/* 293 * Check to see if we will overwrite ourselves. 294 * r4 = final kernel address 295 * r5 = start of this image 296 * r2 = end of malloc space (and therefore this image) 297 * We basically want: 298 * r4 >= r2 -> OK 299 * r4 + image length <= r5 -> OK 300 */ 301 cmp r4, r2 302 bhs wont_overwrite 303 add r0, r4, #4096*1024 @ 4MB largest kernel size 304 cmp r0, r5 305 bls wont_overwrite 306 307 mov r5, r2 @ decompress after malloc space 308 mov r0, r5 309 mov r3, r7 310 bl decompress_kernel 311 312 add r0, r0, #127 313 bic r0, r0, #127 @ align the kernel length 314/* 315 * r0 = decompressed kernel length 316 * r1-r3 = unused 317 * r4 = kernel execution address 318 * r5 = decompressed kernel start 319 * r6 = processor ID 320 * r7 = architecture ID 321 * r8-r14 = unused 322 */ 323 add r1, r5, r0 @ end of decompressed kernel 324 adr r2, reloc_start 325 ldr r3, LC1 326 add r3, r2, r3 3271: ldmia r2!, {r8 - r13} @ copy relocation code 328 stmia r1!, {r8 - r13} 329 ldmia r2!, {r8 - r13} 330 stmia r1!, {r8 - r13} 331 cmp r2, r3 332 blo 1b 333 334 bl cache_clean_flush 335 add pc, r5, r0 @ call relocation code 336 337/* 338 * We're not in danger of overwriting ourselves. Do this the simple way. 339 * 340 * r4 = kernel execution address 341 * r7 = architecture ID 342 */ 343wont_overwrite: mov r0, r4 344 mov r3, r7 345 bl decompress_kernel 346 b call_kernel 347 348 .type LC0, #object 349LC0: .word LC0 @ r1 350 .word __bss_start @ r2 351 .word _end @ r3 352 .word zreladdr @ r4 353 .word _start @ r5 354 .word _got_start @ r6 355 .word _got_end @ ip 356 .word user_stack+4096 @ sp 357LC1: .word reloc_end - reloc_start 358 .size LC0, . - LC0 359 360#ifdef CONFIG_ARCH_RPC 361 .globl params 362params: ldr r0, =params_phys 363 mov pc, lr 364 .ltorg 365 .align 366#endif 367 368/* 369 * Turn on the cache. We need to setup some page tables so that we 370 * can have both the I and D caches on. 371 * 372 * We place the page tables 16k down from the kernel execution address, 373 * and we hope that nothing else is using it. If we're using it, we 374 * will go pop! 375 * 376 * On entry, 377 * r4 = kernel execution address 378 * r6 = processor ID 379 * r7 = architecture number 380 * r8 = run-time address of "start" 381 * On exit, 382 * r1, r2, r3, r8, r9, r12 corrupted 383 * This routine must preserve: 384 * r4, r5, r6, r7 385 */ 386 .align 5 387cache_on: mov r3, #8 @ cache_on function 388 b call_cache_fn 389 390__setup_mmu: sub r3, r4, #16384 @ Page directory size 391 bic r3, r3, #0xff @ Align the pointer 392 bic r3, r3, #0x3f00 393/* 394 * Initialise the page tables, turning on the cacheable and bufferable 395 * bits for the RAM area only. 396 */ 397 mov r0, r3 398 mov r8, r0, lsr #18 399 mov r8, r8, lsl #18 @ start of RAM 400 add r9, r8, #0x10000000 @ a reasonable RAM size 401 mov r1, #0x12 402 orr r1, r1, #3 << 10 403 add r2, r3, #16384 4041: cmp r1, r8 @ if virt > start of RAM 405 orrhs r1, r1, #0x0c @ set cacheable, bufferable 406 cmp r1, r9 @ if virt > end of RAM 407 bichs r1, r1, #0x0c @ clear cacheable, bufferable 408 str r1, [r0], #4 @ 1:1 mapping 409 add r1, r1, #1048576 410 teq r0, r2 411 bne 1b 412/* 413 * If ever we are running from Flash, then we surely want the cache 414 * to be enabled also for our execution instance... We map 2MB of it 415 * so there is no map overlap problem for up to 1 MB compressed kernel. 416 * If the execution is in RAM then we would only be duplicating the above. 417 */ 418 mov r1, #0x1e 419 orr r1, r1, #3 << 10 420 mov r2, pc, lsr #20 421 orr r1, r1, r2, lsl #20 422 add r0, r3, r2, lsl #2 423 str r1, [r0], #4 424 add r1, r1, #1048576 425 str r1, [r0] 426 mov pc, lr 427 428__armv4_cache_on: 429 mov r12, lr 430 bl __setup_mmu 431 mov r0, #0 432 mcr p15, 0, r0, c7, c10, 4 @ drain write buffer 433 mcr p15, 0, r0, c8, c7, 0 @ flush I,D TLBs 434 mrc p15, 0, r0, c1, c0, 0 @ read control reg 435 orr r0, r0, #0x5000 @ I-cache enable, RR cache replacement 436 orr r0, r0, #0x0030 437 bl __common_cache_on 438 mov r0, #0 439 mcr p15, 0, r0, c8, c7, 0 @ flush I,D TLBs 440 mov pc, r12 441 442__arm6_cache_on: 443 mov r12, lr 444 bl __setup_mmu 445 mov r0, #0 446 mcr p15, 0, r0, c7, c0, 0 @ invalidate whole cache v3 447 mcr p15, 0, r0, c5, c0, 0 @ invalidate whole TLB v3 448 mov r0, #0x30 449 bl __common_cache_on 450 mov r0, #0 451 mcr p15, 0, r0, c5, c0, 0 @ invalidate whole TLB v3 452 mov pc, r12 453 454__common_cache_on: 455#ifndef DEBUG 456 orr r0, r0, #0x000d @ Write buffer, mmu 457#endif 458 mov r1, #-1 459 mcr p15, 0, r3, c2, c0, 0 @ load page table pointer 460 mcr p15, 0, r1, c3, c0, 0 @ load domain access control 461 mcr p15, 0, r0, c1, c0, 0 @ load control register 462 mov pc, lr 463 464/* 465 * All code following this line is relocatable. It is relocated by 466 * the above code to the end of the decompressed kernel image and 467 * executed there. During this time, we have no stacks. 468 * 469 * r0 = decompressed kernel length 470 * r1-r3 = unused 471 * r4 = kernel execution address 472 * r5 = decompressed kernel start 473 * r6 = processor ID 474 * r7 = architecture ID 475 * r8-r14 = unused 476 */ 477 .align 5 478reloc_start: add r8, r5, r0 479 debug_reloc_start 480 mov r1, r4 4811: 482 .rept 4 483 ldmia r5!, {r0, r2, r3, r9 - r13} @ relocate kernel 484 stmia r1!, {r0, r2, r3, r9 - r13} 485 .endr 486 487 cmp r5, r8 488 blo 1b 489 debug_reloc_end 490 491call_kernel: bl cache_clean_flush 492 bl cache_off 493 mov r0, #0 494 mov r1, r7 @ restore architecture number 495 mov pc, r4 @ call kernel 496 497/* 498 * Here follow the relocatable cache support functions for the 499 * various processors. This is a generic hook for locating an 500 * entry and jumping to an instruction at the specified offset 501 * from the start of the block. Please note this is all position 502 * independent code. 503 * 504 * r1 = corrupted 505 * r2 = corrupted 506 * r3 = block offset 507 * r6 = corrupted 508 * r12 = corrupted 509 */ 510 511call_cache_fn: adr r12, proc_types 512 mrc p15, 0, r6, c0, c0 @ get processor ID 5131: ldr r1, [r12, #0] @ get value 514 ldr r2, [r12, #4] @ get mask 515 eor r1, r1, r6 @ (real ^ match) 516 tst r1, r2 @ & mask 517 addeq pc, r12, r3 @ call cache function 518 add r12, r12, #4*5 519 b 1b 520 521/* 522 * Table for cache operations. This is basically: 523 * - CPU ID match 524 * - CPU ID mask 525 * - 'cache on' method instruction 526 * - 'cache off' method instruction 527 * - 'cache flush' method instruction 528 * 529 * We match an entry using: ((real_id ^ match) & mask) == 0 530 * 531 * Writethrough caches generally only need 'on' and 'off' 532 * methods. Writeback caches _must_ have the flush method 533 * defined. 534 */ 535 .type proc_types,#object 536proc_types: 537 .word 0x41560600 @ ARM6/610 538 .word 0xffffffe0 539 b __arm6_cache_off @ works, but slow 540 b __arm6_cache_off 541 mov pc, lr 542@ b __arm6_cache_on @ untested 543@ b __arm6_cache_off 544@ b __armv3_cache_flush 545 546 .word 0x00000000 @ old ARM ID 547 .word 0x0000f000 548 mov pc, lr 549 mov pc, lr 550 mov pc, lr 551 552 .word 0x41007000 @ ARM7/710 553 .word 0xfff8fe00 554 b __arm7_cache_off 555 b __arm7_cache_off 556 mov pc, lr 557 558 .word 0x41807200 @ ARM720T (writethrough) 559 .word 0xffffff00 560 b __armv4_cache_on 561 b __armv4_cache_off 562 mov pc, lr 563 564 .word 0x00007000 @ ARM7 IDs 565 .word 0x0000f000 566 mov pc, lr 567 mov pc, lr 568 mov pc, lr 569 570 @ Everything from here on will be the new ID system. 571 572 .word 0x4401a100 @ sa110 / sa1100 573 .word 0xffffffe0 574 b __armv4_cache_on 575 b __armv4_cache_off 576 b __armv4_cache_flush 577 578 .word 0x6901b110 @ sa1110 579 .word 0xfffffff0 580 b __armv4_cache_on 581 b __armv4_cache_off 582 b __armv4_cache_flush 583 584 @ These match on the architecture ID 585 586 .word 0x00020000 @ ARMv4T 587 .word 0x000f0000 588 b __armv4_cache_on 589 b __armv4_cache_off 590 b __armv4_cache_flush 591 592 .word 0x00050000 @ ARMv5TE 593 .word 0x000f0000 594 b __armv4_cache_on 595 b __armv4_cache_off 596 b __armv4_cache_flush 597 598 .word 0x00060000 @ ARMv5TEJ 599 .word 0x000f0000 600 b __armv4_cache_on 601 b __armv4_cache_off 602 b __armv4_cache_flush 603 604 .word 0x00070000 @ ARMv6 605 .word 0x000f0000 606 b __armv4_cache_on 607 b __armv4_cache_off 608 b __armv6_cache_flush 609 610 .word 0 @ unrecognised type 611 .word 0 612 mov pc, lr 613 mov pc, lr 614 mov pc, lr 615 616 .size proc_types, . - proc_types 617 618/* 619 * Turn off the Cache and MMU. ARMv3 does not support 620 * reading the control register, but ARMv4 does. 621 * 622 * On entry, r6 = processor ID 623 * On exit, r0, r1, r2, r3, r12 corrupted 624 * This routine must preserve: r4, r6, r7 625 */ 626 .align 5 627cache_off: mov r3, #12 @ cache_off function 628 b call_cache_fn 629 630__armv4_cache_off: 631 mrc p15, 0, r0, c1, c0 632 bic r0, r0, #0x000d 633 mcr p15, 0, r0, c1, c0 @ turn MMU and cache off 634 mov r0, #0 635 mcr p15, 0, r0, c7, c7 @ invalidate whole cache v4 636 mcr p15, 0, r0, c8, c7 @ invalidate whole TLB v4 637 mov pc, lr 638 639__arm6_cache_off: 640 mov r0, #0x00000030 @ ARM6 control reg. 641 b __armv3_cache_off 642 643__arm7_cache_off: 644 mov r0, #0x00000070 @ ARM7 control reg. 645 b __armv3_cache_off 646 647__armv3_cache_off: 648 mcr p15, 0, r0, c1, c0, 0 @ turn MMU and cache off 649 mov r0, #0 650 mcr p15, 0, r0, c7, c0, 0 @ invalidate whole cache v3 651 mcr p15, 0, r0, c5, c0, 0 @ invalidate whole TLB v3 652 mov pc, lr 653 654/* 655 * Clean and flush the cache to maintain consistency. 656 * 657 * On entry, 658 * r6 = processor ID 659 * On exit, 660 * r1, r2, r3, r11, r12 corrupted 661 * This routine must preserve: 662 * r0, r4, r5, r6, r7 663 */ 664 .align 5 665cache_clean_flush: 666 mov r3, #16 667 b call_cache_fn 668 669__armv6_cache_flush: 670 mov r1, #0 671 mcr p15, 0, r1, c7, c14, 0 @ clean+invalidate D 672 mcr p15, 0, r1, c7, c5, 0 @ invalidate I+BTB 673 mcr p15, 0, r1, c7, c15, 0 @ clean+invalidate unified 674 mcr p15, 0, r1, c7, c10, 4 @ drain WB 675 mov pc, lr 676 677__armv4_cache_flush: 678 mov r2, #64*1024 @ default: 32K dcache size (*2) 679 mov r11, #32 @ default: 32 byte line size 680 mrc p15, 0, r3, c0, c0, 1 @ read cache type 681 teq r3, r6 @ cache ID register present? 682 beq no_cache_id 683 mov r1, r3, lsr #18 684 and r1, r1, #7 685 mov r2, #1024 686 mov r2, r2, lsl r1 @ base dcache size *2 687 tst r3, #1 << 14 @ test M bit 688 addne r2, r2, r2, lsr #1 @ +1/2 size if M == 1 689 mov r3, r3, lsr #12 690 and r3, r3, #3 691 mov r11, #8 692 mov r11, r11, lsl r3 @ cache line size in bytes 693no_cache_id: 694 bic r1, pc, #63 @ align to longest cache line 695 add r2, r1, r2 6961: ldr r3, [r1], r11 @ s/w flush D cache 697 teq r1, r2 698 bne 1b 699 700 mcr p15, 0, r1, c7, c5, 0 @ flush I cache 701 mcr p15, 0, r1, c7, c6, 0 @ flush D cache 702 mcr p15, 0, r1, c7, c10, 4 @ drain WB 703 mov pc, lr 704 705__armv3_cache_flush: 706 mov r1, #0 707 mcr p15, 0, r0, c7, c0, 0 @ invalidate whole cache v3 708 mov pc, lr 709 710/* 711 * Various debugging routines for printing hex characters and 712 * memory, which again must be relocatable. 713 */ 714#ifdef DEBUG 715 .type phexbuf,#object 716phexbuf: .space 12 717 .size phexbuf, . - phexbuf 718 719phex: adr r3, phexbuf 720 mov r2, #0 721 strb r2, [r3, r1] 7221: subs r1, r1, #1 723 movmi r0, r3 724 bmi puts 725 and r2, r0, #15 726 mov r0, r0, lsr #4 727 cmp r2, #10 728 addge r2, r2, #7 729 add r2, r2, #'0' 730 strb r2, [r3, r1] 731 b 1b 732 733puts: loadsp r3 7341: ldrb r2, [r0], #1 735 teq r2, #0 736 moveq pc, lr 7372: writeb r2 738 mov r1, #0x00020000 7393: subs r1, r1, #1 740 bne 3b 741 teq r2, #'\n' 742 moveq r2, #'\r' 743 beq 2b 744 teq r0, #0 745 bne 1b 746 mov pc, lr 747putc: 748 mov r2, r0 749 mov r0, #0 750 loadsp r3 751 b 2b 752 753memdump: mov r12, r0 754 mov r10, lr 755 mov r11, #0 7562: mov r0, r11, lsl #2 757 add r0, r0, r12 758 mov r1, #8 759 bl phex 760 mov r0, #':' 761 bl putc 7621: mov r0, #' ' 763 bl putc 764 ldr r0, [r12, r11, lsl #2] 765 mov r1, #8 766 bl phex 767 and r0, r11, #7 768 teq r0, #3 769 moveq r0, #' ' 770 bleq putc 771 and r0, r11, #7 772 add r11, r11, #1 773 teq r0, #7 774 bne 1b 775 mov r0, #'\n' 776 bl putc 777 cmp r11, #64 778 blt 2b 779 mov pc, r10 780#endif 781 782reloc_end: 783 784 .align 785 .section ".stack", "w" 786user_stack: .space 4096 787