Need to declare nlm32_sparc_vec; oopsie.
[deliverable/binutils-gdb.git] / gdb / symm-tdep.c
1 /* Sequent Symmetry target interface, for GDB when running under Unix.
2 Copyright (C) 1986, 1987, 1989, 1991 Free Software Foundation, Inc.
3
4 This file is part of GDB.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20 /* many 387-specific items of use taken from i386-dep.c */
21
22 #include "defs.h"
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
36 static long i386_get_frame_setup ();
37 static i386_follow_jump ();
38
39 #include <sgtty.h>
40 #define TERMINAL struct sgttyb
41
42 /* rounds 'one' up to divide evenly by 'two' */
43
44 int
45 round(one,two)
46 register 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
58 static CORE_ADDR codestream_next_addr;
59 static CORE_ADDR codestream_addr;
60 static unsigned char codestream_buf[sizeof (int)];
61 static int codestream_off;
62 static 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
71 static unsigned char
72 codestream_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
88 static void
89 codestream_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
98 static void
99 codestream_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 */
122 i386_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
133 memset (fsrp, 0, sizeof *fsrp);
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
172 static long
173 i386_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);
205 if (memcmp (buf, proto1, 3) == 0)
206 pos += 3;
207 else if (memcmp (buf, proto2, 4) == 0)
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 */
266 static
267 i386_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
311 i386_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
338 void
339 symmetry_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;
348 struct minimal_symbol *msymbol;
349 float f;
350
351 if (TYPE_CODE_FLT == TYPE_CODE(type)) {
352 msymbol = lookup_minimal_symbol ("1167_flt", (struct objfile *) NULL);
353 if (msymbol != NULL) {
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:
361 /* FIXME: broken for cross-debugging. */
362 f = (float) xd.d;
363 memcpy (valbuf, &f, TYPE_LENGTH(type));
364 break;
365 case 8:
366 /* FIXME: broken for cross-debugging. */
367 memcpy (valbuf, &xd.d, TYPE_LENGTH(type));
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;
380 /* FIXME: broken for cross-debugging. */
381 memcpy (valbuf, &f, 4);
382 break;
383 case 8: /* double */
384 /* FIXME: broken for cross-debugging. */
385 memcpy (valbuf, &xd.d, 8);
386 break;
387 default:
388 error("Unknown floating point size");
389 break;
390 }
391 }
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 */
404 int
405 ptx_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
421 static 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 */
429 0x18d0, /* eax */
430 0x18c8, /* eax */
431 0x18cc, /* eax */
432 0x1be0, /* st0 */
433 0x1bea, /* st1 */
434 0x18c4, /* ebx */
435 0x18b8, /* esi */
436 0x18b4, /* edi */
437 0x1bf4, /* st2 */
438 0x1bfe, /* st3 */
439 0x1c08, /* st4 */
440 0x1c12, /* st5 */
441 0x1c1c, /* st6 */
442 0x1c26, /* st7 */
443 0x18e0, /* esp */
444 0x18bc, /* ebp */
445 0x18d4, /* eip */
446 0x18dc, /* flags */
447 0x1c38, /* fp1 */
448 0x1c3c, /* fp2 */
449 0x1c40, /* fp3 */
450 0x1c44, /* fp4 */
451 0x1c48, /* fp5 */
452 0x1c4c, /* fp6 */
453 0x1c50, /* fp7 */
454 0x1c54, /* fp8 */
455 0x1c58, /* fp9 */
456 0x1c5c, /* fp10 */
457 0x1c60, /* fp11 */
458 0x1c64, /* fp12 */
459 0x1c68, /* fp13 */
460 0x1c6c, /* fp14 */
461 0x1c70, /* fp15 */
462 0x1c74, /* fp16 */
463 0x1c78, /* fp17 */
464 0x1c7c, /* fp18 */
465 0x1c80, /* fp19 */
466 0x1c84, /* fp20 */
467 0x1c88, /* fp21 */
468 0x1c8c, /* fp22 */
469 0x1c90, /* fp23 */
470 0x1c94, /* fp24 */
471 0x1c98, /* fp25 */
472 0x1c9c, /* fp26 */
473 0x1ca0, /* fp27 */
474 0x1ca4, /* fp28 */
475 0x1ca8, /* fp29 */
476 0x1cac, /* fp30 */
477 0x1cb0, /* fp31 */
478 };
479
480 unsigned int
481 register_addr (regno, blockend)
482 int regno, blockend;
483 {
484 if ((regno < 0) || (regno >= NUM_REGS)) {
485 error("Invalid register number %d.", regno);
486 }
487 return reg_offsets[regno];
488 }
489 #endif /* _SEQUENT_ */
This page took 0.044873 seconds and 4 git commands to generate.