#
#  _____     ___ ____
#   ____|   |    ____|      PS2 OpenSource Project
#  |     ___|   |____
#  ------------------------------------------------------------------------
#  crt0.s                   Standard startup file.
#                           Altered to not setup a thread as
#                           ps2link will have done that already

.set noat
.set noreorder

.global _start
.global	_exit

	.extern	_heap_size
	.extern	_stack
	.extern _stack_size

	.text

	nop
	nop

	.ent _start
_start:

# Clear bss elf segment (static uninitalised data)
zerobss:
	la	$2, _fbss
	la	$3, _end
loop:
	nop
	nop
	nop
	sq		$0,($2)
	sltu	$1,$2,$3
	bne		$1,$0,loop
	addiu	$2,$2,16


# Disable branch prediction on those EEs it's broken on. (EEs <= #2.5)
	mfc0	$8,$15				# CP0_PRID
	andi	$8, 0xff
	li		$9, 0x13			# 0x13: EE#2.5
	slt		$at, $9, $8
	bne		$at, $0, 1f
#	bgt		$8, 0x13, 1f		# 0x13: EE#2.5
	mfc0	$8,$16				# CP0_CONFIG
	lui		$9, %hi(~(1<<12))
	ori		$9, $9, %lo(~(1<<12))
	and		$8,$8,$9
	mtc0	$8, $16
	sync.p

# Some program loaders (such as Pukklink) execute programs as a thread, but
# support passing argc and argv values via a0.  This also indicates that when
# the program terminates, control should be returned to the program loader
# instead of the PS2 browser.
1:	la	$2, _args_ptr
    sw	$4,($2)

# Setup a thread to use -> We don't want to do this for ps2gdbStub as pukklink's already set a thread up; don't know about naplink!
#	la	$4, _gp
#	la	$5, _stack
#	la	$6, _stack_size
#	la	$7, _args
#	la	$8, _root
#	move	$28,$4
#	addiu	$3,$0,60
#	syscall			# RFU060(gp, stack, stack_size, args, root_func)
#	move	$29, $2

# Instead, I just put values directly into registers, copying the stack into fp. Should work!
	la		$28, _gp
	por		$30, $29, $29

# Heap. Could we be overwriting each other's heaps here? Looks that way, need to find out what this does exactly. Presumably it's
# malloc'able ram? I ain't calling this again anyway.
#	addiu	$3,$0,61
#	la	$4, _end
#	la	$5, _heap_size
#	syscall			# RFU061(heap_start, heap_size)
#	nop

# Flush the data cache (no need to preserve regs for this call)
	li	$3, 0x64
	move	$4,$0
	syscall			# FlushCache(0) - Writeback data cache

# Jump main, now that environment and args are setup
	ei

# Check for arguments pased via ExecPS2 or LoadExecPS2
	la	$2, _args
	lw	$3, ($2)
	bnez	$3, 1f
	nop

# Otherwise check for arguments passed by a loader via a0 (_arg_ptr)
	la	$2, _args_ptr
	lw	$3, ($2)
	beqzl	$3, 2f
	addu	$4, $0, 0

	addiu	$2, $3, 4
1:
	lw	$4, ($2)
	addiu	$5, $2, 4
2:
	jal	main
	nop
	.end	_start

	.ent	_exit
_exit:
# If we received our program arguments in a0, then we were executed by a
# loader, and we don't want to return to the browser.
	la	$4, _args_ptr
	lw	$5, ($4)
	beqz	$5, 1f
	move	$4, $2		# main()'s return code

	lw	$6, ($5)
	sw	$0, ($6)
	addiu	$3, $0, 36
	syscall			# ExitDeleteThread(void)

# Return to the browser via Exit()
1:
	addiu	$3, $0, 4
	syscall			# Exit(void)
	.end	_exit

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

	.bss
	.align	6
_args:
	.space	256+16*4+4
_args_ptr:
	.space	4