newlib/libgloss/frv/crt0.S

277 lines
7.5 KiB
ArmAsm

/* 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),.Lend2-EXT(__frv_fix_usrptrs)
.section .data
.global __dso_handle
.weak __dso_handle
__dso_handle:
.long 0