* infptrace.c: Split out define of PT_KILL; Sequent defines PT_KILL
[platform/upstream/binutils.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_ */