1//
2// debug_hndlr.S -- default Xtensa debug exception handler
3//
4// $Id: //depot/rel/Foxhill/dot.8/Xtensa/OS/hal/debug_hndlr.S#1 $
5
6// Copyright (c) 2003-2010 Tensilica Inc.
7//
8// Permission is hereby granted, free of charge, to any person obtaining
9// a copy of this software and associated documentation files (the
10// "Software"), to deal in the Software without restriction, including
11// without limitation the rights to use, copy, modify, merge, publish,
12// distribute, sublicense, and/or sell copies of the Software, and to
13// permit persons to whom the Software is furnished to do so, subject to
14// the following conditions:
15//
16// The above copyright notice and this permission notice shall be included
17// in all copies or substantial portions of the Software.
18//
19// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
23// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26
27#include <xtensa/coreasm.h>
28#include <xtensa/config/system.h>
29
30#if XCHAL_HAVE_DEBUG && XCHAL_HAVE_EXCEPTIONS
31
32	/*
33	 *  Default debug exception handler.
34	 *
35	 *  Note that the debug exception vector must save a3
36	 *  in EXCSAVE+XCHAL_DEBUGLEVEL before jumping here.
37	 *
38	 *  This handler is used when no debugger is present.
39	 *  The end result of executing this default handler
40	 *  is as if no debug exception had occurred, eg. as if
41	 *  the core was running at PS.INTLEVEL >= DEBUGLEVEL.
42	 *
43	 *  Because the debug exception vector might get
44	 *  placed in ROM, and be expected to work regardless
45	 *  of what executable image or OS is running in RAM,
46	 *  we're very careful not to use any RAM here.
47	 *  We don't know what RAM we can safely use.
48	 *  This tricky part to accomplishing this feat
49	 *  is to use only *one* register (a3, which was
50	 *  saved in EXCSAVE+XCHAL_DEBUGLEVEL), because we don't
51	 *  have RAM in which to safely store other regs.
52	 *
53	 *  A real debugger application would normally
54	 *  have some kind of conventions, or special
55	 *  hardware support, to have its own RAM workspace
56	 *  in which to save context and do real work
57	 *  in this handler.
58	 */
59
60
61#if XSHAL_DEBUG_VECTOR_ISROM
62	//  Debug exception vector is in ROM, so place the handler
63	//  in ROM also.  Otherwise running different executables
64	//  with that ROM will not work because the handler would
65	//  likely not be there or be at the wrong address.
66	//
67	.section	.srom.text, "ax"
68#else
69	//  Debug exception vector is in RAM, so we can safely
70	//  place the handler in RAM as well.
71	//
72	.text
73#endif
74
75	.global xthal_debugexc_defhndlr_nw
76	.align 4
77xthal_debugexc_defhndlr_nw:
78	rsr.debugcause	a3		// get cause of debug exception
79
80	//  Check for possible debug causes, in priority order.
81	//  We only handle the highest priority condition present.
82	//  (If there are multiple conditions, the lower priority
83	//   condition(s) will normally trigger upon return from
84	//   this exception handler.)
85
86	bbci.l	a3, DEBUGCAUSE_ICOUNT_SHIFT, 1f	// ICOUNT trap?
87	movi	a3, 0
88	wsr.icount a3				// clear ICOUNT
89	j	3f
90
91/*
92 *  Ensure that we have IBREAKs, otherwise the IBREAKENABLE
93 *  special register is not there:
94 */
95#if XCHAL_NUM_IBREAK > 0
961:	bbci.l	a3, DEBUGCAUSE_IBREAK_SHIFT, 1f	// IBREAK match?
97	movi	a3, 0
98	wsr.ibreakenable a3			// disable IBREAK traps
99	j	3f
100#endif
101
102/*  Also check for DBREAK registers:  */
103#if XCHAL_NUM_DBREAK > 0
1041:	bbci.l	a3, DEBUGCAUSE_DBREAK_SHIFT, 1f	// DBREAK match?
105	movi	a3, 0
106	wsr.dbreakc0 a3				// disable DBREAK register 0
107# if XCHAL_NUM_DBREAK > 1
108	wsr.dbreakc1 a3				// disable DBREAK register 1
109# endif
110	j	3f
111#endif
112
1131:	bbci.l	a3, DEBUGCAUSE_BREAK_SHIFT, 1f	// BREAK instruction?
114	//readsr epc XCHAL_DEBUGLEVEL a3	// get PC pointing to BREAK
115	//l8ui	a3, a3, 1			// get first 4-bit operand of BREAK (in 2nd byte)
116	//extui	a3, a3, (XCHAL_HAVE_BE*4), 4	// pos depends on endianness
117	//bnei	a3, 1, 3f			// is it a BREAK 1,x instruction?
118	readsr	epc XCHAL_DEBUGLEVEL a3		// get PC pointing to BREAK
119	addi	a3, a3, 3			// skip BREAK instruction
120	writesr	epc XCHAL_DEBUGLEVEL a3		// update PC
121	j	3f
122
1231:	bbci.l	a3, DEBUGCAUSE_BREAKN_SHIFT, 1f	// BREAK.N instruction?
124	readsr	epc XCHAL_DEBUGLEVEL a3		// get PC pointing to BREAK
125	addi	a3, a3, 2			// skip BREAK.N instruction
126	writesr	epc XCHAL_DEBUGLEVEL a3		// update PC
127	j	3f
128
1291:	bbci.l	a3, DEBUGCAUSE_DEBUGINT_SHIFT, 1f	// debug interrupt?
130	//  Nothing to do...
131	j	3f
132
1331:	//  Unknown debug case?  ignore
134
1353:	readsr	excsave XCHAL_DEBUGLEVEL a3	// restore a3
136	rfi	XCHAL_DEBUGLEVEL		// return from debug exception
137
138	.size	xthal_debugexc_defhndlr_nw, . - xthal_debugexc_defhndlr_nw
139
140
141#if XSHAL_DEBUG_VECTOR_ISROM
142	.text		// in case this gets included by something else
143#endif
144
145#endif /* XCHAL_HAVE_DEBUG */
146
147