;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     R2, R1				;preserve R1/R4 as CODELET corrupt them
 MOV     R5, R4

 CODELET 12

 MOV     R1, R2
 MOV     R4, R5

 MOV     R3, R1, LSR #4			;ignore Rs if it's not there

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

 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

 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 --------
 BIC     R0, R0, #%1111			;clear PC from Rm
 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
 STR     R1, _codelet_R0-8		;R2
 #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
 ANDEQ   R0, R0, R0			;R2 original instruction
 LDR     R0, _codelet_R0-4		;R3
 DCD     B_blank			;R4 B <original address + 4>
					;12 instructions

 ._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 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
 ANDEQ   R0, R0, R1			;R2 original instruction
 LDR     R1, _codelet_R1-8		;R3
 DCD     B_blank			;R4 B <original address + 4>


 ._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 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
 ANDEQ   R0, R0, R2			;R2 original instruction
 LDR     R2, _codelet_R2-8		;R3
 DCD     B_blank			;R4 B <original address + 4>


 ._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 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
 ANDEQ   R0, R0, R3			;R2 original instruction
 LDR     R3, _codelet_R3-8		;R3
 DCD     B_blank			;R4 B <original address + 4>





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

 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}
 STMIA   R6!, {R1-R4}


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


 LDMIA   R5!, {R0-R4}
 STMIA   R6!, {R0-R4}
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-4		;R4
 MOVEQ   R0, R0				;R1 MOV R0, Rm {, <shift> ...}
 BIC     R0, R0, #&FC000003		;R2
 CMP     R0, #jit_appspace_end		;R3 jumping to appspace?
 ADDLO   R0, R0, #jit_code_start	;R4 YES, correct
 STR     R0, _codelet_R0-12		;R0
 LDR     R0, _codelet_R0-8		;R1
 MSR     CPSR_f, R0			;R2
 LDR     R0, _codelet_R0-4		;R3
 LDR     PC, _codelet_R0-12		;R4
					;13 instructions

 ._codelet_R1
 STR     R1, _codelet_R1-4		;R1
 MRS     R1, CPSR			;R2
 STR     R1, _codelet_R1-8		;R3
 LDR     R1, _codelet_R1-4		;R4
 MOVEQ   R1, R0				;R1 MOV R1, Rm {, <shift> ...}
 BIC     R1, R1, #&FC000003		;R2
 CMP     R1, #jit_appspace_end		;R3 jumping to appspace?
 ADDLO   R1, R1, #jit_code_start	;R4 YES, correct
 STR     R1, _codelet_R1-12		;R0
 LDR     R1, _codelet_R1-8		;R1
 MSR     CPSR_f, R1			;R2
 LDR     R1, _codelet_R1-4		;R3
 LDR     PC, _codelet_R1-12		;R4


 ._codelet_R2
 STR     R2, _codelet_R2-4		;R1
 MRS     R2, CPSR			;R2
 STR     R2, _codelet_R2-8		;R3
 LDR     R2, _codelet_R2-4		;R4
 MOVEQ   R2, R0				;R1 MOV R2, Rm {, <shift> ...}
 BIC     R2, R2, #&FC000003		;R2
 CMP     R2, #jit_appspace_end		;R3 jumping to appspace?
 ADDLO   R2, R2, #jit_code_start	;R4 YES, correct
 STR     R2, _codelet_R2-12		;R0
 LDR     R2, _codelet_R2-8		;R1
 MSR     CPSR_f, R2			;R2
 LDR     R2, _codelet_R2-4		;R3
 LDR     PC, _codelet_R2-12		;R4




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

.i_MOVS_PC_in_Rd
 #if compile_RO == 400
   CODELET_REUSE 12
 #endif
 #if compile_RO > 400
   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-R3}
					;-------- 2nd instruction --------
 ORR     R2, R2, R0			;add to instruction
					;---------------------------------
 STMIA   R6!, {R1-R3}


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


 #if compile_RO > 400
   LDMIA   R5!, {R0-R4}
   STMIA   R6!, {R0-R4}
   LDMIA   R5!, {R1-R3}
   STMIA   R6!, {R1-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
 MOVEQ   R0, R0				;R2 MOV R0, Rm {, <shift> ...}
 STR     R0, _codelet_R0-8		;R3
 BIC     R0, R0, #&FC000003		;R0 clear flags, IRQ/FIQ and CPU mode
 CMP     R0, #jit_appspace_end		;R1 jumping to appspace?
 ADDLO   R0, R0, #jit_code_start	;R2 YES, correct
 STR     R0, _codelet_R0-12		;R3
 LDR     R0, _codelet_R0-8		;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		;R4 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-12		;R3
					;26bit - 12 instructions
					;32bit - 16 instructions

 ._codelet_R1
 STR     R1, _codelet_R1-4		;R1
 MOVEQ   R1, R0				;R2 MOV R1, Rm {, <shift> ...}
 STR     R1, _codelet_R1-8		;R3
 BIC     R1, R1, #&FC000003		;R0 clear flags, IRQ/FIQ and CPU mode
 CMP     R1, #jit_appspace_end		;R1 jumping to appspace?
 ADDLO   R1, R1, #jit_code_start	;R2 YES, correct
 STR     R1, _codelet_R1-12		;R3
 LDR     R1, _codelet_R1-8		;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		;R4 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-4		;R2
 LDR     PC, _codelet_R1-12		;R3


 ._codelet_R2
 STR     R2, _codelet_R2-4		;R1
 MOVEQ   R2, R0				;R2 MOV R2, Rm {, <shift> ...}
 STR     R2, _codelet_R2-8		;R3
 BIC     R2, R2, #&FC000003		;R0 clear flags, IRQ/FIQ and CPU mode
 CMP     R2, #jit_appspace_end		;R1 jumping to appspace?
 ADDLO   R2, R2, #jit_code_start	;R2 YES, correct
 STR     R2, _codelet_R2-12		;R3
 LDR     R2, _codelet_R2-8		;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		;R4 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-4		;R2
 LDR     PC, _codelet_R2-12		;R3
