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