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