#set jit_allocate_memory = 8 * 1024 * 1024	;total memory for JIT
#set jit_RMA_size	 = 1.5 * 1024 * 1024	;total memory for JIT RMA
#set jit_slotsize	 = 27.5 * 1024 * 1024	;ram to allocate for appspace
#set jit_code_start	 = jit_slotsize - (jit_allocate_memory + jit_RMA_size)
#if compile_RO > 311 AND compile_RO < 450
  #set jit_ram		 = jit_slotsize		;total ram for WimpSlot
#else
  #set jit_ram		 = &1F08000		;total ram for WimpSlot
#endif

#set jit_appspace_end	 = jit_allocate_memory + jit_RMA_size
						;max RAM JIT supports
						;16mb is theorical max
#set jit_RMA_heap	 = jit_allocate_memory	;start of JIT RMA

#set lastfree_codelet	 = jit_appspace_end	;last free block in codelets

#set jit_trace_buffer_size	= &300000	;size of the trace buffer


.Entry_GOARM3JIT
 TEQ     R1, #0				;are we initialising?
 MOV     R1, R0
 STMFD   R13!, {R1-R12, R14}
 ADR     R12, VARS
 BNE     _P1				;YES

 LDR     R0, jit_code			;NO, shutting down
 TEQ     R0, #0				;is the JIT running?
 LDMEQFD R13!, {R1-R12, PC}		;NO, exit

 BL      shutdown_interrupts
 BL      kill_26bit_modules		;kill legacy modules
 BL      release_ChangeEnvironmentV	;release environment handlers

 LDR     R0, [R12, #jit_task_count - VARS]
 SUBS    R0, R0, #1			;decrease JIT task count
 STR     R0, [R12, #jit_task_count - VARS]
 BNE     _remove_taskID			;not the last task

;@@@ NEEDS TO ONLY CLEAN UP THIS TASK AND SHUTDOWN IF LAST TASK

 #if Managed_ChannelHandler == 1
   BL      reset_sound_configure	;reset audio subsystem
 #endif
 BL      clear_jitmemorya		;remove any buffered code changes

 #if JIT_debug == 1 AND compile_IOMD == 1
   ADR     R0, report_JIT_IOMD
   MOV     R1, #0
   SWI     XOS_RemoveTickerEvent
 #endif

 BL      _release_processor_vectors
 LDMVSFD R13!, {R1-R12, PC}		;exit on error

 TEMP    R1
 MOV     R0, #0
 STR     R0, jit_code
 STR     R0, JIT_event11_active		;reset Event 11 counter
 LOCK    R1

 #if JIT_protect_page_zero == 1
   LDR     R0, os_version		;ARM710VE-83 / 85
   CMP     R0, #&380 << 8		;are we below RO3.8?
   LDRLO   R1, page_zero_L2PT		;YES, restore page zero protection
   MOVLO   R0, #0			; |
   BLLO    CACHEOP_INVALIDATE_TLB_R0	; |+ flush TLB
 #endif

 #if compile_RO == 500
   TEMP    R1
   ADR     R2, Current_Machine_State
   LDR     R0, [R2, #Machine_State.cpu_control_register]
   TEQ     R0, #0			;did we change the CPU CR?
   MCRNE   P15, 0, R0, C1, C0, 0	;YES, set it back
   MOVNE   R0, #0
   STRNE   R0, [R2, #Machine_State.cpu_control_register]
   LOCK    R1
   #if compile_RO == 500 AND High_Vectors == 1
;ref. https://www.riscosopen.org/wiki/documentation/show/OS_Memory%2020
     MOV     R0, #20			;check compatibility page
     LDR     R1, [R2, #Machine_State.OS_Memory20]
     TEQ     R1, #0			;did we change it?
     SWINE   XOS_Memory			;YES
   #endif
 #endif

 LDR     R0, [R12, #BASICTrans_loaded - VARS]
 TEQ     R0, #0
 MOVNE   R0, #Module_Delete		;RMKill BASIC module
 ADRNE   R1, _BASICTrans
 SWINE   XOS_Module			;PRM1-235
 MOV     R0, #0
 STR     R0, [R12, #BASICTrans_loaded - VARS]

 ._remove_taskID
 #if JIT_self_modifying_support == 1
   BL      reset_appspace_L2PT
 #endif

 MOV     R0, #5				;get current task ID
 SWI     XWimp_ReadSysInfo		;PRM3-216
 TEQ     R0, #0				;do we need to remove Filters
 BLNE    Remove_Wimp_Filters		;YES
 
 BL      remove_this_taskID		;stop tracking the current task

 MVN     R0, #0
 SWI     XWimp_CommandWindow		;hide command window

 SUBS    R0, R0, R0			;clear V
LDMFD   R13!, {R1-R12, PC}


 ._P1
 #if JIT_debug == 1 AND compile_IOMD == 1
   MOV     R0, #dbg_pause_default
   TEMP    R1
   STR     R0, dbg_pause
   LOCK    R1

   MOV     R0, #1
   ADR     R1, report_JIT_IOMD
   MOV     R2, #0
   SWI     XOS_CallEvery
 #endif

 LDR     R0, jit_code
 TEQ     R0, #0				;is the JIT already setup?
 BNE     _already_setup			; |+ skip initialisation

 BL      store_machine_state		;store key repeat etc
 
 MVN     R0, #0				;read current slotsize
 MVN     R1, #0
 SWI     XWimp_SlotSize			;PRM3-203

 MOV     R1, #jit_allocate_memory - &8000	;RAM limit
 CMP     R0, R1				;do we have enough RAM?
 MOVHS   R3, R1				;cap at jit_ram limit
 MOVLO   R3, R0				;store current slotsize
 MOV     R1, #jit_ram - &8000
 CMP     R0, R1				;do we have enough RAM?
 MOVLO   R0, R1				;NO, allocate more
 MVNLO   R1, #0
 SWILO   XWimp_SlotSize			;PRM3-203
 LDMVSFD R13!, {R1-R12, PC}		;exit on error

 MVN     R0, #0				;read current slotsize
 MVN     R1, #0
 SWI     XWimp_SlotSize			;PRM3-203
 MOV     R1, #jit_ram - &8000
 CMP     R0, R1				;do we have enough RAM?
 MOVLO   R0, #1 << 31			;NO, set V
 ADDLOS  R0, R0, R0
 ADRVS   R0, Error_jit_slotsize
 LDMVSFD R13!, {R1-R12, PC}		;exit on error
 TEMP    R0
 STR     R3, pre_JIT_wimp_slot_size	;store current WimpSlot
 LOCK    R0

 MOV     R0, #Heap_Initialise		;initialise JIT RMA heap
 MOV     R1, #jit_RMA_heap
 MOV     R3, #jit_RMA_size
 SWI     XOS_Heap			;PRM1-377

 ADR     R7, MEMC_registers		;reset MEMC registers
 MOV     R0, #&1F03800
 STR     R0, [R7, #IOC_Cinit << 2]	;Pointer
 MOV     R0, #&36E0D0C
 STR     R0, [R7, #MEMC_CR << 2]

 MOV     R0, #0
 #if compile_GPU == 1
   BL      reset_IOC
 #endif

 TEMP    R1
 STR     R0, linear_handler_entry	;reset sound handler
 STR     R0, Module_being_inserted	;reset
 LOCK    R1

 ADR     R7, DeviceVectors		;initialise Device Vector claims
 MOV     R1, #(last_device_to_track + 1) * device_table.size
 ._device_vectors_L1
   STR     R0, [R7], #4
   SUBS    R1, R1, #4
 BNE     _device_vectors_L1

 ADR     R2, Current_Machine_State
 #if Unaligned_Support == 0
   MRC     P15, 0, R0, C1, C0, 0	;get CPU control register
					;see ARM ARM rev.I B3-12
   BIC     R3, R0, #1 << 1		;disable alignment fault checking
   BIC     R3, R3, #1 << 22		;enable rotated unaligned loads
   TEQ     R0, R3
   TEMP    R1
   STRNE   R0, [R2, #Machine_State.cpu_control_register]
   LOCK    R1
   MCRNE   P15, 0, R3, C1, C0, 0	;update ARM Control Register
 #endif
 #if Unaligned_Support == 1
   MRC     P15, 0, R0, C1, C0, 0	;get CPU control register
					;see ARM ARM rev.I B3-12
   ORR     R3, R0, #1 << 1		;enable alignment fault checking
   TEQ     R0, R3
   TEMP    R1
   STRNE   R0, [R2, #Machine_State.cpu_control_register]
   LOCK    R1
   MCRNE   P15, 0, R3, C1, C0, 0	;update ARM Control Register
 #endif

 #if compile_RO == 500 AND High_Vectors == 1
;ref. https://www.riscosopen.org/wiki/documentation/show/OS_Memory%2020
   MOV     R0, #20			;check compatibility page
   MVN     R1, #0
   SWI     XOS_Memory
   MOVVS   R1, #0
   CMP     R1, #0			;is it available?
   MOVMI   R1, #0			;NO
   STR     R1, [R2, #Machine_State.OS_Memory20]
   TEQ     R1, #1			;is page zero mapped?
   MOVEQ   R1, #0			;YES
   SWIEQ   XOS_Memory			; |+ disable page
 #endif

 #if JIT_protect_page_zero == 1
   LDR     R0, os_version		;ARM710VE-83 / 85
   CMP     R0, #&380 << 8		;are we below RO3.8?
   TEMP    R3
   LDRLO   R0, L2PT_addr		;YES, protect page zero
   LDRLO   R1, [R0]			; |  page zero L2PT
   STRLO   R1, page_zero_L2PT		; |  keep a copy for later
   BICLO   R1, R1, #%11111111 << 4	; |  user is read-only
   ORRLO   R1, R1, #%11101010 << 4	; |  protect 0..&2FFF
   MOVLO   R0, #0			; |
   BLLO    CACHEOP_INVALIDATE_TLB_R0	; |+ flush TLB
   LOCK    R3
 #endif

 #if JIT_instruction_trace == 1
   LDR     R3, [R12, #IT_DA_address - VARS]	;our DA address
   MOV     R1, #&100000
   ADD     R3, R3, #&100000
   SUB     R1, R1, #1
   BIC     R3, R3, R1				;align to 1MB boundary
   TEMP    R1
   STR     R3, instruction_trace_ptr
   LOCK    R1
   STR     R3, [R3, #-4]
 #endif
					;Now setup the top 16mb ready for
					;translated code, which needs to
					;jump back into the JIT
 MOV     R3, #jit_code_start
 LDR     R1, branch_to_jit		;instruction to enter JIT
 MOV     R2, R1, LSL #4
 TEMP    R7
 STR     R2, branch_to_jit_no_condition	;used to quickly check for Hypercalls
 LOCK    R7
 MOV     R2, R1
 MOV     R4, R1
 MOV     R5, R1
 MOV     R6, R1
 MOV     R7, R1
 MOV     R8, R1
 MOV     R0, R1
 ._L2
   STMIA   R3!, {R0-R2, R4-R8}
   STMIA   R3!, {R0-R2, R4-R8}
   TEQ     R3, #jit_slotsize
 BNE     _L2

 #if compile_DEBUG == 1 OR JIT_instruction_trace == 1	;force chocolate off
   MOV     R0, #5			;turn lazy page mapping off
   MOV     R1, #0
   SWI     XOS_AMBControl

   MOV     R3, #&4000
   LDR     R4, current_PageSize
   ._L1_chocolate
     LDR     R0, [R3], R4		;force pages to be mapped
     CMP     R3, #jit_code_start
   BLO     _L1_chocolate
 #endif

 TEMP    R3
 LDR     R0, OIRQ_vector_stack		;reset private stacks
 STR     R0, IRQ_vector_stack
 LDR     R0, Otmp_module_stack
 STR     R0, tmp_module_stack

 SWI     XOS_GetEnv			;get EnvString
 STR     R0, page_zero_EnvString	;used in page_zero_abort handler
 STR     R2, page_zero_EnvTime		;used in page_zero_abort handler
					;setup exit code below 27.5mb
 MOV     R0, #0				;reset hypervised IRQ handlers
 STR     R0, hypervised_IRQ1V
 STR     R0, hypervised_IRQv
 STR     R0, terminate_all_voices
 #if JIT_debug == 1
   STR     R0, jit_codelet_count
   STR     R0, jit_joysticks
 #endif

 MOV     R0, #jit_code_start
 LDR     R1, _codelet_os_exit		;OS_Exit for general use
 STR     R1, [R0, #-4]!
 STR     R0, jit_managed_os_exit

 ADR     R5, _codelet3			;LDR PC, [R13], #4 for general use
 LDMIA   R5, {R1-R3}
 STMDB   R0!, {R1-R3}			;entry for us
 ADD     R1, R0, #8			;skip the two NOP's
 STR     R1, jit_managed_ldr_pc_r13

 ADR     R5, _codelet3_2		;LDR PC, [R13+4], #4 for general use
 LDMIA   R5, {R1-R4}
 STMDB   R0!, {R1-R4}			;entry for us
 ADD     R1, R0, #8			;skip the two NOP's
 STR     R1, jit_managed_ldr_pc_r13_2
 SUB     R1, R1, #&18 + 8
 MOV     R1, R1, LSR #2
 ORR     R1, R1, #&EA000000		;B <address>
 STR     R1, jit_managed_IRQ_entry	;instruction game sees at &18

 SUB     R0, R0, #EnvHandler.size * 17	;space to track environment handlers
 STR     R0, environment_handlers
 BL      claim_ChangeEnvironmentV	;ensure we've claimed environment handlers
 BL      initialise_vector_table
 BL      get_DA2_size

 ADR     R1, _codelet_wimp_pollidle_end	;create Wimp_Poll codelets
 LDMDB   R1!, {R2-R3}
 STMDB   R0!, {R2-R3}
 STR     R0, codelet_Wimp_PollIdle
 ADR     R1, _codelet_wimp_pollidle
 LDMDB   R1!, {R2-R3}
 STMDB   R0!, {R2-R3}
 STR     R0, codelet_Wimp_Poll

 MOV     R1, #0
 STR     R1, [R0, #-4]!
 STR     R0, private_CLibCounter
 STR     R1, [R0, #-4]!
 STR     R0, private_RISCOSLibWord
 STR     R1, [R0, #-4]!
 STR     R0, private_CLibWord
					;-----------------------
 SUB     R0, R0, #codelet_struct.codelet	;initialize first codelet
 BIC     R0, R0, #codelet_alignment - 1		;align it
 STR     R0, [R0, #codelet_struct.next]		;next=pointer to itself
 STR     R0, [R0, #codelet_struct.previous]	;previous=pointer to itself
 MOV     R1, #codelet_struct.codelet
 STR     R1, [R0, #codelet_struct.size]		;size=codelet_struct size
 MVN     R1, #0
 STR     R1, [R0, #codelet_struct.source]	;source=-1
 STR     R0, first_codelet
						;initialize last free codelet
 MOV     R2, #lastfree_codelet			;R2=codelet
 STR     R2, [R2, #codelet_struct.next]		;next=pointer to itself
 STR     R2, [R2, #codelet_struct.previous]	;previous=pointer to itself
 MOV     R1, #0
 STR     R1, [R2, #codelet_struct.source]	;source=0
 SUB     R1, R0, R2				;R1=size
 STR     R1, [R2, #codelet_struct.size]		;size=free space
					;-----------------------
 MOV     R0, #jit_code_start
 STR     R0, jit_code			;start of translated code

 BL      _claim_processor_vectors	;claim processor vectors
 BVC     _already_setup

 MOV     R3, R0				;remember error
 BL      _release_processor_vectors
 MOV     R0, R3
 MSR     CPSR_f, #1 << 28		;set V
 LDMFD   R13!, {R1-R12, PC}		;exit
 LOCK    R3

 ._already_setup
 LDR     R0, [R12, #jit_task_count - VARS]
 ADD     R0, R0, #1			;increase JIT task count
 STR     R0, [R12, #jit_task_count - VARS]

 BL      get_taskID			;get current task

 LDR     R1, [R13, #0]			;command tail
 MOV     R0, #16			;base 16 number with restricted range
 SWI     XOS_ReadUnsigned		;read the value PRM1-460
 LDMVSFD R13!, {R1-R12, PC}		;exit on error
 ADD     R4, R2, #jit_code_start	;R4=start address

 MOV     R3, R1				;do we have an environment string?
 ._find_env_L1
   LDRB    R1, [R3], #1
   TEQ     R1, #ASC(";")		;environment string?
   TEQNE   R1, #0			;terminator?
 BNE     _find_env_L1			;NO

 TEQ     R1, #ASC(";")			;environment string found?
 BNE     _find_env_P1
 SWI     XOS_GetEnv			;PRM1-301
 MOV     R1, R2				;R1=time
 MOV     R0, R3				;string to become environment
 SWI     XOS_WriteEnv			;PRM1-322

 ._find_env_P1
 MOV     R2, R4				;preserve R2
 TEQ     R2, #jit_code_start		;are we simply setting up the JIT?
 LDMEQFD R13!, {R1-R12, PC}		;YES, exit

 ADD     R13, R13, #2 * 4		;drop R1-R2 from stack
 LDMFD   R13!, {R3-R12}			;clear down stack
 ADD     R13, R13, #4			;drop R14

 MRS     R14, CPSR			;go into the correct USER mode
 BIC     R14, R14, #%11001111 + (%1111 << 28)	;USER/USER32 IRQ/FIQ enabled
 MSR     CPSR_all, R14
 #if compile_IOMD == 1
   NOP
 #endif

 MOV     R13, #jit_allocate_memory	;put stack at end of user space
 LDR     R14, jit_managed_os_exit
MOV     PC, R2				;call code, R0=environment string


 ._claim_processor_vectors
 STR     R14, [R13, #-4]!

 TEMP    R14
 BL      Claim_DataAbort_Vector			;claim DataAbort vector
 LDRVS   PC, [R13], #4

 MOV     R0, #Vector_UndefinedInstr + (1<<8)	;claim Undefined instruction vector
 ADR     R1, Undefined_Instruction_Vector
 SWI     XOS_ClaimProcessorVector		;PRM5a-30
 LDRVS   PC, [R13], #4
 STR     R1, existing_UndefinedInstr

 MOV     R0, #Vector_IRQ + (1<<8)		;claim IRQ vector
 ADR     R1, IRQ_Vector_Handler
 SWI     XOS_ClaimProcessorVector		;PRM5a-30
 LDRVS   PC, [R13], #4
 STR     R1, existing_IRQVector			;store existing

 MOV     R0, #Vector_BranchThruZero + (1<<8)	;claim Reset vector
 ADR     R1, Branch_thru_zero
 SWI     XOS_ClaimProcessorVector		;PRM5a-30
 LDRVS   PC, [R13], #4
 STR     R1, [R12, #existing_Branch_thru_zero - VARS]	;store existing

 #if compile_RO > 400
   MOV     R0, #Vector_SeriousErrorV		;claim SeriousError vector
   ADR     R1, seriousErrorV_handler
   ADR     R2, VARS
   SWI     XOS_Claim
 #endif

 LOCK    R14
LDR     PC, [R13], #4



 ._release_processor_vectors
 STMFD   R13!, {R1-R4, R14}

 TEMP    R14
 MOV     R4, #0
 BL      release_DataAbort_Vector
 MOVVS   R4, R0
 MOV     R3, #0
 MOV     R0, #Vector_IRQ		;release IRQ vector
 LDR     R1, existing_IRQVector
 ADR     R2, IRQ_Vector_Handler
 TEQ     R1, #0
 SWINE   XOS_ClaimProcessorVector	;PRM5a-30
 MOVVS   R4, R0
 STRVC   R3, existing_IRQVector
 MOV     R0, #Vector_BranchThruZero	;release branch through zero handler
 LDR     R1, existing_Branch_thru_zero
 ADR     R2, Branch_thru_zero
 TEQ     R1, #0
 SWINE   XOS_ClaimProcessorVector	;PRM5a-30
 MOVVS   R4, R0
 STRVC   R3, [R12, #existing_Branch_thru_zero - VARS]
 MOV     R0, #Vector_UndefinedInstr	;release Undefined Instruction vector
 LDR     R1, existing_UndefinedInstr
 ADR     R2, Undefined_Instruction_Vector
 TEQ     R1, #0
 SWINE   XOS_ClaimProcessorVector	;PRM5a-30
 MOVVS   R4, R0
 STRVC   R3, existing_UndefinedInstr
 #if compile_RO > 400
   MOV     R0, #Vector_SeriousErrorV	;release SeriousError vector
   ADR     R1, seriousErrorV_handler
   ADR     R2, VARS
   SWI     XOS_Release
   MOVVS   R4, R0
 #endif
 LOCK    R14

 MOVS    R0, R4
 MSRNE   CPSR_f, #1 << 28		;set V
LDMFD   R13!, {R1-R4, PC}



 ._BASICTrans		DCB "BASICTrans", 0
			ALIGN

 ._codelet_os_exit	SWI OS_Exit	;hypervised exit back to OS

 ._codelet3
 NOP					;R1 NOP's for processor vector returns
 NOP					;R2
 LDR     PC, [R13], #4			;R3 hypervised exit back to us

 ._codelet3_2
 NOP					;R1 NOP's for processor vector returns
 NOP					;R2
 ADD     R13, R13, #4			;R3
 LDR     PC, [R13], #4			;R4 hypervised exit back to us

; DCD 0					;return address
 ._codelet_wimp_poll
; STR     R0, _codelet_wimp_poll - 16	;R1
; STR     R1, _codelet_wimp_poll - 12	;R2
; STR     R14, _codelet_wimp_poll - 8	;R3
; ADR     R0, _codelet_wimp_poll - 512	;R4
; MOV     R1, #512 - 20			;R5
; SWI     XOS_DelinkApplication		;R6
; LDR     R0, _codelet_wimp_poll - 16	;R7
; LDR     R1, _codelet_wimp_poll - 12	;R8
 SWI     XWimp_Poll			;R9
; STR     R0, _codelet_wimp_poll - 16	;R10
;   MOV     R0, #jit_slotsize
;   ._L2_chocolate
;     SUB     R0, R0, #4*1024
;     LDR     R14, [R0, #0]
;     CMP     R0, #&4000
;   BNE     _L2_chocolate
; ADR     R0, _codelet_wimp_poll - 512	;R2
; SWI     XOS_RelinkApplication		;R3
; LDR     R0, _codelet_wimp_poll - 16	;R4
; LDR     R14, _codelet_wimp_poll - 8	;R5
 LDR     PC, _codelet_wimp_poll - 4	;R6

 ._codelet_wimp_pollidle
; STR     R0, _codelet_wimp_poll - 16	;R1
; STR     R1, _codelet_wimp_poll - 12	;R2
; STR     R14, _codelet_wimp_poll - 8	;R3
; ADR     R0, _codelet_wimp_poll - 512	;R4
; MOV     R1, #512 - 20			;R5
; SWI     XOS_DelinkApplication		;R6
; LDR     R0, _codelet_wimp_poll - 16	;R7
; LDR     R1, _codelet_wimp_poll - 12	;R8
 SWI     XWimp_PollIdle			;R9
; STR     R0, _codelet_wimp_poll - 16	;R10
;   MOV     R0, #jit_slotsize
;   ._L3_chocolate
;     SUB     R0, R0, #4*1024
;     LDR     R14, [R0, #0]
;     CMP     R0, #&4000
;   BNE     _L3_chocolate
; ADR     R0, _codelet_wimp_poll - 512	;R2
; SWI     XOS_RelinkApplication		;R3
; LDR     R0, _codelet_wimp_poll - 16	;R4
; LDR     R14, _codelet_wimp_poll - 8	;R5
 LDR     PC, _codelet_wimp_poll - 4	;R6
 ._codelet_wimp_pollidle_end