1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 #include "src/disassembler.h"
31 #include "src/factory.h"
32 #include "src/macro-assembler.h"
33 #include "src/mips/macro-assembler-mips.h"
34 #include "src/mips/simulator-mips.h"
36 #include "test/cctest/cctest.h"
38 using namespace v8::internal;
41 // Define these function prototypes to match JSEntryFunction in execution.cc.
42 typedef Object* (*F1)(int x, int p1, int p2, int p3, int p4);
43 typedef Object* (*F2)(int x, int y, int p2, int p3, int p4);
44 typedef Object* (*F3)(void* p, int p1, int p2, int p3, int p4);
51 CcTest::InitializeVM();
52 Isolate* isolate = CcTest::i_isolate();
53 HandleScope scope(isolate);
55 MacroAssembler assm(isolate, NULL, 0);
64 Handle<Code> code = isolate->factory()->NewCode(
65 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
66 F2 f = FUNCTION_CAST<F2>(code->entry());
67 int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 0xab0, 0xc, 0, 0, 0));
68 ::printf("f() = %d\n", res);
74 CcTest::InitializeVM();
75 Isolate* isolate = CcTest::i_isolate();
76 HandleScope scope(isolate);
78 MacroAssembler assm(isolate, NULL, 0);
92 __ Branch(&L, ne, v1, Operand(0));
100 Handle<Code> code = isolate->factory()->NewCode(
101 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
102 F1 f = FUNCTION_CAST<F1>(code->entry());
103 int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 50, 0, 0, 0, 0));
104 ::printf("f() = %d\n", res);
110 CcTest::InitializeVM();
111 Isolate* isolate = CcTest::i_isolate();
112 HandleScope scope(isolate);
114 MacroAssembler assm(isolate, NULL, 0);
118 // ----- Test all instructions.
120 // Test lui, ori, and addiu, used in the li pseudo-instruction.
121 // This way we can then safely load registers with chosen values.
123 __ ori(t0, zero_reg, 0);
126 __ ori(t0, t0, 0x0f0f);
127 __ ori(t0, t0, 0xf0f0);
129 __ addiu(t2, t1, -0x10);
131 // Load values in temporary registers.
132 __ li(t0, 0x00000004);
133 __ li(t1, 0x00001234);
134 __ li(t2, 0x12345678);
135 __ li(t3, 0x7fffffff);
136 __ li(t4, 0xfffffffc);
137 __ li(t5, 0xffffedcc);
138 __ li(t6, 0xedcba988);
139 __ li(t7, 0x80000000);
142 __ srl(v0, t2, 8); // 0x00123456
143 __ sll(v0, v0, 11); // 0x91a2b000
144 __ sra(v0, v0, 3); // 0xf2345600
145 __ srav(v0, v0, t0); // 0xff234560
146 __ sllv(v0, v0, t0); // 0xf2345600
147 __ srlv(v0, v0, t0); // 0x0f234560
148 __ Branch(&error, ne, v0, Operand(0x0f234560));
151 __ addu(v0, t0, t1); // 0x00001238
152 __ subu(v0, v0, t0); // 0x00001234
153 __ Branch(&error, ne, v0, Operand(0x00001234));
156 __ Branch(&error, ne, v1, Operand(0x80000003));
158 __ subu(v1, t7, t0); // 0x7ffffffc
159 __ Branch(&error, ne, v1, Operand(0x7ffffffc));
162 __ and_(v0, t1, t2); // 0x00001230
163 __ or_(v0, v0, t1); // 0x00001234
164 __ xor_(v0, v0, t2); // 0x1234444c
165 __ nor(v0, v0, t2); // 0xedcba987
166 __ Branch(&error, ne, v0, Operand(0xedcba983));
170 __ Branch(&error, ne, v0, Operand(0x1));
173 __ Branch(&error, ne, v0, Operand(0x0));
175 // End of SPECIAL class.
177 __ addiu(v0, zero_reg, 0x7421); // 0x00007421
178 __ addiu(v0, v0, -0x1); // 0x00007420
179 __ addiu(v0, v0, -0x20); // 0x00007400
180 __ Branch(&error, ne, v0, Operand(0x00007400));
182 __ addiu(v1, t3, 0x1); // 0x80000000
183 __ Branch(&error, ne, v1, Operand(0x80000000));
186 __ slti(v0, t1, 0x00002000); // 0x1
187 __ slti(v0, v0, 0xffff8000); // 0x0
188 __ Branch(&error, ne, v0, Operand(0x0));
190 __ sltiu(v0, t1, 0x00002000); // 0x1
191 __ sltiu(v0, v0, 0x00008000); // 0x1
192 __ Branch(&error, ne, v0, Operand(0x1));
195 __ andi(v0, t1, 0xf0f0); // 0x00001030
196 __ ori(v0, v0, 0x8a00); // 0x00009a30
197 __ xori(v0, v0, 0x83cc); // 0x000019fc
198 __ Branch(&error, ne, v0, Operand(0x000019fc));
200 __ lui(v1, 0x8123); // 0x81230000
201 __ Branch(&error, ne, v1, Operand(0x81230000));
204 // Bit twiddling instructions & conditional moves.
205 // Uses t0-t7 as set above.
206 __ Clz(v0, t0); // 29
207 __ Clz(v1, t1); // 19
208 __ addu(v0, v0, v1); // 48
210 __ addu(v0, v0, v1); // 51
212 __ addu(v0, v0, v1); // 51
213 __ Branch(&error, ne, v0, Operand(51));
214 __ Movn(a0, t3, t0); // Move a0<-t3 (t0 is NOT 0).
215 __ Ins(a0, t1, 12, 8); // 0x7ff34fff
216 __ Branch(&error, ne, a0, Operand(0x7ff34fff));
217 __ Movz(a0, t6, t7); // a0 not updated (t7 is NOT 0).
218 __ Ext(a1, a0, 8, 12); // 0x34f
219 __ Branch(&error, ne, a1, Operand(0x34f));
220 __ Movz(a0, t6, v1); // a0<-t6, v0 is 0, from 8 instr back.
221 __ Branch(&error, ne, a0, Operand(t6));
223 // Everything was correctly executed. Load the expected result.
224 __ li(v0, 0x31415926);
229 // Got an error. Return a wrong result.
238 Handle<Code> code = isolate->factory()->NewCode(
239 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
240 F2 f = FUNCTION_CAST<F2>(code->entry());
241 int res = reinterpret_cast<int>(CALL_GENERATED_CODE(f, 0xab0, 0xc, 0, 0, 0));
242 ::printf("f() = %d\n", res);
243 CHECK_EQ(0x31415926, res);
248 // Test floating point instructions.
249 CcTest::InitializeVM();
250 Isolate* isolate = CcTest::i_isolate();
251 HandleScope scope(isolate);
266 // Create a function that accepts &t, and loads, manipulates, and stores
267 // the doubles t.a ... t.f.
268 MacroAssembler assm(isolate, NULL, 0);
271 __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, a)) );
272 __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, b)) );
273 __ add_d(f8, f4, f6);
274 __ sdc1(f8, MemOperand(a0, OFFSET_OF(T, c)) ); // c = a + b.
276 __ mov_d(f10, f8); // c
277 __ neg_d(f12, f6); // -b
278 __ sub_d(f10, f10, f12);
279 __ sdc1(f10, MemOperand(a0, OFFSET_OF(T, d)) ); // d = c - (-b).
281 __ sdc1(f4, MemOperand(a0, OFFSET_OF(T, b)) ); // b = a.
285 __ cvt_d_w(f14, f14); // f14 = 120.0.
286 __ mul_d(f10, f10, f14);
287 __ sdc1(f10, MemOperand(a0, OFFSET_OF(T, e)) ); // e = d * 120 = 1.8066e16.
289 __ div_d(f12, f10, f4);
290 __ sdc1(f12, MemOperand(a0, OFFSET_OF(T, f)) ); // f = e / a = 120.44.
293 __ sdc1(f14, MemOperand(a0, OFFSET_OF(T, g)) );
294 // g = sqrt(f) = 10.97451593465515908537
296 if (kArchVariant == kMips32r2) {
297 __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, h)) );
298 __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, i)) );
299 __ madd_d(f14, f6, f4, f6);
300 __ sdc1(f14, MemOperand(a0, OFFSET_OF(T, h)) );
308 Handle<Code> code = isolate->factory()->NewCode(
309 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
310 F3 f = FUNCTION_CAST<F3>(code->entry());
319 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
321 CHECK_EQ(1.5e14, t.a);
322 CHECK_EQ(1.5e14, t.b);
323 CHECK_EQ(1.50275e14, t.c);
324 CHECK_EQ(1.50550e14, t.d);
325 CHECK_EQ(1.8066e16, t.e);
326 CHECK_EQ(120.44, t.f);
327 CHECK_EQ(10.97451593465515908537, t.g);
328 if (kArchVariant == kMips32r2) {
329 CHECK_EQ(6.875, t.h);
335 // Test moves between floating point and integer registers.
336 CcTest::InitializeVM();
337 Isolate* isolate = CcTest::i_isolate();
338 HandleScope scope(isolate);
347 Assembler assm(isolate, NULL, 0);
350 __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, a)) );
351 __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, b)) );
353 // Swap f4 and f6, by using four integer registers, t0-t3.
364 // Store the swapped f4 and f5 back to memory.
365 __ sdc1(f4, MemOperand(a0, OFFSET_OF(T, a)) );
366 __ sdc1(f6, MemOperand(a0, OFFSET_OF(T, c)) );
373 Handle<Code> code = isolate->factory()->NewCode(
374 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
375 F3 f = FUNCTION_CAST<F3>(code->entry());
379 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
382 CHECK_EQ(2.75e11, t.a);
383 CHECK_EQ(2.75e11, t.b);
384 CHECK_EQ(1.5e22, t.c);
389 // Test conversions between doubles and integers.
390 CcTest::InitializeVM();
391 Isolate* isolate = CcTest::i_isolate();
392 HandleScope scope(isolate);
402 Assembler assm(isolate, NULL, 0);
405 // Load all structure elements to registers.
406 __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, a)) );
407 __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, b)) );
408 __ lw(t0, MemOperand(a0, OFFSET_OF(T, i)) );
409 __ lw(t1, MemOperand(a0, OFFSET_OF(T, j)) );
411 // Convert double in f4 to int in element i.
414 __ sw(t2, MemOperand(a0, OFFSET_OF(T, i)) );
416 // Convert double in f6 to int in element j.
419 __ sw(t3, MemOperand(a0, OFFSET_OF(T, j)) );
421 // Convert int in original i (t0) to double in a.
424 __ sdc1(f0, MemOperand(a0, OFFSET_OF(T, a)) );
426 // Convert int in original j (t1) to double in b.
429 __ sdc1(f2, MemOperand(a0, OFFSET_OF(T, b)) );
436 Handle<Code> code = isolate->factory()->NewCode(
437 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
438 F3 f = FUNCTION_CAST<F3>(code->entry());
443 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
446 CHECK_EQ(12345678.0, t.a);
447 CHECK_EQ(-100000.0, t.b);
448 CHECK_EQ(15000, t.i);
449 CHECK_EQ(275000000, t.j);
454 // Test simple memory loads and stores.
455 CcTest::InitializeVM();
456 Isolate* isolate = CcTest::i_isolate();
457 HandleScope scope(isolate);
471 Assembler assm(isolate, NULL, 0);
474 // Basic word load/store.
475 __ lw(t0, MemOperand(a0, OFFSET_OF(T, ui)) );
476 __ sw(t0, MemOperand(a0, OFFSET_OF(T, r1)) );
478 // lh with positive data.
479 __ lh(t1, MemOperand(a0, OFFSET_OF(T, ui)) );
480 __ sw(t1, MemOperand(a0, OFFSET_OF(T, r2)) );
482 // lh with negative data.
483 __ lh(t2, MemOperand(a0, OFFSET_OF(T, si)) );
484 __ sw(t2, MemOperand(a0, OFFSET_OF(T, r3)) );
486 // lhu with negative data.
487 __ lhu(t3, MemOperand(a0, OFFSET_OF(T, si)) );
488 __ sw(t3, MemOperand(a0, OFFSET_OF(T, r4)) );
490 // lb with negative data.
491 __ lb(t4, MemOperand(a0, OFFSET_OF(T, si)) );
492 __ sw(t4, MemOperand(a0, OFFSET_OF(T, r5)) );
494 // sh writes only 1/2 of word.
496 __ ori(t5, t5, 0x3333);
497 __ sw(t5, MemOperand(a0, OFFSET_OF(T, r6)) );
498 __ lhu(t5, MemOperand(a0, OFFSET_OF(T, si)) );
499 __ sh(t5, MemOperand(a0, OFFSET_OF(T, r6)) );
506 Handle<Code> code = isolate->factory()->NewCode(
507 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
508 F3 f = FUNCTION_CAST<F3>(code->entry());
511 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
514 CHECK_EQ(0x11223344, t.r1);
515 #if __BYTE_ORDER == __LITTLE_ENDIAN
516 CHECK_EQ(0x3344, t.r2);
517 CHECK_EQ(0xffffbbcc, t.r3);
518 CHECK_EQ(0x0000bbcc, t.r4);
519 CHECK_EQ(0xffffffcc, t.r5);
520 CHECK_EQ(0x3333bbcc, t.r6);
521 #elif __BYTE_ORDER == __BIG_ENDIAN
522 CHECK_EQ(0x1122, t.r2);
523 CHECK_EQ(0xffff99aa, t.r3);
524 CHECK_EQ(0x000099aa, t.r4);
525 CHECK_EQ(0xffffff99, t.r5);
526 CHECK_EQ(0x99aa3333, t.r6);
528 #error Unknown endianness
534 // Test floating point compare and branch instructions.
535 CcTest::InitializeVM();
536 Isolate* isolate = CcTest::i_isolate();
537 HandleScope scope(isolate);
550 // Create a function that accepts &t, and loads, manipulates, and stores
551 // the doubles t.a ... t.f.
552 MacroAssembler assm(isolate, NULL, 0);
553 Label neither_is_nan, less_than, outa_here;
555 __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, a)) );
556 __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, b)) );
558 __ bc1f(&neither_is_nan);
560 __ sw(zero_reg, MemOperand(a0, OFFSET_OF(T, result)) );
561 __ Branch(&outa_here);
563 __ bind(&neither_is_nan);
565 if (kArchVariant == kLoongson) {
566 __ c(OLT, D, f6, f4);
569 __ c(OLT, D, f6, f4, 2);
570 __ bc1t(&less_than, 2);
573 __ sw(zero_reg, MemOperand(a0, OFFSET_OF(T, result)) );
574 __ Branch(&outa_here);
577 __ Addu(t0, zero_reg, Operand(1));
578 __ sw(t0, MemOperand(a0, OFFSET_OF(T, result)) ); // Set true.
581 // This test-case should have additional tests.
590 Handle<Code> code = isolate->factory()->NewCode(
591 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
592 F3 f = FUNCTION_CAST<F3>(code->entry());
600 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
602 CHECK_EQ(1.5e14, t.a);
603 CHECK_EQ(2.75e11, t.b);
604 CHECK_EQ(1, t.result);
609 // Test ROTR and ROTRV instructions.
610 CcTest::InitializeVM();
611 Isolate* isolate = CcTest::i_isolate();
612 HandleScope scope(isolate);
616 int32_t result_rotr_4;
617 int32_t result_rotr_8;
618 int32_t result_rotr_12;
619 int32_t result_rotr_16;
620 int32_t result_rotr_20;
621 int32_t result_rotr_24;
622 int32_t result_rotr_28;
623 int32_t result_rotrv_4;
624 int32_t result_rotrv_8;
625 int32_t result_rotrv_12;
626 int32_t result_rotrv_16;
627 int32_t result_rotrv_20;
628 int32_t result_rotrv_24;
629 int32_t result_rotrv_28;
633 MacroAssembler assm(isolate, NULL, 0);
636 __ lw(t0, MemOperand(a0, OFFSET_OF(T, input)) );
638 // ROTR instruction (called through the Ror macro).
639 __ Ror(t1, t0, 0x0004);
640 __ Ror(t2, t0, 0x0008);
641 __ Ror(t3, t0, 0x000c);
642 __ Ror(t4, t0, 0x0010);
643 __ Ror(t5, t0, 0x0014);
644 __ Ror(t6, t0, 0x0018);
645 __ Ror(t7, t0, 0x001c);
648 __ sw(t1, MemOperand(a0, OFFSET_OF(T, result_rotr_4)) );
649 __ sw(t2, MemOperand(a0, OFFSET_OF(T, result_rotr_8)) );
650 __ sw(t3, MemOperand(a0, OFFSET_OF(T, result_rotr_12)) );
651 __ sw(t4, MemOperand(a0, OFFSET_OF(T, result_rotr_16)) );
652 __ sw(t5, MemOperand(a0, OFFSET_OF(T, result_rotr_20)) );
653 __ sw(t6, MemOperand(a0, OFFSET_OF(T, result_rotr_24)) );
654 __ sw(t7, MemOperand(a0, OFFSET_OF(T, result_rotr_28)) );
656 // ROTRV instruction (called through the Ror macro).
673 __ sw(t1, MemOperand(a0, OFFSET_OF(T, result_rotrv_4)) );
674 __ sw(t2, MemOperand(a0, OFFSET_OF(T, result_rotrv_8)) );
675 __ sw(t3, MemOperand(a0, OFFSET_OF(T, result_rotrv_12)) );
676 __ sw(t4, MemOperand(a0, OFFSET_OF(T, result_rotrv_16)) );
677 __ sw(t5, MemOperand(a0, OFFSET_OF(T, result_rotrv_20)) );
678 __ sw(t6, MemOperand(a0, OFFSET_OF(T, result_rotrv_24)) );
679 __ sw(t7, MemOperand(a0, OFFSET_OF(T, result_rotrv_28)) );
686 Handle<Code> code = isolate->factory()->NewCode(
687 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
688 F3 f = FUNCTION_CAST<F3>(code->entry());
689 t.input = 0x12345678;
690 Object* dummy = CALL_GENERATED_CODE(f, &t, 0x0, 0, 0, 0);
692 CHECK_EQ(0x81234567, t.result_rotr_4);
693 CHECK_EQ(0x78123456, t.result_rotr_8);
694 CHECK_EQ(0x67812345, t.result_rotr_12);
695 CHECK_EQ(0x56781234, t.result_rotr_16);
696 CHECK_EQ(0x45678123, t.result_rotr_20);
697 CHECK_EQ(0x34567812, t.result_rotr_24);
698 CHECK_EQ(0x23456781, t.result_rotr_28);
700 CHECK_EQ(0x81234567, t.result_rotrv_4);
701 CHECK_EQ(0x78123456, t.result_rotrv_8);
702 CHECK_EQ(0x67812345, t.result_rotrv_12);
703 CHECK_EQ(0x56781234, t.result_rotrv_16);
704 CHECK_EQ(0x45678123, t.result_rotrv_20);
705 CHECK_EQ(0x34567812, t.result_rotrv_24);
706 CHECK_EQ(0x23456781, t.result_rotrv_28);
711 // Test BRANCH improvements.
712 CcTest::InitializeVM();
713 Isolate* isolate = CcTest::i_isolate();
714 HandleScope scope(isolate);
716 MacroAssembler assm(isolate, NULL, 0);
717 Label exit, exit2, exit3;
719 __ Branch(&exit, ge, a0, Operand(0x00000000));
720 __ Branch(&exit2, ge, a0, Operand(0x00001FFF));
721 __ Branch(&exit3, ge, a0, Operand(0x0001FFFF));
731 isolate->factory()->NewCode(
732 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
737 // Test conversions between doubles and long integers.
738 // Test hos the long ints map to FP regs pairs.
739 CcTest::InitializeVM();
740 Isolate* isolate = CcTest::i_isolate();
741 HandleScope scope(isolate);
753 Assembler assm(isolate, NULL, 0);
756 if (kArchVariant == kMips32r2) {
757 // Load all structure elements to registers.
758 __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, a)));
760 // Save the raw bits of the double.
763 __ sw(t0, MemOperand(a0, OFFSET_OF(T, dbl_mant)));
764 __ sw(t1, MemOperand(a0, OFFSET_OF(T, dbl_exp)));
766 // Convert double in f0 to long, save hi/lo parts.
768 __ mfc1(t0, f0); // f0 has a 32-bits word.
769 __ sw(t0, MemOperand(a0, OFFSET_OF(T, word)));
771 // Convert the b long integers to double b.
772 __ lw(t0, MemOperand(a0, OFFSET_OF(T, b_word)));
773 __ mtc1(t0, f8); // f8 has a 32-bits word.
775 __ sdc1(f10, MemOperand(a0, OFFSET_OF(T, b)));
782 Handle<Code> code = isolate->factory()->NewCode(
783 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
784 F3 f = FUNCTION_CAST<F3>(code->entry());
785 t.a = 2.147483646e+09; // 0x7FFFFFFE -> 0xFF80000041DFFFFF as double.
786 t.b_word = 0x0ff00ff0; // 0x0FF00FF0 -> 0x as double.
787 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
790 CHECK_EQ(0x41DFFFFF, t.dbl_exp);
791 CHECK_EQ(0xFF800000, t.dbl_mant);
792 CHECK_EQ(0X7FFFFFFE, t.word);
793 // 0x0FF00FF0 -> 2.6739096+e08
794 CHECK_EQ(2.6739096e08, t.b);
800 // Test LWL, LWR, SWL and SWR instructions.
801 CcTest::InitializeVM();
802 Isolate* isolate = CcTest::i_isolate();
803 HandleScope scope(isolate);
827 Assembler assm(isolate, NULL, 0);
829 // Test all combinations of LWL and vAddr.
830 __ lw(t0, MemOperand(a0, OFFSET_OF(T, reg_init)) );
831 __ lwl(t0, MemOperand(a0, OFFSET_OF(T, mem_init)) );
832 __ sw(t0, MemOperand(a0, OFFSET_OF(T, lwl_0)) );
834 __ lw(t1, MemOperand(a0, OFFSET_OF(T, reg_init)) );
835 __ lwl(t1, MemOperand(a0, OFFSET_OF(T, mem_init) + 1) );
836 __ sw(t1, MemOperand(a0, OFFSET_OF(T, lwl_1)) );
838 __ lw(t2, MemOperand(a0, OFFSET_OF(T, reg_init)) );
839 __ lwl(t2, MemOperand(a0, OFFSET_OF(T, mem_init) + 2) );
840 __ sw(t2, MemOperand(a0, OFFSET_OF(T, lwl_2)) );
842 __ lw(t3, MemOperand(a0, OFFSET_OF(T, reg_init)) );
843 __ lwl(t3, MemOperand(a0, OFFSET_OF(T, mem_init) + 3) );
844 __ sw(t3, MemOperand(a0, OFFSET_OF(T, lwl_3)) );
846 // Test all combinations of LWR and vAddr.
847 __ lw(t0, MemOperand(a0, OFFSET_OF(T, reg_init)) );
848 __ lwr(t0, MemOperand(a0, OFFSET_OF(T, mem_init)) );
849 __ sw(t0, MemOperand(a0, OFFSET_OF(T, lwr_0)) );
851 __ lw(t1, MemOperand(a0, OFFSET_OF(T, reg_init)) );
852 __ lwr(t1, MemOperand(a0, OFFSET_OF(T, mem_init) + 1) );
853 __ sw(t1, MemOperand(a0, OFFSET_OF(T, lwr_1)) );
855 __ lw(t2, MemOperand(a0, OFFSET_OF(T, reg_init)) );
856 __ lwr(t2, MemOperand(a0, OFFSET_OF(T, mem_init) + 2) );
857 __ sw(t2, MemOperand(a0, OFFSET_OF(T, lwr_2)) );
859 __ lw(t3, MemOperand(a0, OFFSET_OF(T, reg_init)) );
860 __ lwr(t3, MemOperand(a0, OFFSET_OF(T, mem_init) + 3) );
861 __ sw(t3, MemOperand(a0, OFFSET_OF(T, lwr_3)) );
863 // Test all combinations of SWL and vAddr.
864 __ lw(t0, MemOperand(a0, OFFSET_OF(T, mem_init)) );
865 __ sw(t0, MemOperand(a0, OFFSET_OF(T, swl_0)) );
866 __ lw(t0, MemOperand(a0, OFFSET_OF(T, reg_init)) );
867 __ swl(t0, MemOperand(a0, OFFSET_OF(T, swl_0)) );
869 __ lw(t1, MemOperand(a0, OFFSET_OF(T, mem_init)) );
870 __ sw(t1, MemOperand(a0, OFFSET_OF(T, swl_1)) );
871 __ lw(t1, MemOperand(a0, OFFSET_OF(T, reg_init)) );
872 __ swl(t1, MemOperand(a0, OFFSET_OF(T, swl_1) + 1) );
874 __ lw(t2, MemOperand(a0, OFFSET_OF(T, mem_init)) );
875 __ sw(t2, MemOperand(a0, OFFSET_OF(T, swl_2)) );
876 __ lw(t2, MemOperand(a0, OFFSET_OF(T, reg_init)) );
877 __ swl(t2, MemOperand(a0, OFFSET_OF(T, swl_2) + 2) );
879 __ lw(t3, MemOperand(a0, OFFSET_OF(T, mem_init)) );
880 __ sw(t3, MemOperand(a0, OFFSET_OF(T, swl_3)) );
881 __ lw(t3, MemOperand(a0, OFFSET_OF(T, reg_init)) );
882 __ swl(t3, MemOperand(a0, OFFSET_OF(T, swl_3) + 3) );
884 // Test all combinations of SWR and vAddr.
885 __ lw(t0, MemOperand(a0, OFFSET_OF(T, mem_init)) );
886 __ sw(t0, MemOperand(a0, OFFSET_OF(T, swr_0)) );
887 __ lw(t0, MemOperand(a0, OFFSET_OF(T, reg_init)) );
888 __ swr(t0, MemOperand(a0, OFFSET_OF(T, swr_0)) );
890 __ lw(t1, MemOperand(a0, OFFSET_OF(T, mem_init)) );
891 __ sw(t1, MemOperand(a0, OFFSET_OF(T, swr_1)) );
892 __ lw(t1, MemOperand(a0, OFFSET_OF(T, reg_init)) );
893 __ swr(t1, MemOperand(a0, OFFSET_OF(T, swr_1) + 1) );
895 __ lw(t2, MemOperand(a0, OFFSET_OF(T, mem_init)) );
896 __ sw(t2, MemOperand(a0, OFFSET_OF(T, swr_2)) );
897 __ lw(t2, MemOperand(a0, OFFSET_OF(T, reg_init)) );
898 __ swr(t2, MemOperand(a0, OFFSET_OF(T, swr_2) + 2) );
900 __ lw(t3, MemOperand(a0, OFFSET_OF(T, mem_init)) );
901 __ sw(t3, MemOperand(a0, OFFSET_OF(T, swr_3)) );
902 __ lw(t3, MemOperand(a0, OFFSET_OF(T, reg_init)) );
903 __ swr(t3, MemOperand(a0, OFFSET_OF(T, swr_3) + 3) );
910 Handle<Code> code = isolate->factory()->NewCode(
911 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
912 F3 f = FUNCTION_CAST<F3>(code->entry());
913 t.reg_init = 0xaabbccdd;
914 t.mem_init = 0x11223344;
916 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
919 #if __BYTE_ORDER == __LITTLE_ENDIAN
920 CHECK_EQ(0x44bbccdd, t.lwl_0);
921 CHECK_EQ(0x3344ccdd, t.lwl_1);
922 CHECK_EQ(0x223344dd, t.lwl_2);
923 CHECK_EQ(0x11223344, t.lwl_3);
925 CHECK_EQ(0x11223344, t.lwr_0);
926 CHECK_EQ(0xaa112233, t.lwr_1);
927 CHECK_EQ(0xaabb1122, t.lwr_2);
928 CHECK_EQ(0xaabbcc11, t.lwr_3);
930 CHECK_EQ(0x112233aa, t.swl_0);
931 CHECK_EQ(0x1122aabb, t.swl_1);
932 CHECK_EQ(0x11aabbcc, t.swl_2);
933 CHECK_EQ(0xaabbccdd, t.swl_3);
935 CHECK_EQ(0xaabbccdd, t.swr_0);
936 CHECK_EQ(0xbbccdd44, t.swr_1);
937 CHECK_EQ(0xccdd3344, t.swr_2);
938 CHECK_EQ(0xdd223344, t.swr_3);
939 #elif __BYTE_ORDER == __BIG_ENDIAN
940 CHECK_EQ(0x11223344, t.lwl_0);
941 CHECK_EQ(0x223344dd, t.lwl_1);
942 CHECK_EQ(0x3344ccdd, t.lwl_2);
943 CHECK_EQ(0x44bbccdd, t.lwl_3);
945 CHECK_EQ(0xaabbcc11, t.lwr_0);
946 CHECK_EQ(0xaabb1122, t.lwr_1);
947 CHECK_EQ(0xaa112233, t.lwr_2);
948 CHECK_EQ(0x11223344, t.lwr_3);
950 CHECK_EQ(0xaabbccdd, t.swl_0);
951 CHECK_EQ(0x11aabbcc, t.swl_1);
952 CHECK_EQ(0x1122aabb, t.swl_2);
953 CHECK_EQ(0x112233aa, t.swl_3);
955 CHECK_EQ(0xdd223344, t.swr_0);
956 CHECK_EQ(0xccdd3344, t.swr_1);
957 CHECK_EQ(0xbbccdd44, t.swr_2);
958 CHECK_EQ(0xaabbccdd, t.swr_3);
960 #error Unknown endianness
966 CcTest::InitializeVM();
967 Isolate* isolate = CcTest::i_isolate();
968 HandleScope scope(isolate);
980 MacroAssembler assm(isolate, NULL, 0);
982 __ mov(t6, fp); // Save frame pointer.
983 __ mov(fp, a0); // Access struct T by fp.
984 __ lw(t0, MemOperand(a0, OFFSET_OF(T, y)) );
985 __ lw(t3, MemOperand(a0, OFFSET_OF(T, y4)) );
990 __ push(t0); // These instructions disappear after opt.
994 __ Pop(); // These instructions disappear after opt.
997 __ push(t3); // These instructions disappear after opt.
1003 __ sw(t0, MemOperand(fp, OFFSET_OF(T, y)) );
1004 __ lw(t0, MemOperand(fp, OFFSET_OF(T, y)) );
1006 __ sw(t0, MemOperand(fp, OFFSET_OF(T, y)) );
1007 __ lw(t1, MemOperand(fp, OFFSET_OF(T, y)) );
1010 __ lw(t1, MemOperand(fp, OFFSET_OF(T, y)) );
1014 __ lw(t2, MemOperand(fp, OFFSET_OF(T, y)) );
1018 __ lw(t2, MemOperand(fp, OFFSET_OF(T, y)) );
1022 __ lw(t2, MemOperand(fp, OFFSET_OF(T, y)) );
1026 __ lw(t2, MemOperand(fp, OFFSET_OF(T, y)) );
1035 assm.GetCode(&desc);
1036 Handle<Code> code = isolate->factory()->NewCode(
1037 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1038 F3 f = FUNCTION_CAST<F3>(code->entry());
1046 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
1054 // Test Cvt_d_uw and Trunc_uw_d macros.
1055 CcTest::InitializeVM();
1056 Isolate* isolate = CcTest::i_isolate();
1057 HandleScope scope(isolate);
1061 double cvt_small_out;
1062 uint32_t trunc_big_out;
1063 uint32_t trunc_small_out;
1064 uint32_t cvt_big_in;
1065 uint32_t cvt_small_in;
1069 MacroAssembler assm(isolate, NULL, 0);
1071 __ sw(t0, MemOperand(a0, OFFSET_OF(T, cvt_small_in)));
1072 __ Cvt_d_uw(f10, t0, f22);
1073 __ sdc1(f10, MemOperand(a0, OFFSET_OF(T, cvt_small_out)));
1075 __ Trunc_uw_d(f10, f10, f22);
1076 __ swc1(f10, MemOperand(a0, OFFSET_OF(T, trunc_small_out)));
1078 __ sw(t0, MemOperand(a0, OFFSET_OF(T, cvt_big_in)));
1079 __ Cvt_d_uw(f8, t0, f22);
1080 __ sdc1(f8, MemOperand(a0, OFFSET_OF(T, cvt_big_out)));
1082 __ Trunc_uw_d(f8, f8, f22);
1083 __ swc1(f8, MemOperand(a0, OFFSET_OF(T, trunc_big_out)));
1089 assm.GetCode(&desc);
1090 Handle<Code> code = isolate->factory()->NewCode(
1091 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1092 F3 f = FUNCTION_CAST<F3>(code->entry());
1094 t.cvt_big_in = 0xFFFFFFFF;
1095 t.cvt_small_in = 333;
1097 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
1100 CHECK_EQ(t.cvt_big_out, static_cast<double>(t.cvt_big_in));
1101 CHECK_EQ(t.cvt_small_out, static_cast<double>(t.cvt_small_in));
1103 CHECK_EQ(static_cast<int>(t.trunc_big_out), static_cast<int>(t.cvt_big_in));
1104 CHECK_EQ(static_cast<int>(t.trunc_small_out),
1105 static_cast<int>(t.cvt_small_in));
1110 // Test round, floor, ceil, trunc, cvt.
1111 CcTest::InitializeVM();
1112 Isolate* isolate = CcTest::i_isolate();
1113 HandleScope scope(isolate);
1115 #define ROUND_STRUCT_ELEMENT(x) \
1116 int32_t x##_up_out; \
1117 int32_t x##_down_out; \
1118 int32_t neg_##x##_up_out; \
1119 int32_t neg_##x##_down_out; \
1120 uint32_t x##_err1_out; \
1121 uint32_t x##_err2_out; \
1122 uint32_t x##_err3_out; \
1123 uint32_t x##_err4_out; \
1124 int32_t x##_invalid_result;
1128 double round_down_in;
1129 double neg_round_up_in;
1130 double neg_round_down_in;
1136 ROUND_STRUCT_ELEMENT(round)
1137 ROUND_STRUCT_ELEMENT(floor)
1138 ROUND_STRUCT_ELEMENT(ceil)
1139 ROUND_STRUCT_ELEMENT(trunc)
1140 ROUND_STRUCT_ELEMENT(cvt)
1144 #undef ROUND_STRUCT_ELEMENT
1146 MacroAssembler assm(isolate, NULL, 0);
1150 // Disable FPU exceptions.
1151 __ ctc1(zero_reg, FCSR);
1152 #define RUN_ROUND_TEST(x) \
1153 __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, round_up_in))); \
1154 __ x##_w_d(f0, f0); \
1155 __ swc1(f0, MemOperand(a0, OFFSET_OF(T, x##_up_out))); \
1157 __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, round_down_in))); \
1158 __ x##_w_d(f0, f0); \
1159 __ swc1(f0, MemOperand(a0, OFFSET_OF(T, x##_down_out))); \
1161 __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, neg_round_up_in))); \
1162 __ x##_w_d(f0, f0); \
1163 __ swc1(f0, MemOperand(a0, OFFSET_OF(T, neg_##x##_up_out))); \
1165 __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, neg_round_down_in))); \
1166 __ x##_w_d(f0, f0); \
1167 __ swc1(f0, MemOperand(a0, OFFSET_OF(T, neg_##x##_down_out))); \
1169 __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, err1_in))); \
1170 __ ctc1(zero_reg, FCSR); \
1171 __ x##_w_d(f0, f0); \
1172 __ cfc1(a2, FCSR); \
1173 __ sw(a2, MemOperand(a0, OFFSET_OF(T, x##_err1_out))); \
1175 __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, err2_in))); \
1176 __ ctc1(zero_reg, FCSR); \
1177 __ x##_w_d(f0, f0); \
1178 __ cfc1(a2, FCSR); \
1179 __ sw(a2, MemOperand(a0, OFFSET_OF(T, x##_err2_out))); \
1181 __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, err3_in))); \
1182 __ ctc1(zero_reg, FCSR); \
1183 __ x##_w_d(f0, f0); \
1184 __ cfc1(a2, FCSR); \
1185 __ sw(a2, MemOperand(a0, OFFSET_OF(T, x##_err3_out))); \
1187 __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, err4_in))); \
1188 __ ctc1(zero_reg, FCSR); \
1189 __ x##_w_d(f0, f0); \
1190 __ cfc1(a2, FCSR); \
1191 __ sw(a2, MemOperand(a0, OFFSET_OF(T, x##_err4_out))); \
1192 __ swc1(f0, MemOperand(a0, OFFSET_OF(T, x##_invalid_result)));
1194 RUN_ROUND_TEST(round)
1195 RUN_ROUND_TEST(floor)
1196 RUN_ROUND_TEST(ceil)
1197 RUN_ROUND_TEST(trunc)
1207 assm.GetCode(&desc);
1208 Handle<Code> code = isolate->factory()->NewCode(
1209 desc, Code::ComputeFlags(Code::STUB), Handle<Code>());
1210 F3 f = FUNCTION_CAST<F3>(code->entry());
1212 t.round_up_in = 123.51;
1213 t.round_down_in = 123.49;
1214 t.neg_round_up_in = -123.5;
1215 t.neg_round_down_in = -123.49;
1218 t.err3_in = static_cast<double>(1) + 0xFFFFFFFF;
1221 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0);
1224 #define GET_FPU_ERR(x) (static_cast<int>(x & kFCSRFlagMask))
1225 #define CHECK_ROUND_RESULT(type) \
1226 CHECK(GET_FPU_ERR(t.type##_err1_out) & kFCSRInexactFlagMask); \
1227 CHECK_EQ(0, GET_FPU_ERR(t.type##_err2_out)); \
1228 CHECK(GET_FPU_ERR(t.type##_err3_out) & kFCSRInvalidOpFlagMask); \
1229 CHECK(GET_FPU_ERR(t.type##_err4_out) & kFCSRInvalidOpFlagMask); \
1230 CHECK_EQ(kFPUInvalidResult, t.type##_invalid_result);
1232 CHECK_ROUND_RESULT(round);
1233 CHECK_ROUND_RESULT(floor);
1234 CHECK_ROUND_RESULT(ceil);
1235 CHECK_ROUND_RESULT(cvt);
1240 // Test chaining of label usages within instructions (issue 1644).
1241 CcTest::InitializeVM();
1242 Isolate* isolate = CcTest::i_isolate();
1243 HandleScope scope(isolate);
1244 Assembler assm(isolate, NULL, 0);
1247 __ beq(v0, v1, &target);
1249 __ bne(v0, v1, &target);