Index: runtime/vm/assembler_mips.h |
=================================================================== |
--- runtime/vm/assembler_mips.h (revision 20394) |
+++ runtime/vm/assembler_mips.h (working copy) |
@@ -147,9 +147,7 @@ |
UNIMPLEMENTED(); |
} |
- void Bind(Label* label) { |
- UNIMPLEMENTED(); |
- } |
+ void Bind(Label* label); |
// Misc. functionality |
int CodeSize() const { return buffer_.Size(); } |
@@ -245,6 +243,96 @@ |
EmitIType(ANDI, rs, rt, imm_value); |
} |
+ // Branch if equal. |
+ void beq(Register rs, Register rt, Label* l) { |
+ 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.
|
+ EmitBranch(BEQ, rs, rt, l); |
+ EmitBranchDelayNop(); |
+ } |
+ |
+ // Branch if equal, likely taken. |
+ // Delay slot executed only when branch taken. |
+ void beql(Register rs, Register rt, Label* l) { |
+ ASSERT(!in_delay_slot_); // Jump within a delay slot is not supported. |
+ EmitBranch(BEQL, rs, rt, l); |
+ EmitBranchDelayNop(); |
+ } |
+ |
+ // Brach if rs >= 0. |
regis
2013/03/22 19:51:16
Branch
zra
2013/03/22 20:16:01
Done.
|
+ void bgez(Register rs, Label* l) { |
+ ASSERT(!in_delay_slot_); |
+ EmitRegImmBranch(BGEZ, rs, l); |
+ EmitBranchDelayNop(); |
+ } |
+ |
+ // Branch if rs >= 0, likely taken. |
+ // Delay slot executed only when branch taken. |
+ void bgezl(Register rs, Label* l) { |
+ ASSERT(!in_delay_slot_); |
+ EmitRegImmBranch(BGEZL, rs, l); |
+ EmitBranchDelayNop(); |
+ } |
+ |
+ // Brach if rs > 0. |
regis
2013/03/22 19:51:16
Branch
zra
2013/03/22 20:16:01
Done.
|
+ void bgtz(Register rs, Label* l) { |
+ ASSERT(!in_delay_slot_); |
+ EmitBranch(BGTZ, rs, R0, l); |
+ EmitBranchDelayNop(); |
+ } |
+ |
+ // Branch if rs > 0, likely taken. |
+ // Delay slot executed only when branch taken. |
+ void bgtzl(Register rs, Label* l) { |
+ ASSERT(!in_delay_slot_); |
+ EmitBranch(BGTZL, rs, R0, l); |
+ EmitBranchDelayNop(); |
+ } |
+ |
+ // Brach if rs <= 0. |
regis
2013/03/22 19:51:16
Branch
zra
2013/03/22 20:16:01
Done.
|
+ void blez(Register rs, Label* l) { |
+ ASSERT(!in_delay_slot_); |
+ EmitBranch(BLEZ, rs, R0, l); |
+ EmitBranchDelayNop(); |
+ } |
+ |
+ // Branch if rs <= 0, likely taken. |
+ // Delay slot executed only when branch taken. |
+ void blezl(Register rs, Label* l) { |
+ ASSERT(!in_delay_slot_); |
+ EmitBranch(BLEZL, rs, R0, l); |
+ EmitBranchDelayNop(); |
+ } |
+ |
+ // Brach if rs < 0. |
regis
2013/03/22 19:51:16
Branch
zra
2013/03/22 20:16:01
Done.
|
+ void bltz(Register rs, Label* l) { |
+ ASSERT(!in_delay_slot_); |
+ EmitRegImmBranch(BLTZ, rs, l); |
+ EmitBranchDelayNop(); |
+ } |
+ |
+ // Branch if rs < 0, likely taken. |
+ // Delay slot executed only when branch taken. |
+ void bltzl(Register rs, Label* l) { |
+ ASSERT(!in_delay_slot_); |
+ EmitRegImmBranch(BLTZL, rs, l); |
+ EmitBranchDelayNop(); |
+ } |
+ |
+ // Branch if not equal. |
+ void bne(Register rs, Register rt, Label* l) { |
+ ASSERT(!in_delay_slot_); // Jump within a delay slot is not supported. |
+ EmitBranch(BNE, rs, rt, l); |
+ EmitBranchDelayNop(); |
+ } |
+ |
+ // Branch if not equal, likely taken. |
+ // Delay slot executed only when branch taken. |
+ void bnel(Register rs, Register rt, Label* l) { |
+ ASSERT(!in_delay_slot_); // Jump within a delay slot is not supported. |
+ EmitBranch(BNEL, rs, rt, l); |
+ EmitBranchDelayNop(); |
+ } |
+ |
void break_(int32_t code) { |
ASSERT(Utils::IsUint(20, code)); |
Emit(SPECIAL << kOpcodeShift | |
@@ -402,6 +490,12 @@ |
} |
// Macros in alphabetical order. |
+ |
+ // Unconditional branch. |
+ 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
|
+ beq(R0, R0, l); |
+ } |
+ |
void LoadImmediate(Register rd, int32_t value) { |
if (Utils::IsInt(16, value)) { |
addiu(rd, ZR, Immediate(value)); |
@@ -415,6 +509,10 @@ |
or_(rd, rs, ZR); |
} |
+ void Nop() { |
regis
2013/03/22 19:51:16
nop?
zra
2013/03/22 20:16:01
Same as with mov.
|
+ Emit(Instr::kNopInstruction); |
+ } |
+ |
private: |
AssemblerBuffer buffer_; |
GrowableObjectArray& object_pool_; // Objects and patchable jump targets. |
@@ -496,6 +594,31 @@ |
func << kFunctionShift); |
} |
+ void EmitBranch(Opcode b, Register rs, Register rt, Label* label) { |
+ if (label->IsBound()) { |
+ uint16_t dest = EncodeBranchOffset(label->Position() - buffer_.Size(), 0); |
+ EmitIType(b, rs, rt, dest); |
+ } else { |
+ int position = buffer_.Size(); |
+ EmitIType(b, rs, rt, label->position_); |
+ label->LinkTo(position); |
+ } |
+ } |
+ |
+ void EmitRegImmBranch(RtRegImm b, Register rs, Label* label) { |
+ if (label->IsBound()) { |
+ uint16_t dest = EncodeBranchOffset(label->Position() - buffer_.Size(), 0); |
+ EmitRegImmType(REGIMM, rs, b, dest); |
+ } else { |
+ int position = buffer_.Size(); |
+ EmitRegImmType(REGIMM, rs, b, label->position_); |
+ label->LinkTo(position); |
+ } |
+ } |
+ |
+ 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.
|
+ static int DecodeBranchOffset(int32_t inst); |
regis
2013/03/22 19:51:16
inst -> instr
zra
2013/03/22 20:16:01
Done.
|
+ |
void EmitBranchDelayNop() { |
Emit(Instr::kNopInstruction); // Branch delay NOP. |
delay_slot_available_ = true; |