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