gen_loadstore.cc revision e196567b50a084b163937ea9605b51ee1e48adeb
167bf885d62b1473c833bece1c9e0bb624e6ba391buzbee/*
267bf885d62b1473c833bece1c9e0bb624e6ba391buzbee * Copyright (C) 2011 The Android Open Source Project
367bf885d62b1473c833bece1c9e0bb624e6ba391buzbee *
467bf885d62b1473c833bece1c9e0bb624e6ba391buzbee * Licensed under the Apache License, Version 2.0 (the "License");
567bf885d62b1473c833bece1c9e0bb624e6ba391buzbee * you may not use this file except in compliance with the License.
667bf885d62b1473c833bece1c9e0bb624e6ba391buzbee * You may obtain a copy of the License at
767bf885d62b1473c833bece1c9e0bb624e6ba391buzbee *
867bf885d62b1473c833bece1c9e0bb624e6ba391buzbee *      http://www.apache.org/licenses/LICENSE-2.0
967bf885d62b1473c833bece1c9e0bb624e6ba391buzbee *
1067bf885d62b1473c833bece1c9e0bb624e6ba391buzbee * Unless required by applicable law or agreed to in writing, software
1167bf885d62b1473c833bece1c9e0bb624e6ba391buzbee * distributed under the License is distributed on an "AS IS" BASIS,
1267bf885d62b1473c833bece1c9e0bb624e6ba391buzbee * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1367bf885d62b1473c833bece1c9e0bb624e6ba391buzbee * See the License for the specific language governing permissions and
1467bf885d62b1473c833bece1c9e0bb624e6ba391buzbee * limitations under the License.
1567bf885d62b1473c833bece1c9e0bb624e6ba391buzbee */
1667bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
1711d1b0c31ddd710d26068da8e0e4621002205b4bElliott Hughesnamespace art {
1811d1b0c31ddd710d26068da8e0e4621002205b4bElliott Hughes
1967bf885d62b1473c833bece1c9e0bb624e6ba391buzbee/*
2067bf885d62b1473c833bece1c9e0bb624e6ba391buzbee * This file contains target-independent codegen and support, and is
2167bf885d62b1473c833bece1c9e0bb624e6ba391buzbee * included by:
2267bf885d62b1473c833bece1c9e0bb624e6ba391buzbee *
2367bf885d62b1473c833bece1c9e0bb624e6ba391buzbee *        $(TARGET_ARCH)/Codegen-$(TARGET_ARCH_VARIANT).c
2467bf885d62b1473c833bece1c9e0bb624e6ba391buzbee *
2567bf885d62b1473c833bece1c9e0bb624e6ba391buzbee * which combines this common code with specific support found in the
2667bf885d62b1473c833bece1c9e0bb624e6ba391buzbee * applicable directories below this one.
2767bf885d62b1473c833bece1c9e0bb624e6ba391buzbee *
2867bf885d62b1473c833bece1c9e0bb624e6ba391buzbee */
2967bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
3031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee/*
3131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * Load an immediate value into a fixed or temp register.  Target
3231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * register is clobbered, and marked inUse.
3331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee */
3431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbeeLIR* loadConstant(CompilationUnit* cUnit, int rDest, int value)
3531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{
3631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    if (oatIsTemp(cUnit, rDest)) {
3731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee        oatClobber(cUnit, rDest);
3831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee        oatMarkInUse(cUnit, rDest);
3931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    }
4031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    return loadConstantNoClobber(cUnit, rDest, value);
4131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
4267bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
4367bf885d62b1473c833bece1c9e0bb624e6ba391buzbee/* Load a word at base + displacement.  Displacement must be word multiple */
4431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbeeLIR* loadWordDisp(CompilationUnit* cUnit, int rBase, int displacement,
4531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee                  int rDest)
4667bf885d62b1473c833bece1c9e0bb624e6ba391buzbee{
4767bf885d62b1473c833bece1c9e0bb624e6ba391buzbee    return loadBaseDisp(cUnit, NULL, rBase, displacement, rDest, kWord,
4867bf885d62b1473c833bece1c9e0bb624e6ba391buzbee                        INVALID_SREG);
4967bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
5067bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
5131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbeeLIR* storeWordDisp(CompilationUnit* cUnit, int rBase, int displacement,
5231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee                   int rSrc)
5367bf885d62b1473c833bece1c9e0bb624e6ba391buzbee{
5467bf885d62b1473c833bece1c9e0bb624e6ba391buzbee    return storeBaseDisp(cUnit, rBase, displacement, rSrc, kWord);
5567bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
5667bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
5767bf885d62b1473c833bece1c9e0bb624e6ba391buzbee/*
5867bf885d62b1473c833bece1c9e0bb624e6ba391buzbee * Load a Dalvik register into a physical register.  Take care when
5967bf885d62b1473c833bece1c9e0bb624e6ba391buzbee * using this routine, as it doesn't perform any bookkeeping regarding
6067bf885d62b1473c833bece1c9e0bb624e6ba391buzbee * register liveness.  That is the responsibility of the caller.
6167bf885d62b1473c833bece1c9e0bb624e6ba391buzbee */
6231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbeevoid loadValueDirect(CompilationUnit* cUnit, RegLocation rlSrc, int reg1)
6367bf885d62b1473c833bece1c9e0bb624e6ba391buzbee{
6467bf885d62b1473c833bece1c9e0bb624e6ba391buzbee    rlSrc = oatUpdateLoc(cUnit, rlSrc);
6567bf885d62b1473c833bece1c9e0bb624e6ba391buzbee    if (rlSrc.location == kLocPhysReg) {
6682488f563e7f72f8c626052893c1792d76ab3fafbuzbee        opRegCopy(cUnit, reg1, rlSrc.lowReg);
6767bf885d62b1473c833bece1c9e0bb624e6ba391buzbee    } else {
68e196567b50a084b163937ea9605b51ee1e48adebbuzbee        DCHECK((rlSrc.location == kLocDalvikFrame) ||
69e196567b50a084b163937ea9605b51ee1e48adebbuzbee               (rlSrc.location == kLocCompilerTemp));
7067bc236a207852d652f6ddeab0a90efc1bd111bbbuzbee        loadWordDisp(cUnit, rSP, oatSRegOffset(cUnit, rlSrc.sRegLow), reg1);
7167bf885d62b1473c833bece1c9e0bb624e6ba391buzbee    }
7267bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
7367bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
7467bf885d62b1473c833bece1c9e0bb624e6ba391buzbee/*
7567bf885d62b1473c833bece1c9e0bb624e6ba391buzbee * Similar to loadValueDirect, but clobbers and allocates the target
7667bf885d62b1473c833bece1c9e0bb624e6ba391buzbee * register.  Should be used when loading to a fixed register (for example,
7767bf885d62b1473c833bece1c9e0bb624e6ba391buzbee * loading arguments to an out of line call.
7867bf885d62b1473c833bece1c9e0bb624e6ba391buzbee */
7931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbeevoid loadValueDirectFixed(CompilationUnit* cUnit, RegLocation rlSrc, int reg1)
8067bf885d62b1473c833bece1c9e0bb624e6ba391buzbee{
8167bf885d62b1473c833bece1c9e0bb624e6ba391buzbee    oatClobber(cUnit, reg1);
8267bf885d62b1473c833bece1c9e0bb624e6ba391buzbee    oatMarkInUse(cUnit, reg1);
8367bf885d62b1473c833bece1c9e0bb624e6ba391buzbee    loadValueDirect(cUnit, rlSrc, reg1);
8467bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
8567bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
8667bf885d62b1473c833bece1c9e0bb624e6ba391buzbee/*
8767bf885d62b1473c833bece1c9e0bb624e6ba391buzbee * Load a Dalvik register pair into a physical register[s].  Take care when
8867bf885d62b1473c833bece1c9e0bb624e6ba391buzbee * using this routine, as it doesn't perform any bookkeeping regarding
8967bf885d62b1473c833bece1c9e0bb624e6ba391buzbee * register liveness.  That is the responsibility of the caller.
9067bf885d62b1473c833bece1c9e0bb624e6ba391buzbee */
9131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbeevoid loadValueDirectWide(CompilationUnit* cUnit, RegLocation rlSrc, int regLo,
9231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee                         int regHi)
9367bf885d62b1473c833bece1c9e0bb624e6ba391buzbee{
9467bf885d62b1473c833bece1c9e0bb624e6ba391buzbee    rlSrc = oatUpdateLocWide(cUnit, rlSrc);
9567bf885d62b1473c833bece1c9e0bb624e6ba391buzbee    if (rlSrc.location == kLocPhysReg) {
9682488f563e7f72f8c626052893c1792d76ab3fafbuzbee        opRegCopyWide(cUnit, regLo, regHi, rlSrc.lowReg, rlSrc.highReg);
9767bf885d62b1473c833bece1c9e0bb624e6ba391buzbee    } else {
98e196567b50a084b163937ea9605b51ee1e48adebbuzbee        DCHECK((rlSrc.location == kLocDalvikFrame) ||
99e196567b50a084b163937ea9605b51ee1e48adebbuzbee               (rlSrc.location == kLocCompilerTemp));
10067bc236a207852d652f6ddeab0a90efc1bd111bbbuzbee        loadBaseDispWide(cUnit, NULL, rSP,
10167bc236a207852d652f6ddeab0a90efc1bd111bbbuzbee                         oatSRegOffset(cUnit, rlSrc.sRegLow),
10267bf885d62b1473c833bece1c9e0bb624e6ba391buzbee                         regLo, regHi, INVALID_SREG);
10367bf885d62b1473c833bece1c9e0bb624e6ba391buzbee    }
10467bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
10567bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
10667bf885d62b1473c833bece1c9e0bb624e6ba391buzbee/*
10767bf885d62b1473c833bece1c9e0bb624e6ba391buzbee * Similar to loadValueDirect, but clobbers and allocates the target
10867bf885d62b1473c833bece1c9e0bb624e6ba391buzbee * registers.  Should be used when loading to a fixed registers (for example,
10967bf885d62b1473c833bece1c9e0bb624e6ba391buzbee * loading arguments to an out of line call.
11067bf885d62b1473c833bece1c9e0bb624e6ba391buzbee */
11131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbeevoid loadValueDirectWideFixed(CompilationUnit* cUnit, RegLocation rlSrc,
11231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee                              int regLo, int regHi)
11367bf885d62b1473c833bece1c9e0bb624e6ba391buzbee{
11467bf885d62b1473c833bece1c9e0bb624e6ba391buzbee    oatClobber(cUnit, regLo);
11567bf885d62b1473c833bece1c9e0bb624e6ba391buzbee    oatClobber(cUnit, regHi);
11667bf885d62b1473c833bece1c9e0bb624e6ba391buzbee    oatMarkInUse(cUnit, regLo);
11767bf885d62b1473c833bece1c9e0bb624e6ba391buzbee    oatMarkInUse(cUnit, regHi);
11867bf885d62b1473c833bece1c9e0bb624e6ba391buzbee    loadValueDirectWide(cUnit, rlSrc, regLo, regHi);
11967bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
12067bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
12131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbeeRegLocation loadValue(CompilationUnit* cUnit, RegLocation rlSrc,
12231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee                      RegisterClass opKind)
12367bf885d62b1473c833bece1c9e0bb624e6ba391buzbee{
12467bf885d62b1473c833bece1c9e0bb624e6ba391buzbee    rlSrc = oatEvalLoc(cUnit, rlSrc, opKind, false);
125e196567b50a084b163937ea9605b51ee1e48adebbuzbee    if (rlSrc.location != kLocPhysReg) {
126e196567b50a084b163937ea9605b51ee1e48adebbuzbee        DCHECK((rlSrc.location == kLocDalvikFrame) ||
127e196567b50a084b163937ea9605b51ee1e48adebbuzbee               (rlSrc.location == kLocCompilerTemp));
12867bf885d62b1473c833bece1c9e0bb624e6ba391buzbee        loadValueDirect(cUnit, rlSrc, rlSrc.lowReg);
12967bf885d62b1473c833bece1c9e0bb624e6ba391buzbee        rlSrc.location = kLocPhysReg;
13067bf885d62b1473c833bece1c9e0bb624e6ba391buzbee        oatMarkLive(cUnit, rlSrc.lowReg, rlSrc.sRegLow);
13167bf885d62b1473c833bece1c9e0bb624e6ba391buzbee    }
13267bf885d62b1473c833bece1c9e0bb624e6ba391buzbee    return rlSrc;
13367bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
13467bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
13531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbeevoid storeValue(CompilationUnit* cUnit, RegLocation rlDest, RegLocation rlSrc)
13667bf885d62b1473c833bece1c9e0bb624e6ba391buzbee{
13767bf885d62b1473c833bece1c9e0bb624e6ba391buzbee    LIR* defStart;
13867bf885d62b1473c833bece1c9e0bb624e6ba391buzbee    LIR* defEnd;
139ed3e930109e3f01804ca32cee4afe4f2d4b3f4d8buzbee    DCHECK(!rlDest.wide);
140ed3e930109e3f01804ca32cee4afe4f2d4b3f4d8buzbee    DCHECK(!rlSrc.wide);
14167bf885d62b1473c833bece1c9e0bb624e6ba391buzbee    rlSrc = oatUpdateLoc(cUnit, rlSrc);
14267bf885d62b1473c833bece1c9e0bb624e6ba391buzbee    rlDest = oatUpdateLoc(cUnit, rlDest);
14367bf885d62b1473c833bece1c9e0bb624e6ba391buzbee    if (rlSrc.location == kLocPhysReg) {
14467bf885d62b1473c833bece1c9e0bb624e6ba391buzbee        if (oatIsLive(cUnit, rlSrc.lowReg) ||
145b29e4d1423028fab47db3be6e41e4b2a067bf100buzbee            oatIsPromoted(cUnit, rlSrc.lowReg) ||
14667bf885d62b1473c833bece1c9e0bb624e6ba391buzbee            (rlDest.location == kLocPhysReg)) {
147b29e4d1423028fab47db3be6e41e4b2a067bf100buzbee            // Src is live/promoted or Dest has assigned reg.
14867bf885d62b1473c833bece1c9e0bb624e6ba391buzbee            rlDest = oatEvalLoc(cUnit, rlDest, kAnyReg, false);
14982488f563e7f72f8c626052893c1792d76ab3fafbuzbee            opRegCopy(cUnit, rlDest.lowReg, rlSrc.lowReg);
15067bf885d62b1473c833bece1c9e0bb624e6ba391buzbee        } else {
15167bf885d62b1473c833bece1c9e0bb624e6ba391buzbee            // Just re-assign the registers.  Dest gets Src's regs
15267bf885d62b1473c833bece1c9e0bb624e6ba391buzbee            rlDest.lowReg = rlSrc.lowReg;
15367bf885d62b1473c833bece1c9e0bb624e6ba391buzbee            oatClobber(cUnit, rlSrc.lowReg);
15467bf885d62b1473c833bece1c9e0bb624e6ba391buzbee        }
15567bf885d62b1473c833bece1c9e0bb624e6ba391buzbee    } else {
15667bf885d62b1473c833bece1c9e0bb624e6ba391buzbee        // Load Src either into promoted Dest or temps allocated for Dest
15767bf885d62b1473c833bece1c9e0bb624e6ba391buzbee        rlDest = oatEvalLoc(cUnit, rlDest, kAnyReg, false);
15867bf885d62b1473c833bece1c9e0bb624e6ba391buzbee        loadValueDirect(cUnit, rlSrc, rlDest.lowReg);
15967bf885d62b1473c833bece1c9e0bb624e6ba391buzbee    }
16067bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
16167bf885d62b1473c833bece1c9e0bb624e6ba391buzbee    // Dest is now live and dirty (until/if we flush it to home location)
16267bf885d62b1473c833bece1c9e0bb624e6ba391buzbee    oatMarkLive(cUnit, rlDest.lowReg, rlDest.sRegLow);
16367bf885d62b1473c833bece1c9e0bb624e6ba391buzbee    oatMarkDirty(cUnit, rlDest);
16467bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
16567bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
16667bf885d62b1473c833bece1c9e0bb624e6ba391buzbee    oatResetDefLoc(cUnit, rlDest);
16767bf885d62b1473c833bece1c9e0bb624e6ba391buzbee    if (oatIsDirty(cUnit, rlDest.lowReg) &&
16867bf885d62b1473c833bece1c9e0bb624e6ba391buzbee        oatLiveOut(cUnit, rlDest.sRegLow)) {
16967bf885d62b1473c833bece1c9e0bb624e6ba391buzbee        defStart = (LIR* )cUnit->lastLIRInsn;
17067bc236a207852d652f6ddeab0a90efc1bd111bbbuzbee        storeBaseDisp(cUnit, rSP, oatSRegOffset(cUnit, rlDest.sRegLow),
17167bc236a207852d652f6ddeab0a90efc1bd111bbbuzbee                      rlDest.lowReg, kWord);
17267bf885d62b1473c833bece1c9e0bb624e6ba391buzbee        oatMarkClean(cUnit, rlDest);
17367bf885d62b1473c833bece1c9e0bb624e6ba391buzbee        defEnd = (LIR* )cUnit->lastLIRInsn;
17467bf885d62b1473c833bece1c9e0bb624e6ba391buzbee        oatMarkDef(cUnit, rlDest, defStart, defEnd);
17567bf885d62b1473c833bece1c9e0bb624e6ba391buzbee    }
17667bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
17767bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
17831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbeeRegLocation loadValueWide(CompilationUnit* cUnit, RegLocation rlSrc,
17931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee                          RegisterClass opKind)
18067bf885d62b1473c833bece1c9e0bb624e6ba391buzbee{
181ed3e930109e3f01804ca32cee4afe4f2d4b3f4d8buzbee    DCHECK(rlSrc.wide);
18267bf885d62b1473c833bece1c9e0bb624e6ba391buzbee    rlSrc = oatEvalLoc(cUnit, rlSrc, opKind, false);
183e196567b50a084b163937ea9605b51ee1e48adebbuzbee    if (rlSrc.location != kLocPhysReg) {
184e196567b50a084b163937ea9605b51ee1e48adebbuzbee        DCHECK((rlSrc.location == kLocDalvikFrame) ||
185e196567b50a084b163937ea9605b51ee1e48adebbuzbee               (rlSrc.location == kLocCompilerTemp));
18667bf885d62b1473c833bece1c9e0bb624e6ba391buzbee        loadValueDirectWide(cUnit, rlSrc, rlSrc.lowReg, rlSrc.highReg);
18767bf885d62b1473c833bece1c9e0bb624e6ba391buzbee        rlSrc.location = kLocPhysReg;
18867bf885d62b1473c833bece1c9e0bb624e6ba391buzbee        oatMarkLive(cUnit, rlSrc.lowReg, rlSrc.sRegLow);
18967bf885d62b1473c833bece1c9e0bb624e6ba391buzbee        oatMarkLive(cUnit, rlSrc.highReg,
19067bf885d62b1473c833bece1c9e0bb624e6ba391buzbee                            oatSRegHi(rlSrc.sRegLow));
19167bf885d62b1473c833bece1c9e0bb624e6ba391buzbee    }
19267bf885d62b1473c833bece1c9e0bb624e6ba391buzbee    return rlSrc;
19367bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
19467bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
19531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbeevoid storeValueWide(CompilationUnit* cUnit, RegLocation rlDest,
19631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee                    RegLocation rlSrc)
19767bf885d62b1473c833bece1c9e0bb624e6ba391buzbee{
19867bf885d62b1473c833bece1c9e0bb624e6ba391buzbee    LIR* defStart;
19967bf885d62b1473c833bece1c9e0bb624e6ba391buzbee    LIR* defEnd;
200ed3e930109e3f01804ca32cee4afe4f2d4b3f4d8buzbee    DCHECK_EQ(FPREG(rlSrc.lowReg), FPREG(rlSrc.highReg));
201ed3e930109e3f01804ca32cee4afe4f2d4b3f4d8buzbee    DCHECK(rlDest.wide);
202ed3e930109e3f01804ca32cee4afe4f2d4b3f4d8buzbee    DCHECK(rlSrc.wide);
20367bf885d62b1473c833bece1c9e0bb624e6ba391buzbee    if (rlSrc.location == kLocPhysReg) {
20467bf885d62b1473c833bece1c9e0bb624e6ba391buzbee        if (oatIsLive(cUnit, rlSrc.lowReg) ||
20567bf885d62b1473c833bece1c9e0bb624e6ba391buzbee            oatIsLive(cUnit, rlSrc.highReg) ||
206b29e4d1423028fab47db3be6e41e4b2a067bf100buzbee            oatIsPromoted(cUnit, rlSrc.lowReg) ||
207b29e4d1423028fab47db3be6e41e4b2a067bf100buzbee            oatIsPromoted(cUnit, rlSrc.highReg) ||
20867bf885d62b1473c833bece1c9e0bb624e6ba391buzbee            (rlDest.location == kLocPhysReg)) {
209b29e4d1423028fab47db3be6e41e4b2a067bf100buzbee            // Src is live or promoted or Dest has assigned reg.
21067bf885d62b1473c833bece1c9e0bb624e6ba391buzbee            rlDest = oatEvalLoc(cUnit, rlDest, kAnyReg, false);
21182488f563e7f72f8c626052893c1792d76ab3fafbuzbee            opRegCopyWide(cUnit, rlDest.lowReg, rlDest.highReg,
21267bf885d62b1473c833bece1c9e0bb624e6ba391buzbee                           rlSrc.lowReg, rlSrc.highReg);
21367bf885d62b1473c833bece1c9e0bb624e6ba391buzbee        } else {
21467bf885d62b1473c833bece1c9e0bb624e6ba391buzbee            // Just re-assign the registers.  Dest gets Src's regs
21567bf885d62b1473c833bece1c9e0bb624e6ba391buzbee            rlDest.lowReg = rlSrc.lowReg;
21667bf885d62b1473c833bece1c9e0bb624e6ba391buzbee            rlDest.highReg = rlSrc.highReg;
21767bf885d62b1473c833bece1c9e0bb624e6ba391buzbee            oatClobber(cUnit, rlSrc.lowReg);
21867bf885d62b1473c833bece1c9e0bb624e6ba391buzbee            oatClobber(cUnit, rlSrc.highReg);
21967bf885d62b1473c833bece1c9e0bb624e6ba391buzbee        }
22067bf885d62b1473c833bece1c9e0bb624e6ba391buzbee    } else {
22167bf885d62b1473c833bece1c9e0bb624e6ba391buzbee        // Load Src either into promoted Dest or temps allocated for Dest
22267bf885d62b1473c833bece1c9e0bb624e6ba391buzbee        rlDest = oatEvalLoc(cUnit, rlDest, kAnyReg, false);
22367bf885d62b1473c833bece1c9e0bb624e6ba391buzbee        loadValueDirectWide(cUnit, rlSrc, rlDest.lowReg,
22467bf885d62b1473c833bece1c9e0bb624e6ba391buzbee                            rlDest.highReg);
22567bf885d62b1473c833bece1c9e0bb624e6ba391buzbee    }
22667bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
22767bf885d62b1473c833bece1c9e0bb624e6ba391buzbee    // Dest is now live and dirty (until/if we flush it to home location)
22867bf885d62b1473c833bece1c9e0bb624e6ba391buzbee    oatMarkLive(cUnit, rlDest.lowReg, rlDest.sRegLow);
22967bf885d62b1473c833bece1c9e0bb624e6ba391buzbee    oatMarkLive(cUnit, rlDest.highReg,
23067bf885d62b1473c833bece1c9e0bb624e6ba391buzbee                        oatSRegHi(rlDest.sRegLow));
23167bf885d62b1473c833bece1c9e0bb624e6ba391buzbee    oatMarkDirty(cUnit, rlDest);
23267bf885d62b1473c833bece1c9e0bb624e6ba391buzbee    oatMarkPair(cUnit, rlDest.lowReg, rlDest.highReg);
23367bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
23467bf885d62b1473c833bece1c9e0bb624e6ba391buzbee
23567bf885d62b1473c833bece1c9e0bb624e6ba391buzbee    oatResetDefLocWide(cUnit, rlDest);
23667bf885d62b1473c833bece1c9e0bb624e6ba391buzbee    if ((oatIsDirty(cUnit, rlDest.lowReg) ||
23767bf885d62b1473c833bece1c9e0bb624e6ba391buzbee        oatIsDirty(cUnit, rlDest.highReg)) &&
23867bf885d62b1473c833bece1c9e0bb624e6ba391buzbee        (oatLiveOut(cUnit, rlDest.sRegLow) ||
23967bf885d62b1473c833bece1c9e0bb624e6ba391buzbee        oatLiveOut(cUnit, oatSRegHi(rlDest.sRegLow)))) {
24067bf885d62b1473c833bece1c9e0bb624e6ba391buzbee        defStart = (LIR*)cUnit->lastLIRInsn;
241e196567b50a084b163937ea9605b51ee1e48adebbuzbee        DCHECK_EQ((SRegToVReg(cUnit, rlDest.sRegLow)+1),
242e196567b50a084b163937ea9605b51ee1e48adebbuzbee                   SRegToVReg(cUnit, oatSRegHi(rlDest.sRegLow)));
24367bc236a207852d652f6ddeab0a90efc1bd111bbbuzbee        storeBaseDispWide(cUnit, rSP, oatSRegOffset(cUnit, rlDest.sRegLow),
24467bf885d62b1473c833bece1c9e0bb624e6ba391buzbee                          rlDest.lowReg, rlDest.highReg);
24567bf885d62b1473c833bece1c9e0bb624e6ba391buzbee        oatMarkClean(cUnit, rlDest);
24667bf885d62b1473c833bece1c9e0bb624e6ba391buzbee        defEnd = (LIR*)cUnit->lastLIRInsn;
24767bf885d62b1473c833bece1c9e0bb624e6ba391buzbee        oatMarkDefWide(cUnit, rlDest, defStart, defEnd);
24867bf885d62b1473c833bece1c9e0bb624e6ba391buzbee    }
24967bf885d62b1473c833bece1c9e0bb624e6ba391buzbee}
25011d1b0c31ddd710d26068da8e0e4621002205b4bElliott Hughes
25131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee/*
25231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee * Mark garbage collection card. Skip if the value we're storing is null.
25331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee */
25431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbeevoid markGCCard(CompilationUnit* cUnit, int valReg, int tgtAddrReg)
25531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{
256a7678db092ac6bb79f7cad490099a1015fbbc714buzbee#if defined(TARGET_X86)
257a7678db092ac6bb79f7cad490099a1015fbbc714buzbee    UNIMPLEMENTED(WARNING) << "markGCCard";
258a7678db092ac6bb79f7cad490099a1015fbbc714buzbee#else
25931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    int regCardBase = oatAllocTemp(cUnit);
26031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    int regCardNo = oatAllocTemp(cUnit);
26182488f563e7f72f8c626052893c1792d76ab3fafbuzbee    LIR* branchOver = opCmpImmBranch(cUnit, kCondEq, valReg, 0, NULL);
26231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    loadWordDisp(cUnit, rSELF, Thread::CardTableOffset().Int32Value(),
26331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee                 regCardBase);
26431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    opRegRegImm(cUnit, kOpLsr, regCardNo, tgtAddrReg, GC_CARD_SHIFT);
26531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    storeBaseIndexed(cUnit, regCardBase, regCardNo, regCardBase, 0,
26631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee                     kUnsignedByte);
26731a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    LIR* target = newLIR0(cUnit, kPseudoTargetLabel);
26831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    branchOver->target = (LIR*)target;
26931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    oatFreeTemp(cUnit, regCardBase);
27031a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee    oatFreeTemp(cUnit, regCardNo);
271a7678db092ac6bb79f7cad490099a1015fbbc714buzbee#endif
27231a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
27331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
274e196567b50a084b163937ea9605b51ee1e48adebbuzbee/* Utilities to load the current Method* */
27531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbeevoid loadCurrMethodDirect(CompilationUnit *cUnit, int rTgt)
27631a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{
277e196567b50a084b163937ea9605b51ee1e48adebbuzbee    loadValueDirectFixed(cUnit, cUnit->regLocation[cUnit->methodSReg], rTgt);
27831a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
27931a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
280e196567b50a084b163937ea9605b51ee1e48adebbuzbeeRegLocation loadCurrMethod(CompilationUnit *cUnit)
28131a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee{
282e196567b50a084b163937ea9605b51ee1e48adebbuzbee    return loadValue(cUnit, cUnit->regLocation[cUnit->methodSReg], kCoreReg);
28331a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee}
28431a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
28531a4a6f5717f645da6b97ccc1e420ae1e1c71ce0buzbee
28611d1b0c31ddd710d26068da8e0e4621002205b4bElliott Hughes}  // namespace art
287