Skip to content

Commit

Permalink
Only shrink the addressing on resolved bundles
Browse files Browse the repository at this point in the history
Commit ea5f0f8 ("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à <[email protected]>
  • Loading branch information
mssola committed Dec 20, 2024
1 parent ea5f0f8 commit ed3d34b
Showing 1 changed file with 35 additions and 3 deletions.
38 changes: 35 additions & 3 deletions lib/xixanta/src/assembler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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 {
Expand Down Expand Up @@ -2527,6 +2531,34 @@ nop
assert_eq!(res[3].bytes[2], 0x80);
}

#[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]);
Expand Down

0 comments on commit ed3d34b

Please sign in to comment.