use revm_primitives::Bytes;
use crate::{
gas,
primitives::{Spec, U256},
Host, InstructionResult, Interpreter, InterpreterResult,
};
pub fn jump<H: Host>(interpreter: &mut Interpreter, _host: &mut H) {
gas!(interpreter, gas::MID);
pop!(interpreter, dest);
let dest = as_usize_or_fail!(interpreter, dest, InstructionResult::InvalidJump);
if interpreter.contract.is_valid_jump(dest) {
interpreter.instruction_pointer =
unsafe { interpreter.contract.bytecode.as_ptr().add(dest) };
} else {
interpreter.instruction_result = InstructionResult::InvalidJump;
}
}
pub fn jumpi<H: Host>(interpreter: &mut Interpreter, _host: &mut H) {
gas!(interpreter, gas::HIGH);
pop!(interpreter, dest, value);
if value != U256::ZERO {
let dest = as_usize_or_fail!(interpreter, dest, InstructionResult::InvalidJump);
if interpreter.contract.is_valid_jump(dest) {
interpreter.instruction_pointer =
unsafe { interpreter.contract.bytecode.as_ptr().add(dest) };
} else {
interpreter.instruction_result = InstructionResult::InvalidJump
}
}
}
pub fn jumpdest<H: Host>(interpreter: &mut Interpreter, _host: &mut H) {
gas!(interpreter, gas::JUMPDEST);
}
pub fn pc<H: Host>(interpreter: &mut Interpreter, _host: &mut H) {
gas!(interpreter, gas::BASE);
push!(interpreter, U256::from(interpreter.program_counter() - 1));
}
#[inline(always)]
fn return_inner(interpreter: &mut Interpreter, instruction_result: InstructionResult) {
pop!(interpreter, offset, len);
let len = as_usize_or_fail!(interpreter, len);
let mut output = Bytes::default();
if len != 0 {
let offset = as_usize_or_fail!(interpreter, offset);
shared_memory_resize!(interpreter, offset, len);
output = interpreter.shared_memory.slice(offset, len).to_vec().into()
}
interpreter.instruction_result = instruction_result;
interpreter.next_action = crate::InterpreterAction::Return {
result: InterpreterResult {
output,
gas: interpreter.gas,
result: instruction_result,
},
};
}
pub fn ret<H: Host>(interpreter: &mut Interpreter, _host: &mut H) {
return_inner(interpreter, InstructionResult::Return);
}
pub fn revert<H: Host, SPEC: Spec>(interpreter: &mut Interpreter, _host: &mut H) {
check!(interpreter, BYZANTIUM);
return_inner(interpreter, InstructionResult::Revert);
}
pub fn stop<H: Host>(interpreter: &mut Interpreter, _host: &mut H) {
interpreter.instruction_result = InstructionResult::Stop;
}
pub fn invalid<H: Host>(interpreter: &mut Interpreter, _host: &mut H) {
interpreter.instruction_result = InstructionResult::InvalidFEOpcode;
}
pub fn unknown<H: Host>(interpreter: &mut Interpreter, _host: &mut H) {
interpreter.instruction_result = InstructionResult::OpcodeNotFound;
}