| /* 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 <frv-asm.h> |
| |
| /* 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 |