1// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
4
5#include "vm/globals.h"
6#if defined(TARGET_ARCH_X64)
7
8#include "vm/compiler/assembler/assembler.h"
9#include "vm/cpu.h"
10#include "vm/os.h"
11#include "vm/unit_test.h"
12#include "vm/virtual_memory.h"
13
14namespace dart {
15namespace compiler {
16
17#define __ assembler->
18
19#if defined(PRODUCT)
20#define EXPECT_DISASSEMBLY(expected)
21#define EXPECT_DISASSEMBLY_ENDS_WITH(expected)
22#define EXPECT_DISASSEMBLY_NOT_WINDOWS(expected)
23#define EXPECT_DISASSEMBLY_NOT_WINDOWS_ENDS_WITH(expected)
24#else
25#define EXPECT_DISASSEMBLY(expected) \
26 EXPECT_STREQ(expected, test->BlankedDisassembly())
27#define EXPECT_DISASSEMBLY_ENDS_WITH(expected_arg) \
28 char* disassembly = test->BlankedDisassembly(); \
29 const char* expected = expected_arg; \
30 intptr_t dis_len = strlen(disassembly); \
31 intptr_t exp_len = strlen(expected); \
32 EXPECT_GT(dis_len, exp_len); \
33 EXPECT_STREQ(expected, disassembly + dis_len - exp_len);
34#if defined(TARGET_OS_WINDOWS)
35// Windows has different calling conventions on x64, which means the
36// disassembly looks different on some tests. We skip testing the
37// disassembly output for those tests on Windows.
38#define EXPECT_DISASSEMBLY_NOT_WINDOWS(expected)
39#define EXPECT_DISASSEMBLY_NOT_WINDOWS_ENDS_WITH(expected)
40#else
41#define EXPECT_DISASSEMBLY_NOT_WINDOWS(expected) EXPECT_DISASSEMBLY(expected)
42#define EXPECT_DISASSEMBLY_NOT_WINDOWS_ENDS_WITH(expected) \
43 EXPECT_DISASSEMBLY_ENDS_WITH(expected)
44#endif
45#endif
46
47ASSEMBLER_TEST_GENERATE(ReadArgument, assembler) {
48 __ pushq(CallingConventions::kArg1Reg);
49 __ movq(RAX, Address(RSP, 0));
50 __ popq(RDX);
51 __ ret();
52}
53
54ASSEMBLER_TEST_RUN(ReadArgument, test) {
55 typedef int64_t (*ReadArgumentCode)(int64_t n);
56 ReadArgumentCode id = reinterpret_cast<ReadArgumentCode>(test->entry());
57 EXPECT_EQ(42, id(42));
58 EXPECT_EQ(87, id(87));
59 static const int64_t kLargeConstant = 0x1234567812345678LL;
60 EXPECT_EQ(kLargeConstant, id(kLargeConstant));
61 EXPECT_DISASSEMBLY_NOT_WINDOWS(
62 "push rdi\n"
63 "movq rax,[rsp]\n"
64 "pop rdx\n"
65 "ret\n");
66}
67
68ASSEMBLER_TEST_GENERATE(AddressingModes, assembler) {
69 __ movq(RAX, Address(RSP, 0));
70 __ movq(RAX, Address(RBP, 0));
71 __ movq(RAX, Address(RAX, 0));
72 __ movq(RAX, Address(R10, 0));
73 __ movq(RAX, Address(R12, 0));
74 __ movq(RAX, Address(R13, 0));
75 __ movq(R10, Address(RAX, 0));
76
77 __ movq(RAX, Address(RSP, target::kWordSize));
78 __ movq(RAX, Address(RBP, target::kWordSize));
79 __ movq(RAX, Address(RAX, target::kWordSize));
80 __ movq(RAX, Address(R10, target::kWordSize));
81 __ movq(RAX, Address(R12, target::kWordSize));
82 __ movq(RAX, Address(R13, target::kWordSize));
83
84 __ movq(RAX, Address(RSP, -target::kWordSize));
85 __ movq(RAX, Address(RBP, -target::kWordSize));
86 __ movq(RAX, Address(RAX, -target::kWordSize));
87 __ movq(RAX, Address(R10, -target::kWordSize));
88 __ movq(RAX, Address(R12, -target::kWordSize));
89 __ movq(RAX, Address(R13, -target::kWordSize));
90
91 __ movq(RAX, Address(RSP, 256 * target::kWordSize));
92 __ movq(RAX, Address(RBP, 256 * target::kWordSize));
93 __ movq(RAX, Address(RAX, 256 * target::kWordSize));
94 __ movq(RAX, Address(R10, 256 * target::kWordSize));
95 __ movq(RAX, Address(R12, 256 * target::kWordSize));
96 __ movq(RAX, Address(R13, 256 * target::kWordSize));
97
98 __ movq(RAX, Address(RSP, -256 * target::kWordSize));
99 __ movq(RAX, Address(RBP, -256 * target::kWordSize));
100 __ movq(RAX, Address(RAX, -256 * target::kWordSize));
101 __ movq(RAX, Address(R10, -256 * target::kWordSize));
102 __ movq(RAX, Address(R12, -256 * target::kWordSize));
103 __ movq(RAX, Address(R13, -256 * target::kWordSize));
104
105 __ movq(RAX, Address(RAX, TIMES_1, 0));
106 __ movq(RAX, Address(RAX, TIMES_2, 0));
107 __ movq(RAX, Address(RAX, TIMES_4, 0));
108 __ movq(RAX, Address(RAX, TIMES_8, 0));
109
110 __ movq(RAX, Address(RBP, TIMES_2, 0));
111 __ movq(RAX, Address(RAX, TIMES_2, 0));
112 __ movq(RAX, Address(R10, TIMES_2, 0));
113 __ movq(RAX, Address(R12, TIMES_2, 0));
114 __ movq(RAX, Address(R13, TIMES_2, 0));
115
116 __ movq(RAX, Address(RBP, TIMES_2, target::kWordSize));
117 __ movq(RAX, Address(RAX, TIMES_2, target::kWordSize));
118 __ movq(RAX, Address(R10, TIMES_2, target::kWordSize));
119 __ movq(RAX, Address(R12, TIMES_2, target::kWordSize));
120 __ movq(RAX, Address(R13, TIMES_2, target::kWordSize));
121
122 __ movq(RAX, Address(RBP, TIMES_2, 256 * target::kWordSize));
123 __ movq(RAX, Address(RAX, TIMES_2, 256 * target::kWordSize));
124 __ movq(RAX, Address(R10, TIMES_2, 256 * target::kWordSize));
125 __ movq(RAX, Address(R12, TIMES_2, 256 * target::kWordSize));
126 __ movq(RAX, Address(R13, TIMES_2, 256 * target::kWordSize));
127
128 __ movq(RAX, Address(RAX, RBP, TIMES_2, 0));
129 __ movq(RAX, Address(RAX, RAX, TIMES_2, 0));
130 __ movq(RAX, Address(RAX, R10, TIMES_2, 0));
131 __ movq(RAX, Address(RAX, R12, TIMES_2, 0));
132 __ movq(RAX, Address(RAX, R13, TIMES_2, 0));
133
134 __ movq(RAX, Address(RBP, RBP, TIMES_2, 0));
135 __ movq(RAX, Address(RBP, RAX, TIMES_2, 0));
136 __ movq(RAX, Address(RBP, R10, TIMES_2, 0));
137 __ movq(RAX, Address(RBP, R12, TIMES_2, 0));
138 __ movq(RAX, Address(RBP, R13, TIMES_2, 0));
139
140 __ movq(RAX, Address(RSP, RBP, TIMES_2, 0));
141 __ movq(RAX, Address(RSP, RAX, TIMES_2, 0));
142 __ movq(RAX, Address(RSP, R10, TIMES_2, 0));
143 __ movq(RAX, Address(RSP, R12, TIMES_2, 0));
144 __ movq(RAX, Address(RSP, R13, TIMES_2, 0));
145
146 __ movq(RAX, Address(R10, RBP, TIMES_2, 0));
147 __ movq(RAX, Address(R10, RAX, TIMES_2, 0));
148 __ movq(RAX, Address(R10, R10, TIMES_2, 0));
149 __ movq(RAX, Address(R10, R12, TIMES_2, 0));
150 __ movq(RAX, Address(R10, R13, TIMES_2, 0));
151
152 __ movq(RAX, Address(R12, RBP, TIMES_2, 0));
153 __ movq(RAX, Address(R12, RAX, TIMES_2, 0));
154 __ movq(RAX, Address(R12, R10, TIMES_2, 0));
155 __ movq(RAX, Address(R12, R12, TIMES_2, 0));
156 __ movq(RAX, Address(R12, R13, TIMES_2, 0));
157
158 __ movq(RAX, Address(R13, RBP, TIMES_2, 0));
159 __ movq(RAX, Address(R13, RAX, TIMES_2, 0));
160 __ movq(RAX, Address(R13, R10, TIMES_2, 0));
161 __ movq(RAX, Address(R13, R12, TIMES_2, 0));
162 __ movq(RAX, Address(R13, R13, TIMES_2, 0));
163
164 __ movq(RAX, Address(RAX, RBP, TIMES_2, target::kWordSize));
165 __ movq(RAX, Address(RAX, RAX, TIMES_2, target::kWordSize));
166 __ movq(RAX, Address(RAX, R10, TIMES_2, target::kWordSize));
167 __ movq(RAX, Address(RAX, R12, TIMES_2, target::kWordSize));
168 __ movq(RAX, Address(RAX, R13, TIMES_2, target::kWordSize));
169
170 __ movq(RAX, Address(RBP, RBP, TIMES_2, target::kWordSize));
171 __ movq(RAX, Address(RBP, RAX, TIMES_2, target::kWordSize));
172 __ movq(RAX, Address(RBP, R10, TIMES_2, target::kWordSize));
173 __ movq(RAX, Address(RBP, R12, TIMES_2, target::kWordSize));
174 __ movq(RAX, Address(RBP, R13, TIMES_2, target::kWordSize));
175
176 __ movq(RAX, Address(RSP, RBP, TIMES_2, target::kWordSize));
177 __ movq(RAX, Address(RSP, RAX, TIMES_2, target::kWordSize));
178 __ movq(RAX, Address(RSP, R10, TIMES_2, target::kWordSize));
179 __ movq(RAX, Address(RSP, R12, TIMES_2, target::kWordSize));
180 __ movq(RAX, Address(RSP, R13, TIMES_2, target::kWordSize));
181
182 __ movq(RAX, Address(R10, RBP, TIMES_2, target::kWordSize));
183 __ movq(RAX, Address(R10, RAX, TIMES_2, target::kWordSize));
184 __ movq(RAX, Address(R10, R10, TIMES_2, target::kWordSize));
185 __ movq(RAX, Address(R10, R12, TIMES_2, target::kWordSize));
186 __ movq(RAX, Address(R10, R13, TIMES_2, target::kWordSize));
187
188 __ movq(RAX, Address(R12, RBP, TIMES_2, target::kWordSize));
189 __ movq(RAX, Address(R12, RAX, TIMES_2, target::kWordSize));
190 __ movq(RAX, Address(R12, R10, TIMES_2, target::kWordSize));
191 __ movq(RAX, Address(R12, R12, TIMES_2, target::kWordSize));
192 __ movq(RAX, Address(R12, R13, TIMES_2, target::kWordSize));
193
194 __ movq(RAX, Address(R13, RBP, TIMES_2, target::kWordSize));
195 __ movq(RAX, Address(R13, RAX, TIMES_2, target::kWordSize));
196 __ movq(RAX, Address(R13, R10, TIMES_2, target::kWordSize));
197 __ movq(RAX, Address(R13, R12, TIMES_2, target::kWordSize));
198 __ movq(RAX, Address(R13, R13, TIMES_2, target::kWordSize));
199
200 __ movq(RAX, Address(RAX, RBP, TIMES_2, 256 * target::kWordSize));
201 __ movq(RAX, Address(RAX, RAX, TIMES_2, 256 * target::kWordSize));
202 __ movq(RAX, Address(RAX, R10, TIMES_2, 256 * target::kWordSize));
203 __ movq(RAX, Address(RAX, R12, TIMES_2, 256 * target::kWordSize));
204 __ movq(RAX, Address(RAX, R13, TIMES_2, 256 * target::kWordSize));
205
206 __ movq(RAX, Address(RBP, RBP, TIMES_2, 256 * target::kWordSize));
207 __ movq(RAX, Address(RBP, RAX, TIMES_2, 256 * target::kWordSize));
208 __ movq(RAX, Address(RBP, R10, TIMES_2, 256 * target::kWordSize));
209 __ movq(RAX, Address(RBP, R12, TIMES_2, 256 * target::kWordSize));
210 __ movq(RAX, Address(RBP, R13, TIMES_2, 256 * target::kWordSize));
211
212 __ movq(RAX, Address(RSP, RBP, TIMES_2, 256 * target::kWordSize));
213 __ movq(RAX, Address(RSP, RAX, TIMES_2, 256 * target::kWordSize));
214 __ movq(RAX, Address(RSP, R10, TIMES_2, 256 * target::kWordSize));
215 __ movq(RAX, Address(RSP, R12, TIMES_2, 256 * target::kWordSize));
216 __ movq(RAX, Address(RSP, R13, TIMES_2, 256 * target::kWordSize));
217
218 __ movq(RAX, Address(R10, RBP, TIMES_2, 256 * target::kWordSize));
219 __ movq(RAX, Address(R10, RAX, TIMES_2, 256 * target::kWordSize));
220 __ movq(RAX, Address(R10, R10, TIMES_2, 256 * target::kWordSize));
221 __ movq(RAX, Address(R10, R12, TIMES_2, 256 * target::kWordSize));
222 __ movq(RAX, Address(R10, R13, TIMES_2, 256 * target::kWordSize));
223
224 __ movq(RAX, Address(R12, RBP, TIMES_2, 256 * target::kWordSize));
225 __ movq(RAX, Address(R12, RAX, TIMES_2, 256 * target::kWordSize));
226 __ movq(RAX, Address(R12, R10, TIMES_2, 256 * target::kWordSize));
227 __ movq(RAX, Address(R12, R12, TIMES_2, 256 * target::kWordSize));
228 __ movq(RAX, Address(R12, R13, TIMES_2, 256 * target::kWordSize));
229
230 __ movq(RAX, Address(R13, RBP, TIMES_2, 256 * target::kWordSize));
231 __ movq(RAX, Address(R13, RAX, TIMES_2, 256 * target::kWordSize));
232 __ movq(RAX, Address(R13, R10, TIMES_2, 256 * target::kWordSize));
233 __ movq(RAX, Address(R13, R12, TIMES_2, 256 * target::kWordSize));
234 __ movq(RAX, Address(R13, R13, TIMES_2, 256 * target::kWordSize));
235
236 __ movq(RAX, Address::AddressBaseImm32(RSP, 0));
237 __ movq(RAX, Address::AddressBaseImm32(RBP, 0));
238 __ movq(RAX, Address::AddressBaseImm32(RAX, 0));
239 __ movq(RAX, Address::AddressBaseImm32(R10, 0));
240 __ movq(RAX, Address::AddressBaseImm32(R12, 0));
241 __ movq(RAX, Address::AddressBaseImm32(R13, 0));
242 __ movq(R10, Address::AddressBaseImm32(RAX, 0));
243
244 __ movq(RAX, Address::AddressBaseImm32(RSP, target::kWordSize));
245 __ movq(RAX, Address::AddressBaseImm32(RBP, target::kWordSize));
246 __ movq(RAX, Address::AddressBaseImm32(RAX, target::kWordSize));
247 __ movq(RAX, Address::AddressBaseImm32(R10, target::kWordSize));
248 __ movq(RAX, Address::AddressBaseImm32(R12, target::kWordSize));
249 __ movq(RAX, Address::AddressBaseImm32(R13, target::kWordSize));
250
251 __ movq(RAX, Address::AddressBaseImm32(RSP, -target::kWordSize));
252 __ movq(RAX, Address::AddressBaseImm32(RBP, -target::kWordSize));
253 __ movq(RAX, Address::AddressBaseImm32(RAX, -target::kWordSize));
254 __ movq(RAX, Address::AddressBaseImm32(R10, -target::kWordSize));
255 __ movq(RAX, Address::AddressBaseImm32(R12, -target::kWordSize));
256 __ movq(RAX, Address::AddressBaseImm32(R13, -target::kWordSize));
257}
258
259ASSEMBLER_TEST_RUN(AddressingModes, test) {
260 // Avoid running the code since it is constructed to lead to crashes.
261 EXPECT_DISASSEMBLY(
262 "movq rax,[rsp]\n"
263 "movq rax,[rbp+0]\n"
264 "movq rax,[rax]\n"
265 "movq rax,[r10]\n"
266 "movq rax,[r12]\n"
267 "movq rax,[r13+0]\n"
268 "movq r10,[rax]\n"
269 "movq rax,[rsp+0x8]\n"
270 "movq rax,[rbp+0x8]\n"
271 "movq rax,[rax+0x8]\n"
272 "movq rax,[r10+0x8]\n"
273 "movq rax,[r12+0x8]\n"
274 "movq rax,[r13+0x8]\n"
275 "movq rax,[rsp-0x8]\n"
276 "movq rax,[rbp-0x8]\n"
277 "movq rax,[rax-0x8]\n"
278 "movq rax,[r10-0x8]\n"
279 "movq rax,[r12-0x8]\n"
280 "movq rax,[r13-0x8]\n"
281 "movq rax,[rsp+0x...]\n"
282 "movq rax,[rbp+0x...]\n"
283 "movq rax,[rax+0x...]\n"
284 "movq rax,[r10+0x...]\n"
285 "movq rax,[r12+0x...]\n"
286 "movq rax,[r13+0x...]\n"
287 "movq rax,[rsp-0x...]\n"
288 "movq rax,[rbp-0x...]\n"
289 "movq rax,[rax-0x...]\n"
290 "movq rax,[r10-0x...]\n"
291 "movq rax,[r12-0x...]\n"
292 "movq rax,[r13-0x...]\n"
293 "movq rax,[rax*1+0]\n"
294 "movq rax,[rax*2+0]\n"
295 "movq rax,[rax*4+0]\n"
296 "movq rax,[rax*8+0]\n"
297 "movq rax,[rbp*2+0]\n"
298 "movq rax,[rax*2+0]\n"
299 "movq rax,[r10*2+0]\n"
300 "movq rax,[r12*2+0]\n"
301 "movq rax,[r13*2+0]\n"
302 "movq rax,[rbp*2+0x8]\n"
303 "movq rax,[rax*2+0x8]\n"
304 "movq rax,[r10*2+0x8]\n"
305 "movq rax,[r12*2+0x8]\n"
306 "movq rax,[r13*2+0x8]\n"
307 "movq rax,[rbp*2+0x...]\n"
308 "movq rax,[rax*2+0x...]\n"
309 "movq rax,[r10*2+0x...]\n"
310 "movq rax,[r12*2+0x...]\n"
311 "movq rax,[r13*2+0x...]\n"
312 "movq rax,[rax+rbp*2]\n"
313 "movq rax,[rax+rax*2]\n"
314 "movq rax,[rax+r10*2]\n"
315 "movq rax,[rax+r12*2]\n"
316 "movq rax,[rax+r13*2]\n"
317 "movq rax,[rbp+rbp*2+0]\n"
318 "movq rax,[rbp+rax*2+0]\n"
319 "movq rax,[rbp+r10*2+0]\n"
320 "movq rax,[rbp+r12*2+0]\n"
321 "movq rax,[rbp+r13*2+0]\n"
322 "movq rax,[rsp+rbp*2]\n"
323 "movq rax,[rsp+rax*2]\n"
324 "movq rax,[rsp+r10*2]\n"
325 "movq rax,[rsp+r12*2]\n"
326 "movq rax,[rsp+r13*2]\n"
327 "movq rax,[r10+rbp*2]\n"
328 "movq rax,[r10+rax*2]\n"
329 "movq rax,[r10+r10*2]\n"
330 "movq rax,[r10+r12*2]\n"
331 "movq rax,[r10+r13*2]\n"
332 "movq rax,[r12+rbp*2]\n"
333 "movq rax,[r12+rax*2]\n"
334 "movq rax,[r12+r10*2]\n"
335 "movq rax,[r12+r12*2]\n"
336 "movq rax,[r12+r13*2]\n"
337 "movq rax,[r13+rbp*2+0]\n"
338 "movq rax,[r13+rax*2+0]\n"
339 "movq rax,[r13+r10*2+0]\n"
340 "movq rax,[r13+r12*2+0]\n"
341 "movq rax,[r13+r13*2+0]\n"
342 "movq rax,[rax+rbp*2+0x8]\n"
343 "movq rax,[rax+rax*2+0x8]\n"
344 "movq rax,[rax+r10*2+0x8]\n"
345 "movq rax,[rax+r12*2+0x8]\n"
346 "movq rax,[rax+r13*2+0x8]\n"
347 "movq rax,[rbp+rbp*2+0x8]\n"
348 "movq rax,[rbp+rax*2+0x8]\n"
349 "movq rax,[rbp+r10*2+0x8]\n"
350 "movq rax,[rbp+r12*2+0x8]\n"
351 "movq rax,[rbp+r13*2+0x8]\n"
352 "movq rax,[rsp+rbp*2+0x8]\n"
353 "movq rax,[rsp+rax*2+0x8]\n"
354 "movq rax,[rsp+r10*2+0x8]\n"
355 "movq rax,[rsp+r12*2+0x8]\n"
356 "movq rax,[rsp+r13*2+0x8]\n"
357 "movq rax,[r10+rbp*2+0x8]\n"
358 "movq rax,[r10+rax*2+0x8]\n"
359 "movq rax,[r10+r10*2+0x8]\n"
360 "movq rax,[r10+r12*2+0x8]\n"
361 "movq rax,[r10+r13*2+0x8]\n"
362 "movq rax,[r12+rbp*2+0x8]\n"
363 "movq rax,[r12+rax*2+0x8]\n"
364 "movq rax,[r12+r10*2+0x8]\n"
365 "movq rax,[r12+r12*2+0x8]\n"
366 "movq rax,[r12+r13*2+0x8]\n"
367 "movq rax,[r13+rbp*2+0x8]\n"
368 "movq rax,[r13+rax*2+0x8]\n"
369 "movq rax,[r13+r10*2+0x8]\n"
370 "movq rax,[r13+r12*2+0x8]\n"
371 "movq rax,[r13+r13*2+0x8]\n"
372 "movq rax,[rax+rbp*2+0x...]\n"
373 "movq rax,[rax+rax*2+0x...]\n"
374 "movq rax,[rax+r10*2+0x...]\n"
375 "movq rax,[rax+r12*2+0x...]\n"
376 "movq rax,[rax+r13*2+0x...]\n"
377 "movq rax,[rbp+rbp*2+0x...]\n"
378 "movq rax,[rbp+rax*2+0x...]\n"
379 "movq rax,[rbp+r10*2+0x...]\n"
380 "movq rax,[rbp+r12*2+0x...]\n"
381 "movq rax,[rbp+r13*2+0x...]\n"
382 "movq rax,[rsp+rbp*2+0x...]\n"
383 "movq rax,[rsp+rax*2+0x...]\n"
384 "movq rax,[rsp+r10*2+0x...]\n"
385 "movq rax,[rsp+r12*2+0x...]\n"
386 "movq rax,[rsp+r13*2+0x...]\n"
387 "movq rax,[r10+rbp*2+0x...]\n"
388 "movq rax,[r10+rax*2+0x...]\n"
389 "movq rax,[r10+r10*2+0x...]\n"
390 "movq rax,[r10+r12*2+0x...]\n"
391 "movq rax,[r10+r13*2+0x...]\n"
392 "movq rax,[r12+rbp*2+0x...]\n"
393 "movq rax,[r12+rax*2+0x...]\n"
394 "movq rax,[r12+r10*2+0x...]\n"
395 "movq rax,[r12+r12*2+0x...]\n"
396 "movq rax,[r12+r13*2+0x...]\n"
397 "movq rax,[r13+rbp*2+0x...]\n"
398 "movq rax,[r13+rax*2+0x...]\n"
399 "movq rax,[r13+r10*2+0x...]\n"
400 "movq rax,[r13+r12*2+0x...]\n"
401 "movq rax,[r13+r13*2+0x...]\n"
402 "movq rax,[rsp+0]\n"
403 "movq rax,[rbp+0]\n"
404 "movq rax,[rax+0]\n"
405 "movq rax,[r10+0]\n"
406 "movq rax,[r12+0]\n"
407 "movq rax,[r13+0]\n"
408 "movq r10,[rax+0]\n"
409 "movq rax,[rsp+0x8]\n"
410 "movq rax,[rbp+0x8]\n"
411 "movq rax,[rax+0x8]\n"
412 "movq rax,[r10+0x8]\n"
413 "movq rax,[r12+0x8]\n"
414 "movq rax,[r13+0x8]\n"
415 "movq rax,[rsp-0x8]\n"
416 "movq rax,[rbp-0x8]\n"
417 "movq rax,[rax-0x8]\n"
418 "movq rax,[r10-0x8]\n"
419 "movq rax,[r12-0x8]\n"
420 "movq rax,[r13-0x8]\n");
421}
422
423ASSEMBLER_TEST_GENERATE(JumpAroundCrash, assembler) {
424 Label done;
425 // Make sure all the condition jumps work.
426 for (Condition condition = OVERFLOW; condition <= GREATER;
427 condition = static_cast<Condition>(condition + 1)) {
428 __ j(condition, &done);
429 }
430 // This isn't strictly necessary, but we do an unconditional
431 // jump around the crashing code anyway.
432 __ jmp(&done);
433
434 // Be sure to skip this crashing code.
435 __ movq(RAX, Immediate(0));
436 __ movq(Address(RAX, 0), RAX);
437
438 __ Bind(&done);
439 __ ret();
440}
441
442ASSEMBLER_TEST_RUN(JumpAroundCrash, test) {
443 Instr* instr = Instr::At(test->entry());
444 EXPECT(!instr->IsBreakPoint());
445 typedef void (*JumpAroundCrashCode)();
446 reinterpret_cast<JumpAroundCrashCode>(test->entry())();
447 EXPECT_DISASSEMBLY(
448 "jo 0x................\n"
449 "jno 0x................\n"
450 "jc 0x................\n"
451 "jnc 0x................\n"
452 "jz 0x................\n"
453 "jnz 0x................\n"
454 "jna 0x................\n"
455 "ja 0x................\n"
456 "js 0x................\n"
457 "jns 0x................\n"
458 "jpe 0x................\n"
459 "jpo 0x................\n"
460 "jl 0x................\n"
461 "jge 0x................\n"
462 "jle 0x................\n"
463 "jg 0x................\n"
464 "jmp 0x................\n"
465 "movl rax,0\n"
466 "movq [rax],rax\n"
467 "ret\n");
468}
469
470ASSEMBLER_TEST_GENERATE(SimpleLoop, assembler) {
471 __ movq(RAX, Immediate(0));
472 __ movq(RCX, Immediate(0));
473 Label loop;
474 __ Bind(&loop);
475 __ addq(RAX, Immediate(2));
476 __ incq(RCX);
477 __ cmpq(RCX, Immediate(87));
478 __ j(LESS, &loop);
479 __ ret();
480}
481
482ASSEMBLER_TEST_RUN(SimpleLoop, test) {
483 typedef int (*SimpleLoopCode)();
484 EXPECT_EQ(2 * 87, reinterpret_cast<SimpleLoopCode>(test->entry())());
485 EXPECT_DISASSEMBLY(
486 "movl rax,0\n"
487 "movl rcx,0\n"
488 "addq rax,2\n"
489 "incq rcx\n"
490 "cmpq rcx,0x57\n"
491 "jl 0x................\n"
492 "ret\n");
493}
494
495ASSEMBLER_TEST_GENERATE(Cmpb, assembler) {
496 Label done;
497 __ movq(RAX, Immediate(1));
498 __ pushq(Immediate(0xffffff11));
499 __ cmpb(Address(RSP, 0), Immediate(0x11));
500 __ j(EQUAL, &done, Assembler::kNearJump);
501 __ movq(RAX, Immediate(0));
502 __ Bind(&done);
503 __ popq(RCX);
504 __ ret();
505}
506
507ASSEMBLER_TEST_RUN(Cmpb, test) {
508 typedef int (*CmpbCode)();
509 EXPECT_EQ(1, reinterpret_cast<CmpbCode>(test->entry())());
510 EXPECT_DISASSEMBLY(
511 "movl rax,1\n"
512 "movl r11,0x........\n"
513 "push r11\n"
514 "cmpb [rsp],0x11\n"
515 "jz 0x................\n"
516 "movl rax,0\n"
517 "pop rcx\n"
518 "ret\n");
519}
520
521ASSEMBLER_TEST_GENERATE(Testb, assembler) {
522 Label done;
523 __ movq(RAX, Immediate(1));
524 __ movq(RCX, Immediate(0));
525 __ pushq(Immediate(0xffffff11));
526 __ testb(Address(RSP, 0), Immediate(0x10));
527 // Fail if zero flag set.
528 __ cmoveq(RAX, RCX);
529 __ testb(Address(RSP, 0), Immediate(0x20));
530 // Fail if zero flag not set.
531 __ j(ZERO, &done);
532 __ movq(RAX, Immediate(0));
533 __ Bind(&done);
534 __ popq(RCX);
535 __ ret();
536}
537
538ASSEMBLER_TEST_RUN(Testb, test) {
539 typedef int (*TestbCode)();
540 EXPECT_EQ(1, reinterpret_cast<TestbCode>(test->entry())());
541 EXPECT_DISASSEMBLY(
542 "movl rax,1\n"
543 "movl rcx,0\n"
544 "movl r11,0x........\n"
545 "push r11\n"
546 "testb [rsp],0x10\n"
547 "cmovzq rax,rcx\n"
548 "testb [rsp],0x20\n"
549 "jz 0x................\n"
550 "movl rax,0\n"
551 "pop rcx\n"
552 "ret\n");
553}
554
555ASSEMBLER_TEST_GENERATE(Testb2, assembler) {
556 Label done, ok1, ok2, ok3, ok4, ok5, ok6, ok7;
557
558 __ movq(RAX, Immediate(0xffffefff));
559 __ bsrq(RCX, RAX);
560 __ cmpq(RCX, Immediate(31));
561 __ j(EQUAL, &ok1);
562 __ int3();
563 __ Bind(&ok1);
564
565 __ sarq(RAX, Immediate(1));
566 __ cmpq(RAX, Immediate(0x7ffff7ff));
567 __ j(EQUAL, &ok2);
568 __ int3();
569 __ Bind(&ok2);
570
571 __ movq(RAX, Immediate(0x7fffffff));
572 __ bsrq(RCX, RAX);
573 __ cmpq(RCX, Immediate(30));
574 __ j(EQUAL, &ok3);
575 __ int3();
576 __ Bind(&ok3);
577
578 __ cmpq(RAX, Immediate(0x7fffffff));
579 __ j(EQUAL, &ok4);
580 __ int3();
581 __ Bind(&ok4);
582
583 __ movq(RAX, Immediate(0x101020408));
584 __ andq(RAX, Immediate(0xffffffff));
585 __ cmpq(RAX, Immediate(0x1020408));
586 __ j(EQUAL, &ok5);
587 __ int3();
588 __ Bind(&ok5);
589
590 __ movq(RCX, Immediate(0x101020408));
591 __ andq(RCX, Immediate(0xffffffff));
592 __ cmpq(RCX, Immediate(0x1020408));
593 __ j(EQUAL, &ok6);
594 __ int3();
595 __ Bind(&ok6);
596
597 __ movq(RAX, Immediate(0x0fffeff0));
598 __ bsfq(RCX, RAX);
599 __ cmpq(RCX, Immediate(4));
600 __ j(EQUAL, &ok7);
601 __ int3();
602 __ Bind(&ok7);
603
604 __ movq(RAX, Immediate(42));
605 __ ret();
606}
607
608ASSEMBLER_TEST_RUN(Testb2, test) {
609 typedef int64_t (*Testb2Code)();
610 EXPECT_EQ(42, reinterpret_cast<Testb2Code>(test->entry())());
611 EXPECT_DISASSEMBLY(
612 "movl rax,0x........\n"
613 "bsrq rcx,rax\n"
614 "cmpq rcx,0x1f\n"
615 "jz 0x................\n"
616 "int3\n"
617
618 "sarq rax,1\n"
619 "cmpq rax,0x........\n"
620 "jz 0x................\n"
621 "int3\n"
622
623 "movl rax,0x........\n"
624 "bsrq rcx,rax\n"
625 "cmpq rcx,0x1e\n"
626 "jz 0x................\n"
627 "int3\n"
628
629 "cmpq rax,0x........\n"
630 "jz 0x................\n"
631 "int3\n"
632
633 "movq rax,0x................\n"
634 "andl rax,0x........\n"
635 "cmpq rax,0x........\n"
636 "jz 0x................\n"
637 "int3\n"
638
639 "movq rcx,0x................\n"
640 "andl rcx,0x........\n"
641 "cmpq rcx,0x........\n"
642 "jz 0x................\n"
643 "int3\n"
644
645 "movl rax,0x........\n"
646 "bsfq rcx,rax\n"
647 "cmpq rcx,4\n"
648 "jz 0x................\n"
649 "int3\n"
650
651 "movl rax,0x2a\n"
652 "ret\n");
653}
654
655ASSEMBLER_TEST_GENERATE(Testb3, assembler) {
656 Label zero;
657 __ pushq(CallingConventions::kArg1Reg);
658 __ movq(RDX, Immediate(0x10));
659 __ testb(Address(RSP, 0), RDX);
660 __ j(ZERO, &zero);
661 __ movq(RAX, Immediate(1));
662 __ popq(RCX);
663 __ ret();
664 __ Bind(&zero);
665 __ movq(RAX, Immediate(0));
666 __ popq(RCX);
667 __ ret();
668}
669
670ASSEMBLER_TEST_RUN(Testb3, test) {
671 typedef int (*TestbCode)(int);
672 EXPECT_EQ(1, reinterpret_cast<TestbCode>(test->entry())(0x11));
673 EXPECT_EQ(0, reinterpret_cast<TestbCode>(test->entry())(0x101));
674 EXPECT_DISASSEMBLY_NOT_WINDOWS(
675 "push rdi\n"
676 "movl rdx,0x10\n"
677 "testb rdx,[rsp]\n"
678 "jz 0x................\n"
679 "movl rax,1\n"
680 "pop rcx\n"
681 "ret\n"
682 "movl rax,0\n"
683 "pop rcx\n"
684 "ret\n");
685}
686
687ASSEMBLER_TEST_GENERATE(Popcnt, assembler) {
688 __ movq(RCX, Immediate(-1));
689 __ popcntq(RAX, RCX);
690 __ movq(RCX, Immediate(0xf));
691 __ popcntq(RCX, RCX);
692 __ addq(RAX, RCX);
693 __ ret();
694}
695
696ASSEMBLER_TEST_RUN(Popcnt, test) {
697 if (!HostCPUFeatures::popcnt_supported()) {
698 return;
699 }
700 typedef int64_t (*PopcntCode)();
701 EXPECT_EQ(68, reinterpret_cast<PopcntCode>(test->entry())());
702 EXPECT_DISASSEMBLY(
703 "movq rcx,-1\n"
704 "popcntq rax,rcx\n"
705 "movl rcx,0xf\n"
706 "popcntq rcx,rcx\n"
707 "addq rax,rcx\n"
708 "ret\n");
709}
710
711ASSEMBLER_TEST_GENERATE(Lzcnt, assembler) {
712 __ movq(RCX, Immediate(0x0f00));
713 __ lzcntq(RAX, RCX);
714 __ movq(RCX, Immediate(0x00f0));
715 __ lzcntq(RCX, RCX);
716 __ addq(RAX, RCX);
717 __ ret();
718}
719
720ASSEMBLER_TEST_RUN(Lzcnt, test) {
721 if (!HostCPUFeatures::abm_supported()) {
722 return;
723 }
724 typedef int64_t (*LzcntCode)();
725 EXPECT_EQ(108, reinterpret_cast<LzcntCode>(test->entry())());
726 EXPECT_DISASSEMBLY(
727 "movl rcx,0x...\n"
728 "lzcntq rax,rcx\n"
729 "movl rcx,0xf0\n"
730 "lzcntq rcx,rcx\n"
731 "addq rax,rcx\n"
732 "ret\n");
733}
734
735struct JumpAddress {
736 uword filler1;
737 uword filler2;
738 uword filler3;
739 uword filler4;
740 uword filler5;
741 uword target;
742 uword filler6;
743 uword filler7;
744 uword filler8;
745};
746static JumpAddress jump_address;
747static uword jump_address_offset;
748
749ASSEMBLER_TEST_GENERATE(JumpAddress, assembler) {
750 __ jmp(Address(CallingConventions::kArg1Reg, OFFSET_OF(JumpAddress, target)));
751 __ int3();
752 __ int3();
753 __ int3();
754 __ int3();
755 __ int3();
756 jump_address_offset = __ CodeSize();
757 __ movl(RAX, Immediate(42));
758 __ ret();
759}
760
761ASSEMBLER_TEST_RUN(JumpAddress, test) {
762 memset(&jump_address, 0, sizeof(jump_address));
763 jump_address.target = test->entry() + jump_address_offset;
764
765 typedef int (*TestCode)(void*);
766 EXPECT_EQ(42, reinterpret_cast<TestCode>(test->entry())(&jump_address));
767 EXPECT_DISASSEMBLY_NOT_WINDOWS(
768 "jmp [rdi+0x28]\n"
769 "int3\n"
770 "int3\n"
771 "int3\n"
772 "int3\n"
773 "int3\n"
774 "movl rax,0x2a\n"
775 "ret\n");
776}
777
778ASSEMBLER_TEST_GENERATE(Increment, assembler) {
779 __ movq(RAX, Immediate(0));
780 __ pushq(RAX);
781 __ incl(Address(RSP, 0));
782 __ incq(Address(RSP, 0));
783 __ movq(RCX, Address(RSP, 0));
784 __ incq(RCX);
785 __ popq(RAX);
786 __ movq(RAX, RCX);
787 __ ret();
788}
789
790ASSEMBLER_TEST_RUN(Increment, test) {
791 typedef int (*IncrementCode)();
792 EXPECT_EQ(3, reinterpret_cast<IncrementCode>(test->entry())());
793 EXPECT_DISASSEMBLY(
794 "movl rax,0\n"
795 "push rax\n"
796 "incl [rsp]\n"
797 "incq [rsp]\n"
798 "movq rcx,[rsp]\n"
799 "incq rcx\n"
800 "pop rax\n"
801 "movq rax,rcx\n"
802 "ret\n");
803}
804
805ASSEMBLER_TEST_GENERATE(IncrementLong, assembler) {
806 __ movq(RAX, Immediate(0xffffffff));
807 __ pushq(RAX);
808 __ incq(Address(RSP, 0));
809 __ movq(RCX, Address(RSP, 0));
810 __ incq(RCX);
811 __ popq(RAX);
812 __ movq(RAX, RCX);
813 __ ret();
814}
815
816ASSEMBLER_TEST_RUN(IncrementLong, test) {
817 typedef int64_t (*IncrementCodeLong)();
818 EXPECT_EQ(0x100000001, reinterpret_cast<IncrementCodeLong>(test->entry())());
819 EXPECT_DISASSEMBLY(
820 "movl rax,0x........\n"
821 "push rax\n"
822 "incq [rsp]\n"
823 "movq rcx,[rsp]\n"
824 "incq rcx\n"
825 "pop rax\n"
826 "movq rax,rcx\n"
827 "ret\n");
828}
829
830ASSEMBLER_TEST_GENERATE(Decrement, assembler) {
831 __ movq(RAX, Immediate(3));
832 __ pushq(RAX);
833 __ decl(Address(RSP, 0));
834 __ decq(Address(RSP, 0));
835 __ movq(RCX, Address(RSP, 0));
836 __ decq(RCX);
837 __ popq(RAX);
838 __ movq(RAX, RCX);
839 __ ret();
840}
841
842ASSEMBLER_TEST_RUN(Decrement, test) {
843 typedef int (*DecrementCode)();
844 EXPECT_EQ(0, reinterpret_cast<DecrementCode>(test->entry())());
845 EXPECT_DISASSEMBLY(
846 "movl rax,3\n"
847 "push rax\n"
848 "decl [rsp]\n"
849 "decq [rsp]\n"
850 "movq rcx,[rsp]\n"
851 "decq rcx\n"
852 "pop rax\n"
853 "movq rax,rcx\n"
854 "ret\n");
855}
856
857ASSEMBLER_TEST_GENERATE(DecrementLong, assembler) {
858 __ movq(RAX, Immediate(0x100000001));
859 __ pushq(RAX);
860 __ decq(Address(RSP, 0));
861 __ movq(RCX, Address(RSP, 0));
862 __ decq(RCX);
863 __ popq(RAX);
864 __ movq(RAX, RCX);
865 __ ret();
866}
867
868ASSEMBLER_TEST_RUN(DecrementLong, test) {
869 typedef int64_t (*DecrementCodeLong)();
870 EXPECT_EQ(0xffffffff, reinterpret_cast<DecrementCodeLong>(test->entry())());
871 EXPECT_DISASSEMBLY(
872 "movq rax,0x................\n"
873 "push rax\n"
874 "decq [rsp]\n"
875 "movq rcx,[rsp]\n"
876 "decq rcx\n"
877 "pop rax\n"
878 "movq rax,rcx\n"
879 "ret\n");
880}
881
882ASSEMBLER_TEST_GENERATE(SignedMultiply, assembler) {
883 __ movl(RAX, Immediate(2));
884 __ movl(RCX, Immediate(4));
885 __ imull(RAX, RCX);
886 __ imull(RAX, Immediate(1000));
887 __ ret();
888}
889
890ASSEMBLER_TEST_RUN(SignedMultiply, test) {
891 typedef int (*SignedMultiply)();
892 EXPECT_EQ(8000, reinterpret_cast<SignedMultiply>(test->entry())());
893 EXPECT_DISASSEMBLY(
894 "movl rax,2\n"
895 "movl rcx,4\n"
896 "imull rax,rcx\n"
897 "imull rax,rax,0x...\n"
898 "ret\n");
899}
900
901ASSEMBLER_TEST_GENERATE(UnsignedMultiply, assembler) {
902 __ movl(RAX, Immediate(-1)); // RAX = 0xFFFFFFFF
903 __ movl(RCX, Immediate(16)); // RCX = 0x10
904 __ mull(RCX); // RDX:RAX = RAX * RCX = 0x0FFFFFFFF0
905 __ movq(RAX, RDX); // Return high32(0x0FFFFFFFF0) == 0x0F
906 __ ret();
907}
908
909ASSEMBLER_TEST_RUN(UnsignedMultiply, test) {
910 typedef int (*UnsignedMultiply)();
911 EXPECT_EQ(15, reinterpret_cast<UnsignedMultiply>(test->entry())());
912 EXPECT_DISASSEMBLY(
913 "movl rax,-1\n"
914 "movl rcx,0x10\n"
915 "mull (rax,rdx),rcx\n"
916 "movq rax,rdx\n"
917 "ret\n");
918}
919
920ASSEMBLER_TEST_GENERATE(SignedMultiply64Implicit, assembler) {
921 __ movq(RAX, Immediate(7));
922 __ movq(RDX, Immediate(-3));
923 __ imulq(RDX); // // RDX:RAX = -21
924 __ addq(RAX, RDX);
925 __ ret();
926}
927
928ASSEMBLER_TEST_RUN(SignedMultiply64Implicit, test) {
929 typedef int (*SignedMultiply64Implicit)();
930 EXPECT_EQ(-22, reinterpret_cast<SignedMultiply64Implicit>(test->entry())());
931 EXPECT_DISASSEMBLY(
932 "movl rax,7\n"
933 "movq rdx,-3\n"
934 "imulq (rax,rdx),rdx\n"
935 "addq rax,rdx\n"
936 "ret\n");
937}
938
939ASSEMBLER_TEST_GENERATE(SignedMultiply64, assembler) {
940 __ pushq(R15); // Callee saved.
941 __ movq(RAX, Immediate(2));
942 __ movq(RCX, Immediate(4));
943 __ imulq(RAX, RCX);
944
945 __ movq(R8, Immediate(2));
946 __ movq(R9, Immediate(4));
947 __ pushq(R9);
948 __ imulq(R8, Address(RSP, 0));
949 __ popq(R9);
950 __ addq(RAX, R8);
951
952 __ movq(R10, Immediate(2));
953 __ movq(R11, Immediate(4));
954 __ imulq(R10, R11);
955 __ addq(RAX, R10);
956
957 __ movq(R15, Immediate(2));
958 __ imulq(R15, Immediate(4));
959 __ addq(RAX, R15);
960 __ popq(R15);
961 __ ret();
962}
963
964ASSEMBLER_TEST_RUN(SignedMultiply64, test) {
965 typedef int64_t (*SignedMultiply64)();
966 EXPECT_EQ(32, reinterpret_cast<SignedMultiply64>(test->entry())());
967 EXPECT_DISASSEMBLY(
968 "push pp\n"
969 "movl rax,2\n"
970 "movl rcx,4\n"
971 "imulq rax,rcx\n"
972 "movl r8,2\n"
973 "movl r9,4\n"
974 "push r9\n"
975 "imulq r8,[rsp]\n"
976 "pop r9\n"
977 "addq rax,r8\n"
978 "movl r10,2\n"
979 "movl r11,4\n"
980 "imulq r10,r11\n"
981 "addq rax,r10\n"
982 "movl pp,2\n"
983 "imulq pp,pp,4\n"
984 "addq rax,pp\n"
985 "pop pp\n"
986 "ret\n");
987}
988
989static const int64_t kLargeConstant = 0x1234567887654321;
990static const int64_t kAnotherLargeConstant = 987654321987654321LL;
991static const int64_t kProductLargeConstants = 0x5bbb29a7f52fbbd1;
992
993ASSEMBLER_TEST_GENERATE(SignedMultiplyLong, assembler) {
994 Label done;
995 __ movq(RAX, Immediate(kLargeConstant));
996 __ movq(RCX, Immediate(kAnotherLargeConstant));
997 __ imulq(RAX, RCX);
998 __ MulImmediate(RCX, Immediate(kLargeConstant));
999 __ cmpq(RAX, RCX);
1000 __ j(EQUAL, &done);
1001 __ int3();
1002 __ Bind(&done);
1003 __ ret();
1004}
1005
1006ASSEMBLER_TEST_RUN(SignedMultiplyLong, test) {
1007 typedef int64_t (*SignedMultiplyLong)();
1008 EXPECT_EQ(kProductLargeConstants,
1009 reinterpret_cast<SignedMultiplyLong>(test->entry())());
1010 EXPECT_DISASSEMBLY(
1011 "movq rax,0x................\n"
1012 "movq rcx,0x................\n"
1013 "imulq rax,rcx\n"
1014 "movq r11,0x................\n"
1015 "imulq rcx,r11\n"
1016 "cmpq rax,rcx\n"
1017 "jz 0x................\n"
1018 "int3\n"
1019 "ret\n");
1020}
1021
1022ASSEMBLER_TEST_GENERATE(OverflowSignedMultiply, assembler) {
1023 __ movl(RDX, Immediate(0));
1024 __ movl(RAX, Immediate(0x0fffffff));
1025 __ movl(RCX, Immediate(0x0fffffff));
1026 __ imull(RAX, RCX);
1027 __ imull(RAX, RDX);
1028 __ ret();
1029}
1030
1031ASSEMBLER_TEST_RUN(OverflowSignedMultiply, test) {
1032 typedef int (*OverflowSignedMultiply)();
1033 EXPECT_EQ(0, reinterpret_cast<OverflowSignedMultiply>(test->entry())());
1034 EXPECT_DISASSEMBLY(
1035 "movl rdx,0\n"
1036 "movl rax,0x........\n"
1037 "movl rcx,0x........\n"
1038 "imull rax,rcx\n"
1039 "imull rax,rdx\n"
1040 "ret\n");
1041}
1042
1043ASSEMBLER_TEST_GENERATE(SignedMultiply1, assembler) {
1044 __ movl(RDX, Immediate(2));
1045 __ movl(RCX, Immediate(4));
1046 __ imull(RDX, RCX);
1047 __ imull(RDX, Immediate(1000));
1048 __ movl(RAX, RDX);
1049 __ ret();
1050}
1051
1052ASSEMBLER_TEST_RUN(SignedMultiply1, test) {
1053 typedef int (*SignedMultiply1)();
1054 EXPECT_EQ(8000, reinterpret_cast<SignedMultiply1>(test->entry())());
1055 EXPECT_DISASSEMBLY(
1056 "movl rdx,2\n"
1057 "movl rcx,4\n"
1058 "imull rdx,rcx\n"
1059 "imull rdx,rdx,0x...\n"
1060 "movl rax,rdx\n"
1061 "ret\n");
1062}
1063
1064ASSEMBLER_TEST_GENERATE(SignedMultiply2, assembler) {
1065 __ pushq(R15); // Callee saved.
1066 __ movl(R15, Immediate(2));
1067 __ imull(R15, Immediate(1000));
1068 __ movl(RAX, R15);
1069 __ popq(R15);
1070 __ ret();
1071}
1072
1073ASSEMBLER_TEST_RUN(SignedMultiply2, test) {
1074 typedef int (*SignedMultiply2)();
1075 EXPECT_EQ(2000, reinterpret_cast<SignedMultiply2>(test->entry())());
1076 EXPECT_DISASSEMBLY(
1077 "push pp\n"
1078 "movl pp,2\n"
1079 "imull pp,pp,0x...\n"
1080 "movl rax,pp\n"
1081 "pop pp\n"
1082 "ret\n");
1083}
1084
1085ASSEMBLER_TEST_GENERATE(UnsignedMultiplyLong, assembler) {
1086 __ movq(RAX, Immediate(-1)); // RAX = 0xFFFFFFFFFFFFFFFF
1087 __ movq(RCX, Immediate(16)); // RCX = 0x10
1088 __ mulq(RCX); // RDX:RAX = RAX * RCX = 0x0FFFFFFFFFFFFFFFF0
1089 __ movq(RAX, RDX); // Return high64(0x0FFFFFFFFFFFFFFFF0) == 0x0F
1090 __ ret();
1091}
1092
1093ASSEMBLER_TEST_RUN(UnsignedMultiplyLong, test) {
1094 typedef int64_t (*UnsignedMultiplyLong)();
1095 EXPECT_EQ(15, reinterpret_cast<UnsignedMultiplyLong>(test->entry())());
1096 EXPECT_DISASSEMBLY(
1097 "movq rax,-1\n"
1098 "movl rcx,0x10\n"
1099 "mulq (rax,rdx),rcx\n"
1100 "movq rax,rdx\n"
1101 "ret\n");
1102}
1103
1104ASSEMBLER_TEST_GENERATE(SignedDivide, assembler) {
1105 __ movl(RAX, Immediate(-87));
1106 __ movl(RDX, Immediate(123));
1107 __ cdq();
1108 __ movl(RCX, Immediate(42));
1109 __ idivl(RCX);
1110 __ ret();
1111}
1112
1113ASSEMBLER_TEST_RUN(SignedDivide, test) {
1114 typedef int32_t (*SignedDivide)();
1115 EXPECT_EQ(-87 / 42, reinterpret_cast<SignedDivide>(test->entry())());
1116 EXPECT_DISASSEMBLY(
1117 "movl rax,-0x........\n"
1118 "movl rdx,0x7b\n"
1119 "cdq\n"
1120 "movl rcx,0x2a\n"
1121 "idivl (rax,rdx),rcx\n"
1122 "ret\n");
1123}
1124
1125ASSEMBLER_TEST_GENERATE(UnsignedDivide, assembler) {
1126 const int32_t low = 0;
1127 const int32_t high = 0xf0000000;
1128 const int32_t divisor = 0xffffffff;
1129 __ movl(RAX, Immediate(low));
1130 __ movl(RDX, Immediate(high));
1131 __ movl(RCX, Immediate(divisor));
1132 __ divl(RCX); // RAX = RDX:RAX / RCX =
1133 // = 0xf000000000000000 / 0xffffffff = 0xf0000000
1134 __ ret();
1135}
1136
1137ASSEMBLER_TEST_RUN(UnsignedDivide, test) {
1138 typedef uint32_t (*UnsignedDivide)();
1139 EXPECT_EQ(0xf0000000, reinterpret_cast<UnsignedDivide>(test->entry())());
1140 EXPECT_DISASSEMBLY(
1141 "movl rax,0\n"
1142 "movl rdx,-0x........\n"
1143 "movl rcx,-1\n"
1144 "divl (rax,rdx),rcx\n"
1145 "ret\n");
1146}
1147
1148ASSEMBLER_TEST_GENERATE(SignedDivideLong, assembler) {
1149 __ movq(RAX, Immediate(kLargeConstant));
1150 __ movq(RDX, Immediate(123));
1151 __ cqo(); // Clear RDX.
1152 __ movq(RCX, Immediate(42));
1153 __ idivq(RCX);
1154 __ ret();
1155}
1156
1157ASSEMBLER_TEST_RUN(SignedDivideLong, test) {
1158 typedef int64_t (*SignedDivideLong)();
1159 EXPECT_EQ(kLargeConstant / 42,
1160 reinterpret_cast<SignedDivideLong>(test->entry())());
1161 EXPECT_DISASSEMBLY(
1162 "movq rax,0x................\n"
1163 "movl rdx,0x7b\n"
1164 "cqo\n"
1165 "movl rcx,0x2a\n"
1166 "idivq (rax,rdx),rcx\n"
1167 "ret\n");
1168}
1169
1170ASSEMBLER_TEST_GENERATE(UnsignedDivideLong, assembler) {
1171 const int64_t low = 0;
1172 const int64_t high = 0xf000000000000000;
1173 const int64_t divisor = 0xffffffffffffffff;
1174 __ movq(RAX, Immediate(low));
1175 __ movq(RDX, Immediate(high));
1176 __ movq(RCX, Immediate(divisor));
1177 __ divq(RCX); // RAX = RDX:RAX / RCX =
1178 // = 0xf0000000000000000000000000000000 /
1179 // 0xffffffffffffffff = 0xf000000000000000
1180 __ ret();
1181}
1182
1183ASSEMBLER_TEST_RUN(UnsignedDivideLong, test) {
1184 typedef uint64_t (*UnsignedDivideLong)();
1185 EXPECT_EQ(0xf000000000000000,
1186 reinterpret_cast<UnsignedDivideLong>(test->entry())());
1187 EXPECT_DISASSEMBLY(
1188 "movl rax,0\n"
1189 "movq rdx,0x................\n"
1190 "movq rcx,-1\n"
1191 "divq (rax,rdx),rcx\n"
1192 "ret\n");
1193}
1194
1195ASSEMBLER_TEST_GENERATE(Negate, assembler) {
1196 __ movq(RCX, Immediate(42));
1197 __ negq(RCX);
1198 __ movq(RAX, RCX);
1199 __ ret();
1200}
1201
1202ASSEMBLER_TEST_RUN(Negate, test) {
1203 typedef int (*Negate)();
1204 EXPECT_EQ(-42, reinterpret_cast<Negate>(test->entry())());
1205 EXPECT_DISASSEMBLY(
1206 "movl rcx,0x2a\n"
1207 "negq rcx\n"
1208 "movq rax,rcx\n"
1209 "ret\n");
1210}
1211
1212ASSEMBLER_TEST_GENERATE(BitScanReverseTest, assembler) {
1213 __ pushq(CallingConventions::kArg1Reg);
1214 __ movq(RCX, Address(RSP, 0));
1215 __ movq(RAX, Immediate(666)); // Marker for conditional write.
1216 __ bsrq(RAX, RCX);
1217 __ popq(RCX);
1218 __ ret();
1219}
1220
1221ASSEMBLER_TEST_RUN(BitScanReverseTest, test) {
1222 typedef int (*Bsr)(int input);
1223 Bsr call = reinterpret_cast<Bsr>(test->entry());
1224 EXPECT_EQ(666, call(0));
1225 EXPECT_EQ(0, call(1));
1226 EXPECT_EQ(1, call(2));
1227 EXPECT_EQ(1, call(3));
1228 EXPECT_EQ(2, call(4));
1229 EXPECT_EQ(5, call(42));
1230 EXPECT_EQ(31, call(-1));
1231 EXPECT_DISASSEMBLY_NOT_WINDOWS(
1232 "push rdi\n"
1233 "movq rcx,[rsp]\n"
1234 "movl rax,0x...\n"
1235 "bsrq rax,rcx\n"
1236 "pop rcx\n"
1237 "ret\n");
1238}
1239
1240ASSEMBLER_TEST_GENERATE(MoveExtend, assembler) {
1241 __ movq(RDX, Immediate(0xffff));
1242 __ movzxb(RAX, RDX); // RAX = 0xff
1243 __ movsxw(R8, RDX); // R8 = -1
1244 __ movzxw(RCX, RDX); // RCX = 0xffff
1245 __ addq(R8, RCX);
1246 __ addq(RAX, R8);
1247 __ ret();
1248}
1249
1250ASSEMBLER_TEST_RUN(MoveExtend, test) {
1251 typedef int (*MoveExtend)();
1252 EXPECT_EQ(0xff - 1 + 0xffff, reinterpret_cast<MoveExtend>(test->entry())());
1253 EXPECT_DISASSEMBLY(
1254 "movl rdx,0x....\n"
1255 "movzxbq rax,rdx\n"
1256 "movsxwq r8,rdx\n"
1257 "movzxwq rcx,rdx\n"
1258 "addq r8,rcx\n"
1259 "addq rax,r8\n"
1260 "ret\n");
1261}
1262
1263ASSEMBLER_TEST_GENERATE(MoveExtend32, assembler) {
1264 __ movq(RDX, Immediate(0xffffffff));
1265 __ movsxd(RDX, RDX);
1266 __ movq(RAX, Immediate(0x7fffffff));
1267 __ movsxd(RAX, RAX);
1268 __ addq(RAX, RDX);
1269 __ ret();
1270}
1271
1272ASSEMBLER_TEST_RUN(MoveExtend32, test) {
1273 typedef intptr_t (*MoveExtend)();
1274 EXPECT_EQ(0x7ffffffe, reinterpret_cast<MoveExtend>(test->entry())());
1275 EXPECT_DISASSEMBLY(
1276 "movl rdx,0x........\n"
1277 "movsxdq rdx,rdx\n"
1278 "movl rax,0x........\n"
1279 "movsxdq rax,rax\n"
1280 "addq rax,rdx\n"
1281 "ret\n");
1282}
1283
1284ASSEMBLER_TEST_GENERATE(MoveExtendMemory, assembler) {
1285 __ movq(RDX, Immediate(0x123456781234ffff));
1286
1287 __ pushq(RDX);
1288 __ movzxb(RAX, Address(RSP, 0)); // RAX = 0xff
1289 __ movsxw(R8, Address(RSP, 0)); // R8 = -1
1290 __ movzxw(RCX, Address(RSP, 0)); // RCX = 0xffff
1291 __ addq(RSP, Immediate(target::kWordSize));
1292
1293 __ addq(R8, RCX);
1294 __ addq(RAX, R8);
1295 __ ret();
1296}
1297
1298ASSEMBLER_TEST_RUN(MoveExtendMemory, test) {
1299 typedef int (*MoveExtendMemory)();
1300 EXPECT_EQ(0xff - 1 + 0xffff,
1301 reinterpret_cast<MoveExtendMemory>(test->entry())());
1302 EXPECT_DISASSEMBLY(
1303 "movq rdx,0x................\n"
1304 "push rdx\n"
1305 "movzxbq rax,[rsp]\n"
1306 "movsxwq r8,[rsp]\n"
1307 "movzxwq rcx,[rsp]\n"
1308 "addq rsp,8\n"
1309 "addq r8,rcx\n"
1310 "addq rax,r8\n"
1311 "ret\n");
1312}
1313
1314ASSEMBLER_TEST_GENERATE(MoveExtend32Memory, assembler) {
1315 __ pushq(Immediate(0xffffffff));
1316 __ pushq(Immediate(0x7fffffff));
1317 __ movsxd(RDX, Address(RSP, target::kWordSize));
1318 __ movsxd(RAX, Address(RSP, 0));
1319 __ addq(RSP, Immediate(target::kWordSize * 2));
1320
1321 __ addq(RAX, RDX);
1322 __ ret();
1323}
1324
1325ASSEMBLER_TEST_RUN(MoveExtend32Memory, test) {
1326 typedef intptr_t (*MoveExtend)();
1327 EXPECT_EQ(0x7ffffffe, reinterpret_cast<MoveExtend>(test->entry())());
1328 EXPECT_DISASSEMBLY(
1329 "movl r11,0x........\n"
1330 "push r11\n"
1331 "push 0x........\n"
1332 "movsxdq rdx,[rsp+0x8]\n"
1333 "movsxdq rax,[rsp]\n"
1334 "addq rsp,0x10\n"
1335 "addq rax,rdx\n"
1336 "ret\n");
1337}
1338
1339ASSEMBLER_TEST_GENERATE(MoveWord, assembler) {
1340 __ xorq(RAX, RAX);
1341 __ pushq(Immediate(0));
1342 __ movq(RAX, RSP);
1343 __ movq(RCX, Immediate(-1));
1344 __ movw(Address(RAX, 0), RCX);
1345 __ movzxw(RAX, Address(RAX, 0)); // RAX = 0xffff
1346 __ addq(RSP, Immediate(target::kWordSize));
1347 __ ret();
1348}
1349
1350ASSEMBLER_TEST_RUN(MoveWord, test) {
1351 typedef int (*MoveWord)();
1352 EXPECT_EQ(0xffff, reinterpret_cast<MoveWord>(test->entry())());
1353 EXPECT_DISASSEMBLY(
1354 "xorq rax,rax\n"
1355 "push 0\n"
1356 "movq rax,rsp\n"
1357 "movq rcx,-1\n"
1358 "movw [rax],rcx\n"
1359 "movzxwq rax,[rax]\n"
1360 "addq rsp,8\n"
1361 "ret\n");
1362}
1363
1364ASSEMBLER_TEST_GENERATE(WordOps, assembler) {
1365 __ movq(RAX, Immediate(0x0102030405060708));
1366 __ pushq(RAX);
1367 __ addw(Address(RSP, 0), Immediate(-0x201));
1368 __ subw(Address(RSP, 2), Immediate(0x201));
1369 __ xorw(Address(RSP, 4), Immediate(0x201));
1370 __ andw(Address(RSP, 6), Immediate(0x301));
1371 __ andw(Address(RSP, 0), Immediate(-1));
1372 __ popq(RAX);
1373 __ ret();
1374}
1375
1376ASSEMBLER_TEST_RUN(WordOps, test) {
1377 typedef int64_t (*WordOps)();
1378 EXPECT_EQ(0x0100010503050507, reinterpret_cast<WordOps>(test->entry())());
1379 EXPECT_DISASSEMBLY(
1380 "movq rax,0x................\n"
1381 "push rax\n"
1382 "addw [rsp],0x....\n"
1383 "subw [rsp+0x2],0x...\n"
1384 "xorw [rsp+0x4],0x...\n"
1385 "andw [rsp+0x6],0x...\n"
1386 "andw [rsp],-1\n"
1387 "pop rax\n"
1388 "ret\n");
1389}
1390
1391ASSEMBLER_TEST_GENERATE(ByteOps, assembler) {
1392 __ movq(RAX, Immediate(0x0102030405060708));
1393 __ pushq(RAX);
1394 __ addb(Address(RSP, 0), Immediate(0xff));
1395 __ subb(Address(RSP, 2), Immediate(1));
1396 __ xorb(Address(RSP, 4), Immediate(1));
1397 __ andb(Address(RSP, 6), Immediate(1));
1398 __ andb(Address(RSP, 0), Immediate(-1));
1399 __ popq(RAX);
1400 __ ret();
1401}
1402
1403ASSEMBLER_TEST_RUN(ByteOps, test) {
1404 typedef int64_t (*ByteOps)();
1405 EXPECT_EQ(0x0100030505050707, reinterpret_cast<ByteOps>(test->entry())());
1406 EXPECT_DISASSEMBLY(
1407 "movq rax,0x................\n"
1408 "push rax\n"
1409 "addb [rsp],-1\n"
1410 "subb [rsp+0x2],1\n"
1411 "xorb [rsp+0x4],1\n"
1412 "andb [rsp+0x6],1\n"
1413 "andb [rsp],-1\n"
1414 "pop rax\n"
1415 "ret\n");
1416}
1417
1418ASSEMBLER_TEST_GENERATE(MoveWordRex, assembler) {
1419 __ pushq(Immediate(0));
1420 __ movq(R8, RSP);
1421 __ movq(R9, Immediate(-1));
1422 __ movw(Address(R8, 0), R9);
1423 __ movzxw(R8, Address(R8, 0)); // 0xffff
1424 __ xorq(RAX, RAX);
1425 __ addq(RAX, R8); // RAX = 0xffff
1426 __ addq(RSP, Immediate(target::kWordSize));
1427 __ ret();
1428}
1429
1430ASSEMBLER_TEST_RUN(MoveWordRex, test) {
1431 typedef int (*MoveWordRex)();
1432 EXPECT_EQ(0xffff, reinterpret_cast<MoveWordRex>(test->entry())());
1433 EXPECT_DISASSEMBLY(
1434 "push 0\n"
1435 "movq r8,rsp\n"
1436 "movq r9,-1\n"
1437 "movw [r8],r9\n"
1438 "movzxwq r8,[r8]\n"
1439 "xorq rax,rax\n"
1440 "addq rax,r8\n"
1441 "addq rsp,8\n"
1442 "ret\n");
1443}
1444
1445ASSEMBLER_TEST_GENERATE(LongAddReg, assembler) {
1446 __ pushq(CallingConventions::kArg2Reg);
1447 __ pushq(CallingConventions::kArg1Reg);
1448 __ movl(RAX, Address(RSP, 0)); // left low.
1449 __ movl(RDX, Address(RSP, 4)); // left high.
1450 __ movl(RCX, Address(RSP, 8)); // right low.
1451 __ movl(R8, Address(RSP, 12)); // right high
1452 __ addl(RAX, RCX);
1453 __ adcl(RDX, R8);
1454 // Result is in RAX/RDX.
1455 __ movl(Address(RSP, 0), RAX); // result low.
1456 __ movl(Address(RSP, 4), RDX); // result high.
1457 __ popq(RAX);
1458 __ popq(RDX);
1459 __ ret();
1460}
1461
1462ASSEMBLER_TEST_RUN(LongAddReg, test) {
1463 typedef int64_t (*LongAddRegCode)(int64_t a, int64_t b);
1464 int64_t a = 12;
1465 int64_t b = 14;
1466 int64_t res = reinterpret_cast<LongAddRegCode>(test->entry())(a, b);
1467 EXPECT_EQ((a + b), res);
1468 a = 2147483647;
1469 b = 600000;
1470 res = reinterpret_cast<LongAddRegCode>(test->entry())(a, b);
1471 EXPECT_EQ((a + b), res);
1472 EXPECT_DISASSEMBLY_NOT_WINDOWS(
1473 "push rsi\n"
1474 "push rdi\n"
1475 "movl rax,[rsp]\n"
1476 "movl rdx,[rsp+0x4]\n"
1477 "movl rcx,[rsp+0x8]\n"
1478 "movl r8,[rsp+0xc]\n"
1479 "addl rax,rcx\n"
1480 "adcl rdx,r8\n"
1481 "movl [rsp],rax\n"
1482 "movl [rsp+0x4],rdx\n"
1483 "pop rax\n"
1484 "pop rdx\n"
1485 "ret\n");
1486}
1487
1488ASSEMBLER_TEST_GENERATE(LongAddImmediate, assembler) {
1489 __ pushq(CallingConventions::kArg1Reg);
1490 __ movl(RAX, Address(RSP, 0)); // left low.
1491 __ movl(RDX, Address(RSP, 4)); // left high.
1492 __ addl(RAX, Immediate(12)); // right low immediate.
1493 __ adcl(RDX, Immediate(11)); // right high immediate.
1494 // Result is in RAX/RDX.
1495 __ movl(Address(RSP, 0), RAX); // result low.
1496 __ movl(Address(RSP, 4), RDX); // result high.
1497 __ popq(RAX);
1498 __ ret();
1499}
1500
1501ASSEMBLER_TEST_RUN(LongAddImmediate, test) {
1502 typedef int64_t (*LongAddImmediateCode)(int64_t a);
1503 int64_t a = (13LL << 32) + 14;
1504 int64_t b = (11LL << 32) + 12;
1505 int64_t res = reinterpret_cast<LongAddImmediateCode>(test->entry())(a);
1506 EXPECT_EQ((a + b), res);
1507 a = (13LL << 32) - 1;
1508 res = reinterpret_cast<LongAddImmediateCode>(test->entry())(a);
1509 EXPECT_EQ((a + b), res);
1510 EXPECT_DISASSEMBLY_NOT_WINDOWS(
1511 "push rdi\n"
1512 "movl rax,[rsp]\n"
1513 "movl rdx,[rsp+0x4]\n"
1514 "addl rax,0xc\n"
1515 "adcl rdx,0xb\n"
1516 "movl [rsp],rax\n"
1517 "movl [rsp+0x4],rdx\n"
1518 "pop rax\n"
1519 "ret\n");
1520}
1521
1522ASSEMBLER_TEST_GENERATE(LongAddAddress, assembler) {
1523 __ pushq(CallingConventions::kArg2Reg);
1524 __ pushq(CallingConventions::kArg1Reg);
1525 __ movl(RAX, Address(RSP, 0)); // left low.
1526 __ movl(RDX, Address(RSP, 4)); // left high.
1527 __ addl(RAX, Address(RSP, 8)); // low.
1528 __ adcl(RDX, Address(RSP, 12)); // high.
1529 // Result is in RAX/RDX.
1530 __ movl(Address(RSP, 0), RAX); // result low.
1531 __ movl(Address(RSP, 4), RDX); // result high.
1532 __ popq(RAX);
1533 __ popq(RDX);
1534 __ ret();
1535}
1536
1537ASSEMBLER_TEST_RUN(LongAddAddress, test) {
1538 typedef int64_t (*LongAddAddressCode)(int64_t a, int64_t b);
1539 int64_t a = 12;
1540 int64_t b = 14;
1541 int64_t res = reinterpret_cast<LongAddAddressCode>(test->entry())(a, b);
1542 EXPECT_EQ((a + b), res);
1543 a = 2147483647;
1544 b = 600000;
1545 res = reinterpret_cast<LongAddAddressCode>(test->entry())(a, b);
1546 EXPECT_EQ((a + b), res);
1547 EXPECT_DISASSEMBLY_NOT_WINDOWS(
1548 "push rsi\n"
1549 "push rdi\n"
1550 "movl rax,[rsp]\n"
1551 "movl rdx,[rsp+0x4]\n"
1552 "addl rax,[rsp+0x8]\n"
1553 "adcl rdx,[rsp+0xc]\n"
1554 "movl [rsp],rax\n"
1555 "movl [rsp+0x4],rdx\n"
1556 "pop rax\n"
1557 "pop rdx\n"
1558 "ret\n");
1559}
1560
1561ASSEMBLER_TEST_GENERATE(LongSubReg, assembler) {
1562 __ pushq(CallingConventions::kArg2Reg);
1563 __ pushq(CallingConventions::kArg1Reg);
1564 __ movl(RAX, Address(RSP, 0)); // left low.
1565 __ movl(RDX, Address(RSP, 4)); // left high.
1566 __ movl(RCX, Address(RSP, 8)); // right low.
1567 __ movl(R8, Address(RSP, 12)); // right high
1568 __ subl(RAX, RCX);
1569 __ sbbl(RDX, R8);
1570 // Result is in RAX/RDX.
1571 __ movl(Address(RSP, 0), RAX); // result low.
1572 __ movl(Address(RSP, 4), RDX); // result high.
1573 __ popq(RAX);
1574 __ popq(RDX);
1575 __ ret();
1576}
1577
1578ASSEMBLER_TEST_RUN(LongSubReg, test) {
1579 typedef int64_t (*LongSubRegCode)(int64_t a, int64_t b);
1580 int64_t a = 12;
1581 int64_t b = 14;
1582 int64_t res = reinterpret_cast<LongSubRegCode>(test->entry())(a, b);
1583 EXPECT_EQ((a - b), res);
1584 a = 600000;
1585 b = 2147483647;
1586 res = reinterpret_cast<LongSubRegCode>(test->entry())(a, b);
1587 EXPECT_EQ((a - b), res);
1588 EXPECT_DISASSEMBLY_NOT_WINDOWS(
1589 "push rsi\n"
1590 "push rdi\n"
1591 "movl rax,[rsp]\n"
1592 "movl rdx,[rsp+0x4]\n"
1593 "movl rcx,[rsp+0x8]\n"
1594 "movl r8,[rsp+0xc]\n"
1595 "subl rax,rcx\n"
1596 "sbbl rdx,r8\n"
1597 "movl [rsp],rax\n"
1598 "movl [rsp+0x4],rdx\n"
1599 "pop rax\n"
1600 "pop rdx\n"
1601 "ret\n");
1602}
1603
1604ASSEMBLER_TEST_GENERATE(LongSubImmediate, assembler) {
1605 __ pushq(CallingConventions::kArg1Reg);
1606 __ movl(RAX, Immediate(0));
1607 __ subl(
1608 RAX,
1609 Immediate(1)); // Set the carry flag so we can test that subl ignores it.
1610 __ movl(RAX, Address(RSP, 0)); // left low.
1611 __ movl(RDX, Address(RSP, 4)); // left high.
1612 __ subl(RAX, Immediate(12)); // right low immediate.
1613 __ sbbl(RDX, Immediate(11)); // right high immediate.
1614 // Result is in RAX/RDX.
1615 __ movl(Address(RSP, 0), RAX); // result low.
1616 __ movl(Address(RSP, 4), RDX); // result high.
1617 __ popq(RAX);
1618 __ ret();
1619}
1620
1621ASSEMBLER_TEST_RUN(LongSubImmediate, test) {
1622 typedef int64_t (*LongSubImmediateCode)(int64_t a);
1623 int64_t a = (13LL << 32) + 14;
1624 int64_t b = (11LL << 32) + 12;
1625 int64_t res = reinterpret_cast<LongSubImmediateCode>(test->entry())(a);
1626 EXPECT_EQ((a - b), res);
1627 a = (13LL << 32) + 10;
1628 res = reinterpret_cast<LongSubImmediateCode>(test->entry())(a);
1629 EXPECT_EQ((a - b), res);
1630 EXPECT_DISASSEMBLY_NOT_WINDOWS(
1631 "push rdi\n"
1632 "movl rax,0\n"
1633 "subl rax,1\n"
1634 "movl rax,[rsp]\n"
1635 "movl rdx,[rsp+0x4]\n"
1636 "subl rax,0xc\n"
1637 "sbbl rdx,0xb\n"
1638 "movl [rsp],rax\n"
1639 "movl [rsp+0x4],rdx\n"
1640 "pop rax\n"
1641 "ret\n");
1642}
1643
1644ASSEMBLER_TEST_GENERATE(LongSubAddress, assembler) {
1645 __ pushq(CallingConventions::kArg2Reg);
1646 __ pushq(CallingConventions::kArg1Reg);
1647 __ movl(RAX, Address(RSP, 0)); // left low.
1648 __ movl(RDX, Address(RSP, 4)); // left high.
1649 __ subl(RAX, Address(RSP, 8)); // low.
1650 __ sbbl(RDX, Address(RSP, 12)); // high.
1651 // Result is in RAX/RDX.
1652 __ movl(Address(RSP, 0), RAX); // result low.
1653 __ movl(Address(RSP, 4), RDX); // result high.
1654 __ popq(RAX);
1655 __ popq(RDX);
1656 __ ret();
1657}
1658
1659ASSEMBLER_TEST_RUN(LongSubAddress, test) {
1660 typedef int64_t (*LongSubAddressCode)(int64_t a, int64_t b);
1661 int64_t a = 12;
1662 int64_t b = 14;
1663 int64_t res = reinterpret_cast<LongSubAddressCode>(test->entry())(a, b);
1664 EXPECT_EQ((a - b), res);
1665 a = 600000;
1666 b = 2147483647;
1667 res = reinterpret_cast<LongSubAddressCode>(test->entry())(a, b);
1668 EXPECT_EQ((a - b), res);
1669 EXPECT_DISASSEMBLY_NOT_WINDOWS(
1670 "push rsi\n"
1671 "push rdi\n"
1672 "movl rax,[rsp]\n"
1673 "movl rdx,[rsp+0x4]\n"
1674 "subl rax,[rsp+0x8]\n"
1675 "sbbl rdx,[rsp+0xc]\n"
1676 "movl [rsp],rax\n"
1677 "movl [rsp+0x4],rdx\n"
1678 "pop rax\n"
1679 "pop rdx\n"
1680 "ret\n");
1681}
1682
1683ASSEMBLER_TEST_GENERATE(AddReg, assembler) {
1684 __ movq(R10, CallingConventions::kArg1Reg); // al.
1685 __ addq(R10, CallingConventions::kArg3Reg); // bl.
1686 __ movq(RAX, CallingConventions::kArg2Reg); // ah.
1687 __ adcq(RAX, CallingConventions::kArg4Reg); // bh.
1688 // RAX = high64(ah:al + bh:bl).
1689 __ ret();
1690}
1691
1692ASSEMBLER_TEST_RUN(AddReg, test) {
1693 typedef int64_t (*AddRegCode)(int64_t al, int64_t ah, int64_t bl, int64_t bh);
1694 int64_t al = 11;
1695 int64_t ah = 12;
1696 int64_t bl = 13;
1697 int64_t bh = 14;
1698 int64_t res = reinterpret_cast<AddRegCode>(test->entry())(al, ah, bl, bh);
1699 EXPECT_EQ((ah + bh), res);
1700 al = -1;
1701 res = reinterpret_cast<AddRegCode>(test->entry())(al, ah, bl, bh);
1702 EXPECT_EQ((ah + bh + 1), res);
1703 EXPECT_DISASSEMBLY_NOT_WINDOWS(
1704 "movq r10,rdi\n"
1705 "addq r10,rdx\n"
1706 "movq rax,rsi\n"
1707 "adcq rax,rcx\n"
1708 "ret\n");
1709}
1710
1711ASSEMBLER_TEST_GENERATE(AddImmediate, assembler) {
1712 __ movq(R10, CallingConventions::kArg1Reg); // al.
1713 __ addq(R10, Immediate(13)); // bl.
1714 __ movq(RAX, CallingConventions::kArg2Reg); // ah.
1715 __ adcq(RAX, Immediate(14)); // bh.
1716 // RAX = high64(ah:al + bh:bl).
1717 __ ret();
1718}
1719
1720ASSEMBLER_TEST_RUN(AddImmediate, test) {
1721 typedef int64_t (*AddImmediateCode)(int64_t al, int64_t ah);
1722 int64_t al = 11;
1723 int64_t ah = 12;
1724 int64_t bh = 14;
1725 int64_t res = reinterpret_cast<AddImmediateCode>(test->entry())(al, ah);
1726 EXPECT_EQ((ah + bh), res);
1727 al = -1;
1728 res = reinterpret_cast<AddImmediateCode>(test->entry())(al, ah);
1729 EXPECT_EQ((ah + bh + 1), res);
1730 EXPECT_DISASSEMBLY_NOT_WINDOWS(
1731 "movq r10,rdi\n"
1732 "addq r10,0xd\n"
1733 "movq rax,rsi\n"
1734 "adcq rax,0xe\n"
1735 "ret\n");
1736}
1737
1738ASSEMBLER_TEST_GENERATE(AddAddress, assembler) {
1739 __ pushq(CallingConventions::kArg4Reg);
1740 __ pushq(CallingConventions::kArg3Reg);
1741 __ pushq(CallingConventions::kArg2Reg);
1742 __ pushq(CallingConventions::kArg1Reg);
1743 __ movq(R10, Address(RSP, 0 * target::kWordSize)); // al.
1744 __ addq(R10, Address(RSP, 2 * target::kWordSize)); // bl.
1745 __ movq(RAX, Address(RSP, 1 * target::kWordSize)); // ah.
1746 __ adcq(RAX, Address(RSP, 3 * target::kWordSize)); // bh.
1747 // RAX = high64(ah:al + bh:bl).
1748 __ Drop(4);
1749 __ ret();
1750}
1751
1752ASSEMBLER_TEST_RUN(AddAddress, test) {
1753 typedef int64_t (*AddCode)(int64_t al, int64_t ah, int64_t bl, int64_t bh);
1754 int64_t al = 11;
1755 int64_t ah = 12;
1756 int64_t bl = 13;
1757 int64_t bh = 14;
1758 int64_t res = reinterpret_cast<AddCode>(test->entry())(al, ah, bl, bh);
1759 EXPECT_EQ((ah + bh), res);
1760 al = -1;
1761 res = reinterpret_cast<AddCode>(test->entry())(al, ah, bl, bh);
1762 EXPECT_EQ((ah + bh + 1), res);
1763 EXPECT_DISASSEMBLY_NOT_WINDOWS(
1764 "push rcx\n"
1765 "push rdx\n"
1766 "push rsi\n"
1767 "push rdi\n"
1768 "movq r10,[rsp]\n"
1769 "addq r10,[rsp+0x10]\n"
1770 "movq rax,[rsp+0x8]\n"
1771 "adcq rax,[rsp+0x18]\n"
1772 "pop r11\n"
1773 "pop r11\n"
1774 "pop r11\n"
1775 "pop r11\n"
1776 "ret\n");
1777}
1778
1779ASSEMBLER_TEST_GENERATE(SubReg, assembler) {
1780 __ movq(R10, CallingConventions::kArg1Reg); // al.
1781 __ subq(R10, CallingConventions::kArg3Reg); // bl.
1782 __ movq(RAX, CallingConventions::kArg2Reg); // ah.
1783 __ sbbq(RAX, CallingConventions::kArg4Reg); // bh.
1784 // RAX = high64(ah:al - bh:bl).
1785 __ ret();
1786}
1787
1788ASSEMBLER_TEST_RUN(SubReg, test) {
1789 typedef int64_t (*SubRegCode)(int64_t al, int64_t ah, int64_t bl, int64_t bh);
1790 int64_t al = 14;
1791 int64_t ah = 13;
1792 int64_t bl = 12;
1793 int64_t bh = 11;
1794 int64_t res = reinterpret_cast<SubRegCode>(test->entry())(al, ah, bl, bh);
1795 EXPECT_EQ((ah - bh), res);
1796 al = 10;
1797 res = reinterpret_cast<SubRegCode>(test->entry())(al, ah, bl, bh);
1798 EXPECT_EQ((ah - bh - 1), res);
1799 EXPECT_DISASSEMBLY_NOT_WINDOWS(
1800 "movq r10,rdi\n"
1801 "subq r10,rdx\n"
1802 "movq rax,rsi\n"
1803 "sbbq rax,rcx\n"
1804 "ret\n");
1805}
1806
1807ASSEMBLER_TEST_GENERATE(SubImmediate, assembler) {
1808 __ movq(R10, CallingConventions::kArg1Reg); // al.
1809 __ subq(R10, Immediate(12)); // bl.
1810 __ movq(RAX, CallingConventions::kArg2Reg); // ah.
1811 __ sbbq(RAX, Immediate(11)); // bh.
1812 // RAX = high64(ah:al - bh:bl).
1813 __ ret();
1814}
1815
1816ASSEMBLER_TEST_RUN(SubImmediate, test) {
1817 typedef int64_t (*SubImmediateCode)(int64_t al, int64_t ah);
1818 int64_t al = 14;
1819 int64_t ah = 13;
1820 int64_t bh = 11;
1821 int64_t res = reinterpret_cast<SubImmediateCode>(test->entry())(al, ah);
1822 EXPECT_EQ((ah - bh), res);
1823 al = 10;
1824 res = reinterpret_cast<SubImmediateCode>(test->entry())(al, ah);
1825 EXPECT_EQ((ah - bh - 1), res);
1826 EXPECT_DISASSEMBLY_NOT_WINDOWS(
1827 "movq r10,rdi\n"
1828 "subq r10,0xc\n"
1829 "movq rax,rsi\n"
1830 "sbbq rax,0xb\n"
1831 "ret\n");
1832}
1833
1834ASSEMBLER_TEST_GENERATE(SubAddress, assembler) {
1835 __ pushq(CallingConventions::kArg4Reg);
1836 __ pushq(CallingConventions::kArg3Reg);
1837 __ pushq(CallingConventions::kArg2Reg);
1838 __ pushq(CallingConventions::kArg1Reg);
1839 __ movq(R10, Address(RSP, 0 * target::kWordSize)); // al.
1840 __ subq(R10, Address(RSP, 2 * target::kWordSize)); // bl.
1841 __ movq(RAX, Address(RSP, 1 * target::kWordSize)); // ah.
1842 __ sbbq(RAX, Address(RSP, 3 * target::kWordSize)); // bh.
1843 // RAX = high64(ah:al - bh:bl).
1844 __ Drop(4);
1845 __ ret();
1846}
1847
1848ASSEMBLER_TEST_RUN(SubAddress, test) {
1849 typedef int64_t (*SubCode)(int64_t al, int64_t ah, int64_t bl, int64_t bh);
1850 int64_t al = 14;
1851 int64_t ah = 13;
1852 int64_t bl = 12;
1853 int64_t bh = 11;
1854 int64_t res = reinterpret_cast<SubCode>(test->entry())(al, ah, bl, bh);
1855 EXPECT_EQ((ah - bh), res);
1856 al = 10;
1857 res = reinterpret_cast<SubCode>(test->entry())(al, ah, bl, bh);
1858 EXPECT_EQ((ah - bh - 1), res);
1859 EXPECT_DISASSEMBLY_NOT_WINDOWS(
1860 "push rcx\n"
1861 "push rdx\n"
1862 "push rsi\n"
1863 "push rdi\n"
1864 "movq r10,[rsp]\n"
1865 "subq r10,[rsp+0x10]\n"
1866 "movq rax,[rsp+0x8]\n"
1867 "sbbq rax,[rsp+0x18]\n"
1868 "pop r11\n"
1869 "pop r11\n"
1870 "pop r11\n"
1871 "pop r11\n"
1872 "ret\n");
1873}
1874
1875ASSEMBLER_TEST_GENERATE(Bitwise, assembler) {
1876 __ movq(R10, Immediate(-1));
1877 __ orl(Address(CallingConventions::kArg1Reg, 0), R10);
1878 __ orl(Address(CallingConventions::kArg2Reg, 0), R10);
1879 __ movl(RCX, Immediate(42));
1880 __ xorl(RCX, RCX);
1881 __ orl(RCX, Immediate(256));
1882 __ movl(RAX, Immediate(4));
1883 __ orl(RCX, RAX);
1884 __ movl(RAX, Immediate(0xfff0));
1885 __ andl(RCX, RAX);
1886 __ movl(RAX, Immediate(1));
1887 __ orl(RCX, RAX);
1888 __ movl(RAX, RCX);
1889 __ ret();
1890}
1891
1892ASSEMBLER_TEST_RUN(Bitwise, test) {
1893 uint64_t f1 = 0;
1894 uint64_t f2 = 0;
1895 typedef int (*Bitwise)(void*, void*);
1896 int result = reinterpret_cast<Bitwise>(test->entry())(&f1, &f2);
1897 EXPECT_EQ(256 + 1, result);
1898 EXPECT_EQ(kMaxUint32, f1);
1899 EXPECT_EQ(kMaxUint32, f2);
1900 EXPECT_DISASSEMBLY_NOT_WINDOWS(
1901 "movq r10,-1\n"
1902 "orl [rdi],r10\n"
1903 "orl [rsi],r10\n"
1904 "movl rcx,0x2a\n"
1905 "xorl rcx,rcx\n"
1906 "orl rcx,0x...\n"
1907 "movl rax,4\n"
1908 "orl rcx,rax\n"
1909 "movl rax,0x....\n"
1910 "andl rcx,rax\n"
1911 "movl rax,1\n"
1912 "orl rcx,rax\n"
1913 "movl rax,rcx\n"
1914 "ret\n");
1915}
1916
1917ASSEMBLER_TEST_GENERATE(Bitwise64, assembler) {
1918 Label error;
1919 __ movq(RAX, Immediate(42));
1920 __ pushq(RAX);
1921 __ xorq(RAX, Address(RSP, 0));
1922 __ popq(RCX);
1923 __ cmpq(RAX, Immediate(0));
1924 __ j(NOT_EQUAL, &error);
1925 __ movq(RCX, Immediate(0xFF));
1926 __ movq(RAX, Immediate(0x5));
1927 __ xorq(RCX, RAX);
1928 __ cmpq(RCX, Immediate(0xFF ^ 0x5));
1929 __ j(NOT_EQUAL, &error);
1930 __ pushq(Immediate(0xFF));
1931 __ movq(RCX, Immediate(0x5));
1932 __ xorq(Address(RSP, 0), RCX);
1933 __ popq(RCX);
1934 __ cmpq(RCX, Immediate(0xFF ^ 0x5));
1935 __ j(NOT_EQUAL, &error);
1936 __ xorq(RCX, RCX);
1937 __ orq(RCX, Immediate(256));
1938 __ movq(RAX, Immediate(4));
1939 __ orq(RCX, RAX);
1940 __ movq(RAX, Immediate(0xfff0));
1941 __ andq(RCX, RAX);
1942 __ movq(RAX, Immediate(1));
1943 __ pushq(RAX);
1944 __ orq(RCX, Address(RSP, 0));
1945 __ xorq(RCX, Immediate(0));
1946 __ popq(RAX);
1947 __ movq(RAX, RCX);
1948 __ ret();
1949 __ Bind(&error);
1950 __ movq(RAX, Immediate(-1));
1951 __ ret();
1952}
1953
1954ASSEMBLER_TEST_RUN(Bitwise64, test) {
1955 typedef int (*Bitwise64)();
1956 EXPECT_EQ(256 + 1, reinterpret_cast<Bitwise64>(test->entry())());
1957 EXPECT_DISASSEMBLY(
1958 "movl rax,0x2a\n"
1959 "push rax\n"
1960 "xorq rax,[rsp]\n"
1961 "pop rcx\n"
1962 "cmpq rax,0\n"
1963 "jnz 0x................\n"
1964 "movl rcx,0xff\n"
1965 "movl rax,5\n"
1966 "xorq rcx,rax\n"
1967 "cmpq rcx,0xfa\n"
1968 "jnz 0x................\n"
1969 "push 0xff\n"
1970 "movl rcx,5\n"
1971 "xorq [rsp],rcx\n"
1972 "pop rcx\n"
1973 "cmpq rcx,0xfa\n"
1974 "jnz 0x................\n"
1975 "xorq rcx,rcx\n"
1976 "orq rcx,0x...\n"
1977 "movl rax,4\n"
1978 "orq rcx,rax\n"
1979 "movl rax,0x....\n"
1980 "andq rcx,rax\n"
1981 "movl rax,1\n"
1982 "push rax\n"
1983 "orq rcx,[rsp]\n"
1984 "xorq rcx,0\n"
1985 "pop rax\n"
1986 "movq rax,rcx\n"
1987 "ret\n"
1988 "movq rax,-1\n"
1989 "ret\n");
1990}
1991
1992ASSEMBLER_TEST_GENERATE(LogicalOps, assembler) {
1993 Label donetest1;
1994 __ movl(RAX, Immediate(4));
1995 __ andl(RAX, Immediate(2));
1996 __ cmpl(RAX, Immediate(0));
1997 __ j(EQUAL, &donetest1);
1998 // Be sure to skip this crashing code.
1999 __ movl(RAX, Immediate(0));
2000 __ movl(Address(RAX, 0), RAX);
2001 __ Bind(&donetest1);
2002
2003 Label donetest2;
2004 __ movl(RCX, Immediate(4));
2005 __ andl(RCX, Immediate(4));
2006 __ cmpl(RCX, Immediate(0));
2007 __ j(NOT_EQUAL, &donetest2);
2008 // Be sure to skip this crashing code.
2009 __ movl(RAX, Immediate(0));
2010 __ movl(Address(RAX, 0), RAX);
2011 __ Bind(&donetest2);
2012
2013 Label donetest3;
2014 __ movl(RAX, Immediate(0));
2015 __ orl(RAX, Immediate(0));
2016 __ cmpl(RAX, Immediate(0));
2017 __ j(EQUAL, &donetest3);
2018 // Be sure to skip this crashing code.
2019 __ movl(RAX, Immediate(0));
2020 __ movl(Address(RAX, 0), RAX);
2021 __ Bind(&donetest3);
2022
2023 Label donetest4;
2024 __ movl(RAX, Immediate(4));
2025 __ orl(RAX, Immediate(0));
2026 __ cmpl(RAX, Immediate(0));
2027 __ j(NOT_EQUAL, &donetest4);
2028 // Be sure to skip this crashing code.
2029 __ movl(RAX, Immediate(0));
2030 __ movl(Address(RAX, 0), RAX);
2031 __ Bind(&donetest4);
2032
2033 Label donetest5;
2034 __ pushq(RAX);
2035 __ movl(RAX, Immediate(0xff));
2036 __ movl(Address(RSP, 0), RAX);
2037 __ cmpl(Address(RSP, 0), Immediate(0xff));
2038 __ j(EQUAL, &donetest5);
2039 // Be sure to skip this crashing code.
2040 __ movq(RAX, Immediate(0));
2041 __ movq(Address(RAX, 0), RAX);
2042 __ Bind(&donetest5);
2043 __ popq(RAX);
2044
2045 Label donetest6;
2046 __ movl(RAX, Immediate(1));
2047 __ shll(RAX, Immediate(3));
2048 __ cmpl(RAX, Immediate(8));
2049 __ j(EQUAL, &donetest6);
2050 // Be sure to skip this crashing code.
2051 __ movl(RAX, Immediate(0));
2052 __ movl(Address(RAX, 0), RAX);
2053 __ Bind(&donetest6);
2054
2055 Label donetest7;
2056 __ movl(RAX, Immediate(2));
2057 __ shrl(RAX, Immediate(1));
2058 __ cmpl(RAX, Immediate(1));
2059 __ j(EQUAL, &donetest7);
2060 // Be sure to skip this crashing code.
2061 __ movl(RAX, Immediate(0));
2062 __ movl(Address(RAX, 0), RAX);
2063 __ Bind(&donetest7);
2064
2065 Label donetest8;
2066 __ movl(RAX, Immediate(8));
2067 __ shrl(RAX, Immediate(3));
2068 __ cmpl(RAX, Immediate(1));
2069 __ j(EQUAL, &donetest8);
2070 // Be sure to skip this crashing code.
2071 __ movl(RAX, Immediate(0));
2072 __ movl(Address(RAX, 0), RAX);
2073 __ Bind(&donetest8);
2074
2075 Label donetest9;
2076 __ movl(RAX, Immediate(1));
2077 __ movl(RCX, Immediate(3));
2078 __ shll(RAX, RCX);
2079 __ cmpl(RAX, Immediate(8));
2080 __ j(EQUAL, &donetest9);
2081 // Be sure to skip this crashing code.
2082 __ movl(RAX, Immediate(0));
2083 __ movl(Address(RAX, 0), RAX);
2084 __ Bind(&donetest9);
2085
2086 Label donetest10;
2087 __ movl(RAX, Immediate(8));
2088 __ movl(RCX, Immediate(3));
2089 __ shrl(RAX, RCX);
2090 __ cmpl(RAX, Immediate(1));
2091 __ j(EQUAL, &donetest10);
2092 // Be sure to skip this crashing code.
2093 __ movl(RAX, Immediate(0));
2094 __ movl(Address(RAX, 0), RAX);
2095 __ Bind(&donetest10);
2096
2097 Label donetest6a;
2098 __ movl(RAX, Immediate(1));
2099 __ shlq(RAX, Immediate(3));
2100 __ cmpl(RAX, Immediate(8));
2101 __ j(EQUAL, &donetest6a);
2102 // Be sure to skip this crashing code.
2103 __ movl(RAX, Immediate(0));
2104 __ movl(Address(RAX, 0), RAX);
2105 __ Bind(&donetest6a);
2106
2107 Label donetest7a;
2108 __ movl(RAX, Immediate(2));
2109 __ shrq(RAX, Immediate(1));
2110 __ cmpl(RAX, Immediate(1));
2111 __ j(EQUAL, &donetest7a);
2112 // Be sure to skip this crashing code.
2113 __ movl(RAX, Immediate(0));
2114 __ movl(Address(RAX, 0), RAX);
2115 __ Bind(&donetest7a);
2116
2117 Label donetest8a;
2118 __ movl(RAX, Immediate(8));
2119 __ shrq(RAX, Immediate(3));
2120 __ cmpl(RAX, Immediate(1));
2121 __ j(EQUAL, &donetest8a);
2122 // Be sure to skip this crashing code.
2123 __ movl(RAX, Immediate(0));
2124 __ movl(Address(RAX, 0), RAX);
2125 __ Bind(&donetest8a);
2126
2127 Label donetest9a;
2128 __ movl(RAX, Immediate(1));
2129 __ movl(RCX, Immediate(3));
2130 __ shlq(RAX, RCX);
2131 __ cmpl(RAX, Immediate(8));
2132 __ j(EQUAL, &donetest9a);
2133 // Be sure to skip this crashing code.
2134 __ movl(RAX, Immediate(0));
2135 __ movl(Address(RAX, 0), RAX);
2136 __ Bind(&donetest9a);
2137
2138 Label donetest10a;
2139 __ movl(RAX, Immediate(8));
2140 __ movl(RCX, Immediate(3));
2141 __ shrq(RAX, RCX);
2142 __ cmpl(RAX, Immediate(1));
2143 __ j(EQUAL, &donetest10a);
2144 // Be sure to skip this crashing code.
2145 __ movl(RAX, Immediate(0));
2146 __ movl(Address(RAX, 0), RAX);
2147 __ Bind(&donetest10a);
2148
2149 Label donetest11a;
2150 __ movl(RAX, Immediate(1));
2151 __ shlq(RAX, Immediate(31));
2152 __ shrq(RAX, Immediate(3));
2153 __ cmpq(RAX, Immediate(0x10000000));
2154 __ j(EQUAL, &donetest11a);
2155 // Be sure to skip this crashing code.
2156 __ movl(RAX, Immediate(0));
2157 __ movl(Address(RAX, 0), RAX);
2158 __ Bind(&donetest11a);
2159
2160 Label donetest12a;
2161 __ movl(RAX, Immediate(1));
2162 __ shlq(RAX, Immediate(31));
2163 __ sarl(RAX, Immediate(3));
2164 __ cmpl(RAX, Immediate(0xfffffffff0000000));
2165 __ j(EQUAL, &donetest12a);
2166 // Be sure to skip this crashing code.
2167 __ movl(RAX, Immediate(0));
2168 __ movl(Address(RAX, 0), RAX);
2169 __ Bind(&donetest12a);
2170
2171 Label donetest13a;
2172 __ movl(RAX, Immediate(1));
2173 __ movl(RCX, Immediate(3));
2174 __ shlq(RAX, Immediate(31));
2175 __ sarl(RAX, RCX);
2176 __ cmpl(RAX, Immediate(0xfffffffff0000000));
2177 __ j(EQUAL, &donetest13a);
2178 // Be sure to skip this crashing code.
2179 __ movl(RAX, Immediate(0));
2180 __ movl(Address(RAX, 0), RAX);
2181 __ Bind(&donetest13a);
2182
2183 {
2184 Label donetest15a;
2185 const int32_t left = 0xff000000;
2186 const int32_t right = 0xffffffff;
2187 const int32_t shifted = 0xf0000003;
2188 __ movl(RDX, Immediate(left));
2189 __ movl(R8, Immediate(right));
2190 __ movl(RCX, Immediate(2));
2191 __ shll(RDX, RCX); // RDX = 0xff000000 << 2 == 0xfc000000
2192 __ shldl(RDX, R8, Immediate(2));
2193 // RDX = high32(0xfc000000:0xffffffff << 2) == 0xf0000003
2194 __ cmpl(RDX, Immediate(shifted));
2195 __ j(EQUAL, &donetest15a);
2196 __ int3();
2197 __ Bind(&donetest15a);
2198 }
2199
2200 {
2201 Label donetest15b;
2202 const int64_t left = 0xff00000000000000;
2203 const int64_t right = 0xffffffffffffffff;
2204 const int64_t shifted = 0xf000000000000003;
2205 __ movq(RDX, Immediate(left));
2206 __ movq(R8, Immediate(right));
2207 __ movq(RCX, Immediate(2));
2208 __ shlq(RDX, RCX); // RDX = 0xff00000000000000 << 2 == 0xfc00000000000000
2209 __ shldq(RDX, R8, Immediate(2));
2210 // RDX = high64(0xfc00000000000000:0xffffffffffffffff << 2)
2211 // == 0xf000000000000003
2212 __ cmpq(RDX, Immediate(shifted));
2213 __ j(EQUAL, &donetest15b);
2214 __ int3();
2215 __ Bind(&donetest15b);
2216 }
2217
2218 {
2219 Label donetest15c;
2220 const int64_t left = 0xff00000000000000;
2221 const int64_t right = 0xffffffffffffffff;
2222 const int64_t shifted = 0xf000000000000003;
2223 __ movq(RDX, Immediate(left));
2224 __ movq(R8, Immediate(right));
2225 __ movq(RCX, Immediate(2));
2226 __ shlq(RDX, RCX); // RDX = 0xff00000000000000 << 2 == 0xfc00000000000000
2227 __ shldq(RDX, R8, RCX);
2228 // RDX = high64(0xfc00000000000000:0xffffffffffffffff << 2)
2229 // == 0xf000000000000003
2230 __ cmpq(RDX, Immediate(shifted));
2231 __ j(EQUAL, &donetest15c);
2232 __ int3();
2233 __ Bind(&donetest15c);
2234 }
2235
2236 {
2237 Label donetest15d;
2238 const int64_t left = 0xff00000000000000;
2239 const int64_t right = 0xffffffffffffffff;
2240 const int64_t shifted = 0xcff0000000000000;
2241 __ movq(RDX, Immediate(left));
2242 __ movq(R8, Immediate(right));
2243 __ movq(RCX, Immediate(2));
2244 __ shrq(RDX, RCX); // RDX = 0xff00000000000000 >> 2 == 0x3fc0000000000000
2245 __ shrdq(RDX, R8, RCX);
2246 // RDX = low64(0xffffffffffffffff:0x3fc0000000000000 >> 2)
2247 // == 0xcff0000000000000
2248 __ cmpq(RDX, Immediate(shifted));
2249 __ j(EQUAL, &donetest15d);
2250 __ int3();
2251 __ Bind(&donetest15d);
2252 }
2253
2254 __ movl(RAX, Immediate(0));
2255 __ ret();
2256}
2257
2258ASSEMBLER_TEST_RUN(LogicalOps, test) {
2259 typedef int (*LogicalOpsCode)();
2260 EXPECT_EQ(0, reinterpret_cast<LogicalOpsCode>(test->entry())());
2261 EXPECT_DISASSEMBLY(
2262 "movl rax,4\n"
2263 "andl rax,2\n"
2264 "cmpl rax,0\n"
2265 "jz 0x................\n"
2266 "movl rax,0\n"
2267 "movl [rax],rax\n"
2268 "movl rcx,4\n"
2269 "andl rcx,4\n"
2270 "cmpl rcx,0\n"
2271 "jnz 0x................\n"
2272 "movl rax,0\n"
2273 "movl [rax],rax\n"
2274 "movl rax,0\n"
2275 "orl rax,0\n"
2276 "cmpl rax,0\n"
2277 "jz 0x................\n"
2278 "movl rax,0\n"
2279 "movl [rax],rax\n"
2280 "movl rax,4\n"
2281 "orl rax,0\n"
2282 "cmpl rax,0\n"
2283 "jnz 0x................\n"
2284 "movl rax,0\n"
2285 "movl [rax],rax\n"
2286 "push rax\n"
2287 "movl rax,0xff\n"
2288 "movl [rsp],rax\n"
2289 "cmpl [rsp],0xff\n"
2290 "jz 0x................\n"
2291 "movl rax,0\n"
2292 "movq [rax],rax\n"
2293 "pop rax\n"
2294 "movl rax,1\n"
2295 "shll rax,3\n"
2296 "cmpl rax,8\n"
2297 "jz 0x................\n"
2298 "movl rax,0\n"
2299 "movl [rax],rax\n"
2300 "movl rax,2\n"
2301 "shrl rax,1\n"
2302 "cmpl rax,1\n"
2303 "jz 0x................\n"
2304 "movl rax,0\n"
2305 "movl [rax],rax\n"
2306 "movl rax,8\n"
2307 "shrl rax,3\n"
2308 "cmpl rax,1\n"
2309 "jz 0x................\n"
2310 "movl rax,0\n"
2311 "movl [rax],rax\n"
2312 "movl rax,1\n"
2313 "movl rcx,3\n"
2314 "shll rax,cl\n"
2315 "cmpl rax,8\n"
2316 "jz 0x................\n"
2317 "movl rax,0\n"
2318 "movl [rax],rax\n"
2319 "movl rax,8\n"
2320 "movl rcx,3\n"
2321 "shrl rax,cl\n"
2322 "cmpl rax,1\n"
2323 "jz 0x................\n"
2324 "movl rax,0\n"
2325 "movl [rax],rax\n"
2326 "movl rax,1\n"
2327 "shlq rax,3\n"
2328 "cmpl rax,8\n"
2329 "jz 0x................\n"
2330 "movl rax,0\n"
2331 "movl [rax],rax\n"
2332 "movl rax,2\n"
2333 "shrq rax,1\n"
2334 "cmpl rax,1\n"
2335 "jz 0x................\n"
2336 "movl rax,0\n"
2337 "movl [rax],rax\n"
2338 "movl rax,8\n"
2339 "shrq rax,3\n"
2340 "cmpl rax,1\n"
2341 "jz 0x................\n"
2342 "movl rax,0\n"
2343 "movl [rax],rax\n"
2344 "movl rax,1\n"
2345 "movl rcx,3\n"
2346 "shlq rax,cl\n"
2347 "cmpl rax,8\n"
2348 "jz 0x................\n"
2349 "movl rax,0\n"
2350 "movl [rax],rax\n"
2351 "movl rax,8\n"
2352 "movl rcx,3\n"
2353 "shrq rax,cl\n"
2354 "cmpl rax,1\n"
2355 "jz 0x................\n"
2356 "movl rax,0\n"
2357 "movl [rax],rax\n"
2358 "movl rax,1\n"
2359 "shlq rax,31\n"
2360 "shrq rax,3\n"
2361 "cmpq rax,0x........\n"
2362 "jz 0x................\n"
2363 "movl rax,0\n"
2364 "movl [rax],rax\n"
2365 "movl rax,1\n"
2366 "shlq rax,31\n"
2367 "sarl rax,3\n"
2368 "cmpl rax,0x........\n"
2369 "jz 0x................\n"
2370 "movl rax,0\n"
2371 "movl [rax],rax\n"
2372 "movl rax,1\n"
2373 "movl rcx,3\n"
2374 "shlq rax,31\n"
2375 "sarl rax,cl\n"
2376 "cmpl rax,0x........\n"
2377 "jz 0x................\n"
2378 "movl rax,0\n"
2379 "movl [rax],rax\n"
2380 "movl rdx,-0x........\n"
2381 "movl r8,-1\n"
2382 "movl rcx,2\n"
2383 "shll rdx,cl\n"
2384 "shldl rdx,r8,2\n"
2385 "cmpl rdx,0x........\n"
2386 "jz 0x................\n"
2387 "int3\n"
2388 "movq rdx,0x................\n"
2389 "movq r8,-1\n"
2390 "movl rcx,2\n"
2391 "shlq rdx,cl\n"
2392 "shldq rdx,r8,2\n"
2393 "movq r11,0x................\n"
2394 "cmpq rdx,r11\n"
2395 "jz 0x................\n"
2396 "int3\n"
2397 "movq rdx,0x................\n"
2398 "movq r8,-1\n"
2399 "movl rcx,2\n"
2400 "shlq rdx,cl\n"
2401 "shldq rdx,r8,cl\n"
2402 "movq r11,0x................\n"
2403 "cmpq rdx,r11\n"
2404 "jz 0x................\n"
2405 "int3\n"
2406 "movq rdx,0x................\n"
2407 "movq r8,-1\n"
2408 "movl rcx,2\n"
2409 "shrq rdx,cl\n"
2410 "shrdq rdx,r8,cl\n"
2411 "movq r11,0x................\n"
2412 "cmpq rdx,r11\n"
2413 "jz 0x................\n"
2414 "int3\n"
2415 "movl rax,0\n"
2416 "ret\n");
2417}
2418
2419ASSEMBLER_TEST_GENERATE(LogicalOps64, assembler) {
2420 Label donetest1;
2421 __ movq(RAX, Immediate(4));
2422 __ andq(RAX, Immediate(2));
2423 __ cmpq(RAX, Immediate(0));
2424 __ j(EQUAL, &donetest1);
2425 __ int3();
2426 __ Bind(&donetest1);
2427
2428 Label donetest2;
2429 __ movq(RCX, Immediate(4));
2430 __ pushq(RCX);
2431 __ andq(RCX, Address(RSP, 0));
2432 __ popq(RAX);
2433 __ cmpq(RCX, Immediate(0));
2434 __ j(NOT_EQUAL, &donetest2);
2435 __ int3();
2436 __ Bind(&donetest2);
2437
2438 Label donetest3;
2439 __ movq(RAX, Immediate(0));
2440 __ orq(RAX, Immediate(0));
2441 __ cmpq(RAX, Immediate(0));
2442 __ j(EQUAL, &donetest3);
2443 __ int3();
2444 __ Bind(&donetest3);
2445
2446 Label donetest4;
2447 __ movq(RAX, Immediate(4));
2448 __ orq(RAX, Immediate(0));
2449 __ cmpq(RAX, Immediate(0));
2450 __ j(NOT_EQUAL, &donetest4);
2451 __ int3();
2452 __ Bind(&donetest4);
2453
2454 Label donetest5;
2455 __ pushq(RAX);
2456 __ movq(RAX, Immediate(0xff));
2457 __ movq(Address(RSP, 0), RAX);
2458 __ cmpq(Address(RSP, 0), Immediate(0xff));
2459 __ j(EQUAL, &donetest5);
2460 __ int3();
2461 __ Bind(&donetest5);
2462 __ popq(RAX);
2463
2464 Label donetest6;
2465 __ movq(RAX, Immediate(1));
2466 __ shlq(RAX, Immediate(3));
2467 __ cmpq(RAX, Immediate(8));
2468 __ j(EQUAL, &donetest6);
2469 __ int3();
2470 __ Bind(&donetest6);
2471
2472 Label donetest7;
2473 __ movq(RAX, Immediate(2));
2474 __ shrq(RAX, Immediate(1));
2475 __ cmpq(RAX, Immediate(1));
2476 __ j(EQUAL, &donetest7);
2477 __ int3();
2478 __ Bind(&donetest7);
2479
2480 Label donetest8;
2481 __ movq(RAX, Immediate(8));
2482 __ shrq(RAX, Immediate(3));
2483 __ cmpq(RAX, Immediate(1));
2484 __ j(EQUAL, &donetest8);
2485 __ int3();
2486 __ Bind(&donetest8);
2487
2488 Label donetest9;
2489 __ movq(RAX, Immediate(1));
2490 __ movq(RCX, Immediate(3));
2491 __ shlq(RAX, RCX);
2492 __ cmpq(RAX, Immediate(8));
2493 __ j(EQUAL, &donetest9);
2494 __ int3();
2495 __ Bind(&donetest9);
2496
2497 Label donetest10;
2498 __ movq(RAX, Immediate(8));
2499 __ movq(RCX, Immediate(3));
2500 __ shrq(RAX, RCX);
2501 __ cmpq(RAX, Immediate(1));
2502 __ j(EQUAL, &donetest10);
2503 __ int3();
2504 __ Bind(&donetest10);
2505
2506 Label donetest6a;
2507 __ movq(RAX, Immediate(1));
2508 __ shlq(RAX, Immediate(3));
2509 __ cmpq(RAX, Immediate(8));
2510 __ j(EQUAL, &donetest6a);
2511 // Be sure to skip this crashing code.
2512 __ movq(RAX, Immediate(0));
2513 __ movq(Address(RAX, 0), RAX);
2514 __ Bind(&donetest6a);
2515
2516 Label donetest7a;
2517 __ movq(RAX, Immediate(2));
2518 __ shrq(RAX, Immediate(1));
2519 __ cmpq(RAX, Immediate(1));
2520 __ j(EQUAL, &donetest7a);
2521 __ int3();
2522 __ Bind(&donetest7a);
2523
2524 Label donetest8a;
2525 __ movq(RAX, Immediate(8));
2526 __ shrq(RAX, Immediate(3));
2527 __ cmpq(RAX, Immediate(1));
2528 __ j(EQUAL, &donetest8a);
2529 __ int3();
2530 __ Bind(&donetest8a);
2531
2532 Label donetest9a;
2533 __ movq(RAX, Immediate(1));
2534 __ movq(RCX, Immediate(3));
2535 __ shlq(RAX, RCX);
2536 __ cmpq(RAX, Immediate(8));
2537 __ j(EQUAL, &donetest9a);
2538 __ int3();
2539 __ Bind(&donetest9a);
2540
2541 Label donetest10a;
2542 __ movq(RAX, Immediate(8));
2543 __ movq(RCX, Immediate(3));
2544 __ shrq(RAX, RCX);
2545 __ cmpq(RAX, Immediate(1));
2546 __ j(EQUAL, &donetest10a);
2547 __ int3();
2548 __ Bind(&donetest10a);
2549
2550 Label donetest11a;
2551 __ movq(RAX, Immediate(1));
2552 __ shlq(RAX, Immediate(31));
2553 __ shrq(RAX, Immediate(3));
2554 __ cmpq(RAX, Immediate(0x10000000));
2555 __ j(EQUAL, &donetest11a);
2556 __ int3();
2557 __ Bind(&donetest11a);
2558
2559 Label donetest12a;
2560 __ movq(RAX, Immediate(1));
2561 __ shlq(RAX, Immediate(63));
2562 __ sarq(RAX, Immediate(3));
2563 __ cmpq(RAX, Immediate(0xf000000000000000));
2564 __ j(EQUAL, &donetest12a);
2565 __ int3();
2566 __ Bind(&donetest12a);
2567
2568 Label donetest13a;
2569 __ movq(RAX, Immediate(1));
2570 __ movq(RCX, Immediate(3));
2571 __ shlq(RAX, Immediate(63));
2572 __ sarq(RAX, RCX);
2573 __ cmpq(RAX, Immediate(0xf000000000000000));
2574 __ j(EQUAL, &donetest13a);
2575 __ int3();
2576 __ Bind(&donetest13a);
2577
2578 Label donetest14, donetest15;
2579 __ pushq(R15); // Callee saved.
2580 __ movq(R15, Immediate(0xf000000000000001));
2581 __ andq(R15, Immediate(-1));
2582 __ andq(R15, Immediate(0x8000000000000001));
2583 __ orq(R15, Immediate(2));
2584 __ orq(R15, Immediate(0xf800000000000000));
2585 __ xorq(R15, Immediate(1));
2586 __ xorq(R15, Immediate(0x0800000000000000));
2587 __ cmpq(R15, Immediate(0xf000000000000002));
2588 __ j(EQUAL, &donetest14);
2589 __ int3();
2590 __ Bind(&donetest14);
2591 __ andq(R15, Immediate(2));
2592 __ cmpq(R15, Immediate(2));
2593 __ j(EQUAL, &donetest15);
2594 __ int3();
2595 __ Bind(&donetest15);
2596 __ popq(R15); // Callee saved.
2597
2598 __ movq(RAX, Immediate(0));
2599 __ ret();
2600}
2601
2602ASSEMBLER_TEST_RUN(LogicalOps64, test) {
2603 typedef int (*LogicalOpsCode)();
2604 EXPECT_EQ(0, reinterpret_cast<LogicalOpsCode>(test->entry())());
2605 EXPECT_DISASSEMBLY(
2606 "movl rax,4\n"
2607 "andl rax,2\n"
2608 "cmpq rax,0\n"
2609 "jz 0x................\n"
2610 "int3\n"
2611 "movl rcx,4\n"
2612 "push rcx\n"
2613 "andq rcx,[rsp]\n"
2614 "pop rax\n"
2615 "cmpq rcx,0\n"
2616 "jnz 0x................\n"
2617 "int3\n"
2618 "movl rax,0\n"
2619 "orq rax,0\n"
2620 "cmpq rax,0\n"
2621 "jz 0x................\n"
2622 "int3\n"
2623 "movl rax,4\n"
2624 "orq rax,0\n"
2625 "cmpq rax,0\n"
2626 "jnz 0x................\n"
2627 "int3\n"
2628 "push rax\n"
2629 "movl rax,0xff\n"
2630 "movq [rsp],rax\n"
2631 "cmpq [rsp],0xff\n"
2632 "jz 0x................\n"
2633 "int3\n"
2634 "pop rax\n"
2635 "movl rax,1\n"
2636 "shlq rax,3\n"
2637 "cmpq rax,8\n"
2638 "jz 0x................\n"
2639 "int3\n"
2640 "movl rax,2\n"
2641 "shrq rax,1\n"
2642 "cmpq rax,1\n"
2643 "jz 0x................\n"
2644 "int3\n"
2645 "movl rax,8\n"
2646 "shrq rax,3\n"
2647 "cmpq rax,1\n"
2648 "jz 0x................\n"
2649 "int3\n"
2650 "movl rax,1\n"
2651 "movl rcx,3\n"
2652 "shlq rax,cl\n"
2653 "cmpq rax,8\n"
2654 "jz 0x................\n"
2655 "int3\n"
2656 "movl rax,8\n"
2657 "movl rcx,3\n"
2658 "shrq rax,cl\n"
2659 "cmpq rax,1\n"
2660 "jz 0x................\n"
2661 "int3\n"
2662 "movl rax,1\n"
2663 "shlq rax,3\n"
2664 "cmpq rax,8\n"
2665 "jz 0x................\n"
2666 "movl rax,0\n"
2667 "movq [rax],rax\n"
2668 "movl rax,2\n"
2669 "shrq rax,1\n"
2670 "cmpq rax,1\n"
2671 "jz 0x................\n"
2672 "int3\n"
2673 "movl rax,8\n"
2674 "shrq rax,3\n"
2675 "cmpq rax,1\n"
2676 "jz 0x................\n"
2677 "int3\n"
2678 "movl rax,1\n"
2679 "movl rcx,3\n"
2680 "shlq rax,cl\n"
2681 "cmpq rax,8\n"
2682 "jz 0x................\n"
2683 "int3\n"
2684 "movl rax,8\n"
2685 "movl rcx,3\n"
2686 "shrq rax,cl\n"
2687 "cmpq rax,1\n"
2688 "jz 0x................\n"
2689 "int3\n"
2690 "movl rax,1\n"
2691 "shlq rax,31\n"
2692 "shrq rax,3\n"
2693 "cmpq rax,0x........\n"
2694 "jz 0x................\n"
2695 "int3\n"
2696 "movl rax,1\n"
2697 "shlq rax,63\n"
2698 "sarq rax,3\n"
2699 "movq r11,0x................\n"
2700 "cmpq rax,r11\n"
2701 "jz 0x................\n"
2702 "int3\n"
2703 "movl rax,1\n"
2704 "movl rcx,3\n"
2705 "shlq rax,63\n"
2706 "sarq rax,cl\n"
2707 "movq r11,0x................\n"
2708 "cmpq rax,r11\n"
2709 "jz 0x................\n"
2710 "int3\n"
2711 "push pp\n"
2712 "movq pp,0x................\n"
2713 "andq pp,-1\n"
2714 "movq r11,0x................\n"
2715 "andq pp,r11\n"
2716 "orq pp,2\n"
2717 "movq r11,0x................\n"
2718 "orq pp,r11\n"
2719 "xorq pp,1\n"
2720 "movq r11,0x................\n"
2721 "xorq pp,r11\n"
2722 "movq r11,0x................\n"
2723 "cmpq pp,r11\n"
2724 "jz 0x................\n"
2725 "int3\n"
2726 "andl pp,2\n"
2727 "cmpq pp,2\n"
2728 "jz 0x................\n"
2729 "int3\n"
2730 "pop pp\n"
2731 "movl rax,0\n"
2732 "ret\n");
2733}
2734
2735ASSEMBLER_TEST_GENERATE(LogicalTestL, assembler) {
2736 Label donetest1;
2737 __ movl(RAX, Immediate(4));
2738 __ movl(RCX, Immediate(2));
2739 __ testl(RAX, RCX);
2740 __ j(EQUAL, &donetest1);
2741 // Be sure to skip this crashing code.
2742 __ movl(RAX, Immediate(0));
2743 __ movl(Address(RAX, 0), RAX);
2744 __ Bind(&donetest1);
2745
2746 Label donetest2;
2747 __ movl(RDX, Immediate(4));
2748 __ movl(RCX, Immediate(4));
2749 __ testl(RDX, RCX);
2750 __ j(NOT_EQUAL, &donetest2);
2751 // Be sure to skip this crashing code.
2752 __ movl(RAX, Immediate(0));
2753 __ movl(Address(RAX, 0), RAX);
2754 __ Bind(&donetest2);
2755
2756 Label donetest3;
2757 __ movl(RAX, Immediate(0));
2758 __ testl(RAX, Immediate(0));
2759 __ j(EQUAL, &donetest3);
2760 // Be sure to skip this crashing code.
2761 __ movl(RAX, Immediate(0));
2762 __ movl(Address(RAX, 0), RAX);
2763 __ Bind(&donetest3);
2764
2765 Label donetest4;
2766 __ movl(RCX, Immediate(4));
2767 __ testl(RCX, Immediate(4));
2768 __ j(NOT_EQUAL, &donetest4);
2769 // Be sure to skip this crashing code.
2770 __ movl(RAX, Immediate(0));
2771 __ movl(Address(RAX, 0), RAX);
2772 __ Bind(&donetest4);
2773
2774 __ movl(RAX, Immediate(0));
2775 __ ret();
2776}
2777
2778ASSEMBLER_TEST_RUN(LogicalTestL, test) {
2779 typedef int (*LogicalTestCode)();
2780 EXPECT_EQ(0, reinterpret_cast<LogicalTestCode>(test->entry())());
2781 EXPECT_DISASSEMBLY(
2782 "movl rax,4\n"
2783 "movl rcx,2\n"
2784 "testl rax,rcx\n"
2785 "jz 0x................\n"
2786 "movl rax,0\n"
2787 "movl [rax],rax\n"
2788 "movl rdx,4\n"
2789 "movl rcx,4\n"
2790 "testl rdx,rcx\n"
2791 "jnz 0x................\n"
2792 "movl rax,0\n"
2793 "movl [rax],rax\n"
2794 "movl rax,0\n"
2795 "test al,0\n"
2796 "jz 0x................\n"
2797 "movl rax,0\n"
2798 "movl [rax],rax\n"
2799 "movl rcx,4\n"
2800 "testb rcx,4\n"
2801 "jnz 0x................\n"
2802 "movl rax,0\n"
2803 "movl [rax],rax\n"
2804 "movl rax,0\n"
2805 "ret\n");
2806}
2807
2808ASSEMBLER_TEST_GENERATE(LogicalTestQ, assembler) {
2809 Label donetest1;
2810 __ movq(RAX, Immediate(4));
2811 __ movq(RCX, Immediate(2));
2812 __ testq(RAX, RCX);
2813 __ j(EQUAL, &donetest1);
2814 // Be sure to skip this crashing code.
2815 __ movq(RAX, Immediate(0));
2816 __ movq(Address(RAX, 0), RAX);
2817 __ Bind(&donetest1);
2818
2819 Label donetest2;
2820 __ movq(RDX, Immediate(4));
2821 __ movq(RCX, Immediate(4));
2822 __ testq(RDX, RCX);
2823 __ j(NOT_EQUAL, &donetest2);
2824 // Be sure to skip this crashing code.
2825 __ movq(RAX, Immediate(0));
2826 __ movq(Address(RAX, 0), RAX);
2827 __ Bind(&donetest2);
2828
2829 Label donetest3;
2830 __ movq(RAX, Immediate(0));
2831 __ testq(RAX, Immediate(0));
2832 __ j(EQUAL, &donetest3);
2833 // Be sure to skip this crashing code.
2834 __ movq(RAX, Immediate(0));
2835 __ movq(Address(RAX, 0), RAX);
2836 __ Bind(&donetest3);
2837
2838 Label donetest4;
2839 __ movq(RCX, Immediate(4));
2840 __ testq(RCX, Immediate(4));
2841 __ j(NOT_EQUAL, &donetest4);
2842 // Be sure to skip this crashing code.
2843 __ movq(RAX, Immediate(0));
2844 __ movq(Address(RAX, 0), RAX);
2845 __ Bind(&donetest4);
2846
2847 Label donetest5;
2848 __ movq(RCX, Immediate(0xff));
2849 __ testq(RCX, Immediate(0xff));
2850 __ j(NOT_EQUAL, &donetest5);
2851 // Be sure to skip this crashing code.
2852 __ movq(RAX, Immediate(0));
2853 __ movq(Address(RAX, 0), RAX);
2854 __ Bind(&donetest5);
2855
2856 Label donetest6;
2857 __ movq(RAX, Immediate(0xff));
2858 __ testq(RAX, Immediate(0xff));
2859 __ j(NOT_EQUAL, &donetest6);
2860 // Be sure to skip this crashing code.
2861 __ movq(RAX, Immediate(0));
2862 __ movq(Address(RAX, 0), RAX);
2863 __ Bind(&donetest6);
2864
2865 __ movq(RAX, Immediate(0));
2866 __ ret();
2867}
2868
2869ASSEMBLER_TEST_RUN(LogicalTestQ, test) {
2870 typedef int (*LogicalTestCode)();
2871 EXPECT_EQ(0, reinterpret_cast<LogicalTestCode>(test->entry())());
2872 EXPECT_DISASSEMBLY(
2873 "movl rax,4\n"
2874 "movl rcx,2\n"
2875 "testq rax,rcx\n"
2876 "jz 0x................\n"
2877 "movl rax,0\n"
2878 "movq [rax],rax\n"
2879 "movl rdx,4\n"
2880 "movl rcx,4\n"
2881 "testq rdx,rcx\n"
2882 "jnz 0x................\n"
2883 "movl rax,0\n"
2884 "movq [rax],rax\n"
2885 "movl rax,0\n"
2886 "test al,0\n"
2887 "jz 0x................\n"
2888 "movl rax,0\n"
2889 "movq [rax],rax\n"
2890 "movl rcx,4\n"
2891 "testb rcx,4\n"
2892 "jnz 0x................\n"
2893 "movl rax,0\n"
2894 "movq [rax],rax\n"
2895 "movl rcx,0xff\n"
2896 "testb rcx,0xff\n"
2897 "jnz 0x................\n"
2898 "movl rax,0\n"
2899 "movq [rax],rax\n"
2900 "movl rax,0xff\n"
2901 "test al,0xff\n"
2902 "jnz 0x................\n"
2903 "movl rax,0\n"
2904 "movq [rax],rax\n"
2905 "movl rax,0\n"
2906 "ret\n");
2907}
2908
2909ASSEMBLER_TEST_GENERATE(CompareSwapEQ, assembler) {
2910 __ movq(RAX, Immediate(0));
2911 __ pushq(RAX);
2912 __ movq(RAX, Immediate(4));
2913 __ movq(RCX, Immediate(0));
2914 __ movq(Address(RSP, 0), RAX);
2915 __ LockCmpxchgq(Address(RSP, 0), RCX);
2916 __ popq(RAX);
2917 __ ret();
2918}
2919
2920ASSEMBLER_TEST_RUN(CompareSwapEQ, test) {
2921 typedef int (*CompareSwapEQCode)();
2922 EXPECT_EQ(0, reinterpret_cast<CompareSwapEQCode>(test->entry())());
2923 EXPECT_DISASSEMBLY(
2924 "movl rax,0\n"
2925 "push rax\n"
2926 "movl rax,4\n"
2927 "movl rcx,0\n"
2928 "movq [rsp],rax\n"
2929 "lock cmpxchgq rcx,[rsp]\n"
2930 "pop rax\n"
2931 "ret\n");
2932}
2933
2934ASSEMBLER_TEST_GENERATE(CompareSwapNEQ, assembler) {
2935 __ movq(RAX, Immediate(0));
2936 __ pushq(RAX);
2937 __ movq(RAX, Immediate(2));
2938 __ movq(RCX, Immediate(4));
2939 __ movq(Address(RSP, 0), RCX);
2940 __ LockCmpxchgq(Address(RSP, 0), RCX);
2941 __ popq(RAX);
2942 __ ret();
2943}
2944
2945ASSEMBLER_TEST_RUN(CompareSwapNEQ, test) {
2946 typedef int (*CompareSwapNEQCode)();
2947 EXPECT_EQ(4, reinterpret_cast<CompareSwapNEQCode>(test->entry())());
2948 EXPECT_DISASSEMBLY(
2949 "movl rax,0\n"
2950 "push rax\n"
2951 "movl rax,2\n"
2952 "movl rcx,4\n"
2953 "movq [rsp],rcx\n"
2954 "lock cmpxchgq rcx,[rsp]\n"
2955 "pop rax\n"
2956 "ret\n");
2957}
2958
2959ASSEMBLER_TEST_GENERATE(CompareSwapEQ32, assembler) {
2960 __ movq(RAX, Immediate(0x100000000));
2961 __ pushq(RAX);
2962 __ movq(RAX, Immediate(4));
2963 __ movq(RCX, Immediate(0));
2964 // 32 bit store of 4.
2965 __ movl(Address(RSP, 0), RAX);
2966 // Compare 32 bit memory location with RAX (4) and write 0.
2967 __ LockCmpxchgl(Address(RSP, 0), RCX);
2968 // Pop unchanged high word and zeroed out low word.
2969 __ popq(RAX);
2970 __ ret();
2971}
2972
2973ASSEMBLER_TEST_RUN(CompareSwapEQ32, test) {
2974 typedef intptr_t (*CompareSwapEQ32Code)();
2975 EXPECT_EQ(0x100000000,
2976 reinterpret_cast<CompareSwapEQ32Code>(test->entry())());
2977 EXPECT_DISASSEMBLY(
2978 "movq rax,0x................\n"
2979 "push rax\n"
2980 "movl rax,4\n"
2981 "movl rcx,0\n"
2982 "movl [rsp],rax\n"
2983 "lock cmpxchgl rcx,[rsp]\n"
2984 "pop rax\n"
2985 "ret\n");
2986}
2987
2988ASSEMBLER_TEST_GENERATE(CompareSwapNEQ32, assembler) {
2989 __ movq(RAX, Immediate(0x100000000));
2990 __ pushq(RAX);
2991 __ movq(RAX, Immediate(2));
2992 __ movq(RCX, Immediate(4));
2993 __ movl(Address(RSP, 0), RCX);
2994 __ LockCmpxchgl(Address(RSP, 0), RCX);
2995 __ popq(RAX);
2996 __ ret();
2997}
2998
2999ASSEMBLER_TEST_RUN(CompareSwapNEQ32, test) {
3000 typedef intptr_t (*CompareSwapNEQ32Code)();
3001 EXPECT_EQ(0x100000004l,
3002 reinterpret_cast<CompareSwapNEQ32Code>(test->entry())());
3003 EXPECT_DISASSEMBLY(
3004 "movq rax,0x................\n"
3005 "push rax\n"
3006 "movl rax,2\n"
3007 "movl rcx,4\n"
3008 "movl [rsp],rcx\n"
3009 "lock cmpxchgl rcx,[rsp]\n"
3010 "pop rax\n"
3011 "ret\n");
3012}
3013
3014ASSEMBLER_TEST_GENERATE(Exchange, assembler) {
3015 __ movq(RAX, Immediate(kLargeConstant));
3016 __ movq(RDX, Immediate(kAnotherLargeConstant));
3017 __ xchgq(RAX, RDX);
3018 __ subq(RAX, RDX);
3019 __ ret();
3020}
3021
3022ASSEMBLER_TEST_RUN(Exchange, test) {
3023 typedef int64_t (*Exchange)();
3024 EXPECT_EQ(kAnotherLargeConstant - kLargeConstant,
3025 reinterpret_cast<Exchange>(test->entry())());
3026 EXPECT_DISASSEMBLY(
3027 "movq rax,0x................\n"
3028 "movq rdx,0x................\n"
3029 "xchgq rax,rdx\n"
3030 "subq rax,rdx\n"
3031 "ret\n");
3032}
3033
3034ASSEMBLER_TEST_GENERATE(LargeConstant, assembler) {
3035 __ movq(RAX, Immediate(kLargeConstant));
3036 __ ret();
3037}
3038
3039ASSEMBLER_TEST_RUN(LargeConstant, test) {
3040 typedef int64_t (*LargeConstantCode)();
3041 EXPECT_EQ(kLargeConstant,
3042 reinterpret_cast<LargeConstantCode>(test->entry())());
3043 EXPECT_DISASSEMBLY(
3044 "movq rax,0x................\n"
3045 "ret\n");
3046}
3047
3048static int ComputeStackSpaceReservation(int needed, int fixed) {
3049 return (OS::ActivationFrameAlignment() > 1)
3050 ? Utils::RoundUp(needed + fixed, OS::ActivationFrameAlignment()) -
3051 fixed
3052 : needed;
3053}
3054
3055static int LeafReturn42() {
3056 return 42;
3057}
3058
3059static int LeafReturnArgument(int x) {
3060 return x + 87;
3061}
3062
3063ASSEMBLER_TEST_GENERATE(CallSimpleLeaf, assembler) {
3064 ExternalLabel call1(reinterpret_cast<uword>(LeafReturn42));
3065 ExternalLabel call2(reinterpret_cast<uword>(LeafReturnArgument));
3066 int space = ComputeStackSpaceReservation(0, 8);
3067 __ subq(RSP, Immediate(space));
3068 __ call(&call1);
3069 __ addq(RSP, Immediate(space));
3070 space = ComputeStackSpaceReservation(0, 8);
3071 __ subq(RSP, Immediate(space));
3072 __ movl(CallingConventions::kArg1Reg, RAX);
3073 __ call(&call2);
3074 __ addq(RSP, Immediate(space));
3075 __ ret();
3076}
3077
3078ASSEMBLER_TEST_RUN(CallSimpleLeaf, test) {
3079 typedef int (*CallSimpleLeafCode)();
3080 EXPECT_EQ(42 + 87, reinterpret_cast<CallSimpleLeafCode>(test->entry())());
3081 EXPECT_DISASSEMBLY_ENDS_WITH(
3082 "call r11\n"
3083 "addq rsp,8\n"
3084 "ret\n");
3085}
3086
3087ASSEMBLER_TEST_GENERATE(JumpSimpleLeaf, assembler) {
3088 ExternalLabel call1(reinterpret_cast<uword>(LeafReturn42));
3089 Label L;
3090 int space = ComputeStackSpaceReservation(0, 8);
3091 __ subq(RSP, Immediate(space));
3092 __ call(&L);
3093 __ addq(RSP, Immediate(space));
3094 __ ret();
3095 __ Bind(&L);
3096 __ jmp(&call1);
3097}
3098
3099ASSEMBLER_TEST_RUN(JumpSimpleLeaf, test) {
3100 typedef int (*JumpSimpleLeafCode)();
3101 EXPECT_EQ(42, reinterpret_cast<JumpSimpleLeafCode>(test->entry())());
3102 EXPECT_DISASSEMBLY_ENDS_WITH("jmp r11\n");
3103}
3104
3105ASSEMBLER_TEST_GENERATE(JumpIndirect, assembler) {
3106 ExternalLabel call1(reinterpret_cast<uword>(LeafReturn42));
3107 __ movq(Address(CallingConventions::kArg1Reg, 0), Immediate(call1.address()));
3108 __ jmp(Address(CallingConventions::kArg1Reg, 0));
3109}
3110
3111ASSEMBLER_TEST_RUN(JumpIndirect, test) {
3112 uword temp = 0;
3113 typedef int (*JumpIndirect)(uword*);
3114 EXPECT_EQ(42, reinterpret_cast<JumpIndirect>(test->entry())(&temp));
3115}
3116
3117ASSEMBLER_TEST_GENERATE(SingleFPMoves, assembler) {
3118 __ movq(RAX, Immediate(bit_cast<int32_t, float>(234.0f)));
3119 __ movd(XMM0, RAX);
3120 __ movss(XMM1, XMM0);
3121 __ movss(XMM2, XMM1);
3122 __ movss(XMM3, XMM2);
3123 __ movss(XMM4, XMM3);
3124 __ movss(XMM5, XMM4);
3125 __ movss(XMM6, XMM5);
3126 __ movss(XMM7, XMM6);
3127 __ movss(XMM8, XMM7);
3128 __ movss(XMM9, XMM8);
3129 __ movss(XMM10, XMM9);
3130 __ movss(XMM11, XMM10);
3131 __ movss(XMM12, XMM11);
3132 __ movss(XMM13, XMM12);
3133 __ movss(XMM14, XMM13);
3134 __ movss(XMM15, XMM14);
3135 __ pushq(R15); // Callee saved.
3136 __ pushq(RAX);
3137 __ movq(Address(RSP, 0), Immediate(0));
3138 __ movss(XMM0, Address(RSP, 0));
3139 __ movss(Address(RSP, 0), XMM7);
3140 __ movss(XMM1, Address(RSP, 0));
3141 __ movq(R10, RSP);
3142 __ movss(Address(R10, 0), XMM1);
3143 __ movss(XMM2, Address(R10, 0));
3144 __ movq(R15, RSP);
3145 __ movss(Address(R15, 0), XMM2);
3146 __ movss(XMM3, Address(R15, 0));
3147 __ movq(RAX, RSP);
3148 __ movss(Address(RAX, 0), XMM3);
3149 __ movss(XMM1, Address(RAX, 0));
3150 __ movss(XMM15, Address(RAX, 0));
3151 __ movss(XMM14, XMM15);
3152 __ movss(XMM13, XMM14);
3153 __ movss(XMM12, XMM13);
3154 __ movss(XMM11, XMM12);
3155 __ movss(XMM10, XMM11);
3156 __ movss(XMM9, XMM10);
3157 __ movss(XMM8, XMM9);
3158 __ movss(XMM7, XMM8);
3159 __ movss(XMM6, XMM7);
3160 __ movss(XMM5, XMM6);
3161 __ movss(XMM4, XMM5);
3162 __ movss(XMM3, XMM4);
3163 __ movss(XMM2, XMM3);
3164 __ movss(XMM1, XMM2);
3165 __ movss(XMM0, XMM1);
3166 __ popq(RAX);
3167 __ popq(R15); // Callee saved.
3168 __ ret();
3169}
3170
3171ASSEMBLER_TEST_RUN(SingleFPMoves, test) {
3172 typedef float (*SingleFPMovesCode)();
3173 EXPECT_EQ(234, reinterpret_cast<SingleFPMovesCode>(test->entry())());
3174 EXPECT_DISASSEMBLY(
3175 "movl rax,0x........\n"
3176 "movd xmm0,rax\n"
3177 "movss rcx,xmm0\n"
3178 "movss rdx,xmm1\n"
3179 "movss rbx,xmm2\n"
3180 "movss rsp,xmm3\n"
3181 "movss rbp,xmm4\n"
3182 "movss rsi,xmm5\n"
3183 "movss rdi,xmm6\n"
3184 "movss r8,xmm7\n"
3185 "movss r9,xmm8\n"
3186 "movss r10,xmm9\n"
3187 "movss r11,xmm10\n"
3188 "movss r12,xmm11\n"
3189 "movss r13,xmm12\n"
3190 "movss thr,xmm13\n"
3191 "movss pp,xmm14\n"
3192 "push pp\n"
3193 "push rax\n"
3194 "movq [rsp],0\n"
3195 "movss xmm0,[rsp]\n"
3196 "movss [rsp],xmm7\n"
3197 "movss xmm1,[rsp]\n"
3198 "movq r10,rsp\n"
3199 "movss [r10],xmm1\n"
3200 "movss xmm2,[r10]\n"
3201 "movq pp,rsp\n"
3202 "movss [pp],xmm2\n"
3203 "movss xmm3,[pp]\n"
3204 "movq rax,rsp\n"
3205 "movss [rax],xmm3\n"
3206 "movss xmm1,[rax]\n"
3207 "movss xmm15,[rax]\n"
3208 "movss thr,xmm15\n"
3209 "movss r13,xmm14\n"
3210 "movss r12,xmm13\n"
3211 "movss r11,xmm12\n"
3212 "movss r10,xmm11\n"
3213 "movss r9,xmm10\n"
3214 "movss r8,xmm9\n"
3215 "movss rdi,xmm8\n"
3216 "movss rsi,xmm7\n"
3217 "movss rbp,xmm6\n"
3218 "movss rsp,xmm5\n"
3219 "movss rbx,xmm4\n"
3220 "movss rdx,xmm3\n"
3221 "movss rcx,xmm2\n"
3222 "movss rax,xmm1\n"
3223 "pop rax\n"
3224 "pop pp\n"
3225 "ret\n");
3226}
3227
3228ASSEMBLER_TEST_GENERATE(SingleFPMoves2, assembler) {
3229 __ movq(RAX, Immediate(bit_cast<int32_t, float>(234.0f)));
3230 __ movd(XMM0, RAX);
3231 __ movd(XMM8, RAX);
3232 __ movss(XMM1, XMM8);
3233 __ pushq(RAX);
3234 __ movq(Address(RSP, 0), Immediate(0));
3235 __ movss(XMM0, Address(RSP, 0));
3236 __ movss(Address(RSP, 0), XMM1);
3237 __ movss(XMM0, Address(RSP, 0));
3238 __ movq(Address(RSP, 0), Immediate(0));
3239 __ movss(XMM9, XMM8);
3240 __ movss(Address(RSP, 0), XMM9);
3241 __ movss(XMM8, Address(RSP, 0));
3242 __ movss(XMM0, XMM8);
3243 __ popq(RAX);
3244 __ ret();
3245}
3246
3247ASSEMBLER_TEST_RUN(SingleFPMoves2, test) {
3248 typedef float (*SingleFPMoves2Code)();
3249 EXPECT_EQ(234, reinterpret_cast<SingleFPMoves2Code>(test->entry())());
3250 EXPECT_DISASSEMBLY(
3251 "movl rax,0x........\n"
3252 "movd xmm0,rax\n"
3253 "movd xmm8,rax\n"
3254 "movss rcx,xmm8\n"
3255 "push rax\n"
3256 "movq [rsp],0\n"
3257 "movss xmm0,[rsp]\n"
3258 "movss [rsp],xmm1\n"
3259 "movss xmm0,[rsp]\n"
3260 "movq [rsp],0\n"
3261 "movss r9,xmm8\n"
3262 "movss [rsp],xmm9\n"
3263 "movss xmm8,[rsp]\n"
3264 "movss rax,xmm8\n"
3265 "pop rax\n"
3266 "ret\n");
3267}
3268
3269ASSEMBLER_TEST_GENERATE(MovqXmmToCpu, assembler) {
3270 __ movq(RAX, Immediate(bit_cast<int32_t, float>(234.5f)));
3271 __ movd(XMM0, RAX);
3272 __ cvtss2sd(XMM0, XMM0);
3273 __ movq(RAX, XMM0);
3274 __ ret();
3275}
3276
3277ASSEMBLER_TEST_RUN(MovqXmmToCpu, test) {
3278 typedef uint64_t (*MovqXmmToCpuCode)();
3279 EXPECT_EQ((bit_cast<uint64_t, double>(234.5f)),
3280 reinterpret_cast<MovqXmmToCpuCode>(test->entry())());
3281 EXPECT_DISASSEMBLY(
3282 "movl rax,0x........\n"
3283 "movd xmm0,rax\n"
3284 "cvtss2sd xmm0,xmm0\n"
3285 "movq rax,xmm0\n"
3286 "ret\n");
3287}
3288
3289ASSEMBLER_TEST_GENERATE(PackedDoubleAdd, assembler) {
3290 static const struct ALIGN16 {
3291 double a;
3292 double b;
3293 } constant0 = {1.0, 2.0};
3294 static const struct ALIGN16 {
3295 double a;
3296 double b;
3297 } constant1 = {3.0, 4.0};
3298 __ movq(RAX, Immediate(reinterpret_cast<uword>(&constant0)));
3299 __ movups(XMM10, Address(RAX, 0));
3300 __ movq(RAX, Immediate(reinterpret_cast<uword>(&constant1)));
3301 __ movups(XMM11, Address(RAX, 0));
3302 __ addpd(XMM10, XMM11);
3303 __ movaps(XMM0, XMM10);
3304 __ ret();
3305}
3306
3307ASSEMBLER_TEST_RUN(PackedDoubleAdd, test) {
3308 typedef double (*PackedDoubleAdd)();
3309 double res = reinterpret_cast<PackedDoubleAdd>(test->entry())();
3310 EXPECT_FLOAT_EQ(4.0, res, 0.000001f);
3311 EXPECT_DISASSEMBLY_ENDS_WITH(
3312 "movups xmm11,[rax]\n"
3313 "addpd xmm10,xmm11\n"
3314 "movaps xmm0,xmm10\n"
3315 "ret\n");
3316}
3317
3318ASSEMBLER_TEST_GENERATE(PackedDoubleSub, assembler) {
3319 static const struct ALIGN16 {
3320 double a;
3321 double b;
3322 } constant0 = {1.0, 2.0};
3323 static const struct ALIGN16 {
3324 double a;
3325 double b;
3326 } constant1 = {3.0, 4.0};
3327 __ movq(RAX, Immediate(reinterpret_cast<uword>(&constant0)));
3328 __ movups(XMM10, Address(RAX, 0));
3329 __ movq(RAX, Immediate(reinterpret_cast<uword>(&constant1)));
3330 __ movups(XMM11, Address(RAX, 0));
3331 __ subpd(XMM10, XMM11);
3332 __ movaps(XMM0, XMM10);
3333 __ ret();
3334}
3335
3336ASSEMBLER_TEST_RUN(PackedDoubleSub, test) {
3337 typedef double (*PackedDoubleSub)();
3338 double res = reinterpret_cast<PackedDoubleSub>(test->entry())();
3339 EXPECT_FLOAT_EQ(-2.0, res, 0.000001f);
3340 EXPECT_DISASSEMBLY_ENDS_WITH(
3341 "movups xmm11,[rax]\n"
3342 "subpd xmm10,xmm11\n"
3343 "movaps xmm0,xmm10\n"
3344 "ret\n");
3345}
3346
3347static void EnterTestFrame(Assembler* assembler) {
3348 COMPILE_ASSERT(THR != CallingConventions::kArg1Reg);
3349 COMPILE_ASSERT(CODE_REG != CallingConventions::kArg2Reg);
3350 __ EnterFrame(0);
3351 __ pushq(CODE_REG);
3352 __ pushq(PP);
3353 __ pushq(THR);
3354 __ movq(CODE_REG, Address(CallingConventions::kArg1Reg,
3355 VMHandles::kOffsetOfRawPtrInHandle));
3356 __ movq(THR, CallingConventions::kArg2Reg);
3357 __ LoadPoolPointer(PP);
3358}
3359
3360static void LeaveTestFrame(Assembler* assembler) {
3361 __ popq(THR);
3362 __ popq(PP);
3363 __ popq(CODE_REG);
3364 __ LeaveFrame();
3365}
3366
3367ASSEMBLER_TEST_GENERATE(PackedDoubleNegate, assembler) {
3368 static const struct ALIGN16 {
3369 double a;
3370 double b;
3371 } constant0 = {1.0, 2.0};
3372 EnterTestFrame(assembler);
3373 __ movq(RAX, Immediate(reinterpret_cast<uword>(&constant0)));
3374 __ movups(XMM10, Address(RAX, 0));
3375 __ negatepd(XMM10, XMM10);
3376 __ movaps(XMM0, XMM10);
3377 LeaveTestFrame(assembler);
3378 __ ret();
3379}
3380
3381ASSEMBLER_TEST_RUN(PackedDoubleNegate, test) {
3382 double res = test->InvokeWithCodeAndThread<double>();
3383 EXPECT_FLOAT_EQ(-1.0, res, 0.000001f);
3384 EXPECT_DISASSEMBLY_NOT_WINDOWS_ENDS_WITH(
3385 "movups xmm10,[rax]\n"
3386 "movq r11,[thr+0x...]\n"
3387 "xorpd xmm10,[r11]\n"
3388 "movaps xmm0,xmm10\n"
3389 "pop thr\n"
3390 "pop pp\n"
3391 "pop r12\n"
3392 "movq rsp,rbp\n"
3393 "pop rbp\n"
3394 "ret\n");
3395}
3396
3397ASSEMBLER_TEST_GENERATE(PackedDoubleAbsolute, assembler) {
3398 static const struct ALIGN16 {
3399 double a;
3400 double b;
3401 } constant0 = {-1.0, 2.0};
3402 EnterTestFrame(assembler);
3403 __ movq(RAX, Immediate(reinterpret_cast<uword>(&constant0)));
3404 __ movups(XMM10, Address(RAX, 0));
3405 __ abspd(XMM0, XMM10);
3406 LeaveTestFrame(assembler);
3407 __ ret();
3408}
3409
3410ASSEMBLER_TEST_RUN(PackedDoubleAbsolute, test) {
3411 double res = test->InvokeWithCodeAndThread<double>();
3412 EXPECT_FLOAT_EQ(1.0, res, 0.000001f);
3413 EXPECT_DISASSEMBLY_NOT_WINDOWS_ENDS_WITH(
3414 "movups xmm10,[rax]\n"
3415 "movq r11,[thr+0x...]\n"
3416 "movups xmm0,[r11]\n"
3417 "andpd xmm0,xmm10\n"
3418 "pop thr\n"
3419 "pop pp\n"
3420 "pop r12\n"
3421 "movq rsp,rbp\n"
3422 "pop rbp\n"
3423 "ret\n");
3424}
3425
3426ASSEMBLER_TEST_GENERATE(PackedDoubleMul, assembler) {
3427 static const struct ALIGN16 {
3428 double a;
3429 double b;
3430 } constant0 = {3.0, 2.0};
3431 static const struct ALIGN16 {
3432 double a;
3433 double b;
3434 } constant1 = {3.0, 4.0};
3435 __ movq(RAX, Immediate(reinterpret_cast<uword>(&constant0)));
3436 __ movups(XMM10, Address(RAX, 0));
3437 __ movq(RAX, Immediate(reinterpret_cast<uword>(&constant1)));
3438 __ movups(XMM11, Address(RAX, 0));
3439 __ mulpd(XMM10, XMM11);
3440 __ movaps(XMM0, XMM10);
3441 __ ret();
3442}
3443
3444ASSEMBLER_TEST_RUN(PackedDoubleMul, test) {
3445 typedef double (*PackedDoubleMul)();
3446 double res = reinterpret_cast<PackedDoubleMul>(test->entry())();
3447 EXPECT_FLOAT_EQ(9.0, res, 0.000001f);
3448 EXPECT_DISASSEMBLY_ENDS_WITH(
3449 "movups xmm11,[rax]\n"
3450 "mulpd xmm10,xmm11\n"
3451 "movaps xmm0,xmm10\n"
3452 "ret\n");
3453}
3454
3455ASSEMBLER_TEST_GENERATE(PackedDoubleDiv, assembler) {
3456 static const struct ALIGN16 {
3457 double a;
3458 double b;
3459 } constant0 = {9.0, 2.0};
3460 static const struct ALIGN16 {
3461 double a;
3462 double b;
3463 } constant1 = {3.0, 4.0};
3464 __ movq(RAX, Immediate(reinterpret_cast<uword>(&constant0)));
3465 __ movups(XMM10, Address(RAX, 0));
3466 __ movq(RAX, Immediate(reinterpret_cast<uword>(&constant1)));
3467 __ movups(XMM11, Address(RAX, 0));
3468 __ divpd(XMM10, XMM11);
3469 __ movaps(XMM0, XMM10);
3470 __ ret();
3471}
3472
3473ASSEMBLER_TEST_RUN(PackedDoubleDiv, test) {
3474 typedef double (*PackedDoubleDiv)();
3475 double res = reinterpret_cast<PackedDoubleDiv>(test->entry())();
3476 EXPECT_FLOAT_EQ(3.0, res, 0.000001f);
3477 EXPECT_DISASSEMBLY_ENDS_WITH(
3478 "movups xmm11,[rax]\n"
3479 "divpd xmm10,xmm11\n"
3480 "movaps xmm0,xmm10\n"
3481 "ret\n");
3482}
3483
3484ASSEMBLER_TEST_GENERATE(PackedDoubleSqrt, assembler) {
3485 static const struct ALIGN16 {
3486 double a;
3487 double b;
3488 } constant0 = {16.0, 2.0};
3489 __ movq(RAX, Immediate(reinterpret_cast<uword>(&constant0)));
3490 __ movups(XMM10, Address(RAX, 0));
3491 __ sqrtpd(XMM10, XMM10);
3492 __ movaps(XMM0, XMM10);
3493 __ ret();
3494}
3495
3496ASSEMBLER_TEST_RUN(PackedDoubleSqrt, test) {
3497 typedef double (*PackedDoubleSqrt)();
3498 double res = reinterpret_cast<PackedDoubleSqrt>(test->entry())();
3499 EXPECT_FLOAT_EQ(4.0, res, 0.000001f);
3500 EXPECT_DISASSEMBLY_ENDS_WITH(
3501 "movups xmm10,[rax]\n"
3502 "sqrtpd xmm10,xmm10\n"
3503 "movaps xmm0,xmm10\n"
3504 "ret\n");
3505}
3506
3507ASSEMBLER_TEST_GENERATE(PackedDoubleMin, assembler) {
3508 static const struct ALIGN16 {
3509 double a;
3510 double b;
3511 } constant0 = {9.0, 2.0};
3512 static const struct ALIGN16 {
3513 double a;
3514 double b;
3515 } constant1 = {3.0, 4.0};
3516 __ movq(RAX, Immediate(reinterpret_cast<uword>(&constant0)));
3517 __ movups(XMM10, Address(RAX, 0));
3518 __ movq(RAX, Immediate(reinterpret_cast<uword>(&constant1)));
3519 __ movups(XMM11, Address(RAX, 0));
3520 __ minpd(XMM10, XMM11);
3521 __ movaps(XMM0, XMM10);
3522 __ ret();
3523}
3524
3525ASSEMBLER_TEST_RUN(PackedDoubleMin, test) {
3526 typedef double (*PackedDoubleMin)();
3527 double res = reinterpret_cast<PackedDoubleMin>(test->entry())();
3528 EXPECT_FLOAT_EQ(3.0, res, 0.000001f);
3529 EXPECT_DISASSEMBLY_ENDS_WITH(
3530 "movups xmm11,[rax]\n"
3531 "minpd xmm10,xmm11\n"
3532 "movaps xmm0,xmm10\n"
3533 "ret\n");
3534}
3535
3536ASSEMBLER_TEST_GENERATE(PackedDoubleMax, assembler) {
3537 static const struct ALIGN16 {
3538 double a;
3539 double b;
3540 } constant0 = {9.0, 2.0};
3541 static const struct ALIGN16 {
3542 double a;
3543 double b;
3544 } constant1 = {3.0, 4.0};
3545 __ movq(RAX, Immediate(reinterpret_cast<uword>(&constant0)));
3546 __ movups(XMM10, Address(RAX, 0));
3547 __ movq(RAX, Immediate(reinterpret_cast<uword>(&constant1)));
3548 __ movups(XMM11, Address(RAX, 0));
3549 __ maxpd(XMM10, XMM11);
3550 __ movaps(XMM0, XMM10);
3551 __ ret();
3552}
3553
3554ASSEMBLER_TEST_RUN(PackedDoubleMax, test) {
3555 typedef double (*PackedDoubleMax)();
3556 double res = reinterpret_cast<PackedDoubleMax>(test->entry())();
3557 EXPECT_FLOAT_EQ(9.0, res, 0.000001f);
3558 EXPECT_DISASSEMBLY_ENDS_WITH(
3559 "movups xmm11,[rax]\n"
3560 "maxpd xmm10,xmm11\n"
3561 "movaps xmm0,xmm10\n"
3562 "ret\n");
3563}
3564
3565ASSEMBLER_TEST_GENERATE(PackedDoubleShuffle, assembler) {
3566 static const struct ALIGN16 {
3567 double a;
3568 double b;
3569 } constant0 = {2.0, 9.0};
3570 __ movq(RAX, Immediate(reinterpret_cast<uword>(&constant0)));
3571 __ movups(XMM10, Address(RAX, 0));
3572 // Splat Y across all lanes.
3573 __ shufpd(XMM10, XMM10, Immediate(0x33));
3574 // Splat X across all lanes.
3575 __ shufpd(XMM10, XMM10, Immediate(0x0));
3576 // Set return value.
3577 __ movaps(XMM0, XMM10);
3578 __ ret();
3579}
3580
3581ASSEMBLER_TEST_RUN(PackedDoubleShuffle, test) {
3582 typedef double (*PackedDoubleShuffle)();
3583 double res = reinterpret_cast<PackedDoubleShuffle>(test->entry())();
3584 EXPECT_FLOAT_EQ(9.0, res, 0.000001f);
3585 EXPECT_DISASSEMBLY_ENDS_WITH(
3586 "movups xmm10,[rax]\n"
3587 "shufpd xmm10, xmm10 [33]\n"
3588 "shufpd xmm10, xmm10 [0]\n"
3589 "movaps xmm0,xmm10\n"
3590 "ret\n");
3591}
3592
3593ASSEMBLER_TEST_GENERATE(PackedDoubleToSingle, assembler) {
3594 static const struct ALIGN16 {
3595 double a;
3596 double b;
3597 } constant0 = {9.0, 2.0};
3598 __ movq(RAX, Immediate(reinterpret_cast<uword>(&constant0)));
3599 __ movups(XMM11, Address(RAX, 0));
3600 __ cvtpd2ps(XMM10, XMM11);
3601 __ movaps(XMM0, XMM10);
3602 __ ret();
3603}
3604
3605ASSEMBLER_TEST_RUN(PackedDoubleToSingle, test) {
3606 typedef float (*PackedDoubleToSingle)();
3607 float res = reinterpret_cast<PackedDoubleToSingle>(test->entry())();
3608 EXPECT_FLOAT_EQ(9.0f, res, 0.000001f);
3609 EXPECT_DISASSEMBLY_ENDS_WITH(
3610 "movups xmm11,[rax]\n"
3611 "cvtpd2ps xmm10,xmm11\n"
3612 "movaps xmm0,xmm10\n"
3613 "ret\n");
3614}
3615
3616ASSEMBLER_TEST_GENERATE(PackedSingleToDouble, assembler) {
3617 static const struct ALIGN16 {
3618 float a;
3619 float b;
3620 float c;
3621 float d;
3622 } constant0 = {9.0f, 2.0f, 3.0f, 4.0f};
3623 __ movq(RAX, Immediate(reinterpret_cast<uword>(&constant0)));
3624 __ movups(XMM11, Address(RAX, 0));
3625 __ cvtps2pd(XMM10, XMM11);
3626 __ movaps(XMM0, XMM10);
3627 __ ret();
3628}
3629
3630ASSEMBLER_TEST_RUN(PackedSingleToDouble, test) {
3631 typedef double (*PackedSingleToDouble)();
3632 double res = reinterpret_cast<PackedSingleToDouble>(test->entry())();
3633 EXPECT_FLOAT_EQ(9.0f, res, 0.000001f);
3634 EXPECT_DISASSEMBLY_ENDS_WITH(
3635 "movups xmm11,[rax]\n"
3636 "cvtps2pd xmm10,xmm11\n"
3637 "movaps xmm0,xmm10\n"
3638 "ret\n");
3639}
3640
3641ASSEMBLER_TEST_GENERATE(SingleFPOperations, assembler) {
3642 __ pushq(RBX);
3643 __ pushq(RCX);
3644 __ movq(RBX, Immediate(bit_cast<int32_t, float>(12.3f)));
3645 __ movd(XMM0, RBX);
3646 __ movd(XMM8, RBX);
3647 __ movq(RCX, Immediate(bit_cast<int32_t, float>(3.4f)));
3648 __ movd(XMM1, RCX);
3649 __ movd(XMM9, RCX);
3650 __ addss(XMM0, XMM1); // 15.7f
3651 __ mulss(XMM0, XMM1); // 53.38f
3652 __ subss(XMM0, XMM1); // 49.98f
3653 __ divss(XMM0, XMM1); // 14.7f
3654 __ addss(XMM8, XMM9); // 15.7f
3655 __ mulss(XMM8, XMM9); // 53.38f
3656 __ subss(XMM8, XMM9); // 49.98f
3657 __ divss(XMM8, XMM9); // 14.7f
3658 __ subss(XMM0, XMM8); // 0.0f
3659 __ popq(RCX);
3660 __ popq(RBX);
3661 __ ret();
3662}
3663
3664ASSEMBLER_TEST_RUN(SingleFPOperations, test) {
3665 typedef float (*SingleFPOperationsCode)();
3666 float res = reinterpret_cast<SingleFPOperationsCode>(test->entry())();
3667 EXPECT_FLOAT_EQ(0.0f, res, 0.001f);
3668 EXPECT_DISASSEMBLY(
3669 "push rbx\n"
3670 "push rcx\n"
3671 "movl rbx,0x........\n"
3672 "movd xmm0,rbx\n"
3673 "movd xmm8,rbx\n"
3674 "movl rcx,0x........\n"
3675 "movd xmm1,rcx\n"
3676 "movd xmm9,rcx\n"
3677 "addss xmm0,xmm1\n"
3678 "mulss xmm0,xmm1\n"
3679 "subss xmm0,xmm1\n"
3680 "divss xmm0,xmm1\n"
3681 "addss xmm8,xmm9\n"
3682 "mulss xmm8,xmm9\n"
3683 "subss xmm8,xmm9\n"
3684 "divss xmm8,xmm9\n"
3685 "subss xmm0,xmm8\n"
3686 "pop rcx\n"
3687 "pop rbx\n"
3688 "ret\n");
3689}
3690
3691ASSEMBLER_TEST_GENERATE(PackedFPOperations, assembler) {
3692 __ movq(RAX, Immediate(bit_cast<int32_t, float>(12.3f)));
3693 __ movd(XMM10, RAX);
3694 __ shufps(XMM10, XMM10, Immediate(0x0));
3695 __ movq(RAX, Immediate(bit_cast<int32_t, float>(3.4f)));
3696 __ movd(XMM9, RAX);
3697 __ shufps(XMM9, XMM9, Immediate(0x0));
3698 __ addps(XMM10, XMM9); // 15.7f
3699 __ mulps(XMM10, XMM9); // 53.38f
3700 __ subps(XMM10, XMM9); // 49.98f
3701 __ divps(XMM10, XMM9); // 14.7f
3702 __ movaps(XMM0, XMM10);
3703 __ shufps(XMM0, XMM0, Immediate(0x55)); // Copy second lane into all 4 lanes.
3704 __ ret();
3705}
3706
3707ASSEMBLER_TEST_RUN(PackedFPOperations, test) {
3708 typedef float (*PackedFPOperationsCode)();
3709 float res = reinterpret_cast<PackedFPOperationsCode>(test->entry())();
3710 EXPECT_FLOAT_EQ(14.7f, res, 0.001f);
3711 EXPECT_DISASSEMBLY(
3712 "movl rax,0x........\n"
3713 "movd xmm10,rax\n"
3714 "shufps xmm10,xmm10 [0]\n"
3715 "movl rax,0x........\n"
3716 "movd xmm9,rax\n"
3717 "shufps xmm9,xmm9 [0]\n"
3718 "addps xmm10,xmm9\n"
3719 "mulps xmm10,xmm9\n"
3720 "subps xmm10,xmm9\n"
3721 "divps xmm10,xmm9\n"
3722 "movaps xmm0,xmm10\n"
3723 "shufps xmm0,xmm0 [55]\n"
3724 "ret\n");
3725}
3726
3727ASSEMBLER_TEST_GENERATE(PackedIntOperations, assembler) {
3728 __ movl(RAX, Immediate(0x2));
3729 __ movd(XMM0, RAX);
3730 __ shufps(XMM0, XMM0, Immediate(0x0));
3731 __ movl(RAX, Immediate(0x1));
3732 __ movd(XMM1, RAX);
3733 __ shufps(XMM1, XMM1, Immediate(0x0));
3734 __ addpl(XMM0, XMM1); // 0x3
3735 __ addpl(XMM0, XMM0); // 0x6
3736 __ subpl(XMM0, XMM1); // 0x5
3737 __ pushq(RAX);
3738 __ movss(Address(RSP, 0), XMM0);
3739 __ popq(RAX);
3740 __ ret();
3741}
3742
3743ASSEMBLER_TEST_RUN(PackedIntOperations, test) {
3744 typedef uint32_t (*PackedIntOperationsCode)();
3745 uint32_t res = reinterpret_cast<PackedIntOperationsCode>(test->entry())();
3746 EXPECT_EQ(static_cast<uword>(0x5), res);
3747 EXPECT_DISASSEMBLY(
3748 "movl rax,2\n"
3749 "movd xmm0,rax\n"
3750 "shufps xmm0,xmm0 [0]\n"
3751 "movl rax,1\n"
3752 "movd xmm1,rax\n"
3753 "shufps xmm1,xmm1 [0]\n"
3754 "paddd xmm0,xmm1\n"
3755 "paddd xmm0,xmm0\n"
3756 "psubd xmm0,xmm1\n"
3757 "push rax\n"
3758 "movss [rsp],xmm0\n"
3759 "pop rax\n"
3760 "ret\n");
3761}
3762
3763ASSEMBLER_TEST_GENERATE(PackedIntOperations2, assembler) {
3764 // Note: on Windows 64 XMM6-XMM15 are callee save.
3765 const intptr_t cpu_register_set = 0;
3766 const intptr_t fpu_register_set =
3767 ((1 << XMM10) | (1 << XMM11)) & CallingConventions::kVolatileXmmRegisters;
3768 __ PushRegisters(cpu_register_set, fpu_register_set);
3769 __ movl(RAX, Immediate(0x2));
3770 __ movd(XMM10, RAX);
3771 __ shufps(XMM10, XMM10, Immediate(0x0));
3772 __ movl(RAX, Immediate(0x1));
3773 __ movd(XMM11, RAX);
3774 __ shufps(XMM11, XMM11, Immediate(0x0));
3775 __ addpl(XMM10, XMM11); // 0x3
3776 __ addpl(XMM10, XMM10); // 0x6
3777 __ subpl(XMM10, XMM11); // 0x5
3778 __ pushq(RAX);
3779 __ movss(Address(RSP, 0), XMM10);
3780 __ popq(RAX);
3781 __ PopRegisters(cpu_register_set, fpu_register_set);
3782 __ ret();
3783}
3784
3785ASSEMBLER_TEST_RUN(PackedIntOperations2, test) {
3786 typedef uint32_t (*PackedIntOperationsCode)();
3787 uint32_t res = reinterpret_cast<PackedIntOperationsCode>(test->entry())();
3788 EXPECT_EQ(static_cast<uword>(0x5), res);
3789 EXPECT_DISASSEMBLY_NOT_WINDOWS(
3790 "subq rsp,0x20\n"
3791 "movups [rsp],xmm10\n"
3792 "movups [rsp+0x10],xmm11\n"
3793 "movl rax,2\n"
3794 "movd xmm10,rax\n"
3795 "shufps xmm10,xmm10 [0]\n"
3796 "movl rax,1\n"
3797 "movd xmm11,rax\n"
3798 "shufps xmm11,xmm11 [0]\n"
3799 "paddd xmm10,xmm11\n"
3800 "paddd xmm10,xmm10\n"
3801 "psubd xmm10,xmm11\n"
3802 "push rax\n"
3803 "movss [rsp],xmm10\n"
3804 "pop rax\n"
3805 "movups xmm10,[rsp]\n"
3806 "movups xmm11,[rsp+0x10]\n"
3807 "addq rsp,0x20\n"
3808 "ret\n");
3809}
3810
3811ASSEMBLER_TEST_GENERATE(PackedFPOperations2, assembler) {
3812 __ movq(RAX, Immediate(bit_cast<int32_t, float>(4.0f)));
3813 __ movd(XMM0, RAX);
3814 __ shufps(XMM0, XMM0, Immediate(0x0));
3815
3816 __ movaps(XMM11, XMM0); // Copy XMM0
3817 __ rcpps(XMM11, XMM11); // 0.25
3818 __ sqrtps(XMM11, XMM11); // 0.5
3819 __ rsqrtps(XMM0, XMM0); // ~0.5
3820 __ subps(XMM0, XMM11); // ~0.0
3821 __ shufps(XMM0, XMM0, Immediate(0x00)); // Copy second lane into all 4 lanes.
3822 __ ret();
3823}
3824
3825ASSEMBLER_TEST_RUN(PackedFPOperations2, test) {
3826 typedef float (*PackedFPOperations2Code)();
3827 float res = reinterpret_cast<PackedFPOperations2Code>(test->entry())();
3828 EXPECT_FLOAT_EQ(0.0f, res, 0.001f);
3829 EXPECT_DISASSEMBLY(
3830 "movl rax,0x........\n"
3831 "movd xmm0,rax\n"
3832 "shufps xmm0,xmm0 [0]\n"
3833 "movaps xmm11,xmm0\n"
3834 "rcpps xmm11,xmm11\n"
3835 "sqrtps xmm11,xmm11\n"
3836 "rsqrtps xmm0,xmm0\n"
3837 "subps xmm0,xmm11\n"
3838 "shufps xmm0,xmm0 [0]\n"
3839 "ret\n");
3840}
3841
3842ASSEMBLER_TEST_GENERATE(PackedCompareEQ, assembler) {
3843 __ set1ps(XMM0, RAX, Immediate(bit_cast<int32_t, float>(2.0f)));
3844 __ set1ps(XMM1, RAX, Immediate(bit_cast<int32_t, float>(4.0f)));
3845 __ cmppseq(XMM0, XMM1);
3846 __ pushq(RAX);
3847 __ movss(Address(RSP, 0), XMM0);
3848 __ popq(RAX);
3849 __ ret();
3850}
3851
3852ASSEMBLER_TEST_RUN(PackedCompareEQ, test) {
3853 typedef uint32_t (*PackedCompareEQCode)();
3854 uint32_t res = reinterpret_cast<PackedCompareEQCode>(test->entry())();
3855 EXPECT_EQ(static_cast<uword>(0x0), res);
3856 EXPECT_DISASSEMBLY(
3857 "movl rax,0x........\n"
3858 "movd xmm0,rax\n"
3859 "shufps xmm0,xmm0 [0]\n"
3860 "movl rax,0x........\n"
3861 "movd xmm1,rax\n"
3862 "shufps xmm1,xmm1 [0]\n"
3863 "cmpps xmm0,xmm1 [eq]\n"
3864 "push rax\n"
3865 "movss [rsp],xmm0\n"
3866 "pop rax\n"
3867 "ret\n");
3868}
3869
3870ASSEMBLER_TEST_GENERATE(XmmAlu, assembler) {
3871 // Test the disassembler.
3872 __ addss(XMM0, XMM0);
3873 __ addsd(XMM0, XMM0);
3874 __ addps(XMM0, XMM0);
3875 __ addpd(XMM0, XMM0);
3876 __ cvtss2sd(XMM0, XMM0);
3877 __ cvtsd2ss(XMM0, XMM0);
3878 __ cvtps2pd(XMM0, XMM0);
3879 __ cvtpd2ps(XMM0, XMM0);
3880 __ movl(RAX, Immediate(0));
3881 __ ret();
3882}
3883
3884ASSEMBLER_TEST_RUN(XmmAlu, test) {
3885 typedef intptr_t (*XmmAluTest)();
3886 intptr_t res = reinterpret_cast<XmmAluTest>(test->entry())();
3887 EXPECT_EQ(res, 0);
3888 EXPECT_DISASSEMBLY(
3889 "addss xmm0,xmm0\n"
3890 "addsd xmm0,xmm0\n"
3891 "addps xmm0,xmm0\n"
3892 "addpd xmm0,xmm0\n"
3893 "cvtss2sd xmm0,xmm0\n"
3894 "cvtsd2ss xmm0,xmm0\n"
3895 "cvtps2pd xmm0,xmm0\n"
3896 "cvtpd2ps xmm0,xmm0\n"
3897 "movl rax,0\n"
3898 "ret\n");
3899}
3900
3901ASSEMBLER_TEST_GENERATE(PackedCompareNEQ, assembler) {
3902 __ set1ps(XMM0, RAX, Immediate(bit_cast<int32_t, float>(2.0f)));
3903 __ set1ps(XMM1, RAX, Immediate(bit_cast<int32_t, float>(4.0f)));
3904 __ cmppsneq(XMM0, XMM1);
3905 __ pushq(RAX);
3906 __ movss(Address(RSP, 0), XMM0);
3907 __ popq(RAX);
3908 __ ret();
3909}
3910
3911ASSEMBLER_TEST_RUN(PackedCompareNEQ, test) {
3912 typedef uint32_t (*PackedCompareNEQCode)();
3913 uint32_t res = reinterpret_cast<PackedCompareNEQCode>(test->entry())();
3914 EXPECT_EQ(static_cast<uword>(0xFFFFFFFF), res);
3915 EXPECT_DISASSEMBLY(
3916 "movl rax,0x........\n"
3917 "movd xmm0,rax\n"
3918 "shufps xmm0,xmm0 [0]\n"
3919 "movl rax,0x........\n"
3920 "movd xmm1,rax\n"
3921 "shufps xmm1,xmm1 [0]\n"
3922 "cmpps xmm0,xmm1 [neq]\n"
3923 "push rax\n"
3924 "movss [rsp],xmm0\n"
3925 "pop rax\n"
3926 "ret\n");
3927}
3928
3929ASSEMBLER_TEST_GENERATE(PackedCompareLT, assembler) {
3930 __ set1ps(XMM0, RAX, Immediate(bit_cast<int32_t, float>(2.0f)));
3931 __ set1ps(XMM1, RAX, Immediate(bit_cast<int32_t, float>(4.0f)));
3932 __ cmppslt(XMM0, XMM1);
3933 __ pushq(RAX);
3934 __ movss(Address(RSP, 0), XMM0);
3935 __ popq(RAX);
3936 __ ret();
3937}
3938
3939ASSEMBLER_TEST_RUN(PackedCompareLT, test) {
3940 typedef uint32_t (*PackedCompareLTCode)();
3941 uint32_t res = reinterpret_cast<PackedCompareLTCode>(test->entry())();
3942 EXPECT_EQ(static_cast<uword>(0xFFFFFFFF), res);
3943 EXPECT_DISASSEMBLY(
3944 "movl rax,0x........\n"
3945 "movd xmm0,rax\n"
3946 "shufps xmm0,xmm0 [0]\n"
3947 "movl rax,0x........\n"
3948 "movd xmm1,rax\n"
3949 "shufps xmm1,xmm1 [0]\n"
3950 "cmpps xmm0,xmm1 [lt]\n"
3951 "push rax\n"
3952 "movss [rsp],xmm0\n"
3953 "pop rax\n"
3954 "ret\n");
3955}
3956
3957ASSEMBLER_TEST_GENERATE(PackedCompareLE, assembler) {
3958 __ set1ps(XMM0, RAX, Immediate(bit_cast<int32_t, float>(2.0f)));
3959 __ set1ps(XMM1, RAX, Immediate(bit_cast<int32_t, float>(4.0f)));
3960 __ cmppsle(XMM0, XMM1);
3961 __ pushq(RAX);
3962 __ movss(Address(RSP, 0), XMM0);
3963 __ popq(RAX);
3964 __ ret();
3965}
3966
3967ASSEMBLER_TEST_RUN(PackedCompareLE, test) {
3968 typedef uint32_t (*PackedCompareLECode)();
3969 uint32_t res = reinterpret_cast<PackedCompareLECode>(test->entry())();
3970 EXPECT_EQ(static_cast<uword>(0xFFFFFFFF), res);
3971 EXPECT_DISASSEMBLY(
3972 "movl rax,0x........\n"
3973 "movd xmm0,rax\n"
3974 "shufps xmm0,xmm0 [0]\n"
3975 "movl rax,0x........\n"
3976 "movd xmm1,rax\n"
3977 "shufps xmm1,xmm1 [0]\n"
3978 "cmpps xmm0,xmm1 [le]\n"
3979 "push rax\n"
3980 "movss [rsp],xmm0\n"
3981 "pop rax\n"
3982 "ret\n");
3983}
3984
3985ASSEMBLER_TEST_GENERATE(PackedCompareNLT, assembler) {
3986 __ set1ps(XMM0, RAX, Immediate(bit_cast<int32_t, float>(2.0f)));
3987 __ set1ps(XMM1, RAX, Immediate(bit_cast<int32_t, float>(4.0f)));
3988 __ cmppsnlt(XMM0, XMM1);
3989 __ pushq(RAX);
3990 __ movss(Address(RSP, 0), XMM0);
3991 __ popq(RAX);
3992 __ ret();
3993}
3994
3995ASSEMBLER_TEST_RUN(PackedCompareNLT, test) {
3996 typedef uint32_t (*PackedCompareNLTCode)();
3997 uint32_t res = reinterpret_cast<PackedCompareNLTCode>(test->entry())();
3998 EXPECT_EQ(static_cast<uword>(0x0), res);
3999 EXPECT_DISASSEMBLY(
4000 "movl rax,0x........\n"
4001 "movd xmm0,rax\n"
4002 "shufps xmm0,xmm0 [0]\n"
4003 "movl rax,0x........\n"
4004 "movd xmm1,rax\n"
4005 "shufps xmm1,xmm1 [0]\n"
4006 "cmpps xmm0,xmm1 [nlt]\n"
4007 "push rax\n"
4008 "movss [rsp],xmm0\n"
4009 "pop rax\n"
4010 "ret\n");
4011}
4012
4013ASSEMBLER_TEST_GENERATE(PackedCompareNLE, assembler) {
4014 __ set1ps(XMM0, RAX, Immediate(bit_cast<int32_t, float>(2.0f)));
4015 __ set1ps(XMM1, RAX, Immediate(bit_cast<int32_t, float>(4.0f)));
4016 __ cmppsnle(XMM0, XMM1);
4017 __ pushq(RAX);
4018 __ movss(Address(RSP, 0), XMM0);
4019 __ popq(RAX);
4020 __ ret();
4021}
4022
4023ASSEMBLER_TEST_RUN(PackedCompareNLE, test) {
4024 typedef uint32_t (*PackedCompareNLECode)();
4025 uint32_t res = reinterpret_cast<PackedCompareNLECode>(test->entry())();
4026 EXPECT_EQ(static_cast<uword>(0x0), res);
4027 EXPECT_DISASSEMBLY(
4028 "movl rax,0x........\n"
4029 "movd xmm0,rax\n"
4030 "shufps xmm0,xmm0 [0]\n"
4031 "movl rax,0x........\n"
4032 "movd xmm1,rax\n"
4033 "shufps xmm1,xmm1 [0]\n"
4034 "cmpps xmm0,xmm1 [nle]\n"
4035 "push rax\n"
4036 "movss [rsp],xmm0\n"
4037 "pop rax\n"
4038 "ret\n");
4039}
4040
4041ASSEMBLER_TEST_GENERATE(PackedNegate, assembler) {
4042 EnterTestFrame(assembler);
4043 __ movl(RAX, Immediate(bit_cast<int32_t, float>(12.3f)));
4044 __ movd(XMM0, RAX);
4045 __ shufps(XMM0, XMM0, Immediate(0x0));
4046 __ negateps(XMM0, XMM0);
4047 __ shufps(XMM0, XMM0, Immediate(0xAA)); // Copy third lane into all 4 lanes.
4048 LeaveTestFrame(assembler);
4049 __ ret();
4050}
4051
4052ASSEMBLER_TEST_RUN(PackedNegate, test) {
4053 float res = test->InvokeWithCodeAndThread<float>();
4054 EXPECT_FLOAT_EQ(-12.3f, res, 0.001f);
4055 EXPECT_DISASSEMBLY_NOT_WINDOWS(
4056 "push rbp\n"
4057 "movq rbp,rsp\n"
4058 "push r12\n"
4059 "push pp\n"
4060 "push thr\n"
4061 "movq r12,[rdi+0x8]\n"
4062 "movq thr,rsi\n"
4063 "movq pp,[r12+0x27]\n"
4064 "movl rax,0x........\n"
4065 "movd xmm0,rax\n"
4066 "shufps xmm0,xmm0 [0]\n"
4067 "movq r11,[thr+0x...]\n"
4068 "xorps xmm0,[r11]\n"
4069 "shufps xmm0,xmm0 [aa]\n"
4070 "pop thr\n"
4071 "pop pp\n"
4072 "pop r12\n"
4073 "movq rsp,rbp\n"
4074 "pop rbp\n"
4075 "ret\n");
4076}
4077
4078ASSEMBLER_TEST_GENERATE(PackedAbsolute, assembler) {
4079 EnterTestFrame(assembler);
4080 __ movl(RAX, Immediate(bit_cast<int32_t, float>(-15.3f)));
4081 __ movd(XMM0, RAX);
4082 __ shufps(XMM0, XMM0, Immediate(0x0));
4083 __ absps(XMM0, XMM0);
4084 __ shufps(XMM0, XMM0, Immediate(0xAA)); // Copy third lane into all 4 lanes.
4085 LeaveTestFrame(assembler);
4086 __ ret();
4087}
4088
4089ASSEMBLER_TEST_RUN(PackedAbsolute, test) {
4090 float res = test->InvokeWithCodeAndThread<float>();
4091 EXPECT_FLOAT_EQ(15.3f, res, 0.001f);
4092 EXPECT_DISASSEMBLY_NOT_WINDOWS(
4093 "push rbp\n"
4094 "movq rbp,rsp\n"
4095 "push r12\n"
4096 "push pp\n"
4097 "push thr\n"
4098 "movq r12,[rdi+0x8]\n"
4099 "movq thr,rsi\n"
4100 "movq pp,[r12+0x27]\n"
4101 "movl rax,-0x........\n"
4102 "movd xmm0,rax\n"
4103 "shufps xmm0,xmm0 [0]\n"
4104 "movq r11,[thr+0x...]\n"
4105 "andps xmm0,[r11]\n"
4106 "shufps xmm0,xmm0 [aa]\n"
4107 "pop thr\n"
4108 "pop pp\n"
4109 "pop r12\n"
4110 "movq rsp,rbp\n"
4111 "pop rbp\n"
4112 "ret\n");
4113}
4114
4115ASSEMBLER_TEST_GENERATE(PackedSetWZero, assembler) {
4116 EnterTestFrame(assembler);
4117 __ set1ps(XMM0, RAX, Immediate(bit_cast<int32_t, float>(12.3f)));
4118 __ zerowps(XMM0, XMM0);
4119 __ shufps(XMM0, XMM0, Immediate(0xFF)); // Copy the W lane which is now 0.0.
4120 LeaveTestFrame(assembler);
4121 __ ret();
4122}
4123
4124ASSEMBLER_TEST_RUN(PackedSetWZero, test) {
4125 float res = test->InvokeWithCodeAndThread<float>();
4126 EXPECT_FLOAT_EQ(0.0f, res, 0.001f);
4127 EXPECT_DISASSEMBLY_NOT_WINDOWS(
4128 "push rbp\n"
4129 "movq rbp,rsp\n"
4130 "push r12\n"
4131 "push pp\n"
4132 "push thr\n"
4133 "movq r12,[rdi+0x8]\n"
4134 "movq thr,rsi\n"
4135 "movq pp,[r12+0x27]\n"
4136 "movl rax,0x........\n"
4137 "movd xmm0,rax\n"
4138 "shufps xmm0,xmm0 [0]\n"
4139 "movq r11,[thr+0x...]\n"
4140 "andps xmm0,[r11]\n"
4141 "shufps xmm0,xmm0 [ff]\n"
4142 "pop thr\n"
4143 "pop pp\n"
4144 "pop r12\n"
4145 "movq rsp,rbp\n"
4146 "pop rbp\n"
4147 "ret\n");
4148}
4149
4150ASSEMBLER_TEST_GENERATE(PackedMin, assembler) {
4151 __ set1ps(XMM0, RAX, Immediate(bit_cast<int32_t, float>(2.0f)));
4152 __ set1ps(XMM1, RAX, Immediate(bit_cast<int32_t, float>(4.0f)));
4153 __ minps(XMM0, XMM1);
4154 __ ret();
4155}
4156
4157ASSEMBLER_TEST_RUN(PackedMin, test) {
4158 typedef float (*PackedMinCode)();
4159 float res = reinterpret_cast<PackedMinCode>(test->entry())();
4160 EXPECT_FLOAT_EQ(2.0f, res, 0.001f);
4161 EXPECT_DISASSEMBLY(
4162 "movl rax,0x........\n"
4163 "movd xmm0,rax\n"
4164 "shufps xmm0,xmm0 [0]\n"
4165 "movl rax,0x........\n"
4166 "movd xmm1,rax\n"
4167 "shufps xmm1,xmm1 [0]\n"
4168 "minps xmm0,xmm1\n"
4169 "ret\n");
4170}
4171
4172ASSEMBLER_TEST_GENERATE(PackedMax, assembler) {
4173 __ set1ps(XMM0, RAX, Immediate(bit_cast<int32_t, float>(2.0f)));
4174 __ set1ps(XMM1, RAX, Immediate(bit_cast<int32_t, float>(4.0f)));
4175 __ maxps(XMM0, XMM1);
4176 __ ret();
4177}
4178
4179ASSEMBLER_TEST_RUN(PackedMax, test) {
4180 typedef float (*PackedMaxCode)();
4181 float res = reinterpret_cast<PackedMaxCode>(test->entry())();
4182 EXPECT_FLOAT_EQ(4.0f, res, 0.001f);
4183 EXPECT_DISASSEMBLY(
4184 "movl rax,0x........\n"
4185 "movd xmm0,rax\n"
4186 "shufps xmm0,xmm0 [0]\n"
4187 "movl rax,0x........\n"
4188 "movd xmm1,rax\n"
4189 "shufps xmm1,xmm1 [0]\n"
4190 "maxps xmm0,xmm1\n"
4191 "ret\n");
4192}
4193
4194ASSEMBLER_TEST_GENERATE(PackedLogicalOr, assembler) {
4195 static const struct ALIGN16 {
4196 uint32_t a;
4197 uint32_t b;
4198 uint32_t c;
4199 uint32_t d;
4200 } constant1 = {0xF0F0F0F0, 0xF0F0F0F0, 0xF0F0F0F0, 0xF0F0F0F0};
4201 static const struct ALIGN16 {
4202 uint32_t a;
4203 uint32_t b;
4204 uint32_t c;
4205 uint32_t d;
4206 } constant2 = {0x0F0F0F0F, 0x0F0F0F0F, 0x0F0F0F0F, 0x0F0F0F0F};
4207 __ movq(RAX, Immediate(reinterpret_cast<intptr_t>(&constant1)));
4208 __ movups(XMM0, Address(RAX, 0));
4209 __ movq(RAX, Immediate(reinterpret_cast<intptr_t>(&constant2)));
4210 __ movups(XMM1, Address(RAX, 0));
4211 __ orps(XMM0, XMM1);
4212 __ pushq(RAX);
4213 __ movss(Address(RSP, 0), XMM0);
4214 __ popq(RAX);
4215 __ ret();
4216}
4217
4218ASSEMBLER_TEST_RUN(PackedLogicalOr, test) {
4219 typedef uint32_t (*PackedLogicalOrCode)();
4220 uint32_t res = reinterpret_cast<PackedLogicalOrCode>(test->entry())();
4221 EXPECT_EQ(0xFFFFFFFF, res);
4222 EXPECT_DISASSEMBLY_ENDS_WITH(
4223 "movups xmm1,[rax]\n"
4224 "orps xmm0,xmm1\n"
4225 "push rax\n"
4226 "movss [rsp],xmm0\n"
4227 "pop rax\n"
4228 "ret\n");
4229}
4230
4231ASSEMBLER_TEST_GENERATE(PackedLogicalAnd, assembler) {
4232 static const struct ALIGN16 {
4233 uint32_t a;
4234 uint32_t b;
4235 uint32_t c;
4236 uint32_t d;
4237 } constant1 = {0xF0F0F0F0, 0xF0F0F0F0, 0xF0F0F0F0, 0xF0F0F0F0};
4238 static const struct ALIGN16 {
4239 uint32_t a;
4240 uint32_t b;
4241 uint32_t c;
4242 uint32_t d;
4243 } constant2 = {0x0F0FFF0F, 0x0F0F0F0F, 0x0F0F0F0F, 0x0F0F0F0F};
4244 __ movq(RAX, Immediate(reinterpret_cast<intptr_t>(&constant1)));
4245 __ movups(XMM0, Address(RAX, 0));
4246 __ movq(RAX, Immediate(reinterpret_cast<intptr_t>(&constant2)));
4247 __ andps(XMM0, Address(RAX, 0));
4248 __ pushq(RAX);
4249 __ movss(Address(RSP, 0), XMM0);
4250 __ popq(RAX);
4251 __ ret();
4252}
4253
4254ASSEMBLER_TEST_RUN(PackedLogicalAnd, test) {
4255 typedef uint32_t (*PackedLogicalAndCode)();
4256 uint32_t res = reinterpret_cast<PackedLogicalAndCode>(test->entry())();
4257 EXPECT_EQ(static_cast<uword>(0x0000F000), res);
4258 EXPECT_DISASSEMBLY_ENDS_WITH(
4259 "andps xmm0,[rax]\n"
4260 "push rax\n"
4261 "movss [rsp],xmm0\n"
4262 "pop rax\n"
4263 "ret\n");
4264}
4265
4266ASSEMBLER_TEST_GENERATE(PackedLogicalNot, assembler) {
4267 static const struct ALIGN16 {
4268 uint32_t a;
4269 uint32_t b;
4270 uint32_t c;
4271 uint32_t d;
4272 } constant1 = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF};
4273 EnterTestFrame(assembler);
4274 __ LoadImmediate(RAX, Immediate(reinterpret_cast<intptr_t>(&constant1)));
4275 __ movups(XMM9, Address(RAX, 0));
4276 __ notps(XMM0, XMM9);
4277 __ pushq(RAX);
4278 __ movss(Address(RSP, 0), XMM0);
4279 __ popq(RAX);
4280 LeaveTestFrame(assembler);
4281 __ ret();
4282}
4283
4284ASSEMBLER_TEST_RUN(PackedLogicalNot, test) {
4285 uint32_t res = test->InvokeWithCodeAndThread<uint32_t>();
4286 EXPECT_EQ(static_cast<uword>(0x0), res);
4287 EXPECT_DISASSEMBLY_NOT_WINDOWS_ENDS_WITH(
4288 "movups xmm9,[rax]\n"
4289 "movq r11,[thr+0x...]\n"
4290 "movups xmm0,[r11]\n"
4291 "xorps xmm0,xmm9\n"
4292 "push rax\n"
4293 "movss [rsp],xmm0\n"
4294 "pop rax\n"
4295 "pop thr\n"
4296 "pop pp\n"
4297 "pop r12\n"
4298 "movq rsp,rbp\n"
4299 "pop rbp\n"
4300 "ret\n");
4301}
4302
4303ASSEMBLER_TEST_GENERATE(PackedMoveHighLow, assembler) {
4304 static const struct ALIGN16 {
4305 float a;
4306 float b;
4307 float c;
4308 float d;
4309 } constant0 = {1.0, 2.0, 3.0, 4.0};
4310 static const struct ALIGN16 {
4311 float a;
4312 float b;
4313 float c;
4314 float d;
4315 } constant1 = {5.0, 6.0, 7.0, 8.0};
4316 // XMM9 = 1.0f, 2.0f, 3.0f, 4.0f.
4317 __ movq(RAX, Immediate(reinterpret_cast<intptr_t>(&constant0)));
4318 __ movups(XMM9, Address(RAX, 0));
4319 // XMM1 = 5.0f, 6.0f, 7.0f, 8.0f.
4320 __ movq(RAX, Immediate(reinterpret_cast<intptr_t>(&constant1)));
4321 __ movups(XMM1, Address(RAX, 0));
4322 // XMM9 = 7.0f, 8.0f, 3.0f, 4.0f.
4323 __ movhlps(XMM9, XMM1);
4324 __ xorps(XMM1, XMM1);
4325 // XMM1 = 7.0f, 8.0f, 3.0f, 4.0f.
4326 __ movaps(XMM1, XMM9);
4327 __ shufps(XMM9, XMM9, Immediate(0x00)); // 7.0f.
4328 __ shufps(XMM1, XMM1, Immediate(0x55)); // 8.0f.
4329 __ addss(XMM9, XMM1); // 15.0f.
4330 __ movaps(XMM0, XMM9);
4331 __ ret();
4332}
4333
4334ASSEMBLER_TEST_RUN(PackedMoveHighLow, test) {
4335 typedef float (*PackedMoveHighLow)();
4336 float res = reinterpret_cast<PackedMoveHighLow>(test->entry())();
4337 EXPECT_FLOAT_EQ(15.0f, res, 0.001f);
4338 EXPECT_DISASSEMBLY_ENDS_WITH(
4339 "movups xmm1,[rax]\n"
4340 "movhlps xmm9,xmm1\n"
4341 "xorps xmm1,xmm1\n"
4342 "movaps xmm1,xmm9\n"
4343 "shufps xmm9,xmm9 [0]\n"
4344 "shufps xmm1,xmm1 [55]\n"
4345 "addss xmm9,xmm1\n"
4346 "movaps xmm0,xmm9\n"
4347 "ret\n");
4348}
4349
4350ASSEMBLER_TEST_GENERATE(PackedMoveLowHigh, assembler) {
4351 static const struct ALIGN16 {
4352 float a;
4353 float b;
4354 float c;
4355 float d;
4356 } constant0 = {1.0, 2.0, 3.0, 4.0};
4357 static const struct ALIGN16 {
4358 float a;
4359 float b;
4360 float c;
4361 float d;
4362 } constant1 = {5.0, 6.0, 7.0, 8.0};
4363 // XMM9 = 1.0f, 2.0f, 3.0f, 4.0f.
4364 __ movq(RAX, Immediate(reinterpret_cast<intptr_t>(&constant0)));
4365 __ movups(XMM9, Address(RAX, 0));
4366 // XMM1 = 5.0f, 6.0f, 7.0f, 8.0f.
4367 __ movq(RAX, Immediate(reinterpret_cast<intptr_t>(&constant1)));
4368 __ movups(XMM1, Address(RAX, 0));
4369 // XMM9 = 1.0f, 2.0f, 5.0f, 6.0f
4370 __ movlhps(XMM9, XMM1);
4371 __ xorps(XMM1, XMM1);
4372 // XMM1 = 1.0f, 2.0f, 5.0f, 6.0f
4373 __ movaps(XMM1, XMM9);
4374 __ shufps(XMM9, XMM9, Immediate(0xAA)); // 5.0f.
4375 __ shufps(XMM1, XMM1, Immediate(0xFF)); // 6.0f.
4376 __ addss(XMM9, XMM1); // 11.0f.
4377 __ movaps(XMM0, XMM9);
4378 __ ret();
4379}
4380
4381ASSEMBLER_TEST_RUN(PackedMoveLowHigh, test) {
4382 typedef float (*PackedMoveLowHigh)();
4383 float res = reinterpret_cast<PackedMoveLowHigh>(test->entry())();
4384 EXPECT_FLOAT_EQ(11.0f, res, 0.001f);
4385 EXPECT_DISASSEMBLY_ENDS_WITH(
4386 "movups xmm1,[rax]\n"
4387 "movlhps xmm9,xmm1\n"
4388 "xorps xmm1,xmm1\n"
4389 "movaps xmm1,xmm9\n"
4390 "shufps xmm9,xmm9 [aa]\n"
4391 "shufps xmm1,xmm1 [ff]\n"
4392 "addss xmm9,xmm1\n"
4393 "movaps xmm0,xmm9\n"
4394 "ret\n");
4395}
4396
4397ASSEMBLER_TEST_GENERATE(PackedUnpackLow, assembler) {
4398 static const struct ALIGN16 {
4399 float a;
4400 float b;
4401 float c;
4402 float d;
4403 } constant0 = {1.0, 2.0, 3.0, 4.0};
4404 static const struct ALIGN16 {
4405 float a;
4406 float b;
4407 float c;
4408 float d;
4409 } constant1 = {5.0, 6.0, 7.0, 8.0};
4410 // XMM9 = 1.0f, 2.0f, 3.0f, 4.0f.
4411 __ movq(RAX, Immediate(reinterpret_cast<intptr_t>(&constant0)));
4412 __ movups(XMM9, Address(RAX, 0));
4413 // XMM1 = 5.0f, 6.0f, 7.0f, 8.0f.
4414 __ movq(RAX, Immediate(reinterpret_cast<intptr_t>(&constant1)));
4415 __ movups(XMM1, Address(RAX, 0));
4416 // XMM9 = 1.0f, 5.0f, 2.0f, 6.0f.
4417 __ unpcklps(XMM9, XMM1);
4418 // XMM1 = 1.0f, 5.0f, 2.0f, 6.0f.
4419 __ movaps(XMM1, XMM9);
4420 __ shufps(XMM9, XMM9, Immediate(0x55));
4421 __ shufps(XMM1, XMM1, Immediate(0xFF));
4422 __ addss(XMM9, XMM1); // 11.0f.
4423 __ movaps(XMM0, XMM9);
4424 __ ret();
4425}
4426
4427ASSEMBLER_TEST_RUN(PackedUnpackLow, test) {
4428 typedef float (*PackedUnpackLow)();
4429 float res = reinterpret_cast<PackedUnpackLow>(test->entry())();
4430 EXPECT_FLOAT_EQ(11.0f, res, 0.001f);
4431 EXPECT_DISASSEMBLY_ENDS_WITH(
4432 "movups xmm1,[rax]\n"
4433 "unpcklps xmm9,xmm1\n"
4434 "movaps xmm1,xmm9\n"
4435 "shufps xmm9,xmm9 [55]\n"
4436 "shufps xmm1,xmm1 [ff]\n"
4437 "addss xmm9,xmm1\n"
4438 "movaps xmm0,xmm9\n"
4439 "ret\n");
4440}
4441
4442ASSEMBLER_TEST_GENERATE(PackedUnpackHigh, assembler) {
4443 static const struct ALIGN16 {
4444 float a;
4445 float b;
4446 float c;
4447 float d;
4448 } constant0 = {1.0, 2.0, 3.0, 4.0};
4449 static const struct ALIGN16 {
4450 float a;
4451 float b;
4452 float c;
4453 float d;
4454 } constant1 = {5.0, 6.0, 7.0, 8.0};
4455 // XMM9 = 1.0f, 2.0f, 3.0f, 4.0f.
4456 __ movq(RAX, Immediate(reinterpret_cast<intptr_t>(&constant0)));
4457 __ movups(XMM9, Address(RAX, 0));
4458 // XMM1 = 5.0f, 6.0f, 7.0f, 8.0f.
4459 __ movq(RAX, Immediate(reinterpret_cast<intptr_t>(&constant1)));
4460 __ movups(XMM1, Address(RAX, 0));
4461 // XMM9 = 3.0f, 7.0f, 4.0f, 8.0f.
4462 __ unpckhps(XMM9, XMM1);
4463 // XMM1 = 3.0f, 7.0f, 4.0f, 8.0f.
4464 __ movaps(XMM1, XMM9);
4465 __ shufps(XMM9, XMM9, Immediate(0x00));
4466 __ shufps(XMM1, XMM1, Immediate(0xAA));
4467 __ addss(XMM9, XMM1); // 7.0f.
4468 __ movaps(XMM0, XMM9);
4469 __ ret();
4470}
4471
4472ASSEMBLER_TEST_RUN(PackedUnpackHigh, test) {
4473 typedef float (*PackedUnpackHigh)();
4474 float res = reinterpret_cast<PackedUnpackHigh>(test->entry())();
4475 EXPECT_FLOAT_EQ(7.0f, res, 0.001f);
4476 EXPECT_DISASSEMBLY_ENDS_WITH(
4477 "movups xmm1,[rax]\n"
4478 "unpckhps xmm9,xmm1\n"
4479 "movaps xmm1,xmm9\n"
4480 "shufps xmm9,xmm9 [0]\n"
4481 "shufps xmm1,xmm1 [aa]\n"
4482 "addss xmm9,xmm1\n"
4483 "movaps xmm0,xmm9\n"
4484 "ret\n");
4485}
4486
4487ASSEMBLER_TEST_GENERATE(PackedUnpackLowPair, assembler) {
4488 static const struct ALIGN16 {
4489 float a;
4490 float b;
4491 float c;
4492 float d;
4493 } constant0 = {1.0, 2.0, 3.0, 4.0};
4494 static const struct ALIGN16 {
4495 float a;
4496 float b;
4497 float c;
4498 float d;
4499 } constant1 = {5.0, 6.0, 7.0, 8.0};
4500 // XMM9 = 1.0f, 2.0f, 3.0f, 4.0f.
4501 __ movq(RAX, Immediate(reinterpret_cast<intptr_t>(&constant0)));
4502 __ movups(XMM9, Address(RAX, 0));
4503 // XMM1 = 5.0f, 6.0f, 7.0f, 8.0f.
4504 __ movq(RAX, Immediate(reinterpret_cast<intptr_t>(&constant1)));
4505 __ movups(XMM1, Address(RAX, 0));
4506 // XMM9 = 1.0f, 2.0f, 5.0f, 6.0f.
4507 __ unpcklpd(XMM9, XMM1);
4508 // XMM1 = 1.0f, 2.0f, 5.0f, 6.0f.
4509 __ movaps(XMM1, XMM9);
4510 __ shufps(XMM9, XMM9, Immediate(0x00));
4511 __ shufps(XMM1, XMM1, Immediate(0xAA));
4512 __ addss(XMM9, XMM1); // 6.0f.
4513 __ movaps(XMM0, XMM9);
4514 __ ret();
4515}
4516
4517ASSEMBLER_TEST_RUN(PackedUnpackLowPair, test) {
4518 typedef float (*PackedUnpackLowPair)();
4519 float res = reinterpret_cast<PackedUnpackLowPair>(test->entry())();
4520 EXPECT_FLOAT_EQ(6.0f, res, 0.001f);
4521 EXPECT_DISASSEMBLY_ENDS_WITH(
4522 "movups xmm1,[rax]\n"
4523 "unpcklpd xmm9,xmm1\n"
4524 "movaps xmm1,xmm9\n"
4525 "shufps xmm9,xmm9 [0]\n"
4526 "shufps xmm1,xmm1 [aa]\n"
4527 "addss xmm9,xmm1\n"
4528 "movaps xmm0,xmm9\n"
4529 "ret\n");
4530}
4531
4532ASSEMBLER_TEST_GENERATE(PackedUnpackHighPair, assembler) {
4533 static const struct ALIGN16 {
4534 float a;
4535 float b;
4536 float c;
4537 float d;
4538 } constant0 = {1.0, 2.0, 3.0, 4.0};
4539 static const struct ALIGN16 {
4540 float a;
4541 float b;
4542 float c;
4543 float d;
4544 } constant1 = {5.0, 6.0, 7.0, 8.0};
4545 // XMM9 = 1.0f, 2.0f, 3.0f, 4.0f.
4546 __ movq(RAX, Immediate(reinterpret_cast<intptr_t>(&constant0)));
4547 __ movups(XMM9, Address(RAX, 0));
4548 // XMM1 = 5.0f, 6.0f, 7.0f, 8.0f.
4549 __ movq(RAX, Immediate(reinterpret_cast<intptr_t>(&constant1)));
4550 __ movups(XMM1, Address(RAX, 0));
4551 // XMM9 = 3.0f, 4.0f, 7.0f, 8.0f.
4552 __ unpckhpd(XMM9, XMM1);
4553 // XMM1 = 3.0f, 4.0f, 7.0f, 8.0f.
4554 __ movaps(XMM1, XMM9);
4555 __ shufps(XMM9, XMM9, Immediate(0x55));
4556 __ shufps(XMM1, XMM1, Immediate(0xFF));
4557 __ addss(XMM9, XMM1); // 12.0f.
4558 __ movaps(XMM0, XMM9);
4559 __ ret();
4560}
4561
4562ASSEMBLER_TEST_RUN(PackedUnpackHighPair, test) {
4563 typedef float (*PackedUnpackHighPair)();
4564 float res = reinterpret_cast<PackedUnpackHighPair>(test->entry())();
4565 EXPECT_FLOAT_EQ(12.0f, res, 0.001f);
4566 EXPECT_DISASSEMBLY_ENDS_WITH(
4567 "movups xmm1,[rax]\n"
4568 "unpckhpd xmm9,xmm1\n"
4569 "movaps xmm1,xmm9\n"
4570 "shufps xmm9,xmm9 [55]\n"
4571 "shufps xmm1,xmm1 [ff]\n"
4572 "addss xmm9,xmm1\n"
4573 "movaps xmm0,xmm9\n"
4574 "ret\n");
4575}
4576
4577ASSEMBLER_TEST_GENERATE(DoubleFPMoves, assembler) {
4578 __ movq(RAX, Immediate(bit_cast<int64_t, double>(1024.67)));
4579 __ pushq(R15); // Callee saved.
4580 __ pushq(RAX);
4581 __ movsd(XMM0, Address(RSP, 0));
4582 __ movsd(XMM1, XMM0);
4583 __ movsd(XMM2, XMM1);
4584 __ movsd(XMM3, XMM2);
4585 __ movsd(XMM4, XMM3);
4586 __ movsd(XMM5, XMM4);
4587 __ movsd(XMM6, XMM5);
4588 __ movsd(XMM7, XMM6);
4589 __ movsd(XMM8, XMM7);
4590 __ movsd(XMM9, XMM8);
4591 __ movsd(XMM10, XMM9);
4592 __ movsd(XMM11, XMM10);
4593 __ movsd(XMM12, XMM11);
4594 __ movsd(XMM13, XMM12);
4595 __ movsd(XMM14, XMM13);
4596 __ movsd(XMM15, XMM14);
4597 __ movq(Address(RSP, 0), Immediate(0));
4598 __ movsd(XMM0, Address(RSP, 0));
4599 __ movsd(Address(RSP, 0), XMM15);
4600 __ movsd(XMM1, Address(RSP, 0));
4601 __ movq(R10, RSP);
4602 __ movsd(Address(R10, 0), XMM1);
4603 __ movsd(XMM2, Address(R10, 0));
4604 __ movq(R15, RSP);
4605 __ movsd(Address(R15, 0), XMM2);
4606 __ movsd(XMM3, Address(R15, 0));
4607 __ movq(RAX, RSP);
4608 __ movsd(Address(RAX, 0), XMM3);
4609 __ movsd(XMM4, Address(RAX, 0));
4610 __ movsd(XMM15, Address(RSP, 0));
4611 __ movaps(XMM14, XMM15);
4612 __ movaps(XMM13, XMM14);
4613 __ movaps(XMM12, XMM13);
4614 __ movaps(XMM11, XMM12);
4615 __ movaps(XMM10, XMM11);
4616 __ movaps(XMM9, XMM10);
4617 __ movaps(XMM8, XMM9);
4618 __ movaps(XMM7, XMM8);
4619 __ movaps(XMM6, XMM7);
4620 __ movaps(XMM5, XMM6);
4621 __ movaps(XMM4, XMM5);
4622 __ movaps(XMM3, XMM4);
4623 __ movaps(XMM2, XMM3);
4624 __ movaps(XMM1, XMM2);
4625 __ movaps(XMM0, XMM1);
4626 __ popq(RAX);
4627 __ popq(R15); // Callee saved.
4628 __ ret();
4629}
4630
4631ASSEMBLER_TEST_RUN(DoubleFPMoves, test) {
4632 typedef double (*DoubleFPMovesCode)();
4633 EXPECT_FLOAT_EQ(1024.67, reinterpret_cast<DoubleFPMovesCode>(test->entry())(),
4634 0.001);
4635 EXPECT_DISASSEMBLY(
4636 "movq rax,0x................\n"
4637 "push pp\n"
4638 "push rax\n"
4639 "movsd xmm0,[rsp]\n"
4640 "movsd xmm1,xmm0\n"
4641 "movsd xmm2,xmm1\n"
4642 "movsd xmm3,xmm2\n"
4643 "movsd xmm4,xmm3\n"
4644 "movsd xmm5,xmm4\n"
4645 "movsd xmm6,xmm5\n"
4646 "movsd xmm7,xmm6\n"
4647 "movsd xmm8,xmm7\n"
4648 "movsd xmm9,xmm8\n"
4649 "movsd xmm10,xmm9\n"
4650 "movsd xmm11,xmm10\n"
4651 "movsd xmm12,xmm11\n"
4652 "movsd xmm13,xmm12\n"
4653 "movsd xmm14,xmm13\n"
4654 "movsd xmm15,xmm14\n"
4655 "movq [rsp],0\n"
4656 "movsd xmm0,[rsp]\n"
4657 "movsd [rsp],xmm15\n"
4658 "movsd xmm1,[rsp]\n"
4659 "movq r10,rsp\n"
4660 "movsd [r10],xmm1\n"
4661 "movsd xmm2,[r10]\n"
4662 "movq pp,rsp\n"
4663 "movsd [pp],xmm2\n"
4664 "movsd xmm3,[pp]\n"
4665 "movq rax,rsp\n"
4666 "movsd [rax],xmm3\n"
4667 "movsd xmm4,[rax]\n"
4668 "movsd xmm15,[rsp]\n"
4669 "movaps xmm14,xmm15\n"
4670 "movaps xmm13,xmm14\n"
4671 "movaps xmm12,xmm13\n"
4672 "movaps xmm11,xmm12\n"
4673 "movaps xmm10,xmm11\n"
4674 "movaps xmm9,xmm10\n"
4675 "movaps xmm8,xmm9\n"
4676 "movaps xmm7,xmm8\n"
4677 "movaps xmm6,xmm7\n"
4678 "movaps xmm5,xmm6\n"
4679 "movaps xmm4,xmm5\n"
4680 "movaps xmm3,xmm4\n"
4681 "movaps xmm2,xmm3\n"
4682 "movaps xmm1,xmm2\n"
4683 "movaps xmm0,xmm1\n"
4684 "pop rax\n"
4685 "pop pp\n"
4686 "ret\n");
4687}
4688
4689ASSEMBLER_TEST_GENERATE(DoubleFPOperations, assembler) {
4690 __ movq(RAX, Immediate(bit_cast<int64_t, double>(12.3)));
4691 __ pushq(RAX);
4692 __ movsd(XMM0, Address(RSP, 0));
4693 __ movsd(XMM8, Address(RSP, 0));
4694 __ movq(RAX, Immediate(bit_cast<int64_t, double>(3.4)));
4695 __ movq(Address(RSP, 0), RAX);
4696 __ movsd(XMM12, Address(RSP, 0));
4697 __ addsd(XMM8, XMM12); // 15.7
4698 __ mulsd(XMM8, XMM12); // 53.38
4699 __ subsd(XMM8, XMM12); // 49.98
4700 __ divsd(XMM8, XMM12); // 14.7
4701 __ sqrtsd(XMM8, XMM8); // 3.834
4702 __ movsd(XMM1, Address(RSP, 0));
4703 __ addsd(XMM0, XMM1); // 15.7
4704 __ mulsd(XMM0, XMM1); // 53.38
4705 __ subsd(XMM0, XMM1); // 49.98
4706 __ divsd(XMM0, XMM1); // 14.7
4707 __ sqrtsd(XMM0, XMM0); // 3.834057902
4708 __ addsd(XMM0, XMM8); // 7.6681
4709 __ popq(RAX);
4710 __ ret();
4711}
4712
4713ASSEMBLER_TEST_RUN(DoubleFPOperations, test) {
4714 typedef double (*SingleFPOperationsCode)();
4715 double res = reinterpret_cast<SingleFPOperationsCode>(test->entry())();
4716 EXPECT_FLOAT_EQ(7.668, res, 0.001);
4717 EXPECT_DISASSEMBLY(
4718 "movq rax,0x................\n"
4719 "push rax\n"
4720 "movsd xmm0,[rsp]\n"
4721 "movsd xmm8,[rsp]\n"
4722 "movq rax,0x................\n"
4723 "movq [rsp],rax\n"
4724 "movsd xmm12,[rsp]\n"
4725 "addsd xmm8,xmm12\n"
4726 "mulsd xmm8,xmm12\n"
4727 "subsd xmm8,xmm12\n"
4728 "divsd xmm8,xmm12\n"
4729 "sqrtsd xmm8,xmm8\n"
4730 "movsd xmm1,[rsp]\n"
4731 "addsd xmm0,xmm1\n"
4732 "mulsd xmm0,xmm1\n"
4733 "subsd xmm0,xmm1\n"
4734 "divsd xmm0,xmm1\n"
4735 "sqrtsd xmm0,xmm0\n"
4736 "addsd xmm0,xmm8\n"
4737 "pop rax\n"
4738 "ret\n");
4739}
4740
4741ASSEMBLER_TEST_GENERATE(Int32ToDoubleConversion, assembler) {
4742 // Fill upper bits with garbage.
4743 __ movq(R11, Immediate(0x1111111100000006));
4744 __ cvtsi2sdl(XMM0, R11);
4745 // Fill upper bits with garbage.
4746 __ movq(R11, Immediate(0x2222222200000008));
4747 __ cvtsi2sdl(XMM8, R11);
4748 __ subsd(XMM0, XMM8);
4749 __ ret();
4750}
4751
4752ASSEMBLER_TEST_RUN(Int32ToDoubleConversion, test) {
4753 typedef double (*Int32ToDoubleConversion)();
4754 double res = reinterpret_cast<Int32ToDoubleConversion>(test->entry())();
4755 EXPECT_FLOAT_EQ(-2.0, res, 0.001);
4756 EXPECT_DISASSEMBLY(
4757 "movq r11,0x................\n"
4758 "cvtsi2sd xmm0,r11\n"
4759 "movq r11,0x................\n"
4760 "cvtsi2sd xmm8,r11\n"
4761 "subsd xmm0,xmm8\n"
4762 "ret\n");
4763}
4764
4765ASSEMBLER_TEST_GENERATE(Int64ToDoubleConversion, assembler) {
4766 __ movq(RDX, Immediate(12LL << 32));
4767 __ cvtsi2sdq(XMM0, RDX);
4768 __ movsd(XMM15, XMM0); // Move to high register
4769 __ addsd(XMM0, XMM0); // Stomp XMM0
4770 __ movsd(XMM0, XMM15); // Move back to XMM0
4771 __ ret();
4772}
4773
4774ASSEMBLER_TEST_RUN(Int64ToDoubleConversion, test) {
4775 typedef double (*Int64ToDoubleConversionCode)();
4776 double res = reinterpret_cast<Int64ToDoubleConversionCode>(test->entry())();
4777 EXPECT_FLOAT_EQ(static_cast<double>(12LL << 32), res, 0.001);
4778 EXPECT_DISASSEMBLY(
4779 "movq rdx,0x................\n"
4780 "cvtsi2sd xmm0,rdx\n"
4781 "movsd xmm15,xmm0\n"
4782 "addsd xmm0,xmm0\n"
4783 "movsd xmm0,xmm15\n"
4784 "ret\n");
4785}
4786
4787ASSEMBLER_TEST_GENERATE(DoubleToInt64Conversion, assembler) {
4788 __ movq(RAX, Immediate(bit_cast<int64_t, double>(4.2e22)));
4789 __ pushq(RAX);
4790 __ movsd(XMM9, Address(RSP, 0));
4791 __ popq(RAX);
4792 __ cvttsd2siq(RAX, XMM9);
4793 __ CompareImmediate(RAX, Immediate(0x8000000000000000ll));
4794 Label ok;
4795 __ j(EQUAL, &ok);
4796 __ int3(); // cvttsd2siq overflow not detected
4797 __ Bind(&ok);
4798 __ movq(RAX, Immediate(bit_cast<int64_t, double>(4.2e11)));
4799 __ pushq(RAX);
4800 __ movsd(XMM9, Address(RSP, 0));
4801 __ movsd(XMM6, Address(RSP, 0));
4802 __ popq(RAX);
4803 __ cvttsd2siq(R10, XMM6);
4804 __ cvttsd2siq(RDX, XMM6);
4805 __ cvttsd2siq(R10, XMM9);
4806 __ cvttsd2siq(RDX, XMM9);
4807 __ subq(RDX, R10);
4808 __ addq(RDX, RDX);
4809 __ addq(RDX, R10);
4810 __ movq(RAX, RDX);
4811 __ ret();
4812}
4813
4814ASSEMBLER_TEST_RUN(DoubleToInt64Conversion, test) {
4815 typedef int64_t (*DoubleToInt64ConversionCode)();
4816 int64_t res = reinterpret_cast<DoubleToInt64ConversionCode>(test->entry())();
4817 EXPECT_EQ(420000000000l, res);
4818 EXPECT_DISASSEMBLY(
4819 "movq rax,0x................\n"
4820 "push rax\n"
4821 "movsd xmm9,[rsp]\n"
4822 "pop rax\n"
4823 "cvttsd2siq rax,xmm9\n"
4824 "movq r11,0x................\n"
4825 "cmpq rax,r11\n"
4826 "jz 0x................\n"
4827 "int3\n"
4828 "movq rax,0x................\n"
4829 "push rax\n"
4830 "movsd xmm9,[rsp]\n"
4831 "movsd xmm6,[rsp]\n"
4832 "pop rax\n"
4833 "cvttsd2siq r10,xmm6\n"
4834 "cvttsd2siq rdx,xmm6\n"
4835 "cvttsd2siq r10,xmm9\n"
4836 "cvttsd2siq rdx,xmm9\n"
4837 "subq rdx,r10\n"
4838 "addq rdx,rdx\n"
4839 "addq rdx,r10\n"
4840 "movq rax,rdx\n"
4841 "ret\n");
4842}
4843
4844ASSEMBLER_TEST_GENERATE(DoubleToInt32Conversion, assembler) {
4845 // Check that a too big double results in the overflow value for a conversion
4846 // to signed 32 bit.
4847 __ movq(RAX, Immediate(bit_cast<int64_t, double>(4.2e11)));
4848 __ pushq(RAX);
4849 __ movsd(XMM9, Address(RSP, 0));
4850 __ popq(RAX);
4851 __ cvttsd2sil(RAX, XMM9);
4852 __ CompareImmediate(RAX, Immediate(0x80000000ll));
4853 {
4854 Label ok;
4855 __ j(EQUAL, &ok);
4856 __ int3(); // cvttsd2sil overflow not detected.
4857 __ Bind(&ok);
4858 }
4859
4860 // Check that negative floats result in signed 32 bit results with the top
4861 // bits zeroed.
4862 __ movq(RAX, Immediate(bit_cast<int64_t, double>(-42.0)));
4863 __ pushq(RAX);
4864 __ movsd(XMM9, Address(RSP, 0));
4865 __ popq(RAX);
4866 // These high 1-bits will be zeroed in the next insn.
4867 __ movq(R10, Immediate(-1));
4868 // Put -42 in r10d, zeroing the high bits of r10.
4869 __ cvttsd2sil(R10, XMM9);
4870 __ CompareImmediate(R10, Immediate(-42 & 0xffffffffll));
4871 {
4872 Label ok;
4873 __ j(EQUAL, &ok);
4874 __ int3(); // cvttsd2sil negative result error
4875 __ Bind(&ok);
4876 }
4877
4878 // Check for correct result for positive in-range input.
4879 __ movq(RAX, Immediate(bit_cast<int64_t, double>(42.0)));
4880 __ pushq(RAX);
4881 __ movsd(XMM9, Address(RSP, 0));
4882 __ movsd(XMM6, Address(RSP, 0));
4883 __ popq(RAX);
4884 __ cvttsd2sil(R10, XMM6);
4885 __ cvttsd2sil(RDX, XMM6);
4886 __ cvttsd2sil(R10, XMM9);
4887 __ cvttsd2sil(RDX, XMM9);
4888 __ subq(RDX, R10);
4889 __ addq(RDX, RDX);
4890 __ addq(RDX, R10);
4891 __ movq(RAX, RDX);
4892 __ ret();
4893}
4894
4895ASSEMBLER_TEST_RUN(DoubleToInt32Conversion, test) {
4896 typedef int64_t (*DoubleToInt32ConversionCode)();
4897 int64_t res = reinterpret_cast<DoubleToInt32ConversionCode>(test->entry())();
4898 EXPECT_EQ(42, res);
4899 EXPECT_DISASSEMBLY(
4900 "movq rax,0x................\n"
4901 "push rax\n"
4902 "movsd xmm9,[rsp]\n"
4903 "pop rax\n"
4904 "cvttsd2sil rax,xmm9\n"
4905 "movl r11,0x........\n"
4906 "cmpq rax,r11\n"
4907 "jz 0x................\n"
4908 "int3\n"
4909 "movq rax,0x................\n"
4910 "push rax\n"
4911 "movsd xmm9,[rsp]\n"
4912 "pop rax\n"
4913 "movq r10,-1\n"
4914 "cvttsd2sil r10,xmm9\n"
4915 "movl r11,0x........\n"
4916 "cmpq r10,r11\n"
4917 "jz 0x................\n"
4918 "int3\n"
4919 "movq rax,0x................\n"
4920 "push rax\n"
4921 "movsd xmm9,[rsp]\n"
4922 "movsd xmm6,[rsp]\n"
4923 "pop rax\n"
4924 "cvttsd2sil r10,xmm6\n"
4925 "cvttsd2sil rdx,xmm6\n"
4926 "cvttsd2sil r10,xmm9\n"
4927 "cvttsd2sil rdx,xmm9\n"
4928 "subq rdx,r10\n"
4929 "addq rdx,rdx\n"
4930 "addq rdx,r10\n"
4931 "movq rax,rdx\n"
4932 "ret\n");
4933}
4934
4935ASSEMBLER_TEST_GENERATE(TestObjectCompare, assembler) {
4936 ObjectStore* object_store = Isolate::Current()->object_store();
4937 const Object& obj = Object::ZoneHandle(object_store->smi_class());
4938 Label fail;
4939 EnterTestFrame(assembler);
4940 __ LoadObject(RAX, obj);
4941 __ CompareObject(RAX, obj);
4942 __ j(NOT_EQUAL, &fail);
4943 __ LoadObject(RCX, obj);
4944 __ CompareObject(RCX, obj);
4945 __ j(NOT_EQUAL, &fail);
4946 const Smi& smi = Smi::ZoneHandle(Smi::New(15));
4947 __ LoadObject(RCX, smi);
4948 __ CompareObject(RCX, smi);
4949 __ j(NOT_EQUAL, &fail);
4950 __ pushq(RAX);
4951 __ StoreObject(Address(RSP, 0), obj);
4952 __ popq(RCX);
4953 __ CompareObject(RCX, obj);
4954 __ j(NOT_EQUAL, &fail);
4955 __ pushq(RAX);
4956 __ StoreObject(Address(RSP, 0), smi);
4957 __ popq(RCX);
4958 __ CompareObject(RCX, smi);
4959 __ j(NOT_EQUAL, &fail);
4960 __ movl(RAX, Immediate(1)); // OK
4961 LeaveTestFrame(assembler);
4962 __ ret();
4963 __ Bind(&fail);
4964 __ movl(RAX, Immediate(0)); // Fail.
4965 LeaveTestFrame(assembler);
4966 __ ret();
4967}
4968
4969ASSEMBLER_TEST_RUN(TestObjectCompare, test) {
4970 bool res = test->InvokeWithCodeAndThread<bool>();
4971 EXPECT_EQ(true, res);
4972 EXPECT_DISASSEMBLY_NOT_WINDOWS(
4973 "push rbp\n"
4974 "movq rbp,rsp\n"
4975 "push r12\n"
4976 "push pp\n"
4977 "push thr\n"
4978 "movq r12,[rdi+0x8]\n"
4979 "movq thr,rsi\n"
4980 "movq pp,[r12+0x27]\n"
4981 "movq rax,[pp+0xf]\n"
4982 "cmpq rax,[pp+0xf]\n"
4983 "jnz 0x................\n"
4984 "movq rcx,[pp+0xf]\n"
4985 "cmpq rcx,[pp+0xf]\n"
4986 "jnz 0x................\n"
4987 "movl rcx,0x1e\n"
4988 "cmpq rcx,0x1e\n"
4989 "jnz 0x................\n"
4990 "push rax\n"
4991 "movq r11,[pp+0xf]\n"
4992 "movq [rsp],r11\n"
4993 "pop rcx\n"
4994 "cmpq rcx,[pp+0xf]\n"
4995 "jnz 0x................\n"
4996 "push rax\n"
4997 "movq [rsp],0x1e\n"
4998 "pop rcx\n"
4999 "cmpq rcx,0x1e\n"
5000 "jnz 0x................\n"
5001 "movl rax,1\n"
5002 "pop thr\n"
5003 "pop pp\n"
5004 "pop r12\n"
5005 "movq rsp,rbp\n"
5006 "pop rbp\n"
5007 "ret\n"
5008 "movl rax,0\n"
5009 "pop thr\n"
5010 "pop pp\n"
5011 "pop r12\n"
5012 "movq rsp,rbp\n"
5013 "pop rbp\n"
5014 "ret\n");
5015}
5016
5017ASSEMBLER_TEST_GENERATE(TestNop, assembler) {
5018 __ nop(1);
5019 __ nop(2);
5020 __ nop(3);
5021 __ nop(4);
5022 __ nop(5);
5023 __ nop(6);
5024 __ nop(7);
5025 __ nop(8);
5026 __ movq(RAX, Immediate(assembler->CodeSize())); // Return code size.
5027 __ ret();
5028}
5029
5030ASSEMBLER_TEST_RUN(TestNop, test) {
5031 typedef int (*TestNop)();
5032 int res = reinterpret_cast<TestNop>(test->payload_start())();
5033 EXPECT_EQ(36, res); // 36 nop bytes emitted.
5034 EXPECT_DISASSEMBLY(
5035 "nop\n"
5036 "nop\n"
5037 "nop\n"
5038 "nop\n"
5039 "nop\n"
5040 "nop\n"
5041 "nop\n"
5042 "nop\n"
5043 "movl rax,0x24\n"
5044 "ret\n");
5045}
5046
5047ASSEMBLER_TEST_GENERATE(TestAlign0, assembler) {
5048 __ Align(4, 0);
5049 __ movq(RAX, Immediate(assembler->CodeSize())); // Return code size.
5050 __ ret();
5051}
5052
5053ASSEMBLER_TEST_RUN(TestAlign0, test) {
5054 typedef int (*TestAlign0)();
5055 int res = reinterpret_cast<TestAlign0>(test->payload_start())();
5056 EXPECT_EQ(0, res); // 0 bytes emitted.
5057 EXPECT_DISASSEMBLY(
5058 "movl rax,0\n"
5059 "ret\n");
5060}
5061
5062ASSEMBLER_TEST_GENERATE(TestAlign1, assembler) {
5063 __ nop(1);
5064 __ Align(4, 0);
5065 __ movq(RAX, Immediate(assembler->CodeSize())); // Return code size.
5066 __ ret();
5067}
5068
5069ASSEMBLER_TEST_RUN(TestAlign1, test) {
5070 typedef int (*TestAlign1)();
5071 int res = reinterpret_cast<TestAlign1>(test->payload_start())();
5072 EXPECT_EQ(4, res); // 4 bytes emitted.
5073 EXPECT_DISASSEMBLY(
5074 "nop\n"
5075 "nop\n"
5076 "movl rax,4\n"
5077 "ret\n");
5078}
5079
5080ASSEMBLER_TEST_GENERATE(TestAlign1Offset1, assembler) {
5081 __ nop(1);
5082 __ Align(4, 1);
5083 __ movq(RAX, Immediate(assembler->CodeSize())); // Return code size.
5084 __ ret();
5085}
5086
5087ASSEMBLER_TEST_RUN(TestAlign1Offset1, test) {
5088 typedef int (*TestAlign1Offset1)();
5089 int res = reinterpret_cast<TestAlign1Offset1>(test->payload_start())();
5090 EXPECT_EQ(3, res); // 3 bytes emitted.
5091 EXPECT_DISASSEMBLY(
5092 "nop\n"
5093 "nop\n"
5094 "movl rax,3\n"
5095 "ret\n");
5096}
5097
5098ASSEMBLER_TEST_GENERATE(TestAlignLarge, assembler) {
5099 __ nop(1);
5100 __ Align(16, 0);
5101 __ movq(RAX, Immediate(assembler->CodeSize())); // Return code size.
5102 __ ret();
5103}
5104
5105ASSEMBLER_TEST_RUN(TestAlignLarge, test) {
5106 typedef int (*TestAlignLarge)();
5107 int res = reinterpret_cast<TestAlignLarge>(test->payload_start())();
5108 EXPECT_EQ(16, res); // 16 bytes emitted.
5109 EXPECT_DISASSEMBLY(
5110 "nop\n"
5111 "nop\n"
5112 "nop\n"
5113 "movl rax,0x10\n"
5114 "ret\n");
5115}
5116
5117ASSEMBLER_TEST_GENERATE(TestAdds, assembler) {
5118 __ movq(RAX, Immediate(4));
5119 __ pushq(RAX);
5120 __ addq(Address(RSP, 0), Immediate(5));
5121 // TOS: 9
5122 __ addq(Address(RSP, 0), Immediate(-2));
5123 // TOS: 7
5124 __ movq(RCX, Immediate(3));
5125 __ addq(Address(RSP, 0), RCX);
5126 // TOS: 10
5127 __ movq(RAX, Immediate(10));
5128 __ addq(RAX, Address(RSP, 0));
5129 // RAX: 20
5130 __ popq(RCX);
5131 __ ret();
5132}
5133
5134ASSEMBLER_TEST_RUN(TestAdds, test) {
5135 typedef int (*TestAdds)();
5136 int res = reinterpret_cast<TestAdds>(test->entry())();
5137 EXPECT_EQ(20, res);
5138 EXPECT_DISASSEMBLY(
5139 "movl rax,4\n"
5140 "push rax\n"
5141 "addq [rsp],5\n"
5142 "addq [rsp],-2\n"
5143 "movl rcx,3\n"
5144 "addq [rsp],rcx\n"
5145 "movl rax,0xa\n"
5146 "addq rax,[rsp]\n"
5147 "pop rcx\n"
5148 "ret\n");
5149}
5150
5151ASSEMBLER_TEST_GENERATE(TestNot, assembler) {
5152 __ movq(RAX, Immediate(0xFFFFFFFF00000000));
5153 __ notq(RAX);
5154 __ ret();
5155}
5156
5157ASSEMBLER_TEST_RUN(TestNot, test) {
5158 typedef int (*TestNot)();
5159 unsigned int res = reinterpret_cast<TestNot>(test->entry())();
5160 EXPECT_EQ(0xFFFFFFFF, res);
5161 EXPECT_DISASSEMBLY(
5162 "movq rax,0x................\n"
5163 "notq rax\n"
5164 "ret\n");
5165}
5166
5167ASSEMBLER_TEST_GENERATE(TestNotInt32, assembler) {
5168 __ movq(RAX, Immediate(0x0));
5169 __ notl(RAX);
5170 __ ret();
5171}
5172
5173ASSEMBLER_TEST_RUN(TestNotInt32, test) {
5174 typedef int (*TestNot)();
5175 unsigned int res = reinterpret_cast<TestNot>(test->entry())();
5176 EXPECT_EQ(0xFFFFFFFF, res);
5177 EXPECT_DISASSEMBLY(
5178 "movl rax,0\n"
5179 "notl rax\n"
5180 "ret\n");
5181}
5182
5183ASSEMBLER_TEST_GENERATE(XorpdZeroing, assembler) {
5184 __ pushq(RAX);
5185 __ movsd(Address(RSP, 0), XMM0);
5186 __ xorpd(XMM0, Address(RSP, 0));
5187 __ popq(RAX);
5188 __ ret();
5189}
5190
5191ASSEMBLER_TEST_RUN(XorpdZeroing, test) {
5192 typedef double (*XorpdZeroingCode)(double d);
5193 double res = reinterpret_cast<XorpdZeroingCode>(test->entry())(12.56e3);
5194 EXPECT_FLOAT_EQ(0.0, res, 0.0001);
5195 EXPECT_DISASSEMBLY(
5196 "push rax\n"
5197 "movsd [rsp],xmm0\n"
5198 "xorpd xmm0,[rsp]\n"
5199 "pop rax\n"
5200 "ret\n");
5201}
5202
5203ASSEMBLER_TEST_GENERATE(XorpdZeroing2, assembler) {
5204 Label done;
5205 __ xorpd(XMM15, XMM15);
5206 __ xorpd(XMM0, XMM0);
5207 __ xorpd(XMM0, XMM15);
5208 __ comisd(XMM0, XMM15);
5209 __ j(ZERO, &done);
5210 __ int3();
5211 __ Bind(&done);
5212 __ ret();
5213}
5214
5215ASSEMBLER_TEST_RUN(XorpdZeroing2, test) {
5216 typedef double (*XorpdZeroing2Code)(double d);
5217 double res = reinterpret_cast<XorpdZeroing2Code>(test->entry())(12.56e3);
5218 EXPECT_FLOAT_EQ(0.0, res, 0.0001);
5219 EXPECT_DISASSEMBLY(
5220 "xorpd xmm15,xmm15\n"
5221 "xorpd xmm0,xmm0\n"
5222 "xorpd xmm0,xmm15\n"
5223 "comisd xmm0,xmm15\n"
5224 "jz 0x................\n"
5225 "int3\n"
5226 "ret\n");
5227}
5228
5229ASSEMBLER_TEST_GENERATE(Pxor, assembler) {
5230 __ pxor(XMM0, XMM0);
5231 __ ret();
5232}
5233
5234ASSEMBLER_TEST_RUN(Pxor, test) {
5235 typedef double (*PxorCode)(double d);
5236 double res = reinterpret_cast<PxorCode>(test->entry())(12.3456e3);
5237 EXPECT_FLOAT_EQ(0.0, res, 0.0);
5238 EXPECT_DISASSEMBLY(
5239 "pxor xmm0,xmm0\n"
5240 "ret\n");
5241}
5242
5243ASSEMBLER_TEST_GENERATE(SquareRootDouble, assembler) {
5244 __ sqrtsd(XMM0, XMM0);
5245 __ ret();
5246}
5247
5248ASSEMBLER_TEST_RUN(SquareRootDouble, test) {
5249 typedef double (*SquareRootDoubleCode)(double d);
5250 const double kDoubleConst = .7;
5251 double res =
5252 reinterpret_cast<SquareRootDoubleCode>(test->entry())(kDoubleConst);
5253 EXPECT_FLOAT_EQ(sqrt(kDoubleConst), res, 0.0001);
5254 EXPECT_DISASSEMBLY(
5255 "sqrtsd xmm0,xmm0\n"
5256 "ret\n");
5257}
5258
5259// Called from assembler_test.cc.
5260ASSEMBLER_TEST_GENERATE(StoreIntoObject, assembler) {
5261 __ pushq(CODE_REG);
5262 __ pushq(THR);
5263 __ movq(THR, CallingConventions::kArg3Reg);
5264 __ StoreIntoObject(CallingConventions::kArg2Reg,
5265 FieldAddress(CallingConventions::kArg2Reg,
5266 GrowableObjectArray::data_offset()),
5267 CallingConventions::kArg1Reg);
5268 __ popq(THR);
5269 __ popq(CODE_REG);
5270 __ ret();
5271}
5272
5273ASSEMBLER_TEST_GENERATE(DoubleFPUStackMoves, assembler) {
5274 int64_t l = bit_cast<int64_t, double>(1024.67);
5275 __ movq(RAX, Immediate(l));
5276 __ pushq(RAX);
5277 __ fldl(Address(RSP, 0));
5278 __ movq(Address(RSP, 0), Immediate(0));
5279 __ fstpl(Address(RSP, 0));
5280 __ popq(RAX);
5281 __ ret();
5282}
5283
5284ASSEMBLER_TEST_RUN(DoubleFPUStackMoves, test) {
5285 typedef int64_t (*DoubleFPUStackMovesCode)();
5286 int64_t res = reinterpret_cast<DoubleFPUStackMovesCode>(test->entry())();
5287 EXPECT_FLOAT_EQ(1024.67, (bit_cast<double, int64_t>(res)), 0.001);
5288 EXPECT_DISASSEMBLY(
5289 "movq rax,0x................\n"
5290 "push rax\n"
5291 "fld_d [rsp]\n"
5292 "movq [rsp],0\n"
5293 "fstp_d [rsp]\n"
5294 "pop rax\n"
5295 "ret\n");
5296}
5297
5298ASSEMBLER_TEST_GENERATE(Sine, assembler) {
5299 __ pushq(RAX);
5300 __ movsd(Address(RSP, 0), XMM0);
5301 __ fldl(Address(RSP, 0));
5302 __ fsin();
5303 __ fstpl(Address(RSP, 0));
5304 __ movsd(XMM0, Address(RSP, 0));
5305 __ popq(RAX);
5306 __ ret();
5307}
5308
5309ASSEMBLER_TEST_RUN(Sine, test) {
5310 typedef double (*SineCode)(double d);
5311 const double kDoubleConst = 0.7;
5312 double res = reinterpret_cast<SineCode>(test->entry())(kDoubleConst);
5313 EXPECT_FLOAT_EQ(sin(kDoubleConst), res, 0.0001);
5314 EXPECT_DISASSEMBLY(
5315 "push rax\n"
5316 "movsd [rsp],xmm0\n"
5317 "fld_d [rsp]\n"
5318 "fsin\n"
5319 "fstp_d [rsp]\n"
5320 "movsd xmm0,[rsp]\n"
5321 "pop rax\n"
5322 "ret\n");
5323}
5324
5325ASSEMBLER_TEST_GENERATE(Cosine, assembler) {
5326 __ pushq(RAX);
5327 __ movsd(Address(RSP, 0), XMM0);
5328 __ fldl(Address(RSP, 0));
5329 __ fcos();
5330 __ fstpl(Address(RSP, 0));
5331 __ movsd(XMM0, Address(RSP, 0));
5332 __ popq(RAX);
5333 __ ret();
5334}
5335
5336ASSEMBLER_TEST_RUN(Cosine, test) {
5337 typedef double (*CosineCode)(double f);
5338 const double kDoubleConst = 0.7;
5339 double res = reinterpret_cast<CosineCode>(test->entry())(kDoubleConst);
5340 EXPECT_FLOAT_EQ(cos(kDoubleConst), res, 0.0001);
5341 EXPECT_DISASSEMBLY(
5342 "push rax\n"
5343 "movsd [rsp],xmm0\n"
5344 "fld_d [rsp]\n"
5345 "fcos\n"
5346 "fstp_d [rsp]\n"
5347 "movsd xmm0,[rsp]\n"
5348 "pop rax\n"
5349 "ret\n");
5350}
5351
5352ASSEMBLER_TEST_GENERATE(IntToDoubleConversion, assembler) {
5353 __ movq(RDX, Immediate(6));
5354 __ cvtsi2sdq(XMM0, RDX);
5355 __ ret();
5356}
5357
5358ASSEMBLER_TEST_RUN(IntToDoubleConversion, test) {
5359 typedef double (*IntToDoubleConversionCode)();
5360 double res = reinterpret_cast<IntToDoubleConversionCode>(test->entry())();
5361 EXPECT_FLOAT_EQ(6.0, res, 0.001);
5362 EXPECT_DISASSEMBLY(
5363 "movl rdx,6\n"
5364 "cvtsi2sd xmm0,rdx\n"
5365 "ret\n");
5366}
5367
5368ASSEMBLER_TEST_GENERATE(DoubleToDoubleTrunc, assembler) {
5369 __ roundsd(XMM0, XMM0, Assembler::kRoundToZero);
5370 __ ret();
5371}
5372
5373ASSEMBLER_TEST_RUN(DoubleToDoubleTrunc, test) {
5374 typedef double (*DoubleToDoubleTruncCode)(double d);
5375 double res = reinterpret_cast<DoubleToDoubleTruncCode>(test->entry())(12.3);
5376 EXPECT_EQ(12.0, res);
5377 res = reinterpret_cast<DoubleToDoubleTruncCode>(test->entry())(12.8);
5378 EXPECT_EQ(12.0, res);
5379 res = reinterpret_cast<DoubleToDoubleTruncCode>(test->entry())(-12.3);
5380 EXPECT_EQ(-12.0, res);
5381 res = reinterpret_cast<DoubleToDoubleTruncCode>(test->entry())(-12.8);
5382 EXPECT_EQ(-12.0, res);
5383 EXPECT_DISASSEMBLY(
5384 "roundsd rax, rax, 3\n"
5385 "ret\n");
5386}
5387
5388ASSEMBLER_TEST_GENERATE(DoubleAbs, assembler) {
5389 EnterTestFrame(assembler);
5390#if defined(HOST_OS_WINDOWS)
5391 // First argument is code object, second argument is thread. MSVC passes
5392 // third argument in XMM2.
5393 __ DoubleAbs(XMM0, XMM2);
5394#else
5395 // SysV ABI allocates integral and double registers for arguments
5396 // independently.
5397 __ DoubleAbs(XMM0, XMM0);
5398#endif
5399 LeaveTestFrame(assembler);
5400 __ ret();
5401}
5402
5403ASSEMBLER_TEST_RUN(DoubleAbs, test) {
5404 double val = -12.45;
5405 double res = test->InvokeWithCodeAndThread<double, double>(val);
5406 EXPECT_FLOAT_EQ(-val, res, 0.001);
5407 val = 12.45;
5408 res = test->InvokeWithCodeAndThread<double, double>(val);
5409 EXPECT_FLOAT_EQ(val, res, 0.001);
5410 EXPECT_DISASSEMBLY_NOT_WINDOWS(
5411 "push rbp\n"
5412 "movq rbp,rsp\n"
5413 "push r12\n"
5414 "push pp\n"
5415 "push thr\n"
5416 "movq r12,[rdi+0x8]\n"
5417 "movq thr,rsi\n"
5418 "movq pp,[r12+0x27]\n"
5419 "movq r11,[thr+0x...]\n"
5420 "andpd xmm0,[r11]\n"
5421 "pop thr\n"
5422 "pop pp\n"
5423 "pop r12\n"
5424 "movq rsp,rbp\n"
5425 "pop rbp\n"
5426 "ret\n");
5427}
5428
5429ASSEMBLER_TEST_GENERATE(ExtractSignBits, assembler) {
5430 __ movmskpd(RAX, XMM0);
5431 __ andq(RAX, Immediate(0x1));
5432 __ ret();
5433}
5434
5435ASSEMBLER_TEST_RUN(ExtractSignBits, test) {
5436 typedef int (*ExtractSignBits)(double d);
5437 int res = reinterpret_cast<ExtractSignBits>(test->entry())(1.0);
5438 EXPECT_EQ(0, res);
5439 res = reinterpret_cast<ExtractSignBits>(test->entry())(-1.0);
5440 EXPECT_EQ(1, res);
5441 res = reinterpret_cast<ExtractSignBits>(test->entry())(-0.0);
5442 EXPECT_EQ(1, res);
5443 EXPECT_DISASSEMBLY(
5444 "movmskpd rax,xmm0\n"
5445 "andl rax,1\n"
5446 "ret\n");
5447}
5448
5449ASSEMBLER_TEST_GENERATE(TestSetCC, assembler) {
5450 __ movq(RAX, Immediate(0xFFFFFFFF));
5451 __ cmpq(RAX, RAX);
5452 __ setcc(NOT_EQUAL, AL);
5453 __ ret();
5454}
5455
5456ASSEMBLER_TEST_RUN(TestSetCC, test) {
5457 typedef uword (*TestSetCC)();
5458 uword res = reinterpret_cast<TestSetCC>(test->entry())();
5459 EXPECT_EQ(0xFFFFFF00, res);
5460 EXPECT_DISASSEMBLY(
5461 "movl rax,0x........\n"
5462 "cmpq rax,rax\n"
5463 "setnzl rax\n"
5464 "ret\n");
5465}
5466
5467ASSEMBLER_TEST_GENERATE(TestSetCC2, assembler) {
5468 __ pushq(RBX);
5469 __ movq(RBX, Immediate(0xFFFFFFFF));
5470 __ cmpq(RBX, RBX);
5471 __ setcc(EQUAL, BH);
5472 __ movq(RAX, RBX);
5473 __ popq(RBX);
5474 __ ret();
5475}
5476
5477ASSEMBLER_TEST_RUN(TestSetCC2, test) {
5478 typedef uword (*TestSetCC)();
5479 uword res = reinterpret_cast<TestSetCC>(test->entry())();
5480 EXPECT_EQ(0xFFFF01FF, res);
5481 EXPECT_DISASSEMBLY(
5482 "push rbx\n"
5483 "movl rbx,0x........\n"
5484 "cmpq rbx,rbx\n"
5485 "setzl rdi\n"
5486 "movq rax,rbx\n"
5487 "pop rbx\n"
5488 "ret\n");
5489}
5490
5491ASSEMBLER_TEST_GENERATE(TestSetCC3, assembler) {
5492 __ pushq(R10);
5493 __ movq(R10, Immediate(0xFFFFFFFF));
5494 __ cmpq(R10, R10);
5495 __ setcc(NOT_EQUAL, R10B);
5496 __ movq(RAX, R10);
5497 __ popq(R10);
5498 __ ret();
5499}
5500
5501ASSEMBLER_TEST_RUN(TestSetCC3, test) {
5502 typedef uword (*TestSetCC)();
5503 uword res = reinterpret_cast<TestSetCC>(test->entry())();
5504 EXPECT_EQ(0xFFFFFF00, res);
5505 EXPECT_DISASSEMBLY(
5506 "push r10\n"
5507 "movl r10,0x........\n"
5508 "cmpq r10,r10\n"
5509 "setnzl r10\n"
5510 "movq rax,r10\n"
5511 "pop r10\n"
5512 "ret\n");
5513}
5514
5515ASSEMBLER_TEST_GENERATE(TestSetCC4, assembler) {
5516 __ pushq(RSI);
5517 __ movq(RSI, Immediate(0xFFFFFFFF));
5518 __ cmpq(RSI, RSI);
5519 __ setcc(EQUAL, SIL);
5520 __ movq(RAX, RSI);
5521 __ popq(RSI);
5522 __ ret();
5523}
5524
5525ASSEMBLER_TEST_RUN(TestSetCC4, test) {
5526 typedef uword (*TestSetCC)();
5527 uword res = reinterpret_cast<TestSetCC>(test->entry())();
5528 EXPECT_EQ(0xFFFFFF01, res);
5529 EXPECT_DISASSEMBLY(
5530 "push rsi\n"
5531 "movl rsi,0x........\n"
5532 "cmpq rsi,rsi\n"
5533 "setzl rsi\n"
5534 "movq rax,rsi\n"
5535 "pop rsi\n"
5536 "ret\n");
5537}
5538
5539ASSEMBLER_TEST_GENERATE(TestRepMovsBytes, assembler) {
5540 __ pushq(RSI);
5541 __ pushq(RDI);
5542 __ pushq(CallingConventions::kArg1Reg); // from.
5543 __ pushq(CallingConventions::kArg2Reg); // to.
5544 __ pushq(CallingConventions::kArg3Reg); // count.
5545 __ movq(RSI, Address(RSP, 2 * target::kWordSize)); // from.
5546 __ movq(RDI, Address(RSP, 1 * target::kWordSize)); // to.
5547 __ movq(RCX, Address(RSP, 0 * target::kWordSize)); // count.
5548 __ rep_movsb();
5549 // Remove saved arguments.
5550 __ popq(RAX);
5551 __ popq(RAX);
5552 __ popq(RAX);
5553 __ popq(RDI);
5554 __ popq(RSI);
5555 __ ret();
5556}
5557
5558ASSEMBLER_TEST_RUN(TestRepMovsBytes, test) {
5559 const char* from = "0123456789x";
5560 char* to = new char[11]{0};
5561 to[10] = 'y';
5562 typedef void (*TestRepMovsBytes)(const char* from, char* to, int count);
5563 reinterpret_cast<TestRepMovsBytes>(test->entry())(from, to, 10);
5564 EXPECT_EQ(to[0], '0');
5565 for (int i = 0; i < 10; i++) {
5566 EXPECT_EQ(from[i], to[i]);
5567 }
5568 EXPECT_EQ(to[10], 'y');
5569 delete[] to;
5570 EXPECT_DISASSEMBLY_NOT_WINDOWS(
5571 "push rsi\n"
5572 "push rdi\n"
5573 "push rdi\n"
5574 "push rsi\n"
5575 "push rdx\n"
5576 "movq rsi,[rsp+0x10]\n"
5577 "movq rdi,[rsp+0x8]\n"
5578 "movq rcx,[rsp]\n"
5579 "rep movsb\n"
5580 "pop rax\n"
5581 "pop rax\n"
5582 "pop rax\n"
5583 "pop rdi\n"
5584 "pop rsi\n"
5585 "ret\n");
5586}
5587
5588ASSEMBLER_TEST_GENERATE(TestRepMovsWords, assembler) {
5589 __ pushq(RSI);
5590 __ pushq(RDI);
5591 __ pushq(CallingConventions::kArg1Reg); // from.
5592 __ pushq(CallingConventions::kArg2Reg); // to.
5593 __ pushq(CallingConventions::kArg3Reg); // count.
5594 __ movq(RSI, Address(RSP, 2 * target::kWordSize)); // from.
5595 __ movq(RDI, Address(RSP, 1 * target::kWordSize)); // to.
5596 __ movq(RCX, Address(RSP, 0 * target::kWordSize)); // count.
5597 __ rep_movsw();
5598 // Remove saved arguments.
5599 __ popq(RAX);
5600 __ popq(RAX);
5601 __ popq(RAX);
5602 __ popq(RDI);
5603 __ popq(RSI);
5604 __ ret();
5605}
5606
5607ASSEMBLER_TEST_RUN(TestRepMovsWords, test) {
5608 const uint16_t from[11] = {0x0123, 0x1234, 0x2345, 0x3456, 0x4567, 0x5678,
5609 0x6789, 0x789A, 0x89AB, 0x9ABC, 0xABCD};
5610 uint16_t* to = new uint16_t[11]{0};
5611 to[10] = 0xFEFE;
5612 typedef void (*TestRepMovsWords)(const uint16_t* from, uint16_t* to,
5613 int count);
5614 reinterpret_cast<TestRepMovsWords>(test->entry())(from, to, 10);
5615 EXPECT_EQ(to[0], 0x0123u);
5616 for (int i = 0; i < 10; i++) {
5617 EXPECT_EQ(from[i], to[i]);
5618 }
5619 EXPECT_EQ(to[10], 0xFEFEu);
5620 delete[] to;
5621 EXPECT_DISASSEMBLY_NOT_WINDOWS(
5622 "push rsi\n"
5623 "push rdi\n"
5624 "push rdi\n"
5625 "push rsi\n"
5626 "push rdx\n"
5627 "movq rsi,[rsp+0x10]\n"
5628 "movq rdi,[rsp+0x8]\n"
5629 "movq rcx,[rsp]\n"
5630 "rep movsw\n"
5631 "pop rax\n"
5632 "pop rax\n"
5633 "pop rax\n"
5634 "pop rdi\n"
5635 "pop rsi\n"
5636 "ret\n");
5637}
5638
5639ASSEMBLER_TEST_GENERATE(TestRepMovsDwords, assembler) {
5640 __ pushq(RSI);
5641 __ pushq(RDI);
5642 __ pushq(CallingConventions::kArg1Reg); // from.
5643 __ pushq(CallingConventions::kArg2Reg); // to.
5644 __ pushq(CallingConventions::kArg3Reg); // count.
5645 __ movq(RSI, Address(RSP, 2 * target::kWordSize)); // from.
5646 __ movq(RDI, Address(RSP, 1 * target::kWordSize)); // to.
5647 __ movq(RCX, Address(RSP, 0 * target::kWordSize)); // count.
5648 __ rep_movsl();
5649 // Remove saved arguments.
5650 __ popq(RAX);
5651 __ popq(RAX);
5652 __ popq(RAX);
5653 __ popq(RDI);
5654 __ popq(RSI);
5655 __ ret();
5656}
5657
5658ASSEMBLER_TEST_RUN(TestRepMovsDwords, test) {
5659 const uint32_t from[11] = {0x01234567, 0x12345678, 0x23456789, 0x3456789A,
5660 0x456789AB, 0x56789ABC, 0x6789ABCD, 0x789ABCDE,
5661 0x89ABCDEF, 0x9ABCDEF0, 0xABCDEF01};
5662 uint32_t* to = new uint32_t[11]{0};
5663 to[10] = 0xFEFEFEFE;
5664 typedef void (*TestRepMovsDwords)(const uint32_t* from, uint32_t* to,
5665 int count);
5666 reinterpret_cast<TestRepMovsDwords>(test->entry())(from, to, 10);
5667 EXPECT_EQ(to[0], 0x01234567u);
5668 for (int i = 0; i < 10; i++) {
5669 EXPECT_EQ(from[i], to[i]);
5670 }
5671 EXPECT_EQ(to[10], 0xFEFEFEFEu);
5672 delete[] to;
5673 EXPECT_DISASSEMBLY_NOT_WINDOWS(
5674 "push rsi\n"
5675 "push rdi\n"
5676 "push rdi\n"
5677 "push rsi\n"
5678 "push rdx\n"
5679 "movq rsi,[rsp+0x10]\n"
5680 "movq rdi,[rsp+0x8]\n"
5681 "movq rcx,[rsp]\n"
5682 "rep movsl\n"
5683 "pop rax\n"
5684 "pop rax\n"
5685 "pop rax\n"
5686 "pop rdi\n"
5687 "pop rsi\n"
5688 "ret\n");
5689}
5690
5691ASSEMBLER_TEST_GENERATE(TestRepMovsQwords, assembler) {
5692 __ pushq(RSI);
5693 __ pushq(RDI);
5694 __ pushq(CallingConventions::kArg1Reg); // from.
5695 __ pushq(CallingConventions::kArg2Reg); // to.
5696 __ pushq(CallingConventions::kArg3Reg); // count.
5697 __ movq(RSI, Address(RSP, 2 * target::kWordSize)); // from.
5698 __ movq(RDI, Address(RSP, 1 * target::kWordSize)); // to.
5699 __ movq(RCX, Address(RSP, 0 * target::kWordSize)); // count.
5700 __ rep_movsq();
5701 // Remove saved arguments.
5702 __ popq(RAX);
5703 __ popq(RAX);
5704 __ popq(RAX);
5705 __ popq(RDI);
5706 __ popq(RSI);
5707 __ ret();
5708}
5709
5710ASSEMBLER_TEST_RUN(TestRepMovsQwords, test) {
5711 const uint64_t from[11] = {
5712 0x0123456789ABCDEF, 0x123456789ABCDEF0, 0x23456789ABCDEF01,
5713 0x3456789ABCDEF012, 0x456789ABCDEF0123, 0x56789ABCDEF01234,
5714 0x6789ABCDEF012345, 0x789ABCDEF0123456, 0x89ABCDEF01234567,
5715 0x9ABCDEF012345678, 0xABCDEF0123456789};
5716 uint64_t* to = new uint64_t[11]{0};
5717 to[10] = 0xFEFEFEFEFEFEFEFE;
5718 typedef void (*TestRepMovsQwords)(const uint64_t* from, uint64_t* to,
5719 int count);
5720 reinterpret_cast<TestRepMovsQwords>(test->entry())(from, to, 10);
5721 EXPECT_EQ(to[0], 0x0123456789ABCDEFu);
5722 for (int i = 0; i < 10; i++) {
5723 EXPECT_EQ(from[i], to[i]);
5724 }
5725 EXPECT_EQ(to[10], 0xFEFEFEFEFEFEFEFEu);
5726 delete[] to;
5727 EXPECT_DISASSEMBLY_NOT_WINDOWS(
5728 "push rsi\n"
5729 "push rdi\n"
5730 "push rdi\n"
5731 "push rsi\n"
5732 "push rdx\n"
5733 "movq rsi,[rsp+0x10]\n"
5734 "movq rdi,[rsp+0x8]\n"
5735 "movq rcx,[rsp]\n"
5736 "rep movsq\n"
5737 "pop rax\n"
5738 "pop rax\n"
5739 "pop rax\n"
5740 "pop rdi\n"
5741 "pop rsi\n"
5742 "ret\n");
5743}
5744
5745ASSEMBLER_TEST_GENERATE(ConditionalMovesCompare, assembler) {
5746 __ cmpq(CallingConventions::kArg1Reg, CallingConventions::kArg2Reg);
5747 __ movq(RDX, Immediate(1)); // Greater equal.
5748 __ movq(RCX, Immediate(-1)); // Less
5749 __ cmovlq(RAX, RCX);
5750 __ cmovgeq(RAX, RDX);
5751 __ ret();
5752}
5753
5754ASSEMBLER_TEST_RUN(ConditionalMovesCompare, test) {
5755 typedef int (*ConditionalMovesCompareCode)(int i, int j);
5756 int res = reinterpret_cast<ConditionalMovesCompareCode>(test->entry())(10, 5);
5757 EXPECT_EQ(1, res); // Greater equal.
5758 res = reinterpret_cast<ConditionalMovesCompareCode>(test->entry())(5, 5);
5759 EXPECT_EQ(1, res); // Greater equal.
5760 res = reinterpret_cast<ConditionalMovesCompareCode>(test->entry())(2, 5);
5761 EXPECT_EQ(-1, res); // Less.
5762 EXPECT_DISASSEMBLY_ENDS_WITH(
5763 "movl rdx,1\n"
5764 "movq rcx,-1\n"
5765 "cmovlq rax,rcx\n"
5766 "cmovgeq rax,rdx\n"
5767 "ret\n");
5768}
5769
5770ASSEMBLER_TEST_GENERATE(BitTestTest, assembler) {
5771 __ movq(RAX, Immediate(4));
5772 __ movq(R11, Immediate(2));
5773 __ btq(RAX, R11);
5774 Label ok;
5775 __ j(CARRY, &ok);
5776 __ int3();
5777 __ Bind(&ok);
5778 __ movq(RAX, Immediate(1));
5779 __ ret();
5780}
5781
5782ASSEMBLER_TEST_RUN(BitTestTest, test) {
5783 typedef int (*BitTest)();
5784 EXPECT_EQ(1, reinterpret_cast<BitTest>(test->entry())());
5785 EXPECT_DISASSEMBLY(
5786 "movl rax,4\n"
5787 "movl r11,2\n"
5788 "btq rax,r11\n"
5789 "jc 0x................\n"
5790 "int3\n"
5791 "movl rax,1\n"
5792 "ret\n");
5793}
5794
5795ASSEMBLER_TEST_GENERATE(BitTestImmediate, assembler) {
5796 __ movq(R11, Immediate(32));
5797 __ btq(R11, 5);
5798 Label ok;
5799 __ j(CARRY, &ok);
5800 __ int3();
5801 __ Bind(&ok);
5802 __ movq(RAX, Immediate(1));
5803 __ ret();
5804}
5805
5806ASSEMBLER_TEST_RUN(BitTestImmediate, test) {
5807 typedef int (*BitTestImmediate)();
5808 EXPECT_EQ(1, reinterpret_cast<BitTestImmediate>(test->entry())());
5809 EXPECT_DISASSEMBLY(
5810 "movl r11,0x20\n"
5811 "bt r11,5\n"
5812 "jc 0x................\n"
5813 "int3\n"
5814 "movl rax,1\n"
5815 "ret\n");
5816}
5817
5818// Return 1 if equal, 0 if not equal.
5819ASSEMBLER_TEST_GENERATE(ConditionalMovesEqual, assembler) {
5820 __ movq(RDX, CallingConventions::kArg1Reg);
5821 __ xorq(RAX, RAX);
5822 __ movq(RCX, Immediate(1));
5823 __ cmpq(RDX, Immediate(785));
5824 __ cmoveq(RAX, RCX);
5825 __ ret();
5826}
5827
5828ASSEMBLER_TEST_RUN(ConditionalMovesEqual, test) {
5829 typedef int (*ConditionalMovesEqualCode)(int i);
5830 int res = reinterpret_cast<ConditionalMovesEqualCode>(test->entry())(785);
5831 EXPECT_EQ(1, res);
5832 res = reinterpret_cast<ConditionalMovesEqualCode>(test->entry())(-12);
5833 EXPECT_EQ(0, res);
5834 EXPECT_DISASSEMBLY_ENDS_WITH(
5835 "xorq rax,rax\n"
5836 "movl rcx,1\n"
5837 "cmpq rdx,0x...\n"
5838 "cmovzq rax,rcx\n"
5839 "ret\n");
5840}
5841
5842// Return 1 if overflow, 0 if no overflow.
5843ASSEMBLER_TEST_GENERATE(ConditionalMovesNoOverflow, assembler) {
5844 __ movq(RDX, CallingConventions::kArg1Reg);
5845 __ addq(RDX, CallingConventions::kArg2Reg);
5846 __ movq(RAX, Immediate(1));
5847 __ movq(RCX, Immediate(0));
5848 __ cmovnoq(RAX, RCX);
5849 __ ret();
5850}
5851
5852ASSEMBLER_TEST_RUN(ConditionalMovesNoOverflow, test) {
5853 typedef int (*ConditionalMovesNoOverflowCode)(int64_t i, int64_t j);
5854 int res = reinterpret_cast<ConditionalMovesNoOverflowCode>(test->entry())(
5855 0x7fffffffffffffff, 2);
5856 EXPECT_EQ(1, res);
5857 res = reinterpret_cast<ConditionalMovesNoOverflowCode>(test->entry())(1, 1);
5858 EXPECT_EQ(0, res);
5859 EXPECT_DISASSEMBLY_NOT_WINDOWS(
5860 "movq rdx,rdi\n"
5861 "addq rdx,rsi\n"
5862 "movl rax,1\n"
5863 "movl rcx,0\n"
5864 "cmovnoq rax,rcx\n"
5865 "ret\n");
5866}
5867
5868ASSEMBLER_TEST_GENERATE(ImmediateMacros, assembler) {
5869 const intptr_t kBillion = 1000 * 1000 * 1000;
5870 {
5871 __ LoadImmediate(RAX, Immediate(42));
5872 __ MulImmediate(RAX, Immediate(kBillion));
5873 Label ok;
5874 __ CompareImmediate(RAX, Immediate(42 * kBillion));
5875 __ j(EQUAL, &ok);
5876 __ int3(); // MulImmediate 64 bit.
5877 __ Bind(&ok);
5878 }
5879 {
5880 __ LoadImmediate(RAX, Immediate(42));
5881 __ MulImmediate(RAX, Immediate(kBillion), Assembler::k32Bit);
5882 Label ok;
5883 __ CompareImmediate(RAX, Immediate((42 * kBillion) & 0xffffffffll));
5884 __ j(EQUAL, &ok);
5885 __ int3(); // MulImmediate 32 bit.
5886 __ Bind(&ok);
5887 }
5888 {
5889 __ LoadImmediate(RAX, Immediate(kBillion));
5890 __ AddImmediate(RAX, Immediate(41 * kBillion));
5891 Label ok;
5892 __ CompareImmediate(RAX, Immediate(42 * kBillion));
5893 __ j(EQUAL, &ok);
5894 __ int3(); // AddImmediate 64 bit.
5895 __ Bind(&ok);
5896 }
5897 {
5898 __ LoadImmediate(RAX, Immediate(kBillion));
5899 __ AddImmediate(RAX, Immediate(kBillion), Assembler::k32Bit);
5900 __ AddImmediate(RAX, Immediate(kBillion), Assembler::k32Bit);
5901 __ AddImmediate(RAX, Immediate(kBillion), Assembler::k32Bit);
5902 Label ok;
5903 __ CompareImmediate(RAX, Immediate((4 * kBillion) & 0xffffffffll));
5904 __ j(EQUAL, &ok);
5905 __ int3(); // AddImmediate 32 bit.
5906 __ Bind(&ok);
5907 }
5908 {
5909 __ LoadImmediate(RAX, Immediate(kBillion));
5910 __ AddImmediate(RAX, Immediate(static_cast<int32_t>(3 * kBillion)),
5911 Assembler::k32Bit);
5912 __ AddImmediate(RAX, Immediate(kBillion), Assembler::k32Bit);
5913 __ AddImmediate(RAX, Immediate(-kBillion), Assembler::k32Bit);
5914 Label ok;
5915 __ CompareImmediate(RAX, Immediate((4 * kBillion) & 0xffffffffll));
5916 __ j(EQUAL, &ok);
5917 __ int3(); // AddImmediate negative 32 bit.
5918 __ Bind(&ok);
5919 }
5920 {
5921 __ LoadImmediate(RAX, Immediate(kBillion));
5922 __ SubImmediate(RAX, Immediate(43 * kBillion));
5923 Label ok;
5924 __ CompareImmediate(RAX, Immediate(-42 * kBillion));
5925 __ j(EQUAL, &ok);
5926 __ int3(); // AddImmediate negative 64 bit.
5927 __ Bind(&ok);
5928 }
5929 {
5930 __ LoadImmediate(RAX, Immediate(-kBillion));
5931 __ SubImmediate(RAX, Immediate(kBillion), Assembler::k32Bit);
5932 __ SubImmediate(RAX, Immediate(kBillion), Assembler::k32Bit);
5933 __ SubImmediate(RAX, Immediate(kBillion), Assembler::k32Bit);
5934 Label ok;
5935 __ CompareImmediate(RAX, Immediate((-4 * kBillion) & 0xffffffffll));
5936 __ j(EQUAL, &ok);
5937 __ int3(); // SubImmediate 32 bit.
5938 __ Bind(&ok);
5939 }
5940 {
5941 __ LoadImmediate(RAX, Immediate(kBillion));
5942 __ SubImmediate(RAX, Immediate((-3 * kBillion) & 0xffffffffll),
5943 Assembler::k32Bit);
5944 __ SubImmediate(RAX, Immediate(kBillion), Assembler::k32Bit);
5945 __ SubImmediate(RAX, Immediate(-kBillion), Assembler::k32Bit);
5946 Label ok;
5947 __ CompareImmediate(RAX, Immediate((4 * kBillion) & 0xffffffffll));
5948 __ j(EQUAL, &ok);
5949 __ int3(); // SubImmediate 32 bit.
5950 __ Bind(&ok);
5951 }
5952 __ LoadImmediate(RAX, Immediate(42));
5953 __ ret();
5954}
5955
5956ASSEMBLER_TEST_RUN(ImmediateMacros, test) {
5957 typedef int (*ImmediateMacrosCode)();
5958 int res = reinterpret_cast<ImmediateMacrosCode>(test->entry())();
5959 EXPECT_EQ(42, res);
5960 EXPECT_DISASSEMBLY(
5961 "movl rax,0x2a\n"
5962 "imulq rax,rax,0x........\n"
5963 "movq r11,0x................\n"
5964 "cmpq rax,r11\n"
5965 "jz 0x................\n"
5966 "int3\n"
5967 "movl rax,0x2a\n"
5968 "imull rax,rax,0x........\n"
5969 "movl r11,0x........\n"
5970 "cmpq rax,r11\n"
5971 "jz 0x................\n"
5972 "int3\n"
5973 "movl rax,0x........\n"
5974 "movq r11,0x................\n"
5975 "addq rax,r11\n"
5976 "movq r11,0x................\n"
5977 "cmpq rax,r11\n"
5978 "jz 0x................\n"
5979 "int3\n"
5980 "movl rax,0x........\n"
5981 "addl rax,0x........\n"
5982 "addl rax,0x........\n"
5983 "addl rax,0x........\n"
5984 "movl r11,0x........\n"
5985 "cmpq rax,r11\n"
5986 "jz 0x................\n"
5987 "int3\n"
5988 "movl rax,0x........\n"
5989 "subl rax,0x........\n"
5990 "addl rax,0x........\n"
5991 "subl rax,0x........\n"
5992 "movl r11,0x........\n"
5993 "cmpq rax,r11\n"
5994 "jz 0x................\n"
5995 "int3\n"
5996 "movl rax,0x........\n"
5997 "movq r11,0x................\n"
5998 "subq rax,r11\n"
5999 "movq r11,0x................\n"
6000 "cmpq rax,r11\n"
6001 "jz 0x................\n"
6002 "int3\n"
6003 "movq rax,-0x........\n"
6004 "subl rax,0x........\n"
6005 "subl rax,0x........\n"
6006 "subl rax,0x........\n"
6007 "cmpq rax,0x........\n"
6008 "jz 0x................\n"
6009 "int3\n"
6010 "movl rax,0x........\n"
6011 "subl rax,0x........\n"
6012 "subl rax,0x........\n"
6013 "addl rax,0x........\n"
6014 "movl r11,0x........\n"
6015 "cmpq rax,r11\n"
6016 "jz 0x................\n"
6017 "int3\n"
6018 "movl rax,0x2a\n"
6019 "ret\n");
6020}
6021
6022// clang-format off
6023#define ALU_TEST(NAME, WIDTH, INTRO, LHS, RHS, OUTRO) \
6024 ASSEMBLER_TEST_GENERATE(NAME, assembler) { \
6025 int32_t input1_w = static_cast<int32_t>(0x87654321); \
6026 int32_t input1_l = input1_w; \
6027 int64_t input1_q = 0xfedcba987654321ll; \
6028 input1_##WIDTH += input1_w * 0 + input1_l * 0 + input1_q * 0; \
6029 int32_t input2_w = static_cast<int32_t>(0x12345678); \
6030 int32_t input2_l = input2_w; \
6031 int64_t input2_q = 0xabcdef912345678ll; \
6032 input2_##WIDTH += input2_w * 0 + input2_l * 0 + input2_q * 0; \
6033 \
6034 __ movq(RAX, Immediate(input1_##WIDTH)); \
6035 __ movq(RCX, Immediate(input2_##WIDTH)); \
6036 \
6037 INTRO; \
6038 \
6039 __ and##WIDTH(LHS, RHS); \
6040 __ or##WIDTH(RHS, LHS); \
6041 __ xor##WIDTH(LHS, RHS); \
6042 __ add##WIDTH(RHS, LHS); \
6043 __ cmp##WIDTH(LHS, RHS); \
6044 __ adc##WIDTH(LHS, RHS); \
6045 __ sub##WIDTH(RHS, LHS); \
6046 __ sbb##WIDTH(LHS, RHS); \
6047 \
6048 OUTRO; \
6049 /* A sort of movx(RAX, RAX) */ \
6050 __ xorq(RCX, RCX); \
6051 __ add##WIDTH(RCX, RAX); \
6052 __ andq(RAX, RCX); \
6053 __ ret(); \
6054 } \
6055 \
6056 ASSEMBLER_TEST_RUN(NAME, test) { \
6057 typedef uint64_t (*NAME)(); \
6058 uint64_t expectation_q = 0xaed1be942649381ll; \
6059 uint32_t expectation_l = expectation_q; \
6060 uint16_t expectation_w = expectation_l; \
6061 uint64_t expectation = expectation_##WIDTH | expectation_w; \
6062 EXPECT_EQ(expectation, reinterpret_cast<NAME>(test->entry())()); \
6063 }
6064// clang-format on
6065
6066ALU_TEST(RegRegW, w, , RAX, RCX, )
6067ALU_TEST(RegAddrW1, w, __ pushq(RAX), Address(RSP, 0), RCX, __ popq(RAX))
6068ALU_TEST(RegAddrW2, w, __ pushq(RCX), RAX, Address(RSP, 0), __ popq(RCX))
6069ALU_TEST(RegRegL, l, , RAX, RCX, )
6070ALU_TEST(RegAddrL1, l, __ pushq(RAX), Address(RSP, 0), RCX, __ popq(RAX))
6071ALU_TEST(RegAddrL2, l, __ pushq(RCX), RAX, Address(RSP, 0), __ popq(RCX))
6072ALU_TEST(RegRegQ, q, , RAX, RCX, )
6073ALU_TEST(RegAddrQ1, q, __ pushq(RAX), Address(RSP, 0), RCX, __ popq(RAX))
6074ALU_TEST(RegAddrQ2, q, __ pushq(RCX), RAX, Address(RSP, 0), __ popq(RCX))
6075
6076#define IMMEDIATE_TEST(NAME, REG, MASK, INTRO, VALUE, OUTRO) \
6077 ASSEMBLER_TEST_GENERATE(NAME, assembler) { \
6078 __ movl(REG, Immediate(static_cast<int32_t>(0x87654321))); \
6079 \
6080 INTRO; \
6081 \
6082 __ andl(VALUE, Immediate(static_cast<int32_t>(0xa8df51d3 & MASK))); \
6083 __ orl(VALUE, Immediate(0x1582a681 & MASK)); \
6084 __ xorl(VALUE, Immediate(static_cast<int32_t>(0xa5a5a5a5 & MASK))); \
6085 __ addl(VALUE, Immediate(0x7fffffff & MASK)); \
6086 __ cmpl(VALUE, Immediate(0x40404040 & MASK)); \
6087 __ adcl(VALUE, Immediate(0x6eeeeeee & MASK)); \
6088 __ subl(VALUE, Immediate(0x7eeeeeee & MASK)); \
6089 __ sbbl(VALUE, Immediate(0x6fffffff & MASK)); \
6090 \
6091 OUTRO; \
6092 \
6093 __ movl(RAX, REG); \
6094 __ ret(); \
6095 } \
6096 \
6097 ASSEMBLER_TEST_RUN(NAME, test) { \
6098 typedef uint64_t (*NAME)(); \
6099 unsigned expectation = MASK < 0x100 ? 0x24 : 0x30624223; \
6100 EXPECT_EQ(expectation, reinterpret_cast<NAME>(test->entry())()); \
6101 }
6102
6103// RAX-based instructions have different encodings so we test both RAX and RCX.
6104// If the immediate can be encoded as one byte there is also a different
6105// encoding, so test that too.
6106IMMEDIATE_TEST(RegImmRAX, RAX, 0xffffffff, , RAX, )
6107IMMEDIATE_TEST(RegImmRCX, RCX, 0xffffffff, , RCX, )
6108IMMEDIATE_TEST(RegImmRAXByte, RAX, 0x7f, , RAX, )
6109IMMEDIATE_TEST(RegImmRCXByte, RCX, 0x7f, , RCX, )
6110IMMEDIATE_TEST(AddrImmRAX,
6111 RAX,
6112 0xffffffff,
6113 __ pushq(RAX),
6114 Address(RSP, 0),
6115 __ popq(RAX))
6116IMMEDIATE_TEST(AddrImmRAXByte,
6117 RAX,
6118 0x7f,
6119 __ pushq(RAX),
6120 Address(RSP, 0),
6121 __ popq(RAX))
6122
6123} // namespace compiler
6124} // namespace dart
6125
6126#endif // defined TARGET_ARCH_X64
6127