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