Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
Signed-off-by: Miquel Sabaté Solà <[email protected]>
  • Loading branch information
mssola committed Oct 23, 2024
1 parent 37fdd3a commit 124dc01
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 16 deletions.
83 changes: 67 additions & 16 deletions lib/xixanta/src/assembler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,25 +61,23 @@ pub struct Assembler {
stage: Stage,
macros: HashMap<String, Macro>,
can_bundle: bool,
segments: Vec<Segment>,
current_segment: usize,
}

impl Assembler {
pub fn new(segments: Vec<Segment>) -> Self {
assert!(!segments.is_empty());

// TODO
let mut offsets = HashMap::new();
for segment in segments {
offsets.insert(segment.name, 0);
}

// TODO
Self {
context: Context::new(),
literal_mode: None,
stage: Stage::Init,
macros: HashMap::new(),
can_bundle: true,
segments,
current_segment: 0,
}
}

Expand All @@ -104,14 +102,18 @@ impl Assembler {
// used by the caller.
self.stage = Stage::Bundling;
self.bundle(&parser.nodes)

// TODO: some of these bundles are to be marked as "pending", which
// should contain the scope::Variable being referenced, so it's picked
// up again. Moreover, each scope also has a list of anonymous labels,
// which contain the address, but also the line where they were found.
}

pub fn eval_context(&mut self, nodes: &[PNode]) -> Result<(), Vec<Error>> {
let mut errors = Vec::new();
let mut current_macro = None;

for (idx, node) in nodes.iter().enumerate() {
// TODO: initilize labels on each scope.
match node.node_type {
NodeType::Assignment => {
// TODO: in fact, we cannot have assignments in many places.
Expand Down Expand Up @@ -192,10 +194,31 @@ impl Assembler {

for node in nodes {
match node.node_type {
NodeType::Label => {
// And now make up a fake bundle object which contains the
// value of the address that has been processed.
let segment = &self.segments[self.current_segment];
let value = (segment.start as usize + segment.offset).to_le_bytes();
let bundle = Bundle {
bytes: [value[0], value[1], value[2]],
size: 2,
address: 0,
cycles: 0,
affected_on_page: false,
};

if let Err(err) = self.context.set_variable(&node.value, &bundle) {
errors.push(Error::Context(err));
}
}
NodeType::Instruction => {
if self.can_bundle {
match self.evaluate_node(node) {
Ok(bundle) => bundles.push(bundle),
Ok(bundle) => {
if let Err(e) = self.push_bundle(&mut bundles, bundle) {
errors.push(Error::Eval(e));
}
}
Err(e) => errors.push(Error::Eval(e)),
}
}
Expand Down Expand Up @@ -277,9 +300,30 @@ impl Assembler {
.get(mcr.nodes.start..=mcr.nodes.end)
.unwrap_or_default()
{
bundles.push(self.evaluate_node(node)?);
let bundle = self.evaluate_node(node)?;
self.push_bundle(bundles, bundle)?;
}

Ok(())
}

// TODO: move
fn push_bundle(&mut self, bundles: &mut Vec<Bundle>, bundle: Bundle) -> Result<(), EvalError> {
let current = &mut self.segments[self.current_segment];
current.offset += bundle.size as usize;

if current.offset > current.size {
return Err(EvalError {
line: 0,
message: format!(
"exceeding segment size for '{}' ({} bytes)",
current.name, current.size
),
});
}

bundles.push(bundle);

Ok(())
}

Expand Down Expand Up @@ -589,7 +633,7 @@ impl Assembler {
let function = node.value.value.as_str();
match function {
".byte" | ".db" => self.push_evaluated_arguments(node, res, 1),
".addr" | ".dw" => self.push_evaluated_arguments(node, res, 2),
".addr" | ".word" | ".dw" => self.push_evaluated_arguments(node, res, 2),
_ => Err(EvalError {
line: node.value.line,
message: format!(
Expand Down Expand Up @@ -749,7 +793,7 @@ impl Assembler {
} else if node.right.is_some() {
self.get_from_indexed(node)
} else {
self.get_from_left(left.as_ref().unwrap())
self.get_from_left(node, left.as_ref().unwrap())
}
}

Expand Down Expand Up @@ -856,7 +900,11 @@ impl Assembler {
}
}

fn get_from_left(&mut self, left_arm: &PNode) -> Result<(AddressingMode, Bundle), EvalError> {
fn get_from_left(
&mut self,
base: &PNode,
left_arm: &PNode,
) -> Result<(AddressingMode, Bundle), EvalError> {
if left_arm.value.value.to_lowercase().trim() == "a" {
return Ok((AddressingMode::Implied, Bundle::default()));
}
Expand All @@ -872,10 +920,13 @@ impl Assembler {
}
Some(LiteralMode::Plain) => {
if val.size > 1 {
Err(EvalError {
message: "immediate is too big".to_string(),
line: left_arm.value.line,
})
match base.value.value.as_str() {
"jmp" | "jsr" => Ok((AddressingMode::Absolute, val)),
_ => Err(EvalError {
message: "immediate is too big".to_string(),
line: left_arm.value.line,
}),
}
} else {
Ok((AddressingMode::Immediate, val))
}
Expand Down
6 changes: 6 additions & 0 deletions lib/xixanta/src/mapping.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,31 +3,36 @@ lazy_static! {
name: String::from("CODE"),
start: 0x0000,
size: 0xFFFF,
offset: 0,
fill: None,
}];
pub static ref NROM: Vec<Segment> = vec![
Segment {
name: String::from("HEADER"),
start: 0x0000,
size: 0x0010,
offset: 0,
fill: Some(0x00),
},
Segment {
name: String::from("VECTORS"),
start: 0xFFFA,
size: 0x0006,
offset: 0,
fill: Some(0x00),
},
Segment {
name: String::from("CODE"),
start: 0x8000,
size: 0x7FFA,
offset: 0,
fill: Some(0x00),
},
Segment {
name: String::from("CHARS"),
start: 0x0000,
size: 0x2000,
offset: 0,
fill: Some(0x00),
}
];
Expand All @@ -38,6 +43,7 @@ pub struct Segment {
pub name: String,
pub start: u16,
pub size: usize,
pub offset: usize,
pub fill: Option<usize>,
}

Expand Down
1 change: 1 addition & 0 deletions lib/xixanta/src/opcodes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -727,6 +727,7 @@ lazy_static! {
functions.insert(String::from(".db"), Control { has_identifier: false, required_args: None, touches_context: false });
functions.insert(String::from(".word"), Control { has_identifier: false, required_args: None, touches_context: false });
functions.insert(String::from(".dw"), Control { has_identifier: false, required_args: None, touches_context: false });
functions.insert(String::from(".addr"), Control { has_identifier: false, required_args: None, touches_context: false });

functions
};
Expand Down

0 comments on commit 124dc01

Please sign in to comment.