15d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng/*
25d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * Copyright (C) 2009 The Android Open Source Project
35d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng *
45d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * Licensed under the Apache License, Version 2.0 (the "License");
55d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * you may not use this file except in compliance with the License.
65d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * You may obtain a copy of the License at
75d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng *
85d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng *      http://www.apache.org/licenses/LICENSE-2.0
95d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng *
105d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * Unless required by applicable law or agreed to in writing, software
115d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * distributed under the License is distributed on an "AS IS" BASIS,
125d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * See the License for the specific language governing permissions and
145d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * limitations under the License.
155d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng */
165d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng
175d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng/*
18e3f97d3bf789bfa7cd9d295d019396d85481a87fbuzbee * This file contains target-independent codegen and support, and is
19e3f97d3bf789bfa7cd9d295d019396d85481a87fbuzbee * included by:
205d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng *
21e3f97d3bf789bfa7cd9d295d019396d85481a87fbuzbee *        $(TARGET_ARCH)/Codegen-$(TARGET_ARCH_VARIANT).c
225d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng *
235d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * which combines this common code with specific support found in the
24e3f97d3bf789bfa7cd9d295d019396d85481a87fbuzbee * applicable directories below this one.
25e3f97d3bf789bfa7cd9d295d019396d85481a87fbuzbee *
26e3f97d3bf789bfa7cd9d295d019396d85481a87fbuzbee * Prior to including this file, TGT_LIR should be #defined.
27e3f97d3bf789bfa7cd9d295d019396d85481a87fbuzbee * For example, for arm:
28e3f97d3bf789bfa7cd9d295d019396d85481a87fbuzbee *    #define TGT_LIR ArmLIR
29e3f97d3bf789bfa7cd9d295d019396d85481a87fbuzbee * and for x86:
30e3f97d3bf789bfa7cd9d295d019396d85481a87fbuzbee *    #define TGT_LIR X86LIR
315d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng */
325d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng
335d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng
345d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng/* Load a word at base + displacement.  Displacement must be word multiple */
35e3f97d3bf789bfa7cd9d295d019396d85481a87fbuzbeestatic TGT_LIR *loadWordDisp(CompilationUnit *cUnit, int rBase,
36e3f97d3bf789bfa7cd9d295d019396d85481a87fbuzbee                             int displacement, int rDest)
375d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng{
385d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    return loadBaseDisp(cUnit, NULL, rBase, displacement, rDest, kWord,
395d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                        INVALID_SREG);
405d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng}
415d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng
42e3f97d3bf789bfa7cd9d295d019396d85481a87fbuzbeestatic TGT_LIR *storeWordDisp(CompilationUnit *cUnit, int rBase,
435d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                             int displacement, int rSrc)
445d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng{
455d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    return storeBaseDisp(cUnit, rBase, displacement, rSrc, kWord);
465d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng}
475d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng
485d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng/*
495d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * Load a Dalvik register into a physical register.  Take care when
505d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * using this routine, as it doesn't perform any bookkeeping regarding
515d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * register liveness.  That is the responsibility of the caller.
525d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng */
535d90c20bd7903d7bba966b224e576bf137bf8b4bBen Chengstatic void loadValueDirect(CompilationUnit *cUnit, RegLocation rlSrc,
54e3f97d3bf789bfa7cd9d295d019396d85481a87fbuzbee                            int reg1)
555d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng{
56c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    rlSrc = dvmCompilerUpdateLoc(cUnit, rlSrc);
575d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    if (rlSrc.location == kLocPhysReg) {
585d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        genRegCopy(cUnit, reg1, rlSrc.lowReg);
595d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    } else  if (rlSrc.location == kLocRetval) {
60cf4a20cf0cbc53f03a5b16c7152bbb29907f7108buzbee        loadWordDisp(cUnit, rSELF, offsetof(Thread, interpSave.retval), reg1);
615d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    } else {
625d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        assert(rlSrc.location == kLocDalvikFrame);
63c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        loadWordDisp(cUnit, rFP, dvmCompilerS2VReg(cUnit, rlSrc.sRegLow) << 2,
645d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                     reg1);
655d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    }
665d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng}
675d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng
685d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng/*
695d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * Similar to loadValueDirect, but clobbers and allocates the target
705d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * register.  Should be used when loading to a fixed register (for example,
715d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * loading arguments to an out of line call.
725d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng */
735d90c20bd7903d7bba966b224e576bf137bf8b4bBen Chengstatic void loadValueDirectFixed(CompilationUnit *cUnit, RegLocation rlSrc,
745d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                                 int reg1)
755d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng{
76c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    dvmCompilerClobber(cUnit, reg1);
776a55513b0d268bc0721834050a3698316854fa0aElliott Hughes    dvmCompilerMarkInUse(cUnit, reg1);
785d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    loadValueDirect(cUnit, rlSrc, reg1);
795d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng}
805d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng
815d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng/*
825d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * Load a Dalvik register pair into a physical register[s].  Take care when
835d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * using this routine, as it doesn't perform any bookkeeping regarding
845d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * register liveness.  That is the responsibility of the caller.
855d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng */
865d90c20bd7903d7bba966b224e576bf137bf8b4bBen Chengstatic void loadValueDirectWide(CompilationUnit *cUnit, RegLocation rlSrc,
875d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                                int regLo, int regHi)
885d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng{
89c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    rlSrc = dvmCompilerUpdateLocWide(cUnit, rlSrc);
905d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    if (rlSrc.location == kLocPhysReg) {
915d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        genRegCopyWide(cUnit, regLo, regHi, rlSrc.lowReg, rlSrc.highReg);
925d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    } else if (rlSrc.location == kLocRetval) {
93cf4a20cf0cbc53f03a5b16c7152bbb29907f7108buzbee        loadBaseDispWide(cUnit, NULL, rSELF,
94cf4a20cf0cbc53f03a5b16c7152bbb29907f7108buzbee                         offsetof(Thread, interpSave.retval),
955d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                         regLo, regHi, INVALID_SREG);
965d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    } else {
975d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        assert(rlSrc.location == kLocDalvikFrame);
985d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            loadBaseDispWide(cUnit, NULL, rFP,
99c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee                             dvmCompilerS2VReg(cUnit, rlSrc.sRegLow) << 2,
1005d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                             regLo, regHi, INVALID_SREG);
1015d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    }
1025d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng}
1035d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng
1045d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng/*
1055d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * Similar to loadValueDirect, but clobbers and allocates the target
1065d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * registers.  Should be used when loading to a fixed registers (for example,
1075d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng * loading arguments to an out of line call.
1085d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng */
1095d90c20bd7903d7bba966b224e576bf137bf8b4bBen Chengstatic void loadValueDirectWideFixed(CompilationUnit *cUnit, RegLocation rlSrc,
1105d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                                     int regLo, int regHi)
1115d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng{
112c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    dvmCompilerClobber(cUnit, regLo);
113c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    dvmCompilerClobber(cUnit, regHi);
1146a55513b0d268bc0721834050a3698316854fa0aElliott Hughes    dvmCompilerMarkInUse(cUnit, regLo);
1156a55513b0d268bc0721834050a3698316854fa0aElliott Hughes    dvmCompilerMarkInUse(cUnit, regHi);
1165d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    loadValueDirectWide(cUnit, rlSrc, regLo, regHi);
1175d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng}
1185d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng
1195d90c20bd7903d7bba966b224e576bf137bf8b4bBen Chengstatic RegLocation loadValue(CompilationUnit *cUnit, RegLocation rlSrc,
1205d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                             RegisterClass opKind)
1215d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng{
122c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    rlSrc = dvmCompilerEvalLoc(cUnit, rlSrc, opKind, false);
1235d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    if (rlSrc.location == kLocDalvikFrame) {
1245d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        loadValueDirect(cUnit, rlSrc, rlSrc.lowReg);
1255d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        rlSrc.location = kLocPhysReg;
126c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        dvmCompilerMarkLive(cUnit, rlSrc.lowReg, rlSrc.sRegLow);
1275d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    } else if (rlSrc.location == kLocRetval) {
128cf4a20cf0cbc53f03a5b16c7152bbb29907f7108buzbee        loadWordDisp(cUnit, rSELF, offsetof(Thread, interpSave.retval),
129cf4a20cf0cbc53f03a5b16c7152bbb29907f7108buzbee                     rlSrc.lowReg);
1305d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        rlSrc.location = kLocPhysReg;
131c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        dvmCompilerClobber(cUnit, rlSrc.lowReg);
1325d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    }
1335d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    return rlSrc;
1345d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng}
1355d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng
1365d90c20bd7903d7bba966b224e576bf137bf8b4bBen Chengstatic void storeValue(CompilationUnit *cUnit, RegLocation rlDest,
1375d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                       RegLocation rlSrc)
1385d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng{
1395d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    LIR *defStart;
1405d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    LIR *defEnd;
1415d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    assert(!rlDest.wide);
1425d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    assert(!rlSrc.wide);
143c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    dvmCompilerKillNullCheckedLoc(cUnit, rlDest);
144c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    rlSrc = dvmCompilerUpdateLoc(cUnit, rlSrc);
145c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    rlDest = dvmCompilerUpdateLoc(cUnit, rlDest);
1465d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    if (rlSrc.location == kLocPhysReg) {
147c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        if (dvmCompilerIsLive(cUnit, rlSrc.lowReg) ||
148c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee            (rlDest.location == kLocPhysReg)) {
1495d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            // Src is live or Dest has assigned reg.
150c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee            rlDest = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, false);
1515d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            genRegCopy(cUnit, rlDest.lowReg, rlSrc.lowReg);
1525d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        } else {
1535d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            // Just re-assign the registers.  Dest gets Src's regs
1545d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            rlDest.lowReg = rlSrc.lowReg;
155c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee            dvmCompilerClobber(cUnit, rlSrc.lowReg);
1565d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        }
1575d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    } else {
1585d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        // Load Src either into promoted Dest or temps allocated for Dest
159c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        rlDest = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, false);
1605d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        loadValueDirect(cUnit, rlSrc, rlDest.lowReg);
1615d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    }
1625d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng
1635d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    // Dest is now live and dirty (until/if we flush it to home location)
164c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    dvmCompilerMarkLive(cUnit, rlDest.lowReg, rlDest.sRegLow);
165c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    dvmCompilerMarkDirty(cUnit, rlDest.lowReg);
1665d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng
1675d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng
1685d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    if (rlDest.location == kLocRetval) {
169cf4a20cf0cbc53f03a5b16c7152bbb29907f7108buzbee        storeBaseDisp(cUnit, rSELF, offsetof(Thread, interpSave.retval),
1705d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                      rlDest.lowReg, kWord);
171c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        dvmCompilerClobber(cUnit, rlDest.lowReg);
1725d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    } else {
173c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        dvmCompilerResetDefLoc(cUnit, rlDest);
174c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        if (dvmCompilerLiveOut(cUnit, rlDest.sRegLow)) {
1755d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            defStart = (LIR *)cUnit->lastLIRInsn;
176c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee            int vReg = dvmCompilerS2VReg(cUnit, rlDest.sRegLow);
1775d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            storeBaseDisp(cUnit, rFP, vReg << 2, rlDest.lowReg, kWord);
178c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee            dvmCompilerMarkClean(cUnit, rlDest.lowReg);
1795d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            defEnd = (LIR *)cUnit->lastLIRInsn;
180c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee            dvmCompilerMarkDef(cUnit, rlDest, defStart, defEnd);
1815d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        }
1825d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    }
1835d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng}
1845d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng
1855d90c20bd7903d7bba966b224e576bf137bf8b4bBen Chengstatic RegLocation loadValueWide(CompilationUnit *cUnit, RegLocation rlSrc,
1865d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                                 RegisterClass opKind)
1875d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng{
1885d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    assert(rlSrc.wide);
189c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    rlSrc = dvmCompilerEvalLoc(cUnit, rlSrc, opKind, false);
1905d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    if (rlSrc.location == kLocDalvikFrame) {
1915d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        loadValueDirectWide(cUnit, rlSrc, rlSrc.lowReg, rlSrc.highReg);
1925d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        rlSrc.location = kLocPhysReg;
193c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        dvmCompilerMarkLive(cUnit, rlSrc.lowReg, rlSrc.sRegLow);
194c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        dvmCompilerMarkLive(cUnit, rlSrc.highReg,
195c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee                            dvmCompilerSRegHi(rlSrc.sRegLow));
1965d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    } else if (rlSrc.location == kLocRetval) {
197cf4a20cf0cbc53f03a5b16c7152bbb29907f7108buzbee        loadBaseDispWide(cUnit, NULL, rSELF,
198cf4a20cf0cbc53f03a5b16c7152bbb29907f7108buzbee                         offsetof(Thread, interpSave.retval),
1995d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                         rlSrc.lowReg, rlSrc.highReg, INVALID_SREG);
2005d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        rlSrc.location = kLocPhysReg;
201c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        dvmCompilerClobber(cUnit, rlSrc.lowReg);
202c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        dvmCompilerClobber(cUnit, rlSrc.highReg);
2035d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    }
2045d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    return rlSrc;
2055d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng}
2065d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng
2075d90c20bd7903d7bba966b224e576bf137bf8b4bBen Chengstatic void storeValueWide(CompilationUnit *cUnit, RegLocation rlDest,
208e3f97d3bf789bfa7cd9d295d019396d85481a87fbuzbee                           RegLocation rlSrc)
2095d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng{
2105d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    LIR *defStart;
2115d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    LIR *defEnd;
2125d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    assert(FPREG(rlSrc.lowReg)==FPREG(rlSrc.highReg));
2135d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    assert(rlDest.wide);
2145d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    assert(rlSrc.wide);
215c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    dvmCompilerKillNullCheckedLoc(cUnit, rlDest);
2165d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    if (rlSrc.location == kLocPhysReg) {
217c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        if (dvmCompilerIsLive(cUnit, rlSrc.lowReg) ||
218c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee            dvmCompilerIsLive(cUnit, rlSrc.highReg) ||
2195d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            (rlDest.location == kLocPhysReg)) {
2205d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            // Src is live or Dest has assigned reg.
221c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee            rlDest = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, false);
2225d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            genRegCopyWide(cUnit, rlDest.lowReg, rlDest.highReg,
2235d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                           rlSrc.lowReg, rlSrc.highReg);
2245d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        } else {
2255d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            // Just re-assign the registers.  Dest gets Src's regs
2265d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            rlDest.lowReg = rlSrc.lowReg;
2275d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            rlDest.highReg = rlSrc.highReg;
228c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee            dvmCompilerClobber(cUnit, rlSrc.lowReg);
229c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee            dvmCompilerClobber(cUnit, rlSrc.highReg);
2305d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        }
2315d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    } else {
2325d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        // Load Src either into promoted Dest or temps allocated for Dest
233c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        rlDest = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, false);
2345d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        loadValueDirectWide(cUnit, rlSrc, rlDest.lowReg,
2355d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                            rlDest.highReg);
2365d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    }
2375d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng
2385d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    // Dest is now live and dirty (until/if we flush it to home location)
239c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    dvmCompilerMarkLive(cUnit, rlDest.lowReg, rlDest.sRegLow);
240c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    dvmCompilerMarkLive(cUnit, rlDest.highReg,
241c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee                        dvmCompilerSRegHi(rlDest.sRegLow));
242c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    dvmCompilerMarkDirty(cUnit, rlDest.lowReg);
243c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    dvmCompilerMarkDirty(cUnit, rlDest.highReg);
244c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee    dvmCompilerMarkPair(cUnit, rlDest.lowReg, rlDest.highReg);
2455d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng
2465d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng
2475d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    if (rlDest.location == kLocRetval) {
248cf4a20cf0cbc53f03a5b16c7152bbb29907f7108buzbee        storeBaseDispWide(cUnit, rSELF, offsetof(Thread, interpSave.retval),
2495d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                          rlDest.lowReg, rlDest.highReg);
250c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        dvmCompilerClobber(cUnit, rlDest.lowReg);
251c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        dvmCompilerClobber(cUnit, rlDest.highReg);
2525d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    } else {
253c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        dvmCompilerResetDefLocWide(cUnit, rlDest);
254c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee        if (dvmCompilerLiveOut(cUnit, rlDest.sRegLow) ||
255c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee            dvmCompilerLiveOut(cUnit, dvmCompilerSRegHi(rlDest.sRegLow))) {
2565d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            defStart = (LIR *)cUnit->lastLIRInsn;
257c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee            int vReg = dvmCompilerS2VReg(cUnit, rlDest.sRegLow);
258c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee            assert((vReg+1) == dvmCompilerS2VReg(cUnit,
259c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee                                     dvmCompilerSRegHi(rlDest.sRegLow)));
2605d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            storeBaseDispWide(cUnit, rFP, vReg << 2, rlDest.lowReg,
2615d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng                              rlDest.highReg);
262c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee            dvmCompilerMarkClean(cUnit, rlDest.lowReg);
263c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee            dvmCompilerMarkClean(cUnit, rlDest.highReg);
2645d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng            defEnd = (LIR *)cUnit->lastLIRInsn;
265c6f1066fd2dd761349128a9f422bc1ce3c3de595Bill Buzbee            dvmCompilerMarkDefWide(cUnit, rlDest, defStart, defEnd);
2665d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng        }
2675d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng    }
2685d90c20bd7903d7bba966b224e576bf137bf8b4bBen Cheng}
269