;Abort handler
;
;Addresses we need to translate
; 1F00000            - CursorChunkAddress (pre RO5)
; 1F033C0            - SWI dispatch handler (RO5+)
; 1F03800            - mouse pointer (Diggers, Caverns) (RO5+)
; 1F06000            - sound buffer 1 (RO5+)
; 1F07000            - sound buffer 2 (RO5+)
; 1F88000 to 2078000 - screen memory (lower half is logical, top half physical)
; 3200000            - IOC (read/write)
; 3400000            - VIDC1 (write only)
; 3500000            - VIDC20 (write only)
; 3600000            - MEMC (write only)
; 3800000            - Logical to Physical Address Translator (write only)

;seriousErrorV_handler
;---------------------
;Watches for fatal error recovery events

#if compile_RO > 400
; Entry:
;  R0 - Pointer to register dump (Collect)
;  R2 - Reason code.  0=Collect, 1=Recover, 2=Report, 3=Custom Report

.seriousErrorV_handler
; STMFD   R13!, {R0-R12, R14}
; BL      check_JIT_and_taskID		;is the task supported?
; LDMNEFD R13!, {R0-R12, PC}		;NO
; TEQ     R2, #SeriousErrorV_Report
; BEQ     _shutdown
;
; TEQ     R2, #SeriousErrorV_Collect	;Error occurred, collect debug info
; LDMNEFD R13!, {R0-R12, PC}
;
; ADR     R1, DAV_r0
; LDMIA   R0!, {R3-R10}			;R0-R7
; STMIA   R1!, {R3-R10}
; LDMIA   R0!, {R3-R10}			;R8-PC
; SUB     R10, R10, #8			;correct PC
; STMIA   R1!, {R3-R10}
; LDR     R1, [R0]			;PSR
; STR     R1, DAV_CPSR
;; ADD     R13, R13, #4
;; MOV     R12, #&14			;ADFF5014
;; B       report_unimplemented		;ABT or UND stack will contain reg dump
;LDMFD   R13!, {R0-R12, PC}
;
; ._shutdown
; ADR     R1, adffs_task_terminated
; TEQ     R0, R1				;is it us terminating a task?
; LDMEQFD R13!, {R0-R12, PC}		;YES
;
; MOV     R0, #1
; STR     R0, [R12, #jit_task_count - VARS]	;force a shutdown
; MOV     R1, #0				;shutdown JIT
; BL      Entry_GOARM3JIT
;LDMFD   R13!, {R0-R12, PC}


 MOV     R11, R14
 TEQ     R2, #SeriousErrorV_Collect	;Error occurred, collect debug info
; TEQNE   R2, #SeriousErrorV_Recover	;Report?
 BLEQ    check_JIT_and_taskID		;is the task supported?
 MOVNE   PC, R11			;NO

; TEQ     R2, #SeriousErrorV_Recover
; BEQ     _shutdown

 ADR     R1, DAV_r0
 LDMIA   R0!, {R3-R10}			;R0-R7
 STMIA   R1!, {R3-R10}
 LDMIA   R0!, {R3-R10}			;R8-PC
 SUB     R10, R10, #8			;correct PC
 STMIA   R1!, {R3-R10}
 LDR     R1, [R0]			;PSR
 STR     R1, DAV_CPSR
 ADD     R13, R13, #4
 MOV     R12, #&14			;ADFF5014
 B       report_unimplemented		;ABT or UND stack will contain reg dump

; ._shutdown
;; LDR     R13, SVC_stack_init		;collapse SVCxx stack
; STMFD   R13!, {R0-R1, R11}
; ADR     R1, adffs_task_terminated
; TEQ     R0, R1				;is it us terminating a task?
; LDMEQFD R13!, {R0-R1, PC}		;YES
;
; MOV     R1, #0				;shutdown JIT
; BL      Entry_GOARM3JIT
; LDMFD   R13!, {R0-R1, PC}
#endif



;BBB Claim ErrorV
;.ErrorV_handler
;; STR     R0, DAV_r0
;; ADR     R0, DAV_r0
;; STMIA   R0, {R1-R14}
;;
; MOV     R12, #&14			;ADFF5014
; B       report_unimplemented		;ABT or UND stack will contain reg dump



 ALIGN   32, 4
 #if compile_RO == 400
   .MEMC_L1PT		DCD 0		;temp copy of MEMC1 L1PT entry
   .abt_stack		DCD 0		;our ABT32 stack
 #endif
 #if compile_IOMD == 1
   .Screen_Cache_Off	DCD 0		;<>0 force screen cache off on RO4
 #endif
 #if JIT_self_modifying_support == 1
   .subpages_supported	DCD 0		;[31..16]=L2PT AP mask, [0]=subpage support
 #endif
 .L1PT_addr		DCD RO371_L1PT	;address of L1PT
 .L2PT_addr		DCD RO371_L2PT	;address of L2PT
 .DA_mask		DCD 0		;mask to clear from address to get block
 .DA_mask_shift		DCD 0		;bit shift required for mask
 .abort_address		DCD 0		;address causing error

 .existing_DataAbort		DCD 0	;OS Data Abort vector address
 .existing_UndefinedInstr	DCD 0

 .DAV_CPSR		DCD 0
 .DAV_r0_tmp		DCD 0		;temp for entry
 .DAV_abort_tmp		DCD 0		;temp for entry

					;****** MUST REMAIN TOGETHER *****
 .DAV_r0		DBD 15		;aborting R0-R14 registers
 .DAV_abort		DCD 0		;..PC
 #if JIT_pipelining == 1
   ._pipeline		DCD 0		;JIT pipeline stage 2 instruction
   ._pipeline_non_JIT	DCD 0		;actual pipeline stage 2 instruction
 #endif					;*********************************

 .DAV_ABT_R14		DCD 0		;ABT R14 <>0 if abort in progress
 .DAV_ABT_resume	DCD 0,0		;address to return to if an abort occurs
					;...to prevent recursive aborts

 .Early_Abort_Mode	DCD %00		;bit 0 - 0=LDM/STM early abort mode
					;bit 1 - 0=LDR/STR early abort mode

 .current_abort_type	DCD 0		;0=Data, 1=Prefetch, 2=Addr Exception

 .DA2_address		DCD 0		;current DA2 start
 .DA2_size		DCD 0		;size of screen DA



;pass_to_previous_Und
;--------------------
;pass an Undefined instruction onto RISCOS

.pass_to_previous_Und
 LDMFD   R13!, {R0-R7, R14}		;restore registers
.pass_to_existing_UndInstr_2
 ADD     R14, R14, #4			;correct as we altered it
.pass_to_existing_UndInstr
LDR     PC, existing_UndefinedInstr	;pass call on



;Data_Abort_inprogress
;---------------------
;An Abort occurred within the Abort handler, pass to RISC OS

.Data_Abort_inprogress
 LDR     R0, DAV_ABT_resume
 TEQ     R0, #0				;are we report an abort?
 MOVNE   R14, R0
 LDRNE   R0, DAV_ABT_resume+4
 MSRNE   SPSR_all, R0
; MOVNE   R0, #0
; STRNE   R0, DAV_ABT_R14		;allow more Aborts
 LDR     R0, DAV_r0_tmp
 MOVNES  PC, R14
LDR     PC, existing_DataAbort		;hand to OS



;Data_Abort_Vector
;-----------------
;Handles memory exceptions when accessing the original Archimedes
;address range, also checks for JIT initiated aborts and passes them to
;JIT_abort_handler

 ALIGN   32, 4
.Data_Abort_Vector
 STR     R0, DAV_r0_tmp
 LDR     R0, DAV_ABT_R14		;is an abort in progress
 TEQ     R0, #0
 BNE     Data_Abort_inprogress		;YES, hand to OS
 STR     R14, DAV_ABT_R14		;store ABT R14
					;R0=0 (abort type)
 SUB     R14, R14, #8			;correct address (PC -8)
 STR     R0, current_abort_type		;store abort type
 STR     R14, DAV_abort_tmp		;store aborting PC

 #if compile_RO == 400
   LDR     R13, abt_stack		;setup stack
 #endif

 #if JIT_debug == 1 OR JIT_PMPaware == 1
   MOV     R0, R12
   MOV     R12, R14
   BL      ADFFS_internal_check		;is it us?
   MOV     R12, R0
   BEQ     _pass_to_OS			;report aborts within ADFFS
 #endif

 BL      check_taskID
 BNE     _pass_to_OS

 #if JIT_debug == 1
   TEMP    R0
   LDR     R14, DAV_abort_tmp
   STR     R14, user_PC
   MRS     R14, SPSR
   STR     R14, user_SPSR
   LOCK    R0
 #endif

 MRC     P15, 0, R0, C6, C0		;read Fault Address Register
 STR     R0, abort_address		;store the aborting address
 CMP     R0, #page_zero_Scratch_Space	;is the aborting address in page zero?
 BLO     _P1				;YES, keep it
 CMP     R0, #jit_slotsize		;NO, application memory?
 BHI     _P1				;NO, keep it
					;YES, could be caused by the JIT
 MRC     P15, 0, R0, C5, C0		;ARM710VE-89 read Fault Status Register

 #if compile_RO == 500
   TST     R0, #1 << 10			;check FSR is correct type
   ANDEQ   R0, R0, #%1111		;YES, R0=Status
 #endif
 #if compile_IOMD == 1
   AND     R0, R0, #%1111		;R0=Status
 #endif

 TEQ     R0, #%1111			;is it a page access permission?
 #if Unaligned_Support == 1
   TEQNE   R0, #%0001			;Alignment error?
 #endif
 BEQ     JIT_abort_handler		;YES, pass to JIT Abort handler

; #if JIT_PMPaware == 1
;   TEQ     R0, #7			;Page Translation fault?
;   BEQ     _pass_to_OS			;YES, Lazy Page fault
; #endif
B       _pass_to_OS			;NO, pass to RISCOS


 ._P1
 LDR     R14, DAV_abort_tmp
 LDR     R0, DAV_r0_tmp
 STR     R14, DAV_abort
 STR     R0, DAV_r0
 ADR     R0, DAV_r0 + 4			;buffer for registers
 STMIA   R0!, {R1-R7}			;store unbanked registers

 MRS     R1, SPSR			;get original CPU state
 TST     R1, #%1111			;is abort in User mode?
 STR     R1, DAV_CPSR			;store CPU state for exit and..
					;..fix for errata on SA-110 rev.2
 STMEQIA R0, {R8-R14}^			;get User mode registers
 BEQ     _P2

 MRS     R2, CPSR
 ORR     R1, R1, #%11 << 6		;disable IRQ/FIQ
 ORR     R2, R2, #%11 << 6		;disable IRQ/FIQ
 MSR     CPSR_c, R1			;switch to faulting mode
 #if compile_IOMD == 1
   NOP
 #endif
 STMIA   R0, {R8-R14}			;get aborting mode registers

 MSR     CPSR_c, R2			;return to original mode
 #if compile_IOMD == 1
   NOP
 #endif

 ._P2
 #if JIT_debug == 1 AND JIT_report_immediate == 1
   BL      report_JIT			;display JIT information
   LDR     R14, DAV_abort
 #endif

 LDR     R1, abort_address		;get the faulting address
 #if JIT_instruction_trace == 1
   LDR     R7, instruction_trace_ptr
   LDR     R3, [R7, #-4]
   ORR     R2, R14, #&A<<28
   ORR     R4, R1, #&B<<28
   STMIA   R3!, {R2, R4}
   BIC     R3, R3, #jit_trace_buffer_size
   STR     R3, [R7, #-4]
 #endif
 MOVS    R0, R1, LSR #14
 BEQ     _page_zero			;trying to write to <&4000?

 MOV     R0, R1, LSR #20		;check memory block

 TEQ     R0, #&1F00000 >> 20		;RO3.1 screen memory?
 #if Unaligned_Support == 1
   TEQNE   R0, #&2000000 >> 20
 #endif
 BEQ     _RO3_screen_address		;YES

 TEQ     R0, #&3000000 >> 20		;I/O?
 TEQNE   R0, #&3100000 >> 20
 BEQ     report_abort

 TEQ     R0, #&3200000 >> 20		;IOC write?
 TEQNE   R0, #&3300000 >> 20
 BEQ     IOC_abort			;YES

 TEQ     R0, #VIDC1_addr >> 20		;VIDC1 write?
 BEQ     VIDC1_abort			;YES

 TEQ     R0, #VIDC20_base_addr >> 20	;VIDC20 write?
 BEQ     VIDC20_abort			;YES

 TEQ     R0, #&3600000 >> 20		;MEMC write?
 BEQ     MEMC_abort			;YES

 #if compile_RO > 400
   LDR     R0, page_zero_EnvString	;may be HIGH
   SUB     R0, R1, R0
   CMP     R0, #&100			;EnvString?
   BLO     page_zero_abort_OS		;YES

   LDR     R0, page_zero_module_cmdline	;will be HIGH
   CMP     R0, #0			;is it set?
   SUBNE   R0, R1, R0			;YES,
   CMPNE   R0, #&100			; |   Module Commandline?
   BLO     page_zero_abort_OS		; |+  YES

   TEQ     R1, #&3800000		;trying perform a reboot?
   BEQ     _reboot_attempted		;YES, terminate task
 #endif

 ;**** these checks must be mirrored in translate_page_zero_read
 #if High_Vectors == 1
   LDR     R0, page_zero_UpCall		;may be HIGH
   SUB     R0, R1, R0
   CMP     R0, #&100			;UpCall discname?
   BLO     page_zero_abort_OS		;YES and needs to remain high
 #endif
 ;****

 #if Unaligned_Support == 1
   MRC     P15, 0, R0, C5, C0		;ARM710VE-89 read Fault Status Register
   #if Unaligned_Support == 1 AND compile_RO == 500
     TST     R0, #1 << 10		;check FSR is correct type
     ANDEQ   R0, R0, #%1111		;YES, R0=Status
   #endif
   #if Unaligned_Support == 1 AND compile_IOMD == 1
     AND     R0, R0, #%1111		;R0=Status
   #endif
   TEQ     R0, #%0001			;Alignment error?
   BNE     _pass_to_OS2			;NO

;   LDR     R0, DA2_address		;commented to allow RMA unaligned reads
;   LDR     R2, DA2_size		;(fixes SpeedBall 2)
;   ADD     R2, R2, R0
;   CMP     R1, R0
;   CMPHI   R2, R0			;is it an unaligned screen access?
;   BHI     _unaligned_keep		;YES
;
;   CMP     R1, #jit_code_start		;is it within JIT space?
;   BHI     _pass_to_OS2			;NO
;
;   ._unaligned_keep
   ADR     R8, DAV_r0
   LDR     R14, DAV_abort
   B       JIT_abort_handler_decode	;YES
 #endif

; #if JIT_debug == 1
;   LDR     R2, jit_code
;   TEQ     R2, #0			;is the ARM3 JIT running?
;   BEQ     _pass_to_OS2			;NO
;
;   LDR     R0, DAV_ABT_R14
;   CMP     R0, R2			;report aborts in our JIT
;   BLO     report_abort
; #endif

._pass_to_OS2
#if JIT_report_unhandled_aborts == 1
 ._pass_to_OS
 B       report_abort
#endif
#if JIT_report_unhandled_aborts == 0
 MOV     R0, #0
 LDR     R14, DAV_ABT_R14		;restore ABT R14
 STR     R0, DAV_ABT_R14		;allow abort entries
 LDR     R0, DAV_CPSR			;restore ABT SPSR
 MSR     SPSR_all, R0
 ADR     R0, DAV_r0			;restore corrupt registers
 LDMIA   R0, {R0-R7}
LDR     PC, existing_DataAbort		;pass to OS


._pass_to_OS
 MOV     R0, #0
 LDR     R14, DAV_ABT_R14		;restore ABT R14
 STR     R0, DAV_ABT_R14		;allow abort entries
 LDR     R0, DAV_r0_tmp
LDR     PC, existing_DataAbort		;pass to OS
#endif

._page_zero
 #if High_Vectors == 0 OR Unaligned_Support == 0
   CMP     R1, #page_zero_Scratch_Space	;application space?
   BHS     _pass_to_OS2			;YES, pass to OS
   B       page_zero_abort
 #endif
 #if High_Vectors == 1 AND Unaligned_Support == 1
   CMP     R1, #page_zero_Scratch_Space	;application space?
   BLO     page_zero_abort		;NO
   ADR     R8, DAV_r0			;YES
   B       JIT_abort_handler_decode	; |+ pass to JIT Abort handler
 #endif


._reboot_attempted
 BL      check_JIT_and_taskID		;is this a task we support?
 BNE     _pass_to_OS2			;NO

 MOV     R12, #&1A			;ADFF501A
 B       report_unimplemented


._RO3_screen_address
 #if compile_IOMD == 1
   AND     R0, R1, #&00FF000
					;1F01B84-1F02C83 is RedirectBuff
					;1F01C84-1F02C83 is OscliCircBuffStart
					;1F02C84-1F02CC3 is MouseBuff
					;1F02CC4-1F02CC7 is SpeechBuff
					;1F02CC8-1F02CCB is Sound3Buff
					;1F02CCC-1F02CBF is Sound2Buff
					;1F02CC0-1F02CC3 is Sound1Buff
					;1F02CC4-1F02CC7 is Sound0Buff
					;1F02CC8-1F030C7 is PrintBuff
					;1F030C8-1F03187 is RS423OutBuff
					;1F03188-1F03287 is RS423InBuff
					;1F03288-1F03387 is KeyBuff
					;1F03388-1F033FB is SWIDespatch
					;1F033FC-1F037FB is SvcTable
					;1F037FC-1F037FF is BranchToSWIExit
					;1F03800-1F03FFF is CursorData
   CMP     R0, #&0003000
   BEQ     mouse_ptr_abort
					;1F04000-1F05FFF is sound workspace
					;1F06000-1F07FFF is sound DMA buffer
					;1F08000 is nowhere - unmapped pages
   CMP     R0, #&0010000
   BLO     AbortI_skip			;skip writes to nowhere
  B       report_abort
 #endif
 #if compile_GPU == 1
   #if Unaligned_Support == 1
     TST     R1, #%11			;is it an unaligned access?
     ADRNE   R8, DAV_r0
     LDRNE   R14, DAV_abort
     BNE     JIT_abort_handler_decode	;YES, pass to JIT Abort handler
   #endif

 #endif
 B       _pass_to_OS2			;allow lazy page mapping
.pass_Abort_to_OS			;branched via B pass_Abort_to_OS-4



 ALIGN   32, 4
.AbortI_skip
 LDR     R0, DAV_abort			;load PC
 MOV     R1, #0
 ADD     R0, R0, #4			;we want to skip current instruction
 ADR     R14, DAV_r0			;R14=register list
 STR     R1, DAV_ABT_R14		;allow abort entries
 STR     R0, DAV_abort			;store back and return to abort addr+4

 LDR     R1, DAV_CPSR
 MSR     SPSR_all, R1
 TST     R1, #%1111			;was abort caused in user mode?
 LDMEQIA R14, {R0-R14}^			;YES
 BEQ     _exit

 MOV     R0, R14			;NO, IRQ, FIQ or SVC
 ORR     R1, R1, #%11 << 6		;IRQ/FIQ disabled
 MSR     CPSR_c, R1			;switch to faulting CPU mode
 #if compile_IOMD == 1
   NOP
 #endif
 LDMIA   R0, {R0-R14}
 MSR     CPSR_c, #%10010111		;Abort32 IRQ disabled
 #if compile_IOMD == 1
   NOP
 #endif

 ._exit
 LDR     R14, [R14, #4 * 15]
MOVS    PC, R14






;release_DataAbort_Vector
;------------------------
;Releases the Data Abort vector and prevents Video memory remapping
;
;Exit:
;  V set on error
; R0 - corrupt or error block

.release_DataAbort_Vector
 STMFD   R13!, {R1-R3, R14}
 BL      unmap_screen_memory		;unmap RO3.1 screen memory
 SUBS    R3, R3, R3			;R3=0 and V cleared
 MOV     R0, #Vector_DataAbort		;release Data abort
 LDR     R1, existing_DataAbort
 ADR     R2, Data_Abort_Vector
 TEQ     R1, #0
 SWINE   XOS_ClaimProcessorVector	;PRM5a-30
 STRVC   R3, existing_DataAbort
LDMFD   R13!, {R1-R3, PC}





;Claim_DataAbort_Vector
;----------------------
;Claims the Data Abort vector, allowing dynamic Video memory remapping
;
;Exit:
;  V set on error
; R0 - corrupt or error block

.Claim_DataAbort_Vector
 LDR     R0, existing_DataAbort
 TEQ     R0, #0				;do we already have the vector?
 MOVNE   PC, R14			;YES, exit
 STMFD   R13!, {R1-R5, R14}

 MOV     R0, #WimpSysInfo_ActiveTasks	;get number of WIMP tasks
 SWI     XWimp_ReadSysInfo		;PRM3-216
 TEQ     R0, #0				;R0>0 if WIMP is active
 BLEQ    _unmap_IOC_chipset		;WIMP isn't active

 BL      get_DA2_size			;get DA 2's size

					;CHECK FOR EARLY ABORT MODE
					;--------------------------
 #if compile_IOMD == 1
   MRS     R4, CPSR				;R4=CPSR
   ORR     R0, R4, #%11 << 6			;disable IRQ/FIQ
   MSR     CPSR_c, R0

   ADR     R1, _Early_Abort_Check
   MOV     R0, #Vector_DataAbort + (1<<8)	;claim Data abort
   SWI     XOS_ClaimProcessorVector		;PRM5a-30
   BVS     _error				;exit on error

   MOV     R0, #&2000000			;R0 = IOC physical screen address
   MOV     R2, R0

   MOV     R3, #0
   LDMIA   R0!, {R14}				;generate a Data Abort
   TEQ     R0, #&2000000			;is LDM/STM in Early Abort Mode
   ORRNE   R3, R3, #%01				;NO

   LDR     R14, [R2, #4]!			;generate a Data Abort
   TEQ     R2, #&2000000			;is LDR/STR in Early Abort Mode
   ORRNE   R3, R3, #%10				;NO
  
   MOV     R0, #Vector_DataAbort		;release Data abort vector
   ADR     R2, _Early_Abort_Check
   SWI     XOS_ClaimProcessorVector		;PRM5a-30

   ._error
   ORRVS   R4, R4, #1 << 28			;set V
   MSR     CPSR_all, R4				;..and restore IRQ/FIQ state
   NOP
   LDMVSFD R13!, {R1-R5, PC}			;exit on error
 #endif
 #if compile_IOMD == 0
   MOV     R0, #0				;read code features
   SWI     XOS_PlatformFeatures
   TST     R0, #%10000				;Early Abort Mode?
   MOVEQ   R3, #%11				;NO
   MOVNE   R3, #%00				;YES
 #endif

 STR     R3, Early_Abort_Mode		;store the abort mode
					;--------------------------
 MOV     R0, #Vector_DataAbort + (1<<8)	;claim Data abort vector
 ADR     R1, Data_Abort_Vector
 SWI     XOS_ClaimProcessorVector	;PRM5a-30
 STRVC   R1, existing_DataAbort		;store the existing DataAbort vector

 MOV     R0, #0
 STR     R0, DAV_ABT_R14		;allow Aborts to be trapped
LDMFD   R13!, {R1-R5, PC}


#if compile_IOMD == 1
  ._Early_Abort_Check
  SUBS    PC, R14, #4			;exit, skipping aborting instruction
#endif


 ._unmap_IOC_chipset
 STMFD   R13!, {R0-R9, R14}
 MOV     R9, #0

 MOV     R0, #&2000000			;unmap IOC physical screen
 BL      setup_L1_L2PT_registers
 STR     R9, [R5, #0]			;clear L2PT entry

 #if compile_RO > 400
   MOV     R0, #IOC_addr		;unmap IOC chipset
   ._L1
     BL      setup_L1_L2PT_registers
     STR     R9, [R7, #0]		;clear L1PT entry
  
     ADD     R0, R0, #&100000
     TEQ     R0, #&4000000
   BNE     _L1
 #endif

 MOV     R0, #&C0000001		;flush TLBs and caches
 SWI     XOS_MMUControl		;www.riscos.com/support/developers/strong
 SUBS    R0, R0, R0		;clear V
LDMFD   R13!, {R0-R9, PC}




;get_DA2_size
;------------
;works out the current DA 2 size, accounting for RO4/6 SA being fixed to 1mb
;boundaries

.get_DA2_size
 STMFD   R13!, {R0-R2, R14}

 LDR     R2, os_version
 MOV     R0, #DA2_magic_number		;read screen DA size
 SWI     XOS_ReadDynamicArea		;PRM1-396
 TEMP    R14
 STR     R0, DA2_address
 LOCK    R14

 CMP     R2, #&500 << 8			;RO5 or above?
 BHS     _exit				;YES, any size allowed

 CMP     R2, #&350 << 8			;RO3.50 or above?
 BGE     _max_2mb

 CMP     R1, #480 * 1024		;max RO3.1x screen size
 MOVHI   R1, #480 * 1024		;cap
 ._exit
 STR     R1, DA2_size
LDMFD   R13!, {R0-R2, PC}


 ._max_2mb
 CMP     R1, #2048 * 1024		;max RO3.5+ screen size
 MOVHI   R1, #2048 * 1024		;cap
 B       _exit




;get_screen_start
;----------------
;Returns the display screen start address
;
;Exit:
; R0 - display start address

.get_screen_start
 STMFD   R13!, {R1, R14}
 ADR     R0, readVDUstart

 ADD     R1, R0, #12 + 1		;+1 to force our handler to pass on
 SWI     XOS_ReadVduVariables		;PRM1-730

 LDR     R0, [R1, #0]
 TEMP    R1
 BIC     R0, R0, #%1111			;ensure it's quad-word aligned
 STR     R0, MEMC_Vinit			;initialise MEMC Vinit / Vstart
 STR     R0, MEMC_Vstart
 LOCK    R1
LDMFD   R13!, {R1, PC}




;map_screen_memory
;-----------------
;duplicates mapping of the current screen memory to the RO3.1 memory space
;and turns off screen caching on StrongARM

.map_screen_memory
 STMFD   R13!, {R0-R10, R14}
 LDR     R0, DA2_size
 TEQ     R0, #0				;is DA2 set?
 LDMEQFD R13!, {R0-R10, PC}		;NO, exit

 BL      setup_screen_registers

 LDRB    R14, remapping_video_memory	;are we remapping video memory?
 TEQ     R14, #0
 #if compile_GPU == 1
   LDMEQFD R13!, {R0-R10, PC}
 #endif
 #if compile_IOMD == 1
   BEQ     _check_caching
 #endif

 #if JIT_debug == 1 AND compile_IOMD == 1
   TEMP    R10
   MOV     R14, #10
   STR     R14, dbg_pause		;pause debug info whilst we switch mode
   LOCK    R10
 #endif

 #if Cached_DA2 == 0
   MOV     R10, #%0000			;force cacheable/bufferable off
 #endif
 #if Cached_DA2 == 1
   MOV     R10, #%1100			;force cacheable/bufferable on
 #endif
 #if compile_IOMD == 1 AND Cached_DA2 == 1
   LDR     R14, Screen_Cache_Off
   TEQ     R14, #0			;turn the screen cache off?
   MOVNE   R10, #%0000			;YES, force cacheable/bufferable off
 #endif

 ._L1					;map RO3.1 screen memory
   LDR     R14, [R5], #4
   BICS    R14, R14, #%1100		;set cacheable/bufferable
   ORRNE   R14, R14, R10
   STRNE   R14, [R5, #-4]
   STRNE   R14, [R0], #4		;update L2PT
   STRNE   R14, [R4], #4		;update L2PT double mapping
   ADDEQ   R0, R0, #4
   ADDEQ   R4, R4, #4

   SUBS    R1, R1, R9
 BGT     _L1

 TEMP    R10
 MOV     R14, #1
 STRB    R14, is_screen_remapped	;screen is now remapped

 #if compile_IOMD == 1
   B       map_screen_memory_P2

   ._check_caching
   LDR     R14, cpu_id
   TEQ     R14, #CPUID_StrongARM	;StrongARM?
   LDMNEFD R13!, {R0-R10, PC}		;NO, leave cache enabled
   LDR     R14, Screen_Cache_Off
   TEQ     R14, #0			;turn the screen cache off?
   LDMEQFD R13!, {R0-R10, PC}		;NO

   ADD     R5, R3, R0, LSR #10		;R5=L2PT offset of screen
   MOV     R2, R1			;R1=size of screen memory
   BL      L2PT_clear_cache		;disable L2 caching
   MOV     R2, R1			; |  R0=size of screen memory
   BL      L2PT_clear_cache		; |+ enable caching
					;set L1 caching/domain
   .map_screen_memory_P1
;   MOV     R6, #0			;domain 0
    ._map_screen_memory_L1
;     LDR     R10, [R7], #4
;     AND     R14, R10, #%11		;R14=descriptor type
;     BIC     R10, R10, #%111101100	;clear cacheable/bufferable/domain
;     ADD     PC, PC, R14, LSL #4	;4 words per code block
;     NOP
;
;     B       map_screen_memory_P2	;%00:Fault
;     NOP
;     NOP
;     NOP
;					;%01:Page
;     AND     R14, R6, #%111100000
;     ORR     R10, R10, R14		;set domain
;     B       _good
;     NOP
;					;%10:Section
;     ORR     R10, R10, R6		;set cacheable/bufferable/domain
;     ._good
;     STR     R10, [R7, #-4]
;     SUBS    R1, R1, #1 << 20		;next section
;   BGT     _map_screen_memory_L1
;					;%11:Reserved or Fault
 #endif

 .map_screen_memory_P2
 LDR     R0, DA2_address
 MOV     R1, #480 >> 2			;no of 4K pages (480K)
 LDR     R2, MMUControl_ARMop14		;refresh the TLB
 MOV     R14, PC
 MOV     PC, R2
 MOV     R0, #&1F88000			;legacy screen address
 MOV     R1, #480 >> 1			;no of 4K pages (480K * 2)
 MOV     R14, PC
 MOV     PC, R2                 

 LOCK    R10
LDMFD   R13!, {R0-R10, PC}




;unmap_screen_memory
;-------------------
;puts L1PT and L2PT back into their original state, unmapping RO3.1 screen
;memory and moving the actual screen memory into domain 1 on RO4/SA

.unmap_screen_memory
 STMFD   R13!, {R0-R10, R14}
 LDR     R0, DA2_size
 TEQ     R0, #0				;is DA2 set?
 LDMEQFD R13!, {R0-R10, PC}		;NO, exit

 BL      setup_screen_registers

 LDRB    R14, remapping_video_memory	;are we remapping video memory?
 TEQ     R14, #0
 #if compile_GPU == 1
   LDMEQFD R13!, {R0-R10, PC}
 #endif
 #if compile_IOMD == 1
   BEQ     _check_caching
 #endif
 ADR     R10, is_screen_remapped	;R10=is_screen_remapped
 LDRB    R14, [R10]
 TEQ     R14, #0			;is screen memory remapped?
 LDMEQFD R13!, {R0-R10, PC}		;NO

 MOV     R14, #0
 STRB    R14, [R10]			;screen is now unmapped

 #if JIT_debug == 1 AND compile_IOMD == 1
   TEMP    R14
   MOV     R10, #10
   STR     R10, dbg_pause		;pause debug info whilst we switch mode
   LOCK    R14
   MOV     R14, #0
 #endif

 ._L1					;map RO3.1 screen memory
   #if Cached_DA2 == 0
     LDR     R14, [R5], #4
     BIC     R14, R14, #%1100		;turn cacheable/bufferable off
     STR     R14, [R5, #-4]
     MOV     R14, #0
   #endif
   STR     R14, [R0], #4		;update L2PT
   STR     R14, [R4], #4		;update L2PT double mapping

   SUBS    R2, R2, R9
 BNE     _L1
B       map_screen_memory_P2


#if compile_IOMD == 1
 ._check_caching
 LDR     R0, cpu_id
 TEQ     R0, #CPUID_StrongARM		;StrongARM?
 LDMNEFD R13!, {R0-R10, PC}		;NO, exit

 LDR     R0, DA2_size
 ADD     R5, R3, R0, LSR #10		;R5=L2PT offset of screen
 MOV     R2, R1				;R0=size of screen memory
 BL      L2PT_set_cache			;enable caching
 MOV     R2, R1				; |  R0=size of screen memory
 BL      L2PT_set_cache			; |+ enable caching
B       map_screen_memory_P1




;L2PT_clear_cache
;----------------
;alters L2PT entries to disable caching
;
;Entry:
; R5 - start address of L2PT entries
; R2 - size of memory in bytes
;
;Exit:
; R2, R4, R5 - corrupt

.L2PT_clear_cache
   LDR     R4, [R5], #4			;R4=L2PT descriptor
   BICS    R4, R4, #%1100		;clear caching/buffering/domain
   STRNE   R4, [R5, #-4]		;update L2PT if entry exists

   SUBNES  R2, R2, R9			;next page
 BNE     L2PT_clear_cache
MOV     PC, R14




;L2PT_set_cache
;--------------
;alters L2PT entries to enable caching
;
;Entry:
; R5 - start address of L2PT entries
; R2 - size of memory in bytes
;
;Exit:
; R2, R4, R5 - corrupt


.L2PT_set_cache
   LDR     R4, [R5], #4			;R4=L2PT descriptor
   TEQ     R4, #0			;is the entry there?
   ORRNE   R4, R4, #%1100		;YES, enable buffering/caching
   STRNE   R4, [R5, #-4]		; |+   update L2PT if entry exists

   SUBNES  R2, R2, R9			;next page
 BNE     L2PT_set_cache
MOV     PC, R14
#endif




;setup_screen_registers
;----------------------
;sets up registers for altering L1 / L2 PT's

;Exit:
; R0 - L2PT address of RO3.1 screen
; R1 - size of DA 2
; R2 - size of RO3.1 screen DA (480kb)
; R3 - address of L2PT
; R4 - L2PT address of RO3.1 screen dbl map
; R5 - L2PT address of screen
; R6 - L1PT domain with cacheable/bufferable set
; R7 - L1PT address of screen
; R8 - offset in L1PT of screen double map
; R9 = Page size

.setup_screen_registers
 STMFD   R13!, {R12, R14}
 ADR     R12, VARS

 MOV     R0, #DA2_magic_number
 SWI     XOS_ReadDynamicArea		;PRM1-396
					;R0=DA address, R1=DA size
 #if compile_RO == 400
   LDRB    R14, [R12, #riscos6 - VARS]		;RISC OS 4/6
   TEQ     R14, #0
   LDREQ   R14, [R12, #DA2_delta - VARS]	;fix RO4/6 SA
   ADDEQ   R1, R1, R14
 #endif
 BL      setup_L1_L2PT_registers

 ADD     R4, R3, #&2000000 >> 10	;R4=L2PT address of RO3.1 screen dbl map
 LDR     R0, DA2_size
 MOV     R2, #480 * 1024		;R2=max size of RO3.1 screen memory
 LDR     R9, [R12, #current_PageSize - VARS]
 #if compile_RO == 400
   LDRB    R14, [R12, #riscos6 - VARS]		;RISC OS 4/6
   TEQ     R14, #0
   LDREQ   R14, [R12, #DA2_delta - VARS]	;fix RO4/6 SA
   ADDEQ   R0, R0, R14
 #endif
 SUB     R0, R4, R0, LSR #10		;R0=L2PT address of RO3.1 screen
LDMFD   R13!, {R12, PC}




;setup_L1_L2PT_registers
;-----------------------
;setup registers to alter L1 and L2 page tables

;Entry:
; R0 - start address
; R1 - size
;
;Exit:
; R3 - address of L2PT
; R5 - L2PT address of R0
; R6 - L1PT domain with cacheable/bufferable set
; R7 - L1PT address of R0
; R8 - offset in L1PT of screen double map

.setup_L1_L2PT_registers
 LDR     R3, L2PT_addr
 LDR     R7, L1PT_addr
 LDR     R5, os_version
 MOV     R6, #%001100			;assume RO3.71 domain 0
 SUB     R5, R5, #&380 << 8
 CMP     R5, #(&500 - &380) << 8	;>=RO3.80 and <RO5.0
 MOVLO   R6, #%101100			;YES, L1 needs to be domain 1
 ADD     R8, R7, R1, LSR #18		;R8=offset in L1PT of screen double map
 ADD     R7, R7, R0, LSR #18		;R7=L1PT address of R0
 BIC     R8, R8, #%11			;align L1PT addresses
 BIC     R7, R7, #%11
 ADD     R5, R3, R0, LSR #10		;R5=L2PT address R0
MOV     PC, R14




;shutdown_interrupts
;-------------------
;shutdown screen remapping, the JIT, any vector claims, timers etc.

.shutdown_interrupts
 STMFD   R13!, {R0-R12, R14}

 ADR     R12, VARS

 TEMP    R7
 #if compile_IOMD == 1
   LDR     R1, IOMD_addr
   LDRB    R0, [R1, #IOC_IRQA_mask]	;stop VSync and T0/T1 IRQ's
   BIC     R0, R0, #(1 << IOC_Timer_1)
   STRB    R0, [R1, #IOC_IRQA_mask]

   MOV     R0, #0
   ADD     R1, R12, #DeviceVectors - VARS
   MOV     R2, #last_device_to_track
   ._device_L1
     STR     R0, [R1, #device_table.entry_code]
     ADD     R1, R1, #device_table.size
     SUBS    R2, R2, #1
   BNE     _device_L1
 #endif
 #if compile_RO > 400
   BL      reset_IOC
 #endif

 #if compile_IOMD == 1 AND No_Frame_Pacing == 0
   BL      release_event_4
 #endif
 LOCK    R7

 MOV     R8, #&20			;kill voices running under the JIT
 MOV     R9, #jit_code_start
 #if JIT_instruction_trace == 1
   LDR     R7, instruction_trace_ptr
   LDR     R3, [R7, #-4]
 #endif
 #if JIT_leave_voices == 0
   MOV     R0, #1			;disable voice handler code
   BL      kill_voices_in_range
 #endif
 BL      kill_vectors_in_range		;kill any rogue vectors
 BL      release_all_ChangeEnvironmentV	;release Environment handlers
 #if JIT_instruction_trace == 1
   STR     R3, [R7, #-4]		;preserve instruction trace pointer
 #endif

 #if compile_RO > 400
   BL      seriousError
 #endif

 SWI     XHourglass_Smash		;turn off the Hourglass

 #if Managed_ChannelHandler == 1
   BL      reset_audio
 #endif

 #if JIT_debug == 0
   MOV     R2, #page_zero_Scratch_Space
   MOV     R4, #jit_appspace_end
   SUB     R4, R4, R2
   BL      hv_reset_memory_block	;reset memory to R/W
 #endif

 BL      restore_machine_state
LDMFD   R13!, {R0-R12, PC}




;report_unimplemented_PC_plus_4
;------------------------------
;reports an instruction that will crash the machine
;
;Entry:
; R12 - identifier
; DAV_abort - PC + 4

.report_unimplemented_PC_plus_4
 ADR     R0, DAV_abort
 LDR     R1, [R0]
 SUB     R1, R1, #4
 STR     R1, [R0]
B       report_unimplemented




;report_unimplemented_PC_plus_8
;-------------------------------
;reports an instruction that will crash the machine
;
;Entry:
; R12 - identifier
; DAV_abort - PC + 8

.report_unimplemented_PC_plus_8
 ADR     R0, DAV_abort
 LDR     R1, [R0]
 SUB     R1, R1, #8
 STR     R1, [R0]
;B       report_unimplemented		;fall-thru to report_unimplemented




;report_unimplemented
;--------------------
;reports an instruction that will crash the machine
;
;Entry:
; R12 - identifier

.report_unimplemented
 TEMP    R14
 ADD     R12, R12, #&ADFF5000
 STR     R12, current_abort_type
 LOCK    R14
;B       report_abort			;fall-thru to report_abort




;report_abort
;------------
;displays an abort screen and exits to the OS

#set step_back_DBG = &60		;step back, so were showing &20 past
					;DO NOT ALIGN, fall-thru code above
.report_abort
 #if JIT_debug == 1 AND compile_IOMD == 1
   MOV     R0, #100
   TEMP    R1
   STR     R0, dbg_pause		;pause the JIT debug info
   LOCK    R1
 #endif

 MRS     R0, CPSR
 BIC     R0, R0, #%11011111
 #if compile_RO > 400
   MSR     CPSR_c, #%11010011		;SVC32 IRQ/FIQ disabled
 #endif
 #if compile_RO == 400
   MSR     CPSR_c, #%11000011		;SVC26 IRQ/FIQ disabled
 #endif
 #if compile_IOMD == 1
   NOP
 #endif
 LDR     R13, SVC_stack_init		;collapse SVCxx stack

 LDR     R2, IRQsema
 MOV     R1, #0
 STR     R1, [R2, #0]			;reset IRQsema
 #if compile_RO > 400
   MSR     CPSR_c, #%11010010		;IRQ32 IRQ/FIQ disabled
 #endif
 #if compile_RO == 400
   MSR     CPSR_c, #%11000010		;IRQ26 IRQ/FIQ disabled
 #endif
 #if compile_IOMD == 1
   NOP
 #endif
 LDR     R13, IRQ_stack_init		;reset IRQ stack base

 #if compile_RO > 400
   MSR     CPSR_c, #%10010011		;SVC32 IRQ disabled
 #endif
 #if compile_RO == 400
   MSR     CPSR_c, #%10000011		;SVC26 IRQ disabled
 #endif
 #if compile_IOMD == 1
   NOP
 #endif

 ADR     R0, DAV_r0			;preserve error details
 LDMIA   R0!, {R1-R8}			;R0-R7
 STMFD   R13!, {R1-R8}
 LDMIA   R0!, {R1-R8}			;R8-PC
 STMFD   R13!, {R1-R8}
 LDR     R1, DAV_CPSR
 LDR     R2, current_abort_type
 STMFD   R13!, {R1, R2}

 ADR     R12, VARS
 #if compile_GPU == 1
   STR     R13, [R12, #blit_in_progress - VARS]	;pause the blitter
 #endif

 LDR     R0, [R12, #jit_task_count - VARS]
 TEQ     R0, #0
 MOVNE   R0, #1				;force all tasks to shutdown
 STRNE   R0, [R12, #jit_task_count - VARS]

 MOV     R1, #0
 BL      Entry_GOARM3JIT
 MOV     R1, #0
 BL      Entry_ADFRemapVideoMemory
 MOV     R0, #0
 TEMP    R1
 STR     R0, DAV_ABT_R14		;allow abort entries
 #if compile_GPU == 1
   STR     R0, [R12, #blit_in_progress - VARS]
 #endif
 LOCK    R1

 ADR     R0, DAV_r0 + (8*4)
 LDMFD   R13!, {R1, R2}
 STR     R1, DAV_CPSR
 STR     R2, current_abort_type
 LDMFD   R13!, {R1-R8}			;R8-PC
 STMIA   R0, {R1-R8}
 LDMFD   R13!, {R1-R8}			;R0-R7
 STMDB   R0, {R1-R8}

 #if compile_IOMD == 1
   MOV     R1, #25			;go to MODE 25
 #endif
 #if compile_GPU == 1
   ADR     R1, debug_mode_28		;MODE 28 C16M
 #endif
 MOV     R0, #0
 SWI     XOS_ScreenMode

 LDR     R7, jit_claimed_vectors
 TEQ     R7, #0
 BEQ     report_abort_JIT_startup_fail
 BL      report_abort_JIT_vectors

 ADR     R7, DeviceVectors
 MOV     R8, #0
 .report_abort_release_vectors_L2
   LDR     R3, [R7, #device_table.original_code]
   TEQ     R3, #0
   BEQ     report_abort_release_vectors_P1

   writeS  "Device "
   writeB  R8
   writeS  " @ "
   writeD  R3
   writeS  ""

   .report_abort_release_vectors_P1
   ADD     R7, R7, #device_table.size
   ADD     R8, R8, #1
   CMP     R8, #last_device_to_track
 BLS     report_abort_release_vectors_L2

 LDR     R7, environment_handlers
 ADD     R7, R7, #6 * EnvHandler.size
 MOV     R8, #6
 ADD     R4, PC, #0
 B       report_environment_handlers_L1
 DCB	"Error handler     ", 0
 DCB	"CallBack handler  ", 0
 DCB	"Breakpoint handler", 0
 DCB	"Escape handler    ", 0
 DCB	"Event handler     ", 0
 DCB	"Exit handler      ", 0
 DCB	"Unused SWI handler", 0
 DCB	"UpCall handler    ", 0
 ALIGN
 .report_environment_handlers_L1
   LDR     R3, [R7, #EnvHandler.user_entry]
   TEQ     R3, #0
   BEQ     report_environment_handlers_P2

   MOV     R0, R4
   SWI     XOS_Write0
   writeS  " @ "
   writeD  R3
   writeS  " "
   TEQ     R8, #6
   ADDEQ   R0, PC, #4			;"R0"
   ADDNE   R0, PC, #4			;"R12"
   B       report_environment_handlers_P3
   DCB     " R0", 0
   DCB     "R12", 0
   .report_environment_handlers_P3
   SWI     XOS_Write0
   writeS  "="
   LDR     R3, [R7, #EnvHandler.user_r12_value]
   writeD  R3
   TEQ     R8, #6			;is there a buffer?
   TEQNE   R8, #7
   TEQNE   R8, #8
   BNE     report_environment_handlers_P4
   LDR     R3, [R7, #EnvHandler.user_buffer]
   writeS  " buffer="
   writeD  R3
   B       report_environment_handlers_P1
   .report_environment_handlers_P4
   writeS  "                "
   .report_environment_handlers_P1
   writeS  " previous="
   LDR     R3, [R7, #EnvHandler.entry]
   writeD  R3
   writeS  ""

   .report_environment_handlers_P2
     LDRB    R0, [R4], #1
     TEQ     R0, #0
   BNE     report_environment_handlers_P2
   ADD     R7, R7, #EnvHandler.size
   ADD     R8, R8, #1				;go to next handler
   TEQ     R8, #13				;skip handlers 13..15
   MOVEQ   R8, #16
   ADDEQ   R7, R7, #EnvHandler.size * (16 - 13)
   TEQ     R8, #17				;last handler?
 BNE     report_environment_handlers_L1

 .report_abort_JIT_startup_fail
 BL      task_page_zero_R5			;R5=Page Zero pointer
 MOV     R0, R5
 ADD     R1, R5, #&1000
 SWI     XOS_ValidateAddress			;is the memory mapped in
 BCS     report_abort_P1			;NO, skip
 LDR     R1, [R12, #hypervised_IRQ - VARS]
 LDR     R0, [R5, #page_zero_IRQ]		;IRQ vector
 TEQ     R1, R0
 BEQ     no_IRQ_claim_to_report
 writeS  "IRQv: "
 writeD  R0
 writeS  " : "
 MOV     R1, #page_zero_IRQ
 SWI     XDebugger_Disassemble			;PRM4-225
 MOV     R0, R1
 MOV     R1, R2
 SWI     XOS_WriteN
 writeS  ""

 .no_IRQ_claim_to_report
 LDR     R1, [R12, #hypervised_IRQ1V - VARS]
 LDR     R2, [R5, #page_zero_IRQ1V]
 TEQ     R1, R2
 writeSNE "IRQ1v: "
 writeDNE R2
 writeSNE ""

 writeS  "ADFFS Exception: "
 LDR     R0, current_abort_type
 CMP     R0, #1
 BHI     report_Unimplemented_error
 writeS  "Data Abort"
 B       report_abort_P1

 .report_Unimplemented_error
 writeD  R0
 writeS  " "
 AND     R0, R0, #&FF
 ADD     PC, PC, R0, LSL #2
 B       report_abort_P1
 NOP
 B       report_adff5001
 B       report_adff5002
 B       report_adff5003
 B       report_adff5004
 B       report_adff5005
 B       report_adff5006
 B       report_adff5007
 B       report_adff5008
 B       report_adff5009
 B       report_adff500A
 B       report_adff500B
 B       report_adff500C
 B       report_adff500D
 B       report_adff500E
 B       report_adff500F
 B       report_adff5010
 B       report_adff5011
 B       report_adff5012
 B       report_adff5013
 B       report_adff5014
 B       report_adff5015
 B       report_adff5016
 B       report_adff5017
 B       report_adff5018
 B       report_adff5019
 B       report_adff501A
 B       report_adff501B
 B       report_adff501C
 B       report_adff501D
 B       report_adff501E
 B       report_adff501F

 .report_adff5001
 writeS  "Illegal Vector value"
 B       report_abort_P1

 .report_adff5002
 writeS  "SWI unsupported"
 B       report_abort_P1

 .report_adff5003
 writeS  "Device Vector unsupported"
 B       report_abort_P1

 .report_adff5004
 #if JIT_report_unknown_vectors == 1
   writeS  "Unknown Vector release"
   B       report_abort_P1
 #endif

 .report_adff5005
 writeS  "IRQ occurred in a codelet, couldn't find codelet base"
 B       report_abort_P1

 .report_adff5006
 writeS  "Directly accessing 1772 FDC"
 B       report_abort_P1

 .report_adff5007
 #if ARMv7_support == 1
   writeS  "Aborted LDM or STM with PC in reglist"
   B       report_abort_P1
 #endif

 .report_adff5008
 writeS  "SharedCLibrary_LibInitModule called"
 B       report_abort_P1

 .report_adff5009
 writeS  "Instruction not implemented"
 B       report_abort_P1

 .report_adff500A
 #if JIT_cache_consistency == 1
   writeS  "JIT cache inconsistent with main memory"
   B       report_abort_P1
 #endif

 .report_adff500B
 writeS  "Can't translate MEMC physical address"
 B       report_abort_P1

 .report_adff500C
 writeS  "Branch direct to SWI dispatcher at &1F033C0"
 B       report_abort_P1

 .report_adff500D
 #if compile_DEBUG == 1 AND JIT_debug == 1
   writeS  "Breakpoint"
   B       report_abort_P1
 #endif

 .report_adff500E
 #if JIT_prevent_OS_EnterOS == 1
   writeS  "Trying to enter SVC"
   B       report_abort_P1
 #endif

 .report_adff500F
 writeS  "Unsupported Environment handler"
 B       report_abort_P1

 .report_adff5010
 writeS  "Branch into Page Zero"
 B       report_abort_P1

 .report_adff5011
 writeS  "Unhandled read in Page Zero"
 B       report_abort_P1

 .report_adff5012
 writeS  "Too many Vector claims"
 B       report_abort_P1

 .report_adff5013
 writeS  "Unsupported Branch address"
 B       report_abort_P1

 .report_adff5014
 #if compile_RO > 400
   writeS  "Serious Error Reported"
   B       report_abort_P1
 #endif

 .report_adff5015
 writeS  "Unhandled write to Page Zero"
 B       report_abort_P1

 .report_adff5016
 writeS  "Modifying hardware vectors"
 B       report_abort_P1

 .report_adff5017
 #if ARMv7_support == 1
   writeS  "LDM or STM with R13 in reg list"
   B       report_abort_P1
 #endif

 .report_adff5018
 writeS  "Only one FS/ImageFS per Module supported"
 B       report_abort_P1

 .report_adff5019
 #if ARMv7_support == 1
   writeS  "LDM/STM with Rn in reg list, writeback and ^"
   B       report_abort_P1
 #endif

 .report_adff501A
 writeS  "Reboot attempted"
 B       report_abort_P1

 .report_adff501B
 writeS  "Unable to locate stub Module address in RMA"
 B       report_abort_P1

 .report_adff501C
 writeS  "Transient stacks exhausted"
 B       report_abort_P1

 .report_adff501D
 writeS  "Codelet space exhausted"
 B       report_abort_P1

 .report_adff501E
 #if JIT_trap_pz_code == 1
   writeS  "Branch to code in Page Zero"
 #endif
 B       report_abort_P1

 .report_adff501F
 #if report_null_dereference == 1
   writeS  "Null dereference?"
 #endif
; B       report_abort_P1

 .report_abort_P1
 writeS  ""
 writeS  ""
 writeS  "R0       R1       R2       R3       R4       R5       R6       R7"
 writeS  ""

 ADR     R0, DAV_r0
 MOV     R2, #16
 .report_abort_L1
   LDR     R1, [R0], #4
   writeD  R1
   TEQ     R2, #9
   writeSEQ  ""
   SWINE   XOS_WriteI + 32
   SUBS    R2, R2, #1
 BNE     report_abort_L1

 writeS  ""
 writeS  "R8       R9       R10      R11      R12      R13      R14      PC"
 writeS  ""
 writeS  ""
 writeS  "Address   Data      Instruction"
 writeS  ""

 LDR     R6, DAV_abort
 BIC     R6, R6, #%11			;ensure it's aligned
 SUB     R3, R6, #jit_code_start
 CMP     R3, #jit_appspace_end		;in JIT appspace?
 MOVHI   R3, R6				;NO
 MOV     R4, #&A0			;amount to display
 MOV     R6, R3				;the aborting address
 SUBS    R3, R3, #&AC - step_back_DBG
 #if compile_RO == 400
   MOVMI   R3, #0
 #endif
 #if compile_RO > 400
   CMP     R3, #&FFFFFF00		;just below zero?
   MOVHI   R3, #0
;   BHI     report_abort_P3		;YES
   CMP     R3, #&FC000000		;within the OS?
   BHI     report_abort_L2		;YES
 #endif
 CMP     R3, #page_zero_Scratch_Space
 BLLO    task_page_zero_R2
 ADDLO   R3, R3, R2

 MOV     R0, R3
 ADD     R1, R0, R4			;is the address range valid?
 SWI     XOS_ValidateAddress		;PRM1-386
 BCS     report_abort_P3		;NO

 .report_abort_L2
   BL      task_page_zero_R2
   SUB     R2, R3, R2
   CMP     R2, #page_zero_Scratch_Space	;within our page zero?
   MOVLO   R5, R2			;YES
   MOVEQ   R3, #page_zero_Scratch_Space
   MOVEQ   R5, #page_zero_Scratch_Space
   MOVHI   R5, R3
   MOV     R2, #12			;size of buffer
   SUB     R13, R13, R2			;use stack for buffer
   MOV     R1, R13			;display Address
   MOV     R0, R5
   SWI     XOS_ConvertHex8		;PRM1-483
   SUB     R1, R1, R0
   SWI     XOS_WriteN			;PRM1-540

   SWI     XOS_WriteI + 32
   SWI     XOS_WriteI + 32

   LDR     R0, [R3, #0]			;display Data
   MOV     R1, R13			;use stack for buffer
   MOV     R2, #12			;size of buffer
   SWI     XOS_ConvertHex8		;PRM1-483
   SUB     R1, R1, R0
   SWI     XOS_WriteN			;PRM1-540
   ADD     R13, R13, #12		;reset stack

   SWI     XOS_WriteI + 32
   TEQ     R3, R6			;is this the aborting instruction?
   SWIEQ   XOS_WriteI + ASC("*")	;YES
   SWINE   XOS_WriteI + 32

   LDR     R0, [R3, #0]			;display Instruction
   MOV     R1, R5
   SWI     XDebugger_Disassemble	;PRM4-225

   MOV     R0, R1
   MOV     R1, R2
   SWI     XOS_WriteN
   SWI     XOS_NewLine

   ADD     R3, R3, #4
   SUBS    R4, R4, #4
 BNE     report_abort_L2

 .report_abort_P3
 writeS  ""
 writeS  "Screen: "
 LDR     R0, DA2_address
 writeD  R0
 writeS  "-"
 LDR     R1, DA2_size
 ADD     R0, R0, R1
 writeD  R0
 writeS  "  CPSR: "

 LDR     R3, DAV_CPSR			;original CPSR
 MOVS    R3, R3, LSL #1
 writeSCC "n"
 writeSCS "N"
 writeSPL "z"
 writeSMI "Z"
 MOVS    R3, R3, LSL #2
 writeSCC "c"
 writeSCS "C"
 writeSPL "v"
 writeSMI "V"
 writeS  " "
 MOVS    R3, R3, LSL #22
 writeSCC "i"
 writeSCS "I"
 writeSPL "f"
 writeSMI "F"

 BIC     R0, R3, #%111 << 29
 ADD     R0, PC, R0, LSR #23
 B       _skip_CPU_modes
 DCB " USR FIQ IRQ SVC -4- -5- -6- ABT -8- -9- -A- UND -C- -D- -E- -F-"
 ._skip_CPU_modes
 MOV     R1, #4
 SWI     XOS_WriteN
 #if compile_IOMD == 1
   TST     R3, #1 << 29
   writeSEQ  "2"
   TST     R3, #1 << 29
   writeSEQ  "6"
 #endif
 writeS  ""

 MRS     R0, CPSR
 #if compile_RO > 311 AND lock_machine_on_abort == 1
   ORR     R0, R0, #%11000000		;disable FIQ/IRQ
 #endif
 #if compile_RO > 311 AND lock_machine_on_abort == 0
   BIC     R0, R0, #%11000000		;enable FIQ/IRQ USER
 #endif
 MSR     CPSR_c, R0
 #if compile_IOMD == 1
   NOP					;fix for StrongARM errata
 #endif

#if compile_RO > 311 AND lock_machine_on_abort == 1
 ._lock_machine				;lock machine
 B       _lock_machine
#endif

 ADR     R0, _shell
 SWI     XOS_CLI
 MRS     R0, CPSR			;switch to USER
 TST     R0, #%1111
 BICNE   R0, R0, #%1111
 MSRNE   CPSR_c, R0
 #if compile_IOMD == 1
   NOP					;fix for StrongARM errata
 #endif
 B       call_OS_Exit			;exit cleanly

 ._shell DCB "Debug", 0
 ALIGN


.report_abort_JIT_vectors
 STMFD   R13!, {R14}
 MOV     R8, #max_vectors_to_track
 .report_abort_vectors_L1
   LDR     R0, [R7, #vector_table.original_code]
   TEQ     R0, #0				;is there a vector claim?
   BEQ     report_abort_vector_done		;NO

   LDR     R10, [R7, #vector_table.type]	;get the SWI used

   writeS  "OS_"
   TEQ     R10, #&1F << 12			;OS_Claim		PRM1-66
   writeSEQ "Claim       "
   TEQ     R10, #&47 << 12			;OS_AddToVector		PRM1-72
   writeSEQ "AddToVector    "
   TEQ     R10, #&4B << 12			;OS_ClaimDeviceVector	PRM1-123
   writeSEQ "ClaimDeviceVector"
   TEQ     R10, #&3B << 12			;OS_CallAfter		PRM1-441
   writeSEQ "CallAfter      "
   TEQ     R10, #&3C << 12			;OS_CallEvery		PRM1-443
   writeSEQ "CallEvery      "
   TEQ     R10, #&54 << 12			;OS_AddCallBack		PRM1-324
   writeSEQ "AddCallBack    "

   TEQ     R10, #&3B << 12			;OS_CallAfter		PRM1-441
   TEQNE   R10, #&3C << 12			;OS_CallEvery		PRM1-443
   BEQ     report_abort_vectors_parameter_done
   LDR     R0, [R7, #vector_table.parameter]	;original parameter
   writeS  " "
   writeB  R0
   .report_abort_vectors_parameter_done

   writeS  " @ "
   LDR     R1, [R7, #vector_table.original_code]
   writeD  R1
   writeS  " R12="
   LDR     R1, [R7, #vector_table.private]
   writeD  R1
   writeS  ""
   .report_abort_vector_done
   ADD     R7, R7, #vector_table.size
   SUBS    R8, R8, #1
 BNE     report_abort_vectors_L1
LDMFD   R13!, {PC}
