Home | History | Annotate | Line # | Download | only in opcodes
mips-dis.c revision 1.9
      1  1.1     skrll /* Print mips instructions for GDB, the GNU debugger, or for objdump.
      2  1.9  christos    Copyright (C) 1989-2020 Free Software Foundation, Inc.
      3  1.1     skrll    Contributed by Nobuyuki Hikichi(hikichi (at) sra.co.jp).
      4  1.1     skrll 
      5  1.1     skrll    This file is part of the GNU opcodes library.
      6  1.1     skrll 
      7  1.1     skrll    This library is free software; you can redistribute it and/or modify
      8  1.1     skrll    it under the terms of the GNU General Public License as published by
      9  1.1     skrll    the Free Software Foundation; either version 3, or (at your option)
     10  1.1     skrll    any later version.
     11  1.1     skrll 
     12  1.1     skrll    It is distributed in the hope that it will be useful, but WITHOUT
     13  1.1     skrll    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     14  1.1     skrll    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
     15  1.1     skrll    License for more details.
     16  1.1     skrll 
     17  1.1     skrll    You should have received a copy of the GNU General Public License
     18  1.1     skrll    along with this program; if not, write to the Free Software
     19  1.1     skrll    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
     20  1.1     skrll    MA 02110-1301, USA.  */
     21  1.1     skrll 
     22  1.1     skrll #include "sysdep.h"
     23  1.7  christos #include "disassemble.h"
     24  1.1     skrll #include "libiberty.h"
     25  1.1     skrll #include "opcode/mips.h"
     26  1.1     skrll #include "opintl.h"
     27  1.9  christos #include "elf-bfd.h"
     28  1.9  christos #include "elf/mips.h"
     29  1.9  christos #include "elfxx-mips.h"
     30  1.1     skrll 
     31  1.1     skrll /* FIXME: These are needed to figure out if the code is mips16 or
     32  1.1     skrll    not. The low bit of the address is often a good indicator.  No
     33  1.1     skrll    symbol table is available when this code runs out in an embedded
     34  1.1     skrll    system as when it is used for disassembler support in a monitor.  */
     35  1.1     skrll 
     36  1.1     skrll #if !defined(EMBEDDED_ENV)
     37  1.1     skrll #define SYMTAB_AVAILABLE 1
     38  1.1     skrll #endif
     39  1.1     skrll 
     40  1.1     skrll /* Mips instructions are at maximum this many bytes long.  */
     41  1.1     skrll #define INSNLEN 4
     42  1.1     skrll 
     43  1.1     skrll 
     44  1.1     skrll /* FIXME: These should be shared with gdb somehow.  */
     46  1.1     skrll 
     47  1.1     skrll struct mips_cp0sel_name
     48  1.1     skrll {
     49  1.1     skrll   unsigned int cp0reg;
     50  1.1     skrll   unsigned int sel;
     51  1.1     skrll   const char * const name;
     52  1.1     skrll };
     53  1.1     skrll 
     54  1.1     skrll static const char * const mips_gpr_names_numeric[32] =
     55  1.1     skrll {
     56  1.1     skrll   "$0",   "$1",   "$2",   "$3",   "$4",   "$5",   "$6",   "$7",
     57  1.1     skrll   "$8",   "$9",   "$10",  "$11",  "$12",  "$13",  "$14",  "$15",
     58  1.1     skrll   "$16",  "$17",  "$18",  "$19",  "$20",  "$21",  "$22",  "$23",
     59  1.1     skrll   "$24",  "$25",  "$26",  "$27",  "$28",  "$29",  "$30",  "$31"
     60  1.1     skrll };
     61  1.1     skrll 
     62  1.1     skrll static const char * const mips_gpr_names_oldabi[32] =
     63  1.1     skrll {
     64  1.1     skrll   "zero", "at",   "v0",   "v1",   "a0",   "a1",   "a2",   "a3",
     65  1.1     skrll   "t0",   "t1",   "t2",   "t3",   "t4",   "t5",   "t6",   "t7",
     66  1.1     skrll   "s0",   "s1",   "s2",   "s3",   "s4",   "s5",   "s6",   "s7",
     67  1.1     skrll   "t8",   "t9",   "k0",   "k1",   "gp",   "sp",   "s8",   "ra"
     68  1.1     skrll };
     69  1.1     skrll 
     70  1.1     skrll static const char * const mips_gpr_names_newabi[32] =
     71  1.1     skrll {
     72  1.1     skrll   "zero", "at",   "v0",   "v1",   "a0",   "a1",   "a2",   "a3",
     73  1.1     skrll   "a4",   "a5",   "a6",   "a7",   "t0",   "t1",   "t2",   "t3",
     74  1.1     skrll   "s0",   "s1",   "s2",   "s3",   "s4",   "s5",   "s6",   "s7",
     75  1.1     skrll   "t8",   "t9",   "k0",   "k1",   "gp",   "sp",   "s8",   "ra"
     76  1.1     skrll };
     77  1.1     skrll 
     78  1.1     skrll static const char * const mips_fpr_names_numeric[32] =
     79  1.1     skrll {
     80  1.1     skrll   "$f0",  "$f1",  "$f2",  "$f3",  "$f4",  "$f5",  "$f6",  "$f7",
     81  1.1     skrll   "$f8",  "$f9",  "$f10", "$f11", "$f12", "$f13", "$f14", "$f15",
     82  1.1     skrll   "$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23",
     83  1.1     skrll   "$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31"
     84  1.1     skrll };
     85  1.1     skrll 
     86  1.1     skrll static const char * const mips_fpr_names_32[32] =
     87  1.1     skrll {
     88  1.1     skrll   "fv0",  "fv0f", "fv1",  "fv1f", "ft0",  "ft0f", "ft1",  "ft1f",
     89  1.1     skrll   "ft2",  "ft2f", "ft3",  "ft3f", "fa0",  "fa0f", "fa1",  "fa1f",
     90  1.1     skrll   "ft4",  "ft4f", "ft5",  "ft5f", "fs0",  "fs0f", "fs1",  "fs1f",
     91  1.1     skrll   "fs2",  "fs2f", "fs3",  "fs3f", "fs4",  "fs4f", "fs5",  "fs5f"
     92  1.1     skrll };
     93  1.1     skrll 
     94  1.1     skrll static const char * const mips_fpr_names_n32[32] =
     95  1.1     skrll {
     96  1.1     skrll   "fv0",  "ft14", "fv1",  "ft15", "ft0",  "ft1",  "ft2",  "ft3",
     97  1.1     skrll   "ft4",  "ft5",  "ft6",  "ft7",  "fa0",  "fa1",  "fa2",  "fa3",
     98  1.1     skrll   "fa4",  "fa5",  "fa6",  "fa7",  "fs0",  "ft8",  "fs1",  "ft9",
     99  1.1     skrll   "fs2",  "ft10", "fs3",  "ft11", "fs4",  "ft12", "fs5",  "ft13"
    100  1.1     skrll };
    101  1.1     skrll 
    102  1.1     skrll static const char * const mips_fpr_names_64[32] =
    103  1.1     skrll {
    104  1.1     skrll   "fv0",  "ft12", "fv1",  "ft13", "ft0",  "ft1",  "ft2",  "ft3",
    105  1.1     skrll   "ft4",  "ft5",  "ft6",  "ft7",  "fa0",  "fa1",  "fa2",  "fa3",
    106  1.1     skrll   "fa4",  "fa5",  "fa6",  "fa7",  "ft8",  "ft9",  "ft10", "ft11",
    107  1.1     skrll   "fs0",  "fs1",  "fs2",  "fs3",  "fs4",  "fs5",  "fs6",  "fs7"
    108  1.1     skrll };
    109  1.1     skrll 
    110  1.1     skrll static const char * const mips_cp0_names_numeric[32] =
    111  1.1     skrll {
    112  1.1     skrll   "$0",   "$1",   "$2",   "$3",   "$4",   "$5",   "$6",   "$7",
    113  1.1     skrll   "$8",   "$9",   "$10",  "$11",  "$12",  "$13",  "$14",  "$15",
    114  1.1     skrll   "$16",  "$17",  "$18",  "$19",  "$20",  "$21",  "$22",  "$23",
    115  1.1     skrll   "$24",  "$25",  "$26",  "$27",  "$28",  "$29",  "$30",  "$31"
    116  1.1     skrll };
    117  1.5  christos 
    118  1.5  christos static const char * const mips_cp1_names_numeric[32] =
    119  1.5  christos {
    120  1.5  christos   "$0",   "$1",   "$2",   "$3",   "$4",   "$5",   "$6",   "$7",
    121  1.5  christos   "$8",   "$9",   "$10",  "$11",  "$12",  "$13",  "$14",  "$15",
    122  1.5  christos   "$16",  "$17",  "$18",  "$19",  "$20",  "$21",  "$22",  "$23",
    123  1.5  christos   "$24",  "$25",  "$26",  "$27",  "$28",  "$29",  "$30",  "$31"
    124  1.5  christos };
    125  1.1     skrll 
    126  1.1     skrll static const char * const mips_cp0_names_r3000[32] =
    127  1.1     skrll {
    128  1.1     skrll   "c0_index",     "c0_random",    "c0_entrylo",   "$3",
    129  1.1     skrll   "c0_context",   "$5",           "$6",           "$7",
    130  1.1     skrll   "c0_badvaddr",  "$9",           "c0_entryhi",   "$11",
    131  1.1     skrll   "c0_sr",        "c0_cause",     "c0_epc",       "c0_prid",
    132  1.1     skrll   "$16",          "$17",          "$18",          "$19",
    133  1.1     skrll   "$20",          "$21",          "$22",          "$23",
    134  1.1     skrll   "$24",          "$25",          "$26",          "$27",
    135  1.1     skrll   "$28",          "$29",          "$30",          "$31",
    136  1.1     skrll };
    137  1.1     skrll 
    138  1.1     skrll static const char * const mips_cp0_names_r4000[32] =
    139  1.1     skrll {
    140  1.1     skrll   "c0_index",     "c0_random",    "c0_entrylo0",  "c0_entrylo1",
    141  1.1     skrll   "c0_context",   "c0_pagemask",  "c0_wired",     "$7",
    142  1.1     skrll   "c0_badvaddr",  "c0_count",     "c0_entryhi",   "c0_compare",
    143  1.1     skrll   "c0_sr",        "c0_cause",     "c0_epc",       "c0_prid",
    144  1.1     skrll   "c0_config",    "c0_lladdr",    "c0_watchlo",   "c0_watchhi",
    145  1.1     skrll   "c0_xcontext",  "$21",          "$22",          "$23",
    146  1.1     skrll   "$24",          "$25",          "c0_ecc",       "c0_cacheerr",
    147  1.1     skrll   "c0_taglo",     "c0_taghi",     "c0_errorepc",  "$31",
    148  1.1     skrll };
    149  1.5  christos 
    150  1.5  christos static const char * const mips_cp0_names_r5900[32] =
    151  1.5  christos {
    152  1.5  christos   "c0_index",     "c0_random",    "c0_entrylo0",  "c0_entrylo1",
    153  1.5  christos   "c0_context",   "c0_pagemask",  "c0_wired",     "$7",
    154  1.5  christos   "c0_badvaddr",  "c0_count",     "c0_entryhi",   "c0_compare",
    155  1.5  christos   "c0_sr",        "c0_cause",     "c0_epc",       "c0_prid",
    156  1.5  christos   "c0_config",    "$17",          "$18",          "$19",
    157  1.5  christos   "$20",          "$21",          "$22",          "c0_badpaddr",
    158  1.5  christos   "c0_depc",      "c0_perfcnt",   "$26",          "$27",
    159  1.5  christos   "c0_taglo",     "c0_taghi",     "c0_errorepc",  "$31"
    160  1.5  christos };
    161  1.1     skrll 
    162  1.1     skrll static const char * const mips_cp0_names_mips3264[32] =
    163  1.1     skrll {
    164  1.1     skrll   "c0_index",     "c0_random",    "c0_entrylo0",  "c0_entrylo1",
    165  1.1     skrll   "c0_context",   "c0_pagemask",  "c0_wired",     "$7",
    166  1.1     skrll   "c0_badvaddr",  "c0_count",     "c0_entryhi",   "c0_compare",
    167  1.1     skrll   "c0_status",    "c0_cause",     "c0_epc",       "c0_prid",
    168  1.1     skrll   "c0_config",    "c0_lladdr",    "c0_watchlo",   "c0_watchhi",
    169  1.1     skrll   "c0_xcontext",  "$21",          "$22",          "c0_debug",
    170  1.1     skrll   "c0_depc",      "c0_perfcnt",   "c0_errctl",    "c0_cacheerr",
    171  1.1     skrll   "c0_taglo",     "c0_taghi",     "c0_errorepc",  "c0_desave",
    172  1.1     skrll };
    173  1.5  christos 
    174  1.5  christos static const char * const mips_cp1_names_mips3264[32] =
    175  1.5  christos {
    176  1.5  christos   "c1_fir",       "c1_ufr",       "$2",           "$3",
    177  1.5  christos   "c1_unfr",      "$5",           "$6",           "$7",
    178  1.5  christos   "$8",           "$9",           "$10",          "$11",
    179  1.5  christos   "$12",          "$13",          "$14",          "$15",
    180  1.5  christos   "$16",          "$17",          "$18",          "$19",
    181  1.5  christos   "$20",          "$21",          "$22",          "$23",
    182  1.5  christos   "$24",          "c1_fccr",      "c1_fexr",      "$27",
    183  1.5  christos   "c1_fenr",      "$29",          "$30",          "c1_fcsr"
    184  1.5  christos };
    185  1.1     skrll 
    186  1.1     skrll static const struct mips_cp0sel_name mips_cp0sel_names_mips3264[] =
    187  1.1     skrll {
    188  1.1     skrll   { 16, 1, "c0_config1"		},
    189  1.1     skrll   { 16, 2, "c0_config2"		},
    190  1.1     skrll   { 16, 3, "c0_config3"		},
    191  1.1     skrll   { 18, 1, "c0_watchlo,1"	},
    192  1.1     skrll   { 18, 2, "c0_watchlo,2"	},
    193  1.1     skrll   { 18, 3, "c0_watchlo,3"	},
    194  1.1     skrll   { 18, 4, "c0_watchlo,4"	},
    195  1.1     skrll   { 18, 5, "c0_watchlo,5"	},
    196  1.1     skrll   { 18, 6, "c0_watchlo,6"	},
    197  1.1     skrll   { 18, 7, "c0_watchlo,7"	},
    198  1.1     skrll   { 19, 1, "c0_watchhi,1"	},
    199  1.1     skrll   { 19, 2, "c0_watchhi,2"	},
    200  1.1     skrll   { 19, 3, "c0_watchhi,3"	},
    201  1.1     skrll   { 19, 4, "c0_watchhi,4"	},
    202  1.1     skrll   { 19, 5, "c0_watchhi,5"	},
    203  1.1     skrll   { 19, 6, "c0_watchhi,6"	},
    204  1.1     skrll   { 19, 7, "c0_watchhi,7"	},
    205  1.1     skrll   { 25, 1, "c0_perfcnt,1"	},
    206  1.1     skrll   { 25, 2, "c0_perfcnt,2"	},
    207  1.1     skrll   { 25, 3, "c0_perfcnt,3"	},
    208  1.1     skrll   { 25, 4, "c0_perfcnt,4"	},
    209  1.1     skrll   { 25, 5, "c0_perfcnt,5"	},
    210  1.1     skrll   { 25, 6, "c0_perfcnt,6"	},
    211  1.1     skrll   { 25, 7, "c0_perfcnt,7"	},
    212  1.1     skrll   { 27, 1, "c0_cacheerr,1"	},
    213  1.1     skrll   { 27, 2, "c0_cacheerr,2"	},
    214  1.1     skrll   { 27, 3, "c0_cacheerr,3"	},
    215  1.1     skrll   { 28, 1, "c0_datalo"		},
    216  1.1     skrll   { 29, 1, "c0_datahi"		}
    217  1.1     skrll };
    218  1.1     skrll 
    219  1.1     skrll static const char * const mips_cp0_names_mips3264r2[32] =
    220  1.1     skrll {
    221  1.1     skrll   "c0_index",     "c0_random",    "c0_entrylo0",  "c0_entrylo1",
    222  1.1     skrll   "c0_context",   "c0_pagemask",  "c0_wired",     "c0_hwrena",
    223  1.1     skrll   "c0_badvaddr",  "c0_count",     "c0_entryhi",   "c0_compare",
    224  1.1     skrll   "c0_status",    "c0_cause",     "c0_epc",       "c0_prid",
    225  1.1     skrll   "c0_config",    "c0_lladdr",    "c0_watchlo",   "c0_watchhi",
    226  1.1     skrll   "c0_xcontext",  "$21",          "$22",          "c0_debug",
    227  1.1     skrll   "c0_depc",      "c0_perfcnt",   "c0_errctl",    "c0_cacheerr",
    228  1.1     skrll   "c0_taglo",     "c0_taghi",     "c0_errorepc",  "c0_desave",
    229  1.1     skrll };
    230  1.1     skrll 
    231  1.1     skrll static const struct mips_cp0sel_name mips_cp0sel_names_mips3264r2[] =
    232  1.1     skrll {
    233  1.1     skrll   {  4, 1, "c0_contextconfig"	},
    234  1.1     skrll   {  0, 1, "c0_mvpcontrol"	},
    235  1.1     skrll   {  0, 2, "c0_mvpconf0"	},
    236  1.1     skrll   {  0, 3, "c0_mvpconf1"	},
    237  1.1     skrll   {  1, 1, "c0_vpecontrol"	},
    238  1.1     skrll   {  1, 2, "c0_vpeconf0"	},
    239  1.1     skrll   {  1, 3, "c0_vpeconf1"	},
    240  1.1     skrll   {  1, 4, "c0_yqmask"		},
    241  1.1     skrll   {  1, 5, "c0_vpeschedule"	},
    242  1.1     skrll   {  1, 6, "c0_vpeschefback"	},
    243  1.1     skrll   {  2, 1, "c0_tcstatus"	},
    244  1.1     skrll   {  2, 2, "c0_tcbind"		},
    245  1.1     skrll   {  2, 3, "c0_tcrestart"	},
    246  1.1     skrll   {  2, 4, "c0_tchalt"		},
    247  1.1     skrll   {  2, 5, "c0_tccontext"	},
    248  1.1     skrll   {  2, 6, "c0_tcschedule"	},
    249  1.1     skrll   {  2, 7, "c0_tcschefback"	},
    250  1.1     skrll   {  5, 1, "c0_pagegrain"	},
    251  1.1     skrll   {  6, 1, "c0_srsconf0"	},
    252  1.1     skrll   {  6, 2, "c0_srsconf1"	},
    253  1.1     skrll   {  6, 3, "c0_srsconf2"	},
    254  1.1     skrll   {  6, 4, "c0_srsconf3"	},
    255  1.1     skrll   {  6, 5, "c0_srsconf4"	},
    256  1.1     skrll   { 12, 1, "c0_intctl"		},
    257  1.1     skrll   { 12, 2, "c0_srsctl"		},
    258  1.1     skrll   { 12, 3, "c0_srsmap"		},
    259  1.1     skrll   { 15, 1, "c0_ebase"		},
    260  1.1     skrll   { 16, 1, "c0_config1"		},
    261  1.1     skrll   { 16, 2, "c0_config2"		},
    262  1.1     skrll   { 16, 3, "c0_config3"		},
    263  1.1     skrll   { 18, 1, "c0_watchlo,1"	},
    264  1.1     skrll   { 18, 2, "c0_watchlo,2"	},
    265  1.1     skrll   { 18, 3, "c0_watchlo,3"	},
    266  1.1     skrll   { 18, 4, "c0_watchlo,4"	},
    267  1.1     skrll   { 18, 5, "c0_watchlo,5"	},
    268  1.1     skrll   { 18, 6, "c0_watchlo,6"	},
    269  1.1     skrll   { 18, 7, "c0_watchlo,7"	},
    270  1.1     skrll   { 19, 1, "c0_watchhi,1"	},
    271  1.1     skrll   { 19, 2, "c0_watchhi,2"	},
    272  1.1     skrll   { 19, 3, "c0_watchhi,3"	},
    273  1.1     skrll   { 19, 4, "c0_watchhi,4"	},
    274  1.1     skrll   { 19, 5, "c0_watchhi,5"	},
    275  1.1     skrll   { 19, 6, "c0_watchhi,6"	},
    276  1.1     skrll   { 19, 7, "c0_watchhi,7"	},
    277  1.1     skrll   { 23, 1, "c0_tracecontrol"	},
    278  1.1     skrll   { 23, 2, "c0_tracecontrol2"	},
    279  1.1     skrll   { 23, 3, "c0_usertracedata"	},
    280  1.1     skrll   { 23, 4, "c0_tracebpc"	},
    281  1.1     skrll   { 25, 1, "c0_perfcnt,1"	},
    282  1.1     skrll   { 25, 2, "c0_perfcnt,2"	},
    283  1.1     skrll   { 25, 3, "c0_perfcnt,3"	},
    284  1.1     skrll   { 25, 4, "c0_perfcnt,4"	},
    285  1.1     skrll   { 25, 5, "c0_perfcnt,5"	},
    286  1.1     skrll   { 25, 6, "c0_perfcnt,6"	},
    287  1.1     skrll   { 25, 7, "c0_perfcnt,7"	},
    288  1.1     skrll   { 27, 1, "c0_cacheerr,1"	},
    289  1.1     skrll   { 27, 2, "c0_cacheerr,2"	},
    290  1.1     skrll   { 27, 3, "c0_cacheerr,3"	},
    291  1.1     skrll   { 28, 1, "c0_datalo"		},
    292  1.1     skrll   { 28, 2, "c0_taglo1"		},
    293  1.1     skrll   { 28, 3, "c0_datalo1"		},
    294  1.1     skrll   { 28, 4, "c0_taglo2"		},
    295  1.1     skrll   { 28, 5, "c0_datalo2"		},
    296  1.1     skrll   { 28, 6, "c0_taglo3"		},
    297  1.1     skrll   { 28, 7, "c0_datalo3"		},
    298  1.1     skrll   { 29, 1, "c0_datahi"		},
    299  1.1     skrll   { 29, 2, "c0_taghi1"		},
    300  1.1     skrll   { 29, 3, "c0_datahi1"		},
    301  1.1     skrll   { 29, 4, "c0_taghi2"		},
    302  1.1     skrll   { 29, 5, "c0_datahi2"		},
    303  1.1     skrll   { 29, 6, "c0_taghi3"		},
    304  1.1     skrll   { 29, 7, "c0_datahi3"		},
    305  1.1     skrll };
    306  1.1     skrll 
    307  1.1     skrll /* SB-1: MIPS64 (mips_cp0_names_mips3264) with minor mods.  */
    308  1.1     skrll static const char * const mips_cp0_names_sb1[32] =
    309  1.1     skrll {
    310  1.1     skrll   "c0_index",     "c0_random",    "c0_entrylo0",  "c0_entrylo1",
    311  1.1     skrll   "c0_context",   "c0_pagemask",  "c0_wired",     "$7",
    312  1.1     skrll   "c0_badvaddr",  "c0_count",     "c0_entryhi",   "c0_compare",
    313  1.1     skrll   "c0_status",    "c0_cause",     "c0_epc",       "c0_prid",
    314  1.1     skrll   "c0_config",    "c0_lladdr",    "c0_watchlo",   "c0_watchhi",
    315  1.1     skrll   "c0_xcontext",  "$21",          "$22",          "c0_debug",
    316  1.1     skrll   "c0_depc",      "c0_perfcnt",   "c0_errctl",    "c0_cacheerr_i",
    317  1.1     skrll   "c0_taglo_i",   "c0_taghi_i",   "c0_errorepc",  "c0_desave",
    318  1.1     skrll };
    319  1.1     skrll 
    320  1.1     skrll static const struct mips_cp0sel_name mips_cp0sel_names_sb1[] =
    321  1.1     skrll {
    322  1.1     skrll   { 16, 1, "c0_config1"		},
    323  1.1     skrll   { 18, 1, "c0_watchlo,1"	},
    324  1.1     skrll   { 19, 1, "c0_watchhi,1"	},
    325  1.1     skrll   { 22, 0, "c0_perftrace"	},
    326  1.1     skrll   { 23, 3, "c0_edebug"		},
    327  1.1     skrll   { 25, 1, "c0_perfcnt,1"	},
    328  1.1     skrll   { 25, 2, "c0_perfcnt,2"	},
    329  1.1     skrll   { 25, 3, "c0_perfcnt,3"	},
    330  1.1     skrll   { 25, 4, "c0_perfcnt,4"	},
    331  1.1     skrll   { 25, 5, "c0_perfcnt,5"	},
    332  1.1     skrll   { 25, 6, "c0_perfcnt,6"	},
    333  1.1     skrll   { 25, 7, "c0_perfcnt,7"	},
    334  1.1     skrll   { 26, 1, "c0_buserr_pa"	},
    335  1.1     skrll   { 27, 1, "c0_cacheerr_d"	},
    336  1.1     skrll   { 27, 3, "c0_cacheerr_d_pa"	},
    337  1.1     skrll   { 28, 1, "c0_datalo_i"	},
    338  1.1     skrll   { 28, 2, "c0_taglo_d"		},
    339  1.1     skrll   { 28, 3, "c0_datalo_d"	},
    340  1.1     skrll   { 29, 1, "c0_datahi_i"	},
    341  1.1     skrll   { 29, 2, "c0_taghi_d"		},
    342  1.1     skrll   { 29, 3, "c0_datahi_d"	},
    343  1.1     skrll };
    344  1.2      matt 
    345  1.2      matt /* Xlr cop0 register names.  */
    346  1.2      matt static const char * const mips_cp0_names_xlr[32] = {
    347  1.3  christos   "c0_index",     "c0_random",    "c0_entrylo0",  "c0_entrylo1",
    348  1.2      matt   "c0_context",   "c0_pagemask",  "c0_wired",     "$7",
    349  1.2      matt   "c0_badvaddr",  "c0_count",     "c0_entryhi",   "c0_compare",
    350  1.2      matt   "c0_status",    "c0_cause",     "c0_epc",       "c0_prid",
    351  1.3  christos   "c0_config",    "c0_lladdr",    "c0_watchlo",   "c0_watchhi",
    352  1.2      matt   "c0_xcontext",  "$21",          "$22",          "c0_debug",
    353  1.2      matt   "c0_depc",      "c0_perfcnt",   "c0_errctl",    "c0_cacheerr_i",
    354  1.2      matt   "c0_taglo_i",   "c0_taghi_i",   "c0_errorepc",  "c0_desave",
    355  1.2      matt };
    356  1.2      matt 
    357  1.2      matt /* XLR's CP0 Select Registers.  */
    358  1.2      matt 
    359  1.2      matt static const struct mips_cp0sel_name mips_cp0sel_names_xlr[] = {
    360  1.2      matt   {  9, 6, "c0_extintreq"       },
    361  1.2      matt   {  9, 7, "c0_extintmask"      },
    362  1.2      matt   { 15, 1, "c0_ebase"           },
    363  1.2      matt   { 16, 1, "c0_config1"         },
    364  1.2      matt   { 16, 2, "c0_config2"         },
    365  1.2      matt   { 16, 3, "c0_config3"         },
    366  1.2      matt   { 16, 7, "c0_procid2"         },
    367  1.2      matt   { 18, 1, "c0_watchlo,1"       },
    368  1.2      matt   { 18, 2, "c0_watchlo,2"       },
    369  1.2      matt   { 18, 3, "c0_watchlo,3"       },
    370  1.2      matt   { 18, 4, "c0_watchlo,4"       },
    371  1.2      matt   { 18, 5, "c0_watchlo,5"       },
    372  1.2      matt   { 18, 6, "c0_watchlo,6"       },
    373  1.2      matt   { 18, 7, "c0_watchlo,7"       },
    374  1.2      matt   { 19, 1, "c0_watchhi,1"       },
    375  1.2      matt   { 19, 2, "c0_watchhi,2"       },
    376  1.2      matt   { 19, 3, "c0_watchhi,3"       },
    377  1.2      matt   { 19, 4, "c0_watchhi,4"       },
    378  1.2      matt   { 19, 5, "c0_watchhi,5"       },
    379  1.2      matt   { 19, 6, "c0_watchhi,6"       },
    380  1.2      matt   { 19, 7, "c0_watchhi,7"       },
    381  1.2      matt   { 25, 1, "c0_perfcnt,1"       },
    382  1.2      matt   { 25, 2, "c0_perfcnt,2"       },
    383  1.2      matt   { 25, 3, "c0_perfcnt,3"       },
    384  1.2      matt   { 25, 4, "c0_perfcnt,4"       },
    385  1.2      matt   { 25, 5, "c0_perfcnt,5"       },
    386  1.2      matt   { 25, 6, "c0_perfcnt,6"       },
    387  1.2      matt   { 25, 7, "c0_perfcnt,7"       },
    388  1.2      matt   { 27, 1, "c0_cacheerr,1"      },
    389  1.2      matt   { 27, 2, "c0_cacheerr,2"      },
    390  1.2      matt   { 27, 3, "c0_cacheerr,3"      },
    391  1.2      matt   { 28, 1, "c0_datalo"          },
    392  1.2      matt   { 29, 1, "c0_datahi"          }
    393  1.2      matt };
    394  1.1     skrll 
    395  1.1     skrll static const char * const mips_hwr_names_numeric[32] =
    396  1.1     skrll {
    397  1.1     skrll   "$0",   "$1",   "$2",   "$3",   "$4",   "$5",   "$6",   "$7",
    398  1.1     skrll   "$8",   "$9",   "$10",  "$11",  "$12",  "$13",  "$14",  "$15",
    399  1.1     skrll   "$16",  "$17",  "$18",  "$19",  "$20",  "$21",  "$22",  "$23",
    400  1.1     skrll   "$24",  "$25",  "$26",  "$27",  "$28",  "$29",  "$30",  "$31"
    401  1.1     skrll };
    402  1.1     skrll 
    403  1.1     skrll static const char * const mips_hwr_names_mips3264r2[32] =
    404  1.1     skrll {
    405  1.1     skrll   "hwr_cpunum",   "hwr_synci_step", "hwr_cc",     "hwr_ccres",
    406  1.1     skrll   "$4",          "$5",            "$6",           "$7",
    407  1.1     skrll   "$8",   "$9",   "$10",  "$11",  "$12",  "$13",  "$14",  "$15",
    408  1.1     skrll   "$16",  "$17",  "$18",  "$19",  "$20",  "$21",  "$22",  "$23",
    409  1.1     skrll   "$24",  "$25",  "$26",  "$27",  "$28",  "$29",  "$30",  "$31"
    410  1.1     skrll };
    411  1.5  christos 
    412  1.5  christos static const char * const msa_control_names[32] =
    413  1.5  christos {
    414  1.5  christos   "msa_ir",	"msa_csr",	"msa_access",	"msa_save",
    415  1.5  christos   "msa_modify",	"msa_request",	"msa_map",	"msa_unmap",
    416  1.5  christos   "$8",   "$9",   "$10",  "$11",  "$12",  "$13",  "$14",  "$15",
    417  1.5  christos   "$16",  "$17",  "$18",  "$19",  "$20",  "$21",  "$22",  "$23",
    418  1.5  christos   "$24",  "$25",  "$26",  "$27",  "$28",  "$29",  "$30",  "$31"
    419  1.5  christos };
    420  1.1     skrll 
    421  1.1     skrll struct mips_abi_choice
    422  1.1     skrll {
    423  1.1     skrll   const char * name;
    424  1.1     skrll   const char * const *gpr_names;
    425  1.1     skrll   const char * const *fpr_names;
    426  1.1     skrll };
    427  1.1     skrll 
    428  1.1     skrll struct mips_abi_choice mips_abi_choices[] =
    429  1.1     skrll {
    430  1.1     skrll   { "numeric", mips_gpr_names_numeric, mips_fpr_names_numeric },
    431  1.1     skrll   { "32", mips_gpr_names_oldabi, mips_fpr_names_32 },
    432  1.1     skrll   { "n32", mips_gpr_names_newabi, mips_fpr_names_n32 },
    433  1.1     skrll   { "64", mips_gpr_names_newabi, mips_fpr_names_64 },
    434  1.1     skrll };
    435  1.1     skrll 
    436  1.1     skrll struct mips_arch_choice
    437  1.1     skrll {
    438  1.1     skrll   const char *name;
    439  1.1     skrll   int bfd_mach_valid;
    440  1.1     skrll   unsigned long bfd_mach;
    441  1.1     skrll   int processor;
    442  1.5  christos   int isa;
    443  1.1     skrll   int ase;
    444  1.1     skrll   const char * const *cp0_names;
    445  1.1     skrll   const struct mips_cp0sel_name *cp0sel_names;
    446  1.5  christos   unsigned int cp0sel_names_len;
    447  1.1     skrll   const char * const *cp1_names;
    448  1.1     skrll   const char * const *hwr_names;
    449  1.1     skrll };
    450  1.1     skrll 
    451  1.1     skrll const struct mips_arch_choice mips_arch_choices[] =
    452  1.5  christos {
    453  1.5  christos   { "numeric",	0, 0, 0, 0, 0,
    454  1.5  christos     mips_cp0_names_numeric, NULL, 0, mips_cp1_names_numeric,
    455  1.1     skrll     mips_hwr_names_numeric },
    456  1.5  christos 
    457  1.5  christos   { "r3000",	1, bfd_mach_mips3000, CPU_R3000, ISA_MIPS1, 0,
    458  1.5  christos     mips_cp0_names_r3000, NULL, 0, mips_cp1_names_numeric,
    459  1.5  christos     mips_hwr_names_numeric },
    460  1.5  christos   { "r3900",	1, bfd_mach_mips3900, CPU_R3900, ISA_MIPS1, 0,
    461  1.5  christos     mips_cp0_names_numeric, NULL, 0, mips_cp1_names_numeric,
    462  1.5  christos     mips_hwr_names_numeric },
    463  1.5  christos   { "r4000",	1, bfd_mach_mips4000, CPU_R4000, ISA_MIPS3, 0,
    464  1.5  christos     mips_cp0_names_r4000, NULL, 0, mips_cp1_names_numeric,
    465  1.5  christos     mips_hwr_names_numeric },
    466  1.5  christos   { "r4010",	1, bfd_mach_mips4010, CPU_R4010, ISA_MIPS2, 0,
    467  1.5  christos     mips_cp0_names_numeric, NULL, 0, mips_cp1_names_numeric,
    468  1.5  christos     mips_hwr_names_numeric },
    469  1.5  christos   { "vr4100",	1, bfd_mach_mips4100, CPU_VR4100, ISA_MIPS3, 0,
    470  1.5  christos     mips_cp0_names_numeric, NULL, 0, mips_cp1_names_numeric,
    471  1.5  christos     mips_hwr_names_numeric },
    472  1.5  christos   { "vr4111",	1, bfd_mach_mips4111, CPU_R4111, ISA_MIPS3, 0,
    473  1.5  christos     mips_cp0_names_numeric, NULL, 0, mips_cp1_names_numeric,
    474  1.5  christos     mips_hwr_names_numeric },
    475  1.5  christos   { "vr4120",	1, bfd_mach_mips4120, CPU_VR4120, ISA_MIPS3, 0,
    476  1.5  christos     mips_cp0_names_numeric, NULL, 0, mips_cp1_names_numeric,
    477  1.5  christos     mips_hwr_names_numeric },
    478  1.5  christos   { "r4300",	1, bfd_mach_mips4300, CPU_R4300, ISA_MIPS3, 0,
    479  1.5  christos     mips_cp0_names_numeric, NULL, 0, mips_cp1_names_numeric,
    480  1.5  christos     mips_hwr_names_numeric },
    481  1.5  christos   { "r4400",	1, bfd_mach_mips4400, CPU_R4400, ISA_MIPS3, 0,
    482  1.5  christos     mips_cp0_names_r4000, NULL, 0, mips_cp1_names_numeric,
    483  1.5  christos     mips_hwr_names_numeric },
    484  1.5  christos   { "r4600",	1, bfd_mach_mips4600, CPU_R4600, ISA_MIPS3, 0,
    485  1.5  christos     mips_cp0_names_numeric, NULL, 0, mips_cp1_names_numeric,
    486  1.5  christos     mips_hwr_names_numeric },
    487  1.5  christos   { "r4650",	1, bfd_mach_mips4650, CPU_R4650, ISA_MIPS3, 0,
    488  1.5  christos     mips_cp0_names_numeric, NULL, 0, mips_cp1_names_numeric,
    489  1.5  christos     mips_hwr_names_numeric },
    490  1.5  christos   { "r5000",	1, bfd_mach_mips5000, CPU_R5000, ISA_MIPS4, 0,
    491  1.5  christos     mips_cp0_names_numeric, NULL, 0, mips_cp1_names_numeric,
    492  1.5  christos     mips_hwr_names_numeric },
    493  1.5  christos   { "vr5400",	1, bfd_mach_mips5400, CPU_VR5400, ISA_MIPS4, 0,
    494  1.5  christos     mips_cp0_names_numeric, NULL, 0, mips_cp1_names_numeric,
    495  1.5  christos     mips_hwr_names_numeric },
    496  1.5  christos   { "vr5500",	1, bfd_mach_mips5500, CPU_VR5500, ISA_MIPS4, 0,
    497  1.5  christos     mips_cp0_names_numeric, NULL, 0, mips_cp1_names_numeric,
    498  1.5  christos     mips_hwr_names_numeric },
    499  1.5  christos   { "r5900",	1, bfd_mach_mips5900, CPU_R5900, ISA_MIPS3, 0,
    500  1.5  christos     mips_cp0_names_r5900, NULL, 0, mips_cp1_names_numeric,
    501  1.5  christos     mips_hwr_names_numeric },
    502  1.5  christos   { "r6000",	1, bfd_mach_mips6000, CPU_R6000, ISA_MIPS2, 0,
    503  1.5  christos     mips_cp0_names_numeric, NULL, 0, mips_cp1_names_numeric,
    504  1.5  christos     mips_hwr_names_numeric },
    505  1.5  christos   { "rm7000",	1, bfd_mach_mips7000, CPU_RM7000, ISA_MIPS4, 0,
    506  1.5  christos     mips_cp0_names_numeric, NULL, 0, mips_cp1_names_numeric,
    507  1.5  christos     mips_hwr_names_numeric },
    508  1.5  christos   { "rm9000",	1, bfd_mach_mips7000, CPU_RM7000, ISA_MIPS4, 0,
    509  1.5  christos     mips_cp0_names_numeric, NULL, 0, mips_cp1_names_numeric,
    510  1.5  christos     mips_hwr_names_numeric },
    511  1.5  christos   { "r8000",	1, bfd_mach_mips8000, CPU_R8000, ISA_MIPS4, 0,
    512  1.5  christos     mips_cp0_names_numeric, NULL, 0, mips_cp1_names_numeric,
    513  1.5  christos     mips_hwr_names_numeric },
    514  1.5  christos   { "r10000",	1, bfd_mach_mips10000, CPU_R10000, ISA_MIPS4, 0,
    515  1.5  christos     mips_cp0_names_numeric, NULL, 0, mips_cp1_names_numeric,
    516  1.5  christos     mips_hwr_names_numeric },
    517  1.5  christos   { "r12000",	1, bfd_mach_mips12000, CPU_R12000, ISA_MIPS4, 0,
    518  1.5  christos     mips_cp0_names_numeric, NULL, 0, mips_cp1_names_numeric,
    519  1.5  christos     mips_hwr_names_numeric },
    520  1.5  christos   { "r14000",	1, bfd_mach_mips14000, CPU_R14000, ISA_MIPS4, 0,
    521  1.5  christos     mips_cp0_names_numeric, NULL, 0, mips_cp1_names_numeric,
    522  1.5  christos     mips_hwr_names_numeric },
    523  1.5  christos   { "r16000",	1, bfd_mach_mips16000, CPU_R16000, ISA_MIPS4, 0,
    524  1.5  christos     mips_cp0_names_numeric, NULL, 0, mips_cp1_names_numeric,
    525  1.5  christos     mips_hwr_names_numeric },
    526  1.5  christos   { "mips5",	1, bfd_mach_mips5, CPU_MIPS5, ISA_MIPS5, 0,
    527  1.5  christos     mips_cp0_names_numeric, NULL, 0, mips_cp1_names_numeric,
    528  1.1     skrll     mips_hwr_names_numeric },
    529  1.1     skrll 
    530  1.1     skrll   /* For stock MIPS32, disassemble all applicable MIPS-specified ASEs.
    531  1.1     skrll      Note that MIPS-3D and MDMX are not applicable to MIPS32.  (See
    532  1.1     skrll      _MIPS32 Architecture For Programmers Volume I: Introduction to the
    533  1.1     skrll      MIPS32 Architecture_ (MIPS Document Number MD00082, Revision 0.95),
    534  1.1     skrll      page 1.  */
    535  1.5  christos   { "mips32",	1, bfd_mach_mipsisa32, CPU_MIPS32,
    536  1.1     skrll     ISA_MIPS32,  ASE_SMARTMIPS,
    537  1.1     skrll     mips_cp0_names_mips3264,
    538  1.5  christos     mips_cp0sel_names_mips3264, ARRAY_SIZE (mips_cp0sel_names_mips3264),
    539  1.1     skrll     mips_cp1_names_mips3264, mips_hwr_names_numeric },
    540  1.1     skrll 
    541  1.5  christos   { "mips32r2",	1, bfd_mach_mipsisa32r2, CPU_MIPS32R2,
    542  1.5  christos     ISA_MIPS32R2,
    543  1.5  christos     (ASE_SMARTMIPS | ASE_DSP | ASE_DSPR2 | ASE_EVA | ASE_MIPS3D
    544  1.5  christos      | ASE_MT | ASE_MCU | ASE_VIRT | ASE_MSA | ASE_XPA),
    545  1.5  christos     mips_cp0_names_mips3264r2,
    546  1.5  christos     mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2),
    547  1.5  christos     mips_cp1_names_mips3264, mips_hwr_names_mips3264r2 },
    548  1.5  christos 
    549  1.5  christos   { "mips32r3",	1, bfd_mach_mipsisa32r3, CPU_MIPS32R3,
    550  1.5  christos     ISA_MIPS32R3,
    551  1.5  christos     (ASE_SMARTMIPS | ASE_DSP | ASE_DSPR2 | ASE_EVA | ASE_MIPS3D
    552  1.5  christos      | ASE_MT | ASE_MCU | ASE_VIRT | ASE_MSA | ASE_XPA),
    553  1.5  christos     mips_cp0_names_mips3264r2,
    554  1.5  christos     mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2),
    555  1.5  christos     mips_cp1_names_mips3264, mips_hwr_names_mips3264r2 },
    556  1.5  christos 
    557  1.5  christos   { "mips32r5",	1, bfd_mach_mipsisa32r5, CPU_MIPS32R5,
    558  1.5  christos     ISA_MIPS32R5,
    559  1.5  christos     (ASE_SMARTMIPS | ASE_DSP | ASE_DSPR2 | ASE_EVA | ASE_MIPS3D
    560  1.5  christos      | ASE_MT | ASE_MCU | ASE_VIRT | ASE_MSA | ASE_XPA),
    561  1.5  christos     mips_cp0_names_mips3264r2,
    562  1.5  christos     mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2),
    563  1.5  christos     mips_cp1_names_mips3264, mips_hwr_names_mips3264r2 },
    564  1.5  christos 
    565  1.5  christos   { "mips32r6",	1, bfd_mach_mipsisa32r6, CPU_MIPS32R6,
    566  1.5  christos     ISA_MIPS32R6,
    567  1.8  christos     (ASE_EVA | ASE_MSA | ASE_VIRT | ASE_XPA | ASE_MCU | ASE_MT | ASE_DSP
    568  1.1     skrll      | ASE_DSPR2 | ASE_DSPR3 | ASE_CRC | ASE_GINV),
    569  1.1     skrll     mips_cp0_names_mips3264r2,
    570  1.5  christos     mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2),
    571  1.1     skrll     mips_cp1_names_mips3264, mips_hwr_names_mips3264r2 },
    572  1.1     skrll 
    573  1.1     skrll   /* For stock MIPS64, disassemble all applicable MIPS-specified ASEs.  */
    574  1.5  christos   { "mips64",	1, bfd_mach_mipsisa64, CPU_MIPS64,
    575  1.1     skrll     ISA_MIPS64,  ASE_MIPS3D | ASE_MDMX,
    576  1.1     skrll     mips_cp0_names_mips3264,
    577  1.5  christos     mips_cp0sel_names_mips3264, ARRAY_SIZE (mips_cp0sel_names_mips3264),
    578  1.1     skrll     mips_cp1_names_mips3264, mips_hwr_names_numeric },
    579  1.1     skrll 
    580  1.5  christos   { "mips64r2",	1, bfd_mach_mipsisa64r2, CPU_MIPS64R2,
    581  1.5  christos     ISA_MIPS64R2,
    582  1.5  christos     (ASE_MIPS3D | ASE_DSP | ASE_DSPR2 | ASE_DSP64 | ASE_EVA | ASE_MT
    583  1.5  christos      | ASE_MCU | ASE_VIRT | ASE_VIRT64 | ASE_MSA | ASE_MSA64 | ASE_XPA),
    584  1.5  christos     mips_cp0_names_mips3264r2,
    585  1.5  christos     mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2),
    586  1.5  christos     mips_cp1_names_mips3264, mips_hwr_names_mips3264r2 },
    587  1.5  christos 
    588  1.5  christos   { "mips64r3",	1, bfd_mach_mipsisa64r3, CPU_MIPS64R3,
    589  1.5  christos     ISA_MIPS64R3,
    590  1.5  christos     (ASE_MIPS3D | ASE_DSP | ASE_DSPR2 | ASE_DSP64 | ASE_EVA | ASE_MT
    591  1.5  christos      | ASE_MCU | ASE_VIRT | ASE_VIRT64 | ASE_MSA | ASE_MSA64 | ASE_XPA),
    592  1.5  christos     mips_cp0_names_mips3264r2,
    593  1.5  christos     mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2),
    594  1.5  christos     mips_cp1_names_mips3264, mips_hwr_names_mips3264r2 },
    595  1.5  christos 
    596  1.5  christos   { "mips64r5",	1, bfd_mach_mipsisa64r5, CPU_MIPS64R5,
    597  1.5  christos     ISA_MIPS64R5,
    598  1.5  christos     (ASE_MIPS3D | ASE_DSP | ASE_DSPR2 | ASE_DSP64 | ASE_EVA | ASE_MT
    599  1.5  christos      | ASE_MCU | ASE_VIRT | ASE_VIRT64 | ASE_MSA | ASE_MSA64 | ASE_XPA),
    600  1.5  christos     mips_cp0_names_mips3264r2,
    601  1.5  christos     mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2),
    602  1.5  christos     mips_cp1_names_mips3264, mips_hwr_names_mips3264r2 },
    603  1.5  christos 
    604  1.5  christos   { "mips64r6",	1, bfd_mach_mipsisa64r6, CPU_MIPS64R6,
    605  1.5  christos     ISA_MIPS64R6,
    606  1.8  christos     (ASE_EVA | ASE_MSA | ASE_MSA64 | ASE_XPA | ASE_VIRT | ASE_VIRT64
    607  1.8  christos      | ASE_MCU | ASE_MT | ASE_DSP | ASE_DSPR2 | ASE_DSPR3 | ASE_CRC
    608  1.1     skrll      | ASE_CRC64 | ASE_GINV),
    609  1.1     skrll     mips_cp0_names_mips3264r2,
    610  1.5  christos     mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2),
    611  1.1     skrll     mips_cp1_names_mips3264, mips_hwr_names_mips3264r2 },
    612  1.7  christos 
    613  1.7  christos   { "interaptiv-mr2",	1, bfd_mach_mips_interaptiv_mr2, CPU_INTERAPTIV_MR2,
    614  1.7  christos     ISA_MIPS32R3,
    615  1.7  christos     ASE_MT | ASE_EVA | ASE_DSP | ASE_DSPR2 | ASE_MIPS16E2 | ASE_MIPS16E2_MT,
    616  1.7  christos     mips_cp0_names_mips3264r2,
    617  1.7  christos     mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2),
    618  1.7  christos     mips_cp1_names_mips3264, mips_hwr_names_mips3264r2 },
    619  1.1     skrll 
    620  1.5  christos   { "sb1",	1, bfd_mach_mips_sb1, CPU_SB1,
    621  1.1     skrll     ISA_MIPS64 | INSN_SB1,  ASE_MIPS3D,
    622  1.1     skrll     mips_cp0_names_sb1,
    623  1.5  christos     mips_cp0sel_names_sb1, ARRAY_SIZE (mips_cp0sel_names_sb1),
    624  1.1     skrll     mips_cp1_names_mips3264, mips_hwr_names_numeric },
    625  1.1     skrll 
    626  1.5  christos   { "loongson2e",   1, bfd_mach_mips_loongson_2e, CPU_LOONGSON_2E,
    627  1.5  christos     ISA_MIPS3 | INSN_LOONGSON_2E, 0, mips_cp0_names_numeric,
    628  1.1     skrll     NULL, 0, mips_cp1_names_numeric, mips_hwr_names_numeric },
    629  1.1     skrll 
    630  1.9  christos   { "loongson2f",   1, bfd_mach_mips_loongson_2f, CPU_LOONGSON_2F,
    631  1.5  christos     ISA_MIPS3 | INSN_LOONGSON_2F, ASE_LOONGSON_MMI, mips_cp0_names_numeric,
    632  1.1     skrll     NULL, 0, mips_cp1_names_numeric, mips_hwr_names_numeric },
    633  1.9  christos 
    634  1.9  christos   /* The loongson3a is an alias of gs464 for compatibility */
    635  1.9  christos   { "loongson3a",   1, bfd_mach_mips_gs464, CPU_GS464,
    636  1.9  christos     ISA_MIPS64R2, ASE_LOONGSON_MMI | ASE_LOONGSON_CAM | ASE_LOONGSON_EXT,
    637  1.9  christos     mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips3264,
    638  1.9  christos     mips_hwr_names_numeric },
    639  1.9  christos 
    640  1.9  christos   { "gs464",   1, bfd_mach_mips_gs464, CPU_GS464,
    641  1.9  christos     ISA_MIPS64R2, ASE_LOONGSON_MMI | ASE_LOONGSON_CAM | ASE_LOONGSON_EXT,
    642  1.9  christos     mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips3264,
    643  1.9  christos     mips_hwr_names_numeric },
    644  1.9  christos 
    645  1.9  christos   { "gs464e",   1, bfd_mach_mips_gs464e, CPU_GS464E,
    646  1.9  christos     ISA_MIPS64R2, ASE_LOONGSON_MMI | ASE_LOONGSON_CAM | ASE_LOONGSON_EXT
    647  1.9  christos     | ASE_LOONGSON_EXT2, mips_cp0_names_numeric, NULL, 0, mips_cp1_names_mips3264,
    648  1.9  christos     mips_hwr_names_numeric },
    649  1.9  christos 
    650  1.9  christos   { "gs264e",   1, bfd_mach_mips_gs464e, CPU_GS264E,
    651  1.9  christos     ISA_MIPS64R2, ASE_LOONGSON_MMI | ASE_LOONGSON_CAM | ASE_LOONGSON_EXT
    652  1.9  christos     | ASE_LOONGSON_EXT2 | ASE_MSA | ASE_MSA64, mips_cp0_names_numeric, NULL,
    653  1.4  christos     0, mips_cp1_names_mips3264, mips_hwr_names_numeric },
    654  1.1     skrll 
    655  1.5  christos   { "octeon",   1, bfd_mach_mips_octeon, CPU_OCTEON,
    656  1.5  christos     ISA_MIPS64R2 | INSN_OCTEON, 0, mips_cp0_names_numeric, NULL, 0,
    657  1.1     skrll     mips_cp1_names_mips3264, mips_hwr_names_numeric },
    658  1.4  christos 
    659  1.5  christos   { "octeon+",   1, bfd_mach_mips_octeonp, CPU_OCTEONP,
    660  1.5  christos     ISA_MIPS64R2 | INSN_OCTEONP, 0, mips_cp0_names_numeric,
    661  1.4  christos     NULL, 0, mips_cp1_names_mips3264, mips_hwr_names_numeric },
    662  1.4  christos 
    663  1.5  christos   { "octeon2",   1, bfd_mach_mips_octeon2, CPU_OCTEON2,
    664  1.5  christos     ISA_MIPS64R2 | INSN_OCTEON2, 0, mips_cp0_names_numeric,
    665  1.5  christos     NULL, 0, mips_cp1_names_mips3264, mips_hwr_names_numeric },
    666  1.5  christos 
    667  1.5  christos   { "octeon3",   1, bfd_mach_mips_octeon3, CPU_OCTEON3,
    668  1.5  christos     ISA_MIPS64R5 | INSN_OCTEON3, ASE_VIRT | ASE_VIRT64,
    669  1.5  christos     mips_cp0_names_numeric,
    670  1.4  christos     NULL, 0, mips_cp1_names_mips3264, mips_hwr_names_numeric },
    671  1.2      matt 
    672  1.5  christos   { "xlr", 1, bfd_mach_mips_xlr, CPU_XLR,
    673  1.2      matt     ISA_MIPS64 | INSN_XLR, 0,
    674  1.2      matt     mips_cp0_names_xlr,
    675  1.5  christos     mips_cp0sel_names_xlr, ARRAY_SIZE (mips_cp0sel_names_xlr),
    676  1.2      matt     mips_cp1_names_mips3264, mips_hwr_names_numeric },
    677  1.4  christos 
    678  1.4  christos   /* XLP is mostly like XLR, with the prominent exception it is being
    679  1.4  christos      MIPS64R2.  */
    680  1.5  christos   { "xlp", 1, bfd_mach_mips_xlr, CPU_XLR,
    681  1.4  christos     ISA_MIPS64R2 | INSN_XLR, 0,
    682  1.4  christos     mips_cp0_names_xlr,
    683  1.5  christos     mips_cp0sel_names_xlr, ARRAY_SIZE (mips_cp0sel_names_xlr),
    684  1.4  christos     mips_cp1_names_mips3264, mips_hwr_names_numeric },
    685  1.1     skrll 
    686  1.1     skrll   /* This entry, mips16, is here only for ISA/processor selection; do
    687  1.7  christos      not print its name.  */
    688  1.7  christos   { "",		1, bfd_mach_mips16, CPU_MIPS16, ISA_MIPS64,
    689  1.5  christos     ASE_MIPS16E2 | ASE_MIPS16E2_MT,
    690  1.5  christos     mips_cp0_names_numeric, NULL, 0, mips_cp1_names_numeric,
    691  1.1     skrll     mips_hwr_names_numeric },
    692  1.1     skrll };
    693  1.1     skrll 
    694  1.1     skrll /* ISA and processor type to disassemble for, and register names to use.
    695  1.1     skrll    set_default_mips_dis_options and parse_mips_dis_options fill in these
    696  1.1     skrll    values.  */
    697  1.1     skrll static int mips_processor;
    698  1.5  christos static int mips_isa;
    699  1.4  christos static int mips_ase;
    700  1.1     skrll static int micromips_ase;
    701  1.1     skrll static const char * const *mips_gpr_names;
    702  1.1     skrll static const char * const *mips_fpr_names;
    703  1.1     skrll static const char * const *mips_cp0_names;
    704  1.1     skrll static const struct mips_cp0sel_name *mips_cp0sel_names;
    705  1.5  christos static int mips_cp0sel_names_len;
    706  1.1     skrll static const char * const *mips_cp1_names;
    707  1.1     skrll static const char * const *mips_hwr_names;
    708  1.1     skrll 
    709  1.1     skrll /* Other options */
    710  1.1     skrll static int no_aliases;	/* If set disassemble as most general inst.  */
    711  1.1     skrll 
    712  1.1     skrll static const struct mips_abi_choice *
    714  1.1     skrll choose_abi_by_name (const char *name, unsigned int namelen)
    715  1.1     skrll {
    716  1.1     skrll   const struct mips_abi_choice *c;
    717  1.1     skrll   unsigned int i;
    718  1.1     skrll 
    719  1.1     skrll   for (i = 0, c = NULL; i < ARRAY_SIZE (mips_abi_choices) && c == NULL; i++)
    720  1.1     skrll     if (strncmp (mips_abi_choices[i].name, name, namelen) == 0
    721  1.1     skrll 	&& strlen (mips_abi_choices[i].name) == namelen)
    722  1.1     skrll       c = &mips_abi_choices[i];
    723  1.1     skrll 
    724  1.1     skrll   return c;
    725  1.1     skrll }
    726  1.1     skrll 
    727  1.1     skrll static const struct mips_arch_choice *
    728  1.1     skrll choose_arch_by_name (const char *name, unsigned int namelen)
    729  1.1     skrll {
    730  1.1     skrll   const struct mips_arch_choice *c = NULL;
    731  1.1     skrll   unsigned int i;
    732  1.1     skrll 
    733  1.1     skrll   for (i = 0, c = NULL; i < ARRAY_SIZE (mips_arch_choices) && c == NULL; i++)
    734  1.1     skrll     if (strncmp (mips_arch_choices[i].name, name, namelen) == 0
    735  1.1     skrll 	&& strlen (mips_arch_choices[i].name) == namelen)
    736  1.1     skrll       c = &mips_arch_choices[i];
    737  1.1     skrll 
    738  1.1     skrll   return c;
    739  1.1     skrll }
    740  1.1     skrll 
    741  1.1     skrll static const struct mips_arch_choice *
    742  1.1     skrll choose_arch_by_number (unsigned long mach)
    743  1.1     skrll {
    744  1.1     skrll   static unsigned long hint_bfd_mach;
    745  1.1     skrll   static const struct mips_arch_choice *hint_arch_choice;
    746  1.1     skrll   const struct mips_arch_choice *c;
    747  1.1     skrll   unsigned int i;
    748  1.1     skrll 
    749  1.1     skrll   /* We optimize this because even if the user specifies no
    750  1.1     skrll      flags, this will be done for every instruction!  */
    751  1.1     skrll   if (hint_bfd_mach == mach
    752  1.1     skrll       && hint_arch_choice != NULL
    753  1.1     skrll       && hint_arch_choice->bfd_mach == hint_bfd_mach)
    754  1.1     skrll     return hint_arch_choice;
    755  1.1     skrll 
    756  1.1     skrll   for (i = 0, c = NULL; i < ARRAY_SIZE (mips_arch_choices) && c == NULL; i++)
    757  1.1     skrll     {
    758  1.1     skrll       if (mips_arch_choices[i].bfd_mach_valid
    759  1.1     skrll 	  && mips_arch_choices[i].bfd_mach == mach)
    760  1.1     skrll 	{
    761  1.1     skrll 	  c = &mips_arch_choices[i];
    762  1.1     skrll 	  hint_bfd_mach = mach;
    763  1.1     skrll 	  hint_arch_choice = c;
    764  1.1     skrll 	}
    765  1.1     skrll     }
    766  1.1     skrll   return c;
    767  1.1     skrll }
    768  1.1     skrll 
    769  1.1     skrll /* Check if the object uses NewABI conventions.  */
    770  1.1     skrll 
    771  1.1     skrll static int
    772  1.1     skrll is_newabi (Elf_Internal_Ehdr *header)
    773  1.1     skrll {
    774  1.1     skrll   /* There are no old-style ABIs which use 64-bit ELF.  */
    775  1.1     skrll   if (header->e_ident[EI_CLASS] == ELFCLASS64)
    776  1.1     skrll     return 1;
    777  1.1     skrll 
    778  1.1     skrll   /* If a 32-bit ELF file, n32 is a new-style ABI.  */
    779  1.1     skrll   if ((header->e_flags & EF_MIPS_ABI2) != 0)
    780  1.1     skrll     return 1;
    781  1.1     skrll 
    782  1.1     skrll   return 0;
    783  1.4  christos }
    784  1.4  christos 
    785  1.4  christos /* Check if the object has microMIPS ASE code.  */
    786  1.4  christos 
    787  1.4  christos static int
    788  1.4  christos is_micromips (Elf_Internal_Ehdr *header)
    789  1.4  christos {
    790  1.4  christos   if ((header->e_flags & EF_MIPS_ARCH_ASE_MICROMIPS) != 0)
    791  1.4  christos     return 1;
    792  1.4  christos 
    793  1.4  christos   return 0;
    794  1.7  christos }
    795  1.7  christos 
    796  1.7  christos /* Convert ASE flags from .MIPS.abiflags to internal values.  */
    797  1.7  christos 
    798  1.7  christos static unsigned long
    799  1.7  christos mips_convert_abiflags_ases (unsigned long afl_ases)
    800  1.7  christos {
    801  1.7  christos   unsigned long opcode_ases = 0;
    802  1.7  christos 
    803  1.7  christos   if (afl_ases & AFL_ASE_DSP)
    804  1.7  christos     opcode_ases |= ASE_DSP;
    805  1.7  christos   if (afl_ases & AFL_ASE_DSPR2)
    806  1.7  christos     opcode_ases |= ASE_DSPR2;
    807  1.7  christos   if (afl_ases & AFL_ASE_EVA)
    808  1.7  christos     opcode_ases |= ASE_EVA;
    809  1.7  christos   if (afl_ases & AFL_ASE_MCU)
    810  1.7  christos     opcode_ases |= ASE_MCU;
    811  1.7  christos   if (afl_ases & AFL_ASE_MDMX)
    812  1.7  christos     opcode_ases |= ASE_MDMX;
    813  1.7  christos   if (afl_ases & AFL_ASE_MIPS3D)
    814  1.7  christos     opcode_ases |= ASE_MIPS3D;
    815  1.7  christos   if (afl_ases & AFL_ASE_MT)
    816  1.7  christos     opcode_ases |= ASE_MT;
    817  1.7  christos   if (afl_ases & AFL_ASE_SMARTMIPS)
    818  1.7  christos     opcode_ases |= ASE_SMARTMIPS;
    819  1.7  christos   if (afl_ases & AFL_ASE_VIRT)
    820  1.7  christos     opcode_ases |= ASE_VIRT;
    821  1.7  christos   if (afl_ases & AFL_ASE_MSA)
    822  1.7  christos     opcode_ases |= ASE_MSA;
    823  1.7  christos   if (afl_ases & AFL_ASE_XPA)
    824  1.7  christos     opcode_ases |= ASE_XPA;
    825  1.7  christos   if (afl_ases & AFL_ASE_DSPR3)
    826  1.7  christos     opcode_ases |= ASE_DSPR3;
    827  1.7  christos   if (afl_ases & AFL_ASE_MIPS16E2)
    828  1.7  christos     opcode_ases |= ASE_MIPS16E2;
    829  1.7  christos   return opcode_ases;
    830  1.7  christos }
    831  1.7  christos 
    832  1.7  christos /* Calculate combination ASE flags from regular ASE flags.  */
    833  1.9  christos 
    834  1.7  christos static unsigned long
    835  1.7  christos mips_calculate_combination_ases (int opcode_isa, unsigned long opcode_ases)
    836  1.7  christos {
    837  1.7  christos   unsigned long combination_ases = 0;
    838  1.7  christos 
    839  1.7  christos   if ((opcode_ases & (ASE_XPA | ASE_VIRT)) == (ASE_XPA | ASE_VIRT))
    840  1.7  christos     combination_ases |= ASE_XPA_VIRT;
    841  1.9  christos   if ((opcode_ases & (ASE_MIPS16E2 | ASE_MT)) == (ASE_MIPS16E2 | ASE_MT))
    842  1.9  christos     combination_ases |= ASE_MIPS16E2_MT;
    843  1.9  christos   if ((opcode_ases & ASE_EVA)
    844  1.9  christos       && ((opcode_isa & INSN_ISA_MASK) == ISA_MIPS64R6
    845  1.7  christos 	  || (opcode_isa & INSN_ISA_MASK) == ISA_MIPS32R6))
    846  1.7  christos     combination_ases |= ASE_EVA_R6;
    847  1.7  christos   return combination_ases;
    848  1.1     skrll }
    849  1.1     skrll 
    850  1.1     skrll static void
    851  1.1     skrll set_default_mips_dis_options (struct disassemble_info *info)
    852  1.1     skrll {
    853  1.4  christos   const struct mips_arch_choice *chosen_arch;
    854  1.4  christos 
    855  1.4  christos   /* Defaults: mipsIII/r3000 (?!), no microMIPS ASE (any compressed code
    856  1.1     skrll      is MIPS16 ASE) (o)32-style ("oldabi") GPR names, and numeric FPR,
    857  1.4  christos      CP0 register, and HWR names.  */
    858  1.4  christos   mips_isa = ISA_MIPS3;
    859  1.5  christos   mips_processor = CPU_R3000;
    860  1.1     skrll   micromips_ase = 0;
    861  1.1     skrll   mips_ase = 0;
    862  1.1     skrll   mips_gpr_names = mips_gpr_names_oldabi;
    863  1.1     skrll   mips_fpr_names = mips_fpr_names_numeric;
    864  1.1     skrll   mips_cp0_names = mips_cp0_names_numeric;
    865  1.5  christos   mips_cp0sel_names = NULL;
    866  1.1     skrll   mips_cp0sel_names_len = 0;
    867  1.1     skrll   mips_cp1_names = mips_cp1_names_numeric;
    868  1.1     skrll   mips_hwr_names = mips_hwr_names_numeric;
    869  1.1     skrll   no_aliases = 0;
    870  1.1     skrll 
    871  1.1     skrll   /* Set ISA, architecture, and cp0 register names as best we can.  */
    872  1.1     skrll #if ! SYMTAB_AVAILABLE
    873  1.1     skrll   /* This is running out on a target machine, not in a host tool.
    874  1.1     skrll      FIXME: Where does mips_target_info come from?  */
    875  1.5  christos   target_processor = mips_target_info.processor;
    876  1.1     skrll   mips_isa = mips_target_info.isa;
    877  1.1     skrll   mips_ase = mips_target_info.ase;
    878  1.1     skrll #else
    879  1.1     skrll   chosen_arch = choose_arch_by_number (info->mach);
    880  1.1     skrll   if (chosen_arch != NULL)
    881  1.1     skrll     {
    882  1.5  christos       mips_processor = chosen_arch->processor;
    883  1.1     skrll       mips_isa = chosen_arch->isa;
    884  1.1     skrll       mips_ase = chosen_arch->ase;
    885  1.1     skrll       mips_cp0_names = chosen_arch->cp0_names;
    886  1.5  christos       mips_cp0sel_names = chosen_arch->cp0sel_names;
    887  1.1     skrll       mips_cp0sel_names_len = chosen_arch->cp0sel_names_len;
    888  1.1     skrll       mips_cp1_names = chosen_arch->cp1_names;
    889  1.7  christos       mips_hwr_names = chosen_arch->hwr_names;
    890  1.7  christos     }
    891  1.7  christos 
    892  1.7  christos   /* Update settings according to the ELF file header flags.  */
    893  1.7  christos   if (info->flavour == bfd_target_elf_flavour && info->section != NULL)
    894  1.7  christos     {
    895  1.7  christos       struct bfd *abfd = info->section->owner;
    896  1.7  christos       Elf_Internal_Ehdr *header = elf_elfheader (abfd);
    897  1.7  christos       Elf_Internal_ABIFlags_v0 *abiflags = NULL;
    898  1.7  christos 
    899  1.7  christos       /* We won't ever get here if !HAVE_BFD_MIPS_ELF_GET_ABIFLAGS,
    900  1.7  christos 	 because we won't then have a MIPS/ELF BFD, however we need
    901  1.7  christos 	 to guard against a link error in a `--enable-targets=...'
    902  1.7  christos 	 configuration with a 32-bit host where the MIPS target is
    903  1.7  christos 	 a secondary, or with MIPS/ECOFF configurations.  */
    904  1.1     skrll #ifdef HAVE_BFD_MIPS_ELF_GET_ABIFLAGS
    905  1.7  christos       abiflags = bfd_mips_elf_get_abiflags (abfd);
    906  1.7  christos #endif
    907  1.7  christos       /* If an ELF "newabi" binary, use the n32/(n)64 GPR names.  */
    908  1.7  christos       if (is_newabi (header))
    909  1.7  christos 	mips_gpr_names = mips_gpr_names_newabi;
    910  1.7  christos       /* If a microMIPS binary, then don't use MIPS16 bindings.  */
    911  1.7  christos       micromips_ase = is_micromips (header);
    912  1.7  christos       /* OR in any extra ASE flags set in ELF file structures.  */
    913  1.7  christos       if (abiflags)
    914  1.7  christos 	mips_ase |= mips_convert_abiflags_ases (abiflags->ases);
    915  1.7  christos       else if (header->e_flags & EF_MIPS_ARCH_ASE_MDMX)
    916  1.7  christos 	mips_ase |= ASE_MDMX;
    917  1.9  christos     }
    918  1.1     skrll #endif
    919  1.1     skrll   mips_ase |= mips_calculate_combination_ases (mips_isa, mips_ase);
    920  1.7  christos }
    921  1.7  christos 
    922  1.7  christos /* Parse an ASE disassembler option and set the corresponding global
    923  1.7  christos    ASE flag(s).  Return TRUE if successful, FALSE otherwise.  */
    924  1.7  christos 
    925  1.1     skrll static bfd_boolean
    926  1.5  christos parse_mips_ase_option (const char *option)
    927  1.5  christos {
    928  1.5  christos   if (CONST_STRNEQ (option, "msa"))
    929  1.5  christos     {
    930  1.5  christos       mips_ase |= ASE_MSA;
    931  1.5  christos       if ((mips_isa & INSN_ISA_MASK) == ISA_MIPS64R2
    932  1.5  christos 	   || (mips_isa & INSN_ISA_MASK) == ISA_MIPS64R3
    933  1.5  christos 	   || (mips_isa & INSN_ISA_MASK) == ISA_MIPS64R5
    934  1.7  christos 	   || (mips_isa & INSN_ISA_MASK) == ISA_MIPS64R6)
    935  1.5  christos 	  mips_ase |= ASE_MSA64;
    936  1.5  christos       return TRUE;
    937  1.5  christos     }
    938  1.5  christos 
    939  1.5  christos   if (CONST_STRNEQ (option, "virt"))
    940  1.5  christos     {
    941  1.5  christos       mips_ase |= ASE_VIRT;
    942  1.5  christos       if (mips_isa & ISA_MIPS64R2
    943  1.5  christos 	  || mips_isa & ISA_MIPS64R3
    944  1.5  christos 	  || mips_isa & ISA_MIPS64R5
    945  1.7  christos 	  || mips_isa & ISA_MIPS64R6)
    946  1.5  christos 	mips_ase |= ASE_VIRT64;
    947  1.5  christos       return TRUE;
    948  1.5  christos     }
    949  1.5  christos 
    950  1.5  christos   if (CONST_STRNEQ (option, "xpa"))
    951  1.7  christos     {
    952  1.7  christos       mips_ase |= ASE_XPA;
    953  1.7  christos       return TRUE;
    954  1.8  christos     }
    955  1.8  christos 
    956  1.8  christos   if (CONST_STRNEQ (option, "ginv"))
    957  1.8  christos     {
    958  1.8  christos       mips_ase |= ASE_GINV;
    959  1.8  christos       return TRUE;
    960  1.9  christos     }
    961  1.9  christos 
    962  1.9  christos   if (CONST_STRNEQ (option, "loongson-mmi"))
    963  1.9  christos     {
    964  1.9  christos       mips_ase |= ASE_LOONGSON_MMI;
    965  1.9  christos       return TRUE;
    966  1.9  christos     }
    967  1.9  christos 
    968  1.9  christos   if (CONST_STRNEQ (option, "loongson-cam"))
    969  1.9  christos     {
    970  1.9  christos       mips_ase |= ASE_LOONGSON_CAM;
    971  1.9  christos       return TRUE;
    972  1.9  christos     }
    973  1.9  christos 
    974  1.9  christos   /* Put here for match ext2 frist */
    975  1.9  christos   if (CONST_STRNEQ (option, "loongson-ext2"))
    976  1.9  christos     {
    977  1.9  christos       mips_ase |= ASE_LOONGSON_EXT2;
    978  1.9  christos       return TRUE;
    979  1.9  christos     }
    980  1.9  christos 
    981  1.9  christos   if (CONST_STRNEQ (option, "loongson-ext"))
    982  1.9  christos     {
    983  1.9  christos       mips_ase |= ASE_LOONGSON_EXT;
    984  1.9  christos       return TRUE;
    985  1.7  christos     }
    986  1.7  christos 
    987  1.7  christos   return FALSE;
    988  1.7  christos }
    989  1.7  christos 
    990  1.7  christos static void
    991  1.7  christos parse_mips_dis_option (const char *option, unsigned int len)
    992  1.7  christos {
    993  1.7  christos   unsigned int i, optionlen, vallen;
    994  1.7  christos   const char *val;
    995  1.7  christos   const struct mips_abi_choice *chosen_abi;
    996  1.7  christos   const struct mips_arch_choice *chosen_arch;
    997  1.7  christos 
    998  1.7  christos   /* Try to match options that are simple flags */
    999  1.7  christos   if (CONST_STRNEQ (option, "no-aliases"))
   1000  1.5  christos     {
   1001  1.5  christos       no_aliases = 1;
   1002  1.5  christos       return;
   1003  1.7  christos     }
   1004  1.7  christos 
   1005  1.9  christos   if (parse_mips_ase_option (option))
   1006  1.7  christos     {
   1007  1.7  christos       mips_ase |= mips_calculate_combination_ases (mips_isa, mips_ase);
   1008  1.5  christos       return;
   1009  1.1     skrll     }
   1010  1.1     skrll 
   1011  1.1     skrll   /* Look for the = that delimits the end of the option name.  */
   1012  1.1     skrll   for (i = 0; i < len; i++)
   1013  1.1     skrll     if (option[i] == '=')
   1014  1.1     skrll       break;
   1015  1.1     skrll 
   1016  1.1     skrll   if (i == 0)		/* Invalid option: no name before '='.  */
   1017  1.1     skrll     return;
   1018  1.1     skrll   if (i == len)		/* Invalid option: no '='.  */
   1019  1.1     skrll     return;
   1020  1.1     skrll   if (i == (len - 1))	/* Invalid option: no value after '='.  */
   1021  1.1     skrll     return;
   1022  1.1     skrll 
   1023  1.1     skrll   optionlen = i;
   1024  1.1     skrll   val = option + (optionlen + 1);
   1025  1.1     skrll   vallen = len - (optionlen + 1);
   1026  1.1     skrll 
   1027  1.1     skrll   if (strncmp ("gpr-names", option, optionlen) == 0
   1028  1.1     skrll       && strlen ("gpr-names") == optionlen)
   1029  1.1     skrll     {
   1030  1.1     skrll       chosen_abi = choose_abi_by_name (val, vallen);
   1031  1.1     skrll       if (chosen_abi != NULL)
   1032  1.1     skrll 	mips_gpr_names = chosen_abi->gpr_names;
   1033  1.1     skrll       return;
   1034  1.1     skrll     }
   1035  1.1     skrll 
   1036  1.1     skrll   if (strncmp ("fpr-names", option, optionlen) == 0
   1037  1.1     skrll       && strlen ("fpr-names") == optionlen)
   1038  1.1     skrll     {
   1039  1.1     skrll       chosen_abi = choose_abi_by_name (val, vallen);
   1040  1.1     skrll       if (chosen_abi != NULL)
   1041  1.1     skrll 	mips_fpr_names = chosen_abi->fpr_names;
   1042  1.1     skrll       return;
   1043  1.1     skrll     }
   1044  1.1     skrll 
   1045  1.1     skrll   if (strncmp ("cp0-names", option, optionlen) == 0
   1046  1.1     skrll       && strlen ("cp0-names") == optionlen)
   1047  1.1     skrll     {
   1048  1.1     skrll       chosen_arch = choose_arch_by_name (val, vallen);
   1049  1.1     skrll       if (chosen_arch != NULL)
   1050  1.1     skrll 	{
   1051  1.1     skrll 	  mips_cp0_names = chosen_arch->cp0_names;
   1052  1.1     skrll 	  mips_cp0sel_names = chosen_arch->cp0sel_names;
   1053  1.1     skrll 	  mips_cp0sel_names_len = chosen_arch->cp0sel_names_len;
   1054  1.1     skrll 	}
   1055  1.1     skrll       return;
   1056  1.5  christos     }
   1057  1.5  christos 
   1058  1.5  christos   if (strncmp ("cp1-names", option, optionlen) == 0
   1059  1.5  christos       && strlen ("cp1-names") == optionlen)
   1060  1.5  christos     {
   1061  1.5  christos       chosen_arch = choose_arch_by_name (val, vallen);
   1062  1.5  christos       if (chosen_arch != NULL)
   1063  1.5  christos 	mips_cp1_names = chosen_arch->cp1_names;
   1064  1.5  christos       return;
   1065  1.1     skrll     }
   1066  1.1     skrll 
   1067  1.1     skrll   if (strncmp ("hwr-names", option, optionlen) == 0
   1068  1.1     skrll       && strlen ("hwr-names") == optionlen)
   1069  1.1     skrll     {
   1070  1.1     skrll       chosen_arch = choose_arch_by_name (val, vallen);
   1071  1.1     skrll       if (chosen_arch != NULL)
   1072  1.1     skrll 	mips_hwr_names = chosen_arch->hwr_names;
   1073  1.1     skrll       return;
   1074  1.1     skrll     }
   1075  1.1     skrll 
   1076  1.1     skrll   if (strncmp ("reg-names", option, optionlen) == 0
   1077  1.1     skrll       && strlen ("reg-names") == optionlen)
   1078  1.1     skrll     {
   1079  1.1     skrll       /* We check both ABI and ARCH here unconditionally, so
   1080  1.1     skrll 	 that "numeric" will do the desirable thing: select
   1081  1.1     skrll 	 numeric register names for all registers.  Other than
   1082  1.1     skrll 	 that, a given name probably won't match both.  */
   1083  1.1     skrll       chosen_abi = choose_abi_by_name (val, vallen);
   1084  1.1     skrll       if (chosen_abi != NULL)
   1085  1.1     skrll 	{
   1086  1.1     skrll 	  mips_gpr_names = chosen_abi->gpr_names;
   1087  1.1     skrll 	  mips_fpr_names = chosen_abi->fpr_names;
   1088  1.1     skrll 	}
   1089  1.1     skrll       chosen_arch = choose_arch_by_name (val, vallen);
   1090  1.1     skrll       if (chosen_arch != NULL)
   1091  1.1     skrll 	{
   1092  1.1     skrll 	  mips_cp0_names = chosen_arch->cp0_names;
   1093  1.5  christos 	  mips_cp0sel_names = chosen_arch->cp0sel_names;
   1094  1.1     skrll 	  mips_cp0sel_names_len = chosen_arch->cp0sel_names_len;
   1095  1.1     skrll 	  mips_cp1_names = chosen_arch->cp1_names;
   1096  1.1     skrll 	  mips_hwr_names = chosen_arch->hwr_names;
   1097  1.1     skrll 	}
   1098  1.1     skrll       return;
   1099  1.1     skrll     }
   1100  1.1     skrll 
   1101  1.1     skrll   /* Invalid option.  */
   1102  1.1     skrll }
   1103  1.1     skrll 
   1104  1.1     skrll static void
   1105  1.1     skrll parse_mips_dis_options (const char *options)
   1106  1.1     skrll {
   1107  1.1     skrll   const char *option_end;
   1108  1.1     skrll 
   1109  1.1     skrll   if (options == NULL)
   1110  1.1     skrll     return;
   1111  1.1     skrll 
   1112  1.1     skrll   while (*options != '\0')
   1113  1.1     skrll     {
   1114  1.1     skrll       /* Skip empty options.  */
   1115  1.1     skrll       if (*options == ',')
   1116  1.1     skrll 	{
   1117  1.1     skrll 	  options++;
   1118  1.1     skrll 	  continue;
   1119  1.1     skrll 	}
   1120  1.1     skrll 
   1121  1.1     skrll       /* We know that *options is neither NUL or a comma.  */
   1122  1.1     skrll       option_end = options + 1;
   1123  1.1     skrll       while (*option_end != ',' && *option_end != '\0')
   1124  1.1     skrll 	option_end++;
   1125  1.1     skrll 
   1126  1.1     skrll       parse_mips_dis_option (options, option_end - options);
   1127  1.1     skrll 
   1128  1.1     skrll       /* Go on to the next one.  If option_end points to a comma, it
   1129  1.1     skrll 	 will be skipped above.  */
   1130  1.1     skrll       options = option_end;
   1131  1.1     skrll     }
   1132  1.1     skrll }
   1133  1.1     skrll 
   1134  1.1     skrll static const struct mips_cp0sel_name *
   1135  1.1     skrll lookup_mips_cp0sel_name (const struct mips_cp0sel_name *names,
   1136  1.1     skrll 			 unsigned int len,
   1137  1.1     skrll 			 unsigned int cp0reg,
   1138  1.1     skrll 			 unsigned int sel)
   1139  1.1     skrll {
   1140  1.1     skrll   unsigned int i;
   1141  1.1     skrll 
   1142  1.1     skrll   for (i = 0; i < len; i++)
   1143  1.1     skrll     if (names[i].cp0reg == cp0reg && names[i].sel == sel)
   1144  1.1     skrll       return &names[i];
   1145  1.5  christos   return NULL;
   1146  1.5  christos }
   1147  1.1     skrll 
   1148  1.1     skrll /* Print register REGNO, of type TYPE, for instruction OPCODE.  */
   1149  1.5  christos 
   1150  1.5  christos static void
   1151  1.1     skrll print_reg (struct disassemble_info *info, const struct mips_opcode *opcode,
   1152  1.5  christos 	   enum mips_reg_operand_type type, int regno)
   1153  1.5  christos {
   1154  1.5  christos   switch (type)
   1155  1.5  christos     {
   1156  1.5  christos     case OP_REG_GP:
   1157  1.5  christos       info->fprintf_func (info->stream, "%s", mips_gpr_names[regno]);
   1158  1.5  christos       break;
   1159  1.5  christos 
   1160  1.5  christos     case OP_REG_FP:
   1161  1.5  christos       info->fprintf_func (info->stream, "%s", mips_fpr_names[regno]);
   1162  1.5  christos       break;
   1163  1.5  christos 
   1164  1.5  christos     case OP_REG_CCC:
   1165  1.5  christos       if (opcode->pinfo & (FP_D | FP_S))
   1166  1.5  christos 	info->fprintf_func (info->stream, "$fcc%d", regno);
   1167  1.5  christos       else
   1168  1.1     skrll 	info->fprintf_func (info->stream, "$cc%d", regno);
   1169  1.5  christos       break;
   1170  1.5  christos 
   1171  1.5  christos     case OP_REG_VEC:
   1172  1.5  christos       if (opcode->membership & INSN_5400)
   1173  1.5  christos 	info->fprintf_func (info->stream, "$f%d", regno);
   1174  1.5  christos       else
   1175  1.1     skrll 	info->fprintf_func (info->stream, "$v%d", regno);
   1176  1.5  christos       break;
   1177  1.5  christos 
   1178  1.5  christos     case OP_REG_ACC:
   1179  1.1     skrll       info->fprintf_func (info->stream, "$ac%d", regno);
   1180  1.5  christos       break;
   1181  1.5  christos 
   1182  1.5  christos     case OP_REG_COPRO:
   1183  1.5  christos       if (opcode->name[strlen (opcode->name) - 1] == '0')
   1184  1.5  christos 	info->fprintf_func (info->stream, "%s", mips_cp0_names[regno]);
   1185  1.5  christos       else if (opcode->name[strlen (opcode->name) - 1] == '1')
   1186  1.5  christos 	info->fprintf_func (info->stream, "%s", mips_cp1_names[regno]);
   1187  1.5  christos       else
   1188  1.1     skrll 	info->fprintf_func (info->stream, "$%d", regno);
   1189  1.5  christos       break;
   1190  1.5  christos 
   1191  1.5  christos     case OP_REG_HW:
   1192  1.1     skrll       info->fprintf_func (info->stream, "%s", mips_hwr_names[regno]);
   1193  1.5  christos       break;
   1194  1.5  christos 
   1195  1.5  christos     case OP_REG_VF:
   1196  1.1     skrll       info->fprintf_func (info->stream, "$vf%d", regno);
   1197  1.5  christos       break;
   1198  1.5  christos 
   1199  1.5  christos     case OP_REG_VI:
   1200  1.1     skrll       info->fprintf_func (info->stream, "$vi%d", regno);
   1201  1.5  christos       break;
   1202  1.5  christos 
   1203  1.5  christos     case OP_REG_R5900_I:
   1204  1.1     skrll       info->fprintf_func (info->stream, "$I");
   1205  1.5  christos       break;
   1206  1.5  christos 
   1207  1.5  christos     case OP_REG_R5900_Q:
   1208  1.1     skrll       info->fprintf_func (info->stream, "$Q");
   1209  1.5  christos       break;
   1210  1.5  christos 
   1211  1.5  christos     case OP_REG_R5900_R:
   1212  1.1     skrll       info->fprintf_func (info->stream, "$R");
   1213  1.5  christos       break;
   1214  1.5  christos 
   1215  1.5  christos     case OP_REG_R5900_ACC:
   1216  1.1     skrll       info->fprintf_func (info->stream, "$ACC");
   1217  1.5  christos       break;
   1218  1.5  christos 
   1219  1.5  christos     case OP_REG_MSA:
   1220  1.1     skrll       info->fprintf_func (info->stream, "$w%d", regno);
   1221  1.5  christos       break;
   1222  1.5  christos 
   1223  1.5  christos     case OP_REG_MSA_CTRL:
   1224  1.1     skrll       info->fprintf_func (info->stream, "%s", msa_control_names[regno]);
   1225  1.5  christos       break;
   1226  1.5  christos 
   1227  1.5  christos     }
   1228  1.5  christos }
   1229  1.5  christos 
   1230  1.5  christos /* Used to track the state carried over from previous operands in
   1232  1.5  christos    an instruction.  */
   1233  1.5  christos struct mips_print_arg_state {
   1234  1.5  christos   /* The value of the last OP_INT seen.  We only use this for OP_MSB,
   1235  1.5  christos      where the value is known to be unsigned and small.  */
   1236  1.5  christos   unsigned int last_int;
   1237  1.5  christos 
   1238  1.5  christos   /* The type and number of the last OP_REG seen.  We only use this for
   1239  1.5  christos      OP_REPEAT_DEST_REG and OP_REPEAT_PREV_REG.  */
   1240  1.5  christos   enum mips_reg_operand_type last_reg_type;
   1241  1.5  christos   unsigned int last_regno;
   1242  1.1     skrll   unsigned int dest_regno;
   1243  1.5  christos   unsigned int seen_dest;
   1244  1.1     skrll };
   1245  1.5  christos 
   1246  1.5  christos /* Initialize STATE for the start of an instruction.  */
   1247  1.5  christos 
   1248  1.5  christos static inline void
   1249  1.5  christos init_print_arg_state (struct mips_print_arg_state *state)
   1250  1.1     skrll {
   1251  1.5  christos   memset (state, 0, sizeof (*state));
   1252  1.5  christos }
   1253  1.1     skrll 
   1254  1.5  christos /* Print OP_VU0_SUFFIX or OP_VU0_MATCH_SUFFIX operand OPERAND,
   1255  1.5  christos    whose value is given by UVAL.  */
   1256  1.5  christos 
   1257  1.5  christos static void
   1258  1.5  christos print_vu0_channel (struct disassemble_info *info,
   1259  1.5  christos 		   const struct mips_operand *operand, unsigned int uval)
   1260  1.5  christos {
   1261  1.5  christos   if (operand->size == 4)
   1262  1.5  christos     info->fprintf_func (info->stream, "%s%s%s%s",
   1263  1.5  christos 			uval & 8 ? "x" : "",
   1264  1.5  christos 			uval & 4 ? "y" : "",
   1265  1.5  christos 			uval & 2 ? "z" : "",
   1266  1.5  christos 			uval & 1 ? "w" : "");
   1267  1.5  christos   else if (operand->size == 2)
   1268  1.5  christos     info->fprintf_func (info->stream, "%c", "xyzw"[uval]);
   1269  1.1     skrll   else
   1270  1.5  christos     abort ();
   1271  1.1     skrll }
   1272  1.5  christos 
   1273  1.5  christos /* Record information about a register operand.  */
   1274  1.5  christos 
   1275  1.5  christos static void
   1276  1.5  christos mips_seen_register (struct mips_print_arg_state *state,
   1277  1.5  christos 		    unsigned int regno,
   1278  1.5  christos 		    enum mips_reg_operand_type reg_type)
   1279  1.1     skrll {
   1280  1.5  christos   state->last_reg_type = reg_type;
   1281  1.5  christos   state->last_regno = regno;
   1282  1.5  christos 
   1283  1.5  christos   if (!state->seen_dest)
   1284  1.5  christos     {
   1285  1.5  christos       state->seen_dest = 1;
   1286  1.1     skrll       state->dest_regno = regno;
   1287  1.7  christos     }
   1288  1.7  christos }
   1289  1.7  christos 
   1290  1.7  christos /* Print SAVE/RESTORE instruction operands according to the argument
   1291  1.7  christos    register mask AMASK, the number of static registers saved NSREG,
   1292  1.7  christos    the $ra, $s0 and $s1 register specifiers RA, S0 and S1 respectively,
   1293  1.7  christos    and the frame size FRAME_SIZE.  */
   1294  1.7  christos 
   1295  1.7  christos static void
   1296  1.7  christos mips_print_save_restore (struct disassemble_info *info, unsigned int amask,
   1297  1.7  christos 			 unsigned int nsreg, unsigned int ra,
   1298  1.7  christos 			 unsigned int s0, unsigned int s1,
   1299  1.7  christos 			 unsigned int frame_size)
   1300  1.7  christos {
   1301  1.7  christos   const fprintf_ftype infprintf = info->fprintf_func;
   1302  1.7  christos   unsigned int nargs, nstatics, smask, i, j;
   1303  1.7  christos   void *is = info->stream;
   1304  1.7  christos   const char *sep;
   1305  1.7  christos 
   1306  1.7  christos   if (amask == MIPS_SVRS_ALL_ARGS)
   1307  1.7  christos     {
   1308  1.7  christos       nargs = 4;
   1309  1.7  christos       nstatics = 0;
   1310  1.7  christos     }
   1311  1.7  christos   else if (amask == MIPS_SVRS_ALL_STATICS)
   1312  1.7  christos     {
   1313  1.7  christos       nargs = 0;
   1314  1.7  christos       nstatics = 4;
   1315  1.7  christos     }
   1316  1.7  christos   else
   1317  1.7  christos     {
   1318  1.7  christos       nargs = amask >> 2;
   1319  1.7  christos       nstatics = amask & 3;
   1320  1.7  christos     }
   1321  1.7  christos 
   1322  1.7  christos   sep = "";
   1323  1.7  christos   if (nargs > 0)
   1324  1.7  christos     {
   1325  1.7  christos       infprintf (is, "%s", mips_gpr_names[4]);
   1326  1.7  christos       if (nargs > 1)
   1327  1.7  christos 	infprintf (is, "-%s", mips_gpr_names[4 + nargs - 1]);
   1328  1.7  christos       sep = ",";
   1329  1.7  christos     }
   1330  1.7  christos 
   1331  1.7  christos   infprintf (is, "%s%d", sep, frame_size);
   1332  1.7  christos 
   1333  1.7  christos   if (ra)			/* $ra */
   1334  1.7  christos     infprintf (is, ",%s", mips_gpr_names[31]);
   1335  1.7  christos 
   1336  1.7  christos   smask = 0;
   1337  1.7  christos   if (s0)			/* $s0 */
   1338  1.7  christos     smask |= 1 << 0;
   1339  1.7  christos   if (s1)			/* $s1 */
   1340  1.7  christos     smask |= 1 << 1;
   1341  1.7  christos   if (nsreg > 0)		/* $s2-$s8 */
   1342  1.7  christos     smask |= ((1 << nsreg) - 1) << 2;
   1343  1.7  christos 
   1344  1.7  christos   for (i = 0; i < 9; i++)
   1345  1.7  christos     if (smask & (1 << i))
   1346  1.7  christos       {
   1347  1.7  christos 	infprintf (is, ",%s", mips_gpr_names[i == 8 ? 30 : (16 + i)]);
   1348  1.7  christos 	/* Skip over string of set bits.  */
   1349  1.7  christos 	for (j = i; smask & (2 << j); j++)
   1350  1.7  christos 	  continue;
   1351  1.7  christos 	if (j > i)
   1352  1.7  christos 	  infprintf (is, "-%s", mips_gpr_names[j == 8 ? 30 : (16 + j)]);
   1353  1.7  christos 	i = j + 1;
   1354  1.7  christos       }
   1355  1.7  christos   /* Statics $ax - $a3.  */
   1356  1.7  christos   if (nstatics == 1)
   1357  1.7  christos     infprintf (is, ",%s", mips_gpr_names[7]);
   1358  1.7  christos   else if (nstatics > 0)
   1359  1.7  christos     infprintf (is, ",%s-%s",
   1360  1.7  christos 	       mips_gpr_names[7 - nstatics + 1],
   1361  1.7  christos 	       mips_gpr_names[7]);
   1362  1.5  christos }
   1363  1.5  christos 
   1364  1.5  christos 
   1365  1.1     skrll /* Print operand OPERAND of OPCODE, using STATE to track inter-operand state.
   1366  1.5  christos    UVAL is the encoding of the operand (shifted into bit 0) and BASE_PC is
   1367  1.5  christos    the base address for OP_PCREL operands.  */
   1368  1.5  christos 
   1369  1.5  christos static void
   1370  1.5  christos print_insn_arg (struct disassemble_info *info,
   1371  1.5  christos 		struct mips_print_arg_state *state,
   1372  1.5  christos 		const struct mips_opcode *opcode,
   1373  1.5  christos 		const struct mips_operand *operand,
   1374  1.5  christos 		bfd_vma base_pc,
   1375  1.5  christos 		unsigned int uval)
   1376  1.1     skrll {
   1377  1.5  christos   const fprintf_ftype infprintf = info->fprintf_func;
   1378  1.5  christos   void *is = info->stream;
   1379  1.5  christos 
   1380  1.5  christos   switch (operand->type)
   1381  1.5  christos     {
   1382  1.4  christos     case OP_INT:
   1383  1.5  christos       {
   1384  1.5  christos 	const struct mips_int_operand *int_op;
   1385  1.5  christos 
   1386  1.5  christos 	int_op = (const struct mips_int_operand *) operand;
   1387  1.5  christos 	uval = mips_decode_int_operand (int_op, uval);
   1388  1.5  christos 	state->last_int = uval;
   1389  1.5  christos 	if (int_op->print_hex)
   1390  1.5  christos 	  infprintf (is, "0x%x", uval);
   1391  1.5  christos 	else
   1392  1.4  christos 	  infprintf (is, "%d", uval);
   1393  1.5  christos       }
   1394  1.5  christos       break;
   1395  1.5  christos 
   1396  1.1     skrll     case OP_MAPPED_INT:
   1397  1.5  christos       {
   1398  1.5  christos 	const struct mips_mapped_int_operand *mint_op;
   1399  1.5  christos 
   1400  1.5  christos 	mint_op = (const struct mips_mapped_int_operand *) operand;
   1401  1.5  christos 	uval = mint_op->int_map[uval];
   1402  1.5  christos 	state->last_int = uval;
   1403  1.5  christos 	if (mint_op->print_hex)
   1404  1.5  christos 	  infprintf (is, "0x%x", uval);
   1405  1.5  christos 	else
   1406  1.1     skrll 	  infprintf (is, "%d", uval);
   1407  1.5  christos       }
   1408  1.5  christos       break;
   1409  1.5  christos 
   1410  1.1     skrll     case OP_MSB:
   1411  1.5  christos       {
   1412  1.5  christos 	const struct mips_msb_operand *msb_op;
   1413  1.5  christos 
   1414  1.5  christos 	msb_op = (const struct mips_msb_operand *) operand;
   1415  1.5  christos 	uval += msb_op->bias;
   1416  1.5  christos 	if (msb_op->add_lsb)
   1417  1.5  christos 	  uval -= state->last_int;
   1418  1.1     skrll 	infprintf (is, "0x%x", uval);
   1419  1.5  christos       }
   1420  1.5  christos       break;
   1421  1.5  christos 
   1422  1.5  christos     case OP_REG:
   1423  1.1     skrll     case OP_OPTIONAL_REG:
   1424  1.5  christos       {
   1425  1.5  christos 	const struct mips_reg_operand *reg_op;
   1426  1.5  christos 
   1427  1.1     skrll 	reg_op = (const struct mips_reg_operand *) operand;
   1428  1.5  christos 	uval = mips_decode_reg_operand (reg_op, uval);
   1429  1.5  christos 	print_reg (info, opcode, reg_op->reg_type, uval);
   1430  1.5  christos 
   1431  1.1     skrll 	mips_seen_register (state, uval, reg_op->reg_type);
   1432  1.5  christos       }
   1433  1.5  christos       break;
   1434  1.5  christos 
   1435  1.1     skrll     case OP_REG_PAIR:
   1436  1.5  christos       {
   1437  1.5  christos 	const struct mips_reg_pair_operand *pair_op;
   1438  1.5  christos 
   1439  1.5  christos 	pair_op = (const struct mips_reg_pair_operand *) operand;
   1440  1.5  christos 	print_reg (info, opcode, pair_op->reg_type,
   1441  1.5  christos 		   pair_op->reg1_map[uval]);
   1442  1.5  christos 	infprintf (is, ",");
   1443  1.5  christos 	print_reg (info, opcode, pair_op->reg_type,
   1444  1.1     skrll 		   pair_op->reg2_map[uval]);
   1445  1.5  christos       }
   1446  1.5  christos       break;
   1447  1.5  christos 
   1448  1.1     skrll     case OP_PCREL:
   1449  1.5  christos       {
   1450  1.5  christos 	const struct mips_pcrel_operand *pcrel_op;
   1451  1.1     skrll 
   1452  1.7  christos 	pcrel_op = (const struct mips_pcrel_operand *) operand;
   1453  1.7  christos 	info->target = mips_decode_pcrel_operand (pcrel_op, base_pc, uval);
   1454  1.7  christos 
   1455  1.7  christos 	/* For jumps and branches clear the ISA bit except for
   1456  1.5  christos 	   the GDB disassembler.  */
   1457  1.1     skrll 	if (pcrel_op->include_isa_bit
   1458  1.5  christos 	    && info->flavour != bfd_target_unknown_flavour)
   1459  1.5  christos 	  info->target &= -2;
   1460  1.5  christos 
   1461  1.1     skrll 	(*info->print_address_func) (info->target, info);
   1462  1.5  christos       }
   1463  1.5  christos       break;
   1464  1.5  christos 
   1465  1.1     skrll     case OP_PERF_REG:
   1466  1.5  christos       infprintf (is, "%d", uval);
   1467  1.5  christos       break;
   1468  1.5  christos 
   1469  1.1     skrll     case OP_ADDIUSP_INT:
   1470  1.5  christos       {
   1471  1.5  christos 	int sval;
   1472  1.5  christos 
   1473  1.5  christos 	sval = mips_signed_operand (operand, uval) * 4;
   1474  1.5  christos 	if (sval >= -8 && sval < 8)
   1475  1.5  christos 	  sval ^= 0x400;
   1476  1.1     skrll 	infprintf (is, "%d", sval);
   1477  1.5  christos 	break;
   1478  1.5  christos       }
   1479  1.5  christos 
   1480  1.1     skrll     case OP_CLO_CLZ_DEST:
   1481  1.5  christos       {
   1482  1.5  christos 	unsigned int reg1, reg2;
   1483  1.5  christos 
   1484  1.5  christos 	reg1 = uval & 31;
   1485  1.5  christos 	reg2 = uval >> 5;
   1486  1.5  christos 	/* If one is zero use the other.  */
   1487  1.5  christos 	if (reg1 == reg2 || reg2 == 0)
   1488  1.5  christos 	  infprintf (is, "%s", mips_gpr_names[reg1]);
   1489  1.5  christos 	else if (reg1 == 0)
   1490  1.5  christos 	  infprintf (is, "%s", mips_gpr_names[reg2]);
   1491  1.5  christos 	else
   1492  1.5  christos 	  /* Bogus, result depends on processor.  */
   1493  1.5  christos 	  infprintf (is, "%s or %s", mips_gpr_names[reg1],
   1494  1.5  christos 		     mips_gpr_names[reg2]);
   1495  1.5  christos       }
   1496  1.5  christos       break;
   1497  1.5  christos 
   1498  1.5  christos     case OP_SAME_RS_RT:
   1499  1.5  christos     case OP_CHECK_PREV:
   1500  1.5  christos     case OP_NON_ZERO_REG:
   1501  1.5  christos       {
   1502  1.5  christos 	print_reg (info, opcode, OP_REG_GP, uval & 31);
   1503  1.5  christos 	mips_seen_register (state, uval, OP_REG_GP);
   1504  1.5  christos       }
   1505  1.5  christos       break;
   1506  1.5  christos 
   1507  1.5  christos     case OP_LWM_SWM_LIST:
   1508  1.5  christos       if (operand->size == 2)
   1509  1.5  christos 	{
   1510  1.5  christos 	  if (uval == 0)
   1511  1.5  christos 	    infprintf (is, "%s,%s",
   1512  1.5  christos 		       mips_gpr_names[16],
   1513  1.5  christos 		       mips_gpr_names[31]);
   1514  1.5  christos 	  else
   1515  1.5  christos 	    infprintf (is, "%s-%s,%s",
   1516  1.5  christos 		       mips_gpr_names[16],
   1517  1.5  christos 		       mips_gpr_names[16 + uval],
   1518  1.5  christos 		       mips_gpr_names[31]);
   1519  1.5  christos 	}
   1520  1.5  christos       else
   1521  1.5  christos 	{
   1522  1.5  christos 	  int s_reg_encode;
   1523  1.5  christos 
   1524  1.5  christos 	  s_reg_encode = uval & 0xf;
   1525  1.5  christos 	  if (s_reg_encode != 0)
   1526  1.5  christos 	    {
   1527  1.5  christos 	      if (s_reg_encode == 1)
   1528  1.5  christos 		infprintf (is, "%s", mips_gpr_names[16]);
   1529  1.5  christos 	      else if (s_reg_encode < 9)
   1530  1.5  christos 		infprintf (is, "%s-%s",
   1531  1.5  christos 			   mips_gpr_names[16],
   1532  1.5  christos 			   mips_gpr_names[15 + s_reg_encode]);
   1533  1.5  christos 	      else if (s_reg_encode == 9)
   1534  1.5  christos 		infprintf (is, "%s-%s,%s",
   1535  1.5  christos 			   mips_gpr_names[16],
   1536  1.5  christos 			   mips_gpr_names[23],
   1537  1.5  christos 			   mips_gpr_names[30]);
   1538  1.5  christos 	      else
   1539  1.5  christos 		infprintf (is, "UNKNOWN");
   1540  1.5  christos 	    }
   1541  1.5  christos 
   1542  1.5  christos 	  if (uval & 0x10) /* For ra.  */
   1543  1.5  christos 	    {
   1544  1.5  christos 	      if (s_reg_encode == 0)
   1545  1.5  christos 		infprintf (is, "%s", mips_gpr_names[31]);
   1546  1.5  christos 	      else
   1547  1.5  christos 		infprintf (is, ",%s", mips_gpr_names[31]);
   1548  1.5  christos 	    }
   1549  1.5  christos 	}
   1550  1.5  christos       break;
   1551  1.5  christos 
   1552  1.5  christos     case OP_ENTRY_EXIT_LIST:
   1553  1.5  christos       {
   1554  1.5  christos 	const char *sep;
   1555  1.5  christos 	unsigned int amask, smask;
   1556  1.5  christos 
   1557  1.1     skrll 	sep = "";
   1558  1.5  christos 	amask = (uval >> 3) & 7;
   1559  1.5  christos 	if (amask > 0 && amask < 5)
   1560  1.5  christos 	  {
   1561  1.5  christos 	    infprintf (is, "%s", mips_gpr_names[4]);
   1562  1.5  christos 	    if (amask > 1)
   1563  1.5  christos 	      infprintf (is, "-%s", mips_gpr_names[amask + 3]);
   1564  1.5  christos 	    sep = ",";
   1565  1.5  christos 	  }
   1566  1.5  christos 
   1567  1.5  christos 	smask = (uval >> 1) & 3;
   1568  1.5  christos 	if (smask == 3)
   1569  1.5  christos 	  {
   1570  1.5  christos 	    infprintf (is, "%s??", sep);
   1571  1.5  christos 	    sep = ",";
   1572  1.5  christos 	  }
   1573  1.5  christos 	else if (smask > 0)
   1574  1.5  christos 	  {
   1575  1.5  christos 	    infprintf (is, "%s%s", sep, mips_gpr_names[16]);
   1576  1.5  christos 	    if (smask > 1)
   1577  1.5  christos 	      infprintf (is, "-%s", mips_gpr_names[smask + 15]);
   1578  1.5  christos 	    sep = ",";
   1579  1.5  christos 	  }
   1580  1.5  christos 
   1581  1.5  christos 	if (uval & 1)
   1582  1.5  christos 	  {
   1583  1.5  christos 	    infprintf (is, "%s%s", sep, mips_gpr_names[31]);
   1584  1.5  christos 	    sep = ",";
   1585  1.5  christos 	  }
   1586  1.5  christos 
   1587  1.5  christos 	if (amask == 5 || amask == 6)
   1588  1.5  christos 	  {
   1589  1.5  christos 	    infprintf (is, "%s%s", sep, mips_fpr_names[0]);
   1590  1.5  christos 	    if (amask == 6)
   1591  1.5  christos 	      infprintf (is, "-%s", mips_fpr_names[1]);
   1592  1.5  christos 	  }
   1593  1.5  christos       }
   1594  1.7  christos       break;
   1595  1.5  christos 
   1596  1.5  christos     case OP_SAVE_RESTORE_LIST:
   1597  1.5  christos       /* Should be handled by the caller due to complex behavior.  */
   1598  1.5  christos       abort ();
   1599  1.5  christos 
   1600  1.5  christos     case OP_MDMX_IMM_REG:
   1601  1.5  christos       {
   1602  1.5  christos 	unsigned int vsel;
   1603  1.5  christos 
   1604  1.5  christos 	vsel = uval >> 5;
   1605  1.5  christos 	uval &= 31;
   1606  1.5  christos 	if ((vsel & 0x10) == 0)
   1607  1.5  christos 	  {
   1608  1.5  christos 	    int fmt;
   1609  1.5  christos 
   1610  1.5  christos 	    vsel &= 0x0f;
   1611  1.5  christos 	    for (fmt = 0; fmt < 3; fmt++, vsel >>= 1)
   1612  1.5  christos 	      if ((vsel & 1) == 0)
   1613  1.1     skrll 		break;
   1614  1.5  christos 	    print_reg (info, opcode, OP_REG_VEC, uval);
   1615  1.5  christos 	    infprintf (is, "[%d]", vsel >> 1);
   1616  1.5  christos 	  }
   1617  1.5  christos 	else if ((vsel & 0x08) == 0)
   1618  1.5  christos 	  print_reg (info, opcode, OP_REG_VEC, uval);
   1619  1.5  christos 	else
   1620  1.1     skrll 	  infprintf (is, "0x%x", uval);
   1621  1.5  christos       }
   1622  1.5  christos       break;
   1623  1.5  christos 
   1624  1.1     skrll     case OP_REPEAT_PREV_REG:
   1625  1.5  christos       print_reg (info, opcode, state->last_reg_type, state->last_regno);
   1626  1.5  christos       break;
   1627  1.5  christos 
   1628  1.1     skrll     case OP_REPEAT_DEST_REG:
   1629  1.5  christos       print_reg (info, opcode, state->last_reg_type, state->dest_regno);
   1630  1.5  christos       break;
   1631  1.5  christos 
   1632  1.1     skrll     case OP_PC:
   1633  1.7  christos       infprintf (is, "$pc");
   1634  1.7  christos       break;
   1635  1.7  christos 
   1636  1.7  christos     case OP_REG28:
   1637  1.5  christos       print_reg (info, opcode, OP_REG_GP, 28);
   1638  1.5  christos       break;
   1639  1.5  christos 
   1640  1.5  christos     case OP_VU0_SUFFIX:
   1641  1.1     skrll     case OP_VU0_MATCH_SUFFIX:
   1642  1.5  christos       print_vu0_channel (info, operand, uval);
   1643  1.5  christos       break;
   1644  1.5  christos 
   1645  1.1     skrll     case OP_IMM_INDEX:
   1646  1.5  christos       infprintf (is, "[%d]", uval);
   1647  1.5  christos       break;
   1648  1.5  christos 
   1649  1.5  christos     case OP_REG_INDEX:
   1650  1.5  christos       infprintf (is, "[");
   1651  1.5  christos       print_reg (info, opcode, OP_REG_GP, uval);
   1652  1.5  christos       infprintf (is, "]");
   1653  1.1     skrll       break;
   1654  1.5  christos     }
   1655  1.5  christos }
   1656  1.1     skrll 
   1657  1.5  christos /* Validate the arguments for INSN, which is described by OPCODE.
   1658  1.5  christos    Use DECODE_OPERAND to get the encoding of each operand.  */
   1659  1.5  christos 
   1660  1.5  christos static bfd_boolean
   1661  1.5  christos validate_insn_args (const struct mips_opcode *opcode,
   1662  1.5  christos 		    const struct mips_operand *(*decode_operand) (const char *),
   1663  1.5  christos 		    unsigned int insn)
   1664  1.5  christos {
   1665  1.5  christos   struct mips_print_arg_state state;
   1666  1.1     skrll   const struct mips_operand *operand;
   1667  1.5  christos   const char *s;
   1668  1.5  christos   unsigned int uval;
   1669  1.5  christos 
   1670  1.5  christos   init_print_arg_state (&state);
   1671  1.5  christos   for (s = opcode->args; *s; ++s)
   1672  1.5  christos     {
   1673  1.5  christos       switch (*s)
   1674  1.5  christos 	{
   1675  1.1     skrll 	case ',':
   1676  1.1     skrll 	case '(':
   1677  1.5  christos 	case ')':
   1678  1.5  christos 	  break;
   1679  1.1     skrll 
   1680  1.1     skrll 	case '#':
   1681  1.5  christos 	  ++s;
   1682  1.5  christos 	  break;
   1683  1.1     skrll 
   1684  1.5  christos 	default:
   1685  1.5  christos 	  operand = decode_operand (s);
   1686  1.5  christos 
   1687  1.5  christos 	  if (operand)
   1688  1.5  christos 	    {
   1689  1.5  christos 	      uval = mips_extract_operand (operand, insn);
   1690  1.5  christos 	      switch (operand->type)
   1691  1.5  christos 		{
   1692  1.5  christos 		case OP_REG:
   1693  1.1     skrll 		case OP_OPTIONAL_REG:
   1694  1.5  christos 		  {
   1695  1.5  christos 		    const struct mips_reg_operand *reg_op;
   1696  1.5  christos 
   1697  1.5  christos 		    reg_op = (const struct mips_reg_operand *) operand;
   1698  1.5  christos 		    uval = mips_decode_reg_operand (reg_op, uval);
   1699  1.1     skrll 		    mips_seen_register (&state, uval, reg_op->reg_type);
   1700  1.5  christos 		  }
   1701  1.5  christos 		break;
   1702  1.5  christos 
   1703  1.1     skrll 		case OP_SAME_RS_RT:
   1704  1.5  christos 		  {
   1705  1.5  christos 		    unsigned int reg1, reg2;
   1706  1.1     skrll 
   1707  1.5  christos 		    reg1 = uval & 31;
   1708  1.5  christos 		    reg2 = uval >> 5;
   1709  1.5  christos 
   1710  1.5  christos 		    if (reg1 != reg2 || reg1 == 0)
   1711  1.1     skrll 		      return FALSE;
   1712  1.5  christos 		  }
   1713  1.5  christos 		break;
   1714  1.5  christos 
   1715  1.1     skrll 		case OP_CHECK_PREV:
   1716  1.5  christos 		  {
   1717  1.1     skrll 		    const struct mips_check_prev_operand *prev_op;
   1718  1.5  christos 
   1719  1.5  christos 		    prev_op = (const struct mips_check_prev_operand *) operand;
   1720  1.1     skrll 
   1721  1.5  christos 		    if (!prev_op->zero_ok && uval == 0)
   1722  1.5  christos 		      return FALSE;
   1723  1.5  christos 
   1724  1.5  christos 		    if (((prev_op->less_than_ok && uval < state.last_regno)
   1725  1.1     skrll 			|| (prev_op->greater_than_ok && uval > state.last_regno)
   1726  1.5  christos 			|| (prev_op->equal_ok && uval == state.last_regno)))
   1727  1.5  christos 		      break;
   1728  1.1     skrll 
   1729  1.5  christos 		    return FALSE;
   1730  1.5  christos 		  }
   1731  1.5  christos 
   1732  1.5  christos 		case OP_NON_ZERO_REG:
   1733  1.5  christos 		  {
   1734  1.5  christos 		    if (uval == 0)
   1735  1.1     skrll 		      return FALSE;
   1736  1.5  christos 		  }
   1737  1.5  christos 		break;
   1738  1.5  christos 
   1739  1.5  christos 		case OP_INT:
   1740  1.5  christos 		case OP_MAPPED_INT:
   1741  1.5  christos 		case OP_MSB:
   1742  1.5  christos 		case OP_REG_PAIR:
   1743  1.5  christos 		case OP_PCREL:
   1744  1.5  christos 		case OP_PERF_REG:
   1745  1.5  christos 		case OP_ADDIUSP_INT:
   1746  1.5  christos 		case OP_CLO_CLZ_DEST:
   1747  1.5  christos 		case OP_LWM_SWM_LIST:
   1748  1.5  christos 		case OP_ENTRY_EXIT_LIST:
   1749  1.5  christos 		case OP_MDMX_IMM_REG:
   1750  1.7  christos 		case OP_REPEAT_PREV_REG:
   1751  1.5  christos 		case OP_REPEAT_DEST_REG:
   1752  1.5  christos 		case OP_PC:
   1753  1.5  christos 		case OP_REG28:
   1754  1.5  christos 		case OP_VU0_SUFFIX:
   1755  1.7  christos 		case OP_VU0_MATCH_SUFFIX:
   1756  1.5  christos 		case OP_IMM_INDEX:
   1757  1.5  christos 		case OP_REG_INDEX:
   1758  1.5  christos 		case OP_SAVE_RESTORE_LIST:
   1759  1.5  christos 		  break;
   1760  1.5  christos 		}
   1761  1.5  christos 	    }
   1762  1.5  christos 	  if (*s == 'm' || *s == '+' || *s == '-')
   1763  1.5  christos 	    ++s;
   1764  1.5  christos 	}
   1765  1.1     skrll     }
   1766  1.5  christos   return TRUE;
   1767  1.5  christos }
   1768  1.5  christos 
   1769  1.5  christos /* Print the arguments for INSN, which is described by OPCODE.
   1770  1.1     skrll    Use DECODE_OPERAND to get the encoding of each operand.  Use BASE_PC
   1771  1.5  christos    as the base of OP_PCREL operands, adjusting by LENGTH if the OP_PCREL
   1772  1.5  christos    operand is for a branch or jump.  */
   1773  1.5  christos 
   1774  1.5  christos static void
   1775  1.5  christos print_insn_args (struct disassemble_info *info,
   1776  1.5  christos 		 const struct mips_opcode *opcode,
   1777  1.5  christos 		 const struct mips_operand *(*decode_operand) (const char *),
   1778  1.5  christos 		 unsigned int insn, bfd_vma insn_pc, unsigned int length)
   1779  1.5  christos {
   1780  1.5  christos   const fprintf_ftype infprintf = info->fprintf_func;
   1781  1.5  christos   void *is = info->stream;
   1782  1.1     skrll   struct mips_print_arg_state state;
   1783  1.5  christos   const struct mips_operand *operand;
   1784  1.5  christos   const char *s;
   1785  1.5  christos 
   1786  1.5  christos   init_print_arg_state (&state);
   1787  1.5  christos   for (s = opcode->args; *s; ++s)
   1788  1.5  christos     {
   1789  1.5  christos       switch (*s)
   1790  1.5  christos 	{
   1791  1.5  christos 	case ',':
   1792  1.1     skrll 	case '(':
   1793  1.1     skrll 	case ')':
   1794  1.5  christos 	  infprintf (is, "%c", *s);
   1795  1.5  christos 	  break;
   1796  1.5  christos 
   1797  1.1     skrll 	case '#':
   1798  1.1     skrll 	  ++s;
   1799  1.1     skrll 	  infprintf (is, "%c%c", *s, *s);
   1800  1.5  christos 	  break;
   1801  1.5  christos 
   1802  1.5  christos 	default:
   1803  1.5  christos 	  operand = decode_operand (s);
   1804  1.5  christos 	  if (!operand)
   1805  1.5  christos 	    {
   1806  1.5  christos 	      /* xgettext:c-format */
   1807  1.5  christos 	      infprintf (is,
   1808  1.5  christos 			 _("# internal error, undefined operand in `%s %s'"),
   1809  1.7  christos 			 opcode->name, opcode->args);
   1810  1.7  christos 	      return;
   1811  1.7  christos 	    }
   1812  1.7  christos 
   1813  1.7  christos 	  if (operand->type == OP_SAVE_RESTORE_LIST)
   1814  1.7  christos 	    {
   1815  1.7  christos 	      /* Handle this case here because of the complex behavior.  */
   1816  1.7  christos 	      unsigned int amask = (insn >> 15) & 0xf;
   1817  1.7  christos 	      unsigned int nsreg = (insn >> 23) & 0x7;
   1818  1.7  christos 	      unsigned int ra = insn & 0x1000;			/* $ra */
   1819  1.7  christos 	      unsigned int s0 = insn & 0x800;			/* $s0 */
   1820  1.7  christos 	      unsigned int s1 = insn & 0x400;			/* $s1 */
   1821  1.7  christos 	      unsigned int frame_size = (((insn >> 15) & 0xf0)
   1822  1.7  christos 					 | ((insn >> 6) & 0x0f)) * 8;
   1823  1.7  christos 	      mips_print_save_restore (info, amask, nsreg, ra, s0, s1,
   1824  1.7  christos 				       frame_size);
   1825  1.7  christos 	    }
   1826  1.7  christos 	  else if (operand->type == OP_REG
   1827  1.5  christos 		   && s[1] == ','
   1828  1.7  christos 		   && s[2] == 'H'
   1829  1.5  christos 		   && opcode->name[strlen (opcode->name) - 1] == '0')
   1830  1.5  christos 	    {
   1831  1.5  christos 	      /* Coprocessor register 0 with sel field.  */
   1832  1.5  christos 	      const struct mips_cp0sel_name *n;
   1833  1.5  christos 	      unsigned int reg, sel;
   1834  1.5  christos 
   1835  1.5  christos 	      reg = mips_extract_operand (operand, insn);
   1836  1.5  christos 	      s += 2;
   1837  1.5  christos 	      operand = decode_operand (s);
   1838  1.5  christos 	      sel = mips_extract_operand (operand, insn);
   1839  1.5  christos 
   1840  1.5  christos 	      /* CP0 register including 'sel' code for mftc0, to be
   1841  1.5  christos 		 printed textually if known.  If not known, print both
   1842  1.5  christos 		 CP0 register name and sel numerically since CP0 register
   1843  1.5  christos 		 with sel 0 may have a name unrelated to register being
   1844  1.5  christos 		 printed.  */
   1845  1.5  christos 	      n = lookup_mips_cp0sel_name (mips_cp0sel_names,
   1846  1.5  christos 					   mips_cp0sel_names_len,
   1847  1.5  christos 					   reg, sel);
   1848  1.5  christos 	      if (n != NULL)
   1849  1.5  christos 		infprintf (is, "%s", n->name);
   1850  1.5  christos 	      else
   1851  1.5  christos 		infprintf (is, "$%d,%d", reg, sel);
   1852  1.5  christos 	    }
   1853  1.5  christos 	  else
   1854  1.5  christos 	    {
   1855  1.5  christos 	      bfd_vma base_pc = insn_pc;
   1856  1.5  christos 
   1857  1.5  christos 	      /* Adjust the PC relative base so that branch/jump insns use
   1858  1.5  christos 		 the following PC as the base but genuinely PC relative
   1859  1.5  christos 		 operands use the current PC.  */
   1860  1.5  christos 	      if (operand->type == OP_PCREL)
   1861  1.5  christos 		{
   1862  1.5  christos 		  const struct mips_pcrel_operand *pcrel_op;
   1863  1.5  christos 
   1864  1.5  christos 		  pcrel_op = (const struct mips_pcrel_operand *) operand;
   1865  1.5  christos 		  /* The include_isa_bit flag is sufficient to distinguish
   1866  1.5  christos 		     branch/jump from other PC relative operands.  */
   1867  1.5  christos 		  if (pcrel_op->include_isa_bit)
   1868  1.5  christos 		    base_pc += length;
   1869  1.5  christos 		}
   1870  1.5  christos 
   1871  1.5  christos 	      print_insn_arg (info, &state, opcode, operand, base_pc,
   1872  1.5  christos 			      mips_extract_operand (operand, insn));
   1873  1.5  christos 	    }
   1874  1.1     skrll 	  if (*s == 'm' || *s == '+' || *s == '-')
   1875  1.1     skrll 	    ++s;
   1876  1.1     skrll 	  break;
   1877  1.1     skrll 	}
   1878  1.1     skrll     }
   1879  1.1     skrll }
   1880  1.1     skrll 
   1881  1.1     skrll /* Print the mips instruction at address MEMADDR in debugged memory,
   1883  1.1     skrll    on using INFO.  Returns length of the instruction, in bytes, which is
   1884  1.1     skrll    always INSNLEN.  BIGENDIAN must be 1 if this is big-endian code, 0 if
   1885  1.4  christos    this is little-endian code.  */
   1886  1.1     skrll 
   1887  1.1     skrll static int
   1888  1.5  christos print_insn_mips (bfd_vma memaddr,
   1889  1.5  christos 		 int word,
   1890  1.4  christos 		 struct disassemble_info *info)
   1891  1.4  christos {
   1892  1.1     skrll #define GET_OP(insn, field)			\
   1893  1.1     skrll   (((insn) >> OP_SH_##field) & OP_MASK_##field)
   1894  1.4  christos   static const struct mips_opcode *mips_hash[OP_MASK_OP + 1];
   1895  1.1     skrll   const fprintf_ftype infprintf = info->fprintf_func;
   1896  1.1     skrll   const struct mips_opcode *op;
   1897  1.1     skrll   static bfd_boolean init = 0;
   1898  1.1     skrll   void *is = info->stream;
   1899  1.1     skrll 
   1900  1.1     skrll   /* Build a hash table to shorten the search time.  */
   1901  1.1     skrll   if (! init)
   1902  1.1     skrll     {
   1903  1.1     skrll       unsigned int i;
   1904  1.1     skrll 
   1905  1.1     skrll       for (i = 0; i <= OP_MASK_OP; i++)
   1906  1.1     skrll 	{
   1907  1.1     skrll 	  for (op = mips_opcodes; op < &mips_opcodes[NUMOPCODES]; op++)
   1908  1.4  christos 	    {
   1909  1.1     skrll 	      if (op->pinfo == INSN_MACRO
   1910  1.1     skrll 		  || (no_aliases && (op->pinfo2 & INSN2_ALIAS)))
   1911  1.1     skrll 		continue;
   1912  1.1     skrll 	      if (i == GET_OP (op->match, OP))
   1913  1.1     skrll 		{
   1914  1.1     skrll 		  mips_hash[i] = op;
   1915  1.1     skrll 		  break;
   1916  1.1     skrll 		}
   1917  1.1     skrll 	    }
   1918  1.1     skrll 	}
   1919  1.1     skrll 
   1920  1.1     skrll       init = 1;
   1921  1.1     skrll     }
   1922  1.1     skrll 
   1923  1.1     skrll   info->bytes_per_chunk = INSNLEN;
   1924  1.1     skrll   info->display_endian = info->endian;
   1925  1.1     skrll   info->insn_info_valid = 1;
   1926  1.1     skrll   info->branch_delay_insns = 0;
   1927  1.1     skrll   info->data_size = 0;
   1928  1.4  christos   info->insn_type = dis_nonbranch;
   1929  1.1     skrll   info->target = 0;
   1930  1.1     skrll   info->target2 = 0;
   1931  1.1     skrll 
   1932  1.1     skrll   op = mips_hash[GET_OP (word, OP)];
   1933  1.5  christos   if (op != NULL)
   1934  1.1     skrll     {
   1935  1.1     skrll       for (; op < &mips_opcodes[NUMOPCODES]; op++)
   1936  1.1     skrll 	{
   1937  1.5  christos 	  if (op->pinfo != INSN_MACRO
   1938  1.5  christos 	      && !(no_aliases && (op->pinfo2 & INSN2_ALIAS))
   1939  1.5  christos 	      && (word & op->mask) == op->match)
   1940  1.5  christos 	    {
   1941  1.5  christos 	      /* We always disassemble the jalx instruction, except for MIPS r6.  */
   1942  1.1     skrll 	      if (!opcode_is_member (op, mips_isa, mips_ase, mips_processor)
   1943  1.1     skrll 		 && (strcmp (op->name, "jalx")
   1944  1.1     skrll 		     || (mips_isa & INSN_ISA_MASK) == ISA_MIPS32R6
   1945  1.1     skrll 		     || (mips_isa & INSN_ISA_MASK) == ISA_MIPS64R6))
   1946  1.1     skrll 		continue;
   1947  1.5  christos 
   1948  1.1     skrll 	      /* Figure out instruction type and branch delay information.  */
   1949  1.1     skrll 	      if ((op->pinfo & INSN_UNCOND_BRANCH_DELAY) != 0)
   1950  1.1     skrll 	        {
   1951  1.1     skrll 		  if ((op->pinfo & (INSN_WRITE_GPR_31 | INSN_WRITE_1)) != 0)
   1952  1.1     skrll 		    info->insn_type = dis_jsr;
   1953  1.1     skrll 		  else
   1954  1.1     skrll 		    info->insn_type = dis_branch;
   1955  1.1     skrll 		  info->branch_delay_insns = 1;
   1956  1.3  christos 		}
   1957  1.1     skrll 	      else if ((op->pinfo & (INSN_COND_BRANCH_DELAY
   1958  1.1     skrll 				     | INSN_COND_BRANCH_LIKELY)) != 0)
   1959  1.1     skrll 		{
   1960  1.1     skrll 		  if ((op->pinfo & INSN_WRITE_GPR_31) != 0)
   1961  1.1     skrll 		    info->insn_type = dis_condjsr;
   1962  1.1     skrll 		  else
   1963  1.5  christos 		    info->insn_type = dis_condbranch;
   1964  1.1     skrll 		  info->branch_delay_insns = 1;
   1965  1.1     skrll 		}
   1966  1.5  christos 	      else if ((op->pinfo & (INSN_STORE_MEMORY
   1967  1.5  christos 				     | INSN_LOAD_MEMORY)) != 0)
   1968  1.5  christos 		info->insn_type = dis_dref;
   1969  1.4  christos 
   1970  1.5  christos 	      if (!validate_insn_args (op, decode_mips_operand, word))
   1971  1.5  christos 		continue;
   1972  1.5  christos 
   1973  1.5  christos 	      infprintf (is, "%s", op->name);
   1974  1.5  christos 	      if (op->pinfo2 & INSN2_VU0_CHANNEL_SUFFIX)
   1975  1.5  christos 		{
   1976  1.5  christos 		  unsigned int uval;
   1977  1.5  christos 
   1978  1.1     skrll 		  infprintf (is, ".");
   1979  1.5  christos 		  uval = mips_extract_operand (&mips_vu0_channel_mask, word);
   1980  1.1     skrll 		  print_vu0_channel (info, &mips_vu0_channel_mask, uval);
   1981  1.4  christos 		}
   1982  1.5  christos 
   1983  1.5  christos 	      if (op->args[0])
   1984  1.1     skrll 		{
   1985  1.1     skrll 		  infprintf (is, "\t");
   1986  1.1     skrll 		  print_insn_args (info, op, decode_mips_operand, word,
   1987  1.1     skrll 				   memaddr, 4);
   1988  1.1     skrll 		}
   1989  1.1     skrll 
   1990  1.4  christos 	      return INSNLEN;
   1991  1.1     skrll 	    }
   1992  1.1     skrll 	}
   1993  1.1     skrll     }
   1994  1.4  christos #undef GET_OP
   1995  1.1     skrll 
   1996  1.1     skrll   /* Handle undefined instructions.  */
   1997  1.1     skrll   info->insn_type = dis_noninsn;
   1998  1.1     skrll   infprintf (is, "0x%x", word);
   1999  1.1     skrll   return INSNLEN;
   2000  1.1     skrll }
   2001  1.5  christos 
   2002  1.5  christos /* Disassemble an operand for a mips16 instruction.  */
   2004  1.5  christos 
   2005  1.5  christos static void
   2006  1.5  christos print_mips16_insn_arg (struct disassemble_info *info,
   2007  1.1     skrll 		       struct mips_print_arg_state *state,
   2008  1.4  christos 		       const struct mips_opcode *opcode,
   2009  1.4  christos 		       char type, bfd_vma memaddr,
   2010  1.5  christos 		       unsigned insn, bfd_boolean use_extend,
   2011  1.7  christos 		       unsigned extend, bfd_boolean is_offset)
   2012  1.5  christos {
   2013  1.5  christos   const fprintf_ftype infprintf = info->fprintf_func;
   2014  1.5  christos   void *is = info->stream;
   2015  1.5  christos   const struct mips_operand *operand, *ext_operand;
   2016  1.5  christos   unsigned short ext_size;
   2017  1.4  christos   unsigned int uval;
   2018  1.1     skrll   bfd_vma baseaddr;
   2019  1.1     skrll 
   2020  1.1     skrll   if (!use_extend)
   2021  1.1     skrll     extend = 0;
   2022  1.1     skrll 
   2023  1.4  christos   switch (type)
   2024  1.1     skrll     {
   2025  1.1     skrll     case ',':
   2026  1.5  christos     case '(':
   2027  1.5  christos     case ')':
   2028  1.5  christos       infprintf (is, "%c", type);
   2029  1.5  christos       break;
   2030  1.5  christos 
   2031  1.5  christos     default:
   2032  1.5  christos       operand = decode_mips16_operand (type, FALSE);
   2033  1.5  christos       if (!operand)
   2034  1.5  christos 	{
   2035  1.1     skrll 	  /* xgettext:c-format */
   2036  1.5  christos 	  infprintf (is, _("# internal error, undefined operand in `%s %s'"),
   2037  1.5  christos 		     opcode->name, opcode->args);
   2038  1.7  christos 	  return;
   2039  1.5  christos 	}
   2040  1.7  christos 
   2041  1.7  christos       if (operand->type == OP_SAVE_RESTORE_LIST)
   2042  1.7  christos 	{
   2043  1.7  christos 	  /* Handle this case here because of the complex interaction
   2044  1.7  christos 	     with the EXTEND opcode.  */
   2045  1.7  christos 	  unsigned int amask = extend & 0xf;
   2046  1.5  christos 	  unsigned int nsreg = (extend >> 8) & 0x7;
   2047  1.5  christos 	  unsigned int ra = insn & 0x40;			/* $ra */
   2048  1.7  christos 	  unsigned int s0 = insn & 0x20;			/* $s0 */
   2049  1.5  christos 	  unsigned int s1 = insn & 0x10;			/* $s1 */
   2050  1.5  christos 	  unsigned int frame_size = ((extend & 0xf0) | (insn & 0x0f)) * 8;
   2051  1.1     skrll 	  if (frame_size == 0 && !use_extend)
   2052  1.5  christos 	    frame_size = 128;
   2053  1.5  christos 	  mips_print_save_restore (info, amask, nsreg, ra, s0, s1, frame_size);
   2054  1.5  christos 	  break;
   2055  1.1     skrll 	}
   2056  1.5  christos 
   2057  1.5  christos       if (is_offset && operand->type == OP_INT)
   2058  1.5  christos 	{
   2059  1.5  christos 	  const struct mips_int_operand *int_op;
   2060  1.1     skrll 
   2061  1.7  christos 	  int_op = (const struct mips_int_operand *) operand;
   2062  1.7  christos 	  info->insn_type = dis_dref;
   2063  1.5  christos 	  info->data_size = 1 << int_op->shift;
   2064  1.7  christos 	}
   2065  1.7  christos 
   2066  1.7  christos       ext_size = 0;
   2067  1.7  christos       if (use_extend)
   2068  1.5  christos 	{
   2069  1.7  christos 	  ext_operand = decode_mips16_operand (type, TRUE);
   2070  1.7  christos 	  if (ext_operand != operand
   2071  1.5  christos 	      || (operand->type == OP_INT && operand->lsb == 0
   2072  1.5  christos 		  && mips_opcode_32bit_p (opcode)))
   2073  1.7  christos 	    {
   2074  1.7  christos 	      ext_size = ext_operand->size;
   2075  1.7  christos 	      operand = ext_operand;
   2076  1.7  christos 	    }
   2077  1.7  christos 	}
   2078  1.7  christos       if (operand->size == 26)
   2079  1.7  christos 	uval = ((extend & 0x1f) << 21) | ((extend & 0x3e0) << 11) | insn;
   2080  1.7  christos       else if (ext_size == 16 || ext_size == 9)
   2081  1.7  christos 	uval = ((extend & 0x1f) << 11) | (extend & 0x7e0) | (insn & 0x1f);
   2082  1.7  christos       else if (ext_size == 15)
   2083  1.7  christos 	uval = ((extend & 0xf) << 11) | (extend & 0x7f0) | (insn & 0xf);
   2084  1.7  christos       else if (ext_size == 6)
   2085  1.1     skrll 	uval = ((extend >> 6) & 0x1f) | (extend & 0x20);
   2086  1.5  christos       else
   2087  1.5  christos 	uval = mips_extract_operand (operand, (extend << 16) | insn);
   2088  1.5  christos       if (ext_size == 9)
   2089  1.5  christos 	uval &= (1U << ext_size) - 1;
   2090  1.1     skrll 
   2091  1.5  christos       baseaddr = memaddr + 2;
   2092  1.5  christos       if (operand->type == OP_PCREL)
   2093  1.5  christos 	{
   2094  1.5  christos 	  const struct mips_pcrel_operand *pcrel_op;
   2095  1.7  christos 
   2096  1.7  christos 	  pcrel_op = (const struct mips_pcrel_operand *) operand;
   2097  1.5  christos 	  if (!pcrel_op->include_isa_bit && use_extend)
   2098  1.7  christos 	    baseaddr = memaddr - 2;
   2099  1.7  christos 	  else if (!pcrel_op->include_isa_bit)
   2100  1.7  christos 	    {
   2101  1.7  christos 	      bfd_byte buffer[2];
   2102  1.7  christos 
   2103  1.7  christos 	      /* If this instruction is in the delay slot of a JAL/JALX
   2104  1.7  christos 		 instruction, the base address is the address of the
   2105  1.7  christos 		 JAL/JALX instruction.  If it is in the delay slot of
   2106  1.7  christos 		 a JR/JALR instruction, the base address is the address
   2107  1.7  christos 		 of the JR/JALR instruction.  This test is unreliable:
   2108  1.7  christos 		 we have no way of knowing whether the previous word is
   2109  1.7  christos 		 instruction or data.  */
   2110  1.7  christos 	      if (info->read_memory_func (memaddr - 4, buffer, 2, info) == 0
   2111  1.7  christos 		  && (((info->endian == BFD_ENDIAN_BIG
   2112  1.7  christos 			? bfd_getb16 (buffer)
   2113  1.7  christos 			: bfd_getl16 (buffer))
   2114  1.7  christos 		       & 0xf800) == 0x1800))
   2115  1.7  christos 		baseaddr = memaddr - 4;
   2116  1.7  christos 	      else if (info->read_memory_func (memaddr - 2, buffer, 2,
   2117  1.7  christos 					       info) == 0
   2118  1.7  christos 		       && (((info->endian == BFD_ENDIAN_BIG
   2119  1.7  christos 			     ? bfd_getb16 (buffer)
   2120  1.7  christos 			     : bfd_getl16 (buffer))
   2121  1.7  christos 			    & 0xf89f) == 0xe800)
   2122  1.7  christos 		       && (((info->endian == BFD_ENDIAN_BIG
   2123  1.7  christos 			     ? bfd_getb16 (buffer)
   2124  1.7  christos 			     : bfd_getl16 (buffer))
   2125  1.5  christos 			    & 0x0060) != 0x0060))
   2126  1.1     skrll 		baseaddr = memaddr - 2;
   2127  1.5  christos 	      else
   2128  1.1     skrll 		baseaddr = memaddr;
   2129  1.5  christos 	    }
   2130  1.5  christos 	}
   2131  1.1     skrll 
   2132  1.1     skrll       print_insn_arg (info, state, opcode, operand, baseaddr + 1, uval);
   2133  1.5  christos       break;
   2134  1.5  christos     }
   2135  1.5  christos }
   2136  1.5  christos 
   2137  1.5  christos 
   2138  1.5  christos /* Check if the given address is the last word of a MIPS16 PLT entry.
   2139  1.5  christos    This word is data and depending on the value it may interfere with
   2140  1.5  christos    disassembly of further PLT entries.  We make use of the fact PLT
   2141  1.5  christos    symbols are marked BSF_SYNTHETIC.  */
   2142  1.5  christos static bfd_boolean
   2143  1.5  christos is_mips16_plt_tail (struct disassemble_info *info, bfd_vma addr)
   2144  1.5  christos {
   2145  1.1     skrll   if (info->symbols
   2146  1.5  christos       && info->symbols[0]
   2147  1.1     skrll       && (info->symbols[0]->flags & BSF_SYNTHETIC)
   2148  1.1     skrll       && addr == bfd_asymbol_value (info->symbols[0]) + 12)
   2149  1.7  christos     return TRUE;
   2150  1.7  christos 
   2151  1.7  christos   return FALSE;
   2152  1.7  christos }
   2153  1.7  christos 
   2154  1.7  christos /* Whether none, a 32-bit or a 16-bit instruction match has been done.  */
   2155  1.7  christos 
   2156  1.7  christos enum match_kind
   2157  1.7  christos {
   2158  1.1     skrll   MATCH_NONE,
   2159  1.1     skrll   MATCH_FULL,
   2160  1.1     skrll   MATCH_SHORT
   2161  1.1     skrll };
   2162  1.1     skrll 
   2163  1.4  christos /* Disassemble mips16 instructions.  */
   2164  1.1     skrll 
   2165  1.5  christos static int
   2166  1.1     skrll print_insn_mips16 (bfd_vma memaddr, struct disassemble_info *info)
   2167  1.5  christos {
   2168  1.4  christos   const fprintf_ftype infprintf = info->fprintf_func;
   2169  1.7  christos   int status;
   2170  1.7  christos   bfd_byte buffer[4];
   2171  1.7  christos   const struct mips_opcode *op, *opend;
   2172  1.7  christos   struct mips_print_arg_state state;
   2173  1.7  christos   void *is = info->stream;
   2174  1.1     skrll   bfd_boolean have_second;
   2175  1.1     skrll   bfd_boolean extend_only;
   2176  1.1     skrll   unsigned int second;
   2177  1.1     skrll   unsigned int first;
   2178  1.1     skrll   unsigned int full;
   2179  1.1     skrll 
   2180  1.1     skrll   info->bytes_per_chunk = 2;
   2181  1.1     skrll   info->display_endian = info->endian;
   2182  1.1     skrll   info->insn_info_valid = 1;
   2183  1.5  christos   info->branch_delay_insns = 0;
   2184  1.5  christos   info->data_size = 0;
   2185  1.5  christos   info->target = 0;
   2186  1.5  christos   info->target2 = 0;
   2187  1.5  christos 
   2188  1.5  christos #define GET_OP(insn, field) \
   2189  1.5  christos   (((insn) >> MIPS16OP_SH_##field) & MIPS16OP_MASK_##field)
   2190  1.5  christos   /* Decode PLT entry's GOT slot address word.  */
   2191  1.5  christos   if (is_mips16_plt_tail (info, memaddr))
   2192  1.5  christos     {
   2193  1.5  christos       info->insn_type = dis_noninsn;
   2194  1.5  christos       status = (*info->read_memory_func) (memaddr, buffer, 4, info);
   2195  1.5  christos       if (status == 0)
   2196  1.5  christos 	{
   2197  1.5  christos 	  unsigned int gotslot;
   2198  1.5  christos 
   2199  1.5  christos 	  if (info->endian == BFD_ENDIAN_BIG)
   2200  1.5  christos 	    gotslot = bfd_getb32 (buffer);
   2201  1.5  christos 	  else
   2202  1.5  christos 	    gotslot = bfd_getl32 (buffer);
   2203  1.5  christos 	  infprintf (is, ".word\t0x%x", gotslot);
   2204  1.5  christos 
   2205  1.5  christos 	  return 4;
   2206  1.5  christos 	}
   2207  1.5  christos     }
   2208  1.1     skrll   else
   2209  1.1     skrll     {
   2210  1.1     skrll       info->insn_type = dis_nonbranch;
   2211  1.1     skrll       status = (*info->read_memory_func) (memaddr, buffer, 2, info);
   2212  1.1     skrll     }
   2213  1.1     skrll   if (status != 0)
   2214  1.7  christos     {
   2215  1.1     skrll       (*info->memory_error_func) (status, memaddr, info);
   2216  1.1     skrll       return -1;
   2217  1.7  christos     }
   2218  1.1     skrll 
   2219  1.7  christos   extend_only = FALSE;
   2220  1.1     skrll 
   2221  1.7  christos   if (info->endian == BFD_ENDIAN_BIG)
   2222  1.7  christos     first = bfd_getb16 (buffer);
   2223  1.1     skrll   else
   2224  1.7  christos     first = bfd_getl16 (buffer);
   2225  1.1     skrll 
   2226  1.7  christos   status = (*info->read_memory_func) (memaddr + 2, buffer, 2, info);
   2227  1.1     skrll   if (status == 0)
   2228  1.7  christos     {
   2229  1.7  christos       have_second = TRUE;
   2230  1.7  christos       if (info->endian == BFD_ENDIAN_BIG)
   2231  1.7  christos 	second = bfd_getb16 (buffer);
   2232  1.7  christos       else
   2233  1.7  christos 	second = bfd_getl16 (buffer);
   2234  1.7  christos       full = (first << 16) | second;
   2235  1.7  christos     }
   2236  1.1     skrll   else
   2237  1.1     skrll     {
   2238  1.1     skrll       have_second = FALSE;
   2239  1.1     skrll       second = 0;
   2240  1.1     skrll       full = first;
   2241  1.1     skrll     }
   2242  1.1     skrll 
   2243  1.7  christos   /* FIXME: Should probably use a hash table on the major opcode here.  */
   2244  1.7  christos 
   2245  1.7  christos   opend = mips16_opcodes + bfd_mips16_num_opcodes;
   2246  1.7  christos   for (op = mips16_opcodes; op < opend; op++)
   2247  1.7  christos     {
   2248  1.7  christos       enum match_kind match;
   2249  1.7  christos 
   2250  1.7  christos       if (!opcode_is_member (op, mips_isa, mips_ase, mips_processor))
   2251  1.7  christos 	continue;
   2252  1.7  christos 
   2253  1.7  christos       if (op->pinfo == INSN_MACRO
   2254  1.7  christos 	  || (no_aliases && (op->pinfo2 & INSN2_ALIAS)))
   2255  1.7  christos 	match = MATCH_NONE;
   2256  1.7  christos       else if (mips_opcode_32bit_p (op))
   2257  1.7  christos 	{
   2258  1.7  christos 	  if (have_second
   2259  1.7  christos 	      && (full & op->mask) == op->match)
   2260  1.7  christos 	    match = MATCH_FULL;
   2261  1.7  christos 	  else
   2262  1.7  christos 	    match = MATCH_NONE;
   2263  1.7  christos 	}
   2264  1.7  christos       else if ((first & op->mask) == op->match)
   2265  1.7  christos 	{
   2266  1.7  christos 	  match = MATCH_SHORT;
   2267  1.7  christos 	  second = 0;
   2268  1.7  christos 	  full = first;
   2269  1.1     skrll 	}
   2270  1.7  christos       else if ((first & 0xf800) == 0xf000
   2271  1.1     skrll 	       && have_second
   2272  1.7  christos 	       && !extend_only
   2273  1.7  christos 	       && (second & op->mask) == op->match)
   2274  1.7  christos 	{
   2275  1.7  christos 	  if (op->pinfo2 & INSN2_SHORT_ONLY)
   2276  1.7  christos 	    {
   2277  1.7  christos 	      match = MATCH_NONE;
   2278  1.7  christos 	      extend_only = TRUE;
   2279  1.7  christos 	    }
   2280  1.1     skrll 	  else
   2281  1.7  christos 	    match = MATCH_FULL;
   2282  1.7  christos 	}
   2283  1.7  christos       else
   2284  1.1     skrll 	match = MATCH_NONE;
   2285  1.4  christos 
   2286  1.1     skrll       if (match != MATCH_NONE)
   2287  1.4  christos 	{
   2288  1.1     skrll 	  const char *s;
   2289  1.5  christos 
   2290  1.1     skrll 	  infprintf (is, "%s", op->name);
   2291  1.1     skrll 	  if (op->args[0] != '\0')
   2292  1.1     skrll 	    infprintf (is, "\t");
   2293  1.1     skrll 
   2294  1.7  christos 	  init_print_arg_state (&state);
   2295  1.1     skrll 	  for (s = op->args; *s != '\0'; s++)
   2296  1.1     skrll 	    {
   2297  1.1     skrll 	      if (*s == ','
   2298  1.1     skrll 		  && s[1] == 'w'
   2299  1.1     skrll 		  && GET_OP (full, RX) == GET_OP (full, RY))
   2300  1.1     skrll 		{
   2301  1.1     skrll 		  /* Skip the register and the comma.  */
   2302  1.7  christos 		  ++s;
   2303  1.1     skrll 		  continue;
   2304  1.1     skrll 		}
   2305  1.1     skrll 	      if (*s == ','
   2306  1.1     skrll 		  && s[1] == 'v'
   2307  1.1     skrll 		  && GET_OP (full, RZ) == GET_OP (full, RX))
   2308  1.7  christos 		{
   2309  1.7  christos 		  /* Skip the register and the comma.  */
   2310  1.7  christos 		  ++s;
   2311  1.7  christos 		  continue;
   2312  1.7  christos 		}
   2313  1.7  christos 	      if (s[0] == 'N'
   2314  1.7  christos 		  && s[1] == ','
   2315  1.7  christos 		  && s[2] == 'O'
   2316  1.7  christos 		  && op->name[strlen (op->name) - 1] == '0')
   2317  1.7  christos 		{
   2318  1.7  christos 		  /* Coprocessor register 0 with sel field.  */
   2319  1.7  christos 		  const struct mips_cp0sel_name *n;
   2320  1.7  christos 		  const struct mips_operand *operand;
   2321  1.7  christos 		  unsigned int reg, sel;
   2322  1.7  christos 
   2323  1.7  christos 		  operand = decode_mips16_operand (*s, TRUE);
   2324  1.7  christos 		  reg = mips_extract_operand (operand, (first << 16) | second);
   2325  1.7  christos 		  s += 2;
   2326  1.7  christos 		  operand = decode_mips16_operand (*s, TRUE);
   2327  1.7  christos 		  sel = mips_extract_operand (operand, (first << 16) | second);
   2328  1.7  christos 
   2329  1.7  christos 		  /* CP0 register including 'sel' code for mftc0, to be
   2330  1.7  christos 		     printed textually if known.  If not known, print both
   2331  1.7  christos 		     CP0 register name and sel numerically since CP0 register
   2332  1.7  christos 		     with sel 0 may have a name unrelated to register being
   2333  1.7  christos 		     printed.  */
   2334  1.7  christos 		  n = lookup_mips_cp0sel_name (mips_cp0sel_names,
   2335  1.7  christos 					       mips_cp0sel_names_len,
   2336  1.7  christos 					       reg, sel);
   2337  1.7  christos 		  if (n != NULL)
   2338  1.7  christos 		    infprintf (is, "%s", n->name);
   2339  1.7  christos 		  else
   2340  1.7  christos 		    infprintf (is, "$%d,%d", reg, sel);
   2341  1.7  christos 		}
   2342  1.7  christos 	      else
   2343  1.7  christos 		switch (match)
   2344  1.7  christos 		  {
   2345  1.7  christos 		    case MATCH_FULL:
   2346  1.7  christos 		      print_mips16_insn_arg (info, &state, op, *s, memaddr + 2,
   2347  1.7  christos 					     second, TRUE, first, s[1] == '(');
   2348  1.7  christos 		      break;
   2349  1.7  christos 		    case MATCH_SHORT:
   2350  1.7  christos 		      print_mips16_insn_arg (info, &state, op, *s, memaddr,
   2351  1.1     skrll 					     first, FALSE, 0, s[1] == '(');
   2352  1.1     skrll 		      break;
   2353  1.3  christos 		    case MATCH_NONE:	/* Stop the compiler complaining.  */
   2354  1.1     skrll 		      break;
   2355  1.3  christos 		  }
   2356  1.5  christos 	    }
   2357  1.5  christos 
   2358  1.1     skrll 	  /* Figure out branch instruction type and delay slot information.  */
   2359  1.3  christos 	  if ((op->pinfo & INSN_UNCOND_BRANCH_DELAY) != 0)
   2360  1.3  christos 	    info->branch_delay_insns = 1;
   2361  1.3  christos 	  if ((op->pinfo & INSN_UNCOND_BRANCH_DELAY) != 0
   2362  1.1     skrll 	      || (op->pinfo2 & INSN2_UNCOND_BRANCH) != 0)
   2363  1.1     skrll 	    {
   2364  1.5  christos 	      if ((op->pinfo & INSN_WRITE_GPR_31) != 0)
   2365  1.3  christos 		info->insn_type = dis_jsr;
   2366  1.1     skrll 	      else
   2367  1.7  christos 		info->insn_type = dis_branch;
   2368  1.1     skrll 	    }
   2369  1.1     skrll 	  else if ((op->pinfo2 & INSN2_COND_BRANCH) != 0)
   2370  1.4  christos 	    info->insn_type = dis_condbranch;
   2371  1.1     skrll 
   2372  1.7  christos 	  return match == MATCH_FULL ? 4 : 2;
   2373  1.4  christos 	}
   2374  1.4  christos     }
   2375  1.7  christos #undef GET_OP
   2376  1.4  christos 
   2377  1.4  christos   infprintf (is, "0x%x", first);
   2378  1.4  christos   info->insn_type = dis_noninsn;
   2379  1.4  christos 
   2380  1.4  christos   return 2;
   2381  1.4  christos }
   2382  1.4  christos 
   2383  1.4  christos /* Disassemble microMIPS instructions.  */
   2384  1.4  christos 
   2385  1.4  christos static int
   2386  1.4  christos print_insn_micromips (bfd_vma memaddr, struct disassemble_info *info)
   2387  1.5  christos {
   2388  1.5  christos   const fprintf_ftype infprintf = info->fprintf_func;
   2389  1.4  christos   const struct mips_opcode *op, *opend;
   2390  1.5  christos   void *is = info->stream;
   2391  1.4  christos   bfd_byte buffer[2];
   2392  1.4  christos   unsigned int higher;
   2393  1.4  christos   unsigned int length;
   2394  1.4  christos   int status;
   2395  1.4  christos   unsigned int insn;
   2396  1.4  christos 
   2397  1.4  christos   info->bytes_per_chunk = 2;
   2398  1.4  christos   info->display_endian = info->endian;
   2399  1.4  christos   info->insn_info_valid = 1;
   2400  1.4  christos   info->branch_delay_insns = 0;
   2401  1.4  christos   info->data_size = 0;
   2402  1.4  christos   info->insn_type = dis_nonbranch;
   2403  1.4  christos   info->target = 0;
   2404  1.4  christos   info->target2 = 0;
   2405  1.4  christos 
   2406  1.4  christos   status = (*info->read_memory_func) (memaddr, buffer, 2, info);
   2407  1.4  christos   if (status != 0)
   2408  1.4  christos     {
   2409  1.4  christos       (*info->memory_error_func) (status, memaddr, info);
   2410  1.4  christos       return -1;
   2411  1.4  christos     }
   2412  1.4  christos 
   2413  1.4  christos   length = 2;
   2414  1.4  christos 
   2415  1.6  christos   if (info->endian == BFD_ENDIAN_BIG)
   2416  1.4  christos     insn = bfd_getb16 (buffer);
   2417  1.4  christos   else
   2418  1.4  christos     insn = bfd_getl16 (buffer);
   2419  1.4  christos 
   2420  1.4  christos   if ((insn & 0x1c00) == 0x0000 || (insn & 0x1000) == 0x1000)
   2421  1.4  christos     {
   2422  1.4  christos       /* This is a 32-bit microMIPS instruction.  */
   2423  1.4  christos       higher = insn;
   2424  1.4  christos 
   2425  1.4  christos       status = (*info->read_memory_func) (memaddr + 2, buffer, 2, info);
   2426  1.4  christos       if (status != 0)
   2427  1.4  christos 	{
   2428  1.4  christos 	  infprintf (is, "micromips 0x%x", higher);
   2429  1.4  christos 	  (*info->memory_error_func) (status, memaddr + 2, info);
   2430  1.4  christos 	  return -1;
   2431  1.4  christos 	}
   2432  1.4  christos 
   2433  1.4  christos       if (info->endian == BFD_ENDIAN_BIG)
   2434  1.4  christos 	insn = bfd_getb16 (buffer);
   2435  1.4  christos       else
   2436  1.4  christos 	insn = bfd_getl16 (buffer);
   2437  1.4  christos 
   2438  1.4  christos       insn = insn | (higher << 16);
   2439  1.4  christos 
   2440  1.4  christos       length += 2;
   2441  1.4  christos     }
   2442  1.4  christos 
   2443  1.4  christos   /* FIXME: Should probably use a hash table on the major opcode here.  */
   2444  1.4  christos 
   2445  1.4  christos   opend = micromips_opcodes + bfd_micromips_num_opcodes;
   2446  1.4  christos   for (op = micromips_opcodes; op < opend; op++)
   2447  1.4  christos     {
   2448  1.4  christos       if (op->pinfo != INSN_MACRO
   2449  1.5  christos 	  && !(no_aliases && (op->pinfo2 & INSN2_ALIAS))
   2450  1.5  christos 	  && (insn & op->mask) == op->match
   2451  1.4  christos 	  && ((length == 2 && (op->mask & 0xffff0000) == 0)
   2452  1.4  christos 	      || (length == 4 && (op->mask & 0xffff0000) != 0)))
   2453  1.4  christos 	{
   2454  1.5  christos 	  if (!validate_insn_args (op, decode_micromips_operand, insn))
   2455  1.4  christos 	    continue;
   2456  1.5  christos 
   2457  1.5  christos 	  infprintf (is, "%s", op->name);
   2458  1.5  christos 
   2459  1.4  christos 	  if (op->args[0])
   2460  1.4  christos 	    {
   2461  1.4  christos 	      infprintf (is, "\t");
   2462  1.4  christos 	      print_insn_args (info, op, decode_micromips_operand, insn,
   2463  1.4  christos 			       memaddr + 1, length);
   2464  1.4  christos 	    }
   2465  1.4  christos 
   2466  1.4  christos 	  /* Figure out instruction type and branch delay information.  */
   2467  1.4  christos 	  if ((op->pinfo
   2468  1.5  christos 	       & (INSN_UNCOND_BRANCH_DELAY | INSN_COND_BRANCH_DELAY)) != 0)
   2469  1.4  christos 	    info->branch_delay_insns = 1;
   2470  1.4  christos 	  if (((op->pinfo & INSN_UNCOND_BRANCH_DELAY)
   2471  1.4  christos 	       | (op->pinfo2 & INSN2_UNCOND_BRANCH)) != 0)
   2472  1.4  christos 	    {
   2473  1.4  christos 	      if ((op->pinfo & (INSN_WRITE_GPR_31 | INSN_WRITE_1)) != 0)
   2474  1.4  christos 		info->insn_type = dis_jsr;
   2475  1.4  christos 	      else
   2476  1.4  christos 		info->insn_type = dis_branch;
   2477  1.4  christos 	    }
   2478  1.4  christos 	  else if (((op->pinfo & INSN_COND_BRANCH_DELAY)
   2479  1.4  christos 		    | (op->pinfo2 & INSN2_COND_BRANCH)) != 0)
   2480  1.4  christos 	    {
   2481  1.4  christos 	      if ((op->pinfo & INSN_WRITE_GPR_31) != 0)
   2482  1.5  christos 		info->insn_type = dis_condjsr;
   2483  1.4  christos 	      else
   2484  1.4  christos 		info->insn_type = dis_condbranch;
   2485  1.4  christos 	    }
   2486  1.4  christos 	  else if ((op->pinfo
   2487  1.4  christos 		    & (INSN_STORE_MEMORY | INSN_LOAD_MEMORY)) != 0)
   2488  1.4  christos 	    info->insn_type = dis_dref;
   2489  1.4  christos 
   2490  1.1     skrll 	  return length;
   2491  1.1     skrll 	}
   2492  1.1     skrll     }
   2493  1.1     skrll 
   2494  1.1     skrll   infprintf (is, "0x%x", insn);
   2495  1.4  christos   info->insn_type = dis_noninsn;
   2496  1.6  christos 
   2497  1.6  christos   return length;
   2498  1.6  christos }
   2499  1.6  christos 
   2500  1.6  christos /* Return 1 if a symbol associated with the location being disassembled
   2501  1.6  christos    indicates a compressed mode, either MIPS16 or microMIPS, according to
   2502  1.4  christos    MICROMIPS_P.  We iterate over all the symbols at the address being
   2503  1.4  christos    considered assuming if at least one of them indicates code compression,
   2504  1.6  christos    then such code has been genuinely produced here (other symbols could
   2505  1.4  christos    have been derived from function symbols defined elsewhere or could
   2506  1.4  christos    define data).  Otherwise, return 0.  */
   2507  1.5  christos 
   2508  1.4  christos static bfd_boolean
   2509  1.5  christos is_compressed_mode_p (struct disassemble_info *info, bfd_boolean micromips_p)
   2510  1.5  christos {
   2511  1.6  christos   int i;
   2512  1.5  christos   int l;
   2513  1.6  christos 
   2514  1.5  christos   for (i = info->symtab_pos, l = i + info->num_symbols; i < l; i++)
   2515  1.5  christos     if (((info->symtab[i])->flags & BSF_SYNTHETIC) != 0
   2516  1.5  christos 	&& ((!micromips_p
   2517  1.5  christos 	     && ELF_ST_IS_MIPS16 ((*info->symbols)->udata.i))
   2518  1.5  christos 	    || (micromips_p
   2519  1.5  christos 		&& ELF_ST_IS_MICROMIPS ((*info->symbols)->udata.i))))
   2520  1.6  christos       return 1;
   2521  1.5  christos     else if (bfd_asymbol_flavour (info->symtab[i]) == bfd_target_elf_flavour
   2522  1.6  christos 	      && info->symtab[i]->section == info->section)
   2523  1.5  christos       {
   2524  1.5  christos 	elf_symbol_type *symbol = (elf_symbol_type *) info->symtab[i];
   2525  1.5  christos 	if ((!micromips_p
   2526  1.4  christos 	     && ELF_ST_IS_MIPS16 (symbol->internal_elf_sym.st_other))
   2527  1.4  christos 	    || (micromips_p
   2528  1.4  christos 		&& ELF_ST_IS_MICROMIPS (symbol->internal_elf_sym.st_other)))
   2529  1.4  christos 	  return 1;
   2530  1.1     skrll       }
   2531  1.1     skrll 
   2532  1.1     skrll   return 0;
   2533  1.1     skrll }
   2534  1.1     skrll 
   2535  1.1     skrll /* In an environment where we do not know the symbol type of the
   2536  1.1     skrll    instruction we are forced to assume that the low order bit of the
   2537  1.1     skrll    instructions' address may mark it as a mips16 instruction.  If we
   2538  1.1     skrll    are single stepping, or the pc is within the disassembled function,
   2539  1.1     skrll    this works.  Otherwise, we need a clue.  Sometimes.  */
   2540  1.1     skrll 
   2541  1.1     skrll static int
   2542  1.1     skrll _print_insn_mips (bfd_vma memaddr,
   2543  1.1     skrll 		  struct disassemble_info *info,
   2544  1.1     skrll 		  enum bfd_endian endianness)
   2545  1.1     skrll {
   2546  1.1     skrll   bfd_byte buffer[INSNLEN];
   2547  1.4  christos   int status;
   2548  1.4  christos 
   2549  1.4  christos   set_default_mips_dis_options (info);
   2550  1.4  christos   parse_mips_dis_options (info->disassembler_options);
   2551  1.4  christos 
   2552  1.1     skrll   if (info->mach == bfd_mach_mips16)
   2553  1.4  christos     return print_insn_mips16 (memaddr, info);
   2554  1.1     skrll   if (info->mach == bfd_mach_mips_micromips)
   2555  1.1     skrll     return print_insn_micromips (memaddr, info);
   2556  1.6  christos 
   2557  1.6  christos #if 1
   2558  1.6  christos   /* FIXME: If odd address, this is CLEARLY a compressed instruction.  */
   2559  1.6  christos   /* Only a few tools will work this way.  */
   2560  1.6  christos   if (memaddr & 0x01)
   2561  1.6  christos     {
   2562  1.1     skrll       if (micromips_ase)
   2563  1.1     skrll 	return print_insn_micromips (memaddr, info);
   2564  1.1     skrll       else
   2565  1.6  christos 	return print_insn_mips16 (memaddr, info);
   2566  1.6  christos     }
   2567  1.6  christos #endif
   2568  1.6  christos 
   2569  1.1     skrll #if SYMTAB_AVAILABLE
   2570  1.1     skrll   if (is_compressed_mode_p (info, TRUE))
   2571  1.1     skrll     return print_insn_micromips (memaddr, info);
   2572  1.1     skrll   if (is_compressed_mode_p (info, FALSE))
   2573  1.1     skrll     return print_insn_mips16 (memaddr, info);
   2574  1.4  christos #endif
   2575  1.1     skrll 
   2576  1.1     skrll   status = (*info->read_memory_func) (memaddr, buffer, INSNLEN, info);
   2577  1.4  christos   if (status == 0)
   2578  1.1     skrll     {
   2579  1.4  christos       int insn;
   2580  1.1     skrll 
   2581  1.1     skrll       if (endianness == BFD_ENDIAN_BIG)
   2582  1.1     skrll 	insn = bfd_getb32 (buffer);
   2583  1.1     skrll       else
   2584  1.1     skrll 	insn = bfd_getl32 (buffer);
   2585  1.1     skrll 
   2586  1.1     skrll       return print_insn_mips (memaddr, insn, info);
   2587  1.1     skrll     }
   2588  1.1     skrll   else
   2589  1.1     skrll     {
   2590  1.1     skrll       (*info->memory_error_func) (status, memaddr, info);
   2591  1.1     skrll       return -1;
   2592  1.1     skrll     }
   2593  1.1     skrll }
   2594  1.1     skrll 
   2595  1.1     skrll int
   2596  1.1     skrll print_insn_big_mips (bfd_vma memaddr, struct disassemble_info *info)
   2597  1.1     skrll {
   2598  1.1     skrll   return _print_insn_mips (memaddr, info, BFD_ENDIAN_BIG);
   2599  1.1     skrll }
   2600  1.1     skrll 
   2601  1.1     skrll int
   2602  1.9  christos print_insn_little_mips (bfd_vma memaddr, struct disassemble_info *info)
   2603  1.9  christos {
   2604  1.9  christos   return _print_insn_mips (memaddr, info, BFD_ENDIAN_LITTLE);
   2605  1.9  christos }
   2606  1.9  christos 
   2607  1.9  christos /* Indices into option argument vector for options accepting an argument.
   2609  1.9  christos    Use MIPS_OPTION_ARG_NONE for options accepting no argument.  */
   2610  1.9  christos typedef enum
   2611  1.9  christos {
   2612  1.9  christos   MIPS_OPTION_ARG_NONE = -1,
   2613  1.9  christos   MIPS_OPTION_ARG_ABI,
   2614  1.9  christos   MIPS_OPTION_ARG_ARCH,
   2615  1.9  christos   MIPS_OPTION_ARG_SIZE
   2616  1.9  christos } mips_option_arg_t;
   2617  1.9  christos 
   2618  1.9  christos /* Valid MIPS disassembler options.  */
   2619  1.9  christos static struct
   2620  1.9  christos {
   2621  1.9  christos   const char *name;
   2622  1.9  christos   const char *description;
   2623  1.9  christos   mips_option_arg_t arg;
   2624  1.9  christos } mips_options[] =
   2625  1.9  christos {
   2626  1.9  christos   { "no-aliases", N_("Use canonical instruction forms.\n"),
   2627  1.9  christos 		  MIPS_OPTION_ARG_NONE },
   2628  1.9  christos   { "msa",        N_("Recognize MSA instructions.\n"),
   2629  1.9  christos 		  MIPS_OPTION_ARG_NONE },
   2630  1.9  christos   { "virt",       N_("Recognize the virtualization ASE instructions.\n"),
   2631  1.9  christos 		  MIPS_OPTION_ARG_NONE },
   2632  1.9  christos   { "xpa",        N_("Recognize the eXtended Physical Address (XPA) ASE\n\
   2633  1.9  christos                   instructions.\n"),
   2634  1.9  christos 		  MIPS_OPTION_ARG_NONE },
   2635  1.9  christos   { "ginv",       N_("Recognize the Global INValidate (GINV) ASE "
   2636  1.9  christos 		     "instructions.\n"),
   2637  1.9  christos 		  MIPS_OPTION_ARG_NONE },
   2638  1.9  christos   { "loongson-mmi",
   2639  1.9  christos 		  N_("Recognize the Loongson MultiMedia extensions "
   2640  1.9  christos 		     "Instructions (MMI) ASE instructions.\n"),
   2641  1.9  christos 		  MIPS_OPTION_ARG_NONE },
   2642  1.9  christos   { "loongson-cam",
   2643  1.9  christos 		  N_("Recognize the Loongson Content Address Memory (CAM) "
   2644  1.9  christos 		     " instructions.\n"),
   2645  1.9  christos 		  MIPS_OPTION_ARG_NONE },
   2646  1.9  christos   { "loongson-ext",
   2647  1.9  christos 		  N_("Recognize the Loongson EXTensions (EXT) "
   2648  1.9  christos 		     " instructions.\n"),
   2649  1.9  christos 		  MIPS_OPTION_ARG_NONE },
   2650  1.9  christos   { "loongson-ext2",
   2651  1.9  christos 		  N_("Recognize the Loongson EXTensions R2 (EXT2) "
   2652  1.9  christos 		     " instructions.\n"),
   2653  1.9  christos 		  MIPS_OPTION_ARG_NONE },
   2654  1.9  christos   { "gpr-names=", N_("Print GPR names according to specified ABI.\n\
   2655  1.9  christos                   Default: based on binary being disassembled.\n"),
   2656  1.9  christos 		  MIPS_OPTION_ARG_ABI },
   2657  1.9  christos   { "fpr-names=", N_("Print FPR names according to specified ABI.\n\
   2658  1.9  christos                   Default: numeric.\n"),
   2659  1.9  christos 		  MIPS_OPTION_ARG_ABI },
   2660  1.9  christos   { "cp0-names=", N_("Print CP0 register names according to specified "
   2661  1.9  christos 		     "architecture.\n\
   2662  1.9  christos                   Default: based on binary being disassembled.\n"),
   2663  1.9  christos 		  MIPS_OPTION_ARG_ARCH },
   2664  1.9  christos   { "hwr-names=", N_("Print HWR names according to specified architecture.\n\
   2665  1.9  christos                   Default: based on binary being disassembled.\n"),
   2666  1.9  christos 		  MIPS_OPTION_ARG_ARCH },
   2667  1.9  christos   { "reg-names=", N_("Print GPR and FPR names according to specified ABI.\n"),
   2668  1.9  christos 		  MIPS_OPTION_ARG_ABI },
   2669  1.9  christos   { "reg-names=", N_("Print CP0 register and HWR names according to "
   2670  1.9  christos 		     "specified\n\
   2671  1.9  christos                   architecture."),
   2672  1.9  christos 		  MIPS_OPTION_ARG_ARCH }
   2673  1.9  christos };
   2674  1.9  christos 
   2675  1.9  christos /* Build the structure representing valid MIPS disassembler options.
   2676  1.9  christos    This is done dynamically for maintenance ease purpose; a static
   2677  1.9  christos    initializer would be unreadable.  */
   2678  1.9  christos 
   2679  1.9  christos const disasm_options_and_args_t *
   2680  1.9  christos disassembler_options_mips (void)
   2681  1.9  christos {
   2682  1.9  christos   static disasm_options_and_args_t *opts_and_args;
   2683  1.9  christos 
   2684  1.9  christos   if (opts_and_args == NULL)
   2685  1.9  christos     {
   2686  1.9  christos       size_t num_options = ARRAY_SIZE (mips_options);
   2687  1.9  christos       size_t num_args = MIPS_OPTION_ARG_SIZE;
   2688  1.9  christos       disasm_option_arg_t *args;
   2689  1.9  christos       disasm_options_t *opts;
   2690  1.9  christos       size_t i;
   2691  1.9  christos       size_t j;
   2692  1.9  christos 
   2693  1.9  christos       args = XNEWVEC (disasm_option_arg_t, num_args + 1);
   2694  1.9  christos 
   2695  1.9  christos       args[MIPS_OPTION_ARG_ABI].name = "ABI";
   2696  1.9  christos       args[MIPS_OPTION_ARG_ABI].values
   2697  1.9  christos 	= XNEWVEC (const char *, ARRAY_SIZE (mips_abi_choices) + 1);
   2698  1.9  christos       for (i = 0; i < ARRAY_SIZE (mips_abi_choices); i++)
   2699  1.9  christos 	args[MIPS_OPTION_ARG_ABI].values[i] = mips_abi_choices[i].name;
   2700  1.9  christos       /* The array we return must be NULL terminated.  */
   2701  1.9  christos       args[MIPS_OPTION_ARG_ABI].values[i] = NULL;
   2702  1.9  christos 
   2703  1.9  christos       args[MIPS_OPTION_ARG_ARCH].name = "ARCH";
   2704  1.9  christos       args[MIPS_OPTION_ARG_ARCH].values
   2705  1.9  christos 	= XNEWVEC (const char *, ARRAY_SIZE (mips_arch_choices) + 1);
   2706  1.9  christos       for (i = 0, j = 0; i < ARRAY_SIZE (mips_arch_choices); i++)
   2707  1.9  christos 	if (*mips_arch_choices[i].name != '\0')
   2708  1.9  christos 	  args[MIPS_OPTION_ARG_ARCH].values[j++] = mips_arch_choices[i].name;
   2709  1.9  christos       /* The array we return must be NULL terminated.  */
   2710  1.9  christos       args[MIPS_OPTION_ARG_ARCH].values[j] = NULL;
   2711  1.9  christos 
   2712  1.9  christos       /* The array we return must be NULL terminated.  */
   2713  1.9  christos       args[MIPS_OPTION_ARG_SIZE].name = NULL;
   2714  1.9  christos       args[MIPS_OPTION_ARG_SIZE].values = NULL;
   2715  1.9  christos 
   2716  1.9  christos       opts_and_args = XNEW (disasm_options_and_args_t);
   2717  1.9  christos       opts_and_args->args = args;
   2718  1.9  christos 
   2719  1.9  christos       opts = &opts_and_args->options;
   2720  1.9  christos       opts->name = XNEWVEC (const char *, num_options + 1);
   2721  1.9  christos       opts->description = XNEWVEC (const char *, num_options + 1);
   2722  1.9  christos       opts->arg = XNEWVEC (const disasm_option_arg_t *, num_options + 1);
   2723  1.9  christos       for (i = 0; i < num_options; i++)
   2724  1.9  christos 	{
   2725  1.9  christos 	  opts->name[i] = mips_options[i].name;
   2726  1.9  christos 	  opts->description[i] = _(mips_options[i].description);
   2727  1.9  christos 	  if (mips_options[i].arg != MIPS_OPTION_ARG_NONE)
   2728  1.9  christos 	    opts->arg[i] = &args[mips_options[i].arg];
   2729  1.9  christos 	  else
   2730  1.9  christos 	    opts->arg[i] = NULL;
   2731  1.9  christos 	}
   2732  1.9  christos       /* The array we return must be NULL terminated.  */
   2733  1.9  christos       opts->name[i] = NULL;
   2734  1.9  christos       opts->description[i] = NULL;
   2735  1.1     skrll       opts->arg[i] = NULL;
   2736  1.1     skrll     }
   2737  1.1     skrll 
   2738  1.9  christos   return opts_and_args;
   2739  1.9  christos }
   2740  1.9  christos 
   2741  1.9  christos void
   2742  1.9  christos print_mips_disassembler_options (FILE *stream)
   2743  1.9  christos {
   2744  1.9  christos   const disasm_options_and_args_t *opts_and_args;
   2745  1.9  christos   const disasm_option_arg_t *args;
   2746  1.9  christos   const disasm_options_t *opts;
   2747  1.9  christos   size_t max_len = 0;
   2748  1.1     skrll   size_t i;
   2749  1.1     skrll   size_t j;
   2750  1.1     skrll 
   2751  1.9  christos   opts_and_args = disassembler_options_mips ();
   2752  1.1     skrll   opts = &opts_and_args->options;
   2753  1.9  christos   args = opts_and_args->args;
   2754  1.9  christos 
   2755  1.9  christos   fprintf (stream, _("\n\
   2756  1.9  christos The following MIPS specific disassembler options are supported for use\n\
   2757  1.7  christos with the -M switch (multiple options should be separated by commas):\n\n"));
   2758  1.9  christos 
   2759  1.9  christos   /* Compute the length of the longest option name.  */
   2760  1.9  christos   for (i = 0; opts->name[i] != NULL; i++)
   2761  1.9  christos     {
   2762  1.9  christos       size_t len = strlen (opts->name[i]);
   2763  1.5  christos 
   2764  1.9  christos       if (opts->arg[i] != NULL)
   2765  1.9  christos 	len += strlen (opts->arg[i]->name);
   2766  1.9  christos       if (max_len < len)
   2767  1.9  christos 	max_len = len;
   2768  1.9  christos     }
   2769  1.9  christos 
   2770  1.9  christos   for (i = 0, max_len++; opts->name[i] != NULL; i++)
   2771  1.9  christos     {
   2772  1.5  christos       fprintf (stream, "  %s", opts->name[i]);
   2773  1.9  christos       if (opts->arg[i] != NULL)
   2774  1.9  christos 	fprintf (stream, "%s", opts->arg[i]->name);
   2775  1.9  christos       if (opts->description[i] != NULL)
   2776  1.9  christos 	{
   2777  1.9  christos 	  size_t len = strlen (opts->name[i]);
   2778  1.9  christos 
   2779  1.9  christos 	  if (opts->arg[i] != NULL)
   2780  1.5  christos 	    len += strlen (opts->arg[i]->name);
   2781  1.9  christos 	  fprintf (stream,
   2782  1.9  christos 		   "%*c %s", (int) (max_len - len), ' ', opts->description[i]);
   2783  1.9  christos 	}
   2784  1.9  christos       fprintf (stream, _("\n"));
   2785  1.9  christos     }
   2786  1.9  christos 
   2787  1.9  christos   for (i = 0; args[i].name != NULL; i++)
   2788  1.9  christos     {
   2789  1.9  christos       fprintf (stream, _("\n\
   2790  1.1     skrll   For the options above, the following values are supported for \"%s\":\n   "),
   2791  1.1     skrll 	       args[i].name);
   2792  1.1     skrll       for (j = 0; args[i].values[j] != NULL; j++)
   2793                	fprintf (stream, " %s", args[i].values[j]);
   2794                      fprintf (stream, _("\n"));
   2795                    }
   2796                
   2797                  fprintf (stream, _("\n"));
   2798                }
   2799