-/* Target-dependent code for the SPARC 64 for GDB, the GNU debugger.
- Copyright 1986, 1987, 1989, 1991, 1992, 1993 Free Software Foundation, Inc.
- Contributed by Doug Evans (dje@cygnus.com).
-
-This file is part of GDB.
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-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. */
-
-#include "defs.h"
-#include "frame.h"
-#include "inferior.h"
-#include "obstack.h"
-#include "target.h"
-
-/*#include "symfile.h" /* for objfiles.h */
-/*#include "objfiles.h" /* for find_pc_section */
-
-/* This file contains replacements and additions to sparc-tdep.c only.
- Some of this code has been written for a day when we can merge at least
- some of this with sparc-tdep.c. Macro TARGET_SPARC64 exists to allow some
- code to potentially be used by both. */
-
-#define TARGET_SPARC64 1 /* later make a config parm or some such */
-
-/* From infrun.c */
-extern int stop_after_trap;
-
-/* Branches with prediction are treated like their non-predicting cousins. */
-/* FIXME: What about floating point branches? */
-
-typedef enum
-{
- Error, not_branch, bicc, bicca, ba, baa, ticc, ta, done_retry
-} branch_type;
-
-/* Simulate single-step ptrace call for sun4. Code written by Gary
- Beihl (beihl@mcc.com). */
-
-/* npc4 and next_pc describe the situation at the time that the
- step-breakpoint was set, not necessary the current value of NPC_REGNUM. */
-static CORE_ADDR next_pc, npc4, target;
-static int brknpc4, brktrg;
-typedef char binsn_quantum[BREAKPOINT_MAX];
-static binsn_quantum break_mem[3];
-
-/* Non-zero if we just simulated a single-step ptrace call. This is
- needed because we cannot remove the breakpoints in the inferior
- process until after the `wait' in `wait_for_inferior'. Used for
- sun4. */
-
-int one_stepped;
-
-/* sparc64_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
- coming instruction and breakpoint them.
-
- single_step is also called just after the inferior stops. If we had
- set up a simulated single-step, we undo our damage. */
-
-/* FIXME: When the code is releasable, sparc's single step could become this
- one, removing the duplication. */
-
-void
-sparc64_single_step (ignore)
- int ignore; /* pid, but we don't need it */
-{
- branch_type br, isbranch();
- CORE_ADDR pc;
- long pc_instruction;
-
- if (!one_stepped)
- {
- /* Always set breakpoint for NPC. */
- next_pc = read_register (NPC_REGNUM);
- npc4 = next_pc + 4; /* branch not taken */
-
- target_insert_breakpoint (next_pc, break_mem[0]);
- /* printf_unfiltered ("set break at %x\n",next_pc); */
-
- pc = read_register (PC_REGNUM);
- pc_instruction = read_memory_integer (pc, sizeof(pc_instruction));
- br = isbranch (pc_instruction, pc, &target);
- brknpc4 = brktrg = 0;
-
- if (br == bicca)
- {
- /* Conditional annulled branch will either end up at
- npc (if taken) or at npc+4 (if not taken).
- Trap npc+4. */
- brknpc4 = 1;
- target_insert_breakpoint (npc4, break_mem[1]);
- }
- else if ((br == baa && target != next_pc)
- || (TARGET_SPARC64 && br == done_retry))
- {
- /* Unconditional annulled branch will always end up at
- the target. */
- brktrg = 1;
- target_insert_breakpoint (target, break_mem[2]);
- }
-
- /* We are ready to let it go */
- one_stepped = 1;
- return;
- }
- else
- {
- /* Remove breakpoints */
- target_remove_breakpoint (next_pc, break_mem[0]);
-
- if (brknpc4)
- target_remove_breakpoint (npc4, break_mem[1]);
-
- if (brktrg)
- target_remove_breakpoint (target, break_mem[2]);
-
- one_stepped = 0;
- }
-}
-\f
-CORE_ADDR
-sparc64_extract_struct_value_address (regbuf)
- char regbuf[REGISTER_BYTES];
-{
- CORE_ADDR addr;
-
- /* FIXME: We assume a non-leaf function. */
- addr = read_register (I0_REGNUM);
- return addr;
-}
-
-/* Check instruction at ADDR to see if it is an annulled branch or other
- instruction whose npc isn't pc+4 (eg: trap, done, retry).
- All other instructions will go to NPC or will trap.
- Set *TARGET if we find a candidate branch; set to zero if not. */
-
-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. */
- union
- {
- unsigned long int code;
- struct
- {
- unsigned int op:2;
- unsigned int a:1;
- unsigned int cond:4;
- unsigned int op2:3;
- unsigned int disp22:22;
- } b;
- struct
- {
- unsigned int op:2;
- unsigned int a:1;
- unsigned int cond:4;
- unsigned int op2:3;
- unsigned int cc:2;
- unsigned int p:1;
- unsigned int disp19:19;
- } bp;
- struct
- {
- unsigned int op:2;
- unsigned int a:1;
- unsigned int zero:1;
- unsigned int rcond:3;
- unsigned int op2:3;
- unsigned int disp16hi:2;
- unsigned int p:1;
- unsigned int rs1:5;
- unsigned int disp16lo:14;
- } bpr;
- struct
- {
- unsigned int op:2;
- unsigned int fcn:5;
- unsigned int op3:6;
- unsigned int reserved:19;
- } dr;
- } insn;
-
- *target = 0;
- insn.code = instruction;
-
- if (insn.b.op == 0
- && (insn.b.op2 == 1 || insn.b.op2 == 2 || insn.b.op2 ==3
- || insn.b.op2 == 5 || insn.b.op2 == 6))
- {
- if (insn.b.cond == 8)
- val = insn.b.a ? baa : ba;
- else
- val = insn.b.a ? bicca : bicc;
- switch (insn.b.op2)
- {
- case 1: /* bpcc */
- offset = 4 * ((int) (insn.bp.disp19 << 13) >> 13);
- break;
- case 2: /* bicc */
- offset = 4 * ((int) (insn.b.disp22 << 10) >> 10);
- break;
- case 3: /* bpr */
- offset = 4 * ((int) ((insn.bpr.disp16hi << 10)
- || (insn.bpr.disp16lo << 18)) >> 13);
- break;
- case 5: /* fbpfcc */
- offset = 4 * ((int) (insn.bp.disp19 << 13) >> 13);
- break;
- case 6: /* fbfcc */
- offset = 4 * ((int) (insn.b.disp22 << 10) >> 10);
- break;
- }
- *target = addr + offset;
- }
- else if (insn.dr.op == 2 && insn.dr.op3 == 62)
- {
- if (insn.dr.fcn == 0)
- {
- /* done */
- *target = read_register (TNPC_REGNUM);
- val = done_retry;
- }
- else if (insn.dr.fcn == 1)
- {
- /* retry */
- *target = read_register (TPC_REGNUM);
- val = done_retry;
- }
- }
-
- return val;
-}
-
-/* PRINT_REGISTER_HOOK routine.
- Pretty print various registers. */
-
-static void
-dump_ccreg (reg, val)
- char *reg;
- int val;
-{
- printf_unfiltered ("%s:%s,%s,%s,%s", reg,
- val & 8 ? "N" : "NN",
- val & 4 ? "Z" : "NZ",
- val & 2 ? "O" : "NO",
- val & 1 ? "C" : "NC"
- );
-}
-
-void
-sparc_print_register_hook (regno)
- int regno;
-{
- if (((unsigned) (regno) - FP0_REGNUM < FP_MAX_REGNUM - FP0_REGNUM)
- && ((regno) & 1) == 0)
- {
- char doublereg[8]; /* two float regs */
- if (!read_relative_register_raw_bytes ((regno), doublereg))
- {
- printf_unfiltered("\t");
- print_floating (doublereg, builtin_type_double, gdb_stdout);
- }
- }
- else if ((regno) == CCR_REGNUM)
- {
- int ccr = read_register (CCR_REGNUM);
- printf_unfiltered("\t");
- dump_ccreg ("xcc", ccr >> 4);
- printf_unfiltered(", ");
- dump_ccreg ("icc", ccr & 15);
- }
-}