#![allow(dead_code)]
use zisk_core::zisk_ops::ZiskOp;
const OP_SIGNEXTENDB: u8 = ZiskOp::SignExtendB.code();
const OP_SIGNEXTENDH: u8 = ZiskOp::SignExtendH.code();
const OP_SIGNEXTENDW: u8 = ZiskOp::SignExtendW.code();
const OP_SLL: u8 = ZiskOp::Sll.code();
const OP_SLLW: u8 = ZiskOp::SllW.code();
const OP_SRA: u8 = ZiskOp::Sra.code();
const OP_SRL: u8 = ZiskOp::Srl.code();
const OP_SRAW: u8 = ZiskOp::SraW.code();
const OP_SRLW: u8 = ZiskOp::SrlW.code();
const MAX_A_LOW_VALUE: u64 = 386;
const MAX_B_LOW_VALUE: u64 = 386;
const LOW_VALUE_SIZE: usize = MAX_A_LOW_VALUE as usize * MAX_B_LOW_VALUE as usize;
const MAX_U64: u64 = 0xFFFF_FFFF_FFFF_FFFF;
const SLR_MASK_FROM: u64 = 0xFFFF_FFFF_FFFF_F000;
const SLR_TO_B: u64 = 64;
const OP_TABLE_OFFSETS_START: usize = 33;
const OP_TABLE_OFFSETS: [usize; 9] =
[0, 148996, 564232, 713228, 862224, 1011220, 1160216, 1309212, 1458208];
#[derive(Debug, Clone, Default)]
pub struct BinaryExtensionLegacyFrops;
impl BinaryExtensionLegacyFrops {
pub const NO_FROPS: usize = usize::MAX;
#[inline(always)]
fn is_frequent_srl(a: u64, b: u64) -> bool {
(a < MAX_A_LOW_VALUE && b < MAX_B_LOW_VALUE) || (a >= SLR_MASK_FROM && b <= SLR_TO_B)
}
#[inline(always)]
fn get_srl_offset(a: u64, b: u64) -> usize {
if a < MAX_A_LOW_VALUE && b < MAX_B_LOW_VALUE {
Self::get_low_values_offset(a, b)
} else if a >= SLR_MASK_FROM && b <= SLR_TO_B {
LOW_VALUE_SIZE + ((a - SLR_MASK_FROM) * (SLR_TO_B + 1) + b) as usize
} else {
Self::NO_FROPS
}
}
#[inline(always)]
fn get_low_values_offset(a: u64, b: u64) -> usize {
(a * MAX_B_LOW_VALUE + b) as usize
}
#[inline(always)]
pub fn is_frequent_op(op: u8, a: u64, b: u64) -> bool {
match op {
OP_SIGNEXTENDB | OP_SIGNEXTENDH | OP_SIGNEXTENDW | OP_SLL | OP_SLLW | OP_SRA
| OP_SRAW | OP_SRLW => a < MAX_A_LOW_VALUE && b < MAX_B_LOW_VALUE,
OP_SRL => Self::is_frequent_srl(a, b),
_ => false,
}
}
#[inline(always)]
pub fn get_row(op: u8, a: u64, b: u64) -> usize {
let relative_offset = match op {
OP_SIGNEXTENDB | OP_SIGNEXTENDH | OP_SIGNEXTENDW | OP_SLL | OP_SLLW | OP_SRA
| OP_SRAW | OP_SRLW => {
if a < MAX_A_LOW_VALUE && b < MAX_B_LOW_VALUE {
Self::get_low_values_offset(a, b)
} else {
Self::NO_FROPS
}
}
OP_SRL => Self::get_srl_offset(a, b),
_ => Self::NO_FROPS,
};
if relative_offset == Self::NO_FROPS {
Self::NO_FROPS
} else {
relative_offset + OP_TABLE_OFFSETS[op as usize - OP_TABLE_OFFSETS_START]
}
}
}