* config/tc-hppa.c (pa_ip): Add new codes 'cc', 'cd', 'cC', 'co',
[deliverable/binutils-gdb.git] / opcodes / hppa-dis.c
CommitLineData
252b5132
RH
1/* Disassembler for the PA-RISC. Somewhat derived from sparc-pinsn.c.
2 Copyright 1989, 1990, 1992, 1993 Free Software Foundation, Inc.
3
4 Contributed by the Center for Software Science at the
5 University of Utah (pa-gdb-bugs@cs.utah.edu).
6
7This program is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2 of the License, or
10(at your option) any later version.
11
12This program is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with this program; if not, write to the Free Software
19Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
20
21#include <ansidecl.h>
22#include "sysdep.h"
23#include "dis-asm.h"
24#include "libhppa.h"
25#include "opcode/hppa.h"
26
27/* Integer register names, indexed by the numbers which appear in the
28 opcodes. */
29static const char *const reg_names[] =
30 {"flags", "r1", "rp", "r3", "r4", "r5", "r6", "r7", "r8", "r9",
31 "r10", "r11", "r12", "r13", "r14", "r15", "r16", "r17", "r18", "r19",
32 "r20", "r21", "r22", "r23", "r24", "r25", "r26", "dp", "ret0", "ret1",
33 "sp", "r31"};
34
35/* Floating point register names, indexed by the numbers which appear in the
36 opcodes. */
37static const char *const fp_reg_names[] =
38 {"fpsr", "fpe2", "fpe4", "fpe6",
39 "fr4", "fr5", "fr6", "fr7", "fr8",
40 "fr9", "fr10", "fr11", "fr12", "fr13", "fr14", "fr15",
41 "fr16", "fr17", "fr18", "fr19", "fr20", "fr21", "fr22", "fr23",
42 "fr24", "fr25", "fr26", "fr27", "fr28", "fr29", "fr30", "fr31"};
43
44typedef unsigned int CORE_ADDR;
45
46/* Get at various relevent fields of an instruction word. */
47
48#define MASK_5 0x1f
3b67cf2b 49#define MASK_10 0x3ff
252b5132
RH
50#define MASK_11 0x7ff
51#define MASK_14 0x3fff
52#define MASK_21 0x1fffff
53
54/* This macro gets bit fields using HP's numbering (MSB = 0) */
55
56#define GET_FIELD(X, FROM, TO) \
57 ((X) >> (31 - (TO)) & ((1 << ((TO) - (FROM) + 1)) - 1))
58
59/* Some of these have been converted to 2-d arrays because they
60 consume less storage this way. If the maintenance becomes a
61 problem, convert them back to const 1-d pointer arrays. */
58d0c905 62static const char *const control_reg[] = {
252b5132
RH
63 "rctr", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7",
64 "pidr1", "pidr2", "ccr", "sar", "pidr3", "pidr4",
65 "iva", "eiem", "itmr", "pcsq", "pcoq", "iir", "isr",
66 "ior", "ipsw", "eirr", "tr0", "tr1", "tr2", "tr3",
67 "tr4", "tr5", "tr6", "tr7"
68};
69
58d0c905 70static const char *const compare_cond_names[] = {
b333b6c6
JL
71 "", ",=", ",<", ",<=", ",<<", ",<<=", ",sv", ",od",
72 ",tr", ",<>", ",>=", ",>", ",>>=", ",>>", ",nsv", ",ev"
73};
58d0c905 74static const char *const compare_cond_64_names[] = {
b333b6c6
JL
75 "", ",*=", ",*<", ",*<=", ",*<<", ",*<<=", ",*sv", ",*od",
76 ",*tr", ",*<>", ",*>=", ",*>", ",*>>=", ",*>>", ",*nsv", ",*ev"
77};
58d0c905 78static const char *const cmpib_cond_64_names[] = {
b333b6c6 79 ",*<<", ",*=", ",*<", ",*<=", ",*>>=", ",*<>", ",*>=", ",*>"
252b5132 80};
58d0c905 81static const char *const add_cond_names[] = {
b333b6c6
JL
82 "", ",=", ",<", ",<=", ",nuv", ",znv", ",sv", ",od",
83 ",tr", ",<>", ",>=", ",>", ",uv", ",vnz", ",nsv", ",ev"
84};
58d0c905 85static const char *const add_cond_64_names[] = {
d1e9bd1f 86 "", ",*=", ",*<", ",*<=", ",*nuv", ",*znv", ",*sv", ",*od",
b333b6c6
JL
87 ",*tr", ",*<>", ",*>=", ",*>", ",*uv", ",*vnz", ",*nsv", ",*ev"
88};
58d0c905 89static const char *const wide_add_cond_names[] = {
b333b6c6
JL
90 "", ",=", ",<", ",<=", ",nuv", ",*=", ",*<", ",*<=",
91 ",tr", ",<>", ",>=", ",>", ",uv", ",*<>", ",*>=", ",*>"
252b5132
RH
92};
93static const char *const logical_cond_names[] = {
94 "", ",=", ",<", ",<=", 0, 0, 0, ",od",
95 ",tr", ",<>", ",>=", ",>", 0, 0, 0, ",ev"};
b333b6c6 96static const char *const logical_cond_64_names[] = {
d1e9bd1f 97 "", ",*=", ",*<", ",*<=", 0, 0, 0, ",*od",
b333b6c6 98 ",*tr", ",*<>", ",*>=", ",*>", 0, 0, 0, ",*ev"};
252b5132
RH
99static const char *const unit_cond_names[] = {
100 "", 0, ",sbz", ",shz", ",sdc", 0, ",sbc", ",shc",
101 ",tr", 0, ",nbz", ",nhz", ",ndc", 0, ",nbc", ",nhc"
102};
b333b6c6 103static const char *const unit_cond_64_names[] = {
d1e9bd1f 104 "", ",*swz", ",*sbz", ",*shz", ",*sdc", ",*swc", ",*sbc", ",*shc",
b333b6c6
JL
105 ",*tr", ",*nwz", ",*nbz", ",*nhz", ",*ndc", ",*nwc", ",*nbc", ",*nhc"
106};
58d0c905 107static const char *const shift_cond_names[] = {
252b5132
RH
108 "", ",=", ",<", ",od", ",tr", ",<>", ",>=", ",ev"
109};
58d0c905 110static const char *const shift_cond_64_names[] = {
d1e9bd1f 111 "", ",*=", ",*<", ",*od", ",*tr", ",*<>", ",*>=", ",*ev"
b333b6c6 112};
58d0c905 113static const char *const bb_cond_64_names[] = {
b333b6c6
JL
114 ",*<", ",*>="
115};
58d0c905
JL
116static const char *const index_compl_names[] = {"", ",m", ",s", ",sm"};
117static const char *const short_ldst_compl_names[] = {"", ",ma", "", ",mb"};
252b5132
RH
118static const char *const short_bytes_compl_names[] = {
119 "", ",b,m", ",e", ",e,m"
120};
121static const char *const float_format_names[] = {",sgl", ",dbl", "", ",quad"};
58d0c905 122static const char *const float_comp_names[] =
252b5132
RH
123{
124 ",false?", ",false", ",?", ",!<=>", ",=", ",=t", ",?=", ",!<>",
125 ",!?>=", ",<", ",?<", ",!>=", ",!?>", ",<=", ",?<=", ",!>",
126 ",!?<=", ",>", ",?>", ",!<=", ",!?<", ",>=", ",?>=", ",!<",
127 ",!?=", ",<>", ",!=", ",!=t", ",!?", ",<=>", ",true?", ",true"
128};
58d0c905
JL
129static const char *const signed_unsigned_names[] = {",u", ",s"};
130static const char *const mix_half_names[] = {",l", ",r"};
131static const char *const saturation_names[] = {",us", ",ss", 0, ""};
132static const char *const read_write_names[] = {",r", ",w"};
133static const char *const add_compl_names[] = { 0, "", ",l", ",tsv" };
252b5132
RH
134
135/* For a bunch of different instructions form an index into a
136 completer name table. */
137#define GET_COMPL(insn) (GET_FIELD (insn, 26, 26) | \
138 GET_FIELD (insn, 18, 18) << 1)
139
140#define GET_COND(insn) (GET_FIELD ((insn), 16, 18) + \
141 (GET_FIELD ((insn), 19, 19) ? 8 : 0))
142
143/* Utility function to print registers. Put these first, so gcc's function
144 inlining can do its stuff. */
145
146#define fputs_filtered(STR,F) (*info->fprintf_func) (info->stream, "%s", STR)
147
148static void
149fput_reg (reg, info)
150 unsigned reg;
151 disassemble_info *info;
152{
153 (*info->fprintf_func) (info->stream, reg ? reg_names[reg] : "r0");
154}
155
156static void
157fput_fp_reg (reg, info)
158 unsigned reg;
159 disassemble_info *info;
160{
161 (*info->fprintf_func) (info->stream, reg ? fp_reg_names[reg] : "fr0");
162}
163
164static void
165fput_fp_reg_r (reg, info)
166 unsigned reg;
167 disassemble_info *info;
168{
169 /* Special case floating point exception registers. */
170 if (reg < 4)
171 (*info->fprintf_func) (info->stream, "fpe%d", reg * 2 + 1);
172 else
173 (*info->fprintf_func) (info->stream, "%sR", reg ? fp_reg_names[reg]
174 : "fr0");
175}
176
177static void
178fput_creg (reg, info)
179 unsigned reg;
180 disassemble_info *info;
181{
182 (*info->fprintf_func) (info->stream, control_reg[reg]);
183}
184
185/* print constants with sign */
186
187static void
188fput_const (num, info)
189 unsigned num;
190 disassemble_info *info;
191{
192 if ((int)num < 0)
193 (*info->fprintf_func) (info->stream, "-%x", -(int)num);
194 else
195 (*info->fprintf_func) (info->stream, "%x", num);
196}
197
198/* Routines to extract various sized constants out of hppa
199 instructions. */
200
201/* extract a 3-bit space register number from a be, ble, mtsp or mfsp */
202static int
203extract_3 (word)
204 unsigned word;
205{
206 return GET_FIELD (word, 18, 18) << 2 | GET_FIELD (word, 16, 17);
207}
208
209static int
210extract_5_load (word)
211 unsigned word;
212{
213 return low_sign_extend (word >> 16 & MASK_5, 5);
214}
215
216/* extract the immediate field from a st{bhw}s instruction */
217static int
218extract_5_store (word)
219 unsigned word;
220{
221 return low_sign_extend (word & MASK_5, 5);
222}
223
224/* extract the immediate field from a break instruction */
225static unsigned
226extract_5r_store (word)
227 unsigned word;
228{
229 return (word & MASK_5);
230}
231
232/* extract the immediate field from a {sr}sm instruction */
233static unsigned
234extract_5R_store (word)
235 unsigned word;
236{
237 return (word >> 16 & MASK_5);
238}
239
3b67cf2b
JL
240/* extract the 10 bit immediate field from a {sr}sm instruction */
241static unsigned
242extract_10U_store (word)
243 unsigned word;
244{
245 return (word >> 16 & MASK_10);
246}
247
252b5132
RH
248/* extract the immediate field from a bb instruction */
249static unsigned
250extract_5Q_store (word)
251 unsigned word;
252{
253 return (word >> 21 & MASK_5);
254}
255
256/* extract an 11 bit immediate field */
257static int
258extract_11 (word)
259 unsigned word;
260{
261 return low_sign_extend (word & MASK_11, 11);
262}
263
264/* extract a 14 bit immediate field */
265static int
266extract_14 (word)
267 unsigned word;
268{
269 return low_sign_extend (word & MASK_14, 14);
270}
271
272/* extract a 21 bit constant */
273
274static int
275extract_21 (word)
276 unsigned word;
277{
278 int val;
279
280 word &= MASK_21;
281 word <<= 11;
282 val = GET_FIELD (word, 20, 20);
283 val <<= 11;
284 val |= GET_FIELD (word, 9, 19);
285 val <<= 2;
286 val |= GET_FIELD (word, 5, 6);
287 val <<= 5;
288 val |= GET_FIELD (word, 0, 4);
289 val <<= 2;
290 val |= GET_FIELD (word, 7, 8);
291 return sign_extend (val, 21) << 11;
292}
293
294/* extract a 12 bit constant from branch instructions */
295
296static int
297extract_12 (word)
298 unsigned word;
299{
300 return sign_extend (GET_FIELD (word, 19, 28) |
301 GET_FIELD (word, 29, 29) << 10 |
302 (word & 0x1) << 11, 12) << 2;
303}
304
305/* extract a 17 bit constant from branch instructions, returning the
306 19 bit signed value. */
307
308static int
309extract_17 (word)
310 unsigned word;
311{
312 return sign_extend (GET_FIELD (word, 19, 28) |
313 GET_FIELD (word, 29, 29) << 10 |
314 GET_FIELD (word, 11, 15) << 11 |
315 (word & 0x1) << 16, 17) << 2;
316}
317
b3fe7ee2
JL
318static int
319extract_22 (word)
320 unsigned word;
321{
322 return sign_extend (GET_FIELD (word, 19, 28) |
323 GET_FIELD (word, 29, 29) << 10 |
324 GET_FIELD (word, 11, 15) << 11 |
325 GET_FIELD (word, 6, 10) << 16 |
326 (word & 0x1) << 21, 22) << 2;
327}
328
252b5132
RH
329/* Print one instruction. */
330int
331print_insn_hppa (memaddr, info)
332 bfd_vma memaddr;
333 disassemble_info *info;
334{
335 bfd_byte buffer[4];
336 unsigned int insn, i;
337
338 {
339 int status =
340 (*info->read_memory_func) (memaddr, buffer, sizeof (buffer), info);
341 if (status != 0)
342 {
343 (*info->memory_error_func) (status, memaddr, info);
344 return -1;
345 }
346 }
347
348 insn = bfd_getb32 (buffer);
349
350 for (i = 0; i < NUMOPCODES; ++i)
351 {
352 const struct pa_opcode *opcode = &pa_opcodes[i];
353 if ((insn & opcode->mask) == opcode->match)
354 {
355 register const char *s;
356
357 (*info->fprintf_func) (info->stream, "%s", opcode->name);
358
46e36b17 359 if (!strchr ("cfCY?-+nHNZFIuv", opcode->args[0]))
252b5132
RH
360 (*info->fprintf_func) (info->stream, " ");
361 for (s = opcode->args; *s != '\0'; ++s)
362 {
363 switch (*s)
364 {
365 case 'x':
366 fput_reg (GET_FIELD (insn, 11, 15), info);
367 break;
1eee34f5 368 case 'a':
252b5132
RH
369 case 'b':
370 fput_reg (GET_FIELD (insn, 6, 10), info);
371 break;
372 case '^':
373 fput_creg (GET_FIELD (insn, 6, 10), info);
374 break;
252b5132
RH
375 case 't':
376 fput_reg (GET_FIELD (insn, 27, 31), info);
377 break;
a349b151
JL
378
379 /* Handle floating point registers. */
380 case 'f':
381 switch (*++s)
382 {
383 case 't':
252b5132 384 fput_fp_reg (GET_FIELD (insn, 27, 31), info);
a349b151
JL
385 break;
386 case 'T':
387 if (GET_FIELD (insn, 25, 25))
388 fput_fp_reg_r (GET_FIELD (insn, 27, 31), info);
389 else
390 fput_fp_reg (GET_FIELD (insn, 27, 31), info);
391 break;
392 case 'a':
393 if (GET_FIELD (insn, 25, 25))
394 fput_fp_reg_r (GET_FIELD (insn, 6, 10), info);
395 else
396 fput_fp_reg (GET_FIELD (insn, 6, 10), info);
397 break;
debc018d
JL
398
399 /* 'fA' will not generate a space before the regsiter
400 name. Normally that is fine. Except that it
401 causes problems with xmpyu which has no FP format
402 completer. */
403 case 'X':
404 fputs_filtered (" ", info);
405
406 /* FALLTHRU */
407
a349b151
JL
408 case 'A':
409 if (GET_FIELD (insn, 24, 24))
410 fput_fp_reg_r (GET_FIELD (insn, 6, 10), info);
411 else
412 fput_fp_reg (GET_FIELD (insn, 6, 10), info);
413
414 break;
415 case 'b':
416 if (GET_FIELD (insn, 25, 25))
417 fput_fp_reg_r (GET_FIELD (insn, 11, 15), info);
418 else
419 fput_fp_reg (GET_FIELD (insn, 11, 15), info);
420 break;
421 case 'B':
422 if (GET_FIELD (insn, 19, 19))
423 fput_fp_reg_r (GET_FIELD (insn, 11, 15), info);
424 else
425 fput_fp_reg (GET_FIELD (insn, 11, 15), info);
426 break;
427 case 'C':
428 {
429 int reg = GET_FIELD (insn, 21, 22);
430 reg |= GET_FIELD (insn, 16, 18) << 2;
431 if (GET_FIELD (insn, 23, 23) != 0)
432 fput_fp_reg_r (reg, info);
433 else
434 fput_fp_reg (reg, info);
435 break;
436 }
437 case 'i':
438 {
439 int reg = GET_FIELD (insn, 6, 10);
252b5132 440
a349b151
JL
441 reg |= (GET_FIELD (insn, 26, 26) << 4);
442 fput_fp_reg (reg, info);
443 break;
444 }
445 case 'j':
446 {
447 int reg = GET_FIELD (insn, 11, 15);
252b5132 448
a349b151
JL
449 reg |= (GET_FIELD (insn, 26, 26) << 4);
450 fput_fp_reg (reg, info);
451 break;
452 }
453 case 'k':
454 {
455 int reg = GET_FIELD (insn, 27, 31);
252b5132 456
a349b151
JL
457 reg |= (GET_FIELD (insn, 26, 26) << 4);
458 fput_fp_reg (reg, info);
459 break;
460 }
461 case 'l':
462 {
463 int reg = GET_FIELD (insn, 21, 25);
252b5132 464
a349b151
JL
465 reg |= (GET_FIELD (insn, 26, 26) << 4);
466 fput_fp_reg (reg, info);
467 break;
468 }
469 case 'm':
470 {
471 int reg = GET_FIELD (insn, 16, 20);
472
473 reg |= (GET_FIELD (insn, 26, 26) << 4);
474 fput_fp_reg (reg, info);
475 break;
476 }
f322c2c2
JL
477 case 'e':
478 if (GET_FIELD (insn, 25, 25))
479 fput_fp_reg_r (GET_FIELD (insn, 11, 15), info);
480 else
481 fput_fp_reg (GET_FIELD (insn, 11, 15), info);
482 break;
483
a349b151 484 }
2f87f883 485 break;
252b5132 486
252b5132
RH
487 case '5':
488 fput_const (extract_5_load (insn), info);
489 break;
490 case 's':
491 (*info->fprintf_func) (info->stream,
492 "sr%d", GET_FIELD (insn, 16, 17));
493 break;
b333b6c6 494
252b5132
RH
495 case 'S':
496 (*info->fprintf_func) (info->stream, "sr%d", extract_3 (insn));
497 break;
3281117a
JL
498
499 /* Handle completers. */
252b5132 500 case 'c':
3281117a
JL
501 switch (*++s)
502 {
503 case 'x':
504 (*info->fprintf_func) (info->stream, "%s ",
505 index_compl_names[GET_COMPL (insn)]);
506 break;
507 case 'm':
508 (*info->fprintf_func) (info->stream, "%s ",
509 short_ldst_compl_names[GET_COMPL (insn)]);
510 break;
511 case 's':
512 (*info->fprintf_func) (info->stream, "%s ",
513 short_bytes_compl_names[GET_COMPL (insn)]);
514 break;
1fb72ed1
JL
515 case 'g':
516 (*info->fprintf_func) (info->stream, ",gate");
517 case 'p':
518 (*info->fprintf_func) (info->stream, ",l,push");
519 break;
520 case 'P':
521 (*info->fprintf_func) (info->stream, ",pop");
522 break;
523 case 'l':
3b67cf2b
JL
524 case 'L':
525 (*info->fprintf_func) (info->stream, ",l");
526 break;
527 case 'w':
528 (*info->fprintf_func) (info->stream, "%s ",
529 read_write_names[GET_FIELD (insn, 25, 25)]);
530 break;
531 case 'W':
532 (*info->fprintf_func) (info->stream, ",w");
533 break;
534 case 'r':
535 if (GET_FIELD (insn, 23, 26) == 5)
536 (*info->fprintf_func) (info->stream, ",r");
537 break;
3281117a
JL
538 case 'Z':
539 if (GET_FIELD (insn, 26, 26))
540 (*info->fprintf_func) (info->stream, ",m ");
541 else
542 (*info->fprintf_func) (info->stream, " ");
543 break;
3b67cf2b
JL
544 case 'i':
545 if (GET_FIELD (insn, 25, 25))
546 (*info->fprintf_func) (info->stream, ",i");
547 break;
af10de82
JL
548 case 'z':
549 if (!GET_FIELD (insn, 21, 21))
550 (*info->fprintf_func) (info->stream, ",z");
551 break;
3b67cf2b
JL
552 case 'a':
553 (*info->fprintf_func)
554 (info->stream, "%s", add_compl_names[GET_FIELD
555 (insn, 20, 21)]);
556 break;
557 case 'Y':
558 (*info->fprintf_func)
559 (info->stream, ",dc%s", add_compl_names[GET_FIELD
560 (insn, 20, 21)]);
561 break;
562 case 'y':
563 (*info->fprintf_func)
564 (info->stream, ",c%s", add_compl_names[GET_FIELD
565 (insn, 20, 21)]);
566 break;
567 case 'v':
568 if (GET_FIELD (insn, 20, 20))
569 (*info->fprintf_func) (info->stream, ",tsv");
570 break;
571 case 't':
572 (*info->fprintf_func) (info->stream, ",tc");
573 if (GET_FIELD (insn, 20, 20))
574 (*info->fprintf_func) (info->stream, ",tsv");
575 break;
576 case 'B':
577 (*info->fprintf_func) (info->stream, ",db");
578 if (GET_FIELD (insn, 20, 20))
579 (*info->fprintf_func) (info->stream, ",tsv");
580 break;
581 case 'b':
582 (*info->fprintf_func) (info->stream, ",b");
583 if (GET_FIELD (insn, 20, 20))
584 (*info->fprintf_func) (info->stream, ",tsv");
585 break;
586 case 'T':
587 if (GET_FIELD (insn, 25, 25))
588 (*info->fprintf_func) (info->stream, ",tc");
589 break;
1eee34f5
JL
590 case 'S':
591 /* EXTRD/W has a following condition. */
592 if (*(s + 1) == '?')
593 (*info->fprintf_func)
594 (info->stream, "%s", signed_unsigned_names[GET_FIELD
595 (insn, 21, 21)]);
596 else
597 (*info->fprintf_func)
598 (info->stream, "%s ", signed_unsigned_names[GET_FIELD
599 (insn, 21, 21)]);
600 break;
601 case 'h':
602 (*info->fprintf_func)
603 (info->stream, "%s", mix_half_names[GET_FIELD
604 (insn, 17, 17)]);
605 break;
606 case 'H':
607 (*info->fprintf_func)
608 (info->stream, "%s", saturation_names[GET_FIELD
609 (insn, 24, 25)]);
610 break;
611 case '*':
612 (*info->fprintf_func)
613 (info->stream, ",%d%d%d%d ",
614 GET_FIELD (insn, 17, 18), GET_FIELD (insn, 20, 21),
615 GET_FIELD (insn, 22, 23), GET_FIELD (insn, 24, 25));
616 break;
9c1faa82
JL
617
618 case 'q':
619 {
620 int m, a;
621
622 m = GET_FIELD (insn, 28, 28);
623 a = GET_FIELD (insn, 29, 29);
624
625 if (m && !a)
626 fputs_filtered (",ma ", info);
627 else if (m && a)
628 fputs_filtered (",mb ", info);
629 else
630 fputs_filtered (" ", info);
631 break;
632 }
633
634 case 'J':
635 {
636 int opcode = GET_FIELD (insn, 0, 5);
637
638 if (opcode == 0x16 || opcode == 0x1e)
639 {
640 if (GET_FIELD (insn, 29, 29) == 0)
641 fputs_filtered (",ma ", info);
642 else
643 fputs_filtered (",mb ", info);
644 }
645 else
646 fputs_filtered (" ", info);
647 break;
648 }
649
650 case 'c':
651 {
652 int opcode = GET_FIELD (insn, 0, 5);
653
654 if (opcode == 0x13 || opcode == 0x1b)
655 {
656 if (GET_FIELD (insn, 18, 18) == 1)
657 fputs_filtered (",mb ", info);
658 else
659 fputs_filtered (",ma ", info);
660 }
661 else if (opcode == 0x17 || opcode == 0x1f)
662 {
663 if (GET_FIELD (insn, 31, 31) == 1)
664 fputs_filtered (",ma ", info);
665 else
666 fputs_filtered (",mb ", info);
667 }
668 else
669 fputs_filtered (" ", info);
670
671 break;
672 }
3281117a 673 }
252b5132 674 break;
feb12992
JL
675
676 /* Handle conditions. */
252b5132 677 case '?':
feb12992
JL
678 {
679 s++;
680 switch (*s)
681 {
682 case 'f':
683 (*info->fprintf_func) (info->stream, "%s ",
684 float_comp_names[GET_FIELD
685 (insn, 27, 31)]);
686 break;
687
688 /* these four conditions are for the set of instructions
689 which distinguish true/false conditions by opcode
690 rather than by the 'f' bit (sigh): comb, comib,
691 addb, addib */
692 case 't':
a349b151 693 fputs_filtered (compare_cond_names[GET_FIELD (insn, 16, 18)],
feb12992
JL
694 info);
695 break;
b333b6c6
JL
696 case 'T':
697 fputs_filtered (compare_cond_names[GET_FIELD (insn, 16, 18)
698 + 8], info);
699 break;
700 case 'r':
701 fputs_filtered (compare_cond_64_names[GET_FIELD (insn, 16, 18)],
702 info);
703 break;
704 case 'R':
705 fputs_filtered (compare_cond_64_names[GET_FIELD (insn, 16, 18)
706 + 8], info);
707 break;
708 case 'Q':
709 fputs_filtered (cmpib_cond_64_names[GET_FIELD (insn, 16, 18)],
710 info);
711 break;
feb12992 712 case 'n':
a349b151 713 fputs_filtered (compare_cond_names[GET_FIELD (insn, 16, 18)
feb12992
JL
714 + GET_FIELD (insn, 4, 4) * 8], info);
715 break;
716 case '@':
717 fputs_filtered (add_cond_names[GET_FIELD (insn, 16, 18)
718 + GET_FIELD (insn, 4, 4) * 8], info);
719 break;
720 case 's':
721 (*info->fprintf_func) (info->stream, "%s ",
722 compare_cond_names[GET_COND (insn)]);
723 break;
b333b6c6
JL
724 case 'S':
725 (*info->fprintf_func) (info->stream, "%s ",
726 compare_cond_64_names[GET_COND (insn)]);
727 break;
feb12992
JL
728 case 'a':
729 (*info->fprintf_func) (info->stream, "%s ",
730 add_cond_names[GET_COND (insn)]);
731 break;
b333b6c6
JL
732 case 'A':
733 (*info->fprintf_func) (info->stream, "%s ",
734 add_cond_64_names[GET_COND (insn)]);
735 break;
feb12992
JL
736 case 'd':
737 (*info->fprintf_func) (info->stream, "%s",
a349b151 738 add_cond_names[GET_FIELD (insn, 16, 18)]);
feb12992 739 break;
a349b151 740
b333b6c6
JL
741 case 'D':
742 (*info->fprintf_func) (info->stream, "%s",
a349b151
JL
743 add_cond_names[GET_FIELD (insn, 16, 18)
744 + 8]);
b333b6c6
JL
745 break;
746 case 'w':
a349b151 747 (*info->fprintf_func)
b333b6c6
JL
748 (info->stream, "%s",
749 wide_add_cond_names[GET_FIELD (insn, 16, 18)]);
750 break;
751
752 case 'W':
a349b151 753 (*info->fprintf_func)
b333b6c6
JL
754 (info->stream, "%s",
755 wide_add_cond_names[GET_FIELD (insn, 16, 18) + 8]);
756 break;
feb12992
JL
757
758 case 'l':
759 (*info->fprintf_func) (info->stream, "%s ",
760 logical_cond_names[GET_COND (insn)]);
761 break;
b333b6c6
JL
762 case 'L':
763 (*info->fprintf_func) (info->stream, "%s ",
764 logical_cond_64_names[GET_COND (insn)]);
765 break;
feb12992
JL
766 case 'u':
767 (*info->fprintf_func) (info->stream, "%s ",
768 unit_cond_names[GET_COND (insn)]);
769 break;
b333b6c6
JL
770 case 'U':
771 (*info->fprintf_func) (info->stream, "%s ",
772 unit_cond_64_names[GET_COND (insn)]);
773 break;
feb12992
JL
774 case 'y':
775 case 'x':
776 case 'b':
777 (*info->fprintf_func)
778 (info->stream, "%s",
779 shift_cond_names[GET_FIELD (insn, 16, 18)]);
780
781 /* If the next character in args is 'n', it will handle
782 putting out the space. */
783 if (s[1] != 'n')
784 (*info->fprintf_func) (info->stream, " ");
785 break;
b333b6c6 786 case 'X':
e46def7b 787 (*info->fprintf_func) (info->stream, "%s ",
b333b6c6
JL
788 shift_cond_64_names[GET_FIELD (insn, 16, 18)]);
789 break;
790 case 'B':
791 (*info->fprintf_func)
792 (info->stream, "%s",
793 bb_cond_64_names[GET_FIELD (insn, 16, 16)]);
feb12992 794
b333b6c6
JL
795 /* If the next character in args is 'n', it will handle
796 putting out the space. */
797 if (s[1] != 'n')
798 (*info->fprintf_func) (info->stream, " ");
799 break;
feb12992
JL
800 }
801 break;
802 }
252b5132 803
252b5132
RH
804 case 'V':
805 fput_const (extract_5_store (insn), info);
806 break;
807 case 'r':
808 fput_const (extract_5r_store (insn), info);
809 break;
810 case 'R':
811 fput_const (extract_5R_store (insn), info);
812 break;
3b67cf2b
JL
813 case 'U':
814 fput_const (extract_10U_store (insn), info);
815 break;
252b5132
RH
816 case 'Q':
817 fput_const (extract_5Q_store (insn), info);
818 break;
819 case 'i':
820 fput_const (extract_11 (insn), info);
821 break;
822 case 'j':
823 fput_const (extract_14 (insn), info);
824 break;
825 case 'k':
826 fput_const (extract_21 (insn), info);
827 break;
828 case 'n':
829 if (insn & 0x2)
830 (*info->fprintf_func) (info->stream, ",n ");
831 else
832 (*info->fprintf_func) (info->stream, " ");
833 break;
834 case 'N':
835 if ((insn & 0x20) && s[1])
836 (*info->fprintf_func) (info->stream, ",n ");
837 else if (insn & 0x20)
838 (*info->fprintf_func) (info->stream, ",n");
839 else if (s[1])
840 (*info->fprintf_func) (info->stream, " ");
841 break;
842 case 'w':
843 (*info->print_address_func) (memaddr + 8 + extract_12 (insn),
844 info);
845 break;
846 case 'W':
847 /* 17 bit PC-relative branch. */
848 (*info->print_address_func) ((memaddr + 8
849 + extract_17 (insn)),
850 info);
851 break;
852 case 'z':
853 /* 17 bit displacement. This is an offset from a register
854 so it gets disasssembled as just a number, not any sort
855 of address. */
856 fput_const (extract_17 (insn), info);
857 break;
d1e9bd1f
JL
858
859 case 'Z':
860 /* addil %r1 implicit output. */
2beaab59 861 (*info->fprintf_func) (info->stream, "%%r1");
d1e9bd1f 862 break;
1fb72ed1
JL
863
864 case 'Y':
865 /* be,l %sr0,%r31 implicit output. */
866 (*info->fprintf_func) (info->stream, "%%sr0,%%r31");
867 break;
d1e9bd1f 868
46424e05
JL
869 case '.':
870 (*info->fprintf_func) (info->stream, "%d",
871 GET_FIELD (insn, 24, 25));
872 break;
3b67cf2b
JL
873 case '*':
874 (*info->fprintf_func) (info->stream, "%d",
875 GET_FIELD (insn, 22, 25));
876 break;
b7d6d485 877 case '!':
2beaab59 878 (*info->fprintf_func) (info->stream, "%%sar");
b7d6d485 879 break;
252b5132
RH
880 case 'p':
881 (*info->fprintf_func) (info->stream, "%d",
882 31 - GET_FIELD (insn, 22, 26));
883 break;
46424e05
JL
884 case '~':
885 {
886 int num;
887 num = GET_FIELD (insn, 20, 20) << 5;
888 num |= GET_FIELD (insn, 22, 26);
889 (*info->fprintf_func) (info->stream, "%d", 63 - num);
890 break;
891 }
252b5132
RH
892 case 'P':
893 (*info->fprintf_func) (info->stream, "%d",
894 GET_FIELD (insn, 22, 26));
895 break;
af10de82
JL
896 case 'q':
897 {
898 int num;
899 num = GET_FIELD (insn, 20, 20) << 5;
900 num |= GET_FIELD (insn, 22, 26);
901 (*info->fprintf_func) (info->stream, "%d", num);
902 break;
903 }
252b5132
RH
904 case 'T':
905 (*info->fprintf_func) (info->stream, "%d",
906 32 - GET_FIELD (insn, 27, 31));
907 break;
af10de82
JL
908 case '%':
909 {
910 int num;
911 num = (GET_FIELD (insn, 23, 23) + 1) * 32;
912 num -= GET_FIELD (insn, 27, 31);
913 (*info->fprintf_func) (info->stream, "%d", num);
914 break;
915 }
916 case '|':
917 {
918 int num;
919 num = (GET_FIELD (insn, 19, 19) + 1) * 32;
920 num -= GET_FIELD (insn, 27, 31);
921 (*info->fprintf_func) (info->stream, "%d", num);
922 break;
923 }
46424e05
JL
924 case '$':
925 fput_const (GET_FIELD (insn, 20, 28), info);
926 break;
252b5132
RH
927 case 'A':
928 fput_const (GET_FIELD (insn, 6, 18), info);
929 break;
252b5132
RH
930 case 'D':
931 fput_const (GET_FIELD (insn, 6, 31), info);
932 break;
a349b151 933 case 'v':
252b5132
RH
934 (*info->fprintf_func) (info->stream, ",%d", GET_FIELD (insn, 23, 25));
935 break;
936 case 'O':
937 fput_const ((GET_FIELD (insn, 6,20) << 5 |
938 GET_FIELD (insn, 27, 31)), info);
939 break;
940 case 'o':
941 fput_const (GET_FIELD (insn, 6, 20), info);
942 break;
252b5132
RH
943 case '2':
944 fput_const ((GET_FIELD (insn, 6, 22) << 5 |
945 GET_FIELD (insn, 27, 31)), info);
946 break;
947 case '1':
948 fput_const ((GET_FIELD (insn, 11, 20) << 5 |
949 GET_FIELD (insn, 27, 31)), info);
950 break;
951 case '0':
952 fput_const ((GET_FIELD (insn, 16, 20) << 5 |
953 GET_FIELD (insn, 27, 31)), info);
954 break;
955 case 'u':
956 (*info->fprintf_func) (info->stream, ",%d", GET_FIELD (insn, 23, 25));
957 break;
958 case 'F':
959 /* if no destination completer and not before a completer
960 for fcmp, need a space here */
4f312591 961 if (s[1] == 'G' || s[1] == '?')
252b5132
RH
962 fputs_filtered (float_format_names[GET_FIELD (insn, 19, 20)],
963 info);
964 else
965 (*info->fprintf_func) (info->stream, "%s ",
966 float_format_names[GET_FIELD
967 (insn, 19, 20)]);
968 break;
969 case 'G':
970 (*info->fprintf_func) (info->stream, "%s ",
971 float_format_names[GET_FIELD (insn,
972 17, 18)]);
973 break;
974 case 'H':
975 if (GET_FIELD (insn, 26, 26) == 1)
976 (*info->fprintf_func) (info->stream, "%s ",
977 float_format_names[0]);
978 else
979 (*info->fprintf_func) (info->stream, "%s ",
980 float_format_names[1]);
981 break;
982 case 'I':
983 /* if no destination completer and not before a completer
984 for fcmp, need a space here */
4f312591 985 if (s[1] == '?')
252b5132
RH
986 fputs_filtered (float_format_names[GET_FIELD (insn, 20, 20)],
987 info);
988 else
989 (*info->fprintf_func) (info->stream, "%s ",
990 float_format_names[GET_FIELD
991 (insn, 20, 20)]);
992 break;
eb32eb44
JL
993
994 case 'J':
995 fput_const (extract_14 (insn), info);
996 break;
997
d758242c
JL
998 case '#':
999 {
1000 int sign = GET_FIELD (insn, 31, 31);
1001 int imm10 = GET_FIELD (insn, 18, 27);
1002 int disp;
1003
1004 if (sign)
1005 disp = (-1 << 10) | imm10;
1006 else
1007 disp = imm10;
1008
1009 disp <<= 3;
1010 fput_const (disp, info);
1011 break;
1012 }
eb32eb44 1013 case 'K':
d758242c
JL
1014 case 'd':
1015 {
1016 int sign = GET_FIELD (insn, 31, 31);
1017 int imm11 = GET_FIELD (insn, 18, 28);
1018 int disp;
1019
1020 if (sign)
1021 disp = (-1 << 11) | imm11;
1022 else
1023 disp = imm11;
1024
1025 disp <<= 2;
1026 fput_const (disp, info);
1027 break;
1028 }
1029
838c65f0
JL
1030 /* ?!? FIXME */
1031 case '_':
1032 case '{':
1033 fputs_filtered ("Disassembler botch.\n", info);
1034 break;
1035
1036 case 'm':
1037 {
1038 int y = GET_FIELD (insn, 16, 18);
1039
1040 if (y != 1)
1041 fput_const ((y ^ 1) - 1, info);
1042 }
1043 break;
1044
1045 case 'h':
1046 {
1047 int cbit;
1048
1049 cbit = GET_FIELD (insn, 16, 18);
1050
1051 if (cbit > 0)
1052 (*info->fprintf_func) (info->stream, ",%d", cbit - 1);
1053 break;
1054 }
1055
1056 case '=':
1057 {
1058 int cond = GET_FIELD (insn, 27, 31);
1059
1060 if (cond == 0)
1061 fputs_filtered (" ", info);
1062 else if (cond == 1)
1063 fputs_filtered ("acc ", info);
1064 else if (cond == 2)
1065 fputs_filtered ("rej ", info);
1066 else if (cond == 5)
1067 fputs_filtered ("acc8 ", info);
1068 else if (cond == 6)
1069 fputs_filtered ("rej8 ", info);
1070 else if (cond == 9)
1071 fputs_filtered ("acc6 ", info);
1072 else if (cond == 13)
1073 fputs_filtered ("acc4 ", info);
1074 else if (cond == 17)
1075 fputs_filtered ("acc2 ", info);
1076 break;
1077 }
1078
3610d131
JL
1079 case 'X':
1080 (*info->print_address_func) ((memaddr + 8
1081 + extract_22 (insn)),
1082 info);
1083 break;
2784abe5
JL
1084 case 'L':
1085 fputs_filtered (",%r2", info);
1086 break;
252b5132
RH
1087 default:
1088 (*info->fprintf_func) (info->stream, "%c", *s);
1089 break;
1090 }
1091 }
1092 return sizeof(insn);
1093 }
1094 }
1095 (*info->fprintf_func) (info->stream, "#%8x", insn);
1096 return sizeof(insn);
1097}
This page took 0.082549 seconds and 4 git commands to generate.