use crate::{source_to_str, store_to_str, InstContext};
pub const SRC_C: u64 = 0;
pub const SRC_MEM: u64 = 1;
pub const SRC_IMM: u64 = 2;
pub const SRC_STEP: u64 = 3;
pub const SRC_IND: u64 = 5;
pub const SRC_REG: u64 = 6;
pub const STORE_NONE: u64 = 0;
pub const STORE_MEM: u64 = 1;
pub const STORE_IND: u64 = 2;
pub const STORE_REG: u64 = 3;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd)]
#[repr(u32)]
pub enum ZiskOperationType {
None,
Internal,
Arith,
Binary,
BinaryE,
Keccak,
Sha256,
Poseidon,
Blake2,
PubOut,
ArithEq,
ArithEq384,
BigInt, Evm,
Dma, FcallParam,
Fcall,
FcallGet,
Profile,
}
pub const NONE_OP_TYPE_ID: u32 = ZiskOperationType::None as u32;
pub const INTERNAL_OP_TYPE_ID: u32 = ZiskOperationType::Internal as u32;
pub const ARITH_OP_TYPE_ID: u32 = ZiskOperationType::Arith as u32;
pub const BINARY_OP_TYPE_ID: u32 = ZiskOperationType::Binary as u32;
pub const BINARY_E_OP_TYPE_ID: u32 = ZiskOperationType::BinaryE as u32;
pub const KECCAK_OP_TYPE_ID: u32 = ZiskOperationType::Keccak as u32;
pub const SHA256_OP_TYPE_ID: u32 = ZiskOperationType::Sha256 as u32;
pub const POSEIDON_OP_TYPE_ID: u32 = ZiskOperationType::Poseidon as u32;
pub const PUB_OUT_OP_TYPE_ID: u32 = ZiskOperationType::PubOut as u32;
pub const ARITH_EQ_OP_TYPE_ID: u32 = ZiskOperationType::ArithEq as u32;
pub const ARITH_EQ_384_OP_TYPE_ID: u32 = ZiskOperationType::ArithEq384 as u32;
pub const BIG_INT_OP_TYPE_ID: u32 = ZiskOperationType::BigInt as u32;
pub const EVM_OP_TYPE_ID: u32 = ZiskOperationType::Evm as u32;
pub const FCALL_PARAM_OP_TYPE_ID: u32 = ZiskOperationType::FcallParam as u32;
pub const FCALL_OP_TYPE_ID: u32 = ZiskOperationType::Fcall as u32;
pub const DMA_OP_TYPE_ID: u32 = ZiskOperationType::Dma as u32;
pub const BLAKE2_OP_TYPE_ID: u32 = ZiskOperationType::Blake2 as u32;
#[derive(Debug, Clone)]
pub struct ZiskInst {
pub paddr: u64,
pub store_pc: bool,
pub store_use_sp: bool,
pub store: u64,
pub store_offset: i64,
pub set_pc: bool,
pub is_precompiled: bool,
pub ind_width: u64,
pub end: bool,
pub a_src: u64,
pub a_use_sp_imm1: u64,
pub a_offset_imm0: u64,
pub b_src: u64,
pub b_use_sp_imm1: u64,
pub b_offset_imm0: u64,
pub jmp_offset1: i64,
pub jmp_offset2: i64,
pub is_external_op: bool,
pub op: u8,
pub func: fn(&mut InstContext) -> (),
pub op_str: &'static str,
pub op_type: ZiskOperationType,
pub verbose: String,
pub m32: bool,
pub input_size: u64,
pub sorted_pc_list_index: usize,
pub riscv_inst: Option<String>,
pub index: u64, pub next_internal_inst: Option<u64>, pub external_ref_addr: Option<u64>, pub meta_rs1: Option<u8>, pub meta_rd: Option<u8>, }
impl Default for ZiskInst {
fn default() -> Self {
Self {
paddr: 0,
store_pc: false,
store_use_sp: false,
store: 0,
store_offset: 0,
set_pc: false,
is_precompiled: false,
ind_width: 0,
end: false,
a_src: 0,
a_use_sp_imm1: 0,
a_offset_imm0: 0,
b_src: 0,
b_use_sp_imm1: 0,
b_offset_imm0: 0,
jmp_offset1: 0,
jmp_offset2: 0,
is_external_op: false,
op: 0,
func: |_| (),
op_str: "",
op_type: ZiskOperationType::None,
verbose: String::new(),
m32: false,
input_size: 0,
sorted_pc_list_index: 0,
riscv_inst: None,
index: 0,
next_internal_inst: None,
external_ref_addr: None,
meta_rs1: None,
meta_rd: None,
}
}
}
impl ZiskInst {
pub fn to_text(&self) -> String {
let mut s = String::new();
if self.paddr != 0 {
s += &format!(" paddr=0x{:x}", self.paddr);
}
if !self.verbose.is_empty() {
s += &format!(" verbose={}", self.verbose);
}
s += &format!(" a_src={}={}", self.a_src, source_to_str(self.a_src));
if self.a_use_sp_imm1 != 0 {
s += &format!(" a_use_sp_imm1=0x{:x}", self.a_use_sp_imm1);
}
if self.a_offset_imm0 != 0 {
s += &format!(" a_offset_imm0=0x{:x}", self.a_offset_imm0);
}
s += &format!(" b_src={}={}", self.b_src, source_to_str(self.b_src));
if self.b_use_sp_imm1 != 0 {
s += &format!(" b_use_sp_imm1=0x{:x}", self.b_use_sp_imm1);
}
if self.b_offset_imm0 != 0 {
s += &format!(" b_offset_imm0=0x{:x}", self.b_offset_imm0);
}
if self.ind_width != 0 {
s += &format!(" ind_width={}", self.ind_width);
}
{
s += &format!(" op={}={}", self.op, self.op_str);
}
if self.store != 0 {
s += &format!(" store={}={}", self.store, store_to_str(self.store));
}
if self.store_offset != 0 {
s += &format!(" store_offset=0x{:x}", self.store_offset as u64);
}
if self.store_pc {
s += &format!(" store_pc={}", self.store_pc);
}
if self.store_use_sp {
s += &format!(" store_use_sp={}", self.store_use_sp);
}
if self.set_pc {
s += &format!(" set_pc={}", self.set_pc);
}
if self.is_precompiled {
s += &format!(" op_with_step={}", self.is_precompiled);
}
if self.jmp_offset1 != 0 {
s += &format!(" jmp_offset1={}", self.jmp_offset1);
}
if self.jmp_offset2 != 0 {
s += &format!(" jmp_offset2={}", self.jmp_offset2);
}
if self.end {
s += &format!(" end={}", self.end);
}
if self.is_external_op {
s += &format!(" is_external_op={}", self.is_external_op);
}
if self.m32 {
s += &format!(" m32={}", self.m32);
}
s += &format!(" index={}", self.index);
if let Some(next_internal_inst) = self.next_internal_inst {
s += &format!(" next_internal_inst=0x{:x}", next_internal_inst);
}
if let Some(meta_reg) = self.meta_rs1 {
s += &format!(" meta_rs1=0x{:x}", meta_reg);
}
if let Some(meta_reg) = self.meta_rd {
s += &format!(" meta_rd=0x{:x}", meta_reg);
}
s.remove(0); s
}
pub fn get_flags(&self) -> u64 {
let flags: u64 = 1
| (((self.a_src == SRC_IMM) as u64) << 1)
| (((self.a_src == SRC_MEM) as u64) << 2)
| ((self.is_precompiled as u64) << 3)
| (((self.b_src == SRC_IMM) as u64) << 4)
| (((self.b_src == SRC_MEM) as u64) << 5)
| ((self.is_external_op as u64) << 6)
| ((self.store_pc as u64) << 7)
| (((self.store == STORE_MEM) as u64) << 8)
| (((self.store == STORE_IND) as u64) << 9)
| ((self.set_pc as u64) << 10)
| ((self.m32 as u64) << 11)
| (((self.b_src == SRC_IND) as u64) << 12)
| (((self.a_src == SRC_REG) as u64) << 13)
| (((self.b_src == SRC_REG) as u64) << 14)
| (((self.store == STORE_REG) as u64) << 15);
flags
}
}