Back to index

cell-binutils  2.17cvs20070401
mips-dis.c
Go to the documentation of this file.
00001 /* Print mips instructions for GDB, the GNU debugger, or for objdump.
00002    Copyright 1989, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
00003    2000, 2001, 2002, 2003, 2005
00004    Free Software Foundation, Inc.
00005    Contributed by Nobuyuki Hikichi(hikichi@sra.co.jp).
00006 
00007    This file is part of GDB, GAS, and the GNU binutils.
00008 
00009    This program is free software; you can redistribute it and/or modify
00010    it under the terms of the GNU General Public License as published by
00011    the Free Software Foundation; either version 2 of the License, or
00012    (at your option) any later version.
00013 
00014    This program is distributed in the hope that it will be useful,
00015    but WITHOUT ANY WARRANTY; without even the implied warranty of
00016    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017    GNU General Public License for more details.
00018 
00019    You should have received a copy of the GNU General Public License
00020    along with this program; if not, write to the Free Software
00021    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
00022    MA 02110-1301, USA.  */
00023 
00024 #include "sysdep.h"
00025 #include "dis-asm.h"
00026 #include "libiberty.h"
00027 #include "opcode/mips.h"
00028 #include "opintl.h"
00029 
00030 /* FIXME: These are needed to figure out if the code is mips16 or
00031    not. The low bit of the address is often a good indicator.  No
00032    symbol table is available when this code runs out in an embedded
00033    system as when it is used for disassembler support in a monitor.  */
00034 
00035 #if !defined(EMBEDDED_ENV)
00036 #define SYMTAB_AVAILABLE 1
00037 #include "elf-bfd.h"
00038 #include "elf/mips.h"
00039 #endif
00040 
00041 /* Mips instructions are at maximum this many bytes long.  */
00042 #define INSNLEN 4
00043 
00044 
00045 /* FIXME: These should be shared with gdb somehow.  */
00046 
00047 struct mips_cp0sel_name
00048 {
00049   unsigned int cp0reg;
00050   unsigned int sel;
00051   const char * const name;
00052 };
00053 
00054 /* The mips16 registers.  */
00055 static const unsigned int mips16_to_32_reg_map[] =
00056 {
00057   16, 17, 2, 3, 4, 5, 6, 7
00058 };
00059 
00060 #define mips16_reg_names(rn)       mips_gpr_names[mips16_to_32_reg_map[rn]]
00061 
00062 
00063 static const char * const mips_gpr_names_numeric[32] =
00064 {
00065   "$0",   "$1",   "$2",   "$3",   "$4",   "$5",   "$6",   "$7",
00066   "$8",   "$9",   "$10",  "$11",  "$12",  "$13",  "$14",  "$15",
00067   "$16",  "$17",  "$18",  "$19",  "$20",  "$21",  "$22",  "$23",
00068   "$24",  "$25",  "$26",  "$27",  "$28",  "$29",  "$30",  "$31"
00069 };
00070 
00071 static const char * const mips_gpr_names_oldabi[32] =
00072 {
00073   "zero", "at",   "v0",   "v1",   "a0",   "a1",   "a2",   "a3",
00074   "t0",   "t1",   "t2",   "t3",   "t4",   "t5",   "t6",   "t7",
00075   "s0",   "s1",   "s2",   "s3",   "s4",   "s5",   "s6",   "s7",
00076   "t8",   "t9",   "k0",   "k1",   "gp",   "sp",   "s8",   "ra"
00077 };
00078 
00079 static const char * const mips_gpr_names_newabi[32] =
00080 {
00081   "zero", "at",   "v0",   "v1",   "a0",   "a1",   "a2",   "a3",
00082   "a4",   "a5",   "a6",   "a7",   "t0",   "t1",   "t2",   "t3",
00083   "s0",   "s1",   "s2",   "s3",   "s4",   "s5",   "s6",   "s7",
00084   "t8",   "t9",   "k0",   "k1",   "gp",   "sp",   "s8",   "ra"
00085 };
00086 
00087 static const char * const mips_fpr_names_numeric[32] =
00088 {
00089   "$f0",  "$f1",  "$f2",  "$f3",  "$f4",  "$f5",  "$f6",  "$f7",
00090   "$f8",  "$f9",  "$f10", "$f11", "$f12", "$f13", "$f14", "$f15",
00091   "$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23",
00092   "$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31"
00093 };
00094 
00095 static const char * const mips_fpr_names_32[32] =
00096 {
00097   "fv0",  "fv0f", "fv1",  "fv1f", "ft0",  "ft0f", "ft1",  "ft1f",
00098   "ft2",  "ft2f", "ft3",  "ft3f", "fa0",  "fa0f", "fa1",  "fa1f",
00099   "ft4",  "ft4f", "ft5",  "ft5f", "fs0",  "fs0f", "fs1",  "fs1f",
00100   "fs2",  "fs2f", "fs3",  "fs3f", "fs4",  "fs4f", "fs5",  "fs5f"
00101 };
00102 
00103 static const char * const mips_fpr_names_n32[32] =
00104 {
00105   "fv0",  "ft14", "fv1",  "ft15", "ft0",  "ft1",  "ft2",  "ft3",
00106   "ft4",  "ft5",  "ft6",  "ft7",  "fa0",  "fa1",  "fa2",  "fa3",
00107   "fa4",  "fa5",  "fa6",  "fa7",  "fs0",  "ft8",  "fs1",  "ft9",
00108   "fs2",  "ft10", "fs3",  "ft11", "fs4",  "ft12", "fs5",  "ft13"
00109 };
00110 
00111 static const char * const mips_fpr_names_64[32] =
00112 {
00113   "fv0",  "ft12", "fv1",  "ft13", "ft0",  "ft1",  "ft2",  "ft3",
00114   "ft4",  "ft5",  "ft6",  "ft7",  "fa0",  "fa1",  "fa2",  "fa3",
00115   "fa4",  "fa5",  "fa6",  "fa7",  "ft8",  "ft9",  "ft10", "ft11",
00116   "fs0",  "fs1",  "fs2",  "fs3",  "fs4",  "fs5",  "fs6",  "fs7"
00117 };
00118 
00119 static const char * const mips_cp0_names_numeric[32] =
00120 {
00121   "$0",   "$1",   "$2",   "$3",   "$4",   "$5",   "$6",   "$7",
00122   "$8",   "$9",   "$10",  "$11",  "$12",  "$13",  "$14",  "$15",
00123   "$16",  "$17",  "$18",  "$19",  "$20",  "$21",  "$22",  "$23",
00124   "$24",  "$25",  "$26",  "$27",  "$28",  "$29",  "$30",  "$31"
00125 };
00126 
00127 static const char * const mips_cp0_names_mips3264[32] =
00128 {
00129   "c0_index",     "c0_random",    "c0_entrylo0",  "c0_entrylo1",
00130   "c0_context",   "c0_pagemask",  "c0_wired",     "$7",
00131   "c0_badvaddr",  "c0_count",     "c0_entryhi",   "c0_compare",
00132   "c0_status",    "c0_cause",     "c0_epc",       "c0_prid",
00133   "c0_config",    "c0_lladdr",    "c0_watchlo",   "c0_watchhi",
00134   "c0_xcontext",  "$21",          "$22",          "c0_debug",
00135   "c0_depc",      "c0_perfcnt",   "c0_errctl",    "c0_cacheerr",
00136   "c0_taglo",     "c0_taghi",     "c0_errorepc",  "c0_desave",
00137 };
00138 
00139 static const struct mips_cp0sel_name mips_cp0sel_names_mips3264[] =
00140 {
00141   { 16, 1, "c0_config1"            },
00142   { 16, 2, "c0_config2"            },
00143   { 16, 3, "c0_config3"            },
00144   { 18, 1, "c0_watchlo,1"   },
00145   { 18, 2, "c0_watchlo,2"   },
00146   { 18, 3, "c0_watchlo,3"   },
00147   { 18, 4, "c0_watchlo,4"   },
00148   { 18, 5, "c0_watchlo,5"   },
00149   { 18, 6, "c0_watchlo,6"   },
00150   { 18, 7, "c0_watchlo,7"   },
00151   { 19, 1, "c0_watchhi,1"   },
00152   { 19, 2, "c0_watchhi,2"   },
00153   { 19, 3, "c0_watchhi,3"   },
00154   { 19, 4, "c0_watchhi,4"   },
00155   { 19, 5, "c0_watchhi,5"   },
00156   { 19, 6, "c0_watchhi,6"   },
00157   { 19, 7, "c0_watchhi,7"   },
00158   { 25, 1, "c0_perfcnt,1"   },
00159   { 25, 2, "c0_perfcnt,2"   },
00160   { 25, 3, "c0_perfcnt,3"   },
00161   { 25, 4, "c0_perfcnt,4"   },
00162   { 25, 5, "c0_perfcnt,5"   },
00163   { 25, 6, "c0_perfcnt,6"   },
00164   { 25, 7, "c0_perfcnt,7"   },
00165   { 27, 1, "c0_cacheerr,1"  },
00166   { 27, 2, "c0_cacheerr,2"  },
00167   { 27, 3, "c0_cacheerr,3"  },
00168   { 28, 1, "c0_datalo"             },
00169   { 29, 1, "c0_datahi"             }
00170 };
00171 
00172 static const char * const mips_cp0_names_mips3264r2[32] =
00173 {
00174   "c0_index",     "c0_random",    "c0_entrylo0",  "c0_entrylo1",
00175   "c0_context",   "c0_pagemask",  "c0_wired",     "c0_hwrena",
00176   "c0_badvaddr",  "c0_count",     "c0_entryhi",   "c0_compare",
00177   "c0_status",    "c0_cause",     "c0_epc",       "c0_prid",
00178   "c0_config",    "c0_lladdr",    "c0_watchlo",   "c0_watchhi",
00179   "c0_xcontext",  "$21",          "$22",          "c0_debug",
00180   "c0_depc",      "c0_perfcnt",   "c0_errctl",    "c0_cacheerr",
00181   "c0_taglo",     "c0_taghi",     "c0_errorepc",  "c0_desave",
00182 };
00183 
00184 static const struct mips_cp0sel_name mips_cp0sel_names_mips3264r2[] =
00185 {
00186   {  4, 1, "c0_contextconfig"      },
00187   {  0, 1, "c0_mvpcontrol"  },
00188   {  0, 2, "c0_mvpconf0"    },
00189   {  0, 3, "c0_mvpconf1"    },
00190   {  1, 1, "c0_vpecontrol"  },
00191   {  1, 2, "c0_vpeconf0"    },
00192   {  1, 3, "c0_vpeconf1"    },
00193   {  1, 4, "c0_yqmask"             },
00194   {  1, 5, "c0_vpeschedule" },
00195   {  1, 6, "c0_vpeschefback"       },
00196   {  2, 1, "c0_tcstatus"    },
00197   {  2, 2, "c0_tcbind"             },
00198   {  2, 3, "c0_tcrestart"   },
00199   {  2, 4, "c0_tchalt"             },
00200   {  2, 5, "c0_tccontext"   },
00201   {  2, 6, "c0_tcschedule"  },
00202   {  2, 7, "c0_tcschefback" },
00203   {  5, 1, "c0_pagegrain"   },
00204   {  6, 1, "c0_srsconf0"    },
00205   {  6, 2, "c0_srsconf1"    },
00206   {  6, 3, "c0_srsconf2"    },
00207   {  6, 4, "c0_srsconf3"    },
00208   {  6, 5, "c0_srsconf4"    },
00209   { 12, 1, "c0_intctl"             },
00210   { 12, 2, "c0_srsctl"             },
00211   { 12, 3, "c0_srsmap"             },
00212   { 15, 1, "c0_ebase"              },
00213   { 16, 1, "c0_config1"            },
00214   { 16, 2, "c0_config2"            },
00215   { 16, 3, "c0_config3"            },
00216   { 18, 1, "c0_watchlo,1"   },
00217   { 18, 2, "c0_watchlo,2"   },
00218   { 18, 3, "c0_watchlo,3"   },
00219   { 18, 4, "c0_watchlo,4"   },
00220   { 18, 5, "c0_watchlo,5"   },
00221   { 18, 6, "c0_watchlo,6"   },
00222   { 18, 7, "c0_watchlo,7"   },
00223   { 19, 1, "c0_watchhi,1"   },
00224   { 19, 2, "c0_watchhi,2"   },
00225   { 19, 3, "c0_watchhi,3"   },
00226   { 19, 4, "c0_watchhi,4"   },
00227   { 19, 5, "c0_watchhi,5"   },
00228   { 19, 6, "c0_watchhi,6"   },
00229   { 19, 7, "c0_watchhi,7"   },
00230   { 23, 1, "c0_tracecontrol"       },
00231   { 23, 2, "c0_tracecontrol2"      },
00232   { 23, 3, "c0_usertracedata"      },
00233   { 23, 4, "c0_tracebpc"    },
00234   { 25, 1, "c0_perfcnt,1"   },
00235   { 25, 2, "c0_perfcnt,2"   },
00236   { 25, 3, "c0_perfcnt,3"   },
00237   { 25, 4, "c0_perfcnt,4"   },
00238   { 25, 5, "c0_perfcnt,5"   },
00239   { 25, 6, "c0_perfcnt,6"   },
00240   { 25, 7, "c0_perfcnt,7"   },
00241   { 27, 1, "c0_cacheerr,1"  },
00242   { 27, 2, "c0_cacheerr,2"  },
00243   { 27, 3, "c0_cacheerr,3"  },
00244   { 28, 1, "c0_datalo"             },
00245   { 28, 2, "c0_taglo1"             },
00246   { 28, 3, "c0_datalo1"            },
00247   { 28, 4, "c0_taglo2"             },
00248   { 28, 5, "c0_datalo2"            },
00249   { 28, 6, "c0_taglo3"             },
00250   { 28, 7, "c0_datalo3"            },
00251   { 29, 1, "c0_datahi"             },
00252   { 29, 2, "c0_taghi1"             },
00253   { 29, 3, "c0_datahi1"            },
00254   { 29, 4, "c0_taghi2"             },
00255   { 29, 5, "c0_datahi2"            },
00256   { 29, 6, "c0_taghi3"             },
00257   { 29, 7, "c0_datahi3"            },
00258 };
00259 
00260 /* SB-1: MIPS64 (mips_cp0_names_mips3264) with minor mods.  */
00261 static const char * const mips_cp0_names_sb1[32] =
00262 {
00263   "c0_index",     "c0_random",    "c0_entrylo0",  "c0_entrylo1",
00264   "c0_context",   "c0_pagemask",  "c0_wired",     "$7",
00265   "c0_badvaddr",  "c0_count",     "c0_entryhi",   "c0_compare",
00266   "c0_status",    "c0_cause",     "c0_epc",       "c0_prid",
00267   "c0_config",    "c0_lladdr",    "c0_watchlo",   "c0_watchhi",
00268   "c0_xcontext",  "$21",          "$22",          "c0_debug",
00269   "c0_depc",      "c0_perfcnt",   "c0_errctl",    "c0_cacheerr_i",
00270   "c0_taglo_i",   "c0_taghi_i",   "c0_errorepc",  "c0_desave",
00271 };
00272 
00273 static const struct mips_cp0sel_name mips_cp0sel_names_sb1[] =
00274 {
00275   { 16, 1, "c0_config1"            },
00276   { 18, 1, "c0_watchlo,1"   },
00277   { 19, 1, "c0_watchhi,1"   },
00278   { 22, 0, "c0_perftrace"   },
00279   { 23, 3, "c0_edebug"             },
00280   { 25, 1, "c0_perfcnt,1"   },
00281   { 25, 2, "c0_perfcnt,2"   },
00282   { 25, 3, "c0_perfcnt,3"   },
00283   { 25, 4, "c0_perfcnt,4"   },
00284   { 25, 5, "c0_perfcnt,5"   },
00285   { 25, 6, "c0_perfcnt,6"   },
00286   { 25, 7, "c0_perfcnt,7"   },
00287   { 26, 1, "c0_buserr_pa"   },
00288   { 27, 1, "c0_cacheerr_d"  },
00289   { 27, 3, "c0_cacheerr_d_pa"      },
00290   { 28, 1, "c0_datalo_i"    },
00291   { 28, 2, "c0_taglo_d"            },
00292   { 28, 3, "c0_datalo_d"    },
00293   { 29, 1, "c0_datahi_i"    },
00294   { 29, 2, "c0_taghi_d"            },
00295   { 29, 3, "c0_datahi_d"    },
00296 };
00297 
00298 static const char * const mips_hwr_names_numeric[32] =
00299 {
00300   "$0",   "$1",   "$2",   "$3",   "$4",   "$5",   "$6",   "$7",
00301   "$8",   "$9",   "$10",  "$11",  "$12",  "$13",  "$14",  "$15",
00302   "$16",  "$17",  "$18",  "$19",  "$20",  "$21",  "$22",  "$23",
00303   "$24",  "$25",  "$26",  "$27",  "$28",  "$29",  "$30",  "$31"
00304 };
00305 
00306 static const char * const mips_hwr_names_mips3264r2[32] =
00307 {
00308   "hwr_cpunum",   "hwr_synci_step", "hwr_cc",     "hwr_ccres",
00309   "$4",          "$5",            "$6",           "$7",
00310   "$8",   "$9",   "$10",  "$11",  "$12",  "$13",  "$14",  "$15",
00311   "$16",  "$17",  "$18",  "$19",  "$20",  "$21",  "$22",  "$23",
00312   "$24",  "$25",  "$26",  "$27",  "$28",  "$29",  "$30",  "$31"
00313 };
00314 
00315 struct mips_abi_choice
00316 {
00317   const char * name;
00318   const char * const *gpr_names;
00319   const char * const *fpr_names;
00320 };
00321 
00322 struct mips_abi_choice mips_abi_choices[] =
00323 {
00324   { "numeric", mips_gpr_names_numeric, mips_fpr_names_numeric },
00325   { "32", mips_gpr_names_oldabi, mips_fpr_names_32 },
00326   { "n32", mips_gpr_names_newabi, mips_fpr_names_n32 },
00327   { "64", mips_gpr_names_newabi, mips_fpr_names_64 },
00328 };
00329 
00330 struct mips_arch_choice
00331 {
00332   const char *name;
00333   int bfd_mach_valid;
00334   unsigned long bfd_mach;
00335   int processor;
00336   int isa;
00337   const char * const *cp0_names;
00338   const struct mips_cp0sel_name *cp0sel_names;
00339   unsigned int cp0sel_names_len;
00340   const char * const *hwr_names;
00341 };
00342 
00343 const struct mips_arch_choice mips_arch_choices[] =
00344 {
00345   { "numeric",       0, 0, 0, 0,
00346     mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
00347 
00348   { "r3000",  1, bfd_mach_mips3000, CPU_R3000, ISA_MIPS1,
00349     mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
00350   { "r3900",  1, bfd_mach_mips3900, CPU_R3900, ISA_MIPS1,
00351     mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
00352   { "r4000",  1, bfd_mach_mips4000, CPU_R4000, ISA_MIPS3,
00353     mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
00354   { "r4010",  1, bfd_mach_mips4010, CPU_R4010, ISA_MIPS2,
00355     mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
00356   { "vr4100", 1, bfd_mach_mips4100, CPU_VR4100, ISA_MIPS3,
00357     mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
00358   { "vr4111", 1, bfd_mach_mips4111, CPU_R4111, ISA_MIPS3,
00359     mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
00360   { "vr4120", 1, bfd_mach_mips4120, CPU_VR4120, ISA_MIPS3,
00361     mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
00362   { "r4300",  1, bfd_mach_mips4300, CPU_R4300, ISA_MIPS3,
00363     mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
00364   { "r4400",  1, bfd_mach_mips4400, CPU_R4400, ISA_MIPS3,
00365     mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
00366   { "r4600",  1, bfd_mach_mips4600, CPU_R4600, ISA_MIPS3,
00367     mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
00368   { "r4650",  1, bfd_mach_mips4650, CPU_R4650, ISA_MIPS3,
00369     mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
00370   { "r5000",  1, bfd_mach_mips5000, CPU_R5000, ISA_MIPS4,
00371     mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
00372   { "vr5400", 1, bfd_mach_mips5400, CPU_VR5400, ISA_MIPS4,
00373     mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
00374   { "vr5500", 1, bfd_mach_mips5500, CPU_VR5500, ISA_MIPS4,
00375     mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
00376   { "r6000",  1, bfd_mach_mips6000, CPU_R6000, ISA_MIPS2,
00377     mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
00378   { "rm7000", 1, bfd_mach_mips7000, CPU_RM7000, ISA_MIPS4,
00379     mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
00380   { "rm9000", 1, bfd_mach_mips7000, CPU_RM7000, ISA_MIPS4,
00381     mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
00382   { "r8000",  1, bfd_mach_mips8000, CPU_R8000, ISA_MIPS4,
00383     mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
00384   { "r10000", 1, bfd_mach_mips10000, CPU_R10000, ISA_MIPS4,
00385     mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
00386   { "r12000", 1, bfd_mach_mips12000, CPU_R12000, ISA_MIPS4,
00387     mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
00388   { "mips5",  1, bfd_mach_mips5, CPU_MIPS5, ISA_MIPS5,
00389     mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
00390 
00391   /* For stock MIPS32, disassemble all applicable MIPS-specified ASEs.
00392      Note that MIPS-3D and MDMX are not applicable to MIPS32.  (See
00393      _MIPS32 Architecture For Programmers Volume I: Introduction to the
00394      MIPS32 Architecture_ (MIPS Document Number MD00082, Revision 0.95),
00395      page 1.  */
00396   { "mips32", 1, bfd_mach_mipsisa32, CPU_MIPS32,
00397     ISA_MIPS32 | INSN_MIPS16 | INSN_SMARTMIPS,
00398     mips_cp0_names_mips3264,
00399     mips_cp0sel_names_mips3264, ARRAY_SIZE (mips_cp0sel_names_mips3264),
00400     mips_hwr_names_numeric },
00401 
00402   { "mips32r2",      1, bfd_mach_mipsisa32r2, CPU_MIPS32R2,
00403     (ISA_MIPS32R2 | INSN_MIPS16 | INSN_SMARTMIPS | INSN_DSP | INSN_DSPR2
00404      | INSN_MIPS3D | INSN_MT),
00405     mips_cp0_names_mips3264r2,
00406     mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2),
00407     mips_hwr_names_mips3264r2 },
00408 
00409   /* For stock MIPS64, disassemble all applicable MIPS-specified ASEs.  */
00410   { "mips64", 1, bfd_mach_mipsisa64, CPU_MIPS64,
00411     ISA_MIPS64 | INSN_MIPS16 | INSN_MIPS3D | INSN_MDMX,
00412     mips_cp0_names_mips3264,
00413     mips_cp0sel_names_mips3264, ARRAY_SIZE (mips_cp0sel_names_mips3264),
00414     mips_hwr_names_numeric },
00415 
00416   { "mips64r2",      1, bfd_mach_mipsisa64r2, CPU_MIPS64R2,
00417     (ISA_MIPS64R2 | INSN_MIPS16 | INSN_MIPS3D | INSN_DSP | INSN_DSPR2
00418      | INSN_DSP64 | INSN_MT | INSN_MDMX),
00419     mips_cp0_names_mips3264r2,
00420     mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2),
00421     mips_hwr_names_mips3264r2 },
00422 
00423   { "sb1",    1, bfd_mach_mips_sb1, CPU_SB1,
00424     ISA_MIPS64 | INSN_MIPS3D | INSN_SB1,
00425     mips_cp0_names_sb1,
00426     mips_cp0sel_names_sb1, ARRAY_SIZE (mips_cp0sel_names_sb1),
00427     mips_hwr_names_numeric },
00428 
00429   /* This entry, mips16, is here only for ISA/processor selection; do
00430      not print its name.  */
00431   { "",              1, bfd_mach_mips16, CPU_MIPS16, ISA_MIPS3 | INSN_MIPS16,
00432     mips_cp0_names_numeric, NULL, 0, mips_hwr_names_numeric },
00433 };
00434 
00435 /* ISA and processor type to disassemble for, and register names to use.
00436    set_default_mips_dis_options and parse_mips_dis_options fill in these
00437    values.  */
00438 static int mips_processor;
00439 static int mips_isa;
00440 static const char * const *mips_gpr_names;
00441 static const char * const *mips_fpr_names;
00442 static const char * const *mips_cp0_names;
00443 static const struct mips_cp0sel_name *mips_cp0sel_names;
00444 static int mips_cp0sel_names_len;
00445 static const char * const *mips_hwr_names;
00446 
00447 /* Other options */
00448 static int no_aliases;      /* If set disassemble as most general inst.  */
00449 
00450 static const struct mips_abi_choice *
00451 choose_abi_by_name (const char *name, unsigned int namelen)
00452 {
00453   const struct mips_abi_choice *c;
00454   unsigned int i;
00455 
00456   for (i = 0, c = NULL; i < ARRAY_SIZE (mips_abi_choices) && c == NULL; i++)
00457     if (strncmp (mips_abi_choices[i].name, name, namelen) == 0
00458        && strlen (mips_abi_choices[i].name) == namelen)
00459       c = &mips_abi_choices[i];
00460 
00461   return c;
00462 }
00463 
00464 static const struct mips_arch_choice *
00465 choose_arch_by_name (const char *name, unsigned int namelen)
00466 {
00467   const struct mips_arch_choice *c = NULL;
00468   unsigned int i;
00469 
00470   for (i = 0, c = NULL; i < ARRAY_SIZE (mips_arch_choices) && c == NULL; i++)
00471     if (strncmp (mips_arch_choices[i].name, name, namelen) == 0
00472        && strlen (mips_arch_choices[i].name) == namelen)
00473       c = &mips_arch_choices[i];
00474 
00475   return c;
00476 }
00477 
00478 static const struct mips_arch_choice *
00479 choose_arch_by_number (unsigned long mach)
00480 {
00481   static unsigned long hint_bfd_mach;
00482   static const struct mips_arch_choice *hint_arch_choice;
00483   const struct mips_arch_choice *c;
00484   unsigned int i;
00485 
00486   /* We optimize this because even if the user specifies no
00487      flags, this will be done for every instruction!  */
00488   if (hint_bfd_mach == mach
00489       && hint_arch_choice != NULL
00490       && hint_arch_choice->bfd_mach == hint_bfd_mach)
00491     return hint_arch_choice;
00492 
00493   for (i = 0, c = NULL; i < ARRAY_SIZE (mips_arch_choices) && c == NULL; i++)
00494     {
00495       if (mips_arch_choices[i].bfd_mach_valid
00496          && mips_arch_choices[i].bfd_mach == mach)
00497        {
00498          c = &mips_arch_choices[i];
00499          hint_bfd_mach = mach;
00500          hint_arch_choice = c;
00501        }
00502     }
00503   return c;
00504 }
00505 
00506 /* Check if the object uses NewABI conventions.  */
00507 
00508 static int
00509 is_newabi (Elf_Internal_Ehdr *header)
00510 {
00511   /* There are no old-style ABIs which use 64-bit ELF.  */
00512   if (header->e_ident[EI_CLASS] == ELFCLASS64)
00513     return 1;
00514 
00515   /* If a 32-bit ELF file, n32 is a new-style ABI.  */
00516   if ((header->e_flags & EF_MIPS_ABI2) != 0)
00517     return 1;
00518 
00519   return 0;
00520 }
00521 
00522 static void
00523 set_default_mips_dis_options (struct disassemble_info *info)
00524 {
00525   const struct mips_arch_choice *chosen_arch;
00526 
00527   /* Defaults: mipsIII/r3000 (?!), (o)32-style ("oldabi") GPR names,
00528      and numeric FPR, CP0 register, and HWR names.  */
00529   mips_isa = ISA_MIPS3;
00530   mips_processor =  CPU_R3000;
00531   mips_gpr_names = mips_gpr_names_oldabi;
00532   mips_fpr_names = mips_fpr_names_numeric;
00533   mips_cp0_names = mips_cp0_names_numeric;
00534   mips_cp0sel_names = NULL;
00535   mips_cp0sel_names_len = 0;
00536   mips_hwr_names = mips_hwr_names_numeric;
00537   no_aliases = 0;
00538 
00539   /* If an ELF "newabi" binary, use the n32/(n)64 GPR names.  */
00540   if (info->flavour == bfd_target_elf_flavour && info->section != NULL)
00541     {
00542       Elf_Internal_Ehdr *header;
00543 
00544       header = elf_elfheader (info->section->owner);
00545       if (is_newabi (header))
00546        mips_gpr_names = mips_gpr_names_newabi;
00547     }
00548 
00549   /* Set ISA, architecture, and cp0 register names as best we can.  */
00550 #if ! SYMTAB_AVAILABLE
00551   /* This is running out on a target machine, not in a host tool.
00552      FIXME: Where does mips_target_info come from?  */
00553   target_processor = mips_target_info.processor;
00554   mips_isa = mips_target_info.isa;
00555 #else
00556   chosen_arch = choose_arch_by_number (info->mach);
00557   if (chosen_arch != NULL)
00558     {
00559       mips_processor = chosen_arch->processor;
00560       mips_isa = chosen_arch->isa;
00561       mips_cp0_names = chosen_arch->cp0_names;
00562       mips_cp0sel_names = chosen_arch->cp0sel_names;
00563       mips_cp0sel_names_len = chosen_arch->cp0sel_names_len;
00564       mips_hwr_names = chosen_arch->hwr_names;
00565     }
00566 #endif
00567 }
00568 
00569 static void
00570 parse_mips_dis_option (const char *option, unsigned int len)
00571 {
00572   unsigned int i, optionlen, vallen;
00573   const char *val;
00574   const struct mips_abi_choice *chosen_abi;
00575   const struct mips_arch_choice *chosen_arch;
00576 
00577   /* Try to match options that are simple flags */
00578   if (CONST_STRNEQ (option, "no-aliases"))
00579     {
00580       no_aliases = 1;
00581       return;
00582     }
00583   
00584   /* Look for the = that delimits the end of the option name.  */
00585   for (i = 0; i < len; i++)
00586     if (option[i] == '=')
00587       break;
00588 
00589   if (i == 0)        /* Invalid option: no name before '='.  */
00590     return;
00591   if (i == len)             /* Invalid option: no '='.  */
00592     return;
00593   if (i == (len - 1))       /* Invalid option: no value after '='.  */
00594     return;
00595 
00596   optionlen = i;
00597   val = option + (optionlen + 1);
00598   vallen = len - (optionlen + 1);
00599 
00600   if (strncmp ("gpr-names", option, optionlen) == 0
00601       && strlen ("gpr-names") == optionlen)
00602     {
00603       chosen_abi = choose_abi_by_name (val, vallen);
00604       if (chosen_abi != NULL)
00605        mips_gpr_names = chosen_abi->gpr_names;
00606       return;
00607     }
00608 
00609   if (strncmp ("fpr-names", option, optionlen) == 0
00610       && strlen ("fpr-names") == optionlen)
00611     {
00612       chosen_abi = choose_abi_by_name (val, vallen);
00613       if (chosen_abi != NULL)
00614        mips_fpr_names = chosen_abi->fpr_names;
00615       return;
00616     }
00617 
00618   if (strncmp ("cp0-names", option, optionlen) == 0
00619       && strlen ("cp0-names") == optionlen)
00620     {
00621       chosen_arch = choose_arch_by_name (val, vallen);
00622       if (chosen_arch != NULL)
00623        {
00624          mips_cp0_names = chosen_arch->cp0_names;
00625          mips_cp0sel_names = chosen_arch->cp0sel_names;
00626          mips_cp0sel_names_len = chosen_arch->cp0sel_names_len;
00627        }
00628       return;
00629     }
00630 
00631   if (strncmp ("hwr-names", option, optionlen) == 0
00632       && strlen ("hwr-names") == optionlen)
00633     {
00634       chosen_arch = choose_arch_by_name (val, vallen);
00635       if (chosen_arch != NULL)
00636        mips_hwr_names = chosen_arch->hwr_names;
00637       return;
00638     }
00639 
00640   if (strncmp ("reg-names", option, optionlen) == 0
00641       && strlen ("reg-names") == optionlen)
00642     {
00643       /* We check both ABI and ARCH here unconditionally, so
00644         that "numeric" will do the desirable thing: select
00645         numeric register names for all registers.  Other than
00646         that, a given name probably won't match both.  */
00647       chosen_abi = choose_abi_by_name (val, vallen);
00648       if (chosen_abi != NULL)
00649        {
00650          mips_gpr_names = chosen_abi->gpr_names;
00651          mips_fpr_names = chosen_abi->fpr_names;
00652        }
00653       chosen_arch = choose_arch_by_name (val, vallen);
00654       if (chosen_arch != NULL)
00655        {
00656          mips_cp0_names = chosen_arch->cp0_names;
00657          mips_cp0sel_names = chosen_arch->cp0sel_names;
00658          mips_cp0sel_names_len = chosen_arch->cp0sel_names_len;
00659          mips_hwr_names = chosen_arch->hwr_names;
00660        }
00661       return;
00662     }
00663 
00664   /* Invalid option.  */
00665 }
00666 
00667 static void
00668 parse_mips_dis_options (const char *options)
00669 {
00670   const char *option_end;
00671 
00672   if (options == NULL)
00673     return;
00674 
00675   while (*options != '\0')
00676     {
00677       /* Skip empty options.  */
00678       if (*options == ',')
00679        {
00680          options++;
00681          continue;
00682        }
00683 
00684       /* We know that *options is neither NUL or a comma.  */
00685       option_end = options + 1;
00686       while (*option_end != ',' && *option_end != '\0')
00687        option_end++;
00688 
00689       parse_mips_dis_option (options, option_end - options);
00690 
00691       /* Go on to the next one.  If option_end points to a comma, it
00692         will be skipped above.  */
00693       options = option_end;
00694     }
00695 }
00696 
00697 static const struct mips_cp0sel_name *
00698 lookup_mips_cp0sel_name (const struct mips_cp0sel_name *names,
00699                       unsigned int len,
00700                       unsigned int cp0reg,
00701                       unsigned int sel)
00702 {
00703   unsigned int i;
00704 
00705   for (i = 0; i < len; i++)
00706     if (names[i].cp0reg == cp0reg && names[i].sel == sel)
00707       return &names[i];
00708   return NULL;
00709 }
00710 
00711 /* Print insn arguments for 32/64-bit code.  */
00712 
00713 static void
00714 print_insn_args (const char *d,
00715                register unsigned long int l,
00716                bfd_vma pc,
00717                struct disassemble_info *info,
00718                const struct mips_opcode *opp)
00719 {
00720   int op, delta;
00721   unsigned int lsb, msb, msbd;
00722 
00723   lsb = 0;
00724 
00725   for (; *d != '\0'; d++)
00726     {
00727       switch (*d)
00728        {
00729        case ',':
00730        case '(':
00731        case ')':
00732        case '[':
00733        case ']':
00734          (*info->fprintf_func) (info->stream, "%c", *d);
00735          break;
00736 
00737        case '+':
00738          /* Extension character; switch for second char.  */
00739          d++;
00740          switch (*d)
00741            {
00742            case '\0':
00743              /* xgettext:c-format */
00744              (*info->fprintf_func) (info->stream,
00745                                  _("# internal error, incomplete extension sequence (+)"));
00746              return;
00747 
00748            case 'A':
00749              lsb = (l >> OP_SH_SHAMT) & OP_MASK_SHAMT;
00750              (*info->fprintf_func) (info->stream, "0x%x", lsb);
00751              break;
00752        
00753            case 'B':
00754              msb = (l >> OP_SH_INSMSB) & OP_MASK_INSMSB;
00755              (*info->fprintf_func) (info->stream, "0x%x", msb - lsb + 1);
00756              break;
00757 
00758            case '1':
00759              (*info->fprintf_func) (info->stream, "0x%lx",
00760                                  (l >> OP_SH_UDI1) & OP_MASK_UDI1);
00761              break;
00762              
00763            case '2':
00764              (*info->fprintf_func) (info->stream, "0x%lx",
00765                                  (l >> OP_SH_UDI2) & OP_MASK_UDI2);
00766              break;
00767              
00768            case '3':
00769              (*info->fprintf_func) (info->stream, "0x%lx",
00770                                  (l >> OP_SH_UDI3) & OP_MASK_UDI3);
00771              break;
00772       
00773            case '4':
00774              (*info->fprintf_func) (info->stream, "0x%lx",
00775                                  (l >> OP_SH_UDI4) & OP_MASK_UDI4);
00776              break;
00777              
00778            case 'C':
00779            case 'H':
00780              msbd = (l >> OP_SH_EXTMSBD) & OP_MASK_EXTMSBD;
00781              (*info->fprintf_func) (info->stream, "0x%x", msbd + 1);
00782              break;
00783 
00784            case 'D':
00785              {
00786               const struct mips_cp0sel_name *n;
00787               unsigned int cp0reg, sel;
00788 
00789               cp0reg = (l >> OP_SH_RD) & OP_MASK_RD;
00790               sel = (l >> OP_SH_SEL) & OP_MASK_SEL;
00791 
00792               /* CP0 register including 'sel' code for mtcN (et al.), to be
00793                  printed textually if known.  If not known, print both
00794                  CP0 register name and sel numerically since CP0 register
00795                  with sel 0 may have a name unrelated to register being
00796                  printed.  */
00797               n = lookup_mips_cp0sel_name(mips_cp0sel_names,
00798                                        mips_cp0sel_names_len, cp0reg, sel);
00799               if (n != NULL)
00800                 (*info->fprintf_func) (info->stream, "%s", n->name);
00801               else
00802                 (*info->fprintf_func) (info->stream, "$%d,%d", cp0reg, sel);
00803               break;
00804              }
00805 
00806            case 'E':
00807              lsb = ((l >> OP_SH_SHAMT) & OP_MASK_SHAMT) + 32;
00808              (*info->fprintf_func) (info->stream, "0x%x", lsb);
00809              break;
00810        
00811            case 'F':
00812              msb = ((l >> OP_SH_INSMSB) & OP_MASK_INSMSB) + 32;
00813              (*info->fprintf_func) (info->stream, "0x%x", msb - lsb + 1);
00814              break;
00815 
00816            case 'G':
00817              msbd = ((l >> OP_SH_EXTMSBD) & OP_MASK_EXTMSBD) + 32;
00818              (*info->fprintf_func) (info->stream, "0x%x", msbd + 1);
00819              break;
00820 
00821            case 't': /* Coprocessor 0 reg name */
00822              (*info->fprintf_func) (info->stream, "%s",
00823                                  mips_cp0_names[(l >> OP_SH_RT) &
00824                                                OP_MASK_RT]);
00825              break;
00826 
00827            case 'T': /* Coprocessor 0 reg name */
00828              {
00829               const struct mips_cp0sel_name *n;
00830               unsigned int cp0reg, sel;
00831 
00832               cp0reg = (l >> OP_SH_RT) & OP_MASK_RT;
00833               sel = (l >> OP_SH_SEL) & OP_MASK_SEL;
00834 
00835               /* CP0 register including 'sel' code for mftc0, to be
00836                  printed textually if known.  If not known, print both
00837                  CP0 register name and sel numerically since CP0 register
00838                  with sel 0 may have a name unrelated to register being
00839                  printed.  */
00840               n = lookup_mips_cp0sel_name(mips_cp0sel_names,
00841                                        mips_cp0sel_names_len, cp0reg, sel);
00842               if (n != NULL)
00843                 (*info->fprintf_func) (info->stream, "%s", n->name);
00844               else
00845                 (*info->fprintf_func) (info->stream, "$%d,%d", cp0reg, sel);
00846               break;
00847              }
00848 
00849            default:
00850              /* xgettext:c-format */
00851              (*info->fprintf_func) (info->stream,
00852                                  _("# internal error, undefined extension sequence (+%c)"),
00853                                  *d);
00854              return;
00855            }
00856          break;
00857 
00858        case '2':
00859          (*info->fprintf_func) (info->stream, "0x%lx",
00860                              (l >> OP_SH_BP) & OP_MASK_BP);
00861          break;
00862 
00863        case '3':
00864          (*info->fprintf_func) (info->stream, "0x%lx",
00865                              (l >> OP_SH_SA3) & OP_MASK_SA3);
00866          break;
00867 
00868        case '4':
00869          (*info->fprintf_func) (info->stream, "0x%lx",
00870                              (l >> OP_SH_SA4) & OP_MASK_SA4);
00871          break;
00872 
00873        case '5':
00874          (*info->fprintf_func) (info->stream, "0x%lx",
00875                              (l >> OP_SH_IMM8) & OP_MASK_IMM8);
00876          break;
00877 
00878        case '6':
00879          (*info->fprintf_func) (info->stream, "0x%lx",
00880                              (l >> OP_SH_RS) & OP_MASK_RS);
00881          break;
00882 
00883        case '7':
00884          (*info->fprintf_func) (info->stream, "$ac%ld",
00885                              (l >> OP_SH_DSPACC) & OP_MASK_DSPACC);
00886          break;
00887 
00888        case '8':
00889          (*info->fprintf_func) (info->stream, "0x%lx",
00890                              (l >> OP_SH_WRDSP) & OP_MASK_WRDSP);
00891          break;
00892 
00893        case '9':
00894          (*info->fprintf_func) (info->stream, "$ac%ld",
00895                              (l >> OP_SH_DSPACC_S) & OP_MASK_DSPACC_S);
00896          break;
00897 
00898        case '0': /* dsp 6-bit signed immediate in bit 20 */
00899          delta = ((l >> OP_SH_DSPSFT) & OP_MASK_DSPSFT);
00900          if (delta & 0x20) /* test sign bit */
00901            delta |= ~OP_MASK_DSPSFT;
00902          (*info->fprintf_func) (info->stream, "%d", delta);
00903          break;
00904 
00905        case ':': /* dsp 7-bit signed immediate in bit 19 */
00906          delta = ((l >> OP_SH_DSPSFT_7) & OP_MASK_DSPSFT_7);
00907          if (delta & 0x40) /* test sign bit */
00908            delta |= ~OP_MASK_DSPSFT_7;
00909          (*info->fprintf_func) (info->stream, "%d", delta);
00910          break;
00911 
00912        case '\'':
00913          (*info->fprintf_func) (info->stream, "0x%lx",
00914                              (l >> OP_SH_RDDSP) & OP_MASK_RDDSP);
00915          break;
00916 
00917        case '@': /* dsp 10-bit signed immediate in bit 16 */
00918          delta = ((l >> OP_SH_IMM10) & OP_MASK_IMM10);
00919          if (delta & 0x200) /* test sign bit */
00920            delta |= ~OP_MASK_IMM10;
00921          (*info->fprintf_func) (info->stream, "%d", delta);
00922          break;
00923 
00924        case '!':
00925          (*info->fprintf_func) (info->stream, "%ld",
00926                              (l >> OP_SH_MT_U) & OP_MASK_MT_U);
00927          break;
00928 
00929        case '$':
00930          (*info->fprintf_func) (info->stream, "%ld",
00931                              (l >> OP_SH_MT_H) & OP_MASK_MT_H);
00932          break;
00933 
00934        case '*':
00935          (*info->fprintf_func) (info->stream, "$ac%ld",
00936                              (l >> OP_SH_MTACC_T) & OP_MASK_MTACC_T);
00937          break;
00938 
00939        case '&':
00940          (*info->fprintf_func) (info->stream, "$ac%ld",
00941                              (l >> OP_SH_MTACC_D) & OP_MASK_MTACC_D);
00942          break;
00943 
00944        case 'g':
00945          /* Coprocessor register for CTTC1, MTTC2, MTHC2, CTTC2.  */
00946          (*info->fprintf_func) (info->stream, "$%ld",
00947                              (l >> OP_SH_RD) & OP_MASK_RD);
00948          break;
00949 
00950        case 's':
00951        case 'b':
00952        case 'r':
00953        case 'v':
00954          (*info->fprintf_func) (info->stream, "%s",
00955                              mips_gpr_names[(l >> OP_SH_RS) & OP_MASK_RS]);
00956          break;
00957 
00958        case 't':
00959        case 'w':
00960          (*info->fprintf_func) (info->stream, "%s",
00961                              mips_gpr_names[(l >> OP_SH_RT) & OP_MASK_RT]);
00962          break;
00963 
00964        case 'i':
00965        case 'u':
00966          (*info->fprintf_func) (info->stream, "0x%lx",
00967                              (l >> OP_SH_IMMEDIATE) & OP_MASK_IMMEDIATE);
00968          break;
00969 
00970        case 'j': /* Same as i, but sign-extended.  */
00971        case 'o':
00972          delta = (l >> OP_SH_DELTA) & OP_MASK_DELTA;
00973          if (delta & 0x8000)
00974            delta |= ~0xffff;
00975          (*info->fprintf_func) (info->stream, "%d",
00976                              delta);
00977          break;
00978 
00979        case 'h':
00980          (*info->fprintf_func) (info->stream, "0x%x",
00981                              (unsigned int) ((l >> OP_SH_PREFX)
00982                                            & OP_MASK_PREFX));
00983          break;
00984 
00985        case 'k':
00986          (*info->fprintf_func) (info->stream, "0x%x",
00987                              (unsigned int) ((l >> OP_SH_CACHE)
00988                                            & OP_MASK_CACHE));
00989          break;
00990 
00991        case 'a':
00992          info->target = (((pc + 4) & ~(bfd_vma) 0x0fffffff)
00993                        | (((l >> OP_SH_TARGET) & OP_MASK_TARGET) << 2));
00994          /* For gdb disassembler, force odd address on jalx.  */
00995          if (info->flavour == bfd_target_unknown_flavour
00996              && strcmp (opp->name, "jalx") == 0)
00997            info->target |= 1;
00998          (*info->print_address_func) (info->target, info);
00999          break;
01000 
01001        case 'p':
01002          /* Sign extend the displacement.  */
01003          delta = (l >> OP_SH_DELTA) & OP_MASK_DELTA;
01004          if (delta & 0x8000)
01005            delta |= ~0xffff;
01006          info->target = (delta << 2) + pc + INSNLEN;
01007          (*info->print_address_func) (info->target, info);
01008          break;
01009 
01010        case 'd':
01011          (*info->fprintf_func) (info->stream, "%s",
01012                              mips_gpr_names[(l >> OP_SH_RD) & OP_MASK_RD]);
01013          break;
01014 
01015        case 'U':
01016          {
01017            /* First check for both rd and rt being equal.  */
01018            unsigned int reg = (l >> OP_SH_RD) & OP_MASK_RD;
01019            if (reg == ((l >> OP_SH_RT) & OP_MASK_RT))
01020              (*info->fprintf_func) (info->stream, "%s",
01021                                  mips_gpr_names[reg]);
01022            else
01023              {
01024               /* If one is zero use the other.  */
01025               if (reg == 0)
01026                 (*info->fprintf_func) (info->stream, "%s",
01027                                     mips_gpr_names[(l >> OP_SH_RT) & OP_MASK_RT]);
01028               else if (((l >> OP_SH_RT) & OP_MASK_RT) == 0)
01029                 (*info->fprintf_func) (info->stream, "%s",
01030                                     mips_gpr_names[reg]);
01031               else /* Bogus, result depends on processor.  */
01032                 (*info->fprintf_func) (info->stream, "%s or %s",
01033                                     mips_gpr_names[reg],
01034                                     mips_gpr_names[(l >> OP_SH_RT) & OP_MASK_RT]);
01035              }
01036          }
01037          break;
01038 
01039        case 'z':
01040          (*info->fprintf_func) (info->stream, "%s", mips_gpr_names[0]);
01041          break;
01042 
01043        case '<':
01044          (*info->fprintf_func) (info->stream, "0x%lx",
01045                              (l >> OP_SH_SHAMT) & OP_MASK_SHAMT);
01046          break;
01047 
01048        case 'c':
01049          (*info->fprintf_func) (info->stream, "0x%lx",
01050                              (l >> OP_SH_CODE) & OP_MASK_CODE);
01051          break;
01052 
01053        case 'q':
01054          (*info->fprintf_func) (info->stream, "0x%lx",
01055                              (l >> OP_SH_CODE2) & OP_MASK_CODE2);
01056          break;
01057 
01058        case 'C':
01059          (*info->fprintf_func) (info->stream, "0x%lx",
01060                              (l >> OP_SH_COPZ) & OP_MASK_COPZ);
01061          break;
01062 
01063        case 'B':
01064          (*info->fprintf_func) (info->stream, "0x%lx",
01065 
01066                              (l >> OP_SH_CODE20) & OP_MASK_CODE20);
01067          break;
01068 
01069        case 'J':
01070          (*info->fprintf_func) (info->stream, "0x%lx",
01071                              (l >> OP_SH_CODE19) & OP_MASK_CODE19);
01072          break;
01073 
01074        case 'S':
01075        case 'V':
01076          (*info->fprintf_func) (info->stream, "%s",
01077                              mips_fpr_names[(l >> OP_SH_FS) & OP_MASK_FS]);
01078          break;
01079 
01080        case 'T':
01081        case 'W':
01082          (*info->fprintf_func) (info->stream, "%s",
01083                              mips_fpr_names[(l >> OP_SH_FT) & OP_MASK_FT]);
01084          break;
01085 
01086        case 'D':
01087          (*info->fprintf_func) (info->stream, "%s",
01088                              mips_fpr_names[(l >> OP_SH_FD) & OP_MASK_FD]);
01089          break;
01090 
01091        case 'R':
01092          (*info->fprintf_func) (info->stream, "%s",
01093                              mips_fpr_names[(l >> OP_SH_FR) & OP_MASK_FR]);
01094          break;
01095 
01096        case 'E':
01097          /* Coprocessor register for lwcN instructions, et al.
01098 
01099             Note that there is no load/store cp0 instructions, and
01100             that FPU (cp1) instructions disassemble this field using
01101             'T' format.  Therefore, until we gain understanding of
01102             cp2 register names, we can simply print the register
01103             numbers.  */
01104          (*info->fprintf_func) (info->stream, "$%ld",
01105                              (l >> OP_SH_RT) & OP_MASK_RT);
01106          break;
01107 
01108        case 'G':
01109          /* Coprocessor register for mtcN instructions, et al.  Note
01110             that FPU (cp1) instructions disassemble this field using
01111             'S' format.  Therefore, we only need to worry about cp0,
01112             cp2, and cp3.  */
01113          op = (l >> OP_SH_OP) & OP_MASK_OP;
01114          if (op == OP_OP_COP0)
01115            (*info->fprintf_func) (info->stream, "%s",
01116                                mips_cp0_names[(l >> OP_SH_RD) & OP_MASK_RD]);
01117          else
01118            (*info->fprintf_func) (info->stream, "$%ld",
01119                                (l >> OP_SH_RD) & OP_MASK_RD);
01120          break;
01121 
01122        case 'K':
01123          (*info->fprintf_func) (info->stream, "%s",
01124                              mips_hwr_names[(l >> OP_SH_RD) & OP_MASK_RD]);
01125          break;
01126 
01127        case 'N':
01128          (*info->fprintf_func) (info->stream,
01129                              ((opp->pinfo & (FP_D | FP_S)) != 0
01130                               ? "$fcc%ld" : "$cc%ld"),
01131                              (l >> OP_SH_BCC) & OP_MASK_BCC);
01132          break;
01133 
01134        case 'M':
01135          (*info->fprintf_func) (info->stream, "$fcc%ld",
01136                              (l >> OP_SH_CCC) & OP_MASK_CCC);
01137          break;
01138 
01139        case 'P':
01140          (*info->fprintf_func) (info->stream, "%ld",
01141                              (l >> OP_SH_PERFREG) & OP_MASK_PERFREG);
01142          break;
01143 
01144        case 'e':
01145          (*info->fprintf_func) (info->stream, "%ld",
01146                              (l >> OP_SH_VECBYTE) & OP_MASK_VECBYTE);
01147          break;
01148 
01149        case '%':
01150          (*info->fprintf_func) (info->stream, "%ld",
01151                              (l >> OP_SH_VECALIGN) & OP_MASK_VECALIGN);
01152          break;
01153 
01154        case 'H':
01155          (*info->fprintf_func) (info->stream, "%ld",
01156                              (l >> OP_SH_SEL) & OP_MASK_SEL);
01157          break;
01158 
01159        case 'O':
01160          (*info->fprintf_func) (info->stream, "%ld",
01161                              (l >> OP_SH_ALN) & OP_MASK_ALN);
01162          break;
01163 
01164        case 'Q':
01165          {
01166            unsigned int vsel = (l >> OP_SH_VSEL) & OP_MASK_VSEL;
01167 
01168            if ((vsel & 0x10) == 0)
01169              {
01170               int fmt;
01171 
01172               vsel &= 0x0f;
01173               for (fmt = 0; fmt < 3; fmt++, vsel >>= 1)
01174                 if ((vsel & 1) == 0)
01175                   break;
01176               (*info->fprintf_func) (info->stream, "$v%ld[%d]",
01177                                    (l >> OP_SH_FT) & OP_MASK_FT,
01178                                    vsel >> 1);
01179              }
01180            else if ((vsel & 0x08) == 0)
01181              {
01182               (*info->fprintf_func) (info->stream, "$v%ld",
01183                                    (l >> OP_SH_FT) & OP_MASK_FT);
01184              }
01185            else
01186              {
01187               (*info->fprintf_func) (info->stream, "0x%lx",
01188                                    (l >> OP_SH_FT) & OP_MASK_FT);
01189              }
01190          }
01191          break;
01192 
01193        case 'X':
01194          (*info->fprintf_func) (info->stream, "$v%ld",
01195                              (l >> OP_SH_FD) & OP_MASK_FD);
01196          break;
01197 
01198        case 'Y':
01199          (*info->fprintf_func) (info->stream, "$v%ld",
01200                              (l >> OP_SH_FS) & OP_MASK_FS);
01201          break;
01202 
01203        case 'Z':
01204          (*info->fprintf_func) (info->stream, "$v%ld",
01205                              (l >> OP_SH_FT) & OP_MASK_FT);
01206          break;
01207 
01208        default:
01209          /* xgettext:c-format */
01210          (*info->fprintf_func) (info->stream,
01211                              _("# internal error, undefined modifier(%c)"),
01212                              *d);
01213          return;
01214        }
01215     }
01216 }
01217 
01218 /* Print the mips instruction at address MEMADDR in debugged memory,
01219    on using INFO.  Returns length of the instruction, in bytes, which is
01220    always INSNLEN.  BIGENDIAN must be 1 if this is big-endian code, 0 if
01221    this is little-endian code.  */
01222 
01223 static int
01224 print_insn_mips (bfd_vma memaddr,
01225                unsigned long int word,
01226                struct disassemble_info *info)
01227 {
01228   const struct mips_opcode *op;
01229   static bfd_boolean init = 0;
01230   static const struct mips_opcode *mips_hash[OP_MASK_OP + 1];
01231 
01232   /* Build a hash table to shorten the search time.  */
01233   if (! init)
01234     {
01235       unsigned int i;
01236 
01237       for (i = 0; i <= OP_MASK_OP; i++)
01238        {
01239          for (op = mips_opcodes; op < &mips_opcodes[NUMOPCODES]; op++)
01240            {
01241              if (op->pinfo == INSN_MACRO
01242                 || (no_aliases && (op->pinfo2 & INSN2_ALIAS)))
01243               continue;
01244              if (i == ((op->match >> OP_SH_OP) & OP_MASK_OP))
01245               {
01246                 mips_hash[i] = op;
01247                 break;
01248               }
01249            }
01250        }
01251 
01252       init = 1;
01253     }
01254 
01255   info->bytes_per_chunk = INSNLEN;
01256   info->display_endian = info->endian;
01257   info->insn_info_valid = 1;
01258   info->branch_delay_insns = 0;
01259   info->data_size = 0;
01260   info->insn_type = dis_nonbranch;
01261   info->target = 0;
01262   info->target2 = 0;
01263 
01264   op = mips_hash[(word >> OP_SH_OP) & OP_MASK_OP];
01265   if (op != NULL)
01266     {
01267       for (; op < &mips_opcodes[NUMOPCODES]; op++)
01268        {
01269          if (op->pinfo != INSN_MACRO 
01270              && !(no_aliases && (op->pinfo2 & INSN2_ALIAS))
01271              && (word & op->mask) == op->match)
01272            {
01273              const char *d;
01274 
01275              /* We always allow to disassemble the jalx instruction.  */
01276              if (! OPCODE_IS_MEMBER (op, mips_isa, mips_processor)
01277                 && strcmp (op->name, "jalx"))
01278               continue;
01279 
01280              /* Figure out instruction type and branch delay information.  */
01281              if ((op->pinfo & INSN_UNCOND_BRANCH_DELAY) != 0)
01282                {
01283                 if ((info->insn_type & INSN_WRITE_GPR_31) != 0)
01284                   info->insn_type = dis_jsr;
01285                 else
01286                   info->insn_type = dis_branch;
01287                 info->branch_delay_insns = 1;
01288               }
01289              else if ((op->pinfo & (INSN_COND_BRANCH_DELAY
01290                                  | INSN_COND_BRANCH_LIKELY)) != 0)
01291               {
01292                 if ((info->insn_type & INSN_WRITE_GPR_31) != 0)
01293                   info->insn_type = dis_condjsr;
01294                 else
01295                   info->insn_type = dis_condbranch;
01296                 info->branch_delay_insns = 1;
01297               }
01298              else if ((op->pinfo & (INSN_STORE_MEMORY
01299                                  | INSN_LOAD_MEMORY_DELAY)) != 0)
01300               info->insn_type = dis_dref;
01301 
01302              (*info->fprintf_func) (info->stream, "%s", op->name);
01303 
01304              d = op->args;
01305              if (d != NULL && *d != '\0')
01306               {
01307                 (*info->fprintf_func) (info->stream, "\t");
01308                 print_insn_args (d, word, memaddr, info, op);
01309               }
01310 
01311              return INSNLEN;
01312            }
01313        }
01314     }
01315 
01316   /* Handle undefined instructions.  */
01317   info->insn_type = dis_noninsn;
01318   (*info->fprintf_func) (info->stream, "0x%lx", word);
01319   return INSNLEN;
01320 }
01321 
01322 /* Disassemble an operand for a mips16 instruction.  */
01323 
01324 static void
01325 print_mips16_insn_arg (char type,
01326                      const struct mips_opcode *op,
01327                      int l,
01328                      bfd_boolean use_extend,
01329                      int extend,
01330                      bfd_vma memaddr,
01331                      struct disassemble_info *info)
01332 {
01333   switch (type)
01334     {
01335     case ',':
01336     case '(':
01337     case ')':
01338       (*info->fprintf_func) (info->stream, "%c", type);
01339       break;
01340 
01341     case 'y':
01342     case 'w':
01343       (*info->fprintf_func) (info->stream, "%s",
01344                           mips16_reg_names(((l >> MIPS16OP_SH_RY)
01345                                           & MIPS16OP_MASK_RY)));
01346       break;
01347 
01348     case 'x':
01349     case 'v':
01350       (*info->fprintf_func) (info->stream, "%s",
01351                           mips16_reg_names(((l >> MIPS16OP_SH_RX)
01352                                           & MIPS16OP_MASK_RX)));
01353       break;
01354 
01355     case 'z':
01356       (*info->fprintf_func) (info->stream, "%s",
01357                           mips16_reg_names(((l >> MIPS16OP_SH_RZ)
01358                                           & MIPS16OP_MASK_RZ)));
01359       break;
01360 
01361     case 'Z':
01362       (*info->fprintf_func) (info->stream, "%s",
01363                           mips16_reg_names(((l >> MIPS16OP_SH_MOVE32Z)
01364                                           & MIPS16OP_MASK_MOVE32Z)));
01365       break;
01366 
01367     case '0':
01368       (*info->fprintf_func) (info->stream, "%s", mips_gpr_names[0]);
01369       break;
01370 
01371     case 'S':
01372       (*info->fprintf_func) (info->stream, "%s", mips_gpr_names[29]);
01373       break;
01374 
01375     case 'P':
01376       (*info->fprintf_func) (info->stream, "$pc");
01377       break;
01378 
01379     case 'R':
01380       (*info->fprintf_func) (info->stream, "%s", mips_gpr_names[31]);
01381       break;
01382 
01383     case 'X':
01384       (*info->fprintf_func) (info->stream, "%s",
01385                           mips_gpr_names[((l >> MIPS16OP_SH_REGR32)
01386                                        & MIPS16OP_MASK_REGR32)]);
01387       break;
01388 
01389     case 'Y':
01390       (*info->fprintf_func) (info->stream, "%s",
01391                           mips_gpr_names[MIPS16OP_EXTRACT_REG32R (l)]);
01392       break;
01393 
01394     case '<':
01395     case '>':
01396     case '[':
01397     case ']':
01398     case '4':
01399     case '5':
01400     case 'H':
01401     case 'W':
01402     case 'D':
01403     case 'j':
01404     case '6':
01405     case '8':
01406     case 'V':
01407     case 'C':
01408     case 'U':
01409     case 'k':
01410     case 'K':
01411     case 'p':
01412     case 'q':
01413     case 'A':
01414     case 'B':
01415     case 'E':
01416       {
01417        int immed, nbits, shift, signedp, extbits, pcrel, extu, branch;
01418 
01419        shift = 0;
01420        signedp = 0;
01421        extbits = 16;
01422        pcrel = 0;
01423        extu = 0;
01424        branch = 0;
01425        switch (type)
01426          {
01427          case '<':
01428            nbits = 3;
01429            immed = (l >> MIPS16OP_SH_RZ) & MIPS16OP_MASK_RZ;
01430            extbits = 5;
01431            extu = 1;
01432            break;
01433          case '>':
01434            nbits = 3;
01435            immed = (l >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX;
01436            extbits = 5;
01437            extu = 1;
01438            break;
01439          case '[':
01440            nbits = 3;
01441            immed = (l >> MIPS16OP_SH_RZ) & MIPS16OP_MASK_RZ;
01442            extbits = 6;
01443            extu = 1;
01444            break;
01445          case ']':
01446            nbits = 3;
01447            immed = (l >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX;
01448            extbits = 6;
01449            extu = 1;
01450            break;
01451          case '4':
01452            nbits = 4;
01453            immed = (l >> MIPS16OP_SH_IMM4) & MIPS16OP_MASK_IMM4;
01454            signedp = 1;
01455            extbits = 15;
01456            break;
01457          case '5':
01458            nbits = 5;
01459            immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
01460            info->insn_type = dis_dref;
01461            info->data_size = 1;
01462            break;
01463          case 'H':
01464            nbits = 5;
01465            shift = 1;
01466            immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
01467            info->insn_type = dis_dref;
01468            info->data_size = 2;
01469            break;
01470          case 'W':
01471            nbits = 5;
01472            shift = 2;
01473            immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
01474            if ((op->pinfo & MIPS16_INSN_READ_PC) == 0
01475               && (op->pinfo & MIPS16_INSN_READ_SP) == 0)
01476              {
01477               info->insn_type = dis_dref;
01478               info->data_size = 4;
01479              }
01480            break;
01481          case 'D':
01482            nbits = 5;
01483            shift = 3;
01484            immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
01485            info->insn_type = dis_dref;
01486            info->data_size = 8;
01487            break;
01488          case 'j':
01489            nbits = 5;
01490            immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
01491            signedp = 1;
01492            break;
01493          case '6':
01494            nbits = 6;
01495            immed = (l >> MIPS16OP_SH_IMM6) & MIPS16OP_MASK_IMM6;
01496            break;
01497          case '8':
01498            nbits = 8;
01499            immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
01500            break;
01501          case 'V':
01502            nbits = 8;
01503            shift = 2;
01504            immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
01505            /* FIXME: This might be lw, or it might be addiu to $sp or
01506                $pc.  We assume it's load.  */
01507            info->insn_type = dis_dref;
01508            info->data_size = 4;
01509            break;
01510          case 'C':
01511            nbits = 8;
01512            shift = 3;
01513            immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
01514            info->insn_type = dis_dref;
01515            info->data_size = 8;
01516            break;
01517          case 'U':
01518            nbits = 8;
01519            immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
01520            extu = 1;
01521            break;
01522          case 'k':
01523            nbits = 8;
01524            immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
01525            signedp = 1;
01526            break;
01527          case 'K':
01528            nbits = 8;
01529            shift = 3;
01530            immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
01531            signedp = 1;
01532            break;
01533          case 'p':
01534            nbits = 8;
01535            immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
01536            signedp = 1;
01537            pcrel = 1;
01538            branch = 1;
01539            info->insn_type = dis_condbranch;
01540            break;
01541          case 'q':
01542            nbits = 11;
01543            immed = (l >> MIPS16OP_SH_IMM11) & MIPS16OP_MASK_IMM11;
01544            signedp = 1;
01545            pcrel = 1;
01546            branch = 1;
01547            info->insn_type = dis_branch;
01548            break;
01549          case 'A':
01550            nbits = 8;
01551            shift = 2;
01552            immed = (l >> MIPS16OP_SH_IMM8) & MIPS16OP_MASK_IMM8;
01553            pcrel = 1;
01554            /* FIXME: This can be lw or la.  We assume it is lw.  */
01555            info->insn_type = dis_dref;
01556            info->data_size = 4;
01557            break;
01558          case 'B':
01559            nbits = 5;
01560            shift = 3;
01561            immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
01562            pcrel = 1;
01563            info->insn_type = dis_dref;
01564            info->data_size = 8;
01565            break;
01566          case 'E':
01567            nbits = 5;
01568            shift = 2;
01569            immed = (l >> MIPS16OP_SH_IMM5) & MIPS16OP_MASK_IMM5;
01570            pcrel = 1;
01571            break;
01572          default:
01573            abort ();
01574          }
01575 
01576        if (! use_extend)
01577          {
01578            if (signedp && immed >= (1 << (nbits - 1)))
01579              immed -= 1 << nbits;
01580            immed <<= shift;
01581            if ((type == '<' || type == '>' || type == '[' || type == ']')
01582               && immed == 0)
01583              immed = 8;
01584          }
01585        else
01586          {
01587            if (extbits == 16)
01588              immed |= ((extend & 0x1f) << 11) | (extend & 0x7e0);
01589            else if (extbits == 15)
01590              immed |= ((extend & 0xf) << 11) | (extend & 0x7f0);
01591            else
01592              immed = ((extend >> 6) & 0x1f) | (extend & 0x20);
01593            immed &= (1 << extbits) - 1;
01594            if (! extu && immed >= (1 << (extbits - 1)))
01595              immed -= 1 << extbits;
01596          }
01597 
01598        if (! pcrel)
01599          (*info->fprintf_func) (info->stream, "%d", immed);
01600        else
01601          {
01602            bfd_vma baseaddr;
01603 
01604            if (branch)
01605              {
01606               immed *= 2;
01607               baseaddr = memaddr + 2;
01608              }
01609            else if (use_extend)
01610              baseaddr = memaddr - 2;
01611            else
01612              {
01613               int status;
01614               bfd_byte buffer[2];
01615 
01616               baseaddr = memaddr;
01617 
01618               /* If this instruction is in the delay slot of a jr
01619                    instruction, the base address is the address of the
01620                    jr instruction.  If it is in the delay slot of jalr
01621                    instruction, the base address is the address of the
01622                    jalr instruction.  This test is unreliable: we have
01623                    no way of knowing whether the previous word is
01624                    instruction or data.  */
01625               status = (*info->read_memory_func) (memaddr - 4, buffer, 2,
01626                                               info);
01627               if (status == 0
01628                   && (((info->endian == BFD_ENDIAN_BIG
01629                        ? bfd_getb16 (buffer)
01630                        : bfd_getl16 (buffer))
01631                       & 0xf800) == 0x1800))
01632                 baseaddr = memaddr - 4;
01633               else
01634                 {
01635                   status = (*info->read_memory_func) (memaddr - 2, buffer,
01636                                                  2, info);
01637                   if (status == 0
01638                      && (((info->endian == BFD_ENDIAN_BIG
01639                            ? bfd_getb16 (buffer)
01640                            : bfd_getl16 (buffer))
01641                           & 0xf81f) == 0xe800))
01642                     baseaddr = memaddr - 2;
01643                 }
01644              }
01645            info->target = (baseaddr & ~((1 << shift) - 1)) + immed;
01646            if (pcrel && branch
01647               && info->flavour == bfd_target_unknown_flavour)
01648              /* For gdb disassembler, maintain odd address.  */
01649              info->target |= 1;
01650            (*info->print_address_func) (info->target, info);
01651          }
01652       }
01653       break;
01654 
01655     case 'a':
01656       {
01657        int jalx = l & 0x400;
01658 
01659        if (! use_extend)
01660          extend = 0;
01661        l = ((l & 0x1f) << 23) | ((l & 0x3e0) << 13) | (extend << 2);
01662        if (!jalx && info->flavour == bfd_target_unknown_flavour)
01663          /* For gdb disassembler, maintain odd address.  */
01664          l |= 1;
01665       }
01666       info->target = ((memaddr + 4) & ~(bfd_vma) 0x0fffffff) | l;
01667       (*info->print_address_func) (info->target, info);
01668       info->insn_type = dis_jsr;
01669       info->branch_delay_insns = 1;
01670       break;
01671 
01672     case 'l':
01673     case 'L':
01674       {
01675        int need_comma, amask, smask;
01676 
01677        need_comma = 0;
01678 
01679        l = (l >> MIPS16OP_SH_IMM6) & MIPS16OP_MASK_IMM6;
01680 
01681        amask = (l >> 3) & 7;
01682 
01683        if (amask > 0 && amask < 5)
01684          {
01685            (*info->fprintf_func) (info->stream, "%s", mips_gpr_names[4]);
01686            if (amask > 1)
01687              (*info->fprintf_func) (info->stream, "-%s",
01688                                  mips_gpr_names[amask + 3]);
01689            need_comma = 1;
01690          }
01691 
01692        smask = (l >> 1) & 3;
01693        if (smask == 3)
01694          {
01695            (*info->fprintf_func) (info->stream, "%s??",
01696                                need_comma ? "," : "");
01697            need_comma = 1;
01698          }
01699        else if (smask > 0)
01700          {
01701            (*info->fprintf_func) (info->stream, "%s%s",
01702                                need_comma ? "," : "",
01703                                mips_gpr_names[16]);
01704            if (smask > 1)
01705              (*info->fprintf_func) (info->stream, "-%s",
01706                                  mips_gpr_names[smask + 15]);
01707            need_comma = 1;
01708          }
01709 
01710        if (l & 1)
01711          {
01712            (*info->fprintf_func) (info->stream, "%s%s",
01713                                need_comma ? "," : "",
01714                                mips_gpr_names[31]);
01715            need_comma = 1;
01716          }
01717 
01718        if (amask == 5 || amask == 6)
01719          {
01720            (*info->fprintf_func) (info->stream, "%s$f0",
01721                                need_comma ? "," : "");
01722            if (amask == 6)
01723              (*info->fprintf_func) (info->stream, "-$f1");
01724          }
01725       }
01726       break;
01727 
01728     case 'm':
01729     case 'M':
01730       /* MIPS16e save/restore.  */
01731       {
01732       int need_comma = 0;
01733       int amask, args, statics;
01734       int nsreg, smask;
01735       int framesz;
01736       int i, j;
01737 
01738       l = l & 0x7f;
01739       if (use_extend)
01740         l |= extend << 16;
01741 
01742       amask = (l >> 16) & 0xf;
01743       if (amask == MIPS16_ALL_ARGS)
01744         {
01745           args = 4;
01746           statics = 0;
01747         }
01748       else if (amask == MIPS16_ALL_STATICS)
01749         {
01750           args = 0;
01751           statics = 4;
01752         }
01753       else
01754         {
01755           args = amask >> 2;
01756           statics = amask & 3;
01757         }
01758 
01759       if (args > 0) {
01760           (*info->fprintf_func) (info->stream, "%s", mips_gpr_names[4]);
01761           if (args > 1)
01762             (*info->fprintf_func) (info->stream, "-%s",
01763                                    mips_gpr_names[4 + args - 1]);
01764           need_comma = 1;
01765       }
01766 
01767       framesz = (((l >> 16) & 0xf0) | (l & 0x0f)) * 8;
01768       if (framesz == 0 && !use_extend)
01769         framesz = 128;
01770 
01771       (*info->fprintf_func) (info->stream, "%s%d", 
01772                              need_comma ? "," : "",
01773                              framesz);
01774 
01775       if (l & 0x40)                   /* $ra */
01776         (*info->fprintf_func) (info->stream, ",%s", mips_gpr_names[31]);
01777 
01778       nsreg = (l >> 24) & 0x7;
01779       smask = 0;
01780       if (l & 0x20)                   /* $s0 */
01781         smask |= 1 << 0;
01782       if (l & 0x10)                   /* $s1 */
01783         smask |= 1 << 1;
01784       if (nsreg > 0)                  /* $s2-$s8 */
01785         smask |= ((1 << nsreg) - 1) << 2;
01786 
01787       /* Find first set static reg bit.  */
01788       for (i = 0; i < 9; i++)
01789         {
01790           if (smask & (1 << i))
01791             {
01792               (*info->fprintf_func) (info->stream, ",%s",
01793                                      mips_gpr_names[i == 8 ? 30 : (16 + i)]);
01794               /* Skip over string of set bits.  */
01795               for (j = i; smask & (2 << j); j++)
01796                 continue;
01797               if (j > i)
01798                 (*info->fprintf_func) (info->stream, "-%s",
01799                                        mips_gpr_names[j == 8 ? 30 : (16 + j)]);
01800               i = j + 1;
01801             }
01802         }
01803 
01804       /* Statics $ax - $a3.  */
01805       if (statics == 1)
01806         (*info->fprintf_func) (info->stream, ",%s", mips_gpr_names[7]);
01807       else if (statics > 0) 
01808         (*info->fprintf_func) (info->stream, ",%s-%s", 
01809                                mips_gpr_names[7 - statics + 1],
01810                                mips_gpr_names[7]);
01811       }
01812       break;
01813 
01814     default:
01815       /* xgettext:c-format */
01816       (*info->fprintf_func)
01817        (info->stream,
01818         _("# internal disassembler error, unrecognised modifier (%c)"),
01819         type);
01820       abort ();
01821     }
01822 }
01823 
01824 /* Disassemble mips16 instructions.  */
01825 
01826 static int
01827 print_insn_mips16 (bfd_vma memaddr, struct disassemble_info *info)
01828 {
01829   int status;
01830   bfd_byte buffer[2];
01831   int length;
01832   int insn;
01833   bfd_boolean use_extend;
01834   int extend = 0;
01835   const struct mips_opcode *op, *opend;
01836 
01837   info->bytes_per_chunk = 2;
01838   info->display_endian = info->endian;
01839   info->insn_info_valid = 1;
01840   info->branch_delay_insns = 0;
01841   info->data_size = 0;
01842   info->insn_type = dis_nonbranch;
01843   info->target = 0;
01844   info->target2 = 0;
01845 
01846   status = (*info->read_memory_func) (memaddr, buffer, 2, info);
01847   if (status != 0)
01848     {
01849       (*info->memory_error_func) (status, memaddr, info);
01850       return -1;
01851     }
01852 
01853   length = 2;
01854 
01855   if (info->endian == BFD_ENDIAN_BIG)
01856     insn = bfd_getb16 (buffer);
01857   else
01858     insn = bfd_getl16 (buffer);
01859 
01860   /* Handle the extend opcode specially.  */
01861   use_extend = FALSE;
01862   if ((insn & 0xf800) == 0xf000)
01863     {
01864       use_extend = TRUE;
01865       extend = insn & 0x7ff;
01866 
01867       memaddr += 2;
01868 
01869       status = (*info->read_memory_func) (memaddr, buffer, 2, info);
01870       if (status != 0)
01871        {
01872          (*info->fprintf_func) (info->stream, "extend 0x%x",
01873                              (unsigned int) extend);
01874          (*info->memory_error_func) (status, memaddr, info);
01875          return -1;
01876        }
01877 
01878       if (info->endian == BFD_ENDIAN_BIG)
01879        insn = bfd_getb16 (buffer);
01880       else
01881        insn = bfd_getl16 (buffer);
01882 
01883       /* Check for an extend opcode followed by an extend opcode.  */
01884       if ((insn & 0xf800) == 0xf000)
01885        {
01886          (*info->fprintf_func) (info->stream, "extend 0x%x",
01887                              (unsigned int) extend);
01888          info->insn_type = dis_noninsn;
01889          return length;
01890        }
01891 
01892       length += 2;
01893     }
01894 
01895   /* FIXME: Should probably use a hash table on the major opcode here.  */
01896 
01897   opend = mips16_opcodes + bfd_mips16_num_opcodes;
01898   for (op = mips16_opcodes; op < opend; op++)
01899     {
01900       if (op->pinfo != INSN_MACRO
01901          && !(no_aliases && (op->pinfo2 & INSN2_ALIAS))
01902          && (insn & op->mask) == op->match)
01903        {
01904          const char *s;
01905 
01906          if (strchr (op->args, 'a') != NULL)
01907            {
01908              if (use_extend)
01909               {
01910                 (*info->fprintf_func) (info->stream, "extend 0x%x",
01911                                     (unsigned int) extend);
01912                 info->insn_type = dis_noninsn;
01913                 return length - 2;
01914               }
01915 
01916              use_extend = FALSE;
01917 
01918              memaddr += 2;
01919 
01920              status = (*info->read_memory_func) (memaddr, buffer, 2,
01921                                             info);
01922              if (status == 0)
01923               {
01924                 use_extend = TRUE;
01925                 if (info->endian == BFD_ENDIAN_BIG)
01926                   extend = bfd_getb16 (buffer);
01927                 else
01928                   extend = bfd_getl16 (buffer);
01929                 length += 2;
01930               }
01931            }
01932 
01933          (*info->fprintf_func) (info->stream, "%s", op->name);
01934          if (op->args[0] != '\0')
01935            (*info->fprintf_func) (info->stream, "\t");
01936 
01937          for (s = op->args; *s != '\0'; s++)
01938            {
01939              if (*s == ','
01940                 && s[1] == 'w'
01941                 && (((insn >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX)
01942                     == ((insn >> MIPS16OP_SH_RY) & MIPS16OP_MASK_RY)))
01943               {
01944                 /* Skip the register and the comma.  */
01945                 ++s;
01946                 continue;
01947               }
01948              if (*s == ','
01949                 && s[1] == 'v'
01950                 && (((insn >> MIPS16OP_SH_RZ) & MIPS16OP_MASK_RZ)
01951                     == ((insn >> MIPS16OP_SH_RX) & MIPS16OP_MASK_RX)))
01952               {
01953                 /* Skip the register and the comma.  */
01954                 ++s;
01955                 continue;
01956               }
01957              print_mips16_insn_arg (*s, op, insn, use_extend, extend, memaddr,
01958                                  info);
01959            }
01960 
01961          if ((op->pinfo & INSN_UNCOND_BRANCH_DELAY) != 0)
01962            {
01963              info->branch_delay_insns = 1;
01964              if (info->insn_type != dis_jsr)
01965               info->insn_type = dis_branch;
01966            }
01967 
01968          return length;
01969        }
01970     }
01971 
01972   if (use_extend)
01973     (*info->fprintf_func) (info->stream, "0x%x", extend | 0xf000);
01974   (*info->fprintf_func) (info->stream, "0x%x", insn);
01975   info->insn_type = dis_noninsn;
01976 
01977   return length;
01978 }
01979 
01980 /* In an environment where we do not know the symbol type of the
01981    instruction we are forced to assume that the low order bit of the
01982    instructions' address may mark it as a mips16 instruction.  If we
01983    are single stepping, or the pc is within the disassembled function,
01984    this works.  Otherwise, we need a clue.  Sometimes.  */
01985 
01986 static int
01987 _print_insn_mips (bfd_vma memaddr,
01988                 struct disassemble_info *info,
01989                 enum bfd_endian endianness)
01990 {
01991   bfd_byte buffer[INSNLEN];
01992   int status;
01993 
01994   set_default_mips_dis_options (info);
01995   parse_mips_dis_options (info->disassembler_options);
01996 
01997 #if 1
01998   /* FIXME: If odd address, this is CLEARLY a mips 16 instruction.  */
01999   /* Only a few tools will work this way.  */
02000   if (memaddr & 0x01)
02001     return print_insn_mips16 (memaddr, info);
02002 #endif
02003 
02004 #if SYMTAB_AVAILABLE
02005   if (info->mach == bfd_mach_mips16
02006       || (info->flavour == bfd_target_elf_flavour
02007          && info->symbols != NULL
02008          && ((*(elf_symbol_type **) info->symbols)->internal_elf_sym.st_other
02009              == STO_MIPS16)))
02010     return print_insn_mips16 (memaddr, info);
02011 #endif
02012 
02013   status = (*info->read_memory_func) (memaddr, buffer, INSNLEN, info);
02014   if (status == 0)
02015     {
02016       unsigned long insn;
02017 
02018       if (endianness == BFD_ENDIAN_BIG)
02019        insn = (unsigned long) bfd_getb32 (buffer);
02020       else
02021        insn = (unsigned long) bfd_getl32 (buffer);
02022 
02023       return print_insn_mips (memaddr, insn, info);
02024     }
02025   else
02026     {
02027       (*info->memory_error_func) (status, memaddr, info);
02028       return -1;
02029     }
02030 }
02031 
02032 int
02033 print_insn_big_mips (bfd_vma memaddr, struct disassemble_info *info)
02034 {
02035   return _print_insn_mips (memaddr, info, BFD_ENDIAN_BIG);
02036 }
02037 
02038 int
02039 print_insn_little_mips (bfd_vma memaddr, struct disassemble_info *info)
02040 {
02041   return _print_insn_mips (memaddr, info, BFD_ENDIAN_LITTLE);
02042 }
02043 
02044 void
02045 print_mips_disassembler_options (FILE *stream)
02046 {
02047   unsigned int i;
02048 
02049   fprintf (stream, _("\n\
02050 The following MIPS specific disassembler options are supported for use\n\
02051 with the -M switch (multiple options should be separated by commas):\n"));
02052 
02053   fprintf (stream, _("\n\
02054   gpr-names=ABI            Print GPR names according to  specified ABI.\n\
02055                            Default: based on binary being disassembled.\n"));
02056 
02057   fprintf (stream, _("\n\
02058   fpr-names=ABI            Print FPR names according to specified ABI.\n\
02059                            Default: numeric.\n"));
02060 
02061   fprintf (stream, _("\n\
02062   cp0-names=ARCH           Print CP0 register names according to\n\
02063                            specified architecture.\n\
02064                            Default: based on binary being disassembled.\n"));
02065 
02066   fprintf (stream, _("\n\
02067   hwr-names=ARCH           Print HWR names according to specified \n\
02068                         architecture.\n\
02069                            Default: based on binary being disassembled.\n"));
02070 
02071   fprintf (stream, _("\n\
02072   reg-names=ABI            Print GPR and FPR names according to\n\
02073                            specified ABI.\n"));
02074 
02075   fprintf (stream, _("\n\
02076   reg-names=ARCH           Print CP0 register and HWR names according to\n\
02077                            specified architecture.\n"));
02078 
02079   fprintf (stream, _("\n\
02080   For the options above, the following values are supported for \"ABI\":\n\
02081    "));
02082   for (i = 0; i < ARRAY_SIZE (mips_abi_choices); i++)
02083     fprintf (stream, " %s", mips_abi_choices[i].name);
02084   fprintf (stream, _("\n"));
02085 
02086   fprintf (stream, _("\n\
02087   For the options above, The following values are supported for \"ARCH\":\n\
02088    "));
02089   for (i = 0; i < ARRAY_SIZE (mips_arch_choices); i++)
02090     if (*mips_arch_choices[i].name != '\0')
02091       fprintf (stream, " %s", mips_arch_choices[i].name);
02092   fprintf (stream, _("\n"));
02093 
02094   fprintf (stream, _("\n"));
02095 }