Compare commits

...

2 commits

Author SHA1 Message Date
4fb80fe158
add disassembly & display functions 2024-05-12 04:21:17 +02:00
7efee58c4d
linker: add link_relative() 2024-05-12 04:20:45 +02:00
3 changed files with 76 additions and 1 deletions

View file

@ -5,7 +5,7 @@ use {
}
};
#[derive(Clone)]
#[derive(Clone, Debug)]
pub enum AssemblyWord {
Symbol( LinkAddr ),
Lit( VM_Word )
@ -25,6 +25,38 @@ impl AssemblyWord {
}
}
pub fn disassemble(bytecode: &Vec< AssemblyWord >) -> Vec< String > {
let mut words = bytecode.iter();
let mut result = Vec::new();
let mut remaining_params = 0;
while let Some(w) = words.next() {
match w {
AssemblyWord::Symbol( addr ) => {
result.push( format!("{}", addr) );
remaining_params -= 1;
}
AssemblyWord::Lit(w) => {
if remaining_params == 0 {
if *w < 18 {
let inst : VM_Instruction = unsafe { std::mem::transmute(*w) };
result.push(format!("{:?}", inst));
remaining_params = inst.param_length();
} else {
result.push(format!("invalid opcode {}", w));
}
} else {
remaining_params -= 1;
result.push(format!("{}", w));
}
}
}
}
result
}
pub struct Assembler {
words: Vec< AssemblyWord >,
}

View file

@ -12,6 +12,21 @@ pub enum LinkAddr {
}
}
impl std::fmt::Display for LinkAddr {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
match self {
LinkAddr::Absolute(addr) =>
write!(f, "{:x}", addr),
LinkAddr::Relative{ symbol, offset } =>
if *offset == 0 {
write!(f, "{}", symbol)
} else {
write!(f, "{}+{:x}", symbol, offset)
}
}
}
}
pub struct Section {
addr: VM_Word,
data: Vec< AssemblyWord >
@ -47,6 +62,20 @@ impl Linker {
Ok(bytecode)
}
pub fn link_relative(self, symbol: &String) -> Result<Vec<AssemblyWord>, LinkError> {
Ok(self.link_partial()?
.into_iter()
.map(|w| match w {
AssemblyWord::Symbol(LinkAddr::Absolute(addr)) =>
AssemblyWord::Symbol(LinkAddr::Relative {
symbol: symbol.clone(),
offset: addr
}),
w => w
})
.collect())
}
pub fn link_total(self) -> Result<Vec<VM_Word>, LinkError> {
self.link_partial()?
.into_iter()

View file

@ -12,6 +12,20 @@ pub enum VM_Instruction {
BitwiseNot,
}
impl VM_Instruction {
pub fn param_length(&self) -> usize {
match self {
VM_Instruction::Jmp |
VM_Instruction::Call |
VM_Instruction::Branch |
VM_Instruction::Lit => {
1
},
_ => 0
}
}
}
pub struct VM {
pub data_stack: Vec< VM_Word >,
pub call_stack: Vec< VM_Word >,