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 // Exchange between GP anf FP registers is done through memory 388 // on FPXX compiled binaries and architectures that do not support 389 // MTHC1 and MTFC1. If this is the case, skipping this test. 390 if (IsFpxxMode() && 391 (IsMipsArchVariant(kMips32r1) || IsMipsArchVariant(kLoongson))) { 392 return; 393 } 394 395 // Test moves between floating point and integer registers. 396 CcTest::InitializeVM(); 397 Isolate* isolate = CcTest::i_isolate(); 398 HandleScope scope(isolate); 399 400 typedef struct { 401 double a; 402 double b; 403 double c; 404 } T; 405 T t; 406 407 Assembler assm(isolate, NULL, 0); 408 Label L, C; 409 410 __ ldc1(f4, MemOperand(a0, offsetof(T, a)) ); 411 __ ldc1(f6, MemOperand(a0, offsetof(T, b)) ); 412 413 // Swap f4 and f6, by using four integer registers, t0-t3. 414 if (IsFp32Mode()) { 415 __ mfc1(t0, f4); 416 __ mfc1(t1, f5); 417 __ mfc1(t2, f6); 418 __ mfc1(t3, f7); 419 420 __ mtc1(t0, f6); 421 __ mtc1(t1, f7); 422 __ mtc1(t2, f4); 423 __ mtc1(t3, f5); 424 } else { 425 CHECK(!IsMipsArchVariant(kMips32r1) && !IsMipsArchVariant(kLoongson)); 426 DCHECK(IsFp64Mode() || IsFpxxMode()); 427 __ mfc1(t0, f4); 428 __ mfhc1(t1, f4); 429 __ mfc1(t2, f6); 430 __ mfhc1(t3, f6); 431 432 __ mtc1(t0, f6); 433 __ mthc1(t1, f6); 434 __ mtc1(t2, f4); 435 __ mthc1(t3, f4); 436 } 437 438 // Store the swapped f4 and f5 back to memory. 439 __ sdc1(f4, MemOperand(a0, offsetof(T, a)) ); 440 __ sdc1(f6, MemOperand(a0, offsetof(T, c)) ); 441 442 __ jr(ra); 443 __ nop(); 444 445 CodeDesc desc; 446 assm.GetCode(&desc); 447 Handle<Code> code = isolate->factory()->NewCode( 448 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 449 F3 f = FUNCTION_CAST<F3>(code->entry()); 450 t.a = 1.5e22; 451 t.b = 2.75e11; 452 t.c = 17.17; 453 Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0); 454 USE(dummy); 455 456 CHECK_EQ(2.75e11, t.a); 457 CHECK_EQ(2.75e11, t.b); 458 CHECK_EQ(1.5e22, t.c); 459 } 460 461 462 TEST(MIPS5) { 463 // Test conversions between doubles and integers. 464 CcTest::InitializeVM(); 465 Isolate* isolate = CcTest::i_isolate(); 466 HandleScope scope(isolate); 467 468 typedef struct { 469 double a; 470 double b; 471 int i; 472 int j; 473 } T; 474 T t; 475 476 Assembler assm(isolate, NULL, 0); 477 Label L, C; 478 479 // Load all structure elements to registers. 480 __ ldc1(f4, MemOperand(a0, offsetof(T, a)) ); 481 __ ldc1(f6, MemOperand(a0, offsetof(T, b)) ); 482 __ lw(t0, MemOperand(a0, offsetof(T, i)) ); 483 __ lw(t1, MemOperand(a0, offsetof(T, j)) ); 484 485 // Convert double in f4 to int in element i. 486 __ cvt_w_d(f8, f4); 487 __ mfc1(t2, f8); 488 __ sw(t2, MemOperand(a0, offsetof(T, i)) ); 489 490 // Convert double in f6 to int in element j. 491 __ cvt_w_d(f10, f6); 492 __ mfc1(t3, f10); 493 __ sw(t3, MemOperand(a0, offsetof(T, j)) ); 494 495 // Convert int in original i (t0) to double in a. 496 __ mtc1(t0, f12); 497 __ cvt_d_w(f0, f12); 498 __ sdc1(f0, MemOperand(a0, offsetof(T, a)) ); 499 500 // Convert int in original j (t1) to double in b. 501 __ mtc1(t1, f14); 502 __ cvt_d_w(f2, f14); 503 __ sdc1(f2, MemOperand(a0, offsetof(T, b)) ); 504 505 __ jr(ra); 506 __ nop(); 507 508 CodeDesc desc; 509 assm.GetCode(&desc); 510 Handle<Code> code = isolate->factory()->NewCode( 511 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 512 F3 f = FUNCTION_CAST<F3>(code->entry()); 513 t.a = 1.5e4; 514 t.b = 2.75e8; 515 t.i = 12345678; 516 t.j = -100000; 517 Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0); 518 USE(dummy); 519 520 CHECK_EQ(12345678.0, t.a); 521 CHECK_EQ(-100000.0, t.b); 522 CHECK_EQ(15000, t.i); 523 CHECK_EQ(275000000, t.j); 524 } 525 526 527 TEST(MIPS6) { 528 // Test simple memory loads and stores. 529 CcTest::InitializeVM(); 530 Isolate* isolate = CcTest::i_isolate(); 531 HandleScope scope(isolate); 532 533 typedef struct { 534 uint32_t ui; 535 int32_t si; 536 int32_t r1; 537 int32_t r2; 538 int32_t r3; 539 int32_t r4; 540 int32_t r5; 541 int32_t r6; 542 } T; 543 T t; 544 545 Assembler assm(isolate, NULL, 0); 546 Label L, C; 547 548 // Basic word load/store. 549 __ lw(t0, MemOperand(a0, offsetof(T, ui)) ); 550 __ sw(t0, MemOperand(a0, offsetof(T, r1)) ); 551 552 // lh with positive data. 553 __ lh(t1, MemOperand(a0, offsetof(T, ui)) ); 554 __ sw(t1, MemOperand(a0, offsetof(T, r2)) ); 555 556 // lh with negative data. 557 __ lh(t2, MemOperand(a0, offsetof(T, si)) ); 558 __ sw(t2, MemOperand(a0, offsetof(T, r3)) ); 559 560 // lhu with negative data. 561 __ lhu(t3, MemOperand(a0, offsetof(T, si)) ); 562 __ sw(t3, MemOperand(a0, offsetof(T, r4)) ); 563 564 // lb with negative data. 565 __ lb(t4, MemOperand(a0, offsetof(T, si)) ); 566 __ sw(t4, MemOperand(a0, offsetof(T, r5)) ); 567 568 // sh writes only 1/2 of word. 569 __ lui(t5, 0x3333); 570 __ ori(t5, t5, 0x3333); 571 __ sw(t5, MemOperand(a0, offsetof(T, r6)) ); 572 __ lhu(t5, MemOperand(a0, offsetof(T, si)) ); 573 __ sh(t5, MemOperand(a0, offsetof(T, r6)) ); 574 575 __ jr(ra); 576 __ nop(); 577 578 CodeDesc desc; 579 assm.GetCode(&desc); 580 Handle<Code> code = isolate->factory()->NewCode( 581 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 582 F3 f = FUNCTION_CAST<F3>(code->entry()); 583 t.ui = 0x11223344; 584 t.si = 0x99aabbcc; 585 Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0); 586 USE(dummy); 587 588 CHECK_EQ(static_cast<int32_t>(0x11223344), t.r1); 589 #if __BYTE_ORDER == __LITTLE_ENDIAN 590 CHECK_EQ(static_cast<int32_t>(0x3344), t.r2); 591 CHECK_EQ(static_cast<int32_t>(0xffffbbcc), t.r3); 592 CHECK_EQ(static_cast<int32_t>(0x0000bbcc), t.r4); 593 CHECK_EQ(static_cast<int32_t>(0xffffffcc), t.r5); 594 CHECK_EQ(static_cast<int32_t>(0x3333bbcc), t.r6); 595 #elif __BYTE_ORDER == __BIG_ENDIAN 596 CHECK_EQ(static_cast<int32_t>(0x1122), t.r2); 597 CHECK_EQ(static_cast<int32_t>(0xffff99aa), t.r3); 598 CHECK_EQ(static_cast<int32_t>(0x000099aa), t.r4); 599 CHECK_EQ(static_cast<int32_t>(0xffffff99), t.r5); 600 CHECK_EQ(static_cast<int32_t>(0x99aa3333), t.r6); 601 #else 602 #error Unknown endianness 603 #endif 604 } 605 606 607 TEST(MIPS7) { 608 // Test floating point compare and branch instructions. 609 CcTest::InitializeVM(); 610 Isolate* isolate = CcTest::i_isolate(); 611 HandleScope scope(isolate); 612 613 typedef struct { 614 double a; 615 double b; 616 double c; 617 double d; 618 double e; 619 double f; 620 int32_t result; 621 } T; 622 T t; 623 624 // Create a function that accepts &t, and loads, manipulates, and stores 625 // the doubles t.a ... t.f. 626 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); 627 Label neither_is_nan, less_than, outa_here; 628 629 __ ldc1(f4, MemOperand(a0, offsetof(T, a)) ); 630 __ ldc1(f6, MemOperand(a0, offsetof(T, b)) ); 631 if (!IsMipsArchVariant(kMips32r6)) { 632 __ c(UN, D, f4, f6); 633 __ bc1f(&neither_is_nan); 634 } else { 635 __ cmp(UN, L, f2, f4, f6); 636 __ bc1eqz(&neither_is_nan, f2); 637 } 638 __ nop(); 639 __ sw(zero_reg, MemOperand(a0, offsetof(T, result)) ); 640 __ Branch(&outa_here); 641 642 __ bind(&neither_is_nan); 643 644 if (IsMipsArchVariant(kLoongson)) { 645 __ c(OLT, D, f6, f4); 646 __ bc1t(&less_than); 647 } else if (IsMipsArchVariant(kMips32r6)) { 648 __ cmp(OLT, L, f2, f6, f4); 649 __ bc1nez(&less_than, f2); 650 } else { 651 __ c(OLT, D, f6, f4, 2); 652 __ bc1t(&less_than, 2); 653 } 654 655 __ nop(); 656 __ sw(zero_reg, MemOperand(a0, offsetof(T, result)) ); 657 __ Branch(&outa_here); 658 659 __ bind(&less_than); 660 __ Addu(t0, zero_reg, Operand(1)); 661 __ sw(t0, MemOperand(a0, offsetof(T, result)) ); // Set true. 662 663 664 // This test-case should have additional tests. 665 666 __ bind(&outa_here); 667 668 __ jr(ra); 669 __ nop(); 670 671 CodeDesc desc; 672 assm.GetCode(&desc); 673 Handle<Code> code = isolate->factory()->NewCode( 674 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 675 F3 f = FUNCTION_CAST<F3>(code->entry()); 676 t.a = 1.5e14; 677 t.b = 2.75e11; 678 t.c = 2.0; 679 t.d = -4.0; 680 t.e = 0.0; 681 t.f = 0.0; 682 t.result = 0; 683 Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0); 684 USE(dummy); 685 CHECK_EQ(1.5e14, t.a); 686 CHECK_EQ(2.75e11, t.b); 687 CHECK_EQ(1, t.result); 688 } 689 690 691 TEST(MIPS8) { 692 // Test ROTR and ROTRV instructions. 693 if (IsMipsArchVariant(kMips32r2)) { 694 CcTest::InitializeVM(); 695 Isolate* isolate = CcTest::i_isolate(); 696 HandleScope scope(isolate); 697 698 typedef struct { 699 int32_t input; 700 int32_t result_rotr_4; 701 int32_t result_rotr_8; 702 int32_t result_rotr_12; 703 int32_t result_rotr_16; 704 int32_t result_rotr_20; 705 int32_t result_rotr_24; 706 int32_t result_rotr_28; 707 int32_t result_rotrv_4; 708 int32_t result_rotrv_8; 709 int32_t result_rotrv_12; 710 int32_t result_rotrv_16; 711 int32_t result_rotrv_20; 712 int32_t result_rotrv_24; 713 int32_t result_rotrv_28; 714 } T; 715 T t; 716 717 MacroAssembler assm(isolate, NULL, 0, 718 v8::internal::CodeObjectRequired::kYes); 719 720 // Basic word load. 721 __ lw(t0, MemOperand(a0, offsetof(T, input)) ); 722 723 // ROTR instruction (called through the Ror macro). 724 __ Ror(t1, t0, 0x0004); 725 __ Ror(t2, t0, 0x0008); 726 __ Ror(t3, t0, 0x000c); 727 __ Ror(t4, t0, 0x0010); 728 __ Ror(t5, t0, 0x0014); 729 __ Ror(t6, t0, 0x0018); 730 __ Ror(t7, t0, 0x001c); 731 732 // Basic word store. 733 __ sw(t1, MemOperand(a0, offsetof(T, result_rotr_4)) ); 734 __ sw(t2, MemOperand(a0, offsetof(T, result_rotr_8)) ); 735 __ sw(t3, MemOperand(a0, offsetof(T, result_rotr_12)) ); 736 __ sw(t4, MemOperand(a0, offsetof(T, result_rotr_16)) ); 737 __ sw(t5, MemOperand(a0, offsetof(T, result_rotr_20)) ); 738 __ sw(t6, MemOperand(a0, offsetof(T, result_rotr_24)) ); 739 __ sw(t7, MemOperand(a0, offsetof(T, result_rotr_28)) ); 740 741 // ROTRV instruction (called through the Ror macro). 742 __ li(t7, 0x0004); 743 __ Ror(t1, t0, t7); 744 __ li(t7, 0x0008); 745 __ Ror(t2, t0, t7); 746 __ li(t7, 0x000C); 747 __ Ror(t3, t0, t7); 748 __ li(t7, 0x0010); 749 __ Ror(t4, t0, t7); 750 __ li(t7, 0x0014); 751 __ Ror(t5, t0, t7); 752 __ li(t7, 0x0018); 753 __ Ror(t6, t0, t7); 754 __ li(t7, 0x001C); 755 __ Ror(t7, t0, t7); 756 757 // Basic word store. 758 __ sw(t1, MemOperand(a0, offsetof(T, result_rotrv_4)) ); 759 __ sw(t2, MemOperand(a0, offsetof(T, result_rotrv_8)) ); 760 __ sw(t3, MemOperand(a0, offsetof(T, result_rotrv_12)) ); 761 __ sw(t4, MemOperand(a0, offsetof(T, result_rotrv_16)) ); 762 __ sw(t5, MemOperand(a0, offsetof(T, result_rotrv_20)) ); 763 __ sw(t6, MemOperand(a0, offsetof(T, result_rotrv_24)) ); 764 __ sw(t7, MemOperand(a0, offsetof(T, result_rotrv_28)) ); 765 766 __ jr(ra); 767 __ nop(); 768 769 CodeDesc desc; 770 assm.GetCode(&desc); 771 Handle<Code> code = isolate->factory()->NewCode( 772 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 773 F3 f = FUNCTION_CAST<F3>(code->entry()); 774 t.input = 0x12345678; 775 Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0x0, 0, 0, 0); 776 USE(dummy); 777 CHECK_EQ(static_cast<int32_t>(0x81234567), t.result_rotr_4); 778 CHECK_EQ(static_cast<int32_t>(0x78123456), t.result_rotr_8); 779 CHECK_EQ(static_cast<int32_t>(0x67812345), t.result_rotr_12); 780 CHECK_EQ(static_cast<int32_t>(0x56781234), t.result_rotr_16); 781 CHECK_EQ(static_cast<int32_t>(0x45678123), t.result_rotr_20); 782 CHECK_EQ(static_cast<int32_t>(0x34567812), t.result_rotr_24); 783 CHECK_EQ(static_cast<int32_t>(0x23456781), t.result_rotr_28); 784 785 CHECK_EQ(static_cast<int32_t>(0x81234567), t.result_rotrv_4); 786 CHECK_EQ(static_cast<int32_t>(0x78123456), t.result_rotrv_8); 787 CHECK_EQ(static_cast<int32_t>(0x67812345), t.result_rotrv_12); 788 CHECK_EQ(static_cast<int32_t>(0x56781234), t.result_rotrv_16); 789 CHECK_EQ(static_cast<int32_t>(0x45678123), t.result_rotrv_20); 790 CHECK_EQ(static_cast<int32_t>(0x34567812), t.result_rotrv_24); 791 CHECK_EQ(static_cast<int32_t>(0x23456781), t.result_rotrv_28); 792 } 793 } 794 795 796 TEST(MIPS9) { 797 // Test BRANCH improvements. 798 CcTest::InitializeVM(); 799 Isolate* isolate = CcTest::i_isolate(); 800 HandleScope scope(isolate); 801 802 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); 803 Label exit, exit2, exit3; 804 805 __ Branch(&exit, ge, a0, Operand(zero_reg)); 806 __ Branch(&exit2, ge, a0, Operand(0x00001FFF)); 807 __ Branch(&exit3, ge, a0, Operand(0x0001FFFF)); 808 809 __ bind(&exit); 810 __ bind(&exit2); 811 __ bind(&exit3); 812 __ jr(ra); 813 __ nop(); 814 815 CodeDesc desc; 816 assm.GetCode(&desc); 817 isolate->factory()->NewCode( 818 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 819 } 820 821 822 TEST(MIPS10) { 823 // Test conversions between doubles and words. 824 CcTest::InitializeVM(); 825 Isolate* isolate = CcTest::i_isolate(); 826 HandleScope scope(isolate); 827 828 typedef struct { 829 double a; 830 double b; 831 int32_t dbl_mant; 832 int32_t dbl_exp; 833 int32_t word; 834 int32_t b_word; 835 } T; 836 T t; 837 838 Assembler assm(isolate, NULL, 0); 839 Label L, C; 840 841 if (IsMipsArchVariant(kMips32r1) || IsMipsArchVariant(kLoongson)) return; 842 843 // Load all structure elements to registers. 844 // (f0, f1) = a (fp32), f0 = a (fp64) 845 __ ldc1(f0, MemOperand(a0, offsetof(T, a))); 846 847 __ mfc1(t0, f0); // t0 = f0(31..0) 848 __ mfhc1(t1, f0); // t1 = sign_extend(f0(63..32)) 849 __ sw(t0, MemOperand(a0, offsetof(T, dbl_mant))); // dbl_mant = t0 850 __ sw(t1, MemOperand(a0, offsetof(T, dbl_exp))); // dbl_exp = t1 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, nullptr, 0, 1460 v8::internal::CodeObjectRequired::kYes); 1461 1462 struct TestFloat { 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 }; 1472 1473 TestFloat test; 1474 const double dnan = std::numeric_limits<double>::quiet_NaN(); 1475 const double dinf = std::numeric_limits<double>::infinity(); 1476 const double dminf = -std::numeric_limits<double>::infinity(); 1477 const float fnan = std::numeric_limits<float>::quiet_NaN(); 1478 const float finf = std::numeric_limits<float>::infinity(); 1479 const float fminf = std::numeric_limits<float>::infinity(); 1480 const int kTableLength = 13; 1481 double inputsa[kTableLength] = {2.0, 3.0, dnan, 3.0, -0.0, 0.0, dinf, 1482 dnan, 42.0, dinf, dminf, dinf, dnan}; 1483 double inputsb[kTableLength] = {3.0, 2.0, 3.0, dnan, 0.0, -0.0, dnan, 1484 dinf, dinf, 42.0, dinf, dminf, dnan}; 1485 double outputsdmin[kTableLength] = {2.0, 2.0, 3.0, 3.0, -0.0, 1486 -0.0, dinf, dinf, 42.0, 42.0, 1487 dminf, dminf, dnan}; 1488 double outputsdmax[kTableLength] = {3.0, 3.0, 3.0, 3.0, 0.0, 0.0, dinf, 1489 dinf, dinf, dinf, dinf, dinf, dnan}; 1490 1491 float inputse[kTableLength] = {2.0, 3.0, fnan, 3.0, -0.0, 0.0, finf, 1492 fnan, 42.0, finf, fminf, finf, fnan}; 1493 float inputsf[kTableLength] = {3.0, 2.0, 3.0, fnan, 0.0, -0.0, fnan, 1494 finf, finf, 42.0, finf, fminf, fnan}; 1495 float outputsfmin[kTableLength] = {2.0, 2.0, 3.0, 3.0, -0.0, 1496 -0.0, finf, finf, 42.0, 42.0, 1497 fminf, fminf, fnan}; 1498 float outputsfmax[kTableLength] = {3.0, 3.0, 3.0, 3.0, 0.0, 0.0, finf, 1499 finf, finf, finf, finf, finf, fnan}; 1500 1501 __ ldc1(f4, MemOperand(a0, offsetof(TestFloat, a))); 1502 __ ldc1(f8, MemOperand(a0, offsetof(TestFloat, b))); 1503 __ lwc1(f2, MemOperand(a0, offsetof(TestFloat, e))); 1504 __ lwc1(f6, MemOperand(a0, offsetof(TestFloat, f))); 1505 __ min_d(f10, f4, f8); 1506 __ max_d(f12, f4, f8); 1507 __ min_s(f14, f2, f6); 1508 __ max_s(f16, f2, f6); 1509 __ sdc1(f10, MemOperand(a0, offsetof(TestFloat, c))); 1510 __ sdc1(f12, MemOperand(a0, offsetof(TestFloat, d))); 1511 __ swc1(f14, MemOperand(a0, offsetof(TestFloat, g))); 1512 __ swc1(f16, MemOperand(a0, offsetof(TestFloat, h))); 1513 __ jr(ra); 1514 __ nop(); 1515 1516 CodeDesc desc; 1517 assm.GetCode(&desc); 1518 Handle<Code> code = isolate->factory()->NewCode( 1519 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 1520 F3 f = FUNCTION_CAST<F3>(code->entry()); 1521 for (int i = 0; i < kTableLength; i++) { 1522 test.a = inputsa[i]; 1523 test.b = inputsb[i]; 1524 test.e = inputse[i]; 1525 test.f = inputsf[i]; 1526 1527 CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0); 1528 1529 CHECK_EQ(0, memcmp(&test.c, &outputsdmin[i], sizeof(test.c))); 1530 CHECK_EQ(0, memcmp(&test.d, &outputsdmax[i], sizeof(test.d))); 1531 CHECK_EQ(0, memcmp(&test.g, &outputsfmin[i], sizeof(test.g))); 1532 CHECK_EQ(0, memcmp(&test.h, &outputsfmax[i], sizeof(test.h))); 1533 } 1534 } 1535 } 1536 1537 1538 TEST(rint_d) { 1539 if (IsMipsArchVariant(kMips32r6)) { 1540 const int kTableLength = 30; 1541 CcTest::InitializeVM(); 1542 Isolate* isolate = CcTest::i_isolate(); 1543 HandleScope scope(isolate); 1544 MacroAssembler assm(isolate, NULL, 0, 1545 v8::internal::CodeObjectRequired::kYes); 1546 1547 typedef struct test_float { 1548 double a; 1549 double b; 1550 int fcsr; 1551 }TestFloat; 1552 1553 TestFloat test; 1554 double inputs[kTableLength] = {18446744073709551617.0, 1555 4503599627370496.0, -4503599627370496.0, 1556 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E147, 1557 1.7976931348623157E+308, 6.27463370218383111104242366943E-307, 1558 309485009821345068724781056.89, 1559 2.1, 2.6, 2.5, 3.1, 3.6, 3.5, 1560 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5, 1561 37778931862957161709568.0, 37778931862957161709569.0, 1562 37778931862957161709580.0, 37778931862957161709581.0, 1563 37778931862957161709582.0, 37778931862957161709583.0, 1564 37778931862957161709584.0, 37778931862957161709585.0, 1565 37778931862957161709586.0, 37778931862957161709587.0}; 1566 double outputs_RN[kTableLength] = {18446744073709551617.0, 1567 4503599627370496.0, -4503599627370496.0, 1568 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E147, 1569 1.7976931348623157E308, 0, 1570 309485009821345068724781057.0, 1571 2.0, 3.0, 2.0, 3.0, 4.0, 4.0, 1572 -2.0, -3.0, -2.0, -3.0, -4.0, -4.0, 1573 37778931862957161709568.0, 37778931862957161709569.0, 1574 37778931862957161709580.0, 37778931862957161709581.0, 1575 37778931862957161709582.0, 37778931862957161709583.0, 1576 37778931862957161709584.0, 37778931862957161709585.0, 1577 37778931862957161709586.0, 37778931862957161709587.0}; 1578 double outputs_RZ[kTableLength] = {18446744073709551617.0, 1579 4503599627370496.0, -4503599627370496.0, 1580 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E147, 1581 1.7976931348623157E308, 0, 1582 309485009821345068724781057.0, 1583 2.0, 2.0, 2.0, 3.0, 3.0, 3.0, 1584 -2.0, -2.0, -2.0, -3.0, -3.0, -3.0, 1585 37778931862957161709568.0, 37778931862957161709569.0, 1586 37778931862957161709580.0, 37778931862957161709581.0, 1587 37778931862957161709582.0, 37778931862957161709583.0, 1588 37778931862957161709584.0, 37778931862957161709585.0, 1589 37778931862957161709586.0, 37778931862957161709587.0}; 1590 double outputs_RP[kTableLength] = {18446744073709551617.0, 1591 4503599627370496.0, -4503599627370496.0, 1592 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E147, 1593 1.7976931348623157E308, 1, 1594 309485009821345068724781057.0, 1595 3.0, 3.0, 3.0, 4.0, 4.0, 4.0, 1596 -2.0, -2.0, -2.0, -3.0, -3.0, -3.0, 1597 37778931862957161709568.0, 37778931862957161709569.0, 1598 37778931862957161709580.0, 37778931862957161709581.0, 1599 37778931862957161709582.0, 37778931862957161709583.0, 1600 37778931862957161709584.0, 37778931862957161709585.0, 1601 37778931862957161709586.0, 37778931862957161709587.0}; 1602 double outputs_RM[kTableLength] = {18446744073709551617.0, 1603 4503599627370496.0, -4503599627370496.0, 1604 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E147, 1605 1.7976931348623157E308, 0, 1606 309485009821345068724781057.0, 1607 2.0, 2.0, 2.0, 3.0, 3.0, 3.0, 1608 -3.0, -3.0, -3.0, -4.0, -4.0, -4.0, 1609 37778931862957161709568.0, 37778931862957161709569.0, 1610 37778931862957161709580.0, 37778931862957161709581.0, 1611 37778931862957161709582.0, 37778931862957161709583.0, 1612 37778931862957161709584.0, 37778931862957161709585.0, 1613 37778931862957161709586.0, 37778931862957161709587.0}; 1614 int fcsr_inputs[4] = 1615 {kRoundToNearest, kRoundToZero, kRoundToPlusInf, kRoundToMinusInf}; 1616 double* outputs[4] = {outputs_RN, outputs_RZ, outputs_RP, outputs_RM}; 1617 __ ldc1(f4, MemOperand(a0, offsetof(TestFloat, a)) ); 1618 __ lw(t0, MemOperand(a0, offsetof(TestFloat, fcsr)) ); 1619 __ cfc1(t1, FCSR); 1620 __ ctc1(t0, FCSR); 1621 __ rint_d(f8, f4); 1622 __ sdc1(f8, MemOperand(a0, offsetof(TestFloat, b)) ); 1623 __ ctc1(t1, FCSR); 1624 __ jr(ra); 1625 __ nop(); 1626 1627 CodeDesc desc; 1628 assm.GetCode(&desc); 1629 Handle<Code> code = isolate->factory()->NewCode( 1630 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 1631 F3 f = FUNCTION_CAST<F3>(code->entry()); 1632 1633 for (int j = 0; j < 4; j++) { 1634 test.fcsr = fcsr_inputs[j]; 1635 for (int i = 0; i < kTableLength; i++) { 1636 test.a = inputs[i]; 1637 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 1638 CHECK_EQ(test.b, outputs[j][i]); 1639 } 1640 } 1641 } 1642 } 1643 1644 1645 TEST(sel) { 1646 if (IsMipsArchVariant(kMips32r6)) { 1647 CcTest::InitializeVM(); 1648 Isolate* isolate = CcTest::i_isolate(); 1649 HandleScope scope(isolate); 1650 MacroAssembler assm(isolate, NULL, 0, 1651 v8::internal::CodeObjectRequired::kYes); 1652 1653 typedef struct test { 1654 double dd; 1655 double ds; 1656 double dt; 1657 float fd; 1658 float fs; 1659 float ft; 1660 } Test; 1661 1662 Test test; 1663 __ ldc1(f0, MemOperand(a0, offsetof(Test, dd)) ); // test 1664 __ ldc1(f2, MemOperand(a0, offsetof(Test, ds)) ); // src1 1665 __ ldc1(f4, MemOperand(a0, offsetof(Test, dt)) ); // src2 1666 __ lwc1(f6, MemOperand(a0, offsetof(Test, fd)) ); // test 1667 __ lwc1(f8, MemOperand(a0, offsetof(Test, fs)) ); // src1 1668 __ lwc1(f10, MemOperand(a0, offsetof(Test, ft)) ); // src2 1669 __ sel_d(f0, f2, f4); 1670 __ sel_s(f6, f8, f10); 1671 __ sdc1(f0, MemOperand(a0, offsetof(Test, dd)) ); 1672 __ swc1(f6, MemOperand(a0, offsetof(Test, fd)) ); 1673 __ jr(ra); 1674 __ nop(); 1675 CodeDesc desc; 1676 assm.GetCode(&desc); 1677 Handle<Code> code = isolate->factory()->NewCode( 1678 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 1679 F3 f = FUNCTION_CAST<F3>(code->entry()); 1680 1681 const int test_size = 3; 1682 const int input_size = 5; 1683 1684 double inputs_dt[input_size] = {0.0, 65.2, -70.32, 1685 18446744073709551621.0, -18446744073709551621.0}; 1686 double inputs_ds[input_size] = {0.1, 69.88, -91.325, 1687 18446744073709551625.0, -18446744073709551625.0}; 1688 float inputs_ft[input_size] = {0.0, 65.2, -70.32, 1689 18446744073709551621.0, -18446744073709551621.0}; 1690 float inputs_fs[input_size] = {0.1, 69.88, -91.325, 1691 18446744073709551625.0, -18446744073709551625.0}; 1692 double tests_D[test_size*2] = {2.8, 2.9, -2.8, -2.9, 1693 18446744073709551616.0, 18446744073709555712.0}; 1694 float tests_S[test_size*2] = {2.9, 2.8, -2.9, -2.8, 1695 18446744073709551616.0, 18446746272732807168.0}; 1696 for (int j=0; j < test_size; j+=2) { 1697 for (int i=0; i < input_size; i++) { 1698 test.dt = inputs_dt[i]; 1699 test.dd = tests_D[j]; 1700 test.ds = inputs_ds[i]; 1701 test.ft = inputs_ft[i]; 1702 test.fd = tests_S[j]; 1703 test.fs = inputs_fs[i]; 1704 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 1705 CHECK_EQ(test.dd, inputs_ds[i]); 1706 CHECK_EQ(test.fd, inputs_fs[i]); 1707 1708 test.dd = tests_D[j+1]; 1709 test.fd = tests_S[j+1]; 1710 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 1711 CHECK_EQ(test.dd, inputs_dt[i]); 1712 CHECK_EQ(test.fd, inputs_ft[i]); 1713 } 1714 } 1715 } 1716 } 1717 1718 1719 TEST(rint_s) { 1720 if (IsMipsArchVariant(kMips32r6)) { 1721 const int kTableLength = 30; 1722 CcTest::InitializeVM(); 1723 Isolate* isolate = CcTest::i_isolate(); 1724 HandleScope scope(isolate); 1725 MacroAssembler assm(isolate, NULL, 0, 1726 v8::internal::CodeObjectRequired::kYes); 1727 1728 typedef struct test_float { 1729 float a; 1730 float b; 1731 int fcsr; 1732 }TestFloat; 1733 1734 TestFloat test; 1735 float inputs[kTableLength] = {18446744073709551617.0, 1736 4503599627370496.0, -4503599627370496.0, 1737 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E37, 1738 1.7976931348623157E+38, 6.27463370218383111104242366943E-37, 1739 309485009821345068724781056.89, 1740 2.1, 2.6, 2.5, 3.1, 3.6, 3.5, 1741 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5, 1742 37778931862957161709568.0, 37778931862957161709569.0, 1743 37778931862957161709580.0, 37778931862957161709581.0, 1744 37778931862957161709582.0, 37778931862957161709583.0, 1745 37778931862957161709584.0, 37778931862957161709585.0, 1746 37778931862957161709586.0, 37778931862957161709587.0}; 1747 float outputs_RN[kTableLength] = {18446744073709551617.0, 1748 4503599627370496.0, -4503599627370496.0, 1749 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E37, 1750 1.7976931348623157E38, 0, 1751 309485009821345068724781057.0, 1752 2.0, 3.0, 2.0, 3.0, 4.0, 4.0, 1753 -2.0, -3.0, -2.0, -3.0, -4.0, -4.0, 1754 37778931862957161709568.0, 37778931862957161709569.0, 1755 37778931862957161709580.0, 37778931862957161709581.0, 1756 37778931862957161709582.0, 37778931862957161709583.0, 1757 37778931862957161709584.0, 37778931862957161709585.0, 1758 37778931862957161709586.0, 37778931862957161709587.0}; 1759 float outputs_RZ[kTableLength] = {18446744073709551617.0, 1760 4503599627370496.0, -4503599627370496.0, 1761 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E37, 1762 1.7976931348623157E38, 0, 1763 309485009821345068724781057.0, 1764 2.0, 2.0, 2.0, 3.0, 3.0, 3.0, 1765 -2.0, -2.0, -2.0, -3.0, -3.0, -3.0, 1766 37778931862957161709568.0, 37778931862957161709569.0, 1767 37778931862957161709580.0, 37778931862957161709581.0, 1768 37778931862957161709582.0, 37778931862957161709583.0, 1769 37778931862957161709584.0, 37778931862957161709585.0, 1770 37778931862957161709586.0, 37778931862957161709587.0}; 1771 float outputs_RP[kTableLength] = {18446744073709551617.0, 1772 4503599627370496.0, -4503599627370496.0, 1773 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E37, 1774 1.7976931348623157E38, 1, 1775 309485009821345068724781057.0, 1776 3.0, 3.0, 3.0, 4.0, 4.0, 4.0, 1777 -2.0, -2.0, -2.0, -3.0, -3.0, -3.0, 1778 37778931862957161709568.0, 37778931862957161709569.0, 1779 37778931862957161709580.0, 37778931862957161709581.0, 1780 37778931862957161709582.0, 37778931862957161709583.0, 1781 37778931862957161709584.0, 37778931862957161709585.0, 1782 37778931862957161709586.0, 37778931862957161709587.0}; 1783 float outputs_RM[kTableLength] = {18446744073709551617.0, 1784 4503599627370496.0, -4503599627370496.0, 1785 1.26782468584154733584017312973E30, 1.44860108245951772690707170478E37, 1786 1.7976931348623157E38, 0, 1787 309485009821345068724781057.0, 1788 2.0, 2.0, 2.0, 3.0, 3.0, 3.0, 1789 -3.0, -3.0, -3.0, -4.0, -4.0, -4.0, 1790 37778931862957161709568.0, 37778931862957161709569.0, 1791 37778931862957161709580.0, 37778931862957161709581.0, 1792 37778931862957161709582.0, 37778931862957161709583.0, 1793 37778931862957161709584.0, 37778931862957161709585.0, 1794 37778931862957161709586.0, 37778931862957161709587.0}; 1795 int fcsr_inputs[4] = 1796 {kRoundToNearest, kRoundToZero, kRoundToPlusInf, kRoundToMinusInf}; 1797 float* outputs[4] = {outputs_RN, outputs_RZ, outputs_RP, outputs_RM}; 1798 __ lwc1(f4, MemOperand(a0, offsetof(TestFloat, a)) ); 1799 __ lw(t0, MemOperand(a0, offsetof(TestFloat, fcsr)) ); 1800 __ cfc1(t1, FCSR); 1801 __ ctc1(t0, FCSR); 1802 __ rint_s(f8, f4); 1803 __ swc1(f8, MemOperand(a0, offsetof(TestFloat, b)) ); 1804 __ ctc1(t1, FCSR); 1805 __ jr(ra); 1806 __ nop(); 1807 1808 CodeDesc desc; 1809 assm.GetCode(&desc); 1810 Handle<Code> code = isolate->factory()->NewCode( 1811 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 1812 F3 f = FUNCTION_CAST<F3>(code->entry()); 1813 1814 for (int j = 0; j < 4; j++) { 1815 test.fcsr = fcsr_inputs[j]; 1816 for (int i = 0; i < kTableLength; i++) { 1817 test.a = inputs[i]; 1818 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 1819 CHECK_EQ(test.b, outputs[j][i]); 1820 } 1821 } 1822 } 1823 } 1824 1825 1826 TEST(Cvt_d_uw) { 1827 CcTest::InitializeVM(); 1828 Isolate* isolate = CcTest::i_isolate(); 1829 HandleScope scope(isolate); 1830 MacroAssembler assm(isolate, NULL, 0, 1831 v8::internal::CodeObjectRequired::kYes); 1832 1833 typedef struct test_struct { 1834 unsigned input; 1835 uint64_t output; 1836 } TestStruct; 1837 1838 unsigned inputs[] = { 1839 0x0, 0xffffffff, 0x80000000, 0x7fffffff 1840 }; 1841 1842 uint64_t outputs[] = { 1843 0x0, 0x41efffffffe00000, 1844 0x41e0000000000000, 0x41dfffffffc00000 1845 }; 1846 1847 int kTableLength = sizeof(inputs)/sizeof(inputs[0]); 1848 1849 TestStruct test; 1850 1851 __ lw(t1, MemOperand(a0, offsetof(TestStruct, input))); 1852 __ Cvt_d_uw(f4, t1, f6); 1853 __ sdc1(f4, MemOperand(a0, offsetof(TestStruct, output))); 1854 __ jr(ra); 1855 __ nop(); 1856 1857 CodeDesc desc; 1858 assm.GetCode(&desc); 1859 Handle<Code> code = isolate->factory()->NewCode( 1860 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 1861 F3 f = FUNCTION_CAST<F3>(code->entry()); 1862 for (int i = 0; i < kTableLength; i++) { 1863 test.input = inputs[i]; 1864 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 1865 // Check outputs 1866 CHECK_EQ(test.output, outputs[i]); 1867 } 1868 } 1869 1870 1871 TEST(mina_maxa) { 1872 if (IsMipsArchVariant(kMips32r6)) { 1873 const int kTableLength = 23; 1874 CcTest::InitializeVM(); 1875 Isolate* isolate = CcTest::i_isolate(); 1876 HandleScope scope(isolate); 1877 MacroAssembler assm(isolate, nullptr, 0, 1878 v8::internal::CodeObjectRequired::kYes); 1879 const double dnan = std::numeric_limits<double>::quiet_NaN(); 1880 const double dinf = std::numeric_limits<double>::infinity(); 1881 const double dminf = -std::numeric_limits<double>::infinity(); 1882 const float fnan = std::numeric_limits<float>::quiet_NaN(); 1883 const float finf = std::numeric_limits<float>::infinity(); 1884 const float fminf = std::numeric_limits<float>::infinity(); 1885 1886 struct TestFloat { 1887 double a; 1888 double b; 1889 double resd; 1890 double resd1; 1891 float c; 1892 float d; 1893 float resf; 1894 float resf1; 1895 }; 1896 1897 TestFloat test; 1898 double inputsa[kTableLength] = { 1899 5.3, 4.8, 6.1, 9.8, 9.8, 9.8, -10.0, -8.9, -9.8, -10.0, -8.9, -9.8, 1900 dnan, 3.0, -0.0, 0.0, dinf, dnan, 42.0, dinf, dminf, dinf, dnan}; 1901 double inputsb[kTableLength] = { 1902 4.8, 5.3, 6.1, -10.0, -8.9, -9.8, 9.8, 9.8, 9.8, -9.8, -11.2, -9.8, 1903 3.0, dnan, 0.0, -0.0, dnan, dinf, dinf, 42.0, dinf, dminf, dnan}; 1904 double resd[kTableLength] = { 1905 4.8, 4.8, 6.1, 9.8, -8.9, -9.8, 9.8, -8.9, -9.8, -9.8, -8.9, -9.8, 1906 3.0, 3.0, -0.0, -0.0, dinf, dinf, 42.0, 42.0, dminf, dminf, dnan}; 1907 double resd1[kTableLength] = { 1908 5.3, 5.3, 6.1, -10.0, 9.8, 9.8, -10.0, 9.8, 9.8, -10.0, -11.2, -9.8, 1909 3.0, 3.0, 0.0, 0.0, dinf, dinf, dinf, dinf, dinf, dinf, dnan}; 1910 float inputsc[kTableLength] = { 1911 5.3, 4.8, 6.1, 9.8, 9.8, 9.8, -10.0, -8.9, -9.8, -10.0, -8.9, -9.8, 1912 fnan, 3.0, -0.0, 0.0, finf, fnan, 42.0, finf, fminf, finf, fnan}; 1913 float inputsd[kTableLength] = {4.8, 5.3, 6.1, -10.0, -8.9, -9.8, 1914 9.8, 9.8, 9.8, -9.8, -11.2, -9.8, 1915 3.0, fnan, -0.0, 0.0, fnan, finf, 1916 finf, 42.0, finf, fminf, fnan}; 1917 float resf[kTableLength] = { 1918 4.8, 4.8, 6.1, 9.8, -8.9, -9.8, 9.8, -8.9, -9.8, -9.8, -8.9, -9.8, 1919 3.0, 3.0, -0.0, -0.0, finf, finf, 42.0, 42.0, fminf, fminf, fnan}; 1920 float resf1[kTableLength] = { 1921 5.3, 5.3, 6.1, -10.0, 9.8, 9.8, -10.0, 9.8, 9.8, -10.0, -11.2, -9.8, 1922 3.0, 3.0, 0.0, 0.0, finf, finf, finf, finf, finf, finf, fnan}; 1923 1924 __ ldc1(f2, MemOperand(a0, offsetof(TestFloat, a)) ); 1925 __ ldc1(f4, MemOperand(a0, offsetof(TestFloat, b)) ); 1926 __ lwc1(f8, MemOperand(a0, offsetof(TestFloat, c)) ); 1927 __ lwc1(f10, MemOperand(a0, offsetof(TestFloat, d)) ); 1928 __ mina_d(f6, f2, f4); 1929 __ mina_s(f12, f8, f10); 1930 __ maxa_d(f14, f2, f4); 1931 __ maxa_s(f16, f8, f10); 1932 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, resf)) ); 1933 __ sdc1(f6, MemOperand(a0, offsetof(TestFloat, resd)) ); 1934 __ swc1(f16, MemOperand(a0, offsetof(TestFloat, resf1)) ); 1935 __ sdc1(f14, MemOperand(a0, offsetof(TestFloat, resd1)) ); 1936 __ jr(ra); 1937 __ nop(); 1938 1939 CodeDesc desc; 1940 assm.GetCode(&desc); 1941 Handle<Code> code = isolate->factory()->NewCode( 1942 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 1943 F3 f = FUNCTION_CAST<F3>(code->entry()); 1944 for (int i = 0; i < kTableLength; i++) { 1945 test.a = inputsa[i]; 1946 test.b = inputsb[i]; 1947 test.c = inputsc[i]; 1948 test.d = inputsd[i]; 1949 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 1950 if (i < kTableLength - 1) { 1951 CHECK_EQ(test.resd, resd[i]); 1952 CHECK_EQ(test.resf, resf[i]); 1953 CHECK_EQ(test.resd1, resd1[i]); 1954 CHECK_EQ(test.resf1, resf1[i]); 1955 } else { 1956 CHECK(std::isnan(test.resd)); 1957 CHECK(std::isnan(test.resf)); 1958 CHECK(std::isnan(test.resd1)); 1959 CHECK(std::isnan(test.resf1)); 1960 } 1961 } 1962 } 1963 } 1964 1965 1966 // ----------------------mips32r2 specific tests---------------------- 1967 TEST(trunc_l) { 1968 if (IsMipsArchVariant(kMips32r2) && IsFp64Mode()) { 1969 CcTest::InitializeVM(); 1970 Isolate* isolate = CcTest::i_isolate(); 1971 HandleScope scope(isolate); 1972 MacroAssembler assm(isolate, NULL, 0, 1973 v8::internal::CodeObjectRequired::kYes); 1974 const double dFPU64InvalidResult = static_cast<double>(kFPU64InvalidResult); 1975 typedef struct test_float { 1976 uint32_t isNaN2008; 1977 double a; 1978 float b; 1979 int64_t c; // a trunc result 1980 int64_t d; // b trunc result 1981 }Test; 1982 const int kTableLength = 15; 1983 double inputs_D[kTableLength] = { 1984 2.1, 2.6, 2.5, 3.1, 3.6, 3.5, 1985 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5, 1986 2147483648.0, 1987 std::numeric_limits<double>::quiet_NaN(), 1988 std::numeric_limits<double>::infinity() 1989 }; 1990 float inputs_S[kTableLength] = { 1991 2.1, 2.6, 2.5, 3.1, 3.6, 3.5, 1992 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5, 1993 2147483648.0, 1994 std::numeric_limits<float>::quiet_NaN(), 1995 std::numeric_limits<float>::infinity() 1996 }; 1997 double outputs[kTableLength] = { 1998 2.0, 2.0, 2.0, 3.0, 3.0, 3.0, 1999 -2.0, -2.0, -2.0, -3.0, -3.0, -3.0, 2000 2147483648.0, dFPU64InvalidResult, 2001 dFPU64InvalidResult}; 2002 double outputsNaN2008[kTableLength] = { 2003 2.0, 2.0, 2.0, 3.0, 3.0, 3.0, 2004 -2.0, -2.0, -2.0, -3.0, -3.0, -3.0, 2005 2147483648.0, 2006 0, 2007 dFPU64InvalidResult}; 2008 2009 __ cfc1(t1, FCSR); 2010 __ sw(t1, MemOperand(a0, offsetof(Test, isNaN2008))); 2011 __ ldc1(f4, MemOperand(a0, offsetof(Test, a)) ); 2012 __ lwc1(f6, MemOperand(a0, offsetof(Test, b)) ); 2013 __ trunc_l_d(f8, f4); 2014 __ trunc_l_s(f10, f6); 2015 __ sdc1(f8, MemOperand(a0, offsetof(Test, c)) ); 2016 __ sdc1(f10, MemOperand(a0, offsetof(Test, d)) ); 2017 __ jr(ra); 2018 __ nop(); 2019 Test test; 2020 CodeDesc desc; 2021 assm.GetCode(&desc); 2022 Handle<Code> code = isolate->factory()->NewCode( 2023 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 2024 F3 f = FUNCTION_CAST<F3>(code->entry()); 2025 for (int i = 0; i < kTableLength; i++) { 2026 test.a = inputs_D[i]; 2027 test.b = inputs_S[i]; 2028 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 2029 if ((test.isNaN2008 & kFCSRNaN2008FlagMask) && 2030 kArchVariant == kMips32r6) { 2031 CHECK_EQ(test.c, outputsNaN2008[i]); 2032 } else { 2033 CHECK_EQ(test.c, outputs[i]); 2034 } 2035 CHECK_EQ(test.d, test.c); 2036 } 2037 } 2038 } 2039 2040 2041 TEST(movz_movn) { 2042 if (IsMipsArchVariant(kMips32r2)) { 2043 const int kTableLength = 4; 2044 CcTest::InitializeVM(); 2045 Isolate* isolate = CcTest::i_isolate(); 2046 HandleScope scope(isolate); 2047 MacroAssembler assm(isolate, NULL, 0, 2048 v8::internal::CodeObjectRequired::kYes); 2049 2050 typedef struct test_float { 2051 int32_t rt; 2052 double a; 2053 double b; 2054 double bold; 2055 double b1; 2056 double bold1; 2057 float c; 2058 float d; 2059 float dold; 2060 float d1; 2061 float dold1; 2062 }TestFloat; 2063 2064 TestFloat test; 2065 double inputs_D[kTableLength] = { 2066 5.3, -5.3, 5.3, -2.9 2067 }; 2068 double inputs_S[kTableLength] = { 2069 4.8, 4.8, -4.8, -0.29 2070 }; 2071 2072 float outputs_S[kTableLength] = { 2073 4.8, 4.8, -4.8, -0.29 2074 }; 2075 double outputs_D[kTableLength] = { 2076 5.3, -5.3, 5.3, -2.9 2077 }; 2078 2079 __ ldc1(f2, MemOperand(a0, offsetof(TestFloat, a)) ); 2080 __ lwc1(f6, MemOperand(a0, offsetof(TestFloat, c)) ); 2081 __ lw(t0, MemOperand(a0, offsetof(TestFloat, rt)) ); 2082 __ Move(f12, 0.0); 2083 __ Move(f10, 0.0); 2084 __ Move(f16, 0.0); 2085 __ Move(f14, 0.0); 2086 __ sdc1(f12, MemOperand(a0, offsetof(TestFloat, bold)) ); 2087 __ swc1(f10, MemOperand(a0, offsetof(TestFloat, dold)) ); 2088 __ sdc1(f16, MemOperand(a0, offsetof(TestFloat, bold1)) ); 2089 __ swc1(f14, MemOperand(a0, offsetof(TestFloat, dold1)) ); 2090 __ movz_s(f10, f6, t0); 2091 __ movz_d(f12, f2, t0); 2092 __ movn_s(f14, f6, t0); 2093 __ movn_d(f16, f2, t0); 2094 __ swc1(f10, MemOperand(a0, offsetof(TestFloat, d)) ); 2095 __ sdc1(f12, MemOperand(a0, offsetof(TestFloat, b)) ); 2096 __ swc1(f14, MemOperand(a0, offsetof(TestFloat, d1)) ); 2097 __ sdc1(f16, MemOperand(a0, offsetof(TestFloat, b1)) ); 2098 __ jr(ra); 2099 __ nop(); 2100 2101 CodeDesc desc; 2102 assm.GetCode(&desc); 2103 Handle<Code> code = isolate->factory()->NewCode( 2104 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 2105 F3 f = FUNCTION_CAST<F3>(code->entry()); 2106 for (int i = 0; i < kTableLength; i++) { 2107 test.a = inputs_D[i]; 2108 test.c = inputs_S[i]; 2109 2110 test.rt = 1; 2111 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 2112 CHECK_EQ(test.b, test.bold); 2113 CHECK_EQ(test.d, test.dold); 2114 CHECK_EQ(test.b1, outputs_D[i]); 2115 CHECK_EQ(test.d1, outputs_S[i]); 2116 2117 test.rt = 0; 2118 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 2119 CHECK_EQ(test.b, outputs_D[i]); 2120 CHECK_EQ(test.d, outputs_S[i]); 2121 CHECK_EQ(test.b1, test.bold1); 2122 CHECK_EQ(test.d1, test.dold1); 2123 } 2124 } 2125 } 2126 2127 2128 TEST(movt_movd) { 2129 if (IsMipsArchVariant(kMips32r2)) { 2130 const int kTableLength = 4; 2131 CcTest::InitializeVM(); 2132 Isolate* isolate = CcTest::i_isolate(); 2133 2134 typedef struct test_float { 2135 double srcd; 2136 double dstd; 2137 double dstdold; 2138 double dstd1; 2139 double dstdold1; 2140 float srcf; 2141 float dstf; 2142 float dstfold; 2143 float dstf1; 2144 float dstfold1; 2145 int32_t cc; 2146 int32_t fcsr; 2147 }TestFloat; 2148 2149 TestFloat test; 2150 double inputs_D[kTableLength] = { 2151 5.3, -5.3, 20.8, -2.9 2152 }; 2153 double inputs_S[kTableLength] = { 2154 4.88, 4.8, -4.8, -0.29 2155 }; 2156 2157 float outputs_S[kTableLength] = { 2158 4.88, 4.8, -4.8, -0.29 2159 }; 2160 double outputs_D[kTableLength] = { 2161 5.3, -5.3, 20.8, -2.9 2162 }; 2163 int condition_flags[8] = {0, 1, 2, 3, 4, 5, 6, 7}; 2164 2165 for (int i = 0; i < kTableLength; i++) { 2166 test.srcd = inputs_D[i]; 2167 test.srcf = inputs_S[i]; 2168 2169 for (int j = 0; j< 8; j++) { 2170 test.cc = condition_flags[j]; 2171 if (test.cc == 0) { 2172 test.fcsr = 1 << 23; 2173 } else { 2174 test.fcsr = 1 << (24+condition_flags[j]); 2175 } 2176 HandleScope scope(isolate); 2177 MacroAssembler assm(isolate, NULL, 0, 2178 v8::internal::CodeObjectRequired::kYes); 2179 __ ldc1(f2, MemOperand(a0, offsetof(TestFloat, srcd)) ); 2180 __ lwc1(f4, MemOperand(a0, offsetof(TestFloat, srcf)) ); 2181 __ lw(t1, MemOperand(a0, offsetof(TestFloat, fcsr)) ); 2182 __ cfc1(t0, FCSR); 2183 __ ctc1(t1, FCSR); 2184 __ li(t2, 0x0); 2185 __ mtc1(t2, f12); 2186 __ mtc1(t2, f10); 2187 __ sdc1(f10, MemOperand(a0, offsetof(TestFloat, dstdold)) ); 2188 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, dstfold)) ); 2189 __ movt_s(f12, f4, test.cc); 2190 __ movt_d(f10, f2, test.cc); 2191 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, dstf)) ); 2192 __ sdc1(f10, MemOperand(a0, offsetof(TestFloat, dstd)) ); 2193 __ sdc1(f10, MemOperand(a0, offsetof(TestFloat, dstdold1)) ); 2194 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, dstfold1)) ); 2195 __ movf_s(f12, f4, test.cc); 2196 __ movf_d(f10, f2, test.cc); 2197 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, dstf1)) ); 2198 __ sdc1(f10, MemOperand(a0, offsetof(TestFloat, dstd1)) ); 2199 __ ctc1(t0, FCSR); 2200 __ jr(ra); 2201 __ nop(); 2202 2203 CodeDesc desc; 2204 assm.GetCode(&desc); 2205 Handle<Code> code = isolate->factory()->NewCode( 2206 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 2207 F3 f = FUNCTION_CAST<F3>(code->entry()); 2208 2209 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 2210 CHECK_EQ(test.dstf, outputs_S[i]); 2211 CHECK_EQ(test.dstd, outputs_D[i]); 2212 CHECK_EQ(test.dstf1, test.dstfold1); 2213 CHECK_EQ(test.dstd1, test.dstdold1); 2214 test.fcsr = 0; 2215 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 2216 CHECK_EQ(test.dstf, test.dstfold); 2217 CHECK_EQ(test.dstd, test.dstdold); 2218 CHECK_EQ(test.dstf1, outputs_S[i]); 2219 CHECK_EQ(test.dstd1, outputs_D[i]); 2220 } 2221 } 2222 } 2223 } 2224 2225 2226 // ----------------------tests for all archs-------------------------- 2227 TEST(cvt_w_d) { 2228 CcTest::InitializeVM(); 2229 Isolate* isolate = CcTest::i_isolate(); 2230 HandleScope scope(isolate); 2231 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); 2232 2233 typedef struct test_float { 2234 double a; 2235 int32_t b; 2236 int32_t fcsr; 2237 }Test; 2238 const int kTableLength = 24; 2239 double inputs[kTableLength] = { 2240 2.1, 2.6, 2.5, 3.1, 3.6, 3.5, 2241 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5, 2242 2147483637.0, 2147483638.0, 2147483639.0, 2243 2147483640.0, 2147483641.0, 2147483642.0, 2244 2147483643.0, 2147483644.0, 2147483645.0, 2245 2147483646.0, 2147483647.0, 2147483653.0 2246 }; 2247 double outputs_RN[kTableLength] = { 2248 2.0, 3.0, 2.0, 3.0, 4.0, 4.0, 2249 -2.0, -3.0, -2.0, -3.0, -4.0, -4.0, 2250 2147483637.0, 2147483638.0, 2147483639.0, 2251 2147483640.0, 2147483641.0, 2147483642.0, 2252 2147483643.0, 2147483644.0, 2147483645.0, 2253 2147483646.0, 2147483647.0, kFPUInvalidResult}; 2254 double outputs_RZ[kTableLength] = { 2255 2.0, 2.0, 2.0, 3.0, 3.0, 3.0, 2256 -2.0, -2.0, -2.0, -3.0, -3.0, -3.0, 2257 2147483637.0, 2147483638.0, 2147483639.0, 2258 2147483640.0, 2147483641.0, 2147483642.0, 2259 2147483643.0, 2147483644.0, 2147483645.0, 2260 2147483646.0, 2147483647.0, kFPUInvalidResult}; 2261 double outputs_RP[kTableLength] = { 2262 3.0, 3.0, 3.0, 4.0, 4.0, 4.0, 2263 -2.0, -2.0, -2.0, -3.0, -3.0, -3.0, 2264 2147483637.0, 2147483638.0, 2147483639.0, 2265 2147483640.0, 2147483641.0, 2147483642.0, 2266 2147483643.0, 2147483644.0, 2147483645.0, 2267 2147483646.0, 2147483647.0, kFPUInvalidResult}; 2268 double outputs_RM[kTableLength] = { 2269 2.0, 2.0, 2.0, 3.0, 3.0, 3.0, 2270 -3.0, -3.0, -3.0, -4.0, -4.0, -4.0, 2271 2147483637.0, 2147483638.0, 2147483639.0, 2272 2147483640.0, 2147483641.0, 2147483642.0, 2273 2147483643.0, 2147483644.0, 2147483645.0, 2274 2147483646.0, 2147483647.0, kFPUInvalidResult}; 2275 int fcsr_inputs[4] = 2276 {kRoundToNearest, kRoundToZero, kRoundToPlusInf, kRoundToMinusInf}; 2277 double* outputs[4] = {outputs_RN, outputs_RZ, outputs_RP, outputs_RM}; 2278 __ ldc1(f4, MemOperand(a0, offsetof(Test, a)) ); 2279 __ lw(t0, MemOperand(a0, offsetof(Test, fcsr)) ); 2280 __ cfc1(t1, FCSR); 2281 __ ctc1(t0, FCSR); 2282 __ cvt_w_d(f8, f4); 2283 __ swc1(f8, MemOperand(a0, offsetof(Test, b)) ); 2284 __ ctc1(t1, FCSR); 2285 __ jr(ra); 2286 __ nop(); 2287 Test test; 2288 CodeDesc desc; 2289 assm.GetCode(&desc); 2290 Handle<Code> code = isolate->factory()->NewCode( 2291 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 2292 F3 f = FUNCTION_CAST<F3>(code->entry()); 2293 for (int j = 0; j < 4; j++) { 2294 test.fcsr = fcsr_inputs[j]; 2295 for (int i = 0; i < kTableLength; i++) { 2296 test.a = inputs[i]; 2297 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 2298 CHECK_EQ(test.b, outputs[j][i]); 2299 } 2300 } 2301 } 2302 2303 2304 TEST(trunc_w) { 2305 CcTest::InitializeVM(); 2306 Isolate* isolate = CcTest::i_isolate(); 2307 HandleScope scope(isolate); 2308 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); 2309 2310 typedef struct test_float { 2311 uint32_t isNaN2008; 2312 double a; 2313 float b; 2314 int32_t c; // a trunc result 2315 int32_t d; // b trunc result 2316 }Test; 2317 const int kTableLength = 15; 2318 double inputs_D[kTableLength] = { 2319 2.1, 2.6, 2.5, 3.1, 3.6, 3.5, 2320 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5, 2321 2147483648.0, 2322 std::numeric_limits<double>::quiet_NaN(), 2323 std::numeric_limits<double>::infinity() 2324 }; 2325 float inputs_S[kTableLength] = { 2326 2.1, 2.6, 2.5, 3.1, 3.6, 3.5, 2327 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5, 2328 2147483648.0, 2329 std::numeric_limits<float>::quiet_NaN(), 2330 std::numeric_limits<float>::infinity() 2331 }; 2332 double outputs[kTableLength] = { 2333 2.0, 2.0, 2.0, 3.0, 3.0, 3.0, 2334 -2.0, -2.0, -2.0, -3.0, -3.0, -3.0, 2335 kFPUInvalidResult, kFPUInvalidResult, 2336 kFPUInvalidResult}; 2337 double outputsNaN2008[kTableLength] = { 2338 2.0, 2.0, 2.0, 3.0, 3.0, 3.0, 2339 -2.0, -2.0, -2.0, -3.0, -3.0, -3.0, 2340 kFPUInvalidResult, 2341 0, 2342 kFPUInvalidResult}; 2343 2344 __ cfc1(t1, FCSR); 2345 __ sw(t1, MemOperand(a0, offsetof(Test, isNaN2008))); 2346 __ ldc1(f4, MemOperand(a0, offsetof(Test, a)) ); 2347 __ lwc1(f6, MemOperand(a0, offsetof(Test, b)) ); 2348 __ trunc_w_d(f8, f4); 2349 __ trunc_w_s(f10, f6); 2350 __ swc1(f8, MemOperand(a0, offsetof(Test, c)) ); 2351 __ swc1(f10, MemOperand(a0, offsetof(Test, d)) ); 2352 __ jr(ra); 2353 __ nop(); 2354 Test test; 2355 CodeDesc desc; 2356 assm.GetCode(&desc); 2357 Handle<Code> code = isolate->factory()->NewCode( 2358 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 2359 F3 f = FUNCTION_CAST<F3>(code->entry()); 2360 for (int i = 0; i < kTableLength; i++) { 2361 test.a = inputs_D[i]; 2362 test.b = inputs_S[i]; 2363 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 2364 if ((test.isNaN2008 & kFCSRNaN2008FlagMask) && kArchVariant == kMips32r6) { 2365 CHECK_EQ(test.c, outputsNaN2008[i]); 2366 } else { 2367 CHECK_EQ(test.c, outputs[i]); 2368 } 2369 CHECK_EQ(test.d, test.c); 2370 } 2371 } 2372 2373 2374 TEST(round_w) { 2375 CcTest::InitializeVM(); 2376 Isolate* isolate = CcTest::i_isolate(); 2377 HandleScope scope(isolate); 2378 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); 2379 2380 typedef struct test_float { 2381 uint32_t isNaN2008; 2382 double a; 2383 float b; 2384 int32_t c; // a trunc result 2385 int32_t d; // b trunc result 2386 }Test; 2387 const int kTableLength = 15; 2388 double inputs_D[kTableLength] = { 2389 2.1, 2.6, 2.5, 3.1, 3.6, 3.5, 2390 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5, 2391 2147483648.0, 2392 std::numeric_limits<double>::quiet_NaN(), 2393 std::numeric_limits<double>::infinity() 2394 }; 2395 float inputs_S[kTableLength] = { 2396 2.1, 2.6, 2.5, 3.1, 3.6, 3.5, 2397 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5, 2398 2147483648.0, 2399 std::numeric_limits<float>::quiet_NaN(), 2400 std::numeric_limits<float>::infinity() 2401 }; 2402 double outputs[kTableLength] = { 2403 2.0, 3.0, 2.0, 3.0, 4.0, 4.0, 2404 -2.0, -3.0, -2.0, -3.0, -4.0, -4.0, 2405 kFPUInvalidResult, kFPUInvalidResult, 2406 kFPUInvalidResult}; 2407 double outputsNaN2008[kTableLength] = { 2408 2.0, 3.0, 2.0, 3.0, 4.0, 4.0, 2409 -2.0, -3.0, -2.0, -3.0, -4.0, -4.0, 2410 kFPUInvalidResult, 0, 2411 kFPUInvalidResult}; 2412 2413 __ cfc1(t1, FCSR); 2414 __ sw(t1, MemOperand(a0, offsetof(Test, isNaN2008))); 2415 __ ldc1(f4, MemOperand(a0, offsetof(Test, a)) ); 2416 __ lwc1(f6, MemOperand(a0, offsetof(Test, b)) ); 2417 __ round_w_d(f8, f4); 2418 __ round_w_s(f10, f6); 2419 __ swc1(f8, MemOperand(a0, offsetof(Test, c)) ); 2420 __ swc1(f10, MemOperand(a0, offsetof(Test, d)) ); 2421 __ jr(ra); 2422 __ nop(); 2423 Test test; 2424 CodeDesc desc; 2425 assm.GetCode(&desc); 2426 Handle<Code> code = isolate->factory()->NewCode( 2427 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 2428 F3 f = FUNCTION_CAST<F3>(code->entry()); 2429 for (int i = 0; i < kTableLength; i++) { 2430 test.a = inputs_D[i]; 2431 test.b = inputs_S[i]; 2432 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 2433 if ((test.isNaN2008 & kFCSRNaN2008FlagMask) && kArchVariant == kMips32r6) { 2434 CHECK_EQ(test.c, outputsNaN2008[i]); 2435 } else { 2436 CHECK_EQ(test.c, outputs[i]); 2437 } 2438 CHECK_EQ(test.d, test.c); 2439 } 2440 } 2441 2442 2443 TEST(round_l) { 2444 if (IsFp64Mode()) { 2445 CcTest::InitializeVM(); 2446 Isolate* isolate = CcTest::i_isolate(); 2447 HandleScope scope(isolate); 2448 MacroAssembler assm(isolate, NULL, 0, 2449 v8::internal::CodeObjectRequired::kYes); 2450 const double dFPU64InvalidResult = static_cast<double>(kFPU64InvalidResult); 2451 typedef struct test_float { 2452 uint32_t isNaN2008; 2453 double a; 2454 float b; 2455 int64_t c; 2456 int64_t d; 2457 }Test; 2458 const int kTableLength = 15; 2459 double inputs_D[kTableLength] = { 2460 2.1, 2.6, 2.5, 3.1, 3.6, 3.5, 2461 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5, 2462 2147483648.0, 2463 std::numeric_limits<double>::quiet_NaN(), 2464 std::numeric_limits<double>::infinity() 2465 }; 2466 float inputs_S[kTableLength] = { 2467 2.1, 2.6, 2.5, 3.1, 3.6, 3.5, 2468 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5, 2469 2147483648.0, 2470 std::numeric_limits<float>::quiet_NaN(), 2471 std::numeric_limits<float>::infinity() 2472 }; 2473 double outputs[kTableLength] = { 2474 2.0, 3.0, 2.0, 3.0, 4.0, 4.0, 2475 -2.0, -3.0, -2.0, -3.0, -4.0, -4.0, 2476 2147483648.0, dFPU64InvalidResult, 2477 dFPU64InvalidResult}; 2478 double outputsNaN2008[kTableLength] = { 2479 2.0, 3.0, 2.0, 3.0, 4.0, 4.0, 2480 -2.0, -3.0, -2.0, -3.0, -4.0, -4.0, 2481 2147483648.0, 2482 0, 2483 dFPU64InvalidResult}; 2484 2485 __ cfc1(t1, FCSR); 2486 __ sw(t1, MemOperand(a0, offsetof(Test, isNaN2008))); 2487 __ ldc1(f4, MemOperand(a0, offsetof(Test, a)) ); 2488 __ lwc1(f6, MemOperand(a0, offsetof(Test, b)) ); 2489 __ round_l_d(f8, f4); 2490 __ round_l_s(f10, f6); 2491 __ sdc1(f8, MemOperand(a0, offsetof(Test, c)) ); 2492 __ sdc1(f10, MemOperand(a0, offsetof(Test, d)) ); 2493 __ jr(ra); 2494 __ nop(); 2495 Test test; 2496 CodeDesc desc; 2497 assm.GetCode(&desc); 2498 Handle<Code> code = isolate->factory()->NewCode( 2499 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 2500 F3 f = FUNCTION_CAST<F3>(code->entry()); 2501 for (int i = 0; i < kTableLength; i++) { 2502 test.a = inputs_D[i]; 2503 test.b = inputs_S[i]; 2504 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 2505 if ((test.isNaN2008 & kFCSRNaN2008FlagMask) && 2506 kArchVariant == kMips32r6) { 2507 CHECK_EQ(test.c, outputsNaN2008[i]); 2508 } else { 2509 CHECK_EQ(test.c, outputs[i]); 2510 } 2511 CHECK_EQ(test.d, test.c); 2512 } 2513 } 2514 } 2515 2516 2517 TEST(sub) { 2518 const int kTableLength = 12; 2519 CcTest::InitializeVM(); 2520 Isolate* isolate = CcTest::i_isolate(); 2521 HandleScope scope(isolate); 2522 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); 2523 2524 typedef struct test_float { 2525 float a; 2526 float b; 2527 float resultS; 2528 double c; 2529 double d; 2530 double resultD; 2531 }TestFloat; 2532 2533 TestFloat test; 2534 double inputfs_D[kTableLength] = { 2535 5.3, 4.8, 2.9, -5.3, -4.8, -2.9, 2536 5.3, 4.8, 2.9, -5.3, -4.8, -2.9 2537 }; 2538 double inputft_D[kTableLength] = { 2539 4.8, 5.3, 2.9, 4.8, 5.3, 2.9, 2540 -4.8, -5.3, -2.9, -4.8, -5.3, -2.9 2541 }; 2542 double outputs_D[kTableLength] = { 2543 0.5, -0.5, 0.0, -10.1, -10.1, -5.8, 2544 10.1, 10.1, 5.8, -0.5, 0.5, 0.0 2545 }; 2546 float inputfs_S[kTableLength] = { 2547 5.3, 4.8, 2.9, -5.3, -4.8, -2.9, 2548 5.3, 4.8, 2.9, -5.3, -4.8, -2.9 2549 }; 2550 float inputft_S[kTableLength] = { 2551 4.8, 5.3, 2.9, 4.8, 5.3, 2.9, 2552 -4.8, -5.3, -2.9, -4.8, -5.3, -2.9 2553 }; 2554 float outputs_S[kTableLength] = { 2555 0.5, -0.5, 0.0, -10.1, -10.1, -5.8, 2556 10.1, 10.1, 5.8, -0.5, 0.5, 0.0 2557 }; 2558 __ lwc1(f2, MemOperand(a0, offsetof(TestFloat, a)) ); 2559 __ lwc1(f4, MemOperand(a0, offsetof(TestFloat, b)) ); 2560 __ ldc1(f8, MemOperand(a0, offsetof(TestFloat, c)) ); 2561 __ ldc1(f10, MemOperand(a0, offsetof(TestFloat, d)) ); 2562 __ sub_s(f6, f2, f4); 2563 __ sub_d(f12, f8, f10); 2564 __ swc1(f6, MemOperand(a0, offsetof(TestFloat, resultS)) ); 2565 __ sdc1(f12, MemOperand(a0, offsetof(TestFloat, resultD)) ); 2566 __ jr(ra); 2567 __ nop(); 2568 2569 CodeDesc desc; 2570 assm.GetCode(&desc); 2571 Handle<Code> code = isolate->factory()->NewCode( 2572 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 2573 F3 f = FUNCTION_CAST<F3>(code->entry()); 2574 for (int i = 0; i < kTableLength; i++) { 2575 test.a = inputfs_S[i]; 2576 test.b = inputft_S[i]; 2577 test.c = inputfs_D[i]; 2578 test.d = inputft_D[i]; 2579 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 2580 CHECK_EQ(test.resultS, outputs_S[i]); 2581 CHECK_EQ(test.resultD, outputs_D[i]); 2582 } 2583 } 2584 2585 2586 TEST(sqrt_rsqrt_recip) { 2587 const int kTableLength = 4; 2588 const double deltaDouble = 2E-15; 2589 const float deltaFloat = 2E-7; 2590 const float sqrt2_s = sqrt(2); 2591 const double sqrt2_d = sqrt(2); 2592 CcTest::InitializeVM(); 2593 Isolate* isolate = CcTest::i_isolate(); 2594 HandleScope scope(isolate); 2595 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); 2596 2597 typedef struct test_float { 2598 float a; 2599 float resultS; 2600 float resultS1; 2601 float resultS2; 2602 double c; 2603 double resultD; 2604 double resultD1; 2605 double resultD2; 2606 }TestFloat; 2607 TestFloat test; 2608 2609 double inputs_D[kTableLength] = { 2610 0.0L, 4.0L, 2.0L, 4e-28L 2611 }; 2612 2613 double outputs_D[kTableLength] = { 2614 0.0L, 2.0L, sqrt2_d, 2e-14L 2615 }; 2616 float inputs_S[kTableLength] = { 2617 0.0, 4.0, 2.0, 4e-28 2618 }; 2619 2620 float outputs_S[kTableLength] = { 2621 0.0, 2.0, sqrt2_s, 2e-14 2622 }; 2623 2624 2625 __ lwc1(f2, MemOperand(a0, offsetof(TestFloat, a)) ); 2626 __ ldc1(f8, MemOperand(a0, offsetof(TestFloat, c)) ); 2627 __ sqrt_s(f6, f2); 2628 __ sqrt_d(f12, f8); 2629 2630 if (IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) { 2631 __ rsqrt_d(f14, f8); 2632 __ rsqrt_s(f16, f2); 2633 __ recip_d(f18, f8); 2634 __ recip_s(f4, f2); 2635 } 2636 __ swc1(f6, MemOperand(a0, offsetof(TestFloat, resultS)) ); 2637 __ sdc1(f12, MemOperand(a0, offsetof(TestFloat, resultD)) ); 2638 2639 if (IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) { 2640 __ swc1(f16, MemOperand(a0, offsetof(TestFloat, resultS1)) ); 2641 __ sdc1(f14, MemOperand(a0, offsetof(TestFloat, resultD1)) ); 2642 __ swc1(f4, MemOperand(a0, offsetof(TestFloat, resultS2)) ); 2643 __ sdc1(f18, MemOperand(a0, offsetof(TestFloat, resultD2)) ); 2644 } 2645 __ jr(ra); 2646 __ nop(); 2647 2648 CodeDesc desc; 2649 assm.GetCode(&desc); 2650 Handle<Code> code = isolate->factory()->NewCode( 2651 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 2652 F3 f = FUNCTION_CAST<F3>(code->entry()); 2653 2654 for (int i = 0; i < kTableLength; i++) { 2655 float f1; 2656 double d1; 2657 test.a = inputs_S[i]; 2658 test.c = inputs_D[i]; 2659 2660 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 2661 2662 CHECK_EQ(test.resultS, outputs_S[i]); 2663 CHECK_EQ(test.resultD, outputs_D[i]); 2664 2665 if (IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) { 2666 if (i != 0) { 2667 f1 = test.resultS1 - 1.0F/outputs_S[i]; 2668 f1 = (f1 < 0) ? f1 : -f1; 2669 CHECK(f1 <= deltaFloat); 2670 d1 = test.resultD1 - 1.0L/outputs_D[i]; 2671 d1 = (d1 < 0) ? d1 : -d1; 2672 CHECK(d1 <= deltaDouble); 2673 f1 = test.resultS2 - 1.0F/inputs_S[i]; 2674 f1 = (f1 < 0) ? f1 : -f1; 2675 CHECK(f1 <= deltaFloat); 2676 d1 = test.resultD2 - 1.0L/inputs_D[i]; 2677 d1 = (d1 < 0) ? d1 : -d1; 2678 CHECK(d1 <= deltaDouble); 2679 } else { 2680 CHECK_EQ(test.resultS1, 1.0F/outputs_S[i]); 2681 CHECK_EQ(test.resultD1, 1.0L/outputs_D[i]); 2682 CHECK_EQ(test.resultS2, 1.0F/inputs_S[i]); 2683 CHECK_EQ(test.resultD2, 1.0L/inputs_D[i]); 2684 } 2685 } 2686 } 2687 } 2688 2689 2690 TEST(neg) { 2691 const int kTableLength = 3; 2692 CcTest::InitializeVM(); 2693 Isolate* isolate = CcTest::i_isolate(); 2694 HandleScope scope(isolate); 2695 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); 2696 2697 typedef struct test_float { 2698 float a; 2699 float resultS; 2700 double c; 2701 double resultD; 2702 }TestFloat; 2703 2704 TestFloat test; 2705 double inputs_D[kTableLength] = { 2706 0.0, 4.0, -2.0 2707 }; 2708 2709 double outputs_D[kTableLength] = { 2710 0.0, -4.0, 2.0 2711 }; 2712 float inputs_S[kTableLength] = { 2713 0.0, 4.0, -2.0 2714 }; 2715 2716 float outputs_S[kTableLength] = { 2717 0.0, -4.0, 2.0 2718 }; 2719 __ lwc1(f2, MemOperand(a0, offsetof(TestFloat, a)) ); 2720 __ ldc1(f8, MemOperand(a0, offsetof(TestFloat, c)) ); 2721 __ neg_s(f6, f2); 2722 __ neg_d(f12, f8); 2723 __ swc1(f6, MemOperand(a0, offsetof(TestFloat, resultS)) ); 2724 __ sdc1(f12, MemOperand(a0, offsetof(TestFloat, resultD)) ); 2725 __ jr(ra); 2726 __ nop(); 2727 2728 CodeDesc desc; 2729 assm.GetCode(&desc); 2730 Handle<Code> code = isolate->factory()->NewCode( 2731 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 2732 F3 f = FUNCTION_CAST<F3>(code->entry()); 2733 for (int i = 0; i < kTableLength; i++) { 2734 test.a = inputs_S[i]; 2735 test.c = inputs_D[i]; 2736 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 2737 CHECK_EQ(test.resultS, outputs_S[i]); 2738 CHECK_EQ(test.resultD, outputs_D[i]); 2739 } 2740 } 2741 2742 2743 TEST(mul) { 2744 const int kTableLength = 4; 2745 CcTest::InitializeVM(); 2746 Isolate* isolate = CcTest::i_isolate(); 2747 HandleScope scope(isolate); 2748 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); 2749 2750 typedef struct test_float { 2751 float a; 2752 float b; 2753 float resultS; 2754 double c; 2755 double d; 2756 double resultD; 2757 }TestFloat; 2758 2759 TestFloat test; 2760 double inputfs_D[kTableLength] = { 2761 5.3, -5.3, 5.3, -2.9 2762 }; 2763 double inputft_D[kTableLength] = { 2764 4.8, 4.8, -4.8, -0.29 2765 }; 2766 2767 float inputfs_S[kTableLength] = { 2768 5.3, -5.3, 5.3, -2.9 2769 }; 2770 float inputft_S[kTableLength] = { 2771 4.8, 4.8, -4.8, -0.29 2772 }; 2773 2774 __ lwc1(f2, MemOperand(a0, offsetof(TestFloat, a)) ); 2775 __ lwc1(f4, MemOperand(a0, offsetof(TestFloat, b)) ); 2776 __ ldc1(f6, MemOperand(a0, offsetof(TestFloat, c)) ); 2777 __ ldc1(f8, MemOperand(a0, offsetof(TestFloat, d)) ); 2778 __ mul_s(f10, f2, f4); 2779 __ mul_d(f12, f6, f8); 2780 __ swc1(f10, MemOperand(a0, offsetof(TestFloat, resultS)) ); 2781 __ sdc1(f12, MemOperand(a0, offsetof(TestFloat, resultD)) ); 2782 __ jr(ra); 2783 __ nop(); 2784 2785 CodeDesc desc; 2786 assm.GetCode(&desc); 2787 Handle<Code> code = isolate->factory()->NewCode( 2788 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 2789 F3 f = FUNCTION_CAST<F3>(code->entry()); 2790 for (int i = 0; i < kTableLength; i++) { 2791 test.a = inputfs_S[i]; 2792 test.b = inputft_S[i]; 2793 test.c = inputfs_D[i]; 2794 test.d = inputft_D[i]; 2795 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 2796 CHECK_EQ(test.resultS, inputfs_S[i]*inputft_S[i]); 2797 CHECK_EQ(test.resultD, inputfs_D[i]*inputft_D[i]); 2798 } 2799 } 2800 2801 2802 TEST(mov) { 2803 const int kTableLength = 4; 2804 CcTest::InitializeVM(); 2805 Isolate* isolate = CcTest::i_isolate(); 2806 HandleScope scope(isolate); 2807 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); 2808 2809 typedef struct test_float { 2810 double a; 2811 double b; 2812 float c; 2813 float d; 2814 }TestFloat; 2815 2816 TestFloat test; 2817 double inputs_D[kTableLength] = { 2818 5.3, -5.3, 5.3, -2.9 2819 }; 2820 double inputs_S[kTableLength] = { 2821 4.8, 4.8, -4.8, -0.29 2822 }; 2823 2824 float outputs_S[kTableLength] = { 2825 4.8, 4.8, -4.8, -0.29 2826 }; 2827 double outputs_D[kTableLength] = { 2828 5.3, -5.3, 5.3, -2.9 2829 }; 2830 2831 __ ldc1(f4, MemOperand(a0, offsetof(TestFloat, a)) ); 2832 __ lwc1(f6, MemOperand(a0, offsetof(TestFloat, c)) ); 2833 __ mov_s(f8, f6); 2834 __ mov_d(f10, f4); 2835 __ swc1(f8, MemOperand(a0, offsetof(TestFloat, d)) ); 2836 __ sdc1(f10, MemOperand(a0, offsetof(TestFloat, b)) ); 2837 2838 __ jr(ra); 2839 __ nop(); 2840 2841 CodeDesc desc; 2842 assm.GetCode(&desc); 2843 Handle<Code> code = isolate->factory()->NewCode( 2844 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 2845 F3 f = FUNCTION_CAST<F3>(code->entry()); 2846 for (int i = 0; i < kTableLength; i++) { 2847 test.a = inputs_D[i]; 2848 test.c = inputs_S[i]; 2849 2850 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 2851 CHECK_EQ(test.b, outputs_D[i]); 2852 CHECK_EQ(test.d, outputs_S[i]); 2853 } 2854 } 2855 2856 2857 TEST(floor_w) { 2858 CcTest::InitializeVM(); 2859 Isolate* isolate = CcTest::i_isolate(); 2860 HandleScope scope(isolate); 2861 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); 2862 2863 typedef struct test_float { 2864 uint32_t isNaN2008; 2865 double a; 2866 float b; 2867 int32_t c; // a floor result 2868 int32_t d; // b floor result 2869 }Test; 2870 const int kTableLength = 15; 2871 double inputs_D[kTableLength] = { 2872 2.1, 2.6, 2.5, 3.1, 3.6, 3.5, 2873 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5, 2874 2147483648.0, 2875 std::numeric_limits<double>::quiet_NaN(), 2876 std::numeric_limits<double>::infinity() 2877 }; 2878 float inputs_S[kTableLength] = { 2879 2.1, 2.6, 2.5, 3.1, 3.6, 3.5, 2880 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5, 2881 2147483648.0, 2882 std::numeric_limits<float>::quiet_NaN(), 2883 std::numeric_limits<float>::infinity() 2884 }; 2885 double outputs[kTableLength] = { 2886 2.0, 2.0, 2.0, 3.0, 3.0, 3.0, 2887 -3.0, -3.0, -3.0, -4.0, -4.0, -4.0, 2888 kFPUInvalidResult, kFPUInvalidResult, 2889 kFPUInvalidResult}; 2890 double outputsNaN2008[kTableLength] = { 2891 2.0, 2.0, 2.0, 3.0, 3.0, 3.0, 2892 -3.0, -3.0, -3.0, -4.0, -4.0, -4.0, 2893 kFPUInvalidResult, 2894 0, 2895 kFPUInvalidResult}; 2896 2897 __ cfc1(t1, FCSR); 2898 __ sw(t1, MemOperand(a0, offsetof(Test, isNaN2008))); 2899 __ ldc1(f4, MemOperand(a0, offsetof(Test, a)) ); 2900 __ lwc1(f6, MemOperand(a0, offsetof(Test, b)) ); 2901 __ floor_w_d(f8, f4); 2902 __ floor_w_s(f10, f6); 2903 __ swc1(f8, MemOperand(a0, offsetof(Test, c)) ); 2904 __ swc1(f10, MemOperand(a0, offsetof(Test, d)) ); 2905 __ jr(ra); 2906 __ nop(); 2907 Test test; 2908 CodeDesc desc; 2909 assm.GetCode(&desc); 2910 Handle<Code> code = isolate->factory()->NewCode( 2911 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 2912 F3 f = FUNCTION_CAST<F3>(code->entry()); 2913 for (int i = 0; i < kTableLength; i++) { 2914 test.a = inputs_D[i]; 2915 test.b = inputs_S[i]; 2916 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 2917 if ((test.isNaN2008 & kFCSRNaN2008FlagMask) && kArchVariant == kMips32r6) { 2918 CHECK_EQ(test.c, outputsNaN2008[i]); 2919 } else { 2920 CHECK_EQ(test.c, outputs[i]); 2921 } 2922 CHECK_EQ(test.d, test.c); 2923 } 2924 } 2925 2926 2927 TEST(floor_l) { 2928 if (IsFp64Mode()) { 2929 CcTest::InitializeVM(); 2930 Isolate* isolate = CcTest::i_isolate(); 2931 HandleScope scope(isolate); 2932 MacroAssembler assm(isolate, NULL, 0, 2933 v8::internal::CodeObjectRequired::kYes); 2934 const double dFPU64InvalidResult = static_cast<double>(kFPU64InvalidResult); 2935 typedef struct test_float { 2936 uint32_t isNaN2008; 2937 double a; 2938 float b; 2939 int64_t c; 2940 int64_t d; 2941 }Test; 2942 const int kTableLength = 15; 2943 double inputs_D[kTableLength] = { 2944 2.1, 2.6, 2.5, 3.1, 3.6, 3.5, 2945 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5, 2946 2147483648.0, 2947 std::numeric_limits<double>::quiet_NaN(), 2948 std::numeric_limits<double>::infinity() 2949 }; 2950 float inputs_S[kTableLength] = { 2951 2.1, 2.6, 2.5, 3.1, 3.6, 3.5, 2952 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5, 2953 2147483648.0, 2954 std::numeric_limits<float>::quiet_NaN(), 2955 std::numeric_limits<float>::infinity() 2956 }; 2957 double outputs[kTableLength] = { 2958 2.0, 2.0, 2.0, 3.0, 3.0, 3.0, 2959 -3.0, -3.0, -3.0, -4.0, -4.0, -4.0, 2960 2147483648.0, dFPU64InvalidResult, 2961 dFPU64InvalidResult}; 2962 double outputsNaN2008[kTableLength] = { 2963 2.0, 2.0, 2.0, 3.0, 3.0, 3.0, 2964 -3.0, -3.0, -3.0, -4.0, -4.0, -4.0, 2965 2147483648.0, 2966 0, 2967 dFPU64InvalidResult}; 2968 2969 __ cfc1(t1, FCSR); 2970 __ sw(t1, MemOperand(a0, offsetof(Test, isNaN2008))); 2971 __ ldc1(f4, MemOperand(a0, offsetof(Test, a)) ); 2972 __ lwc1(f6, MemOperand(a0, offsetof(Test, b)) ); 2973 __ floor_l_d(f8, f4); 2974 __ floor_l_s(f10, f6); 2975 __ sdc1(f8, MemOperand(a0, offsetof(Test, c)) ); 2976 __ sdc1(f10, MemOperand(a0, offsetof(Test, d)) ); 2977 __ jr(ra); 2978 __ nop(); 2979 Test test; 2980 CodeDesc desc; 2981 assm.GetCode(&desc); 2982 Handle<Code> code = isolate->factory()->NewCode( 2983 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 2984 F3 f = FUNCTION_CAST<F3>(code->entry()); 2985 for (int i = 0; i < kTableLength; i++) { 2986 test.a = inputs_D[i]; 2987 test.b = inputs_S[i]; 2988 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 2989 if ((test.isNaN2008 & kFCSRNaN2008FlagMask) && 2990 kArchVariant == kMips32r6) { 2991 CHECK_EQ(test.c, outputsNaN2008[i]); 2992 } else { 2993 CHECK_EQ(test.c, outputs[i]); 2994 } 2995 CHECK_EQ(test.d, test.c); 2996 } 2997 } 2998 } 2999 3000 3001 TEST(ceil_w) { 3002 CcTest::InitializeVM(); 3003 Isolate* isolate = CcTest::i_isolate(); 3004 HandleScope scope(isolate); 3005 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); 3006 3007 typedef struct test_float { 3008 uint32_t isNaN2008; 3009 double a; 3010 float b; 3011 int32_t c; // a floor result 3012 int32_t d; // b floor result 3013 }Test; 3014 const int kTableLength = 15; 3015 double inputs_D[kTableLength] = { 3016 2.1, 2.6, 2.5, 3.1, 3.6, 3.5, 3017 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5, 3018 2147483648.0, 3019 std::numeric_limits<double>::quiet_NaN(), 3020 std::numeric_limits<double>::infinity() 3021 }; 3022 float inputs_S[kTableLength] = { 3023 2.1, 2.6, 2.5, 3.1, 3.6, 3.5, 3024 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5, 3025 2147483648.0, 3026 std::numeric_limits<float>::quiet_NaN(), 3027 std::numeric_limits<float>::infinity() 3028 }; 3029 double outputs[kTableLength] = { 3030 3.0, 3.0, 3.0, 4.0, 4.0, 4.0, 3031 -2.0, -2.0, -2.0, -3.0, -3.0, -3.0, 3032 kFPUInvalidResult, kFPUInvalidResult, 3033 kFPUInvalidResult}; 3034 double outputsNaN2008[kTableLength] = { 3035 3.0, 3.0, 3.0, 4.0, 4.0, 4.0, 3036 -2.0, -2.0, -2.0, -3.0, -3.0, -3.0, 3037 kFPUInvalidResult, 3038 0, 3039 kFPUInvalidResult}; 3040 3041 __ cfc1(t1, FCSR); 3042 __ sw(t1, MemOperand(a0, offsetof(Test, isNaN2008))); 3043 __ ldc1(f4, MemOperand(a0, offsetof(Test, a)) ); 3044 __ lwc1(f6, MemOperand(a0, offsetof(Test, b)) ); 3045 __ ceil_w_d(f8, f4); 3046 __ ceil_w_s(f10, f6); 3047 __ swc1(f8, MemOperand(a0, offsetof(Test, c)) ); 3048 __ swc1(f10, MemOperand(a0, offsetof(Test, d)) ); 3049 __ jr(ra); 3050 __ nop(); 3051 Test test; 3052 CodeDesc desc; 3053 assm.GetCode(&desc); 3054 Handle<Code> code = isolate->factory()->NewCode( 3055 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 3056 F3 f = FUNCTION_CAST<F3>(code->entry()); 3057 for (int i = 0; i < kTableLength; i++) { 3058 test.a = inputs_D[i]; 3059 test.b = inputs_S[i]; 3060 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 3061 if ((test.isNaN2008 & kFCSRNaN2008FlagMask) && kArchVariant == kMips32r6) { 3062 CHECK_EQ(test.c, outputsNaN2008[i]); 3063 } else { 3064 CHECK_EQ(test.c, outputs[i]); 3065 } 3066 CHECK_EQ(test.d, test.c); 3067 } 3068 } 3069 3070 3071 TEST(ceil_l) { 3072 if (IsFp64Mode()) { 3073 CcTest::InitializeVM(); 3074 Isolate* isolate = CcTest::i_isolate(); 3075 HandleScope scope(isolate); 3076 MacroAssembler assm(isolate, NULL, 0, 3077 v8::internal::CodeObjectRequired::kYes); 3078 const double dFPU64InvalidResult = static_cast<double>(kFPU64InvalidResult); 3079 typedef struct test_float { 3080 uint32_t isNaN2008; 3081 double a; 3082 float b; 3083 int64_t c; 3084 int64_t d; 3085 }Test; 3086 const int kTableLength = 15; 3087 double inputs_D[kTableLength] = { 3088 2.1, 2.6, 2.5, 3.1, 3.6, 3.5, 3089 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5, 3090 2147483648.0, 3091 std::numeric_limits<double>::quiet_NaN(), 3092 std::numeric_limits<double>::infinity() 3093 }; 3094 float inputs_S[kTableLength] = { 3095 2.1, 2.6, 2.5, 3.1, 3.6, 3.5, 3096 -2.1, -2.6, -2.5, -3.1, -3.6, -3.5, 3097 2147483648.0, 3098 std::numeric_limits<float>::quiet_NaN(), 3099 std::numeric_limits<float>::infinity() 3100 }; 3101 double outputs[kTableLength] = { 3102 3.0, 3.0, 3.0, 4.0, 4.0, 4.0, 3103 -2.0, -2.0, -2.0, -3.0, -3.0, -3.0, 3104 2147483648.0, dFPU64InvalidResult, 3105 dFPU64InvalidResult}; 3106 double outputsNaN2008[kTableLength] = { 3107 3.0, 3.0, 3.0, 4.0, 4.0, 4.0, 3108 -2.0, -2.0, -2.0, -3.0, -3.0, -3.0, 3109 2147483648.0, 3110 0, 3111 dFPU64InvalidResult}; 3112 3113 __ cfc1(t1, FCSR); 3114 __ sw(t1, MemOperand(a0, offsetof(Test, isNaN2008))); 3115 __ ldc1(f4, MemOperand(a0, offsetof(Test, a)) ); 3116 __ lwc1(f6, MemOperand(a0, offsetof(Test, b)) ); 3117 __ ceil_l_d(f8, f4); 3118 __ ceil_l_s(f10, f6); 3119 __ sdc1(f8, MemOperand(a0, offsetof(Test, c)) ); 3120 __ sdc1(f10, MemOperand(a0, offsetof(Test, d)) ); 3121 __ jr(ra); 3122 __ nop(); 3123 Test test; 3124 CodeDesc desc; 3125 assm.GetCode(&desc); 3126 Handle<Code> code = isolate->factory()->NewCode( 3127 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 3128 F3 f = FUNCTION_CAST<F3>(code->entry()); 3129 for (int i = 0; i < kTableLength; i++) { 3130 test.a = inputs_D[i]; 3131 test.b = inputs_S[i]; 3132 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 3133 if ((test.isNaN2008 & kFCSRNaN2008FlagMask) && 3134 kArchVariant == kMips32r6) { 3135 CHECK_EQ(test.c, outputsNaN2008[i]); 3136 } else { 3137 CHECK_EQ(test.c, outputs[i]); 3138 } 3139 CHECK_EQ(test.d, test.c); 3140 } 3141 } 3142 } 3143 3144 3145 TEST(jump_tables1) { 3146 // Test jump tables with forward jumps. 3147 CcTest::InitializeVM(); 3148 Isolate* isolate = CcTest::i_isolate(); 3149 HandleScope scope(isolate); 3150 Assembler assm(isolate, nullptr, 0); 3151 3152 const int kNumCases = 512; 3153 int values[kNumCases]; 3154 isolate->random_number_generator()->NextBytes(values, sizeof(values)); 3155 Label labels[kNumCases]; 3156 3157 __ addiu(sp, sp, -4); 3158 __ sw(ra, MemOperand(sp)); 3159 3160 Label done; 3161 { 3162 __ BlockTrampolinePoolFor(kNumCases + 7); 3163 PredictableCodeSizeScope predictable( 3164 &assm, (kNumCases + 7) * Assembler::kInstrSize); 3165 Label here; 3166 3167 __ bal(&here); 3168 __ nop(); 3169 __ bind(&here); 3170 __ sll(at, a0, 2); 3171 __ addu(at, at, ra); 3172 __ lw(at, MemOperand(at, 5 * Assembler::kInstrSize)); 3173 __ jr(at); 3174 __ nop(); 3175 for (int i = 0; i < kNumCases; ++i) { 3176 __ dd(&labels[i]); 3177 } 3178 } 3179 3180 for (int i = 0; i < kNumCases; ++i) { 3181 __ bind(&labels[i]); 3182 __ lui(v0, (values[i] >> 16) & 0xffff); 3183 __ ori(v0, v0, values[i] & 0xffff); 3184 __ b(&done); 3185 __ nop(); 3186 } 3187 3188 __ bind(&done); 3189 __ lw(ra, MemOperand(sp)); 3190 __ addiu(sp, sp, 4); 3191 __ jr(ra); 3192 __ nop(); 3193 3194 CHECK_EQ(assm.UnboundLabelsCount(), 0); 3195 3196 CodeDesc desc; 3197 assm.GetCode(&desc); 3198 Handle<Code> code = isolate->factory()->NewCode( 3199 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 3200 #ifdef OBJECT_PRINT 3201 code->Print(std::cout); 3202 #endif 3203 F1 f = FUNCTION_CAST<F1>(code->entry()); 3204 for (int i = 0; i < kNumCases; ++i) { 3205 int res = reinterpret_cast<int>( 3206 CALL_GENERATED_CODE(isolate, f, i, 0, 0, 0, 0)); 3207 ::printf("f(%d) = %d\n", i, res); 3208 CHECK_EQ(values[i], res); 3209 } 3210 } 3211 3212 3213 TEST(jump_tables2) { 3214 // Test jump tables with backward jumps. 3215 CcTest::InitializeVM(); 3216 Isolate* isolate = CcTest::i_isolate(); 3217 HandleScope scope(isolate); 3218 Assembler assm(isolate, nullptr, 0); 3219 3220 const int kNumCases = 512; 3221 int values[kNumCases]; 3222 isolate->random_number_generator()->NextBytes(values, sizeof(values)); 3223 Label labels[kNumCases]; 3224 3225 __ addiu(sp, sp, -4); 3226 __ sw(ra, MemOperand(sp)); 3227 3228 Label done, dispatch; 3229 __ b(&dispatch); 3230 __ nop(); 3231 3232 for (int i = 0; i < kNumCases; ++i) { 3233 __ bind(&labels[i]); 3234 __ lui(v0, (values[i] >> 16) & 0xffff); 3235 __ ori(v0, v0, values[i] & 0xffff); 3236 __ b(&done); 3237 __ nop(); 3238 } 3239 3240 __ bind(&dispatch); 3241 { 3242 __ BlockTrampolinePoolFor(kNumCases + 7); 3243 PredictableCodeSizeScope predictable( 3244 &assm, (kNumCases + 7) * Assembler::kInstrSize); 3245 Label here; 3246 3247 __ bal(&here); 3248 __ nop(); 3249 __ bind(&here); 3250 __ sll(at, a0, 2); 3251 __ addu(at, at, ra); 3252 __ lw(at, MemOperand(at, 5 * Assembler::kInstrSize)); 3253 __ jr(at); 3254 __ nop(); 3255 for (int i = 0; i < kNumCases; ++i) { 3256 __ dd(&labels[i]); 3257 } 3258 } 3259 3260 __ bind(&done); 3261 __ lw(ra, MemOperand(sp)); 3262 __ addiu(sp, sp, 4); 3263 __ jr(ra); 3264 __ nop(); 3265 3266 CodeDesc desc; 3267 assm.GetCode(&desc); 3268 Handle<Code> code = isolate->factory()->NewCode( 3269 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 3270 #ifdef OBJECT_PRINT 3271 code->Print(std::cout); 3272 #endif 3273 F1 f = FUNCTION_CAST<F1>(code->entry()); 3274 for (int i = 0; i < kNumCases; ++i) { 3275 int res = reinterpret_cast<int>( 3276 CALL_GENERATED_CODE(isolate, f, i, 0, 0, 0, 0)); 3277 ::printf("f(%d) = %d\n", i, res); 3278 CHECK_EQ(values[i], res); 3279 } 3280 } 3281 3282 3283 TEST(jump_tables3) { 3284 // Test jump tables with backward jumps and embedded heap objects. 3285 CcTest::InitializeVM(); 3286 Isolate* isolate = CcTest::i_isolate(); 3287 HandleScope scope(isolate); 3288 Assembler assm(isolate, nullptr, 0); 3289 3290 const int kNumCases = 256; 3291 Handle<Object> values[kNumCases]; 3292 for (int i = 0; i < kNumCases; ++i) { 3293 double value = isolate->random_number_generator()->NextDouble(); 3294 values[i] = isolate->factory()->NewHeapNumber(value, IMMUTABLE, TENURED); 3295 } 3296 Label labels[kNumCases]; 3297 Object* obj; 3298 int32_t imm32; 3299 3300 __ addiu(sp, sp, -4); 3301 __ sw(ra, MemOperand(sp)); 3302 3303 Label done, dispatch; 3304 __ b(&dispatch); 3305 3306 3307 for (int i = 0; i < kNumCases; ++i) { 3308 __ bind(&labels[i]); 3309 obj = *values[i]; 3310 imm32 = reinterpret_cast<intptr_t>(obj); 3311 __ lui(v0, (imm32 >> 16) & 0xffff); 3312 __ ori(v0, v0, imm32 & 0xffff); 3313 __ b(&done); 3314 __ nop(); 3315 } 3316 3317 __ bind(&dispatch); 3318 { 3319 __ BlockTrampolinePoolFor(kNumCases + 7); 3320 PredictableCodeSizeScope predictable( 3321 &assm, (kNumCases + 7) * Assembler::kInstrSize); 3322 Label here; 3323 3324 __ bal(&here); 3325 __ nop(); 3326 __ bind(&here); 3327 __ sll(at, a0, 2); 3328 __ addu(at, at, ra); 3329 __ lw(at, MemOperand(at, 5 * Assembler::kInstrSize)); 3330 __ jr(at); 3331 __ nop(); 3332 for (int i = 0; i < kNumCases; ++i) { 3333 __ dd(&labels[i]); 3334 } 3335 } 3336 3337 __ bind(&done); 3338 __ lw(ra, MemOperand(sp)); 3339 __ addiu(sp, sp, 4); 3340 __ jr(ra); 3341 __ nop(); 3342 3343 CodeDesc desc; 3344 assm.GetCode(&desc); 3345 Handle<Code> code = isolate->factory()->NewCode( 3346 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 3347 #ifdef OBJECT_PRINT 3348 code->Print(std::cout); 3349 #endif 3350 F1 f = FUNCTION_CAST<F1>(code->entry()); 3351 for (int i = 0; i < kNumCases; ++i) { 3352 Handle<Object> result( 3353 CALL_GENERATED_CODE(isolate, f, i, 0, 0, 0, 0), isolate); 3354 #ifdef OBJECT_PRINT 3355 ::printf("f(%d) = ", i); 3356 result->Print(std::cout); 3357 ::printf("\n"); 3358 #endif 3359 CHECK(values[i].is_identical_to(result)); 3360 } 3361 } 3362 3363 3364 TEST(BITSWAP) { 3365 // Test BITSWAP 3366 if (IsMipsArchVariant(kMips32r6)) { 3367 CcTest::InitializeVM(); 3368 Isolate* isolate = CcTest::i_isolate(); 3369 HandleScope scope(isolate); 3370 3371 typedef struct { 3372 int32_t r1; 3373 int32_t r2; 3374 int32_t r3; 3375 int32_t r4; 3376 } T; 3377 T t; 3378 3379 Assembler assm(isolate, NULL, 0); 3380 3381 __ lw(a2, MemOperand(a0, offsetof(T, r1))); 3382 __ nop(); 3383 __ bitswap(a1, a2); 3384 __ sw(a1, MemOperand(a0, offsetof(T, r1))); 3385 3386 __ lw(a2, MemOperand(a0, offsetof(T, r2))); 3387 __ nop(); 3388 __ bitswap(a1, a2); 3389 __ sw(a1, MemOperand(a0, offsetof(T, r2))); 3390 3391 __ jr(ra); 3392 __ nop(); 3393 3394 CodeDesc desc; 3395 assm.GetCode(&desc); 3396 Handle<Code> code = isolate->factory()->NewCode( 3397 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 3398 F3 f = FUNCTION_CAST<F3>(code->entry()); 3399 t.r1 = 0x781A15C3; 3400 t.r2 = 0x8B71FCDE; 3401 Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0); 3402 USE(dummy); 3403 3404 CHECK_EQ(static_cast<int32_t>(0x1E58A8C3), t.r1); 3405 CHECK_EQ(static_cast<int32_t>(0xD18E3F7B), t.r2); 3406 } 3407 } 3408 3409 3410 TEST(class_fmt) { 3411 if (IsMipsArchVariant(kMips32r6)) { 3412 // Test CLASS.fmt instruction. 3413 CcTest::InitializeVM(); 3414 Isolate* isolate = CcTest::i_isolate(); 3415 HandleScope scope(isolate); 3416 3417 typedef struct { 3418 double dSignalingNan; 3419 double dQuietNan; 3420 double dNegInf; 3421 double dNegNorm; 3422 double dNegSubnorm; 3423 double dNegZero; 3424 double dPosInf; 3425 double dPosNorm; 3426 double dPosSubnorm; 3427 double dPosZero; 3428 float fSignalingNan; 3429 float fQuietNan; 3430 float fNegInf; 3431 float fNegNorm; 3432 float fNegSubnorm; 3433 float fNegZero; 3434 float fPosInf; 3435 float fPosNorm; 3436 float fPosSubnorm; 3437 float fPosZero; } T; 3438 T t; 3439 3440 // Create a function that accepts &t, and loads, manipulates, and stores 3441 // the doubles t.a ... t.f. 3442 MacroAssembler assm(isolate, NULL, 0, 3443 v8::internal::CodeObjectRequired::kYes); 3444 3445 __ ldc1(f4, MemOperand(a0, offsetof(T, dSignalingNan))); 3446 __ class_d(f6, f4); 3447 __ sdc1(f6, MemOperand(a0, offsetof(T, dSignalingNan))); 3448 3449 __ ldc1(f4, MemOperand(a0, offsetof(T, dQuietNan))); 3450 __ class_d(f6, f4); 3451 __ sdc1(f6, MemOperand(a0, offsetof(T, dQuietNan))); 3452 3453 __ ldc1(f4, MemOperand(a0, offsetof(T, dNegInf))); 3454 __ class_d(f6, f4); 3455 __ sdc1(f6, MemOperand(a0, offsetof(T, dNegInf))); 3456 3457 __ ldc1(f4, MemOperand(a0, offsetof(T, dNegNorm))); 3458 __ class_d(f6, f4); 3459 __ sdc1(f6, MemOperand(a0, offsetof(T, dNegNorm))); 3460 3461 __ ldc1(f4, MemOperand(a0, offsetof(T, dNegSubnorm))); 3462 __ class_d(f6, f4); 3463 __ sdc1(f6, MemOperand(a0, offsetof(T, dNegSubnorm))); 3464 3465 __ ldc1(f4, MemOperand(a0, offsetof(T, dNegZero))); 3466 __ class_d(f6, f4); 3467 __ sdc1(f6, MemOperand(a0, offsetof(T, dNegZero))); 3468 3469 __ ldc1(f4, MemOperand(a0, offsetof(T, dPosInf))); 3470 __ class_d(f6, f4); 3471 __ sdc1(f6, MemOperand(a0, offsetof(T, dPosInf))); 3472 3473 __ ldc1(f4, MemOperand(a0, offsetof(T, dPosNorm))); 3474 __ class_d(f6, f4); 3475 __ sdc1(f6, MemOperand(a0, offsetof(T, dPosNorm))); 3476 3477 __ ldc1(f4, MemOperand(a0, offsetof(T, dPosSubnorm))); 3478 __ class_d(f6, f4); 3479 __ sdc1(f6, MemOperand(a0, offsetof(T, dPosSubnorm))); 3480 3481 __ ldc1(f4, MemOperand(a0, offsetof(T, dPosZero))); 3482 __ class_d(f6, f4); 3483 __ sdc1(f6, MemOperand(a0, offsetof(T, dPosZero))); 3484 3485 // Testing instruction CLASS.S 3486 __ lwc1(f4, MemOperand(a0, offsetof(T, fSignalingNan))); 3487 __ class_s(f6, f4); 3488 __ swc1(f6, MemOperand(a0, offsetof(T, fSignalingNan))); 3489 3490 __ lwc1(f4, MemOperand(a0, offsetof(T, fQuietNan))); 3491 __ class_s(f6, f4); 3492 __ swc1(f6, MemOperand(a0, offsetof(T, fQuietNan))); 3493 3494 __ lwc1(f4, MemOperand(a0, offsetof(T, fNegInf))); 3495 __ class_s(f6, f4); 3496 __ swc1(f6, MemOperand(a0, offsetof(T, fNegInf))); 3497 3498 __ lwc1(f4, MemOperand(a0, offsetof(T, fNegNorm))); 3499 __ class_s(f6, f4); 3500 __ swc1(f6, MemOperand(a0, offsetof(T, fNegNorm))); 3501 3502 __ lwc1(f4, MemOperand(a0, offsetof(T, fNegSubnorm))); 3503 __ class_s(f6, f4); 3504 __ swc1(f6, MemOperand(a0, offsetof(T, fNegSubnorm))); 3505 3506 __ lwc1(f4, MemOperand(a0, offsetof(T, fNegZero))); 3507 __ class_s(f6, f4); 3508 __ swc1(f6, MemOperand(a0, offsetof(T, fNegZero))); 3509 3510 __ lwc1(f4, MemOperand(a0, offsetof(T, fPosInf))); 3511 __ class_s(f6, f4); 3512 __ swc1(f6, MemOperand(a0, offsetof(T, fPosInf))); 3513 3514 __ lwc1(f4, MemOperand(a0, offsetof(T, fPosNorm))); 3515 __ class_s(f6, f4); 3516 __ swc1(f6, MemOperand(a0, offsetof(T, fPosNorm))); 3517 3518 __ lwc1(f4, MemOperand(a0, offsetof(T, fPosSubnorm))); 3519 __ class_s(f6, f4); 3520 __ swc1(f6, MemOperand(a0, offsetof(T, fPosSubnorm))); 3521 3522 __ lwc1(f4, MemOperand(a0, offsetof(T, fPosZero))); 3523 __ class_s(f6, f4); 3524 __ swc1(f6, MemOperand(a0, offsetof(T, fPosZero))); 3525 3526 __ jr(ra); 3527 __ nop(); 3528 3529 CodeDesc desc; 3530 assm.GetCode(&desc); 3531 Handle<Code> code = isolate->factory()->NewCode( 3532 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 3533 F3 f = FUNCTION_CAST<F3>(code->entry()); 3534 3535 t.dSignalingNan = std::numeric_limits<double>::signaling_NaN(); 3536 t.dQuietNan = std::numeric_limits<double>::quiet_NaN(); 3537 t.dNegInf = -1.0 / 0.0; 3538 t.dNegNorm = -5.0; 3539 t.dNegSubnorm = -DBL_MIN / 2.0; 3540 t.dNegZero = -0.0; 3541 t.dPosInf = 2.0 / 0.0; 3542 t.dPosNorm = 275.35; 3543 t.dPosSubnorm = DBL_MIN / 2.0; 3544 t.dPosZero = +0.0; 3545 // Float test values 3546 3547 t.fSignalingNan = std::numeric_limits<float>::signaling_NaN(); 3548 t.fQuietNan = std::numeric_limits<float>::quiet_NaN(); 3549 t.fNegInf = -0.5/0.0; 3550 t.fNegNorm = -FLT_MIN; 3551 t.fNegSubnorm = -FLT_MIN / 1.5; 3552 t.fNegZero = -0.0; 3553 t.fPosInf = 100000.0 / 0.0; 3554 t.fPosNorm = FLT_MAX; 3555 t.fPosSubnorm = FLT_MIN / 20.0; 3556 t.fPosZero = +0.0; 3557 3558 Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0); 3559 USE(dummy); 3560 // Expected double results. 3561 CHECK_EQ(bit_cast<int64_t>(t.dSignalingNan), 0x001); 3562 CHECK_EQ(bit_cast<int64_t>(t.dQuietNan), 0x002); 3563 CHECK_EQ(bit_cast<int64_t>(t.dNegInf), 0x004); 3564 CHECK_EQ(bit_cast<int64_t>(t.dNegNorm), 0x008); 3565 CHECK_EQ(bit_cast<int64_t>(t.dNegSubnorm), 0x010); 3566 CHECK_EQ(bit_cast<int64_t>(t.dNegZero), 0x020); 3567 CHECK_EQ(bit_cast<int64_t>(t.dPosInf), 0x040); 3568 CHECK_EQ(bit_cast<int64_t>(t.dPosNorm), 0x080); 3569 CHECK_EQ(bit_cast<int64_t>(t.dPosSubnorm), 0x100); 3570 CHECK_EQ(bit_cast<int64_t>(t.dPosZero), 0x200); 3571 3572 // Expected float results. 3573 CHECK_EQ(bit_cast<int32_t>(t.fSignalingNan), 0x001); 3574 CHECK_EQ(bit_cast<int32_t>(t.fQuietNan), 0x002); 3575 CHECK_EQ(bit_cast<int32_t>(t.fNegInf), 0x004); 3576 CHECK_EQ(bit_cast<int32_t>(t.fNegNorm), 0x008); 3577 CHECK_EQ(bit_cast<int32_t>(t.fNegSubnorm), 0x010); 3578 CHECK_EQ(bit_cast<int32_t>(t.fNegZero), 0x020); 3579 CHECK_EQ(bit_cast<int32_t>(t.fPosInf), 0x040); 3580 CHECK_EQ(bit_cast<int32_t>(t.fPosNorm), 0x080); 3581 CHECK_EQ(bit_cast<int32_t>(t.fPosSubnorm), 0x100); 3582 CHECK_EQ(bit_cast<int32_t>(t.fPosZero), 0x200); 3583 } 3584 } 3585 3586 3587 TEST(ABS) { 3588 CcTest::InitializeVM(); 3589 Isolate* isolate = CcTest::i_isolate(); 3590 HandleScope scope(isolate); 3591 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); 3592 3593 typedef struct test_float { 3594 int64_t fir; 3595 double a; 3596 float b; 3597 double fcsr; 3598 } TestFloat; 3599 3600 TestFloat test; 3601 3602 // Save FIR. 3603 __ cfc1(a1, FCSR); 3604 // Disable FPU exceptions. 3605 __ ctc1(zero_reg, FCSR); 3606 3607 __ ldc1(f4, MemOperand(a0, offsetof(TestFloat, a))); 3608 __ abs_d(f10, f4); 3609 __ sdc1(f10, MemOperand(a0, offsetof(TestFloat, a))); 3610 3611 __ lwc1(f4, MemOperand(a0, offsetof(TestFloat, b))); 3612 __ abs_s(f10, f4); 3613 __ swc1(f10, MemOperand(a0, offsetof(TestFloat, b))); 3614 3615 // Restore FCSR. 3616 __ ctc1(a1, FCSR); 3617 3618 __ jr(ra); 3619 __ nop(); 3620 3621 CodeDesc desc; 3622 assm.GetCode(&desc); 3623 Handle<Code> code = isolate->factory()->NewCode( 3624 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 3625 F3 f = FUNCTION_CAST<F3>(code->entry()); 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 test.a = 2.0; 3633 test.b = 2.0; 3634 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 3635 CHECK_EQ(test.a, 2.0); 3636 CHECK_EQ(test.b, 2.0); 3637 3638 // Testing biggest positive number 3639 test.a = std::numeric_limits<double>::max(); 3640 test.b = std::numeric_limits<float>::max(); 3641 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 3642 CHECK_EQ(test.a, std::numeric_limits<double>::max()); 3643 CHECK_EQ(test.b, std::numeric_limits<float>::max()); 3644 3645 // Testing smallest negative number 3646 test.a = -std::numeric_limits<double>::max(); // lowest() 3647 test.b = -std::numeric_limits<float>::max(); // lowest() 3648 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 3649 CHECK_EQ(test.a, std::numeric_limits<double>::max()); 3650 CHECK_EQ(test.b, std::numeric_limits<float>::max()); 3651 3652 // Testing smallest positive number 3653 test.a = -std::numeric_limits<double>::min(); 3654 test.b = -std::numeric_limits<float>::min(); 3655 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 3656 CHECK_EQ(test.a, std::numeric_limits<double>::min()); 3657 CHECK_EQ(test.b, std::numeric_limits<float>::min()); 3658 3659 // Testing infinity 3660 test.a = -std::numeric_limits<double>::max() 3661 / std::numeric_limits<double>::min(); 3662 test.b = -std::numeric_limits<float>::max() 3663 / std::numeric_limits<float>::min(); 3664 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 3665 CHECK_EQ(test.a, std::numeric_limits<double>::max() 3666 / std::numeric_limits<double>::min()); 3667 CHECK_EQ(test.b, std::numeric_limits<float>::max() 3668 / std::numeric_limits<float>::min()); 3669 3670 test.a = std::numeric_limits<double>::quiet_NaN(); 3671 test.b = std::numeric_limits<float>::quiet_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 test.a = std::numeric_limits<double>::signaling_NaN(); 3677 test.b = std::numeric_limits<float>::signaling_NaN(); 3678 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 3679 CHECK_EQ(std::isnan(test.a), true); 3680 CHECK_EQ(std::isnan(test.b), true); 3681 } 3682 3683 3684 TEST(ADD_FMT) { 3685 CcTest::InitializeVM(); 3686 Isolate* isolate = CcTest::i_isolate(); 3687 HandleScope scope(isolate); 3688 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); 3689 3690 typedef struct test_float { 3691 double a; 3692 double b; 3693 double c; 3694 float fa; 3695 float fb; 3696 float fc; 3697 } TestFloat; 3698 3699 TestFloat test; 3700 3701 __ ldc1(f4, MemOperand(a0, offsetof(TestFloat, a))); 3702 __ ldc1(f8, MemOperand(a0, offsetof(TestFloat, b))); 3703 __ add_d(f10, f8, f4); 3704 __ sdc1(f10, MemOperand(a0, offsetof(TestFloat, c))); 3705 3706 __ lwc1(f4, MemOperand(a0, offsetof(TestFloat, fa))); 3707 __ lwc1(f8, MemOperand(a0, offsetof(TestFloat, fb))); 3708 __ add_s(f10, f8, f4); 3709 __ swc1(f10, MemOperand(a0, offsetof(TestFloat, fc))); 3710 3711 __ jr(ra); 3712 __ nop(); 3713 3714 CodeDesc desc; 3715 assm.GetCode(&desc); 3716 Handle<Code> code = isolate->factory()->NewCode( 3717 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 3718 F3 f = FUNCTION_CAST<F3>(code->entry()); 3719 test.a = 2.0; 3720 test.b = 3.0; 3721 test.fa = 2.0; 3722 test.fb = 3.0; 3723 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 3724 CHECK_EQ(test.c, 5.0); 3725 CHECK_EQ(test.fc, 5.0); 3726 3727 test.a = std::numeric_limits<double>::max(); 3728 test.b = -std::numeric_limits<double>::max(); // lowest() 3729 test.fa = std::numeric_limits<float>::max(); 3730 test.fb = -std::numeric_limits<float>::max(); // lowest() 3731 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 3732 CHECK_EQ(test.c, 0.0); 3733 CHECK_EQ(test.fc, 0.0); 3734 3735 test.a = std::numeric_limits<double>::max(); 3736 test.b = std::numeric_limits<double>::max(); 3737 test.fa = std::numeric_limits<float>::max(); 3738 test.fb = std::numeric_limits<float>::max(); 3739 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 3740 CHECK_EQ(std::isfinite(test.c), false); 3741 CHECK_EQ(std::isfinite(test.fc), false); 3742 3743 test.a = 5.0; 3744 test.b = std::numeric_limits<double>::signaling_NaN(); 3745 test.fa = 5.0; 3746 test.fb = std::numeric_limits<float>::signaling_NaN(); 3747 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 3748 CHECK_EQ(std::isnan(test.c), true); 3749 CHECK_EQ(std::isnan(test.fc), true); 3750 } 3751 3752 3753 TEST(C_COND_FMT) { 3754 if ((IsMipsArchVariant(kMips32r1)) || (IsMipsArchVariant(kMips32r2))) { 3755 CcTest::InitializeVM(); 3756 Isolate* isolate = CcTest::i_isolate(); 3757 HandleScope scope(isolate); 3758 MacroAssembler assm(isolate, NULL, 0, 3759 v8::internal::CodeObjectRequired::kYes); 3760 3761 typedef struct test_float { 3762 double dOp1; 3763 double dOp2; 3764 uint32_t dF; 3765 uint32_t dUn; 3766 uint32_t dEq; 3767 uint32_t dUeq; 3768 uint32_t dOlt; 3769 uint32_t dUlt; 3770 uint32_t dOle; 3771 uint32_t dUle; 3772 float fOp1; 3773 float fOp2; 3774 uint32_t fF; 3775 uint32_t fUn; 3776 uint32_t fEq; 3777 uint32_t fUeq; 3778 uint32_t fOlt; 3779 uint32_t fUlt; 3780 uint32_t fOle; 3781 uint32_t fUle; 3782 } TestFloat; 3783 3784 TestFloat test; 3785 3786 __ li(t1, 1); 3787 3788 __ ldc1(f4, MemOperand(a0, offsetof(TestFloat, dOp1))); 3789 __ ldc1(f6, MemOperand(a0, offsetof(TestFloat, dOp2))); 3790 3791 __ lwc1(f14, MemOperand(a0, offsetof(TestFloat, fOp1))); 3792 __ lwc1(f16, MemOperand(a0, offsetof(TestFloat, fOp2))); 3793 3794 __ mov(t2, zero_reg); 3795 __ mov(t3, zero_reg); 3796 __ c_d(F, f4, f6, 0); 3797 __ c_s(F, f14, f16, 2); 3798 __ movt(t2, t1, 0); 3799 __ movt(t3, t1, 2); 3800 __ sw(t2, MemOperand(a0, offsetof(TestFloat, dF)) ); 3801 __ sw(t3, MemOperand(a0, offsetof(TestFloat, fF)) ); 3802 3803 __ mov(t2, zero_reg); 3804 __ mov(t3, zero_reg); 3805 __ c_d(UN, f4, f6, 2); 3806 __ c_s(UN, f14, f16, 4); 3807 __ movt(t2, t1, 2); 3808 __ movt(t3, t1, 4); 3809 __ sw(t2, MemOperand(a0, offsetof(TestFloat, dUn)) ); 3810 __ sw(t3, MemOperand(a0, offsetof(TestFloat, fUn)) ); 3811 3812 __ mov(t2, zero_reg); 3813 __ mov(t3, zero_reg); 3814 __ c_d(EQ, f4, f6, 4); 3815 __ c_s(EQ, f14, f16, 6); 3816 __ movt(t2, t1, 4); 3817 __ movt(t3, t1, 6); 3818 __ sw(t2, MemOperand(a0, offsetof(TestFloat, dEq)) ); 3819 __ sw(t3, MemOperand(a0, offsetof(TestFloat, fEq)) ); 3820 3821 __ mov(t2, zero_reg); 3822 __ mov(t3, zero_reg); 3823 __ c_d(UEQ, f4, f6, 6); 3824 __ c_s(UEQ, f14, f16, 0); 3825 __ movt(t2, t1, 6); 3826 __ movt(t3, t1, 0); 3827 __ sw(t2, MemOperand(a0, offsetof(TestFloat, dUeq)) ); 3828 __ sw(t3, MemOperand(a0, offsetof(TestFloat, fUeq)) ); 3829 3830 __ mov(t2, zero_reg); 3831 __ mov(t3, zero_reg); 3832 __ c_d(OLT, f4, f6, 0); 3833 __ c_s(OLT, f14, f16, 2); 3834 __ movt(t2, t1, 0); 3835 __ movt(t3, t1, 2); 3836 __ sw(t2, MemOperand(a0, offsetof(TestFloat, dOlt)) ); 3837 __ sw(t3, MemOperand(a0, offsetof(TestFloat, fOlt)) ); 3838 3839 __ mov(t2, zero_reg); 3840 __ mov(t3, zero_reg); 3841 __ c_d(ULT, f4, f6, 2); 3842 __ c_s(ULT, f14, f16, 4); 3843 __ movt(t2, t1, 2); 3844 __ movt(t3, t1, 4); 3845 __ sw(t2, MemOperand(a0, offsetof(TestFloat, dUlt)) ); 3846 __ sw(t3, MemOperand(a0, offsetof(TestFloat, fUlt)) ); 3847 3848 __ mov(t2, zero_reg); 3849 __ mov(t3, zero_reg); 3850 __ c_d(OLE, f4, f6, 4); 3851 __ c_s(OLE, f14, f16, 6); 3852 __ movt(t2, t1, 4); 3853 __ movt(t3, t1, 6); 3854 __ sw(t2, MemOperand(a0, offsetof(TestFloat, dOle)) ); 3855 __ sw(t3, MemOperand(a0, offsetof(TestFloat, fOle)) ); 3856 3857 __ mov(t2, zero_reg); 3858 __ mov(t3, zero_reg); 3859 __ c_d(ULE, f4, f6, 6); 3860 __ c_s(ULE, f14, f16, 0); 3861 __ movt(t2, t1, 6); 3862 __ movt(t3, t1, 0); 3863 __ sw(t2, MemOperand(a0, offsetof(TestFloat, dUle)) ); 3864 __ sw(t3, MemOperand(a0, offsetof(TestFloat, fUle)) ); 3865 3866 __ jr(ra); 3867 __ nop(); 3868 3869 CodeDesc desc; 3870 assm.GetCode(&desc); 3871 Handle<Code> code = isolate->factory()->NewCode( 3872 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 3873 F3 f = FUNCTION_CAST<F3>(code->entry()); 3874 test.dOp1 = 2.0; 3875 test.dOp2 = 3.0; 3876 test.fOp1 = 2.0; 3877 test.fOp2 = 3.0; 3878 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 3879 CHECK_EQ(test.dF, 0U); 3880 CHECK_EQ(test.dUn, 0U); 3881 CHECK_EQ(test.dEq, 0U); 3882 CHECK_EQ(test.dUeq, 0U); 3883 CHECK_EQ(test.dOlt, 1U); 3884 CHECK_EQ(test.dUlt, 1U); 3885 CHECK_EQ(test.dOle, 1U); 3886 CHECK_EQ(test.dUle, 1U); 3887 CHECK_EQ(test.fF, 0U); 3888 CHECK_EQ(test.fUn, 0U); 3889 CHECK_EQ(test.fEq, 0U); 3890 CHECK_EQ(test.fUeq, 0U); 3891 CHECK_EQ(test.fOlt, 1U); 3892 CHECK_EQ(test.fUlt, 1U); 3893 CHECK_EQ(test.fOle, 1U); 3894 CHECK_EQ(test.fUle, 1U); 3895 3896 test.dOp1 = std::numeric_limits<double>::max(); 3897 test.dOp2 = std::numeric_limits<double>::min(); 3898 test.fOp1 = std::numeric_limits<float>::min(); 3899 test.fOp2 = -std::numeric_limits<float>::max(); // lowest() 3900 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 3901 CHECK_EQ(test.dF, 0U); 3902 CHECK_EQ(test.dUn, 0U); 3903 CHECK_EQ(test.dEq, 0U); 3904 CHECK_EQ(test.dUeq, 0U); 3905 CHECK_EQ(test.dOlt, 0U); 3906 CHECK_EQ(test.dUlt, 0U); 3907 CHECK_EQ(test.dOle, 0U); 3908 CHECK_EQ(test.dUle, 0U); 3909 CHECK_EQ(test.fF, 0U); 3910 CHECK_EQ(test.fUn, 0U); 3911 CHECK_EQ(test.fEq, 0U); 3912 CHECK_EQ(test.fUeq, 0U); 3913 CHECK_EQ(test.fOlt, 0U); 3914 CHECK_EQ(test.fUlt, 0U); 3915 CHECK_EQ(test.fOle, 0U); 3916 CHECK_EQ(test.fUle, 0U); 3917 3918 test.dOp1 = -std::numeric_limits<double>::max(); // lowest() 3919 test.dOp2 = -std::numeric_limits<double>::max(); // lowest() 3920 test.fOp1 = std::numeric_limits<float>::max(); 3921 test.fOp2 = std::numeric_limits<float>::max(); 3922 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 3923 CHECK_EQ(test.dF, 0U); 3924 CHECK_EQ(test.dUn, 0U); 3925 CHECK_EQ(test.dEq, 1U); 3926 CHECK_EQ(test.dUeq, 1U); 3927 CHECK_EQ(test.dOlt, 0U); 3928 CHECK_EQ(test.dUlt, 0U); 3929 CHECK_EQ(test.dOle, 1U); 3930 CHECK_EQ(test.dUle, 1U); 3931 CHECK_EQ(test.fF, 0U); 3932 CHECK_EQ(test.fUn, 0U); 3933 CHECK_EQ(test.fEq, 1U); 3934 CHECK_EQ(test.fUeq, 1U); 3935 CHECK_EQ(test.fOlt, 0U); 3936 CHECK_EQ(test.fUlt, 0U); 3937 CHECK_EQ(test.fOle, 1U); 3938 CHECK_EQ(test.fUle, 1U); 3939 3940 test.dOp1 = std::numeric_limits<double>::quiet_NaN(); 3941 test.dOp2 = 0.0; 3942 test.fOp1 = std::numeric_limits<float>::quiet_NaN(); 3943 test.fOp2 = 0.0; 3944 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 3945 CHECK_EQ(test.dF, 0U); 3946 CHECK_EQ(test.dUn, 1U); 3947 CHECK_EQ(test.dEq, 0U); 3948 CHECK_EQ(test.dUeq, 1U); 3949 CHECK_EQ(test.dOlt, 0U); 3950 CHECK_EQ(test.dUlt, 1U); 3951 CHECK_EQ(test.dOle, 0U); 3952 CHECK_EQ(test.dUle, 1U); 3953 CHECK_EQ(test.fF, 0U); 3954 CHECK_EQ(test.fUn, 1U); 3955 CHECK_EQ(test.fEq, 0U); 3956 CHECK_EQ(test.fUeq, 1U); 3957 CHECK_EQ(test.fOlt, 0U); 3958 CHECK_EQ(test.fUlt, 1U); 3959 CHECK_EQ(test.fOle, 0U); 3960 CHECK_EQ(test.fUle, 1U); 3961 } 3962 } 3963 3964 3965 TEST(CMP_COND_FMT) { 3966 if (IsMipsArchVariant(kMips32r6)) { 3967 CcTest::InitializeVM(); 3968 Isolate* isolate = CcTest::i_isolate(); 3969 HandleScope scope(isolate); 3970 MacroAssembler assm(isolate, NULL, 0, 3971 v8::internal::CodeObjectRequired::kYes); 3972 3973 typedef struct test_float { 3974 double dOp1; 3975 double dOp2; 3976 double dF; 3977 double dUn; 3978 double dEq; 3979 double dUeq; 3980 double dOlt; 3981 double dUlt; 3982 double dOle; 3983 double dUle; 3984 double dOr; 3985 double dUne; 3986 double dNe; 3987 float fOp1; 3988 float fOp2; 3989 float fF; 3990 float fUn; 3991 float fEq; 3992 float fUeq; 3993 float fOlt; 3994 float fUlt; 3995 float fOle; 3996 float fUle; 3997 float fOr; 3998 float fUne; 3999 float fNe; 4000 } TestFloat; 4001 4002 TestFloat test; 4003 4004 __ li(t1, 1); 4005 4006 __ ldc1(f4, MemOperand(a0, offsetof(TestFloat, dOp1))); 4007 __ ldc1(f6, MemOperand(a0, offsetof(TestFloat, dOp2))); 4008 4009 __ lwc1(f14, MemOperand(a0, offsetof(TestFloat, fOp1))); 4010 __ lwc1(f16, MemOperand(a0, offsetof(TestFloat, fOp2))); 4011 4012 __ cmp_d(F, f2, f4, f6); 4013 __ cmp_s(F, f12, f14, f16); 4014 __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dF)) ); 4015 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fF)) ); 4016 4017 __ cmp_d(UN, f2, f4, f6); 4018 __ cmp_s(UN, f12, f14, f16); 4019 __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dUn)) ); 4020 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fUn)) ); 4021 4022 __ cmp_d(EQ, f2, f4, f6); 4023 __ cmp_s(EQ, f12, f14, f16); 4024 __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dEq)) ); 4025 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fEq)) ); 4026 4027 __ cmp_d(UEQ, f2, f4, f6); 4028 __ cmp_s(UEQ, f12, f14, f16); 4029 __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dUeq)) ); 4030 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fUeq)) ); 4031 4032 __ cmp_d(LT, f2, f4, f6); 4033 __ cmp_s(LT, f12, f14, f16); 4034 __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dOlt)) ); 4035 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fOlt)) ); 4036 4037 __ cmp_d(ULT, f2, f4, f6); 4038 __ cmp_s(ULT, f12, f14, f16); 4039 __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dUlt)) ); 4040 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fUlt)) ); 4041 4042 __ cmp_d(LE, f2, f4, f6); 4043 __ cmp_s(LE, f12, f14, f16); 4044 __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dOle)) ); 4045 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fOle)) ); 4046 4047 __ cmp_d(ULE, f2, f4, f6); 4048 __ cmp_s(ULE, f12, f14, f16); 4049 __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dUle)) ); 4050 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fUle)) ); 4051 4052 __ cmp_d(ORD, f2, f4, f6); 4053 __ cmp_s(ORD, f12, f14, f16); 4054 __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dOr)) ); 4055 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fOr)) ); 4056 4057 __ cmp_d(UNE, f2, f4, f6); 4058 __ cmp_s(UNE, f12, f14, f16); 4059 __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dUne)) ); 4060 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fUne)) ); 4061 4062 __ cmp_d(NE, f2, f4, f6); 4063 __ cmp_s(NE, f12, f14, f16); 4064 __ sdc1(f2, MemOperand(a0, offsetof(TestFloat, dNe)) ); 4065 __ swc1(f12, MemOperand(a0, offsetof(TestFloat, fNe)) ); 4066 4067 __ jr(ra); 4068 __ nop(); 4069 4070 CodeDesc desc; 4071 assm.GetCode(&desc); 4072 Handle<Code> code = isolate->factory()->NewCode( 4073 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 4074 F3 f = FUNCTION_CAST<F3>(code->entry()); 4075 uint64_t dTrue = 0xFFFFFFFFFFFFFFFF; 4076 uint64_t dFalse = 0x0000000000000000; 4077 uint32_t fTrue = 0xFFFFFFFF; 4078 uint32_t fFalse = 0x00000000; 4079 4080 test.dOp1 = 2.0; 4081 test.dOp2 = 3.0; 4082 test.fOp1 = 2.0; 4083 test.fOp2 = 3.0; 4084 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 4085 CHECK_EQ(bit_cast<uint64_t>(test.dF), dFalse); 4086 CHECK_EQ(bit_cast<uint64_t>(test.dUn), dFalse); 4087 CHECK_EQ(bit_cast<uint64_t>(test.dEq), dFalse); 4088 CHECK_EQ(bit_cast<uint64_t>(test.dUeq), dFalse); 4089 CHECK_EQ(bit_cast<uint64_t>(test.dOlt), dTrue); 4090 CHECK_EQ(bit_cast<uint64_t>(test.dUlt), dTrue); 4091 CHECK_EQ(bit_cast<uint64_t>(test.dOle), dTrue); 4092 CHECK_EQ(bit_cast<uint64_t>(test.dUle), dTrue); 4093 CHECK_EQ(bit_cast<uint64_t>(test.dOr), dTrue); 4094 CHECK_EQ(bit_cast<uint64_t>(test.dUne), dTrue); 4095 CHECK_EQ(bit_cast<uint64_t>(test.dNe), dTrue); 4096 CHECK_EQ(bit_cast<uint32_t>(test.fF), fFalse); 4097 CHECK_EQ(bit_cast<uint32_t>(test.fUn), fFalse); 4098 CHECK_EQ(bit_cast<uint32_t>(test.fEq), fFalse); 4099 CHECK_EQ(bit_cast<uint32_t>(test.fUeq), fFalse); 4100 CHECK_EQ(bit_cast<uint32_t>(test.fOlt), fTrue); 4101 CHECK_EQ(bit_cast<uint32_t>(test.fUlt), fTrue); 4102 CHECK_EQ(bit_cast<uint32_t>(test.fOle), fTrue); 4103 CHECK_EQ(bit_cast<uint32_t>(test.fUle), fTrue); 4104 4105 test.dOp1 = std::numeric_limits<double>::max(); 4106 test.dOp2 = std::numeric_limits<double>::min(); 4107 test.fOp1 = std::numeric_limits<float>::min(); 4108 test.fOp2 = -std::numeric_limits<float>::max(); // lowest() 4109 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 4110 CHECK_EQ(bit_cast<uint64_t>(test.dF), dFalse); 4111 CHECK_EQ(bit_cast<uint64_t>(test.dUn), dFalse); 4112 CHECK_EQ(bit_cast<uint64_t>(test.dEq), dFalse); 4113 CHECK_EQ(bit_cast<uint64_t>(test.dUeq), dFalse); 4114 CHECK_EQ(bit_cast<uint64_t>(test.dOlt), dFalse); 4115 CHECK_EQ(bit_cast<uint64_t>(test.dUlt), dFalse); 4116 CHECK_EQ(bit_cast<uint64_t>(test.dOle), dFalse); 4117 CHECK_EQ(bit_cast<uint64_t>(test.dUle), dFalse); 4118 CHECK_EQ(bit_cast<uint64_t>(test.dOr), dTrue); 4119 CHECK_EQ(bit_cast<uint64_t>(test.dUne), dTrue); 4120 CHECK_EQ(bit_cast<uint64_t>(test.dNe), dTrue); 4121 CHECK_EQ(bit_cast<uint32_t>(test.fF), fFalse); 4122 CHECK_EQ(bit_cast<uint32_t>(test.fUn), fFalse); 4123 CHECK_EQ(bit_cast<uint32_t>(test.fEq), fFalse); 4124 CHECK_EQ(bit_cast<uint32_t>(test.fUeq), fFalse); 4125 CHECK_EQ(bit_cast<uint32_t>(test.fOlt), fFalse); 4126 CHECK_EQ(bit_cast<uint32_t>(test.fUlt), fFalse); 4127 CHECK_EQ(bit_cast<uint32_t>(test.fOle), fFalse); 4128 CHECK_EQ(bit_cast<uint32_t>(test.fUle), fFalse); 4129 4130 test.dOp1 = -std::numeric_limits<double>::max(); // lowest() 4131 test.dOp2 = -std::numeric_limits<double>::max(); // lowest() 4132 test.fOp1 = std::numeric_limits<float>::max(); 4133 test.fOp2 = std::numeric_limits<float>::max(); 4134 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 4135 CHECK_EQ(bit_cast<uint64_t>(test.dF), dFalse); 4136 CHECK_EQ(bit_cast<uint64_t>(test.dUn), dFalse); 4137 CHECK_EQ(bit_cast<uint64_t>(test.dEq), dTrue); 4138 CHECK_EQ(bit_cast<uint64_t>(test.dUeq), dTrue); 4139 CHECK_EQ(bit_cast<uint64_t>(test.dOlt), dFalse); 4140 CHECK_EQ(bit_cast<uint64_t>(test.dUlt), dFalse); 4141 CHECK_EQ(bit_cast<uint64_t>(test.dOle), dTrue); 4142 CHECK_EQ(bit_cast<uint64_t>(test.dUle), dTrue); 4143 CHECK_EQ(bit_cast<uint64_t>(test.dOr), dTrue); 4144 CHECK_EQ(bit_cast<uint64_t>(test.dUne), dFalse); 4145 CHECK_EQ(bit_cast<uint64_t>(test.dNe), dFalse); 4146 CHECK_EQ(bit_cast<uint32_t>(test.fF), fFalse); 4147 CHECK_EQ(bit_cast<uint32_t>(test.fUn), fFalse); 4148 CHECK_EQ(bit_cast<uint32_t>(test.fEq), fTrue); 4149 CHECK_EQ(bit_cast<uint32_t>(test.fUeq), fTrue); 4150 CHECK_EQ(bit_cast<uint32_t>(test.fOlt), fFalse); 4151 CHECK_EQ(bit_cast<uint32_t>(test.fUlt), fFalse); 4152 CHECK_EQ(bit_cast<uint32_t>(test.fOle), fTrue); 4153 CHECK_EQ(bit_cast<uint32_t>(test.fUle), fTrue); 4154 4155 test.dOp1 = std::numeric_limits<double>::quiet_NaN(); 4156 test.dOp2 = 0.0; 4157 test.fOp1 = std::numeric_limits<float>::quiet_NaN(); 4158 test.fOp2 = 0.0; 4159 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 4160 CHECK_EQ(bit_cast<uint64_t>(test.dF), dFalse); 4161 CHECK_EQ(bit_cast<uint64_t>(test.dUn), dTrue); 4162 CHECK_EQ(bit_cast<uint64_t>(test.dEq), dFalse); 4163 CHECK_EQ(bit_cast<uint64_t>(test.dUeq), dTrue); 4164 CHECK_EQ(bit_cast<uint64_t>(test.dOlt), dFalse); 4165 CHECK_EQ(bit_cast<uint64_t>(test.dUlt), dTrue); 4166 CHECK_EQ(bit_cast<uint64_t>(test.dOle), dFalse); 4167 CHECK_EQ(bit_cast<uint64_t>(test.dUle), dTrue); 4168 CHECK_EQ(bit_cast<uint64_t>(test.dOr), dFalse); 4169 CHECK_EQ(bit_cast<uint64_t>(test.dUne), dTrue); 4170 CHECK_EQ(bit_cast<uint64_t>(test.dNe), dFalse); 4171 CHECK_EQ(bit_cast<uint32_t>(test.fF), fFalse); 4172 CHECK_EQ(bit_cast<uint32_t>(test.fUn), fTrue); 4173 CHECK_EQ(bit_cast<uint32_t>(test.fEq), fFalse); 4174 CHECK_EQ(bit_cast<uint32_t>(test.fUeq), fTrue); 4175 CHECK_EQ(bit_cast<uint32_t>(test.fOlt), fFalse); 4176 CHECK_EQ(bit_cast<uint32_t>(test.fUlt), fTrue); 4177 CHECK_EQ(bit_cast<uint32_t>(test.fOle), fFalse); 4178 CHECK_EQ(bit_cast<uint32_t>(test.fUle), fTrue); 4179 } 4180 } 4181 4182 4183 TEST(CVT) { 4184 CcTest::InitializeVM(); 4185 Isolate* isolate = CcTest::i_isolate(); 4186 HandleScope scope(isolate); 4187 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); 4188 4189 typedef struct test_float { 4190 float cvt_d_s_in; 4191 double cvt_d_s_out; 4192 int32_t cvt_d_w_in; 4193 double cvt_d_w_out; 4194 int64_t cvt_d_l_in; 4195 double cvt_d_l_out; 4196 4197 float cvt_l_s_in; 4198 int64_t cvt_l_s_out; 4199 double cvt_l_d_in; 4200 int64_t cvt_l_d_out; 4201 4202 double cvt_s_d_in; 4203 float cvt_s_d_out; 4204 int32_t cvt_s_w_in; 4205 float cvt_s_w_out; 4206 int64_t cvt_s_l_in; 4207 float cvt_s_l_out; 4208 4209 float cvt_w_s_in; 4210 int32_t cvt_w_s_out; 4211 double cvt_w_d_in; 4212 int32_t cvt_w_d_out; 4213 } TestFloat; 4214 4215 TestFloat test; 4216 4217 // Save FCSR. 4218 __ cfc1(a1, FCSR); 4219 // Disable FPU exceptions. 4220 __ ctc1(zero_reg, FCSR); 4221 4222 #define GENERATE_CVT_TEST(x, y, z) \ 4223 __ y##c1(f0, MemOperand(a0, offsetof(TestFloat, x##_in))); \ 4224 __ x(f0, f0); \ 4225 __ nop(); \ 4226 __ z##c1(f0, MemOperand(a0, offsetof(TestFloat, x##_out))); 4227 4228 GENERATE_CVT_TEST(cvt_d_s, lw, sd) 4229 GENERATE_CVT_TEST(cvt_d_w, lw, sd) 4230 if ((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) && 4231 IsFp64Mode()) { 4232 GENERATE_CVT_TEST(cvt_d_l, ld, sd) 4233 } 4234 4235 if (IsFp64Mode()) { 4236 GENERATE_CVT_TEST(cvt_l_s, lw, sd) 4237 GENERATE_CVT_TEST(cvt_l_d, ld, sd) 4238 } 4239 4240 GENERATE_CVT_TEST(cvt_s_d, ld, sw) 4241 GENERATE_CVT_TEST(cvt_s_w, lw, sw) 4242 if ((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) && 4243 IsFp64Mode()) { 4244 GENERATE_CVT_TEST(cvt_s_l, ld, sw) 4245 } 4246 4247 GENERATE_CVT_TEST(cvt_w_s, lw, sw) 4248 GENERATE_CVT_TEST(cvt_w_d, ld, sw) 4249 4250 // Restore FCSR. 4251 __ ctc1(a1, FCSR); 4252 4253 __ jr(ra); 4254 __ nop(); 4255 4256 CodeDesc desc; 4257 assm.GetCode(&desc); 4258 Handle<Code> code = isolate->factory()->NewCode( 4259 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 4260 F3 f = FUNCTION_CAST<F3>(code->entry()); 4261 4262 test.cvt_d_s_in = -0.51; 4263 test.cvt_d_w_in = -1; 4264 test.cvt_d_l_in = -1; 4265 test.cvt_l_s_in = -0.51; 4266 test.cvt_l_d_in = -0.51; 4267 test.cvt_s_d_in = -0.51; 4268 test.cvt_s_w_in = -1; 4269 test.cvt_s_l_in = -1; 4270 test.cvt_w_s_in = -0.51; 4271 test.cvt_w_d_in = -0.51; 4272 4273 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 4274 CHECK_EQ(test.cvt_d_s_out, static_cast<double>(test.cvt_d_s_in)); 4275 CHECK_EQ(test.cvt_d_w_out, static_cast<double>(test.cvt_d_w_in)); 4276 if ((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) && 4277 IsFp64Mode()) { 4278 CHECK_EQ(test.cvt_d_l_out, static_cast<double>(test.cvt_d_l_in)); 4279 } 4280 if (IsFp64Mode()) { 4281 CHECK_EQ(test.cvt_l_s_out, -1); 4282 CHECK_EQ(test.cvt_l_d_out, -1); 4283 } 4284 CHECK_EQ(test.cvt_s_d_out, static_cast<float>(test.cvt_s_d_in)); 4285 CHECK_EQ(test.cvt_s_w_out, static_cast<float>(test.cvt_s_w_in)); 4286 if ((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) && 4287 IsFp64Mode()) { 4288 CHECK_EQ(test.cvt_s_l_out, static_cast<float>(test.cvt_s_l_in)); 4289 } 4290 CHECK_EQ(test.cvt_w_s_out, -1); 4291 CHECK_EQ(test.cvt_w_d_out, -1); 4292 4293 4294 test.cvt_d_s_in = 0.49; 4295 test.cvt_d_w_in = 1; 4296 test.cvt_d_l_in = 1; 4297 test.cvt_l_s_in = 0.49; 4298 test.cvt_l_d_in = 0.49; 4299 test.cvt_s_d_in = 0.49; 4300 test.cvt_s_w_in = 1; 4301 test.cvt_s_l_in = 1; 4302 test.cvt_w_s_in = 0.49; 4303 test.cvt_w_d_in = 0.49; 4304 4305 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 4306 CHECK_EQ(test.cvt_d_s_out, static_cast<double>(test.cvt_d_s_in)); 4307 CHECK_EQ(test.cvt_d_w_out, static_cast<double>(test.cvt_d_w_in)); 4308 if ((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) && 4309 IsFp64Mode()) { 4310 CHECK_EQ(test.cvt_d_l_out, static_cast<double>(test.cvt_d_l_in)); 4311 } 4312 if (IsFp64Mode()) { 4313 CHECK_EQ(test.cvt_l_s_out, 0); 4314 CHECK_EQ(test.cvt_l_d_out, 0); 4315 } 4316 CHECK_EQ(test.cvt_s_d_out, static_cast<float>(test.cvt_s_d_in)); 4317 CHECK_EQ(test.cvt_s_w_out, static_cast<float>(test.cvt_s_w_in)); 4318 if ((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) && 4319 IsFp64Mode()) { 4320 CHECK_EQ(test.cvt_s_l_out, static_cast<float>(test.cvt_s_l_in)); 4321 } 4322 CHECK_EQ(test.cvt_w_s_out, 0); 4323 CHECK_EQ(test.cvt_w_d_out, 0); 4324 4325 test.cvt_d_s_in = std::numeric_limits<float>::max(); 4326 test.cvt_d_w_in = std::numeric_limits<int32_t>::max(); 4327 test.cvt_d_l_in = std::numeric_limits<int64_t>::max(); 4328 test.cvt_l_s_in = std::numeric_limits<float>::max(); 4329 test.cvt_l_d_in = std::numeric_limits<double>::max(); 4330 test.cvt_s_d_in = std::numeric_limits<double>::max(); 4331 test.cvt_s_w_in = std::numeric_limits<int32_t>::max(); 4332 test.cvt_s_l_in = std::numeric_limits<int64_t>::max(); 4333 test.cvt_w_s_in = std::numeric_limits<float>::max(); 4334 test.cvt_w_d_in = std::numeric_limits<double>::max(); 4335 4336 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 4337 CHECK_EQ(test.cvt_d_s_out, static_cast<double>(test.cvt_d_s_in)); 4338 CHECK_EQ(test.cvt_d_w_out, static_cast<double>(test.cvt_d_w_in)); 4339 if ((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) && 4340 IsFp64Mode()) { 4341 CHECK_EQ(test.cvt_d_l_out, static_cast<double>(test.cvt_d_l_in)); 4342 } 4343 if (IsFp64Mode()) { 4344 CHECK_EQ(test.cvt_l_s_out, std::numeric_limits<int64_t>::max()); 4345 CHECK_EQ(test.cvt_l_d_out, std::numeric_limits<int64_t>::max()); 4346 } 4347 CHECK_EQ(test.cvt_s_d_out, static_cast<float>(test.cvt_s_d_in)); 4348 CHECK_EQ(test.cvt_s_w_out, static_cast<float>(test.cvt_s_w_in)); 4349 if ((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) && 4350 IsFp64Mode()) { 4351 CHECK_EQ(test.cvt_s_l_out, static_cast<float>(test.cvt_s_l_in)); 4352 } 4353 CHECK_EQ(test.cvt_w_s_out, std::numeric_limits<int32_t>::max()); 4354 CHECK_EQ(test.cvt_w_d_out, std::numeric_limits<int32_t>::max()); 4355 4356 4357 test.cvt_d_s_in = -std::numeric_limits<float>::max(); // lowest() 4358 test.cvt_d_w_in = std::numeric_limits<int32_t>::min(); // lowest() 4359 test.cvt_d_l_in = std::numeric_limits<int64_t>::min(); // lowest() 4360 test.cvt_l_s_in = -std::numeric_limits<float>::max(); // lowest() 4361 test.cvt_l_d_in = -std::numeric_limits<double>::max(); // lowest() 4362 test.cvt_s_d_in = -std::numeric_limits<double>::max(); // lowest() 4363 test.cvt_s_w_in = std::numeric_limits<int32_t>::min(); // lowest() 4364 test.cvt_s_l_in = std::numeric_limits<int64_t>::min(); // lowest() 4365 test.cvt_w_s_in = -std::numeric_limits<float>::max(); // lowest() 4366 test.cvt_w_d_in = -std::numeric_limits<double>::max(); // lowest() 4367 4368 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 4369 CHECK_EQ(test.cvt_d_s_out, static_cast<double>(test.cvt_d_s_in)); 4370 CHECK_EQ(test.cvt_d_w_out, static_cast<double>(test.cvt_d_w_in)); 4371 if ((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) && 4372 IsFp64Mode()) { 4373 CHECK_EQ(test.cvt_d_l_out, static_cast<double>(test.cvt_d_l_in)); 4374 } 4375 // The returned value when converting from fixed-point to float-point 4376 // is not consistent between board, simulator and specification 4377 // in this test case, therefore modifying the test 4378 if (IsFp64Mode()) { 4379 CHECK(test.cvt_l_s_out == std::numeric_limits<int64_t>::min() || 4380 test.cvt_l_s_out == std::numeric_limits<int64_t>::max()); 4381 CHECK(test.cvt_l_d_out == std::numeric_limits<int64_t>::min() || 4382 test.cvt_l_d_out == std::numeric_limits<int64_t>::max()); 4383 } 4384 CHECK_EQ(test.cvt_s_d_out, static_cast<float>(test.cvt_s_d_in)); 4385 CHECK_EQ(test.cvt_s_w_out, static_cast<float>(test.cvt_s_w_in)); 4386 if ((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) && 4387 IsFp64Mode()) { 4388 CHECK_EQ(test.cvt_s_l_out, static_cast<float>(test.cvt_s_l_in)); 4389 } 4390 CHECK(test.cvt_w_s_out == std::numeric_limits<int32_t>::min() || 4391 test.cvt_w_s_out == std::numeric_limits<int32_t>::max()); 4392 CHECK(test.cvt_w_d_out == std::numeric_limits<int32_t>::min() || 4393 test.cvt_w_d_out == std::numeric_limits<int32_t>::max()); 4394 4395 4396 test.cvt_d_s_in = std::numeric_limits<float>::min(); 4397 test.cvt_d_w_in = std::numeric_limits<int32_t>::min(); 4398 test.cvt_d_l_in = std::numeric_limits<int64_t>::min(); 4399 test.cvt_l_s_in = std::numeric_limits<float>::min(); 4400 test.cvt_l_d_in = std::numeric_limits<double>::min(); 4401 test.cvt_s_d_in = std::numeric_limits<double>::min(); 4402 test.cvt_s_w_in = std::numeric_limits<int32_t>::min(); 4403 test.cvt_s_l_in = std::numeric_limits<int64_t>::min(); 4404 test.cvt_w_s_in = std::numeric_limits<float>::min(); 4405 test.cvt_w_d_in = std::numeric_limits<double>::min(); 4406 4407 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 4408 CHECK_EQ(test.cvt_d_s_out, static_cast<double>(test.cvt_d_s_in)); 4409 CHECK_EQ(test.cvt_d_w_out, static_cast<double>(test.cvt_d_w_in)); 4410 if ((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) && 4411 IsFp64Mode()) { 4412 CHECK_EQ(test.cvt_d_l_out, static_cast<double>(test.cvt_d_l_in)); 4413 } 4414 if (IsFp64Mode()) { 4415 CHECK_EQ(test.cvt_l_s_out, 0); 4416 CHECK_EQ(test.cvt_l_d_out, 0); 4417 } 4418 CHECK_EQ(test.cvt_s_d_out, static_cast<float>(test.cvt_s_d_in)); 4419 CHECK_EQ(test.cvt_s_w_out, static_cast<float>(test.cvt_s_w_in)); 4420 if ((IsMipsArchVariant(kMips32r2) || IsMipsArchVariant(kMips32r6)) && 4421 IsFp64Mode()) { 4422 CHECK_EQ(test.cvt_s_l_out, static_cast<float>(test.cvt_s_l_in)); 4423 } 4424 CHECK_EQ(test.cvt_w_s_out, 0); 4425 CHECK_EQ(test.cvt_w_d_out, 0); 4426 } 4427 4428 4429 TEST(DIV_FMT) { 4430 CcTest::InitializeVM(); 4431 Isolate* isolate = CcTest::i_isolate(); 4432 HandleScope scope(isolate); 4433 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); 4434 4435 typedef struct test { 4436 double dOp1; 4437 double dOp2; 4438 double dRes; 4439 float fOp1; 4440 float fOp2; 4441 float fRes; 4442 } Test; 4443 4444 Test test; 4445 4446 // Save FCSR. 4447 __ cfc1(a1, FCSR); 4448 // Disable FPU exceptions. 4449 __ ctc1(zero_reg, FCSR); 4450 4451 __ ldc1(f4, MemOperand(a0, offsetof(Test, dOp1)) ); 4452 __ ldc1(f2, MemOperand(a0, offsetof(Test, dOp2)) ); 4453 __ nop(); 4454 __ div_d(f6, f4, f2); 4455 __ sdc1(f6, MemOperand(a0, offsetof(Test, dRes)) ); 4456 4457 __ lwc1(f4, MemOperand(a0, offsetof(Test, fOp1)) ); 4458 __ lwc1(f2, MemOperand(a0, offsetof(Test, fOp2)) ); 4459 __ nop(); 4460 __ div_s(f6, f4, f2); 4461 __ swc1(f6, MemOperand(a0, offsetof(Test, fRes)) ); 4462 4463 // Restore FCSR. 4464 __ ctc1(a1, FCSR); 4465 4466 __ jr(ra); 4467 __ nop(); 4468 4469 CodeDesc desc; 4470 assm.GetCode(&desc); 4471 Handle<Code> code = isolate->factory()->NewCode( 4472 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 4473 4474 F3 f = FUNCTION_CAST<F3>(code->entry()); 4475 4476 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 4477 4478 const int test_size = 3; 4479 4480 double dOp1[test_size] = { 4481 5.0, 4482 DBL_MAX, 4483 DBL_MAX, 4484 }; 4485 double dOp2[test_size] = { 4486 2.0, 4487 2.0, 4488 -DBL_MAX, 4489 }; 4490 double dRes[test_size] = { 4491 2.5, 4492 DBL_MAX / 2.0, 4493 -1.0, 4494 }; 4495 float fOp1[test_size] = { 4496 5.0, 4497 FLT_MAX, 4498 FLT_MAX, 4499 }; 4500 float fOp2[test_size] = { 4501 2.0, 4502 2.0, 4503 -FLT_MAX, 4504 }; 4505 float fRes[test_size] = { 4506 2.5, 4507 FLT_MAX / 2.0, 4508 -1.0, 4509 }; 4510 4511 for (int i = 0; i < test_size; i++) { 4512 test.dOp1 = dOp1[i]; 4513 test.dOp2 = dOp2[i]; 4514 test.fOp1 = fOp1[i]; 4515 test.fOp2 = fOp2[i]; 4516 4517 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 4518 CHECK_EQ(test.dRes, dRes[i]); 4519 CHECK_EQ(test.fRes, fRes[i]); 4520 } 4521 4522 test.dOp1 = DBL_MAX; 4523 test.dOp2 = -0.0; 4524 test.fOp1 = FLT_MAX; 4525 test.fOp2 = -0.0; 4526 4527 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 4528 CHECK_EQ(false, std::isfinite(test.dRes)); 4529 CHECK_EQ(false, std::isfinite(test.fRes)); 4530 4531 test.dOp1 = 0.0; 4532 test.dOp2 = -0.0; 4533 test.fOp1 = 0.0; 4534 test.fOp2 = -0.0; 4535 4536 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 4537 CHECK_EQ(true, std::isnan(test.dRes)); 4538 CHECK_EQ(true, std::isnan(test.fRes)); 4539 4540 test.dOp1 = std::numeric_limits<double>::quiet_NaN(); 4541 test.dOp2 = -5.0; 4542 test.fOp1 = std::numeric_limits<float>::quiet_NaN(); 4543 test.fOp2 = -5.0; 4544 4545 (CALL_GENERATED_CODE(isolate, f, &test, 0, 0, 0, 0)); 4546 CHECK_EQ(true, std::isnan(test.dRes)); 4547 CHECK_EQ(true, std::isnan(test.fRes)); 4548 } 4549 4550 4551 uint32_t run_align(uint32_t rs_value, uint32_t rt_value, uint8_t bp) { 4552 Isolate* isolate = CcTest::i_isolate(); 4553 HandleScope scope(isolate); 4554 4555 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); 4556 4557 __ align(v0, a0, a1, bp); 4558 __ jr(ra); 4559 __ nop(); 4560 4561 CodeDesc desc; 4562 assm.GetCode(&desc); 4563 Handle<Code> code = isolate->factory()->NewCode( 4564 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 4565 4566 F2 f = FUNCTION_CAST<F2>(code->entry()); 4567 4568 uint32_t res = reinterpret_cast<uint32_t>(CALL_GENERATED_CODE( 4569 isolate, f, rs_value, rt_value, 0, 0, 0)); 4570 4571 return res; 4572 } 4573 4574 4575 TEST(r6_align) { 4576 if (IsMipsArchVariant(kMips32r6)) { 4577 CcTest::InitializeVM(); 4578 4579 struct TestCaseAlign { 4580 uint32_t rs_value; 4581 uint32_t rt_value; 4582 uint8_t bp; 4583 uint32_t expected_res; 4584 }; 4585 4586 struct TestCaseAlign tc[] = { 4587 // rs_value, rt_value, bp, expected_res 4588 { 0x11223344, 0xaabbccdd, 0, 0xaabbccdd }, 4589 { 0x11223344, 0xaabbccdd, 1, 0xbbccdd11 }, 4590 { 0x11223344, 0xaabbccdd, 2, 0xccdd1122 }, 4591 { 0x11223344, 0xaabbccdd, 3, 0xdd112233 }, 4592 }; 4593 4594 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseAlign); 4595 for (size_t i = 0; i < nr_test_cases; ++i) { 4596 CHECK_EQ(tc[i].expected_res, run_align(tc[i].rs_value, 4597 tc[i].rt_value, tc[i].bp)); 4598 } 4599 } 4600 } 4601 4602 uint32_t PC; // The program counter. 4603 4604 uint32_t run_aluipc(int16_t offset) { 4605 Isolate* isolate = CcTest::i_isolate(); 4606 HandleScope scope(isolate); 4607 4608 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); 4609 4610 __ aluipc(v0, offset); 4611 __ jr(ra); 4612 __ nop(); 4613 4614 CodeDesc desc; 4615 assm.GetCode(&desc); 4616 Handle<Code> code = isolate->factory()->NewCode( 4617 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 4618 4619 F2 f = FUNCTION_CAST<F2>(code->entry()); 4620 PC = (uint32_t) f; // Set the program counter. 4621 4622 uint32_t res = reinterpret_cast<uint32_t>( 4623 CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0)); 4624 4625 return res; 4626 } 4627 4628 4629 TEST(r6_aluipc) { 4630 if (IsMipsArchVariant(kMips32r6)) { 4631 CcTest::InitializeVM(); 4632 4633 struct TestCaseAluipc { 4634 int16_t offset; 4635 }; 4636 4637 struct TestCaseAluipc tc[] = { 4638 // offset 4639 { -32768 }, // 0x8000 4640 { -1 }, // 0xFFFF 4641 { 0 }, 4642 { 1 }, 4643 { 32767 }, // 0x7FFF 4644 }; 4645 4646 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseAluipc); 4647 for (size_t i = 0; i < nr_test_cases; ++i) { 4648 PC = 0; 4649 uint32_t res = run_aluipc(tc[i].offset); 4650 // Now, the program_counter (PC) is set. 4651 uint32_t expected_res = ~0x0FFFF & (PC + (tc[i].offset << 16)); 4652 CHECK_EQ(expected_res, res); 4653 } 4654 } 4655 } 4656 4657 4658 uint32_t run_auipc(int16_t offset) { 4659 Isolate* isolate = CcTest::i_isolate(); 4660 HandleScope scope(isolate); 4661 4662 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); 4663 4664 __ auipc(v0, offset); 4665 __ jr(ra); 4666 __ nop(); 4667 4668 CodeDesc desc; 4669 assm.GetCode(&desc); 4670 Handle<Code> code = isolate->factory()->NewCode( 4671 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 4672 4673 F2 f = FUNCTION_CAST<F2>(code->entry()); 4674 PC = (uint32_t) f; // Set the program counter. 4675 4676 uint32_t res = reinterpret_cast<uint32_t>( 4677 CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0)); 4678 4679 return res; 4680 } 4681 4682 4683 TEST(r6_auipc) { 4684 if (IsMipsArchVariant(kMips32r6)) { 4685 CcTest::InitializeVM(); 4686 4687 struct TestCaseAuipc { 4688 int16_t offset; 4689 }; 4690 4691 struct TestCaseAuipc tc[] = { 4692 // offset 4693 { -32768 }, // 0x8000 4694 { -1 }, // 0xFFFF 4695 { 0 }, 4696 { 1 }, 4697 { 32767 }, // 0x7FFF 4698 }; 4699 4700 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseAuipc); 4701 for (size_t i = 0; i < nr_test_cases; ++i) { 4702 PC = 0; 4703 uint32_t res = run_auipc(tc[i].offset); 4704 // Now, the program_counter (PC) is set. 4705 uint32_t expected_res = PC + (tc[i].offset << 16); 4706 CHECK_EQ(expected_res, res); 4707 } 4708 } 4709 } 4710 4711 4712 uint32_t run_lwpc(int offset) { 4713 Isolate* isolate = CcTest::i_isolate(); 4714 HandleScope scope(isolate); 4715 4716 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); 4717 4718 // 256k instructions; 2^8k 4719 // addiu t7, t0, 0xffff; (0x250fffff) 4720 // ... 4721 // addiu t4, t0, 0x0000; (0x250c0000) 4722 uint32_t addiu_start_1 = 0x25000000; 4723 for (int32_t i = 0xfffff; i >= 0xc0000; --i) { 4724 uint32_t addiu_new = addiu_start_1 + i; 4725 __ dd(addiu_new); 4726 } 4727 4728 __ lwpc(t8, offset); // offset 0; 0xef080000 (t8 register) 4729 __ mov(v0, t8); 4730 4731 // 256k instructions; 2^8k 4732 // addiu t0, t0, 0x0000; (0x25080000) 4733 // ... 4734 // addiu t3, t0, 0xffff; (0x250bffff) 4735 uint32_t addiu_start_2 = 0x25000000; 4736 for (int32_t i = 0x80000; i <= 0xbffff; ++i) { 4737 uint32_t addiu_new = addiu_start_2 + i; 4738 __ dd(addiu_new); 4739 } 4740 4741 __ jr(ra); 4742 __ nop(); 4743 4744 CodeDesc desc; 4745 assm.GetCode(&desc); 4746 Handle<Code> code = isolate->factory()->NewCode( 4747 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 4748 4749 F2 f = FUNCTION_CAST<F2>(code->entry()); 4750 4751 uint32_t res = reinterpret_cast<uint32_t>( 4752 CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0)); 4753 4754 return res; 4755 } 4756 4757 4758 TEST(r6_lwpc) { 4759 if (IsMipsArchVariant(kMips32r6)) { 4760 CcTest::InitializeVM(); 4761 4762 struct TestCaseLwpc { 4763 int offset; 4764 uint32_t expected_res; 4765 }; 4766 4767 struct TestCaseLwpc tc[] = { 4768 // offset, expected_res 4769 { -262144, 0x250fffff }, // offset 0x40000 4770 { -4, 0x250c0003 }, 4771 { -1, 0x250c0000 }, 4772 { 0, 0xef080000 }, 4773 { 1, 0x03001025 }, // mov(v0, t8) 4774 { 2, 0x25080000 }, 4775 { 4, 0x25080002 }, 4776 { 262143, 0x250bfffd }, // offset 0x3ffff 4777 }; 4778 4779 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseLwpc); 4780 for (size_t i = 0; i < nr_test_cases; ++i) { 4781 uint32_t res = run_lwpc(tc[i].offset); 4782 CHECK_EQ(tc[i].expected_res, res); 4783 } 4784 } 4785 } 4786 4787 4788 uint32_t run_jic(int16_t offset) { 4789 Isolate* isolate = CcTest::i_isolate(); 4790 HandleScope scope(isolate); 4791 4792 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); 4793 4794 Label get_program_counter, stop_execution; 4795 __ push(ra); 4796 __ li(v0, 0); 4797 __ li(t1, 0x66); 4798 4799 __ addiu(v0, v0, 0x1); // <-- offset = -32 4800 __ addiu(v0, v0, 0x2); 4801 __ addiu(v0, v0, 0x10); 4802 __ addiu(v0, v0, 0x20); 4803 __ beq(v0, t1, &stop_execution); 4804 __ nop(); 4805 4806 __ bal(&get_program_counter); // t0 <- program counter 4807 __ nop(); 4808 __ jic(t0, offset); 4809 4810 __ addiu(v0, v0, 0x100); 4811 __ addiu(v0, v0, 0x200); 4812 __ addiu(v0, v0, 0x1000); 4813 __ addiu(v0, v0, 0x2000); // <--- offset = 16 4814 __ pop(ra); 4815 __ jr(ra); 4816 __ nop(); 4817 4818 __ bind(&get_program_counter); 4819 __ mov(t0, ra); 4820 __ jr(ra); 4821 __ nop(); 4822 4823 __ bind(&stop_execution); 4824 __ pop(ra); 4825 __ jr(ra); 4826 __ nop(); 4827 4828 CodeDesc desc; 4829 assm.GetCode(&desc); 4830 Handle<Code> code = isolate->factory()->NewCode( 4831 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 4832 4833 F2 f = FUNCTION_CAST<F2>(code->entry()); 4834 4835 uint32_t res = reinterpret_cast<uint32_t>( 4836 CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0)); 4837 4838 return res; 4839 } 4840 4841 4842 TEST(r6_jic) { 4843 if (IsMipsArchVariant(kMips32r6)) { 4844 CcTest::InitializeVM(); 4845 4846 struct TestCaseJic { 4847 // As rt will be used t0 register which will have value of 4848 // the program counter for the jic instruction. 4849 int16_t offset; 4850 uint32_t expected_res; 4851 }; 4852 4853 struct TestCaseJic tc[] = { 4854 // offset, expected_result 4855 { 16, 0x2033 }, 4856 { 4, 0x3333 }, 4857 { -32, 0x66 }, 4858 }; 4859 4860 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseJic); 4861 for (size_t i = 0; i < nr_test_cases; ++i) { 4862 uint32_t res = run_jic(tc[i].offset); 4863 CHECK_EQ(tc[i].expected_res, res); 4864 } 4865 } 4866 } 4867 4868 4869 uint64_t run_beqzc(int32_t value, int32_t offset) { 4870 Isolate* isolate = CcTest::i_isolate(); 4871 HandleScope scope(isolate); 4872 4873 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); 4874 4875 Label stop_execution; 4876 __ li(v0, 0); 4877 __ li(t1, 0x66); 4878 4879 __ addiu(v0, v0, 0x1); // <-- offset = -32 4880 __ addiu(v0, v0, 0x2); 4881 __ addiu(v0, v0, 0x10); 4882 __ addiu(v0, v0, 0x20); 4883 __ beq(v0, t1, &stop_execution); 4884 __ nop(); 4885 4886 __ beqzc(a0, offset); // BEQZC rs, offset 4887 4888 __ addiu(v0, v0, 0x1); 4889 __ addiu(v0, v0, 0x100); 4890 __ addiu(v0, v0, 0x200); 4891 __ addiu(v0, v0, 0x1000); 4892 __ addiu(v0, v0, 0x2000); // <--- offset = 16 4893 __ jr(ra); 4894 __ nop(); 4895 4896 __ bind(&stop_execution); 4897 __ jr(ra); 4898 __ nop(); 4899 4900 CodeDesc desc; 4901 assm.GetCode(&desc); 4902 Handle<Code> code = isolate->factory()->NewCode( 4903 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 4904 4905 F2 f = FUNCTION_CAST<F2>(code->entry()); 4906 4907 uint32_t res = reinterpret_cast<uint32_t>( 4908 CALL_GENERATED_CODE(isolate, f, value, 0, 0, 0, 0)); 4909 4910 return res; 4911 } 4912 4913 4914 TEST(r6_beqzc) { 4915 if (IsMipsArchVariant(kMips32r6)) { 4916 CcTest::InitializeVM(); 4917 4918 struct TestCaseBeqzc { 4919 uint32_t value; 4920 int32_t offset; 4921 uint32_t expected_res; 4922 }; 4923 4924 struct TestCaseBeqzc tc[] = { 4925 // value, offset, expected_res 4926 { 0x0, -8, 0x66 }, 4927 { 0x0, 0, 0x3334 }, 4928 { 0x0, 1, 0x3333 }, 4929 { 0xabc, 1, 0x3334 }, 4930 { 0x0, 4, 0x2033 }, 4931 }; 4932 4933 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseBeqzc); 4934 for (size_t i = 0; i < nr_test_cases; ++i) { 4935 uint32_t res = run_beqzc(tc[i].value, tc[i].offset); 4936 CHECK_EQ(tc[i].expected_res, res); 4937 } 4938 } 4939 } 4940 4941 4942 uint32_t run_jialc(int16_t offset) { 4943 Isolate* isolate = CcTest::i_isolate(); 4944 HandleScope scope(isolate); 4945 4946 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); 4947 4948 Label main_block, get_program_counter; 4949 __ push(ra); 4950 __ li(v0, 0); 4951 __ beq(v0, v0, &main_block); 4952 __ nop(); 4953 4954 // Block 1 4955 __ addiu(v0, v0, 0x1); // <-- offset = -40 4956 __ addiu(v0, v0, 0x2); 4957 __ jr(ra); 4958 __ nop(); 4959 4960 // Block 2 4961 __ addiu(v0, v0, 0x10); // <-- offset = -24 4962 __ addiu(v0, v0, 0x20); 4963 __ jr(ra); 4964 __ nop(); 4965 4966 // Block 3 (Main) 4967 __ bind(&main_block); 4968 __ bal(&get_program_counter); // t0 <- program counter 4969 __ nop(); 4970 __ jialc(t0, offset); 4971 __ addiu(v0, v0, 0x4); 4972 __ pop(ra); 4973 __ jr(ra); 4974 __ nop(); 4975 4976 // Block 4 4977 __ addiu(v0, v0, 0x100); // <-- offset = 20 4978 __ addiu(v0, v0, 0x200); 4979 __ jr(ra); 4980 __ nop(); 4981 4982 // Block 5 4983 __ addiu(v0, v0, 0x1000); // <--- offset = 36 4984 __ addiu(v0, v0, 0x2000); 4985 __ jr(ra); 4986 __ nop(); 4987 4988 __ bind(&get_program_counter); 4989 __ mov(t0, ra); 4990 __ jr(ra); 4991 __ nop(); 4992 4993 4994 CodeDesc desc; 4995 assm.GetCode(&desc); 4996 Handle<Code> code = isolate->factory()->NewCode( 4997 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 4998 4999 F2 f = FUNCTION_CAST<F2>(code->entry()); 5000 5001 uint32_t res = reinterpret_cast<uint32_t>( 5002 CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0)); 5003 5004 return res; 5005 } 5006 5007 5008 TEST(r6_jialc) { 5009 if (IsMipsArchVariant(kMips32r6)) { 5010 CcTest::InitializeVM(); 5011 5012 struct TestCaseJialc { 5013 int16_t offset; 5014 uint32_t expected_res; 5015 }; 5016 5017 struct TestCaseJialc tc[] = { 5018 // offset, expected_res 5019 { -40, 0x7 }, 5020 { -24, 0x34 }, 5021 { 20, 0x304 }, 5022 { 36, 0x3004 } 5023 }; 5024 5025 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseJialc); 5026 for (size_t i = 0; i < nr_test_cases; ++i) { 5027 uint32_t res = run_jialc(tc[i].offset); 5028 CHECK_EQ(tc[i].expected_res, res); 5029 } 5030 } 5031 } 5032 5033 static uint32_t run_addiupc(int32_t imm19) { 5034 Isolate* isolate = CcTest::i_isolate(); 5035 HandleScope scope(isolate); 5036 5037 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); 5038 5039 __ addiupc(v0, imm19); 5040 __ jr(ra); 5041 __ nop(); 5042 5043 CodeDesc desc; 5044 assm.GetCode(&desc); 5045 Handle<Code> code = isolate->factory()->NewCode( 5046 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 5047 5048 F2 f = FUNCTION_CAST<F2>(code->entry()); 5049 PC = (uint32_t) f; // Set the program counter. 5050 5051 uint32_t rs = reinterpret_cast<uint32_t>( 5052 CALL_GENERATED_CODE(isolate, f, imm19, 0, 0, 0, 0)); 5053 5054 return rs; 5055 } 5056 5057 5058 TEST(r6_addiupc) { 5059 if (IsMipsArchVariant(kMips32r6)) { 5060 CcTest::InitializeVM(); 5061 5062 struct TestCaseAddiupc { 5063 int32_t imm19; 5064 }; 5065 5066 TestCaseAddiupc tc[] = { 5067 // imm19 5068 {-262144}, // 0x40000 5069 {-1}, // 0x7FFFF 5070 {0}, 5071 {1}, // 0x00001 5072 {262143} // 0x3FFFF 5073 }; 5074 5075 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseAddiupc); 5076 for (size_t i = 0; i < nr_test_cases; ++i) { 5077 PC = 0; 5078 uint32_t res = run_addiupc(tc[i].imm19); 5079 // Now, the program_counter (PC) is set. 5080 uint32_t expected_res = PC + (tc[i].imm19 << 2); 5081 CHECK_EQ(expected_res, res); 5082 } 5083 } 5084 } 5085 5086 5087 int32_t run_bc(int32_t offset) { 5088 Isolate* isolate = CcTest::i_isolate(); 5089 HandleScope scope(isolate); 5090 5091 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); 5092 5093 Label continue_1, stop_execution; 5094 __ push(ra); 5095 __ li(v0, 0); 5096 __ li(t8, 0); 5097 __ li(t9, 2); // A condition for stopping execution. 5098 5099 for (int32_t i = -100; i <= -11; ++i) { 5100 __ addiu(v0, v0, 1); 5101 } 5102 5103 __ addiu(t8, t8, 1); // -10 5104 5105 __ beq(t8, t9, &stop_execution); // -9 5106 __ nop(); // -8 5107 __ beq(t8, t8, &continue_1); // -7 5108 __ nop(); // -6 5109 5110 __ bind(&stop_execution); 5111 __ pop(ra); // -5, -4 5112 __ jr(ra); // -3 5113 __ nop(); // -2 5114 5115 __ bind(&continue_1); 5116 __ bc(offset); // -1 5117 5118 for (int32_t i = 0; i <= 99; ++i) { 5119 __ addiu(v0, v0, 1); 5120 } 5121 5122 __ pop(ra); 5123 __ jr(ra); 5124 __ nop(); 5125 5126 CodeDesc desc; 5127 assm.GetCode(&desc); 5128 Handle<Code> code = isolate->factory()->NewCode( 5129 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 5130 5131 F2 f = FUNCTION_CAST<F2>(code->entry()); 5132 5133 int32_t res = reinterpret_cast<int32_t>( 5134 CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0)); 5135 5136 return res; 5137 } 5138 5139 5140 TEST(r6_bc) { 5141 if (IsMipsArchVariant(kMips32r6)) { 5142 CcTest::InitializeVM(); 5143 5144 struct TestCaseBc { 5145 int32_t offset; 5146 int32_t expected_res; 5147 }; 5148 5149 struct TestCaseBc tc[] = { 5150 // offset, expected_result 5151 { -100, (abs(-100) - 10) * 2 }, 5152 { -11, (abs(-100) - 10 + 1) }, 5153 { 0, (abs(-100) - 10 + 1 + 99) }, 5154 { 1, (abs(-100) - 10 + 99) }, 5155 { 99, (abs(-100) - 10 + 1) }, 5156 }; 5157 5158 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseBc); 5159 for (size_t i = 0; i < nr_test_cases; ++i) { 5160 int32_t res = run_bc(tc[i].offset); 5161 CHECK_EQ(tc[i].expected_res, res); 5162 } 5163 } 5164 } 5165 5166 5167 int32_t run_balc(int32_t offset) { 5168 Isolate* isolate = CcTest::i_isolate(); 5169 HandleScope scope(isolate); 5170 5171 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); 5172 5173 Label continue_1, stop_execution; 5174 __ push(ra); 5175 __ li(v0, 0); 5176 __ li(t8, 0); 5177 __ li(t9, 2); // A condition for stopping execution. 5178 5179 __ beq(t8, t8, &continue_1); 5180 __ nop(); 5181 5182 uint32_t instruction_addiu = 0x24420001; // addiu v0, v0, 1 5183 for (int32_t i = -117; i <= -57; ++i) { 5184 __ dd(instruction_addiu); 5185 } 5186 __ jr(ra); // -56 5187 __ nop(); // -55 5188 5189 for (int32_t i = -54; i <= -4; ++i) { 5190 __ dd(instruction_addiu); 5191 } 5192 __ jr(ra); // -3 5193 __ nop(); // -2 5194 5195 __ bind(&continue_1); 5196 __ balc(offset); // -1 5197 5198 __ pop(ra); // 0, 1 5199 __ jr(ra); // 2 5200 __ nop(); // 3 5201 5202 for (int32_t i = 4; i <= 44; ++i) { 5203 __ dd(instruction_addiu); 5204 } 5205 __ jr(ra); 5206 __ nop(); 5207 5208 CodeDesc desc; 5209 assm.GetCode(&desc); 5210 Handle<Code> code = isolate->factory()->NewCode( 5211 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 5212 5213 F2 f = FUNCTION_CAST<F2>(code->entry()); 5214 5215 int32_t res = reinterpret_cast<int32_t>( 5216 CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0)); 5217 5218 return res; 5219 } 5220 5221 5222 uint32_t run_aui(uint32_t rs, uint16_t offset) { 5223 Isolate* isolate = CcTest::i_isolate(); 5224 HandleScope scope(isolate); 5225 5226 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); 5227 5228 __ li(t0, rs); 5229 __ aui(v0, t0, offset); 5230 __ jr(ra); 5231 __ nop(); 5232 5233 CodeDesc desc; 5234 assm.GetCode(&desc); 5235 Handle<Code> code = isolate->factory()->NewCode( 5236 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 5237 5238 F2 f = FUNCTION_CAST<F2>(code->entry()); 5239 5240 uint32_t res = 5241 reinterpret_cast<uint32_t> 5242 (CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0)); 5243 5244 return res; 5245 } 5246 5247 5248 TEST(r6_aui) { 5249 if (IsMipsArchVariant(kMips32r6)) { 5250 CcTest::InitializeVM(); 5251 5252 struct TestCaseAui { 5253 uint32_t rs; 5254 uint16_t offset; 5255 uint32_t ref_res; 5256 }; 5257 5258 struct TestCaseAui tc[] = { 5259 // input, offset, result 5260 {0xfffeffff, 1, 0xffffffff}, 5261 {0xffffffff, 0, 0xffffffff}, 5262 {0, 0xffff, 0xffff0000}, 5263 {0x0008ffff, 0xfff7, 0xffffffff}, 5264 {32767, 32767, 0x7fff7fff}, 5265 // overflow cases 5266 {0xffffffff, 0x1, 0x0000ffff}, 5267 {0xffffffff, 0xffff, 0xfffeffff}, 5268 }; 5269 5270 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseAui); 5271 for (size_t i = 0; i < nr_test_cases; ++i) { 5272 PC = 0; 5273 uint32_t res = run_aui(tc[i].rs, tc[i].offset); 5274 CHECK_EQ(tc[i].ref_res, res); 5275 } 5276 } 5277 } 5278 5279 5280 TEST(r6_balc) { 5281 if (IsMipsArchVariant(kMips32r6)) { 5282 CcTest::InitializeVM(); 5283 5284 struct TestCaseBalc { 5285 int32_t offset; 5286 int32_t expected_res; 5287 }; 5288 5289 struct TestCaseBalc tc[] = { 5290 // offset, expected_result 5291 { -117, 61 }, 5292 { -54, 51 }, 5293 { 0, 0 }, 5294 { 4, 41 }, 5295 }; 5296 5297 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseBalc); 5298 for (size_t i = 0; i < nr_test_cases; ++i) { 5299 int32_t res = run_balc(tc[i].offset); 5300 CHECK_EQ(tc[i].expected_res, res); 5301 } 5302 } 5303 } 5304 5305 5306 uint32_t run_bal(int16_t offset) { 5307 Isolate* isolate = CcTest::i_isolate(); 5308 HandleScope scope(isolate); 5309 5310 MacroAssembler assm(isolate, NULL, 0, v8::internal::CodeObjectRequired::kYes); 5311 5312 __ mov(t0, ra); 5313 __ bal(offset); // Equivalent for "BGEZAL zero_reg, offset". 5314 __ nop(); 5315 5316 __ mov(ra, t0); 5317 __ jr(ra); 5318 __ nop(); 5319 5320 __ li(v0, 1); 5321 __ jr(ra); 5322 __ nop(); 5323 5324 CodeDesc desc; 5325 assm.GetCode(&desc); 5326 Handle<Code> code = isolate->factory()->NewCode( 5327 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 5328 5329 F2 f = FUNCTION_CAST<F2>(code->entry()); 5330 5331 uint32_t res = reinterpret_cast<uint32_t>( 5332 CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0)); 5333 5334 return res; 5335 } 5336 5337 5338 TEST(bal) { 5339 CcTest::InitializeVM(); 5340 5341 struct TestCaseBal { 5342 int16_t offset; 5343 uint32_t expected_res; 5344 }; 5345 5346 struct TestCaseBal tc[] = { 5347 // offset, expected_res 5348 { 4, 1 }, 5349 }; 5350 5351 size_t nr_test_cases = sizeof(tc) / sizeof(TestCaseBal); 5352 for (size_t i = 0; i < nr_test_cases; ++i) { 5353 CHECK_EQ(tc[i].expected_res, run_bal(tc[i].offset)); 5354 } 5355 } 5356 5357 5358 TEST(Trampoline) { 5359 // Private member of Assembler class. 5360 static const int kMaxBranchOffset = (1 << (18 - 1)) - 1; 5361 5362 CcTest::InitializeVM(); 5363 Isolate* isolate = CcTest::i_isolate(); 5364 HandleScope scope(isolate); 5365 5366 MacroAssembler assm(isolate, nullptr, 0, 5367 v8::internal::CodeObjectRequired::kYes); 5368 Label done; 5369 size_t nr_calls = kMaxBranchOffset / (2 * Instruction::kInstrSize) + 2; 5370 5371 for (size_t i = 0; i < nr_calls; ++i) { 5372 __ BranchShort(&done, eq, a0, Operand(a1)); 5373 } 5374 __ bind(&done); 5375 __ Ret(USE_DELAY_SLOT); 5376 __ mov(v0, zero_reg); 5377 5378 CodeDesc desc; 5379 assm.GetCode(&desc); 5380 Handle<Code> code = isolate->factory()->NewCode( 5381 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); 5382 F2 f = FUNCTION_CAST<F2>(code->entry()); 5383 5384 int32_t res = reinterpret_cast<int32_t>( 5385 CALL_GENERATED_CODE(isolate, f, 42, 42, 0, 0, 0)); 5386 CHECK_EQ(res, 0); 5387 } 5388 5389 #undef __ 5390