#include <sys/file.h>
#include <sys/stat.h>
#include <machine/psl.h>
-
-#ifdef KERNELDEBUG
-#include <sys/vmmac.h>
-#include <machine/machparam.h>
-#include <machine/vmparam.h>
-#include <machine/pde.h>
-#include <machine/cpu.h>
-#include <machine/iomod.h>
-#include <machine/pcb.h>
-#include <machine/rpb.h>
-#include <ctype.h>
-
-extern int kernel_debugging;
-extern CORE_ADDR startup_file_start;
-extern CORE_ADDR startup_file_end;
-
-#define KERNOFF ((unsigned)KERNBASE)
-#define INKERNEL(x) ((x) >= KERNOFF && (x) < KERNOFF + ctob(slr))
-
-static int ok_to_cache();
-static void set_kernel_boundaries();
-
-int devmem = 0;
-int vtophys_ready = 0;
-int kerneltype;
-#define OS_BSD 1
-#define OS_MACH 2
-#endif
+#include "wait.h"
#include "gdbcore.h"
#include "gdbcmd.h"
+#include "target.h"
-extern int errno;
\f
-
-
-
-
-
/* Last modification time of executable file.
Also used in source.c to compare against mtime of a source file. */
struct header file_hdr;
struct som_exec_auxhdr exec_hdr;
\f
-#ifdef KERNELDEBUG
-/*
- * Kernel debugging routines.
- */
-
-static struct pcb pcb;
-static struct pde *pdir;
-static struct hte *htbl;
-static u_int npdir, nhtbl;
-
-static CORE_ADDR
-ksym_lookup(name)
- char *name;
-{
- struct symbol *sym;
- int i;
-
- if ((i = lookup_misc_func(name)) < 0)
- error("kernel symbol `%s' not found.", name);
-
- return (misc_function_vector[i].address);
-}
-
-/*
- * (re-)set the variables that tell "inside_entry_file" where to end
- * a stack backtrace.
- */
-void
-set_kernel_boundaries()
-{
- switch (kerneltype) {
- case OS_MACH:
- startup_file_start = ksym_lookup("$syscall");
- startup_file_end = ksym_lookup("trap");
- break;
- case OS_BSD:
- startup_file_start = ksym_lookup("syscallinit");
- startup_file_end = ksym_lookup("$syscallexit");
- break;
- }
-}
-
-/*
- * return true if 'len' bytes starting at 'addr' can be read out as
- * longwords and/or locally cached (this is mostly for memory mapped
- * i/o register access when debugging remote kernels).
- */
-static int
-ok_to_cache(addr, len)
-{
- static CORE_ADDR ioptr;
-
- if (! ioptr)
- ioptr = ksym_lookup("ioptr");
-
- if (addr >= ioptr && addr < SPA_HIGH)
- return (0);
-
- return (1);
-}
-
-static
-physrd(addr, dat, len)
- u_int addr;
- char *dat;
-{
- if (lseek(corechan, addr, L_SET) == -1)
- return (-1);
- if (read(corechan, dat, len) != len)
- return (-1);
-
- return (0);
-}
-
-/*
- * When looking at kernel data space through /dev/mem or with a core file, do
- * virtual memory mapping.
- */
-static CORE_ADDR
-vtophys(space, addr)
- unsigned space;
- CORE_ADDR addr;
-{
- struct pde *pptr;
- u_int hindx, vpageno, ppageno;
- CORE_ADDR phys = ~0;
-
- if (!vtophys_ready) {
- phys = addr; /* XXX for kvread */
- } else if (kerneltype == OS_BSD) {
- /* make offset into a virtual page no */
- vpageno = btop(addr);
- /*
- * Determine index into hash table, initialize pptr to this
- * entry (since first word of pte & hte are same), and set
- * physical page number for first entry in chain.
- */
- hindx = pdirhash(space, addr) & (nhtbl-1);
- pptr = (struct pde *) &htbl[hindx];
- ppageno = pptr->pde_next;
- while (1) {
- if (pptr->pde_end)
- break;
- pptr = &pdir[ppageno];
- /*
- * If space id & virtual page number match, return
- * "next PDIR entry of previous PDIR entry" as the
- * physical page or'd with offset into page.
- */
- if (pptr->pde_space == space &&
- pptr->pde_page == vpageno) {
- phys = (CORE_ADDR) ((u_int)ptob(ppageno) |
- (addr & PGOFSET));
- break;
- }
- ppageno = pptr->pde_next;
- }
- }
-#ifdef MACHKERNELDEBUG
- else if (kerneltype == OS_MACH) {
- mach_vtophys(space, addr, &phys);
- }
-#endif
-#if 0
- printf("vtophys(%x.%x) -> %x\n", space, addr, phys);
-#endif
- return (phys);
-}
-
-static
-kvread(addr)
- CORE_ADDR addr;
-{
- CORE_ADDR paddr;
-
- paddr = vtophys(0, addr);
- if (paddr != ~0)
- if (physrd(paddr, (char *)&addr, sizeof(addr)) == 0)
- return (addr);
-
- return (~0);
-}
-
-static void
-read_pcb(addr)
- u_int addr;
-{
- int i, off;
- extern char registers[];
- static int reg2pcb[] = {
- /* RPB */
- -1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
- 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
- 45, 52, 51, 75, 74, 49, 53, 54, 55, 56, -1, 70, 66, 67, 68, 69,
- 71, 72, 73, 34, 42, 43, 44, 46, 47, 58, 59, 60, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1,
- /* BSD */
- -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
- 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
- 43, 64, 67, 68, 67, 47, 51, 52, 53, 54, -1, 35, 31, 32, 33, 34,
- 36, 37, 38, 39, 40, 41, 42, 44, 45, 56, 57, 58,102,103,104, -1,
- 70, 71, 72, 73, 74, 75, 76, 77, 78, 80, 82, 84, 86, 88, 90, 92,
- 94, 96, 98, 100,
- /* Mach */
- -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
- 14, 15, 16, -1, -1, -1, -1, -1, -1, -1, -1, 17, -1, -1, 18, -1,
- 25, -1, -1, -1, -1, 30, -1, -1, -1, -1, -1, 20, -1, -1, -1, 19,
- 21, 22, 23, 24, 26, 27, -1, 28, 29, -1, -1, -1, -1, -1, -1, -1,
- 34, 35, 36, 37, 38, 39, 40, 41, -1, -1, -1, -1, -1, -1, -1, -1,
- 42, 44, 46, 48
- };
- static struct rpb *rpbaddr = (struct rpb *) 0;
- static u_int rpbpcbaddr = 0;
-
- if (!remote_debugging) {
- /*
- * If we are debugging a post-mortem and this is the first
- * call of read_pcb, read the RPB. Also assoicate the
- * thread/proc running at the time with the RPB.
- */
- if (!devmem && rpbpcbaddr == 0) {
- CORE_ADDR raddr = ksym_lookup("rpb");
- int usepcb = 1;
-
- if (raddr != ~0) {
- rpbaddr = (struct rpb *) malloc(sizeof *rpbaddr);
- if (!physrd(raddr, (char *)rpbaddr, sizeof *rpbaddr)) {
- rpbpcbaddr = addr;
- usepcb = 0;
- }
- }
- if (usepcb) {
- error("cannot read rpb, using pcb for registers\n");
- if (rpbaddr)
- free((char *)rpbaddr);
- rpbpcbaddr = ~0;
- }
- }
- if (physrd (addr, (char *)&pcb, sizeof pcb))
- error ("cannot read pcb at %x.\n", addr);
- } else {
- if (remote_read_inferior_memory(addr, (char *)&pcb, sizeof pcb))
- error ("cannot read pcb at %x.\n", addr);
- }
-
- if (kerneltype == OS_BSD) {
- printf("p0br %lx p0lr %lx p1br %lx p1lr %lx\n",
- pcb.pcb_p0br, pcb.pcb_p0lr, pcb.pcb_p1br, pcb.pcb_p1lr);
- off = NUM_REGS;
- } else {
- printf("pcb %lx psw %lx ksp %lx\n",
- addr, ((int *)&pcb)[31], ((int *)&pcb)[32]);
- off = NUM_REGS * 2;
- }
- /*
- * get the register values out of the sys pcb and
- * store them where `read_register' will find them.
- */
- bzero(registers, REGISTER_BYTES);
- for (i = 0; i < NUM_REGS; ++i)
- if (reg2pcb[i+off] != -1)
- supply_register(i, &((int *)&pcb)[reg2pcb[i+off]]);
- /*
- * If the RPB is valid for this thread/proc use the register values
- * contained there.
- */
- if (addr == rpbpcbaddr) {
- off = 0;
- for (i = 0; i < NUM_REGS; ++i)
- if (reg2pcb[i+off] != -1)
- supply_register(i, &((int *)rpbaddr)[reg2pcb[i+off]]);
- }
-}
-
-void
-setup_kernel_debugging()
-{
- struct stat stb;
- CORE_ADDR addr;
-
- fstat(corechan, &stb);
- devmem = 0;
- if ((stb.st_mode & S_IFMT) == S_IFCHR && stb.st_rdev == makedev(2, 0))
- devmem = 1;
-
- /* XXX */
- if (lookup_misc_func("Sysmap") < 0)
- kerneltype = OS_MACH;
- else
- kerneltype = OS_BSD;
-
- if (kerneltype == OS_BSD) {
- int len, err = 0;
-
- /*
- * Hash table and PDIR are equivalently mapped
- */
- nhtbl = kvread(ksym_lookup("nhtbl"));
- if (nhtbl != ~0) {
- len = nhtbl * sizeof(*htbl);
- htbl = (struct hte *) malloc(len);
- if (htbl) {
- addr = kvread(ksym_lookup("htbl"));
- if (physrd(addr, (char *)htbl, len))
- err++;
- } else
- err++;
- } else
- err++;
- npdir = kvread(ksym_lookup("npdir"));
- if (npdir != ~0) {
- len = npdir * sizeof(*pdir);
- pdir = (struct pde *) malloc(len);
- if (pdir) {
- addr = kvread(ksym_lookup("pdir"));
- if (physrd(addr, (char *)pdir, len))
- err++;
- } else
- err++;
- } else
- err++;
- if (err) {
- error("cannot read PDIR/HTBL");
- return;
- }
- vtophys_ready = 1;
-
- /*
- * pcb where "panic" saved registers in first thing in
- * current u-area. The current u-area is pointed to by
- * "uptr".
- */
- addr = kvread(ksym_lookup("uptr"));
- if (addr == ~0) {
- error("cannot read current u-area address");
- return;
- }
- read_pcb(vtophys(0, addr)); /* XXX space */
- if (!devmem) {
- /* find stack frame */
- CORE_ADDR panicstr;
- char buf[256];
- register char *cp;
-
- panicstr = kvread(ksym_lookup("panicstr"));
- if (panicstr == ~0)
- return;
- kernel_core_file_hook(panicstr, buf, sizeof(buf));
- for (cp = buf; cp < &buf[sizeof(buf)] && *cp; cp++)
- if (!isascii(*cp) || (!isprint(*cp) && !isspace(*cp)))
- *cp = '?';
- if (*cp)
- *cp = '\0';
- printf("panic: %s\n", buf);
- }
- }
-#ifdef MACHKERNELDEBUG
- else {
- int *thread;
-
- /*
- * Set up address translation
- */
- if (mach_vtophys_init() == 0) {
- error("cannot initialize vtophys for Mach");
- return;
- }
- vtophys_ready = 1;
-
- /*
- * Locate active thread and read PCB
- * XXX MAJOR HACK
- * - assumes uni-processor
- * - assumes position of pcb to avoid mach includes
- */
- thread = (int *)kvread(ksym_lookup("active_threads"));
- addr = kvread(&thread[9]); /* XXX: pcb addr */
- read_pcb(vtophys(0, addr));
- }
-#endif
-}
-
-vtop_command(arg)
- char *arg;
-{
- u_int sp, off, pa;
-
- if (!arg)
- error_no_arg("kernel virtual address");
- if (!kernel_debugging)
- error("not debugging kernel");
-
- sp = 0; /* XXX */
- off = (u_int) parse_and_eval_address(arg);
- pa = vtophys(sp, off);
- printf("%lx.%lx -> ", sp, off);
- if (pa == ~0)
- printf("<invalid>\n");
- else
- printf("%lx\n", pa);
-}
-
-set_paddr_command(arg)
- char *arg;
-{
- u_int addr;
-
- if (!arg) {
- if (kerneltype == OS_BSD)
- error_no_arg("ps-style address for new process");
- else
- error_no_arg("thread structure virtual address");
- }
- if (!kernel_debugging)
- error("not debugging kernel");
-
- addr = (u_int) parse_and_eval_address(arg);
- if (kerneltype == OS_BSD)
- addr = ctob(addr);
- else {
- addr = kvread(&(((int *)addr)[9])); /* XXX: pcb addr */
- addr = vtophys(0, addr); /* XXX space */
- }
- read_pcb(addr);
-
- flush_cached_frames();
- set_current_frame(create_new_frame(read_register(FP_REGNUM), read_pc()));
- select_frame(get_current_frame(), 0);
-}
-
-/*
- * read len bytes from kernel virtual address 'addr' into local
- * buffer 'buf'. Return 0 if read ok, 1 otherwise. On read
- * errors, portion of buffer not read is zeroed.
- */
-kernel_core_file_hook(addr, buf, len)
- CORE_ADDR addr;
- char *buf;
- int len;
-{
- int i;
- CORE_ADDR paddr;
-
- while (len > 0) {
- paddr = vtophys(0, addr); /* XXX space */
- if (paddr == ~0) {
- bzero(buf, len);
- return (1);
- }
- /* we can't read across a page boundary */
- i = min(len, NBPG - (addr & PGOFSET));
- if (physrd(paddr, buf, i)) {
- bzero(buf, len);
- return (1);
- }
- buf += i;
- addr += i;
- len -= i;
- }
- return (0);
-}
-#endif
-
-
-\f
-
-
-
/* Routines to extract various sized constants out of hppa
instructions. */
GET_FIELD (word, 11, 15) << 11 |
(word & 0x1) << 16, 17) << 2;
}
-
-
+\f
CORE_ADDR
frame_saved_pc (frame)
FRAME frame;
{
struct frame_saved_regs saved_regs;
CORE_ADDR pc = get_frame_pc (frame);
+ int flags;
+ flags = read_register (FLAGS_REGNUM);
get_frame_saved_regs (frame, &saved_regs);
- if (pc >= millicode_start && pc < millicode_end)
- return read_register (31);
+ if (pc >= millicode_start && pc < millicode_end
+ || (flags & 2)) /* In system call? */
+ return read_register (31) & ~3;
else if (saved_regs.regs[RP_REGNUM])
- return read_memory_integer (saved_regs.regs[RP_REGNUM], 4);
+ return read_memory_integer (saved_regs.regs[RP_REGNUM], 4) & ~3;
else
- return read_register (RP_REGNUM);
+ return read_register (RP_REGNUM) & ~3;
}
return read_memory_integer (frame->frame - 20, 4) & ~0x3;
}
-
/* To see if a frame chain is valid, see if the caller looks like it
was compiled with gcc. */
FRAME_ADDR chain;
FRAME thisframe;
{
- if (chain && (chain > 0x60000000
- /* || remote_debugging -this is no longer used */
-#ifdef KERNELDEBUG
- || kernel_debugging
-#endif
- ))
+ if (chain && (chain > 0x60000000))
{
CORE_ADDR pc = get_pc_function_start (FRAME_SAVED_PC (thisframe));
return 0;
}
+/*
+ * These functions deal with saving and restoring register state
+ * around a function call in the inferior. They keep the stack
+ * double-word aligned; eventually, on an hp700, the stack will have
+ * to be aligned to a 64-byte boundary.
+ */
+
+int
+push_dummy_frame ()
+{
+ register CORE_ADDR sp = read_register (SP_REGNUM);
+ register int regnum;
+ int int_buffer;
+ double freg_buffer;
+ /* Space for "arguments"; the RP goes in here. */
+ sp += 48;
+ int_buffer = read_register (RP_REGNUM) | 0x3;
+ write_memory (sp - 20, (char *)&int_buffer, 4);
+ int_buffer = read_register (FP_REGNUM);
+ write_memory (sp, (char *)&int_buffer, 4);
+ write_register (FP_REGNUM, sp);
+ sp += 8;
+ for (regnum = 1; regnum < 32; regnum++)
+ if (regnum != RP_REGNUM && regnum != FP_REGNUM)
+ sp = push_word (sp, read_register (regnum));
+ sp += 4;
+ for (regnum = FP0_REGNUM; regnum < NUM_REGS; regnum++)
+ { read_register_bytes (REGISTER_BYTE (regnum), (char *)&freg_buffer, 8);
+ sp = push_bytes (sp, (char *)&freg_buffer, 8);}
+ sp = push_word (sp, read_register (IPSW_REGNUM));
+ sp = push_word (sp, read_register (SAR_REGNUM));
+ sp = push_word (sp, read_register (PCOQ_HEAD_REGNUM));
+ sp = push_word (sp, read_register (PCSQ_HEAD_REGNUM));
+ sp = push_word (sp, read_register (PCOQ_TAIL_REGNUM));
+ sp = push_word (sp, read_register (PCSQ_TAIL_REGNUM));
+ write_register (SP_REGNUM, sp);
+}
+
find_dummy_frame_regs (frame, frame_saved_regs)
struct frame_info *frame;
struct frame_saved_regs *frame_saved_regs;
{
CORE_ADDR fp = frame->frame;
int i;
-
+
frame_saved_regs->regs[RP_REGNUM] = fp - 20 & ~0x3;
frame_saved_regs->regs[FP_REGNUM] = fp;
frame_saved_regs->regs[1] = fp + 8;
frame_saved_regs->regs[3] = fp + 12;
- for (fp += 16, i = 3; i < 30; fp += 4, i++)
+ for (fp += 16, i = 5; i < 32; fp += 4, i++)
frame_saved_regs->regs[i] = fp;
- frame_saved_regs->regs[31] = fp;
fp += 4;
for (i = FP0_REGNUM; i < NUM_REGS; i++, fp += 8)
frame_saved_regs->regs[i] = fp;
- /* depend on last increment of fp */
- frame_saved_regs->regs[IPSW_REGNUM] = fp - 4;
- frame_saved_regs->regs[SAR_REGNUM] = fp;
- fp += 4;
- frame_saved_regs->regs[PCOQ_TAIL_REGNUM] = fp;
+ frame_saved_regs->regs[IPSW_REGNUM] = fp; fp += 4;
+ frame_saved_regs->regs[SAR_REGNUM] = fp; fp += 4;
+ frame_saved_regs->regs[PCOQ_HEAD_REGNUM] = fp; fp +=4;
+ frame_saved_regs->regs[PCSQ_HEAD_REGNUM] = fp; fp +=4;
+ frame_saved_regs->regs[PCOQ_TAIL_REGNUM] = fp; fp +=4;
frame_saved_regs->regs[PCSQ_TAIL_REGNUM] = fp;
}
+int
+hp_pop_frame ()
+{
+ register FRAME frame = get_current_frame ();
+ register CORE_ADDR fp;
+ register int regnum;
+ struct frame_saved_regs fsr;
+ struct frame_info *fi;
+ double freg_buffer;
+ fi = get_frame_info (frame);
+ fp = fi->frame;
+ get_frame_saved_regs (fi, &fsr);
+ if (fsr.regs[IPSW_REGNUM]) /* Restoring a call dummy frame */
+ hp_restore_pc_queue (&fsr);
+ for (regnum = 31; regnum > 0; regnum--)
+ if (fsr.regs[regnum])
+ write_register (regnum, read_memory_integer (fsr.regs[regnum], 4));
+ for (regnum = NUM_REGS - 1; regnum >= FP0_REGNUM ; regnum--)
+ if (fsr.regs[regnum])
+ { read_memory (fsr.regs[regnum], (char *)&freg_buffer, 8);
+ write_register_bytes (REGISTER_BYTE (regnum), (char *)&freg_buffer, 8);
+ }
+ if (fsr.regs[IPSW_REGNUM])
+ write_register (IPSW_REGNUM,
+ read_memory_integer (fsr.regs[IPSW_REGNUM], 4));
+ if (fsr.regs[SAR_REGNUM])
+ write_register (SAR_REGNUM,
+ read_memory_integer (fsr.regs[SAR_REGNUM], 4));
+ if (fsr.regs[PCOQ_TAIL_REGNUM])
+ write_register (PCOQ_TAIL_REGNUM,
+ read_memory_integer (fsr.regs[PCOQ_TAIL_REGNUM], 4));
+ write_register (FP_REGNUM, read_memory_integer (fp, 4));
+ if (fsr.regs[IPSW_REGNUM]) /* call dummy */
+ write_register (SP_REGNUM, fp - 48);
+ else
+ write_register (SP_REGNUM, fp);
+ flush_cached_frames ();
+ set_current_frame (create_new_frame (read_register (FP_REGNUM),
+ read_pc ()));
+}
+
+/*
+ * After returning to a dummy on the stack, restore the instruction
+ * queue space registers. */
+
+int
+hp_restore_pc_queue (fsr)
+ struct frame_saved_regs *fsr;
+{
+ CORE_ADDR pc = read_pc ();
+ CORE_ADDR new_pc = read_memory_integer (fsr->regs[PCOQ_HEAD_REGNUM], 4);
+ int pid;
+ WAITTYPE w;
+ int insn_count;
+
+ /* Advance past break instruction in the call dummy. */
+ pc += 4; write_register (PCOQ_HEAD_REGNUM, pc);
+ pc += 4; write_register (PCOQ_TAIL_REGNUM, pc);
+
+ /*
+ * HPUX doesn't let us set the space registers or the space
+ * registers of the PC queue through ptrace. Boo, hiss.
+ * Conveniently, the call dummy has this sequence of instructions
+ * after the break:
+ * mtsp r21, sr0
+ * ble,n 0(sr0, r22)
+ *
+ * So, load up the registers and single step until we are in the
+ * right place.
+ */
+
+ write_register (21, read_memory_integer (fsr->regs[PCSQ_HEAD_REGNUM], 4));
+ write_register (22, new_pc);
+
+ for (insn_count = 0; insn_count < 3; insn_count++)
+ {
+ resume (1, 0);
+ target_wait(&w);
+
+ if (!WIFSTOPPED (w))
+ {
+ stop_signal = WTERMSIG (w);
+ terminal_ours_for_output ();
+ printf ("\nProgram terminated with signal %d, %s\n",
+ stop_signal, safe_strsignal (stop_signal));
+ fflush (stdout);
+ return 0;
+ }
+ }
+ fetch_inferior_registers (-1);
+ return 1;
+}
+
CORE_ADDR
hp_push_arguments (nargs, args, sp, struct_return, struct_addr)
int nargs;
cum = (cum + alignment) & -alignment;
offset[i] = -cum;
}
- for (i == 0; i < nargs; i++)
+ sp += min ((cum + 7) & -8, 16);
+ for (i = 0; i < nargs; i++)
{
- write_memory (sp + offset[i], VALUE_CONTENTS (args[i]), sizeof(int));
+ write_memory (sp + offset[i], VALUE_CONTENTS (args[i]),
+ TYPE_LENGTH (VALUE_TYPE (args[i])));
}
- sp += min ((cum + 7) & -8, 48);
if (struct_return)
write_register (28, struct_addr);
- return sp + 48;
+ return sp + 32;
}
/* return the alignment of a type in bytes. Structures have the maximum
for (i = 0; i < NUM_REGS; i++)
read_relative_register_raw_bytes (i, raw_regs + REGISTER_BYTE (i));
- if (regnum = -1)
- pa_print_registers (raw_regs, regnum);
+ if (regnum == -1)
+ pa_print_registers (raw_regs, regnum, fpregs);
else if (regnum < FP0_REGNUM)
{
printf ("%s %x\n", reg_names[regnum], *(long *)(raw_regs +
pa_print_fp_reg (regnum);
}
-pa_print_registers (raw_regs, regnum)
+pa_print_registers (raw_regs, regnum, fpregs)
char *raw_regs;
int regnum;
+ int fpregs;
{
int i;
*(int *)(raw_regs + REGISTER_BYTE (i + 36)),
reg_names[i + 54],
*(int *)(raw_regs + REGISTER_BYTE (i + 54)));
- for (i = 72; i < NUM_REGS; i++)
- pa_print_fp_reg (i);
+
+ if (fpregs)
+ for (i = 72; i < NUM_REGS; i++)
+ pa_print_fp_reg (i);
}
pa_print_fp_reg (i)
}
-/*
- * Virtual to physical translation routines for Utah's Mach 3.0
- */
-#ifdef MACHKERNELDEBUG
-
-#define STATIC
-
-#if 0 /* too many includes to resolve, too much crap */
-#include <kern/queue.h>
-#include <vm/pmap.h>
-#include <mach/vm_prot.h>
-#else
-/* queue.h */
-struct queue_entry {
- struct queue_entry *next; /* next element */
- struct queue_entry *prev; /* previous element */
-};
-
-typedef struct queue_entry *queue_t;
-typedef struct queue_entry queue_head_t;
-typedef struct queue_entry queue_chain_t;
-typedef struct queue_entry *queue_entry_t;
-
-/* pmap.h */
-#define HP800_HASHSIZE 1024
-#define HP800_HASHSIZE_LOG2 10
-
-#define pmap_hash(space, offset) \
- (((unsigned) (space) << 5 ^ \
- ((unsigned) (offset) >> 19 | (unsigned) (space) << 13) ^ \
- (unsigned) (offset) >> 11) & (HP800_HASHSIZE-1))
-
-struct mapping {
- queue_head_t hash_link; /* hash table links */
- queue_head_t phys_link; /* for mappings of a given PA */
- space_t space; /* virtual space */
- unsigned offset; /* virtual page number */
- unsigned tlbpage; /* physical page (for TLB load) */
- unsigned tlbprot; /* prot/access rights (for TLB load) */
- struct pmap *pmap; /* pmap mapping belongs to */
-};
-
-struct phys_entry {
- queue_head_t phys_link; /* head of mappings of a given PA */
- struct mapping *writer; /* mapping with R/W access */
- unsigned tlbprot; /* TLB format protection */
-};
-
-#endif
-
-#define atop(a) ((unsigned)(a) >> 11)
-#define ptoa(p) ((unsigned)(p) << 11)
-#define trunc_page(a) ((unsigned)(a) & ~2047)
-
-STATIC long equiv_end;
-STATIC queue_head_t *Ovtop_table, *vtop_table, *Ofree_mapping, free_mapping;
-STATIC struct phys_entry *Ophys_table, *phys_table;
-STATIC long vm_last_phys, vm_first_phys;
-STATIC struct mapping *firstmap, *lastmap, *Omap_table, *map_table;
-STATIC unsigned Omlow, Omhigh, Omhead, Ovlow, Ovhigh, Oplow, Ophigh;
-STATIC unsigned mlow, mhigh, mhead, vlow, vhigh, plow, phigh;
-STATIC int vtopsize, physsize, mapsize;
-STATIC int kmemfd;
-
-#define IS_OVTOPPTR(p) ((unsigned)(p) >= Ovlow && (unsigned)(p) < Ovhigh)
-#define IS_OMAPPTR(p) ((unsigned)(p) >= Omlow && (unsigned)(p) < Omhigh)
-#define IS_OPHYSPTR(p) ((unsigned)(p) >= Oplow && (unsigned)(p) < Ophigh)
-#define IS_VTOPPTR(p) ((unsigned)(p) >= vlow && (unsigned)(p) < vhigh)
-#define IS_MAPPTR(p) ((unsigned)(p) >= mlow && (unsigned)(p) < mhigh)
-#define IS_PHYSPTR(p) ((unsigned)(p) >= plow && (unsigned)(p) < phigh)
-
-struct mapstate {
- char unused;
- char flags;
- short hashix;
- short physix;
-} *mapstate;
-
-/* flags */
-#define M_ISFREE 1
-#define M_ISHASH 2
-#define M_ISPHYS 4
-
-mach_vtophys_init()
-{
- int errors = 0;
-
- if (!readdata())
- errors++;
- if (!verifydata())
- errors++;
- if (!errors)
- return(1);
- fflush(stdout);
- fprintf(stderr,
- "translate: may not be able to translate all addresses\n");
- return(0);
-}
-
-mach_vtophys(space, off, pa)
- unsigned space, off, *pa;
-{
- register int i;
- register queue_t qp;
- register struct mapping *mp;
- int poff;
-
- /*
- * Kernel IO or equivilently mapped, one to one.
- */
- if (space == 0 && (long)off < equiv_end) {
- *pa = off;
- return(1);
- }
- /*
- * Else look it up in specified space
- */
- poff = off - trunc_page(off);
- off = trunc_page(off);
- qp = &vtop_table[pmap_hash(space, off)];
- for (mp = (struct mapping *)qp->next;
- qp != (queue_entry_t)mp;
- mp = (struct mapping *)mp->hash_link.next) {
- if (mp->space == space && mp->offset == off) {
- *pa = (mp->tlbpage << 7) | poff;
- return(1);
- }
- }
- return(0);
-}
+/* Function calls that pass into a new compilation unit must pass through a
+ small piece of code that does long format (`external' in HPPA parlance)
+ jumps. We figure out where the trampoline is going to end up, and return
+ the PC of the final destination. If we aren't in a trampoline, we just
+ return NULL. */
-STATIC
-readdata()
-{
- char *tmp, *mach_malloc();
- long size;
-
- /* easy scalars */
- mach_read("equiv_end", ~0, (char *)&equiv_end, sizeof equiv_end);
- mach_read("vm_first_phys", ~0,
- (char *)&vm_first_phys, sizeof vm_first_phys);
- mach_read("vm_last_phys", ~0,
- (char *)&vm_last_phys, sizeof vm_last_phys);
- mach_read("firstmap", ~0, (char *)&firstmap, sizeof firstmap);
- mach_read("lastmap", ~0, (char *)&lastmap, sizeof lastmap);
-
- /* virtual to physical hash table */
- vtopsize = HP800_HASHSIZE;
- size = vtopsize * sizeof(queue_head_t);
- tmp = mach_malloc("vtop table", size);
- mach_read("vtop_table", ~0, (char *)&Ovtop_table, sizeof Ovtop_table);
- mach_read("vtop table", (CORE_ADDR)Ovtop_table, tmp, size);
- vtop_table = (queue_head_t *) tmp;
-
- /* inverted page table */
- physsize = atop(vm_last_phys - vm_first_phys);
- size = physsize * sizeof(struct phys_entry);
- tmp = mach_malloc("phys table", size);
- mach_read("phys_table", ~0, (char *)&Ophys_table, sizeof Ophys_table);
- mach_read("phys table", (CORE_ADDR)Ophys_table, tmp, size);
- phys_table = (struct phys_entry *) tmp;
-
- /* mapping structures */
- Ofree_mapping = (queue_head_t *) ksym_lookup("free_mapping");
- mach_read("free mapping", (CORE_ADDR)Ofree_mapping,
- (char *) &free_mapping, sizeof free_mapping);
- Omap_table = firstmap;
- mapsize = lastmap - firstmap;
- size = mapsize * sizeof(struct mapping);
- tmp = mach_malloc("mapping table", size);
- mach_read("mapping table", (CORE_ADDR)Omap_table, tmp, size);
- map_table = (struct mapping *) tmp;
-
- /* set limits */
- Ovlow = (unsigned) Ovtop_table;
- Ovhigh = (unsigned) &Ovtop_table[vtopsize];
- Oplow = (unsigned) Ophys_table;
- Ophigh = (unsigned) &Ophys_table[physsize];
- Omhead = (unsigned) Ofree_mapping;
- Omlow = (unsigned) firstmap;
- Omhigh = (unsigned) lastmap;
- mlow = (unsigned) map_table;
- mhigh = (unsigned) &map_table[mapsize];
- mhead = (unsigned) &free_mapping;
- vlow = (unsigned) vtop_table;
- vhigh = (unsigned) &vtop_table[vtopsize];
- plow = (unsigned) phys_table;
- phigh = (unsigned) &phys_table[physsize];
-
-#if 0
- fprintf(stderr, "Ovtop [%#x-%#x) Ophys [%#x-%#x) Omap %#x [%#x-%#x)\n",
- Ovlow, Ovhigh, Oplow, Ophigh, Omhead, Omlow, Omhigh);
- fprintf(stderr, "vtop [%#x-%#x) phys [%#x-%#x) map %#x [%#x-%#x)\n",
- vlow, vhigh, plow, phigh, mhead, mlow, mhigh);
-#endif
- return(adjustdata());
-}
-
-STATIC unsigned
-ptrcvt(ptr)
- unsigned ptr;
-{
- unsigned ret;
- char *str;
-
- if (ptr == 0) {
- ret = ptr;
- str = "null";
- } else if (IS_OVTOPPTR(ptr)) {
- ret = vlow + (ptr - Ovlow);
- str = "vtop";
- } else if (IS_OPHYSPTR(ptr)) {
- ret = plow + (ptr - Oplow);
- str = "phys";
- } else if (IS_OMAPPTR(ptr)) {
- ret = mlow + (ptr - Omlow);
- str = "map";
- } else if (ptr == Omhead) {
- ret = mhead;
- str = "maphead";
- } else {
- error("bogus pointer %#x", ptr);
- str = "wild";
- ret = ptr;
- }
-#if 0
- fprintf(stderr, "%x (%s) -> %x\n", ptr, str, ret);
-#endif
- return(ret);
-}
-
-STATIC int
-adjustdata()
-{
- register int i, lim;
- queue_head_t *nq;
- struct phys_entry *np;
- struct mapping *nm;
-
- /* hash table */
- lim = vtopsize;
- for (nq = vtop_table; nq < &vtop_table[lim]; nq++) {
- nq->next = (queue_entry_t) ptrcvt((unsigned)nq->next);
- nq->prev = (queue_entry_t) ptrcvt((unsigned)nq->prev);
- }
-
- /* IPT */
- lim = physsize;
- for (np = phys_table; np < &phys_table[lim]; np++) {
- np->phys_link.next = (queue_entry_t)
- ptrcvt((unsigned)np->phys_link.next);
- np->phys_link.prev = (queue_entry_t)
- ptrcvt((unsigned)np->phys_link.prev);
- np->writer = (struct mapping *) ptrcvt((unsigned)np->writer);
- }
-
- /* mapping table */
- free_mapping.next = (queue_entry_t)ptrcvt((unsigned)free_mapping.next);
- free_mapping.prev = (queue_entry_t)ptrcvt((unsigned)free_mapping.prev);
- lim = mapsize;
- for (nm = map_table; nm < &map_table[lim]; nm++) {
- nm->hash_link.next = (queue_entry_t)
- ptrcvt((unsigned)nm->hash_link.next);
- nm->hash_link.prev = (queue_entry_t)
- ptrcvt((unsigned)nm->hash_link.prev);
- nm->phys_link.next = (queue_entry_t)
- ptrcvt((unsigned)nm->phys_link.next);
- nm->phys_link.prev = (queue_entry_t)
- ptrcvt((unsigned)nm->phys_link.prev);
- }
- return(1);
-}
-
-/*
- * Consistency checks, make sure:
- *
- * 1. all mappings are accounted for
- * 2. no cycles
- * 3. no wild pointers
- * 4. consisent TLB state
- */
-STATIC int
-verifydata()
-{
- register struct mapstate *ms;
- register int i;
- int errors = 0;
-
- mapstate = (struct mapstate *)
- mach_malloc("map state", mapsize * sizeof(struct mapstate));
- for (ms = mapstate; ms < &mapstate[mapsize]; ms++) {
- ms->flags = 0;
- ms->hashix = ms->physix = -2;
- }
-
- /*
- * Check the free list
- */
- checkhashchain(&free_mapping, M_ISFREE, -1);
- /*
- * Check every hash chain
- */
- for (i = 0; i < vtopsize; i++)
- checkhashchain(&vtop_table[i], M_ISHASH, i);
- /*
- * Check every phys chain
- */
- for (i = 0; i < physsize; i++)
- checkphyschain(&phys_table[i].phys_link, M_ISPHYS, i);
- /*
- * Cycle through mapstate looking for anomolies
- */
- ms = mapstate;
- for (i = 0; i < mapsize; i++) {
- switch (ms->flags) {
- case M_ISFREE:
- case M_ISHASH|M_ISPHYS:
- break;
- case 0:
- merror(ms, "not found");
- errors++;
- break;
- case M_ISHASH:
- merror(ms, "in vtop but not phys");
- errors++;
- break;
- case M_ISPHYS:
- merror(ms, "in phys but not vtop");
- errors++;
- break;
- default:
- merror(ms, "totally bogus");
- errors++;
- break;
- }
- ms++;
- }
- return(errors ? 0 : 1);
-}
-
-STATIC void
-checkhashchain(qhp, flag, ix)
- queue_entry_t qhp;
-{
- register queue_entry_t qp, pqp;
- register struct mapping *mp;
- struct mapstate *ms;
-
- qp = qhp->next;
- /*
- * First element is not a mapping structure,
- * chain must be empty.
- */
- if (!IS_MAPPTR(qp)) {
- if (qp != qhp || qp != qhp->prev)
- fatal("bad vtop_table header pointer");
- } else {
- pqp = qhp;
- do {
- mp = (struct mapping *) qp;
- qp = &mp->hash_link;
- if (qp->prev != pqp)
- fatal("bad hash_link prev pointer");
- ms = &mapstate[mp-map_table];
- ms->flags |= flag;
- ms->hashix = ix;
- pqp = (queue_entry_t) mp;
- qp = qp->next;
- } while (IS_MAPPTR(qp));
- if (qp != qhp)
- fatal("bad hash_link next pointer");
- }
-}
-
-STATIC void
-checkphyschain(qhp, flag, ix)
- queue_entry_t qhp;
-{
- register queue_entry_t qp, pqp;
- register struct mapping *mp;
- struct mapstate *ms;
-
- qp = qhp->next;
- /*
- * First element is not a mapping structure,
- * chain must be empty.
- */
- if (!IS_MAPPTR(qp)) {
- if (qp != qhp || qp != qhp->prev)
- fatal("bad phys_table header pointer");
- } else {
- pqp = qhp;
- do {
- mp = (struct mapping *) qp;
- qp = &mp->phys_link;
- if (qp->prev != pqp)
- fatal("bad phys_link prev pointer");
- ms = &mapstate[mp-map_table];
- ms->flags |= flag;
- ms->physix = ix;
- pqp = (queue_entry_t) mp;
- qp = qp->next;
- } while (IS_MAPPTR(qp));
- if (qp != qhp)
- fatal("bad phys_link next pointer");
- }
-}
-
-STATIC void
-merror(ms, str)
- struct mapstate *ms;
- char *str;
-{
- terminal_ours();
- fflush(stdout);
- fprintf(stderr,
- "vtophys: %s: %c%c%c, hashix %d, physix %d, mapping %x\n",
- str,
- (ms->flags & M_ISFREE) ? 'F' : '-',
- (ms->flags & M_ISHASH) ? 'H' : '-',
- (ms->flags & M_ISPHYS) ? 'P' : '-',
- ms->hashix, ms->physix, &map_table[ms-mapstate]);
- return_to_top_level();
-}
-
-STATIC int
-mach_read(str, from, top, size)
- char *str;
- CORE_ADDR from;
- char *top;
- int size;
+CORE_ADDR
+skip_trampoline_code (pc)
+ CORE_ADDR pc;
{
- CORE_ADDR paddr;
+ long inst0, inst1;
- if (from == ~0)
- from = ksym_lookup(str);
- paddr = vtophys(0, from);
- if (paddr == ~0 || physrd(paddr, top, size) != 0)
- fatal("cannot read %s", str);
-}
-
-STATIC char *
-mach_malloc(str, size)
- char *str;
- int size;
-{
- char *ptr = (char *) malloc(size);
+ inst0 = read_memory_integer (pc, 4);
+ inst1 = read_memory_integer (pc+4, 4);
- if (ptr == 0)
- fatal("no memory for %s", str);
- return(ptr);
-}
-#endif
+ if ( (inst0 & 0xffe00000) == 0x20200000 /* ldil xxx, r1 */
+ && (inst1 & 0xffe0e002) == 0xe0202002) /* be,n yyy(sr4, r1) */
+ pc = extract_21 (inst0) + extract_17 (inst1);
+ else
+ pc = NULL;
-#ifdef KERNELDEBUG
-void
-_initialize_hp9k8_dep()
-{
- add_com ("process-address", class_obscure, set_paddr_command,
-"The process identified by (ps-style) ADDR becomes the\n\
-\"current\" process context for kernel debugging.");
- add_com_alias ("paddr", "process-address", class_obscure, 0);
- add_com ("virtual-to-physical", class_obscure, vtop_command,
-"Translates the kernel virtual address ADDR into a physical address.");
- add_com_alias ("vtop", "virtual-to-physical", class_obscure, 0);
+ return pc;
}
-#endif
-/* Parameters for execution on a Hewlett-Packard PA-RISC machine.
+/* Parameters for execution on a Hewlett-Packard PA-RISC machine, running
+ HPUX or BSD.
Copyright 1986, 1987, 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
Contributed by the Center for Software Science at the
else if ((read_memory_integer (pc, 4) & ~MASK_14) == 0x68810000) \
(pc) += 4;}
+/* If PC is in some function-call trampoline code, return the PC
+ where the function itself actually starts. If not, return NULL. */
+
+#define SKIP_TRAMPOLINE_CODE(pc) skip_trampoline_code (pc)
+
+/* Return non-zero if we are in some sort of a trampoline. */
+
+#define IN_SOLIB_TRAMPOLINE(pc,name) skip_trampoline_code (pc)
+
/* Immediately after a function call, return the saved pc.
Can't go through the frames for this because on some machines
the new frame is not set up until the new function executes
to be actual register numbers as far as the user is concerned
but do serve to get the desired values when passed to read_register. */
+#define FLAGS_REGNUM 0 /* Various status flags */
#define RP_REGNUM 2 /* return pointer */
#define FP_REGNUM 4 /* Contains address of executing stack */
/* frame */
/* Convert data from raw format for register REGNUM
to virtual format for register REGNUM. */
-#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,FROM,TO) \
-{ bcopy ((FROM), (TO), (REGNUM) < FP4_REGNUM ? 4 : 8); }
+#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM, FROM, TO) \
+{ memcpy ((TO), (FROM), (REGNUM) < FP4_REGNUM ? 4 : 8); }
/* Convert data from virtual format for register REGNUM
to raw format for register REGNUM. */
-#define REGISTER_CONVERT_TO_RAW(REGNUM,FROM,TO) \
-{ bcopy ((FROM), (TO), (REGNUM) < FP4_REGNUM ? 4 : 8); }
+#define REGISTER_CONVERT_TO_RAW(REGNUM, FROM, TO) \
+{ memcpy ((TO), (FROM), (REGNUM) < FP4_REGNUM ? 4 : 8); }
/* Return the GDB type object for the "standard" data type
of data in register N. */
#define EXTRACT_STRUCT_VALUE_ADDRESS(REGBUF) (*(int *)((REGBUF) + 28))
+/*
+ * This macro defines the register numbers (from REGISTER_NAMES) that
+ * are effectively unavailable to the user through ptrace(). It allows
+ * us to include the whole register set in REGISTER_NAMES (inorder to
+ * better support remote debugging). If it is used in
+ * fetch/store_inferior_registers() gdb will not complain about I/O errors
+ * on fetching these registers. If all registers in REGISTER_NAMES
+ * are available, then return false (0).
+ */
+
+#define CANNOT_STORE_REGISTER(regno) \
+ ((regno) == 0) || \
+ ((regno) == PCSQ_HEAD_REGNUM) || \
+ ((regno) >= PCSQ_TAIL_REGNUM && (regno) < IPSW_REGNUM) || \
+ ((regno) > IPSW_REGNUM && (regno) < FP4_REGNUM)
+
/* This is a piece of magic that is given a register number REGNO
and as BLOCKEND the address in the system of the end of the user structure
and stores in ADDR the address in the kernel or core dump
#define ADDIL_P(INSN) (((INSN) & 0xfc000000) == 0x28000000)
#define LDO_P(INSN) (((INSN) & 0xfc00c000) == 0x34000000)
-
#define FRAME_FIND_SAVED_REGS(frame_info, frame_saved_regs) \
{ register int regnum; \
register CORE_ADDR next_addr; \
unsigned address; \
\
bzero (&frame_saved_regs, sizeof frame_saved_regs); \
- if ((frame_info)->pc <= ((frame_info)->frame - CALL_DUMMY_LENGTH - \
- FP_REGNUM * 4 - 16 * 8) \
- && (frame_info)->pc > (frame_info)->frame) \
+ if ((frame_info->pc >= (frame_info)->frame \
+ && (frame_info)->pc <= ((frame_info)->frame + CALL_DUMMY_LENGTH \
+ + 32 * 4 + (NUM_REGS - FP0_REGNUM) * 8 \
+ + 6 * 4))) \
find_dummy_frame_regs ((frame_info), &(frame_saved_regs)); \
else \
{ pc = get_pc_function_start ((frame_info)->pc); \
{ regnum = GET_FIELD (this_insn, 27, 31); \
(frame_saved_regs).regs[regnum + FP0_REGNUM] = next_addr; \
next_addr += 8; \
+ pc += 4; \
} \
else \
break; \
/* Push an empty stack frame, to record the current PC, etc. */
-#define PUSH_DUMMY_FRAME \
-{ register CORE_ADDR sp = read_register (SP_REGNUM); \
- register int regnum; \
- int int_buffer; \
- char freg_buffer[8]; \
- /* Space for "arguments"; the RP goes in here. */ \
- sp += 48; \
- int_buffer = read_register (RP_REGNUM) | 0x3; \
- write_memory (sp - 20, (char *)&int_buffer, 4); \
- int_buffer = read_register (FP_REGNUM); \
- write_memory (sp, (char *)&int_buffer, 4); \
- write_register (FP_REGNUM, sp); \
- sp += 4; \
- for (regnum = 1; regnum < 31; regnum++) \
- if (regnum != RP_REGNUM && regnum != FP_REGNUM) \
- sp = push_word (sp, read_register (regnum)); \
- for (regnum = FP0_REGNUM; regnum < NUM_REGS; regnum++) \
- { read_register_bytes (REGISTER_BYTE (regnum), freg_buffer, 8); \
- sp = push_bytes (sp, freg_buffer, 8);} \
- sp = push_word (sp, read_register (IPSW_REGNUM)); \
- sp = push_word (sp, read_register (SAR_REGNUM)); \
- sp = push_word (sp, read_register (PCOQ_TAIL_REGNUM)); \
- sp = push_word (sp, read_register (PCSQ_TAIL_REGNUM)); \
- write_register (SP_REGNUM, sp);}
+#define PUSH_DUMMY_FRAME push_dummy_frame ()
/* Discard from the stack the innermost frame,
restoring all saved registers. */
-#define POP_FRAME \
-{ register FRAME frame = get_current_frame (); \
- register CORE_ADDR fp; \
- register int regnum; \
- struct frame_saved_regs fsr; \
- struct frame_info *fi; \
- char freg_buffer[8]; \
- fi = get_frame_info (frame); \
- fp = fi->frame; \
- get_frame_saved_regs (fi, &fsr); \
- for (regnum = 31; regnum > 0; regnum--) \
- if (fsr.regs[regnum]) \
- write_register (regnum, read_memory_integer (fsr.regs[regnum], 4)); \
- for (regnum = NUM_REGS - 1; regnum >= FP0_REGNUM ; regnum--) \
- if (fsr.regs[regnum]) \
- { read_memory (fsr.regs[regnum], freg_buffer, 8); \
- write_register_bytes (REGISTER_BYTE (regnum), freg_buffer, 8); }\
- if (fsr.regs[IPSW_REGNUM]) \
- write_register (IPSW_REGNUM, \
- read_memory_integer (fsr.regs[IPSW_REGNUM], 4)); \
- if (fsr.regs[SAR_REGNUM]) \
- write_register (SAR_REGNUM, \
- read_memory_integer (fsr.regs[SAR_REGNUM], 4)); \
- if (fsr.regs[PCOQ_TAIL_REGNUM]) \
- write_register (PCOQ_TAIL_REGNUM, \
- read_memory_integer (fsr.regs[PCOQ_TAIL_REGNUM], 4));\
- if (fsr.regs[PCSQ_TAIL_REGNUM]) \
- write_register (PCSQ_TAIL_REGNUM, \
- read_memory_integer (fsr.regs[PCSQ_TAIL_REGNUM], 4));\
- write_register (FP_REGNUM, read_memory_integer (fp, 4)); \
- write_register (SP_REGNUM, fp + 8); \
- flush_cached_frames (); \
- set_current_frame (create_new_frame (read_register (FP_REGNUM),\
- read_pc ())); }
+#define POP_FRAME hp_pop_frame ()
/* This sequence of words is the instructions
ldsid (0,r22), r3
ldil 0, r1 ; _sr4export will be placed here.
ldo 0(r1), r1
- ldsid (0,r1), r4
- combt,=,n r3, r4, text_space ; If target is in data space, do a
+ ldsid (0,r1), r19
+ combt,=,n r3, r19, text_space ; If target is in data space, do a
ble 0(sr5, r22) ; "normal" procedure call
copy r31, r2
break 4, 8
+ mtsp r21, sr0
+ ble,n 0(sr0, r22)
text_space ; Otherwise, go through _sr4export,
ble (sr4, r1) ; which will return back here.
stw 31,-24(r30)
break 4, 8
+ mtsp r21, sr0
+ ble,n 0(sr0, r22)
The dummy decides if the target is in text space or data space. If
it's in data space, there's no problem because the target can
know that the frame is associated with the call dummy and treat it
specially. */
-#define CALL_DUMMY { 0x4bda3fb9, 0x4bd93fb1, 0x4bd83fa9, 0x4bd73fa1, \
- 0x37c13fb9, 0x24201004, 0x2c391005, 0x24311006, \
- 0x2c291007, 0x22c00000, 0x36d60000, 0x02c010a3, \
- 0x20200000, 0x34210000, 0x002010a4, 0x80832012, \
- 0xe6c06000, 0x081f0242, 0x00010004, 0xe4202000, \
- 0x6bdf3fd1, 0x00010004}
+#define CALL_DUMMY {0x4BDA3FB9, 0x4BD93FB1, 0x4BD83FA9, 0x4BD73FA1,\
+ 0x37C13FB9, 0x24201004, 0x2C391005, 0x24311006,\
+ 0x2C291007, 0x22C00000, 0x36D60000, 0x02C010A3,\
+ 0x20200000, 0x34210000, 0x002010b3, 0x82632022,\
+ 0xe6c06000, 0x081f0242, 0x00010004, 0x00151820,\
+ 0xe6c00002, 0xe4202000, 0x6bdf3fd1, 0x00010004,\
+ 0x00151820, 0xe6c00002}
-#define CALL_DUMMY_LENGTH 88
+#define CALL_DUMMY_LENGTH 104
#define CALL_DUMMY_START_OFFSET 0
-/* Insert the specified number of args and function address
- into a call sequence of the above form stored at DUMMYNAME. */
-#define FIX_CALL_DUMMY(dummyname, pc, fun, nargs, args, type, gcc_p) \
-{ static CORE_ADDR sr4export_address = 0; \
- \
- if (!sr4export_address) \
- { \
+
+/*
+ * Insert the specified number of args and function address
+ * into a call sequence of the above form stored at DUMMYNAME.
+ *
+ * On the hppa we need to call the stack dummy through $$dyncall.
+ * Therefore our version of FIX_CALL_DUMMY takes an extra argument,
+ * real_pc, which is the location where gdb should start up the
+ * inferior to do the function call.
+ */
+
+#define FIX_CALL_DUMMY(dummyname, pc, real_pc, fun, nargs, args, type, gcc_p) \
+{ \
+ CORE_ADDR dyncall_addr = 0, sr4export_addr = 0; \
+ \
+ if (!dyncall_addr) \
+ { \
struct minimal_symbol *msymbol; \
+ msymbol = lookup_minimal_symbol ("$$dyncall", (struct objfile *) NULL);\
+ if (msymbol == NULL) \
+ error ("Can't find an address for $$dyncall trampoline"); \
+ else \
+ dyncall_addr = msymbol -> address; \
msymbol = lookup_minimal_symbol ("_sr4export", (struct objfile *) NULL);\
- if (msymbol = NULL) \
- error ("Can't find an address for _sr4export trampoline"); \
- else \
- sr4export_address = msymbol -> address; \
- } \
- dummyname[9] = deposit_21 (fun >> 11, dummyname[9]); \
- dummyname[10] = deposit_14 (fun & MASK_11, dummyname[10]); \
- dummyname[12] = deposit_21 (sr4export_address >> 11, dummyname[12]); \
- dummyname[13] = deposit_14 (sr4export_address & MASK_11, dummyname[13]);\
+ if (msymbol == NULL) \
+ error ("Can't find an address for _sr4export trampoline"); \
+ else \
+ sr4export_addr = msymbol -> address; \
+ } \
+ dummyname[9] = deposit_21 (fun >> 11, dummyname[9]); \
+ dummyname[10] = deposit_14 (fun & MASK_11, dummyname[10]); \
+ dummyname[12] = deposit_21 (sr4export_addr >> 11, \
+ dummyname[12]); \
+ dummyname[13] = deposit_14 (sr4export_addr & MASK_11, \
+ dummyname[13]); \
+ write_register (22, pc); \
+ real_pc = dyncall_addr; \
}
-
#define PUSH_ARGUMENTS(nargs, args, sp, struct_return, struct_addr) \
sp = hp_push_arguments(nargs, args, sp, struct_return, struct_addr)
-/* Write the PC to a random value.
- On PA-RISC, we need to be sure that the PC space queue is correct. */
-
-#define WRITE_PC(addr) \
-{ int space_reg, space = ((addr) >> 30); \
- int space_val; \
- if (space == 0) \
- space_reg = 43; /* Space reg sr4 */ \
- else if (space == 1) \
- space_reg = 48; /* Space reg sr5*/ \
- else \
- error ("pc = %x is in illegal space.", addr); \
- space_val = read_register (space_reg); \
- write_register (PCOQ_HEAD_REGNUM, addr); \
- write_register (PCSQ_HEAD_REGNUM, space_val); \
- write_register (PCOQ_TAIL_REGNUM, addr); \
- write_register (PCSQ_TAIL_REGNUM, space_val);}
-
/* Symbol files have two symbol tables. Rather than do this right,
like the ELF symbol reading code, massive hackery was added
to dbxread.c and partial-stab.h. This flag turns on that
hackery, which should all go away FIXME FIXME FIXME FIXME now. */
#define GDB_TARGET_IS_HPPA
+
+/*
+ * Unwind table and descriptor.
+ */
+
+struct unwind_table_entry {
+ unsigned int region_start;
+ unsigned int region_end;
+
+ unsigned int Cannot_unwind : 1;
+ unsigned int Millicode : 1;
+ unsigned int Millicode_save_sr0 : 1;
+ unsigned int Region_description : 2;
+ unsigned int reserverd1 : 1;
+ unsigned int Entry_SR : 1;
+ unsigned int Entry_FR : 4; /* number saved */
+ unsigned int Entry_GR : 5; /* number saved */
+ unsigned int Args_stored : 1;
+ unsigned int Variable_Frame : 1;
+ unsigned int Separate_Package_Body : 1;
+ unsigned int Frame_Extension_Millicode:1;
+ unsigned int Stack_Overflow_Check : 1;
+ unsigned int Two_Instruction_SP_Increment:1;
+ unsigned int Ada_Region : 1;
+ unsigned int reserved2 : 4;
+ unsigned int Save_SP : 1;
+ unsigned int Save_RP : 1;
+ unsigned int Save_MRP_in_frame : 1;
+ unsigned int extn_ptr_defined : 1;
+ unsigned int Cleanup_defined : 1;
+
+ unsigned int MPE_XL_interrupt_marker: 1;
+ unsigned int HP_UX_interrupt_marker: 1;
+ unsigned int Large_frame : 1;
+ unsigned int reserved4 : 2;
+ unsigned int Total_frame_size : 27;
+};