279 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
			
		
		
	
	
			279 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
| /*
 | |
|  * crt0.S -- startup file for MIPS.
 | |
|  *
 | |
|  * Copyright (c) 1995, 1996, 1997, 2001 Cygnus Support
 | |
|  *
 | |
|  * 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.
 | |
|  */
 | |
| 
 | |
| #ifdef __mips16
 | |
| /* This file contains 32 bit assembly code.  */
 | |
| 	.set nomips16
 | |
| #endif
 | |
| 
 | |
| #include "regs.S"
 | |
| 
 | |
| /*
 | |
|  * Set up some room for a stack. We just grab a chunk of memory.
 | |
|  */
 | |
| #define STACK_SIZE  0x4000
 | |
| #define GLOBAL_SIZE 0x2000
 | |
| 
 | |
| #define STARTUP_STACK_SIZE	0x0100
 | |
| 
 | |
| /* This is for referencing addresses that are not in the .sdata or
 | |
|    .sbss section under embedded-pic, or before we've set up gp.  */
 | |
| #ifdef __mips_embedded_pic
 | |
| # ifdef __mips64
 | |
| #  define LA(t,x) la t,x-PICBASE ; daddu t,s0,t
 | |
| # else
 | |
| #  define LA(t,x) la t,x-PICBASE ; addu t,s0,t
 | |
| # endif
 | |
| #else /* __mips_embedded_pic */
 | |
| # define LA(t,x) la t,x
 | |
| #endif /* __mips_embedded_pic */
 | |
| 
 | |
| 	.comm	__memsize, 12
 | |
| 	.comm	__lstack, STARTUP_STACK_SIZE
 | |
| 
 | |
| 	.text
 | |
| 	.align	2
 | |
| 
 | |
| /* Without the following nop, GDB thinks _start is a data variable.
 | |
|  * This is probably a bug in GDB in handling a symbol that is at the
 | |
|  * start of the .text section.
 | |
|  */
 | |
| 	nop
 | |
| 
 | |
| 	.globl	hardware_hazard_hook .text
 | |
| 	.globl	_start
 | |
| 	.ent	_start
 | |
| _start:
 | |
| 	.set	noreorder
 | |
| #ifdef __mips_embedded_pic
 | |
| #define PICBASE start_PICBASE
 | |
| 	PICBASE = .+8
 | |
|         bal	PICBASE
 | |
| 	nop
 | |
| 	move	s0,$31
 | |
| #endif
 | |
| #if !defined(__mips64) || (__mips_fpr==32)
 | |
| #define STATUS_MASK (SR_CU1|SR_PE)
 | |
| #else
 | |
| # For mips3 or mips4, turn on 64-bit addressing and additional float regs
 | |
| #define STATUS_MASK (SR_CU1|SR_PE|SR_FR|SR_KX|SR_SX|SR_UX)
 | |
| #endif
 | |
| 	li	v0, STATUS_MASK
 | |
| 	mtc0	v0, C0_SR
 | |
| 	mtc0	zero, C0_CAUSE
 | |
| 	nop
 | |
| 
 | |
| 	/* Avoid hazard from FPU enable and other SR changes.  */
 | |
| 	LA (t0, hardware_hazard_hook)
 | |
| 	beq	t0,zero,1f
 | |
| 	nop
 | |
| 	jal	t0
 | |
| 	nop
 | |
| 1:
 | |
| 
 | |
| /* Check for FPU presence.  Don't check if we know that soft_float is
 | |
|    being used.  (This also avoids illegal instruction exceptions.)  */
 | |
| 
 | |
| #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
 | |
| 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 FPU disable.  */
 | |
| 	LA (t0, hardware_hazard_hook)
 | |
| 	beq	t0,zero,2f
 | |
| 	nop
 | |
| 	jal	t0
 | |
| 	nop
 | |
| 2:
 | |
| 
 | |
| 
 | |
| /* 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
 | |
| 
 | |
| /*
 | |
|  * zero out the bss section.
 | |
|  */
 | |
| 	.globl	__memsize
 | |
| 	.globl	get_mem_info .text
 | |
| 	.globl	__stack
 | |
| 	.globl	__global
 | |
| 	.ent	zerobss
 | |
| zerobss:
 | |
| 	LA (v0, _fbss)
 | |
| 	LA (v1, _end)
 | |
| 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. */
 | |
| 	la	a0, __memsize
 | |
| 	lw	t0,0(a0)			# last address of memory available
 | |
| 	la	t1,K0BASE			# cached kernel memory
 | |
| 	addu	t0,t0,t1			# get the end of memory address
 | |
| 	/* Allocate 32 bytes for the register parameters.  Allocate 16
 | |
| 	   bytes for a null argv and envp.  Round the result up to 64
 | |
| 	   bytes to preserve alignment.  */
 | |
| 	subu	t0,t0,64
 | |
| 4:
 | |
| 	move	sp,t0				# set stack pointer
 | |
| 	.end	zerobss
 | |
| 
 | |
| /*
 | |
|  * initialize target specific stuff. Only execute these
 | |
|  * functions it they exist.
 | |
|  */
 | |
| 	.globl	hardware_init_hook .text
 | |
| 	.globl	software_init_hook .text
 | |
| 	.type	_fini,@function
 | |
| 	.type	_init,@function
 | |
| 	.globl	atexit .text
 | |
| 	.globl	exit .text
 | |
| 	.ent	init
 | |
| init:
 | |
| 	LA (t9, hardware_init_hook)		# init the hardware if needed
 | |
| 	beq	t9,zero,6f
 | |
| 	nop
 | |
| 	jal	t9
 | |
| 	nop
 | |
| 6:
 | |
| 	LA (t9, software_init_hook)		# init the hardware if needed
 | |
| 	beq	t9,zero,7f
 | |
| 	nop
 | |
| 	jal	t9
 | |
| 	nop
 | |
| 7:
 | |
| 	LA (a0, _fini)
 | |
| 	jal	atexit
 | |
| 	nop
 | |
| 
 | |
| #ifdef GCRT0
 | |
| 	.globl	_ftext
 | |
| 	.globl	_extext
 | |
| 	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
 | |
| #if __mips64
 | |
| 	sd	zero,(a1)			# argv[argc] = 0
 | |
| 	sd	zero,(a2)			# envp[0] = 0
 | |
| #else
 | |
| 	sw	zero,(a1)
 | |
| 	sw	zero,(a2)
 | |
| #endif
 | |
| 	jal	main				# call the program start function
 | |
| 	move	a0,zero				# set argc to 0
 | |
| 
 | |
| 	# fall through to the "exit" routine
 | |
| 	jal	exit				# call libc exit to run the G++
 | |
| 						# destructors
 | |
| 	move	a0,v0				# pass through the exit code
 | |
| 	.end	init
 | |
| 
 | |
|  
 | |
| /* Assume the PICBASE set up above is no longer valid below here.  */
 | |
| #ifdef __mips_embedded_pic
 | |
| #undef PICBASE
 | |
| #endif
 | |
| 	
 | |
| /*
 | |
|  * _exit -- Exit from the application. Normally we cause a user trap
 | |
|  *          to return to the ROM monitor for another run. NOTE: This is
 | |
|  *	    the only other routine we provide in the crt0.o object, since
 | |
|  *          it may be tied to the "_start" routine. It also allows
 | |
|  *          executables that contain a complete world to be linked with
 | |
|  *          just the crt0.o object.
 | |
|  */
 | |
| 	.globl	hardware_exit_hook .text
 | |
| 	.globl	_exit
 | |
| 	.ent _exit
 | |
| _exit:
 | |
| 7:
 | |
| #ifdef __mips_embedded_pic
 | |
| 	/* 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
 | |
| 	PICBASE = .+8
 | |
| 	bal	PICBASE
 | |
| 	nop
 | |
| 	move	s0,$31
 | |
| #endif
 | |
| #ifdef GCRT0
 | |
| 	LA (t0, _mcleanup)
 | |
| 	jal	t0
 | |
| 	nop
 | |
| #endif
 | |
| 	LA (t0, hardware_exit_hook)
 | |
| 	beq	t0,zero,1f
 | |
| 	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.  */
 | |
| #ifdef __mips_embedded_pic
 | |
| #undef PICBASE
 | |
| #endif
 | |
| 
 | |
| /* EOF crt0.S */
 |