]> Git Repo - binutils.git/blob - gdb/sparc-pinsn.c
ansi name abuse changes
[binutils.git] / gdb / sparc-pinsn.c
1 /* Disassembler for the sparc.
2    Copyright (C) 1989 Free Software Foundation, Inc.
3
4 This file is part of GDB, the GNU disassembler.
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 "sparc-opcode.h"
26 #include "gdbcore.h"
27 #include "string.h"
28 #include "target.h"
29
30 extern void qsort ();
31
32
33 extern char *reg_names[];
34 #define freg_names      (&reg_names[4 * 8])
35
36 union sparc_insn
37   {
38     unsigned long int code;
39     struct
40       {
41         unsigned int OP:2;
42 #define op      ldst.OP
43         unsigned int RD:5;
44 #define rd      ldst.RD
45         unsigned int op3:6;
46         unsigned int RS1:5;
47 #define rs1     ldst.RS1
48         unsigned int i:1;
49         unsigned int ASI:8;
50 #define asi     ldst.ASI
51         unsigned int RS2:5;
52 #define rs2     ldst.RS2
53 #define shcnt   rs2
54       } ldst;
55     struct
56       {
57         unsigned int OP:2, RD:5, op3:6, RS1:5, i:1;
58         unsigned int IMM13:13;
59 #define imm13   IMM13.IMM13
60       } IMM13;
61     struct
62       {
63         unsigned int OP:2;
64         unsigned int a:1;
65         unsigned int cond:4;
66         unsigned int op2:3;
67         unsigned int DISP22:22;
68 #define disp22  branch.DISP22
69       } branch;
70 #define imm22   disp22
71     struct
72       {
73         unsigned int OP:2;
74         unsigned int DISP30:30;
75 #define disp30  call.DISP30
76       } call;
77   };
78
79 /* Nonzero if INSN is the opcode for a delayed branch.  */
80 static int
81 is_delayed_branch (insn)
82      union sparc_insn insn;
83 {
84   unsigned int i;
85
86   for (i = 0; i < NUMOPCODES; ++i)
87     {
88       const struct sparc_opcode *opcode = &sparc_opcodes[i];
89       if ((opcode->match & insn.code) == opcode->match
90           && (opcode->lose & insn.code) == 0)
91         return (opcode->flags & F_DELAYED);
92     }
93   return 0;
94 }
95
96 static int opcodes_sorted = 0;
97
98 /* Print one instruction from MEMADDR on STREAM.  */
99 int
100 print_insn (memaddr, stream)
101      CORE_ADDR memaddr;
102      FILE *stream;
103 {
104   union sparc_insn insn;
105
106   register unsigned int i;
107
108   if (!opcodes_sorted)
109     {
110       static int compare_opcodes ();
111       qsort ((char *) sparc_opcodes, NUMOPCODES,
112              sizeof (sparc_opcodes[0]), compare_opcodes);
113       opcodes_sorted = 1;
114     }
115
116   read_memory (memaddr, &insn, sizeof (insn));
117
118   for (i = 0; i < NUMOPCODES; ++i)
119     {
120       const struct sparc_opcode *opcode = &sparc_opcodes[i];
121       if ((opcode->match & insn.code) == opcode->match
122           && (opcode->lose & insn.code) == 0)
123         {
124           /* Nonzero means that we have found an instruction which has
125              the effect of adding or or'ing the imm13 field to rs1.  */
126           int imm_added_to_rs1 = 0;
127
128           /* Nonzero means that we have found a plus sign in the args
129              field of the opcode table.  */
130           int found_plus = 0;
131           
132           /* Do we have an 'or' instruction where rs1 is the same
133              as rsd, and which has the i bit set?  */
134           if (opcode->match == 0x80102000
135               && insn.rs1 == insn.rd)
136             imm_added_to_rs1 = 1;
137
138           if (insn.rs1 != insn.rd
139               && strchr (opcode->args, 'r') != 0)
140               /* Can't do simple format if source and dest are different.  */
141               continue;
142
143           fputs_filtered (opcode->name, stream);
144
145           {
146             register const char *s;
147
148             if (opcode->args[0] != ',')
149               fputs_filtered (" ", stream);
150             for (s = opcode->args; *s != '\0'; ++s)
151               {
152                 if (*s == ',')
153                   {
154                     fputs_filtered (",", stream);
155                     ++s;
156                     if (*s == 'a')
157                       {
158                         fputs_filtered ("a", stream);
159                         ++s;
160                       }
161                     fputs_filtered (" ", stream);
162                   }
163
164                 switch (*s)
165                   {
166                   case '+':
167                     found_plus = 1;
168
169                     /* note fall-through */
170                   default:
171                     fprintf_filtered (stream, "%c", *s);
172                     break;
173
174                   case '#':
175                     fputs_filtered ("0", stream);
176                     break;
177
178 #define reg(n)  fprintf_filtered (stream, "%%%s", reg_names[n])
179                   case '1':
180                   case 'r':
181                     reg (insn.rs1);
182                     break;
183
184                   case '2':
185                     reg (insn.rs2);
186                     break;
187
188                   case 'd':
189                     reg (insn.rd);
190                     break;
191 #undef  reg
192
193 #define freg(n) fprintf_filtered (stream, "%%%s", freg_names[n])
194                   case 'e':
195                     freg (insn.rs1);
196                     break;
197
198                   case 'f':
199                     freg (insn.rs2);
200                     break;
201
202                   case 'g':
203                     freg (insn.rd);
204                     break;
205 #undef  freg
206
207 #define creg(n) fprintf_filtered (stream, "%%c%u", (unsigned int) (n))
208                   case 'b':
209                     creg (insn.rs1);
210                     break;
211
212                   case 'c':
213                     creg (insn.rs2);
214                     break;
215
216                   case 'D':
217                     creg (insn.rd);
218                     break;
219 #undef  creg
220
221                   case 'h':
222                     fprintf_filtered (stream, "%%hi(%#x)",
223                                       (int) insn.imm22 << 10);
224                     break;
225
226                   case 'i':
227                     {
228                       /* We cannot trust the compiler to sign-extend
229                          when extracting the bitfield, hence the shifts.  */
230                       int imm = ((int) insn.imm13 << 19) >> 19;
231
232                       /* Check to see whether we have a 1+i, and take
233                          note of that fact.
234
235                          Note: because of the way we sort the table,
236                          we will be matching 1+i rather than i+1,
237                          so it is OK to assume that i is after +,
238                          not before it.  */
239                       if (found_plus)
240                         imm_added_to_rs1 = 1;
241                       
242                       if (imm <= 9)
243                         fprintf_filtered (stream, "%d", imm);
244                       else
245                         fprintf_filtered (stream, "%#x", imm);
246                     }
247                     break;
248
249                   case 'L':
250                     print_address ((CORE_ADDR) memaddr + insn.disp30 * 4,
251                                    stream);
252                     break;
253
254                   case 'l':
255                     if ((insn.code >> 22) == 0)
256                       /* Special case for `unimp'.  Don't try to turn
257                          it's operand into a function offset.  */
258                       fprintf_filtered (stream, "%#x",
259                                         (int) (((int) insn.disp22 << 10) >> 10));
260                     else
261                       /* We cannot trust the compiler to sign-extend
262                          when extracting the bitfield, hence the shifts.  */
263                       print_address ((CORE_ADDR)
264                                      (memaddr
265                                       + (((int) insn.disp22 << 10) >> 10) * 4),
266                                      stream);
267                     break;
268
269                   case 'A':
270                     fprintf_filtered (stream, "(%d)", (int) insn.asi);
271                     break;
272
273                   case 'C':
274                     fputs_filtered ("%csr", stream);
275                     break;
276
277                   case 'F':
278                     fputs_filtered ("%fsr", stream);
279                     break;
280
281                   case 'p':
282                     fputs_filtered ("%psr", stream);
283                     break;
284
285                   case 'q':
286                     fputs_filtered ("%fq", stream);
287                     break;
288
289                   case 'Q':
290                     fputs_filtered ("%cq", stream);
291                     break;
292
293                   case 't':
294                     fputs_filtered ("%tbr", stream);
295                     break;
296
297                   case 'w':
298                     fputs_filtered ("%wim", stream);
299                     break;
300
301                   case 'y':
302                     fputs_filtered ("%y", stream);
303                     break;
304                   }
305               }
306           }
307
308           /* If we are adding or or'ing something to rs1, then
309              check to see whether the previous instruction was
310              a sethi to the same register as in the sethi.
311              If so, attempt to print the result of the add or
312              or (in this context add and or do the same thing)
313              and its symbolic value.  */
314           if (imm_added_to_rs1)
315             {
316               union sparc_insn prev_insn;
317               int errcode;
318
319               errcode = target_read_memory (memaddr - 4,
320                                      (char *)&prev_insn, sizeof (prev_insn));
321
322               if (errcode == 0)
323                 {
324                   /* If it is a delayed branch, we need to look at the
325                      instruction before the delayed branch.  This handles
326                      sequences such as
327
328                      sethi %o1, %hi(_foo), %o1
329                      call _printf
330                      or %o1, %lo(_foo), %o1
331                      */
332
333                   if (is_delayed_branch (prev_insn))
334                     errcode = target_read_memory
335                       (memaddr - 8, (char *)&prev_insn, sizeof (prev_insn));
336                 }
337
338               /* If there was a problem reading memory, then assume
339                  the previous instruction was not sethi.  */
340               if (errcode == 0)
341                 {
342                   /* Is it sethi to the same register?  */
343                   if ((prev_insn.code & 0xc1c00000) == 0x01000000
344                       && prev_insn.rd == insn.rs1)
345                     {
346                       fprintf_filtered (stream, "\t! ");
347                       /* We cannot trust the compiler to sign-extend
348                          when extracting the bitfield, hence the shifts.  */
349                       print_address (((int) prev_insn.imm22 << 10)
350                                      | (insn.imm13 << 19) >> 19, stream);
351                     }
352                 }
353             }
354
355           return sizeof (insn);
356         }
357     }
358
359   printf_filtered ("%#8x", insn.code);
360   return sizeof (insn);
361 }
362
363
364 /* Compare opcodes A and B.  */
365
366 static int
367 compare_opcodes (a, b)
368      char *a, *b;
369 {
370   struct sparc_opcode *op0 = (struct sparc_opcode *) a;
371   struct sparc_opcode *op1 = (struct sparc_opcode *) b;
372   unsigned long int match0 = op0->match, match1 = op1->match;
373   unsigned long int lose0 = op0->lose, lose1 = op1->lose;
374   register unsigned int i;
375
376   /* If a bit is set in both match and lose, there is something
377      wrong with the opcode table.  */
378   if (match0 & lose0)
379     {
380       fprintf (stderr, "Internal error:  bad sparc-opcode.h: \"%s\", %#.8lx, %#.8lx\n",
381                op0->name, match0, lose0);
382       op0->lose &= ~op0->match;
383       lose0 = op0->lose;
384     }
385
386   if (match1 & lose1)
387     {
388       fprintf (stderr, "Internal error: bad sparc-opcode.h: \"%s\", %#.8lx, %#.8lx\n",
389                op1->name, match1, lose1);
390       op1->lose &= ~op1->match;
391       lose1 = op1->lose;
392     }
393
394   /* Because the bits that are variable in one opcode are constant in
395      another, it is important to order the opcodes in the right order.  */
396   for (i = 0; i < 32; ++i)
397     {
398       unsigned long int x = 1 << i;
399       int x0 = (match0 & x) != 0;
400       int x1 = (match1 & x) != 0;
401
402       if (x0 != x1)
403         return x1 - x0;
404     }
405
406   for (i = 0; i < 32; ++i)
407     {
408       unsigned long int x = 1 << i;
409       int x0 = (lose0 & x) != 0;
410       int x1 = (lose1 & x) != 0;
411
412       if (x0 != x1)
413         return x1 - x0;
414     }
415
416   /* They are functionally equal.  So as long as the opcode table is
417      valid, we can put whichever one first we want, on aesthetic grounds.  */
418
419   /* Our first aesthetic ground is that aliases defer to real insns.  */
420   {
421     int alias_diff = (op0->flags & F_ALIAS) - (op1->flags & F_ALIAS);
422     if (alias_diff != 0)
423       /* Put the one that isn't an alias first.  */
424       return alias_diff;
425   }
426
427   /* Except for the above aliases, two "identical" instructions had
428      better have the same opcode.  This is a sanity check on the table.  */
429   if (0 != strcmp (op0->name, op1->name))
430       fprintf (stderr, "Internal error: bad sparc-opcode.h: \"%s\" == \"%s\"\n",
431         op0->name, op1->name);
432
433   /* Fewer arguments are preferred.  */
434   {
435     int length_diff = strlen (op0->args) - strlen (op1->args);
436     if (length_diff != 0)
437       /* Put the one with fewer arguments first.  */
438       return length_diff;
439   }
440
441   /* Put 1+i before i+1.  */
442   {
443     char *p0 = (char *) strchr(op0->args, '+');
444     char *p1 = (char *) strchr(op1->args, '+');
445
446     if (p0 && p1)
447       {
448         /* There is a plus in both operands.  Note that a plus
449            sign cannot be the first character in args,
450            so the following [-1]'s are valid.  */
451         if (p0[-1] == 'i' && p1[1] == 'i')
452           /* op0 is i+1 and op1 is 1+i, so op1 goes first.  */
453           return 1;
454         if (p0[1] == 'i' && p1[-1] == 'i')
455           /* op0 is 1+i and op1 is i+1, so op0 goes first.  */
456           return -1;
457       }
458   }
459
460   /* They are, as far as we can tell, identical.
461      Since qsort may have rearranged the table partially, there is
462      no way to tell which one was first in the opcode table as
463      written, so just say there are equal.  */
464   return 0;
465 }
This page took 0.050409 seconds and 4 git commands to generate.