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_MIPS) | 6 #if defined(TARGET_ARCH_MIPS) |
7 | 7 |
8 #include "vm/assembler.h" | 8 #include "vm/assembler.h" |
9 #include "vm/longjump.h" | 9 #include "vm/longjump.h" |
10 #include "vm/runtime_entry.h" | 10 #include "vm/runtime_entry.h" |
11 #include "vm/simulator.h" | 11 #include "vm/simulator.h" |
12 #include "vm/stack_frame.h" | 12 #include "vm/stack_frame.h" |
13 #include "vm/stub_code.h" | 13 #include "vm/stub_code.h" |
14 | 14 |
15 namespace dart { | 15 namespace dart { |
16 | 16 |
17 #if defined(USING_SIMULATOR) | 17 #if defined(USING_SIMULATOR) |
18 DECLARE_FLAG(bool, trace_sim); | 18 DECLARE_FLAG(bool, trace_sim); |
19 #endif | 19 #endif |
20 DEFINE_FLAG(bool, print_stop_message, false, "Print stop message."); | 20 DEFINE_FLAG(bool, print_stop_message, false, "Print stop message."); |
21 DECLARE_FLAG(bool, inline_alloc); | 21 DECLARE_FLAG(bool, inline_alloc); |
22 | 22 |
23 void Assembler::InitializeMemoryWithBreakpoints(uword data, int length) { | 23 void Assembler::InitializeMemoryWithBreakpoints(uword data, intptr_t length) { |
24 ASSERT(Utils::IsAligned(data, 4)); | 24 ASSERT(Utils::IsAligned(data, 4)); |
25 ASSERT(Utils::IsAligned(length, 4)); | 25 ASSERT(Utils::IsAligned(length, 4)); |
26 const uword end = data + length; | 26 const uword end = data + length; |
27 while (data < end) { | 27 while (data < end) { |
28 *reinterpret_cast<int32_t*>(data) = Instr::kBreakPointInstruction; | 28 *reinterpret_cast<int32_t*>(data) = Instr::kBreakPointInstruction; |
29 data += 4; | 29 data += 4; |
30 } | 30 } |
31 } | 31 } |
32 | 32 |
33 | 33 |
(...skipping 22 matching lines...) Expand all Loading... |
56 1, Object::branch_offset_error()); | 56 1, Object::branch_offset_error()); |
57 } | 57 } |
58 | 58 |
59 // Properly preserve only the bits supported in the instruction. | 59 // Properly preserve only the bits supported in the instruction. |
60 offset >>= 2; | 60 offset >>= 2; |
61 offset &= kBranchOffsetMask; | 61 offset &= kBranchOffsetMask; |
62 return (instr & ~kBranchOffsetMask) | offset; | 62 return (instr & ~kBranchOffsetMask) | offset; |
63 } | 63 } |
64 | 64 |
65 | 65 |
66 static int DecodeBranchOffset(int32_t instr) { | 66 static intptr_t DecodeBranchOffset(int32_t instr) { |
67 // Sign-extend, left-shift by 2. | 67 // Sign-extend, left-shift by 2. |
68 return (((instr & kBranchOffsetMask) << 16) >> 14); | 68 return (((instr & kBranchOffsetMask) << 16) >> 14); |
69 } | 69 } |
70 | 70 |
71 | 71 |
72 static int32_t DecodeLoadImmediate(int32_t ori_instr, int32_t lui_instr) { | 72 static int32_t DecodeLoadImmediate(int32_t ori_instr, int32_t lui_instr) { |
73 return (((lui_instr & kBranchOffsetMask) << 16) | | 73 return (((lui_instr & kBranchOffsetMask) << 16) | |
74 (ori_instr & kBranchOffsetMask)); | 74 (ori_instr & kBranchOffsetMask)); |
75 } | 75 } |
76 | 76 |
77 | 77 |
78 static int32_t EncodeLoadImmediate(int32_t dest, int32_t instr) { | 78 static int32_t EncodeLoadImmediate(int32_t dest, int32_t instr) { |
79 return ((instr & ~kBranchOffsetMask) | (dest & kBranchOffsetMask)); | 79 return ((instr & ~kBranchOffsetMask) | (dest & kBranchOffsetMask)); |
80 } | 80 } |
81 | 81 |
82 | 82 |
83 class PatchFarJump : public AssemblerFixup { | 83 class PatchFarJump : public AssemblerFixup { |
84 public: | 84 public: |
85 PatchFarJump() {} | 85 PatchFarJump() {} |
86 | 86 |
87 void Process(const MemoryRegion& region, int position) { | 87 void Process(const MemoryRegion& region, intptr_t position) { |
88 const int32_t high = region.Load<int32_t>(position); | 88 const int32_t high = region.Load<int32_t>(position); |
89 const int32_t low = region.Load<int32_t>(position + Instr::kInstrSize); | 89 const int32_t low = region.Load<int32_t>(position + Instr::kInstrSize); |
90 const int32_t offset = DecodeLoadImmediate(low, high); | 90 const int32_t offset = DecodeLoadImmediate(low, high); |
91 const int32_t dest = region.start() + offset; | 91 const int32_t dest = region.start() + offset; |
92 | 92 |
93 if ((Instr::At(reinterpret_cast<uword>(&high))->OpcodeField() == LUI) && | 93 if ((Instr::At(reinterpret_cast<uword>(&high))->OpcodeField() == LUI) && |
94 (Instr::At(reinterpret_cast<uword>(&low))->OpcodeField() == ORI)) { | 94 (Instr::At(reinterpret_cast<uword>(&low))->OpcodeField() == ORI)) { |
95 // Change the offset to the absolute value. | 95 // Change the offset to the absolute value. |
96 const int32_t encoded_low = | 96 const int32_t encoded_low = |
97 EncodeLoadImmediate(dest & kBranchOffsetMask, low); | 97 EncodeLoadImmediate(dest & kBranchOffsetMask, low); |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
184 // Relative destination from an instruction after the branch. | 184 // Relative destination from an instruction after the branch. |
185 const int32_t dest = | 185 const int32_t dest = |
186 label->Position() - (buffer_.Size() + Instr::kInstrSize); | 186 label->Position() - (buffer_.Size() + Instr::kInstrSize); |
187 if (use_far_branches() && !CanEncodeBranchOffset(dest)) { | 187 if (use_far_branches() && !CanEncodeBranchOffset(dest)) { |
188 EmitFarBranch(b, rs, rt, label->Position()); | 188 EmitFarBranch(b, rs, rt, label->Position()); |
189 } else { | 189 } else { |
190 const uint16_t dest_off = EncodeBranchOffset(dest, 0); | 190 const uint16_t dest_off = EncodeBranchOffset(dest, 0); |
191 EmitIType(b, rs, rt, dest_off); | 191 EmitIType(b, rs, rt, dest_off); |
192 } | 192 } |
193 } else { | 193 } else { |
194 const int position = buffer_.Size(); | 194 const intptr_t position = buffer_.Size(); |
195 if (use_far_branches()) { | 195 if (use_far_branches()) { |
196 const uint32_t dest_off = label->position_; | 196 const uint32_t dest_off = label->position_; |
197 EmitFarBranch(b, rs, rt, dest_off); | 197 EmitFarBranch(b, rs, rt, dest_off); |
198 } else { | 198 } else { |
199 const uint16_t dest_off = EncodeBranchOffset(label->position_, 0); | 199 const uint16_t dest_off = EncodeBranchOffset(label->position_, 0); |
200 EmitIType(b, rs, rt, dest_off); | 200 EmitIType(b, rs, rt, dest_off); |
201 } | 201 } |
202 label->LinkTo(position); | 202 label->LinkTo(position); |
203 } | 203 } |
204 } | 204 } |
205 | 205 |
206 | 206 |
207 void Assembler::EmitRegImmBranch(RtRegImm b, Register rs, Label* label) { | 207 void Assembler::EmitRegImmBranch(RtRegImm b, Register rs, Label* label) { |
208 if (label->IsBound()) { | 208 if (label->IsBound()) { |
209 // Relative destination from an instruction after the branch. | 209 // Relative destination from an instruction after the branch. |
210 const int32_t dest = | 210 const int32_t dest = |
211 label->Position() - (buffer_.Size() + Instr::kInstrSize); | 211 label->Position() - (buffer_.Size() + Instr::kInstrSize); |
212 if (use_far_branches() && !CanEncodeBranchOffset(dest)) { | 212 if (use_far_branches() && !CanEncodeBranchOffset(dest)) { |
213 EmitFarRegImmBranch(b, rs, label->Position()); | 213 EmitFarRegImmBranch(b, rs, label->Position()); |
214 } else { | 214 } else { |
215 const uint16_t dest_off = EncodeBranchOffset(dest, 0); | 215 const uint16_t dest_off = EncodeBranchOffset(dest, 0); |
216 EmitRegImmType(REGIMM, rs, b, dest_off); | 216 EmitRegImmType(REGIMM, rs, b, dest_off); |
217 } | 217 } |
218 } else { | 218 } else { |
219 const int position = buffer_.Size(); | 219 const intptr_t position = buffer_.Size(); |
220 if (use_far_branches()) { | 220 if (use_far_branches()) { |
221 const uint32_t dest_off = label->position_; | 221 const uint32_t dest_off = label->position_; |
222 EmitFarRegImmBranch(b, rs, dest_off); | 222 EmitFarRegImmBranch(b, rs, dest_off); |
223 } else { | 223 } else { |
224 const uint16_t dest_off = EncodeBranchOffset(label->position_, 0); | 224 const uint16_t dest_off = EncodeBranchOffset(label->position_, 0); |
225 EmitRegImmType(REGIMM, rs, b, dest_off); | 225 EmitRegImmType(REGIMM, rs, b, dest_off); |
226 } | 226 } |
227 label->LinkTo(position); | 227 label->LinkTo(position); |
228 } | 228 } |
229 } | 229 } |
230 | 230 |
231 | 231 |
232 void Assembler::EmitFpuBranch(bool kind, Label *label) { | 232 void Assembler::EmitFpuBranch(bool kind, Label *label) { |
233 const int32_t b16 = kind ? (1 << 16) : 0; // Bit 16 set for branch on true. | 233 const int32_t b16 = kind ? (1 << 16) : 0; // Bit 16 set for branch on true. |
234 if (label->IsBound()) { | 234 if (label->IsBound()) { |
235 // Relative destination from an instruction after the branch. | 235 // Relative destination from an instruction after the branch. |
236 const int32_t dest = | 236 const int32_t dest = |
237 label->Position() - (buffer_.Size() + Instr::kInstrSize); | 237 label->Position() - (buffer_.Size() + Instr::kInstrSize); |
238 if (use_far_branches() && !CanEncodeBranchOffset(dest)) { | 238 if (use_far_branches() && !CanEncodeBranchOffset(dest)) { |
239 EmitFarFpuBranch(kind, label->Position()); | 239 EmitFarFpuBranch(kind, label->Position()); |
240 } else { | 240 } else { |
241 const uint16_t dest_off = EncodeBranchOffset(dest, 0); | 241 const uint16_t dest_off = EncodeBranchOffset(dest, 0); |
242 Emit(COP1 << kOpcodeShift | | 242 Emit(COP1 << kOpcodeShift | |
243 COP1_BC << kCop1SubShift | | 243 COP1_BC << kCop1SubShift | |
244 b16 | | 244 b16 | |
245 dest_off); | 245 dest_off); |
246 } | 246 } |
247 } else { | 247 } else { |
248 const int position = buffer_.Size(); | 248 const intptr_t position = buffer_.Size(); |
249 if (use_far_branches()) { | 249 if (use_far_branches()) { |
250 const uint32_t dest_off = label->position_; | 250 const uint32_t dest_off = label->position_; |
251 EmitFarFpuBranch(kind, dest_off); | 251 EmitFarFpuBranch(kind, dest_off); |
252 } else { | 252 } else { |
253 const uint16_t dest_off = EncodeBranchOffset(label->position_, 0); | 253 const uint16_t dest_off = EncodeBranchOffset(label->position_, 0); |
254 Emit(COP1 << kOpcodeShift | | 254 Emit(COP1 << kOpcodeShift | |
255 COP1_BC << kCop1SubShift | | 255 COP1_BC << kCop1SubShift | |
256 b16 | | 256 b16 | |
257 dest_off); | 257 dest_off); |
258 } | 258 } |
(...skipping 12 matching lines...) Expand all Loading... |
271 return instr ^ (1 << 16); | 271 return instr ^ (1 << 16); |
272 } | 272 } |
273 Opcode b = OppositeBranchOpcode(i->OpcodeField()); | 273 Opcode b = OppositeBranchOpcode(i->OpcodeField()); |
274 i->SetOpcodeField(b); | 274 i->SetOpcodeField(b); |
275 return i->InstructionBits(); | 275 return i->InstructionBits(); |
276 } | 276 } |
277 | 277 |
278 | 278 |
279 void Assembler::Bind(Label* label) { | 279 void Assembler::Bind(Label* label) { |
280 ASSERT(!label->IsBound()); | 280 ASSERT(!label->IsBound()); |
281 int bound_pc = buffer_.Size(); | 281 intptr_t bound_pc = buffer_.Size(); |
282 | 282 |
283 while (label->IsLinked()) { | 283 while (label->IsLinked()) { |
284 int32_t position = label->Position(); | 284 int32_t position = label->Position(); |
285 int32_t dest = bound_pc - (position + Instr::kInstrSize); | 285 int32_t dest = bound_pc - (position + Instr::kInstrSize); |
286 | 286 |
287 if (use_far_branches() && !CanEncodeBranchOffset(dest)) { | 287 if (use_far_branches() && !CanEncodeBranchOffset(dest)) { |
288 // Far branches are enabled and we can't encode the branch offset. | 288 // Far branches are enabled and we can't encode the branch offset. |
289 | 289 |
290 // Grab the branch instruction. We'll need to flip it later. | 290 // Grab the branch instruction. We'll need to flip it later. |
291 const int32_t branch = buffer_.Load<int32_t>(position); | 291 const int32_t branch = buffer_.Load<int32_t>(position); |
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
465 | 465 |
466 | 466 |
467 int32_t Assembler::AddObject(const Object& obj) { | 467 int32_t Assembler::AddObject(const Object& obj) { |
468 ASSERT(obj.IsNotTemporaryScopedHandle()); | 468 ASSERT(obj.IsNotTemporaryScopedHandle()); |
469 ASSERT(obj.IsOld()); | 469 ASSERT(obj.IsOld()); |
470 if (object_pool_.IsNull()) { | 470 if (object_pool_.IsNull()) { |
471 // The object pool cannot be used in the vm isolate. | 471 // The object pool cannot be used in the vm isolate. |
472 ASSERT(Isolate::Current() != Dart::vm_isolate()); | 472 ASSERT(Isolate::Current() != Dart::vm_isolate()); |
473 object_pool_ = GrowableObjectArray::New(Heap::kOld); | 473 object_pool_ = GrowableObjectArray::New(Heap::kOld); |
474 } | 474 } |
475 for (int i = 0; i < object_pool_.Length(); i++) { | 475 for (intptr_t i = 0; i < object_pool_.Length(); i++) { |
476 if (object_pool_.At(i) == obj.raw()) { | 476 if (object_pool_.At(i) == obj.raw()) { |
477 return i; | 477 return i; |
478 } | 478 } |
479 } | 479 } |
480 object_pool_.Add(obj, Heap::kOld); | 480 object_pool_.Add(obj, Heap::kOld); |
481 return object_pool_.Length() - 1; | 481 return object_pool_.Length() - 1; |
482 } | 482 } |
483 | 483 |
484 | 484 |
485 void Assembler::PushObject(const Object& object) { | 485 void Assembler::PushObject(const Object& object) { |
(...skipping 492 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
978 Bind(&msg); | 978 Bind(&msg); |
979 break_(Instr::kMsgMessageCode); | 979 break_(Instr::kMsgMessageCode); |
980 } | 980 } |
981 #endif | 981 #endif |
982 } | 982 } |
983 | 983 |
984 } // namespace dart | 984 } // namespace dart |
985 | 985 |
986 #endif // defined TARGET_ARCH_MIPS | 986 #endif // defined TARGET_ARCH_MIPS |
987 | 987 |
OLD | NEW |