1 1.1 christos /* RISC-V disassembler 2 1.1.1.7 christos Copyright (C) 2011-2025 Free Software Foundation, Inc. 3 1.1 christos 4 1.1 christos Contributed by Andrew Waterman (andrew (at) sifive.com). 5 1.1 christos Based on MIPS target. 6 1.1 christos 7 1.1 christos This file is part of the GNU opcodes library. 8 1.1 christos 9 1.1 christos This library is free software; you can redistribute it and/or modify 10 1.1 christos it under the terms of the GNU General Public License as published by 11 1.1 christos the Free Software Foundation; either version 3, or (at your option) 12 1.1 christos any later version. 13 1.1 christos 14 1.1 christos It is distributed in the hope that it will be useful, but WITHOUT 15 1.1 christos ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 16 1.1 christos or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public 17 1.1 christos License for more details. 18 1.1 christos 19 1.1 christos You should have received a copy of the GNU General Public License 20 1.1 christos along with this program; see the file COPYING3. If not, 21 1.1 christos see <http://www.gnu.org/licenses/>. */ 22 1.1 christos 23 1.1 christos #include "sysdep.h" 24 1.1.1.2 christos #include "disassemble.h" 25 1.1 christos #include "libiberty.h" 26 1.1 christos #include "opcode/riscv.h" 27 1.1 christos #include "opintl.h" 28 1.1 christos #include "elf-bfd.h" 29 1.1 christos #include "elf/riscv.h" 30 1.1.1.3 christos #include "elfxx-riscv.h" 31 1.1 christos 32 1.1.1.4 christos #include <stdint.h> 33 1.1 christos #include <ctype.h> 34 1.1 christos 35 1.1.1.6 christos /* The RISC-V disassembler produces styled output using 36 1.1.1.6 christos disassemble_info::fprintf_styled_func. This define prevents use of 37 1.1.1.6 christos disassemble_info::fprintf_func which is for unstyled output. */ 38 1.1.1.6 christos #define fprintf_func please_use_fprintf_styled_func_instead 39 1.1.1.6 christos 40 1.1.1.7 christos /* The earliest privilege spec supported by disassembler. */ 41 1.1.1.7 christos #define PRIV_SPEC_EARLIEST PRIV_SPEC_CLASS_1P10 42 1.1.1.3 christos 43 1.1 christos struct riscv_private_data 44 1.1 christos { 45 1.1 christos bfd_vma gp; 46 1.1 christos bfd_vma print_addr; 47 1.1 christos bfd_vma hi_addr[OP_MASK_RD + 1]; 48 1.1.1.4 christos bool to_print_addr; 49 1.1.1.4 christos bool has_gp; 50 1.1.1.7 christos /* Current XLEN for the disassembler. */ 51 1.1.1.7 christos unsigned xlen; 52 1.1.1.7 christos /* Default ISA specification version. */ 53 1.1.1.7 christos enum riscv_spec_class default_isa_spec; 54 1.1.1.7 christos /* Default privileged specification. */ 55 1.1.1.7 christos enum riscv_spec_class default_priv_spec; 56 1.1.1.7 christos /* Used for architecture parser. */ 57 1.1.1.7 christos riscv_parse_subset_t riscv_rps_dis; 58 1.1.1.7 christos /* Default architecture string for the object file. It will be changed once 59 1.1.1.7 christos elf architecture attribute exits. This is used for mapping symbol $x. */ 60 1.1.1.7 christos const char* default_arch; 61 1.1.1.7 christos /* Used for mapping symbols. */ 62 1.1.1.7 christos int last_map_symbol; 63 1.1.1.7 christos bfd_vma last_stop_offset; 64 1.1.1.7 christos bfd_vma last_map_symbol_boundary; 65 1.1.1.7 christos enum riscv_seg_mstate last_map_state; 66 1.1.1.7 christos asection *last_map_section; 67 1.1.1.7 christos /* Register names as used by the disassembler. */ 68 1.1.1.7 christos const char (*riscv_gpr_names)[NRC]; 69 1.1.1.7 christos const char (*riscv_fpr_names)[NRC]; 70 1.1.1.7 christos /* If set, disassemble as most general instruction. */ 71 1.1.1.7 christos bool no_aliases; 72 1.1.1.7 christos /* If set, disassemble without checking architecture string, just like what 73 1.1.1.7 christos we did at the beginning. */ 74 1.1.1.7 christos bool all_ext; 75 1.1 christos }; 76 1.1 christos 77 1.1.1.4 christos /* Set default RISC-V disassembler options. */ 78 1.1 christos 79 1.1 christos static void 80 1.1.1.7 christos set_default_riscv_dis_options (struct disassemble_info *info) 81 1.1 christos { 82 1.1.1.7 christos struct riscv_private_data *pd = info->private_data; 83 1.1.1.7 christos pd->riscv_gpr_names = riscv_gpr_names_abi; 84 1.1.1.7 christos pd->riscv_fpr_names = riscv_fpr_names_abi; 85 1.1.1.7 christos pd->no_aliases = false; 86 1.1.1.7 christos pd->all_ext = false; 87 1.1 christos } 88 1.1 christos 89 1.1.1.4 christos /* Parse RISC-V disassembler option (without arguments). */ 90 1.1.1.4 christos 91 1.1.1.4 christos static bool 92 1.1.1.7 christos parse_riscv_dis_option_without_args (const char *option, 93 1.1.1.7 christos struct disassemble_info *info) 94 1.1 christos { 95 1.1.1.7 christos struct riscv_private_data *pd = info->private_data; 96 1.1 christos if (strcmp (option, "no-aliases") == 0) 97 1.1.1.7 christos pd->no_aliases = true; 98 1.1 christos else if (strcmp (option, "numeric") == 0) 99 1.1 christos { 100 1.1.1.7 christos pd->riscv_gpr_names = riscv_gpr_names_numeric; 101 1.1.1.7 christos pd->riscv_fpr_names = riscv_fpr_names_numeric; 102 1.1 christos } 103 1.1.1.6 christos else if (strcmp (option, "max") == 0) 104 1.1.1.7 christos pd->all_ext = true; 105 1.1 christos else 106 1.1.1.4 christos return false; 107 1.1.1.4 christos return true; 108 1.1.1.3 christos } 109 1.1.1.3 christos 110 1.1.1.4 christos /* Parse RISC-V disassembler option (possibly with arguments). */ 111 1.1.1.4 christos 112 1.1.1.3 christos static void 113 1.1.1.7 christos parse_riscv_dis_option (const char *option, struct disassemble_info *info) 114 1.1.1.3 christos { 115 1.1.1.3 christos char *equal, *value; 116 1.1.1.3 christos 117 1.1.1.7 christos if (parse_riscv_dis_option_without_args (option, info)) 118 1.1.1.3 christos return; 119 1.1.1.3 christos 120 1.1.1.3 christos equal = strchr (option, '='); 121 1.1.1.3 christos if (equal == NULL) 122 1.1.1.3 christos { 123 1.1.1.3 christos /* The option without '=' should be defined above. */ 124 1.1.1.3 christos opcodes_error_handler (_("unrecognized disassembler option: %s"), option); 125 1.1.1.3 christos return; 126 1.1.1.3 christos } 127 1.1.1.3 christos if (equal == option 128 1.1.1.3 christos || *(equal + 1) == '\0') 129 1.1.1.3 christos { 130 1.1.1.3 christos /* Invalid options with '=', no option name before '=', 131 1.1.1.3 christos and no value after '='. */ 132 1.1.1.3 christos opcodes_error_handler (_("unrecognized disassembler option with '=': %s"), 133 1.1.1.3 christos option); 134 1.1.1.3 christos return; 135 1.1.1.3 christos } 136 1.1.1.3 christos 137 1.1.1.3 christos *equal = '\0'; 138 1.1.1.3 christos value = equal + 1; 139 1.1.1.3 christos if (strcmp (option, "priv-spec") == 0) 140 1.1.1.3 christos { 141 1.1.1.7 christos struct riscv_private_data *pd = info->private_data; 142 1.1.1.4 christos enum riscv_spec_class priv_spec = PRIV_SPEC_CLASS_NONE; 143 1.1.1.4 christos const char *name = NULL; 144 1.1.1.4 christos 145 1.1.1.4 christos RISCV_GET_PRIV_SPEC_CLASS (value, priv_spec); 146 1.1.1.7 christos if (priv_spec < PRIV_SPEC_EARLIEST) 147 1.1.1.4 christos opcodes_error_handler (_("unknown privileged spec set by %s=%s"), 148 1.1.1.4 christos option, value); 149 1.1.1.7 christos else if (pd->default_priv_spec == PRIV_SPEC_CLASS_NONE) 150 1.1.1.7 christos pd->default_priv_spec = priv_spec; 151 1.1.1.7 christos else if (pd->default_priv_spec != priv_spec) 152 1.1.1.4 christos { 153 1.1.1.7 christos RISCV_GET_PRIV_SPEC_NAME (name, pd->default_priv_spec); 154 1.1.1.4 christos opcodes_error_handler (_("mis-matched privilege spec set by %s=%s, " 155 1.1.1.4 christos "the elf privilege attribute is %s"), 156 1.1.1.4 christos option, value, name); 157 1.1.1.4 christos } 158 1.1.1.3 christos } 159 1.1.1.3 christos else 160 1.1 christos { 161 1.1.1.2 christos /* xgettext:c-format */ 162 1.1.1.2 christos opcodes_error_handler (_("unrecognized disassembler option: %s"), option); 163 1.1 christos } 164 1.1 christos } 165 1.1 christos 166 1.1.1.4 christos /* Parse RISC-V disassembler options. */ 167 1.1.1.4 christos 168 1.1 christos static void 169 1.1.1.7 christos parse_riscv_dis_options (const char *opts_in, struct disassemble_info *info) 170 1.1 christos { 171 1.1 christos char *opts = xstrdup (opts_in), *opt = opts, *opt_end = opts; 172 1.1 christos 173 1.1.1.7 christos set_default_riscv_dis_options (info); 174 1.1 christos 175 1.1 christos for ( ; opt_end != NULL; opt = opt_end + 1) 176 1.1 christos { 177 1.1 christos if ((opt_end = strchr (opt, ',')) != NULL) 178 1.1 christos *opt_end = 0; 179 1.1.1.7 christos parse_riscv_dis_option (opt, info); 180 1.1 christos } 181 1.1 christos 182 1.1 christos free (opts); 183 1.1 christos } 184 1.1 christos 185 1.1 christos /* Print one argument from an array. */ 186 1.1 christos 187 1.1 christos static void 188 1.1 christos arg_print (struct disassemble_info *info, unsigned long val, 189 1.1 christos const char* const* array, size_t size) 190 1.1 christos { 191 1.1 christos const char *s = val >= size || array[val] == NULL ? "unknown" : array[val]; 192 1.1.1.4 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, "%s", s); 193 1.1 christos } 194 1.1 christos 195 1.1.1.4 christos /* If we need to print an address, set its value and state. */ 196 1.1.1.4 christos 197 1.1 christos static void 198 1.1.1.4 christos maybe_print_address (struct riscv_private_data *pd, int base_reg, int offset, 199 1.1.1.4 christos int wide) 200 1.1 christos { 201 1.1 christos if (pd->hi_addr[base_reg] != (bfd_vma)-1) 202 1.1 christos { 203 1.1.1.2 christos pd->print_addr = (base_reg != 0 ? pd->hi_addr[base_reg] : 0) + offset; 204 1.1 christos pd->hi_addr[base_reg] = -1; 205 1.1 christos } 206 1.1.1.4 christos else if (base_reg == X_GP && pd->has_gp) 207 1.1 christos pd->print_addr = pd->gp + offset; 208 1.1 christos else if (base_reg == X_TP || base_reg == 0) 209 1.1 christos pd->print_addr = offset; 210 1.1.1.4 christos else 211 1.1.1.4 christos return; /* Don't print the address. */ 212 1.1.1.4 christos pd->to_print_addr = true; 213 1.1.1.4 christos 214 1.1.1.4 christos /* Sign-extend a 32-bit value to a 64-bit value. */ 215 1.1.1.4 christos if (wide) 216 1.1.1.4 christos pd->print_addr = (bfd_vma)(int32_t) pd->print_addr; 217 1.1.1.4 christos 218 1.1.1.4 christos /* Fit into a 32-bit value on RV32. */ 219 1.1.1.7 christos if (pd->xlen == 32) 220 1.1.1.4 christos pd->print_addr = (bfd_vma)(uint32_t)pd->print_addr; 221 1.1 christos } 222 1.1 christos 223 1.1.1.5 christos /* Get Zcmp reg_list field. */ 224 1.1.1.5 christos 225 1.1.1.5 christos static void 226 1.1.1.5 christos print_reg_list (disassemble_info *info, insn_t l) 227 1.1.1.5 christos { 228 1.1.1.7 christos struct riscv_private_data *pd = info->private_data; 229 1.1.1.7 christos bool numeric = pd->riscv_gpr_names == riscv_gpr_names_numeric; 230 1.1.1.5 christos unsigned reg_list = (int)EXTRACT_OPERAND (REG_LIST, l); 231 1.1.1.5 christos unsigned r_start = numeric ? X_S2 : X_S0; 232 1.1.1.6 christos info->fprintf_styled_func (info->stream, dis_style_register, 233 1.1.1.7 christos "%s", pd->riscv_gpr_names[X_RA]); 234 1.1.1.5 christos 235 1.1.1.5 christos if (reg_list == 5) 236 1.1.1.6 christos { 237 1.1.1.6 christos info->fprintf_styled_func (info->stream, dis_style_text, ","); 238 1.1.1.6 christos info->fprintf_styled_func (info->stream, dis_style_register, 239 1.1.1.7 christos "%s", pd->riscv_gpr_names[X_S0]); 240 1.1.1.6 christos } 241 1.1.1.5 christos else if (reg_list == 6 || (numeric && reg_list > 6)) 242 1.1.1.6 christos { 243 1.1.1.6 christos info->fprintf_styled_func (info->stream, dis_style_text, ","); 244 1.1.1.6 christos info->fprintf_styled_func (info->stream, dis_style_register, 245 1.1.1.7 christos "%s", pd->riscv_gpr_names[X_S0]); 246 1.1.1.6 christos info->fprintf_styled_func (info->stream, dis_style_text, "-"); 247 1.1.1.6 christos info->fprintf_styled_func (info->stream, dis_style_register, 248 1.1.1.7 christos "%s", pd->riscv_gpr_names[X_S1]); 249 1.1.1.6 christos } 250 1.1.1.6 christos 251 1.1.1.5 christos if (reg_list == 15) 252 1.1.1.6 christos { 253 1.1.1.6 christos info->fprintf_styled_func (info->stream, dis_style_text, ","); 254 1.1.1.6 christos info->fprintf_styled_func (info->stream, dis_style_register, 255 1.1.1.7 christos "%s", pd->riscv_gpr_names[r_start]); 256 1.1.1.6 christos info->fprintf_styled_func (info->stream, dis_style_text, "-"); 257 1.1.1.6 christos info->fprintf_styled_func (info->stream, dis_style_register, 258 1.1.1.7 christos "%s", pd->riscv_gpr_names[X_S11]); 259 1.1.1.6 christos } 260 1.1.1.5 christos else if (reg_list == 7 && numeric) 261 1.1.1.6 christos { 262 1.1.1.6 christos info->fprintf_styled_func (info->stream, dis_style_text, ","); 263 1.1.1.6 christos info->fprintf_styled_func (info->stream, dis_style_register, 264 1.1.1.7 christos "%s", pd->riscv_gpr_names[X_S2]); 265 1.1.1.6 christos } 266 1.1.1.5 christos else if (reg_list > 6) 267 1.1.1.6 christos { 268 1.1.1.6 christos info->fprintf_styled_func (info->stream, dis_style_text, ","); 269 1.1.1.6 christos info->fprintf_styled_func (info->stream, dis_style_register, 270 1.1.1.7 christos "%s", pd->riscv_gpr_names[r_start]); 271 1.1.1.6 christos info->fprintf_styled_func (info->stream, dis_style_text, "-"); 272 1.1.1.6 christos info->fprintf_styled_func (info->stream, dis_style_register, 273 1.1.1.7 christos "%s", pd->riscv_gpr_names[reg_list + 11]); 274 1.1.1.6 christos } 275 1.1.1.5 christos } 276 1.1.1.5 christos 277 1.1.1.5 christos /* Get Zcmp sp adjustment immediate. */ 278 1.1.1.5 christos 279 1.1.1.5 christos static int 280 1.1.1.7 christos riscv_get_spimm (insn_t l, int xlen) 281 1.1.1.5 christos { 282 1.1.1.7 christos int spimm = riscv_get_sp_base(l, xlen); 283 1.1.1.5 christos spimm += EXTRACT_ZCMP_SPIMM (l); 284 1.1.1.5 christos if (((l ^ MATCH_CM_PUSH) & MASK_CM_PUSH) == 0) 285 1.1.1.5 christos spimm *= -1; 286 1.1.1.5 christos return spimm; 287 1.1.1.5 christos } 288 1.1.1.5 christos 289 1.1.1.6 christos /* Get s-register regno by using sreg number. 290 1.1.1.6 christos e.g. the regno of s0 is 8, so 291 1.1.1.6 christos riscv_zcmp_get_sregno (0) equals 8. */ 292 1.1.1.6 christos 293 1.1.1.6 christos static unsigned 294 1.1.1.6 christos riscv_zcmp_get_sregno (unsigned sreg_idx) 295 1.1.1.6 christos { 296 1.1.1.6 christos return sreg_idx > 1 ? 297 1.1.1.6 christos sreg_idx + 16 : sreg_idx + 8; 298 1.1.1.6 christos } 299 1.1.1.6 christos 300 1.1 christos /* Print insn arguments for 32/64-bit code. */ 301 1.1 christos 302 1.1 christos static void 303 1.1.1.4 christos print_insn_args (const char *oparg, insn_t l, bfd_vma pc, disassemble_info *info) 304 1.1 christos { 305 1.1 christos struct riscv_private_data *pd = info->private_data; 306 1.1 christos int rs1 = (l >> OP_SH_RS1) & OP_MASK_RS1; 307 1.1 christos int rd = (l >> OP_SH_RD) & OP_MASK_RD; 308 1.1.1.4 christos fprintf_styled_ftype print = info->fprintf_styled_func; 309 1.1.1.4 christos const char *opargStart; 310 1.1 christos 311 1.1.1.4 christos if (*oparg != '\0') 312 1.1.1.4 christos print (info->stream, dis_style_text, "\t"); 313 1.1 christos 314 1.1.1.4 christos for (; *oparg != '\0'; oparg++) 315 1.1 christos { 316 1.1.1.4 christos opargStart = oparg; 317 1.1.1.4 christos switch (*oparg) 318 1.1 christos { 319 1.1 christos case 'C': /* RVC */ 320 1.1.1.4 christos switch (*++oparg) 321 1.1 christos { 322 1.1.1.4 christos case 's': /* RS1 x8-x15. */ 323 1.1.1.4 christos case 'w': /* RS1 x8-x15. */ 324 1.1.1.4 christos print (info->stream, dis_style_register, "%s", 325 1.1.1.7 christos pd->riscv_gpr_names[EXTRACT_OPERAND (CRS1S, l) + 8]); 326 1.1 christos break; 327 1.1.1.4 christos case 't': /* RS2 x8-x15. */ 328 1.1.1.4 christos case 'x': /* RS2 x8-x15. */ 329 1.1.1.4 christos print (info->stream, dis_style_register, "%s", 330 1.1.1.7 christos pd->riscv_gpr_names[EXTRACT_OPERAND (CRS2S, l) + 8]); 331 1.1 christos break; 332 1.1.1.4 christos case 'U': /* RS1, constrained to equal RD. */ 333 1.1.1.4 christos print (info->stream, dis_style_register, 334 1.1.1.7 christos "%s", pd->riscv_gpr_names[rd]); 335 1.1.1.4 christos break; 336 1.1.1.4 christos case 'c': /* RS1, constrained to equal sp. */ 337 1.1.1.4 christos print (info->stream, dis_style_register, "%s", 338 1.1.1.7 christos pd->riscv_gpr_names[X_SP]); 339 1.1 christos break; 340 1.1 christos case 'V': /* RS2 */ 341 1.1.1.4 christos print (info->stream, dis_style_register, "%s", 342 1.1.1.7 christos pd->riscv_gpr_names[EXTRACT_OPERAND (CRS2, l)]); 343 1.1 christos break; 344 1.1.1.2 christos case 'o': 345 1.1 christos case 'j': 346 1.1.1.4 christos if (((l & MASK_C_ADDI) == MATCH_C_ADDI) && rd != 0) 347 1.1.1.4 christos maybe_print_address (pd, rd, EXTRACT_CITYPE_IMM (l), 0); 348 1.1.1.7 christos if (pd->xlen == 64 349 1.1.1.4 christos && ((l & MASK_C_ADDIW) == MATCH_C_ADDIW) && rd != 0) 350 1.1.1.4 christos maybe_print_address (pd, rd, EXTRACT_CITYPE_IMM (l), 1); 351 1.1.1.4 christos print (info->stream, dis_style_immediate, "%d", 352 1.1.1.4 christos (int)EXTRACT_CITYPE_IMM (l)); 353 1.1 christos break; 354 1.1 christos case 'k': 355 1.1.1.4 christos print (info->stream, dis_style_address_offset, "%d", 356 1.1.1.4 christos (int)EXTRACT_CLTYPE_LW_IMM (l)); 357 1.1 christos break; 358 1.1 christos case 'l': 359 1.1.1.4 christos print (info->stream, dis_style_address_offset, "%d", 360 1.1.1.4 christos (int)EXTRACT_CLTYPE_LD_IMM (l)); 361 1.1 christos break; 362 1.1 christos case 'm': 363 1.1.1.4 christos print (info->stream, dis_style_address_offset, "%d", 364 1.1.1.4 christos (int)EXTRACT_CITYPE_LWSP_IMM (l)); 365 1.1 christos break; 366 1.1 christos case 'n': 367 1.1.1.4 christos print (info->stream, dis_style_address_offset, "%d", 368 1.1.1.4 christos (int)EXTRACT_CITYPE_LDSP_IMM (l)); 369 1.1 christos break; 370 1.1 christos case 'K': 371 1.1.1.4 christos print (info->stream, dis_style_immediate, "%d", 372 1.1.1.4 christos (int)EXTRACT_CIWTYPE_ADDI4SPN_IMM (l)); 373 1.1 christos break; 374 1.1 christos case 'L': 375 1.1.1.4 christos print (info->stream, dis_style_immediate, "%d", 376 1.1.1.4 christos (int)EXTRACT_CITYPE_ADDI16SP_IMM (l)); 377 1.1 christos break; 378 1.1 christos case 'M': 379 1.1.1.4 christos print (info->stream, dis_style_address_offset, "%d", 380 1.1.1.4 christos (int)EXTRACT_CSSTYPE_SWSP_IMM (l)); 381 1.1 christos break; 382 1.1 christos case 'N': 383 1.1.1.4 christos print (info->stream, dis_style_address_offset, "%d", 384 1.1.1.4 christos (int)EXTRACT_CSSTYPE_SDSP_IMM (l)); 385 1.1 christos break; 386 1.1 christos case 'p': 387 1.1.1.4 christos info->target = EXTRACT_CBTYPE_IMM (l) + pc; 388 1.1 christos (*info->print_address_func) (info->target, info); 389 1.1 christos break; 390 1.1 christos case 'a': 391 1.1.1.4 christos info->target = EXTRACT_CJTYPE_IMM (l) + pc; 392 1.1 christos (*info->print_address_func) (info->target, info); 393 1.1 christos break; 394 1.1 christos case 'u': 395 1.1.1.4 christos print (info->stream, dis_style_immediate, "0x%x", 396 1.1.1.4 christos (unsigned)(EXTRACT_CITYPE_IMM (l) & (RISCV_BIGIMM_REACH-1))); 397 1.1 christos break; 398 1.1 christos case '>': 399 1.1.1.4 christos print (info->stream, dis_style_immediate, "0x%x", 400 1.1.1.4 christos (unsigned)EXTRACT_CITYPE_IMM (l) & 0x3f); 401 1.1 christos break; 402 1.1 christos case '<': 403 1.1.1.4 christos print (info->stream, dis_style_immediate, "0x%x", 404 1.1.1.4 christos (unsigned)EXTRACT_CITYPE_IMM (l) & 0x1f); 405 1.1 christos break; 406 1.1.1.4 christos case 'T': /* Floating-point RS2. */ 407 1.1.1.4 christos print (info->stream, dis_style_register, "%s", 408 1.1.1.7 christos pd->riscv_fpr_names[EXTRACT_OPERAND (CRS2, l)]); 409 1.1 christos break; 410 1.1.1.4 christos case 'D': /* Floating-point RS2 x8-x15. */ 411 1.1.1.4 christos print (info->stream, dis_style_register, "%s", 412 1.1.1.7 christos pd->riscv_fpr_names[EXTRACT_OPERAND (CRS2S, l) + 8]); 413 1.1 christos break; 414 1.1 christos } 415 1.1 christos break; 416 1.1 christos 417 1.1.1.4 christos case 'V': /* RVV */ 418 1.1.1.4 christos switch (*++oparg) 419 1.1.1.4 christos { 420 1.1.1.4 christos case 'd': 421 1.1.1.4 christos case 'f': 422 1.1.1.4 christos print (info->stream, dis_style_register, "%s", 423 1.1.1.4 christos riscv_vecr_names_numeric[EXTRACT_OPERAND (VD, l)]); 424 1.1.1.4 christos break; 425 1.1.1.4 christos case 'e': 426 1.1.1.4 christos if (!EXTRACT_OPERAND (VWD, l)) 427 1.1.1.4 christos print (info->stream, dis_style_register, "%s", 428 1.1.1.7 christos pd->riscv_gpr_names[0]); 429 1.1.1.4 christos else 430 1.1.1.4 christos print (info->stream, dis_style_register, "%s", 431 1.1.1.4 christos riscv_vecr_names_numeric[EXTRACT_OPERAND (VD, l)]); 432 1.1.1.4 christos break; 433 1.1.1.4 christos case 's': 434 1.1.1.4 christos print (info->stream, dis_style_register, "%s", 435 1.1.1.4 christos riscv_vecr_names_numeric[EXTRACT_OPERAND (VS1, l)]); 436 1.1.1.4 christos break; 437 1.1.1.4 christos case 't': 438 1.1.1.4 christos case 'u': /* VS1 == VS2 already verified at this point. */ 439 1.1.1.4 christos case 'v': /* VD == VS1 == VS2 already verified at this point. */ 440 1.1.1.4 christos print (info->stream, dis_style_register, "%s", 441 1.1.1.4 christos riscv_vecr_names_numeric[EXTRACT_OPERAND (VS2, l)]); 442 1.1.1.4 christos break; 443 1.1.1.4 christos case '0': 444 1.1.1.4 christos print (info->stream, dis_style_register, "%s", 445 1.1.1.4 christos riscv_vecr_names_numeric[0]); 446 1.1.1.4 christos break; 447 1.1.1.4 christos case 'b': 448 1.1.1.4 christos case 'c': 449 1.1.1.4 christos { 450 1.1.1.4 christos int imm = (*oparg == 'b') ? EXTRACT_RVV_VB_IMM (l) 451 1.1.1.4 christos : EXTRACT_RVV_VC_IMM (l); 452 1.1.1.4 christos unsigned int imm_vlmul = EXTRACT_OPERAND (VLMUL, imm); 453 1.1.1.4 christos unsigned int imm_vsew = EXTRACT_OPERAND (VSEW, imm); 454 1.1.1.4 christos unsigned int imm_vta = EXTRACT_OPERAND (VTA, imm); 455 1.1.1.4 christos unsigned int imm_vma = EXTRACT_OPERAND (VMA, imm); 456 1.1.1.4 christos unsigned int imm_vtype_res = (imm >> 8); 457 1.1.1.4 christos 458 1.1.1.4 christos if (imm_vsew < ARRAY_SIZE (riscv_vsew) 459 1.1.1.4 christos && imm_vlmul < ARRAY_SIZE (riscv_vlmul) 460 1.1.1.4 christos && imm_vta < ARRAY_SIZE (riscv_vta) 461 1.1.1.4 christos && imm_vma < ARRAY_SIZE (riscv_vma) 462 1.1.1.4 christos && !imm_vtype_res 463 1.1.1.4 christos && riscv_vsew[imm_vsew] != NULL 464 1.1.1.4 christos && riscv_vlmul[imm_vlmul] != NULL) 465 1.1.1.4 christos print (info->stream, dis_style_text, "%s,%s,%s,%s", 466 1.1.1.4 christos riscv_vsew[imm_vsew], 467 1.1.1.4 christos riscv_vlmul[imm_vlmul], riscv_vta[imm_vta], 468 1.1.1.4 christos riscv_vma[imm_vma]); 469 1.1.1.4 christos else 470 1.1.1.4 christos print (info->stream, dis_style_immediate, "%d", imm); 471 1.1.1.4 christos } 472 1.1.1.4 christos break; 473 1.1.1.4 christos case 'i': 474 1.1.1.4 christos print (info->stream, dis_style_immediate, "%d", 475 1.1.1.4 christos (int)EXTRACT_RVV_VI_IMM (l)); 476 1.1.1.4 christos break; 477 1.1.1.4 christos case 'j': 478 1.1.1.4 christos print (info->stream, dis_style_immediate, "%d", 479 1.1.1.4 christos (int)EXTRACT_RVV_VI_UIMM (l)); 480 1.1.1.4 christos break; 481 1.1.1.4 christos case 'k': 482 1.1.1.4 christos print (info->stream, dis_style_immediate, "%d", 483 1.1.1.4 christos (int)EXTRACT_RVV_OFFSET (l)); 484 1.1.1.4 christos break; 485 1.1.1.5 christos case 'l': 486 1.1.1.5 christos print (info->stream, dis_style_immediate, "%d", 487 1.1.1.5 christos (int)EXTRACT_RVV_VI_UIMM6 (l)); 488 1.1.1.5 christos break; 489 1.1.1.4 christos case 'm': 490 1.1.1.4 christos if (!EXTRACT_OPERAND (VMASK, l)) 491 1.1.1.4 christos { 492 1.1.1.4 christos print (info->stream, dis_style_text, ","); 493 1.1.1.4 christos print (info->stream, dis_style_register, "%s", 494 1.1.1.4 christos riscv_vecm_names_numeric[0]); 495 1.1.1.4 christos } 496 1.1.1.4 christos break; 497 1.1.1.4 christos } 498 1.1.1.4 christos break; 499 1.1.1.4 christos 500 1.1 christos case ',': 501 1.1 christos case '(': 502 1.1 christos case ')': 503 1.1 christos case '[': 504 1.1 christos case ']': 505 1.1.1.5 christos case '{': 506 1.1.1.5 christos case '}': 507 1.1.1.4 christos print (info->stream, dis_style_text, "%c", *oparg); 508 1.1 christos break; 509 1.1 christos 510 1.1 christos case '0': 511 1.1.1.4 christos /* Only print constant 0 if it is the last argument. */ 512 1.1.1.4 christos if (!oparg[1]) 513 1.1.1.4 christos print (info->stream, dis_style_immediate, "0"); 514 1.1 christos break; 515 1.1 christos 516 1.1.1.7 christos case 'r': 517 1.1.1.7 christos print (info->stream, dis_style_register, "%s", 518 1.1.1.7 christos pd->riscv_gpr_names[EXTRACT_OPERAND (RS3, l)]); 519 1.1.1.7 christos break; 520 1.1.1.7 christos 521 1.1 christos case 's': 522 1.1.1.2 christos if ((l & MASK_JALR) == MATCH_JALR) 523 1.1.1.4 christos maybe_print_address (pd, rs1, EXTRACT_ITYPE_IMM (l), 0); 524 1.1.1.7 christos print (info->stream, dis_style_register, "%s", 525 1.1.1.7 christos pd->riscv_gpr_names[rs1]); 526 1.1 christos break; 527 1.1 christos 528 1.1 christos case 't': 529 1.1.1.4 christos print (info->stream, dis_style_register, "%s", 530 1.1.1.7 christos pd->riscv_gpr_names[EXTRACT_OPERAND (RS2, l)]); 531 1.1 christos break; 532 1.1 christos 533 1.1 christos case 'u': 534 1.1.1.4 christos print (info->stream, dis_style_immediate, "0x%x", 535 1.1 christos (unsigned)EXTRACT_UTYPE_IMM (l) >> RISCV_IMM_BITS); 536 1.1 christos break; 537 1.1 christos 538 1.1 christos case 'm': 539 1.1 christos arg_print (info, EXTRACT_OPERAND (RM, l), 540 1.1 christos riscv_rm, ARRAY_SIZE (riscv_rm)); 541 1.1 christos break; 542 1.1 christos 543 1.1 christos case 'P': 544 1.1 christos arg_print (info, EXTRACT_OPERAND (PRED, l), 545 1.1 christos riscv_pred_succ, ARRAY_SIZE (riscv_pred_succ)); 546 1.1 christos break; 547 1.1 christos 548 1.1 christos case 'Q': 549 1.1 christos arg_print (info, EXTRACT_OPERAND (SUCC, l), 550 1.1 christos riscv_pred_succ, ARRAY_SIZE (riscv_pred_succ)); 551 1.1 christos break; 552 1.1 christos 553 1.1 christos case 'o': 554 1.1.1.4 christos maybe_print_address (pd, rs1, EXTRACT_ITYPE_IMM (l), 0); 555 1.1 christos /* Fall through. */ 556 1.1 christos case 'j': 557 1.1 christos if (((l & MASK_ADDI) == MATCH_ADDI && rs1 != 0) 558 1.1 christos || (l & MASK_JALR) == MATCH_JALR) 559 1.1.1.4 christos maybe_print_address (pd, rs1, EXTRACT_ITYPE_IMM (l), 0); 560 1.1.1.7 christos if (pd->xlen == 64 561 1.1.1.4 christos && ((l & MASK_ADDIW) == MATCH_ADDIW) && rs1 != 0) 562 1.1.1.4 christos maybe_print_address (pd, rs1, EXTRACT_ITYPE_IMM (l), 1); 563 1.1.1.4 christos print (info->stream, dis_style_immediate, "%d", 564 1.1.1.4 christos (int)EXTRACT_ITYPE_IMM (l)); 565 1.1 christos break; 566 1.1 christos 567 1.1 christos case 'q': 568 1.1.1.4 christos maybe_print_address (pd, rs1, EXTRACT_STYPE_IMM (l), 0); 569 1.1.1.4 christos print (info->stream, dis_style_address_offset, "%d", 570 1.1.1.4 christos (int)EXTRACT_STYPE_IMM (l)); 571 1.1.1.4 christos break; 572 1.1.1.4 christos 573 1.1 christos case 'a': 574 1.1.1.4 christos info->target = EXTRACT_JTYPE_IMM (l) + pc; 575 1.1 christos (*info->print_address_func) (info->target, info); 576 1.1 christos break; 577 1.1 christos 578 1.1 christos case 'p': 579 1.1.1.4 christos info->target = EXTRACT_BTYPE_IMM (l) + pc; 580 1.1 christos (*info->print_address_func) (info->target, info); 581 1.1 christos break; 582 1.1 christos 583 1.1 christos case 'd': 584 1.1 christos if ((l & MASK_AUIPC) == MATCH_AUIPC) 585 1.1 christos pd->hi_addr[rd] = pc + EXTRACT_UTYPE_IMM (l); 586 1.1 christos else if ((l & MASK_LUI) == MATCH_LUI) 587 1.1 christos pd->hi_addr[rd] = EXTRACT_UTYPE_IMM (l); 588 1.1 christos else if ((l & MASK_C_LUI) == MATCH_C_LUI) 589 1.1.1.4 christos pd->hi_addr[rd] = EXTRACT_CITYPE_LUI_IMM (l); 590 1.1.1.7 christos print (info->stream, dis_style_register, "%s", 591 1.1.1.7 christos pd->riscv_gpr_names[rd]); 592 1.1.1.4 christos break; 593 1.1.1.4 christos 594 1.1.1.4 christos case 'y': 595 1.1.1.4 christos print (info->stream, dis_style_immediate, "0x%x", 596 1.1.1.5 christos EXTRACT_OPERAND (BS, l)); 597 1.1 christos break; 598 1.1 christos 599 1.1 christos case 'z': 600 1.1.1.7 christos print (info->stream, dis_style_register, "%s", 601 1.1.1.7 christos pd->riscv_gpr_names[0]); 602 1.1 christos break; 603 1.1 christos 604 1.1 christos case '>': 605 1.1.1.4 christos print (info->stream, dis_style_immediate, "0x%x", 606 1.1.1.5 christos EXTRACT_OPERAND (SHAMT, l)); 607 1.1 christos break; 608 1.1 christos 609 1.1 christos case '<': 610 1.1.1.4 christos print (info->stream, dis_style_immediate, "0x%x", 611 1.1.1.5 christos EXTRACT_OPERAND (SHAMTW, l)); 612 1.1 christos break; 613 1.1 christos 614 1.1 christos case 'S': 615 1.1 christos case 'U': 616 1.1.1.7 christos print (info->stream, dis_style_register, "%s", 617 1.1.1.7 christos pd->riscv_fpr_names[rs1]); 618 1.1 christos break; 619 1.1 christos 620 1.1 christos case 'T': 621 1.1.1.4 christos print (info->stream, dis_style_register, "%s", 622 1.1.1.7 christos pd->riscv_fpr_names[EXTRACT_OPERAND (RS2, l)]); 623 1.1 christos break; 624 1.1 christos 625 1.1 christos case 'D': 626 1.1.1.7 christos print (info->stream, dis_style_register, "%s", 627 1.1.1.7 christos pd->riscv_fpr_names[rd]); 628 1.1 christos break; 629 1.1 christos 630 1.1 christos case 'R': 631 1.1.1.4 christos print (info->stream, dis_style_register, "%s", 632 1.1.1.7 christos pd->riscv_fpr_names[EXTRACT_OPERAND (RS3, l)]); 633 1.1 christos break; 634 1.1 christos 635 1.1 christos case 'E': 636 1.1 christos { 637 1.1.1.4 christos static const char *riscv_csr_hash[4096]; /* Total 2^12 CSRs. */ 638 1.1.1.4 christos static bool init_csr = false; 639 1.1 christos unsigned int csr = EXTRACT_OPERAND (CSR, l); 640 1.1.1.3 christos 641 1.1.1.3 christos if (!init_csr) 642 1.1 christos { 643 1.1.1.3 christos unsigned int i; 644 1.1.1.3 christos for (i = 0; i < 4096; i++) 645 1.1.1.3 christos riscv_csr_hash[i] = NULL; 646 1.1.1.3 christos 647 1.1.1.4 christos /* Set to the newest privileged version. */ 648 1.1.1.7 christos if (pd->default_priv_spec == PRIV_SPEC_CLASS_NONE) 649 1.1.1.7 christos pd->default_priv_spec = PRIV_SPEC_CLASS_DRAFT - 1; 650 1.1.1.3 christos 651 1.1.1.3 christos #define DECLARE_CSR(name, num, class, define_version, abort_version) \ 652 1.1.1.3 christos if (riscv_csr_hash[num] == NULL \ 653 1.1.1.3 christos && ((define_version == PRIV_SPEC_CLASS_NONE \ 654 1.1.1.3 christos && abort_version == PRIV_SPEC_CLASS_NONE) \ 655 1.1.1.7 christos || (pd->default_priv_spec >= define_version \ 656 1.1.1.7 christos && pd->default_priv_spec < abort_version))) \ 657 1.1.1.3 christos riscv_csr_hash[num] = #name; 658 1.1.1.3 christos #define DECLARE_CSR_ALIAS(name, num, class, define_version, abort_version) \ 659 1.1.1.3 christos DECLARE_CSR (name, num, class, define_version, abort_version) 660 1.1 christos #include "opcode/riscv-opc.h" 661 1.1 christos #undef DECLARE_CSR 662 1.1 christos } 663 1.1.1.3 christos 664 1.1.1.3 christos if (riscv_csr_hash[csr] != NULL) 665 1.1.1.7 christos if (riscv_subset_supports (&pd->riscv_rps_dis, "xtheadvector") 666 1.1.1.5 christos && (csr == CSR_VSTART 667 1.1.1.5 christos || csr == CSR_VXSAT 668 1.1.1.5 christos || csr == CSR_VXRM 669 1.1.1.5 christos || csr == CSR_VL 670 1.1.1.5 christos || csr == CSR_VTYPE 671 1.1.1.5 christos || csr == CSR_VLENB)) 672 1.1.1.5 christos print (info->stream, dis_style_register, "%s", 673 1.1.1.5 christos concat ("th.", riscv_csr_hash[csr], NULL)); 674 1.1.1.5 christos else 675 1.1.1.5 christos print (info->stream, dis_style_register, "%s", 676 1.1.1.5 christos riscv_csr_hash[csr]); 677 1.1 christos else 678 1.1.1.4 christos print (info->stream, dis_style_immediate, "0x%x", csr); 679 1.1 christos break; 680 1.1 christos } 681 1.1 christos 682 1.1.1.4 christos case 'Y': 683 1.1.1.4 christos print (info->stream, dis_style_immediate, "0x%x", 684 1.1.1.5 christos EXTRACT_OPERAND (RNUM, l)); 685 1.1.1.4 christos break; 686 1.1.1.4 christos 687 1.1 christos case 'Z': 688 1.1.1.4 christos print (info->stream, dis_style_immediate, "%d", rs1); 689 1.1 christos break; 690 1.1 christos 691 1.1.1.5 christos case 'W': /* Various operands for standard z extensions. */ 692 1.1.1.5 christos switch (*++oparg) 693 1.1.1.5 christos { 694 1.1.1.5 christos case 'i': 695 1.1.1.5 christos switch (*++oparg) 696 1.1.1.5 christos { 697 1.1.1.5 christos case 'f': 698 1.1.1.5 christos print (info->stream, dis_style_address_offset, "%d", 699 1.1.1.5 christos (int) EXTRACT_STYPE_IMM (l)); 700 1.1.1.4 christos break; 701 1.1.1.5 christos default: 702 1.1.1.5 christos goto undefined_modifier; 703 1.1.1.5 christos } 704 1.1.1.5 christos break; 705 1.1.1.5 christos case 'f': 706 1.1.1.5 christos switch (*++oparg) 707 1.1.1.5 christos { 708 1.1.1.5 christos case 'v': 709 1.1.1.5 christos if (riscv_fli_symval[rs1]) 710 1.1.1.5 christos print (info->stream, dis_style_text, "%s", 711 1.1.1.5 christos riscv_fli_symval[rs1]); 712 1.1.1.4 christos else 713 1.1.1.5 christos print (info->stream, dis_style_immediate, "%a", 714 1.1.1.5 christos riscv_fli_numval[rs1]); 715 1.1.1.4 christos break; 716 1.1.1.4 christos default: 717 1.1.1.4 christos goto undefined_modifier; 718 1.1.1.5 christos } 719 1.1.1.5 christos break; 720 1.1.1.5 christos case 'c': /* Zcb extension 16 bits length instruction fields. */ 721 1.1.1.5 christos switch (*++oparg) 722 1.1.1.5 christos { 723 1.1.1.6 christos case '1': 724 1.1.1.6 christos print (info->stream, dis_style_register, "%s", 725 1.1.1.7 christos pd->riscv_gpr_names[riscv_zcmp_get_sregno (EXTRACT_OPERAND (SREG1, l))]); 726 1.1.1.6 christos break; 727 1.1.1.6 christos case '2': 728 1.1.1.6 christos print (info->stream, dis_style_register, "%s", 729 1.1.1.7 christos pd->riscv_gpr_names[riscv_zcmp_get_sregno (EXTRACT_OPERAND (SREG2, l))]); 730 1.1.1.6 christos break; 731 1.1.1.5 christos case 'b': 732 1.1.1.5 christos print (info->stream, dis_style_immediate, "%d", 733 1.1.1.5 christos (int)EXTRACT_ZCB_BYTE_UIMM (l)); 734 1.1.1.5 christos break; 735 1.1.1.5 christos case 'h': 736 1.1.1.5 christos print (info->stream, dis_style_immediate, "%d", 737 1.1.1.5 christos (int)EXTRACT_ZCB_HALFWORD_UIMM (l)); 738 1.1.1.5 christos break; 739 1.1.1.5 christos case 'r': 740 1.1.1.5 christos print_reg_list (info, l); 741 1.1.1.5 christos break; 742 1.1.1.5 christos case 'p': 743 1.1.1.5 christos print (info->stream, dis_style_immediate, "%d", 744 1.1.1.7 christos riscv_get_spimm (l, pd->xlen)); 745 1.1.1.5 christos break; 746 1.1.1.6 christos case 'i': 747 1.1.1.6 christos case 'I': 748 1.1.1.6 christos print (info->stream, dis_style_address_offset, 749 1.1.1.6 christos "%" PRIu64, EXTRACT_ZCMT_INDEX (l)); 750 1.1.1.6 christos break; 751 1.1.1.5 christos default: 752 1.1.1.5 christos goto undefined_modifier; 753 1.1.1.5 christos } 754 1.1.1.5 christos break; 755 1.1.1.5 christos default: 756 1.1.1.5 christos goto undefined_modifier; 757 1.1.1.5 christos } 758 1.1.1.5 christos break; 759 1.1.1.5 christos 760 1.1.1.5 christos case 'X': /* Vendor-specific operands. */ 761 1.1.1.5 christos switch (*++oparg) 762 1.1.1.5 christos { 763 1.1.1.5 christos case 't': /* Vendor-specific (T-head) operands. */ 764 1.1.1.5 christos { 765 1.1.1.5 christos size_t n; 766 1.1.1.5 christos size_t s; 767 1.1.1.5 christos bool sign; 768 1.1.1.5 christos switch (*++oparg) 769 1.1.1.5 christos { 770 1.1.1.5 christos case 'V': 771 1.1.1.5 christos ++oparg; 772 1.1.1.5 christos if (*oparg != 'c') 773 1.1.1.5 christos goto undefined_modifier; 774 1.1.1.5 christos 775 1.1.1.5 christos int imm = (*oparg == 'b') ? EXTRACT_RVV_VB_IMM (l) 776 1.1.1.5 christos : EXTRACT_RVV_VC_IMM (l); 777 1.1.1.5 christos unsigned int imm_vediv = EXTRACT_OPERAND (XTHEADVEDIV, imm); 778 1.1.1.5 christos unsigned int imm_vlmul = EXTRACT_OPERAND (XTHEADVLMUL, imm); 779 1.1.1.5 christos unsigned int imm_vsew = EXTRACT_OPERAND (XTHEADVSEW, imm); 780 1.1.1.5 christos unsigned int imm_vtype_res 781 1.1.1.5 christos = EXTRACT_OPERAND (XTHEADVTYPE_RES, imm); 782 1.1.1.5 christos if (imm_vsew < ARRAY_SIZE (riscv_vsew) 783 1.1.1.5 christos && imm_vlmul < ARRAY_SIZE (riscv_th_vlen) 784 1.1.1.5 christos && imm_vediv < ARRAY_SIZE (riscv_th_vediv) 785 1.1.1.5 christos && ! imm_vtype_res) 786 1.1.1.5 christos print (info->stream, dis_style_text, "%s,%s,%s", 787 1.1.1.5 christos riscv_vsew[imm_vsew], riscv_th_vlen[imm_vlmul], 788 1.1.1.5 christos riscv_th_vediv[imm_vediv]); 789 1.1.1.5 christos else 790 1.1.1.5 christos print (info->stream, dis_style_immediate, "%d", imm); 791 1.1.1.5 christos break; 792 1.1.1.5 christos case 'l': /* Integer immediate, literal. */ 793 1.1.1.5 christos oparg++; 794 1.1.1.5 christos while (*oparg && *oparg != ',') 795 1.1.1.5 christos { 796 1.1.1.5 christos print (info->stream, dis_style_immediate, "%c", *oparg); 797 1.1.1.5 christos oparg++; 798 1.1.1.5 christos } 799 1.1.1.5 christos oparg--; 800 1.1.1.5 christos break; 801 1.1.1.5 christos case 's': /* Integer immediate, 'XsN@S' ... N-bit signed immediate at bit S. */ 802 1.1.1.5 christos sign = true; 803 1.1.1.5 christos goto print_imm; 804 1.1.1.5 christos case 'u': /* Integer immediate, 'XuN@S' ... N-bit unsigned immediate at bit S. */ 805 1.1.1.5 christos sign = false; 806 1.1.1.5 christos goto print_imm; 807 1.1.1.5 christos print_imm: 808 1.1.1.5 christos n = strtol (oparg + 1, (char **)&oparg, 10); 809 1.1.1.5 christos if (*oparg != '@') 810 1.1.1.5 christos goto undefined_modifier; 811 1.1.1.5 christos s = strtol (oparg + 1, (char **)&oparg, 10); 812 1.1.1.5 christos oparg--; 813 1.1.1.5 christos 814 1.1.1.5 christos if (!sign) 815 1.1.1.5 christos print (info->stream, dis_style_immediate, "%lu", 816 1.1.1.5 christos (unsigned long)EXTRACT_U_IMM (n, s, l)); 817 1.1.1.5 christos else 818 1.1.1.5 christos print (info->stream, dis_style_immediate, "%li", 819 1.1.1.5 christos (signed long)EXTRACT_S_IMM (n, s, l)); 820 1.1.1.5 christos break; 821 1.1.1.5 christos default: 822 1.1.1.5 christos goto undefined_modifier; 823 1.1.1.5 christos } 824 1.1.1.4 christos } 825 1.1.1.5 christos break; 826 1.1.1.5 christos case 'c': /* Vendor-specific (CORE-V) operands. */ 827 1.1.1.5 christos switch (*++oparg) 828 1.1.1.5 christos { 829 1.1.1.5 christos case '2': 830 1.1.1.5 christos print (info->stream, dis_style_immediate, "%d", 831 1.1.1.5 christos ((int) EXTRACT_CV_IS2_UIMM5 (l))); 832 1.1.1.5 christos break; 833 1.1.1.5 christos case '3': 834 1.1.1.5 christos print (info->stream, dis_style_immediate, "%d", 835 1.1.1.5 christos ((int) EXTRACT_CV_IS3_UIMM5 (l))); 836 1.1.1.5 christos break; 837 1.1.1.6 christos case '4': 838 1.1.1.6 christos print (info->stream, dis_style_immediate, "%d", 839 1.1.1.6 christos ((int) EXTRACT_CV_BI_IMM5 (l))); 840 1.1.1.6 christos break; 841 1.1.1.6 christos case '5': 842 1.1.1.6 christos print (info->stream, dis_style_immediate, "%d", 843 1.1.1.6 christos ((int) EXTRACT_CV_SIMD_IMM6 (l))); 844 1.1.1.6 christos break; 845 1.1.1.6 christos case '6': 846 1.1.1.6 christos print (info->stream, dis_style_immediate, "%d", 847 1.1.1.6 christos ((int) EXTRACT_CV_BITMANIP_UIMM5 (l))); 848 1.1.1.6 christos break; 849 1.1.1.6 christos case '7': 850 1.1.1.6 christos print (info->stream, dis_style_immediate, "%d", 851 1.1.1.6 christos ((int) EXTRACT_CV_BITMANIP_UIMM2 (l))); 852 1.1.1.6 christos break; 853 1.1.1.6 christos case '8': 854 1.1.1.6 christos print (info->stream, dis_style_immediate, "%d", 855 1.1.1.6 christos ((int) EXTRACT_CV_SIMD_UIMM6 (l))); 856 1.1.1.6 christos ++oparg; 857 1.1.1.6 christos break; 858 1.1.1.5 christos default: 859 1.1.1.5 christos goto undefined_modifier; 860 1.1.1.5 christos } 861 1.1.1.5 christos break; 862 1.1.1.5 christos case 's': /* Vendor-specific (SiFive) operands. */ 863 1.1.1.5 christos switch (*++oparg) 864 1.1.1.5 christos { 865 1.1.1.5 christos /* SiFive vector coprocessor interface. */ 866 1.1.1.5 christos case 'd': 867 1.1.1.5 christos print (info->stream, dis_style_register, "0x%x", 868 1.1.1.5 christos (unsigned) EXTRACT_OPERAND (RD, l)); 869 1.1.1.5 christos break; 870 1.1.1.5 christos case 't': 871 1.1.1.5 christos print (info->stream, dis_style_register, "0x%x", 872 1.1.1.5 christos (unsigned) EXTRACT_OPERAND (RS2, l)); 873 1.1.1.5 christos break; 874 1.1.1.5 christos case 'O': 875 1.1.1.5 christos switch (*++oparg) 876 1.1.1.5 christos { 877 1.1.1.5 christos case '2': 878 1.1.1.5 christos print (info->stream, dis_style_register, "0x%x", 879 1.1.1.5 christos (unsigned) EXTRACT_OPERAND (XSO2, l)); 880 1.1.1.5 christos break; 881 1.1.1.5 christos case '1': 882 1.1.1.5 christos print (info->stream, dis_style_register, "0x%x", 883 1.1.1.5 christos (unsigned) EXTRACT_OPERAND (XSO1, l)); 884 1.1.1.5 christos break; 885 1.1.1.5 christos } 886 1.1.1.5 christos break; 887 1.1.1.5 christos } 888 1.1.1.5 christos break; 889 1.1.1.7 christos case 'm': /* Vendor-specific (MIPS) operands. */ 890 1.1.1.7 christos switch (*++oparg) 891 1.1.1.7 christos { 892 1.1.1.7 christos case '@': 893 1.1.1.7 christos print (info->stream, dis_style_register, "0x%x", 894 1.1.1.7 christos (unsigned) EXTRACT_OPERAND (MIPS_HINT, l)); 895 1.1.1.7 christos break; 896 1.1.1.7 christos case '#': 897 1.1.1.7 christos print (info->stream, dis_style_register, "0x%x", 898 1.1.1.7 christos (unsigned) EXTRACT_OPERAND (MIPS_IMM9, l)); 899 1.1.1.7 christos break; 900 1.1.1.7 christos case '$': 901 1.1.1.7 christos print (info->stream, dis_style_immediate, "%d", 902 1.1.1.7 christos (unsigned)EXTRACT_MIPS_LDP_IMM (l)); 903 1.1.1.7 christos break; 904 1.1.1.7 christos case '%': 905 1.1.1.7 christos print (info->stream, dis_style_immediate, "%d", 906 1.1.1.7 christos (unsigned)EXTRACT_MIPS_LWP_IMM (l)); 907 1.1.1.7 christos break; 908 1.1.1.7 christos case '^': 909 1.1.1.7 christos print (info->stream, dis_style_immediate, "%d", 910 1.1.1.7 christos (unsigned)EXTRACT_MIPS_SDP_IMM (l)); 911 1.1.1.7 christos break; 912 1.1.1.7 christos case '&': 913 1.1.1.7 christos print (info->stream, dis_style_immediate, "%d", 914 1.1.1.7 christos (unsigned)EXTRACT_MIPS_SWP_IMM (l)); 915 1.1.1.7 christos break; 916 1.1.1.7 christos default: 917 1.1.1.7 christos goto undefined_modifier; 918 1.1.1.7 christos } 919 1.1.1.7 christos break; 920 1.1.1.5 christos default: 921 1.1.1.5 christos goto undefined_modifier; 922 1.1.1.5 christos } 923 1.1.1.4 christos break; 924 1.1.1.5 christos 925 1.1 christos default: 926 1.1.1.4 christos undefined_modifier: 927 1.1 christos /* xgettext:c-format */ 928 1.1.1.4 christos print (info->stream, dis_style_text, 929 1.1.1.4 christos _("# internal error, undefined modifier (%c)"), 930 1.1.1.4 christos *opargStart); 931 1.1 christos return; 932 1.1 christos } 933 1.1 christos } 934 1.1 christos } 935 1.1 christos 936 1.1 christos /* Print the RISC-V instruction at address MEMADDR in debugged memory, 937 1.1 christos on using INFO. Returns length of the instruction, in bytes. 938 1.1 christos BIGENDIAN must be 1 if this is big-endian code, 0 if 939 1.1 christos this is little-endian code. */ 940 1.1 christos 941 1.1 christos static int 942 1.1.1.4 christos riscv_disassemble_insn (bfd_vma memaddr, 943 1.1.1.4 christos insn_t word, 944 1.1.1.4 christos const bfd_byte *packet, 945 1.1.1.4 christos disassemble_info *info) 946 1.1 christos { 947 1.1 christos const struct riscv_opcode *op; 948 1.1.1.4 christos static bool init = false; 949 1.1 christos static const struct riscv_opcode *riscv_hash[OP_MASK_OP + 1]; 950 1.1.1.5 christos struct riscv_private_data *pd = info->private_data; 951 1.1.1.5 christos int insnlen, i; 952 1.1.1.5 christos bool printed; 953 1.1 christos 954 1.1 christos #define OP_HASH_IDX(i) ((i) & (riscv_insn_length (i) == 2 ? 0x3 : OP_MASK_OP)) 955 1.1 christos 956 1.1 christos /* Build a hash table to shorten the search time. */ 957 1.1 christos if (! init) 958 1.1 christos { 959 1.1 christos for (op = riscv_opcodes; op->name; op++) 960 1.1 christos if (!riscv_hash[OP_HASH_IDX (op->match)]) 961 1.1 christos riscv_hash[OP_HASH_IDX (op->match)] = op; 962 1.1 christos 963 1.1.1.4 christos init = true; 964 1.1 christos } 965 1.1 christos 966 1.1 christos insnlen = riscv_insn_length (word); 967 1.1 christos 968 1.1.1.3 christos /* RISC-V instructions are always little-endian. */ 969 1.1.1.3 christos info->endian_code = BFD_ENDIAN_LITTLE; 970 1.1.1.3 christos 971 1.1 christos info->bytes_per_chunk = insnlen % 4 == 0 ? 4 : 2; 972 1.1 christos info->bytes_per_line = 8; 973 1.1.1.3 christos /* We don't support constant pools, so this must be code. */ 974 1.1.1.3 christos info->display_endian = info->endian_code; 975 1.1 christos info->insn_info_valid = 1; 976 1.1 christos info->branch_delay_insns = 0; 977 1.1 christos info->data_size = 0; 978 1.1 christos info->insn_type = dis_nonbranch; 979 1.1 christos info->target = 0; 980 1.1 christos info->target2 = 0; 981 1.1 christos 982 1.1 christos op = riscv_hash[OP_HASH_IDX (word)]; 983 1.1 christos if (op != NULL) 984 1.1 christos { 985 1.1 christos /* If XLEN is not known, get its value from the ELF class. */ 986 1.1.1.7 christos if (pd->xlen != 0) 987 1.1.1.7 christos ; 988 1.1.1.7 christos else if (info->mach == bfd_mach_riscv64) 989 1.1.1.7 christos pd->xlen = 64; 990 1.1 christos else if (info->mach == bfd_mach_riscv32) 991 1.1.1.7 christos pd->xlen = 32; 992 1.1 christos else if (info->section != NULL) 993 1.1 christos { 994 1.1 christos Elf_Internal_Ehdr *ehdr = elf_elfheader (info->section->owner); 995 1.1.1.7 christos pd->xlen = ehdr->e_ident[EI_CLASS] == ELFCLASS64 ? 64 : 32; 996 1.1 christos } 997 1.1 christos 998 1.1.1.4 christos /* If arch has the Zfinx extension, replace FPR with GPR. */ 999 1.1.1.7 christos if (riscv_subset_supports (&pd->riscv_rps_dis, "zfinx")) 1000 1.1.1.7 christos pd->riscv_fpr_names = pd->riscv_gpr_names; 1001 1.1.1.4 christos else 1002 1.1.1.7 christos pd->riscv_fpr_names = pd->riscv_gpr_names == riscv_gpr_names_abi ? 1003 1.1.1.7 christos riscv_fpr_names_abi : riscv_fpr_names_numeric; 1004 1.1.1.4 christos 1005 1.1 christos for (; op->name; op++) 1006 1.1 christos { 1007 1.1.1.5 christos /* Ignore macro insns. */ 1008 1.1.1.5 christos if (op->pinfo == INSN_MACRO) 1009 1.1.1.5 christos continue; 1010 1.1 christos /* Does the opcode match? */ 1011 1.1 christos if (! (op->match_func) (op, word)) 1012 1.1 christos continue; 1013 1.1 christos /* Is this a pseudo-instruction and may we print it as such? */ 1014 1.1.1.7 christos if (pd->no_aliases && (op->pinfo & INSN_ALIAS)) 1015 1.1 christos continue; 1016 1.1 christos /* Is this instruction restricted to a certain value of XLEN? */ 1017 1.1.1.7 christos if ((op->xlen_requirement != 0) 1018 1.1.1.7 christos && (op->xlen_requirement != pd->xlen)) 1019 1.1 christos continue; 1020 1.1.1.4 christos /* Is this instruction supported by the current architecture? */ 1021 1.1.1.7 christos if (!pd->all_ext 1022 1.1.1.7 christos && !riscv_multi_subset_supports (&pd->riscv_rps_dis, 1023 1.1.1.7 christos op->insn_class)) 1024 1.1.1.4 christos continue; 1025 1.1 christos 1026 1.1 christos /* It's a match. */ 1027 1.1.1.4 christos (*info->fprintf_styled_func) (info->stream, dis_style_mnemonic, 1028 1.1.1.4 christos "%s", op->name); 1029 1.1 christos print_insn_args (op->args, word, memaddr, info); 1030 1.1 christos 1031 1.1 christos /* Try to disassemble multi-instruction addressing sequences. */ 1032 1.1.1.4 christos if (pd->to_print_addr) 1033 1.1 christos { 1034 1.1 christos info->target = pd->print_addr; 1035 1.1.1.4 christos (*info->fprintf_styled_func) 1036 1.1.1.4 christos (info->stream, dis_style_comment_start, " # "); 1037 1.1 christos (*info->print_address_func) (info->target, info); 1038 1.1.1.4 christos pd->to_print_addr = false; 1039 1.1 christos } 1040 1.1 christos 1041 1.1.1.2 christos /* Finish filling out insn_info fields. */ 1042 1.1.1.2 christos switch (op->pinfo & INSN_TYPE) 1043 1.1.1.2 christos { 1044 1.1.1.2 christos case INSN_BRANCH: 1045 1.1.1.2 christos info->insn_type = dis_branch; 1046 1.1.1.2 christos break; 1047 1.1.1.2 christos case INSN_CONDBRANCH: 1048 1.1.1.2 christos info->insn_type = dis_condbranch; 1049 1.1.1.2 christos break; 1050 1.1.1.2 christos case INSN_JSR: 1051 1.1.1.2 christos info->insn_type = dis_jsr; 1052 1.1.1.2 christos break; 1053 1.1.1.2 christos case INSN_DREF: 1054 1.1.1.2 christos info->insn_type = dis_dref; 1055 1.1.1.2 christos break; 1056 1.1.1.2 christos default: 1057 1.1.1.2 christos break; 1058 1.1.1.2 christos } 1059 1.1.1.2 christos 1060 1.1.1.2 christos if (op->pinfo & INSN_DATA_SIZE) 1061 1.1.1.2 christos { 1062 1.1.1.2 christos int size = ((op->pinfo & INSN_DATA_SIZE) 1063 1.1.1.2 christos >> INSN_DATA_SIZE_SHIFT); 1064 1.1.1.2 christos info->data_size = 1 << (size - 1); 1065 1.1.1.2 christos } 1066 1.1.1.2 christos 1067 1.1 christos return insnlen; 1068 1.1 christos } 1069 1.1 christos } 1070 1.1 christos 1071 1.1.1.5 christos /* We did not find a match, so just print the instruction bits in 1072 1.1.1.5 christos the shape of an assembler .insn directive. */ 1073 1.1 christos info->insn_type = dis_noninsn; 1074 1.1.1.5 christos (*info->fprintf_styled_func) 1075 1.1.1.5 christos (info->stream, dis_style_assembler_directive, ".insn"); 1076 1.1.1.5 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t"); 1077 1.1.1.5 christos (*info->fprintf_styled_func) (info->stream, dis_style_immediate, 1078 1.1.1.5 christos "%d", insnlen); 1079 1.1.1.5 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, ", "); 1080 1.1.1.5 christos (*info->fprintf_styled_func) (info->stream, dis_style_immediate, "0x"); 1081 1.1.1.5 christos for (i = insnlen, printed = false; i >= 2; ) 1082 1.1.1.5 christos { 1083 1.1.1.5 christos i -= 2; 1084 1.1.1.5 christos word = bfd_get_bits (packet + i, 16, false); 1085 1.1.1.6 christos if (!word && !printed && i) 1086 1.1.1.5 christos continue; 1087 1.1.1.5 christos 1088 1.1.1.4 christos (*info->fprintf_styled_func) (info->stream, dis_style_immediate, 1089 1.1.1.5 christos "%04x", (unsigned int) word); 1090 1.1.1.5 christos printed = true; 1091 1.1.1.4 christos } 1092 1.1.1.5 christos 1093 1.1 christos return insnlen; 1094 1.1 christos } 1095 1.1 christos 1096 1.1.1.7 christos /* Decide if we need to parse the architecture string again, also record the 1097 1.1.1.7 christos string into the current subset list. */ 1098 1.1.1.7 christos 1099 1.1.1.7 christos static void 1100 1.1.1.7 christos riscv_dis_parse_subset (struct disassemble_info *info, const char *arch_new) 1101 1.1.1.7 christos { 1102 1.1.1.7 christos struct riscv_private_data *pd = info->private_data; 1103 1.1.1.7 christos const char *arch_subset_list = pd->riscv_rps_dis.subset_list->arch_str; 1104 1.1.1.7 christos if (arch_subset_list == NULL || strcmp (arch_subset_list, arch_new) != 0) 1105 1.1.1.7 christos { 1106 1.1.1.7 christos riscv_release_subset_list (pd->riscv_rps_dis.subset_list); 1107 1.1.1.7 christos riscv_parse_subset (&pd->riscv_rps_dis, arch_new); 1108 1.1.1.7 christos riscv_arch_str (pd->xlen, pd->riscv_rps_dis.subset_list, 1109 1.1.1.7 christos true/* update */); 1110 1.1.1.7 christos } 1111 1.1.1.7 christos } 1112 1.1.1.7 christos 1113 1.1.1.5 christos /* If we find the suitable mapping symbol update the STATE. 1114 1.1.1.5 christos Otherwise, do nothing. */ 1115 1.1.1.4 christos 1116 1.1.1.5 christos static void 1117 1.1.1.5 christos riscv_update_map_state (int n, 1118 1.1.1.5 christos enum riscv_seg_mstate *state, 1119 1.1.1.5 christos struct disassemble_info *info) 1120 1.1.1.4 christos { 1121 1.1.1.7 christos struct riscv_private_data *pd = info->private_data; 1122 1.1.1.4 christos const char *name; 1123 1.1.1.4 christos 1124 1.1.1.4 christos /* If the symbol is in a different section, ignore it. */ 1125 1.1.1.4 christos if (info->section != NULL 1126 1.1.1.4 christos && info->section != info->symtab[n]->section) 1127 1.1.1.5 christos return; 1128 1.1.1.4 christos 1129 1.1.1.4 christos name = bfd_asymbol_name(info->symtab[n]); 1130 1.1.1.7 christos if (strcmp (name, "$d") == 0) 1131 1.1.1.4 christos *state = MAP_DATA; 1132 1.1.1.7 christos else if (strcmp (name, "$x") == 0) 1133 1.1.1.7 christos { 1134 1.1.1.7 christos *state = MAP_INSN; 1135 1.1.1.7 christos riscv_dis_parse_subset (info, pd->default_arch); 1136 1.1.1.7 christos } 1137 1.1.1.4 christos else if (strncmp (name, "$xrv", 4) == 0) 1138 1.1.1.4 christos { 1139 1.1.1.4 christos *state = MAP_INSN; 1140 1.1.1.5 christos 1141 1.1.1.5 christos /* ISA mapping string may be numbered, suffixed with '.n'. Do not 1142 1.1.1.5 christos consider this as part of the ISA string. */ 1143 1.1.1.5 christos char *suffix = strchr (name, '.'); 1144 1.1.1.5 christos if (suffix) 1145 1.1.1.5 christos { 1146 1.1.1.5 christos int suffix_index = (int)(suffix - name); 1147 1.1.1.5 christos char *name_substr = xmalloc (suffix_index + 1); 1148 1.1.1.5 christos strncpy (name_substr, name, suffix_index); 1149 1.1.1.5 christos name_substr[suffix_index] = '\0'; 1150 1.1.1.7 christos riscv_dis_parse_subset (info, name_substr + 2); 1151 1.1.1.5 christos free (name_substr); 1152 1.1.1.5 christos } 1153 1.1.1.5 christos else 1154 1.1.1.7 christos riscv_dis_parse_subset (info, name + 2); 1155 1.1.1.4 christos } 1156 1.1.1.5 christos } 1157 1.1.1.5 christos 1158 1.1.1.5 christos /* Return true if we find the suitable mapping symbol. 1159 1.1.1.5 christos Otherwise, return false. */ 1160 1.1.1.5 christos 1161 1.1.1.5 christos static bool 1162 1.1.1.5 christos riscv_is_valid_mapping_symbol (int n, 1163 1.1.1.5 christos struct disassemble_info *info) 1164 1.1.1.5 christos { 1165 1.1.1.5 christos const char *name; 1166 1.1.1.5 christos 1167 1.1.1.5 christos /* If the symbol is in a different section, ignore it. */ 1168 1.1.1.5 christos if (info->section != NULL 1169 1.1.1.5 christos && info->section != info->symtab[n]->section) 1170 1.1.1.4 christos return false; 1171 1.1.1.4 christos 1172 1.1.1.5 christos name = bfd_asymbol_name(info->symtab[n]); 1173 1.1.1.5 christos return riscv_elf_is_mapping_symbols (name); 1174 1.1.1.4 christos } 1175 1.1.1.4 christos 1176 1.1.1.4 christos /* Check the sorted symbol table (sorted by the symbol value), find the 1177 1.1.1.4 christos suitable mapping symbols. */ 1178 1.1.1.4 christos 1179 1.1.1.4 christos static enum riscv_seg_mstate 1180 1.1.1.4 christos riscv_search_mapping_symbol (bfd_vma memaddr, 1181 1.1.1.4 christos struct disassemble_info *info) 1182 1.1.1.4 christos { 1183 1.1.1.7 christos struct riscv_private_data *pd = info->private_data; 1184 1.1.1.4 christos enum riscv_seg_mstate mstate; 1185 1.1.1.4 christos bool from_last_map_symbol; 1186 1.1.1.4 christos bool found = false; 1187 1.1.1.4 christos int symbol = -1; 1188 1.1.1.4 christos int n; 1189 1.1.1.4 christos 1190 1.1.1.5 christos /* Return the last map state if the address is still within the range of the 1191 1.1.1.5 christos last mapping symbol. */ 1192 1.1.1.7 christos if (pd->last_map_section == info->section 1193 1.1.1.7 christos && (memaddr < pd->last_map_symbol_boundary)) 1194 1.1.1.7 christos return pd->last_map_state; 1195 1.1.1.5 christos 1196 1.1.1.7 christos pd->last_map_section = info->section; 1197 1.1.1.5 christos 1198 1.1.1.4 christos /* Decide whether to print the data or instruction by default, in case 1199 1.1.1.4 christos we can not find the corresponding mapping symbols. */ 1200 1.1.1.4 christos mstate = MAP_DATA; 1201 1.1.1.4 christos if ((info->section 1202 1.1.1.4 christos && info->section->flags & SEC_CODE) 1203 1.1.1.4 christos || !info->section) 1204 1.1.1.4 christos mstate = MAP_INSN; 1205 1.1.1.4 christos 1206 1.1.1.4 christos if (info->symtab_size == 0 1207 1.1.1.4 christos || bfd_asymbol_flavour (*info->symtab) != bfd_target_elf_flavour) 1208 1.1.1.4 christos return mstate; 1209 1.1.1.4 christos 1210 1.1.1.4 christos /* Reset the last_map_symbol if we start to dump a new section. */ 1211 1.1.1.4 christos if (memaddr <= 0) 1212 1.1.1.7 christos pd->last_map_symbol = -1; 1213 1.1.1.4 christos 1214 1.1.1.4 christos /* If the last stop offset is different from the current one, then 1215 1.1.1.4 christos don't use the last_map_symbol to search. We usually reset the 1216 1.1.1.4 christos info->stop_offset when handling a new section. */ 1217 1.1.1.7 christos from_last_map_symbol = (pd->last_map_symbol >= 0 1218 1.1.1.7 christos && info->stop_offset == pd->last_stop_offset); 1219 1.1.1.4 christos 1220 1.1.1.5 christos /* Start scanning from wherever we finished last time, or the start 1221 1.1.1.5 christos of the function. */ 1222 1.1.1.7 christos n = from_last_map_symbol ? pd->last_map_symbol : info->symtab_pos + 1; 1223 1.1.1.4 christos 1224 1.1.1.4 christos /* Find the suitable mapping symbol to dump. */ 1225 1.1.1.4 christos for (; n < info->symtab_size; n++) 1226 1.1.1.4 christos { 1227 1.1.1.4 christos bfd_vma addr = bfd_asymbol_value (info->symtab[n]); 1228 1.1.1.4 christos /* We have searched all possible symbols in the range. */ 1229 1.1.1.4 christos if (addr > memaddr) 1230 1.1.1.4 christos break; 1231 1.1.1.5 christos if (riscv_is_valid_mapping_symbol (n, info)) 1232 1.1.1.4 christos { 1233 1.1.1.4 christos symbol = n; 1234 1.1.1.4 christos found = true; 1235 1.1.1.4 christos /* Do not stop searching, in case there are some mapping 1236 1.1.1.4 christos symbols have the same value, but have different names. 1237 1.1.1.4 christos Use the last one. */ 1238 1.1.1.4 christos } 1239 1.1.1.4 christos } 1240 1.1.1.4 christos 1241 1.1.1.4 christos /* We can not find the suitable mapping symbol above. Therefore, we 1242 1.1.1.5 christos look forwards and try to find it again, but don't go past the start 1243 1.1.1.4 christos of the section. Otherwise a data section without mapping symbols 1244 1.1.1.4 christos can pick up a text mapping symbol of a preceeding section. */ 1245 1.1.1.4 christos if (!found) 1246 1.1.1.4 christos { 1247 1.1.1.7 christos n = from_last_map_symbol ? pd->last_map_symbol : info->symtab_pos; 1248 1.1.1.4 christos 1249 1.1.1.4 christos for (; n >= 0; n--) 1250 1.1.1.4 christos { 1251 1.1.1.4 christos bfd_vma addr = bfd_asymbol_value (info->symtab[n]); 1252 1.1.1.4 christos /* We have searched all possible symbols in the range. */ 1253 1.1.1.4 christos if (addr < (info->section ? info->section->vma : 0)) 1254 1.1.1.4 christos break; 1255 1.1.1.4 christos /* Stop searching once we find the closed mapping symbol. */ 1256 1.1.1.5 christos if (riscv_is_valid_mapping_symbol (n, info)) 1257 1.1.1.4 christos { 1258 1.1.1.4 christos symbol = n; 1259 1.1.1.4 christos found = true; 1260 1.1.1.4 christos break; 1261 1.1.1.4 christos } 1262 1.1.1.4 christos } 1263 1.1.1.4 christos } 1264 1.1.1.4 christos 1265 1.1.1.5 christos if (found) 1266 1.1.1.5 christos { 1267 1.1.1.5 christos riscv_update_map_state (symbol, &mstate, info); 1268 1.1.1.5 christos 1269 1.1.1.5 christos /* Find the next mapping symbol to determine the boundary of this mapping 1270 1.1.1.5 christos symbol. */ 1271 1.1.1.5 christos 1272 1.1.1.5 christos bool found_next = false; 1273 1.1.1.5 christos /* Try to found next mapping symbol. */ 1274 1.1.1.5 christos for (n = symbol + 1; n < info->symtab_size; n++) 1275 1.1.1.5 christos { 1276 1.1.1.5 christos if (info->symtab[symbol]->section != info->symtab[n]->section) 1277 1.1.1.5 christos continue; 1278 1.1.1.5 christos 1279 1.1.1.5 christos bfd_vma addr = bfd_asymbol_value (info->symtab[n]); 1280 1.1.1.5 christos const char *sym_name = bfd_asymbol_name(info->symtab[n]); 1281 1.1.1.5 christos if (sym_name[0] == '$' && (sym_name[1] == 'x' || sym_name[1] == 'd')) 1282 1.1.1.5 christos { 1283 1.1.1.5 christos /* The next mapping symbol has been found, and it represents the 1284 1.1.1.5 christos boundary of this mapping symbol. */ 1285 1.1.1.5 christos found_next = true; 1286 1.1.1.7 christos pd->last_map_symbol_boundary = addr; 1287 1.1.1.5 christos break; 1288 1.1.1.5 christos } 1289 1.1.1.5 christos } 1290 1.1.1.5 christos 1291 1.1.1.5 christos /* No further mapping symbol has been found, indicating that the boundary 1292 1.1.1.5 christos of the current mapping symbol is the end of this section. */ 1293 1.1.1.5 christos if (!found_next) 1294 1.1.1.7 christos pd->last_map_symbol_boundary = info->section->vma 1295 1.1.1.7 christos + info->section->size; 1296 1.1.1.5 christos } 1297 1.1.1.5 christos 1298 1.1.1.4 christos /* Save the information for next use. */ 1299 1.1.1.7 christos pd->last_map_symbol = symbol; 1300 1.1.1.7 christos pd->last_stop_offset = info->stop_offset; 1301 1.1.1.4 christos 1302 1.1.1.4 christos return mstate; 1303 1.1.1.4 christos } 1304 1.1.1.4 christos 1305 1.1.1.4 christos /* Decide which data size we should print. */ 1306 1.1.1.4 christos 1307 1.1.1.4 christos static bfd_vma 1308 1.1.1.4 christos riscv_data_length (bfd_vma memaddr, 1309 1.1.1.4 christos disassemble_info *info) 1310 1.1.1.4 christos { 1311 1.1.1.7 christos struct riscv_private_data *pd = info->private_data; 1312 1.1.1.4 christos bfd_vma length; 1313 1.1.1.4 christos bool found = false; 1314 1.1.1.4 christos 1315 1.1.1.4 christos length = 4; 1316 1.1.1.4 christos if (info->symtab_size != 0 1317 1.1.1.4 christos && bfd_asymbol_flavour (*info->symtab) == bfd_target_elf_flavour 1318 1.1.1.7 christos && pd->last_map_symbol >= 0) 1319 1.1.1.4 christos { 1320 1.1.1.4 christos int n; 1321 1.1.1.4 christos enum riscv_seg_mstate m = MAP_NONE; 1322 1.1.1.7 christos for (n = pd->last_map_symbol + 1; n < info->symtab_size; n++) 1323 1.1.1.4 christos { 1324 1.1.1.4 christos bfd_vma addr = bfd_asymbol_value (info->symtab[n]); 1325 1.1.1.4 christos if (addr > memaddr 1326 1.1.1.5 christos && riscv_is_valid_mapping_symbol (n, info)) 1327 1.1.1.4 christos { 1328 1.1.1.4 christos if (addr - memaddr < length) 1329 1.1.1.4 christos length = addr - memaddr; 1330 1.1.1.4 christos found = true; 1331 1.1.1.5 christos riscv_update_map_state (n, &m, info); 1332 1.1.1.4 christos break; 1333 1.1.1.4 christos } 1334 1.1.1.4 christos } 1335 1.1.1.4 christos } 1336 1.1.1.4 christos if (!found) 1337 1.1.1.4 christos { 1338 1.1.1.4 christos /* Do not set the length which exceeds the section size. */ 1339 1.1.1.4 christos bfd_vma offset = info->section->vma + info->section->size; 1340 1.1.1.4 christos offset -= memaddr; 1341 1.1.1.4 christos length = (offset < length) ? offset : length; 1342 1.1.1.4 christos } 1343 1.1.1.4 christos length = length == 3 ? 2 : length; 1344 1.1.1.4 christos return length; 1345 1.1.1.4 christos } 1346 1.1.1.4 christos 1347 1.1.1.4 christos /* Dump the data contents. */ 1348 1.1.1.4 christos 1349 1.1.1.4 christos static int 1350 1.1.1.4 christos riscv_disassemble_data (bfd_vma memaddr ATTRIBUTE_UNUSED, 1351 1.1.1.4 christos insn_t data, 1352 1.1.1.4 christos const bfd_byte *packet ATTRIBUTE_UNUSED, 1353 1.1.1.4 christos disassemble_info *info) 1354 1.1.1.4 christos { 1355 1.1.1.4 christos info->display_endian = info->endian; 1356 1.1.1.7 christos int i; 1357 1.1.1.4 christos 1358 1.1.1.4 christos switch (info->bytes_per_chunk) 1359 1.1.1.4 christos { 1360 1.1.1.4 christos case 1: 1361 1.1.1.4 christos info->bytes_per_line = 6; 1362 1.1.1.4 christos (*info->fprintf_styled_func) 1363 1.1.1.4 christos (info->stream, dis_style_assembler_directive, ".byte"); 1364 1.1.1.4 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t"); 1365 1.1.1.4 christos (*info->fprintf_styled_func) (info->stream, dis_style_immediate, 1366 1.1.1.4 christos "0x%02x", (unsigned)data); 1367 1.1.1.4 christos break; 1368 1.1.1.4 christos case 2: 1369 1.1.1.4 christos info->bytes_per_line = 8; 1370 1.1.1.4 christos (*info->fprintf_styled_func) 1371 1.1.1.4 christos (info->stream, dis_style_assembler_directive, ".short"); 1372 1.1.1.4 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t"); 1373 1.1.1.4 christos (*info->fprintf_styled_func) 1374 1.1.1.4 christos (info->stream, dis_style_immediate, "0x%04x", (unsigned) data); 1375 1.1.1.4 christos break; 1376 1.1.1.4 christos case 4: 1377 1.1.1.4 christos info->bytes_per_line = 8; 1378 1.1.1.4 christos (*info->fprintf_styled_func) 1379 1.1.1.4 christos (info->stream, dis_style_assembler_directive, ".word"); 1380 1.1.1.4 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t"); 1381 1.1.1.4 christos (*info->fprintf_styled_func) 1382 1.1.1.4 christos (info->stream, dis_style_immediate, "0x%08lx", 1383 1.1.1.4 christos (unsigned long) data); 1384 1.1.1.4 christos break; 1385 1.1.1.4 christos case 8: 1386 1.1.1.4 christos info->bytes_per_line = 8; 1387 1.1.1.4 christos (*info->fprintf_styled_func) 1388 1.1.1.4 christos (info->stream, dis_style_assembler_directive, ".dword"); 1389 1.1.1.4 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t"); 1390 1.1.1.4 christos (*info->fprintf_styled_func) 1391 1.1.1.4 christos (info->stream, dis_style_immediate, "0x%016llx", 1392 1.1.1.4 christos (unsigned long long) data); 1393 1.1.1.4 christos break; 1394 1.1.1.4 christos default: 1395 1.1.1.7 christos /* Arbitrary data so just print the bits in the shape of an .<N>byte 1396 1.1.1.7 christos directive. */ 1397 1.1.1.7 christos info->bytes_per_line = info->bytes_per_chunk; 1398 1.1.1.7 christos (*info->fprintf_styled_func) 1399 1.1.1.7 christos (info->stream, dis_style_assembler_directive, ".%dbyte", info->bytes_per_chunk); 1400 1.1.1.7 christos (*info->fprintf_styled_func) (info->stream, dis_style_text, "\t"); 1401 1.1.1.7 christos (*info->fprintf_styled_func) (info->stream, dis_style_immediate, "0x"); 1402 1.1.1.7 christos for (i = info->bytes_per_line; i > 0;) 1403 1.1.1.7 christos { 1404 1.1.1.7 christos i--; 1405 1.1.1.7 christos data = bfd_get_bits (packet + i, 8, false); 1406 1.1.1.7 christos (*info->fprintf_styled_func) 1407 1.1.1.7 christos (info->stream, dis_style_immediate, "%02x", 1408 1.1.1.7 christos (unsigned) data); 1409 1.1.1.7 christos } 1410 1.1.1.7 christos break; 1411 1.1.1.4 christos } 1412 1.1.1.4 christos return info->bytes_per_chunk; 1413 1.1.1.4 christos } 1414 1.1.1.4 christos 1415 1.1.1.5 christos static bool 1416 1.1.1.5 christos riscv_init_disasm_info (struct disassemble_info *info) 1417 1.1.1.5 christos { 1418 1.1.1.5 christos int i; 1419 1.1.1.5 christos struct riscv_private_data *pd = 1420 1.1.1.5 christos xcalloc (1, sizeof (struct riscv_private_data)); 1421 1.1.1.5 christos pd->gp = 0; 1422 1.1.1.5 christos pd->print_addr = 0; 1423 1.1.1.5 christos for (i = 0; i < (int) ARRAY_SIZE (pd->hi_addr); i++) 1424 1.1.1.5 christos pd->hi_addr[i] = -1; 1425 1.1.1.5 christos pd->to_print_addr = false; 1426 1.1.1.5 christos 1427 1.1.1.7 christos pd->has_gp = false; 1428 1.1.1.5 christos for (i = 0; i < info->symtab_size; i++) 1429 1.1.1.5 christos { 1430 1.1.1.5 christos asymbol *sym = info->symtab[i]; 1431 1.1.1.5 christos if (strcmp (bfd_asymbol_name (sym), RISCV_GP_SYMBOL) == 0) 1432 1.1.1.5 christos { 1433 1.1.1.5 christos pd->gp = bfd_asymbol_value (sym); 1434 1.1.1.5 christos pd->has_gp = true; 1435 1.1.1.5 christos } 1436 1.1.1.5 christos } 1437 1.1.1.5 christos 1438 1.1.1.7 christos pd->xlen = 0; 1439 1.1.1.7 christos pd->default_isa_spec = ISA_SPEC_CLASS_DRAFT - 1; 1440 1.1.1.7 christos pd->default_priv_spec = PRIV_SPEC_CLASS_NONE; 1441 1.1.1.7 christos 1442 1.1.1.7 christos pd->riscv_rps_dis.subset_list = xcalloc (1, sizeof (riscv_parse_subset_t)); 1443 1.1.1.7 christos pd->riscv_rps_dis.error_handler = opcodes_error_handler; 1444 1.1.1.7 christos pd->riscv_rps_dis.xlen = &pd->xlen; 1445 1.1.1.7 christos pd->riscv_rps_dis.isa_spec = &pd->default_isa_spec; 1446 1.1.1.7 christos pd->riscv_rps_dis.check_unknown_prefixed_ext = false; 1447 1.1.1.7 christos pd->default_arch = "rv64gc"; 1448 1.1.1.7 christos if (info->section != NULL) 1449 1.1.1.7 christos { 1450 1.1.1.7 christos bfd *abfd = info->section->owner; 1451 1.1.1.7 christos if (abfd && bfd_get_flavour (abfd) == bfd_target_elf_flavour) 1452 1.1.1.7 christos { 1453 1.1.1.7 christos const char *sec_name = 1454 1.1.1.7 christos get_elf_backend_data (abfd)->obj_attrs_section; 1455 1.1.1.7 christos if (bfd_get_section_by_name (abfd, sec_name) != NULL) 1456 1.1.1.7 christos { 1457 1.1.1.7 christos obj_attribute *attr = elf_known_obj_attributes_proc (abfd); 1458 1.1.1.7 christos unsigned int Tag_a = Tag_RISCV_priv_spec; 1459 1.1.1.7 christos unsigned int Tag_b = Tag_RISCV_priv_spec_minor; 1460 1.1.1.7 christos unsigned int Tag_c = Tag_RISCV_priv_spec_revision; 1461 1.1.1.7 christos riscv_get_priv_spec_class_from_numbers (attr[Tag_a].i, 1462 1.1.1.7 christos attr[Tag_b].i, 1463 1.1.1.7 christos attr[Tag_c].i, 1464 1.1.1.7 christos &pd->default_priv_spec); 1465 1.1.1.7 christos pd->default_arch = attr[Tag_RISCV_arch].s; 1466 1.1.1.7 christos } 1467 1.1.1.7 christos } 1468 1.1.1.7 christos } 1469 1.1.1.7 christos 1470 1.1.1.7 christos pd->last_map_symbol = -1; 1471 1.1.1.7 christos pd->last_stop_offset = 0; 1472 1.1.1.7 christos pd->last_map_symbol_boundary = 0; 1473 1.1.1.7 christos pd->last_map_state = MAP_NONE; 1474 1.1.1.7 christos pd->last_map_section = NULL; 1475 1.1.1.7 christos pd->riscv_gpr_names = NULL; 1476 1.1.1.7 christos pd->riscv_fpr_names = NULL; 1477 1.1.1.7 christos pd->no_aliases = false; 1478 1.1.1.7 christos pd->all_ext = false; 1479 1.1.1.7 christos 1480 1.1.1.5 christos info->private_data = pd; 1481 1.1.1.7 christos riscv_dis_parse_subset (info, pd->default_arch); 1482 1.1.1.5 christos return true; 1483 1.1.1.5 christos } 1484 1.1.1.5 christos 1485 1.1.1.7 christos /* Fetch an instruction. If only a partial instruction is able to be fetched, 1486 1.1.1.7 christos return the number of accessible bytes. */ 1487 1.1.1.7 christos 1488 1.1.1.7 christos static bfd_vma 1489 1.1.1.7 christos fetch_insn (bfd_vma memaddr, 1490 1.1.1.7 christos bfd_byte *packet, 1491 1.1.1.7 christos bfd_vma dump_size, 1492 1.1.1.7 christos struct disassemble_info *info, 1493 1.1.1.7 christos volatile int *status) 1494 1.1.1.7 christos { 1495 1.1.1.7 christos do 1496 1.1.1.7 christos { 1497 1.1.1.7 christos *status = (*info->read_memory_func) (memaddr, packet, dump_size, info); 1498 1.1.1.7 christos } 1499 1.1.1.7 christos while (*status != 0 && dump_size-- > 1); 1500 1.1.1.7 christos 1501 1.1.1.7 christos return dump_size; 1502 1.1.1.7 christos } 1503 1.1.1.7 christos 1504 1.1 christos int 1505 1.1 christos print_insn_riscv (bfd_vma memaddr, struct disassemble_info *info) 1506 1.1 christos { 1507 1.1.1.4 christos bfd_byte packet[RISCV_MAX_INSN_LEN]; 1508 1.1 christos insn_t insn = 0; 1509 1.1.1.7 christos bfd_vma dump_size, bytes_fetched; 1510 1.1 christos int status; 1511 1.1.1.4 christos enum riscv_seg_mstate mstate; 1512 1.1.1.4 christos int (*riscv_disassembler) (bfd_vma, insn_t, const bfd_byte *, 1513 1.1.1.4 christos struct disassemble_info *); 1514 1.1 christos 1515 1.1.1.7 christos if (info->private_data == NULL && !riscv_init_disasm_info (info)) 1516 1.1.1.7 christos return -1; 1517 1.1.1.7 christos 1518 1.1 christos if (info->disassembler_options != NULL) 1519 1.1 christos { 1520 1.1.1.7 christos parse_riscv_dis_options (info->disassembler_options, info); 1521 1.1 christos /* Avoid repeatedly parsing the options. */ 1522 1.1 christos info->disassembler_options = NULL; 1523 1.1 christos } 1524 1.1.1.7 christos else if (((struct riscv_private_data *) info->private_data)->riscv_gpr_names == NULL) 1525 1.1.1.7 christos set_default_riscv_dis_options (info); 1526 1.1.1.5 christos 1527 1.1.1.4 christos mstate = riscv_search_mapping_symbol (memaddr, info); 1528 1.1.1.5 christos /* Save the last mapping state. */ 1529 1.1.1.7 christos ((struct riscv_private_data *) info->private_data)->last_map_state = mstate; 1530 1.1.1.4 christos 1531 1.1.1.4 christos /* Set the size to dump. */ 1532 1.1.1.4 christos if (mstate == MAP_DATA 1533 1.1.1.4 christos && (info->flags & DISASSEMBLE_DATA) == 0) 1534 1.1 christos { 1535 1.1.1.4 christos dump_size = riscv_data_length (memaddr, info); 1536 1.1.1.4 christos info->bytes_per_chunk = dump_size; 1537 1.1.1.4 christos riscv_disassembler = riscv_disassemble_data; 1538 1.1.1.4 christos } 1539 1.1.1.4 christos else 1540 1.1.1.4 christos { 1541 1.1.1.4 christos /* Get the first 2-bytes to check the lenghth of instruction. */ 1542 1.1.1.7 christos bytes_fetched = fetch_insn (memaddr, packet, 2, info, &status); 1543 1.1 christos if (status != 0) 1544 1.1 christos { 1545 1.1 christos (*info->memory_error_func) (status, memaddr, info); 1546 1.1.1.5 christos return -1; 1547 1.1 christos } 1548 1.1.1.7 christos else if (bytes_fetched != 2) 1549 1.1.1.7 christos { 1550 1.1.1.7 christos /* Only the first byte was able to be read. Dump the partial 1551 1.1.1.7 christos instruction. */ 1552 1.1.1.7 christos dump_size = bytes_fetched; 1553 1.1.1.7 christos info->bytes_per_chunk = dump_size; 1554 1.1.1.7 christos riscv_disassembler = riscv_disassemble_data; 1555 1.1.1.7 christos goto print; 1556 1.1.1.7 christos } 1557 1.1.1.4 christos insn = (insn_t) bfd_getl16 (packet); 1558 1.1.1.4 christos dump_size = riscv_insn_length (insn); 1559 1.1.1.4 christos riscv_disassembler = riscv_disassemble_insn; 1560 1.1.1.4 christos } 1561 1.1.1.4 christos 1562 1.1.1.7 christos bytes_fetched = fetch_insn (memaddr, packet, dump_size, info, &status); 1563 1.1.1.7 christos 1564 1.1.1.4 christos if (status != 0) 1565 1.1.1.4 christos { 1566 1.1.1.4 christos (*info->memory_error_func) (status, memaddr, info); 1567 1.1.1.5 christos return -1; 1568 1.1.1.4 christos } 1569 1.1.1.7 christos else if (bytes_fetched != dump_size) 1570 1.1.1.4 christos { 1571 1.1.1.7 christos dump_size = bytes_fetched; 1572 1.1.1.7 christos info->bytes_per_chunk = dump_size; 1573 1.1.1.7 christos riscv_disassembler = riscv_disassemble_data; 1574 1.1 christos } 1575 1.1 christos 1576 1.1.1.7 christos print: 1577 1.1.1.7 christos 1578 1.1.1.7 christos insn = (insn_t) bfd_get_bits (packet, dump_size * 8, false); 1579 1.1.1.7 christos 1580 1.1.1.7 christos return (*riscv_disassembler) (memaddr, insn, packet, info); 1581 1.1 christos } 1582 1.1 christos 1583 1.1.1.2 christos /* Prevent use of the fake labels that are generated as part of the DWARF 1584 1.1.1.2 christos and for relaxable relocations in the assembler. */ 1585 1.1.1.2 christos 1586 1.1.1.4 christos bool 1587 1.1.1.2 christos riscv_symbol_is_valid (asymbol * sym, 1588 1.1.1.2 christos struct disassemble_info * info ATTRIBUTE_UNUSED) 1589 1.1.1.2 christos { 1590 1.1.1.2 christos const char * name; 1591 1.1.1.2 christos 1592 1.1.1.2 christos if (sym == NULL) 1593 1.1.1.4 christos return false; 1594 1.1.1.2 christos 1595 1.1.1.2 christos name = bfd_asymbol_name (sym); 1596 1.1.1.2 christos 1597 1.1.1.4 christos return (strcmp (name, RISCV_FAKE_LABEL_NAME) != 0 1598 1.1.1.4 christos && !riscv_elf_is_mapping_symbols (name)); 1599 1.1.1.4 christos } 1600 1.1.1.4 christos 1601 1.1.1.4 christos 1603 1.1.1.4 christos /* Indices into option argument vector for options accepting an argument. 1604 1.1.1.4 christos Use RISCV_OPTION_ARG_NONE for options accepting no argument. */ 1605 1.1.1.4 christos 1606 1.1.1.4 christos typedef enum 1607 1.1.1.4 christos { 1608 1.1.1.4 christos RISCV_OPTION_ARG_NONE = -1, 1609 1.1.1.4 christos RISCV_OPTION_ARG_PRIV_SPEC, 1610 1.1.1.4 christos 1611 1.1.1.4 christos RISCV_OPTION_ARG_COUNT 1612 1.1.1.4 christos } riscv_option_arg_t; 1613 1.1.1.4 christos 1614 1.1.1.4 christos /* Valid RISCV disassembler options. */ 1615 1.1.1.7 christos 1616 1.1.1.4 christos static const struct 1617 1.1.1.4 christos { 1618 1.1.1.4 christos const char *name; 1619 1.1.1.4 christos const char *description; 1620 1.1.1.4 christos riscv_option_arg_t arg; 1621 1.1.1.4 christos } riscv_options[] = 1622 1.1.1.7 christos { 1623 1.1.1.7 christos { "max", 1624 1.1.1.7 christos N_("Disassemble without checking architecture string."), 1625 1.1.1.4 christos RISCV_OPTION_ARG_NONE }, 1626 1.1.1.4 christos { "numeric", 1627 1.1.1.4 christos N_("Print numeric register names, rather than ABI names."), 1628 1.1.1.4 christos RISCV_OPTION_ARG_NONE }, 1629 1.1.1.4 christos { "no-aliases", 1630 1.1.1.4 christos N_("Disassemble only into canonical instructions."), 1631 1.1.1.4 christos RISCV_OPTION_ARG_NONE }, 1632 1.1.1.4 christos { "priv-spec=", 1633 1.1.1.4 christos N_("Print the CSR according to the chosen privilege spec."), 1634 1.1.1.4 christos RISCV_OPTION_ARG_PRIV_SPEC } 1635 1.1.1.4 christos }; 1636 1.1.1.4 christos 1637 1.1.1.4 christos /* Build the structure representing valid RISCV disassembler options. 1638 1.1.1.4 christos This is done dynamically for maintenance ease purpose; a static 1639 1.1.1.4 christos initializer would be unreadable. */ 1640 1.1.1.4 christos 1641 1.1.1.4 christos const disasm_options_and_args_t * 1642 1.1.1.4 christos disassembler_options_riscv (void) 1643 1.1.1.4 christos { 1644 1.1.1.4 christos static disasm_options_and_args_t *opts_and_args; 1645 1.1.1.4 christos 1646 1.1.1.4 christos if (opts_and_args == NULL) 1647 1.1.1.4 christos { 1648 1.1.1.4 christos size_t num_options = ARRAY_SIZE (riscv_options); 1649 1.1.1.4 christos size_t num_args = RISCV_OPTION_ARG_COUNT; 1650 1.1.1.4 christos disasm_option_arg_t *args; 1651 1.1.1.4 christos disasm_options_t *opts; 1652 1.1.1.4 christos size_t i, priv_spec_count; 1653 1.1.1.4 christos 1654 1.1.1.4 christos args = XNEWVEC (disasm_option_arg_t, num_args + 1); 1655 1.1.1.4 christos 1656 1.1.1.7 christos args[RISCV_OPTION_ARG_PRIV_SPEC].name = "SPEC"; 1657 1.1.1.4 christos priv_spec_count = PRIV_SPEC_CLASS_DRAFT - PRIV_SPEC_EARLIEST; 1658 1.1.1.4 christos args[RISCV_OPTION_ARG_PRIV_SPEC].values 1659 1.1.1.4 christos = XNEWVEC (const char *, priv_spec_count + 1); 1660 1.1.1.4 christos for (i = 0; i < priv_spec_count; i++) 1661 1.1.1.7 christos args[RISCV_OPTION_ARG_PRIV_SPEC].values[i] 1662 1.1.1.4 christos = riscv_priv_specs[PRIV_SPEC_EARLIEST - PRIV_SPEC_CLASS_NONE - 1 + i].name; 1663 1.1.1.4 christos /* The array we return must be NULL terminated. */ 1664 1.1.1.4 christos args[RISCV_OPTION_ARG_PRIV_SPEC].values[i] = NULL; 1665 1.1.1.4 christos 1666 1.1.1.4 christos /* The array we return must be NULL terminated. */ 1667 1.1.1.4 christos args[num_args].name = NULL; 1668 1.1.1.4 christos args[num_args].values = NULL; 1669 1.1.1.4 christos 1670 1.1.1.4 christos opts_and_args = XNEW (disasm_options_and_args_t); 1671 1.1.1.4 christos opts_and_args->args = args; 1672 1.1.1.4 christos 1673 1.1.1.4 christos opts = &opts_and_args->options; 1674 1.1.1.4 christos opts->name = XNEWVEC (const char *, num_options + 1); 1675 1.1.1.4 christos opts->description = XNEWVEC (const char *, num_options + 1); 1676 1.1.1.4 christos opts->arg = XNEWVEC (const disasm_option_arg_t *, num_options + 1); 1677 1.1.1.4 christos for (i = 0; i < num_options; i++) 1678 1.1.1.4 christos { 1679 1.1.1.4 christos opts->name[i] = riscv_options[i].name; 1680 1.1.1.4 christos opts->description[i] = _(riscv_options[i].description); 1681 1.1.1.4 christos if (riscv_options[i].arg != RISCV_OPTION_ARG_NONE) 1682 1.1.1.4 christos opts->arg[i] = &args[riscv_options[i].arg]; 1683 1.1.1.4 christos else 1684 1.1.1.4 christos opts->arg[i] = NULL; 1685 1.1.1.4 christos } 1686 1.1.1.4 christos /* The array we return must be NULL terminated. */ 1687 1.1.1.4 christos opts->name[i] = NULL; 1688 1.1.1.4 christos opts->description[i] = NULL; 1689 1.1.1.4 christos opts->arg[i] = NULL; 1690 1.1.1.4 christos } 1691 1.1.1.4 christos 1692 1.1.1.2 christos return opts_and_args; 1693 1.1.1.2 christos } 1694 1.1 christos 1695 1.1 christos void 1696 1.1 christos print_riscv_disassembler_options (FILE *stream) 1697 1.1.1.4 christos { 1698 1.1.1.4 christos const disasm_options_and_args_t *opts_and_args; 1699 1.1.1.4 christos const disasm_option_arg_t *args; 1700 1.1.1.4 christos const disasm_options_t *opts; 1701 1.1.1.4 christos size_t max_len = 0; 1702 1.1.1.4 christos size_t i; 1703 1.1.1.4 christos size_t j; 1704 1.1.1.4 christos 1705 1.1.1.4 christos opts_and_args = disassembler_options_riscv (); 1706 1.1.1.4 christos opts = &opts_and_args->options; 1707 1.1.1.4 christos args = opts_and_args->args; 1708 1.1 christos 1709 1.1.1.4 christos fprintf (stream, _("\n\ 1710 1.1 christos The following RISC-V specific disassembler options are supported for use\n\ 1711 1.1.1.4 christos with the -M switch (multiple options should be separated by commas):\n")); 1712 1.1 christos fprintf (stream, "\n"); 1713 1.1.1.4 christos 1714 1.1.1.4 christos /* Compute the length of the longest option name. */ 1715 1.1.1.4 christos for (i = 0; opts->name[i] != NULL; i++) 1716 1.1.1.4 christos { 1717 1.1.1.3 christos size_t len = strlen (opts->name[i]); 1718 1.1.1.4 christos 1719 1.1.1.4 christos if (opts->arg[i] != NULL) 1720 1.1.1.4 christos len += strlen (opts->arg[i]->name); 1721 1.1.1.4 christos if (max_len < len) 1722 1.1.1.4 christos max_len = len; 1723 1.1 christos } 1724 1.1.1.4 christos 1725 1.1.1.4 christos for (i = 0, max_len++; opts->name[i] != NULL; i++) 1726 1.1.1.4 christos { 1727 1.1.1.4 christos fprintf (stream, " %s", opts->name[i]); 1728 1.1.1.4 christos if (opts->arg[i] != NULL) 1729 1.1.1.4 christos fprintf (stream, "%s", opts->arg[i]->name); 1730 1.1.1.4 christos if (opts->description[i] != NULL) 1731 1.1.1.4 christos { 1732 1.1.1.4 christos size_t len = strlen (opts->name[i]); 1733 1.1.1.4 christos 1734 1.1.1.4 christos if (opts->arg != NULL && opts->arg[i] != NULL) 1735 1.1.1.4 christos len += strlen (opts->arg[i]->name); 1736 1.1.1.4 christos fprintf (stream, "%*c %s", (int) (max_len - len), ' ', 1737 1.1.1.4 christos opts->description[i]); 1738 1.1.1.4 christos } 1739 1.1.1.4 christos fprintf (stream, "\n"); 1740 1.1.1.4 christos } 1741 1.1.1.4 christos 1742 1.1.1.4 christos for (i = 0; args[i].name != NULL; i++) 1743 1.1.1.4 christos { 1744 1.1.1.4 christos if (args[i].values == NULL) 1745 1.1.1.4 christos continue; 1746 1.1.1.4 christos fprintf (stream, _("\n\ 1747 1.1.1.4 christos For the options above, the following values are supported for \"%s\":\n "), 1748 1.1.1.4 christos args[i].name); 1749 1.1.1.4 christos for (j = 0; args[i].values[j] != NULL; j++) 1750 1.1.1.4 christos fprintf (stream, " %s", args[i].values[j]); 1751 1.1.1.4 christos fprintf (stream, _("\n")); 1752 1.1 christos } 1753 1.1 christos 1754 1.1 christos fprintf (stream, _("\n")); 1755 1.1.1.5 christos } 1756 1.1.1.5 christos 1757 1.1.1.5 christos void disassemble_free_riscv (struct disassemble_info *info ATTRIBUTE_UNUSED) 1758 1.1.1.7 christos { 1759 1.1.1.7 christos struct riscv_private_data *pd = info->private_data; 1760 1.1.1.7 christos if (pd) 1761 1.1.1.7 christos { 1762 1.1.1.7 christos riscv_release_subset_list (pd->riscv_rps_dis.subset_list); 1763 1.1.1.7 christos free (pd->riscv_rps_dis.subset_list); 1764 1.1.1.5 christos } 1765 } 1766