diff options
Diffstat (limited to 'src/compiler/codegen/mips')
| -rw-r--r-- | src/compiler/codegen/mips/ArchFactory.cc | 71 | ||||
| -rw-r--r-- | src/compiler/codegen/mips/Assemble.cc | 74 | ||||
| -rw-r--r-- | src/compiler/codegen/mips/Codegen.h | 6 | ||||
| -rw-r--r-- | src/compiler/codegen/mips/FP/MipsFP.cc | 8 | ||||
| -rw-r--r-- | src/compiler/codegen/mips/Mips32/Factory.cc | 6 | ||||
| -rw-r--r-- | src/compiler/codegen/mips/Mips32/Gen.cc | 222 | ||||
| -rw-r--r-- | src/compiler/codegen/mips/MipsLIR.h | 9 |
7 files changed, 314 insertions, 82 deletions
diff --git a/src/compiler/codegen/mips/ArchFactory.cc b/src/compiler/codegen/mips/ArchFactory.cc index 963427ddce..9050cf973c 100644 --- a/src/compiler/codegen/mips/ArchFactory.cc +++ b/src/compiler/codegen/mips/ArchFactory.cc @@ -24,6 +24,77 @@ namespace art { +bool genAddLong(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest, + RegLocation rlSrc1, RegLocation rlSrc2) +{ + rlSrc1 = loadValueWide(cUnit, rlSrc1, kCoreReg); + rlSrc2 = loadValueWide(cUnit, rlSrc2, kCoreReg); + RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true); + /* + * [v1 v0] = [a1 a0] + [a3 a2]; + * addu v0,a2,a0 + * addu t1,a3,a1 + * sltu v1,v0,a2 + * addu v1,v1,t1 + */ + + opRegRegReg(cUnit, kOpAdd, rlResult.lowReg, rlSrc2.lowReg, rlSrc1.lowReg); + int tReg = oatAllocTemp(cUnit); + opRegRegReg(cUnit, kOpAdd, tReg, rlSrc2.highReg, rlSrc1.highReg); + newLIR3(cUnit, kMipsSltu, rlResult.highReg, rlResult.lowReg, rlSrc2.lowReg); + opRegRegReg(cUnit, kOpAdd, rlResult.highReg, rlResult.highReg, tReg); + oatFreeTemp(cUnit, tReg); + storeValueWide(cUnit, rlDest, rlResult); + return false; +} + +bool genSubLong(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest, + RegLocation rlSrc1, RegLocation rlSrc2) +{ + rlSrc1 = loadValueWide(cUnit, rlSrc1, kCoreReg); + rlSrc2 = loadValueWide(cUnit, rlSrc2, kCoreReg); + RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true); + /* + * [v1 v0] = [a1 a0] - [a3 a2]; + * subu v0,a0,a2 + * subu v1,a1,a3 + * sltu t1,a0,v0 + * subu v1,v1,t1 + */ + + opRegRegReg(cUnit, kOpSub, rlResult.lowReg, rlSrc1.lowReg, rlSrc2.lowReg); + opRegRegReg(cUnit, kOpSub, rlResult.highReg, rlSrc1.highReg, rlSrc2.highReg); + int tReg = oatAllocTemp(cUnit); + newLIR3(cUnit, kMipsSltu, tReg, rlSrc1.lowReg, rlResult.lowReg); + opRegRegReg(cUnit, kOpSub, rlResult.highReg, rlResult.highReg, tReg); + oatFreeTemp(cUnit, tReg); + storeValueWide(cUnit, rlDest, rlResult); + return false; +} + +bool genNegLong(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest, + RegLocation rlSrc) +{ + rlSrc = loadValueWide(cUnit, rlSrc, kCoreReg); + RegLocation rlResult = oatEvalLoc(cUnit, rlDest, kCoreReg, true); + /* + * [v1 v0] = -[a1 a0] + * negu v0,a0 + * negu v1,a1 + * sltu t1,r_zero + * subu v1,v1,t1 + */ + + opRegReg(cUnit, kOpNeg, rlResult.lowReg, rlSrc.lowReg); + opRegReg(cUnit, kOpNeg, rlResult.highReg, rlSrc.highReg); + int tReg = oatAllocTemp(cUnit); + newLIR3(cUnit, kMipsSltu, tReg, r_ZERO, rlResult.lowReg); + opRegRegReg(cUnit, kOpSub, rlResult.highReg, rlResult.highReg, tReg); + oatFreeTemp(cUnit, tReg); + storeValueWide(cUnit, rlDest, rlResult); + return false; +} + void genDebuggerUpdate(CompilationUnit* cUnit, int32_t offset); /* diff --git a/src/compiler/codegen/mips/Assemble.cc b/src/compiler/codegen/mips/Assemble.cc index 0021318c6d..5f215ef6bf 100644 --- a/src/compiler/codegen/mips/Assemble.cc +++ b/src/compiler/codegen/mips/Assemble.cc @@ -221,7 +221,7 @@ MipsEncodingMap EncodingMap[kMipsLast] = { ENCODING_MAP(kMipsNop, 0x00000000, kFmtUnused, -1, -1, kFmtUnused, -1, -1, kFmtUnused, -1, -1, kFmtUnused, -1, -1, NO_OPERAND, - "nop", "", 4), + "nop", ";", 4), ENCODING_MAP(kMipsNor, 0x00000027, /* used for "not" too */ kFmtBitBlt, 15, 11, kFmtBitBlt, 25, 21, kFmtBitBlt, 20, 16, kFmtUnused, -1, -1, IS_TERTIARY_OP | REG_DEF0_USE12, @@ -398,6 +398,22 @@ MipsEncodingMap EncodingMap[kMipsLast] = { kFmtUnused, -1, -1, IS_BINARY_OP | REG_USE0 | REG_DEF1, "mtc1", "!0r,!1s", 4), #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), + ENCODING_MAP(kMipsDeltaHi, 0x3C000000, + kFmtBitBlt, 20, 16, kFmtBitBlt, 15, 0, kFmtUnused, -1, -1, + kFmtUnused, -1, -1, IS_QUAD_OP | REG_DEF0, + "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, + "ori", "!0r,!0r,0x!1h(!1d)", 4), + ENCODING_MAP(kMipsCurrPC, 0x0c000000, + 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(kMipsUndefined, 0x64000000, kFmtUnused, -1, -1, kFmtUnused, -1, -1, kFmtUnused, -1, -1, kFmtUnused, -1, -1, NO_OPERAND, @@ -426,7 +442,56 @@ AssemblerStatus oatAssembleInstructions(CompilationUnit *cUnit, continue; } - if (lir->opcode == kMipsB || lir->opcode == kMipsBal) { +// 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; @@ -508,6 +573,11 @@ AssemblerStatus oatAssembleInstructions(CompilationUnit *cUnit, } bits |= value; break; + case kFmtBlt5_2: + value = (operand & 0x1f); + bits |= (value << encoder->fieldLoc[i].start); + bits |= (value << encoder->fieldLoc[i].end); + break; case kFmtDfp: { DCHECK(DOUBLEREG(operand)); DCHECK((operand & 0x1) == 0); diff --git a/src/compiler/codegen/mips/Codegen.h b/src/compiler/codegen/mips/Codegen.h index c6f1d98b0f..520d638fe7 100644 --- a/src/compiler/codegen/mips/Codegen.h +++ b/src/compiler/codegen/mips/Codegen.h @@ -27,6 +27,12 @@ namespace art { #if defined(_CODEGEN_C) +bool genAddLong(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest, + RegLocation rlSrc1, RegLocation rlSrc2); +bool genSubLong(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest, + RegLocation rlSrc1, RegLocation rlSrc2); +bool genNegLong(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest, + RegLocation rlSrc); LIR *opRegImm(CompilationUnit* cUnit, OpKind op, int rDestSrc1, int value); LIR *opRegReg(CompilationUnit* cUnit, OpKind op, int rDestSrc1, int rSrc2); LIR* opCmpBranch(CompilationUnit* cUnit, ConditionCode cond, int src1, diff --git a/src/compiler/codegen/mips/FP/MipsFP.cc b/src/compiler/codegen/mips/FP/MipsFP.cc index 4501210d6c..6a51f6965d 100644 --- a/src/compiler/codegen/mips/FP/MipsFP.cc +++ b/src/compiler/codegen/mips/FP/MipsFP.cc @@ -61,7 +61,7 @@ bool genArithOpFloat(CompilationUnit *cUnit, MIR *mir, RegLocation rlDest, return false; #else - UNIMPLEMENTED(FATAL) << "Need Mips soft float implementation"; + UNIMPLEMENTED(WARNING) << "Need Mips soft float implementation"; return false; #endif } @@ -112,7 +112,7 @@ static bool genArithOpDouble(CompilationUnit *cUnit, MIR *mir, storeValueWide(cUnit, rlDest, rlResult); return false; #else - UNIMPLEMENTED(FATAL) << "Need Mips soft float implementation"; + UNIMPLEMENTED(WARNING) << "Need Mips soft float implementation"; return false; #endif } @@ -181,7 +181,7 @@ static bool genConversion(CompilationUnit *cUnit, MIR *mir) } return false; #else - UNIMPLEMENTED(FATAL) << "Need Mips soft float implementation"; + UNIMPLEMENTED(WARNING) << "Need Mips soft float implementation"; return false; #endif } @@ -189,7 +189,7 @@ static bool genConversion(CompilationUnit *cUnit, MIR *mir) static bool genCmpFP(CompilationUnit *cUnit, MIR *mir, RegLocation rlDest, RegLocation rlSrc1, RegLocation rlSrc2) { - UNIMPLEMENTED(FATAL) << "Need Mips implementation"; + UNIMPLEMENTED(WARNING) << "Need Mips implementation"; return false; #if 0 TemplateOpcode templateOpcode; diff --git a/src/compiler/codegen/mips/Mips32/Factory.cc b/src/compiler/codegen/mips/Mips32/Factory.cc index 46987d356d..105677eef2 100644 --- a/src/compiler/codegen/mips/Mips32/Factory.cc +++ b/src/compiler/codegen/mips/Mips32/Factory.cc @@ -28,7 +28,7 @@ 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}; +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 @@ -227,6 +227,10 @@ LIR *opRegRegReg(CompilationUnit *cUnit, OpKind op, int rDest, case kOpAsr: opcode = kMipsSrav; break; + case kOpAdc: + case kOpSbc: + LOG(FATAL) << "No carry bit on MIPS"; + break; default: LOG(FATAL) << "bad case in opRegRegReg"; break; diff --git a/src/compiler/codegen/mips/Mips32/Gen.cc b/src/compiler/codegen/mips/Mips32/Gen.cc index 155675c700..c975889bed 100644 --- a/src/compiler/codegen/mips/Mips32/Gen.cc +++ b/src/compiler/codegen/mips/Mips32/Gen.cc @@ -25,28 +25,38 @@ namespace art { /* - * The sparse table in the literal pool is an array of <key,displacement> - * pairs. For each set, we'll load them as a pair using ldmia. - * This means that the register number of the temp we use for the key - * must be lower than the reg for the displacement. + * The lack of pc-relative loads on Mips presents somewhat of a challenge + * for our PIC switch table strategy. To materialize the current location + * we'll do a dummy JAL and reference our tables using r_RA as the + * base register. Note that r_RA will be used both as the base to + * locate the switch table data and as the reference base for the switch + * target offsets stored in the table. We'll use a special pseudo-instruction + * to represent the jal and trigger the construction of the + * switch table offsets (which will happen after final assembly and all + * labels are fixed). * * The test loop will look something like: * - * adr rBase, <table> - * ldr rVal, [rSP, vRegOff] - * mov rIdx, #tableSize - * lp: - * ldmia rBase!, {rKey, rDisp} - * sub rIdx, #1 - * cmp rVal, rKey - * ifeq - * add rPC, rDisp ; This is the branch from which we compute displacement - * cbnz rIdx, lp + * ori rEnd, r_ZERO, #tableSize ; size in bytes + * jal BaseLabel ; stores "return address" (BaseLabel) in r_RA + * nop ; opportunistically fill + * BaseLabel: + * addiu rBase, r_RA, <table> - <BaseLabel> ; table relative to BaseLabel + addu rEnd, rEnd, rBase ; end of table + * lw rVal, [rSP, vRegOff] ; Test Value + * loop: + * beq rBase, rEnd, done + * lw rKey, 0(rBase) + * addu rBase, 8 + * bne rVal, rKey, loop + * lw rDisp, -4(rBase) + * addu r_RA, rDisp + * jr r_RA + * done: + * */ void genSparseSwitch(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc) { - UNIMPLEMENTED(FATAL) << "Needs Mips sparse switch"; -#if 0 const u2* table = cUnit->insns + mir->offset + mir->dalvikInsn.vB; if (cUnit->printMe) { dumpSparseSwitchTable(table); @@ -56,49 +66,75 @@ void genSparseSwitch(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc) true, kAllocData); tabRec->table = table; tabRec->vaddr = mir->offset; - int size = table[1]; - tabRec->targets = (LIR* *)oatNew(cUnit, size * sizeof(LIR*), true, + int elements = table[1]; + tabRec->targets = (LIR* *)oatNew(cUnit, elements * sizeof(LIR*), true, kAllocLIR); oatInsertGrowableList(cUnit, &cUnit->switchTables, (intptr_t)tabRec); - // Get the switch value - rlSrc = loadValue(cUnit, rlSrc, kCoreReg); + // The table is composed of 8-byte key/disp pairs + int byteSize = elements * 8; + + int sizeHi = byteSize >> 16; + int sizeLo = byteSize & 0xffff; + + int rEnd = oatAllocTemp(cUnit); + if (sizeHi) { + newLIR2(cUnit, kMipsLui, rEnd, sizeHi); + } + // Must prevent code motion for the curr pc pair + genBarrier(cUnit); // Scheduling barrier + newLIR0(cUnit, kMipsCurrPC); // Really a jal to .+8 + // Now, fill the branch delay slot + if (sizeHi) { + newLIR3(cUnit, kMipsOri, rEnd, rEnd, sizeLo); + } else { + newLIR3(cUnit, kMipsOri, rEnd, r_ZERO, sizeLo); + } + genBarrier(cUnit); // Scheduling barrier + + // Construct BaseLabel and set up table base register + LIR* baseLabel = newLIR0(cUnit, kPseudoTargetLabel); + // Remember base label so offsets can be computed later + tabRec->anchor = baseLabel; int rBase = oatAllocTemp(cUnit); - /* Allocate key and disp temps */ + newLIR4(cUnit, kMipsDelta, rBase, 0, (intptr_t)baseLabel, (intptr_t)tabRec); + opRegRegReg(cUnit, kOpAdd, rEnd, rEnd, rBase); + + // Grab switch test value + rlSrc = loadValue(cUnit, rlSrc, kCoreReg); + + // Test loop int rKey = oatAllocTemp(cUnit); + LIR* loopLabel = newLIR0(cUnit, kPseudoTargetLabel); + LIR* exitBranch = opCmpBranch(cUnit , kCondEq, rBase, rEnd, NULL); + loadWordDisp(cUnit, rBase, 0, rKey); + opRegImm(cUnit, kOpAdd, rBase, 8); + opCmpBranch(cUnit, kCondNe, rlSrc.lowReg, rKey, loopLabel); int rDisp = oatAllocTemp(cUnit); - // Make sure rKey's register number is less than rDisp's number for ldmia - if (rKey > rDisp) { - int tmp = rDisp; - rDisp = rKey; - rKey = tmp; - } - // Materialize a pointer to the switch table - newLIR3(cUnit, kThumb2Adr, rBase, 0, (intptr_t)tabRec); - // Set up rIdx - int rIdx = oatAllocTemp(cUnit); - loadConstant(cUnit, rIdx, size); - // Establish loop branch target - LIR* target = newLIR0(cUnit, kPseudoTargetLabel); - target->defMask = ENCODE_ALL; - // Load next key/disp - newLIR2(cUnit, kThumb2LdmiaWB, rBase, (1 << rKey) | (1 << rDisp)); - opRegReg(cUnit, kOpCmp, rKey, rlSrc.lowReg); - // Go if match. NOTE: No instruction set switch here - must stay Thumb2 - opIT(cUnit, kArmCondEq, ""); - LIR* switchBranch = newLIR1(cUnit, kThumb2AddPCR, rDisp); - tabRec->bxInst = switchBranch; - // Needs to use setflags encoding here - newLIR3(cUnit, kThumb2SubsRRI12, rIdx, rIdx, 1); - LIR* branch = opCondBranch(cUnit, kCondNe, target); -#endif -} + loadWordDisp(cUnit, rBase, -4, rDisp); + opRegRegReg(cUnit, kOpAdd, r_RA, r_RA, rDisp); + opReg(cUnit, kOpBx, r_RA); + // Loop exit + LIR* exitLabel = newLIR0(cUnit, kPseudoTargetLabel); + exitBranch->target = exitLabel; +} +/* + * Code pattern will look something like: + * + * lw rVal + * jal BaseLabel ; stores "return address" (BaseLabel) in r_RA + * nop ; opportunistically fill + * [subiu rVal, bias] ; Remove bias if lowVal != 0 + * bound check -> done + * lw rDisp, [r_RA, rVal] + * addu r_RA, rDisp + * jr r_RA + * done: + */ void genPackedSwitch(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc) { - UNIMPLEMENTED(FATAL) << "Need Mips packed switch"; -#if 0 const u2* table = cUnit->insns + mir->offset + mir->dalvikInsn.vB; if (cUnit->printMe) { dumpPackedSwitchTable(table); @@ -115,35 +151,59 @@ void genPackedSwitch(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc) // Get the switch value rlSrc = loadValue(cUnit, rlSrc, kCoreReg); - int tableBase = oatAllocTemp(cUnit); - // Materialize a pointer to the switch table - newLIR3(cUnit, kThumb2Adr, tableBase, 0, (intptr_t)tabRec); + + // Prepare the bias. If too big, handle 1st stage here int lowKey = s4FromSwitchData(&table[2]); - int keyReg; - // Remove the bias, if necessary + bool largeBias = false; + int rKey; if (lowKey == 0) { - keyReg = rlSrc.lowReg; + rKey = rlSrc.lowReg; + } else if ((lowKey & 0xffff) != lowKey) { + rKey = oatAllocTemp(cUnit); + loadConstant(cUnit, rKey, lowKey); + largeBias = true; } else { - keyReg = oatAllocTemp(cUnit); - opRegRegImm(cUnit, kOpSub, keyReg, rlSrc.lowReg, lowKey); + rKey = oatAllocTemp(cUnit); } + + // Must prevent code motion for the curr pc pair + genBarrier(cUnit); + newLIR0(cUnit, kMipsCurrPC); // Really a jal to .+8 + // Now, fill the branch delay slot with bias strip + if (lowKey == 0) { + newLIR0(cUnit, kMipsNop); + } else { + if (largeBias) { + opRegRegReg(cUnit, kOpSub, rKey, rlSrc.lowReg, rKey); + } else { + opRegRegImm(cUnit, kOpSub, rKey, rlSrc.lowReg, lowKey); + } + } + genBarrier(cUnit); // Scheduling barrier + + // Construct BaseLabel and set up table base register + LIR* baseLabel = newLIR0(cUnit, kPseudoTargetLabel); + // Remember base label so offsets can be computed later + tabRec->anchor = baseLabel; + // Bounds check - if < 0 or >= size continue following switch - opRegImm(cUnit, kOpCmp, keyReg, size-1); - LIR* branchOver = opCondBranch(cUnit, kCondHi, NULL); + LIR* branchOver = opCmpImmBranch(cUnit, kCondHi, rKey, size-1, NULL); + + // Materialize the table base pointer + int rBase = oatAllocTemp(cUnit); + newLIR4(cUnit, kMipsDelta, rBase, 0, (intptr_t)baseLabel, (intptr_t)tabRec); // Load the displacement from the switch table - int dispReg = oatAllocTemp(cUnit); - loadBaseIndexed(cUnit, tableBase, keyReg, dispReg, 2, kWord); + int rDisp = oatAllocTemp(cUnit); + loadBaseIndexed(cUnit, rBase, rKey, rDisp, 2, kWord); - // ..and go! NOTE: No instruction set switch here - must stay Thumb2 - LIR* switchBranch = newLIR1(cUnit, kThumb2AddPCR, dispReg); - tabRec->bxInst = switchBranch; + // Add to r_AP and go + opRegRegReg(cUnit, kOpAdd, r_RA, r_RA, rDisp); + opReg(cUnit, kOpBx, r_RA); /* branchOver target here */ LIR* target = newLIR0(cUnit, kPseudoTargetLabel); - target->defMask = ENCODE_ALL; branchOver->target = (LIR*)target; -#endif } /* @@ -158,8 +218,6 @@ void genPackedSwitch(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc) */ void genFillArrayData(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc) { - UNIMPLEMENTED(FATAL) << "Needs Mips FillArrayData"; -#if 0 const u2* table = cUnit->insns + mir->offset + mir->dalvikInsn.vB; // Add the table to the list - we'll process it later FillArrayData *tabRec = (FillArrayData *) @@ -174,13 +232,25 @@ void genFillArrayData(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc) // Making a call - use explicit registers oatFlushAllRegs(cUnit); /* Everything to home location */ + oatLockCallTemps(cUnit); loadValueDirectFixed(cUnit, rlSrc, rARG0); - loadWordDisp(cUnit, rSELF, - OFFSETOF_MEMBER(Thread, pHandleFillArrayDataFromCode), rLR); + + // Must prevent code motion for the curr pc pair + genBarrier(cUnit); + newLIR0(cUnit, kMipsCurrPC); // Really a jal to .+8 + // Now, fill the branch delay slot with the helper load + int rTgt = loadHelper(cUnit, OFFSETOF_MEMBER(Thread, + pHandleFillArrayDataFromCode)); + genBarrier(cUnit); // Scheduling barrier + + // Construct BaseLabel and set up table base register + LIR* baseLabel = newLIR0(cUnit, kPseudoTargetLabel); + // Materialize a pointer to the fill data image - newLIR3(cUnit, kThumb2Adr, r1, 0, (intptr_t)tabRec); - callRuntimeHelper(cUnit, rLR); -#endif + newLIR4(cUnit, kMipsDelta, rARG1, 0, (intptr_t)baseLabel, (intptr_t)tabRec); + + // And go... + callRuntimeHelper(cUnit, rTgt); // ( array*, fill_data* ) } void genNegFloat(CompilationUnit *cUnit, RegLocation rlDest, RegLocation rlSrc) @@ -266,7 +336,6 @@ void genCmpLong(CompilationUnit* cUnit, MIR* mir, RegLocation rlDest, oatFreeTemp(cUnit, t0); oatFreeTemp(cUnit, t1); LIR* target = newLIR0(cUnit, kPseudoTargetLabel); - target->defMask = ENCODE_ALL; branch->target = (LIR*)target; storeValue(cUnit, rlDest, rlResult); } @@ -314,6 +383,11 @@ LIR* opCmpBranch(CompilationUnit* cUnit, ConditionCode cond, int src1, sltOp = kMipsSlt; brOp = kMipsBnez; break; + case kCondHi: // Gtu + sltOp = kMipsSltu; + brOp = kMipsBnez; + swapped = true; + break; default: UNIMPLEMENTED(FATAL) << "No support for ConditionCode: " << (int) cond; diff --git a/src/compiler/codegen/mips/MipsLIR.h b/src/compiler/codegen/mips/MipsLIR.h index b2cfdbed59..5034623c2b 100644 --- a/src/compiler/codegen/mips/MipsLIR.h +++ b/src/compiler/codegen/mips/MipsLIR.h @@ -426,6 +426,10 @@ typedef enum MipsOpCode { kMipsMfc1, /* mfc1 t,s [01000100000] t[20..16] s[15..11] [00000000000] */ kMipsMtc1, /* mtc1 t,s [01000100100] t[20..16] s[15..11] [00000000000] */ #endif + kMipsDelta, /* Psuedo for ori t, s, <label>-<label> */ + kMipsDeltaHi, /* Pseudo for lui t, high16(<label>-<label>) */ + kMipsDeltaLo, /* Pseudo for ori t, s, low16(<label>-<label>) */ + kMipsCurrPC, /* jal to .+8 to materialize pc */ kMipsUndefined, /* undefined [011001xxxxxxxxxxxxxxxx] */ kMipsLast } MipsOpCode; @@ -458,6 +462,7 @@ typedef enum MipsOpFeatureFlags { kMemLoad, kMemStore, kPCRelFixup, + kRegUseLR, // FIXME: add NEEDS_FIXUP to instruction attributes } MipsOpFeatureFlags; @@ -486,7 +491,8 @@ typedef enum MipsOpFeatureFlags { #define IS_IT (1 << kIsIT) #define SETS_CCODES (1 << kSetsCCodes) #define USES_CCODES (1 << kUsesCCodes) -#define NEEDS_FIXUP (1 << kPCRelFixup) +#define NEEDS_FIXUP (1 << kPCRelFixup) +#define REG_USE_LR (1 << kRegUseLR) /* attributes, included for compatibility */ #define REG_DEF_FPCS_LIST0 (0) @@ -513,6 +519,7 @@ typedef enum MipsEncodingKind { kFmtBitBlt, /* Bit string using end/start */ kFmtDfp, /* Double FP reg */ kFmtSfp, /* Single FP reg */ + kFmtBlt5_2, /* Same 5-bit field to 2 locations */ } MipsEncodingKind; /* Struct used to define the snippet positions for each Thumb opcode */ |