golang.org/x/arch@v0.17.0/s390x/s390xasm/plan9.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 s390xasm 6 7 import ( 8 "fmt" 9 "strconv" 10 "strings" 11 ) 12 13 var vectorSize = map[int]string{0: "B", 1: "H", 2: "F", 3: "G", 4: "Q"} 14 var vectorCS = map[int]string{0: "BS", 1: "HS", 2: "FS", 3: "GS"} 15 16 // GoSyntax returns the Go assembler syntax for the instruction. 17 // The syntax was originally defined by Plan 9. 18 // The inst relates to single instruction. 19 // The pc is the program counter of the instruction, used for 20 // expanding PC-relative addresses into absolute ones. 21 // The symname function queries the symbol table for the program 22 // being disassembled. Given a target address it returns the name 23 // and base address of the symbol containing the target, if any; 24 // otherwise it returns "", 0. 25 func GoSyntax(inst Inst, pc uint64, symname func(uint64) (string, uint64)) string { 26 if symname == nil { 27 symname = func(uint64) (string, uint64) { return "", 0 } 28 } 29 30 var args []string 31 opString := inst.Op.String() 32 op := strings.ToUpper(opString) 33 for i := 0; i < len(inst.Args); i++ { 34 if inst.Args[i] == nil { 35 break 36 } 37 switch inst.Args[i].(type) { 38 case Disp12, Disp20: 39 var temp []string 40 switch inst.Args[i+1].(type) { 41 case Index: // D(X,B) 42 for j := 0; j < 3; j++ { 43 temp = append(temp, plan9Arg(&inst, pc, symname, inst.Args[i+j])) 44 } 45 args = append(args, mem_operandx(temp)) 46 i = i + 2 47 case Base: // D(B) 48 for j := 0; j < 2; j++ { 49 temp = append(temp, plan9Arg(&inst, pc, symname, inst.Args[i+j])) 50 } 51 args = append(args, mem_operand(temp)) 52 i = i + 1 53 case VReg: // D(B) 54 for j := 0; j < 3; j++ { 55 temp = append(temp, plan9Arg(&inst, pc, symname, inst.Args[i+j])) 56 } 57 args = append(args, mem_operandv(temp)) 58 i = i + 2 59 case Len: // D(L,B) 60 for j := 0; j < 3; j++ { 61 temp = append(temp, plan9Arg(&inst, pc, symname, inst.Args[i+j])) 62 } 63 ar1, ar2 := mem_operandl(temp) 64 args = append(args, ar1, ar2) 65 i = i + 2 66 default: // D(R,B) 67 for j := 0; j < 3; j++ { 68 temp = append(temp, plan9Arg(&inst, pc, symname, inst.Args[i+j])) 69 } 70 args = append(args, mem_operandx(temp)) 71 i = i + 2 72 } 73 default: 74 args = append(args, plan9Arg(&inst, pc, symname, inst.Args[i])) 75 } 76 } 77 if strings.HasPrefix(op, "V") || strings.Contains(op, "WFC") || strings.Contains(op, "WFK") { 78 args = args[:len(args)-1] 79 } 80 81 switch inst.Op { 82 default: 83 switch len(args) { 84 case 0: 85 return op 86 case 1: 87 return fmt.Sprintf("%s %s", op, args[0]) 88 case 2: 89 if reverseOperandOrder(inst.Op) { 90 args[0], args[1] = args[1], args[0] 91 } 92 case 3: 93 if reverseOperandOrder(inst.Op) { 94 args[0], args[2] = args[2], args[0] 95 } else if reverseAllOperands(inst.Op) { 96 args[0], args[1], args[2] = args[1], args[2], args[0] 97 } 98 case 4: 99 if reverseOperandOrder(inst.Op) { 100 args[0], args[3] = args[3], args[0] 101 } else if reverseAllOperands(inst.Op) { 102 args[0], args[1], args[2], args[3] = args[1], args[2], args[3], args[0] 103 } 104 } 105 case LCGR, LCGFR: 106 switch inst.Op { 107 case LCGR: 108 op = "NEG" 109 case LCGFR: 110 op = "NEGW" 111 } 112 if args[0] == args[1] { 113 args = args[:1] 114 } else { 115 args[0], args[1] = args[1], args[0] 116 } 117 case LD, LE, LG, LGF, LLGF, LGH, LLGH, LGB, LLGC, LDY, LEY, LRVG, LRV, LRVH: 118 args[0], args[1] = args[1], args[0] 119 switch inst.Op { 120 case LG: 121 op = "MOVD" 122 case LGF: 123 op = "MOVW" 124 case LLGF: 125 op = "MOVWZ" 126 case LGH: 127 op = "MOVH" 128 case LLGH: 129 op = "MOVHZ" 130 case LGB: 131 op = "MOVB" 132 case LLGC: 133 op = "MOVBZ" 134 case LDY, LD: 135 op = "FMOVD" 136 case LEY, LE: 137 op = "FMOVS" 138 case LRVG: 139 op = "MOVDBR" 140 case LRV: 141 op = "MOVWBR" 142 case LRVH: 143 op = "MOVHBR" 144 } 145 case LA, LAY: 146 args[0], args[1] = args[1], args[0] 147 op = "MOVD" 148 149 case LAA, LAAG, LAAL, LAALG, LAN, LANG, LAX, LAXG, LAO, LAOG: 150 args[0], args[1] = args[1], args[0] 151 case LM, LMY, LMG: // Load Multiple 152 switch inst.Op { 153 case LM, LMY: 154 op = "LMY" 155 } 156 args[0], args[1], args[2] = args[2], args[0], args[1] 157 158 case STM, STMY, STMG: // Store Multiple 159 switch inst.Op { 160 case STM, STMY: 161 op = "STMY" 162 } 163 case ST, STY, STG, STHY, STCY, STRVG, STRV: 164 switch inst.Op { 165 case ST, STY: 166 op = "MOVW" 167 case STHY: 168 op = "MOVH" 169 case STCY: 170 op = "MOVB" 171 case STG: 172 op = "MOVD" 173 case STRVG: 174 op = "MOVDBR" 175 case STRV: 176 op = "MOVWBR" 177 } 178 case LGR, LGFR, LGHR, LGBR, LLGFR, LLGHR, LLGCR, LRVGR, LRVR, LDR: 179 switch inst.Op { 180 case LGR: 181 op = "MOVD" 182 case LGFR: 183 op = "MOVW" 184 case LGHR: 185 op = "MOVH" 186 case LGBR: 187 op = "MOVB" 188 case LLGFR: 189 op = "MOVWZ" 190 case LLGHR: 191 op = "MOVHZ" 192 case LLGCR: 193 op = "MOVBZ" 194 case LRVGR: 195 op = "MOVDBR" 196 case LRVR: 197 op = "MOVWBR" 198 case LDR: 199 op = "FMOVD" 200 } 201 args[0], args[1] = args[1], args[0] 202 case LZDR: 203 op = "FMOVD" 204 return op + " " + "$0" + ", " + args[0] 205 case LZER: 206 op = "FMOVS" 207 return op + " " + "$0" + ", " + args[0] 208 case STD, STDY, STE, STEY: 209 switch inst.Op { 210 case STD, STDY: 211 op = "FMOVD" 212 case STE, STEY: 213 op = "FMOVS" 214 } 215 216 case LGHI, LLILH, LLIHL, LLIHH, LGFI, LLILF, LLIHF: 217 switch inst.Op { 218 case LGFI: 219 op = "MOVW" 220 case LGHI: 221 num, err := strconv.ParseInt(args[1][1:], 10, 16) 222 if err != nil { 223 return fmt.Sprintf("plan9Arg: error in converting ParseInt:%s", err) 224 } 225 if num == int64(int8(num)) { 226 op = "MOVB" 227 } else { 228 op = "MOVH" 229 } 230 default: 231 op = "MOVD" 232 } 233 args[0], args[1] = args[1], args[0] 234 case ARK, AGRK, ALGRK: 235 switch inst.Op { 236 case ARK: 237 op = "ADDW" 238 case AGRK: 239 op = "ADD" 240 case ALGRK: 241 op = "ADDC" 242 } 243 if args[0] == args[1] { 244 args[0], args[1] = args[2], args[0] 245 args = args[:2] 246 } else { 247 args[0], args[2] = args[2], args[0] 248 } 249 case AGHIK, AHIK, ALGHSIK: 250 num, err := strconv.ParseInt(args[2][1:], 10, 32) 251 if err != nil { 252 return fmt.Sprintf("plan9Arg: error in converting ParseInt:%s", err) 253 } 254 switch inst.Op { 255 case AGHIK: 256 if num < 0 { 257 op = "SUB" 258 args[2] = args[2][:1] + args[2][2:] 259 } else { 260 op = "ADD" 261 } 262 case AHIK: 263 op = "ADDW" 264 case ALGHSIK: 265 if num < 0 { 266 op = "SUBC" 267 args[2] = args[2][:1] + args[2][2:] 268 } else { 269 op = "ADDC" 270 } 271 } 272 args[0], args[2] = args[2], args[0] 273 case AGHI, AHI, AGFI, AFI, AR, ALCGR: 274 num, err := strconv.ParseInt(args[1][1:], 10, 32) 275 if err != nil { 276 return fmt.Sprintf("plan9Arg: error in converting ParseInt:%s", err) 277 } 278 switch inst.Op { 279 case AGHI, AGFI: 280 if num < 0 { 281 op = "SUB" 282 args[1] = args[1][:1] + args[1][2:] 283 } else { 284 op = "ADD" 285 } 286 case AHI, AFI, AR: 287 op = "ADDW" 288 case ALCGR: 289 op = "ADDE" 290 } 291 args[0], args[1] = args[1], args[0] 292 case AEBR, ADBR, DDBR, DEBR, MDBR, MEEBR, SDBR, SEBR, LPDBR, LNDBR, LPDFR, LNDFR, LCDFR, LCEBR, LEDBR, LDEBR, SQDBR, SQEBR: 293 switch inst.Op { 294 case AEBR: 295 op = "FADDS" 296 case ADBR: 297 op = "FADD" 298 case DDBR: 299 op = "FDIV" 300 case DEBR: 301 op = "FDIVS" 302 case MDBR: 303 op = "FMUL" 304 case MEEBR: 305 op = "FMULS" 306 case SDBR: 307 op = "FSUB" 308 case SEBR: 309 op = "FSUBS" 310 case LPDBR: 311 op = "FABS" 312 case LNDBR: 313 op = "FNABS" 314 case LCDFR: 315 op = "FNEG" 316 case LCEBR: 317 op = "FNEGS" 318 case SQDBR: 319 op = "FSQRT" 320 case SQEBR: 321 op = "FSQRTS" 322 } 323 args[0], args[1] = args[1], args[0] 324 case SR, SGR, SLGR, SLFI: 325 switch inst.Op { 326 case SR, SLFI: 327 op = "SUBW" 328 case SGR: 329 op = "SUB" 330 case SLGR: 331 op = "SUBC" 332 } 333 args[0], args[1] = args[1], args[0] 334 case SGRK, SLGRK, SRK: 335 switch inst.Op { 336 case SGRK: 337 op = "SUB" 338 case SLGRK: 339 op = "SUBC" 340 case SRK: 341 op = "SUBW" 342 } 343 if args[0] == args[1] { 344 args[0], args[1] = args[2], args[0] 345 args = args[:2] 346 } else { 347 args[0], args[2] = args[2], args[0] 348 } 349 case SLBGR: 350 op = "SUBE" 351 args[0], args[1] = args[1], args[0] 352 case MSGFR, MHI, MSFI, MSGFI: 353 switch inst.Op { 354 case MSGFR, MHI, MSFI: 355 op = "MULLW" 356 case MSGFI: 357 op = "MULLD" 358 } 359 args[0], args[1] = args[1], args[0] 360 361 case NGR, NR, NILL, NILF, NILH, OGR, OR, OILL, OILF, OILH, XGR, XR, XILF: 362 op = bitwise_op(inst.Op) 363 args[0], args[1] = args[1], args[0] 364 switch inst.Op { 365 case NILL: 366 if int(inst.Args[1].(Sign16)) < 0 { 367 op = "ANDW" 368 } 369 370 case NILF: 371 if int(inst.Args[1].(Sign32)) < 0 { 372 op = "AND" 373 } 374 case OILF: 375 if int(inst.Args[1].(Sign32)) < 0 { 376 op = "ORW" 377 } 378 case XILF: 379 if int(inst.Args[1].(Sign32)) < 0 { 380 op = "XORW" 381 } 382 } 383 384 case NGRK, NRK, OGRK, ORK, XGRK, XRK: // opcode R1, R2, R3 385 op = bitwise_op(inst.Op) 386 args[0], args[1], args[2] = args[1], args[2], args[0] 387 case SLLG, SRLG, SLLK, SRLK, RLL, RLLG, SRAK, SRAG: 388 switch inst.Op { 389 case SLLG: 390 op = "SLD" 391 case SRLG: 392 op = "SRD" 393 case SLLK: 394 op = "SLW" 395 case SRLK: 396 op = "SRW" 397 case SRAK: 398 op = "SRAW" 399 case SRAG: 400 op = "SRAD" 401 } 402 args[0], args[2] = args[2], args[0] 403 case TRAP2, SVC: 404 op = "SYSALL" 405 case CR, CLR, CGR, CLGR, KDBR, CDBR, CEBR, CGHI, CHI, CGFI, CLGFI, CFI, CLFI: 406 switch inst.Op { 407 case CGHI, CGFI, CGR: 408 op = "CMP" 409 case CHI, CFI, CR: 410 op = "CMPW" 411 case CLGFI, CLGR: 412 op = "CMPU" 413 case CLFI, CLR: 414 op = "CMPWU" 415 case CDBR: 416 op = "FCMPU" 417 case KDBR: 418 op = "FCMPO" 419 } 420 case CEFBRA, CDFBRA, CEGBRA, CDGBRA, CELFBR, CDLFBR, CELGBR, CDLGBR, CFEBRA, CFDBRA, CGEBRA, CGDBRA, CLFEBR, CLFDBR, CLGEBR, CLGDBR: 421 args[0], args[1] = args[2], args[0] 422 args = args[:2] 423 case CGRJ, CGIJ: 424 mask, err := strconv.Atoi(args[2][1:]) 425 if err != nil { 426 return fmt.Sprintf("GoSyntax: error in converting Atoi:%s", err) 427 } 428 var check bool 429 switch mask & 0xf { 430 case 2: 431 op = "CMPBGT" 432 check = true 433 case 4: 434 op = "CMPBLT" 435 check = true 436 case 6: 437 op = "CMPBNE" 438 check = true 439 case 8: 440 op = "CMPBEQ" 441 check = true 442 case 10: 443 op = "CMPBGE" 444 check = true 445 case 12: 446 op = "CMPBLE" 447 check = true 448 } 449 if check { 450 args[2] = args[3] 451 args = args[:3] 452 } 453 case CLGRJ, CLGIJ: 454 mask, err := strconv.Atoi(args[2][1:]) 455 if err != nil { 456 return fmt.Sprintf("GoSyntax: error in converting Atoi:%s", err) 457 } 458 var check bool 459 switch mask & 0xf { 460 case 2: 461 op = "CMPUBGT" 462 check = true 463 case 4: 464 op = "CMPUBLT" 465 check = true 466 case 7: 467 op = "CMPUBNE" 468 check = true 469 case 8: 470 op = "CMPUBEQ" 471 check = true 472 case 10: 473 op = "CMPUBGE" 474 check = true 475 case 12: 476 op = "CMPUBLE" 477 check = true 478 } 479 if check { 480 args[2] = args[3] 481 args = args[:3] 482 } 483 case CLRJ, CRJ, CIJ, CLIJ: 484 args[0], args[1], args[2] = args[2], args[0], args[1] 485 case BRC, BRCL: 486 mask, err := strconv.Atoi(args[0][1:]) 487 if err != nil { 488 return fmt.Sprintf("GoSyntax: error in converting Atoi:%s", err) 489 } 490 opStr, check := branch_relative_op(mask, inst.Op) 491 if opStr != "" { 492 op = opStr 493 } 494 if check { 495 args[0] = args[1] 496 args = args[:1] 497 } 498 case BCR: 499 mask, err := strconv.Atoi(args[0][1:]) 500 if err != nil { 501 return fmt.Sprintf("GoSyntax: error in converting Atoi:%s", err) 502 } 503 opStr, check := branchOnConditionOp(mask, inst.Op) 504 if opStr != "" { 505 op = opStr 506 } 507 if op == "SYNC" || op == "NOPH" { 508 return op 509 } 510 if check { 511 args[0] = args[1] 512 args = args[:1] 513 } 514 case LOCGR: 515 mask, err := strconv.Atoi(args[2][1:]) 516 if err != nil { 517 return fmt.Sprintf("GoSyntax: error in converting Atoi:%s", err) 518 } 519 var check bool 520 switch mask & 0xf { 521 case 2: //Greaterthan (M=2) 522 op = "MOVDGT" 523 check = true 524 case 4: //Lessthan (M=4) 525 op = "MOVDLT" 526 check = true 527 case 7: // Not Equal (M=7) 528 op = "MOVDNE" 529 check = true 530 case 8: // Equal (M=8) 531 op = "MOVDEQ" 532 check = true 533 case 10: // Greaterthan or Equal (M=10) 534 op = "MOVDGE" 535 check = true 536 case 12: // Lessthan or Equal (M=12) 537 op = "MOVDLE" 538 check = true 539 } 540 if check { 541 args[0], args[1] = args[1], args[0] 542 args = args[:2] 543 } else { 544 args[0], args[2] = args[2], args[0] 545 } 546 case BRASL: 547 op = "CALL" // BL 548 args[0] = args[1] 549 args = args[:1] 550 case X, XY, XG: 551 switch inst.Op { 552 case X, XY: 553 op = "XORW" 554 case XG: 555 op = "XOR" 556 } 557 case N, NY, NG, O, OY, OG, XC, NC, OC, MVC, MVCIN, CLC: 558 switch inst.Op { 559 case N, NY: 560 op = "ANDW" 561 case NG: 562 op = "AND" 563 case O, OY: 564 op = "ORW" 565 case OG: 566 op = "OR" 567 } 568 args[0], args[1] = args[1], args[0] 569 case S, SY, SLBG, SLG, SG: 570 switch inst.Op { 571 case S, SY: 572 op = "SUBW" 573 case SLBG: 574 op = "SUBE" 575 case SLG: 576 op = "SUBC" 577 case SG: 578 op = "SUB" 579 } 580 args[0], args[1] = args[1], args[0] 581 case MSG, MSY, MS: 582 switch inst.Op { 583 case MSG: 584 op = "MULLD" 585 case MSY, MS: 586 op = "MULLW" 587 } 588 case A, AY, ALCG, ALG, AG: 589 switch inst.Op { 590 case A, AY: 591 op = "ADDW" 592 case ALCG: 593 op = "ADDE" 594 case ALG: 595 op = "ADDC" 596 case AG: 597 op = "ADD" 598 } 599 args[0], args[1] = args[1], args[0] 600 case RISBG, RISBGN, RISBHG, RISBLG, RNSBG, RXSBG, ROSBG: 601 switch inst.Op { 602 case RNSBG, RXSBG, ROSBG: 603 num, err := strconv.Atoi(args[2][1:]) 604 if err != nil { 605 return fmt.Sprintf("GoSyntax: error in converting Atoi:%s", err) 606 } 607 if ((num >> 7) & 0x1) != 0 { 608 op = op + "T" 609 } 610 case RISBG, RISBGN, RISBHG, RISBLG: 611 num, err := strconv.Atoi(args[3][1:]) 612 if err != nil { 613 return fmt.Sprintf("GoSyntax: error in converting Atoi:%s", err) 614 } 615 if ((num >> 7) & 0x1) != 0 { 616 op = op + "Z" 617 } 618 } 619 if len(args) == 5 { 620 args[0], args[1], args[2], args[3], args[4] = args[2], args[3], args[4], args[1], args[0] 621 } else { 622 args[0], args[1], args[2], args[3] = args[2], args[3], args[1], args[0] 623 } 624 625 case VEC, VECL, VCLZ, VCTZ, VREPI, VPOPCT: //mnemonic V1, V2, M3 626 mask, err := strconv.Atoi(args[2][1:]) 627 if err != nil { 628 return fmt.Sprintf("GoSyntax: error in converting Atoi for %q:%s", op, err) 629 } 630 val := mask & 0x7 631 if val >= 0 && val < 4 { 632 op = op + vectorSize[val] 633 args = args[:2] 634 } else { 635 return fmt.Sprintf("specification exception is recognized for %q with mask value: %v \n", op, mask) 636 } 637 switch inst.Op { 638 case VCLZ, VCTZ, VREPI, VPOPCT: 639 args[0], args[1] = args[1], args[0] 640 default: 641 } 642 //Mnemonic V1, V2, V3, M4 or Mnemonic V1, I2, I3, M4 or Mnemonic V1, V3, I2, M4 643 case VA, VS, VACC, VAVG, VAVGL, VMX, VMXL, VMN, VMNL, VGFM, VGM, VREP, VERLLV, VESLV, VSCBI, VSUM, VSUMG, VSUMQ, VMH, VMLH, VML, VME, VMLE, VMO, VMLO: 644 mask, err := strconv.Atoi(args[3][1:]) 645 if err != nil { 646 return fmt.Sprintf("GoSyntax: error in converting Atoi:%s", err) 647 } 648 val := mask & 0x7 649 switch inst.Op { 650 case VA, VS, VACC, VSCBI: 651 if val >= 0 && val < 5 { 652 if args[0] == args[2] { 653 args[0], args[1] = args[1], args[0] 654 args = args[:2] 655 } else if inst.Op == VS { 656 if args[0] == args[1] { 657 args[0] = args[2] 658 args = args[:2] 659 } else { 660 args[0], args[2] = args[2], args[0] 661 args = args[:3] 662 } 663 } else { 664 args[0], args[1], args[2] = args[1], args[2], args[0] 665 args = args[:3] 666 } 667 op = op + vectorSize[val] 668 } else { 669 return fmt.Sprintf("specification exception is recognized for %q with mask value: %v \n", op, mask) 670 } 671 case VAVG, VAVGL, VMX, VMXL, VMN, VMNL, VGFM, VGM: 672 if val >= 0 && val < 4 { 673 op = op + vectorSize[val] 674 args[0], args[1], args[2] = args[1], args[2], args[0] 675 args = args[:3] 676 } else { 677 return fmt.Sprintf("specification exception is recognized for %q with mask value: %v \n", op, mask) 678 } 679 case VREP, VERLLV, VESLV: 680 if val >= 0 && val < 4 { 681 op = op + vectorSize[val] 682 args[0], args[2] = args[2], args[0] 683 args = args[:3] 684 } else { 685 return fmt.Sprintf("specification exception is recognized for %q with mask value: %v \n", op, mask) 686 } 687 case VSUM, VSUMG, VSUMQ: 688 var off int 689 switch inst.Op { 690 case VSUM: 691 off = 0 692 case VSUMG: 693 off = 1 694 case VSUMQ: 695 off = 2 696 } 697 if (val > (-1 + off)) && (val < (2 + off)) { 698 op = op + vectorSize[val] 699 } else { 700 return fmt.Sprintf("specification exception is recognized for %q with mask value: %v \n", op, mask) 701 } 702 args = args[:3] 703 case VML, VMH, VMLH, VME, VMLE, VMO, VMLO: 704 if val >= 0 && val < 3 { 705 op = op + vectorSize[val] 706 } 707 if op == "VML" && val == 2 { 708 op = op + "W" 709 } 710 if args[0] == args[2] { 711 args[0], args[1] = args[1], args[0] 712 args = args[:2] 713 } else { 714 args[0], args[1], args[2] = args[1], args[2], args[0] 715 args = args[:3] 716 } 717 } 718 719 case VGFMA, VERIM, VMAH, VMALH: // Mnemonic V1, V2, V3, V4/I4, M5 720 mask, err := strconv.Atoi(args[4][1:]) 721 if err != nil { 722 return fmt.Sprintf("GoSyntax: error in converting Atoi:%s", err) 723 } 724 val := mask & 0x7 725 args = args[:4] 726 var off int 727 switch inst.Op { 728 case VMAH, VMALH: 729 off = -1 730 } 731 732 if val >= 0 && val < (4+off) { 733 op = op + vectorSize[val] 734 } else { 735 return fmt.Sprintf("specification exception is recognized for %q with mask value: %v \n", op, mask) 736 } 737 switch inst.Op { 738 case VGFMA, VMAH, VMALH: 739 args[0], args[1], args[2], args[3] = args[1], args[2], args[3], args[0] 740 default: 741 args[0], args[3] = args[3], args[0] 742 } 743 case VSTRC, VFAE, VFEE, VFENE: 744 var off uint8 745 switch inst.Op { 746 case VSTRC: 747 off = uint8(1) 748 default: 749 off = uint8(0) 750 } 751 m1, err := strconv.Atoi(args[3+off][1:]) 752 if err != nil { 753 return fmt.Sprintf("GoSyntax: error in converting Atoi:%s", err) 754 } 755 m2, err := strconv.Atoi(args[4+off][1:]) 756 if err != nil { 757 return fmt.Sprintf("GoSyntax: error in converting Atoi:%s", err) 758 } 759 index := m1 & 0x3 760 if index < 0 || index > 2 { 761 return fmt.Sprintf("specification exception is recognized for %q with mask values: %v, %v \n", op, m1, m2) 762 } 763 switch m2 { 764 case 0: 765 op = op + vectorSize[index] 766 case 1: 767 op = op + vectorCS[index] 768 case 2: 769 op = op + "Z" + vectorSize[index] 770 case 3: 771 op = op + "Z" + vectorCS[index] 772 default: 773 return fmt.Sprintf("specification exception is recognized for %q with mask values: %v, %v \n", op, m1, m2) 774 } 775 switch inst.Op { 776 case VSTRC: 777 args[0], args[1], args[2], args[3] = args[1], args[2], args[3], args[0] 778 default: 779 args[0], args[1], args[2] = args[1], args[2], args[0] 780 } 781 args = args[:3+off] 782 783 case VCEQ, VCH, VCHL: // Mnemonic V1, V2, V3, M4, M5 784 m4, err := strconv.Atoi(args[3][1:]) 785 if err != nil { 786 return fmt.Sprintf("GoSyntax: %q error in converting Atoi:%s", op, err) 787 } 788 m5, err := strconv.Atoi(args[4][1:]) 789 if err != nil { 790 return fmt.Sprintf("GoSyntax: %q error in converting Atoi:%s", op, err) 791 } 792 val := (m4 & 0x7) 793 if m5 == 0 { 794 if val >= 0 && val < 4 { 795 op = op + vectorSize[val] 796 args[0], args[1], args[2] = args[1], args[2], args[0] 797 args = args[:3] 798 } else { 799 return fmt.Sprintf("specification exception is recognized for %q with mask(m4) value: %v \n", op, m4) 800 } 801 } else if m5 == 1 { 802 if val >= 0 && val < 4 { 803 op = op + vectorCS[val] 804 args[0], args[1], args[2] = args[1], args[2], args[0] 805 args = args[:3] 806 } else { 807 return fmt.Sprintf("specification exception is recognized for %q with mask(m4) value: %v \n", op, m4) 808 } 809 } else { 810 return fmt.Sprintf("specification exception is recognized for %q with mask(m5) value: %v \n", op, m5) 811 } 812 case VFMA, VFMS, VMSL: //Mnemonic V1, V2, V3, V4, M5, M6 813 m5, err := strconv.Atoi(args[4][1:]) 814 if err != nil { 815 return fmt.Sprintf("GoSyntax: %q error in converting Atoi:%s", op, err) 816 } 817 m6, err := strconv.Atoi(args[5][1:]) 818 if err != nil { 819 return fmt.Sprintf("GoSyntax: %q error in converting Atoi:%s", op, err) 820 } 821 switch inst.Op { 822 case VMSL: 823 if m5 == 3 && m6 == 8 { 824 op = op + "EG" 825 } else if m5 == 3 && m6 == 4 { 826 op = op + "OG" 827 } else if m5 == 3 && m6 == 12 { 828 op = op + "EOG" 829 } else if m5 == 3 { 830 op = op + "G" 831 } 832 default: 833 if m5 == 0 && m6 == 3 { 834 op = op + "DB" 835 } else if m5 == 8 && m6 == 3 { 836 op = "W" + op[1:] + "DB" 837 } else { 838 return fmt.Sprintf("specification exception is recognized for %q with m5: %v m6: %v \n", op, m5, m6) 839 } 840 } 841 args[0], args[1], args[2], args[3] = args[1], args[2], args[3], args[0] 842 args = args[:4] 843 844 case VFCE, VFCH, VFCHE: //Mnemonic V1,V2,V3,M4,M5,M6 845 m4, err := strconv.Atoi(args[3][1:]) 846 if err != nil { 847 return fmt.Sprintf("GoSyntax: %q error in converting Atoi:%s", op, err) 848 } 849 m5, err := strconv.Atoi(args[4][1:]) 850 if err != nil { 851 return fmt.Sprintf("GoSyntax: %q error in converting Atoi:%s", op, err) 852 } 853 m6, err := strconv.Atoi(args[5][1:]) 854 if err != nil { 855 return fmt.Sprintf("GoSyntax: %q error in converting Atoi:%s", op, err) 856 } 857 if m5 == 0 { 858 if m4 == 3 && m6 == 0 { 859 op = op + "DB" 860 } else if m4 == 3 && m6 == 1 { 861 op = op + "DBS" 862 } else { 863 return fmt.Sprintf("specification exception is recognized for %q with m4: %v, m6: %v \n", op, m4, m6) 864 } 865 866 } else if m5 == 8 { 867 if m4 == 3 && m6 == 0 { 868 op = "W" + op[1:] + "DB" 869 } else if m4 == 3 && m6 == 1 { 870 op = "W" + op[1:] + "DBS" 871 } else { 872 return fmt.Sprintf("specification exception is recognized for %q with m4: %v, m6: %v \n", op, m4, m6) 873 } 874 } else { 875 return fmt.Sprintf("specification exception is recognized for %q with m5: %v \n", op, m5) 876 } 877 args[0], args[1], args[2] = args[1], args[2], args[0] 878 args = args[:3] 879 880 case VFTCI: 881 m4, err := strconv.Atoi(args[3][1:]) 882 if err != nil { 883 return fmt.Sprintf("GoSyntax: %q error in converting Atoi:%s", op, err) 884 } 885 m5, err := strconv.Atoi(args[4][1:]) 886 if err != nil { 887 return fmt.Sprintf("GoSyntax: %q error in converting Atoi:%s", op, err) 888 } 889 val := (m4 & 0x7) 890 if m5 == 0 { 891 switch val { 892 case 2: 893 op = op + "SB" 894 case 3: 895 op = op + "DB" 896 default: 897 return fmt.Sprintf("specification exception is recognized for %q with mask(m4) value: %v \n", op, m4) 898 } 899 } else if m5 == 8 { 900 switch val { 901 case 2: 902 op = "W" + op[1:] + "SB" 903 case 3: 904 op = "W" + op[1:] + "DB" 905 case 4: 906 op = "W" + op[1:] + "XB" 907 default: 908 return fmt.Sprintf("specification exception is recognized for %q with mask(m4) value: %v \n", op, m4) 909 } 910 } else { 911 return fmt.Sprintf("specification exception is recognized for %q with mask(m5) value: %v \n", op, m5) 912 } 913 args[0], args[2] = args[2], args[0] 914 args = args[:3] 915 case VAC, VACCC: 916 mask, err := strconv.Atoi(args[4][1:]) 917 if err != nil { 918 return fmt.Sprintf("GoSyntax: error in converting Atoi:%s", err) 919 } 920 if mask&0x04 == 0 { 921 return fmt.Sprintf("specification exception is recognized for %q with mask value: %v \n", op, mask) 922 } 923 op = op + "Q" 924 args[0], args[1], args[2], args[3] = args[1], args[2], args[3], args[0] 925 args = args[:4] 926 case VL, VLREP: 927 switch inst.Op { 928 case VL: 929 args[0], args[1] = args[1], args[0] 930 case VLREP: 931 args[0], args[1] = args[1], args[0] 932 mask, err := strconv.Atoi(args[2][1:]) 933 if err != nil { 934 return fmt.Sprintf("GoSyntax: error in converting Atoi:%s", err) 935 } 936 if mask >= 0 && mask < 4 { 937 op = op + vectorSize[mask] 938 } 939 } 940 args = args[:2] 941 case VST, VSTEB, VSTEH, VSTEF, VSTEG, VLEB, VLEH, VLEF, VLEG: //Mnemonic V1, D2(X2,B2), M3 942 m, err := strconv.Atoi(args[2][1:]) 943 if err != nil { 944 return fmt.Sprintf("GoSyntax: error in converting Atoi:%s", err) 945 } 946 switch inst.Op { 947 case VST: 948 if m == 0 || (m > 2 && m < 5) { 949 args = args[:2] 950 } else { 951 return fmt.Sprintf("specification exception is recognized for %q with mask value: %v \n", op, m) 952 } 953 case VLEB, VLEH, VLEF, VLEG: 954 args[0], args[2] = args[2], args[0] 955 default: 956 args[0], args[1], args[2] = args[2], args[0], args[1] 957 } 958 case VSTM, VSTL, VESL, VESRA, VLM, VERLL, VLVG: //Mnemonic V1, V3, D2(B2)[,M4] or V1, R3,D2(B2) 959 switch inst.Op { 960 case VSTM, VLM: 961 m, err := strconv.Atoi(args[3][1:]) 962 if err != nil { 963 return fmt.Sprintf("GoSyntax: error in converting Atoi:%s", err) 964 } 965 if !(m == 0 || (m > 2 && m < 5)) { 966 return fmt.Sprintf("specification exception is recognized for %q with mask value: %v \n", op, m) 967 } 968 if inst.Op == VLM { 969 args[0], args[1], args[2] = args[2], args[0], args[1] 970 } 971 args = args[:3] 972 case VESL, VESRA, VERLL, VLVG: 973 m, err := strconv.Atoi(args[3][1:]) 974 if err != nil { 975 return fmt.Sprintf("GoSyntax: error in converting Atoi:%s", err) 976 } 977 if m >= 0 && m < 4 { 978 op = op + vectorSize[m] 979 } else { 980 return fmt.Sprintf("specification exception is recognized for %q with mask value: %v \n", op, m) 981 } 982 switch inst.Op { 983 case VLVG: 984 args[0], args[2] = args[2], args[0] 985 args = args[:3] 986 default: 987 if args[0] == args[1] { 988 args[0] = args[2] 989 args = args[:2] 990 break 991 } 992 args[0], args[2] = args[2], args[0] 993 args = args[:3] 994 } 995 case VSTL: 996 args[0], args[1] = args[1], args[0] 997 args = args[:3] 998 } 999 case VGBM: 1000 val, err := strconv.Atoi(args[1][1:]) 1001 if err != nil { 1002 return fmt.Sprintf("GoSyntax: error in converting Atoi:%s", err) 1003 } 1004 if val == 0 { 1005 op = "VZERO" 1006 args = args[:1] 1007 } else if val == 0xffff { 1008 op = "VONE" 1009 args = args[:1] 1010 } else { 1011 args[0], args[1] = args[1], args[0] 1012 args = args[:2] 1013 } 1014 case VN, VNC, VO, VX, VNO: //mnemonic V1, V2, V3 1015 if args[0] == args[2] { 1016 args = args[:2] 1017 args[0], args[1] = args[1], args[0] 1018 } else { 1019 args[0], args[1], args[2] = args[1], args[2], args[0] 1020 } 1021 if op == "VNO" { 1022 op = op + "T" 1023 } 1024 case VGEG, VGEF, VSCEG, VSCEF: //Mnemonic V1, D2(V2, B2), M3 1025 args[0], args[2] = args[2], args[0] 1026 1027 } 1028 if args != nil { 1029 op += " " + strings.Join(args, ", ") 1030 } 1031 1032 return op 1033 } 1034 1035 // This function returns corresponding extended mnemonic for the given 1036 // branch on relative mnemonic. 1037 func branch_relative_op(mask int, opconst Op) (op string, check bool) { 1038 switch mask & 0xf { 1039 case 2: 1040 op = "BGT" 1041 check = true 1042 case 4: 1043 op = "BLT" 1044 check = true 1045 case 5: 1046 op = "BLTU" 1047 check = true 1048 case 7: 1049 op = "BNE" 1050 check = true 1051 case 8: 1052 op = "BEQ" 1053 check = true 1054 case 10: 1055 op = "BGE" 1056 check = true 1057 case 12: 1058 op = "BLE" 1059 check = true 1060 case 13: 1061 op = "BLEU" 1062 check = true 1063 case 15: 1064 op = "JMP" // BR 1065 check = true 1066 } 1067 return op, check 1068 } 1069 1070 // This function returns corresponding extended mnemonic for the given 1071 // brach on condition mnemonic. 1072 func branchOnConditionOp(mask int, opconst Op) (op string, check bool) { 1073 switch mask & 0xf { 1074 case 0: 1075 op = "NOPH" 1076 case 14: 1077 op = "SYNC" 1078 case 15: 1079 op = "JMP" 1080 check = true 1081 } 1082 return op, check 1083 } 1084 1085 // This function returns corresponding plan9 mnemonic for the native bitwise mnemonic. 1086 func bitwise_op(op Op) string { 1087 var ret string 1088 switch op { 1089 case NGR, NGRK, NILL: 1090 ret = "AND" 1091 case NR, NRK, NILH, NILF: 1092 ret = "ANDW" 1093 case OGR, OGRK, OILF: 1094 ret = "OR" 1095 case OR, ORK, OILH, OILL: 1096 ret = "ORW" 1097 case XGR, XGRK, XILF: 1098 ret = "XOR" 1099 case XR, XRK: 1100 ret = "XORW" 1101 } 1102 return ret 1103 } 1104 1105 // This function parses memory operand of type D(B) 1106 func mem_operand(args []string) string { 1107 if args[0] != "" && args[1] != "" { 1108 args[0] = fmt.Sprintf("%s(%s)", args[0], args[1]) 1109 } else if args[0] != "" { 1110 args[0] = fmt.Sprintf("$%s", args[0]) 1111 } else if args[1] != "" { 1112 args[0] = fmt.Sprintf("(%s)", args[1]) 1113 } else { 1114 args[0] = "" 1115 } 1116 return args[0] 1117 } 1118 1119 // This function parses memory operand of type D(X,B) 1120 func mem_operandx(args []string) string { 1121 if args[1] != "" && args[2] != "" { 1122 args[1] = fmt.Sprintf("(%s)(%s*1)", args[2], args[1]) 1123 } else if args[1] != "" { 1124 args[1] = fmt.Sprintf("(%s)", args[1]) 1125 } else if args[2] != "" { 1126 args[1] = fmt.Sprintf("(%s)", args[2]) 1127 } else if args[0] != "" { 1128 args[1] = "" 1129 } 1130 if args[0] != "" && args[1] != "" { 1131 args[0] = fmt.Sprintf("%s%s", args[0], args[1]) 1132 } else if args[0] != "" { 1133 args[0] = fmt.Sprintf("$%s", args[0]) 1134 } else if args[1] != "" { 1135 args[0] = fmt.Sprintf("%s", args[1]) 1136 } else { 1137 args[0] = "" 1138 } 1139 return args[0] 1140 } 1141 1142 // This function parses memory operand of type D(V,B) 1143 func mem_operandv(args []string) string { 1144 if args[1] != "" && args[2] != "" { 1145 args[1] = fmt.Sprintf("(%s)(%s*1)", args[2], args[1]) 1146 } else if args[1] != "" { 1147 args[1] = fmt.Sprintf("(%s*1)", args[1]) 1148 } else if args[2] != "" { 1149 args[1] = fmt.Sprintf("(%s)", args[2]) 1150 } else if args[0] != "" { 1151 args[1] = "" 1152 } 1153 if args[0] != "" && args[1] != "" { 1154 args[0] = fmt.Sprintf("%s%s", args[0], args[1]) 1155 } else if args[0] != "" { 1156 args[0] = fmt.Sprintf("$%s", args[0]) 1157 } else if args[1] != "" { 1158 args[0] = fmt.Sprintf("%s", args[1]) 1159 } else { 1160 args[0] = "" 1161 } 1162 return args[0] 1163 } 1164 1165 // This function parses memory operand of type D(L,B) 1166 func mem_operandl(args []string) (string, string) { 1167 if args[0] != "" && args[2] != "" { 1168 args[0] = fmt.Sprintf("%s(%s)", args[0], args[2]) 1169 } else if args[2] != "" { 1170 args[0] = fmt.Sprintf("(%s)", args[2]) 1171 } else { 1172 args[0] = fmt.Sprintf("%s", args[0]) 1173 } 1174 return args[0], args[1] 1175 } 1176 1177 // plan9Arg formats arg (which is the argIndex's arg in inst) according to Plan 9 rules. 1178 // NOTE: because Plan9Syntax is the only caller of this func, and it receives a copy 1179 // of inst, it's ok to modify inst.Args here. 1180 func plan9Arg(inst *Inst, pc uint64, symname func(uint64) (string, uint64), arg Arg) string { 1181 switch arg.(type) { 1182 case Reg: 1183 if arg == R13 { 1184 return "g" 1185 } 1186 return strings.ToUpper(arg.String(pc)[1:]) 1187 case Base: 1188 if arg == R13 { 1189 return "g" 1190 } 1191 s := arg.String(pc) 1192 if s != "" { 1193 return strings.ToUpper(s[1 : len(s)-1]) 1194 } 1195 return "R0" 1196 case Index: 1197 if arg == R13 { 1198 return "g" 1199 } 1200 s := arg.String(pc) 1201 if s != "" { 1202 return strings.ToUpper(s[1:]) 1203 } 1204 return "" 1205 case VReg: 1206 return strings.ToUpper(arg.String(pc)[1:]) 1207 case Disp20, Disp12: 1208 numstr := arg.String(pc) 1209 num, err := strconv.Atoi(numstr[:len(numstr)]) 1210 if err != nil { 1211 return fmt.Sprintf("plan9Arg: error in converting Atoi:%s", err) 1212 } 1213 if num == 0 { 1214 return "" 1215 } else { 1216 return strconv.Itoa(num) 1217 } 1218 case RegIm12, RegIm16, RegIm24, RegIm32: 1219 addr, err := strconv.ParseUint(arg.String(pc)[2:], 16, 64) 1220 if err != nil { 1221 return fmt.Sprintf("plan9Arg: error in converting ParseUint:%s", err) 1222 } 1223 off := int(addr - pc) 1224 s, base := symname(addr) 1225 if s != "" && addr == base { 1226 return fmt.Sprintf("%s(SB)", s) 1227 } 1228 off = off / inst.Len 1229 return fmt.Sprintf("%v(PC)", off) 1230 case Imm, Sign8, Sign16, Sign32: 1231 numImm := arg.String(pc) 1232 switch arg.(type) { 1233 case Sign32, Sign16, Imm: 1234 num, err := strconv.ParseInt(numImm, 10, 64) 1235 if err != nil { 1236 return fmt.Sprintf("plan9Arg: error in converting ParseInt:%s", err) 1237 } 1238 switch inst.Op { 1239 case LLIHF: 1240 num = num << 32 1241 case LLILH: 1242 num = num << 16 1243 case NILH: 1244 num = (num << 16) | int64(0xFFFF) 1245 case OILH: 1246 num = num << 16 1247 } 1248 numImm = fmt.Sprintf("%d", num) 1249 } 1250 return fmt.Sprintf("$%s", numImm) 1251 case Mask, Len: 1252 num := arg.String(pc) 1253 return fmt.Sprintf("$%s", num) 1254 } 1255 return fmt.Sprintf("???(%v)", arg) 1256 } 1257 1258 // It checks any 2 args of given instructions to swap or not 1259 func reverseOperandOrder(op Op) bool { 1260 switch op { 1261 case LOCR, MLGR: 1262 return true 1263 case LTEBR, LTDBR: 1264 return true 1265 case VLEIB, VLEIH, VLEIF, VLEIG, VPDI: 1266 return true 1267 case VSLDB: 1268 return true 1269 } 1270 return false 1271 } 1272 1273 // It checks whether to reverse all the args of given mnemonic or not 1274 func reverseAllOperands(op Op) bool { 1275 switch op { 1276 case VLVGP: //3-operand list 1277 return true 1278 case VSEL, VPERM: //4-Operand list 1279 return true 1280 } 1281 return false 1282 }