* stabsread.c (rs6000_builtin_type): Make logical types be
[external/binutils.git] / gdb / ns32k-pinsn.c
1 /* Print National Semiconductor 32000 instructions for GDB, the GNU debugger.
2    Copyright 1986, 1988, 1991, 1992 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 #include "defs.h"
21 #include "symtab.h"
22 #include "ns32k-opcode.h"
23 #include "gdbcore.h"
24
25 /* 32000 instructions are never longer than this.  */
26 #define MAXLEN 62
27
28 /* Number of elements in the opcode table.  */
29 #define NOPCODES (sizeof notstrs / sizeof notstrs[0])
30
31 #define NEXT_IS_ADDR    '|'
32
33 /*
34  * extract "count" bits starting "offset" bits
35  * into buffer
36  */
37
38 int
39 bit_extract (buffer, offset, count)
40      char *buffer;
41      int offset;
42      int count;
43 {
44   int result;
45   int mask;
46   int bit;
47
48   buffer += offset >> 3;
49   offset &= 7;
50   bit = 1;
51   result = 0;
52   while (count--) 
53     {
54       if ((*buffer & (1 << offset)))
55         result |= bit;
56       if (++offset == 8)
57         {
58           offset = 0;
59           buffer++;
60         }
61       bit <<= 1;
62     }
63   return result;
64 }
65
66 float
67 fbit_extract (buffer, offset, count)
68 {
69   union {
70     int ival;
71     float fval;
72   } foo;
73
74   foo.ival = bit_extract (buffer, offset, 32);
75   return foo.fval;
76 }
77
78 double
79 dbit_extract (buffer, offset, count)
80 {
81   union {
82     struct {int low, high; } ival;
83     double dval;
84   } foo;
85
86   foo.ival.low = bit_extract (buffer, offset, 32);
87   foo.ival.high = bit_extract (buffer, offset+32, 32);
88   return foo.dval;
89 }
90
91 sign_extend (value, bits)
92 {
93   value = value & ((1 << bits) - 1);
94   return (value & (1 << (bits-1))
95           ? value | (~((1 << bits) - 1))
96           : value);
97 }
98
99 flip_bytes (ptr, count)
100      char *ptr;
101      int count;
102 {
103   char tmp;
104
105   while (count > 0)
106     {
107       tmp = *ptr;
108       ptr[0] = ptr[count-1];
109       ptr[count-1] = tmp;
110       ptr++;
111       count -= 2;
112     }
113 }
114 \f
115 /* Given a character C, does it represent a general addressing mode?  */
116 #define Is_gen(c) \
117   ((c) == 'F' || (c) == 'L' || (c) == 'B' \
118    || (c) == 'W' || (c) == 'D' || (c) == 'A')
119
120 /* Adressing modes.  */
121 #define Adrmod_index_byte 0x1c
122 #define Adrmod_index_word 0x1d
123 #define Adrmod_index_doubleword 0x1e
124 #define Adrmod_index_quadword 0x1f
125
126 /* Is MODE an indexed addressing mode?  */
127 #define Adrmod_is_index(mode) \
128   (mode == Adrmod_index_byte \
129    || mode == Adrmod_index_word \
130    || mode == Adrmod_index_doubleword \
131    || mode == Adrmod_index_quadword)
132
133 \f
134 /* Print the 32000 instruction at address MEMADDR in debugged memory,
135    on STREAM.  Returns length of the instruction, in bytes.  */
136
137 int
138 print_insn (memaddr, stream)
139      CORE_ADDR memaddr;
140      FILE *stream;
141 {
142   unsigned char buffer[MAXLEN];
143   register int i;
144   register unsigned char *p;
145   register char *d;
146   unsigned short first_word;
147   int gen, disp;
148   int ioffset;          /* bits into instruction */
149   int aoffset;          /* bits into arguments */
150   char arg_bufs[MAX_ARGS+1][ARG_LEN];
151   int argnum;
152   int maxarg;
153
154   read_memory (memaddr, buffer, MAXLEN);
155
156   first_word = *(unsigned short *) buffer;
157   for (i = 0; i < NOPCODES; i++)
158     if ((first_word & ((1 << notstrs[i].detail.obits) - 1))
159         == notstrs[i].detail.code)
160       break;
161
162   /* Handle undefined instructions.  */
163   if (i == NOPCODES)
164     {
165       fprintf (stream, "0%o", buffer[0]);
166       return 1;
167     }
168
169   fprintf (stream, "%s", notstrs[i].name);
170
171   ioffset = notstrs[i].detail.ibits;
172   aoffset = notstrs[i].detail.ibits;
173   d = notstrs[i].detail.args;
174
175   if (*d)
176     {
177       /* Offset in bits of the first thing beyond each index byte.
178          Element 0 is for operand A and element 1 is for operand B.
179          The rest are irrelevant, but we put them here so we don't
180          index outside the array.  */
181       int index_offset[MAX_ARGS];
182
183       /* 0 for operand A, 1 for operand B, greater for other args.  */
184       int whicharg = 0;
185       
186       fputc ('\t', stream);
187
188       maxarg = 0;
189
190       /* First we have to find and keep track of the index bytes,
191          if we are using scaled indexed addressing mode, since the index
192          bytes occur right after the basic instruction, not as part
193          of the addressing extension.  */
194       if (Is_gen(d[1]))
195         {
196           int addr_mode = bit_extract (buffer, ioffset - 5, 5);
197
198           if (Adrmod_is_index (addr_mode))
199             {
200               aoffset += 8;
201               index_offset[0] = aoffset;
202             }
203         }
204       if (d[2] && Is_gen(d[3]))
205         {
206           int addr_mode = bit_extract (buffer, ioffset - 10, 5);
207
208           if (Adrmod_is_index (addr_mode))
209             {
210               aoffset += 8;
211               index_offset[1] = aoffset;
212             }
213         }
214
215       while (*d)
216         {
217           argnum = *d - '1';
218           d++;
219           if (argnum > maxarg && argnum < MAX_ARGS)
220             maxarg = argnum;
221           ioffset = print_insn_arg (*d, ioffset, &aoffset, buffer,
222                                     memaddr, arg_bufs[argnum],
223                                     index_offset[whicharg]);
224           d++;
225           whicharg++;
226         }
227       for (argnum = 0; argnum <= maxarg; argnum++)
228         {
229           CORE_ADDR addr;
230           char *ch, *index ();
231           for (ch = arg_bufs[argnum]; *ch;)
232             {
233               if (*ch == NEXT_IS_ADDR)
234                 {
235                   ++ch;
236                   addr = atoi (ch);
237                   print_address (addr, stream);
238                   while (*ch && *ch != NEXT_IS_ADDR)
239                     ++ch;
240                   if (*ch)
241                     ++ch;
242                 }
243               else
244                 putc (*ch++, stream);
245             }
246           if (argnum < maxarg)
247             fprintf (stream, ", ");
248         }
249     }
250   return aoffset / 8;
251 }
252
253 /* Print an instruction operand of category given by d.  IOFFSET is
254    the bit position below which small (<1 byte) parts of the operand can
255    be found (usually in the basic instruction, but for indexed
256    addressing it can be in the index byte).  AOFFSETP is a pointer to the
257    bit position of the addressing extension.  BUFFER contains the
258    instruction.  ADDR is where BUFFER was read from.  Put the disassembled
259    version of the operand in RESULT.  INDEX_OFFSET is the bit position
260    of the index byte (it contains garbage if this operand is not a
261    general operand using scaled indexed addressing mode).  */
262
263 print_insn_arg (d, ioffset, aoffsetp, buffer, addr, result, index_offset)
264      char d;
265      int ioffset, *aoffsetp;
266      char *buffer;
267      CORE_ADDR addr;
268      char *result;
269      int index_offset;
270 {
271   int addr_mode;
272   float Fvalue;
273   double Lvalue;
274   int Ivalue;
275   int disp1, disp2;
276   int index;
277
278   switch (d)
279     {
280     case 'F':
281     case 'L':
282     case 'B':
283     case 'W':
284     case 'D':
285     case 'A':
286       addr_mode = bit_extract (buffer, ioffset-5, 5);
287       ioffset -= 5;
288       switch (addr_mode)
289         {
290         case 0x0: case 0x1: case 0x2: case 0x3:
291         case 0x4: case 0x5: case 0x6: case 0x7:
292           switch (d)
293             {
294             case 'F':
295             case 'L':
296               sprintf (result, "f%d", addr_mode);
297               break;
298             default:
299               sprintf (result, "r%d", addr_mode);
300             }
301           break;
302         case 0x8: case 0x9: case 0xa: case 0xb:
303         case 0xc: case 0xd: case 0xe: case 0xf:
304           disp1 = get_displacement (buffer, aoffsetp);
305           sprintf (result, "%d(r%d)", disp1, addr_mode & 7);
306           break;
307         case 0x10:
308         case 0x11:
309         case 0x12:
310           disp1 = get_displacement (buffer, aoffsetp);
311           disp2 = get_displacement (buffer, aoffsetp);
312           sprintf (result, "%d(%d(%s))", disp2, disp1,
313                    addr_mode==0x10?"fp":addr_mode==0x11?"sp":"sb");
314           break;
315         case 0x13:
316           sprintf (result, "reserved");
317           break;
318         case 0x14:
319           switch (d)
320             {
321             case 'B':
322               Ivalue = bit_extract (buffer, *aoffsetp, 8);
323               Ivalue = sign_extend (Ivalue, 8);
324               *aoffsetp += 8;
325               sprintf (result, "$%d", Ivalue);
326               break;
327             case 'W':
328               Ivalue = bit_extract (buffer, *aoffsetp, 16);
329               flip_bytes (&Ivalue, 2);
330               *aoffsetp += 16;
331               Ivalue = sign_extend (Ivalue, 16);
332               sprintf (result, "$%d", Ivalue);
333               break;
334             case 'D':
335               Ivalue = bit_extract (buffer, *aoffsetp, 32);
336               flip_bytes (&Ivalue, 4);
337               *aoffsetp += 32;
338               sprintf (result, "$%d", Ivalue);
339               break;
340             case 'A':
341               Ivalue = bit_extract (buffer, *aoffsetp, 32);
342               flip_bytes (&Ivalue, 4);
343               *aoffsetp += 32;
344               sprintf (result, "$|%d|", Ivalue);
345               break;
346             case 'F':
347               Fvalue = fbit_extract (buffer, *aoffsetp, 32);
348               flip_bytes (&Fvalue, 4);
349               *aoffsetp += 32;
350               sprintf (result, "$%g", Fvalue);
351               break;
352             case 'L':
353               Lvalue = dbit_extract (buffer, *aoffsetp, 64);
354               flip_bytes (&Lvalue, 8);
355               *aoffsetp += 64;
356               sprintf (result, "$%g", Lvalue);
357               break;
358             }
359           break;
360         case 0x15:
361           disp1 = get_displacement (buffer, aoffsetp);
362           sprintf (result, "@|%d|", disp1);
363           break;
364         case 0x16:
365           disp1 = get_displacement (buffer, aoffsetp);
366           disp2 = get_displacement (buffer, aoffsetp);
367           sprintf (result, "EXT(%d) + %d", disp1, disp2);
368           break;
369         case 0x17:
370           sprintf (result, "tos");
371           break;
372         case 0x18:
373           disp1 = get_displacement (buffer, aoffsetp);
374           sprintf (result, "%d(fp)", disp1);
375           break;
376         case 0x19:
377           disp1 = get_displacement (buffer, aoffsetp);
378           sprintf (result, "%d(sp)", disp1);
379           break;
380         case 0x1a:
381           disp1 = get_displacement (buffer, aoffsetp);
382           sprintf (result, "%d(sb)", disp1);
383           break;
384         case 0x1b:
385           disp1 = get_displacement (buffer, aoffsetp);
386           sprintf (result, "|%d|", addr + disp1);
387           break;
388         case 0x1c:
389         case 0x1d:
390         case 0x1e:
391         case 0x1f:
392           index = bit_extract (buffer, index_offset - 8, 3);
393           print_insn_arg (d, index_offset, aoffsetp, buffer, addr,
394                           result, 0);
395           {
396             static char *ind[] = {"b", "w", "d", "q"};
397             char *off;
398
399             off = result + strlen (result);
400             sprintf (off, "[r%d:%s]", index,
401                      ind[addr_mode & 3]);
402           }
403           break;
404         }
405       break;
406     case 'q':
407       Ivalue = bit_extract (buffer, ioffset-4, 4);
408       Ivalue = sign_extend (Ivalue, 4);
409       sprintf (result, "%d", Ivalue);
410       ioffset -= 4;
411       break;
412     case 'r':
413       Ivalue = bit_extract (buffer, ioffset-3, 3);
414       sprintf (result, "r%d", Ivalue&7);
415       ioffset -= 3;
416       break;
417     case 'd':
418       sprintf (result, "%d", get_displacement (buffer, aoffsetp));
419       break;
420     case 'p':
421       sprintf (result, "%c%d%c", NEXT_IS_ADDR,
422                addr + get_displacement (buffer, aoffsetp),
423                NEXT_IS_ADDR);
424       break;
425     case 'i':
426       Ivalue = bit_extract (buffer, *aoffsetp, 8);
427       *aoffsetp += 8;
428       sprintf (result, "0x%x", Ivalue);
429       break;
430     }
431   return ioffset;
432 }
433
434 get_displacement (buffer, aoffsetp)
435      char *buffer;
436      int *aoffsetp;
437 {
438   int Ivalue;
439
440   Ivalue = bit_extract (buffer, *aoffsetp, 8);
441   switch (Ivalue & 0xc0)
442     {
443     case 0x00:
444     case 0x40:
445       Ivalue = sign_extend (Ivalue, 7);
446       *aoffsetp += 8;
447       break;
448     case 0x80:
449       Ivalue = bit_extract (buffer, *aoffsetp, 16);
450       flip_bytes (&Ivalue, 2);
451       Ivalue = sign_extend (Ivalue, 14);
452       *aoffsetp += 16;
453       break;
454     case 0xc0:
455       Ivalue = bit_extract (buffer, *aoffsetp, 32);
456       flip_bytes (&Ivalue, 4);
457       Ivalue = sign_extend (Ivalue, 30);
458       *aoffsetp += 32;
459       break;
460     }
461   return Ivalue;
462 }
463 \f
464 /* Return the number of locals in the current frame given a pc
465    pointing to the enter instruction.  This is used in the macro
466    FRAME_FIND_SAVED_REGS.  */
467
468 ns32k_localcount (enter_pc)
469      CORE_ADDR enter_pc;
470 {
471   unsigned char localtype;
472   int localcount;
473
474   localtype = read_memory_integer (enter_pc+2, 1);
475   if ((localtype & 0x80) == 0)
476     localcount = localtype;
477   else if ((localtype & 0xc0) == 0x80)
478     localcount = (((localtype & 0x3f) << 8)
479                   | (read_memory_integer (enter_pc+3, 1) & 0xff));
480   else
481     localcount = (((localtype & 0x3f) << 24)
482                   | ((read_memory_integer (enter_pc+3, 1) & 0xff) << 16)
483                   | ((read_memory_integer (enter_pc+4, 1) & 0xff) << 8 )
484                   | (read_memory_integer (enter_pc+5, 1) & 0xff));
485   return localcount;
486 }
487
488 /*
489  * Get the address of the enter opcode for the function
490  * containing PC, if there is an enter for the function,
491  * and if the pc is between the enter and exit.
492  * Returns positive address if pc is between enter/exit,
493  * 1 if pc before enter or after exit, 0 otherwise.
494  */
495
496 CORE_ADDR
497 ns32k_get_enter_addr (pc)
498      CORE_ADDR pc;
499 {
500   CORE_ADDR enter_addr;
501   unsigned char op;
502
503   if (ABOUT_TO_RETURN (pc))
504     return 1;           /* after exit */
505
506   enter_addr = get_pc_function_start (pc);
507
508   if (pc == enter_addr) 
509     return 1;           /* before enter */
510
511   op = read_memory_integer (enter_addr, 1);
512
513   if (op != 0x82)
514     return 0;           /* function has no enter/exit */
515
516   return enter_addr;    /* pc is between enter and exit */
517 }