diff options
| author | 2012-03-04 14:57:06 -0800 | |
|---|---|---|
| committer | 2012-03-04 15:00:36 -0800 | |
| commit | a2ebdd74eb2f36e6efa7a482bc11c7b93d97c2c3 (patch) | |
| tree | 2d63c98a1f729f1e17969bfbc4b7dc1da48f4567 /src/compiler/codegen | |
| parent | 11f9d2130e938511efceb6d2a4793cee7dfdde35 (diff) | |
Complete MIPS code generation support
With this CL code generation for MIPS is complete (though untested on
actual hardware). Core and the boot classpath compile without issue.
The primary thrust here was to support expanding of short branch
sequences to long form during assembly if the displacement field overflowed.
That led to a general cleanup of creation on LIR nodes outside of the
normal flow.
Also introduced is a README to describe the state of MIPS support, as well
as memory barrier handling.
Change-Id: I251a2ef8d74bc7183406dce9493464be24a9d7f7
Diffstat (limited to 'src/compiler/codegen')
| -rw-r--r-- | src/compiler/codegen/CodegenUtil.cc | 61 | ||||
| -rw-r--r-- | src/compiler/codegen/CompilerCodegen.h | 3 | ||||
| -rw-r--r-- | src/compiler/codegen/GenCommon.cc | 26 | ||||
| -rw-r--r-- | src/compiler/codegen/arm/Assemble.cc | 52 | ||||
| -rw-r--r-- | src/compiler/codegen/arm/Thumb2/Factory.cc | 60 | ||||
| -rw-r--r-- | src/compiler/codegen/arm/Thumb2/Gen.cc | 8 | ||||
| -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 |
13 files changed, 391 insertions, 304 deletions
diff --git a/src/compiler/codegen/CodegenUtil.cc b/src/compiler/codegen/CodegenUtil.cc index 8a38db480f..07eb672eeb 100644 --- a/src/compiler/codegen/CodegenUtil.cc +++ b/src/compiler/codegen/CodegenUtil.cc @@ -410,21 +410,34 @@ void oatCodegenDump(CompilationUnit* cUnit) } } -/* - * The following are building blocks to construct low-level IRs with 0 - 4 - * operands. - */ -LIR* newLIR0(CompilationUnit* cUnit, int opcode) + +LIR* rawLIR(CompilationUnit* cUnit, int dalvikOffset, int opcode, int op0, + int op1, int op2, int op3, LIR* target) { LIR* insn = (LIR* ) oatNew(cUnit, sizeof(LIR), true, kAllocLIR); - DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & NO_OPERAND)); + insn->dalvikOffset = dalvikOffset; insn->opcode = opcode; - setupResourceMasks(insn); - insn->dalvikOffset = cUnit->currentDalvikOffset; + insn->operands[0] = op0; + insn->operands[1] = op1; + insn->operands[2] = op2; + insn->operands[3] = op3; + insn->target = target; + oatSetupResourceMasks(insn); if (opcode == kPseudoTargetLabel) { // Always make labels scheduling barriers insn->defMask = ENCODE_ALL; } + return insn; +} + +/* + * The following are building blocks to construct low-level IRs with 0 - 4 + * operands. + */ +LIR* newLIR0(CompilationUnit* cUnit, int opcode) +{ + DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & NO_OPERAND)); + LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode); oatAppendLIR(cUnit, (LIR*) insn); return insn; } @@ -432,12 +445,8 @@ LIR* newLIR0(CompilationUnit* cUnit, int opcode) LIR* newLIR1(CompilationUnit* cUnit, int opcode, int dest) { - LIR* insn = (LIR* ) oatNew(cUnit, sizeof(LIR), true, kAllocLIR); DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_UNARY_OP)); - insn->opcode = opcode; - insn->operands[0] = dest; - setupResourceMasks(insn); - insn->dalvikOffset = cUnit->currentDalvikOffset; + LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, dest); oatAppendLIR(cUnit, (LIR*) insn); return insn; } @@ -445,14 +454,9 @@ LIR* newLIR1(CompilationUnit* cUnit, int opcode, LIR* newLIR2(CompilationUnit* cUnit, int opcode, int dest, int src1) { - LIR* insn = (LIR* ) oatNew(cUnit, sizeof(LIR), true, kAllocLIR); DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_BINARY_OP)); - insn->opcode = opcode; - insn->operands[0] = dest; - insn->operands[1] = src1; - setupResourceMasks(insn); - insn->dalvikOffset = cUnit->currentDalvikOffset; + LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, dest, src1); oatAppendLIR(cUnit, (LIR*) insn); return insn; } @@ -460,18 +464,13 @@ LIR* newLIR2(CompilationUnit* cUnit, int opcode, LIR* newLIR3(CompilationUnit* cUnit, int opcode, int dest, int src1, int src2) { - LIR* insn = (LIR* ) oatNew(cUnit, sizeof(LIR), true, kAllocLIR); DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_TERTIARY_OP)) << (int)opcode << " " << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " " << cUnit->currentDalvikOffset; - insn->opcode = opcode; - insn->operands[0] = dest; - insn->operands[1] = src1; - insn->operands[2] = src2; - setupResourceMasks(insn); - insn->dalvikOffset = cUnit->currentDalvikOffset; + LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, dest, src1, + src2); oatAppendLIR(cUnit, (LIR*) insn); return insn; } @@ -479,16 +478,10 @@ LIR* newLIR3(CompilationUnit* cUnit, int opcode, LIR* newLIR4(CompilationUnit* cUnit, int opcode, int dest, int src1, int src2, int info) { - LIR* insn = (LIR* ) oatNew(cUnit, sizeof(LIR), true, kAllocLIR); DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_QUAD_OP)); - insn->opcode = opcode; - insn->operands[0] = dest; - insn->operands[1] = src1; - insn->operands[2] = src2; - insn->operands[3] = info; - setupResourceMasks(insn); - insn->dalvikOffset = cUnit->currentDalvikOffset; + LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, dest, src1, + src2, info); oatAppendLIR(cUnit, (LIR*) insn); return insn; } diff --git a/src/compiler/codegen/CompilerCodegen.h b/src/compiler/codegen/CompilerCodegen.h index 26dad8240c..fdcb55557a 100644 --- a/src/compiler/codegen/CompilerCodegen.h +++ b/src/compiler/codegen/CompilerCodegen.h @@ -21,6 +21,9 @@ namespace art { +LIR* rawLIR(CompilationUnit* cUnit, int dalvikOffset, int opcode, int op0 = 0, + int op1 = 0, int op2 = 0, int op3 = 0, LIR* target = NULL); + /* Lower middle-level IR to low-level IR for the whole method */ void oatMethodMIR2LIR(CompilationUnit* cUnit); diff --git a/src/compiler/codegen/GenCommon.cc b/src/compiler/codegen/GenCommon.cc index d0063faf9d..f33b3742a3 100644 --- a/src/compiler/codegen/GenCommon.cc +++ b/src/compiler/codegen/GenCommon.cc @@ -58,10 +58,8 @@ LIR* opUnconditionalBranch(CompilationUnit* cUnit, LIR* target) LIR* genCheck(CompilationUnit* cUnit, ConditionCode cCode, MIR* mir, ThrowKind kind) { - LIR* tgt = (LIR*)oatNew(cUnit, sizeof(LIR), true, kAllocLIR); - tgt->opcode = kPseudoThrowTarget; - tgt->operands[0] = kind; - tgt->operands[1] = mir ? mir->offset : 0; + LIR* tgt = rawLIR(cUnit, 0, kPseudoThrowTarget, kind, + mir ? mir->offset : 0); LIR* branch = opCondBranch(cUnit, cCode, tgt); // Remember branch target - will process later oatInsertGrowableList(cUnit, &cUnit->throwLaunchpads, (intptr_t)tgt); @@ -72,10 +70,7 @@ LIR* genCheck(CompilationUnit* cUnit, ConditionCode cCode, MIR* mir, LIR* genImmedCheck(CompilationUnit* cUnit, ConditionCode cCode, int reg, int immVal, MIR* mir, ThrowKind kind) { - LIR* tgt = (LIR*)oatNew(cUnit, sizeof(LIR), true, kAllocLIR); - tgt->opcode = kPseudoThrowTarget; - tgt->operands[0] = kind; - tgt->operands[1] = mir->offset; + LIR* tgt = rawLIR(cUnit, 0, kPseudoThrowTarget, kind, mir->offset); LIR* branch; if (cCode == kCondAl) { branch = opUnconditionalBranch(cUnit, tgt); @@ -101,12 +96,8 @@ LIR* genNullCheck(CompilationUnit* cUnit, int sReg, int mReg, MIR* mir) LIR* genRegRegCheck(CompilationUnit* cUnit, ConditionCode cCode, int reg1, int reg2, MIR* mir, ThrowKind kind) { - LIR* tgt = (LIR*)oatNew(cUnit, sizeof(LIR), true, kAllocLIR); - tgt->opcode = kPseudoThrowTarget; - tgt->operands[0] = kind; - tgt->operands[1] = mir ? mir->offset : 0; - tgt->operands[2] = reg1; - tgt->operands[3] = reg2; + LIR* tgt = rawLIR(cUnit, 0, kPseudoThrowTarget, kind, + mir ? mir->offset : 0, reg1, reg2); #if defined(TARGET_MIPS) LIR* branch = opCmpBranch(cUnit, cCode, reg1, reg2, tgt); #else @@ -2127,11 +2118,8 @@ void genSuspendTest(CompilationUnit* cUnit, MIR* mir) #endif } LIR* retLab = newLIR0(cUnit, kPseudoTargetLabel); - LIR* target = (LIR*)oatNew(cUnit, sizeof(LIR), true, kAllocLIR); - target->dalvikOffset = cUnit->currentDalvikOffset; - target->opcode = kPseudoSuspendTarget; - target->operands[0] = (intptr_t)retLab; - target->operands[1] = mir->offset; + LIR* target = rawLIR(cUnit, cUnit->currentDalvikOffset, + kPseudoSuspendTarget, (intptr_t)retLab, mir->offset); branch->target = (LIR*)target; oatInsertGrowableList(cUnit, &cUnit->suspendLaunchpads, (intptr_t)target); } diff --git a/src/compiler/codegen/arm/Assemble.cc b/src/compiler/codegen/arm/Assemble.cc index 79a72e74d9..acd2af5535 100644 --- a/src/compiler/codegen/arm/Assemble.cc +++ b/src/compiler/codegen/arm/Assemble.cc @@ -1050,13 +1050,8 @@ AssemblerStatus oatAssembleInstructions(CompilationUnit* cUnit, lir->operands[0] : rLR; // Add new Adr to generate the address - LIR *newAdr = (LIR *)oatNew(cUnit, sizeof(LIR), - true, kAllocLIR); - newAdr->dalvikOffset = lir->dalvikOffset; - newAdr->target = lir->target; - newAdr->opcode = kThumb2Adr; - newAdr->operands[0] = baseReg; - oatSetupResourceMasks(newAdr); + LIR* newAdr = rawLIR(cUnit, lir->dalvikOffset, kThumb2Adr, + baseReg, 0, 0, 0, lir->target); oatInsertLIRBefore((LIR*)lir, (LIR*)newAdr); // Convert to normal load @@ -1083,17 +1078,14 @@ AssemblerStatus oatAssembleInstructions(CompilationUnit* cUnit, intptr_t target = targetLIR->offset; int delta = target - pc; if (delta > 126 || delta < 0) { - /* Convert to cmp rx,#0 / b[eq/ne] tgt pair */ - LIR *newInst = (LIR *)oatNew(cUnit, sizeof(LIR), - true, kAllocLIR); - /* Make new branch instruction and insert after */ - newInst->dalvikOffset = lir->dalvikOffset; - newInst->opcode = kThumbBCond; - newInst->operands[0] = 0; - newInst->operands[1] = (lir->opcode == kThumb2Cbz) ? - kArmCondEq : kArmCondNe; - newInst->target = lir->target; - oatSetupResourceMasks(newInst); + /* + * Convert to cmp rx,#0 / b[eq/ne] tgt pair + * Make new branch instruction and insert after + */ + LIR* newInst = + rawLIR(cUnit, lir->dalvikOffset, kThumbBCond, 0, + (lir->opcode == kThumb2Cbz) ? kArmCondEq : kArmCondNe, + 0, 0, lir->target); oatInsertLIRAfter((LIR *)lir, (LIR *)newInst); /* Convert the cb[n]z to a cmp rx, #0 ] */ lir->opcode = kThumbCmpRI8; @@ -1209,26 +1201,14 @@ AssemblerStatus oatAssembleInstructions(CompilationUnit* cUnit, } else { // convert to ldimm16l, ldimm16h, add tgt, pc, operands[0] LIR *newMov16L = - (LIR *)oatNew(cUnit, sizeof(LIR), true, - kAllocLIR); - newMov16L->dalvikOffset = lir->dalvikOffset; - newMov16L->target = lir->target; - newMov16L->opcode = kThumb2MovImm16LST; - newMov16L->operands[0] = lir->operands[0]; - newMov16L->operands[2] = (intptr_t)lir; - newMov16L->operands[3] = (intptr_t)tabRec; - oatSetupResourceMasks(newMov16L); + rawLIR(cUnit, lir->dalvikOffset, kThumb2MovImm16LST, + lir->operands[0], 0, (intptr_t)lir, (intptr_t)tabRec, + lir->target); oatInsertLIRBefore((LIR*)lir, (LIR*)newMov16L); LIR *newMov16H = - (LIR *)oatNew(cUnit, sizeof(LIR), true, - kAllocLIR); - newMov16H->dalvikOffset = lir->dalvikOffset; - newMov16H->target = lir->target; - newMov16H->opcode = kThumb2MovImm16HST; - newMov16H->operands[0] = lir->operands[0]; - newMov16H->operands[2] = (intptr_t)lir; - newMov16H->operands[3] = (intptr_t)tabRec; - oatSetupResourceMasks(newMov16H); + rawLIR(cUnit, lir->dalvikOffset, kThumb2MovImm16HST, + lir->operands[0], 0, (intptr_t)lir, (intptr_t)tabRec, + lir->target); oatInsertLIRBefore((LIR*)lir, (LIR*)newMov16H); lir->opcode = kThumb2AddRRR; lir->operands[1] = rPC; diff --git a/src/compiler/codegen/arm/Thumb2/Factory.cc b/src/compiler/codegen/arm/Thumb2/Factory.cc index 03a69d5759..b6df8e3ead 100644 --- a/src/compiler/codegen/arm/Thumb2/Factory.cc +++ b/src/compiler/codegen/arm/Thumb2/Factory.cc @@ -68,14 +68,8 @@ LIR* loadFPConstantValue(CompilationUnit* cUnit, int rDest, int value) if (dataTarget == NULL) { dataTarget = addWordData(cUnit, &cUnit->literalList, value); } - LIR* loadPcRel = (LIR* ) oatNew(cUnit, sizeof(LIR), true, - kAllocLIR); - loadPcRel->dalvikOffset = cUnit->currentDalvikOffset; - loadPcRel->opcode = kThumb2Vldrs; - loadPcRel->target = (LIR* ) dataTarget; - loadPcRel->operands[0] = rDest; - loadPcRel->operands[1] = r15pc; - setupResourceMasks(loadPcRel); + LIR* loadPcRel = rawLIR(cUnit, cUnit->currentDalvikOffset, kThumb2Vldrs, + rDest, r15pc, 0, 0, dataTarget); setMemRefType(loadPcRel, true, kLiteral); loadPcRel->aliasInfo = (intptr_t)dataTarget; oatAppendLIR(cUnit, (LIR* ) loadPcRel); @@ -177,13 +171,8 @@ LIR* loadConstantNoClobber(CompilationUnit* cUnit, int rDest, int value) if (dataTarget == NULL) { dataTarget = addWordData(cUnit, &cUnit->literalList, value); } - LIR* loadPcRel = (LIR* ) oatNew(cUnit, sizeof(LIR), true, - kAllocLIR); - loadPcRel->opcode = kThumb2LdrPcRel12; - loadPcRel->target = (LIR* ) dataTarget; - loadPcRel->dalvikOffset = cUnit->currentDalvikOffset; - loadPcRel->operands[0] = rDest; - setupResourceMasks(loadPcRel); + LIR* loadPcRel = rawLIR(cUnit, cUnit->currentDalvikOffset, + kThumb2LdrPcRel12, rDest, 0, 0, 0, dataTarget); setMemRefType(loadPcRel, true, kLiteral); loadPcRel->aliasInfo = (intptr_t)dataTarget; res = loadPcRel; @@ -643,14 +632,9 @@ LIR* loadConstantValueWide(CompilationUnit* cUnit, int rDestLo, int rDestHi, dataTarget = addWideData(cUnit, &cUnit->literalList, valLo, valHi); } - LIR* loadPcRel = (LIR* ) oatNew(cUnit, sizeof(LIR), true, - kAllocLIR); - loadPcRel->dalvikOffset = cUnit->currentDalvikOffset; - loadPcRel->opcode = kThumb2Vldrd; - loadPcRel->target = (LIR* ) dataTarget; - loadPcRel->operands[0] = S2D(rDestLo, rDestHi); - loadPcRel->operands[1] = r15pc; - setupResourceMasks(loadPcRel); + LIR* loadPcRel = rawLIR(cUnit, cUnit->currentDalvikOffset, + kThumb2Vldrd, S2D(rDestLo, rDestHi), + r15pc, 0, 0, dataTarget); setMemRefType(loadPcRel, true, kLiteral); loadPcRel->aliasInfo = (intptr_t)dataTarget; oatAppendLIR(cUnit, (LIR* ) loadPcRel); @@ -1042,28 +1026,22 @@ void loadPair(CompilationUnit* cUnit, int base, int lowReg, int highReg) LIR* fpRegCopy(CompilationUnit* cUnit, int rDest, int rSrc) { - LIR* res = (LIR* ) oatNew(cUnit, sizeof(LIR), true, kAllocLIR); - res->dalvikOffset = cUnit->currentDalvikOffset; - res->operands[0] = rDest; - res->operands[1] = rSrc; - if (rDest == rSrc) { - res->flags.isNop = true; + int opcode; + DCHECK_EQ(DOUBLEREG(rDest), DOUBLEREG(rSrc)); + if (DOUBLEREG(rDest)) { + opcode = kThumb2Vmovd; } else { - DCHECK_EQ(DOUBLEREG(rDest), DOUBLEREG(rSrc)); - if (DOUBLEREG(rDest)) { - res->opcode = kThumb2Vmovd; + if (SINGLEREG(rDest)) { + opcode = SINGLEREG(rSrc) ? kThumb2Vmovs : kThumb2Fmsr; } else { - if (SINGLEREG(rDest)) { - res->opcode = SINGLEREG(rSrc) ? kThumb2Vmovs : kThumb2Fmsr; - } else { - DCHECK(SINGLEREG(rSrc)); - res->opcode = kThumb2Fmrs; - } + DCHECK(SINGLEREG(rSrc)); + opcode = kThumb2Fmrs; } - res->operands[0] = rDest; - res->operands[1] = rSrc; } - setupResourceMasks(res); + LIR* res = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, rDest, rSrc); + if (rDest == rSrc) { + res->flags.isNop = true; + } return res; } diff --git a/src/compiler/codegen/arm/Thumb2/Gen.cc b/src/compiler/codegen/arm/Thumb2/Gen.cc index cba37b71ce..135199225b 100644 --- a/src/compiler/codegen/arm/Thumb2/Gen.cc +++ b/src/compiler/codegen/arm/Thumb2/Gen.cc @@ -428,8 +428,6 @@ LIR* opRegCopyNoInsert(CompilationUnit* cUnit, int rDest, int rSrc) ArmOpcode opcode; if (FPREG(rDest) || FPREG(rSrc)) return fpRegCopy(cUnit, rDest, rSrc); - res = (LIR* ) oatNew(cUnit, sizeof(LIR), true, kAllocLIR); - res->dalvikOffset = cUnit->currentDalvikOffset; if (LOWREG(rDest) && LOWREG(rSrc)) opcode = kThumbMovRR; else if (!LOWREG(rDest) && !LOWREG(rSrc)) @@ -438,11 +436,7 @@ LIR* opRegCopyNoInsert(CompilationUnit* cUnit, int rDest, int rSrc) opcode = kThumbMovRR_H2L; else opcode = kThumbMovRR_L2H; - - res->operands[0] = rDest; - res->operands[1] = rSrc; - res->opcode = opcode; - setupResourceMasks(res); + res = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, rDest, rSrc); if (rDest == rSrc) { res->flags.isNop = true; } 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 } |