Index: vm/port/src/encoder/ia32_em64t/enc_tabl.cpp =================================================================== --- vm/port/src/encoder/ia32_em64t/enc_tabl.cpp (revision 542750) +++ vm/port/src/encoder/ia32_em64t/enc_tabl.cpp (working copy) @@ -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 // Index: vm/port/src/encoder/ia32_em64t/enc_defs.h =================================================================== --- vm/port/src/encoder/ia32_em64t/enc_defs.h (revision 542750) +++ vm/port/src/encoder/ia32_em64t/enc_defs.h (working copy) @@ -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 Index: vm/jitrino/src/jet/cg.h =================================================================== --- vm/jitrino/src/jet/cg.h (revision 542750) +++ vm/jitrino/src/jet/cg.h (working copy) @@ -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. */ Index: vm/jitrino/src/jet/cg_regs.cpp =================================================================== --- vm/jitrino/src/jet/cg_regs.cpp (revision 542750) +++ vm/jitrino/src/jet/cg_regs.cpp (working copy) @@ -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; isize(); 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) Index: vm/jitrino/src/jet/enc.h =================================================================== --- vm/jitrino/src/jet/enc.h (revision 542750) +++ vm/jitrino/src/jet/enc.h (working copy) @@ -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(). Index: vm/jitrino/src/jet/cg_fld_arr.cpp =================================================================== --- vm/jitrino/src/jet/cg_fld_arr.cpp (revision 542750) +++ vm/jitrino/src/jet/cg_fld_arr.cpp (working copy) @@ -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); + } } } Index: vm/jitrino/src/jet/enc_ia32.cpp =================================================================== --- vm/jitrino/src/jet/enc_ia32.cpp (revision 542750) +++ vm/jitrino/src/jet/enc_ia32.cpp (working copy) @@ -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;