1/* RISC-V-specific support for ELF. 2 Copyright (C) 2011-2022 Free Software Foundation, Inc. 3 4 Contributed by Andrew Waterman (andrew@sifive.com). 5 Based on TILE-Gx and MIPS targets. 6 7 This file is part of BFD, the Binary File Descriptor library. 8 9 This program is free software; you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation; either version 3 of the License, or 12 (at your option) any later version. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program; see the file COPYING3. If not, 21 see <http://www.gnu.org/licenses/>. */ 22 23#include "sysdep.h" 24#include "bfd.h" 25#include "libbfd.h" 26#include "elf-bfd.h" 27#include "elf/riscv.h" 28#include "opcode/riscv.h" 29#include "libiberty.h" 30#include "elfxx-riscv.h" 31#include "safe-ctype.h" 32 33#define MINUS_ONE ((bfd_vma)0 - 1) 34 35/* Special handler for ADD/SUB relocations that allows them to be filled out 36 both in the pre-linked and post-linked file. This is necessary to make 37 pre-linked debug info work, as due to linker relaxations we need to emit 38 relocations for the debug info. */ 39static bfd_reloc_status_type riscv_elf_add_sub_reloc 40 (bfd *, arelent *, asymbol *, void *, asection *, bfd *, char **); 41 42/* The relocation table used for SHT_RELA sections. */ 43 44static reloc_howto_type howto_table[] = 45{ 46 /* No relocation. */ 47 HOWTO (R_RISCV_NONE, /* type */ 48 0, /* rightshift */ 49 0, /* size */ 50 0, /* bitsize */ 51 false, /* pc_relative */ 52 0, /* bitpos */ 53 complain_overflow_dont, /* complain_on_overflow */ 54 bfd_elf_generic_reloc, /* special_function */ 55 "R_RISCV_NONE", /* name */ 56 false, /* partial_inplace */ 57 0, /* src_mask */ 58 0, /* dst_mask */ 59 false), /* pcrel_offset */ 60 61 /* 32 bit relocation. */ 62 HOWTO (R_RISCV_32, /* type */ 63 0, /* rightshift */ 64 4, /* size */ 65 32, /* bitsize */ 66 false, /* pc_relative */ 67 0, /* bitpos */ 68 complain_overflow_dont, /* complain_on_overflow */ 69 bfd_elf_generic_reloc, /* special_function */ 70 "R_RISCV_32", /* name */ 71 false, /* partial_inplace */ 72 0, /* src_mask */ 73 0xffffffff, /* dst_mask */ 74 false), /* pcrel_offset */ 75 76 /* 64 bit relocation. */ 77 HOWTO (R_RISCV_64, /* type */ 78 0, /* rightshift */ 79 8, /* size */ 80 64, /* bitsize */ 81 false, /* pc_relative */ 82 0, /* bitpos */ 83 complain_overflow_dont, /* complain_on_overflow */ 84 bfd_elf_generic_reloc, /* special_function */ 85 "R_RISCV_64", /* name */ 86 false, /* partial_inplace */ 87 0, /* src_mask */ 88 MINUS_ONE, /* dst_mask */ 89 false), /* pcrel_offset */ 90 91 /* Relocation against a local symbol in a shared object. */ 92 HOWTO (R_RISCV_RELATIVE, /* type */ 93 0, /* rightshift */ 94 4, /* size */ 95 32, /* bitsize */ 96 false, /* pc_relative */ 97 0, /* bitpos */ 98 complain_overflow_dont, /* complain_on_overflow */ 99 bfd_elf_generic_reloc, /* special_function */ 100 "R_RISCV_RELATIVE", /* name */ 101 false, /* partial_inplace */ 102 0, /* src_mask */ 103 0xffffffff, /* dst_mask */ 104 false), /* pcrel_offset */ 105 106 HOWTO (R_RISCV_COPY, /* type */ 107 0, /* rightshift */ 108 0, /* this one is variable size */ 109 0, /* bitsize */ 110 false, /* pc_relative */ 111 0, /* bitpos */ 112 complain_overflow_bitfield, /* complain_on_overflow */ 113 bfd_elf_generic_reloc, /* special_function */ 114 "R_RISCV_COPY", /* name */ 115 false, /* partial_inplace */ 116 0, /* src_mask */ 117 0, /* dst_mask */ 118 false), /* pcrel_offset */ 119 120 HOWTO (R_RISCV_JUMP_SLOT, /* type */ 121 0, /* rightshift */ 122 8, /* size */ 123 64, /* bitsize */ 124 false, /* pc_relative */ 125 0, /* bitpos */ 126 complain_overflow_bitfield, /* complain_on_overflow */ 127 bfd_elf_generic_reloc, /* special_function */ 128 "R_RISCV_JUMP_SLOT", /* name */ 129 false, /* partial_inplace */ 130 0, /* src_mask */ 131 0, /* dst_mask */ 132 false), /* pcrel_offset */ 133 134 /* Dynamic TLS relocations. */ 135 HOWTO (R_RISCV_TLS_DTPMOD32, /* type */ 136 0, /* rightshift */ 137 4, /* size */ 138 32, /* bitsize */ 139 false, /* pc_relative */ 140 0, /* bitpos */ 141 complain_overflow_dont, /* complain_on_overflow */ 142 bfd_elf_generic_reloc, /* special_function */ 143 "R_RISCV_TLS_DTPMOD32", /* name */ 144 false, /* partial_inplace */ 145 0, /* src_mask */ 146 0xffffffff, /* dst_mask */ 147 false), /* pcrel_offset */ 148 149 HOWTO (R_RISCV_TLS_DTPMOD64, /* type */ 150 0, /* rightshift */ 151 8, /* size */ 152 64, /* bitsize */ 153 false, /* pc_relative */ 154 0, /* bitpos */ 155 complain_overflow_dont, /* complain_on_overflow */ 156 bfd_elf_generic_reloc, /* special_function */ 157 "R_RISCV_TLS_DTPMOD64", /* name */ 158 false, /* partial_inplace */ 159 0, /* src_mask */ 160 MINUS_ONE, /* dst_mask */ 161 false), /* pcrel_offset */ 162 163 HOWTO (R_RISCV_TLS_DTPREL32, /* type */ 164 0, /* rightshift */ 165 4, /* size */ 166 32, /* bitsize */ 167 false, /* pc_relative */ 168 0, /* bitpos */ 169 complain_overflow_dont, /* complain_on_overflow */ 170 bfd_elf_generic_reloc, /* special_function */ 171 "R_RISCV_TLS_DTPREL32", /* name */ 172 true, /* partial_inplace */ 173 0, /* src_mask */ 174 0xffffffff, /* dst_mask */ 175 false), /* pcrel_offset */ 176 177 HOWTO (R_RISCV_TLS_DTPREL64, /* type */ 178 0, /* rightshift */ 179 8, /* size */ 180 64, /* bitsize */ 181 false, /* pc_relative */ 182 0, /* bitpos */ 183 complain_overflow_dont, /* complain_on_overflow */ 184 bfd_elf_generic_reloc, /* special_function */ 185 "R_RISCV_TLS_DTPREL64", /* name */ 186 true, /* partial_inplace */ 187 0, /* src_mask */ 188 MINUS_ONE, /* dst_mask */ 189 false), /* pcrel_offset */ 190 191 HOWTO (R_RISCV_TLS_TPREL32, /* type */ 192 0, /* rightshift */ 193 4, /* size */ 194 32, /* bitsize */ 195 false, /* pc_relative */ 196 0, /* bitpos */ 197 complain_overflow_dont, /* complain_on_overflow */ 198 bfd_elf_generic_reloc, /* special_function */ 199 "R_RISCV_TLS_TPREL32", /* name */ 200 false, /* partial_inplace */ 201 0, /* src_mask */ 202 0xffffffff, /* dst_mask */ 203 false), /* pcrel_offset */ 204 205 HOWTO (R_RISCV_TLS_TPREL64, /* type */ 206 0, /* rightshift */ 207 8, /* size */ 208 64, /* bitsize */ 209 false, /* pc_relative */ 210 0, /* bitpos */ 211 complain_overflow_dont, /* complain_on_overflow */ 212 bfd_elf_generic_reloc, /* special_function */ 213 "R_RISCV_TLS_TPREL64", /* name */ 214 false, /* partial_inplace */ 215 0, /* src_mask */ 216 MINUS_ONE, /* dst_mask */ 217 false), /* pcrel_offset */ 218 219 /* Reserved for future relocs that the dynamic linker must understand. */ 220 EMPTY_HOWTO (12), 221 EMPTY_HOWTO (13), 222 EMPTY_HOWTO (14), 223 EMPTY_HOWTO (15), 224 225 /* 12-bit PC-relative branch offset. */ 226 HOWTO (R_RISCV_BRANCH, /* type */ 227 0, /* rightshift */ 228 4, /* size */ 229 32, /* bitsize */ 230 true, /* pc_relative */ 231 0, /* bitpos */ 232 complain_overflow_signed, /* complain_on_overflow */ 233 bfd_elf_generic_reloc, /* special_function */ 234 "R_RISCV_BRANCH", /* name */ 235 false, /* partial_inplace */ 236 0, /* src_mask */ 237 ENCODE_BTYPE_IMM (-1U), /* dst_mask */ 238 true), /* pcrel_offset */ 239 240 /* 20-bit PC-relative jump offset. */ 241 HOWTO (R_RISCV_JAL, /* type */ 242 0, /* rightshift */ 243 4, /* size */ 244 32, /* bitsize */ 245 true, /* pc_relative */ 246 0, /* bitpos */ 247 complain_overflow_dont, /* complain_on_overflow */ 248 bfd_elf_generic_reloc, /* special_function */ 249 "R_RISCV_JAL", /* name */ 250 false, /* partial_inplace */ 251 0, /* src_mask */ 252 ENCODE_JTYPE_IMM (-1U), /* dst_mask */ 253 true), /* pcrel_offset */ 254 255 /* 32-bit PC-relative function call (AUIPC/JALR). */ 256 HOWTO (R_RISCV_CALL, /* type */ 257 0, /* rightshift */ 258 8, /* size */ 259 64, /* bitsize */ 260 true, /* pc_relative */ 261 0, /* bitpos */ 262 complain_overflow_dont, /* complain_on_overflow */ 263 bfd_elf_generic_reloc, /* special_function */ 264 "R_RISCV_CALL", /* name */ 265 false, /* partial_inplace */ 266 0, /* src_mask */ 267 ENCODE_UTYPE_IMM (-1U) | ((bfd_vma) ENCODE_ITYPE_IMM (-1U) << 32), 268 /* dst_mask */ 269 true), /* pcrel_offset */ 270 271 /* Like R_RISCV_CALL, but not locally binding. */ 272 HOWTO (R_RISCV_CALL_PLT, /* type */ 273 0, /* rightshift */ 274 8, /* size */ 275 64, /* bitsize */ 276 true, /* pc_relative */ 277 0, /* bitpos */ 278 complain_overflow_dont, /* complain_on_overflow */ 279 bfd_elf_generic_reloc, /* special_function */ 280 "R_RISCV_CALL_PLT", /* name */ 281 false, /* partial_inplace */ 282 0, /* src_mask */ 283 ENCODE_UTYPE_IMM (-1U) | ((bfd_vma) ENCODE_ITYPE_IMM (-1U) << 32), 284 /* dst_mask */ 285 true), /* pcrel_offset */ 286 287 /* High 20 bits of 32-bit PC-relative GOT access. */ 288 HOWTO (R_RISCV_GOT_HI20, /* type */ 289 0, /* rightshift */ 290 4, /* size */ 291 32, /* bitsize */ 292 true, /* pc_relative */ 293 0, /* bitpos */ 294 complain_overflow_dont, /* complain_on_overflow */ 295 bfd_elf_generic_reloc, /* special_function */ 296 "R_RISCV_GOT_HI20", /* name */ 297 false, /* partial_inplace */ 298 0, /* src_mask */ 299 ENCODE_UTYPE_IMM (-1U), /* dst_mask */ 300 false), /* pcrel_offset */ 301 302 /* High 20 bits of 32-bit PC-relative TLS IE GOT access. */ 303 HOWTO (R_RISCV_TLS_GOT_HI20, /* type */ 304 0, /* rightshift */ 305 4, /* size */ 306 32, /* bitsize */ 307 true, /* pc_relative */ 308 0, /* bitpos */ 309 complain_overflow_dont, /* complain_on_overflow */ 310 bfd_elf_generic_reloc, /* special_function */ 311 "R_RISCV_TLS_GOT_HI20", /* name */ 312 false, /* partial_inplace */ 313 0, /* src_mask */ 314 ENCODE_UTYPE_IMM (-1U), /* dst_mask */ 315 false), /* pcrel_offset */ 316 317 /* High 20 bits of 32-bit PC-relative TLS GD GOT reference. */ 318 HOWTO (R_RISCV_TLS_GD_HI20, /* type */ 319 0, /* rightshift */ 320 4, /* size */ 321 32, /* bitsize */ 322 true, /* pc_relative */ 323 0, /* bitpos */ 324 complain_overflow_dont, /* complain_on_overflow */ 325 bfd_elf_generic_reloc, /* special_function */ 326 "R_RISCV_TLS_GD_HI20", /* name */ 327 false, /* partial_inplace */ 328 0, /* src_mask */ 329 ENCODE_UTYPE_IMM (-1U), /* dst_mask */ 330 false), /* pcrel_offset */ 331 332 /* High 20 bits of 32-bit PC-relative reference. */ 333 HOWTO (R_RISCV_PCREL_HI20, /* type */ 334 0, /* rightshift */ 335 4, /* size */ 336 32, /* bitsize */ 337 true, /* pc_relative */ 338 0, /* bitpos */ 339 complain_overflow_dont, /* complain_on_overflow */ 340 bfd_elf_generic_reloc, /* special_function */ 341 "R_RISCV_PCREL_HI20", /* name */ 342 false, /* partial_inplace */ 343 0, /* src_mask */ 344 ENCODE_UTYPE_IMM (-1U), /* dst_mask */ 345 true), /* pcrel_offset */ 346 347 /* Low 12 bits of a 32-bit PC-relative load or add. */ 348 HOWTO (R_RISCV_PCREL_LO12_I, /* type */ 349 0, /* rightshift */ 350 4, /* size */ 351 32, /* bitsize */ 352 false, /* pc_relative */ 353 0, /* bitpos */ 354 complain_overflow_dont, /* complain_on_overflow */ 355 bfd_elf_generic_reloc, /* special_function */ 356 "R_RISCV_PCREL_LO12_I", /* name */ 357 false, /* partial_inplace */ 358 0, /* src_mask */ 359 ENCODE_ITYPE_IMM (-1U), /* dst_mask */ 360 false), /* pcrel_offset */ 361 362 /* Low 12 bits of a 32-bit PC-relative store. */ 363 HOWTO (R_RISCV_PCREL_LO12_S, /* type */ 364 0, /* rightshift */ 365 4, /* size */ 366 32, /* bitsize */ 367 false, /* pc_relative */ 368 0, /* bitpos */ 369 complain_overflow_dont, /* complain_on_overflow */ 370 bfd_elf_generic_reloc, /* special_function */ 371 "R_RISCV_PCREL_LO12_S", /* name */ 372 false, /* partial_inplace */ 373 0, /* src_mask */ 374 ENCODE_STYPE_IMM (-1U), /* dst_mask */ 375 false), /* pcrel_offset */ 376 377 /* High 20 bits of 32-bit absolute address. */ 378 HOWTO (R_RISCV_HI20, /* type */ 379 0, /* rightshift */ 380 4, /* size */ 381 32, /* bitsize */ 382 false, /* pc_relative */ 383 0, /* bitpos */ 384 complain_overflow_dont, /* complain_on_overflow */ 385 bfd_elf_generic_reloc, /* special_function */ 386 "R_RISCV_HI20", /* name */ 387 false, /* partial_inplace */ 388 0, /* src_mask */ 389 ENCODE_UTYPE_IMM (-1U), /* dst_mask */ 390 false), /* pcrel_offset */ 391 392 /* High 12 bits of 32-bit load or add. */ 393 HOWTO (R_RISCV_LO12_I, /* type */ 394 0, /* rightshift */ 395 4, /* size */ 396 32, /* bitsize */ 397 false, /* pc_relative */ 398 0, /* bitpos */ 399 complain_overflow_dont, /* complain_on_overflow */ 400 bfd_elf_generic_reloc, /* special_function */ 401 "R_RISCV_LO12_I", /* name */ 402 false, /* partial_inplace */ 403 0, /* src_mask */ 404 ENCODE_ITYPE_IMM (-1U), /* dst_mask */ 405 false), /* pcrel_offset */ 406 407 /* High 12 bits of 32-bit store. */ 408 HOWTO (R_RISCV_LO12_S, /* type */ 409 0, /* rightshift */ 410 4, /* size */ 411 32, /* bitsize */ 412 false, /* pc_relative */ 413 0, /* bitpos */ 414 complain_overflow_dont, /* complain_on_overflow */ 415 bfd_elf_generic_reloc, /* special_function */ 416 "R_RISCV_LO12_S", /* name */ 417 false, /* partial_inplace */ 418 0, /* src_mask */ 419 ENCODE_STYPE_IMM (-1U), /* dst_mask */ 420 false), /* pcrel_offset */ 421 422 /* High 20 bits of TLS LE thread pointer offset. */ 423 HOWTO (R_RISCV_TPREL_HI20, /* type */ 424 0, /* rightshift */ 425 4, /* size */ 426 32, /* bitsize */ 427 false, /* pc_relative */ 428 0, /* bitpos */ 429 complain_overflow_signed, /* complain_on_overflow */ 430 bfd_elf_generic_reloc, /* special_function */ 431 "R_RISCV_TPREL_HI20", /* name */ 432 true, /* partial_inplace */ 433 0, /* src_mask */ 434 ENCODE_UTYPE_IMM (-1U), /* dst_mask */ 435 false), /* pcrel_offset */ 436 437 /* Low 12 bits of TLS LE thread pointer offset for loads and adds. */ 438 HOWTO (R_RISCV_TPREL_LO12_I, /* type */ 439 0, /* rightshift */ 440 4, /* size */ 441 32, /* bitsize */ 442 false, /* pc_relative */ 443 0, /* bitpos */ 444 complain_overflow_signed, /* complain_on_overflow */ 445 bfd_elf_generic_reloc, /* special_function */ 446 "R_RISCV_TPREL_LO12_I", /* name */ 447 false, /* partial_inplace */ 448 0, /* src_mask */ 449 ENCODE_ITYPE_IMM (-1U), /* dst_mask */ 450 false), /* pcrel_offset */ 451 452 /* Low 12 bits of TLS LE thread pointer offset for stores. */ 453 HOWTO (R_RISCV_TPREL_LO12_S, /* type */ 454 0, /* rightshift */ 455 4, /* size */ 456 32, /* bitsize */ 457 false, /* pc_relative */ 458 0, /* bitpos */ 459 complain_overflow_signed, /* complain_on_overflow */ 460 bfd_elf_generic_reloc, /* special_function */ 461 "R_RISCV_TPREL_LO12_S", /* name */ 462 false, /* partial_inplace */ 463 0, /* src_mask */ 464 ENCODE_STYPE_IMM (-1U), /* dst_mask */ 465 false), /* pcrel_offset */ 466 467 /* TLS LE thread pointer usage. May be relaxed. */ 468 HOWTO (R_RISCV_TPREL_ADD, /* type */ 469 0, /* rightshift */ 470 0, /* size */ 471 0, /* bitsize */ 472 false, /* pc_relative */ 473 0, /* bitpos */ 474 complain_overflow_dont, /* complain_on_overflow */ 475 bfd_elf_generic_reloc, /* special_function */ 476 "R_RISCV_TPREL_ADD", /* name */ 477 false, /* partial_inplace */ 478 0, /* src_mask */ 479 0, /* dst_mask */ 480 false), /* pcrel_offset */ 481 482 /* 8-bit in-place addition, for local label subtraction. */ 483 HOWTO (R_RISCV_ADD8, /* type */ 484 0, /* rightshift */ 485 1, /* size */ 486 8, /* bitsize */ 487 false, /* pc_relative */ 488 0, /* bitpos */ 489 complain_overflow_dont, /* complain_on_overflow */ 490 riscv_elf_add_sub_reloc, /* special_function */ 491 "R_RISCV_ADD8", /* name */ 492 false, /* partial_inplace */ 493 0, /* src_mask */ 494 0xff, /* dst_mask */ 495 false), /* pcrel_offset */ 496 497 /* 16-bit in-place addition, for local label subtraction. */ 498 HOWTO (R_RISCV_ADD16, /* type */ 499 0, /* rightshift */ 500 2, /* size */ 501 16, /* bitsize */ 502 false, /* pc_relative */ 503 0, /* bitpos */ 504 complain_overflow_dont, /* complain_on_overflow */ 505 riscv_elf_add_sub_reloc, /* special_function */ 506 "R_RISCV_ADD16", /* name */ 507 false, /* partial_inplace */ 508 0, /* src_mask */ 509 0xffff, /* dst_mask */ 510 false), /* pcrel_offset */ 511 512 /* 32-bit in-place addition, for local label subtraction. */ 513 HOWTO (R_RISCV_ADD32, /* type */ 514 0, /* rightshift */ 515 4, /* size */ 516 32, /* bitsize */ 517 false, /* pc_relative */ 518 0, /* bitpos */ 519 complain_overflow_dont, /* complain_on_overflow */ 520 riscv_elf_add_sub_reloc, /* special_function */ 521 "R_RISCV_ADD32", /* name */ 522 false, /* partial_inplace */ 523 0, /* src_mask */ 524 0xffffffff, /* dst_mask */ 525 false), /* pcrel_offset */ 526 527 /* 64-bit in-place addition, for local label subtraction. */ 528 HOWTO (R_RISCV_ADD64, /* type */ 529 0, /* rightshift */ 530 8, /* size */ 531 64, /* bitsize */ 532 false, /* pc_relative */ 533 0, /* bitpos */ 534 complain_overflow_dont, /* complain_on_overflow */ 535 riscv_elf_add_sub_reloc, /* special_function */ 536 "R_RISCV_ADD64", /* name */ 537 false, /* partial_inplace */ 538 0, /* src_mask */ 539 MINUS_ONE, /* dst_mask */ 540 false), /* pcrel_offset */ 541 542 /* 8-bit in-place addition, for local label subtraction. */ 543 HOWTO (R_RISCV_SUB8, /* type */ 544 0, /* rightshift */ 545 1, /* size */ 546 8, /* bitsize */ 547 false, /* pc_relative */ 548 0, /* bitpos */ 549 complain_overflow_dont, /* complain_on_overflow */ 550 riscv_elf_add_sub_reloc, /* special_function */ 551 "R_RISCV_SUB8", /* name */ 552 false, /* partial_inplace */ 553 0, /* src_mask */ 554 0xff, /* dst_mask */ 555 false), /* pcrel_offset */ 556 557 /* 16-bit in-place addition, for local label subtraction. */ 558 HOWTO (R_RISCV_SUB16, /* type */ 559 0, /* rightshift */ 560 2, /* size */ 561 16, /* bitsize */ 562 false, /* pc_relative */ 563 0, /* bitpos */ 564 complain_overflow_dont, /* complain_on_overflow */ 565 riscv_elf_add_sub_reloc, /* special_function */ 566 "R_RISCV_SUB16", /* name */ 567 false, /* partial_inplace */ 568 0, /* src_mask */ 569 0xffff, /* dst_mask */ 570 false), /* pcrel_offset */ 571 572 /* 32-bit in-place addition, for local label subtraction. */ 573 HOWTO (R_RISCV_SUB32, /* type */ 574 0, /* rightshift */ 575 4, /* size */ 576 32, /* bitsize */ 577 false, /* pc_relative */ 578 0, /* bitpos */ 579 complain_overflow_dont, /* complain_on_overflow */ 580 riscv_elf_add_sub_reloc, /* special_function */ 581 "R_RISCV_SUB32", /* name */ 582 false, /* partial_inplace */ 583 0, /* src_mask */ 584 0xffffffff, /* dst_mask */ 585 false), /* pcrel_offset */ 586 587 /* 64-bit in-place addition, for local label subtraction. */ 588 HOWTO (R_RISCV_SUB64, /* type */ 589 0, /* rightshift */ 590 8, /* size */ 591 64, /* bitsize */ 592 false, /* pc_relative */ 593 0, /* bitpos */ 594 complain_overflow_dont, /* complain_on_overflow */ 595 riscv_elf_add_sub_reloc, /* special_function */ 596 "R_RISCV_SUB64", /* name */ 597 false, /* partial_inplace */ 598 0, /* src_mask */ 599 MINUS_ONE, /* dst_mask */ 600 false), /* pcrel_offset */ 601 602 /* GNU extension to record C++ vtable hierarchy */ 603 HOWTO (R_RISCV_GNU_VTINHERIT, /* type */ 604 0, /* rightshift */ 605 8, /* size */ 606 0, /* bitsize */ 607 false, /* pc_relative */ 608 0, /* bitpos */ 609 complain_overflow_dont, /* complain_on_overflow */ 610 NULL, /* special_function */ 611 "R_RISCV_GNU_VTINHERIT", /* name */ 612 false, /* partial_inplace */ 613 0, /* src_mask */ 614 0, /* dst_mask */ 615 false), /* pcrel_offset */ 616 617 /* GNU extension to record C++ vtable member usage */ 618 HOWTO (R_RISCV_GNU_VTENTRY, /* type */ 619 0, /* rightshift */ 620 8, /* size */ 621 0, /* bitsize */ 622 false, /* pc_relative */ 623 0, /* bitpos */ 624 complain_overflow_dont, /* complain_on_overflow */ 625 _bfd_elf_rel_vtable_reloc_fn, /* special_function */ 626 "R_RISCV_GNU_VTENTRY", /* name */ 627 false, /* partial_inplace */ 628 0, /* src_mask */ 629 0, /* dst_mask */ 630 false), /* pcrel_offset */ 631 632 /* Indicates an alignment statement. The addend field encodes how many 633 bytes of NOPs follow the statement. The desired alignment is the 634 addend rounded up to the next power of two. */ 635 HOWTO (R_RISCV_ALIGN, /* type */ 636 0, /* rightshift */ 637 0, /* size */ 638 0, /* bitsize */ 639 false, /* pc_relative */ 640 0, /* bitpos */ 641 complain_overflow_dont, /* complain_on_overflow */ 642 bfd_elf_generic_reloc, /* special_function */ 643 "R_RISCV_ALIGN", /* name */ 644 false, /* partial_inplace */ 645 0, /* src_mask */ 646 0, /* dst_mask */ 647 false), /* pcrel_offset */ 648 649 /* 8-bit PC-relative branch offset. */ 650 HOWTO (R_RISCV_RVC_BRANCH, /* type */ 651 0, /* rightshift */ 652 2, /* size */ 653 16, /* bitsize */ 654 true, /* pc_relative */ 655 0, /* bitpos */ 656 complain_overflow_signed, /* complain_on_overflow */ 657 bfd_elf_generic_reloc, /* special_function */ 658 "R_RISCV_RVC_BRANCH", /* name */ 659 false, /* partial_inplace */ 660 0, /* src_mask */ 661 ENCODE_CBTYPE_IMM (-1U), /* dst_mask */ 662 true), /* pcrel_offset */ 663 664 /* 11-bit PC-relative jump offset. */ 665 HOWTO (R_RISCV_RVC_JUMP, /* type */ 666 0, /* rightshift */ 667 2, /* size */ 668 16, /* bitsize */ 669 true, /* pc_relative */ 670 0, /* bitpos */ 671 complain_overflow_dont, /* complain_on_overflow */ 672 bfd_elf_generic_reloc, /* special_function */ 673 "R_RISCV_RVC_JUMP", /* name */ 674 false, /* partial_inplace */ 675 0, /* src_mask */ 676 ENCODE_CJTYPE_IMM (-1U), /* dst_mask */ 677 true), /* pcrel_offset */ 678 679 /* High 6 bits of 18-bit absolute address. */ 680 HOWTO (R_RISCV_RVC_LUI, /* type */ 681 0, /* rightshift */ 682 2, /* size */ 683 16, /* bitsize */ 684 false, /* pc_relative */ 685 0, /* bitpos */ 686 complain_overflow_dont, /* complain_on_overflow */ 687 bfd_elf_generic_reloc, /* special_function */ 688 "R_RISCV_RVC_LUI", /* name */ 689 false, /* partial_inplace */ 690 0, /* src_mask */ 691 ENCODE_CITYPE_IMM (-1U), /* dst_mask */ 692 false), /* pcrel_offset */ 693 694 /* GP-relative load. */ 695 HOWTO (R_RISCV_GPREL_I, /* type */ 696 0, /* rightshift */ 697 4, /* size */ 698 32, /* bitsize */ 699 false, /* pc_relative */ 700 0, /* bitpos */ 701 complain_overflow_dont, /* complain_on_overflow */ 702 bfd_elf_generic_reloc, /* special_function */ 703 "R_RISCV_GPREL_I", /* name */ 704 false, /* partial_inplace */ 705 0, /* src_mask */ 706 ENCODE_ITYPE_IMM (-1U), /* dst_mask */ 707 false), /* pcrel_offset */ 708 709 /* GP-relative store. */ 710 HOWTO (R_RISCV_GPREL_S, /* type */ 711 0, /* rightshift */ 712 4, /* size */ 713 32, /* bitsize */ 714 false, /* pc_relative */ 715 0, /* bitpos */ 716 complain_overflow_dont, /* complain_on_overflow */ 717 bfd_elf_generic_reloc, /* special_function */ 718 "R_RISCV_GPREL_S", /* name */ 719 false, /* partial_inplace */ 720 0, /* src_mask */ 721 ENCODE_STYPE_IMM (-1U), /* dst_mask */ 722 false), /* pcrel_offset */ 723 724 /* TP-relative TLS LE load. */ 725 HOWTO (R_RISCV_TPREL_I, /* type */ 726 0, /* rightshift */ 727 4, /* size */ 728 32, /* bitsize */ 729 false, /* pc_relative */ 730 0, /* bitpos */ 731 complain_overflow_signed, /* complain_on_overflow */ 732 bfd_elf_generic_reloc, /* special_function */ 733 "R_RISCV_TPREL_I", /* name */ 734 false, /* partial_inplace */ 735 0, /* src_mask */ 736 ENCODE_ITYPE_IMM (-1U), /* dst_mask */ 737 false), /* pcrel_offset */ 738 739 /* TP-relative TLS LE store. */ 740 HOWTO (R_RISCV_TPREL_S, /* type */ 741 0, /* rightshift */ 742 4, /* size */ 743 32, /* bitsize */ 744 false, /* pc_relative */ 745 0, /* bitpos */ 746 complain_overflow_signed, /* complain_on_overflow */ 747 bfd_elf_generic_reloc, /* special_function */ 748 "R_RISCV_TPREL_S", /* name */ 749 false, /* partial_inplace */ 750 0, /* src_mask */ 751 ENCODE_STYPE_IMM (-1U), /* dst_mask */ 752 false), /* pcrel_offset */ 753 754 /* The paired relocation may be relaxed. */ 755 HOWTO (R_RISCV_RELAX, /* type */ 756 0, /* rightshift */ 757 0, /* size */ 758 0, /* bitsize */ 759 false, /* pc_relative */ 760 0, /* bitpos */ 761 complain_overflow_dont, /* complain_on_overflow */ 762 bfd_elf_generic_reloc, /* special_function */ 763 "R_RISCV_RELAX", /* name */ 764 false, /* partial_inplace */ 765 0, /* src_mask */ 766 0, /* dst_mask */ 767 false), /* pcrel_offset */ 768 769 /* 6-bit in-place addition, for local label subtraction. */ 770 HOWTO (R_RISCV_SUB6, /* type */ 771 0, /* rightshift */ 772 1, /* size */ 773 8, /* bitsize */ 774 false, /* pc_relative */ 775 0, /* bitpos */ 776 complain_overflow_dont, /* complain_on_overflow */ 777 riscv_elf_add_sub_reloc, /* special_function */ 778 "R_RISCV_SUB6", /* name */ 779 false, /* partial_inplace */ 780 0, /* src_mask */ 781 0x3f, /* dst_mask */ 782 false), /* pcrel_offset */ 783 784 /* 6-bit in-place setting, for local label subtraction. */ 785 HOWTO (R_RISCV_SET6, /* type */ 786 0, /* rightshift */ 787 1, /* size */ 788 8, /* bitsize */ 789 false, /* pc_relative */ 790 0, /* bitpos */ 791 complain_overflow_dont, /* complain_on_overflow */ 792 bfd_elf_generic_reloc, /* special_function */ 793 "R_RISCV_SET6", /* name */ 794 false, /* partial_inplace */ 795 0, /* src_mask */ 796 0x3f, /* dst_mask */ 797 false), /* pcrel_offset */ 798 799 /* 8-bit in-place setting, for local label subtraction. */ 800 HOWTO (R_RISCV_SET8, /* type */ 801 0, /* rightshift */ 802 1, /* size */ 803 8, /* bitsize */ 804 false, /* pc_relative */ 805 0, /* bitpos */ 806 complain_overflow_dont, /* complain_on_overflow */ 807 bfd_elf_generic_reloc, /* special_function */ 808 "R_RISCV_SET8", /* name */ 809 false, /* partial_inplace */ 810 0, /* src_mask */ 811 0xff, /* dst_mask */ 812 false), /* pcrel_offset */ 813 814 /* 16-bit in-place setting, for local label subtraction. */ 815 HOWTO (R_RISCV_SET16, /* type */ 816 0, /* rightshift */ 817 2, /* size */ 818 16, /* bitsize */ 819 false, /* pc_relative */ 820 0, /* bitpos */ 821 complain_overflow_dont, /* complain_on_overflow */ 822 bfd_elf_generic_reloc, /* special_function */ 823 "R_RISCV_SET16", /* name */ 824 false, /* partial_inplace */ 825 0, /* src_mask */ 826 0xffff, /* dst_mask */ 827 false), /* pcrel_offset */ 828 829 /* 32-bit in-place setting, for local label subtraction. */ 830 HOWTO (R_RISCV_SET32, /* type */ 831 0, /* rightshift */ 832 4, /* size */ 833 32, /* bitsize */ 834 false, /* pc_relative */ 835 0, /* bitpos */ 836 complain_overflow_dont, /* complain_on_overflow */ 837 bfd_elf_generic_reloc, /* special_function */ 838 "R_RISCV_SET32", /* name */ 839 false, /* partial_inplace */ 840 0, /* src_mask */ 841 0xffffffff, /* dst_mask */ 842 false), /* pcrel_offset */ 843 844 /* 32-bit PC relative. */ 845 HOWTO (R_RISCV_32_PCREL, /* type */ 846 0, /* rightshift */ 847 4, /* size */ 848 32, /* bitsize */ 849 true, /* pc_relative */ 850 0, /* bitpos */ 851 complain_overflow_dont, /* complain_on_overflow */ 852 bfd_elf_generic_reloc, /* special_function */ 853 "R_RISCV_32_PCREL", /* name */ 854 false, /* partial_inplace */ 855 0, /* src_mask */ 856 0xffffffff, /* dst_mask */ 857 false), /* pcrel_offset */ 858 859 /* Relocation against a local ifunc symbol in a shared object. */ 860 HOWTO (R_RISCV_IRELATIVE, /* type */ 861 0, /* rightshift */ 862 4, /* size */ 863 32, /* bitsize */ 864 false, /* pc_relative */ 865 0, /* bitpos */ 866 complain_overflow_dont, /* complain_on_overflow */ 867 bfd_elf_generic_reloc, /* special_function */ 868 "R_RISCV_IRELATIVE", /* name */ 869 false, /* partial_inplace */ 870 0, /* src_mask */ 871 0xffffffff, /* dst_mask */ 872 false), /* pcrel_offset */ 873}; 874 875/* A mapping from BFD reloc types to RISC-V ELF reloc types. */ 876struct elf_reloc_map 877{ 878 bfd_reloc_code_real_type bfd_val; 879 enum elf_riscv_reloc_type elf_val; 880}; 881 882static const struct elf_reloc_map riscv_reloc_map[] = 883{ 884 { BFD_RELOC_NONE, R_RISCV_NONE }, 885 { BFD_RELOC_32, R_RISCV_32 }, 886 { BFD_RELOC_64, R_RISCV_64 }, 887 { BFD_RELOC_RISCV_ADD8, R_RISCV_ADD8 }, 888 { BFD_RELOC_RISCV_ADD16, R_RISCV_ADD16 }, 889 { BFD_RELOC_RISCV_ADD32, R_RISCV_ADD32 }, 890 { BFD_RELOC_RISCV_ADD64, R_RISCV_ADD64 }, 891 { BFD_RELOC_RISCV_SUB8, R_RISCV_SUB8 }, 892 { BFD_RELOC_RISCV_SUB16, R_RISCV_SUB16 }, 893 { BFD_RELOC_RISCV_SUB32, R_RISCV_SUB32 }, 894 { BFD_RELOC_RISCV_SUB64, R_RISCV_SUB64 }, 895 { BFD_RELOC_CTOR, R_RISCV_64 }, 896 { BFD_RELOC_12_PCREL, R_RISCV_BRANCH }, 897 { BFD_RELOC_RISCV_HI20, R_RISCV_HI20 }, 898 { BFD_RELOC_RISCV_LO12_I, R_RISCV_LO12_I }, 899 { BFD_RELOC_RISCV_LO12_S, R_RISCV_LO12_S }, 900 { BFD_RELOC_RISCV_PCREL_LO12_I, R_RISCV_PCREL_LO12_I }, 901 { BFD_RELOC_RISCV_PCREL_LO12_S, R_RISCV_PCREL_LO12_S }, 902 { BFD_RELOC_RISCV_CALL, R_RISCV_CALL }, 903 { BFD_RELOC_RISCV_CALL_PLT, R_RISCV_CALL_PLT }, 904 { BFD_RELOC_RISCV_PCREL_HI20, R_RISCV_PCREL_HI20 }, 905 { BFD_RELOC_RISCV_JMP, R_RISCV_JAL }, 906 { BFD_RELOC_RISCV_GOT_HI20, R_RISCV_GOT_HI20 }, 907 { BFD_RELOC_RISCV_TLS_DTPMOD32, R_RISCV_TLS_DTPMOD32 }, 908 { BFD_RELOC_RISCV_TLS_DTPREL32, R_RISCV_TLS_DTPREL32 }, 909 { BFD_RELOC_RISCV_TLS_DTPMOD64, R_RISCV_TLS_DTPMOD64 }, 910 { BFD_RELOC_RISCV_TLS_DTPREL64, R_RISCV_TLS_DTPREL64 }, 911 { BFD_RELOC_RISCV_TLS_TPREL32, R_RISCV_TLS_TPREL32 }, 912 { BFD_RELOC_RISCV_TLS_TPREL64, R_RISCV_TLS_TPREL64 }, 913 { BFD_RELOC_RISCV_TPREL_HI20, R_RISCV_TPREL_HI20 }, 914 { BFD_RELOC_RISCV_TPREL_ADD, R_RISCV_TPREL_ADD }, 915 { BFD_RELOC_RISCV_TPREL_LO12_S, R_RISCV_TPREL_LO12_S }, 916 { BFD_RELOC_RISCV_TPREL_LO12_I, R_RISCV_TPREL_LO12_I }, 917 { BFD_RELOC_RISCV_TLS_GOT_HI20, R_RISCV_TLS_GOT_HI20 }, 918 { BFD_RELOC_RISCV_TLS_GD_HI20, R_RISCV_TLS_GD_HI20 }, 919 { BFD_RELOC_RISCV_ALIGN, R_RISCV_ALIGN }, 920 { BFD_RELOC_RISCV_RVC_BRANCH, R_RISCV_RVC_BRANCH }, 921 { BFD_RELOC_RISCV_RVC_JUMP, R_RISCV_RVC_JUMP }, 922 { BFD_RELOC_RISCV_RVC_LUI, R_RISCV_RVC_LUI }, 923 { BFD_RELOC_RISCV_GPREL_I, R_RISCV_GPREL_I }, 924 { BFD_RELOC_RISCV_GPREL_S, R_RISCV_GPREL_S }, 925 { BFD_RELOC_RISCV_TPREL_I, R_RISCV_TPREL_I }, 926 { BFD_RELOC_RISCV_TPREL_S, R_RISCV_TPREL_S }, 927 { BFD_RELOC_RISCV_RELAX, R_RISCV_RELAX }, 928 { BFD_RELOC_RISCV_SUB6, R_RISCV_SUB6 }, 929 { BFD_RELOC_RISCV_SET6, R_RISCV_SET6 }, 930 { BFD_RELOC_RISCV_SET8, R_RISCV_SET8 }, 931 { BFD_RELOC_RISCV_SET16, R_RISCV_SET16 }, 932 { BFD_RELOC_RISCV_SET32, R_RISCV_SET32 }, 933 { BFD_RELOC_RISCV_32_PCREL, R_RISCV_32_PCREL }, 934}; 935 936/* Given a BFD reloc type, return a howto structure. */ 937 938reloc_howto_type * 939riscv_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, 940 bfd_reloc_code_real_type code) 941{ 942 unsigned int i; 943 944 for (i = 0; i < ARRAY_SIZE (riscv_reloc_map); i++) 945 if (riscv_reloc_map[i].bfd_val == code) 946 return &howto_table[(int) riscv_reloc_map[i].elf_val]; 947 948 bfd_set_error (bfd_error_bad_value); 949 return NULL; 950} 951 952reloc_howto_type * 953riscv_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name) 954{ 955 unsigned int i; 956 957 for (i = 0; i < ARRAY_SIZE (howto_table); i++) 958 if (howto_table[i].name && strcasecmp (howto_table[i].name, r_name) == 0) 959 return &howto_table[i]; 960 961 return NULL; 962} 963 964reloc_howto_type * 965riscv_elf_rtype_to_howto (bfd *abfd, unsigned int r_type) 966{ 967 if (r_type >= ARRAY_SIZE (howto_table)) 968 { 969 (*_bfd_error_handler) (_("%pB: unsupported relocation type %#x"), 970 abfd, r_type); 971 bfd_set_error (bfd_error_bad_value); 972 return NULL; 973 } 974 return &howto_table[r_type]; 975} 976 977/* Special_function of RISCV_ADD and RISCV_SUB relocations. */ 978 979static bfd_reloc_status_type 980riscv_elf_add_sub_reloc (bfd *abfd, 981 arelent *reloc_entry, 982 asymbol *symbol, 983 void *data, 984 asection *input_section, 985 bfd *output_bfd, 986 char **error_message ATTRIBUTE_UNUSED) 987{ 988 reloc_howto_type *howto = reloc_entry->howto; 989 bfd_vma relocation; 990 991 if (output_bfd != NULL 992 && (symbol->flags & BSF_SECTION_SYM) == 0 993 && (!reloc_entry->howto->partial_inplace || reloc_entry->addend == 0)) 994 { 995 reloc_entry->address += input_section->output_offset; 996 return bfd_reloc_ok; 997 } 998 999 if (output_bfd != NULL) 1000 return bfd_reloc_continue; 1001 1002 relocation = symbol->value + symbol->section->output_section->vma 1003 + symbol->section->output_offset + reloc_entry->addend; 1004 1005 bfd_size_type octets = reloc_entry->address 1006 * bfd_octets_per_byte (abfd, input_section); 1007 if (!bfd_reloc_offset_in_range (reloc_entry->howto, abfd, 1008 input_section, octets)) 1009 return bfd_reloc_outofrange; 1010 1011 bfd_vma old_value = bfd_get (howto->bitsize, abfd, 1012 data + reloc_entry->address); 1013 1014 switch (howto->type) 1015 { 1016 case R_RISCV_ADD8: 1017 case R_RISCV_ADD16: 1018 case R_RISCV_ADD32: 1019 case R_RISCV_ADD64: 1020 relocation = old_value + relocation; 1021 break; 1022 case R_RISCV_SUB6: 1023 case R_RISCV_SUB8: 1024 case R_RISCV_SUB16: 1025 case R_RISCV_SUB32: 1026 case R_RISCV_SUB64: 1027 relocation = old_value - relocation; 1028 break; 1029 } 1030 bfd_put (howto->bitsize, abfd, relocation, data + reloc_entry->address); 1031 1032 return bfd_reloc_ok; 1033} 1034 1035/* Always add the IMPLICIT for the SUBSET. */ 1036 1037static bool 1038check_implicit_always (const char *implicit ATTRIBUTE_UNUSED, 1039 riscv_subset_t *subset ATTRIBUTE_UNUSED) 1040{ 1041 return true; 1042} 1043 1044/* Add the IMPLICIT only when the version of SUBSET less than 2.1. */ 1045 1046static bool 1047check_implicit_for_i (const char *implicit ATTRIBUTE_UNUSED, 1048 riscv_subset_t *subset) 1049{ 1050 return (subset->major_version < 2 1051 || (subset->major_version == 2 1052 && subset->minor_version < 1)); 1053} 1054 1055/* Record all implicit information for the subsets. */ 1056struct riscv_implicit_subset 1057{ 1058 const char *subset_name; 1059 const char *implicit_name; 1060 /* A function to determine if we need to add the implicit subset. */ 1061 bool (*check_func) (const char *, riscv_subset_t *); 1062}; 1063static struct riscv_implicit_subset riscv_implicit_subsets[] = 1064{ 1065 {"e", "i", check_implicit_always}, 1066 {"i", "zicsr", check_implicit_for_i}, 1067 {"i", "zifencei", check_implicit_for_i}, 1068 {"g", "i", check_implicit_always}, 1069 {"g", "m", check_implicit_always}, 1070 {"g", "a", check_implicit_always}, 1071 {"g", "f", check_implicit_always}, 1072 {"g", "d", check_implicit_always}, 1073 {"g", "zicsr", check_implicit_always}, 1074 {"g", "zifencei", check_implicit_always}, 1075 {"q", "d", check_implicit_always}, 1076 {"v", "d", check_implicit_always}, 1077 {"v", "zve64d", check_implicit_always}, 1078 {"v", "zvl128b", check_implicit_always}, 1079 {"zve64d", "d", check_implicit_always}, 1080 {"zve64d", "zve64f", check_implicit_always}, 1081 {"zve64f", "zve32f", check_implicit_always}, 1082 {"zve64f", "zve64x", check_implicit_always}, 1083 {"zve64f", "zvl64b", check_implicit_always}, 1084 {"zve32f", "f", check_implicit_always}, 1085 {"zve32f", "zvl32b", check_implicit_always}, 1086 {"zve32f", "zve32x", check_implicit_always}, 1087 {"zve64x", "zve32x", check_implicit_always}, 1088 {"zve64x", "zvl64b", check_implicit_always}, 1089 {"zve32x", "zvl32b", check_implicit_always}, 1090 {"zvl65536b", "zvl32768b", check_implicit_always}, 1091 {"zvl32768b", "zvl16384b", check_implicit_always}, 1092 {"zvl16384b", "zvl8192b", check_implicit_always}, 1093 {"zvl8192b", "zvl4096b", check_implicit_always}, 1094 {"zvl4096b", "zvl2048b", check_implicit_always}, 1095 {"zvl2048b", "zvl1024b", check_implicit_always}, 1096 {"zvl1024b", "zvl512b", check_implicit_always}, 1097 {"zvl512b", "zvl256b", check_implicit_always}, 1098 {"zvl256b", "zvl128b", check_implicit_always}, 1099 {"zvl128b", "zvl64b", check_implicit_always}, 1100 {"zvl64b", "zvl32b", check_implicit_always}, 1101 {"d", "f", check_implicit_always}, 1102 {"zfh", "zfhmin", check_implicit_always}, 1103 {"zfhmin", "f", check_implicit_always}, 1104 {"f", "zicsr", check_implicit_always}, 1105 {"zqinx", "zdinx", check_implicit_always}, 1106 {"zdinx", "zfinx", check_implicit_always}, 1107 {"zhinx", "zhinxmin", check_implicit_always}, 1108 {"zhinxmin", "zfinx", check_implicit_always}, 1109 {"zfinx", "zicsr", check_implicit_always}, 1110 {"zk", "zkn", check_implicit_always}, 1111 {"zk", "zkr", check_implicit_always}, 1112 {"zk", "zkt", check_implicit_always}, 1113 {"zkn", "zbkb", check_implicit_always}, 1114 {"zkn", "zbkc", check_implicit_always}, 1115 {"zkn", "zbkx", check_implicit_always}, 1116 {"zkn", "zkne", check_implicit_always}, 1117 {"zkn", "zknd", check_implicit_always}, 1118 {"zkn", "zknh", check_implicit_always}, 1119 {"zks", "zbkb", check_implicit_always}, 1120 {"zks", "zbkc", check_implicit_always}, 1121 {"zks", "zbkx", check_implicit_always}, 1122 {"zks", "zksed", check_implicit_always}, 1123 {"zks", "zksh", check_implicit_always}, 1124 {NULL, NULL, NULL} 1125}; 1126 1127/* For default_enable field, decide if the extension should 1128 be enbaled by default. */ 1129 1130#define EXT_DEFAULT 0x1 1131 1132/* List all extensions that binutils should know about. */ 1133 1134struct riscv_supported_ext 1135{ 1136 const char *name; 1137 enum riscv_spec_class isa_spec_class; 1138 int major_version; 1139 int minor_version; 1140 unsigned long default_enable; 1141}; 1142 1143/* The standard extensions must be added in canonical order. */ 1144 1145static struct riscv_supported_ext riscv_supported_std_ext[] = 1146{ 1147 {"e", ISA_SPEC_CLASS_20191213, 1, 9, 0 }, 1148 {"e", ISA_SPEC_CLASS_20190608, 1, 9, 0 }, 1149 {"e", ISA_SPEC_CLASS_2P2, 1, 9, 0 }, 1150 {"i", ISA_SPEC_CLASS_20191213, 2, 1, 0 }, 1151 {"i", ISA_SPEC_CLASS_20190608, 2, 1, 0 }, 1152 {"i", ISA_SPEC_CLASS_2P2, 2, 0, 0 }, 1153 /* The g is a special case which we don't want to output it, 1154 but still need it when adding implicit extensions. */ 1155 {"g", ISA_SPEC_CLASS_NONE, RISCV_UNKNOWN_VERSION, RISCV_UNKNOWN_VERSION, EXT_DEFAULT }, 1156 {"m", ISA_SPEC_CLASS_20191213, 2, 0, 0 }, 1157 {"m", ISA_SPEC_CLASS_20190608, 2, 0, 0 }, 1158 {"m", ISA_SPEC_CLASS_2P2, 2, 0, 0 }, 1159 {"a", ISA_SPEC_CLASS_20191213, 2, 1, 0 }, 1160 {"a", ISA_SPEC_CLASS_20190608, 2, 0, 0 }, 1161 {"a", ISA_SPEC_CLASS_2P2, 2, 0, 0 }, 1162 {"f", ISA_SPEC_CLASS_20191213, 2, 2, 0 }, 1163 {"f", ISA_SPEC_CLASS_20190608, 2, 2, 0 }, 1164 {"f", ISA_SPEC_CLASS_2P2, 2, 0, 0 }, 1165 {"d", ISA_SPEC_CLASS_20191213, 2, 2, 0 }, 1166 {"d", ISA_SPEC_CLASS_20190608, 2, 2, 0 }, 1167 {"d", ISA_SPEC_CLASS_2P2, 2, 0, 0 }, 1168 {"q", ISA_SPEC_CLASS_20191213, 2, 2, 0 }, 1169 {"q", ISA_SPEC_CLASS_20190608, 2, 2, 0 }, 1170 {"q", ISA_SPEC_CLASS_2P2, 2, 0, 0 }, 1171 {"c", ISA_SPEC_CLASS_20191213, 2, 0, 0 }, 1172 {"c", ISA_SPEC_CLASS_20190608, 2, 0, 0 }, 1173 {"c", ISA_SPEC_CLASS_2P2, 2, 0, 0 }, 1174 {"v", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, 1175 {"h", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, 1176 {NULL, 0, 0, 0, 0} 1177}; 1178 1179static struct riscv_supported_ext riscv_supported_std_z_ext[] = 1180{ 1181 {"zicbom", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, 1182 {"zicbop", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, 1183 {"zicboz", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, 1184 {"zicsr", ISA_SPEC_CLASS_20191213, 2, 0, 0 }, 1185 {"zicsr", ISA_SPEC_CLASS_20190608, 2, 0, 0 }, 1186 {"zifencei", ISA_SPEC_CLASS_20191213, 2, 0, 0 }, 1187 {"zifencei", ISA_SPEC_CLASS_20190608, 2, 0, 0 }, 1188 {"zihintpause", ISA_SPEC_CLASS_DRAFT, 2, 0, 0 }, 1189 {"zfh", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, 1190 {"zfhmin", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, 1191 {"zfinx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, 1192 {"zdinx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, 1193 {"zqinx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, 1194 {"zhinx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, 1195 {"zhinxmin", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, 1196 {"zbb", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, 1197 {"zba", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, 1198 {"zbc", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, 1199 {"zbs", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, 1200 {"zbkb", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, 1201 {"zbkc", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, 1202 {"zbkx", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, 1203 {"zk", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, 1204 {"zkn", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, 1205 {"zknd", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, 1206 {"zkne", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, 1207 {"zknh", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, 1208 {"zkr", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, 1209 {"zks", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, 1210 {"zksed", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, 1211 {"zksh", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, 1212 {"zkt", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, 1213 {"zve32x", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, 1214 {"zve32f", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, 1215 {"zve32d", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, 1216 {"zve64x", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, 1217 {"zve64f", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, 1218 {"zve64d", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, 1219 {"zvl32b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, 1220 {"zvl64b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, 1221 {"zvl128b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, 1222 {"zvl256b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, 1223 {"zvl512b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, 1224 {"zvl1024b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, 1225 {"zvl2048b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, 1226 {"zvl4096b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, 1227 {"zvl8192b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, 1228 {"zvl16384b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, 1229 {"zvl32768b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, 1230 {"zvl65536b", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, 1231 {NULL, 0, 0, 0, 0} 1232}; 1233 1234static struct riscv_supported_ext riscv_supported_std_s_ext[] = 1235{ 1236 {"smstateen", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, 1237 {"sscofpmf", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, 1238 {"sstc", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, 1239 {"svinval", ISA_SPEC_CLASS_DRAFT, 1, 0, 0 }, 1240 {NULL, 0, 0, 0, 0} 1241}; 1242 1243static struct riscv_supported_ext riscv_supported_std_zxm_ext[] = 1244{ 1245 {NULL, 0, 0, 0, 0} 1246}; 1247 1248const struct riscv_supported_ext *riscv_all_supported_ext[] = 1249{ 1250 riscv_supported_std_ext, 1251 riscv_supported_std_z_ext, 1252 riscv_supported_std_s_ext, 1253 riscv_supported_std_zxm_ext, 1254 NULL 1255}; 1256 1257/* ISA extension prefixed name class. Must define them in parsing order. */ 1258enum riscv_prefix_ext_class 1259{ 1260 RV_ISA_CLASS_Z = 1, 1261 RV_ISA_CLASS_S, 1262 RV_ISA_CLASS_ZXM, 1263 RV_ISA_CLASS_X, 1264 RV_ISA_CLASS_UNKNOWN 1265}; 1266 1267/* Record the strings of the prefixed extensions, and their corresponding 1268 classes. The more letters of the prefix string, the more forward it must 1269 be defined. Otherwise, the riscv_get_prefix_class will map it to the 1270 wrong classes. */ 1271struct riscv_parse_prefix_config 1272{ 1273 /* Class of the extension. */ 1274 enum riscv_prefix_ext_class class; 1275 1276 /* Prefix string for error printing and internal parser usage. */ 1277 const char *prefix; 1278}; 1279static const struct riscv_parse_prefix_config parse_config[] = 1280{ 1281 {RV_ISA_CLASS_ZXM, "zxm"}, 1282 {RV_ISA_CLASS_Z, "z"}, 1283 {RV_ISA_CLASS_S, "s"}, 1284 {RV_ISA_CLASS_X, "x"}, 1285 {RV_ISA_CLASS_UNKNOWN, NULL} 1286}; 1287 1288/* Get the prefixed name class for the extensions, the class also 1289 means the order of the prefixed extensions. */ 1290 1291static enum riscv_prefix_ext_class 1292riscv_get_prefix_class (const char *arch) 1293{ 1294 int i = 0; 1295 while (parse_config[i].class != RV_ISA_CLASS_UNKNOWN) 1296 { 1297 if (strncmp (arch, parse_config[i].prefix, 1298 strlen (parse_config[i].prefix)) == 0) 1299 return parse_config[i].class; 1300 i++; 1301 } 1302 return RV_ISA_CLASS_UNKNOWN; 1303} 1304 1305/* Check KNOWN_EXTS to see if the EXT is supported. */ 1306 1307static bool 1308riscv_known_prefixed_ext (const char *ext, 1309 struct riscv_supported_ext *known_exts) 1310{ 1311 size_t i; 1312 for (i = 0; known_exts[i].name != NULL; ++i) 1313 if (strcmp (ext, known_exts[i].name) == 0) 1314 return true; 1315 return false; 1316} 1317 1318/* Check whether the prefixed extension is recognized or not. Return 1319 true if recognized, otehrwise return false. */ 1320 1321static bool 1322riscv_recognized_prefixed_ext (const char *ext) 1323{ 1324 enum riscv_prefix_ext_class class = riscv_get_prefix_class (ext); 1325 switch (class) 1326 { 1327 case RV_ISA_CLASS_Z: 1328 return riscv_known_prefixed_ext (ext, riscv_supported_std_z_ext); 1329 case RV_ISA_CLASS_ZXM: 1330 return riscv_known_prefixed_ext (ext, riscv_supported_std_zxm_ext); 1331 case RV_ISA_CLASS_S: 1332 return riscv_known_prefixed_ext (ext, riscv_supported_std_s_ext); 1333 case RV_ISA_CLASS_X: 1334 /* Only the single x is unrecognized. */ 1335 if (strcmp (ext, "x") != 0) 1336 return true; 1337 default: 1338 break; 1339 } 1340 return false; 1341} 1342 1343/* Canonical order for single letter extensions. */ 1344static const char riscv_ext_canonical_order[] = "eigmafdqlcbkjtpvnh"; 1345 1346/* Array is used to compare the orders of standard extensions quickly. */ 1347static int riscv_ext_order[26] = {0}; 1348 1349/* Init the riscv_ext_order array. */ 1350 1351static void 1352riscv_init_ext_order (void) 1353{ 1354 static bool inited = false; 1355 if (inited) 1356 return; 1357 1358 /* The orders of all standard extensions are positive. */ 1359 int order = 1; 1360 1361 for (const char *ext = &riscv_ext_canonical_order[0]; *ext; ++ext) 1362 riscv_ext_order[(*ext - 'a')] = order++; 1363 1364 /* Some of the prefixed keyword are not single letter, so we set 1365 their prefixed orders in the riscv_compare_subsets directly, 1366 not through the riscv_ext_order. */ 1367 1368 inited = true; 1369} 1370 1371/* Similar to the strcmp. It returns an integer less than, equal to, 1372 or greater than zero if `subset2` is found, respectively, to be less 1373 than, to match, or be greater than `subset1`. 1374 1375 The order values, 1376 Zero: Preserved keywords. 1377 Positive number: Standard extensions. 1378 Negative number: Prefixed keywords. */ 1379 1380int 1381riscv_compare_subsets (const char *subset1, const char *subset2) 1382{ 1383 int order1 = riscv_ext_order[(*subset1 - 'a')]; 1384 int order2 = riscv_ext_order[(*subset2 - 'a')]; 1385 1386 /* Compare the standard extension first. */ 1387 if (order1 > 0 && order2 > 0) 1388 return order1 - order2; 1389 1390 /* Set the prefixed orders to negative numbers. */ 1391 enum riscv_prefix_ext_class class1 = riscv_get_prefix_class (subset1); 1392 enum riscv_prefix_ext_class class2 = riscv_get_prefix_class (subset2); 1393 1394 if (class1 != RV_ISA_CLASS_UNKNOWN) 1395 order1 = - (int) class1; 1396 if (class2 != RV_ISA_CLASS_UNKNOWN) 1397 order2 = - (int) class2; 1398 1399 if (order1 == order2) 1400 { 1401 /* Compare the standard addition z extensions. */ 1402 if (class1 == RV_ISA_CLASS_Z) 1403 { 1404 order1 = riscv_ext_order[(*++subset1 - 'a')]; 1405 order2 = riscv_ext_order[(*++subset2 - 'a')]; 1406 if (order1 != order2) 1407 return order1 - order2; 1408 } 1409 return strcasecmp (++subset1, ++subset2); 1410 } 1411 1412 return order2 - order1; 1413} 1414 1415/* Find subset in the list. Return TRUE and set `current` to the subset 1416 if it is found. Otherwise, return FALSE and set `current` to the place 1417 where we should insert the subset. However, return FALSE with the NULL 1418 `current` means we should insert the subset at the head of subset list, 1419 if needed. */ 1420 1421bool 1422riscv_lookup_subset (const riscv_subset_list_t *subset_list, 1423 const char *subset, 1424 riscv_subset_t **current) 1425{ 1426 riscv_subset_t *s, *pre_s = NULL; 1427 1428 /* If the subset is added in order, then just add it at the tail. */ 1429 if (subset_list->tail != NULL 1430 && riscv_compare_subsets (subset_list->tail->name, subset) < 0) 1431 { 1432 *current = subset_list->tail; 1433 return false; 1434 } 1435 1436 for (s = subset_list->head; 1437 s != NULL; 1438 pre_s = s, s = s->next) 1439 { 1440 int cmp = riscv_compare_subsets (s->name, subset); 1441 if (cmp == 0) 1442 { 1443 *current = s; 1444 return true; 1445 } 1446 else if (cmp > 0) 1447 break; 1448 } 1449 *current = pre_s; 1450 1451 return false; 1452} 1453 1454/* Add the extension to the subset list. Search the 1455 list first, and then find the right place to add. */ 1456 1457void 1458riscv_add_subset (riscv_subset_list_t *subset_list, 1459 const char *subset, 1460 int major, 1461 int minor) 1462{ 1463 riscv_subset_t *current, *new; 1464 1465 if (riscv_lookup_subset (subset_list, subset, ¤t)) 1466 return; 1467 1468 new = xmalloc (sizeof *new); 1469 new->name = xstrdup (subset); 1470 new->major_version = major; 1471 new->minor_version = minor; 1472 new->next = NULL; 1473 1474 if (current != NULL) 1475 { 1476 new->next = current->next; 1477 current->next = new; 1478 } 1479 else 1480 { 1481 new->next = subset_list->head; 1482 subset_list->head = new; 1483 } 1484 1485 if (new->next == NULL) 1486 subset_list->tail = new; 1487} 1488 1489/* Get the default versions from the riscv_supported_*ext tables. */ 1490 1491static void 1492riscv_get_default_ext_version (enum riscv_spec_class *default_isa_spec, 1493 const char *name, 1494 int *major_version, 1495 int *minor_version) 1496{ 1497 if (name == NULL 1498 || default_isa_spec == NULL 1499 || *default_isa_spec == ISA_SPEC_CLASS_NONE) 1500 return; 1501 1502 struct riscv_supported_ext *table = NULL; 1503 enum riscv_prefix_ext_class class = riscv_get_prefix_class (name); 1504 switch (class) 1505 { 1506 case RV_ISA_CLASS_ZXM: table = riscv_supported_std_zxm_ext; break; 1507 case RV_ISA_CLASS_Z: table = riscv_supported_std_z_ext; break; 1508 case RV_ISA_CLASS_S: table = riscv_supported_std_s_ext; break; 1509 case RV_ISA_CLASS_X: 1510 break; 1511 default: 1512 table = riscv_supported_std_ext; 1513 } 1514 1515 int i = 0; 1516 while (table != NULL && table[i].name != NULL) 1517 { 1518 if (strcmp (table[i].name, name) == 0 1519 && (table[i].isa_spec_class == ISA_SPEC_CLASS_DRAFT 1520 || table[i].isa_spec_class == *default_isa_spec)) 1521 { 1522 *major_version = table[i].major_version; 1523 *minor_version = table[i].minor_version; 1524 return; 1525 } 1526 i++; 1527 } 1528} 1529 1530/* Find the default versions for the extension before adding them to 1531 the subset list, if their versions are RISCV_UNKNOWN_VERSION. 1532 Afterwards, report errors if we can not find their default versions. */ 1533 1534static void 1535riscv_parse_add_subset (riscv_parse_subset_t *rps, 1536 const char *subset, 1537 int major, 1538 int minor, 1539 bool implicit) 1540{ 1541 int major_version = major; 1542 int minor_version = minor; 1543 1544 if (major_version == RISCV_UNKNOWN_VERSION 1545 || minor_version == RISCV_UNKNOWN_VERSION) 1546 riscv_get_default_ext_version (rps->isa_spec, subset, 1547 &major_version, &minor_version); 1548 1549 /* We don't care the versions of the implicit extensions. */ 1550 if (!implicit 1551 && (major_version == RISCV_UNKNOWN_VERSION 1552 || minor_version == RISCV_UNKNOWN_VERSION)) 1553 { 1554 if (subset[0] == 'x') 1555 rps->error_handler 1556 (_("x ISA extension `%s' must be set with the versions"), 1557 subset); 1558 /* Allow old ISA spec can recognize zicsr and zifencei. */ 1559 else if (strcmp (subset, "zicsr") != 0 1560 && strcmp (subset, "zifencei") != 0) 1561 rps->error_handler 1562 (_("cannot find default versions of the ISA extension `%s'"), 1563 subset); 1564 return; 1565 } 1566 1567 riscv_add_subset (rps->subset_list, subset, 1568 major_version, minor_version); 1569} 1570 1571/* Release subset list. */ 1572 1573void 1574riscv_release_subset_list (riscv_subset_list_t *subset_list) 1575{ 1576 while (subset_list->head != NULL) 1577 { 1578 riscv_subset_t *next = subset_list->head->next; 1579 free ((void *)subset_list->head->name); 1580 free (subset_list->head); 1581 subset_list->head = next; 1582 } 1583 1584 subset_list->tail = NULL; 1585} 1586 1587/* Parsing extension version. 1588 1589 Return Value: 1590 Points to the end of version 1591 1592 Arguments: 1593 `p`: Curent parsing position. 1594 `major_version`: Parsed major version. 1595 `minor_version`: Parsed minor version. */ 1596 1597static const char * 1598riscv_parsing_subset_version (const char *p, 1599 int *major_version, 1600 int *minor_version) 1601{ 1602 bool major_p = true; 1603 int version = 0; 1604 char np; 1605 1606 *major_version = 0; 1607 *minor_version = 0; 1608 for (; *p; ++p) 1609 { 1610 if (*p == 'p') 1611 { 1612 np = *(p + 1); 1613 1614 /* Might be beginning of `p` extension. */ 1615 if (!ISDIGIT (np)) 1616 break; 1617 1618 *major_version = version; 1619 major_p = false; 1620 version = 0; 1621 } 1622 else if (ISDIGIT (*p)) 1623 version = (version * 10) + (*p - '0'); 1624 else 1625 break; 1626 } 1627 1628 if (major_p) 1629 *major_version = version; 1630 else 1631 *minor_version = version; 1632 1633 /* We can not find any version in string. */ 1634 if (*major_version == 0 && *minor_version == 0) 1635 { 1636 *major_version = RISCV_UNKNOWN_VERSION; 1637 *minor_version = RISCV_UNKNOWN_VERSION; 1638 } 1639 1640 return p; 1641} 1642 1643/* Parsing function for standard extensions. 1644 1645 Return Value: 1646 Points to the end of extensions. 1647 1648 Arguments: 1649 `rps`: Hooks and status for parsing extensions. 1650 `arch`: Full ISA string. 1651 `p`: Curent parsing position. */ 1652 1653static const char * 1654riscv_parse_std_ext (riscv_parse_subset_t *rps, 1655 const char *arch, 1656 const char *p) 1657{ 1658 /* First letter must start with i, e or g. */ 1659 if (*p != 'e' && *p != 'i' && *p != 'g') 1660 { 1661 rps->error_handler 1662 (_("%s: first ISA extension must be `e', `i' or `g'"), 1663 arch); 1664 return NULL; 1665 } 1666 1667 while (p != NULL && *p != '\0') 1668 { 1669 /* Stop when we parsed the known prefix class. */ 1670 enum riscv_prefix_ext_class class = riscv_get_prefix_class (p); 1671 if (class != RV_ISA_CLASS_UNKNOWN) 1672 break; 1673 1674 if (*p == '_') 1675 { 1676 p++; 1677 continue; 1678 } 1679 1680 bool implicit = false; 1681 int major = RISCV_UNKNOWN_VERSION; 1682 int minor = RISCV_UNKNOWN_VERSION; 1683 char subset[2] = {0, 0}; 1684 1685 subset[0] = *p; 1686 1687 /* Check if the standard extension is supported. */ 1688 if (riscv_ext_order[(subset[0] - 'a')] == 0) 1689 { 1690 rps->error_handler 1691 (_("%s: unknown standard ISA extension `%c'"), 1692 arch, subset[0]); 1693 return NULL; 1694 } 1695 1696 /* Checking canonical order. */ 1697 if (rps->subset_list->tail != NULL 1698 && riscv_compare_subsets (rps->subset_list->tail->name, subset) > 0) 1699 { 1700 rps->error_handler 1701 (_("%s: standard ISA extension `%c' is not " 1702 "in canonical order"), arch, subset[0]); 1703 return NULL; 1704 } 1705 1706 p = riscv_parsing_subset_version (++p, &major, &minor); 1707 /* Added g as an implicit extension. */ 1708 if (subset[0] == 'g') 1709 { 1710 implicit = true; 1711 major = RISCV_UNKNOWN_VERSION; 1712 minor = RISCV_UNKNOWN_VERSION; 1713 } 1714 riscv_parse_add_subset (rps, subset, major, minor, implicit); 1715 } 1716 1717 return p; 1718} 1719 1720/* Parsing function for prefixed extensions. 1721 1722 Return Value: 1723 Points to the end of extension. 1724 1725 Arguments: 1726 `rps`: Hooks and status for parsing extensions. 1727 `arch`: Full ISA string. 1728 `p`: Curent parsing position. */ 1729 1730static const char * 1731riscv_parse_prefixed_ext (riscv_parse_subset_t *rps, 1732 const char *arch, 1733 const char *p) 1734{ 1735 int major_version; 1736 int minor_version; 1737 enum riscv_prefix_ext_class class; 1738 1739 while (*p) 1740 { 1741 if (*p == '_') 1742 { 1743 p++; 1744 continue; 1745 } 1746 1747 class = riscv_get_prefix_class (p); 1748 if (class == RV_ISA_CLASS_UNKNOWN) 1749 { 1750 rps->error_handler 1751 (_("%s: unknown prefix class for the ISA extension `%s'"), 1752 arch, p); 1753 return NULL; 1754 } 1755 1756 char *subset = xstrdup (p); 1757 char *q = subset; 1758 const char *end_of_version; 1759 1760 /* Extract the whole prefixed extension by '_'. */ 1761 while (*++q != '\0' && *q != '_') 1762 ; 1763 /* Look forward to the first letter which is not <major>p<minor>. */ 1764 bool find_any_version = false; 1765 bool find_minor_version = false; 1766 while (1) 1767 { 1768 q--; 1769 if (ISDIGIT (*q)) 1770 find_any_version = true; 1771 else if (find_any_version 1772 && !find_minor_version 1773 && *q == 'p' 1774 && ISDIGIT (*(q - 1))) 1775 find_minor_version = true; 1776 else 1777 break; 1778 } 1779 q++; 1780 1781 /* Check if the end of extension is 'p' or not. If yes, then 1782 the second letter from the end cannot be number. */ 1783 if (*(q - 1) == 'p' && ISDIGIT (*(q - 2))) 1784 { 1785 *q = '\0'; 1786 rps->error_handler 1787 (_("%s: invalid prefixed ISA extension `%s' ends with <number>p"), 1788 arch, subset); 1789 free (subset); 1790 return NULL; 1791 } 1792 1793 end_of_version = 1794 riscv_parsing_subset_version (q, &major_version, &minor_version); 1795 *q = '\0'; 1796 if (end_of_version == NULL) 1797 { 1798 free (subset); 1799 return NULL; 1800 } 1801 1802 /* Check that the extension name is well-formed. */ 1803 if (rps->check_unknown_prefixed_ext 1804 && !riscv_recognized_prefixed_ext (subset)) 1805 { 1806 rps->error_handler 1807 (_("%s: unknown prefixed ISA extension `%s'"), 1808 arch, subset); 1809 free (subset); 1810 return NULL; 1811 } 1812 1813 riscv_parse_add_subset (rps, subset, 1814 major_version, 1815 minor_version, false); 1816 p += end_of_version - subset; 1817 free (subset); 1818 1819 if (*p != '\0' && *p != '_') 1820 { 1821 rps->error_handler 1822 (_("%s: prefixed ISA extension must separate with _"), 1823 arch); 1824 return NULL; 1825 } 1826 } 1827 1828 return p; 1829} 1830 1831/* Add the implicit extensions. */ 1832 1833static void 1834riscv_parse_add_implicit_subsets (riscv_parse_subset_t *rps) 1835{ 1836 struct riscv_implicit_subset *t = riscv_implicit_subsets; 1837 for (; t->subset_name; t++) 1838 { 1839 riscv_subset_t *subset = NULL; 1840 if (riscv_lookup_subset (rps->subset_list, t->subset_name, &subset) 1841 && t->check_func (t->implicit_name, subset)) 1842 riscv_parse_add_subset (rps, t->implicit_name, 1843 RISCV_UNKNOWN_VERSION, 1844 RISCV_UNKNOWN_VERSION, true); 1845 } 1846} 1847 1848/* Check extensions conflicts. */ 1849 1850static bool 1851riscv_parse_check_conflicts (riscv_parse_subset_t *rps) 1852{ 1853 riscv_subset_t *subset = NULL; 1854 int xlen = *rps->xlen; 1855 bool no_conflict = true; 1856 1857 if (riscv_lookup_subset (rps->subset_list, "e", &subset) 1858 && xlen > 32) 1859 { 1860 rps->error_handler 1861 (_("rv%d does not support the `e' extension"), xlen); 1862 no_conflict = false; 1863 } 1864 if (riscv_lookup_subset (rps->subset_list, "q", &subset) 1865 && (subset->major_version < 2 || (subset->major_version == 2 1866 && subset->minor_version < 2)) 1867 && xlen < 64) 1868 { 1869 rps->error_handler (_("rv%d does not support the `q' extension"), xlen); 1870 no_conflict = false; 1871 } 1872 if (riscv_lookup_subset (rps->subset_list, "e", &subset) 1873 && riscv_lookup_subset (rps->subset_list, "f", &subset)) 1874 { 1875 rps->error_handler 1876 (_("rv32e does not support the `f' extension")); 1877 no_conflict = false; 1878 } 1879 if (riscv_lookup_subset (rps->subset_list, "zfinx", &subset) 1880 && riscv_lookup_subset (rps->subset_list, "f", &subset)) 1881 { 1882 rps->error_handler 1883 (_("`zfinx' is conflict with the `f/d/q/zfh/zfhmin' extension")); 1884 no_conflict = false; 1885 } 1886 1887 bool support_zve = false; 1888 bool support_zvl = false; 1889 riscv_subset_t *s = rps->subset_list->head; 1890 for (; s != NULL; s = s->next) 1891 { 1892 if (!support_zve 1893 && strncmp (s->name, "zve", 3) == 0) 1894 support_zve = true; 1895 if (!support_zvl 1896 && strncmp (s->name, "zvl", 3) == 0) 1897 support_zvl = true; 1898 if (support_zve && support_zvl) 1899 break; 1900 } 1901 if (support_zvl && !support_zve) 1902 { 1903 rps->error_handler 1904 (_("zvl*b extensions need to enable either `v' or `zve' extension")); 1905 no_conflict = false; 1906 } 1907 1908 return no_conflict; 1909} 1910 1911/* Set the default subset list according to the default_enable field 1912 of riscv_supported_*ext tables. */ 1913 1914static void 1915riscv_set_default_arch (riscv_parse_subset_t *rps) 1916{ 1917 unsigned long enable = EXT_DEFAULT; 1918 int i, j; 1919 for (i = 0; riscv_all_supported_ext[i] != NULL; i++) 1920 { 1921 const struct riscv_supported_ext *table = riscv_all_supported_ext[i]; 1922 for (j = 0; table[j].name != NULL; j++) 1923 { 1924 bool implicit = false; 1925 if (strcmp (table[j].name, "g") == 0) 1926 implicit = true; 1927 if (table[j].default_enable & enable) 1928 riscv_parse_add_subset (rps, table[j].name, 1929 RISCV_UNKNOWN_VERSION, 1930 RISCV_UNKNOWN_VERSION, implicit); 1931 } 1932 } 1933} 1934 1935/* Function for parsing ISA string. 1936 1937 Return Value: 1938 Return TRUE on success. 1939 1940 Arguments: 1941 `rps`: Hooks and status for parsing extensions. 1942 `arch`: Full ISA string. */ 1943 1944bool 1945riscv_parse_subset (riscv_parse_subset_t *rps, 1946 const char *arch) 1947{ 1948 const char *p; 1949 1950 /* Init the riscv_ext_order array to compare the order of extensions 1951 quickly. */ 1952 riscv_init_ext_order (); 1953 1954 if (arch == NULL) 1955 { 1956 riscv_set_default_arch (rps); 1957 riscv_parse_add_implicit_subsets (rps); 1958 return riscv_parse_check_conflicts (rps); 1959 } 1960 1961 for (p = arch; *p != '\0'; p++) 1962 { 1963 if (ISUPPER (*p)) 1964 { 1965 rps->error_handler 1966 (_("%s: ISA string cannot contain uppercase letters"), 1967 arch); 1968 return false; 1969 } 1970 } 1971 1972 p = arch; 1973 if (startswith (p, "rv32")) 1974 { 1975 *rps->xlen = 32; 1976 p += 4; 1977 } 1978 else if (startswith (p, "rv64")) 1979 { 1980 *rps->xlen = 64; 1981 p += 4; 1982 } 1983 else 1984 { 1985 /* ISA string shouldn't be NULL or empty here. For linker, 1986 it might be empty when we failed to merge the ISA string 1987 in the riscv_merge_attributes. For assembler, we might 1988 give an empty string by .attribute arch, "" or -march=. 1989 However, We have already issued the correct error message 1990 in another side, so do not issue this error when the ISA 1991 string is empty. */ 1992 if (strlen (arch)) 1993 rps->error_handler ( 1994 _("%s: ISA string must begin with rv32 or rv64"), 1995 arch); 1996 return false; 1997 } 1998 1999 /* Parsing standard extension. */ 2000 p = riscv_parse_std_ext (rps, arch, p); 2001 2002 if (p == NULL) 2003 return false; 2004 2005 /* Parse prefixed extensions. */ 2006 p = riscv_parse_prefixed_ext (rps, arch, p); 2007 2008 if (p == NULL) 2009 return false; 2010 2011 /* Finally add implicit extensions according to the current 2012 extensions. */ 2013 riscv_parse_add_implicit_subsets (rps); 2014 2015 /* Check the conflicts. */ 2016 return riscv_parse_check_conflicts (rps); 2017} 2018 2019/* Return the number of digits for the input. */ 2020 2021size_t 2022riscv_estimate_digit (unsigned num) 2023{ 2024 size_t digit = 0; 2025 if (num == 0) 2026 return 1; 2027 2028 for (digit = 0; num ; num /= 10) 2029 digit++; 2030 2031 return digit; 2032} 2033 2034/* Auxiliary function to estimate string length of subset list. */ 2035 2036static size_t 2037riscv_estimate_arch_strlen1 (const riscv_subset_t *subset) 2038{ 2039 if (subset == NULL) 2040 return 6; /* For rv32/rv64/rv128 and string terminator. */ 2041 2042 return riscv_estimate_arch_strlen1 (subset->next) 2043 + strlen (subset->name) 2044 + riscv_estimate_digit (subset->major_version) 2045 + 1 /* For version seperator 'p'. */ 2046 + riscv_estimate_digit (subset->minor_version) 2047 + 1 /* For underscore. */; 2048} 2049 2050/* Estimate the string length of this subset list. */ 2051 2052static size_t 2053riscv_estimate_arch_strlen (const riscv_subset_list_t *subset_list) 2054{ 2055 return riscv_estimate_arch_strlen1 (subset_list->head); 2056} 2057 2058/* Auxiliary function to convert subset info to string. */ 2059 2060static void 2061riscv_arch_str1 (riscv_subset_t *subset, 2062 char *attr_str, char *buf, size_t bufsz) 2063{ 2064 const char *underline = "_"; 2065 riscv_subset_t *subset_t = subset; 2066 2067 if (subset_t == NULL) 2068 return; 2069 2070 /* No underline between rvXX and i/e. */ 2071 if ((strcasecmp (subset_t->name, "i") == 0) 2072 || (strcasecmp (subset_t->name, "e") == 0)) 2073 underline = ""; 2074 2075 snprintf (buf, bufsz, "%s%s%dp%d", 2076 underline, 2077 subset_t->name, 2078 subset_t->major_version, 2079 subset_t->minor_version); 2080 2081 strncat (attr_str, buf, bufsz); 2082 2083 /* Skip 'i' extension after 'e', or skip extensions which 2084 versions are unknown. */ 2085 while (subset_t->next 2086 && ((strcmp (subset_t->name, "e") == 0 2087 && strcmp (subset_t->next->name, "i") == 0) 2088 || subset_t->next->major_version == RISCV_UNKNOWN_VERSION 2089 || subset_t->next->minor_version == RISCV_UNKNOWN_VERSION)) 2090 subset_t = subset_t->next; 2091 2092 riscv_arch_str1 (subset_t->next, attr_str, buf, bufsz); 2093} 2094 2095/* Convert subset information into string with explicit versions. */ 2096 2097char * 2098riscv_arch_str (unsigned xlen, const riscv_subset_list_t *subset) 2099{ 2100 size_t arch_str_len = riscv_estimate_arch_strlen (subset); 2101 char *attr_str = xmalloc (arch_str_len); 2102 char *buf = xmalloc (arch_str_len); 2103 2104 snprintf (attr_str, arch_str_len, "rv%u", xlen); 2105 2106 riscv_arch_str1 (subset->head, attr_str, buf, arch_str_len); 2107 free (buf); 2108 2109 return attr_str; 2110} 2111 2112/* Copy the subset in the subset list. */ 2113 2114static struct riscv_subset_t * 2115riscv_copy_subset (riscv_subset_list_t *subset_list, 2116 riscv_subset_t *subset) 2117{ 2118 if (subset == NULL) 2119 return NULL; 2120 2121 riscv_subset_t *new = xmalloc (sizeof *new); 2122 new->name = xstrdup (subset->name); 2123 new->major_version = subset->major_version; 2124 new->minor_version = subset->minor_version; 2125 new->next = riscv_copy_subset (subset_list, subset->next); 2126 2127 if (subset->next == NULL) 2128 subset_list->tail = new; 2129 2130 return new; 2131} 2132 2133/* Copy the subset list. */ 2134 2135riscv_subset_list_t * 2136riscv_copy_subset_list (riscv_subset_list_t *subset_list) 2137{ 2138 riscv_subset_list_t *new = xmalloc (sizeof *new); 2139 new->head = riscv_copy_subset (new, subset_list->head); 2140 return new; 2141} 2142 2143/* Remove the SUBSET from the subset list. */ 2144 2145static void 2146riscv_remove_subset (riscv_subset_list_t *subset_list, 2147 const char *subset) 2148{ 2149 riscv_subset_t *current = subset_list->head; 2150 riscv_subset_t *pre = NULL; 2151 for (; current != NULL; pre = current, current = current->next) 2152 { 2153 if (strcmp (current->name, subset) == 0) 2154 { 2155 if (pre == NULL) 2156 subset_list->head = current->next; 2157 else 2158 pre->next = current->next; 2159 if (current->next == NULL) 2160 subset_list->tail = pre; 2161 free ((void *) current->name); 2162 free (current); 2163 break; 2164 } 2165 } 2166} 2167 2168/* Add/Remove an extension to/from the subset list. This is used for 2169 the .option rvc or norvc, and .option arch directives. */ 2170 2171bool 2172riscv_update_subset (riscv_parse_subset_t *rps, 2173 const char *str) 2174{ 2175 const char *p = str; 2176 2177 do 2178 { 2179 int major_version = RISCV_UNKNOWN_VERSION; 2180 int minor_version = RISCV_UNKNOWN_VERSION; 2181 2182 bool removed = false; 2183 switch (*p) 2184 { 2185 case '+': removed = false; break; 2186 case '-': removed = true; break; 2187 default: 2188 riscv_release_subset_list (rps->subset_list); 2189 return riscv_parse_subset (rps, p); 2190 } 2191 ++p; 2192 2193 char *subset = xstrdup (p); 2194 char *q = subset; 2195 const char *end_of_version; 2196 /* Extract the whole prefixed extension by ','. */ 2197 while (*q != '\0' && *q != ',') 2198 q++; 2199 2200 /* Look forward to the first letter which is not <major>p<minor>. */ 2201 bool find_any_version = false; 2202 bool find_minor_version = false; 2203 size_t len = q - subset; 2204 size_t i; 2205 for (i = len; i > 0; i--) 2206 { 2207 q--; 2208 if (ISDIGIT (*q)) 2209 find_any_version = true; 2210 else if (find_any_version 2211 && !find_minor_version 2212 && *q == 'p' 2213 && ISDIGIT (*(q - 1))) 2214 find_minor_version = true; 2215 else 2216 break; 2217 } 2218 if (len > 0) 2219 q++; 2220 2221 /* Check if the end of extension is 'p' or not. If yes, then 2222 the second letter from the end cannot be number. */ 2223 if (len > 1 && *(q - 1) == 'p' && ISDIGIT (*(q - 2))) 2224 { 2225 *q = '\0'; 2226 rps->error_handler 2227 (_("invalid ISA extension ends with <number>p " 2228 "in .option arch `%s'"), str); 2229 free (subset); 2230 return false; 2231 } 2232 2233 end_of_version = 2234 riscv_parsing_subset_version (q, &major_version, &minor_version); 2235 *q = '\0'; 2236 if (end_of_version == NULL) 2237 { 2238 free (subset); 2239 return false; 2240 } 2241 2242 if (strlen (subset) == 0 2243 || (strlen (subset) == 1 2244 && riscv_ext_order[(*subset - 'a')] == 0) 2245 || (strlen (subset) > 1 2246 && rps->check_unknown_prefixed_ext 2247 && !riscv_recognized_prefixed_ext (subset))) 2248 { 2249 rps->error_handler 2250 (_("unknown ISA extension `%s' in .option arch `%s'"), 2251 subset, str); 2252 free (subset); 2253 return false; 2254 } 2255 2256 if (strcmp (subset, "i") == 0 2257 || strcmp (subset, "e") == 0 2258 || strcmp (subset, "g") == 0) 2259 { 2260 rps->error_handler 2261 (_("cannot + or - base extension `%s' in .option " 2262 "arch `%s'"), subset, str); 2263 free (subset); 2264 return false; 2265 } 2266 2267 if (removed) 2268 riscv_remove_subset (rps->subset_list, subset); 2269 else 2270 riscv_parse_add_subset (rps, subset, major_version, minor_version, true); 2271 p += end_of_version - subset; 2272 free (subset); 2273 } 2274 while (*p++ == ','); 2275 2276 riscv_parse_add_implicit_subsets (rps); 2277 return riscv_parse_check_conflicts (rps); 2278} 2279 2280/* Check if the FEATURE subset is supported or not in the subset list. 2281 Return true if it is supported; Otherwise, return false. */ 2282 2283bool 2284riscv_subset_supports (riscv_parse_subset_t *rps, 2285 const char *feature) 2286{ 2287 struct riscv_subset_t *subset; 2288 return riscv_lookup_subset (rps->subset_list, feature, &subset); 2289} 2290 2291/* Each instuction is belonged to an instruction class INSN_CLASS_*. 2292 Call riscv_subset_supports to make sure if the instuction is valid. */ 2293 2294bool 2295riscv_multi_subset_supports (riscv_parse_subset_t *rps, 2296 enum riscv_insn_class insn_class) 2297{ 2298 switch (insn_class) 2299 { 2300 case INSN_CLASS_I: 2301 return riscv_subset_supports (rps, "i"); 2302 case INSN_CLASS_ZICBOM: 2303 return riscv_subset_supports (rps, "zicbom"); 2304 case INSN_CLASS_ZICBOP: 2305 return riscv_subset_supports (rps, "zicbop"); 2306 case INSN_CLASS_ZICBOZ: 2307 return riscv_subset_supports (rps, "zicboz"); 2308 case INSN_CLASS_ZICSR: 2309 return riscv_subset_supports (rps, "zicsr"); 2310 case INSN_CLASS_ZIFENCEI: 2311 return riscv_subset_supports (rps, "zifencei"); 2312 case INSN_CLASS_ZIHINTPAUSE: 2313 return riscv_subset_supports (rps, "zihintpause"); 2314 case INSN_CLASS_M: 2315 return riscv_subset_supports (rps, "m"); 2316 case INSN_CLASS_A: 2317 return riscv_subset_supports (rps, "a"); 2318 case INSN_CLASS_F: 2319 return riscv_subset_supports (rps, "f"); 2320 case INSN_CLASS_D: 2321 return riscv_subset_supports (rps, "d"); 2322 case INSN_CLASS_Q: 2323 return riscv_subset_supports (rps, "q"); 2324 case INSN_CLASS_C: 2325 return riscv_subset_supports (rps, "c"); 2326 case INSN_CLASS_F_AND_C: 2327 return (riscv_subset_supports (rps, "f") 2328 && riscv_subset_supports (rps, "c")); 2329 case INSN_CLASS_D_AND_C: 2330 return (riscv_subset_supports (rps, "d") 2331 && riscv_subset_supports (rps, "c")); 2332 case INSN_CLASS_F_OR_ZFINX: 2333 return (riscv_subset_supports (rps, "f") 2334 || riscv_subset_supports (rps, "zfinx")); 2335 case INSN_CLASS_D_OR_ZDINX: 2336 return (riscv_subset_supports (rps, "d") 2337 || riscv_subset_supports (rps, "zdinx")); 2338 case INSN_CLASS_Q_OR_ZQINX: 2339 return (riscv_subset_supports (rps, "q") 2340 || riscv_subset_supports (rps, "zqinx")); 2341 case INSN_CLASS_ZFH_OR_ZHINX: 2342 return (riscv_subset_supports (rps, "zfh") 2343 || riscv_subset_supports (rps, "zhinx")); 2344 case INSN_CLASS_ZFHMIN: 2345 return riscv_subset_supports (rps, "zfhmin"); 2346 case INSN_CLASS_ZFHMIN_OR_ZHINXMIN: 2347 return (riscv_subset_supports (rps, "zfhmin") 2348 || riscv_subset_supports (rps, "zhinxmin")); 2349 case INSN_CLASS_ZFHMIN_AND_D: 2350 return ((riscv_subset_supports (rps, "zfhmin") 2351 && riscv_subset_supports (rps, "d")) 2352 || (riscv_subset_supports (rps, "zhinxmin") 2353 && riscv_subset_supports (rps, "zdinx"))); 2354 case INSN_CLASS_ZFHMIN_AND_Q: 2355 return ((riscv_subset_supports (rps, "zfhmin") 2356 && riscv_subset_supports (rps, "q")) 2357 || (riscv_subset_supports (rps, "zhinxmin") 2358 && riscv_subset_supports (rps, "zqinx"))); 2359 case INSN_CLASS_ZBA: 2360 return riscv_subset_supports (rps, "zba"); 2361 case INSN_CLASS_ZBB: 2362 return riscv_subset_supports (rps, "zbb"); 2363 case INSN_CLASS_ZBC: 2364 return riscv_subset_supports (rps, "zbc"); 2365 case INSN_CLASS_ZBS: 2366 return riscv_subset_supports (rps, "zbs"); 2367 case INSN_CLASS_ZBKB: 2368 return riscv_subset_supports (rps, "zbkb"); 2369 case INSN_CLASS_ZBKC: 2370 return riscv_subset_supports (rps, "zbkc"); 2371 case INSN_CLASS_ZBKX: 2372 return riscv_subset_supports (rps, "zbkx"); 2373 case INSN_CLASS_ZBB_OR_ZBKB: 2374 return (riscv_subset_supports (rps, "zbb") 2375 || riscv_subset_supports (rps, "zbkb")); 2376 case INSN_CLASS_ZBC_OR_ZBKC: 2377 return (riscv_subset_supports (rps, "zbc") 2378 || riscv_subset_supports (rps, "zbkc")); 2379 case INSN_CLASS_ZKND: 2380 return riscv_subset_supports (rps, "zknd"); 2381 case INSN_CLASS_ZKNE: 2382 return riscv_subset_supports (rps, "zkne"); 2383 case INSN_CLASS_ZKNH: 2384 return riscv_subset_supports (rps, "zknh"); 2385 case INSN_CLASS_ZKND_OR_ZKNE: 2386 return (riscv_subset_supports (rps, "zknd") 2387 || riscv_subset_supports (rps, "zkne")); 2388 case INSN_CLASS_ZKSED: 2389 return riscv_subset_supports (rps, "zksed"); 2390 case INSN_CLASS_ZKSH: 2391 return riscv_subset_supports (rps, "zksh"); 2392 case INSN_CLASS_V: 2393 return (riscv_subset_supports (rps, "v") 2394 || riscv_subset_supports (rps, "zve64x") 2395 || riscv_subset_supports (rps, "zve32x")); 2396 case INSN_CLASS_ZVEF: 2397 return (riscv_subset_supports (rps, "v") 2398 || riscv_subset_supports (rps, "zve64d") 2399 || riscv_subset_supports (rps, "zve64f") 2400 || riscv_subset_supports (rps, "zve32f")); 2401 case INSN_CLASS_SVINVAL: 2402 return riscv_subset_supports (rps, "svinval"); 2403 case INSN_CLASS_H: 2404 return riscv_subset_supports (rps, "h"); 2405 default: 2406 rps->error_handler 2407 (_("internal: unreachable INSN_CLASS_*")); 2408 return false; 2409 } 2410} 2411 2412/* Each instuction is belonged to an instruction class INSN_CLASS_*. 2413 Call riscv_subset_supports_ext to determine the missing extension. */ 2414 2415const char * 2416riscv_multi_subset_supports_ext (riscv_parse_subset_t *rps, 2417 enum riscv_insn_class insn_class) 2418{ 2419 switch (insn_class) 2420 { 2421 case INSN_CLASS_I: 2422 return "i"; 2423 case INSN_CLASS_ZICSR: 2424 return "zicsr"; 2425 case INSN_CLASS_ZIFENCEI: 2426 return "zifencei"; 2427 case INSN_CLASS_ZIHINTPAUSE: 2428 return "zihintpause"; 2429 case INSN_CLASS_M: 2430 return "m"; 2431 case INSN_CLASS_A: 2432 return "a"; 2433 case INSN_CLASS_F: 2434 return "f"; 2435 case INSN_CLASS_D: 2436 return "d"; 2437 case INSN_CLASS_Q: 2438 return "q"; 2439 case INSN_CLASS_C: 2440 return "c"; 2441 case INSN_CLASS_F_AND_C: 2442 if (!riscv_subset_supports (rps, "f") 2443 && !riscv_subset_supports (rps, "c")) 2444 return _("f' and `c"); 2445 else if (!riscv_subset_supports (rps, "f")) 2446 return "f"; 2447 else 2448 return "c"; 2449 case INSN_CLASS_D_AND_C: 2450 if (!riscv_subset_supports (rps, "d") 2451 && !riscv_subset_supports (rps, "c")) 2452 return _("d' and `c"); 2453 else if (!riscv_subset_supports (rps, "d")) 2454 return "d"; 2455 else 2456 return "c"; 2457 case INSN_CLASS_F_OR_ZFINX: 2458 /* i18n: Formatted like "extension `f' or `zfinx' required". */ 2459 return _("f' or `zfinx"); 2460 case INSN_CLASS_D_OR_ZDINX: 2461 return _("d' or `zdinx"); 2462 case INSN_CLASS_Q_OR_ZQINX: 2463 return _("q' or `zqinx"); 2464 case INSN_CLASS_ZFH_OR_ZHINX: 2465 return _("zfh' or `zhinx"); 2466 case INSN_CLASS_ZFHMIN: 2467 return "zfhmin"; 2468 case INSN_CLASS_ZFHMIN_OR_ZHINXMIN: 2469 return _("zfhmin' or `zhinxmin"); 2470 case INSN_CLASS_ZFHMIN_AND_D: 2471 if (riscv_subset_supports (rps, "zfhmin")) 2472 return "d"; 2473 else if (riscv_subset_supports (rps, "d")) 2474 return "zfhmin"; 2475 else if (riscv_subset_supports (rps, "zhinxmin")) 2476 return "zdinx"; 2477 else if (riscv_subset_supports (rps, "zdinx")) 2478 return "zhinxmin"; 2479 else 2480 return _("zfhmin' and `d', or `zhinxmin' and `zdinx"); 2481 case INSN_CLASS_ZFHMIN_AND_Q: 2482 if (riscv_subset_supports (rps, "zfhmin")) 2483 return "q"; 2484 else if (riscv_subset_supports (rps, "q")) 2485 return "zfhmin"; 2486 else if (riscv_subset_supports (rps, "zhinxmin")) 2487 return "zqinx"; 2488 else if (riscv_subset_supports (rps, "zqinx")) 2489 return "zhinxmin"; 2490 else 2491 return _("zfhmin' and `q', or `zhinxmin' and `zqinx"); 2492 case INSN_CLASS_ZBA: 2493 return "zba"; 2494 case INSN_CLASS_ZBB: 2495 return "zbb"; 2496 case INSN_CLASS_ZBC: 2497 return "zbc"; 2498 case INSN_CLASS_ZBS: 2499 return "zbs"; 2500 case INSN_CLASS_ZBKB: 2501 return "zbkb"; 2502 case INSN_CLASS_ZBKC: 2503 return "zbkc"; 2504 case INSN_CLASS_ZBKX: 2505 return "zbkx"; 2506 case INSN_CLASS_ZBB_OR_ZBKB: 2507 return _("zbb' or `zbkb"); 2508 case INSN_CLASS_ZBC_OR_ZBKC: 2509 return _("zbc' or `zbkc"); 2510 case INSN_CLASS_ZKND: 2511 return "zknd"; 2512 case INSN_CLASS_ZKNE: 2513 return "zkne"; 2514 case INSN_CLASS_ZKNH: 2515 return "zknh"; 2516 case INSN_CLASS_ZKND_OR_ZKNE: 2517 return _("zknd' or `zkne"); 2518 case INSN_CLASS_ZKSED: 2519 return "zksed"; 2520 case INSN_CLASS_ZKSH: 2521 return "zksh"; 2522 case INSN_CLASS_V: 2523 return _("v' or `zve64x' or `zve32x"); 2524 case INSN_CLASS_ZVEF: 2525 return _("v' or `zve64d' or `zve64f' or `zve32f"); 2526 case INSN_CLASS_SVINVAL: 2527 return "svinval"; 2528 case INSN_CLASS_H: 2529 return _("h"); 2530 default: 2531 rps->error_handler 2532 (_("internal: unreachable INSN_CLASS_*")); 2533 return NULL; 2534 } 2535} 2536