| OLD | NEW |
| (Empty) | |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. |
| 4 |
| 5 #include "vm/globals.h" |
| 6 #if defined(TARGET_ARCH_X64) |
| 7 |
| 8 #include "vm/assembler.h" |
| 9 #include "vm/os.h" |
| 10 #include "vm/unit_test.h" |
| 11 #include "vm/virtual_memory.h" |
| 12 |
| 13 namespace dart { |
| 14 |
| 15 #define __ assembler-> |
| 16 |
| 17 |
| 18 ASSEMBLER_TEST_GENERATE(ReadArgument, assembler) { |
| 19 __ pushq(RDI); // First argument is passed in register rdi. |
| 20 __ movq(RAX, Address(RSP, 0)); |
| 21 __ popq(RDX); |
| 22 __ ret(); |
| 23 } |
| 24 |
| 25 |
| 26 ASSEMBLER_TEST_RUN(ReadArgument, entry) { |
| 27 typedef int64_t (*ReadArgumentCode)(int64_t n); |
| 28 ReadArgumentCode id = reinterpret_cast<ReadArgumentCode>(entry); |
| 29 EXPECT_EQ(42, id(42)); |
| 30 EXPECT_EQ(87, id(87)); |
| 31 static const int64_t kLargeConstant = 0x1234567812345678LL; |
| 32 EXPECT_EQ(kLargeConstant, id(kLargeConstant)); |
| 33 } |
| 34 |
| 35 |
| 36 ASSEMBLER_TEST_GENERATE(AddressingModes, assembler) { |
| 37 __ movq(RAX, Address(RSP, 0)); |
| 38 __ movq(RAX, Address(RBP, 0)); |
| 39 __ movq(RAX, Address(RAX, 0)); |
| 40 __ movq(RAX, Address(R10, 0)); |
| 41 __ movq(R10, Address(RAX, 0)); |
| 42 |
| 43 __ movq(RAX, Address(RSP, kWordSize)); |
| 44 __ movq(RAX, Address(RBP, kWordSize)); |
| 45 __ movq(RAX, Address(RAX, kWordSize)); |
| 46 __ movq(RAX, Address(R10, kWordSize)); |
| 47 |
| 48 __ movq(RAX, Address(RSP, -kWordSize)); |
| 49 __ movq(RAX, Address(RBP, -kWordSize)); |
| 50 __ movq(RAX, Address(RAX, -kWordSize)); |
| 51 __ movq(RAX, Address(R10, -kWordSize)); |
| 52 |
| 53 __ movq(RAX, Address(RSP, 256 * kWordSize)); |
| 54 __ movq(RAX, Address(RBP, 256 * kWordSize)); |
| 55 __ movq(RAX, Address(RAX, 256 * kWordSize)); |
| 56 __ movq(RAX, Address(R10, 256 * kWordSize)); |
| 57 |
| 58 __ movq(RAX, Address(RSP, -256 * kWordSize)); |
| 59 __ movq(RAX, Address(RBP, -256 * kWordSize)); |
| 60 __ movq(RAX, Address(RAX, -256 * kWordSize)); |
| 61 __ movq(RAX, Address(R10, -256 * kWordSize)); |
| 62 |
| 63 __ movq(RAX, Address(RAX, TIMES_1)); |
| 64 __ movq(RAX, Address(RAX, TIMES_2)); |
| 65 __ movq(RAX, Address(RAX, TIMES_4)); |
| 66 __ movq(RAX, Address(RAX, TIMES_8)); |
| 67 |
| 68 __ movq(RAX, Address(RBP, TIMES_2)); |
| 69 __ movq(RAX, Address(RAX, TIMES_2)); |
| 70 __ movq(RAX, Address(R10, TIMES_2)); |
| 71 |
| 72 __ movq(RAX, Address(RBP, TIMES_2, kWordSize)); |
| 73 __ movq(RAX, Address(RAX, TIMES_2, kWordSize)); |
| 74 __ movq(RAX, Address(R10, TIMES_2, kWordSize)); |
| 75 |
| 76 __ movq(RAX, Address(RBP, TIMES_2, 256 * kWordSize)); |
| 77 __ movq(RAX, Address(RAX, TIMES_2, 256 * kWordSize)); |
| 78 __ movq(RAX, Address(R10, TIMES_2, 256 * kWordSize)); |
| 79 |
| 80 __ movq(RAX, Address(RAX, RBP, TIMES_2, 0)); |
| 81 __ movq(RAX, Address(RAX, RAX, TIMES_2, 0)); |
| 82 __ movq(RAX, Address(RAX, R10, TIMES_2, 0)); |
| 83 |
| 84 __ movq(RAX, Address(RBP, RBP, TIMES_2, 0)); |
| 85 __ movq(RAX, Address(RBP, RAX, TIMES_2, 0)); |
| 86 __ movq(RAX, Address(RBP, R10, TIMES_2, 0)); |
| 87 |
| 88 __ movq(RAX, Address(RSP, RBP, TIMES_2, 0)); |
| 89 __ movq(RAX, Address(RSP, RAX, TIMES_2, 0)); |
| 90 __ movq(RAX, Address(RSP, R10, TIMES_2, 0)); |
| 91 |
| 92 __ movq(RAX, Address(R10, RBP, TIMES_2, 0)); |
| 93 __ movq(RAX, Address(R10, RAX, TIMES_2, 0)); |
| 94 __ movq(RAX, Address(R10, R10, TIMES_2, 0)); |
| 95 |
| 96 __ movq(RAX, Address(RAX, RBP, TIMES_2, kWordSize)); |
| 97 __ movq(RAX, Address(RAX, RAX, TIMES_2, kWordSize)); |
| 98 __ movq(RAX, Address(RAX, R10, TIMES_2, kWordSize)); |
| 99 |
| 100 __ movq(RAX, Address(RBP, RBP, TIMES_2, kWordSize)); |
| 101 __ movq(RAX, Address(RBP, RAX, TIMES_2, kWordSize)); |
| 102 __ movq(RAX, Address(RBP, R10, TIMES_2, kWordSize)); |
| 103 |
| 104 __ movq(RAX, Address(RSP, RBP, TIMES_2, kWordSize)); |
| 105 __ movq(RAX, Address(RSP, RAX, TIMES_2, kWordSize)); |
| 106 __ movq(RAX, Address(RSP, R10, TIMES_2, kWordSize)); |
| 107 |
| 108 __ movq(RAX, Address(R10, RBP, TIMES_2, kWordSize)); |
| 109 __ movq(RAX, Address(R10, RAX, TIMES_2, kWordSize)); |
| 110 __ movq(RAX, Address(R10, R10, TIMES_2, kWordSize)); |
| 111 |
| 112 __ movq(RAX, Address(RAX, RBP, TIMES_2, 256 * kWordSize)); |
| 113 __ movq(RAX, Address(RAX, RAX, TIMES_2, 256 * kWordSize)); |
| 114 __ movq(RAX, Address(RAX, R10, TIMES_2, 256 * kWordSize)); |
| 115 |
| 116 __ movq(RAX, Address(RBP, RBP, TIMES_2, 256 * kWordSize)); |
| 117 __ movq(RAX, Address(RBP, RAX, TIMES_2, 256 * kWordSize)); |
| 118 __ movq(RAX, Address(RBP, R10, TIMES_2, 256 * kWordSize)); |
| 119 |
| 120 __ movq(RAX, Address(RSP, RBP, TIMES_2, 256 * kWordSize)); |
| 121 __ movq(RAX, Address(RSP, RAX, TIMES_2, 256 * kWordSize)); |
| 122 __ movq(RAX, Address(RSP, R10, TIMES_2, 256 * kWordSize)); |
| 123 |
| 124 __ movq(RAX, Address(R10, RBP, TIMES_2, 256 * kWordSize)); |
| 125 __ movq(RAX, Address(R10, RAX, TIMES_2, 256 * kWordSize)); |
| 126 __ movq(RAX, Address(R10, R10, TIMES_2, 256 * kWordSize)); |
| 127 } |
| 128 |
| 129 |
| 130 ASSEMBLER_TEST_RUN(AddressingModes, entry) { |
| 131 // Avoid running the code since it is constructed to lead to crashes. |
| 132 } |
| 133 |
| 134 |
| 135 ASSEMBLER_TEST_GENERATE(JumpAroundCrash, assembler) { |
| 136 Label done; |
| 137 // Make sure all the condition jumps work. |
| 138 for (Condition condition = OVERFLOW; |
| 139 condition <= GREATER; |
| 140 condition = static_cast<Condition>(condition + 1)) { |
| 141 __ j(condition, &done); |
| 142 } |
| 143 // This isn't strictly necessary, but we do an unconditional |
| 144 // jump around the crashing code anyway. |
| 145 __ jmp(&done); |
| 146 |
| 147 // Be sure to skip this crashing code. |
| 148 __ movq(RAX, Immediate(0)); |
| 149 __ movq(Address(RAX, 0), RAX); |
| 150 |
| 151 __ Bind(&done); |
| 152 __ ret(); |
| 153 } |
| 154 |
| 155 |
| 156 ASSEMBLER_TEST_RUN(JumpAroundCrash, entry) { |
| 157 Instr* instr = Instr::At(entry); |
| 158 EXPECT(!instr->IsBreakPoint()); |
| 159 typedef void (*JumpAroundCrashCode)(); |
| 160 reinterpret_cast<JumpAroundCrashCode>(entry)(); |
| 161 } |
| 162 |
| 163 |
| 164 ASSEMBLER_TEST_GENERATE(SimpleLoop, assembler) { |
| 165 __ movq(RAX, Immediate(0)); |
| 166 __ movq(RCX, Immediate(0)); |
| 167 Label loop; |
| 168 __ Bind(&loop); |
| 169 __ addq(RAX, Immediate(2)); |
| 170 __ incq(RCX); |
| 171 __ cmpq(RCX, Immediate(87)); |
| 172 __ j(LESS, &loop); |
| 173 __ ret(); |
| 174 } |
| 175 |
| 176 |
| 177 ASSEMBLER_TEST_RUN(SimpleLoop, entry) { |
| 178 typedef int (*SimpleLoopCode)(); |
| 179 EXPECT_EQ(2 * 87, reinterpret_cast<SimpleLoopCode>(entry)()); |
| 180 } |
| 181 |
| 182 |
| 183 ASSEMBLER_TEST_GENERATE(Increment, assembler) { |
| 184 __ movq(RAX, Immediate(0)); |
| 185 __ pushq(RAX); |
| 186 __ incl(Address(RSP, 0)); |
| 187 __ incq(Address(RSP, 0)); |
| 188 __ movq(RCX, Address(RSP, 0)); |
| 189 __ incq(RCX); |
| 190 __ popq(RAX); |
| 191 __ movq(RAX, RCX); |
| 192 __ ret(); |
| 193 } |
| 194 |
| 195 |
| 196 ASSEMBLER_TEST_RUN(Increment, entry) { |
| 197 typedef int (*IncrementCode)(); |
| 198 EXPECT_EQ(3, reinterpret_cast<IncrementCode>(entry)()); |
| 199 } |
| 200 |
| 201 |
| 202 ASSEMBLER_TEST_GENERATE(IncrementLong, assembler) { |
| 203 __ movq(RAX, Immediate(0xffffffff)); |
| 204 __ pushq(RAX); |
| 205 __ incq(Address(RSP, 0)); |
| 206 __ movq(RCX, Address(RSP, 0)); |
| 207 __ incq(RCX); |
| 208 __ popq(RAX); |
| 209 __ movq(RAX, RCX); |
| 210 __ ret(); |
| 211 } |
| 212 |
| 213 |
| 214 ASSEMBLER_TEST_RUN(IncrementLong, entry) { |
| 215 typedef int64_t (*IncrementCodeLong)(); |
| 216 EXPECT_EQ(0x100000001, reinterpret_cast<IncrementCodeLong>(entry)()); |
| 217 } |
| 218 |
| 219 |
| 220 ASSEMBLER_TEST_GENERATE(Decrement, assembler) { |
| 221 __ movq(RAX, Immediate(3)); |
| 222 __ pushq(RAX); |
| 223 __ decl(Address(RSP, 0)); |
| 224 __ decq(Address(RSP, 0)); |
| 225 __ movq(RCX, Address(RSP, 0)); |
| 226 __ decq(RCX); |
| 227 __ popq(RAX); |
| 228 __ movq(RAX, RCX); |
| 229 __ ret(); |
| 230 } |
| 231 |
| 232 |
| 233 ASSEMBLER_TEST_RUN(Decrement, entry) { |
| 234 typedef int (*DecrementCode)(); |
| 235 EXPECT_EQ(0, reinterpret_cast<DecrementCode>(entry)()); |
| 236 } |
| 237 |
| 238 |
| 239 ASSEMBLER_TEST_GENERATE(DecrementLong, assembler) { |
| 240 __ movq(RAX, Immediate(0x100000001)); |
| 241 __ pushq(RAX); |
| 242 __ decq(Address(RSP, 0)); |
| 243 __ movq(RCX, Address(RSP, 0)); |
| 244 __ decq(RCX); |
| 245 __ popq(RAX); |
| 246 __ movq(RAX, RCX); |
| 247 __ ret(); |
| 248 } |
| 249 |
| 250 |
| 251 ASSEMBLER_TEST_RUN(DecrementLong, entry) { |
| 252 typedef int64_t (*DecrementCodeLong)(); |
| 253 EXPECT_EQ(0xffffffff, reinterpret_cast<DecrementCodeLong>(entry)()); |
| 254 } |
| 255 |
| 256 |
| 257 ASSEMBLER_TEST_GENERATE(SignedMultiply, assembler) { |
| 258 __ movl(RAX, Immediate(2)); |
| 259 __ movl(RCX, Immediate(4)); |
| 260 __ imull(RAX, RCX); |
| 261 __ imull(RAX, Immediate(1000)); |
| 262 __ ret(); |
| 263 } |
| 264 |
| 265 |
| 266 ASSEMBLER_TEST_RUN(SignedMultiply, entry) { |
| 267 typedef int (*SignedMultiply)(); |
| 268 EXPECT_EQ(8000, reinterpret_cast<SignedMultiply>(entry)()); |
| 269 } |
| 270 |
| 271 |
| 272 static const int64_t kLargeConstant = 0x1234567887654321; |
| 273 static const int64_t kAnotherLargeConstant = 987654321987654321LL; |
| 274 static const int64_t kProductLargeConstants = 0x5bbb29a7f52fbbd1; |
| 275 |
| 276 |
| 277 ASSEMBLER_TEST_GENERATE(SignedMultiplyLong, assembler) { |
| 278 __ movq(RAX, Immediate(kLargeConstant)); |
| 279 __ movq(RCX, Immediate(kAnotherLargeConstant)); |
| 280 __ imulq(RAX, RCX); |
| 281 __ ret(); |
| 282 } |
| 283 |
| 284 |
| 285 ASSEMBLER_TEST_RUN(SignedMultiplyLong, entry) { |
| 286 typedef int64_t (*SignedMultiplyLong)(); |
| 287 EXPECT_EQ(kProductLargeConstants, |
| 288 reinterpret_cast<SignedMultiplyLong>(entry)()); |
| 289 } |
| 290 |
| 291 |
| 292 ASSEMBLER_TEST_GENERATE(OverflowSignedMultiply, assembler) { |
| 293 __ movl(RDX, Immediate(0)); |
| 294 __ movl(RAX, Immediate(0x0fffffff)); |
| 295 __ movl(RCX, Immediate(0x0fffffff)); |
| 296 __ imull(RAX, RCX); |
| 297 __ imull(RAX, RDX); |
| 298 __ ret(); |
| 299 } |
| 300 |
| 301 |
| 302 ASSEMBLER_TEST_RUN(OverflowSignedMultiply, entry) { |
| 303 typedef int (*OverflowSignedMultiply)(); |
| 304 EXPECT_EQ(0, reinterpret_cast<OverflowSignedMultiply>(entry)()); |
| 305 } |
| 306 |
| 307 |
| 308 ASSEMBLER_TEST_GENERATE(SignedMultiply1, assembler) { |
| 309 __ movl(RDX, Immediate(2)); |
| 310 __ movl(RCX, Immediate(4)); |
| 311 __ imull(RDX, RCX); |
| 312 __ imull(RDX, Immediate(1000)); |
| 313 __ movl(RAX, RDX); |
| 314 __ ret(); |
| 315 } |
| 316 |
| 317 |
| 318 ASSEMBLER_TEST_RUN(SignedMultiply1, entry) { |
| 319 typedef int (*SignedMultiply1)(); |
| 320 EXPECT_EQ(8000, reinterpret_cast<SignedMultiply1>(entry)()); |
| 321 } |
| 322 |
| 323 |
| 324 ASSEMBLER_TEST_GENERATE(SignedDivide, assembler) { |
| 325 __ movl(RAX, Immediate(-87)); |
| 326 __ movl(RDX, Immediate(123)); |
| 327 __ cdq(); |
| 328 __ movl(RCX, Immediate(42)); |
| 329 __ idivl(RCX); |
| 330 __ ret(); |
| 331 } |
| 332 |
| 333 |
| 334 ASSEMBLER_TEST_RUN(SignedDivide, entry) { |
| 335 typedef int32_t (*SignedDivide)(); |
| 336 EXPECT_EQ(-87 / 42, reinterpret_cast<SignedDivide>(entry)()); |
| 337 } |
| 338 |
| 339 |
| 340 ASSEMBLER_TEST_GENERATE(SignedDivideLong, assembler) { |
| 341 __ movq(RAX, Immediate(kLargeConstant)); |
| 342 __ movq(RDX, Immediate(123)); |
| 343 __ cqo(); // Clear RDX. |
| 344 __ movq(RCX, Immediate(42)); |
| 345 __ idivq(RCX); |
| 346 __ ret(); |
| 347 } |
| 348 |
| 349 |
| 350 ASSEMBLER_TEST_RUN(SignedDivideLong, entry) { |
| 351 typedef int64_t (*SignedDivideLong)(); |
| 352 EXPECT_EQ(kLargeConstant / 42, reinterpret_cast<SignedDivideLong>(entry)()); |
| 353 } |
| 354 |
| 355 |
| 356 ASSEMBLER_TEST_GENERATE(Negate, assembler) { |
| 357 __ movl(RCX, Immediate(42)); |
| 358 __ negl(RCX); |
| 359 __ movl(RAX, RCX); |
| 360 __ ret(); |
| 361 } |
| 362 |
| 363 |
| 364 ASSEMBLER_TEST_RUN(Negate, entry) { |
| 365 typedef int (*Negate)(); |
| 366 EXPECT_EQ(-42, reinterpret_cast<Negate>(entry)()); |
| 367 } |
| 368 |
| 369 |
| 370 ASSEMBLER_TEST_GENERATE(MoveExtend, assembler) { |
| 371 __ movq(RDX, Immediate(0xffff)); |
| 372 __ movzxb(RAX, RDX); // RAX = 0xff |
| 373 __ movsxw(R8, RDX); // R8 = -1 |
| 374 __ movzxw(RCX, RDX); // RCX = 0xffff |
| 375 __ addq(R8, RCX); |
| 376 __ addq(RAX, R8); |
| 377 __ ret(); |
| 378 } |
| 379 |
| 380 |
| 381 ASSEMBLER_TEST_RUN(MoveExtend, entry) { |
| 382 typedef int (*MoveExtend)(); |
| 383 EXPECT_EQ(0xff - 1 + 0xffff, reinterpret_cast<MoveExtend>(entry)()); |
| 384 } |
| 385 |
| 386 |
| 387 ASSEMBLER_TEST_GENERATE(MoveExtendMemory, assembler) { |
| 388 __ movq(RDX, Immediate(0x123456781234ffff)); |
| 389 |
| 390 __ pushq(RDX); |
| 391 __ movzxb(RAX, Address(RSP, 0)); // RAX = 0xff |
| 392 __ movsxw(R8, Address(RSP, 0)); // R8 = -1 |
| 393 __ movzxw(RCX, Address(RSP, 0)); // RCX = 0xffff |
| 394 __ addq(RSP, Immediate(kWordSize)); |
| 395 |
| 396 __ addq(R8, RCX); |
| 397 __ addq(RAX, R8); |
| 398 __ ret(); |
| 399 } |
| 400 |
| 401 |
| 402 ASSEMBLER_TEST_RUN(MoveExtendMemory, entry) { |
| 403 typedef int (*MoveExtendMemory)(); |
| 404 EXPECT_EQ(0xff - 1 + 0xffff, reinterpret_cast<MoveExtendMemory>(entry)()); |
| 405 } |
| 406 |
| 407 |
| 408 ASSEMBLER_TEST_GENERATE(Bitwise, assembler) { |
| 409 __ movl(RCX, Immediate(42)); |
| 410 __ xorl(RCX, RCX); |
| 411 __ orl(RCX, Immediate(256)); |
| 412 __ movl(RAX, Immediate(4)); |
| 413 __ orl(RCX, RAX); |
| 414 __ movl(RAX, Immediate(0xfff0)); |
| 415 __ andl(RCX, RAX); |
| 416 __ movl(RAX, Immediate(1)); |
| 417 __ orl(RCX, RAX); |
| 418 __ movl(RAX, RCX); |
| 419 __ ret(); |
| 420 } |
| 421 |
| 422 |
| 423 ASSEMBLER_TEST_RUN(Bitwise, entry) { |
| 424 typedef int (*Bitwise)(); |
| 425 EXPECT_EQ(256 + 1, reinterpret_cast<Bitwise>(entry)()); |
| 426 } |
| 427 |
| 428 |
| 429 ASSEMBLER_TEST_GENERATE(LogicalOps, assembler) { |
| 430 Label donetest1; |
| 431 __ movl(RAX, Immediate(4)); |
| 432 __ andl(RAX, Immediate(2)); |
| 433 __ cmpl(RAX, Immediate(0)); |
| 434 __ j(EQUAL, &donetest1); |
| 435 // Be sure to skip this crashing code. |
| 436 __ movl(RAX, Immediate(0)); |
| 437 __ movl(Address(RAX, 0), RAX); |
| 438 __ Bind(&donetest1); |
| 439 |
| 440 Label donetest2; |
| 441 __ movl(RCX, Immediate(4)); |
| 442 __ andl(RCX, Immediate(4)); |
| 443 __ cmpl(RCX, Immediate(0)); |
| 444 __ j(NOT_EQUAL, &donetest2); |
| 445 // Be sure to skip this crashing code. |
| 446 __ movl(RAX, Immediate(0)); |
| 447 __ movl(Address(RAX, 0), RAX); |
| 448 __ Bind(&donetest2); |
| 449 |
| 450 Label donetest3; |
| 451 __ movl(RAX, Immediate(0)); |
| 452 __ orl(RAX, Immediate(0)); |
| 453 __ cmpl(RAX, Immediate(0)); |
| 454 __ j(EQUAL, &donetest3); |
| 455 // Be sure to skip this crashing code. |
| 456 __ movl(RAX, Immediate(0)); |
| 457 __ movl(Address(RAX, 0), RAX); |
| 458 __ Bind(&donetest3); |
| 459 |
| 460 Label donetest4; |
| 461 __ movl(RAX, Immediate(4)); |
| 462 __ orl(RAX, Immediate(0)); |
| 463 __ cmpl(RAX, Immediate(0)); |
| 464 __ j(NOT_EQUAL, &donetest4); |
| 465 // Be sure to skip this crashing code. |
| 466 __ movl(RAX, Immediate(0)); |
| 467 __ movl(Address(RAX, 0), RAX); |
| 468 __ Bind(&donetest4); |
| 469 |
| 470 Label donetest5; |
| 471 __ pushq(RAX); |
| 472 __ movl(RAX, Immediate(0xff)); |
| 473 __ movl(Address(RSP, 0), RAX); |
| 474 __ cmpl(Address(RSP, 0), Immediate(0xff)); |
| 475 __ j(EQUAL, &donetest5); |
| 476 // Be sure to skip this crashing code. |
| 477 __ movq(RAX, Immediate(0)); |
| 478 __ movq(Address(RAX, 0), RAX); |
| 479 __ Bind(&donetest5); |
| 480 __ popq(RAX); |
| 481 |
| 482 Label donetest6; |
| 483 __ movl(RAX, Immediate(1)); |
| 484 __ shll(RAX, Immediate(3)); |
| 485 __ cmpl(RAX, Immediate(8)); |
| 486 __ j(EQUAL, &donetest6); |
| 487 // Be sure to skip this crashing code. |
| 488 __ movl(RAX, Immediate(0)); |
| 489 __ movl(Address(RAX, 0), RAX); |
| 490 __ Bind(&donetest6); |
| 491 |
| 492 Label donetest7; |
| 493 __ movl(RAX, Immediate(2)); |
| 494 __ shrl(RAX, Immediate(1)); |
| 495 __ cmpl(RAX, Immediate(1)); |
| 496 __ j(EQUAL, &donetest7); |
| 497 // Be sure to skip this crashing code. |
| 498 __ movl(RAX, Immediate(0)); |
| 499 __ movl(Address(RAX, 0), RAX); |
| 500 __ Bind(&donetest7); |
| 501 |
| 502 Label donetest8; |
| 503 __ movl(RAX, Immediate(8)); |
| 504 __ shrl(RAX, Immediate(3)); |
| 505 __ cmpl(RAX, Immediate(1)); |
| 506 __ j(EQUAL, &donetest8); |
| 507 // Be sure to skip this crashing code. |
| 508 __ movl(RAX, Immediate(0)); |
| 509 __ movl(Address(RAX, 0), RAX); |
| 510 __ Bind(&donetest8); |
| 511 |
| 512 Label donetest9; |
| 513 __ movl(RAX, Immediate(1)); |
| 514 __ movl(RCX, Immediate(3)); |
| 515 __ shll(RAX, RCX); |
| 516 __ cmpl(RAX, Immediate(8)); |
| 517 __ j(EQUAL, &donetest9); |
| 518 // Be sure to skip this crashing code. |
| 519 __ movl(RAX, Immediate(0)); |
| 520 __ movl(Address(RAX, 0), RAX); |
| 521 __ Bind(&donetest9); |
| 522 |
| 523 Label donetest10; |
| 524 __ movl(RAX, Immediate(8)); |
| 525 __ movl(RCX, Immediate(3)); |
| 526 __ shrl(RAX, RCX); |
| 527 __ cmpl(RAX, Immediate(1)); |
| 528 __ j(EQUAL, &donetest10); |
| 529 // Be sure to skip this crashing code. |
| 530 __ movl(RAX, Immediate(0)); |
| 531 __ movl(Address(RAX, 0), RAX); |
| 532 __ Bind(&donetest10); |
| 533 |
| 534 Label donetest6a; |
| 535 __ movl(RAX, Immediate(1)); |
| 536 __ shlq(RAX, Immediate(3)); |
| 537 __ cmpl(RAX, Immediate(8)); |
| 538 __ j(EQUAL, &donetest6a); |
| 539 // Be sure to skip this crashing code. |
| 540 __ movl(RAX, Immediate(0)); |
| 541 __ movl(Address(RAX, 0), RAX); |
| 542 __ Bind(&donetest6a); |
| 543 |
| 544 Label donetest7a; |
| 545 __ movl(RAX, Immediate(2)); |
| 546 __ shrq(RAX, Immediate(1)); |
| 547 __ cmpl(RAX, Immediate(1)); |
| 548 __ j(EQUAL, &donetest7a); |
| 549 // Be sure to skip this crashing code. |
| 550 __ movl(RAX, Immediate(0)); |
| 551 __ movl(Address(RAX, 0), RAX); |
| 552 __ Bind(&donetest7a); |
| 553 |
| 554 Label donetest8a; |
| 555 __ movl(RAX, Immediate(8)); |
| 556 __ shrq(RAX, Immediate(3)); |
| 557 __ cmpl(RAX, Immediate(1)); |
| 558 __ j(EQUAL, &donetest8a); |
| 559 // Be sure to skip this crashing code. |
| 560 __ movl(RAX, Immediate(0)); |
| 561 __ movl(Address(RAX, 0), RAX); |
| 562 __ Bind(&donetest8a); |
| 563 |
| 564 Label donetest9a; |
| 565 __ movl(RAX, Immediate(1)); |
| 566 __ movl(RCX, Immediate(3)); |
| 567 __ shlq(RAX, RCX); |
| 568 __ cmpl(RAX, Immediate(8)); |
| 569 __ j(EQUAL, &donetest9a); |
| 570 // Be sure to skip this crashing code. |
| 571 __ movl(RAX, Immediate(0)); |
| 572 __ movl(Address(RAX, 0), RAX); |
| 573 __ Bind(&donetest9a); |
| 574 |
| 575 Label donetest10a; |
| 576 __ movl(RAX, Immediate(8)); |
| 577 __ movl(RCX, Immediate(3)); |
| 578 __ shrq(RAX, RCX); |
| 579 __ cmpl(RAX, Immediate(1)); |
| 580 __ j(EQUAL, &donetest10a); |
| 581 // Be sure to skip this crashing code. |
| 582 __ movl(RAX, Immediate(0)); |
| 583 __ movl(Address(RAX, 0), RAX); |
| 584 __ Bind(&donetest10a); |
| 585 |
| 586 Label donetest11a; |
| 587 __ movl(RAX, Immediate(1)); |
| 588 __ shlq(RAX, Immediate(31)); |
| 589 __ shrq(RAX, Immediate(3)); |
| 590 __ cmpq(RAX, Immediate(0x10000000)); |
| 591 __ j(EQUAL, &donetest11a); |
| 592 // Be sure to skip this crashing code. |
| 593 __ movl(RAX, Immediate(0)); |
| 594 __ movl(Address(RAX, 0), RAX); |
| 595 __ Bind(&donetest11a); |
| 596 |
| 597 Label donetest12a; |
| 598 __ movl(RAX, Immediate(1)); |
| 599 __ shlq(RAX, Immediate(31)); |
| 600 __ sarl(RAX, Immediate(3)); |
| 601 __ cmpl(RAX, Immediate(0xfffffffff0000000)); |
| 602 __ j(EQUAL, &donetest12a); |
| 603 // Be sure to skip this crashing code. |
| 604 __ movl(RAX, Immediate(0)); |
| 605 __ movl(Address(RAX, 0), RAX); |
| 606 __ Bind(&donetest12a); |
| 607 |
| 608 Label donetest13a; |
| 609 __ movl(RAX, Immediate(1)); |
| 610 __ movl(RCX, Immediate(3)); |
| 611 __ shlq(RAX, Immediate(31)); |
| 612 __ sarl(RAX, RCX); |
| 613 __ cmpl(RAX, Immediate(0xfffffffff0000000)); |
| 614 __ j(EQUAL, &donetest13a); |
| 615 // Be sure to skip this crashing code. |
| 616 __ movl(RAX, Immediate(0)); |
| 617 __ movl(Address(RAX, 0), RAX); |
| 618 __ Bind(&donetest13a); |
| 619 |
| 620 __ movl(RAX, Immediate(0)); |
| 621 __ ret(); |
| 622 } |
| 623 |
| 624 |
| 625 ASSEMBLER_TEST_RUN(LogicalOps, entry) { |
| 626 typedef int (*LogicalOpsCode)(); |
| 627 EXPECT_EQ(0, reinterpret_cast<LogicalOpsCode>(entry)()); |
| 628 } |
| 629 |
| 630 |
| 631 ASSEMBLER_TEST_GENERATE(LogicalTestL, assembler) { |
| 632 Label donetest1; |
| 633 __ movl(RAX, Immediate(4)); |
| 634 __ movl(RCX, Immediate(2)); |
| 635 __ testl(RAX, RCX); |
| 636 __ j(EQUAL, &donetest1); |
| 637 // Be sure to skip this crashing code. |
| 638 __ movl(RAX, Immediate(0)); |
| 639 __ movl(Address(RAX, 0), RAX); |
| 640 __ Bind(&donetest1); |
| 641 |
| 642 Label donetest2; |
| 643 __ movl(RDX, Immediate(4)); |
| 644 __ movl(RCX, Immediate(4)); |
| 645 __ testl(RDX, RCX); |
| 646 __ j(NOT_EQUAL, &donetest2); |
| 647 // Be sure to skip this crashing code. |
| 648 __ movl(RAX, Immediate(0)); |
| 649 __ movl(Address(RAX, 0), RAX); |
| 650 __ Bind(&donetest2); |
| 651 |
| 652 Label donetest3; |
| 653 __ movl(RAX, Immediate(0)); |
| 654 __ testl(RAX, Immediate(0)); |
| 655 __ j(EQUAL, &donetest3); |
| 656 // Be sure to skip this crashing code. |
| 657 __ movl(RAX, Immediate(0)); |
| 658 __ movl(Address(RAX, 0), RAX); |
| 659 __ Bind(&donetest3); |
| 660 |
| 661 Label donetest4; |
| 662 __ movl(RCX, Immediate(4)); |
| 663 __ testl(RCX, Immediate(4)); |
| 664 __ j(NOT_EQUAL, &donetest4); |
| 665 // Be sure to skip this crashing code. |
| 666 __ movl(RAX, Immediate(0)); |
| 667 __ movl(Address(RAX, 0), RAX); |
| 668 __ Bind(&donetest4); |
| 669 |
| 670 __ movl(RAX, Immediate(0)); |
| 671 __ ret(); |
| 672 } |
| 673 |
| 674 |
| 675 ASSEMBLER_TEST_RUN(LogicalTestL, entry) { |
| 676 typedef int (*LogicalTestCode)(); |
| 677 EXPECT_EQ(0, reinterpret_cast<LogicalTestCode>(entry)()); |
| 678 } |
| 679 |
| 680 |
| 681 ASSEMBLER_TEST_GENERATE(LogicalTestQ, assembler) { |
| 682 Label donetest1; |
| 683 __ movq(RAX, Immediate(4)); |
| 684 __ movq(RCX, Immediate(2)); |
| 685 __ testq(RAX, RCX); |
| 686 __ j(EQUAL, &donetest1); |
| 687 // Be sure to skip this crashing code. |
| 688 __ movq(RAX, Immediate(0)); |
| 689 __ movq(Address(RAX, 0), RAX); |
| 690 __ Bind(&donetest1); |
| 691 |
| 692 Label donetest2; |
| 693 __ movq(RDX, Immediate(4)); |
| 694 __ movq(RCX, Immediate(4)); |
| 695 __ testq(RDX, RCX); |
| 696 __ j(NOT_EQUAL, &donetest2); |
| 697 // Be sure to skip this crashing code. |
| 698 __ movq(RAX, Immediate(0)); |
| 699 __ movq(Address(RAX, 0), RAX); |
| 700 __ Bind(&donetest2); |
| 701 |
| 702 Label donetest3; |
| 703 __ movq(RAX, Immediate(0)); |
| 704 __ testq(RAX, Immediate(0)); |
| 705 __ j(EQUAL, &donetest3); |
| 706 // Be sure to skip this crashing code. |
| 707 __ movq(RAX, Immediate(0)); |
| 708 __ movq(Address(RAX, 0), RAX); |
| 709 __ Bind(&donetest3); |
| 710 |
| 711 Label donetest4; |
| 712 __ movq(RCX, Immediate(4)); |
| 713 __ testq(RCX, Immediate(4)); |
| 714 __ j(NOT_EQUAL, &donetest4); |
| 715 // Be sure to skip this crashing code. |
| 716 __ movq(RAX, Immediate(0)); |
| 717 __ movq(Address(RAX, 0), RAX); |
| 718 __ Bind(&donetest4); |
| 719 |
| 720 Label donetest5; |
| 721 __ movq(RCX, Immediate(0xff)); |
| 722 __ testq(RCX, Immediate(0xff)); |
| 723 __ j(NOT_EQUAL, &donetest5); |
| 724 // Be sure to skip this crashing code. |
| 725 __ movq(RAX, Immediate(0)); |
| 726 __ movq(Address(RAX, 0), RAX); |
| 727 __ Bind(&donetest5); |
| 728 |
| 729 Label donetest6; |
| 730 __ movq(RAX, Immediate(0xff)); |
| 731 __ testq(RAX, Immediate(0xff)); |
| 732 __ j(NOT_EQUAL, &donetest6); |
| 733 // Be sure to skip this crashing code. |
| 734 __ movq(RAX, Immediate(0)); |
| 735 __ movq(Address(RAX, 0), RAX); |
| 736 __ Bind(&donetest6); |
| 737 |
| 738 __ movq(RAX, Immediate(0)); |
| 739 __ ret(); |
| 740 } |
| 741 |
| 742 |
| 743 ASSEMBLER_TEST_RUN(LogicalTestQ, entry) { |
| 744 typedef int (*LogicalTestCode)(); |
| 745 EXPECT_EQ(0, reinterpret_cast<LogicalTestCode>(entry)()); |
| 746 } |
| 747 |
| 748 |
| 749 ASSEMBLER_TEST_GENERATE(CompareSwapEQ, assembler) { |
| 750 __ movq(RAX, Immediate(0)); |
| 751 __ pushq(RAX); |
| 752 __ movq(RAX, Immediate(4)); |
| 753 __ movq(RCX, Immediate(0)); |
| 754 __ movq(Address(RSP, 0), RAX); |
| 755 __ lock_cmpxchgq(Address(RSP, 0), RCX); |
| 756 __ popq(RAX); |
| 757 __ ret(); |
| 758 } |
| 759 |
| 760 |
| 761 ASSEMBLER_TEST_RUN(CompareSwapEQ, entry) { |
| 762 typedef int (*CompareSwapEQCode)(); |
| 763 EXPECT_EQ(0, reinterpret_cast<CompareSwapEQCode>(entry)()); |
| 764 } |
| 765 |
| 766 |
| 767 ASSEMBLER_TEST_GENERATE(CompareSwapNEQ, assembler) { |
| 768 __ movq(RAX, Immediate(0)); |
| 769 __ pushq(RAX); |
| 770 __ movq(RAX, Immediate(2)); |
| 771 __ movq(RCX, Immediate(4)); |
| 772 __ movq(Address(RSP, 0), RCX); |
| 773 __ lock_cmpxchgq(Address(RSP, 0), RCX); |
| 774 __ popq(RAX); |
| 775 __ ret(); |
| 776 } |
| 777 |
| 778 |
| 779 ASSEMBLER_TEST_RUN(CompareSwapNEQ, entry) { |
| 780 typedef int (*CompareSwapNEQCode)(); |
| 781 EXPECT_EQ(4, reinterpret_cast<CompareSwapNEQCode>(entry)()); |
| 782 } |
| 783 |
| 784 |
| 785 ASSEMBLER_TEST_GENERATE(Exchange, assembler) { |
| 786 __ movq(RAX, Immediate(kLargeConstant)); |
| 787 __ movq(RDX, Immediate(kAnotherLargeConstant)); |
| 788 __ xchgq(RAX, RDX); |
| 789 __ subq(RAX, RDX); |
| 790 __ ret(); |
| 791 } |
| 792 |
| 793 |
| 794 ASSEMBLER_TEST_RUN(Exchange, entry) { |
| 795 typedef int64_t (*Exchange)(); |
| 796 EXPECT_EQ(kAnotherLargeConstant - kLargeConstant, |
| 797 reinterpret_cast<Exchange>(entry)()); |
| 798 } |
| 799 |
| 800 |
| 801 ASSEMBLER_TEST_GENERATE(LargeConstant, assembler) { |
| 802 __ movq(RAX, Immediate(kLargeConstant)); |
| 803 __ ret(); |
| 804 } |
| 805 |
| 806 |
| 807 ASSEMBLER_TEST_RUN(LargeConstant, entry) { |
| 808 typedef int64_t (*LargeConstantCode)(); |
| 809 EXPECT_EQ(kLargeConstant, reinterpret_cast<LargeConstantCode>(entry)()); |
| 810 } |
| 811 |
| 812 |
| 813 static int ComputeStackSpaceReservation(int needed, int fixed) { |
| 814 static const int kFrameAlignment = OS::ActivationFrameAlignment(); |
| 815 return (kFrameAlignment > 0) |
| 816 ? Utils::RoundUp(needed + fixed, kFrameAlignment) - fixed |
| 817 : needed; |
| 818 } |
| 819 |
| 820 |
| 821 static int LeafReturn42() { |
| 822 return 42; |
| 823 } |
| 824 |
| 825 |
| 826 static int LeafReturnArgument(int x) { |
| 827 return x + 87; |
| 828 } |
| 829 |
| 830 |
| 831 ASSEMBLER_TEST_GENERATE(CallSimpleLeaf, assembler) { |
| 832 ExternalLabel call1("LeafReturn42", reinterpret_cast<uword>(LeafReturn42)); |
| 833 ExternalLabel call2("LeafReturnArgument", |
| 834 reinterpret_cast<uword>(LeafReturnArgument)); |
| 835 int space = ComputeStackSpaceReservation(0, 8); |
| 836 __ AddImmediate(RSP, Immediate(-space)); |
| 837 __ call(&call1); |
| 838 __ AddImmediate(RSP, Immediate(space)); |
| 839 space = ComputeStackSpaceReservation(0, 8); |
| 840 __ AddImmediate(RSP, Immediate(-space)); |
| 841 __ movl(RDI, RAX); |
| 842 __ call(&call2); |
| 843 __ AddImmediate(RSP, Immediate(space)); |
| 844 __ ret(); |
| 845 } |
| 846 |
| 847 |
| 848 ASSEMBLER_TEST_RUN(CallSimpleLeaf, entry) { |
| 849 typedef int (*CallSimpleLeafCode)(); |
| 850 EXPECT_EQ(42 + 87, reinterpret_cast<CallSimpleLeafCode>(entry)()); |
| 851 } |
| 852 |
| 853 |
| 854 ASSEMBLER_TEST_GENERATE(JumpSimpleLeaf, assembler) { |
| 855 ExternalLabel call1("LeafReturn42", reinterpret_cast<uword>(LeafReturn42)); |
| 856 Label L; |
| 857 int space = ComputeStackSpaceReservation(0, 8); |
| 858 __ AddImmediate(RSP, Immediate(-space)); |
| 859 __ call(&L); |
| 860 __ AddImmediate(RSP, Immediate(space)); |
| 861 __ ret(); |
| 862 __ Bind(&L); |
| 863 __ jmp(&call1); |
| 864 } |
| 865 |
| 866 |
| 867 ASSEMBLER_TEST_RUN(JumpSimpleLeaf, entry) { |
| 868 typedef int (*JumpSimpleLeafCode)(); |
| 869 EXPECT_EQ(42, reinterpret_cast<JumpSimpleLeafCode>(entry)()); |
| 870 } |
| 871 |
| 872 |
| 873 ASSEMBLER_TEST_GENERATE(SingleFPMoves, assembler) { |
| 874 __ movq(RAX, Immediate(bit_cast<int32_t, float>(234.0f))); |
| 875 __ movd(XMM0, RAX); |
| 876 __ movss(XMM1, XMM0); |
| 877 __ movss(XMM2, XMM1); |
| 878 __ movss(XMM3, XMM2); |
| 879 __ movss(XMM4, XMM3); |
| 880 __ movss(XMM5, XMM4); |
| 881 __ movss(XMM6, XMM5); |
| 882 __ movss(XMM7, XMM6); |
| 883 __ pushq(R15); // Callee saved. |
| 884 __ pushq(RAX); |
| 885 __ movq(Address(RSP, 0), Immediate(0)); |
| 886 __ movss(XMM0, Address(RSP, 0)); |
| 887 __ movss(Address(RSP, 0), XMM7); |
| 888 __ movss(XMM1, Address(RSP, 0)); |
| 889 __ movq(R10, RSP); |
| 890 __ movss(Address(R10, 0), XMM1); |
| 891 __ movss(XMM2, Address(R10, 0)); |
| 892 __ movq(R15, RSP); |
| 893 __ movss(Address(R15, 0), XMM2); |
| 894 __ movss(XMM3, Address(R15, 0)); |
| 895 __ movq(RAX, RSP); |
| 896 __ movss(Address(RAX, 0), XMM3); |
| 897 __ movss(XMM4, Address(RAX, 0)); |
| 898 __ movss(XMM0, Address(RAX, 0)); |
| 899 __ popq(RAX); |
| 900 __ popq(R15); // Callee saved. |
| 901 __ ret(); |
| 902 } |
| 903 |
| 904 |
| 905 ASSEMBLER_TEST_RUN(SingleFPMoves, entry) { |
| 906 typedef float (*SingleFPMovesCode)(); |
| 907 EXPECT_EQ(234, reinterpret_cast<SingleFPMovesCode>(entry)()); |
| 908 } |
| 909 |
| 910 |
| 911 ASSEMBLER_TEST_GENERATE(SingleFPMoves2, assembler) { |
| 912 __ movq(RAX, Immediate(bit_cast<int32_t, float>(234.0f))); |
| 913 __ movd(XMM0, RAX); |
| 914 __ movss(XMM1, XMM0); |
| 915 __ pushq(RAX); |
| 916 __ movq(Address(RSP, 0), Immediate(0)); |
| 917 __ movss(XMM0, Address(RSP, 0)); |
| 918 __ movss(Address(RSP, 0), XMM1); |
| 919 __ movss(XMM0, Address(RSP, 0)); |
| 920 __ popq(RAX); |
| 921 __ ret(); |
| 922 } |
| 923 |
| 924 |
| 925 ASSEMBLER_TEST_RUN(SingleFPMoves2, entry) { |
| 926 typedef float (*SingleFPMoves2Code)(); |
| 927 EXPECT_EQ(234, reinterpret_cast<SingleFPMoves2Code>(entry)()); |
| 928 } |
| 929 |
| 930 |
| 931 ASSEMBLER_TEST_GENERATE(SingleFPOperations, assembler) { |
| 932 __ pushq(RBX); |
| 933 __ pushq(RCX); |
| 934 __ movq(RBX, Immediate(bit_cast<int32_t, float>(12.3f))); |
| 935 __ movd(XMM0, RBX); |
| 936 __ movq(RCX, Immediate(bit_cast<int32_t, float>(3.4f))); |
| 937 __ movd(XMM1, RCX); |
| 938 __ addss(XMM0, XMM1); // 15.7f |
| 939 __ mulss(XMM0, XMM1); // 53.38f |
| 940 __ subss(XMM0, XMM1); // 49.98f |
| 941 __ divss(XMM0, XMM1); // 14.7f |
| 942 __ popq(RCX); |
| 943 __ popq(RBX); |
| 944 __ ret(); |
| 945 } |
| 946 |
| 947 |
| 948 ASSEMBLER_TEST_RUN(SingleFPOperations, entry) { |
| 949 typedef float (*SingleFPOperationsCode)(); |
| 950 float res = reinterpret_cast<SingleFPOperationsCode>(entry)(); |
| 951 EXPECT_FLOAT_EQ(14.7f, res, 0.001f); |
| 952 } |
| 953 |
| 954 |
| 955 ASSEMBLER_TEST_GENERATE(DoubleFPMoves, assembler) { |
| 956 __ movq(RAX, Immediate(bit_cast<int64_t, double>(1024.67))); |
| 957 __ pushq(R15); // Callee saved. |
| 958 __ pushq(RAX); |
| 959 __ movsd(XMM0, Address(RSP, 0)); |
| 960 __ movsd(XMM1, XMM0); |
| 961 __ movsd(XMM2, XMM1); |
| 962 __ movsd(XMM3, XMM2); |
| 963 __ movsd(XMM4, XMM3); |
| 964 __ movsd(XMM5, XMM4); |
| 965 __ movsd(XMM6, XMM5); |
| 966 __ movsd(XMM7, XMM6); |
| 967 __ movq(Address(RSP, 0), Immediate(0)); |
| 968 __ movsd(XMM0, Address(RSP, 0)); |
| 969 __ movsd(Address(RSP, 0), XMM7); |
| 970 __ movsd(XMM1, Address(RSP, 0)); |
| 971 __ movq(R10, RSP); |
| 972 __ movsd(Address(R10, 0), XMM1); |
| 973 __ movsd(XMM2, Address(R10, 0)); |
| 974 __ movq(R15, RSP); |
| 975 __ movsd(Address(R15, 0), XMM2); |
| 976 __ movsd(XMM3, Address(R15, 0)); |
| 977 __ movq(RAX, RSP); |
| 978 __ movsd(Address(RAX, 0), XMM3); |
| 979 __ movsd(XMM4, Address(RAX, 0)); |
| 980 __ movsd(XMM0, Address(RSP, 0)); |
| 981 __ popq(RAX); |
| 982 __ popq(R15); // Callee saved. |
| 983 __ ret(); |
| 984 } |
| 985 |
| 986 |
| 987 ASSEMBLER_TEST_RUN(DoubleFPMoves, entry) { |
| 988 typedef double (*DoubleFPMovesCode)(); |
| 989 EXPECT_FLOAT_EQ(1024.67, reinterpret_cast<DoubleFPMovesCode>(entry)(), 0.001); |
| 990 } |
| 991 |
| 992 |
| 993 ASSEMBLER_TEST_GENERATE(DoubleFPOperations, assembler) { |
| 994 __ movq(RAX, Immediate(bit_cast<int64_t, double>(12.3))); |
| 995 __ pushq(RAX); |
| 996 __ movsd(XMM0, Address(RSP, 0)); |
| 997 __ movq(RAX, Immediate(bit_cast<int64_t, double>(3.4))); |
| 998 __ movq(Address(RSP, 0), RAX); |
| 999 __ movsd(XMM1, Address(RSP, 0)); |
| 1000 __ addsd(XMM0, XMM1); // 15.7 |
| 1001 __ mulsd(XMM0, XMM1); // 53.38 |
| 1002 __ subsd(XMM0, XMM1); // 49.98 |
| 1003 __ divsd(XMM0, XMM1); // 14.7 |
| 1004 __ popq(RAX); |
| 1005 __ ret(); |
| 1006 } |
| 1007 |
| 1008 |
| 1009 ASSEMBLER_TEST_RUN(DoubleFPOperations, entry) { |
| 1010 typedef double (*SingleFPOperationsCode)(); |
| 1011 double res = reinterpret_cast<SingleFPOperationsCode>(entry)(); |
| 1012 EXPECT_FLOAT_EQ(14.7, res, 0.001); |
| 1013 } |
| 1014 |
| 1015 } // namespace dart |
| 1016 |
| 1017 #endif // defined TARGET_ARCH_X64 |
| OLD | NEW |