#include #include #include #include #include #include #include #include #include #include #include "ppc.h" extern char *mem2hex (void *mem, char *buf, int count, int may_fault); extern char *hex2mem (char *buf, void *mem, int count, int may_fault); extern int computeSignal (int exceptionVector); void flush_i_cache (void) { } /* Get the registers out of the frame information. */ void frame_to_registers (frame, regs) struct StackFrame *frame; char *regs; { mem2hex (&frame->ExceptionState.CsavedRegs, ®s[GP0_REGNUM * 4 * 2], 4 * 32, 0); mem2hex (&frame->ExceptionState.CSavedFPRegs, ®s[FP0_REGNUM * 4 * 2], 4 * 32, 0); mem2hex (&frame->ExceptionPC, ®s[PC_REGNUM * 4 * 2], 4 * 1, 0); mem2hex (&frame->ExceptionState.u.SpecialRegistersEnumerated.CsavedSRR1, ®s[CR_REGNUM * 4 * 2], 4 * 1, 0); mem2hex (&frame->ExceptionState.u.SpecialRegistersEnumerated.CsavedLR, ®s[LR_REGNUM * 4 * 2], 4 * 1, 0); mem2hex (&frame->ExceptionState.u.SpecialRegistersEnumerated.CsavedCTR, ®s[CTR_REGNUM * 4 * 2], 4 * 1, 0); mem2hex (&frame->ExceptionState.u.SpecialRegistersEnumerated.CsavedXER, ®s[XER_REGNUM * 4 * 2], 4 * 1, 0); mem2hex (&frame->ExceptionState.u.SpecialRegistersEnumerated.CsavedMQ, ®s[MQ_REGNUM * 4 * 2], 4 * 1, 0); } /* Put the registers back into the frame information. */ void registers_to_frame (regs, frame) char *regs; struct StackFrame *frame; { hex2mem (®s[GP0_REGNUM * 4 * 2], &frame->ExceptionState.CsavedRegs, 4 * 32, 0); hex2mem (®s[FP0_REGNUM * 4 * 2], &frame->ExceptionState.CSavedFPRegs, 4 * 32, 0); hex2mem (®s[PC_REGNUM * 4 * 2], &frame->ExceptionPC, 4 * 1, 0); hex2mem (®s[CR_REGNUM * 4 * 2], &frame->ExceptionState.u.SpecialRegistersEnumerated.CsavedSRR1, 4 * 1, 0); hex2mem (®s[LR_REGNUM * 4 * 2], &frame->ExceptionState.u.SpecialRegistersEnumerated.CsavedLR, 4 * 1, 0); hex2mem (®s[CTR_REGNUM * 4 * 2], &frame->ExceptionState.u.SpecialRegistersEnumerated.CsavedCTR, 4 * 1, 0); hex2mem (®s[XER_REGNUM * 4 * 2], &frame->ExceptionState.u.SpecialRegistersEnumerated.CsavedXER, 4 * 1, 0); hex2mem (®s[MQ_REGNUM * 4 * 2], &frame->ExceptionState.u.SpecialRegistersEnumerated.CsavedMQ, 4 * 1, 0); } extern int ReadByteAltDebugger (char* addr, char *theByte); extern int WriteByteAltDebugger (char* addr, char theByte); extern volatile int mem_err; int get_char (addr) char *addr; { char c; if (!ReadByteAltDebugger (addr, &c)) mem_err = 1; return c; } void set_char (addr, val) char *addr; int val; { if (!WriteByteAltDebugger (addr, val)) mem_err = 1; } int mem_write (dst, src, len) char *dst, *src; int len; { while (len-- && !mem_err) set_char (dst++, *src++); return mem_err; } union inst { LONG l; struct { union { struct /* Unconditional branch */ { unsigned opcode : 6; /* 18 */ signed li : 24; unsigned aa : 1; unsigned lk : 1; } b; struct /* Conditional branch */ { unsigned opcode : 6; /* 16 */ unsigned bo : 5; unsigned bi : 5; signed bd : 14; unsigned aa : 1; unsigned lk : 1; } bc; struct /* Conditional branch to ctr or lr reg */ { unsigned opcode : 6; /* 19 */ unsigned bo : 5; unsigned bi : 5; unsigned type : 15; /* 528 = ctr, 16 = lr */ unsigned lk : 1; } bclr; } variant; } inst; }; static LONG saved_inst; static LONG *saved_inst_pc = 0; static LONG saved_target_inst; static LONG *saved_target_inst_pc = 0; void set_step_traps (frame) struct StackFrame *frame; { union inst inst; LONG *target; int opcode; int ra, rb; LONG *pc = (LONG *)frame->ExceptionPC; inst.l = *pc++; opcode = inst.inst.variant.b.opcode; target = pc; switch (opcode) { case 18: /* Unconditional branch */ if (inst.inst.variant.b.aa) /* Absolute? */ target = 0; target += inst.inst.variant.b.li; break; case 16: /* Conditional branch */ if (!inst.inst.variant.bc.aa) /* Absolute? */ target = 0; target += inst.inst.variant.bc.bd; break; case 19: /* Cond. branch via ctr or lr reg */ switch (inst.inst.variant.bclr.type) { case 528: /* ctr */ target = (LONG *)frame->ExceptionState.u.SpecialRegistersEnumerated.CsavedCTR; break; case 16: /* lr */ target = (LONG *)frame->ExceptionState.u.SpecialRegistersEnumerated.CsavedLR; break; } break; } saved_inst = *pc; mem_write (pc, breakpoint_insn, BREAKPOINT_SIZE); saved_inst_pc = pc; if (target != pc) { saved_target_inst = *target; mem_write (target, breakpoint_insn, BREAKPOINT_SIZE); saved_target_inst_pc = target; } } /* Remove step breakpoints. Returns non-zero if pc was at a step breakpoint, zero otherwise. This routine works even if there were no step breakpoints set. */ int clear_step_traps (frame) struct StackFrame *frame; { int retcode; LONG *pc = (LONG *)frame->ExceptionPC; if (saved_inst_pc == pc || saved_target_inst_pc == pc) retcode = 1; else retcode = 0; if (saved_inst_pc) { mem_write (saved_inst_pc, saved_inst, BREAKPOINT_SIZE); saved_inst_pc = 0; } if (saved_target_inst_pc) { mem_write (saved_target_inst_pc, saved_target_inst, BREAKPOINT_SIZE); saved_target_inst_pc = 0; } return retcode; } void do_status (ptr, frame) char *ptr; struct StackFrame *frame; { int sigval; sigval = computeSignal (frame->ExceptionNumber); sprintf (ptr, "T%02x", sigval); ptr += 3; sprintf (ptr, "%02x:", PC_REGNUM); ptr = mem2hex (&frame->ExceptionPC, ptr + 3, 4, 0); *ptr++ = ';'; sprintf (ptr, "%02x:", SP_REGNUM); ptr = mem2hex (&frame->ExceptionState.CsavedRegs[SP_REGNUM], ptr + 3, 4, 0); *ptr++ = ';'; sprintf (ptr, "%02x:", LR_REGNUM); ptr = mem2hex (&frame->ExceptionState.CsavedRegs[LR_REGNUM], ptr + 3, 4, 0); *ptr++ = ';'; *ptr = '\000'; } #if 0 /* * strtol : convert a string to long. * * Andy Wilson, 2-Oct-89. */ /* FIXME: It'd be nice to configure around these, but the include files are too painful. These macros should at least be more portable than hardwired hex constants. */ #define ULONG_MAX ((unsigned long)(~0L)) /* 0xFFFFFFFF */ #define LONG_MAX ((long)(ULONG_MAX >> 1)) /* 0x7FFFFFFF */ #define LONG_MIN ((long)(~LONG_MAX)) /* 0x80000000 */ extern int errno; unsigned long strtoul(const char *s, char **ptr, int base); long strtol(s, ptr, base) const char *s; char **ptr; int base; { int minus=0; unsigned long tmp; const char *start=s; char *eptr; if (s==NULL) { errno = ERANGE; if (!ptr) *ptr = (char *)start; return 0L; } while (isspace(*s)) s++; if (*s == '-') { s++; minus = 1; } else if (*s == '+') s++; /* * let strtoul do the hard work. */ tmp = strtoul(s, &eptr, base); if (ptr != NULL) *ptr = (char *)((eptr==s) ? (char *)start : eptr); if (tmp > (minus ? - (unsigned long) LONG_MIN : (unsigned long) LONG_MAX)) { errno = ERANGE; return (minus ? LONG_MIN : LONG_MAX); } return (minus ? (long) -tmp : (long) tmp); } /* * strtol : convert a string to long. * * Andy Wilson, 2-Oct-89. */ #ifndef ULONG_MAX #define ULONG_MAX ((unsigned long)(~0L)) /* 0xFFFFFFFF */ #endif extern int errno; unsigned long strtoul(s, ptr, base) const char *s; char **ptr; int base; { unsigned long total = 0; unsigned digit; const char *start=s; int did_conversion=0; int overflow = 0; int negate = 0; unsigned long maxdiv, maxrem; if (s==NULL) { errno = ERANGE; if (!ptr) *ptr = (char *)start; return 0L; } while (isspace(*s)) s++; if (*s == '+') s++; else if (*s == '-') s++, negate = 1; if (base==0 || base==16) /* the 'base==16' is for handling 0x */ { int tmp; /* * try to infer base from the string */ if (*s != '0') tmp = 10; /* doesn't start with 0 - assume decimal */ else if (s[1] == 'X' || s[1] == 'x') tmp = 16, s += 2; /* starts with 0x or 0X - hence hex */ else tmp = 8; /* starts with 0 - hence octal */ if (base==0) base = (int)tmp; } maxdiv = ULONG_MAX / base; maxrem = ULONG_MAX % base; while ((digit = *s) != '\0') { if (digit >= '0' && digit < ('0'+base)) digit -= '0'; else if (base > 10) { if (digit >= 'a' && digit < ('a'+(base-10))) digit = digit - 'a' + 10; else if (digit >= 'A' && digit < ('A'+(base-10))) digit = digit - 'A' + 10; else break; } else break; did_conversion = 1; if (total > maxdiv || (total == maxdiv && digit > maxrem)) overflow = 1; total = (total * base) + digit; s++; } if (overflow) { errno = ERANGE; if (ptr != NULL) *ptr = (char *)s; return (ULONG_MAX); } if (ptr != NULL) *ptr = (char *) ((did_conversion) ? (char *)s : (char *)start); return negate ? -total : total; } #endif void _exit (int foo) __attribute__ ((noreturn)); void exit (int foo) { _exit (foo); }