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/*
185d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * This file contains codegen for the Thumb 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
255d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng/*
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 (12 bytes):
362e152baec01433de9c63633ebc6f4adf1cea3a87buzbee *
372e152baec01433de9c63633ebc6f4adf1cea3a87buzbee *       mov   r0, pc       @ move adr of "mov r0,pc" + 4 to r0
382e152baec01433de9c63633ebc6f4adf1cea3a87buzbee *       sub   r0, #10      @ back up to addr prof count pointer
392e152baec01433de9c63633ebc6f4adf1cea3a87buzbee *       ldr   r0, [r0]     @ get address of counter
402e152baec01433de9c63633ebc6f4adf1cea3a87buzbee *       ldr   r1, [r0]
412e152baec01433de9c63633ebc6f4adf1cea3a87buzbee *       add   r1, #1
422e152baec01433de9c63633ebc6f4adf1cea3a87buzbee *       str   r1, [r0]
432e152baec01433de9c63633ebc6f4adf1cea3a87buzbee *
442e152baec01433de9c63633ebc6f4adf1cea3a87buzbee * For periodic profiling (4 bytes):
452e152baec01433de9c63633ebc6f4adf1cea3a87buzbee *       call  TEMPLATE_PERIODIC_PROFILING
462e152baec01433de9c63633ebc6f4adf1cea3a87buzbee *
472e152baec01433de9c63633ebc6f4adf1cea3a87buzbee * and return the size (in bytes) of the generated code.
482e152baec01433de9c63633ebc6f4adf1cea3a87buzbee */
492e152baec01433de9c63633ebc6f4adf1cea3a87buzbee
502e152baec01433de9c63633ebc6f4adf1cea3a87buzbeestatic int genTraceProfileEntry(CompilationUnit *cUnit)
512e152baec01433de9c63633ebc6f4adf1cea3a87buzbee{
522e152baec01433de9c63633ebc6f4adf1cea3a87buzbee    intptr_t addr = (intptr_t)dvmJitNextTraceCounter();
532e152baec01433de9c63633ebc6f4adf1cea3a87buzbee    assert(__BYTE_ORDER == __LITTLE_ENDIAN);
542e152baec01433de9c63633ebc6f4adf1cea3a87buzbee    newLIR1(cUnit, kArm16BitData, addr & 0xffff);
552e152baec01433de9c63633ebc6f4adf1cea3a87buzbee    newLIR1(cUnit, kArm16BitData, (addr >> 16) & 0xffff);
562e152baec01433de9c63633ebc6f4adf1cea3a87buzbee    cUnit->chainCellOffsetLIR =
572e152baec01433de9c63633ebc6f4adf1cea3a87buzbee        (LIR *) newLIR1(cUnit, kArm16BitData, CHAIN_CELL_OFFSET_TAG);
582e152baec01433de9c63633ebc6f4adf1cea3a87buzbee    cUnit->headerSize = 6;
592e152baec01433de9c63633ebc6f4adf1cea3a87buzbee    if ((gDvmJit.profileMode == kTraceProfilingContinuous) ||
602e152baec01433de9c63633ebc6f4adf1cea3a87buzbee        (gDvmJit.profileMode == kTraceProfilingDisabled)) {
612e152baec01433de9c63633ebc6f4adf1cea3a87buzbee        /* Thumb instruction used directly here to ensure correct size */
6220d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng        newLIR2(cUnit, kThumbMovRR_H2L, r0, r15pc);
632e152baec01433de9c63633ebc6f4adf1cea3a87buzbee        newLIR2(cUnit, kThumbSubRI8, r0, 10);
642e152baec01433de9c63633ebc6f4adf1cea3a87buzbee        newLIR3(cUnit, kThumbLdrRRI5, r0, r0, 0);
652e152baec01433de9c63633ebc6f4adf1cea3a87buzbee        newLIR3(cUnit, kThumbLdrRRI5, r1, r0, 0);
662e152baec01433de9c63633ebc6f4adf1cea3a87buzbee        newLIR2(cUnit, kThumbAddRI8, r1, 1);
672e152baec01433de9c63633ebc6f4adf1cea3a87buzbee        newLIR3(cUnit, kThumbStrRRI5, r1, r0, 0);
682e152baec01433de9c63633ebc6f4adf1cea3a87buzbee        return 12;
692e152baec01433de9c63633ebc6f4adf1cea3a87buzbee    } else {
702e152baec01433de9c63633ebc6f4adf1cea3a87buzbee        int opcode = TEMPLATE_PERIODIC_PROFILING;
712e152baec01433de9c63633ebc6f4adf1cea3a87buzbee        newLIR2(cUnit, kThumbBlx1,
722e152baec01433de9c63633ebc6f4adf1cea3a87buzbee            (int) gDvmJit.codeCache + templateEntryOffsets[opcode],
732e152baec01433de9c63633ebc6f4adf1cea3a87buzbee            (int) gDvmJit.codeCache + templateEntryOffsets[opcode]);
742e152baec01433de9c63633ebc6f4adf1cea3a87buzbee        newLIR2(cUnit, kThumbBlx2,
752e152baec01433de9c63633ebc6f4adf1cea3a87buzbee            (int) gDvmJit.codeCache + templateEntryOffsets[opcode],
762e152baec01433de9c63633ebc6f4adf1cea3a87buzbee            (int) gDvmJit.codeCache + templateEntryOffsets[opcode]);
772e152baec01433de9c63633ebc6f4adf1cea3a87buzbee        return 4;
782e152baec01433de9c63633ebc6f4adf1cea3a87buzbee    }
792e152baec01433de9c63633ebc6f4adf1cea3a87buzbee}
802e152baec01433de9c63633ebc6f4adf1cea3a87buzbee
812e152baec01433de9c63633ebc6f4adf1cea3a87buzbee/*
825d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * Perform a "reg cmp imm" operation and jump to the PCR region if condition
835d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * satisfies.
845d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng */
855d90c20bd7903d7bba966b224e576bf137bf8b4bBen Chengstatic void genNegFloat(CompilationUnit *cUnit, RegLocation rlDest,
865d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                        RegLocation rlSrc)
875d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng{
885d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    RegLocation rlResult;
895d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
90c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
915d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    opRegRegImm(cUnit, kOpAdd, rlResult.lowReg,
925d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                rlSrc.lowReg, 0x80000000);
935d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    storeValue(cUnit, rlDest, rlResult);
945d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng}
955d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng
965d90c20bd7903d7bba966b224e576bf137bf8b4bBen Chengstatic void genNegDouble(CompilationUnit *cUnit, RegLocation rlDest,
97c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee                         RegLocation rlSrc)
985d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng{
995d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    RegLocation rlResult;
1005d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    rlSrc = loadValueWide(cUnit, rlSrc, kCoreReg);
101c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, true);
1025d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    opRegRegImm(cUnit, kOpAdd, rlResult.highReg, rlSrc.highReg,
1035d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                        0x80000000);
1045d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    genRegCopy(cUnit, rlResult.lowReg, rlSrc.lowReg);
1055d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    storeValueWide(cUnit, rlDest, rlResult);
1065d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng}
1075d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng
1085d90c20bd7903d7bba966b224e576bf137bf8b4bBen Chengstatic void genMulLong(CompilationUnit *cUnit, RegLocation rlDest,
1095d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                       RegLocation rlSrc1, RegLocation rlSrc2)
1105d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng{
1115d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    RegLocation rlResult;
1125d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    loadValueDirectWideFixed(cUnit, rlSrc1, r0, r1);
1135d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    loadValueDirectWideFixed(cUnit, rlSrc2, r2, r3);
1145d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    genDispatchToHandler(cUnit, TEMPLATE_MUL_LONG);
115c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    rlResult = dvmCompilerGetReturnWide(cUnit);
1165d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    storeValueWide(cUnit, rlDest, rlResult);
1175d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng}
1185d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng
119434bae646046871c334b95bd9123a78da66c27c3Bill Buzbeestatic bool partialOverlap(int sreg1, int sreg2)
12080cef8675b2ce54faa31e837b79db9f66d8e652cBill Buzbee{
12180cef8675b2ce54faa31e837b79db9f66d8e652cBill Buzbee    return abs(sreg1 - sreg2) == 1;
12280cef8675b2ce54faa31e837b79db9f66d8e652cBill Buzbee}
12380cef8675b2ce54faa31e837b79db9f66d8e652cBill Buzbee
12480cef8675b2ce54faa31e837b79db9f66d8e652cBill Buzbeestatic void genLong3Addr(CompilationUnit *cUnit, MIR *mir, OpKind firstOp,
1255d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                         OpKind secondOp, RegLocation rlDest,
1265d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                         RegLocation rlSrc1, RegLocation rlSrc2)
1275d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng{
1285d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    RegLocation rlResult;
12980cef8675b2ce54faa31e837b79db9f66d8e652cBill Buzbee    if (partialOverlap(rlSrc1.sRegLow,rlSrc2.sRegLow) ||
13080cef8675b2ce54faa31e837b79db9f66d8e652cBill Buzbee        partialOverlap(rlSrc1.sRegLow,rlDest.sRegLow) ||
13180cef8675b2ce54faa31e837b79db9f66d8e652cBill Buzbee        partialOverlap(rlSrc2.sRegLow,rlDest.sRegLow)) {
13280cef8675b2ce54faa31e837b79db9f66d8e652cBill Buzbee        // Rare case - not enough registers to properly handle
13380cef8675b2ce54faa31e837b79db9f66d8e652cBill Buzbee        genInterpSingleStep(cUnit, mir);
13480cef8675b2ce54faa31e837b79db9f66d8e652cBill Buzbee    } else if (rlDest.sRegLow == rlSrc1.sRegLow) {
1355d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        // Already 2-operand
1365d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        rlResult = loadValueWide(cUnit, rlDest, kCoreReg);
1375d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        rlSrc2 = loadValueWide(cUnit, rlSrc2, kCoreReg);
1385d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        opRegReg(cUnit, firstOp, rlResult.lowReg, rlSrc2.lowReg);
1395d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        opRegReg(cUnit, secondOp, rlResult.highReg, rlSrc2.highReg);
1405d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        storeValueWide(cUnit, rlDest, rlResult);
1415d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    } else if (rlDest.sRegLow == rlSrc2.sRegLow) {
1425d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        // Bad case - must use/clobber Src1 and reassign Dest
1435d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        rlSrc1 = loadValueWide(cUnit, rlSrc1, kCoreReg);
1445d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        rlResult = loadValueWide(cUnit, rlDest, kCoreReg);
1455d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        opRegReg(cUnit, firstOp, rlSrc1.lowReg, rlResult.lowReg);
1465d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        opRegReg(cUnit, secondOp, rlSrc1.highReg, rlResult.highReg);
1475d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        // Old reg assignments are now invalid
148c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        dvmCompilerClobber(cUnit, rlResult.lowReg);
149c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        dvmCompilerClobber(cUnit, rlResult.highReg);
150c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        dvmCompilerClobber(cUnit, rlSrc1.lowReg);
151c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        dvmCompilerClobber(cUnit, rlSrc1.highReg);
1525d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        rlDest.location = kLocDalvikFrame;
1535d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        assert(rlSrc1.location == kLocPhysReg);
1545d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        // Reassign registers - rlDest will now get rlSrc1's old regs
1555d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        storeValueWide(cUnit, rlDest, rlSrc1);
1565d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    } else {
1575d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        // Copy Src1 to Dest
1585d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        rlSrc2 = loadValueWide(cUnit, rlSrc2, kCoreReg);
159c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kCoreReg, false);
1605d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        loadValueDirectWide(cUnit, rlSrc1, rlResult.lowReg,
1615d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                            rlResult.highReg);
1625d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        rlResult.location = kLocPhysReg;
1635d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        opRegReg(cUnit, firstOp, rlResult.lowReg, rlSrc2.lowReg);
1645d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        opRegReg(cUnit, secondOp, rlResult.highReg, rlSrc2.highReg);
1655d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        storeValueWide(cUnit, rlDest, rlResult);
1665d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    }
1675d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng}
1685d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng
1695d90c20bd7903d7bba966b224e576bf137bf8b4bBen Chengvoid dvmCompilerInitializeRegAlloc(CompilationUnit *cUnit)
1705d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng{
1715d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    int numTemps = sizeof(coreTemps)/sizeof(int);
172a118989d1b33e1513f08863e58308e7e3a68a18aBen Cheng    RegisterPool *pool = (RegisterPool *) dvmCompilerNew(sizeof(*pool), true);
1735d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    cUnit->regPool = pool;
1745d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    pool->numCoreTemps = numTemps;
175a118989d1b33e1513f08863e58308e7e3a68a18aBen Cheng    pool->coreTemps = (RegisterInfo *)
1765d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            dvmCompilerNew(numTemps * sizeof(*pool->coreTemps), true);
1775d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    pool->numFPTemps = 0;
1785d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    pool->FPTemps = NULL;
179c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    dvmCompilerInitPool(pool->coreTemps, coreTemps, pool->numCoreTemps);
180c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    dvmCompilerInitPool(pool->FPTemps, NULL, 0);
1815d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    pool->nullCheckedRegs =
1825d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        dvmCompilerAllocBitVector(cUnit->numSSARegs, false);
1835d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng}
1845d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng
1855d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng/* Export the Dalvik PC assicated with an instruction to the StackSave area */
1865d90c20bd7903d7bba966b224e576bf137bf8b4bBen Chengstatic ArmLIR *genExportPC(CompilationUnit *cUnit, MIR *mir)
1875d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng{
1885d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    ArmLIR *res;
189c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    int rDPC = dvmCompilerAllocTemp(cUnit);
190c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    int rAddr = dvmCompilerAllocTemp(cUnit);
1915d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    int offset = offsetof(StackSaveArea, xtra.currentPc);
1925d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    res = loadConstant(cUnit, rDPC, (int) (cUnit->method->insns + mir->offset));
19320d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng    newLIR2(cUnit, kThumbMovRR, rAddr, r5FP);
1945d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    newLIR2(cUnit, kThumbSubRI8, rAddr, sizeof(StackSaveArea) - offset);
1955d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    storeWordDisp( cUnit, rAddr, 0, rDPC);
1965d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    return res;
1975d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng}
1985d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng
1995d90c20bd7903d7bba966b224e576bf137bf8b4bBen Chengstatic void genMonitor(CompilationUnit *cUnit, MIR *mir)
2005d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng{
2015d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    genMonitorPortable(cUnit, mir);
2025d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng}
2035d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng
2045d90c20bd7903d7bba966b224e576bf137bf8b4bBen Chengstatic void genCmpLong(CompilationUnit *cUnit, MIR *mir, RegLocation rlDest,
2055d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                       RegLocation rlSrc1, RegLocation rlSrc2)
2065d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng{
2075d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    RegLocation rlResult;
2085d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    loadValueDirectWideFixed(cUnit, rlSrc1, r0, r1);
2095d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    loadValueDirectWideFixed(cUnit, rlSrc2, r2, r3);
2105d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    genDispatchToHandler(cUnit, TEMPLATE_CMP_LONG);
211c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    rlResult = dvmCompilerGetReturn(cUnit);
2125d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    storeValue(cUnit, rlDest, rlResult);
2135d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng}
2145d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng
2155d90c20bd7903d7bba966b224e576bf137bf8b4bBen Chengstatic bool genInlinedAbsFloat(CompilationUnit *cUnit, MIR *mir)
2165d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng{
217cf4a20cf0cbc53f03a5b16c7152bbb29907f7108buzbee    int offset = offsetof(Thread, interpSave.retval);
218c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    RegLocation rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
2195d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    int reg0 = loadValue(cUnit, rlSrc, kCoreReg).lowReg;
220c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    int signMask = dvmCompilerAllocTemp(cUnit);
2215d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    loadConstant(cUnit, signMask, 0x7fffffff);
2225d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    newLIR2(cUnit, kThumbAndRR, reg0, signMask);
223c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    dvmCompilerFreeTemp(cUnit, signMask);
22420d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng    storeWordDisp(cUnit, r6SELF, offset, reg0);
2251f74863d3e0f19930818398f375ebf1cf2d78969Bill Buzbee    //TUNING: rewrite this to not clobber
226c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    dvmCompilerClobber(cUnit, reg0);
2277e914f110323165e7f683eece444ef83a499596dElliott Hughes    return false;
2285d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng}
2295d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng
2305d90c20bd7903d7bba966b224e576bf137bf8b4bBen Chengstatic bool genInlinedAbsDouble(CompilationUnit *cUnit, MIR *mir)
2315d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng{
232cf4a20cf0cbc53f03a5b16c7152bbb29907f7108buzbee    int offset = offsetof(Thread, interpSave.retval);
233c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    RegLocation rlSrc = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
2345d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    RegLocation regSrc = loadValueWide(cUnit, rlSrc, kCoreReg);
2355d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    int reglo = regSrc.lowReg;
2365d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    int reghi = regSrc.highReg;
237c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    int signMask = dvmCompilerAllocTemp(cUnit);
2385d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    loadConstant(cUnit, signMask, 0x7fffffff);
23920d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng    storeWordDisp(cUnit, r6SELF, offset, reglo);
2405d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    newLIR2(cUnit, kThumbAndRR, reghi, signMask);
241c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    dvmCompilerFreeTemp(cUnit, signMask);
24220d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng    storeWordDisp(cUnit, r6SELF, offset + 4, reghi);
2431f74863d3e0f19930818398f375ebf1cf2d78969Bill Buzbee    //TUNING: rewrite this to not clobber
244c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    dvmCompilerClobber(cUnit, reghi);
2457e914f110323165e7f683eece444ef83a499596dElliott Hughes    return false;
2465d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng}
2475d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng
2485d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng/* No select in thumb, so we need to branch.  Thumb2 will do better */
2495d90c20bd7903d7bba966b224e576bf137bf8b4bBen Chengstatic bool genInlinedMinMaxInt(CompilationUnit *cUnit, MIR *mir, bool isMin)
2505d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng{
251cf4a20cf0cbc53f03a5b16c7152bbb29907f7108buzbee    int offset = offsetof(Thread, interpSave.retval);
252c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    RegLocation rlSrc1 = dvmCompilerGetSrc(cUnit, mir, 0);
253c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    RegLocation rlSrc2 = dvmCompilerGetSrc(cUnit, mir, 1);
2545d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    int reg0 = loadValue(cUnit, rlSrc1, kCoreReg).lowReg;
2555d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    int reg1 = loadValue(cUnit, rlSrc2, kCoreReg).lowReg;
2565d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    newLIR2(cUnit, kThumbCmpRR, reg0, reg1);
2575d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    ArmLIR *branch1 = newLIR2(cUnit, kThumbBCond, 2,
2585d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng           isMin ? kArmCondLt : kArmCondGt);
2595d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    newLIR2(cUnit, kThumbMovRR, reg0, reg1);
2605d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    ArmLIR *target = newLIR0(cUnit, kArmPseudoTargetLabel);
2615d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    target->defMask = ENCODE_ALL;
26220d7e6c67af128d5bf7cc003564a8122c4101c84Ben Cheng    newLIR3(cUnit, kThumbStrRRI5, reg0, r6SELF, offset >> 2);
2635d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    branch1->generic.target = (LIR *)target;
2641f74863d3e0f19930818398f375ebf1cf2d78969Bill Buzbee    //TUNING: rewrite this to not clobber
265c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    dvmCompilerClobber(cUnit,reg0);
2665d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    return false;
2675d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng}
2685d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng
269b4c05977c28c38d2f81b48d0cb15559dc3d05564Elliott Hughesstatic void genMultiplyByTwoBitMultiplier(CompilationUnit *cUnit,
270b4c05977c28c38d2f81b48d0cb15559dc3d05564Elliott Hughes        RegLocation rlSrc, RegLocation rlResult, int lit,
271b4c05977c28c38d2f81b48d0cb15559dc3d05564Elliott Hughes        int firstBit, int secondBit)
272b4c05977c28c38d2f81b48d0cb15559dc3d05564Elliott Hughes{
273b4c05977c28c38d2f81b48d0cb15559dc3d05564Elliott Hughes    // We can't implement "add src, src, src, lsl#shift" on Thumb, so we have
274b4c05977c28c38d2f81b48d0cb15559dc3d05564Elliott Hughes    // to do a regular multiply.
275b4c05977c28c38d2f81b48d0cb15559dc3d05564Elliott Hughes    opRegRegImm(cUnit, kOpMul, rlResult.lowReg, rlSrc.lowReg, lit);
276b4c05977c28c38d2f81b48d0cb15559dc3d05564Elliott Hughes}
27720111d635e9210bdd105219eceb263607ec4d5c5Anders O Nilsson
27820111d635e9210bdd105219eceb263607ec4d5c5Anders O Nilssonstatic void genMultiplyByShiftAndReverseSubtract(CompilationUnit *cUnit,
27920111d635e9210bdd105219eceb263607ec4d5c5Anders O Nilsson        RegLocation rlSrc, RegLocation rlResult, int lit)
28020111d635e9210bdd105219eceb263607ec4d5c5Anders O Nilsson{
28120111d635e9210bdd105219eceb263607ec4d5c5Anders O Nilsson    int tReg = dvmCompilerAllocTemp(cUnit);
28220111d635e9210bdd105219eceb263607ec4d5c5Anders O Nilsson    opRegRegImm(cUnit, kOpLsl, tReg, rlSrc.lowReg, lit);
28320111d635e9210bdd105219eceb263607ec4d5c5Anders O Nilsson    opRegRegReg(cUnit, kOpSub, rlResult.lowReg, tReg, rlSrc.lowReg);
28420111d635e9210bdd105219eceb263607ec4d5c5Anders O Nilsson}
285