Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/globals.h" | 5 #include "vm/globals.h" |
| 6 #if defined(TARGET_ARCH_ARM) | 6 #if defined(TARGET_ARCH_ARM) |
| 7 | 7 |
| 8 #include "vm/assembler.h" | 8 #include "vm/assembler.h" |
| 9 | 9 |
| 10 namespace dart { | 10 namespace dart { |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 65 uint32_t offset = encoding_ & offset_mask; | 65 uint32_t offset = encoding_ & offset_mask; |
| 66 ASSERT(offset < 256); | 66 ASSERT(offset < 256); |
| 67 return (encoding_ & ~offset_mask) | ((offset & 0xf0) << 4) | (offset & 0xf); | 67 return (encoding_ & ~offset_mask) | ((offset & 0xf0) << 4) | (offset & 0xf); |
| 68 } | 68 } |
| 69 | 69 |
| 70 | 70 |
| 71 uint32_t Address::vencoding() const { | 71 uint32_t Address::vencoding() const { |
| 72 const uint32_t offset_mask = (1 << 12) - 1; | 72 const uint32_t offset_mask = (1 << 12) - 1; |
| 73 uint32_t offset = encoding_ & offset_mask; | 73 uint32_t offset = encoding_ & offset_mask; |
| 74 ASSERT(offset < (1 << 10)); // In the range 0 to +1020. | 74 ASSERT(offset < (1 << 10)); // In the range 0 to +1020. |
| 75 ASSERT(Utils::Utils::IsAligned(offset, 2)); // Multiple of 4. | 75 ASSERT(Utils::IsAligned(offset, 4)); // Multiple of 4. |
| 76 int mode = encoding_ & ((8|4|1) << 21); | 76 int mode = encoding_ & ((8|4|1) << 21); |
| 77 ASSERT((mode == Offset) || (mode == NegOffset)); | 77 ASSERT((mode == Offset) || (mode == NegOffset)); |
| 78 uint32_t vencoding = (encoding_ & (0xf << kRnShift)) | (offset >> 2); | 78 uint32_t vencoding = (encoding_ & (0xf << kRnShift)) | (offset >> 2); |
| 79 if (mode == Offset) { | 79 if (mode == Offset) { |
| 80 vencoding |= 1 << 23; | 80 vencoding |= 1 << 23; |
| 81 } | 81 } |
| 82 return vencoding; | 82 return vencoding; |
| 83 } | 83 } |
| 84 | 84 |
| 85 | 85 |
| 86 void Assembler::InitializeMemoryWithBreakpoints(uword data, int length) { | |
| 87 ASSERT(Utils::IsAligned(data, 4)); | |
| 88 ASSERT(Utils::IsAligned(length, 4)); | |
| 89 const uword end = data + length; | |
| 90 while (data < end) { | |
| 91 *reinterpret_cast<int32_t*>(data) = Instr::kBreakPointInstruction; | |
| 92 data += 4; | |
| 93 } | |
| 94 } | |
| 95 | |
| 96 | |
| 86 void Assembler::Emit(int32_t value) { | 97 void Assembler::Emit(int32_t value) { |
| 87 AssemblerBuffer::EnsureCapacity ensured(&buffer_); | 98 AssemblerBuffer::EnsureCapacity ensured(&buffer_); |
| 88 buffer_.Emit<int32_t>(value); | 99 buffer_.Emit<int32_t>(value); |
| 89 } | 100 } |
| 90 | 101 |
| 91 | 102 |
| 92 void Assembler::EmitType01(Condition cond, | 103 void Assembler::EmitType01(Condition cond, |
| 93 int type, | 104 int type, |
| 94 Opcode opcode, | 105 Opcode opcode, |
| 95 int set_cc, | 106 int set_cc, |
| (...skipping 917 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1013 void Assembler::MarkExceptionHandler(Label* label) { | 1024 void Assembler::MarkExceptionHandler(Label* label) { |
| 1014 EmitType01(AL, 1, TST, 1, PC, R0, ShifterOperand(0)); | 1025 EmitType01(AL, 1, TST, 1, PC, R0, ShifterOperand(0)); |
| 1015 Label l; | 1026 Label l; |
| 1016 b(&l); | 1027 b(&l); |
| 1017 EmitBranch(AL, label, false); | 1028 EmitBranch(AL, label, false); |
| 1018 Bind(&l); | 1029 Bind(&l); |
| 1019 } | 1030 } |
| 1020 | 1031 |
| 1021 | 1032 |
| 1022 void Assembler::LoadObject(Register rd, const Object& object) { | 1033 void Assembler::LoadObject(Register rd, const Object& object) { |
| 1023 UNIMPLEMENTED(); | 1034 // TODO(regis): If the object is never relocated (null, true, false, ...), |
| 1035 // load as immediate. | |
| 1036 int32_t offset = AddObject(object); | |
| 1037 ASSERT(Utils::IsAligned(offset, 4) && (offset >= 0)); | |
| 1038 if (Address::CanHoldLoadOffset(kLoadWord, offset)) { | |
| 1039 ldr(rd, Address(CP, offset)); | |
| 1040 } else { | |
| 1041 int32_t offset12_hi = offset & ~kOffset12Mask; // signed | |
| 1042 uint32_t offset12_lo = offset & kOffset12Mask; // unsigned | |
| 1043 AddConstant(rd, CP, offset12_hi); | |
| 1044 ldr(rd, Address(rd, offset12_lo)); | |
| 1045 } | |
| 1024 } | 1046 } |
| 1025 | 1047 |
| 1026 | 1048 |
| 1027 void Assembler::Bind(Label* label) { | 1049 void Assembler::Bind(Label* label) { |
| 1028 ASSERT(!label->IsBound()); | 1050 ASSERT(!label->IsBound()); |
| 1029 int bound_pc = buffer_.Size(); | 1051 int bound_pc = buffer_.Size(); |
| 1030 while (label->IsLinked()) { | 1052 while (label->IsLinked()) { |
| 1031 int32_t position = label->Position(); | 1053 int32_t position = label->Position(); |
| 1032 int32_t next = buffer_.Load<int32_t>(position); | 1054 int32_t next = buffer_.Load<int32_t>(position); |
| 1033 int32_t encoded = Assembler::EncodeBranchOffset(bound_pc - position, next); | 1055 int32_t encoded = Assembler::EncodeBranchOffset(bound_pc - position, next); |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1132 mov(rd, ShifterOperand(rm, ROR, shift_imm), cond); | 1154 mov(rd, ShifterOperand(rm, ROR, shift_imm), cond); |
| 1133 } | 1155 } |
| 1134 | 1156 |
| 1135 | 1157 |
| 1136 void Assembler::Rrx(Register rd, Register rm, Condition cond) { | 1158 void Assembler::Rrx(Register rd, Register rm, Condition cond) { |
| 1137 mov(rd, ShifterOperand(rm, ROR, 0), cond); | 1159 mov(rd, ShifterOperand(rm, ROR, 0), cond); |
| 1138 } | 1160 } |
| 1139 | 1161 |
| 1140 | 1162 |
| 1141 void Assembler::Branch(const ExternalLabel* label) { | 1163 void Assembler::Branch(const ExternalLabel* label) { |
| 1142 // TODO(regis): Revisit this code sequence. | |
| 1143 LoadImmediate(IP, label->address()); // Target address is never patched. | 1164 LoadImmediate(IP, label->address()); // Target address is never patched. |
| 1144 mov(PC, ShifterOperand(IP)); | 1165 mov(PC, ShifterOperand(IP)); |
| 1145 } | 1166 } |
| 1146 | 1167 |
| 1147 | 1168 |
| 1148 void Assembler::BranchLink(const ExternalLabel* label) { | 1169 void Assembler::BranchLink(const ExternalLabel* label) { |
| 1149 // TODO(regis): Revisit this code sequence. | 1170 // TODO(regis): Make sure that CodePatcher is able to patch the label referred |
| 1150 // Make sure that CodePatcher is able to patch this code sequence. | 1171 // to by this code sequence. |
| 1151 // For added code robustness, use 'blx lr' in a patchable sequence and | 1172 // For added code robustness, use 'blx lr' in a patchable sequence and |
| 1152 // use 'blx ip' in a non-patchable sequence (see other BranchLink flavors). | 1173 // use 'blx ip' in a non-patchable sequence (see other BranchLink flavors). |
| 1153 ldr(LR, Address(PC)); | 1174 int32_t offset = AddExternalLabel(label); |
| 1154 Label skip; | 1175 ASSERT(Utils::IsAligned(offset, 4) && (offset >= 0)); |
| 1155 b(&skip); | 1176 if (Address::CanHoldLoadOffset(kLoadWord, offset)) { |
| 1156 Emit(label->address()); // May get patched. | 1177 ldr(LR, Address(CP, offset)); |
| 1157 Bind(&skip); | 1178 } else { |
| 1179 int32_t offset12_hi = offset & ~kOffset12Mask; // signed | |
| 1180 uint32_t offset12_lo = offset & kOffset12Mask; // unsigned | |
| 1181 // TODO(regis): Using AddConstant may generate too many sequences to be | |
| 1182 // easily decoded by CodePatcher. If so, use a simpler fixed sequence. | |
| 1183 AddConstant(LR, CP, offset12_hi); | |
|
Ivan Posva
2013/02/06 23:33:50
As discussed, please do not use macros here as the
regis
2013/02/07 00:53:24
Done.
| |
| 1184 ldr(LR, Address(LR, offset12_lo)); | |
| 1185 } | |
| 1158 blx(LR); // Use blx instruction so that the return branch prediction works. | 1186 blx(LR); // Use blx instruction so that the return branch prediction works. |
| 1159 } | 1187 } |
| 1160 | 1188 |
| 1161 | 1189 |
| 1162 void Assembler::BranchLinkStore(const ExternalLabel* label, Address ad) { | 1190 void Assembler::BranchLinkStore(const ExternalLabel* label, Address ad) { |
| 1163 // TODO(regis): Revisit this code sequence. | 1191 // TODO(regis): Revisit this code sequence. |
| 1164 LoadImmediate(IP, label->address()); // Target address is never patched. | 1192 LoadImmediate(IP, label->address()); // Target address is never patched. |
| 1165 str(PC, ad); | 1193 str(PC, ad); |
| 1166 blx(IP); // Use blx instruction so that the return branch prediction works. | 1194 blx(IP); // Use blx instruction so that the return branch prediction works. |
| 1167 } | 1195 } |
| (...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1487 offset &= kBranchOffsetMask; | 1515 offset &= kBranchOffsetMask; |
| 1488 return (inst & ~kBranchOffsetMask) | offset; | 1516 return (inst & ~kBranchOffsetMask) | offset; |
| 1489 } | 1517 } |
| 1490 | 1518 |
| 1491 | 1519 |
| 1492 int Assembler::DecodeBranchOffset(int32_t inst) { | 1520 int Assembler::DecodeBranchOffset(int32_t inst) { |
| 1493 // Sign-extend, left-shift by 2, then add 8. | 1521 // Sign-extend, left-shift by 2, then add 8. |
| 1494 return ((((inst & kBranchOffsetMask) << 8) >> 6) + 8); | 1522 return ((((inst & kBranchOffsetMask) << 8) >> 6) + 8); |
| 1495 } | 1523 } |
| 1496 | 1524 |
| 1525 | |
| 1526 int32_t Assembler::AddObject(const Object& obj) { | |
| 1527 for (int i = 0; i < objects_.Length(); i++) { | |
|
Ivan Posva
2013/02/06 23:33:50
As discussed we should just return the offset here
regis
2013/02/07 00:53:24
Done.
| |
| 1528 if (objects_.At(i) == obj.raw()) { | |
| 1529 // TODO(regis): Skip over header. | |
| 1530 return /*kCodeObjectsHeaderSize +*/ 4*i; | |
| 1531 } | |
| 1532 } | |
| 1533 objects_.Add(obj); | |
| 1534 // TODO(regis): Skip over header. | |
| 1535 return /*kCodeObjectsHeaderSize +*/ 4*(objects_.Length() - 1); | |
| 1536 } | |
| 1537 | |
| 1538 | |
| 1539 int32_t Assembler::AddExternalLabel(const ExternalLabel* label) { | |
| 1540 const uword address = label->address(); | |
| 1541 ASSERT(Utils::IsAligned(address, 4)); | |
| 1542 // The address is stored in the object array as a RawSmi. | |
| 1543 const Smi& smi = Smi::Handle(Smi::New(address >> kSmiTagShift)); | |
| 1544 // Do not reuse an existing entry, since each reference may be patched | |
| 1545 // independently. | |
| 1546 objects_.Add(smi); | |
| 1547 // TODO(regis): Skip over header. | |
| 1548 return /*kCodeObjectsHeaderSize +*/ 4*(objects_.Length() - 1); | |
|
Ivan Posva
2013/02/06 23:33:50
ditto.
regis
2013/02/07 00:53:24
Done.
| |
| 1549 } | |
| 1550 | |
| 1497 } // namespace dart | 1551 } // namespace dart |
| 1498 | 1552 |
| 1499 #endif // defined TARGET_ARCH_ARM | 1553 #endif // defined TARGET_ARCH_ARM |
| 1500 | 1554 |
| OLD | NEW |