use std::num::Wrapping;
const M64: u64 = 0xFFFFFFFFFFFFFFFF;
#[inline(always)]
pub const fn op_flag(_a: u64, _b: u64) -> (u64, bool) {
(0, true)
}
#[inline(always)]
pub const fn op_copyb(_a: u64, b: u64) -> (u64, bool) {
(b, false)
}
#[inline(always)]
pub const fn op_signextend_b(_a: u64, b: u64) -> (u64, bool) {
((b as i8) as u64, false)
}
#[inline(always)]
pub const fn op_signextend_h(_a: u64, b: u64) -> (u64, bool) {
((b as i16) as u64, false)
}
#[inline(always)]
pub const fn op_signextend_w(_a: u64, b: u64) -> (u64, bool) {
((b as i32) as u64, false)
}
#[inline(always)]
pub fn op_add(a: u64, b: u64) -> (u64, bool) {
((Wrapping(a) + Wrapping(b)).0, false)
}
#[inline(always)]
pub fn op_add_w(a: u64, b: u64) -> (u64, bool) {
((Wrapping(a as i32) + Wrapping(b as i32)).0 as u64, false)
}
#[inline(always)]
pub fn op_sub(a: u64, b: u64) -> (u64, bool) {
((Wrapping(a) - Wrapping(b)).0, false)
}
#[inline(always)]
pub fn op_sub_w(a: u64, b: u64) -> (u64, bool) {
((Wrapping(a as i32) - Wrapping(b as i32)).0 as u64, false)
}
#[inline(always)]
pub const fn op_sll(a: u64, b: u64) -> (u64, bool) {
(a << (b & 0x3f), false)
}
#[inline(always)]
pub fn op_sll_w(a: u64, b: u64) -> (u64, bool) {
(((Wrapping(a as u32) << (b & 0x1f) as usize).0 as i32) as u64, false)
}
#[inline(always)]
pub const fn op_sra(a: u64, b: u64) -> (u64, bool) {
(((a as i64) >> (b & 0x3f)) as u64, false)
}
#[inline(always)]
pub const fn op_srl(a: u64, b: u64) -> (u64, bool) {
(a >> (b & 0x3f), false)
}
#[inline(always)]
pub fn op_sra_w(a: u64, b: u64) -> (u64, bool) {
((Wrapping(a as i32) >> (b & 0x1f) as usize).0 as u64, false)
}
#[inline(always)]
pub fn op_srl_w(a: u64, b: u64) -> (u64, bool) {
(((Wrapping(a as u32) >> (b & 0x1f) as usize).0 as i32) as u64, false)
}
#[inline(always)]
pub const fn op_eq(a: u64, b: u64) -> (u64, bool) {
if a == b {
(1, true)
} else {
(0, false)
}
}
#[inline(always)]
pub const fn op_eq_w(a: u64, b: u64) -> (u64, bool) {
if (a as i32) == (b as i32) {
(1, true)
} else {
(0, false)
}
}
#[inline(always)]
pub const fn op_ltu(a: u64, b: u64) -> (u64, bool) {
if a < b {
(1, true)
} else {
(0, false)
}
}
#[inline(always)]
pub const fn op_lt(a: u64, b: u64) -> (u64, bool) {
if (a as i64) < (b as i64) {
(1, true)
} else {
(0, false)
}
}
#[inline(always)]
pub const fn op_ltu_w(a: u64, b: u64) -> (u64, bool) {
if (a as u32) < (b as u32) {
(1, true)
} else {
(0, false)
}
}
#[inline(always)]
pub const fn op_lt_w(a: u64, b: u64) -> (u64, bool) {
if (a as i32) < (b as i32) {
(1, true)
} else {
(0, false)
}
}
#[inline(always)]
pub const fn op_leu(a: u64, b: u64) -> (u64, bool) {
if a <= b {
(1, true)
} else {
(0, false)
}
}
#[inline(always)]
pub const fn op_le(a: u64, b: u64) -> (u64, bool) {
if (a as i64) <= (b as i64) {
(1, true)
} else {
(0, false)
}
}
#[inline(always)]
pub const fn op_leu_w(a: u64, b: u64) -> (u64, bool) {
if (a as u32) <= (b as u32) {
(1, true)
} else {
(0, false)
}
}
#[inline(always)]
pub const fn op_le_w(a: u64, b: u64) -> (u64, bool) {
if (a as i32) <= (b as i32) {
(1, true)
} else {
(0, false)
}
}
#[inline(always)]
pub const fn op_and(a: u64, b: u64) -> (u64, bool) {
(a & b, false)
}
#[inline(always)]
pub const fn op_or(a: u64, b: u64) -> (u64, bool) {
(a | b, false)
}
#[inline(always)]
pub const fn op_xor(a: u64, b: u64) -> (u64, bool) {
(a ^ b, false)
}
#[inline(always)]
pub fn op_mulu(a: u64, b: u64) -> (u64, bool) {
((Wrapping(a) * Wrapping(b)).0, false)
}
#[inline(always)]
pub fn op_mul(a: u64, b: u64) -> (u64, bool) {
((Wrapping(a as i64) * Wrapping(b as i64)).0 as u64, false)
}
#[inline(always)]
pub fn op_mul_w(a: u64, b: u64) -> (u64, bool) {
((Wrapping(a as i32) * Wrapping(b as i32)).0 as u64, false)
}
#[inline(always)]
pub const fn op_muluh(a: u64, b: u64) -> (u64, bool) {
(((a as u128 * b as u128) >> 64) as u64, false)
}
#[inline(always)]
pub const fn op_mulh(a: u64, b: u64) -> (u64, bool) {
(((((a as i64) as i128) * ((b as i64) as i128)) >> 64) as u64, false)
}
#[inline(always)]
pub const fn op_mulsuh(a: u64, b: u64) -> (u64, bool) {
(((((a as i64) as i128) * (b as i128)) >> 64) as u64, false)
}
#[inline(always)]
pub const fn op_divu(a: u64, b: u64) -> (u64, bool) {
if b == 0 {
return (M64, true);
}
(a / b, false)
}
#[inline(always)]
pub const fn op_div(a: u64, b: u64) -> (u64, bool) {
if b == 0 {
return (M64, true);
}
if (a == 0x8000_0000_0000_0000) && (b as i64 == -1) {
return (0x8000_0000_0000_0000, false);
}
((((a as i64) as i128) / ((b as i64) as i128)) as u64, false)
}
#[inline(always)]
pub const fn op_divu_w(a: u64, b: u64) -> (u64, bool) {
if b as u32 == 0 {
return (M64, true);
}
(((a as u32 / b as u32) as i32) as u64, false)
}
#[inline(always)]
pub const fn op_div_w(a: u64, b: u64) -> (u64, bool) {
if b as i32 == 0 {
return (M64, true);
}
if a as u32 == 0x8000_0000 && b as i32 == -1 {
return (0xFFFFFFFF80000000, false);
}
((((a as i32) as i64) / ((b as i32) as i64)) as i32 as u64, false)
}
#[inline(always)]
pub const fn op_remu(a: u64, b: u64) -> (u64, bool) {
if b == 0 {
return (a, true);
}
(a % b, false)
}
#[inline(always)]
pub const fn op_rem(a: u64, b: u64) -> (u64, bool) {
if b == 0 {
return (a, true);
}
if (a == 0x8000_0000_0000_0000) && (b as i64 == -1) {
return (0, false);
}
((((a as i64) as i128) % ((b as i64) as i128)) as u64, false)
}
#[inline(always)]
pub const fn op_remu_w(a: u64, b: u64) -> (u64, bool) {
if (b as u32) == 0 {
return ((a as i32) as u64, true);
}
((((a as u32) % (b as u32)) as i32) as u64, false)
}
#[inline(always)]
pub const fn op_rem_w(a: u64, b: u64) -> (u64, bool) {
if (b as i32) == 0 {
return ((a as i32) as u64, true);
}
if a as u32 == 0x8000_0000 && b as i32 == -1 {
return (0, false);
}
((((a as i32) as i64) % ((b as i32) as i64)) as u64, false)
}
#[inline(always)]
pub const fn op_minu(a: u64, b: u64) -> (u64, bool) {
if a < b {
(a, false)
} else {
(b, false)
}
}
#[inline(always)]
pub const fn op_min(a: u64, b: u64) -> (u64, bool) {
if (a as i64) < (b as i64) {
(a, false)
} else {
(b, false)
}
}
#[inline(always)]
pub const fn op_minu_w(a: u64, b: u64) -> (u64, bool) {
if (a as u32) < (b as u32) {
(a as i32 as i64 as u64, false)
} else {
(b as i32 as i64 as u64, false)
}
}
#[inline(always)]
pub const fn op_min_w(a: u64, b: u64) -> (u64, bool) {
if (a as i32) < (b as i32) {
(a as i32 as i64 as u64, false)
} else {
(b as i32 as i64 as u64, false)
}
}
#[inline(always)]
pub const fn op_maxu(a: u64, b: u64) -> (u64, bool) {
if a > b {
(a, false)
} else {
(b, false)
}
}
#[inline(always)]
pub const fn op_max(a: u64, b: u64) -> (u64, bool) {
if (a as i64) > (b as i64) {
(a, false)
} else {
(b, false)
}
}
#[inline(always)]
pub const fn op_maxu_w(a: u64, b: u64) -> (u64, bool) {
if (a as u32) > (b as u32) {
(a as i32 as i64 as u64, false)
} else {
(b as i32 as i64 as u64, false)
}
}
#[inline(always)]
pub const fn op_max_w(a: u64, b: u64) -> (u64, bool) {
if (a as i32) > (b as i32) {
(a as i32 as i64 as u64, false)
} else {
(b as i32 as i64 as u64, false)
}
}
#[inline(always)]
pub const fn op_rev8(_a: u64, b: u64) -> (u64, bool) {
(b.swap_bytes(), false)
}
#[inline(always)]
pub const fn op_brev8(_a: u64, b: u64) -> (u64, bool) {
let mut bytes: [u8; 8] = b.to_le_bytes();
let mut i = 0;
while i < 8 {
bytes[i] = bytes[i].reverse_bits();
i += 1;
}
(u64::from_le_bytes(bytes), false)
}
#[inline(always)]
pub const fn op_andn(a: u64, b: u64) -> (u64, bool) {
(a & !b, false)
}
#[inline(always)]
pub const fn op_orn(a: u64, b: u64) -> (u64, bool) {
(a | !b, false)
}
#[inline(always)]
pub const fn op_xnor(a: u64, b: u64) -> (u64, bool) {
(!(a ^ b), false)
}
#[inline(always)]
pub const fn op_pack(a: u64, b: u64) -> (u64, bool) {
(a & 0xFFFFFFFF | (b & 0xFFFFFFFF) << 32, false)
}
#[inline(always)]
pub const fn op_pack_h(a: u64, b: u64) -> (u64, bool) {
(a & 0xFF | (b & 0xFF) << 8, false)
}
#[inline(always)]
pub const fn op_pack_w(a: u64, b: u64) -> (u64, bool) {
(((a & 0xFFFF) | ((b & 0xFFFF) << 16)) as i32 as u64, false)
}
#[inline(always)]
pub const fn op_rol(a: u64, b: u64) -> (u64, bool) {
(a.rotate_left((b & 0x3F) as u32), false)
}
#[inline(always)]
pub const fn op_rol_w(a: u64, b: u64) -> (u64, bool) {
(((a & 0xFFFFFFFF) as u32).rotate_left((b & 0x1F) as u32) as i32 as u64, false)
}
#[inline(always)]
pub const fn op_ror(a: u64, b: u64) -> (u64, bool) {
(a.rotate_right((b & 0x3F) as u32), false)
}
#[inline(always)]
pub const fn op_ror_w(a: u64, b: u64) -> (u64, bool) {
(((a & 0xFFFFFFFF) as u32).rotate_right((b & 0x1F) as u32) as i32 as u64, false)
}
#[inline(always)]
pub const fn op_clz(_a: u64, b: u64) -> (u64, bool) {
(b.leading_zeros() as u64, false)
}
#[inline(always)]
pub const fn op_clz_w(_a: u64, b: u64) -> (u64, bool) {
((b as u32).leading_zeros() as u64, false)
}
#[inline(always)]
pub const fn op_ctz(_a: u64, b: u64) -> (u64, bool) {
(b.trailing_zeros() as u64, false)
}
#[inline(always)]
pub const fn op_ctz_w(_a: u64, b: u64) -> (u64, bool) {
((b as u32).trailing_zeros() as u64, false)
}
#[inline(always)]
pub const fn op_cpop(_a: u64, b: u64) -> (u64, bool) {
(b.count_ones() as u64, false)
}
#[inline(always)]
pub const fn op_cpop_w(_a: u64, b: u64) -> (u64, bool) {
((b as u32).count_ones() as u64, false)
}
#[inline(always)]
pub const fn op_orc_b(_a: u64, b: u64) -> (u64, bool) {
let mut result = 0;
if (b & 0xFF) != 0 {
result |= 0xFF;
}
if (b & 0xFF00) != 0 {
result |= 0xFF00;
}
if (b & 0xFF0000) != 0 {
result |= 0xFF0000;
}
if (b & 0xFF000000) != 0 {
result |= 0xFF000000;
}
if (b & 0xFF00000000) != 0 {
result |= 0xFF00000000;
}
if (b & 0xFF0000000000) != 0 {
result |= 0xFF0000000000;
}
if (b & 0xFF000000000000) != 0 {
result |= 0xFF000000000000;
}
if (b & 0xFF00000000000000) != 0 {
result |= 0xFF00000000000000;
}
(result, false)
}
#[inline(always)]
pub const fn op_bclr(a: u64, b: u64) -> (u64, bool) {
(a & !(1 << (b & 0x3F)), false)
}
#[inline(always)]
pub const fn op_bext(a: u64, b: u64) -> (u64, bool) {
((a >> (b & 0x3F)) & 1, false)
}
#[inline(always)]
pub const fn op_binv(a: u64, b: u64) -> (u64, bool) {
(a ^ (1 << (b & 0x3F)), false)
}
#[inline(always)]
pub const fn op_bset(a: u64, b: u64) -> (u64, bool) {
(a | (1 << (b & 0x3F)), false)
}
#[inline(always)]
pub const fn op_add_u_w(a: u64, b: u64) -> (u64, bool) {
(b.wrapping_add(a & 0xFFFF_FFFF), false)
}
#[inline(always)]
pub const fn op_sh1add(a: u64, b: u64) -> (u64, bool) {
(b.wrapping_add(a << 1), false)
}
#[inline(always)]
pub const fn op_sh1add_u_w(a: u64, b: u64) -> (u64, bool) {
(b.wrapping_add((a & 0xFFFFFFFF) << 1), false)
}
#[inline(always)]
pub const fn op_sh2add(a: u64, b: u64) -> (u64, bool) {
(b.wrapping_add(a << 2), false)
}
#[inline(always)]
pub const fn op_sh2add_u_w(a: u64, b: u64) -> (u64, bool) {
(b.wrapping_add((a & 0xFFFFFFFF) << 2), false)
}
#[inline(always)]
pub const fn op_sh3add(a: u64, b: u64) -> (u64, bool) {
(b.wrapping_add(a << 3), false)
}
#[inline(always)]
pub const fn op_sh3add_u_w(a: u64, b: u64) -> (u64, bool) {
(b.wrapping_add((a & 0xFFFFFFFF) << 3), false)
}
#[inline(always)]
pub const fn op_sll_u_w(a: u64, b: u64) -> (u64, bool) {
((a & 0xFFFFFFFF) << (b & 0x3F), false)
}
#[inline(always)]
pub const fn op_clmul(a: u64, b: u64) -> (u64, bool) {
let mut output: u64 = 0;
let mut i = 0;
while i < 64 {
if (b >> i) & 1 == 1 {
output ^= a << i;
}
i += 1;
}
(output, false)
}
#[inline(always)]
pub const fn op_clmul_h(a: u64, b: u64) -> (u64, bool) {
let mut output: u64 = 0;
let mut i = 1;
while i < 64 {
if (b >> i) & 1 == 1 {
output ^= a >> (64 - i);
}
i += 1;
}
(output, false)
}
#[inline(always)]
pub const fn op_clmul_r(a: u64, b: u64) -> (u64, bool) {
let mut output: u64 = 0;
let mut i = 0;
while i < 64 {
if (b >> i) & 1 == 1 {
output ^= a >> (63 - i);
}
i += 1;
}
(output, false)
}
#[inline(always)]
pub const fn op_xperm4(a: u64, b: u64) -> (u64, bool) {
let mut values: [u8; 16] = [0; 16];
let mut i = 0;
while i < 16 {
values[i] = ((a >> (i * 4)) & 0xF) as u8;
i += 1;
}
let mut indexes: [u8; 16] = [0; 16];
i = 0;
while i < 16 {
indexes[i] = ((b >> (i * 4)) & 0xF) as u8;
i += 1;
}
let mut output: [u8; 16] = [0; 16];
i = 0;
while i < 16 {
output[i] = values[indexes[i] as usize];
i += 1;
}
let mut result: u64 = 0;
i = 0;
while i < 16 {
result |= (output[i] as u64) << (i * 4);
i += 1;
}
(result, false)
}
#[inline(always)]
pub const fn op_xperm8(a: u64, b: u64) -> (u64, bool) {
let mut values: [u8; 8] = [0; 8];
let mut i = 0;
while i < 8 {
values[i] = ((a >> (i * 8)) & 0xFF) as u8;
i += 1;
}
let mut indexes: [u8; 8] = [0; 8];
i = 0;
while i < 8 {
indexes[i] = ((b >> (i * 8)) & 0xFF) as u8;
i += 1;
}
let mut output: [u8; 8] = [0; 8];
i = 0;
while i < 8 {
if indexes[i] < 8 {
output[i] = values[indexes[i] as usize];
}
i += 1;
}
let mut result: u64 = 0;
i = 0;
while i < 8 {
result |= (output[i] as u64) << (i * 8);
i += 1;
}
(result, false)
}
#[inline(always)]
pub fn op_czero_eqz(a: u64, b: u64) -> (u64, bool) {
if b == 0 {
(0, false)
} else {
(a, false)
}
}
#[inline(always)]
pub fn op_czero_nez(a: u64, b: u64) -> (u64, bool) {
if b != 0 {
(0, false)
} else {
(a, false)
}
}