| Index: gdb/sparc-tdep.c
|
| diff --git a/gdb/sparc-tdep.c b/gdb/sparc-tdep.c
|
| index 6da2297a3cb9547ab8c48f8e4e8947fd2cc13ad9..950ca8cd55cc2519559551bae1f0260f7958c55d 100644
|
| --- a/gdb/sparc-tdep.c
|
| +++ b/gdb/sparc-tdep.c
|
| @@ -1,6 +1,6 @@
|
| /* Target-dependent code for SPARC.
|
|
|
| - Copyright (C) 2003-2012 Free Software Foundation, Inc.
|
| + Copyright (C) 2003-2013 Free Software Foundation, Inc.
|
|
|
| This file is part of GDB.
|
|
|
| @@ -36,9 +36,10 @@
|
| #include "value.h"
|
|
|
| #include "gdb_assert.h"
|
| -#include "gdb_string.h"
|
| +#include <string.h>
|
|
|
| #include "sparc-tdep.h"
|
| +#include "sparc-ravenscar-thread.h"
|
|
|
| struct regset;
|
|
|
| @@ -120,6 +121,37 @@ sparc_is_unimp_insn (CORE_ADDR pc)
|
| return ((insn & 0xc1c00000) == 0);
|
| }
|
|
|
| +/* Return non-zero if the instruction corresponding to PC is an
|
| + "annulled" branch, i.e. the annul bit is set. */
|
| +
|
| +int
|
| +sparc_is_annulled_branch_insn (CORE_ADDR pc)
|
| +{
|
| + /* The branch instructions featuring an annul bit can be identified
|
| + by the following bit patterns:
|
| +
|
| + OP=0
|
| + OP2=1: Branch on Integer Condition Codes with Prediction (BPcc).
|
| + OP2=2: Branch on Integer Condition Codes (Bcc).
|
| + OP2=5: Branch on FP Condition Codes with Prediction (FBfcc).
|
| + OP2=6: Branch on FP Condition Codes (FBcc).
|
| + OP2=3 && Bit28=0:
|
| + Branch on Integer Register with Prediction (BPr).
|
| +
|
| + This leaves out ILLTRAP (OP2=0), SETHI/NOP (OP2=4) and the V8
|
| + coprocessor branch instructions (Op2=7). */
|
| +
|
| + const unsigned long insn = sparc_fetch_instruction (pc);
|
| + const unsigned op2 = X_OP2 (insn);
|
| +
|
| + if ((X_OP (insn) == 0)
|
| + && ((op2 == 1) || (op2 == 2) || (op2 == 5) || (op2 == 6)
|
| + || ((op2 == 3) && ((insn & 0x10000000) == 0))))
|
| + return X_A (insn);
|
| + else
|
| + return 0;
|
| +}
|
| +
|
| /* OpenBSD/sparc includes StackGhost, which according to the author's
|
| website http://stackghost.cerias.purdue.edu "... transparently and
|
| automatically protects applications' stack frames; more
|
| @@ -854,7 +886,7 @@ sparc_analyze_prologue (struct gdbarch *gdbarch, CORE_ADDR pc,
|
| dynamic linker patches up the first PLT with some code that
|
| starts with a SAVE instruction. Patch up PC such that it points
|
| at the start of our PLT entry. */
|
| - if (tdep->plt_entry_size > 0 && in_plt_section (current_pc, NULL))
|
| + if (tdep->plt_entry_size > 0 && in_plt_section (current_pc))
|
| pc = current_pc - ((current_pc - pc) % tdep->plt_entry_size);
|
|
|
| insn = sparc_fetch_instruction (pc);
|
| @@ -1369,15 +1401,21 @@ sparc32_return_value (struct gdbarch *gdbarch, struct value *function,
|
| if (sparc_structure_or_union_p (type)
|
| || (sparc_floating_p (type) && TYPE_LENGTH (type) == 16))
|
| {
|
| + ULONGEST sp;
|
| + CORE_ADDR addr;
|
| +
|
| if (readbuf)
|
| {
|
| - ULONGEST sp;
|
| - CORE_ADDR addr;
|
| -
|
| regcache_cooked_read_unsigned (regcache, SPARC_SP_REGNUM, &sp);
|
| addr = read_memory_unsigned_integer (sp + 64, 4, byte_order);
|
| read_memory (addr, readbuf, TYPE_LENGTH (type));
|
| }
|
| + if (writebuf)
|
| + {
|
| + regcache_cooked_read_unsigned (regcache, SPARC_SP_REGNUM, &sp);
|
| + addr = read_memory_unsigned_integer (sp + 64, 4, byte_order);
|
| + write_memory (addr, writebuf, TYPE_LENGTH (type));
|
| + }
|
|
|
| return RETURN_VALUE_ABI_PRESERVES_ADDRESS;
|
| }
|
| @@ -1531,7 +1569,6 @@ sparc_analyze_control_transfer (struct frame_info *frame,
|
| if (X_A (insn))
|
| *npc = 0;
|
|
|
| - gdb_assert (offset != 0);
|
| return pc + offset;
|
| }
|
| }
|
| @@ -1683,6 +1720,8 @@ sparc32_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
|
| set_gdbarch_regset_from_core_section (gdbarch,
|
| sparc_regset_from_core_section);
|
|
|
| + register_sparc_ravenscar_ops (gdbarch);
|
| +
|
| return gdbarch;
|
| }
|
|
|
| @@ -1953,7 +1992,8 @@ sparc32_collect_gregset (const struct sparc_gregset *gregset,
|
| }
|
|
|
| void
|
| -sparc32_supply_fpregset (struct regcache *regcache,
|
| +sparc32_supply_fpregset (const struct sparc_fpregset *fpregset,
|
| + struct regcache *regcache,
|
| int regnum, const void *fpregs)
|
| {
|
| const gdb_byte *regs = fpregs;
|
| @@ -1962,15 +2002,18 @@ sparc32_supply_fpregset (struct regcache *regcache,
|
| for (i = 0; i < 32; i++)
|
| {
|
| if (regnum == (SPARC_F0_REGNUM + i) || regnum == -1)
|
| - regcache_raw_supply (regcache, SPARC_F0_REGNUM + i, regs + (i * 4));
|
| + regcache_raw_supply (regcache, SPARC_F0_REGNUM + i,
|
| + regs + fpregset->r_f0_offset + (i * 4));
|
| }
|
|
|
| if (regnum == SPARC32_FSR_REGNUM || regnum == -1)
|
| - regcache_raw_supply (regcache, SPARC32_FSR_REGNUM, regs + (32 * 4) + 4);
|
| + regcache_raw_supply (regcache, SPARC32_FSR_REGNUM,
|
| + regs + fpregset->r_fsr_offset);
|
| }
|
|
|
| void
|
| -sparc32_collect_fpregset (const struct regcache *regcache,
|
| +sparc32_collect_fpregset (const struct sparc_fpregset *fpregset,
|
| + const struct regcache *regcache,
|
| int regnum, void *fpregs)
|
| {
|
| gdb_byte *regs = fpregs;
|
| @@ -1979,11 +2022,13 @@ sparc32_collect_fpregset (const struct regcache *regcache,
|
| for (i = 0; i < 32; i++)
|
| {
|
| if (regnum == (SPARC_F0_REGNUM + i) || regnum == -1)
|
| - regcache_raw_collect (regcache, SPARC_F0_REGNUM + i, regs + (i * 4));
|
| + regcache_raw_collect (regcache, SPARC_F0_REGNUM + i,
|
| + regs + fpregset->r_f0_offset + (i * 4));
|
| }
|
|
|
| if (regnum == SPARC32_FSR_REGNUM || regnum == -1)
|
| - regcache_raw_collect (regcache, SPARC32_FSR_REGNUM, regs + (32 * 4) + 4);
|
| + regcache_raw_collect (regcache, SPARC32_FSR_REGNUM,
|
| + regs + fpregset->r_fsr_offset);
|
| }
|
|
|
|
|
| @@ -2001,6 +2046,18 @@ const struct sparc_gregset sparc32_sunos4_gregset =
|
| 4 * 4, /* %g1 */
|
| -1 /* %l0 */
|
| };
|
| +
|
| +const struct sparc_fpregset sparc32_sunos4_fpregset =
|
| +{
|
| + 0 * 4, /* %f0 */
|
| + 33 * 4, /* %fsr */
|
| +};
|
| +
|
| +const struct sparc_fpregset sparc32_bsd_fpregset =
|
| +{
|
| + 0 * 4, /* %f0 */
|
| + 32 * 4, /* %fsr */
|
| +};
|
|
|
|
|
| /* Provide a prototype to silence -Wmissing-prototypes. */
|
|
|