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