~ubuntu-branches/ubuntu/saucy/nodejs/saucy-proposed

« back to all changes in this revision

Viewing changes to deps/v8/src/x64/assembler-x64.cc

  • Committer: Package Import Robot
  • Author(s): Jérémy Lal
  • Date: 2013-08-14 00:16:46 UTC
  • mfrom: (7.1.40 sid)
  • Revision ID: package-import@ubuntu.com-20130814001646-bzlysfh8sd6mukbo
Tags: 0.10.15~dfsg1-4
* Update 2005 patch, adding a handful of tests that can fail on
  slow platforms.
* Add 1004 patch to fix test failures when writing NaN to buffer
  on mipsel.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
// Copyright 2011 the V8 project authors. All rights reserved.
 
1
// Copyright 2012 the V8 project authors. All rights reserved.
2
2
// Redistribution and use in source and binary forms, with or without
3
3
// modification, are permitted provided that the following conditions are
4
4
// met:
47
47
 
48
48
 
49
49
void CpuFeatures::Probe() {
50
 
  ASSERT(!initialized_);
 
50
  ASSERT(supported_ == CpuFeatures::kDefaultCpuFeatures);
51
51
#ifdef DEBUG
52
52
  initialized_ = true;
53
53
#endif
75
75
  // Save old rsp, since we are going to modify the stack.
76
76
  __ push(rbp);
77
77
  __ pushfq();
 
78
  __ push(rdi);
78
79
  __ push(rcx);
79
80
  __ push(rbx);
80
81
  __ movq(rbp, rsp);
128
129
  __ movq(rsp, rbp);
129
130
  __ pop(rbx);
130
131
  __ pop(rcx);
 
132
  __ pop(rdi);
131
133
  __ popfq();
132
134
  __ pop(rbp);
133
135
  __ ret(0);
348
350
    : AssemblerBase(arg_isolate),
349
351
      code_targets_(100),
350
352
      positions_recorder_(this),
351
 
      emit_debug_code_(FLAG_debug_code) {
 
353
      emit_debug_code_(FLAG_debug_code),
 
354
      predictable_code_size_(false) {
352
355
  if (buffer == NULL) {
353
356
    // Do our own buffer management.
354
357
    if (buffer_size <= kMinimalBufferSize) {
383
386
  }
384
387
#endif
385
388
 
386
 
  // Setup buffer pointers.
 
389
  // Set up buffer pointers.
387
390
  ASSERT(buffer_ != NULL);
388
391
  pc_ = buffer_;
389
392
  reloc_info_writer.Reposition(buffer_ + buffer_size, pc_);
412
415
  // Finalize code (at this point overflow() may be true, but the gap ensures
413
416
  // that we are still not overlapping instructions and relocation info).
414
417
  ASSERT(pc_ <= reloc_info_writer.pos());  // No overlap.
415
 
  // Setup code descriptor.
 
418
  // Set up code descriptor.
416
419
  desc->buffer = buffer_;
417
420
  desc->buffer_size = buffer_size_;
418
421
  desc->instr_size = pc_offset();
426
429
void Assembler::Align(int m) {
427
430
  ASSERT(IsPowerOf2(m));
428
431
  int delta = (m - (pc_offset() & (m - 1))) & (m - 1);
429
 
  while (delta >= 9) {
430
 
    nop(9);
431
 
    delta -= 9;
432
 
  }
433
 
  if (delta > 0) {
434
 
    nop(delta);
435
 
  }
 
432
  Nop(delta);
436
433
}
437
434
 
438
435
 
441
438
}
442
439
 
443
440
 
 
441
bool Assembler::IsNop(Address addr) {
 
442
  Address a = addr;
 
443
  while (*a == 0x66) a++;
 
444
  if (*a == 0x90) return true;
 
445
  if (a[0] == 0xf && a[1] == 0x1f) return true;
 
446
  return false;
 
447
}
 
448
 
 
449
 
444
450
void Assembler::bind_to(Label* L, int pos) {
445
451
  ASSERT(!L->is_bound());  // Label may only be bound once.
446
452
  ASSERT(0 <= pos && pos <= pc_offset());  // Position must be valid.
464
470
        static_cast<int>(*reinterpret_cast<int8_t*>(addr_at(fixup_pos)));
465
471
    ASSERT(offset_to_next <= 0);
466
472
    int disp = pos - (fixup_pos + sizeof(int8_t));
467
 
    ASSERT(is_int8(disp));
 
473
    CHECK(is_int8(disp));
468
474
    set_byte_at(fixup_pos, disp);
469
475
    if (offset_to_next < 0) {
470
476
      L->link_to(fixup_pos + offset_to_next, Label::kNear);
499
505
    V8::FatalProcessOutOfMemory("Assembler::GrowBuffer");
500
506
  }
501
507
 
502
 
  // Setup new buffer.
 
508
  // Set up new buffer.
503
509
  desc.buffer = NewArray<byte>(desc.buffer_size);
504
510
  desc.instr_size = pc_offset();
505
511
  desc.reloc_size =
772
778
                                          Register dst,
773
779
                                          Immediate src) {
774
780
  EnsureSpace ensure_space(this);
775
 
  if (dst.code() > 3) {
 
781
  if (!dst.is_byte_register()) {
776
782
    // Use 64-bit mode byte registers.
777
783
    emit_rex_64(dst);
778
784
  }
872
878
 
873
879
void Assembler::call(Handle<Code> target,
874
880
                     RelocInfo::Mode rmode,
875
 
                     unsigned ast_id) {
 
881
                     TypeFeedbackId ast_id) {
876
882
  positions_recorder()->WriteRecordedPositions();
877
883
  EnsureSpace ensure_space(this);
878
884
  // 1110 1000 #32-bit disp.
1056
1062
 
1057
1063
void Assembler::decb(Register dst) {
1058
1064
  EnsureSpace ensure_space(this);
1059
 
  if (dst.code() > 3) {
 
1065
  if (!dst.is_byte_register()) {
1060
1066
    // Register is not one of al, bl, cl, dl.  Its encoding needs REX.
1061
1067
    emit_rex_32(dst);
1062
1068
  }
1229
1235
    const int long_size  = 6;
1230
1236
    int offs = L->pos() - pc_offset();
1231
1237
    ASSERT(offs <= 0);
1232
 
    if (is_int8(offs - short_size)) {
 
1238
    // Determine whether we can use 1-byte offsets for backwards branches,
 
1239
    // which have a max range of 128 bytes.
 
1240
 
 
1241
    // We also need to check the predictable_code_size_ flag here, because
 
1242
    // on x64, when the full code generator recompiles code for debugging, some
 
1243
    // places need to be padded out to a certain size. The debugger is keeping
 
1244
    // track of how often it did this so that it can adjust return addresses on
 
1245
    // the stack, but if the size of jump instructions can also change, that's
 
1246
    // not enough and the calculated offsets would be incorrect.
 
1247
    if (is_int8(offs - short_size) && !predictable_code_size_) {
1233
1248
      // 0111 tttn #8-bit disp.
1234
1249
      emit(0x70 | cc);
1235
1250
      emit((offs - short_size) & 0xFF);
1286
1301
  if (L->is_bound()) {
1287
1302
    int offs = L->pos() - pc_offset() - 1;
1288
1303
    ASSERT(offs <= 0);
1289
 
    if (is_int8(offs - short_size)) {
 
1304
    if (is_int8(offs - short_size) && !predictable_code_size_) {
1290
1305
      // 1110 1011 #8-bit disp.
1291
1306
      emit(0xEB);
1292
1307
      emit((offs - short_size) & 0xFF);
1384
1399
 
1385
1400
void Assembler::movb(Register dst, const Operand& src) {
1386
1401
  EnsureSpace ensure_space(this);
1387
 
  if (dst.code() > 3) {
 
1402
  if (!dst.is_byte_register()) {
1388
1403
    // Register is not one of al, bl, cl, dl.  Its encoding needs REX.
1389
1404
    emit_rex_32(dst, src);
1390
1405
  } else {
1397
1412
 
1398
1413
void Assembler::movb(Register dst, Immediate imm) {
1399
1414
  EnsureSpace ensure_space(this);
1400
 
  if (dst.code() > 3) {
 
1415
  if (!dst.is_byte_register()) {
1401
1416
    emit_rex_32(dst);
1402
1417
  }
1403
1418
  emit(0xB0 + dst.low_bits());
1407
1422
 
1408
1423
void Assembler::movb(const Operand& dst, Register src) {
1409
1424
  EnsureSpace ensure_space(this);
1410
 
  if (src.code() > 3) {
 
1425
  if (!src.is_byte_register()) {
1411
1426
    emit_rex_32(src, dst);
1412
1427
  } else {
1413
1428
    emit_optional_rex_32(src, dst);
1637
1652
 
1638
1653
void Assembler::movzxbq(Register dst, const Operand& src) {
1639
1654
  EnsureSpace ensure_space(this);
 
1655
  // 32 bit operations zero the top 32 bits of 64 bit registers.  Therefore
 
1656
  // there is no need to make this a 64 bit operation.
1640
1657
  emit_optional_rex_32(dst, src);
1641
1658
  emit(0x0F);
1642
1659
  emit(0xB6);
1763
1780
}
1764
1781
 
1765
1782
 
1766
 
void Assembler::nop(int n) {
 
1783
void Assembler::Nop(int n) {
1767
1784
  // The recommended muti-byte sequences of NOP instructions from the Intel 64
1768
1785
  // and IA-32 Architectures Software Developer's Manual.
1769
1786
  //
1778
1795
  // 9 bytes  66 NOP DWORD ptr [EAX + EAX*1 +         66 0F 1F 84 00 00 00 00
1779
1796
  //          00000000H]                              00H
1780
1797
 
1781
 
  ASSERT(1 <= n);
1782
 
  ASSERT(n <= 9);
1783
1798
  EnsureSpace ensure_space(this);
1784
 
  switch (n) {
1785
 
  case 1:
1786
 
    emit(0x90);
1787
 
    return;
1788
 
  case 2:
1789
 
    emit(0x66);
1790
 
    emit(0x90);
1791
 
    return;
1792
 
  case 3:
1793
 
    emit(0x0f);
1794
 
    emit(0x1f);
1795
 
    emit(0x00);
1796
 
    return;
1797
 
  case 4:
1798
 
    emit(0x0f);
1799
 
    emit(0x1f);
1800
 
    emit(0x40);
1801
 
    emit(0x00);
1802
 
    return;
1803
 
  case 5:
1804
 
    emit(0x0f);
1805
 
    emit(0x1f);
1806
 
    emit(0x44);
1807
 
    emit(0x00);
1808
 
    emit(0x00);
1809
 
    return;
1810
 
  case 6:
1811
 
    emit(0x66);
1812
 
    emit(0x0f);
1813
 
    emit(0x1f);
1814
 
    emit(0x44);
1815
 
    emit(0x00);
1816
 
    emit(0x00);
1817
 
    return;
1818
 
  case 7:
1819
 
    emit(0x0f);
1820
 
    emit(0x1f);
1821
 
    emit(0x80);
1822
 
    emit(0x00);
1823
 
    emit(0x00);
1824
 
    emit(0x00);
1825
 
    emit(0x00);
1826
 
    return;
1827
 
  case 8:
1828
 
    emit(0x0f);
1829
 
    emit(0x1f);
1830
 
    emit(0x84);
1831
 
    emit(0x00);
1832
 
    emit(0x00);
1833
 
    emit(0x00);
1834
 
    emit(0x00);
1835
 
    emit(0x00);
1836
 
    return;
1837
 
  case 9:
1838
 
    emit(0x66);
1839
 
    emit(0x0f);
1840
 
    emit(0x1f);
1841
 
    emit(0x84);
1842
 
    emit(0x00);
1843
 
    emit(0x00);
1844
 
    emit(0x00);
1845
 
    emit(0x00);
1846
 
    emit(0x00);
1847
 
    return;
 
1799
  while (n > 0) {
 
1800
    switch (n) {
 
1801
      case 2:
 
1802
        emit(0x66);
 
1803
      case 1:
 
1804
        emit(0x90);
 
1805
        return;
 
1806
      case 3:
 
1807
        emit(0x0f);
 
1808
        emit(0x1f);
 
1809
        emit(0x00);
 
1810
        return;
 
1811
      case 4:
 
1812
        emit(0x0f);
 
1813
        emit(0x1f);
 
1814
        emit(0x40);
 
1815
        emit(0x00);
 
1816
        return;
 
1817
      case 6:
 
1818
        emit(0x66);
 
1819
      case 5:
 
1820
        emit(0x0f);
 
1821
        emit(0x1f);
 
1822
        emit(0x44);
 
1823
        emit(0x00);
 
1824
        emit(0x00);
 
1825
        return;
 
1826
      case 7:
 
1827
        emit(0x0f);
 
1828
        emit(0x1f);
 
1829
        emit(0x80);
 
1830
        emit(0x00);
 
1831
        emit(0x00);
 
1832
        emit(0x00);
 
1833
        emit(0x00);
 
1834
        return;
 
1835
      default:
 
1836
      case 11:
 
1837
        emit(0x66);
 
1838
        n--;
 
1839
      case 10:
 
1840
        emit(0x66);
 
1841
        n--;
 
1842
      case 9:
 
1843
        emit(0x66);
 
1844
        n--;
 
1845
      case 8:
 
1846
        emit(0x0f);
 
1847
        emit(0x1f);
 
1848
        emit(0x84);
 
1849
        emit(0x00);
 
1850
        emit(0x00);
 
1851
        emit(0x00);
 
1852
        emit(0x00);
 
1853
        emit(0x00);
 
1854
        n -= 8;
 
1855
    }
1848
1856
  }
1849
1857
}
1850
1858
 
1937
1945
  }
1938
1946
  EnsureSpace ensure_space(this);
1939
1947
  ASSERT(is_uint4(cc));
1940
 
  if (reg.code() > 3) {  // Use x64 byte registers, where different.
 
1948
  if (!reg.is_byte_register()) {  // Use x64 byte registers, where different.
1941
1949
    emit_rex_32(reg);
1942
1950
  }
1943
1951
  emit(0x0F);
2002
2010
    emit(0x84);
2003
2011
    emit_modrm(src, dst);
2004
2012
  } else {
2005
 
    if (dst.code() > 3 || src.code() > 3) {
 
2013
    if (!dst.is_byte_register() || !src.is_byte_register()) {
2006
2014
      // Register is not one of al, bl, cl, dl.  Its encoding needs REX.
2007
2015
      emit_rex_32(dst, src);
2008
2016
    }
2019
2027
    emit(0xA8);
2020
2028
    emit(mask.value_);  // Low byte emitted.
2021
2029
  } else {
2022
 
    if (reg.code() > 3) {
 
2030
    if (!reg.is_byte_register()) {
2023
2031
      // Register is not one of al, bl, cl, dl.  Its encoding needs REX.
2024
2032
      emit_rex_32(reg);
2025
2033
    }
2042
2050
 
2043
2051
void Assembler::testb(const Operand& op, Register reg) {
2044
2052
  EnsureSpace ensure_space(this);
2045
 
  if (reg.code() > 3) {
 
2053
  if (!reg.is_byte_register()) {
2046
2054
    // Register is not one of al, bl, cl, dl.  Its encoding needs REX.
2047
2055
    emit_rex_32(reg, op);
2048
2056
  } else {
2299
2307
}
2300
2308
 
2301
2309
 
 
2310
void Assembler::fptan() {
 
2311
  EnsureSpace ensure_space(this);
 
2312
  emit(0xD9);
 
2313
  emit(0xF2);
 
2314
}
 
2315
 
 
2316
 
2302
2317
void Assembler::fyl2x() {
2303
2318
  EnsureSpace ensure_space(this);
2304
2319
  emit(0xD9);
2306
2321
}
2307
2322
 
2308
2323
 
 
2324
void Assembler::f2xm1() {
 
2325
  EnsureSpace ensure_space(this);
 
2326
  emit(0xD9);
 
2327
  emit(0xF0);
 
2328
}
 
2329
 
 
2330
 
 
2331
void Assembler::fscale() {
 
2332
  EnsureSpace ensure_space(this);
 
2333
  emit(0xD9);
 
2334
  emit(0xFD);
 
2335
}
 
2336
 
 
2337
 
 
2338
void Assembler::fninit() {
 
2339
  EnsureSpace ensure_space(this);
 
2340
  emit(0xDB);
 
2341
  emit(0xE3);
 
2342
}
 
2343
 
 
2344
 
2309
2345
void Assembler::fadd(int i) {
2310
2346
  EnsureSpace ensure_space(this);
2311
2347
  emit_farith(0xDC, 0xC0, i);
2565
2601
 
2566
2602
 
2567
2603
void Assembler::extractps(Register dst, XMMRegister src, byte imm8) {
2568
 
  ASSERT(is_uint2(imm8));
 
2604
  ASSERT(CpuFeatures::IsSupported(SSE4_1));
 
2605
  ASSERT(is_uint8(imm8));
2569
2606
  EnsureSpace ensure_space(this);
2570
2607
  emit(0x66);
2571
2608
  emit_optional_rex_32(dst, src);
2983
3020
      return;
2984
3021
    }
2985
3022
  }
2986
 
  RelocInfo rinfo(pc_, rmode, data);
 
3023
  RelocInfo rinfo(pc_, rmode, data, NULL);
2987
3024
  reloc_info_writer.Write(&rinfo);
2988
3025
}
2989
3026
 
3020
3057
  return (1 << rmode_) & kApplyMask;
3021
3058
}
3022
3059
 
3023
 
 
3024
 
 
3025
3060
} }  // namespace v8::internal
3026
3061
 
3027
3062
#endif  // V8_TARGET_ARCH_X64