1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-20 03:23:01 +02:00

[mips] Support 64-bit offsets for lb/sb/ld/sd/lld ... instructions

The `MipsAsmParser::loadImmediate` can load immediates of various sizes
into a register. Idea of this change is to use `loadImmediate` in the
`MipsAsmParser::expandMemInst` method to load offset into a register and
then call required load/store instruction.

The patch removes separate `expandLoadInst` and `expandStoreInst`
methods and does everything in the `expandMemInst` method to escape code
duplication.

Differential Revision: https://reviews.llvm.org/D47316

llvm-svn: 333774
This commit is contained in:
Simon Atanasyan 2018-06-01 16:37:53 +00:00
parent a01979c6b4
commit dd563e1f3f
5 changed files with 206 additions and 81 deletions

View File

@ -245,12 +245,6 @@ class MipsAsmParser : public MCTargetAsmParser {
void expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
const MCSubtargetInfo *STI, bool IsLoad);
void expandLoadInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
const MCSubtargetInfo *STI);
void expandStoreInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
const MCSubtargetInfo *STI);
bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
const MCSubtargetInfo *STI);
@ -1326,7 +1320,7 @@ public:
return false;
if (!getMemBase()->isGPRAsmReg())
return false;
const unsigned PtrBits = 32;
const unsigned PtrBits = AsmParser.getABI().ArePtrs64bit() ? 64 : 32;
if (isa<MCTargetExpr>(getMemOff()) ||
(isConstantMemOff() && isIntN(PtrBits, getConstantMemOff())))
return true;
@ -2143,7 +2137,7 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
(OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
MCOperand &Op = Inst.getOperand(i);
if (Op.isImm()) {
int MemOffset = Op.getImm();
int64_t MemOffset = Op.getImm();
if (MemOffset < -32768 || MemOffset > 32767) {
// Offset can't exceed 16bit value.
expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad());
@ -3569,14 +3563,6 @@ bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
const MCSubtargetInfo *STI, bool IsLoad) {
if (IsLoad)
expandLoadInst(Inst, IDLoc, Out, STI);
else
expandStoreInst(Inst, IDLoc, Out, STI);
}
void MipsAsmParser::expandLoadInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
const MCSubtargetInfo *STI) {
const MCOperand &DstRegOp = Inst.getOperand(0);
assert(DstRegOp.isReg() && "expected register operand kind");
const MCOperand &BaseRegOp = Inst.getOperand(1);
@ -3595,7 +3581,7 @@ void MipsAsmParser::expandLoadInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
bool IsGPR = (DstRegClassID == Mips::GPR32RegClassID) ||
(DstRegClassID == Mips::GPR64RegClassID);
if (!IsGPR || (BaseReg == DstReg)) {
if (!IsLoad || !IsGPR || (BaseReg == DstReg)) {
// At this point we need AT to perform the expansions
// and we exit if it is not available.
TmpReg = getATReg(IDLoc);
@ -3604,8 +3590,27 @@ void MipsAsmParser::expandLoadInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
}
if (OffsetOp.isImm()) {
TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
OffsetOp.getImm(), TmpReg, IDLoc, STI);
int64_t LoOffset = OffsetOp.getImm() & 0xffff;
int64_t HiOffset = OffsetOp.getImm() & ~0xffff;
// If msb of LoOffset is 1(negative number) we must increment
// HiOffset to account for the sign-extension of the low part.
if (LoOffset & 0x8000)
HiOffset += 0x10000;
bool IsLargeOffset = HiOffset != 0;
if (IsLargeOffset) {
bool Is32BitImm = (HiOffset >> 32) == 0;
if (loadImmediate(HiOffset, TmpReg, Mips::NoRegister, Is32BitImm, true,
IDLoc, Out, STI))
return;
}
if (BaseReg != Mips::ZERO && BaseReg != Mips::ZERO_64)
TOut.emitRRR(isGP64bit() ? Mips::DADDu : Mips::ADDu, TmpReg, TmpReg,
BaseReg, IDLoc, STI);
TOut.emitRRI(Inst.getOpcode(), DstReg, TmpReg, LoOffset, IDLoc, STI);
} else {
assert(OffsetOp.isExpr() && "expected expression operand kind");
const MCExpr *ExprOffset = OffsetOp.getExpr();
@ -3613,44 +3618,16 @@ void MipsAsmParser::expandLoadInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
MCOperand HiOperand = MCOperand::createExpr(
MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
LoOperand, TmpReg, IDLoc, STI);
if (IsLoad)
TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
LoOperand, TmpReg, IDLoc, STI);
else
TOut.emitStoreWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
LoOperand, TmpReg, IDLoc, STI);
}
}
void MipsAsmParser::expandStoreInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
const MCSubtargetInfo *STI) {
const MCOperand &SrcRegOp = Inst.getOperand(0);
assert(SrcRegOp.isReg() && "expected register operand kind");
const MCOperand &BaseRegOp = Inst.getOperand(1);
assert(BaseRegOp.isReg() && "expected register operand kind");
const MCOperand &OffsetOp = Inst.getOperand(2);
MipsTargetStreamer &TOut = getTargetStreamer();
unsigned SrcReg = SrcRegOp.getReg();
unsigned BaseReg = BaseRegOp.getReg();
if (OffsetOp.isImm()) {
TOut.emitStoreWithImmOffset(Inst.getOpcode(), SrcReg, BaseReg,
OffsetOp.getImm(),
[&]() { return getATReg(IDLoc); }, IDLoc, STI);
return;
}
unsigned ATReg = getATReg(IDLoc);
if (!ATReg)
return;
assert(OffsetOp.isExpr() && "expected expression operand kind");
const MCExpr *ExprOffset = OffsetOp.getExpr();
MCOperand LoOperand = MCOperand::createExpr(
MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
MCOperand HiOperand = MCOperand::createExpr(
MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
TOut.emitStoreWithSymOffset(Inst.getOpcode(), SrcReg, BaseReg, HiOperand,
LoOperand, ATReg, IDLoc, STI);
}
bool MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
MCStreamer &Out,
const MCSubtargetInfo *STI) {

View File

@ -270,11 +270,10 @@ sym:
# CHECK: lwl $8, 3($1) # encoding: [0x03,0x00,0x28,0x88]
# CHECK: lwr $8, 0($1) # encoding: [0x00,0x00,0x28,0x98]
# Test ld/sd/lld with offsets exceed 16-bit size.
# Test lb/sb/ld/sd/lld with offsets exceeding 16-bits in size.
ld $4, 0x8000
# CHECK: lui $4, 1
# CHECK-NEXT: addu $4, $4, $zero
# CHECK-NEXT: ld $4, -32768($4)
ld $4, 0x20008($3)
@ -282,9 +281,32 @@ sym:
# CHECK-NEXT: addu $4, $4, $3
# CHECK-NEXT: ld $4, 8($4)
ld $4,0x100010004
# CHECK: addiu $4, $zero, 1
# CHECK-NEXT: dsll $4, $4, 16
# CHECK-NEXT: ori $4, $4, 1
# CHECK-NEXT: dsll $4, $4, 16
# CHECK-NEXT: ld $4, 4($4)
ld $4,0x1800180018004
# CHECK: lui $4, 1
# CHECK-NEXT: ori $4, $4, 32769
# CHECK-NEXT: dsll $4, $4, 16
# CHECK-NEXT: ori $4, $4, 32770
# CHECK-NEXT: dsll $4, $4, 16
# CHECK-NEXT: ld $4, -32764($4)
ld $4,0x1800180018004($3)
# CHECK: lui $4, 1
# CHECK-NEXT: ori $4, $4, 32769
# CHECK-NEXT: dsll $4, $4, 16
# CHECK-NEXT: ori $4, $4, 32770
# CHECK-NEXT: dsll $4, $4, 16
# CHECK-NEXT: daddu $4, $4, $3
# CHECK-NEXT: ld $4, -32764($4)
sd $4, 0x8000
# CHECK: lui $1, 1
# CHECK-NEXT: addu $1, $1, $zero
# CHECK-NEXT: sd $4, -32768($1)
sd $4, 0x20008($3)
@ -292,12 +314,155 @@ sym:
# CHECK-NEXT: addu $1, $1, $3
# CHECK-NEXT: sd $4, 8($1)
sd $4,0x100010004
# CHECK: addiu $1, $zero, 1
# CHECK-NEXT: dsll $1, $1, 16
# CHECK-NEXT: ori $1, $1, 1
# CHECK-NEXT: dsll $1, $1, 16
# CHECK-NEXT: sd $4, 4($1)
sd $4,0x1800180018004
# CHECK: lui $1, 1
# CHECK-NEXT: ori $1, $1, 32769
# CHECK-NEXT: dsll $1, $1, 16
# CHECK-NEXT: ori $1, $1, 32770
# CHECK-NEXT: dsll $1, $1, 16
# CHECK-NEXT: sd $4, -32764($1)
sd $4,0x1800180018004($3)
# CHECK: lui $1, 1
# CHECK-NEXT: ori $1, $1, 32769
# CHECK-NEXT: dsll $1, $1, 16
# CHECK-NEXT: ori $1, $1, 32770
# CHECK-NEXT: dsll $1, $1, 16
# CHECK-NEXT: daddu $1, $1, $3
# CHECK-NEXT: sd $4, -32764($1)
lld $4, 0x8000
# CHECK: lui $4, 1
# CHECK-NEXT: addu $4, $4, $zero
# CHECK-NEXT: lld $4, -32768($4)
lld $4, 0x20008($3)
# CHECK: lui $4, 2
# CHECK-NEXT: addu $4, $4, $3
# CHECK-NEXT: lld $4, 8($4)
lld $4,0x100010004
# CHECK: addiu $4, $zero, 1
# CHECK-NEXT: dsll $4, $4, 16
# CHECK-NEXT: ori $4, $4, 1
# CHECK-NEXT: dsll $4, $4, 16
# CHECK-NEXT: lld $4, 4($4)
lld $4,0x1800180018004
# CHECK: lui $4, 1
# CHECK-NEXT: ori $4, $4, 32769
# CHECK-NEXT: dsll $4, $4, 16
# CHECK-NEXT: ori $4, $4, 32770
# CHECK-NEXT: dsll $4, $4, 16
# CHECK-NEXT: lld $4, -32764($4)
lld $4,0x1800180018004($3)
# CHECK: lui $4, 1
# CHECK-NEXT: ori $4, $4, 32769
# CHECK-NEXT: dsll $4, $4, 16
# CHECK-NEXT: ori $4, $4, 32770
# CHECK-NEXT: dsll $4, $4, 16
# CHECK-NEXT: daddu $4, $4, $3
# CHECK-NEXT: lld $4, -32764($4)
lb $4,0x100010004
# CHECK: addiu $4, $zero, 1
# CHECK-NEXT: dsll $4, $4, 16
# CHECK-NEXT: ori $4, $4, 1
# CHECK-NEXT: dsll $4, $4, 16
# CHECK-NEXT: lb $4, 4($4)
lb $4,0x1800180018004
# CHECK: lui $4, 1
# CHECK-NEXT: ori $4, $4, 32769
# CHECK-NEXT: dsll $4, $4, 16
# CHECK-NEXT: ori $4, $4, 32770
# CHECK-NEXT: dsll $4, $4, 16
# CHECK-NEXT: lb $4, -32764($4)
lb $4,0x1800180018004($3)
# CHECK: lui $4, 1
# CHECK-NEXT: ori $4, $4, 32769
# CHECK-NEXT: dsll $4, $4, 16
# CHECK-NEXT: ori $4, $4, 32770
# CHECK-NEXT: dsll $4, $4, 16
# CHECK-NEXT: daddu $4, $4, $3
# CHECK-NEXT: lb $4, -32764($4)
sb $4,0x100010004
# CHECK: addiu $1, $zero, 1
# CHECK-NEXT: dsll $1, $1, 16
# CHECK-NEXT: ori $1, $1, 1
# CHECK-NEXT: dsll $1, $1, 16
# CHECK-NEXT: sb $4, 4($1)
sb $4,0x1800180018004
# CHECK: lui $1, 1
# CHECK-NEXT: ori $1, $1, 32769
# CHECK-NEXT: dsll $1, $1, 16
# CHECK-NEXT: ori $1, $1, 32770
# CHECK-NEXT: dsll $1, $1, 16
# CHECK-NEXT: sb $4, -32764($1)
sb $4,0x1800180018004($3)
# CHECK: lui $1, 1
# CHECK-NEXT: ori $1, $1, 32769
# CHECK-NEXT: dsll $1, $1, 16
# CHECK-NEXT: ori $1, $1, 32770
# CHECK-NEXT: dsll $1, $1, 16
# CHECK-NEXT: daddu $1, $1, $3
# CHECK-NEXT: sb $4, -32764($1)
lh $4,0x100010004
# CHECK: addiu $4, $zero, 1
# CHECK-NEXT: dsll $4, $4, 16
# CHECK-NEXT: ori $4, $4, 1
# CHECK-NEXT: dsll $4, $4, 16
# CHECK-NEXT: lh $4, 4($4)
lh $4,0x1800180018004
# CHECK: lui $4, 1
# CHECK-NEXT: ori $4, $4, 32769
# CHECK-NEXT: dsll $4, $4, 16
# CHECK-NEXT: ori $4, $4, 32770
# CHECK-NEXT: dsll $4, $4, 16
# CHECK-NEXT: lh $4, -32764($4)
lh $4,0x1800180018004($3)
# CHECK: lui $4, 1
# CHECK-NEXT: ori $4, $4, 32769
# CHECK-NEXT: dsll $4, $4, 16
# CHECK-NEXT: ori $4, $4, 32770
# CHECK-NEXT: dsll $4, $4, 16
# CHECK-NEXT: daddu $4, $4, $3
# CHECK-NEXT: lh $4, -32764($4)
lhu $4,0x100010004
# CHECK: addiu $4, $zero, 1
# CHECK-NEXT: dsll $4, $4, 16
# CHECK-NEXT: ori $4, $4, 1
# CHECK-NEXT: dsll $4, $4, 16
# CHECK-NEXT: lhu $4, 4($4)
lhu $4,0x1800180018004
# CHECK: lui $4, 1
# CHECK-NEXT: ori $4, $4, 32769
# CHECK-NEXT: dsll $4, $4, 16
# CHECK-NEXT: ori $4, $4, 32770
# CHECK-NEXT: dsll $4, $4, 16
# CHECK-NEXT: lhu $4, -32764($4)
lhu $4,0x1800180018004($3)
# CHECK: lui $4, 1
# CHECK-NEXT: ori $4, $4, 32769
# CHECK-NEXT: dsll $4, $4, 16
# CHECK-NEXT: ori $4, $4, 32770
# CHECK-NEXT: dsll $4, $4, 16
# CHECK-NEXT: daddu $4, $4, $3
# CHECK-NEXT: lhu $4, -32764($4)

View File

@ -20,12 +20,8 @@
dmfc0 $4, $3, 8 # CHECK: :[[@LINE]]:24: error: expected 3-bit unsigned immediate
sd $32, 65536($32) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid register number
lb $32, 8($5) # CHECK: :[[@LINE]]:12: error: invalid register number
lb $4, -2147483649($5) # CHECK: :[[@LINE]]:16: error: expected memory with 32-bit signed offset
lb $4, 2147483648($5) # CHECK: :[[@LINE]]:16: error: expected memory with 32-bit signed offset
lb $4, 8($32) # CHECK: :[[@LINE]]:18: error: invalid register number
lbu $32, 8($5) # CHECK: :[[@LINE]]:13: error: invalid register number
lbu $4, -2147483649($5) # CHECK: :[[@LINE]]:17: error: expected memory with 32-bit signed offset
lbu $4, 2147483648($5) # CHECK: :[[@LINE]]:17: error: expected memory with 32-bit signed offset
lbu $4, 8($32) # CHECK: :[[@LINE]]:19: error: invalid register number
ldc1 $f32, 300($10) # CHECK: :[[@LINE]]:14: error: invalid operand for instruction
ldc1 $f7, -32769($10) # CHECK: :[[@LINE]]:19: error: expected memory with 16-bit signed offset

View File

@ -194,20 +194,21 @@ a:
jalr.hb $4, $5 # CHECK: jalr.hb $4, $5 # encoding: [0x00,0xa0,0x24,0x09]
l.s $f2, 8($3) # CHECK: lwc1 $f2, 8($3) # encoding: [0xc4,0x62,0x00,0x08]
l.d $f2, 8($3) # CHECK: ldc1 $f2, 8($3) # encoding: [0xd4,0x62,0x00,0x08]
lb $24,-14515($10)
lbu $8,30195($v1)
ld $sp,-28645($s1)
lb $24,-2147483649($10)
lbu $24,-2147483649($10)
ld $sp,-2147483649($s1)
ldc1 $f11,16391($s0)
ldc2 $8,-21181($at) # CHECK: ldc2 $8, -21181($1) # encoding: [0xd8,0x28,0xad,0x43]
ldl $24,-4167($24)
ldr $14,-30358($s4)
ldxc1 $f8,$s7($15)
lh $11,-8556($s5)
lhu $s3,-22851($v0)
lh $11,-2147483649($s5)
lhu $s3,-2147483649($v0)
li $at,-29773
li $zero,-29889
ll $v0,-7321($s2) # CHECK: ll $2, -7321($18) # encoding: [0xc2,0x42,0xe3,0x67]
lld $zero,-14736($ra) # CHECK: lld $zero, -14736($ra) # encoding: [0xd3,0xe0,0xc6,0x70]
lld $24,-2147483649($10)
luxc1 $f19,$s6($s5)
lw $8,5674($a1)
lwc1 $f16,10225($k0)

View File

@ -60,12 +60,8 @@ local_label:
lhe $4, 8($33) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid register number
lhu $4, 8($35) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid register number
lhue $4, 8($37) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid register number
lh $2, -2147483649($4) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: expected memory with 32-bit signed offset
lh $2, 2147483648($4) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: expected memory with 32-bit signed offset
lhe $4, -512($2) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
lhe $4, 512($2) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
lhu $4, -2147483649($2) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: expected memory with 32-bit signed offset
lhu $4, 2147483648($2) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: expected memory with 32-bit signed offset
lhue $4, -512($2) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
lhue $4, 512($2) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
// FIXME: Following tests are temporarily disabled, until "PredicateControl not in hierarchy" problem is resolved
@ -178,14 +174,8 @@ local_label:
dmtc0 $4, $3, 8 # CHECK: :[[@LINE]]:24: error: expected 3-bit unsigned immediate
dmfc0 $4, $3, -1 # CHECK: :[[@LINE]]:24: error: expected 3-bit unsigned immediate
dmfc0 $4, $3, 8 # CHECK: :[[@LINE]]:24: error: expected 3-bit unsigned immediate
ld $2, 2147483648($4) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: expected memory with 32-bit signed offset
ld $2, -2147483649($4) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: expected memory with 32-bit signed offset
ld $32, 65536($32) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid register number
lld $2, -2147483649($4) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: expected memory with 32-bit signed offset
lld $2, 2147483648($4) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: expected memory with 32-bit signed offset
sd $2, -2147483649($4) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: expected memory with 32-bit signed offset
lld $32, 4096($32) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid register number
sd $2, 2147483648($4) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: expected memory with 32-bit signed offset
sd $32, 65536($32) # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid register number
dsrl $2, $4, 64 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: expected 6-bit unsigned immediate
dsrl $2, $4, -2 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: expected 6-bit unsigned immediate
@ -195,12 +185,8 @@ local_label:
dsrlv $2, $4, 2 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid operand for instruction
dsrlv $32, $32, $32 # CHECK: :[[@LINE]]:{{[0-9]+}}: error: invalid register number
lb $32, 8($5) # CHECK: :[[@LINE]]:12: error: invalid register number
lb $4, -2147483649($5) # CHECK: :[[@LINE]]:16: error: expected memory with 32-bit signed offset
lb $4, 2147483648($5) # CHECK: :[[@LINE]]:16: error: expected memory with 32-bit signed offset
lb $4, 8($32) # CHECK: :[[@LINE]]:18: error: invalid register number
lbu $32, 8($5) # CHECK: :[[@LINE]]:13: error: invalid register number
lbu $4, -2147483649($5) # CHECK: :[[@LINE]]:17: error: expected memory with 32-bit signed offset
lbu $4, 2147483648($5) # CHECK: :[[@LINE]]:17: error: expected memory with 32-bit signed offset
lbu $4, 8($32) # CHECK: :[[@LINE]]:19: error: invalid register number
ldc1 $f32, 300($10) # CHECK: :[[@LINE]]:14: error: invalid operand for instruction
ldc1 $f7, -32769($10) # CHECK: :[[@LINE]]:19: error: expected memory with 16-bit signed offset