15d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng/*
25d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * Copyright (C) 2009 The Android Open Source Project
35d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng *
45d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * Licensed under the Apache License, Version 2.0 (the "License");
55d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * you may not use this file except in compliance with the License.
65d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * You may obtain a copy of the License at
75d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng *
85d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng *      http://www.apache.org/licenses/LICENSE-2.0
95d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng *
105d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * Unless required by applicable law or agreed to in writing, software
115d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * distributed under the License is distributed on an "AS IS" BASIS,
125d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * See the License for the specific language governing permissions and
145d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * limitations under the License.
155d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng */
165d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng
175d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng/*
182e152baec01433de9c63633ebc6f4adf1cea3a87buzbee * This file contains codegen for the Thumb2 ISA and is intended to be
195d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * includes by:
205d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng *
215d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng *        Codegen-$(TARGET_ARCH_VARIANT).c
225d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng *
235d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng */
245d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng
252e152baec01433de9c63633ebc6f4adf1cea3a87buzbee/*
262e152baec01433de9c63633ebc6f4adf1cea3a87buzbee * Reserve 6 bytes at the beginning of the trace
272e152baec01433de9c63633ebc6f4adf1cea3a87buzbee *        +----------------------------+
282e152baec01433de9c63633ebc6f4adf1cea3a87buzbee *        | prof count addr (4 bytes)  |
292e152baec01433de9c63633ebc6f4adf1cea3a87buzbee *        +----------------------------+
302e152baec01433de9c63633ebc6f4adf1cea3a87buzbee *        | chain cell offset (2 bytes)|
312e152baec01433de9c63633ebc6f4adf1cea3a87buzbee *        +----------------------------+
322e152baec01433de9c63633ebc6f4adf1cea3a87buzbee *
332e152baec01433de9c63633ebc6f4adf1cea3a87buzbee * ...and then code to increment the execution
342e152baec01433de9c63633ebc6f4adf1cea3a87buzbee *
352e152baec01433de9c63633ebc6f4adf1cea3a87buzbee * For continuous profiling (10 bytes)
362e152baec01433de9c63633ebc6f4adf1cea3a87buzbee *       ldr   r0, [pc-8]   @ get prof count addr    [4 bytes]
372e152baec01433de9c63633ebc6f4adf1cea3a87buzbee *       ldr   r1, [r0]     @ load counter           [2 bytes]
382e152baec01433de9c63633ebc6f4adf1cea3a87buzbee *       add   r1, #1       @ increment              [2 bytes]
392e152baec01433de9c63633ebc6f4adf1cea3a87buzbee *       str   r1, [r0]     @ store                  [2 bytes]
402e152baec01433de9c63633ebc6f4adf1cea3a87buzbee *
412e152baec01433de9c63633ebc6f4adf1cea3a87buzbee * For periodic profiling (4 bytes)
422e152baec01433de9c63633ebc6f4adf1cea3a87buzbee *       call  TEMPLATE_PERIODIC_PROFILING
432e152baec01433de9c63633ebc6f4adf1cea3a87buzbee *
442e152baec01433de9c63633ebc6f4adf1cea3a87buzbee * and return the size (in bytes) of the generated code.
452e152baec01433de9c63633ebc6f4adf1cea3a87buzbee */
462e152baec01433de9c63633ebc6f4adf1cea3a87buzbee
472e152baec01433de9c63633ebc6f4adf1cea3a87buzbeestatic int genTraceProfileEntry(CompilationUnit *cUnit)
482e152baec01433de9c63633ebc6f4adf1cea3a87buzbee{
492e152baec01433de9c63633ebc6f4adf1cea3a87buzbee    intptr_t addr = (intptr_t)dvmJitNextTraceCounter();
502e152baec01433de9c63633ebc6f4adf1cea3a87buzbee    assert(__BYTE_ORDER == __LITTLE_ENDIAN);
512e152baec01433de9c63633ebc6f4adf1cea3a87buzbee    newLIR1(cUnit, kArm16BitData, addr & 0xffff);
522e152baec01433de9c63633ebc6f4adf1cea3a87buzbee    newLIR1(cUnit, kArm16BitData, (addr >> 16) & 0xffff);
532e152baec01433de9c63633ebc6f4adf1cea3a87buzbee    cUnit->chainCellOffsetLIR =
542e152baec01433de9c63633ebc6f4adf1cea3a87buzbee        (LIR *) newLIR1(cUnit, kArm16BitData, CHAIN_CELL_OFFSET_TAG);
552e152baec01433de9c63633ebc6f4adf1cea3a87buzbee    cUnit->headerSize = 6;
562e152baec01433de9c63633ebc6f4adf1cea3a87buzbee    if ((gDvmJit.profileMode == kTraceProfilingContinuous) ||
572e152baec01433de9c63633ebc6f4adf1cea3a87buzbee        (gDvmJit.profileMode == kTraceProfilingDisabled)) {
582e152baec01433de9c63633ebc6f4adf1cea3a87buzbee        /* Thumb[2] instruction used directly here to ensure correct size */
592e152baec01433de9c63633ebc6f4adf1cea3a87buzbee        newLIR2(cUnit, kThumb2LdrPcReln12, r0, 8);
602e152baec01433de9c63633ebc6f4adf1cea3a87buzbee        newLIR3(cUnit, kThumbLdrRRI5, r1, r0, 0);
612e152baec01433de9c63633ebc6f4adf1cea3a87buzbee        newLIR2(cUnit, kThumbAddRI8, r1, 1);
622e152baec01433de9c63633ebc6f4adf1cea3a87buzbee        newLIR3(cUnit, kThumbStrRRI5, r1, r0, 0);
632e152baec01433de9c63633ebc6f4adf1cea3a87buzbee        return 10;
642e152baec01433de9c63633ebc6f4adf1cea3a87buzbee    } else {
652e152baec01433de9c63633ebc6f4adf1cea3a87buzbee        int opcode = TEMPLATE_PERIODIC_PROFILING;
662e152baec01433de9c63633ebc6f4adf1cea3a87buzbee        newLIR2(cUnit, kThumbBlx1,
672e152baec01433de9c63633ebc6f4adf1cea3a87buzbee            (int) gDvmJit.codeCache + templateEntryOffsets[opcode],
682e152baec01433de9c63633ebc6f4adf1cea3a87buzbee            (int) gDvmJit.codeCache + templateEntryOffsets[opcode]);
692e152baec01433de9c63633ebc6f4adf1cea3a87buzbee        newLIR2(cUnit, kThumbBlx2,
702e152baec01433de9c63633ebc6f4adf1cea3a87buzbee            (int) gDvmJit.codeCache + templateEntryOffsets[opcode],
712e152baec01433de9c63633ebc6f4adf1cea3a87buzbee            (int) gDvmJit.codeCache + templateEntryOffsets[opcode]);
722e152baec01433de9c63633ebc6f4adf1cea3a87buzbee        return 4;
732e152baec01433de9c63633ebc6f4adf1cea3a87buzbee    }
742e152baec01433de9c63633ebc6f4adf1cea3a87buzbee}
752e152baec01433de9c63633ebc6f4adf1cea3a87buzbee
765d90c20bd7903d7bba966b224e576bf137bf8b4bBen Chengstatic void genNegFloat(CompilationUnit *cUnit, RegLocation rlDest,
775d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                        RegLocation rlSrc)
785d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng{
795d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    RegLocation rlResult;
805d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    rlSrc = loadValue(cUnit, rlSrc, kFPReg);
81c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kFPReg, true);
825d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    newLIR2(cUnit, kThumb2Vnegs, rlResult.lowReg, rlSrc.lowReg);
835d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    storeValue(cUnit, rlDest, rlResult);
845d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng}
855d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng
865d90c20bd7903d7bba966b224e576bf137bf8b4bBen Chengstatic void genNegDouble(CompilationUnit *cUnit, RegLocation rlDest,
87c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee                         RegLocation rlSrc)
885d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng{
895d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    RegLocation rlResult;
905d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    rlSrc = loadValueWide(cUnit, rlSrc, kFPReg);
91c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kFPReg, true);
925d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    newLIR2(cUnit, kThumb2Vnegd, S2D(rlResult.lowReg, rlResult.highReg),
935d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            S2D(rlSrc.lowReg, rlSrc.highReg));
945d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    storeValueWide(cUnit, rlDest, rlResult);
955d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng}
965d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng
975d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng/*
985d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * To avoid possible conflicts, we use a lot of temps here.  Note that
995d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * our usage of Thumb2 instruction forms avoids the problems with register
1005d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * reuse for multiply instructions prior to arm6.
1015d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng */
1025d90c20bd7903d7bba966b224e576bf137bf8b4bBen Chengstatic void genMulLong(CompilationUnit *cUnit, RegLocation rlDest,
1035d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                       RegLocation rlSrc1, RegLocation rlSrc2)
1045d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng{
1055d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    RegLocation rlResult;
106c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    int resLo = dvmCompilerAllocTemp(cUnit);
107c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    int resHi = dvmCompilerAllocTemp(cUnit);
108c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    int tmp1 = dvmCompilerAllocTemp(cUnit);
1095d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng
1105d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    rlSrc1 = loadValueWide(cUnit, rlSrc1, kCoreReg);
1115d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    rlSrc2 = loadValueWide(cUnit, rlSrc2, kCoreReg);
1125d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng
1135d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    newLIR3(cUnit, kThumb2MulRRR, tmp1, rlSrc2.lowReg, rlSrc1.highReg);
1145d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    newLIR4(cUnit, kThumb2Umull, resLo, resHi, rlSrc2.lowReg, rlSrc1.lowReg);
1155d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    newLIR4(cUnit, kThumb2Mla, tmp1, rlSrc1.lowReg, rlSrc2.highReg, tmp1);
1165d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    newLIR4(cUnit, kThumb2AddRRR, resHi, tmp1, resHi, 0);
117c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    dvmCompilerFreeTemp(cUnit, tmp1);
1185d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng
119c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    rlResult = dvmCompilerGetReturnWide(cUnit);  // Just as a template, will patch
1205d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    rlResult.lowReg = resLo;
1215d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    rlResult.highReg = resHi;
1225d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    storeValueWide(cUnit, rlDest, rlResult);
1235d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng}
1245d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng
12580cef8675b2ce54faa31e837b79db9f66d8e652cBill Buzbeestatic void genLong3Addr(CompilationUnit *cUnit, MIR *mir, OpKind firstOp,
1265d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                         OpKind secondOp, RegLocation rlDest,
1275d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                         RegLocation rlSrc1, RegLocation rlSrc2)
1285d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng{
1295d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    RegLocation rlResult;
1305d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    rlSrc1 = loadValueWide(cUnit, rlSrc1, kCoreReg);
1315d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    rlSrc2 = loadValueWide(cUnit, rlSrc2, kCoreReg);
132c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
1335d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    opRegRegReg(cUnit, firstOp, rlResult.lowReg, rlSrc1.lowReg, rlSrc2.lowReg);
1345d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    opRegRegReg(cUnit, secondOp, rlResult.highReg, rlSrc1.highReg,
1355d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                rlSrc2.highReg);
1365d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    storeValueWide(cUnit, rlDest, rlResult);
1375d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng}
1385d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng
1395d90c20bd7903d7bba966b224e576bf137bf8b4bBen Chengvoid dvmCompilerInitializeRegAlloc(CompilationUnit *cUnit)
1405d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng{
1415d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    int numTemps = sizeof(coreTemps)/sizeof(int);
1425d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    int numFPTemps = sizeof(fpTemps)/sizeof(int);
143fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro    RegisterPool *pool = (RegisterPool *)dvmCompilerNew(sizeof(*pool), true);
1445d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    cUnit->regPool = pool;
1455d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    pool->numCoreTemps = numTemps;
146fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro    pool->coreTemps = (RegisterInfo *)
1475d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            dvmCompilerNew(numTemps * sizeof(*cUnit->regPool->coreTemps), true);
1485d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    pool->numFPTemps = numFPTemps;
149fc75f3ed87b55d625b6054e18645da5cbdba31c6Carl Shapiro    pool->FPTemps = (RegisterInfo *)
1505d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            dvmCompilerNew(numFPTemps * sizeof(*cUnit->regPool->FPTemps), true);
151c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    dvmCompilerInitPool(pool->coreTemps, coreTemps, pool->numCoreTemps);
152c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    dvmCompilerInitPool(pool->FPTemps, fpTemps, pool->numFPTemps);
1535d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    pool->nullCheckedRegs =
1545d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        dvmCompilerAllocBitVector(cUnit->numSSARegs, false);
1555d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng}
1565d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng
1575d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng/*
1585d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * Generate a Thumb2 IT instruction, which can nullify up to
1595d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * four subsequent instructions based on a condition and its
1605d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * inverse.  The condition applies to the first instruction, which
1615d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * is executed if the condition is met.  The string "guide" consists
1625d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * of 0 to 3 chars, and applies to the 2nd through 4th instruction.
1635d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * A "T" means the instruction is executed if the condition is
1645d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * met, and an "E" means the instruction is executed if the condition
1655d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * is not met.
1665d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng */
1675d90c20bd7903d7bba966b224e576bf137bf8b4bBen Chengstatic ArmLIR *genIT(CompilationUnit *cUnit, ArmConditionCode code,
1685d5b94c8d14b166af580d5dd5906db4f9527d6caCarl Shapiro                     const char *guide)
1695d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng{
1705d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    int mask;
1715d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    int condBit = code & 1;
1725d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    int altBit = condBit ^ 1;
1735d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    int mask3 = 0;
1745d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    int mask2 = 0;
1755d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    int mask1 = 0;
1765d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng
1775d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    //Note: case fallthroughs intentional
1785d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    switch(strlen(guide)) {
1795d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        case 3:
1805d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            mask1 = (guide[2] == 'T') ? condBit : altBit;
1815d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        case 2:
1825d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            mask2 = (guide[1] == 'T') ? condBit : altBit;
1835d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        case 1:
1845d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            mask3 = (guide[0] == 'T') ? condBit : altBit;
1855d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            break;
1865d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        case 0:
1875d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            break;
1885d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        default:
189c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block            ALOGE("Jit: bad case in genIT");
190fc519dc8f4444f6d93806ec15ce7445b322070fdBill Buzbee            dvmCompilerAbort(cUnit);
1915d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    }
1925d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    mask = (mask3 << 3) | (mask2 << 2) | (mask1 << 1) |
1935d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng           (1 << (3 - strlen(guide)));
1945d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    return newLIR2(cUnit, kThumb2It, code, mask);
1955d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng}
1965d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng
1975d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng/* Export the Dalvik PC assicated with an instruction to the StackSave area */
1985d90c20bd7903d7bba966b224e576bf137bf8b4bBen Chengstatic ArmLIR *genExportPC(CompilationUnit *cUnit, MIR *mir)
1995d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng{
2005d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    ArmLIR *res;
2015d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    int offset = offsetof(StackSaveArea, xtra.currentPc);
202c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    int rDPC = dvmCompilerAllocTemp(cUnit);
2035d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    res = loadConstant(cUnit, rDPC, (int) (cUnit->method->insns + mir->offset));
20420d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng    newLIR3(cUnit, kThumb2StrRRI8Predec, rDPC, r5FP,
2055d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            sizeof(StackSaveArea) - offset);
206c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    dvmCompilerFreeTemp(cUnit, rDPC);
2075d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    return res;
2085d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng}
2095d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng
2105d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng/*
2115d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * Handle simple case (thin lock) inline.  If it's complicated, bail
2125d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * out to the heavyweight lock/unlock routines.  We'll use dedicated
2135d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * registers here in order to be in the right position in case we
2145d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * to bail to dvm[Lock/Unlock]Object(self, object)
2155d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng *
2165d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * r0 -> self pointer [arg0 for dvm[Lock/Unlock]Object
2175d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * r1 -> object [arg1 for dvm[Lock/Unlock]Object
21815812f132f22da443c24609e37298f130acfcfa4Carl Shapiro * r2 -> intial contents of object->lock, later result of strex
2195d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * r3 -> self->threadId
2205d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * r7 -> temp to hold new lock value [unlock only]
2215d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * r4 -> allow to be used by utilities as general temp
2225d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng *
2235d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * The result of the strex is 0 if we acquire the lock.
224d0937ef76b41a57d25c084e76aed1bb91c6dfde7Bill Buzbee *
225d0937ef76b41a57d25c084e76aed1bb91c6dfde7Bill Buzbee * See comments in Sync.c for the layout of the lock word.
226d0937ef76b41a57d25c084e76aed1bb91c6dfde7Bill Buzbee * Of particular interest to this code is the test for the
227d0937ef76b41a57d25c084e76aed1bb91c6dfde7Bill Buzbee * simple case - which we handle inline.  For monitor enter, the
228d0937ef76b41a57d25c084e76aed1bb91c6dfde7Bill Buzbee * simple case is thin lock, held by no-one.  For monitor exit,
229d0937ef76b41a57d25c084e76aed1bb91c6dfde7Bill Buzbee * the simple case is thin lock, held by the unlocking thread with
230d0937ef76b41a57d25c084e76aed1bb91c6dfde7Bill Buzbee * a recurse count of 0.
231d0937ef76b41a57d25c084e76aed1bb91c6dfde7Bill Buzbee *
232d0937ef76b41a57d25c084e76aed1bb91c6dfde7Bill Buzbee * A minor complication is that there is a field in the lock word
233d0937ef76b41a57d25c084e76aed1bb91c6dfde7Bill Buzbee * unrelated to locking: the hash state.  This field must be ignored, but
234d0937ef76b41a57d25c084e76aed1bb91c6dfde7Bill Buzbee * preserved.
235d0937ef76b41a57d25c084e76aed1bb91c6dfde7Bill Buzbee *
2365d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng */
2375d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbeestatic void genMonitorEnter(CompilationUnit *cUnit, MIR *mir)
2385d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng{
239c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
2405d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    ArmLIR *target;
2415d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee    ArmLIR *hopTarget;
2425d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    ArmLIR *branch;
2435d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee    ArmLIR *hopBranch;
2445d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng
245d0937ef76b41a57d25c084e76aed1bb91c6dfde7Bill Buzbee    assert(LW_SHAPE_THIN == 0);
2465d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    loadValueDirectFixed(cUnit, rlSrc, r1);  // Get obj
247c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    dvmCompilerLockAllTemps(cUnit);  // Prepare for explicit register usage
248c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    dvmCompilerFreeTemp(cUnit, r4PC);  // Free up r4 for general use
2495d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    genNullCheck(cUnit, rlSrc.sRegLow, r1, mir->offset, NULL);
25020d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng    loadWordDisp(cUnit, r6SELF, offsetof(Thread, threadId), r3); // Get threadId
2515d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    newLIR3(cUnit, kThumb2Ldrex, r2, r1,
25215812f132f22da443c24609e37298f130acfcfa4Carl Shapiro            offsetof(Object, lock) >> 2); // Get object->lock
253d0937ef76b41a57d25c084e76aed1bb91c6dfde7Bill Buzbee    opRegImm(cUnit, kOpLsl, r3, LW_LOCK_OWNER_SHIFT); // Align owner
25415812f132f22da443c24609e37298f130acfcfa4Carl Shapiro    // Is lock unheld on lock or held by us (==threadId) on unlock?
2555d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee    newLIR4(cUnit, kThumb2Bfi, r3, r2, 0, LW_LOCK_OWNER_SHIFT - 1);
2565d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee    newLIR3(cUnit, kThumb2Bfc, r2, LW_HASH_STATE_SHIFT,
2575d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee            LW_LOCK_OWNER_SHIFT - 1);
2585d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee    hopBranch = newLIR2(cUnit, kThumb2Cbnz, r2, 0);
2595d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee    newLIR4(cUnit, kThumb2Strex, r2, r3, r1, offsetof(Object, lock) >> 2);
2602ce33c938286c7694238b417be65a9918f421b3dbuzbee    dvmCompilerGenMemBarrier(cUnit, kSY);
2615d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    branch = newLIR2(cUnit, kThumb2Cbz, r2, 0);
2625d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng
2635d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee    hopTarget = newLIR0(cUnit, kArmPseudoTargetLabel);
2645d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee    hopTarget->defMask = ENCODE_ALL;
2655d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee    hopBranch->generic.target = (LIR *)hopTarget;
2665d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee
267c1d9ed490a7bd6caab51df41f3c9e590fcecb727Bill Buzbee    // Export PC (part 1)
268c1d9ed490a7bd6caab51df41f3c9e590fcecb727Bill Buzbee    loadConstant(cUnit, r3, (int) (cUnit->method->insns + mir->offset));
269c1d9ed490a7bd6caab51df41f3c9e590fcecb727Bill Buzbee
2705d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee    /* Get dPC of next insn */
2715d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee    loadConstant(cUnit, r4PC, (int)(cUnit->method->insns + mir->offset +
272e485276c6ba778cafa373b3b5c867f84e91b0bfdDan Bornstein                 dexGetWidthFromOpcode(OP_MONITOR_ENTER)));
2735d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee    // Export PC (part 2)
27420d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng    newLIR3(cUnit, kThumb2StrRRI8Predec, r3, r5FP,
2755d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee            sizeof(StackSaveArea) -
2765d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee            offsetof(StackSaveArea, xtra.currentPc));
2775d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee    /* Call template, and don't return */
27820d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng    genRegCopy(cUnit, r0, r6SELF);
2795d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee    genDispatchToHandler(cUnit, TEMPLATE_MONITOR_ENTER);
2805d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee    // Resume here
2815d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee    target = newLIR0(cUnit, kArmPseudoTargetLabel);
2825d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee    target->defMask = ENCODE_ALL;
2835d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee    branch->generic.target = (LIR *)target;
2845d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee}
2855d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee
2865d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee/*
2875d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee * For monitor unlock, we don't have to use ldrex/strex.  Once
2885d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee * we've determined that the lock is thin and that we own it with
2895d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee * a zero recursion count, it's safe to punch it back to the
2905d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee * initial, unlock thin state with a store word.
2915d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee */
2925d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbeestatic void genMonitorExit(CompilationUnit *cUnit, MIR *mir)
2935d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee{
2945d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee    RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
2955d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee    ArmLIR *target;
2965d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee    ArmLIR *branch;
2975d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee    ArmLIR *hopTarget;
2985d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee    ArmLIR *hopBranch;
2995d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee
3005d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee    assert(LW_SHAPE_THIN == 0);
3015d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee    loadValueDirectFixed(cUnit, rlSrc, r1);  // Get obj
3025d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee    dvmCompilerLockAllTemps(cUnit);  // Prepare for explicit register usage
3035d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee    dvmCompilerFreeTemp(cUnit, r4PC);  // Free up r4 for general use
3045d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee    genNullCheck(cUnit, rlSrc.sRegLow, r1, mir->offset, NULL);
3055d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee    loadWordDisp(cUnit, r1, offsetof(Object, lock), r2); // Get object->lock
30620d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng    loadWordDisp(cUnit, r6SELF, offsetof(Thread, threadId), r3); // Get threadId
3075d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee    // Is lock unheld on lock or held by us (==threadId) on unlock?
3085d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee    opRegRegImm(cUnit, kOpAnd, r7, r2,
3095d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee                (LW_HASH_STATE_MASK << LW_HASH_STATE_SHIFT));
3105d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee    opRegImm(cUnit, kOpLsl, r3, LW_LOCK_OWNER_SHIFT); // Align owner
3115d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee    newLIR3(cUnit, kThumb2Bfc, r2, LW_HASH_STATE_SHIFT,
3125d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee            LW_LOCK_OWNER_SHIFT - 1);
3135d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee    opRegReg(cUnit, kOpSub, r2, r3);
3145d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee    hopBranch = opCondBranch(cUnit, kArmCondNe);
3152ce33c938286c7694238b417be65a9918f421b3dbuzbee    dvmCompilerGenMemBarrier(cUnit, kSY);
3165d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee    storeWordDisp(cUnit, r1, offsetof(Object, lock), r7);
3175d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee    branch = opNone(cUnit, kOpUncondBr);
3185d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee
3195d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee    hopTarget = newLIR0(cUnit, kArmPseudoTargetLabel);
3205d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee    hopTarget->defMask = ENCODE_ALL;
3215d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee    hopBranch->generic.target = (LIR *)hopTarget;
3225d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee
3235d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee    // Export PC (part 1)
3245d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee    loadConstant(cUnit, r3, (int) (cUnit->method->insns + mir->offset));
3255d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee
326bd1326d0e6b82a24ee80d50921e62152ea919151Ben Cheng    LOAD_FUNC_ADDR(cUnit, r7, (int)dvmUnlockObject);
32720d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng    genRegCopy(cUnit, r0, r6SELF);
3285d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee    // Export PC (part 2)
32920d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng    newLIR3(cUnit, kThumb2StrRRI8Predec, r3, r5FP,
3305d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee            sizeof(StackSaveArea) -
3315d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee            offsetof(StackSaveArea, xtra.currentPc));
3325d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee    opReg(cUnit, kOpBlx, r7);
3338f8109ade5c32c8c94fa6b7c058045733c8c5ad1buzbee    /* Did we throw? */
3348f8109ade5c32c8c94fa6b7c058045733c8c5ad1buzbee    ArmLIR *branchOver = genCmpImmBranch(cUnit, kArmCondNe, r0, 0);
3355d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee    loadConstant(cUnit, r0,
3365d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee                 (int) (cUnit->method->insns + mir->offset +
337e485276c6ba778cafa373b3b5c867f84e91b0bfdDan Bornstein                 dexGetWidthFromOpcode(OP_MONITOR_EXIT)));
3385d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee    genDispatchToHandler(cUnit, TEMPLATE_THROW_EXCEPTION_COMMON);
3395d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng
3405d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    // Resume here
3415d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    target = newLIR0(cUnit, kArmPseudoTargetLabel);
3425d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    target->defMask = ENCODE_ALL;
3435d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    branch->generic.target = (LIR *)target;
3445d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee    branchOver->generic.target = (LIR *) target;
3455d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee}
3465d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee
3475d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbeestatic void genMonitor(CompilationUnit *cUnit, MIR *mir)
3485d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee{
3499a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein    if (mir->dalvikInsn.opcode == OP_MONITOR_ENTER)
3505d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee        genMonitorEnter(cUnit, mir);
3515d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee    else
3525d4bac4cf4474d789258e1a0d7d8aec80ea27ec5Bill Buzbee        genMonitorExit(cUnit, mir);
3535d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng}
3545d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng
3555d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng/*
3565d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * 64-bit 3way compare function.
3575d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng *     mov   r7, #-1
3585d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng *     cmp   op1hi, op2hi
3595d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng *     blt   done
3605d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng *     bgt   flip
3615d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng *     sub   r7, op1lo, op2lo (treat as unsigned)
3625d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng *     beq   done
3635d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng *     ite   hi
3645d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng *     mov(hi)   r7, #-1
3655d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng *     mov(!hi)  r7, #1
3665d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * flip:
3675d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng *     neg   r7
3685d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * done:
3695d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng */
3705d90c20bd7903d7bba966b224e576bf137bf8b4bBen Chengstatic void genCmpLong(CompilationUnit *cUnit, MIR *mir,
3715d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                       RegLocation rlDest, RegLocation rlSrc1,
3725d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                       RegLocation rlSrc2)
3735d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng{
3745d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    RegLocation rlTemp = LOC_C_RETURN; // Just using as template, will change
3755d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    ArmLIR *target1;
3765d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    ArmLIR *target2;
3775d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    rlSrc1 = loadValueWide(cUnit, rlSrc1, kCoreReg);
3785d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    rlSrc2 = loadValueWide(cUnit, rlSrc2, kCoreReg);
379c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    rlTemp.lowReg = dvmCompilerAllocTemp(cUnit);
3805d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    loadConstant(cUnit, rlTemp.lowReg, -1);
3815d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    opRegReg(cUnit, kOpCmp, rlSrc1.highReg, rlSrc2.highReg);
3825d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    ArmLIR *branch1 = opCondBranch(cUnit, kArmCondLt);
3835d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    ArmLIR *branch2 = opCondBranch(cUnit, kArmCondGt);
3845d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    opRegRegReg(cUnit, kOpSub, rlTemp.lowReg, rlSrc1.lowReg, rlSrc2.lowReg);
3855d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    ArmLIR *branch3 = opCondBranch(cUnit, kArmCondEq);
3865d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng
3875d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    genIT(cUnit, kArmCondHi, "E");
3885d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    newLIR2(cUnit, kThumb2MovImmShift, rlTemp.lowReg, modifiedImmediate(-1));
3895d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    loadConstant(cUnit, rlTemp.lowReg, 1);
3905d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    genBarrier(cUnit);
3915d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng
3925d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    target2 = newLIR0(cUnit, kArmPseudoTargetLabel);
3935d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    target2->defMask = -1;
3945d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    opRegReg(cUnit, kOpNeg, rlTemp.lowReg, rlTemp.lowReg);
3955d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng
3965d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    target1 = newLIR0(cUnit, kArmPseudoTargetLabel);
3975d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    target1->defMask = -1;
3985d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng
3995d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    storeValue(cUnit, rlDest, rlTemp);
4005d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng
4015d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    branch1->generic.target = (LIR *)target1;
4025d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    branch2->generic.target = (LIR *)target2;
4035d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    branch3->generic.target = branch1->generic.target;
4045d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng}
4055d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng
4065d90c20bd7903d7bba966b224e576bf137bf8b4bBen Chengstatic bool genInlinedAbsFloat(CompilationUnit *cUnit, MIR *mir)
4075d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng{
408c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
4095d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    RegLocation rlDest = inlinedTarget(cUnit, mir, true);
4105d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    rlSrc = loadValue(cUnit, rlSrc, kFPReg);
411c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    RegLocation rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kFPReg, true);
4125d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    newLIR2(cUnit, kThumb2Vabss, rlResult.lowReg, rlSrc.lowReg);
4135d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    storeValue(cUnit, rlDest, rlResult);
4147e914f110323165e7f683eece444ef83a499596dElliott Hughes    return false;
4155d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng}
4165d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng
4175d90c20bd7903d7bba966b224e576bf137bf8b4bBen Chengstatic bool genInlinedAbsDouble(CompilationUnit *cUnit, MIR *mir)
4185d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng{
419c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    RegLocation rlSrc = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
4205d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    RegLocation rlDest = inlinedTargetWide(cUnit, mir, true);
4215d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    rlSrc = loadValueWide(cUnit, rlSrc, kFPReg);
422c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    RegLocation rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kFPReg, true);
4235d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    newLIR2(cUnit, kThumb2Vabsd, S2D(rlResult.lowReg, rlResult.highReg),
4245d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            S2D(rlSrc.lowReg, rlSrc.highReg));
4255d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    storeValueWide(cUnit, rlDest, rlResult);
4267e914f110323165e7f683eece444ef83a499596dElliott Hughes    return false;
4275d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng}
4285d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng
4295d90c20bd7903d7bba966b224e576bf137bf8b4bBen Chengstatic bool genInlinedMinMaxInt(CompilationUnit *cUnit, MIR *mir, bool isMin)
4305d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng{
431c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    RegLocation rlSrc1 = dvmCompilerGetSrc(cUnit, mir, 0);
432c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    RegLocation rlSrc2 = dvmCompilerGetSrc(cUnit, mir, 1);
4335d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    rlSrc1 = loadValue(cUnit, rlSrc1, kCoreReg);
4345d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    rlSrc2 = loadValue(cUnit, rlSrc2, kCoreReg);
4355d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    RegLocation rlDest = inlinedTarget(cUnit, mir, false);
436c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    RegLocation rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
4375d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    opRegReg(cUnit, kOpCmp, rlSrc1.lowReg, rlSrc2.lowReg);
4385d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    genIT(cUnit, (isMin) ? kArmCondGt : kArmCondLt, "E");
4395d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    opRegReg(cUnit, kOpMov, rlResult.lowReg, rlSrc2.lowReg);
4405d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    opRegReg(cUnit, kOpMov, rlResult.lowReg, rlSrc1.lowReg);
4415d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    genBarrier(cUnit);
4425d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    storeValue(cUnit, rlDest, rlResult);
4435d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    return false;
4445d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng}
4455d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng
446b4c05977c28c38d2f81b48d0cb15559dc3d05564Elliott Hughesstatic void genMultiplyByTwoBitMultiplier(CompilationUnit *cUnit,
447b4c05977c28c38d2f81b48d0cb15559dc3d05564Elliott Hughes        RegLocation rlSrc, RegLocation rlResult, int lit,
448b4c05977c28c38d2f81b48d0cb15559dc3d05564Elliott Hughes        int firstBit, int secondBit)
449b4c05977c28c38d2f81b48d0cb15559dc3d05564Elliott Hughes{
450b4c05977c28c38d2f81b48d0cb15559dc3d05564Elliott Hughes    opRegRegRegShift(cUnit, kOpAdd, rlResult.lowReg, rlSrc.lowReg, rlSrc.lowReg,
451b4c05977c28c38d2f81b48d0cb15559dc3d05564Elliott Hughes                     encodeShift(kArmLsl, secondBit - firstBit));
452b4c05977c28c38d2f81b48d0cb15559dc3d05564Elliott Hughes    if (firstBit != 0) {
453b4c05977c28c38d2f81b48d0cb15559dc3d05564Elliott Hughes        opRegRegImm(cUnit, kOpLsl, rlResult.lowReg, rlResult.lowReg, firstBit);
454b4c05977c28c38d2f81b48d0cb15559dc3d05564Elliott Hughes    }
455b4c05977c28c38d2f81b48d0cb15559dc3d05564Elliott Hughes}
45620111d635e9210bdd105219eceb263607ec4d5c5Anders O Nilsson
45720111d635e9210bdd105219eceb263607ec4d5c5Anders O Nilssonstatic void genMultiplyByShiftAndReverseSubtract(CompilationUnit *cUnit,
45820111d635e9210bdd105219eceb263607ec4d5c5Anders O Nilsson        RegLocation rlSrc, RegLocation rlResult, int lit)
45920111d635e9210bdd105219eceb263607ec4d5c5Anders O Nilsson{
46020111d635e9210bdd105219eceb263607ec4d5c5Anders O Nilsson    newLIR4(cUnit, kThumb2RsbRRR, rlResult.lowReg, rlSrc.lowReg, rlSrc.lowReg,
46120111d635e9210bdd105219eceb263607ec4d5c5Anders O Nilsson            encodeShift(kArmLsl, lit));
46220111d635e9210bdd105219eceb263607ec4d5c5Anders O Nilsson}
463