locore-v6.S revision 282024
1276396Sian/*- 2276396Sian * Copyright 2004-2014 Olivier Houchard <cognet@FreeBSD.org> 3276396Sian * Copyright 2012-2014 Ian Lepore <ian@FreeBSD.org> 4276396Sian * Copyright 2013-2014 Andrew Turner <andrew@FreeBSD.org> 5276396Sian * Copyright 2014 Svatopluk Kraus <onwahe@gmail.com> 6276396Sian * Copyright 2014 Michal Meloun <meloun@miracle.cz> 7276396Sian * All rights reserved. 8276396Sian * 9276396Sian * Redistribution and use in source and binary forms, with or without 10276396Sian * modification, are permitted provided that the following conditions 11276396Sian * are met: 12276396Sian * 1. Redistributions of source code must retain the above copyright 13276396Sian * notice, this list of conditions and the following disclaimer. 14276396Sian * 2. Redistributions in binary form must reproduce the above copyright 15276396Sian * notice, this list of conditions and the following disclaimer in the 16276396Sian * documentation and/or other materials provided with the distribution. 17276396Sian * 18276396Sian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19276396Sian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20276396Sian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21276396Sian * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22276396Sian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23276396Sian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24276396Sian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25276396Sian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26276396Sian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27276396Sian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28276396Sian * SUCH DAMAGE. 29276396Sian */ 30276396Sian 31276396Sian#include "assym.s" 32276396Sian#include <sys/syscall.h> 33276396Sian#include <machine/asm.h> 34276396Sian#include <machine/asmacros.h> 35276396Sian#include <machine/armreg.h> 36276396Sian#include <machine/sysreg.h> 37276396Sian#include <machine/cpuconf.h> 38276396Sian#include <machine/pte.h> 39276396Sian 40276396Sian__FBSDID("$FreeBSD: head/sys/arm/arm/locore-v6.S 282024 2015-04-26 16:18:41Z andrew $"); 41276396Sian 42276396Sian#ifndef ARM_NEW_PMAP 43276396Sian#define PTE1_OFFSET L1_S_OFFSET 44276396Sian#define PTE1_SHIFT L1_S_SHIFT 45276396Sian#define PTE1_SIZE L1_S_SIZE 46276396Sian#endif 47276396Sian 48276396Sian/* A small statically-allocated stack used only during initarm() and AP startup. */ 49276396Sian#define INIT_ARM_STACK_SIZE 2048 50276396Sian 51276396Sian .text 52276596Sian .align 2 53276396Sian 54276396Sian/* 55282024Sandrew * On entry for FreeBSD boot ABI: 56282024Sandrew * r0 - metadata pointer or 0 (boothowto on AT91's boot2) 57282024Sandrew * r1 - if (r0 == 0) then metadata pointer 58282024Sandrew * On entry for Linux boot ABI: 59276396Sian * r0 - 0 60276396Sian * r1 - machine type (passed as arg2 to initarm) 61282024Sandrew * r2 - Pointer to a tagged list or dtb image (phys addr) (passed as arg1 initarm) 62276396Sian * 63276396Sian * For both types of boot we gather up the args, put them in a struct arm_boot_params 64276396Sian * structure and pass that to initarm. 65276396Sian */ 66276396Sian .globl btext 67276396Sianbtext: 68276396SianASENTRY_NP(_start) 69282024Sandrew STOP_UNWINDING /* Can't unwind into the bootloader! */ 70276396Sian 71282024Sandrew /* Make sure interrupts are disabled. */ 72276396Sian cpsid ifa 73276396Sian 74282024Sandrew mov r8, r0 /* 0 or boot mode from boot2 */ 75282024Sandrew mov r9, r1 /* Save Machine type */ 76282024Sandrew mov r10, r2 /* Save meta data */ 77276396Sian mov r11, r3 /* Future expansion */ 78276396Sian 79282024Sandrew /* 80276396Sian * Check whether data cache is enabled. If it is, then we know 81276396Sian * current tags are valid (not power-on garbage values) and there 82276396Sian * might be dirty lines that need cleaning. Disable cache to prevent 83276396Sian * new lines being allocated, then call wbinv_poc_all to clean it. 84276396Sian */ 85276396Sian mrc CP15_SCTLR(r7) 86276396Sian tst r7, #CPU_CONTROL_DC_ENABLE 87276445Sian blne dcache_wbinv_poc_all 88276396Sian 89276445Sian /* ! Do not write to memory between wbinv and disabling cache ! */ 90276445Sian 91276396Sian /* 92276396Sian * Now there are no dirty lines, but there may still be lines marked 93276396Sian * valid. Disable all caches and the MMU, and invalidate everything 94276396Sian * before setting up new page tables and re-enabling the mmu. 95276396Sian */ 96276396Sian1: 97276445Sian bic r7, #CPU_CONTROL_DC_ENABLE 98276396Sian bic r7, #CPU_CONTROL_MMU_ENABLE 99276396Sian bic r7, #CPU_CONTROL_IC_ENABLE 100276396Sian bic r7, #CPU_CONTROL_UNAL_ENABLE 101276396Sian bic r7, #CPU_CONTROL_BPRD_ENABLE 102276396Sian bic r7, #CPU_CONTROL_SW_ENABLE 103276396Sian orr r7, #CPU_CONTROL_AFLT_ENABLE 104276396Sian orr r7, #CPU_CONTROL_VECRELOC 105276396Sian mcr CP15_SCTLR(r7) 106276396Sian ISB 107276396Sian bl dcache_inv_poc_all 108276396Sian mcr CP15_ICIALLU 109276396Sian ISB 110276396Sian 111276396Sian /* 112276396Sian * Build page table from scratch. 113276396Sian */ 114276396Sian 115276396Sian /* Calculate the physical address of the startup pagetable. */ 116276396Sian adr r0, Lpagetable 117276396Sian bl translate_va_to_pa 118276396Sian 119276396Sian /* 120276396Sian * Map PA == VA 121276396Sian */ 122282024Sandrew /* Find the start kernels load address */ 123276396Sian adr r5, _start 124276396Sian ldr r2, =(PTE1_OFFSET) 125276396Sian bic r5, r2 126276396Sian mov r1, r5 127276396Sian mov r2, r5 128282024Sandrew /* Map 64MiB, preserved over calls to build_pagetables */ 129276396Sian mov r3, #64 130276396Sian bl build_pagetables 131276396Sian 132276396Sian /* Create the kernel map to jump to */ 133276396Sian mov r1, r5 134276396Sian ldr r2, =(KERNVIRTADDR) 135276396Sian bl build_pagetables 136276396Sian 137276396Sian#if defined(SOCDEV_PA) && defined(SOCDEV_VA) 138276396Sian /* Create the custom map used for early_printf(). */ 139276396Sian ldr r1, =SOCDEV_PA 140276396Sian ldr r2, =SOCDEV_VA 141276396Sian bl build_pagetables 142276396Sian#endif 143276396Sian bl init_mmu 144276396Sian 145282024Sandrew /* Switch to virtual addresses. */ 146276396Sian ldr pc, =1f 147276396Sian1: 148276396Sian 149282024Sandrew /* Setup stack, clear BSS */ 150276396Sian ldr r1, =.Lstart 151276396Sian ldmia r1, {r1, r2, sp} /* Set initial stack and */ 152276396Sian add sp, sp, #INIT_ARM_STACK_SIZE 153282024Sandrew sub r2, r2, r1 /* get zero init data */ 154276396Sian mov r3, #0 155276396Sian2: 156276396Sian str r3, [r1], #0x0004 /* get zero init data */ 157282024Sandrew subs r2, r2, #4 158276396Sian bgt 2b 159276396Sian 160282024Sandrew mov r1, #28 /* loader info size is 28 bytes also second arg */ 161282024Sandrew subs sp, sp, r1 /* allocate arm_boot_params struct on stack */ 162282024Sandrew mov r0, sp /* loader info pointer is first arg */ 163282024Sandrew bic sp, sp, #7 /* align stack to 8 bytes */ 164282024Sandrew str r1, [r0] /* Store length of loader info */ 165276396Sian str r8, [r0, #4] /* Store r0 from boot loader */ 166276396Sian str r9, [r0, #8] /* Store r1 from boot loader */ 167276396Sian str r10, [r0, #12] /* store r2 from boot loader */ 168276396Sian str r11, [r0, #16] /* store r3 from boot loader */ 169276396Sian str r5, [r0, #20] /* store the physical address */ 170282024Sandrew adr r4, Lpagetable /* load the pagetable address */ 171276396Sian ldr r5, [r4, #4] 172276396Sian str r5, [r0, #24] /* store the pagetable address */ 173276396Sian mov fp, #0 /* trace back starts here */ 174276396Sian bl _C_LABEL(initarm) /* Off we go */ 175276396Sian 176282024Sandrew /* init arm will return the new stack pointer. */ 177276396Sian mov sp, r0 178276396Sian 179282024Sandrew bl _C_LABEL(mi_startup) /* call mi_startup()! */ 180276396Sian 181276396Sian ldr r0, =.Lmainreturned 182276396Sian b _C_LABEL(panic) 183276396Sian /* NOTREACHED */ 184276396SianEND(_start) 185276396Sian 186276396Sian#define VA_TO_PA_POINTER(name, table) \ 187276396Sianname: ;\ 188276396Sian .word . ;\ 189276396Sian .word table 190276396Sian 191276396Sian/* 192276396Sian * Returns the physical address of a magic va to pa pointer. 193276396Sian * r0 - The pagetable data pointer. This must be built using the 194276396Sian * VA_TO_PA_POINTER macro. 195276396Sian * e.g. 196276396Sian * VA_TO_PA_POINTER(Lpagetable, pagetable) 197276396Sian * ... 198276396Sian * adr r0, Lpagetable 199276396Sian * bl translate_va_to_pa 200276396Sian * r0 will now contain the physical address of pagetable 201276396Sian * r1, r2 - Trashed 202276396Sian */ 203276396Siantranslate_va_to_pa: 204276396Sian ldr r1, [r0] 205276396Sian sub r2, r1, r0 206276396Sian /* At this point: r2 = VA - PA */ 207276396Sian 208276396Sian /* 209276396Sian * Find the physical address of the table. After these two 210276396Sian * instructions: 211276396Sian * r1 = va(pagetable) 212276396Sian * 213276396Sian * r0 = va(pagetable) - (VA - PA) 214276396Sian * = va(pagetable) - VA + PA 215276396Sian * = pa(pagetable) 216276396Sian */ 217276396Sian ldr r1, [r0, #4] 218276396Sian sub r0, r1, r2 219276396Sian mov pc, lr 220276396Sian 221276396Sian/* 222282024Sandrew * Init MMU 223282024Sandrew * r0 - the table base address 224276396Sian */ 225276396Sian 226276396SianASENTRY_NP(init_mmu) 227276396Sian 228276396Sian /* Setup TLB and MMU registers */ 229276396Sian mcr CP15_TTBR0(r0) /* Set TTB */ 230276396Sian mov r0, #0 231276396Sian mcr CP15_CONTEXTIDR(r0) /* Set ASID to 0 */ 232276396Sian 233276396Sian /* Set the Domain Access register */ 234276396Sian mov r0, #((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT) 235276396Sian mcr CP15_DACR(r0) 236276396Sian 237276396Sian#ifdef ARM_NEW_PMAP 238276396Sian /* 239276396Sian * Set TEX remap registers 240276396Sian * - All is set to uncacheable memory 241276396Sian */ 242276396Sian ldr r0, =0xAAAAA 243276396Sian mrc CP15_PRRR(r0) 244276396Sian mov r0, #0 245276396Sian mcr CP15_NMRR(r0) 246276396Sian#endif 247276396Sian mcr CP15_TLBIALL /* Flush TLB */ 248276396Sian DSB 249276396Sian ISB 250276396Sian 251276396Sian /* Enable MMU */ 252276396Sian mrc CP15_SCTLR(r0) 253276396Sian orr r0, r0, #CPU_CONTROL_MMU_ENABLE 254276396Sian orr r0, r0, #CPU_CONTROL_V6_EXTPAGE 255276396Sian#ifdef ARM_NEW_PMAP 256276396Sian orr r0, r0, #CPU_CONTROL_TR_ENABLE 257276396Sian#endif 258276396Sian orr r0, r0, #CPU_CONTROL_AF_ENABLE 259276396Sian mcr CP15_SCTLR(r0) 260276396Sian DSB 261276396Sian ISB 262276396Sian mcr CP15_TLBIALL /* Flush TLB */ 263276396Sian mcr CP15_BPIALL /* Flush Branch predictor */ 264276396Sian ISB 265276396Sian mov pc, lr 266276396SianEND(init_mmu) 267276396Sian 268276396Sian 269276396Sian/* 270282024Sandrew * Init SMP coherent mode, enable caching and switch to final MMU table. 271282024Sandrew * Called with disabled caches 272282024Sandrew * r0 - The table base address 273282024Sandrew * r1 - clear bits for aux register 274282024Sandrew * r2 - set bits for aux register 275276396Sian */ 276276396SianASENTRY_NP(reinit_mmu) 277276396Sian push {r4-r11, lr} 278276396Sian mov r4, r0 279276396Sian mov r5, r1 280276396Sian mov r6, r2 281276396Sian 282276396Sian /* !! Be very paranoid here !! */ 283276396Sian /* !! We cannot write single bit here !! */ 284276396Sian 285276396Sian#if 0 /* XXX writeback shouldn't be necessary */ 286276396Sian /* Write back and invalidate all integrated caches */ 287276396Sian bl dcache_wbinv_poc_all 288276396Sian#else 289276396Sian bl dcache_inv_pou_all 290276396Sian#endif 291276396Sian mcr CP15_ICIALLU 292276396Sian ISB 293276396Sian 294276396Sian /* Set auxiliary register */ 295276396Sian mrc CP15_ACTLR(r7) 296276396Sian bic r8, r7, r5 /* Mask bits */ 297276396Sian eor r8, r8, r6 /* Set bits */ 298276396Sian teq r7, r8 299276396Sian mcrne CP15_ACTLR(r8) 300276396Sian ISB 301276396Sian 302276396Sian /* Enable caches. */ 303276396Sian mrc CP15_SCTLR(r7) 304276396Sian orr r7, #CPU_CONTROL_DC_ENABLE 305276396Sian orr r7, #CPU_CONTROL_IC_ENABLE 306276396Sian orr r7, #CPU_CONTROL_BPRD_ENABLE 307276396Sian mcr CP15_SCTLR(r7) 308276396Sian DSB 309276396Sian 310276396Sian mcr CP15_TTBR0(r4) /* Set new TTB */ 311276396Sian DSB 312276396Sian ISB 313276396Sian 314276396Sian /* Flush all TLBs */ 315276396Sian mcr CP15_TLBIALL 316276396Sian DSB 317276396Sian ISB 318276396Sian 319276396Sian#if 0 /* XXX writeback shouldn't be necessary */ 320276396Sian /* Write back and invalidate all integrated caches */ 321276396Sian bl dcache_wbinv_poc_all 322276396Sian#else 323276396Sian bl dcache_inv_pou_all 324276396Sian#endif 325276396Sian mcr CP15_ICIALLU 326276396Sian ISB 327276396Sian 328276396Sian pop {r4-r11, pc} 329276396SianEND(reinit_mmu) 330276396Sian 331276396Sian 332276396Sian/* 333276396Sian * Builds the page table 334282024Sandrew * r0 - The table base address 335282024Sandrew * r1 - The physical address (trashed) 336282024Sandrew * r2 - The virtual address (trashed) 337282024Sandrew * r3 - The number of 1MiB sections 338282024Sandrew * r4 - Trashed 339276396Sian * 340276396Sian * Addresses must be 1MiB aligned 341276396Sian */ 342276470Sianbuild_pagetables: 343276396Sian /* Set the required page attributed */ 344276396Sian#if defined(ARM_NEW_PMAP) 345276396Sian ldr r4, =PTE1_V|PTE1_A|PTE1_AP_KRW|TEX1_CLASS_0 346276396Sian#elif defined(SMP) 347276396Sian ldr r4, =(L1_TYPE_S|L1_S_C|L1_S_AP(AP_KRW)|L1_SHARED) 348276396Sian#else 349276396Sian ldr r4, =(L1_TYPE_S|L1_S_C|L1_S_AP(AP_KRW)) 350276396Sian#endif 351276396Sian orr r1, r4 352276396Sian 353282024Sandrew /* Move the virtual address to the correct bit location */ 354276396Sian lsr r2, #(PTE1_SHIFT - 2) 355276396Sian 356276396Sian mov r4, r3 357276396Sian1: 358276396Sian str r1, [r0, r2] 359282024Sandrew add r2, r2, #4 360282024Sandrew add r1, r1, #(PTE1_SIZE) 361282024Sandrew adds r4, r4, #-1 362276396Sian bhi 1b 363276396Sian 364276396Sian mov pc, lr 365276396Sian 366276396SianVA_TO_PA_POINTER(Lpagetable, boot_pt1) 367276396Sian 368276396Sian 369276396Sian.Lstart: 370277305Sian .word _edata /* Note that these three items are */ 371277305Sian .word _ebss /* loaded with a single ldmia and */ 372277305Sian .word svcstk /* must remain in order together. */ 373276396Sian 374276396Sian.Lmainreturned: 375282024Sandrew .asciz "main() returned" 376276596Sian .align 2 377276396Sian 378276396Sian .bss 379276396Siansvcstk: 380276396Sian .space INIT_ARM_STACK_SIZE * MAXCPU 381276396Sian 382276396Sian/* 383282024Sandrew * Memory for the initial pagetable. We are unable to place this in 384282024Sandrew * the bss as this will be cleared after the table is loaded. 385276396Sian */ 386276396Sian .section ".init_pagetable" 387276396Sian .align 14 /* 16KiB aligned */ 388276396Sian .globl boot_pt1 389276396Sianboot_pt1: 390276396Sian .space L1_TABLE_SIZE 391276396Sian 392276396Sian .text 393276596Sian .align 2 394276396Sian 395276396Sian.Lcpufuncs: 396276396Sian .word _C_LABEL(cpufuncs) 397276396Sian 398276396Sian#if defined(SMP) 399276396Sian 400276396SianASENTRY_NP(mpentry) 401282024Sandrew /* Make sure interrupts are disabled. */ 402276396Sian cpsid ifa 403276396Sian 404276396Sian /* Setup core, disable all caches. */ 405276396Sian mrc CP15_SCTLR(r0) 406276396Sian bic r0, #CPU_CONTROL_MMU_ENABLE 407276396Sian bic r0, #CPU_CONTROL_DC_ENABLE 408276396Sian bic r0, #CPU_CONTROL_IC_ENABLE 409276396Sian bic r0, #CPU_CONTROL_UNAL_ENABLE 410276396Sian bic r0, #CPU_CONTROL_BPRD_ENABLE 411276396Sian bic r0, #CPU_CONTROL_SW_ENABLE 412276396Sian orr r0, #CPU_CONTROL_AFLT_ENABLE 413276396Sian orr r0, #CPU_CONTROL_VECRELOC 414276396Sian mcr CP15_SCTLR(r0) 415276396Sian ISB 416276396Sian 417276396Sian /* Invalidate L1 cache I+D cache */ 418276396Sian bl dcache_inv_pou_all 419276396Sian mcr CP15_ICIALLU 420276396Sian ISB 421276396Sian 422282024Sandrew /* Find the delta between VA and PA */ 423276396Sian adr r0, Lpagetable 424276396Sian bl translate_va_to_pa 425276396Sian 426276396Sian bl init_mmu 427276396Sian 428277305Sian adr r1, .Lstart+8 /* Get initstack pointer from */ 429277305Sian ldr sp, [r1] /* startup data. */ 430277305Sian mrc CP15_MPIDR(r0) /* Get processor id number. */ 431277305Sian and r0, r0, #0x0f 432276396Sian mov r1, #INIT_ARM_STACK_SIZE 433277305Sian mul r2, r1, r0 /* Point sp to initstack */ 434277305Sian add sp, sp, r2 /* area for this processor. */ 435276396Sian 436282024Sandrew /* Switch to virtual addresses. */ 437276396Sian ldr pc, =1f 438276396Sian1: 439276396Sian mov fp, #0 /* trace back starts here */ 440277305Sian bl _C_LABEL(init_secondary)/* Off we go, cpu id in r0. */ 441276396Sian 442276396Sian adr r0, .Lmpreturned 443276396Sian b _C_LABEL(panic) 444276396Sian /* NOTREACHED */ 445276596SianEND(mpentry) 446276396Sian 447276396Sian.Lmpreturned: 448276396Sian .asciz "init_secondary() returned" 449276596Sian .align 2 450276396Sian#endif 451276396Sian 452276396SianENTRY_NP(cpu_halt) 453276396Sian 454276396Sian /* XXX re-implement !!! */ 455276396Sian cpsid ifa 456276396Sian bl dcache_wbinv_poc_all 457276396Sian 458276396Sian ldr r4, .Lcpu_reset_address 459276396Sian ldr r4, [r4] 460276396Sian teq r4, #0 461276396Sian movne pc, r4 462276396Sian1: 463276519Sian WFI 464276396Sian b 1b 465276396Sian 466276396Sian /* 467276396Sian * _cpu_reset_address contains the address to branch to, to complete 468276396Sian * the cpu reset after turning the MMU off 469282024Sandrew * This variable is provided by the hardware specific code 470276396Sian */ 471276396Sian.Lcpu_reset_address: 472276396Sian .word _C_LABEL(cpu_reset_address) 473276396SianEND(cpu_halt) 474276396Sian 475276396Sian 476276396Sian/* 477276396Sian * setjump + longjmp 478276396Sian */ 479276396SianENTRY(setjmp) 480276396Sian stmia r0, {r4-r14} 481276396Sian mov r0, #0x00000000 482276396Sian RET 483276396SianEND(setjmp) 484276396Sian 485276396SianENTRY(longjmp) 486276396Sian ldmia r0, {r4-r14} 487276396Sian mov r0, #0x00000001 488276396Sian RET 489276396SianEND(longjmp) 490276396Sian 491276396Sian .data 492276396Sian .global _C_LABEL(esym) 493276396Sian_C_LABEL(esym): .word _C_LABEL(end) 494276396Sian 495276396SianENTRY_NP(abort) 496276396Sian b _C_LABEL(abort) 497276396SianEND(abort) 498276396Sian 499276396SianENTRY_NP(sigcode) 500276396Sian mov r0, sp 501282024Sandrew add r0, r0, #SIGF_UC 502276396Sian 503276396Sian /* 504282024Sandrew * Call the sigreturn system call. 505276396Sian * 506276396Sian * We have to load r7 manually rather than using 507282024Sandrew * "ldr r7, =SYS_sigreturn" to ensure the value of szsigcode is 508276396Sian * correct. Using the alternative places esigcode at the address 509282024Sandrew * of the data rather than the address one past the data. 510276396Sian */ 511276396Sian 512282024Sandrew ldr r7, [pc, #12] /* Load SYS_sigreturn */ 513276396Sian swi SYS_sigreturn 514276396Sian 515282024Sandrew /* Well if that failed we better exit quick ! */ 516276396Sian 517282024Sandrew ldr r7, [pc, #8] /* Load SYS_exit */ 518276396Sian swi SYS_exit 519276396Sian 520282024Sandrew /* Branch back to retry SYS_sigreturn */ 521276396Sian b . - 16 522276470SianEND(sigcode) 523276396Sian .word SYS_sigreturn 524276396Sian .word SYS_exit 525276396Sian 526276596Sian .align 2 527282024Sandrew .global _C_LABEL(esigcode) 528276396Sian _C_LABEL(esigcode): 529276396Sian 530276396Sian .data 531282024Sandrew .global szsigcode 532276396Sianszsigcode: 533276396Sian .long esigcode-sigcode 534276470Sian 535276396Sian/* End of locore.S */ 536