OLD | NEW |
1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 442 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
453 last_pc_ = pc_; | 453 last_pc_ = pc_; |
454 emit_rex_64(reg, op); | 454 emit_rex_64(reg, op); |
455 emit(opcode); | 455 emit(opcode); |
456 emit_operand(reg, op); | 456 emit_operand(reg, op); |
457 } | 457 } |
458 | 458 |
459 | 459 |
460 void Assembler::arithmetic_op(byte opcode, Register reg, Register rm_reg) { | 460 void Assembler::arithmetic_op(byte opcode, Register reg, Register rm_reg) { |
461 EnsureSpace ensure_space(this); | 461 EnsureSpace ensure_space(this); |
462 last_pc_ = pc_; | 462 last_pc_ = pc_; |
463 emit_rex_64(reg, rm_reg); | 463 ASSERT((opcode & 0xC6) == 2); |
464 emit(opcode); | 464 if (rm_reg.low_bits() == 4) { // Forces SIB byte. |
465 emit_modrm(reg, rm_reg); | 465 emit_rex_64(rm_reg, reg); |
| 466 emit(opcode ^ 0x02); |
| 467 emit_modrm(rm_reg, reg); |
| 468 } else { |
| 469 emit_rex_64(reg, rm_reg); |
| 470 emit(opcode); |
| 471 emit_modrm(reg, rm_reg); |
| 472 } |
466 } | 473 } |
467 | 474 |
468 | 475 |
469 void Assembler::arithmetic_op_16(byte opcode, Register reg, Register rm_reg) { | 476 void Assembler::arithmetic_op_16(byte opcode, Register reg, Register rm_reg) { |
470 EnsureSpace ensure_space(this); | 477 EnsureSpace ensure_space(this); |
471 last_pc_ = pc_; | 478 last_pc_ = pc_; |
472 emit(0x66); | 479 ASSERT((opcode & 0xC6) == 2); |
473 emit_optional_rex_32(reg, rm_reg); | 480 if (rm_reg.low_bits() == 4) { // Forces SIB byte. |
474 emit(opcode); | 481 emit(0x66); |
475 emit_modrm(reg, rm_reg); | 482 emit_optional_rex_32(rm_reg, reg); |
| 483 emit(opcode ^ 0x02); |
| 484 emit_modrm(rm_reg, reg); |
| 485 } else { |
| 486 emit(0x66); |
| 487 emit_optional_rex_32(reg, rm_reg); |
| 488 emit(opcode); |
| 489 emit_modrm(reg, rm_reg); |
| 490 } |
476 } | 491 } |
477 | 492 |
478 | 493 |
479 void Assembler::arithmetic_op_16(byte opcode, | 494 void Assembler::arithmetic_op_16(byte opcode, |
480 Register reg, | 495 Register reg, |
481 const Operand& rm_reg) { | 496 const Operand& rm_reg) { |
482 EnsureSpace ensure_space(this); | 497 EnsureSpace ensure_space(this); |
483 last_pc_ = pc_; | 498 last_pc_ = pc_; |
484 emit(0x66); | 499 emit(0x66); |
485 emit_optional_rex_32(reg, rm_reg); | 500 emit_optional_rex_32(reg, rm_reg); |
486 emit(opcode); | 501 emit(opcode); |
487 emit_operand(reg, rm_reg); | 502 emit_operand(reg, rm_reg); |
488 } | 503 } |
489 | 504 |
490 | 505 |
491 void Assembler::arithmetic_op_32(byte opcode, Register reg, Register rm_reg) { | 506 void Assembler::arithmetic_op_32(byte opcode, Register reg, Register rm_reg) { |
492 EnsureSpace ensure_space(this); | 507 EnsureSpace ensure_space(this); |
493 last_pc_ = pc_; | 508 last_pc_ = pc_; |
494 emit_optional_rex_32(reg, rm_reg); | 509 ASSERT((opcode & 0xC6) == 2); |
495 emit(opcode); | 510 if (rm_reg.low_bits() == 4) { // Forces SIB byte. |
496 emit_modrm(reg, rm_reg); | 511 emit_optional_rex_32(rm_reg, reg); |
| 512 emit(opcode ^ 0x02); // E.g. 0x03 -> 0x01 for ADD. |
| 513 emit_modrm(rm_reg, reg); |
| 514 } else { |
| 515 emit_optional_rex_32(reg, rm_reg); |
| 516 emit(opcode); |
| 517 emit_modrm(reg, rm_reg); |
| 518 } |
497 } | 519 } |
498 | 520 |
499 | 521 |
500 void Assembler::arithmetic_op_32(byte opcode, | 522 void Assembler::arithmetic_op_32(byte opcode, |
501 Register reg, | 523 Register reg, |
502 const Operand& rm_reg) { | 524 const Operand& rm_reg) { |
503 EnsureSpace ensure_space(this); | 525 EnsureSpace ensure_space(this); |
504 last_pc_ = pc_; | 526 last_pc_ = pc_; |
505 emit_optional_rex_32(reg, rm_reg); | 527 emit_optional_rex_32(reg, rm_reg); |
506 emit(opcode); | 528 emit(opcode); |
(...skipping 778 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1285 last_pc_ = pc_; | 1307 last_pc_ = pc_; |
1286 emit_optional_rex_32(dst, src); | 1308 emit_optional_rex_32(dst, src); |
1287 emit(0x8B); | 1309 emit(0x8B); |
1288 emit_operand(dst, src); | 1310 emit_operand(dst, src); |
1289 } | 1311 } |
1290 | 1312 |
1291 | 1313 |
1292 void Assembler::movl(Register dst, Register src) { | 1314 void Assembler::movl(Register dst, Register src) { |
1293 EnsureSpace ensure_space(this); | 1315 EnsureSpace ensure_space(this); |
1294 last_pc_ = pc_; | 1316 last_pc_ = pc_; |
1295 emit_optional_rex_32(dst, src); | 1317 if (src.low_bits() == 4) { |
1296 emit(0x8B); | 1318 emit_optional_rex_32(src, dst); |
1297 emit_modrm(dst, src); | 1319 emit(0x89); |
| 1320 emit_modrm(src, dst); |
| 1321 } else { |
| 1322 emit_optional_rex_32(dst, src); |
| 1323 emit(0x8B); |
| 1324 emit_modrm(dst, src); |
| 1325 } |
1298 } | 1326 } |
1299 | 1327 |
1300 | 1328 |
1301 void Assembler::movl(const Operand& dst, Register src) { | 1329 void Assembler::movl(const Operand& dst, Register src) { |
1302 EnsureSpace ensure_space(this); | 1330 EnsureSpace ensure_space(this); |
1303 last_pc_ = pc_; | 1331 last_pc_ = pc_; |
1304 emit_optional_rex_32(src, dst); | 1332 emit_optional_rex_32(src, dst); |
1305 emit(0x89); | 1333 emit(0x89); |
1306 emit_operand(src, dst); | 1334 emit_operand(src, dst); |
1307 } | 1335 } |
(...skipping 24 matching lines...) Expand all Loading... |
1332 last_pc_ = pc_; | 1360 last_pc_ = pc_; |
1333 emit_rex_64(dst, src); | 1361 emit_rex_64(dst, src); |
1334 emit(0x8B); | 1362 emit(0x8B); |
1335 emit_operand(dst, src); | 1363 emit_operand(dst, src); |
1336 } | 1364 } |
1337 | 1365 |
1338 | 1366 |
1339 void Assembler::movq(Register dst, Register src) { | 1367 void Assembler::movq(Register dst, Register src) { |
1340 EnsureSpace ensure_space(this); | 1368 EnsureSpace ensure_space(this); |
1341 last_pc_ = pc_; | 1369 last_pc_ = pc_; |
1342 emit_rex_64(dst, src); | 1370 if (src.low_bits() == 4) { |
1343 emit(0x8B); | 1371 emit_rex_64(src, dst); |
1344 emit_modrm(dst, src); | 1372 emit(0x89); |
| 1373 emit_modrm(src, dst); |
| 1374 } else { |
| 1375 emit_rex_64(dst, src); |
| 1376 emit(0x8B); |
| 1377 emit_modrm(dst, src); |
| 1378 } |
1345 } | 1379 } |
1346 | 1380 |
1347 | 1381 |
1348 void Assembler::movq(Register dst, Immediate value) { | 1382 void Assembler::movq(Register dst, Immediate value) { |
1349 EnsureSpace ensure_space(this); | 1383 EnsureSpace ensure_space(this); |
1350 last_pc_ = pc_; | 1384 last_pc_ = pc_; |
1351 emit_rex_64(dst); | 1385 emit_rex_64(dst); |
1352 emit(0xC7); | 1386 emit(0xC7); |
1353 emit_modrm(0x0, dst); | 1387 emit_modrm(0x0, dst); |
1354 emit(value); // Only 32-bit immediates are possible, not 8-bit immediates. | 1388 emit(value); // Only 32-bit immediates are possible, not 8-bit immediates. |
(...skipping 500 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1855 } | 1889 } |
1856 | 1890 |
1857 | 1891 |
1858 void Assembler::xchg(Register dst, Register src) { | 1892 void Assembler::xchg(Register dst, Register src) { |
1859 EnsureSpace ensure_space(this); | 1893 EnsureSpace ensure_space(this); |
1860 last_pc_ = pc_; | 1894 last_pc_ = pc_; |
1861 if (src.is(rax) || dst.is(rax)) { // Single-byte encoding | 1895 if (src.is(rax) || dst.is(rax)) { // Single-byte encoding |
1862 Register other = src.is(rax) ? dst : src; | 1896 Register other = src.is(rax) ? dst : src; |
1863 emit_rex_64(other); | 1897 emit_rex_64(other); |
1864 emit(0x90 | other.low_bits()); | 1898 emit(0x90 | other.low_bits()); |
| 1899 } else if (dst.low_bits() == 4) { |
| 1900 emit_rex_64(dst, src); |
| 1901 emit(0x87); |
| 1902 emit_modrm(dst, src); |
1865 } else { | 1903 } else { |
1866 emit_rex_64(src, dst); | 1904 emit_rex_64(src, dst); |
1867 emit(0x87); | 1905 emit(0x87); |
1868 emit_modrm(src, dst); | 1906 emit_modrm(src, dst); |
1869 } | 1907 } |
1870 } | 1908 } |
1871 | 1909 |
1872 | 1910 |
1873 void Assembler::store_rax(void* dst, RelocInfo::Mode mode) { | 1911 void Assembler::store_rax(void* dst, RelocInfo::Mode mode) { |
1874 EnsureSpace ensure_space(this); | 1912 EnsureSpace ensure_space(this); |
1875 last_pc_ = pc_; | 1913 last_pc_ = pc_; |
1876 emit(0x48); // REX.W | 1914 emit(0x48); // REX.W |
1877 emit(0xA3); | 1915 emit(0xA3); |
1878 emitq(reinterpret_cast<uintptr_t>(dst), mode); | 1916 emitq(reinterpret_cast<uintptr_t>(dst), mode); |
1879 } | 1917 } |
1880 | 1918 |
1881 | 1919 |
1882 void Assembler::store_rax(ExternalReference ref) { | 1920 void Assembler::store_rax(ExternalReference ref) { |
1883 store_rax(ref.address(), RelocInfo::EXTERNAL_REFERENCE); | 1921 store_rax(ref.address(), RelocInfo::EXTERNAL_REFERENCE); |
1884 } | 1922 } |
1885 | 1923 |
1886 | 1924 |
1887 void Assembler::testb(Register dst, Register src) { | 1925 void Assembler::testb(Register dst, Register src) { |
1888 EnsureSpace ensure_space(this); | 1926 EnsureSpace ensure_space(this); |
1889 last_pc_ = pc_; | 1927 last_pc_ = pc_; |
1890 if (dst.code() > 3 || src.code() > 3) { | 1928 if (src.low_bits() == 4) { |
1891 // Register is not one of al, bl, cl, dl. Its encoding needs REX. | 1929 emit_rex_32(src, dst); |
1892 emit_rex_32(dst, src); | 1930 emit(0x84); |
| 1931 emit_modrm(src, dst); |
| 1932 } else { |
| 1933 if (dst.code() > 3 || src.code() > 3) { |
| 1934 // Register is not one of al, bl, cl, dl. Its encoding needs REX. |
| 1935 emit_rex_32(dst, src); |
| 1936 } |
| 1937 emit(0x84); |
| 1938 emit_modrm(dst, src); |
1893 } | 1939 } |
1894 emit(0x84); | |
1895 emit_modrm(dst, src); | |
1896 } | 1940 } |
1897 | 1941 |
1898 | 1942 |
1899 void Assembler::testb(Register reg, Immediate mask) { | 1943 void Assembler::testb(Register reg, Immediate mask) { |
1900 ASSERT(is_int8(mask.value_) || is_uint8(mask.value_)); | 1944 ASSERT(is_int8(mask.value_) || is_uint8(mask.value_)); |
1901 EnsureSpace ensure_space(this); | 1945 EnsureSpace ensure_space(this); |
1902 last_pc_ = pc_; | 1946 last_pc_ = pc_; |
1903 if (reg.is(rax)) { | 1947 if (reg.is(rax)) { |
1904 emit(0xA8); | 1948 emit(0xA8); |
1905 emit(mask.value_); // Low byte emitted. | 1949 emit(mask.value_); // Low byte emitted. |
(...skipping 30 matching lines...) Expand all Loading... |
1936 emit_optional_rex_32(reg, op); | 1980 emit_optional_rex_32(reg, op); |
1937 } | 1981 } |
1938 emit(0x84); | 1982 emit(0x84); |
1939 emit_operand(reg, op); | 1983 emit_operand(reg, op); |
1940 } | 1984 } |
1941 | 1985 |
1942 | 1986 |
1943 void Assembler::testl(Register dst, Register src) { | 1987 void Assembler::testl(Register dst, Register src) { |
1944 EnsureSpace ensure_space(this); | 1988 EnsureSpace ensure_space(this); |
1945 last_pc_ = pc_; | 1989 last_pc_ = pc_; |
1946 emit_optional_rex_32(dst, src); | 1990 if (src.low_bits() == 4) { |
1947 emit(0x85); | 1991 emit_optional_rex_32(src, dst); |
1948 emit_modrm(dst, src); | 1992 emit(0x85); |
| 1993 emit_modrm(src, dst); |
| 1994 } else { |
| 1995 emit_optional_rex_32(dst, src); |
| 1996 emit(0x85); |
| 1997 emit_modrm(dst, src); |
| 1998 } |
1949 } | 1999 } |
1950 | 2000 |
1951 | 2001 |
1952 void Assembler::testl(Register reg, Immediate mask) { | 2002 void Assembler::testl(Register reg, Immediate mask) { |
1953 // testl with a mask that fits in the low byte is exactly testb. | 2003 // testl with a mask that fits in the low byte is exactly testb. |
1954 if (is_uint8(mask.value_)) { | 2004 if (is_uint8(mask.value_)) { |
1955 testb(reg, mask); | 2005 testb(reg, mask); |
1956 return; | 2006 return; |
1957 } | 2007 } |
1958 EnsureSpace ensure_space(this); | 2008 EnsureSpace ensure_space(this); |
(...skipping 30 matching lines...) Expand all Loading... |
1989 last_pc_ = pc_; | 2039 last_pc_ = pc_; |
1990 emit_rex_64(reg, op); | 2040 emit_rex_64(reg, op); |
1991 emit(0x85); | 2041 emit(0x85); |
1992 emit_operand(reg, op); | 2042 emit_operand(reg, op); |
1993 } | 2043 } |
1994 | 2044 |
1995 | 2045 |
1996 void Assembler::testq(Register dst, Register src) { | 2046 void Assembler::testq(Register dst, Register src) { |
1997 EnsureSpace ensure_space(this); | 2047 EnsureSpace ensure_space(this); |
1998 last_pc_ = pc_; | 2048 last_pc_ = pc_; |
1999 emit_rex_64(dst, src); | 2049 if (src.low_bits() == 4) { |
2000 emit(0x85); | 2050 emit_rex_64(src, dst); |
2001 emit_modrm(dst, src); | 2051 emit(0x85); |
| 2052 emit_modrm(src, dst); |
| 2053 } else { |
| 2054 emit_rex_64(dst, src); |
| 2055 emit(0x85); |
| 2056 emit_modrm(dst, src); |
| 2057 } |
2002 } | 2058 } |
2003 | 2059 |
2004 | 2060 |
2005 void Assembler::testq(Register dst, Immediate mask) { | 2061 void Assembler::testq(Register dst, Immediate mask) { |
2006 EnsureSpace ensure_space(this); | 2062 EnsureSpace ensure_space(this); |
2007 last_pc_ = pc_; | 2063 last_pc_ = pc_; |
2008 if (dst.is(rax)) { | 2064 if (dst.is(rax)) { |
2009 emit_rex_64(); | 2065 emit_rex_64(); |
2010 emit(0xA9); | 2066 emit(0xA9); |
2011 emit(mask); | 2067 emit(mask); |
(...skipping 725 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2737 } | 2793 } |
2738 | 2794 |
2739 | 2795 |
2740 const int RelocInfo::kApplyMask = RelocInfo::kCodeTargetMask | | 2796 const int RelocInfo::kApplyMask = RelocInfo::kCodeTargetMask | |
2741 1 << RelocInfo::INTERNAL_REFERENCE | | 2797 1 << RelocInfo::INTERNAL_REFERENCE | |
2742 1 << RelocInfo::JS_RETURN; | 2798 1 << RelocInfo::JS_RETURN; |
2743 | 2799 |
2744 } } // namespace v8::internal | 2800 } } // namespace v8::internal |
2745 | 2801 |
2746 #endif // V8_TARGET_ARCH_X64 | 2802 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |