Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(443)

Unified Diff: runtime/vm/assembler_mips.h

Issue 12634030: Adds branch instructions and labels to the MIPS simulator, assembler, disassembler. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | runtime/vm/assembler_mips.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/assembler_mips.h
===================================================================
--- runtime/vm/assembler_mips.h (revision 20399)
+++ 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,101 @@
EmitIType(ANDI, rs, rt, imm_value);
}
+ // Unconditional branch.
+ void b(Label* l) {
+ beq(R0, R0, l);
+ }
+
+ // Branch if equal.
+ void beq(Register rs, Register rt, Label* l) {
+ ASSERT(!in_delay_slot_);
+ 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_);
+ EmitBranch(BEQL, rs, rt, l);
+ EmitBranchDelayNop();
+ }
+
+ // Branch if rs >= 0.
+ 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();
+ }
+
+ // Branch if rs > 0.
+ 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();
+ }
+
+ // Branch if rs <= 0.
+ 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();
+ }
+
+ // Branch if rs < 0.
+ 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 |
@@ -315,6 +408,10 @@
EmitRType(SPECIAL, R0, R0, rd, 0, MFLO);
}
+ void mov(Register rd, Register rs) {
+ or_(rd, rs, ZR);
+ }
+
void movn(Register rd, Register rs, Register rt) {
EmitRType(SPECIAL, rs, rt, rd, 0, MOVN);
}
@@ -331,6 +428,10 @@
EmitRType(SPECIAL, rs, rt, R0, 0, MULTU);
}
+ void nop() {
+ Emit(Instr::kNopInstruction);
+ }
+
void nor(Register rd, Register rs, Register rt) {
EmitRType(SPECIAL, rs, rt, rd, 0, NOR);
}
@@ -411,10 +512,6 @@
}
}
- void Move(Register rd, Register rs) {
- or_(rd, rs, ZR);
- }
-
private:
AssemblerBuffer buffer_;
GrowableObjectArray& object_pool_; // Objects and patchable jump targets.
@@ -496,6 +593,35 @@
func << kFunctionShift);
}
+ void EmitBranch(Opcode b, Register rs, Register rt, Label* label) {
+ if (label->IsBound()) {
+ // Reletive destination from an instruction after the branch.
+ int32_t dest = label->Position() - (buffer_.Size() + Instr::kInstrSize);
+ uint16_t dest_off = EncodeBranchOffset(dest, 0);
+ EmitIType(b, rs, rt, dest_off);
+ } 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()) {
+ // Reletive destination from an instruction after the branch.
+ int32_t dest = label->Position() - (buffer_.Size() + Instr::kInstrSize);
+ uint16_t dest_off = EncodeBranchOffset(dest, 0);
+ EmitRegImmType(REGIMM, rs, b, dest_off);
+ } else {
+ int position = buffer_.Size();
+ EmitRegImmType(REGIMM, rs, b, label->position_);
+ label->LinkTo(position);
+ }
+ }
+
+ static int32_t EncodeBranchOffset(int32_t offset, int32_t instr);
+ static int DecodeBranchOffset(int32_t instr);
+
void EmitBranchDelayNop() {
Emit(Instr::kNopInstruction); // Branch delay NOP.
delay_slot_available_ = true;
« no previous file with comments | « no previous file | runtime/vm/assembler_mips.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698