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