// Computes aR * bR mod N with R = 2**64. inline uint64_t montmul64(uint64_t a, uint64_t b, uint64_t N, uint64_t Nneginv) { std::pair<uint64_t, uint64_t> T, mN; uint64_t Th, Tl, m, mNh, mNl, th; std::tie(Th, Tl) = mulu64(a, b); m = Tl * Nneginv; std::tie(mNh, mNl) = mulu64(m, N); bool lc = Tl + mNl < Tl; th = Th + mNh + lc; bool hc = (th < Th) || (th == Th && lc); if (hc > 0 || th >= N) th = th - N; return th; }
static void test_u(void) { int i; for (i = 0; i < ARRAY_SIZE(test_u_data); ++i) { uint64_t rl, rh; mulu64(&rl, &rh, test_u_data[i].a, test_u_data[i].b); g_assert_cmpuint(rl, ==, test_u_data[i].rl); g_assert_cmpuint(rh, ==, test_u_data[i].rh); } }
uint64_t HELPER(muluh_i64)(uint64_t arg1, uint64_t arg2) { uint64_t l, h; mulu64(&l, &h, arg1, arg2); return h; }
static TCGArg do_constant_folding_2(TCGOpcode op, TCGArg x, TCGArg y) { uint64_t l64, h64; switch (op) { CASE_OP_32_64(add): return x + y; CASE_OP_32_64(sub): return x - y; CASE_OP_32_64(mul): return x * y; CASE_OP_32_64(and): return x & y; CASE_OP_32_64(or): return x | y; CASE_OP_32_64(xor): return x ^ y; case INDEX_op_shl_i32: return (uint32_t)x << (y & 31); case INDEX_op_shl_i64: return (uint64_t)x << (y & 63); case INDEX_op_shr_i32: return (uint32_t)x >> (y & 31); case INDEX_op_trunc_shr_i32: case INDEX_op_shr_i64: return (uint64_t)x >> (y & 63); case INDEX_op_sar_i32: return (int32_t)x >> (y & 31); case INDEX_op_sar_i64: return (int64_t)x >> (y & 63); case INDEX_op_rotr_i32: return ror32(x, y & 31); case INDEX_op_rotr_i64: return (TCGArg)ror64(x, y & 63); case INDEX_op_rotl_i32: return rol32(x, y & 31); case INDEX_op_rotl_i64: return (TCGArg)rol64(x, y & 63); CASE_OP_32_64(not): return ~x; CASE_OP_32_64(neg): return 0-x; CASE_OP_32_64(andc): return x & ~y; CASE_OP_32_64(orc): return x | ~y; CASE_OP_32_64(eqv): return ~(x ^ y); CASE_OP_32_64(nand): return ~(x & y); CASE_OP_32_64(nor): return ~(x | y); CASE_OP_32_64(ext8s): return (int8_t)x; CASE_OP_32_64(ext16s): return (int16_t)x; CASE_OP_32_64(ext8u): return (uint8_t)x; CASE_OP_32_64(ext16u): return (uint16_t)x; case INDEX_op_ext32s_i64: return (int32_t)x; case INDEX_op_ext32u_i64: return (uint32_t)x; case INDEX_op_muluh_i32: return ((uint64_t)(uint32_t)x * (uint32_t)y) >> 32; case INDEX_op_mulsh_i32: return ((int64_t)(int32_t)x * (int32_t)y) >> 32; case INDEX_op_muluh_i64: mulu64(&l64, &h64, x, y); return (TCGArg)h64; case INDEX_op_mulsh_i64: muls64(&l64, &h64, x, y); return (TCGArg)h64; case INDEX_op_div_i32: /* Avoid crashing on divide by zero, otherwise undefined. */ return (int32_t)x / ((int32_t)y ? (int32_t)y : 1); case INDEX_op_divu_i32: return (uint32_t)x / ((uint32_t)y ? (uint32_t)y : 1); case INDEX_op_div_i64: return (int64_t)x / ((int64_t)y ? (int64_t)y : 1); case INDEX_op_divu_i64: return (uint64_t)x / ((uint64_t)y ? (uint64_t)y : 1); case INDEX_op_rem_i32: return (int32_t)x % ((int32_t)y ? (int32_t)y : 1); case INDEX_op_remu_i32: return (uint32_t)x % ((uint32_t)y ? (uint32_t)y : 1); case INDEX_op_rem_i64: return (int64_t)x % ((int64_t)y ? (int64_t)y : 1); case INDEX_op_remu_i64: return (uint64_t)x % ((uint64_t)y ? (uint64_t)y : 1); default: fprintf(stderr, "Unrecognized operation %d in do_constant_folding.\n", op); tcg_abort(); } }