diff options
Diffstat (limited to 'libgloss/mips/crt0.S')
-rw-r--r-- | libgloss/mips/crt0.S | 152 |
1 files changed, 62 insertions, 90 deletions
diff --git a/libgloss/mips/crt0.S b/libgloss/mips/crt0.S index 254998242..599e79c60 100644 --- a/libgloss/mips/crt0.S +++ b/libgloss/mips/crt0.S @@ -14,16 +14,12 @@ * they apply. */ -/* This file does not use any floating-point ABI. */ - .gnu_attribute 4,0 - #ifdef __mips16 /* This file contains 32 bit assembly code. */ .set nomips16 #endif #include "regs.S" -#include "abiflags.S" /* * Set up some room for a stack. We just grab a chunk of memory. @@ -61,14 +57,13 @@ .globl _start .ent _start _start: + .set noreorder #ifdef __mips_embedded_pic #define PICBASE start_PICBASE - .set noreorder PICBASE = .+8 bal PICBASE nop move s0,$31 - .set reorder #endif #if __mips<3 # define STATUS_MASK (SR_CU1|SR_PE) @@ -86,88 +81,55 @@ _start: # endif # endif #endif - - /* Clear Cause register. */ - mtc0 zero,C0_CAUSE + li v0, STATUS_MASK + mtc0 v0, C0_SR + mtc0 zero, C0_CAUSE nop - /* Read MIPS_abiflags structure and set status/config registers - accordingly. */ - .weak __MIPS_abiflags_start - .weak __MIPS_abiflags_end - LA (t0,__MIPS_abiflags_start) - LA (t1,__MIPS_abiflags_end) - addiu t1,t1,-24 - move v0,zero /* Mask for C0_SR. */ - - /* Branch to 1f is the .MIPS.abiflags section is not 24 bytes. This - indicates it is either missing or corrupt. */ - bne t0,t1,1f - - /* Check isa_level. */ - lbu t1,ABIFlags_isa_level(t0) - sltu v1,t1,3 /* Is MIPS < 3? */ - xori t1,t1,64 /* Is MIPS64? */ - beq v1,zero,4f - li v1,SR_PE - or v0,v0,v1 /* Enable soft reset. */ -4: - li v1,(SR_KX|SR_SX|SR_UX) - bne t1,zero,5f - or v0,v0,v1 /* Enable extended addressing. */ -5: - /* Check fp_abi. */ - lbu t1,ABIFlags_fp_abi(t0) - xori t1,t1,Val_GNU_MIPS_ABI_FP_SOFT - li v1,SR_CU1 - beq t1,zero,2f /* Skip MSA and cpr1_size checks. */ - or v0,v0,v1 /* Enable co-processor 1. */ + /* Avoid hazard from FPU enable and other SR changes. */ + LA (t0, hardware_hazard_hook) + beq t0,zero,1f + nop + jal t0 + nop +1: - /* Check cpr1_size. */ - lbu t1,ABIFlags_cpr1_size(t0) - xori t1,t1,AFL_REG_64 - li v1,SR_FR - bne t1,zero,3f - or v0,v0,v1 /* Enable 64-bit FPU registers. */ -3: - /* Check ases. */ - lw t1,ABIFlags_ases(t0) - andi t1,t1,AFL_ASE_MSA - li v1,SR_FR - beq t1,zero,2f - or v0,v0,v1 /* Enable 64-bit FPU registers. */ - li v1,SR_MSA - .set push - .set mips32 - mtc0 v1,C0_CONFIG,5 /* Enable MSA. */ - .set pop - b 2f +/* Check for FPU presence. Don't check if we know that soft_float is + being used. (This also avoids illegal instruction exceptions.) */ -1: - /* MIPS_abiflags structure is not available. Set status/config - registers based on flags defined by compiler. */ -#ifdef __mips_soft_float - li v0,(STATUS_MASK-(STATUS_MASK & SR_CU1)) -#else - li v0,STATUS_MASK +#ifndef __mips_soft_float + li t2,0xAAAA5555 + mtc1 t2,fp0 /* write to FPR 0 */ + mtc1 zero,fp1 /* write to FPR 1 */ + mfc1 t0,fp0 + mfc1 t1,fp1 + nop + bne t0,t2,1f /* check for match */ + nop + bne t1,zero,1f /* double check */ + nop + j 2f /* FPU is present. */ + nop #endif - -2: - /* Set C0_SR, */ - mtc0 v0,C0_SR +1: + /* FPU is not present. Set status register to say that. */ + li v0, (STATUS_MASK-(STATUS_MASK & SR_CU1)) + mtc0 v0, C0_SR nop - - /* Avoid hazard from C0_SR changes. */ - LA (t0, hardware_hazard_hook) + /* Avoid hazard from FPU disable. */ + LA (t0, hardware_hazard_hook) beq t0,zero,2f - jalr t0 + nop + jal t0 + nop 2: -/* Fix high bits, if any, of the PC so that exception handling doesn't get - confused. */ +/* Fix high bits, if any, of the PC so that exception handling + doesn't get confused. */ LA (v0, 3f) jr v0 + nop 3: LA (gp, _gp) # set the global data pointer .end _start @@ -183,20 +145,21 @@ _start: zerobss: LA (v0, _fbss) LA (v1, _end) - beq v0,v1,2f -1: - addiu v0,v0,4 - sw zero,-4(v0) - bne v0,v1,1b -2: +3: + sw zero,0(v0) + bltu v0,v1,3b + addiu v0,v0,4 # executed in delay slot + la t0, __lstack # make a small stack so we addiu sp, t0, STARTUP_STACK_SIZE # can run some C code la a0, __memsize # get the usable memory size jal get_mem_info + nop /* setup the stack pointer */ LA (t0, __stack) # is __stack set ? bne t0,zero,4f + nop /* NOTE: a0[0] contains the amount of memory available, and not the last memory address. */ @@ -226,14 +189,19 @@ zerobss: init: LA (t9, hardware_init_hook) # init the hardware if needed beq t9,zero,6f - jalr t9 + nop + jal t9 + nop 6: LA (t9, software_init_hook) # init the hardware if needed beq t9,zero,7f - jalr t9 + nop + jal t9 + nop 7: LA (a0, _fini) jal atexit + nop #ifdef GCRT0 .globl _ftext @@ -241,10 +209,12 @@ init: LA (a0, _ftext) LA (a1, _etext) jal monstartup + nop #endif jal _init # run global constructors + nop addiu a1,sp,32 # argv = sp + 32 addiu a2,sp,40 # envp = sp + 40 @@ -255,13 +225,13 @@ init: sw zero,(a1) sw zero,(a2) #endif - move a0,zero # set argc to 0 jal main # call the program start function + move a0,zero # set argc to 0 # fall through to the "exit" routine - move a0,v0 # pass through the exit code jal exit # call libc exit to run the G++ # destructors + move a0,v0 # pass through the exit code .end init @@ -287,25 +257,27 @@ _exit: /* Need to reinit PICBASE, since we might be called via exit() rather than via a return path which would restore old s0. */ #define PICBASE exit_PICBASE - .set noreorder PICBASE = .+8 bal PICBASE nop move s0,$31 - .set reorder #endif #ifdef GCRT0 LA (t0, _mcleanup) - jalr t0 + jal t0 + nop #endif LA (t0, hardware_exit_hook) beq t0,zero,1f - jalr t0 + nop + jal t0 + nop 1: # break instruction can cope with 0xfffff, but GAS limits the range: break 1023 b 7b # but loop back just in-case + nop .end _exit /* Assume the PICBASE set up above is no longer valid below here. */ |