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 4// met: 5// 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. 15// 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. 27 28#include "src/v8.h" 29 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" 35 36#include "test/cctest/cctest.h" 37 38using namespace v8::internal; 39 40 41// Define these function prototypes to match JSEntryFunction in execution.cc. 42typedef Object* (*F1)(int x, int p1, int p2, int p3, int p4); 43typedef Object* (*F2)(int x, int y, int p2, int p3, int p4); 44typedef Object* (*F3)(void* p, int p1, int p2, int p3, int p4); 45 46 47#define __ assm. 48 49 50TEST(MIPS0) { 51 CcTest::InitializeVM(); 52 Isolate* isolate = CcTest::i_isolate(); 53 HandleScope scope(isolate); 54 55 MacroAssembler assm(isolate, NULL, 0); 56 57 // Addition. 58 __ addu(v0, a0, a1); 59 __ jr(ra); 60 __ nop(); 61 62 CodeDesc desc; 63 assm.GetCode(&desc); 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); 69 CHECK_EQ(0xabc, res); 70} 71 72 73TEST(MIPS1) { 74 CcTest::InitializeVM(); 75 Isolate* isolate = CcTest::i_isolate(); 76 HandleScope scope(isolate); 77 78 MacroAssembler assm(isolate, NULL, 0); 79 Label L, C; 80 81 __ mov(a1, a0); 82 __ li(v0, 0); 83 __ b(&C); 84 __ nop(); 85 86 __ bind(&L); 87 __ addu(v0, v0, a1); 88 __ addiu(a1, a1, -1); 89 90 __ bind(&C); 91 __ xori(v1, a1, 0); 92 __ Branch(&L, ne, v1, Operand(0)); 93 __ nop(); 94 95 __ jr(ra); 96 __ nop(); 97 98 CodeDesc desc; 99 assm.GetCode(&desc); 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); 105 CHECK_EQ(1275, res); 106} 107 108 109TEST(MIPS2) { 110 CcTest::InitializeVM(); 111 Isolate* isolate = CcTest::i_isolate(); 112 HandleScope scope(isolate); 113 114 MacroAssembler assm(isolate, NULL, 0); 115 116 Label exit, error; 117 118 // ----- Test all instructions. 119 120 // Test lui, ori, and addiu, used in the li pseudo-instruction. 121 // This way we can then safely load registers with chosen values. 122 123 __ ori(t0, zero_reg, 0); 124 __ lui(t0, 0x1234); 125 __ ori(t0, t0, 0); 126 __ ori(t0, t0, 0x0f0f); 127 __ ori(t0, t0, 0xf0f0); 128 __ addiu(t1, t0, 1); 129 __ addiu(t2, t1, -0x10); 130 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); 140 141 // SPECIAL class. 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)); 149 __ nop(); 150 151 __ addu(v0, t0, t1); // 0x00001238 152 __ subu(v0, v0, t0); // 0x00001234 153 __ Branch(&error, ne, v0, Operand(0x00001234)); 154 __ nop(); 155 __ addu(v1, t3, t0); 156 __ Branch(&error, ne, v1, Operand(0x80000003)); 157 __ nop(); 158 __ subu(v1, t7, t0); // 0x7ffffffc 159 __ Branch(&error, ne, v1, Operand(0x7ffffffc)); 160 __ nop(); 161 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)); 167 __ nop(); 168 169 __ slt(v0, t7, t3); 170 __ Branch(&error, ne, v0, Operand(0x1)); 171 __ nop(); 172 __ sltu(v0, t7, t3); 173 __ Branch(&error, ne, v0, Operand(0x0)); 174 __ nop(); 175 // End of SPECIAL class. 176 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)); 181 __ nop(); 182 __ addiu(v1, t3, 0x1); // 0x80000000 183 __ Branch(&error, ne, v1, Operand(0x80000000)); 184 __ nop(); 185 186 __ slti(v0, t1, 0x00002000); // 0x1 187 __ slti(v0, v0, 0xffff8000); // 0x0 188 __ Branch(&error, ne, v0, Operand(0x0)); 189 __ nop(); 190 __ sltiu(v0, t1, 0x00002000); // 0x1 191 __ sltiu(v0, v0, 0x00008000); // 0x1 192 __ Branch(&error, ne, v0, Operand(0x1)); 193 __ nop(); 194 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)); 199 __ nop(); 200 __ lui(v1, 0x8123); // 0x81230000 201 __ Branch(&error, ne, v1, Operand(0x81230000)); 202 __ nop(); 203 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 209 __ Clz(v1, t2); // 3 210 __ addu(v0, v0, v1); // 51 211 __ Clz(v1, t7); // 0 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)); 222 223 // Everything was correctly executed. Load the expected result. 224 __ li(v0, 0x31415926); 225 __ b(&exit); 226 __ nop(); 227 228 __ bind(&error); 229 // Got an error. Return a wrong result. 230 __ li(v0, 666); 231 232 __ bind(&exit); 233 __ jr(ra); 234 __ nop(); 235 236 CodeDesc desc; 237 assm.GetCode(&desc); 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); 244} 245 246 247TEST(MIPS3) { 248 // Test floating point instructions. 249 CcTest::InitializeVM(); 250 Isolate* isolate = CcTest::i_isolate(); 251 HandleScope scope(isolate); 252 253 typedef struct { 254 double a; 255 double b; 256 double c; 257 double d; 258 double e; 259 double f; 260 double g; 261 double h; 262 double i; 263 } T; 264 T t; 265 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); 269 Label L, C; 270 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. 275 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). 280 281 __ sdc1(f4, MemOperand(a0, OFFSET_OF(T, b)) ); // b = a. 282 283 __ li(t0, 120); 284 __ mtc1(t0, f14); 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. 288 289 __ div_d(f12, f10, f4); 290 __ sdc1(f12, MemOperand(a0, OFFSET_OF(T, f)) ); // f = e / a = 120.44. 291 292 __ sqrt_d(f14, f12); 293 __ sdc1(f14, MemOperand(a0, OFFSET_OF(T, g)) ); 294 // g = sqrt(f) = 10.97451593465515908537 295 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)) ); 301 } 302 303 __ jr(ra); 304 __ nop(); 305 306 CodeDesc desc; 307 assm.GetCode(&desc); 308 Handle<Code> code = isolate->factory()->NewCode( 309 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 310 F3 f = FUNCTION_CAST<F3>(code->entry()); 311 t.a = 1.5e14; 312 t.b = 2.75e11; 313 t.c = 0.0; 314 t.d = 0.0; 315 t.e = 0.0; 316 t.f = 0.0; 317 t.h = 1.5; 318 t.i = 2.75; 319 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); 320 USE(dummy); 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); 330 } 331} 332 333 334TEST(MIPS4) { 335 // Test moves between floating point and integer registers. 336 CcTest::InitializeVM(); 337 Isolate* isolate = CcTest::i_isolate(); 338 HandleScope scope(isolate); 339 340 typedef struct { 341 double a; 342 double b; 343 double c; 344 } T; 345 T t; 346 347 Assembler assm(isolate, NULL, 0); 348 Label L, C; 349 350 __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, a)) ); 351 __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, b)) ); 352 353 // Swap f4 and f6, by using four integer registers, t0-t3. 354 __ mfc1(t0, f4); 355 __ mfc1(t1, f5); 356 __ mfc1(t2, f6); 357 __ mfc1(t3, f7); 358 359 __ mtc1(t0, f6); 360 __ mtc1(t1, f7); 361 __ mtc1(t2, f4); 362 __ mtc1(t3, f5); 363 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)) ); 367 368 __ jr(ra); 369 __ nop(); 370 371 CodeDesc desc; 372 assm.GetCode(&desc); 373 Handle<Code> code = isolate->factory()->NewCode( 374 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 375 F3 f = FUNCTION_CAST<F3>(code->entry()); 376 t.a = 1.5e22; 377 t.b = 2.75e11; 378 t.c = 17.17; 379 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); 380 USE(dummy); 381 382 CHECK_EQ(2.75e11, t.a); 383 CHECK_EQ(2.75e11, t.b); 384 CHECK_EQ(1.5e22, t.c); 385} 386 387 388TEST(MIPS5) { 389 // Test conversions between doubles and integers. 390 CcTest::InitializeVM(); 391 Isolate* isolate = CcTest::i_isolate(); 392 HandleScope scope(isolate); 393 394 typedef struct { 395 double a; 396 double b; 397 int i; 398 int j; 399 } T; 400 T t; 401 402 Assembler assm(isolate, NULL, 0); 403 Label L, C; 404 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)) ); 410 411 // Convert double in f4 to int in element i. 412 __ cvt_w_d(f8, f4); 413 __ mfc1(t2, f8); 414 __ sw(t2, MemOperand(a0, OFFSET_OF(T, i)) ); 415 416 // Convert double in f6 to int in element j. 417 __ cvt_w_d(f10, f6); 418 __ mfc1(t3, f10); 419 __ sw(t3, MemOperand(a0, OFFSET_OF(T, j)) ); 420 421 // Convert int in original i (t0) to double in a. 422 __ mtc1(t0, f12); 423 __ cvt_d_w(f0, f12); 424 __ sdc1(f0, MemOperand(a0, OFFSET_OF(T, a)) ); 425 426 // Convert int in original j (t1) to double in b. 427 __ mtc1(t1, f14); 428 __ cvt_d_w(f2, f14); 429 __ sdc1(f2, MemOperand(a0, OFFSET_OF(T, b)) ); 430 431 __ jr(ra); 432 __ nop(); 433 434 CodeDesc desc; 435 assm.GetCode(&desc); 436 Handle<Code> code = isolate->factory()->NewCode( 437 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 438 F3 f = FUNCTION_CAST<F3>(code->entry()); 439 t.a = 1.5e4; 440 t.b = 2.75e8; 441 t.i = 12345678; 442 t.j = -100000; 443 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); 444 USE(dummy); 445 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); 450} 451 452 453TEST(MIPS6) { 454 // Test simple memory loads and stores. 455 CcTest::InitializeVM(); 456 Isolate* isolate = CcTest::i_isolate(); 457 HandleScope scope(isolate); 458 459 typedef struct { 460 uint32_t ui; 461 int32_t si; 462 int32_t r1; 463 int32_t r2; 464 int32_t r3; 465 int32_t r4; 466 int32_t r5; 467 int32_t r6; 468 } T; 469 T t; 470 471 Assembler assm(isolate, NULL, 0); 472 Label L, C; 473 474 // Basic word load/store. 475 __ lw(t0, MemOperand(a0, OFFSET_OF(T, ui)) ); 476 __ sw(t0, MemOperand(a0, OFFSET_OF(T, r1)) ); 477 478 // lh with positive data. 479 __ lh(t1, MemOperand(a0, OFFSET_OF(T, ui)) ); 480 __ sw(t1, MemOperand(a0, OFFSET_OF(T, r2)) ); 481 482 // lh with negative data. 483 __ lh(t2, MemOperand(a0, OFFSET_OF(T, si)) ); 484 __ sw(t2, MemOperand(a0, OFFSET_OF(T, r3)) ); 485 486 // lhu with negative data. 487 __ lhu(t3, MemOperand(a0, OFFSET_OF(T, si)) ); 488 __ sw(t3, MemOperand(a0, OFFSET_OF(T, r4)) ); 489 490 // lb with negative data. 491 __ lb(t4, MemOperand(a0, OFFSET_OF(T, si)) ); 492 __ sw(t4, MemOperand(a0, OFFSET_OF(T, r5)) ); 493 494 // sh writes only 1/2 of word. 495 __ lui(t5, 0x3333); 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)) ); 500 501 __ jr(ra); 502 __ nop(); 503 504 CodeDesc desc; 505 assm.GetCode(&desc); 506 Handle<Code> code = isolate->factory()->NewCode( 507 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 508 F3 f = FUNCTION_CAST<F3>(code->entry()); 509 t.ui = 0x11223344; 510 t.si = 0x99aabbcc; 511 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); 512 USE(dummy); 513 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); 527#else 528#error Unknown endianness 529#endif 530} 531 532 533TEST(MIPS7) { 534 // Test floating point compare and branch instructions. 535 CcTest::InitializeVM(); 536 Isolate* isolate = CcTest::i_isolate(); 537 HandleScope scope(isolate); 538 539 typedef struct { 540 double a; 541 double b; 542 double c; 543 double d; 544 double e; 545 double f; 546 int32_t result; 547 } T; 548 T t; 549 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; 554 555 __ ldc1(f4, MemOperand(a0, OFFSET_OF(T, a)) ); 556 __ ldc1(f6, MemOperand(a0, OFFSET_OF(T, b)) ); 557 __ c(UN, D, f4, f6); 558 __ bc1f(&neither_is_nan); 559 __ nop(); 560 __ sw(zero_reg, MemOperand(a0, OFFSET_OF(T, result)) ); 561 __ Branch(&outa_here); 562 563 __ bind(&neither_is_nan); 564 565 if (kArchVariant == kLoongson) { 566 __ c(OLT, D, f6, f4); 567 __ bc1t(&less_than); 568 } else { 569 __ c(OLT, D, f6, f4, 2); 570 __ bc1t(&less_than, 2); 571 } 572 __ nop(); 573 __ sw(zero_reg, MemOperand(a0, OFFSET_OF(T, result)) ); 574 __ Branch(&outa_here); 575 576 __ bind(&less_than); 577 __ Addu(t0, zero_reg, Operand(1)); 578 __ sw(t0, MemOperand(a0, OFFSET_OF(T, result)) ); // Set true. 579 580 581 // This test-case should have additional tests. 582 583 __ bind(&outa_here); 584 585 __ jr(ra); 586 __ nop(); 587 588 CodeDesc desc; 589 assm.GetCode(&desc); 590 Handle<Code> code = isolate->factory()->NewCode( 591 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 592 F3 f = FUNCTION_CAST<F3>(code->entry()); 593 t.a = 1.5e14; 594 t.b = 2.75e11; 595 t.c = 2.0; 596 t.d = -4.0; 597 t.e = 0.0; 598 t.f = 0.0; 599 t.result = 0; 600 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); 601 USE(dummy); 602 CHECK_EQ(1.5e14, t.a); 603 CHECK_EQ(2.75e11, t.b); 604 CHECK_EQ(1, t.result); 605} 606 607 608TEST(MIPS8) { 609 // Test ROTR and ROTRV instructions. 610 CcTest::InitializeVM(); 611 Isolate* isolate = CcTest::i_isolate(); 612 HandleScope scope(isolate); 613 614 typedef struct { 615 int32_t input; 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; 630 } T; 631 T t; 632 633 MacroAssembler assm(isolate, NULL, 0); 634 635 // Basic word load. 636 __ lw(t0, MemOperand(a0, OFFSET_OF(T, input)) ); 637 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); 646 647 // Basic word store. 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)) ); 655 656 // ROTRV instruction (called through the Ror macro). 657 __ li(t7, 0x0004); 658 __ Ror(t1, t0, t7); 659 __ li(t7, 0x0008); 660 __ Ror(t2, t0, t7); 661 __ li(t7, 0x000C); 662 __ Ror(t3, t0, t7); 663 __ li(t7, 0x0010); 664 __ Ror(t4, t0, t7); 665 __ li(t7, 0x0014); 666 __ Ror(t5, t0, t7); 667 __ li(t7, 0x0018); 668 __ Ror(t6, t0, t7); 669 __ li(t7, 0x001C); 670 __ Ror(t7, t0, t7); 671 672 // Basic word store. 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)) ); 680 681 __ jr(ra); 682 __ nop(); 683 684 CodeDesc desc; 685 assm.GetCode(&desc); 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); 691 USE(dummy); 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); 699 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); 707} 708 709 710TEST(MIPS9) { 711 // Test BRANCH improvements. 712 CcTest::InitializeVM(); 713 Isolate* isolate = CcTest::i_isolate(); 714 HandleScope scope(isolate); 715 716 MacroAssembler assm(isolate, NULL, 0); 717 Label exit, exit2, exit3; 718 719 __ Branch(&exit, ge, a0, Operand(0x00000000)); 720 __ Branch(&exit2, ge, a0, Operand(0x00001FFF)); 721 __ Branch(&exit3, ge, a0, Operand(0x0001FFFF)); 722 723 __ bind(&exit); 724 __ bind(&exit2); 725 __ bind(&exit3); 726 __ jr(ra); 727 __ nop(); 728 729 CodeDesc desc; 730 assm.GetCode(&desc); 731 isolate->factory()->NewCode( 732 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 733} 734 735 736TEST(MIPS10) { 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); 742 743 typedef struct { 744 double a; 745 double b; 746 int32_t dbl_mant; 747 int32_t dbl_exp; 748 int32_t word; 749 int32_t b_word; 750 } T; 751 T t; 752 753 Assembler assm(isolate, NULL, 0); 754 Label L, C; 755 756 if (kArchVariant == kMips32r2) { 757 // Load all structure elements to registers. 758 __ ldc1(f0, MemOperand(a0, OFFSET_OF(T, a))); 759 760 // Save the raw bits of the double. 761 __ mfc1(t0, f0); 762 __ mfc1(t1, f1); 763 __ sw(t0, MemOperand(a0, OFFSET_OF(T, dbl_mant))); 764 __ sw(t1, MemOperand(a0, OFFSET_OF(T, dbl_exp))); 765 766 // Convert double in f0 to long, save hi/lo parts. 767 __ cvt_w_d(f0, f0); 768 __ mfc1(t0, f0); // f0 has a 32-bits word. 769 __ sw(t0, MemOperand(a0, OFFSET_OF(T, word))); 770 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. 774 __ cvt_d_w(f10, f8); 775 __ sdc1(f10, MemOperand(a0, OFFSET_OF(T, b))); 776 777 __ jr(ra); 778 __ nop(); 779 780 CodeDesc desc; 781 assm.GetCode(&desc); 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); 788 USE(dummy); 789 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); 795 } 796} 797 798 799TEST(MIPS11) { 800 // Test LWL, LWR, SWL and SWR instructions. 801 CcTest::InitializeVM(); 802 Isolate* isolate = CcTest::i_isolate(); 803 HandleScope scope(isolate); 804 805 typedef struct { 806 int32_t reg_init; 807 int32_t mem_init; 808 int32_t lwl_0; 809 int32_t lwl_1; 810 int32_t lwl_2; 811 int32_t lwl_3; 812 int32_t lwr_0; 813 int32_t lwr_1; 814 int32_t lwr_2; 815 int32_t lwr_3; 816 int32_t swl_0; 817 int32_t swl_1; 818 int32_t swl_2; 819 int32_t swl_3; 820 int32_t swr_0; 821 int32_t swr_1; 822 int32_t swr_2; 823 int32_t swr_3; 824 } T; 825 T t; 826 827 Assembler assm(isolate, NULL, 0); 828 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)) ); 833 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)) ); 837 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)) ); 841 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)) ); 845 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)) ); 850 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)) ); 854 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)) ); 858 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)) ); 862 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)) ); 868 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) ); 873 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) ); 878 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) ); 883 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)) ); 889 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) ); 894 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) ); 899 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) ); 904 905 __ jr(ra); 906 __ nop(); 907 908 CodeDesc desc; 909 assm.GetCode(&desc); 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; 915 916 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); 917 USE(dummy); 918 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); 924 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); 929 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); 934 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); 944 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); 949 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); 954 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); 959#else 960#error Unknown endianness 961#endif 962} 963 964 965TEST(MIPS12) { 966 CcTest::InitializeVM(); 967 Isolate* isolate = CcTest::i_isolate(); 968 HandleScope scope(isolate); 969 970 typedef struct { 971 int32_t x; 972 int32_t y; 973 int32_t y1; 974 int32_t y2; 975 int32_t y3; 976 int32_t y4; 977 } T; 978 T t; 979 980 MacroAssembler assm(isolate, NULL, 0); 981 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)) ); 986 987 __ addu(t1, t0, t3); 988 __ subu(t4, t0, t3); 989 __ nop(); 990 __ push(t0); // These instructions disappear after opt. 991 __ Pop(); 992 __ addu(t0, t0, t0); 993 __ nop(); 994 __ Pop(); // These instructions disappear after opt. 995 __ push(t3); 996 __ nop(); 997 __ push(t3); // These instructions disappear after opt. 998 __ pop(t3); 999 __ nop(); 1000 __ push(t3); 1001 __ pop(t4); 1002 __ nop(); 1003 __ sw(t0, MemOperand(fp, OFFSET_OF(T, y)) ); 1004 __ lw(t0, MemOperand(fp, OFFSET_OF(T, y)) ); 1005 __ nop(); 1006 __ sw(t0, MemOperand(fp, OFFSET_OF(T, y)) ); 1007 __ lw(t1, MemOperand(fp, OFFSET_OF(T, y)) ); 1008 __ nop(); 1009 __ push(t1); 1010 __ lw(t1, MemOperand(fp, OFFSET_OF(T, y)) ); 1011 __ pop(t1); 1012 __ nop(); 1013 __ push(t1); 1014 __ lw(t2, MemOperand(fp, OFFSET_OF(T, y)) ); 1015 __ pop(t1); 1016 __ nop(); 1017 __ push(t1); 1018 __ lw(t2, MemOperand(fp, OFFSET_OF(T, y)) ); 1019 __ pop(t2); 1020 __ nop(); 1021 __ push(t2); 1022 __ lw(t2, MemOperand(fp, OFFSET_OF(T, y)) ); 1023 __ pop(t1); 1024 __ nop(); 1025 __ push(t1); 1026 __ lw(t2, MemOperand(fp, OFFSET_OF(T, y)) ); 1027 __ pop(t3); 1028 __ nop(); 1029 1030 __ mov(fp, t6); 1031 __ jr(ra); 1032 __ nop(); 1033 1034 CodeDesc desc; 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()); 1039 t.x = 1; 1040 t.y = 2; 1041 t.y1 = 3; 1042 t.y2 = 4; 1043 t.y3 = 0XBABA; 1044 t.y4 = 0xDEDA; 1045 1046 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); 1047 USE(dummy); 1048 1049 CHECK_EQ(3, t.y1); 1050} 1051 1052 1053TEST(MIPS13) { 1054 // Test Cvt_d_uw and Trunc_uw_d macros. 1055 CcTest::InitializeVM(); 1056 Isolate* isolate = CcTest::i_isolate(); 1057 HandleScope scope(isolate); 1058 1059 typedef struct { 1060 double cvt_big_out; 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; 1066 } T; 1067 T t; 1068 1069 MacroAssembler assm(isolate, NULL, 0); 1070 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))); 1074 1075 __ Trunc_uw_d(f10, f10, f22); 1076 __ swc1(f10, MemOperand(a0, OFFSET_OF(T, trunc_small_out))); 1077 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))); 1081 1082 __ Trunc_uw_d(f8, f8, f22); 1083 __ swc1(f8, MemOperand(a0, OFFSET_OF(T, trunc_big_out))); 1084 1085 __ jr(ra); 1086 __ nop(); 1087 1088 CodeDesc desc; 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()); 1093 1094 t.cvt_big_in = 0xFFFFFFFF; 1095 t.cvt_small_in = 333; 1096 1097 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); 1098 USE(dummy); 1099 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)); 1102 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)); 1106} 1107 1108 1109TEST(MIPS14) { 1110 // Test round, floor, ceil, trunc, cvt. 1111 CcTest::InitializeVM(); 1112 Isolate* isolate = CcTest::i_isolate(); 1113 HandleScope scope(isolate); 1114 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; 1125 1126 typedef struct { 1127 double round_up_in; 1128 double round_down_in; 1129 double neg_round_up_in; 1130 double neg_round_down_in; 1131 double err1_in; 1132 double err2_in; 1133 double err3_in; 1134 double err4_in; 1135 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) 1141 } T; 1142 T t; 1143 1144#undef ROUND_STRUCT_ELEMENT 1145 1146 MacroAssembler assm(isolate, NULL, 0); 1147 1148 // Save FCSR. 1149 __ cfc1(a1, FCSR); 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))); \ 1156 \ 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))); \ 1160 \ 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))); \ 1164 \ 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))); \ 1168 \ 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))); \ 1174 \ 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))); \ 1180 \ 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))); \ 1186 \ 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))); 1193 1194 RUN_ROUND_TEST(round) 1195 RUN_ROUND_TEST(floor) 1196 RUN_ROUND_TEST(ceil) 1197 RUN_ROUND_TEST(trunc) 1198 RUN_ROUND_TEST(cvt) 1199 1200 // Restore FCSR. 1201 __ ctc1(a1, FCSR); 1202 1203 __ jr(ra); 1204 __ nop(); 1205 1206 CodeDesc desc; 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()); 1211 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; 1216 t.err1_in = 123.51; 1217 t.err2_in = 1; 1218 t.err3_in = static_cast<double>(1) + 0xFFFFFFFF; 1219 t.err4_in = NAN; 1220 1221 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); 1222 USE(dummy); 1223 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); 1231 1232 CHECK_ROUND_RESULT(round); 1233 CHECK_ROUND_RESULT(floor); 1234 CHECK_ROUND_RESULT(ceil); 1235 CHECK_ROUND_RESULT(cvt); 1236} 1237 1238 1239TEST(MIPS15) { 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); 1245 1246 Label target; 1247 __ beq(v0, v1, &target); 1248 __ nop(); 1249 __ bne(v0, v1, &target); 1250 __ nop(); 1251 __ bind(&target); 1252 __ nop(); 1253} 1254 1255#undef __ 1256