/* crt0.S -- startup file for frv. * * Copyright (c) 2002, 2003 Red Hat, Inc * * The authors hereby grant permission to use, copy, modify, distribute, * and license this software and its documentation for any purpose, provided * that existing copyright notices are retained in all copies and that this * notice is included verbatim in any distributions. No written agreement, * license, or royalty fee is required for any of the authorized uses. * Modifications to this software may be copyrighted by their authors * and need not follow the licensing terms described here, provided that * the new terms are clearly indicated on the first page of each file where * they apply. */ #include /* statically store .Lcall's address so we can see if we are running at the location we were linked for or a different location. */ .data .type EXT(__start_cmp),@object .size EXT(__start_cmp),4 .p2align 2 EXT(__start_cmp): .picptr .Lcall .globl __start .weak _start .text .type __start,@function __start: _start: call .Lcall /* set up _gp in a pic-friendly manor */ .Lcall: movsg lr, gr4 P(sethi) #gprelhi(.Lcall), gr5 setlo #gprello(.Lcall), gr5 P(sub) gr4, gr5, gr16 #if ! __FRV_FDPIC__ sethi #gprelhi(EXT(_stack)), sp /* load up stack pointer */ P(setlo) #gprello(EXT(_stack)), sp setlos #0, fp /* zero fp to allow unwinders to stop */ P(add) sp, gr16, sp #define FDPIC(...) #else #define FDPIC(...) __VA_ARGS__ /* The assembler will rightfully claim that #hi/lo(__stacksize) are unsafe for PIC, but since __stacksize is absolute, and we don't want it to be relocated, we should be fine. */ sethi #gprelhi(EXT(__end)), gr6 P(sethi) #hi(EXT(__stacksize+7)), gr5 setlo #gprello(EXT(__end)), gr6 P(setlo) #lo(EXT(__stacksize+7)), gr5 add gr6, gr16, gr6 add gr6, gr5, gr5 andi gr5, -8, sp /* Using GPREL to compute _GLOBAL_OFFSET_TABLE_'s will force the entire program to relocate as a unit, which is fine for frv-elf. */ P(sethi) #gprelhi(EXT(_GLOBAL_OFFSET_TABLE_)), gr15 setlo #gprello(EXT(_GLOBAL_OFFSET_TABLE_)), gr15 /* We compute the value in a call-saved register (that happens to be the PIC register in the EABI, and copy it to gr15 before every call. */ add gr15, gr16, gr17 #endif sethi #gprelhi(EXT(__start_cmp)), gr5 setlo #gprello(EXT(__start_cmp)), gr5 ld @(gr5,gr16), gr6 subcc gr4, gr6, gr8, icc0 beq icc0, 0, .Lfixed P(st) gr4, @(gr5, gr16) /* update so if we restart no need to fixup */ setlos 4, gr11 #if ! __FRV_FDPIC__ /* fixup the .ctors list */ sethi #gprelhi(EXT(__CTOR_LIST__)), gr9 P(sethi) #gprelhi(EXT(__CTOR_END__)), gr10 setlo #gprello(EXT(__CTOR_LIST__)), gr9 P(setlo) #gprello(EXT(__CTOR_END__)), gr10 add gr9, gr16, gr9 P(add) gr10, gr16, gr10 addi gr9, 4, gr9 P(subi) gr10, 4, gr10 call EXT(__frv_fixptrs) /* fixup the .dtors list */ P(sethi) #gprelhi(EXT(__DTOR_LIST__)), gr9 sethi #gprelhi(EXT(__DTOR_END__)), gr10 P(setlo) #gprello(EXT(__DTOR_LIST__)), gr9 setlo #gprello(EXT(__DTOR_END__)), gr10 P(add) gr9, gr16, gr9 add gr10, gr16, gr10 P(addi) gr9, 4, gr9 subi gr10, 4, gr10 call EXT(__frv_fixptrs) #endif /* ! __FRV_FDPIC__ */ /* fixup the user .rofixup list */ P(sethi) #gprelhi(EXT(__ROFIXUP_LIST__)), gr9 sethi #gprelhi(EXT(__ROFIXUP_END__)), gr10 P(setlo) #gprello(EXT(__ROFIXUP_LIST__)), gr9 setlo #gprello(EXT(__ROFIXUP_END__)), gr10 P(add) gr9, gr16, gr9 add gr10, gr16, gr10 FDPIC(mov gr17, gr15) call EXT(__frv_fix_usrptrs) .Lfixed: /* HSR flags */ #define HSR_ICE 0x80000000 /* Instruction cache enable */ #define HSR_DCE 0x40000000 /* Data cache enable */ #define HSR_CBM 0x08000000 /* Cache copy back mode */ #define HSR_EIMM 0x04000000 /* Enable Instruction MMU */ #define HSR_EDMM 0x02000000 /* Enable Data MMU */ #define HSR_EMEM 0x00800000 /* Enable MMU miss exception mask */ #define HSR_RME 0x00400000 /* Ram mode enable */ #define HSR_SA 0x00001000 /* Start address */ #define HSR_FRN 0x00000800 /* Number of FPRs */ #define HSR_GRN 0x00000400 /* Number of GPRs */ #define HSR_FRHE 0x00000200 /* FR Higher Enable */ #define HSR_FRLE 0x00000100 /* FR Lower Enable */ #define HSR_GRHE 0x00000080 /* GR Higher Enable */ #define HSR_GRLE 0x00000040 /* GR Lower Enable */ #ifndef HSR_CLEAR #define HSR_CLEAR 0 #endif #ifndef HSR_SET #ifndef FRV_NO_CACHE #define HSR_SET (HSR_ICE|HSR_DCE|HSR_FRHE|HSR_FRLE|HSR_GRHE|HSR_GRLE) #else #define HSR_SET (HSR_FRHE|HSR_FRLE|HSR_GRHE|HSR_GRLE) #endif #endif /* PSR flags */ #define PSR_ICE 0x00010000 /* In circuit emulation mode */ #define PSR_NEM 0x00004000 /* Non-exception mode */ #define PSR_CM 0x00002000 /* Conditional mode */ #define PSR_BE 0x00001000 /* Big endian mode */ #define PSR_EF 0x00000100 /* Enable floating point */ #define PSR_EM 0x00000080 /* Enable media instructions */ #define PSR_S 0x00000004 /* Enable supervisor mode */ #define PSR_PS 0x00000002 /* Previous supervisor mode */ #define PSR_ET 0x00000001 /* Enable interrupts */ #ifndef PSR_CLEAR #if __FRV_FPR__ #define PSR_CLEAR 0 #else #define PSR_CLEAR (PSR_EF|PSR_EM) #endif #endif #ifndef PSR_SET #if __FRV_FPR__ #define PSR_SET (PSR_NEM|PSR_CM|PSR_EF|PSR_EM) #else #define PSR_SET (PSR_NEM|PSR_CM) #endif #endif /* Enable floating point */ movsg hsr0, gr4 P(sethi) #hi(HSR_SET), gr5 setlo #lo(HSR_SET), gr5 P(sethi) #hi(~HSR_CLEAR), gr6 setlo #lo(~HSR_CLEAR), gr6 or gr4, gr5, gr4 and gr4, gr6, gr4 movgs gr4, hsr0 movsg psr, gr4 P(sethi) #hi(PSR_SET), gr5 setlo #lo(PSR_SET), gr5 P(sethi) #hi(~PSR_CLEAR), gr6 setlo #lo(~PSR_CLEAR), gr6 or gr4, gr5, gr4 and gr4, gr6, gr4 movgs gr4, psr /* zero the bss area */ P(sethi) #gprelhi(__bss_start), gr8 sethi #gprelhi(__end), gr4 P(setlo) #gprello(__bss_start), gr8 setlo #gprello(__end), gr4 P(add) gr8, gr16, gr8 add gr4, gr16, gr4 P(setlos) #0, gr9 sub gr4, gr8, gr10 FDPIC(mov gr17, gr15) call EXT(memset) P(setlos) #0, gr8 /* zero argc, argv, envp */ setlos #0, gr9 P(setlos) #0, gr10 FDPIC(mov gr17, gr15) call EXT(main) FDPIC(mov gr17, gr15) call EXT(exit) .Lend: .size __start,(.Lend-__start) #if ! __FRV_FDPIC__ /* Routine to adjust pointers gr8 = difference to adjust by gr9 = starting address gr10 = ending address + 4 gr11 = amount to add to the pointer each iteration. */ .globl EXT(__frv_fixptrs) .type EXT(__frv_fixptrs),@function EXT(__frv_fixptrs): P(sub) gr9, gr11, gr9 sub gr10, gr11, gr10 .Lloop2: cmp gr10, gr9, icc0 bls icc0, 0, .Lret2 ldu @(gr9,gr11), gr5 add gr8, gr5, gr5 P(st) gr5, @(gr9,gr0) bra .Lloop2 .Lret2: ret .Lend2: .size EXT(__frv_fixptrs),.Lend2-EXT(__frv_fixptrs) #endif /* ! __FRV_FDPIC__ */ /* Routine to adjust statically initialized pointers Note since these are pointers to pointers, they need to be adjusted themsevles. gr8 = difference to adjust by gr9 = starting address gr10 = ending address + 4 gr11 = amount to add to the pointer each iteration. */ .globl EXT(__frv_fix_usrptrs) .type EXT(__frv_fix_usrptrs),@function EXT(__frv_fix_usrptrs): P(sub) gr9, gr11, gr9 sub gr10, gr11, gr10 .Lloop3: cmp gr10, gr9, icc0 bls icc0, 0, .Lret3 ldu @(gr9,gr11), gr5 ld @(gr5, gr8), gr6 cmp gr6, gr0, icc0 /* skip pointers initialized to 0 */ beq icc0, 0, .Lloop3 add gr8, gr6, gr6 P(st) gr6, @(gr5,gr8) bra .Lloop3 .Lret3: ret .Lend3: .size EXT(__frv_fix_usrptrs),.Lend3-EXT(__frv_fix_usrptrs) .section .data .global __dso_handle .weak __dso_handle __dso_handle: .long 0