Copyright 1989, 1990, 1992, 1993, 1994, 1995, 1998, 1999, 2000, 2001, 2003,
2005, 2007 Free Software Foundation, Inc.
Contributed by the Center for Software Science at the
University of Utah (pa-gdb-bugs@cs.utah.edu).
This file is part of the GNU opcodes library.
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
It is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
MA 02110-1301, USA. */
#include "sysdep.h"
#include "dis-asm.h"
#include "libhppa.h"
#include "opcode/hppa.h"
opcodes. */
static const char *const reg_names[] =
{
"flags", "r1", "rp", "r3", "r4", "r5", "r6", "r7", "r8", "r9",
"r10", "r11", "r12", "r13", "r14", "r15", "r16", "r17", "r18", "r19",
"r20", "r21", "r22", "r23", "r24", "r25", "r26", "dp", "ret0", "ret1",
"sp", "r31"
};
opcodes. */
static const char *const fp_reg_names[] =
{
"fpsr", "fpe2", "fpe4", "fpe6",
"fr4", "fr5", "fr6", "fr7", "fr8",
"fr9", "fr10", "fr11", "fr12", "fr13", "fr14", "fr15",
"fr16", "fr17", "fr18", "fr19", "fr20", "fr21", "fr22", "fr23",
"fr24", "fr25", "fr26", "fr27", "fr28", "fr29", "fr30", "fr31"
};
typedef unsigned int CORE_ADDR;
#define MASK_5 0x1f
#define MASK_10 0x3ff
#define MASK_11 0x7ff
#define MASK_14 0x3fff
#define MASK_16 0xffff
#define MASK_21 0x1fffff
#define GET_FIELD(X, FROM, TO) \
((X) >> (31 - (TO)) & ((1 << ((TO) - (FROM) + 1)) - 1))
#define GET_BIT(X, WHICH) \
GET_FIELD (X, WHICH, WHICH)
consume less storage this way. If the maintenance becomes a
problem, convert them back to const 1-d pointer arrays. */
static const char *const control_reg[] =
{
"rctr", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7",
"pidr1", "pidr2", "ccr", "sar", "pidr3", "pidr4",
"iva", "eiem", "itmr", "pcsq", "pcoq", "iir", "isr",
"ior", "ipsw", "eirr", "tr0", "tr1", "tr2", "tr3",
"tr4", "tr5", "tr6", "tr7"
};
static const char *const compare_cond_names[] =
{
"", ",=", ",<", ",<=", ",<<", ",<<=", ",sv", ",od",
",tr", ",<>", ",>=", ",>", ",>>=", ",>>", ",nsv", ",ev"
};
static const char *const compare_cond_64_names[] =
{
"", ",*=", ",*<", ",*<=", ",*<<", ",*<<=", ",*sv", ",*od",
",*tr", ",*<>", ",*>=", ",*>", ",*>>=", ",*>>", ",*nsv", ",*ev"
};
static const char *const cmpib_cond_64_names[] =
{
",*<<", ",*=", ",*<", ",*<=", ",*>>=", ",*<>", ",*>=", ",*>"
};
static const char *const add_cond_names[] =
{
"", ",=", ",<", ",<=", ",nuv", ",znv", ",sv", ",od",
",tr", ",<>", ",>=", ",>", ",uv", ",vnz", ",nsv", ",ev"
};
static const char *const add_cond_64_names[] =
{
"", ",*=", ",*<", ",*<=", ",*nuv", ",*znv", ",*sv", ",*od",
",*tr", ",*<>", ",*>=", ",*>", ",*uv", ",*vnz", ",*nsv", ",*ev"
};
static const char *const wide_add_cond_names[] =
{
"", ",=", ",<", ",<=", ",nuv", ",*=", ",*<", ",*<=",
",tr", ",<>", ",>=", ",>", ",uv", ",*<>", ",*>=", ",*>"
};
static const char *const logical_cond_names[] =
{
"", ",=", ",<", ",<=", 0, 0, 0, ",od",
",tr", ",<>", ",>=", ",>", 0, 0, 0, ",ev"};
static const char *const logical_cond_64_names[] =
{
"", ",*=", ",*<", ",*<=", 0, 0, 0, ",*od",
",*tr", ",*<>", ",*>=", ",*>", 0, 0, 0, ",*ev"};
static const char *const unit_cond_names[] =
{
"", ",swz", ",sbz", ",shz", ",sdc", ",swc", ",sbc", ",shc",
",tr", ",nwz", ",nbz", ",nhz", ",ndc", ",nwc", ",nbc", ",nhc"
};
static const char *const unit_cond_64_names[] =
{
"", ",*swz", ",*sbz", ",*shz", ",*sdc", ",*swc", ",*sbc", ",*shc",
",*tr", ",*nwz", ",*nbz", ",*nhz", ",*ndc", ",*nwc", ",*nbc", ",*nhc"
};
static const char *const shift_cond_names[] =
{
"", ",=", ",<", ",od", ",tr", ",<>", ",>=", ",ev"
};
static const char *const shift_cond_64_names[] =
{
"", ",*=", ",*<", ",*od", ",*tr", ",*<>", ",*>=", ",*ev"
};
static const char *const bb_cond_64_names[] =
{
",*<", ",*>="
};
static const char *const index_compl_names[] = {"", ",m", ",s", ",sm"};
static const char *const short_ldst_compl_names[] = {"", ",ma", "", ",mb"};
static const char *const short_bytes_compl_names[] =
{
"", ",b,m", ",e", ",e,m"
};
static const char *const float_format_names[] = {",sgl", ",dbl", "", ",quad"};
static const char *const fcnv_fixed_names[] = {",w", ",dw", "", ",qw"};
static const char *const fcnv_ufixed_names[] = {",uw", ",udw", "", ",uqw"};
static const char *const float_comp_names[] =
{
",false?", ",false", ",?", ",!<=>", ",=", ",=t", ",?=", ",!<>",
",!?>=", ",<", ",?<", ",!>=", ",!?>", ",<=", ",?<=", ",!>",
",!?<=", ",>", ",?>", ",!<=", ",!?<", ",>=", ",?>=", ",!<",
",!?=", ",<>", ",!=", ",!=t", ",!?", ",<=>", ",true?", ",true"
};
static const char *const signed_unsigned_names[] = {",u", ",s"};
static const char *const mix_half_names[] = {",l", ",r"};
static const char *const saturation_names[] = {",us", ",ss", 0, ""};
static const char *const read_write_names[] = {",r", ",w"};
static const char *const add_compl_names[] = { 0, "", ",l", ",tsv" };
completer name table. */
#define GET_COMPL(insn) (GET_FIELD (insn, 26, 26) | \
GET_FIELD (insn, 18, 18) << 1)
#define GET_COND(insn) (GET_FIELD ((insn), 16, 18) + \
(GET_FIELD ((insn), 19, 19) ? 8 : 0))
inlining can do its stuff. */
#define fputs_filtered(STR,F) (*info->fprintf_func) (info->stream, "%s", STR)
static void
fput_reg (unsigned reg, disassemble_info *info)
{
(*info->fprintf_func) (info->stream, reg ? reg_names[reg] : "r0");
}
static void
fput_fp_reg (unsigned reg, disassemble_info *info)
{
(*info->fprintf_func) (info->stream, reg ? fp_reg_names[reg] : "fr0");
}
static void
fput_fp_reg_r (unsigned reg, disassemble_info *info)
{
if (reg < 4)
(*info->fprintf_func) (info->stream, "fpe%d", reg * 2 + 1);
else
(*info->fprintf_func) (info->stream, "%sR",
reg ? fp_reg_names[reg] : "fr0");
}
static void
fput_creg (unsigned reg, disassemble_info *info)
{
(*info->fprintf_func) (info->stream, control_reg[reg]);
}
static void
fput_const (unsigned num, disassemble_info *info)
{
if ((int) num < 0)
(*info->fprintf_func) (info->stream, "-%x", - (int) num);
else
(*info->fprintf_func) (info->stream, "%x", num);
}
instructions. */
static int
extract_3 (unsigned word)
{
return GET_FIELD (word, 18, 18) << 2 | GET_FIELD (word, 16, 17);
}
static int
extract_5_load (unsigned word)
{
return low_sign_extend (word >> 16 & MASK_5, 5);
}
static int
extract_5_store (unsigned word)
{
return low_sign_extend (word & MASK_5, 5);
}
static unsigned
extract_5r_store (unsigned word)
{
return (word & MASK_5);
}
static unsigned
extract_5R_store (unsigned word)
{
return (word >> 16 & MASK_5);
}
static unsigned
extract_10U_store (unsigned word)
{
return (word >> 16 & MASK_10);
}
static unsigned
extract_5Q_store (unsigned word)
{
return (word >> 21 & MASK_5);
}
static int
extract_11 (unsigned word)
{
return low_sign_extend (word & MASK_11, 11);
}
static int
extract_14 (unsigned word)
{
return low_sign_extend (word & MASK_14, 14);
}
static int
extract_16 (unsigned word)
{
int m15, m0, m1;
m0 = GET_BIT (word, 16);
m1 = GET_BIT (word, 17);
m15 = GET_BIT (word, 31);
word = (word >> 1) & 0x1fff;
word = word | (m15 << 15) | ((m15 ^ m0) << 14) | ((m15 ^ m1) << 13);
return sign_extend (word, 16);
}
static int
extract_21 (unsigned word)
{
int val;
word &= MASK_21;
word <<= 11;
val = GET_FIELD (word, 20, 20);
val <<= 11;
val |= GET_FIELD (word, 9, 19);
val <<= 2;
val |= GET_FIELD (word, 5, 6);
val <<= 5;
val |= GET_FIELD (word, 0, 4);
val <<= 2;
val |= GET_FIELD (word, 7, 8);
return sign_extend (val, 21) << 11;
}
static int
extract_12 (unsigned word)
{
return sign_extend (GET_FIELD (word, 19, 28)
| GET_FIELD (word, 29, 29) << 10
| (word & 0x1) << 11, 12) << 2;
}
19 bit signed value. */
static int
extract_17 (unsigned word)
{
return sign_extend (GET_FIELD (word, 19, 28)
| GET_FIELD (word, 29, 29) << 10
| GET_FIELD (word, 11, 15) << 11
| (word & 0x1) << 16, 17) << 2;
}
static int
extract_22 (unsigned word)
{
return sign_extend (GET_FIELD (word, 19, 28)
| GET_FIELD (word, 29, 29) << 10
| GET_FIELD (word, 11, 15) << 11
| GET_FIELD (word, 6, 10) << 16
| (word & 0x1) << 21, 22) << 2;
}
int
print_insn_hppa (bfd_vma memaddr, disassemble_info *info)
{
bfd_byte buffer[4];
unsigned int insn, i;
{
int status =
(*info->read_memory_func) (memaddr, buffer, sizeof (buffer), info);
if (status != 0)
{
(*info->memory_error_func) (status, memaddr, info);
return -1;
}
}
insn = bfd_getb32 (buffer);
for (i = 0; i < NUMOPCODES; ++i)
{
const struct pa_opcode *opcode = &pa_opcodes[i];
if ((insn & opcode->mask) == opcode->match)
{
const char *s;
#ifndef BFD64
if (opcode->arch == pa20w)
continue;
#endif
(*info->fprintf_func) (info->stream, "%s", opcode->name);
if (!strchr ("cfCY?-+nHNZFIuv{", opcode->args[0]))
(*info->fprintf_func) (info->stream, " ");
for (s = opcode->args; *s != '\0'; ++s)
{
switch (*s)
{
case 'x':
fput_reg (GET_FIELD (insn, 11, 15), info);
break;
case 'a':
case 'b':
fput_reg (GET_FIELD (insn, 6, 10), info);
break;
case '^':
fput_creg (GET_FIELD (insn, 6, 10), info);
break;
case 't':
fput_reg (GET_FIELD (insn, 27, 31), info);
break;
case 'f':
switch (*++s)
{
case 't':
fput_fp_reg (GET_FIELD (insn, 27, 31), info);
break;
case 'T':
if (GET_FIELD (insn, 25, 25))
fput_fp_reg_r (GET_FIELD (insn, 27, 31), info);
else
fput_fp_reg (GET_FIELD (insn, 27, 31), info);
break;
case 'a':
if (GET_FIELD (insn, 25, 25))
fput_fp_reg_r (GET_FIELD (insn, 6, 10), info);
else
fput_fp_reg (GET_FIELD (insn, 6, 10), info);
break;
name. Normally that is fine. Except that it
causes problems with xmpyu which has no FP format
completer. */
case 'X':
fputs_filtered (" ", info);
case 'A':
if (GET_FIELD (insn, 24, 24))
fput_fp_reg_r (GET_FIELD (insn, 6, 10), info);
else
fput_fp_reg (GET_FIELD (insn, 6, 10), info);
break;
case 'b':
if (GET_FIELD (insn, 25, 25))
fput_fp_reg_r (GET_FIELD (insn, 11, 15), info);
else
fput_fp_reg (GET_FIELD (insn, 11, 15), info);
break;
case 'B':
if (GET_FIELD (insn, 19, 19))
fput_fp_reg_r (GET_FIELD (insn, 11, 15), info);
else
fput_fp_reg (GET_FIELD (insn, 11, 15), info);
break;
case 'C':
{
int reg = GET_FIELD (insn, 21, 22);
reg |= GET_FIELD (insn, 16, 18) << 2;
if (GET_FIELD (insn, 23, 23) != 0)
fput_fp_reg_r (reg, info);
else
fput_fp_reg (reg, info);
break;
}
case 'i':
{
int reg = GET_FIELD (insn, 6, 10);
reg |= (GET_FIELD (insn, 26, 26) << 4);
fput_fp_reg (reg, info);
break;
}
case 'j':
{
int reg = GET_FIELD (insn, 11, 15);
reg |= (GET_FIELD (insn, 26, 26) << 4);
fput_fp_reg (reg, info);
break;
}
case 'k':
{
int reg = GET_FIELD (insn, 27, 31);
reg |= (GET_FIELD (insn, 26, 26) << 4);
fput_fp_reg (reg, info);
break;
}
case 'l':
{
int reg = GET_FIELD (insn, 21, 25);
reg |= (GET_FIELD (insn, 26, 26) << 4);
fput_fp_reg (reg, info);
break;
}
case 'm':
{
int reg = GET_FIELD (insn, 16, 20);
reg |= (GET_FIELD (insn, 26, 26) << 4);
fput_fp_reg (reg, info);
break;
}
name. Normally that is fine. Except that it
causes problems with fstw fe,y(b) which has no FP
format completer. */
case 'E':
fputs_filtered (" ", info);
case 'e':
if (GET_FIELD (insn, 30, 30))
fput_fp_reg_r (GET_FIELD (insn, 11, 15), info);
else
fput_fp_reg (GET_FIELD (insn, 11, 15), info);
break;
case 'x':
fput_fp_reg (GET_FIELD (insn, 11, 15), info);
break;
}
break;
case '5':
fput_const (extract_5_load (insn), info);
break;
case 's':
{
int space = GET_FIELD (insn, 16, 17);
if (space != 0)
(*info->fprintf_func) (info->stream, "sr%d", space);
}
break;
case 'S':
(*info->fprintf_func) (info->stream, "sr%d",
extract_3 (insn));
break;
case 'c':
switch (*++s)
{
case 'x':
(*info->fprintf_func)
(info->stream, "%s",
index_compl_names[GET_COMPL (insn)]);
break;
case 'X':
(*info->fprintf_func)
(info->stream, "%s ",
index_compl_names[GET_COMPL (insn)]);
break;
case 'm':
(*info->fprintf_func)
(info->stream, "%s",
short_ldst_compl_names[GET_COMPL (insn)]);
break;
case 'M':
(*info->fprintf_func)
(info->stream, "%s ",
short_ldst_compl_names[GET_COMPL (insn)]);
break;
case 'A':
(*info->fprintf_func)
(info->stream, "%s ",
short_bytes_compl_names[GET_COMPL (insn)]);
break;
case 's':
(*info->fprintf_func)
(info->stream, "%s",
short_bytes_compl_names[GET_COMPL (insn)]);
break;
case 'c':
case 'C':
switch (GET_FIELD (insn, 20, 21))
{
case 1:
(*info->fprintf_func) (info->stream, ",bc ");
break;
case 2:
(*info->fprintf_func) (info->stream, ",sl ");
break;
default:
(*info->fprintf_func) (info->stream, " ");
}
break;
case 'd':
switch (GET_FIELD (insn, 20, 21))
{
case 1:
(*info->fprintf_func) (info->stream, ",co ");
break;
default:
(*info->fprintf_func) (info->stream, " ");
}
break;
case 'o':
(*info->fprintf_func) (info->stream, ",o");
break;
case 'g':
(*info->fprintf_func) (info->stream, ",gate");
break;
case 'p':
(*info->fprintf_func) (info->stream, ",l,push");
break;
case 'P':
(*info->fprintf_func) (info->stream, ",pop");
break;
case 'l':
case 'L':
(*info->fprintf_func) (info->stream, ",l");
break;
case 'w':
(*info->fprintf_func)
(info->stream, "%s ",
read_write_names[GET_FIELD (insn, 25, 25)]);
break;
case 'W':
(*info->fprintf_func) (info->stream, ",w ");
break;
case 'r':
if (GET_FIELD (insn, 23, 26) == 5)
(*info->fprintf_func) (info->stream, ",r");
break;
case 'Z':
if (GET_FIELD (insn, 26, 26))
(*info->fprintf_func) (info->stream, ",m ");
else
(*info->fprintf_func) (info->stream, " ");
break;
case 'i':
if (GET_FIELD (insn, 25, 25))
(*info->fprintf_func) (info->stream, ",i");
break;
case 'z':
if (!GET_FIELD (insn, 21, 21))
(*info->fprintf_func) (info->stream, ",z");
break;
case 'a':
(*info->fprintf_func)
(info->stream, "%s",
add_compl_names[GET_FIELD (insn, 20, 21)]);
break;
case 'Y':
(*info->fprintf_func)
(info->stream, ",dc%s",
add_compl_names[GET_FIELD (insn, 20, 21)]);
break;
case 'y':
(*info->fprintf_func)
(info->stream, ",c%s",
add_compl_names[GET_FIELD (insn, 20, 21)]);
break;
case 'v':
if (GET_FIELD (insn, 20, 20))
(*info->fprintf_func) (info->stream, ",tsv");
break;
case 't':
(*info->fprintf_func) (info->stream, ",tc");
if (GET_FIELD (insn, 20, 20))
(*info->fprintf_func) (info->stream, ",tsv");
break;
case 'B':
(*info->fprintf_func) (info->stream, ",db");
if (GET_FIELD (insn, 20, 20))
(*info->fprintf_func) (info->stream, ",tsv");
break;
case 'b':
(*info->fprintf_func) (info->stream, ",b");
if (GET_FIELD (insn, 20, 20))
(*info->fprintf_func) (info->stream, ",tsv");
break;
case 'T':
if (GET_FIELD (insn, 25, 25))
(*info->fprintf_func) (info->stream, ",tc");
break;
case 'S':
if (*(s + 1) == '?')
(*info->fprintf_func)
(info->stream, "%s",
signed_unsigned_names[GET_FIELD (insn, 21, 21)]);
else
(*info->fprintf_func)
(info->stream, "%s ",
signed_unsigned_names[GET_FIELD (insn, 21, 21)]);
break;
case 'h':
(*info->fprintf_func)
(info->stream, "%s",
mix_half_names[GET_FIELD (insn, 17, 17)]);
break;
case 'H':
(*info->fprintf_func)
(info->stream, "%s ",
saturation_names[GET_FIELD (insn, 24, 25)]);
break;
case '*':
(*info->fprintf_func)
(info->stream, ",%d%d%d%d ",
GET_FIELD (insn, 17, 18), GET_FIELD (insn, 20, 21),
GET_FIELD (insn, 22, 23), GET_FIELD (insn, 24, 25));
break;
case 'q':
{
int m, a;
m = GET_FIELD (insn, 28, 28);
a = GET_FIELD (insn, 29, 29);
if (m && !a)
fputs_filtered (",ma ", info);
else if (m && a)
fputs_filtered (",mb ", info);
else
fputs_filtered (" ", info);
break;
}
case 'J':
{
int opc = GET_FIELD (insn, 0, 5);
if (opc == 0x16 || opc == 0x1e)
{
if (GET_FIELD (insn, 29, 29) == 0)
fputs_filtered (",ma ", info);
else
fputs_filtered (",mb ", info);
}
else
fputs_filtered (" ", info);
break;
}
case 'e':
{
int opc = GET_FIELD (insn, 0, 5);
if (opc == 0x13 || opc == 0x1b)
{
if (GET_FIELD (insn, 18, 18) == 1)
fputs_filtered (",mb ", info);
else
fputs_filtered (",ma ", info);
}
else if (opc == 0x17 || opc == 0x1f)
{
if (GET_FIELD (insn, 31, 31) == 1)
fputs_filtered (",ma ", info);
else
fputs_filtered (",mb ", info);
}
else
fputs_filtered (" ", info);
break;
}
}
break;
case '?':
{
s++;
switch (*s)
{
case 'f':
(*info->fprintf_func)
(info->stream, "%s ",
float_comp_names[GET_FIELD (insn, 27, 31)]);
break;
which distinguish true/false conditions by opcode
rather than by the 'f' bit (sigh): comb, comib,
addb, addib. */
case 't':
fputs_filtered
(compare_cond_names[GET_FIELD (insn, 16, 18)], info);
break;
case 'n':
fputs_filtered
(compare_cond_names[GET_FIELD (insn, 16, 18)
+ GET_FIELD (insn, 4, 4) * 8],
info);
break;
case 'N':
fputs_filtered
(compare_cond_64_names[GET_FIELD (insn, 16, 18)
+ GET_FIELD (insn, 2, 2) * 8],
info);
break;
case 'Q':
fputs_filtered
(cmpib_cond_64_names[GET_FIELD (insn, 16, 18)],
info);
break;
case '@':
fputs_filtered
(add_cond_names[GET_FIELD (insn, 16, 18)
+ GET_FIELD (insn, 4, 4) * 8],
info);
break;
case 's':
(*info->fprintf_func)
(info->stream, "%s ",
compare_cond_names[GET_COND (insn)]);
break;
case 'S':
(*info->fprintf_func)
(info->stream, "%s ",
compare_cond_64_names[GET_COND (insn)]);
break;
case 'a':
(*info->fprintf_func)
(info->stream, "%s ",
add_cond_names[GET_COND (insn)]);
break;
case 'A':
(*info->fprintf_func)
(info->stream, "%s ",
add_cond_64_names[GET_COND (insn)]);
break;
case 'd':
(*info->fprintf_func)
(info->stream, "%s",
add_cond_names[GET_FIELD (insn, 16, 18)]);
break;
case 'W':
(*info->fprintf_func)
(info->stream, "%s",
wide_add_cond_names[GET_FIELD (insn, 16, 18) +
GET_FIELD (insn, 4, 4) * 8]);
break;
case 'l':
(*info->fprintf_func)
(info->stream, "%s ",
logical_cond_names[GET_COND (insn)]);
break;
case 'L':
(*info->fprintf_func)
(info->stream, "%s ",
logical_cond_64_names[GET_COND (insn)]);
break;
case 'u':
(*info->fprintf_func)
(info->stream, "%s ",
unit_cond_names[GET_COND (insn)]);
break;
case 'U':
(*info->fprintf_func)
(info->stream, "%s ",
unit_cond_64_names[GET_COND (insn)]);
break;
case 'y':
case 'x':
case 'b':
(*info->fprintf_func)
(info->stream, "%s",
shift_cond_names[GET_FIELD (insn, 16, 18)]);
putting out the space. */
if (s[1] != 'n')
(*info->fprintf_func) (info->stream, " ");
break;
case 'X':
(*info->fprintf_func)
(info->stream, "%s ",
shift_cond_64_names[GET_FIELD (insn, 16, 18)]);
break;
case 'B':
(*info->fprintf_func)
(info->stream, "%s",
bb_cond_64_names[GET_FIELD (insn, 16, 16)]);
putting out the space. */
if (s[1] != 'n')
(*info->fprintf_func) (info->stream, " ");
break;
}
break;
}
case 'V':
fput_const (extract_5_store (insn), info);
break;
case 'r':
fput_const (extract_5r_store (insn), info);
break;
case 'R':
fput_const (extract_5R_store (insn), info);
break;
case 'U':
fput_const (extract_10U_store (insn), info);
break;
case 'B':
case 'Q':
fput_const (extract_5Q_store (insn), info);
break;
case 'i':
fput_const (extract_11 (insn), info);
break;
case 'j':
fput_const (extract_14 (insn), info);
break;
case 'k':
fputs_filtered ("L%", info);
fput_const (extract_21 (insn), info);
break;
case '<':
case 'l':
fput_const (extract_16 (insn), info);
break;
case 'n':
if (insn & 0x2)
(*info->fprintf_func) (info->stream, ",n ");
else
(*info->fprintf_func) (info->stream, " ");
break;
case 'N':
if ((insn & 0x20) && s[1])
(*info->fprintf_func) (info->stream, ",n ");
else if (insn & 0x20)
(*info->fprintf_func) (info->stream, ",n");
else if (s[1])
(*info->fprintf_func) (info->stream, " ");
break;
case 'w':
(*info->print_address_func)
(memaddr + 8 + extract_12 (insn), info);
break;
case 'W':
(*info->print_address_func)
((memaddr + 8 + extract_17 (insn)), info);
break;
case 'z':
so it gets disasssembled as just a number, not any sort
of address. */
fput_const (extract_17 (insn), info);
break;
case 'Z':
fputs_filtered ("r1", info);
break;
case 'Y':
fputs_filtered ("sr0,r31", info);
break;
case '@':
(*info->fprintf_func) (info->stream, "0");
break;
case '.':
(*info->fprintf_func) (info->stream, "%d",
GET_FIELD (insn, 24, 25));
break;
case '*':
(*info->fprintf_func) (info->stream, "%d",
GET_FIELD (insn, 22, 25));
break;
case '!':
fputs_filtered ("sar", info);
break;
case 'p':
(*info->fprintf_func) (info->stream, "%d",
31 - GET_FIELD (insn, 22, 26));
break;
case '~':
{
int num;
num = GET_FIELD (insn, 20, 20) << 5;
num |= GET_FIELD (insn, 22, 26);
(*info->fprintf_func) (info->stream, "%d", 63 - num);
break;
}
case 'P':
(*info->fprintf_func) (info->stream, "%d",
GET_FIELD (insn, 22, 26));
break;
case 'q':
{
int num;
num = GET_FIELD (insn, 20, 20) << 5;
num |= GET_FIELD (insn, 22, 26);
(*info->fprintf_func) (info->stream, "%d", num);
break;
}
case 'T':
(*info->fprintf_func) (info->stream, "%d",
32 - GET_FIELD (insn, 27, 31));
break;
case '%':
{
int num;
num = (GET_FIELD (insn, 23, 23) + 1) * 32;
num -= GET_FIELD (insn, 27, 31);
(*info->fprintf_func) (info->stream, "%d", num);
break;
}
case '|':
{
int num;
num = (GET_FIELD (insn, 19, 19) + 1) * 32;
num -= GET_FIELD (insn, 27, 31);
(*info->fprintf_func) (info->stream, "%d", num);
break;
}
case '$':
fput_const (GET_FIELD (insn, 20, 28), info);
break;
case 'A':
fput_const (GET_FIELD (insn, 6, 18), info);
break;
case 'D':
fput_const (GET_FIELD (insn, 6, 31), info);
break;
case 'v':
(*info->fprintf_func) (info->stream, ",%d",
GET_FIELD (insn, 23, 25));
break;
case 'O':
fput_const ((GET_FIELD (insn, 6,20) << 5 |
GET_FIELD (insn, 27, 31)), info);
break;
case 'o':
fput_const (GET_FIELD (insn, 6, 20), info);
break;
case '2':
fput_const ((GET_FIELD (insn, 6, 22) << 5 |
GET_FIELD (insn, 27, 31)), info);
break;
case '1':
fput_const ((GET_FIELD (insn, 11, 20) << 5 |
GET_FIELD (insn, 27, 31)), info);
break;
case '0':
fput_const ((GET_FIELD (insn, 16, 20) << 5 |
GET_FIELD (insn, 27, 31)), info);
break;
case 'u':
(*info->fprintf_func) (info->stream, ",%d",
GET_FIELD (insn, 23, 25));
break;
case 'F':
for fcmp, need a space here. */
if (s[1] == 'G' || s[1] == '?')
fputs_filtered
(float_format_names[GET_FIELD (insn, 19, 20)], info);
else
(*info->fprintf_func)
(info->stream, "%s ",
float_format_names[GET_FIELD (insn, 19, 20)]);
break;
case 'G':
(*info->fprintf_func)
(info->stream, "%s ",
float_format_names[GET_FIELD (insn, 17, 18)]);
break;
case 'H':
if (GET_FIELD (insn, 26, 26) == 1)
(*info->fprintf_func) (info->stream, "%s ",
float_format_names[0]);
else
(*info->fprintf_func) (info->stream, "%s ",
float_format_names[1]);
break;
case 'I':
for fcmp, need a space here. */
if (s[1] == '?')
fputs_filtered
(float_format_names[GET_FIELD (insn, 20, 20)], info);
else
(*info->fprintf_func)
(info->stream, "%s ",
float_format_names[GET_FIELD (insn, 20, 20)]);
break;
case 'J':
fput_const (extract_14 (insn), info);
break;
case '#':
{
int sign = GET_FIELD (insn, 31, 31);
int imm10 = GET_FIELD (insn, 18, 27);
int disp;
if (sign)
disp = (-1 << 10) | imm10;
else
disp = imm10;
disp <<= 3;
fput_const (disp, info);
break;
}
case 'K':
case 'd':
{
int sign = GET_FIELD (insn, 31, 31);
int imm11 = GET_FIELD (insn, 18, 28);
int disp;
if (sign)
disp = (-1 << 11) | imm11;
else
disp = imm11;
disp <<= 2;
fput_const (disp, info);
break;
}
case '>':
case 'y':
{
int disp = extract_16 (insn);
disp &= ~3;
fput_const (disp, info);
break;
}
case '&':
{
int disp = extract_16 (insn);
disp &= ~7;
fput_const (disp, info);
break;
}
case '_':
break;
case '{':
{
int sub = GET_FIELD (insn, 14, 16);
int df = GET_FIELD (insn, 17, 18);
int sf = GET_FIELD (insn, 19, 20);
const char * const * source = float_format_names;
const char * const * dest = float_format_names;
char *t = "";
if (sub == 4)
{
fputs_filtered (",UND ", info);
break;
}
if ((sub & 3) == 3)
t = ",t";
if ((sub & 3) == 1)
source = sub & 4 ? fcnv_ufixed_names : fcnv_fixed_names;
if (sub & 2)
dest = sub & 4 ? fcnv_ufixed_names : fcnv_fixed_names;
(*info->fprintf_func) (info->stream, "%s%s%s ",
t, source[sf], dest[df]);
break;
}
case 'm':
{
int y = GET_FIELD (insn, 16, 18);
if (y != 1)
fput_const ((y ^ 1) - 1, info);
}
break;
case 'h':
{
int cbit;
cbit = GET_FIELD (insn, 16, 18);
if (cbit > 0)
(*info->fprintf_func) (info->stream, ",%d", cbit - 1);
break;
}
case '=':
{
int cond = GET_FIELD (insn, 27, 31);
switch (cond)
{
case 0: fputs_filtered (" ", info); break;
case 1: fputs_filtered ("acc ", info); break;
case 2: fputs_filtered ("rej ", info); break;
case 5: fputs_filtered ("acc8 ", info); break;
case 6: fputs_filtered ("rej8 ", info); break;
case 9: fputs_filtered ("acc6 ", info); break;
case 13: fputs_filtered ("acc4 ", info); break;
case 17: fputs_filtered ("acc2 ", info); break;
default: break;
}
break;
}
case 'X':
(*info->print_address_func)
(memaddr + 8 + extract_22 (insn), info);
break;
case 'L':
fputs_filtered (",rp", info);
break;
default:
(*info->fprintf_func) (info->stream, "%c", *s);
break;
}
}
return sizeof (insn);
}
}
(*info->fprintf_func) (info->stream, "#%8x", insn);
return sizeof (insn);
}