1 /*========================== begin_copyright_notice ============================ 2 3 Copyright (C) 2018-2021 Intel Corporation 4 5 SPDX-License-Identifier: MIT 6 7 ============================= end_copyright_notice ===========================*/ 8 9 #ifndef IGA_NATIVE_INSTDECODER_HPP 10 #define IGA_NATIVE_INSTDECODER_HPP 11 12 #include "../../Frontend/IRToString.hpp" 13 #include "../../Frontend/Floats.hpp" 14 #include "../../IR/InstBuilder.hpp" 15 #include "../../strings.hpp" 16 #include "../BitProcessor.hpp" 17 #include "Field.hpp" 18 #include "Interface.hpp" 19 #include "MInst.hpp" 20 21 #include <algorithm> 22 #include <functional> 23 #include <initializer_list> 24 #include <iomanip> 25 #include <sstream> 26 #include <string> 27 #include <vector> 28 29 namespace iga 30 { 31 typedef std::function<void(uint64_t bits, std::stringstream &ss)> FormatFunction; 32 nextPowerOfTwo(int v)33 static inline int nextPowerOfTwo(int v) { 34 v--; 35 v |= v >> 1; 36 v |= v >> 2; 37 v |= v >> 4; 38 v |= v >> 8; 39 v |= v >> 16; 40 v++; 41 return v; 42 } decodePredCtrl(uint64_t bits)43 static inline PredCtrl decodePredCtrl(uint64_t bits) { 44 return static_cast<PredCtrl>(bits); 45 } decodePredCtrlPvc(uint64_t bits)46 static inline PredCtrl decodePredCtrlPvc(uint64_t bits) { 47 switch (bits) { 48 case 0: return PredCtrl::NONE; 49 case 1: return PredCtrl::SEQ; 50 case 2: return PredCtrl::ANY; 51 case 3: return PredCtrl::ALL; 52 } 53 return static_cast<PredCtrl>(bits); 54 } decodeExecSizeBits(uint64_t val)55 static inline ExecSize decodeExecSizeBits(uint64_t val) { 56 switch (val) { 57 case 0: return ExecSize::SIMD1; 58 case 1: return ExecSize::SIMD2; 59 case 2: return ExecSize::SIMD4; 60 case 3: return ExecSize::SIMD8; 61 case 4: return ExecSize::SIMD16; 62 case 5: return ExecSize::SIMD32; 63 default: return ExecSize::INVALID; 64 } 65 } decodeChannelOffsetBits(uint64_t val)66 static inline ChannelOffset decodeChannelOffsetBits(uint64_t val) { 67 return static_cast<ChannelOffset>(val); 68 } decodeFlagModifierBits(uint64_t val)69 static inline FlagModifier decodeFlagModifierBits(uint64_t val) { 70 FlagModifier fm; 71 switch (val) { 72 case 0: fm = FlagModifier::NONE; break; 73 case 1: fm = FlagModifier::EQ; break; 74 case 2: fm = FlagModifier::NE; break; 75 case 3: fm = FlagModifier::GT; break; 76 case 4: fm = FlagModifier::GE; break; 77 case 5: fm = FlagModifier::LT; break; 78 case 6: fm = FlagModifier::LE; break; 79 // case 7: reserved 80 case 8: fm = FlagModifier::OV; break; 81 case 9: fm = FlagModifier::UN; break; 82 default: fm = static_cast<FlagModifier>(val); break; 83 } 84 return fm; 85 } decodeSrcModifierBits(uint64_t bits)86 static inline SrcModifier decodeSrcModifierBits(uint64_t bits) 87 { 88 switch (bits) { 89 case 0: return SrcModifier::NONE; 90 case 1: return SrcModifier::ABS; 91 case 2: return SrcModifier::NEG; 92 case 3: return SrcModifier::NEG_ABS; 93 default: return static_cast<SrcModifier>(bits); 94 } 95 } decodeFlagModifier(uint64_t bits)96 static inline FlagModifier decodeFlagModifier(uint64_t bits) 97 { 98 switch (bits) { 99 case 0: return FlagModifier::NONE; 100 case 1: return FlagModifier::EQ; 101 case 2: return FlagModifier::NE; 102 case 3: return FlagModifier::GT; 103 case 4: return FlagModifier::GE; 104 case 5: return FlagModifier::LT; 105 case 6: return FlagModifier::LE; 106 // 107 case 8: return FlagModifier::OV; 108 case 9: return FlagModifier::UN; 109 default: return static_cast<FlagModifier>(bits); 110 } 111 } 112 113 // 114 // This is a generic template for instruction decoders for various GEN 115 // platforms. Users can use this via inheritance or composition equally. 116 // This class also decodes field by field for various debugging routines. 117 // E.g. iga64 -Xifs ... decodes each field 118 // 119 // The naming convention is as follows: 120 // 121 // T decodeXXXX(Field fXXXX) 122 // decodes something (an XXXX) using field fXXXX and store this into the 123 // field list. This implies that fXXXX is properly part of the format and 124 // thus will not overlap with any other field decoded. It also might 125 // commit the field to the instruction builder. 126 // 127 // T peekXXXX(Field fXXXX) 128 // decoes something, but quietly (don't add it to the list of 129 // fields decoded). E.g. we might speculatively need to look at a field 130 // that we might not want to add. 131 // 132 // TODO: template<typename P> where P is PlatformInfo 133 // for GEN-specific stuff use this var; e.g. P.decodeBasicRegType(...) 134 struct InstDecoder 135 { 136 InstBuilder &builder; 137 ErrorHandler &errorHandler; 138 const Model &model; 139 const OpSpec &os; 140 MInst bits; 141 FragmentList *fields; 142 Loc loc; 143 144 // instruction state 145 ExecSize execSize; 146 InstOptSet instOptSet; 147 InstDecoderiga::InstDecoder148 InstDecoder( 149 InstBuilder &_builder, 150 ErrorHandler &_errorHandler, 151 const Model &_model, 152 const OpSpec &_os, 153 MInst _bits, 154 FragmentList *_fields, 155 Loc _loc) 156 : builder(_builder) 157 , errorHandler(_errorHandler) 158 , model(_model) 159 , os(_os) 160 , bits(_bits) 161 , fields(_fields) 162 , loc(_loc) 163 , execSize(ExecSize::INVALID) 164 , instOptSet(0) 165 { 166 } 167 isXeHpcPlusiga::InstDecoder168 bool isXeHpcPlus() const { 169 return model.platform >= Platform::XE_HPC; 170 } 171 reportErroriga::InstDecoder172 void reportError(const char *msg) { 173 errorHandler.reportError(loc, msg); 174 } reportErroriga::InstDecoder175 void reportError(const std::string &msg) { 176 errorHandler.reportError(loc, msg); 177 } reportWarningiga::InstDecoder178 void reportWarning(const std::string &msg) { 179 errorHandler.reportWarning(loc, msg); 180 } reportFieldErroriga::InstDecoder181 void reportFieldError(const Field &f, const char *msg) { 182 std::stringstream ss; 183 ss << f.name << ": " << msg; 184 reportError(ss.str()); 185 } reportFieldWarningiga::InstDecoder186 void reportFieldWarning(const Field &f, const char *msg) { 187 std::stringstream ss; 188 ss << f.name << ": " << msg; 189 reportWarning(ss.str()); 190 } reportFieldErrorInvalidValueiga::InstDecoder191 void reportFieldErrorInvalidValue(const Field &f) { 192 std::stringstream ss; 193 reportFieldError(f, "invalid value"); 194 } 195 196 /////////////////////////////////////////// 197 // PRIMITIVE FIELD ADDERS addDecodedFieldiga::InstDecoder198 void addDecodedField(const Field &f, std::string meaning) { 199 if (fields) { 200 int encodedFragments = 0; 201 for (const Fragment &fr : f.fragments) { 202 if (fr.isInvalid()) 203 break; 204 else if (fr.isEncoded()) 205 encodedFragments++; 206 } 207 bool multipleFragments = false; 208 int fragIx = 0; 209 for (const Fragment &fr : f.fragments) { 210 if (fr.isInvalid()) 211 break; 212 else if (fr.isEncoded()) { 213 std::string fragMeaning; 214 if (multipleFragments) { 215 std::stringstream ss; 216 ss << "[frag. " << fragIx << "]: " << meaning; 217 fragMeaning = ss.str(); 218 fragIx++; 219 } else { 220 fragMeaning = meaning; 221 } 222 addDecodedFragment(fr, fragMeaning); 223 } 224 } 225 } 226 } addDecodedFragmentiga::InstDecoder227 void addDecodedFragment(const Fragment &fr, std::string val) { 228 if (fields) 229 fields->emplace_back(fr, val); 230 } decodeFragmentiga::InstDecoder231 uint64_t decodeFragment(const Fragment &f) { 232 addDecodedFragment(f, ""); 233 return bits.getFragment(f); 234 } decodeFragmentiga::InstDecoder235 uint64_t decodeFragment(const Fragment &f, FormatFunction fmt) { 236 auto val = bits.getFragment(f); 237 if (fields) { 238 std::stringstream ss; 239 fmt(val, ss); 240 addDecodedFragment(f, ss.str()); 241 } 242 return val; 243 } decodeFieldWithFunctioniga::InstDecoder244 uint64_t decodeFieldWithFunction( 245 const Fragment &f, FormatFunction fmt) 246 { 247 return decodeFragment(f, fmt); 248 } 249 250 addReservediga::InstDecoder251 void addReserved(int off, int len, std::string errStr = "?") { 252 Fragment fRSVD("Reserved", off, len); 253 auto b = bits.getFragment(fRSVD); 254 addDecodedFragment(fRSVD, b != 0 ? errStr : ""); 255 } addReservediga::InstDecoder256 void addReserved(const Fragment &f) { 257 std::stringstream ss; 258 ss << "? (shadows " << f.name << ")"; 259 addReserved(f.offset, f.length, ss.str().c_str()); 260 } addReservediga::InstDecoder261 void addReserved(const Field &f) { 262 for (const Fragment &fr : f.fragments) { 263 if (fr.isEncoded()) { 264 addReserved(fr); 265 } 266 } 267 } 268 decodeFieldU32iga::InstDecoder269 uint32_t decodeFieldU32(const Field &f) { 270 addDecodedField(f, ""); 271 return (uint32_t)bits.getField(f); 272 } 273 274 /////////////////////////////////////////////////////////////////////////// 275 // one bit fields 276 /////////////////////////////////////////////////////////////////////////// 277 template <typename T> decodeFieldiga::InstDecoder278 T decodeField( 279 const Field &f, 280 T val0, const char *str0, 281 T val1, const char *str1) 282 { 283 IGA_ASSERT(f.length() == 1, "field is >1 bit"); 284 T val; 285 const char *str = ""; 286 auto b = bits.getField(f); 287 switch (b) { 288 case 0: val = val0; str = str0; break; 289 case 1: val = val1; str = str1; break; 290 default: 291 val = val0; // for compiler warning 292 IGA_ASSERT_FALSE("Unreachable"); 293 break; // unreachable 294 }; 295 if (fields) { 296 fields->emplace_back(f, str); 297 } 298 return val; 299 } decodeBoolFieldiga::InstDecoder300 bool decodeBoolField( 301 const Field &f, 302 const char *falseMeaning, 303 const char *trueMeaning) 304 { 305 return decodeField<bool>( 306 f, false, falseMeaning, true, trueMeaning); 307 } 308 309 /////////////////////////////////////////////////////////////////////// 310 // two bit fields 311 /////////////////////////////////////////////////////////////////////// 312 template <typename T> decodeFieldiga::InstDecoder313 T decodeField( 314 const Field &f, 315 T val0, const char *str0, 316 T val1, const char *str1, 317 T val2, const char *str2, 318 T val3, const char *str3) 319 { 320 // IGA_ASSERT(f.length == 2, "field is not a two bits"); 321 // we can have subset fields like Dst.RgnHz[0] in ternary 322 IGA_ASSERT(f.length() <= 2, "field is <=2 bits"); 323 T val; 324 const char *str = ""; 325 auto b = bits.getField(f); 326 switch (b) { 327 case 0: val = val0; str = str0; break; 328 case 1: val = val1; str = str1; break; 329 case 2: val = val2; str = str2; break; 330 case 3: val = val3; str = str3; break; 331 default: 332 val = val0; // for compiler warning 333 IGA_ASSERT_FALSE("Unreachable"); 334 break; // unreachable 335 }; 336 if (fields) { 337 fields->emplace_back(f, str); 338 } 339 return val; 340 } 341 342 /////////////////////////////////////////////////////////////////////// 343 // multi bit fields 344 /////////////////////////////////////////////////////////////////////// decodeFieldiga::InstDecoder345 uint64_t decodeField( 346 const Field &f, 347 FormatFunction fmt) 348 { 349 auto val = bits.getField(f); 350 if (fields) 351 { 352 std::stringstream ss; 353 fmt(val, ss); 354 fields->emplace_back(f, ss.str()); 355 } 356 return val; 357 } 358 359 template <typename T> decodeFieldiga::InstDecoder360 T decodeField( 361 const Field &f, 362 T invalid, 363 std::initializer_list<std::pair<T,const char *>> vals) 364 { 365 IGA_ASSERT(nextPowerOfTwo((int)vals.size()) != f.length(), 366 "field is wrong number of bits"); 367 int i = 0; 368 T retVal = invalid; 369 const char *strVal = "?"; 370 auto b = bits.getField(f); 371 for (const auto &val : vals) { 372 if (i == (int)b) { 373 retVal = val.first; 374 strVal = val.second; 375 break; 376 } 377 i++; 378 } 379 if (i == (int)vals.size() || retVal == invalid) { // didn't find it 380 retVal = invalid; 381 strVal = "?"; 382 reportFieldErrorInvalidValue(f); 383 } 384 385 if (fields) { 386 fields->emplace_back(f, strVal); 387 } 388 return retVal; 389 } 390 391 392 /////////////////////////////////////////////////////////////////////// 393 // generic GEN helpers 394 /////////////////////////////////////////////////////////////////////// isMacroiga::InstDecoder395 bool isMacro() const { 396 return builder.isMacroOp(); 397 } 398 decodeMaskCtrliga::InstDecoder399 void decodeMaskCtrl(const Field &fMASKCTRL) { 400 if (decodeBoolField(fMASKCTRL, "", "WrEn")) { 401 builder.InstNoMask(loc); 402 } 403 } 404 decodePredicationiga::InstDecoder405 void decodePredication( 406 const Field &fPREDINV, 407 const Field &fPREDCTRL, 408 const Field &fFLAGREG) 409 { 410 PredCtrl predCtrl = 411 isXeHpcPlus() ? 412 decodePredCtrlPvc(bits.getField(fPREDCTRL)) : 413 decodePredCtrl(bits.getField(fPREDCTRL)); 414 addDecodedField(fPREDCTRL, ToSyntax(predCtrl)); 415 bool predInv = decodeBoolField(fPREDINV, "", "~"); 416 if (predInv && predCtrl == PredCtrl::NONE) { 417 reportFieldError(fPREDINV, 418 "PredCtrl is not set, but PredInv is set"); 419 } 420 if (predCtrl != PredCtrl::NONE) { 421 RegRef flagReg = peekFlagRegRef(fFLAGREG); 422 builder.InstPredication(loc, predInv, flagReg, predCtrl); 423 } 424 } 425 decodeBrCtliga::InstDecoder426 void decodeBrCtl(const Field &fBRCTL) { 427 bool brCtl = decodeBoolField(fBRCTL, "", ".b"); 428 builder.InstSubfunction( 429 brCtl ? BranchCntrl::ON : BranchCntrl::OFF); 430 } 431 peekFlagRegRefiga::InstDecoder432 RegRef peekFlagRegRef(const Field &fFLAGREG) const { 433 auto val = (uint32_t)bits.getField(fFLAGREG); 434 return RegRef(val >> 1, val & 0x1); 435 } 436 decodeFlagRegiga::InstDecoder437 RegRef decodeFlagReg(const Field &fFLAGREG) { 438 // flag register 439 decodeField(fFLAGREG, 440 [] (uint64_t bits, std::stringstream &ss) { 441 ss << "f" << (bits >> 1) << "." << (bits & 0x1); 442 }); 443 return peekFlagRegRef(fFLAGREG); 444 } 445 decodeFlagModifierFieldiga::InstDecoder446 void decodeFlagModifierField( 447 const Field &fFLAGMOD, 448 const Field &fFLAGREG) 449 { 450 RegRef flagReg = peekFlagRegRef(fFLAGREG); 451 FlagModifier invalidModifier = static_cast<FlagModifier>(-1); 452 FlagModifier zeroValue = FlagModifier::NONE; 453 const char *zeroString = ""; 454 if (os.is(Op::MATH) && isMacro()) { 455 zeroValue = FlagModifier::EO; 456 zeroString = "(eo) (early out)"; 457 } 458 // TODO: use decodeFlagModifier() and ToSyntax 459 FlagModifier flagMod = decodeField<FlagModifier>( 460 fFLAGMOD, invalidModifier, { 461 {zeroValue, zeroString}, 462 {FlagModifier::EQ, "(eq)"}, 463 {FlagModifier::NE, "(ne)"}, 464 {FlagModifier::GT, "(gt)"}, 465 {FlagModifier::GE, "(ge)"}, 466 {FlagModifier::LT, "(lt)"}, 467 {FlagModifier::LE, "(le)"}, 468 {invalidModifier, "?"}, 469 {FlagModifier::OV, "(ov) (overflow)"}, 470 {FlagModifier::UN, "(un) (unordered)"}}); 471 builder.InstFlagModifier(flagReg, flagMod); 472 } 473 decodeImm32iga::InstDecoder474 ImmVal decodeImm32(const Field &fIMM32L, Type t) { 475 std::stringstream ss; 476 ImmVal immVal; 477 uint64_t val = bits.getField(fIMM32L); 478 // 479 // TODO: determine if ImmVal should store everything as s64 480 // otherwise I need to normalize what the GED parser and decoder 481 // a specific exmaple: 482 // NATIVE: 0x0000000000008000 483 // GED: 0xFFFFFFFFFFFF8000 484 // 485 // NATIVE: src0: PC[0]: 486 // mov: 61 00 03 00 a0 45 05 01 00 00 00 00 00 80 00 80 487 // mov (8|M0) r1.0<1>:f -32768:w 488 // GED takes a 64b value 489 switch (t) { 490 case Type::UW: 491 immVal = (uint16_t)val; 492 ss << std::hex << (uint16_t)val; 493 break; 494 case Type::UD: 495 immVal = (uint32_t)val; 496 ss << std::hex << "0x" << (uint32_t)val; 497 break; 498 case Type::W: 499 immVal = (int16_t)val; 500 immVal.s64 = immVal.s16; 501 ss << std::dec << (int16_t)val; 502 break; 503 case Type::D: 504 immVal = (int32_t)val; 505 immVal.s64 = immVal.s32; 506 ss << std::dec << (int32_t)val; 507 break; 508 case Type::HF: 509 immVal = (uint16_t)val; 510 immVal.kind = ImmVal::Kind::F16; 511 FormatFloat(ss, FloatFromBits((uint16_t)val)); 512 break; 513 case Type::F: 514 immVal = FloatFromBits((uint32_t)val); 515 FormatFloat(ss, FloatFromBits((uint32_t)val)); 516 break; 517 case Type::V: 518 case Type::UV: 519 immVal = (uint32_t)val; 520 ss << "("; 521 for (int i = 7; i >= 0; i--) { 522 if (i < 7) ss << ','; 523 if (t == Type::V) { 524 ss << std::hex << getSignedBits<int64_t>((int64_t)val, i*4, 4); 525 } else { 526 ss << std::dec << getBits<uint64_t>(val, i*4, 4); 527 } 528 } 529 ss << ")"; 530 break; 531 case Type::VF: 532 immVal = (uint32_t)val; 533 ss << "("; 534 for (int i = 3; i >= 0; i--) { 535 if (i < 3) ss << ','; 536 FormatFloat(ss, (uint8_t)getBits(val, i*8, 8)); 537 } 538 ss << ")"; 539 break; 540 break; 541 default: 542 immVal = (uint32_t)0; 543 reportFieldError(fIMM32L, "invalid type for 32b IMM"); 544 ss << "?"; 545 } 546 547 addDecodedField(fIMM32L, ss.str()); 548 549 return immVal; 550 } 551 decodeImm64iga::InstDecoder552 ImmVal decodeImm64( 553 const Field &fIMM32L, const Field &fIMM32H, Type type) 554 { 555 uint64_t lo = bits.getField(fIMM32L); 556 uint64_t hi = bits.getField(fIMM32H); 557 ImmVal immVal; 558 immVal.u64 = ((hi << 32) | lo);; 559 std::stringstream ss; 560 ss << "("; 561 switch (type) { 562 case Type::DF: 563 immVal.kind = ImmVal::Kind::F64; 564 FormatFloat(ss, FloatFromBits(immVal.u64)); 565 break; 566 case Type::UQ: 567 immVal.kind = ImmVal::Kind::U64; 568 ss << immVal.u64; 569 break; 570 case Type::Q: 571 immVal.kind = ImmVal::Kind::S64; 572 ss << immVal.s64; 573 break; 574 default: 575 ss << "ERROR: expected 64b type"; 576 reportError("ERROR: expected 64b type"); 577 } 578 ss << ")"; 579 addDecodedField(fIMM32L, "LO32" + ss.str()); 580 addDecodedField(fIMM32H, "HI32" + ss.str()); 581 return immVal; 582 } 583 decodeExecOffsetInfoiga::InstDecoder584 void decodeExecOffsetInfo( 585 const Field &fEXECSIZE, 586 const Field &fCHANOFF) 587 { 588 execSize = decodeExecSizeBits(bits.getField(fEXECSIZE)); 589 if (execSize == ExecSize::INVALID) { 590 reportFieldErrorInvalidValue(fEXECSIZE); 591 } 592 std::stringstream ssEs; 593 ssEs << "(" << ToSyntax(execSize) << "|...)"; 594 addDecodedField(fEXECSIZE, ssEs.str()); 595 596 auto chOffBits = bits.getField(fCHANOFF); 597 ChannelOffset chOff = decodeChannelOffsetBits(chOffBits); 598 if (chOff < ChannelOffset::M0 || chOff > ChannelOffset::M28) { 599 reportFieldErrorInvalidValue(fCHANOFF); 600 } 601 std::stringstream ssCo; 602 ssCo << "(..." << ToSyntax(chOff) << ")"; 603 addDecodedField(fCHANOFF, ssCo.str()); 604 605 builder.InstExecInfo(loc, execSize, loc, chOff); 606 } 607 decodeDstModifieriga::InstDecoder608 DstModifier decodeDstModifier(const Field &fSATURATE) { 609 return 610 decodeField(fSATURATE, 611 DstModifier::NONE, "", 612 DstModifier::SAT, "(sat)"); 613 } 614 decodeSrcModsiga::InstDecoder615 SrcModifier decodeSrcMods(const Field &fSRCMODS) { 616 return decodeField<SrcModifier>( 617 fSRCMODS, 618 SrcModifier::NONE,"", 619 SrcModifier::ABS, "(abs)", 620 SrcModifier::NEG, os.isBitwise() ? "~" : "-", 621 SrcModifier::NEG_ABS,"-(abs)"); 622 } 623 decodeMathMacroRegiga::InstDecoder624 MathMacroExt decodeMathMacroReg(const Field &fSPCACC) { 625 addReserved(fSPCACC.fragments[0].offset + 4, 1); 626 return decodeMathMacroRegField(fSPCACC); 627 } 628 decodeSubRegiga::InstDecoder629 void decodeSubReg( 630 OperandInfo &opInfo, 631 const Field &fSUBREG) 632 { 633 decodeSubRegWithType( 634 opInfo, fSUBREG, opInfo.type, ToSyntax(opInfo.type)); 635 } 636 637 // e.g. for subregisters without proper types decodeSubRegWithImplicitTypeiga::InstDecoder638 void decodeSubRegWithImplicitType( 639 OperandInfo &opInfo, 640 const Field &fSUBREG, 641 Type t) 642 { 643 decodeSubRegWithType(opInfo, fSUBREG, t, ""); 644 } 645 decodeSubRegWithTypeiga::InstDecoder646 void decodeSubRegWithType( 647 OperandInfo &opInfo, 648 const Field &fSUBREG, 649 Type type, 650 std::string typeSyntax) 651 { 652 auto srb = (int)bits.getField(fSUBREG); 653 auto scaled = BinaryOffsetToSubReg(srb, opInfo.regOpName, type, model.platform); 654 auto unscaled = 655 SubRegToBinaryOffset((int)scaled, opInfo.regOpName, type, model.platform); 656 if ((int)unscaled != srb) { 657 reportFieldError(fSUBREG, 658 "subregister offset is misaligned for type size"); 659 } 660 bool scaleArfFc = false; 661 scaleArfFc = model.platform >= Platform::XE_HPC; 662 if (opInfo.regOpName == RegName::ARF_FC && scaleArfFc) { 663 scaled /= 2; 664 } 665 opInfo.regOpReg.subRegNum = scaled; 666 667 std::stringstream ss; 668 ss << "." << (int)opInfo.regOpReg.subRegNum << typeSyntax; 669 addDecodedField(fSUBREG, ss.str()); 670 } 671 decodeRegDirectFieldsiga::InstDecoder672 void decodeRegDirectFields( 673 OpIx opIndex, 674 OperandInfo &opInfo, 675 const Field &fREGFILE, // direct only 676 const Field &fSPCACC, 677 const Field &fSUBREG, 678 const Field &fREG) 679 { 680 decodeRegFields(opInfo, fREGFILE, fREG); 681 if (isMacro()) { 682 opInfo.kind = Operand::Kind::MACRO; 683 opInfo.regOpMathMacroExtReg = decodeMathMacroRegField(fSPCACC); 684 addReserved( 685 fSPCACC.fragments[0].offset + fSPCACC.fragments[0].length, 686 1); 687 if (!IsTernary(opIndex) && 688 (IsDst(opIndex) || ToSrcIndex(opIndex) == 0) && 689 fSUBREG.length() > 1 && 690 fSUBREG.fragments[0].length == 1) 691 { 692 // for binary macros, the low of subreg is stowed elsewhere 693 addReserved(fSUBREG.fragments[0]); 694 } 695 } else { 696 opInfo.kind = Operand::Kind::DIRECT; 697 decodeSubReg(opInfo, fSUBREG); 698 } 699 } 700 decodeRegFieldsiga::InstDecoder701 void decodeRegFields( 702 OperandInfo &opInfo, 703 const Field &fREGFILE, 704 const Field &fREG) 705 { 706 bool isGrf = decodeBoolField(fREGFILE, "ARF", "GRF"); 707 std::stringstream ss; 708 auto regVal = bits.getField(fREG); 709 if (isGrf) { 710 opInfo.regOpName = RegName::GRF_R; 711 opInfo.regOpReg.regNum = (uint16_t)regVal; 712 ss << "r" << regVal; 713 } else { 714 readArfRegisterInfo(opInfo, fREG, ss); 715 } 716 addDecodedField(fREG, ss.str()); 717 } 718 719 // factored out so decodeInstSendDstOperand can share it readArfRegisterInfoiga::InstDecoder720 void readArfRegisterInfo( 721 OperandInfo &opInfo, 722 const Field &fREG, 723 std::stringstream &ssDesc) 724 { 725 auto regVal = bits.getField(fREG); 726 const RegInfo *regInfo = 727 model.lookupArfRegInfoByRegNum((uint8_t)regVal); 728 if (regInfo == nullptr) { 729 opInfo.regOpName = RegName::INVALID; 730 ssDesc << "invalid ARF"; 731 std::stringstream ssErr; 732 ssErr << "invalid ARF Reg (" << fmtHex(regVal, 2) << ")"; 733 reportFieldError(fREG, ssErr.str().c_str()); 734 return; 735 } 736 // 737 opInfo.regOpName = regInfo->regName; 738 ssDesc << regInfo->syntax; 739 int arfReg = 0; 740 if (regVal > 0xFF || !regInfo->decode((uint8_t)regVal, arfReg)) { 741 ssDesc << arfReg << "?"; 742 std::stringstream ss; 743 ss << regInfo->syntax << arfReg << " is out of bounds"; 744 reportFieldError(fREG, ss.str().c_str()); 745 } else { 746 if (regInfo->hasRegNum()) { 747 ssDesc << arfReg; 748 } 749 opInfo.regOpReg.regNum = (uint16_t)arfReg; 750 if (regInfo->regNumBase > 0) { 751 // if the register covers to another, let's tell 752 // them which 753 uint8_t coverRegBits = (uint8_t)(regVal & 0xF0); 754 const RegInfo *coverRegInfo = 755 model.lookupArfRegInfoByRegNum(coverRegBits); 756 if (coverRegInfo) { 757 // e.g. XE+ acc10 is mme2 758 ssDesc << " (" << 759 coverRegInfo->syntax << (regVal & 0xF) << ")"; 760 } 761 } 762 } 763 } 764 765 decodeMathMacroRegFieldiga::InstDecoder766 MathMacroExt decodeMathMacroRegField(const Field &fSPCACC) { 767 return decodeField<MathMacroExt>( 768 fSPCACC, MathMacroExt::INVALID, 769 {{MathMacroExt::MME0,".mme0"}, 770 {MathMacroExt::MME1,".mme1"}, 771 {MathMacroExt::MME2,".mme2"}, 772 {MathMacroExt::MME3,".mme3"}, 773 {MathMacroExt::MME4,".mme4"}, 774 {MathMacroExt::MME5,".mme5"}, 775 {MathMacroExt::MME6,".mme6"}, 776 {MathMacroExt::MME7,".mme7"}, 777 {MathMacroExt::NOMME,".nomme"}}); 778 } 779 decodeInstOptiga::InstDecoder780 bool decodeInstOpt(const Field &fINSTOPT, InstOpt opt) { 781 IGA_ASSERT(fINSTOPT.length() == 1, "inst opt field is >1 bit"); 782 783 std::stringstream ss; 784 bool z = bits.getField(fINSTOPT) != 0; 785 if (z) { 786 instOptSet.add(opt); 787 ss << "{" << ToSyntax(opt) << "}"; 788 } 789 addDecodedField(fINSTOPT, ss.str()); 790 return z; 791 } 792 }; // InstDecoder 793 } // iga:: 794 795 796 #endif // IGA_NATIVE_INSTDECODER_HPP 797