Index: vm/jitrino/src/codegenerator/ia32/Ia32Inst.h =================================================================== --- vm/jitrino/src/codegenerator/ia32/Ia32Inst.h (revision 546740) +++ vm/jitrino/src/codegenerator/ia32/Ia32Inst.h (working copy) @@ -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 */ @@ -947,6 +948,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 //========================================================================================================= /** Index: vm/jitrino/src/codegenerator/ia32/Ia32IRManager.cpp =================================================================== --- vm/jitrino/src/codegenerator/ia32/Ia32IRManager.cpp (revision 546740) +++ vm/jitrino/src/codegenerator/ia32/Ia32IRManager.cpp (working copy) @@ -640,6 +640,38 @@ } //_________________________________________________________________________________________________ +CMPXCHG8BPseudoInst * IRManager::newCMPXCHG8BPseudoInst(Opnd* mem, Opnd* edx, Opnd* eax, Opnd* ecx, Opnd* ebx) +{ + CMPXCHG8BPseudoInst* inst = new (memoryManager, 7) 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] = edx; + opnds[4] = eax; + opnds[5] = ecx; + opnds[6] = ebx; + opndConstraints[0] = Constraint(OpndKind_Memory, OpndSize_64); + opndConstraints[1] = Constraint(RegName_EDX); + opndConstraints[2] = Constraint(RegName_EAX); + opndConstraints[3] = Constraint(RegName_EDX); + opndConstraints[4] = Constraint(RegName_EAX); + opndConstraints[5] = Constraint(RegName_ECX); + opndConstraints[6] = Constraint(RegName_EBX); + + inst->opndCount = 7; + inst->defOpndCount = 3; + + inst->assignOpcodeGroup(this); + return inst; +} + +//_________________________________________________________________________________________________ Inst * IRManager::newCopyPseudoInst(Mnemonic mn, Opnd * opnd0, Opnd * opnd1) { assert(mn==Mnemonic_MOV||mn==Mnemonic_PUSH||mn==Mnemonic_POP); Index: vm/jitrino/src/codegenerator/ia32/Ia32I8Lowerer.cpp =================================================================== --- vm/jitrino/src/codegenerator/ia32/Ia32I8Lowerer.cpp (revision 546740) +++ vm/jitrino/src/codegenerator/ia32/Ia32I8Lowerer.cpp (working copy) @@ -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,145 +355,250 @@ Opnd * src1 = useCount> 0 ? inst->getOpnd(defCount): NULL; Opnd * src2 = useCount> 1 ? inst->getOpnd(defCount+1): NULL; + bool dstIsLongVolatile = false; + 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); - } + 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 { + prepareNewOpnds(dst,dst_1,dst_2); + } + } + 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); - 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()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); + 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 { - //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(src1,src1_1,src1_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 (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 { - buildComplexSubGraph(inst,src1_1,src1_2,src2_1,src2_2); + prepareNewOpnds(src2,src2_1,src2_2); } - inst->unlink(); - break; } - case Mnemonic_IMUL: - lowerMul64(inst); - break; - case Mnemonic_IDIV: - if (isI8RemInst(inst)) { - lowerRem64(inst); - } - else { - lowerDiv64(inst); - } - 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()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()), * dst1_2 = irManager->newOpnd(dst_2->getType()), Index: vm/jitrino/src/codegenerator/ia32/Ia32Printer.cpp =================================================================== --- vm/jitrino/src/codegenerator/ia32/Ia32Printer.cpp (revision 546740) +++ vm/jitrino/src/codegenerator/ia32/Ia32Printer.cpp (working copy) @@ -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 ""; } } Index: vm/jitrino/src/codegenerator/ia32/Ia32IRManager.h =================================================================== --- vm/jitrino/src/codegenerator/ia32/Ia32IRManager.h (revision 546740) +++ vm/jitrino/src/codegenerator/ia32/Ia32IRManager.h (working copy) @@ -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, Index: vm/jitrino/src/codegenerator/ia32/Ia32CopyExpansion.cpp =================================================================== --- vm/jitrino/src/codegenerator/ia32/Ia32CopyExpansion.cpp (revision 546740) +++ vm/jitrino/src/codegenerator/ia32/Ia32CopyExpansion.cpp (working copy) @@ -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){