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

Unified Diff: runtime/vm/assembler_mips.h

Issue 20369003: Implements far branch targets for MIPS. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 5 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 25483)
+++ runtime/vm/assembler_mips.h (working copy)
@@ -22,6 +22,8 @@
// The MIPS32® Instruction Set" in short "VolII-A"
namespace dart {
+DECLARE_FLAG(bool, mips_far_branches);
+
// Forward declarations.
class RuntimeEntry;
@@ -854,76 +856,80 @@
}
void BranchEqual(Register rd, int32_t value, Label* l) {
- ASSERT(rd != CMPRES);
- LoadImmediate(CMPRES, value);
- beq(rd, CMPRES, l);
+ ASSERT(rd != CMPRES2);
+ LoadImmediate(CMPRES2, value);
+ beq(rd, CMPRES2, l);
}
void BranchEqual(Register rd, const Object& object, Label* l) {
- ASSERT(rd != CMPRES);
- LoadObject(CMPRES, object);
- beq(rd, CMPRES, l);
+ ASSERT(rd != CMPRES2);
+ LoadObject(CMPRES2, object);
+ beq(rd, CMPRES2, l);
}
void BranchNotEqual(Register rd, int32_t value, Label* l) {
- ASSERT(rd != CMPRES);
- LoadImmediate(CMPRES, value);
- bne(rd, CMPRES, l);
+ ASSERT(rd != CMPRES2);
+ LoadImmediate(CMPRES2, value);
+ bne(rd, CMPRES2, l);
}
void BranchNotEqual(Register rd, const Object& object, Label* l) {
- ASSERT(rd != CMPRES);
- LoadObject(CMPRES, object);
- bne(rd, CMPRES, l);
+ ASSERT(rd != CMPRES2);
+ LoadObject(CMPRES2, object);
+ bne(rd, CMPRES2, l);
}
void BranchSignedGreater(Register rd, Register rs, Label* l) {
- slt(CMPRES, rs, rd); // CMPRES = rd > rs ? 1 : 0.
- bne(CMPRES, ZR, l);
+ slt(CMPRES1, rs, rd); // CMPRES1 = rd > rs ? 1 : 0.
regis 2013/07/25 20:07:43 It's awkward that some branch instructions use CMP
zra 2013/07/26 21:26:15 Done.
+ bne(CMPRES1, ZR, l);
}
void BranchSignedGreater(Register rd, int32_t value, Label* l) {
- LoadImmediate(CMPRES, value);
- BranchSignedGreater(rd, CMPRES, l);
+ ASSERT(rd != CMPRES2);
+ LoadImmediate(CMPRES2, value);
+ BranchSignedGreater(rd, CMPRES2, l);
}
void BranchUnsignedGreater(Register rd, Register rs, Label* l) {
- sltu(CMPRES, rs, rd);
- bne(CMPRES, ZR, l);
+ sltu(CMPRES1, rs, rd);
+ bne(CMPRES1, ZR, l);
}
void BranchUnsignedGreater(Register rd, int32_t value, Label* l) {
- LoadImmediate(CMPRES, value);
- BranchUnsignedGreater(rd, CMPRES, l);
+ ASSERT(rd != CMPRES2);
+ LoadImmediate(CMPRES2, value);
+ BranchUnsignedGreater(rd, CMPRES2, l);
}
void BranchSignedGreaterEqual(Register rd, Register rs, Label* l) {
- slt(CMPRES, rd, rs); // CMPRES = rd < rs ? 1 : 0.
- beq(CMPRES, ZR, l); // If CMPRES = 0, then rd >= rs.
+ slt(CMPRES1, rd, rs); // CMPRES1 = rd < rs ? 1 : 0.
+ beq(CMPRES1, ZR, l); // If CMPRES1 = 0, then rd >= rs.
}
void BranchSignedGreaterEqual(Register rd, int32_t value, Label* l) {
if (Utils::IsInt(kImmBits, value)) {
- slti(CMPRES, rd, Immediate(value));
- beq(CMPRES, ZR, l);
+ slti(CMPRES1, rd, Immediate(value));
+ beq(CMPRES1, ZR, l);
} else {
- LoadImmediate(CMPRES, value);
- BranchSignedGreaterEqual(rd, CMPRES, l);
+ ASSERT(rd != CMPRES2);
+ LoadImmediate(CMPRES2, value);
+ BranchSignedGreaterEqual(rd, CMPRES2, l);
}
}
void BranchUnsignedGreaterEqual(Register rd, Register rs, Label* l) {
- sltu(CMPRES, rd, rs); // CMPRES = rd < rs ? 1 : 0.
- beq(CMPRES, ZR, l);
+ sltu(CMPRES1, rd, rs); // CMPRES1 = rd < rs ? 1 : 0.
+ beq(CMPRES1, ZR, l);
}
void BranchUnsignedGreaterEqual(Register rd, int32_t value, Label* l) {
if (Utils::IsUint(kImmBits, value)) {
- sltiu(CMPRES, rd, Immediate(value));
- beq(CMPRES, ZR, l);
+ sltiu(CMPRES1, rd, Immediate(value));
+ beq(CMPRES1, ZR, l);
} else {
- LoadImmediate(CMPRES, value);
- BranchUnsignedGreaterEqual(rd, CMPRES, l);
+ ASSERT(rd != CMPRES2);
+ LoadImmediate(CMPRES2, value);
+ BranchUnsignedGreaterEqual(rd, CMPRES2, l);
}
}
@@ -933,11 +939,12 @@
void BranchSignedLess(Register rd, int32_t value, Label* l) {
if (Utils::IsInt(kImmBits, value)) {
- slti(CMPRES, rd, Immediate(value));
- bne(CMPRES, ZR, l);
+ slti(CMPRES1, rd, Immediate(value));
+ bne(CMPRES1, ZR, l);
} else {
- LoadImmediate(CMPRES, value);
- BranchSignedGreater(CMPRES, rd, l);
+ ASSERT(rd != CMPRES2);
+ LoadImmediate(CMPRES2, value);
+ BranchSignedGreater(CMPRES2, rd, l);
}
}
@@ -947,11 +954,12 @@
void BranchUnsignedLess(Register rd, int32_t value, Label* l) {
if (Utils::IsUint(kImmBits, value)) {
- sltiu(CMPRES, rd, Immediate(value));
- bne(CMPRES, ZR, l);
+ sltiu(CMPRES1, rd, Immediate(value));
+ bne(CMPRES1, ZR, l);
} else {
- LoadImmediate(CMPRES, value);
- BranchUnsignedGreater(CMPRES, rd, l);
+ ASSERT(rd != CMPRES2);
+ LoadImmediate(CMPRES2, value);
+ BranchUnsignedGreater(CMPRES2, rd, l);
}
}
@@ -960,8 +968,8 @@
}
void BranchSignedLessEqual(Register rd, int32_t value, Label* l) {
- LoadImmediate(CMPRES, value);
- BranchSignedGreaterEqual(CMPRES, rd, l);
+ LoadImmediate(CMPRES1, value);
+ BranchSignedGreaterEqual(CMPRES1, rd, l);
}
void BranchUnsignedLessEqual(Register rd, Register rs, Label* l) {
@@ -969,8 +977,8 @@
}
void BranchUnsignedLessEqual(Register rd, int32_t value, Label* l) {
- LoadImmediate(CMPRES, value);
- BranchUnsignedGreaterEqual(CMPRES, rd, l);
+ LoadImmediate(CMPRES1, value);
+ BranchUnsignedGreaterEqual(CMPRES1, rd, l);
}
void Push(Register rt) {
@@ -1029,6 +1037,19 @@
lwc1(hi, Address(base, offset + kWordSize));
}
+ // dest gets the address of the following instruction. If preserve ra is true
+ // RA is preserved using CMPRES1 as a temporary.
+ void GetNextPC(Register dest, bool preserve_ra) {
+ if (preserve_ra) {
+ mov(CMPRES1, RA);
+ }
+ EmitRegImmType(REGIMM, R0, BGEZAL, 1);
+ mov(dest, RA);
+ if (preserve_ra) {
+ mov(RA, CMPRES1);
+ }
+ }
+
void ReserveAlignedFrameSpace(intptr_t frame_space);
// Create a frame for calling into runtime that preserves all volatile
@@ -1182,17 +1203,140 @@
func << kCop1FnShift);
}
+ int32_t DecodeLoadImmediate(int32_t low, int32_t high);
+ int32_t EncodeLoadImmediate(int32_t dest, int32_t instr);
+
+ Opcode OppositeBranchOpcode(Opcode b) {
+ switch (b) {
+ case BEQ: return BNE;
+ case BNE: return BEQ;
+ case BGTZ: return BLEZ;
+ case BLEZ: return BGTZ;
+ case BEQL: return BNEL;
+ case BNEL: return BEQL;
+ case BGTZL: return BLEZL;
+ case BLEZL: return BGTZL;
+ default:
+ UNREACHABLE();
+ break;
+ }
+ return BNE;
+ }
+
+ void EmitFarBranch(Opcode b, Register rs, Register rt, int32_t offset) {
+ ASSERT(rs != TMP);
+ ASSERT(rt != TMP);
+
+ const uint16_t low = Utils::Low16Bits(offset);
+ const uint16_t high = Utils::High16Bits(offset);
+ lui(TMP, Immediate(high));
+ ori(TMP, TMP, Immediate(low));
+
+ addiu(SP, SP, Immediate(-1 * kWordSize));
+ sw(CMPRES1, Address(SP, -0 * kWordSize));
+
+ mov(CMPRES1, RA);
+ EmitRegImmType(REGIMM, R0, BGEZAL, 1);
regis 2013/07/25 20:07:43 You are not using GetNextPC. Still needed? OK, I s
+ addu(TMP, TMP, RA);
+ mov(RA, CMPRES1);
+
+ lw(CMPRES1, Address(SP, -0 * kWordSize));
+ addiu(SP, SP, Immediate(1 * kWordSize));
regis 2013/07/25 20:07:43 Preserving and restoring CMPRES1 in order to, in t
+
+ EmitIType(OppositeBranchOpcode(b), rs, rt, 2);
regis 2013/07/25 20:07:43 You should have an unconditional EmitFarBranch(off
zra 2013/07/26 21:26:15 Done.
+ nop();
+ EmitRType(SPECIAL, TMP, R0, R0, 0, JR);
+ }
+
+ RtRegImm OppositeBranchNoLink(RtRegImm b) {
+ switch (b) {
+ case BLTZ: return BGEZ;
+ case BGEZ: return BLTZ;
+ case BLTZAL: return BGEZ;
+ case BGEZAL: return BLTZ;
+ default:
+ UNREACHABLE();
+ break;
+ }
+ return BLTZ;
+ }
+
+ void EmitFarRegImmBranch(RtRegImm b, Register rs, int32_t offset) {
+ ASSERT(rs != TMP);
+
+ const uint16_t low = Utils::Low16Bits(offset);
+ const uint16_t high = Utils::High16Bits(offset);
+ lui(TMP, Immediate(high));
+ ori(TMP, TMP, Immediate(low));
+
+ addiu(SP, SP, Immediate(-1 * kWordSize));
+ sw(CMPRES1, Address(SP, -0 * kWordSize));
+
+ mov(CMPRES1, RA);
+ EmitRegImmType(REGIMM, R0, BGEZAL, 1);
+ addu(TMP, TMP, RA);
+ mov(RA, CMPRES1);
+
+ lw(CMPRES1, Address(SP, -0 * kWordSize));
+ addiu(SP, SP, Immediate(1 * kWordSize));
+
+ EmitRegImmType(REGIMM, rs, OppositeBranchNoLink(b), 2);
+ nop();
+ if ((b == BLTZAL) || (b == BGEZAL)) {
+ EmitRType(SPECIAL, TMP, R0, RA, 0, JALR);
+ } else {
+ EmitRType(SPECIAL, TMP, R0, R0, 0, JR);
+ }
+ }
+
+
+ void EmitFarFpuBranch(bool kind, int32_t offset) {
+ const uint32_t b16 = kind ? 0 : (1 << 16);
+
+ const uint16_t low = Utils::Low16Bits(offset);
+ const uint16_t high = Utils::High16Bits(offset);
+ lui(TMP, Immediate(high));
+ ori(TMP, TMP, Immediate(low));
+
+ addiu(SP, SP, Immediate(-1 * kWordSize));
+ sw(CMPRES1, Address(SP, -0 * kWordSize));
+
+ mov(CMPRES1, RA);
+ EmitRegImmType(REGIMM, R0, BGEZAL, 1);
+ addu(TMP, TMP, RA);
+ mov(RA, CMPRES1);
+
+ lw(CMPRES1, Address(SP, -0 * kWordSize));
+ addiu(SP, SP, Immediate(1 * kWordSize));
+
+ Emit(COP1 << kOpcodeShift | COP1_BC << kCop1SubShift | b16 | 2);
+ nop();
+ EmitRType(SPECIAL, TMP, R0, R0, 0, JR);
+ }
+
+
void EmitBranch(Opcode b, Register rs, Register rt, Label* label) {
if (label->IsBound()) {
regis 2013/07/25 20:07:43 If the label is bound, you know the offset and you
zra 2013/07/26 21:26:15 Done.
// Relative destination from an instruction after the branch.
- const int32_t dest =
- label->Position() - (buffer_.Size() + Instr::kInstrSize);
- const uint16_t dest_off = EncodeBranchOffset(dest, 0);
- EmitIType(b, rs, rt, dest_off);
+ if (FLAG_mips_far_branches) {
+ const int32_t dest =
+ label->Position() - (buffer_.Size() + 7 * Instr::kInstrSize);
+ EmitFarBranch(b, rs, rt, dest);
+ } else {
+ const int32_t dest =
+ label->Position() - (buffer_.Size() + Instr::kInstrSize);
+ const uint16_t dest_off = EncodeBranchOffset(dest, 0);
+ EmitIType(b, rs, rt, dest_off);
+ }
} else {
const int position = buffer_.Size();
- const uint16_t dest_off = EncodeBranchOffset(label->position_, 0);
- EmitIType(b, rs, rt, dest_off);
+ if (FLAG_mips_far_branches) {
+ const uint32_t dest_off = label->position_;
+ EmitFarBranch(b, rs, rt, dest_off);
+ } else {
+ const uint16_t dest_off = EncodeBranchOffset(label->position_, 0);
+ EmitIType(b, rs, rt, dest_off);
+ }
label->LinkTo(position);
}
}
@@ -1200,14 +1344,25 @@
void EmitRegImmBranch(RtRegImm b, Register rs, Label* label) {
if (label->IsBound()) {
regis 2013/07/25 20:07:43 ditto
zra 2013/07/26 21:26:15 Done.
// Relative destination from an instruction after the branch.
- const int32_t dest =
- label->Position() - (buffer_.Size() + Instr::kInstrSize);
- const uint16_t dest_off = EncodeBranchOffset(dest, 0);
- EmitRegImmType(REGIMM, rs, b, dest_off);
+ if (FLAG_mips_far_branches) {
+ const int32_t dest =
+ label->Position() - (buffer_.Size() + 7 * Instr::kInstrSize);
+ EmitFarRegImmBranch(b, rs, dest);
+ } else {
+ const int32_t dest =
+ label->Position() - (buffer_.Size() + Instr::kInstrSize);
+ const uint16_t dest_off = EncodeBranchOffset(dest, 0);
+ EmitRegImmType(REGIMM, rs, b, dest_off);
+ }
} else {
const int position = buffer_.Size();
- const uint16_t dest_off = EncodeBranchOffset(label->position_, 0);
- EmitRegImmType(REGIMM, rs, b, dest_off);
+ if (FLAG_mips_far_branches) {
+ const uint32_t dest_off = label->position_;
+ EmitFarRegImmBranch(b, rs, dest_off);
+ } else {
+ const uint16_t dest_off = EncodeBranchOffset(label->position_, 0);
+ EmitRegImmType(REGIMM, rs, b, dest_off);
+ }
label->LinkTo(position);
}
}
@@ -1216,20 +1371,31 @@
const int32_t b16 = kind ? (1 << 16) : 0; // Bit 16 set for branch on true.
if (label->IsBound()) {
regis 2013/07/25 20:07:43 ditto
zra 2013/07/26 21:26:15 Done.
// Relative destination from an instruction after the branch.
- const int32_t dest =
- label->Position() - (buffer_.Size() + Instr::kInstrSize);
- const uint16_t dest_off = EncodeBranchOffset(dest, 0);
- Emit(COP1 << kOpcodeShift |
- COP1_BC << kCop1SubShift |
- b16 |
- dest_off);
+ if (FLAG_mips_far_branches) {
+ const int32_t dest =
+ label->Position() - (buffer_.Size() + 7 * Instr::kInstrSize);
+ EmitFarFpuBranch(kind, dest);
+ } else {
+ const int32_t dest =
+ label->Position() - (buffer_.Size() + Instr::kInstrSize);
+ const uint16_t dest_off = EncodeBranchOffset(dest, 0);
+ Emit(COP1 << kOpcodeShift |
+ COP1_BC << kCop1SubShift |
+ b16 |
+ dest_off);
+ }
} else {
const int position = buffer_.Size();
- const uint16_t dest_off = EncodeBranchOffset(label->position_, 0);
- Emit(COP1 << kOpcodeShift |
- COP1_BC << kCop1SubShift |
- b16 |
- dest_off);
+ if (FLAG_mips_far_branches) {
+ const uint32_t dest_off = label->position_;
+ EmitFarFpuBranch(kind, dest_off);
+ } else {
+ const uint16_t dest_off = EncodeBranchOffset(label->position_, 0);
+ Emit(COP1 << kOpcodeShift |
+ COP1_BC << kCop1SubShift |
+ b16 |
+ dest_off);
+ }
label->LinkTo(position);
}
}
« 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