#[must_use]
pub fn mnemonic(opcode: u8) -> Option<&'static str> {
MNEMONICS[usize::from(opcode)]
}
#[must_use]
pub fn immediate_size(opcode: u8) -> usize {
if (0x60..=0x7f).contains(&opcode) {
usize::from(opcode - 0x5f)
} else {
0
}
}
const MNEMONICS: [Option<&str>; 256] = [
Some("STOP"), Some("ADD"), Some("MUL"), Some("SUB"), Some("DIV"), Some("SDIV"), Some("MOD"), Some("SMOD"), Some("ADDMOD"), Some("MULMOD"), Some("EXP"), Some("SIGNEXTEND"), None, None, None, None, Some("LT"), Some("GT"), Some("SLT"), Some("SGT"), Some("EQ"), Some("ISZERO"), Some("AND"), Some("OR"), Some("XOR"), Some("NOT"), Some("BYTE"), Some("SHL"), Some("SHR"), Some("SAR"), Some("CLZ"), None, Some("KECCAK256"), None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, Some("ADDRESS"), Some("BALANCE"), Some("ORIGIN"), Some("CALLER"), Some("CALLVALUE"), Some("CALLDATALOAD"), Some("CALLDATASIZE"), Some("CALLDATACOPY"), Some("CODESIZE"), Some("CODECOPY"), Some("GASPRICE"), Some("EXTCODESIZE"), Some("EXTCODECOPY"), Some("RETURNDATASIZE"), Some("RETURNDATACOPY"), Some("EXTCODEHASH"), Some("BLOCKHASH"), Some("COINBASE"), Some("TIMESTAMP"), Some("NUMBER"), Some("DIFFICULTY"), Some("GASLIMIT"), Some("CHAINID"), Some("SELFBALANCE"), Some("BASEFEE"), Some("BLOBHASH"), Some("BLOBBASEFEE"), Some("SLOTNUM"), None, None, None, None, Some("POP"), Some("MLOAD"), Some("MSTORE"), Some("MSTORE8"), Some("SLOAD"), Some("SSTORE"), Some("JUMP"), Some("JUMPI"), Some("PC"), Some("MSIZE"), Some("GAS"), Some("JUMPDEST"), Some("TLOAD"), Some("TSTORE"), Some("MCOPY"), Some("PUSH0"), Some("PUSH1"), Some("PUSH2"), Some("PUSH3"), Some("PUSH4"), Some("PUSH5"), Some("PUSH6"), Some("PUSH7"), Some("PUSH8"), Some("PUSH9"), Some("PUSH10"), Some("PUSH11"), Some("PUSH12"), Some("PUSH13"), Some("PUSH14"), Some("PUSH15"), Some("PUSH16"), Some("PUSH17"), Some("PUSH18"), Some("PUSH19"), Some("PUSH20"), Some("PUSH21"), Some("PUSH22"), Some("PUSH23"), Some("PUSH24"), Some("PUSH25"), Some("PUSH26"), Some("PUSH27"), Some("PUSH28"), Some("PUSH29"), Some("PUSH30"), Some("PUSH31"), Some("PUSH32"), Some("DUP1"), Some("DUP2"), Some("DUP3"), Some("DUP4"), Some("DUP5"), Some("DUP6"), Some("DUP7"), Some("DUP8"), Some("DUP9"), Some("DUP10"), Some("DUP11"), Some("DUP12"), Some("DUP13"), Some("DUP14"), Some("DUP15"), Some("DUP16"), Some("SWAP1"), Some("SWAP2"), Some("SWAP3"), Some("SWAP4"), Some("SWAP5"), Some("SWAP6"), Some("SWAP7"), Some("SWAP8"), Some("SWAP9"), Some("SWAP10"), Some("SWAP11"), Some("SWAP12"), Some("SWAP13"), Some("SWAP14"), Some("SWAP15"), Some("SWAP16"), Some("LOG0"), Some("LOG1"), Some("LOG2"), Some("LOG3"), Some("LOG4"), None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, Some("DUPN"), Some("SWAPN"), Some("EXCHANGE"), None, None, None, None, None, None, None, Some("CREATE"), Some("CALL"), Some("CALLCODE"), Some("RETURN"), Some("DELEGATECALL"), Some("CREATE2"), None, None, None, None, Some("STATICCALL"), None, None, Some("REVERT"), Some("INVALID"), Some("SELFDESTRUCT"), ];
#[cfg(test)]
mod tests {
use super::{immediate_size, mnemonic, MNEMONICS};
#[test]
fn names_the_evm_instruction_set() {
assert_eq!(mnemonic(0x00), Some("STOP"));
assert_eq!(mnemonic(0x1e), Some("CLZ"));
assert_eq!(mnemonic(0x20), Some("KECCAK256"));
assert_eq!(mnemonic(0x5b), Some("JUMPDEST"));
assert_eq!(mnemonic(0x5e), Some("MCOPY"));
assert_eq!(mnemonic(0x5f), Some("PUSH0"));
assert_eq!(mnemonic(0x60), Some("PUSH1"));
assert_eq!(mnemonic(0x7f), Some("PUSH32"));
assert_eq!(mnemonic(0x80), Some("DUP1"));
assert_eq!(mnemonic(0x8f), Some("DUP16"));
assert_eq!(mnemonic(0x90), Some("SWAP1"));
assert_eq!(mnemonic(0x9f), Some("SWAP16"));
assert_eq!(mnemonic(0xa4), Some("LOG4"));
assert_eq!(mnemonic(0xf5), Some("CREATE2"));
assert_eq!(mnemonic(0xfa), Some("STATICCALL"));
assert_eq!(mnemonic(0xff), Some("SELFDESTRUCT"));
assert_eq!(mnemonic(0x0c), None);
assert_eq!(mnemonic(0x21), None);
assert_eq!(mnemonic(0xef), None);
assert_eq!(mnemonic(0xfc), None);
assert_eq!(MNEMONICS.iter().filter(|name| name.is_some()).count(), 154);
}
#[test]
fn only_pushes_carry_immediates() {
assert_eq!(immediate_size(0x5f), 0);
assert_eq!(immediate_size(0x60), 1);
assert_eq!(immediate_size(0x7f), 32);
assert_eq!(immediate_size(0x80), 0);
assert_eq!(immediate_size(0xff), 0);
}
}