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 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
193 if (TargetFalse == OldNode) { | 193 if (TargetFalse == OldNode) { |
194 TargetFalse = NewNode; | 194 TargetFalse = NewNode; |
195 return true; | 195 return true; |
196 } else if (TargetTrue == OldNode) { | 196 } else if (TargetTrue == OldNode) { |
197 TargetTrue = NewNode; | 197 TargetTrue = NewNode; |
198 return true; | 198 return true; |
199 } | 199 } |
200 return false; | 200 return false; |
201 } | 201 } |
202 | 202 |
| 203 InstX8632Jmp::InstX8632Jmp(Cfg *Func, Operand *Target) |
| 204 : InstX8632(Func, InstX8632::Jmp, 1, nullptr) { |
| 205 addSource(Target); |
| 206 } |
| 207 |
203 InstX8632Call::InstX8632Call(Cfg *Func, Variable *Dest, Operand *CallTarget) | 208 InstX8632Call::InstX8632Call(Cfg *Func, Variable *Dest, Operand *CallTarget) |
204 : InstX8632(Func, InstX8632::Call, 1, Dest) { | 209 : InstX8632(Func, InstX8632::Call, 1, Dest) { |
205 HasSideEffects = true; | 210 HasSideEffects = true; |
206 addSource(CallTarget); | 211 addSource(CallTarget); |
207 } | 212 } |
208 | 213 |
209 InstX8632Cmov::InstX8632Cmov(Cfg *Func, Variable *Dest, Operand *Source, | 214 InstX8632Cmov::InstX8632Cmov(Cfg *Func, Variable *Dest, Operand *Source, |
210 CondX86::BrCond Condition) | 215 CondX86::BrCond Condition) |
211 : InstX8632(Func, InstX8632::Cmov, 2, Dest), Condition(Condition) { | 216 : InstX8632(Func, InstX8632::Cmov, 2, Dest), Condition(Condition) { |
212 // The final result is either the original Dest, or Source, so mark | 217 // The final result is either the original Dest, or Source, so mark |
(...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
443 if (Label) { | 448 if (Label) { |
444 Str << ", label %" << Label->getName(Func); | 449 Str << ", label %" << Label->getName(Func); |
445 } else { | 450 } else { |
446 Str << ", label %" << getTargetTrue()->getName(); | 451 Str << ", label %" << getTargetTrue()->getName(); |
447 if (getTargetFalse()) { | 452 if (getTargetFalse()) { |
448 Str << ", label %" << getTargetFalse()->getName(); | 453 Str << ", label %" << getTargetFalse()->getName(); |
449 } | 454 } |
450 } | 455 } |
451 } | 456 } |
452 | 457 |
| 458 void InstX8632Jmp::emit(const Cfg *Func) const { |
| 459 if (!ALLOW_DUMP) |
| 460 return; |
| 461 Ostream &Str = Func->getContext()->getStrEmit(); |
| 462 assert(getSrcSize() == 1); |
| 463 Str << "\tjmp\t*"; |
| 464 getJmpTarget()->emit(Func); |
| 465 } |
| 466 |
| 467 void InstX8632Jmp::emitIAS(const Cfg *Func) const { |
| 468 // Note: Adapted (mostly copied) from InstX8632Call::emitIAS(). |
| 469 x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
| 470 Operand *Target = getJmpTarget(); |
| 471 if (const auto Var = llvm::dyn_cast<Variable>(Target)) { |
| 472 if (Var->hasReg()) { |
| 473 Asm->jmp(RegX8632::getEncodedGPR(Var->getRegNum())); |
| 474 } else { |
| 475 // The jmp instruction with a memory operand should be possible |
| 476 // to encode, but it isn't a valid sandboxed instruction, and |
| 477 // there shouldn't be a register allocation issue to jump |
| 478 // through a scratch register, so we don't really need to bother |
| 479 // implementing it. |
| 480 llvm::report_fatal_error("Assembler can't jmp to memory operand"); |
| 481 } |
| 482 } else if (const auto Mem = llvm::dyn_cast<OperandX8632Mem>(Target)) { |
| 483 assert(Mem->getSegmentRegister() == OperandX8632Mem::DefaultSegment); |
| 484 llvm::report_fatal_error("Assembler can't jmp to memory operand"); |
| 485 } else if (const auto CR = llvm::dyn_cast<ConstantRelocatable>(Target)) { |
| 486 assert(CR->getOffset() == 0 && "We only support jumping to a function"); |
| 487 Asm->jmp(CR); |
| 488 } else if (const auto Imm = llvm::dyn_cast<ConstantInteger32>(Target)) { |
| 489 // NaCl trampoline calls refer to an address within the sandbox directly. |
| 490 // This is usually only needed for non-IRT builds and otherwise not |
| 491 // very portable or stable. For this, we would use the 0xE8 opcode |
| 492 // (relative version of call) and there should be a PC32 reloc too. |
| 493 // The PC32 reloc will have symbol index 0, and the absolute address |
| 494 // would be encoded as an offset relative to the next instruction. |
| 495 // TODO(jvoung): Do we need to support this? |
| 496 (void)Imm; |
| 497 llvm::report_fatal_error("Unexpected jmp to absolute address"); |
| 498 } else { |
| 499 llvm::report_fatal_error("Unexpected operand type"); |
| 500 } |
| 501 } |
| 502 |
| 503 void InstX8632Jmp::dump(const Cfg *Func) const { |
| 504 if (!ALLOW_DUMP) |
| 505 return; |
| 506 Ostream &Str = Func->getContext()->getStrDump(); |
| 507 Str << "jmp "; |
| 508 getJmpTarget()->dump(Func); |
| 509 } |
| 510 |
453 void InstX8632Call::emit(const Cfg *Func) const { | 511 void InstX8632Call::emit(const Cfg *Func) const { |
454 if (!ALLOW_DUMP) | 512 if (!ALLOW_DUMP) |
455 return; | 513 return; |
456 Ostream &Str = Func->getContext()->getStrEmit(); | 514 Ostream &Str = Func->getContext()->getStrEmit(); |
457 assert(getSrcSize() == 1); | 515 assert(getSrcSize() == 1); |
458 Str << "\tcall\t"; | 516 Str << "\tcall\t"; |
459 if (const auto CallTarget = | 517 if (const auto CallTarget = |
460 llvm::dyn_cast<ConstantRelocatable>(getCallTarget())) { | 518 llvm::dyn_cast<ConstantRelocatable>(getCallTarget())) { |
461 // TODO(stichnot): All constant targets should suppress the '$', | 519 // TODO(stichnot): All constant targets should suppress the '$', |
462 // not just relocatables. | 520 // not just relocatables. |
(...skipping 2259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2722 Str << "xchg." << Ty << " "; | 2780 Str << "xchg." << Ty << " "; |
2723 dumpSources(Func); | 2781 dumpSources(Func); |
2724 } | 2782 } |
2725 | 2783 |
2726 void OperandX8632Mem::emit(const Cfg *Func) const { | 2784 void OperandX8632Mem::emit(const Cfg *Func) const { |
2727 if (!ALLOW_DUMP) | 2785 if (!ALLOW_DUMP) |
2728 return; | 2786 return; |
2729 Ostream &Str = Func->getContext()->getStrEmit(); | 2787 Ostream &Str = Func->getContext()->getStrEmit(); |
2730 if (SegmentReg != DefaultSegment) { | 2788 if (SegmentReg != DefaultSegment) { |
2731 assert(SegmentReg >= 0 && SegmentReg < SegReg_NUM); | 2789 assert(SegmentReg >= 0 && SegmentReg < SegReg_NUM); |
2732 Str << InstX8632SegmentRegNames[SegmentReg] << ":"; | 2790 Str << "%" << InstX8632SegmentRegNames[SegmentReg] << ":"; |
2733 } | 2791 } |
2734 // Emit as Offset(Base,Index,1<<Shift). | 2792 // Emit as Offset(Base,Index,1<<Shift). |
2735 // Offset is emitted without the leading '$'. | 2793 // Offset is emitted without the leading '$'. |
2736 // Omit the (Base,Index,1<<Shift) part if Base==nullptr. | 2794 // Omit the (Base,Index,1<<Shift) part if Base==nullptr. |
2737 if (!Offset) { | 2795 if (!Offset) { |
2738 // No offset, emit nothing. | 2796 // No offset, emit nothing. |
2739 } else if (const auto CI = llvm::dyn_cast<ConstantInteger32>(Offset)) { | 2797 } else if (const auto CI = llvm::dyn_cast<ConstantInteger32>(Offset)) { |
2740 if (CI->getValue()) | 2798 if (Base == nullptr || CI->getValue()) |
2741 // Emit a non-zero offset without a leading '$'. | 2799 // Emit a non-zero offset without a leading '$'. |
2742 Str << CI->getValue(); | 2800 Str << CI->getValue(); |
2743 } else if (const auto CR = llvm::dyn_cast<ConstantRelocatable>(Offset)) { | 2801 } else if (const auto CR = llvm::dyn_cast<ConstantRelocatable>(Offset)) { |
2744 CR->emitWithoutDollar(Func->getContext()); | 2802 CR->emitWithoutDollar(Func->getContext()); |
2745 } else { | 2803 } else { |
2746 llvm_unreachable("Invalid offset type for x86 mem operand"); | 2804 llvm_unreachable("Invalid offset type for x86 mem operand"); |
2747 } | 2805 } |
2748 | 2806 |
2749 if (Base) { | 2807 if (Base) { |
2750 Str << "("; | 2808 Str << "("; |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2887 } | 2945 } |
2888 Str << "("; | 2946 Str << "("; |
2889 if (Func) | 2947 if (Func) |
2890 Var->dump(Func); | 2948 Var->dump(Func); |
2891 else | 2949 else |
2892 Var->dump(Str); | 2950 Var->dump(Str); |
2893 Str << ")"; | 2951 Str << ")"; |
2894 } | 2952 } |
2895 | 2953 |
2896 } // end of namespace Ice | 2954 } // end of namespace Ice |
OLD | NEW |