1/* 2 * crt0.S -- startup file for MIPS. 3 * 4 * Copyright (c) 1995, 1996, 1997, 2001 Cygnus Support 5 * 6 * The authors hereby grant permission to use, copy, modify, distribute, 7 * and license this software and its documentation for any purpose, provided 8 * that existing copyright notices are retained in all copies and that this 9 * notice is included verbatim in any distributions. No written agreement, 10 * license, or royalty fee is required for any of the authorized uses. 11 * Modifications to this software may be copyrighted by their authors 12 * and need not follow the licensing terms described here, provided that 13 * the new terms are clearly indicated on the first page of each file where 14 * they apply. 15 */ 16 17/* This file does not use any floating-point ABI. */ 18 .gnu_attribute 4,0 19 20#ifdef __mips16 21/* This file contains 32 bit assembly code. */ 22 .set nomips16 23#endif 24 25#include "regs.S" 26#include "abiflags.S" 27 28/* 29 * Set up some room for a stack. We just grab a chunk of memory. 30 */ 31#define STACK_SIZE 0x4000 32#define GLOBAL_SIZE 0x2000 33 34#define STARTUP_STACK_SIZE 0x0100 35 36/* This is for referencing addresses that are not in the .sdata or 37 .sbss section under embedded-pic, or before we've set up gp. */ 38#ifdef __mips_embedded_pic 39# ifdef __mips64 40# define LA(t,x) la t,x-PICBASE ; daddu t,s0,t 41# else 42# define LA(t,x) la t,x-PICBASE ; addu t,s0,t 43# endif 44#else /* __mips_embedded_pic */ 45# define LA(t,x) la t,x 46#endif /* __mips_embedded_pic */ 47 48 .comm __memsize, 12 49 .comm __lstack, STARTUP_STACK_SIZE 50 51 .text 52 .align 2 53 54/* Without the following nop, GDB thinks _start is a data variable. 55 * This is probably a bug in GDB in handling a symbol that is at the 56 * start of the .text section. 57 */ 58 nop 59 60 .globl hardware_hazard_hook .text 61 .globl _start 62 .ent _start 63_start: 64#ifdef __mips_embedded_pic 65#define PICBASE start_PICBASE 66 .set noreorder 67 PICBASE = .+8 68 bal PICBASE 69 nop 70 move s0,$31 71 .set reorder 72#endif 73#if __mips<3 74# define STATUS_MASK (SR_CU1|SR_PE) 75#else 76/* Post-mips2 has no SR_PE bit. */ 77# ifdef __mips64 78/* Turn on 64-bit addressing and additional float regs. */ 79# define STATUS_MASK (SR_CU1|SR_FR|SR_KX|SR_SX|SR_UX) 80# else 81# if __mips_fpr==32 82# define STATUS_MASK (SR_CU1) 83# else 84/* Turn on additional float regs. */ 85# define STATUS_MASK (SR_CU1|SR_FR) 86# endif 87# endif 88#endif 89 90 /* Clear Cause register. */ 91 mtc0 zero,C0_CAUSE 92 nop 93 94 /* Read MIPS_abiflags structure and set status/config registers 95 accordingly. */ 96 .weak __MIPS_abiflags_start 97 .weak __MIPS_abiflags_end 98 LA (t0,__MIPS_abiflags_start) 99 LA (t1,__MIPS_abiflags_end) 100 addiu t1,t1,-24 101 move v0,zero /* Mask for C0_SR. */ 102 103 /* Branch to 1f is the .MIPS.abiflags section is not 24 bytes. This 104 indicates it is either missing or corrupt. */ 105 bne t0,t1,1f 106 107 /* Check isa_level. */ 108 lbu t1,ABIFlags_isa_level(t0) 109 sltu v1,t1,3 /* Is MIPS < 3? */ 110 xori t1,t1,64 /* Is MIPS64? */ 111 beq v1,zero,4f 112 li v1,SR_PE 113 or v0,v0,v1 /* Enable soft reset. */ 1144: 115 li v1,(SR_KX|SR_SX|SR_UX) 116 bne t1,zero,5f 117 or v0,v0,v1 /* Enable extended addressing. */ 1185: 119 /* Check fp_abi. */ 120 lbu t1,ABIFlags_fp_abi(t0) 121 xori t1,t1,Val_GNU_MIPS_ABI_FP_SOFT 122 li v1,SR_CU1 123 beq t1,zero,2f /* Skip MSA and cpr1_size checks. */ 124 or v0,v0,v1 /* Enable co-processor 1. */ 125 126 /* Check cpr1_size. */ 127 lbu t1,ABIFlags_cpr1_size(t0) 128 xori t1,t1,AFL_REG_64 129 li v1,SR_FR 130 bne t1,zero,3f 131 or v0,v0,v1 /* Enable 64-bit FPU registers. */ 1323: 133 /* Check ases. */ 134 lw t1,ABIFlags_ases(t0) 135 andi t1,t1,AFL_ASE_MSA 136 li v1,SR_FR 137 beq t1,zero,2f 138 or v0,v0,v1 /* Enable 64-bit FPU registers. */ 139 li v1,SR_MSA 140 .set push 141 .set mips32 142 mtc0 v1,C0_CONFIG,5 /* Enable MSA. */ 143 .set pop 144 b 2f 145 1461: 147 /* MIPS_abiflags structure is not available. Set status/config 148 registers based on flags defined by compiler. */ 149#ifdef __mips_soft_float 150 li v0,(STATUS_MASK-(STATUS_MASK & SR_CU1)) 151#else 152 li v0,STATUS_MASK 153#endif 154 1552: 156 /* Set C0_SR, */ 157 mtc0 v0,C0_SR 158 nop 159 160 /* Avoid hazard from C0_SR changes. */ 161 LA (t0, hardware_hazard_hook) 162 beq t0,zero,2f 163 jalr t0 1642: 165 166 167/* Fix high bits, if any, of the PC so that exception handling doesn't get 168 confused. */ 169 LA (v0, 3f) 170 jr v0 1713: 172 LA (gp, _gp) # set the global data pointer 173 .end _start 174 175/* 176 * zero out the bss section. 177 */ 178 .globl __memsize 179 .globl get_mem_info .text 180 .globl __stack 181 .globl __global 182 .ent zerobss 183zerobss: 184 LA (v0, _fbss) 185 LA (v1, _end) 186 beq v0,v1,2f 1871: 188 addiu v0,v0,4 189 sw zero,-4(v0) 190 bne v0,v1,1b 1912: 192 la t0, __lstack # make a small stack so we 193 addiu sp, t0, STARTUP_STACK_SIZE # can run some C code 194 la a0, __memsize # get the usable memory size 195 jal get_mem_info 196 197 /* setup the stack pointer */ 198 LA (t0, __stack) # is __stack set ? 199 bne t0,zero,4f 200 201 /* NOTE: a0[0] contains the amount of memory available, and 202 not the last memory address. */ 203 la a0, __memsize 204 lw t0,0(a0) # last address of memory available 205 la t1,K0BASE # cached kernel memory 206 addu t0,t0,t1 # get the end of memory address 207 /* Allocate 32 bytes for the register parameters. Allocate 16 208 bytes for a null argv and envp. Round the result up to 64 209 bytes to preserve alignment. */ 210 subu t0,t0,64 2114: 212 move sp,t0 # set stack pointer 213 .end zerobss 214 215/* 216 * initialize target specific stuff. Only execute these 217 * functions it they exist. 218 */ 219 .globl hardware_init_hook .text 220 .globl software_init_hook .text 221 .type _fini,@function 222 .type _init,@function 223 .globl atexit .text 224 .globl exit .text 225 .ent init 226init: 227 LA (t9, hardware_init_hook) # init the hardware if needed 228 beq t9,zero,6f 229 jalr t9 2306: 231 LA (t9, software_init_hook) # init the hardware if needed 232 beq t9,zero,7f 233 jalr t9 2347: 235 LA (a0, _fini) 236 jal atexit 237 238#ifdef GCRT0 239 .globl _ftext 240 .globl _extext 241 LA (a0, _ftext) 242 LA (a1, _etext) 243 jal monstartup 244#endif 245 246 247 jal _init # run global constructors 248 249 addiu a1,sp,32 # argv = sp + 32 250 addiu a2,sp,40 # envp = sp + 40 251#if __mips64 252 sd zero,(a1) # argv[argc] = 0 253 sd zero,(a2) # envp[0] = 0 254#else 255 sw zero,(a1) 256 sw zero,(a2) 257#endif 258 move a0,zero # set argc to 0 259 jal main # call the program start function 260 261 # fall through to the "exit" routine 262 move a0,v0 # pass through the exit code 263 jal exit # call libc exit to run the G++ 264 # destructors 265 .end init 266 267 268/* Assume the PICBASE set up above is no longer valid below here. */ 269#ifdef __mips_embedded_pic 270#undef PICBASE 271#endif 272 273/* 274 * _exit -- Exit from the application. Normally we cause a user trap 275 * to return to the ROM monitor for another run. NOTE: This is 276 * the only other routine we provide in the crt0.o object, since 277 * it may be tied to the "_start" routine. It also allows 278 * executables that contain a complete world to be linked with 279 * just the crt0.o object. 280 */ 281 .globl hardware_exit_hook .text 282 .globl _exit 283 .ent _exit 284_exit: 2857: 286#ifdef __mips_embedded_pic 287 /* Need to reinit PICBASE, since we might be called via exit() 288 rather than via a return path which would restore old s0. */ 289#define PICBASE exit_PICBASE 290 .set noreorder 291 PICBASE = .+8 292 bal PICBASE 293 nop 294 move s0,$31 295 .set reorder 296#endif 297#ifdef GCRT0 298 LA (t0, _mcleanup) 299 jalr t0 300#endif 301 LA (t0, hardware_exit_hook) 302 beq t0,zero,1f 303 jalr t0 3041: 305 306 # break instruction can cope with 0xfffff, but GAS limits the range: 307 break 1023 308 b 7b # but loop back just in-case 309 .end _exit 310 311/* Assume the PICBASE set up above is no longer valid below here. */ 312#ifdef __mips_embedded_pic 313#undef PICBASE 314#endif 315 316/* EOF crt0.S */ 317