# ==========  RUNTIME SUPPORT CODE  ========== 
#
#  This file contains
#    _entry
#      Where execution begins
#
# This version supports KPL programs running in kernel space as stand-alone programs.
# It assumes the program is being executed by the Blitz emulator. There is no thread
# scheduler, so all programs are single-threaded. All code runs with interrupts
# enabled, except exception handler functions.
#
# Harry Porter  -  30 May 2003         - From old Blitz-32 code
# Harry Porter  -  24 April 2019       - Initial version
# Harry Porter  -   1 May 2020         - Mods re: Host file I/O
# Harry Porter  -  21 Sept 2022        - Changed to support ISA version 2
# Harry Porter  -  21 Sept 2023        - Reorganized
#

	.sourcefile	"BasicEntry.s", "Support for Stand-alone Programs - Harry Porter"


	.import		_P_BasicSystem_Boot_Code                    # e.g., "coldboot" = 0x636F6C64626F6F74
	.import		_P_BasicSystem_Boot_Private_Memory_Size     # in bytes
	.import		_P_BasicSystem_Boot_Shared_Memory_Start
	.import		_P_BasicSystem_Boot_Shared_Memory_Size      # in bytes, possibly 0
	.import		_P_BasicSystem_Boot_First_Unused_Addr
	.import		_P_BasicSystem_Boot_Csr_Version


	.import		_kplEntry				# From compiled "main" function
	.import		exit					# From KPLLRuntime.s
	.import		_putString				# .
	.import		GlobalTrapHandler			# From GlobalTrapHandler
	.import		CPUStateSaveArea			# .
	.import		TimerInterval				# .


	.begin		kernel, startaddr = 0x0_0000_0008

# 
# =====================  RuntimeStartup  =====================
#
# Prepare for KPL program execution.  Initialize the stack pointer and other things.
# Then call the "_kplEntry" function, which will call "main". "_kplEntry" is a function
# generated by the compiler for any package containing the "main" function.
#
# CONCERNING STACK USAGE: "_entry" allocates exactly 8 bytes onto the stack. The value
#        of 0 is pushed as the "return address", indicating the bottom of the stack
#        to the debugger. If the framesize changes later on, it will affect any
#        and all stack overflow calculations, since this is a fixed, known overhead.
#        (See also all stack usage related to errors and THROW processing, since that
#        can push additional bytes onto the stack.)
#
_entry:
	.export		_entry

	.function	"_entry",line=0,framesize=32
	.local		0,"arg_1",line=0,type="I"
	.local		8,"arg_2",line=0,type="I"
	.local		16,"arg_3",line=0,type="I"
	movi		gp,0x0_0001_0000	# Initialize the Global Pointer register

	stored		_P_BasicSystem_Boot_Code,r1			# Store parameters from boot program
	stored		_P_BasicSystem_Boot_Private_Memory_Size,r2	# Store parameters from boot program
	stored		_P_BasicSystem_Boot_Shared_Memory_Start,r3	# Store parameters from boot program
	stored		_P_BasicSystem_Boot_Shared_Memory_Size,r4	# Store parameters from boot program
	stored		_P_BasicSystem_Boot_First_Unused_Addr,r5	# Store parameters from boot program
	csrread		r1,csr_version				# Store csr_version in "Boot_Csr_Version"
	stored		_P_BasicSystem_Boot_Csr_Version,r1		# Store parameters from boot program

	add		sp,r2,r4		# Initialize the stack pointer
	addi		sp,sp,-32		# Allocate frame (argSaveArea=3*8) with
	stored		24(sp),r0		# . return address of zero, to indicate no caller
	movi		r1,GlobalTrapHandler	# Initialize csr_trapvec
	csrwrite	csr_trapvec,r1		# .
	movi		tp,0			# Set "tp", the Thread Pointer register to NULL
	movi		r1,TimerInterval        # How often timer interrupts will occur
	csrwrite	csr_timer,r1		# .
	movi		r1,CPUStateSaveArea	# Initialize csr_ptr to point to TCB
	csrwrite	csr_ptr,r1		# .
	csrset		csr_status,3		# Enable interrupts
#	movi		r1,startupMessage	# Print start-up message
#	call		_putString		# .
	movi		r1,0			# Call "_kplEntry" with args (0,0,0)
	movi		r2,0			# .
	movi		r3,0			# .
	call		_kplEntry		# .
	movi		r1,0			# Call exit(0)
	call		exit			# .
	.endfunction
startupMessage:
	.string		"====================  KPL PROGRAM STARTING  ====================\n\0"
	.align		8

