1/*
2 * Copyright (c) 2000-2005 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28/*
29 * @OSF_COPYRIGHT@
30 */
31
32#include <mach_kdb.h>
33#include <mach_kgdb.h>
34#include <mach_debug.h>
35#include <assym.s>
36#include <ppc/asm.h>
37#include <ppc/proc_reg.h>
38#include <mach/ppc/vm_param.h>
39
40/*
41 * vm_offset_t getrpc(void) - Return address of the function
42 *	                      that called the current function
43 */
44
45/* By using this function, we force the caller to save its LR in a known
46 * location, which we can pick up and return. See PowerPC ELF specs.
47 */
48ENTRY(getrpc, TAG_NO_FRAME_USED)
49	lwz	ARG0,	FM_BACKPTR(r1)		/* Load our backchain ptr */
50	lwz	ARG0,	FM_LR_SAVE(ARG0)	/* Load previously saved LR */
51	blr					/* And return */
52
53
54/*
55 *	General entry for all debuggers.  This gets us onto the debug stack and
56 *	then back off at exit. We need to pass back R3 to caller.
57 */
58
59ENTRY(Call_Debugger, TAG_NO_FRAME_USED)
60
61
62			lis		r8,hi16(MASK(MSR_VEC))			; Get the vector flag
63			mfmsr	r7				; Get the current MSR
64			ori		r8,r8,lo16(MASK(MSR_EE)|MASK(MSR_FP))	; Add the FP flag
65			mflr	r0				; Save the return
66			andc	r7,r7,r8						; Clear VEC and FP
67			mtmsr	r7				; Do it
68			isync
69			mfsprg	r8,1					; Get the current activation
70			lwz		r8,ACT_PER_PROC(r8)		; Get the per_proc block
71			stw		r0,FM_LR_SAVE(r1)	; Save return on current stack
72
73			lwz		r9,PP_DEBSTACKPTR(r8)	; Get the debug stack
74			cmpwi	r9,0			; Are we already on it?
75			bne		cdNewDeb		; No...
76
77			mr		r9,r1 			; We are already on the stack, so use the current value
78			subi	r9,r9,FM_REDZONE+FM_SIZE	; Carve some extra space here
79
80cdNewDeb:	li		r0,0			; Clear this out
81			stw		r1,FM_ARG0(r9)	; Save the old stack pointer as if it were the first arg
82
83			stw		r0,PP_DEBSTACKPTR(r8)	; Mark debug stack as busy
84
85			subi	r1,r9,FM_SIZE	; Carve a new frame
86			stw		r0,FM_BACKPTR(r1)	; Chain back
87
88			bl		EXT(Call_DebuggerC)	; Call the "C" phase of this
89
90			lis		r8,hi16(MASK(MSR_VEC))			; Get the vector flag
91			mfmsr	r0				; Get the current MSR
92			ori		r8,r8,lo16(MASK(MSR_EE)|MASK(MSR_FP))	; Add the FP flag
93			addi	r1,r1,FM_SIZE	; Pop off first stack frame
94			andc	r0,r0,r8		; Turn off all the interesting stuff
95			mtmsr	r0
96
97			mfsprg	r8,1					; Get the current activation
98			lwz		r8,ACT_PER_PROC(r8)		; Get the per_proc block
99
100			lwz		r9,PP_DEBSTACK_TOP_SS(r8)	; Get the top of the stack
101			cmplw	r1,r9			; Have we hit the bottom of the debug stack?
102			lwz		r1,FM_ARG0(r1)	; Get previous stack frame
103			lwz		r0,FM_LR_SAVE(r1)	; Get return address
104			mtlr	r0				; Set the return point
105			bnelr					; Return if still on debug stack
106
107			stw		r9,PP_DEBSTACKPTR(r8)	; Mark debug stack as free
108			blr
109
110
111/* The following routines are for C-support. They are usually
112 * inlined into the C using the specifications in proc_reg.h,
113 * but if optimisation is switched off, the inlining doesn't work
114 */
115
116ENTRY(get_got, TAG_NO_FRAME_USED)
117	mr	ARG0,	r2
118	blr
119
120ENTRY(mflr, TAG_NO_FRAME_USED)
121	mflr	ARG0
122	blr
123
124ENTRY(mfpvr, TAG_NO_FRAME_USED)
125	mfpvr	ARG0
126	blr
127
128ENTRY(mtmsr, TAG_NO_FRAME_USED)
129	mtmsr	ARG0
130	isync
131	blr
132
133ENTRY(mfmsr, TAG_NO_FRAME_USED)
134	mfmsr	ARG0
135	blr
136
137ENTRY(mtsrin, TAG_NO_FRAME_USED)
138	isync
139	mtsrin	ARG0,	ARG1
140	isync
141	blr
142
143ENTRY(mfsrin, TAG_NO_FRAME_USED)
144	mfsrin	ARG0,	ARG0
145	blr
146
147ENTRY(mtsdr1, TAG_NO_FRAME_USED)
148	mtsdr1	ARG0
149	blr
150
151ENTRY(mtdar, TAG_NO_FRAME_USED)
152	mtdar	ARG0
153	blr
154
155ENTRY(mfdar, TAG_NO_FRAME_USED)
156	mfdar	ARG0
157	blr
158
159ENTRY(mtdec, TAG_NO_FRAME_USED)
160	mtdec	ARG0
161	blr
162
163ENTRY(cntlzw, TAG_NO_FRAME_USED)
164	cntlzw	r3,r3
165	blr
166
167/* Decrementer frequency and realtime|timebase processor registers
168 * are different between ppc601 and ppc603/4, we define them all.
169 */
170
171ENTRY(isync_mfdec, TAG_NO_FRAME_USED)
172	isync
173	mfdec	ARG0
174	blr
175
176
177ENTRY(mftb, TAG_NO_FRAME_USED)
178	mftb	ARG0
179	blr
180
181ENTRY(mftbu, TAG_NO_FRAME_USED)
182	mftbu	ARG0
183	blr
184
185ENTRY(mfrtcl, TAG_NO_FRAME_USED)
186	mfspr	ARG0,	5
187	blr
188
189ENTRY(mfrtcu, TAG_NO_FRAME_USED)
190	mfspr	ARG0,	4
191	blr
192
193ENTRY(tlbie, TAG_NO_FRAME_USED)
194	tlbie	ARG0
195	blr
196
197
198/*
199 * Performance Monitor Register Support
200 */
201
202ENTRY(mfmmcr0, TAG_NO_FRAME_USED)
203	mfspr	r3,mmcr0
204	blr
205
206ENTRY(mtmmcr0, TAG_NO_FRAME_USED)
207	mtspr	mmcr0,r3
208	blr
209
210ENTRY(mfmmcr1, TAG_NO_FRAME_USED)
211	mfspr	r3,mmcr1
212	blr
213
214ENTRY(mtmmcr1, TAG_NO_FRAME_USED)
215	mtspr	mmcr1,r3
216	blr
217
218ENTRY(mfmmcr2, TAG_NO_FRAME_USED)
219	mfspr	r3,mmcr2
220	blr
221
222ENTRY(mtmmcr2, TAG_NO_FRAME_USED)
223	mtspr	mmcr2,r3
224	blr
225
226ENTRY(mfpmc1, TAG_NO_FRAME_USED)
227	mfspr	r3,pmc1
228	blr
229
230ENTRY(mtpmc1, TAG_NO_FRAME_USED)
231	mtspr	pmc1,r3
232	blr
233
234ENTRY(mfpmc2, TAG_NO_FRAME_USED)
235	mfspr	r3,pmc2
236	blr
237
238ENTRY(mtpmc2, TAG_NO_FRAME_USED)
239	mtspr	pmc2,r3
240	blr
241
242ENTRY(mfpmc3, TAG_NO_FRAME_USED)
243	mfspr	r3,pmc3
244	blr
245
246ENTRY(mtpmc3, TAG_NO_FRAME_USED)
247	mtspr	pmc3,r3
248	blr
249
250ENTRY(mfpmc4, TAG_NO_FRAME_USED)
251	mfspr	r3,pmc4
252	blr
253
254ENTRY(mtpmc4, TAG_NO_FRAME_USED)
255	mtspr	pmc4,r3
256	blr
257
258ENTRY(mfsia, TAG_NO_FRAME_USED)
259	mfspr	r3,sia
260	blr
261
262ENTRY(mfsda, TAG_NO_FRAME_USED)
263	mfspr	r3,sda
264	blr
265
266	.globl	EXT(hid1get)
267LEXT(hid1get)
268
269	mfspr	r3,hid1					; Get the HID1
270	blr
271
272	.globl	EXT(hid0get64)
273LEXT(hid0get64)
274
275	mfspr	r4,hid0					; Get the HID0
276	srdi	r3,r4,32				; Move top down
277	rlwinm	r4,r4,0,0,31			; Clean top
278	blr
279
280	.globl	EXT(hid5set64)
281LEXT(hid5set64)
282
283	rlwinm	r3,r3,0,1,0				; Copy low 32 int high 32
284	rlwimi	r3,r4,0,0,31			; Inser the low part behind top
285	mtspr	hid5,r3					; Set it
286	isync							; Wait for it
287	blr
288