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