diff options
| author | Miquel Sabaté Solà <mikisabate@gmail.com> | 2024-12-20 15:41:46 +0100 |
|---|---|---|
| committer | Miquel Sabaté Solà <mikisabate@gmail.com> | 2024-12-20 15:41:46 +0100 |
| commit | ed3d34b0afb1edb405dfa6dcb00527b9a9a2e480 (patch) | |
| tree | 35fb1e0e3d22b2d6d35db778b45e5ade05337929 /lib/xixanta/src | |
| parent | ea5f0f81b8a76408d8311cabbc48228798cc20e8 (diff) | |
| download | tools.nes-ed3d34b0afb1edb405dfa6dcb00527b9a9a2e480.tar.gz tools.nes-ed3d34b0afb1edb405dfa6dcb00527b9a9a2e480.zip | |
Only shrink the addressing on resolved bundles
Commit ea5f0f81b8a7 ("Shrink some absolute instructions by one byte")
applied the optimization in all cases, but we cannot perform it on
bundles which are yet to be resolved. This is because in unresolved
bundles the value is only an offset, which usually will fit on a single
byte and hence the optimization would've been carried out. That being
said, whenever we resolve this it might just be the case the it wouldn't
have fit in that single byte, and hence we end up with an artificially
shrinked instruction for a 16-bit address.
Signed-off-by: Miquel Sabaté Solà <mikisabate@gmail.com>
Diffstat (limited to 'lib/xixanta/src')
| -rw-r--r-- | lib/xixanta/src/assembler.rs | 38 |
1 files changed, 35 insertions, 3 deletions
diff --git a/lib/xixanta/src/assembler.rs b/lib/xixanta/src/assembler.rs index 92f57cd..4fd8d92 100644 --- a/lib/xixanta/src/assembler.rs +++ b/lib/xixanta/src/assembler.rs @@ -1429,8 +1429,12 @@ impl Assembler { "x" => { // If the size == 2 but we can fit it on a single byte (i.e. // because the second byte is just 0x00), then just "compress" - // this instruction. - if val.size == 1 || val.bytes[1] == 0x00 { + // this instruction. Note that this is only valid if the value + // is fully well-known (i.e. it's not yet to be resolved). When + // the value is not yet resolved, it usually revolves around an + // address being referenced, which is never on the zeropage + // section, so it wouldn't fit on a single byte anyways. + if val.size == 1 || (val.resolved && val.bytes[1] == 0x00) { // Re-inforce the optimization when val.size == 2 by forcing // the size to 1. val.size = 1; @@ -1441,7 +1445,7 @@ impl Assembler { } "y" => { // Same optimization as with the "x" case. - if val.size == 1 || val.bytes[1] == 0x00 { + if val.size == 1 || (val.resolved && val.bytes[1] == 0x00) { val.size = 1; Ok((AddressingMode::ZeropageIndexedY, val)) } else { @@ -2528,6 +2532,34 @@ nop } #[test] + fn label_in_instruction_addressing() { + let mut asm = Assembler::new(EMPTY.to_vec()); + asm.mappings[0].segments[0].bundles = minimal_header(); + asm.mappings[0].offset = 6; + asm.current_mapping = 1; + let res = &asm + .assemble( + std::env::current_dir().unwrap().to_path_buf(), + r#" + ldx #0 +@load_palettes_loop: + lda palettes, x +palettes: + .byte $0F, $12, $22, $32 +"# + .as_bytes(), + ) + .unwrap()[0x10..]; + + assert_instruction("ldx #0", &res[0].bytes); + assert_instruction("lda $8005, x", &res[1].bytes); + assert_eq!(&res[2].bytes, &[0x0F, 0x00, 0x00]); + assert_eq!(&res[3].bytes, &[0x12, 0x00, 0x00]); + assert_eq!(&res[4].bytes, &[0x22, 0x00, 0x00]); + assert_eq!(&res[5].bytes, &[0x32, 0x00, 0x00]); + } + + #[test] fn full_to_zeropage_optimization() { assert_instruction("sta $0020", &[0x85, 0x20]); assert_instruction("sty $021, x", &[0x94, 0x21]); |
