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