;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?

 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
 MOVEQ   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 tmp1
 LDR     R0, _codelet_R0-codelet_PC	;R2 PC
 ANDEQ   R0, R0, R0			;R3 <original instruction> Rd, R0, ...
 LDR     R0, _codelet_R0-4		;R1 tmp1
 DCD     B_blank			;R2 B <original address + 4>
					;5 instructions

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


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


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




.i_ALU_PC_in_Rn_immediate
 CODELET 3
		;  00IopcdS
 AND     R2, R0, #%11111111 << 20	;R2=I | OpCode | S
 TEQ     R2,     #%00100010 << 20	;EOR Rx, PC, #0
 TEQNE   R2,     #%00100100 << 20	;SUB Rx, PC, #0
 TEQNE   R2,     #%00101000 << 20	;ADD Rx, PC, #0
 TEQNE   R2,     #%00111000 << 20	;ORR Rx, PC, #0
 TEQNE   R2,     #%00111100 << 20	;BIC Rx, PC, #0
 MOVEQS  R3, R0, LSL #32-11		;is Op2 blank?

 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, ...
					;-------- 3rd instruction --------
 SUB     R5, R14, R6
 SUBNE   R5, R5, #8 + (3 * 4)		;correct for offset and prefetch
 SUBEQ   R5, R5, #8 + (2 * 4)
 BIC     R5, R5, #%111111 << 26
 ORR     R3, R3, R5, LSR #2		;B <original address + 4>

 STMNEIA R6, {R1-R3}			;store codelet
 STMEQIA R6, {R1, R3}

B       i_instruction_handled

 ._codelet
 LDR     R0, _codelet-codelet_PC	;R1 LDR Rd, _PC
; ANDEQ   R0, R0, R0			;R2 (optional) <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

 TEQ     R1, #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 7
 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 8

 .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


 BIC     R4, R0, #%1111 << 12		;xxx __, Rn{, <shift>}
 AND     R0, R0, #%1111 << 16		;R0=Rn
 TEQ     R0, #PC_reg << 16		;is Rn PC?
 LDMIA   R5!, {R1-R3}
					;-------- 3rd instruction --------
 ORR     R3, R3, R4			;xxx Rx, Rn{, <shift>}

;ADD PC, PC, #<immed>
;ADD PC, PC, Rm {, <shift> #<immed>}
;ADD PC, PC, Rm {, <shift> Rs}
 BICEQ   R3, R3, #%1111 << 16		;Rn=PC, clear it
 ANDEQ   R4, R3, #%1111 << 12		; |  get Rx
 ORREQ   R3, R3, R4, LSL #4		; |+ xxx Rx, Rx{, <shift>}
 STMEQIA R6!, {R1-R3}
 STMNEIA R6!, {R1,R3}


 LDMIA   R5, {R0-R4}
 SUBNE   R2, R2, #4			;correct if Rn<>PC
 SUBNE   R3, R3, #4
 SUBNE   R4, R4, #4
 STMIA   R6, {R0-R4}			;store codelet

B       i_und_exit


 ._codelet_R0
 STR     R0, _codelet_R0-4		;R1 tmp1
 LDR     R0, _codelet_R0-codelet_PC	;R2 (discarded if Rn<>PC)
 ANDEQ   R0, R0, R0			;R3 <original instruction> R0, ...
 ADD     R0, R0, #jit_code_start	;R0 correct
 BIC     R0, R0, #&FC000003		;R1
 STR     R0, _codelet_R0-8		;R2 tmp2
 LDR     R0, _codelet_R0-4		;R3 tmp1
 LDR     PC, _codelet_R0-8		;R4 tmp2
					;8 instructions
					;7 if Rn<>PC

 ._codelet_R1
 STR     R1, _codelet_R1-4		;R1 tmp1
 LDR     R1, _codelet_R1-codelet_PC	;R2 (discarded if Rn<>PC)
 ANDEQ   R1, R0, R0			;R3 <original instruction> R1, ...
 ADD     R1, R1, #jit_code_start	;R0 correct
 BIC     R1, R1, #&FC000003		;R1
 STR     R1, _codelet_R1-8		;R2 tmp2
 LDR     R1, _codelet_R1-4		;R3 tmp1
 LDR     PC, _codelet_R1-8		;R4 tmp2


 ._codelet_R2
 STR     R2, _codelet_R2-4		;R1 tmp1
 LDR     R2, _codelet_R2-codelet_PC	;R2 (discarded if Rn<>PC)
 ANDEQ   R2, R0, R0			;R3 <original instruction> R2, ...
 ADD     R2, R2, #jit_code_start	;R0 correct
 BIC     R2, R2, #&FC000003		;R1
 STR     R2, _codelet_R2-8		;R2 tmp2
 LDR     R2, _codelet_R2-4		;R3 tmp1
 LDR     PC, _codelet_R2-8		;R4 tmp2


 ._codelet_R3
 STR     R3, _codelet_R3-4		;R1 tmp1
 LDR     R3, _codelet_R3-codelet_PC	;R2 (discarded if Rn<>PC)
 ANDEQ   R3, R0, R0			;R3 <original instruction> R3, ...
 ADD     R3, R3, #jit_code_start	;R0 correct
 BIC     R3, R3, #&FC000003		;R1
 STR     R3, _codelet_R3-8		;R2 tmp2
 LDR     R3, _codelet_R3-4		;R3 tmp1
 LDR     PC, _codelet_R3-8		;R4 tmp2




;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

;Entry:
;R1 - Rn
;R2 - Rd
;R3 - Rm (if used)
;R5 - codelet to use (0-3)

.i_ALUS_PC_in_Rd
 TEQ     R1, #PC_reg << 16		;is Rn PC?
 BEQ     i_ALUS_PC_in_Rd_and_Rn		;YES

;ADDS PC, Rn, #<immed>
;ADDS PC, Rn, Rm {, <shift> #<immed>}
;ADDS PC, Rn, Rm {, <shift> Rs}

 #if compile_RO > 400 AND compile_IOMD == 0
   CODELET_REUSE 15
 #endif
 #if compile_RO > 400 AND compile_IOMD == 1
   CODELET_REUSE 16
 #endif
 #if compile_RO == 400
   CODELET_REUSE 11
 #endif

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

 LDMIA   R5!, {R2-R4}
					;-------- 2nd instruction --------
 BIC     R0, R0, #%1111 << 12		;clear Rd
 BIC     R0, R0, #1 << 20		;clear S
 ORR     R3, R3, R0
 STMIA   R6!, {R2-R4}


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


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


 #if compile_RO > 400 AND compile_IOMD == 1
   LDMIA   R5!, {R0-R3}
   STMIA   R6!, {R0-R3}
 #endif
 #if compile_RO > 400 AND compile_IOMD == 0
   LDMIA   R5!, {R0, R2-R3}
   STMIA   R6!, {R0, R2-R3}
 #endif
 #if compile_RO == 400
   LDMIA   R5!, {R0-R3}
   STMIA   R6!, {R0-R3}
 #endif

B       i_und_exit



 ._codelet_R0
 STR     R0, _codelet_R0-4		;R2 tmp1
 DCD     0<<12				;R3 <original instruction> R0, ...
 ADD     R0, R0, #jit_code_start	;R4
 STR     R0, _codelet_R0-8		;R0 tmp2
 BIC     R0, R0, #&FC000003		;R1
 STR     R0, _codelet_R0-12		;R2 tmp3
 LDR     R0, _codelet_R0-8		;R3 tmp2
 #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		;R4 32bit
   MSR     CPSR_cf, R0			;R0
 #endif
 #if compile_RO == 400
   TEQP    R0, #0			;R0
 #endif
 #if compile_IOMD == 1
   NOP					;R1
 #endif
 LDR     R0, _codelet_R0-4		;R2 tmp1
 LDR     PC, _codelet_R0-12		;R3 tmp3
					;15 instructions 32bit (+1 IOMD)
					;11 instructions 26bit
 ._codelet_R1
 STR     R1, _codelet_R1-4		;R2 tmp1
 DCD     1<<12				;R3 <original instruction> R1, ...
 ADD     R1, R1, #jit_code_start	;R4
 STR     R1, _codelet_R1-8		;R0 tmp2
 BIC     R1, R1, #&FC000003		;R1
 STR     R1, _codelet_R1-12		;R2 tmp3
 LDR     R1, _codelet_R1-8		;R3 tmp2
 #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
   MSR     CPSR_cf, R1			;R1
 #endif
 #if compile_RO == 400
   TEQP    R1, #0			;R0
 #endif
 #if compile_IOMD == 1
   NOP					;R1
 #endif
 LDR     R1, _codelet_R1-4		;R2 tmp1
 LDR     PC, _codelet_R1-12		;R3 tmp3

 ._codelet_R2
 STR     R2, _codelet_R2-4		;R2 tmp1
 DCD     2<<12				;R3 <original instruction> R2, ...
 ADD     R2, R2, #jit_code_start	;R4
 STR     R2, _codelet_R2-8		;R0 tmp2
 BIC     R2, R2, #&FC000003		;R1
 STR     R2, _codelet_R2-12		;R2 tmp3
 LDR     R2, _codelet_R2-8		;R3 tmp2
 #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
   MSR     CPSR_cf, R2			;R1
 #endif
 #if compile_RO == 400
   TEQP    R2, #0			;R0
 #endif
 #if compile_IOMD == 1
   NOP					;R1
 #endif
 LDR     R2, _codelet_R2-4		;R2 tmp1
 LDR     PC, _codelet_R2-12		;R3 tmp3

 ._codelet_R3
 STR     R3, _codelet_R3-4		;R2 tmp1
 DCD     3<<12				;R3 <original instruction> R3, ...
 ADD     R3, R3, #jit_code_start	;R4 correct  ADD R3, Rn, ...
 STR     R3, _codelet_R3-8		;R0 tmp2
 BIC     R3, R3, #&FC000003		;R1
 STR     R3, _codelet_R3-12		;R2 tmp3
 LDR     R3, _codelet_R3-8		;R3 tmp2
 #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
   MSR     CPSR_cf, R3			;R1
 #endif
 #if compile_RO == 400
   TEQP    R3, #0			;R0
 #endif
 #if compile_IOMD == 1
   NOP					;R1
 #endif
 LDR     R3, _codelet_R3-4		;R2 tmp1
 LDR     PC, _codelet_R3-12		;R3 tmp3




.i_ALUS_PC_in_Rd_and_Rn
;ADDS PC, PC, #<immed>
;ADDS PC, PC, Rm {, <shift> #<immed>}
;ADDS PC, PC, Rm {, <shift> Rs}
 #if compile_RO > 400 AND compile_IOMD == 0
   CODELET 23
 #endif
 #if compile_RO > 400 AND compile_IOMD == 1
   CODELET 24
 #endif
 #if compile_RO == 400
   CODELET 17
 #endif
					;-------- 2nd instruction --------
 BIC     R0, R0, #%11111111 << 12	;clear Rd, Rn
 ORR     R0, R0, R5, LSL #12		;replace Rd with Rx
 ORR     R0, R0, R5, LSL #16		;replace Rn with Rx
					;---------------------------------

 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}

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

 MOV     R1, R0
 LDMIA   R5!, {R0,R2-R4}
 STMIA   R6!, {R0-R4}

 #if compile_RO == 400
   LDMIA   R5, {R0-R5}
   STMIA   R6, {R0-R5}
 #endif
 #if compile_RO > 400
   LDMIA   R5!, {R0-R4}
   STMIA   R6!, {R0-R4}
   #if compile_RO > 400 AND compile_IOMD == 0
     LDMIA   R5, {R0-R2, R4-R5}
     STMIA   R6, {R0-R2, R4-R5}
   #endif
   #if compile_RO > 400 AND compile_IOMD == 1
     LDMIA   R5, {R0-R5}
     STMIA   R6, {R0-R5}
   #endif
 #endif

B       i_und_exit


 ._codelet_R0
 STR     R0, _codelet_R0-4		;R1 tmp1
 STR     R1, _codelet_R0-8		;R2 tmp2
 #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
 #endif
 LDR     R0, _codelet_R0-codelet_PC	;R3
 ORR     R0, R0, R1			;R4
 LDR     R1, _codelet_R0-8		;R0 tmp2
 ;<original instruction> R0, R0, ...
 ADD     R0, R0, #jit_code_start	;R2 correct
 STR     R0, _codelet_R0-8 -4		;R3 tmp2
 BIC     R0, R0, #&FC000003		;R4
 STR     R0, _codelet_R0-12 -4		;R0 tmp3
 LDR     R0, _codelet_R0-8 -4		;R1 tmp2
 #if compile_RO > 400
   AND     R0, R0, #&FC000003		;R2
   ORR     R0, R0, R0, LSR #20		;R3
   BIC     R0, R0, #%1111 << 8		;R4 clear unwanted bits
   BIC     R0, R0, #%11 << 26		;R0 clear FIQ/IRQ
   ORR     R0, R0, #c32bit		;R1 32bit
   MSR     CPSR_cf, R0			;R2
 #endif
 #if compile_RO == 400
   TEQP    R0, #0			;R2
 #endif
 #if compile_IOMD == 1
   NOP					;R3
 #endif
 LDR     R0, _codelet_R0-4 -4		;R4 tmp1
 LDR     PC, _codelet_R0-12 -4		;R5 tmp3
					;23 instructions 32bit (+1 IOMD)
					;17 instructions 26bit
 ._codelet_R1
 STR     R0, _codelet_R1-4		;R1 tmp1
 STR     R1, _codelet_R1-8		;R2 tmp2
 #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
 #endif
 LDR     R0, _codelet_R1-codelet_PC	;R3
 ORR     R1, R1, R0			;R4
 LDR     R0, _codelet_R1-4		;R0 tmp1
;<original instruction> R1, R1, ...
 ADD     R1, R1, #jit_code_start	;R2 correct
 STR     R1, _codelet_R1-4 -4		;R3 tmp1
 BIC     R1, R1, #&FC000003		;R4
 STR     R1, _codelet_R1-12 -4		;R0 tmp3
 LDR     R1, _codelet_R1-4 -4		;R1 tmp1
 #if compile_RO > 400
   AND     R1, R1, #&FC000003		;R2
   ORR     R1, R1, R1, LSR #20		;R3
   BIC     R1, R1, #%1111 << 8		;R4 clear unwanted bits
   BIC     R1, R1, #%11 << 26		;R0 clear FIQ/IRQ
   ORR     R1, R1, #c32bit		;R1 32bit
   MSR     CPSR_cf, R1			;R2
 #endif
 #if compile_RO == 400
   TEQP    R1, #0			;R2
 #endif
 #if compile_IOMD == 1
   NOP					;R3
 #endif
 LDR     R1, _codelet_R1-8 -4		;R4 tmp2
 LDR     PC, _codelet_R1-12 -4		;R5 tmp3


 ._codelet_R2
 STR     R0, _codelet_R2-4		;R1 tmp1
 STR     R2, _codelet_R2-8		;R2 tmp2
 #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
 #endif
 LDR     R0, _codelet_R2-codelet_PC	;R3
 ORR     R2, R2, R0			;R4
 LDR     R0, _codelet_R2-4		;R0 tmp1
;<original instruction> R2, R2, ...
 ADD     R2, R2, #jit_code_start	;R2 correct
 STR     R2, _codelet_R2-4 -4		;R3 tmp1
 BIC     R2, R2, #&FC000003		;R4
 STR     R2, _codelet_R2-12 -4		;R0 tmp3
 LDR     R2, _codelet_R2-4 -4		;R1 tmp1
 #if compile_RO > 400
   AND     R2, R2, #&FC000003		;R2
   ORR     R2, R2, R2, LSR #20		;R3
   BIC     R2, R2, #%1111 << 8		;R4 clear unwanted bits
   BIC     R2, R2, #%11 << 26		;R0 clear FIQ/IRQ
   ORR     R2, R2, #c32bit		;R1 32bit
   MSR     CPSR_cf, R2			;R2
 #endif
 #if compile_RO == 400
   TEQP    R2, #0			;R2
 #endif
 #if compile_IOMD == 1
   NOP					;R3
 #endif
 LDR     R2, _codelet_R2-8 -4		;R4 tmp2
 LDR     PC, _codelet_R2-12 -4		;R5 tmp3


 ._codelet_R3
 STR     R0, _codelet_R3-4		;R1 tmp1
 STR     R3, _codelet_R3-8		;R2 tmp2
 #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
 #endif
 LDR     R0, _codelet_R3-codelet_PC	;R3
 ORR     R3, R3, R0			;R4
 LDR     R0, _codelet_R3-4		;R0 tmp1
;<original instruction> R3, R3, ...
 ADD     R3, R3, #jit_code_start	;R2 correct
 STR     R3, _codelet_R3-4 -4		;R3 tmp1
 BIC     R3, R3, #&FC000003		;R4
 STR     R3, _codelet_R3-12 -4		;R0 tmp3
 LDR     R3, _codelet_R3-4 -4		;R1 tmp1
 #if compile_RO > 400
   AND     R3, R3, #&FC000003		;R2
   ORR     R3, R3, R3, LSR #20		;R3
   BIC     R3, R3, #%1111 << 8		;R4 clear unwanted bits
   BIC     R3, R3, #%11 << 26		;R0 clear FIQ/IRQ
   ORR     R3, R3, #c32bit		;R1 32bit
   MSR     CPSR_cf, R3			;R2
 #endif
 #if compile_RO == 400
   TEQP    R3, #0			;R2
 #endif
 #if compile_IOMD == 1
   NOP					;R3
 #endif
 LDR     R3, _codelet_R3-8 -4		;R4 tmp2
 LDR     PC, _codelet_R3-12 -4		;R5 tmp3




;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
   BEQ     i_copy_instruction
 #endif
 BEQ     i_comparisonP			;YES

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

 TST     R0, #1 << 20			;is S bit set?
 MOVEQ   R0, #%1101 << 21		;NO, MRS Rd, {C/S}PSR
 #if compile_RO > 400                   ; |
   BEQ     i_copy_instruction		; |+ use NOP instead (fixes Slappit)

   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
 #endif
B       i_copy_instruction




;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>

;NOTE: without the S bit, only the CPU mode changes, flags are unchanged

.i_comparisonP
 #if compile_RO == 400
   TST     R0, #1 << 20			;is S bit set?
   BNE     i_copy_instruction		;YES, okay to leave
 #endif
 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

 #if compile_IOMD == 0
   CODELET 11
 #endif
 #if compile_IOMD == 1
   CODELET 12
 #endif

 BIC     R0, R0, #%1111 << 12		;clear P
 BIC     R0, R0, #%1111 << 21		;clear instruction
 ORR     R0, R0, R2			;change to AND, EOR, SUB or ADD

 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>}
 BIC     R4, R4, #1 << 20		;clear S bit
 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
					;-------- 2nd instruction --------
 TST     R0, #1 << 20			;is the S bit set?
 ORRNE   R2, R2, #1 << 19		;YES, change to MSR CPSR_cf, ..
					;-------- 4th instruction --------
 SUB     R5, R14, R6
 #if compile_IOMD == 0
   SUB     R5, R5, #8 + (4 * 4)		;correct for offset and prefetch
 #endif
 #if compile_IOMD == 1
   SUB     R5, R5, #8 + (5 * 4)		;correct for offset and prefetch
 #endif
 BIC     R5, R5, #%111111 << 26
 ORR     R4, R4, R5, LSR #2		;B <original address + 4>

 #if compile_IOMD == 0
   STMIA   R6!, {R1-R4}
 #endif
 #if compile_IOMD == 1
   STMIA   R6!, {R1-R2}
   MOV     R2, #&1A << 20		;add a NOP
   ADD     R3, R3, #4			;correct LDR, _codelet_Rx-4
   STMIA   R6!, {R2-R4}
 #endif

B       i_instruction_handled


 ._codelet_R0
 STR     R0, _codelet_R0-4		;R1 tmp1
 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
 MSR     CPSR_c, R0			;R2
;#if compile_IOMD == 1
;  NOP
;#endif
 LDR     R0, _codelet_R0-4		;R3 tmp1
 DCD     B_blank			;R4 B <original address + 4>
					;11 instructions
					;12 instructions (IOMD)

 ._codelet_R1
 STR     R1, _codelet_R1-4		;R1 tmp1
 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
 MSR     CPSR_c, R1			;R2
;#if compile_IOMD == 1
;  NOP
;#endif
 LDR     R1, _codelet_R1-4		;R3 tmp1
 DCD     B_blank			;R4 B <original address + 4>


 ._codelet_R2
 STR     R2, _codelet_R2-4		;R1 tmp1
 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
 MSR     CPSR_c, R2			;R2
;#if compile_IOMD == 1
;  NOP
;#endif
 LDR     R2, _codelet_R2-4		;R3 tmp1
 DCD     B_blank			;R4 B <original address + 4>


 ._codelet_R3
 STR     R3, _codelet_R3-4		;R1 tmp1
 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
 MSR     CPSR_c, R3			;R2
;#if compile_IOMD == 1
;  NOP
;#endif
 LDR     R3, _codelet_R3-4		;R3 tmp1
 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

 CODELET 18

 BIC     R0, R0, #%1111 << 12		;clear P
 BIC     R0, R0, #%1111 << 21		;clear instruction
 ORR     R0, R0, R2			;change to AND, EOR, SUB or ADD
 BIC     R0, R0, #%1111			;clear Rm

 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>}
 BIC     R2, R2, #1 << 20		;clear S bit
 STMIA   R6!, {R1-R3}


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


 LDMIA   R5!, {R1-R3}
					;-------- 1st instruction --------
 TST     R0, #1 << 20			;is the S bit set?
 ORRNE   R1, R1, #1 << 19		;YES, change to MSR CPSR_cf, ..
					;-------- 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 tmp1
 STR     R1, _codelet_R0-8		;R2 tmp2
 MRS     R0, CPSR			;R3
 AND     R1, R0, #%11 << 6		;R4 FIQ/IRQ
 AND     R0, R0, #&F0000003		;R1
 ORR     R0, R0, R1, LSL #20		;R2
 LDR     R1, _codelet_R0-codelet_PC	;R3
 ORR     R0, R0, R1			;R4
 LDR     R1, _codelet_R0-8		;R1 tmp2
 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
 MSR     CPSR_c, R0			;R1
 LDR     R0, _codelet_R0-4		;R2 tmp1
 DCD     B_blank			;R3 B <original address + 4>
					;18 instructions

 ._codelet_R1
 STR     R0, _codelet_R1-4		;R1 tmp1
 STR     R1, _codelet_R1-8		;R2 tmp2
 MRS     R0, CPSR			;R3
 AND     R1, R0, #%11 << 6		;R4 FIQ/IRQ
 AND     R0, R0, #&F0000003		;R1
 ORR     R0, R0, R1, LSL #20		;R2
 LDR     R1, _codelet_R1-codelet_PC	;R3
 ORR     R1, R0, R1			;R4
 LDR     R0, _codelet_R1-4		;R1 tmp1
 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
 MSR     CPSR_c, R1			;R1
 LDR     R1, _codelet_R1-8		;R2 tmp2
 DCD     B_blank			;R3 B <original address + 4>


 ._codelet_R2
 STR     R1, _codelet_R2-4		;R1 tmp1
 STR     R2, _codelet_R2-8		;R2 tmp2
 MRS     R1, CPSR			;R3
 AND     R2, R1, #%11 << 6		;R4 FIQ/IRQ
 AND     R1, R1, #&F0000003		;R1
 ORR     R1, R1, R1, LSL #20		;R2
 LDR     R2, _codelet_R2-codelet_PC	;R3
 ORR     R2, R1, R2			;R4
 LDR     R1, _codelet_R2-4		;R1 tmp1
 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
 MSR     CPSR_c, R2			;R1
 LDR     R2, _codelet_R2-8		;R2 tmp2
 DCD     B_blank			;R3 B <original address + 4>
