#![allow(dead_code)]
#![allow(clippy::manual_range_contains, clippy::nonminimal_bool)]
use std::error::Error;
use zisk_core::zisk_ops::ZiskOp;
use zisk_sm_frequent_ops::FrequentOpsHelpers;
const OP_MINU: u8 = ZiskOp::Minu.code();
const OP_MAXU: u8 = ZiskOp::Maxu.code();
const OP_LTU: u8 = ZiskOp::Ltu.code();
const OP_LT: u8 = ZiskOp::Lt.code();
const OP_EQ: u8 = ZiskOp::Eq.code();
const OP_ADD: u8 = ZiskOp::Add.code();
const OP_SUB: u8 = ZiskOp::Sub.code();
const OP_AND: u8 = ZiskOp::And.code();
const OP_OR: u8 = ZiskOp::Or.code();
const OP_XOR: u8 = ZiskOp::Xor.code();
const OP_ADDW: u8 = ZiskOp::AddW.code();
const OP_SUBW: u8 = ZiskOp::SubW.code();
const OP_ANDN: u8 = ZiskOp::Andn.code();
const OP_ORN: u8 = ZiskOp::Orn.code();
const OP_TABLE_OFFSETS_START: usize = 2;
const OP_TABLE_OFFSETS: [usize; 51] = [
0, 0, 11454, 0, 13326, 1066002, 0, 1827332, 2377264, 12108082, 0, 0, 12511466, 12850410,
18562081, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18628381, 18630684, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 18663708, 18663747,
];
#[derive(Debug, Clone)]
pub struct BinaryBasicFrops {
table: FrequentOpsHelpers,
}
const FREQUENT_OP_EMPTY: usize = 256;
impl Default for BinaryBasicFrops {
fn default() -> Self {
Self::new()
}
}
impl BinaryBasicFrops {
pub const TABLE_ID: usize = 5011;
pub const NO_FROPS: usize = FrequentOpsHelpers::NO_FROPS;
pub fn new() -> Self {
Self { table: FrequentOpsHelpers::new() }
}
pub fn build_table(&mut self) {
{
let mut ops: Vec<[u64; 2]> = Vec::new();
for a in 0..166 {
for b in 0..69 {
ops.push([a, b]);
}
}
self.table.add_ops(OP_MINU, &mut ops, true);
}
{
let mut ops: Vec<[u64; 2]> = Vec::new();
for a in 0..104 {
for b in 0..18 {
ops.push([a, b]);
}
}
self.table.add_ops(OP_MAXU, &mut ops, true);
}
{
let mut ops: Vec<[u64; 2]> = Vec::new();
for a in 0..1026 {
for b in 0..1026 {
ops.push([a, b]);
}
}
self.table.add_ops(OP_LTU, &mut ops, true);
}
{
let mut ops: Vec<[u64; 2]> = Vec::new();
for a in 0..537 {
for b in 0..128 {
ops.push([a, b]);
}
}
for a in 0x7FFFFFFFFFFFF000..0x8000000000001000 {
for b in 0..1 {
ops.push([a, b]);
}
}
for a in (0x9400000000000000..0x9400000000001000).step_by(8) {
for b in 0..1 {
ops.push([a, b]);
}
}
for a in 0xFFFFFFFFFFFAC847..=u64::MAX {
for b in 0..2 {
ops.push([a, b]);
}
}
self.table.add_ops(OP_LT, &mut ops, true);
}
{
let mut ops: Vec<[u64; 2]> = Vec::new();
for a in 0..534 {
for b in 0..1026 {
ops.push([a, b]);
}
}
for a in (0x43E1F593F0000001..0x43E1F593F0001001).step_by(8) {
for b in 0..2 {
ops.push([a, b]);
}
}
for a in (0x8080808080808000..0x8080808080809000).step_by(8) {
for b in 0..1 {
ops.push([a, b]);
}
}
for a in (0xFBF7FFFFF9B9F005..0xFBF7FFFFF9BA0005).step_by(8) {
for b in 0..1 {
ops.push([a, b]);
}
}
self.table.add_ops(OP_EQ, &mut ops, true);
}
{
let mut ops: Vec<[u64; 2]> = Vec::new();
for a in 0..547 {
for b in 0..534 {
ops.push([a, b]);
}
}
for a in (0x100F000..0x1011000).step_by(8) {
for b in 0x101..0x102 {
ops.push([a, b]);
}
}
for a in (0xA03F3000..0xA03FC000).step_by(8) {
for b in 0..2048 {
ops.push([a, b]);
}
}
for a in (0xFFFFFFFF80808000..0xFFFFFFFF80809000).step_by(8) {
for b in 0x80..0x81 {
ops.push([a, b]);
}
}
self.table.add_ops(OP_ADD, &mut ops, true);
}
{
let mut ops: Vec<[u64; 2]> = Vec::new();
for a in 0..534 {
for b in 0..532 {
ops.push([a, b]);
}
}
for a in (0xA03F5000..0xA03FC000).step_by(8) {
for b in 0..33 {
ops.push([a, b]);
}
}
for a in (0xAF89EFC2C1EA000..0xAF89EFC2C1EB000).step_by(8) {
for b in 0..1 {
ops.push([a, b]);
}
}
for a in (0x2725DD1D243AB006..0x2725DD1D243AC006).step_by(8) {
for b in 0..1 {
ops.push([a, b]);
}
}
self.table.add_ops(OP_SUB, &mut ops, true);
}
{
let mut ops: Vec<[u64; 2]> = Vec::new();
for a in 0..1190 {
for b in 0..256 {
ops.push([a, b]);
}
}
for a in (0x1FFFFFFF007..0x20000000007).step_by(8) {
for b in 0..3 {
ops.push([a, b]);
}
}
for a in 0x7FFFFFFFFFFFF000..0x8000000000001000 {
for b in 0..4 {
ops.push([a, b]);
}
}
self.table.add_ops(OP_AND, &mut ops, true);
}
{
let mut ops: Vec<[u64; 2]> = Vec::new();
for a in 0..1541 {
for b in 0..267 {
ops.push([a, b]);
}
}
for a in (0x1000..0x10000).step_by(8) {
for b in 0..690 {
ops.push([a, b]);
}
}
for a in (0x4C440000..0x4C441000).step_by(8) {
for b in 0x400..0x401 {
ops.push([a, b]);
}
}
for a in (0xA0110000..0xA0111000).step_by(8) {
for b in 0x2F9..0x2FA {
ops.push([a, b]);
}
}
self.table.add_ops(OP_OR, &mut ops, true);
}
{
let mut ops: Vec<[u64; 2]> = Vec::new();
for a in 0..255 {
for b in 0..260 {
ops.push([a, b]);
}
}
self.table.add_ops(OP_XOR, &mut ops, true);
}
{
let mut ops: Vec<[u64; 2]> = Vec::new();
for a in 0..256 {
for b in 0..8 {
ops.push([a, b]);
}
}
for a in 0xFFFFFFFFFFFFFF01..=u64::MAX {
for b in 0..1 {
ops.push([a, b]);
}
}
self.table.add_ops(OP_ADDW, &mut ops, true);
}
{
let mut ops: Vec<[u64; 2]> = Vec::new();
for a in 0..129 {
for b in 0..256 {
ops.push([a, b]);
}
}
self.table.add_ops(OP_SUBW, &mut ops, true);
}
{
let mut ops: Vec<[u64; 2]> = Vec::new();
for a in 0..3 {
for b in 0..13 {
ops.push([a, b]);
}
}
self.table.add_ops(OP_ANDN, &mut ops, true);
}
{
let mut ops: Vec<[u64; 2]> = Vec::new();
for a in 0..63 {
for b in 0..1 {
ops.push([a, b]);
}
}
for a in 0xFFFFFFFFFFFFFFFF..=u64::MAX {
for b in 0..1 {
ops.push([a, b]);
}
}
self.table.add_ops(OP_ORN, &mut ops, true);
}
}
#[inline(always)]
pub fn is_frequent_op(op: u8, a: u64, b: u64) -> bool {
match op {
OP_MINU => a < 166 && b < 69,
OP_MAXU => a < 104 && b < 18,
OP_LTU => a < 1026 && b < 1026,
OP_LT => {
a < 537 && b < 128
|| a >= 0x7FFFFFFFFFFFF000 && a < 0x8000000000001000 && b == 0
|| a >= 0x9400000000000000 && a < 0x9400000000001000 && (a & 7) == 0 && b == 0
|| a >= 0xFFFFFFFFFFFAC847 && b < 2
}
OP_EQ => {
a < 534 && b < 1026
|| a >= 0x43E1F593F0000001 && a < 0x43E1F593F0001001 && (a & 7) == 1 && b < 2
|| a >= 0x8080808080808000 && a < 0x8080808080809000 && (a & 7) == 0 && b == 0
|| a >= 0xFBF7FFFFF9B9F005 && a < 0xFBF7FFFFF9BA0005 && (a & 7) == 5 && b == 0
}
OP_ADD => {
a < 547 && b < 534
|| a >= 0x100F000 && a < 0x1011000 && (a & 7) == 0 && b == 257
|| a >= 0xA03F3000 && a < 0xA03FC000 && (a & 7) == 0 && b < 2048
|| a >= 0xFFFFFFFF80808000 && a < 0xFFFFFFFF80809000 && (a & 7) == 0 && b == 128
}
OP_SUB => {
a < 534 && b < 532
|| a >= 0xA03F5000 && a < 0xA03FC000 && (a & 7) == 0 && b < 33
|| a >= 0xAF89EFC2C1EA000 && a < 0xAF89EFC2C1EB000 && (a & 7) == 0 && b == 0
|| a >= 0x2725DD1D243AB006 && a < 0x2725DD1D243AC006 && (a & 7) == 6 && b == 0
}
OP_AND => {
a < 1190 && b < 256
|| a >= 0x1FFFFFFF007 && a < 0x20000000007 && (a & 7) == 7 && b < 3
|| a >= 0x7FFFFFFFFFFFF000 && a < 0x8000000000001000 && b < 4
}
OP_OR => {
a < 1541 && b < 267
|| a >= 4096 && a < 0x10000 && (a & 7) == 0 && b < 690
|| a >= 0x4C440000 && a < 0x4C441000 && (a & 7) == 0 && b == 1024
|| a >= 0xA0110000 && a < 0xA0111000 && (a & 7) == 0 && b == 761
}
OP_XOR => a < 255 && b < 260,
OP_ADDW => a < 256 && b < 8 || a >= 0xFFFFFFFFFFFFFF01 && b == 0,
OP_SUBW => a < 129 && b < 256,
OP_ANDN => a < 3 && b < 13,
OP_ORN => a < 63 && b == 0 || a == 0xFFFFFFFFFFFFFFFF && b == 0,
_ => false,
}
}
#[inline(always)]
pub fn get_row(op: u8, a: u64, b: u64) -> usize {
let relative_offset = match op {
OP_MINU => {
if a < 166 && b < 69 {
(a * 69 + b) as usize
} else {
Self::NO_FROPS
}
}
OP_MAXU => {
if a < 104 && b < 18 {
(a * 18 + b) as usize
} else {
Self::NO_FROPS
}
}
OP_LTU => {
if a < 1026 && b < 1026 {
(a * 1026 + b) as usize
} else {
Self::NO_FROPS
}
}
OP_LT => {
if a < 537 && b < 128 {
(a * 128 + b) as usize
} else if a >= 0x7FFFFFFFFFFFF000 && a < 0x8000000000001000 && b == 0 {
(a - 0x7FFFFFFFFFFFF000) as usize + 68736
} else if a >= 0x9400000000000000
&& a < 0x9400000000001000
&& (a & 7) == 0
&& b == 0
{
((a - 0x9400000000000000) / 8) as usize + 76928
} else if a >= 0xFFFFFFFFFFFAC847 && b < 2 {
((a - 0xFFFFFFFFFFFAC847) * 2 + b) as usize + 77440
} else {
Self::NO_FROPS
}
}
OP_EQ => {
if a < 534 && b < 1026 {
(a * 1026 + b) as usize
} else if a >= 0x43E1F593F0000001 && a < 0x43E1F593F0001001 && (a & 7) == 1 && b < 2
{
(((a - 0x43E1F593F0000001) / 8) * 2 + b) as usize + 547884
} else if a >= 0x8080808080808000
&& a < 0x8080808080809000
&& (a & 7) == 0
&& b == 0
{
((a - 0x8080808080808000) / 8) as usize + 548908
} else if a >= 0xFBF7FFFFF9B9F005
&& a < 0xFBF7FFFFF9BA0005
&& (a & 7) == 5
&& b == 0
{
((a - 0xFBF7FFFFF9B9F005) / 8) as usize + 549420
} else {
Self::NO_FROPS
}
}
OP_ADD => {
if a < 547 && b < 534 {
(a * 534 + b) as usize
} else if a >= 0x100F000 && a < 0x1011000 && (a & 7) == 0 && b == 257 {
((a - 0x100F000) / 8) as usize + 292098
} else if a >= 0xA03F3000 && a < 0xA03FC000 && (a & 7) == 0 && b < 2048 {
(((a - 0xA03F3000) / 8) * 2048 + b) as usize + 293122
} else if a >= 0xFFFFFFFF80808000
&& a < 0xFFFFFFFF80809000
&& (a & 7) == 0
&& b == 128
{
((a - 0xFFFFFFFF80808000) / 8) as usize + 9730306
} else {
Self::NO_FROPS
}
}
OP_SUB => {
if a < 534 && b < 532 {
(a * 532 + b) as usize
} else if a >= 0xA03F5000 && a < 0xA03FC000 && (a & 7) == 0 && b < 33 {
(((a - 0xA03F5000) / 8) * 33 + b) as usize + 284088
} else if a >= 0xAF89EFC2C1EA000 && a < 0xAF89EFC2C1EB000 && (a & 7) == 0 && b == 0
{
((a - 0xAF89EFC2C1EA000) / 8) as usize + 402360
} else if a >= 0x2725DD1D243AB006
&& a < 0x2725DD1D243AC006
&& (a & 7) == 6
&& b == 0
{
((a - 0x2725DD1D243AB006) / 8) as usize + 402872
} else {
Self::NO_FROPS
}
}
OP_AND => {
if a < 1190 && b < 256 {
(a * 256 + b) as usize
} else if a >= 0x1FFFFFFF007 && a < 0x20000000007 && (a & 7) == 7 && b < 3 {
(((a - 0x1FFFFFFF007) / 8) * 3 + b) as usize + 304640
} else if a >= 0x7FFFFFFFFFFFF000 && a < 0x8000000000001000 && b < 4 {
((a - 0x7FFFFFFFFFFFF000) * 4 + b) as usize + 306176
} else {
Self::NO_FROPS
}
}
OP_OR => {
if a < 1541 && b < 267 {
(a * 267 + b) as usize
} else if a >= 4096 && a < 0x10000 && (a & 7) == 0 && b < 690 {
(((a - 0x1000) / 8) * 690 + b) as usize + 411447
} else if a >= 0x4C440000 && a < 0x4C441000 && (a & 7) == 0 && b == 1024 {
((a - 0x4C440000) / 8) as usize + 5710647
} else if a >= 0xA0110000 && a < 0xA0111000 && (a & 7) == 0 && b == 761 {
((a - 0xA0110000) / 8) as usize + 5711159
} else {
Self::NO_FROPS
}
}
OP_XOR => {
if a < 255 && b < 260 {
(a * 260 + b) as usize
} else {
Self::NO_FROPS
}
}
OP_ADDW => {
if a < 256 && b < 8 {
(a * 8 + b) as usize
} else if a >= 0xFFFFFFFFFFFFFF01 && b == 0 {
(a - 0xFFFFFFFFFFFFFF01) as usize + 2048
} else {
Self::NO_FROPS
}
}
OP_SUBW => {
if a < 129 && b < 256 {
(a * 256 + b) as usize
} else {
Self::NO_FROPS
}
}
OP_ANDN => {
if a < 3 && b < 13 {
(a * 13 + b) as usize
} else {
Self::NO_FROPS
}
}
OP_ORN => {
if a < 63 && b == 0 {
a as usize
} else if a == 0xFFFFFFFFFFFFFFFF && b == 0 {
(a - 0xFFFFFFFFFFFFFFFF) as usize + 63
} else {
Self::NO_FROPS
}
}
_ => return 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]
}
}
#[inline(always)]
pub fn count(&self) -> usize {
self.table.count()
}
#[cfg(test)]
pub fn test_table_offsets(&mut self) {
self.build_table();
let (start, offsets) = self.table.generate_table_offsets();
if (start != OP_TABLE_OFFSETS_START) || (offsets != OP_TABLE_OFFSETS) {
self.table.print_table_offsets();
panic!("Table offsets do not match expected values");
}
assert_eq!(start, OP_TABLE_OFFSETS_START);
assert_eq!(offsets, OP_TABLE_OFFSETS);
}
#[inline(always)]
pub fn generate_full_table(&self) -> Vec<(u8, u64, u64, u64, bool)> {
self.table.generate_full_table()
}
#[inline(always)]
pub fn generate_table(&self) -> Vec<(u8, u64, u64)> {
self.table.generate_table()
}
#[inline(always)]
pub fn generate_cmd(
&mut self,
cmd_name: &'static str,
default_file: &'static str,
) -> Result<(), Box<dyn Error>> {
self.build_table();
let full_table = self.generate_full_table();
let full_table_count = full_table.len();
self.table.generate_cmd(
"Zisk",
"BinaryBasicFrops",
cmd_name,
default_file,
full_table,
full_table_count,
)
}
}
#[test]
fn test_table_offsets() {
let mut fops = BinaryBasicFrops::new();
fops.test_table_offsets();
}
#[test]
fn test_all_accessible_values() {
let mut fops = BinaryBasicFrops::new();
fops.build_table();
let table = fops.generate_full_table();
FrequentOpsHelpers::test_all_accessible_values(
&table,
BinaryBasicFrops::is_frequent_op,
BinaryBasicFrops::get_row,
);
}