1 //===- subzero/unittest/AssemblerX8632/X87.cpp ----------------------------===//
2 //
3 // The Subzero Code Generator
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 #include "AssemblerX8632/TestUtil.h"
10
11 namespace Ice {
12 namespace X8632 {
13 namespace Test {
14 namespace {
15
TEST_F(AssemblerX8632LowLevelTest,Fld)16 TEST_F(AssemblerX8632LowLevelTest, Fld) {
17 __ fld(IceType_f32,
18 Address(GPRRegister::Encoded_Reg_ebp, 1, AssemblerFixup::NoFixup));
19 __ fld(IceType_f64, Address(GPRRegister::Encoded_Reg_ebp, 0x10000,
20 AssemblerFixup::NoFixup));
21
22 constexpr size_t ByteCount = 9;
23 ASSERT_EQ(ByteCount, codeBytesSize());
24
25 constexpr uint8_t Fld32Opcode = 0xd9;
26 constexpr uint8_t Fld32ModRM = (/*mod*/ 1 << 6) | (/*reg*/ 0 << 3) |
27 (/*rm*/ GPRRegister::Encoded_Reg_ebp);
28 constexpr uint8_t Fld64Opcode = 0xdd;
29 constexpr uint8_t Fld64ModRM = (/*mod*/ 2 << 6) | (/*reg*/ 0 << 3) |
30 (/*rm*/ GPRRegister::Encoded_Reg_ebp);
31 verifyBytes<ByteCount>(codeBytes(), Fld32Opcode, Fld32ModRM, 0x01,
32 Fld64Opcode, Fld64ModRM, 0x00, 0x00, 0x01, 0x00);
33 }
34
TEST_F(AssemblerX8632LowLevelTest,FstpAddr)35 TEST_F(AssemblerX8632LowLevelTest, FstpAddr) {
36 __ fstp(IceType_f32,
37 Address(GPRRegister::Encoded_Reg_ebp, 1, AssemblerFixup::NoFixup));
38 __ fstp(IceType_f64, Address(GPRRegister::Encoded_Reg_ebp, 0x10000,
39 AssemblerFixup::NoFixup));
40
41 constexpr size_t ByteCount = 9;
42 ASSERT_EQ(ByteCount, codeBytesSize());
43
44 constexpr uint8_t Fld32Opcode = 0xd9;
45 constexpr uint8_t Fld32ModRM = (/*mod*/ 1 << 6) | (/*reg*/ 3 << 3) |
46 (/*rm*/ GPRRegister::Encoded_Reg_ebp);
47 constexpr uint8_t Fld64Opcode = 0xdd;
48 constexpr uint8_t Fld64ModRM = (/*mod*/ 2 << 6) | (/*reg*/ 3 << 3) |
49 (/*rm*/ GPRRegister::Encoded_Reg_ebp);
50 verifyBytes<ByteCount>(codeBytes(), Fld32Opcode, Fld32ModRM, 0x01,
51 Fld64Opcode, Fld64ModRM, 0x00, 0x00, 0x01, 0x00);
52 }
53
TEST_F(AssemblerX8632LowLevelTest,Fincstp)54 TEST_F(AssemblerX8632LowLevelTest, Fincstp) {
55 __ fincstp();
56
57 constexpr size_t ByteCount = 2;
58 ASSERT_EQ(ByteCount, codeBytesSize());
59
60 verifyBytes<ByteCount>(codeBytes(), 0xD9, 0XF7);
61 }
62
TEST_F(AssemblerX8632LowLevelTest,FnstcwAddr)63 TEST_F(AssemblerX8632LowLevelTest, FnstcwAddr) {
64 __ fnstcw(
65 Address(GPRRegister::Encoded_Reg_ebp, 0x12345, AssemblerFixup::NoFixup));
66
67 constexpr size_t ByteCount = 6;
68 ASSERT_EQ(ByteCount, codeBytesSize());
69
70 constexpr uint8_t Opcode = 0xd9;
71 constexpr uint8_t ModRM = (/*mod*/ 2 << 6) | (/*reg*/ 7 << 3) |
72 (/*rm*/ GPRRegister::Encoded_Reg_ebp);
73 verifyBytes<ByteCount>(codeBytes(), Opcode, ModRM, 0x45, 0x23, 0x01, 0x00);
74 }
75
TEST_F(AssemblerX8632LowLevelTest,FldcwAddr)76 TEST_F(AssemblerX8632LowLevelTest, FldcwAddr) {
77 __ fldcw(
78 Address(GPRRegister::Encoded_Reg_ebp, 0x12345, AssemblerFixup::NoFixup));
79
80 constexpr size_t ByteCount = 6;
81 ASSERT_EQ(ByteCount, codeBytesSize());
82
83 constexpr uint8_t Opcode = 0xd9;
84 constexpr uint8_t ModRM = (/*mod*/ 2 << 6) | (/*reg*/ 5 << 3) |
85 (/*rm*/ GPRRegister::Encoded_Reg_ebp);
86 verifyBytes<ByteCount>(codeBytes(), Opcode, ModRM, 0x45, 0x23, 0x01, 0x00);
87 }
88
TEST_F(AssemblerX8632Test,FstpSt)89 TEST_F(AssemblerX8632Test, FstpSt) {
90 #define TestFstpSt(Size, MemorySize, Type) \
91 do { \
92 const uint32_t T1 = allocate##MemorySize(); \
93 const Type OldValue1 = -1.0f; \
94 const uint32_t T2 = allocate##MemorySize(); \
95 const Type OldValue2 = -2.0f; \
96 const uint32_t T3 = allocate##MemorySize(); \
97 const Type OldValue3 = -3.0f; \
98 const uint32_t T4 = allocate##MemorySize(); \
99 const Type OldValue4 = -4.0f; \
100 const uint32_t T5 = allocate##MemorySize(); \
101 const Type OldValue5 = -5.0f; \
102 const uint32_t T6 = allocate##MemorySize(); \
103 const Type OldValue6 = -6.0f; \
104 const uint32_t T7 = allocate##MemorySize(); \
105 const Type OldValue7 = -7.0f; \
106 \
107 const uint32_t N7 = allocate##MemorySize(); \
108 constexpr Type NewValue7 = 777.77f; \
109 const uint32_t N6 = allocate##MemorySize(); \
110 constexpr Type NewValue6 = 666.66f; \
111 const uint32_t N5 = allocate##MemorySize(); \
112 constexpr Type NewValue5 = 555.55f; \
113 const uint32_t N4 = allocate##MemorySize(); \
114 constexpr Type NewValue4 = 444.44f; \
115 const uint32_t N3 = allocate##MemorySize(); \
116 constexpr Type NewValue3 = 333.33f; \
117 const uint32_t N2 = allocate##MemorySize(); \
118 constexpr Type NewValue2 = 222.22f; \
119 const uint32_t N1 = allocate##MemorySize(); \
120 constexpr Type NewValue1 = 111.11f; \
121 \
122 __ fincstp(); \
123 __ fincstp(); \
124 __ fincstp(); \
125 __ fincstp(); \
126 __ fincstp(); \
127 __ fincstp(); \
128 __ fincstp(); \
129 \
130 __ fld(IceType_f##Size, dwordAddress(N7)); \
131 __ fstp(X87STRegister::Encoded_X87ST_7); \
132 __ fld(IceType_f##Size, dwordAddress(N6)); \
133 __ fstp(X87STRegister::Encoded_X87ST_6); \
134 __ fld(IceType_f##Size, dwordAddress(N5)); \
135 __ fstp(X87STRegister::Encoded_X87ST_5); \
136 __ fld(IceType_f##Size, dwordAddress(N4)); \
137 __ fstp(X87STRegister::Encoded_X87ST_4); \
138 __ fld(IceType_f##Size, dwordAddress(N3)); \
139 __ fstp(X87STRegister::Encoded_X87ST_3); \
140 __ fld(IceType_f##Size, dwordAddress(N2)); \
141 __ fstp(X87STRegister::Encoded_X87ST_2); \
142 __ fld(IceType_f##Size, dwordAddress(N1)); \
143 __ fstp(X87STRegister::Encoded_X87ST_1); \
144 \
145 __ fstp(IceType_f##Size, dwordAddress(T1)); \
146 __ fstp(IceType_f##Size, dwordAddress(T2)); \
147 __ fstp(IceType_f##Size, dwordAddress(T3)); \
148 __ fstp(IceType_f##Size, dwordAddress(T4)); \
149 __ fstp(IceType_f##Size, dwordAddress(T5)); \
150 __ fstp(IceType_f##Size, dwordAddress(T6)); \
151 __ fstp(IceType_f##Size, dwordAddress(T7)); \
152 \
153 AssembledTest test = assemble(); \
154 test.set##MemorySize##To(T1, OldValue1); \
155 test.set##MemorySize##To(N1, NewValue1); \
156 test.set##MemorySize##To(T2, OldValue2); \
157 test.set##MemorySize##To(N2, NewValue2); \
158 test.set##MemorySize##To(T3, OldValue3); \
159 test.set##MemorySize##To(N3, NewValue3); \
160 test.set##MemorySize##To(T4, OldValue4); \
161 test.set##MemorySize##To(N4, NewValue4); \
162 test.set##MemorySize##To(T5, OldValue5); \
163 test.set##MemorySize##To(N5, NewValue5); \
164 test.set##MemorySize##To(T6, OldValue6); \
165 test.set##MemorySize##To(N6, NewValue6); \
166 test.set##MemorySize##To(T7, OldValue7); \
167 test.set##MemorySize##To(N7, NewValue7); \
168 \
169 test.run(); \
170 \
171 ASSERT_FLOAT_EQ(NewValue1, test.contentsOf##MemorySize<Type>(T1)) \
172 << "(" #Size ", " #MemorySize ", " #Type ")"; \
173 ASSERT_FLOAT_EQ(NewValue1, test.contentsOf##MemorySize<Type>(N1)) \
174 << "(" #Size ", " #MemorySize ", " #Type ")"; \
175 ASSERT_FLOAT_EQ(NewValue2, test.contentsOf##MemorySize<Type>(T2)) \
176 << "(" #Size ", " #MemorySize ", " #Type ")"; \
177 ASSERT_FLOAT_EQ(NewValue2, test.contentsOf##MemorySize<Type>(N2)) \
178 << "(" #Size ", " #MemorySize ", " #Type ")"; \
179 ASSERT_FLOAT_EQ(NewValue3, test.contentsOf##MemorySize<Type>(T3)) \
180 << "(" #Size ", " #MemorySize ", " #Type ")"; \
181 ASSERT_FLOAT_EQ(NewValue3, test.contentsOf##MemorySize<Type>(N3)) \
182 << "(" #Size ", " #MemorySize ", " #Type ")"; \
183 ASSERT_FLOAT_EQ(NewValue4, test.contentsOf##MemorySize<Type>(T4)) \
184 << "(" #Size ", " #MemorySize ", " #Type ")"; \
185 ASSERT_FLOAT_EQ(NewValue4, test.contentsOf##MemorySize<Type>(N4)) \
186 << "(" #Size ", " #MemorySize ", " #Type ")"; \
187 ASSERT_FLOAT_EQ(NewValue5, test.contentsOf##MemorySize<Type>(T5)) \
188 << "(" #Size ", " #MemorySize ", " #Type ")"; \
189 ASSERT_FLOAT_EQ(NewValue5, test.contentsOf##MemorySize<Type>(N5)) \
190 << "(" #Size ", " #MemorySize ", " #Type ")"; \
191 ASSERT_FLOAT_EQ(NewValue6, test.contentsOf##MemorySize<Type>(T6)) \
192 << "(" #Size ", " #MemorySize ", " #Type ")"; \
193 ASSERT_FLOAT_EQ(NewValue6, test.contentsOf##MemorySize<Type>(N6)) \
194 << "(" #Size ", " #MemorySize ", " #Type ")"; \
195 ASSERT_FLOAT_EQ(NewValue7, test.contentsOf##MemorySize<Type>(T7)) \
196 << "(" #Size ", " #MemorySize ", " #Type ")"; \
197 ASSERT_FLOAT_EQ(NewValue7, test.contentsOf##MemorySize<Type>(N7)) \
198 << "(" #Size ", " #MemorySize ", " #Type ")"; \
199 \
200 reset(); \
201 } while (0)
202
203 TestFstpSt(32, Dword, float);
204 TestFstpSt(64, Qword, double);
205
206 #undef TestFstpSt
207 }
208
TEST_F(AssemblerX8632Test,Fild)209 TEST_F(AssemblerX8632Test, Fild) {
210 #define TestFild(OperandType, Size, MemorySize, FpType, IntType) \
211 do { \
212 const uint32_t T0 = allocate##MemorySize(); \
213 constexpr IntType V0 = 0x1234; \
214 \
215 __ fild##OperandType(dwordAddress(T0)); \
216 __ fstp(IceType_f##Size, dwordAddress(T0)); \
217 \
218 AssembledTest test = assemble(); \
219 \
220 test.set##MemorySize##To(T0, V0); \
221 test.run(); \
222 \
223 ASSERT_FLOAT_EQ(static_cast<FpType>(V0), \
224 test.contentsOf##MemorySize<FpType>(T0)) \
225 << "(" #OperandType ", " #Size ", " #MemorySize ", " #FpType \
226 ", " #IntType ")"; \
227 \
228 reset(); \
229 } while (0)
230
231 TestFild(s, 32, Dword, float, uint32_t);
232 TestFild(l, 64, Qword, double, uint64_t);
233 #undef TestFild
234 }
235
TEST_F(AssemblerX8632Test,Fistp)236 TEST_F(AssemblerX8632Test, Fistp) {
237 #define TestFistp(OperandType, Size, MemorySize, FpType, IntType) \
238 do { \
239 const uint32_t T0 = allocate##MemorySize(); \
240 constexpr IntType V0 = 0x1234; \
241 const uint32_t T1 = allocate##MemorySize(); \
242 constexpr IntType V1 = 0xFFFF; \
243 \
244 __ fild##OperandType(dwordAddress(T0)); \
245 __ fistp##OperandType(dwordAddress(T1)); \
246 \
247 AssembledTest test = assemble(); \
248 \
249 test.set##MemorySize##To(T0, V0); \
250 test.set##MemorySize##To(T1, V1); \
251 test.run(); \
252 \
253 ASSERT_EQ(static_cast<IntType>(V0), \
254 test.contentsOf##MemorySize<IntType>(T0)) \
255 << "(" #OperandType ", " #Size ", " #MemorySize ", " #FpType \
256 ", " #IntType ")"; \
257 ASSERT_EQ(static_cast<IntType>(V0), \
258 test.contentsOf##MemorySize<IntType>(T1)) \
259 << "(" #OperandType ", " #Size ", " #MemorySize ", " #FpType \
260 ", " #IntType ")"; \
261 \
262 reset(); \
263 } while (0)
264
265 TestFistp(s, 32, Dword, float, uint32_t);
266 TestFistp(l, 64, Qword, double, uint64_t);
267 #undef TestFistp
268 }
269
270 } // end of anonymous namespace
271 } // end of namespace Test
272 } // end of namespace X8632
273 } // end of namespace Ice
274