Add assembler and execution logic
Most everything works, but there's one small bug with the execution involving jumps - still have to figure that one out. Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
@@ -1,4 +1,7 @@
|
||||
use crate::vm::reg::Reg;
|
||||
use crate::vm::{
|
||||
inst,
|
||||
reg::Reg,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum SectionDef {
|
||||
@@ -8,7 +11,7 @@ pub enum SectionDef {
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct MetaSection {
|
||||
pub values: Vec<MetaLine>,
|
||||
pub lines: Vec<MetaLine>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@@ -20,10 +23,27 @@ pub struct MetaLine {
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct DataSection {
|
||||
pub name: String,
|
||||
pub org: Option<SectionOrg>,
|
||||
pub org: SectionOrg,
|
||||
pub lines: Vec<DataLine>,
|
||||
}
|
||||
|
||||
impl DataSection {
|
||||
pub fn exports(&self) -> impl Iterator<Item=&str> {
|
||||
self.lines.iter()
|
||||
.filter_map(|line| if let DataLine::Export(s) = line {
|
||||
Some(s.as_str())
|
||||
} else {
|
||||
None
|
||||
})
|
||||
}
|
||||
|
||||
pub fn len(&self) -> usize {
|
||||
self.lines.iter()
|
||||
.map(DataLine::len)
|
||||
.sum()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum SectionOrg {
|
||||
Start(u64),
|
||||
@@ -38,6 +58,16 @@ pub enum DataLine {
|
||||
Label(String),
|
||||
}
|
||||
|
||||
impl DataLine {
|
||||
pub fn len(&self) -> usize {
|
||||
match self {
|
||||
DataLine::ValueDef(v) => v.len(),
|
||||
DataLine::Inst(i) => i.len(),
|
||||
DataLine::Export(_) | DataLine::Label(_) => 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum ValueDef {
|
||||
Int(u64),
|
||||
@@ -45,6 +75,16 @@ pub enum ValueDef {
|
||||
ZString(String),
|
||||
}
|
||||
|
||||
impl ValueDef {
|
||||
pub fn len(&self) -> usize {
|
||||
match self {
|
||||
ValueDef::Int(_) => 8,
|
||||
ValueDef::String(s) => 8 + s.as_bytes().len(),
|
||||
ValueDef::ZString(s) => s.as_bytes().len() + 1,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Value {
|
||||
Int(u64),
|
||||
@@ -52,7 +92,34 @@ pub enum Value {
|
||||
Name(String),
|
||||
Here,
|
||||
//Array(Vec<Value>),
|
||||
//Deref(Value, Size
|
||||
//Deref(Value, IntSize),
|
||||
}
|
||||
|
||||
impl Value {
|
||||
pub fn len(&self) -> usize {
|
||||
match self {
|
||||
// TODO : immediate int sizes
|
||||
Value::Int(_) => 8,
|
||||
Value::Reg(_) => 1,
|
||||
Value::Name(_) => 8,
|
||||
Value::Here => 8,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn dest_encoding(&self) -> Option<u8> {
|
||||
match self {
|
||||
Value::Int(_) | Value::Name(_) | Value::Here => None,
|
||||
Value::Reg(_) => Some(inst::DEST_REG),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn source_encoding(&self) -> u8 {
|
||||
match self {
|
||||
Value::Int(_) => inst::SOURCE_IMM64,
|
||||
Value::Reg(_) => inst::SOURCE_REG,
|
||||
Value::Name(_) | Value::Here => inst::SOURCE_IMM64,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@@ -80,3 +147,32 @@ pub enum Inst {
|
||||
Nop,
|
||||
Dump,
|
||||
}
|
||||
|
||||
impl Inst {
|
||||
pub fn len(&self) -> usize {
|
||||
match self {
|
||||
Inst::Add(v1, v2)
|
||||
| Inst::Sub(v1, v2)
|
||||
| Inst::Mul(v1, v2)
|
||||
| Inst::Div(v1, v2)
|
||||
| Inst::Mod(v1, v2)
|
||||
| Inst::And(v1, v2)
|
||||
| Inst::Or(v1, v2)
|
||||
| Inst::Xor(v1, v2)
|
||||
| Inst::Shl(v1, v2)
|
||||
| Inst::Shr(v1, v2)
|
||||
| Inst::INeg(v1, v2)
|
||||
| Inst::Inv(v1, v2)
|
||||
| Inst::Not(v1, v2)
|
||||
| Inst::CmpEq(v1, v2)
|
||||
| Inst::CmpLt(v1, v2)
|
||||
| Inst::Mov(v1, v2) => { 3 + v1.len() + v2.len() }
|
||||
Inst::Jmp(v)
|
||||
| Inst::Jz(v)
|
||||
| Inst::Jnz(v) => { 3 + v.len() }
|
||||
Inst::Halt
|
||||
| Inst::Nop
|
||||
| Inst::Dump => { 2 }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,8 +7,8 @@ SectionDefs -> Vec<SectionDef>:
|
||||
;
|
||||
|
||||
SectionDef -> SectionDef:
|
||||
'DIR_META' MetaBlock { SectionDef::Meta(MetaSection { values: $2 }) }
|
||||
| 'DIR_SECTION' Name MaybeSectionOrg DataBlock {
|
||||
'DIR_META' MetaBlock { SectionDef::Meta(MetaSection { lines: $2 }) }
|
||||
| 'DIR_SECTION' Name SectionOrg DataBlock {
|
||||
SectionDef::Data(DataSection {
|
||||
name: $2,
|
||||
org: $3,
|
||||
@@ -27,11 +27,6 @@ MetaLines -> Vec<MetaLine>:
|
||||
|
||||
MetaLine -> MetaLine: Name 'COLON' Value { MetaLine { name: $1, value: $3 } };
|
||||
|
||||
MaybeSectionOrg -> Option<SectionOrg>:
|
||||
SectionOrg { Some($1) }
|
||||
| { None }
|
||||
;
|
||||
|
||||
SectionOrg -> SectionOrg:
|
||||
Int { SectionOrg::Start($1) }
|
||||
| Int 'DOTDOT' Int { SectionOrg::StartEnd($1, $3) }
|
||||
|
||||
Reference in New Issue
Block a user