Chromium Code Reviews| 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 |