golang.org/x/arch@v0.17.0/riscv64/riscv64asm/decode.go (about) 1 // Copyright 2024 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package riscv64asm 6 7 import ( 8 "encoding/binary" 9 "errors" 10 ) 11 12 type argTypeList [6]argType 13 14 // An instFormat describes the format of an instruction encoding. 15 type instFormat struct { 16 mask uint32 17 value uint32 18 op Op 19 // args describe how to decode the instruction arguments. 20 // args is stored as a fixed-size array. 21 // if there are fewer than len(args) arguments, args[i] == 0 marks 22 // the end of the argument list. 23 args argTypeList 24 } 25 26 var ( 27 errShort = errors.New("truncated instruction") 28 errUnknown = errors.New("unknown instruction") 29 ) 30 31 var decoderCover []bool 32 33 func init() { 34 decoderCover = make([]bool, len(instFormats)) 35 } 36 37 // Decode decodes the 4 bytes in src as a single instruction. 38 func Decode(src []byte) (Inst, error) { 39 length := len(src) 40 if length < 2 { 41 return Inst{}, errShort 42 } 43 44 var x uint32 45 // Non-RVC instructions always starts with 0x11 46 // So check whether src[0] & 3 == 3 47 if src[0]&3 == 3 { 48 if length < 4 { 49 return Inst{}, errShort 50 } 51 length = 4 52 x = binary.LittleEndian.Uint32(src) 53 } else { 54 length = 2 55 x = uint32(binary.LittleEndian.Uint16(src)) 56 } 57 58 Search: 59 for i, f := range instFormats { 60 if (x & f.mask) != f.value { 61 continue 62 } 63 64 // Decode args. 65 var args Args 66 for j, aop := range f.args { 67 if aop == 0 { 68 break 69 } 70 arg := decodeArg(aop, x, i) 71 if arg == nil && f.op != C_NOP { 72 // Cannot decode argument. 73 continue Search 74 } 75 args[j] = arg 76 } 77 78 if length == 2 { 79 args = convertCompressedIns(&f, args) 80 } 81 82 decoderCover[i] = true 83 inst := Inst{ 84 Op: f.op, 85 Args: args, 86 Enc: x, 87 Len: length, 88 } 89 return inst, nil 90 } 91 return Inst{}, errUnknown 92 } 93 94 // decodeArg decodes the arg described by aop from the instruction bits x. 95 // It returns nil if x cannot be decoded according to aop. 96 func decodeArg(aop argType, x uint32, index int) Arg { 97 switch aop { 98 case arg_rd: 99 return X0 + Reg((x>>7)&((1<<5)-1)) 100 101 case arg_rs1: 102 return X0 + Reg((x>>15)&((1<<5)-1)) 103 104 case arg_rs2: 105 return X0 + Reg((x>>20)&((1<<5)-1)) 106 107 case arg_rs3: 108 return X0 + Reg((x>>27)&((1<<5)-1)) 109 110 case arg_fd: 111 return F0 + Reg((x>>7)&((1<<5)-1)) 112 113 case arg_fs1: 114 return F0 + Reg((x>>15)&((1<<5)-1)) 115 116 case arg_fs2: 117 return F0 + Reg((x>>20)&((1<<5)-1)) 118 119 case arg_fs3: 120 return F0 + Reg((x>>27)&((1<<5)-1)) 121 122 case arg_rs1_amo: 123 return AmoReg{X0 + Reg((x>>15)&((1<<5)-1))} 124 125 case arg_rs1_mem: 126 imm := x >> 20 127 // Sign-extend 128 if imm>>uint32(12-1) == 1 { 129 imm |= 0xfffff << 12 130 } 131 return RegOffset{X0 + Reg((x>>15)&((1<<5)-1)), Simm{int32(imm), true, 12}} 132 133 case arg_rs1_store: 134 imm := (x<<20)>>27 | (x>>25)<<5 135 // Sign-extend 136 if imm>>uint32(12-1) == 1 { 137 imm |= 0xfffff << 12 138 } 139 return RegOffset{X0 + Reg((x>>15)&((1<<5)-1)), Simm{int32(imm), true, 12}} 140 141 case arg_pred: 142 imm := x << 4 >> 28 143 return MemOrder(uint8(imm)) 144 145 case arg_succ: 146 imm := x << 8 >> 28 147 return MemOrder(uint8(imm)) 148 149 case arg_csr: 150 imm := x >> 20 151 return CSR(imm) 152 153 case arg_zimm: 154 imm := x << 12 >> 27 155 return Uimm{imm, true} 156 157 case arg_shamt5: 158 imm := x << 7 >> 27 159 return Uimm{imm, false} 160 161 case arg_shamt6: 162 imm := x << 6 >> 26 163 return Uimm{imm, false} 164 165 case arg_imm12: 166 imm := x >> 20 167 // Sign-extend 168 if imm>>uint32(12-1) == 1 { 169 imm |= 0xfffff << 12 170 } 171 return Simm{int32(imm), true, 12} 172 173 case arg_imm20: 174 imm := x >> 12 175 return Uimm{imm, false} 176 177 case arg_jimm20: 178 imm := (x>>31)<<20 | (x<<1)>>22<<1 | (x<<11)>>31<<11 | (x<<12)>>24<<12 179 // Sign-extend 180 if imm>>uint32(21-1) == 1 { 181 imm |= 0x7ff << 21 182 } 183 return Simm{int32(imm), true, 21} 184 185 case arg_simm12: 186 imm := (x<<20)>>27 | (x>>25)<<5 187 // Sign-extend 188 if imm>>uint32(12-1) == 1 { 189 imm |= 0xfffff << 12 190 } 191 return Simm{int32(imm), true, 12} 192 193 case arg_bimm12: 194 imm := (x<<20)>>28<<1 | (x<<1)>>26<<5 | (x<<24)>>31<<11 | (x>>31)<<12 195 // Sign-extend 196 if imm>>uint32(13-1) == 1 { 197 imm |= 0x7ffff << 13 198 } 199 return Simm{int32(imm), true, 13} 200 201 case arg_rd_p, arg_rs2_p: 202 return X8 + Reg((x>>2)&((1<<3)-1)) 203 204 case arg_fd_p, arg_fs2_p: 205 return F8 + Reg((x>>2)&((1<<3)-1)) 206 207 case arg_rs1_p, arg_rd_rs1_p: 208 return X8 + Reg((x>>7)&((1<<3)-1)) 209 210 case arg_rd_n0, arg_rs1_n0, arg_rd_rs1_n0, arg_c_rs1_n0: 211 if X0+Reg((x>>7)&((1<<5)-1)) == X0 { 212 return nil 213 } 214 return X0 + Reg((x>>7)&((1<<5)-1)) 215 216 case arg_c_rs2_n0: 217 if X0+Reg((x>>2)&((1<<5)-1)) == X0 { 218 return nil 219 } 220 return X0 + Reg((x>>2)&((1<<5)-1)) 221 222 case arg_c_fs2: 223 return F0 + Reg((x>>2)&((1<<5)-1)) 224 225 case arg_c_rs2: 226 return X0 + Reg((x>>2)&((1<<5)-1)) 227 228 case arg_rd_n2: 229 if X0+Reg((x>>7)&((1<<5)-1)) == X0 || X0+Reg((x>>7)&((1<<5)-1)) == X2 { 230 return nil 231 } 232 return X0 + Reg((x>>7)&((1<<5)-1)) 233 234 case arg_c_imm6: 235 imm := (x<<25)>>27 | (x<<19)>>31<<5 236 // Sign-extend 237 if imm>>uint32(6-1) == 1 { 238 imm |= 0x3ffffff << 6 239 } 240 return Simm{int32(imm), true, 6} 241 242 case arg_c_nzimm6: 243 imm := (x<<25)>>27 | (x<<19)>>31<<5 244 // Sign-extend 245 if imm>>uint32(6-1) == 1 { 246 imm |= 0x3ffffff << 6 247 } 248 if int32(imm) == 0 { 249 return nil 250 } 251 return Simm{int32(imm), true, 6} 252 253 case arg_c_nzuimm6: 254 imm := (x<<25)>>27 | (x<<19)>>31<<5 255 if int32(imm) == 0 { 256 return nil 257 } 258 return Uimm{imm, false} 259 260 case arg_c_uimm7: 261 imm := (x<<26)>>31<<6 | (x<<25)>>31<<2 | (x<<19)>>29<<3 262 return Uimm{imm, false} 263 264 case arg_c_uimm8: 265 imm := (x<<25)>>30<<6 | (x<<19)>>29<<3 266 return Uimm{imm, false} 267 268 case arg_c_uimm8sp_s: 269 imm := (x<<23)>>30<<6 | (x<<19)>>28<<2 270 return Uimm{imm, false} 271 272 case arg_c_uimm8sp: 273 imm := (x<<25)>>29<<2 | (x<<19)>>31<<5 | (x<<28)>>30<<6 274 return Uimm{imm, false} 275 276 case arg_c_uimm9sp_s: 277 imm := (x<<22)>>29<<6 | (x<<19)>>29<<3 278 return Uimm{imm, false} 279 280 case arg_c_uimm9sp: 281 imm := (x<<25)>>30<<3 | (x<<19)>>31<<5 | (x<<27)>>29<<6 282 return Uimm{imm, false} 283 284 case arg_c_bimm9: 285 imm := (x<<29)>>31<<5 | (x<<27)>>30<<1 | (x<<25)>>30<<6 | (x<<19)>>31<<8 | (x<<20)>>30<<3 286 // Sign-extend 287 if imm>>uint32(9-1) == 1 { 288 imm |= 0x7fffff << 9 289 } 290 return Simm{int32(imm), true, 9} 291 292 case arg_c_nzimm10: 293 imm := (x<<29)>>31<<5 | (x<<27)>>30<<7 | (x<<26)>>31<<6 | (x<<25)>>31<<4 | (x<<19)>>31<<9 294 // Sign-extend 295 if imm>>uint32(10-1) == 1 { 296 imm |= 0x3fffff << 10 297 } 298 if int32(imm) == 0 { 299 return nil 300 } 301 return Simm{int32(imm), true, 10} 302 303 case arg_c_nzuimm10: 304 imm := (x<<26)>>31<<3 | (x<<25)>>31<<2 | (x<<21)>>28<<6 | (x<<19)>>30<<4 305 if int32(imm) == 0 { 306 return nil 307 } 308 return Uimm{imm, false} 309 310 case arg_c_imm12: 311 imm := (x<<29)>>31<<5 | (x<<26)>>28<<1 | (x<<25)>>31<<7 | (x<<24)>>31<<6 | (x<<23)>>31<<10 | (x<<21)>>30<<8 | (x<<20)>>31<<4 | (x<<19)>>31<<11 312 // Sign-extend 313 if imm>>uint32(12-1) == 1 { 314 imm |= 0xfffff << 12 315 } 316 return Simm{int32(imm), true, 12} 317 318 case arg_c_nzimm18: 319 imm := (x<<25)>>27<<12 | (x<<19)>>31<<17 320 // Sign-extend 321 if imm>>uint32(18-1) == 1 { 322 imm |= 0x3fff << 18 323 } 324 if int32(imm) == 0 { 325 return nil 326 } 327 return Simm{int32(imm), true, 18} 328 329 default: 330 return nil 331 } 332 } 333 334 // convertCompressedIns rewrites the RVC Instruction to regular Instructions 335 func convertCompressedIns(f *instFormat, args Args) Args { 336 var newargs Args 337 switch f.op { 338 case C_ADDI4SPN: 339 f.op = ADDI 340 newargs[0] = args[0] 341 newargs[1] = Reg(X2) 342 newargs[2] = Simm{int32(args[1].(Uimm).Imm), true, 12} 343 344 case C_LW: 345 f.op = LW 346 newargs[0] = args[0] 347 newargs[1] = RegOffset{args[1].(Reg), Simm{int32(args[2].(Uimm).Imm), true, 12}} 348 349 case C_SW: 350 f.op = SW 351 newargs[0] = args[1] 352 newargs[1] = RegOffset{args[0].(Reg), Simm{int32(args[2].(Uimm).Imm), true, 12}} 353 354 case C_NOP: 355 f.op = ADDI 356 newargs[0] = X0 357 newargs[1] = X0 358 newargs[2] = Simm{0, true, 12} 359 360 case C_ADDI: 361 f.op = ADDI 362 newargs[0] = args[0] 363 newargs[1] = args[0] 364 newargs[2] = Simm{args[1].(Simm).Imm, true, 12} 365 366 case C_LI: 367 f.op = ADDI 368 newargs[0] = args[0] 369 newargs[1] = Reg(X0) 370 newargs[2] = Simm{args[1].(Simm).Imm, true, 12} 371 372 case C_ADDI16SP: 373 f.op = ADDI 374 newargs[0] = Reg(X2) 375 newargs[1] = Reg(X2) 376 newargs[2] = Simm{args[0].(Simm).Imm, true, 12} 377 378 case C_LUI: 379 f.op = LUI 380 newargs[0] = args[0] 381 newargs[1] = Uimm{uint32(args[1].(Simm).Imm >> 12), false} 382 383 case C_ANDI: 384 f.op = ANDI 385 newargs[0] = args[0] 386 newargs[1] = args[0] 387 newargs[2] = Simm{args[1].(Simm).Imm, true, 12} 388 389 case C_SUB: 390 f.op = SUB 391 newargs[0] = args[0] 392 newargs[1] = args[0] 393 newargs[2] = args[1] 394 395 case C_XOR: 396 f.op = XOR 397 newargs[0] = args[0] 398 newargs[1] = args[0] 399 newargs[2] = args[1] 400 401 case C_OR: 402 f.op = OR 403 newargs[0] = args[0] 404 newargs[1] = args[0] 405 newargs[2] = args[1] 406 407 case C_AND: 408 f.op = AND 409 newargs[0] = args[0] 410 newargs[1] = args[0] 411 newargs[2] = args[1] 412 413 case C_J: 414 f.op = JAL 415 newargs[0] = Reg(X0) 416 newargs[1] = Simm{args[0].(Simm).Imm, true, 21} 417 418 case C_BEQZ: 419 f.op = BEQ 420 newargs[0] = args[0] 421 newargs[1] = Reg(X0) 422 newargs[2] = Simm{args[1].(Simm).Imm, true, 13} 423 424 case C_BNEZ: 425 f.op = BNE 426 newargs[0] = args[0] 427 newargs[1] = Reg(X0) 428 newargs[2] = Simm{args[1].(Simm).Imm, true, 13} 429 430 case C_LWSP: 431 f.op = LW 432 newargs[0] = args[0] 433 newargs[1] = RegOffset{Reg(X2), Simm{int32(args[1].(Uimm).Imm), true, 12}} 434 435 case C_JR: 436 f.op = JALR 437 newargs[0] = Reg(X0) 438 newargs[1] = RegOffset{args[0].(Reg), Simm{0, true, 12}} 439 440 case C_MV: 441 f.op = ADD 442 newargs[0] = args[0] 443 newargs[1] = Reg(X0) 444 newargs[2] = args[1] 445 446 case C_EBREAK: 447 f.op = EBREAK 448 449 case C_JALR: 450 f.op = JALR 451 newargs[0] = Reg(X1) 452 newargs[1] = RegOffset{args[0].(Reg), Simm{0, true, 12}} 453 454 case C_ADD: 455 f.op = ADD 456 newargs[0] = args[0] 457 newargs[1] = args[0] 458 newargs[2] = args[1] 459 460 case C_SWSP: 461 f.op = SW 462 newargs[0] = args[0] 463 newargs[1] = RegOffset{Reg(X2), Simm{int32(args[1].(Uimm).Imm), true, 12}} 464 465 // riscv64 compressed instructions 466 case C_LD: 467 f.op = LD 468 newargs[0] = args[0] 469 newargs[1] = RegOffset{args[1].(Reg), Simm{int32(args[2].(Uimm).Imm), true, 12}} 470 471 case C_SD: 472 f.op = SD 473 newargs[0] = args[1] 474 newargs[1] = RegOffset{args[0].(Reg), Simm{int32(args[2].(Uimm).Imm), true, 12}} 475 476 case C_ADDIW: 477 f.op = ADDIW 478 newargs[0] = args[0] 479 newargs[1] = args[0] 480 newargs[2] = Simm{args[1].(Simm).Imm, true, 12} 481 482 case C_SRLI: 483 f.op = SRLI 484 newargs[0] = args[0] 485 newargs[1] = args[0] 486 newargs[2] = args[1] 487 488 case C_SRAI: 489 f.op = SRAI 490 newargs[0] = args[0] 491 newargs[1] = args[0] 492 newargs[2] = args[1] 493 494 case C_SUBW: 495 f.op = SUBW 496 newargs[0] = args[0] 497 newargs[1] = args[0] 498 newargs[2] = args[1] 499 500 case C_ADDW: 501 f.op = ADDW 502 newargs[0] = args[0] 503 newargs[1] = args[0] 504 newargs[2] = args[1] 505 506 case C_SLLI: 507 f.op = SLLI 508 newargs[0] = args[0] 509 newargs[1] = args[0] 510 newargs[2] = args[1] 511 512 case C_LDSP: 513 f.op = LD 514 newargs[0] = args[0] 515 newargs[1] = RegOffset{Reg(X2), Simm{int32(args[1].(Uimm).Imm), true, 12}} 516 517 case C_SDSP: 518 f.op = SD 519 newargs[0] = args[0] 520 newargs[1] = RegOffset{Reg(X2), Simm{int32(args[1].(Uimm).Imm), true, 12}} 521 522 // riscv double precision floating point compressed instructions 523 case C_FLD: 524 f.op = FLD 525 newargs[0] = args[0] 526 newargs[1] = RegOffset{args[1].(Reg), Simm{int32(args[2].(Uimm).Imm), true, 12}} 527 528 case C_FSD: 529 f.op = FSD 530 newargs[0] = args[1] 531 newargs[1] = RegOffset{args[0].(Reg), Simm{int32(args[2].(Uimm).Imm), true, 12}} 532 533 case C_FLDSP: 534 f.op = FLD 535 newargs[0] = args[0] 536 newargs[1] = RegOffset{Reg(X2), Simm{int32(args[1].(Uimm).Imm), true, 12}} 537 538 case C_FSDSP: 539 f.op = FSD 540 newargs[0] = args[0] 541 newargs[1] = RegOffset{Reg(X2), Simm{int32(args[1].(Uimm).Imm), true, 12}} 542 543 case C_UNIMP: 544 f.op = CSRRW 545 newargs[0] = Reg(X0) 546 newargs[1] = CSR(CYCLE) 547 newargs[2] = Reg(X0) 548 } 549 return newargs 550 }