* Makefile.in (ALLCONFIG): Add config/i386/ptx.mh
[deliverable/binutils-gdb.git] / gdb / sp64-tdep.c
CommitLineData
cb747ec5
DE
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 (dje@cygnus.com).
4
5This file is part of GDB.
6
7This program is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2 of the License, or
10(at your option) any later version.
11
12This program is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with this program; if not, write to the Free Software
19Foundation, 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#include "ieee-float.h"
27
28/*#include "symfile.h" /* for objfiles.h */
29/*#include "objfiles.h" /* for find_pc_section */
30
31/* This file contains replacements and additions to sparc-tdep.c only.
32 Some of this code has been written for a day when we can merge at least
33 some of this with sparc-tdep.c. Macro TARGET_SPARC64 exists to allow some
34 code to potentially be used by both. */
35
36#define TARGET_SPARC64 1 /* later make a config parm or some such */
37
38/* From infrun.c */
39extern int stop_after_trap;
40
41/* Branches with prediction are treated like their non-predicting cousins. */
42/* FIXME: What about floating point branches? */
43
44typedef enum
45{
46 Error, not_branch, bicc, bicca, ba, baa, ticc, ta, done_retry
47} branch_type;
48
49/* Simulate single-step ptrace call for sun4. Code written by Gary
50 Beihl (beihl@mcc.com). */
51
52/* npc4 and next_pc describe the situation at the time that the
53 step-breakpoint was set, not necessary the current value of NPC_REGNUM. */
54static CORE_ADDR next_pc, npc4, target;
55static int brknpc4, brktrg;
56typedef char binsn_quantum[BREAKPOINT_MAX];
57static binsn_quantum break_mem[3];
58
59/* Non-zero if we just simulated a single-step ptrace call. This is
60 needed because we cannot remove the breakpoints in the inferior
61 process until after the `wait' in `wait_for_inferior'. Used for
62 sun4. */
63
64int one_stepped;
65
66/* sparc64_single_step() is called just before we want to resume the inferior,
67 if we want to single-step it but there is no hardware or kernel single-step
68 support (as on all SPARCs). We find all the possible targets of the
69 coming instruction and breakpoint them.
70
71 single_step is also called just after the inferior stops. If we had
72 set up a simulated single-step, we undo our damage. */
73
74/* FIXME: When the code is releasable, sparc's single step could become this
75 one, removing the duplication. */
76
77void
78sparc64_single_step (ignore)
79 int ignore; /* pid, but we don't need it */
80{
81 branch_type br, isbranch();
82 CORE_ADDR pc;
83 long pc_instruction;
84
85 if (!one_stepped)
86 {
87 /* Always set breakpoint for NPC. */
88 next_pc = read_register (NPC_REGNUM);
89 npc4 = next_pc + 4; /* branch not taken */
90
91 target_insert_breakpoint (next_pc, break_mem[0]);
92 /* printf ("set break at %x\n",next_pc); */
93
94 pc = read_register (PC_REGNUM);
95 pc_instruction = read_memory_integer (pc, sizeof(pc_instruction));
96 br = isbranch (pc_instruction, pc, &target);
97 brknpc4 = brktrg = 0;
98
99 if (br == bicca)
100 {
101 /* Conditional annulled branch will either end up at
102 npc (if taken) or at npc+4 (if not taken).
103 Trap npc+4. */
104 brknpc4 = 1;
105 target_insert_breakpoint (npc4, break_mem[1]);
106 }
107 else if ((br == baa && target != next_pc)
108 || (TARGET_SPARC64 && br == done_retry))
109 {
110 /* Unconditional annulled branch will always end up at
111 the target. */
112 brktrg = 1;
113 target_insert_breakpoint (target, break_mem[2]);
114 }
115
116 /* We are ready to let it go */
117 one_stepped = 1;
118 return;
119 }
120 else
121 {
122 /* Remove breakpoints */
123 target_remove_breakpoint (next_pc, break_mem[0]);
124
125 if (brknpc4)
126 target_remove_breakpoint (npc4, break_mem[1]);
127
128 if (brktrg)
129 target_remove_breakpoint (target, break_mem[2]);
130
131 one_stepped = 0;
132 }
133}
134\f
135/* FIXME: sparc64_frame_chain() is temporary. sparc_frame_chain() can
136 be fixed to support both of us. */
137
138#define FRAME_SAVED_L0 0 /* Byte offset from SP */
139#define FRAME_SAVED_I0 (8*REGISTER_RAW_SIZE (0)) /* Byte offset from SP */
140
141CORE_ADDR
142sparc64_frame_chain (thisframe)
143 FRAME thisframe;
144{
145 REGISTER_TYPE retval;
146 int err;
147 CORE_ADDR addr;
148
149 addr = thisframe->frame + FRAME_SAVED_I0 +
150 REGISTER_RAW_SIZE (0) * (FP_REGNUM - I0_REGNUM);
151 err = target_read_memory (addr, (char *) &retval, sizeof (REGISTER_TYPE));
152 if (err)
153 return 0;
154 SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
155 return retval;
156}
157
158CORE_ADDR
159sparc64_extract_struct_value_address (regbuf)
160 char regbuf[REGISTER_BYTES];
161{
162 CORE_ADDR addr;
163
164 /* FIXME: We assume a non-leaf function. */
165 addr = read_register (I0_REGNUM);
166 return addr;
167}
168
169/* Find the pc saved in frame FRAME. */
170/* FIXME: This function can be removed when sparc_frame_saved_pc
171 handles us too. */
172
173CORE_ADDR
174sparc64_frame_saved_pc (frame)
175 FRAME frame;
176{
177 int err;
178 REGISTER_TYPE retval;
179 CORE_ADDR addr,prev_pc;
180
181 if (get_current_frame () == frame) /* FIXME, debug check. Remove >=gdb-4.6 */
182 {
183 if (read_register (SP_REGNUM) != frame->bottom) abort();
184 }
185
186 addr = frame->bottom + FRAME_SAVED_I0 +
187 REGISTER_RAW_SIZE (0) * (I7_REGNUM - I0_REGNUM);
188 err = target_read_memory (addr, (char *) &retval, sizeof (REGISTER_TYPE));
189 if (err)
190 return 0;
191 SWAP_TARGET_AND_HOST (&retval, sizeof (retval));
192
193 /* CORE_ADDR isn't always the same size as REGISTER_TYPE, so convert. */
194
195 prev_pc = (CORE_ADDR) retval;
196 return PC_ADJUST (prev_pc);
197}
198
199/* Check instruction at ADDR to see if it is an annulled branch or other
200 instruction whose npc isn't pc+4 (eg: trap, done, retry).
201 All other instructions will go to NPC or will trap.
202 Set *TARGET if we find a candidate branch; set to zero if not. */
203
204branch_type
205isbranch (instruction, addr, target)
206 long instruction;
207 CORE_ADDR addr, *target;
208{
209 branch_type val = not_branch;
210 long int offset; /* Must be signed for sign-extend. */
211 union
212 {
213 unsigned long int code;
214 struct
215 {
216 unsigned int op:2;
217 unsigned int a:1;
218 unsigned int cond:4;
219 unsigned int op2:3;
220 unsigned int disp22:22;
221 } b;
222 struct
223 {
224 unsigned int op:2;
225 unsigned int a:1;
226 unsigned int cond:4;
227 unsigned int op2:3;
228 unsigned int cc:2;
229 unsigned int p:1;
230 unsigned int disp19:19;
231 } bp;
232 struct
233 {
234 unsigned int op:2;
235 unsigned int a:1;
236 unsigned int zero:1;
237 unsigned int rcond:3;
238 unsigned int op2:3;
239 unsigned int disp16hi:2;
240 unsigned int p:1;
241 unsigned int rs1:5;
242 unsigned int disp16lo:14;
243 } bpr;
244 struct
245 {
246 unsigned int op:2;
247 unsigned int fcn:5;
248 unsigned int op3:6;
249 unsigned int reserved:19;
250 } dr;
251 } insn;
252
253 *target = 0;
254 insn.code = instruction;
255
256 if (insn.b.op == 0
257 && (insn.b.op2 == 1 || insn.b.op2 == 2 || insn.b.op2 ==3
258 || insn.b.op2 == 5 || insn.b.op2 == 6))
259 {
260 if (insn.b.cond == 8)
261 val = insn.b.a ? baa : ba;
262 else
263 val = insn.b.a ? bicca : bicc;
264 switch (insn.b.op2)
265 {
266 case 1: /* bpcc */
267 offset = 4 * ((int) (insn.bp.disp19 << 13) >> 13);
268 break;
269 case 2: /* bicc */
270 offset = 4 * ((int) (insn.b.disp22 << 10) >> 10);
271 break;
272 case 3: /* bpr */
273 offset = 4 * ((int) ((insn.bpr.disp16hi << 10)
274 || (insn.bpr.disp16lo << 18)) >> 13);
275 break;
276 case 5: /* fbpfcc */
277 offset = 4 * ((int) (insn.bp.disp19 << 13) >> 13);
278 break;
279 case 6: /* fbfcc */
280 offset = 4 * ((int) (insn.b.disp22 << 10) >> 10);
281 break;
282 }
283 *target = addr + offset;
284 }
285 else if (insn.dr.op == 2 && insn.dr.op3 == 62)
286 {
287 if (insn.dr.fcn == 0)
288 {
289 /* done */
290 *target = read_register (TNPC_REGNUM);
291 val = done_retry;
292 }
293 else if (insn.dr.fcn == 1)
294 {
295 /* retry */
296 *target = read_register (TPC_REGNUM);
297 val = done_retry;
298 }
299 }
300
301 return val;
302}
303
304/* We try to support 32 bit and 64 bit pointers.
305 We are called when the Shade target is selected by shadeif.c. */
306
307int target_ptr_bit = 64; /* default */
308
309void
310set_target_ptr_bit(ptr_bit)
311 int ptr_bit;
312{
313 target_ptr_bit = ptr_bit;
314}
This page took 0.069872 seconds and 4 git commands to generate.