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 // Unconditional branch. |
| 247 void b(Label* l) { |
| 248 beq(R0, R0, l); |
| 249 } |
| 250 |
| 251 // Branch if equal. |
| 252 void beq(Register rs, Register rt, Label* l) { |
| 253 ASSERT(!in_delay_slot_); |
| 254 EmitBranch(BEQ, rs, rt, l); |
| 255 EmitBranchDelayNop(); |
| 256 } |
| 257 |
| 258 // Branch if equal, likely taken. |
| 259 // Delay slot executed only when branch taken. |
| 260 void beql(Register rs, Register rt, Label* l) { |
| 261 ASSERT(!in_delay_slot_); |
| 262 EmitBranch(BEQL, rs, rt, l); |
| 263 EmitBranchDelayNop(); |
| 264 } |
| 265 |
| 266 // Branch if rs >= 0. |
| 267 void bgez(Register rs, Label* l) { |
| 268 ASSERT(!in_delay_slot_); |
| 269 EmitRegImmBranch(BGEZ, rs, l); |
| 270 EmitBranchDelayNop(); |
| 271 } |
| 272 |
| 273 // Branch if rs >= 0, likely taken. |
| 274 // Delay slot executed only when branch taken. |
| 275 void bgezl(Register rs, Label* l) { |
| 276 ASSERT(!in_delay_slot_); |
| 277 EmitRegImmBranch(BGEZL, rs, l); |
| 278 EmitBranchDelayNop(); |
| 279 } |
| 280 |
| 281 // Branch if rs > 0. |
| 282 void bgtz(Register rs, Label* l) { |
| 283 ASSERT(!in_delay_slot_); |
| 284 EmitBranch(BGTZ, rs, R0, l); |
| 285 EmitBranchDelayNop(); |
| 286 } |
| 287 |
| 288 // Branch if rs > 0, likely taken. |
| 289 // Delay slot executed only when branch taken. |
| 290 void bgtzl(Register rs, Label* l) { |
| 291 ASSERT(!in_delay_slot_); |
| 292 EmitBranch(BGTZL, rs, R0, l); |
| 293 EmitBranchDelayNop(); |
| 294 } |
| 295 |
| 296 // Branch if rs <= 0. |
| 297 void blez(Register rs, Label* l) { |
| 298 ASSERT(!in_delay_slot_); |
| 299 EmitBranch(BLEZ, rs, R0, l); |
| 300 EmitBranchDelayNop(); |
| 301 } |
| 302 |
| 303 // Branch if rs <= 0, likely taken. |
| 304 // Delay slot executed only when branch taken. |
| 305 void blezl(Register rs, Label* l) { |
| 306 ASSERT(!in_delay_slot_); |
| 307 EmitBranch(BLEZL, rs, R0, l); |
| 308 EmitBranchDelayNop(); |
| 309 } |
| 310 |
| 311 // Branch if rs < 0. |
| 312 void bltz(Register rs, Label* l) { |
| 313 ASSERT(!in_delay_slot_); |
| 314 EmitRegImmBranch(BLTZ, rs, l); |
| 315 EmitBranchDelayNop(); |
| 316 } |
| 317 |
| 318 // Branch if rs < 0, likely taken. |
| 319 // Delay slot executed only when branch taken. |
| 320 void bltzl(Register rs, Label* l) { |
| 321 ASSERT(!in_delay_slot_); |
| 322 EmitRegImmBranch(BLTZL, rs, l); |
| 323 EmitBranchDelayNop(); |
| 324 } |
| 325 |
| 326 // Branch if not equal. |
| 327 void bne(Register rs, Register rt, Label* l) { |
| 328 ASSERT(!in_delay_slot_); // Jump within a delay slot is not supported. |
| 329 EmitBranch(BNE, rs, rt, l); |
| 330 EmitBranchDelayNop(); |
| 331 } |
| 332 |
| 333 // Branch if not equal, likely taken. |
| 334 // Delay slot executed only when branch taken. |
| 335 void bnel(Register rs, Register rt, Label* l) { |
| 336 ASSERT(!in_delay_slot_); // Jump within a delay slot is not supported. |
| 337 EmitBranch(BNEL, rs, rt, l); |
| 338 EmitBranchDelayNop(); |
| 339 } |
| 340 |
248 void break_(int32_t code) { | 341 void break_(int32_t code) { |
249 ASSERT(Utils::IsUint(20, code)); | 342 ASSERT(Utils::IsUint(20, code)); |
250 Emit(SPECIAL << kOpcodeShift | | 343 Emit(SPECIAL << kOpcodeShift | |
251 code << kBreakCodeShift | | 344 code << kBreakCodeShift | |
252 BREAK << kFunctionShift); | 345 BREAK << kFunctionShift); |
253 } | 346 } |
254 | 347 |
255 void clo(Register rd, Register rs) { | 348 void clo(Register rd, Register rs) { |
256 EmitRType(SPECIAL2, rs, rd, rd, 0, CLO); | 349 EmitRType(SPECIAL2, rs, rd, rd, 0, CLO); |
257 } | 350 } |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
308 } | 401 } |
309 | 402 |
310 void mfhi(Register rd) { | 403 void mfhi(Register rd) { |
311 EmitRType(SPECIAL, R0, R0, rd, 0, MFHI); | 404 EmitRType(SPECIAL, R0, R0, rd, 0, MFHI); |
312 } | 405 } |
313 | 406 |
314 void mflo(Register rd) { | 407 void mflo(Register rd) { |
315 EmitRType(SPECIAL, R0, R0, rd, 0, MFLO); | 408 EmitRType(SPECIAL, R0, R0, rd, 0, MFLO); |
316 } | 409 } |
317 | 410 |
| 411 void mov(Register rd, Register rs) { |
| 412 or_(rd, rs, ZR); |
| 413 } |
| 414 |
318 void movn(Register rd, Register rs, Register rt) { | 415 void movn(Register rd, Register rs, Register rt) { |
319 EmitRType(SPECIAL, rs, rt, rd, 0, MOVN); | 416 EmitRType(SPECIAL, rs, rt, rd, 0, MOVN); |
320 } | 417 } |
321 | 418 |
322 void movz(Register rd, Register rs, Register rt) { | 419 void movz(Register rd, Register rs, Register rt) { |
323 EmitRType(SPECIAL, rs, rt, rd, 0, MOVZ); | 420 EmitRType(SPECIAL, rs, rt, rd, 0, MOVZ); |
324 } | 421 } |
325 | 422 |
326 void mult(Register rs, Register rt) { | 423 void mult(Register rs, Register rt) { |
327 EmitRType(SPECIAL, rs, rt, R0, 0, MULT); | 424 EmitRType(SPECIAL, rs, rt, R0, 0, MULT); |
328 } | 425 } |
329 | 426 |
330 void multu(Register rs, Register rt) { | 427 void multu(Register rs, Register rt) { |
331 EmitRType(SPECIAL, rs, rt, R0, 0, MULTU); | 428 EmitRType(SPECIAL, rs, rt, R0, 0, MULTU); |
332 } | 429 } |
333 | 430 |
| 431 void nop() { |
| 432 Emit(Instr::kNopInstruction); |
| 433 } |
| 434 |
334 void nor(Register rd, Register rs, Register rt) { | 435 void nor(Register rd, Register rs, Register rt) { |
335 EmitRType(SPECIAL, rs, rt, rd, 0, NOR); | 436 EmitRType(SPECIAL, rs, rt, rd, 0, NOR); |
336 } | 437 } |
337 | 438 |
338 void or_(Register rd, Register rs, Register rt) { | 439 void or_(Register rd, Register rs, Register rt) { |
339 EmitRType(SPECIAL, rs, rt, rd, 0, OR); | 440 EmitRType(SPECIAL, rs, rt, rd, 0, OR); |
340 } | 441 } |
341 | 442 |
342 void ori(Register rt, Register rs, const Immediate& imm) { | 443 void ori(Register rt, Register rs, const Immediate& imm) { |
343 ASSERT(Utils::IsUint(16, imm.value())); | 444 ASSERT(Utils::IsUint(16, imm.value())); |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
404 // Macros in alphabetical order. | 505 // Macros in alphabetical order. |
405 void LoadImmediate(Register rd, int32_t value) { | 506 void LoadImmediate(Register rd, int32_t value) { |
406 if (Utils::IsInt(16, value)) { | 507 if (Utils::IsInt(16, value)) { |
407 addiu(rd, ZR, Immediate(value)); | 508 addiu(rd, ZR, Immediate(value)); |
408 } else { | 509 } else { |
409 lui(rd, Immediate((value >> 16) & 0xffff)); | 510 lui(rd, Immediate((value >> 16) & 0xffff)); |
410 ori(rd, rd, Immediate(value & 0xffff)); | 511 ori(rd, rd, Immediate(value & 0xffff)); |
411 } | 512 } |
412 } | 513 } |
413 | 514 |
414 void Move(Register rd, Register rs) { | |
415 or_(rd, rs, ZR); | |
416 } | |
417 | |
418 private: | 515 private: |
419 AssemblerBuffer buffer_; | 516 AssemblerBuffer buffer_; |
420 GrowableObjectArray& object_pool_; // Objects and patchable jump targets. | 517 GrowableObjectArray& object_pool_; // Objects and patchable jump targets. |
421 int prologue_offset_; | 518 int prologue_offset_; |
422 | 519 |
423 bool delay_slot_available_; | 520 bool delay_slot_available_; |
424 bool in_delay_slot_; | 521 bool in_delay_slot_; |
425 | 522 |
426 class CodeComment : public ZoneAllocated { | 523 class CodeComment : public ZoneAllocated { |
427 public: | 524 public: |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
489 SpecialFunction func) { | 586 SpecialFunction func) { |
490 ASSERT(Utils::IsUint(5, sa)); | 587 ASSERT(Utils::IsUint(5, sa)); |
491 Emit(opcode << kOpcodeShift | | 588 Emit(opcode << kOpcodeShift | |
492 rs << kRsShift | | 589 rs << kRsShift | |
493 rt << kRtShift | | 590 rt << kRtShift | |
494 rd << kRdShift | | 591 rd << kRdShift | |
495 sa << kSaShift | | 592 sa << kSaShift | |
496 func << kFunctionShift); | 593 func << kFunctionShift); |
497 } | 594 } |
498 | 595 |
| 596 void EmitBranch(Opcode b, Register rs, Register rt, Label* label) { |
| 597 if (label->IsBound()) { |
| 598 // Reletive destination from an instruction after the branch. |
| 599 int32_t dest = label->Position() - (buffer_.Size() + Instr::kInstrSize); |
| 600 uint16_t dest_off = EncodeBranchOffset(dest, 0); |
| 601 EmitIType(b, rs, rt, dest_off); |
| 602 } else { |
| 603 int position = buffer_.Size(); |
| 604 EmitIType(b, rs, rt, label->position_); |
| 605 label->LinkTo(position); |
| 606 } |
| 607 } |
| 608 |
| 609 void EmitRegImmBranch(RtRegImm b, Register rs, Label* label) { |
| 610 if (label->IsBound()) { |
| 611 // Reletive destination from an instruction after the branch. |
| 612 int32_t dest = label->Position() - (buffer_.Size() + Instr::kInstrSize); |
| 613 uint16_t dest_off = EncodeBranchOffset(dest, 0); |
| 614 EmitRegImmType(REGIMM, rs, b, dest_off); |
| 615 } else { |
| 616 int position = buffer_.Size(); |
| 617 EmitRegImmType(REGIMM, rs, b, label->position_); |
| 618 label->LinkTo(position); |
| 619 } |
| 620 } |
| 621 |
| 622 static int32_t EncodeBranchOffset(int32_t offset, int32_t instr); |
| 623 static int DecodeBranchOffset(int32_t instr); |
| 624 |
499 void EmitBranchDelayNop() { | 625 void EmitBranchDelayNop() { |
500 Emit(Instr::kNopInstruction); // Branch delay NOP. | 626 Emit(Instr::kNopInstruction); // Branch delay NOP. |
501 delay_slot_available_ = true; | 627 delay_slot_available_ = true; |
502 } | 628 } |
503 | 629 |
504 DISALLOW_ALLOCATION(); | 630 DISALLOW_ALLOCATION(); |
505 DISALLOW_COPY_AND_ASSIGN(Assembler); | 631 DISALLOW_COPY_AND_ASSIGN(Assembler); |
506 }; | 632 }; |
507 | 633 |
508 } // namespace dart | 634 } // namespace dart |
509 | 635 |
510 #endif // VM_ASSEMBLER_MIPS_H_ | 636 #endif // VM_ASSEMBLER_MIPS_H_ |
OLD | NEW |