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

ALIGN   32, 4
.i_ALU
 TST     R0, #%111111 << 22		;MUL / MLA?
 ANDEQ   R1, R0, #%1111 << 4		; |
 TEQEQ   R1,     #%1001 << 4		; |
 BEQ     i_MUL				; |+ YES

 AND     R1, R0, #%11111011 << 20	;SWP?
 TEQ     R1,     #%00010000 << 20	; |
 ANDEQ   R1, R0, #%11111111 << 4	; |
 TEQEQ   R1,     #%00001001 << 4	; |
 #if ARMv7_support == 0
   BEQ     i_copy_instruction		; -+ YES
 #endif
 #if ARMv7_support == 1
   BEQ     i_SWP			; -+ YES
 #endif

 AND     R1, R0, #%1111 << 21
 TEQ     R1,     #%1101 << 21		;MOV / MOVS?
 TEQNE   R1,     #%1111 << 21		;MVN / MVNS?
 BEQ     i_MOV

 TEQ     R1,     #%1000 << 21		;TST
 TEQNE   R1,     #%1001 << 21		;TEQ
 TEQNE   R1,     #%1010 << 21		;CMP
 TEQNE   R1,     #%1011 << 21		;CMN
 BEQ     i_comparison

;ADD{S} PC, ...
 AND     R1, R0, #%1111 << 12
 TEQ     R1, #PC_reg << 12		;Rd is PC?
 BEQ     i_ALU_PC_in_Rd			;YES

;ADD{S} Rd, PC, ...
 AND     R1, R0, #%1111 << 16
 TEQ     R1, #PC_reg << 16		;Rn is PC?
 BEQ     i_ALU_PC_in_Rn			;YES

 TST     R0, #1 << 25			;is Op2 a Rm or immediate?
 BNE     i_copy_instruction		;immediate

;ADD{S} Rd, Rn, PC, ...
 AND     R4, R0, #%1111
 TEQ     R4, #PC_reg			;Rm is PC?
 ANDEQ   R4, R0, #%1111 << 16		;YES, R1=Rd, R4=Rn
 BEQ     i_ALU_PC_in_Rm			; |+  use i_MOV to code it

B       i_copy_instruction




;i_ALU_PC_in_Rn
;--------------
;xxx Rx, {[}PC, ...
; AND, EOR, SUB, RSB, ADD, ADC, SBC, RSC, ORR, BIC, with PC as Rn
; TEQ, TST, CMN, CMP
;
;ADD{S} Rd, PC, #<immed>
;ADD{S} Rd, PC, Rm {, <shift> #<immed>}
;ADD{S} Rd, PC, Rm {, <shift> Rs}
;ADD{S} Rd, PC, PC {, <shift> #<immed>} - not coded
;ADD{S} Rd, PC, PC {, <shift> Rs}       - not coded

.i_ALU_PC_in_Rn
 TST     R0, #1 << 25			;is Op2 a register?
 BNE     i_ALU_PC_in_Rn_immediate	;NO, it's an immediate

.i_ALU_PC_in_Rn_comparison		;CMP/CMN/TEQ/TST PC,#<immed> enter here
 AND     R2, R0, #%1111			;R2=Rm
 TEQ     R2, #PC_reg			;is Rm PC?
 MOVEQ   R1, #9				;ADFF5009
 BEQ     JIT_report_unimplemented	;YES, not supported yet

 CODELET 5

 TST     R0, #1 << 25			;is Op2 a register?
 ADRNE   R5, _codelet_R0		;NO, immediate
 BNE     _immediate			;CMP PC,#<immed> etc

 AND     R1, R0, #%1111 << 12		;R1=Rd
 TST     R0, #1 << 4			;YES is there an Rs?
 ANDNE   R3, R0, #%1111 << 8		;YES R3=Rs
 MOVNE   R3, R1, LSR #4			;NO ignore R3

 MOV     R5, #0
 TEQ     R1, R5, LSL #12		;is register being used
 TEQNE   R2, R5
 TEQNE   R3, R5, LSL #8
 ADDEQ   R5, R5, #1			;YES, use next register
 TEQ     R1, R5, LSL #12		;is register being used
 TEQNE   R2, R5
 TEQNE   R3, R5, LSL #8
 ADDEQ   R5, R5, #1			;YES, use next register
 TEQ     R1, R5, LSL #12		;is register being used
 TEQNE   R2, R5
 TEQNE   R3, R5, LSL #8
 ADDEQ   R5, R5, #1			;YES, use next register

 CMP     R5, #2
 ADREQ   R5, _codelet_R2
 ADRHI   R5, _codelet_R3
 CMP     R5, #1
 ADRLO   R5, _codelet_R0
 ADREQ   R5, _codelet_R1

 ._immediate
 LDMIA   R5!, {R1-R3}
					;-------- 3rd instruction --------
 AND     R3, R3, #%1111 << 16		;___ __, Rn, ___
 BIC     R0, R0, #%1111 << 16		;xxx Rd, __, ...
 ORR     R3, R3, R0			;xxx Rd, Rn, ...

 STMIA   R6!, {R1-R3}
 LDMIA   R5!, {R1-R2}
					;-------- 2nd instruction --------
 SUB     R5, R14, R6
 SUB     R5, R5, #8 + (2 * 4)		;correct for offset and prefetch
 BIC     R5, R5, #%111111 << 26
 ORR     R2, R2, R5, LSR #2		;B <original address + 4>

 STMIA   R6, {R1-R2}			;store codelet

B       i_instruction_handled


 ._codelet_R0
 STR     R0, _codelet_R0-4		;R1
 LDR     R0, _codelet_R0-codelet_PC	;R2 PC
 ANDEQ   R0, R0, R0			;R3 <original instruction> Rd, R0, ...
 LDR     R0, _codelet_R0-4		;R1
 DCD     B_blank			;R2 B <original address + 4>
					;5 instructions

 ._codelet_R1
 STR     R1, _codelet_R1-4		;R1
 LDR     R1, _codelet_R1-codelet_PC	;R2
 ANDEQ   R1, R1, R0			;R3 <original instruction> Rd, R1, ...
 LDR     R1, _codelet_R1-4		;R1
 DCD     B_blank			;R2 B <original address + 4>


 ._codelet_R2
 STR     R2, _codelet_R2-4		;R1
 LDR     R2, _codelet_R2-codelet_PC	;R2
 ANDEQ   R2, R2, R0			;R3 <original instruction> Rd, R2, ...
 LDR     R2, _codelet_R2-4		;R1
 DCD     B_blank			;R2 B <original address + 4>


 ._codelet_R3
 STR     R3, _codelet_R3-4		;R1
 LDR     R3, _codelet_R3-codelet_PC	;R2
 ANDEQ   R3, R3, R0			;R3 <original instruction> Rd, R3, ...
 LDR     R3, _codelet_R3-4		;R1
 DCD     B_blank			;R2 B <original address + 4>




.i_ALU_PC_in_Rn_immediate
 CODELET 3

 ADR     R5, _codelet
 LDMIA   R5!, {R1, R3}

 BIC     R2, R0, #%1111 << 16		;xxx Rd, __, ...
					;-------- 1st instruction --------
 AND     R0, R0, #%1111 << 12		;R0=Rd
 ORR     R1, R1, R0			;LDR Rd, _PC
					;-------- 2nd instruction --------
 ORR     R2, R2, R0, LSL #4		;xxx Rd, Rd, ...
					;-------- 2nd instruction --------
 SUB     R5, R14, R6
 SUB     R5, R5, #8 + (3 * 4)		;correct for offset and prefetch
 BIC     R5, R5, #%111111 << 26
 ORR     R3, R3, R5, LSR #2		;B <original address + 4>

 STMIA   R6, {R1-R3}			;store codelet

B       i_instruction_handled

 ._codelet
 LDR     R0, _codelet-codelet_PC	;R1
; ANDEQ   R0, R0, R0			;R2 <original instruction> Rd, R0, ...
 DCD     B_blank			;R3 B <original address + 4>
					;3 instructions





;i_ALU_PC_in_Rd
;--------------
;ADD{S} PC, Rn, #<immed>
;ADD{S} PC, Rn, Rm {, <shift> #<immed>}
;ADD{S} PC, Rn, Rm {, <shift> Rs}
;ADD{S} PC, PC, #<immed>
;ADD{S} PC, PC, Rm {, <shift> #<immed>}
;ADD{S} PC, PC, Rm {, <shift> Rs}
;ADD{S} PC, Rn, PC {, <shift> #<immed>} - not coded
;ADD{S} PC, PC, PC {, <shift> #<immed>} - not coded

.i_ALU_PC_in_Rd
 AND     R1, R0, #%1111 << 16		;R1=Rn
 MOV     R2, R1, LSR #16
 MOV     R3, R1, LSR #8

 TST     R0, #1 << 25			;is Op2 a register?
 BNE     _immediate			;NO

 AND     R2, R0, #%1111			;R2=Rm
 TEQ     R2, #PC_reg			;is Rm PC?
 MOVEQ   R1, #9				;ADFF5009
 BEQ     JIT_report_unimplemented	;YES, not supported yet

 TST     R0, #1 << 4			;is there an Rs?
 MOVEQ   R3, R2, LSL #8			;NO, ignore R3 is no Rs
 ANDNE   R3, R0, #%1111 << 8		;YES R3=Rs

 ._immediate
 MOV     R5, #0
 TEQ     R2, R5				;is register being used?
 TEQNE   R3, R5, LSL #8
 TEQNE   R1, R5, LSL #16
 ADDEQ   R5, R5, #1			;YES, use next register
 TEQ     R2, R5				;is register being used?
 TEQNE   R3, R5, LSL #8
 TEQNE   R1, R5, LSL #16
 ADDEQ   R5, R5, #1			;YES, use next register
 TEQ     R2, R5				;is register being used?
 TEQNE   R3, R5, LSL #8
 TEQNE   R1, R5, LSL #16
 ADDEQ   R5, R5, #1			;YES, use next register

 TST     R0, #1 << 20			;ADDS?
 BNE     i_ALUS_PC_in_Rd

 AND     R2, R0, #%1111 << 16		;R2=Rn
 TEQ     R2, #PC_reg << 16		;is Rn PC?
 BEQ     i_ALU_PC_in_Rd_and_Rn		;YES

;ADD PC, Rn, #<immed>
;ADD PC, Rn, Rm {, <shift> #<immed>}
;ADD PC, Rn, Rm {, <shift> Rs}
 CODELET_REUSE 13
 B       i_ALU_PC_in_Rd_P1

.i_ALU_PC_in_Rd_and_Rn
;ADD PC, PC, #<immed>
;ADD PC, PC, Rm {, <shift> #<immed>}
;ADD PC, PC, Rm {, <shift> Rs}
 CODELET 13

 .i_ALU_PC_in_Rd_P1
 CMP     R5, #2
 ADREQ   R5, _codelet_R2
 ADRHI   R5, _codelet_R3
 CMP     R5, #1
 ADRLT   R5, _codelet_R0
 ADREQ   R5, _codelet_R1


 TEQ     R2, #PC_reg << 16		;is Rn PC?
 LDMIA   R5!, {R1-R4}
 MOVNE   R4, #&01A00000			;NO, NOP:LDR R0, _codelet_R0-codelet_PC
 STMIA   R6!, {R1-R4}


 LDMIA   R5!, {R1-R3}
					;-------- 1st instruction --------
 BIC     R4, R0, #%1111 << 12		;xxx __, Rn{, <shift>}
 ORR     R1, R1, R4			;xxx Rx, Rn{, <shift>}

;ADD{S} PC, PC, #<immed>
;ADD{S} PC, PC, Rm {, <shift> #<immed>}
;ADD{S} PC, PC, Rm {, <shift> Rs}
 AND     R0, R0, #%1111 << 16		;R0=Rn
 TEQ     R0, #PC_reg << 16		;is Rn PC?
 BICEQ   R1, R1, #%1111 << 16		;YES, clear it
 ANDEQ   R4, R1, #%1111 << 12		; |  get Rx
 ORREQ   R1, R1, R4, LSL #4		; |+ xxx Rx, Rx{, <shift>}
 STMIA   R6!, {R1-R3}


 LDMIA   R5, {R0-R5}
 STMIA   R6, {R0-R5}			;store codelet

B       i_und_exit


 ._codelet_R0
 STR     R0, _codelet_R0-4		;R1
 MRS     R0, CPSR			;R2
 STR     R0, _codelet_R0-8		;R3
 LDR     R0, _codelet_R0-codelet_PC	;R4
 ANDEQ   R0, R0, R0			;R1 <original instruction> R0, ...
 BIC     R0, R0, #&FC000003		;R2
 CMP     R0, #jit_appspace_end		;R3 jumping to appspace?
 ADDLO   R0, R0, #jit_code_start	;R0 YES, correct
 STR     R0, _codelet_R0-12		;R1
 LDR     R0, _codelet_R0-8		;R2
 MSR     CPSR_f, R0			;R3
 LDR     R0, _codelet_R0-4		;R4
 LDR     PC, _codelet_R0-12		;R5
					;13 instructions

 ._codelet_R1
 STR     R1, _codelet_R1-4		;R1
 MRS     R1, CPSR			;R2
 STR     R1, _codelet_R1-8		;R3
 LDR     R1, _codelet_R1-codelet_PC	;R4
 ANDEQ   R1, R0, R0			;R1 <original instruction> R1, ...
 BIC     R1, R1, #&FC000003		;R2
 CMP     R1, #jit_appspace_end		;R3 jumping to appspace?
 ADDLO   R1, R1, #jit_code_start	;R0 YES, correct
 STR     R1, _codelet_R1-12		;R1
 LDR     R1, _codelet_R1-8		;R2
 MSR     CPSR_f, R1			;R3
 LDR     R1, _codelet_R1-4		;R4
 LDR     PC, _codelet_R1-12		;R5


 ._codelet_R2
 STR     R2, _codelet_R2-4		;R1
 MRS     R2, CPSR			;R2
 STR     R2, _codelet_R2-8		;R3
 LDR     R2, _codelet_R2-codelet_PC	;R4
 ANDEQ   R2, R0, R0			;R1 <original instruction> R2, ...
 BIC     R2, R2, #&FC000003		;R2
 CMP     R2, #jit_appspace_end		;R3 jumping to appspace?
 ADDLO   R2, R2, #jit_code_start	;R0 YES, correct
 STR     R2, _codelet_R2-12		;R1
 LDR     R2, _codelet_R2-8		;R2
 MSR     CPSR_f, R2			;R3
 LDR     R2, _codelet_R2-4		;R4
 LDR     PC, _codelet_R2-12		;R5


 ._codelet_R3
 STR     R3, _codelet_R3-4		;R1
 MRS     R3, CPSR			;R2
 STR     R3, _codelet_R3-8		;R3
 LDR     R3, _codelet_R3-codelet_PC	;R4
 ANDEQ   R3, R0, R0			;R1 <original instruction> R3, ...
 BIC     R3, R3, #&FC000003		;R2
 CMP     R3, #jit_appspace_end		;R3 jumping to appspace?
 ADDLO   R3, R3, #jit_code_start	;R0 YES, correct
 STR     R3, _codelet_R3-12		;R1
 LDR     R3, _codelet_R3-8		;R2
 MSR     CPSR_f, R3			;R3
 LDR     R3, _codelet_R3-4		;R4
 LDR     PC, _codelet_R3-12		;R5




;i_ALUS_PC_in_Rd
;---------------
;ADDS PC, Rn, #<immed>
;ADDS PC, Rn, Rm {, <shift> #<immed>}
;ADDS PC, Rn, Rm {, <shift> Rs}
;ADDS PC, PC, #<immed>
;ADDS PC, PC, Rm {, <shift> #<immed>}
;ADDS PC, PC, Rm {, <shift> Rs}
;ADDS PC, __, PC {, <shift> #<immed>} - not coded

.i_ALUS_PC_in_Rd
 AND     R2, R0, #%1111 << 16		;R2=Rn
 TEQ     R2, #PC_reg << 16		;is Rn PC?
 BEQ     i_ALUS_PC_in_Rd_and_Rn		;YES

;ADD PC, Rn, #<immed>
;ADD PC, Rn, Rm {, <shift> #<immed>}
;ADD PC, Rn, Rm {, <shift> Rs}
 #if compile_RO > 400
   CODELET_REUSE 24
 #endif
 #if compile_RO == 400
   CODELET_REUSE 21
 #endif
 B       i_ALUS_PC_in_Rd_P1

.i_ALUS_PC_in_Rd_and_Rn
;ADD PC, PC, #<immed>
;ADD PC, PC, Rm {, <shift> #<immed>}
;ADD PC, PC, Rm {, <shift> Rs}
 #if compile_RO > 400
   CODELET 24
 #endif
 #if compile_RO == 400
   CODELET 21
 #endif

 .i_ALUS_PC_in_Rd_P1
 CMP     R5, #2
 ADREQ   R5, _codelet_R2
 ADRHI   R5, _codelet_R3
 CMP     R5, #1
 ADRLO   R5, _codelet_R0
 ADREQ   R5, _codelet_R1

 LDMIA   R5!, {R1-R4}
 STMIA   R6!, {R1-R4}


 AND     R4, R0, #%1111 << 16
 TEQ     R4, #PC_reg << 16		;is Rn PC?
 LDMIA   R5!, {R1-R4}
 MOVNE   R3, #&01A00000			;NO, NOP:LDR R0, _codelet_R0-codelet_PC
 STMIA   R6!, {R1-R4}


 LDMIA   R5!, {R1-R3}
					;-------- 2nd instruction --------
 BICEQ   R0, R0, #%1111 << 16		;YES, clear it
 ANDEQ   R4, R2, #%1111 << 12		; |  get Rx
 ORREQ   R2, R2, R4, LSL #4		; |+ xxx Rx, Rx
 BIC     R4, R0, #%1111 << 12		;xxx __, Rn{, <shift>}
 ORR     R2, R2, R4			;xxx Rx, Rn{, <shift>}
					;---------------------------------
 STMIA   R6!, {R1-R3}


 LDMIA   R5!, {R0-R4}
 STMIA   R6!, {R0-R4}


 #if compile_RO > 400
   LDMIA   R5!, {R0-R3}
   STMIA   R6!, {R0-R3}
 #endif


 LDMIA   R5, {R0-R3}
 STMIA   R6, {R0-R3}

B       i_und_exit


 ._codelet_R0
 STR     R0, _codelet_R0-4		;R1
 STR     R1, _codelet_R0-8		;R2
 #if compile_RO > 400
   MRS     R0, CPSR			;R3
   AND     R1, R0, #&F0000003		;R4
   AND     R0, R0, #%11 << 6		;R1 - IRQ / FIQ
   ORR     R1, R1, R0, LSL #20		;R2
 #endif
 #if compile_RO == 400
   MOV     R1, PC			;R3 NOP if Rn <> PC
   AND     R1, R1, #&FC000003		;R4 NOP if Rn <> PC
   NOP					;R1
   NOP					;R2
 #endif
 LDR     R0, _codelet_R0-codelet_PC	;R3 NOP if Rn <> PC
 ORR     R0, R0, R1			;R4 NOP if Rn <> PC
 LDR     R1, _codelet_R0-8		;R1
 ANDEQ   R0, R0, R0			;R2 <original instruction> R0, ...
 STR     R0, _codelet_R0-12		;R3
 BIC     R0, R0, #&FC000003		;R0
 CMP     R0, #jit_appspace_end		;R1 jumping to appspace?
 ADDLO   R0, R0, #jit_code_start	;R2 YES, correct
 STR     R0, _codelet_R0-16		;R3
 LDR     R0, _codelet_R0-12		;R4
 #if compile_RO > 400
   AND     R0, R0, #&FC000003		;R0
   ORR     R0, R0, R0, LSR #20		;R1
   BIC     R0, R0, #%1111 << 8		;R2 clear unwanted bits
   BIC     R0, R0, #%11 << 26		;R3 clear FIQ/IRQ
   ORR     R0, R0, #c32bit		;R0 32bit
   #if compile_RO == 450
     MSR     CPSR_all, R0		;R1
   #endif
   #if compile_RO == 500
     MSR     CPSR_cf, R0		;R1
   #endif
 #endif
 #if compile_RO == 400
   TEQP    R0, #0			;R0
   NOP					;R1
 #endif
 LDR     R0, _codelet_R0-4		;R2
 LDR     PC, _codelet_R0-16		;R3
					;24 instructions 32bit
					;21 instructions 26bit
 ._codelet_R1
 STR     R0, _codelet_R1-4		;R1
 STR     R1, _codelet_R1-8		;R2
 #if compile_RO > 400
   MRS     R0, CPSR			;R3
   AND     R1, R0, #&F0000003		;R4
   AND     R0, R0, #%11 << 6		;R1 - IRQ / FIQ
   ORR     R1, R1, R0, LSL #20		;R2
 #endif
 #if compile_RO == 400
   MOV     R1, PC			;R3
   AND     R1, R1, #&FC000003		;R4
   NOP					;R1
   NOP					;R2
 #endif
 LDR     R0, _codelet_R1-codelet_PC	;R3
 ORR     R1, R1, R0			;R4
 LDR     R0, _codelet_R1-4		;R1
 ANDEQ   R1, R0, R0			;R2 <original instruction> R1, ...
 STR     R1, _codelet_R1-12		;R3
 BIC     R1, R1, #&FC000003		;R0
 CMP     R1, #jit_appspace_end		;R1 jumping to appspace?
 ADDLO   R1, R1, #jit_code_start	;R2 YES, correct
 STR     R1, _codelet_R1-16		;R3
 LDR     R1, _codelet_R1-12		;R4
 #if compile_RO > 400
   AND     R1, R1, #&FC000003		;R0
   ORR     R1, R1, R1, LSR #20		;R1
   BIC     R1, R1, #%1111 << 8		;R2 clear unwanted bits
   BIC     R1, R1, #%11 << 26		;R3 clear FIQ/IRQ
   ORR     R1, R1, #c32bit		;R0 32bit
   #if compile_RO == 450
     MSR     CPSR_all, R1		;R1
   #endif
   #if compile_RO == 500
     MSR     CPSR_cf, R1		;R1
   #endif
 #endif
 #if compile_RO == 400
   TEQP    R1, #0			;R0
   NOP					;R1
 #endif
 LDR     R1, _codelet_R1-8		;R2
 LDR     PC, _codelet_R1-16		;R3


 ._codelet_R2
 STR     R0, _codelet_R2-4		;R1
 STR     R2, _codelet_R2-8		;R2
 #if compile_RO > 400
   MRS     R0, CPSR			;R3
   AND     R2, R0, #&F0000003		;R4
   AND     R0, R0, #%11 << 6		;R1 - IRQ / FIQ
   ORR     R2, R2, R0, LSL #20		;R2
 #endif
 #if compile_RO == 400
   MOV     R2, PC			;R3
   AND     R2, R2, #&FC000003		;R4
   NOP					;R1
   NOP					;R2
 #endif
 LDR     R0, _codelet_R2-codelet_PC	;R3
 ORR     R2, R2, R0			;R4
 LDR     R0, _codelet_R2-4		;R1
 ANDEQ   R2, R0, R0			;R2 <original instruction> R2, ...
 STR     R2, _codelet_R2-12		;R3
 BIC     R2, R2, #&FC000003		;R0
 CMP     R2, #jit_appspace_end		;R1 jumping to appspace?
 ADDLO   R2, R2, #jit_code_start	;R2 YES, correct
 STR     R2, _codelet_R2-16		;R3
 LDR     R2, _codelet_R2-12		;R4
 #if compile_RO > 400
   AND     R2, R2, #&FC000003		;R0
   ORR     R2, R2, R2, LSR #20		;R1
   BIC     R2, R2, #%1111 << 8		;R2 clear unwanted bits
   BIC     R2, R2, #%11 << 26		;R3 clear FIQ/IRQ
   ORR     R2, R2, #c32bit		;R0 32bit
   #if compile_RO == 450
     MSR     CPSR_all, R2		;R1
   #endif
   #if compile_RO == 500
     MSR     CPSR_cf, R2		;R1
   #endif
 #endif
 #if compile_RO == 400
   TEQP    R2, #0			;R0
   NOP					;R1
 #endif
 LDR     R2, _codelet_R2-8		;R2
 LDR     PC, _codelet_R2-16		;R3


 ._codelet_R3
 STR     R0, _codelet_R3-4		;R1
 STR     R3, _codelet_R3-8		;R2
 #if compile_RO > 400
   MRS     R0, CPSR			;R3
   AND     R3, R0, #&F0000003		;R4
   AND     R0, R0, #%11 << 6		;R1 - IRQ / FIQ
   ORR     R3, R3, R0, LSL #20		;R2
 #endif
 #if compile_RO == 400
   MOV     R3, PC			;R3
   AND     R3, R3, #&FC000003		;R4
   NOP					;R1
   NOP					;R2
 #endif
 LDR     R0, _codelet_R3-codelet_PC	;R3
 ORR     R3, R3, R0			;R4
 LDR     R0, _codelet_R3-4		;R1
 ANDEQ   R3, R0, R0			;R2 <original instruction> R3, ...
 STR     R3, _codelet_R3-12		;R3
 BIC     R3, R3, #&FC000003		;R0
 CMP     R3, #jit_appspace_end		;R1 jumping to appspace?
 ADDLO   R3, R3, #jit_code_start	;R2 YES, correct
 STR     R3, _codelet_R3-16		;R3
 LDR     R3, _codelet_R3-12		;R4
 #if compile_RO > 400
   AND     R3, R3, #&FC000003		;R0
   ORR     R3, R3, R3, LSR #20		;R1
   BIC     R3, R3, #%1111 << 8		;R2 clear unwanted bits
   BIC     R3, R3, #%11 << 26		;R3 clear FIQ/IRQ
   ORR     R3, R3, #c32bit		;R0 32bit
   #if compile_RO == 450
     MSR     CPSR_all, R3		;R1
   #endif
   #if compile_RO == 500
     MSR     CPSR_cf, R3		;R1
   #endif
 #endif
 #if compile_RO == 400
   TEQP    R3, #0			;R0
   NOP					;R1
 #endif
 LDR     R3, _codelet_R3-8		;R2
 LDR     PC, _codelet_R3-16		;R3




;i_comparison
;------------
;TST, TEQ, CMP, CMN
;
;Entry:
; R1 = <instruction> bits
; R2 = Rn

;TST{P} Rn, Rm{, <shift>}
;TST{P} Rn, #<immediate>

.i_comparison
 AND     R3, R0, #%1111 << 12		;R3=Rd=F if TEQP etc
 TEQ     R3,     #%1111 << 12		;TSTP etc?
 #if compile_RO >= 400 AND JIT_prevent_OS_EnterOS > 1
   MOVEQ   R0, #%1101 << 21		;YES, NOP it
 #endif
 #if compile_RO == 400
   BEQ     i_copy_instruction		;YES
 #endif
 #if compile_RO > 400
   BEQ     i_comparisonP		;YES
 #endif

 TST     R0, #1 << 20			;is S bit set?
 MOVEQ   R0, #%1101 << 21		;NO
 BEQ     i_copy_instruction		; |+ use NOP instead (fixes Slappit)

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

 TST     R0, #1 << 25			;is Op2 a register?
 MOVNE   R2, #0				;Rm doesn't exist
 BNE     _immediate			;NO

 AND     R2, R0, #%1111			;R2=Rm
 TEQ     R2, #PC_reg			;Rm is PC?
 BEQ     i_MOV				;YES

 ._immediate
 AND     R1, R0, #%1111 << 16		;R1=Rn
 TEQ     R1, #PC_reg << 16		;Rn is PC?
 BEQ     i_ALU_PC_in_Rn_comparison	;YES
B       i_copy_instruction




#if compile_RO > 400
;i_comparisonP
;-------------
;TSTP, TEQP, CMPP, CMNP
;
;Entry:
;
;R1 = <instruction> bits

;TSTP/TEQP/CMPP/CMNP Rn, Rm{, <shift> Rs}
;TSTP/TEQP/CMPP/CMNP Rn, #<immediate>
;TSTP/TEQP/CMPP/CMNP PC, Rm{, <shift> Rs}
;TSTP/TEQP/CMPP/CMNP PC, #<immediate>

.i_comparisonP
 TST     R0, #1 << 25			;is Op2 a register?
 BNE     _immediate			;NO

 AND     R2, R0, #%1111			;R2=Rm
 TEQ     R2, #PC_reg			;Rm is PC?  (No Excuses @ F7A0)
 BEQ     i_comparisonP_PC_in_Rm

 ._immediate
 CMP     R1, #%1011 << 21		;TSTP, TEQP, CMPP?
 ANDLO   R2, R1, #%0111 << 21		;YES, change to AND, EOR, SUB
 MOVEQ   R2,     #%0100 << 21		;CMNP, change to ADD

 BIC     R0, R0, #%1111 << 12		;clear P
 BIC     R0, R0, #%11111 << 20		;clear instruction and S bit
 ORR     R0, R0, R2			;change to AND, EOR, SUB or ADD

 CODELET 11

 AND     R1, R0, #%1111 << 16		;R1=Rn
 MOV     R2, R1, LSR #16		;ignore R3 if immediate
 MOV     R3, R2, LSL #8			;ignore R3 if no Rs
 TST     R0, #1 << 25			;is Op2 a register?
 BNE     _immediate2
 AND     R2, R0, #%1111			;YES R2=Rm
 TST     R0, #1 << 4			;YES is there an Rs?
 ANDNE   R3, R0, #%1111 << 8		;YES R3=Rs

 ._immediate2
 MOV     R5, #0
 TEQ     R1, R5, LSL #16		;is register being used
 TEQNE   R2, R5
 TEQNE   R3, R5, LSL #8
 ADDEQ   R5, R5, #1			;YES, use next register
 TEQ     R1, R5, LSL #16		;is register being used
 TEQNE   R2, R5
 TEQNE   R3, R5, LSL #8
 ADDEQ   R5, R5, #1			;YES, use next register
 TEQ     R1, R5, LSL #16		;is register being used
 TEQNE   R2, R5
 TEQNE   R3, R5, LSL #8
 ADDEQ   R5, R5, #1			;YES, use next register

 CMP     R5, #2
 ADREQ   R5, _codelet_R2
 ADRHI   R5, _codelet_R3
 CMP     R5, #1
 ADRLO   R5, _codelet_R0
 ADREQ   R5, _codelet_R1

 LDMIA   R5!, {R1-R3}
 AND     R4, R0, #%1111 << 16
 TEQ     R4, #PC_reg << 16		;is Rn PC?
					;-------- 3rd instruction --------
 ANDEQ   R4, R3, #%1111 << 12		;YES  get Rx
 ORREQ   R3, R3, R4, LSL #4		; |+ xxx Rx, Rx
 BICEQ   R0, R0, #%1111 << 16		; |+ clear PC from original instr.
 BIC     R4, R0, #%1111 << 12		;xxx __, Rn{, <shift>}
 ORR     R3, R3, R4			;xxx Rx, Rn{, <shift>}
					;---------------------------------
 STMEQIA R6!, {R1-R3}
 STMNEIA R6!, {R1,R3}


 LDMIA   R5!, {R1-R4}
 STMIA   R6!, {R1-R4}


 LDMIA   R5!, {R1-R4}
					;-------- 3rd instruction --------
 SUBNE   R3, R3, #4			;correct 3rd instruction
					;-------- 4th instruction --------
 SUB     R5, R14, R6
 SUB     R5, R5, #8 + (4 * 4)		;correct for offset and prefetch
 BIC     R5, R5, #%111111 << 26
 ORR     R4, R4, R5, LSR #2		;B <original address + 4>

 STMIA   R6!, {R1-R4}

B       i_instruction_handled


 ._codelet_R0
 STR     R0, _codelet_R0-4		;R1
 LDR     R0, _codelet_R0-codelet_PC	;R2 (optional)
 ANDEQ   R0, R0, R0			;R3 <original instruction> R0, ...
 AND     R0, R0, #&FC000003		;R1
 ORR     R0, R0, R0, LSR #20		;R2
 BIC     R0, R0, #%1111 << 8		;R3 clear unwanted bits
 BIC     R0, R0, #%11 << 26		;R4 clear FIQ/IRQ
 ORR     R0, R0, #c32bit		;R1 32bit
 #if compile_RO > 311 AND compile_RO < 500
   MSR     CPSR_all, R0			;R2
 #endif
 #if compile_RO == 500
   MSR     CPSR_cf, R0			;R2
 #endif
 LDR     R0, _codelet_R0-4		;R3
 DCD     B_blank			;R4 B <original address + 4>
					;11 instructions

 ._codelet_R1
 STR     R1, _codelet_R1-4		;R1
 LDR     R1, _codelet_R1-codelet_PC	;R2 (optional)
 ANDEQ   R1, R0, R0			;R3 <original instruction> R1, ...
 AND     R1, R1, #&FC000003		;R1
 ORR     R1, R1, R1, LSR #20		;R2
 BIC     R1, R1, #%1111 << 8		;R3 clear unwanted bits
 BIC     R1, R1, #%11 << 26		;R4 clear FIQ/IRQ
 ORR     R1, R1, #c32bit		;R1 32bit
 #if compile_RO > 311 AND compile_RO < 500
   MSR     CPSR_all, R1			;R2
 #endif
 #if compile_RO == 500
   MSR     CPSR_cf, R1			;R2
 #endif
 LDR     R1, _codelet_R1-4		;R3
 DCD     B_blank			;R4 B <original address + 4>


 ._codelet_R2
 STR     R2, _codelet_R2-4		;R1
 LDR     R2, _codelet_R2-codelet_PC	;R2 (optional)
 ANDEQ   R2, R0, R0			;R3 <original instruction> R2, ...
 AND     R2, R2, #&FC000003		;R1
 ORR     R2, R2, R2, LSR #20		;R2
 BIC     R2, R2, #%1111 << 8		;R3 clear unwanted bits
 BIC     R2, R2, #%11 << 26		;R4 clear FIQ/IRQ
 ORR     R2, R2, #c32bit		;R1 32bit
 #if compile_RO > 311 AND compile_RO < 500
   MSR     CPSR_all, R2			;R2
 #endif
 #if compile_RO == 500
   MSR     CPSR_cf, R2			;R2
 #endif
 LDR     R2, _codelet_R2-4		;R3
 DCD     B_blank			;R4 B <original address + 4>


 ._codelet_R3
 STR     R3, _codelet_R3-4		;R1
 LDR     R3, _codelet_R3-codelet_PC	;R2 (optional)
 ANDEQ   R3, R0, R0			;R3 <original instruction> R3, ...
 AND     R3, R3, #&FC000003		;R1
 ORR     R3, R3, R3, LSR #20		;R2
 BIC     R3, R3, #%1111 << 8		;R3 clear unwanted bits
 BIC     R3, R3, #%11 << 26		;R4 clear FIQ/IRQ
 ORR     R3, R3, #c32bit		;R1 32bit
 #if compile_RO > 311 AND compile_RO < 500
   MSR     CPSR_all, R3			;R2
 #endif
 #if compile_RO == 500
   MSR     CPSR_cf, R3			;R2
 #endif
 LDR     R3, _codelet_R3-4		;R3
 DCD     B_blank			;R4 B <original address + 4>




;i_comparisonP_PC_in_Rm
;----------------------
;TSTP, TEQP, CMPP, CMNP (No Excuses @ F7A0)
;
;Entry:
;
;R1 = <instruction> bits

;TSTP/TEQP/CMPP/CMNP Rn, PC{, <shift> Rs}

.i_comparisonP_PC_in_Rm
 AND     R4, R0, #%1111 << 16
 TEQ     R4, #PC_reg << 16		;is Rn PC?
 MOVEQ   R1, #9				;ADFF5009
 BEQ     JIT_report_unimplemented	;YES, not supported yet

 CMP     R1, #%1011 << 21		;TSTP, TEQP, CMPP?
 ANDLO   R2, R1, #%0111 << 21		;YES, change to AND, EOR, SUB
 MOVEQ   R2,     #%0100 << 21		;CMNP, change to ADD

 BIC     R0, R0, #%1111 << 12		;clear P
 BIC     R0, R0, #%11111 << 20		;clear instruction and S bit
 ORR     R0, R0, R2			;change to AND, EOR, SUB or ADD
 BIC     R0, R0, #%1111			;clear Rm

 CODELET 18

 AND     R1, R0, #%1111 << 16		;R1=Rn
 TST     R0, #1 << 4			;is there an Rs?
 MOVEQ   R3, R1, LSR #8			;ignore R3 if no Rs
 ANDNE   R3, R0, #%1111 << 8		;YES R3=Rs

 MOV     R5, #0
 TEQ     R1, R5, LSL #16		;is register being used
 TEQNE   R3, R5, LSL #8
 ADDEQ   R5, R5, #1			;YES, use next register
 TEQ     R1, R5, LSL #16		;is register being used
 TEQNE   R3, R5, LSL #8
 ADDEQ   R5, R5, #1			;YES, use next register

 CMP     R5, #1
 ADRLO   R5, _codelet_R0
 ADREQ   R5, _codelet_R1
 ADRHI   R5, _codelet_R2

 LDMIA   R5!, {R1-R4}
 STMIA   R6!, {R1-R4}


 LDMIA   R5!, {R1-R4}
 STMIA   R6!, {R1-R4}


 LDMIA   R5!, {R1-R3}
					;-------- 2nd instruction --------
 ORR     R2, R2, R0			;xxx Rx, Rx, Rn{, <shift>}
 STMIA   R6!, {R1-R3}


 LDMIA   R5!, {R1-R4}
 STMIA   R6!, {R1-R4}


 LDMIA   R5!, {R1-R3}
					;-------- 3rd instruction --------
 SUB     R5, R14, R6
 SUB     R5, R5, #8 + (3 * 4)		;correct for offset and prefetch
 BIC     R5, R5, #%111111 << 26
 ORR     R3, R3, R5, LSR #2		;B <original address + 4>

 STMIA   R6!, {R1-R3}

B       i_instruction_handled


 ._codelet_R0
 STR     R0, _codelet_R0-4		;R1
 STR     R1, _codelet_R0-8		;R2
 MRS     R0, CPSR			;R3
 AND     R1, R0, #%11 << 26		;R4 FIQ/IRQ
 ORR     R0, R0, R1, LSR #20		;R1
 AND     R0, R0, #&FC000003		;R2
 LDR     R1, _codelet_R0-codelet_PC	;R3
 ORR     R0, R0, R1			;R4
 LDR     R1, _codelet_R0-8		;R1
 ANDEQ   R0, R0, R0			;R2 <original instr> R0, Rx, R0, ...
 AND     R0, R0, #&FC000003		;R3
 ORR     R0, R0, R0, LSR #20		;R1
 BIC     R0, R0, #%1111 << 8		;R2 clear unwanted bits
 BIC     R0, R0, #%11 << 26		;R3 clear FIQ/IRQ
 ORR     R0, R0, #c32bit		;R4 32bit
 #if compile_RO > 311 AND compile_RO < 500
   MSR     CPSR_all, R0			;R1
 #endif
 #if compile_RO == 500
   MSR     CPSR_cf, R0			;R1
 #endif
 LDR     R0, _codelet_R0-4		;R2
 DCD     B_blank			;R3 B <original address + 4>
					;18 instructions

 ._codelet_R1
 STR     R0, _codelet_R1-4		;R1
 STR     R1, _codelet_R1-8		;R2
 MRS     R0, CPSR			;R3
 AND     R1, R0, #%11 << 26		;R4 FIQ/IRQ
 ORR     R0, R0, R1, LSR #20		;R1
 AND     R0, R0, #&FC000003		;R2
 LDR     R1, _codelet_R1-codelet_PC	;R3
 ORR     R1, R0, R1			;R4
 LDR     R0, _codelet_R1-4		;R1
 ANDEQ   R1, R0, R1			;R2 <original instr> R1, Rx, R1, ...
 AND     R1, R1, #&FC000003		;R3
 ORR     R1, R1, R1, LSR #20		;R1
 BIC     R1, R1, #%1111 << 8		;R2 clear unwanted bits
 BIC     R1, R1, #%11 << 26		;R3 clear FIQ/IRQ
 ORR     R1, R1, #c32bit		;R4 32bit
 #if compile_RO > 311 AND compile_RO < 500
   MSR     CPSR_all, R1			;R1
 #endif
 #if compile_RO == 500
   MSR     CPSR_cf, R1			;R1
 #endif
 LDR     R1, _codelet_R1-8		;R2
 DCD     B_blank			;R3 B <original address + 4>


 ._codelet_R2
 STR     R1, _codelet_R2-4		;R1
 STR     R2, _codelet_R2-8		;R2
 MRS     R1, CPSR			;R3
 AND     R2, R1, #%11 << 26		;R4 FIQ/IRQ
 ORR     R1, R1, R2, LSR #20		;R1
 AND     R1, R1, #&FC000003		;R2
 LDR     R2, _codelet_R2-codelet_PC	;R3
 ORR     R2, R1, R2			;R4
 LDR     R1, _codelet_R2-4		;R1
 ANDEQ   R2, R0, R2			;R2 <original instr> R2, Rx, R2, ...
 AND     R2, R2, #&FC000003		;R3
 ORR     R2, R2, R2, LSR #20		;R1
 BIC     R2, R2, #%1111 << 8		;R2 clear unwanted bits
 BIC     R2, R2, #%11 << 26		;R3 clear FIQ/IRQ
 ORR     R2, R2, #c32bit		;R4 32bit
 #if compile_RO > 311 AND compile_RO < 500
   MSR     CPSR_all, R2			;R1
 #endif
 #if compile_RO == 500
   MSR     CPSR_cf, R2			;R1
 #endif
 LDR     R2, _codelet_R2-8		;R2
 DCD     B_blank			;R3 B <original address + 4>
#endif
