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