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 <iostream> // NOLINT(readability/streams) 29 30 #include "src/v8.h" 31 32 #include "src/base/utils/random-number-generator.h" 33 #include "src/disassembler.h" 34 #include "src/factory.h" 35 #include "src/macro-assembler.h" 36 #include "src/mips/macro-assembler-mips.h" 37 #include "src/mips/simulator-mips.h" 38 39 #include "test/cctest/cctest.h" 40 41 42 using namespace v8::internal; 43 44 45 // Define these function prototypes to match JSEntryFunction in execution.cc. 46 typedef Object* (*F1)(int x, int p1, int p2, int p3, int p4); 47 typedef Object* (*F2)(int x, int y, int p2, int p3, int p4); 48 typedef Object* (*F3)(void* p, int p1, int p2, int p3, int p4); 49 50 51 #define __ assm. 52 53 TEST(MIPS0) { 54 CcTest::InitializeVM(); 55 Isolate* isolate = CcTest::i_isolate(); 56 HandleScope scope(isolate); 57 58 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); 59 60 // Addition. 61 __ addu(v0, a0, a1); 62 __ jr(ra); 63 __ nop(); 64 65 CodeDesc desc; 66 assm.GetCode(&desc); 67 Handle<Code> code = isolate->factory()->NewCode( 68 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 69 F2 f = FUNCTION_CAST<F2>(code->entry()); 70 int res = reinterpret_cast<int>( 71 CALL_GENERATED_CODE(isolate, f, 0xab0, 0xc, 0, 0, 0)); 72 CHECK_EQ(static_cast<int32_t>(0xabc), res); 73 } 74 75 76 TEST(MIPS1) { 77 CcTest::InitializeVM(); 78 Isolate* isolate = CcTest::i_isolate(); 79 HandleScope scope(isolate); 80 81 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); 82 Label L, C; 83 84 __ mov(a1, a0); 85 __ li(v0, 0); 86 __ b(&C); 87 __ nop(); 88 89 __ bind(&L); 90 __ addu(v0, v0, a1); 91 __ addiu(a1, a1, -1); 92 93 __ bind(&C); 94 __ xori(v1, a1, 0); 95 __ Branch(&L, ne, v1, Operand(0)); 96 __ nop(); 97 98 __ jr(ra); 99 __ nop(); 100 101 CodeDesc desc; 102 assm.GetCode(&desc); 103 Handle<Code> code = isolate->factory()->NewCode( 104 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 105 F1 f = FUNCTION_CAST<F1>(code->entry()); 106 int res = reinterpret_cast<int>( 107 CALL_GENERATED_CODE(isolate, f, 50, 0, 0, 0, 0)); 108 CHECK_EQ(1275, res); 109 } 110 111 112 TEST(MIPS2) { 113 CcTest::InitializeVM(); 114 Isolate* isolate = CcTest::i_isolate(); 115 HandleScope scope(isolate); 116 117 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); 118 119 Label exit, error; 120 121 // ----- Test all instructions. 122 123 // Test lui, ori, and addiu, used in the li pseudo-instruction. 124 // This way we can then safely load registers with chosen values. 125 126 __ ori(t0, zero_reg, 0); 127 __ lui(t0, 0x1234); 128 __ ori(t0, t0, 0); 129 __ ori(t0, t0, 0x0f0f); 130 __ ori(t0, t0, 0xf0f0); 131 __ addiu(t1, t0, 1); 132 __ addiu(t2, t1, -0x10); 133 134 // Load values in temporary registers. 135 __ li(t0, 0x00000004); 136 __ li(t1, 0x00001234); 137 __ li(t2, 0x12345678); 138 __ li(t3, 0x7fffffff); 139 __ li(t4, 0xfffffffc); 140 __ li(t5, 0xffffedcc); 141 __ li(t6, 0xedcba988); 142 __ li(t7, 0x80000000); 143 144 // SPECIAL class. 145 __ srl(v0, t2, 8); // 0x00123456 146 __ sll(v0, v0, 11); // 0x91a2b000 147 __ sra(v0, v0, 3); // 0xf2345600 148 __ srav(v0, v0, t0); // 0xff234560 149 __ sllv(v0, v0, t0); // 0xf2345600 150 __ srlv(v0, v0, t0); // 0x0f234560 151 __ Branch(&error, ne, v0, Operand(0x0f234560)); 152 __ nop(); 153 154 __ addu(v0, t0, t1); // 0x00001238 155 __ subu(v0, v0, t0); // 0x00001234 156 __ Branch(&error, ne, v0, Operand(0x00001234)); 157 __ nop(); 158 __ addu(v1, t3, t0); 159 __ Branch(&error, ne, v1, Operand(0x80000003)); 160 __ nop(); 161 __ subu(v1, t7, t0); // 0x7ffffffc 162 __ Branch(&error, ne, v1, Operand(0x7ffffffc)); 163 __ nop(); 164 165 __ and_(v0, t1, t2); // 0x00001230 166 __ or_(v0, v0, t1); // 0x00001234 167 __ xor_(v0, v0, t2); // 0x1234444c 168 __ nor(v0, v0, t2); // 0xedcba987 169 __ Branch(&error, ne, v0, Operand(0xedcba983)); 170 __ nop(); 171 172 __ slt(v0, t7, t3); 173 __ Branch(&error, ne, v0, Operand(0x1)); 174 __ nop(); 175 __ sltu(v0, t7, t3); 176 __ Branch(&error, ne, v0, Operand(zero_reg)); 177 __ nop(); 178 // End of SPECIAL class. 179 180 __ addiu(v0, zero_reg, 0x7421); // 0x00007421 181 __ addiu(v0, v0, -0x1); // 0x00007420 182 __ addiu(v0, v0, -0x20); // 0x00007400 183 __ Branch(&error, ne, v0, Operand(0x00007400)); 184 __ nop(); 185 __ addiu(v1, t3, 0x1); // 0x80000000 186 __ Branch(&error, ne, v1, Operand(0x80000000)); 187 __ nop(); 188 189 __ slti(v0, t1, 0x00002000); // 0x1 190 __ slti(v0, v0, 0xffff8000); // 0x0 191 __ Branch(&error, ne, v0, Operand(zero_reg)); 192 __ nop(); 193 __ sltiu(v0, t1, 0x00002000); // 0x1 194 __ sltiu(v0, v0, 0x00008000); // 0x1 195 __ Branch(&error, ne, v0, Operand(0x1)); 196 __ nop(); 197 198 __ andi(v0, t1, 0xf0f0); // 0x00001030 199 __ ori(v0, v0, 0x8a00); // 0x00009a30 200 __ xori(v0, v0, 0x83cc); // 0x000019fc 201 __ Branch(&error, ne, v0, Operand(0x000019fc)); 202 __ nop(); 203 __ lui(v1, 0x8123); // 0x81230000 204 __ Branch(&error, ne, v1, Operand(0x81230000)); 205 __ nop(); 206 207 // Bit twiddling instructions & conditional moves. 208 // Uses t0-t7 as set above. 209 __ Clz(v0, t0); // 29 210 __ Clz(v1, t1); // 19 211 __ addu(v0, v0, v1); // 48 212 __ Clz(v1, t2); // 3 213 __ addu(v0, v0, v1); // 51 214 __ Clz(v1, t7); // 0 215 __ addu(v0, v0, v1); // 51 216 __ Branch(&error, ne, v0, Operand(51)); 217 __ Movn(a0, t3, t0); // Move a0<-t3 (t0 is NOT 0). 218 __ Ins(a0, t1, 12, 8); // 0x7ff34fff 219 __ Branch(&error, ne, a0, Operand(0x7ff34fff)); 220 __ Movz(a0, t6, t7); // a0 not updated (t7 is NOT 0). 221 __ Ext(a1, a0, 8, 12); // 0x34f 222 __ Branch(&error, ne, a1, Operand(0x34f)); 223 __ Movz(a0, t6, v1); // a0<-t6, v0 is 0, from 8 instr back. 224 __ Branch(&error, ne, a0, Operand(t6)); 225 226 // Everything was correctly executed. Load the expected result. 227 __ li(v0, 0x31415926); 228 __ b(&exit); 229 __ nop(); 230 231 __ bind(&error); 232 // Got an error. Return a wrong result. 233 __ li(v0, 666); 234 235 __ bind(&exit); 236 __ jr(ra); 237 __ nop(); 238 239 CodeDesc desc; 240 assm.GetCode(&desc); 241 Handle<Code> code = isolate->factory()->NewCode( 242 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 243 F2 f = FUNCTION_CAST<F2>(code->entry()); 244 int res = reinterpret_cast<int>( 245 CALL_GENERATED_CODE(isolate, f, 0xab0, 0xc, 0, 0, 0)); 246 CHECK_EQ(static_cast<int32_t>(0x31415926), res); 247 } 248 249 250 TEST(MIPS3) { 251 // Test floating point instructions. 252 CcTest::InitializeVM(); 253 Isolate* isolate = CcTest::i_isolate(); 254 HandleScope scope(isolate); 255 256 typedef struct { 257 double a; 258 double b; 259 double c; 260 double d; 261 double e; 262 double f; 263 double g; 264 double h; 265 double i; 266 float fa; 267 float fb; 268 float fc; 269 float fd; 270 float fe; 271 float ff; 272 float fg; 273 } T; 274 T t; 275 276 // Create a function that accepts &t, and loads, manipulates, and stores 277 // the doubles t.a ... t.f. 278 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); 279 Label L, C; 280 281 // Double precision floating point instructions. 282 __ ldc1(f4, MemOperand(a0, offsetof(T, a)) ); 283 __ ldc1(f6, MemOperand(a0, offsetof(T, b)) ); 284 __ add_d(f8, f4, f6); 285 __ sdc1(f8, MemOperand(a0, offsetof(T, c)) ); // c = a + b. 286 287 __ mov_d(f10, f8); // c 288 __ neg_d(f12, f6); // -b 289 __ sub_d(f10, f10, f12); 290 __ sdc1(f10, MemOperand(a0, offsetof(T, d)) ); // d = c - (-b). 291 292 __ sdc1(f4, MemOperand(a0, offsetof(T, b)) ); // b = a. 293 294 __ li(t0, 120); 295 __ mtc1(t0, f14); 296 __ cvt_d_w(f14, f14); // f14 = 120.0. 297 __ mul_d(f10, f10, f14); 298 __ sdc1(f10, MemOperand(a0, offsetof(T, e)) ); // e = d * 120 = 1.8066e16. 299 300 __ div_d(f12, f10, f4); 301 __ sdc1(f12, MemOperand(a0, offsetof(T, f)) ); // f = e / a = 120.44. 302 303 __ sqrt_d(f14, f12); 304 __ sdc1(f14, MemOperand(a0, offsetof(T, g)) ); 305 // g = sqrt(f) = 10.97451593465515908537 306 307 if (IsMipsArchVariant(kMips32r2)) { 308 __ ldc1(f4, MemOperand(a0, offsetof(T, h)) ); 309 __ ldc1(f6, MemOperand(a0, offsetof(T, i)) ); 310 __ madd_d(f14, f6, f4, f6); 311 __ sdc1(f14, MemOperand(a0, offsetof(T, h)) ); 312 } 313 314 // Single precision floating point instructions. 315 __ lwc1(f4, MemOperand(a0, offsetof(T, fa)) ); 316 __ lwc1(f6, MemOperand(a0, offsetof(T, fb)) ); 317 __ add_s(f8, f4, f6); 318 __ swc1(f8, MemOperand(a0, offsetof(T, fc)) ); // fc = fa + fb. 319 320 __ neg_s(f10, f6); // -fb 321 __ sub_s(f10, f8, f10); 322 __ swc1(f10, MemOperand(a0, offsetof(T, fd)) ); // fd = fc - (-fb). 323 324 __ swc1(f4, MemOperand(a0, offsetof(T, fb)) ); // fb = fa. 325 326 __ li(t0, 120); 327 __ mtc1(t0, f14); 328 __ cvt_s_w(f14, f14); // f14 = 120.0. 329 __ mul_s(f10, f10, f14); 330 __ swc1(f10, MemOperand(a0, offsetof(T, fe)) ); // fe = fd * 120 331 332 __ div_s(f12, f10, f4); 333 __ swc1(f12, MemOperand(a0, offsetof(T, ff)) ); // ff = fe / fa 334 335 __ sqrt_s(f14, f12); 336 __ swc1(f14, MemOperand(a0, offsetof(T, fg)) ); 337 338 __ jr(ra); 339 __ nop(); 340 341 CodeDesc desc; 342 assm.GetCode(&desc); 343 Handle<Code> code = isolate->factory()->NewCode( 344 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 345 F3 f = FUNCTION_CAST<F3>(code->entry()); 346 // Double test values. 347 t.a = 1.5e14; 348 t.b = 2.75e11; 349 t.c = 0.0; 350 t.d = 0.0; 351 t.e = 0.0; 352 t.f = 0.0; 353 t.h = 1.5; 354 t.i = 2.75; 355 // Single test values. 356 t.fa = 1.5e6; 357 t.fb = 2.75e4; 358 t.fc = 0.0; 359 t.fd = 0.0; 360 t.fe = 0.0; 361 t.ff = 0.0; 362 Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0); 363 USE(dummy); 364 // Expected double results. 365 CHECK_EQ(1.5e14, t.a); 366 CHECK_EQ(1.5e14, t.b); 367 CHECK_EQ(1.50275e14, t.c); 368 CHECK_EQ(1.50550e14, t.d); 369 CHECK_EQ(1.8066e16, t.e); 370 CHECK_EQ(120.44, t.f); 371 CHECK_EQ(10.97451593465515908537, t.g); 372 if (IsMipsArchVariant(kMips32r2)) { 373 CHECK_EQ(6.875, t.h); 374 } 375 // Expected single results. 376 CHECK_EQ(1.5e6, t.fa); 377 CHECK_EQ(1.5e6, t.fb); 378 CHECK_EQ(1.5275e06, t.fc); 379 CHECK_EQ(1.5550e06, t.fd); 380 CHECK_EQ(1.866e08, t.fe); 381 CHECK_EQ(124.40000152587890625, t.ff); 382 CHECK_EQ(11.1534748077392578125, t.fg); 383 } 384 385 386 TEST(MIPS4) { 387 // Test moves between floating point and integer registers. 388 CcTest::InitializeVM(); 389 Isolate* isolate = CcTest::i_isolate(); 390 HandleScope scope(isolate); 391 392 typedef struct { 393 double a; 394 double b; 395 double c; 396 } T; 397 T t; 398 399 Assembler assm(isolate, NULL, 0); 400 Label L, C; 401 402 __ ldc1(f4, MemOperand(a0, offsetof(T, a)) ); 403 __ ldc1(f6, MemOperand(a0, offsetof(T, b)) ); 404 405 // Swap f4 and f6, by using four integer registers, t0-t3. 406 if (!IsFp64Mode()) { 407 __ mfc1(t0, f4); 408 __ mfc1(t1, f5); 409 __ mfc1(t2, f6); 410 __ mfc1(t3, f7); 411 412 __ mtc1(t0, f6); 413 __ mtc1(t1, f7); 414 __ mtc1(t2, f4); 415 __ mtc1(t3, f5); 416 } else { 417 CHECK(!IsMipsArchVariant(kMips32r1) && !IsMipsArchVariant(kLoongson)); 418 __ mfc1(t0, f4); 419 __ mfhc1(t1, f4); 420 __ mfc1(t2, f6); 421 __ mfhc1(t3, f6); 422 423 __ mtc1(t0, f6); 424 __ mthc1(t1, f6); 425 __ mtc1(t2, f4); 426 __ mthc1(t3, f4); 427 } 428 // Store the swapped f4 and f5 back to memory. 429 __ sdc1(f4, MemOperand(a0, offsetof(T, a)) ); 430 __ sdc1(f6, MemOperand(a0, offsetof(T, c)) ); 431 432 __ jr(ra); 433 __ nop(); 434 435 CodeDesc desc; 436 assm.GetCode(&desc); 437 Handle<Code> code = isolate->factory()->NewCode( 438 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 439 F3 f = FUNCTION_CAST<F3>(code->entry()); 440 t.a = 1.5e22; 441 t.b = 2.75e11; 442 t.c = 17.17; 443 Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0); 444 USE(dummy); 445 446 CHECK_EQ(2.75e11, t.a); 447 CHECK_EQ(2.75e11, t.b); 448 CHECK_EQ(1.5e22, t.c); 449 } 450 451 452 TEST(MIPS5) { 453 // Test conversions between doubles and integers. 454 CcTest::InitializeVM(); 455 Isolate* isolate = CcTest::i_isolate(); 456 HandleScope scope(isolate); 457 458 typedef struct { 459 double a; 460 double b; 461 int i; 462 int j; 463 } T; 464 T t; 465 466 Assembler assm(isolate, NULL, 0); 467 Label L, C; 468 469 // Load all structure elements to registers. 470 __ ldc1(f4, MemOperand(a0, offsetof(T, a)) ); 471 __ ldc1(f6, MemOperand(a0, offsetof(T, b)) ); 472 __ lw(t0, MemOperand(a0, offsetof(T, i)) ); 473 __ lw(t1, MemOperand(a0, offsetof(T, j)) ); 474 475 // Convert double in f4 to int in element i. 476 __ cvt_w_d(f8, f4); 477 __ mfc1(t2, f8); 478 __ sw(t2, MemOperand(a0, offsetof(T, i)) ); 479 480 // Convert double in f6 to int in element j. 481 __ cvt_w_d(f10, f6); 482 __ mfc1(t3, f10); 483 __ sw(t3, MemOperand(a0, offsetof(T, j)) ); 484 485 // Convert int in original i (t0) to double in a. 486 __ mtc1(t0, f12); 487 __ cvt_d_w(f0, f12); 488 __ sdc1(f0, MemOperand(a0, offsetof(T, a)) ); 489 490 // Convert int in original j (t1) to double in b. 491 __ mtc1(t1, f14); 492 __ cvt_d_w(f2, f14); 493 __ sdc1(f2, MemOperand(a0, offsetof(T, b)) ); 494 495 __ jr(ra); 496 __ nop(); 497 498 CodeDesc desc; 499 assm.GetCode(&desc); 500 Handle<Code> code = isolate->factory()->NewCode( 501 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 502 F3 f = FUNCTION_CAST<F3>(code->entry()); 503 t.a = 1.5e4; 504 t.b = 2.75e8; 505 t.i = 12345678; 506 t.j = -100000; 507 Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0); 508 USE(dummy); 509 510 CHECK_EQ(12345678.0, t.a); 511 CHECK_EQ(-100000.0, t.b); 512 CHECK_EQ(15000, t.i); 513 CHECK_EQ(275000000, t.j); 514 } 515 516 517 TEST(MIPS6) { 518 // Test simple memory loads and stores. 519 CcTest::InitializeVM(); 520 Isolate* isolate = CcTest::i_isolate(); 521 HandleScope scope(isolate); 522 523 typedef struct { 524 uint32_t ui; 525 int32_t si; 526 int32_t r1; 527 int32_t r2; 528 int32_t r3; 529 int32_t r4; 530 int32_t r5; 531 int32_t r6; 532 } T; 533 T t; 534 535 Assembler assm(isolate, NULL, 0); 536 Label L, C; 537 538 // Basic word load/store. 539 __ lw(t0, MemOperand(a0, offsetof(T, ui)) ); 540 __ sw(t0, MemOperand(a0, offsetof(T, r1)) ); 541 542 // lh with positive data. 543 __ lh(t1, MemOperand(a0, offsetof(T, ui)) ); 544 __ sw(t1, MemOperand(a0, offsetof(T, r2)) ); 545 546 // lh with negative data. 547 __ lh(t2, MemOperand(a0, offsetof(T, si)) ); 548 __ sw(t2, MemOperand(a0, offsetof(T, r3)) ); 549 550 // lhu with negative data. 551 __ lhu(t3, MemOperand(a0, offsetof(T, si)) ); 552 __ sw(t3, MemOperand(a0, offsetof(T, r4)) ); 553 554 // lb with negative data. 555 __ lb(t4, MemOperand(a0, offsetof(T, si)) ); 556 __ sw(t4, MemOperand(a0, offsetof(T, r5)) ); 557 558 // sh writes only 1/2 of word. 559 __ lui(t5, 0x3333); 560 __ ori(t5, t5, 0x3333); 561 __ sw(t5, MemOperand(a0, offsetof(T, r6)) ); 562 __ lhu(t5, MemOperand(a0, offsetof(T, si)) ); 563 __ sh(t5, MemOperand(a0, offsetof(T, r6)) ); 564 565 __ jr(ra); 566 __ nop(); 567 568 CodeDesc desc; 569 assm.GetCode(&desc); 570 Handle<Code> code = isolate->factory()->NewCode( 571 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 572 F3 f = FUNCTION_CAST<F3>(code->entry()); 573 t.ui = 0x11223344; 574 t.si = 0x99aabbcc; 575 Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0); 576 USE(dummy); 577 578 CHECK_EQ(static_cast<int32_t>(0x11223344), t.r1); 579 #if __BYTE_ORDER == __LITTLE_ENDIAN 580 CHECK_EQ(static_cast<int32_t>(0x3344), t.r2); 581 CHECK_EQ(static_cast<int32_t>(0xffffbbcc), t.r3); 582 CHECK_EQ(static_cast<int32_t>(0x0000bbcc), t.r4); 583 CHECK_EQ(static_cast<int32_t>(0xffffffcc), t.r5); 584 CHECK_EQ(static_cast<int32_t>(0x3333bbcc), t.r6); 585 #elif __BYTE_ORDER == __BIG_ENDIAN 586 CHECK_EQ(static_cast<int32_t>(0x1122), t.r2); 587 CHECK_EQ(static_cast<int32_t>(0xffff99aa), t.r3); 588 CHECK_EQ(static_cast<int32_t>(0x000099aa), t.r4); 589 CHECK_EQ(static_cast<int32_t>(0xffffff99), t.r5); 590 CHECK_EQ(static_cast<int32_t>(0x99aa3333), t.r6); 591 #else 592 #error Unknown endianness 593 #endif 594 } 595 596 597 TEST(MIPS7) { 598 // Test floating point compare and branch instructions. 599 CcTest::InitializeVM(); 600 Isolate* isolate = CcTest::i_isolate(); 601 HandleScope scope(isolate); 602 603 typedef struct { 604 double a; 605 double b; 606 double c; 607 double d; 608 double e; 609 double f; 610 int32_t result; 611 } T; 612 T t; 613 614 // Create a function that accepts &t, and loads, manipulates, and stores 615 // the doubles t.a ... t.f. 616 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); 617 Label neither_is_nan, less_than, outa_here; 618 619 __ ldc1(f4, MemOperand(a0, offsetof(T, a)) ); 620 __ ldc1(f6, MemOperand(a0, offsetof(T, b)) ); 621 if (!IsMipsArchVariant(kMips32r6)) { 622 __ c(UN, D, f4, f6); 623 __ bc1f(&neither_is_nan); 624 } else { 625 __ cmp(UN, L, f2, f4, f6); 626 __ bc1eqz(&neither_is_nan, f2); 627 } 628 __ nop(); 629 __ sw(zero_reg, MemOperand(a0, offsetof(T, result)) ); 630 __ Branch(&outa_here); 631 632 __ bind(&neither_is_nan); 633 634 if (IsMipsArchVariant(kLoongson)) { 635 __ c(OLT, D, f6, f4); 636 __ bc1t(&less_than); 637 } else if (IsMipsArchVariant(kMips32r6)) { 638 __ cmp(OLT, L, f2, f6, f4); 639 __ bc1nez(&less_than, f2); 640 } else { 641 __ c(OLT, D, f6, f4, 2); 642 __ bc1t(&less_than, 2); 643 } 644 645 __ nop(); 646 __ sw(zero_reg, MemOperand(a0, offsetof(T, result)) ); 647 __ Branch(&outa_here); 648 649 __ bind(&less_than); 650 __ Addu(t0, zero_reg, Operand(1)); 651 __ sw(t0, MemOperand(a0, offsetof(T, result)) ); // Set true. 652 653 654 // This test-case should have additional tests. 655 656 __ bind(&outa_here); 657 658 __ jr(ra); 659 __ nop(); 660 661 CodeDesc desc; 662 assm.GetCode(&desc); 663 Handle<Code> code = isolate->factory()->NewCode( 664 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 665 F3 f = FUNCTION_CAST<F3>(code->entry()); 666 t.a = 1.5e14; 667 t.b = 2.75e11; 668 t.c = 2.0; 669 t.d = -4.0; 670 t.e = 0.0; 671 t.f = 0.0; 672 t.result = 0; 673 Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0); 674 USE(dummy); 675 CHECK_EQ(1.5e14, t.a); 676 CHECK_EQ(2.75e11, t.b); 677 CHECK_EQ(1, t.result); 678 } 679 680 681 TEST(MIPS8) { 682 // Test ROTR and ROTRV instructions. 683 if (IsMipsArchVariant(kMips32r2)) { 684 CcTest::InitializeVM(); 685 Isolate* isolate = CcTest::i_isolate(); 686 HandleScope scope(isolate); 687 688 typedef struct { 689 int32_t input; 690 int32_t result_rotr_4; 691 int32_t result_rotr_8; 692 int32_t result_rotr_12; 693 int32_t result_rotr_16; 694 int32_t result_rotr_20; 695 int32_t result_rotr_24; 696 int32_t result_rotr_28; 697 int32_t result_rotrv_4; 698 int32_t result_rotrv_8; 699 int32_t result_rotrv_12; 700 int32_t result_rotrv_16; 701 int32_t result_rotrv_20; 702 int32_t result_rotrv_24; 703 int32_t result_rotrv_28; 704 } T; 705 T t; 706 707 MacroAssembler assm(isolate, NULL, 0, 708 v8::internal::CodeObjectRequired::kYes); 709 710 // Basic word load. 711 __ lw(t0, MemOperand(a0, offsetof(T, input)) ); 712 713 // ROTR instruction (called through the Ror macro). 714 __ Ror(t1, t0, 0x0004); 715 __ Ror(t2, t0, 0x0008); 716 __ Ror(t3, t0, 0x000c); 717 __ Ror(t4, t0, 0x0010); 718 __ Ror(t5, t0, 0x0014); 719 __ Ror(t6, t0, 0x0018); 720 __ Ror(t7, t0, 0x001c); 721 722 // Basic word store. 723 __ sw(t1, MemOperand(a0, offsetof(T, result_rotr_4)) ); 724 __ sw(t2, MemOperand(a0, offsetof(T, result_rotr_8)) ); 725 __ sw(t3, MemOperand(a0, offsetof(T, result_rotr_12)) ); 726 __ sw(t4, MemOperand(a0, offsetof(T, result_rotr_16)) ); 727 __ sw(t5, MemOperand(a0, offsetof(T, result_rotr_20)) ); 728 __ sw(t6, MemOperand(a0, offsetof(T, result_rotr_24)) ); 729 __ sw(t7, MemOperand(a0, offsetof(T, result_rotr_28)) ); 730 731 // ROTRV instruction (called through the Ror macro). 732 __ li(t7, 0x0004); 733 __ Ror(t1, t0, t7); 734 __ li(t7, 0x0008); 735 __ Ror(t2, t0, t7); 736 __ li(t7, 0x000C); 737 __ Ror(t3, t0, t7); 738 __ li(t7, 0x0010); 739 __ Ror(t4, t0, t7); 740 __ li(t7, 0x0014); 741 __ Ror(t5, t0, t7); 742 __ li(t7, 0x0018); 743 __ Ror(t6, t0, t7); 744 __ li(t7, 0x001C); 745 __ Ror(t7, t0, t7); 746 747 // Basic word store. 748 __ sw(t1, MemOperand(a0, offsetof(T, result_rotrv_4)) ); 749 __ sw(t2, MemOperand(a0, offsetof(T, result_rotrv_8)) ); 750 __ sw(t3, MemOperand(a0, offsetof(T, result_rotrv_12)) ); 751 __ sw(t4, MemOperand(a0, offsetof(T, result_rotrv_16)) ); 752 __ sw(t5, MemOperand(a0, offsetof(T, result_rotrv_20)) ); 753 __ sw(t6, MemOperand(a0, offsetof(T, result_rotrv_24)) ); 754 __ sw(t7, MemOperand(a0, offsetof(T, result_rotrv_28)) ); 755 756 __ jr(ra); 757 __ nop(); 758 759 CodeDesc desc; 760 assm.GetCode(&desc); 761 Handle<Code> code = isolate->factory()->NewCode( 762 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 763 F3 f = FUNCTION_CAST<F3>(code->entry()); 764 t.input = 0x12345678; 765 Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0x0, 0, 0, 0); 766 USE(dummy); 767 CHECK_EQ(static_cast<int32_t>(0x81234567), t.result_rotr_4); 768 CHECK_EQ(static_cast<int32_t>(0x78123456), t.result_rotr_8); 769 CHECK_EQ(static_cast<int32_t>(0x67812345), t.result_rotr_12); 770 CHECK_EQ(static_cast<int32_t>(0x56781234), t.result_rotr_16); 771 CHECK_EQ(static_cast<int32_t>(0x45678123), t.result_rotr_20); 772 CHECK_EQ(static_cast<int32_t>(0x34567812), t.result_rotr_24); 773 CHECK_EQ(static_cast<int32_t>(0x23456781), t.result_rotr_28); 774 775 CHECK_EQ(static_cast<int32_t>(0x81234567), t.result_rotrv_4); 776 CHECK_EQ(static_cast<int32_t>(0x78123456), t.result_rotrv_8); 777 CHECK_EQ(static_cast<int32_t>(0x67812345), t.result_rotrv_12); 778 CHECK_EQ(static_cast<int32_t>(0x56781234), t.result_rotrv_16); 779 CHECK_EQ(static_cast<int32_t>(0x45678123), t.result_rotrv_20); 780 CHECK_EQ(static_cast<int32_t>(0x34567812), t.result_rotrv_24); 781 CHECK_EQ(static_cast<int32_t>(0x23456781), t.result_rotrv_28); 782 } 783 } 784 785 786 TEST(MIPS9) { 787 // Test BRANCH improvements. 788 CcTest::InitializeVM(); 789 Isolate* isolate = CcTest::i_isolate(); 790 HandleScope scope(isolate); 791 792 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); 793 Label exit, exit2, exit3; 794 795 __ Branch(&exit, ge, a0, Operand(zero_reg)); 796 __ Branch(&exit2, ge, a0, Operand(0x00001FFF)); 797 __ Branch(&exit3, ge, a0, Operand(0x0001FFFF)); 798 799 __ bind(&exit); 800 __ bind(&exit2); 801 __ bind(&exit3); 802 __ jr(ra); 803 __ nop(); 804 805 CodeDesc desc; 806 assm.GetCode(&desc); 807 isolate->factory()->NewCode( 808 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 809 } 810 811 812 TEST(MIPS10) { 813 // Test conversions between doubles and words. 814 // Test maps double to FP reg pairs in fp32 mode 815 // and into FP reg in fp64 mode. 816 CcTest::InitializeVM(); 817 Isolate* isolate = CcTest::i_isolate(); 818 HandleScope scope(isolate); 819 820 typedef struct { 821 double a; 822 double b; 823 int32_t dbl_mant; 824 int32_t dbl_exp; 825 int32_t word; 826 int32_t b_word; 827 } T; 828 T t; 829 830 Assembler assm(isolate, NULL, 0); 831 Label L, C; 832 833 if (!IsMipsArchVariant(kMips32r2)) return; 834 835 // Load all structure elements to registers. 836 // (f0, f1) = a (fp32), f0 = a (fp64) 837 __ ldc1(f0, MemOperand(a0, offsetof(T, a))); 838 839 if (IsFp64Mode()) { 840 __ mfc1(t0, f0); // t0 = f0(31..0) 841 __ mfhc1(t1, f0); // t1 = sign_extend(f0(63..32)) 842 __ sw(t0, MemOperand(a0, offsetof(T, dbl_mant))); // dbl_mant = t0 843 __ sw(t1, MemOperand(a0, offsetof(T, dbl_exp))); // dbl_exp = t1 844 } else { 845 // Save the raw bits of the double. 846 __ mfc1(t0, f0); // t0 = a1 847 __ mfc1(t1, f1); // t1 = a2 848 __ sw(t0, MemOperand(a0, offsetof(T, dbl_mant))); // dbl_mant = t0 849 __ sw(t1, MemOperand(a0, offsetof(T, dbl_exp))); // dbl_exp = t1 850 } 851 852 // Convert double in f0 to word, save hi/lo parts. 853 __ cvt_w_d(f0, f0); // a_word = (word)a 854 __ mfc1(t0, f0); // f0 has a 32-bits word. t0 = a_word 855 __ sw(t0, MemOperand(a0, offsetof(T, word))); // word = a_word 856 857 // Convert the b word to double b. 858 __ lw(t0, MemOperand(a0, offsetof(T, b_word))); 859 __ mtc1(t0, f8); // f8 has a 32-bits word. 860 __ cvt_d_w(f10, f8); 861 __ sdc1(f10, MemOperand(a0, offsetof(T, b))); 862 863 __ jr(ra); 864 __ nop(); 865 866 CodeDesc desc; 867 assm.GetCode(&desc); 868 Handle<Code> code = isolate->factory()->NewCode( 869 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 870 F3 f = FUNCTION_CAST<F3>(code->entry()); 871 t.a = 2.147483646e+09; // 0x7FFFFFFE -> 0xFF80000041DFFFFF as double. 872 t.b_word = 0x0ff00ff0; // 0x0FF00FF0 -> 0x as double. 873 Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0); 874 USE(dummy); 875 CHECK_EQ(static_cast<int32_t>(0x41DFFFFF), t.dbl_exp); 876 CHECK_EQ(static_cast<int32_t>(0xFF800000), t.dbl_mant); 877 CHECK_EQ(static_cast<int32_t>(0x7FFFFFFE), t.word); 878 // 0x0FF00FF0 -> 2.6739096+e08 879 CHECK_EQ(2.6739096e08, t.b); 880 } 881 882 883 TEST(MIPS11) { 884 // Do not run test on MIPS32r6, as these instructions are removed. 885 if (IsMipsArchVariant(kMips32r6)) return; 886 // Test LWL, LWR, SWL and SWR instructions. 887 CcTest::InitializeVM(); 888 Isolate* isolate = CcTest::i_isolate(); 889 HandleScope scope(isolate); 890 891 typedef struct { 892 int32_t reg_init; 893 int32_t mem_init; 894 int32_t lwl_0; 895 int32_t lwl_1; 896 int32_t lwl_2; 897 int32_t lwl_3; 898 int32_t lwr_0; 899 int32_t lwr_1; 900 int32_t lwr_2; 901 int32_t lwr_3; 902 int32_t swl_0; 903 int32_t swl_1; 904 int32_t swl_2; 905 int32_t swl_3; 906 int32_t swr_0; 907 int32_t swr_1; 908 int32_t swr_2; 909 int32_t swr_3; 910 } T; 911 T t; 912 913 Assembler assm(isolate, NULL, 0); 914 915 // Test all combinations of LWL and vAddr. 916 __ lw(t0, MemOperand(a0, offsetof(T, reg_init)) ); 917 __ lwl(t0, MemOperand(a0, offsetof(T, mem_init)) ); 918 __ sw(t0, MemOperand(a0, offsetof(T, lwl_0)) ); 919 920 __ lw(t1, MemOperand(a0, offsetof(T, reg_init)) ); 921 __ lwl(t1, MemOperand(a0, offsetof(T, mem_init) + 1) ); 922 __ sw(t1, MemOperand(a0, offsetof(T, lwl_1)) ); 923 924 __ lw(t2, MemOperand(a0, offsetof(T, reg_init)) ); 925 __ lwl(t2, MemOperand(a0, offsetof(T, mem_init) + 2) ); 926 __ sw(t2, MemOperand(a0, offsetof(T, lwl_2)) ); 927 928 __ lw(t3, MemOperand(a0, offsetof(T, reg_init)) ); 929 __ lwl(t3, MemOperand(a0, offsetof(T, mem_init) + 3) ); 930 __ sw(t3, MemOperand(a0, offsetof(T, lwl_3)) ); 931 932 // Test all combinations of LWR and vAddr. 933 __ lw(t0, MemOperand(a0, offsetof(T, reg_init)) ); 934 __ lwr(t0, MemOperand(a0, offsetof(T, mem_init)) ); 935 __ sw(t0, MemOperand(a0, offsetof(T, lwr_0)) ); 936 937 __ lw(t1, MemOperand(a0, offsetof(T, reg_init)) ); 938 __ lwr(t1, MemOperand(a0, offsetof(T, mem_init) + 1) ); 939 __ sw(t1, MemOperand(a0, offsetof(T, lwr_1)) ); 940 941 __ lw(t2, MemOperand(a0, offsetof(T, reg_init)) ); 942 __ lwr(t2, MemOperand(a0, offsetof(T, mem_init) + 2) ); 943 __ sw(t2, MemOperand(a0, offsetof(T, lwr_2)) ); 944 945 __ lw(t3, MemOperand(a0, offsetof(T, reg_init)) ); 946 __ lwr(t3, MemOperand(a0, offsetof(T, mem_init) + 3) ); 947 __ sw(t3, MemOperand(a0, offsetof(T, lwr_3)) ); 948 949 // Test all combinations of SWL and vAddr. 950 __ lw(t0, MemOperand(a0, offsetof(T, mem_init)) ); 951 __ sw(t0, MemOperand(a0, offsetof(T, swl_0)) ); 952 __ lw(t0, MemOperand(a0, offsetof(T, reg_init)) ); 953 __ swl(t0, MemOperand(a0, offsetof(T, swl_0)) ); 954 955 __ lw(t1, MemOperand(a0, offsetof(T, mem_init)) ); 956 __ sw(t1, MemOperand(a0, offsetof(T, swl_1)) ); 957 __ lw(t1, MemOperand(a0, offsetof(T, reg_init)) ); 958 __ swl(t1, MemOperand(a0, offsetof(T, swl_1) + 1) ); 959 960 __ lw(t2, MemOperand(a0, offsetof(T, mem_init)) ); 961 __ sw(t2, MemOperand(a0, offsetof(T, swl_2)) ); 962 __ lw(t2, MemOperand(a0, offsetof(T, reg_init)) ); 963 __ swl(t2, MemOperand(a0, offsetof(T, swl_2) + 2) ); 964 965 __ lw(t3, MemOperand(a0, offsetof(T, mem_init)) ); 966 __ sw(t3, MemOperand(a0, offsetof(T, swl_3)) ); 967 __ lw(t3, MemOperand(a0, offsetof(T, reg_init)) ); 968 __ swl(t3, MemOperand(a0, offsetof(T, swl_3) + 3) ); 969 970 // Test all combinations of SWR and vAddr. 971 __ lw(t0, MemOperand(a0, offsetof(T, mem_init)) ); 972 __ sw(t0, MemOperand(a0, offsetof(T, swr_0)) ); 973 __ lw(t0, MemOperand(a0, offsetof(T, reg_init)) ); 974 __ swr(t0, MemOperand(a0, offsetof(T, swr_0)) ); 975 976 __ lw(t1, MemOperand(a0, offsetof(T, mem_init)) ); 977 __ sw(t1, MemOperand(a0, offsetof(T, swr_1)) ); 978 __ lw(t1, MemOperand(a0, offsetof(T, reg_init)) ); 979 __ swr(t1, MemOperand(a0, offsetof(T, swr_1) + 1) ); 980 981 __ lw(t2, MemOperand(a0, offsetof(T, mem_init)) ); 982 __ sw(t2, MemOperand(a0, offsetof(T, swr_2)) ); 983 __ lw(t2, MemOperand(a0, offsetof(T, reg_init)) ); 984 __ swr(t2, MemOperand(a0, offsetof(T, swr_2) + 2) ); 985 986 __ lw(t3, MemOperand(a0, offsetof(T, mem_init)) ); 987 __ sw(t3, MemOperand(a0, offsetof(T, swr_3)) ); 988 __ lw(t3, MemOperand(a0, offsetof(T, reg_init)) ); 989 __ swr(t3, MemOperand(a0, offsetof(T, swr_3) + 3) ); 990 991 __ jr(ra); 992 __ nop(); 993 994 CodeDesc desc; 995 assm.GetCode(&desc); 996 Handle<Code> code = isolate->factory()->NewCode( 997 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 998 F3 f = FUNCTION_CAST<F3>(code->entry()); 999 t.reg_init = 0xaabbccdd; 1000 t.mem_init = 0x11223344; 1001 1002 Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0); 1003 USE(dummy); 1004 1005 #if __BYTE_ORDER == __LITTLE_ENDIAN 1006 CHECK_EQ(static_cast<int32_t>(0x44bbccdd), t.lwl_0); 1007 CHECK_EQ(static_cast<int32_t>(0x3344ccdd), t.lwl_1); 1008 CHECK_EQ(static_cast<int32_t>(0x223344dd), t.lwl_2); 1009 CHECK_EQ(static_cast<int32_t>(0x11223344), t.lwl_3); 1010 1011 CHECK_EQ(static_cast<int32_t>(0x11223344), t.lwr_0); 1012 CHECK_EQ(static_cast<int32_t>(0xaa112233), t.lwr_1); 1013 CHECK_EQ(static_cast<int32_t>(0xaabb1122), t.lwr_2); 1014 CHECK_EQ(static_cast<int32_t>(0xaabbcc11), t.lwr_3); 1015 1016 CHECK_EQ(static_cast<int32_t>(0x112233aa), t.swl_0); 1017 CHECK_EQ(static_cast<int32_t>(0x1122aabb), t.swl_1); 1018 CHECK_EQ(static_cast<int32_t>(0x11aabbcc), t.swl_2); 1019 CHECK_EQ(static_cast<int32_t>(0xaabbccdd), t.swl_3); 1020 1021 CHECK_EQ(static_cast<int32_t>(0xaabbccdd), t.swr_0); 1022 CHECK_EQ(static_cast<int32_t>(0xbbccdd44), t.swr_1); 1023 CHECK_EQ(static_cast<int32_t>(0xccdd3344), t.swr_2); 1024 CHECK_EQ(static_cast<int32_t>(0xdd223344), t.swr_3); 1025 #elif __BYTE_ORDER == __BIG_ENDIAN 1026 CHECK_EQ(static_cast<int32_t>(0x11223344), t.lwl_0); 1027 CHECK_EQ(static_cast<int32_t>(0x223344dd), t.lwl_1); 1028 CHECK_EQ(static_cast<int32_t>(0x3344ccdd), t.lwl_2); 1029 CHECK_EQ(static_cast<int32_t>(0x44bbccdd), t.lwl_3); 1030 1031 CHECK_EQ(static_cast<int32_t>(0xaabbcc11), t.lwr_0); 1032 CHECK_EQ(static_cast<int32_t>(0xaabb1122), t.lwr_1); 1033 CHECK_EQ(static_cast<int32_t>(0xaa112233), t.lwr_2); 1034 CHECK_EQ(static_cast<int32_t>(0x11223344), t.lwr_3); 1035 1036 CHECK_EQ(static_cast<int32_t>(0xaabbccdd), t.swl_0); 1037 CHECK_EQ(static_cast<int32_t>(0x11aabbcc), t.swl_1); 1038 CHECK_EQ(static_cast<int32_t>(0x1122aabb), t.swl_2); 1039 CHECK_EQ(static_cast<int32_t>(0x112233aa), t.swl_3); 1040 1041 CHECK_EQ(static_cast<int32_t>(0xdd223344), t.swr_0); 1042 CHECK_EQ(static_cast<int32_t>(0xccdd3344), t.swr_1); 1043 CHECK_EQ(static_cast<int32_t>(0xbbccdd44), t.swr_2); 1044 CHECK_EQ(static_cast<int32_t>(0xaabbccdd), t.swr_3); 1045 #else 1046 #error Unknown endianness 1047 #endif 1048 } 1049 1050 1051 TEST(MIPS12) { 1052 CcTest::InitializeVM(); 1053 Isolate* isolate = CcTest::i_isolate(); 1054 HandleScope scope(isolate); 1055 1056 typedef struct { 1057 int32_t x; 1058 int32_t y; 1059 int32_t y1; 1060 int32_t y2; 1061 int32_t y3; 1062 int32_t y4; 1063 } T; 1064 T t; 1065 1066 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); 1067 1068 __ mov(t6, fp); // Save frame pointer. 1069 __ mov(fp, a0); // Access struct T by fp. 1070 __ lw(t0, MemOperand(a0, offsetof(T, y)) ); 1071 __ lw(t3, MemOperand(a0, offsetof(T, y4)) ); 1072 1073 __ addu(t1, t0, t3); 1074 __ subu(t4, t0, t3); 1075 __ nop(); 1076 __ push(t0); // These instructions disappear after opt. 1077 __ Pop(); 1078 __ addu(t0, t0, t0); 1079 __ nop(); 1080 __ Pop(); // These instructions disappear after opt. 1081 __ push(t3); 1082 __ nop(); 1083 __ push(t3); // These instructions disappear after opt. 1084 __ pop(t3); 1085 __ nop(); 1086 __ push(t3); 1087 __ pop(t4); 1088 __ nop(); 1089 __ sw(t0, MemOperand(fp, offsetof(T, y)) ); 1090 __ lw(t0, MemOperand(fp, offsetof(T, y)) ); 1091 __ nop(); 1092 __ sw(t0, MemOperand(fp, offsetof(T, y)) ); 1093 __ lw(t1, MemOperand(fp, offsetof(T, y)) ); 1094 __ nop(); 1095 __ push(t1); 1096 __ lw(t1, MemOperand(fp, offsetof(T, y)) ); 1097 __ pop(t1); 1098 __ nop(); 1099 __ push(t1); 1100 __ lw(t2, MemOperand(fp, offsetof(T, y)) ); 1101 __ pop(t1); 1102 __ nop(); 1103 __ push(t1); 1104 __ lw(t2, MemOperand(fp, offsetof(T, y)) ); 1105 __ pop(t2); 1106 __ nop(); 1107 __ push(t2); 1108 __ lw(t2, MemOperand(fp, offsetof(T, y)) ); 1109 __ pop(t1); 1110 __ nop(); 1111 __ push(t1); 1112 __ lw(t2, MemOperand(fp, offsetof(T, y)) ); 1113 __ pop(t3); 1114 __ nop(); 1115 1116 __ mov(fp, t6); 1117 __ jr(ra); 1118 __ nop(); 1119 1120 CodeDesc desc; 1121 assm.GetCode(&desc); 1122 Handle<Code> code = isolate->factory()->NewCode( 1123 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 1124 F3 f = FUNCTION_CAST<F3>(code->entry()); 1125 t.x = 1; 1126 t.y = 2; 1127 t.y1 = 3; 1128 t.y2 = 4; 1129 t.y3 = 0XBABA; 1130 t.y4 = 0xDEDA; 1131 1132 Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0); 1133 USE(dummy); 1134 1135 CHECK_EQ(3, t.y1); 1136 } 1137 1138 1139 TEST(MIPS13) { 1140 // Test Cvt_d_uw and Trunc_uw_d macros. 1141 CcTest::InitializeVM(); 1142 Isolate* isolate = CcTest::i_isolate(); 1143 HandleScope scope(isolate); 1144 1145 typedef struct { 1146 double cvt_big_out; 1147 double cvt_small_out; 1148 uint32_t trunc_big_out; 1149 uint32_t trunc_small_out; 1150 uint32_t cvt_big_in; 1151 uint32_t cvt_small_in; 1152 } T; 1153 T t; 1154 1155 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); 1156 1157 __ sw(t0, MemOperand(a0, offsetof(T, cvt_small_in))); 1158 __ Cvt_d_uw(f10, t0, f4); 1159 __ sdc1(f10, MemOperand(a0, offsetof(T, cvt_small_out))); 1160 1161 __ Trunc_uw_d(f10, f10, f4); 1162 __ swc1(f10, MemOperand(a0, offsetof(T, trunc_small_out))); 1163 1164 __ sw(t0, MemOperand(a0, offsetof(T, cvt_big_in))); 1165 __ Cvt_d_uw(f8, t0, f4); 1166 __ sdc1(f8, MemOperand(a0, offsetof(T, cvt_big_out))); 1167 1168 __ Trunc_uw_d(f8, f8, f4); 1169 __ swc1(f8, MemOperand(a0, offsetof(T, trunc_big_out))); 1170 1171 __ jr(ra); 1172 __ nop(); 1173 1174 CodeDesc desc; 1175 assm.GetCode(&desc); 1176 Handle<Code> code = isolate->factory()->NewCode( 1177 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 1178 F3 f = FUNCTION_CAST<F3>(code->entry()); 1179 1180 t.cvt_big_in = 0xFFFFFFFF; 1181 t.cvt_small_in = 333; 1182 1183 Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0); 1184 USE(dummy); 1185 1186 CHECK_EQ(t.cvt_big_out, static_cast<double>(t.cvt_big_in)); 1187 CHECK_EQ(t.cvt_small_out, static_cast<double>(t.cvt_small_in)); 1188 1189 CHECK_EQ(static_cast<int>(t.trunc_big_out), static_cast<int>(t.cvt_big_in)); 1190 CHECK_EQ(static_cast<int>(t.trunc_small_out), 1191 static_cast<int>(t.cvt_small_in)); 1192 } 1193 1194 1195 TEST(MIPS14) { 1196 // Test round, floor, ceil, trunc, cvt. 1197 CcTest::InitializeVM(); 1198 Isolate* isolate = CcTest::i_isolate(); 1199 HandleScope scope(isolate); 1200 1201 #define ROUND_STRUCT_ELEMENT(x) \ 1202 uint32_t x##_isNaN2008; \ 1203 int32_t x##_up_out; \ 1204 int32_t x##_down_out; \ 1205 int32_t neg_##x##_up_out; \ 1206 int32_t neg_##x##_down_out; \ 1207 uint32_t x##_err1_out; \ 1208 uint32_t x##_err2_out; \ 1209 uint32_t x##_err3_out; \ 1210 uint32_t x##_err4_out; \ 1211 int32_t x##_invalid_result; 1212 1213 typedef struct { 1214 double round_up_in; 1215 double round_down_in; 1216 double neg_round_up_in; 1217 double neg_round_down_in; 1218 double err1_in; 1219 double err2_in; 1220 double err3_in; 1221 double err4_in; 1222 1223 ROUND_STRUCT_ELEMENT(round) 1224 ROUND_STRUCT_ELEMENT(floor) 1225 ROUND_STRUCT_ELEMENT(ceil) 1226 ROUND_STRUCT_ELEMENT(trunc) 1227 ROUND_STRUCT_ELEMENT(cvt) 1228 } T; 1229 T t; 1230 1231 #undef ROUND_STRUCT_ELEMENT 1232 1233 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); 1234 1235 // Save FCSR. 1236 __ cfc1(a1, FCSR); 1237 // Disable FPU exceptions. 1238 __ ctc1(zero_reg, FCSR); 1239 #define RUN_ROUND_TEST(x) \ 1240 __ cfc1(t0, FCSR);\ 1241 __ sw(t0, MemOperand(a0, offsetof(T, x##_isNaN2008))); \ 1242 __ ldc1(f0, MemOperand(a0, offsetof(T, round_up_in))); \ 1243 __ x##_w_d(f0, f0); \ 1244 __ swc1(f0, MemOperand(a0, offsetof(T, x##_up_out))); \ 1245 \ 1246 __ ldc1(f0, MemOperand(a0, offsetof(T, round_down_in))); \ 1247 __ x##_w_d(f0, f0); \ 1248 __ swc1(f0, MemOperand(a0, offsetof(T, x##_down_out))); \ 1249 \ 1250 __ ldc1(f0, MemOperand(a0, offsetof(T, neg_round_up_in))); \ 1251 __ x##_w_d(f0, f0); \ 1252 __ swc1(f0, MemOperand(a0, offsetof(T, neg_##x##_up_out))); \ 1253 \ 1254 __ ldc1(f0, MemOperand(a0, offsetof(T, neg_round_down_in))); \ 1255 __ x##_w_d(f0, f0); \ 1256 __ swc1(f0, MemOperand(a0, offsetof(T, neg_##x##_down_out))); \ 1257 \ 1258 __ ldc1(f0, MemOperand(a0, offsetof(T, err1_in))); \ 1259 __ ctc1(zero_reg, FCSR); \ 1260 __ x##_w_d(f0, f0); \ 1261 __ cfc1(a2, FCSR); \ 1262 __ sw(a2, MemOperand(a0, offsetof(T, x##_err1_out))); \ 1263 \ 1264 __ ldc1(f0, MemOperand(a0, offsetof(T, err2_in))); \ 1265 __ ctc1(zero_reg, FCSR); \ 1266 __ x##_w_d(f0, f0); \ 1267 __ cfc1(a2, FCSR); \ 1268 __ sw(a2, MemOperand(a0, offsetof(T, x##_err2_out))); \ 1269 \ 1270 __ ldc1(f0, MemOperand(a0, offsetof(T, err3_in))); \ 1271 __ ctc1(zero_reg, FCSR); \ 1272 __ x##_w_d(f0, f0); \ 1273 __ cfc1(a2, FCSR); \ 1274 __ sw(a2, MemOperand(a0, offsetof(T, x##_err3_out))); \ 1275 \ 1276 __ ldc1(f0, MemOperand(a0, offsetof(T, err4_in))); \ 1277 __ ctc1(zero_reg, FCSR); \ 1278 __ x##_w_d(f0, f0); \ 1279 __ cfc1(a2, FCSR); \ 1280 __ sw(a2, MemOperand(a0, offsetof(T, x##_err4_out))); \ 1281 __ swc1(f0, MemOperand(a0, offsetof(T, x##_invalid_result))); 1282 1283 RUN_ROUND_TEST(round) 1284 RUN_ROUND_TEST(floor) 1285 RUN_ROUND_TEST(ceil) 1286 RUN_ROUND_TEST(trunc) 1287 RUN_ROUND_TEST(cvt) 1288 1289 // Restore FCSR. 1290 __ ctc1(a1, FCSR); 1291 1292 __ jr(ra); 1293 __ nop(); 1294 1295 CodeDesc desc; 1296 assm.GetCode(&desc); 1297 Handle<Code> code = isolate->factory()->NewCode( 1298 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 1299 F3 f = FUNCTION_CAST<F3>(code->entry()); 1300 1301 t.round_up_in = 123.51; 1302 t.round_down_in = 123.49; 1303 t.neg_round_up_in = -123.5; 1304 t.neg_round_down_in = -123.49; 1305 t.err1_in = 123.51; 1306 t.err2_in = 1; 1307 t.err3_in = static_cast<double>(1) + 0xFFFFFFFF; 1308 t.err4_in = NAN; 1309 1310 Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0); 1311 USE(dummy); 1312 1313 #define GET_FPU_ERR(x) (static_cast<int>(x & kFCSRFlagMask)) 1314 #define CHECK_NAN2008(x) (x & kFCSRNaN2008FlagMask) 1315 #define CHECK_ROUND_RESULT(type) \ 1316 CHECK(GET_FPU_ERR(t.type##_err1_out) & kFCSRInexactFlagMask); \ 1317 CHECK_EQ(0, GET_FPU_ERR(t.type##_err2_out)); \ 1318 CHECK(GET_FPU_ERR(t.type##_err3_out) & kFCSRInvalidOpFlagMask); \ 1319 CHECK(GET_FPU_ERR(t.type##_err4_out) & kFCSRInvalidOpFlagMask); \ 1320 if (CHECK_NAN2008(t.type##_isNaN2008) && kArchVariant == kMips32r6) {\ 1321 CHECK_EQ(static_cast<int32_t>(0), t.type##_invalid_result);\ 1322 } else {\ 1323 CHECK_EQ(static_cast<int32_t>(kFPUInvalidResult), t.type##_invalid_result);\ 1324 } 1325 1326 1327 CHECK_ROUND_RESULT(round); 1328 CHECK_ROUND_RESULT(floor); 1329 CHECK_ROUND_RESULT(ceil); 1330 CHECK_ROUND_RESULT(cvt); 1331 } 1332 1333 1334 TEST(MIPS15) { 1335 // Test chaining of label usages within instructions (issue 1644). 1336 CcTest::InitializeVM(); 1337 Isolate* isolate = CcTest::i_isolate(); 1338 HandleScope scope(isolate); 1339 Assembler assm(isolate, NULL, 0); 1340 1341 Label target; 1342 __ beq(v0, v1, &target); 1343 __ nop(); 1344 __ bne(v0, v1, &target); 1345 __ nop(); 1346 __ bind(&target); 1347 __ nop(); 1348 } 1349 1350 1351 // ----------------------mips32r6 specific tests---------------------- 1352 TEST(seleqz_selnez) { 1353 if (IsMipsArchVariant(kMips32r6)) { 1354 CcTest::InitializeVM(); 1355 Isolate* isolate = CcTest::i_isolate(); 1356 HandleScope scope(isolate); 1357 MacroAssembler assm(isolate, NULL, 0, 1358 v8::internal::CodeObjectRequired::kYes); 1359 1360 typedef struct test { 1361 int a; 1362 int b; 1363 int c; 1364 int d; 1365 double e; 1366 double f; 1367 double g; 1368 double h; 1369 float i; 1370 float j; 1371 float k; 1372 float l; 1373 } Test; 1374 1375 Test test; 1376 // Integer part of test. 1377 __ addiu(t1, zero_reg, 1); // t1 = 1 1378 __ seleqz(t3, t1, zero_reg); // t3 = 1 1379 __ sw(t3, MemOperand(a0, offsetof(Test, a))); // a = 1 1380 __ seleqz(t2, t1, t1); // t2 = 0 1381 __ sw(t2, MemOperand(a0, offsetof(Test, b))); // b = 0 1382 __ selnez(t3, t1, zero_reg); // t3 = 1; 1383 __ sw(t3, MemOperand(a0, offsetof(Test, c))); // c = 0 1384 __ selnez(t3, t1, t1); // t3 = 1 1385 __ sw(t3, MemOperand(a0, offsetof(Test, d))); // d = 1 1386 // Floating point part of test. 1387 __ ldc1(f0, MemOperand(a0, offsetof(Test, e)) ); // src 1388 __ ldc1(f2, MemOperand(a0, offsetof(Test, f)) ); // test 1389 __ lwc1(f8, MemOperand(a0, offsetof(Test, i)) ); // src 1390 __ lwc1(f10, MemOperand(a0, offsetof(Test, j)) ); // test 1391 __ seleqz_d(f4, f0, f2); 1392 __ selnez_d(f6, f0, f2); 1393 __ seleqz_s(f12, f8, f10); 1394 __ selnez_s(f14, f8, f10); 1395 __ sdc1(f4, MemOperand(a0, offsetof(Test, g)) ); // src 1396 __ sdc1(f6, MemOperand(a0, offsetof(Test, h)) ); // src 1397 __ swc1(f12, MemOperand(a0, offsetof(Test, k)) ); // src 1398 __ swc1(f14, MemOperand(a0, offsetof(Test, l)) ); // src 1399 __ jr(ra); 1400 __ nop(); 1401 CodeDesc desc; 1402 assm.GetCode(&desc); 1403 Handle<Code> code = isolate->factory()->NewCode( 1404 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 1405 F3 f = FUNCTION_CAST<F3>(code->entry()); 1406 1407 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 1408 1409 CHECK_EQ(test.a, 1); 1410 CHECK_EQ(test.b, 0); 1411 CHECK_EQ(test.c, 0); 1412 CHECK_EQ(test.d, 1); 1413 1414 const int test_size = 3; 1415 const int input_size = 5; 1416 1417 double inputs_D[input_size] = {0.0, 65.2, -70.32, 1418 18446744073709551621.0, -18446744073709551621.0}; 1419 double outputs_D[input_size] = {0.0, 65.2, -70.32, 1420 18446744073709551621.0, -18446744073709551621.0}; 1421 double tests_D[test_size*2] = {2.8, 2.9, -2.8, -2.9, 1422 18446744073709551616.0, 18446744073709555712.0}; 1423 float inputs_S[input_size] = {0.0, 65.2, -70.32, 1424 18446744073709551621.0, -18446744073709551621.0}; 1425 float outputs_S[input_size] = {0.0, 65.2, -70.32, 1426 18446744073709551621.0, -18446744073709551621.0}; 1427 float tests_S[test_size*2] = {2.9, 2.8, -2.9, -2.8, 1428 18446744073709551616.0, 18446746272732807168.0}; 1429 for (int j=0; j < test_size; j+=2) { 1430 for (int i=0; i < input_size; i++) { 1431 test.e = inputs_D[i]; 1432 test.f = tests_D[j]; 1433 test.i = inputs_S[i]; 1434 test.j = tests_S[j]; 1435 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 1436 CHECK_EQ(test.g, outputs_D[i]); 1437 CHECK_EQ(test.h, 0); 1438 CHECK_EQ(test.k, outputs_S[i]); 1439 CHECK_EQ(test.l, 0); 1440 1441 test.f = tests_D[j+1]; 1442 test.j = tests_S[j+1]; 1443 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 1444 CHECK_EQ(test.g, 0); 1445 CHECK_EQ(test.h, outputs_D[i]); 1446 CHECK_EQ(test.k, 0); 1447 CHECK_EQ(test.l, outputs_S[i]); 1448 } 1449 } 1450 } 1451 } 1452 1453 1454 TEST(min_max) { 1455 if (IsMipsArchVariant(kMips32r6)) { 1456 CcTest::InitializeVM(); 1457 Isolate* isolate = CcTest::i_isolate(); 1458 HandleScope scope(isolate); 1459 MacroAssembler assm(isolate, NULL, 0, 1460 v8::internal::CodeObjectRequired::kYes); 1461 1462 typedef struct test_float { 1463 double a; 1464 double b; 1465 double c; 1466 double d; 1467 float e; 1468 float f; 1469 float g; 1470 float h; 1471 } TestFloat; 1472 1473 TestFloat test; 1474 const double double_nan = std::numeric_limits<double>::quiet_NaN(); 1475 const float float_nan = std::numeric_limits<float>::quiet_NaN(); 1476 const int kTableLength = 5; 1477 double inputsa[kTableLength] = {2.0, 3.0, double_nan, 3.0, double_nan}; 1478 double inputsb[kTableLength] = {3.0, 2.0, 3.0, double_nan, double_nan}; 1479 double outputsdmin[kTableLength] = {2.0, 2.0, 3.0, 3.0, double_nan}; 1480 double outputsdmax[kTableLength] = {3.0, 3.0, 3.0, 3.0, double_nan}; 1481 1482 float inputse[kTableLength] = {2.0, 3.0, float_nan, 3.0, float_nan}; 1483 float inputsf[kTableLength] = {3.0, 2.0, 3.0, float_nan, float_nan}; 1484 float outputsfmin[kTableLength] = {2.0, 2.0, 3.0, 3.0, float_nan}; 1485 float outputsfmax[kTableLength] = {3.0, 3.0, 3.0, 3.0, float_nan}; 1486 1487 __ ldc1(f4, MemOperand(a0, offsetof(TestFloat, a))); 1488 __ ldc1(f8, MemOperand(a0, offsetof(TestFloat, b))); 1489 __ lwc1(f2, MemOperand(a0, offsetof(TestFloat, e))); 1490 __ lwc1(f6, MemOperand(a0, offsetof(TestFloat, f))); 1491 __ min_d(f10, f4, f8); 1492 __ max_d(f12, f4, f8); 1493 __ min_s(f14, f2, f6); 1494 __ max_s(f16, f2, f6); 1495 __ sdc1(f10, MemOperand(a0, offsetof(TestFloat, c))); 1496 __ sdc1(f12, MemOperand(a0, offsetof(TestFloat, d))); 1497 __ swc1(f14, MemOperand(a0, offsetof(TestFloat, g))); 1498 __ swc1(f16, MemOperand(a0, offsetof(TestFloat, h))); 1499 __ jr(ra); 1500 __ nop(); 1501 1502 CodeDesc desc; 1503 assm.GetCode(&desc); 1504 Handle<Code> code = isolate->factory()->NewCode( 1505 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 1506 F3 f = FUNCTION_CAST<F3>(code->entry()); 1507 for (int i = 0; i < kTableLength; i++) { 1508 test.a = inputsa[i]; 1509 test.b = inputsb[i]; 1510 test.e = inputse[i]; 1511 test.f = inputsf[i]; 1512 1513 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 1514 1515 if (i < kTableLength - 1) { 1516 CHECK_EQ(test.c, outputsdmin[i]); 1517 CHECK_EQ(test.d, outputsdmax[i]); 1518 CHECK_EQ(test.g, outputsfmin[i]); 1519 CHECK_EQ(test.h, outputsfmax[i]); 1520 } else { 1521 CHECK(std::isnan(test.c)); 1522 CHECK(std::isnan(test.d)); 1523 CHECK(std::isnan(test.g)); 1524 CHECK(std::isnan(test.h)); 1525 } 1526 } 1527 } 1528 } 1529 1530 1531 TEST(rint_d) { 1532 if (IsMipsArchVariant(kMips32r6)) { 1533 const int kTableLength = 30; 1534 CcTest::InitializeVM(); 1535 Isolate* isolate = CcTest::i_isolate(); 1536 HandleScope scope(isolate); 1537 MacroAssembler assm(isolate, NULL, 0, 1538 v8::internal::CodeObjectRequired::kYes); 1539 1540 typedef struct test_float { 1541 double a; 1542 double b; 1543 int fcsr; 1544 }TestFloat; 1545 1546 TestFloat test; 1547 double inputs[kTableLength] = {18446744073709551617.0, 1548 4503599627370496.0, -4503599627370496.0, 1549 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E147, 1550 1.7976931348623157E+308, 6.27463370218383111104242366943E-307, 1551 309485009821345068724781056.89, 1552 2.1, 2.6, 2.5, 3.1, 3.6, 3.5, 1553 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5, 1554 37778931862957161709568.0, 37778931862957161709569.0, 1555 37778931862957161709580.0, 37778931862957161709581.0, 1556 37778931862957161709582.0, 37778931862957161709583.0, 1557 37778931862957161709584.0, 37778931862957161709585.0, 1558 37778931862957161709586.0, 37778931862957161709587.0}; 1559 double outputs_RN[kTableLength] = {18446744073709551617.0, 1560 4503599627370496.0, -4503599627370496.0, 1561 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E147, 1562 1.7976931348623157E308, 0, 1563 309485009821345068724781057.0, 1564 2.0, 3.0, 2.0, 3.0, 4.0, 4.0, 1565 -2.0, -3.0, -2.0, -3.0, -4.0, -4.0, 1566 37778931862957161709568.0, 37778931862957161709569.0, 1567 37778931862957161709580.0, 37778931862957161709581.0, 1568 37778931862957161709582.0, 37778931862957161709583.0, 1569 37778931862957161709584.0, 37778931862957161709585.0, 1570 37778931862957161709586.0, 37778931862957161709587.0}; 1571 double outputs_RZ[kTableLength] = {18446744073709551617.0, 1572 4503599627370496.0, -4503599627370496.0, 1573 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E147, 1574 1.7976931348623157E308, 0, 1575 309485009821345068724781057.0, 1576 2.0, 2.0, 2.0, 3.0, 3.0, 3.0, 1577 -2.0, -2.0, -2.0, -3.0, -3.0, -3.0, 1578 37778931862957161709568.0, 37778931862957161709569.0, 1579 37778931862957161709580.0, 37778931862957161709581.0, 1580 37778931862957161709582.0, 37778931862957161709583.0, 1581 37778931862957161709584.0, 37778931862957161709585.0, 1582 37778931862957161709586.0, 37778931862957161709587.0}; 1583 double outputs_RP[kTableLength] = {18446744073709551617.0, 1584 4503599627370496.0, -4503599627370496.0, 1585 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E147, 1586 1.7976931348623157E308, 1, 1587 309485009821345068724781057.0, 1588 3.0, 3.0, 3.0, 4.0, 4.0, 4.0, 1589 -2.0, -2.0, -2.0, -3.0, -3.0, -3.0, 1590 37778931862957161709568.0, 37778931862957161709569.0, 1591 37778931862957161709580.0, 37778931862957161709581.0, 1592 37778931862957161709582.0, 37778931862957161709583.0, 1593 37778931862957161709584.0, 37778931862957161709585.0, 1594 37778931862957161709586.0, 37778931862957161709587.0}; 1595 double outputs_RM[kTableLength] = {18446744073709551617.0, 1596 4503599627370496.0, -4503599627370496.0, 1597 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E147, 1598 1.7976931348623157E308, 0, 1599 309485009821345068724781057.0, 1600 2.0, 2.0, 2.0, 3.0, 3.0, 3.0, 1601 -3.0, -3.0, -3.0, -4.0, -4.0, -4.0, 1602 37778931862957161709568.0, 37778931862957161709569.0, 1603 37778931862957161709580.0, 37778931862957161709581.0, 1604 37778931862957161709582.0, 37778931862957161709583.0, 1605 37778931862957161709584.0, 37778931862957161709585.0, 1606 37778931862957161709586.0, 37778931862957161709587.0}; 1607 int fcsr_inputs[4] = 1608 {kRoundToNearest, kRoundToZero, kRoundToPlusInf, kRoundToMinusInf}; 1609 double* outputs[4] = {outputs_RN, outputs_RZ, outputs_RP, outputs_RM}; 1610 __ ldc1(f4, MemOperand(a0, offsetof(TestFloat, a)) ); 1611 __ lw(t0, MemOperand(a0, offsetof(TestFloat, fcsr)) ); 1612 __ cfc1(t1, FCSR); 1613 __ ctc1(t0, FCSR); 1614 __ rint_d(f8, f4); 1615 __ sdc1(f8, MemOperand(a0, offsetof(TestFloat, b)) ); 1616 __ ctc1(t1, FCSR); 1617 __ jr(ra); 1618 __ nop(); 1619 1620 CodeDesc desc; 1621 assm.GetCode(&desc); 1622 Handle<Code> code = isolate->factory()->NewCode( 1623 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 1624 F3 f = FUNCTION_CAST<F3>(code->entry()); 1625 1626 for (int j = 0; j < 4; j++) { 1627 test.fcsr = fcsr_inputs[j]; 1628 for (int i = 0; i < kTableLength; i++) { 1629 test.a = inputs[i]; 1630 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 1631 CHECK_EQ(test.b, outputs[j][i]); 1632 } 1633 } 1634 } 1635 } 1636 1637 1638 TEST(sel) { 1639 if (IsMipsArchVariant(kMips32r6)) { 1640 CcTest::InitializeVM(); 1641 Isolate* isolate = CcTest::i_isolate(); 1642 HandleScope scope(isolate); 1643 MacroAssembler assm(isolate, NULL, 0, 1644 v8::internal::CodeObjectRequired::kYes); 1645 1646 typedef struct test { 1647 double dd; 1648 double ds; 1649 double dt; 1650 float fd; 1651 float fs; 1652 float ft; 1653 } Test; 1654 1655 Test test; 1656 __ ldc1(f0, MemOperand(a0, offsetof(Test, dd)) ); // test 1657 __ ldc1(f2, MemOperand(a0, offsetof(Test, ds)) ); // src1 1658 __ ldc1(f4, MemOperand(a0, offsetof(Test, dt)) ); // src2 1659 __ lwc1(f6, MemOperand(a0, offsetof(Test, fd)) ); // test 1660 __ lwc1(f8, MemOperand(a0, offsetof(Test, fs)) ); // src1 1661 __ lwc1(f10, MemOperand(a0, offsetof(Test, ft)) ); // src2 1662 __ sel_d(f0, f2, f4); 1663 __ sel_s(f6, f8, f10); 1664 __ sdc1(f0, MemOperand(a0, offsetof(Test, dd)) ); 1665 __ swc1(f6, MemOperand(a0, offsetof(Test, fd)) ); 1666 __ jr(ra); 1667 __ nop(); 1668 CodeDesc desc; 1669 assm.GetCode(&desc); 1670 Handle<Code> code = isolate->factory()->NewCode( 1671 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 1672 F3 f = FUNCTION_CAST<F3>(code->entry()); 1673 1674 const int test_size = 3; 1675 const int input_size = 5; 1676 1677 double inputs_dt[input_size] = {0.0, 65.2, -70.32, 1678 18446744073709551621.0, -18446744073709551621.0}; 1679 double inputs_ds[input_size] = {0.1, 69.88, -91.325, 1680 18446744073709551625.0, -18446744073709551625.0}; 1681 float inputs_ft[input_size] = {0.0, 65.2, -70.32, 1682 18446744073709551621.0, -18446744073709551621.0}; 1683 float inputs_fs[input_size] = {0.1, 69.88, -91.325, 1684 18446744073709551625.0, -18446744073709551625.0}; 1685 double tests_D[test_size*2] = {2.8, 2.9, -2.8, -2.9, 1686 18446744073709551616.0, 18446744073709555712.0}; 1687 float tests_S[test_size*2] = {2.9, 2.8, -2.9, -2.8, 1688 18446744073709551616.0, 18446746272732807168.0}; 1689 for (int j=0; j < test_size; j+=2) { 1690 for (int i=0; i < input_size; i++) { 1691 test.dt = inputs_dt[i]; 1692 test.dd = tests_D[j]; 1693 test.ds = inputs_ds[i]; 1694 test.ft = inputs_ft[i]; 1695 test.fd = tests_S[j]; 1696 test.fs = inputs_fs[i]; 1697 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 1698 CHECK_EQ(test.dd, inputs_ds[i]); 1699 CHECK_EQ(test.fd, inputs_fs[i]); 1700 1701 test.dd = tests_D[j+1]; 1702 test.fd = tests_S[j+1]; 1703 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 1704 CHECK_EQ(test.dd, inputs_dt[i]); 1705 CHECK_EQ(test.fd, inputs_ft[i]); 1706 } 1707 } 1708 } 1709 } 1710 1711 1712 TEST(rint_s) { 1713 if (IsMipsArchVariant(kMips32r6)) { 1714 const int kTableLength = 30; 1715 CcTest::InitializeVM(); 1716 Isolate* isolate = CcTest::i_isolate(); 1717 HandleScope scope(isolate); 1718 MacroAssembler assm(isolate, NULL, 0, 1719 v8::internal::CodeObjectRequired::kYes); 1720 1721 typedef struct test_float { 1722 float a; 1723 float b; 1724 int fcsr; 1725 }TestFloat; 1726 1727 TestFloat test; 1728 float inputs[kTableLength] = {18446744073709551617.0, 1729 4503599627370496.0, -4503599627370496.0, 1730 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E37, 1731 1.7976931348623157E+38, 6.27463370218383111104242366943E-37, 1732 309485009821345068724781056.89, 1733 2.1, 2.6, 2.5, 3.1, 3.6, 3.5, 1734 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5, 1735 37778931862957161709568.0, 37778931862957161709569.0, 1736 37778931862957161709580.0, 37778931862957161709581.0, 1737 37778931862957161709582.0, 37778931862957161709583.0, 1738 37778931862957161709584.0, 37778931862957161709585.0, 1739 37778931862957161709586.0, 37778931862957161709587.0}; 1740 float outputs_RN[kTableLength] = {18446744073709551617.0, 1741 4503599627370496.0, -4503599627370496.0, 1742 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E37, 1743 1.7976931348623157E38, 0, 1744 309485009821345068724781057.0, 1745 2.0, 3.0, 2.0, 3.0, 4.0, 4.0, 1746 -2.0, -3.0, -2.0, -3.0, -4.0, -4.0, 1747 37778931862957161709568.0, 37778931862957161709569.0, 1748 37778931862957161709580.0, 37778931862957161709581.0, 1749 37778931862957161709582.0, 37778931862957161709583.0, 1750 37778931862957161709584.0, 37778931862957161709585.0, 1751 37778931862957161709586.0, 37778931862957161709587.0}; 1752 float outputs_RZ[kTableLength] = {18446744073709551617.0, 1753 4503599627370496.0, -4503599627370496.0, 1754 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E37, 1755 1.7976931348623157E38, 0, 1756 309485009821345068724781057.0, 1757 2.0, 2.0, 2.0, 3.0, 3.0, 3.0, 1758 -2.0, -2.0, -2.0, -3.0, -3.0, -3.0, 1759 37778931862957161709568.0, 37778931862957161709569.0, 1760 37778931862957161709580.0, 37778931862957161709581.0, 1761 37778931862957161709582.0, 37778931862957161709583.0, 1762 37778931862957161709584.0, 37778931862957161709585.0, 1763 37778931862957161709586.0, 37778931862957161709587.0}; 1764 float outputs_RP[kTableLength] = {18446744073709551617.0, 1765 4503599627370496.0, -4503599627370496.0, 1766 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E37, 1767 1.7976931348623157E38, 1, 1768 309485009821345068724781057.0, 1769 3.0, 3.0, 3.0, 4.0, 4.0, 4.0, 1770 -2.0, -2.0, -2.0, -3.0, -3.0, -3.0, 1771 37778931862957161709568.0, 37778931862957161709569.0, 1772 37778931862957161709580.0, 37778931862957161709581.0, 1773 37778931862957161709582.0, 37778931862957161709583.0, 1774 37778931862957161709584.0, 37778931862957161709585.0, 1775 37778931862957161709586.0, 37778931862957161709587.0}; 1776 float outputs_RM[kTableLength] = {18446744073709551617.0, 1777 4503599627370496.0, -4503599627370496.0, 1778 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E37, 1779 1.7976931348623157E38, 0, 1780 309485009821345068724781057.0, 1781 2.0, 2.0, 2.0, 3.0, 3.0, 3.0, 1782 -3.0, -3.0, -3.0, -4.0, -4.0, -4.0, 1783 37778931862957161709568.0, 37778931862957161709569.0, 1784 37778931862957161709580.0, 37778931862957161709581.0, 1785 37778931862957161709582.0, 37778931862957161709583.0, 1786 37778931862957161709584.0, 37778931862957161709585.0, 1787 37778931862957161709586.0, 37778931862957161709587.0}; 1788 int fcsr_inputs[4] = 1789 {kRoundToNearest, kRoundToZero, kRoundToPlusInf, kRoundToMinusInf}; 1790 float* outputs[4] = {outputs_RN, outputs_RZ, outputs_RP, outputs_RM}; 1791 __ lwc1(f4, MemOperand(a0, offsetof(TestFloat, a)) ); 1792 __ lw(t0, MemOperand(a0, offsetof(TestFloat, fcsr)) ); 1793 __ cfc1(t1, FCSR); 1794 __ ctc1(t0, FCSR); 1795 __ rint_s(f8, f4); 1796 __ swc1(f8, MemOperand(a0, offsetof(TestFloat, b)) ); 1797 __ ctc1(t1, FCSR); 1798 __ jr(ra); 1799 __ nop(); 1800 1801 CodeDesc desc; 1802 assm.GetCode(&desc); 1803 Handle<Code> code = isolate->factory()->NewCode( 1804 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 1805 F3 f = FUNCTION_CAST<F3>(code->entry()); 1806 1807 for (int j = 0; j < 4; j++) { 1808 test.fcsr = fcsr_inputs[j]; 1809 for (int i = 0; i < kTableLength; i++) { 1810 test.a = inputs[i]; 1811 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 1812 CHECK_EQ(test.b, outputs[j][i]); 1813 } 1814 } 1815 } 1816 } 1817 1818 1819 TEST(Cvt_d_uw) { 1820 CcTest::InitializeVM(); 1821 Isolate* isolate = CcTest::i_isolate(); 1822 HandleScope scope(isolate); 1823 MacroAssembler assm(isolate, NULL, 0, 1824 v8::internal::CodeObjectRequired::kYes); 1825 1826 typedef struct test_struct { 1827 unsigned input; 1828 uint64_t output; 1829 } TestStruct; 1830 1831 unsigned inputs[] = { 1832 0x0, 0xffffffff, 0x80000000, 0x7fffffff 1833 }; 1834 1835 uint64_t outputs[] = { 1836 0x0, 0x41efffffffe00000, 1837 0x41e0000000000000, 0x41dfffffffc00000 1838 }; 1839 1840 int kTableLength = sizeof(inputs)/sizeof(inputs[0]); 1841 1842 TestStruct test; 1843 1844 __ lw(t1, MemOperand(a0, offsetof(TestStruct, input))); 1845 __ Cvt_d_uw(f4, t1, f6); 1846 __ sdc1(f4, MemOperand(a0, offsetof(TestStruct, output))); 1847 __ jr(ra); 1848 __ nop(); 1849 1850 CodeDesc desc; 1851 assm.GetCode(&desc); 1852 Handle<Code> code = isolate->factory()->NewCode( 1853 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 1854 F3 f = FUNCTION_CAST<F3>(code->entry()); 1855 for (int i = 0; i < kTableLength; i++) { 1856 test.input = inputs[i]; 1857 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 1858 // Check outputs 1859 CHECK_EQ(test.output, outputs[i]); 1860 } 1861 } 1862 1863 1864 TEST(mina_maxa) { 1865 if (IsMipsArchVariant(kMips32r6)) { 1866 const int kTableLength = 15; 1867 CcTest::InitializeVM(); 1868 Isolate* isolate = CcTest::i_isolate(); 1869 HandleScope scope(isolate); 1870 MacroAssembler assm(isolate, NULL, 0, 1871 v8::internal::CodeObjectRequired::kYes); 1872 const double double_nan = std::numeric_limits<double>::quiet_NaN(); 1873 const float float_nan = std::numeric_limits<float>::quiet_NaN(); 1874 1875 typedef struct test_float { 1876 double a; 1877 double b; 1878 double resd; 1879 double resd1; 1880 float c; 1881 float d; 1882 float resf; 1883 float resf1; 1884 }TestFloat; 1885 1886 TestFloat test; 1887 double inputsa[kTableLength] = { 1888 5.3, 4.8, 6.1, 9.8, 9.8, 9.8, -10.0, -8.9, 1889 -9.8, -10.0, -8.9, -9.8, double_nan, 3.0, double_nan 1890 }; 1891 double inputsb[kTableLength] = { 1892 4.8, 5.3, 6.1, -10.0, -8.9, -9.8, 9.8, 9.8, 1893 9.8, -9.8, -11.2, -9.8, 3.0, double_nan, double_nan 1894 }; 1895 double resd[kTableLength] = { 1896 4.8, 4.8, 6.1, 9.8, -8.9, -9.8, 9.8, -8.9, 1897 -9.8, -9.8, -8.9, -9.8, 3.0, 3.0, double_nan 1898 }; 1899 double resd1[kTableLength] = { 1900 5.3, 5.3, 6.1, -10.0, 9.8, 9.8, -10.0, 9.8, 1901 9.8, -10.0, -11.2, -9.8, 3.0, 3.0, double_nan 1902 }; 1903 float inputsc[kTableLength] = { 1904 5.3, 4.8, 6.1, 9.8, 9.8, 9.8, -10.0, -8.9, 1905 -9.8, -10.0, -8.9, -9.8, float_nan, 3.0, float_nan 1906 }; 1907 float inputsd[kTableLength] = { 1908 4.8, 5.3, 6.1, -10.0, -8.9, -9.8, 9.8, 9.8, 1909 9.8, -9.8, -11.2, -9.8, 3.0, float_nan, float_nan 1910 }; 1911 float resf[kTableLength] = { 1912 4.8, 4.8, 6.1, 9.8, -8.9, -9.8, 9.8, -8.9, 1913 -9.8, -9.8, -8.9, -9.8, 3.0, 3.0, float_nan 1914 }; 1915 float resf1[kTableLength] = { 1916 5.3, 5.3, 6.1, -10.0, 9.8, 9.8, -10.0, 9.8, 1917 9.8, -10.0, -11.2, -9.8, 3.0, 3.0, float_nan 1918 }; 1919 1920 __ ldc1(f2, MemOperand(a0, offsetof(TestFloat, a)) ); 1921 __ ldc1(f4, MemOperand(a0, offsetof(TestFloat, b)) ); 1922 __ lwc1(f8, MemOperand(a0, offsetof(TestFloat, c)) ); 1923 __ lwc1(f10, MemOperand(a0, offsetof(TestFloat, d)) ); 1924 __ mina_d(f6, f2, f4); 1925 __ mina_s(f12, f8, f10); 1926 __ maxa_d(f14, f2, f4); 1927 __ maxa_s(f16, f8, f10); 1928 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, resf)) ); 1929 __ sdc1(f6, MemOperand(a0, offsetof(TestFloat, resd)) ); 1930 __ swc1(f16, MemOperand(a0, offsetof(TestFloat, resf1)) ); 1931 __ sdc1(f14, MemOperand(a0, offsetof(TestFloat, resd1)) ); 1932 __ jr(ra); 1933 __ nop(); 1934 1935 CodeDesc desc; 1936 assm.GetCode(&desc); 1937 Handle<Code> code = isolate->factory()->NewCode( 1938 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 1939 F3 f = FUNCTION_CAST<F3>(code->entry()); 1940 for (int i = 0; i < kTableLength; i++) { 1941 test.a = inputsa[i]; 1942 test.b = inputsb[i]; 1943 test.c = inputsc[i]; 1944 test.d = inputsd[i]; 1945 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 1946 if (i < kTableLength - 1) { 1947 CHECK_EQ(test.resd, resd[i]); 1948 CHECK_EQ(test.resf, resf[i]); 1949 CHECK_EQ(test.resd1, resd1[i]); 1950 CHECK_EQ(test.resf1, resf1[i]); 1951 } else { 1952 CHECK(std::isnan(test.resd)); 1953 CHECK(std::isnan(test.resf)); 1954 CHECK(std::isnan(test.resd1)); 1955 CHECK(std::isnan(test.resf1)); 1956 } 1957 } 1958 } 1959 } 1960 1961 1962 // ----------------------mips32r2 specific tests---------------------- 1963 TEST(trunc_l) { 1964 if (IsMipsArchVariant(kMips32r2) && IsFp64Mode()) { 1965 CcTest::InitializeVM(); 1966 Isolate* isolate = CcTest::i_isolate(); 1967 HandleScope scope(isolate); 1968 MacroAssembler assm(isolate, NULL, 0, 1969 v8::internal::CodeObjectRequired::kYes); 1970 const double dFPU64InvalidResult = static_cast<double>(kFPU64InvalidResult); 1971 typedef struct test_float { 1972 uint32_t isNaN2008; 1973 double a; 1974 float b; 1975 int64_t c; // a trunc result 1976 int64_t d; // b trunc result 1977 }Test; 1978 const int kTableLength = 15; 1979 double inputs_D[kTableLength] = { 1980 2.1, 2.6, 2.5, 3.1, 3.6, 3.5, 1981 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5, 1982 2147483648.0, 1983 std::numeric_limits<double>::quiet_NaN(), 1984 std::numeric_limits<double>::infinity() 1985 }; 1986 float inputs_S[kTableLength] = { 1987 2.1, 2.6, 2.5, 3.1, 3.6, 3.5, 1988 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5, 1989 2147483648.0, 1990 std::numeric_limits<float>::quiet_NaN(), 1991 std::numeric_limits<float>::infinity() 1992 }; 1993 double outputs[kTableLength] = { 1994 2.0, 2.0, 2.0, 3.0, 3.0, 3.0, 1995 -2.0, -2.0, -2.0, -3.0, -3.0, -3.0, 1996 2147483648.0, dFPU64InvalidResult, 1997 dFPU64InvalidResult}; 1998 double outputsNaN2008[kTableLength] = { 1999 2.0, 2.0, 2.0, 3.0, 3.0, 3.0, 2000 -2.0, -2.0, -2.0, -3.0, -3.0, -3.0, 2001 2147483648.0, 2002 0, 2003 dFPU64InvalidResult}; 2004 2005 __ cfc1(t1, FCSR); 2006 __ sw(t1, MemOperand(a0, offsetof(Test, isNaN2008))); 2007 __ ldc1(f4, MemOperand(a0, offsetof(Test, a)) ); 2008 __ lwc1(f6, MemOperand(a0, offsetof(Test, b)) ); 2009 __ trunc_l_d(f8, f4); 2010 __ trunc_l_s(f10, f6); 2011 __ sdc1(f8, MemOperand(a0, offsetof(Test, c)) ); 2012 __ sdc1(f10, MemOperand(a0, offsetof(Test, d)) ); 2013 __ jr(ra); 2014 __ nop(); 2015 Test test; 2016 CodeDesc desc; 2017 assm.GetCode(&desc); 2018 Handle<Code> code = isolate->factory()->NewCode( 2019 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 2020 F3 f = FUNCTION_CAST<F3>(code->entry()); 2021 for (int i = 0; i < kTableLength; i++) { 2022 test.a = inputs_D[i]; 2023 test.b = inputs_S[i]; 2024 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 2025 if ((test.isNaN2008 & kFCSRNaN2008FlagMask) && 2026 kArchVariant == kMips32r6) { 2027 CHECK_EQ(test.c, outputsNaN2008[i]); 2028 } else { 2029 CHECK_EQ(test.c, outputs[i]); 2030 } 2031 CHECK_EQ(test.d, test.c); 2032 } 2033 } 2034 } 2035 2036 2037 TEST(movz_movn) { 2038 if (IsMipsArchVariant(kMips32r2)) { 2039 const int kTableLength = 4; 2040 CcTest::InitializeVM(); 2041 Isolate* isolate = CcTest::i_isolate(); 2042 HandleScope scope(isolate); 2043 MacroAssembler assm(isolate, NULL, 0, 2044 v8::internal::CodeObjectRequired::kYes); 2045 2046 typedef struct test_float { 2047 int64_t rt; 2048 double a; 2049 double b; 2050 double bold; 2051 double b1; 2052 double bold1; 2053 float c; 2054 float d; 2055 float dold; 2056 float d1; 2057 float dold1; 2058 }TestFloat; 2059 2060 TestFloat test; 2061 double inputs_D[kTableLength] = { 2062 5.3, -5.3, 5.3, -2.9 2063 }; 2064 double inputs_S[kTableLength] = { 2065 4.8, 4.8, -4.8, -0.29 2066 }; 2067 2068 float outputs_S[kTableLength] = { 2069 4.8, 4.8, -4.8, -0.29 2070 }; 2071 double outputs_D[kTableLength] = { 2072 5.3, -5.3, 5.3, -2.9 2073 }; 2074 2075 __ ldc1(f2, MemOperand(a0, offsetof(TestFloat, a)) ); 2076 __ lwc1(f6, MemOperand(a0, offsetof(TestFloat, c)) ); 2077 __ lw(t0, MemOperand(a0, offsetof(TestFloat, rt)) ); 2078 __ Move(f12, 0.0); 2079 __ Move(f10, 0.0); 2080 __ Move(f16, 0.0); 2081 __ Move(f14, 0.0); 2082 __ sdc1(f12, MemOperand(a0, offsetof(TestFloat, bold)) ); 2083 __ swc1(f10, MemOperand(a0, offsetof(TestFloat, dold)) ); 2084 __ sdc1(f16, MemOperand(a0, offsetof(TestFloat, bold1)) ); 2085 __ swc1(f14, MemOperand(a0, offsetof(TestFloat, dold1)) ); 2086 __ movz_s(f10, f6, t0); 2087 __ movz_d(f12, f2, t0); 2088 __ movn_s(f14, f6, t0); 2089 __ movn_d(f16, f2, t0); 2090 __ swc1(f10, MemOperand(a0, offsetof(TestFloat, d)) ); 2091 __ sdc1(f12, MemOperand(a0, offsetof(TestFloat, b)) ); 2092 __ swc1(f14, MemOperand(a0, offsetof(TestFloat, d1)) ); 2093 __ sdc1(f16, MemOperand(a0, offsetof(TestFloat, b1)) ); 2094 __ jr(ra); 2095 __ nop(); 2096 2097 CodeDesc desc; 2098 assm.GetCode(&desc); 2099 Handle<Code> code = isolate->factory()->NewCode( 2100 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 2101 F3 f = FUNCTION_CAST<F3>(code->entry()); 2102 for (int i = 0; i < kTableLength; i++) { 2103 test.a = inputs_D[i]; 2104 test.c = inputs_S[i]; 2105 2106 test.rt = 1; 2107 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 2108 CHECK_EQ(test.b, test.bold); 2109 CHECK_EQ(test.d, test.dold); 2110 CHECK_EQ(test.b1, outputs_D[i]); 2111 CHECK_EQ(test.d1, outputs_S[i]); 2112 2113 test.rt = 0; 2114 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 2115 CHECK_EQ(test.b, outputs_D[i]); 2116 CHECK_EQ(test.d, outputs_S[i]); 2117 CHECK_EQ(test.b1, test.bold1); 2118 CHECK_EQ(test.d1, test.dold1); 2119 } 2120 } 2121 } 2122 2123 2124 TEST(movt_movd) { 2125 if (IsMipsArchVariant(kMips32r2)) { 2126 const int kTableLength = 4; 2127 CcTest::InitializeVM(); 2128 Isolate* isolate = CcTest::i_isolate(); 2129 2130 typedef struct test_float { 2131 double srcd; 2132 double dstd; 2133 double dstdold; 2134 double dstd1; 2135 double dstdold1; 2136 float srcf; 2137 float dstf; 2138 float dstfold; 2139 float dstf1; 2140 float dstfold1; 2141 int32_t cc; 2142 int32_t fcsr; 2143 }TestFloat; 2144 2145 TestFloat test; 2146 double inputs_D[kTableLength] = { 2147 5.3, -5.3, 20.8, -2.9 2148 }; 2149 double inputs_S[kTableLength] = { 2150 4.88, 4.8, -4.8, -0.29 2151 }; 2152 2153 float outputs_S[kTableLength] = { 2154 4.88, 4.8, -4.8, -0.29 2155 }; 2156 double outputs_D[kTableLength] = { 2157 5.3, -5.3, 20.8, -2.9 2158 }; 2159 int condition_flags[8] = {0, 1, 2, 3, 4, 5, 6, 7}; 2160 2161 for (int i = 0; i < kTableLength; i++) { 2162 test.srcd = inputs_D[i]; 2163 test.srcf = inputs_S[i]; 2164 2165 for (int j = 0; j< 8; j++) { 2166 test.cc = condition_flags[j]; 2167 if (test.cc == 0) { 2168 test.fcsr = 1 << 23; 2169 } else { 2170 test.fcsr = 1 << (24+condition_flags[j]); 2171 } 2172 HandleScope scope(isolate); 2173 MacroAssembler assm(isolate, NULL, 0, 2174 v8::internal::CodeObjectRequired::kYes); 2175 __ ldc1(f2, MemOperand(a0, offsetof(TestFloat, srcd)) ); 2176 __ lwc1(f4, MemOperand(a0, offsetof(TestFloat, srcf)) ); 2177 __ lw(t1, MemOperand(a0, offsetof(TestFloat, fcsr)) ); 2178 __ cfc1(t0, FCSR); 2179 __ ctc1(t1, FCSR); 2180 __ li(t2, 0x0); 2181 __ mtc1(t2, f12); 2182 __ mtc1(t2, f10); 2183 __ sdc1(f10, MemOperand(a0, offsetof(TestFloat, dstdold)) ); 2184 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, dstfold)) ); 2185 __ movt_s(f12, f4, test.cc); 2186 __ movt_d(f10, f2, test.cc); 2187 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, dstf)) ); 2188 __ sdc1(f10, MemOperand(a0, offsetof(TestFloat, dstd)) ); 2189 __ sdc1(f10, MemOperand(a0, offsetof(TestFloat, dstdold1)) ); 2190 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, dstfold1)) ); 2191 __ movf_s(f12, f4, test.cc); 2192 __ movf_d(f10, f2, test.cc); 2193 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, dstf1)) ); 2194 __ sdc1(f10, MemOperand(a0, offsetof(TestFloat, dstd1)) ); 2195 __ ctc1(t0, FCSR); 2196 __ jr(ra); 2197 __ nop(); 2198 2199 CodeDesc desc; 2200 assm.GetCode(&desc); 2201 Handle<Code> code = isolate->factory()->NewCode( 2202 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 2203 F3 f = FUNCTION_CAST<F3>(code->entry()); 2204 2205 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 2206 CHECK_EQ(test.dstf, outputs_S[i]); 2207 CHECK_EQ(test.dstd, outputs_D[i]); 2208 CHECK_EQ(test.dstf1, test.dstfold1); 2209 CHECK_EQ(test.dstd1, test.dstdold1); 2210 test.fcsr = 0; 2211 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 2212 CHECK_EQ(test.dstf, test.dstfold); 2213 CHECK_EQ(test.dstd, test.dstdold); 2214 CHECK_EQ(test.dstf1, outputs_S[i]); 2215 CHECK_EQ(test.dstd1, outputs_D[i]); 2216 } 2217 } 2218 } 2219 } 2220 2221 2222 // ----------------------tests for all archs-------------------------- 2223 TEST(cvt_w_d) { 2224 CcTest::InitializeVM(); 2225 Isolate* isolate = CcTest::i_isolate(); 2226 HandleScope scope(isolate); 2227 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); 2228 2229 typedef struct test_float { 2230 double a; 2231 int32_t b; 2232 int32_t fcsr; 2233 }Test; 2234 const int kTableLength = 24; 2235 double inputs[kTableLength] = { 2236 2.1, 2.6, 2.5, 3.1, 3.6, 3.5, 2237 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5, 2238 2147483637.0, 2147483638.0, 2147483639.0, 2239 2147483640.0, 2147483641.0, 2147483642.0, 2240 2147483643.0, 2147483644.0, 2147483645.0, 2241 2147483646.0, 2147483647.0, 2147483653.0 2242 }; 2243 double outputs_RN[kTableLength] = { 2244 2.0, 3.0, 2.0, 3.0, 4.0, 4.0, 2245 -2.0, -3.0, -2.0, -3.0, -4.0, -4.0, 2246 2147483637.0, 2147483638.0, 2147483639.0, 2247 2147483640.0, 2147483641.0, 2147483642.0, 2248 2147483643.0, 2147483644.0, 2147483645.0, 2249 2147483646.0, 2147483647.0, kFPUInvalidResult}; 2250 double outputs_RZ[kTableLength] = { 2251 2.0, 2.0, 2.0, 3.0, 3.0, 3.0, 2252 -2.0, -2.0, -2.0, -3.0, -3.0, -3.0, 2253 2147483637.0, 2147483638.0, 2147483639.0, 2254 2147483640.0, 2147483641.0, 2147483642.0, 2255 2147483643.0, 2147483644.0, 2147483645.0, 2256 2147483646.0, 2147483647.0, kFPUInvalidResult}; 2257 double outputs_RP[kTableLength] = { 2258 3.0, 3.0, 3.0, 4.0, 4.0, 4.0, 2259 -2.0, -2.0, -2.0, -3.0, -3.0, -3.0, 2260 2147483637.0, 2147483638.0, 2147483639.0, 2261 2147483640.0, 2147483641.0, 2147483642.0, 2262 2147483643.0, 2147483644.0, 2147483645.0, 2263 2147483646.0, 2147483647.0, kFPUInvalidResult}; 2264 double outputs_RM[kTableLength] = { 2265 2.0, 2.0, 2.0, 3.0, 3.0, 3.0, 2266 -3.0, -3.0, -3.0, -4.0, -4.0, -4.0, 2267 2147483637.0, 2147483638.0, 2147483639.0, 2268 2147483640.0, 2147483641.0, 2147483642.0, 2269 2147483643.0, 2147483644.0, 2147483645.0, 2270 2147483646.0, 2147483647.0, kFPUInvalidResult}; 2271 int fcsr_inputs[4] = 2272 {kRoundToNearest, kRoundToZero, kRoundToPlusInf, kRoundToMinusInf}; 2273 double* outputs[4] = {outputs_RN, outputs_RZ, outputs_RP, outputs_RM}; 2274 __ ldc1(f4, MemOperand(a0, offsetof(Test, a)) ); 2275 __ lw(t0, MemOperand(a0, offsetof(Test, fcsr)) ); 2276 __ cfc1(t1, FCSR); 2277 __ ctc1(t0, FCSR); 2278 __ cvt_w_d(f8, f4); 2279 __ swc1(f8, MemOperand(a0, offsetof(Test, b)) ); 2280 __ ctc1(t1, FCSR); 2281 __ jr(ra); 2282 __ nop(); 2283 Test test; 2284 CodeDesc desc; 2285 assm.GetCode(&desc); 2286 Handle<Code> code = isolate->factory()->NewCode( 2287 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 2288 F3 f = FUNCTION_CAST<F3>(code->entry()); 2289 for (int j = 0; j < 4; j++) { 2290 test.fcsr = fcsr_inputs[j]; 2291 for (int i = 0; i < kTableLength; i++) { 2292 test.a = inputs[i]; 2293 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 2294 CHECK_EQ(test.b, outputs[j][i]); 2295 } 2296 } 2297 } 2298 2299 2300 TEST(trunc_w) { 2301 CcTest::InitializeVM(); 2302 Isolate* isolate = CcTest::i_isolate(); 2303 HandleScope scope(isolate); 2304 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); 2305 2306 typedef struct test_float { 2307 uint32_t isNaN2008; 2308 double a; 2309 float b; 2310 int32_t c; // a trunc result 2311 int32_t d; // b trunc result 2312 }Test; 2313 const int kTableLength = 15; 2314 double inputs_D[kTableLength] = { 2315 2.1, 2.6, 2.5, 3.1, 3.6, 3.5, 2316 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5, 2317 2147483648.0, 2318 std::numeric_limits<double>::quiet_NaN(), 2319 std::numeric_limits<double>::infinity() 2320 }; 2321 float inputs_S[kTableLength] = { 2322 2.1, 2.6, 2.5, 3.1, 3.6, 3.5, 2323 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5, 2324 2147483648.0, 2325 std::numeric_limits<float>::quiet_NaN(), 2326 std::numeric_limits<float>::infinity() 2327 }; 2328 double outputs[kTableLength] = { 2329 2.0, 2.0, 2.0, 3.0, 3.0, 3.0, 2330 -2.0, -2.0, -2.0, -3.0, -3.0, -3.0, 2331 kFPUInvalidResult, kFPUInvalidResult, 2332 kFPUInvalidResult}; 2333 double outputsNaN2008[kTableLength] = { 2334 2.0, 2.0, 2.0, 3.0, 3.0, 3.0, 2335 -2.0, -2.0, -2.0, -3.0, -3.0, -3.0, 2336 kFPUInvalidResult, 2337 0, 2338 kFPUInvalidResult}; 2339 2340 __ cfc1(t1, FCSR); 2341 __ sw(t1, MemOperand(a0, offsetof(Test, isNaN2008))); 2342 __ ldc1(f4, MemOperand(a0, offsetof(Test, a)) ); 2343 __ lwc1(f6, MemOperand(a0, offsetof(Test, b)) ); 2344 __ trunc_w_d(f8, f4); 2345 __ trunc_w_s(f10, f6); 2346 __ swc1(f8, MemOperand(a0, offsetof(Test, c)) ); 2347 __ swc1(f10, MemOperand(a0, offsetof(Test, d)) ); 2348 __ jr(ra); 2349 __ nop(); 2350 Test test; 2351 CodeDesc desc; 2352 assm.GetCode(&desc); 2353 Handle<Code> code = isolate->factory()->NewCode( 2354 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 2355 F3 f = FUNCTION_CAST<F3>(code->entry()); 2356 for (int i = 0; i < kTableLength; i++) { 2357 test.a = inputs_D[i]; 2358 test.b = inputs_S[i]; 2359 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 2360 if ((test.isNaN2008 & kFCSRNaN2008FlagMask) && kArchVariant == kMips32r6) { 2361 CHECK_EQ(test.c, outputsNaN2008[i]); 2362 } else { 2363 CHECK_EQ(test.c, outputs[i]); 2364 } 2365 CHECK_EQ(test.d, test.c); 2366 } 2367 } 2368 2369 2370 TEST(round_w) { 2371 CcTest::InitializeVM(); 2372 Isolate* isolate = CcTest::i_isolate(); 2373 HandleScope scope(isolate); 2374 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); 2375 2376 typedef struct test_float { 2377 uint32_t isNaN2008; 2378 double a; 2379 float b; 2380 int32_t c; // a trunc result 2381 int32_t d; // b trunc result 2382 }Test; 2383 const int kTableLength = 15; 2384 double inputs_D[kTableLength] = { 2385 2.1, 2.6, 2.5, 3.1, 3.6, 3.5, 2386 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5, 2387 2147483648.0, 2388 std::numeric_limits<double>::quiet_NaN(), 2389 std::numeric_limits<double>::infinity() 2390 }; 2391 float inputs_S[kTableLength] = { 2392 2.1, 2.6, 2.5, 3.1, 3.6, 3.5, 2393 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5, 2394 2147483648.0, 2395 std::numeric_limits<float>::quiet_NaN(), 2396 std::numeric_limits<float>::infinity() 2397 }; 2398 double outputs[kTableLength] = { 2399 2.0, 3.0, 2.0, 3.0, 4.0, 4.0, 2400 -2.0, -3.0, -2.0, -3.0, -4.0, -4.0, 2401 kFPUInvalidResult, kFPUInvalidResult, 2402 kFPUInvalidResult}; 2403 double outputsNaN2008[kTableLength] = { 2404 2.0, 3.0, 2.0, 3.0, 4.0, 4.0, 2405 -2.0, -3.0, -2.0, -3.0, -4.0, -4.0, 2406 kFPUInvalidResult, 0, 2407 kFPUInvalidResult}; 2408 2409 __ cfc1(t1, FCSR); 2410 __ sw(t1, MemOperand(a0, offsetof(Test, isNaN2008))); 2411 __ ldc1(f4, MemOperand(a0, offsetof(Test, a)) ); 2412 __ lwc1(f6, MemOperand(a0, offsetof(Test, b)) ); 2413 __ round_w_d(f8, f4); 2414 __ round_w_s(f10, f6); 2415 __ swc1(f8, MemOperand(a0, offsetof(Test, c)) ); 2416 __ swc1(f10, MemOperand(a0, offsetof(Test, d)) ); 2417 __ jr(ra); 2418 __ nop(); 2419 Test test; 2420 CodeDesc desc; 2421 assm.GetCode(&desc); 2422 Handle<Code> code = isolate->factory()->NewCode( 2423 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 2424 F3 f = FUNCTION_CAST<F3>(code->entry()); 2425 for (int i = 0; i < kTableLength; i++) { 2426 test.a = inputs_D[i]; 2427 test.b = inputs_S[i]; 2428 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 2429 if ((test.isNaN2008 & kFCSRNaN2008FlagMask) && kArchVariant == kMips32r6) { 2430 CHECK_EQ(test.c, outputsNaN2008[i]); 2431 } else { 2432 CHECK_EQ(test.c, outputs[i]); 2433 } 2434 CHECK_EQ(test.d, test.c); 2435 } 2436 } 2437 2438 2439 TEST(round_l) { 2440 if (IsFp64Mode()) { 2441 CcTest::InitializeVM(); 2442 Isolate* isolate = CcTest::i_isolate(); 2443 HandleScope scope(isolate); 2444 MacroAssembler assm(isolate, NULL, 0, 2445 v8::internal::CodeObjectRequired::kYes); 2446 const double dFPU64InvalidResult = static_cast<double>(kFPU64InvalidResult); 2447 typedef struct test_float { 2448 uint32_t isNaN2008; 2449 double a; 2450 float b; 2451 int64_t c; 2452 int64_t d; 2453 }Test; 2454 const int kTableLength = 15; 2455 double inputs_D[kTableLength] = { 2456 2.1, 2.6, 2.5, 3.1, 3.6, 3.5, 2457 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5, 2458 2147483648.0, 2459 std::numeric_limits<double>::quiet_NaN(), 2460 std::numeric_limits<double>::infinity() 2461 }; 2462 float inputs_S[kTableLength] = { 2463 2.1, 2.6, 2.5, 3.1, 3.6, 3.5, 2464 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5, 2465 2147483648.0, 2466 std::numeric_limits<float>::quiet_NaN(), 2467 std::numeric_limits<float>::infinity() 2468 }; 2469 double outputs[kTableLength] = { 2470 2.0, 3.0, 2.0, 3.0, 4.0, 4.0, 2471 -2.0, -3.0, -2.0, -3.0, -4.0, -4.0, 2472 2147483648.0, dFPU64InvalidResult, 2473 dFPU64InvalidResult}; 2474 double outputsNaN2008[kTableLength] = { 2475 2.0, 3.0, 2.0, 3.0, 4.0, 4.0, 2476 -2.0, -3.0, -2.0, -3.0, -4.0, -4.0, 2477 2147483648.0, 2478 0, 2479 dFPU64InvalidResult}; 2480 2481 __ cfc1(t1, FCSR); 2482 __ sw(t1, MemOperand(a0, offsetof(Test, isNaN2008))); 2483 __ ldc1(f4, MemOperand(a0, offsetof(Test, a)) ); 2484 __ lwc1(f6, MemOperand(a0, offsetof(Test, b)) ); 2485 __ round_l_d(f8, f4); 2486 __ round_l_s(f10, f6); 2487 __ sdc1(f8, MemOperand(a0, offsetof(Test, c)) ); 2488 __ sdc1(f10, MemOperand(a0, offsetof(Test, d)) ); 2489 __ jr(ra); 2490 __ nop(); 2491 Test test; 2492 CodeDesc desc; 2493 assm.GetCode(&desc); 2494 Handle<Code> code = isolate->factory()->NewCode( 2495 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 2496 F3 f = FUNCTION_CAST<F3>(code->entry()); 2497 for (int i = 0; i < kTableLength; i++) { 2498 test.a = inputs_D[i]; 2499 test.b = inputs_S[i]; 2500 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 2501 if ((test.isNaN2008 & kFCSRNaN2008FlagMask) && 2502 kArchVariant == kMips32r6) { 2503 CHECK_EQ(test.c, outputsNaN2008[i]); 2504 } else { 2505 CHECK_EQ(test.c, outputs[i]); 2506 } 2507 CHECK_EQ(test.d, test.c); 2508 } 2509 } 2510 } 2511 2512 2513 TEST(sub) { 2514 const int kTableLength = 12; 2515 CcTest::InitializeVM(); 2516 Isolate* isolate = CcTest::i_isolate(); 2517 HandleScope scope(isolate); 2518 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); 2519 2520 typedef struct test_float { 2521 float a; 2522 float b; 2523 float resultS; 2524 double c; 2525 double d; 2526 double resultD; 2527 }TestFloat; 2528 2529 TestFloat test; 2530 double inputfs_D[kTableLength] = { 2531 5.3, 4.8, 2.9, -5.3, -4.8, -2.9, 2532 5.3, 4.8, 2.9, -5.3, -4.8, -2.9 2533 }; 2534 double inputft_D[kTableLength] = { 2535 4.8, 5.3, 2.9, 4.8, 5.3, 2.9, 2536 -4.8, -5.3, -2.9, -4.8, -5.3, -2.9 2537 }; 2538 double outputs_D[kTableLength] = { 2539 0.5, -0.5, 0.0, -10.1, -10.1, -5.8, 2540 10.1, 10.1, 5.8, -0.5, 0.5, 0.0 2541 }; 2542 float inputfs_S[kTableLength] = { 2543 5.3, 4.8, 2.9, -5.3, -4.8, -2.9, 2544 5.3, 4.8, 2.9, -5.3, -4.8, -2.9 2545 }; 2546 float inputft_S[kTableLength] = { 2547 4.8, 5.3, 2.9, 4.8, 5.3, 2.9, 2548 -4.8, -5.3, -2.9, -4.8, -5.3, -2.9 2549 }; 2550 float outputs_S[kTableLength] = { 2551 0.5, -0.5, 0.0, -10.1, -10.1, -5.8, 2552 10.1, 10.1, 5.8, -0.5, 0.5, 0.0 2553 }; 2554 __ lwc1(f2, MemOperand(a0, offsetof(TestFloat, a)) ); 2555 __ lwc1(f4, MemOperand(a0, offsetof(TestFloat, b)) ); 2556 __ ldc1(f8, MemOperand(a0, offsetof(TestFloat, c)) ); 2557 __ ldc1(f10, MemOperand(a0, offsetof(TestFloat, d)) ); 2558 __ sub_s(f6, f2, f4); 2559 __ sub_d(f12, f8, f10); 2560 __ swc1(f6, MemOperand(a0, offsetof(TestFloat, resultS)) ); 2561 __ sdc1(f12, MemOperand(a0, offsetof(TestFloat, resultD)) ); 2562 __ jr(ra); 2563 __ nop(); 2564 2565 CodeDesc desc; 2566 assm.GetCode(&desc); 2567 Handle<Code> code = isolate->factory()->NewCode( 2568 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 2569 F3 f = FUNCTION_CAST<F3>(code->entry()); 2570 for (int i = 0; i < kTableLength; i++) { 2571 test.a = inputfs_S[i]; 2572 test.b = inputft_S[i]; 2573 test.c = inputfs_D[i]; 2574 test.d = inputft_D[i]; 2575 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 2576 CHECK_EQ(test.resultS, outputs_S[i]); 2577 CHECK_EQ(test.resultD, outputs_D[i]); 2578 } 2579 } 2580 2581 2582 TEST(sqrt_rsqrt_recip) { 2583 const int kTableLength = 4; 2584 const double deltaDouble = 2E-15; 2585 const float deltaFloat = 2E-7; 2586 const float sqrt2_s = sqrt(2); 2587 const double sqrt2_d = sqrt(2); 2588 CcTest::InitializeVM(); 2589 Isolate* isolate = CcTest::i_isolate(); 2590 HandleScope scope(isolate); 2591 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); 2592 2593 typedef struct test_float { 2594 float a; 2595 float resultS; 2596 float resultS1; 2597 float resultS2; 2598 double c; 2599 double resultD; 2600 double resultD1; 2601 double resultD2; 2602 }TestFloat; 2603 TestFloat test; 2604 2605 double inputs_D[kTableLength] = { 2606 0.0L, 4.0L, 2.0L, 4e-28L 2607 }; 2608 2609 double outputs_D[kTableLength] = { 2610 0.0L, 2.0L, sqrt2_d, 2e-14L 2611 }; 2612 float inputs_S[kTableLength] = { 2613 0.0, 4.0, 2.0, 4e-28 2614 }; 2615 2616 float outputs_S[kTableLength] = { 2617 0.0, 2.0, sqrt2_s, 2e-14 2618 }; 2619 2620 2621 __ lwc1(f2, MemOperand(a0, offsetof(TestFloat, a)) ); 2622 __ ldc1(f8, MemOperand(a0, offsetof(TestFloat, c)) ); 2623 __ sqrt_s(f6, f2); 2624 __ sqrt_d(f12, f8); 2625 2626 if (IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) { 2627 __ rsqrt_d(f14, f8); 2628 __ rsqrt_s(f16, f2); 2629 __ recip_d(f18, f8); 2630 __ recip_s(f4, f2); 2631 } 2632 __ swc1(f6, MemOperand(a0, offsetof(TestFloat, resultS)) ); 2633 __ sdc1(f12, MemOperand(a0, offsetof(TestFloat, resultD)) ); 2634 2635 if (IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) { 2636 __ swc1(f16, MemOperand(a0, offsetof(TestFloat, resultS1)) ); 2637 __ sdc1(f14, MemOperand(a0, offsetof(TestFloat, resultD1)) ); 2638 __ swc1(f4, MemOperand(a0, offsetof(TestFloat, resultS2)) ); 2639 __ sdc1(f18, MemOperand(a0, offsetof(TestFloat, resultD2)) ); 2640 } 2641 __ jr(ra); 2642 __ nop(); 2643 2644 CodeDesc desc; 2645 assm.GetCode(&desc); 2646 Handle<Code> code = isolate->factory()->NewCode( 2647 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 2648 F3 f = FUNCTION_CAST<F3>(code->entry()); 2649 2650 for (int i = 0; i < kTableLength; i++) { 2651 float f1; 2652 double d1; 2653 test.a = inputs_S[i]; 2654 test.c = inputs_D[i]; 2655 2656 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 2657 2658 CHECK_EQ(test.resultS, outputs_S[i]); 2659 CHECK_EQ(test.resultD, outputs_D[i]); 2660 2661 if (IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) { 2662 if (i != 0) { 2663 f1 = test.resultS1 - 1.0F/outputs_S[i]; 2664 f1 = (f1 < 0) ? f1 : -f1; 2665 CHECK(f1 <= deltaFloat); 2666 d1 = test.resultD1 - 1.0L/outputs_D[i]; 2667 d1 = (d1 < 0) ? d1 : -d1; 2668 CHECK(d1 <= deltaDouble); 2669 f1 = test.resultS2 - 1.0F/inputs_S[i]; 2670 f1 = (f1 < 0) ? f1 : -f1; 2671 CHECK(f1 <= deltaFloat); 2672 d1 = test.resultD2 - 1.0L/inputs_D[i]; 2673 d1 = (d1 < 0) ? d1 : -d1; 2674 CHECK(d1 <= deltaDouble); 2675 } else { 2676 CHECK_EQ(test.resultS1, 1.0F/outputs_S[i]); 2677 CHECK_EQ(test.resultD1, 1.0L/outputs_D[i]); 2678 CHECK_EQ(test.resultS2, 1.0F/inputs_S[i]); 2679 CHECK_EQ(test.resultD2, 1.0L/inputs_D[i]); 2680 } 2681 } 2682 } 2683 } 2684 2685 2686 TEST(neg) { 2687 const int kTableLength = 3; 2688 CcTest::InitializeVM(); 2689 Isolate* isolate = CcTest::i_isolate(); 2690 HandleScope scope(isolate); 2691 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); 2692 2693 typedef struct test_float { 2694 float a; 2695 float resultS; 2696 double c; 2697 double resultD; 2698 }TestFloat; 2699 2700 TestFloat test; 2701 double inputs_D[kTableLength] = { 2702 0.0, 4.0, -2.0 2703 }; 2704 2705 double outputs_D[kTableLength] = { 2706 0.0, -4.0, 2.0 2707 }; 2708 float inputs_S[kTableLength] = { 2709 0.0, 4.0, -2.0 2710 }; 2711 2712 float outputs_S[kTableLength] = { 2713 0.0, -4.0, 2.0 2714 }; 2715 __ lwc1(f2, MemOperand(a0, offsetof(TestFloat, a)) ); 2716 __ ldc1(f8, MemOperand(a0, offsetof(TestFloat, c)) ); 2717 __ neg_s(f6, f2); 2718 __ neg_d(f12, f8); 2719 __ swc1(f6, MemOperand(a0, offsetof(TestFloat, resultS)) ); 2720 __ sdc1(f12, MemOperand(a0, offsetof(TestFloat, resultD)) ); 2721 __ jr(ra); 2722 __ nop(); 2723 2724 CodeDesc desc; 2725 assm.GetCode(&desc); 2726 Handle<Code> code = isolate->factory()->NewCode( 2727 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 2728 F3 f = FUNCTION_CAST<F3>(code->entry()); 2729 for (int i = 0; i < kTableLength; i++) { 2730 test.a = inputs_S[i]; 2731 test.c = inputs_D[i]; 2732 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 2733 CHECK_EQ(test.resultS, outputs_S[i]); 2734 CHECK_EQ(test.resultD, outputs_D[i]); 2735 } 2736 } 2737 2738 2739 TEST(mul) { 2740 const int kTableLength = 4; 2741 CcTest::InitializeVM(); 2742 Isolate* isolate = CcTest::i_isolate(); 2743 HandleScope scope(isolate); 2744 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); 2745 2746 typedef struct test_float { 2747 float a; 2748 float b; 2749 float resultS; 2750 double c; 2751 double d; 2752 double resultD; 2753 }TestFloat; 2754 2755 TestFloat test; 2756 double inputfs_D[kTableLength] = { 2757 5.3, -5.3, 5.3, -2.9 2758 }; 2759 double inputft_D[kTableLength] = { 2760 4.8, 4.8, -4.8, -0.29 2761 }; 2762 2763 float inputfs_S[kTableLength] = { 2764 5.3, -5.3, 5.3, -2.9 2765 }; 2766 float inputft_S[kTableLength] = { 2767 4.8, 4.8, -4.8, -0.29 2768 }; 2769 2770 __ lwc1(f2, MemOperand(a0, offsetof(TestFloat, a)) ); 2771 __ lwc1(f4, MemOperand(a0, offsetof(TestFloat, b)) ); 2772 __ ldc1(f6, MemOperand(a0, offsetof(TestFloat, c)) ); 2773 __ ldc1(f8, MemOperand(a0, offsetof(TestFloat, d)) ); 2774 __ mul_s(f10, f2, f4); 2775 __ mul_d(f12, f6, f8); 2776 __ swc1(f10, MemOperand(a0, offsetof(TestFloat, resultS)) ); 2777 __ sdc1(f12, MemOperand(a0, offsetof(TestFloat, resultD)) ); 2778 __ jr(ra); 2779 __ nop(); 2780 2781 CodeDesc desc; 2782 assm.GetCode(&desc); 2783 Handle<Code> code = isolate->factory()->NewCode( 2784 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 2785 F3 f = FUNCTION_CAST<F3>(code->entry()); 2786 for (int i = 0; i < kTableLength; i++) { 2787 test.a = inputfs_S[i]; 2788 test.b = inputft_S[i]; 2789 test.c = inputfs_D[i]; 2790 test.d = inputft_D[i]; 2791 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 2792 CHECK_EQ(test.resultS, inputfs_S[i]*inputft_S[i]); 2793 CHECK_EQ(test.resultD, inputfs_D[i]*inputft_D[i]); 2794 } 2795 } 2796 2797 2798 TEST(mov) { 2799 const int kTableLength = 4; 2800 CcTest::InitializeVM(); 2801 Isolate* isolate = CcTest::i_isolate(); 2802 HandleScope scope(isolate); 2803 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); 2804 2805 typedef struct test_float { 2806 double a; 2807 double b; 2808 float c; 2809 float d; 2810 }TestFloat; 2811 2812 TestFloat test; 2813 double inputs_D[kTableLength] = { 2814 5.3, -5.3, 5.3, -2.9 2815 }; 2816 double inputs_S[kTableLength] = { 2817 4.8, 4.8, -4.8, -0.29 2818 }; 2819 2820 float outputs_S[kTableLength] = { 2821 4.8, 4.8, -4.8, -0.29 2822 }; 2823 double outputs_D[kTableLength] = { 2824 5.3, -5.3, 5.3, -2.9 2825 }; 2826 2827 __ ldc1(f4, MemOperand(a0, offsetof(TestFloat, a)) ); 2828 __ lwc1(f6, MemOperand(a0, offsetof(TestFloat, c)) ); 2829 __ mov_s(f8, f6); 2830 __ mov_d(f10, f4); 2831 __ swc1(f8, MemOperand(a0, offsetof(TestFloat, d)) ); 2832 __ sdc1(f10, MemOperand(a0, offsetof(TestFloat, b)) ); 2833 2834 __ jr(ra); 2835 __ nop(); 2836 2837 CodeDesc desc; 2838 assm.GetCode(&desc); 2839 Handle<Code> code = isolate->factory()->NewCode( 2840 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 2841 F3 f = FUNCTION_CAST<F3>(code->entry()); 2842 for (int i = 0; i < kTableLength; i++) { 2843 test.a = inputs_D[i]; 2844 test.c = inputs_S[i]; 2845 2846 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 2847 CHECK_EQ(test.b, outputs_D[i]); 2848 CHECK_EQ(test.d, outputs_S[i]); 2849 } 2850 } 2851 2852 2853 TEST(floor_w) { 2854 CcTest::InitializeVM(); 2855 Isolate* isolate = CcTest::i_isolate(); 2856 HandleScope scope(isolate); 2857 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); 2858 2859 typedef struct test_float { 2860 uint32_t isNaN2008; 2861 double a; 2862 float b; 2863 int32_t c; // a floor result 2864 int32_t d; // b floor result 2865 }Test; 2866 const int kTableLength = 15; 2867 double inputs_D[kTableLength] = { 2868 2.1, 2.6, 2.5, 3.1, 3.6, 3.5, 2869 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5, 2870 2147483648.0, 2871 std::numeric_limits<double>::quiet_NaN(), 2872 std::numeric_limits<double>::infinity() 2873 }; 2874 float inputs_S[kTableLength] = { 2875 2.1, 2.6, 2.5, 3.1, 3.6, 3.5, 2876 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5, 2877 2147483648.0, 2878 std::numeric_limits<float>::quiet_NaN(), 2879 std::numeric_limits<float>::infinity() 2880 }; 2881 double outputs[kTableLength] = { 2882 2.0, 2.0, 2.0, 3.0, 3.0, 3.0, 2883 -3.0, -3.0, -3.0, -4.0, -4.0, -4.0, 2884 kFPUInvalidResult, kFPUInvalidResult, 2885 kFPUInvalidResult}; 2886 double outputsNaN2008[kTableLength] = { 2887 2.0, 2.0, 2.0, 3.0, 3.0, 3.0, 2888 -3.0, -3.0, -3.0, -4.0, -4.0, -4.0, 2889 kFPUInvalidResult, 2890 0, 2891 kFPUInvalidResult}; 2892 2893 __ cfc1(t1, FCSR); 2894 __ sw(t1, MemOperand(a0, offsetof(Test, isNaN2008))); 2895 __ ldc1(f4, MemOperand(a0, offsetof(Test, a)) ); 2896 __ lwc1(f6, MemOperand(a0, offsetof(Test, b)) ); 2897 __ floor_w_d(f8, f4); 2898 __ floor_w_s(f10, f6); 2899 __ swc1(f8, MemOperand(a0, offsetof(Test, c)) ); 2900 __ swc1(f10, MemOperand(a0, offsetof(Test, d)) ); 2901 __ jr(ra); 2902 __ nop(); 2903 Test test; 2904 CodeDesc desc; 2905 assm.GetCode(&desc); 2906 Handle<Code> code = isolate->factory()->NewCode( 2907 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 2908 F3 f = FUNCTION_CAST<F3>(code->entry()); 2909 for (int i = 0; i < kTableLength; i++) { 2910 test.a = inputs_D[i]; 2911 test.b = inputs_S[i]; 2912 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 2913 if ((test.isNaN2008 & kFCSRNaN2008FlagMask) && kArchVariant == kMips32r6) { 2914 CHECK_EQ(test.c, outputsNaN2008[i]); 2915 } else { 2916 CHECK_EQ(test.c, outputs[i]); 2917 } 2918 CHECK_EQ(test.d, test.c); 2919 } 2920 } 2921 2922 2923 TEST(floor_l) { 2924 if (IsFp64Mode()) { 2925 CcTest::InitializeVM(); 2926 Isolate* isolate = CcTest::i_isolate(); 2927 HandleScope scope(isolate); 2928 MacroAssembler assm(isolate, NULL, 0, 2929 v8::internal::CodeObjectRequired::kYes); 2930 const double dFPU64InvalidResult = static_cast<double>(kFPU64InvalidResult); 2931 typedef struct test_float { 2932 uint32_t isNaN2008; 2933 double a; 2934 float b; 2935 int64_t c; 2936 int64_t d; 2937 }Test; 2938 const int kTableLength = 15; 2939 double inputs_D[kTableLength] = { 2940 2.1, 2.6, 2.5, 3.1, 3.6, 3.5, 2941 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5, 2942 2147483648.0, 2943 std::numeric_limits<double>::quiet_NaN(), 2944 std::numeric_limits<double>::infinity() 2945 }; 2946 float inputs_S[kTableLength] = { 2947 2.1, 2.6, 2.5, 3.1, 3.6, 3.5, 2948 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5, 2949 2147483648.0, 2950 std::numeric_limits<float>::quiet_NaN(), 2951 std::numeric_limits<float>::infinity() 2952 }; 2953 double outputs[kTableLength] = { 2954 2.0, 2.0, 2.0, 3.0, 3.0, 3.0, 2955 -3.0, -3.0, -3.0, -4.0, -4.0, -4.0, 2956 2147483648.0, dFPU64InvalidResult, 2957 dFPU64InvalidResult}; 2958 double outputsNaN2008[kTableLength] = { 2959 2.0, 2.0, 2.0, 3.0, 3.0, 3.0, 2960 -3.0, -3.0, -3.0, -4.0, -4.0, -4.0, 2961 2147483648.0, 2962 0, 2963 dFPU64InvalidResult}; 2964 2965 __ cfc1(t1, FCSR); 2966 __ sw(t1, MemOperand(a0, offsetof(Test, isNaN2008))); 2967 __ ldc1(f4, MemOperand(a0, offsetof(Test, a)) ); 2968 __ lwc1(f6, MemOperand(a0, offsetof(Test, b)) ); 2969 __ floor_l_d(f8, f4); 2970 __ floor_l_s(f10, f6); 2971 __ sdc1(f8, MemOperand(a0, offsetof(Test, c)) ); 2972 __ sdc1(f10, MemOperand(a0, offsetof(Test, d)) ); 2973 __ jr(ra); 2974 __ nop(); 2975 Test test; 2976 CodeDesc desc; 2977 assm.GetCode(&desc); 2978 Handle<Code> code = isolate->factory()->NewCode( 2979 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 2980 F3 f = FUNCTION_CAST<F3>(code->entry()); 2981 for (int i = 0; i < kTableLength; i++) { 2982 test.a = inputs_D[i]; 2983 test.b = inputs_S[i]; 2984 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 2985 if ((test.isNaN2008 & kFCSRNaN2008FlagMask) && 2986 kArchVariant == kMips32r6) { 2987 CHECK_EQ(test.c, outputsNaN2008[i]); 2988 } else { 2989 CHECK_EQ(test.c, outputs[i]); 2990 } 2991 CHECK_EQ(test.d, test.c); 2992 } 2993 } 2994 } 2995 2996 2997 TEST(ceil_w) { 2998 CcTest::InitializeVM(); 2999 Isolate* isolate = CcTest::i_isolate(); 3000 HandleScope scope(isolate); 3001 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); 3002 3003 typedef struct test_float { 3004 uint32_t isNaN2008; 3005 double a; 3006 float b; 3007 int32_t c; // a floor result 3008 int32_t d; // b floor result 3009 }Test; 3010 const int kTableLength = 15; 3011 double inputs_D[kTableLength] = { 3012 2.1, 2.6, 2.5, 3.1, 3.6, 3.5, 3013 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5, 3014 2147483648.0, 3015 std::numeric_limits<double>::quiet_NaN(), 3016 std::numeric_limits<double>::infinity() 3017 }; 3018 float inputs_S[kTableLength] = { 3019 2.1, 2.6, 2.5, 3.1, 3.6, 3.5, 3020 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5, 3021 2147483648.0, 3022 std::numeric_limits<float>::quiet_NaN(), 3023 std::numeric_limits<float>::infinity() 3024 }; 3025 double outputs[kTableLength] = { 3026 3.0, 3.0, 3.0, 4.0, 4.0, 4.0, 3027 -2.0, -2.0, -2.0, -3.0, -3.0, -3.0, 3028 kFPUInvalidResult, kFPUInvalidResult, 3029 kFPUInvalidResult}; 3030 double outputsNaN2008[kTableLength] = { 3031 3.0, 3.0, 3.0, 4.0, 4.0, 4.0, 3032 -2.0, -2.0, -2.0, -3.0, -3.0, -3.0, 3033 kFPUInvalidResult, 3034 0, 3035 kFPUInvalidResult}; 3036 3037 __ cfc1(t1, FCSR); 3038 __ sw(t1, MemOperand(a0, offsetof(Test, isNaN2008))); 3039 __ ldc1(f4, MemOperand(a0, offsetof(Test, a)) ); 3040 __ lwc1(f6, MemOperand(a0, offsetof(Test, b)) ); 3041 __ ceil_w_d(f8, f4); 3042 __ ceil_w_s(f10, f6); 3043 __ swc1(f8, MemOperand(a0, offsetof(Test, c)) ); 3044 __ swc1(f10, MemOperand(a0, offsetof(Test, d)) ); 3045 __ jr(ra); 3046 __ nop(); 3047 Test test; 3048 CodeDesc desc; 3049 assm.GetCode(&desc); 3050 Handle<Code> code = isolate->factory()->NewCode( 3051 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 3052 F3 f = FUNCTION_CAST<F3>(code->entry()); 3053 for (int i = 0; i < kTableLength; i++) { 3054 test.a = inputs_D[i]; 3055 test.b = inputs_S[i]; 3056 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 3057 if ((test.isNaN2008 & kFCSRNaN2008FlagMask) && kArchVariant == kMips32r6) { 3058 CHECK_EQ(test.c, outputsNaN2008[i]); 3059 } else { 3060 CHECK_EQ(test.c, outputs[i]); 3061 } 3062 CHECK_EQ(test.d, test.c); 3063 } 3064 } 3065 3066 3067 TEST(ceil_l) { 3068 if (IsFp64Mode()) { 3069 CcTest::InitializeVM(); 3070 Isolate* isolate = CcTest::i_isolate(); 3071 HandleScope scope(isolate); 3072 MacroAssembler assm(isolate, NULL, 0, 3073 v8::internal::CodeObjectRequired::kYes); 3074 const double dFPU64InvalidResult = static_cast<double>(kFPU64InvalidResult); 3075 typedef struct test_float { 3076 uint32_t isNaN2008; 3077 double a; 3078 float b; 3079 int64_t c; 3080 int64_t d; 3081 }Test; 3082 const int kTableLength = 15; 3083 double inputs_D[kTableLength] = { 3084 2.1, 2.6, 2.5, 3.1, 3.6, 3.5, 3085 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5, 3086 2147483648.0, 3087 std::numeric_limits<double>::quiet_NaN(), 3088 std::numeric_limits<double>::infinity() 3089 }; 3090 float inputs_S[kTableLength] = { 3091 2.1, 2.6, 2.5, 3.1, 3.6, 3.5, 3092 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5, 3093 2147483648.0, 3094 std::numeric_limits<float>::quiet_NaN(), 3095 std::numeric_limits<float>::infinity() 3096 }; 3097 double outputs[kTableLength] = { 3098 3.0, 3.0, 3.0, 4.0, 4.0, 4.0, 3099 -2.0, -2.0, -2.0, -3.0, -3.0, -3.0, 3100 2147483648.0, dFPU64InvalidResult, 3101 dFPU64InvalidResult}; 3102 double outputsNaN2008[kTableLength] = { 3103 3.0, 3.0, 3.0, 4.0, 4.0, 4.0, 3104 -2.0, -2.0, -2.0, -3.0, -3.0, -3.0, 3105 2147483648.0, 3106 0, 3107 dFPU64InvalidResult}; 3108 3109 __ cfc1(t1, FCSR); 3110 __ sw(t1, MemOperand(a0, offsetof(Test, isNaN2008))); 3111 __ ldc1(f4, MemOperand(a0, offsetof(Test, a)) ); 3112 __ lwc1(f6, MemOperand(a0, offsetof(Test, b)) ); 3113 __ ceil_l_d(f8, f4); 3114 __ ceil_l_s(f10, f6); 3115 __ sdc1(f8, MemOperand(a0, offsetof(Test, c)) ); 3116 __ sdc1(f10, MemOperand(a0, offsetof(Test, d)) ); 3117 __ jr(ra); 3118 __ nop(); 3119 Test test; 3120 CodeDesc desc; 3121 assm.GetCode(&desc); 3122 Handle<Code> code = isolate->factory()->NewCode( 3123 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 3124 F3 f = FUNCTION_CAST<F3>(code->entry()); 3125 for (int i = 0; i < kTableLength; i++) { 3126 test.a = inputs_D[i]; 3127 test.b = inputs_S[i]; 3128 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 3129 if ((test.isNaN2008 & kFCSRNaN2008FlagMask) && 3130 kArchVariant == kMips32r6) { 3131 CHECK_EQ(test.c, outputsNaN2008[i]); 3132 } else { 3133 CHECK_EQ(test.c, outputs[i]); 3134 } 3135 CHECK_EQ(test.d, test.c); 3136 } 3137 } 3138 } 3139 3140 3141 TEST(jump_tables1) { 3142 // Test jump tables with forward jumps. 3143 CcTest::InitializeVM(); 3144 Isolate* isolate = CcTest::i_isolate(); 3145 HandleScope scope(isolate); 3146 Assembler assm(isolate, nullptr, 0); 3147 3148 const int kNumCases = 512; 3149 int values[kNumCases]; 3150 isolate->random_number_generator()->NextBytes(values, sizeof(values)); 3151 Label labels[kNumCases]; 3152 3153 __ addiu(sp, sp, -4); 3154 __ sw(ra, MemOperand(sp)); 3155 3156 Label done; 3157 { 3158 __ BlockTrampolinePoolFor(kNumCases + 7); 3159 PredictableCodeSizeScope predictable( 3160 &assm, (kNumCases + 7) * Assembler::kInstrSize); 3161 Label here; 3162 3163 __ bal(&here); 3164 __ nop(); 3165 __ bind(&here); 3166 __ sll(at, a0, 2); 3167 __ addu(at, at, ra); 3168 __ lw(at, MemOperand(at, 5 * Assembler::kInstrSize)); 3169 __ jr(at); 3170 __ nop(); 3171 for (int i = 0; i < kNumCases; ++i) { 3172 __ dd(&labels[i]); 3173 } 3174 } 3175 3176 for (int i = 0; i < kNumCases; ++i) { 3177 __ bind(&labels[i]); 3178 __ lui(v0, (values[i] >> 16) & 0xffff); 3179 __ ori(v0, v0, values[i] & 0xffff); 3180 __ b(&done); 3181 __ nop(); 3182 } 3183 3184 __ bind(&done); 3185 __ lw(ra, MemOperand(sp)); 3186 __ addiu(sp, sp, 4); 3187 __ jr(ra); 3188 __ nop(); 3189 3190 CodeDesc desc; 3191 assm.GetCode(&desc); 3192 Handle<Code> code = isolate->factory()->NewCode( 3193 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 3194 #ifdef OBJECT_PRINT 3195 code->Print(std::cout); 3196 #endif 3197 F1 f = FUNCTION_CAST<F1>(code->entry()); 3198 for (int i = 0; i < kNumCases; ++i) { 3199 int res = reinterpret_cast<int>( 3200 CALL_GENERATED_CODE(isolate, f, i, 0, 0, 0, 0)); 3201 ::printf("f(%d) = %d\n", i, res); 3202 CHECK_EQ(values[i], res); 3203 } 3204 } 3205 3206 3207 TEST(jump_tables2) { 3208 // Test jump tables with backward jumps. 3209 CcTest::InitializeVM(); 3210 Isolate* isolate = CcTest::i_isolate(); 3211 HandleScope scope(isolate); 3212 Assembler assm(isolate, nullptr, 0); 3213 3214 const int kNumCases = 512; 3215 int values[kNumCases]; 3216 isolate->random_number_generator()->NextBytes(values, sizeof(values)); 3217 Label labels[kNumCases]; 3218 3219 __ addiu(sp, sp, -4); 3220 __ sw(ra, MemOperand(sp)); 3221 3222 Label done, dispatch; 3223 __ b(&dispatch); 3224 __ nop(); 3225 3226 for (int i = 0; i < kNumCases; ++i) { 3227 __ bind(&labels[i]); 3228 __ lui(v0, (values[i] >> 16) & 0xffff); 3229 __ ori(v0, v0, values[i] & 0xffff); 3230 __ b(&done); 3231 __ nop(); 3232 } 3233 3234 __ bind(&dispatch); 3235 { 3236 __ BlockTrampolinePoolFor(kNumCases + 7); 3237 PredictableCodeSizeScope predictable( 3238 &assm, (kNumCases + 7) * Assembler::kInstrSize); 3239 Label here; 3240 3241 __ bal(&here); 3242 __ nop(); 3243 __ bind(&here); 3244 __ sll(at, a0, 2); 3245 __ addu(at, at, ra); 3246 __ lw(at, MemOperand(at, 5 * Assembler::kInstrSize)); 3247 __ jr(at); 3248 __ nop(); 3249 for (int i = 0; i < kNumCases; ++i) { 3250 __ dd(&labels[i]); 3251 } 3252 } 3253 3254 __ bind(&done); 3255 __ lw(ra, MemOperand(sp)); 3256 __ addiu(sp, sp, 4); 3257 __ jr(ra); 3258 __ nop(); 3259 3260 CodeDesc desc; 3261 assm.GetCode(&desc); 3262 Handle<Code> code = isolate->factory()->NewCode( 3263 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 3264 #ifdef OBJECT_PRINT 3265 code->Print(std::cout); 3266 #endif 3267 F1 f = FUNCTION_CAST<F1>(code->entry()); 3268 for (int i = 0; i < kNumCases; ++i) { 3269 int res = reinterpret_cast<int>( 3270 CALL_GENERATED_CODE(isolate, f, i, 0, 0, 0, 0)); 3271 ::printf("f(%d) = %d\n", i, res); 3272 CHECK_EQ(values[i], res); 3273 } 3274 } 3275 3276 3277 TEST(jump_tables3) { 3278 // Test jump tables with backward jumps and embedded heap objects. 3279 CcTest::InitializeVM(); 3280 Isolate* isolate = CcTest::i_isolate(); 3281 HandleScope scope(isolate); 3282 Assembler assm(isolate, nullptr, 0); 3283 3284 const int kNumCases = 256; 3285 Handle<Object> values[kNumCases]; 3286 for (int i = 0; i < kNumCases; ++i) { 3287 double value = isolate->random_number_generator()->NextDouble(); 3288 values[i] = isolate->factory()->NewHeapNumber(value, IMMUTABLE, TENURED); 3289 } 3290 Label labels[kNumCases]; 3291 Object* obj; 3292 int32_t imm32; 3293 3294 __ addiu(sp, sp, -4); 3295 __ sw(ra, MemOperand(sp)); 3296 3297 Label done, dispatch; 3298 __ b(&dispatch); 3299 3300 3301 for (int i = 0; i < kNumCases; ++i) { 3302 __ bind(&labels[i]); 3303 obj = *values[i]; 3304 imm32 = reinterpret_cast<intptr_t>(obj); 3305 __ lui(v0, (imm32 >> 16) & 0xffff); 3306 __ ori(v0, v0, imm32 & 0xffff); 3307 __ b(&done); 3308 __ nop(); 3309 } 3310 3311 __ bind(&dispatch); 3312 { 3313 __ BlockTrampolinePoolFor(kNumCases + 7); 3314 PredictableCodeSizeScope predictable( 3315 &assm, (kNumCases + 7) * Assembler::kInstrSize); 3316 Label here; 3317 3318 __ bal(&here); 3319 __ nop(); 3320 __ bind(&here); 3321 __ sll(at, a0, 2); 3322 __ addu(at, at, ra); 3323 __ lw(at, MemOperand(at, 5 * Assembler::kInstrSize)); 3324 __ jr(at); 3325 __ nop(); 3326 for (int i = 0; i < kNumCases; ++i) { 3327 __ dd(&labels[i]); 3328 } 3329 } 3330 3331 __ bind(&done); 3332 __ lw(ra, MemOperand(sp)); 3333 __ addiu(sp, sp, 4); 3334 __ jr(ra); 3335 __ nop(); 3336 3337 CodeDesc desc; 3338 assm.GetCode(&desc); 3339 Handle<Code> code = isolate->factory()->NewCode( 3340 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 3341 #ifdef OBJECT_PRINT 3342 code->Print(std::cout); 3343 #endif 3344 F1 f = FUNCTION_CAST<F1>(code->entry()); 3345 for (int i = 0; i < kNumCases; ++i) { 3346 Handle<Object> result( 3347 CALL_GENERATED_CODE(isolate, f, i, 0, 0, 0, 0), isolate); 3348 #ifdef OBJECT_PRINT 3349 ::printf("f(%d) = ", i); 3350 result->Print(std::cout); 3351 ::printf("\n"); 3352 #endif 3353 CHECK(values[i].is_identical_to(result)); 3354 } 3355 } 3356 3357 3358 TEST(BITSWAP) { 3359 // Test BITSWAP 3360 if (IsMipsArchVariant(kMips32r6)) { 3361 CcTest::InitializeVM(); 3362 Isolate* isolate = CcTest::i_isolate(); 3363 HandleScope scope(isolate); 3364 3365 typedef struct { 3366 int32_t r1; 3367 int32_t r2; 3368 int32_t r3; 3369 int32_t r4; 3370 } T; 3371 T t; 3372 3373 Assembler assm(isolate, NULL, 0); 3374 3375 __ lw(a2, MemOperand(a0, offsetof(T, r1))); 3376 __ nop(); 3377 __ bitswap(a1, a2); 3378 __ sw(a1, MemOperand(a0, offsetof(T, r1))); 3379 3380 __ lw(a2, MemOperand(a0, offsetof(T, r2))); 3381 __ nop(); 3382 __ bitswap(a1, a2); 3383 __ sw(a1, MemOperand(a0, offsetof(T, r2))); 3384 3385 __ jr(ra); 3386 __ nop(); 3387 3388 CodeDesc desc; 3389 assm.GetCode(&desc); 3390 Handle<Code> code = isolate->factory()->NewCode( 3391 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 3392 F3 f = FUNCTION_CAST<F3>(code->entry()); 3393 t.r1 = 0x781A15C3; 3394 t.r2 = 0x8B71FCDE; 3395 Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0); 3396 USE(dummy); 3397 3398 CHECK_EQ(static_cast<int32_t>(0x1E58A8C3), t.r1); 3399 CHECK_EQ(static_cast<int32_t>(0xD18E3F7B), t.r2); 3400 } 3401 } 3402 3403 3404 TEST(class_fmt) { 3405 if (IsMipsArchVariant(kMips32r6)) { 3406 // Test CLASS.fmt instruction. 3407 CcTest::InitializeVM(); 3408 Isolate* isolate = CcTest::i_isolate(); 3409 HandleScope scope(isolate); 3410 3411 typedef struct { 3412 double dSignalingNan; 3413 double dQuietNan; 3414 double dNegInf; 3415 double dNegNorm; 3416 double dNegSubnorm; 3417 double dNegZero; 3418 double dPosInf; 3419 double dPosNorm; 3420 double dPosSubnorm; 3421 double dPosZero; 3422 float fSignalingNan; 3423 float fQuietNan; 3424 float fNegInf; 3425 float fNegNorm; 3426 float fNegSubnorm; 3427 float fNegZero; 3428 float fPosInf; 3429 float fPosNorm; 3430 float fPosSubnorm; 3431 float fPosZero; } T; 3432 T t; 3433 3434 // Create a function that accepts &t, and loads, manipulates, and stores 3435 // the doubles t.a ... t.f. 3436 MacroAssembler assm(isolate, NULL, 0, 3437 v8::internal::CodeObjectRequired::kYes); 3438 3439 __ ldc1(f4, MemOperand(a0, offsetof(T, dSignalingNan))); 3440 __ class_d(f6, f4); 3441 __ sdc1(f6, MemOperand(a0, offsetof(T, dSignalingNan))); 3442 3443 __ ldc1(f4, MemOperand(a0, offsetof(T, dQuietNan))); 3444 __ class_d(f6, f4); 3445 __ sdc1(f6, MemOperand(a0, offsetof(T, dQuietNan))); 3446 3447 __ ldc1(f4, MemOperand(a0, offsetof(T, dNegInf))); 3448 __ class_d(f6, f4); 3449 __ sdc1(f6, MemOperand(a0, offsetof(T, dNegInf))); 3450 3451 __ ldc1(f4, MemOperand(a0, offsetof(T, dNegNorm))); 3452 __ class_d(f6, f4); 3453 __ sdc1(f6, MemOperand(a0, offsetof(T, dNegNorm))); 3454 3455 __ ldc1(f4, MemOperand(a0, offsetof(T, dNegSubnorm))); 3456 __ class_d(f6, f4); 3457 __ sdc1(f6, MemOperand(a0, offsetof(T, dNegSubnorm))); 3458 3459 __ ldc1(f4, MemOperand(a0, offsetof(T, dNegZero))); 3460 __ class_d(f6, f4); 3461 __ sdc1(f6, MemOperand(a0, offsetof(T, dNegZero))); 3462 3463 __ ldc1(f4, MemOperand(a0, offsetof(T, dPosInf))); 3464 __ class_d(f6, f4); 3465 __ sdc1(f6, MemOperand(a0, offsetof(T, dPosInf))); 3466 3467 __ ldc1(f4, MemOperand(a0, offsetof(T, dPosNorm))); 3468 __ class_d(f6, f4); 3469 __ sdc1(f6, MemOperand(a0, offsetof(T, dPosNorm))); 3470 3471 __ ldc1(f4, MemOperand(a0, offsetof(T, dPosSubnorm))); 3472 __ class_d(f6, f4); 3473 __ sdc1(f6, MemOperand(a0, offsetof(T, dPosSubnorm))); 3474 3475 __ ldc1(f4, MemOperand(a0, offsetof(T, dPosZero))); 3476 __ class_d(f6, f4); 3477 __ sdc1(f6, MemOperand(a0, offsetof(T, dPosZero))); 3478 3479 // Testing instruction CLASS.S 3480 __ lwc1(f4, MemOperand(a0, offsetof(T, fSignalingNan))); 3481 __ class_s(f6, f4); 3482 __ swc1(f6, MemOperand(a0, offsetof(T, fSignalingNan))); 3483 3484 __ lwc1(f4, MemOperand(a0, offsetof(T, fQuietNan))); 3485 __ class_s(f6, f4); 3486 __ swc1(f6, MemOperand(a0, offsetof(T, fQuietNan))); 3487 3488 __ lwc1(f4, MemOperand(a0, offsetof(T, fNegInf))); 3489 __ class_s(f6, f4); 3490 __ swc1(f6, MemOperand(a0, offsetof(T, fNegInf))); 3491 3492 __ lwc1(f4, MemOperand(a0, offsetof(T, fNegNorm))); 3493 __ class_s(f6, f4); 3494 __ swc1(f6, MemOperand(a0, offsetof(T, fNegNorm))); 3495 3496 __ lwc1(f4, MemOperand(a0, offsetof(T, fNegSubnorm))); 3497 __ class_s(f6, f4); 3498 __ swc1(f6, MemOperand(a0, offsetof(T, fNegSubnorm))); 3499 3500 __ lwc1(f4, MemOperand(a0, offsetof(T, fNegZero))); 3501 __ class_s(f6, f4); 3502 __ swc1(f6, MemOperand(a0, offsetof(T, fNegZero))); 3503 3504 __ lwc1(f4, MemOperand(a0, offsetof(T, fPosInf))); 3505 __ class_s(f6, f4); 3506 __ swc1(f6, MemOperand(a0, offsetof(T, fPosInf))); 3507 3508 __ lwc1(f4, MemOperand(a0, offsetof(T, fPosNorm))); 3509 __ class_s(f6, f4); 3510 __ swc1(f6, MemOperand(a0, offsetof(T, fPosNorm))); 3511 3512 __ lwc1(f4, MemOperand(a0, offsetof(T, fPosSubnorm))); 3513 __ class_s(f6, f4); 3514 __ swc1(f6, MemOperand(a0, offsetof(T, fPosSubnorm))); 3515 3516 __ lwc1(f4, MemOperand(a0, offsetof(T, fPosZero))); 3517 __ class_s(f6, f4); 3518 __ swc1(f6, MemOperand(a0, offsetof(T, fPosZero))); 3519 3520 __ jr(ra); 3521 __ nop(); 3522 3523 CodeDesc desc; 3524 assm.GetCode(&desc); 3525 Handle<Code> code = isolate->factory()->NewCode( 3526 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 3527 F3 f = FUNCTION_CAST<F3>(code->entry()); 3528 3529 t.dSignalingNan = std::numeric_limits<double>::signaling_NaN(); 3530 t.dQuietNan = std::numeric_limits<double>::quiet_NaN(); 3531 t.dNegInf = -1.0 / 0.0; 3532 t.dNegNorm = -5.0; 3533 t.dNegSubnorm = -DBL_MIN / 2.0; 3534 t.dNegZero = -0.0; 3535 t.dPosInf = 2.0 / 0.0; 3536 t.dPosNorm = 275.35; 3537 t.dPosSubnorm = DBL_MIN / 2.0; 3538 t.dPosZero = +0.0; 3539 // Float test values 3540 3541 t.fSignalingNan = std::numeric_limits<float>::signaling_NaN(); 3542 t.fQuietNan = std::numeric_limits<float>::quiet_NaN(); 3543 t.fNegInf = -0.5/0.0; 3544 t.fNegNorm = -FLT_MIN; 3545 t.fNegSubnorm = -FLT_MIN / 1.5; 3546 t.fNegZero = -0.0; 3547 t.fPosInf = 100000.0 / 0.0; 3548 t.fPosNorm = FLT_MAX; 3549 t.fPosSubnorm = FLT_MIN / 20.0; 3550 t.fPosZero = +0.0; 3551 3552 Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0); 3553 USE(dummy); 3554 // Expected double results. 3555 CHECK_EQ(bit_cast<int64_t>(t.dSignalingNan), 0x001); 3556 CHECK_EQ(bit_cast<int64_t>(t.dQuietNan), 0x002); 3557 CHECK_EQ(bit_cast<int64_t>(t.dNegInf), 0x004); 3558 CHECK_EQ(bit_cast<int64_t>(t.dNegNorm), 0x008); 3559 CHECK_EQ(bit_cast<int64_t>(t.dNegSubnorm), 0x010); 3560 CHECK_EQ(bit_cast<int64_t>(t.dNegZero), 0x020); 3561 CHECK_EQ(bit_cast<int64_t>(t.dPosInf), 0x040); 3562 CHECK_EQ(bit_cast<int64_t>(t.dPosNorm), 0x080); 3563 CHECK_EQ(bit_cast<int64_t>(t.dPosSubnorm), 0x100); 3564 CHECK_EQ(bit_cast<int64_t>(t.dPosZero), 0x200); 3565 3566 // Expected float results. 3567 CHECK_EQ(bit_cast<int32_t>(t.fSignalingNan), 0x001); 3568 CHECK_EQ(bit_cast<int32_t>(t.fQuietNan), 0x002); 3569 CHECK_EQ(bit_cast<int32_t>(t.fNegInf), 0x004); 3570 CHECK_EQ(bit_cast<int32_t>(t.fNegNorm), 0x008); 3571 CHECK_EQ(bit_cast<int32_t>(t.fNegSubnorm), 0x010); 3572 CHECK_EQ(bit_cast<int32_t>(t.fNegZero), 0x020); 3573 CHECK_EQ(bit_cast<int32_t>(t.fPosInf), 0x040); 3574 CHECK_EQ(bit_cast<int32_t>(t.fPosNorm), 0x080); 3575 CHECK_EQ(bit_cast<int32_t>(t.fPosSubnorm), 0x100); 3576 CHECK_EQ(bit_cast<int32_t>(t.fPosZero), 0x200); 3577 } 3578 } 3579 3580 3581 TEST(ABS) { 3582 CcTest::InitializeVM(); 3583 Isolate* isolate = CcTest::i_isolate(); 3584 HandleScope scope(isolate); 3585 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); 3586 3587 typedef struct test_float { 3588 int64_t fir; 3589 double a; 3590 float b; 3591 double fcsr; 3592 } TestFloat; 3593 3594 TestFloat test; 3595 3596 // Save FIR. 3597 __ cfc1(a1, FCSR); 3598 // Disable FPU exceptions. 3599 __ ctc1(zero_reg, FCSR); 3600 3601 __ ldc1(f4, MemOperand(a0, offsetof(TestFloat, a))); 3602 __ abs_d(f10, f4); 3603 __ sdc1(f10, MemOperand(a0, offsetof(TestFloat, a))); 3604 3605 __ lwc1(f4, MemOperand(a0, offsetof(TestFloat, b))); 3606 __ abs_s(f10, f4); 3607 __ swc1(f10, MemOperand(a0, offsetof(TestFloat, b))); 3608 3609 // Restore FCSR. 3610 __ ctc1(a1, FCSR); 3611 3612 __ jr(ra); 3613 __ nop(); 3614 3615 CodeDesc desc; 3616 assm.GetCode(&desc); 3617 Handle<Code> code = isolate->factory()->NewCode( 3618 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 3619 F3 f = FUNCTION_CAST<F3>(code->entry()); 3620 test.a = -2.0; 3621 test.b = -2.0; 3622 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 3623 CHECK_EQ(test.a, 2.0); 3624 CHECK_EQ(test.b, 2.0); 3625 3626 test.a = 2.0; 3627 test.b = 2.0; 3628 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 3629 CHECK_EQ(test.a, 2.0); 3630 CHECK_EQ(test.b, 2.0); 3631 3632 // Testing biggest positive number 3633 test.a = std::numeric_limits<double>::max(); 3634 test.b = std::numeric_limits<float>::max(); 3635 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 3636 CHECK_EQ(test.a, std::numeric_limits<double>::max()); 3637 CHECK_EQ(test.b, std::numeric_limits<float>::max()); 3638 3639 // Testing smallest negative number 3640 test.a = -std::numeric_limits<double>::max(); // lowest() 3641 test.b = -std::numeric_limits<float>::max(); // lowest() 3642 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 3643 CHECK_EQ(test.a, std::numeric_limits<double>::max()); 3644 CHECK_EQ(test.b, std::numeric_limits<float>::max()); 3645 3646 // Testing smallest positive number 3647 test.a = -std::numeric_limits<double>::min(); 3648 test.b = -std::numeric_limits<float>::min(); 3649 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 3650 CHECK_EQ(test.a, std::numeric_limits<double>::min()); 3651 CHECK_EQ(test.b, std::numeric_limits<float>::min()); 3652 3653 // Testing infinity 3654 test.a = -std::numeric_limits<double>::max() 3655 / std::numeric_limits<double>::min(); 3656 test.b = -std::numeric_limits<float>::max() 3657 / std::numeric_limits<float>::min(); 3658 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 3659 CHECK_EQ(test.a, std::numeric_limits<double>::max() 3660 / std::numeric_limits<double>::min()); 3661 CHECK_EQ(test.b, std::numeric_limits<float>::max() 3662 / std::numeric_limits<float>::min()); 3663 3664 test.a = std::numeric_limits<double>::quiet_NaN(); 3665 test.b = std::numeric_limits<float>::quiet_NaN(); 3666 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 3667 CHECK_EQ(std::isnan(test.a), true); 3668 CHECK_EQ(std::isnan(test.b), true); 3669 3670 test.a = std::numeric_limits<double>::signaling_NaN(); 3671 test.b = std::numeric_limits<float>::signaling_NaN(); 3672 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 3673 CHECK_EQ(std::isnan(test.a), true); 3674 CHECK_EQ(std::isnan(test.b), true); 3675 } 3676 3677 3678 TEST(ADD_FMT) { 3679 CcTest::InitializeVM(); 3680 Isolate* isolate = CcTest::i_isolate(); 3681 HandleScope scope(isolate); 3682 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); 3683 3684 typedef struct test_float { 3685 double a; 3686 double b; 3687 double c; 3688 float fa; 3689 float fb; 3690 float fc; 3691 } TestFloat; 3692 3693 TestFloat test; 3694 3695 __ ldc1(f4, MemOperand(a0, offsetof(TestFloat, a))); 3696 __ ldc1(f8, MemOperand(a0, offsetof(TestFloat, b))); 3697 __ add_d(f10, f8, f4); 3698 __ sdc1(f10, MemOperand(a0, offsetof(TestFloat, c))); 3699 3700 __ lwc1(f4, MemOperand(a0, offsetof(TestFloat, fa))); 3701 __ lwc1(f8, MemOperand(a0, offsetof(TestFloat, fb))); 3702 __ add_s(f10, f8, f4); 3703 __ swc1(f10, MemOperand(a0, offsetof(TestFloat, fc))); 3704 3705 __ jr(ra); 3706 __ nop(); 3707 3708 CodeDesc desc; 3709 assm.GetCode(&desc); 3710 Handle<Code> code = isolate->factory()->NewCode( 3711 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 3712 F3 f = FUNCTION_CAST<F3>(code->entry()); 3713 test.a = 2.0; 3714 test.b = 3.0; 3715 test.fa = 2.0; 3716 test.fb = 3.0; 3717 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 3718 CHECK_EQ(test.c, 5.0); 3719 CHECK_EQ(test.fc, 5.0); 3720 3721 test.a = std::numeric_limits<double>::max(); 3722 test.b = -std::numeric_limits<double>::max(); // lowest() 3723 test.fa = std::numeric_limits<float>::max(); 3724 test.fb = -std::numeric_limits<float>::max(); // lowest() 3725 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 3726 CHECK_EQ(test.c, 0.0); 3727 CHECK_EQ(test.fc, 0.0); 3728 3729 test.a = std::numeric_limits<double>::max(); 3730 test.b = std::numeric_limits<double>::max(); 3731 test.fa = std::numeric_limits<float>::max(); 3732 test.fb = std::numeric_limits<float>::max(); 3733 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 3734 CHECK_EQ(std::isfinite(test.c), false); 3735 CHECK_EQ(std::isfinite(test.fc), false); 3736 3737 test.a = 5.0; 3738 test.b = std::numeric_limits<double>::signaling_NaN(); 3739 test.fa = 5.0; 3740 test.fb = std::numeric_limits<float>::signaling_NaN(); 3741 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 3742 CHECK_EQ(std::isnan(test.c), true); 3743 CHECK_EQ(std::isnan(test.fc), true); 3744 } 3745 3746 3747 TEST(C_COND_FMT) { 3748 if ((IsMipsArchVariant(kMips32r1)) || (IsMipsArchVariant(kMips32r2))) { 3749 CcTest::InitializeVM(); 3750 Isolate* isolate = CcTest::i_isolate(); 3751 HandleScope scope(isolate); 3752 MacroAssembler assm(isolate, NULL, 0, 3753 v8::internal::CodeObjectRequired::kYes); 3754 3755 typedef struct test_float { 3756 double dOp1; 3757 double dOp2; 3758 uint32_t dF; 3759 uint32_t dUn; 3760 uint32_t dEq; 3761 uint32_t dUeq; 3762 uint32_t dOlt; 3763 uint32_t dUlt; 3764 uint32_t dOle; 3765 uint32_t dUle; 3766 float fOp1; 3767 float fOp2; 3768 uint32_t fF; 3769 uint32_t fUn; 3770 uint32_t fEq; 3771 uint32_t fUeq; 3772 uint32_t fOlt; 3773 uint32_t fUlt; 3774 uint32_t fOle; 3775 uint32_t fUle; 3776 } TestFloat; 3777 3778 TestFloat test; 3779 3780 __ li(t1, 1); 3781 3782 __ ldc1(f4, MemOperand(a0, offsetof(TestFloat, dOp1))); 3783 __ ldc1(f6, MemOperand(a0, offsetof(TestFloat, dOp2))); 3784 3785 __ lwc1(f14, MemOperand(a0, offsetof(TestFloat, fOp1))); 3786 __ lwc1(f16, MemOperand(a0, offsetof(TestFloat, fOp2))); 3787 3788 __ mov(t2, zero_reg); 3789 __ mov(t3, zero_reg); 3790 __ c_d(F, f4, f6, 0); 3791 __ c_s(F, f14, f16, 2); 3792 __ movt(t2, t1, 0); 3793 __ movt(t3, t1, 2); 3794 __ sw(t2, MemOperand(a0, offsetof(TestFloat, dF)) ); 3795 __ sw(t3, MemOperand(a0, offsetof(TestFloat, fF)) ); 3796 3797 __ mov(t2, zero_reg); 3798 __ mov(t3, zero_reg); 3799 __ c_d(UN, f4, f6, 2); 3800 __ c_s(UN, f14, f16, 4); 3801 __ movt(t2, t1, 2); 3802 __ movt(t3, t1, 4); 3803 __ sw(t2, MemOperand(a0, offsetof(TestFloat, dUn)) ); 3804 __ sw(t3, MemOperand(a0, offsetof(TestFloat, fUn)) ); 3805 3806 __ mov(t2, zero_reg); 3807 __ mov(t3, zero_reg); 3808 __ c_d(EQ, f4, f6, 4); 3809 __ c_s(EQ, f14, f16, 6); 3810 __ movt(t2, t1, 4); 3811 __ movt(t3, t1, 6); 3812 __ sw(t2, MemOperand(a0, offsetof(TestFloat, dEq)) ); 3813 __ sw(t3, MemOperand(a0, offsetof(TestFloat, fEq)) ); 3814 3815 __ mov(t2, zero_reg); 3816 __ mov(t3, zero_reg); 3817 __ c_d(UEQ, f4, f6, 6); 3818 __ c_s(UEQ, f14, f16, 0); 3819 __ movt(t2, t1, 6); 3820 __ movt(t3, t1, 0); 3821 __ sw(t2, MemOperand(a0, offsetof(TestFloat, dUeq)) ); 3822 __ sw(t3, MemOperand(a0, offsetof(TestFloat, fUeq)) ); 3823 3824 __ mov(t2, zero_reg); 3825 __ mov(t3, zero_reg); 3826 __ c_d(OLT, f4, f6, 0); 3827 __ c_s(OLT, f14, f16, 2); 3828 __ movt(t2, t1, 0); 3829 __ movt(t3, t1, 2); 3830 __ sw(t2, MemOperand(a0, offsetof(TestFloat, dOlt)) ); 3831 __ sw(t3, MemOperand(a0, offsetof(TestFloat, fOlt)) ); 3832 3833 __ mov(t2, zero_reg); 3834 __ mov(t3, zero_reg); 3835 __ c_d(ULT, f4, f6, 2); 3836 __ c_s(ULT, f14, f16, 4); 3837 __ movt(t2, t1, 2); 3838 __ movt(t3, t1, 4); 3839 __ sw(t2, MemOperand(a0, offsetof(TestFloat, dUlt)) ); 3840 __ sw(t3, MemOperand(a0, offsetof(TestFloat, fUlt)) ); 3841 3842 __ mov(t2, zero_reg); 3843 __ mov(t3, zero_reg); 3844 __ c_d(OLE, f4, f6, 4); 3845 __ c_s(OLE, f14, f16, 6); 3846 __ movt(t2, t1, 4); 3847 __ movt(t3, t1, 6); 3848 __ sw(t2, MemOperand(a0, offsetof(TestFloat, dOle)) ); 3849 __ sw(t3, MemOperand(a0, offsetof(TestFloat, fOle)) ); 3850 3851 __ mov(t2, zero_reg); 3852 __ mov(t3, zero_reg); 3853 __ c_d(ULE, f4, f6, 6); 3854 __ c_s(ULE, f14, f16, 0); 3855 __ movt(t2, t1, 6); 3856 __ movt(t3, t1, 0); 3857 __ sw(t2, MemOperand(a0, offsetof(TestFloat, dUle)) ); 3858 __ sw(t3, MemOperand(a0, offsetof(TestFloat, fUle)) ); 3859 3860 __ jr(ra); 3861 __ nop(); 3862 3863 CodeDesc desc; 3864 assm.GetCode(&desc); 3865 Handle<Code> code = isolate->factory()->NewCode( 3866 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 3867 F3 f = FUNCTION_CAST<F3>(code->entry()); 3868 test.dOp1 = 2.0; 3869 test.dOp2 = 3.0; 3870 test.fOp1 = 2.0; 3871 test.fOp2 = 3.0; 3872 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 3873 CHECK_EQ(test.dF, 0U); 3874 CHECK_EQ(test.dUn, 0U); 3875 CHECK_EQ(test.dEq, 0U); 3876 CHECK_EQ(test.dUeq, 0U); 3877 CHECK_EQ(test.dOlt, 1U); 3878 CHECK_EQ(test.dUlt, 1U); 3879 CHECK_EQ(test.dOle, 1U); 3880 CHECK_EQ(test.dUle, 1U); 3881 CHECK_EQ(test.fF, 0U); 3882 CHECK_EQ(test.fUn, 0U); 3883 CHECK_EQ(test.fEq, 0U); 3884 CHECK_EQ(test.fUeq, 0U); 3885 CHECK_EQ(test.fOlt, 1U); 3886 CHECK_EQ(test.fUlt, 1U); 3887 CHECK_EQ(test.fOle, 1U); 3888 CHECK_EQ(test.fUle, 1U); 3889 3890 test.dOp1 = std::numeric_limits<double>::max(); 3891 test.dOp2 = std::numeric_limits<double>::min(); 3892 test.fOp1 = std::numeric_limits<float>::min(); 3893 test.fOp2 = -std::numeric_limits<float>::max(); // lowest() 3894 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 3895 CHECK_EQ(test.dF, 0U); 3896 CHECK_EQ(test.dUn, 0U); 3897 CHECK_EQ(test.dEq, 0U); 3898 CHECK_EQ(test.dUeq, 0U); 3899 CHECK_EQ(test.dOlt, 0U); 3900 CHECK_EQ(test.dUlt, 0U); 3901 CHECK_EQ(test.dOle, 0U); 3902 CHECK_EQ(test.dUle, 0U); 3903 CHECK_EQ(test.fF, 0U); 3904 CHECK_EQ(test.fUn, 0U); 3905 CHECK_EQ(test.fEq, 0U); 3906 CHECK_EQ(test.fUeq, 0U); 3907 CHECK_EQ(test.fOlt, 0U); 3908 CHECK_EQ(test.fUlt, 0U); 3909 CHECK_EQ(test.fOle, 0U); 3910 CHECK_EQ(test.fUle, 0U); 3911 3912 test.dOp1 = -std::numeric_limits<double>::max(); // lowest() 3913 test.dOp2 = -std::numeric_limits<double>::max(); // lowest() 3914 test.fOp1 = std::numeric_limits<float>::max(); 3915 test.fOp2 = std::numeric_limits<float>::max(); 3916 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 3917 CHECK_EQ(test.dF, 0U); 3918 CHECK_EQ(test.dUn, 0U); 3919 CHECK_EQ(test.dEq, 1U); 3920 CHECK_EQ(test.dUeq, 1U); 3921 CHECK_EQ(test.dOlt, 0U); 3922 CHECK_EQ(test.dUlt, 0U); 3923 CHECK_EQ(test.dOle, 1U); 3924 CHECK_EQ(test.dUle, 1U); 3925 CHECK_EQ(test.fF, 0U); 3926 CHECK_EQ(test.fUn, 0U); 3927 CHECK_EQ(test.fEq, 1U); 3928 CHECK_EQ(test.fUeq, 1U); 3929 CHECK_EQ(test.fOlt, 0U); 3930 CHECK_EQ(test.fUlt, 0U); 3931 CHECK_EQ(test.fOle, 1U); 3932 CHECK_EQ(test.fUle, 1U); 3933 3934 test.dOp1 = std::numeric_limits<double>::quiet_NaN(); 3935 test.dOp2 = 0.0; 3936 test.fOp1 = std::numeric_limits<float>::quiet_NaN(); 3937 test.fOp2 = 0.0; 3938 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 3939 CHECK_EQ(test.dF, 0U); 3940 CHECK_EQ(test.dUn, 1U); 3941 CHECK_EQ(test.dEq, 0U); 3942 CHECK_EQ(test.dUeq, 1U); 3943 CHECK_EQ(test.dOlt, 0U); 3944 CHECK_EQ(test.dUlt, 1U); 3945 CHECK_EQ(test.dOle, 0U); 3946 CHECK_EQ(test.dUle, 1U); 3947 CHECK_EQ(test.fF, 0U); 3948 CHECK_EQ(test.fUn, 1U); 3949 CHECK_EQ(test.fEq, 0U); 3950 CHECK_EQ(test.fUeq, 1U); 3951 CHECK_EQ(test.fOlt, 0U); 3952 CHECK_EQ(test.fUlt, 1U); 3953 CHECK_EQ(test.fOle, 0U); 3954 CHECK_EQ(test.fUle, 1U); 3955 } 3956 } 3957 3958 3959 TEST(CMP_COND_FMT) { 3960 if (IsMipsArchVariant(kMips32r6)) { 3961 CcTest::InitializeVM(); 3962 Isolate* isolate = CcTest::i_isolate(); 3963 HandleScope scope(isolate); 3964 MacroAssembler assm(isolate, NULL, 0, 3965 v8::internal::CodeObjectRequired::kYes); 3966 3967 typedef struct test_float { 3968 double dOp1; 3969 double dOp2; 3970 double dF; 3971 double dUn; 3972 double dEq; 3973 double dUeq; 3974 double dOlt; 3975 double dUlt; 3976 double dOle; 3977 double dUle; 3978 double dOr; 3979 double dUne; 3980 double dNe; 3981 float fOp1; 3982 float fOp2; 3983 float fF; 3984 float fUn; 3985 float fEq; 3986 float fUeq; 3987 float fOlt; 3988 float fUlt; 3989 float fOle; 3990 float fUle; 3991 float fOr; 3992 float fUne; 3993 float fNe; 3994 } TestFloat; 3995 3996 TestFloat test; 3997 3998 __ li(t1, 1); 3999 4000 __ ldc1(f4, MemOperand(a0, offsetof(TestFloat, dOp1))); 4001 __ ldc1(f6, MemOperand(a0, offsetof(TestFloat, dOp2))); 4002 4003 __ lwc1(f14, MemOperand(a0, offsetof(TestFloat, fOp1))); 4004 __ lwc1(f16, MemOperand(a0, offsetof(TestFloat, fOp2))); 4005 4006 __ cmp_d(F, f2, f4, f6); 4007 __ cmp_s(F, f12, f14, f16); 4008 __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dF)) ); 4009 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fF)) ); 4010 4011 __ cmp_d(UN, f2, f4, f6); 4012 __ cmp_s(UN, f12, f14, f16); 4013 __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dUn)) ); 4014 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fUn)) ); 4015 4016 __ cmp_d(EQ, f2, f4, f6); 4017 __ cmp_s(EQ, f12, f14, f16); 4018 __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dEq)) ); 4019 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fEq)) ); 4020 4021 __ cmp_d(UEQ, f2, f4, f6); 4022 __ cmp_s(UEQ, f12, f14, f16); 4023 __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dUeq)) ); 4024 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fUeq)) ); 4025 4026 __ cmp_d(LT, f2, f4, f6); 4027 __ cmp_s(LT, f12, f14, f16); 4028 __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dOlt)) ); 4029 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fOlt)) ); 4030 4031 __ cmp_d(ULT, f2, f4, f6); 4032 __ cmp_s(ULT, f12, f14, f16); 4033 __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dUlt)) ); 4034 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fUlt)) ); 4035 4036 __ cmp_d(LE, f2, f4, f6); 4037 __ cmp_s(LE, f12, f14, f16); 4038 __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dOle)) ); 4039 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fOle)) ); 4040 4041 __ cmp_d(ULE, f2, f4, f6); 4042 __ cmp_s(ULE, f12, f14, f16); 4043 __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dUle)) ); 4044 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fUle)) ); 4045 4046 __ cmp_d(ORD, f2, f4, f6); 4047 __ cmp_s(ORD, f12, f14, f16); 4048 __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dOr)) ); 4049 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fOr)) ); 4050 4051 __ cmp_d(UNE, f2, f4, f6); 4052 __ cmp_s(UNE, f12, f14, f16); 4053 __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dUne)) ); 4054 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fUne)) ); 4055 4056 __ cmp_d(NE, f2, f4, f6); 4057 __ cmp_s(NE, f12, f14, f16); 4058 __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dNe)) ); 4059 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fNe)) ); 4060 4061 __ jr(ra); 4062 __ nop(); 4063 4064 CodeDesc desc; 4065 assm.GetCode(&desc); 4066 Handle<Code> code = isolate->factory()->NewCode( 4067 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 4068 F3 f = FUNCTION_CAST<F3>(code->entry()); 4069 uint64_t dTrue = 0xFFFFFFFFFFFFFFFF; 4070 uint64_t dFalse = 0x0000000000000000; 4071 uint32_t fTrue = 0xFFFFFFFF; 4072 uint32_t fFalse = 0x00000000; 4073 4074 test.dOp1 = 2.0; 4075 test.dOp2 = 3.0; 4076 test.fOp1 = 2.0; 4077 test.fOp2 = 3.0; 4078 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 4079 CHECK_EQ(bit_cast<uint64_t>(test.dF), dFalse); 4080 CHECK_EQ(bit_cast<uint64_t>(test.dUn), dFalse); 4081 CHECK_EQ(bit_cast<uint64_t>(test.dEq), dFalse); 4082 CHECK_EQ(bit_cast<uint64_t>(test.dUeq), dFalse); 4083 CHECK_EQ(bit_cast<uint64_t>(test.dOlt), dTrue); 4084 CHECK_EQ(bit_cast<uint64_t>(test.dUlt), dTrue); 4085 CHECK_EQ(bit_cast<uint64_t>(test.dOle), dTrue); 4086 CHECK_EQ(bit_cast<uint64_t>(test.dUle), dTrue); 4087 CHECK_EQ(bit_cast<uint64_t>(test.dOr), dTrue); 4088 CHECK_EQ(bit_cast<uint64_t>(test.dUne), dTrue); 4089 CHECK_EQ(bit_cast<uint64_t>(test.dNe), dTrue); 4090 CHECK_EQ(bit_cast<uint32_t>(test.fF), fFalse); 4091 CHECK_EQ(bit_cast<uint32_t>(test.fUn), fFalse); 4092 CHECK_EQ(bit_cast<uint32_t>(test.fEq), fFalse); 4093 CHECK_EQ(bit_cast<uint32_t>(test.fUeq), fFalse); 4094 CHECK_EQ(bit_cast<uint32_t>(test.fOlt), fTrue); 4095 CHECK_EQ(bit_cast<uint32_t>(test.fUlt), fTrue); 4096 CHECK_EQ(bit_cast<uint32_t>(test.fOle), fTrue); 4097 CHECK_EQ(bit_cast<uint32_t>(test.fUle), fTrue); 4098 4099 test.dOp1 = std::numeric_limits<double>::max(); 4100 test.dOp2 = std::numeric_limits<double>::min(); 4101 test.fOp1 = std::numeric_limits<float>::min(); 4102 test.fOp2 = -std::numeric_limits<float>::max(); // lowest() 4103 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 4104 CHECK_EQ(bit_cast<uint64_t>(test.dF), dFalse); 4105 CHECK_EQ(bit_cast<uint64_t>(test.dUn), dFalse); 4106 CHECK_EQ(bit_cast<uint64_t>(test.dEq), dFalse); 4107 CHECK_EQ(bit_cast<uint64_t>(test.dUeq), dFalse); 4108 CHECK_EQ(bit_cast<uint64_t>(test.dOlt), dFalse); 4109 CHECK_EQ(bit_cast<uint64_t>(test.dUlt), dFalse); 4110 CHECK_EQ(bit_cast<uint64_t>(test.dOle), dFalse); 4111 CHECK_EQ(bit_cast<uint64_t>(test.dUle), dFalse); 4112 CHECK_EQ(bit_cast<uint64_t>(test.dOr), dTrue); 4113 CHECK_EQ(bit_cast<uint64_t>(test.dUne), dTrue); 4114 CHECK_EQ(bit_cast<uint64_t>(test.dNe), dTrue); 4115 CHECK_EQ(bit_cast<uint32_t>(test.fF), fFalse); 4116 CHECK_EQ(bit_cast<uint32_t>(test.fUn), fFalse); 4117 CHECK_EQ(bit_cast<uint32_t>(test.fEq), fFalse); 4118 CHECK_EQ(bit_cast<uint32_t>(test.fUeq), fFalse); 4119 CHECK_EQ(bit_cast<uint32_t>(test.fOlt), fFalse); 4120 CHECK_EQ(bit_cast<uint32_t>(test.fUlt), fFalse); 4121 CHECK_EQ(bit_cast<uint32_t>(test.fOle), fFalse); 4122 CHECK_EQ(bit_cast<uint32_t>(test.fUle), fFalse); 4123 4124 test.dOp1 = -std::numeric_limits<double>::max(); // lowest() 4125 test.dOp2 = -std::numeric_limits<double>::max(); // lowest() 4126 test.fOp1 = std::numeric_limits<float>::max(); 4127 test.fOp2 = std::numeric_limits<float>::max(); 4128 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 4129 CHECK_EQ(bit_cast<uint64_t>(test.dF), dFalse); 4130 CHECK_EQ(bit_cast<uint64_t>(test.dUn), dFalse); 4131 CHECK_EQ(bit_cast<uint64_t>(test.dEq), dTrue); 4132 CHECK_EQ(bit_cast<uint64_t>(test.dUeq), dTrue); 4133 CHECK_EQ(bit_cast<uint64_t>(test.dOlt), dFalse); 4134 CHECK_EQ(bit_cast<uint64_t>(test.dUlt), dFalse); 4135 CHECK_EQ(bit_cast<uint64_t>(test.dOle), dTrue); 4136 CHECK_EQ(bit_cast<uint64_t>(test.dUle), dTrue); 4137 CHECK_EQ(bit_cast<uint64_t>(test.dOr), dTrue); 4138 CHECK_EQ(bit_cast<uint64_t>(test.dUne), dFalse); 4139 CHECK_EQ(bit_cast<uint64_t>(test.dNe), dFalse); 4140 CHECK_EQ(bit_cast<uint32_t>(test.fF), fFalse); 4141 CHECK_EQ(bit_cast<uint32_t>(test.fUn), fFalse); 4142 CHECK_EQ(bit_cast<uint32_t>(test.fEq), fTrue); 4143 CHECK_EQ(bit_cast<uint32_t>(test.fUeq), fTrue); 4144 CHECK_EQ(bit_cast<uint32_t>(test.fOlt), fFalse); 4145 CHECK_EQ(bit_cast<uint32_t>(test.fUlt), fFalse); 4146 CHECK_EQ(bit_cast<uint32_t>(test.fOle), fTrue); 4147 CHECK_EQ(bit_cast<uint32_t>(test.fUle), fTrue); 4148 4149 test.dOp1 = std::numeric_limits<double>::quiet_NaN(); 4150 test.dOp2 = 0.0; 4151 test.fOp1 = std::numeric_limits<float>::quiet_NaN(); 4152 test.fOp2 = 0.0; 4153 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 4154 CHECK_EQ(bit_cast<uint64_t>(test.dF), dFalse); 4155 CHECK_EQ(bit_cast<uint64_t>(test.dUn), dTrue); 4156 CHECK_EQ(bit_cast<uint64_t>(test.dEq), dFalse); 4157 CHECK_EQ(bit_cast<uint64_t>(test.dUeq), dTrue); 4158 CHECK_EQ(bit_cast<uint64_t>(test.dOlt), dFalse); 4159 CHECK_EQ(bit_cast<uint64_t>(test.dUlt), dTrue); 4160 CHECK_EQ(bit_cast<uint64_t>(test.dOle), dFalse); 4161 CHECK_EQ(bit_cast<uint64_t>(test.dUle), dTrue); 4162 CHECK_EQ(bit_cast<uint64_t>(test.dOr), dFalse); 4163 CHECK_EQ(bit_cast<uint64_t>(test.dUne), dTrue); 4164 CHECK_EQ(bit_cast<uint64_t>(test.dNe), dFalse); 4165 CHECK_EQ(bit_cast<uint32_t>(test.fF), fFalse); 4166 CHECK_EQ(bit_cast<uint32_t>(test.fUn), fTrue); 4167 CHECK_EQ(bit_cast<uint32_t>(test.fEq), fFalse); 4168 CHECK_EQ(bit_cast<uint32_t>(test.fUeq), fTrue); 4169 CHECK_EQ(bit_cast<uint32_t>(test.fOlt), fFalse); 4170 CHECK_EQ(bit_cast<uint32_t>(test.fUlt), fTrue); 4171 CHECK_EQ(bit_cast<uint32_t>(test.fOle), fFalse); 4172 CHECK_EQ(bit_cast<uint32_t>(test.fUle), fTrue); 4173 } 4174 } 4175 4176 4177 TEST(CVT) { 4178 CcTest::InitializeVM(); 4179 Isolate* isolate = CcTest::i_isolate(); 4180 HandleScope scope(isolate); 4181 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); 4182 4183 typedef struct test_float { 4184 float cvt_d_s_in; 4185 double cvt_d_s_out; 4186 int32_t cvt_d_w_in; 4187 double cvt_d_w_out; 4188 int64_t cvt_d_l_in; 4189 double cvt_d_l_out; 4190 4191 float cvt_l_s_in; 4192 int64_t cvt_l_s_out; 4193 double cvt_l_d_in; 4194 int64_t cvt_l_d_out; 4195 4196 double cvt_s_d_in; 4197 float cvt_s_d_out; 4198 int32_t cvt_s_w_in; 4199 float cvt_s_w_out; 4200 int64_t cvt_s_l_in; 4201 float cvt_s_l_out; 4202 4203 float cvt_w_s_in; 4204 int32_t cvt_w_s_out; 4205 double cvt_w_d_in; 4206 int32_t cvt_w_d_out; 4207 } TestFloat; 4208 4209 TestFloat test; 4210 4211 // Save FCSR. 4212 __ cfc1(a1, FCSR); 4213 // Disable FPU exceptions. 4214 __ ctc1(zero_reg, FCSR); 4215 4216 #define GENERATE_CVT_TEST(x, y, z) \ 4217 __ y##c1(f0, MemOperand(a0, offsetof(TestFloat, x##_in))); \ 4218 __ x(f0, f0); \ 4219 __ nop(); \ 4220 __ z##c1(f0, MemOperand(a0, offsetof(TestFloat, x##_out))); 4221 4222 GENERATE_CVT_TEST(cvt_d_s, lw, sd) 4223 GENERATE_CVT_TEST(cvt_d_w, lw, sd) 4224 if ((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) && 4225 IsFp64Mode()) { 4226 GENERATE_CVT_TEST(cvt_d_l, ld, sd) 4227 } 4228 4229 if (IsFp64Mode()) { 4230 GENERATE_CVT_TEST(cvt_l_s, lw, sd) 4231 GENERATE_CVT_TEST(cvt_l_d, ld, sd) 4232 } 4233 4234 GENERATE_CVT_TEST(cvt_s_d, ld, sw) 4235 GENERATE_CVT_TEST(cvt_s_w, lw, sw) 4236 if ((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) && 4237 IsFp64Mode()) { 4238 GENERATE_CVT_TEST(cvt_s_l, ld, sw) 4239 } 4240 4241 GENERATE_CVT_TEST(cvt_w_s, lw, sw) 4242 GENERATE_CVT_TEST(cvt_w_d, ld, sw) 4243 4244 // Restore FCSR. 4245 __ ctc1(a1, FCSR); 4246 4247 __ jr(ra); 4248 __ nop(); 4249 4250 CodeDesc desc; 4251 assm.GetCode(&desc); 4252 Handle<Code> code = isolate->factory()->NewCode( 4253 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 4254 F3 f = FUNCTION_CAST<F3>(code->entry()); 4255 4256 test.cvt_d_s_in = -0.51; 4257 test.cvt_d_w_in = -1; 4258 test.cvt_d_l_in = -1; 4259 test.cvt_l_s_in = -0.51; 4260 test.cvt_l_d_in = -0.51; 4261 test.cvt_s_d_in = -0.51; 4262 test.cvt_s_w_in = -1; 4263 test.cvt_s_l_in = -1; 4264 test.cvt_w_s_in = -0.51; 4265 test.cvt_w_d_in = -0.51; 4266 4267 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 4268 CHECK_EQ(test.cvt_d_s_out, static_cast<double>(test.cvt_d_s_in)); 4269 CHECK_EQ(test.cvt_d_w_out, static_cast<double>(test.cvt_d_w_in)); 4270 if ((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) && 4271 IsFp64Mode()) { 4272 CHECK_EQ(test.cvt_d_l_out, static_cast<double>(test.cvt_d_l_in)); 4273 } 4274 if (IsFp64Mode()) { 4275 CHECK_EQ(test.cvt_l_s_out, -1); 4276 CHECK_EQ(test.cvt_l_d_out, -1); 4277 } 4278 CHECK_EQ(test.cvt_s_d_out, static_cast<float>(test.cvt_s_d_in)); 4279 CHECK_EQ(test.cvt_s_w_out, static_cast<float>(test.cvt_s_w_in)); 4280 if ((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) && 4281 IsFp64Mode()) { 4282 CHECK_EQ(test.cvt_s_l_out, static_cast<float>(test.cvt_s_l_in)); 4283 } 4284 CHECK_EQ(test.cvt_w_s_out, -1); 4285 CHECK_EQ(test.cvt_w_d_out, -1); 4286 4287 4288 test.cvt_d_s_in = 0.49; 4289 test.cvt_d_w_in = 1; 4290 test.cvt_d_l_in = 1; 4291 test.cvt_l_s_in = 0.49; 4292 test.cvt_l_d_in = 0.49; 4293 test.cvt_s_d_in = 0.49; 4294 test.cvt_s_w_in = 1; 4295 test.cvt_s_l_in = 1; 4296 test.cvt_w_s_in = 0.49; 4297 test.cvt_w_d_in = 0.49; 4298 4299 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 4300 CHECK_EQ(test.cvt_d_s_out, static_cast<double>(test.cvt_d_s_in)); 4301 CHECK_EQ(test.cvt_d_w_out, static_cast<double>(test.cvt_d_w_in)); 4302 if ((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) && 4303 IsFp64Mode()) { 4304 CHECK_EQ(test.cvt_d_l_out, static_cast<double>(test.cvt_d_l_in)); 4305 } 4306 if (IsFp64Mode()) { 4307 CHECK_EQ(test.cvt_l_s_out, 0); 4308 CHECK_EQ(test.cvt_l_d_out, 0); 4309 } 4310 CHECK_EQ(test.cvt_s_d_out, static_cast<float>(test.cvt_s_d_in)); 4311 CHECK_EQ(test.cvt_s_w_out, static_cast<float>(test.cvt_s_w_in)); 4312 if ((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) && 4313 IsFp64Mode()) { 4314 CHECK_EQ(test.cvt_s_l_out, static_cast<float>(test.cvt_s_l_in)); 4315 } 4316 CHECK_EQ(test.cvt_w_s_out, 0); 4317 CHECK_EQ(test.cvt_w_d_out, 0); 4318 4319 test.cvt_d_s_in = std::numeric_limits<float>::max(); 4320 test.cvt_d_w_in = std::numeric_limits<int32_t>::max(); 4321 test.cvt_d_l_in = std::numeric_limits<int64_t>::max(); 4322 test.cvt_l_s_in = std::numeric_limits<float>::max(); 4323 test.cvt_l_d_in = std::numeric_limits<double>::max(); 4324 test.cvt_s_d_in = std::numeric_limits<double>::max(); 4325 test.cvt_s_w_in = std::numeric_limits<int32_t>::max(); 4326 test.cvt_s_l_in = std::numeric_limits<int64_t>::max(); 4327 test.cvt_w_s_in = std::numeric_limits<float>::max(); 4328 test.cvt_w_d_in = std::numeric_limits<double>::max(); 4329 4330 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 4331 CHECK_EQ(test.cvt_d_s_out, static_cast<double>(test.cvt_d_s_in)); 4332 CHECK_EQ(test.cvt_d_w_out, static_cast<double>(test.cvt_d_w_in)); 4333 if ((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) && 4334 IsFp64Mode()) { 4335 CHECK_EQ(test.cvt_d_l_out, static_cast<double>(test.cvt_d_l_in)); 4336 } 4337 if (IsFp64Mode()) { 4338 CHECK_EQ(test.cvt_l_s_out, std::numeric_limits<int64_t>::max()); 4339 CHECK_EQ(test.cvt_l_d_out, std::numeric_limits<int64_t>::max()); 4340 } 4341 CHECK_EQ(test.cvt_s_d_out, static_cast<float>(test.cvt_s_d_in)); 4342 CHECK_EQ(test.cvt_s_w_out, static_cast<float>(test.cvt_s_w_in)); 4343 if ((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) && 4344 IsFp64Mode()) { 4345 CHECK_EQ(test.cvt_s_l_out, static_cast<float>(test.cvt_s_l_in)); 4346 } 4347 CHECK_EQ(test.cvt_w_s_out, std::numeric_limits<int32_t>::max()); 4348 CHECK_EQ(test.cvt_w_d_out, std::numeric_limits<int32_t>::max()); 4349 4350 4351 test.cvt_d_s_in = -std::numeric_limits<float>::max(); // lowest() 4352 test.cvt_d_w_in = std::numeric_limits<int32_t>::min(); // lowest() 4353 test.cvt_d_l_in = std::numeric_limits<int64_t>::min(); // lowest() 4354 test.cvt_l_s_in = -std::numeric_limits<float>::max(); // lowest() 4355 test.cvt_l_d_in = -std::numeric_limits<double>::max(); // lowest() 4356 test.cvt_s_d_in = -std::numeric_limits<double>::max(); // lowest() 4357 test.cvt_s_w_in = std::numeric_limits<int32_t>::min(); // lowest() 4358 test.cvt_s_l_in = std::numeric_limits<int64_t>::min(); // lowest() 4359 test.cvt_w_s_in = -std::numeric_limits<float>::max(); // lowest() 4360 test.cvt_w_d_in = -std::numeric_limits<double>::max(); // lowest() 4361 4362 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 4363 CHECK_EQ(test.cvt_d_s_out, static_cast<double>(test.cvt_d_s_in)); 4364 CHECK_EQ(test.cvt_d_w_out, static_cast<double>(test.cvt_d_w_in)); 4365 if ((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) && 4366 IsFp64Mode()) { 4367 CHECK_EQ(test.cvt_d_l_out, static_cast<double>(test.cvt_d_l_in)); 4368 } 4369 // The returned value when converting from fixed-point to float-point 4370 // is not consistent between board, simulator and specification 4371 // in this test case, therefore modifying the test 4372 if (IsFp64Mode()) { 4373 CHECK(test.cvt_l_s_out == std::numeric_limits<int64_t>::min() || 4374 test.cvt_l_s_out == std::numeric_limits<int64_t>::max()); 4375 CHECK(test.cvt_l_d_out == std::numeric_limits<int64_t>::min() || 4376 test.cvt_l_d_out == std::numeric_limits<int64_t>::max()); 4377 } 4378 CHECK_EQ(test.cvt_s_d_out, static_cast<float>(test.cvt_s_d_in)); 4379 CHECK_EQ(test.cvt_s_w_out, static_cast<float>(test.cvt_s_w_in)); 4380 if ((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) && 4381 IsFp64Mode()) { 4382 CHECK_EQ(test.cvt_s_l_out, static_cast<float>(test.cvt_s_l_in)); 4383 } 4384 CHECK(test.cvt_w_s_out == std::numeric_limits<int32_t>::min() || 4385 test.cvt_w_s_out == std::numeric_limits<int32_t>::max()); 4386 CHECK(test.cvt_w_d_out == std::numeric_limits<int32_t>::min() || 4387 test.cvt_w_d_out == std::numeric_limits<int32_t>::max()); 4388 4389 4390 test.cvt_d_s_in = std::numeric_limits<float>::min(); 4391 test.cvt_d_w_in = std::numeric_limits<int32_t>::min(); 4392 test.cvt_d_l_in = std::numeric_limits<int64_t>::min(); 4393 test.cvt_l_s_in = std::numeric_limits<float>::min(); 4394 test.cvt_l_d_in = std::numeric_limits<double>::min(); 4395 test.cvt_s_d_in = std::numeric_limits<double>::min(); 4396 test.cvt_s_w_in = std::numeric_limits<int32_t>::min(); 4397 test.cvt_s_l_in = std::numeric_limits<int64_t>::min(); 4398 test.cvt_w_s_in = std::numeric_limits<float>::min(); 4399 test.cvt_w_d_in = std::numeric_limits<double>::min(); 4400 4401 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 4402 CHECK_EQ(test.cvt_d_s_out, static_cast<double>(test.cvt_d_s_in)); 4403 CHECK_EQ(test.cvt_d_w_out, static_cast<double>(test.cvt_d_w_in)); 4404 if ((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) && 4405 IsFp64Mode()) { 4406 CHECK_EQ(test.cvt_d_l_out, static_cast<double>(test.cvt_d_l_in)); 4407 } 4408 if (IsFp64Mode()) { 4409 CHECK_EQ(test.cvt_l_s_out, 0); 4410 CHECK_EQ(test.cvt_l_d_out, 0); 4411 } 4412 CHECK_EQ(test.cvt_s_d_out, static_cast<float>(test.cvt_s_d_in)); 4413 CHECK_EQ(test.cvt_s_w_out, static_cast<float>(test.cvt_s_w_in)); 4414 if ((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) && 4415 IsFp64Mode()) { 4416 CHECK_EQ(test.cvt_s_l_out, static_cast<float>(test.cvt_s_l_in)); 4417 } 4418 CHECK_EQ(test.cvt_w_s_out, 0); 4419 CHECK_EQ(test.cvt_w_d_out, 0); 4420 } 4421 4422 4423 TEST(DIV_FMT) { 4424 CcTest::InitializeVM(); 4425 Isolate* isolate = CcTest::i_isolate(); 4426 HandleScope scope(isolate); 4427 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); 4428 4429 typedef struct test { 4430 double dOp1; 4431 double dOp2; 4432 double dRes; 4433 float fOp1; 4434 float fOp2; 4435 float fRes; 4436 } Test; 4437 4438 Test test; 4439 4440 // Save FCSR. 4441 __ cfc1(a1, FCSR); 4442 // Disable FPU exceptions. 4443 __ ctc1(zero_reg, FCSR); 4444 4445 __ ldc1(f4, MemOperand(a0, offsetof(Test, dOp1)) ); 4446 __ ldc1(f2, MemOperand(a0, offsetof(Test, dOp2)) ); 4447 __ nop(); 4448 __ div_d(f6, f4, f2); 4449 __ sdc1(f6, MemOperand(a0, offsetof(Test, dRes)) ); 4450 4451 __ lwc1(f4, MemOperand(a0, offsetof(Test, fOp1)) ); 4452 __ lwc1(f2, MemOperand(a0, offsetof(Test, fOp2)) ); 4453 __ nop(); 4454 __ div_s(f6, f4, f2); 4455 __ swc1(f6, MemOperand(a0, offsetof(Test, fRes)) ); 4456 4457 // Restore FCSR. 4458 __ ctc1(a1, FCSR); 4459 4460 __ jr(ra); 4461 __ nop(); 4462 4463 CodeDesc desc; 4464 assm.GetCode(&desc); 4465 Handle<Code> code = isolate->factory()->NewCode( 4466 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 4467 4468 F3 f = FUNCTION_CAST<F3>(code->entry()); 4469 4470 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 4471 4472 const int test_size = 3; 4473 4474 double dOp1[test_size] = { 4475 5.0, 4476 DBL_MAX, 4477 DBL_MAX, 4478 }; 4479 double dOp2[test_size] = { 4480 2.0, 4481 2.0, 4482 -DBL_MAX, 4483 }; 4484 double dRes[test_size] = { 4485 2.5, 4486 DBL_MAX / 2.0, 4487 -1.0, 4488 }; 4489 float fOp1[test_size] = { 4490 5.0, 4491 FLT_MAX, 4492 FLT_MAX, 4493 }; 4494 float fOp2[test_size] = { 4495 2.0, 4496 2.0, 4497 -FLT_MAX, 4498 }; 4499 float fRes[test_size] = { 4500 2.5, 4501 FLT_MAX / 2.0, 4502 -1.0, 4503 }; 4504 4505 for (int i = 0; i < test_size; i++) { 4506 test.dOp1 = dOp1[i]; 4507 test.dOp2 = dOp2[i]; 4508 test.fOp1 = fOp1[i]; 4509 test.fOp2 = fOp2[i]; 4510 4511 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 4512 CHECK_EQ(test.dRes, dRes[i]); 4513 CHECK_EQ(test.fRes, fRes[i]); 4514 } 4515 4516 test.dOp1 = DBL_MAX; 4517 test.dOp2 = -0.0; 4518 test.fOp1 = FLT_MAX; 4519 test.fOp2 = -0.0; 4520 4521 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 4522 CHECK_EQ(false, std::isfinite(test.dRes)); 4523 CHECK_EQ(false, std::isfinite(test.fRes)); 4524 4525 test.dOp1 = 0.0; 4526 test.dOp2 = -0.0; 4527 test.fOp1 = 0.0; 4528 test.fOp2 = -0.0; 4529 4530 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 4531 CHECK_EQ(true, std::isnan(test.dRes)); 4532 CHECK_EQ(true, std::isnan(test.fRes)); 4533 4534 test.dOp1 = std::numeric_limits<double>::quiet_NaN(); 4535 test.dOp2 = -5.0; 4536 test.fOp1 = std::numeric_limits<float>::quiet_NaN(); 4537 test.fOp2 = -5.0; 4538 4539 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 4540 CHECK_EQ(true, std::isnan(test.dRes)); 4541 CHECK_EQ(true, std::isnan(test.fRes)); 4542 } 4543 4544 4545 uint32_t run_align(uint32_t rs_value, uint32_t rt_value, uint8_t bp) { 4546 Isolate* isolate = CcTest::i_isolate(); 4547 HandleScope scope(isolate); 4548 4549 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); 4550 4551 __ align(v0, a0, a1, bp); 4552 __ jr(ra); 4553 __ nop(); 4554 4555 CodeDesc desc; 4556 assm.GetCode(&desc); 4557 Handle<Code> code = isolate->factory()->NewCode( 4558 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 4559 4560 F2 f = FUNCTION_CAST<F2>(code->entry()); 4561 4562 uint32_t res = reinterpret_cast<uint32_t>(CALL_GENERATED_CODE( 4563 isolate, f, rs_value, rt_value, 0, 0, 0)); 4564 4565 return res; 4566 } 4567 4568 4569 TEST(r6_align) { 4570 if (IsMipsArchVariant(kMips32r6)) { 4571 CcTest::InitializeVM(); 4572 4573 struct TestCaseAlign { 4574 uint32_t rs_value; 4575 uint32_t rt_value; 4576 uint8_t bp; 4577 uint32_t expected_res; 4578 }; 4579 4580 struct TestCaseAlign tc[] = { 4581 // rs_value, rt_value, bp, expected_res 4582 { 0x11223344, 0xaabbccdd, 0, 0xaabbccdd }, 4583 { 0x11223344, 0xaabbccdd, 1, 0xbbccdd11 }, 4584 { 0x11223344, 0xaabbccdd, 2, 0xccdd1122 }, 4585 { 0x11223344, 0xaabbccdd, 3, 0xdd112233 }, 4586 }; 4587 4588 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseAlign); 4589 for (size_t i = 0; i < nr_test_cases; ++i) { 4590 CHECK_EQ(tc[i].expected_res, run_align(tc[i].rs_value, 4591 tc[i].rt_value, tc[i].bp)); 4592 } 4593 } 4594 } 4595 4596 uint32_t PC; // The program counter. 4597 4598 uint32_t run_aluipc(int16_t offset) { 4599 Isolate* isolate = CcTest::i_isolate(); 4600 HandleScope scope(isolate); 4601 4602 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); 4603 4604 __ aluipc(v0, offset); 4605 __ jr(ra); 4606 __ nop(); 4607 4608 CodeDesc desc; 4609 assm.GetCode(&desc); 4610 Handle<Code> code = isolate->factory()->NewCode( 4611 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 4612 4613 F2 f = FUNCTION_CAST<F2>(code->entry()); 4614 PC = (uint32_t) f; // Set the program counter. 4615 4616 uint32_t res = reinterpret_cast<uint32_t>( 4617 CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0)); 4618 4619 return res; 4620 } 4621 4622 4623 TEST(r6_aluipc) { 4624 if (IsMipsArchVariant(kMips32r6)) { 4625 CcTest::InitializeVM(); 4626 4627 struct TestCaseAluipc { 4628 int16_t offset; 4629 }; 4630 4631 struct TestCaseAluipc tc[] = { 4632 // offset 4633 { -32768 }, // 0x8000 4634 { -1 }, // 0xFFFF 4635 { 0 }, 4636 { 1 }, 4637 { 32767 }, // 0x7FFF 4638 }; 4639 4640 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseAluipc); 4641 for (size_t i = 0; i < nr_test_cases; ++i) { 4642 PC = 0; 4643 uint32_t res = run_aluipc(tc[i].offset); 4644 // Now, the program_counter (PC) is set. 4645 uint32_t expected_res = ~0x0FFFF & (PC + (tc[i].offset << 16)); 4646 CHECK_EQ(expected_res, res); 4647 } 4648 } 4649 } 4650 4651 4652 uint32_t run_auipc(int16_t offset) { 4653 Isolate* isolate = CcTest::i_isolate(); 4654 HandleScope scope(isolate); 4655 4656 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); 4657 4658 __ auipc(v0, offset); 4659 __ jr(ra); 4660 __ nop(); 4661 4662 CodeDesc desc; 4663 assm.GetCode(&desc); 4664 Handle<Code> code = isolate->factory()->NewCode( 4665 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 4666 4667 F2 f = FUNCTION_CAST<F2>(code->entry()); 4668 PC = (uint32_t) f; // Set the program counter. 4669 4670 uint32_t res = reinterpret_cast<uint32_t>( 4671 CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0)); 4672 4673 return res; 4674 } 4675 4676 4677 TEST(r6_auipc) { 4678 if (IsMipsArchVariant(kMips32r6)) { 4679 CcTest::InitializeVM(); 4680 4681 struct TestCaseAuipc { 4682 int16_t offset; 4683 }; 4684 4685 struct TestCaseAuipc tc[] = { 4686 // offset 4687 { -32768 }, // 0x8000 4688 { -1 }, // 0xFFFF 4689 { 0 }, 4690 { 1 }, 4691 { 32767 }, // 0x7FFF 4692 }; 4693 4694 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseAuipc); 4695 for (size_t i = 0; i < nr_test_cases; ++i) { 4696 PC = 0; 4697 uint32_t res = run_auipc(tc[i].offset); 4698 // Now, the program_counter (PC) is set. 4699 uint32_t expected_res = PC + (tc[i].offset << 16); 4700 CHECK_EQ(expected_res, res); 4701 } 4702 } 4703 } 4704 4705 4706 uint32_t run_lwpc(int offset) { 4707 Isolate* isolate = CcTest::i_isolate(); 4708 HandleScope scope(isolate); 4709 4710 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); 4711 4712 // 256k instructions; 2^8k 4713 // addiu t7, t0, 0xffff; (0x250fffff) 4714 // ... 4715 // addiu t4, t0, 0x0000; (0x250c0000) 4716 uint32_t addiu_start_1 = 0x25000000; 4717 for (int32_t i = 0xfffff; i >= 0xc0000; --i) { 4718 uint32_t addiu_new = addiu_start_1 + i; 4719 __ dd(addiu_new); 4720 } 4721 4722 __ lwpc(t8, offset); // offset 0; 0xef080000 (t8 register) 4723 __ mov(v0, t8); 4724 4725 // 256k instructions; 2^8k 4726 // addiu t0, t0, 0x0000; (0x25080000) 4727 // ... 4728 // addiu t3, t0, 0xffff; (0x250bffff) 4729 uint32_t addiu_start_2 = 0x25000000; 4730 for (int32_t i = 0x80000; i <= 0xbffff; ++i) { 4731 uint32_t addiu_new = addiu_start_2 + i; 4732 __ dd(addiu_new); 4733 } 4734 4735 __ jr(ra); 4736 __ nop(); 4737 4738 CodeDesc desc; 4739 assm.GetCode(&desc); 4740 Handle<Code> code = isolate->factory()->NewCode( 4741 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 4742 4743 F2 f = FUNCTION_CAST<F2>(code->entry()); 4744 4745 uint32_t res = reinterpret_cast<uint32_t>( 4746 CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0)); 4747 4748 return res; 4749 } 4750 4751 4752 TEST(r6_lwpc) { 4753 if (IsMipsArchVariant(kMips32r6)) { 4754 CcTest::InitializeVM(); 4755 4756 struct TestCaseLwpc { 4757 int offset; 4758 uint32_t expected_res; 4759 }; 4760 4761 struct TestCaseLwpc tc[] = { 4762 // offset, expected_res 4763 { -262144, 0x250fffff }, // offset 0x40000 4764 { -4, 0x250c0003 }, 4765 { -1, 0x250c0000 }, 4766 { 0, 0xef080000 }, 4767 { 1, 0x03001025 }, // mov(v0, t8) 4768 { 2, 0x25080000 }, 4769 { 4, 0x25080002 }, 4770 { 262143, 0x250bfffd }, // offset 0x3ffff 4771 }; 4772 4773 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseLwpc); 4774 for (size_t i = 0; i < nr_test_cases; ++i) { 4775 uint32_t res = run_lwpc(tc[i].offset); 4776 CHECK_EQ(tc[i].expected_res, res); 4777 } 4778 } 4779 } 4780 4781 4782 uint32_t run_jic(int16_t offset) { 4783 Isolate* isolate = CcTest::i_isolate(); 4784 HandleScope scope(isolate); 4785 4786 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); 4787 4788 Label get_program_counter, stop_execution; 4789 __ push(ra); 4790 __ li(v0, 0); 4791 __ li(t1, 0x66); 4792 4793 __ addiu(v0, v0, 0x1); // <-- offset = -32 4794 __ addiu(v0, v0, 0x2); 4795 __ addiu(v0, v0, 0x10); 4796 __ addiu(v0, v0, 0x20); 4797 __ beq(v0, t1, &stop_execution); 4798 __ nop(); 4799 4800 __ bal(&get_program_counter); // t0 <- program counter 4801 __ nop(); 4802 __ jic(t0, offset); 4803 4804 __ addiu(v0, v0, 0x100); 4805 __ addiu(v0, v0, 0x200); 4806 __ addiu(v0, v0, 0x1000); 4807 __ addiu(v0, v0, 0x2000); // <--- offset = 16 4808 __ pop(ra); 4809 __ jr(ra); 4810 __ nop(); 4811 4812 __ bind(&get_program_counter); 4813 __ mov(t0, ra); 4814 __ jr(ra); 4815 __ nop(); 4816 4817 __ bind(&stop_execution); 4818 __ pop(ra); 4819 __ jr(ra); 4820 __ nop(); 4821 4822 CodeDesc desc; 4823 assm.GetCode(&desc); 4824 Handle<Code> code = isolate->factory()->NewCode( 4825 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 4826 4827 F2 f = FUNCTION_CAST<F2>(code->entry()); 4828 4829 uint32_t res = reinterpret_cast<uint32_t>( 4830 CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0)); 4831 4832 return res; 4833 } 4834 4835 4836 TEST(r6_jic) { 4837 if (IsMipsArchVariant(kMips32r6)) { 4838 CcTest::InitializeVM(); 4839 4840 struct TestCaseJic { 4841 // As rt will be used t0 register which will have value of 4842 // the program counter for the jic instruction. 4843 int16_t offset; 4844 uint32_t expected_res; 4845 }; 4846 4847 struct TestCaseJic tc[] = { 4848 // offset, expected_result 4849 { 16, 0x2033 }, 4850 { 4, 0x3333 }, 4851 { -32, 0x66 }, 4852 }; 4853 4854 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseJic); 4855 for (size_t i = 0; i < nr_test_cases; ++i) { 4856 uint32_t res = run_jic(tc[i].offset); 4857 CHECK_EQ(tc[i].expected_res, res); 4858 } 4859 } 4860 } 4861 4862 4863 uint64_t run_beqzc(int32_t value, int32_t offset) { 4864 Isolate* isolate = CcTest::i_isolate(); 4865 HandleScope scope(isolate); 4866 4867 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); 4868 4869 Label stop_execution; 4870 __ li(v0, 0); 4871 __ li(t1, 0x66); 4872 4873 __ addiu(v0, v0, 0x1); // <-- offset = -32 4874 __ addiu(v0, v0, 0x2); 4875 __ addiu(v0, v0, 0x10); 4876 __ addiu(v0, v0, 0x20); 4877 __ beq(v0, t1, &stop_execution); 4878 __ nop(); 4879 4880 __ beqzc(a0, offset); // BEQZC rs, offset 4881 4882 __ addiu(v0, v0, 0x1); 4883 __ addiu(v0, v0, 0x100); 4884 __ addiu(v0, v0, 0x200); 4885 __ addiu(v0, v0, 0x1000); 4886 __ addiu(v0, v0, 0x2000); // <--- offset = 16 4887 __ jr(ra); 4888 __ nop(); 4889 4890 __ bind(&stop_execution); 4891 __ jr(ra); 4892 __ nop(); 4893 4894 CodeDesc desc; 4895 assm.GetCode(&desc); 4896 Handle<Code> code = isolate->factory()->NewCode( 4897 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 4898 4899 F2 f = FUNCTION_CAST<F2>(code->entry()); 4900 4901 uint32_t res = reinterpret_cast<uint32_t>( 4902 CALL_GENERATED_CODE(isolate, f, value, 0, 0, 0, 0)); 4903 4904 return res; 4905 } 4906 4907 4908 TEST(r6_beqzc) { 4909 if (IsMipsArchVariant(kMips32r6)) { 4910 CcTest::InitializeVM(); 4911 4912 struct TestCaseBeqzc { 4913 uint32_t value; 4914 int32_t offset; 4915 uint32_t expected_res; 4916 }; 4917 4918 struct TestCaseBeqzc tc[] = { 4919 // value, offset, expected_res 4920 { 0x0, -8, 0x66 }, 4921 { 0x0, 0, 0x3334 }, 4922 { 0x0, 1, 0x3333 }, 4923 { 0xabc, 1, 0x3334 }, 4924 { 0x0, 4, 0x2033 }, 4925 }; 4926 4927 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseBeqzc); 4928 for (size_t i = 0; i < nr_test_cases; ++i) { 4929 uint32_t res = run_beqzc(tc[i].value, tc[i].offset); 4930 CHECK_EQ(tc[i].expected_res, res); 4931 } 4932 } 4933 } 4934 4935 4936 uint32_t run_jialc(int16_t offset) { 4937 Isolate* isolate = CcTest::i_isolate(); 4938 HandleScope scope(isolate); 4939 4940 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); 4941 4942 Label main_block, get_program_counter; 4943 __ push(ra); 4944 __ li(v0, 0); 4945 __ beq(v0, v0, &main_block); 4946 __ nop(); 4947 4948 // Block 1 4949 __ addiu(v0, v0, 0x1); // <-- offset = -40 4950 __ addiu(v0, v0, 0x2); 4951 __ jr(ra); 4952 __ nop(); 4953 4954 // Block 2 4955 __ addiu(v0, v0, 0x10); // <-- offset = -24 4956 __ addiu(v0, v0, 0x20); 4957 __ jr(ra); 4958 __ nop(); 4959 4960 // Block 3 (Main) 4961 __ bind(&main_block); 4962 __ bal(&get_program_counter); // t0 <- program counter 4963 __ nop(); 4964 __ jialc(t0, offset); 4965 __ addiu(v0, v0, 0x4); 4966 __ pop(ra); 4967 __ jr(ra); 4968 __ nop(); 4969 4970 // Block 4 4971 __ addiu(v0, v0, 0x100); // <-- offset = 20 4972 __ addiu(v0, v0, 0x200); 4973 __ jr(ra); 4974 __ nop(); 4975 4976 // Block 5 4977 __ addiu(v0, v0, 0x1000); // <--- offset = 36 4978 __ addiu(v0, v0, 0x2000); 4979 __ jr(ra); 4980 __ nop(); 4981 4982 __ bind(&get_program_counter); 4983 __ mov(t0, ra); 4984 __ jr(ra); 4985 __ nop(); 4986 4987 4988 CodeDesc desc; 4989 assm.GetCode(&desc); 4990 Handle<Code> code = isolate->factory()->NewCode( 4991 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 4992 4993 F2 f = FUNCTION_CAST<F2>(code->entry()); 4994 4995 uint32_t res = reinterpret_cast<uint32_t>( 4996 CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0)); 4997 4998 return res; 4999 } 5000 5001 5002 TEST(r6_jialc) { 5003 if (IsMipsArchVariant(kMips32r6)) { 5004 CcTest::InitializeVM(); 5005 5006 struct TestCaseJialc { 5007 int16_t offset; 5008 uint32_t expected_res; 5009 }; 5010 5011 struct TestCaseJialc tc[] = { 5012 // offset, expected_res 5013 { -40, 0x7 }, 5014 { -24, 0x34 }, 5015 { 20, 0x304 }, 5016 { 36, 0x3004 } 5017 }; 5018 5019 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseJialc); 5020 for (size_t i = 0; i < nr_test_cases; ++i) { 5021 uint32_t res = run_jialc(tc[i].offset); 5022 CHECK_EQ(tc[i].expected_res, res); 5023 } 5024 } 5025 } 5026 5027 5028 uint64_t run_addiupc(int32_t imm19) { 5029 Isolate* isolate = CcTest::i_isolate(); 5030 HandleScope scope(isolate); 5031 5032 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); 5033 5034 __ addiupc(v0, imm19); 5035 __ jr(ra); 5036 __ nop(); 5037 5038 CodeDesc desc; 5039 assm.GetCode(&desc); 5040 Handle<Code> code = isolate->factory()->NewCode( 5041 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 5042 5043 F2 f = FUNCTION_CAST<F2>(code->entry()); 5044 PC = (uint32_t) f; // Set the program counter. 5045 5046 uint32_t rs = reinterpret_cast<uint32_t>( 5047 CALL_GENERATED_CODE(isolate, f, imm19, 0, 0, 0, 0)); 5048 5049 return rs; 5050 } 5051 5052 5053 TEST(r6_addiupc) { 5054 if (IsMipsArchVariant(kMips32r6)) { 5055 CcTest::InitializeVM(); 5056 5057 struct TestCaseAddiupc { 5058 int32_t imm19; 5059 }; 5060 5061 struct TestCaseAddiupc tc[] = { 5062 // imm19 5063 { -262144 }, // 0x40000 5064 { -1 }, // 0x7FFFF 5065 { 0 }, 5066 { 1 }, // 0x00001 5067 { 262143 } // 0x3FFFF 5068 }; 5069 5070 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseAddiupc); 5071 for (size_t i = 0; i < nr_test_cases; ++i) { 5072 PC = 0; 5073 uint32_t res = run_addiupc(tc[i].imm19); 5074 // Now, the program_counter (PC) is set. 5075 uint32_t expected_res = PC + (tc[i].imm19 << 2); 5076 CHECK_EQ(expected_res, res); 5077 } 5078 } 5079 } 5080 5081 5082 int32_t run_bc(int32_t offset) { 5083 Isolate* isolate = CcTest::i_isolate(); 5084 HandleScope scope(isolate); 5085 5086 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); 5087 5088 Label continue_1, stop_execution; 5089 __ push(ra); 5090 __ li(v0, 0); 5091 __ li(t8, 0); 5092 __ li(t9, 2); // A condition for stopping execution. 5093 5094 for (int32_t i = -100; i <= -11; ++i) { 5095 __ addiu(v0, v0, 1); 5096 } 5097 5098 __ addiu(t8, t8, 1); // -10 5099 5100 __ beq(t8, t9, &stop_execution); // -9 5101 __ nop(); // -8 5102 __ beq(t8, t8, &continue_1); // -7 5103 __ nop(); // -6 5104 5105 __ bind(&stop_execution); 5106 __ pop(ra); // -5, -4 5107 __ jr(ra); // -3 5108 __ nop(); // -2 5109 5110 __ bind(&continue_1); 5111 __ bc(offset); // -1 5112 5113 for (int32_t i = 0; i <= 99; ++i) { 5114 __ addiu(v0, v0, 1); 5115 } 5116 5117 __ pop(ra); 5118 __ jr(ra); 5119 __ nop(); 5120 5121 CodeDesc desc; 5122 assm.GetCode(&desc); 5123 Handle<Code> code = isolate->factory()->NewCode( 5124 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 5125 5126 F2 f = FUNCTION_CAST<F2>(code->entry()); 5127 5128 int32_t res = reinterpret_cast<int32_t>( 5129 CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0)); 5130 5131 return res; 5132 } 5133 5134 5135 TEST(r6_bc) { 5136 if (IsMipsArchVariant(kMips32r6)) { 5137 CcTest::InitializeVM(); 5138 5139 struct TestCaseBc { 5140 int32_t offset; 5141 int32_t expected_res; 5142 }; 5143 5144 struct TestCaseBc tc[] = { 5145 // offset, expected_result 5146 { -100, (abs(-100) - 10) * 2 }, 5147 { -11, (abs(-100) - 10 + 1) }, 5148 { 0, (abs(-100) - 10 + 1 + 99) }, 5149 { 1, (abs(-100) - 10 + 99) }, 5150 { 99, (abs(-100) - 10 + 1) }, 5151 }; 5152 5153 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseBc); 5154 for (size_t i = 0; i < nr_test_cases; ++i) { 5155 int32_t res = run_bc(tc[i].offset); 5156 CHECK_EQ(tc[i].expected_res, res); 5157 } 5158 } 5159 } 5160 5161 5162 int32_t run_balc(int32_t offset) { 5163 Isolate* isolate = CcTest::i_isolate(); 5164 HandleScope scope(isolate); 5165 5166 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); 5167 5168 Label continue_1, stop_execution; 5169 __ push(ra); 5170 __ li(v0, 0); 5171 __ li(t8, 0); 5172 __ li(t9, 2); // A condition for stopping execution. 5173 5174 __ beq(t8, t8, &continue_1); 5175 __ nop(); 5176 5177 uint32_t instruction_addiu = 0x24420001; // addiu v0, v0, 1 5178 for (int32_t i = -117; i <= -57; ++i) { 5179 __ dd(instruction_addiu); 5180 } 5181 __ jr(ra); // -56 5182 __ nop(); // -55 5183 5184 for (int32_t i = -54; i <= -4; ++i) { 5185 __ dd(instruction_addiu); 5186 } 5187 __ jr(ra); // -3 5188 __ nop(); // -2 5189 5190 __ bind(&continue_1); 5191 __ balc(offset); // -1 5192 5193 __ pop(ra); // 0, 1 5194 __ jr(ra); // 2 5195 __ nop(); // 3 5196 5197 for (int32_t i = 4; i <= 44; ++i) { 5198 __ dd(instruction_addiu); 5199 } 5200 __ jr(ra); 5201 __ nop(); 5202 5203 CodeDesc desc; 5204 assm.GetCode(&desc); 5205 Handle<Code> code = isolate->factory()->NewCode( 5206 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 5207 5208 F2 f = FUNCTION_CAST<F2>(code->entry()); 5209 5210 int32_t res = reinterpret_cast<int32_t>( 5211 CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0)); 5212 5213 return res; 5214 } 5215 5216 5217 uint32_t run_aui(uint32_t rs, uint16_t offset) { 5218 Isolate* isolate = CcTest::i_isolate(); 5219 HandleScope scope(isolate); 5220 5221 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); 5222 5223 __ li(t0, rs); 5224 __ aui(v0, t0, offset); 5225 __ jr(ra); 5226 __ nop(); 5227 5228 CodeDesc desc; 5229 assm.GetCode(&desc); 5230 Handle<Code> code = isolate->factory()->NewCode( 5231 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 5232 5233 F2 f = FUNCTION_CAST<F2>(code->entry()); 5234 5235 uint32_t res = 5236 reinterpret_cast<uint32_t> 5237 (CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0)); 5238 5239 return res; 5240 } 5241 5242 5243 TEST(r6_aui) { 5244 if (IsMipsArchVariant(kMips32r6)) { 5245 CcTest::InitializeVM(); 5246 5247 struct TestCaseAui { 5248 uint32_t rs; 5249 uint16_t offset; 5250 uint32_t ref_res; 5251 }; 5252 5253 struct TestCaseAui tc[] = { 5254 // input, offset, result 5255 {0xfffeffff, 1, 0xffffffff}, 5256 {0xffffffff, 0, 0xffffffff}, 5257 {0, 0xffff, 0xffff0000}, 5258 {0x0008ffff, 0xfff7, 0xffffffff}, 5259 {32767, 32767, 0x7fff7fff}, 5260 // overflow cases 5261 {0xffffffff, 0x1, 0x0000ffff}, 5262 {0xffffffff, 0xffff, 0xfffeffff}, 5263 }; 5264 5265 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseAui); 5266 for (size_t i = 0; i < nr_test_cases; ++i) { 5267 PC = 0; 5268 uint32_t res = run_aui(tc[i].rs, tc[i].offset); 5269 CHECK_EQ(tc[i].ref_res, res); 5270 } 5271 } 5272 } 5273 5274 5275 TEST(r6_balc) { 5276 if (IsMipsArchVariant(kMips32r6)) { 5277 CcTest::InitializeVM(); 5278 5279 struct TestCaseBalc { 5280 int32_t offset; 5281 int32_t expected_res; 5282 }; 5283 5284 struct TestCaseBalc tc[] = { 5285 // offset, expected_result 5286 { -117, 61 }, 5287 { -54, 51 }, 5288 { 0, 0 }, 5289 { 4, 41 }, 5290 }; 5291 5292 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseBalc); 5293 for (size_t i = 0; i < nr_test_cases; ++i) { 5294 int32_t res = run_balc(tc[i].offset); 5295 CHECK_EQ(tc[i].expected_res, res); 5296 } 5297 } 5298 } 5299 5300 5301 uint32_t run_bal(int16_t offset) { 5302 Isolate* isolate = CcTest::i_isolate(); 5303 HandleScope scope(isolate); 5304 5305 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); 5306 5307 __ mov(t0, ra); 5308 __ bal(offset); // Equivalent for "BGEZAL zero_reg, offset". 5309 __ nop(); 5310 5311 __ mov(ra, t0); 5312 __ jr(ra); 5313 __ nop(); 5314 5315 __ li(v0, 1); 5316 __ jr(ra); 5317 __ nop(); 5318 5319 CodeDesc desc; 5320 assm.GetCode(&desc); 5321 Handle<Code> code = isolate->factory()->NewCode( 5322 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 5323 5324 F2 f = FUNCTION_CAST<F2>(code->entry()); 5325 5326 uint32_t res = reinterpret_cast<uint32_t>( 5327 CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0)); 5328 5329 return res; 5330 } 5331 5332 5333 TEST(bal) { 5334 CcTest::InitializeVM(); 5335 5336 struct TestCaseBal { 5337 int16_t offset; 5338 uint32_t expected_res; 5339 }; 5340 5341 struct TestCaseBal tc[] = { 5342 // offset, expected_res 5343 { 4, 1 }, 5344 }; 5345 5346 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseBal); 5347 for (size_t i = 0; i < nr_test_cases; ++i) { 5348 CHECK_EQ(tc[i].expected_res, run_bal(tc[i].offset)); 5349 } 5350 } 5351 5352 5353 static uint32_t run_lsa(uint32_t rt, uint32_t rs, int8_t sa) { 5354 Isolate* isolate = CcTest::i_isolate(); 5355 HandleScope scope(isolate); 5356 MacroAssembler assm(isolate, nullptr, 0, 5357 v8::internal::CodeObjectRequired::kYes); 5358 5359 __ lsa(v0, a0, a1, sa); 5360 __ jr(ra); 5361 __ nop(); 5362 5363 CodeDesc desc; 5364 assm.GetCode(&desc); 5365 Handle<Code> code = isolate->factory()->NewCode( 5366 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 5367 5368 F1 f = FUNCTION_CAST<F1>(code->entry()); 5369 5370 uint32_t res = reinterpret_cast<uint32_t>( 5371 CALL_GENERATED_CODE(isolate, f, rt, rs, 0, 0, 0)); 5372 5373 return res; 5374 } 5375 5376 5377 TEST(lsa) { 5378 if (!IsMipsArchVariant(kMips32r6)) return; 5379 5380 CcTest::InitializeVM(); 5381 struct TestCaseLsa { 5382 int32_t rt; 5383 int32_t rs; 5384 uint8_t sa; 5385 uint32_t expected_res; 5386 }; 5387 5388 struct TestCaseLsa tc[] = { 5389 // rt, rs, sa, expected_res 5390 {0x4, 0x1, 1, 0x6}, 5391 {0x4, 0x1, 2, 0x8}, 5392 {0x4, 0x1, 3, 0xc}, 5393 {0x4, 0x1, 4, 0x14}, 5394 {0x0, 0x1, 1, 0x2}, 5395 {0x0, 0x1, 2, 0x4}, 5396 {0x0, 0x1, 3, 0x8}, 5397 {0x0, 0x1, 4, 0x10}, 5398 {0x4, 0x0, 1, 0x4}, 5399 {0x4, 0x0, 2, 0x4}, 5400 {0x4, 0x0, 3, 0x4}, 5401 {0x4, 0x0, 4, 0x4}, 5402 {0x4, INT32_MAX, 1, 0x2}, // Shift overflow. 5403 {0x4, INT32_MAX >> 1, 2, 0x0}, // Shift overflow. 5404 {0x4, INT32_MAX >> 2, 3, 0xfffffffc}, // Shift overflow. 5405 {0x4, INT32_MAX >> 3, 4, 0xfffffff4}, // Shift overflow. 5406 {INT32_MAX - 1, 0x1, 1, 0x80000000}, // Signed adition overflow. 5407 {INT32_MAX - 3, 0x1, 2, 0x80000000}, // Signed addition overflow. 5408 {INT32_MAX - 7, 0x1, 3, 0x80000000}, // Signed addition overflow. 5409 {INT32_MAX - 15, 0x1, 4, 0x80000000}, // Signed addition overflow. 5410 {-2, 0x1, 1, 0x0}, // Addition overflow. 5411 {-4, 0x1, 2, 0x0}, // Addition overflow. 5412 {-8, 0x1, 3, 0x0}, // Addition overflow. 5413 {-16, 0x1, 4, 0x0}}; // Addition overflow. 5414 5415 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseLsa); 5416 for (size_t i = 0; i < nr_test_cases; ++i) { 5417 uint32_t res = run_lsa(tc[i].rt, tc[i].rs, tc[i].sa); 5418 PrintF("0x%x =? 0x%x == lsa(v0, %x, %x, %hhu)\n", tc[i].expected_res, res, 5419 tc[i].rt, tc[i].rs, tc[i].sa); 5420 CHECK_EQ(tc[i].expected_res, res); 5421 } 5422 } 5423 5424 5425 TEST(Trampoline) { 5426 // Private member of Assembler class. 5427 static const int kMaxBranchOffset = (1 << (18 - 1)) - 1; 5428 5429 CcTest::InitializeVM(); 5430 Isolate* isolate = CcTest::i_isolate(); 5431 HandleScope scope(isolate); 5432 5433 MacroAssembler assm(isolate, nullptr, 0, 5434 v8::internal::CodeObjectRequired::kYes); 5435 Label done; 5436 size_t nr_calls = kMaxBranchOffset / (2 * Instruction::kInstrSize) + 2; 5437 5438 for (size_t i = 0; i < nr_calls; ++i) { 5439 __ BranchShort(&done, eq, a0, Operand(a1)); 5440 } 5441 __ bind(&done); 5442 __ Ret(USE_DELAY_SLOT); 5443 __ mov(v0, zero_reg); 5444 5445 CodeDesc desc; 5446 assm.GetCode(&desc); 5447 Handle<Code> code = isolate->factory()->NewCode( 5448 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 5449 F2 f = FUNCTION_CAST<F2>(code->entry()); 5450 5451 int32_t res = reinterpret_cast<int32_t>( 5452 CALL_GENERATED_CODE(isolate, f, 42, 42, 0, 0, 0)); 5453 CHECK_EQ(res, 0); 5454 } 5455 5456 #undef __ 5457