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 #ifndef VM_ASSEMBLER_MIPS_H_ | 5 #ifndef VM_ASSEMBLER_MIPS_H_ |
6 #define VM_ASSEMBLER_MIPS_H_ | 6 #define VM_ASSEMBLER_MIPS_H_ |
7 | 7 |
8 #ifndef VM_ASSEMBLER_H_ | 8 #ifndef VM_ASSEMBLER_H_ |
9 #error Do not include assembler_mips.h directly; use assembler.h instead. | 9 #error Do not include assembler_mips.h directly; use assembler.h instead. |
10 #endif | 10 #endif |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
140 prologue_offset_(-1), | 140 prologue_offset_(-1), |
141 delay_slot_available_(false), | 141 delay_slot_available_(false), |
142 in_delay_slot_(false), | 142 in_delay_slot_(false), |
143 comments_() { } | 143 comments_() { } |
144 ~Assembler() { } | 144 ~Assembler() { } |
145 | 145 |
146 void PopRegister(Register r) { | 146 void PopRegister(Register r) { |
147 UNIMPLEMENTED(); | 147 UNIMPLEMENTED(); |
148 } | 148 } |
149 | 149 |
150 void Bind(Label* label) { | 150 void Bind(Label* label); |
151 UNIMPLEMENTED(); | |
152 } | |
153 | 151 |
154 // Misc. functionality | 152 // Misc. functionality |
155 int CodeSize() const { return buffer_.Size(); } | 153 int CodeSize() const { return buffer_.Size(); } |
156 int prologue_offset() const { return -1; } | 154 int prologue_offset() const { return -1; } |
157 const ZoneGrowableArray<int>& GetPointerOffsets() const { | 155 const ZoneGrowableArray<int>& GetPointerOffsets() const { |
158 return buffer_.pointer_offsets(); | 156 return buffer_.pointer_offsets(); |
159 } | 157 } |
160 const GrowableObjectArray& object_pool() const { return object_pool_; } | 158 const GrowableObjectArray& object_pool() const { return object_pool_; } |
161 void FinalizeInstructions(const MemoryRegion& region) { | 159 void FinalizeInstructions(const MemoryRegion& region) { |
162 buffer_.FinalizeInstructions(region); | 160 buffer_.FinalizeInstructions(region); |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
238 void and_(Register rd, Register rs, Register rt) { | 236 void and_(Register rd, Register rs, Register rt) { |
239 EmitRType(SPECIAL, rs, rt, rd, 0, AND); | 237 EmitRType(SPECIAL, rs, rt, rd, 0, AND); |
240 } | 238 } |
241 | 239 |
242 void andi(Register rt, Register rs, const Immediate& imm) { | 240 void andi(Register rt, Register rs, const Immediate& imm) { |
243 ASSERT(Utils::IsUint(16, imm.value())); | 241 ASSERT(Utils::IsUint(16, imm.value())); |
244 uint16_t imm_value = static_cast<uint16_t>(imm.value()); | 242 uint16_t imm_value = static_cast<uint16_t>(imm.value()); |
245 EmitIType(ANDI, rs, rt, imm_value); | 243 EmitIType(ANDI, rs, rt, imm_value); |
246 } | 244 } |
247 | 245 |
246 // Branch if equal. | |
247 void beq(Register rs, Register rt, Label* l) { | |
248 ASSERT(!in_delay_slot_); // Jump within a delay slot is not supported. | |
regis
2013/03/22 19:51:16
Either remove this comment or add it consistently
zra
2013/03/22 20:16:01
Done.
| |
249 EmitBranch(BEQ, rs, rt, l); | |
250 EmitBranchDelayNop(); | |
251 } | |
252 | |
253 // Branch if equal, likely taken. | |
254 // Delay slot executed only when branch taken. | |
255 void beql(Register rs, Register rt, Label* l) { | |
256 ASSERT(!in_delay_slot_); // Jump within a delay slot is not supported. | |
257 EmitBranch(BEQL, rs, rt, l); | |
258 EmitBranchDelayNop(); | |
259 } | |
260 | |
261 // Brach if rs >= 0. | |
regis
2013/03/22 19:51:16
Branch
zra
2013/03/22 20:16:01
Done.
| |
262 void bgez(Register rs, Label* l) { | |
263 ASSERT(!in_delay_slot_); | |
264 EmitRegImmBranch(BGEZ, rs, l); | |
265 EmitBranchDelayNop(); | |
266 } | |
267 | |
268 // Branch if rs >= 0, likely taken. | |
269 // Delay slot executed only when branch taken. | |
270 void bgezl(Register rs, Label* l) { | |
271 ASSERT(!in_delay_slot_); | |
272 EmitRegImmBranch(BGEZL, rs, l); | |
273 EmitBranchDelayNop(); | |
274 } | |
275 | |
276 // Brach if rs > 0. | |
regis
2013/03/22 19:51:16
Branch
zra
2013/03/22 20:16:01
Done.
| |
277 void bgtz(Register rs, Label* l) { | |
278 ASSERT(!in_delay_slot_); | |
279 EmitBranch(BGTZ, rs, R0, l); | |
280 EmitBranchDelayNop(); | |
281 } | |
282 | |
283 // Branch if rs > 0, likely taken. | |
284 // Delay slot executed only when branch taken. | |
285 void bgtzl(Register rs, Label* l) { | |
286 ASSERT(!in_delay_slot_); | |
287 EmitBranch(BGTZL, rs, R0, l); | |
288 EmitBranchDelayNop(); | |
289 } | |
290 | |
291 // Brach if rs <= 0. | |
regis
2013/03/22 19:51:16
Branch
zra
2013/03/22 20:16:01
Done.
| |
292 void blez(Register rs, Label* l) { | |
293 ASSERT(!in_delay_slot_); | |
294 EmitBranch(BLEZ, rs, R0, l); | |
295 EmitBranchDelayNop(); | |
296 } | |
297 | |
298 // Branch if rs <= 0, likely taken. | |
299 // Delay slot executed only when branch taken. | |
300 void blezl(Register rs, Label* l) { | |
301 ASSERT(!in_delay_slot_); | |
302 EmitBranch(BLEZL, rs, R0, l); | |
303 EmitBranchDelayNop(); | |
304 } | |
305 | |
306 // Brach if rs < 0. | |
regis
2013/03/22 19:51:16
Branch
zra
2013/03/22 20:16:01
Done.
| |
307 void bltz(Register rs, Label* l) { | |
308 ASSERT(!in_delay_slot_); | |
309 EmitRegImmBranch(BLTZ, rs, l); | |
310 EmitBranchDelayNop(); | |
311 } | |
312 | |
313 // Branch if rs < 0, likely taken. | |
314 // Delay slot executed only when branch taken. | |
315 void bltzl(Register rs, Label* l) { | |
316 ASSERT(!in_delay_slot_); | |
317 EmitRegImmBranch(BLTZL, rs, l); | |
318 EmitBranchDelayNop(); | |
319 } | |
320 | |
321 // Branch if not equal. | |
322 void bne(Register rs, Register rt, Label* l) { | |
323 ASSERT(!in_delay_slot_); // Jump within a delay slot is not supported. | |
324 EmitBranch(BNE, rs, rt, l); | |
325 EmitBranchDelayNop(); | |
326 } | |
327 | |
328 // Branch if not equal, likely taken. | |
329 // Delay slot executed only when branch taken. | |
330 void bnel(Register rs, Register rt, Label* l) { | |
331 ASSERT(!in_delay_slot_); // Jump within a delay slot is not supported. | |
332 EmitBranch(BNEL, rs, rt, l); | |
333 EmitBranchDelayNop(); | |
334 } | |
335 | |
248 void break_(int32_t code) { | 336 void break_(int32_t code) { |
249 ASSERT(Utils::IsUint(20, code)); | 337 ASSERT(Utils::IsUint(20, code)); |
250 Emit(SPECIAL << kOpcodeShift | | 338 Emit(SPECIAL << kOpcodeShift | |
251 code << kBreakCodeShift | | 339 code << kBreakCodeShift | |
252 BREAK << kFunctionShift); | 340 BREAK << kFunctionShift); |
253 } | 341 } |
254 | 342 |
255 void clo(Register rd, Register rs) { | 343 void clo(Register rd, Register rs) { |
256 EmitRType(SPECIAL2, rs, rd, rd, 0, CLO); | 344 EmitRType(SPECIAL2, rs, rd, rd, 0, CLO); |
257 } | 345 } |
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
395 | 483 |
396 void sw(Register rt, const Address& addr) { | 484 void sw(Register rt, const Address& addr) { |
397 EmitLoadStore(SW, rt, addr); | 485 EmitLoadStore(SW, rt, addr); |
398 } | 486 } |
399 | 487 |
400 void xor_(Register rd, Register rs, Register rt) { | 488 void xor_(Register rd, Register rs, Register rt) { |
401 EmitRType(SPECIAL, rs, rt, rd, 0, XOR); | 489 EmitRType(SPECIAL, rs, rt, rd, 0, XOR); |
402 } | 490 } |
403 | 491 |
404 // Macros in alphabetical order. | 492 // Macros in alphabetical order. |
493 | |
494 // Unconditional branch. | |
495 void B(Label* l) { | |
regis
2013/03/22 19:51:16
I would use a lower case 'b', since the MIPS assem
zra
2013/03/22 20:16:01
That makes sense. I've made it lowercase and moved
| |
496 beq(R0, R0, l); | |
497 } | |
498 | |
405 void LoadImmediate(Register rd, int32_t value) { | 499 void LoadImmediate(Register rd, int32_t value) { |
406 if (Utils::IsInt(16, value)) { | 500 if (Utils::IsInt(16, value)) { |
407 addiu(rd, ZR, Immediate(value)); | 501 addiu(rd, ZR, Immediate(value)); |
408 } else { | 502 } else { |
409 lui(rd, Immediate((value >> 16) & 0xffff)); | 503 lui(rd, Immediate((value >> 16) & 0xffff)); |
410 ori(rd, rd, Immediate(value & 0xffff)); | 504 ori(rd, rd, Immediate(value & 0xffff)); |
411 } | 505 } |
412 } | 506 } |
413 | 507 |
414 void Move(Register rd, Register rs) { | 508 void Move(Register rd, Register rs) { |
regis
2013/03/22 19:51:16
This one is debatable, but this is also a pseudo i
zra
2013/03/22 20:16:01
I've made it mov, and moved it up, too, since mov
| |
415 or_(rd, rs, ZR); | 509 or_(rd, rs, ZR); |
416 } | 510 } |
417 | 511 |
512 void Nop() { | |
regis
2013/03/22 19:51:16
nop?
zra
2013/03/22 20:16:01
Same as with mov.
| |
513 Emit(Instr::kNopInstruction); | |
514 } | |
515 | |
418 private: | 516 private: |
419 AssemblerBuffer buffer_; | 517 AssemblerBuffer buffer_; |
420 GrowableObjectArray& object_pool_; // Objects and patchable jump targets. | 518 GrowableObjectArray& object_pool_; // Objects and patchable jump targets. |
421 int prologue_offset_; | 519 int prologue_offset_; |
422 | 520 |
423 bool delay_slot_available_; | 521 bool delay_slot_available_; |
424 bool in_delay_slot_; | 522 bool in_delay_slot_; |
425 | 523 |
426 class CodeComment : public ZoneAllocated { | 524 class CodeComment : public ZoneAllocated { |
427 public: | 525 public: |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
489 SpecialFunction func) { | 587 SpecialFunction func) { |
490 ASSERT(Utils::IsUint(5, sa)); | 588 ASSERT(Utils::IsUint(5, sa)); |
491 Emit(opcode << kOpcodeShift | | 589 Emit(opcode << kOpcodeShift | |
492 rs << kRsShift | | 590 rs << kRsShift | |
493 rt << kRtShift | | 591 rt << kRtShift | |
494 rd << kRdShift | | 592 rd << kRdShift | |
495 sa << kSaShift | | 593 sa << kSaShift | |
496 func << kFunctionShift); | 594 func << kFunctionShift); |
497 } | 595 } |
498 | 596 |
597 void EmitBranch(Opcode b, Register rs, Register rt, Label* label) { | |
598 if (label->IsBound()) { | |
599 uint16_t dest = EncodeBranchOffset(label->Position() - buffer_.Size(), 0); | |
600 EmitIType(b, rs, rt, dest); | |
601 } else { | |
602 int position = buffer_.Size(); | |
603 EmitIType(b, rs, rt, label->position_); | |
604 label->LinkTo(position); | |
605 } | |
606 } | |
607 | |
608 void EmitRegImmBranch(RtRegImm b, Register rs, Label* label) { | |
609 if (label->IsBound()) { | |
610 uint16_t dest = EncodeBranchOffset(label->Position() - buffer_.Size(), 0); | |
611 EmitRegImmType(REGIMM, rs, b, dest); | |
612 } else { | |
613 int position = buffer_.Size(); | |
614 EmitRegImmType(REGIMM, rs, b, label->position_); | |
615 label->LinkTo(position); | |
616 } | |
617 } | |
618 | |
619 static int32_t EncodeBranchOffset(int32_t offset, int32_t inst); | |
regis
2013/03/22 19:51:16
inst -> instr
zra
2013/03/22 20:16:01
Done.
| |
620 static int DecodeBranchOffset(int32_t inst); | |
regis
2013/03/22 19:51:16
inst -> instr
zra
2013/03/22 20:16:01
Done.
| |
621 | |
499 void EmitBranchDelayNop() { | 622 void EmitBranchDelayNop() { |
500 Emit(Instr::kNopInstruction); // Branch delay NOP. | 623 Emit(Instr::kNopInstruction); // Branch delay NOP. |
501 delay_slot_available_ = true; | 624 delay_slot_available_ = true; |
502 } | 625 } |
503 | 626 |
504 DISALLOW_ALLOCATION(); | 627 DISALLOW_ALLOCATION(); |
505 DISALLOW_COPY_AND_ASSIGN(Assembler); | 628 DISALLOW_COPY_AND_ASSIGN(Assembler); |
506 }; | 629 }; |
507 | 630 |
508 } // namespace dart | 631 } // namespace dart |
509 | 632 |
510 #endif // VM_ASSEMBLER_MIPS_H_ | 633 #endif // VM_ASSEMBLER_MIPS_H_ |
OLD | NEW |