* hppa-tdep.c: Remove all uses of use_unwind and `set use_unwind'
[deliverable/binutils-gdb.git] / gdb / symm-tdep.c
CommitLineData
07d021a6
JG
1/* Sequent Symmetry target interface, for GDB when running under Unix.
2 Copyright (C) 1986, 1987, 1989, 1991 Free Software Foundation, Inc.
3
4This file is part of GDB.
5
99a7de40 6This program is free software; you can redistribute it and/or modify
07d021a6 7it under the terms of the GNU General Public License as published by
99a7de40
JG
8the Free Software Foundation; either version 2 of the License, or
9(at your option) any later version.
07d021a6 10
99a7de40 11This program is distributed in the hope that it will be useful,
07d021a6
JG
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
99a7de40
JG
17along with this program; if not, write to the Free Software
18Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
07d021a6
JG
19
20/* many 387-specific items of use taken from i386-dep.c */
21
07d021a6 22#include "defs.h"
07d021a6
JG
23#include "frame.h"
24#include "inferior.h"
25#include "symtab.h"
26
27#include <signal.h>
28#include <sys/param.h>
29#include <sys/user.h>
30#include <sys/dir.h>
31#include <sys/ioctl.h>
32#include <sys/stat.h>
33#include "gdbcore.h"
34#include <fcntl.h>
35
36static long i386_get_frame_setup ();
37static i386_follow_jump ();
38
39#include <sgtty.h>
40#define TERMINAL struct sgttyb
41
07d021a6
JG
42/* rounds 'one' up to divide evenly by 'two' */
43
44int
45round(one,two)
46register int one, two;
47
48{
49 register int temp;
50 temp = (one/two)*two;
51 if (one != temp) {
52 temp += two;
53 }
54 return temp;
55}
56
57
58static CORE_ADDR codestream_next_addr;
59static CORE_ADDR codestream_addr;
60static unsigned char codestream_buf[sizeof (int)];
61static int codestream_off;
62static int codestream_cnt;
63
64#define codestream_tell() (codestream_addr + codestream_off)
65#define codestream_peek() (codestream_cnt == 0 ? \
66 codestream_fill(1): codestream_buf[codestream_off])
67#define codestream_get() (codestream_cnt-- == 0 ? \
68 codestream_fill(0) : codestream_buf[codestream_off++])
69
70
71static unsigned char
72codestream_fill (peek_flag)
73{
74 codestream_addr = codestream_next_addr;
75 codestream_next_addr += sizeof (int);
76 codestream_off = 0;
77 codestream_cnt = sizeof (int);
78 read_memory (codestream_addr,
79 (unsigned char *)codestream_buf,
80 sizeof (int));
81
82 if (peek_flag)
83 return (codestream_peek());
84 else
85 return (codestream_get());
86}
87
88static void
89codestream_seek (place)
90{
91 codestream_next_addr = place & -sizeof (int);
92 codestream_cnt = 0;
93 codestream_fill (1);
94 while (codestream_tell() != place)
95 codestream_get ();
96}
97
98static void
99codestream_read (buf, count)
100 unsigned char *buf;
101{
102 unsigned char *p;
103 int i;
104 p = buf;
105 for (i = 0; i < count; i++)
106 *p++ = codestream_get ();
107}
108
109/*
110 * Following macro translates i386 opcode register numbers to Symmetry
111 * register numbers. This is used by FRAME_FIND_SAVED_REGS.
112 *
113 * %eax %ecx %edx %ebx %esp %ebp %esi %edi
114 * i386 0 1 2 3 4 5 6 7
115 * Symmetry 0 2 1 5 14 15 6 7
116 *
117 */
118#define I386_REGNO_TO_SYMMETRY(n) \
119((n)==0?0 :(n)==1?2 :(n)==2?1 :(n)==3?5 :(n)==4?14 :(n)==5?15 :(n))
120
121/* from i386-dep.c */
122i386_frame_find_saved_regs (fip, fsrp)
123 struct frame_info *fip;
124 struct frame_saved_regs *fsrp;
125{
126 unsigned long locals;
127 unsigned char *p;
128 unsigned char op;
129 CORE_ADDR dummy_bottom;
130 CORE_ADDR adr;
131 int i;
132
56eec3c7 133 memset (fsrp, 0, sizeof *fsrp);
07d021a6
JG
134
135 /* if frame is the end of a dummy, compute where the
136 * beginning would be
137 */
138 dummy_bottom = fip->frame - 4 - NUM_REGS*4 - CALL_DUMMY_LENGTH;
139
140 /* check if the PC is in the stack, in a dummy frame */
141 if (dummy_bottom <= fip->pc && fip->pc <= fip->frame)
142 {
143 /* all regs were saved by push_call_dummy () */
144 adr = fip->frame - 4;
145 for (i = 0; i < NUM_REGS; i++)
146 {
147 fsrp->regs[i] = adr;
148 adr -= 4;
149 }
150 return;
151 }
152
153 locals = i386_get_frame_setup (get_pc_function_start (fip->pc));
154
155 if (locals >= 0)
156 {
157 adr = fip->frame - 4 - locals;
158 for (i = 0; i < 8; i++)
159 {
160 op = codestream_get ();
161 if (op < 0x50 || op > 0x57)
162 break;
163 fsrp->regs[I386_REGNO_TO_SYMMETRY(op - 0x50)] = adr;
164 adr -= 4;
165 }
166 }
167
168 fsrp->regs[PC_REGNUM] = fip->frame + 4;
169 fsrp->regs[FP_REGNUM] = fip->frame;
170}
171
172static long
173i386_get_frame_setup (pc)
174{
175 unsigned char op;
176
177 codestream_seek (pc);
178
179 i386_follow_jump ();
180
181 op = codestream_get ();
182
183 if (op == 0x58) /* popl %eax */
184 {
185 /*
186 * this function must start with
187 *
188 * popl %eax 0x58
189 * xchgl %eax, (%esp) 0x87 0x04 0x24
190 * or xchgl %eax, 0(%esp) 0x87 0x44 0x24 0x00
191 *
192 * (the system 5 compiler puts out the second xchg
193 * inst, and the assembler doesn't try to optimize it,
194 * so the 'sib' form gets generated)
195 *
196 * this sequence is used to get the address of the return
197 * buffer for a function that returns a structure
198 */
199 int pos;
200 unsigned char buf[4];
201 static unsigned char proto1[3] = { 0x87,0x04,0x24 };
202 static unsigned char proto2[4] = { 0x87,0x44,0x24,0x00 };
203 pos = codestream_tell ();
204 codestream_read (buf, 4);
56eec3c7 205 if (memcmp (buf, proto1, 3) == 0)
07d021a6 206 pos += 3;
56eec3c7 207 else if (memcmp (buf, proto2, 4) == 0)
07d021a6
JG
208 pos += 4;
209
210 codestream_seek (pos);
211 op = codestream_get (); /* update next opcode */
212 }
213
214 if (op == 0x55) /* pushl %esp */
215 {
216 if (codestream_get () != 0x8b) /* movl %esp, %ebp (2bytes) */
217 return (-1);
218 if (codestream_get () != 0xec)
219 return (-1);
220 /*
221 * check for stack adjustment
222 *
223 * subl $XXX, %esp
224 *
225 * note: you can't subtract a 16 bit immediate
226 * from a 32 bit reg, so we don't have to worry
227 * about a data16 prefix
228 */
229 op = codestream_peek ();
230 if (op == 0x83) /* subl with 8 bit immed */
231 {
232 codestream_get ();
233 if (codestream_get () != 0xec)
234 return (-1);
235 /* subl with signed byte immediate
236 * (though it wouldn't make sense to be negative)
237 */
238 return (codestream_get());
239 }
240 else if (op == 0x81) /* subl with 32 bit immed */
241 {
242 int locals;
243 if (codestream_get () != 0xec)
244 return (-1);
245 /* subl with 32 bit immediate */
246 codestream_read ((unsigned char *)&locals, 4);
247 return (locals);
248 }
249 else
250 {
251 return (0);
252 }
253 }
254 else if (op == 0xc8)
255 {
256 /* enter instruction: arg is 16 unsigned immed */
257 unsigned short slocals;
258 codestream_read ((unsigned char *)&slocals, 2);
259 codestream_get (); /* flush final byte of enter instruction */
260 return (slocals);
261 }
262 return (-1);
263}
264
265/* next instruction is a jump, move to target */
266static
267i386_follow_jump ()
268{
269 int long_delta;
270 short short_delta;
271 char byte_delta;
272 int data16;
273 int pos;
274
275 pos = codestream_tell ();
276
277 data16 = 0;
278 if (codestream_peek () == 0x66)
279 {
280 codestream_get ();
281 data16 = 1;
282 }
283
284 switch (codestream_get ())
285 {
286 case 0xe9:
287 /* relative jump: if data16 == 0, disp32, else disp16 */
288 if (data16)
289 {
290 codestream_read ((unsigned char *)&short_delta, 2);
291 pos += short_delta + 3; /* include size of jmp inst */
292 }
293 else
294 {
295 codestream_read ((unsigned char *)&long_delta, 4);
296 pos += long_delta + 5;
297 }
298 break;
299 case 0xeb:
300 /* relative jump, disp8 (ignore data16) */
301 codestream_read ((unsigned char *)&byte_delta, 1);
302 pos += byte_delta + 2;
303 break;
304 }
305 codestream_seek (pos + data16);
306}
307
308/* return pc of first real instruction */
309/* from i386-dep.c */
310
311i386_skip_prologue (pc)
312{
313 unsigned char op;
314 int i;
315
316 if (i386_get_frame_setup (pc) < 0)
317 return (pc);
318
319 /* found valid frame setup - codestream now points to
320 * start of push instructions for saving registers
321 */
322
323 /* skip over register saves */
324 for (i = 0; i < 8; i++)
325 {
326 op = codestream_peek ();
327 /* break if not pushl inst */
328 if (op < 0x50 || op > 0x57)
329 break;
330 codestream_get ();
331 }
332
333 i386_follow_jump ();
334
335 return (codestream_tell ());
336}
337
56eec3c7 338void
07d021a6
JG
339symmetry_extract_return_value(type, regbuf, valbuf)
340 struct type *type;
341 char *regbuf;
342 char *valbuf;
343{
344 union {
345 double d;
346 int l[2];
347 } xd;
1ab3bf1b 348 struct minimal_symbol *msymbol;
07d021a6
JG
349 float f;
350
351 if (TYPE_CODE_FLT == TYPE_CODE(type)) {
1ab3bf1b
JG
352 msymbol = lookup_minimal_symbol ("1167_flt", (struct objfile *) NULL);
353 if (msymbol != NULL) {
07d021a6
JG
354 /* found "1167_flt" means 1167, %fp2-%fp3 */
355 /* float & double; 19= %fp2, 20= %fp3 */
356 /* no single precision on 1167 */
357 xd.l[1] = *((int *)&regbuf[REGISTER_BYTE(19)]);
358 xd.l[0] = *((int *)&regbuf[REGISTER_BYTE(20)]);
359 switch (TYPE_LENGTH(type)) {
360 case 4:
56eec3c7 361 /* FIXME: broken for cross-debugging. */
07d021a6 362 f = (float) xd.d;
56eec3c7 363 memcpy (valbuf, &f, TYPE_LENGTH(type));
07d021a6
JG
364 break;
365 case 8:
56eec3c7
JK
366 /* FIXME: broken for cross-debugging. */
367 memcpy (valbuf, &xd.d, TYPE_LENGTH(type));
07d021a6
JG
368 break;
369 default:
370 error("Unknown floating point size");
371 break;
372 }
373 } else {
374 /* 387 %st(0), gcc uses this */
375 i387_to_double(((int *)&regbuf[REGISTER_BYTE(3)]),
376 &xd.d);
377 switch (TYPE_LENGTH(type)) {
378 case 4: /* float */
379 f = (float) xd.d;
56eec3c7
JK
380 /* FIXME: broken for cross-debugging. */
381 memcpy (valbuf, &f, 4);
07d021a6
JG
382 break;
383 case 8: /* double */
56eec3c7
JK
384 /* FIXME: broken for cross-debugging. */
385 memcpy (valbuf, &xd.d, 8);
07d021a6
JG
386 break;
387 default:
388 error("Unknown floating point size");
389 break;
390 }
391 }
56eec3c7
JK
392 } else {
393 memcpy (valbuf, regbuf, TYPE_LENGTH (type));
394 }
395}
396
397#ifdef _SEQUENT_ /* ptx, not dynix */
398/*
399 * Convert compiler register number to gdb internal
400 * register number. The PTX C compiler only really
401 * puts things in %edi, %esi and %ebx, but it can't hurt
402 * to be complete here.
403 */
404int
405ptx_coff_regno_to_gdb(regno)
406 int regno;
407{
408 return I386_REGNO_TO_SYMMETRY(regno);
409}
410
411/* For ptx, the value in blockend will be meaningless. This function
412 merely returns the proper offset given the register number. This
413 is much easier, because under ptx, the upage is set up with the
414 user struct on "top", and the registers "beneath" it (and thus defines
415 TRAD_CORE_USER_OFFSET in bfd). */
416
417/* The following table is for ptx 1.3. In theory it should not change with
418 the OS version, but if it does we should (if possible) figure out a way
419 to accept both the old and the new formats. */
420
421static unsigned int reg_offsets[NUM_REGS] = {
422/*
423 * u.u_ar0 = 0xfffff8d0
424 * VA_UBLOCK = 0xffffe000
425 * VA_UAREA = 0xfffff8e8
426 * struct user at ublock offset 0x18e8
427 * registers at ublock offset 0x18d0
428 */
4290x18d0, /* eax */
4300x18c8, /* eax */
4310x18cc, /* eax */
4320x1be0, /* st0 */
4330x1bea, /* st1 */
4340x18c4, /* ebx */
4350x18b8, /* esi */
4360x18b4, /* edi */
4370x1bf4, /* st2 */
4380x1bfe, /* st3 */
4390x1c08, /* st4 */
4400x1c12, /* st5 */
4410x1c1c, /* st6 */
4420x1c26, /* st7 */
4430x18e0, /* esp */
4440x18bc, /* ebp */
4450x18d4, /* eip */
4460x18dc, /* flags */
4470x1c38, /* fp1 */
4480x1c3c, /* fp2 */
4490x1c40, /* fp3 */
4500x1c44, /* fp4 */
4510x1c48, /* fp5 */
4520x1c4c, /* fp6 */
4530x1c50, /* fp7 */
4540x1c54, /* fp8 */
4550x1c58, /* fp9 */
4560x1c5c, /* fp10 */
4570x1c60, /* fp11 */
4580x1c64, /* fp12 */
4590x1c68, /* fp13 */
4600x1c6c, /* fp14 */
4610x1c70, /* fp15 */
4620x1c74, /* fp16 */
4630x1c78, /* fp17 */
4640x1c7c, /* fp18 */
4650x1c80, /* fp19 */
4660x1c84, /* fp20 */
4670x1c88, /* fp21 */
4680x1c8c, /* fp22 */
4690x1c90, /* fp23 */
4700x1c94, /* fp24 */
4710x1c98, /* fp25 */
4720x1c9c, /* fp26 */
4730x1ca0, /* fp27 */
4740x1ca4, /* fp28 */
4750x1ca8, /* fp29 */
4760x1cac, /* fp30 */
4770x1cb0, /* fp31 */
478};
479
480unsigned int
481register_addr (regno, blockend)
482 int regno, blockend;
483{
484 if ((regno < 0) || (regno >= NUM_REGS)) {
485 error("Invalid register number %d.", regno);
07d021a6 486 }
56eec3c7 487 return reg_offsets[regno];
07d021a6 488}
56eec3c7 489#endif /* _SEQUENT_ */
This page took 0.135689 seconds and 4 git commands to generate.