Initial xloong code
[xloong.git] / pmon / arch / i386 / dbg_machdep.c
blob76707a783e02a018b65e2c80bc7064ea9f7b2801
1 /* $Id: dbg_machdep.c,v 1.1.1.1 2006/09/14 01:59:08 root Exp $ */
3 /*
4 * Copyright (c) 2000-2001 Opsycon AB (http://www.opsycon.se)
5 * Copyright (c) 2000-2001 RTMX, Inc (http://www.rtmx.com)
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed for Rtmx, Inc by
18 * Opsycon Open System Consulting AB, Sweden.
19 * 4. The name of the author may not be used to endorse or promote products
20 * derived from this software without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
23 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
24 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
26 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
36 #include <stdio.h>
37 #include <termio.h>
38 #include <ctype.h>
39 #include <stdlib.h>
40 #ifdef _KERNEL
41 #undef _KERNEL
42 #include <sys/ioctl.h>
43 #define _KERNEL
44 #else
45 #include <sys/ioctl.h>
46 #endif
48 #include <machine/cpu.h>
50 #include <pmon.h>
52 #include "mod_debugger.h"
54 extern struct trapframe DBGREG;
55 extern u_int32_t FPREG[];
56 extern int memorysize;
57 extern u_int8_t end[];
61 * Debug helpers.
63 void
64 md_setpc(pc)
65 register_t pc;
67 DBGREG.srr0 = pc;
71 * This function clears all client registers for launch.
73 void
74 md_clreg()
76 struct trapframe *tf;
77 int i;
79 tf = &DBGREG;
80 for(i = 0; i < 32; i++) {
81 tf->fixreg[i] = 0;
83 tf->lr = 0;
84 tf->cr = 0;
85 tf->xer = 0;
86 tf->ctr = 0;
87 tf->srr0 = 0;
88 tf->srr1 = initial_sr;
90 savebat(&tf->batreg[0]); /* Initially use PMON mapping */
94 * This function sets the client stack pointer.
96 void
97 md_setsp(sp)
98 register_t sp;
100 DBGREG.fixreg[1] = sp;
104 * This function sets the client sr to the given value.
106 void
107 md_setsr(sr)
108 register_t sr;
110 DBGREG.srr1 = sr;
114 * ator returns either 32 bit or 64 bit conversion
115 * depending on CPU word length. PPC is for now 32.
117 int32_t
118 md_ator(vp, p, base)
119 register_t *vp;
120 char *p;
121 int base;
123 return(atob((void *)vp, p, base));
127 * This function sets the SP to the new value given if it's
128 * non zero. The old value of sp is returned.
130 register_t
131 md_adjstack(newsp)
132 register_t newsp;
134 register_t oldsp;
136 oldsp = DBGREG.fixreg[1];
137 if(newsp != 0) {
138 DBGREG.fixreg[1] = newsp;
140 return(oldsp);
144 * This function returns true if the address range given is
145 * invalid for load, eg will overwrite PMON or its working
146 * areas or other protected memory areas or load into
147 * existing memory.
150 md_valid_load_addr(first_addr, last_addr)
151 paddr_t first_addr;
152 paddr_t last_addr;
154 /* XXX This should be more clever */
155 if((first_addr < (paddr_t)end) || (last_addr > (paddr_t)memorysize)) {
156 return(1);
158 return(0);
162 * This function sets the arguments to client code so
163 * the client sees the arguments as if it was called
164 * with the arguments.
166 void
167 md_setargs(a1, a2, a3, a4)
168 register_t a1;
169 register_t a2;
170 register_t a3;
171 register_t a4;
173 struct trapframe *tf;
175 tf = &DBGREG;
176 tf->fixreg[3] = a1;
177 tf->fixreg[4] = a2;
178 tf->fixreg[5] = a3;
179 tf->fixreg[6] = a4;
182 void
183 md_setentry(pc)
184 register_t pc;
186 DBGREG.srr0 = pc;
190 * This function sets the client sr to do a trace.
192 void
193 md_setlr(lr)
194 register_t lr;
196 DBGREG.lr = lr;
199 #if NMOD_DEBUGGER > 0
201 * This function returns the value of the clients sr.
203 register_t
204 md_getsr()
206 return(DBGREG.srr1);
210 * This function sets the client sr to do a trace.
212 void
213 md_settrace()
215 DBGREG.srr1 |= PSL_SE;
219 * This function returns the PC value that is supposed
220 * to be used at restore to client state. Do not confuse
221 * with the value of the exception PC. (Diff on some arches).
223 void *
224 md_getpc()
226 return((void *)DBGREG.srr0);
230 * This function is called from exception(). It's purpose
231 * is to decode the exception and return the exception
232 * type to the caller for further processing.
235 md_exc_type(frame)
236 struct trapframe *frame;
238 switch(frame->exc) {
239 /* XXX DSI check for DABP */
240 case EX_IABP:
241 return(EXC_BPT);
242 case EX_DECR:
243 case EX_EINT:
244 return(EXC_INT);
245 case EX_TRACE:
246 frame->srr1 &= ~(PSL_SE | PSL_BE);
247 return(EXC_TRC);
248 case EX_PRGM: /* Check for BP instruction */
249 if(load_word(md_get_excpc(frame)) == BPT_CODE) {
250 return(EXC_BPT);
252 break;
253 default:
254 break;
256 return(EXC_BAD);
260 * This function returns the value of the PC reg when an
261 * exception have been take.
263 void *
264 md_get_excpc(frame)
265 struct trapframe *frame;
267 return((void *)frame->srr0);
270 const char *
271 md_getexcname(frame)
272 struct trapframe *frame;
274 switch(frame->exc) {
275 default:
276 return("????");
277 case EX_MCHEK:
278 return("Machine Check");
279 case EX_DSI:
280 return("DSI");
281 case EX_ISI:
282 return("ISI");
283 case EX_EINT:
284 return("External Interrupt");
285 case EX_ALIGN:
286 return("Alignment");
287 case EX_PRGM:
288 return("Program");
289 case EX_NOFP:
290 return("No FP");
291 case EX_DECR:
292 return("Decrementer");
293 case EX_SC:
294 return("System Call");
295 case EX_TRACE:
296 return("Trace");
297 case EX_FPA:
298 return("FP Assistance");
299 case EX_PERF:
300 return("Performance Monitor");
301 case EX_IABP:
302 return("Instruction BP");
303 case EX_SMI:
304 return("System Management");
309 * This function returns true if the instruction pointed
310 * by 'p' is a subroutine call instruction.
313 md_is_call(p)
314 void *p;
316 return(0);
320 * This function returns true if the instruction pointed
321 * by 'p' is a branch type instruction.
324 md_is_branch(p)
325 void *p;
327 return(0);
331 * Returns true and sets the location pointed by vp to the value
332 * of the specified register or false if not recognized. Register
333 * names can be n the form <regno> r<nr> or sp.
334 * Some special registers are also detected.
337 md_getreg(vp, p)
338 register_t *vp;
339 char *p;
341 int i;
343 if(isdigit(*p)) {
344 i = atoi(p);
345 if(i >= 0 || i <= 31) {
346 *vp = DBGREG.fixreg[i];
347 return(1);
350 else if((*p == 'r' || *p == 'R') && isdigit(*(p+1))) {
351 i = atoi(p+1);
352 if(i >= 0 || i <= 31) {
353 *vp = DBGREG.fixreg[i];
354 return(1);
357 else if(strcmp(p, "cpc") == 0) {
358 *vp = DBGREG.srr0;
359 return(1);
361 else if(strcmp(p, "sr") == 0) {
362 *vp = DBGREG.srr1;
363 return(1);
365 else {
366 return(0);
371 md_getregaddr(r, p)
372 register_t **r;
373 char *p;
375 int i;
377 if(isdigit(*p)) {
378 i = atoi(p);
379 if(i >= 0 || i <= 31) {
380 *r = (register_t *)&DBGREG.fixreg[i];
381 return(1);
384 else if((*p == 'r' || *p == 'R') && isdigit(*(p+1))) {
385 i = atoi(p+1);
386 if(i >= 0 || i <= 31) {
387 *r = (register_t *)&DBGREG.fixreg[i];
388 return(1);
391 else if((*p == 'f' || *p == 'F') && isdigit(*(p+1))) {
392 i = atoi(p+1);
393 if(i >= 0 || i <= 31) {
394 *r = (register_t *)&FPREG[i+i];
395 return(1);
398 else if(strcmp(p, "cpc") == 0) {
399 *r = (register_t *)&DBGREG.srr0;
400 return(1);
402 else if(strcmp(p, "sr") == 0) {
403 *r = (register_t *)&DBGREG.srr1;
404 return(1);
406 else if(strcmp(p, "fsr") == 0) {
407 *r = (register_t *)&FPREG[64];
408 return(1);
410 else if(strcmp(p, "lr") == 0) {
411 *r = (register_t *)&DBGREG.lr;
412 return(1);
414 else if(strcmp(p, "ctr") == 0) {
415 *r = (register_t *)&DBGREG.ctr;
416 return(1);
418 else {
419 return(0);
421 return(0);
425 md_disp_as_reg(r, c, w)
426 register_t *r;
427 char *c;
428 int *w;
430 return(0);
433 const Optdesc md_r_opts[] = {
434 {"*", "display all registers"},
435 {"r*", "display all general registers"},
436 {"f*", "display all fp registers"},
437 {"reg value", "set specified register"},
441 static void
442 dsp_rregs(void)
444 int regno;
446 for(regno = 0; regno < 32; regno++) {
447 if((regno % 8) == 0) {
448 printf("\nr%02d-%02d ", regno, regno + 7);
450 printf(" %08x", DBGREG.fixreg[regno]);
452 printf("\n");
455 static void
456 dsp_fregs(void)
458 int regno;
460 for(regno = 0; regno < 32; regno++) {
461 if((regno % 4) == 0) {
462 printf("\nf%02d-%02d ", regno, regno + 3);
464 printf(" %08x%08x", FPREG[regno*2], FPREG[regno*2+1]);
466 printf("\n");
467 printf("fsr = %08x%08x\n", FPREG[64], FPREG[65]);
471 * Machine dependent register display/modify code.
474 md_registers(ac, av)
475 int ac;
476 char *av[];
478 register_t *rp;
479 register_t rn;
481 ioctl(STDIN, CBREAK, NULL);
483 switch(ac) {
484 case 1: /* No args, display general registers */
485 dsp_rregs();
486 break;
488 case 2:
489 if(strcmp(av[1], "*") == 0) {
490 dsp_rregs();
491 dsp_fregs();
492 printf("cpc = %08x, lr = %08x, ctr = %08x, sr = %08x\n",
493 DBGREG.srr0, DBGREG.lr, DBGREG.ctr, DBGREG.srr1);
495 else if(strcmp(av[1], "r*") == 0) {
496 dsp_rregs();
498 else if(strcmp(av[1], "f*") == 0) {
499 dsp_fregs();
501 else {
502 if(md_getregaddr(&rp, av[1])) {
503 printf("%s = %08x\n", av[1], *rp);
505 else {
506 printf("%s: unkown.\n", av[1]);
507 return(-1);
510 break;
512 case 3:
513 if(md_getregaddr(&rp, av[1]) == 0) {
514 printf("%s: unkown.\n", av[1]);
515 return(-1);
517 if(!get_rsa_reg(&rn, av[2])) {
518 return(-1);
520 *rp = rn;
521 break;
524 return(0);
527 #endif /* NMOD_DEBUGGER */