emitIAS for fld and fstp
BUG=none
R=stichnot@chromium.org
Review URL: https://codereview.chromium.org/634333002
diff --git a/src/IceInstX8632.cpp b/src/IceInstX8632.cpp
index fd1f80d..d51eeca 100644
--- a/src/IceInstX8632.cpp
+++ b/src/IceInstX8632.cpp
@@ -1919,7 +1919,7 @@
assert(Dest->hasReg() && Src->hasReg());
x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>();
intptr_t StartPosition = Asm->GetPosition();
- Asm->movss(RegX8632::getEncodedXmm(Dest->getRegNum()),
+ Asm->movss(IceType_f32, RegX8632::getEncodedXmm(Dest->getRegNum()),
RegX8632::getEncodedXmm(Src->getRegNum()));
Ostream &Str = Func->getContext()->getStrEmit();
emitIASBytes(Str, Asm, StartPosition);
@@ -2006,6 +2006,38 @@
Str << "\n";
}
+void InstX8632Fld::emitIAS(const Cfg *Func) const {
+ x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>();
+ intptr_t StartPosition = Asm->GetPosition();
+ assert(getSrcSize() == 1);
+ const Operand *Src = getSrc(0);
+ Type Ty = Src->getType();
+ if (const auto Var = llvm::dyn_cast<Variable>(Src)) {
+ if (Var->hasReg()) {
+ // This is a physical xmm register, so we need to spill it to a
+ // temporary stack slot.
+ x86::Immediate Width(typeWidthInBytes(Ty));
+ Asm->sub(IceType_i32, RegX8632::Encoded_Reg_esp, Width);
+ x86::Address StackSlot = x86::Address(RegX8632::Encoded_Reg_esp, 0);
+ Asm->movss(Ty, StackSlot, RegX8632::getEncodedXmm(Var->getRegNum()));
+ Asm->fld(Ty, StackSlot);
+ Asm->add(IceType_i32, RegX8632::Encoded_Reg_esp, Width);
+ } else {
+ x86::Address StackAddr(static_cast<TargetX8632 *>(Func->getTarget())
+ ->stackVarToAsmOperand(Var));
+ Asm->fld(Ty, StackAddr);
+ }
+ } else if (const auto Mem = llvm::dyn_cast<OperandX8632Mem>(Src)) {
+ Asm->fld(Ty, Mem->toAsmAddress(Asm));
+ } else if (const auto Imm = llvm::dyn_cast<Constant>(Src)) {
+ Asm->fld(Ty, x86::Address::ofConstPool(Func->getContext(), Asm, Imm));
+ } else {
+ llvm_unreachable("Unexpected operand type");
+ }
+ Ostream &Str = Func->getContext()->getStrEmit();
+ emitIASBytes(Str, Asm, StartPosition);
+}
+
void InstX8632Fld::dump(const Cfg *Func) const {
Ostream &Str = Func->getContext()->getStrDump();
Str << "fld." << getSrc(0)->getType() << " ";
@@ -2015,6 +2047,10 @@
void InstX8632Fstp::emit(const Cfg *Func) const {
Ostream &Str = Func->getContext()->getStrEmit();
assert(getSrcSize() == 0);
+ // TODO(jvoung,stichnot): Utilize this by setting Dest to NULL to
+ // "partially" delete the fstp if the Dest is unused.
+ // Even if Dest is unused, the fstp should be kept for the SideEffects
+ // of popping the stack.
if (getDest() == NULL) {
Str << "\tfstp\tst(0)\n";
return;
@@ -2039,6 +2075,42 @@
Str << "\tadd\tesp, " << Width << "\n";
}
+void InstX8632Fstp::emitIAS(const Cfg *Func) const {
+ x86::AssemblerX86 *Asm = Func->getAssembler<x86::AssemblerX86>();
+ intptr_t StartPosition = Asm->GetPosition();
+ assert(getSrcSize() == 0);
+ const Variable *Dest = getDest();
+ // TODO(jvoung,stichnot): Utilize this by setting Dest to NULL to
+ // "partially" delete the fstp if the Dest is unused.
+ // Even if Dest is unused, the fstp should be kept for the SideEffects
+ // of popping the stack.
+ if (Dest == NULL) {
+ Asm->fstp(RegX8632::getEncodedSTReg(0));
+ Ostream &Str = Func->getContext()->getStrEmit();
+ emitIASBytes(Str, Asm, StartPosition);
+ return;
+ }
+ Type Ty = Dest->getType();
+ if (!Dest->hasReg()) {
+ x86::Address StackAddr(static_cast<TargetX8632 *>(Func->getTarget())
+ ->stackVarToAsmOperand(Dest));
+ Asm->fstp(Ty, StackAddr);
+ } else {
+ // Dest is a physical (xmm) register, so st(0) needs to go through
+ // memory. Hack this by creating a temporary stack slot, spilling
+ // st(0) there, loading it into the xmm register, and deallocating
+ // the stack slot.
+ x86::Immediate Width(typeWidthInBytes(Ty));
+ Asm->sub(IceType_i32, RegX8632::Encoded_Reg_esp, Width);
+ x86::Address StackSlot = x86::Address(RegX8632::Encoded_Reg_esp, 0);
+ Asm->fstp(Ty, StackSlot);
+ Asm->movss(Ty, RegX8632::getEncodedXmm(Dest->getRegNum()), StackSlot);
+ Asm->add(IceType_i32, RegX8632::Encoded_Reg_esp, Width);
+ }
+ Ostream &Str = Func->getContext()->getStrEmit();
+ emitIASBytes(Str, Asm, StartPosition);
+}
+
void InstX8632Fstp::dump(const Cfg *Func) const {
Ostream &Str = Func->getContext()->getStrDump();
dumpDest(Func);
diff --git a/src/IceInstX8632.def b/src/IceInstX8632.def
index 8e7df05..e48db41 100644
--- a/src/IceInstX8632.def
+++ b/src/IceInstX8632.def
@@ -88,6 +88,21 @@
X(SegReg_GS, "gs") \
//#define X(val, name)
+// X87 ST(n) registers.
+#define X87ST_REGX8632_TABLE \
+ /* enum value, encode, name */ \
+ X(X87ST_First, = 0, "st(0)") \
+ X(X87ST_0, = 0, "st(0)") \
+ X(X87ST_1, = 1, "st(1)") \
+ X(X87ST_2, = 2, "st(2)") \
+ X(X87ST_3, = 3, "st(3)") \
+ X(X87ST_4, = 4, "st(4)") \
+ X(X87ST_5, = 5, "st(5)") \
+ X(X87ST_6, = 6, "st(6)") \
+ X(X87ST_7, = 7, "st(7)") \
+ X(X87ST_Last, = 7, "st(7)") \
+//#define X(val, encode, name)
+
#define ICEINSTX8632BR_TABLE \
/* enum value, encode, opposite, dump, emit */ \
X(Br_o, = 0, Br_no, "o", "jo") \
diff --git a/src/IceInstX8632.h b/src/IceInstX8632.h
index abce706..96978d4 100644
--- a/src/IceInstX8632.h
+++ b/src/IceInstX8632.h
@@ -1352,6 +1352,7 @@
return new (Func->allocate<InstX8632Fld>()) InstX8632Fld(Func, Src);
}
void emit(const Cfg *Func) const override;
+ void emitIAS(const Cfg *Func) const override;
void dump(const Cfg *Func) const override;
static bool classof(const Inst *Inst) { return isClassof(Inst, Fld); }
@@ -1369,6 +1370,7 @@
return new (Func->allocate<InstX8632Fstp>()) InstX8632Fstp(Func, Dest);
}
void emit(const Cfg *Func) const override;
+ void emitIAS(const Cfg *Func) const override;
void dump(const Cfg *Func) const override;
static bool classof(const Inst *Inst) { return isClassof(Inst, Fstp); }
diff --git a/src/IceRegistersX8632.h b/src/IceRegistersX8632.h
index 851908c..86ace82 100644
--- a/src/IceRegistersX8632.h
+++ b/src/IceRegistersX8632.h
@@ -36,7 +36,7 @@
#undef X
};
-// An enum of GPR Registers. The enum value does match encoding used
+// An enum of GPR Registers. The enum value does match the encoding used
// to binary encode register operands in instructions.
enum GPRRegister {
#define X(val, encode, name, name16, name8, scratch, preserved, stackptr, \
@@ -47,7 +47,7 @@
Encoded_Not_GPR = -1
};
-// An enum of XMM Registers. The enum value does match encoding used
+// An enum of XMM Registers. The enum value does match the encoding used
// to binary encode register operands in instructions.
enum XmmRegister {
#define X(val, encode, name, name16, name8, scratch, preserved, stackptr, \
@@ -58,7 +58,7 @@
Encoded_Not_Xmm = -1
};
-// An enum of Byte Registers. The enum value does match encoding used
+// An enum of Byte Registers. The enum value does match the encoding used
// to binary encode register operands in instructions.
enum ByteRegister {
#define X(val, encode) Encoded_##val encode,
@@ -67,6 +67,15 @@
Encoded_Not_ByteReg = -1
};
+// An enum of X87 Stack Registers. The enum value does match the encoding used
+// to binary encode register operands in instructions.
+enum X87STRegister {
+#define X(val, encode, name) Encoded_##val encode,
+ X87ST_REGX8632_TABLE
+#undef X
+ Encoded_Not_X87STReg = -1
+};
+
static inline GPRRegister getEncodedGPR(int32_t RegNum) {
assert(Reg_GPR_First <= RegNum && RegNum <= Reg_GPR_Last);
return GPRRegister(RegNum - Reg_GPR_First);
@@ -91,6 +100,11 @@
return getEncodedGPR(RegNum);
}
+static inline X87STRegister getEncodedSTReg(int32_t RegNum) {
+ assert(Encoded_X87ST_First <= RegNum && RegNum <= Encoded_X87ST_Last);
+ return X87STRegister(RegNum);
+}
+
} // end of namespace RegX8632
} // end of namespace Ice
diff --git a/src/assembler_ia32.cpp b/src/assembler_ia32.cpp
index bc59ca8..6fc7026 100644
--- a/src/assembler_ia32.cpp
+++ b/src/assembler_ia32.cpp
@@ -272,25 +272,25 @@
EmitUint8(0xA4);
}
-void AssemblerX86::movss(XmmRegister dst, const Address &src) {
+void AssemblerX86::movss(Type Ty, XmmRegister dst, const Address &src) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
- EmitUint8(0xF3);
+ EmitUint8(isFloat32Asserting32Or64(Ty) ? 0xF3 : 0xF2);
EmitUint8(0x0F);
EmitUint8(0x10);
EmitOperand(dst, src);
}
-void AssemblerX86::movss(const Address &dst, XmmRegister src) {
+void AssemblerX86::movss(Type Ty, const Address &dst, XmmRegister src) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
- EmitUint8(0xF3);
+ EmitUint8(isFloat32Asserting32Or64(Ty) ? 0xF3 : 0xF2);
EmitUint8(0x0F);
EmitUint8(0x11);
EmitOperand(src, dst);
}
-void AssemblerX86::movss(XmmRegister dst, XmmRegister src) {
+void AssemblerX86::movss(Type Ty, XmmRegister dst, XmmRegister src) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
- EmitUint8(0xF3);
+ EmitUint8(isFloat32Asserting32Or64(Ty) ? 0xF3 : 0xF2);
EmitUint8(0x0F);
EmitUint8(0x11);
EmitXmmRegisterOperand(src, dst);
@@ -416,40 +416,22 @@
EmitOperand(dst, src);
}
-void AssemblerX86::flds(const Address &src) {
+void AssemblerX86::fld(Type Ty, const Address &src) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
- EmitUint8(0xD9);
+ EmitUint8(isFloat32Asserting32Or64(Ty) ? 0xD9 : 0xDD);
EmitOperand(0, src);
}
-void AssemblerX86::fstps(const Address &dst) {
+void AssemblerX86::fstp(Type Ty, const Address &dst) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
- EmitUint8(0xD9);
+ EmitUint8(isFloat32Asserting32Or64(Ty) ? 0xD9 : 0xDD);
EmitOperand(3, dst);
}
-void AssemblerX86::movsd(XmmRegister dst, const Address &src) {
+void AssemblerX86::fstp(X87STRegister st) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
- EmitUint8(0xF2);
- EmitUint8(0x0F);
- EmitUint8(0x10);
- EmitOperand(dst, src);
-}
-
-void AssemblerX86::movsd(const Address &dst, XmmRegister src) {
- AssemblerBuffer::EnsureCapacity ensured(&buffer_);
- EmitUint8(0xF2);
- EmitUint8(0x0F);
- EmitUint8(0x11);
- EmitOperand(src, dst);
-}
-
-void AssemblerX86::movsd(XmmRegister dst, XmmRegister src) {
- AssemblerBuffer::EnsureCapacity ensured(&buffer_);
- EmitUint8(0xF2);
- EmitUint8(0x0F);
- EmitUint8(0x11);
- EmitXmmRegisterOperand(src, dst);
+ EmitUint8(0xDD);
+ EmitUint8(0xD8 + st);
}
void AssemblerX86::movaps(XmmRegister dst, XmmRegister src) {
@@ -1236,18 +1218,6 @@
EmitUint8(static_cast<uint8_t>(mode) | 0x8);
}
-void AssemblerX86::fldl(const Address &src) {
- AssemblerBuffer::EnsureCapacity ensured(&buffer_);
- EmitUint8(0xDD);
- EmitOperand(0, src);
-}
-
-void AssemblerX86::fstpl(const Address &dst) {
- AssemblerBuffer::EnsureCapacity ensured(&buffer_);
- EmitUint8(0xDD);
- EmitOperand(3, dst);
-}
-
void AssemblerX86::fnstcw(const Address &dst) {
AssemblerBuffer::EnsureCapacity ensured(&buffer_);
EmitUint8(0xD9);
diff --git a/src/assembler_ia32.h b/src/assembler_ia32.h
index 22ecb6e..676f4f6 100644
--- a/src/assembler_ia32.h
+++ b/src/assembler_ia32.h
@@ -36,6 +36,7 @@
using RegX8632::GPRRegister;
using RegX8632::XmmRegister;
using RegX8632::ByteRegister;
+using RegX8632::X87STRegister;
namespace x86 {
@@ -455,9 +456,9 @@
void rep_movsb();
- void movss(XmmRegister dst, const Address &src);
- void movss(const Address &dst, XmmRegister src);
- void movss(XmmRegister dst, XmmRegister src);
+ void movss(Type Ty, XmmRegister dst, const Address &src);
+ void movss(Type Ty, const Address &dst, XmmRegister src);
+ void movss(Type Ty, XmmRegister dst, XmmRegister src);
void movd(XmmRegister dst, GPRRegister src);
void movd(XmmRegister dst, const Address &src);
@@ -477,10 +478,6 @@
void divss(Type Ty, XmmRegister dst, XmmRegister src);
void divss(Type Ty, XmmRegister dst, const Address &src);
- void movsd(XmmRegister dst, const Address &src);
- void movsd(const Address &dst, XmmRegister src);
- void movsd(XmmRegister dst, XmmRegister src);
-
void movaps(XmmRegister dst, XmmRegister src);
void movups(XmmRegister dst, XmmRegister src);
@@ -598,11 +595,9 @@
};
void roundsd(XmmRegister dst, XmmRegister src, RoundingMode mode);
- void flds(const Address &src);
- void fstps(const Address &dst);
-
- void fldl(const Address &src);
- void fstpl(const Address &dst);
+ void fld(Type Ty, const Address &src);
+ void fstp(Type Ty, const Address &dst);
+ void fstp(X87STRegister st);
void fnstcw(const Address &dst);
void fldcw(const Address &src);
diff --git a/tests_lit/llvm2ice_tests/fp.pnacl.ll b/tests_lit/llvm2ice_tests/fp.pnacl.ll
index 8376ebd..474961a 100644
--- a/tests_lit/llvm2ice_tests/fp.pnacl.ll
+++ b/tests_lit/llvm2ice_tests/fp.pnacl.ll
@@ -416,7 +416,7 @@
; CALLTARGETS-LABEL: signed64ToDouble
; CHECK: call -4
; CALLTARGETS: call cvtsi64tod
-; CHECK: fstp
+; CHECK: fstp qword
define internal float @signed64ToFloat(i64 %a) {
entry:
@@ -427,7 +427,7 @@
; CALLTARGETS-LABEL: signed64ToFloat
; CHECK: call -4
; CALLTARGETS: call cvtsi64tof
-; CHECK: fstp
+; CHECK: fstp dword
define internal double @unsigned64ToDouble(i64 %a) {
entry:
@@ -500,7 +500,7 @@
; CALLTARGETS-LABEL: unsigned32ToDouble
; CHECK: call -4
; CALLTARGETS: call cvtui32tod
-; CHECK: fstp
+; CHECK: fstp qword
define internal float @unsigned32ToFloat(i32 %a) {
entry:
@@ -511,7 +511,7 @@
; CALLTARGETS-LABEL: unsigned32ToFloat
; CHECK: call -4
; CALLTARGETS: call cvtui32tof
-; CHECK: fstp
+; CHECK: fstp dword
define internal double @signed16ToDouble(i32 %a) {
entry:
@@ -521,7 +521,7 @@
}
; CHECK-LABEL: signed16ToDouble
; CHECK: cvtsi2sd
-; CHECK: fld
+; CHECK: fld qword
define internal float @signed16ToFloat(i32 %a) {
entry:
@@ -531,7 +531,7 @@
}
; CHECK-LABEL: signed16ToFloat
; CHECK: cvtsi2ss
-; CHECK: fld
+; CHECK: fld dword
define internal double @unsigned16ToDouble(i32 %a) {
entry: