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