| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef V8_ARM64_MACRO_ASSEMBLER_ARM64_INL_H_ | 5 #ifndef V8_ARM64_MACRO_ASSEMBLER_ARM64_INL_H_ |
| 6 #define V8_ARM64_MACRO_ASSEMBLER_ARM64_INL_H_ | 6 #define V8_ARM64_MACRO_ASSEMBLER_ARM64_INL_H_ |
| 7 | 7 |
| 8 #include <ctype.h> | 8 #include <ctype.h> |
| 9 | 9 |
| 10 #include "v8globals.h" | 10 #include "v8globals.h" |
| (...skipping 1228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1239 | 1239 |
| 1240 void MacroAssembler::Uxtw(const Register& rd, const Register& rn) { | 1240 void MacroAssembler::Uxtw(const Register& rd, const Register& rn) { |
| 1241 ASSERT(allow_macro_instructions_); | 1241 ASSERT(allow_macro_instructions_); |
| 1242 ASSERT(!rd.IsZero()); | 1242 ASSERT(!rd.IsZero()); |
| 1243 uxtw(rd, rn); | 1243 uxtw(rd, rn); |
| 1244 } | 1244 } |
| 1245 | 1245 |
| 1246 | 1246 |
| 1247 void MacroAssembler::BumpSystemStackPointer(const Operand& space) { | 1247 void MacroAssembler::BumpSystemStackPointer(const Operand& space) { |
| 1248 ASSERT(!csp.Is(sp_)); | 1248 ASSERT(!csp.Is(sp_)); |
| 1249 { InstructionAccurateScope scope(this); | 1249 // TODO(jbramley): Several callers rely on this not using scratch registers, |
| 1250 if (!TmpList()->IsEmpty()) { | 1250 // so we use the assembler directly here. However, this means that large |
| 1251 if (CpuFeatures::IsSupported(ALWAYS_ALIGN_CSP)) { | 1251 // immediate values of 'space' cannot be handled cleanly. (Only 24-bits |
| 1252 UseScratchRegisterScope temps(this); | 1252 // immediates or values of 'space' that can be encoded in one instruction are |
| 1253 Register temp = temps.AcquireX(); | 1253 // accepted.) Once we implement our flexible scratch register idea, we could |
| 1254 sub(temp, StackPointer(), space); | 1254 // greatly simplify this function. |
| 1255 bic(csp, temp, 0xf); | 1255 InstructionAccurateScope scope(this); |
| 1256 } else { | 1256 if ((space.IsImmediate()) && !is_uint12(space.immediate())) { |
| 1257 sub(csp, StackPointer(), space); | 1257 // The subtract instruction supports a 12-bit immediate, shifted left by |
| 1258 } | 1258 // zero or 12 bits. So, in two instructions, we can subtract any immediate |
| 1259 } else { | 1259 // between zero and (1 << 24) - 1. |
| 1260 // TODO(jbramley): Several callers rely on this not using scratch | 1260 int64_t imm = space.immediate(); |
| 1261 // registers, so we use the assembler directly here. However, this means | 1261 ASSERT(is_uint24(imm)); |
| 1262 // that large immediate values of 'space' cannot be handled cleanly. (Only | |
| 1263 // 24-bits immediates or values of 'space' that can be encoded in one | |
| 1264 // instruction are accepted.) Once we implement our flexible scratch | |
| 1265 // register idea, we could greatly simplify this function. | |
| 1266 ASSERT(space.IsImmediate()); | |
| 1267 // Align to 16 bytes. | |
| 1268 uint64_t imm = RoundUp(space.immediate(), 0x10); | |
| 1269 ASSERT(is_uint24(imm)); | |
| 1270 | 1262 |
| 1271 Register source = StackPointer(); | 1263 int64_t imm_top_12_bits = imm >> 12; |
| 1272 if (CpuFeatures::IsSupported(ALWAYS_ALIGN_CSP)) { | 1264 sub(csp, StackPointer(), imm_top_12_bits << 12); |
| 1273 bic(csp, source, 0xf); | 1265 imm -= imm_top_12_bits << 12; |
| 1274 source = csp; | 1266 if (imm > 0) { |
| 1275 } | 1267 sub(csp, csp, imm); |
| 1276 if (!is_uint12(imm)) { | |
| 1277 int64_t imm_top_12_bits = imm >> 12; | |
| 1278 sub(csp, source, imm_top_12_bits << 12); | |
| 1279 source = csp; | |
| 1280 imm -= imm_top_12_bits << 12; | |
| 1281 } | |
| 1282 if (imm > 0) { | |
| 1283 sub(csp, source, imm); | |
| 1284 } | |
| 1285 } | 1268 } |
| 1269 } else { |
| 1270 sub(csp, StackPointer(), space); |
| 1286 } | 1271 } |
| 1287 AssertStackConsistency(); | |
| 1288 } | 1272 } |
| 1289 | 1273 |
| 1290 | 1274 |
| 1291 void MacroAssembler::SyncSystemStackPointer() { | |
| 1292 ASSERT(emit_debug_code()); | |
| 1293 ASSERT(!csp.Is(sp_)); | |
| 1294 if (CpuFeatures::IsSupported(ALWAYS_ALIGN_CSP)) { | |
| 1295 InstructionAccurateScope scope(this); | |
| 1296 bic(csp, StackPointer(), 0xf); | |
| 1297 } | |
| 1298 AssertStackConsistency(); | |
| 1299 } | |
| 1300 | |
| 1301 | |
| 1302 void MacroAssembler::InitializeRootRegister() { | 1275 void MacroAssembler::InitializeRootRegister() { |
| 1303 ExternalReference roots_array_start = | 1276 ExternalReference roots_array_start = |
| 1304 ExternalReference::roots_array_start(isolate()); | 1277 ExternalReference::roots_array_start(isolate()); |
| 1305 Mov(root, Operand(roots_array_start)); | 1278 Mov(root, Operand(roots_array_start)); |
| 1306 } | 1279 } |
| 1307 | 1280 |
| 1308 | 1281 |
| 1309 void MacroAssembler::SmiTag(Register dst, Register src) { | 1282 void MacroAssembler::SmiTag(Register dst, Register src) { |
| 1310 ASSERT(dst.Is64Bits() && src.Is64Bits()); | 1283 ASSERT(dst.Is64Bits() && src.Is64Bits()); |
| 1311 Lsl(dst, src, kSmiShift); | 1284 Lsl(dst, src, kSmiShift); |
| (...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1560 } | 1533 } |
| 1561 | 1534 |
| 1562 Add(StackPointer(), StackPointer(), size); | 1535 Add(StackPointer(), StackPointer(), size); |
| 1563 | 1536 |
| 1564 if (csp.Is(StackPointer())) { | 1537 if (csp.Is(StackPointer())) { |
| 1565 ASSERT(size % 16 == 0); | 1538 ASSERT(size % 16 == 0); |
| 1566 } else if (emit_debug_code()) { | 1539 } else if (emit_debug_code()) { |
| 1567 // It is safe to leave csp where it is when unwinding the JavaScript stack, | 1540 // It is safe to leave csp where it is when unwinding the JavaScript stack, |
| 1568 // but if we keep it matching StackPointer, the simulator can detect memory | 1541 // but if we keep it matching StackPointer, the simulator can detect memory |
| 1569 // accesses in the now-free part of the stack. | 1542 // accesses in the now-free part of the stack. |
| 1570 SyncSystemStackPointer(); | 1543 Mov(csp, StackPointer()); |
| 1571 } | 1544 } |
| 1572 } | 1545 } |
| 1573 | 1546 |
| 1574 | 1547 |
| 1575 void MacroAssembler::Drop(const Register& count, uint64_t unit_size) { | 1548 void MacroAssembler::Drop(const Register& count, uint64_t unit_size) { |
| 1576 if (unit_size == 0) return; | 1549 if (unit_size == 0) return; |
| 1577 ASSERT(IsPowerOf2(unit_size)); | 1550 ASSERT(IsPowerOf2(unit_size)); |
| 1578 | 1551 |
| 1579 const int shift = CountTrailingZeros(unit_size, kXRegSizeInBits); | 1552 const int shift = CountTrailingZeros(unit_size, kXRegSizeInBits); |
| 1580 const Operand size(count, LSL, shift); | 1553 const Operand size(count, LSL, shift); |
| 1581 | 1554 |
| 1582 if (size.IsZero()) { | 1555 if (size.IsZero()) { |
| 1583 return; | 1556 return; |
| 1584 } | 1557 } |
| 1585 | 1558 |
| 1586 Add(StackPointer(), StackPointer(), size); | 1559 Add(StackPointer(), StackPointer(), size); |
| 1587 | 1560 |
| 1588 if (!csp.Is(StackPointer()) && emit_debug_code()) { | 1561 if (!csp.Is(StackPointer()) && emit_debug_code()) { |
| 1589 // It is safe to leave csp where it is when unwinding the JavaScript stack, | 1562 // It is safe to leave csp where it is when unwinding the JavaScript stack, |
| 1590 // but if we keep it matching StackPointer, the simulator can detect memory | 1563 // but if we keep it matching StackPointer, the simulator can detect memory |
| 1591 // accesses in the now-free part of the stack. | 1564 // accesses in the now-free part of the stack. |
| 1592 SyncSystemStackPointer(); | 1565 Mov(csp, StackPointer()); |
| 1593 } | 1566 } |
| 1594 } | 1567 } |
| 1595 | 1568 |
| 1596 | 1569 |
| 1597 void MacroAssembler::DropBySMI(const Register& count_smi, uint64_t unit_size) { | 1570 void MacroAssembler::DropBySMI(const Register& count_smi, uint64_t unit_size) { |
| 1598 ASSERT(unit_size == 0 || IsPowerOf2(unit_size)); | 1571 ASSERT(unit_size == 0 || IsPowerOf2(unit_size)); |
| 1599 const int shift = CountTrailingZeros(unit_size, kXRegSizeInBits) - kSmiShift; | 1572 const int shift = CountTrailingZeros(unit_size, kXRegSizeInBits) - kSmiShift; |
| 1600 const Operand size(count_smi, | 1573 const Operand size(count_smi, |
| 1601 (shift >= 0) ? (LSL) : (LSR), | 1574 (shift >= 0) ? (LSL) : (LSR), |
| 1602 (shift >= 0) ? (shift) : (-shift)); | 1575 (shift >= 0) ? (shift) : (-shift)); |
| 1603 | 1576 |
| 1604 if (size.IsZero()) { | 1577 if (size.IsZero()) { |
| 1605 return; | 1578 return; |
| 1606 } | 1579 } |
| 1607 | 1580 |
| 1608 Add(StackPointer(), StackPointer(), size); | 1581 Add(StackPointer(), StackPointer(), size); |
| 1609 | 1582 |
| 1610 if (!csp.Is(StackPointer()) && emit_debug_code()) { | 1583 if (!csp.Is(StackPointer()) && emit_debug_code()) { |
| 1611 // It is safe to leave csp where it is when unwinding the JavaScript stack, | 1584 // It is safe to leave csp where it is when unwinding the JavaScript stack, |
| 1612 // but if we keep it matching StackPointer, the simulator can detect memory | 1585 // but if we keep it matching StackPointer, the simulator can detect memory |
| 1613 // accesses in the now-free part of the stack. | 1586 // accesses in the now-free part of the stack. |
| 1614 SyncSystemStackPointer(); | 1587 Mov(csp, StackPointer()); |
| 1615 } | 1588 } |
| 1616 } | 1589 } |
| 1617 | 1590 |
| 1618 | 1591 |
| 1619 void MacroAssembler::CompareAndBranch(const Register& lhs, | 1592 void MacroAssembler::CompareAndBranch(const Register& lhs, |
| 1620 const Operand& rhs, | 1593 const Operand& rhs, |
| 1621 Condition cond, | 1594 Condition cond, |
| 1622 Label* label) { | 1595 Label* label) { |
| 1623 if (rhs.IsImmediate() && (rhs.immediate() == 0) && | 1596 if (rhs.IsImmediate() && (rhs.immediate() == 0) && |
| 1624 ((cond == eq) || (cond == ne))) { | 1597 ((cond == eq) || (cond == ne))) { |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1688 // characters are reserved for controlling features of the instrumentation. | 1661 // characters are reserved for controlling features of the instrumentation. |
| 1689 ASSERT(isprint(marker_name[0]) && isprint(marker_name[1])); | 1662 ASSERT(isprint(marker_name[0]) && isprint(marker_name[1])); |
| 1690 | 1663 |
| 1691 InstructionAccurateScope scope(this, 1); | 1664 InstructionAccurateScope scope(this, 1); |
| 1692 movn(xzr, (marker_name[1] << 8) | marker_name[0]); | 1665 movn(xzr, (marker_name[1] << 8) | marker_name[0]); |
| 1693 } | 1666 } |
| 1694 | 1667 |
| 1695 } } // namespace v8::internal | 1668 } } // namespace v8::internal |
| 1696 | 1669 |
| 1697 #endif // V8_ARM64_MACRO_ASSEMBLER_ARM64_INL_H_ | 1670 #endif // V8_ARM64_MACRO_ASSEMBLER_ARM64_INL_H_ |
| OLD | NEW |