Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 //===- subzero/src/IceInstX8632.cpp - X86-32 instruction implementation ---===// | 1 //===- subzero/src/IceInstX8632.cpp - X86-32 instruction implementation ---===// |
| 2 // | 2 // |
| 3 // The Subzero Code Generator | 3 // The Subzero Code Generator |
| 4 // | 4 // |
| 5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
| 6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
| 7 // | 7 // |
| 8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
| 9 // | 9 // |
| 10 // This file implements the InstX8632 and OperandX8632 classes, | 10 // This file implements the InstX8632 and OperandX8632 classes, |
| (...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 335 } | 335 } |
| 336 | 336 |
| 337 InstX8632Xchg::InstX8632Xchg(Cfg *Func, Operand *Dest, Variable *Source) | 337 InstX8632Xchg::InstX8632Xchg(Cfg *Func, Operand *Dest, Variable *Source) |
| 338 : InstX8632(Func, InstX8632::Xchg, 2, llvm::dyn_cast<Variable>(Dest)) { | 338 : InstX8632(Func, InstX8632::Xchg, 2, llvm::dyn_cast<Variable>(Dest)) { |
| 339 addSource(Dest); | 339 addSource(Dest); |
| 340 addSource(Source); | 340 addSource(Source); |
| 341 } | 341 } |
| 342 | 342 |
| 343 // ======================== Dump routines ======================== // | 343 // ======================== Dump routines ======================== // |
| 344 | 344 |
| 345 namespace { | |
|
Jim Stichnoth
2014/11/06 00:02:13
Sweet!
| |
| 346 | |
| 347 void emitIASBytes(const Cfg *Func, const x86::AssemblerX86 *Asm, | |
| 348 intptr_t StartPosition) { | |
| 349 GlobalContext *Ctx = Func->getContext(); | |
| 350 Ostream &Str = Ctx->getStrEmit(); | |
| 351 intptr_t EndPosition = Asm->GetPosition(); | |
| 352 AssemblerFixup *LastFixup = Asm->GetLatestFixup(StartPosition); | |
| 353 if (!LastFixup) { | |
| 354 // The fixup doesn't apply to this current block. | |
| 355 for (intptr_t i = StartPosition; i < EndPosition; ++i) { | |
| 356 Str << "\t.byte 0x"; | |
| 357 Str.write_hex(Asm->LoadBuffer<uint8_t>(i)); | |
| 358 Str << "\n"; | |
| 359 } | |
| 360 return; | |
| 361 } | |
| 362 intptr_t LastFixupLoc = LastFixup->position(); | |
| 363 const intptr_t FixupSize = 4; | |
| 364 // The fixup does apply to this current block. | |
| 365 for (intptr_t i = StartPosition; i < LastFixupLoc; ++i) { | |
| 366 Str << "\t.byte 0x"; | |
| 367 Str.write_hex(Asm->LoadBuffer<uint8_t>(i)); | |
| 368 Str << "\n"; | |
| 369 } | |
| 370 while (LastFixup) { | |
| 371 Str << "\t.long "; | |
| 372 const ConstantRelocatable *Reloc = LastFixup->value(); | |
| 373 if (Reloc->getSuppressMangling()) | |
| 374 Str << Reloc->getName(); | |
| 375 else | |
| 376 Str << Ctx->mangleName(Reloc->getName()); | |
| 377 if (LastFixup->value()->getOffset()) { | |
| 378 Str << " + " << LastFixup->value()->getOffset(); | |
| 379 } | |
| 380 Str << "\n"; | |
| 381 LastFixupLoc += FixupSize; | |
| 382 assert(LastFixupLoc <= EndPosition); | |
| 383 LastFixup = Asm->GetLatestFixup(LastFixupLoc); | |
| 384 // Assume multi-fixups are adjacent in the instruction encoding. | |
| 385 assert(!LastFixup || LastFixup->position() == LastFixupLoc); | |
| 386 } | |
| 387 for (intptr_t i = LastFixupLoc; i < EndPosition; ++i) { | |
| 388 Str << "\t.byte 0x"; | |
| 389 Str.write_hex(Asm->LoadBuffer<uint8_t>(i)); | |
| 390 Str << "\n"; | |
| 391 } | |
| 392 } | |
| 393 | |
| 394 void emitIASBytesBranch(const Cfg *Func, const x86::AssemblerX86 *Asm, | |
| 395 intptr_t StartPosition, const x86::Label *Label, | |
| 396 const IceString &LabelName, bool Near) { | |
| 397 // If this is a backward branch (label is bound), we're good and know | |
| 398 // the offset. If this is a forward branch, then we can't actually emit | |
| 399 // the thing as text in a streaming manner, because the fixup hasn't | |
| 400 // happened yet. Instead, emit .long ($BranchLabel) - (. + 4), in that | |
| 401 // case and let the external assembler take care of that fixup. | |
| 402 if (Label->IsBound()) { | |
| 403 emitIASBytes(Func, Asm, StartPosition); | |
| 404 return; | |
| 405 } | |
| 406 const intptr_t FwdBranchSize = Near ? 1 : 4; | |
| 407 const IceString FwdBranchDirective = Near ? ".byte" : ".long"; | |
| 408 Ostream &Str = Func->getContext()->getStrEmit(); | |
| 409 intptr_t EndPosition = Asm->GetPosition(); | |
| 410 assert(EndPosition - StartPosition > FwdBranchSize); | |
| 411 for (intptr_t i = StartPosition; i < EndPosition - FwdBranchSize; ++i) { | |
| 412 Str << "\t.byte 0x"; | |
| 413 Str.write_hex(Asm->LoadBuffer<uint8_t>(i)); | |
| 414 Str << "\n"; | |
| 415 } | |
| 416 Str << "\t" << FwdBranchDirective << " " << LabelName << " - (. + " | |
| 417 << FwdBranchSize << ")\n"; | |
| 418 return; | |
| 419 } | |
| 420 | |
| 421 } // end of anonymous namespace | |
| 422 | |
| 423 void InstX8632::dump(const Cfg *Func) const { | 345 void InstX8632::dump(const Cfg *Func) const { |
| 424 Ostream &Str = Func->getContext()->getStrDump(); | 346 Ostream &Str = Func->getContext()->getStrDump(); |
| 425 Str << "[X8632] "; | 347 Str << "[X8632] "; |
| 426 Inst::dump(Func); | 348 Inst::dump(Func); |
| 427 } | 349 } |
| 428 | 350 |
| 429 void InstX8632Label::emit(const Cfg *Func) const { | 351 void InstX8632Label::emit(const Cfg *Func) const { |
| 430 Ostream &Str = Func->getContext()->getStrEmit(); | 352 Ostream &Str = Func->getContext()->getStrEmit(); |
| 431 Str << getName(Func) << ":"; | 353 Str << getName(Func) << ":"; |
| 432 } | 354 } |
| 433 | 355 |
| 434 void InstX8632Label::emitIAS(const Cfg *Func) const { | 356 void InstX8632Label::emitIAS(const Cfg *Func) const { |
| 435 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 357 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 436 Asm->BindLocalLabel(Number); | 358 Asm->BindLocalLabel(Number); |
| 437 // TODO(jvoung): remove the the textual label once forward branch | |
| 438 // fixups are used (and text assembler is not used). | |
| 439 Ostream &Str = Func->getContext()->getStrEmit(); | |
| 440 Str << getName(Func) << ":\n"; | |
| 441 } | 359 } |
| 442 | 360 |
| 443 void InstX8632Label::dump(const Cfg *Func) const { | 361 void InstX8632Label::dump(const Cfg *Func) const { |
| 444 Ostream &Str = Func->getContext()->getStrDump(); | 362 Ostream &Str = Func->getContext()->getStrDump(); |
| 445 Str << getName(Func) << ":"; | 363 Str << getName(Func) << ":"; |
| 446 } | 364 } |
| 447 | 365 |
| 448 void InstX8632Br::emit(const Cfg *Func) const { | 366 void InstX8632Br::emit(const Cfg *Func) const { |
| 449 Ostream &Str = Func->getContext()->getStrEmit(); | 367 Ostream &Str = Func->getContext()->getStrEmit(); |
| 450 Str << "\t"; | 368 Str << "\t"; |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 464 Str << "\t" << getTargetTrue()->getAsmName(); | 382 Str << "\t" << getTargetTrue()->getAsmName(); |
| 465 if (getTargetFalse()) { | 383 if (getTargetFalse()) { |
| 466 Str << "\n\tjmp\t" << getTargetFalse()->getAsmName(); | 384 Str << "\n\tjmp\t" << getTargetFalse()->getAsmName(); |
| 467 } | 385 } |
| 468 } | 386 } |
| 469 } | 387 } |
| 470 } | 388 } |
| 471 | 389 |
| 472 void InstX8632Br::emitIAS(const Cfg *Func) const { | 390 void InstX8632Br::emitIAS(const Cfg *Func) const { |
| 473 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 391 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 474 intptr_t StartPosition = Asm->GetPosition(); | |
| 475 if (Label) { | 392 if (Label) { |
| 476 x86::Label *L = Asm->GetOrCreateLocalLabel(Label->getNumber()); | 393 x86::Label *L = Asm->GetOrCreateLocalLabel(Label->getNumber()); |
| 477 // In all these cases, local Labels should only be used for Near. | 394 // In all these cases, local Labels should only be used for Near. |
| 478 const bool Near = true; | 395 const bool Near = true; |
| 479 if (Condition == CondX86::Br_None) { | 396 if (Condition == CondX86::Br_None) { |
| 480 Asm->jmp(L, Near); | 397 Asm->jmp(L, Near); |
| 481 } else { | 398 } else { |
| 482 Asm->j(Condition, L, Near); | 399 Asm->j(Condition, L, Near); |
| 483 } | 400 } |
| 484 emitIASBytesBranch(Func, Asm, StartPosition, L, Label->getName(Func), Near); | |
| 485 } else { | 401 } else { |
| 486 // Pessimistically assume it's far. This only affects Labels that | 402 // Pessimistically assume it's far. This only affects Labels that |
| 487 // are not Bound. | 403 // are not Bound. |
| 488 const bool Near = false; | 404 const bool Near = false; |
| 489 if (Condition == CondX86::Br_None) { | 405 if (Condition == CondX86::Br_None) { |
| 490 x86::Label *L = | 406 x86::Label *L = |
| 491 Asm->GetOrCreateCfgNodeLabel(getTargetFalse()->getIndex()); | 407 Asm->GetOrCreateCfgNodeLabel(getTargetFalse()->getIndex()); |
| 492 assert(!getTargetTrue()); | 408 assert(!getTargetTrue()); |
| 493 Asm->jmp(L, Near); | 409 Asm->jmp(L, Near); |
| 494 emitIASBytesBranch(Func, Asm, StartPosition, L, | |
| 495 getTargetFalse()->getAsmName(), Near); | |
| 496 } else { | 410 } else { |
| 497 x86::Label *L = Asm->GetOrCreateCfgNodeLabel(getTargetTrue()->getIndex()); | 411 x86::Label *L = Asm->GetOrCreateCfgNodeLabel(getTargetTrue()->getIndex()); |
| 498 Asm->j(Condition, L, Near); | 412 Asm->j(Condition, L, Near); |
| 499 emitIASBytesBranch(Func, Asm, StartPosition, L, | |
| 500 getTargetTrue()->getAsmName(), Near); | |
| 501 StartPosition = Asm->GetPosition(); | |
| 502 if (getTargetFalse()) { | 413 if (getTargetFalse()) { |
| 503 x86::Label *L2 = | 414 x86::Label *L2 = |
| 504 Asm->GetOrCreateCfgNodeLabel(getTargetFalse()->getIndex()); | 415 Asm->GetOrCreateCfgNodeLabel(getTargetFalse()->getIndex()); |
| 505 Asm->jmp(L2, Near); | 416 Asm->jmp(L2, Near); |
| 506 emitIASBytesBranch(Func, Asm, StartPosition, L2, | |
| 507 getTargetFalse()->getAsmName(), Near); | |
| 508 } | 417 } |
| 509 } | 418 } |
| 510 } | 419 } |
| 511 } | 420 } |
| 512 | 421 |
| 513 void InstX8632Br::dump(const Cfg *Func) const { | 422 void InstX8632Br::dump(const Cfg *Func) const { |
| 514 Ostream &Str = Func->getContext()->getStrDump(); | 423 Ostream &Str = Func->getContext()->getStrDump(); |
| 515 Str << "br "; | 424 Str << "br "; |
| 516 | 425 |
| 517 if (Condition == CondX86::Br_None) { | 426 if (Condition == CondX86::Br_None) { |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 542 CallTarget->emitWithoutDollar(Func->getContext()); | 451 CallTarget->emitWithoutDollar(Func->getContext()); |
| 543 } else { | 452 } else { |
| 544 Str << "*"; | 453 Str << "*"; |
| 545 getCallTarget()->emit(Func); | 454 getCallTarget()->emit(Func); |
| 546 } | 455 } |
| 547 Func->getTarget()->resetStackAdjustment(); | 456 Func->getTarget()->resetStackAdjustment(); |
| 548 } | 457 } |
| 549 | 458 |
| 550 void InstX8632Call::emitIAS(const Cfg *Func) const { | 459 void InstX8632Call::emitIAS(const Cfg *Func) const { |
| 551 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 460 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 552 intptr_t StartPosition = Asm->GetPosition(); | |
| 553 Operand *Target = getCallTarget(); | 461 Operand *Target = getCallTarget(); |
| 554 bool NeedsFallback = false; | |
| 555 if (const auto Var = llvm::dyn_cast<Variable>(Target)) { | 462 if (const auto Var = llvm::dyn_cast<Variable>(Target)) { |
| 556 if (Var->hasReg()) { | 463 if (Var->hasReg()) { |
| 557 Asm->call(RegX8632::getEncodedGPR(Var->getRegNum())); | 464 Asm->call(RegX8632::getEncodedGPR(Var->getRegNum())); |
| 558 } else { | 465 } else { |
| 559 Asm->call(static_cast<TargetX8632 *>(Func->getTarget()) | 466 Asm->call(static_cast<TargetX8632 *>(Func->getTarget()) |
| 560 ->stackVarToAsmOperand(Var)); | 467 ->stackVarToAsmOperand(Var)); |
| 561 } | 468 } |
| 562 } else if (const auto Mem = llvm::dyn_cast<OperandX8632Mem>(Target)) { | 469 } else if (const auto Mem = llvm::dyn_cast<OperandX8632Mem>(Target)) { |
| 563 assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); | 470 assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); |
| 564 Asm->call(Mem->toAsmAddress(Asm)); | 471 Asm->call(Mem->toAsmAddress(Asm)); |
| 565 } else if (const auto CR = llvm::dyn_cast<ConstantRelocatable>(Target)) { | 472 } else if (const auto CR = llvm::dyn_cast<ConstantRelocatable>(Target)) { |
| 566 assert(CR->getOffset() == 0 && "We only support calling a function"); | 473 assert(CR->getOffset() == 0 && "We only support calling a function"); |
| 567 Asm->call(CR); | 474 Asm->call(CR); |
| 568 NeedsFallback = true; | |
| 569 } else if (const auto Imm = llvm::dyn_cast<ConstantInteger32>(Target)) { | 475 } else if (const auto Imm = llvm::dyn_cast<ConstantInteger32>(Target)) { |
| 570 // NaCl trampoline calls refer to an address within the sandbox directly. | 476 // NaCl trampoline calls refer to an address within the sandbox directly. |
| 571 // This is usually only needed for non-IRT builds and otherwise not | 477 // This is usually only needed for non-IRT builds and otherwise not |
| 572 // very portable or stable. For this, we would use the 0xE8 opcode | 478 // very portable or stable. For this, we would use the 0xE8 opcode |
| 573 // (relative version of call) and there should be a PC32 reloc too. | 479 // (relative version of call) and there should be a PC32 reloc too. |
| 574 // The PC32 reloc will have symbol index 0, and the absolute address | 480 // The PC32 reloc will have symbol index 0, and the absolute address |
| 575 // would be encoded as an offset relative to the next instruction. | 481 // would be encoded as an offset relative to the next instruction. |
| 576 // TODO(jvoung): Do we need to support this? | 482 // TODO(jvoung): Do we need to support this? |
| 577 (void)Imm; | 483 (void)Imm; |
| 578 llvm_unreachable("Unexpected call to absolute address"); | 484 llvm_unreachable("Unexpected call to absolute address"); |
| 579 } else { | 485 } else { |
| 580 llvm_unreachable("Unexpected operand type"); | 486 llvm_unreachable("Unexpected operand type"); |
| 581 } | 487 } |
| 582 if (NeedsFallback) { | |
| 583 // TODO(jvoung): The ".long sym" hack doesn't work, since we need | |
| 584 // a pc-rel relocation and not an absolute relocation. | |
| 585 // | |
| 586 // Still, we have at least filled the assembler buffer so that the | |
| 587 // instruction sizes/positions are correct for jumps. | |
| 588 // For now, fall back to the regular .s emission, after filling the buffer. | |
| 589 emit(Func); | |
| 590 Func->getContext()->getStrEmit() << "\n"; | |
| 591 } else { | |
| 592 emitIASBytes(Func, Asm, StartPosition); | |
| 593 } | |
| 594 Func->getTarget()->resetStackAdjustment(); | 488 Func->getTarget()->resetStackAdjustment(); |
| 595 } | 489 } |
| 596 | 490 |
| 597 void InstX8632Call::dump(const Cfg *Func) const { | 491 void InstX8632Call::dump(const Cfg *Func) const { |
| 598 Ostream &Str = Func->getContext()->getStrDump(); | 492 Ostream &Str = Func->getContext()->getStrDump(); |
| 599 if (getDest()) { | 493 if (getDest()) { |
| 600 dumpDest(Func); | 494 dumpDest(Func); |
| 601 Str << " = "; | 495 Str << " = "; |
| 602 } | 496 } |
| 603 Str << "call "; | 497 Str << "call "; |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 621 Str << "%cl"; | 515 Str << "%cl"; |
| 622 else | 516 else |
| 623 Src1->emit(Func); | 517 Src1->emit(Func); |
| 624 Str << ", "; | 518 Str << ", "; |
| 625 Dest->emit(Func); | 519 Dest->emit(Func); |
| 626 } | 520 } |
| 627 | 521 |
| 628 void emitIASOpTyGPR(const Cfg *Func, Type Ty, const Operand *Op, | 522 void emitIASOpTyGPR(const Cfg *Func, Type Ty, const Operand *Op, |
| 629 const x86::AssemblerX86::GPREmitterOneOp &Emitter) { | 523 const x86::AssemblerX86::GPREmitterOneOp &Emitter) { |
| 630 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 524 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 631 intptr_t StartPosition = Asm->GetPosition(); | |
| 632 if (const auto Var = llvm::dyn_cast<Variable>(Op)) { | 525 if (const auto Var = llvm::dyn_cast<Variable>(Op)) { |
| 633 if (Var->hasReg()) { | 526 if (Var->hasReg()) { |
| 634 // We cheat a little and use GPRRegister even for byte operations. | 527 // We cheat a little and use GPRRegister even for byte operations. |
| 635 RegX8632::GPRRegister VarReg = | 528 RegX8632::GPRRegister VarReg = |
| 636 RegX8632::getEncodedByteRegOrGPR(Ty, Var->getRegNum()); | 529 RegX8632::getEncodedByteRegOrGPR(Ty, Var->getRegNum()); |
| 637 (Asm->*(Emitter.Reg))(Ty, VarReg); | 530 (Asm->*(Emitter.Reg))(Ty, VarReg); |
| 638 } else { | 531 } else { |
| 639 x86::Address StackAddr(static_cast<TargetX8632 *>(Func->getTarget()) | 532 x86::Address StackAddr(static_cast<TargetX8632 *>(Func->getTarget()) |
| 640 ->stackVarToAsmOperand(Var)); | 533 ->stackVarToAsmOperand(Var)); |
| 641 (Asm->*(Emitter.Addr))(Ty, StackAddr); | 534 (Asm->*(Emitter.Addr))(Ty, StackAddr); |
| 642 } | 535 } |
| 643 } else if (const auto Mem = llvm::dyn_cast<OperandX8632Mem>(Op)) { | 536 } else if (const auto Mem = llvm::dyn_cast<OperandX8632Mem>(Op)) { |
| 644 Mem->emitSegmentOverride(Asm); | 537 Mem->emitSegmentOverride(Asm); |
| 645 (Asm->*(Emitter.Addr))(Ty, Mem->toAsmAddress(Asm)); | 538 (Asm->*(Emitter.Addr))(Ty, Mem->toAsmAddress(Asm)); |
| 646 } else { | 539 } else { |
| 647 llvm_unreachable("Unexpected operand type"); | 540 llvm_unreachable("Unexpected operand type"); |
| 648 } | 541 } |
| 649 emitIASBytes(Func, Asm, StartPosition); | |
| 650 } | 542 } |
| 651 | 543 |
| 652 template <bool VarCanBeByte, bool SrcCanBeByte> | 544 template <bool VarCanBeByte, bool SrcCanBeByte> |
| 653 void emitIASRegOpTyGPR(const Cfg *Func, Type Ty, const Variable *Var, | 545 void emitIASRegOpTyGPR(const Cfg *Func, Type Ty, const Variable *Var, |
| 654 const Operand *Src, | 546 const Operand *Src, |
| 655 const x86::AssemblerX86::GPREmitterRegOp &Emitter) { | 547 const x86::AssemblerX86::GPREmitterRegOp &Emitter) { |
| 656 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 548 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 657 intptr_t StartPosition = Asm->GetPosition(); | |
| 658 assert(Var->hasReg()); | 549 assert(Var->hasReg()); |
| 659 // We cheat a little and use GPRRegister even for byte operations. | 550 // We cheat a little and use GPRRegister even for byte operations. |
| 660 RegX8632::GPRRegister VarReg = | 551 RegX8632::GPRRegister VarReg = |
| 661 VarCanBeByte ? RegX8632::getEncodedByteRegOrGPR(Ty, Var->getRegNum()) | 552 VarCanBeByte ? RegX8632::getEncodedByteRegOrGPR(Ty, Var->getRegNum()) |
| 662 : RegX8632::getEncodedGPR(Var->getRegNum()); | 553 : RegX8632::getEncodedGPR(Var->getRegNum()); |
| 663 if (const auto SrcVar = llvm::dyn_cast<Variable>(Src)) { | 554 if (const auto SrcVar = llvm::dyn_cast<Variable>(Src)) { |
| 664 if (SrcVar->hasReg()) { | 555 if (SrcVar->hasReg()) { |
| 665 RegX8632::GPRRegister SrcReg = | 556 RegX8632::GPRRegister SrcReg = |
| 666 SrcCanBeByte | 557 SrcCanBeByte |
| 667 ? RegX8632::getEncodedByteRegOrGPR(Ty, SrcVar->getRegNum()) | 558 ? RegX8632::getEncodedByteRegOrGPR(Ty, SrcVar->getRegNum()) |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 679 (Asm->*(Emitter.GPRImm))(Ty, VarReg, x86::Immediate(Imm->getValue())); | 570 (Asm->*(Emitter.GPRImm))(Ty, VarReg, x86::Immediate(Imm->getValue())); |
| 680 } else if (const auto Reloc = llvm::dyn_cast<ConstantRelocatable>(Src)) { | 571 } else if (const auto Reloc = llvm::dyn_cast<ConstantRelocatable>(Src)) { |
| 681 AssemblerFixup *Fixup = | 572 AssemblerFixup *Fixup = |
| 682 x86::DisplacementRelocation::create(Asm, FK_Abs_4, Reloc); | 573 x86::DisplacementRelocation::create(Asm, FK_Abs_4, Reloc); |
| 683 (Asm->*(Emitter.GPRImm))(Ty, VarReg, x86::Immediate(Fixup)); | 574 (Asm->*(Emitter.GPRImm))(Ty, VarReg, x86::Immediate(Fixup)); |
| 684 } else if (const auto Split = llvm::dyn_cast<VariableSplit>(Src)) { | 575 } else if (const auto Split = llvm::dyn_cast<VariableSplit>(Src)) { |
| 685 (Asm->*(Emitter.GPRAddr))(Ty, VarReg, Split->toAsmAddress(Func)); | 576 (Asm->*(Emitter.GPRAddr))(Ty, VarReg, Split->toAsmAddress(Func)); |
| 686 } else { | 577 } else { |
| 687 llvm_unreachable("Unexpected operand type"); | 578 llvm_unreachable("Unexpected operand type"); |
| 688 } | 579 } |
| 689 emitIASBytes(Func, Asm, StartPosition); | |
| 690 } | 580 } |
| 691 | 581 |
| 692 void emitIASAddrOpTyGPR(const Cfg *Func, Type Ty, const x86::Address &Addr, | 582 void emitIASAddrOpTyGPR(const Cfg *Func, Type Ty, const x86::Address &Addr, |
| 693 const Operand *Src, | 583 const Operand *Src, |
| 694 const x86::AssemblerX86::GPREmitterAddrOp &Emitter) { | 584 const x86::AssemblerX86::GPREmitterAddrOp &Emitter) { |
| 695 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 585 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 696 intptr_t StartPosition = Asm->GetPosition(); | |
| 697 // Src can only be Reg or Immediate. | 586 // Src can only be Reg or Immediate. |
| 698 if (const auto SrcVar = llvm::dyn_cast<Variable>(Src)) { | 587 if (const auto SrcVar = llvm::dyn_cast<Variable>(Src)) { |
| 699 assert(SrcVar->hasReg()); | 588 assert(SrcVar->hasReg()); |
| 700 RegX8632::GPRRegister SrcReg = | 589 RegX8632::GPRRegister SrcReg = |
| 701 RegX8632::getEncodedByteRegOrGPR(Ty, SrcVar->getRegNum()); | 590 RegX8632::getEncodedByteRegOrGPR(Ty, SrcVar->getRegNum()); |
| 702 (Asm->*(Emitter.AddrGPR))(Ty, Addr, SrcReg); | 591 (Asm->*(Emitter.AddrGPR))(Ty, Addr, SrcReg); |
| 703 } else if (const auto Imm = llvm::dyn_cast<ConstantInteger32>(Src)) { | 592 } else if (const auto Imm = llvm::dyn_cast<ConstantInteger32>(Src)) { |
| 704 (Asm->*(Emitter.AddrImm))(Ty, Addr, x86::Immediate(Imm->getValue())); | 593 (Asm->*(Emitter.AddrImm))(Ty, Addr, x86::Immediate(Imm->getValue())); |
| 705 } else if (const auto Reloc = llvm::dyn_cast<ConstantRelocatable>(Src)) { | 594 } else if (const auto Reloc = llvm::dyn_cast<ConstantRelocatable>(Src)) { |
| 706 AssemblerFixup *Fixup = | 595 AssemblerFixup *Fixup = |
| 707 x86::DisplacementRelocation::create(Asm, FK_Abs_4, Reloc); | 596 x86::DisplacementRelocation::create(Asm, FK_Abs_4, Reloc); |
| 708 (Asm->*(Emitter.AddrImm))(Ty, Addr, x86::Immediate(Fixup)); | 597 (Asm->*(Emitter.AddrImm))(Ty, Addr, x86::Immediate(Fixup)); |
| 709 } else { | 598 } else { |
| 710 llvm_unreachable("Unexpected operand type"); | 599 llvm_unreachable("Unexpected operand type"); |
| 711 } | 600 } |
| 712 emitIASBytes(Func, Asm, StartPosition); | |
| 713 } | 601 } |
| 714 | 602 |
| 715 void emitIASAsAddrOpTyGPR(const Cfg *Func, Type Ty, const Operand *Op0, | 603 void emitIASAsAddrOpTyGPR(const Cfg *Func, Type Ty, const Operand *Op0, |
| 716 const Operand *Op1, | 604 const Operand *Op1, |
| 717 const x86::AssemblerX86::GPREmitterAddrOp &Emitter) { | 605 const x86::AssemblerX86::GPREmitterAddrOp &Emitter) { |
| 718 if (const auto Op0Var = llvm::dyn_cast<Variable>(Op0)) { | 606 if (const auto Op0Var = llvm::dyn_cast<Variable>(Op0)) { |
| 719 assert(!Op0Var->hasReg()); | 607 assert(!Op0Var->hasReg()); |
| 720 x86::Address StackAddr(static_cast<TargetX8632 *>(Func->getTarget()) | 608 x86::Address StackAddr(static_cast<TargetX8632 *>(Func->getTarget()) |
| 721 ->stackVarToAsmOperand(Op0Var)); | 609 ->stackVarToAsmOperand(Op0Var)); |
| 722 emitIASAddrOpTyGPR(Func, Ty, StackAddr, Op1, Emitter); | 610 emitIASAddrOpTyGPR(Func, Ty, StackAddr, Op1, Emitter); |
| 723 } else if (const auto Op0Mem = llvm::dyn_cast<OperandX8632Mem>(Op0)) { | 611 } else if (const auto Op0Mem = llvm::dyn_cast<OperandX8632Mem>(Op0)) { |
| 724 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 612 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 725 Op0Mem->emitSegmentOverride(Asm); | 613 Op0Mem->emitSegmentOverride(Asm); |
| 726 emitIASAddrOpTyGPR(Func, Ty, Op0Mem->toAsmAddress(Asm), Op1, Emitter); | 614 emitIASAddrOpTyGPR(Func, Ty, Op0Mem->toAsmAddress(Asm), Op1, Emitter); |
| 727 } else if (const auto Split = llvm::dyn_cast<VariableSplit>(Op0)) { | 615 } else if (const auto Split = llvm::dyn_cast<VariableSplit>(Op0)) { |
| 728 emitIASAddrOpTyGPR(Func, Ty, Split->toAsmAddress(Func), Op1, Emitter); | 616 emitIASAddrOpTyGPR(Func, Ty, Split->toAsmAddress(Func), Op1, Emitter); |
| 729 } else { | 617 } else { |
| 730 llvm_unreachable("Unexpected operand type"); | 618 llvm_unreachable("Unexpected operand type"); |
| 731 } | 619 } |
| 732 } | 620 } |
| 733 | 621 |
| 734 void emitIASGPRShift(const Cfg *Func, Type Ty, const Variable *Var, | 622 void emitIASGPRShift(const Cfg *Func, Type Ty, const Variable *Var, |
| 735 const Operand *Src, | 623 const Operand *Src, |
| 736 const x86::AssemblerX86::GPREmitterShiftOp &Emitter) { | 624 const x86::AssemblerX86::GPREmitterShiftOp &Emitter) { |
| 737 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 625 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 738 intptr_t StartPosition = Asm->GetPosition(); | |
| 739 // Technically, the Dest Var can be mem as well, but we only use Reg. | 626 // Technically, the Dest Var can be mem as well, but we only use Reg. |
| 740 // We can extend this to check Dest if we decide to use that form. | 627 // We can extend this to check Dest if we decide to use that form. |
| 741 assert(Var->hasReg()); | 628 assert(Var->hasReg()); |
| 742 // We cheat a little and use GPRRegister even for byte operations. | 629 // We cheat a little and use GPRRegister even for byte operations. |
| 743 RegX8632::GPRRegister VarReg = | 630 RegX8632::GPRRegister VarReg = |
| 744 RegX8632::getEncodedByteRegOrGPR(Ty, Var->getRegNum()); | 631 RegX8632::getEncodedByteRegOrGPR(Ty, Var->getRegNum()); |
| 745 // Src must be reg == ECX or an Imm8. | 632 // Src must be reg == ECX or an Imm8. |
| 746 // This is asserted by the assembler. | 633 // This is asserted by the assembler. |
| 747 if (const auto SrcVar = llvm::dyn_cast<Variable>(Src)) { | 634 if (const auto SrcVar = llvm::dyn_cast<Variable>(Src)) { |
| 748 assert(SrcVar->hasReg()); | 635 assert(SrcVar->hasReg()); |
| 749 RegX8632::GPRRegister SrcReg = | 636 RegX8632::GPRRegister SrcReg = |
| 750 RegX8632::getEncodedByteRegOrGPR(Ty, SrcVar->getRegNum()); | 637 RegX8632::getEncodedByteRegOrGPR(Ty, SrcVar->getRegNum()); |
| 751 (Asm->*(Emitter.GPRGPR))(Ty, VarReg, SrcReg); | 638 (Asm->*(Emitter.GPRGPR))(Ty, VarReg, SrcReg); |
| 752 } else if (const auto Imm = llvm::dyn_cast<ConstantInteger32>(Src)) { | 639 } else if (const auto Imm = llvm::dyn_cast<ConstantInteger32>(Src)) { |
| 753 (Asm->*(Emitter.GPRImm))(Ty, VarReg, x86::Immediate(Imm->getValue())); | 640 (Asm->*(Emitter.GPRImm))(Ty, VarReg, x86::Immediate(Imm->getValue())); |
| 754 } else { | 641 } else { |
| 755 llvm_unreachable("Unexpected operand type"); | 642 llvm_unreachable("Unexpected operand type"); |
| 756 } | 643 } |
| 757 emitIASBytes(Func, Asm, StartPosition); | |
| 758 } | 644 } |
| 759 | 645 |
| 760 void emitIASGPRShiftDouble(const Cfg *Func, const Variable *Dest, | 646 void emitIASGPRShiftDouble(const Cfg *Func, const Variable *Dest, |
| 761 const Operand *Src1Op, const Operand *Src2Op, | 647 const Operand *Src1Op, const Operand *Src2Op, |
| 762 const x86::AssemblerX86::GPREmitterShiftD &Emitter) { | 648 const x86::AssemblerX86::GPREmitterShiftD &Emitter) { |
| 763 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 649 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 764 intptr_t StartPosition = Asm->GetPosition(); | |
| 765 // Dest can be reg or mem, but we only use the reg variant. | 650 // Dest can be reg or mem, but we only use the reg variant. |
| 766 assert(Dest->hasReg()); | 651 assert(Dest->hasReg()); |
| 767 RegX8632::GPRRegister DestReg = RegX8632::getEncodedGPR(Dest->getRegNum()); | 652 RegX8632::GPRRegister DestReg = RegX8632::getEncodedGPR(Dest->getRegNum()); |
| 768 // SrcVar1 must be reg. | 653 // SrcVar1 must be reg. |
| 769 const auto SrcVar1 = llvm::cast<Variable>(Src1Op); | 654 const auto SrcVar1 = llvm::cast<Variable>(Src1Op); |
| 770 assert(SrcVar1->hasReg()); | 655 assert(SrcVar1->hasReg()); |
| 771 RegX8632::GPRRegister SrcReg = RegX8632::getEncodedGPR(SrcVar1->getRegNum()); | 656 RegX8632::GPRRegister SrcReg = RegX8632::getEncodedGPR(SrcVar1->getRegNum()); |
| 772 Type Ty = SrcVar1->getType(); | 657 Type Ty = SrcVar1->getType(); |
| 773 // Src2 can be the implicit CL register or an immediate. | 658 // Src2 can be the implicit CL register or an immediate. |
| 774 if (const auto Imm = llvm::dyn_cast<ConstantInteger32>(Src2Op)) { | 659 if (const auto Imm = llvm::dyn_cast<ConstantInteger32>(Src2Op)) { |
| 775 (Asm->*(Emitter.GPRGPRImm))(Ty, DestReg, SrcReg, | 660 (Asm->*(Emitter.GPRGPRImm))(Ty, DestReg, SrcReg, |
| 776 x86::Immediate(Imm->getValue())); | 661 x86::Immediate(Imm->getValue())); |
| 777 } else { | 662 } else { |
| 778 assert(llvm::cast<Variable>(Src2Op)->getRegNum() == RegX8632::Reg_ecx); | 663 assert(llvm::cast<Variable>(Src2Op)->getRegNum() == RegX8632::Reg_ecx); |
| 779 (Asm->*(Emitter.GPRGPR))(Ty, DestReg, SrcReg); | 664 (Asm->*(Emitter.GPRGPR))(Ty, DestReg, SrcReg); |
| 780 } | 665 } |
| 781 emitIASBytes(Func, Asm, StartPosition); | |
| 782 } | 666 } |
| 783 | 667 |
| 784 void emitIASXmmShift(const Cfg *Func, Type Ty, const Variable *Var, | 668 void emitIASXmmShift(const Cfg *Func, Type Ty, const Variable *Var, |
| 785 const Operand *Src, | 669 const Operand *Src, |
| 786 const x86::AssemblerX86::XmmEmitterShiftOp &Emitter) { | 670 const x86::AssemblerX86::XmmEmitterShiftOp &Emitter) { |
| 787 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 671 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 788 intptr_t StartPosition = Asm->GetPosition(); | |
| 789 assert(Var->hasReg()); | 672 assert(Var->hasReg()); |
| 790 RegX8632::XmmRegister VarReg = RegX8632::getEncodedXmm(Var->getRegNum()); | 673 RegX8632::XmmRegister VarReg = RegX8632::getEncodedXmm(Var->getRegNum()); |
| 791 if (const auto SrcVar = llvm::dyn_cast<Variable>(Src)) { | 674 if (const auto SrcVar = llvm::dyn_cast<Variable>(Src)) { |
| 792 if (SrcVar->hasReg()) { | 675 if (SrcVar->hasReg()) { |
| 793 RegX8632::XmmRegister SrcReg = | 676 RegX8632::XmmRegister SrcReg = |
| 794 RegX8632::getEncodedXmm(SrcVar->getRegNum()); | 677 RegX8632::getEncodedXmm(SrcVar->getRegNum()); |
| 795 (Asm->*(Emitter.XmmXmm))(Ty, VarReg, SrcReg); | 678 (Asm->*(Emitter.XmmXmm))(Ty, VarReg, SrcReg); |
| 796 } else { | 679 } else { |
| 797 x86::Address SrcStackAddr = static_cast<TargetX8632 *>(Func->getTarget()) | 680 x86::Address SrcStackAddr = static_cast<TargetX8632 *>(Func->getTarget()) |
| 798 ->stackVarToAsmOperand(SrcVar); | 681 ->stackVarToAsmOperand(SrcVar); |
| 799 (Asm->*(Emitter.XmmAddr))(Ty, VarReg, SrcStackAddr); | 682 (Asm->*(Emitter.XmmAddr))(Ty, VarReg, SrcStackAddr); |
| 800 } | 683 } |
| 801 } else if (const auto Mem = llvm::dyn_cast<OperandX8632Mem>(Src)) { | 684 } else if (const auto Mem = llvm::dyn_cast<OperandX8632Mem>(Src)) { |
| 802 assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); | 685 assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); |
| 803 (Asm->*(Emitter.XmmAddr))(Ty, VarReg, Mem->toAsmAddress(Asm)); | 686 (Asm->*(Emitter.XmmAddr))(Ty, VarReg, Mem->toAsmAddress(Asm)); |
| 804 } else if (const auto Imm = llvm::dyn_cast<ConstantInteger32>(Src)) { | 687 } else if (const auto Imm = llvm::dyn_cast<ConstantInteger32>(Src)) { |
| 805 (Asm->*(Emitter.XmmImm))(Ty, VarReg, x86::Immediate(Imm->getValue())); | 688 (Asm->*(Emitter.XmmImm))(Ty, VarReg, x86::Immediate(Imm->getValue())); |
| 806 } else { | 689 } else { |
| 807 llvm_unreachable("Unexpected operand type"); | 690 llvm_unreachable("Unexpected operand type"); |
| 808 } | 691 } |
| 809 emitIASBytes(Func, Asm, StartPosition); | |
| 810 } | 692 } |
| 811 | 693 |
| 812 void emitIASRegOpTyXMM(const Cfg *Func, Type Ty, const Variable *Var, | 694 void emitIASRegOpTyXMM(const Cfg *Func, Type Ty, const Variable *Var, |
| 813 const Operand *Src, | 695 const Operand *Src, |
| 814 const x86::AssemblerX86::XmmEmitterRegOp &Emitter) { | 696 const x86::AssemblerX86::XmmEmitterRegOp &Emitter) { |
| 815 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 697 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 816 intptr_t StartPosition = Asm->GetPosition(); | |
| 817 assert(Var->hasReg()); | 698 assert(Var->hasReg()); |
| 818 RegX8632::XmmRegister VarReg = RegX8632::getEncodedXmm(Var->getRegNum()); | 699 RegX8632::XmmRegister VarReg = RegX8632::getEncodedXmm(Var->getRegNum()); |
| 819 if (const auto SrcVar = llvm::dyn_cast<Variable>(Src)) { | 700 if (const auto SrcVar = llvm::dyn_cast<Variable>(Src)) { |
| 820 if (SrcVar->hasReg()) { | 701 if (SrcVar->hasReg()) { |
| 821 RegX8632::XmmRegister SrcReg = | 702 RegX8632::XmmRegister SrcReg = |
| 822 RegX8632::getEncodedXmm(SrcVar->getRegNum()); | 703 RegX8632::getEncodedXmm(SrcVar->getRegNum()); |
| 823 (Asm->*(Emitter.XmmXmm))(Ty, VarReg, SrcReg); | 704 (Asm->*(Emitter.XmmXmm))(Ty, VarReg, SrcReg); |
| 824 } else { | 705 } else { |
| 825 x86::Address SrcStackAddr = static_cast<TargetX8632 *>(Func->getTarget()) | 706 x86::Address SrcStackAddr = static_cast<TargetX8632 *>(Func->getTarget()) |
| 826 ->stackVarToAsmOperand(SrcVar); | 707 ->stackVarToAsmOperand(SrcVar); |
| 827 (Asm->*(Emitter.XmmAddr))(Ty, VarReg, SrcStackAddr); | 708 (Asm->*(Emitter.XmmAddr))(Ty, VarReg, SrcStackAddr); |
| 828 } | 709 } |
| 829 } else if (const auto Mem = llvm::dyn_cast<OperandX8632Mem>(Src)) { | 710 } else if (const auto Mem = llvm::dyn_cast<OperandX8632Mem>(Src)) { |
| 830 assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); | 711 assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); |
| 831 (Asm->*(Emitter.XmmAddr))(Ty, VarReg, Mem->toAsmAddress(Asm)); | 712 (Asm->*(Emitter.XmmAddr))(Ty, VarReg, Mem->toAsmAddress(Asm)); |
| 832 } else if (const auto Imm = llvm::dyn_cast<Constant>(Src)) { | 713 } else if (const auto Imm = llvm::dyn_cast<Constant>(Src)) { |
| 833 (Asm->*(Emitter.XmmAddr))( | 714 (Asm->*(Emitter.XmmAddr))( |
| 834 Ty, VarReg, x86::Address::ofConstPool(Func->getContext(), Asm, Imm)); | 715 Ty, VarReg, x86::Address::ofConstPool(Func->getContext(), Asm, Imm)); |
| 835 } else { | 716 } else { |
| 836 llvm_unreachable("Unexpected operand type"); | 717 llvm_unreachable("Unexpected operand type"); |
| 837 } | 718 } |
| 838 emitIASBytes(Func, Asm, StartPosition); | |
| 839 } | 719 } |
| 840 | 720 |
| 841 template <typename DReg_t, typename SReg_t, DReg_t (*destEnc)(int32_t), | 721 template <typename DReg_t, typename SReg_t, DReg_t (*destEnc)(int32_t), |
| 842 SReg_t (*srcEnc)(int32_t)> | 722 SReg_t (*srcEnc)(int32_t)> |
| 843 void emitIASCastRegOp( | 723 void emitIASCastRegOp( |
| 844 const Cfg *Func, Type DispatchTy, const Variable *Dest, const Operand *Src, | 724 const Cfg *Func, Type DispatchTy, const Variable *Dest, const Operand *Src, |
| 845 const x86::AssemblerX86::CastEmitterRegOp<DReg_t, SReg_t> Emitter) { | 725 const x86::AssemblerX86::CastEmitterRegOp<DReg_t, SReg_t> Emitter) { |
| 846 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 726 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 847 intptr_t StartPosition = Asm->GetPosition(); | |
| 848 assert(Dest->hasReg()); | 727 assert(Dest->hasReg()); |
| 849 DReg_t DestReg = destEnc(Dest->getRegNum()); | 728 DReg_t DestReg = destEnc(Dest->getRegNum()); |
| 850 if (const auto SrcVar = llvm::dyn_cast<Variable>(Src)) { | 729 if (const auto SrcVar = llvm::dyn_cast<Variable>(Src)) { |
| 851 if (SrcVar->hasReg()) { | 730 if (SrcVar->hasReg()) { |
| 852 SReg_t SrcReg = srcEnc(SrcVar->getRegNum()); | 731 SReg_t SrcReg = srcEnc(SrcVar->getRegNum()); |
| 853 (Asm->*(Emitter.RegReg))(DispatchTy, DestReg, SrcReg); | 732 (Asm->*(Emitter.RegReg))(DispatchTy, DestReg, SrcReg); |
| 854 } else { | 733 } else { |
| 855 x86::Address SrcStackAddr = static_cast<TargetX8632 *>(Func->getTarget()) | 734 x86::Address SrcStackAddr = static_cast<TargetX8632 *>(Func->getTarget()) |
| 856 ->stackVarToAsmOperand(SrcVar); | 735 ->stackVarToAsmOperand(SrcVar); |
| 857 (Asm->*(Emitter.RegAddr))(DispatchTy, DestReg, SrcStackAddr); | 736 (Asm->*(Emitter.RegAddr))(DispatchTy, DestReg, SrcStackAddr); |
| 858 } | 737 } |
| 859 } else if (const auto Mem = llvm::dyn_cast<OperandX8632Mem>(Src)) { | 738 } else if (const auto Mem = llvm::dyn_cast<OperandX8632Mem>(Src)) { |
| 860 Mem->emitSegmentOverride(Asm); | 739 Mem->emitSegmentOverride(Asm); |
| 861 (Asm->*(Emitter.RegAddr))(DispatchTy, DestReg, Mem->toAsmAddress(Asm)); | 740 (Asm->*(Emitter.RegAddr))(DispatchTy, DestReg, Mem->toAsmAddress(Asm)); |
| 862 } else { | 741 } else { |
| 863 llvm_unreachable("Unexpected operand type"); | 742 llvm_unreachable("Unexpected operand type"); |
| 864 } | 743 } |
| 865 emitIASBytes(Func, Asm, StartPosition); | |
| 866 } | 744 } |
| 867 | 745 |
| 868 template <typename DReg_t, typename SReg_t, DReg_t (*destEnc)(int32_t), | 746 template <typename DReg_t, typename SReg_t, DReg_t (*destEnc)(int32_t), |
| 869 SReg_t (*srcEnc)(int32_t)> | 747 SReg_t (*srcEnc)(int32_t)> |
| 870 void emitIASThreeOpImmOps( | 748 void emitIASThreeOpImmOps( |
| 871 const Cfg *Func, Type DispatchTy, const Variable *Dest, const Operand *Src0, | 749 const Cfg *Func, Type DispatchTy, const Variable *Dest, const Operand *Src0, |
| 872 const Operand *Src1, | 750 const Operand *Src1, |
| 873 const x86::AssemblerX86::ThreeOpImmEmitter<DReg_t, SReg_t> Emitter) { | 751 const x86::AssemblerX86::ThreeOpImmEmitter<DReg_t, SReg_t> Emitter) { |
| 874 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 752 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 875 intptr_t StartPosition = Asm->GetPosition(); | |
| 876 // This only handles Dest being a register, and Src1 being an immediate. | 753 // This only handles Dest being a register, and Src1 being an immediate. |
| 877 assert(Dest->hasReg()); | 754 assert(Dest->hasReg()); |
| 878 DReg_t DestReg = destEnc(Dest->getRegNum()); | 755 DReg_t DestReg = destEnc(Dest->getRegNum()); |
| 879 x86::Immediate Imm(llvm::cast<ConstantInteger32>(Src1)->getValue()); | 756 x86::Immediate Imm(llvm::cast<ConstantInteger32>(Src1)->getValue()); |
| 880 if (const auto SrcVar = llvm::dyn_cast<Variable>(Src0)) { | 757 if (const auto SrcVar = llvm::dyn_cast<Variable>(Src0)) { |
| 881 if (SrcVar->hasReg()) { | 758 if (SrcVar->hasReg()) { |
| 882 SReg_t SrcReg = srcEnc(SrcVar->getRegNum()); | 759 SReg_t SrcReg = srcEnc(SrcVar->getRegNum()); |
| 883 (Asm->*(Emitter.RegRegImm))(DispatchTy, DestReg, SrcReg, Imm); | 760 (Asm->*(Emitter.RegRegImm))(DispatchTy, DestReg, SrcReg, Imm); |
| 884 } else { | 761 } else { |
| 885 x86::Address SrcStackAddr = static_cast<TargetX8632 *>(Func->getTarget()) | 762 x86::Address SrcStackAddr = static_cast<TargetX8632 *>(Func->getTarget()) |
| 886 ->stackVarToAsmOperand(SrcVar); | 763 ->stackVarToAsmOperand(SrcVar); |
| 887 (Asm->*(Emitter.RegAddrImm))(DispatchTy, DestReg, SrcStackAddr, Imm); | 764 (Asm->*(Emitter.RegAddrImm))(DispatchTy, DestReg, SrcStackAddr, Imm); |
| 888 } | 765 } |
| 889 } else if (const auto Mem = llvm::dyn_cast<OperandX8632Mem>(Src0)) { | 766 } else if (const auto Mem = llvm::dyn_cast<OperandX8632Mem>(Src0)) { |
| 890 Mem->emitSegmentOverride(Asm); | 767 Mem->emitSegmentOverride(Asm); |
| 891 (Asm->*(Emitter.RegAddrImm))(DispatchTy, DestReg, Mem->toAsmAddress(Asm), | 768 (Asm->*(Emitter.RegAddrImm))(DispatchTy, DestReg, Mem->toAsmAddress(Asm), |
| 892 Imm); | 769 Imm); |
| 893 } else { | 770 } else { |
| 894 llvm_unreachable("Unexpected operand type"); | 771 llvm_unreachable("Unexpected operand type"); |
| 895 } | 772 } |
| 896 emitIASBytes(Func, Asm, StartPosition); | |
| 897 } | 773 } |
| 898 | 774 |
| 899 void emitIASMovlikeXMM(const Cfg *Func, const Variable *Dest, | 775 void emitIASMovlikeXMM(const Cfg *Func, const Variable *Dest, |
| 900 const Operand *Src, | 776 const Operand *Src, |
| 901 const x86::AssemblerX86::XmmEmitterMovOps Emitter) { | 777 const x86::AssemblerX86::XmmEmitterMovOps Emitter) { |
| 902 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 778 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 903 intptr_t StartPosition = Asm->GetPosition(); | |
| 904 if (Dest->hasReg()) { | 779 if (Dest->hasReg()) { |
| 905 RegX8632::XmmRegister DestReg = RegX8632::getEncodedXmm(Dest->getRegNum()); | 780 RegX8632::XmmRegister DestReg = RegX8632::getEncodedXmm(Dest->getRegNum()); |
| 906 if (const auto SrcVar = llvm::dyn_cast<Variable>(Src)) { | 781 if (const auto SrcVar = llvm::dyn_cast<Variable>(Src)) { |
| 907 if (SrcVar->hasReg()) { | 782 if (SrcVar->hasReg()) { |
| 908 (Asm->*(Emitter.XmmXmm))(DestReg, | 783 (Asm->*(Emitter.XmmXmm))(DestReg, |
| 909 RegX8632::getEncodedXmm(SrcVar->getRegNum())); | 784 RegX8632::getEncodedXmm(SrcVar->getRegNum())); |
| 910 } else { | 785 } else { |
| 911 x86::Address StackAddr(static_cast<TargetX8632 *>(Func->getTarget()) | 786 x86::Address StackAddr(static_cast<TargetX8632 *>(Func->getTarget()) |
| 912 ->stackVarToAsmOperand(SrcVar)); | 787 ->stackVarToAsmOperand(SrcVar)); |
| 913 (Asm->*(Emitter.XmmAddr))(DestReg, StackAddr); | 788 (Asm->*(Emitter.XmmAddr))(DestReg, StackAddr); |
| 914 } | 789 } |
| 915 } else if (const auto SrcMem = llvm::dyn_cast<OperandX8632Mem>(Src)) { | 790 } else if (const auto SrcMem = llvm::dyn_cast<OperandX8632Mem>(Src)) { |
| 916 assert(SrcMem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); | 791 assert(SrcMem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); |
| 917 (Asm->*(Emitter.XmmAddr))(DestReg, SrcMem->toAsmAddress(Asm)); | 792 (Asm->*(Emitter.XmmAddr))(DestReg, SrcMem->toAsmAddress(Asm)); |
| 918 } else { | 793 } else { |
| 919 llvm_unreachable("Unexpected operand type"); | 794 llvm_unreachable("Unexpected operand type"); |
| 920 } | 795 } |
| 921 } else { | 796 } else { |
| 922 x86::Address StackAddr(static_cast<TargetX8632 *>(Func->getTarget()) | 797 x86::Address StackAddr(static_cast<TargetX8632 *>(Func->getTarget()) |
| 923 ->stackVarToAsmOperand(Dest)); | 798 ->stackVarToAsmOperand(Dest)); |
| 924 // Src must be a register in this case. | 799 // Src must be a register in this case. |
| 925 const auto SrcVar = llvm::cast<Variable>(Src); | 800 const auto SrcVar = llvm::cast<Variable>(Src); |
| 926 assert(SrcVar->hasReg()); | 801 assert(SrcVar->hasReg()); |
| 927 (Asm->*(Emitter.AddrXmm))(StackAddr, | 802 (Asm->*(Emitter.AddrXmm))(StackAddr, |
| 928 RegX8632::getEncodedXmm(SrcVar->getRegNum())); | 803 RegX8632::getEncodedXmm(SrcVar->getRegNum())); |
| 929 } | 804 } |
| 930 emitIASBytes(Func, Asm, StartPosition); | |
| 931 } | 805 } |
| 932 | 806 |
| 933 bool checkForRedundantAssign(const Variable *Dest, const Operand *Source) { | 807 bool checkForRedundantAssign(const Variable *Dest, const Operand *Source) { |
| 934 const auto SrcVar = llvm::dyn_cast<const Variable>(Source); | 808 const auto SrcVar = llvm::dyn_cast<const Variable>(Source); |
| 935 if (!SrcVar) | 809 if (!SrcVar) |
| 936 return false; | 810 return false; |
| 937 if (Dest->hasReg() && Dest->getRegNum() == SrcVar->getRegNum()) { | 811 if (Dest->hasReg() && Dest->getRegNum() == SrcVar->getRegNum()) { |
| 938 // TODO: On x86-64, instructions like "mov eax, eax" are used to | 812 // TODO: On x86-64, instructions like "mov eax, eax" are used to |
| 939 // clear the upper 32 bits of rax. We need to recognize and | 813 // clear the upper 32 bits of rax. We need to recognize and |
| 940 // preserve these. | 814 // preserve these. |
| (...skipping 484 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1425 break; | 1299 break; |
| 1426 case IceType_i32: | 1300 case IceType_i32: |
| 1427 assert(getDest()->getRegNum() == RegX8632::Reg_edx); | 1301 assert(getDest()->getRegNum() == RegX8632::Reg_edx); |
| 1428 Str << "\tcltd"; | 1302 Str << "\tcltd"; |
| 1429 break; | 1303 break; |
| 1430 } | 1304 } |
| 1431 } | 1305 } |
| 1432 | 1306 |
| 1433 template <> void InstX8632Cbwdq::emitIAS(const Cfg *Func) const { | 1307 template <> void InstX8632Cbwdq::emitIAS(const Cfg *Func) const { |
| 1434 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 1308 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 1435 intptr_t StartPosition = Asm->GetPosition(); | |
| 1436 assert(getSrcSize() == 1); | 1309 assert(getSrcSize() == 1); |
| 1437 Operand *Src0 = getSrc(0); | 1310 Operand *Src0 = getSrc(0); |
| 1438 assert(llvm::isa<Variable>(Src0)); | 1311 assert(llvm::isa<Variable>(Src0)); |
| 1439 assert(llvm::cast<Variable>(Src0)->getRegNum() == RegX8632::Reg_eax); | 1312 assert(llvm::cast<Variable>(Src0)->getRegNum() == RegX8632::Reg_eax); |
| 1440 switch (Src0->getType()) { | 1313 switch (Src0->getType()) { |
| 1441 default: | 1314 default: |
| 1442 llvm_unreachable("unexpected source type!"); | 1315 llvm_unreachable("unexpected source type!"); |
| 1443 break; | 1316 break; |
| 1444 case IceType_i8: | 1317 case IceType_i8: |
| 1445 assert(getDest()->getRegNum() == RegX8632::Reg_eax); | 1318 assert(getDest()->getRegNum() == RegX8632::Reg_eax); |
| 1446 Asm->cbw(); | 1319 Asm->cbw(); |
| 1447 break; | 1320 break; |
| 1448 case IceType_i16: | 1321 case IceType_i16: |
| 1449 assert(getDest()->getRegNum() == RegX8632::Reg_edx); | 1322 assert(getDest()->getRegNum() == RegX8632::Reg_edx); |
| 1450 Asm->cwd(); | 1323 Asm->cwd(); |
| 1451 break; | 1324 break; |
| 1452 case IceType_i32: | 1325 case IceType_i32: |
| 1453 assert(getDest()->getRegNum() == RegX8632::Reg_edx); | 1326 assert(getDest()->getRegNum() == RegX8632::Reg_edx); |
| 1454 Asm->cdq(); | 1327 Asm->cdq(); |
| 1455 break; | 1328 break; |
| 1456 } | 1329 } |
| 1457 emitIASBytes(Func, Asm, StartPosition); | |
| 1458 } | 1330 } |
| 1459 | 1331 |
| 1460 void InstX8632Mul::emit(const Cfg *Func) const { | 1332 void InstX8632Mul::emit(const Cfg *Func) const { |
| 1461 Ostream &Str = Func->getContext()->getStrEmit(); | 1333 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1462 assert(getSrcSize() == 2); | 1334 assert(getSrcSize() == 2); |
| 1463 assert(llvm::isa<Variable>(getSrc(0))); | 1335 assert(llvm::isa<Variable>(getSrc(0))); |
| 1464 assert(llvm::cast<Variable>(getSrc(0))->getRegNum() == RegX8632::Reg_eax); | 1336 assert(llvm::cast<Variable>(getSrc(0))->getRegNum() == RegX8632::Reg_eax); |
| 1465 assert(getDest()->getRegNum() == RegX8632::Reg_eax); // TODO: allow edx? | 1337 assert(getDest()->getRegNum() == RegX8632::Reg_eax); // TODO: allow edx? |
| 1466 Str << "\tmul" << getWidthString(getDest()->getType()) << "\t"; | 1338 Str << "\tmul" << getWidthString(getDest()->getType()) << "\t"; |
| 1467 getSrc(1)->emit(Func); | 1339 getSrc(1)->emit(Func); |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1575 | 1447 |
| 1576 void InstX8632Cmov::emitIAS(const Cfg *Func) const { | 1448 void InstX8632Cmov::emitIAS(const Cfg *Func) const { |
| 1577 assert(Condition != CondX86::Br_None); | 1449 assert(Condition != CondX86::Br_None); |
| 1578 assert(getDest()->hasReg()); | 1450 assert(getDest()->hasReg()); |
| 1579 assert(getSrcSize() == 2); | 1451 assert(getSrcSize() == 2); |
| 1580 // Only need the reg/reg form now. | 1452 // Only need the reg/reg form now. |
| 1581 const auto SrcVar = llvm::cast<Variable>(getSrc(1)); | 1453 const auto SrcVar = llvm::cast<Variable>(getSrc(1)); |
| 1582 assert(SrcVar->hasReg()); | 1454 assert(SrcVar->hasReg()); |
| 1583 assert(SrcVar->getType() == IceType_i32); | 1455 assert(SrcVar->getType() == IceType_i32); |
| 1584 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 1456 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 1585 intptr_t StartPosition = Asm->GetPosition(); | |
| 1586 Asm->cmov(Condition, RegX8632::getEncodedGPR(getDest()->getRegNum()), | 1457 Asm->cmov(Condition, RegX8632::getEncodedGPR(getDest()->getRegNum()), |
| 1587 RegX8632::getEncodedGPR(SrcVar->getRegNum())); | 1458 RegX8632::getEncodedGPR(SrcVar->getRegNum())); |
| 1588 emitIASBytes(Func, Asm, StartPosition); | |
| 1589 } | 1459 } |
| 1590 | 1460 |
| 1591 void InstX8632Cmov::dump(const Cfg *Func) const { | 1461 void InstX8632Cmov::dump(const Cfg *Func) const { |
| 1592 Ostream &Str = Func->getContext()->getStrDump(); | 1462 Ostream &Str = Func->getContext()->getStrDump(); |
| 1593 Str << "cmov" << InstX8632BrAttributes[Condition].DisplayString << "."; | 1463 Str << "cmov" << InstX8632BrAttributes[Condition].DisplayString << "."; |
| 1594 Str << getDest()->getType() << " "; | 1464 Str << getDest()->getType() << " "; |
| 1595 dumpDest(Func); | 1465 dumpDest(Func); |
| 1596 Str << ", "; | 1466 Str << ", "; |
| 1597 dumpSources(Func); | 1467 dumpSources(Func); |
| 1598 } | 1468 } |
| 1599 | 1469 |
| 1600 void InstX8632Cmpps::emit(const Cfg *Func) const { | 1470 void InstX8632Cmpps::emit(const Cfg *Func) const { |
| 1601 Ostream &Str = Func->getContext()->getStrEmit(); | 1471 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1602 assert(getSrcSize() == 2); | 1472 assert(getSrcSize() == 2); |
| 1603 assert(Condition < CondX86::Cmpps_Invalid); | 1473 assert(Condition < CondX86::Cmpps_Invalid); |
| 1604 Str << "\t"; | 1474 Str << "\t"; |
| 1605 Str << "cmp" << InstX8632CmppsAttributes[Condition].EmitString << "ps" | 1475 Str << "cmp" << InstX8632CmppsAttributes[Condition].EmitString << "ps" |
| 1606 << "\t"; | 1476 << "\t"; |
| 1607 getSrc(1)->emit(Func); | 1477 getSrc(1)->emit(Func); |
| 1608 Str << ", "; | 1478 Str << ", "; |
| 1609 getDest()->emit(Func); | 1479 getDest()->emit(Func); |
| 1610 } | 1480 } |
| 1611 | 1481 |
| 1612 void InstX8632Cmpps::emitIAS(const Cfg *Func) const { | 1482 void InstX8632Cmpps::emitIAS(const Cfg *Func) const { |
| 1613 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 1483 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 1614 intptr_t StartPosition = Asm->GetPosition(); | |
| 1615 assert(getSrcSize() == 2); | 1484 assert(getSrcSize() == 2); |
| 1616 assert(Condition < CondX86::Cmpps_Invalid); | 1485 assert(Condition < CondX86::Cmpps_Invalid); |
| 1617 // Assuming there isn't any load folding for cmpps, and vector constants | 1486 // Assuming there isn't any load folding for cmpps, and vector constants |
| 1618 // are not allowed in PNaCl. | 1487 // are not allowed in PNaCl. |
| 1619 assert(llvm::isa<Variable>(getSrc(1))); | 1488 assert(llvm::isa<Variable>(getSrc(1))); |
| 1620 const auto SrcVar = llvm::cast<Variable>(getSrc(1)); | 1489 const auto SrcVar = llvm::cast<Variable>(getSrc(1)); |
| 1621 if (SrcVar->hasReg()) { | 1490 if (SrcVar->hasReg()) { |
| 1622 Asm->cmpps(RegX8632::getEncodedXmm(getDest()->getRegNum()), | 1491 Asm->cmpps(RegX8632::getEncodedXmm(getDest()->getRegNum()), |
| 1623 RegX8632::getEncodedXmm(SrcVar->getRegNum()), Condition); | 1492 RegX8632::getEncodedXmm(SrcVar->getRegNum()), Condition); |
| 1624 } else { | 1493 } else { |
| 1625 x86::Address SrcStackAddr = static_cast<TargetX8632 *>(Func->getTarget()) | 1494 x86::Address SrcStackAddr = static_cast<TargetX8632 *>(Func->getTarget()) |
| 1626 ->stackVarToAsmOperand(SrcVar); | 1495 ->stackVarToAsmOperand(SrcVar); |
| 1627 Asm->cmpps(RegX8632::getEncodedXmm(getDest()->getRegNum()), SrcStackAddr, | 1496 Asm->cmpps(RegX8632::getEncodedXmm(getDest()->getRegNum()), SrcStackAddr, |
| 1628 Condition); | 1497 Condition); |
| 1629 } | 1498 } |
| 1630 emitIASBytes(Func, Asm, StartPosition); | |
| 1631 } | 1499 } |
| 1632 | 1500 |
| 1633 void InstX8632Cmpps::dump(const Cfg *Func) const { | 1501 void InstX8632Cmpps::dump(const Cfg *Func) const { |
| 1634 Ostream &Str = Func->getContext()->getStrDump(); | 1502 Ostream &Str = Func->getContext()->getStrDump(); |
| 1635 assert(Condition < CondX86::Cmpps_Invalid); | 1503 assert(Condition < CondX86::Cmpps_Invalid); |
| 1636 dumpDest(Func); | 1504 dumpDest(Func); |
| 1637 Str << " = cmp" << InstX8632CmppsAttributes[Condition].EmitString << "ps" | 1505 Str << " = cmp" << InstX8632CmppsAttributes[Condition].EmitString << "ps" |
| 1638 << "\t"; | 1506 << "\t"; |
| 1639 dumpSources(Func); | 1507 dumpSources(Func); |
| 1640 } | 1508 } |
| 1641 | 1509 |
| 1642 void InstX8632Cmpxchg::emit(const Cfg *Func) const { | 1510 void InstX8632Cmpxchg::emit(const Cfg *Func) const { |
| 1643 Ostream &Str = Func->getContext()->getStrEmit(); | 1511 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1644 assert(getSrcSize() == 3); | 1512 assert(getSrcSize() == 3); |
| 1645 if (Locked) { | 1513 if (Locked) { |
| 1646 Str << "\tlock"; | 1514 Str << "\tlock"; |
| 1647 } | 1515 } |
| 1648 Str << "\tcmpxchg" << getWidthString(getSrc(0)->getType()) << "\t"; | 1516 Str << "\tcmpxchg" << getWidthString(getSrc(0)->getType()) << "\t"; |
| 1649 getSrc(2)->emit(Func); | 1517 getSrc(2)->emit(Func); |
| 1650 Str << ", "; | 1518 Str << ", "; |
| 1651 getSrc(0)->emit(Func); | 1519 getSrc(0)->emit(Func); |
| 1652 } | 1520 } |
| 1653 | 1521 |
| 1654 void InstX8632Cmpxchg::emitIAS(const Cfg *Func) const { | 1522 void InstX8632Cmpxchg::emitIAS(const Cfg *Func) const { |
| 1655 assert(getSrcSize() == 3); | 1523 assert(getSrcSize() == 3); |
| 1656 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 1524 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 1657 intptr_t StartPosition = Asm->GetPosition(); | |
| 1658 Type Ty = getSrc(0)->getType(); | 1525 Type Ty = getSrc(0)->getType(); |
| 1659 const auto Mem = llvm::cast<OperandX8632Mem>(getSrc(0)); | 1526 const auto Mem = llvm::cast<OperandX8632Mem>(getSrc(0)); |
| 1660 assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); | 1527 assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); |
| 1661 const x86::Address Addr = Mem->toAsmAddress(Asm); | 1528 const x86::Address Addr = Mem->toAsmAddress(Asm); |
| 1662 const auto VarReg = llvm::cast<Variable>(getSrc(2)); | 1529 const auto VarReg = llvm::cast<Variable>(getSrc(2)); |
| 1663 assert(VarReg->hasReg()); | 1530 assert(VarReg->hasReg()); |
| 1664 const RegX8632::GPRRegister Reg = | 1531 const RegX8632::GPRRegister Reg = |
| 1665 RegX8632::getEncodedGPR(VarReg->getRegNum()); | 1532 RegX8632::getEncodedGPR(VarReg->getRegNum()); |
| 1666 if (Locked) { | 1533 if (Locked) { |
| 1667 Asm->LockCmpxchg(Ty, Addr, Reg); | 1534 Asm->LockCmpxchg(Ty, Addr, Reg); |
| 1668 } else { | 1535 } else { |
| 1669 Asm->cmpxchg(Ty, Addr, Reg); | 1536 Asm->cmpxchg(Ty, Addr, Reg); |
| 1670 } | 1537 } |
| 1671 emitIASBytes(Func, Asm, StartPosition); | |
| 1672 } | 1538 } |
| 1673 | 1539 |
| 1674 void InstX8632Cmpxchg::dump(const Cfg *Func) const { | 1540 void InstX8632Cmpxchg::dump(const Cfg *Func) const { |
| 1675 Ostream &Str = Func->getContext()->getStrDump(); | 1541 Ostream &Str = Func->getContext()->getStrDump(); |
| 1676 if (Locked) { | 1542 if (Locked) { |
| 1677 Str << "lock "; | 1543 Str << "lock "; |
| 1678 } | 1544 } |
| 1679 Str << "cmpxchg." << getSrc(0)->getType() << " "; | 1545 Str << "cmpxchg." << getSrc(0)->getType() << " "; |
| 1680 dumpSources(Func); | 1546 dumpSources(Func); |
| 1681 } | 1547 } |
| 1682 | 1548 |
| 1683 void InstX8632Cmpxchg8b::emit(const Cfg *Func) const { | 1549 void InstX8632Cmpxchg8b::emit(const Cfg *Func) const { |
| 1684 Ostream &Str = Func->getContext()->getStrEmit(); | 1550 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1685 assert(getSrcSize() == 5); | 1551 assert(getSrcSize() == 5); |
| 1686 if (Locked) { | 1552 if (Locked) { |
| 1687 Str << "\tlock"; | 1553 Str << "\tlock"; |
| 1688 } | 1554 } |
| 1689 Str << "\tcmpxchg8b\t"; | 1555 Str << "\tcmpxchg8b\t"; |
| 1690 getSrc(0)->emit(Func); | 1556 getSrc(0)->emit(Func); |
| 1691 } | 1557 } |
| 1692 | 1558 |
| 1693 void InstX8632Cmpxchg8b::emitIAS(const Cfg *Func) const { | 1559 void InstX8632Cmpxchg8b::emitIAS(const Cfg *Func) const { |
| 1694 assert(getSrcSize() == 5); | 1560 assert(getSrcSize() == 5); |
| 1695 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 1561 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 1696 intptr_t StartPosition = Asm->GetPosition(); | |
| 1697 const auto Mem = llvm::cast<OperandX8632Mem>(getSrc(0)); | 1562 const auto Mem = llvm::cast<OperandX8632Mem>(getSrc(0)); |
| 1698 assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); | 1563 assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); |
| 1699 const x86::Address Addr = Mem->toAsmAddress(Asm); | 1564 const x86::Address Addr = Mem->toAsmAddress(Asm); |
| 1700 if (Locked) { | 1565 if (Locked) { |
| 1701 Asm->lock(); | 1566 Asm->lock(); |
| 1702 } | 1567 } |
| 1703 Asm->cmpxchg8b(Addr); | 1568 Asm->cmpxchg8b(Addr); |
| 1704 emitIASBytes(Func, Asm, StartPosition); | |
| 1705 } | 1569 } |
| 1706 | 1570 |
| 1707 void InstX8632Cmpxchg8b::dump(const Cfg *Func) const { | 1571 void InstX8632Cmpxchg8b::dump(const Cfg *Func) const { |
| 1708 Ostream &Str = Func->getContext()->getStrDump(); | 1572 Ostream &Str = Func->getContext()->getStrDump(); |
| 1709 if (Locked) { | 1573 if (Locked) { |
| 1710 Str << "lock "; | 1574 Str << "lock "; |
| 1711 } | 1575 } |
| 1712 Str << "cmpxchg8b "; | 1576 Str << "cmpxchg8b "; |
| 1713 dumpSources(Func); | 1577 dumpSources(Func); |
| 1714 } | 1578 } |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1861 } | 1725 } |
| 1862 | 1726 |
| 1863 void InstX8632UD2::emit(const Cfg *Func) const { | 1727 void InstX8632UD2::emit(const Cfg *Func) const { |
| 1864 Ostream &Str = Func->getContext()->getStrEmit(); | 1728 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1865 assert(getSrcSize() == 0); | 1729 assert(getSrcSize() == 0); |
| 1866 Str << "\tud2"; | 1730 Str << "\tud2"; |
| 1867 } | 1731 } |
| 1868 | 1732 |
| 1869 void InstX8632UD2::emitIAS(const Cfg *Func) const { | 1733 void InstX8632UD2::emitIAS(const Cfg *Func) const { |
| 1870 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 1734 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 1871 intptr_t StartPosition = Asm->GetPosition(); | |
| 1872 Asm->ud2(); | 1735 Asm->ud2(); |
| 1873 emitIASBytes(Func, Asm, StartPosition); | |
| 1874 } | 1736 } |
| 1875 | 1737 |
| 1876 void InstX8632UD2::dump(const Cfg *Func) const { | 1738 void InstX8632UD2::dump(const Cfg *Func) const { |
| 1877 Ostream &Str = Func->getContext()->getStrDump(); | 1739 Ostream &Str = Func->getContext()->getStrDump(); |
| 1878 Str << "ud2\n"; | 1740 Str << "ud2\n"; |
| 1879 } | 1741 } |
| 1880 | 1742 |
| 1881 void InstX8632Test::emit(const Cfg *Func) const { | 1743 void InstX8632Test::emit(const Cfg *Func) const { |
| 1882 Ostream &Str = Func->getContext()->getStrEmit(); | 1744 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1883 assert(getSrcSize() == 2); | 1745 assert(getSrcSize() == 2); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1915 } | 1777 } |
| 1916 | 1778 |
| 1917 void InstX8632Mfence::emit(const Cfg *Func) const { | 1779 void InstX8632Mfence::emit(const Cfg *Func) const { |
| 1918 Ostream &Str = Func->getContext()->getStrEmit(); | 1780 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1919 assert(getSrcSize() == 0); | 1781 assert(getSrcSize() == 0); |
| 1920 Str << "\tmfence"; | 1782 Str << "\tmfence"; |
| 1921 } | 1783 } |
| 1922 | 1784 |
| 1923 void InstX8632Mfence::emitIAS(const Cfg *Func) const { | 1785 void InstX8632Mfence::emitIAS(const Cfg *Func) const { |
| 1924 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 1786 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 1925 intptr_t StartPosition = Asm->GetPosition(); | |
| 1926 Asm->mfence(); | 1787 Asm->mfence(); |
| 1927 emitIASBytes(Func, Asm, StartPosition); | |
| 1928 } | 1788 } |
| 1929 | 1789 |
| 1930 void InstX8632Mfence::dump(const Cfg *Func) const { | 1790 void InstX8632Mfence::dump(const Cfg *Func) const { |
| 1931 Ostream &Str = Func->getContext()->getStrDump(); | 1791 Ostream &Str = Func->getContext()->getStrDump(); |
| 1932 Str << "mfence\n"; | 1792 Str << "mfence\n"; |
| 1933 } | 1793 } |
| 1934 | 1794 |
| 1935 void InstX8632Store::emit(const Cfg *Func) const { | 1795 void InstX8632Store::emit(const Cfg *Func) const { |
| 1936 Ostream &Str = Func->getContext()->getStrEmit(); | 1796 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1937 assert(getSrcSize() == 2); | 1797 assert(getSrcSize() == 2); |
| 1938 Type Ty = getSrc(0)->getType(); | 1798 Type Ty = getSrc(0)->getType(); |
| 1939 Str << "\tmov" << getWidthString(Ty) << TypeX8632Attributes[Ty].SdSsString | 1799 Str << "\tmov" << getWidthString(Ty) << TypeX8632Attributes[Ty].SdSsString |
| 1940 << "\t"; | 1800 << "\t"; |
| 1941 getSrc(0)->emit(Func); | 1801 getSrc(0)->emit(Func); |
| 1942 Str << ", "; | 1802 Str << ", "; |
| 1943 getSrc(1)->emit(Func); | 1803 getSrc(1)->emit(Func); |
| 1944 } | 1804 } |
| 1945 | 1805 |
| 1946 void InstX8632Store::emitIAS(const Cfg *Func) const { | 1806 void InstX8632Store::emitIAS(const Cfg *Func) const { |
| 1947 assert(getSrcSize() == 2); | 1807 assert(getSrcSize() == 2); |
| 1948 const Operand *Dest = getSrc(1); | 1808 const Operand *Dest = getSrc(1); |
| 1949 const Operand *Src = getSrc(0); | 1809 const Operand *Src = getSrc(0); |
| 1950 Type DestTy = Dest->getType(); | 1810 Type DestTy = Dest->getType(); |
| 1951 if (isScalarFloatingType(DestTy)) { | 1811 if (isScalarFloatingType(DestTy)) { |
| 1952 // Src must be a register, since Dest is a Mem operand of some kind. | 1812 // Src must be a register, since Dest is a Mem operand of some kind. |
| 1953 const auto SrcVar = llvm::cast<Variable>(Src); | 1813 const auto SrcVar = llvm::cast<Variable>(Src); |
| 1954 assert(SrcVar->hasReg()); | 1814 assert(SrcVar->hasReg()); |
| 1955 RegX8632::XmmRegister SrcReg = RegX8632::getEncodedXmm(SrcVar->getRegNum()); | 1815 RegX8632::XmmRegister SrcReg = RegX8632::getEncodedXmm(SrcVar->getRegNum()); |
| 1956 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 1816 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 1957 intptr_t StartPosition = Asm->GetPosition(); | |
| 1958 if (const auto DestVar = llvm::dyn_cast<Variable>(Dest)) { | 1817 if (const auto DestVar = llvm::dyn_cast<Variable>(Dest)) { |
| 1959 assert(!DestVar->hasReg()); | 1818 assert(!DestVar->hasReg()); |
| 1960 x86::Address StackAddr(static_cast<TargetX8632 *>(Func->getTarget()) | 1819 x86::Address StackAddr(static_cast<TargetX8632 *>(Func->getTarget()) |
| 1961 ->stackVarToAsmOperand(DestVar)); | 1820 ->stackVarToAsmOperand(DestVar)); |
| 1962 Asm->movss(DestTy, StackAddr, SrcReg); | 1821 Asm->movss(DestTy, StackAddr, SrcReg); |
| 1963 } else { | 1822 } else { |
| 1964 const auto DestMem = llvm::cast<OperandX8632Mem>(Dest); | 1823 const auto DestMem = llvm::cast<OperandX8632Mem>(Dest); |
| 1965 assert(DestMem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); | 1824 assert(DestMem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); |
| 1966 Asm->movss(DestTy, DestMem->toAsmAddress(Asm), SrcReg); | 1825 Asm->movss(DestTy, DestMem->toAsmAddress(Asm), SrcReg); |
| 1967 } | 1826 } |
| 1968 emitIASBytes(Func, Asm, StartPosition); | |
| 1969 return; | 1827 return; |
| 1970 } else { | 1828 } else { |
| 1971 assert(isScalarIntegerType(DestTy)); | 1829 assert(isScalarIntegerType(DestTy)); |
| 1972 static const x86::AssemblerX86::GPREmitterAddrOp GPRAddrEmitter = { | 1830 static const x86::AssemblerX86::GPREmitterAddrOp GPRAddrEmitter = { |
| 1973 &x86::AssemblerX86::mov, &x86::AssemblerX86::mov}; | 1831 &x86::AssemblerX86::mov, &x86::AssemblerX86::mov}; |
| 1974 emitIASAsAddrOpTyGPR(Func, DestTy, Dest, Src, GPRAddrEmitter); | 1832 emitIASAsAddrOpTyGPR(Func, DestTy, Dest, Src, GPRAddrEmitter); |
| 1975 } | 1833 } |
| 1976 } | 1834 } |
| 1977 | 1835 |
| 1978 void InstX8632Store::dump(const Cfg *Func) const { | 1836 void InstX8632Store::dump(const Cfg *Func) const { |
| 1979 Ostream &Str = Func->getContext()->getStrDump(); | 1837 Ostream &Str = Func->getContext()->getStrDump(); |
| 1980 Str << "mov." << getSrc(0)->getType() << " "; | 1838 Str << "mov." << getSrc(0)->getType() << " "; |
| 1981 getSrc(1)->dump(Func); | 1839 getSrc(1)->dump(Func); |
| 1982 Str << ", "; | 1840 Str << ", "; |
| 1983 getSrc(0)->dump(Func); | 1841 getSrc(0)->dump(Func); |
| 1984 } | 1842 } |
| 1985 | 1843 |
| 1986 void InstX8632StoreP::emit(const Cfg *Func) const { | 1844 void InstX8632StoreP::emit(const Cfg *Func) const { |
| 1987 Ostream &Str = Func->getContext()->getStrEmit(); | 1845 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1988 assert(getSrcSize() == 2); | 1846 assert(getSrcSize() == 2); |
| 1989 Str << "\tmovups\t"; | 1847 Str << "\tmovups\t"; |
| 1990 getSrc(0)->emit(Func); | 1848 getSrc(0)->emit(Func); |
| 1991 Str << ", "; | 1849 Str << ", "; |
| 1992 getSrc(1)->emit(Func); | 1850 getSrc(1)->emit(Func); |
| 1993 } | 1851 } |
| 1994 | 1852 |
| 1995 void InstX8632StoreP::emitIAS(const Cfg *Func) const { | 1853 void InstX8632StoreP::emitIAS(const Cfg *Func) const { |
| 1996 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 1854 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 1997 intptr_t StartPosition = Asm->GetPosition(); | |
| 1998 assert(getSrcSize() == 2); | 1855 assert(getSrcSize() == 2); |
| 1999 const auto SrcVar = llvm::cast<Variable>(getSrc(0)); | 1856 const auto SrcVar = llvm::cast<Variable>(getSrc(0)); |
| 2000 const auto DestMem = llvm::cast<OperandX8632Mem>(getSrc(1)); | 1857 const auto DestMem = llvm::cast<OperandX8632Mem>(getSrc(1)); |
| 2001 assert(DestMem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); | 1858 assert(DestMem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); |
| 2002 assert(SrcVar->hasReg()); | 1859 assert(SrcVar->hasReg()); |
| 2003 Asm->movups(DestMem->toAsmAddress(Asm), | 1860 Asm->movups(DestMem->toAsmAddress(Asm), |
| 2004 RegX8632::getEncodedXmm(SrcVar->getRegNum())); | 1861 RegX8632::getEncodedXmm(SrcVar->getRegNum())); |
| 2005 emitIASBytes(Func, Asm, StartPosition); | |
| 2006 } | 1862 } |
| 2007 | 1863 |
| 2008 void InstX8632StoreP::dump(const Cfg *Func) const { | 1864 void InstX8632StoreP::dump(const Cfg *Func) const { |
| 2009 Ostream &Str = Func->getContext()->getStrDump(); | 1865 Ostream &Str = Func->getContext()->getStrDump(); |
| 2010 Str << "storep." << getSrc(0)->getType() << " "; | 1866 Str << "storep." << getSrc(0)->getType() << " "; |
| 2011 getSrc(1)->dump(Func); | 1867 getSrc(1)->dump(Func); |
| 2012 Str << ", "; | 1868 Str << ", "; |
| 2013 getSrc(0)->dump(Func); | 1869 getSrc(0)->dump(Func); |
| 2014 } | 1870 } |
| 2015 | 1871 |
| 2016 void InstX8632StoreQ::emit(const Cfg *Func) const { | 1872 void InstX8632StoreQ::emit(const Cfg *Func) const { |
| 2017 Ostream &Str = Func->getContext()->getStrEmit(); | 1873 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2018 assert(getSrcSize() == 2); | 1874 assert(getSrcSize() == 2); |
| 2019 assert(getSrc(1)->getType() == IceType_i64 || | 1875 assert(getSrc(1)->getType() == IceType_i64 || |
| 2020 getSrc(1)->getType() == IceType_f64); | 1876 getSrc(1)->getType() == IceType_f64); |
| 2021 Str << "\tmovq\t"; | 1877 Str << "\tmovq\t"; |
| 2022 getSrc(0)->emit(Func); | 1878 getSrc(0)->emit(Func); |
| 2023 Str << ", "; | 1879 Str << ", "; |
| 2024 getSrc(1)->emit(Func); | 1880 getSrc(1)->emit(Func); |
| 2025 } | 1881 } |
| 2026 | 1882 |
| 2027 void InstX8632StoreQ::emitIAS(const Cfg *Func) const { | 1883 void InstX8632StoreQ::emitIAS(const Cfg *Func) const { |
| 2028 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 1884 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 2029 intptr_t StartPosition = Asm->GetPosition(); | |
| 2030 assert(getSrcSize() == 2); | 1885 assert(getSrcSize() == 2); |
| 2031 const auto SrcVar = llvm::cast<Variable>(getSrc(0)); | 1886 const auto SrcVar = llvm::cast<Variable>(getSrc(0)); |
| 2032 const auto DestMem = llvm::cast<OperandX8632Mem>(getSrc(1)); | 1887 const auto DestMem = llvm::cast<OperandX8632Mem>(getSrc(1)); |
| 2033 assert(DestMem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); | 1888 assert(DestMem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); |
| 2034 assert(SrcVar->hasReg()); | 1889 assert(SrcVar->hasReg()); |
| 2035 Asm->movq(DestMem->toAsmAddress(Asm), | 1890 Asm->movq(DestMem->toAsmAddress(Asm), |
| 2036 RegX8632::getEncodedXmm(SrcVar->getRegNum())); | 1891 RegX8632::getEncodedXmm(SrcVar->getRegNum())); |
| 2037 emitIASBytes(Func, Asm, StartPosition); | |
| 2038 } | 1892 } |
| 2039 | 1893 |
| 2040 void InstX8632StoreQ::dump(const Cfg *Func) const { | 1894 void InstX8632StoreQ::dump(const Cfg *Func) const { |
| 2041 Ostream &Str = Func->getContext()->getStrDump(); | 1895 Ostream &Str = Func->getContext()->getStrDump(); |
| 2042 Str << "storeq." << getSrc(0)->getType() << " "; | 1896 Str << "storeq." << getSrc(0)->getType() << " "; |
| 2043 getSrc(1)->dump(Func); | 1897 getSrc(1)->dump(Func); |
| 2044 Str << ", "; | 1898 Str << ", "; |
| 2045 getSrc(0)->dump(Func); | 1899 getSrc(0)->dump(Func); |
| 2046 } | 1900 } |
| 2047 | 1901 |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2138 } else { | 1992 } else { |
| 2139 // Dest must be Stack and Src *could* be a register. Use Src's type | 1993 // Dest must be Stack and Src *could* be a register. Use Src's type |
| 2140 // to decide on the emitters. | 1994 // to decide on the emitters. |
| 2141 x86::Address StackAddr(static_cast<TargetX8632 *>(Func->getTarget()) | 1995 x86::Address StackAddr(static_cast<TargetX8632 *>(Func->getTarget()) |
| 2142 ->stackVarToAsmOperand(Dest)); | 1996 ->stackVarToAsmOperand(Dest)); |
| 2143 if (isScalarFloatingType(SrcTy)) { | 1997 if (isScalarFloatingType(SrcTy)) { |
| 2144 // Src must be a register. | 1998 // Src must be a register. |
| 2145 const auto SrcVar = llvm::cast<Variable>(Src); | 1999 const auto SrcVar = llvm::cast<Variable>(Src); |
| 2146 assert(SrcVar->hasReg()); | 2000 assert(SrcVar->hasReg()); |
| 2147 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 2001 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 2148 intptr_t StartPosition = Asm->GetPosition(); | |
| 2149 Asm->movss(SrcTy, StackAddr, | 2002 Asm->movss(SrcTy, StackAddr, |
| 2150 RegX8632::getEncodedXmm(SrcVar->getRegNum())); | 2003 RegX8632::getEncodedXmm(SrcVar->getRegNum())); |
| 2151 emitIASBytes(Func, Asm, StartPosition); | |
| 2152 return; | 2004 return; |
| 2153 } else { | 2005 } else { |
| 2154 // Src can be a register or immediate. | 2006 // Src can be a register or immediate. |
| 2155 assert(isScalarIntegerType(SrcTy)); | 2007 assert(isScalarIntegerType(SrcTy)); |
| 2156 emitIASAddrOpTyGPR(Func, SrcTy, StackAddr, Src, GPRAddrEmitter); | 2008 emitIASAddrOpTyGPR(Func, SrcTy, StackAddr, Src, GPRAddrEmitter); |
| 2157 return; | 2009 return; |
| 2158 } | 2010 } |
| 2159 return; | 2011 return; |
| 2160 } | 2012 } |
| 2161 } | 2013 } |
| 2162 | 2014 |
| 2163 template <> void InstX8632Movd::emitIAS(const Cfg *Func) const { | 2015 template <> void InstX8632Movd::emitIAS(const Cfg *Func) const { |
| 2164 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 2016 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 2165 intptr_t StartPosition = Asm->GetPosition(); | |
| 2166 assert(getSrcSize() == 1); | 2017 assert(getSrcSize() == 1); |
| 2167 const Variable *Dest = getDest(); | 2018 const Variable *Dest = getDest(); |
| 2168 const auto SrcVar = llvm::cast<Variable>(getSrc(0)); | 2019 const auto SrcVar = llvm::cast<Variable>(getSrc(0)); |
| 2169 // For insert/extract element (one of Src/Dest is an Xmm vector and | 2020 // For insert/extract element (one of Src/Dest is an Xmm vector and |
| 2170 // the other is an int type). | 2021 // the other is an int type). |
| 2171 if (SrcVar->getType() == IceType_i32) { | 2022 if (SrcVar->getType() == IceType_i32) { |
| 2172 assert(isVectorType(Dest->getType())); | 2023 assert(isVectorType(Dest->getType())); |
| 2173 assert(Dest->hasReg()); | 2024 assert(Dest->hasReg()); |
| 2174 RegX8632::XmmRegister DestReg = RegX8632::getEncodedXmm(Dest->getRegNum()); | 2025 RegX8632::XmmRegister DestReg = RegX8632::getEncodedXmm(Dest->getRegNum()); |
| 2175 if (SrcVar->hasReg()) { | 2026 if (SrcVar->hasReg()) { |
| 2176 Asm->movd(DestReg, RegX8632::getEncodedGPR(SrcVar->getRegNum())); | 2027 Asm->movd(DestReg, RegX8632::getEncodedGPR(SrcVar->getRegNum())); |
| 2177 } else { | 2028 } else { |
| 2178 x86::Address StackAddr(static_cast<TargetX8632 *>(Func->getTarget()) | 2029 x86::Address StackAddr(static_cast<TargetX8632 *>(Func->getTarget()) |
| 2179 ->stackVarToAsmOperand(SrcVar)); | 2030 ->stackVarToAsmOperand(SrcVar)); |
| 2180 Asm->movd(DestReg, StackAddr); | 2031 Asm->movd(DestReg, StackAddr); |
| 2181 } | 2032 } |
| 2182 } else { | 2033 } else { |
| 2183 assert(isVectorType(SrcVar->getType())); | 2034 assert(isVectorType(SrcVar->getType())); |
| 2184 assert(SrcVar->hasReg()); | 2035 assert(SrcVar->hasReg()); |
| 2185 assert(Dest->getType() == IceType_i32); | 2036 assert(Dest->getType() == IceType_i32); |
| 2186 RegX8632::XmmRegister SrcReg = RegX8632::getEncodedXmm(SrcVar->getRegNum()); | 2037 RegX8632::XmmRegister SrcReg = RegX8632::getEncodedXmm(SrcVar->getRegNum()); |
| 2187 if (Dest->hasReg()) { | 2038 if (Dest->hasReg()) { |
| 2188 Asm->movd(RegX8632::getEncodedGPR(Dest->getRegNum()), SrcReg); | 2039 Asm->movd(RegX8632::getEncodedGPR(Dest->getRegNum()), SrcReg); |
| 2189 } else { | 2040 } else { |
| 2190 x86::Address StackAddr(static_cast<TargetX8632 *>(Func->getTarget()) | 2041 x86::Address StackAddr(static_cast<TargetX8632 *>(Func->getTarget()) |
| 2191 ->stackVarToAsmOperand(Dest)); | 2042 ->stackVarToAsmOperand(Dest)); |
| 2192 Asm->movd(StackAddr, SrcReg); | 2043 Asm->movd(StackAddr, SrcReg); |
| 2193 } | 2044 } |
| 2194 } | 2045 } |
| 2195 emitIASBytes(Func, Asm, StartPosition); | |
| 2196 } | 2046 } |
| 2197 | 2047 |
| 2198 template <> void InstX8632Movp::emit(const Cfg *Func) const { | 2048 template <> void InstX8632Movp::emit(const Cfg *Func) const { |
| 2199 // TODO(wala,stichnot): movups works with all vector operands, but | 2049 // TODO(wala,stichnot): movups works with all vector operands, but |
| 2200 // there exist other instructions (movaps, movdqa, movdqu) that may | 2050 // there exist other instructions (movaps, movdqa, movdqu) that may |
| 2201 // perform better, depending on the data type and alignment of the | 2051 // perform better, depending on the data type and alignment of the |
| 2202 // operands. | 2052 // operands. |
| 2203 Ostream &Str = Func->getContext()->getStrEmit(); | 2053 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2204 assert(getSrcSize() == 1); | 2054 assert(getSrcSize() == 1); |
| 2205 Str << "\tmovups\t"; | 2055 Str << "\tmovups\t"; |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2245 | 2095 |
| 2246 template <> void InstX8632MovssRegs::emitIAS(const Cfg *Func) const { | 2096 template <> void InstX8632MovssRegs::emitIAS(const Cfg *Func) const { |
| 2247 // This is Binop variant is only intended to be used for reg-reg moves | 2097 // This is Binop variant is only intended to be used for reg-reg moves |
| 2248 // where part of the Dest register is untouched. | 2098 // where part of the Dest register is untouched. |
| 2249 assert(getSrcSize() == 2); | 2099 assert(getSrcSize() == 2); |
| 2250 const Variable *Dest = getDest(); | 2100 const Variable *Dest = getDest(); |
| 2251 assert(Dest == getSrc(0)); | 2101 assert(Dest == getSrc(0)); |
| 2252 const auto SrcVar = llvm::cast<Variable>(getSrc(1)); | 2102 const auto SrcVar = llvm::cast<Variable>(getSrc(1)); |
| 2253 assert(Dest->hasReg() && SrcVar->hasReg()); | 2103 assert(Dest->hasReg() && SrcVar->hasReg()); |
| 2254 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 2104 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 2255 intptr_t StartPosition = Asm->GetPosition(); | |
| 2256 Asm->movss(IceType_f32, RegX8632::getEncodedXmm(Dest->getRegNum()), | 2105 Asm->movss(IceType_f32, RegX8632::getEncodedXmm(Dest->getRegNum()), |
| 2257 RegX8632::getEncodedXmm(SrcVar->getRegNum())); | 2106 RegX8632::getEncodedXmm(SrcVar->getRegNum())); |
| 2258 emitIASBytes(Func, Asm, StartPosition); | |
| 2259 } | 2107 } |
| 2260 | 2108 |
| 2261 template <> void InstX8632Movsx::emitIAS(const Cfg *Func) const { | 2109 template <> void InstX8632Movsx::emitIAS(const Cfg *Func) const { |
| 2262 assert(getSrcSize() == 1); | 2110 assert(getSrcSize() == 1); |
| 2263 const Variable *Dest = getDest(); | 2111 const Variable *Dest = getDest(); |
| 2264 const Operand *Src = getSrc(0); | 2112 const Operand *Src = getSrc(0); |
| 2265 // Dest must be a > 8-bit register, but Src can be 8-bit. In practice | 2113 // Dest must be a > 8-bit register, but Src can be 8-bit. In practice |
| 2266 // we just use the full register for Dest to avoid having an | 2114 // we just use the full register for Dest to avoid having an |
| 2267 // OperandSizeOverride prefix. It also allows us to only dispatch on SrcTy. | 2115 // OperandSizeOverride prefix. It also allows us to only dispatch on SrcTy. |
| 2268 Type SrcTy = Src->getType(); | 2116 Type SrcTy = Src->getType(); |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 2282 } | 2130 } |
| 2283 | 2131 |
| 2284 void InstX8632Nop::emit(const Cfg *Func) const { | 2132 void InstX8632Nop::emit(const Cfg *Func) const { |
| 2285 Ostream &Str = Func->getContext()->getStrEmit(); | 2133 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2286 // TODO: Emit the right code for each variant. | 2134 // TODO: Emit the right code for each variant. |
| 2287 Str << "\tnop\t# variant = " << Variant; | 2135 Str << "\tnop\t# variant = " << Variant; |
| 2288 } | 2136 } |
| 2289 | 2137 |
| 2290 void InstX8632Nop::emitIAS(const Cfg *Func) const { | 2138 void InstX8632Nop::emitIAS(const Cfg *Func) const { |
| 2291 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 2139 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 2292 intptr_t StartPosition = Asm->GetPosition(); | |
| 2293 // TODO: Emit the right code for the variant. | 2140 // TODO: Emit the right code for the variant. |
| 2294 Asm->nop(); | 2141 Asm->nop(); |
| 2295 emitIASBytes(Func, Asm, StartPosition); | |
| 2296 } | 2142 } |
| 2297 | 2143 |
| 2298 void InstX8632Nop::dump(const Cfg *Func) const { | 2144 void InstX8632Nop::dump(const Cfg *Func) const { |
| 2299 Ostream &Str = Func->getContext()->getStrDump(); | 2145 Ostream &Str = Func->getContext()->getStrDump(); |
| 2300 Str << "nop (variant = " << Variant << ")"; | 2146 Str << "nop (variant = " << Variant << ")"; |
| 2301 } | 2147 } |
| 2302 | 2148 |
| 2303 void InstX8632Fld::emit(const Cfg *Func) const { | 2149 void InstX8632Fld::emit(const Cfg *Func) const { |
| 2304 Ostream &Str = Func->getContext()->getStrEmit(); | 2150 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2305 assert(getSrcSize() == 1); | 2151 assert(getSrcSize() == 1); |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 2318 << "(%esp)\n"; | 2164 << "(%esp)\n"; |
| 2319 Str << "\taddl\t$" << Width << ", %esp"; | 2165 Str << "\taddl\t$" << Width << ", %esp"; |
| 2320 return; | 2166 return; |
| 2321 } | 2167 } |
| 2322 Str << "\tfld" << getFldString(Ty) << "\t"; | 2168 Str << "\tfld" << getFldString(Ty) << "\t"; |
| 2323 getSrc(0)->emit(Func); | 2169 getSrc(0)->emit(Func); |
| 2324 } | 2170 } |
| 2325 | 2171 |
| 2326 void InstX8632Fld::emitIAS(const Cfg *Func) const { | 2172 void InstX8632Fld::emitIAS(const Cfg *Func) const { |
| 2327 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 2173 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 2328 intptr_t StartPosition = Asm->GetPosition(); | |
| 2329 assert(getSrcSize() == 1); | 2174 assert(getSrcSize() == 1); |
| 2330 const Operand *Src = getSrc(0); | 2175 const Operand *Src = getSrc(0); |
| 2331 Type Ty = Src->getType(); | 2176 Type Ty = Src->getType(); |
| 2332 if (const auto Var = llvm::dyn_cast<Variable>(Src)) { | 2177 if (const auto Var = llvm::dyn_cast<Variable>(Src)) { |
| 2333 if (Var->hasReg()) { | 2178 if (Var->hasReg()) { |
| 2334 // This is a physical xmm register, so we need to spill it to a | 2179 // This is a physical xmm register, so we need to spill it to a |
| 2335 // temporary stack slot. | 2180 // temporary stack slot. |
| 2336 x86::Immediate Width(typeWidthInBytes(Ty)); | 2181 x86::Immediate Width(typeWidthInBytes(Ty)); |
| 2337 Asm->sub(IceType_i32, RegX8632::Encoded_Reg_esp, Width); | 2182 Asm->sub(IceType_i32, RegX8632::Encoded_Reg_esp, Width); |
| 2338 x86::Address StackSlot = x86::Address(RegX8632::Encoded_Reg_esp, 0); | 2183 x86::Address StackSlot = x86::Address(RegX8632::Encoded_Reg_esp, 0); |
| 2339 Asm->movss(Ty, StackSlot, RegX8632::getEncodedXmm(Var->getRegNum())); | 2184 Asm->movss(Ty, StackSlot, RegX8632::getEncodedXmm(Var->getRegNum())); |
| 2340 Asm->fld(Ty, StackSlot); | 2185 Asm->fld(Ty, StackSlot); |
| 2341 Asm->add(IceType_i32, RegX8632::Encoded_Reg_esp, Width); | 2186 Asm->add(IceType_i32, RegX8632::Encoded_Reg_esp, Width); |
| 2342 } else { | 2187 } else { |
| 2343 x86::Address StackAddr(static_cast<TargetX8632 *>(Func->getTarget()) | 2188 x86::Address StackAddr(static_cast<TargetX8632 *>(Func->getTarget()) |
| 2344 ->stackVarToAsmOperand(Var)); | 2189 ->stackVarToAsmOperand(Var)); |
| 2345 Asm->fld(Ty, StackAddr); | 2190 Asm->fld(Ty, StackAddr); |
| 2346 } | 2191 } |
| 2347 } else if (const auto Mem = llvm::dyn_cast<OperandX8632Mem>(Src)) { | 2192 } else if (const auto Mem = llvm::dyn_cast<OperandX8632Mem>(Src)) { |
| 2348 assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); | 2193 assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); |
| 2349 Asm->fld(Ty, Mem->toAsmAddress(Asm)); | 2194 Asm->fld(Ty, Mem->toAsmAddress(Asm)); |
| 2350 } else if (const auto Imm = llvm::dyn_cast<Constant>(Src)) { | 2195 } else if (const auto Imm = llvm::dyn_cast<Constant>(Src)) { |
| 2351 Asm->fld(Ty, x86::Address::ofConstPool(Func->getContext(), Asm, Imm)); | 2196 Asm->fld(Ty, x86::Address::ofConstPool(Func->getContext(), Asm, Imm)); |
| 2352 } else { | 2197 } else { |
| 2353 llvm_unreachable("Unexpected operand type"); | 2198 llvm_unreachable("Unexpected operand type"); |
| 2354 } | 2199 } |
| 2355 emitIASBytes(Func, Asm, StartPosition); | |
| 2356 } | 2200 } |
| 2357 | 2201 |
| 2358 void InstX8632Fld::dump(const Cfg *Func) const { | 2202 void InstX8632Fld::dump(const Cfg *Func) const { |
| 2359 Ostream &Str = Func->getContext()->getStrDump(); | 2203 Ostream &Str = Func->getContext()->getStrDump(); |
| 2360 Str << "fld." << getSrc(0)->getType() << " "; | 2204 Str << "fld." << getSrc(0)->getType() << " "; |
| 2361 dumpSources(Func); | 2205 dumpSources(Func); |
| 2362 } | 2206 } |
| 2363 | 2207 |
| 2364 void InstX8632Fstp::emit(const Cfg *Func) const { | 2208 void InstX8632Fstp::emit(const Cfg *Func) const { |
| 2365 Ostream &Str = Func->getContext()->getStrEmit(); | 2209 Ostream &Str = Func->getContext()->getStrEmit(); |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 2388 << "(%esp)\n"; | 2232 << "(%esp)\n"; |
| 2389 Str << "\tmov" << TypeX8632Attributes[Ty].SdSsString << "\t" | 2233 Str << "\tmov" << TypeX8632Attributes[Ty].SdSsString << "\t" |
| 2390 << "(%esp), "; | 2234 << "(%esp), "; |
| 2391 getDest()->emit(Func); | 2235 getDest()->emit(Func); |
| 2392 Str << "\n"; | 2236 Str << "\n"; |
| 2393 Str << "\taddl\t$" << Width << ", %esp"; | 2237 Str << "\taddl\t$" << Width << ", %esp"; |
| 2394 } | 2238 } |
| 2395 | 2239 |
| 2396 void InstX8632Fstp::emitIAS(const Cfg *Func) const { | 2240 void InstX8632Fstp::emitIAS(const Cfg *Func) const { |
| 2397 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 2241 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 2398 intptr_t StartPosition = Asm->GetPosition(); | |
| 2399 assert(getSrcSize() == 0); | 2242 assert(getSrcSize() == 0); |
| 2400 const Variable *Dest = getDest(); | 2243 const Variable *Dest = getDest(); |
| 2401 // TODO(jvoung,stichnot): Utilize this by setting Dest to nullptr to | 2244 // TODO(jvoung,stichnot): Utilize this by setting Dest to nullptr to |
| 2402 // "partially" delete the fstp if the Dest is unused. | 2245 // "partially" delete the fstp if the Dest is unused. |
| 2403 // Even if Dest is unused, the fstp should be kept for the SideEffects | 2246 // Even if Dest is unused, the fstp should be kept for the SideEffects |
| 2404 // of popping the stack. | 2247 // of popping the stack. |
| 2405 if (!Dest) { | 2248 if (!Dest) { |
| 2406 Asm->fstp(RegX8632::getEncodedSTReg(0)); | 2249 Asm->fstp(RegX8632::getEncodedSTReg(0)); |
| 2407 emitIASBytes(Func, Asm, StartPosition); | |
| 2408 return; | 2250 return; |
| 2409 } | 2251 } |
| 2410 Type Ty = Dest->getType(); | 2252 Type Ty = Dest->getType(); |
| 2411 if (!Dest->hasReg()) { | 2253 if (!Dest->hasReg()) { |
| 2412 x86::Address StackAddr(static_cast<TargetX8632 *>(Func->getTarget()) | 2254 x86::Address StackAddr(static_cast<TargetX8632 *>(Func->getTarget()) |
| 2413 ->stackVarToAsmOperand(Dest)); | 2255 ->stackVarToAsmOperand(Dest)); |
| 2414 Asm->fstp(Ty, StackAddr); | 2256 Asm->fstp(Ty, StackAddr); |
| 2415 } else { | 2257 } else { |
| 2416 // Dest is a physical (xmm) register, so st(0) needs to go through | 2258 // Dest is a physical (xmm) register, so st(0) needs to go through |
| 2417 // memory. Hack this by creating a temporary stack slot, spilling | 2259 // memory. Hack this by creating a temporary stack slot, spilling |
| 2418 // st(0) there, loading it into the xmm register, and deallocating | 2260 // st(0) there, loading it into the xmm register, and deallocating |
| 2419 // the stack slot. | 2261 // the stack slot. |
| 2420 x86::Immediate Width(typeWidthInBytes(Ty)); | 2262 x86::Immediate Width(typeWidthInBytes(Ty)); |
| 2421 Asm->sub(IceType_i32, RegX8632::Encoded_Reg_esp, Width); | 2263 Asm->sub(IceType_i32, RegX8632::Encoded_Reg_esp, Width); |
| 2422 x86::Address StackSlot = x86::Address(RegX8632::Encoded_Reg_esp, 0); | 2264 x86::Address StackSlot = x86::Address(RegX8632::Encoded_Reg_esp, 0); |
| 2423 Asm->fstp(Ty, StackSlot); | 2265 Asm->fstp(Ty, StackSlot); |
| 2424 Asm->movss(Ty, RegX8632::getEncodedXmm(Dest->getRegNum()), StackSlot); | 2266 Asm->movss(Ty, RegX8632::getEncodedXmm(Dest->getRegNum()), StackSlot); |
| 2425 Asm->add(IceType_i32, RegX8632::Encoded_Reg_esp, Width); | 2267 Asm->add(IceType_i32, RegX8632::Encoded_Reg_esp, Width); |
| 2426 } | 2268 } |
| 2427 emitIASBytes(Func, Asm, StartPosition); | |
| 2428 } | 2269 } |
| 2429 | 2270 |
| 2430 void InstX8632Fstp::dump(const Cfg *Func) const { | 2271 void InstX8632Fstp::dump(const Cfg *Func) const { |
| 2431 Ostream &Str = Func->getContext()->getStrDump(); | 2272 Ostream &Str = Func->getContext()->getStrDump(); |
| 2432 dumpDest(Func); | 2273 dumpDest(Func); |
| 2433 Str << " = fstp." << getDest()->getType() << ", st(0)"; | 2274 Str << " = fstp." << getDest()->getType() << ", st(0)"; |
| 2434 Str << "\n"; | 2275 Str << "\n"; |
| 2435 } | 2276 } |
| 2436 | 2277 |
| 2437 template <> void InstX8632Pcmpeq::emit(const Cfg *Func) const { | 2278 template <> void InstX8632Pcmpeq::emit(const Cfg *Func) const { |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2568 void InstX8632Pop::emit(const Cfg *Func) const { | 2409 void InstX8632Pop::emit(const Cfg *Func) const { |
| 2569 Ostream &Str = Func->getContext()->getStrEmit(); | 2410 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2570 assert(getSrcSize() == 0); | 2411 assert(getSrcSize() == 0); |
| 2571 Str << "\tpop\t"; | 2412 Str << "\tpop\t"; |
| 2572 getDest()->emit(Func); | 2413 getDest()->emit(Func); |
| 2573 } | 2414 } |
| 2574 | 2415 |
| 2575 void InstX8632Pop::emitIAS(const Cfg *Func) const { | 2416 void InstX8632Pop::emitIAS(const Cfg *Func) const { |
| 2576 assert(getSrcSize() == 0); | 2417 assert(getSrcSize() == 0); |
| 2577 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 2418 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 2578 intptr_t StartPosition = Asm->GetPosition(); | |
| 2579 if (getDest()->hasReg()) { | 2419 if (getDest()->hasReg()) { |
| 2580 Asm->popl(RegX8632::getEncodedGPR(getDest()->getRegNum())); | 2420 Asm->popl(RegX8632::getEncodedGPR(getDest()->getRegNum())); |
| 2581 } else { | 2421 } else { |
| 2582 Asm->popl(static_cast<TargetX8632 *>(Func->getTarget()) | 2422 Asm->popl(static_cast<TargetX8632 *>(Func->getTarget()) |
| 2583 ->stackVarToAsmOperand(getDest())); | 2423 ->stackVarToAsmOperand(getDest())); |
| 2584 } | 2424 } |
| 2585 emitIASBytes(Func, Asm, StartPosition); | |
| 2586 } | 2425 } |
| 2587 | 2426 |
| 2588 void InstX8632Pop::dump(const Cfg *Func) const { | 2427 void InstX8632Pop::dump(const Cfg *Func) const { |
| 2589 Ostream &Str = Func->getContext()->getStrDump(); | 2428 Ostream &Str = Func->getContext()->getStrDump(); |
| 2590 dumpDest(Func); | 2429 dumpDest(Func); |
| 2591 Str << " = pop." << getDest()->getType() << " "; | 2430 Str << " = pop." << getDest()->getType() << " "; |
| 2592 } | 2431 } |
| 2593 | 2432 |
| 2594 void InstX8632AdjustStack::emit(const Cfg *Func) const { | 2433 void InstX8632AdjustStack::emit(const Cfg *Func) const { |
| 2595 Ostream &Str = Func->getContext()->getStrEmit(); | 2434 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2596 Str << "\tsubl\t$" << Amount << ", %esp"; | 2435 Str << "\tsubl\t$" << Amount << ", %esp"; |
| 2597 Func->getTarget()->updateStackAdjustment(Amount); | 2436 Func->getTarget()->updateStackAdjustment(Amount); |
| 2598 } | 2437 } |
| 2599 | 2438 |
| 2600 void InstX8632AdjustStack::emitIAS(const Cfg *Func) const { | 2439 void InstX8632AdjustStack::emitIAS(const Cfg *Func) const { |
| 2601 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 2440 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 2602 intptr_t StartPosition = Asm->GetPosition(); | |
| 2603 Asm->sub(IceType_i32, RegX8632::Encoded_Reg_esp, x86::Immediate(Amount)); | 2441 Asm->sub(IceType_i32, RegX8632::Encoded_Reg_esp, x86::Immediate(Amount)); |
| 2604 emitIASBytes(Func, Asm, StartPosition); | |
| 2605 Func->getTarget()->updateStackAdjustment(Amount); | 2442 Func->getTarget()->updateStackAdjustment(Amount); |
| 2606 } | 2443 } |
| 2607 | 2444 |
| 2608 void InstX8632AdjustStack::dump(const Cfg *Func) const { | 2445 void InstX8632AdjustStack::dump(const Cfg *Func) const { |
| 2609 Ostream &Str = Func->getContext()->getStrDump(); | 2446 Ostream &Str = Func->getContext()->getStrDump(); |
| 2610 Str << "esp = sub.i32 esp, " << Amount; | 2447 Str << "esp = sub.i32 esp, " << Amount; |
| 2611 } | 2448 } |
| 2612 | 2449 |
| 2613 void InstX8632Push::emit(const Cfg *Func) const { | 2450 void InstX8632Push::emit(const Cfg *Func) const { |
| 2614 Ostream &Str = Func->getContext()->getStrEmit(); | 2451 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2615 assert(getSrcSize() == 1); | 2452 assert(getSrcSize() == 1); |
| 2616 // Push is currently only used for saving GPRs. | 2453 // Push is currently only used for saving GPRs. |
| 2617 const auto Var = llvm::cast<Variable>(getSrc(0)); | 2454 const auto Var = llvm::cast<Variable>(getSrc(0)); |
| 2618 assert(Var->hasReg()); | 2455 assert(Var->hasReg()); |
| 2619 Str << "\tpush\t"; | 2456 Str << "\tpush\t"; |
| 2620 Var->emit(Func); | 2457 Var->emit(Func); |
| 2621 } | 2458 } |
| 2622 | 2459 |
| 2623 void InstX8632Push::emitIAS(const Cfg *Func) const { | 2460 void InstX8632Push::emitIAS(const Cfg *Func) const { |
| 2624 assert(getSrcSize() == 1); | 2461 assert(getSrcSize() == 1); |
| 2625 // Push is currently only used for saving GPRs. | 2462 // Push is currently only used for saving GPRs. |
| 2626 const auto Var = llvm::cast<Variable>(getSrc(0)); | 2463 const auto Var = llvm::cast<Variable>(getSrc(0)); |
| 2627 assert(Var->hasReg()); | 2464 assert(Var->hasReg()); |
| 2628 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 2465 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 2629 intptr_t StartPosition = Asm->GetPosition(); | |
| 2630 Asm->pushl(RegX8632::getEncodedGPR(Var->getRegNum())); | 2466 Asm->pushl(RegX8632::getEncodedGPR(Var->getRegNum())); |
| 2631 emitIASBytes(Func, Asm, StartPosition); | |
| 2632 } | 2467 } |
| 2633 | 2468 |
| 2634 void InstX8632Push::dump(const Cfg *Func) const { | 2469 void InstX8632Push::dump(const Cfg *Func) const { |
| 2635 Ostream &Str = Func->getContext()->getStrDump(); | 2470 Ostream &Str = Func->getContext()->getStrDump(); |
| 2636 Str << "push." << getSrc(0)->getType() << " "; | 2471 Str << "push." << getSrc(0)->getType() << " "; |
| 2637 dumpSources(Func); | 2472 dumpSources(Func); |
| 2638 } | 2473 } |
| 2639 | 2474 |
| 2640 template <> void InstX8632Psll::emit(const Cfg *Func) const { | 2475 template <> void InstX8632Psll::emit(const Cfg *Func) const { |
| 2641 assert(getDest()->getType() == IceType_v8i16 || | 2476 assert(getDest()->getType() == IceType_v8i16 || |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 2659 emitTwoAddress(buf, this, Func); | 2494 emitTwoAddress(buf, this, Func); |
| 2660 } | 2495 } |
| 2661 | 2496 |
| 2662 void InstX8632Ret::emit(const Cfg *Func) const { | 2497 void InstX8632Ret::emit(const Cfg *Func) const { |
| 2663 Ostream &Str = Func->getContext()->getStrEmit(); | 2498 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2664 Str << "\tret"; | 2499 Str << "\tret"; |
| 2665 } | 2500 } |
| 2666 | 2501 |
| 2667 void InstX8632Ret::emitIAS(const Cfg *Func) const { | 2502 void InstX8632Ret::emitIAS(const Cfg *Func) const { |
| 2668 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 2503 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 2669 intptr_t StartPosition = Asm->GetPosition(); | |
| 2670 Asm->ret(); | 2504 Asm->ret(); |
| 2671 emitIASBytes(Func, Asm, StartPosition); | |
| 2672 } | 2505 } |
| 2673 | 2506 |
| 2674 void InstX8632Ret::dump(const Cfg *Func) const { | 2507 void InstX8632Ret::dump(const Cfg *Func) const { |
| 2675 Ostream &Str = Func->getContext()->getStrDump(); | 2508 Ostream &Str = Func->getContext()->getStrDump(); |
| 2676 Type Ty = (getSrcSize() == 0 ? IceType_void : getSrc(0)->getType()); | 2509 Type Ty = (getSrcSize() == 0 ? IceType_void : getSrc(0)->getType()); |
| 2677 Str << "ret." << Ty << " "; | 2510 Str << "ret." << Ty << " "; |
| 2678 dumpSources(Func); | 2511 dumpSources(Func); |
| 2679 } | 2512 } |
| 2680 | 2513 |
| 2681 void InstX8632Xadd::emit(const Cfg *Func) const { | 2514 void InstX8632Xadd::emit(const Cfg *Func) const { |
| 2682 Ostream &Str = Func->getContext()->getStrEmit(); | 2515 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2683 if (Locked) { | 2516 if (Locked) { |
| 2684 Str << "\tlock"; | 2517 Str << "\tlock"; |
| 2685 } | 2518 } |
| 2686 Str << "\txadd" << getWidthString(getSrc(0)->getType()) << "\t"; | 2519 Str << "\txadd" << getWidthString(getSrc(0)->getType()) << "\t"; |
| 2687 getSrc(1)->emit(Func); | 2520 getSrc(1)->emit(Func); |
| 2688 Str << ", "; | 2521 Str << ", "; |
| 2689 getSrc(0)->emit(Func); | 2522 getSrc(0)->emit(Func); |
| 2690 } | 2523 } |
| 2691 | 2524 |
| 2692 void InstX8632Xadd::emitIAS(const Cfg *Func) const { | 2525 void InstX8632Xadd::emitIAS(const Cfg *Func) const { |
| 2693 assert(getSrcSize() == 2); | 2526 assert(getSrcSize() == 2); |
| 2694 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 2527 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 2695 intptr_t StartPosition = Asm->GetPosition(); | |
| 2696 Type Ty = getSrc(0)->getType(); | 2528 Type Ty = getSrc(0)->getType(); |
| 2697 const auto Mem = llvm::cast<OperandX8632Mem>(getSrc(0)); | 2529 const auto Mem = llvm::cast<OperandX8632Mem>(getSrc(0)); |
| 2698 assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); | 2530 assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); |
| 2699 const x86::Address Addr = Mem->toAsmAddress(Asm); | 2531 const x86::Address Addr = Mem->toAsmAddress(Asm); |
| 2700 const auto VarReg = llvm::cast<Variable>(getSrc(1)); | 2532 const auto VarReg = llvm::cast<Variable>(getSrc(1)); |
| 2701 assert(VarReg->hasReg()); | 2533 assert(VarReg->hasReg()); |
| 2702 const RegX8632::GPRRegister Reg = | 2534 const RegX8632::GPRRegister Reg = |
| 2703 RegX8632::getEncodedGPR(VarReg->getRegNum()); | 2535 RegX8632::getEncodedGPR(VarReg->getRegNum()); |
| 2704 if (Locked) { | 2536 if (Locked) { |
| 2705 Asm->lock(); | 2537 Asm->lock(); |
| 2706 } | 2538 } |
| 2707 Asm->xadd(Ty, Addr, Reg); | 2539 Asm->xadd(Ty, Addr, Reg); |
| 2708 emitIASBytes(Func, Asm, StartPosition); | |
| 2709 } | 2540 } |
| 2710 | 2541 |
| 2711 void InstX8632Xadd::dump(const Cfg *Func) const { | 2542 void InstX8632Xadd::dump(const Cfg *Func) const { |
| 2712 Ostream &Str = Func->getContext()->getStrDump(); | 2543 Ostream &Str = Func->getContext()->getStrDump(); |
| 2713 if (Locked) { | 2544 if (Locked) { |
| 2714 Str << "lock "; | 2545 Str << "lock "; |
| 2715 } | 2546 } |
| 2716 Type Ty = getSrc(0)->getType(); | 2547 Type Ty = getSrc(0)->getType(); |
| 2717 Str << "xadd." << Ty << " "; | 2548 Str << "xadd." << Ty << " "; |
| 2718 dumpSources(Func); | 2549 dumpSources(Func); |
| 2719 } | 2550 } |
| 2720 | 2551 |
| 2721 void InstX8632Xchg::emit(const Cfg *Func) const { | 2552 void InstX8632Xchg::emit(const Cfg *Func) const { |
| 2722 Ostream &Str = Func->getContext()->getStrEmit(); | 2553 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2723 Str << "\txchg" << getWidthString(getSrc(0)->getType()) << "\t"; | 2554 Str << "\txchg" << getWidthString(getSrc(0)->getType()) << "\t"; |
| 2724 getSrc(1)->emit(Func); | 2555 getSrc(1)->emit(Func); |
| 2725 Str << ", "; | 2556 Str << ", "; |
| 2726 getSrc(0)->emit(Func); | 2557 getSrc(0)->emit(Func); |
| 2727 } | 2558 } |
| 2728 | 2559 |
| 2729 void InstX8632Xchg::emitIAS(const Cfg *Func) const { | 2560 void InstX8632Xchg::emitIAS(const Cfg *Func) const { |
| 2730 assert(getSrcSize() == 2); | 2561 assert(getSrcSize() == 2); |
| 2731 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); | 2562 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 2732 intptr_t StartPosition = Asm->GetPosition(); | |
| 2733 Type Ty = getSrc(0)->getType(); | 2563 Type Ty = getSrc(0)->getType(); |
| 2734 const auto Mem = llvm::cast<OperandX8632Mem>(getSrc(0)); | 2564 const auto Mem = llvm::cast<OperandX8632Mem>(getSrc(0)); |
| 2735 assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); | 2565 assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); |
| 2736 const x86::Address Addr = Mem->toAsmAddress(Asm); | 2566 const x86::Address Addr = Mem->toAsmAddress(Asm); |
| 2737 const auto VarReg = llvm::cast<Variable>(getSrc(1)); | 2567 const auto VarReg = llvm::cast<Variable>(getSrc(1)); |
| 2738 assert(VarReg->hasReg()); | 2568 assert(VarReg->hasReg()); |
| 2739 const RegX8632::GPRRegister Reg = | 2569 const RegX8632::GPRRegister Reg = |
| 2740 RegX8632::getEncodedGPR(VarReg->getRegNum()); | 2570 RegX8632::getEncodedGPR(VarReg->getRegNum()); |
| 2741 Asm->xchg(Ty, Addr, Reg); | 2571 Asm->xchg(Ty, Addr, Reg); |
| 2742 emitIASBytes(Func, Asm, StartPosition); | |
| 2743 } | 2572 } |
| 2744 | 2573 |
| 2745 void InstX8632Xchg::dump(const Cfg *Func) const { | 2574 void InstX8632Xchg::dump(const Cfg *Func) const { |
| 2746 Ostream &Str = Func->getContext()->getStrDump(); | 2575 Ostream &Str = Func->getContext()->getStrDump(); |
| 2747 Type Ty = getSrc(0)->getType(); | 2576 Type Ty = getSrc(0)->getType(); |
| 2748 Str << "xchg." << Ty << " "; | 2577 Str << "xchg." << Ty << " "; |
| 2749 dumpSources(Func); | 2578 dumpSources(Func); |
| 2750 } | 2579 } |
| 2751 | 2580 |
| 2752 void OperandX8632Mem::emit(const Cfg *Func) const { | 2581 void OperandX8632Mem::emit(const Cfg *Func) const { |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2909 } | 2738 } |
| 2910 Str << "("; | 2739 Str << "("; |
| 2911 if (Func) | 2740 if (Func) |
| 2912 Var->dump(Func); | 2741 Var->dump(Func); |
| 2913 else | 2742 else |
| 2914 Var->dump(Str); | 2743 Var->dump(Str); |
| 2915 Str << ")"; | 2744 Str << ")"; |
| 2916 } | 2745 } |
| 2917 | 2746 |
| 2918 } // end of namespace Ice | 2747 } // end of namespace Ice |
| OLD | NEW |