aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiquel Sabaté Solà <mssola@mssola.com>2026-07-07 23:01:50 +0200
committerMiquel Sabaté Solà <mssola@mssola.com>2026-07-07 23:01:50 +0200
commitca7ff2c299dbd15b89adae73caa356584977dd46 (patch)
tree49453a74a93eec303d9bdad29fbc7cab238e83fe
parent85a68dbdcd0200a711bacda9c7170129350813c8 (diff)
downloadtools.nes-ca7ff2c299dbd15b89adae73caa356584977dd46.tar.gz
tools.nes-ca7ff2c299dbd15b89adae73caa356584977dd46.zip
Do not optimize away unresolved non-jumps
In the following code: .macro MACRO ADDR adc ADDR .endmacro MACRO label label: nop The evaluation of the 'adc' instruction went into being re-sized to 1 despite indications of being an address (and hence hinting to a size of 2). This was done because of the optimization to shrink a single byte left arm from absolute to relative addressing. But on unresolved bundles this is bad, as everything may still be zeroed out, and the instruction itself doesn't hint on the end size. This shrinking would then mess with the segment's offset, and we would end up with an offset of 2 instead of 3 for the label 'label'. Note that this is in the same spirit as commit ed3d34b0afb1 ("Only shrink the addressing on resolved bundles"), but now applied to the get_from_left() function which apparently was spared for whatever reason. Signed-off-by: Miquel Sabaté Solà <mssola@mssola.com>
-rw-r--r--lib/xixanta/src/assembler.rs32
1 files changed, 31 insertions, 1 deletions
diff --git a/lib/xixanta/src/assembler.rs b/lib/xixanta/src/assembler.rs
index e8ecd06..6ad2294 100644
--- a/lib/xixanta/src/assembler.rs
+++ b/lib/xixanta/src/assembler.rs
@@ -3167,7 +3167,9 @@ impl<'a> Assembler<'a> {
val.size = 1;
Ok((AddressingMode::RelativeOrZeropage, val))
} else if val.size == 1
- || (val.bytes[1] == 0x00 && !matches!(base.value.value.as_str(), "jmp" | "jsr"))
+ || (val.resolved
+ && val.bytes[1] == 0x00
+ && !matches!(base.value.value.as_str(), "jmp" | "jsr"))
{
self.asan_check_arm(left_arm, &val)?;
val.size = 1;
@@ -4713,6 +4715,34 @@ JAL procedure
}
#[test]
+ fn label_as_macro_argument() {
+ let res = just_bundles(
+ r#"
+.macro MACRO ADDR
+ adc ADDR
+.endmacro
+
+MACRO label
+
+label:
+ nop
+ "#,
+ );
+
+ assert_eq!(res.len(), 2);
+
+ // adc label
+ assert_eq!(res[0].size, 3);
+ assert_eq!(res[0].bytes[0], 0x6D);
+ assert_eq!(res[0].bytes[1], 0x03);
+ assert_eq!(res[0].bytes[2], 0x80);
+
+ // nop
+ assert_eq!(res[1].size, 1);
+ assert_eq!(res[1].bytes[0], 0xEA);
+ }
+
+ #[test]
fn jump_to_next() {
let res = just_assemble(
r#"