OLD | NEW |
(Empty) | |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are |
| 4 // met: |
| 5 // |
| 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided |
| 11 // with the distribution. |
| 12 // * Neither the name of Google Inc. nor the names of its |
| 13 // contributors may be used to endorse or promote products derived |
| 14 // from this software without specific prior written permission. |
| 15 // |
| 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 |
| 28 #include "src/v8.h" |
| 29 |
| 30 #include "src/disassembler.h" |
| 31 #include "src/factory.h" |
| 32 #include "src/ppc/assembler-ppc-inl.h" |
| 33 #include "src/ppc/simulator-ppc.h" |
| 34 #include "test/cctest/cctest.h" |
| 35 |
| 36 using namespace v8::internal; |
| 37 |
| 38 |
| 39 // Define these function prototypes to match JSEntryFunction in execution.cc. |
| 40 typedef Object* (*F1)(int x, int p1, int p2, int p3, int p4); |
| 41 typedef Object* (*F2)(int x, int y, int p2, int p3, int p4); |
| 42 typedef Object* (*F3)(void* p0, int p1, int p2, int p3, int p4); |
| 43 typedef Object* (*F4)(void* p0, void* p1, int p2, int p3, int p4); |
| 44 |
| 45 |
| 46 #define __ assm. |
| 47 |
| 48 // Simple add parameter 1 to parameter 2 and return |
| 49 TEST(0) { |
| 50 CcTest::InitializeVM(); |
| 51 Isolate* isolate = Isolate::Current(); |
| 52 HandleScope scope(isolate); |
| 53 |
| 54 Assembler assm(isolate, NULL, 0); |
| 55 |
| 56 __ function_descriptor(); |
| 57 |
| 58 __ add(r3, r3, r4); |
| 59 __ blr(); |
| 60 |
| 61 CodeDesc desc; |
| 62 assm.GetCode(&desc); |
| 63 Handle<Code> code = isolate->factory()->NewCode( |
| 64 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 65 #ifdef DEBUG |
| 66 code->Print(); |
| 67 #endif |
| 68 F2 f = FUNCTION_CAST<F2>(code->entry()); |
| 69 intptr_t res = |
| 70 reinterpret_cast<intptr_t>(CALL_GENERATED_CODE(f, 3, 4, 0, 0, 0)); |
| 71 ::printf("f() = %" V8PRIdPTR "\n", res); |
| 72 CHECK_EQ(7, static_cast<int>(res)); |
| 73 } |
| 74 |
| 75 |
| 76 // Loop 100 times, adding loop counter to result |
| 77 TEST(1) { |
| 78 CcTest::InitializeVM(); |
| 79 Isolate* isolate = Isolate::Current(); |
| 80 HandleScope scope(isolate); |
| 81 |
| 82 Assembler assm(isolate, NULL, 0); |
| 83 Label L, C; |
| 84 |
| 85 __ function_descriptor(); |
| 86 |
| 87 __ mr(r4, r3); |
| 88 __ li(r3, Operand::Zero()); |
| 89 __ b(&C); |
| 90 |
| 91 __ bind(&L); |
| 92 __ add(r3, r3, r4); |
| 93 __ subi(r4, r4, Operand(1)); |
| 94 |
| 95 __ bind(&C); |
| 96 __ cmpi(r4, Operand::Zero()); |
| 97 __ bne(&L); |
| 98 __ blr(); |
| 99 |
| 100 CodeDesc desc; |
| 101 assm.GetCode(&desc); |
| 102 Handle<Code> code = isolate->factory()->NewCode( |
| 103 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 104 #ifdef DEBUG |
| 105 code->Print(); |
| 106 #endif |
| 107 F1 f = FUNCTION_CAST<F1>(code->entry()); |
| 108 intptr_t res = |
| 109 reinterpret_cast<intptr_t>(CALL_GENERATED_CODE(f, 100, 0, 0, 0, 0)); |
| 110 ::printf("f() = %" V8PRIdPTR "\n", res); |
| 111 CHECK_EQ(5050, static_cast<int>(res)); |
| 112 } |
| 113 |
| 114 |
| 115 TEST(2) { |
| 116 CcTest::InitializeVM(); |
| 117 Isolate* isolate = Isolate::Current(); |
| 118 HandleScope scope(isolate); |
| 119 |
| 120 Assembler assm(isolate, NULL, 0); |
| 121 Label L, C; |
| 122 |
| 123 __ function_descriptor(); |
| 124 |
| 125 __ mr(r4, r3); |
| 126 __ li(r3, Operand(1)); |
| 127 __ b(&C); |
| 128 |
| 129 __ bind(&L); |
| 130 #if defined(V8_TARGET_ARCH_PPC64) |
| 131 __ mulld(r3, r4, r3); |
| 132 #else |
| 133 __ mullw(r3, r4, r3); |
| 134 #endif |
| 135 __ subi(r4, r4, Operand(1)); |
| 136 |
| 137 __ bind(&C); |
| 138 __ cmpi(r4, Operand::Zero()); |
| 139 __ bne(&L); |
| 140 __ blr(); |
| 141 |
| 142 // some relocated stuff here, not executed |
| 143 __ RecordComment("dead code, just testing relocations"); |
| 144 __ mov(r0, Operand(isolate->factory()->true_value())); |
| 145 __ RecordComment("dead code, just testing immediate operands"); |
| 146 __ mov(r0, Operand(-1)); |
| 147 __ mov(r0, Operand(0xFF000000)); |
| 148 __ mov(r0, Operand(0xF0F0F0F0)); |
| 149 __ mov(r0, Operand(0xFFF0FFFF)); |
| 150 |
| 151 CodeDesc desc; |
| 152 assm.GetCode(&desc); |
| 153 Handle<Code> code = isolate->factory()->NewCode( |
| 154 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 155 #ifdef DEBUG |
| 156 code->Print(); |
| 157 #endif |
| 158 F1 f = FUNCTION_CAST<F1>(code->entry()); |
| 159 intptr_t res = |
| 160 reinterpret_cast<intptr_t>(CALL_GENERATED_CODE(f, 10, 0, 0, 0, 0)); |
| 161 ::printf("f() = %" V8PRIdPTR "\n", res); |
| 162 CHECK_EQ(3628800, static_cast<int>(res)); |
| 163 } |
| 164 |
| 165 |
| 166 TEST(3) { |
| 167 CcTest::InitializeVM(); |
| 168 Isolate* isolate = Isolate::Current(); |
| 169 HandleScope scope(isolate); |
| 170 |
| 171 typedef struct { |
| 172 int i; |
| 173 char c; |
| 174 int16_t s; |
| 175 } T; |
| 176 T t; |
| 177 |
| 178 Assembler assm(Isolate::Current(), NULL, 0); |
| 179 Label L, C; |
| 180 |
| 181 __ function_descriptor(); |
| 182 |
| 183 // build a frame |
| 184 #if V8_TARGET_ARCH_PPC64 |
| 185 __ stdu(sp, MemOperand(sp, -32)); |
| 186 __ std(fp, MemOperand(sp, 24)); |
| 187 #else |
| 188 __ stwu(sp, MemOperand(sp, -16)); |
| 189 __ stw(fp, MemOperand(sp, 12)); |
| 190 #endif |
| 191 __ mr(fp, sp); |
| 192 |
| 193 // r4 points to our struct |
| 194 __ mr(r4, r3); |
| 195 |
| 196 // modify field int i of struct |
| 197 __ lwz(r3, MemOperand(r4, OFFSET_OF(T, i))); |
| 198 __ srwi(r5, r3, Operand(1)); |
| 199 __ stw(r5, MemOperand(r4, OFFSET_OF(T, i))); |
| 200 |
| 201 // modify field char c of struct |
| 202 __ lbz(r5, MemOperand(r4, OFFSET_OF(T, c))); |
| 203 __ add(r3, r5, r3); |
| 204 __ slwi(r5, r5, Operand(2)); |
| 205 __ stb(r5, MemOperand(r4, OFFSET_OF(T, c))); |
| 206 |
| 207 // modify field int16_t s of struct |
| 208 __ lhz(r5, MemOperand(r4, OFFSET_OF(T, s))); |
| 209 __ add(r3, r5, r3); |
| 210 __ srwi(r5, r5, Operand(3)); |
| 211 __ sth(r5, MemOperand(r4, OFFSET_OF(T, s))); |
| 212 |
| 213 // restore frame |
| 214 #if V8_TARGET_ARCH_PPC64 |
| 215 __ addi(r11, fp, Operand(32)); |
| 216 __ ld(fp, MemOperand(r11, -8)); |
| 217 #else |
| 218 __ addi(r11, fp, Operand(16)); |
| 219 __ lwz(fp, MemOperand(r11, -4)); |
| 220 #endif |
| 221 __ mr(sp, r11); |
| 222 __ blr(); |
| 223 |
| 224 CodeDesc desc; |
| 225 assm.GetCode(&desc); |
| 226 Handle<Code> code = isolate->factory()->NewCode( |
| 227 desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); |
| 228 #ifdef DEBUG |
| 229 code->Print(); |
| 230 #endif |
| 231 F3 f = FUNCTION_CAST<F3>(code->entry()); |
| 232 t.i = 100000; |
| 233 t.c = 10; |
| 234 t.s = 1000; |
| 235 intptr_t res = |
| 236 reinterpret_cast<intptr_t>(CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0)); |
| 237 ::printf("f() = %" V8PRIdPTR "\n", res); |
| 238 CHECK_EQ(101010, static_cast<int>(res)); |
| 239 CHECK_EQ(100000 / 2, t.i); |
| 240 CHECK_EQ(10 * 4, t.c); |
| 241 CHECK_EQ(1000 / 8, t.s); |
| 242 } |
| 243 |
| 244 #if 0 |
| 245 TEST(4) { |
| 246 // Test the VFP floating point instructions. |
| 247 CcTest::InitializeVM(); |
| 248 Isolate* isolate = Isolate::Current(); |
| 249 HandleScope scope(isolate); |
| 250 |
| 251 typedef struct { |
| 252 double a; |
| 253 double b; |
| 254 double c; |
| 255 double d; |
| 256 double e; |
| 257 double f; |
| 258 double g; |
| 259 double h; |
| 260 int i; |
| 261 double m; |
| 262 double n; |
| 263 float x; |
| 264 float y; |
| 265 } T; |
| 266 T t; |
| 267 |
| 268 // Create a function that accepts &t, and loads, manipulates, and stores |
| 269 // the doubles and floats. |
| 270 Assembler assm(Isolate::Current(), NULL, 0); |
| 271 Label L, C; |
| 272 |
| 273 if (CpuFeatures::IsSupported(VFP3)) { |
| 274 CpuFeatures::Scope scope(VFP3); |
| 275 |
| 276 __ mov(ip, Operand(sp)); |
| 277 __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit()); |
| 278 __ sub(fp, ip, Operand(4)); |
| 279 |
| 280 __ mov(r4, Operand(r0)); |
| 281 __ vldr(d6, r4, OFFSET_OF(T, a)); |
| 282 __ vldr(d7, r4, OFFSET_OF(T, b)); |
| 283 __ vadd(d5, d6, d7); |
| 284 __ vstr(d5, r4, OFFSET_OF(T, c)); |
| 285 |
| 286 __ vmov(r2, r3, d5); |
| 287 __ vmov(d4, r2, r3); |
| 288 __ vstr(d4, r4, OFFSET_OF(T, b)); |
| 289 |
| 290 // Load t.x and t.y, switch values, and store back to the struct. |
| 291 __ vldr(s0, r4, OFFSET_OF(T, x)); |
| 292 __ vldr(s31, r4, OFFSET_OF(T, y)); |
| 293 __ vmov(s16, s0); |
| 294 __ vmov(s0, s31); |
| 295 __ vmov(s31, s16); |
| 296 __ vstr(s0, r4, OFFSET_OF(T, x)); |
| 297 __ vstr(s31, r4, OFFSET_OF(T, y)); |
| 298 |
| 299 // Move a literal into a register that can be encoded in the instruction. |
| 300 __ vmov(d4, 1.0); |
| 301 __ vstr(d4, r4, OFFSET_OF(T, e)); |
| 302 |
| 303 // Move a literal into a register that requires 64 bits to encode. |
| 304 // 0x3ff0000010000000 = 1.000000059604644775390625 |
| 305 __ vmov(d4, 1.000000059604644775390625); |
| 306 __ vstr(d4, r4, OFFSET_OF(T, d)); |
| 307 |
| 308 // Convert from floating point to integer. |
| 309 __ vmov(d4, 2.0); |
| 310 __ vcvt_s32_f64(s31, d4); |
| 311 __ vstr(s31, r4, OFFSET_OF(T, i)); |
| 312 |
| 313 // Convert from integer to floating point. |
| 314 __ mov(lr, Operand(42)); |
| 315 __ vmov(s31, lr); |
| 316 __ vcvt_f64_s32(d4, s31); |
| 317 __ vstr(d4, r4, OFFSET_OF(T, f)); |
| 318 |
| 319 // Test vabs. |
| 320 __ vldr(d1, r4, OFFSET_OF(T, g)); |
| 321 __ vabs(d0, d1); |
| 322 __ vstr(d0, r4, OFFSET_OF(T, g)); |
| 323 __ vldr(d2, r4, OFFSET_OF(T, h)); |
| 324 __ vabs(d0, d2); |
| 325 __ vstr(d0, r4, OFFSET_OF(T, h)); |
| 326 |
| 327 // Test vneg. |
| 328 __ vldr(d1, r4, OFFSET_OF(T, m)); |
| 329 __ vneg(d0, d1); |
| 330 __ vstr(d0, r4, OFFSET_OF(T, m)); |
| 331 __ vldr(d1, r4, OFFSET_OF(T, n)); |
| 332 __ vneg(d0, d1); |
| 333 __ vstr(d0, r4, OFFSET_OF(T, n)); |
| 334 |
| 335 __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit()); |
| 336 |
| 337 CodeDesc desc; |
| 338 assm.GetCode(&desc); |
| 339 Object* code = isolate->heap()->CreateCode( |
| 340 desc, |
| 341 Code::ComputeFlags(Code::STUB), |
| 342 Handle<Code>())->ToObjectChecked(); |
| 343 CHECK(code->IsCode()); |
| 344 #ifdef DEBUG |
| 345 Code::cast(code)->Print(); |
| 346 #endif |
| 347 F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry()); |
| 348 t.a = 1.5; |
| 349 t.b = 2.75; |
| 350 t.c = 17.17; |
| 351 t.d = 0.0; |
| 352 t.e = 0.0; |
| 353 t.f = 0.0; |
| 354 t.g = -2718.2818; |
| 355 t.h = 31415926.5; |
| 356 t.i = 0; |
| 357 t.m = -2718.2818; |
| 358 t.n = 123.456; |
| 359 t.x = 4.5; |
| 360 t.y = 9.0; |
| 361 Object* dummy = CALL_GENERATED_CODE(f, &t, 0, 0, 0, 0); |
| 362 USE(dummy); |
| 363 CHECK_EQ(4.5, t.y); |
| 364 CHECK_EQ(9.0, t.x); |
| 365 CHECK_EQ(-123.456, t.n); |
| 366 CHECK_EQ(2718.2818, t.m); |
| 367 CHECK_EQ(2, t.i); |
| 368 CHECK_EQ(2718.2818, t.g); |
| 369 CHECK_EQ(31415926.5, t.h); |
| 370 CHECK_EQ(42.0, t.f); |
| 371 CHECK_EQ(1.0, t.e); |
| 372 CHECK_EQ(1.000000059604644775390625, t.d); |
| 373 CHECK_EQ(4.25, t.c); |
| 374 CHECK_EQ(4.25, t.b); |
| 375 CHECK_EQ(1.5, t.a); |
| 376 } |
| 377 } |
| 378 |
| 379 |
| 380 TEST(5) { |
| 381 // Test the ARMv7 bitfield instructions. |
| 382 CcTest::InitializeVM(); |
| 383 Isolate* isolate = Isolate::Current(); |
| 384 HandleScope scope(isolate); |
| 385 |
| 386 Assembler assm(isolate, NULL, 0); |
| 387 |
| 388 if (CpuFeatures::IsSupported(ARMv7)) { |
| 389 CpuFeatures::Scope scope(ARMv7); |
| 390 // On entry, r0 = 0xAAAAAAAA = 0b10..10101010. |
| 391 __ ubfx(r0, r0, 1, 12); // 0b00..010101010101 = 0x555 |
| 392 __ sbfx(r0, r0, 0, 5); // 0b11..111111110101 = -11 |
| 393 __ bfc(r0, 1, 3); // 0b11..111111110001 = -15 |
| 394 __ mov(r1, Operand(7)); |
| 395 __ bfi(r0, r1, 3, 3); // 0b11..111111111001 = -7 |
| 396 __ mov(pc, Operand(lr)); |
| 397 |
| 398 CodeDesc desc; |
| 399 assm.GetCode(&desc); |
| 400 Object* code = isolate->heap()->CreateCode( |
| 401 desc, |
| 402 Code::ComputeFlags(Code::STUB), |
| 403 Handle<Code>())->ToObjectChecked(); |
| 404 CHECK(code->IsCode()); |
| 405 #ifdef DEBUG |
| 406 Code::cast(code)->Print(); |
| 407 #endif |
| 408 F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry()); |
| 409 int res = reinterpret_cast<int>( |
| 410 CALL_GENERATED_CODE(f, 0xAAAAAAAA, 0, 0, 0, 0)); |
| 411 ::printf("f() = %d\n", res); |
| 412 CHECK_EQ(-7, res); |
| 413 } |
| 414 } |
| 415 |
| 416 |
| 417 TEST(6) { |
| 418 // Test saturating instructions. |
| 419 CcTest::InitializeVM(); |
| 420 Isolate* isolate = Isolate::Current(); |
| 421 HandleScope scope(isolate); |
| 422 |
| 423 Assembler assm(isolate, NULL, 0); |
| 424 |
| 425 if (CpuFeatures::IsSupported(ARMv7)) { |
| 426 CpuFeatures::Scope scope(ARMv7); |
| 427 __ usat(r1, 8, Operand(r0)); // Sat 0xFFFF to 0-255 = 0xFF. |
| 428 __ usat(r2, 12, Operand(r0, ASR, 9)); // Sat (0xFFFF>>9) to 0-4095 = 0x7F. |
| 429 __ usat(r3, 1, Operand(r0, LSL, 16)); // Sat (0xFFFF<<16) to 0-1 = 0x0. |
| 430 __ addi(r0, r1, Operand(r2)); |
| 431 __ addi(r0, r0, Operand(r3)); |
| 432 __ mov(pc, Operand(lr)); |
| 433 |
| 434 CodeDesc desc; |
| 435 assm.GetCode(&desc); |
| 436 Object* code = isolate->heap()->CreateCode( |
| 437 desc, |
| 438 Code::ComputeFlags(Code::STUB), |
| 439 Handle<Code>())->ToObjectChecked(); |
| 440 CHECK(code->IsCode()); |
| 441 #ifdef DEBUG |
| 442 Code::cast(code)->Print(); |
| 443 #endif |
| 444 F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry()); |
| 445 int res = reinterpret_cast<int>( |
| 446 CALL_GENERATED_CODE(f, 0xFFFF, 0, 0, 0, 0)); |
| 447 ::printf("f() = %d\n", res); |
| 448 CHECK_EQ(382, res); |
| 449 } |
| 450 } |
| 451 |
| 452 enum VCVTTypes { |
| 453 s32_f64, |
| 454 u32_f64 |
| 455 }; |
| 456 |
| 457 static void TestRoundingMode(VCVTTypes types, |
| 458 VFPRoundingMode mode, |
| 459 double value, |
| 460 int expected, |
| 461 bool expected_exception = false) { |
| 462 CcTest::InitializeVM(); |
| 463 Isolate* isolate = Isolate::Current(); |
| 464 HandleScope scope(isolate); |
| 465 |
| 466 Assembler assm(isolate, NULL, 0); |
| 467 |
| 468 if (CpuFeatures::IsSupported(VFP3)) { |
| 469 CpuFeatures::Scope scope(VFP3); |
| 470 |
| 471 Label wrong_exception; |
| 472 |
| 473 __ vmrs(r1); |
| 474 // Set custom FPSCR. |
| 475 __ bic(r2, r1, Operand(kVFPRoundingModeMask | kVFPExceptionMask)); |
| 476 __ orr(r2, r2, Operand(mode)); |
| 477 __ vmsr(r2); |
| 478 |
| 479 // Load value, convert, and move back result to r0 if everything went well. |
| 480 __ vmov(d1, value); |
| 481 switch (types) { |
| 482 case s32_f64: |
| 483 __ vcvt_s32_f64(s0, d1, kFPSCRRounding); |
| 484 break; |
| 485 |
| 486 case u32_f64: |
| 487 __ vcvt_u32_f64(s0, d1, kFPSCRRounding); |
| 488 break; |
| 489 |
| 490 default: |
| 491 UNREACHABLE(); |
| 492 break; |
| 493 } |
| 494 // Check for vfp exceptions |
| 495 __ vmrs(r2); |
| 496 __ tst(r2, Operand(kVFPExceptionMask)); |
| 497 // Check that we behaved as expected. |
| 498 __ b(&wrong_exception, |
| 499 expected_exception ? eq : ne); |
| 500 // There was no exception. Retrieve the result and return. |
| 501 __ vmov(r0, s0); |
| 502 __ mov(pc, Operand(lr)); |
| 503 |
| 504 // The exception behaviour is not what we expected. |
| 505 // Load a special value and return. |
| 506 __ bind(&wrong_exception); |
| 507 __ mov(r0, Operand(11223344)); |
| 508 __ mov(pc, Operand(lr)); |
| 509 |
| 510 CodeDesc desc; |
| 511 assm.GetCode(&desc); |
| 512 Object* code = isolate->heap()->CreateCode( |
| 513 desc, |
| 514 Code::ComputeFlags(Code::STUB), |
| 515 Handle<Code>())->ToObjectChecked(); |
| 516 CHECK(code->IsCode()); |
| 517 #ifdef DEBUG |
| 518 Code::cast(code)->Print(); |
| 519 #endif |
| 520 F1 f = FUNCTION_CAST<F1>(Code::cast(code)->entry()); |
| 521 int res = reinterpret_cast<int>( |
| 522 CALL_GENERATED_CODE(f, 0, 0, 0, 0, 0)); |
| 523 ::printf("res = %d\n", res); |
| 524 CHECK_EQ(expected, res); |
| 525 } |
| 526 } |
| 527 |
| 528 |
| 529 TEST(7) { |
| 530 // Test vfp rounding modes. |
| 531 |
| 532 // s32_f64 (double to integer). |
| 533 |
| 534 TestRoundingMode(s32_f64, RN, 0, 0); |
| 535 TestRoundingMode(s32_f64, RN, 0.5, 0); |
| 536 TestRoundingMode(s32_f64, RN, -0.5, 0); |
| 537 TestRoundingMode(s32_f64, RN, 1.5, 2); |
| 538 TestRoundingMode(s32_f64, RN, -1.5, -2); |
| 539 TestRoundingMode(s32_f64, RN, 123.7, 124); |
| 540 TestRoundingMode(s32_f64, RN, -123.7, -124); |
| 541 TestRoundingMode(s32_f64, RN, 123456.2, 123456); |
| 542 TestRoundingMode(s32_f64, RN, -123456.2, -123456); |
| 543 TestRoundingMode(s32_f64, RN, static_cast<double>(kMaxInt), kMaxInt); |
| 544 TestRoundingMode(s32_f64, RN, (kMaxInt + 0.49), kMaxInt); |
| 545 TestRoundingMode(s32_f64, RN, (kMaxInt + 1.0), kMaxInt, true); |
| 546 TestRoundingMode(s32_f64, RN, (kMaxInt + 0.5), kMaxInt, true); |
| 547 TestRoundingMode(s32_f64, RN, static_cast<double>(kMinInt), kMinInt); |
| 548 TestRoundingMode(s32_f64, RN, (kMinInt - 0.5), kMinInt); |
| 549 TestRoundingMode(s32_f64, RN, (kMinInt - 1.0), kMinInt, true); |
| 550 TestRoundingMode(s32_f64, RN, (kMinInt - 0.51), kMinInt, true); |
| 551 |
| 552 TestRoundingMode(s32_f64, RM, 0, 0); |
| 553 TestRoundingMode(s32_f64, RM, 0.5, 0); |
| 554 TestRoundingMode(s32_f64, RM, -0.5, -1); |
| 555 TestRoundingMode(s32_f64, RM, 123.7, 123); |
| 556 TestRoundingMode(s32_f64, RM, -123.7, -124); |
| 557 TestRoundingMode(s32_f64, RM, 123456.2, 123456); |
| 558 TestRoundingMode(s32_f64, RM, -123456.2, -123457); |
| 559 TestRoundingMode(s32_f64, RM, static_cast<double>(kMaxInt), kMaxInt); |
| 560 TestRoundingMode(s32_f64, RM, (kMaxInt + 0.5), kMaxInt); |
| 561 TestRoundingMode(s32_f64, RM, (kMaxInt + 1.0), kMaxInt, true); |
| 562 TestRoundingMode(s32_f64, RM, static_cast<double>(kMinInt), kMinInt); |
| 563 TestRoundingMode(s32_f64, RM, (kMinInt - 0.5), kMinInt, true); |
| 564 TestRoundingMode(s32_f64, RM, (kMinInt + 0.5), kMinInt); |
| 565 |
| 566 TestRoundingMode(s32_f64, RZ, 0, 0); |
| 567 TestRoundingMode(s32_f64, RZ, 0.5, 0); |
| 568 TestRoundingMode(s32_f64, RZ, -0.5, 0); |
| 569 TestRoundingMode(s32_f64, RZ, 123.7, 123); |
| 570 TestRoundingMode(s32_f64, RZ, -123.7, -123); |
| 571 TestRoundingMode(s32_f64, RZ, 123456.2, 123456); |
| 572 TestRoundingMode(s32_f64, RZ, -123456.2, -123456); |
| 573 TestRoundingMode(s32_f64, RZ, static_cast<double>(kMaxInt), kMaxInt); |
| 574 TestRoundingMode(s32_f64, RZ, (kMaxInt + 0.5), kMaxInt); |
| 575 TestRoundingMode(s32_f64, RZ, (kMaxInt + 1.0), kMaxInt, true); |
| 576 TestRoundingMode(s32_f64, RZ, static_cast<double>(kMinInt), kMinInt); |
| 577 TestRoundingMode(s32_f64, RZ, (kMinInt - 0.5), kMinInt); |
| 578 TestRoundingMode(s32_f64, RZ, (kMinInt - 1.0), kMinInt, true); |
| 579 |
| 580 |
| 581 // u32_f64 (double to integer). |
| 582 |
| 583 // Negative values. |
| 584 TestRoundingMode(u32_f64, RN, -0.5, 0); |
| 585 TestRoundingMode(u32_f64, RN, -123456.7, 0, true); |
| 586 TestRoundingMode(u32_f64, RN, static_cast<double>(kMinInt), 0, true); |
| 587 TestRoundingMode(u32_f64, RN, kMinInt - 1.0, 0, true); |
| 588 |
| 589 TestRoundingMode(u32_f64, RM, -0.5, 0, true); |
| 590 TestRoundingMode(u32_f64, RM, -123456.7, 0, true); |
| 591 TestRoundingMode(u32_f64, RM, static_cast<double>(kMinInt), 0, true); |
| 592 TestRoundingMode(u32_f64, RM, kMinInt - 1.0, 0, true); |
| 593 |
| 594 TestRoundingMode(u32_f64, RZ, -0.5, 0); |
| 595 TestRoundingMode(u32_f64, RZ, -123456.7, 0, true); |
| 596 TestRoundingMode(u32_f64, RZ, static_cast<double>(kMinInt), 0, true); |
| 597 TestRoundingMode(u32_f64, RZ, kMinInt - 1.0, 0, true); |
| 598 |
| 599 // Positive values. |
| 600 // kMaxInt is the maximum *signed* integer: 0x7fffffff. |
| 601 static const uint32_t kMaxUInt = 0xffffffffu; |
| 602 TestRoundingMode(u32_f64, RZ, 0, 0); |
| 603 TestRoundingMode(u32_f64, RZ, 0.5, 0); |
| 604 TestRoundingMode(u32_f64, RZ, 123.7, 123); |
| 605 TestRoundingMode(u32_f64, RZ, 123456.2, 123456); |
| 606 TestRoundingMode(u32_f64, RZ, static_cast<double>(kMaxInt), kMaxInt); |
| 607 TestRoundingMode(u32_f64, RZ, (kMaxInt + 0.5), kMaxInt); |
| 608 TestRoundingMode(u32_f64, RZ, (kMaxInt + 1.0), |
| 609 static_cast<uint32_t>(kMaxInt) + 1); |
| 610 TestRoundingMode(u32_f64, RZ, (kMaxUInt + 0.5), kMaxUInt); |
| 611 TestRoundingMode(u32_f64, RZ, (kMaxUInt + 1.0), kMaxUInt, true); |
| 612 |
| 613 TestRoundingMode(u32_f64, RM, 0, 0); |
| 614 TestRoundingMode(u32_f64, RM, 0.5, 0); |
| 615 TestRoundingMode(u32_f64, RM, 123.7, 123); |
| 616 TestRoundingMode(u32_f64, RM, 123456.2, 123456); |
| 617 TestRoundingMode(u32_f64, RM, static_cast<double>(kMaxInt), kMaxInt); |
| 618 TestRoundingMode(u32_f64, RM, (kMaxInt + 0.5), kMaxInt); |
| 619 TestRoundingMode(u32_f64, RM, (kMaxInt + 1.0), |
| 620 static_cast<uint32_t>(kMaxInt) + 1); |
| 621 TestRoundingMode(u32_f64, RM, (kMaxUInt + 0.5), kMaxUInt); |
| 622 TestRoundingMode(u32_f64, RM, (kMaxUInt + 1.0), kMaxUInt, true); |
| 623 |
| 624 TestRoundingMode(u32_f64, RN, 0, 0); |
| 625 TestRoundingMode(u32_f64, RN, 0.5, 0); |
| 626 TestRoundingMode(u32_f64, RN, 1.5, 2); |
| 627 TestRoundingMode(u32_f64, RN, 123.7, 124); |
| 628 TestRoundingMode(u32_f64, RN, 123456.2, 123456); |
| 629 TestRoundingMode(u32_f64, RN, static_cast<double>(kMaxInt), kMaxInt); |
| 630 TestRoundingMode(u32_f64, RN, (kMaxInt + 0.49), kMaxInt); |
| 631 TestRoundingMode(u32_f64, RN, (kMaxInt + 0.5), |
| 632 static_cast<uint32_t>(kMaxInt) + 1); |
| 633 TestRoundingMode(u32_f64, RN, (kMaxUInt + 0.49), kMaxUInt); |
| 634 TestRoundingMode(u32_f64, RN, (kMaxUInt + 0.5), kMaxUInt, true); |
| 635 TestRoundingMode(u32_f64, RN, (kMaxUInt + 1.0), kMaxUInt, true); |
| 636 } |
| 637 |
| 638 |
| 639 TEST(8) { |
| 640 // Test VFP multi load/store with ia_w. |
| 641 CcTest::InitializeVM(); |
| 642 Isolate* isolate = Isolate::Current(); |
| 643 HandleScope scope(isolate); |
| 644 |
| 645 typedef struct { |
| 646 double a; |
| 647 double b; |
| 648 double c; |
| 649 double d; |
| 650 double e; |
| 651 double f; |
| 652 double g; |
| 653 double h; |
| 654 } D; |
| 655 D d; |
| 656 |
| 657 typedef struct { |
| 658 float a; |
| 659 float b; |
| 660 float c; |
| 661 float d; |
| 662 float e; |
| 663 float f; |
| 664 float g; |
| 665 float h; |
| 666 } F; |
| 667 F f; |
| 668 |
| 669 // Create a function that uses vldm/vstm to move some double and |
| 670 // single precision values around in memory. |
| 671 Assembler assm(isolate, NULL, 0); |
| 672 |
| 673 if (CpuFeatures::IsSupported(VFP2)) { |
| 674 CpuFeatures::Scope scope(VFP2); |
| 675 |
| 676 __ mov(ip, Operand(sp)); |
| 677 __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit()); |
| 678 __ sub(fp, ip, Operand(4)); |
| 679 |
| 680 __ addi(r4, r0, Operand(OFFSET_OF(D, a))); |
| 681 __ vldm(ia_w, r4, d0, d3); |
| 682 __ vldm(ia_w, r4, d4, d7); |
| 683 |
| 684 __ addi(r4, r0, Operand(OFFSET_OF(D, a))); |
| 685 __ vstm(ia_w, r4, d6, d7); |
| 686 __ vstm(ia_w, r4, d0, d5); |
| 687 |
| 688 __ addi(r4, r1, Operand(OFFSET_OF(F, a))); |
| 689 __ vldm(ia_w, r4, s0, s3); |
| 690 __ vldm(ia_w, r4, s4, s7); |
| 691 |
| 692 __ addi(r4, r1, Operand(OFFSET_OF(F, a))); |
| 693 __ vstm(ia_w, r4, s6, s7); |
| 694 __ vstm(ia_w, r4, s0, s5); |
| 695 |
| 696 __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit()); |
| 697 |
| 698 CodeDesc desc; |
| 699 assm.GetCode(&desc); |
| 700 Object* code = isolate->heap()->CreateCode( |
| 701 desc, |
| 702 Code::ComputeFlags(Code::STUB), |
| 703 Handle<Code>())->ToObjectChecked(); |
| 704 CHECK(code->IsCode()); |
| 705 #ifdef DEBUG |
| 706 Code::cast(code)->Print(); |
| 707 #endif |
| 708 F4 fn = FUNCTION_CAST<F4>(Code::cast(code)->entry()); |
| 709 d.a = 1.1; |
| 710 d.b = 2.2; |
| 711 d.c = 3.3; |
| 712 d.d = 4.4; |
| 713 d.e = 5.5; |
| 714 d.f = 6.6; |
| 715 d.g = 7.7; |
| 716 d.h = 8.8; |
| 717 |
| 718 f.a = 1.0; |
| 719 f.b = 2.0; |
| 720 f.c = 3.0; |
| 721 f.d = 4.0; |
| 722 f.e = 5.0; |
| 723 f.f = 6.0; |
| 724 f.g = 7.0; |
| 725 f.h = 8.0; |
| 726 |
| 727 Object* dummy = CALL_GENERATED_CODE(fn, &d, &f, 0, 0, 0); |
| 728 USE(dummy); |
| 729 |
| 730 CHECK_EQ(7.7, d.a); |
| 731 CHECK_EQ(8.8, d.b); |
| 732 CHECK_EQ(1.1, d.c); |
| 733 CHECK_EQ(2.2, d.d); |
| 734 CHECK_EQ(3.3, d.e); |
| 735 CHECK_EQ(4.4, d.f); |
| 736 CHECK_EQ(5.5, d.g); |
| 737 CHECK_EQ(6.6, d.h); |
| 738 |
| 739 CHECK_EQ(7.0, f.a); |
| 740 CHECK_EQ(8.0, f.b); |
| 741 CHECK_EQ(1.0, f.c); |
| 742 CHECK_EQ(2.0, f.d); |
| 743 CHECK_EQ(3.0, f.e); |
| 744 CHECK_EQ(4.0, f.f); |
| 745 CHECK_EQ(5.0, f.g); |
| 746 CHECK_EQ(6.0, f.h); |
| 747 } |
| 748 } |
| 749 |
| 750 |
| 751 TEST(9) { |
| 752 // Test VFP multi load/store with ia. |
| 753 CcTest::InitializeVM(); |
| 754 Isolate* isolate = Isolate::Current(); |
| 755 HandleScope scope(isolate); |
| 756 |
| 757 typedef struct { |
| 758 double a; |
| 759 double b; |
| 760 double c; |
| 761 double d; |
| 762 double e; |
| 763 double f; |
| 764 double g; |
| 765 double h; |
| 766 } D; |
| 767 D d; |
| 768 |
| 769 typedef struct { |
| 770 float a; |
| 771 float b; |
| 772 float c; |
| 773 float d; |
| 774 float e; |
| 775 float f; |
| 776 float g; |
| 777 float h; |
| 778 } F; |
| 779 F f; |
| 780 |
| 781 // Create a function that uses vldm/vstm to move some double and |
| 782 // single precision values around in memory. |
| 783 Assembler assm(isolate, NULL, 0); |
| 784 |
| 785 if (CpuFeatures::IsSupported(VFP2)) { |
| 786 CpuFeatures::Scope scope(VFP2); |
| 787 |
| 788 __ mov(ip, Operand(sp)); |
| 789 __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit()); |
| 790 __ sub(fp, ip, Operand(4)); |
| 791 |
| 792 __ addi(r4, r0, Operand(OFFSET_OF(D, a))); |
| 793 __ vldm(ia, r4, d0, d3); |
| 794 __ addi(r4, r4, Operand(4 * 8)); |
| 795 __ vldm(ia, r4, d4, d7); |
| 796 |
| 797 __ addi(r4, r0, Operand(OFFSET_OF(D, a))); |
| 798 __ vstm(ia, r4, d6, d7); |
| 799 __ addi(r4, r4, Operand(2 * 8)); |
| 800 __ vstm(ia, r4, d0, d5); |
| 801 |
| 802 __ addi(r4, r1, Operand(OFFSET_OF(F, a))); |
| 803 __ vldm(ia, r4, s0, s3); |
| 804 __ addi(r4, r4, Operand(4 * 4)); |
| 805 __ vldm(ia, r4, s4, s7); |
| 806 |
| 807 __ addi(r4, r1, Operand(OFFSET_OF(F, a))); |
| 808 __ vstm(ia, r4, s6, s7); |
| 809 __ addi(r4, r4, Operand(2 * 4)); |
| 810 __ vstm(ia, r4, s0, s5); |
| 811 |
| 812 __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit()); |
| 813 |
| 814 CodeDesc desc; |
| 815 assm.GetCode(&desc); |
| 816 Object* code = isolate->heap()->CreateCode( |
| 817 desc, |
| 818 Code::ComputeFlags(Code::STUB), |
| 819 Handle<Code>())->ToObjectChecked(); |
| 820 CHECK(code->IsCode()); |
| 821 #ifdef DEBUG |
| 822 Code::cast(code)->Print(); |
| 823 #endif |
| 824 F4 fn = FUNCTION_CAST<F4>(Code::cast(code)->entry()); |
| 825 d.a = 1.1; |
| 826 d.b = 2.2; |
| 827 d.c = 3.3; |
| 828 d.d = 4.4; |
| 829 d.e = 5.5; |
| 830 d.f = 6.6; |
| 831 d.g = 7.7; |
| 832 d.h = 8.8; |
| 833 |
| 834 f.a = 1.0; |
| 835 f.b = 2.0; |
| 836 f.c = 3.0; |
| 837 f.d = 4.0; |
| 838 f.e = 5.0; |
| 839 f.f = 6.0; |
| 840 f.g = 7.0; |
| 841 f.h = 8.0; |
| 842 |
| 843 Object* dummy = CALL_GENERATED_CODE(fn, &d, &f, 0, 0, 0); |
| 844 USE(dummy); |
| 845 |
| 846 CHECK_EQ(7.7, d.a); |
| 847 CHECK_EQ(8.8, d.b); |
| 848 CHECK_EQ(1.1, d.c); |
| 849 CHECK_EQ(2.2, d.d); |
| 850 CHECK_EQ(3.3, d.e); |
| 851 CHECK_EQ(4.4, d.f); |
| 852 CHECK_EQ(5.5, d.g); |
| 853 CHECK_EQ(6.6, d.h); |
| 854 |
| 855 CHECK_EQ(7.0, f.a); |
| 856 CHECK_EQ(8.0, f.b); |
| 857 CHECK_EQ(1.0, f.c); |
| 858 CHECK_EQ(2.0, f.d); |
| 859 CHECK_EQ(3.0, f.e); |
| 860 CHECK_EQ(4.0, f.f); |
| 861 CHECK_EQ(5.0, f.g); |
| 862 CHECK_EQ(6.0, f.h); |
| 863 } |
| 864 } |
| 865 |
| 866 |
| 867 TEST(10) { |
| 868 // Test VFP multi load/store with db_w. |
| 869 CcTest::InitializeVM(); |
| 870 Isolate* isolate = Isolate::Current(); |
| 871 HandleScope scope(isolate); |
| 872 |
| 873 typedef struct { |
| 874 double a; |
| 875 double b; |
| 876 double c; |
| 877 double d; |
| 878 double e; |
| 879 double f; |
| 880 double g; |
| 881 double h; |
| 882 } D; |
| 883 D d; |
| 884 |
| 885 typedef struct { |
| 886 float a; |
| 887 float b; |
| 888 float c; |
| 889 float d; |
| 890 float e; |
| 891 float f; |
| 892 float g; |
| 893 float h; |
| 894 } F; |
| 895 F f; |
| 896 |
| 897 // Create a function that uses vldm/vstm to move some double and |
| 898 // single precision values around in memory. |
| 899 Assembler assm(isolate, NULL, 0); |
| 900 |
| 901 if (CpuFeatures::IsSupported(VFP2)) { |
| 902 CpuFeatures::Scope scope(VFP2); |
| 903 |
| 904 __ mov(ip, Operand(sp)); |
| 905 __ stm(db_w, sp, r4.bit() | fp.bit() | lr.bit()); |
| 906 __ sub(fp, ip, Operand(4)); |
| 907 |
| 908 __ addi(r4, r0, Operand(OFFSET_OF(D, h) + 8)); |
| 909 __ vldm(db_w, r4, d4, d7); |
| 910 __ vldm(db_w, r4, d0, d3); |
| 911 |
| 912 __ addi(r4, r0, Operand(OFFSET_OF(D, h) + 8)); |
| 913 __ vstm(db_w, r4, d0, d5); |
| 914 __ vstm(db_w, r4, d6, d7); |
| 915 |
| 916 __ addi(r4, r1, Operand(OFFSET_OF(F, h) + 4)); |
| 917 __ vldm(db_w, r4, s4, s7); |
| 918 __ vldm(db_w, r4, s0, s3); |
| 919 |
| 920 __ addi(r4, r1, Operand(OFFSET_OF(F, h) + 4)); |
| 921 __ vstm(db_w, r4, s0, s5); |
| 922 __ vstm(db_w, r4, s6, s7); |
| 923 |
| 924 __ ldm(ia_w, sp, r4.bit() | fp.bit() | pc.bit()); |
| 925 |
| 926 CodeDesc desc; |
| 927 assm.GetCode(&desc); |
| 928 Object* code = isolate->heap()->CreateCode( |
| 929 desc, |
| 930 Code::ComputeFlags(Code::STUB), |
| 931 Handle<Code>())->ToObjectChecked(); |
| 932 CHECK(code->IsCode()); |
| 933 #ifdef DEBUG |
| 934 Code::cast(code)->Print(); |
| 935 #endif |
| 936 F4 fn = FUNCTION_CAST<F4>(Code::cast(code)->entry()); |
| 937 d.a = 1.1; |
| 938 d.b = 2.2; |
| 939 d.c = 3.3; |
| 940 d.d = 4.4; |
| 941 d.e = 5.5; |
| 942 d.f = 6.6; |
| 943 d.g = 7.7; |
| 944 d.h = 8.8; |
| 945 |
| 946 f.a = 1.0; |
| 947 f.b = 2.0; |
| 948 f.c = 3.0; |
| 949 f.d = 4.0; |
| 950 f.e = 5.0; |
| 951 f.f = 6.0; |
| 952 f.g = 7.0; |
| 953 f.h = 8.0; |
| 954 |
| 955 Object* dummy = CALL_GENERATED_CODE(fn, &d, &f, 0, 0, 0); |
| 956 USE(dummy); |
| 957 |
| 958 CHECK_EQ(7.7, d.a); |
| 959 CHECK_EQ(8.8, d.b); |
| 960 CHECK_EQ(1.1, d.c); |
| 961 CHECK_EQ(2.2, d.d); |
| 962 CHECK_EQ(3.3, d.e); |
| 963 CHECK_EQ(4.4, d.f); |
| 964 CHECK_EQ(5.5, d.g); |
| 965 CHECK_EQ(6.6, d.h); |
| 966 |
| 967 CHECK_EQ(7.0, f.a); |
| 968 CHECK_EQ(8.0, f.b); |
| 969 CHECK_EQ(1.0, f.c); |
| 970 CHECK_EQ(2.0, f.d); |
| 971 CHECK_EQ(3.0, f.e); |
| 972 CHECK_EQ(4.0, f.f); |
| 973 CHECK_EQ(5.0, f.g); |
| 974 CHECK_EQ(6.0, f.h); |
| 975 } |
| 976 } |
| 977 |
| 978 |
| 979 TEST(11) { |
| 980 // Test instructions using the carry flag. |
| 981 CcTest::InitializeVM(); |
| 982 Isolate* isolate = Isolate::Current(); |
| 983 HandleScope scope(isolate); |
| 984 |
| 985 typedef struct { |
| 986 int32_t a; |
| 987 int32_t b; |
| 988 int32_t c; |
| 989 int32_t d; |
| 990 } I; |
| 991 I i; |
| 992 |
| 993 i.a = 0xabcd0001; |
| 994 i.b = 0xabcd0000; |
| 995 |
| 996 Assembler assm(isolate, NULL, 0); |
| 997 |
| 998 // Test HeapObject untagging. |
| 999 __ ldr(r1, MemOperand(r0, OFFSET_OF(I, a))); |
| 1000 __ mov(r1, Operand(r1, ASR, 1), SetCC); |
| 1001 __ adc(r1, r1, Operand(r1), LeaveCC, cs); |
| 1002 __ str(r1, MemOperand(r0, OFFSET_OF(I, a))); |
| 1003 |
| 1004 __ ldr(r2, MemOperand(r0, OFFSET_OF(I, b))); |
| 1005 __ mov(r2, Operand(r2, ASR, 1), SetCC); |
| 1006 __ adc(r2, r2, Operand(r2), LeaveCC, cs); |
| 1007 __ str(r2, MemOperand(r0, OFFSET_OF(I, b))); |
| 1008 |
| 1009 // Test corner cases. |
| 1010 __ mov(r1, Operand(0xffffffff)); |
| 1011 __ mov(r2, Operand::Zero()); |
| 1012 __ mov(r3, Operand(r1, ASR, 1), SetCC); // Set the carry. |
| 1013 __ adc(r3, r1, Operand(r2)); |
| 1014 __ str(r3, MemOperand(r0, OFFSET_OF(I, c))); |
| 1015 |
| 1016 __ mov(r1, Operand(0xffffffff)); |
| 1017 __ mov(r2, Operand::Zero()); |
| 1018 __ mov(r3, Operand(r2, ASR, 1), SetCC); // Unset the carry. |
| 1019 __ adc(r3, r1, Operand(r2)); |
| 1020 __ str(r3, MemOperand(r0, OFFSET_OF(I, d))); |
| 1021 |
| 1022 __ mov(pc, Operand(lr)); |
| 1023 |
| 1024 CodeDesc desc; |
| 1025 assm.GetCode(&desc); |
| 1026 Object* code = isolate->heap()->CreateCode( |
| 1027 desc, |
| 1028 Code::ComputeFlags(Code::STUB), |
| 1029 Handle<Code>())->ToObjectChecked(); |
| 1030 CHECK(code->IsCode()); |
| 1031 #ifdef DEBUG |
| 1032 Code::cast(code)->Print(); |
| 1033 #endif |
| 1034 F3 f = FUNCTION_CAST<F3>(Code::cast(code)->entry()); |
| 1035 Object* dummy = CALL_GENERATED_CODE(f, &i, 0, 0, 0, 0); |
| 1036 USE(dummy); |
| 1037 |
| 1038 CHECK_EQ(0xabcd0001, i.a); |
| 1039 CHECK_EQ(static_cast<int32_t>(0xabcd0000) >> 1, i.b); |
| 1040 CHECK_EQ(0x00000000, i.c); |
| 1041 CHECK_EQ(0xffffffff, i.d); |
| 1042 } |
| 1043 |
| 1044 |
| 1045 TEST(12) { |
| 1046 // Test chaining of label usages within instructions (issue 1644). |
| 1047 CcTest::InitializeVM(); |
| 1048 Isolate* isolate = Isolate::Current(); |
| 1049 HandleScope scope(isolate); |
| 1050 |
| 1051 Assembler assm(isolate, NULL, 0); |
| 1052 Label target; |
| 1053 __ b(eq, &target); |
| 1054 __ b(ne, &target); |
| 1055 __ bind(&target); |
| 1056 __ nop(); |
| 1057 } |
| 1058 #endif |
| 1059 |
| 1060 #undef __ |
OLD | NEW |