| 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 |