mirror of
https://github.com/RPCSX/llvm.git
synced 2025-03-04 19:07:26 +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:
parent
cacc062572
commit
c39b18b306
@ -1144,10 +1144,35 @@ void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
|
|||||||
ExprOffset = Inst.getOperand(2).getExpr();
|
ExprOffset = Inst.getOperand(2).getExpr();
|
||||||
// All instructions will have the same location.
|
// All instructions will have the same location.
|
||||||
TempInst.setLoc(IDLoc);
|
TempInst.setLoc(IDLoc);
|
||||||
// 1st instruction in expansion is LUi. For load instruction we can use
|
// These are some of the types of expansions we perform here:
|
||||||
// the dst register as a temporary if base and dst are different,
|
// 1) lw $8, sym => lui $8, %hi(sym)
|
||||||
// but for stores we must use $at.
|
// lw $8, %lo(sym)($8)
|
||||||
if (isLoad && (BaseRegNum != RegOpNum))
|
// 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;
|
TmpRegNum = RegOpNum;
|
||||||
else {
|
else {
|
||||||
int AT = getATReg(IDLoc);
|
int AT = getATReg(IDLoc);
|
||||||
|
@ -34,6 +34,11 @@
|
|||||||
# CHECK: addu $1, $1, $9 # encoding: [0x21,0x08,0x29,0x00]
|
# CHECK: addu $1, $1, $9 # encoding: [0x21,0x08,0x29,0x00]
|
||||||
# CHECK: sw $10, 57920($1) # encoding: [0x40,0xe2,0x2a,0xac]
|
# CHECK: sw $10, 57920($1) # encoding: [0x40,0xe2,0x2a,0xac]
|
||||||
|
|
||||||
|
# CHECK: lui $1, %hi(symbol)
|
||||||
|
# CHECK: ldc1 $f0, %lo(symbol)($1)
|
||||||
|
# CHECK: lui $1, %hi(symbol)
|
||||||
|
# CHECK: sdc1 $f0, %lo(symbol)($1)
|
||||||
|
|
||||||
li $5,123
|
li $5,123
|
||||||
li $6,-2345
|
li $6,-2345
|
||||||
li $7,65538
|
li $7,65538
|
||||||
@ -51,3 +56,6 @@
|
|||||||
|
|
||||||
lw $t2, 655483($a0)
|
lw $t2, 655483($a0)
|
||||||
sw $t2, 123456($t1)
|
sw $t2, 123456($t1)
|
||||||
|
|
||||||
|
ldc1 $f0, symbol
|
||||||
|
sdc1 $f0, symbol
|
||||||
|
Loading…
x
Reference in New Issue
Block a user