
		AREA	|ARM$$code|,CODE,READONLY

		GET	OSLib:OSLib.Hdr.OS

C0	CN	0
C1	CN	1
CP14	CP	14
CP15	CP	15

		ENTRY

mod_base	DCD	0
		DCD	mod_init - mod_base
		DCD	mod_fin - mod_base
		DCD	0
		DCD	mod_title - mod_base
		DCD	mod_help - mod_base
		DCD	0
		DCD	0
		DCD	0
		DCD	0
		DCD	0
		DCD	0
		DCD	mod_flags - mod_base

mod_title	=	"ProfileMod",0
mod_help	=	"ProfileModule",9,"0.10 (16 Sep 2003)",0
		ALIGN

mod_flags	DCD	1

err_notxscale	DCD	0
		=	"This module requires an Intel XScale processor",0
		ALIGN

mod_init	MOV	R6,R14

		;check that this is an XScale Core

		MRC	CP15,0,R0,C0,C0,0
		AND	R1,R0,#&00FF0000
		AND	R0,R0,#&FF000000
		TEQ	R1,#&00050000
		TEQNE	R1,#&00060000		;optimist!
		TEQEQ	R0,#&69000000
		ADRNE	R0,err_notxscale
		MSRNE	CPSR_f,#V
		MOVNE	PC,R6

		MRC	CP14,0,R3,C0,C0
		BIC	R3,R3,#&F0000006
		BIC	R3,R3,#&00000880
		ORR	R3,R3,#&00000001 ;make sure that CCNT is running
		MCR	CP14,0,R3,C0,C0  ;  but don't change its speed

		MOV	R0,#1
		ADR	R1,undef_handler
		ORR	R0,R0,#&100
		SWI	XOS_ClaimProcessorVector
		STRVC	R1,prev_undefhand
		MOV	PC,R6

mod_fin		MOV	R6,R14
		MOV	R0,#1
		LDR	R1,prev_undefhand
		ADR	R2,undef_handler
		SWI	XOS_ClaimProcessorVector
		MOV	PC,R6

undef_handler	STR	R2,[R13,#-4]!
		STR	R1,[R13,#-4]!
		STR	R0,[R13,#-4]!
		LDR	R1,[R14,#-4]		;read instruction

		;was it an attempted read of the CP14 cycle counter into R0?

		LDR	R2,ccnt_read
		MRS	R0,CPSR
		BIC	R1,R1,#&F0000000
		TEQ	R1,R2
		BNE	pass_on

		;yes, so read the CCNT register and return to caller

ccnt_read	MRCEQ	CP14,0,R0,C1,C0,0	;Note: cond code is zero
		ADD	R13,R13,#4
		LDR	R1,[R13],#4
		LDR	R2,[R13],#4
		MOVS	PC,R14			;continue with next instr

pass_on		MSR	CPSR_f,R0
		LDR	R0,[R13],#4
		LDR	R1,[R13],#4
		LDR	R2,[R13],#4
		LDR	PC,prev_undefhand

prev_undefhand	DCD	0

		END
