1999-04-16 03:35:26 +02:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <time.h>
|
|
|
|
#include <errno.h>
|
|
|
|
|
|
|
|
#include <nwtypes.h>
|
|
|
|
#include <nwdfs.h>
|
|
|
|
#include <nwconio.h>
|
|
|
|
#include <nwadv.h>
|
|
|
|
#include <nwdbgapi.h>
|
|
|
|
#include <nwthread.h>
|
|
|
|
#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
|
2000-07-30 03:48:28 +02:00
|
|
|
frame_to_registers (struct StackFrame *frame, char *regs)
|
1999-04-16 03:35:26 +02:00
|
|
|
{
|
|
|
|
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
|
2000-07-30 03:48:28 +02:00
|
|
|
registers_to_frame (char *regs, struct StackFrame *frame)
|
1999-04-16 03:35:26 +02:00
|
|
|
{
|
|
|
|
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 volatile int mem_err;
|
|
|
|
|
|
|
|
#ifdef ALTERNATE_MEM_FUNCS
|
|
|
|
extern int ReadByteAltDebugger (char* addr, char *theByte);
|
|
|
|
extern int WriteByteAltDebugger (char* addr, char theByte);
|
|
|
|
int
|
2000-07-30 03:48:28 +02:00
|
|
|
get_char (char *addr)
|
1999-04-16 03:35:26 +02:00
|
|
|
{
|
|
|
|
char c;
|
|
|
|
|
|
|
|
if (!ReadByteAltDebugger (addr, &c))
|
|
|
|
mem_err = 1;
|
|
|
|
|
|
|
|
return c;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2000-07-30 03:48:28 +02:00
|
|
|
set_char (char *addr, int val)
|
1999-04-16 03:35:26 +02:00
|
|
|
{
|
|
|
|
if (!WriteByteAltDebugger (addr, val))
|
|
|
|
mem_err = 1;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
int
|
2000-07-30 03:48:28 +02:00
|
|
|
mem_write (char *dst, char *src, int len)
|
1999-04-16 03:35:26 +02:00
|
|
|
{
|
|
|
|
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
|
2000-07-30 03:48:28 +02:00
|
|
|
set_step_traps (struct StackFrame *frame)
|
1999-04-16 03:35:26 +02:00
|
|
|
{
|
|
|
|
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
|
2000-07-30 03:48:28 +02:00
|
|
|
clear_step_traps (struct StackFrame *frame)
|
1999-04-16 03:35:26 +02:00
|
|
|
{
|
|
|
|
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
|
2000-07-30 03:48:28 +02:00
|
|
|
do_status (char *ptr, struct StackFrame *frame)
|
1999-04-16 03:35:26 +02:00
|
|
|
{
|
|
|
|
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';
|
|
|
|
}
|