;padding to work around compiler bug



#if JIT_instruction_trace == 1
.instruction_trace_codelet
 ._codelet
 STR     R0, _codelet-(codelet_struct.codelet - codelet_struct.tmp3)	;preserve R0-R3
 STR     R1, _codelet-(codelet_struct.codelet - codelet_struct.tmp2)
 STR     R2, _codelet-(codelet_struct.codelet - codelet_struct.tmp1)
 LDR     R0, _codelet-(codelet_struct.codelet - codelet_struct.trace)	;pointer to trace buffer
 LDR     R1, [R0, #-4]
 LDR     R2, _codelet-codelet_PC
 SUB     R2, R2, #8			;R14
 STR     R2, [R1], #4			;R0
 BIC     R1, R1, #jit_trace_buffer_size
 STR     R1, [R0, #-4]
 ADR     R0, _codelet-(codelet_struct.codelet - codelet_struct.tmp3)
 LDMIA   R0, {R0-R2}			;tmp3, tmp2, tmp1
 B       _codelet_end + (codelet_struct.codelet - codelet_struct.source)	;R5
 ._codelet_end
 #set JIT_IT_codelet_size = _codelet_end-_codelet + codelet_struct.codelet-codelet_struct.source
#endif




;DID_JIT_ENTER_HERE
;------------------
;checks if the JIT was entered on this instruction
;
;Exit:
; R4, R5 - Corrupted
; EQ if true

MACRO DID_JIT_ENTER_HERE$cc
{
 LDR$cc  R4, [R13, #UND_exit_PC]	;read JIT entry address
 SUB$cc  R5, R14, #8
 TEQ$cc  R4, R5				;was the JIT entered on this instr?
}




;PREDICT_BRANCH
;--------------
;Adds a JIT appspace address to the branch prediction table
;
;Entry:
; Rx - address in JIT appspace to follow
;
;Exit:
; R1, R5 - corrupted

MACRO PREDICT_BRANCH Rx:R
{
 LDR     R5, branch_to_jit_no_condition	;JIT entry instruction
 LDR     R1, [Rx]			;get instruction at Branch
 TEQ     R5, R1, LSL #4			;is it a Hypercall?
 BNE     _ignore			;NO, ignore it then

 ADR     R5, JIT_branch_prediction_table
 LDR     R1, [R5, #-4]			;get index
 TEQ     R1, #JIT_branch_prediction_max	;is the BPT full?
 STRNE   Rx, [R5, R1, LSL #2]		;NO, store in BPT
 ADDNE   R1, R1, #1			; |   go to next table entry
 STRNE   R1, [R5, #-4]			; |+  store back
 ._ignore
}




;CACHEOP_CLEAN_APPSPACE_TO_HERE
;------------------------------
;cleans the D cache from the start of the current code block being processed
;
;Entry:
; R14 - PC+8 due to pipelining
;
;Exit:
; R0-R4 - corrupted

MACRO CACHEOP_CLEAN_APPSPACE_TO_HERE
{
 LDR     R0, JIT_started_at		;start address to clean
 SUB     R1, R14, #4			;last address to clean
 BL      CACHEOP_CLEAN_D_INVALIDATE_I	;clean range
}




;CACHEOP_INVALIDATE_TLB_ENTRY
;----------------------------
;Invalidated a TLB entry
;
;Syntax: CACHEOP_INVALIDATE_TLB_ENTRY{NE/EQ/CC/CS/LO/HS} Rx

MACRO CACHEOP_INVALIDATE_TLB_ENTRY$cc Rx:R		;corrupts R0, R14, flags
{
 LDR$cc  R14, DA_mask
 BIC$cc  R0, Rx, R14
 MOV$cc  R14, PC			;return to us
 LDR$cc  PC, MMUControl_ARMop5
}




;CACHEOP_CLEAN_CODELET
;---------------------
;Ensures the D cache entries are cleaned from the last codelet created
;
;Exit:
; R0-R5 - Corrupted

MACRO CACHEOP_CLEAN_CODELET
{
 ADR     R0, codelet_cache_flush
 LDMIA   R0, {R0, R1}
 TEQ     R0, #0
 ADD     R1, R1, R0			;R1=end address
 MOV     R5, R14			;preserve R14
 BLNE    CACHEOP_CLEAN_D_INVALIDATE_I
 MOV     R14, R5			;preserve R14
}




;CODELET_BL <size in words>
;
;Entry:
; R0 - original instruction
; R4 - address being branched too
;
;Exit:
; R1, R2, R4 - corrupted
; R6     - codelet address

MACRO CODELET_BL size:I
{
 #if JIT_codelet_reuse == 1
   MOV     R1, #1			;codelet can be reused
 #endif

 STR     R0, [R13, #-4]!		;preserve R0
					;fake an instruction so we can reuse
					;the codelet for branches to the same
					;address
 MOV     R0, #&EB << 24			;BL
 ORR     R0, R0, R4, LSR #2		;R0=BL <absolute address>

 MOV     R6, #size << 2
 #if JIT_instruction_trace == 1
   STMFD   R13!, {R3, R5, R8-R9, R14}
   BL      allocate_codelet
   TEQ     R1, #0			;are we reusing an existing codelet?
   LDRNE   R8, instruction_trace_ptr	;NO
   STRNE   R8, [R6, #codelet_struct.trace - codelet_struct.codelet]
   MOVNE   R9, R6
   ADRNE   R8, instruction_trace_codelet
   LDMNEIA R8!, {R0-R5, R14}
   STMNEIA R9!, {R0-R5, R14}
   LDMNEIA R8!, {R0-R5}
   STMNEIA R9!, {R0-R5, R7}
   LDMFD   R13!, {R3, R5, R8-R9, R14}
 #endif
 #if JIT_instruction_trace == 0
   MOV     R2, R14			;preserve R14
   BL      allocate_codelet
   MOV     R14, R2			;preserve R14
 #endif
					;---------------------------------
 LDR     R0, [R13], #4			;preserve R0
 AND     R4, R0, #%11111111 << 24	;R4=BLxx 0
 SUB     R2, R6, R14			;R5=offset from instruction to codelet
 BIC     R2, R2, #%111111 << 26
 ORR     R4, R4, R2, LSR #2		;BL <codelet>
 STR     R4, [R14, #-8]			;change original instruction

 #if JIT_instruction_trace == 1
   ADD     R6, R6, #JIT_IT_codelet_size
 #endif
}




;CODELET <size in words>

;Entry:
; R0 - instruction
; R7 - original instruction address + 8

;Exit:
; R1, R4 - corrupted
; R6     - codelet address

MACRO CODELET size:I
{
 #if JIT_codelet_reuse == 1
   MOV     R1, #0			;codelet cant be reused
 #endif

 MOV     R6, #size << 2
 #if JIT_instruction_trace == 1
   STMFD   R13!, {R0, R2-R3, R5, R8-R9, R14}
   BL      allocate_codelet
   LDR     R8, instruction_trace_ptr
   STR     R8, [R6, #codelet_struct.trace - codelet_struct.codelet]
   MOV     R9, R6
   ADR     R8, instruction_trace_codelet
   LDMIA   R8!, {R0-R5, R14}
   STMIA   R9!, {R0-R5, R14}
   LDMIA   R8!, {R0-R5}
   STMIA   R9!, {R0-R5, R7}
   LDMFD   R13!, {R0, R2-R3, R5, R8-R9, R14}
 #endif
 #if JIT_instruction_trace == 0
   MOV     R4, R14			;preserve R14
   BL      allocate_codelet
   MOV     R14, R4			;preserve R14
 #endif
					;---------------------------------
 AND     R4, R0, #%1111 << 28		;get condition
 ORR     R4, R4, #%1010 << 24		;R4=Bxx 0
 SUB     R1, R6, R14			;R5=offset from instruction to codelet
 BIC     R1, R1, #%111111 << 26
 ORR     R4, R4, R1, LSR #2		;B <codelet>
 STR     R4, [R14, #-8]			;change original instruction
 #if JIT_instruction_trace == 1
   ADD     R6, R6, #JIT_IT_codelet_size
 #endif
}




;CODELET_REUSE <size in words>
;
;Entry:
; R0 - instruction
; R7 - original instruction address + 8
;
;Exit:
; R1, R4 - corrupted
; R6     - codelet address

MACRO CODELET_REUSE size:I
{
 #if JIT_codelet_reuse == 1
   MOV     R1, #1			;codelet can be reused
 #endif

 MOV     R6, #size << 2
 MOV     R4, R14			;preserve R14
 BL      allocate_codelet
 MOV     R14, R4			;preserve R14
 TEQ     R1, #0				;are we reusing an existing codelet?
 #if JIT_instruction_trace == 1
   STMNEFD R13!, {R0, R2-R3, R5, R8-R9, R14}	;NO
   LDRNE   R8, instruction_trace_ptr
   STRNE   R8, [R6, #codelet_struct.trace - codelet_struct.codelet]
   MOVNE   R9, R6
   ADRNE   R8, instruction_trace_codelet
   LDMNEIA R8!, {R0-R5, R14}
   STMNEIA R9!, {R0-R5, R14}
   LDMNEIA R8!, {R0-R5}
   STMNEIA R9!, {R0-R5, R7}
   LDMNEFD R13!, {R0, R2-R3, R5, R8-R9, R14}
 #endif
					;---------------------------------
					;EQ set if using existing codelet
 AND     R4, R0, #OP_condition		;get condition
 #if JIT_codelet_reuse == 1
   BIC     R0, R0, #OP_condition	;clear condition
   ORR     R0, R0, #OP_AL		;change to AL
 #endif
 ORR     R4, R4, #%1010 << 24		;R4=Bxx 0
 SUB     R1, R6, R14			;R5=offset from instruction to codelet
 BIC     R1, R1, #%111111 << 26
 ORR     R4, R4, R1, LSR #2		;B <codelet>
 STR     R4, [R14, #-8]			;change original instruction
 BEQ     i_und_exit_no_codelet		;using an existing codelet, exit JIT

 #if JIT_instruction_trace == 1
   ADD     R6, R6, #JIT_IT_codelet_size
 #endif
}
