mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-07-25 13:24:46 +00:00
[mips] Fix expansion of memory operation if destination register is not a GPR.
Summary: The assembler tries to reuse the destination register for memory operations whenever it can but it's not possible to do so if the destination register is not a GPR. Example: ldc1 $f0, sym should expand to: lui $at, %hi(sym) ldc1 $f0, %lo(sym)($at) It's entirely wrong to expand to: lui $f0, %hi(sym) ldc1 $f0, %lo(sym)($f0) Reviewers: dsanders Reviewed By: dsanders Differential Revision: http://reviews.llvm.org/D4173 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@211169 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -1144,10 +1144,35 @@ void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
|
||||
ExprOffset = Inst.getOperand(2).getExpr();
|
||||
// All instructions will have the same location.
|
||||
TempInst.setLoc(IDLoc);
|
||||
// 1st instruction in expansion is LUi. For load instruction we can use
|
||||
// the dst register as a temporary if base and dst are different,
|
||||
// but for stores we must use $at.
|
||||
if (isLoad && (BaseRegNum != RegOpNum))
|
||||
// These are some of the types of expansions we perform here:
|
||||
// 1) lw $8, sym => lui $8, %hi(sym)
|
||||
// lw $8, %lo(sym)($8)
|
||||
// 2) lw $8, offset($9) => lui $8, %hi(offset)
|
||||
// add $8, $8, $9
|
||||
// lw $8, %lo(offset)($9)
|
||||
// 3) lw $8, offset($8) => lui $at, %hi(offset)
|
||||
// add $at, $at, $8
|
||||
// lw $8, %lo(offset)($at)
|
||||
// 4) sw $8, sym => lui $at, %hi(sym)
|
||||
// sw $8, %lo(sym)($at)
|
||||
// 5) sw $8, offset($8) => lui $at, %hi(offset)
|
||||
// add $at, $at, $8
|
||||
// sw $8, %lo(offset)($at)
|
||||
// 6) ldc1 $f0, sym => lui $at, %hi(sym)
|
||||
// ldc1 $f0, %lo(sym)($at)
|
||||
//
|
||||
// For load instructions we can use the destination register as a temporary
|
||||
// if base and dst are different (examples 1 and 2) and if the base register
|
||||
// is general purpose otherwise we must use $at (example 6) and error if it's
|
||||
// not available. For stores we must use $at (examples 4 and 5) because we
|
||||
// must not clobber the source register setting up the offset.
|
||||
const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
|
||||
int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
|
||||
unsigned RegClassIDOp0 =
|
||||
getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
|
||||
bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
|
||||
(RegClassIDOp0 == Mips::GPR64RegClassID);
|
||||
if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
|
||||
TmpRegNum = RegOpNum;
|
||||
else {
|
||||
int AT = getATReg(IDLoc);
|
||||
|
Reference in New Issue
Block a user