From 7f0c50304ace84794521d66d68f21827b7b58cad Mon Sep 17 00:00:00 2001 From: Scott Duensing Date: Fri, 26 Jun 2026 21:00:32 -0500 Subject: [PATCH] Inadvertent bank-drop fixed. --- .../lib/Target/W65816/W65816AsmPrinter.cpp | 43 ++++++++++++++----- 1 file changed, 32 insertions(+), 11 deletions(-) diff --git a/src/llvm/lib/Target/W65816/W65816AsmPrinter.cpp b/src/llvm/lib/Target/W65816/W65816AsmPrinter.cpp index fc11f16..0540452 100644 --- a/src/llvm/lib/Target/W65816/W65816AsmPrinter.cpp +++ b/src/llvm/lib/Target/W65816/W65816AsmPrinter.cpp @@ -815,9 +815,17 @@ void W65816AsmPrinter::emitInstruction(const MachineInstr *MI) { IsLong = IsLong || isFarGlobalOperand(AddrMO); MCOperand Addr = lowerOperand(AddrMO, MCInstLowering); if (IsLong && Addr.isImm()) { - // 16-bit pointer sign-extended into i32 imm — mask back to 16 bits - // so the encoded bank byte is 0. See STA8long for the rationale. - Addr = MCOperand::createImm(Addr.getImm() & 0xFFFFu); + // Sign-extended 16-bit pointer -> low 16 (bank 0); genuine 24-bit + // constant address -> keep low 24 (bank preserved). See STA8long. + int64_t Imm = Addr.getImm(); + int16_t Lo16 = static_cast(Imm); + bool IsSext16 = + (Imm == static_cast(Lo16)) || + (static_cast(Imm) == + static_cast(static_cast(static_cast(Lo16)))); + Addr = MCOperand::createImm( + IsSext16 ? (static_cast(Imm) & 0xFFFFu) + : (static_cast(Imm) & 0xFFFFFFu)); } emitSepM(); EmitToStreamer(*OutStreamer, @@ -878,15 +886,28 @@ void W65816AsmPrinter::emitInstruction(const MachineInstr *MI) { emitSepM(); } MCOperand Addr = lowerOperand(MI->getOperand(1), MCInstLowering); - // STA_Long takes a 24-bit absolute address. When the input is a - // const-int cast through a 16-bit pointer, TableGen sign-extends - // the 16-bit value into the i32 imm operand: 0xC035 (i16) becomes - // 0xFFFFC035 (i64). Mask to 16 bits to recover the original - // pointer; the resulting encoding has bank=0 explicit. Users who - // need a banked address should construct a far pointer rather than - // casting an int. + // STA_Long takes a 24-bit absolute address. Two cases reach here as + // an immediate: + // (a) a const-int cast through a 16-bit pointer, which TableGen + // SIGN-EXTENDS into the wider imm (0xC035 -> ...FFFFC035); the + // intended bank is 0, so recover the low 16 bits. + // (b) a genuine >16-bit constant address such as 0xE12000 (a fixed + // hardware register in bank $E1); this MUST keep its bank byte. + // Distinguish by the sign-extension round-trip: if the value equals + // the sign-extension of its low 16 bits it is case (a) -> low 16; + // otherwise it is case (b) -> keep the low 24 (bank included), dropping + // any above-bit-23 garbage. The check tolerates both i32-in-i64 and + // full-i64 sign-extended representations of the immediate. if (IsLong && Addr.isImm()) { - Addr = MCOperand::createImm(Addr.getImm() & 0xFFFFu); + int64_t Imm = Addr.getImm(); + int16_t Lo16 = static_cast(Imm); + bool IsSext16 = + (Imm == static_cast(Lo16)) || + (static_cast(Imm) == + static_cast(static_cast(static_cast(Lo16)))); + Addr = MCOperand::createImm( + IsSext16 ? (static_cast(Imm) & 0xFFFFu) + : (static_cast(Imm) & 0xFFFFFFu)); } EmitToStreamer(*OutStreamer, MCInstBuilder(IsLong ? W65816::STA_Long : W65816::STA_Abs)