;References:
;swi - vector_handler_forward

;vector_handler_29
;-----------------
;Takes over running a file if the JIT is running
;
;Reference PRM1-288 for actions to take depending on filetype
;          PRM1-197 for OS_UpCall 256 - new application starting
;          PRM1-266 for Service_NewApplication (not much use)
;          PRM2-85  for OS_FSControl 2 (*GO)
;          PRM2-87  for OS_FSControl 4
;
;Entry:
; R0 = reason code
; R12, R14 stacked

.vector_handler_29
 TEQ     R0, #FSControl_StartApplication	;PRM2-85 *GO?
 TEQNE   R0, #FSControl_Run		;PRM2-87 Run file?
 BNE     vector_handler_forward		;NO, hand to OS

 LDR     R14, jit_code			;is the JIT running?
 TEQ     R14, #0
 BEQ     vector_handler_forward		;NO, hand to OS

 #if JIT_WIMP_support == 1
   BL      check_task_ID		;is the task supported?
   BNE     vector_handler_forward	;NO, hand to OS
 #endif

 TEQ     R0, #FSControl_StartApplication	;PRM2-85 *GO?
 BEQ     _star_go			;YES

;FSControl 4
;
;Entry:
; R1 = pointer to filename
;
;NOTE: Reference /RiscOs/Sources/FileSys/FileSwitch/s/FSControl RunEntry

 ADR     R12, _SPSR			;buffer C/SPSR used by pre_swi_veneer
 BL      pre_SWI_veneer			;call SWI that follows
 SWI     XADFFS_DoNothing

 TEMP    R14
 STMFD   R13!, {R0-R11}			;preserve registers
 ADR     R10, fscontrol_filename	;R10=filename
 MOV     R2, #0
 ._copy_L1
   LDRB    R0, [R1, R2]
   STRB    R0, [R10, R2]
   TEQ     R0, #0
   TEQNE   R0, #13
   ADDNE   R2, R2, #1
   TEQNE   R2, #Max_File_Length		;ensure we dont overrun
 BNE     _copy_L1
 ADD     R11, R10, R2			;R11=end of filename
 MOV     R0, #0
 STRB    R0, [R11, #0]			;terminate filename
 MOV     R1, R10

 MOV     R0, #15			;R4 is path variable
 ADR     R4, _run_path
 SWI     XOS_File			;PRM2-38 read file info
 BVS     _pass_to_RO			;pass to RISCOS on error
 TEQ     R0, #2				;directory?
 BLEQ     _directory			;Yes
 TEQ     R0, #1				;did we find the file?
 BNE     _pass_to_RO			;NO, hand to RISCOS

 MOV     R6, R0				;object type
 MOV     R7, R2				;preserve load address
 MOV     R0, #FSControl_GetFileType	;get filetype
 SWI     XOS_FSControl			;PRM2-123
 BVS     _pass_to_RO			;pass to RISCOS on error

 CMN     R2, #1				;-1 no filetype?
 MOVEQ   R2, R7				;YES, use load address
 BEQ     _load_and_run			; |+  and load it

 TEQ     R2, #&FF8			;Absolute
 BEQ     _load_and_run_absolute

 TEQ     R2, #&FFA			;Module
 BEQ     _run_module

 TEQ     R2, #&FFC			;Utility
 BEQ     _utility

 LOCK    R14
 ._pass_to_RO
 LDMFD   R13!, {R0-R11}			;preserve registers

 BL      dontexit_SWI_veneer
B       vector_handler_forward		;hand to OS


 ._run_module
 MOV     R0, #Module_Run
 STR     R0, [R13, #0]
 LDMFD   R13!, {R0-R11}			;preserve registers
 BL      dontexit_SWI_veneer
 B       load_26bit_module		;run module


 ._run_path	DCB "Run$Path", 0
		ALIGN
 ._plingrun	DCB ".!Run", 0
 		ALIGN

 ._directory				;check if !Run exists
 STR     R14, [R13, #-4]!
 ADR     R2, _plingrun

 ._directory_L1
   LDRB    R0, [R2], #1
   STRB    R0, [R11], #1
   TEQ     R0, #0
 BNE     _directory_L1

 MOV     R0, #15			;R4 is path variable
 ADR     R4, _run_path
 SWI     XOS_File			;PRM2-38 read file info
 LDR     PC, [R13], #4


;Entry:
;R1 = filename
;R4 = filesize

._utility
 ADD     R4, R4, #8			;extra words for alignment
 MOV     R12, R1			;preserve R1
 MOV     R0, #Heap_Claim		;claim JIT RMA space for file
 MOV     R1, #jit_RMA_heap
 ADD     R3, R4, #&1100			;R3=file size + 1K stack
 SWI     XOS_Heap			;PRM1-379
 ADRVS   R0, Error_no_room_in_RMA	;the claim failed
 BVS     _exit_with_error		; |+ exit with error
 MOV     R1, R2
 ADD     R2, R2, #3			;ensure allocation is word aligned
 BIC     R2, R2, #%11			;R2=start of our temp stack
 STR     R1, [R2], #4			;store allocation start
 MOV     R1, R12			;preserve R1

 ADD     R3, R2, #&100			;R3=start of workspace for utility
 STR     R4, [R2], #4			;stack file size

 LDMFD   R13!, {R6-R11}			;pull R0-R5 from stack
 STMIA   R2!, {R6-R11}			;stack into buffer
 LDMFD   R13!, {R6-R11}			;pull R6-R11 from stack
 STMIA   R2!, {R6-R11}			;stack into buffer
 STMIA   R2, {R13-R14}^			;stack USER R13, R14 into buffer
 ADD     R2, R2, #8
 ADR     R12, _SPSR
 LDMIA   R12, {R6-R8}			;get our SWI exit registers
 STMIA   R2!, {R6-R8}			;stack into buffer
 STR     R2, [R13, #-4]!		;preserve R2 so we can free RMA later

 STR     R3, [R2, #2 * 4]		;stack R12
 ADD     R3, R3, #&1000			;needs 1K workspace
 STR     R3, [R2, #3 * 4]		;stack R13
 ADD     R14, R3, #jit_code_start
 STR     R14, [R2, #4 * 4]		;stack PC

 STR     R1, [R13, #-4]!
 MOV     R0, #CAOPointer		;set CAO
 MOV     R1, R3				;to prevent memory shrinkage
 SWI     XOS_ChangeEnvironment		;PRM1-320
 LDR     R1, [R13], #4

 MOV     R0, #14			;R4 is path variable
 MOV     R2, R3				;load address
 MOV     R3, #0
 ADR     R4, _run_path
 SWI     XOS_File + (JIT_SWI_OS_Flag << 20) ;PRM2-43 load file hypervised
 LDR     R2, [R13]			;preserve R2

 STMFD   R13!, {R1-R2}
 SWI     XOS_GetEnv			;PRM1-301 get the environment string
 LDMFD   R13!, {R1-R2}
 STR     R0, [R2, #0 * 4]		;stack R0

 ._utility_L1
   LDRB    R12, [R1], #1		;copy command line
   STRB    R12, [R0], #1
   TEQ     R12, #0
   TEQNE   R12, #13
   TEQNE   R12, #32
 BNE     _utility_L1

 ._utility_L2				;copy any spaces
   TEQ     R12, #32
   STREQB  R12, [R0], #1
   LDREQB  R12, [R1], #1
 BEQ     _utility_L2

 SUB     R0, R0, #1			;R14=command tail
 STR     R0, [R2, #1 * 4]		;stack R1

 ._utility_L3				;copy arguments
   STRB    R12, [R0], #1
   LDRB    R12, [R1], #1
   TEQ     R12, #13
   TEQNE   R12, #0
 BNE     _utility_L3
 MOV     R12, #0
 STRB    R12, [R0]			;terminate string

 LDR     R0, _SPSR
 AND     R0, R0, #%10000		;correct USER mode
 MSR     CPSR_all, R0			;switch to USER with flags cleared
 #if compile_IOMD == 1
   NOP
 #endif

 LDMIA   R2!, {R0-R1, R12-R13}		;load USER registers
 ADR     R14, _utility_return
 STR     R14, [R13, #-4]!		;stack return
 LDR     R14, jit_managed_ldr_pc_r13	;return in 26bit space
LDR     PC, [R2]			;call utility

 ._utility_return
 MRS     R1, CPSR			;need to track V status
 SWI     XOS_EnterOS

 ADR     R12, _SPSR
 LDR     R14, [R13], #4			;pull RMA allocation from SVC stack
 LDMDB   R14!, {R6-R8}			;pull our SWI exit registers
 TST     R1, #1 << 28			;did it exit with V set?
 ORRNE   R6, R6, #1 << 28		;YES, set V in exit CPSR
 STMIA   R12, {R6-R8}			;preserve SWI exit registers
 LDMEQDB R14, {R0-R11, R13-R14}^	;preserve USER registers
 LDMNEDB R14, {R1-R11, R13-R14}^	;V set, preserve USER registers
 #if compile_IOMD == 1
   NOP					;fix for errata on ARM6/7 macrocells, StrongARM
 #endif
 SUB     R14, R14, #14 * 4		;drop registers we just restored
 STMFD   R13!, {R0-R4}			;preserve R0-R4
 LDR     R12, [R14, #-4]!		;R12=file size
					;R14=start of heap allocation
 ADD     R3, R14, #&1100		;R3=start of code (heap + 1K stack)

 MOV     R0, #Heap_Free			;release claimed JIT RMA space
 MOV     R1, #jit_RMA_heap
 LDR     R2, [R14, #-4]			;get address of allocation
 SWI     XOS_Heap			;PRM1-380

 MOV     R2, R3				;RMA block start
 MOV     R4, R12			;filesize
 BL      hv_reset_memory_block		;release block in JIT space
 LDMFD   R13!, {R0-R4}

 ADR     R12, _SPSR
B       exit_SWI_veneer


._exit_with_error
 ADD     R13, R13, #4			;drop R0
 LDMFD   R13!, {R1-R11}			;preserve registers
B      exit_SWI_veneer			;exit with error




;Entry:
; R1,R10 - filename

._load_and_run
 ;check R2 is within application space
 CMP     R2, #&8000			;valid load address?
 BLO     _pass_to_RO			;NO
 ADD     R5, R2, R4			;R5=start+size
 SUB     R14, R5, #1
 CMP     R3, R2				;is exec above load address?
 RSBGES  R14, R3, R14			;YES, is it below end address
 BLT     _pass_to_RO			;NO

 MOV     R0, #14			;R4 is path variable
 MOV     R3, #1				;use file load address
 ADR     R4, _run_path
 SWI     XOS_File + (JIT_SWI_OS_Flag << 20) ;PRM2-43 load file hypervised
 MOV     R9, R3				;R9=execution address
 B       _not_absolute


;Entry:
; R1,R10 - filename

._load_and_run_absolute
 MOV     R0, #14			;R4 is path variable
 MOV     R3, #0				;use address in R2
 MOV     R2, #&8000
 ADR     R4, _run_path
 SWI     XOS_File + (JIT_SWI_OS_Flag << 20) ;PRM2-43 load file hypervised
 MOV     R9, #&8000			;R9=execution address

 ._not_absolute
 BVS     _exit_with_error		;exit on error

 MOV     R1, R10			;R1=filename
 MOV     R2, R9				;CAO
 MOV     R3, R10			;commandline
 ._setup_CAO
 BL      release_ChangeEnvironmentV	;release Environment handlers
					;as RISC OS will clear them
 MOV     R0, #FSControl_StartApplication	;setup environment
 BL      pass_SWI_on
 SWI     XOS_FSControl			;PRM2-85
 BVS     _exit_with_error		;exit on error

 SWI     XOS_GetEnv			;PRM1-301
 MOV     R1, R2				;R1=time
 MOV     R0, R10			;filename to become environment
 SWI     XOS_WriteEnv			;PRM1-322

 BL      dontexit_SWI_veneer
 LDR     R14, [R12, #0]			;get entry SPSR
 BIC     R14, R14, #%1111 << 28		;clear flags (fixes Pipe Mania)
 BIC     R14, R14, #%11001111		;switch to USER, IRQ/FIQ enabled
 LDR     R13, SVC_stack_init		;collapse the SVC stack

 MSR     CPSR_all, R14			;now in USER
 #if compile_IOMD == 1
   NOP
 #endif
 MOV     R13, #jit_allocate_memory	;put stack at end of user space
 MOV     R12, #jit_allocate_memory	;put stack at end of user space
 LDR     R14, jit_managed_os_exit	;return via an OS_Exit
 ADD     PC, R9, #jit_code_start




;FSControl 2
;
;Entry:
; R1=command tail
; R2=address to *GO
; R3=command line
; R7=R2 if called from *GO, R7 is the address *GO uses
;
;Exit:
; R9  - address to call (in original appspace)
; R10 - command line
; NOTE: Dependent on /RiscOs/Sources/Kernel/s/SysComms GO_Code using R7
;       RO5 doesn't clear flags before calling code (causes Pipe Mania
;       to fail)

._star_go
 TEQ     R7, R2				;is it *GO?
 BNE     vector_handler_forward		;NO, pass on

 CMP     R2, #jit_appspace_end		;is it in appspace?
 BHI     vector_handler_forward		;NO

 ADR     R12, _SPSR			;buffer C/SPSR used by pre_swi_veneer
 BL      pre_SWI_veneer			;call SWI that follows
 SWI     XADFFS_DoNothing

 MOV     R10, R3			;command line
 MOV     R9, R2				;address to call
 B       _setup_CAO


 ._SPSR		DBD 4
