upload code
This commit is contained in:
commit
7e10d070b3
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/target
|
219
Cargo.lock
generated
Normal file
219
Cargo.lock
generated
Normal file
@ -0,0 +1,219 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
version = "0.10.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "cpufeatures"
|
||||
version = "0.2.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crypto-common"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.10.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
|
||||
dependencies = [
|
||||
"block-buffer",
|
||||
"crypto-common",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
|
||||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "0.14.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
|
||||
dependencies = [
|
||||
"typenum",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.152"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7"
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149"
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.19.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
|
||||
|
||||
[[package]]
|
||||
name = "pest"
|
||||
version = "2.7.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1f200d8d83c44a45b21764d1916299752ca035d15ecd46faca3e9a2a2bf6ad06"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"thiserror",
|
||||
"ucd-trie",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pest_derive"
|
||||
version = "2.7.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bcd6ab1236bbdb3a49027e920e693192ebfe8913f6d60e294de57463a493cfde"
|
||||
dependencies = [
|
||||
"pest",
|
||||
"pest_generator",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pest_generator"
|
||||
version = "2.7.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2a31940305ffc96863a735bef7c7994a00b325a7138fdbc5bda0f1a0476d3275"
|
||||
dependencies = [
|
||||
"pest",
|
||||
"pest_meta",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pest_meta"
|
||||
version = "2.7.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a7ff62f5259e53b78d1af898941cdcdccfae7385cf7d793a6e55de5d05bb4b7d"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"pest",
|
||||
"sha2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.76"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha2"
|
||||
version = "0.10.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cpufeatures",
|
||||
"digest",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.48"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.56"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.56"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
|
||||
|
||||
[[package]]
|
||||
name = "ucd-trie"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||
|
||||
[[package]]
|
||||
name = "zkevm"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"either",
|
||||
"pest",
|
||||
"pest_derive",
|
||||
]
|
11
Cargo.toml
Normal file
11
Cargo.toml
Normal file
@ -0,0 +1,11 @@
|
||||
[package]
|
||||
name = "zkevm"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
either = "1.9.0"
|
||||
pest = "2.7.6"
|
||||
pest_derive = "2.7.6"
|
1112
src/execution.rs
Normal file
1112
src/execution.rs
Normal file
File diff suppressed because it is too large
Load Diff
91
src/main.rs
Normal file
91
src/main.rs
Normal file
@ -0,0 +1,91 @@
|
||||
use std::fs;
|
||||
|
||||
mod execution;
|
||||
mod zkasm;
|
||||
|
||||
use crate::zkasm::{parse_instruction_list, parse_expr, Definition, Program, Rule, Subroutine, ZkasmParser};
|
||||
use pest::Parser;
|
||||
|
||||
fn main() {
|
||||
let filepath = std::env::args().nth(1).expect("dude, pass a file to decompile");
|
||||
let input = fs::read_to_string(filepath).expect("cannot read file");
|
||||
|
||||
let program = ZkasmParser::parse(Rule::program, &input)
|
||||
.expect("file format is wrong or the parser is wrong")
|
||||
.next()
|
||||
.expect("cannot parse input file as a zkasm program");
|
||||
|
||||
let definitions = program
|
||||
.into_inner()
|
||||
.find_map(|x| match x.as_rule() {
|
||||
Rule::definition_list => Some(x),
|
||||
_ => None,
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let mut program_ast = Program {
|
||||
constants: Vec::new(),
|
||||
definitions: Vec::new(),
|
||||
};
|
||||
|
||||
for definition in definitions.into_inner() {
|
||||
match definition.as_rule() {
|
||||
Rule::variable => {
|
||||
let mut var = definition.into_inner();
|
||||
let vartype = var.next().unwrap();
|
||||
let varname = var.next().unwrap().as_str();
|
||||
if vartype.as_str() == "GLOBAL" {
|
||||
program_ast
|
||||
.definitions
|
||||
.push(Definition::VariableGlobal(varname.into(), var.next().map(parse_expr)));
|
||||
} else if vartype.as_str() == "CTX" {
|
||||
program_ast
|
||||
.definitions
|
||||
.push(Definition::VariableCTX(varname.into(), var.next().map(parse_expr)));
|
||||
} else {
|
||||
unreachable!();
|
||||
}
|
||||
}
|
||||
Rule::constant => {
|
||||
let mut var = definition.into_inner();
|
||||
let constid = var.next().unwrap().as_str();
|
||||
if let Some(constexpr) = var.next() {
|
||||
program_ast.constants.push((constid.into(), format!("{}", parse_expr(constexpr))));
|
||||
} else {
|
||||
program_ast.constants.push((constid.into(), "0".into()));
|
||||
}
|
||||
}
|
||||
Rule::subroutine => {
|
||||
let mut subroutine = definition.into_inner();
|
||||
let name = subroutine.next().unwrap().as_str();
|
||||
if let Some(instructions) = subroutine.next() {
|
||||
let subroutine_ast = Subroutine {
|
||||
name: name.to_string(),
|
||||
instructions: parse_instruction_list(instructions),
|
||||
};
|
||||
program_ast
|
||||
.definitions
|
||||
.push(Definition::Subroutine(subroutine_ast));
|
||||
} else {
|
||||
// empty instruction list, or just a label that is alias to the next
|
||||
let subroutine_ast = Subroutine {
|
||||
name: name.to_string(),
|
||||
instructions: Vec::new(),
|
||||
};
|
||||
program_ast
|
||||
.definitions
|
||||
.push(Definition::Subroutine(subroutine_ast));
|
||||
}
|
||||
}
|
||||
Rule::include => {
|
||||
let file = definition.into_inner().next().unwrap().as_str().to_string().replace("\"", "");
|
||||
program_ast.definitions.push(Definition::Include(file));
|
||||
}
|
||||
_ => {
|
||||
unreachable!();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
program_ast.decompile();
|
||||
}
|
269
src/zkasm.pest
Normal file
269
src/zkasm.pest
Normal file
@ -0,0 +1,269 @@
|
||||
identifier = @{
|
||||
ASCII_ALPHA ~ ("_" | ASCII_ALPHANUMERIC)*
|
||||
}
|
||||
|
||||
reference = @{
|
||||
"@" ~ identifier
|
||||
}
|
||||
|
||||
instruction_name = @{
|
||||
ASCII_ALPHA_UPPER ~ ("_" | ASCII_ALPHANUMERIC)*
|
||||
}
|
||||
|
||||
register = @{
|
||||
"CTX"
|
||||
| "A"
|
||||
| "B"
|
||||
| "C"
|
||||
| "D"
|
||||
| "E"
|
||||
| "F"
|
||||
| "RR"
|
||||
| "SR"
|
||||
| "SP"
|
||||
| "PC"
|
||||
| "RCX"
|
||||
| "GAS"
|
||||
| "HASHPOS"
|
||||
| "HASH_LEFT"
|
||||
| "HASH_RIGHT"
|
||||
| "OLD_ROOT"
|
||||
| "NEW_ROOT"
|
||||
| "VALUE_LOW"
|
||||
| "VALUE_HIGH"
|
||||
| "SIBLING_VALUE_HASH"
|
||||
| "RKEY_BIT"
|
||||
| "RKEY"
|
||||
| "SIBLING_RKEY"
|
||||
| "LEVEL"
|
||||
}
|
||||
|
||||
memory_scope = {
|
||||
"MEM"
|
||||
| "STACK"
|
||||
| "SYS"
|
||||
}
|
||||
memory_access = {
|
||||
memory_scope ~ ":" ~ expr
|
||||
}
|
||||
|
||||
instruction_right_param_atomic = {
|
||||
memory_access
|
||||
| expr
|
||||
}
|
||||
|
||||
instruction_right_param_list = _{
|
||||
instruction_right_param_atomic ~ "," ~ instruction_right_param_list
|
||||
| instruction_right_param_atomic
|
||||
}
|
||||
|
||||
instruction_right = {
|
||||
instruction_name ~ "(" ~ instruction_right_param_list? ~ ")"
|
||||
| instruction_name
|
||||
}
|
||||
|
||||
assignment = {
|
||||
expr ~ "=>" ~ register ~ ("," ~ register)*
|
||||
}
|
||||
|
||||
dotaccess = @{
|
||||
identifier ~ "." ~ identifier
|
||||
}
|
||||
|
||||
invocation_param_atomic = {
|
||||
dotaccess
|
||||
| identifier
|
||||
| register
|
||||
}
|
||||
|
||||
params = {
|
||||
invocation_param_atomic ~ ("," ~ invocation_param_atomic)*
|
||||
}
|
||||
|
||||
invocation = {
|
||||
identifier ~ "(" ~ params? ~ ")"
|
||||
}
|
||||
|
||||
freeinput_param = {
|
||||
invocation
|
||||
| expr
|
||||
}
|
||||
|
||||
freeinput = {
|
||||
|
||||
| "$${" ~ (!("}") ~ ANY)* ~ "}"
|
||||
| "$0{" ~ (!("}") ~ ANY)* ~ "}"
|
||||
| "${" ~ (!("}") ~ ANY)* ~ "}"
|
||||
| "$"
|
||||
}
|
||||
|
||||
binop = _{
|
||||
power
|
||||
| add
|
||||
| sub
|
||||
| mul
|
||||
| div
|
||||
| mod
|
||||
| shl
|
||||
| shr
|
||||
| xor
|
||||
| and
|
||||
| or
|
||||
| lt
|
||||
| gt
|
||||
| lte
|
||||
| gte
|
||||
| eq
|
||||
| neq
|
||||
| land
|
||||
| lor
|
||||
}
|
||||
power = { "**" }
|
||||
add = { "+" }
|
||||
sub = { "-" }
|
||||
mul = { "*" }
|
||||
div = { "/" }
|
||||
mod = { "%" }
|
||||
shl = { "<<" }
|
||||
shr = { ">>" }
|
||||
xor = { "^" }
|
||||
and = { "&" }
|
||||
or = { "|" }
|
||||
lt = { "<" }
|
||||
gt = { ">" }
|
||||
lte = { "<=" }
|
||||
gte = { ">=" }
|
||||
eq = { "==" }
|
||||
neq = { "!=" }
|
||||
land = { "&&" }
|
||||
lor = { "||" }
|
||||
|
||||
special_variable = @{
|
||||
!("VAR") ~ !("INCLUDE") ~ ("_" | ASCII_ALPHANUMERIC)+ ~ !(":")
|
||||
}
|
||||
|
||||
number = @{
|
||||
"0x" ~ ASCII_HEX_DIGIT+ ~ "n"?
|
||||
| ASCII_DIGIT+ ~ "n"?
|
||||
}
|
||||
|
||||
atomic_operand = _{
|
||||
number
|
||||
| constid
|
||||
| freeinput
|
||||
| special_variable
|
||||
| reference
|
||||
| register
|
||||
}
|
||||
|
||||
selfmodifying = _{
|
||||
increment | decrement
|
||||
}
|
||||
increment = {"++"}
|
||||
decrement = {"--"}
|
||||
|
||||
|
||||
exprfragment = _{
|
||||
atomic_operand ~ binop ~ atomic_operand
|
||||
| atomic_operand ~ selfmodifying?
|
||||
| negate_expr
|
||||
| "(" ~ expr_all ~ ")"
|
||||
}
|
||||
expr = {
|
||||
exprfragment ~ (binop ~ exprfragment)*
|
||||
}
|
||||
|
||||
not = { "!" }
|
||||
negate = { "-" }
|
||||
negate_expr = _{
|
||||
(not | negate) ~ expr
|
||||
}
|
||||
|
||||
tenary_expr = {
|
||||
expr ~ "?" ~ expr ~ ":" ~ expr
|
||||
}
|
||||
|
||||
expr_all = _{
|
||||
tenary_expr
|
||||
| negate_expr
|
||||
| expr
|
||||
}
|
||||
|
||||
instruction_type1 = {
|
||||
assignment
|
||||
| expr
|
||||
}
|
||||
|
||||
instruction_type2 = {
|
||||
instruction_right ~ ("," ~ instruction_right)*
|
||||
}
|
||||
|
||||
instruction_type3 = {
|
||||
instruction_type1 ~ ":" ~ instruction_type2
|
||||
}
|
||||
|
||||
instruction = _{
|
||||
instruction_type3
|
||||
| instruction_type1
|
||||
| ":" ~ instruction_type2
|
||||
}
|
||||
|
||||
instruction_list = {
|
||||
instruction ~ (NEWLINE* ~ instruction)*
|
||||
}
|
||||
|
||||
subroutine_id = @{ ("_" | ASCII_ALPHANUMERIC)* }
|
||||
|
||||
subroutine = {
|
||||
subroutine_id ~ ":" ~ NEWLINE* ~ instruction_list?
|
||||
}
|
||||
|
||||
definition = _{
|
||||
constant
|
||||
| variable
|
||||
| subroutine
|
||||
| include
|
||||
}
|
||||
|
||||
definition_list = {
|
||||
definition ~ (NEWLINE* ~ definition)*
|
||||
}
|
||||
|
||||
variable_type = {
|
||||
"GLOBAL"
|
||||
| "CTX"
|
||||
}
|
||||
variable = {
|
||||
"VAR" ~ variable_type ~ identifier ~ ("[" ~ expr ~ "]")?
|
||||
}
|
||||
|
||||
constid = @{
|
||||
"%" ~ identifier
|
||||
}
|
||||
constant = {
|
||||
("CONSTL" | "CONST") ~ constid ~ ("=" ~ expr)?
|
||||
}
|
||||
|
||||
file_path_component = @{
|
||||
(ASCII_ALPHANUMERIC | "_" | "-" | ".")+
|
||||
}
|
||||
file_path = @{
|
||||
file_path_component ~ ("/" ~ file_path_component)*
|
||||
}
|
||||
include_name = @{
|
||||
"\"" ~ file_path ~ "\""
|
||||
}
|
||||
include = {
|
||||
"INCLUDE" ~ include_name
|
||||
}
|
||||
|
||||
// allow newline between
|
||||
program = {
|
||||
SOI ~ NEWLINE* ~ definition_list ~ NEWLINE* ~ EOI
|
||||
}
|
||||
|
||||
WHITESPACE = _{ " " | "\t" }
|
||||
|
||||
comment_type1 = _{ ";" ~ (!NEWLINE ~ ANY)* ~ NEWLINE? }
|
||||
comment_type2 = _{ "/*" ~ (!"*/" ~ ANY)* ~ "*/" }
|
||||
COMMENT = _{ comment_type1 | comment_type2 }
|
623
src/zkasm.rs
Normal file
623
src/zkasm.rs
Normal file
@ -0,0 +1,623 @@
|
||||
#[derive(pest_derive::Parser)]
|
||||
#[grammar = "zkasm.pest"]
|
||||
pub struct ZkasmParser;
|
||||
|
||||
use pest::iterators::Pair;
|
||||
|
||||
use std::fmt;
|
||||
|
||||
use crate::execution::Execution;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum UnaryOp {
|
||||
Negate,
|
||||
Not,
|
||||
}
|
||||
|
||||
impl fmt::Display for UnaryOp {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
UnaryOp::Negate => write!(f, "-"),
|
||||
UnaryOp::Not => write!(f, "!"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum BinaryOp {
|
||||
Add,
|
||||
Sub,
|
||||
Mul,
|
||||
Div,
|
||||
Mod,
|
||||
Lt,
|
||||
Gt,
|
||||
Le,
|
||||
Ge,
|
||||
Eq,
|
||||
Neq,
|
||||
LogicalXor,
|
||||
LogicalAnd,
|
||||
LogicalOr,
|
||||
ArithAnd,
|
||||
ArithOr,
|
||||
ShiftLeft,
|
||||
ShiftRight,
|
||||
Power,
|
||||
}
|
||||
|
||||
impl fmt::Display for BinaryOp {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let s = match self {
|
||||
BinaryOp::Add => "+",
|
||||
BinaryOp::Sub => "-",
|
||||
BinaryOp::Mul => "*",
|
||||
BinaryOp::Div => "/",
|
||||
BinaryOp::Lt => "<",
|
||||
BinaryOp::Gt => ">",
|
||||
BinaryOp::Le => "<=",
|
||||
BinaryOp::Ge => ">=",
|
||||
BinaryOp::Eq => "==",
|
||||
BinaryOp::Neq => "!=",
|
||||
BinaryOp::ArithOr => "|",
|
||||
BinaryOp::ArithAnd => "&",
|
||||
BinaryOp::LogicalOr => "||",
|
||||
BinaryOp::LogicalAnd => "&&",
|
||||
BinaryOp::ShiftLeft => "<<",
|
||||
BinaryOp::ShiftRight => ">>",
|
||||
BinaryOp::Power => "**",
|
||||
BinaryOp::Mod => "%",
|
||||
_ => {
|
||||
unreachable!()
|
||||
}
|
||||
};
|
||||
write!(f, "{}", s)
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<BinaryOp> for String {
|
||||
fn into(self) -> BinaryOp {
|
||||
match self.as_str() {
|
||||
"+" => BinaryOp::Add,
|
||||
"-" => BinaryOp::Sub,
|
||||
"*" => BinaryOp::Mul,
|
||||
"/" => BinaryOp::Div,
|
||||
"%" => BinaryOp::Mod,
|
||||
"<" => BinaryOp::Lt,
|
||||
">" => BinaryOp::Gt,
|
||||
"<=" => BinaryOp::Le,
|
||||
">=" => BinaryOp::Ge,
|
||||
"==" => BinaryOp::Eq,
|
||||
"!=" => BinaryOp::Neq,
|
||||
"|" => BinaryOp::ArithOr,
|
||||
"&" => BinaryOp::ArithAnd,
|
||||
"||" => BinaryOp::LogicalOr,
|
||||
"&&" => BinaryOp::LogicalAnd,
|
||||
"<<" => BinaryOp::ShiftLeft,
|
||||
">>" => BinaryOp::ShiftRight,
|
||||
"**" => BinaryOp::Power,
|
||||
_ => {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Expr {
|
||||
Unary(UnaryOp, Box<Expr>),
|
||||
Binary(Box<Expr>, BinaryOp, Box<Expr>),
|
||||
Tenary(Box<Expr>, Box<Expr>, Box<Expr>),
|
||||
FreeInput(String),
|
||||
Register(Register),
|
||||
Value(u64),
|
||||
ValueComplex(String), // for hex number
|
||||
NameVariable(String),
|
||||
Increment(Box<Expr>),
|
||||
Decrement(Box<Expr>),
|
||||
}
|
||||
|
||||
impl fmt::Display for Expr {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
Expr::Unary(op, expr) => {
|
||||
write!(f, "{}({})", op, expr)
|
||||
}
|
||||
Expr::Binary(lhs, op, rhs) => {
|
||||
write!(f, "({} {} {})", lhs, op, rhs)
|
||||
}
|
||||
Expr::Tenary(expr, ifbranch, elsebranch) => {
|
||||
write!(f, "({} ? {} : {})", expr, ifbranch, elsebranch)
|
||||
}
|
||||
Expr::Register(r) => {
|
||||
write!(f, "{}", r.name())
|
||||
}
|
||||
Expr::Value(v) => {
|
||||
write!(f, "{}", v)
|
||||
}
|
||||
Expr::ValueComplex(v) => {
|
||||
if v.starts_with("0x") {
|
||||
match u64::from_str_radix(v.strip_prefix("0x").unwrap(), 16).ok() {
|
||||
Some(s) => write!(f, "{}/* {} */", s, v),
|
||||
None => write!(f, "{}", v),
|
||||
}
|
||||
} else {
|
||||
write!(f, "{}", v)
|
||||
}
|
||||
}
|
||||
Expr::NameVariable(v) => {
|
||||
write!(f, "{}", v)
|
||||
}
|
||||
Expr::FreeInput(free) => {
|
||||
write!(f, "{}", free)
|
||||
}
|
||||
Expr::Increment(e) => {
|
||||
write!(f, "({})++", e)
|
||||
}
|
||||
Expr::Decrement(e) => {
|
||||
write!(f, "({})--", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
|
||||
pub enum Register {
|
||||
A,
|
||||
B,
|
||||
C,
|
||||
D,
|
||||
E,
|
||||
SP,
|
||||
RR,
|
||||
SR,
|
||||
PC,
|
||||
CTX,
|
||||
RCX,
|
||||
GAS,
|
||||
HASHPOS,
|
||||
HASH_LEFT,
|
||||
HASH_RIGHT,
|
||||
OLD_ROOT,
|
||||
NEW_ROOT,
|
||||
VALUE_LOW,
|
||||
VALUE_HIGH,
|
||||
SIBLING_VALUE_HASH,
|
||||
RKEY,
|
||||
SIBLING_RKEY,
|
||||
RKEY_BIT,
|
||||
LEVEL,
|
||||
}
|
||||
|
||||
impl fmt::Display for Register {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
_ if self.is_special() => write!(f, "{}", self.name()),
|
||||
Register::A => write!(f, "A"),
|
||||
Register::B => write!(f, "B"),
|
||||
Register::C => write!(f, "C"),
|
||||
Register::D => write!(f, "D"),
|
||||
Register::E => write!(f, "E"),
|
||||
Register::SP => write!(f, "SP"),
|
||||
Register::SR => write!(f, "SR"),
|
||||
Register::RR => write!(f, "RR"),
|
||||
Register::PC => write!(f, "PC"),
|
||||
Register::GAS => write!(f, "GAS"),
|
||||
Register::CTX => write!(f, "CTX"),
|
||||
Register::RCX => write!(f, "RCX"),
|
||||
Register::HASHPOS => write!(f, "HASHPOS"),
|
||||
Register::HASH_LEFT => write!(f, "HASH_LEFT"),
|
||||
Register::HASH_RIGHT => write!(f, "HASH_RIGHT"),
|
||||
Register::OLD_ROOT => write!(f, "OLD_ROOT"),
|
||||
Register::NEW_ROOT => write!(f, "NEW_ROOT"),
|
||||
Register::VALUE_LOW => write!(f, "VALUE_LOW"),
|
||||
Register::VALUE_HIGH => write!(f, "VALUE_HIGH"),
|
||||
Register::SIBLING_VALUE_HASH => write!(f, "SIBLING_VALUE_HASH"),
|
||||
Register::RKEY => write!(f, "RKEY"),
|
||||
Register::SIBLING_RKEY => write!(f, "SIBLING_RKEY"),
|
||||
Register::RKEY_BIT => write!(f, "RKEY_BIT"),
|
||||
Register::LEVEL => write!(f, "LEVEL"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Register {
|
||||
pub fn is_special(self) -> bool {
|
||||
match self {
|
||||
Register::A | Register::B | Register::C | Register::D | Register::E => false,
|
||||
_ => true,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn name(self) -> String {
|
||||
match self {
|
||||
Register::SR => "StateRoot".to_string(),
|
||||
Register::RR => "ReturnRegister".to_string(),
|
||||
Register::GAS => "GAS".to_string(),
|
||||
Register::HASHPOS => "HASHPOS".to_string(),
|
||||
Register::CTX => "CONTEXT".to_string(),
|
||||
Register::PC => "EVM(ProgramCounter)".to_string(),
|
||||
Register::SP => "EVM(StackPointer)".to_string(),
|
||||
_ => format!("{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_name(name: &str) -> Self {
|
||||
match name {
|
||||
"A" => Register::A,
|
||||
"B" => Register::B,
|
||||
"C" => Register::C,
|
||||
"D" => Register::D,
|
||||
"E" => Register::E,
|
||||
"SP" => Register::SP,
|
||||
"RR" => Register::RR,
|
||||
"SR" => Register::SR,
|
||||
"PC" => Register::PC,
|
||||
"CTX" => Register::CTX,
|
||||
"RCX" => Register::RCX,
|
||||
"GAS" => Register::GAS,
|
||||
"HASHPOS" => Register::HASHPOS,
|
||||
"HASH_LEFT" => Register::HASH_LEFT,
|
||||
"HASH_RIGHT" => Register::HASH_RIGHT,
|
||||
"OLD_ROOT" => Register::OLD_ROOT,
|
||||
"NEW_ROOT" => Register::NEW_ROOT,
|
||||
"VALUE_LOW" => Register::VALUE_LOW,
|
||||
"VALUE_HIGH" => Register::VALUE_HIGH,
|
||||
"SIBLING_VALUE_HASH" => Register::SIBLING_VALUE_HASH,
|
||||
"RKEY" => Register::RKEY,
|
||||
"SIBLING_RKEY" => Register::SIBLING_RKEY,
|
||||
"RKEY_BIT" => Register::RKEY_BIT,
|
||||
"LEVEL" => Register::LEVEL,
|
||||
_ => {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum AccessPlace {
|
||||
Memory,
|
||||
Stack,
|
||||
System,
|
||||
}
|
||||
|
||||
impl fmt::Display for AccessPlace {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
AccessPlace::Memory => write!(f, "MEM"),
|
||||
AccessPlace::Stack => write!(f, "STACK"),
|
||||
AccessPlace::System => write!(f, "SYS"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum InstructionOpcodeParam {
|
||||
NameVariable(String),
|
||||
Accessor(AccessPlace, Expr),
|
||||
Calculated(Expr),
|
||||
}
|
||||
|
||||
impl fmt::Display for InstructionOpcodeParam {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
InstructionOpcodeParam::NameVariable(name) => {
|
||||
write!(f, "{}", name)
|
||||
}
|
||||
InstructionOpcodeParam::Accessor(access, expr) => {
|
||||
write!(f, "{}:{}", access, expr)
|
||||
}
|
||||
InstructionOpcodeParam::Calculated(expr) => {
|
||||
write!(f, "{}", expr)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct InstructionOpcode {
|
||||
pub name: String,
|
||||
pub params: Vec<InstructionOpcodeParam>,
|
||||
}
|
||||
|
||||
impl InstructionOpcode {
|
||||
pub fn get_single(&self) -> InstructionOpcodeParam {
|
||||
self.params[0].clone()
|
||||
}
|
||||
|
||||
pub fn get_at(&self, idx: usize) -> Option<InstructionOpcodeParam> {
|
||||
self.params.get(idx).map(|x| x.clone())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Instruction {
|
||||
Expr(Expr),
|
||||
Assignment(Expr, Vec<Register>),
|
||||
Opcode(InstructionOpcode),
|
||||
Compound(Box<Instruction>, Vec<Instruction>),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Subroutine {
|
||||
pub name: String,
|
||||
pub instructions: Vec<Instruction>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Definition {
|
||||
VariableGlobal(String, Option<Expr>),
|
||||
VariableCTX(String, Option<Expr>),
|
||||
Subroutine(Subroutine),
|
||||
Include(String),
|
||||
}
|
||||
|
||||
// temporarily use display as a decompile printer
|
||||
impl fmt::Display for Definition {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
Definition::VariableCTX(var, Some(array)) => {
|
||||
write!(f, "VAR CTX {}[{}]", var, array)
|
||||
}
|
||||
Definition::VariableGlobal(var, Some(array)) => {
|
||||
write!(f, "VAR GLOBAL {}[{}]", var, array)
|
||||
}
|
||||
Definition::VariableCTX(var, None) => {
|
||||
write!(f, "VAR CTX {}", var)
|
||||
}
|
||||
Definition::VariableGlobal(var, None) => {
|
||||
write!(f, "VAR GLOBAL {}", var)
|
||||
}
|
||||
Definition::Include(include) => {
|
||||
write!(f, "INCLUDE {}", include)
|
||||
}
|
||||
Definition::Subroutine(subroutine) => {
|
||||
// subroutine will be decompiled
|
||||
let mut run = Execution::new();
|
||||
run.start(subroutine);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Program {
|
||||
pub constants: Vec<(String, String)>,
|
||||
pub definitions: Vec<Definition>,
|
||||
}
|
||||
|
||||
impl Program {
|
||||
pub fn decompile(self) {
|
||||
for c in self.constants {
|
||||
println!("CONST {} = {}", c.0, c.1);
|
||||
}
|
||||
for def in self.definitions {
|
||||
println!("{}", def);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_long_expr(expr: Pair<Rule>) -> Expr {
|
||||
use pest::pratt_parser::PrattParser;
|
||||
use pest::pratt_parser::{Assoc, Op};
|
||||
|
||||
assert!(expr.as_rule() == Rule::expr);
|
||||
|
||||
let pratt =
|
||||
PrattParser::new()
|
||||
.op(Op::infix(Rule::r#mod, Assoc::Left))
|
||||
.op(Op::infix(Rule::add, Assoc::Left) | Op::infix(Rule::sub, Assoc::Left))
|
||||
.op(Op::infix(Rule::mul, Assoc::Left) | Op::infix(Rule::div, Assoc::Left))
|
||||
.op(Op::infix(Rule::and, Assoc::Left) | Op::infix(Rule::or, Assoc::Left) | Op::infix(Rule::xor, Assoc::Left))
|
||||
.op(Op::infix(Rule::shl, Assoc::Left) | Op::infix(Rule::shr, Assoc::Left))
|
||||
.op(Op::infix(Rule::power, Assoc::Left))
|
||||
.op(Op::prefix(Rule::not) | Op::prefix(Rule::negate))
|
||||
.op(Op::postfix(Rule::increment) | Op::postfix(Rule::decrement))
|
||||
;
|
||||
|
||||
// println!("{:?}", expr);
|
||||
|
||||
pratt
|
||||
.map_primary(|primary| match primary.as_rule() {
|
||||
Rule::expr => {
|
||||
// ( expr )
|
||||
parse_expr(primary)
|
||||
}
|
||||
_ => {
|
||||
parse_expr_atomic(primary)
|
||||
}
|
||||
})
|
||||
.map_prefix(|op, rhs| {
|
||||
match op.as_str() {
|
||||
"-" => {
|
||||
Expr::Unary(UnaryOp::Negate, Box::new(rhs))
|
||||
}
|
||||
"!" => {
|
||||
Expr::Unary(UnaryOp::Not, Box::new(rhs))
|
||||
}
|
||||
_ => unreachable!()
|
||||
}})
|
||||
.map_infix(|lhs, op, rhs| {
|
||||
let binop: BinaryOp = op.as_str().to_string().into();
|
||||
Expr::Binary(Box::new(lhs.clone()), binop, Box::new(rhs.clone()))
|
||||
})
|
||||
.map_postfix(|expr, op| {
|
||||
match op.as_rule() {
|
||||
Rule::decrement => Expr::Decrement(Box::new(expr.clone())),
|
||||
Rule::increment => Expr::Increment(Box::new(expr.clone())),
|
||||
_ => unreachable!()
|
||||
}
|
||||
})
|
||||
.parse(expr.into_inner())
|
||||
}
|
||||
|
||||
fn parse_expr_atomic(expr: Pair<Rule>) -> Expr {
|
||||
match expr.as_rule() {
|
||||
Rule::register => Expr::Register(Register::from_name(expr.as_str())),
|
||||
Rule::number => {
|
||||
match expr.as_str().to_string().parse::<u64>().ok() {
|
||||
Some(v) => Expr::Value(v),
|
||||
None => Expr::ValueComplex(expr.as_str().into()),
|
||||
}
|
||||
}
|
||||
Rule::freeinput => Expr::FreeInput(expr.as_str().into()),
|
||||
Rule::special_variable => {
|
||||
let v = expr.as_str();
|
||||
match v {
|
||||
"A" | "B" | "C" | "D" | "E" | "SR" | "RR" | "SP" | "CTX" | "HASHPOS" => {
|
||||
Expr::Register(Register::from_name(v))
|
||||
}
|
||||
_ => Expr::NameVariable(v.into()),
|
||||
}
|
||||
}
|
||||
Rule::constid => {
|
||||
let v = expr.as_str();
|
||||
match v {
|
||||
"A" | "B" | "C" | "D" | "E" | "SR" | "RR" | "SP" | "CTX" | "HASHPOS" => {
|
||||
Expr::Register(Register::from_name(v))
|
||||
}
|
||||
_ => Expr::NameVariable(v.into()),
|
||||
}
|
||||
}
|
||||
Rule::reference => {
|
||||
let v = expr.as_str();
|
||||
Expr::NameVariable(v.into())
|
||||
}
|
||||
_ => {
|
||||
println!("parse atomic {:?}", expr);
|
||||
unreachable!();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_expr(inst: Pair<Rule>) -> Expr {
|
||||
match inst.as_rule() {
|
||||
Rule::expr => {
|
||||
parse_long_expr(inst)
|
||||
// let mut peak = inst.clone().into_inner();
|
||||
|
||||
// if peak.len() > 1 {
|
||||
// return parse_long_expr(inst);
|
||||
// }
|
||||
|
||||
// let expr = peak.next().unwrap();
|
||||
// parse_expr_atomic(expr)
|
||||
}
|
||||
Rule::negate_expr => {
|
||||
let mut p = inst.into_inner();
|
||||
let op = match p.next().unwrap().as_str() {
|
||||
"-" => UnaryOp::Negate,
|
||||
"!" => UnaryOp::Not,
|
||||
_ => unreachable!()
|
||||
};
|
||||
let expr = parse_expr(p.next().unwrap());
|
||||
Expr::Unary(op, Box::new(expr))
|
||||
}
|
||||
Rule::tenary_expr => {
|
||||
let mut p = inst.into_inner();
|
||||
let condition = parse_expr(p.next().unwrap());
|
||||
let ifbranch = parse_expr(p.next().unwrap());
|
||||
let elsebranch = parse_expr(p.next().unwrap());
|
||||
Expr::Tenary(Box::new(condition), Box::new(ifbranch), Box::new(elsebranch))
|
||||
}
|
||||
Rule::register | Rule::number | Rule::freeinput | Rule::special_variable | Rule::constid | Rule::reference => {
|
||||
parse_expr_atomic(inst)
|
||||
}
|
||||
_ => {
|
||||
unreachable!();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_param(param: Pair<Rule>) -> InstructionOpcodeParam {
|
||||
match param.as_rule() {
|
||||
Rule::identifier => InstructionOpcodeParam::NameVariable(param.as_str().into()),
|
||||
Rule::memory_access => {
|
||||
let mut p = param.into_inner();
|
||||
let scope = match p.next().unwrap().as_str() {
|
||||
"MEM" => AccessPlace::Memory,
|
||||
"STACK" => AccessPlace::Stack,
|
||||
"SYS" => AccessPlace::System,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
let expr = parse_expr(p.next().unwrap());
|
||||
InstructionOpcodeParam::Accessor(scope, expr)
|
||||
}
|
||||
Rule::expr => {
|
||||
let e = parse_expr(param);
|
||||
if let Expr::NameVariable(name) = e {
|
||||
InstructionOpcodeParam::NameVariable(name)
|
||||
} else {
|
||||
InstructionOpcodeParam::Calculated(e)
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
unreachable!();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// parse a single instruction, could be type 1, 2 or 3
|
||||
pub fn parse_instruction(instruction: Pair<Rule>) -> Instruction {
|
||||
// println!("parsing inst {:?}", instruction);
|
||||
match instruction.as_rule() {
|
||||
Rule::instruction_type1 => {
|
||||
let inst = instruction.into_inner().next().unwrap();
|
||||
if inst.as_rule() == Rule::expr {
|
||||
Instruction::Expr(parse_expr(inst))
|
||||
} else if inst.as_rule() == Rule::negate_expr {
|
||||
Instruction::Expr(parse_expr(inst))
|
||||
} else if inst.as_rule() == Rule::assignment {
|
||||
let mut p = inst.into_inner();
|
||||
let expr = parse_expr(p.next().unwrap());
|
||||
let registers: Vec<Register> = p.map(|r| Register::from_name(r.as_str())).collect();
|
||||
Instruction::Assignment(expr, registers)
|
||||
} else {
|
||||
println!("parsing inst {:?}", inst);
|
||||
unreachable!()
|
||||
}
|
||||
// println!("typ1 {:?}", inst)
|
||||
}
|
||||
// instruction_type2 is a list of instruction_right and will be resolved using parse_instruction_list
|
||||
Rule::instruction_right => {
|
||||
let mut inst = instruction.into_inner();
|
||||
let name = inst.next().unwrap().as_str();
|
||||
let mut params: Vec<InstructionOpcodeParam> = Vec::new();
|
||||
while let Some(param) = inst.next() {
|
||||
let mut p: Vec<InstructionOpcodeParam> = param.into_inner().map(parse_param).collect();
|
||||
params.append(&mut p);
|
||||
}
|
||||
Instruction::Opcode(InstructionOpcode {
|
||||
name: name.into(),
|
||||
params,
|
||||
})
|
||||
}
|
||||
Rule::instruction_type3 => {
|
||||
let mut insts = instruction.into_inner();
|
||||
let lhs = parse_instruction(insts.next().unwrap());
|
||||
let rhs = parse_instruction_list(insts.next().unwrap());
|
||||
Instruction::Compound(Box::new(lhs), rhs)
|
||||
}
|
||||
_ => {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// parse a list of instruction
|
||||
pub fn parse_instruction_list(instruction_list: Pair<Rule>) -> Vec<Instruction> {
|
||||
let mut parsed_instructions = Vec::new();
|
||||
for instruction in instruction_list.into_inner() {
|
||||
if instruction.as_rule() == Rule::instruction_type2 {
|
||||
// could be many or 1
|
||||
for inst in instruction.into_inner() {
|
||||
parsed_instructions.push(parse_instruction(inst));
|
||||
}
|
||||
} else {
|
||||
parsed_instructions.push(parse_instruction(instruction));
|
||||
}
|
||||
}
|
||||
return parsed_instructions;
|
||||
}
|
43
test.zkasm
Normal file
43
test.zkasm
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
CONST %aa = 2**32**8 ; atomic ** atomic
|
||||
CONST %aa = 2**32 ; atomic ** atomic
|
||||
CONST %bb = 2**32-1 ; atomic ** atomic ~ rest
|
||||
CONST %bb = (1+1)**32-1 ; expr ** atomic ~ rest
|
||||
CONST %bb = 2**(31+1)-1 ; atomic ** expr ~ rest
|
||||
CONST %bb = (1+1)**(31+1)-1 ; expr ** expr ~ rest
|
||||
CONST %bb = (1+1)**(-32)-1 ; expr ** expr ~ rest
|
||||
CONST %cc = 2**32-1-1 % 10
|
||||
CONST %dd = 2**(32-1) ; good
|
||||
CONST %ee = (2**32)-1 ; good
|
||||
|
||||
|
||||
CONSTL %P2_C0_EGX = %ECGX & 0xFFFF
|
||||
|
||||
a:
|
||||
-1 => B
|
||||
|
||||
CONST %MAX_CNT_PADDING_PG_LIMIT = (%TOTAL_STEPS_LIMIT / 56)
|
||||
*/
|
||||
|
||||
|
||||
; CONSTL %FPEC = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2Fn
|
||||
; CONSTL %FPEC_MINUS_ONE = %FPEC - 1
|
||||
; CONSTL %FNEC_DIV_TWO = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0n
|
||||
; CONSTL %FPEC_C2_256 = 0x1000003D1n
|
||||
; CONSTL %FPEC_NON_SQRT = (1n << 256n) - 1n
|
||||
;
|
||||
; CONSTL %FNEC = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141n
|
||||
; CONSTL %FNEC_MINUS_ONE = %FNEC - 1
|
||||
;
|
||||
; CONSTL %ECGX = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798n
|
||||
; CONSTL %ECGY = 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8n
|
||||
; CONSTL %P2_160 = 2n ** 160n
|
||||
; CONSTL %P2_96 = 2n ** 96n
|
||||
|
||||
/*
|
||||
Run:
|
||||
0 => HASH_LEFT, HASH_RIGHT, OLD_ROOT, NEW_ROOT, VALUE_LOW, VALUE_HIGH, SIBLING_VALUE_HASH, RKEY, SIBLING_RKEY, RKEY_BIT, LEVEL
|
||||
*/
|
||||
|
||||
a:
|
||||
A :MSTORE(SP--)
|
Loading…
Reference in New Issue
Block a user