harmony-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mfur...@apache.org
Subject svn commit: r548326 - in /harmony/enhanced/drlvm/trunk/vm: jitrino/src/codegenerator/ia32/ jitrino/src/jet/ port/src/encoder/ia32_em64t/
Date Mon, 18 Jun 2007 11:34:10 GMT
Author: mfursov
Date: Mon Jun 18 04:34:08 2007
New Revision: 548326

URL: http://svn.apache.org/viewvc?view=rev&rev=548326
Log:
HARMONY-2092: fixes for volatile longs handling in Jitrino.OPT and Jitrino.JET jits with regression
test.
(previous commit was not done from the root folder)


Modified:
    harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32CopyExpansion.cpp
    harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32I8Lowerer.cpp
    harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32IRManager.cpp
    harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32IRManager.h
    harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32Inst.h
    harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32Printer.cpp
    harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/cg.h
    harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/cg_fld_arr.cpp
    harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/cg_regs.cpp
    harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/enc.h
    harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/enc_ia32.cpp
    harmony/enhanced/drlvm/trunk/vm/port/src/encoder/ia32_em64t/enc_defs.h
    harmony/enhanced/drlvm/trunk/vm/port/src/encoder/ia32_em64t/enc_tabl.cpp

Modified: harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32CopyExpansion.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32CopyExpansion.cpp?view=diff&rev=548326&r1=548325&r2=548326
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32CopyExpansion.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32CopyExpansion.cpp Mon
Jun 18 04:34:08 2007
@@ -367,7 +367,21 @@
             bool calculatingRegUsage = false;
             for (Inst * inst=(Inst*)node->getLastInst(), * nextInst=NULL; inst!=NULL;
inst=nextInst){
                 nextInst=inst->getPrevInst();
-                if (inst->hasKind(Inst::Kind_CopyPseudoInst)){
+                if (inst->hasKind(Inst::Kind_CMPXCHG8BPseudoInst)){
+                    Opnd* mem = inst->getOpnd(0);
+                    Opnd* base = mem->getMemOpndSubOpnd(MemOpndSubOpndKind_Base);
+                    Opnd* index = mem->getMemOpndSubOpnd(MemOpndSubOpndKind_Index);
+                    Opnd* scale = mem->getMemOpndSubOpnd(MemOpndSubOpndKind_Scale);
+                    Opnd* disp = mem->getMemOpndSubOpnd(MemOpndSubOpndKind_Displacement);
+
+                    Opnd* memCopy = irManager->newMemOpnd(mem->getType(), mem->getMemOpndKind(),
base, index, scale, disp);
+
+                    Inst* cmpxchg = irManager->newInst(Mnemonic_CMPXCHG8B, memCopy);
+                    if(inst->getPrefix() != InstPrefix_Null) {
+                        cmpxchg->setPrefix(inst->getPrefix());
+                    }
+                    cmpxchg->insertAfter(inst);
+                } else if (inst->hasKind(Inst::Kind_CopyPseudoInst)){
                     Mnemonic mn=inst->getMnemonic();
                     Inst *copySequence = NULL;
                     if (mn==Mnemonic_MOV){

Modified: harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32I8Lowerer.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32I8Lowerer.cpp?view=diff&rev=548326&r1=548325&r2=548326
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32I8Lowerer.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32I8Lowerer.cpp Mon Jun
18 04:34:08 2007
@@ -150,6 +150,17 @@
         return true;
     }
     /**
+     * performs original mnemonic action on the new operands
+     */
+    void applyMnemonic(Inst* inst, Opnd* dst,  Opnd* dst_1,   Opnd* dst_2,
+                                   Opnd* src1, Opnd* src1_1, Opnd* src1_2,
+                                   Opnd* src2, Opnd* src2_1, Opnd* src2_2);
+    /**
+     * check if the opnd is a volatile field of long type
+     */
+    bool I8Lowerer::isLongVolatileMemoryOpnd(Opnd* opnd);
+
+    /**
      * Points to the list of instructions to process.
      *
      * The pointer points to the local variable in runImpl();
@@ -344,144 +355,249 @@
         Opnd * src1 = useCount> 0 ? inst->getOpnd(defCount): NULL;
         Opnd * src2 = useCount> 1 ? inst->getOpnd(defCount+1): NULL;
 
-        if (mn!=Mnemonic_IDIV && mn!=Mnemonic_IMUL) {
-            if (dst)
-                prepareNewOpnds(dst, dst_1,dst_2);
-            if (src1)
-                prepareNewOpnds(src1, src1_1,src1_2);
-            if (src2)
-                prepareNewOpnds(src2, src2_1,src2_2);
-        }
+        bool dstIsLongVolatile = false;
 
-        switch(mn) {
-            case Mnemonic_ADD   :
-                assert(dst_1 && src1_1 && src2_1);
-                assert(dst_2 && src1_2 && src2_2);
-                irManager->newInstEx(Mnemonic_ADD, 1, dst_1, src1_1, src2_1)->insertBefore(inst);
-                irManager->newInstEx(Mnemonic_ADC, 1, dst_2, src1_2, src2_2)->insertBefore(inst);
-                inst->unlink();
-                break;
-            case Mnemonic_SUB   :
-                assert(dst_1 && src1_1 && src2_1);
-                assert(dst_2 && src1_2 && src2_2);
-                irManager->newInstEx(Mnemonic_SUB, 1, dst_1, src1_1, src2_1)->insertBefore(inst);
-                irManager->newInstEx(Mnemonic_SBB, 1, dst_2, src1_2, src2_2)->insertBefore(inst);
-                inst->unlink();
-                break;
-            case Mnemonic_AND   :
-            case Mnemonic_OR    :
-            case Mnemonic_XOR   :
-                assert(dst_1 && src1_1 && src2_1);
-                assert(dst_2 && src1_2 && src2_2);
-            case Mnemonic_NOT   :
-                assert(dst_1 && src1_1);
-                assert(dst_2 && src1_2);
-                irManager->newInstEx(mn, 1, dst_1, src1_1, src2_1)->insertBefore(inst);
-                irManager->newInstEx(mn, 1, dst_2, src1_2, src2_2)->insertBefore(inst);
-                inst->unlink();
-                break;
-            case Mnemonic_MOV   :
-                assert(dst_1 && src1_1);
-                irManager->newCopyPseudoInst(Mnemonic_MOV, dst_1, src1_1)->insertBefore(inst);
-                if (dst_2 && src1_2) {
-                    irManager->newCopyPseudoInst(Mnemonic_MOV, dst_2, src1_2)->insertBefore(inst);
-                }
-                inst->unlink();
-                break;
-            case Mnemonic_MOVSX :
-            case Mnemonic_MOVZX :
-                assert(dst_1 && dst_2 && src1_1);
-                assert(!src1_2);
-                if (src1_1->getSize()<OpndSize_32){
-                    irManager->newInstEx(mn, 1, dst_1, src1_1)->insertBefore(inst);
-                }else{
-                    assert(src1_1->getSize()==OpndSize_32);
-                    irManager->newInstEx(Mnemonic_MOV, 1, dst_1, src1_1)->insertBefore(inst);
-                }
-                if (mn==Mnemonic_MOVSX){
-                    // It's possible to substitute complex CDQ with a tight
-                    // constraints to the set of simpler instructions
-                    // with a wider constraints to let more freedom 
-                    // to regalloc and constraint resolver.
-                    // However, this seems does not change anything currently,
-                    // so leaving as-is.
-                    //test 	    low, low
-                    //setns 	hi		; if lo is positive, then load 1 into hi
-                    //sub		hi, 1	; if lo is positive, then hi is now '0'. otherwise, it's
-1
-                    irManager->newInstEx(Mnemonic_CDQ, 1, dst_2, dst_1)->insertBefore(inst);
+        if (mn!=Mnemonic_IDIV && mn!=Mnemonic_IMUL) {
+            if (dst) {
+                if(isLongVolatileMemoryOpnd(dst)) {
+                    // temporary dst placed on stack will be used in the original instruction
+                    dstIsLongVolatile = true;
+                    Type* typeInt32 = irManager->getTypeManager().getInt32Type();
+                    Type* typeUInt32 = irManager->getTypeManager().getUInt32Type();
+                    dst_2 = irManager->newOpnd(typeInt32, Constraint(RegName_EDX));
+                    dst_1 = irManager->newOpnd(typeUInt32, Constraint(RegName_EAX));
                 } else {
-                    //fill upper word with 0
-                    assert(mn == Mnemonic_MOVZX);
-                    Opnd* imm0=irManager->newImmOpnd(irManager->getTypeManager().getInt32Type(),
0);
-                    irManager->newInstEx(Mnemonic_MOV, 1, dst_2, imm0)->insertBefore(inst);
+                    prepareNewOpnds(dst,dst_1,dst_2);
                 }
-                inst->unlink();
-                break;
-            case Mnemonic_PUSH  :
-                assert(src1_1);
-                assert(src1_2);
-                irManager->newInstEx(Mnemonic_PUSH, 0, src1_2)->insertBefore(inst);
-                irManager->newInstEx(Mnemonic_PUSH, 0, src1_1)->insertBefore(inst);
-                inst->unlink();
-                break;
-            case Mnemonic_POP   :
-                assert(dst_1);
-                assert(dst_2);
-                irManager->newInstEx(Mnemonic_POP, 1, dst_1)->insertBefore(inst);
-                irManager->newInstEx(Mnemonic_POP, 1, dst_2)->insertBefore(inst);
-                inst->unlink();
-                break;
-            case Mnemonic_SHL   :
-            {
-                assert(dst && src1 && src2);
-                buildShiftSubGraph(inst, src1_2, src1_1, src2, dst_2, dst_1, mn, Mnemonic_SHR);
-                inst->unlink();
-                break;
-            }
-            case Mnemonic_SHR   :
-            case Mnemonic_SAR   :
-            {
-                assert(dst && src1 && src2);
-                buildShiftSubGraph(inst, src1_1, src1_2, src2, dst_1, dst_2, mn, Mnemonic_SHL);
-                inst->unlink();
-                break;
             }
-            case Mnemonic_CMP   :
-            {
-                assert(src1 && src2);
-                Inst * condInst = inst->getNextInst();
-                while (condInst && condInst->getMnemonic() == Mnemonic_MOV) {
-                    condInst = condInst->getNextInst();
-                }
-                Mnemonic mnem = condInst ? getBaseConditionMnemonic(condInst->getMnemonic())
: Mnemonic_NULL;
-                if (mnem != Mnemonic_NULL) {
-                            if(condInst->hasKind(Inst::Kind_BranchInst)) {
-                                compareAndBranch(inst,src1_1,src1_2,src2_1,src2_2,condInst);
-                            } else {
-                                buildSetSubGraph(inst,src1_1,src1_2,src2_1,src2_2,condInst);
-                            }
+            if (src1) {
+                if(isLongVolatileMemoryOpnd(src1)) {
+                    // prepare gp regs for CMPXCHG8B
+                    Type* typeInt32 = irManager->getTypeManager().getInt32Type();
+                    Type* typeUInt32 = irManager->getTypeManager().getUInt32Type();
+                    Opnd* edx = irManager->newOpnd(typeInt32, Constraint(RegName_EDX));
+                    Opnd* eax = irManager->newOpnd(typeUInt32, Constraint(RegName_EAX));
+                    Opnd* ecx = irManager->newOpnd(typeInt32, Constraint(RegName_ECX));
+                    Opnd* ebx = irManager->newOpnd(typeUInt32, Constraint(RegName_EBX));
+                    Opnd* zero = irManager->newImmOpnd(typeInt32, 0);
+
+                    irManager->newCopyPseudoInst(Mnemonic_MOV, edx, zero)->insertBefore(inst);
+                    irManager->newCopyPseudoInst(Mnemonic_MOV, eax, zero)->insertBefore(inst);
+                    irManager->newCopyPseudoInst(Mnemonic_MOV, ecx, edx)->insertBefore(inst);
+                    irManager->newCopyPseudoInst(Mnemonic_MOV, ebx, eax)->insertBefore(inst);
+
+                    // read src1 -> EDX:EAX regs using CMPXCHG8B inst
+                    Inst* cmpxchg = irManager->newCMPXCHG8BPseudoInst(src1,edx,eax,ecx,ebx);
+                    cmpxchg->setPrefix(InstPrefix_LOCK);
+                    cmpxchg->insertBefore(inst);
+
+                    // let src1_1:src1_2 be EAX:EDX 
+                    src1_1 = eax;
+                    src1_2 = edx;
                 } else {
-                    buildComplexSubGraph(inst,src1_1,src1_2,src2_1,src2_2);
+                    prepareNewOpnds(src1,src1_1,src1_2);
                 }
-                inst->unlink();
-                break;
             }
-            case Mnemonic_IMUL:
-                lowerMul64(inst);
-                break;
-            case Mnemonic_IDIV:
-                if (isI8RemInst(inst)) {
-                    lowerRem64(inst);
-                }
-                else {
-                    lowerDiv64(inst);
+            if (src2) {
+                if(isLongVolatileMemoryOpnd(src2)) {
+                    // prepare gp regs for CMPXCHG8B
+                    Type* typeInt32 = irManager->getTypeManager().getInt32Type();
+                    Type* typeUInt32 = irManager->getTypeManager().getUInt32Type();
+                    Opnd* edx = irManager->newOpnd(typeInt32, Constraint(RegName_EDX));
+                    Opnd* eax = irManager->newOpnd(typeUInt32, Constraint(RegName_EAX));
+                    Opnd* ecx = irManager->newOpnd(typeInt32, Constraint(RegName_ECX));
+                    Opnd* ebx = irManager->newOpnd(typeUInt32, Constraint(RegName_EBX));
+                    Opnd* zero = irManager->newImmOpnd(typeInt32, 0);
+
+                    irManager->newCopyPseudoInst(Mnemonic_MOV, edx, zero)->insertBefore(inst);
+                    irManager->newCopyPseudoInst(Mnemonic_MOV, eax, zero)->insertBefore(inst);
+                    irManager->newCopyPseudoInst(Mnemonic_MOV, ecx, edx)->insertBefore(inst);
+                    irManager->newCopyPseudoInst(Mnemonic_MOV, ebx, eax)->insertBefore(inst);
+
+                    // read src2 -> EDX:EAX regs using CMPXCHG8B inst
+                    Inst* cmpxchg = irManager->newCMPXCHG8BPseudoInst(src2,edx,eax,ecx,ebx);
+                    cmpxchg->setPrefix(InstPrefix_LOCK);
+                    cmpxchg->insertBefore(inst);
+                    // let src2_1:src2_2 be EAX:EDX 
+                    src2_1 = eax;
+                    src2_2 = edx;
+                } else {
+                    prepareNewOpnds(src2,src2_1,src2_2);
                 }
-                break;
-            default :   
-                assert(0);
-        }//end switch by mnemonics
+            }
+        }
+
+        applyMnemonic(inst,dst,dst_1,dst_2,src1,src1_1,src1_2,src2,src2_1,src2_2);
+
+        if(dstIsLongVolatile) {
+            // prepare gp regs for CMPXCHG8B
+            Type* typeInt32 = irManager->getTypeManager().getInt32Type();
+            Type* typeUInt32 = irManager->getTypeManager().getUInt32Type();
+            Opnd* ecx = irManager->newOpnd(typeInt32, Constraint(RegName_ECX));
+            Opnd* ebx = irManager->newOpnd(typeUInt32, Constraint(RegName_EBX));
+
+            irManager->newCopyPseudoInst(Mnemonic_MOV, ecx, dst_2)->insertBefore(inst);
+            irManager->newCopyPseudoInst(Mnemonic_MOV, ebx, dst_1)->insertBefore(inst);
+
+            ControlFlowGraph * fg = irManager->getFlowGraph();
+            Node* prevNode = inst->getNode();
+            Node* nextNode = fg->splitNodeAtInstruction(inst, true, true, NULL);
+            Node* loopNode = fg->createNode(Node::Kind_Block);
+            Edge* prevOut = prevNode->getOutEdges().front();
+            fg->replaceEdgeTarget(prevOut, loopNode);
+
+            // write ECX:EBX -> dst using CMPXCHG8B inst
+            Inst* cmpxchg = irManager->newCMPXCHG8BPseudoInst(dst,dst_2,dst_1,ecx,ebx);
+            cmpxchg->setPrefix(InstPrefix_LOCK);
+            loopNode->appendInst(cmpxchg);
+            loopNode->appendInst(irManager->newBranchInst(Mnemonic_JNZ, loopNode, nextNode));
+
+            fg->addEdge(loopNode, loopNode, 0.5);
+            fg->addEdge(loopNode, nextNode, 0.5);
+        }
+
+        inst->unlink();
     }
 }
+
+bool I8Lowerer::isLongVolatileMemoryOpnd(Opnd* opnd) {
+
+    if ( isI8Type(opnd->getType()) ) {
+        Opnd* disp = opnd->isPlacedIn(OpndKind_Memory) ? opnd->getMemOpndSubOpnd(MemOpndSubOpndKind_Displacement)
: NULL;
+        Opnd::RuntimeInfo* ri = (disp == NULL) ? NULL : disp->getRuntimeInfo();
+        Opnd::RuntimeInfo::Kind riKind = (ri == NULL) ? Opnd::RuntimeInfo::Kind_Null : ri->getKind();
+        return (riKind == Opnd::RuntimeInfo::Kind_FieldOffset ||
+                riKind == Opnd::RuntimeInfo::Kind_StaticFieldAddress) &&
+               ((FieldDesc*)disp->getRuntimeInfo()->getValue(0))->isVolatile();
+    } else {
+        return false;
+    }
+}
+
+
+void I8Lowerer::applyMnemonic(Inst* inst, Opnd* dst,  Opnd* dst_1,  Opnd* dst_2,
+                                          Opnd* src1, Opnd* src1_1, Opnd* src1_2,
+                                          Opnd* src2, Opnd* src2_1, Opnd* src2_2)
+{
+    Mnemonic mn = inst->getMnemonic();
+    switch(mn) {
+        case Mnemonic_ADD   :
+            assert(dst_1 && src1_1 && src2_1);
+            assert(dst_2 && src1_2 && src2_2);
+            irManager->newInstEx(Mnemonic_ADD, 1, dst_1, src1_1, src2_1)->insertBefore(inst);
+            irManager->newInstEx(Mnemonic_ADC, 1, dst_2, src1_2, src2_2)->insertBefore(inst);
+            break;
+        case Mnemonic_SUB   :
+            assert(dst_1 && src1_1 && src2_1);
+            assert(dst_2 && src1_2 && src2_2);
+            irManager->newInstEx(Mnemonic_SUB, 1, dst_1, src1_1, src2_1)->insertBefore(inst);
+            irManager->newInstEx(Mnemonic_SBB, 1, dst_2, src1_2, src2_2)->insertBefore(inst);
+            break;
+        case Mnemonic_AND   :
+        case Mnemonic_OR    :
+        case Mnemonic_XOR   :
+            assert(dst_1 && src1_1 && src2_1);
+            assert(dst_2 && src1_2 && src2_2);
+        case Mnemonic_NOT   :
+            assert(dst_1 && src1_1);
+            assert(dst_2 && src1_2);
+            irManager->newInstEx(mn, 1, dst_1, src1_1, src2_1)->insertBefore(inst);
+            irManager->newInstEx(mn, 1, dst_2, src1_2, src2_2)->insertBefore(inst);
+            break;
+        case Mnemonic_MOV   :
+            assert(dst_1 && src1_1);
+            irManager->newCopyPseudoInst(Mnemonic_MOV, dst_1, src1_1)->insertBefore(inst);
+            if (dst_2 && src1_2) {
+                irManager->newCopyPseudoInst(Mnemonic_MOV, dst_2, src1_2)->insertBefore(inst);
+            }
+            break;
+        case Mnemonic_MOVSX :
+        case Mnemonic_MOVZX :
+            assert(dst_1 && dst_2 && src1_1);
+            assert(!src1_2);
+            if (src1_1->getSize()<OpndSize_32){
+                irManager->newInstEx(mn, 1, dst_1, src1_1)->insertBefore(inst);
+            }else{
+                assert(src1_1->getSize()==OpndSize_32);
+                irManager->newInstEx(Mnemonic_MOV, 1, dst_1, src1_1)->insertBefore(inst);
+            }
+            if (mn==Mnemonic_MOVSX){
+                // It's possible to substitute complex CDQ with a tight
+                // constraints to the set of simpler instructions
+                // with a wider constraints to let more freedom 
+                // to regalloc and constraint resolver.
+                // However, this seems does not change anything currently,
+                // so leaving as-is.
+                //test 	    low, low
+                //setns 	hi		; if lo is positive, then load 1 into hi
+                //sub		hi, 1	; if lo is positive, then hi is now '0'. otherwise, it's -1
+                irManager->newInstEx(Mnemonic_CDQ, 1, dst_2, dst_1)->insertBefore(inst);
+            } else {
+                //fill upper word with 0
+                assert(mn == Mnemonic_MOVZX);
+                Opnd* imm0=irManager->newImmOpnd(irManager->getTypeManager().getInt32Type(),
0);
+                irManager->newInstEx(Mnemonic_MOV, 1, dst_2, imm0)->insertBefore(inst);
+            }
+            break;
+        case Mnemonic_PUSH  :
+            assert(src1_1);
+            assert(src1_2);
+            irManager->newInstEx(Mnemonic_PUSH, 0, src1_2)->insertBefore(inst);
+            irManager->newInstEx(Mnemonic_PUSH, 0, src1_1)->insertBefore(inst);
+            break;
+        case Mnemonic_POP   :
+            assert(dst_1);
+            assert(dst_2);
+            irManager->newInstEx(Mnemonic_POP, 1, dst_1)->insertBefore(inst);
+            irManager->newInstEx(Mnemonic_POP, 1, dst_2)->insertBefore(inst);
+            break;
+        case Mnemonic_SHL   :
+        {
+            assert(dst && src1 && src2);
+            buildShiftSubGraph(inst, src1_2, src1_1, src2, dst_2, dst_1, mn, Mnemonic_SHR);
+            break;
+        }
+        case Mnemonic_SHR   :
+        case Mnemonic_SAR   :
+        {
+            assert(dst && src1 && src2);
+            buildShiftSubGraph(inst, src1_1, src1_2, src2, dst_1, dst_2, mn, Mnemonic_SHL);
+            break;
+        }
+        case Mnemonic_CMP   :
+        {
+            assert(src1 && src2);
+            Inst * condInst = inst->getNextInst();
+            while (condInst && condInst->getMnemonic() == Mnemonic_MOV) {
+                condInst = condInst->getNextInst();
+            }
+            Mnemonic mnem = condInst ? getBaseConditionMnemonic(condInst->getMnemonic())
: Mnemonic_NULL;
+            if (mnem != Mnemonic_NULL) {
+                        if(condInst->hasKind(Inst::Kind_BranchInst)) {
+                            compareAndBranch(inst,src1_1,src1_2,src2_1,src2_2,condInst);
+                        } else {
+                            buildSetSubGraph(inst,src1_1,src1_2,src2_1,src2_2,condInst);
+                        }
+            } else {
+                buildComplexSubGraph(inst,src1_1,src1_2,src2_1,src2_2);
+            }
+            break;
+        }
+        case Mnemonic_IMUL:
+            lowerMul64(inst);
+            break;
+        case Mnemonic_IDIV:
+            if (isI8RemInst(inst)) {
+                lowerRem64(inst);
+            }
+            else {
+                lowerDiv64(inst);
+            }
+            break;
+        default :   
+            assert(0);
+    }
+} // applyMnemonic
 
 void I8Lowerer::buildShiftSubGraph(Inst * inst, Opnd * src1_1, Opnd * src1_2, Opnd * src2,
Opnd * dst_1, Opnd * dst_2, Mnemonic mnem, Mnemonic opMnem) {
     Opnd * dst1_1 = irManager->newOpnd(dst_2->getType()), 

Modified: harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32IRManager.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32IRManager.cpp?view=diff&rev=548326&r1=548325&r2=548326
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32IRManager.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32IRManager.cpp Mon Jun
18 04:34:08 2007
@@ -640,6 +640,40 @@
 }
 
 //_________________________________________________________________________________________________
+CMPXCHG8BPseudoInst * IRManager::newCMPXCHG8BPseudoInst(Opnd* mem, Opnd* edx, Opnd* eax,
Opnd* ecx, Opnd* ebx)
+{ 
+    CMPXCHG8BPseudoInst* inst = new  (memoryManager, 8) CMPXCHG8BPseudoInst(instId++);
+
+    Opnd** opnds = inst->getOpnds();
+    Constraint* opndConstraints = inst->getConstraints();
+
+    // we do not set mem as a use in the inst
+    // just to cheat cg::verifier (see IRManager::verifyOpnds() function)
+    opnds[0] = mem;
+    opnds[1] = edx;
+    opnds[2] = eax;
+    opnds[3] = getRegOpnd(RegName_EFLAGS);
+    opnds[4] = edx;
+    opnds[5] = eax;
+    opnds[6] = ecx;
+    opnds[7] = ebx;
+    opndConstraints[0] = Constraint(OpndKind_Memory, OpndSize_64);
+    opndConstraints[1] = Constraint(RegName_EDX);
+    opndConstraints[2] = Constraint(RegName_EAX);
+    opndConstraints[3] = Constraint(RegName_EFLAGS);
+    opndConstraints[4] = Constraint(RegName_EDX);
+    opndConstraints[5] = Constraint(RegName_EAX);
+    opndConstraints[6] = Constraint(RegName_ECX);
+    opndConstraints[7] = Constraint(RegName_EBX);
+
+    inst->opndCount = 8;
+    inst->defOpndCount = 4;
+
+    inst->assignOpcodeGroup(this);
+    return inst;
+}
+
+//_________________________________________________________________________________________________
 Inst * IRManager::newCopyPseudoInst(Mnemonic mn, Opnd * opnd0, Opnd * opnd1)
 { 
     assert(mn==Mnemonic_MOV||mn==Mnemonic_PUSH||mn==Mnemonic_POP);

Modified: harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32IRManager.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32IRManager.h?view=diff&rev=548326&r1=548325&r2=548326
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32IRManager.h (original)
+++ harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32IRManager.h Mon Jun
18 04:34:08 2007
@@ -223,6 +223,8 @@
     AliasPseudoInst * newAliasPseudoInst(Opnd * targetOpnd, Opnd * sourceOpnd, uint32 offset);
     AliasPseudoInst * newAliasPseudoInst(Opnd * targetOpnd, uint32 sourceOpndCount, Opnd
** sourceOpnds);
 
+    CMPXCHG8BPseudoInst * newCMPXCHG8BPseudoInst(Opnd* mem, Opnd* edx, Opnd* eax, Opnd* ecx,
Opnd* ebx);
+
     CatchPseudoInst * newCatchPseudoInst(Opnd * exception);
 
     Inst * newI8PseudoInst(Mnemonic mnemonic, uint32 defCount,

Modified: harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32Inst.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32Inst.h?view=diff&rev=548326&r1=548325&r2=548326
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32Inst.h (original)
+++ harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32Inst.h Mon Jun 18 04:34:08
2007
@@ -409,26 +409,27 @@
     */
     enum Kind
     {
-        Kind_Inst=0x7fffffff,
-        Kind_PseudoInst=0x7ff00000,
-            Kind_EntryPointPseudoInst=0x40000000,
-            Kind_AliasPseudoInst=0x20000000,
-            Kind_CatchPseudoInst=0x10000000,
-            Kind_CopyPseudoInst=0x01000000,
-            Kind_I8PseudoInst=0x02000000,
-            Kind_GCInfoPseudoInst=0x04000000,
-            Kind_SystemExceptionCheckPseudoInst=0x08000000,
-            Kind_MethodEntryPseudoInst=0x00100000,
-            Kind_MethodEndPseudoInst=0x00200000,
-            Kind_EmptyPseudoInst=0x00400000,
-        Kind_ControlTransferInst=0x0000fff0,
-            Kind_LocalControlTransferInst=0x000003F0,
-            Kind_JmpInst=0x00000200,
-            Kind_BranchInst=0x000001C0,
-            Kind_SwitchInst=0x00000030,
-            Kind_InterProceduralControlTransferInst=0x0000fc00,
-                Kind_CallInst=0x00000f000,
-                Kind_RetInst=0x000000c00,
+        Kind_Inst = 0x7fffffff,
+        Kind_PseudoInst                         = 0x7ff00000,
+            Kind_MethodEntryPseudoInst          = 0x00100000,
+            Kind_MethodEndPseudoInst            = 0x00200000,
+            Kind_EmptyPseudoInst                = 0x00400000,
+            Kind_CMPXCHG8BPseudoInst            = 0x00800000,
+            Kind_CopyPseudoInst                 = 0x01000000,
+            Kind_I8PseudoInst                   = 0x02000000,
+            Kind_GCInfoPseudoInst               = 0x04000000,
+            Kind_SystemExceptionCheckPseudoInst = 0x08000000,
+            Kind_CatchPseudoInst                = 0x10000000,
+            Kind_AliasPseudoInst                = 0x20000000,
+            Kind_EntryPointPseudoInst           = 0x40000000,
+        Kind_ControlTransferInst                    = 0x0000fff0,
+            Kind_LocalControlTransferInst           = 0x000003F0,
+            Kind_JmpInst                            = 0x00000200,
+            Kind_BranchInst                         = 0x000001C0,
+            Kind_SwitchInst                         = 0x00000030,
+            Kind_InterProceduralControlTransferInst = 0x0000fc00,
+                Kind_CallInst                       = 0x0000f000,
+                Kind_RetInst                        = 0x00000c00,
     };
 
     /** Misc properties of an instruction */
@@ -945,6 +946,22 @@
 
 };
 
+
+//=========================================================================================================
+//   class CMPXCHG8BPseudoInst
+//=========================================================================================================
+/**
+    Class CMPXCHG8BPseudoInst represents ...
+*/
+class CMPXCHG8BPseudoInst: public Inst
+{
+protected:
+    CMPXCHG8BPseudoInst(int id)  
+        : Inst(Mnemonic_NULL, id, Inst::Form_Extended)
+    {kind=Kind_CMPXCHG8BPseudoInst;}
+
+    friend class    IRManager;
+};
 
 //=========================================================================================================
 //   class AliasPseudoInst

Modified: harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32Printer.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32Printer.cpp?view=diff&rev=548326&r1=548325&r2=548326
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32Printer.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/jitrino/src/codegenerator/ia32/Ia32Printer.cpp Mon Jun
18 04:34:08 2007
@@ -275,6 +275,7 @@
         case Inst::Kind_MethodEntryPseudoInst: return "MethodEntryPseudoInst";
         case Inst::Kind_MethodEndPseudoInst: return "MethodEndPseudoInst";
         case Inst::Kind_EmptyPseudoInst: return "EmptyPseudoInst";
+        case Inst::Kind_CMPXCHG8BPseudoInst: return "CMPXCHG8BPseudoInst";
         default: return "";
     }
 }

Modified: harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/cg.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/cg.h?view=diff&rev=548326&r1=548325&r2=548326
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/cg.h (original)
+++ harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/cg.h Mon Jun 18 04:34:08 2007
@@ -637,6 +637,10 @@
      */
     AR      valloc(jtype jt);
     /**
+     * @brief spills ar register. after the call ar is free for use. 
+     */
+    void    freeReg(AR ar);
+    /**
      * @brief Ensures operand stack item at the given \c depth resides in 
      * the memory.
      */

Modified: harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/cg_fld_arr.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/cg_fld_arr.cpp?view=diff&rev=548326&r1=548325&r2=548326
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/cg_fld_arr.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/cg_fld_arr.cpp Mon Jun 18 04:34:08 2007
@@ -342,9 +342,31 @@
         }
         else {
             if (is_big(jt)){
-                Opnd where_hi(jt, where.base(), where.disp()+4, 
-                                  where.index(), where.scale());
-                vpush2(where, where_hi);
+                // if in lazy resolution mode the field may be not resolved
+                // it is pessimistically considered as a volatile one.
+                if ( (!fieldOp.fld) || field_is_volatile(fieldOp.fld) ) {
+                    // prepare address
+                    freeReg(gr4); // ESI
+                    lea(gr4,where);
+
+                    // release gp regs used by cmpxchg8b
+                    freeReg(gr0); // EAX
+                    freeReg(gr1); // EBX
+                    freeReg(gr2); // ECX
+                    freeReg(gr3); // EDX
+
+                    // place for loading value (EDX:EAX)
+                    Opnd eax = Opnd(jt, gr0);
+                    Opnd edx = Opnd(jt, gr3);
+
+                    // read the field
+                    cmpxchg8b(true, gr4);
+                    vpush2(eax, edx);
+                } else {
+                    Opnd where_hi(jt, where.base(), where.disp()+4, 
+                                      where.index(), where.scale());
+                    vpush2(where, where_hi);
+                }
             }
             else {
                 vpush(where);
@@ -390,14 +412,44 @@
     }
     else {
         vunref(jt, where);
-        Val& val = vstack(0, vis_mem(0));
-        do_mov(where, val, fieldIsMagic);
-        if (is_big(jt)) {
-            Opnd where_hi(jt, where.base(), where.disp()+4, 
-                              where.index(), where.scale());
-            vunref(jt, where_hi);
-            Opnd val_hi = vstack(1, vis_mem(1)).as_opnd();
-            do_mov(where_hi, val_hi);
+        // if in lazy resolution mode the field may be not resolved
+        // it is pessimistically considered as a volatile one.
+        if (is_big(jt) &&
+           ((!fieldOp.fld) || field_is_volatile(fieldOp.fld))) {
+            Val& val = vstack(0);
+            Val& val_hi = vstack(1);
+
+            // prepare address
+            freeReg(gr4); // ESI
+            lea(gr4,where);
+
+            // prepare the value being stored
+            Opnd ecx = Opnd(i32, gr2);
+            Opnd ebx = Opnd(i32, gr1);
+            freeReg(gr1); // EBX
+            freeReg(gr2); // ECX
+            mov(ecx, val_hi.as_opnd());
+            mov(ebx, val.as_opnd());
+
+            // release EDX:EAX (they are rewritten by cmpxchg8b)
+            freeReg(gr0); // EAX
+            freeReg(gr3); // EDX
+
+            // the loop to write value to the field
+            unsigned _loop = ipoff();
+            cmpxchg8b(true, gr4);
+            unsigned br_off = br(nz, 0, 0);
+            patch(br_off, ip(_loop));
+        } else {
+            Val& val = vstack(0, vis_mem(0));
+            do_mov(where, val);
+            if (is_big(jt)) {
+                Opnd where_hi(jt, where.base(), where.disp()+4, 
+                                  where.index(), where.scale());
+                vunref(jt, where_hi);
+                Opnd val_hi = vstack(1, vis_mem(1)).as_opnd();
+                do_mov(where_hi, val_hi);
+            }
         }
     }
     

Modified: harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/cg_regs.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/cg_regs.cpp?view=diff&rev=548326&r1=548325&r2=548326
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/cg_regs.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/cg_regs.cpp Mon Jun 18 04:34:08 2007
@@ -102,8 +102,6 @@
     assert(min_idx != NOTHING);
     
     AR ar = _ar(min_idx);
-    if (is_set(DBG_TRACE_CG)) { dbg(";;>spill %s\n", to_str(ar).c_str()); }
-    // Where to spill:
      
 #if 0 // TODO: checkit
     // How about scratch registers of other kind ?
@@ -136,9 +134,16 @@
 #endif // if 0
 
     // Ugh... No way out, have to spill to the memory...
+
+    freeReg(ar);
     
-    // Now, update the things
-    
+    return ar;
+}
+
+void CodeGen::freeReg(AR ar)
+{
+    if (is_set(DBG_TRACE_CG)) { dbg(";;>spill %s\n", to_str(ar).c_str()); }
+     
     // First, free out the stack items, which are the register
     for (unsigned i=0; i<m_jframe->size(); i++) {
         Val& s = m_jframe->dip(i);
@@ -184,7 +189,6 @@
         pop(stk);
     }
     if (is_set(DBG_TRACE_CG)) { dbg(";;>~spill\n"); }
-    return ar;
 }
 
 Val& CodeGen::vstack(unsigned depth, bool toReg)

Modified: harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/enc.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/enc.h?view=diff&rev=548326&r1=548325&r2=548326
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/enc.h (original)
+++ harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/enc.h Mon Jun 18 04:34:08 2007
@@ -1031,6 +1031,17 @@
     }
 
     /**
+    * Generates CMPXCHG8B operation.
+    */
+    void cmpxchg8b(bool lockPrefix, AR addrBaseReg)
+    {
+        if (is_trace_on()) {
+            trace(string("cmpxchg8b:"), string(lockPrefix ? "(locked) ":""),  to_str(addrBaseReg));
+        }
+        cmpxchg8b_impl(lockPrefix,addrBaseReg);
+    }
+
+    /**
      * Generates ALU operation between two registers.
      *
      * The registers are used as \c jt type.
@@ -1459,6 +1470,8 @@
     void cmovcc_impl(COND c, const Opnd& op0, const Opnd& op1);
     /// Implementation of cmpxchg().
     void cmpxchg_impl(bool lockPrefix, AR addrReg, AR newReg, AR oldReg);
+    /// Implementation of cmpxchg8b().
+    void cmpxchg8b_impl(bool lockPrefix, AR addrReg);
     /// Implementation of lea().
     void lea_impl(const Opnd& reg, const Opnd& mem);
     /// Implementation of movp().

Modified: harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/enc_ia32.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/enc_ia32.cpp?view=diff&rev=548326&r1=548325&r2=548326
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/enc_ia32.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/jitrino/src/jet/enc_ia32.cpp Mon Jun 18 04:34:08 2007
@@ -728,6 +728,19 @@
 
 }
 
+void Encoder::cmpxchg8b_impl(bool lockPrefix, AR addrReg) {
+
+    if (lockPrefix) {
+        ip(EncoderBase::prefix(ip(), InstPrefix_LOCK));
+    }
+
+    RegName dAddrReg = devirt(addrReg);
+    EncoderBase::Operands args;
+    args.add(EncoderBase::Operand(OpndSize_64, dAddrReg, 0));
+    ip(EncoderBase::encode(ip(), Mnemonic_CMPXCHG8B, args));
+
+}
+
 void Encoder::lea_impl(const Opnd& reg, const Opnd& mem)
 {
     EncoderBase::Operands args;

Modified: harmony/enhanced/drlvm/trunk/vm/port/src/encoder/ia32_em64t/enc_defs.h
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/port/src/encoder/ia32_em64t/enc_defs.h?view=diff&rev=548326&r1=548325&r2=548326
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/port/src/encoder/ia32_em64t/enc_defs.h (original)
+++ harmony/enhanced/drlvm/trunk/vm/port/src/encoder/ia32_em64t/enc_defs.h Mon Jun 18 04:34:08
2007
@@ -434,6 +434,7 @@
 
 Mnemonic_CMP,                           // Compare Two Operands
 Mnemonic_CMPXCHG,                       // Compare and exchange
+Mnemonic_CMPXCHG8B,                     // Compare and Exchange 8 Bytes
 //
 // double -> float
 Mnemonic_CVTSD2SS,                      // Convert Scalar Double-Precision Floating-Point
Value to Scalar Single-Precision Floating-Point Value
@@ -454,8 +455,6 @@
 // int32 -> float
 Mnemonic_CVTSI2SS,                      // Convert Doubleword Integer to Scalar Single-Precision
Floating-Point Value
 
-//Mnemonic_CMPXCHG,                     // Compare and Exchange
-//Mnemonic_CMPXCHG8B,                   // Compare and Exchange 8 Bytes
 Mnemonic_COMISD,                        // Compare Scalar Ordered Double-Precision Floating-Point
Values and Set EFLAGS
 Mnemonic_COMISS,                        // Compare Scalar Ordered Single-Precision Floating-Point
Values and Set EFLAGS
 Mnemonic_DEC,                           // Decrement by 1

Modified: harmony/enhanced/drlvm/trunk/vm/port/src/encoder/ia32_em64t/enc_tabl.cpp
URL: http://svn.apache.org/viewvc/harmony/enhanced/drlvm/trunk/vm/port/src/encoder/ia32_em64t/enc_tabl.cpp?view=diff&rev=548326&r1=548325&r2=548326
==============================================================================
--- harmony/enhanced/drlvm/trunk/vm/port/src/encoder/ia32_em64t/enc_tabl.cpp (original)
+++ harmony/enhanced/drlvm/trunk/vm/port/src/encoder/ia32_em64t/enc_tabl.cpp Mon Jun 18 04:34:08
2007
@@ -429,6 +429,12 @@
 END_OPCODES()
 END_MNEMONIC()
  
+BEGIN_MNEMONIC(CMPXCHG8B, MF_AFFECTS_FLAGS, D)
+BEGIN_OPCODES()
+    {OpcodeInfo::all, {0x0F, 0xC7, _1},         {m64},     DU },
+END_OPCODES()
+END_MNEMONIC()
+ 
 
 #undef DEFINE_ALU_OPCODES
 //



Mime
View raw message