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 const int32_t offset = |
| 1037 Array::data_offset() + 4*AddObject(object) - kHeapObjectTag; |
| 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 const int32_t offset = |
1154 Label skip; | 1175 Array::data_offset() + 4*AddExternalLabel(label) - kHeapObjectTag; |
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 // Inline a simplified version of AddConstant(LR, CP, offset12_hi). |
| 1182 ShifterOperand shifter_op; |
| 1183 if (ShifterOperand::CanHold(offset12_hi, &shifter_op)) { |
| 1184 add(LR, CP, shifter_op); |
| 1185 } else { |
| 1186 movw(LR, Utils::Low16Bits(offset12_hi)); |
| 1187 const uint16_t value_high = Utils::High16Bits(offset12_hi); |
| 1188 if (value_high != 0) { |
| 1189 movt(LR, value_high); |
| 1190 } |
| 1191 add(LR, CP, ShifterOperand(LR)); |
| 1192 } |
| 1193 ldr(LR, Address(LR, offset12_lo)); |
| 1194 } |
1158 blx(LR); // Use blx instruction so that the return branch prediction works. | 1195 blx(LR); // Use blx instruction so that the return branch prediction works. |
1159 } | 1196 } |
1160 | 1197 |
1161 | 1198 |
1162 void Assembler::BranchLinkStore(const ExternalLabel* label, Address ad) { | 1199 void Assembler::BranchLinkStore(const ExternalLabel* label, Address ad) { |
1163 // TODO(regis): Revisit this code sequence. | 1200 // TODO(regis): Revisit this code sequence. |
1164 LoadImmediate(IP, label->address()); // Target address is never patched. | 1201 LoadImmediate(IP, label->address()); // Target address is never patched. |
1165 str(PC, ad); | 1202 str(PC, ad); |
1166 blx(IP); // Use blx instruction so that the return branch prediction works. | 1203 blx(IP); // Use blx instruction so that the return branch prediction works. |
1167 } | 1204 } |
(...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1487 offset &= kBranchOffsetMask; | 1524 offset &= kBranchOffsetMask; |
1488 return (inst & ~kBranchOffsetMask) | offset; | 1525 return (inst & ~kBranchOffsetMask) | offset; |
1489 } | 1526 } |
1490 | 1527 |
1491 | 1528 |
1492 int Assembler::DecodeBranchOffset(int32_t inst) { | 1529 int Assembler::DecodeBranchOffset(int32_t inst) { |
1493 // Sign-extend, left-shift by 2, then add 8. | 1530 // Sign-extend, left-shift by 2, then add 8. |
1494 return ((((inst & kBranchOffsetMask) << 8) >> 6) + 8); | 1531 return ((((inst & kBranchOffsetMask) << 8) >> 6) + 8); |
1495 } | 1532 } |
1496 | 1533 |
| 1534 |
| 1535 int32_t Assembler::AddObject(const Object& obj) { |
| 1536 for (int i = 0; i < object_pool_.Length(); i++) { |
| 1537 if (object_pool_.At(i) == obj.raw()) { |
| 1538 return i; |
| 1539 } |
| 1540 } |
| 1541 object_pool_.Add(obj); |
| 1542 return object_pool_.Length(); |
| 1543 } |
| 1544 |
| 1545 |
| 1546 int32_t Assembler::AddExternalLabel(const ExternalLabel* label) { |
| 1547 const uword address = label->address(); |
| 1548 ASSERT(Utils::IsAligned(address, 4)); |
| 1549 // The address is stored in the object array as a RawSmi. |
| 1550 const Smi& smi = Smi::Handle(Smi::New(address >> kSmiTagShift)); |
| 1551 // Do not reuse an existing entry, since each reference may be patched |
| 1552 // independently. |
| 1553 object_pool_.Add(smi); |
| 1554 return object_pool_.Length(); |
| 1555 } |
| 1556 |
1497 } // namespace dart | 1557 } // namespace dart |
1498 | 1558 |
1499 #endif // defined TARGET_ARCH_ARM | 1559 #endif // defined TARGET_ARCH_ARM |
1500 | 1560 |
OLD | NEW |