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