]> Git Repo - binutils.git/blob - gdb/sp64-tdep.c
* exec.c: Merge in RS6000 support from xcoffexec.c.
[binutils.git] / gdb / sp64-tdep.c
1 /* Target-dependent code for the SPARC 64 for GDB, the GNU debugger.
2    Copyright 1986, 1987, 1989, 1991, 1992, 1993 Free Software Foundation, Inc.
3    Contributed by Doug Evans ([email protected]).
4
5 This file is part of GDB.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
20
21 #include "defs.h"
22 #include "frame.h"
23 #include "inferior.h"
24 #include "obstack.h"
25 #include "target.h"
26
27 /*#include "symfile.h" /* for objfiles.h */
28 /*#include "objfiles.h" /* for find_pc_section */
29
30 /* This file contains replacements and additions to sparc-tdep.c only.
31    Some of this code has been written for a day when we can merge at least
32    some of this with sparc-tdep.c.  Macro TARGET_SPARC64 exists to allow some
33    code to potentially be used by both.  */
34
35 #define TARGET_SPARC64 1        /* later make a config parm or some such */
36
37 /* From infrun.c */
38 extern int stop_after_trap;
39
40 /* Branches with prediction are treated like their non-predicting cousins.  */
41 /* FIXME: What about floating point branches?  */
42
43 typedef enum
44 {
45   Error, not_branch, bicc, bicca, ba, baa, ticc, ta, done_retry
46 } branch_type;
47
48 /* Simulate single-step ptrace call for sun4.  Code written by Gary
49    Beihl ([email protected]).  */
50
51 /* npc4 and next_pc describe the situation at the time that the
52    step-breakpoint was set, not necessary the current value of NPC_REGNUM.  */
53 static CORE_ADDR next_pc, npc4, target;
54 static int brknpc4, brktrg;
55 typedef char binsn_quantum[BREAKPOINT_MAX];
56 static binsn_quantum break_mem[3];
57
58 /* Non-zero if we just simulated a single-step ptrace call.  This is
59    needed because we cannot remove the breakpoints in the inferior
60    process until after the `wait' in `wait_for_inferior'.  Used for
61    sun4. */
62
63 int one_stepped;
64
65 /* sparc64_single_step() is called just before we want to resume the inferior,
66    if we want to single-step it but there is no hardware or kernel single-step
67    support (as on all SPARCs).  We find all the possible targets of the
68    coming instruction and breakpoint them.
69
70    single_step is also called just after the inferior stops.  If we had
71    set up a simulated single-step, we undo our damage.  */
72
73 /* FIXME: When the code is releasable, sparc's single step could become this
74    one, removing the duplication.  */
75
76 void
77 sparc64_single_step (ignore)
78      int ignore; /* pid, but we don't need it */
79 {
80   branch_type br, isbranch();
81   CORE_ADDR pc;
82   long pc_instruction;
83
84   if (!one_stepped)
85     {
86       /* Always set breakpoint for NPC.  */
87       next_pc = read_register (NPC_REGNUM);
88       npc4 = next_pc + 4; /* branch not taken */
89
90       target_insert_breakpoint (next_pc, break_mem[0]);
91       /* printf_unfiltered ("set break at %x\n",next_pc); */
92
93       pc = read_register (PC_REGNUM);
94       pc_instruction = read_memory_integer (pc, sizeof(pc_instruction));
95       br = isbranch (pc_instruction, pc, &target);
96       brknpc4 = brktrg = 0;
97
98       if (br == bicca)
99         {
100           /* Conditional annulled branch will either end up at
101              npc (if taken) or at npc+4 (if not taken).
102              Trap npc+4.  */
103           brknpc4 = 1;
104           target_insert_breakpoint (npc4, break_mem[1]);
105         }
106       else if ((br == baa && target != next_pc)
107                || (TARGET_SPARC64 && br == done_retry))
108         {
109           /* Unconditional annulled branch will always end up at
110              the target.  */
111           brktrg = 1;
112           target_insert_breakpoint (target, break_mem[2]);
113         }
114
115       /* We are ready to let it go */
116       one_stepped = 1;
117       return;
118     }
119   else
120     {
121       /* Remove breakpoints */
122       target_remove_breakpoint (next_pc, break_mem[0]);
123
124       if (brknpc4)
125         target_remove_breakpoint (npc4, break_mem[1]);
126
127       if (brktrg)
128         target_remove_breakpoint (target, break_mem[2]);
129
130       one_stepped = 0;
131     }
132 }
133 \f
134 CORE_ADDR
135 sparc64_extract_struct_value_address (regbuf)
136      char regbuf[REGISTER_BYTES];
137 {
138   CORE_ADDR addr;
139
140   /* FIXME: We assume a non-leaf function.  */
141   addr = read_register (I0_REGNUM);
142   return addr;
143 }
144
145 /* Check instruction at ADDR to see if it is an annulled branch or other
146    instruction whose npc isn't pc+4 (eg: trap, done, retry).
147    All other instructions will go to NPC or will trap.
148    Set *TARGET if we find a candidate branch; set to zero if not. */
149    
150 branch_type
151 isbranch (instruction, addr, target)
152      long instruction;
153      CORE_ADDR addr, *target;
154 {
155   branch_type val = not_branch;
156   long int offset;              /* Must be signed for sign-extend.  */
157   union
158     {
159       unsigned long int code;
160       struct
161         {
162           unsigned int op:2;
163           unsigned int a:1;
164           unsigned int cond:4;
165           unsigned int op2:3;
166           unsigned int disp22:22;
167         } b;
168       struct
169         {
170           unsigned int op:2;
171           unsigned int a:1;
172           unsigned int cond:4;
173           unsigned int op2:3;
174           unsigned int cc:2;
175           unsigned int p:1;
176           unsigned int disp19:19;
177         } bp;
178       struct
179         {
180           unsigned int op:2;
181           unsigned int a:1;
182           unsigned int zero:1;
183           unsigned int rcond:3;
184           unsigned int op2:3;
185           unsigned int disp16hi:2;
186           unsigned int p:1;
187           unsigned int rs1:5;
188           unsigned int disp16lo:14;
189         } bpr;
190       struct
191         {
192           unsigned int op:2;
193           unsigned int fcn:5;
194           unsigned int op3:6;
195           unsigned int reserved:19;
196         } dr;
197     } insn;
198
199   *target = 0;
200   insn.code = instruction;
201
202   if (insn.b.op == 0
203       && (insn.b.op2 == 1 || insn.b.op2 == 2 || insn.b.op2 ==3
204           || insn.b.op2 == 5 || insn.b.op2 == 6))
205     {
206       if (insn.b.cond == 8)
207         val = insn.b.a ? baa : ba;
208       else
209         val = insn.b.a ? bicca : bicc;
210       switch (insn.b.op2)
211         {
212         case 1: /* bpcc */
213           offset = 4 * ((int) (insn.bp.disp19 << 13) >> 13);
214           break;
215         case 2: /* bicc */
216           offset = 4 * ((int) (insn.b.disp22 << 10) >> 10);
217           break;
218         case 3: /* bpr */
219           offset = 4 * ((int) ((insn.bpr.disp16hi << 10)
220                                || (insn.bpr.disp16lo << 18)) >> 13);
221           break;
222         case 5: /* fbpfcc */
223           offset = 4 * ((int) (insn.bp.disp19 << 13) >> 13);
224           break;
225         case 6: /* fbfcc */
226           offset = 4 * ((int) (insn.b.disp22 << 10) >> 10);
227           break;
228         }
229       *target = addr + offset;
230     }
231   else if (insn.dr.op == 2 && insn.dr.op3 == 62)
232     {
233       if (insn.dr.fcn == 0)
234         {
235           /* done */
236           *target = read_register (TNPC_REGNUM);
237           val = done_retry;
238         }
239       else if (insn.dr.fcn == 1)
240         {
241           /* retry */
242           *target = read_register (TPC_REGNUM);
243           val = done_retry;
244         }
245     }
246
247   return val;
248 }
249
250 /* PRINT_REGISTER_HOOK routine.
251    Pretty print various registers.  */
252
253 static void
254 dump_ccreg (reg, val)
255      char *reg;
256      int val;
257 {
258   printf_unfiltered ("%s:%s,%s,%s,%s", reg,
259           val & 8 ? "N" : "NN",
260           val & 4 ? "Z" : "NZ",
261           val & 2 ? "O" : "NO",
262           val & 1 ? "C" : "NC"
263   );
264 }
265
266 void
267 sparc_print_register_hook (regno)
268      int regno;
269 {
270   if (((unsigned) (regno) - FP0_REGNUM < FP_MAX_REGNUM - FP0_REGNUM)
271        && ((regno) & 1) == 0)
272     {
273       char doublereg[8];                /* two float regs */
274       if (!read_relative_register_raw_bytes ((regno), doublereg))
275         {
276           printf_unfiltered("\t");
277           print_floating (doublereg, builtin_type_double, gdb_stdout);
278         }
279     }
280   else if ((regno) == CCR_REGNUM)
281     {
282       int ccr = read_register (CCR_REGNUM);
283       printf_unfiltered("\t");
284       dump_ccreg ("xcc", ccr >> 4);
285       printf_unfiltered(", ");
286       dump_ccreg ("icc", ccr & 15);
287     }
288 }
This page took 0.038326 seconds and 4 git commands to generate.