summaryrefslogtreecommitdiff
path: root/src/compiler/codegen/mips
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler/codegen/mips')
-rw-r--r--src/compiler/codegen/mips/Assemble.cc349
-rw-r--r--src/compiler/codegen/mips/Mips32/Factory.cc45
-rw-r--r--src/compiler/codegen/mips/Mips32/Gen.cc14
-rw-r--r--src/compiler/codegen/mips/MipsLIR.h16
-rw-r--r--src/compiler/codegen/mips/MipsRallocUtil.cc2
-rw-r--r--src/compiler/codegen/mips/README.mips57
-rw-r--r--src/compiler/codegen/mips/mips/ArchVariant.cc2
7 files changed, 318 insertions, 167 deletions
diff --git a/src/compiler/codegen/mips/Assemble.cc b/src/compiler/codegen/mips/Assemble.cc
index 5f215ef6bf..a70d9dafc2 100644
--- a/src/compiler/codegen/mips/Assemble.cc
+++ b/src/compiler/codegen/mips/Assemble.cc
@@ -106,44 +106,44 @@ MipsEncodingMap EncodingMap[kMipsLast] = {
"andi", "!0r,!1r,0x!2h(!2d)", 4),
ENCODING_MAP(kMipsB, 0x10000000,
kFmtBitBlt, 15, 0, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
- kFmtUnused, -1, -1, NO_OPERAND | IS_BRANCH,
+ kFmtUnused, -1, -1, NO_OPERAND | IS_BRANCH | NEEDS_FIXUP,
"b", "!0t!0N", 8),
ENCODING_MAP(kMipsBal, 0x04110000,
kFmtBitBlt, 15, 0, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
- kFmtUnused, -1, -1, NO_OPERAND | IS_BRANCH | REG_DEF_LR,
- "bal", "!0t!0N", 8),
+ kFmtUnused, -1, -1, NO_OPERAND | IS_BRANCH | REG_DEF_LR |
+ NEEDS_FIXUP, "bal", "!0t!0N", 8),
ENCODING_MAP(kMipsBeq, 0x10000000,
kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0,
- kFmtUnused, -1, -1, IS_BINARY_OP | IS_BRANCH | REG_USE01,
- "beq", "!0r,!1r,!2t!0N", 8),
+ kFmtUnused, -1, -1, IS_BINARY_OP | IS_BRANCH | REG_USE01 |
+ NEEDS_FIXUP, "beq", "!0r,!1r,!2t!0N", 8),
ENCODING_MAP(kMipsBeqz, 0x10000000, /* same as beq above with t = $zero */
kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1,
- kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | REG_USE0,
- "beqz", "!0r,!1t!0N", 8),
+ kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | REG_USE0 |
+ NEEDS_FIXUP, "beqz", "!0r,!1t!0N", 8),
ENCODING_MAP(kMipsBgez, 0x04010000,
kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1,
- kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | REG_USE0,
- "bgez", "!0r,!1t!0N", 8),
+ kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | REG_USE0 |
+ NEEDS_FIXUP, "bgez", "!0r,!1t!0N", 8),
ENCODING_MAP(kMipsBgtz, 0x1C000000,
kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1,
- kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | REG_USE0,
- "bgtz", "!0r,!1t!0N", 8),
+ kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | REG_USE0 |
+ NEEDS_FIXUP, "bgtz", "!0r,!1t!0N", 8),
ENCODING_MAP(kMipsBlez, 0x18000000,
kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1,
- kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | REG_USE0,
- "blez", "!0r,!1t!0N", 8),
+ kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | REG_USE0 |
+ NEEDS_FIXUP, "blez", "!0r,!1t!0N", 8),
ENCODING_MAP(kMipsBltz, 0x04000000,
kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1,
- kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | REG_USE0,
- "bltz", "!0r,!1t!0N", 8),
+ kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | REG_USE0 |
+ NEEDS_FIXUP, "bltz", "!0r,!1t!0N", 8),
ENCODING_MAP(kMipsBnez, 0x14000000, /* same as bne below with t = $zero */
kFmtBitBlt, 25, 21, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1,
- kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | REG_USE0,
- "bnez", "!0r,!1t!0N", 8),
+ kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | REG_USE0 |
+ NEEDS_FIXUP, "bnez", "!0r,!1t!0N", 8),
ENCODING_MAP(kMipsBne, 0x14000000,
kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0,
- kFmtUnused, -1, -1, IS_BINARY_OP | IS_BRANCH | REG_USE01,
- "bne", "!0r,!1r,!2t!0N", 8),
+ kFmtUnused, -1, -1, IS_BINARY_OP | IS_BRANCH | REG_USE01 |
+ NEEDS_FIXUP, "bne", "!0r,!1r,!2t!0N", 8),
ENCODING_MAP(kMipsDiv, 0x0000001a,
kFmtUnused, -1, -1, kFmtUnused, -1, -1, kFmtBitBlt, 25, 21,
kFmtBitBlt, 20, 16, IS_QUAD_OP | REG_DEF01 | REG_USE23,
@@ -164,8 +164,8 @@ MipsEncodingMap EncodingMap[kMipsLast] = {
"jalr", "!0r,!1r!0N", 8),
ENCODING_MAP(kMipsJr, 0x00000008,
kFmtBitBlt, 25, 21, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
- kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | REG_USE0,
- "jr", "!0r!0N", 8),
+ kFmtUnused, -1, -1, IS_UNARY_OP | IS_BRANCH | REG_USE0 |
+ NEEDS_FIXUP, "jr", "!0r!0N", 8),
ENCODING_MAP(kMipsLahi, 0x3C000000,
kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1,
kFmtUnused, -1, -1, IS_BINARY_OP | REG_DEF0,
@@ -400,26 +400,117 @@ MipsEncodingMap EncodingMap[kMipsLast] = {
#endif
ENCODING_MAP(kMipsDelta, 0x27e00000,
kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtUnused, 15, 0,
- kFmtUnused, -1, -1, IS_QUAD_OP | REG_DEF0 | REG_USE_LR,
- "addiu", "!0r,r_ra,0x!1h(!1d)", 4),
+ kFmtUnused, -1, -1, IS_QUAD_OP | REG_DEF0 | REG_USE_LR |
+ NEEDS_FIXUP, "addiu", "!0r,r_ra,0x!1h(!1d)", 4),
ENCODING_MAP(kMipsDeltaHi, 0x3C000000,
kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1,
- kFmtUnused, -1, -1, IS_QUAD_OP | REG_DEF0,
+ kFmtUnused, -1, -1, IS_QUAD_OP | REG_DEF0 | NEEDS_FIXUP,
"lui", "!0r,0x!1h(!1d)", 4),
ENCODING_MAP(kMipsDeltaLo, 0x34000000,
kFmtBlt5_2, 16, 21, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1,
- kFmtUnused, -1, -1, IS_QUAD_OP | REG_DEF0_USE0,
+ kFmtUnused, -1, -1, IS_QUAD_OP | REG_DEF0_USE0 | NEEDS_FIXUP,
"ori", "!0r,!0r,0x!1h(!1d)", 4),
- ENCODING_MAP(kMipsCurrPC, 0x0c000000,
+ ENCODING_MAP(kMipsCurrPC, 0x04110020,
kFmtUnused, -1, -1, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
kFmtUnused, -1, -1, NO_OPERAND | IS_BRANCH | REG_DEF_LR,
"pc2ra", "; r_ra <- .+8", 4),
+ ENCODING_MAP(kMipsSync, 0x0000000f,
+ kFmtBitBlt, 10, 6, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
+ kFmtUnused, -1, -1, IS_UNARY_OP,
+ "sync", ";", 4),
ENCODING_MAP(kMipsUndefined, 0x64000000,
kFmtUnused, -1, -1, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
kFmtUnused, -1, -1, NO_OPERAND,
"undefined", "", 4),
};
+
+/*
+ * Convert a short-form branch to long form. Hopefully, this won't happen
+ * very often because the PIC sequence is especially unfortunate.
+ *
+ * Orig conditional branch
+ * -----------------------
+ * beq rs,rt,target
+ *
+ * Long conditional branch
+ * -----------------------
+ * bne rs,rt,hop
+ * bal .+8 ; r_RA <- anchor
+ * lui r_AT, ((target-anchor) >> 16)
+ * anchor:
+ * ori r_AT, r_AT, ((target-anchor) & 0xffff)
+ * addu r_AT, r_AT, r_RA
+ * jr r_AT
+ * hop:
+ *
+ * Orig unconditional branch
+ * -------------------------
+ * b target
+ *
+ * Long unconditional branch
+ * -----------------------
+ * bal .+8 ; r_RA <- anchor
+ * lui r_AT, ((target-anchor) >> 16)
+ * anchor:
+ * ori r_AT, r_AT, ((target-anchor) & 0xffff)
+ * addu r_AT, r_AT, r_RA
+ * jr r_AT
+ *
+ *
+ * NOTE: An out-of-range bal isn't supported because it should
+ * never happen with the current PIC model.
+ */
+void convertShortToLongBranch(CompilationUnit* cUnit, LIR* lir)
+{
+ // For conditional branches we'll need to reverse the sense
+ bool unconditional = false;
+ int opcode = lir->opcode;
+ int dalvikOffset = lir->dalvikOffset;
+ switch(opcode) {
+ case kMipsBal:
+ LOG(FATAL) << "long branch and link unsupported";
+ case kMipsB:
+ unconditional = true;
+ break;
+ case kMipsBeq: opcode = kMipsBne; break;
+ case kMipsBne: opcode = kMipsBeq; break;
+ case kMipsBeqz: opcode = kMipsBnez; break;
+ case kMipsBgez: opcode = kMipsBltz; break;
+ case kMipsBgtz: opcode = kMipsBlez; break;
+ case kMipsBlez: opcode = kMipsBgtz; break;
+ case kMipsBltz: opcode = kMipsBgez; break;
+ case kMipsBnez: opcode = kMipsBeqz; break;
+ default:
+ LOG(FATAL) << "Unexpected branch kind " << (int)opcode;
+ }
+ LIR* hopTarget = NULL;
+ if (!unconditional) {
+ hopTarget = rawLIR(cUnit, dalvikOffset, kPseudoTargetLabel);
+ LIR* hopBranch = rawLIR(cUnit, dalvikOffset, opcode, lir->operands[0],
+ lir->operands[1], 0, 0, hopTarget);
+ oatInsertLIRBefore(lir, hopBranch);
+ }
+ LIR* currPC = rawLIR(cUnit, dalvikOffset, kMipsCurrPC);
+ oatInsertLIRBefore(lir, currPC);
+ LIR* anchor = rawLIR(cUnit, dalvikOffset, kPseudoTargetLabel);
+ LIR* deltaHi = rawLIR(cUnit, dalvikOffset, kMipsDeltaHi, r_AT, 0,
+ (uintptr_t)anchor, 0, lir->target);
+ oatInsertLIRBefore(lir, deltaHi);
+ oatInsertLIRBefore(lir, anchor);
+ LIR* deltaLo = rawLIR(cUnit, dalvikOffset, kMipsDeltaLo, r_AT, 0,
+ (uintptr_t)anchor, 0, lir->target);
+ oatInsertLIRBefore(lir, deltaLo);
+ LIR* addu = rawLIR(cUnit, dalvikOffset, kMipsAddu, r_AT, r_AT, r_RA);
+ oatInsertLIRBefore(lir, addu);
+ LIR* jr = rawLIR(cUnit, dalvikOffset, kMipsJr, r_AT);
+ oatInsertLIRBefore(lir, jr);
+ if (!unconditional) {
+ oatInsertLIRBefore(lir, hopTarget);
+ }
+ lir->flags.isNop = true;
+}
+
/*
* Assemble the LIR into binary instruction format. Note that we may
* discover that pc-relative displacements may not fit the selected
@@ -442,108 +533,112 @@ AssemblerStatus oatAssembleInstructions(CompilationUnit *cUnit,
continue;
}
-// TODO: check for lir->flags.pcRelFixup
-
- if (lir->opcode == kMipsDelta) {
- int offset1 = ((LIR*)lir->operands[2])->offset;
- SwitchTable *tabRec = (SwitchTable*)lir->operands[3];
- int offset2 = tabRec ? tabRec->offset : lir->target->offset;
- int delta = offset2 - offset1;
- if ((delta & 0xffff) == delta) {
- // Fits
- lir->operands[1] = delta;
- } else {
- // Doesn't fit - must expand to kMipsDelta[Hi|Lo] pair
- LIR *newDeltaHi =
- (LIR *)oatNew(cUnit, sizeof(LIR), true,
- kAllocLIR);
- newDeltaHi->dalvikOffset = lir->dalvikOffset;
- newDeltaHi->target = lir->target;
- newDeltaHi->opcode = kMipsDeltaHi;
- newDeltaHi->operands[0] = lir->operands[0];
- newDeltaHi->operands[2] = lir->operands[2];
- newDeltaHi->operands[3] = lir->operands[3];
- oatSetupResourceMasks(newDeltaHi);
- oatInsertLIRBefore((LIR*)lir, (LIR*)newDeltaHi);
- LIR *newDeltaLo =
- (LIR *)oatNew(cUnit, sizeof(LIR), true,
- kAllocLIR);
- newDeltaLo->dalvikOffset = lir->dalvikOffset;
- newDeltaLo->target = lir->target;
- newDeltaLo->opcode = kMipsDeltaLo;
- newDeltaLo->operands[0] = lir->operands[0];
- newDeltaLo->operands[2] = lir->operands[2];
- newDeltaLo->operands[3] = lir->operands[3];
- oatSetupResourceMasks(newDeltaLo);
- oatInsertLIRBefore((LIR*)lir, (LIR*)newDeltaLo);
- lir->flags.isNop = true;
- res = kRetryAll;
- }
- } else if (lir->opcode == kMipsDeltaLo) {
- int offset1 = ((LIR*)lir->operands[2])->offset;
- SwitchTable *tabRec = (SwitchTable*)lir->operands[3];
- int offset2 = tabRec ? tabRec->offset : lir->target->offset;
- int delta = offset2 - offset1;
- lir->operands[1] = delta & 0xffff;
- } else if (lir->opcode == kMipsDeltaHi) {
- int offset1 = ((LIR*)lir->operands[2])->offset;
- SwitchTable *tabRec = (SwitchTable*)lir->operands[3];
- int offset2 = tabRec ? tabRec->offset : lir->target->offset;
- int delta = offset2 - offset1;
- lir->operands[1] = (delta >> 16) & 0xffff;
- } else if (lir->opcode == kMipsB || lir->opcode == kMipsBal) {
- LIR *targetLIR = (LIR *) lir->target;
- intptr_t pc = lir->offset + 4;
- intptr_t target = targetLIR->offset;
- int delta = target - pc;
- if (delta & 0x3) {
- LOG(FATAL) << "PC-rel offset not multiple of 4: " << delta;
- }
- if (delta > 131068 || delta < -131069) {
- UNIMPLEMENTED(FATAL) << "B out of range, need long sequence: " << delta;
- }
- lir->operands[0] = delta >> 2;
- } else if (lir->opcode >= kMipsBeqz && lir->opcode <= kMipsBnez) {
- LIR *targetLIR = (LIR *) lir->target;
- intptr_t pc = lir->offset + 4;
- intptr_t target = targetLIR->offset;
- int delta = target - pc;
- if (delta & 0x3) {
- LOG(FATAL) << "PC-rel offset not multiple of 4: " << delta;
- }
- if (delta > 131068 || delta < -131069) {
- UNIMPLEMENTED(FATAL) << "B[eq|ne]z needs long sequence: " << delta;
- }
- lir->operands[1] = delta >> 2;
- } else if (lir->opcode == kMipsBeq || lir->opcode == kMipsBne) {
- LIR *targetLIR = (LIR *) lir->target;
- intptr_t pc = lir->offset + 4;
- intptr_t target = targetLIR->offset;
- int delta = target - pc;
- if (delta & 0x3) {
- LOG(FATAL) << "PC-rel offset not multiple of 4: " << delta;
- }
- if (delta > 131068 || delta < -131069) {
- UNIMPLEMENTED(FATAL) << "B[eq|ne] needs long sequence: " << delta;
- }
- lir->operands[2] = delta >> 2;
- } else if (lir->opcode == kMipsJal) {
- intptr_t curPC = (startAddr + lir->offset + 4) & ~3;
- intptr_t target = lir->operands[0];
- /* ensure PC-region branch can be used */
- DCHECK_EQ((curPC & 0xF0000000), (target & 0xF0000000));
- if (target & 0x3) {
- LOG(FATAL) << "Jump target not multiple of 4: " << target;
+ if (lir->flags.pcRelFixup) {
+ if (lir->opcode == kMipsDelta) {
+ /*
+ * The "Delta" pseudo-ops load the difference between
+ * two pc-relative locations into a the target register
+ * found in operands[0]. The delta is determined by
+ * (label2 - label1), where label1 is a standard
+ * kPseudoTargetLabel and is stored in operands[2].
+ * If operands[3] is null, then label2 is a kPseudoTargetLabel
+ * and is found in lir->target. If operands[3] is non-NULL,
+ * then it is a Switch/Data table.
+ */
+ int offset1 = ((LIR*)lir->operands[2])->offset;
+ SwitchTable *tabRec = (SwitchTable*)lir->operands[3];
+ int offset2 = tabRec ? tabRec->offset : lir->target->offset;
+ int delta = offset2 - offset1;
+ if ((delta & 0xffff) == delta) {
+ // Fits
+ lir->operands[1] = delta;
+ } else {
+ // Doesn't fit - must expand to kMipsDelta[Hi|Lo] pair
+ LIR *newDeltaHi =
+ rawLIR(cUnit, lir->dalvikOffset, kMipsDeltaHi,
+ lir->operands[0], 0, lir->operands[2],
+ lir->operands[3], lir->target);
+ oatInsertLIRBefore((LIR*)lir, (LIR*)newDeltaHi);
+ LIR *newDeltaLo =
+ rawLIR(cUnit, lir->dalvikOffset, kMipsDeltaLo,
+ lir->operands[0], 0, lir->operands[2],
+ lir->operands[3], lir->target);
+ oatInsertLIRBefore((LIR*)lir, (LIR*)newDeltaLo);
+ lir->flags.isNop = true;
+ res = kRetryAll;
+ }
+ } else if (lir->opcode == kMipsDeltaLo) {
+ int offset1 = ((LIR*)lir->operands[2])->offset;
+ SwitchTable *tabRec = (SwitchTable*)lir->operands[3];
+ int offset2 = tabRec ? tabRec->offset : lir->target->offset;
+ int delta = offset2 - offset1;
+ lir->operands[1] = delta & 0xffff;
+ } else if (lir->opcode == kMipsDeltaHi) {
+ int offset1 = ((LIR*)lir->operands[2])->offset;
+ SwitchTable *tabRec = (SwitchTable*)lir->operands[3];
+ int offset2 = tabRec ? tabRec->offset : lir->target->offset;
+ int delta = offset2 - offset1;
+ lir->operands[1] = (delta >> 16) & 0xffff;
+ } else if (lir->opcode == kMipsB || lir->opcode == kMipsBal) {
+ LIR *targetLIR = (LIR *) lir->target;
+ intptr_t pc = lir->offset + 4;
+ intptr_t target = targetLIR->offset;
+ int delta = target - pc;
+ if (delta & 0x3) {
+ LOG(FATAL) << "PC-rel offset not multiple of 4: " << delta;
+ }
+ if (delta > 131068 || delta < -131069) {
+ res = kRetryAll;
+ convertShortToLongBranch(cUnit, lir);
+ } else {
+ lir->operands[0] = delta >> 2;
+ }
+ } else if (lir->opcode >= kMipsBeqz && lir->opcode <= kMipsBnez) {
+ LIR *targetLIR = (LIR *) lir->target;
+ intptr_t pc = lir->offset + 4;
+ intptr_t target = targetLIR->offset;
+ int delta = target - pc;
+ if (delta & 0x3) {
+ LOG(FATAL) << "PC-rel offset not multiple of 4: " << delta;
+ }
+ if (delta > 131068 || delta < -131069) {
+ res = kRetryAll;
+ convertShortToLongBranch(cUnit, lir);
+ } else {
+ lir->operands[1] = delta >> 2;
+ }
+ } else if (lir->opcode == kMipsBeq || lir->opcode == kMipsBne) {
+ LIR *targetLIR = (LIR *) lir->target;
+ intptr_t pc = lir->offset + 4;
+ intptr_t target = targetLIR->offset;
+ int delta = target - pc;
+ if (delta & 0x3) {
+ LOG(FATAL) << "PC-rel offset not multiple of 4: " << delta;
+ }
+ if (delta > 131068 || delta < -131069) {
+ res = kRetryAll;
+ convertShortToLongBranch(cUnit, lir);
+ } else {
+ lir->operands[2] = delta >> 2;
+ }
+ } else if (lir->opcode == kMipsJal) {
+ intptr_t curPC = (startAddr + lir->offset + 4) & ~3;
+ intptr_t target = lir->operands[0];
+ /* ensure PC-region branch can be used */
+ DCHECK_EQ((curPC & 0xF0000000), (target & 0xF0000000));
+ if (target & 0x3) {
+ LOG(FATAL) << "Jump target not multiple of 4: " << target;
+ }
+ lir->operands[0] = target >> 2;
+ } else if (lir->opcode == kMipsLahi) { /* ld address hi (via lui) */
+ LIR *targetLIR = (LIR *) lir->target;
+ intptr_t target = startAddr + targetLIR->offset;
+ lir->operands[1] = target >> 16;
+ } else if (lir->opcode == kMipsLalo) { /* ld address lo (via ori) */
+ LIR *targetLIR = (LIR *) lir->target;
+ intptr_t target = startAddr + targetLIR->offset;
+ lir->operands[2] = lir->operands[2] + target;
}
- lir->operands[0] = target >> 2;
- } else if (lir->opcode == kMipsLahi) { /* load address hi (via lui) */
- LIR *targetLIR = (LIR *) lir->target;
- intptr_t target = startAddr + targetLIR->offset;
- lir->operands[1] = target >> 16;
- } else if (lir->opcode == kMipsLalo) { /* load address lo (via ori) */
- LIR *targetLIR = (LIR *) lir->target;
- intptr_t target = startAddr + targetLIR->offset;
- lir->operands[2] = lir->operands[2] + target;
}
/*
diff --git a/src/compiler/codegen/mips/Mips32/Factory.cc b/src/compiler/codegen/mips/Mips32/Factory.cc
index 105677eef2..ecc01802c0 100644
--- a/src/compiler/codegen/mips/Mips32/Factory.cc
+++ b/src/compiler/codegen/mips/Mips32/Factory.cc
@@ -28,7 +28,8 @@ static int coreRegs[] = {r_ZERO, r_AT, r_V0, r_V1, r_A0, r_A1, r_A2, r_A3,
r_T0, r_T1, r_T2, r_T3, r_T4, r_T5, r_T6, r_T7,
r_S0, r_S1, r_S2, r_S3, r_S4, r_S5, r_S6, r_S7, r_T8,
r_T9, r_K0, r_K1, r_GP, r_SP, r_FP, r_RA};
-static int reservedRegs[] = {r_ZERO, r_AT, r_S0, r_S1, r_K0, r_K1, r_GP, r_SP, r_RA};
+static int reservedRegs[] = {r_ZERO, r_AT, r_S0, r_S1, r_K0, r_K1, r_GP, r_SP,
+ r_RA};
static int coreTemps[] = {r_V0, r_V1, r_A0, r_A1, r_A2, r_A3, r_T0, r_T1, r_T2,
r_T3, r_T4, r_T5, r_T6, r_T7, r_T8, r_T9};
#ifdef __mips_hard_float
@@ -51,33 +52,31 @@ LIR *loadConstant(CompilationUnit *cUnit, int rDest, int value);
#ifdef __mips_hard_float
LIR *fpRegCopy(CompilationUnit *cUnit, int rDest, int rSrc)
{
- LIR* res = (LIR *) oatNew(cUnit, sizeof(LIR), true, kAllocLIR);
- res->operands[0] = rDest;
- res->operands[1] = rSrc;
- if (rDest == rSrc) {
- res->flags.isNop = true;
+ int opcode;
+ /* must be both DOUBLE or both not DOUBLE */
+ DCHECK_EQ(DOUBLEREG(rDest),DOUBLEREG(rSrc));
+ if (DOUBLEREG(rDest)) {
+ opcode = kMipsFmovd;
} else {
- /* must be both DOUBLE or both not DOUBLE */
- DCHECK_EQ(DOUBLEREG(rDest),DOUBLEREG(rSrc));
- if (DOUBLEREG(rDest)) {
- res->opcode = kMipsFmovd;
- } else {
- if (SINGLEREG(rDest)) {
- if (SINGLEREG(rSrc)) {
- res->opcode = kMipsFmovs;
- } else {
- /* note the operands are swapped for the mtc1 instr */
- res->opcode = kMipsMtc1;
- res->operands[0] = rSrc;
- res->operands[1] = rDest;
- }
+ if (SINGLEREG(rDest)) {
+ if (SINGLEREG(rSrc)) {
+ opcode = kMipsFmovs;
} else {
- DCHECK(SINGLEREG(rSrc));
- res->opcode = kMipsMfc1;
+ /* note the operands are swapped for the mtc1 instr */
+ int tOpnd = rSrc;
+ rSrc = rDest;
+ rDest = tOpnd;
+ opcode = kMipsMtc1;
}
+ } else {
+ DCHECK(SINGLEREG(rSrc));
+ opcode = kMipsMfc1;
}
}
- setupResourceMasks(res);
+ LIR* res = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, rSrc, rDest);
+ if (rDest == rSrc) {
+ res->flags.isNop = true;
+ }
return res;
}
#endif
diff --git a/src/compiler/codegen/mips/Mips32/Gen.cc b/src/compiler/codegen/mips/Mips32/Gen.cc
index c975889bed..2bb2f7a560 100644
--- a/src/compiler/codegen/mips/Mips32/Gen.cc
+++ b/src/compiler/codegen/mips/Mips32/Gen.cc
@@ -389,8 +389,7 @@ LIR* opCmpBranch(CompilationUnit* cUnit, ConditionCode cond, int src1,
swapped = true;
break;
default:
- UNIMPLEMENTED(FATAL) << "No support for ConditionCode: "
- << (int) cond;
+ LOG(FATAL) << "No support for ConditionCode: " << (int) cond;
return NULL;
}
if (cmpZero) {
@@ -445,19 +444,12 @@ LIR* opCmpImmBranch(CompilationUnit* cUnit, ConditionCode cond, int reg,
LIR* opRegCopyNoInsert(CompilationUnit *cUnit, int rDest, int rSrc)
{
- LIR* res;
- MipsOpCode opcode;
#ifdef __mips_hard_float
if (FPREG(rDest) || FPREG(rSrc))
return fpRegCopy(cUnit, rDest, rSrc);
#endif
- res = (LIR *) oatNew(cUnit, sizeof(LIR), true, kAllocLIR);
- opcode = kMipsMove;
- assert(LOWREG(rDest) && LOWREG(rSrc));
- res->operands[0] = rDest;
- res->operands[1] = rSrc;
- res->opcode = opcode;
- setupResourceMasks(res);
+ LIR* res = rawLIR(cUnit, cUnit->currentDalvikOffset, kMipsMove,
+ rDest, rSrc);
if (rDest == rSrc) {
res->flags.isNop = true;
}
diff --git a/src/compiler/codegen/mips/MipsLIR.h b/src/compiler/codegen/mips/MipsLIR.h
index 5034623c2b..18f06ae4b2 100644
--- a/src/compiler/codegen/mips/MipsLIR.h
+++ b/src/compiler/codegen/mips/MipsLIR.h
@@ -311,9 +311,17 @@ typedef enum MipsShiftEncodings {
kMipsRor = 0x3
} MipsShiftEncodings;
-// FIXME: Need support for barriers. Adding these defines to allow compile
-#define kST 0
-#define kSY 1
+// MIPS sync kinds (Note: support for kinds other than kSYNC0 may not exist)
+#define kSYNC0 0x00
+#define kSYNC_WMB 0x04
+#define kSYNC_MB 0x01
+#define kSYNC_ACQUIRE 0x11
+#define kSYNC_RELEASE 0x12
+#define kSYNC_RMB 0x13
+
+// TODO: Use smaller hammer when appropriate for target CPU
+#define kST kSYNC0
+#define kSY kSYNC0
#define isPseudoOpcode(opCode) ((int)(opCode) < 0)
@@ -430,6 +438,7 @@ typedef enum MipsOpCode {
kMipsDeltaHi, /* Pseudo for lui t, high16(<label>-<label>) */
kMipsDeltaLo, /* Pseudo for ori t, s, low16(<label>-<label>) */
kMipsCurrPC, /* jal to .+8 to materialize pc */
+ kMipsSync, /* sync kind [000000] [0000000000000000] s[10..6] [001111] */
kMipsUndefined, /* undefined [011001xxxxxxxxxxxxxxxx] */
kMipsLast
} MipsOpCode;
@@ -463,7 +472,6 @@ typedef enum MipsOpFeatureFlags {
kMemStore,
kPCRelFixup,
kRegUseLR,
-// FIXME: add NEEDS_FIXUP to instruction attributes
} MipsOpFeatureFlags;
#define IS_LOAD (1 << kMemLoad)
diff --git a/src/compiler/codegen/mips/MipsRallocUtil.cc b/src/compiler/codegen/mips/MipsRallocUtil.cc
index 774dffcb43..3cad4d9948 100644
--- a/src/compiler/codegen/mips/MipsRallocUtil.cc
+++ b/src/compiler/codegen/mips/MipsRallocUtil.cc
@@ -47,7 +47,7 @@ void oatAdjustSpillMask(CompilationUnit* cUnit)
*/
void oatMarkPreservedSingle(CompilationUnit* cUnit, int sReg, int reg)
{
- UNIMPLEMENTED(FATAL) << "No support yet for promoted FP regs";
+ LOG(FATAL) << "No support yet for promoted FP regs";
}
void oatFlushRegWide(CompilationUnit* cUnit, int reg1, int reg2)
diff --git a/src/compiler/codegen/mips/README.mips b/src/compiler/codegen/mips/README.mips
new file mode 100644
index 0000000000..5add2f311e
--- /dev/null
+++ b/src/compiler/codegen/mips/README.mips
@@ -0,0 +1,57 @@
+ Notes on the Mips target (3/4/2012)
+ -----------------------------------
+
+Testing
+
+The initial implementation of Mips support in the compiler is untested on
+actual hardware, and as such should be expected to have many bugs. However,
+the vast majority of code for Mips support is either shared with other
+tested targets, or was taken from the functional Mips JIT compiler. The
+expectation is that when it is first tried out on actual hardware lots of
+small bugs will be flushed out, but it should not take long to get it
+solidly running. The following area are considered most likely to have
+problems that need to be addressed:
+
+ o Endianness. Focus was on little-endian support, and if a big-endian
+ target is desired, you should pay particular attention to the
+ code generation for switch tables, fill array data, 64-bit
+ data handling and the register usage conventions.
+
+ o The memory model. Verify that oatGenMemoryBarrier() generates the
+ appropriate flavor of sync.
+
+Register promotion
+
+The resource masks in the LIR structure are 64-bits wide, which is enough
+room to fully describe def/use info for Arm and x86 instructions. However,
+the larger number of MIPS core and float registers render this too small.
+Currently, the workaround for this limitation is to avoid using floating
+point registers 16-31. These are the callee-save registers, which therefore
+means that no floating point promotion is allowed. Among the solution are:
+ o Expand the def/use mask (which, unfortunately, is a significant change)
+ o The Arm target uses 52 of the 64 bits, so we could support float
+ registers 16-27 without much effort.
+ o We could likely assign the 4 non-register bits (kDalvikReg, kLiteral,
+ kHeapRef & kMustNotAlias) to positions occuped by MIPS registers that
+ don't need def/use bits because they are never modified by code
+ subject to scheduling: r_K0, r_K1, r_SP, r_ZERO, r_S1 (rSELF).
+
+Branch delay slots
+
+Little to no attempt was made to fill branch delay slots. Branch
+instructions in the encoding map are given a length of 8 bytes to include
+an implicit NOP. It should not be too difficult to provide a slot-filling
+pass following successful assembly, but thought should be given to the
+design. Branches are currently treated as scheduling barriers. One
+simple solution would be to copy the instruction at branch targets to the
+slot and adjust the displacement. However, given that code expansion is
+already a problem it would be preferable to use a more sophisticated
+scheduling solution.
+
+Code expansion
+
+Code expansion for the MIPS target is significantly higher than we see
+for Arm and x86. It might make sense to replace the inline code generation
+for some of the more verbose Dalik byte codes with subroutine calls to
+shared helper functions.
+
diff --git a/src/compiler/codegen/mips/mips/ArchVariant.cc b/src/compiler/codegen/mips/mips/ArchVariant.cc
index 32b50e9549..6d29fc518e 100644
--- a/src/compiler/codegen/mips/mips/ArchVariant.cc
+++ b/src/compiler/codegen/mips/mips/ArchVariant.cc
@@ -52,7 +52,7 @@ int dvmCompilerTargetOptHint(int key)
void oatGenMemBarrier(CompilationUnit *cUnit, int barrierKind)
{
#if ANDROID_SMP != 0
- // FIXME: what to do here for Mips?
+ newLIR1(cUnit, kMipsSync, barrierKind);
#endif
}