Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 #ifndef VM_ASSEMBLER_ARM64_H_ | 5 #ifndef VM_ASSEMBLER_ARM64_H_ |
| 6 #define VM_ASSEMBLER_ARM64_H_ | 6 #define VM_ASSEMBLER_ARM64_H_ |
| 7 | 7 |
| 8 #ifndef VM_ASSEMBLER_H_ | 8 #ifndef VM_ASSEMBLER_H_ |
| 9 #error Do not include assembler_arm64.h directly; use assembler.h instead. | 9 #error Do not include assembler_arm64.h directly; use assembler.h instead. |
| 10 #endif | 10 #endif |
| 11 | 11 |
| 12 #include "platform/assert.h" | 12 #include "platform/assert.h" |
| 13 #include "platform/utils.h" | 13 #include "platform/utils.h" |
| 14 #include "vm/constants_arm64.h" | 14 #include "vm/constants_arm64.h" |
| 15 #include "vm/hash_map.h" | 15 #include "vm/hash_map.h" |
| 16 #include "vm/longjump.h" | |
| 16 #include "vm/object.h" | 17 #include "vm/object.h" |
| 17 #include "vm/simulator.h" | 18 #include "vm/simulator.h" |
| 18 | 19 |
| 19 namespace dart { | 20 namespace dart { |
| 20 | 21 |
| 21 // Forward declarations. | 22 // Forward declarations. |
| 22 class RuntimeEntry; | 23 class RuntimeEntry; |
| 23 | 24 |
| 24 // TODO(zra): Label, Address, and FieldAddress are copied from ARM, | 25 // TODO(zra): Label, Address, and FieldAddress are copied from ARM, |
| 25 // they must be adapted to ARM64. | 26 // they must be adapted to ARM64. |
| (...skipping 568 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 594 } else { | 595 } else { |
| 595 cmp(rn, Operand(rm)); | 596 cmp(rn, Operand(rm)); |
| 596 } | 597 } |
| 597 } | 598 } |
| 598 | 599 |
| 599 // Conditional branch. | 600 // Conditional branch. |
| 600 void b(Label* label, Condition cond = AL) { | 601 void b(Label* label, Condition cond = AL) { |
| 601 EmitBranch(BCOND, cond, label); | 602 EmitBranch(BCOND, cond, label); |
| 602 } | 603 } |
| 603 | 604 |
| 604 // TODO(zra): branch and link with imm26 offset. | 605 void b(int32_t offset) { |
| 606 EmitUnconditionalBranchOp(B, offset); | |
| 607 } | |
| 608 void bl(int32_t offset) { | |
| 609 EmitUnconditionalBranchOp(BL, offset); | |
| 610 } | |
| 611 | |
| 605 // TODO(zra): cbz, cbnz. | 612 // TODO(zra): cbz, cbnz. |
| 606 | 613 |
| 607 // Branch, link, return. | 614 // Branch, link, return. |
| 608 void br(Register rn) { | 615 void br(Register rn) { |
| 609 EmitUnconditionalBranchRegOp(BR, rn); | 616 EmitUnconditionalBranchRegOp(BR, rn); |
| 610 } | 617 } |
| 611 void blr(Register rn) { | 618 void blr(Register rn) { |
| 612 EmitUnconditionalBranchRegOp(BLR, rn); | 619 EmitUnconditionalBranchRegOp(BLR, rn); |
| 613 } | 620 } |
| 614 void ret(Register rn = R30) { | 621 void ret(Register rn = R30) { |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 794 } | 801 } |
| 795 | 802 |
| 796 // Fixed length branch to label. | 803 // Fixed length branch to label. |
| 797 void BranchPatchable(const ExternalLabel* label) { | 804 void BranchPatchable(const ExternalLabel* label) { |
| 798 // TODO(zra): Use LoadExternalLabelFixed if possible. | 805 // TODO(zra): Use LoadExternalLabelFixed if possible. |
| 799 LoadImmediateFixed(TMP, label->address()); | 806 LoadImmediateFixed(TMP, label->address()); |
| 800 br(TMP); | 807 br(TMP); |
| 801 } | 808 } |
| 802 | 809 |
| 803 void BranchLink(const ExternalLabel* label, Register pp) { | 810 void BranchLink(const ExternalLabel* label, Register pp) { |
| 804 if (Isolate::Current() == Dart::vm_isolate()) { | 811 if ((Isolate::Current() == Dart::vm_isolate()) || (pp == kNoPP)) { |
|
regis
2014/05/12 16:05:02
Can you add a comment explaining this?
zra
2014/05/12 18:42:50
Moved this logic into LoadExternalLabel, and there
| |
| 805 LoadImmediate(TMP, label->address(), kNoPP); | 812 LoadImmediate(TMP, label->address(), kNoPP); |
| 806 blr(TMP); | 813 blr(TMP); |
| 807 } else { | 814 } else { |
| 808 LoadExternalLabel(TMP, label, kNotPatchable, pp); | 815 LoadExternalLabel(TMP, label, kNotPatchable, pp); |
| 809 blr(TMP); | 816 blr(TMP); |
| 810 } | 817 } |
| 811 } | 818 } |
| 812 | 819 |
| 813 // BranchLinkPatchable must be a fixed-length sequence so we can patch it | 820 // BranchLinkPatchable must be a fixed-length sequence so we can patch it |
| 814 // with the debugger. | 821 // with the debugger. |
| (...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1119 const int32_t s = set_flags ? B29 : 0; | 1126 const int32_t s = set_flags ? B29 : 0; |
| 1120 const int32_t encoding = | 1127 const int32_t encoding = |
| 1121 op | size | s | | 1128 op | size | s | |
| 1122 (static_cast<int32_t>(rd) << kRdShift) | | 1129 (static_cast<int32_t>(rd) << kRdShift) | |
| 1123 (static_cast<int32_t>(rn) << kRnShift) | | 1130 (static_cast<int32_t>(rn) << kRnShift) | |
| 1124 o.encoding(); | 1131 o.encoding(); |
| 1125 Emit(encoding); | 1132 Emit(encoding); |
| 1126 } | 1133 } |
| 1127 | 1134 |
| 1128 int32_t EncodeImm19BranchOffset(int64_t imm, int32_t instr) { | 1135 int32_t EncodeImm19BranchOffset(int64_t imm, int32_t instr) { |
| 1136 if (!CanEncodeImm19BranchOffset(imm)) { | |
| 1137 ASSERT(!use_far_branches()); | |
| 1138 Isolate::Current()->long_jump_base()->Jump( | |
| 1139 1, Object::branch_offset_error()); | |
| 1140 } | |
| 1129 const int32_t imm32 = static_cast<int32_t>(imm); | 1141 const int32_t imm32 = static_cast<int32_t>(imm); |
| 1130 const int32_t off = (((imm32 >> 2) << kImm19Shift) & kImm19Mask); | 1142 const int32_t off = (((imm32 >> 2) << kImm19Shift) & kImm19Mask); |
| 1131 return (instr & ~kImm19Mask) | off; | 1143 return (instr & ~kImm19Mask) | off; |
| 1132 } | 1144 } |
| 1133 | 1145 |
| 1134 int64_t DecodeImm19BranchOffset(int32_t instr) { | 1146 int64_t DecodeImm19BranchOffset(int32_t instr) { |
| 1135 const int32_t off = (((instr & kImm19Mask) >> kImm19Shift) << 13) >> 11; | 1147 const int32_t off = (((instr & kImm19Mask) >> kImm19Shift) << 13) >> 11; |
| 1136 return static_cast<int64_t>(off); | 1148 return static_cast<int64_t>(off); |
| 1137 } | 1149 } |
| 1138 | 1150 |
| 1151 Condition DecodeImm19BranchCondition(int32_t instr) { | |
| 1152 return static_cast<Condition>((instr & kCondMask) >> kCondShift); | |
| 1153 } | |
| 1154 | |
| 1155 int32_t EncodeImm19BranchCondition(Condition cond, int32_t instr) { | |
| 1156 const int32_t c_imm = static_cast<int32_t>(cond); | |
| 1157 return (instr & ~kCondMask) | (c_imm << kCondShift); | |
| 1158 } | |
| 1159 | |
| 1160 int32_t EncodeImm26BranchOffset(int64_t imm, int32_t instr) { | |
| 1161 const int32_t imm32 = static_cast<int32_t>(imm); | |
| 1162 const int32_t off = (((imm32 >> 2) << kImm26Shift) & kImm26Mask); | |
| 1163 return (instr & ~kImm26Mask) | off; | |
| 1164 } | |
| 1165 | |
| 1166 int64_t DecodeImm26BranchOffset(int32_t instr) { | |
| 1167 const int32_t off = (((instr & kImm26Mask) >> kImm26Shift) << 6) >> 4; | |
| 1168 return static_cast<int64_t>(off); | |
| 1169 } | |
| 1170 | |
| 1139 void EmitCompareAndBranch(CompareAndBranchOp op, Register rt, int64_t imm, | 1171 void EmitCompareAndBranch(CompareAndBranchOp op, Register rt, int64_t imm, |
| 1140 OperandSize sz) { | 1172 OperandSize sz) { |
| 1141 ASSERT((sz == kDoubleWord) || (sz == kWord) || (sz == kUnsignedWord)); | 1173 ASSERT((sz == kDoubleWord) || (sz == kWord) || (sz == kUnsignedWord)); |
| 1142 ASSERT(Utils::IsInt(21, imm) && ((imm & 0x3) == 0)); | 1174 ASSERT(Utils::IsInt(21, imm) && ((imm & 0x3) == 0)); |
| 1143 ASSERT((rt != SP) && (rt != R31)); | 1175 ASSERT((rt != SP) && (rt != R31)); |
| 1144 const Register crt = ConcreteRegister(rt); | 1176 const Register crt = ConcreteRegister(rt); |
| 1145 const int32_t size = (sz == kDoubleWord) ? B31 : 0; | 1177 const int32_t size = (sz == kDoubleWord) ? B31 : 0; |
| 1146 const int32_t encoded_offset = EncodeImm19BranchOffset(imm, 0); | 1178 const int32_t encoded_offset = EncodeImm19BranchOffset(imm, 0); |
| 1147 const int32_t encoding = | 1179 const int32_t encoding = |
| 1148 op | size | | 1180 op | size | |
| 1149 (static_cast<int32_t>(crt) << kRtShift) | | 1181 (static_cast<int32_t>(crt) << kRtShift) | |
| 1150 encoded_offset; | 1182 encoded_offset; |
| 1151 Emit(encoding); | 1183 Emit(encoding); |
| 1152 } | 1184 } |
| 1153 | 1185 |
| 1154 void EmitConditionalBranch(ConditionalBranchOp op, Condition cond, | 1186 void EmitConditionalBranch(ConditionalBranchOp op, Condition cond, |
| 1155 int64_t imm) { | 1187 int64_t imm) { |
| 1156 ASSERT(Utils::IsInt(21, imm) && ((imm & 0x3) == 0)); | 1188 ASSERT(Utils::IsInt(21, imm) && ((imm & 0x3) == 0)); |
| 1157 const int32_t encoding = | 1189 const int32_t encoding = |
| 1158 op | | 1190 op | |
| 1159 (static_cast<int32_t>(cond) << kCondShift) | | 1191 (static_cast<int32_t>(cond) << kCondShift) | |
| 1160 (((imm >> 2) << kImm19Shift) & kImm19Mask); | 1192 (((imm >> 2) << kImm19Shift) & kImm19Mask); |
| 1161 Emit(encoding); | 1193 Emit(encoding); |
| 1162 } | 1194 } |
| 1163 | 1195 |
| 1196 void EmitFarConditionalBranch(ConditionalBranchOp op, | |
| 1197 Condition cond, | |
| 1198 int64_t offset) { | |
| 1199 EmitConditionalBranch(op, InvertCondition(cond), 2 * Instr::kInstrSize); | |
| 1200 b(offset); | |
| 1201 } | |
| 1202 | |
| 1164 bool CanEncodeImm19BranchOffset(int64_t offset) { | 1203 bool CanEncodeImm19BranchOffset(int64_t offset) { |
| 1165 ASSERT(Utils::IsAligned(offset, 4)); | 1204 ASSERT(Utils::IsAligned(offset, 4)); |
| 1166 return Utils::IsInt(21, offset); | 1205 return Utils::IsInt(21, offset); |
| 1167 } | 1206 } |
| 1168 | 1207 |
| 1169 // TODO(zra): Implement far branches. Requires loading large immediates. | |
| 1170 void EmitBranch(ConditionalBranchOp op, Condition cond, Label* label) { | 1208 void EmitBranch(ConditionalBranchOp op, Condition cond, Label* label) { |
| 1171 if (label->IsBound()) { | 1209 if (label->IsBound()) { |
| 1172 const int64_t dest = label->Position() - buffer_.Size(); | 1210 const int64_t dest = label->Position() - buffer_.Size(); |
| 1173 ASSERT(CanEncodeImm19BranchOffset(dest)); | 1211 if (use_far_branches() && !CanEncodeImm19BranchOffset(dest)) { |
| 1174 EmitConditionalBranch(op, cond, dest); | 1212 EmitFarConditionalBranch(op, cond, dest); |
| 1213 } else { | |
| 1214 EmitConditionalBranch(op, cond, dest); | |
| 1215 } | |
| 1175 } else { | 1216 } else { |
| 1176 const int64_t position = buffer_.Size(); | 1217 const int64_t position = buffer_.Size(); |
| 1177 ASSERT(CanEncodeImm19BranchOffset(position)); | 1218 if (use_far_branches()) { |
| 1178 EmitConditionalBranch(op, cond, label->position_); | 1219 EmitFarConditionalBranch(op, cond, label->position_); |
| 1220 } else { | |
| 1221 EmitConditionalBranch(op, cond, label->position_); | |
| 1222 } | |
| 1179 label->LinkTo(position); | 1223 label->LinkTo(position); |
| 1180 } | 1224 } |
| 1181 } | 1225 } |
| 1182 | 1226 |
| 1227 bool CanEncodeImm26BranchOffset(int64_t offset) { | |
| 1228 ASSERT(Utils::IsAligned(offset, 4)); | |
| 1229 return Utils::IsInt(26, offset); | |
| 1230 } | |
| 1231 | |
| 1232 void EmitUnconditionalBranchOp(UnconditionalBranchOp op, int64_t offset) { | |
| 1233 ASSERT(CanEncodeImm26BranchOffset(offset)); | |
| 1234 const int32_t off = (offset >> 2) << kImm26Shift; | |
| 1235 const int32_t encoding = op | off; | |
| 1236 Emit(encoding); | |
| 1237 } | |
| 1238 | |
| 1183 void EmitUnconditionalBranchRegOp(UnconditionalBranchRegOp op, Register rn) { | 1239 void EmitUnconditionalBranchRegOp(UnconditionalBranchRegOp op, Register rn) { |
| 1184 ASSERT((rn != SP) && (rn != R31)); | 1240 ASSERT((rn != SP) && (rn != R31)); |
| 1185 const Register crn = ConcreteRegister(rn); | 1241 const Register crn = ConcreteRegister(rn); |
| 1186 const int32_t encoding = | 1242 const int32_t encoding = |
| 1187 op | (static_cast<int32_t>(crn) << kRnShift); | 1243 op | (static_cast<int32_t>(crn) << kRnShift); |
| 1188 Emit(encoding); | 1244 Emit(encoding); |
| 1189 } | 1245 } |
| 1190 | 1246 |
| 1191 void EmitExceptionGenOp(ExceptionGenOp op, uint16_t imm) { | 1247 void EmitExceptionGenOp(ExceptionGenOp op, uint16_t imm) { |
| 1192 const int32_t encoding = | 1248 const int32_t encoding = |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1346 Register value, | 1402 Register value, |
| 1347 Label* no_update); | 1403 Label* no_update); |
| 1348 | 1404 |
| 1349 DISALLOW_ALLOCATION(); | 1405 DISALLOW_ALLOCATION(); |
| 1350 DISALLOW_COPY_AND_ASSIGN(Assembler); | 1406 DISALLOW_COPY_AND_ASSIGN(Assembler); |
| 1351 }; | 1407 }; |
| 1352 | 1408 |
| 1353 } // namespace dart | 1409 } // namespace dart |
| 1354 | 1410 |
| 1355 #endif // VM_ASSEMBLER_ARM64_H_ | 1411 #endif // VM_ASSEMBLER_ARM64_H_ |
| OLD | NEW |