Inadvertent bank-drop fixed.
This commit is contained in:
parent
0643479903
commit
7f0c50304a
1 changed files with 32 additions and 11 deletions
|
|
@ -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<int16_t>(Imm);
|
||||
bool IsSext16 =
|
||||
(Imm == static_cast<int64_t>(Lo16)) ||
|
||||
(static_cast<uint64_t>(Imm) ==
|
||||
static_cast<uint64_t>(static_cast<uint32_t>(static_cast<int32_t>(Lo16))));
|
||||
Addr = MCOperand::createImm(
|
||||
IsSext16 ? (static_cast<uint64_t>(Imm) & 0xFFFFu)
|
||||
: (static_cast<uint64_t>(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<int16_t>(Imm);
|
||||
bool IsSext16 =
|
||||
(Imm == static_cast<int64_t>(Lo16)) ||
|
||||
(static_cast<uint64_t>(Imm) ==
|
||||
static_cast<uint64_t>(static_cast<uint32_t>(static_cast<int32_t>(Lo16))));
|
||||
Addr = MCOperand::createImm(
|
||||
IsSext16 ? (static_cast<uint64_t>(Imm) & 0xFFFFu)
|
||||
: (static_cast<uint64_t>(Imm) & 0xFFFFFFu));
|
||||
}
|
||||
EmitToStreamer(*OutStreamer,
|
||||
MCInstBuilder(IsLong ? W65816::STA_Long : W65816::STA_Abs)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue