

;Exit:
;R0-R6  - corrupt

.JIT_ARMv4_consistency
 MOV     R2, #&8000
 LDR     R3, pre_JIT_wimp_slot_size
B       JIT_ARMv4_check




;Exit:
;R0-R6  - corrupt

.JIT_ARMv4_consistency_RMA
 MOV     R2, #jit_RMA_heap
 MOV     R3, #jit_RMA_size
;B       JIT_ARMv4_check




;JIT_ARMv4_check
;---------------
;checks the consistency of the JIT cache against main memory
;called on entry to the JIT when running in ARMv4 mode under Debug mode

;Entry:
;R2 - start address (main memory)
;R3 - size of block to check
;
;Exit:
;R0-R6  - corrupt
;R7-R12 - preserved

.JIT_ARMv4_check
 STMFD   R13!, {R8-R10, R14}
 LDR     R6, branch_to_jit
 LDR     R9, branch_to_jit_no_condition
 ADD     R2, R2, #jit_code_start	;R2=JIT address to check
 SUB     R2, R2, #4			;we're one instruction ahead

 LDR     R8, JIT_inconsistent
 ADD     R3, R3, #4			;R3=end of JIT space to check
 MOV     R4, #jit_code_start
 ._L1
   SUBS    R3, R3, #4			;hit the end?
   LDMLSFD R13!, {R8-R10, PC}		;YES, exit

   LDR     R0, [R2, #4]!		;get the JIT instruction
   TEQ     R9, R0, LSL #4		;is it a JIT entry?
   TEQNE   R0, R8			;is it an inconsistency call?
   BEQ     _L1				;YES, skip

   AND     R5, R0, #%1111 << 24		;R5 = JIT instruction type
   TEQ     R5, #%1010 << 24		;%1010 = B
   BEQ     _B
   TEQ     R5, #%1011 << 24		;%1011 = BL
   BEQ     _BL

._check_match				;check original=JIT instruction
   LDR     R1, [R2, -R4]		;get original instruction
   AND     R5, R1, #OP_condition
   TEQ     R5, #%1111 << 28		;NV?
   BEQ     _NV				;YES

   AND     R5, R1, #%1111 << 24
   ADD     PC, PC, R5, LSR #24 - 2
   NOP
   B       _check_match2		;0000 ALU / MUL
   B       _ALU				;0001 ALU / SWP
   B       _check_match2		;0010 ALU
   B       _ALU				;0011 ALU
   B       _LDR_STR			;0100 LDR / STR
   B       _LDR_STR			;0101 LDR / STR
   B       _LDR_STR			;0110 LDR / STR / Undefined
   B       _LDR_STR			;0111 LDR / STR / Undefined
   B       _LDM_STM			;1000 LDM / STM
   B       _LDM_STM			;1001 LDM / STM
   B       _check_match2		;1010 B
   B       _check_match2		;1011 BL
   B       _check_match2		;1100 Co-pro data transfer
   B       _check_match2		;1101 Co-pro data transfer
   B       _check_match2		;1110 Co-pro
; B       i_SWI				;1111 SWI

._SWI
;; **** THIS SHOULD BE REMOVED ONCE JITMEMORYA IS HANDLED ****
;   MOV     R5, R1, LSL #16
;   TEQ     R5, #&16 << 16		;is it OS_EnterOS?
;   MOVEQ   R0, R1			;YES, assume we changed it
;; ************************************************************

   AND     R1, R1, #%1111 << 24		;SWI, just check for an SWI
   AND     R0, R0, #%1111 << 24

._check_match2			;R0=JIT instruction   R1=original
   TEQ     R0, R1			;do they match?
   BEQ     _L1				;YES
   
._inconsistent
   LDR     R0, JIT_fixups		;check fixups
   TEQ     R0, #0			;are there any fixups to action?
   BEQ     _no_fixups			;NO, skip

   ADD     R2, R2, #8			;need to account for the pipeline
   SUB     R2, R2, #jit_code_start
   SUB     R14, R0, #jit_fixup_table.size - 4
   MOV     R0, #jit_max_fixups
   ._fixup_L1
     ADD     R14, R14, #jit_fixup_table.size
     LDR     R10, [R14, #jit_fixup_table.address]
     TEQ     R10, #0			;entry exist?
     BEQ     _no_fixup			;NO
;     TST     R10, #jit_fixup_live_flag	;have we dealt with it?
;     BNE     _no_fixup			;NO, ignore

     BIC     R10, R10, #%11		;clear flags
     TEQ     R10, R2			;does the address match?
;     LDREQ   R10, [R14, #jit_fixup_table.original]	;YES,
;     TEQEQ   R10, R1			;  |  does the instruction match
     BEQ     _match			;  |+ YES

     ._no_fixup
     SUBS    R0, R0, #1			;any fixups left?
   BNE     _fixup_L1			;YES

   SUB     R2, R2, #8			;correct the address
   ADD     R2, R2, #jit_code_start
   ._no_fixups
   STR     R8, [R2]			;JIT instruction now triggers
 B       _L1				;an inconsistency error


 ._match
 SUB     R2, R2, #8			;correct the address
 ADD     R2, R2, #jit_code_start
 B       _L1




._B
 MOVS    R1, R0, LSL #8
 BEQ     _MOV_PC_PC			;B PC might be MOV PC,PC
 ADD     R1, R2, R1, ASR #6		;in codelet space?
 SUB     R5, R1, #jit_appspace_end
 CMP     R5, #jit_code_start - lastfree_codelet	;in codelet space?
 BHS     _check_match			;NO

#if JIT_codelet_reuse == 0 AND JIT_cache_consistency == 1
 B       _L1				;can't check codelet
#endif
#if JIT_codelet_reuse == 1 AND JIT_cache_consistency == 1
 LDR     R0, [R1, #-(codelet_struct.codelet - codelet_struct.original - 8)]
 LDR     R1, [R2, -R4]			;get original instruction
 MOV     R0, R0, LSL #4			;need to drop the condition
 MOV     R1, R1, LSL #4
 B       _check_match2
#endif

._MOV_PC_PC
 LDR     R1, [R2, -R4]			;get original instruction
 LDR     R5, _MOV_PC_PC_instruction
 MOV     R5, R5, LSL #8
 TEQ     R5, R1, LSL #8			;was it MOV PC,PC
 BEQ     _L1				;YES, it matches then
 B       _check_match2			;NO

 ._MOV_PC_PC_instruction MOV PC,PC

._BL
 MOV     R1, R0, LSL #8
 ADD     R1, R2, R1, ASR #6		;in codelet space?
 SUB     R5, R1, #jit_appspace_end
 CMP     R5, #jit_code_start - lastfree_codelet	;in codelet space?
 BHS     _check_match			;NO

#if JIT_codelet_reuse == 0 AND JIT_cache_consistency == 1
 B       _L1				;can't check codelet
#endif
#if JIT_codelet_reuse == 1 AND JIT_cache_consistency == 1
 LDR     R0, [R1, #-(codelet_struct.codelet - codelet_struct.instruction - 8)]
 LDR     R1, [R2, -R4]			;get original instruction
					;work out actual address
 MOV     R1, R1, LSL #8			;R1=PC relative offset in top bits
 ADD     R1, R2, R1, ASR #6		;R1=BL destination address in JIT space
 SUB     R1, R1, #jit_code_start	;R1=actual address
 ADD     R1, R1, #8			;correct for pipeline
 MOV     R1, R1, LSR #2
 ORR     R1, R1, #&EB << 24		;R1=BL <absolute address>

 MOV     R0, R0, LSL #4			;need to drop the condition
 MOV     R1, R1, LSL #4
 B       _check_match2
#endif


;R0 - JIT instruction
;R1 - original instruction
;R2 - JIT instruction address
;R3 - preserved
;R4 - jit_code_start
;R5 - CORRUPTED
;R6 - branch_to_jit instruction

._LDM_STM
; LDR     R5, _LDMIA_R13_PC		;: LDMIA R13!,{PC}?
; TEQ     R1, R5
; LDREQ   R1, _LDR_PC_R13_4		;YES, change to: LDR PC,[R13],#4
; BEQ     _check_match2
; LDR     R5, _STMDB_R13_R14		;: STMDB R13!,{R14}?
; TEQ     R1, R5
; LDREQ   R1, _STR_R14_R13_4		;YES, change to: STR R14,[R13,#-4]!
; BEQ     _check_match2

 AND     R5, R1, #%1111 << 16
 MOV     R5, R5, LSR #16		;R5=Rn
 MOV     R14, #1
 TST     R1, R14, LSL R5		;is Rn in the reglist?
 BEQ     _check_match2			;NO

 TST     R1, #1 << 20			;LDM?
 BICNE   R1, R1, #1 << 21		;YES, clear writeback
 B       _check_match2


._NV
 TEQ     R0, #%1101 << 21		;is it a NOP?
 BEQ     _L1				;YES
 B       _inconsistent


._ALU
 AND     R5, R1, #%1111 << 21
 TEQ     R5,     #%1000 << 21		;TST
 TEQNE   R5,     #%1001 << 21		;TEQ
 TEQNE   R5,     #%1010 << 21		;CMP
 TEQNE   R5,     #%1011 << 21		;CMN
 BNE     _check_match2			;NO

 AND     R5, R1, #%1111 << 12		;R3=Rd=F if TEQP etc
 TEQ     R5,     #%1111 << 12		;TSTP etc?
 BEQ     _check_match2			;YES

 BIC     R1, R1, #%1111 << 12		;clear Rd (fixes Cannon Fodder)

 TST     R1, #1 << 20			;is S bit set?
 MOVEQ   R1, #%1101 << 21		;NO, MRS Rd, {C/S}PSR
B       _check_match2

; ._LDMIA_R13_PC		LDMIA   R13!, {PC}
; ._LDR_PC_R13_4		LDR     PC, [R13], #4
; ._STMDB_R13_R14	STMDB   R13!, {R14}
; ._STR_R14_R13_4	STR     R14, [R13, #-4]!


._LDR_STR
 AND     R5, R1, #%1111 << 12		;R5=Rd
 AND     R14, R1, #%1111 << 16		;R14=Rn
 TEQ     R5, R14, LSR #4		;does Rd=Rn?
 BNE     _check_match2			;NO

 TST     R0, #1 << 20			;LDR?
 BEQ     _STR				;NO
 
 TST     R1, #1 << 24			;post-indexed eg: LDR R0,[R0],<op2>
 BICNE   R1, R1, #1 << 21		;pre-indexed eg: LDR R0,[R0,<op2>]{!}
					;ensure it's not doing writeback
 BNE     _check_match2

 TST     R1, #1 << 25			;YES, is it an immediate?
 MOVEQS  R5, R1, LSL #32 - 12		; |+ YES, does the immediate = 0
 ORREQ   R1, R1, #1 << 24		;     |+ YES, change to pre-indexing

 ORR     R1, R1, #1 << 24		;change to pre-indexing
 BIC     R1, R1, #1 << 25		;change to immediate
 MOV     R1, R1, LSR #12
 MOV     R1, R1, LSL #12		;change to LDR R1,[R1,#0]
B       _check_match2


._STR
 AND     R5, R1, #%1001 << 21		;P__W
 CMP     R5, #%1000 << 21
 BEQ     _check_match2

; TST     R1, #1 << 25			;is Op2 a register?
; BNE     _check_match2			;YES, needs a codelet
 MOVS    R5, R1, LSL #32 - 11		;is it STR Rd,[Rn],#0 ?
 ORREQ   R1, R1, #1 << 24		;YES, ensure pre-indexed
 BICEQ   R1, R1, #1 << 21		; |+  ensure no writeback
B       _check_match2



.JIT_cache_inconsistent
 LDMFD   R13!, {R0-R1}			;clear the stack
 STMFD   R13!, {R0-R7, R14}		;[R13, #UND_exit_PC] = R14
 ADD     R14, R14, #8
 MOV     R1, #&A			;ADFF500A
B       JIT_report_unimplemented_debug
