;Entry:
;R0  = instruction
;R7  = original instruction address + 8
;R14 = re-interpreted instruction address + 8

;Check for CP15 Co-pro instructions

ALIGN   32, 4
.i_copro
 AND     R1, R0, #%1111 << 8		;R1=CPx
 TEQ     R1, #1 << 8			;FPU?
 BEQ     _i_fpu

 TEQ     R1, #15 << 8			;CP15?
 BNE     i_copy_instruction		;NO


 TST     R0, #1 << 20			;MCR?
 BEQ     _nop				;YES, NOP it

 AND     R2, R0, #%1111 << 16		;ARM register #
 ADD     PC, PC, R2, LSR #16-2
 NOP
 B       _arm_id			;C0
 B       _ARM710_cache_check		;C1
 B       _cache_op			;C2
 B       _C345_codelet			;C3
 B       _C345_codelet			;C4
 B       _C345_codelet			;C5
 B       _nop				;C6
 B       _nop				;C7
 B       _nop				;C8
 B       _nop				;C9
 B       _nop				;C10
 B       _nop				;C11
 B       _nop				;C12
 B       _nop				;C13
 B       _nop				;C14
					;C15
 ._nop
 MOV     R0, #&1A << 20			;YES, NOP it
B       i_copy_instruction


._arm_id				;MRC CP15,0,Rx,C0,C?
 LDR     R2, emulate_RISCOS
 CMP     R2, #&310 << 8			;below RO3.10?
 BLO     _undefined			;YES, assume ARM2
 CMP     R2, #&350 << 8			;below RO3.50?
 LDR     R3, _C0_codelet_ARM710
 LDRLO   R3, _C0_codelet_ARM3
 LDRB    R2, JIT_ARM4
 TEQ     R2, #1
 LDREQ   R3, _C0_codelet_SA
 ._P1
 AND     R2, R0, #%1111 << 12		;Rd
 AND     R0, R0, #OP_condition		;condition
 ORR     R2, R2, R0

 ORR     R0, R3, R2			;MOV Rd, ...
B       i_copy_instruction


 ._C0_codelet_ARM3
   MOVEQ   R0, #&300			;ARM3 ID (should be &41560300)
 ._C0_codelet_ARM710
   MOVEQ   R0, #&7100			;ARM710 ID (should be &41??7100)
 ._C0_codelet_SA
   MOVEQ   R0, #&A000			;SA ID (should be &4401A100)


._ARM710_cache_check			;MRC CP15,0,Rx,C1,C?
 LDR     R2, emulate_RISCOS
 CMP     R2, #&350 << 8			;ARM2/3?
 BLO     _undefined			;YES
 LDR     R3, _C1_codelet_ARM710
 B       _P1


 ._C1_codelet_ARM710
   MOVEQ   R0, #%100			;CACHE ON (ARM710 TRM p69)

					;used by Wolf3D @ 19E94
					;used by K.V.   @ RMA +1B10
					;used by Burn'Out SA Intro @ 1208C
._cache_op				;MRC CP15,0,Rx,C2,C?
 LDR     R2, emulate_RISCOS
 CMP     R2, #&200 << 8			;ARM2?
 BLS     _undefined			;YES, undefined instruction
 LDRB    R2, JIT_ARM4
 TEQ     R2, #0				;ARMv4?
 LDREQ   R3, _C2_codelet_ARM3		;NO, valid ARM3 instruction
 BEQ     _P1

 MOV     R1, #9				;ADFF5009
 B       JIT_report_unimplemented	;YET TO BE CODED

 ._C2_codelet_ARM3
   MOVEQ   R0, #%1			;CACHE ON (ARM3 TRM p3-45)


._misc_op
 LDR     R3, _C345_codelet
 B       _P1

 ._C345_codelet
   MOVEQ   R0, #0


._undefined				;branch to undefined vector
; B _nop
 MOV     R1, #page_zero_Undefined
 SUB     R1, R1, R7			;correct address to be relative to R14
 BIC     R1, R1, #%111111 << 26
 AND     R0, R0, #%1111 << 28		;condition
 ORR     R0, R0, #&A << 24		;instruction
 ORR     R0, R0, R1, LSR #2		;add in corrected address
B       i_copy_and_exit



._i_fpu
 AND     R1, R0, #%11110001 << 4
 AND     R2, R0, #%1111 << 20		;R2=abcL/S
 TEQ     R1,     #%00010001 << 4	;load/store or comparison?
 ADDEQ   PC, PC, R2, LSR #18		;YES
 B       i_copy_instruction		;NO
					;abcL/S
 B       i_copy_instruction		;0000 FLT
 B       _fix				;0001
 B       _wfs				;0010
 B       _rfs				;0011
 B       _wfc				;0100
 B       _rfc				;0101
 B       _undefined			;0110
 B       _undefined			;0111
 B       _undefined			;1000
 B       _cmf				;1001
 B       _undefined			;1010
 B       _cnf				;1011
 B       _undefined			;1100
 B       _cmfe				;1101
 B       _undefined			;1110
 ._cmf
 ._cnf
 ._cmfe
 ._cnfe
 AND     R1, R0, #%1111 << 12		;Compare? (fix for Confusion)
 TEQ     R1,     #%1111 << 12
 BNE     i_copy_instruction		;NO
 BIC     R0, R0, #%1000 << 16		;YES, ensure e is zero
 BIC     R0, R0, #%111 << 5		; |+  ensure fgh are zero
 B       i_copy_instruction

 ._fix					;(fix for Confusion)
 BIC     R0, R0, #%1000 << 16		;ensure e is zero
 BIC     R0, R0, #%100 << 5		;ensure f is zero
 B       i_copy_instruction

 ._wfs
 ._rfs
 ._wfc
 ._rfc
 BIC     R0, R0, #%1000 << 16		;ensure e is zero
 BIC     R0, R0, #%111 << 5		;ensure fgh are zero
 B       i_copy_instruction
