]> Git Repo - binutils.git/blob - gdb/rs6000-pinsn.c
ansi name abuse changes
[binutils.git] / gdb / rs6000-pinsn.c
1 /* Print rs6000 instructions for objdump.
2    This file is part of the binutils.
3 */
4
5
6 #include <stdio.h>
7 #include "defs.h"
8 #include "rs6k-opcode.h"
9
10
11 /* Print the rs6k instruction at address MEMADDR in debugged memory,
12    on STREAM.  Returns length of the instruction, in bytes.  */
13
14 int
15 print_insn (memaddr, stream)
16   CORE_ADDR memaddr;
17   FILE *stream;
18 {
19         int  pop, eop;                  /* primary and extended opcodes */
20         int  min, max;
21         int  best = -1;                 /* found best opcode index      */
22         int  oldbest = -1;
23         unsigned int the_insn;
24
25         read_memory (memaddr, &the_insn, sizeof (the_insn));
26         pop = (unsigned)(the_insn >> 26);
27         eop = ((the_insn) >> 1) & 0x3ff;
28         min = 0, max = NOPCODES-1;
29
30         while (min < max) {
31           best = (min + max) / 2;
32
33           /* see if we are running in loops */
34           if (best == oldbest)
35             goto not_found;
36           oldbest = best;
37
38           if (pop < rs6k_ops [best].p_opcode)
39             max = best;
40
41           else if (pop > rs6k_ops [best].p_opcode)
42             min = best;
43
44           else {
45             /* opcode matched, check extended opcode. */
46
47             if (rs6k_ops [best].e_opcode == -1) {
48               /* there is no valid extended opcode, what we've got is
49                  just fine. */
50               goto insn_found;
51             }
52
53             else if (eop < rs6k_ops [best].e_opcode) {
54
55               while (pop == rs6k_ops [best].p_opcode) {
56                 if (eop == rs6k_ops [best].e_opcode)    /* found it! */
57                   goto insn_found;
58                 --best;
59               }
60               goto not_found;
61             }
62
63             else if (eop > rs6k_ops [best].e_opcode) {
64
65               while (pop == rs6k_ops [best].p_opcode) {
66                 if (eop == rs6k_ops [best].e_opcode)    /* found it! */
67                   goto insn_found;
68                 ++best;
69               }
70               goto not_found;
71             }
72
73             else /*  eop == rs6k_ops [best].e_opcode */
74               goto insn_found;
75           }
76         }       
77
78         best = min;
79         if (pop == rs6k_ops [best].p_opcode &&
80            (rs6k_ops [best].e_opcode == -1 || rs6k_ops [best].e_opcode == eop))
81             goto insn_found;
82
83         else
84           goto not_found;
85
86
87 insn_found:
88         print_operator (stream, memaddr, the_insn, best);
89         return 4;
90
91 not_found:
92         fprintf (stream, "0x%08x", the_insn);
93         return 4;
94 }
95
96
97
98 /* condition code names */
99 static char *cond_code [] = {
100   "lt", "gt", "eq", "so", "ge", "le", "ne", "ns", "nl", "ng", "z", "nz" };
101
102
103 print_operator (stream, memaddr, insn_word, insn_no)
104 FILE    *stream;
105 long    memaddr;
106 long    insn_word;
107 int     insn_no;
108 {
109   char buf [BUFSIZ];
110   char *qq = buf;
111   char *pp = rs6k_ops[insn_no].opr_ext;
112   int tmp;
113   int nocomma = 0;                      /* true if no comma needed */
114
115   *qq = '\0';
116   if (pp) {
117     while (*pp) {
118
119       switch ( *pp ) {
120         case '.':
121           if (insn_word & 0x1)
122            *qq++ = '.';
123           break;
124
125         case 'l':
126           if (insn_word & 0x1)
127            *qq++ = 'l';
128           break;
129
130         case 't':
131           if ((insn_word & 0x03e00000) == 0x01800000)
132            *qq++ = 't';
133           break;
134
135         case 'f':
136           if ((insn_word & 0x03e00000) == 0x00800000)
137            *qq++ = 'f';
138           break;
139
140         case 'a':
141           if (insn_word & 0x2)
142            *qq++ = 'a';
143           break;
144
145         case 'o':
146           if (insn_word & 0x4000)
147            *qq++ = 'o';
148           break;
149
150         case '1':               /* exception #1 for bb/bc ambiguity */
151           tmp = (insn_word >> 21) & 0x1f;       /* extract BO   */
152           if (tmp != 0xc && tmp != 0x4) {
153             /* you can't use `bb' now. switch to `bc' */
154             *(qq-1) = 'c';
155             ++insn_no;
156             pp = rs6k_ops[insn_no].opr_ext;
157             continue;
158           }
159           break;
160
161         default:
162           abort ();
163       }
164       ++pp;
165     }
166   }
167
168   /* tab between orerator and operand */
169   *qq++ = '\t';
170
171   /* parse the operand now. */
172   pp = rs6k_ops[insn_no].oprnd_format;
173
174   while (1) {
175     switch (*pp) {
176       case TO   :
177         sprintf (qq, "%d", (insn_word >> 21) & 0x1f);
178         break;
179
180       case RT   :
181       case RS   :
182         sprintf (qq, "r%d", (insn_word >> 21) & 0x1f);
183         break;
184
185       case LI   :
186         tmp  = (insn_word >> 16) & 0x1f;
187         if (tmp > 11) {
188           fprintf (stderr, "Internal error: unknown cond code: 0x%x\n", insn_word);
189           tmp = 0;
190         }
191         sprintf (qq, "%s", cond_code [tmp]);
192         break;
193
194 #if 0
195       case A2   :
196         tmp = (insn_word >> 2) & 0x3fff;
197         if (tmp & 0x2000)
198          tmp -= 0x4000;
199         sprintf (qq, "0x%x", tmp * 4 + memaddr);
200         break;
201 #endif
202       case A2   :
203       case TA14 :
204         tmp = (insn_word & 0xfffc);
205         if (tmp & 0x8000)               /* fix sign extension   */
206           tmp -= 0x10000;
207
208         if ((insn_word & 0x2) == 0)     /* if AA not set        */
209           tmp += memaddr;
210
211         sprintf (qq, "0x%x", tmp);
212         break;
213
214       case TA24 :
215         tmp = insn_word & 0x03fffffc;
216         if (tmp & 0x2000000)
217           tmp -= 0x4000000;
218         
219         if ((insn_word & 0x2) == 0)             /* if no AA bit set */
220           tmp += memaddr;
221
222         sprintf (qq, "0x%x", tmp);
223         break;
224
225       case LEV  :                       /* for svc only */
226         if (insn_word & 0x2) {          /* SA is set    */
227           nocomma = 1;
228           *qq = '\0';
229         }
230         else
231           sprintf (qq, "%d", (insn_word >> 5) & 0x7f);
232         break;
233
234       case FL1  :                       /* for svc only */
235         if (insn_word & 0x2) {          /* SA is set    */
236           nocomma = 1;
237           *qq = '\0';
238         }
239         else
240           sprintf (qq, "%d", (insn_word >> 12) & 0xf);
241         break;
242
243       case FL2  :                       /* for svc only */
244         nocomma = 0;
245         if (insn_word & 0x2)            /* SA is set    */
246           sprintf (qq, "%d", (insn_word >> 2) & 0x3fff);
247         else
248           sprintf (qq, "%d", (insn_word >> 2) & 0x7);
249         break;
250
251       case RA   :
252         if (nocomma) {
253           sprintf (qq, "r%d)", (insn_word >> 16) & 0x1f);
254           nocomma = 0;
255         }
256         else
257           sprintf (qq, "r%d", (insn_word >> 16) & 0x1f);
258         break;
259
260       case RB   :
261         sprintf (qq, "r%d", (insn_word >> 11) & 0x1f);
262         break;
263
264       case SI   :
265         tmp = insn_word & 0xffff;
266         if (tmp & 0x8000)
267           tmp -= 0x10000;
268         sprintf (qq, "%d", tmp);
269         break;
270
271       case UI   :
272         sprintf (qq, "%d", insn_word & 0xffff);
273         break;
274
275       case BF   :
276         sprintf (qq, "%d", (insn_word >> 23) & 0x7);
277         break;
278
279       case BFA  :
280         sprintf (qq, "%d", (insn_word >> 18) & 0x7);
281         break;
282
283       case BT   :
284         sprintf (qq, "%d", (insn_word >> 21) & 0x1f);
285         break;
286
287       case BA   :
288         sprintf (qq, "%d", (insn_word >> 16) & 0x1f);
289         break;
290
291       case BB   :
292         sprintf (qq, "%d", (insn_word >> 11) & 0x1f);
293         break;
294
295       case BO   :
296         sprintf (qq, "%d", (insn_word >> 21) & 0x1f);
297         break;
298
299       case BI   :
300         sprintf (qq, "%d", (insn_word >> 16) & 0x1f);
301         break;
302
303       case SH   :
304         sprintf (qq, "%d", (insn_word >> 11) & 0x1f);
305         break;
306
307       case MB   :
308         sprintf (qq, "0x%x", (insn_word >> 6) & 0x1f);
309         break;
310
311       case ME   :
312         sprintf (qq, "0x%x", (insn_word >> 1) & 0x1f);
313         break;
314
315       case SPR  :
316         sprintf (qq, "%d", (insn_word >> 16) & 0x1f);
317         break;
318
319       case DIS  :
320         nocomma = 1;
321         tmp = insn_word & 0xffff;
322         if (tmp & 0x8000)
323           tmp -= 0x10000;
324         sprintf (qq, "%d(", tmp);
325         break;
326
327       case FXM  :
328         sprintf (qq, "0x%x", (insn_word >> 12) & 0xff);
329         break;
330
331       case FRT  :
332       case FRS  :
333         sprintf (qq, "f%d", (insn_word >> 21) & 0x1f);
334         break;
335
336       case FRA  :
337         sprintf (qq, "f%d", (insn_word >> 16) & 0x1f);
338         break;
339
340       case FRB  :
341         sprintf (qq, "f%d", (insn_word >> 11) & 0x1f);
342         break;
343
344       case FRC  :
345         sprintf (qq, "f%d", (insn_word >> 6) & 0x1f);
346         break;
347
348       case FLM  :
349         sprintf (qq, "0x%x", (insn_word >> 17) & 0xff);
350         break;
351
352       case NB   :
353         sprintf (qq, "%d", (insn_word >> 11) & 0x1f);
354         break;
355
356       case I    :
357         sprintf (qq, "%d", (insn_word >> 12) & 0xf);
358         break;
359
360       default   :
361         sprintf (qq, "Unknown operand format identifier????");
362         abort ();
363     }
364     while (*qq) ++qq;
365     ++pp;
366
367     if (*pp == '\0')
368       break;
369     else if (!nocomma)
370       *qq++ = ',';
371   }
372   *qq = '\0';
373     
374   fprintf (stream, "0x%08x\t%s%s", 
375         insn_word, rs6k_ops[insn_no].operator, buf);
376 }
377
This page took 0.046524 seconds and 4 git commands to generate.