OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
270 double h; | 270 double h; |
271 double i; | 271 double i; |
272 } T; | 272 } T; |
273 T t; | 273 T t; |
274 | 274 |
275 // Create a function that accepts &t, and loads, manipulates, and stores | 275 // Create a function that accepts &t, and loads, manipulates, and stores |
276 // the doubles t.a ... t.f. | 276 // the doubles t.a ... t.f. |
277 MacroAssembler assm(isolate, NULL, 0); | 277 MacroAssembler assm(isolate, NULL, 0); |
278 Label L, C; | 278 Label L, C; |
279 | 279 |
280 if (CpuFeatures::IsSupported(FPU)) { | 280 __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, a)) ); |
281 CpuFeatureScope scope(&assm, FPU); | 281 __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, b)) ); |
| 282 __ add_d(f8, f4, f6); |
| 283 __ sdc1(f8, MemOperand(a0, OFFSET_OF(T, c)) ); // c = a + b. |
282 | 284 |
283 __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, a)) ); | 285 __ mov_d(f10, f8); // c |
284 __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, b)) ); | 286 __ neg_d(f12, f6); // -b |
285 __ add_d(f8, f4, f6); | 287 __ sub_d(f10, f10, f12); |
286 __ sdc1(f8, MemOperand(a0, OFFSET_OF(T, c)) ); // c = a + b. | 288 __ sdc1(f10, MemOperand(a0, OFFSET_OF(T, d)) ); // d = c - (-b). |
287 | 289 |
288 __ mov_d(f10, f8); // c | 290 __ sdc1(f4, MemOperand(a0, OFFSET_OF(T, b)) ); // b = a. |
289 __ neg_d(f12, f6); // -b | |
290 __ sub_d(f10, f10, f12); | |
291 __ sdc1(f10, MemOperand(a0, OFFSET_OF(T, d)) ); // d = c - (-b). | |
292 | 291 |
293 __ sdc1(f4, MemOperand(a0, OFFSET_OF(T, b)) ); // b = a. | 292 __ li(t0, 120); |
| 293 __ mtc1(t0, f14); |
| 294 __ cvt_d_w(f14, f14); // f14 = 120.0. |
| 295 __ mul_d(f10, f10, f14); |
| 296 __ sdc1(f10, MemOperand(a0, OFFSET_OF(T, e)) ); // e = d * 120 = 1.8066e16. |
294 | 297 |
295 __ li(t0, 120); | 298 __ div_d(f12, f10, f4); |
296 __ mtc1(t0, f14); | 299 __ sdc1(f12, MemOperand(a0, OFFSET_OF(T, f)) ); // f = e / a = 120.44. |
297 __ cvt_d_w(f14, f14); // f14 = 120.0. | |
298 __ mul_d(f10, f10, f14); | |
299 __ sdc1(f10, MemOperand(a0, OFFSET_OF(T, e)) ); // e = d * 120 = 1.8066e16. | |
300 | 300 |
301 __ div_d(f12, f10, f4); | 301 __ sqrt_d(f14, f12); |
302 __ sdc1(f12, MemOperand(a0, OFFSET_OF(T, f)) ); // f = e / a = 120.44. | 302 __ sdc1(f14, MemOperand(a0, OFFSET_OF(T, g)) ); |
303 | 303 // g = sqrt(f) = 10.97451593465515908537 |
304 __ sqrt_d(f14, f12); | |
305 __ sdc1(f14, MemOperand(a0, OFFSET_OF(T, g)) ); | |
306 // g = sqrt(f) = 10.97451593465515908537 | |
307 | 304 |
308 if (kArchVariant == kMips32r2) { | 305 if (kArchVariant == kMips32r2) { |
309 __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, h)) ); | 306 __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, h)) ); |
310 __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, i)) ); | 307 __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, i)) ); |
311 __ madd_d(f14, f6, f4, f6); | 308 __ madd_d(f14, f6, f4, f6); |
312 __ sdc1(f14, MemOperand(a0, OFFSET_OF(T, h)) ); | 309 __ sdc1(f14, MemOperand(a0, OFFSET_OF(T, h)) ); |
313 } | 310 } |
314 | 311 |
315 __ jr(ra); | 312 __ jr(ra); |
316 __ nop(); | 313 __ nop(); |
317 | 314 |
318 CodeDesc desc; | 315 CodeDesc desc; |
319 assm.GetCode(&desc); | 316 assm.GetCode(&desc); |
320 Object* code = HEAP->CreateCode( | 317 Object* code = HEAP->CreateCode( |
321 desc, | 318 desc, |
322 Code::ComputeFlags(Code::STUB), | 319 Code::ComputeFlags(Code::STUB), |
323 Handle<Code>())->ToObjectChecked(); | 320 Handle<Code>())->ToObjectChecked(); |
324 CHECK(code->IsCode()); | 321 CHECK(code->IsCode()); |
325 F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry()); | 322 F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry()); |
326 t.a = 1.5e14; | 323 t.a = 1.5e14; |
327 t.b = 2.75e11; | 324 t.b = 2.75e11; |
328 t.c = 0.0; | 325 t.c = 0.0; |
329 t.d = 0.0; | 326 t.d = 0.0; |
330 t.e = 0.0; | 327 t.e = 0.0; |
331 t.f = 0.0; | 328 t.f = 0.0; |
332 t.h = 1.5; | 329 t.h = 1.5; |
333 t.i = 2.75; | 330 t.i = 2.75; |
334 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); | 331 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); |
335 USE(dummy); | 332 USE(dummy); |
336 CHECK_EQ(1.5e14, t.a); | 333 CHECK_EQ(1.5e14, t.a); |
337 CHECK_EQ(1.5e14, t.b); | 334 CHECK_EQ(1.5e14, t.b); |
338 CHECK_EQ(1.50275e14, t.c); | 335 CHECK_EQ(1.50275e14, t.c); |
339 CHECK_EQ(1.50550e14, t.d); | 336 CHECK_EQ(1.50550e14, t.d); |
340 CHECK_EQ(1.8066e16, t.e); | 337 CHECK_EQ(1.8066e16, t.e); |
341 CHECK_EQ(120.44, t.f); | 338 CHECK_EQ(120.44, t.f); |
342 CHECK_EQ(10.97451593465515908537, t.g); | 339 CHECK_EQ(10.97451593465515908537, t.g); |
343 CHECK_EQ(6.875, t.h); | 340 CHECK_EQ(6.875, t.h); |
344 } | |
345 } | 341 } |
346 | 342 |
347 | 343 |
348 TEST(MIPS4) { | 344 TEST(MIPS4) { |
349 // Test moves between floating point and integer registers. | 345 // Test moves between floating point and integer registers. |
350 CcTest::InitializeVM(); | 346 CcTest::InitializeVM(); |
351 Isolate* isolate = Isolate::Current(); | 347 Isolate* isolate = Isolate::Current(); |
352 HandleScope scope(isolate); | 348 HandleScope scope(isolate); |
353 | 349 |
354 typedef struct { | 350 typedef struct { |
355 double a; | 351 double a; |
356 double b; | 352 double b; |
357 double c; | 353 double c; |
358 } T; | 354 } T; |
359 T t; | 355 T t; |
360 | 356 |
361 Assembler assm(isolate, NULL, 0); | 357 Assembler assm(isolate, NULL, 0); |
362 Label L, C; | 358 Label L, C; |
363 | 359 |
364 if (CpuFeatures::IsSupported(FPU)) { | 360 __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, a)) ); |
365 CpuFeatureScope scope(&assm, FPU); | 361 __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, b)) ); |
366 | 362 |
367 __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, a)) ); | 363 // Swap f4 and f6, by using four integer registers, t0-t3. |
368 __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, b)) ); | 364 __ mfc1(t0, f4); |
| 365 __ mfc1(t1, f5); |
| 366 __ mfc1(t2, f6); |
| 367 __ mfc1(t3, f7); |
369 | 368 |
370 // Swap f4 and f6, by using four integer registers, t0-t3. | 369 __ mtc1(t0, f6); |
371 __ mfc1(t0, f4); | 370 __ mtc1(t1, f7); |
372 __ mfc1(t1, f5); | 371 __ mtc1(t2, f4); |
373 __ mfc1(t2, f6); | 372 __ mtc1(t3, f5); |
374 __ mfc1(t3, f7); | |
375 | 373 |
376 __ mtc1(t0, f6); | 374 // Store the swapped f4 and f5 back to memory. |
377 __ mtc1(t1, f7); | 375 __ sdc1(f4, MemOperand(a0, OFFSET_OF(T, a)) ); |
378 __ mtc1(t2, f4); | 376 __ sdc1(f6, MemOperand(a0, OFFSET_OF(T, c)) ); |
379 __ mtc1(t3, f5); | |
380 | 377 |
381 // Store the swapped f4 and f5 back to memory. | 378 __ jr(ra); |
382 __ sdc1(f4, MemOperand(a0, OFFSET_OF(T, a)) ); | 379 __ nop(); |
383 __ sdc1(f6, MemOperand(a0, OFFSET_OF(T, c)) ); | |
384 | 380 |
385 __ jr(ra); | 381 CodeDesc desc; |
386 __ nop(); | 382 assm.GetCode(&desc); |
| 383 Object* code = HEAP->CreateCode( |
| 384 desc, |
| 385 Code::ComputeFlags(Code::STUB), |
| 386 Handle<Code>())->ToObjectChecked(); |
| 387 CHECK(code->IsCode()); |
| 388 F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry()); |
| 389 t.a = 1.5e22; |
| 390 t.b = 2.75e11; |
| 391 t.c = 17.17; |
| 392 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); |
| 393 USE(dummy); |
387 | 394 |
388 CodeDesc desc; | 395 CHECK_EQ(2.75e11, t.a); |
389 assm.GetCode(&desc); | 396 CHECK_EQ(2.75e11, t.b); |
390 Object* code = HEAP->CreateCode( | 397 CHECK_EQ(1.5e22, t.c); |
391 desc, | |
392 Code::ComputeFlags(Code::STUB), | |
393 Handle<Code>())->ToObjectChecked(); | |
394 CHECK(code->IsCode()); | |
395 F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry()); | |
396 t.a = 1.5e22; | |
397 t.b = 2.75e11; | |
398 t.c = 17.17; | |
399 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); | |
400 USE(dummy); | |
401 | |
402 CHECK_EQ(2.75e11, t.a); | |
403 CHECK_EQ(2.75e11, t.b); | |
404 CHECK_EQ(1.5e22, t.c); | |
405 } | |
406 } | 398 } |
407 | 399 |
408 | 400 |
409 TEST(MIPS5) { | 401 TEST(MIPS5) { |
410 // Test conversions between doubles and integers. | 402 // Test conversions between doubles and integers. |
411 CcTest::InitializeVM(); | 403 CcTest::InitializeVM(); |
412 Isolate* isolate = Isolate::Current(); | 404 Isolate* isolate = Isolate::Current(); |
413 HandleScope scope(isolate); | 405 HandleScope scope(isolate); |
414 | 406 |
415 typedef struct { | 407 typedef struct { |
416 double a; | 408 double a; |
417 double b; | 409 double b; |
418 int i; | 410 int i; |
419 int j; | 411 int j; |
420 } T; | 412 } T; |
421 T t; | 413 T t; |
422 | 414 |
423 Assembler assm(isolate, NULL, 0); | 415 Assembler assm(isolate, NULL, 0); |
424 Label L, C; | 416 Label L, C; |
425 | 417 |
426 if (CpuFeatures::IsSupported(FPU)) { | 418 // Load all structure elements to registers. |
427 CpuFeatureScope scope(&assm, FPU); | 419 __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, a)) ); |
| 420 __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, b)) ); |
| 421 __ lw(t0, MemOperand(a0, OFFSET_OF(T, i)) ); |
| 422 __ lw(t1, MemOperand(a0, OFFSET_OF(T, j)) ); |
428 | 423 |
429 // Load all structure elements to registers. | 424 // Convert double in f4 to int in element i. |
430 __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, a)) ); | 425 __ cvt_w_d(f8, f4); |
431 __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, b)) ); | 426 __ mfc1(t2, f8); |
432 __ lw(t0, MemOperand(a0, OFFSET_OF(T, i)) ); | 427 __ sw(t2, MemOperand(a0, OFFSET_OF(T, i)) ); |
433 __ lw(t1, MemOperand(a0, OFFSET_OF(T, j)) ); | |
434 | 428 |
435 // Convert double in f4 to int in element i. | 429 // Convert double in f6 to int in element j. |
436 __ cvt_w_d(f8, f4); | 430 __ cvt_w_d(f10, f6); |
437 __ mfc1(t2, f8); | 431 __ mfc1(t3, f10); |
438 __ sw(t2, MemOperand(a0, OFFSET_OF(T, i)) ); | 432 __ sw(t3, MemOperand(a0, OFFSET_OF(T, j)) ); |
439 | 433 |
440 // Convert double in f6 to int in element j. | 434 // Convert int in original i (t0) to double in a. |
441 __ cvt_w_d(f10, f6); | 435 __ mtc1(t0, f12); |
442 __ mfc1(t3, f10); | 436 __ cvt_d_w(f0, f12); |
443 __ sw(t3, MemOperand(a0, OFFSET_OF(T, j)) ); | 437 __ sdc1(f0, MemOperand(a0, OFFSET_OF(T, a)) ); |
444 | 438 |
445 // Convert int in original i (t0) to double in a. | 439 // Convert int in original j (t1) to double in b. |
446 __ mtc1(t0, f12); | 440 __ mtc1(t1, f14); |
447 __ cvt_d_w(f0, f12); | 441 __ cvt_d_w(f2, f14); |
448 __ sdc1(f0, MemOperand(a0, OFFSET_OF(T, a)) ); | 442 __ sdc1(f2, MemOperand(a0, OFFSET_OF(T, b)) ); |
449 | 443 |
450 // Convert int in original j (t1) to double in b. | 444 __ jr(ra); |
451 __ mtc1(t1, f14); | 445 __ nop(); |
452 __ cvt_d_w(f2, f14); | |
453 __ sdc1(f2, MemOperand(a0, OFFSET_OF(T, b)) ); | |
454 | 446 |
455 __ jr(ra); | 447 CodeDesc desc; |
456 __ nop(); | 448 assm.GetCode(&desc); |
| 449 Object* code = HEAP->CreateCode( |
| 450 desc, |
| 451 Code::ComputeFlags(Code::STUB), |
| 452 Handle<Code>())->ToObjectChecked(); |
| 453 CHECK(code->IsCode()); |
| 454 F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry()); |
| 455 t.a = 1.5e4; |
| 456 t.b = 2.75e8; |
| 457 t.i = 12345678; |
| 458 t.j = -100000; |
| 459 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); |
| 460 USE(dummy); |
457 | 461 |
458 CodeDesc desc; | 462 CHECK_EQ(12345678.0, t.a); |
459 assm.GetCode(&desc); | 463 CHECK_EQ(-100000.0, t.b); |
460 Object* code = HEAP->CreateCode( | 464 CHECK_EQ(15000, t.i); |
461 desc, | 465 CHECK_EQ(275000000, t.j); |
462 Code::ComputeFlags(Code::STUB), | |
463 Handle<Code>())->ToObjectChecked(); | |
464 CHECK(code->IsCode()); | |
465 F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry()); | |
466 t.a = 1.5e4; | |
467 t.b = 2.75e8; | |
468 t.i = 12345678; | |
469 t.j = -100000; | |
470 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); | |
471 USE(dummy); | |
472 | |
473 CHECK_EQ(12345678.0, t.a); | |
474 CHECK_EQ(-100000.0, t.b); | |
475 CHECK_EQ(15000, t.i); | |
476 CHECK_EQ(275000000, t.j); | |
477 } | |
478 } | 466 } |
479 | 467 |
480 | 468 |
481 TEST(MIPS6) { | 469 TEST(MIPS6) { |
482 // Test simple memory loads and stores. | 470 // Test simple memory loads and stores. |
483 CcTest::InitializeVM(); | 471 CcTest::InitializeVM(); |
484 Isolate* isolate = Isolate::Current(); | 472 Isolate* isolate = Isolate::Current(); |
485 HandleScope scope(isolate); | 473 HandleScope scope(isolate); |
486 | 474 |
487 typedef struct { | 475 typedef struct { |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
566 double f; | 554 double f; |
567 int32_t result; | 555 int32_t result; |
568 } T; | 556 } T; |
569 T t; | 557 T t; |
570 | 558 |
571 // Create a function that accepts &t, and loads, manipulates, and stores | 559 // Create a function that accepts &t, and loads, manipulates, and stores |
572 // the doubles t.a ... t.f. | 560 // the doubles t.a ... t.f. |
573 MacroAssembler assm(isolate, NULL, 0); | 561 MacroAssembler assm(isolate, NULL, 0); |
574 Label neither_is_nan, less_than, outa_here; | 562 Label neither_is_nan, less_than, outa_here; |
575 | 563 |
576 if (CpuFeatures::IsSupported(FPU)) { | 564 __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, a)) ); |
577 CpuFeatureScope scope(&assm, FPU); | 565 __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, b)) ); |
| 566 __ c(UN, D, f4, f6); |
| 567 __ bc1f(&neither_is_nan); |
| 568 __ nop(); |
| 569 __ sw(zero_reg, MemOperand(a0, OFFSET_OF(T, result)) ); |
| 570 __ Branch(&outa_here); |
578 | 571 |
579 __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, a)) ); | 572 __ bind(&neither_is_nan); |
580 __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, b)) ); | |
581 __ c(UN, D, f4, f6); | |
582 __ bc1f(&neither_is_nan); | |
583 __ nop(); | |
584 __ sw(zero_reg, MemOperand(a0, OFFSET_OF(T, result)) ); | |
585 __ Branch(&outa_here); | |
586 | 573 |
587 __ bind(&neither_is_nan); | 574 if (kArchVariant == kLoongson) { |
| 575 __ c(OLT, D, f6, f4); |
| 576 __ bc1t(&less_than); |
| 577 } else { |
| 578 __ c(OLT, D, f6, f4, 2); |
| 579 __ bc1t(&less_than, 2); |
| 580 } |
| 581 __ nop(); |
| 582 __ sw(zero_reg, MemOperand(a0, OFFSET_OF(T, result)) ); |
| 583 __ Branch(&outa_here); |
588 | 584 |
589 if (kArchVariant == kLoongson) { | 585 __ bind(&less_than); |
590 __ c(OLT, D, f6, f4); | 586 __ Addu(t0, zero_reg, Operand(1)); |
591 __ bc1t(&less_than); | 587 __ sw(t0, MemOperand(a0, OFFSET_OF(T, result)) ); // Set true. |
592 } else { | |
593 __ c(OLT, D, f6, f4, 2); | |
594 __ bc1t(&less_than, 2); | |
595 } | |
596 __ nop(); | |
597 __ sw(zero_reg, MemOperand(a0, OFFSET_OF(T, result)) ); | |
598 __ Branch(&outa_here); | |
599 | |
600 __ bind(&less_than); | |
601 __ Addu(t0, zero_reg, Operand(1)); | |
602 __ sw(t0, MemOperand(a0, OFFSET_OF(T, result)) ); // Set true. | |
603 | 588 |
604 | 589 |
605 // This test-case should have additional tests. | 590 // This test-case should have additional tests. |
606 | 591 |
607 __ bind(&outa_here); | 592 __ bind(&outa_here); |
608 | 593 |
609 __ jr(ra); | 594 __ jr(ra); |
610 __ nop(); | 595 __ nop(); |
611 | 596 |
612 CodeDesc desc; | 597 CodeDesc desc; |
613 assm.GetCode(&desc); | 598 assm.GetCode(&desc); |
614 Object* code = HEAP->CreateCode( | 599 Object* code = HEAP->CreateCode( |
615 desc, | 600 desc, |
616 Code::ComputeFlags(Code::STUB), | 601 Code::ComputeFlags(Code::STUB), |
617 Handle<Code>())->ToObjectChecked(); | 602 Handle<Code>())->ToObjectChecked(); |
618 CHECK(code->IsCode()); | 603 CHECK(code->IsCode()); |
619 F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry()); | 604 F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry()); |
620 t.a = 1.5e14; | 605 t.a = 1.5e14; |
621 t.b = 2.75e11; | 606 t.b = 2.75e11; |
622 t.c = 2.0; | 607 t.c = 2.0; |
623 t.d = -4.0; | 608 t.d = -4.0; |
624 t.e = 0.0; | 609 t.e = 0.0; |
625 t.f = 0.0; | 610 t.f = 0.0; |
626 t.result = 0; | 611 t.result = 0; |
627 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); | 612 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); |
628 USE(dummy); | 613 USE(dummy); |
629 CHECK_EQ(1.5e14, t.a); | 614 CHECK_EQ(1.5e14, t.a); |
630 CHECK_EQ(2.75e11, t.b); | 615 CHECK_EQ(2.75e11, t.b); |
631 CHECK_EQ(1, t.result); | 616 CHECK_EQ(1, t.result); |
632 } | |
633 } | 617 } |
634 | 618 |
635 | 619 |
636 TEST(MIPS8) { | 620 TEST(MIPS8) { |
637 // Test ROTR and ROTRV instructions. | 621 // Test ROTR and ROTRV instructions. |
638 CcTest::InitializeVM(); | 622 CcTest::InitializeVM(); |
639 Isolate* isolate = Isolate::Current(); | 623 Isolate* isolate = Isolate::Current(); |
640 HandleScope scope(isolate); | 624 HandleScope scope(isolate); |
641 | 625 |
642 typedef struct { | 626 typedef struct { |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
782 int32_t long_hi; | 766 int32_t long_hi; |
783 int32_t long_lo; | 767 int32_t long_lo; |
784 int32_t b_long_hi; | 768 int32_t b_long_hi; |
785 int32_t b_long_lo; | 769 int32_t b_long_lo; |
786 } T; | 770 } T; |
787 T t; | 771 T t; |
788 | 772 |
789 Assembler assm(isolate, NULL, 0); | 773 Assembler assm(isolate, NULL, 0); |
790 Label L, C; | 774 Label L, C; |
791 | 775 |
792 if (CpuFeatures::IsSupported(FPU) && kArchVariant == kMips32r2) { | 776 if (kArchVariant == kMips32r2) { |
793 CpuFeatureScope scope(&assm, FPU); | |
794 | |
795 // Load all structure elements to registers. | 777 // Load all structure elements to registers. |
796 __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, a))); | 778 __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, a))); |
797 | 779 |
798 // Save the raw bits of the double. | 780 // Save the raw bits of the double. |
799 __ mfc1(t0, f0); | 781 __ mfc1(t0, f0); |
800 __ mfc1(t1, f1); | 782 __ mfc1(t1, f1); |
801 __ sw(t0, MemOperand(a0, OFFSET_OF(T, dbl_mant))); | 783 __ sw(t0, MemOperand(a0, OFFSET_OF(T, dbl_mant))); |
802 __ sw(t1, MemOperand(a0, OFFSET_OF(T, dbl_exp))); | 784 __ sw(t1, MemOperand(a0, OFFSET_OF(T, dbl_exp))); |
803 | 785 |
804 // Convert double in f0 to long, save hi/lo parts. | 786 // Convert double in f0 to long, save hi/lo parts. |
(...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1090 double cvt_small_out; | 1072 double cvt_small_out; |
1091 uint32_t trunc_big_out; | 1073 uint32_t trunc_big_out; |
1092 uint32_t trunc_small_out; | 1074 uint32_t trunc_small_out; |
1093 uint32_t cvt_big_in; | 1075 uint32_t cvt_big_in; |
1094 uint32_t cvt_small_in; | 1076 uint32_t cvt_small_in; |
1095 } T; | 1077 } T; |
1096 T t; | 1078 T t; |
1097 | 1079 |
1098 MacroAssembler assm(isolate, NULL, 0); | 1080 MacroAssembler assm(isolate, NULL, 0); |
1099 | 1081 |
1100 if (CpuFeatures::IsSupported(FPU)) { | 1082 __ sw(t0, MemOperand(a0, OFFSET_OF(T, cvt_small_in))); |
1101 CpuFeatureScope scope(&assm, FPU); | 1083 __ Cvt_d_uw(f10, t0, f22); |
| 1084 __ sdc1(f10, MemOperand(a0, OFFSET_OF(T, cvt_small_out))); |
1102 | 1085 |
1103 __ sw(t0, MemOperand(a0, OFFSET_OF(T, cvt_small_in))); | 1086 __ Trunc_uw_d(f10, f10, f22); |
1104 __ Cvt_d_uw(f10, t0, f22); | 1087 __ swc1(f10, MemOperand(a0, OFFSET_OF(T, trunc_small_out))); |
1105 __ sdc1(f10, MemOperand(a0, OFFSET_OF(T, cvt_small_out))); | |
1106 | 1088 |
1107 __ Trunc_uw_d(f10, f10, f22); | 1089 __ sw(t0, MemOperand(a0, OFFSET_OF(T, cvt_big_in))); |
1108 __ swc1(f10, MemOperand(a0, OFFSET_OF(T, trunc_small_out))); | 1090 __ Cvt_d_uw(f8, t0, f22); |
| 1091 __ sdc1(f8, MemOperand(a0, OFFSET_OF(T, cvt_big_out))); |
1109 | 1092 |
1110 __ sw(t0, MemOperand(a0, OFFSET_OF(T, cvt_big_in))); | 1093 __ Trunc_uw_d(f8, f8, f22); |
1111 __ Cvt_d_uw(f8, t0, f22); | 1094 __ swc1(f8, MemOperand(a0, OFFSET_OF(T, trunc_big_out))); |
1112 __ sdc1(f8, MemOperand(a0, OFFSET_OF(T, cvt_big_out))); | |
1113 | 1095 |
1114 __ Trunc_uw_d(f8, f8, f22); | 1096 __ jr(ra); |
1115 __ swc1(f8, MemOperand(a0, OFFSET_OF(T, trunc_big_out))); | 1097 __ nop(); |
1116 | 1098 |
1117 __ jr(ra); | 1099 CodeDesc desc; |
1118 __ nop(); | 1100 assm.GetCode(&desc); |
| 1101 Object* code = HEAP->CreateCode( |
| 1102 desc, |
| 1103 Code::ComputeFlags(Code::STUB), |
| 1104 Handle<Code>())->ToObjectChecked(); |
| 1105 CHECK(code->IsCode()); |
| 1106 F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry()); |
1119 | 1107 |
1120 CodeDesc desc; | 1108 t.cvt_big_in = 0xFFFFFFFF; |
1121 assm.GetCode(&desc); | 1109 t.cvt_small_in = 333; |
1122 Object* code = HEAP->CreateCode( | |
1123 desc, | |
1124 Code::ComputeFlags(Code::STUB), | |
1125 Handle<Code>())->ToObjectChecked(); | |
1126 CHECK(code->IsCode()); | |
1127 F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry()); | |
1128 | 1110 |
1129 t.cvt_big_in = 0xFFFFFFFF; | 1111 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); |
1130 t.cvt_small_in = 333; | 1112 USE(dummy); |
1131 | 1113 |
1132 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); | 1114 CHECK_EQ(t.cvt_big_out, static_cast<double>(t.cvt_big_in)); |
1133 USE(dummy); | 1115 CHECK_EQ(t.cvt_small_out, static_cast<double>(t.cvt_small_in)); |
1134 | 1116 |
1135 CHECK_EQ(t.cvt_big_out, static_cast<double>(t.cvt_big_in)); | 1117 CHECK_EQ(static_cast<int>(t.trunc_big_out), static_cast<int>(t.cvt_big_in)); |
1136 CHECK_EQ(t.cvt_small_out, static_cast<double>(t.cvt_small_in)); | 1118 CHECK_EQ(static_cast<int>(t.trunc_small_out), |
1137 | 1119 static_cast<int>(t.cvt_small_in)); |
1138 CHECK_EQ(static_cast<int>(t.trunc_big_out), static_cast<int>(t.cvt_big_in)); | |
1139 CHECK_EQ(static_cast<int>(t.trunc_small_out), | |
1140 static_cast<int>(t.cvt_small_in)); | |
1141 } | |
1142 } | 1120 } |
1143 | 1121 |
1144 | 1122 |
1145 TEST(MIPS14) { | 1123 TEST(MIPS14) { |
1146 // Test round, floor, ceil, trunc, cvt. | 1124 // Test round, floor, ceil, trunc, cvt. |
1147 CcTest::InitializeVM(); | 1125 CcTest::InitializeVM(); |
1148 Isolate* isolate = Isolate::Current(); | 1126 Isolate* isolate = Isolate::Current(); |
1149 HandleScope scope(isolate); | 1127 HandleScope scope(isolate); |
1150 | 1128 |
1151 #define ROUND_STRUCT_ELEMENT(x) \ | 1129 #define ROUND_STRUCT_ELEMENT(x) \ |
(...skipping 22 matching lines...) Expand all Loading... |
1174 ROUND_STRUCT_ELEMENT(ceil) | 1152 ROUND_STRUCT_ELEMENT(ceil) |
1175 ROUND_STRUCT_ELEMENT(trunc) | 1153 ROUND_STRUCT_ELEMENT(trunc) |
1176 ROUND_STRUCT_ELEMENT(cvt) | 1154 ROUND_STRUCT_ELEMENT(cvt) |
1177 } T; | 1155 } T; |
1178 T t; | 1156 T t; |
1179 | 1157 |
1180 #undef ROUND_STRUCT_ELEMENT | 1158 #undef ROUND_STRUCT_ELEMENT |
1181 | 1159 |
1182 MacroAssembler assm(isolate, NULL, 0); | 1160 MacroAssembler assm(isolate, NULL, 0); |
1183 | 1161 |
1184 if (CpuFeatures::IsSupported(FPU)) { | 1162 // Save FCSR. |
1185 CpuFeatureScope scope(&assm, FPU); | 1163 __ cfc1(a1, FCSR); |
| 1164 // Disable FPU exceptions. |
| 1165 __ ctc1(zero_reg, FCSR); |
| 1166 #define RUN_ROUND_TEST(x) \ |
| 1167 __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, round_up_in))); \ |
| 1168 __ x##_w_d(f0, f0); \ |
| 1169 __ swc1(f0, MemOperand(a0, OFFSET_OF(T, x##_up_out))); \ |
| 1170 \ |
| 1171 __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, round_down_in))); \ |
| 1172 __ x##_w_d(f0, f0); \ |
| 1173 __ swc1(f0, MemOperand(a0, OFFSET_OF(T, x##_down_out))); \ |
| 1174 \ |
| 1175 __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, neg_round_up_in))); \ |
| 1176 __ x##_w_d(f0, f0); \ |
| 1177 __ swc1(f0, MemOperand(a0, OFFSET_OF(T, neg_##x##_up_out))); \ |
| 1178 \ |
| 1179 __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, neg_round_down_in))); \ |
| 1180 __ x##_w_d(f0, f0); \ |
| 1181 __ swc1(f0, MemOperand(a0, OFFSET_OF(T, neg_##x##_down_out))); \ |
| 1182 \ |
| 1183 __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, err1_in))); \ |
| 1184 __ ctc1(zero_reg, FCSR); \ |
| 1185 __ x##_w_d(f0, f0); \ |
| 1186 __ cfc1(a2, FCSR); \ |
| 1187 __ sw(a2, MemOperand(a0, OFFSET_OF(T, x##_err1_out))); \ |
| 1188 \ |
| 1189 __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, err2_in))); \ |
| 1190 __ ctc1(zero_reg, FCSR); \ |
| 1191 __ x##_w_d(f0, f0); \ |
| 1192 __ cfc1(a2, FCSR); \ |
| 1193 __ sw(a2, MemOperand(a0, OFFSET_OF(T, x##_err2_out))); \ |
| 1194 \ |
| 1195 __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, err3_in))); \ |
| 1196 __ ctc1(zero_reg, FCSR); \ |
| 1197 __ x##_w_d(f0, f0); \ |
| 1198 __ cfc1(a2, FCSR); \ |
| 1199 __ sw(a2, MemOperand(a0, OFFSET_OF(T, x##_err3_out))); \ |
| 1200 \ |
| 1201 __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, err4_in))); \ |
| 1202 __ ctc1(zero_reg, FCSR); \ |
| 1203 __ x##_w_d(f0, f0); \ |
| 1204 __ cfc1(a2, FCSR); \ |
| 1205 __ sw(a2, MemOperand(a0, OFFSET_OF(T, x##_err4_out))); \ |
| 1206 __ swc1(f0, MemOperand(a0, OFFSET_OF(T, x##_invalid_result))); |
1186 | 1207 |
1187 // Save FCSR. | 1208 RUN_ROUND_TEST(round) |
1188 __ cfc1(a1, FCSR); | 1209 RUN_ROUND_TEST(floor) |
1189 // Disable FPU exceptions. | 1210 RUN_ROUND_TEST(ceil) |
1190 __ ctc1(zero_reg, FCSR); | 1211 RUN_ROUND_TEST(trunc) |
1191 #define RUN_ROUND_TEST(x) \ | 1212 RUN_ROUND_TEST(cvt) |
1192 __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, round_up_in))); \ | |
1193 __ x##_w_d(f0, f0); \ | |
1194 __ swc1(f0, MemOperand(a0, OFFSET_OF(T, x##_up_out))); \ | |
1195 \ | |
1196 __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, round_down_in))); \ | |
1197 __ x##_w_d(f0, f0); \ | |
1198 __ swc1(f0, MemOperand(a0, OFFSET_OF(T, x##_down_out))); \ | |
1199 \ | |
1200 __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, neg_round_up_in))); \ | |
1201 __ x##_w_d(f0, f0); \ | |
1202 __ swc1(f0, MemOperand(a0, OFFSET_OF(T, neg_##x##_up_out))); \ | |
1203 \ | |
1204 __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, neg_round_down_in))); \ | |
1205 __ x##_w_d(f0, f0); \ | |
1206 __ swc1(f0, MemOperand(a0, OFFSET_OF(T, neg_##x##_down_out))); \ | |
1207 \ | |
1208 __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, err1_in))); \ | |
1209 __ ctc1(zero_reg, FCSR); \ | |
1210 __ x##_w_d(f0, f0); \ | |
1211 __ cfc1(a2, FCSR); \ | |
1212 __ sw(a2, MemOperand(a0, OFFSET_OF(T, x##_err1_out))); \ | |
1213 \ | |
1214 __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, err2_in))); \ | |
1215 __ ctc1(zero_reg, FCSR); \ | |
1216 __ x##_w_d(f0, f0); \ | |
1217 __ cfc1(a2, FCSR); \ | |
1218 __ sw(a2, MemOperand(a0, OFFSET_OF(T, x##_err2_out))); \ | |
1219 \ | |
1220 __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, err3_in))); \ | |
1221 __ ctc1(zero_reg, FCSR); \ | |
1222 __ x##_w_d(f0, f0); \ | |
1223 __ cfc1(a2, FCSR); \ | |
1224 __ sw(a2, MemOperand(a0, OFFSET_OF(T, x##_err3_out))); \ | |
1225 \ | |
1226 __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, err4_in))); \ | |
1227 __ ctc1(zero_reg, FCSR); \ | |
1228 __ x##_w_d(f0, f0); \ | |
1229 __ cfc1(a2, FCSR); \ | |
1230 __ sw(a2, MemOperand(a0, OFFSET_OF(T, x##_err4_out))); \ | |
1231 __ swc1(f0, MemOperand(a0, OFFSET_OF(T, x##_invalid_result))); | |
1232 | 1213 |
1233 RUN_ROUND_TEST(round) | 1214 // Restore FCSR. |
1234 RUN_ROUND_TEST(floor) | 1215 __ ctc1(a1, FCSR); |
1235 RUN_ROUND_TEST(ceil) | |
1236 RUN_ROUND_TEST(trunc) | |
1237 RUN_ROUND_TEST(cvt) | |
1238 | 1216 |
1239 // Restore FCSR. | 1217 __ jr(ra); |
1240 __ ctc1(a1, FCSR); | 1218 __ nop(); |
1241 | 1219 |
1242 __ jr(ra); | 1220 CodeDesc desc; |
1243 __ nop(); | 1221 assm.GetCode(&desc); |
| 1222 Object* code = HEAP->CreateCode( |
| 1223 desc, |
| 1224 Code::ComputeFlags(Code::STUB), |
| 1225 Handle<Code>())->ToObjectChecked(); |
| 1226 CHECK(code->IsCode()); |
| 1227 F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry()); |
1244 | 1228 |
1245 CodeDesc desc; | 1229 t.round_up_in = 123.51; |
1246 assm.GetCode(&desc); | 1230 t.round_down_in = 123.49; |
1247 Object* code = HEAP->CreateCode( | 1231 t.neg_round_up_in = -123.5; |
1248 desc, | 1232 t.neg_round_down_in = -123.49; |
1249 Code::ComputeFlags(Code::STUB), | 1233 t.err1_in = 123.51; |
1250 Handle<Code>())->ToObjectChecked(); | 1234 t.err2_in = 1; |
1251 CHECK(code->IsCode()); | 1235 t.err3_in = static_cast<double>(1) + 0xFFFFFFFF; |
1252 F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry()); | 1236 t.err4_in = NAN; |
1253 | 1237 |
1254 t.round_up_in = 123.51; | 1238 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); |
1255 t.round_down_in = 123.49; | 1239 USE(dummy); |
1256 t.neg_round_up_in = -123.5; | |
1257 t.neg_round_down_in = -123.49; | |
1258 t.err1_in = 123.51; | |
1259 t.err2_in = 1; | |
1260 t.err3_in = static_cast<double>(1) + 0xFFFFFFFF; | |
1261 t.err4_in = NAN; | |
1262 | |
1263 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); | |
1264 USE(dummy); | |
1265 | 1240 |
1266 #define GET_FPU_ERR(x) (static_cast<int>(x & kFCSRFlagMask)) | 1241 #define GET_FPU_ERR(x) (static_cast<int>(x & kFCSRFlagMask)) |
1267 #define CHECK_ROUND_RESULT(type) \ | 1242 #define CHECK_ROUND_RESULT(type) \ |
1268 CHECK(GET_FPU_ERR(t.type##_err1_out) & kFCSRInexactFlagMask); \ | 1243 CHECK(GET_FPU_ERR(t.type##_err1_out) & kFCSRInexactFlagMask); \ |
1269 CHECK_EQ(0, GET_FPU_ERR(t.type##_err2_out)); \ | 1244 CHECK_EQ(0, GET_FPU_ERR(t.type##_err2_out)); \ |
1270 CHECK(GET_FPU_ERR(t.type##_err3_out) & kFCSRInvalidOpFlagMask); \ | 1245 CHECK(GET_FPU_ERR(t.type##_err3_out) & kFCSRInvalidOpFlagMask); \ |
1271 CHECK(GET_FPU_ERR(t.type##_err4_out) & kFCSRInvalidOpFlagMask); \ | 1246 CHECK(GET_FPU_ERR(t.type##_err4_out) & kFCSRInvalidOpFlagMask); \ |
1272 CHECK_EQ(kFPUInvalidResult, t.type##_invalid_result); | 1247 CHECK_EQ(kFPUInvalidResult, t.type##_invalid_result); |
1273 | 1248 |
1274 CHECK_ROUND_RESULT(round); | 1249 CHECK_ROUND_RESULT(round); |
1275 CHECK_ROUND_RESULT(floor); | 1250 CHECK_ROUND_RESULT(floor); |
1276 CHECK_ROUND_RESULT(ceil); | 1251 CHECK_ROUND_RESULT(ceil); |
1277 CHECK_ROUND_RESULT(cvt); | 1252 CHECK_ROUND_RESULT(cvt); |
1278 } | |
1279 } | 1253 } |
1280 | 1254 |
1281 | 1255 |
1282 TEST(MIPS15) { | 1256 TEST(MIPS15) { |
1283 // Test chaining of label usages within instructions (issue 1644). | 1257 // Test chaining of label usages within instructions (issue 1644). |
1284 CcTest::InitializeVM(); | 1258 CcTest::InitializeVM(); |
1285 Isolate* isolate = Isolate::Current(); | 1259 Isolate* isolate = Isolate::Current(); |
1286 HandleScope scope(isolate); | 1260 HandleScope scope(isolate); |
1287 Assembler assm(isolate, NULL, 0); | 1261 Assembler assm(isolate, NULL, 0); |
1288 | 1262 |
1289 Label target; | 1263 Label target; |
1290 __ beq(v0, v1, &target); | 1264 __ beq(v0, v1, &target); |
1291 __ nop(); | 1265 __ nop(); |
1292 __ bne(v0, v1, &target); | 1266 __ bne(v0, v1, &target); |
1293 __ nop(); | 1267 __ nop(); |
1294 __ bind(&target); | 1268 __ bind(&target); |
1295 __ nop(); | 1269 __ nop(); |
1296 } | 1270 } |
1297 | 1271 |
1298 #undef __ | 1272 #undef __ |
OLD | NEW |