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 |