Tue Mar 3 15:11:52 1992 Michael Tiemann (tiemann@cygnus.com)
[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 exec_file_command (filename, from_tty)
43      char *filename;
44      int from_tty;
45 {
46   int val;
47
48   /* Eliminate all traces of old exec file.
49      Mark text segment as empty.  */
50
51   if (execfile)
52     free (execfile);
53   execfile = 0;
54   data_start = 0;
55   data_end -= exec_data_start;
56   text_start = 0;
57   text_end = 0;
58   exec_data_start = 0;
59   exec_data_end = 0;
60   if (execchan >= 0)
61     close (execchan);
62   execchan = -1;
63
64   /* Now open and digest the file the user requested, if any.  */
65
66   if (filename)
67     {
68       filename = tilde_expand (filename);
69       make_cleanup (free, filename);
70       
71       execchan = openp (getenv ("PATH"), 1, filename, O_RDONLY, 0,
72                         &execfile);
73       if (execchan < 0)
74         perror_with_name (filename);
75
76 #ifdef COFF_FORMAT
77       {
78         int aout_hdrsize;
79         int num_sections;
80
81         if (read_file_hdr (execchan, &file_hdr) < 0)
82           error ("\"%s\": not in executable format.", execfile);
83
84         aout_hdrsize = file_hdr.f_opthdr;
85         num_sections = file_hdr.f_nscns;
86
87         if (read_aout_hdr (execchan, &exec_aouthdr, aout_hdrsize) < 0)
88           error ("\"%s\": can't read optional aouthdr", execfile);
89
90         if (read_section_hdr (execchan, _TEXT, &text_hdr, num_sections,
91                               aout_hdrsize) < 0)
92           error ("\"%s\": can't read text section header", execfile);
93
94         if (read_section_hdr (execchan, _DATA, &data_hdr, num_sections,
95                               aout_hdrsize) < 0)
96           error ("\"%s\": can't read data section header", execfile);
97
98         text_start = exec_aouthdr.text_start;
99         text_end = text_start + exec_aouthdr.tsize;
100         text_offset = text_hdr.s_scnptr;
101         exec_data_start = exec_aouthdr.data_start;
102         exec_data_end = exec_data_start + exec_aouthdr.dsize;
103         exec_data_offset = data_hdr.s_scnptr;
104         data_start = exec_data_start;
105         data_end += exec_data_start;
106         exec_mtime = file_hdr.f_timdat;
107       }
108 #else /* not COFF_FORMAT */
109       {
110         struct stat st_exec;
111
112         val = myread (execchan, &exec_aouthdr, sizeof (AOUTHDR));
113
114         if (val < 0)
115           perror_with_name (filename);
116
117         text_start = N_ADDRADJ(exec_aouthdr);
118         exec_data_start = round(exec_aouthdr.a_text, NBPG*CLSIZE);
119         text_offset = N_TXTOFF (exec_aouthdr);
120         exec_data_offset = N_TXTOFF (exec_aouthdr) + exec_aouthdr.a_text;
121         text_end = exec_aouthdr.a_text;
122         exec_data_end = exec_data_start + exec_aouthdr.a_data;
123         data_start = exec_data_start;
124         data_end = data_start + exec_aouthdr.a_data;
125         exec_data_offset = N_TXTOFF(exec_aouthdr);
126         fstat (execchan, &st_exec);
127         exec_mtime = st_exec.st_mtime;
128       }
129 #endif /* not COFF_FORMAT */
130
131       validate_files ();
132     }
133   else if (from_tty)
134     printf ("No exec file now.\n");
135
136   /* Tell display code (if any) about the changed file name.  */
137   if (exec_file_display_hook)
138     (*exec_file_display_hook) (filename);
139 }
140
141 /* rounds 'one' up to divide evenly by 'two' */
142
143 int
144 round(one,two)
145 register int one, two;
146
147 {
148     register int temp;
149     temp = (one/two)*two;
150     if (one != temp) {
151         temp += two;
152     }
153     return temp;
154 }
155
156
157 static CORE_ADDR codestream_next_addr;
158 static CORE_ADDR codestream_addr;
159 static unsigned char codestream_buf[sizeof (int)];
160 static int codestream_off;
161 static int codestream_cnt;
162
163 #define codestream_tell() (codestream_addr + codestream_off)
164 #define codestream_peek() (codestream_cnt == 0 ? \
165                            codestream_fill(1): codestream_buf[codestream_off])
166 #define codestream_get() (codestream_cnt-- == 0 ? \
167                          codestream_fill(0) : codestream_buf[codestream_off++])
168
169
170 static unsigned char 
171 codestream_fill (peek_flag)
172 {
173   codestream_addr = codestream_next_addr;
174   codestream_next_addr += sizeof (int);
175   codestream_off = 0;
176   codestream_cnt = sizeof (int);
177   read_memory (codestream_addr,
178                (unsigned char *)codestream_buf,
179                sizeof (int));
180   
181   if (peek_flag)
182     return (codestream_peek());
183   else
184     return (codestream_get());
185 }
186
187 static void
188 codestream_seek (place)
189 {
190   codestream_next_addr = place & -sizeof (int);
191   codestream_cnt = 0;
192   codestream_fill (1);
193   while (codestream_tell() != place)
194     codestream_get ();
195 }
196
197 static void
198 codestream_read (buf, count)
199      unsigned char *buf;
200 {
201   unsigned char *p;
202   int i;
203   p = buf;
204   for (i = 0; i < count; i++)
205     *p++ = codestream_get ();
206 }
207
208 /*
209  * Following macro translates i386 opcode register numbers to Symmetry
210  * register numbers.  This is used by FRAME_FIND_SAVED_REGS.
211  *
212  *           %eax  %ecx  %edx  %ebx  %esp  %ebp  %esi  %edi
213  * i386        0     1     2     3     4     5     6     7
214  * Symmetry    0     2     1     5    14    15     6     7
215  *
216  */
217 #define I386_REGNO_TO_SYMMETRY(n) \
218 ((n)==0?0 :(n)==1?2 :(n)==2?1 :(n)==3?5 :(n)==4?14 :(n)==5?15 :(n))
219
220 /* from i386-dep.c */
221 i386_frame_find_saved_regs (fip, fsrp)
222      struct frame_info *fip;
223      struct frame_saved_regs *fsrp;
224 {
225   unsigned long locals;
226   unsigned char *p;
227   unsigned char op;
228   CORE_ADDR dummy_bottom;
229   CORE_ADDR adr;
230   int i;
231   
232   bzero (fsrp, sizeof *fsrp);
233   
234   /* if frame is the end of a dummy, compute where the
235    * beginning would be
236    */
237   dummy_bottom = fip->frame - 4 - NUM_REGS*4 - CALL_DUMMY_LENGTH;
238   
239   /* check if the PC is in the stack, in a dummy frame */
240   if (dummy_bottom <= fip->pc && fip->pc <= fip->frame) 
241     {
242       /* all regs were saved by push_call_dummy () */
243       adr = fip->frame - 4;
244       for (i = 0; i < NUM_REGS; i++) 
245         {
246           fsrp->regs[i] = adr;
247           adr -= 4;
248         }
249       return;
250     }
251   
252   locals = i386_get_frame_setup (get_pc_function_start (fip->pc));
253   
254   if (locals >= 0) 
255     {
256       adr = fip->frame - 4 - locals;
257       for (i = 0; i < 8; i++) 
258         {
259           op = codestream_get ();
260           if (op < 0x50 || op > 0x57)
261             break;
262           fsrp->regs[I386_REGNO_TO_SYMMETRY(op - 0x50)] = adr;
263           adr -= 4;
264         }
265     }
266   
267   fsrp->regs[PC_REGNUM] = fip->frame + 4;
268   fsrp->regs[FP_REGNUM] = fip->frame;
269 }
270
271 static long
272 i386_get_frame_setup (pc)
273 {
274   unsigned char op;
275   
276   codestream_seek (pc);
277   
278   i386_follow_jump ();
279   
280   op = codestream_get ();
281   
282   if (op == 0x58) /* popl %eax */
283     {
284       /*
285        * this function must start with
286        * 
287        *    popl %eax             0x58
288        *    xchgl %eax, (%esp)  0x87 0x04 0x24
289        * or xchgl %eax, 0(%esp) 0x87 0x44 0x24 0x00
290        *
291        * (the system 5 compiler puts out the second xchg
292        * inst, and the assembler doesn't try to optimize it,
293        * so the 'sib' form gets generated)
294        * 
295        * this sequence is used to get the address of the return
296        * buffer for a function that returns a structure
297        */
298       int pos;
299       unsigned char buf[4];
300       static unsigned char proto1[3] = { 0x87,0x04,0x24 };
301       static unsigned char proto2[4] = { 0x87,0x44,0x24,0x00 };
302       pos = codestream_tell ();
303       codestream_read (buf, 4);
304       if (bcmp (buf, proto1, 3) == 0)
305         pos += 3;
306       else if (bcmp (buf, proto2, 4) == 0)
307         pos += 4;
308       
309       codestream_seek (pos);
310       op = codestream_get (); /* update next opcode */
311     }
312   
313   if (op == 0x55)                       /* pushl %esp */
314     {
315       if (codestream_get () != 0x8b)    /* movl %esp, %ebp (2bytes) */
316         return (-1);
317       if (codestream_get () != 0xec)
318         return (-1);
319       /*
320        * check for stack adjustment 
321        *
322        *  subl $XXX, %esp
323        *
324        * note: you can't subtract a 16 bit immediate
325        * from a 32 bit reg, so we don't have to worry
326        * about a data16 prefix 
327        */
328       op = codestream_peek ();
329       if (op == 0x83)  /* subl with 8 bit immed */
330         {
331           codestream_get ();
332           if (codestream_get () != 0xec)
333             return (-1);
334           /* subl with signed byte immediate 
335            * (though it wouldn't make sense to be negative)
336            */
337           return (codestream_get());
338         }
339       else if (op == 0x81)  /* subl with 32 bit immed */
340         {
341           int locals;
342           if (codestream_get () != 0xec)
343             return (-1);
344           /* subl with 32 bit immediate */
345           codestream_read ((unsigned char *)&locals, 4);
346           return (locals);
347         } 
348       else 
349         {
350           return (0);
351         }
352     } 
353   else if (op == 0xc8) 
354     {
355       /* enter instruction: arg is 16 unsigned immed */
356       unsigned short slocals;
357       codestream_read ((unsigned char *)&slocals, 2);
358       codestream_get (); /* flush final byte of enter instruction */
359       return (slocals);
360     }
361   return (-1);
362 }
363
364 /* next instruction is a jump, move to target */
365 static
366 i386_follow_jump ()
367 {
368   int long_delta;
369   short short_delta;
370   char byte_delta;
371   int data16;
372   int pos;
373   
374   pos = codestream_tell ();
375   
376   data16 = 0;
377   if (codestream_peek () == 0x66)
378     {
379       codestream_get ();
380       data16 = 1;
381     }
382   
383   switch (codestream_get ())
384     {
385     case 0xe9:
386       /* relative jump: if data16 == 0, disp32, else disp16 */
387       if (data16)
388         {
389           codestream_read ((unsigned char *)&short_delta, 2);
390           pos += short_delta + 3; /* include size of jmp inst */
391         }
392       else
393         {
394           codestream_read ((unsigned char *)&long_delta, 4);
395           pos += long_delta + 5;
396         }
397       break;
398     case 0xeb:
399       /* relative jump, disp8 (ignore data16) */
400       codestream_read ((unsigned char *)&byte_delta, 1);
401       pos += byte_delta + 2;
402       break;
403     }
404   codestream_seek (pos + data16);
405 }
406
407 /* return pc of first real instruction */
408 /* from i386-dep.c */
409
410 i386_skip_prologue (pc)
411 {
412   unsigned char op;
413   int i;
414   
415   if (i386_get_frame_setup (pc) < 0)
416     return (pc);
417   
418   /* found valid frame setup - codestream now points to 
419    * start of push instructions for saving registers
420    */
421   
422   /* skip over register saves */
423   for (i = 0; i < 8; i++)
424     {
425       op = codestream_peek ();
426       /* break if not pushl inst */
427       if (op < 0x50 || op > 0x57) 
428         break;
429       codestream_get ();
430     }
431   
432   i386_follow_jump ();
433   
434   return (codestream_tell ());
435 }
436
437 symmetry_extract_return_value(type, regbuf, valbuf)
438      struct type *type;
439      char *regbuf;
440      char *valbuf;
441 {
442   union { 
443     double      d; 
444     int l[2]; 
445   } xd; 
446   struct minimal_symbol *msymbol;
447   float f;
448
449   if (TYPE_CODE_FLT == TYPE_CODE(type)) { 
450     msymbol = lookup_minimal_symbol ("1167_flt", (struct objfile *) NULL);
451     if (msymbol != NULL) {
452       /* found "1167_flt" means 1167, %fp2-%fp3 */ 
453       /* float & double; 19= %fp2, 20= %fp3 */
454       /* no single precision on 1167 */
455       xd.l[1] = *((int *)&regbuf[REGISTER_BYTE(19)]);
456       xd.l[0] = *((int *)&regbuf[REGISTER_BYTE(20)]);
457       switch (TYPE_LENGTH(type)) {
458       case 4:
459         f = (float) xd.d;
460         bcopy(&f, valbuf, TYPE_LENGTH(type));
461         break;
462       case 8:
463         bcopy(&xd.d, valbuf, TYPE_LENGTH(type)); 
464         break;
465       default:
466         error("Unknown floating point size");
467         break;
468       }
469     } else { 
470       /* 387 %st(0), gcc uses this */ 
471       i387_to_double(((int *)&regbuf[REGISTER_BYTE(3)]),
472                      &xd.d); 
473       switch (TYPE_LENGTH(type)) {
474       case 4:                   /* float */
475         f = (float) xd.d;
476         bcopy(&f, valbuf, 4); 
477         break;
478       case 8:                   /* double */
479         bcopy(&xd.d, valbuf, 8);
480         break;
481       default:
482         error("Unknown floating point size");
483         break;
484       }
485     }
486   } else { 
487     bcopy (regbuf, valbuf, TYPE_LENGTH (type)); 
488   }
489 }