1 /* 2 * Copyright (C) 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef BERBERIS_DECODER_RISCV64_DECODER_H_ 18 #define BERBERIS_DECODER_RISCV64_DECODER_H_ 19 20 #include <climits> 21 #include <cstdint> 22 #include <cstring> 23 #include <type_traits> 24 25 #include "berberis/base/bit_util.h" 26 #include "berberis/base/checks.h" 27 28 namespace berberis { 29 30 // Decode() method takes a sequence of bytes and decodes it into the instruction opcode and fields. 31 // The InsnConsumer's method corresponding to the decoded opcode is called with the decoded fields 32 // as an argument. Returned is the instruction size. 33 template <class InsnConsumer> 34 class Decoder { 35 public: Decoder(InsnConsumer * insn_consumer)36 explicit Decoder(InsnConsumer* insn_consumer) : insn_consumer_(insn_consumer) {} 37 38 // https://eel.is/c++draft/enum#dcl.enum-8 39 // For an enumeration whose underlying type is fixed, the values of the enumeration are the values 40 // of the underlying type. 41 42 // To ensure that there are no surprises we specify that type in all enums below. 43 44 enum class AmoOpcode : uint8_t { 45 kLr = 0b00010, 46 kSc = 0b00011, 47 kAmoswap = 0b00001, 48 kAmoadd = 0b00000, 49 kAmoxor = 0b00100, 50 kAmoand = 0b01100, 51 kAmoor = 0b01000, 52 kAmomin = 0b10000, 53 kAmomax = 0b10100, 54 kAmominu = 0b11000, 55 kAmomaxu = 0b11100, 56 }; 57 58 enum class BranchOpcode : uint8_t { 59 kBeq = 0b000, 60 kBne = 0b001, 61 kBlt = 0b100, 62 kBge = 0b101, 63 kBltu = 0b110, 64 kBgeu = 0b111, 65 }; 66 67 enum class CsrOpcode : uint8_t { 68 kCsrrw = 0b01, 69 kCsrrs = 0b10, 70 kCsrrc = 0b11, 71 }; 72 73 enum class CsrImmOpcode : uint8_t { 74 kCsrrwi = 0b01, 75 kCsrrsi = 0b10, 76 kCsrrci = 0b11, 77 }; 78 79 enum class FmaOpcode : uint8_t { 80 kFmadd = 0b00, 81 kFmsub = 0b01, 82 kFnmsub = 0b10, 83 kFnmadd = 0b11, 84 }; 85 86 enum class FenceOpcode : uint8_t { 87 kFence = 0b0000, 88 kFenceTso = 0b1000, 89 }; 90 91 enum class OpOpcode : uint16_t { 92 kAdd = 0b0000'000'000, 93 kSub = 0b0100'000'000, 94 kSll = 0b0000'000'001, 95 kSlt = 0b0000'000'010, 96 kSltu = 0b0000'000'011, 97 kXor = 0b0000'000'100, 98 kSrl = 0b0000'000'101, 99 kSra = 0b0100'000'101, 100 kOr = 0b0000'000'110, 101 kAnd = 0b0000'000'111, 102 kMul = 0b0000'001'000, 103 kMulh = 0b0000'001'001, 104 kMulhsu = 0b0000'001'010, 105 kMulhu = 0b0000'001'011, 106 kDiv = 0b0000'001'100, 107 kDivu = 0b0000'001'101, 108 kRem = 0b0000'001'110, 109 kRemu = 0b0000'001'111, 110 kAndn = 0b0100'000'111, 111 kOrn = 0b0100'000'110, 112 kXnor = 0b0100'000'100, 113 kMax = 0b0000'101'110, 114 kMaxu = 0b0000'101'111, 115 kMin = 0b0000'101'100, 116 kMinu = 0b0000'101'101, 117 kRol = 0b0110'000'001, 118 kRor = 0b0110'000'101, 119 kSh1add = 0b0010'000'010, 120 kSh2add = 0b0010'000'100, 121 kSh3add = 0b0010'000'110, 122 kBclr = 0b0100'100'001, 123 kBext = 0b0100'100'101, 124 kBinv = 0b0110'100'001, 125 kBset = 0b0010'100'001, 126 }; 127 128 enum class Op32Opcode : uint16_t { 129 kAddw = 0b0000'000'000, 130 kAdduw = 0b0000'100'000, 131 kSubw = 0b0100'000'000, 132 kSllw = 0b0000'000'001, 133 kSrlw = 0b0000'000'101, 134 kSraw = 0b0100'000'101, 135 kMulw = 0b0000'001'000, 136 kDivw = 0b0000'001'100, 137 kDivuw = 0b0000'001'101, 138 kRemw = 0b0000'001'110, 139 kRemuw = 0b0000'001'111, 140 kRolw = 0b0110'000'001, 141 kRorw = 0b0110'000'101, 142 kSh1adduw = 0b0010'000'010, 143 kSh2adduw = 0b0010'000'100, 144 kSh3adduw = 0b0010'000'110, 145 }; 146 147 enum class OpSingleInputOpcode : uint16_t { 148 kZexth = 0b0000'100'100, 149 }; 150 151 enum class OpFpGpRegisterTargetNoRoundingOpcode : uint8_t { 152 kFle = 0b00'000, 153 kFlt = 0b00'001, 154 kFeq = 0b00'010, 155 }; 156 157 enum class OpFpGpRegisterTargetSingleInputNoRoundingOpcode : uint16_t { 158 kFclass = 0b00'00000'001, 159 }; 160 161 enum class OpFpNoRoundingOpcode : uint8_t { 162 kFSgnj = 0b00'000, 163 kFSgnjn = 0b00'001, 164 kFSgnjx = 0b00'010, 165 kFMin = 0b01'000, 166 kFMax = 0b01'001, 167 }; 168 169 enum class OpFpOpcode : uint8_t { 170 kFAdd = 0b00, 171 kFSub = 0b01, 172 kFMul = 0b10, 173 kFDiv = 0b11, 174 }; 175 176 enum class OpFpSingleInputOpcode : uint8_t { 177 kFSqrt = 0b11'00000, 178 }; 179 180 enum class OpFpSingleInputNoRoundingOpcode : uint8_t { 181 kFmv, 182 }; 183 184 enum class OpImmOpcode : uint8_t { 185 kAddi = 0b000, 186 kSlti = 0b010, 187 kSltiu = 0b011, 188 kXori = 0b100, 189 kOri = 0b110, 190 kAndi = 0b111, 191 }; 192 193 enum class OpImm32Opcode : uint8_t { 194 kAddiw = 0b000, 195 }; 196 197 enum class ShiftImmOpcode : uint8_t { 198 kSlli = 0b000000'001, 199 kSrli = 0b000000'101, 200 kSrai = 0b010000'101, 201 }; 202 203 enum class ShiftImm32Opcode : uint16_t { 204 kSlliw = 0b0000000'001, 205 kSrliw = 0b0000000'101, 206 kSraiw = 0b0100000'101, 207 }; 208 209 enum class BitmanipImmOpcode : uint16_t { 210 kClz = 0b0110000'00000'001, 211 kCpop = 0b0110000'00010'001, 212 kCtz = 0b0110000'00001'001, 213 kSextb = 0b0110000'00100'001, 214 kSexth = 0b0110000'00101'001, 215 kOrcb = 0b0010100'00111'101, 216 kRev8 = 0b0110101'11000'101, 217 kRori = 0b011000'101, 218 kBclri = 0b010010'001, 219 kBexti = 0b010010'101, 220 kBinvi = 0b011010'001, 221 kBseti = 0b001010'001, 222 }; 223 224 enum class BitmanipImm32Opcode : uint16_t { 225 kClzw = 0b0110000'00000'001, 226 kCpopw = 0b0110000'00010'001, 227 kCtzw = 0b0110000'00001'001, 228 kRoriw = 0b0110000'101, 229 kSlliuw = 0b0000100'001, 230 }; 231 232 enum class SystemOpcode : uint32_t { 233 kEcall = 0b000000000000'00000'000'00000, 234 kEbreak = 0b000000000001'00000'000'00000, 235 }; 236 237 enum class VLUmOpOpcode : uint8_t { 238 kVleXX = 0b00000, 239 kVlXreXX = 0b01000, 240 kVleXXff = 0b10000, 241 kVlm = 0b01011, 242 }; 243 244 enum class VOpFVfOpcode : uint8_t { 245 kVfaddvf = 0b000000, 246 kVfsubvf = 0b000010, 247 kVfminvf = 0b000100, 248 kVfmaxvf = 0b000110, 249 kVfsgnjvf = 0b001000, 250 kVfsgnjnvf = 0b001001, 251 kVfsgnjxvf = 0b001010, 252 kVfslide1upvf = 0b001110, 253 kVfslide1downvf = 0b001111, 254 kVfmvsf = 0b010000, 255 kVfmergevf = 0b010111, // Also kVfmv.vf 256 kVmfeqvf = 0b011000, 257 kVmflevf = 0b011001, 258 kVmfltvf = 0b011011, 259 kVmfnevf = 0b011100, 260 kVmfgtvf = 0b011101, 261 kVmfgevf = 0b011111, 262 kVfdivvf = 0b100000, 263 kVfrdivvf = 0b100001, 264 kVfmulvf = 0b100100, 265 kVfrsubvf = 0b100111, 266 kVfmaddvf = 0b101000, 267 kVfnmaddvf = 0b101001, 268 kVfmsubvf = 0b101010, 269 kVfnmsubvf = 0b101011, 270 kVfmaccvf = 0b101100, 271 kVfnmaccvf = 0b101101, 272 kVfmsacvf = 0b101110, 273 kVfnmsacvf = 0b101111, 274 kVfwaddvf = 0b110000, 275 kVfwsubvf = 0b110010, 276 kVfwaddwf = 0b110100, 277 kVfwsubwf = 0b110110, 278 kVfwmulvf = 0b111000, 279 kVfwmaccvf = 0b111100, 280 kVfwnmaccvf = 0b111101, 281 kVfwmsacvf = 0b111110, 282 kVfwnmsacvf = 0b111111, 283 }; 284 285 enum class VOpFVvOpcode : uint8_t { 286 kVfaddvv = 0b000000, 287 kVfredusumvs = 0b000001, 288 kVfsubvv = 0b000010, 289 kVfredosumvs = 0b000011, 290 kVfminvv = 0b000100, 291 kVfredminvs = 0b000101, 292 kVfmaxvv = 0b000110, 293 kVfredmaxvs = 0b000111, 294 kVfsgnjvv = 0b001000, 295 kVfsgnjnvv = 0b001001, 296 kVfsgnjxvv = 0b001010, 297 kVfmvfs = 0b010000, 298 kVFUnary0 = 0b010010, 299 kVFUnary1 = 0b010011, 300 kVmfeqvv = 0b011000, 301 kVmflevv = 0b011001, 302 kVmfltvv = 0b011011, 303 kVmfnevv = 0b011100, 304 kVfdivvv = 0b100000, 305 kVfmulvv = 0b100100, 306 kVfmaddvv = 0b101000, 307 kVfnmaddvv = 0b101001, 308 kVfmsubvv = 0b101010, 309 kVfnmsubvv = 0b101011, 310 kVfmaccvv = 0b101100, 311 kVfnmaccvv = 0b101101, 312 kVfmsacvv = 0b101110, 313 kVfnmsacvv = 0b101111, 314 kVfwaddvv = 0b110000, 315 kVfwredusumvv = 0b110001, 316 kVfwsubvv = 0b110010, 317 kVfwredosumvv = 0b110011, 318 kVfwaddwv = 0b110100, 319 kVfwsubwv = 0b110110, 320 kVfwmulvv = 0b111000, 321 kVfwmaccvv = 0b111100, 322 kVfwnmaccvv = 0b111101, 323 kVfwmsacvv = 0b111110, 324 kVfwnmsacvv = 0b111111, 325 }; 326 327 enum class VOpIViOpcode : uint8_t { 328 kVaddvi = 0b000000, 329 kVrsubvi = 0b000011, 330 kVandvi = 0b001001, 331 kVorvi = 0b001010, 332 kVxorvi = 0b001011, 333 kVrgathervi = 0b001100, 334 kVslideupvi = 0b001110, 335 kVslidedownvi = 0b001111, 336 kVadcvi = 0b010000, 337 kVmadcvi = 0b010001, 338 kVmergevi = 0b010111, // Also kVmv.vi 339 kVmseqvi = 0b011000, 340 kVmsnevi = 0b011001, 341 kVmsleuvi = 0b011100, 342 kVmslevi = 0b011101, 343 kVmsgtuvi = 0b011110, 344 kVmsgtvi = 0b011111, 345 kVsadduvi = 0b100000, 346 kVsaddvi = 0b100001, 347 kVsllvi = 0b100101, 348 kVmvXrv = 0b100111, 349 kVsrlvi = 0b101000, 350 kVsravi = 0b101001, 351 kVssrlvi = 0b101010, 352 kVssravi = 0b101011, 353 kVnsrlwi = 0b101100, 354 kVnsrawi = 0b101101, 355 kVnclipuwi = 0b101110, 356 kVnclipwi = 0b101111, 357 }; 358 359 enum class VOpIVvOpcode : uint8_t { 360 kVaddvv = 0b000000, 361 kVsubvv = 0b000010, 362 kVminuvv = 0b000100, 363 kVminvv = 0b000101, 364 kVmaxuvv = 0b000110, 365 kVmaxvv = 0b000111, 366 kVandvv = 0b001001, 367 kVorvv = 0b001010, 368 kVxorvv = 0b001011, 369 kVrgathervv = 0b001100, 370 kVrgatherei16vv = 0b001110, 371 kVadcvv = 0b010000, 372 kVmadcvv = 0b010001, 373 kVsbcvv = 0b010010, 374 kVmsbcvv = 0b010011, 375 kVmergevv = 0b010111, // Also kVmv.vv 376 kVmseqvv = 0b011000, 377 kVmsnevv = 0b011001, 378 kVmsltuvv = 0b011010, 379 kVmsltvv = 0b011011, 380 kVmsleuvv = 0b011100, 381 kVmslevv = 0b011101, 382 kVsadduvv = 0b100000, 383 kVsaddvv = 0b100001, 384 kVssubuvv = 0b100010, 385 kVssubvv = 0b100011, 386 kVsllvv = 0b100101, 387 kVsmulvv = 0b100111, 388 kVsrlvv = 0b101000, 389 kVsravv = 0b101001, 390 kVssrlvv = 0b101010, 391 kVssravv = 0b101011, 392 kVnsrlwv = 0b101100, 393 kVnsrawv = 0b101101, 394 kVnclipuwv = 0b101110, 395 kVnclipwv = 0b101111, 396 kVwredsumuvv = 0b110000, 397 kVwredsumvv = 0b110001, 398 }; 399 400 enum class VOpIVxOpcode : uint8_t { 401 kVaddvx = 0b000000, 402 kVsubvx = 0b000010, 403 kVrsubvx = 0b000011, 404 kVminuvx = 0b000100, 405 kVminvx = 0b000101, 406 kVmaxuvx = 0b000110, 407 kVmaxvx = 0b000111, 408 kVandvx = 0b001001, 409 kVorvx = 0b001010, 410 kVxorvx = 0b001011, 411 kVrgathervx = 0b001100, 412 kVslideupvx = 0b001110, 413 kVslidedownvx = 0b001111, 414 kVadcvx = 0b010000, 415 kVmadcvx = 0b010001, 416 kVsbcvx = 0b010010, 417 kVmsbcvx = 0b010011, 418 kVmergevx = 0b010111, // Also Vmv.vx 419 kVmseqvx = 0b011000, 420 kVmsnevx = 0b011001, 421 kVmsltuvx = 0b011010, 422 kVmsltvx = 0b011011, 423 kVmsleuvx = 0b011100, 424 kVmslevx = 0b011101, 425 kVmsgtuvx = 0b011110, 426 kVmsgtvx = 0b011111, 427 kVsadduvx = 0b100000, 428 kVsaddvx = 0b100001, 429 kVssubuvx = 0b100010, 430 kVssubvx = 0b100011, 431 kVsllvx = 0b100101, 432 kVsmulvx = 0b100111, 433 kVsrlvx = 0b101000, 434 kVsravx = 0b101001, 435 kVssrlvx = 0b101010, 436 kVssravx = 0b101011, 437 kVnsrlwx = 0b101100, 438 kVnsrawx = 0b101101, 439 kVnclipuwx = 0b101110, 440 kVnclipwx = 0b101111, 441 }; 442 443 enum class VOpMVvOpcode : uint8_t { 444 kVredsumvs = 0b000000, 445 kVredandvs = 0b000001, 446 kVredorvs = 0b000010, 447 kVredxorvs = 0b000011, 448 kVredminuvs = 0b000100, 449 kVredminvs = 0b000101, 450 kVredmaxuvs = 0b000110, 451 kVredmaxvs = 0b000111, 452 kVaadduvv = 0b001000, 453 kVaaddvv = 0b001001, 454 kVasubuvv = 0b001010, 455 kVasubvv = 0b001011, 456 kVWXUnary0 = 0b010000, 457 kVFUnary0 = 0b010010, 458 kVMUnary0 = 0b010100, 459 kVmandnmm = 0b011000, 460 kVmandmm = 0b011001, 461 kVmormm = 0b011010, 462 kVmxormm = 0b011011, 463 kVmornmm = 0b011100, 464 kVmnandmm = 0b011101, 465 kVmnormm = 0b011110, 466 kVmxnormm = 0b011111, 467 kVdivuvv = 0b100000, 468 kVdivvv = 0b100001, 469 kVremuvv = 0b100010, 470 kVremvv = 0b100011, 471 kVmulhuvv = 0b100100, 472 kVmulvv = 0b100101, 473 kVmulhsuvv = 0b100110, 474 kVmulhvv = 0b100111, 475 kVmaddvv = 0b101001, 476 kVnmsubvv = 0b101011, 477 kVmaccvv = 0b101101, 478 kVnmsacvv = 0b101111, 479 kVwadduvv = 0b110000, 480 kVwaddvv = 0b110001, 481 kVwsubuvv = 0b110010, 482 kVwsubvv = 0b110011, 483 kVwadduwv = 0b110100, 484 kVwaddwv = 0b110101, 485 kVwsubuwv = 0b110110, 486 kVwsubwv = 0b110111, 487 kVwmuluvv = 0b111000, 488 kVwmulsuvv = 0b111010, 489 kVwmulvv = 0b111011, 490 kVwmaccuvv = 0b111100, 491 kVwmaccvv = 0b111101, 492 kVwmaccsuvv = 0b111111, 493 }; 494 495 enum class VOpMVxOpcode : uint8_t { 496 kVaadduvx = 0b001000, 497 kVaaddvx = 0b001001, 498 kVasubuvx = 0b001010, 499 kVasubvx = 0b001011, 500 kVslide1upvx = 0b001110, 501 kVslide1downvx = 0b001111, 502 kVRXUnary0 = 0b010000, 503 kVdivuvx = 0b100000, 504 kVdivvx = 0b100001, 505 kVremuvx = 0b100010, 506 kVremvx = 0b100011, 507 kVmulhuvx = 0b100100, 508 kVmulvx = 0b100101, 509 kVmulhsuvx = 0b100110, 510 kVmulhvx = 0b100111, 511 kVmaddvx = 0b101001, 512 kVnmsubvx = 0b101011, 513 kVmaccvx = 0b101101, 514 kVnmsacvx = 0b101111, 515 kVwadduvx = 0b110000, 516 kVwaddvx = 0b110001, 517 kVwsubuvx = 0b110010, 518 kVwsubvx = 0b110011, 519 kVwadduwx = 0b110100, 520 kVwaddwx = 0b110101, 521 kVwsubuwx = 0b110110, 522 kVwsubwx = 0b110111, 523 kVwmuluvx = 0b111000, 524 kVwmulsuvx = 0b111010, 525 kVwmulvx = 0b111011, 526 kVwmaccuvx = 0b111100, 527 kVwmaccvx = 0b111101, 528 kVwmaccusvx = 0b111110, 529 kVwmaccsuvx = 0b111111, 530 }; 531 532 enum class VSUmOpOpcode : uint8_t { 533 kVseXX = 0b00000, 534 kVsX = 0b01000, 535 kVsm = 0b01011, 536 }; 537 538 enum class VFUnary0Opcode : uint8_t { 539 kVfcvtxufv = 0b00000, 540 kVfcvtxfv = 0b00001, 541 kVfcvtfxuv = 0b00010, 542 kVfcvtfxv = 0b00011, 543 kVfcvtrtzxufv = 0b00110, 544 kVfcvtrtzxfv = 0b00111, 545 kVfwcvtxufv = 0b01000, 546 kVfwcvtxfv = 0b01001, 547 kVfwcvtfxuv = 0b01010, 548 kVfwcvtfxv = 0b01011, 549 kVfwcvtffv = 0b01100, 550 kVfwcvtrtzxufv = 0b01110, 551 kVfwcvtrtzxfv = 0b01111, 552 kVfncvtxufw = 0b10000, 553 kVfncvtxfw = 0b10001, 554 kVfncvtfxuw = 0b10010, 555 kVfncvtfxw = 0b10011, 556 kVfncvtffw = 0b10100, 557 kVfncvtrodffw = 0b10101, 558 kVfncvtrtzxufw = 0b10110, 559 kVfncvtrtzxfw = 0b10111, 560 }; 561 562 enum class VFUnary1Opcode : uint8_t { 563 kVfsqrtv = 0b00000, 564 kVfrsqrt7v = 0b00100, 565 kVfclassv = 0b10000, 566 }; 567 568 enum class VRXUnary0Opcode : uint8_t { 569 kVmvsx = 0b00000, 570 }; 571 572 enum class VWXUnary0Opcode : uint8_t { 573 kVmvxs = 0b00000, 574 kVcpopm = 0b10000, 575 kVfirstm = 0b10001, 576 }; 577 578 enum class VMUnary0Opcode : uint8_t { 579 kVmsbfm = 0b00001, 580 kVmsofm = 0b00010, 581 kVmsifm = 0b00011, 582 kViotam = 0b10000, 583 kVidv = 0b10001, 584 }; 585 586 enum class VXUnary0Opcode : uint8_t { 587 kVzextvf8m = 0b00010, 588 kVsextvf8m = 0b00011, 589 kVzextvf4m = 0b00100, 590 kVsextvf4m = 0b00101, 591 kVzextvf2m = 0b00110, 592 kVsextvf2m = 0b00111, 593 }; 594 595 // Load/Store instruction include 3bit “width” field while all other floating-point instructions 596 // include 2bit “fmt” field. 597 // 598 // Decoder unifies these differences and uses FloatOperandType for types of all floating-point 599 // operands. 600 // 601 // Load/Store for regular instruction coulnd't be simiarly unified: Load instructions include 602 // seven types, while Store instructions have only four. 603 // 604 // Fcvt instructions have their own operand type encoding because they are only supporting 32bit 605 // and 64bit operands, there is no support for 8bit and 16bit operands. 606 // 607 // This is because Load can perform either sign-extension or zero-extension for all sizes except 608 // 64bit (which doesn't need neither sign-extension nor zero-extension since operand size is the 609 // same as register size in that case). 610 611 enum class FcvtOperandType : uint8_t { 612 k32bitSigned = 0b00000, 613 k32bitUnsigned = 0b00001, 614 k64bitSigned = 0b00010, 615 k64bitUnsigned = 0b00011, 616 }; 617 618 enum class FloatOperandType : uint8_t { 619 kFloat = 0b00, 620 kDouble = 0b01, 621 kHalf = 0b10, 622 kQuad = 0b11, 623 }; 624 625 // Used in vector loads and stores, and also in scalar stores. 626 // Scalar loads use different type because loads needs to either sign-extend value or zero-extend 627 // it which makes difference between signed and unsigned types meaningful. 628 enum class MemoryDataOperandType : uint8_t { 629 k8bit = 0b000, 630 k16bit = 0b001, 631 k32bit = 0b010, 632 k64bit = 0b011, 633 }; 634 635 enum class LoadOperandType : uint8_t { 636 k8bitSigned = 0b000, 637 k16bitSigned = 0b001, 638 k32bitSigned = 0b010, 639 k64bit = 0b011, 640 k8bitUnsigned = 0b100, 641 k16bitUnsigned = 0b101, 642 k32bitUnsigned = 0b110, 643 }; 644 645 struct AmoArgs { 646 AmoOpcode opcode; 647 MemoryDataOperandType operand_type; 648 uint8_t dst; 649 uint8_t src1; 650 uint8_t src2; 651 bool rl : 1; 652 bool aq : 1; 653 }; 654 655 struct BranchArgs { 656 BranchOpcode opcode; 657 uint8_t src1; 658 uint8_t src2; 659 int16_t offset; 660 }; 661 662 struct CsrArgs { 663 CsrOpcode opcode; 664 uint8_t dst; 665 uint8_t src; 666 uint16_t csr; 667 }; 668 669 struct CsrImmArgs { 670 CsrImmOpcode opcode; 671 uint8_t dst; 672 uint8_t imm; 673 uint16_t csr; 674 }; 675 676 struct FcvtFloatToFloatArgs { 677 FloatOperandType dst_type; 678 FloatOperandType src_type; 679 uint8_t dst; 680 uint8_t src; 681 uint8_t rm; 682 }; 683 684 struct FcvtFloatToIntegerArgs { 685 FcvtOperandType dst_type; 686 FloatOperandType src_type; 687 uint8_t dst; 688 uint8_t src; 689 uint8_t rm; 690 }; 691 692 struct FcvtIntegerToFloatArgs { 693 FloatOperandType dst_type; 694 FcvtOperandType src_type; 695 uint8_t dst; 696 uint8_t src; 697 uint8_t rm; 698 }; 699 700 struct FenceArgs { 701 FenceOpcode opcode; 702 uint8_t dst; 703 uint8_t src; 704 bool sw : 1; 705 bool sr : 1; 706 bool so : 1; 707 bool si : 1; 708 bool pw : 1; 709 bool pr : 1; 710 bool po : 1; 711 bool pi : 1; 712 }; 713 714 struct FenceIArgs { 715 uint8_t dst; 716 uint8_t src; 717 int16_t imm; 718 }; 719 720 struct FmaArgs { 721 FmaOpcode opcode; 722 FloatOperandType operand_type; 723 uint8_t dst; 724 uint8_t src1; 725 uint8_t src2; 726 uint8_t src3; 727 uint8_t rm; 728 }; 729 730 struct JumpAndLinkArgs { 731 uint8_t dst; 732 int32_t offset; 733 uint8_t insn_len; 734 }; 735 736 struct JumpAndLinkRegisterArgs { 737 uint8_t dst; 738 uint8_t base; 739 int16_t offset; 740 uint8_t insn_len; 741 }; 742 743 template <typename OpcodeType> 744 struct OpArgsTemplate { 745 OpcodeType opcode; 746 uint8_t dst; 747 uint8_t src1; 748 uint8_t src2; 749 }; 750 751 struct OpSingleInputArgs { 752 OpSingleInputOpcode opcode; 753 uint8_t dst; 754 uint8_t src; 755 }; 756 757 using OpArgs = OpArgsTemplate<OpOpcode>; 758 using Op32Args = OpArgsTemplate<Op32Opcode>; 759 760 struct OpFpArgs { 761 OpFpOpcode opcode; 762 FloatOperandType operand_type; 763 uint8_t dst; 764 uint8_t src1; 765 uint8_t src2; 766 uint8_t rm; 767 }; 768 769 struct OpFpGpRegisterTargetNoRoundingArgs { 770 OpFpGpRegisterTargetNoRoundingOpcode opcode; 771 FloatOperandType operand_type; 772 uint8_t dst; 773 uint8_t src1; 774 uint8_t src2; 775 }; 776 777 struct OpFpGpRegisterTargetSingleInputNoRoundingArgs { 778 OpFpGpRegisterTargetSingleInputNoRoundingOpcode opcode; 779 FloatOperandType operand_type; 780 uint8_t dst; 781 uint8_t src; 782 }; 783 784 struct FmvFloatToIntegerArgs { 785 FloatOperandType operand_type; 786 uint8_t dst; 787 uint8_t src; 788 }; 789 790 struct FmvIntegerToFloatArgs { 791 FloatOperandType operand_type; 792 uint8_t dst; 793 uint8_t src; 794 }; 795 796 struct OpFpNoRoundingArgs { 797 OpFpNoRoundingOpcode opcode; 798 FloatOperandType operand_type; 799 uint8_t dst; 800 uint8_t src1; 801 uint8_t src2; 802 }; 803 804 struct OpFpSingleInputArgs { 805 OpFpSingleInputOpcode opcode; 806 FloatOperandType operand_type; 807 uint8_t dst; 808 uint8_t src; 809 uint8_t rm; 810 }; 811 812 struct OpFpSingleInputNoRoundingArgs { 813 OpFpSingleInputNoRoundingOpcode opcode; 814 FloatOperandType operand_type; 815 uint8_t dst; 816 uint8_t src; 817 }; 818 819 template <typename OpcodeType> 820 struct OpImmArgsTemplate { 821 OpcodeType opcode; 822 uint8_t dst; 823 uint8_t src; 824 int16_t imm; 825 }; 826 827 using OpImmArgs = OpImmArgsTemplate<OpImmOpcode>; 828 using OpImm32Args = OpImmArgsTemplate<OpImm32Opcode>; 829 830 struct VLoadIndexedArgs { 831 MemoryDataOperandType width; 832 bool vm; 833 bool ordered; 834 uint8_t nf; 835 uint8_t dst; 836 uint8_t src; 837 uint8_t idx; 838 }; 839 840 struct VLoadStrideArgs { 841 MemoryDataOperandType width; 842 bool vm; 843 bool ordered; 844 uint8_t nf; 845 uint8_t dst; 846 uint8_t src; 847 uint8_t std; 848 }; 849 850 struct VLoadUnitStrideArgs { 851 VLUmOpOpcode opcode; 852 MemoryDataOperandType width; 853 bool vm; 854 uint8_t nf; 855 uint8_t dst; 856 uint8_t src; 857 }; 858 859 struct VOpFVfArgs { 860 VOpFVfOpcode opcode; 861 bool vm; 862 uint8_t dst; 863 uint8_t src1; 864 uint8_t src2; 865 }; 866 867 struct VOpFVvArgs { 868 VOpFVvOpcode opcode; 869 bool vm; 870 uint8_t dst; 871 uint8_t src1; 872 union { 873 VFUnary0Opcode vfunary0_opcode; 874 VFUnary1Opcode vfunary1_opcode; 875 uint8_t src2; 876 }; 877 }; 878 879 struct VOpIViArgs { 880 VOpIViOpcode opcode; 881 bool vm; 882 uint8_t dst; 883 uint8_t src; 884 union { 885 int8_t imm : 5; 886 uint8_t uimm : 5; 887 }; 888 }; 889 890 struct VOpIVvArgs { 891 VOpIVvOpcode opcode; 892 bool vm; 893 uint8_t dst; 894 uint8_t src1; 895 uint8_t src2; 896 }; 897 898 struct VOpIVxArgs { 899 VOpIVxOpcode opcode; 900 bool vm; 901 uint8_t dst; 902 uint8_t src1; 903 uint8_t src2; 904 }; 905 906 struct VOpMVvArgs { 907 VOpMVvOpcode opcode; 908 bool vm; 909 uint8_t dst; 910 uint8_t src1; 911 union { 912 VWXUnary0Opcode vwxunary0_opcode; 913 VMUnary0Opcode vmunary0_opcode; 914 VXUnary0Opcode vxunary0_opcode; 915 uint8_t src2; 916 }; 917 }; 918 919 struct VOpMVxArgs { 920 VOpMVxOpcode opcode; 921 bool vm; 922 uint8_t dst; 923 union { 924 VRXUnary0Opcode vrxunary0_opcode; 925 uint8_t src1; 926 }; 927 uint8_t src2; 928 }; 929 930 struct VsetivliArgs { 931 uint8_t dst; 932 uint8_t avl; 933 uint16_t vtype; 934 }; 935 936 struct VsetvliArgs { 937 uint8_t dst; 938 uint8_t src; 939 uint16_t vtype; 940 }; 941 942 struct VsetvlArgs { 943 uint8_t dst; 944 uint8_t src1; 945 uint8_t src2; 946 }; 947 948 struct VStoreIndexedArgs { 949 MemoryDataOperandType width; 950 bool vm; 951 bool ordered; 952 uint8_t nf; 953 uint8_t src; 954 uint8_t idx; 955 uint8_t data; 956 }; 957 958 struct VStoreStrideArgs { 959 MemoryDataOperandType width; 960 bool vm; 961 bool ordered; 962 uint8_t nf; 963 uint8_t src; 964 uint8_t std; 965 uint8_t data; 966 }; 967 968 struct VStoreUnitStrideArgs { 969 VSUmOpOpcode opcode; 970 MemoryDataOperandType width; 971 bool vm; 972 uint8_t nf; 973 uint8_t src; 974 uint8_t data; 975 }; 976 977 template <typename OperandTypeEnum> 978 struct LoadArgsTemplate { 979 OperandTypeEnum operand_type; 980 uint8_t dst; 981 uint8_t src; 982 int16_t offset; 983 }; 984 985 using LoadArgs = LoadArgsTemplate<LoadOperandType>; 986 using LoadFpArgs = LoadArgsTemplate<FloatOperandType>; 987 988 template <typename OpcodeType> 989 struct ShiftImmArgsTemplate { 990 OpcodeType opcode; 991 uint8_t dst; 992 uint8_t src; 993 uint8_t imm; 994 }; 995 996 using ShiftImmArgs = ShiftImmArgsTemplate<ShiftImmOpcode>; 997 using ShiftImm32Args = ShiftImmArgsTemplate<ShiftImm32Opcode>; 998 999 template <typename OpcodeType> 1000 struct BitmanipImmArgsTemplate { 1001 OpcodeType opcode; 1002 uint8_t dst; 1003 uint8_t src; 1004 uint8_t shamt; 1005 }; 1006 1007 using BitmanipImmArgs = BitmanipImmArgsTemplate<BitmanipImmOpcode>; 1008 using BitmanipImm32Args = BitmanipImmArgsTemplate<BitmanipImm32Opcode>; 1009 1010 template <typename OperandTypeEnum> 1011 struct StoreArgsTemplate { 1012 OperandTypeEnum operand_type; 1013 uint8_t src; 1014 int16_t offset; 1015 uint8_t data; 1016 }; 1017 1018 using StoreArgs = StoreArgsTemplate<MemoryDataOperandType>; 1019 using StoreFpArgs = StoreArgsTemplate<FloatOperandType>; 1020 1021 struct SystemArgs { 1022 SystemOpcode opcode; 1023 }; 1024 1025 struct UpperImmArgs { 1026 uint8_t dst; 1027 int32_t imm; 1028 }; 1029 GetInsnSize(const uint16_t * code)1030 static uint8_t GetInsnSize(const uint16_t* code) { 1031 constexpr uint16_t kInsnLenMask = uint16_t{0b11}; 1032 return ((*code & kInsnLenMask) != kInsnLenMask) ? 2 : 4; 1033 } 1034 Decode(const uint16_t * code)1035 uint8_t Decode(const uint16_t* code) { 1036 uint8_t insn_size = GetInsnSize(code); 1037 if (insn_size == 2) { 1038 code_ = *code; 1039 return DecodeCompressedInstruction(); 1040 } 1041 CHECK_EQ(insn_size, 4); 1042 // Warning: do not cast and dereference the pointer 1043 // since the address may not be 4-bytes aligned. 1044 memcpy(&code_, code, sizeof(code_)); 1045 return DecodeBaseInstruction(); 1046 } 1047 DecodeCompressedInstruction()1048 uint8_t DecodeCompressedInstruction() { 1049 CompressedOpcode opcode_bits{(GetBits<13, 3>() << 2) | GetBits<0, 2>()}; 1050 1051 switch (opcode_bits) { 1052 case CompressedOpcode::kAddi4spn: 1053 DecodeCompressedAddi4spn(); 1054 break; 1055 case CompressedOpcode::kFld: 1056 DecodeCompressedLoadStore<LoadStore::kLoad, FloatOperandType::kDouble>(); 1057 break; 1058 case CompressedOpcode::kLw: 1059 DecodeCompressedLoadStore<LoadStore::kLoad, LoadOperandType::k32bitSigned>(); 1060 break; 1061 case CompressedOpcode::kLd: 1062 DecodeCompressedLoadStore<LoadStore::kLoad, LoadOperandType::k64bit>(); 1063 break; 1064 case CompressedOpcode::kFsd: 1065 DecodeCompressedLoadStore<LoadStore::kStore, FloatOperandType::kDouble>(); 1066 break; 1067 case CompressedOpcode::kSw: 1068 DecodeCompressedLoadStore<LoadStore::kStore, MemoryDataOperandType::k32bit>(); 1069 break; 1070 case CompressedOpcode::kSd: 1071 DecodeCompressedLoadStore<LoadStore::kStore, MemoryDataOperandType::k64bit>(); 1072 break; 1073 case CompressedOpcode::kAddi: 1074 DecodeCompressedAddi(); 1075 break; 1076 case CompressedOpcode::kAddiw: 1077 DecodeCompressedAddiw(); 1078 break; 1079 case CompressedOpcode::kLi: 1080 DecodeCompressedLi(); 1081 break; 1082 case CompressedOpcode::kLui_Addi16sp: 1083 DecodeCompressedLuiAddi16sp(); 1084 break; 1085 case CompressedOpcode::kMisc_Alu: 1086 DecodeCompressedMiscAlu(); 1087 break; 1088 case CompressedOpcode::kJ: 1089 DecodeCompressedJ(); 1090 break; 1091 case CompressedOpcode::kBeqz: 1092 case CompressedOpcode::kBnez: 1093 DecodeCompressedBeqzBnez(); 1094 break; 1095 case CompressedOpcode::kSlli: 1096 DecodeCompressedSlli(); 1097 break; 1098 case CompressedOpcode::kFldsp: 1099 DecodeCompressedLoadsp<FloatOperandType::kDouble>(); 1100 break; 1101 case CompressedOpcode::kLwsp: 1102 DecodeCompressedLoadsp<LoadOperandType::k32bitSigned>(); 1103 break; 1104 case CompressedOpcode::kLdsp: 1105 DecodeCompressedLoadsp<LoadOperandType::k64bit>(); 1106 break; 1107 case CompressedOpcode::kJr_Jalr_Mv_Add: 1108 DecodeCompressedJr_Jalr_Mv_Add(); 1109 break; 1110 case CompressedOpcode::kFsdsp: 1111 DecodeCompressedStoresp<FloatOperandType::kDouble>(); 1112 break; 1113 case CompressedOpcode::kSwsp: 1114 DecodeCompressedStoresp<MemoryDataOperandType::k32bit>(); 1115 break; 1116 case CompressedOpcode::kSdsp: 1117 DecodeCompressedStoresp<MemoryDataOperandType::k64bit>(); 1118 break; 1119 default: 1120 insn_consumer_->Undefined(); 1121 } 1122 return 2; 1123 } 1124 DecodeCompressedLi()1125 void DecodeCompressedLi() { 1126 uint8_t low_imm = GetBits<2, 5>(); 1127 uint8_t high_imm = GetBits<12, 1>(); 1128 uint8_t rd = GetBits<7, 5>(); 1129 int8_t imm = SignExtend<6>((high_imm << 5) + low_imm); 1130 const OpImmArgs args = { 1131 .opcode = OpImmOpcode::kAddi, 1132 .dst = rd, 1133 .src = 0, 1134 .imm = imm, 1135 }; 1136 insn_consumer_->OpImm(args); 1137 } 1138 DecodeCompressedMiscAlu()1139 void DecodeCompressedMiscAlu() { 1140 uint8_t r = GetBits<7, 3>() + 8; 1141 uint8_t low_imm = GetBits<2, 5>(); 1142 uint8_t high_imm = GetBits<12, 1>(); 1143 uint8_t imm = (high_imm << 5) + low_imm; 1144 switch (GetBits<10, 2>()) { 1145 case 0b00: { 1146 const ShiftImmArgs args = { 1147 .opcode = ShiftImmOpcode::kSrli, 1148 .dst = r, 1149 .src = r, 1150 .imm = imm, 1151 }; 1152 return insn_consumer_->OpImm(args); 1153 } 1154 case 0b01: { 1155 const ShiftImmArgs args = { 1156 .opcode = ShiftImmOpcode::kSrai, 1157 .dst = r, 1158 .src = r, 1159 .imm = imm, 1160 }; 1161 return insn_consumer_->OpImm(args); 1162 } 1163 case 0b10: { 1164 const OpImmArgs args = { 1165 .opcode = OpImmOpcode::kAndi, 1166 .dst = r, 1167 .src = r, 1168 .imm = SignExtend<6>(imm), 1169 }; 1170 return insn_consumer_->OpImm(args); 1171 } 1172 } 1173 uint8_t rs2 = GetBits<2, 3>() + 8; 1174 if (GetBits<12, 1>() == 0) { 1175 OpOpcode opcode; 1176 switch (GetBits<5, 2>()) { 1177 case 0b00: 1178 opcode = OpOpcode::kSub; 1179 break; 1180 case 0b01: 1181 opcode = OpOpcode::kXor; 1182 break; 1183 case 0b10: 1184 opcode = OpOpcode::kOr; 1185 break; 1186 case 0b11: 1187 opcode = OpOpcode::kAnd; 1188 break; 1189 } 1190 const OpArgs args = { 1191 .opcode = opcode, 1192 .dst = r, 1193 .src1 = r, 1194 .src2 = rs2, 1195 }; 1196 return insn_consumer_->Op(args); 1197 } else { 1198 Op32Opcode opcode; 1199 switch (GetBits<5, 2>()) { 1200 case 0b00: 1201 opcode = Op32Opcode::kSubw; 1202 break; 1203 case 0b01: 1204 opcode = Op32Opcode::kAddw; 1205 break; 1206 default: 1207 return Undefined(); 1208 } 1209 const Op32Args args = { 1210 .opcode = opcode, 1211 .dst = r, 1212 .src1 = r, 1213 .src2 = rs2, 1214 }; 1215 return insn_consumer_->Op(args); 1216 } 1217 } 1218 1219 template <auto kOperandType> DecodeCompressedStoresp()1220 void DecodeCompressedStoresp() { 1221 uint8_t raw_imm = GetBits<7, 6>(); 1222 uint8_t rs2 = GetBits<2, 5>(); 1223 constexpr uint8_t k32bit[64] = { 1224 0x00, 0x10, 0x20, 0x30, 0x01, 0x11, 0x21, 0x31, 0x02, 0x12, 0x22, 0x32, 0x03, 1225 0x13, 0x23, 0x33, 0x04, 0x14, 0x24, 0x34, 0x05, 0x15, 0x25, 0x35, 0x06, 0x16, 1226 0x26, 0x36, 0x07, 0x17, 0x27, 0x37, 0x08, 0x18, 0x28, 0x38, 0x09, 0x19, 0x29, 1227 0x39, 0x0a, 0x1a, 0x2a, 0x3a, 0x0b, 0x1b, 0x2b, 0x3b, 0x0c, 0x1c, 0x2c, 0x3c, 1228 0x0d, 0x1d, 0x2d, 0x3d, 0x0e, 0x1e, 0x2e, 0x3e, 0x0f, 0x1f, 0x2f, 0x3f}; 1229 constexpr uint8_t k64bit[64] = { 1230 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x02, 0x12, 0x22, 0x32, 0x42, 1231 0x52, 0x62, 0x72, 0x04, 0x14, 0x24, 0x34, 0x44, 0x54, 0x64, 0x74, 0x06, 0x16, 1232 0x26, 0x36, 0x46, 0x56, 0x66, 0x76, 0x08, 0x18, 0x28, 0x38, 0x48, 0x58, 0x68, 1233 0x78, 0x0a, 0x1a, 0x2a, 0x3a, 0x4a, 0x5a, 0x6a, 0x7a, 0x0c, 0x1c, 0x2c, 0x3c, 1234 0x4c, 0x5c, 0x6c, 0x7c, 0x0e, 0x1e, 0x2e, 0x3e, 0x4e, 0x5e, 0x6e, 0x7e}; 1235 int16_t imm = (((uint8_t(kOperandType) & 1) == 0) ? k32bit : k64bit)[raw_imm] << 2; 1236 const StoreArgsTemplate<decltype(kOperandType)> args = { 1237 .operand_type = kOperandType, 1238 .src = 2, 1239 .offset = imm, 1240 .data = rs2, 1241 }; 1242 insn_consumer_->Store(args); 1243 } 1244 DecodeCompressedLuiAddi16sp()1245 void DecodeCompressedLuiAddi16sp() { 1246 uint8_t low_imm = GetBits<2, 5>(); 1247 uint8_t high_imm = GetBits<12, 1>(); 1248 uint8_t rd = GetBits<7, 5>(); 1249 if (rd != 2) { 1250 int32_t imm = SignExtend<18>((high_imm << 17) + (low_imm << 12)); 1251 const UpperImmArgs args = { 1252 .dst = rd, 1253 .imm = imm, 1254 }; 1255 return insn_consumer_->Lui(args); 1256 } 1257 constexpr uint8_t kAddi16spLow[32] = {0x00, 0x08, 0x20, 0x28, 0x40, 0x48, 0x60, 0x68, 1258 0x10, 0x18, 0x30, 0x38, 0x50, 0x58, 0x70, 0x78, 1259 0x04, 0x0c, 0x24, 0x2c, 0x44, 0x4c, 0x64, 0x6c, 1260 0x14, 0x1c, 0x34, 0x3c, 0x54, 0x5c, 0x74, 0x7c}; 1261 int16_t imm = SignExtend<10>((high_imm << 9) + (kAddi16spLow[low_imm] << 2)); 1262 const OpImmArgs args = { 1263 .opcode = OpImmOpcode::kAddi, 1264 .dst = 2, 1265 .src = 2, 1266 .imm = imm, 1267 }; 1268 insn_consumer_->OpImm(args); 1269 } 1270 1271 enum class LoadStore { kLoad, kStore }; 1272 1273 template <enum LoadStore kLoadStore, auto kOperandType> DecodeCompressedLoadStore()1274 void DecodeCompressedLoadStore() { 1275 uint8_t low_imm = GetBits<5, 2>(); 1276 uint8_t high_imm = GetBits<10, 3>(); 1277 uint8_t imm; 1278 if constexpr ((uint8_t(kOperandType) & 1) == 0) { 1279 constexpr uint8_t kLwLow[4] = {0x0, 0x40, 0x04, 0x44}; 1280 imm = (kLwLow[low_imm] | high_imm << 3); 1281 } else { 1282 imm = (low_imm << 6 | high_imm << 3); 1283 } 1284 uint8_t rd = GetBits<2, 3>(); 1285 uint8_t rs = GetBits<7, 3>(); 1286 if constexpr (kLoadStore == LoadStore::kStore) { 1287 const StoreArgsTemplate<decltype(kOperandType)> args = { 1288 .operand_type = kOperandType, 1289 .src = uint8_t(8 + rs), 1290 .offset = imm, 1291 .data = uint8_t(8 + rd), 1292 }; 1293 insn_consumer_->Store(args); 1294 } else { 1295 const LoadArgsTemplate<decltype(kOperandType)> args = { 1296 .operand_type = kOperandType, 1297 .dst = uint8_t(8 + rd), 1298 .src = uint8_t(8 + rs), 1299 .offset = imm, 1300 }; 1301 insn_consumer_->Load(args); 1302 } 1303 } 1304 1305 template <auto kOperandType> DecodeCompressedLoadsp()1306 void DecodeCompressedLoadsp() { 1307 uint8_t low_imm = GetBits<2, 5>(); 1308 uint8_t high_imm = GetBits<12, 1>(); 1309 uint8_t rd = GetBits<7, 5>(); 1310 constexpr uint8_t k32bitLow[32] = {0x00, 0x10, 0x20, 0x30, 0x01, 0x11, 0x21, 0x31, 1311 0x02, 0x12, 0x22, 0x32, 0x03, 0x13, 0x23, 0x33, 1312 0x04, 0x14, 0x24, 0x34, 0x05, 0x15, 0x25, 0x35, 1313 0x06, 0x16, 0x26, 0x36, 0x07, 0x17, 0x27, 0x37}; 1314 constexpr uint8_t k64bitLow[32] = {0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 1315 0x02, 0x12, 0x22, 0x32, 0x42, 0x52, 0x62, 0x72, 1316 0x04, 0x14, 0x24, 0x34, 0x44, 0x54, 0x64, 0x74, 1317 0x06, 0x16, 0x26, 0x36, 0x46, 0x56, 0x66, 0x76}; 1318 int16_t imm = (high_imm << 5) + 1319 ((((uint8_t(kOperandType) & 1) == 0) ? k32bitLow : k64bitLow)[low_imm] << 2); 1320 const LoadArgsTemplate<decltype(kOperandType)> args = { 1321 .operand_type = kOperandType, 1322 .dst = rd, 1323 .src = 2, 1324 .offset = imm, 1325 }; 1326 insn_consumer_->Load(args); 1327 } 1328 DecodeCompressedAddi()1329 void DecodeCompressedAddi() { 1330 uint8_t low_imm = GetBits<2, 5>(); 1331 uint8_t high_imm = GetBits<12, 1>(); 1332 int8_t imm = SignExtend<6>(high_imm << 5 | low_imm); 1333 uint8_t r = GetBits<7, 5>(); 1334 if (r == 0 || imm == 0) { 1335 insn_consumer_->Nop(); 1336 } 1337 const OpImmArgs args = { 1338 .opcode = OpImmOpcode::kAddi, 1339 .dst = r, 1340 .src = r, 1341 .imm = imm, 1342 }; 1343 insn_consumer_->OpImm(args); 1344 } 1345 DecodeCompressedAddiw()1346 void DecodeCompressedAddiw() { 1347 uint8_t low_imm = GetBits<2, 5>(); 1348 uint8_t high_imm = GetBits<12, 1>(); 1349 int8_t imm = SignExtend<6>(high_imm << 5 | low_imm); 1350 uint8_t r = GetBits<7, 5>(); 1351 const OpImm32Args args = { 1352 .opcode = OpImm32Opcode::kAddiw, 1353 .dst = r, 1354 .src = r, 1355 .imm = imm, 1356 }; 1357 insn_consumer_->OpImm(args); 1358 } 1359 DecodeCompressedBeqzBnez()1360 void DecodeCompressedBeqzBnez() { 1361 constexpr uint16_t kBHigh[8] = {0x0, 0x8, 0x10, 0x18, 0x100, 0x108, 0x110, 0x118}; 1362 constexpr uint8_t kBLow[32] = {0x00, 0x20, 0x02, 0x22, 0x04, 0x24, 0x06, 0x26, 0x40, 0x60, 0x42, 1363 0x62, 0x44, 0x64, 0x46, 0x66, 0x80, 0xa0, 0x82, 0xa2, 0x84, 0xa4, 1364 0x86, 0xa6, 0xc0, 0xe0, 0xc2, 0xe2, 0xc4, 0xe4, 0xc6, 0xe6}; 1365 uint8_t low_imm = GetBits<2, 5>(); 1366 uint8_t high_imm = GetBits<10, 3>(); 1367 uint8_t rs = GetBits<7, 3>(); 1368 1369 const BranchArgs args = { 1370 .opcode = BranchOpcode{GetBits<13, 1>()}, 1371 .src1 = uint8_t(8 + rs), 1372 .src2 = 0, 1373 .offset = static_cast<int16_t>(SignExtend<9>(kBHigh[high_imm] + kBLow[low_imm])), 1374 }; 1375 insn_consumer_->CompareAndBranch(args); 1376 } 1377 DecodeCompressedJ()1378 void DecodeCompressedJ() { 1379 constexpr uint16_t kJHigh[32] = { 1380 0x0, 0x400, 0x100, 0x500, 0x200, 0x600, 0x300, 0x700, 0x10, 0x410, 0x110, 1381 0x510, 0x210, 0x610, 0x310, 0x710, 0xf800, 0xfc00, 0xf900, 0xfd00, 0xfa00, 0xfe00, 1382 0xfb00, 0xff00, 0xf810, 0xfc10, 0xf910, 0xfd10, 0xfa10, 0xfe10, 0xfb10, 0xff10, 1383 }; 1384 constexpr uint8_t kJLow[64] = { 1385 0x0, 0x20, 0x2, 0x22, 0x4, 0x24, 0x6, 0x26, 0x8, 0x28, 0xa, 0x2a, 0xc, 1386 0x2c, 0xe, 0x2e, 0x80, 0xa0, 0x82, 0xa2, 0x84, 0xa4, 0x86, 0xa6, 0x88, 0xa8, 1387 0x8a, 0xaa, 0x8c, 0xac, 0x8e, 0xae, 0x40, 0x60, 0x42, 0x62, 0x44, 0x64, 0x46, 1388 0x66, 0x48, 0x68, 0x4a, 0x6a, 0x4c, 0x6c, 0x4e, 0x6e, 0xc0, 0xe0, 0xc2, 0xe2, 1389 0xc4, 0xe4, 0xc6, 0xe6, 0xc8, 0xe8, 0xca, 0xea, 0xcc, 0xec, 0xce, 0xee, 1390 }; 1391 const JumpAndLinkArgs args = { 1392 .dst = 0, 1393 .offset = bit_cast<int16_t>(kJHigh[GetBits<8, 5>()]) | kJLow[GetBits<2, 6>()], 1394 .insn_len = 2, 1395 }; 1396 insn_consumer_->JumpAndLink(args); 1397 } 1398 DecodeCompressedAddi4spn()1399 void DecodeCompressedAddi4spn() { 1400 constexpr uint8_t kAddi4spnHigh[16] = { 1401 0x0, 0x40, 0x80, 0xc0, 0x4, 0x44, 0x84, 0xc4, 0x8, 0x48, 0x88, 0xc8, 0xc, 0x4c, 0x8c, 0xcc}; 1402 constexpr uint8_t kAddi4spnLow[16] = { 1403 0x0, 0x2, 0x1, 0x3, 0x10, 0x12, 0x11, 0x13, 0x20, 0x22, 0x21, 0x23, 0x30, 0x32, 0x31, 0x33}; 1404 int16_t imm = (kAddi4spnHigh[GetBits<9, 4>()] | kAddi4spnLow[GetBits<5, 4>()]) << 2; 1405 // If immediate is zero then this instruction is treated as undefined. 1406 // This includes RISC-V dedicated 16bit “undefined instruction” 0x0000. 1407 if (imm == 0) { 1408 return Undefined(); 1409 } 1410 const OpImmArgs args = { 1411 .opcode = OpImmOpcode::kAddi, 1412 .dst = uint8_t(8 + GetBits<2, 3>()), 1413 .src = 2, 1414 .imm = imm, 1415 }; 1416 insn_consumer_->OpImm(args); 1417 } 1418 DecodeCompressedJr_Jalr_Mv_Add()1419 void DecodeCompressedJr_Jalr_Mv_Add() { 1420 uint8_t r = GetBits<7, 5>(); 1421 uint8_t rs2 = GetBits<2, 5>(); 1422 if (GetBits<12, 1>()) { 1423 if (r == 0 && rs2 == 0) { 1424 const SystemArgs args = { 1425 .opcode = SystemOpcode::kEbreak, 1426 }; 1427 return insn_consumer_->System(args); 1428 } else if (rs2 == 0) { 1429 const JumpAndLinkRegisterArgs args = { 1430 .dst = 1, 1431 .base = r, 1432 .offset = 0, 1433 .insn_len = 2, 1434 }; 1435 insn_consumer_->JumpAndLinkRegister(args); 1436 } else { 1437 const OpArgs args = { 1438 .opcode = OpOpcode::kAdd, 1439 .dst = r, 1440 .src1 = r, 1441 .src2 = rs2, 1442 }; 1443 insn_consumer_->Op(args); 1444 } 1445 } else { 1446 if (rs2 == 0) { 1447 const JumpAndLinkRegisterArgs args = { 1448 .dst = 0, 1449 .base = r, 1450 .offset = 0, 1451 .insn_len = 2, 1452 }; 1453 insn_consumer_->JumpAndLinkRegister(args); 1454 } else { 1455 const OpArgs args = { 1456 .opcode = OpOpcode::kAdd, 1457 .dst = r, 1458 .src1 = 0, 1459 .src2 = rs2, 1460 }; 1461 insn_consumer_->Op(args); 1462 } 1463 } 1464 } 1465 DecodeCompressedSlli()1466 void DecodeCompressedSlli() { 1467 uint8_t r = GetBits<7, 5>(); 1468 uint8_t low_imm = GetBits<2, 5>(); 1469 uint8_t high_imm = GetBits<12, 1>(); 1470 uint8_t imm = (high_imm << 5) + low_imm; 1471 const ShiftImmArgs args = { 1472 .opcode = ShiftImmOpcode::kSlli, 1473 .dst = r, 1474 .src = r, 1475 .imm = imm, 1476 }; 1477 return insn_consumer_->OpImm(args); 1478 } 1479 DecodeBaseInstruction()1480 uint8_t DecodeBaseInstruction() { 1481 BaseOpcode opcode_bits{GetBits<2, 5>()}; 1482 1483 switch (opcode_bits) { 1484 case BaseOpcode::kLoad: 1485 DecodeLoad<LoadOperandType>(); 1486 break; 1487 case BaseOpcode::kLoadFp: 1488 DecodeLoad<FloatOperandType>(); 1489 break; 1490 case BaseOpcode::kMiscMem: 1491 DecodeMiscMem(); 1492 break; 1493 case BaseOpcode::kOpImm: 1494 DecodeOp<OpImmOpcode, ShiftImmOpcode, BitmanipImmOpcode, 6>(); 1495 break; 1496 case BaseOpcode::kAuipc: 1497 DecodeAuipc(); 1498 break; 1499 case BaseOpcode::kOpImm32: 1500 DecodeOp<OpImm32Opcode, ShiftImm32Opcode, BitmanipImm32Opcode, 5>(); 1501 break; 1502 case BaseOpcode::kStore: 1503 DecodeStore<MemoryDataOperandType>(); 1504 break; 1505 case BaseOpcode::kStoreFp: 1506 DecodeStore<FloatOperandType>(); 1507 break; 1508 case BaseOpcode::kAmo: 1509 DecodeAmo(); 1510 break; 1511 case BaseOpcode::kOp: 1512 DecodeOp<OpOpcode>(); 1513 break; 1514 case BaseOpcode::kLui: 1515 DecodeLui(); 1516 break; 1517 case BaseOpcode::kOp32: 1518 DecodeOp<Op32Opcode>(); 1519 break; 1520 case BaseOpcode::kMAdd: 1521 case BaseOpcode::kMSub: 1522 case BaseOpcode::kNmSub: 1523 case BaseOpcode::kNmAdd: 1524 DecodeFma(); 1525 break; 1526 case BaseOpcode::kOpFp: 1527 DecodeOpFp(); 1528 break; 1529 case BaseOpcode::vOpV: 1530 DecodeOpV(); 1531 break; 1532 case BaseOpcode::kBranch: 1533 DecodeBranch(); 1534 break; 1535 case BaseOpcode::kJalr: 1536 DecodeJumpAndLinkRegister(); 1537 break; 1538 case BaseOpcode::kJal: 1539 DecodeJumpAndLink(); 1540 break; 1541 case BaseOpcode::kSystem: 1542 DecodeSystem(); 1543 break; 1544 default: 1545 insn_consumer_->Undefined(); 1546 } 1547 return 4; 1548 } 1549 1550 // Signextend bits from size to the corresponding signed type of sizeof(Type) size. 1551 // If the result of this function is assigned to a wider signed type it'll automatically 1552 // sign-extend. 1553 template <unsigned size, typename Type> SignExtend(const Type val)1554 static auto SignExtend(const Type val) { 1555 static_assert(std::is_integral_v<Type>, "Only integral types are supported"); 1556 static_assert(size > 0 && size < (sizeof(Type) * CHAR_BIT), "Invalid size value"); 1557 using SignedType = std::make_signed_t<Type>; 1558 struct { 1559 SignedType val : size; 1560 } holder = {.val = static_cast<SignedType>(val)}; 1561 // Compiler takes care of sign-extension of the field with the specified bit-length. 1562 return static_cast<SignedType>(holder.val); 1563 } 1564 1565 private: 1566 template <uint32_t start, uint32_t size> GetBits()1567 auto GetBits() { 1568 static_assert((start + size) <= 32 && size > 0, "Invalid start or size value"); 1569 using ResultType = std::conditional_t< 1570 size == 1, 1571 bool, 1572 std::conditional_t<size <= 8, uint8_t, std::conditional_t<size <= 16, uint16_t, uint32_t>>>; 1573 uint32_t shifted_val = code_ << (32 - start - size); 1574 return static_cast<ResultType>(shifted_val >> (32 - size)); 1575 } 1576 Undefined()1577 void Undefined() { insn_consumer_->Undefined(); } 1578 DecodeMiscMem()1579 void DecodeMiscMem() { 1580 uint8_t low_opcode = GetBits<12, 3>(); 1581 switch (low_opcode) { 1582 case 0b000: { 1583 uint8_t high_opcode = GetBits<28, 4>(); 1584 FenceOpcode opcode = FenceOpcode{high_opcode}; 1585 const FenceArgs args = { 1586 .opcode = opcode, 1587 .dst = GetBits<7, 5>(), 1588 .src = GetBits<15, 5>(), 1589 .sw = GetBits<20, 1>(), 1590 .sr = GetBits<21, 1>(), 1591 .so = GetBits<22, 1>(), 1592 .si = GetBits<23, 1>(), 1593 .pw = GetBits<24, 1>(), 1594 .pr = GetBits<25, 1>(), 1595 .po = GetBits<26, 1>(), 1596 .pi = GetBits<27, 1>(), 1597 }; 1598 insn_consumer_->Fence(args); 1599 break; 1600 } 1601 case 0b001: { 1602 uint16_t imm = GetBits<20, 12>(); 1603 const FenceIArgs args = { 1604 .dst = GetBits<7, 5>(), 1605 .src = GetBits<15, 5>(), 1606 .imm = SignExtend<12>(imm), 1607 }; 1608 insn_consumer_->FenceI(args); 1609 break; 1610 } 1611 default: 1612 return Undefined(); 1613 } 1614 } 1615 1616 template <typename OpcodeType> DecodeOp()1617 void DecodeOp() { 1618 uint8_t low_opcode = GetBits<12, 3>(); 1619 uint8_t high_opcode = GetBits<25, 7>(); 1620 uint16_t opcode_bits = static_cast<int16_t>(low_opcode | (high_opcode << 3)); 1621 OpcodeType opcode{opcode_bits}; 1622 OpSingleInputOpcode single_input_opcode{opcode_bits}; 1623 1624 switch (single_input_opcode) { 1625 case OpSingleInputOpcode::kZexth: { 1626 DecodeSingleInputOp(single_input_opcode); 1627 return; 1628 } 1629 default: 1630 break; 1631 } 1632 const OpArgsTemplate<OpcodeType> args = { 1633 .opcode = opcode, 1634 .dst = GetBits<7, 5>(), 1635 .src1 = GetBits<15, 5>(), 1636 .src2 = GetBits<20, 5>(), 1637 }; 1638 insn_consumer_->Op(args); 1639 } 1640 DecodeSingleInputOp(OpSingleInputOpcode opcode)1641 void DecodeSingleInputOp(OpSingleInputOpcode opcode) { 1642 uint8_t src1 = GetBits<15, 5>(); 1643 uint8_t src2 = GetBits<20, 5>(); 1644 1645 if (src2 != 0) { 1646 return Undefined(); 1647 } 1648 const OpSingleInputArgs args = {.opcode = opcode, .dst = GetBits<7, 5>(), .src = src1}; 1649 insn_consumer_->OpSingleInput(args); 1650 } 1651 DecodeAmo()1652 void DecodeAmo() { 1653 uint8_t low_opcode = GetBits<12, 3>(); 1654 uint8_t high_opcode = GetBits<27, 5>(); 1655 // lr instruction must have rs2 == 0 1656 if (high_opcode == 0b00010 && GetBits<20, 5>() != 0) { 1657 return Undefined(); 1658 } 1659 AmoOpcode opcode = AmoOpcode{high_opcode}; 1660 MemoryDataOperandType operand_type = MemoryDataOperandType{low_opcode}; 1661 const AmoArgs args = { 1662 .opcode = opcode, 1663 .operand_type = operand_type, 1664 .dst = GetBits<7, 5>(), 1665 .src1 = GetBits<15, 5>(), 1666 .src2 = GetBits<20, 5>(), 1667 .rl = GetBits<25, 1>(), 1668 .aq = GetBits<26, 1>(), 1669 }; 1670 insn_consumer_->Amo(args); 1671 } 1672 DecodeFma()1673 void DecodeFma() { 1674 uint8_t operand_type = GetBits<25, 2>(); 1675 uint8_t opcode_bits = GetBits<2, 2>(); 1676 const FmaArgs args = { 1677 .opcode = FmaOpcode{opcode_bits}, 1678 .operand_type = FloatOperandType{operand_type}, 1679 .dst = GetBits<7, 5>(), 1680 .src1 = GetBits<15, 5>(), 1681 .src2 = GetBits<20, 5>(), 1682 .src3 = GetBits<27, 5>(), 1683 .rm = GetBits<12, 3>(), 1684 }; 1685 insn_consumer_->Fma(args); 1686 } 1687 DecodeLui()1688 void DecodeLui() { 1689 int32_t imm = GetBits<12, 20>(); 1690 const UpperImmArgs args = { 1691 .dst = GetBits<7, 5>(), 1692 .imm = imm << 12, 1693 }; 1694 insn_consumer_->Lui(args); 1695 } 1696 DecodeAuipc()1697 void DecodeAuipc() { 1698 int32_t imm = GetBits<12, 20>(); 1699 const UpperImmArgs args = { 1700 .dst = GetBits<7, 5>(), 1701 .imm = imm << 12, 1702 }; 1703 insn_consumer_->Auipc(args); 1704 } 1705 1706 template <typename OperandTypeEnum> DecodeLoad()1707 void DecodeLoad() { 1708 OperandTypeEnum operand_type; 1709 if constexpr (std::is_same_v<OperandTypeEnum, FloatOperandType>) { 1710 auto decoded_operand_type = kLoadStoreWidthToOperandType[GetBits<12, 3>()]; 1711 if (decoded_operand_type.is_vector_instruction) { 1712 if (GetBits<28, 1>() == 1) { 1713 return Undefined(); 1714 } 1715 switch (GetBits<26, 2>()) { 1716 case 0b00: { 1717 const VLoadUnitStrideArgs args = { 1718 .opcode = VLUmOpOpcode{GetBits<20, 5>()}, 1719 .width = decoded_operand_type.eew, 1720 .vm = GetBits<25, 1>(), 1721 .nf = GetBits<29, 3>(), 1722 .dst = GetBits<7, 5>(), 1723 .src = GetBits<15, 5>(), 1724 }; 1725 return insn_consumer_->OpVector(args); 1726 } 1727 case 0b01: 1728 case 0b11: { 1729 const VLoadIndexedArgs args = { 1730 .width = decoded_operand_type.eew, 1731 .vm = GetBits<25, 1>(), 1732 .ordered = GetBits<27, 1>(), 1733 .nf = GetBits<29, 3>(), 1734 .dst = GetBits<7, 5>(), 1735 .src = GetBits<15, 5>(), 1736 .idx = GetBits<20, 5>(), 1737 }; 1738 return insn_consumer_->OpVector(args); 1739 } 1740 case 0b10: { 1741 const VLoadStrideArgs args = { 1742 .width = decoded_operand_type.eew, 1743 .vm = GetBits<25, 1>(), 1744 .ordered = GetBits<27, 1>(), 1745 .nf = GetBits<29, 3>(), 1746 .dst = GetBits<7, 5>(), 1747 .src = GetBits<15, 5>(), 1748 .std = GetBits<20, 5>(), 1749 }; 1750 return insn_consumer_->OpVector(args); 1751 } 1752 default: 1753 return Undefined(); 1754 } 1755 return Undefined(); 1756 } 1757 operand_type = decoded_operand_type.size; 1758 } else { 1759 operand_type = OperandTypeEnum{GetBits<12, 3>()}; 1760 } 1761 const LoadArgsTemplate<OperandTypeEnum> args = { 1762 .operand_type = operand_type, 1763 .dst = GetBits<7, 5>(), 1764 .src = GetBits<15, 5>(), 1765 .offset = SignExtend<12>(GetBits<20, 12>()), 1766 }; 1767 insn_consumer_->Load(args); 1768 } 1769 1770 template <typename OperandTypeEnum> DecodeStore()1771 void DecodeStore() { 1772 OperandTypeEnum operand_type; 1773 if constexpr (std::is_same_v<OperandTypeEnum, FloatOperandType>) { 1774 auto decoded_operand_type = kLoadStoreWidthToOperandType[GetBits<12, 3>()]; 1775 if (decoded_operand_type.is_vector_instruction) { 1776 if (GetBits<28, 1>() == 1) { 1777 return Undefined(); 1778 } 1779 switch (GetBits<26, 2>()) { 1780 case 0b00: { 1781 const VStoreUnitStrideArgs args = { 1782 .opcode = VSUmOpOpcode{GetBits<20, 5>()}, 1783 .width = decoded_operand_type.eew, 1784 .vm = GetBits<25, 1>(), 1785 .nf = GetBits<29, 3>(), 1786 .src = GetBits<15, 5>(), 1787 .data = GetBits<7, 5>(), 1788 }; 1789 return insn_consumer_->OpVector(args); 1790 } 1791 case 0b01: 1792 case 0b11: { 1793 const VStoreIndexedArgs args = { 1794 .width = decoded_operand_type.eew, 1795 .vm = GetBits<25, 1>(), 1796 .ordered = GetBits<27, 1>(), 1797 .nf = GetBits<29, 3>(), 1798 .src = GetBits<15, 5>(), 1799 .idx = GetBits<20, 5>(), 1800 .data = GetBits<7, 5>(), 1801 }; 1802 return insn_consumer_->OpVector(args); 1803 } 1804 case 0b10: { 1805 const VStoreStrideArgs args = { 1806 .width = decoded_operand_type.eew, 1807 .vm = GetBits<25, 1>(), 1808 .ordered = GetBits<27, 1>(), 1809 .nf = GetBits<29, 3>(), 1810 .src = GetBits<15, 5>(), 1811 .std = GetBits<20, 5>(), 1812 .data = GetBits<7, 5>(), 1813 }; 1814 return insn_consumer_->OpVector(args); 1815 } 1816 default: 1817 return Undefined(); 1818 } 1819 return Undefined(); 1820 } 1821 1822 operand_type = decoded_operand_type.size; 1823 } else { 1824 operand_type = OperandTypeEnum{GetBits<12, 3>()}; 1825 } 1826 1827 uint16_t low_imm = GetBits<7, 5>(); 1828 uint16_t high_imm = GetBits<25, 7>(); 1829 1830 const StoreArgsTemplate<OperandTypeEnum> args = { 1831 .operand_type = operand_type, 1832 .src = GetBits<15, 5>(), 1833 .offset = SignExtend<12>(static_cast<int16_t>(low_imm | (high_imm << 5))), 1834 .data = GetBits<20, 5>(), 1835 }; 1836 insn_consumer_->Store(args); 1837 } 1838 1839 template <typename OpOpcodeType, 1840 typename ShiftOpcodeType, 1841 typename BitmanipOpcodeType, 1842 uint32_t kShiftFieldSize> DecodeOp()1843 void DecodeOp() { 1844 uint8_t low_opcode = GetBits<12, 3>(); 1845 if (low_opcode != 0b001 && low_opcode != 0b101) { 1846 OpOpcodeType opcode{low_opcode}; 1847 1848 uint16_t imm = GetBits<20, 12>(); 1849 1850 const OpImmArgsTemplate<OpOpcodeType> args = { 1851 .opcode = opcode, 1852 .dst = GetBits<7, 5>(), 1853 .src = GetBits<15, 5>(), 1854 .imm = SignExtend<12>(imm), 1855 }; 1856 insn_consumer_->OpImm(args); 1857 } else if ((GetBits<31, 1>() + GetBits<20 + kShiftFieldSize, 10 - kShiftFieldSize>()) == 1858 0) { // For Canonical Shift Instructions from RV64G the opcode contains all 1859 // zeros except for the 30th (second highest) bit. 1860 uint16_t high_opcode = GetBits<20 + kShiftFieldSize, 12 - kShiftFieldSize>(); 1861 ShiftOpcodeType opcode{ 1862 static_cast<std::underlying_type_t<ShiftOpcodeType>>(low_opcode | (high_opcode << 3))}; 1863 1864 const ShiftImmArgsTemplate<ShiftOpcodeType> args = { 1865 .opcode = opcode, 1866 .dst = GetBits<7, 5>(), 1867 .src = GetBits<15, 5>(), 1868 .imm = GetBits<20, kShiftFieldSize>(), 1869 }; 1870 insn_consumer_->OpImm(args); 1871 } else { 1872 uint8_t shamt = GetBits<20, kShiftFieldSize>(); 1873 uint16_t high_opcode = GetBits<20 + kShiftFieldSize, 12 - kShiftFieldSize>(); 1874 BitmanipOpcodeType opcode{static_cast<uint16_t>(low_opcode | (high_opcode << 3))}; 1875 bool has_shamt = false; 1876 1877 switch ((BitmanipImmOpcode)opcode) { 1878 case BitmanipImmOpcode::kRori: 1879 case BitmanipImmOpcode::kBclri: 1880 case BitmanipImmOpcode::kBexti: 1881 case BitmanipImmOpcode::kBinvi: 1882 case BitmanipImmOpcode::kBseti: 1883 has_shamt = true; 1884 break; 1885 default: 1886 break; 1887 } 1888 1889 switch ((BitmanipImm32Opcode)opcode) { 1890 case BitmanipImm32Opcode::kRoriw: 1891 case BitmanipImm32Opcode::kSlliuw: 1892 has_shamt = true; 1893 break; 1894 default: 1895 break; 1896 } 1897 // TODO(b/291851792): Refactor instructions with shamt into ShiftImmArgs 1898 if (!has_shamt) { 1899 high_opcode = GetBits<20, 12>(); 1900 opcode = BitmanipOpcodeType{static_cast<uint16_t>(low_opcode | (high_opcode << 3))}; 1901 shamt = 0; 1902 } 1903 const BitmanipImmArgsTemplate<BitmanipOpcodeType> args = { 1904 .opcode = opcode, 1905 .dst = GetBits<7, 5>(), 1906 .src = GetBits<15, 5>(), 1907 .shamt = shamt, 1908 }; 1909 insn_consumer_->OpImm(args); 1910 } 1911 } 1912 DecodeBranch()1913 void DecodeBranch() { 1914 BranchOpcode opcode{GetBits<12, 3>()}; 1915 1916 // Decode the offset. 1917 auto low_imm = GetBits<8, 4>(); 1918 auto mid_imm = GetBits<25, 6>(); 1919 auto bit11_imm = GetBits<7, 1>(); 1920 auto bit12_imm = GetBits<31, 1>(); 1921 auto offset = 1922 static_cast<int16_t>(low_imm | (mid_imm << 4) | (bit11_imm << 10) | (bit12_imm << 11)); 1923 1924 const BranchArgs args = { 1925 .opcode = opcode, 1926 .src1 = GetBits<15, 5>(), 1927 .src2 = GetBits<20, 5>(), 1928 // The offset is encoded as 2-byte units, we need to multiply by 2. 1929 .offset = SignExtend<13>(static_cast<int16_t>(offset * 2)), 1930 }; 1931 insn_consumer_->CompareAndBranch(args); 1932 } 1933 DecodeJumpAndLink()1934 void DecodeJumpAndLink() { 1935 // Decode the offset. 1936 auto low_imm = GetBits<21, 10>(); 1937 auto mid_imm = GetBits<12, 8>(); 1938 auto bit11_imm = GetBits<20, 1>(); 1939 auto bit20_imm = GetBits<31, 1>(); 1940 auto offset = 1941 static_cast<int32_t>(low_imm | (bit11_imm << 10) | (mid_imm << 11) | (bit20_imm << 19)); 1942 1943 const JumpAndLinkArgs args = { 1944 .dst = GetBits<7, 5>(), 1945 // The offset is encoded as 2-byte units, we need to multiply by 2. 1946 .offset = SignExtend<21>(offset * 2), 1947 .insn_len = 4, 1948 }; 1949 insn_consumer_->JumpAndLink(args); 1950 } 1951 DecodeOpFp()1952 void DecodeOpFp() { 1953 // Bit #29 = 1: means rm is an opcode extension and not operand. 1954 // Bit #30 = 1: means rs2 is an opcode extension and not operand. 1955 // Bit #31 = 1: selects general purpose register instead of floating point register as target. 1956 uint8_t operand_type = GetBits<25, 2>(); 1957 uint8_t opcode_bits = GetBits<27, 2>(); 1958 uint8_t rd = GetBits<7, 5>(); 1959 uint8_t rs1 = GetBits<15, 5>(); 1960 uint8_t rs2 = GetBits<20, 5>(); 1961 uint8_t rm = GetBits<12, 3>(); 1962 switch (GetBits<29, 3>()) { 1963 case 0b000: { 1964 const OpFpArgs args = { 1965 .opcode = OpFpOpcode{opcode_bits}, 1966 .operand_type = FloatOperandType{operand_type}, 1967 .dst = rd, 1968 .src1 = rs1, 1969 .src2 = rs2, 1970 .rm = rm, 1971 }; 1972 return insn_consumer_->OpFp(args); 1973 } 1974 case 0b001: { 1975 uint8_t no_rounding_opcode_bits = (opcode_bits << 3) + rm; 1976 OpFpNoRoundingOpcode no_rounding_opcode = OpFpNoRoundingOpcode{no_rounding_opcode_bits}; 1977 if (no_rounding_opcode == Decoder::OpFpNoRoundingOpcode::kFSgnj && rs1 == rs2) { 1978 const OpFpSingleInputNoRoundingArgs args = { 1979 .opcode = OpFpSingleInputNoRoundingOpcode::kFmv, 1980 .operand_type = FloatOperandType{operand_type}, 1981 .dst = rd, 1982 .src = rs1, 1983 }; 1984 return insn_consumer_->OpFpSingleInputNoRounding(args); 1985 } 1986 const OpFpNoRoundingArgs args = { 1987 .opcode = no_rounding_opcode, 1988 .operand_type = FloatOperandType{operand_type}, 1989 .dst = rd, 1990 .src1 = rs1, 1991 .src2 = rs2, 1992 }; 1993 return insn_consumer_->OpFpNoRounding(args); 1994 } 1995 case 0b010: { 1996 if (opcode_bits == 0) { 1997 // Conversion from one float to the same float type is not supported. 1998 if (operand_type == rs2) { 1999 return Undefined(); 2000 } 2001 // Values larger than 0b11 are reserved in Fcvt. 2002 if (rs2 > 0b11) { 2003 return Undefined(); 2004 } 2005 const FcvtFloatToFloatArgs args = { 2006 .dst_type = FloatOperandType{operand_type}, 2007 .src_type = FloatOperandType{rs2}, 2008 .dst = rd, 2009 .src = rs1, 2010 .rm = rm, 2011 }; 2012 return insn_consumer_->Fcvt(args); 2013 } 2014 uint8_t opcode = (opcode_bits << 5) + rs2; 2015 const OpFpSingleInputArgs args = { 2016 .opcode = OpFpSingleInputOpcode{opcode}, 2017 .operand_type = FloatOperandType{operand_type}, 2018 .dst = rd, 2019 .src = rs1, 2020 .rm = rm, 2021 }; 2022 return insn_consumer_->OpFpSingleInput(args); 2023 } 2024 case 0b101: { 2025 uint8_t opcode = (opcode_bits << 3) + rm; 2026 const OpFpGpRegisterTargetNoRoundingArgs args = { 2027 .opcode = OpFpGpRegisterTargetNoRoundingOpcode{opcode}, 2028 .operand_type = FloatOperandType{operand_type}, 2029 .dst = rd, 2030 .src1 = rs1, 2031 .src2 = rs2, 2032 }; 2033 return insn_consumer_->OpFpGpRegisterTargetNoRounding(args); 2034 } 2035 case 0b110: 2036 switch (opcode_bits) { 2037 case 0b00: { 2038 const FcvtFloatToIntegerArgs args = { 2039 .dst_type = FcvtOperandType{rs2}, 2040 .src_type = FloatOperandType{operand_type}, 2041 .dst = rd, 2042 .src = rs1, 2043 .rm = rm, 2044 }; 2045 return insn_consumer_->Fcvt(args); 2046 } 2047 case 0b10: { 2048 const FcvtIntegerToFloatArgs args = { 2049 .dst_type = FloatOperandType{operand_type}, 2050 .src_type = FcvtOperandType{rs2}, 2051 .dst = rd, 2052 .src = rs1, 2053 .rm = rm, 2054 }; 2055 return insn_consumer_->Fcvt(args); 2056 } 2057 default: 2058 return Undefined(); 2059 } 2060 case 0b111: { 2061 uint16_t opcode = (opcode_bits << 8) + (rs2 << 3) + rm; 2062 switch (rm) { 2063 case 0b001: { 2064 const OpFpGpRegisterTargetSingleInputNoRoundingArgs args = { 2065 .opcode = OpFpGpRegisterTargetSingleInputNoRoundingOpcode{opcode}, 2066 .operand_type = FloatOperandType{operand_type}, 2067 .dst = rd, 2068 .src = rs1, 2069 }; 2070 return insn_consumer_->OpFpGpRegisterTargetSingleInputNoRounding(args); 2071 } 2072 case 0b000: { 2073 if (opcode_bits == 0b00) { 2074 const FmvFloatToIntegerArgs args = { 2075 .operand_type = FloatOperandType{operand_type}, 2076 .dst = rd, 2077 .src = rs1, 2078 }; 2079 return insn_consumer_->FmvFloatToInteger(args); 2080 } else if (opcode_bits == 0b10) { 2081 const FmvIntegerToFloatArgs args = { 2082 .operand_type = FloatOperandType{operand_type}, 2083 .dst = rd, 2084 .src = rs1, 2085 }; 2086 return insn_consumer_->FmvIntegerToFloat(args); 2087 } else { 2088 return Undefined(); 2089 } 2090 } 2091 default: 2092 return Undefined(); 2093 } 2094 } 2095 default: 2096 return Undefined(); 2097 } 2098 } 2099 DecodeOpV()2100 void DecodeOpV() { 2101 uint8_t low_opcode = GetBits<12, 3>(); 2102 bool vm = GetBits<25, 1>(); 2103 uint8_t opcode = GetBits<26, 6>(); 2104 uint8_t dst = GetBits<7, 5>(); 2105 // Note: in vector instructions vs2 field is 2nd operand while vs1 field is 3rd operand. 2106 // FMA instructions are exception, but there are not that many of these. 2107 uint8_t src1 = GetBits<20, 5>(); 2108 uint8_t src2 = GetBits<15, 5>(); 2109 switch (low_opcode) { 2110 case 0b000: { 2111 const VOpIVvArgs args = { 2112 .opcode = VOpIVvOpcode{opcode}, 2113 .vm = vm, 2114 .dst = dst, 2115 .src1 = src1, 2116 .src2 = src2, 2117 }; 2118 return insn_consumer_->OpVector(args); 2119 } 2120 case 0b001: { 2121 const VOpFVvArgs args = { 2122 .opcode = VOpFVvOpcode{opcode}, 2123 .vm = vm, 2124 .dst = dst, 2125 .src1 = src1, 2126 .src2 = src2, 2127 }; 2128 return insn_consumer_->OpVector(args); 2129 } 2130 case 0b010: { 2131 const VOpMVvArgs args = { 2132 .opcode = VOpMVvOpcode{opcode}, 2133 .vm = vm, 2134 .dst = dst, 2135 .src1 = src1, 2136 .src2 = src2, 2137 }; 2138 return insn_consumer_->OpVector(args); 2139 } 2140 case 0b011: { 2141 const VOpIViArgs args = { 2142 .opcode = VOpIViOpcode{opcode}, 2143 .vm = vm, 2144 .dst = dst, 2145 .src = src1, 2146 .uimm = src2, 2147 }; 2148 return insn_consumer_->OpVector(args); 2149 } 2150 case 0b100: { 2151 const VOpIVxArgs args = { 2152 .opcode = VOpIVxOpcode{opcode}, 2153 .vm = vm, 2154 .dst = dst, 2155 .src1 = src1, 2156 .src2 = src2, 2157 }; 2158 return insn_consumer_->OpVector(args); 2159 } 2160 case 0b101: { 2161 const VOpFVfArgs args = { 2162 .opcode = VOpFVfOpcode{opcode}, 2163 .vm = vm, 2164 .dst = dst, 2165 .src1 = src1, 2166 .src2 = src2, 2167 }; 2168 return insn_consumer_->OpVector(args); 2169 } 2170 case 0b110: { 2171 const VOpMVxArgs args = { 2172 .opcode = VOpMVxOpcode{opcode}, 2173 .vm = vm, 2174 .dst = dst, 2175 .src1 = src1, 2176 .src2 = src2, 2177 }; 2178 return insn_consumer_->OpVector(args); 2179 } 2180 case 0b111: 2181 if (GetBits<31, 1>() == 0) { 2182 const VsetvliArgs args = { 2183 .dst = GetBits<7, 5>(), 2184 .src = GetBits<15, 5>(), 2185 .vtype = GetBits<20, 11>(), 2186 }; 2187 return insn_consumer_->Vsetvli(args); 2188 } else if (GetBits<30, 1>() == 1) { 2189 const VsetivliArgs args = { 2190 .dst = GetBits<7, 5>(), 2191 .avl = GetBits<15, 5>(), 2192 .vtype = GetBits<20, 10>(), 2193 }; 2194 return insn_consumer_->Vsetivli(args); 2195 } else if (GetBits<25, 6>() == 0) { 2196 const VsetvlArgs args = { 2197 .dst = GetBits<7, 5>(), 2198 .src1 = GetBits<15, 5>(), 2199 .src2 = GetBits<20, 5>(), 2200 }; 2201 return insn_consumer_->Vsetvl(args); 2202 } 2203 } 2204 } 2205 DecodeSystem()2206 void DecodeSystem() { 2207 uint8_t low_opcode = GetBits<12, 2>(); 2208 if (low_opcode == 0b00) { 2209 uint32_t opcode = GetBits<7, 25>(); 2210 const SystemArgs args = { 2211 .opcode = SystemOpcode{opcode}, 2212 }; 2213 return insn_consumer_->System(args); 2214 } 2215 if (GetBits<14, 1>()) { 2216 CsrImmOpcode opcode = CsrImmOpcode{low_opcode}; 2217 const CsrImmArgs args = { 2218 .opcode = opcode, 2219 .dst = GetBits<7, 5>(), 2220 .imm = GetBits<15, 5>(), 2221 .csr = GetBits<20, 12>(), 2222 }; 2223 return insn_consumer_->Csr(args); 2224 } 2225 CsrOpcode opcode = CsrOpcode{low_opcode}; 2226 const CsrArgs args = { 2227 .opcode = opcode, 2228 .dst = GetBits<7, 5>(), 2229 .src = GetBits<15, 5>(), 2230 .csr = GetBits<20, 12>(), 2231 }; 2232 return insn_consumer_->Csr(args); 2233 } 2234 DecodeJumpAndLinkRegister()2235 void DecodeJumpAndLinkRegister() { 2236 if (GetBits<12, 3>() != 0b000) { 2237 Undefined(); 2238 return; 2239 } 2240 // Decode sign-extend offset. 2241 int16_t offset = GetBits<20, 12>(); 2242 offset = static_cast<int16_t>(offset << 4) >> 4; 2243 2244 const JumpAndLinkRegisterArgs args = { 2245 .dst = GetBits<7, 5>(), 2246 .base = GetBits<15, 5>(), 2247 .offset = offset, 2248 .insn_len = 4, 2249 }; 2250 insn_consumer_->JumpAndLinkRegister(args); 2251 } 2252 2253 enum class BaseOpcode { 2254 kLoad = 0b00'000, 2255 kLoadFp = 0b00'001, 2256 kCustom0 = 0b00'010, 2257 kMiscMem = 0b00'011, 2258 kOpImm = 0b00'100, 2259 kAuipc = 0b00'101, 2260 kOpImm32 = 0b00'110, 2261 // Reserved 0b00'111, 2262 kStore = 0b01'000, 2263 kStoreFp = 0b01'001, 2264 kCustom1 = 0b01'010, 2265 kAmo = 0b01'011, 2266 kOp = 0b01'100, 2267 kLui = 0b01'101, 2268 kOp32 = 0b01'110, 2269 // Reserved 0b01'111, 2270 kMAdd = 0b10'000, 2271 kMSub = 0b10'001, 2272 kNmSub = 0b10'010, 2273 kNmAdd = 0b10'011, 2274 kOpFp = 0b10'100, 2275 vOpV = 0b10'101, 2276 kCustom2 = 0b10'110, 2277 // Reserved 0b10'111, 2278 kBranch = 0b11'000, 2279 kJalr = 0b11'001, 2280 // Reserved 0b11'010, 2281 kJal = 0b11'011, 2282 kSystem = 0b11'100, 2283 // Reserved 0b11'101, 2284 kCustom3 = 0b11'110, 2285 // Reserved 0b11'111, 2286 }; 2287 2288 enum class CompressedOpcode { 2289 kAddi4spn = 0b00'000, 2290 kFld = 0b001'00, 2291 kLw = 0b010'00, 2292 kLd = 0b011'00, 2293 // Reserved 0b00'100 2294 kFsd = 0b101'00, 2295 kSw = 0b110'00, 2296 kSd = 0b111'00, 2297 kAddi = 0b000'01, 2298 kAddiw = 0b001'01, 2299 kLi = 0b010'01, 2300 kLui_Addi16sp = 0b011'01, 2301 kMisc_Alu = 0b100'01, 2302 kJ = 0b101'01, 2303 kBeqz = 0b110'01, 2304 kBnez = 0b111'01, 2305 kSlli = 0b000'10, 2306 kFldsp = 0b001'10, 2307 kLwsp = 0b010'10, 2308 kLdsp = 0b011'10, 2309 kJr_Jalr_Mv_Add = 0b100'10, 2310 kFsdsp = 0b101'10, 2311 kSwsp = 0b110'10, 2312 kSdsp = 0b111'10, 2313 // instruction with 0bxxx'11 opcodes are not compressed instruction and can not be in this 2314 // table. 2315 }; 2316 2317 static constexpr struct { 2318 bool is_vector_instruction; 2319 union { 2320 FloatOperandType size; 2321 MemoryDataOperandType eew; 2322 }; 2323 } kLoadStoreWidthToOperandType[8] = { 2324 {.is_vector_instruction = true, .eew = MemoryDataOperandType::k8bit}, 2325 {.is_vector_instruction = false, .size = FloatOperandType::kHalf}, 2326 {.is_vector_instruction = false, .size = FloatOperandType::kFloat}, 2327 {.is_vector_instruction = false, .size = FloatOperandType::kDouble}, 2328 {.is_vector_instruction = false, .size = FloatOperandType::kQuad}, 2329 {.is_vector_instruction = true, .eew = MemoryDataOperandType::k16bit}, 2330 {.is_vector_instruction = true, .eew = MemoryDataOperandType::k32bit}, 2331 {.is_vector_instruction = true, .eew = MemoryDataOperandType::k64bit}}; 2332 2333 InsnConsumer* insn_consumer_; 2334 uint32_t code_; 2335 }; 2336 2337 } // namespace berberis 2338 2339 #endif // BERBERIS_DECODER_RISCV64_DECODER_H_ 2340