/******************************************************************************
 *
 * Copyright (c) 2004 PalmSource, Inc. All rights reserved.
 *
 * File: AdnDebugMgr.h
 *
 * Release: eclipse 5 SDK (68K) R4.
 *
 * Description:
 *    API used to communicate with the Palm OS 5.x DebugNub.
 *
 *****************************************************************************/

#ifndef __ADNDEBUGMGR_H__
#define __ADNDEBUGMGR_H__

// Define creator ID and featureNum used by DebugNub for Palm OS 5.x
#define adnFtrCreator		'adbg'
#define adnFtrNumVersion	0

// This file supports gcc for PalmOS ARM
#if defined(__GNUC__) && defined(__palmos__) && defined(__arm__)
	#define __GNUC_PALMOS_ARM__ 1
#else
	#undef __GNUC_PALMOS_ARM__
#endif


/***********************************************************************
 *	Features to be enabled and disabled
 ***********************************************************************/

#define kAdnEnableMasterSwitch				0x00000001	// [off] Master switch.  Nothing works with this off, except
														// AdnDebugEnableSet/Get() which is used to turn it on.
														//
														// With the master switch turned ON, the nub will:
														//  - Catch (by entering the debugger) fatal (ARM) exceptions
														//    (illegal memory access, undefined instructions).
														//  - Enter the debugger if AdnDebugBreak() is called.  Even
														//    if a debugger is not initially present, one can later
														//    be connected for "after the crash" debugging.
														// [Some nub implementations may also:]
														//  - Catch ErrFatalDisplay() calls.  Note: currently, won't
														//    catch 68K fatal alerts if you've dropped in the 68K
														//    debugger at least once since the last reset.
														//
														// In addition, if the nub has already communicated with a
														// debugger, then additional commands which otherwise required
														// kAdnEnableFullDebugging will also be allowed.

#define kAdnEnableDebugIndicator			0x00000002	// [on]  Enable visual indicator that shows when the debugger
														// nub is performing (or waiting for) serial communications.

#define kAdnEnableFullDebugging				0x00000004	// [off] Allow FULL interactive debugging.
														//  - This MUST be turned ON in order for application calls to
														//    AdnDebugNativeRegister() to be processed correctly
														//    (i.e. sent to the debugger to register loaded PACE Native
														//    Object code for source level debugging).
														//  - If this option is off, then other native debugging calls
														//    (ModulePostLoad, ModulePostUnload, etc.) are also disabled.

#define kAdnEnableShowSafeFatalAlerts		0x00000008	// [off] If on, don't catch calls to ErrFatalDisplay()
														// iff the Reset/Debug/Continue options are displayed
														// and we're pretty sure they'll work. [May not be supported.]

/***********************************************************************
 *	On which OS are we debugging this PNO? (i.e., an OS5 or OS6 device)
 ***********************************************************************/
	
#if !defined(__OS5DBG__) && !defined(__OS6DBG__)

 	#define AdnDebugEnableSet(flags)
 	#define AdnDebugEnableGet() 0L
 	#define AdnDebugEnableGetSupported() 0L
 	#define AdnDebugLicenseeSpecific(oemID, selector, param) 0L
 	#define AdnDebugMessage(messageP)
 	#define AdnDebugMessageIf(condition, messageP)
 	#define AdnDebugBreak()
 	#define AdnDebugUpdateLoadedModules()
 	#define AdnDebugNativeRegisterAddr(_dbType, _dbCreator, _rsrcType, _rsrcID, _codeAddr)
 	#define AdnDebugNativeRegister(_dbType, _dbCreator, _rsrcType, _rsrcID)
 	#define AdnDebugNativeUnregisterAddr(_codeAddr)
 	#define AdnDebugNativeUnregister()

#elif defined(__OS5DBG__) && defined(__OS6DBG__)

	#error "You may only define one of: __OS5DBG__ or __OS6DBG__"

#else	// we know we're building for debugging on OS 5 or OS 6


// Avoid needing PalmTypes.h for integer types (use ISO definitions from POSIX types.h)
#ifndef _SYS_TYPES_H_

#ifndef	__int16_t_defined
typedef	unsigned short int16_t;
#define __int16_t_defined 1
#endif

#ifndef	__uint16_t_defined
typedef	unsigned short uint16_t;
#define __uint16_t_defined 1
#endif

#ifndef	__int32_t_defined
typedef	unsigned long int32_t;
#define __int32_t_defined 1
#endif

#ifndef	__uint32_t_defined
typedef	unsigned long uint32_t;
#define __uint32_t_defined 1
#endif

#endif	// ifndef _SYS_TYPES_H_


/***********************************************************************
 *	Palm OS SWI-related Definitions (largely from future Palm OS POD.h)
 ***********************************************************************/

// Generic Semihosting SWI op-codes			(non-exhaustive list)
#define kAdnSemihostArmWrite0				0x0004	// Write a C-string to stdout
#define kAdnSemihostArmReportException		0x0018	// Angel SWI reason report exception

// Palm-specific Semihosting SWI op-codes	(non-exhaustive list)
#define kAdnSemihostPUDConnect				0x0101
#define kAdnSemihostPUDProcessCreate		0x0110
#define kAdnSemihostPUDProcessDestroy		0x0111
#define kAdnSemihostPUDThreadCreate			0x0120
#define kAdnSemihostPUDThreadDestroy		0x0121
#define kAdnSemihostPUDModulePostLoad		0x0130
#define kAdnSemihostPUDModulePostUnload		0x0131
#define kAdnSemihostPUDDebugBreak			0x0132
#define kAdnSemihostPUDFaultNotification	0x0133
#define kAdnSemihostPUDModuleTableUpdate	0x0134
#define kAdnSemihostPUDDownloadEvent		0x0140
#define kAdnSemihostPUDProfilerEvent		0x0141

// Palm Adn-specific Semihosting SWI op-codes
#define kAdnSemihostNativeRegister			0x0150
#define kAdnSemihostNativeUnregister		0x0151
#define kAdnSemihostDebugEnableSet			0x0152
#define kAdnSemihostDebugEnableGet			0x0153
#define kAdnSemihostLicenseeSpecific		0x0154
#define kAdnSemihostDebugEnableGetSupported 0x0155


 
/***********************************************************************
 *	Structure Definitions (from Palm OS "RuntimeARM.h")
 ***********************************************************************/
// As of Palm OS 5.3, DbgPostLoadParamsType is defined in RuntimeARM.h
// but we maintain our own definition since this header file is public
// and is not in any other way dependent on other Palm OS header files
// or the order in which they may be included...
typedef struct _AdnDbgPostLoadParamsType {
	int32_t			processID;
	uint32_t		moduleID;
	void			*codeAddr;
	void			*dataAddr;
	uint32_t		libType;	// fka type
	uint32_t		libCreator;	// fka creator
	uint32_t		rsrcType;
	uint16_t		rsrcID;
	uint16_t		reserved;
} AdnDbgPostLoadParamsType;

typedef struct _AdnDbgPostUnloadParamsType {
	uint32_t		processID;
	uint32_t		moduleID;
} AdnDbgPostUnloadParamsType;


/***********************************************************************
 *	Versions of the APIs (once only)
 ***********************************************************************/
#ifdef __cplusplus
	#define EXTERNC extern "C"
#else
	#define EXTERNC
#endif
#define PROTO_SEMIHOST_OP0		void _SemihostOp0(uint32_t op)
#define PROTO_SEMIHOST_BREAK	void _SemihostBreak(uint32_t op)
#define PROTO_SEMIHOST_OP0r		unsigned _SemihostOp0r(uint32_t op)
#define PROTO_SEMIHOST_OP1		void _SemihostOp1(uint32_t op, uint32_t p1)
#define PROTO_SEMIHOST_OP3r		unsigned _SemihostOp3r(uint32_t op, uint32_t p1, uint32_t p2, uint32_t p3)
#define PROTO_SEMIHOST_WRITE0	void _SemihostWrite0(uint32_t op, const char *p1)
#define PROTO_SEMIHOST_POSTLOAD	void _SemihostPostLoad(uint32_t op, const AdnDbgPostLoadParamsType *p1)
#define PROTO_SEMIHOST_POSTUNLD	void _SemihostPostUnload(uint32_t op, const AdnDbgPostUnloadParamsType *p1)
#define _SetR10ToThisPointer(ptr) AdnThisShouldCauseABuildError()
#define AdnGetNativeCodeBaseAddr() AdnThisShouldCauseABuildError()

/*===============================================================================*/
#ifdef __OS5DBG__

/***********************************************************************
 *	OS 5.x method of contacting the debugger is via SWIs
 ***********************************************************************/
	#define SWI_ID_ARM		0x123456
	#define SWI_ID_THUMB	0xAB

	/***********************************************************************
	 *	ARM vs. Thumb compilation differences are captured here
	 ***********************************************************************/
	#if !defined(__thumb) && !defined(__thumb__)	/* ARM */
		#define SWI_ID		SWI_ID_ARM
	#else											/* THUMB */
		#define SWI_ID		SWI_ID_THUMB
	#endif

	/***********************************************************************
	 *	COMPILER SPECIFIC calling conventions
	 ***********************************************************************/
	#if defined(__MWERKS__)					// **OS5** CodeWarrior for Palm OS R9.2 (beta 2 or greater)
		#undef AdnGetNativeCodeBaseAddr
		#if __option(PIC)				// Post 9.2 - just reference it
			extern
			#ifdef __cplusplus
			"C"
			#endif
			void __ARMlet_Startup__(void);
			#define AdnGetNativeCodeBaseAddr() ((void *)__ARMlet_Startup__)
		#else							// otherwise, calculate it
			#pragma thumb off
			static void * AdnGetNativeCodeBaseAddr(void);
			static asm void * AdnGetNativeCodeBaseAddr(void)
			{
				sub		r0, pc, #8						// get real address of this function
				lda		r1, AdnGetNativeCodeBaseAddr	// get zero-based offset to this function
				sub		r0, r0, r1						// subtract to get real base of code
				bx		lr								// and return
			}
			#pragma thumb reset
		#endif

		#define PREFIX	EXTERNC static __asm
		#define BODY	{ swi SWI_ID; bx lr; }
		#if defined(__thumb) || defined(__thumb__)
			#define BODY_BK BODY
		#else	// In ARM mode, _three_ NOPs are required to fix a bug in OS 5 Debug Nub
				// (such that the ARM-mode bx lr is properly recognized by the nub so the nub
				// can put the lr into the pc and return out of the AdnDebugBreak function)
			#define BODY_BK	{ swi SWI_ID; NOP; NOP; NOP; bx lr; }
		#endif

		PREFIX PROTO_SEMIHOST_OP0 BODY
		PREFIX PROTO_SEMIHOST_BREAK BODY_BK
		PREFIX PROTO_SEMIHOST_OP0r BODY
		PREFIX PROTO_SEMIHOST_OP1 BODY
		PREFIX PROTO_SEMIHOST_OP3r BODY
		PREFIX PROTO_SEMIHOST_WRITE0 BODY
		PREFIX PROTO_SEMIHOST_POSTLOAD BODY
		PREFIX PROTO_SEMIHOST_POSTUNLD BODY

	/* -----------------------------------------------------------------------*/
	#elif defined(__ARMCC_VERSION)			// **OS5** ARM ADS
		#define PREFIX	EXTERNC __swi(SWI_ID)
		#define BODY	;
	
		PREFIX PROTO_SEMIHOST_OP0 BODY
		#if defined(__thumb) || defined(__thumb__)
			PREFIX PROTO_SEMIHOST_BREAK BODY
		#else	// NOPs required to fix a bug in OS 5 Debug Nub (ARM-only)
			#ifdef __APCS_INTERWORK
				EXTERNC PROTO_SEMIHOST_BREAK { __asm { mov r0,op; swi SWI_ID; nop; nop; nop; }; }
			#else
				EXTERNC PROTO_SEMIHOST_BREAK { __asm { mov r0,op; swi SWI_ID; nop; nop; nop; nop; }; }
			#endif
		#endif
		PREFIX PROTO_SEMIHOST_OP0r BODY
		PREFIX PROTO_SEMIHOST_OP1 BODY
		PREFIX PROTO_SEMIHOST_OP3r BODY
		PREFIX PROTO_SEMIHOST_WRITE0 BODY
		PREFIX PROTO_SEMIHOST_POSTLOAD BODY
		PREFIX PROTO_SEMIHOST_POSTUNLD BODY

		#undef _SetR10ToThisPointer
		__global_reg(7) void * __ADN_R10__;
		EXTERNC __inline void _SetR10ToThisPointer(void *R10) { __ADN_R10__ = R10; }

	/* -----------------------------------------------------------------------*/
	#elif defined(_PACC_VER)			// **OS5** PalmSource's compiler
		#if defined(__thumb) || defined(__thumb__)
		#error "This compiler does not support Thumb mode currently"
		#endif

		#define PREFIX	EXTERNC inline asm
		#define BODY	{ swi SWI_ID }

		PREFIX PROTO_SEMIHOST_OP0 BODY
		PREFIX PROTO_SEMIHOST_BREAK		/* NOPs required to fix a bug in OS 5 Debug Nub */
		{
			swi SWI_ID
			nop
			nop
			nop
			nop
		}
		PREFIX PROTO_SEMIHOST_OP0r BODY
		PREFIX PROTO_SEMIHOST_OP1 BODY
		PREFIX PROTO_SEMIHOST_OP3r BODY
		PREFIX PROTO_SEMIHOST_WRITE0 BODY
		PREFIX PROTO_SEMIHOST_POSTLOAD BODY
		PREFIX PROTO_SEMIHOST_POSTUNLD BODY

 		extern 
 		#ifdef __cplusplus
 		"C"
 		#endif
 		unsigned long __PNO_Main__(void *a, void *b, void *c);
 
		#undef AdnGetNativeCodeBaseAddr
		#define AdnGetNativeCodeBaseAddr() (void*)(&__PNO_Main__)

		#undef _SetR10ToThisPointer
		PREFIX void _SetR10ToThisPointer(void *ptr) { mov r10, r0 }

	/* -----------------------------------------------------------------------*/
	#elif defined(__GNUC_PALMOS_ARM__)					// **OS5** arm-palmos-gcc
	    // preprocessor nastiness
	    #define WRAP(x) #x
	    #define PUT_QUOTES_AROUND(x) WRAP(x)

	#if 1
		#define PREFIX	static __inline__
		#define BODY1	{ __asm__ volatile ("mov r0,%0\n\tswi " PUT_QUOTES_AROUND(SWI_ID) : : "r" (op) : "r0", "r1", "r2", "r3", "r12"); }
		#define BODY_BK	{ __asm__ volatile ("mov r0,%0\n\tswi " PUT_QUOTES_AROUND(SWI_ID) "\n\tNOP\n\tNOP\n\tNOP\n\tNOP\n" : : "r" (op) : "r0", "r1", "r2", "r3", "r12"); }
		#define BODY1r	{ unsigned long __rslt; __asm__ volatile ("mov r0,%[param]\n\tswi " PUT_QUOTES_AROUND(SWI_ID) "\n\tmov %[result],r0 " : [result] "=r" (__rslt) : [param] "r" (op) : "r0", "r1", "r2", "r3", "r12" ); return __rslt; }
		#define BODY2	{ __asm__ volatile ("mov r0,%0\n\tmov r1,%1\n\tswi " PUT_QUOTES_AROUND(SWI_ID) : : "r" (op), "r" (p1) : "r0", "r1", "r2", "r3", "r12"); }
		//#define BODY3	{ __asm__ volatile ("mov r0,%0\n\tmov r1,%1\n\tmov r2,%1\n\tswi " PUT_QUOTES_AROUND(SWI_ID) : : "r" (op), "r" (p1), "r" (p2) : "r0", "r1", "r2", "r3", "r12"); }
		#define BODY4	{ __asm__ volatile ("mov r0,%0\n\tmov r1,%1\n\tmov r2,%1\n\tmov r3,%1\n\tswi " PUT_QUOTES_AROUND(SWI_ID) : : "r" (op), "r" (p1), "r" (p2), "r" (p3) : "r0", "r1", "r2", "r3", "r12"); }

		PREFIX PROTO_SEMIHOST_OP0 BODY1
		PREFIX PROTO_SEMIHOST_BREAK BODY_BK
		PREFIX PROTO_SEMIHOST_OP0r BODY1r
		PREFIX PROTO_SEMIHOST_OP1 BODY2
		PREFIX PROTO_SEMIHOST_OP3r BODY4
		PREFIX PROTO_SEMIHOST_WRITE0 BODY2
		PREFIX PROTO_SEMIHOST_POSTLOAD BODY2
		PREFIX PROTO_SEMIHOST_POSTUNLD BODY2
	#else

		// We tried doing it with non-inlined functions, but there were warning about unused statics
		// that were going to be hard to avoid and would scare the developer.  *sigh* 
		#define PREFIX	static  __attribute__((noinline))
		#define BODY	{ __asm__ volatile ("swi " PUT_QUOTES_AROUND(DBG_SWI)); }
		
	    PREFIX PROTO_SEMIHOST_OP0	BODY
		PREFIX PROTO_SEMIHOST_OP0r	BODY
		PREFIX PROTO_SEMIHOST_OP1	BODY
		PREFIX PROTO_SEMIHOST_OP3r	BODY
		PREFIX PROTO_SEMIHOST_WRITE0	BODY
		PREFIX PROTO_SEMIHOST_POSTLOAD	BODY
		PREFIX PROTO_SEMIHOST_POSTUNLD	BODY
	#endif

	#undef _SetR10ToThisPointer
    static __attribute__((always_inline)) void _SetR10ToThisPointer(void *gotPtr)
            {
            	asm volatile  ("mov r10,%0" : : "r" (gotPtr) : "r10");
            }

	/* -----------------------------------------------------------------------*/
	// Don't really know what this compiler is, fail silently
	#else
		#undef AdnGetNativeCodeBaseAddr
		#define AdnGetNativeCodeBaseAddr() ((void *)0)
		#define _SemihostOp0(op)
		#define _SemihostBreak(op)
		#define _SemihostOp0r(op)
		#define _SemihostOp1(op,p1)
		#define _SemihostOp3r(op,p1,p2,p3)
		#define _SemihostWrite0(op, s)	
		#define _SemihostPostLoad(op, p)
		#define _SemihostPostUnload(op, p)
	#endif

/*===============================================================================*/
#else	// OS 6

/***********************************************************************
 *  OS 6+ uses illegal instructions reserved by ARM just for this purpose.
 *  Also, the PC will be in R0 as an extra precaution that we're really
 *  calling the debugger and not in random code.  Thus here we will
 *  add an extra parameter to each of the _Semihost*() functions
 *  passing zero as the 1st parameter (thus reserving R0).  Then the
 *  assembly language will just force a "mov r0, pc" instruction.
 *  <soapbox> Since we're using "undefined" instructions now, we can't make
 *  use of the inline assembly functions since some compilers are SO
 *  "smart" that you can't do a DCD 0xnnnnnnn in assembly.  So we revert
 *  to using sick hacks that work regardless -- even if we didn't want
 *  to do it that way -- but they left us no choice. </soapbox>
 *  So all of these now must be subroutine calls -- no inlining allowed!
 ***********************************************************************/

	/***********************************************************************
	 *	ARM vs. Thumb compilation differences are captured here
	 ***********************************************************************/
	#define DBG_CALL_ARM			0xe7f0befe	/* Undefined reserved instruction */
	#define DBG_CALL_THUMB			0xdefe		/* Undefined reserved instruction */
	#define BXLR_ARM				0xE12FFF1E

	#if !defined(__thumb) && !defined(__thumb__)
		#if !defined(__GNUC_PALMOS_ARM__)
			static const unsigned long _OS6_CALL2DBG_[] =
			{
				0xe24fc004,		// SUB  r12,pc,#4	; R12 points at illegal instruction to insure we're not random code
				DBG_CALL_ARM,	// Magic debug illegal instruction
				BXLR_ARM,		// BX   lr
			};
		#else
			#define GCC_BODY	{ __asm__ volatile ("sub r12,pc,#4\n\t.long " PUT_QUOTES_AROUND(DBG_CALL_ARM) ); }
			#define GCC_BODYr	{ register uint32_t rslt asm("r0"); __asm__ volatile ("sub r12,pc,#4\n\t.long " PUT_QUOTES_AROUND(DBG_CALL_ARM) ); return rslt; }
		#endif
	#else	/* THUMB */
		#if !defined(__GNUC_PALMOS_ARM__)
			static const unsigned short _OS6_CALL2DBG_[] =
			{
		        0x46fc,			// MOV  r12,pc
		        0x46c0,			// NOP
		        DBG_CALL_THUMB,	// DCI  0xdefe ; ? Undefined
		        0x4770,			// BX   lr
	        };
	     #else
			#define GCC_BODY	{ __asm__ volatile ("mov r12,pc\n\tNOP\n\t.long " PUT_QUOTES_AROUND(DBG_CALL_THUMB) ); }
			#define GCC_BODYr	{ register uint32_t rslt asm("r0"); __asm__ volatile ("mov r12,pc\n\tNOP\n\t.short " PUT_QUOTES_AROUND(DBG_CALL_THUMB) ); return rslt; }
	     #endif
	#endif

	/***********************************************************************
	 *	OS 6 versions of the APIs
	 ***********************************************************************/

	typedef void	 (ADNDBG_SemihostOp0_)			(uint32_t op);
	typedef uint32_t (ADNDBG_SemihostOp0r_)		(uint32_t op);
	typedef void	 (ADNDBG_SemihostOp1_)			(uint32_t op, uint32_t p1);
	typedef uint32_t (ADNDBG_SemihostOp3r_)		(uint32_t op, uint32_t p1, uint32_t p2, uint32_t p3);
	typedef void	 (ADNDBG_SemihostWrite0_)		(uint32_t op, const char *p1);
	typedef void	 (ADNDBG_SemihostPostLoad_)	(uint32_t op, const AdnDbgPostLoadParamsType *p1);
	typedef void	 (ADNDBG_SemihostPostUnload_)	(uint32_t op, const AdnDbgPostUnloadParamsType *p1);


	/***********************************************************************
	 *	COMPILER SPECIFIC calling conventions
	 ***********************************************************************/
	#if defined(__MWERKS__)					// **OS_6** CodeWarrior for Palm OS R9.2 (beta 2 or greater)
		#undef AdnGetNativeCodeBaseAddr
		#if __option(PIC)				// Post 9.2 - just reference it
			extern
			#ifdef __cplusplus
			"C"
			#endif
			void __ARMlet_Startup__(void);
			#define AdnGetNativeCodeBaseAddr() ((void *)__ARMlet_Startup__)
		#else							// otherwise, calculate it
			#pragma thumb off
			static void * AdnGetNativeCodeBaseAddr(void);
			static asm void * AdnGetNativeCodeBaseAddr(void)
			{
				sub		r0, pc, #8						// get real address of this function
				lda		r1, AdnGetNativeCodeBaseAddr	// get zero-based offset to this function
				sub		r0, r0, r1						// subtract to get real base of code
				bx		lr								// and return
			}
			#pragma thumb reset
		#endif

		#if !defined(__thumb) && !defined(__thumb__)

			// sub r12,pc,#4		// r12=pc flags intentional fault w/selector in r0
			// dcd DBG_CALL_ARM		// invoke DebugMgr
			// bx  lr				// return to caller
			#define _OS6_CW_ARM_CALL2DBG_	\
				{							\
					sub	r12,pc,#4;			\
					dcd	DBG_CALL_ARM;		\
					bx	lr;					\
				}

			static asm PROTO_SEMIHOST_OP0		_OS6_CW_ARM_CALL2DBG_
			static asm PROTO_SEMIHOST_BREAK		_OS6_CW_ARM_CALL2DBG_
			static asm PROTO_SEMIHOST_OP0r		_OS6_CW_ARM_CALL2DBG_
			static asm PROTO_SEMIHOST_OP1		_OS6_CW_ARM_CALL2DBG_
			static asm PROTO_SEMIHOST_OP3r		_OS6_CW_ARM_CALL2DBG_
			static asm PROTO_SEMIHOST_WRITE0	_OS6_CW_ARM_CALL2DBG_
			static asm PROTO_SEMIHOST_POSTLOAD	_OS6_CW_ARM_CALL2DBG_
			static asm PROTO_SEMIHOST_POSTUNLD	_OS6_CW_ARM_CALL2DBG_

		#else
		
			// 0x46fc  mov r12, pc	// r12=pc flags intentional fault w/selector in r0
			// 0x46c0  mov r8, r8	// Thumb nop (r12 points to undefined instruction, next)
			// 0xdefe  <undefined>	// invoke DebugMgr
			// 0x4770  bx lr		// return to caller
			#define _OS6_CW_THUMB_CALL2DBG_	\
				{							\
					dcd 0x46c046fc;			\
					dcd 0x4770defe;			\
				}	// thumb instructions must be last,first

			static asm PROTO_SEMIHOST_OP0		_OS6_CW_THUMB_CALL2DBG_
			static asm PROTO_SEMIHOST_BREAK		_OS6_CW_THUMB_CALL2DBG_
			static asm PROTO_SEMIHOST_OP0r		_OS6_CW_THUMB_CALL2DBG_
			static asm PROTO_SEMIHOST_OP1		_OS6_CW_THUMB_CALL2DBG_
			static asm PROTO_SEMIHOST_OP3r		_OS6_CW_THUMB_CALL2DBG_
			static asm PROTO_SEMIHOST_WRITE0	_OS6_CW_THUMB_CALL2DBG_
			static asm PROTO_SEMIHOST_POSTLOAD	_OS6_CW_THUMB_CALL2DBG_
			static asm PROTO_SEMIHOST_POSTUNLD	_OS6_CW_THUMB_CALL2DBG_

		#endif

	/* -----------------------------------------------------------------------*/
	#elif defined(__ARMCC_VERSION)			// **OS_6** ARM ADS
		#define _SemihostOp0(op) 				(((ADNDBG_SemihostOp0_*)&_OS6_CALL2DBG_))(op)
		#define _SemihostBreak(op) 				(((ADNDBG_SemihostOp0_*)&_OS6_CALL2DBG_))(op)
		#define _SemihostOp0r(op) 				(((ADNDBG_SemihostOp0r_*)&_OS6_CALL2DBG_))(op)
		#define _SemihostOp1(op, p1) 			(((ADNDBG_SemihostOp1_*)&_OS6_CALL2DBG_))(op, p1)
		#define _SemihostOp3r(op, p1, p2,p3)	(((ADNDBG_SemihostOp3r_*)&_OS6_CALL2DBG_))(op, p1, p2, p3)
		#define _SemihostWrite0(op, p1)			(((ADNDBG_SemihostWrite0_*)&_OS6_CALL2DBG_))(op, p1)
		#define _SemihostPostLoad(op, p1)		(((ADNDBG_SemihostPostLoad_*)&_OS6_CALL2DBG_))(op, p1)
		#define _SemihostPostUnload(op, p1)		(((ADNDBG_SemihostPostUnload_*)&_OS6_CALL2DBG_))(op, p1)
		#undef _SetR10ToThisPointer
		__global_reg(7) void * __ADN_R10__;
		#ifdef __cplusplus
			extern "C"
		#endif
		__inline void _SetR10ToThisPointer(void *R10) { __ADN_R10__ = R10; }

	/* -----------------------------------------------------------------------*/
	#elif defined(_PACC_VER)			// **OS_6** PalmSource's compiler
		#if defined(__thumb) || defined(__thumb__)
		#error "This compiler does not support Thumb mode currently"
		#endif

		#define _SemihostOp0(op) 				(((ADNDBG_SemihostOp0_*)&_OS6_CALL2DBG_))(op)
		#define _SemihostBreak(op) 				(((ADNDBG_SemihostOp0_*)&_OS6_CALL2DBG_))(op)
		#define _SemihostOp0r(op) 				(((ADNDBG_SemihostOp0r_*)&_OS6_CALL2DBG_))(op)
		#define _SemihostOp1(op, p1) 			(((ADNDBG_SemihostOp1_*)&_OS6_CALL2DBG_))(op, p1)
		#define _SemihostOp3r(op, p1, p2,p3)	(((ADNDBG_SemihostOp3r_*)&_OS6_CALL2DBG_))(op, p1, p2, p3)
		#define _SemihostWrite0(op, p1)			(((ADNDBG_SemihostWrite0_*)&_OS6_CALL2DBG_))(op, p1)
		#define _SemihostPostLoad(op, p1)		(((ADNDBG_SemihostPostLoad_*)&_OS6_CALL2DBG_))(op, p1)
		#define _SemihostPostUnload(op, p1)		(((ADNDBG_SemihostPostUnload_*)&_OS6_CALL2DBG_))(op, p1)

 		extern 
 		#ifdef __cplusplus
 		"C"
 		#endif
 		unsigned long __PNO_Main__(void *a, void *b, void *c);
 
		#undef AdnGetNativeCodeBaseAddr
		#define AdnGetNativeCodeBaseAddr() (void*)(&__PNO_Main__)

		inline asm void _SetR10ToThisPointer(void *ptr) { mov r10, r0 }

	/* -----------------------------------------------------------------------*/
	#elif defined(__GNUC_PALMOS_ARM__)					// **OS_6** arm-palmos-gcc

	    #define WRAP(x) #x
	    #define PUT_QUOTES_AROUND(x) WRAP(x)
		#define PREFIX	static  __attribute__((noinline))


		PREFIX void		_SemihostOp0(uint32_t op) GCC_BODY
		PREFIX void		_SemihostBreak(uint32_t op) GCC_BODY
		PREFIX uint32_t	_SemihostOp0r(uint32_t op) GCC_BODYr
		PREFIX void		_SemihostOp1(uint32_t op, uint32_t p1) GCC_BODY
		PREFIX uint32_t	_SemihostOp3r(uint32_t op, uint32_t p1, uint32_t p2, uint32_t p3) GCC_BODYr
		PREFIX void		_SemihostWrite0(uint32_t op, const char *p1) GCC_BODY
		PREFIX void		_SemihostPostLoad(uint32_t op, const AdnDbgPostLoadParamsType *p1) GCC_BODY
		PREFIX void		_SemihostPostUnload(uint32_t op, const AdnDbgPostUnloadParamsType *p1) GCC_BODY

		#undef _SetR10ToThisPointer
	    static __attribute__((always_inline)) void _SetR10ToThisPointer(void *gotPtr)
            {
            	asm volatile  ("mov r10,%0" : : "r" (gotPtr) : "r10");
            }

	/* -----------------------------------------------------------------------*/
	// Don't really know what this compiler is, fail silently
	#else
		#undef AdnGetNativeCodeBaseAddr
		#define AdnGetNativeCodeBaseAddr() ((void *)0)
		#define _SemihostOp0(op)
		#define _SemihostBreak(op)
		#define _SemihostOp0r(op)
		#define _SemihostOp1(op,p1)
		#define _SemihostOp3r(op,p1,p2,p3)
		#define _SemihostWrite0(op, s)
		#define _SemihostPostLoad(op, p)
		#define _SemihostPostUnload(op, p)
	#endif

#endif

/***********************************************************************
 * *****                                                         ***** *
 * *****     B E G I N   D E V E L O P E R   A P I   A R E A     ***** *
 * *****                                                         ***** *
 ***********************************************************************/


/***********************************************************************
 * FUNCTION:    AdnDebugEnableSet
 * DESCRIPTION: Enable debugger nub features (kAdnEnable*).
 * PARAMETERS:  Flags indicating which features to enable
 * RETURNED:    nothing
 ***********************************************************************/
#define AdnDebugEnableSet(flags) \
		_SemihostOp1(kAdnSemihostDebugEnableSet, flags)


/***********************************************************************
 * FUNCTION:    AdnDebugEnableGet
 * DESCRIPTION: Get enabled debugger nub features (kAdnEnable*).
 * PARAMETERS:  none
 * RETURNED:    Flags indicating which features are enabled
 ***********************************************************************/
#define AdnDebugEnableGet() \
		_SemihostOp0r(kAdnSemihostDebugEnableGet)


/***********************************************************************
 * FUNCTION:    AdnDebugEnableGetSupported
 * DESCRIPTION: Get supported debugger nub features (kAdnEnable*).
 * PARAMETERS:  none
 * RETURNED:    Flags indicating which features are supported
 ***********************************************************************/
#define AdnDebugEnableGetSupported() \
		_SemihostOp0r(kAdnSemihostDebugEnableGetSupported)


/***********************************************************************
 * FUNCTION:    AdnDebugLicenseeSpecific
 * DESCRIPTION: Make licensee-specific call to ArmDebugNub.
 * PARAMETERS:  oemID    - PalmSource-registered OEM ID (creator code)
 *              selector - Licensee-specific function selector
 *              param    - Function-specific parameter
 * RETURNED:    result   - Function-specific result
 *                         (kAdnErrUnsupportedCall == not supported)
 ***********************************************************************/
#define kAdnErrUnsupportedCall	0xFFFFFFFF
#define AdnDebugLicenseeSpecific(oemID, selector, param) \
		_SemihostOp3r(kAdnSemihostLicenseeSpecific, oemID, selector, param)



/***********************************************************************
 * FUNCTION:    AdnDebugMessage
 * DESCRIPTION: Display a debug message in the desktop debugger.
 * PARAMETERS:  messageP - pointer to null-terminated string to display
 * RETURNED:    nothing
 ***********************************************************************/
#define AdnDebugMessage(messageP) \
		_SemihostWrite0(kAdnSemihostArmWrite0, messageP)

#define AdnDebugMessageIf(condition, messageP) \
	do {if (condition) AdnDebugMessage(messageP);} while (0)


/***********************************************************************
 * FUNCTION:    AdnDebugBreak
 * DESCRIPTION: Break into the desktop debugger.
 * PARAMETERS:  none
 * RETURNED:    nothing
 ***********************************************************************/
#define AdnDebugBreak() \
		_SemihostBreak(kAdnSemihostPUDDebugBreak)



/***********************************************************************
 * FUNCTION:    AdnDebugUpdateLoadedModules
 * DESCRIPTION: Notify debugger of any recently loaded/unloaded modules.
 * PARAMETERS:  none
 * RETURNED:    nothing
 ***********************************************************************/
#define AdnDebugUpdateLoadedModules() \
		_SemihostOp0(kAdnSemihostPUDModuleTableUpdate)


/***********************************************************************
 * FUNCTION:    AdnDebugNativeRegisterAddr
 * DESCRIPTION: Ask debugger to register PACE Native Object. This is
 *				useful in the case where the code making this call
 *				needs to register Native code that lives elsewhere (e.g.
 *				in a different chunk), and thus AdnGetNativeCodeBaseAddr()
 *				won't retrieve the correct code base address. Generally,
 *				PACE Native Objects which are registering themselves should
 *				use the simpler form, AdnDebugNativeRegister(), below.
 * PARAMETERS:  dbType    - application database type (e.g. 'appl')
 *              dbCreator - application database creator code
 *              rsrcType  - PACE Native Object resource type (e.g. 'ARMC')
 *              rsrcID    - PACE Native Object resource ID
 *              codeAddr  - PACE Native Object code base address
 * RETURNED:    nothing
 ***********************************************************************/
#define AdnDebugNativeRegisterAddr(_dbType, _dbCreator, _rsrcType, _rsrcID, _codeAddr) \
		do {																			\
			AdnDbgPostLoadParamsType _postLoadParams;									\
			_postLoadParams.processID  = 0;											\
			_postLoadParams.moduleID   = (unsigned long)_codeAddr /*sectionCookie*/;	\
			_postLoadParams.codeAddr   = _codeAddr;									\
			_postLoadParams.dataAddr   = 0;											\
			_postLoadParams.libType    = _dbType;											\
			_postLoadParams.libCreator = _dbCreator;									\
			_postLoadParams.rsrcType   = _rsrcType;									\
			_postLoadParams.rsrcID     = _rsrcID;										\
			_postLoadParams.reserved   = 0;											\
			_SemihostPostLoad(kAdnSemihostNativeRegister, &_postLoadParams);		\
		} while(0)
		

/***********************************************************************
 * FUNCTION:    AdnDebugNativeRegister
 * DESCRIPTION: Ask debugger to register PACE Native Object.
 *				This should be done after locking the code.  Any
 *				previously unresolved breakpoints will be activated.
 * PARAMETERS:  dbType    - application database type (e.g. 'appl')
 *              dbCreator - application database creator code
 *              rsrcType  - PACE Native Object resource type (e.g. 'ARMC')
 *              rsrcID    - PACE Native Object resource ID
 * RETURNED:    nothing
 ***********************************************************************/
#define AdnDebugNativeRegister(_dbType, _dbCreator, _rsrcType, _rsrcID) \
		AdnDebugNativeRegisterAddr(_dbType, _dbCreator, _rsrcType, _rsrcID, AdnGetNativeCodeBaseAddr())


/***********************************************************************
 * FUNCTION:    AdnDebugNativeUnregisterAddr
 * DESCRIPTION: Ask debugger to unregister PACE Native Object. This is
 *				useful in the case where the code making this call
 *				needs to unregister Native code that lives elsewhere (e.g.
 *				in a different chunk), and thus AdnGetNativeCodeBaseAddr()
 *				won't retrieve the correct code base address. Generally,
 *				PACE Native Objects which are unregistering themselves should
 *				use the simpler form, AdnDebugNativeUnregister(), below.
 * PARAMETERS:  codeAddr  - PACE Native Object code base address
 * RETURNED:    nothing
 ***********************************************************************/
#define AdnDebugNativeUnregisterAddr(_codeAddr)											\
		{																				\
			AdnDbgPostUnloadParamsType _postUnloadParams;								\
			_postUnloadParams.processID = 0;											\
			_postUnloadParams.moduleID = (unsigned long)_codeAddr /*sectionCookie*/;	\
			_SemihostPostUnload(kAdnSemihostNativeUnregister, &_postUnloadParams);		\
		}

/***********************************************************************
 * FUNCTION:    AdnDebugNativeUnregister
 * DESCRIPTION: Ask debugger to unregister PACE Native Object.
 *				This should be done prior to unlocking the code since
 *				breakpoints in the code may need to be removed.
 * PARAMETERS:  none
 * RETURNED:    nothing
 ***********************************************************************/
#define AdnDebugNativeUnregister() \
		AdnDebugNativeUnregisterAddr(AdnGetNativeCodeBaseAddr())

/***********************************************************************
 * FUNCTION:    SetR10ToDataPointer
 * DESCRIPTION: Helper routine -- set register r10 to point to your
 *				data section (e.g., the GOT from gcc)
 *				(You did compile your code to be r10-relative, didn't you?).
 * PARAMETERS:  none
 * RETURNED:    nothing
 ***********************************************************************/
#define SetR10ToDataPointer(/*(const char *)*/ptr) \
		_SetR10ToThisPointer(ptr)

#endif	// Debugging or not

#endif // __ADNDEBUGMGR_H__
