From ca7ff2c299dbd15b89adae73caa356584977dd46 Mon Sep 17 00:00:00 2001 From: Miquel Sabaté Solà Date: Tue, 7 Jul 2026 23:01:50 +0200 Subject: Do not optimize away unresolved non-jumps MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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à --- lib/xixanta/src/assembler.rs | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) (limited to 'lib/xixanta/src/assembler.rs') 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; @@ -4712,6 +4714,34 @@ JAL procedure assert_eq!(res[1].bytes[0], 0x60); } + #[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( -- cgit v1.2.3