diff --git a/evmjit/libevmjit/Arith256.cpp b/evmjit/libevmjit/Arith256.cpp index 2602dfdcc..56dd9bc2e 100644 --- a/evmjit/libevmjit/Arith256.cpp +++ b/evmjit/libevmjit/Arith256.cpp @@ -69,12 +69,31 @@ std::pair Arith256::div(llvm::Value* _arg1, llvm::Va return std::make_pair(m_builder.CreateLoad(m_arg3), m_builder.CreateLoad(m_result)); } -std::pair Arith256::sdiv(llvm::Value* _arg1, llvm::Value* _arg2) +std::pair Arith256::sdiv(llvm::Value* _x, llvm::Value* _y) { - m_builder.CreateStore(_arg1, m_arg1); - m_builder.CreateStore(_arg2, m_arg2); - createCall(m_sdiv, {m_arg1, m_arg2, m_arg3, m_result}); - return std::make_pair(m_builder.CreateLoad(m_arg3), m_builder.CreateLoad(m_result)); + auto xIsNeg = m_builder.CreateICmpSLT(_x, Constant::get(0)); + auto xNeg = m_builder.CreateSub(Constant::get(0), _x); + auto xAbs = m_builder.CreateSelect(xIsNeg, xNeg, _x); + + auto yIsNeg = m_builder.CreateICmpSLT(_y, Constant::get(0)); + auto yNeg = m_builder.CreateSub(Constant::get(0), _y); + auto yAbs = m_builder.CreateSelect(yIsNeg, yNeg, _y); + + m_builder.CreateStore(xAbs, m_arg1); + m_builder.CreateStore(yAbs, m_arg2); + createCall(m_div, {m_arg1, m_arg2, m_arg3, m_result}); + auto qAbs = m_builder.CreateLoad(m_arg3); + auto rAbs = m_builder.CreateLoad(m_result); + + // the reminder has the same sign as dividend + auto rNeg = m_builder.CreateSub(Constant::get(0), rAbs); + auto r = m_builder.CreateSelect(xIsNeg, rNeg, rAbs); + + auto qNeg = m_builder.CreateSub(Constant::get(0), qAbs); + auto xyOpposite = m_builder.CreateXor(xIsNeg, yIsNeg); + auto q = m_builder.CreateSelect(xyOpposite, qNeg, qAbs); + + return std::make_pair(q, r); } llvm::Value* Arith256::exp(llvm::Value* _arg1, llvm::Value* _arg2) @@ -151,14 +170,6 @@ namespace const auto nLimbs = sizeof(i256) / sizeof(mp_limb_t); - // FIXME: Not thread-safe - static mp_limb_t mod_limbs[] = {0, 0, 0, 0, 1}; - static_assert(sizeof(mod_limbs) / sizeof(mod_limbs[0]) == nLimbs + 1, "mp_limb_t size mismatch"); - static const mpz_t mod{nLimbs + 1, nLimbs + 1, &mod_limbs[0]}; - - static mp_limb_t tmp_limbs[nLimbs + 2]; - static mpz_t tmp{nLimbs + 2, 0, &tmp_limbs[0]}; - int countLimbs(i256 const* _n) { static const auto limbsInWord = sizeof(_n->a) / sizeof(mp_limb_t); @@ -174,25 +185,6 @@ namespace if (_n->a != 0) return l; return 0; } - - void u2s(mpz_t _u) - { - if (static_cast::type>(_u->_mp_d[nLimbs - 1]) < 0) - { - mpz_sub(tmp, mod, _u); - mpz_set(_u, tmp); - _u->_mp_size = -_u->_mp_size; - } - } - - void s2u(mpz_t _s) - { - if (_s->_mp_size < 0) - { - mpz_add(tmp, mod, _s); - mpz_set(_s, tmp); - } - } } } @@ -225,24 +217,6 @@ extern "C" mpz_tdiv_qr(q, r, x, y); } - EXPORT void arith_sdiv(i256* _arg1, i256* _arg2, i256* o_div, i256* o_mod) - { - *o_div = {}; - *o_mod = {}; - if (isZero(_arg2)) - return; - - mpz_t x{nLimbs, countLimbs(_arg1), reinterpret_cast(_arg1)}; - mpz_t y{nLimbs, countLimbs(_arg2), reinterpret_cast(_arg2)}; - mpz_t q{nLimbs, 0, reinterpret_cast(o_div)}; - mpz_t r{nLimbs, 0, reinterpret_cast(o_mod)}; - u2s(x); - u2s(y); - mpz_tdiv_qr(q, r, x, y); - s2u(q); - s2u(r); - } - EXPORT void arith_exp(i256* _arg1, i256* _arg2, i256* o_result) { *o_result = {};