codegen_util.cc revision b5d09b2f87202bc132ac3991d4b6d71f4f6d9264
1e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee/*
2e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee * Copyright (C) 2011 The Android Open Source Project
3e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee *
4e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee * Licensed under the Apache License, Version 2.0 (the "License");
5e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee * you may not use this file except in compliance with the License.
6e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee * You may obtain a copy of the License at
7e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee *
8e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee *      http://www.apache.org/licenses/LICENSE-2.0
9e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee *
10e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee * Unless required by applicable law or agreed to in writing, software
11e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee * distributed under the License is distributed on an "AS IS" BASIS,
12e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee * See the License for the specific language governing permissions and
14e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee * limitations under the License.
15e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee */
16e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
17e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbeenamespace art {
18e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
1931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbeevoid setMemRefType(LIR* lir, bool isLoad, int memType)
2031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{
2131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    u8 *maskPtr;
2231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    u8 mask = ENCODE_MEM;;
2331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    DCHECK(EncodingMap[lir->opcode].flags & (IS_LOAD | IS_STORE));
2431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    if (isLoad) {
2531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee        maskPtr = &lir->useMask;
2631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    } else {
2731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee        maskPtr = &lir->defMask;
2831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    }
2931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    /* Clear out the memref flags */
3031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    *maskPtr &= ~mask;
3131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    /* ..and then add back the one we need */
3231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    switch(memType) {
3331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee        case kLiteral:
3431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee            DCHECK(isLoad);
3531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee            *maskPtr |= ENCODE_LITERAL;
3631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee            break;
3731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee        case kDalvikReg:
3831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee            *maskPtr |= ENCODE_DALVIK_REG;
3931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee            break;
4031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee        case kHeapRef:
4131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee            *maskPtr |= ENCODE_HEAP_REF;
4231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee            break;
4331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee        case kMustNotAlias:
4431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee            /* Currently only loads can be marked as kMustNotAlias */
4531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee            DCHECK(!(EncodingMap[lir->opcode].flags & IS_STORE));
4631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee            *maskPtr |= ENCODE_MUST_NOT_ALIAS;
4731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee            break;
4831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee        default:
4931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee            LOG(FATAL) << "Oat: invalid memref kind - " << memType;
5031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    }
5131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
5231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
5331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee/*
54b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers * Mark load/store instructions that access Dalvik registers through the stack.
5531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee */
56b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogersvoid annotateDalvikRegAccess(LIR* lir, int regId, bool isLoad, bool is64bit)
5731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{
5831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    setMemRefType(lir, isLoad, kDalvikReg);
5931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
6031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    /*
61b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers     * Store the Dalvik register id in aliasInfo. Mark the MSB if it is a 64-bit
6231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee     * access.
6331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee     */
6431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    lir->aliasInfo = regId;
65b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    if (is64bit) {
6631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee        lir->aliasInfo |= 0x80000000;
6731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    }
6831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
6931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
7031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee/*
7131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * Decode the register id.
7231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee */
7331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbeeinline u8 getRegMaskCommon(int reg)
7431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{
7531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    u8 seed;
7631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    int shift;
7731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    int regId = reg & 0x1f;
7831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
7931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    /*
8031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee     * Each double register is equal to a pair of single-precision FP registers
8131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee     */
8231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    seed = DOUBLEREG(reg) ? 3 : 1;
8331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    /* FP register starts at bit position 16 */
8431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    shift = FPREG(reg) ? kFPReg0 : 0;
8531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    /* Expand the double register id into single offset */
8631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    shift += regId;
8731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    return (seed << shift);
8831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
8931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
9031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee/*
9131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * Mark the corresponding bit(s).
9231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee */
9331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbeeinline void setupRegMask(u8* mask, int reg)
9431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{
9531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    *mask |= getRegMaskCommon(reg);
9631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
9731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
9831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee/*
9931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * Set up the proper fields in the resource mask
10031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee */
10131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbeevoid setupResourceMasks(LIR* lir)
10231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{
10331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    int opcode = lir->opcode;
10431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    int flags;
10531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
10631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    if (opcode <= 0) {
10731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee        lir->useMask = lir->defMask = 0;
10831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee        return;
10931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    }
11031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
11131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    flags = EncodingMap[lir->opcode].flags;
11231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
11331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    if (flags & NEEDS_FIXUP) {
11431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee        lir->flags.pcRelFixup = true;
11531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    }
11631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
117e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee    /* Get the starting size of the instruction's template */
118e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee    lir->flags.size = oatGetInsnSize(lir);
119e88dfbf138bc204b1ce21911f1c34098ea74af7cbuzbee
12031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    /* Set up the mask for resources that are updated */
12131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    if (flags & (IS_LOAD | IS_STORE)) {
12231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee        /* Default to heap - will catch specialized classes later */
12331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee        setMemRefType(lir, flags & IS_LOAD, kHeapRef);
12431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    }
12531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
12631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    /*
12731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee     * Conservatively assume the branch here will call out a function that in
12831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee     * turn will trash everything.
12931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee     */
13031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    if (flags & IS_BRANCH) {
13131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee        lir->defMask = lir->useMask = ENCODE_ALL;
13231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee        return;
13331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    }
13431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
13531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    if (flags & REG_DEF0) {
13631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee        setupRegMask(&lir->defMask, lir->operands[0]);
13731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    }
13831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
13931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    if (flags & REG_DEF1) {
14031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee        setupRegMask(&lir->defMask, lir->operands[1]);
14131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    }
14231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
14331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    if (flags & REG_DEF_SP) {
14431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee        lir->defMask |= ENCODE_REG_SP;
14531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    }
14631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
147a7678db092ac6bb79f7cad490099a1015fbbc714buzbee#if !defined(TARGET_X86)
14831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    if (flags & REG_DEF_LR) {
14931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee        lir->defMask |= ENCODE_REG_LR;
15031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    }
151a7678db092ac6bb79f7cad490099a1015fbbc714buzbee#endif
15231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
15331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    if (flags & REG_DEF_LIST0) {
15431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee        lir->defMask |= ENCODE_REG_LIST(lir->operands[0]);
15531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    }
15631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
15731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    if (flags & REG_DEF_LIST1) {
15831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee        lir->defMask |= ENCODE_REG_LIST(lir->operands[1]);
15931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    }
16031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
1615de3494e4297c0d480409da3fecee39173f1d4e1buzbee#if defined(TARGET_ARM)
16231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    if (flags & REG_DEF_FPCS_LIST0) {
16331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee        lir->defMask |= ENCODE_REG_FPCS_LIST(lir->operands[0]);
16431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    }
16531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
16631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    if (flags & REG_DEF_FPCS_LIST2) {
16731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee        for (int i = 0; i < lir->operands[2]; i++) {
16831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee            setupRegMask(&lir->defMask, lir->operands[1] + i);
16931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee        }
17031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    }
1715de3494e4297c0d480409da3fecee39173f1d4e1buzbee#endif
17231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
17331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    if (flags & SETS_CCODES) {
17431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee        lir->defMask |= ENCODE_CCODE;
17531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    }
17631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
17731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee#if defined(TARGET_ARM)
17831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    /* Conservatively treat the IT block */
17931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    if (flags & IS_IT) {
18031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee        lir->defMask = ENCODE_ALL;
18131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    }
18231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee#endif
18331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
18431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    if (flags & (REG_USE0 | REG_USE1 | REG_USE2 | REG_USE3)) {
18531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee        int i;
18631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
18731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee        for (i = 0; i < 4; i++) {
18831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee            if (flags & (1 << (kRegUse0 + i))) {
18931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee                setupRegMask(&lir->useMask, lir->operands[i]);
19031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee            }
19131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee        }
19231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    }
19331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
194a7678db092ac6bb79f7cad490099a1015fbbc714buzbee#if defined(TARGET_ARM)
19531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    if (flags & REG_USE_PC) {
19631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee        lir->useMask |= ENCODE_REG_PC;
19731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    }
198a7678db092ac6bb79f7cad490099a1015fbbc714buzbee#endif
19931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
20031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    if (flags & REG_USE_SP) {
20131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee        lir->useMask |= ENCODE_REG_SP;
20231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    }
20331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
20431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    if (flags & REG_USE_LIST0) {
20531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee        lir->useMask |= ENCODE_REG_LIST(lir->operands[0]);
20631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    }
20731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
20831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    if (flags & REG_USE_LIST1) {
20931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee        lir->useMask |= ENCODE_REG_LIST(lir->operands[1]);
21031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    }
21131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
2125de3494e4297c0d480409da3fecee39173f1d4e1buzbee#if defined(TARGET_ARM)
21331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    if (flags & REG_USE_FPCS_LIST0) {
21431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee        lir->useMask |= ENCODE_REG_FPCS_LIST(lir->operands[0]);
21531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    }
21631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
21731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    if (flags & REG_USE_FPCS_LIST2) {
21831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee        for (int i = 0; i < lir->operands[2]; i++) {
21931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee            setupRegMask(&lir->useMask, lir->operands[1] + i);
22031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee        }
22131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    }
2225de3494e4297c0d480409da3fecee39173f1d4e1buzbee#endif
22331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
22431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    if (flags & USES_CCODES) {
22531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee        lir->useMask |= ENCODE_CCODE;
22631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    }
22731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
22831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee#if defined(TARGET_ARM)
22931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    /* Fixup for kThumbPush/lr and kThumbPop/pc */
23031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    if (opcode == kThumbPush || opcode == kThumbPop) {
23131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee        u8 r8Mask = getRegMaskCommon(r8);
23231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee        if ((opcode == kThumbPush) && (lir->useMask & r8Mask)) {
23331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee            lir->useMask &= ~r8Mask;
23431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee            lir->useMask |= ENCODE_REG_LR;
23531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee        } else if ((opcode == kThumbPop) && (lir->defMask & r8Mask)) {
23631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee            lir->defMask &= ~r8Mask;
23731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee            lir->defMask |= ENCODE_REG_PC;
23831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee        }
23931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    }
24031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee#endif
24131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
24231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
24331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee/*
2445de3494e4297c0d480409da3fecee39173f1d4e1buzbee * Debugging macros
2455de3494e4297c0d480409da3fecee39173f1d4e1buzbee */
2465de3494e4297c0d480409da3fecee39173f1d4e1buzbee#define DUMP_RESOURCE_MASK(X)
2475de3494e4297c0d480409da3fecee39173f1d4e1buzbee#define DUMP_SSA_REP(X)
2485de3494e4297c0d480409da3fecee39173f1d4e1buzbee
2495de3494e4297c0d480409da3fecee39173f1d4e1buzbee/* Pretty-print a LIR instruction */
2505de3494e4297c0d480409da3fecee39173f1d4e1buzbeevoid oatDumpLIRInsn(CompilationUnit* cUnit, LIR* arg, unsigned char* baseAddr)
2515de3494e4297c0d480409da3fecee39173f1d4e1buzbee{
2525de3494e4297c0d480409da3fecee39173f1d4e1buzbee    LIR* lir = (LIR*) arg;
2535de3494e4297c0d480409da3fecee39173f1d4e1buzbee    int offset = lir->offset;
2545de3494e4297c0d480409da3fecee39173f1d4e1buzbee    int dest = lir->operands[0];
25586a4bce32e2aaf3d377c0acf865f0630a7c30495buzbee    const bool dumpNop = (cUnit->enableDebug & (1 << kDebugShowNops));
2565de3494e4297c0d480409da3fecee39173f1d4e1buzbee
2575de3494e4297c0d480409da3fecee39173f1d4e1buzbee    /* Handle pseudo-ops individually, and all regular insns as a group */
2585de3494e4297c0d480409da3fecee39173f1d4e1buzbee    switch(lir->opcode) {
2595de3494e4297c0d480409da3fecee39173f1d4e1buzbee        case kPseudoMethodEntry:
2605de3494e4297c0d480409da3fecee39173f1d4e1buzbee            LOG(INFO) << "-------- method entry " <<
2615de3494e4297c0d480409da3fecee39173f1d4e1buzbee                PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
2625de3494e4297c0d480409da3fecee39173f1d4e1buzbee            break;
2635de3494e4297c0d480409da3fecee39173f1d4e1buzbee        case kPseudoMethodExit:
2645de3494e4297c0d480409da3fecee39173f1d4e1buzbee            LOG(INFO) << "-------- Method_Exit";
2655de3494e4297c0d480409da3fecee39173f1d4e1buzbee            break;
2665de3494e4297c0d480409da3fecee39173f1d4e1buzbee        case kPseudoBarrier:
2675de3494e4297c0d480409da3fecee39173f1d4e1buzbee            LOG(INFO) << "-------- BARRIER";
2685de3494e4297c0d480409da3fecee39173f1d4e1buzbee            break;
2695de3494e4297c0d480409da3fecee39173f1d4e1buzbee        case kPseudoExtended:
2705de3494e4297c0d480409da3fecee39173f1d4e1buzbee            LOG(INFO) << "-------- " << (char* ) dest;
2715de3494e4297c0d480409da3fecee39173f1d4e1buzbee            break;
2725de3494e4297c0d480409da3fecee39173f1d4e1buzbee        case kPseudoSSARep:
2735de3494e4297c0d480409da3fecee39173f1d4e1buzbee            DUMP_SSA_REP(LOG(INFO) << "-------- kMirOpPhi: " <<  (char* ) dest);
2745de3494e4297c0d480409da3fecee39173f1d4e1buzbee            break;
2755de3494e4297c0d480409da3fecee39173f1d4e1buzbee        case kPseudoEntryBlock:
2765de3494e4297c0d480409da3fecee39173f1d4e1buzbee            LOG(INFO) << "-------- entry offset: 0x" << std::hex << dest;
2775de3494e4297c0d480409da3fecee39173f1d4e1buzbee            break;
2785de3494e4297c0d480409da3fecee39173f1d4e1buzbee        case kPseudoDalvikByteCodeBoundary:
2795de3494e4297c0d480409da3fecee39173f1d4e1buzbee            LOG(INFO) << "-------- dalvik offset: 0x" << std::hex <<
2805de3494e4297c0d480409da3fecee39173f1d4e1buzbee                 lir->dalvikOffset << " @ " << (char* )lir->operands[0];
2815de3494e4297c0d480409da3fecee39173f1d4e1buzbee            break;
2825de3494e4297c0d480409da3fecee39173f1d4e1buzbee        case kPseudoExitBlock:
2835de3494e4297c0d480409da3fecee39173f1d4e1buzbee            LOG(INFO) << "-------- exit offset: 0x" << std::hex << dest;
2845de3494e4297c0d480409da3fecee39173f1d4e1buzbee            break;
2855de3494e4297c0d480409da3fecee39173f1d4e1buzbee        case kPseudoPseudoAlign4:
2865de3494e4297c0d480409da3fecee39173f1d4e1buzbee            LOG(INFO) << (intptr_t)baseAddr + offset << " (0x" << std::hex <<
2875de3494e4297c0d480409da3fecee39173f1d4e1buzbee                offset << "): .align4";
2885de3494e4297c0d480409da3fecee39173f1d4e1buzbee            break;
2895de3494e4297c0d480409da3fecee39173f1d4e1buzbee        case kPseudoEHBlockLabel:
2905de3494e4297c0d480409da3fecee39173f1d4e1buzbee            LOG(INFO) << "Exception_Handling:";
2915de3494e4297c0d480409da3fecee39173f1d4e1buzbee            break;
2925de3494e4297c0d480409da3fecee39173f1d4e1buzbee        case kPseudoTargetLabel:
2935de3494e4297c0d480409da3fecee39173f1d4e1buzbee        case kPseudoNormalBlockLabel:
2945de3494e4297c0d480409da3fecee39173f1d4e1buzbee            LOG(INFO) << "L" << (intptr_t)lir << ":";
2955de3494e4297c0d480409da3fecee39173f1d4e1buzbee            break;
2965de3494e4297c0d480409da3fecee39173f1d4e1buzbee        case kPseudoThrowTarget:
2975de3494e4297c0d480409da3fecee39173f1d4e1buzbee            LOG(INFO) << "LT" << (intptr_t)lir << ":";
2985de3494e4297c0d480409da3fecee39173f1d4e1buzbee            break;
2995de3494e4297c0d480409da3fecee39173f1d4e1buzbee        case kPseudoSuspendTarget:
3005de3494e4297c0d480409da3fecee39173f1d4e1buzbee            LOG(INFO) << "LS" << (intptr_t)lir << ":";
3015de3494e4297c0d480409da3fecee39173f1d4e1buzbee            break;
3025de3494e4297c0d480409da3fecee39173f1d4e1buzbee        case kPseudoCaseLabel:
3035de3494e4297c0d480409da3fecee39173f1d4e1buzbee            LOG(INFO) << "LC" << (intptr_t)lir << ": Case target 0x" <<
3045de3494e4297c0d480409da3fecee39173f1d4e1buzbee                std::hex << lir->operands[0] << "|" << std::dec <<
3055de3494e4297c0d480409da3fecee39173f1d4e1buzbee                lir->operands[0];
3065de3494e4297c0d480409da3fecee39173f1d4e1buzbee            break;
3075de3494e4297c0d480409da3fecee39173f1d4e1buzbee        default:
3085de3494e4297c0d480409da3fecee39173f1d4e1buzbee            if (lir->flags.isNop && !dumpNop) {
3095de3494e4297c0d480409da3fecee39173f1d4e1buzbee                break;
3105de3494e4297c0d480409da3fecee39173f1d4e1buzbee            } else {
3115de3494e4297c0d480409da3fecee39173f1d4e1buzbee                std::string op_name(buildInsnString(EncodingMap[lir->opcode].name, lir, baseAddr));
3125de3494e4297c0d480409da3fecee39173f1d4e1buzbee                std::string op_operands(buildInsnString(EncodingMap[lir->opcode].fmt, lir, baseAddr));
313be00364d260ea96323a070723af0bd61e3ea703abuzbee                LOG(INFO) << StringPrintf("%05x: %-9s%s%s", (unsigned int)(baseAddr + offset),
3145de3494e4297c0d480409da3fecee39173f1d4e1buzbee                    op_name.c_str(), op_operands.c_str(), lir->flags.isNop ? "(nop)" : "");
3155de3494e4297c0d480409da3fecee39173f1d4e1buzbee            }
3165de3494e4297c0d480409da3fecee39173f1d4e1buzbee            break;
3175de3494e4297c0d480409da3fecee39173f1d4e1buzbee    }
3185de3494e4297c0d480409da3fecee39173f1d4e1buzbee
3195de3494e4297c0d480409da3fecee39173f1d4e1buzbee    if (lir->useMask && (!lir->flags.isNop || dumpNop)) {
3205de3494e4297c0d480409da3fecee39173f1d4e1buzbee        DUMP_RESOURCE_MASK(oatDumpResourceMask((LIR* ) lir,
3215de3494e4297c0d480409da3fecee39173f1d4e1buzbee                                               lir->useMask, "use"));
3225de3494e4297c0d480409da3fecee39173f1d4e1buzbee    }
3235de3494e4297c0d480409da3fecee39173f1d4e1buzbee    if (lir->defMask && (!lir->flags.isNop || dumpNop)) {
3245de3494e4297c0d480409da3fecee39173f1d4e1buzbee        DUMP_RESOURCE_MASK(oatDumpResourceMask((LIR* ) lir,
3255de3494e4297c0d480409da3fecee39173f1d4e1buzbee                                               lir->defMask, "def"));
3265de3494e4297c0d480409da3fecee39173f1d4e1buzbee    }
3275de3494e4297c0d480409da3fecee39173f1d4e1buzbee}
3285de3494e4297c0d480409da3fecee39173f1d4e1buzbee
3295de3494e4297c0d480409da3fecee39173f1d4e1buzbeevoid oatDumpPromotionMap(CompilationUnit *cUnit)
3305de3494e4297c0d480409da3fecee39173f1d4e1buzbee{
3315de3494e4297c0d480409da3fecee39173f1d4e1buzbee    for (int i = 0; i < cUnit->numDalvikRegisters; i++) {
3325de3494e4297c0d480409da3fecee39173f1d4e1buzbee        PromotionMap vRegMap = cUnit->promotionMap[i];
3335de3494e4297c0d480409da3fecee39173f1d4e1buzbee        char buf[100];
3345de3494e4297c0d480409da3fecee39173f1d4e1buzbee        if (vRegMap.fpLocation == kLocPhysReg) {
3355de3494e4297c0d480409da3fecee39173f1d4e1buzbee            snprintf(buf, 100, " : s%d", vRegMap.fpReg & FP_REG_MASK);
3365de3494e4297c0d480409da3fecee39173f1d4e1buzbee        } else {
3375de3494e4297c0d480409da3fecee39173f1d4e1buzbee            buf[0] = 0;
3385de3494e4297c0d480409da3fecee39173f1d4e1buzbee        }
3395de3494e4297c0d480409da3fecee39173f1d4e1buzbee        char buf2[100];
3405de3494e4297c0d480409da3fecee39173f1d4e1buzbee        snprintf(buf2, 100, "V[%02d] -> %s%d%s", i,
3415de3494e4297c0d480409da3fecee39173f1d4e1buzbee                 vRegMap.coreLocation == kLocPhysReg ?
3425de3494e4297c0d480409da3fecee39173f1d4e1buzbee                 "r" : "SP+", vRegMap.coreLocation == kLocPhysReg ?
3435de3494e4297c0d480409da3fecee39173f1d4e1buzbee                 vRegMap.coreReg : oatSRegOffset(cUnit, i), buf);
3445de3494e4297c0d480409da3fecee39173f1d4e1buzbee        LOG(INFO) << buf2;
3455de3494e4297c0d480409da3fecee39173f1d4e1buzbee    }
3465de3494e4297c0d480409da3fecee39173f1d4e1buzbee}
3475de3494e4297c0d480409da3fecee39173f1d4e1buzbee
3485de3494e4297c0d480409da3fecee39173f1d4e1buzbeevoid oatDumpFullPromotionMap(CompilationUnit *cUnit)
3495de3494e4297c0d480409da3fecee39173f1d4e1buzbee{
3505de3494e4297c0d480409da3fecee39173f1d4e1buzbee    for (int i = 0; i < cUnit->numDalvikRegisters; i++) {
3515de3494e4297c0d480409da3fecee39173f1d4e1buzbee        PromotionMap vRegMap = cUnit->promotionMap[i];
3525de3494e4297c0d480409da3fecee39173f1d4e1buzbee        LOG(INFO) << i << " -> " << "CL:" << (int)vRegMap.coreLocation <<
3535de3494e4297c0d480409da3fecee39173f1d4e1buzbee            ", CR:" << (int)vRegMap.coreReg << ", FL:" <<
3545de3494e4297c0d480409da3fecee39173f1d4e1buzbee            (int)vRegMap.fpLocation << ", FR:" << (int)vRegMap.fpReg <<
3555de3494e4297c0d480409da3fecee39173f1d4e1buzbee            ", - " << (int)vRegMap.firstInPair;
3565de3494e4297c0d480409da3fecee39173f1d4e1buzbee    }
3575de3494e4297c0d480409da3fecee39173f1d4e1buzbee}
3585de3494e4297c0d480409da3fecee39173f1d4e1buzbee
3595de3494e4297c0d480409da3fecee39173f1d4e1buzbee/* Dump instructions and constant pool contents */
3605de3494e4297c0d480409da3fecee39173f1d4e1buzbeevoid oatCodegenDump(CompilationUnit* cUnit)
3615de3494e4297c0d480409da3fecee39173f1d4e1buzbee{
3625de3494e4297c0d480409da3fecee39173f1d4e1buzbee    LOG(INFO) << "/*";
3635de3494e4297c0d480409da3fecee39173f1d4e1buzbee    LOG(INFO) << "Dumping LIR insns for "
3645de3494e4297c0d480409da3fecee39173f1d4e1buzbee        << PrettyMethod(cUnit->method_idx, *cUnit->dex_file);
3655de3494e4297c0d480409da3fecee39173f1d4e1buzbee    LIR* lirInsn;
3665de3494e4297c0d480409da3fecee39173f1d4e1buzbee    LIR* thisLIR;
3675de3494e4297c0d480409da3fecee39173f1d4e1buzbee    int insnsSize = cUnit->insnsSize;
3685de3494e4297c0d480409da3fecee39173f1d4e1buzbee
3695de3494e4297c0d480409da3fecee39173f1d4e1buzbee    LOG(INFO) << "Regs (excluding ins) : " << cUnit->numRegs;
3705de3494e4297c0d480409da3fecee39173f1d4e1buzbee    LOG(INFO) << "Ins                  : " << cUnit->numIns;
3715de3494e4297c0d480409da3fecee39173f1d4e1buzbee    LOG(INFO) << "Outs                 : " << cUnit->numOuts;
3725de3494e4297c0d480409da3fecee39173f1d4e1buzbee    LOG(INFO) << "CoreSpills           : " << cUnit->numCoreSpills;
3735de3494e4297c0d480409da3fecee39173f1d4e1buzbee    LOG(INFO) << "FPSpills             : " << cUnit->numFPSpills;
3745de3494e4297c0d480409da3fecee39173f1d4e1buzbee    LOG(INFO) << "Frame size           : " << cUnit->frameSize;
3755de3494e4297c0d480409da3fecee39173f1d4e1buzbee    LOG(INFO) << "code size is " << cUnit->totalSize <<
3765de3494e4297c0d480409da3fecee39173f1d4e1buzbee        " bytes, Dalvik size is " << insnsSize * 2;
3775de3494e4297c0d480409da3fecee39173f1d4e1buzbee    LOG(INFO) << "expansion factor: " <<
3785de3494e4297c0d480409da3fecee39173f1d4e1buzbee         (float)cUnit->totalSize / (float)(insnsSize * 2);
3795de3494e4297c0d480409da3fecee39173f1d4e1buzbee    oatDumpPromotionMap(cUnit);
3805de3494e4297c0d480409da3fecee39173f1d4e1buzbee    for (lirInsn = cUnit->firstLIRInsn; lirInsn; lirInsn = lirInsn->next) {
3815de3494e4297c0d480409da3fecee39173f1d4e1buzbee        oatDumpLIRInsn(cUnit, lirInsn, 0);
3825de3494e4297c0d480409da3fecee39173f1d4e1buzbee    }
3835de3494e4297c0d480409da3fecee39173f1d4e1buzbee    for (lirInsn = cUnit->classPointerList; lirInsn; lirInsn = lirInsn->next) {
3845de3494e4297c0d480409da3fecee39173f1d4e1buzbee        thisLIR = (LIR*) lirInsn;
3855de3494e4297c0d480409da3fecee39173f1d4e1buzbee        LOG(INFO) << StringPrintf("%x (%04x): .class (%s)",
3865de3494e4297c0d480409da3fecee39173f1d4e1buzbee            thisLIR->offset, thisLIR->offset,
3875de3494e4297c0d480409da3fecee39173f1d4e1buzbee            ((CallsiteInfo *) thisLIR->operands[0])->classDescriptor);
3885de3494e4297c0d480409da3fecee39173f1d4e1buzbee    }
3895de3494e4297c0d480409da3fecee39173f1d4e1buzbee    for (lirInsn = cUnit->literalList; lirInsn; lirInsn = lirInsn->next) {
3905de3494e4297c0d480409da3fecee39173f1d4e1buzbee        thisLIR = (LIR*) lirInsn;
3915de3494e4297c0d480409da3fecee39173f1d4e1buzbee        LOG(INFO) << StringPrintf("%x (%04x): .word (%#x)",
3925de3494e4297c0d480409da3fecee39173f1d4e1buzbee            thisLIR->offset, thisLIR->offset, thisLIR->operands[0]);
3935de3494e4297c0d480409da3fecee39173f1d4e1buzbee    }
3945de3494e4297c0d480409da3fecee39173f1d4e1buzbee
3955de3494e4297c0d480409da3fecee39173f1d4e1buzbee    const DexFile::MethodId& method_id =
3965de3494e4297c0d480409da3fecee39173f1d4e1buzbee        cUnit->dex_file->GetMethodId(cUnit->method_idx);
3975de3494e4297c0d480409da3fecee39173f1d4e1buzbee    std::string signature(cUnit->dex_file->GetMethodSignature(method_id));
3985de3494e4297c0d480409da3fecee39173f1d4e1buzbee    std::string name(cUnit->dex_file->GetMethodName(method_id));
3995de3494e4297c0d480409da3fecee39173f1d4e1buzbee    std::string descriptor(cUnit->dex_file->GetMethodDeclaringClassDescriptor(method_id));
4005de3494e4297c0d480409da3fecee39173f1d4e1buzbee
4015de3494e4297c0d480409da3fecee39173f1d4e1buzbee    // Dump mapping table
4025de3494e4297c0d480409da3fecee39173f1d4e1buzbee    if (cUnit->mappingTable.size() > 0) {
4035de3494e4297c0d480409da3fecee39173f1d4e1buzbee        std::string line(StringPrintf("\n    MappingTable %s%s_%s_mappingTable[%zu] = {",
4045de3494e4297c0d480409da3fecee39173f1d4e1buzbee            descriptor.c_str(), name.c_str(), signature.c_str(), cUnit->mappingTable.size()));
4055de3494e4297c0d480409da3fecee39173f1d4e1buzbee        std::replace(line.begin(), line.end(), ';', '_');
4065de3494e4297c0d480409da3fecee39173f1d4e1buzbee        LOG(INFO) << line;
4075de3494e4297c0d480409da3fecee39173f1d4e1buzbee        for (uint32_t i = 0; i < cUnit->mappingTable.size(); i+=2) {
40882488f563e7f72f8c626052893c1792d76ab3fafbuzbee            line = StringPrintf("        {0x%05x, 0x%04x},",
4095de3494e4297c0d480409da3fecee39173f1d4e1buzbee                cUnit->mappingTable[i], cUnit->mappingTable[i+1]);
4105de3494e4297c0d480409da3fecee39173f1d4e1buzbee            LOG(INFO) << line;
4115de3494e4297c0d480409da3fecee39173f1d4e1buzbee        }
4125de3494e4297c0d480409da3fecee39173f1d4e1buzbee        LOG(INFO) <<"    };\n\n";
4135de3494e4297c0d480409da3fecee39173f1d4e1buzbee    }
4145de3494e4297c0d480409da3fecee39173f1d4e1buzbee}
4155de3494e4297c0d480409da3fecee39173f1d4e1buzbee
416a2ebdd74eb2f36e6efa7a482bc11c7b93d97c2c3buzbee
417a2ebdd74eb2f36e6efa7a482bc11c7b93d97c2c3buzbeeLIR* rawLIR(CompilationUnit* cUnit, int dalvikOffset, int opcode, int op0,
418b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers            int op1, int op2, int op3, int op4, LIR* target)
41931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{
42031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    LIR* insn = (LIR* ) oatNew(cUnit, sizeof(LIR), true, kAllocLIR);
421a2ebdd74eb2f36e6efa7a482bc11c7b93d97c2c3buzbee    insn->dalvikOffset = dalvikOffset;
42231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    insn->opcode = opcode;
423a2ebdd74eb2f36e6efa7a482bc11c7b93d97c2c3buzbee    insn->operands[0] = op0;
424a2ebdd74eb2f36e6efa7a482bc11c7b93d97c2c3buzbee    insn->operands[1] = op1;
425a2ebdd74eb2f36e6efa7a482bc11c7b93d97c2c3buzbee    insn->operands[2] = op2;
426a2ebdd74eb2f36e6efa7a482bc11c7b93d97c2c3buzbee    insn->operands[3] = op3;
427b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    insn->operands[4] = op4;
428a2ebdd74eb2f36e6efa7a482bc11c7b93d97c2c3buzbee    insn->target = target;
429a2ebdd74eb2f36e6efa7a482bc11c7b93d97c2c3buzbee    oatSetupResourceMasks(insn);
430c5159d55ca8e9022b748176f9f53676e8e9d4cd2buzbee    if (opcode == kPseudoTargetLabel) {
431c5159d55ca8e9022b748176f9f53676e8e9d4cd2buzbee        // Always make labels scheduling barriers
432c5159d55ca8e9022b748176f9f53676e8e9d4cd2buzbee        insn->defMask = ENCODE_ALL;
433c5159d55ca8e9022b748176f9f53676e8e9d4cd2buzbee    }
434a2ebdd74eb2f36e6efa7a482bc11c7b93d97c2c3buzbee    return insn;
435a2ebdd74eb2f36e6efa7a482bc11c7b93d97c2c3buzbee}
436a2ebdd74eb2f36e6efa7a482bc11c7b93d97c2c3buzbee
437a2ebdd74eb2f36e6efa7a482bc11c7b93d97c2c3buzbee/*
438a2ebdd74eb2f36e6efa7a482bc11c7b93d97c2c3buzbee * The following are building blocks to construct low-level IRs with 0 - 4
439a2ebdd74eb2f36e6efa7a482bc11c7b93d97c2c3buzbee * operands.
440a2ebdd74eb2f36e6efa7a482bc11c7b93d97c2c3buzbee */
441a2ebdd74eb2f36e6efa7a482bc11c7b93d97c2c3buzbeeLIR* newLIR0(CompilationUnit* cUnit, int opcode)
442a2ebdd74eb2f36e6efa7a482bc11c7b93d97c2c3buzbee{
443b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & NO_OPERAND))
444b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers                << EncodingMap[opcode].name << " " << (int)opcode << " "
445b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers                << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
446b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers                << cUnit->currentDalvikOffset;
447a2ebdd74eb2f36e6efa7a482bc11c7b93d97c2c3buzbee    LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode);
44831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    oatAppendLIR(cUnit, (LIR*) insn);
44931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    return insn;
45031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
45131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
4525de3494e4297c0d480409da3fecee39173f1d4e1buzbeeLIR* newLIR1(CompilationUnit* cUnit, int opcode,
45331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee                           int dest)
45431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{
455b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_UNARY_OP))
456b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers                << EncodingMap[opcode].name << " " << (int)opcode << " "
457b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers                << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
458b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers                << cUnit->currentDalvikOffset;
459a2ebdd74eb2f36e6efa7a482bc11c7b93d97c2c3buzbee    LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, dest);
46031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    oatAppendLIR(cUnit, (LIR*) insn);
46131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    return insn;
46231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
46331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
4645de3494e4297c0d480409da3fecee39173f1d4e1buzbeeLIR* newLIR2(CompilationUnit* cUnit, int opcode,
46531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee                           int dest, int src1)
46631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{
467b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_BINARY_OP))
468b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers                << EncodingMap[opcode].name << " " << (int)opcode << " "
469b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers                << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
470b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers                << cUnit->currentDalvikOffset;
471a2ebdd74eb2f36e6efa7a482bc11c7b93d97c2c3buzbee    LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, dest, src1);
47231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    oatAppendLIR(cUnit, (LIR*) insn);
47331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    return insn;
47431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
47531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
4765de3494e4297c0d480409da3fecee39173f1d4e1buzbeeLIR* newLIR3(CompilationUnit* cUnit, int opcode,
47731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee                           int dest, int src1, int src2)
47831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{
479b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_TERTIARY_OP))
480b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers                << EncodingMap[opcode].name << " " << (int)opcode << " "
481b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers                << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
482b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers                << cUnit->currentDalvikOffset;
483a2ebdd74eb2f36e6efa7a482bc11c7b93d97c2c3buzbee    LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, dest, src1,
484a2ebdd74eb2f36e6efa7a482bc11c7b93d97c2c3buzbee                       src2);
48531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    oatAppendLIR(cUnit, (LIR*) insn);
48631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    return insn;
48731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
48831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
4895de3494e4297c0d480409da3fecee39173f1d4e1buzbeeLIR* newLIR4(CompilationUnit* cUnit, int opcode,
490b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers            int dest, int src1, int src2, int info)
49131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{
492b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_QUAD_OP))
493b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers                << EncodingMap[opcode].name << " " << (int)opcode << " "
494b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers                << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
495b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers                << cUnit->currentDalvikOffset;
496a2ebdd74eb2f36e6efa7a482bc11c7b93d97c2c3buzbee    LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, dest, src1,
497a2ebdd74eb2f36e6efa7a482bc11c7b93d97c2c3buzbee                       src2, info);
49831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    oatAppendLIR(cUnit, (LIR*) insn);
49931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    return insn;
50031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
50131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
502b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian RogersLIR* newLIR5(CompilationUnit* cUnit, int opcode,
503b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers             int dest, int src1, int src2, int info1, int info2)
504b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers{
505b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_QUIN_OP))
506b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers                << EncodingMap[opcode].name << " " << (int)opcode << " "
507b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers                << PrettyMethod(cUnit->method_idx, *cUnit->dex_file) << " "
508b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers                << cUnit->currentDalvikOffset;
509b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    LIR* insn = rawLIR(cUnit, cUnit->currentDalvikOffset, opcode, dest, src1,
510b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers                       src2, info1, info2);
511b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    oatAppendLIR(cUnit, (LIR*) insn);
512b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers    return insn;
513b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers}
514b5d09b2f87202bc132ac3991d4b6d71f4f6d9264Ian Rogers
51531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee/*
51631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * Search the existing constants in the literal pool for an exact or close match
51731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * within specified delta (greater or equal to 0).
51831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee */
51931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbeeLIR* scanLiteralPool(LIR* dataTarget, int value, unsigned int delta)
52031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{
52131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    while (dataTarget) {
52231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee        if (((unsigned) (value - ((LIR* ) dataTarget)->operands[0])) <=
52331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee            delta)
52431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee            return (LIR* ) dataTarget;
52531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee        dataTarget = dataTarget->next;
52631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    }
52731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    return NULL;
52831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
52931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
53031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee/* Search the existing constants in the literal pool for an exact wide match */
53131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbeeLIR* scanLiteralPoolWide(LIR* dataTarget, int valLo, int valHi)
53231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{
53331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    bool loMatch = false;
53431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    LIR* loTarget = NULL;
53531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    while (dataTarget) {
53631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee        if (loMatch && (((LIR*)dataTarget)->operands[0] == valHi)) {
53731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee            return (LIR*)loTarget;
53831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee        }
53931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee        loMatch = false;
54031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee        if (((LIR*)dataTarget)->operands[0] == valLo) {
54131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee            loMatch = true;
54231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee            loTarget = dataTarget;
54331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee        }
54431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee        dataTarget = dataTarget->next;
54531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    }
54631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    return NULL;
54731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
54831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
54931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee/*
55031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * The following are building blocks to insert constants into the pool or
55131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * instruction streams.
55231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee */
55331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
5545de3494e4297c0d480409da3fecee39173f1d4e1buzbee/* Add a 32-bit constant either in the constant pool */
55531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbeeLIR* addWordData(CompilationUnit* cUnit, LIR* *constantListP,
55631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee                           int value)
55731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{
55831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    /* Add the constant to the literal pool */
55931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    if (constantListP) {
56031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee        LIR* newValue = (LIR* ) oatNew(cUnit, sizeof(LIR), true,
56131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee                                             kAllocData);
56231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee        newValue->operands[0] = value;
56331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee        newValue->next = *constantListP;
56431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee        *constantListP = (LIR*) newValue;
56531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee        return newValue;
56631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    }
56731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    return NULL;
56831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
56931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
57031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee/* Add a 64-bit constant to the constant pool or mixed with code */
57131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbeeLIR* addWideData(CompilationUnit* cUnit, LIR* *constantListP,
57231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee                           int valLo, int valHi)
57331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{
57431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    //FIXME: hard-coded little endian, need BE variant
5755de3494e4297c0d480409da3fecee39173f1d4e1buzbee    // Insert high word into list first
5765de3494e4297c0d480409da3fecee39173f1d4e1buzbee    addWordData(cUnit, constantListP, valHi);
5775de3494e4297c0d480409da3fecee39173f1d4e1buzbee    return addWordData(cUnit, constantListP, valLo);
57831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
57931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
580ab058bb04d11ed086116d95f2d55bf6b35e8cc35Ian Rogersvoid pushWord(std::vector<uint8_t>&buf, int data) {
581ab058bb04d11ed086116d95f2d55bf6b35e8cc35Ian Rogers    buf.push_back( data & 0xff);
582ab058bb04d11ed086116d95f2d55bf6b35e8cc35Ian Rogers    buf.push_back( (data >> 8) & 0xff);
583ab058bb04d11ed086116d95f2d55bf6b35e8cc35Ian Rogers    buf.push_back( (data >> 16) & 0xff);
584ab058bb04d11ed086116d95f2d55bf6b35e8cc35Ian Rogers    buf.push_back( (data >> 24) & 0xff);
585e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee}
586e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
587ab058bb04d11ed086116d95f2d55bf6b35e8cc35Ian Rogersvoid alignBuffer(std::vector<uint8_t>&buf, size_t offset) {
588ab058bb04d11ed086116d95f2d55bf6b35e8cc35Ian Rogers    while (buf.size() < offset) {
589e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee        buf.push_back(0);
590ab058bb04d11ed086116d95f2d55bf6b35e8cc35Ian Rogers    }
591e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee}
592e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
593e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee/* Write the literal pool to the output stream */
59431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbeevoid installLiteralPools(CompilationUnit* cUnit)
595e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee{
596e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee    alignBuffer(cUnit->codeBuffer, cUnit->dataOffset);
59731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    LIR* dataLIR = (LIR*) cUnit->literalList;
598e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee    while (dataLIR != NULL) {
599e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee        pushWord(cUnit->codeBuffer, dataLIR->operands[0]);
600e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee        dataLIR = NEXT_LIR(dataLIR);
601e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee    }
602e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee}
603e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
604e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee/* Write the switch tables to the output stream */
60531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbeevoid installSwitchTables(CompilationUnit* cUnit)
606e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee{
607e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee    GrowableListIterator iterator;
608e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee    oatGrowableListIteratorInit(&cUnit->switchTables, &iterator);
609e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee    while (true) {
610e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee        SwitchTable* tabRec = (SwitchTable *) oatGrowableListIteratorNext(
611e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee             &iterator);
612e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee        if (tabRec == NULL) break;
613e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee        alignBuffer(cUnit->codeBuffer, tabRec->offset);
614c5159d55ca8e9022b748176f9f53676e8e9d4cd2buzbee        /*
615c5159d55ca8e9022b748176f9f53676e8e9d4cd2buzbee         * For Arm, our reference point is the address of the bx
616c5159d55ca8e9022b748176f9f53676e8e9d4cd2buzbee         * instruction that does the launch, so we have to subtract
617c5159d55ca8e9022b748176f9f53676e8e9d4cd2buzbee         * the auto pc-advance.  For other targets the reference point
618c5159d55ca8e9022b748176f9f53676e8e9d4cd2buzbee         * is a label, so we can use the offset as-is.
619c5159d55ca8e9022b748176f9f53676e8e9d4cd2buzbee         */
620c5159d55ca8e9022b748176f9f53676e8e9d4cd2buzbee#if defined(TARGET_ARM)
621c5159d55ca8e9022b748176f9f53676e8e9d4cd2buzbee        int bxOffset = tabRec->anchor->offset + 4;
622c5159d55ca8e9022b748176f9f53676e8e9d4cd2buzbee#else
623c5159d55ca8e9022b748176f9f53676e8e9d4cd2buzbee        int bxOffset = tabRec->anchor->offset;
624c5159d55ca8e9022b748176f9f53676e8e9d4cd2buzbee#endif
625e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee        if (cUnit->printMe) {
626e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee            LOG(INFO) << "Switch table for offset 0x" << std::hex << bxOffset;
627e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee        }
628adb8c67f6d87a160d4e3a8afea7cb93f6c14568bElliott Hughes        if (tabRec->table[0] == Instruction::kSparseSwitchSignature) {
629e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee            int* keys = (int*)&(tabRec->table[2]);
630e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee            for (int elems = 0; elems < tabRec->table[1]; elems++) {
63131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee                int disp = tabRec->targets[elems]->offset - bxOffset;
632e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee                if (cUnit->printMe) {
633e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee                    LOG(INFO) << "    Case[" << elems << "] key: 0x" <<
634e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee                        std::hex << keys[elems] << ", disp: 0x" <<
635e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee                        std::hex << disp;
636e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee                }
637e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee                pushWord(cUnit->codeBuffer, keys[elems]);
638e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee                pushWord(cUnit->codeBuffer,
63931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee                    tabRec->targets[elems]->offset - bxOffset);
640e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee            }
641e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee        } else {
642adb8c67f6d87a160d4e3a8afea7cb93f6c14568bElliott Hughes            DCHECK_EQ(static_cast<int>(tabRec->table[0]), static_cast<int>(Instruction::kPackedSwitchSignature));
643e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee            for (int elems = 0; elems < tabRec->table[1]; elems++) {
64431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee                int disp = tabRec->targets[elems]->offset - bxOffset;
645e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee                if (cUnit->printMe) {
646e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee                    LOG(INFO) << "    Case[" << elems << "] disp: 0x" <<
647e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee                        std::hex << disp;
648e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee                }
649e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee                pushWord(cUnit->codeBuffer,
65031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee                         tabRec->targets[elems]->offset - bxOffset);
651e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee            }
652e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee        }
653e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee    }
654e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee}
655e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
656e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee/* Write the fill array dta to the output stream */
65731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbeevoid installFillArrayData(CompilationUnit* cUnit)
658e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee{
659e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee    GrowableListIterator iterator;
660e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee    oatGrowableListIteratorInit(&cUnit->fillArrayData, &iterator);
661e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee    while (true) {
662e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee        FillArrayData *tabRec = (FillArrayData *) oatGrowableListIteratorNext(
663e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee             &iterator);
664e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee        if (tabRec == NULL) break;
665e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee        alignBuffer(cUnit->codeBuffer, tabRec->offset);
666ab058bb04d11ed086116d95f2d55bf6b35e8cc35Ian Rogers        for (int i = 0; i < (tabRec->size + 1) / 2; i++) {
667ab058bb04d11ed086116d95f2d55bf6b35e8cc35Ian Rogers            cUnit->codeBuffer.push_back( tabRec->table[i] & 0xFF);
668ab058bb04d11ed086116d95f2d55bf6b35e8cc35Ian Rogers            cUnit->codeBuffer.push_back( (tabRec->table[i] >> 8) & 0xFF);
669e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee        }
670e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee    }
671e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee}
672e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
67331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbeeint assignLiteralOffsetCommon(LIR* lir, int offset)
674e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee{
675e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee    for (;lir != NULL; lir = lir->next) {
676e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee        lir->offset = offset;
677e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee        offset += 4;
678e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee    }
679e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee    return offset;
680e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee}
681e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
68231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbeevoid createMappingTable(CompilationUnit* cUnit)
683e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee{
68431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    LIR* tgtLIR;
685e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee    int currentDalvikOffset = -1;
686e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
68731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    for (tgtLIR = (LIR *) cUnit->firstLIRInsn;
688e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee         tgtLIR;
689e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee         tgtLIR = NEXT_LIR(tgtLIR)) {
690e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee        if ((tgtLIR->opcode >= 0) && !tgtLIR->flags.isNop &&
69131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee            (currentDalvikOffset != tgtLIR->dalvikOffset)) {
692e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee            // Changed - need to emit a record
69331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee            cUnit->mappingTable.push_back(tgtLIR->offset);
69431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee            cUnit->mappingTable.push_back(tgtLIR->dalvikOffset);
69531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee            currentDalvikOffset = tgtLIR->dalvikOffset;
696e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee        }
697e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee    }
698e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee}
699e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
700e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee/* Determine the offset of each literal field */
70131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbeeint assignLiteralOffset(CompilationUnit* cUnit, int offset)
702e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee{
703e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee    offset = assignLiteralOffsetCommon(cUnit->literalList, offset);
704e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee    return offset;
705e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee}
706e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
70731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbeeint assignSwitchTablesOffset(CompilationUnit* cUnit, int offset)
708e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee{
709e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee    GrowableListIterator iterator;
710e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee    oatGrowableListIteratorInit(&cUnit->switchTables, &iterator);
711e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee    while (true) {
712e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee        SwitchTable *tabRec = (SwitchTable *) oatGrowableListIteratorNext(
713e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee             &iterator);
714e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee        if (tabRec == NULL) break;
715e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee        tabRec->offset = offset;
716adb8c67f6d87a160d4e3a8afea7cb93f6c14568bElliott Hughes        if (tabRec->table[0] == Instruction::kSparseSwitchSignature) {
717e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee            offset += tabRec->table[1] * (sizeof(int) * 2);
718e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee        } else {
719adb8c67f6d87a160d4e3a8afea7cb93f6c14568bElliott Hughes            DCHECK_EQ(static_cast<int>(tabRec->table[0]), static_cast<int>(Instruction::kPackedSwitchSignature));
720e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee            offset += tabRec->table[1] * sizeof(int);
721e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee        }
722e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee    }
723e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee    return offset;
724e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee}
725e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
72631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbeeint assignFillArrayDataOffset(CompilationUnit* cUnit, int offset)
727e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee{
728e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee    GrowableListIterator iterator;
729e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee    oatGrowableListIteratorInit(&cUnit->fillArrayData, &iterator);
730e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee    while (true) {
731e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee        FillArrayData *tabRec = (FillArrayData *) oatGrowableListIteratorNext(
732e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee             &iterator);
733e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee        if (tabRec == NULL) break;
734e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee        tabRec->offset = offset;
735e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee        offset += tabRec->size;
736e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee        // word align
737e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee        offset = (offset + 3) & ~3;
738e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee        }
739e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee    return offset;
740e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee}
741e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
742e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee/*
743e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee * Walk the compilation unit and assign offsets to instructions
744e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee * and literals and compute the total size of the compiled unit.
745e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee */
746e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbeevoid oatAssignOffsets(CompilationUnit* cUnit)
747e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee{
748e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee    int offset = oatAssignInsnOffsets(cUnit);
749e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
750e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee    /* Const values have to be word aligned */
751e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee    offset = (offset + 3) & ~3;
752e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
753e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee    /* Set up offsets for literals */
754e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee    cUnit->dataOffset = offset;
755e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
756e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee    offset = assignLiteralOffset(cUnit, offset);
757e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
758e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee    offset = assignSwitchTablesOffset(cUnit, offset);
759e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
760e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee    offset = assignFillArrayDataOffset(cUnit, offset);
761e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
762e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee    cUnit->totalSize = offset;
763e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee}
764e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
765e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee/*
766e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee * Go over each instruction in the list and calculate the offset from the top
767e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee * before sending them off to the assembler. If out-of-range branch distance is
768e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee * seen rearrange the instructions a bit to correct it.
769e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee */
770e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbeevoid oatAssembleLIR(CompilationUnit* cUnit)
771e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee{
772e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee    oatAssignOffsets(cUnit);
773e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee    /*
774e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee     * Assemble here.  Note that we generate code with optimistic assumptions
775e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee     * and if found now to work, we'll have to redo the sequence and retry.
776e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee     */
777e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
778e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee    while (true) {
779e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee        AssemblerStatus res = oatAssembleInstructions(cUnit, 0);
780e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee        if (res == kSuccess) {
781e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee            break;
782e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee        } else {
783e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee            cUnit->assemblerRetries++;
784e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee            if (cUnit->assemblerRetries > MAX_ASSEMBLER_RETRIES) {
785e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee                LOG(FATAL) << "Assembler error - too many retries";
786e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee            }
787e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee            // Redo offsets and try again
788e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee            oatAssignOffsets(cUnit);
789e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee            cUnit->codeBuffer.clear();
790e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee        }
791e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee    }
792e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
793e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee    // Install literals
794e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee    installLiteralPools(cUnit);
795e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
796e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee    // Install switch tables
797e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee    installSwitchTables(cUnit);
798e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
799e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee    // Install fill array data
800e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee    installFillArrayData(cUnit);
801e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
802e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee    /*
803e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee     * Create the mapping table
804e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee     */
805e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee    createMappingTable(cUnit);
806e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee}
807e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
80831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee/*
80931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * Insert a kPseudoCaseLabel at the beginning of the Dalvik
81031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * offset vaddr.  This label will be used to fix up the case
81131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * branch table during the assembly phase.  Be sure to set
81231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * all resource flags on this to prevent code motion across
81331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * target boundaries.  KeyVal is just there for debugging.
81431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee */
81531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbeeLIR* insertCaseLabel(CompilationUnit* cUnit, int vaddr, int keyVal)
81631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{
81731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    std::map<unsigned int, LIR*>::iterator it;
81831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    it = cUnit->boundaryMap.find(vaddr);
81931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    if (it == cUnit->boundaryMap.end()) {
82031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee        LOG(FATAL) << "Error: didn't find vaddr 0x" << std::hex << vaddr;
82131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    }
82231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    LIR* newLabel = (LIR*)oatNew(cUnit, sizeof(LIR), true, kAllocLIR);
82331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    newLabel->dalvikOffset = vaddr;
82431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    newLabel->opcode = kPseudoCaseLabel;
82531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    newLabel->operands[0] = keyVal;
82631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    oatInsertLIRAfter(it->second, (LIR*)newLabel);
82731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    return newLabel;
82831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
82931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
83031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbeevoid markPackedCaseLabels(CompilationUnit* cUnit, SwitchTable *tabRec)
83131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{
83231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    const u2* table = tabRec->table;
83331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    int baseVaddr = tabRec->vaddr;
83431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    int *targets = (int*)&table[4];
83531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    int entries = table[1];
83631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    int lowKey = s4FromSwitchData(&table[2]);
83731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    for (int i = 0; i < entries; i++) {
83831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee        tabRec->targets[i] = insertCaseLabel(cUnit, baseVaddr + targets[i],
83931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee                                             i + lowKey);
84031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    }
84131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
84231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
84331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbeevoid markSparseCaseLabels(CompilationUnit* cUnit, SwitchTable *tabRec)
84431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{
84531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    const u2* table = tabRec->table;
84631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    int baseVaddr = tabRec->vaddr;
84731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    int entries = table[1];
84831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    int* keys = (int*)&table[2];
84931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    int* targets = &keys[entries];
85031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    for (int i = 0; i < entries; i++) {
85131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee        tabRec->targets[i] = insertCaseLabel(cUnit, baseVaddr + targets[i],
85231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee                                             keys[i]);
85331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    }
85431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
85531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
85631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbeevoid oatProcessSwitchTables(CompilationUnit* cUnit)
85731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{
85831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    GrowableListIterator iterator;
85931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    oatGrowableListIteratorInit(&cUnit->switchTables, &iterator);
86031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    while (true) {
86131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee        SwitchTable *tabRec = (SwitchTable *) oatGrowableListIteratorNext(
86231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee             &iterator);
86331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee        if (tabRec == NULL) break;
864adb8c67f6d87a160d4e3a8afea7cb93f6c14568bElliott Hughes        if (tabRec->table[0] == Instruction::kPackedSwitchSignature) {
86531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee            markPackedCaseLabels(cUnit, tabRec);
866adb8c67f6d87a160d4e3a8afea7cb93f6c14568bElliott Hughes        } else if (tabRec->table[0] == Instruction::kSparseSwitchSignature) {
86731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee            markSparseCaseLabels(cUnit, tabRec);
868adb8c67f6d87a160d4e3a8afea7cb93f6c14568bElliott Hughes        } else {
86931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee            LOG(FATAL) << "Invalid switch table";
87031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee        }
87131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    }
87231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
87331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
87431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee//FIXME: Do we have endian issues here?
87531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
87631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbeevoid dumpSparseSwitchTable(const u2* table)
87731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    /*
87831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee     * Sparse switch data format:
87931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee     *  ushort ident = 0x0200   magic value
88031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee     *  ushort size             number of entries in the table; > 0
88131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee     *  int keys[size]          keys, sorted low-to-high; 32-bit aligned
88231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee     *  int targets[size]       branch targets, relative to switch opcode
88331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee     *
88431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee     * Total size is (2+size*4) 16-bit code units.
88531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee     */
88631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{
88731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    u2 ident = table[0];
88831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    int entries = table[1];
88931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    int* keys = (int*)&table[2];
89031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    int* targets = &keys[entries];
89131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    LOG(INFO) <<  "Sparse switch table - ident:0x" << std::hex << ident <<
89231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee       ", entries: " << std::dec << entries;
89331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    for (int i = 0; i < entries; i++) {
89431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee        LOG(INFO) << "    Key[" << keys[i] << "] -> 0x" << std::hex <<
89531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee        targets[i];
89631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    }
89731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
89831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
89931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbeevoid dumpPackedSwitchTable(const u2* table)
90031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    /*
90131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee     * Packed switch data format:
90231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee     *  ushort ident = 0x0100   magic value
90331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee     *  ushort size             number of entries in the table
90431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee     *  int first_key           first (and lowest) switch case value
90531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee     *  int targets[size]       branch targets, relative to switch opcode
90631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee     *
90731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee     * Total size is (4+size*2) 16-bit code units.
90831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee     */
90931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{
91031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    u2 ident = table[0];
91131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    int* targets = (int*)&table[4];
91231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    int entries = table[1];
91331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    int lowKey = s4FromSwitchData(&table[2]);
91431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    LOG(INFO) << "Packed switch table - ident:0x" << std::hex << ident <<
91531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee        ", entries: " << std::dec << entries << ", lowKey: " << lowKey;
91631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    for (int i = 0; i < entries; i++) {
91731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee        LOG(INFO) << "    Key[" << (i + lowKey) << "] -> 0x" << std::hex <<
91831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee            targets[i];
91931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    }
92031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
921e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
922e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee
923e3acd07f28d5625062b599c2817cb5f7a53f54a9buzbee}  // namespace art
924