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);
|
IsLong = IsLong || isFarGlobalOperand(AddrMO);
|
||||||
MCOperand Addr = lowerOperand(AddrMO, MCInstLowering);
|
MCOperand Addr = lowerOperand(AddrMO, MCInstLowering);
|
||||||
if (IsLong && Addr.isImm()) {
|
if (IsLong && Addr.isImm()) {
|
||||||
// 16-bit pointer sign-extended into i32 imm — mask back to 16 bits
|
// Sign-extended 16-bit pointer -> low 16 (bank 0); genuine 24-bit
|
||||||
// so the encoded bank byte is 0. See STA8long for the rationale.
|
// constant address -> keep low 24 (bank preserved). See STA8long.
|
||||||
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));
|
||||||
}
|
}
|
||||||
emitSepM();
|
emitSepM();
|
||||||
EmitToStreamer(*OutStreamer,
|
EmitToStreamer(*OutStreamer,
|
||||||
|
|
@ -878,15 +886,28 @@ void W65816AsmPrinter::emitInstruction(const MachineInstr *MI) {
|
||||||
emitSepM();
|
emitSepM();
|
||||||
}
|
}
|
||||||
MCOperand Addr = lowerOperand(MI->getOperand(1), MCInstLowering);
|
MCOperand Addr = lowerOperand(MI->getOperand(1), MCInstLowering);
|
||||||
// STA_Long takes a 24-bit absolute address. When the input is a
|
// STA_Long takes a 24-bit absolute address. Two cases reach here as
|
||||||
// const-int cast through a 16-bit pointer, TableGen sign-extends
|
// an immediate:
|
||||||
// the 16-bit value into the i32 imm operand: 0xC035 (i16) becomes
|
// (a) a const-int cast through a 16-bit pointer, which TableGen
|
||||||
// 0xFFFFC035 (i64). Mask to 16 bits to recover the original
|
// SIGN-EXTENDS into the wider imm (0xC035 -> ...FFFFC035); the
|
||||||
// pointer; the resulting encoding has bank=0 explicit. Users who
|
// intended bank is 0, so recover the low 16 bits.
|
||||||
// need a banked address should construct a far pointer rather than
|
// (b) a genuine >16-bit constant address such as 0xE12000 (a fixed
|
||||||
// casting an int.
|
// 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()) {
|
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,
|
EmitToStreamer(*OutStreamer,
|
||||||
MCInstBuilder(IsLong ? W65816::STA_Long : W65816::STA_Abs)
|
MCInstBuilder(IsLong ? W65816::STA_Long : W65816::STA_Abs)
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue