diff options
Diffstat (limited to 'src/compiler/codegen/mips')
| -rw-r--r-- | src/compiler/codegen/mips/Assemble.cc | 349 | ||||
| -rw-r--r-- | src/compiler/codegen/mips/Mips32/Factory.cc | 45 | ||||
| -rw-r--r-- | src/compiler/codegen/mips/Mips32/Gen.cc | 14 | ||||
| -rw-r--r-- | src/compiler/codegen/mips/MipsLIR.h | 16 | ||||
| -rw-r--r-- | src/compiler/codegen/mips/MipsRallocUtil.cc | 2 | ||||
| -rw-r--r-- | src/compiler/codegen/mips/README.mips | 57 | ||||
| -rw-r--r-- | src/compiler/codegen/mips/mips/ArchVariant.cc | 2 |
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 } |