#![allow(unused)]
use crate::envi::constants::{BR_DEREF, BR_FALL, IF_CALL, IF_RET};
use crate::envi::emulator::Emulator;
use crate::envi::memcanvas::MemoryCanvas;
use crate::envi::Result;
use crate::error::Error::FuncNotImplemented;
use log::warn;
use std::rc::Rc;
pub trait Operand {
fn is_deref(&self) -> bool {
false
}
fn is_immed(&self) -> bool {
false
}
fn is_reg(&self) -> bool {
false
}
fn is_discrete(&self) -> bool {
false
}
}
impl dyn Operand {
pub fn get_oper_value(
&self,
_op: OpCode,
_emulator: Option<&dyn Emulator>,
) -> Result<Option<i32>> {
Err(FuncNotImplemented("get_oper_value".to_string()))
}
pub fn set_oper_value(
&mut self,
_op: OpCode,
_emulator: Option<&dyn Emulator>,
_val: i32,
) -> Result<()> {
warn!("set_oper_value not implemented");
Err(FuncNotImplemented("set_oper_value".to_string()))
}
pub fn get_oper_addr(
&self,
_op: OpCode,
_emulator: Option<&dyn Emulator>,
) -> Result<Option<i32>> {
warn!("get_oper_addr not implemented");
Err(FuncNotImplemented("get_oper_addr".to_string()))
}
fn repr(&self, _op: &OpCode) -> String {
"Unknown".to_string()
}
fn render(&self, mcanv: &Rc<dyn MemoryCanvas>, op: OpCode, _idx: i32) {
mcanv.add_text(self.repr(&op), None);
}
}
pub struct DerefOper;
impl Operand for DerefOper {
fn is_deref(&self) -> bool {
true
}
}
pub struct ImmedOper;
impl Operand for ImmedOper {
fn is_immed(&self) -> bool {
true
}
fn is_discrete(&self) -> bool {
true
}
}
pub struct RegisterOper;
impl Operand for RegisterOper {
fn is_reg(&self) -> bool {
true
}
}
#[derive(Clone)]
pub struct OpCode {
pub opcode: i32,
pub mnem: String,
pub prefixes: i32,
pub prefix_names: Vec<(i32, String)>,
pub size: i32,
pub opers: Vec<Rc<dyn Operand>>,
pub repr: Option<String>,
pub iflags: i32,
pub va: i32,
}
impl OpCode {
pub fn new(
va: i32,
opcode: i32,
mnem: &str,
prefixes: i32,
size: i32,
operands: Vec<Rc<dyn Operand>>,
iflags: Option<i32>,
) -> Self {
OpCode {
opcode,
mnem: mnem.to_string(),
prefixes,
prefix_names: vec![],
size,
opers: operands,
repr: None,
iflags: iflags.unwrap_or(0),
va,
}
}
pub fn is_call(&self) -> bool {
self.iflags & IF_CALL == 1
}
pub fn is_return(&self) -> bool {
self.iflags & IF_RET == 1
}
pub fn get_targets(&self, emulator: Option<&dyn Emulator>) -> Vec<(Option<i32>, i32)> {
let mut remote_branches = vec![];
for (b_va, mut b_flags) in self.get_branches(emulator.as_ref().cloned()) {
if b_flags & BR_FALL == 1 {
continue;
}
let mut my_bva = Some(b_va);
if b_va == 1 && b_flags & BR_DEREF == 1 {
if let Some(emu) = emulator {
my_bva = Some(emu.read_memory_format(b_va, "<P")[0]);
b_flags &= !BR_DEREF;
} else {
my_bva = None;
}
}
remote_branches.push((my_bva, b_flags));
}
remote_branches
}
pub fn gen_ref_opers(
&self,
_emulator: Option<&dyn Emulator>,
) -> impl Iterator<Item = (i32, &Rc<dyn Operand>)> {
self.opers
.iter()
.enumerate()
.map(|(idx, oper)| (idx as i32, oper))
}
pub fn get_branches(&self, _emulator: Option<&dyn Emulator>) -> Vec<(i32, i32)> {
vec![]
}
pub fn get_operands(&self) -> &Vec<Rc<dyn Operand>> {
&self.opers
}
pub fn get_oper_value(&self, idx: i32, emu: Option<&dyn Emulator>) -> Result<Option<i32>> {
self.opers[idx as usize].get_oper_value(self.clone(), emu)
}
pub fn get_prefix_name(&self) -> String {
let mut ret = vec![];
for (byte, name) in self.prefix_names.iter() {
if self.prefixes & byte == 1 {
ret.push(name.clone());
}
}
ret.join(" ")
}
pub fn repr(&self) -> String {
let pfx = self.get_prefix_name();
format!(
"{}: {} {} ",
pfx,
self.mnem,
self.opers
.iter()
.map(|x| x.repr(self))
.collect::<Vec<String>>()
.join(", ")
)
}
pub fn render(&self, mcanv: &Rc<dyn MemoryCanvas>) {
mcanv.add_text(self.repr(), None);
}
pub fn len(&self) -> usize {
self.size as usize
}
}