/* Target-dependent code for the SPARC for GDB, the GNU debugger.
- Copyright 1986, 1987, 1989, 1991, 1992, 1993, 1994, 1995
+ Copyright 1986, 1987, 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997
Free Software Foundation, Inc.
This file is part of GDB.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
-Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* ??? Support for calling functions from gdb in sparc64 is unfinished. */
#include "obstack.h"
#include "target.h"
#include "value.h"
+#include "bfd.h"
+#include "gdb_string.h"
#ifdef USE_PROC_FS
#include <sys/procfs.h>
#include "gdbcore.h"
#ifdef GDB_TARGET_IS_SPARC64
-#define NUM_SPARC_FPREGS 64
+#define FP_REGISTER_BYTES (64 * 4)
#else
-#define NUM_SPARC_FPREGS 32
+#define FP_REGISTER_BYTES (32 * 4)
+#endif
+
+/* If not defined, assume 32 bit sparc. */
+#ifndef FP_MAX_REGNUM
+#define FP_MAX_REGNUM (FP0_REGNUM + 32)
#endif
#define SPARC_INTREG_SIZE (REGISTER_RAW_SIZE (G0_REGNUM))
/* Sign extension macros. */
#define X_SIMM13(i) ((X_IMM13 (i) ^ 0x1000) - 0x1000)
#define X_DISP22(i) ((X_IMM22 (i) ^ 0x200000) - 0x200000)
-#ifdef GDB_TARGET_IS_SPARC64
#define X_CC(i) (((i) >> 20) & 3)
#define X_P(i) (((i) >> 19) & 1)
#define X_DISP19(i) ((((i) & 0x7ffff) ^ 0x40000) - 0x40000)
#define X_RCOND(i) (((i) >> 25) & 7)
#define X_DISP16(i) ((((((i) >> 6) && 0xc000) | ((i) & 0x3fff)) ^ 0x8000) - 0x8000)
#define X_FCN(i) (((i) >> 25) & 31)
-#endif
typedef enum
{
int one_stepped;
+static branch_type isbranch PARAMS ((long, CORE_ADDR, CORE_ADDR *));
+
/* single_step() is called just before we want to resume the inferior,
if we want to single-step it but there is no hardware or kernel single-step
support (as on all SPARCs). We find all the possible targets of the
void
single_step (ignore)
- int ignore; /* pid, but we don't need it */
+ enum target_signal ignore; /* pid, but we don't need it */
{
- branch_type br, isbranch();
+ branch_type br;
CORE_ADDR pc;
long pc_instruction;
if (fi->next)
{
char buf[MAX_REGISTER_RAW_SIZE];
- int err;
/* Compute ->frame as if not flat. If it is flat, we'll change
it later. */
- /* FIXME: If error reading memory, should just stop backtracing, rather
- than error(). */
- get_saved_register (buf, 0, 0, fi, FP_REGNUM, 0);
- fi->frame = extract_address (buf, REGISTER_RAW_SIZE (FP_REGNUM));
+ if (fi->next->next != NULL
+ && (fi->next->next->signal_handler_caller
+ || frame_in_dummy (fi->next->next))
+ && frameless_look_for_prologue (fi->next))
+ {
+ /* A frameless function interrupted by a signal did not change
+ the frame pointer, fix up frame pointer accordingly. */
+ fi->frame = FRAME_FP (fi->next);
+ fi->bottom = fi->next->bottom;
+ }
+ else
+ {
+ get_saved_register (buf, 0, 0, fi, FP_REGNUM, 0);
+ fi->frame = extract_address (buf, REGISTER_RAW_SIZE (FP_REGNUM));
+ }
}
/* Decide whether this is a function with a ``flat register window''
return extract_address (regbuf + REGISTER_BYTE (O0_REGNUM),
REGISTER_RAW_SIZE (O0_REGNUM));
#else
- return read_memory_integer (((int *)(regbuf)) [SP_REGNUM] + (16 * SPARC_INTREG_SIZE),
+ CORE_ADDR sp = extract_address (®buf [REGISTER_BYTE (SP_REGNUM)],
+ REGISTER_RAW_SIZE (SP_REGNUM));
+ return read_memory_integer (sp + (16 * SPARC_INTREG_SIZE),
TARGET_PTR_BIT / TARGET_CHAR_BIT);
#endif
}
scbuf, sizeof (scbuf));
return extract_address (scbuf, sizeof (scbuf));
}
+ else if (frame->next != NULL
+ && (frame->next->signal_handler_caller
+ || frame_in_dummy (frame->next))
+ && frameless_look_for_prologue (frame))
+ {
+ /* A frameless function interrupted by a signal did not save
+ the PC, it is still in %o7. */
+ get_saved_register (buf, (int *)NULL, (CORE_ADDR *)NULL,
+ frame, O7_REGNUM, (enum lval_type *)NULL);
+ return PC_ADJUST (extract_address (buf, SPARC_INTREG_SIZE));
+ }
if (frame->flat)
addr = frame->pc_addr;
else
This isn't static as it's used by remote-sa.sparc.c. */
-branch_type
+static branch_type
isbranch (instruction, addr, target)
long instruction;
CORE_ADDR addr, *target;
{
branch_type val = not_branch;
- long int offset; /* Must be signed for sign-extend. */
+ long int offset = 0; /* Must be signed for sign-extend. */
*target = 0;
if (X_OP (instruction) == 0
&& (X_OP2 (instruction) == 2
|| X_OP2 (instruction) == 6
-#ifdef GDB_TARGET_IS_SPARC64
|| X_OP2 (instruction) == 1
|| X_OP2 (instruction) == 3
|| X_OP2 (instruction) == 5
-#else
+#ifndef GDB_TARGET_IS_SPARC64
|| X_OP2 (instruction) == 7
#endif
))
val = X_A (instruction) ? baa : ba;
else
val = X_A (instruction) ? bicca : bicc;
- switch (X_OP (instruction))
+ switch (X_OP2 (instruction))
{
case 2:
case 6:
#endif
offset = 4 * X_DISP22 (instruction);
break;
-#ifdef GDB_TARGET_IS_SPARC64
case 1:
case 5:
offset = 4 * X_DISP19 (instruction);
case 3:
offset = 4 * X_DISP16 (instruction);
break;
-#endif
}
*target = addr + offset;
}
*optimized = 0;
addr = 0;
+
+ /* FIXME This code extracted from infcmd.c; should put elsewhere! */
+ if (frame == NULL)
+ {
+ /* error ("No selected frame."); */
+ if (!target_has_registers)
+ error ("The program has no registers now.");
+ if (selected_frame == NULL)
+ error ("No selected frame.");
+ /* Try to use selected frame */
+ frame = get_prev_frame (selected_frame);
+ if (frame == 0)
+ error ("Cmd not meaningful in the outermost frame.");
+ }
+
+
frame1 = frame->next;
+
+ /* Get saved PC from the frame info if not in innermost frame. */
+ if (regnum == PC_REGNUM && frame1 != NULL)
+ {
+ if (lval != NULL)
+ *lval = not_lval;
+ if (raw_buffer != NULL)
+ {
+ /* Put it back in target format. */
+ store_address (raw_buffer, REGISTER_RAW_SIZE (regnum), frame->pc);
+ }
+ if (addrp != NULL)
+ *addrp = 0;
+ return;
+ }
+
while (frame1 != NULL)
{
if (frame1->pc >= (frame1->bottom ? frame1->bottom :
read_register (SP_REGNUM))
&& frame1->pc <= FRAME_FP (frame1))
{
- /* Dummy frame. All but the window regs are in there somewhere. */
- /* FIXME: The offsets are wrong for sparc64 (eg: 0xa0). */
+ /* Dummy frame. All but the window regs are in there somewhere.
+ The window registers are saved on the stack, just like in a
+ normal frame. */
if (regnum >= G1_REGNUM && regnum < G1_REGNUM + 7)
addr = frame1->frame + (regnum - G0_REGNUM) * SPARC_INTREG_SIZE
- - (NUM_SPARC_FPREGS * 4 + 8 * SPARC_INTREG_SIZE);
+ - (FP_REGISTER_BYTES + 8 * SPARC_INTREG_SIZE);
else if (regnum >= I0_REGNUM && regnum < I0_REGNUM + 8)
- addr = frame1->frame + (regnum - I0_REGNUM) * SPARC_INTREG_SIZE
- - (NUM_SPARC_FPREGS * 4 + 16 * SPARC_INTREG_SIZE);
- else if (regnum >= FP0_REGNUM && regnum < FP0_REGNUM + NUM_SPARC_FPREGS)
+ addr = (frame1->prev->bottom
+ + (regnum - I0_REGNUM) * SPARC_INTREG_SIZE
+ + FRAME_SAVED_I0);
+ else if (regnum >= L0_REGNUM && regnum < L0_REGNUM + 8)
+ addr = (frame1->prev->bottom
+ + (regnum - L0_REGNUM) * SPARC_INTREG_SIZE
+ + FRAME_SAVED_L0);
+ else if (regnum >= O0_REGNUM && regnum < O0_REGNUM + 8)
+ addr = frame1->frame + (regnum - O0_REGNUM) * SPARC_INTREG_SIZE
+ - (FP_REGISTER_BYTES + 16 * SPARC_INTREG_SIZE);
+#ifdef FP0_REGNUM
+ else if (regnum >= FP0_REGNUM && regnum < FP0_REGNUM + 32)
addr = frame1->frame + (regnum - FP0_REGNUM) * 4
- - (NUM_SPARC_FPREGS * 4);
+ - (FP_REGISTER_BYTES);
+#ifdef GDB_TARGET_IS_SPARC64
+ else if (regnum >= FP0_REGNUM + 32 && regnum < FP_MAX_REGNUM)
+ addr = frame1->frame + 32 * 4 + (regnum - FP0_REGNUM - 32) * 8
+ - (FP_REGISTER_BYTES);
+#endif
+#endif /* FP0_REGNUM */
else if (regnum >= Y_REGNUM && regnum < NUM_REGS)
addr = frame1->frame + (regnum - Y_REGNUM) * SPARC_INTREG_SIZE
- - (NUM_SPARC_FPREGS * 4 + 24 * SPARC_INTREG_SIZE);
+ - (FP_REGISTER_BYTES + 24 * SPARC_INTREG_SIZE);
}
else if (frame1->flat)
{
#endif
/* See tm-sparc.h for how this is calculated. */
+#ifdef FP0_REGNUM
#define DUMMY_STACK_REG_BUF_SIZE \
(((8+8+8) * SPARC_INTREG_SIZE) + (32 * REGISTER_RAW_SIZE (FP0_REGNUM)))
+#else
+#define DUMMY_STACK_REG_BUF_SIZE \
+(((8+8+8) * SPARC_INTREG_SIZE) )
+#endif /* FP0_REGNUM */
#define DUMMY_STACK_SIZE (DUMMY_STACK_REG_BUF_SIZE + DUMMY_REG_SAVE_OFFSET)
void
®ister_temp[16 * SPARC_INTREG_SIZE],
SPARC_INTREG_SIZE * 8);
- /* ??? The 32 here should be NUM_SPARC_FPREGS, but until we decide what
- REGISTER_RAW_SIZE should be for fp regs, it's left as is. */
+#ifdef FP0_REGNUM
read_register_bytes (REGISTER_BYTE (FP0_REGNUM),
®ister_temp[24 * SPARC_INTREG_SIZE],
- REGISTER_RAW_SIZE (FP0_REGNUM) * 32);
+ FP_REGISTER_BYTES);
+#endif /* FP0_REGNUM */
sp -= DUMMY_STACK_SIZE;
for (regnum = G1_REGNUM; regnum < G1_REGNUM+7; regnum++)
saved_regs_addr->regs[regnum] =
frame_addr + (regnum - G0_REGNUM) * SPARC_INTREG_SIZE
- - (NUM_SPARC_FPREGS * 4 + 8 * SPARC_INTREG_SIZE);
+ - DUMMY_STACK_REG_BUF_SIZE + 16 * SPARC_INTREG_SIZE;
for (regnum = I0_REGNUM; regnum < I0_REGNUM+8; regnum++)
saved_regs_addr->regs[regnum] =
frame_addr + (regnum - I0_REGNUM) * SPARC_INTREG_SIZE
- - (NUM_SPARC_FPREGS * 4 + 16 * SPARC_INTREG_SIZE);
+ - DUMMY_STACK_REG_BUF_SIZE + 8 * SPARC_INTREG_SIZE;
+#ifdef FP0_REGNUM
for (regnum = FP0_REGNUM; regnum < FP0_REGNUM + 32; regnum++)
saved_regs_addr->regs[regnum] =
frame_addr + (regnum - FP0_REGNUM) * 4
- - (NUM_SPARC_FPREGS * 4);
+ - DUMMY_STACK_REG_BUF_SIZE + 24 * SPARC_INTREG_SIZE;
+#ifdef GDB_TARGET_IS_SPARC64
+ for (regnum = FP0_REGNUM + 32; regnum < FP_MAX_REGNUM; regnum++)
+ saved_regs_addr->regs[regnum] =
+ frame_addr + 32 * 4 + (regnum - FP0_REGNUM - 32) * 8
+ - DUMMY_STACK_REG_BUF_SIZE + 24 * SPARC_INTREG_SIZE;
+#endif
+#endif /* FP0_REGNUM */
for (regnum = Y_REGNUM; regnum < NUM_REGS; regnum++)
saved_regs_addr->regs[regnum] =
- frame_addr + (regnum - Y_REGNUM) * SPARC_INTREG_SIZE - 0xe0;
- - (NUM_SPARC_FPREGS * 4 + 24 * SPARC_INTREG_SIZE);
+ frame_addr + (regnum - Y_REGNUM) * SPARC_INTREG_SIZE
+ - DUMMY_STACK_REG_BUF_SIZE;
frame_addr = fi->bottom ?
fi->bottom : read_register (SP_REGNUM);
}
int regnum;
sparc_frame_find_saved_regs (frame, &fsr);
+#ifdef FP0_REGNUM
if (fsr.regs[FP0_REGNUM])
{
- read_memory (fsr.regs[FP0_REGNUM], raw_buffer, NUM_SPARC_FPREGS * 4);
+ read_memory (fsr.regs[FP0_REGNUM], raw_buffer, FP_REGISTER_BYTES);
write_register_bytes (REGISTER_BYTE (FP0_REGNUM),
- raw_buffer, NUM_SPARC_FPREGS * 4);
+ raw_buffer, FP_REGISTER_BYTES);
}
#ifndef GDB_TARGET_IS_SPARC64
if (fsr.regs[FPS_REGNUM])
write_register_bytes (REGISTER_BYTE (CPS_REGNUM), raw_buffer, 4);
}
#endif
+#endif /* FP0_REGNUM */
if (fsr.regs[G1_REGNUM])
{
read_memory (fsr.regs[G1_REGNUM], raw_buffer, 7 * SPARC_INTREG_SIZE);
char buf[4];
int err;
- err = target_read_memory (pc + 8, buf, sizeof(long));
+ err = target_read_memory (pc + 8, buf, 4);
insn = extract_unsigned_integer (buf, 4);
- if ((err == 0) && (insn & 0xfffffe00) == 0)
+ if ((err == 0) && (insn & 0xffc00000) == 0)
return pc+12;
else
return pc+8;
{
register int regi;
register prgreg_t *regp = (prgreg_t *) gregsetp;
+ static char zerobuf[MAX_REGISTER_RAW_SIZE] = {0};
/* GDB register numbers for Gn, On, Ln, In all match /proc reg numbers. */
for (regi = G0_REGNUM ; regi <= I7_REGNUM ; regi++)
supply_register (PC_REGNUM, (char *) (regp + R_PC));
supply_register (NPC_REGNUM,(char *) (regp + R_nPC));
supply_register (Y_REGNUM, (char *) (regp + R_Y));
+
+ /* Fill inaccessible registers with zero. */
+ supply_register (WIM_REGNUM, zerobuf);
+ supply_register (TBR_REGNUM, zerobuf);
+ supply_register (CPS_REGNUM, zerobuf);
}
void
register int regi;
char *from;
- for (regi = FP0_REGNUM ; regi < FP0_REGNUM+32 ; regi++)
+ for (regi = FP0_REGNUM ; regi < FP_MAX_REGNUM ; regi++)
{
from = (char *) &fpregsetp->pr_fr.pr_regs[regi-FP0_REGNUM];
supply_register (regi, from);
char *to;
char *from;
- /* ??? The 32 should probably be NUM_SPARC_FPREGS, but again we're
- waiting on what REGISTER_RAW_SIZE should be for fp regs. */
- for (regi = FP0_REGNUM ; regi < FP0_REGNUM + 32 ; regi++)
+ for (regi = FP0_REGNUM ; regi < FP_MAX_REGNUM ; regi++)
{
if ((regno == -1) || (regno == regi))
{
sparc_print_register_hook (regno)
int regno;
{
- unsigned LONGEST val;
+ ULONGEST val;
- if (((unsigned) (regno) - FP0_REGNUM < FP_MAX_REGNUM - FP0_REGNUM)
- && ((regno) & 1) == 0)
+ /* Handle double/quad versions of lower 32 fp regs. */
+ if (regno >= FP0_REGNUM && regno < FP0_REGNUM + 32
+ && (regno & 1) == 0)
{
- char doublereg[8]; /* two float regs */
- if (!read_relative_register_raw_bytes ((regno), doublereg))
+ char value[16];
+
+ if (!read_relative_register_raw_bytes (regno, value)
+ && !read_relative_register_raw_bytes (regno + 1, value + 4))
+ {
+ printf_unfiltered ("\t");
+ print_floating (value, builtin_type_double, gdb_stdout);
+ }
+#if 0 /* FIXME: gdb doesn't handle long doubles */
+ if ((regno & 3) == 0)
{
- printf_unfiltered("\t");
- print_floating (doublereg, builtin_type_double, gdb_stdout);
+ if (!read_relative_register_raw_bytes (regno + 2, value + 8)
+ && !read_relative_register_raw_bytes (regno + 3, value + 12))
+ {
+ printf_unfiltered ("\t");
+ print_floating (value, builtin_type_long_double, gdb_stdout);
+ }
+ }
+#endif
+ return;
+ }
+
+#if 0 /* FIXME: gdb doesn't handle long doubles */
+ /* Print upper fp regs as long double if appropriate. */
+ if (regno >= FP0_REGNUM + 32 && regno < FP_MAX_REGNUM
+ /* We test for even numbered regs and not a multiple of 4 because
+ the upper fp regs are recorded as doubles. */
+ && (regno & 1) == 0)
+ {
+ char value[16];
+
+ if (!read_relative_register_raw_bytes (regno, value)
+ && !read_relative_register_raw_bytes (regno + 1, value + 8))
+ {
+ printf_unfiltered ("\t");
+ print_floating (value, builtin_type_long_double, gdb_stdout);
}
return;
}
+#endif
/* FIXME: Some of these are priviledged registers.
Not sure how they should be handled. */
#endif
\f
+int
+gdb_print_insn_sparc (memaddr, info)
+ bfd_vma memaddr;
+ disassemble_info *info;
+{
+ /* It's necessary to override mach again because print_insn messes it up. */
+ info->mach = TM_PRINT_INSN_MACH;
+ return print_insn_sparc (memaddr, info);
+}
+\f
+/* The SPARC passes the arguments on the stack; arguments smaller
+ than an int are promoted to an int. */
+
+CORE_ADDR
+sparc_push_arguments (nargs, args, sp, struct_return, struct_addr)
+ int nargs;
+ value_ptr *args;
+ CORE_ADDR sp;
+ int struct_return;
+ CORE_ADDR struct_addr;
+{
+ int i;
+ int accumulate_size = 0;
+ struct sparc_arg
+ {
+ char *contents;
+ int len;
+ int offset;
+ };
+ struct sparc_arg *sparc_args =
+ (struct sparc_arg*)alloca (nargs * sizeof (struct sparc_arg));
+ struct sparc_arg *m_arg;
+
+ /* Promote arguments if necessary, and calculate their stack offsets
+ and sizes. */
+ for (i = 0, m_arg = sparc_args; i < nargs; i++, m_arg++)
+ {
+ value_ptr arg = args[i];
+ struct type *arg_type = check_typedef (VALUE_TYPE (arg));
+ /* Cast argument to long if necessary as the compiler does it too. */
+ switch (TYPE_CODE (arg_type))
+ {
+ case TYPE_CODE_INT:
+ case TYPE_CODE_BOOL:
+ case TYPE_CODE_CHAR:
+ case TYPE_CODE_RANGE:
+ case TYPE_CODE_ENUM:
+ if (TYPE_LENGTH (arg_type) < TYPE_LENGTH (builtin_type_long))
+ {
+ arg_type = builtin_type_long;
+ arg = value_cast (arg_type, arg);
+ }
+ break;
+ default:
+ break;
+ }
+ m_arg->len = TYPE_LENGTH (arg_type);
+ m_arg->offset = accumulate_size;
+ accumulate_size = (accumulate_size + m_arg->len + 3) & ~3;
+ m_arg->contents = VALUE_CONTENTS(arg);
+ }
+
+ /* Make room for the arguments on the stack. */
+ accumulate_size += CALL_DUMMY_STACK_ADJUST;
+ sp = ((sp - accumulate_size) & ~7) + CALL_DUMMY_STACK_ADJUST;
+
+ /* `Push' arguments on the stack. */
+ for (i = nargs; m_arg--, --i >= 0; )
+ write_memory(sp + m_arg->offset, m_arg->contents, m_arg->len);
+
+ return sp;
+}
+\f
void
_initialize_sparc_tdep ()
{
- tm_print_insn = print_insn_sparc;
+ tm_print_insn = gdb_print_insn_sparc;
+ tm_print_insn_info.mach = TM_PRINT_INSN_MACH; /* Selects sparc/sparclite */
}