diff options
| author | Miquel Sabaté Solà <mssola@mssola.com> | 2026-02-11 17:15:31 +0100 |
|---|---|---|
| committer | Miquel Sabaté Solà <mssola@mssola.com> | 2026-02-11 17:15:31 +0100 |
| commit | d10d4fd6e6ed2c6939b5504a7de576fa5d4e5317 (patch) | |
| tree | 8f9fd99e719e4df1fd9bf949975c020b3a21145a | |
| parent | 394ccffc5a3f7a6fb791eaa87767cf1bba34199c (diff) | |
| download | tools.nes-d10d4fd6e6ed2c6939b5504a7de576fa5d4e5317.tar.gz tools.nes-d10d4fd6e6ed2c6939b5504a7de576fa5d4e5317.zip | |
Allow using a byte for indirect jumps
They should be expanded to a 16-bit address from the zero-page. The fact
that the assembler was complaining about it was simply erroneous.
Signed-off-by: Miquel Sabaté Solà <mssola@mssola.com>
| -rw-r--r-- | lib/xixanta/src/assembler.rs | 23 | ||||
| -rwxr-xr-x | scripts/test-e2e.sh | 7 | ||||
| -rw-r--r-- | tests/expected/indirect.nes | bin | 0 -> 28 bytes | |||
| -rw-r--r-- | tests/expected/indirect.txt | 0 | ||||
| -rw-r--r-- | tests/indirect.s | 18 |
5 files changed, 37 insertions, 11 deletions
diff --git a/lib/xixanta/src/assembler.rs b/lib/xixanta/src/assembler.rs index d5dc5fa..11a9409 100644 --- a/lib/xixanta/src/assembler.rs +++ b/lib/xixanta/src/assembler.rs @@ -2739,16 +2739,17 @@ impl<'a> Assembler<'a> { } None => { let evaluated_node = left.left.as_ref().unwrap(); - let val = self.evaluate_node(evaluated_node)?; - if val.size != 2 { - return Err(Error { - message: "expecting a full 16-bit address".to_string(), - line: node.value.line, - source: self.source_for(node), - global: false, - expanded_from: self.macro_context.clone(), - }); - } + let mut val = self.evaluate_node(evaluated_node)?; + + // If this is a valid pure indirect addressing, then we know + // for sure we are in a 'jmp' instruction. In this case, if + // a zero-page address was being used, expand it to an + // absolute address. We do this unconditionally just to be + // sure, just as like we set the high byte of the address to + // $00 just to sanitize things. + val.size = 3; + val.bytes[2] = 0x00; + self.asan_check_arm(evaluated_node, &val)?; Ok((AddressingMode::Indirect, val)) } @@ -3677,7 +3678,6 @@ cpx #(4 * var2)"#, false, "only the Y index is allowed on indirect Y addressing", ); - assert_error("jmp ($20)", 1, false, "expecting a full 16-bit address"); assert_error("adc $20, z", 1, false, "can only use X and Y as indices"); assert_error( "adc ($2000)", @@ -3829,6 +3829,7 @@ cpx #(4 * var2)"#, assert_instruction("jmp $2002", &[0x4C, 0x02, 0x20]); assert_instruction("jmp ($2002)", &[0x6C, 0x02, 0x20]); + assert_instruction("jmp ($20)", &[0x6C, 0x20, 0x00]); } #[test] diff --git a/scripts/test-e2e.sh b/scripts/test-e2e.sh index 06545b8..02d1ca3 100755 --- a/scripts/test-e2e.sh +++ b/scripts/test-e2e.sh @@ -95,6 +95,13 @@ exit_code=$((exit_code + $?)) diff tests/out/avoid_bad_macro.nes tests/expected/avoid_bad_macro.nes exit_code=$((exit_code + $?)) +echo "test: custom => indirect.nes" +./target/debug/nasm -c empty --asan tests/indirect.s -o tests/out/indirect.nes 2>tests/out/indirect.txt +diff tests/out/indirect.txt tests/expected/indirect.txt +exit_code=$((exit_code + $?)) +diff tests/out/indirect.nes tests/expected/indirect.nes +exit_code=$((exit_code + $?)) + ## # code.nes diff --git a/tests/expected/indirect.nes b/tests/expected/indirect.nes Binary files differnew file mode 100644 index 0000000..68136c9 --- /dev/null +++ b/tests/expected/indirect.nes diff --git a/tests/expected/indirect.txt b/tests/expected/indirect.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/tests/expected/indirect.txt diff --git a/tests/indirect.s b/tests/indirect.s new file mode 100644 index 0000000..9629d5f --- /dev/null +++ b/tests/indirect.s @@ -0,0 +1,18 @@ +.segment "HEADER" + .byte 'N', 'E', 'S', $1A + .byte $02, $01 + .byte $00 + .byte $00 + +.segment "CODE" + +zp_something = $20 ; asan:reserve $02 + +lda #<lala +sta zp_something +lda #>lala +sta zp_something + 1 +jmp (zp_something) + +lala: + rts |
