Page 1 of 1

New crt0.s for ps2sdk

Posted: Fri Jul 13, 2007 9:32 am
by chp
I started looking at updating some of the ps2sdk and increasing general code quality. I started with updating the newlib-patch from 1.10.0 to 1.15.0 (still testing it, wait a few days) and also updating the custom ps2 code in there... While doing that I noticed that the crt0.s in there really, really sucks, and the one in ps2sdk isn't that pretty either, so I spent a few hours today rewriting it.

Changes
  • Properly made _ps2sdk_* symbols weak (as they are in the SDK) so that it does no longer actually require PS2SDK to link properly.
  • Return value is now stored before _fini() and _ps2sdk_libc_deinit() is called. It would otherwise have been overwritten by any function returning a value (or whenever the register was used inside a function).
  • zerobss code is now better at handling edge cases
  • A lot more readable than the previous version and should be easy to tweak for different uses.
  • _exit() is now actually returning the proper returncode
Any comments on this are welcome before I commit it to subversion.

Updates 13/07
  • Dropped byte-range clearing of bss (it should be 128-bit aligned both in position and size)

Code: Select all

# _____     ___ ____     ___ ____
#  ____|   |    ____|   |        | |____|
# |     ___|   |____ ___|    ____| |    \    PS2DEV Open Source Project.
#-----------------------------------------------------------------------
# Copyright (c) 2001-2007 ps2dev - http://www.ps2dev.org
# Licenced under Academic Free License version 2.0
# Review ps2sdk README & LICENSE files for further details.
#
# $Id:$
# Standard startup file.


	.globl	_init
	.type	_init, @function
	.weak	_init

	.globl	_fini
	.type	_fini, @function
	.weak	_fini

	.extern	_heap_size
	.extern	_stack
	.extern	_stack_size	

	.globl	_ps2sdk_args_parse
	.type	_ps2sdk_args_parse, @function
	.weak	_ps2sdk_args_parse

	.globl	_ps2sdk_libc_init
	.type	_ps2sdk_libc_init, @function
	.weak	_ps2sdk_libc_init

	.globl	_ps2sdk_libc_deinit
	.type	_ps2sdk_libc_deinit, @function
	.weak	_ps2sdk_libc_deinit

	.set	noat
	.set	noreorder

	.text
	.align	2

	nop
	nop

	.globl	_start
	.ent	_start
_start:

zerobss:
	# clear bss area

	la	$2, _fbss
	la	$3, _end

1:
	sltu	$1, $2, $3
	beq	$1, $0, 2f
	nop
	sq	$0, ($2)
	addiu	$2, $2, 16
	j	1b
	nop
2:

	# store eventual loader arguments (passed via a0)

	la	$2, _loader_args
	sw	$4, ($2)

setupthread:
	# setup current thread

	la	$4, _gp
	la	$5, _stack
	la	$6, _stack_size
	la	$7, _args
	la	$8, _root
	move	$gp, $4
	addiu	$3, $0, 60
	syscall			# SetupThread(_gp, _stack, _stack_size, _args, _root)
	move	$sp, $2

	# initialize heap

	la	$4, _end
	la	$5, _heap_size
	addiu	$3, $0, 61
	syscall			# SetupHeap(_end, _heap_size)

	# writeback data cache

	move	$4, $0
	addiu	$3, $0, 100
	syscall			# FlushCache(0)

parseargs:
	# call ps2sdk argument parsing (weak)

	la	$8, _ps2sdk_args_parse
	beqz	$8, 1f
	nop

	jal	_getargs
	nop
	jalr	$8		# _ps2sdk_args_parse(argc, argv)
	nop
1:

libc_init:
	# initialize ps2sdk libc (weak)

	la	$8, _ps2sdk_libc_init
	beqz	$8, 1f
	nop
	jalr	$8		# _ps2sdk_libc_init()
	nop
1:	

ctors:
	# call global constructors (weak)

	la	$8, _init
	beqz	$8, 1f
	nop
	jalr	$8		# _init()
	nop
1:

	# call main

	ei
	jal	_getargs
	nop
	jal	main		# main(argc, argv)
	nop

	# call _exit

	j	_exit		# _exit(retval)
	move	$4, $2
	.end	_start

	.align	3

	.globl	_exit
	.ent	_exit
	.text
_exit:
	la	$2, _retval
	sw	$4, ($2)

dtors:
	# call global destructors (weak)

	la	$8, _fini
	beqz	$8, 1f
	nop
	jalr	$8		# _fini()
	nop
1:

libc_uninit:
	# uninitialize ps2sdk libc (weak)

	la	$8, _ps2sdk_libc_deinit
	beqz	$8, 1f
	nop
	jalr	$8		# _ps2sdk_libc_deinit()
	nop
1:

	# conditional exit (depending on if we got arguments through the loader or not)

	la	$2, _retval
	lw	$4, ($2)

	la	$5, _loader_args
	lw	$6, ($5)
	beqz	$6, 1f
	nop

	# called from a loader, close thread

	lw	$7, ($6)
	sw	$0, ($7)	# clear thread id

	addiu	$3, $0, 36
	syscall			# ExitDeleteThread() (noreturn)
1:

	# not called from a loader, return to browser

	addiu	$3, $0, 4
	syscall			# Exit(retval) (noreturn)

	.end	_exit

	.ent	_root
_root:
	addiu	$3, $0, 35
	syscall			# ExitThread() (noreturn)
	.end	_root

	.ent	_getargs
_getargs:
	# check normal arguments

	la	$2, _args
	lw	$3, ($2)
	bnez	$3, 1f
	nop

	# check for arguments passed by a loader

	la	$2, _loader_args
	lw	$3, ($2)
	beqzl	$3, 2f
	addu	$4, $0, 0

	addiu	$2, $3, 4
1:
	lw	$4, ($2)
	addiu	$5, $2, 4
2:
	jr	$ra		# $4 = argc, $5 = argv
	nop
	.end	_getargs

	.bss
	.align	6
_args:
	.space	4+16*4+256	# argc, 16 arguments, 256 bytes payload
_loader_args:
	.space	4		# pointer to loader arguments: thread id, argc, argv
_retval:
	.space	4

Posted: Fri Jul 13, 2007 1:29 pm
by ooPo
Yay! Upgrades!