diff options
| author | 2012-03-03 11:48:39 -0800 | |
|---|---|---|
| committer | 2012-03-03 16:32:24 -0800 | |
| commit | c5159d55ca8e9022b748176f9f53676e8e9d4cd2 (patch) | |
| tree | d407a682788fbbca4dbd0821350058a3c2901617 /src/compiler/codegen/mips/Assemble.cc | |
| parent | 5b455485c1deda58959fdc410050e01448c032c2 (diff) | |
MIPS switch table support
And 64-bit neg/add/sub (ouch! Mips has no carry bit...)
Change-Id: Ifb94324a0052d6069977fb8f22679b95890445d8
Diffstat (limited to 'src/compiler/codegen/mips/Assemble.cc')
| -rw-r--r-- | src/compiler/codegen/mips/Assemble.cc | 74 |
1 files changed, 72 insertions, 2 deletions
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); |