Index: src/IceInstX8632.cpp |
diff --git a/src/IceInstX8632.cpp b/src/IceInstX8632.cpp |
index dbacd58a87bdcb65a911de3849a96ea7c20692c6..c0f929a1b0229feab03f79a58689aeb5b1240f6d 100644 |
--- a/src/IceInstX8632.cpp |
+++ b/src/IceInstX8632.cpp |
@@ -375,6 +375,33 @@ void emitIASBytes(const Cfg *Func, const x86::AssemblerX86 *Asm, |
} |
} |
+void emitIASBytesBranch(const Cfg *Func, const x86::AssemblerX86 *Asm, |
+ intptr_t StartPosition, const x86::Label *Label, |
+ const IceString &LabelName, bool Near) { |
+ // If this is a backward branch (label is bound), we're good and know |
+ // the offset. If this is a forward branch, then we can't actually emit |
+ // the thing as text in a streaming manner, because the fixup hasn't |
+ // happened yet. Instead, emit .long ($BranchLabel) - (. + 4), in that |
+ // case and let the external assembler take care of that fixup. |
+ if (Label->IsBound()) { |
+ emitIASBytes(Func, Asm, StartPosition); |
+ return; |
+ } |
+ const intptr_t FwdBranchSize = Near ? 1 : 4; |
+ const IceString FwdBranchDirective = Near ? ".byte" : ".long"; |
+ Ostream &Str = Func->getContext()->getStrEmit(); |
+ intptr_t EndPosition = Asm->GetPosition(); |
+ assert(EndPosition - StartPosition > FwdBranchSize); |
+ for (intptr_t i = StartPosition; i < EndPosition - FwdBranchSize; ++i) { |
+ Str << "\t.byte 0x"; |
+ Str.write_hex(Asm->LoadBuffer<uint8_t>(i)); |
+ Str << "\n"; |
+ } |
+ Str << "\t" << FwdBranchDirective << " " << LabelName << " - (. + " |
+ << FwdBranchSize << ")\n"; |
+ return; |
+} |
+ |
} // end of anonymous namespace |
void InstX8632::dump(const Cfg *Func) const { |
@@ -388,6 +415,15 @@ void InstX8632Label::emit(const Cfg *Func) const { |
Str << getName(Func) << ":\n"; |
} |
+void InstX8632Label::emitIAS(const Cfg *Func) const { |
+ x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
+ Asm->BindLocalLabel(Number); |
+ // TODO(jvoung): remove the the textual label once forward branch |
+ // fixups are used (and text assembler is not used). |
+ Ostream &Str = Func->getContext()->getStrEmit(); |
+ Str << getName(Func) << ":\n"; |
+} |
+ |
void InstX8632Label::dump(const Cfg *Func) const { |
Ostream &Str = Func->getContext()->getStrDump(); |
Str << getName(Func) << ":"; |
@@ -417,6 +453,47 @@ void InstX8632Br::emit(const Cfg *Func) const { |
} |
} |
+void InstX8632Br::emitIAS(const Cfg *Func) const { |
+ x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>(); |
+ intptr_t StartPosition = Asm->GetPosition(); |
+ if (Label) { |
+ x86::Label *L = Asm->GetOrCreateLocalLabel(Label->getNumber()); |
+ // In all these cases, local Labels should only be used for Near. |
+ const bool Near = true; |
+ if (Condition == CondX86::Br_None) { |
+ Asm->jmp(L, Near); |
+ } else { |
+ Asm->j(Condition, L, Near); |
+ } |
+ emitIASBytesBranch(Func, Asm, StartPosition, L, Label->getName(Func), Near); |
+ } else { |
+ // Pessimistically assume it's far. This only affects Labels that |
+ // are not Bound. |
+ const bool Near = false; |
+ if (Condition == CondX86::Br_None) { |
+ x86::Label *L = |
+ Asm->GetOrCreateCfgNodeLabel(getTargetFalse()->getIndex()); |
+ assert(!getTargetTrue()); |
+ Asm->jmp(L, Near); |
+ emitIASBytesBranch(Func, Asm, StartPosition, L, |
+ getTargetFalse()->getAsmName(), Near); |
+ } else { |
+ x86::Label *L = Asm->GetOrCreateCfgNodeLabel(getTargetTrue()->getIndex()); |
+ Asm->j(Condition, L, Near); |
+ emitIASBytesBranch(Func, Asm, StartPosition, L, |
+ getTargetTrue()->getAsmName(), Near); |
+ StartPosition = Asm->GetPosition(); |
+ if (getTargetFalse()) { |
+ x86::Label *L2 = |
+ Asm->GetOrCreateCfgNodeLabel(getTargetFalse()->getIndex()); |
+ Asm->jmp(L2, Near); |
+ emitIASBytesBranch(Func, Asm, StartPosition, L2, |
+ getTargetFalse()->getAsmName(), Near); |
+ } |
+ } |
+ } |
+} |
+ |
void InstX8632Br::dump(const Cfg *Func) const { |
Ostream &Str = Func->getContext()->getStrDump(); |
Str << "br "; |