;Entry:
;R0  = instruction
;R1  = Rd << 12
;R2  = Rn << 16
;R3  = Rm if appropriate eg. STR R0, [R1, R2] or STR R0, [R1], R2
;R7  = original instruction address + 8
;R14 = re-interpreted instruction address + 8

ALIGN   32, 4
.i_STR
#if compile_RO > 450
 TEQ     R1, R2, LSR #4			;Rd=Rn?
 BNE     _rd_rn_different		;NO

 AND     R3, R0, #%1001 << 21		;P__W
 CMP     R3, #%1000 << 21
 BEQ     _rd_rn_different		;STR{B} R0,[R0,#<op2>]
 BHI     i_STR_Rd_Rn_postindexed	;STR{B} R0,[R0,#<op2>]!
					;STR{B}T R0,[R0],<op2>
					;STR{B} R0,[R0],<op2>
 TST     R0, #1 << 25			;is Op2 a register?
 BNE     i_STR_Rd_Rn_postindexed	;YES, needs a codelet
 MOVS    R1, R0, LSL #32 - 11		;is it STR Rd,[Rn],#0 ?
 ORREQ   R0, R0, #1 << 24		;YES, ensure pre-indexed
 BICEQ   R0, R0, #1 << 21		; |+  ensure no writeback
 BNE     i_STR_Rd_Rn_postindexed	;NO, needs a codelet

 ._rd_rn_different
#endif
 TEQ     R2, #PC_reg << 16		;Rn = PC?
 TEQNE   R1, #PC_reg << 12		;NO, Rd = PC?
 BNE     i_copy_instruction		;NO

 BIC     R4, R0, #%1111 << 12		;check for pipeline write
 BIC     R4, R4, #%1111 << 28		;clear condition
 EORS    R4, R4, #&50F0004		;STR Rd,[PC,#-4] ?
 BNE     _not_pipeline_write		;NO

 MOV     R0, #&1A << 20			;YES,
 LDR     R4, [R7, #-4]			; |   get the pipelined instr.
 BIC     R4, R4, #%1111 << 28		; |   clear condition
 MOV     R5, #&B000000			; |   check for next instr.
 SUB     R5, R5, #2			; |   being xAFFFFFE
 TEQ     R4, R5				; |   for B PC-4
 STREQ   R0, [R14, #-8]			; |   YES, NOP two instrucions
 ADDEQ   R14, R14, #4			; |    |+ fixes Carnage Inc
 B       i_copy_instruction		; |+  NO, NOP instruction

 ._not_pipeline_write
 TEQ     R1, #PC_reg << 12		;is PC in Rd?
 BNE     i_LDR_STR_Rn			;NO, must be: LDR R0,[PC ...

; STR PC, [Rn, ...
; STR PC, [PC, ...

.i_STR_PC_in_Rd
 CODELET 13

 STMFD   R13!, {R8-R9}

 MOV     R8, #0				;find spare Rx
 TEQ     R3, R8				;is register being used
 TEQNE   R2, R8, LSL #16
 ADDEQ   R8, R8, #1			;YES, use next register
 TEQ     R3, R8				;is register being used
 TEQNE   R2, R8, LSL #16
 ADDEQ   R8, R8, #1			;YES, use next register

 ADR     R5, _codelet

 LDRB    R1, JIT_ARM4
 TEQ     R1, #0				;is JIT ARMv3 or ARMv4
 MOVNE   R1, R7				;ARMv4 - PC+8
 ADDEQ   R1, R7, #4			;ARMv3 - PC+12
					;R1=PC - written to tmp1
 TEQ     R2, #PC_reg << 16		;is Rn PC? ie: STR PC, [PC ...
 MOVNE   R9, R2, LSR #16		;NO, R9=Rn
 BNE     _not_STR_PC_PC

 BIC     R0, R0, #%1111 << 16		;YES, clear Rn
 TEQ     R8, #0				;is Rx R0?
 MOVEQ   R9, #1				;YES, use R1
 MOVNE   R9, #0				;NO,  use R0
 ORR     R0, R0, R9, LSL #16
 TEQ     R2, #PC_reg << 16		;is Rn PC? ie: STR PC, [PC ...
					;EQ if: STR PC, [PC
 ._not_STR_PC_PC
 LDMIA   R5!, {R2-R4}
					;------------ set var1 -----------
 SUB     R6, R6, #4			;write to var1
					;-------- 2nd instruction --------
 ORR     R2, R2, R9, LSL #12		;add Rd into instruction
					;-------- 3rd instruction --------
 ORR     R3, R3, R8, LSL #12		;add Rd into instruction
					;-------- 4rd instruction --------
 ORR     R4, R4, R8, LSL #12		;add Rd into instruction
 STMIA   R6!, {R1-R4}

 LDMIA   R5!, {R1-R4}
					;-------- 1st instruction --------
 ORR     R1, R1, R9, LSL #12		;add Rd into instruction
 ORR     R1, R1, R8, LSL #16		;add Rn into instruction
					;-------- 2nd instruction --------
 ORR     R2, R2, R8, LSL #12		;add Rd into instruction
 ORR     R2, R2, R8, LSL #16		;add Rn into instruction
					;-------- 3rd instruction --------
 ORRNE   R3, R3, R9, LSL #12		;add Rd into instruction: STR PC,[Rn
 ORREQ   R3, R3, R8, LSL #12		;add Rd into instruction: STR PC,[PC
 ORR     R3, R3, R9, LSL #16		;add Rn into instruction
 ORR     R3, R3, R8
					;-------- 4rd instruction --------
 ORRNE   R4, R4, R8, LSL #12		;add Rd into instruction: STR PC,[Rn
 ORREQ   R4, R4, R9, LSL #12		;add Rd into instruction: STR PC,[PC
 STMIA   R6!, {R1-R4}


 LDMNEIA R5!, {R1-R3}			;STR PC,[Rn,
 LDRNE   R3, [R5], #4
 LDMEQIA R5!, {R1-R2}			;STR PC,[PC,
 LDMEQIA R5!, {R2-R3}

					;-------- 1st instruction --------
 ORR     R1, R1, R8, LSL #12		;ORR Rx, __, __
 ORR     R1, R1, R8, LSL #16		;ORR Rx, Rx, __
 ORR     R1, R1, R9			;ORR Rx, Rx, Rn
					;-------- 2nd instruction --------
 ORR     R2, R2, R9, LSL #12		;LDR Rn, ...
					;-------- 3rd instruction --------
 AND     R4, R0, #%1111111111 << 16	;R4=IPUBW<Rn>
 ORR     R3, R3, R8, LSL #12		;STR{B}{T} Rx, ...
 ORR     R3, R3, R4			;STR{B}{T} Rx, [Rn, ...
 MOV     R4, R0, LSL #32 - 12		;R4=Op2
 ORR     R3, R3, R4, LSR #32 - 12	;add Op2 into instruction: STR PC,[Rn

 STMIA   R6!, {R1-R3}


 LDMIA   R5!, {R1-R3}
					;-------- 1st instruction --------
 ORREQ   R1, R1, R9, LSL #12		;(optional STR PC,[PC...) LDR Rn, _codelet-8
					;-------- 2nd instruction --------
 ORR     R2, R2, R8, LSL #12		;LDR Rn, _codelet-12
 SUBNE   R2, R2, #4			;correct
					;-------- 3rd instruction --------
 SUB     R5, R14, R6
 SUBEQ   R5, R5, #8 + (3 * 4)		;correct for offset and prefetch
 SUBNE   R5, R5, #8 + (2 * 4)		;correct for offset and prefetch
 BIC     R5, R5, #%111111 << 26
 ORR     R3, R3, R5, LSR #2		;B <codelet>
 STMNEIA R6!, {R2-R3}
 STMEQIA R6!, {R1-R3}

 LDMFD   R13!, {R8-R9}
B       i_instruction_handled


 ._codelet
 STR     R0, _codelet-8			;R2 STR Rn, tmp2
 STR     R0, _codelet-12		;R3 STR Rx, tmp3
 MRS     R0, CPSR			;R4 MRS Rx
 AND     R0, R0, #&F0000003		;R1 AND Rn, Rx flags / CPU mode
 AND     R0, R0, #%11 << 6		;R2 AND Rx, Rx - IRQ / FIQ
 ORR     R0, R0, R0, LSL #20		;R3 ORR Rn, Rn, Rx
 LDR     R0, _codelet-4			;R4 LDR Rx, tmp1

 ORR     R0, R0, R0			;R1 ORR Rx, Rx, Rn
 LDR     R0, _codelet-8			;R2 (optional STR PC,[Rx...) LDR Rn, tmp2
 LDR     R0, _codelet-codelet_struct.codelet+codelet_struct.source+4	;R2 (optional STR PC,[PC...) LDR Rn, codelet_struct.source
 DCD     %11100100000000000000 << 12	;R3 STR Rx, [Rn, ...

 LDR     R0, _codelet-8+4		;R1 (optional STR PC,[PC...) LDR Rn, tmp2
 LDR     R0, _codelet-12+4		;R2 LDR Rx, tmp3
 DCD     B_blank			;R3 B <original address + 4>
					;13 instructions




#if compile_RO > 450
;STR R0,[R0],#4		!R0=R0		R0+=4
;STR R0,[R0],R1		!R0=R0		R0+=R1
;STR R0,[R0,#4]!	!(R0+4)=R0	R0+=4
;STR R0,[R0,R1]!	!(R0+R1)=R0	R0+=R1

.i_STR_Rd_Rn_postindexed
 CODELET 4

 AND     R1, R0, #%1111 << 12		;R1=Rd
 TST     R0, #1 << 23			;add or subtract
 ADRNE   R5, _codelet_add
 ADREQ   R5, _codelet_sub
 LDMIA   R5!, {R2-R4}
					;1st instruction
 ORR     R2, R2, R1			;STR Rd, [__, #0]
 ORR     R2, R2, R1, LSL #4		;STR Rd, [Rd, #0]
 TST     R0, #1 << 22			;B or W?
 ORRNE   R2, R2, #1 << 22
 TST     R0, #1 << 24			;pre-indexed?
 STRNE   R7, [R13, #-4]!		;YES,
 MOVNE   R7, R0, LSL #32 - 11		; |  R7=<op2>
 ORRNE   R2, R2, R7, LSR #32 - 11	; |  STR Rd,[Rd,<op2>]
 ANDNE   R7, R0, #1 << 25		; |  R7=I
 ORRNE   R2, R2, R7			; |+ STR Rd,[Rd,Rm] if not an immed
 LDRNE   R7, [R13], #4
					;2nd instruction
 ORR     R3, R3, R1			;ADD/SUB Rd, __, __
 ORR     R3, R3, R1, LSL #4		;ADD/SUB Rd, Rd, __
 TST     R0, #1 << 25			;immediate?
 MOV     R0, R0, LSL #32 - 11
 ORRNE   R3, R3, R0, LSR #32 - 11	;NO, ADD/SUB Rd, Rd, Rm
 ORREQ   R3, R3, #1 << 25		;YES, ADD/SUB Rd, Rd, #<immed>
					;3rd instruction
 ORR     R4, R4, R1			;ADD/SUB Rd, __, __
 ORR     R4, R4, R1, LSL #4		;ADD/SUB Rd, Rd, __
 ORREQ   R4, R4, R0, LSR #32 - 4	;top 4 bits of immediate
 ANDEQ   R0, R0, #%000011111111 << (32 - 11)
 ORREQ   R3, R3, R0, LSR #32 - 11	;bottom 8 bits of immediate

 STMIA   R6!, {R2-R4}

 LDR     R3, [R5]			;4th instruction
 SUB     R5, R14, R6
 SUB     R5, R5, #8 + 4			;correct for offset and prefetch
 BIC     R5, R5, #%111111 << 26
 ORR     R3, R3, R5, LSR #2		;B <original address + 4>
 STR     R3, [R6], #4
B       i_instruction_handled


 ._codelet_add
 STR     R0, [R0, #0]			;STR{B} Rd, [Rd, #0]
 ADD     R0, R0, R0			;ADD Rd, Rd, <op2>
 DCD     &E2800C00			;ADD Rd, Rd, #<immed> << 8
 DCD     B_blank			;B <original address + 4>

 ._codelet_sub
 STR     R0, [R0, #0]			;STR{B} Rd, [Rd, #0]
 SUB     R0, R0, R0			;SUB Rd, Rd, <op2>
 DCD     &E2400C00			;SUB Rd, Rd, #<immed> << 8
 DCD     B_blank			;B <original address + 4>
#endif