1 //===-- X86Operand.h - Parsed X86 machine instruction --------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #ifndef LLVM_LIB_TARGET_X86_ASMPARSER_X86OPERAND_H 11 #define LLVM_LIB_TARGET_X86_ASMPARSER_X86OPERAND_H 12 13 #include "X86AsmParserCommon.h" 14 #include "llvm/MC/MCExpr.h" 15 #include "llvm/MC/MCParser/MCParsedAsmOperand.h" 16 #include "llvm/ADT/STLExtras.h" 17 18 namespace llvm { 19 20 /// X86Operand - Instances of this class represent a parsed X86 machine 21 /// instruction. 22 struct X86Operand : public MCParsedAsmOperand { 23 enum KindTy { 24 Token, 25 Register, 26 Immediate, 27 Memory 28 } Kind; 29 30 SMLoc StartLoc, EndLoc; 31 SMLoc OffsetOfLoc; 32 StringRef SymName; 33 void *OpDecl; 34 bool AddressOf; 35 36 struct TokOp { 37 const char *Data; 38 unsigned Length; 39 }; 40 41 struct RegOp { 42 unsigned RegNo; 43 }; 44 45 struct ImmOp { 46 const MCExpr *Val; 47 }; 48 49 struct MemOp { 50 unsigned SegReg; 51 const MCExpr *Disp; 52 unsigned BaseReg; 53 unsigned IndexReg; 54 unsigned Scale; 55 unsigned Size; 56 unsigned ModeSize; 57 }; 58 59 union { 60 struct TokOp Tok; 61 struct RegOp Reg; 62 struct ImmOp Imm; 63 struct MemOp Mem; 64 }; 65 X86OperandX86Operand66 X86Operand(KindTy K, SMLoc Start, SMLoc End) 67 : Kind(K), StartLoc(Start), EndLoc(End) {} 68 getSymNameX86Operand69 StringRef getSymName() override { return SymName; } getOpDeclX86Operand70 void *getOpDecl() override { return OpDecl; } 71 72 /// getStartLoc - Get the location of the first token of this operand. getStartLocX86Operand73 SMLoc getStartLoc() const override { return StartLoc; } 74 /// getEndLoc - Get the location of the last token of this operand. getEndLocX86Operand75 SMLoc getEndLoc() const override { return EndLoc; } 76 /// getLocRange - Get the range between the first and last token of this 77 /// operand. getLocRangeX86Operand78 SMRange getLocRange() const { return SMRange(StartLoc, EndLoc); } 79 /// getOffsetOfLoc - Get the location of the offset operator. getOffsetOfLocX86Operand80 SMLoc getOffsetOfLoc() const override { return OffsetOfLoc; } 81 printX86Operand82 void print(raw_ostream &OS) const override {} 83 getTokenX86Operand84 StringRef getToken() const { 85 assert(Kind == Token && "Invalid access!"); 86 return StringRef(Tok.Data, Tok.Length); 87 } setTokenValueX86Operand88 void setTokenValue(StringRef Value) { 89 assert(Kind == Token && "Invalid access!"); 90 Tok.Data = Value.data(); 91 Tok.Length = Value.size(); 92 } 93 getRegX86Operand94 unsigned getReg() const override { 95 assert(Kind == Register && "Invalid access!"); 96 return Reg.RegNo; 97 } 98 getImmX86Operand99 const MCExpr *getImm() const { 100 assert(Kind == Immediate && "Invalid access!"); 101 return Imm.Val; 102 } 103 getMemDispX86Operand104 const MCExpr *getMemDisp() const { 105 assert(Kind == Memory && "Invalid access!"); 106 return Mem.Disp; 107 } getMemSegRegX86Operand108 unsigned getMemSegReg() const { 109 assert(Kind == Memory && "Invalid access!"); 110 return Mem.SegReg; 111 } getMemBaseRegX86Operand112 unsigned getMemBaseReg() const { 113 assert(Kind == Memory && "Invalid access!"); 114 return Mem.BaseReg; 115 } getMemIndexRegX86Operand116 unsigned getMemIndexReg() const { 117 assert(Kind == Memory && "Invalid access!"); 118 return Mem.IndexReg; 119 } getMemScaleX86Operand120 unsigned getMemScale() const { 121 assert(Kind == Memory && "Invalid access!"); 122 return Mem.Scale; 123 } getMemModeSizeX86Operand124 unsigned getMemModeSize() const { 125 assert(Kind == Memory && "Invalid access!"); 126 return Mem.ModeSize; 127 } 128 isTokenX86Operand129 bool isToken() const override {return Kind == Token; } 130 isImmX86Operand131 bool isImm() const override { return Kind == Immediate; } 132 isImmSExti16i8X86Operand133 bool isImmSExti16i8() const { 134 if (!isImm()) 135 return false; 136 137 // If this isn't a constant expr, just assume it fits and let relaxation 138 // handle it. 139 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 140 if (!CE) 141 return true; 142 143 // Otherwise, check the value is in a range that makes sense for this 144 // extension. 145 return isImmSExti16i8Value(CE->getValue()); 146 } isImmSExti32i8X86Operand147 bool isImmSExti32i8() const { 148 if (!isImm()) 149 return false; 150 151 // If this isn't a constant expr, just assume it fits and let relaxation 152 // handle it. 153 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 154 if (!CE) 155 return true; 156 157 // Otherwise, check the value is in a range that makes sense for this 158 // extension. 159 return isImmSExti32i8Value(CE->getValue()); 160 } isImmSExti64i8X86Operand161 bool isImmSExti64i8() const { 162 if (!isImm()) 163 return false; 164 165 // If this isn't a constant expr, just assume it fits and let relaxation 166 // handle it. 167 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 168 if (!CE) 169 return true; 170 171 // Otherwise, check the value is in a range that makes sense for this 172 // extension. 173 return isImmSExti64i8Value(CE->getValue()); 174 } isImmSExti64i32X86Operand175 bool isImmSExti64i32() const { 176 if (!isImm()) 177 return false; 178 179 // If this isn't a constant expr, just assume it fits and let relaxation 180 // handle it. 181 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm()); 182 if (!CE) 183 return true; 184 185 // Otherwise, check the value is in a range that makes sense for this 186 // extension. 187 return isImmSExti64i32Value(CE->getValue()); 188 } 189 isOffsetOfX86Operand190 bool isOffsetOf() const override { 191 return OffsetOfLoc.getPointer(); 192 } 193 needAddressOfX86Operand194 bool needAddressOf() const override { 195 return AddressOf; 196 } 197 isMemX86Operand198 bool isMem() const override { return Kind == Memory; } isMemUnsizedX86Operand199 bool isMemUnsized() const { 200 return Kind == Memory && Mem.Size == 0; 201 } isMem8X86Operand202 bool isMem8() const { 203 return Kind == Memory && (!Mem.Size || Mem.Size == 8); 204 } isMem16X86Operand205 bool isMem16() const { 206 return Kind == Memory && (!Mem.Size || Mem.Size == 16); 207 } isMem32X86Operand208 bool isMem32() const { 209 return Kind == Memory && (!Mem.Size || Mem.Size == 32); 210 } isMem64X86Operand211 bool isMem64() const { 212 return Kind == Memory && (!Mem.Size || Mem.Size == 64); 213 } isMem80X86Operand214 bool isMem80() const { 215 return Kind == Memory && (!Mem.Size || Mem.Size == 80); 216 } isMem128X86Operand217 bool isMem128() const { 218 return Kind == Memory && (!Mem.Size || Mem.Size == 128); 219 } isMem256X86Operand220 bool isMem256() const { 221 return Kind == Memory && (!Mem.Size || Mem.Size == 256); 222 } isMem512X86Operand223 bool isMem512() const { 224 return Kind == Memory && (!Mem.Size || Mem.Size == 512); 225 } 226 isMemVX32X86Operand227 bool isMemVX32() const { 228 return Kind == Memory && (!Mem.Size || Mem.Size == 32) && 229 getMemIndexReg() >= X86::XMM0 && getMemIndexReg() <= X86::XMM15; 230 } isMemVY32X86Operand231 bool isMemVY32() const { 232 return Kind == Memory && (!Mem.Size || Mem.Size == 32) && 233 getMemIndexReg() >= X86::YMM0 && getMemIndexReg() <= X86::YMM15; 234 } isMemVX64X86Operand235 bool isMemVX64() const { 236 return Kind == Memory && (!Mem.Size || Mem.Size == 64) && 237 getMemIndexReg() >= X86::XMM0 && getMemIndexReg() <= X86::XMM15; 238 } isMemVY64X86Operand239 bool isMemVY64() const { 240 return Kind == Memory && (!Mem.Size || Mem.Size == 64) && 241 getMemIndexReg() >= X86::YMM0 && getMemIndexReg() <= X86::YMM15; 242 } isMemVZ32X86Operand243 bool isMemVZ32() const { 244 return Kind == Memory && (!Mem.Size || Mem.Size == 32) && 245 getMemIndexReg() >= X86::ZMM0 && getMemIndexReg() <= X86::ZMM31; 246 } isMemVZ64X86Operand247 bool isMemVZ64() const { 248 return Kind == Memory && (!Mem.Size || Mem.Size == 64) && 249 getMemIndexReg() >= X86::ZMM0 && getMemIndexReg() <= X86::ZMM31; 250 } 251 isAbsMemX86Operand252 bool isAbsMem() const { 253 return Kind == Memory && !getMemSegReg() && !getMemBaseReg() && 254 !getMemIndexReg() && getMemScale() == 1; 255 } 256 isAbsMem16X86Operand257 bool isAbsMem16() const { 258 return isAbsMem() && Mem.ModeSize == 16; 259 } 260 isAbsMem32X86Operand261 bool isAbsMem32() const { 262 return isAbsMem() && Mem.ModeSize != 16; 263 } 264 isSrcIdxX86Operand265 bool isSrcIdx() const { 266 return !getMemIndexReg() && getMemScale() == 1 && 267 (getMemBaseReg() == X86::RSI || getMemBaseReg() == X86::ESI || 268 getMemBaseReg() == X86::SI) && isa<MCConstantExpr>(getMemDisp()) && 269 cast<MCConstantExpr>(getMemDisp())->getValue() == 0; 270 } isSrcIdx8X86Operand271 bool isSrcIdx8() const { 272 return isMem8() && isSrcIdx(); 273 } isSrcIdx16X86Operand274 bool isSrcIdx16() const { 275 return isMem16() && isSrcIdx(); 276 } isSrcIdx32X86Operand277 bool isSrcIdx32() const { 278 return isMem32() && isSrcIdx(); 279 } isSrcIdx64X86Operand280 bool isSrcIdx64() const { 281 return isMem64() && isSrcIdx(); 282 } 283 isDstIdxX86Operand284 bool isDstIdx() const { 285 return !getMemIndexReg() && getMemScale() == 1 && 286 (getMemSegReg() == 0 || getMemSegReg() == X86::ES) && 287 (getMemBaseReg() == X86::RDI || getMemBaseReg() == X86::EDI || 288 getMemBaseReg() == X86::DI) && isa<MCConstantExpr>(getMemDisp()) && 289 cast<MCConstantExpr>(getMemDisp())->getValue() == 0; 290 } isDstIdx8X86Operand291 bool isDstIdx8() const { 292 return isMem8() && isDstIdx(); 293 } isDstIdx16X86Operand294 bool isDstIdx16() const { 295 return isMem16() && isDstIdx(); 296 } isDstIdx32X86Operand297 bool isDstIdx32() const { 298 return isMem32() && isDstIdx(); 299 } isDstIdx64X86Operand300 bool isDstIdx64() const { 301 return isMem64() && isDstIdx(); 302 } 303 isMemOffsX86Operand304 bool isMemOffs() const { 305 return Kind == Memory && !getMemBaseReg() && !getMemIndexReg() && 306 getMemScale() == 1; 307 } 308 isMemOffs16_8X86Operand309 bool isMemOffs16_8() const { 310 return isMemOffs() && Mem.ModeSize == 16 && (!Mem.Size || Mem.Size == 8); 311 } isMemOffs16_16X86Operand312 bool isMemOffs16_16() const { 313 return isMemOffs() && Mem.ModeSize == 16 && (!Mem.Size || Mem.Size == 16); 314 } isMemOffs16_32X86Operand315 bool isMemOffs16_32() const { 316 return isMemOffs() && Mem.ModeSize == 16 && (!Mem.Size || Mem.Size == 32); 317 } isMemOffs32_8X86Operand318 bool isMemOffs32_8() const { 319 return isMemOffs() && Mem.ModeSize == 32 && (!Mem.Size || Mem.Size == 8); 320 } isMemOffs32_16X86Operand321 bool isMemOffs32_16() const { 322 return isMemOffs() && Mem.ModeSize == 32 && (!Mem.Size || Mem.Size == 16); 323 } isMemOffs32_32X86Operand324 bool isMemOffs32_32() const { 325 return isMemOffs() && Mem.ModeSize == 32 && (!Mem.Size || Mem.Size == 32); 326 } isMemOffs32_64X86Operand327 bool isMemOffs32_64() const { 328 return isMemOffs() && Mem.ModeSize == 32 && (!Mem.Size || Mem.Size == 64); 329 } isMemOffs64_8X86Operand330 bool isMemOffs64_8() const { 331 return isMemOffs() && Mem.ModeSize == 64 && (!Mem.Size || Mem.Size == 8); 332 } isMemOffs64_16X86Operand333 bool isMemOffs64_16() const { 334 return isMemOffs() && Mem.ModeSize == 64 && (!Mem.Size || Mem.Size == 16); 335 } isMemOffs64_32X86Operand336 bool isMemOffs64_32() const { 337 return isMemOffs() && Mem.ModeSize == 64 && (!Mem.Size || Mem.Size == 32); 338 } isMemOffs64_64X86Operand339 bool isMemOffs64_64() const { 340 return isMemOffs() && Mem.ModeSize == 64 && (!Mem.Size || Mem.Size == 64); 341 } 342 isRegX86Operand343 bool isReg() const override { return Kind == Register; } 344 isGR32orGR64X86Operand345 bool isGR32orGR64() const { 346 return Kind == Register && 347 (X86MCRegisterClasses[X86::GR32RegClassID].contains(getReg()) || 348 X86MCRegisterClasses[X86::GR64RegClassID].contains(getReg())); 349 } 350 addExprX86Operand351 void addExpr(MCInst &Inst, const MCExpr *Expr) const { 352 // Add as immediates when possible. 353 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr)) 354 Inst.addOperand(MCOperand::CreateImm(CE->getValue())); 355 else 356 Inst.addOperand(MCOperand::CreateExpr(Expr)); 357 } 358 addRegOperandsX86Operand359 void addRegOperands(MCInst &Inst, unsigned N) const { 360 assert(N == 1 && "Invalid number of operands!"); 361 Inst.addOperand(MCOperand::CreateReg(getReg())); 362 } 363 getGR32FromGR64X86Operand364 static unsigned getGR32FromGR64(unsigned RegNo) { 365 switch (RegNo) { 366 default: llvm_unreachable("Unexpected register"); 367 case X86::RAX: return X86::EAX; 368 case X86::RCX: return X86::ECX; 369 case X86::RDX: return X86::EDX; 370 case X86::RBX: return X86::EBX; 371 case X86::RBP: return X86::EBP; 372 case X86::RSP: return X86::ESP; 373 case X86::RSI: return X86::ESI; 374 case X86::RDI: return X86::EDI; 375 case X86::R8: return X86::R8D; 376 case X86::R9: return X86::R9D; 377 case X86::R10: return X86::R10D; 378 case X86::R11: return X86::R11D; 379 case X86::R12: return X86::R12D; 380 case X86::R13: return X86::R13D; 381 case X86::R14: return X86::R14D; 382 case X86::R15: return X86::R15D; 383 case X86::RIP: return X86::EIP; 384 } 385 } 386 addGR32orGR64OperandsX86Operand387 void addGR32orGR64Operands(MCInst &Inst, unsigned N) const { 388 assert(N == 1 && "Invalid number of operands!"); 389 unsigned RegNo = getReg(); 390 if (X86MCRegisterClasses[X86::GR64RegClassID].contains(RegNo)) 391 RegNo = getGR32FromGR64(RegNo); 392 Inst.addOperand(MCOperand::CreateReg(RegNo)); 393 } 394 addImmOperandsX86Operand395 void addImmOperands(MCInst &Inst, unsigned N) const { 396 assert(N == 1 && "Invalid number of operands!"); 397 addExpr(Inst, getImm()); 398 } 399 addMemOperandsX86Operand400 void addMemOperands(MCInst &Inst, unsigned N) const { 401 assert((N == 5) && "Invalid number of operands!"); 402 Inst.addOperand(MCOperand::CreateReg(getMemBaseReg())); 403 Inst.addOperand(MCOperand::CreateImm(getMemScale())); 404 Inst.addOperand(MCOperand::CreateReg(getMemIndexReg())); 405 addExpr(Inst, getMemDisp()); 406 Inst.addOperand(MCOperand::CreateReg(getMemSegReg())); 407 } 408 addAbsMemOperandsX86Operand409 void addAbsMemOperands(MCInst &Inst, unsigned N) const { 410 assert((N == 1) && "Invalid number of operands!"); 411 // Add as immediates when possible. 412 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getMemDisp())) 413 Inst.addOperand(MCOperand::CreateImm(CE->getValue())); 414 else 415 Inst.addOperand(MCOperand::CreateExpr(getMemDisp())); 416 } 417 addSrcIdxOperandsX86Operand418 void addSrcIdxOperands(MCInst &Inst, unsigned N) const { 419 assert((N == 2) && "Invalid number of operands!"); 420 Inst.addOperand(MCOperand::CreateReg(getMemBaseReg())); 421 Inst.addOperand(MCOperand::CreateReg(getMemSegReg())); 422 } addDstIdxOperandsX86Operand423 void addDstIdxOperands(MCInst &Inst, unsigned N) const { 424 assert((N == 1) && "Invalid number of operands!"); 425 Inst.addOperand(MCOperand::CreateReg(getMemBaseReg())); 426 } 427 addMemOffsOperandsX86Operand428 void addMemOffsOperands(MCInst &Inst, unsigned N) const { 429 assert((N == 2) && "Invalid number of operands!"); 430 // Add as immediates when possible. 431 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getMemDisp())) 432 Inst.addOperand(MCOperand::CreateImm(CE->getValue())); 433 else 434 Inst.addOperand(MCOperand::CreateExpr(getMemDisp())); 435 Inst.addOperand(MCOperand::CreateReg(getMemSegReg())); 436 } 437 CreateTokenX86Operand438 static std::unique_ptr<X86Operand> CreateToken(StringRef Str, SMLoc Loc) { 439 SMLoc EndLoc = SMLoc::getFromPointer(Loc.getPointer() + Str.size()); 440 auto Res = llvm::make_unique<X86Operand>(Token, Loc, EndLoc); 441 Res->Tok.Data = Str.data(); 442 Res->Tok.Length = Str.size(); 443 return Res; 444 } 445 446 static std::unique_ptr<X86Operand> 447 CreateReg(unsigned RegNo, SMLoc StartLoc, SMLoc EndLoc, 448 bool AddressOf = false, SMLoc OffsetOfLoc = SMLoc(), 449 StringRef SymName = StringRef(), void *OpDecl = nullptr) { 450 auto Res = llvm::make_unique<X86Operand>(Register, StartLoc, EndLoc); 451 Res->Reg.RegNo = RegNo; 452 Res->AddressOf = AddressOf; 453 Res->OffsetOfLoc = OffsetOfLoc; 454 Res->SymName = SymName; 455 Res->OpDecl = OpDecl; 456 return Res; 457 } 458 CreateImmX86Operand459 static std::unique_ptr<X86Operand> CreateImm(const MCExpr *Val, 460 SMLoc StartLoc, SMLoc EndLoc) { 461 auto Res = llvm::make_unique<X86Operand>(Immediate, StartLoc, EndLoc); 462 Res->Imm.Val = Val; 463 return Res; 464 } 465 466 /// Create an absolute memory operand. 467 static std::unique_ptr<X86Operand> 468 CreateMem(unsigned ModeSize, const MCExpr *Disp, SMLoc StartLoc, SMLoc EndLoc, 469 unsigned Size = 0, StringRef SymName = StringRef(), 470 void *OpDecl = nullptr) { 471 auto Res = llvm::make_unique<X86Operand>(Memory, StartLoc, EndLoc); 472 Res->Mem.SegReg = 0; 473 Res->Mem.Disp = Disp; 474 Res->Mem.BaseReg = 0; 475 Res->Mem.IndexReg = 0; 476 Res->Mem.Scale = 1; 477 Res->Mem.Size = Size; 478 Res->Mem.ModeSize = ModeSize; 479 Res->SymName = SymName; 480 Res->OpDecl = OpDecl; 481 Res->AddressOf = false; 482 return Res; 483 } 484 485 /// Create a generalized memory operand. 486 static std::unique_ptr<X86Operand> 487 CreateMem(unsigned ModeSize, unsigned SegReg, const MCExpr *Disp, 488 unsigned BaseReg, unsigned IndexReg, unsigned Scale, SMLoc StartLoc, 489 SMLoc EndLoc, unsigned Size = 0, StringRef SymName = StringRef(), 490 void *OpDecl = nullptr) { 491 // We should never just have a displacement, that should be parsed as an 492 // absolute memory operand. 493 assert((SegReg || BaseReg || IndexReg) && "Invalid memory operand!"); 494 495 // The scale should always be one of {1,2,4,8}. 496 assert(((Scale == 1 || Scale == 2 || Scale == 4 || Scale == 8)) && 497 "Invalid scale!"); 498 auto Res = llvm::make_unique<X86Operand>(Memory, StartLoc, EndLoc); 499 Res->Mem.SegReg = SegReg; 500 Res->Mem.Disp = Disp; 501 Res->Mem.BaseReg = BaseReg; 502 Res->Mem.IndexReg = IndexReg; 503 Res->Mem.Scale = Scale; 504 Res->Mem.Size = Size; 505 Res->Mem.ModeSize = ModeSize; 506 Res->SymName = SymName; 507 Res->OpDecl = OpDecl; 508 Res->AddressOf = false; 509 return Res; 510 } 511 }; 512 513 } // End of namespace llvm 514 515 #endif 516