;Entry:
; R14		- aborting instruction address
; abort_address	- aborting address
; DAV_r0	- entry R0




;JIT_abort_handler
;-----------------
;resets addresses in JIT Application Space to the JIT trigger instruction
;and performs the write on behalf of the code
;
;Entry:
; R14 - Aborting instruction PC (do not use beyond this point as PMP will
;				corrupt R14)

.JIT_abort_handler
 LDR     R0, DAV_r0_tmp
 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}^			;YES, get User mode registers
 BEQ     _P2				; |+ and skip IRQ/FIQ/SVC code

 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			;switch back to Abort32
 #if compile_IOMD == 1
   NOP
 #endif

 ._P2
 SUB     R8, R0, #8 * 4			;R8  = register table

.JIT_abort_handler_decode
 LDR     R10, abort_address		;R10 = address being accessed
 LDR     R3, DAV_abort_tmp		;PMP may trigger abort, so can't use R14
 #if JIT_instruction_trace == 1
   LDR     R0, instruction_trace_ptr
   LDR     R1, [R0, #-4]
   ORR     R2, R3, #&A<<28
   SUB     R2, R2, #4			;correct
   ORR     R4, R10, #&B<<28
   STMIA   R1!, {R2, R4}
   BIC     R1, R1, #jit_trace_buffer_size
   STR     R1, [R0, #-4]
 #endif
 LDR     R11, branch_to_jit		;R11 = Hypercall
 #if High_Vectors == 0
   LDR     R7, branch_to_jit_no_condition	;R7 = Hypercall without condition
 #endif
 LDR     R0, [R3], #4			;R0 = the faulting instruction
 STR     R3, [R8, #15 * 4]		;our return address
 #if compile_RO == 500
   BIC     R2, R10, #%11
   PLD     [R2, #0]			;pre-load the address on 80321+
 #endif

 #if JIT_pipelining == 1
   SUB     R2, R3, #jit_code_start
   CMP     R2, #jit_appspace_end	;is it within JIT space?
   LDRLO   R1, [R3, #0]			;YES, get pipelined instruction
   LDRLO   R4, [R2, #0]			; |
   STRLO   R1, [R8, #16 * 4]		; |   store stage 2 instruction
   STRLO   R4, [R8, #17 * 4]		; |+  store original stage 2 instruction
 #endif

 ANDS    R1, R0, #%111 << 25		;SWP or LDREX/STREX on ARMv5+?
 BEQ     JIT_AbortI_SWP			;YES
 CMP     R1,     #%100 << 25		;is it STM?
 BHI     JIT_AbortI_STF			;NO, %110 : STF
 BNE     JIT_AbortI_STR			;NO, %010 / %011 : STR/LDR

._STM
 AND     R4, R0, #%1111 << 16		;R4 = register
 LDR     R1, Early_Abort_Mode		;R1 = instruction Early Abort Mode
 LDR     R3, [R8, R4, LSR #16 - 2]	;R3 = Rd value (ie address)
 MOV     R12, R3			;R12 = unaligned Abort address
 #if Unaligned_Support == 0 AND JIT_debug == 1
   ADR     R2, jit_write_aborts
 #endif
 #if Unaligned_Support == 1 AND JIT_debug == 1
   TST     R3, #%11			;unaligned?
   ADRNE   R2, jit_unaligned		;YES
   ADREQ   R2, jit_write_aborts		;NO
 #endif
 #if JIT_debug == 1
   LDR     R14, DAV_abort_tmp
   LDR     R5, [R2, #0]
   ADD     R5, R5, #1
   STMIA   R2, {R5, R10, R14}		;count, address being accessed, address of instruction
 #endif
 BIC     R3, R3, #%11			;ensure it's word aligned

; #if ARMv7_support == 1
;   TST     R0, #1 << 15			;is PC in reglist?
;   BNE     abort_with_PC		;YES
; #endif

 #if Unaligned_Support == 1
   TST     R0, #1 << 20			;LDM?
   BNE     JIT_AbortI_LDM		;YES
 #endif

 TST     R1, #%01			;is LDM/STM in Late Abort mode?
 TSTNE   R0, #1 << 21			;YES, write-back?
 BEQ     _STM_early_abort_mode		;NO

 MOV     R1, #&33			;11 instructions
 ORR     R1, R1, R1, LSL #8		;assumes R0-PC can't exist
 EOR     R2, R1, R1, LSL #1
 AND     R2, R2, R0, LSR #1
 SUB     R5, R0, R2
 AND     R2, R1, R5, LSR #2
 AND     R5, R5, R1
 ADD     R5, R5, R2
 ADD     R5, R5, R5, LSR #4
 ADD     R5, R5, R5, LSR #8
 AND     R2, R5, #%1111			;R2=<reglist> bit count

 TST     R0, #1 << 23			;Ix or Dx
 ADDEQ   R3, R3, R2, LSL #2		;Dx
 SUBNE   R3, R3, R2, LSL #2		;Ix

._STM_early_abort_mode
					;now need to perform:
					;STM/LDM<mode> R3,{<reglist>}
 MOV     R2, R4, LSR #16
 MOV     R1, #1
 TST     R0, R1, LSL R2			;is Rd in <reglist>?
 STRNE   R3, [R8, R4, LSR #16 - 2]	;YES, correct value

 MOV     R9, #0				;R9 != 0 if instruction encountered
 TST     R0, #1 << 23			;Ix or Dx
 BNE     _STM_Ix

._STM_Dx
 TST     R0, #1 << 24			;DB or DA
 SUBNE   R3, R3, #4			;DB

 MOV     R6, #15 * 4
 #if Unaligned_Support == 1
   CMP     R12, #jit_code_start		;is Abort outside of JIT space?
   BHS     _STM_Dx_Unaligned		;YES
 #endif

 MOV     R10, #jit_code_start
 MOVS    R1, R0, LSL #16
 BPL     _STM_Dx_L1_P1			;skip to 1st register
 ._STM_Dx_L1_P2
   LDR     R2, [R3, R10]		;load original value
   #if High_Vectors == 1
     TEQ     R2, R11			;did we hit an instruction?
   #endif
   #if High_Vectors == 0
     TEQ     R7, R2, LSL #4		;did we hit an instruction?
   #endif
   STRNE   R11, [R3, R10]		;YES, remove it
   MOVNE   R9, #1			; |   indicate we need to flush cache
   #if JIT_codelet_recycling == 1
     BLNE    AbortI_free_codelet_STM	; |+  free codelet if required
   #endif
   LDR     R5, [R8, R6]			;load the register
   STR     R5, [R3], #-4		;store register

   ._STM_Dx_L1_P1
     SUB     R6, R6, #4			;go to next register
     MOVS    R1, R1, LSL #1		;is it in reglist?
   BGT     _STM_Dx_L1_P1		;NO
 BMI     _STM_Dx_L1_P2			;YES

 TST     R0, #1 << 24			;DB or DA
 ADDNE   R3, R3, #4			;DB
 B       _STM_flush_cache


#if Unaligned_Support == 1
 ;Entry: R12 - Aborting address
._STM_Dx_Unaligned
 TST     R12, #%11			;is it misaligned?
 BEQ     report_abort			;NO, report a Data Abort

 MOVS    R1, R0, LSL #16
 BPL     _STM_Dx_U_L1_P1		;skip to 1st register
 ._STM_Dx_U_L1_P2
   LDR     R5, [R8, R6]			;load the register
   STR     R5, [R3], #-4		;store register

   ._STM_Dx_U_L1_P1
     SUB     R6, R6, #4			;go to next register
     MOVS    R1, R1, LSL #1		;is it in reglist?
   BGT     _STM_Dx_U_L1_P1		;NO
 BMI     _STM_Dx_U_L1_P2		;YES

 TST     R0, #1 << 24			;DB or DA
 ADDNE   R3, R3, #4			;DB
 B       _STM_flush_cache


 ;Entry: R12 - Aborting address
._STM_Ix_Unaligned
 TST     R12, #%11			;is it misaligned?
 BEQ     report_abort			;NO, report a Data Abort

 MOV     R1, R0, LSL #16
 MOVS    R1, R1, LSR #17
 ._STM_Ix_U_L1
   BCC     _STM_Ix_U_L1_P1
   ._STM_Ix_U_L1_P2
   LDR     R5, [R8, R6]			;load the register
   STR     R5, [R3], #4			;store register

   ._STM_Ix_U_L1_P1
   ADD     R6, R6, #4			;go to next register
   MOVS    R1, R1, LSR #1
 BNE     _STM_Ix_U_L1
 BCS     _STM_Ix_U_L1_P2

 TST     R0, #1 << 24			;IB or IA
 SUBNE   R3, R3, #4			;IB
 B       _STM_flush_cache
#endif



._STM_Ix
 TST     R0, #1 << 24			;IB or IA
 ADDNE   R3, R3, #4			;IB

 MOV     R6, #0
 #if Unaligned_Support == 1
   CMP     R12, #jit_code_start		;is Abort outside of JIT space?
   BHS     _STM_Ix_Unaligned		;YES
 #endif

 MOV     R10, #jit_code_start
 MOV     R1, R0, LSL #16
 MOVS    R1, R1, LSR #17
 ._STM_Ix_L1
   BCC     _STM_Ix_L1_P1
   ._STM_Ix_L1_P2
   LDR     R2, [R3, R10]		;load original value
   #if High_Vectors == 1
     TEQ     R2, R11			;did we hit an instruction?
   #endif
   #if High_Vectors == 0
     TEQ     R7, R2, LSL #4		;did we hit an instruction?
   #endif
   STRNE   R11, [R3, R10]		;YES, remove it
   MOVNE   R9, #1			; |   indicate we need to flush cache
   #if JIT_codelet_recycling == 1
     BLNE    AbortI_free_codelet_STM	; |+  free codelet if required
   #endif
   LDR     R5, [R8, R6]			;load the register
   STR     R5, [R3], #4			;store register

   ._STM_Ix_L1_P1
   ADD     R6, R6, #4			;go to next register
   MOVS    R1, R1, LSR #1
 BNE     _STM_Ix_L1
 BCS     _STM_Ix_L1_P2

 TST     R0, #1 << 24			;IB or IA
 SUBNE   R3, R3, #4			;IB

; Entry: R12 - Aborting address if Unaligned_Support == 1
._STM_flush_cache
 TST     R0, #1 << 21			;write-back?
 #if Unaligned_Support == 1
   ANDNE   R10, R12, #%11		; |   get misalignment
   ORRNE   R3, R3, R10			; |   put back into Rd
 #endif
 STRNE   R3, [R8, R4, LSR #16 - 2]	;YES

; #if ARMv7_support == 1
;   TST     R0, #1 << 15			;is PC in reglist?
;   BNE     abort_with_PC		;YES
; #endif

 TEQ     R9, #0				;did we hit an instruction?
 BEQ     JIT_AbortI_decoded		;NO

 #if JIT_pipelining == 1
   LDR     R1, [R8, #15 * 4]		;load PC
   SUB     R2, R1, #jit_code_start
   CMP     R2, #jit_appspace_end	;is it within JIT space?
   BHI     _STM_skip_pipeline
   LDR     R2, [R1]			;get pipelined instruction
   LDR     R4, [R8, #16 * 4]		;retrieve pipeline
   TEQ     R4, R2			;was it changed?
   STRNE   R4, [R1]			;YES, replace it
   ._STM_skip_pipeline
 #endif

 #if JIT_debug == 1
   TEQ     R3, R12			;did we hit the next cache line?
   ADR     R4, jit_cache_flushes
   LDR     R5, [R4]
   ADDEQ   R5, R5, #1			;one cache line flushed
   ADDNE   R5, R5, #2			;two cache lines flushed
   BIC     R5, R5, #%100000
   STR     R5, [R4]
 #endif

 #if compile_IOMD == 1
   LDR     R4, cpu_id
   CMP     R4, #CPUID_StrongARM		;below StrongARM?
   BLO     JIT_AbortI_decoded		;YES, cache flush not required
 #endif
 TST     R0, #1 << 23			;NE=Ix or EQ=Dx
 LDR     R4, L1_CACHE_LINE_MASK		;get cache alignment
 ADDNE   R3, R3, #jit_code_start	;R3=end address, R12=start address
 ADDNE   R0, R12, #jit_code_start	;R0=start
 ADDEQ   R12, R12, #jit_code_start
 ADDEQ   R0, R3, #jit_code_start
 ADD     R5, R4, #1			;convert to CACHE_LINE_SIZE
 BIC     R0, R0, R4			;R0=cache aligned start address
 ADDNE   R1, R3, R5			;ensure at least one cache line
 ADDEQ   R1, R12, R5
 BIC     R1, R1, R4			;R1=cache aligned end address
 ADR     R14, JIT_AbortI_decoded
 LDR     PC, MMUControl_ARMop8		;IMB range





;abort_with_PC
;-------------
;an abort occured in LDM or STM with PC in the reg list

;#if ARMv7_support == 1
;.abort_with_PC
; MOV     R12, #7			;ADFF5007
;B       report_unimplemented		;report issue
;#endif




#if Unaligned_Support == 1
;JIT_AbortI_LDM
;--------------
;Entry:
; R12 - aborting address

.JIT_AbortI_LDM
 TST     R1, #%01			;is LDM/STM in Late Abort mode?
 TSTNE   R0, #1 << 21			;YES, write-back?
 BEQ     _LDM_decoded			;NO

 MOV     R1, #&33			;11 instructions
 ORR     R1, R1, R1, LSL #8		;assumes R0-PC can't exist
 EOR     R2, R1, R1, LSL #1
 AND     R2, R2, R0, LSR #1
 SUB     R5, R0, R2
 AND     R2, R1, R5, LSR #2
 AND     R5, R5, R1
 ADD     R5, R5, R2
 ADD     R5, R5, R5, LSR #4
 ADD     R5, R5, R5, LSR #8
 AND     R2, R5, #%1111			;R2=<reglist> bit count

 TST     R0, #1 << 23			;Ix or Dx
 ADDEQ   R3, R3, R2, LSL #2		;Dx
 SUBNE   R3, R3, R2, LSL #2		;Ix

._LDM_decoded
					;now need to perform:
					;LDM<mode> R3,{<reglist>}
 TST     R0, #1 << 23			;Ix or Dx
 BNE     _LDM_Ix

._LDM_Dx
 TST     R0, #1 << 24			;DB or DA
 SUBNE   R3, R3, #4			;DB

 MOV     R6, #15 * 4
 MOVS    R1, R0, LSL #16
 ._LDM_Dx_L1
   LDRMI   R2, [R3], #-4		;load value
   STRMI   R2, [R8, R6]			;store in register
   SUB     R6, R6, #4			;go to next register
   MOVS    R1, R1, LSL #1
 BNE     _LDM_Dx_L1

 TST     R0, #1 << 24			;DB or DA
 ADDNE   R3, R3, #4			;DB
 TST     R0, #1 << 21			;write-back?
 ANDNE   R12, R12, #%11			;YES, get misalignment
 ORRNE   R3, R3, R12			; |   put back into Rd
 STRNE   R3, [R8, R4, LSR #16 - 2]	; |+  update register

; #if Unaligned_Support == 1 AND ARMv7_support == 1
;   TST     R0, #1 << 15			;is PC in reglist?
;   BNE     abort_with_PC		;YES
; #endif
 B       JIT_AbortI_decoded


._LDM_Ix
 TST     R0, #1 << 24			;IB or IA
 ADDNE   R3, R3, #4			;IB

 MOV     R6, #0
 MOV     R1, R0, LSL #16
 MOVS    R1, R1, LSR #17
 ._LDM_Ix_L1
   LDRCS   R2, [R3], #4			;load value
   STRCS   R2, [R8, R6]			;store in register
   ADD     R6, R6, #4			;go to next register
   MOVS    R1, R1, LSR #1
 BNE     _LDM_Ix_L1
 BCS     _LDM_Ix_L1

 TST     R0, #1 << 24			;IB or IA
 SUBNE   R3, R3, #4			;IB
 TST     R0, #1 << 21			;write-back?
 ANDNE   R12, R12, #%11			;YES, get misalignment
 ORRNE   R3, R3, R12			; |   put back into Rd
 STRNE   R3, [R8, R4, LSR #16 - 2]	; |+  update register

; #if Unaligned_Support == 1 AND ARMv7_support == 1
;   TST     R0, #1 << 15			;is PC in reglist?
;   BNE     abort_with_PC		;YES
; #endif
B       JIT_AbortI_decoded
#endif




; Entry:
;  R10 - Aborting address
;  R11 - Hypercall instruction
;  R3  - Aborting instruction address
;  R0  - Aborting instruction

.JIT_AbortI_STR			;ARM710VE-36
 AND     R2, R0, #%1111 << 12		;R2 = Rd
 #if Unaligned_Support == 1
   #if Unaligned_Support == 1 AND JIT_debug == 1
     SUB     R14, R3, #4
     TST     R0, #1 << 22		;word?
     ADRNE   R4, jit_write_aborts	;NO, byte
     BNE     _P1			;NO
     TST     R10, #%11			;unaligned word?
     ADRNE   R4, jit_unaligned		;YES
     ADREQ   R4, jit_write_aborts	;NO
     ._P1
     LDR     R1, [R4]
     ADD     R1, R1, #1
     STMIA   R4, {R1, R10, R14}
   #endif
   TST     R0, #1 << 20			;LDR?
   BNE     JIT_AbortI_LDR		;YES
 #endif
 #if Unaligned_Support == 0 AND JIT_debug == 1
   SUB     R14, R3, #3
   ADR     R4, jit_write_aborts
   LDR     R1, [R4]
   ADD     R1, R1, #1
   STMIA   R4, {R1, R10, R14}
 #endif

 TST     R0, #1 << 22			;word or byte?
 LDREQ   R1, [R8, R2, LSR #12 - 2]	;word, load value being written
 #if Unaligned_Support == 1
   BICEQ   R10, R10, #%11		;ensure it's aligned
 #endif
 LDRNEB  R1, [R8, R2, LSR #12 - 2]	;bytes, load value being written
;@@@ this needs to validate R10 before reading
 #if compile_IOMD == 0			;errata fails on ARM7 macrocell
   LDREQ   R12, [R10, #0]
   LDRNEB  R12, [R10, #0]
   SUBS    R9, R12, R1			;has the value changed? R9=0 if not
   BEQ     JIT_AbortI_STR_memory_unchanged	;NO, don't write to memory

   TST     R0, #1 << 22			;word or byte?
 #endif
 #if compile_IOMD == 1
   MOV     R9, #1			;assume we need a cache flush
 #endif

 STREQ   R1, [R10, #0]			;proxy the write
 STRNEB  R1, [R10, #0]
.JIT_AbortI_STR_memory_unchanged
					;--------- Now correct Rn ----------
                 ;%IPUBW
 AND     R1, R0, #%01001 << 21
 TEQ     R1,     #%01000 << 21		;LDR/STR Rd, [Rn, xx] ?
 BEQ     JIT_AbortI_STR_SWP_decoded	;YES

 LDR     R1, Early_Abort_Mode		;R1 = instruction Early Abort Mode
 TST     R1, #%10			;is STR in Late Abort mode?
 BNE     JIT_AbortI_STR_SWP_decoded	;YES
					;NO: LDR/STR Rd, [Rn, xx]!
					;OR: LDR/STR Rd, [Rn], xx

				;Reference: ARM710VE-36
 AND     R1, R0, #%1111 << 16		;R1 = Rn
 LDR     R12, [R8, R1, LSR #16 - 2]	;R12 = value of Rn
 TST     R0, #1 << 25			;:STR Rd, [Rn, #{+/-}<immed_12>] ?
 BNE     _xTR_shift			;NO: STR Rd, [Rn, {+/-}Rm{,<shift>}]!

				;:STR Rd, [Rn], #{+/-}<immed_12>
				;:STR Rd, [Rn, #{+/-}<immed_12>]!
 MOV     R4, R0, LSL #31 - 11		;R4 = offset in bits 31..20
 TST     R0, #1 << 23			;U (Up / Down)
 SUBEQ   R12, R12, R4, LSR #31 - 11	;:STR Rd, [Rn, #-<immed_12>]!
 ADDNE   R12, R12, R4, LSR #31 - 11	;:STR Rd, [Rn, #+<immed_12>]!
 STR     R12, [R8, R1, LSR #16 - 2]	;store it back
 B       JIT_AbortI_STR_SWP_decoded
				;Reference: ARM710VE-25
				;NOTE: STR Rd, [Rn, {+/-}Rm, <shift_type> Rx]!
				;     is not a valid instruction
				;:STR Rd, [Rn], {+/-}Rm {, <shift> #<immed_5>}
 ._xTR_shift			;:STR Rd, [Rn, {+/-}Rm {, <shift> #<immed_5>}]!
 AND     R5, R0, #%1111			;R5 = Rm
 LDR     R2, [R8, R5, LSL #2]		;R2 = value of Rm
 AND     R6, R0, #%11111 << 7
 MOV     R6, R6, LSR #7			;R6 = #<immed_5>

 ANDS    R3, R0, #%11 << 5		;R3 = shift type
 MOVEQ   R4, R2, LSL R6			;R4=Rm, LSL #<immed_5>
 BEQ     _xTR_shift_decoded
 CMP     R3, #%10 << 5
 MOVLT   R4, R2, LSR R6			;R4=Rm, LSR #<immed_5>
 MOVEQ   R4, R2, ASR R6			;R4=Rm, ASR #<immed_5>
 BLS     _xTR_shift_decoded
				;Reference: ARM710VE-25
				;:STR Rd, [Rn, {+/-}Rm, ROR #<immed_5>/RRX]!
 TST     R0, #%11111 << 7		;is it RRX?
 MOVNE   R4, R2, ROR R6			;NO, Rm, ROR #n
 BNE     _xTR_shift_decoded
				;:STR Rd, [Rn, {+/-}Rm, RRX]!
 MRS     R4, SPSR			;get CPSR
 MOVS    R4, R4, LSL #3			; |  shift carry into C
 MOV     R4, R2, RRX			; |+ Rm, RRX

 ._xTR_shift_decoded
 TST     R0, #1 << 23			;U (Up / Down)
 ADDNE   R12, R12, R4			;Rm, <shift> #<immed_5>
 SUBEQ   R12, R12, R4			;-Rm, <shift> #<immed_5>
 STR     R12, [R8, R1, LSR #16 - 2]	;store it back

 ;Entry:
 ; R9 - 0 if memory value hasn't changed

.JIT_AbortI_STR_SWP_decoded
 TEQ     R9, #0				;did the value change?
 BEQ     JIT_AbortI_decoded		;NO, exit

 #if Unaligned_Support == 1
   CMP     R10, #jit_appspace_end	;did the abort occur in appspace?
   BHI     JIT_AbortI_decoded		;NO, exit
 #endif

 BIC     R12, R10, #%11			;ensure it's word aligned
 ADD     R12, R12, #jit_code_start
 LDR     R2, [R12, #0]			;get the address we're overwriting
   #if High_Vectors == 1
     TEQ     R2, R11			;did we hit an instruction?
   #endif
   #if High_Vectors == 0
     TEQ     R7, R2, LSL #4		;did we hit an instruction?
   #endif
 BEQ     JIT_AbortI_decoded		;NO

 #if JIT_codelet_recycling == 1
   AND     R14, R2, #%1110 << 24	;%1010 = B   %1011 = BL
   TEQ     R14, #%1010 << 24		;is it B / BL <address>
   BLEQ    AbortI_free_codelet_R12	;YES, free codelet if required
 #endif

 #if JIT_pipelining == 1
   LDR     R1, [R8, #15 * 4]		;load PC
   TEQ     R1, R12			;are we about to overwrite pipeline?
   BEQ     JIT_AbortI_decoded		;YES, leave it
 #endif

 #if compile_IOMD == 1
   LDR     R1, cpu_id
   STR     R11, [R12]			;store JIT entry instruction
   CMP     R1, #CPUID_StrongARM		;below StrongARM?
   BLO     JIT_AbortI_decoded		;YES, cache flush not required
 #endif

 #if JIT_debug == 1
   ADR     R3, jit_cache_flushes
   LDR     R4, [R3]
   ADD     R4, R4, #1
   BIC     R4, R4, #%100000
   STR     R4, [R3]
 #endif

 LDR     R1, L1_CACHE_LINE_MASK		;get cache alignment
 #if compile_IOMD == 0
   STR     R11, [R12]			;store JIT entry instruction
 #endif
 BIC     R0, R12, R1			;R0=cache aligned start address
 ADD     R1, R1, #1			;convert to CACHE_LINE_SIZE
 ADD     R1, R0, R1			;R1=cache aligned end address
 ADR     R14, JIT_AbortI_decoded
 LDR     PC, MMUControl_ARMop8		;IMB range




.JIT_AbortI_decoded
 MOV     R0, #0
 STR     R0, DAV_ABT_R14		;allow abort entries

 LDR     R1, DAV_CPSR
 LDR     R14, [R8, #15*4]
 MSR     SPSR_all, R1
 TST     R1, #%1111			;was abort cause in user mode?
 LDMEQIA R8, {R0-R14}^			;YES
 #if compile_IOMD == 1
   NOP
 #endif
 MOVEQS  PC, R14

 MOV     R0, R8				;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, #%11010111		;Abort32 IRQ/FIQ disabled
 #if compile_IOMD == 1
   NOP
 #endif
MOVS    PC, R14




#if Unaligned_Support == 1
; Entry:
;  R3  - Aborting instruction address
;  R10 - Aborting address
;  R11 - Hypercall instruction

.JIT_AbortI_LDR				;R10=address R2=Rd
					;********************************
;					;check for LDR inside LDM codelet which
;					;occurs in Pocket Money demo
 MOV     R4, #jit_appspace_end
 CMP     R4, R3
 CMPLO   R3, #jit_code_start		;is the abort within a codelet?
 BHI     _not_a_codelet
 BIC     R4, R3, #codelet_alignment - 1	;find codelet header
 LDR     R3, [R4, #-codelet_struct.codelet+codelet_struct.validation]
 EORS    R3, R3, #CODELET_validation	;did we find the header?
 BNE     _not_a_codelet			;NO
					;check for STM codelet
 LDR     R3, [R4, #-codelet_struct.codelet+codelet_struct.instruction]	;get original instruction
 AND     R3, R3, #%11100001 << 20
 TEQ     R3,     #%10000001 << 20	;LDM?
 BICEQ   R10, R10, #%11			;YES, unaligned LDR in LDM codelet
 ._not_a_codelet
					;********************************
 ANDS    R3, R10, #%11			;R3=misalignment
; #if Unaligned_Support == 1 AND JIT_debug == 1
;   BEQ     report_abort			;report a Data Abort if aligned
; #endif

 BIC     R4, R10, #%11			;R4=aligned address
 MOVS    R12, R3, LSL #3		;R12=ROR to match ARM3 behaviour
 LDR     R1, [R4, #0]			;load the value
 MOV     R9, #0				;no write performed
 MOVNE   R1, R1, ROR R12		;rotate it
 STR     R1, [R8, R2, LSR #12 - 2]	;store in register
B       JIT_AbortI_STR_memory_unchanged
#endif




;Entry:
;  R10 - Aborting address
;  R11 - Hypercall instruction
;  R3  - Aborting instruction address
;  R0  - Aborting instruction

.JIT_AbortI_SWP				;SWP Rd, Rm, [Rn] or LDR/STREX
 #if JIT_debug == 1
   ADR     R2, jit_write_aborts
   SUB     R14, R3, #4
   LDR     R1, [R2]
   ADD     R1, R1, #1
   STMIA   R2, {R1, R10, R14}
 #endif
 AND     R2, R0, #%1111			;R2 = Rm
 AND     R3, R0, #%1111 << 12		;R3 = Rd

 #if compile_RO == 500
   TST     R0, #1 << 21			;LDREX{H/D}/STREX{H/D}?
   BNE     JIT_Abort_report		;YES, ADFF5009

   AND     R4, R0, #%1111 << 8
   TEQ     R4,     #%1111 << 8		;is it LDREX or STREX?
   BNE     _keep			;NO

   AND     R4, R0, #%1111
   TEQ     R4,     #%1111		;is it LDREX?
   BEQ     JIT_AbortI_LDREX		;YES
					;NO, STREX
;.JIT_AbortI_STREX
   TST     R0, #1 << 22			;is it STREXB?
   MOV     R1, #0			;STREX succeeded
   LDRNEB  R4, [R8, R2, LSL #2]		;load value to store at [Rm]
   LDREQ   R4, [R8, R2, LSL #2]		;load value to store at [Rm]
   STR     R1, [R8, R3, LSR #12 - 2]	;Rd = 0
   STREQ   R4, [R10, #0]		;store Rm at [Rn]
   STRNEB  R4, [R10, #0]		;store Rm at [Rn]
   MOV     R9, #1			;indicate we need to flush cache
   B       JIT_AbortI_STR_SWP_decoded

   ._keep
 #endif

 #if Unaligned_Support == 1 AND JIT_debug == 1
   TST     R0, #1 << 22			;word?
   BNE     _P1				;NO
   TST     R10, #%11			;unaligned word?
   ADRNE   R4, jit_unaligned		;YES
   LDRNE   R1, [R4]
   ADDNE   R1, R1, #1
   STMNEIA R4, {R1, R10, R14}
   ._P1
 #endif
 TST     R0, #1 << 22			;is it SWPB?
 #if Unaligned_Support == 1
   BICEQ   R10, R10, #%11		;NO, ensure it's aligned
 #endif
 LDRNEB  R1, [R10, #0]
 LDREQ   R1, [R10, #0]			;load Rn value
 LDRNEB  R4, [R8, R2, LSL #2]		;load value to store at [Rm]
 LDREQ   R4, [R8, R2, LSL #2]		;load value to store at [Rm]
 SUBS    R9, R1, R4			;has the value changed?
 BEQ     JIT_AbortI_STR_SWP_decoded	;NO

 TST     R0, #1 << 22			;is it SWPB?
 STR     R1, [R8, R3, LSR #12 - 2]	;Rd = [Rn]
 STREQ   R4, [R10, #0]			;store Rm at [Rn]
 STRNEB  R4, [R10, #0]			;store Rm at [Rn]
 B       JIT_AbortI_STR_SWP_decoded




#if compile_RO == 500
.JIT_AbortI_LDREX			;fall-thru to report
#endif


.JIT_AbortI_STF				;fall-thru to report


.JIT_Abort_report
 MOV     R12, #9
B       report_unimplemented_PC_plus_4	;YET TO BE CODED




#if JIT_codelet_recycling == 1
;AbortI_free_codelet_STM
;-----------------------
;free codelet if required
;
;Entry:
; R2       = instruction (B <address>)
; R3       = original instruction address
; R10      = jit_code_start
; R3 + R10 = instruction address in JIT appspace
;
;Exit:
; R2, R5 - corrupted

 ALIGN   32, 4
.AbortI_free_codelet_STM
 AND     R5, R2, #%1110 << 24		;%1010 = B   %1011 = BL
 TEQ     R5, #%1010 << 24		;is it B/BL <address>
 MOVNE   PC, R14			;NO, exit
 MOV     R2, R2, LSL #8
 ADDS    R2, R3, R2, ASR #6		;in codelet space?
 MOVPL   PC, R14			;NO

 ADD     R2, R2, R10			;R2=codelet_struct.codelet - 8
 #if JIT_codelet_recycling == 1 AND JIT_codelet_reuse == 0
   LDR     R5, [R2, #codelet_struct.source - codelet_struct.codelet + 8]
   SUB     R5, R5, R3			;is it definately the right codelet?
   TEQ     R5, #8			;..accounting for pipeline
   MOVNE   PC, R14			;NO
 #endif
 #if JIT_codelet_recycling == 1 AND JIT_codelet_reuse == 1
   LDR     R5, [R2, #codelet_struct.validation - codelet_struct.codelet + 8]
   EORS    R5, R5, #CODELET_validation
   MOVNE   PC, R14
 #endif
B       free_codelet			;YES, free the codelet




;AbortI_free_codelet_R12
;-----------------------
;free codelet if required
;
;Entry:
; R2  = instruction (B <addess>)
; R10 = source address
; R12 = instruction address in JIT space
;
;Exit:
; R2, R5 - corrupted

 ALIGN   32, 4
.AbortI_free_codelet_R12
 MOV     R2, R2, LSL #8
 ADD     R2, R12, R2, ASR #6		;R2=codelet_struct.codelet - 8

 SUB     R5, R2, #jit_appspace_end
 CMP     R5, #jit_code_start - lastfree_codelet	;in codelet space?
 MOVHS   PC, R14			;NO
 #if JIT_codelet_recycling == 1 AND JIT_codelet_reuse == 0
   LDR     R5, [R2, #codelet_struct.source - codelet_struct.codelet + 8]
   SUB     R5, R5, R10			;is it definately the right codelet?
   TEQ     R5, #8			;..accounting for pipeline
   MOVNE   PC, R14			;NO
 #endif
 #if JIT_codelet_recycling == 1 AND JIT_codelet_reuse == 1
   LDR     R5, [R2, #codelet_struct.validation - codelet_struct.codelet + 8]
   EORS    R5, R5, #CODELET_validation
   MOVNE   PC, R14
 #endif
B       free_codelet			;YES, free the codelet
#endif
