aboutsummaryrefslogtreecommitdiff
path: root/lib/xixanta/src/assembler.rs
diff options
context:
space:
mode:
authorMiquel Sabaté Solà <mikisabate@gmail.com>2025-01-16 16:33:10 +0100
committerMiquel Sabaté Solà <mikisabate@gmail.com>2025-01-16 16:33:10 +0100
commit2455e2bbcfb4372b13a351471a49a585ceb1597c (patch)
treeb751542e846f4eb075163c5580d8b4d85295a630 /lib/xixanta/src/assembler.rs
parenta3a630dfee207c111213d2cad85ceb983df7625a (diff)
downloadtools.nes-2455e2bbcfb4372b13a351471a49a585ceb1597c.tar.gz
tools.nes-2455e2bbcfb4372b13a351471a49a585ceb1597c.zip
Implement .ifdef/.ifndef statements
They are just synonyms for ".if .defined" and ".if !.defined" respectively. Signed-off-by: Miquel Sabaté Solà <mikisabate@gmail.com>
Diffstat (limited to 'lib/xixanta/src/assembler.rs')
-rw-r--r--lib/xixanta/src/assembler.rs49
1 files changed, 49 insertions, 0 deletions
diff --git a/lib/xixanta/src/assembler.rs b/lib/xixanta/src/assembler.rs
index d0a0e6e..8699529 100644
--- a/lib/xixanta/src/assembler.rs
+++ b/lib/xixanta/src/assembler.rs
@@ -1312,6 +1312,9 @@ impl<'a> Assembler<'a> {
Ok(self.incbin(node.args.as_ref().unwrap().first().unwrap())?)
}
NodeType::Control(ControlType::If) => self.evaluate_if_block(node),
+ NodeType::Control(ControlType::IfDef) | NodeType::Control(ControlType::IfNDef) => {
+ self.evaluate_ifdef_block(node)
+ }
NodeType::Control(ControlType::EndIf) => Ok(()),
NodeType::Control(ControlType::IncludeSource) => Ok(()),
_ => Err(Error {
@@ -1521,6 +1524,24 @@ impl<'a> Assembler<'a> {
None => true,
};
+ self.evaluate_if_cond(node, cond)
+ }
+
+ // Evaluate the given `node` by assuming that it's an .ifdef/.ifndef block.
+ fn evaluate_ifdef_block(&mut self, node: &'a PNode) -> Result<(), Vec<Error>> {
+ let defined = self.evaluate_defined(node)?.value();
+ let cond = match &node.node_type {
+ NodeType::Control(ControlType::IfDef) => defined == 1,
+ NodeType::Control(ControlType::IfNDef) => defined == 0,
+ _ => panic!("unexpected .ifdef block"),
+ };
+
+ self.evaluate_if_cond(node, cond)
+ }
+
+ // Evaluate the `node`'s body if `cond` is true, otherwise try to evaluate
+ // the "else" branch for this .if-looking statement.
+ fn evaluate_if_cond(&mut self, node: &'a PNode, cond: bool) -> Result<(), Vec<Error>> {
// If condition was false, try to go into the .elsif/.else statement. If
// that doesn't exist, then we are done.
if !cond {
@@ -3425,6 +3446,34 @@ jsr Movement::update
}
}
+ #[test]
+ fn ifdef_block() {
+ let res = just_bundles(
+ r#"Var = 0
+.ifdef Var
+ lda #1
+.endif
+
+.ifndef Var
+ lda #1
+.elsif Var == 0
+ lda #2
+.elsif Var == 2
+ lda #3
+.endif
+"#,
+ );
+
+ assert_eq!(res.len(), 2);
+
+ let instrs: Vec<[u8; 2]> = vec![[0xA9, 0x01], [0xA9, 0x02]];
+ for i in 0..instrs.len() {
+ assert_eq!(res[i].size, 2);
+ assert_eq!(res[i].bytes[0], instrs[i][0]);
+ assert_eq!(res[i].bytes[1], instrs[i][1]);
+ }
+ }
+
// Macros
#[test]