#set dbg_pause_default		= 100		;VSync pause on debug info
#set JIT_max_instructions	= 128		;max instr. to process
#set JIT_branch_prediction_max	= 8		;max B/BL to predict (must
						;be a power of 2 (2,4,8 etc)
#set JIT_SWI_OS_Flag		= 8		;OS we're going to use for
						;  hypervized SWI's
#if compile_RO == 400
  #set c32bit			= 0 << 4	;IOMD below RO5 needs 26bit
#endif
#if compile_RO > 400
  #set c32bit			= 1 << 4	;32bit mode for 32bit OS's
#endif

#set UND_exit_PC		= 8 * 4		;location on stack of exit PC
#set PC_reg			= 15		;PC register
#set PC_reglist			= 1 << 15	;PC register in LDM/STM
#set OP_condition		= %1111 << 28	;ARM OP condition bits
#set OP_AL			= %1110 << 28	;ARM AL condition

.branch_to_jit  MRC P8, 0, R0, C0, C0	;hypercall to enter JIT
.branch_to_jit_no_condition DCD 0	;hypercall to enter JIT << 4



#if JIT_debug == 1
 .breakpoint		DCD jit_code_start - 4
#endif
#if JIT_debug == 1 AND JIT_dump_crash == 1
 .breakpoint_dump	DCB "hostfs::0.$.dump", 0
			ALIGN
#endif



.pass_to_existing_UndInstr_2
 ADD     R14, R14, #4			;correct for prefetch
B       pass_to_existing_UndInstr




;Undefined_Instruction_Vector
;----------------------------
;entry point for JIT
;
;Entry:
; R14	- instruction address + 4
; SPSR	- original CPU mode

 ALIGN   32, 4

 #if compile_RO == 400
  DBD 256
  .und_stack
 #endif


.Undefined_Instruction_Vector
 CMP     R14, #jit_slotsize		;in Application Space?
 BHI     pass_to_existing_UndInstr	;NO, pass call on
 CMP     R14, #jit_appspace_end		;in JIT Application Space?
 BLO     pass_to_existing_UndInstr	;NO, pass call on

					;---------------------------------
					;CHECK FOR COPRO INSTRUCTIONS
 STMFD   R13!, {R0-R1}
 LDR     R0, [R14, #-4]!		;get instruction and correct pre-fetch
 LDR     R1, branch_to_jit_no_condition	;JIT entry instruction
 TEQ     R1, R0, LSL #4			;is it a JIT entry?
 LDMFD   R13!, {R0-R1}
 BNE     pass_to_existing_UndInstr_2	;NO, CoPro then, pass call on
					;---------------------------------
 #if compile_RO == 400
   STR     R13, und_stack - 4		;private stack on 26bit RISCOS
   ADR     R13, und_stack - 4
 #endif
 STMFD   R13!, {R0-R7, R14}		;[R13, #UND_exit_PC] = R14

 SUB     R7, R14, #jit_code_start	;R7=original address
 CMP     R7, #&4000			;illegal address for code?
 BLO     JIT_report_illegal_address	;YES, ADFF5013

 #if JIT_debug == 1
   TEMP    R1
   STR     R12, DAV_r0 + (12 * 4)	;store R12 as we may overwrite it
   LOCK    R1
   LDR     R1, jit_last_instrR
   SUB     R7, R14, #jit_code_start	;R7=original address
   TEQ     R1, R7
   STRNE   R1, jit_prev_instrL

   LDR     R0, breakpoint		;report at breakpoint
   TEQ     R14, R0
   ADDEQ   R14, R14, #8
   MOVEQ   R1, #&D			;ADFF500D
   BEQ     JIT_report_unimplemented_debug	;abort

   LDR     R0, jit_entry_count		;track how many times we're entered
   ADD     R0, R0, #1
   STR     R0, jit_entry_count
 #endif

 TEMP    R0
 MOV     R1, #0
 STR     R1, JIT_processed_counter	;track number of instr. handled
 #if JIT_predictive_branching == 1
   ADR     R2, JIT_branch_prediction_table
   STR     R1, [R2, #-4]		;reset branch prediction table
 #endif

.JIT_next_instruction_branch_prediction
 STR     R14, JIT_started_at		;track so we can clean the cache
 LOCK    R0

.JIT_next_instruction
 #if JIT_debug == 1
   LDR     R0, breakpoint		;report at breakpoint
   TEQ     R14, R0
   BEQ     i_und_exit_hit_limit
 #endif
 #if JIT_instruction_trace == 1
   MOV     R0, #instruction_trace_ptr
   LDR     R2, [R0, #-4]
   STR     R14, [R2], #4
   BIC     R2, R2, #&80000
   STR     R2, [R0, #-4]
 #endif

 LDR     R2, JIT_processed_counter	;how many instr. we've processed
 CMP     R2, #JIT_max_instructions	;is it time to exit?
 BGT     i_und_exit_hit_limit		;YES

 SUB     R7, R14, #jit_code_start	;R7=original address
 LDR     R0, [R14], #8			;get instruction and add prefetch

 #if JIT_debug == 1
   STR     R7, jit_last_instrR
   LDR     R4, jit_instr_count
   ADD     R4, R4, #1
   STR     R4, jit_instr_count
   LDR     R4, jit_instr_interpreted
   ADD     R4, R4, #1
   STR     R4, jit_instr_interpreted
 #endif

 LDR     R1, branch_to_jit_no_condition	;JIT entry instruction
 TEQ     R1, R0, LSL #4			;is it a JIT entry?
 BNE     check_copro			;NO, flush cache and retry
					;------------------------------
					;write protect page
 #if JIT_self_modifying_support == 1
   LDR     R0, L2PT_addr		;ARM710VE-83 / 85
   LDR     R4, subpages_supported
   ADD     R0, R0, R7, LSR #10		;L2PT entry address for page
   TST     R4, #1			;subpages supported?
   ANDNE   R3, R0, #%11			;YES, R3=1KB sub-page
   MOVNE   R3, R3, LSL #1		; |
   MOVNE   R2, #%01 << 4		; |+  R2=AP mask
   BIC     R0, R0, #%11			;align to word
   LDR     R1, [R0, #0]
   BICNE   R2, R1, R2, LSL R3		;YES, user is read-only
   BICEQ   R2, R1, R4, LSR #16		;NO, user is read-only
   TEQ     R1, R2			;is page already read-only?
   #if JIT_self_modifying_support == 1 AND compile_IOMD == 1
     SWPNE   R2, R2, [R0]		;NO, make read only and flush WB
   #endif
   #if JIT_self_modifying_support == 1 AND compile_IOMD == 0
     STRNE   R2, [R0, #0]		;NO, make read only
   #endif
   #if JIT_self_modifying_support == 1 AND JIT_flush_TLB == 1
     MOV     R1, R14			;preserve R14
     CACHEOP_INVALIDATE_TLB_ENTRYNE R7	;invalidate D TLB entry
     MOV     R14, R1			;preserve R14 / fix for 80321 errata 7
   #endif
 #endif
					;------------------------------
 LDR     R1, JIT_fixups			;+fix for 80321 errata 7
 LDR     R0, [R7], #8			;R0=instruction, add prefetch

 #if JIT_detailed_debug == 1
   STR     R0, jit_disassemble_last
   STR     R7, jit_disassemble_last + 4
 #endif

 TEQ     R1, #0				;are there any fixups to action?
 BEQ     _no_fixups			;NO, skip

 SUB     R2, R1, #jit_fixup_table.size - 4
 LDR     R1, [R1, #0]			;get fixup count
 TEQ     R1, #0				;are there any fixups to action?
 BEQ     _no_fixups			;NO, skip
 ._fixup_L1
   ADD     R2, R2, #jit_fixup_table.size
   LDR     R3, [R2, #jit_fixup_table.address]
   TEQ     R3, #0
   BEQ     _fixup_L1

   BIC     R4, R3, #%11			;clear flags
   TEQ     R4, R7			;does this address need replacing?
   LDREQ   R4, [R2, #jit_fixup_table.original] ;YES
   TEQEQ   R4, R0			;does the instruction match?
   BEQ     _fixup_replace		;YES, replace

   SUBS    R1, R1, #1			;any fixups left?
 BNE     _fixup_L1			;YES
 B       _no_fixups			;NO

 ._fixup_replace
 LDR     R0, [R2, #jit_fixup_table.replace] ;YES, replace the instruction
 TST     R3, #jit_fixup_persistent_flag	;is this a persistent replace?
 MOVEQ   R3, #0				;NO
 STREQ   R3, [R2, #jit_fixup_table.address]
 LDREQ   R3, JIT_fixups
 LDREQ   R1, [R3]
 SUBEQ   R1, R1, #1			;reduce fixup count
 STREQ   R1, [R3]

 ._no_fixups
 AND     R4, R0, #OP_condition
 TEQ     R4, #%1111 << 28		;NV?
 MOVEQ   R0, #%1101 << 21		;YES, replace with NOP
 BEQ     i_copy_instruction_handled

#if JIT_debug == 1 AND JIT_report_zeros == 1
 TEQ     R0, #0				;0 usually indicates an illegal
 MOVEQ   R1, #&13			;ADFF5013
 BEQ     JIT_report_unimplemented	;branch, or badly written software
					;in the case of MiG-29
#endif

 AND     R1, R0, #%1111 << 24
 ADD     PC, PC, R1, LSR #24 - 2
 NOP
 B       i_ALU				;0000 ALU / MUL
 B       i_ALU				;0001 ALU / SWP
 B       i_ALU				;0010 ALU
 B       i_ALU				;0011 ALU
 B       i_LDR_STR			;0100 LDR / STR
 B       i_LDR_STR			;0101 LDR / STR
 B       i_LDR_STR			;0110 LDR / STR / Undefined
 B       i_LDR_STR			;0111 LDR / STR / Undefined
 B       i_LDM_STM			;1000 LDM / STM
 B       i_LDM_STM			;1001 LDM / STM
 B       i_B				;1010 B
 B       i_BL				;1011 BL
 B       i_LDF_STF_post_indexed		;1100 Co-pro data transfer
 B       i_LDF_STF			;1101 Co-pro data transfer
 B       i_copro			;1110 Co-pro
 B       i_SWI				;1111 SWI




.check_copro
 #if JIT_debug == 1
   LDR     R4, jit_instr_count
   SUB     R4, R4, #1
   STR     R4, jit_instr_count
   LDR     R4, jit_instr_interpreted
   SUB     R4, R4, #1
   STR     R4, jit_instr_interpreted
 #endif

 AND     R4, R0, #%1111 << 24		;is it a Co-pro instruction?
 TEQ     R4, #%1100 << 24
 TEQNE   R4, #%1101 << 24
 TEQNE   R4, #%1110 << 24
 DID_JIT_ENTER_HEREEQ			;YES, did the JIT enter here?
 BEQ     pass_to_previous_Und		; |+  YES, pass to RISCOS
B       i_und_exit_no_codelet		;NO, continue at branch prediction




.i_instruction_handled
 CACHEOP_CLEAN_CODELET

.i_instruction_handled_no_codelet
 SUB     R14, R14, #4			;go to next instruction
B       JIT_next_instruction




.i_copy_instruction
 #if JIT_debug == 1
   LDR     R4, jit_instr_interpreted
   SUB     R4, R4, #1
   STR     R4, jit_instr_interpreted
 #endif
;fall-thru to i_copy_instruction_handled

;i_copy_instruction_handled
;--------------------------
;Write instruction contained in R0 to JIT appspace and then continue
;processing instructions

.i_copy_instruction_handled
 STR     R0, [R14, #-8]			;copy instruction

 SUB     R14, R14, #4			;go to next instruction
B       JIT_next_instruction




;i_copy_and_exit
;---------------
;Write instruction contained in R0 to JIT appspace and then exit JIT

.i_copy_and_exit
 #if JIT_debug == 1
   LDR     R4, jit_instr_interpreted
   SUB     R4, R4, #1
   STR     R4, jit_instr_interpreted
 #endif
;fall-thru to i_copy_and_exit_handled


;i_copy_and_exit_handled
;-----------------------
;Write instruction contained in R0 to JIT appspace and then  exit JIT

.i_copy_and_exit_handled
 STR     R0, [R14, #-8]			;copy instruction
 B       i_und_exit_no_codelet




;JIT_branch_prediction
;---------------------
;follow predicted branch
;
;Entry:
; R1 - updated BPT index to write back
; R6 - address to follow

#if JIT_predictive_branching == 1
.JIT_branch_prediction
 STR     R1, [R7, #-4]			;update BPT index

 CACHEOP_CLEAN_APPSPACE_TO_HERE		;clean appspace to here
 MOV     R14, R6			;and start processing

B       JIT_next_instruction_branch_prediction
#endif



;i_und_exit
;----------
;Exit JIT cleaning a codelet that's just been written

.i_und_exit
 CACHEOP_CLEAN_CODELET			;clean last codelet from D cache

;fall-thru to i_und_exit_no_codelet


;i_und_exit_no_codelet
;---------------------
;Exit JIT, no codelet to clean

.i_und_exit_no_codelet
					;---------------------------------
					;BRANCH PREDICTION
					;---------------------------------
#if JIT_predictive_branching == 1
 ADR     R7, JIT_branch_prediction_table
 LDR     R1, [R7, #-4]			;get current index pointer
 LDR     R4, branch_to_jit_no_condition	;JIT entry instruction
 ._L1
   SUBS    R1, R1, #1			;last BPT entry?
   BMI     i_und_exit_hit_limit		;YES

   LDR     R6, [R7, R1, LSL #2]		;get address to predict
   LDR     R3, [R6]			;get the instruction at the Branch
   TEQ     R4, R3, LSL #4		;is it a JIT entry?
   BEQ     JIT_branch_prediction	;YES, follow it
 B       _L1				;NO, go to next BPT entry
#endif
					;----------------------------------


;i_und_exit_hit_limit
;---------------------
;Exit JIT immediately, we've processed the instruction limit

.i_und_exit_hit_limit
 CACHEOP_CLEAN_APPSPACE_TO_HERE		;clean D cache up to here
 BL      CACHEOP_ACTION			;act on pending cache ops

#if compile_RO > 400
LDMFD   R13!, {R0-R7, PC}^		;retry instruction
#endif
#if compile_RO == 400
MOV     R0, R13
LDR     R13, und_stack - 4
LDMFD   R0, {R0-R7, PC}^		;retry instruction
#endif




.i_LDR_STR
 TST     R0, #1 << 25			;Undefined?
 TSTNE   R0, #1 << 4
 MOVNE   R1, #9				;ADFF5009
 BNE     JIT_report_unimplemented	;YET TO BE CODED

 TST     R0, #1 << 25			;is Op2 a register?
 MVNEQ   R3, #0				;NO, R3=<bad value> for checks later
 BEQ     _immediate			; |+ skip Rm PC check

 AND     R3, R0, #%1111			;R3=Rm
 TEQ     R3, #PC_reg			;is PC in Rm? ie: STR R0,[R1,PC]
 MOVEQ   R1, #9				;ADFF5009
 BEQ     JIT_report_unimplemented	;YET TO BE CODED
 ._immediate

 AND     R1, R0, #%1111 << 12		;R1=Rd
 AND     R2, R0, #%1111 << 16		;R2=Rn

 TST     R0, #1 << 20			;LDR?
 BEQ     i_STR				;NO

#if High_Vectors == 1
 B       i_LDR
#endif
#if High_Vectors == 0
					;check for page zero reads
					;----------------------------------
;EXCLUDE:	LDR PC,...
 TEQ     R1, #PC_reg << 12		;:LDR PC, ...?
 BEQ     i_LDR_PC_in_Rd			;YES

;EXCLUDE:	LDR Rd,[PC, #<immed>]
;EXCLUDE:	LDR Rd,[PC],#<immed>
 TEQ     R2, #PC_reg << 16		;:LDR Rx, [PC, ... ?
 TSTEQ   R0, #1 << 25			;YES, is Op2 an immediate?
 BEQ     i_LDR				;YES

 DID_JIT_ENTER_HERE			;did the JIT entered here?
 BEQ     LDR_check			;YES

 LDR     R1, [R7, #-8]			;NO, get the original instruction
 TEQ     R1, R0				;has it changed?
 LDREQ   R2, branch_to_jit_no_condition	;NO, JIT entry instruction
 ANDEQ   R1, R1, #OP_condition		; |  get instruction condition
 ORREQ   R0, R1, R2, LSR #4		; |+ add conditional JIT entry
					;YES, trust the code is okay
B       i_copy_instruction_handled	;continue processing
#endif




.i_LDM_STM
 LDR     R1, _LDMIA_R13_PC		;: LDMIA R13!,{PC}?
 TEQ     R0, R1
 LDREQ   R0, _LDR_PC_R13_4		;YES, change to: LDR PC,[R13],#4
 BEQ     i_LDR_STR

 LDR     R1, _STMDB_R13_R14		;: STMDB R13!,{R14}?
 TEQ     R0, R1
 LDREQ   R0, _STR_R14_R13_4		;YES, change to: STR R14,[R13,#-4]!
 BEQ     i_copy_instruction

 ORR     R1, R0, R0, LSL #16
 CMN     R1, #1				;: LDM/STM Rd{!},{R0-PC}{^} ?
 MOVEQ   R1, #9				;YES, ADFF5009
 BEQ     JIT_report_unimplemented

 AND     R1, R0, #%1111 << 16		;R1=Rn
 TEQ     R1, #PC_reg << 16		;is Rn PC? : LDM/STM PC{!}, ...
 BEQ     _i_LDM_STM_PC_in_Rn		;YES
					;----------------------------------
					;change: LDMIA R0!,{R0}
					;    to: LDMIA R0,{R0}
 MOV     R4, R1, LSR #16		;R4=Rn
 MOV     R2, #1
 TST     R0, R2, LSL R4			;is Rn in the reglist?
 BEQ     _Rn_not_in_reglist		;NO
 TST     R0, #1 << 20			;YES, LDM?
 BICNE   R0, R0, #1 << 21		; |+  YES, clear writeback
 #if ARMv7_support == 1
   BNE     _Rn_not_in_reglist
   TST     R0, #1 << 21			;STM, writeback?
   BNE     i_STM_Rn_in_reglist		;YES
 #endif
 ._Rn_not_in_reglist
					;----------------------------------
; #if ARMv7_support == 1
;   TST     R0, #1 << 13			;is R13 in reg_list?
;   MOVNE   R1, #&17
;   BNE     JIT_report_unimplemented	;YES, ADFF5017
; #endif

 TST     R0, #PC_reglist		;:LDM/STM Rn{!}, {<reg_list>, PC}?
; #if ARMv7_support == 1
;   BICEQ   R0, R0, #1 << 22		;NO, ensure ^ isn't set
;					;(fixes Zarch/Chopper Force on ARMv7)
; #endif
 BEQ     i_copy_instruction

 TST     R0, #1 << 20			;LDM?
 BNE     i_LDM				;YES
B       i_STM

 ._LDMIA_R13_PC		LDMIA   R13!, {PC}
 ._LDR_PC_R13_4		LDR     PC, [R13], #4
 ._STMDB_R13_R14	STMDB   R13!, {R14}
 ._STR_R14_R13_4	STR     R14, [R13, #-4]!


._i_LDM_STM_PC_in_Rn
 TST     R0, #PC_reglist		;is PC in the reglist?
 MOVNE   R1, #9				;YES, ADFF5009
 BNE     JIT_report_unimplemented	;unsupported

 BIC     R0, R0, #1 << 21		;clear writeback

 TST     R0, #1 << 20			;LDM?
 BEQ     i_STM_PC_in_Rn
B       i_LDM_PC_in_Rn




;JIT_report_illegal
;------------------
;report an illegal branch address

.JIT_report_illegal_address
 ADD     R14, R14, #8
 MOV     R1, #&13			;ADFF5013
B       JIT_report_unimplemented_debug



;JIT_report_unimplemented
;------------------------
;report an unimplemented feature
;
;Entry:
; R1 - ADFFS error number (see data_abort.report_abort)

.JIT_report_unimplemented
 DID_JIT_ENTER_HERE			;did the JIT enter on this instr?
 BNE     i_und_exit_no_codelet		;NO, assume it's going to self-
					;    modify and check branch pred.
.JIT_report_unimplemented_debug
 TEMP    R2
 ADD     R12, R1, #&ADFF5000
 STR     R12, current_abort_type
 LDR     R12, DAV_r0 + (12 * 4)
 LOCK    R2
					;fall-thru to JIT_report_abort

.JIT_report_abort
 ADR     R0, DAV_r0
 SUB     R1, R14, #8
 SUB     R1, R1, #jit_code_start
 STR     R1, [R0, #15 * 4]		;store PC

 LDR     R1, [R13], #4			;pull R0 from stack
 STR     R1, [R0], #4
 LDMFD   R13!, {R1-R7, R14}		;restore registers
 STMIA   R0!, {R1-R7}			;store unbanked registers

 MRS     R1, SPSR			;get original CPU state
 TST     R1, #%1111			;is abort in User mode?
 TEMP    R2
 STR     R1, DAV_CPSR			;store it for exit and..
 LOCK    R2				;..fix for errata on SA-110 rev.2
 STMEQIA R0, {R8-R14}^			;get User mode registers
 BEQ     _P2

 MRS     R2, CPSR
 MSR     CPSR_all, R1			;switch to faulting mode
 #if compile_IOMD == 1
   NOP
 #endif
 STMIA   R0, {R8-R14}			;get aborting mode registers
 MSR     CPSR_all, R2
 #if compile_IOMD == 1
   NOP
 #endif

 ._P2
 #if JIT_debug == 1 AND JIT_dump_crash == 1
   ADR     R1, breakpoint_dump
   MOV     R4, #&8000
   MOV     R2, R4
   MOV     R3, #0
   MOV     R5, #jit_slotsize

   MRS     R7, CPSR
   BIC     R0, R7, #%11001111		;retain reserved bit
   ORR     R0, R0, #%00000011		;SVC with IRQ/FIQ enabled
   MSR     CPSR_all, R0
   NOP
   MOV     R0, #0
   SWI     XOS_File
   MSR     CPSR_all, R7
   NOP
 #endif
B       report_abort




#if JIT_debug == 1 AND compile_IOMD == 1
  .report_JIT_IOMD_occurred DCD 0

  .report_JIT_IOMD			;only report if OS_Byte 113 not called
  STR     R14, [R13, #-4]!
  LDR     R14, report_JIT_IOMD_occurred
  TEQ     R14, #0
  MOVNE   R14, #0
  STRNE   R14, report_JIT_IOMD_occurred
  LDRNE   PC, [R13], #4
  LDR     R14, [R13], #4
  ;fall-thru to report_JIT
#endif


#if JIT_debug == 1
;report_JIT
;----------
;displays statistics from the JIT
;
;Exit:
; Registers preserved

.report_JIT
 #if JIT_debug == 1 AND compile_GPU == 1
   STMFD   R13!, {R0-R12, R14}
 #endif
 #if JIT_debug == 1 AND compile_IOMD == 1
   STR     R14, [R13, #-4]!
   LDR     R14, is_screen_remapped	;is the screen remapped?
   TEQ     R14, #0
   LDREQ   PC, [R13], #4		;NO, exit

   LDR     R14, dbg_pause
   SUBS    R14, R14, #1
   STRPL   R14, dbg_pause
   LDRPL   PC, [R13], #4
   STMFD   R13!, {R0-R12}
 #endif

 BL      our_VDU30			;go to top left of screen
 our_writeS  ""
 our_writeS  ""
 #if JIT_detailed_debug == 1
   LDR     R0, jit_disassemble_last
   LDR     R1, jit_disassemble_last + 4

   MRS     R5, CPSR			;R5=entry CPU mode
   #if compile_RO == 400
     MOV     R6, #%10000011		;SVC26 IRQ disabled
   #endif
   #if compile_RO > 400
     MOV     R6, #%10010011		;SVC32 IRQ disabled
   #endif
   MSR     CPSR_all, R6
   NOP
   MRS     R6, SPSR			;preserve SVC SPSR and R14
   MOV     R7, R14

   SUB     R1, R1, #8			;correct for prefetch
   SWI     XDebugger_Disassemble	;PRM4-225

   MOV     R14, R7
   MSR     SPSR_all, R6
   MSR     CPSR_all, R5			;back into entry CPU mode
   NOP

   MVN     R3, #0
   ._report_JIT_find_end		;find end or ";"
     ADD     R3, R3, #1
     LDRB    R0, [R1, R3]
     TEQ     R0, #ASC(";")
     TEQNE   R3, R2
   BNE     _report_JIT_find_end
					;R3 points to end of string or ";"
   TEQ     R0, #ASC(";")		;is there a ";"
   BNE     _report_JIT_no_work_back	;NO
   ._report_JIT_work_back		;YES, remove spaces
     SUB     R3, R3, #1
     LDRB    R0, [R1, R3]
     TEQ     R0, #ASC(" ")
   BEQ     _report_JIT_work_back

   ._report_JIT_no_work_back		;R3=instruction end
   CMP     R3, #39
   MOVHI   R2, #39			;cap to 39 chars
   MOVLS   R2, R3			;or use new length

   our_writeN R1, R2			;display on screen

   LDR     R1, jit_disassemble_len	;previous instruction length
   STR     R2, jit_disassemble_len

   MOV     R0, #ASC(" ")		;blank previous instruction text
   .report_JIT_clear_L1
     CMP     R2, R1
     BLLT    our_XOS_WriteC		;overwrite old text with spaces
     ADD     R2, R2, #1
   BLT     report_JIT_clear_L1

   .report_JIT_skip_disassemble
 #endif
 our_writeS  ""
 LDR     R0, blitter_FPS
 our_writeDecimal R0, dbtext_buffer, 7
 our_writeS  "fps "
 LDR     R1, jit_prev_instrL		;penultimate entry instruction
 our_writeD_n  R1, 6
 our_writeS  " "
 LDR     R1, jit_last_instrR		;last instruction seen
 our_writeD_n  R1, 6

 our_writeS  " PC:"
 LDR     R0, user_PC			;last known PC
 LDR     R4, first_codelet
 CMP     R0, #lastfree_codelet		;above last codelet?
 CMPHS   R4, R0				;possibly, below first codelet?
 BLO     _not_codelet_address		;NO
					;an Abort occurred in a codelet
 BIC     R1, R0, #codelet_alignment - 1	;find codelet header
#if JIT_debug == 1 AND JIT_codelet_reuse == 0
 ._aborted_codelet_L1
   LDR     R3, [R1, #-codelet_struct.codelet]!		;get .next value
   SUB     R3, R3, #jit_appspace_end
   CMP     R3, #jit_code_start - jit_appspace_end	;in codelet space?
 BHI     _aborted_codelet_L1
#endif
#if  JIT_debug == 1 AND JIT_codelet_reuse == 1
 MOV     R5, #CODELET_validation
 ADD     R1, R1, #codelet_struct.validation
 ._aborted_codelet_L1
   LDR     R3, [R1, #-codelet_struct.codelet]!		;get .next value
   TEQ     R3, R5					;EQ if codelet header
 BNE     _aborted_codelet_L1
 SUB     R1, R1, #codelet_struct.validation
#endif
 LDR     R0, [R1, #codelet_struct.source]

 ._not_codelet_address
 CMP     R0, #jit_code_start		;in JIT space?
 BLO     _not_Abort_address		;NO
 SUB     R2, R0, #jit_code_start
 CMP     R2, #jit_appspace_end		;in JIT space?
 SUBLO   R0, R0, #jit_code_start	;YES, correct address
 ._not_Abort_address
 our_writeD R0

 LDR     R3, user_SPSR
 AND     R0, R3, #%1111
 ADD     R1, PC, R0, LSL #2
 B       _skip_CPU_modes
 DCB " USR FIQ IRQ SVC -4- -5- -6- ABT -8- -9- -A- UND -C- -D- -E- -F-"
 ._skip_CPU_modes
 MOV     R2, #4
 our_writeN R1, R2
 #if JIT_debug == 1 AND compile_IOMD == 1
   TST     R3, #%10000
   our_writeSEQ  "26"
 #endif

 TST     R3, #%11000000
 our_writeSNE " "
 TST     R3, #%10000000			;IRQ enabled?
 our_writeSNE "I"
 our_writeSEQ " "
 TST     R3, #%01000000			;FIQ enabled?
 our_writeSNE "F"
 our_writeSEQ " "

 LDR     R1, jit_code
 TEQ     R1, #0				;is the JIT running?
 BEQ     no_JIT1			;NO
 our_writeS  ""
 our_writeS  "A:"
 LDR     R0, jit_write_aborts
; our_writeD R0
 our_writeDecimal R0, dbtext_buffer, 7
 our_writeS  " >"
 LDR     R0, jit_entry_count
 our_writeDecimal R0, dbtext_buffer, 7
 our_writeS  " I:"
 LDR     R0, jit_instr_count
 our_writeDecimal R0, dbtext_buffer, 7
 our_writeS  " R:"
 LDR     R0, jit_instr_interpreted
 our_writeDecimal R0, dbtext_buffer, 7
 #if JIT_debug == 1 AND Unaligned_Support == 1
   our_writeS  " U:"
   LDR     R0, jit_unaligned
   our_writeDecimal R0, dbtext_buffer, 7
 #endif
 our_writeS  " 0:"
 LDR     R0, jit_page_zero_aborts
 our_writeDecimal R0, dbtext_buffer, 7

 our_writeS  ""
 #if JIT_debug == 1 AND High_Vectors == 0
   our_writeS  "L:"
   LDR     R0, jit_LDR_interpreted
   our_writeDecimal R0, dbtext_buffer, 7
   our_writeS  " C:"
 #endif
 #if JIT_debug == 1 AND High_Vectors == 1
   our_writeS  "C:"
 #endif
 LDR     R1, jit_cache_flushes
 MOV     R0, R1, LSR #8			;complete cache flushes
 our_writeDecimal R0, dbtext_buffer, 7
 AND     R0, R1, #31			;cache line flushes
 ADD     R0, R0, #ASC("}") + 1
 BL      our_XOS_WriteC
 our_writeS  " "
 LDR     R1, screen_borders
 LDR     R0, VIDC20_width		;display width
 SUB     R0, R0, R1, LSR #24		;reduce by left border
 AND     R3, R1, #&FF << 16
 SUB     R0, R0, R3, LSR #16		;reduce by right border
 our_writeDecimal R0, dbtext_buffer, 7
 our_writeS  "x"
 LDR     R0, VIDC20_height		;display height
 AND     R3, R1, #&FF << 8
 SUB     R0, R0, R3, LSR #8		;reduce by top border
 AND     R3, R1, #&FF
 SUB     R0, R0, R3			;reduce by bottom border
 our_writeDecimal R0, dbtext_buffer, 7
 LDR     R1, current_mode_bitdepth	;get MODE bpp
 MOV     R0, #1
 MOV     R0, R0, LSL R1
 our_writeS  "x"
 our_writeD_n R0, 1
 #if JIT_debug == 1 AND compile_RO == 500
   LDR     R0, monitor_hz
   our_writeS  " "
   our_writeDecimal R0, dbtext_buffer, 7
   our_writeS  "hz"
   .report_JIT_P4
 #endif

 our_writeS  ""
 our_writeS  "FF:"
 MOV     R1, #lastfree_codelet
 LDR     R0, [R1, #codelet_struct.previous]
 our_writeD_n  R0, 7
 our_writeS  " LC:"
 MOV     R1, #jit_appspace_end
 LDR     R2, [R1, #codelet_struct.size]
 ADD     R1, R1, R2
 our_writeD_n  R1, 7
 our_writeS  " #:"
 LDR     R1, jit_codelet_count
 MOV     R0, R1, LSR #8			;remove the recycle indicator
 our_writeDecimal R0, dbtext_buffer, 7
 AND     R0, R1, #31			;cache line flushes
 ADD     R0, R0, #ASC("}") + 1
 BL      our_XOS_WriteC

 our_writeS ""
 our_writeS "Vi:"
 LDR     R0, MEMC_Vinit
 our_writeD R0
 our_writeS " Vs:"
 LDR     R0, MEMC_Vstart
 our_writeD R0
 LDR     R0, MEMC_Vend
 CMN     R0, #129
 our_writeSNE " Ve:"
 our_writeDNE R0

 #if JIT_debug == 1 AND compile_GPU == 1
   our_writeS ""
   our_writeS "B:"
   LDR     R0, screen_borders
   our_writeD R0

   LDR     R1, hypervised_IRQv
   TEQ     R1, #0			;was IRQv claimed?
   our_writeSNE " IRQv"
   LDR     R1, hypervised_IRQ1V
   TEQ     R1, #0			;was IRQ1V claimed?
   our_writeSNE " IRQ1V"

   ADR     R1, IOC_registers
   LDRB    R0, [R1, #IOC_IRQA_mask >> 2]
   LDRB    R3, [R1, #IOC_IRQB_mask >> 2]
   ADR     R2, DeviceVectors + device_table.entry_code

   LDR     R1, [R2, #IOC_VSync_Pulse * device_table.size]
   TEQ     R1, #0			;VSync claimed?
   TSTNE   R0, #1 << IOC_VSync_Pulse	;YES, is it active?
   our_writeSNE " VSync"		;YES

   LDR     R1, [R2, #IOC_Timer_0 * device_table.size]
   TEQ     R1, #0			;VSync claimed?
   our_writeSNE " T0"			;YES

   LDR     R1, [R2, #IOC_Timer_1 * device_table.size]
   TEQ     R1, #0			;VSync claimed?
   our_writeSNE " T1"			;YES

   LDR     R1, [R2, #IOC_SSBC * device_table.size]
   TEQ     R1, #0			;SSBC claimed?
   TSTNE   R3, #1 << (IOC_SSBC - 8)	;YES, is it active?
   our_writeSNE " SSBC"			;YES

;   LDR     R0, T0_latch
;   EORS    R0, R0, #20000		;different to default value?
   LDR     R0, T0_value
   TEQ     R0, #&10000000		;is it set?
   our_writeSNE " T0:"			;YES
   our_writeDTNE R0
   our_writeSNE " "

   LDR     R0, T1_value
   TEQ     R0, #&10000000		;is it set?
   our_writeSNE " T1:"			;YES
   our_writeDTNE R0
   our_writeSNE " "
   LDRNE   R0, jit_T1_ticks
   our_writeDecimalNE R0, dbtext_buffer, 2
 #endif

 .no_JIT1
LDMFD   R13!, {R0-R12, PC}


 .dbtext_buffer	DCB "9999999", 0
 ALIGN
 .jit_last_instrR	DCD 0
 .jit_prev_instrL	DCD 0
 .jit_instr_count	DCD 0
 .jit_instr_interpreted	DCD 0
 .jit_cache_flushes	DCD 0
 .jit_write_aborts	DCD 0
 .jit_page_zero_aborts	DCD 0
 .jit_codelet_count	DCD 0
 .jit_LDR_interpreted	DCD 0
 .jit_entry_count	DCD 0
 .jit_T1_ticks		DCD 0
 #if JIT_debug == 1 AND compile_IOMD == 1
   .dbg_pause		DCD dbg_pause_default
 #endif
 .user_PC		DCD 0
 .user_SPSR		DCD 0
 .screen_borders	DCD 0
 #if JIT_detailed_debug == 1
  .jit_disassemble_len	DCD 0		;length of the last inst.
  .jit_disassemble_last	DBD 2
 #endif
 #if Unaligned_Support == 1
   .jit_unaligned	DCD 0
 #endif
#endif
