#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 AND JIT_report_immediate == 1
   STMFD   R13!, {R12, R14}
   LDR     R12, closest_screen_mode
   CMN     R12, #1			;are we blitting?
   LDMEQFD R13!, {R12, PC}

   ADR     R12, report_JIT_blitter_return
   EORS    R12, R12, R14
   LDRNE   R12, blit_in_progress
   TEQNE   R12, #0
   LDMNEFD R13!, {R12, PC}
   STMFD   R13!, {R0-R11}
 #endif
 #if JIT_debug == 1 AND compile_GPU == 1 AND JIT_report_immediate == 0
   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_debug == 1 AND JIT_detailed_debug == 1
   BL      check_JIT_and_taskID
   BNE     report_JIT_skip_disassemble

   LDR     R0, jit_disassemble_last
   LDR     R1, jit_disassemble_last + 4

   MRS     R5, CPSR			;R5=entry CPU mode
   #if JIT_debug == 1 AND JIT_detailed_debug == 1 AND compile_RO == 400
     MOV     R6, #%10000011		;SVC26 IRQ disabled
   #endif
   #if JIT_debug == 1 AND JIT_detailed_debug == 1 AND 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
   BL      pass_SWI_on2
   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
     LDRB    R0, [R1, R3]
     TEQ     R0, #ASC(" ")
     SUBEQ   R3, R3, #1
   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

   #if JIT_debug == 1 AND JIT_detailed_debug == 1 AND JIT_report_registers == 1
     our_writeS ""
     our_writeS "R0       R1       R2       R3       R4       R5       R6       R7"
     our_writeS ""
     ADR     R0, DAV_r0
     MOV     R2, #16
     .report_registers_L1
       LDR     R1, [R0], #4
       our_writeD R1
       TEQ     R2, #9
       our_writeSEQ ""
       our_writeSNE " "
       SUBS    R2, R2, #1
     BNE     report_registers_L1
    
     our_writeS ""
     our_writeS "R8       R9       R10      R11      R12      R13      R14      PC"
     our_writeS ""
   #endif

   .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 AND Unaligned_Support == 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 OR Unaligned_Support == 1)
  ADD     R1, R1, #codelet_struct.validation
  MOV     R5, #CODELET_validation
  ._aborted_codelet_L1
    LDR     R3, [R1, #-codelet_struct.codelet]!		;get .next value
    CMP     R1, #jit_appspace_end			;check for codelet find fail
    BLO     _not_codelet_address
    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, #%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_GPU == 1
   LDR     R0, monitor_hz
   our_writeS  " "
   our_writeDecimal R0, dbtext_buffer, 7
   our_writeS  "hz"
   .report_JIT_P4
 #endif
 our_writeS  " "
 LDR     R0, jit_joysticks			;PJSRA
 TST     R0, #%0001
 our_writeSNE "A"
 TST     R0, #%1000
 our_writeSNE "J"
 TST     R0, #%0100
 our_writeSNE "S"
 TST     R0, #%0010
 our_writeSNE "R"
 TST     R0, #%10000
 our_writeSNE "P"

 our_writeS  ""
 our_writeS  "LF:"
 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

   BL      task_page_zero_R3		;R3=Page Zero pointer
   LDR     R1, hypervised_Undefined
   LDR     R0, [R3, #page_zero_Undefined]	;Undefined vector
   TEQ     R0, R1			;was IRQv claimed?
   our_writeSNE " Undefined"
   LDR     R1, hypervised_IRQ
   LDR     R0, [R3, #page_zero_IRQ]	;IRQ vector
   TEQ     R0, R1			;was IRQ claimed?
   our_writeSNE " IRQ"
   LDR     R1, hypervised_IRQ1V
   LDR     R0, [R3, #page_zero_IRQ1V]
   TEQ     R0, R1			;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			;T0 claimed?
   our_writeSNE " T0"			;YES

   LDR     R1, [R2, #IOC_Timer_1 * device_table.size]
   TEQ     R1, #0			;T1 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_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_debug == 1 AND JIT_detailed_debug == 1
  .jit_disassemble_len	DCD 0		;length of the last inst.
  .jit_disassemble_last	DBD 2
 #endif
 #if JIT_debug == 1 AND Unaligned_Support == 1
   .jit_unaligned	DCD 0
 #endif
 .jit_joysticks		DCD 0		;PJSRA
#endif


#if JIT_debug == 1 AND JIT_trap_pz_code == 1
.JIT_page_zero_code
 LDMFD   R13!, {R0-R1}			;clear the stack
 STMFD   R13!, {R0-R7, R14}		;[R13, #UND_exit_PC] = R14
 ADD     R14, R14, #8
 MOV     R1, #&1E			;ADFF501E
B       JIT_report_unimplemented_debug
#endif



;our_writeDecimal<CC> Rx, buffer, buffer_size
;output 123456
MACRO our_writeDecimal$cc n:R, buffer:I, size:I		;PRESERVES FLAGS
{
 STM$cc#FD R13!, {R0-R1, R4, R14}
 #if n <> 0
   MOV$cc    R0, n
 #endif
 MOV$cc    R1, #size
 ADR$cc    R4, buffer + size + 1
 BL$cc     debug_writeDecimal
 LDM$cc#FD R13!, {R0-R1, R4, R14}
}




;our_writeS<CC> string
;output - string or CR/LF if ""
MACRO our_writeS$cc s:S					;PRESERVES FLAGS
{
 #if LEN(s) == 0
   STR$cc  R14, [R13, #-4]!
   BL$cc   our_XOS_NewLine
   LDR$cc  R14, [R13], #4
 #endif
 #if LEN(s) == 1
   STM$cc#FD R13!, {R0, R14}
   MOV$cc  R0, #ASC(s)
   BL$cc   our_XOS_WriteC
   LDM$cc#FD R13!, {R0, R14}
 #endif
 #if LEN(s) > 1
   #if LEN(s) > 1 AND cc<>&E
     ADD$cc  PC, PC, #0
     ._start
     ADD     PC, PC, #_end - _start - 8
   #endif
   STR     R14, [R13, #-4]!
   BL      our_XOS_WriteS
   DCB     s, 0
   ALIGN
   LDR     R14, [R13], #4
   ._end
 #endif
}




;our_writeN<CC> addr, length
;output - string
MACRO our_writeN$cc addr:R, len:R			;PRESERVES FLAGS
{
   #if cc<>&E
     ADD$cc  PC, PC, #0
     ._start
     ADD     PC, PC, #_end - _start - 8
   #endif
   STMFD   R13!, {R1-R2, R14}
   #if addr <> 1
     MOV     R1, addr
   #endif
   #if len <> 2
     MOV     R2, len
   #endif
   BL      our_XOS_WriteN
   LDMFD   R13!, {R1-R2, R14}
   ._end
}





;our_writeB<CC> Rx
;output FF
MACRO our_writeB$cc n:R					;PRESERVES FLAGS
{
 STM$cc#FD R13!, {R1-R2}
 #if n <> 1
   MOV$cc    R1, n
 #endif

 MOV$cc    R2, #4
 BL$cc     debug_outputHexByte
 LDM$cc#FD R13!, {R1-R2}
}





;our_writeD<CC> Rx
;output FFFFFFFF
MACRO our_writeD$cc n:R					;PRESERVES FLAGS
{
 #if n <> 1
   STR$cc  R1, [R13, #-4]!
   MOV$cc  R1, n
 #endif

 BL$cc   debug_outputHex

 #if n <> 1
   LDR$cc  R1, [R13], #4
 #endif
}





;our_writeDT<CC> Rx
;output Double with leading 0's removed
MACRO our_writeDT$cc n:R				;PRESERVES FLAGS
{
 #if n <> 1
   STR$cc  R1, [R13, #-4]!
   MOV$cc  R1, n
 #endif

 BL$cc   debug_outputHexTruncated

 #if n <> 1
   LDR$cc  R1, [R13], #4
 #endif
}




;our_writeD_n<CC> Rx, N
;output N chars of Rx
MACRO our_writeD_n$cc n:R s:I				;PRESERVES FLAGS
{
 STM$cc#FD R13!, {R1-R2, R14}
 #if n <> 1
   MOV$cc     R1, n
 #endif
 MOV$cc    R2, #(s << 2) - 4
 BL$cc     debug_outputHexByte
 LDM$cc#FD R13!, {R1-R2, R14}
}
