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

ALIGN   32, 4
.i_MOV
 AND     R2, R0, #%1111 << 12
 TEQ     R2,     #PC_reg << 12		;MOV PC, ...?
 BEQ     i_MOV_PC_in_Rd			;YES

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

 AND     R1, R0, #%1111
 TEQ     R1, #PC_reg			;MOV Rd, PC?
 BNE     i_copy_instruction		;NO

;MOV Rd, PC {, <shift> ..}

 MOV     R4, R1, LSL #4			;ignore Rn, it's not used in MOV

.i_ALU_PC_in_Rm
 AND     R1, R0, #%1111 << 12		;R1=Rd
 MOV     R3, R1, LSR #4			;ignore Rs if it's not there

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

 TST     R0, #1 << 4			;YES is there an Rs?
 ANDNE   R3, R0, #%1111 << 8		;YES R3=Rs

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

		;  00Iopcd
 AND     R2, R0, #%1111111 << 21	;R2=00 | I | OpCode
 TST     R0, #%111110010000		;is shift blank?
 TEQEQ   R2,     #%0001101 << 21	;YES, MOV{S} Rx, PC
 BEQ     i_MOV_Rd_PC			;YES, optimize it

 CODELET 12

 BIC     R0, R0, #%1111			;clear PC from Rm
 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}			;get replacement instructions
 STMIA   R6!, {R1-R4}


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


 LDMIA   R5, {R1-R4}
					;-------- 2nd instruction --------
 ORR     R2, R2, R0			;add to 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 tmp1
 STR     R1, _codelet_R0-8		;R2 tmp2
 #if compile_RO > 400
   MRS     R0, CPSR			;R3
   AND     R1, R0, #&F0000003		;R4 flags / CPU mode
   AND     R0, R0, #%11 << 6		;R1 IRQ / FIQ
   ORR     R0, R1, R0, LSL #20		;R2
 #endif
 #if compile_RO == 400
   MOV     R0, PC			;R3
   AND     R0, R0, #&FC000003		;R4
   NOP					;R1
   NOP					;R2
 #endif
 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 instruction
 LDR     R0, _codelet_R0-4		;R3 tmp1
 DCD     B_blank			;R4 B <original address + 4>
					;12 instructions

 ._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 flags / CPU mode
   AND     R0, R0, #%11 << 6		;R1 IRQ / FIQ
   ORR     R0, R1, R0, LSL #20		;R2
 #endif
 #if compile_RO == 400
   MOV     R0, PC			;R3
   AND     R0, R0, #&FC000003		;R4
   NOP					;R1
   NOP					;R2
 #endif
 LDR     R1, _codelet_R1-codelet_PC	;R3
 ORR     R1, R0, R1			;R4
 LDR     R0, _codelet_R1-4		;R1 tmp1
 ANDEQ   R0, R0, R1			;R2 original instruction
 LDR     R1, _codelet_R1-8		;R3 tmp2
 DCD     B_blank			;R4 B <original address + 4>


 ._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 flags / CPU mode
   AND     R0, R0, #%11 << 6		;R1 IRQ / FIQ
   ORR     R0, R2, R0, LSL #20		;R2
 #endif
 #if compile_RO == 400
   MOV     R0, PC			;R3
   AND     R0, R0, #&FC000003		;R4
   NOP					;R1
   NOP					;R2
 #endif
 LDR     R2, _codelet_R2-codelet_PC	;R3
 ORR     R2, R0, R2			;R4
 LDR     R0, _codelet_R2-4		;R1 tmp1
 ANDEQ   R0, R0, R2			;R2 original instruction
 LDR     R2, _codelet_R2-8		;R3 tmp2
 DCD     B_blank			;R4 B <original address + 4>


 ._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 flags / CPU mode
   AND     R0, R0, #%11 << 6		;R1 IRQ / FIQ
   ORR     R0, R3, R0, LSL #20		;R2
 #endif
 #if compile_RO == 400
   MOV     R0, PC			;R3
   AND     R0, R0, #&FC000003		;R4
   NOP					;R1
   NOP					;R2
 #endif
 LDR     R3, _codelet_R3-codelet_PC	;R3
 ORR     R3, R0, R3			;R4
 LDR     R0, _codelet_R3-4		;R1 tmp1
 ANDEQ   R0, R0, R3			;R2 original instruction
 LDR     R3, _codelet_R3-8		;R3 tmp2
 DCD     B_blank			;R4 B <original address + 4>



;Entry:
; R1 - Rd
; R5 - tmp register to use
; R7 - original instruction address + 8

; MOV{S} Rx, PC

.i_MOV_Rd_PC
 STMFD   R13!, {R8-R9}
 MOV     R9, R1, LSR #12		;R9=Rd

 #if compile_RO > 400
   CODELET 9
 #endif
 #if compile_RO == 400
   CODELET 7
 #endif

 ADR     R8, _codelet

 LDR     R1, [R8], #4			;get replacement instructions
 ORR     R1, R1, R5, LSL #12		;STR Rx,_
 STR     R1, [R6], #4

 #if compile_RO > 400
   LDMIA   R8!, {R1-R4}
					;-------- 1st instruction --------
   ORR     R1, R1, R9, LSL #12		;MRS Rd, _
					;-------- 2nd instruction --------
   ORR     R2, R2, R5, LSL #12		;AND Rx, _
   ORR     R2, R2, R9, LSL #16		;AND Rx, Rd, _
					;-------- 3rd instruction --------
   ORR     R3, R3, R9, LSL #12		;AND Rd, _
   ORR     R3, R3, R9, LSL #16		;AND Rd, Rd, _
					;-------- 4th instruction --------
   ORR     R4, R4, R9, LSL #12		;ORR Rd, _
   ORR     R4, R4, R5, LSL #16		;ORR Rd, Rx
   ORR     R4, R4, R9			;ORR Rd, Rx, Rd, _
   STMIA   R6!, {R1-R4}
 #endif
 #if compile_RO == 400
   LDMIA   R8!, {R1-R2}
					;-------- 1st instruction --------
   ORR     R1, R1, R9, LSL #12		;MOV Rd, _
					;-------- 2nd instruction --------
   ORR     R2, R2, R9, LSL #12		;AND Rd, _
   ORR     R2, R2, R9, LSL #16		;AND Rd, Rd, _
   STMIA   R6!, {R1-R2}
 #endif

 LDMIA   R8, {R1-R4}
					;-------- 1st instruction --------
 ORR     R1, R1, R5, LSL #12		;LDR Rx, _
					;-------- 2nd instruction --------
 AND     R0, R0, #1 << 20
 ORR     R2, R2, R9, LSL #12		;ORR Rd, _
 ORR     R2, R2, R9, LSL #16		;ORR Rd, Rd, _
 ORR     R2, R2, R5			;ORR Rd, Rd, Rx
 ORR     R2, R2, R0			;ORR{S} Rd, Rd, Rx
					;-------- 3rd instruction --------
 ORR     R3, R3, R5, LSL #12		;LDR Rx, _
					;-------- 4th instruction --------
 SUB     R8, R14, R6
 SUB     R8, R8, #8 + (4 * 4)		;correct for offset and prefetch
 BIC     R8, R8, #%111111 << 26
 ORR     R4, R4, R8, LSR #2		;B <original address + 4>

 STMIA   R6, {R1-R4}

 LDMFD   R13!, {R8-R9}
B       i_instruction_handled


 ._codelet
 STR     R0, _codelet-4			;R1 STR Rx, tmp1
 #if compile_RO > 400
   MRS     R0, CPSR			;R1 MRS Rd, CPSR
   AND     R0, R0, #&F0000003		;R2 AND Rx, Rd, #&F0000003
   AND     R0, R0, #%11 << 6		;R3 AND Rd, Rd, #%11 << 6
   ORR     R0, R0, R0, LSL #20		;R4 ORR Rd, Rx, Rd, LSL #20
 #endif
 #if compile_RO == 400
   MOV     R0, PC			;R1 MOV Rd, PC
   AND     R0, R0, #&FC000003		;R2 AND Rd, Rd, #&FC000003
 #endif
 LDR     R0, _codelet-codelet_PC	;R1 LDR Rx, _PC
 ORR     R0, R0, R0			;R2 ORR{S} Rd, Rd, Rx
 LDR     R0, _codelet-4			;R3 LDR Rx, tmp1
 DCD     B_blank			;R4 B <original address + 4>
					;32bit - 9 instructions
					;26bit - 7 instructions




;i_MOV_PC_in_Rd
;--------------
;MOV PC, ...

.i_MOV_PC_in_Rd
 MOV     R5, #0
 TST     R0, #1 << 25			;is Op2 a register?
 BNE     _immediate

 AND     R2, R0, #%1111			;YES R2=Rm
 TEQ     R2, #PC_reg			;is it MOV{S} PC, PC
 ANDEQ   R0, R0, #OP_condition		;YES
 ORREQ   R0, R0, #&0A000000		; |   change to B <PC>
 BEQ     i_copy_and_exit		; |+  and exit

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

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

 ._immediate
 TST     R0, #1 << 20			;MOVS ?
 BNE     i_MOVS_PC_in_Rd		;YES

 CODELET_REUSE 7

 BIC     R0, R0, #%1111 << 12		;clear PC from Rd

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

 LDMIA   R5!, {R1-R4}
					;-------- 1st instruction --------
 ORR     R2, R2, R0			;MOV Rx, Rm, {, <shift> ...}
 STMIA   R6!, {R1-R4}


 LDMIA   R5!, {R1-R3}
 STMIA   R6!, {R1-R3}
B       i_und_exit


 ._codelet_R0
 STR     R0, _codelet_R0-4		;R1 tmp1
 MOVEQ   R0, R0				;R2 MOV R0, Rm {, <shift> ...}
 ADD     R0, R0, #jit_code_start	;R3 correct
 BIC     R0, R0, #&FC000003		;R4
 STR     R0, _codelet_R0-8		;R1 tmp2
 LDR     R0, _codelet_R0-4		;R2 tmp1
 LDR     PC, _codelet_R0-8		;R3 tmp2
					;7 instructions

 ._codelet_R1
 STR     R1, _codelet_R1-4		;R1 tmp1
 MOVEQ   R1, R0				;R2 MOV R1, Rm {, <shift> ...}
 ADD     R1, R1, #jit_code_start	;R3 correct
 BIC     R1, R1, #&FC000003		;R4
 STR     R1, _codelet_R1-8		;R1 tmp2
 LDR     R1, _codelet_R1-4		;R2 tmp1
 LDR     PC, _codelet_R1-8		;R3 tmp2


 ._codelet_R2
 STR     R2, _codelet_R2-4		;R1 tmp1
 MOVEQ   R2, R0				;R2 MOV R2, Rm {, <shift> ...}
 ADD     R2, R2, #jit_code_start	;R3 correct
 BIC     R2, R2, #&FC000003		;R4
 STR     R2, _codelet_R2-8		;R1 tmp2
 LDR     R2, _codelet_R2-4		;R2 tmp1
 LDR     PC, _codelet_R2-8		;R3 tmp2




;i_MOVS_PC_in_Rd
;---------------
;MOVS PC, Rn, ...

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

 BIC     R0, R0, #1 << 20		;clear S
 BIC     R0, R0, #%1111 << 12		;clear PC from Rd

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

 LDMIA   R5!, {R1-R4}
					;-------- 2nd instruction --------
 ORR     R2, R2, R0			;add to instruction
					;---------------------------------
 STMIA   R6!, {R1-R4}


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


 #if compile_RO > 400
   LDMIA   R5!, {R0-R4}
   STMIA   R6!, {R0-R4}
 #endif
 #if compile_RO > 400 AND compile_IOMD == 0
   LDMIA   R5!, {R0, R2-R3}
   STMIA   R6!, {R0, R2-R3}
 #endif
 #if compile_RO > 400 AND compile_IOMD == 1
   LDMIA   R5!, {R0-R3}
   STMIA   R6!, {R0-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		;R1 tmp1
 MOVEQ   R0, R0				;R2 MOV R0, Rm {, <shift> ...}
 ADD     R0, R0, #jit_code_start	;R3 correct
 STR     R0, _codelet_R0-8		;R4 tmp2
 BIC     R0, R0, #&FC000003		;R1 clear flags, IRQ/FIQ and CPU mode
 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
					;26bit - 11 instructions
					;32bit - 15 instructions (+1 IOMD)

 ._codelet_R1
 STR     R1, _codelet_R1-4		;R1 tmp1
 MOVEQ   R1, R0				;R2 MOV R1, Rm {, <shift> ...}
 ADD     R1, R1, #jit_code_start	;R3 correct
 STR     R1, _codelet_R1-8		;R4 tmp2
 BIC     R1, R1, #&FC000003		;R1 clear flags, IRQ/FIQ and CPU mode
 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		;R4 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		;R1 tmp1
 MOVEQ   R2, R0				;R2 MOV R2, Rm {, <shift> ...}
 ADD     R2, R2, #jit_code_start	;R3 correct
 STR     R2, _codelet_R2-8		;R4 tmp2
 BIC     R2, R2, #&FC000003		;R1 clear flags, IRQ/FIQ and CPU mode
 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		;R4 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
