forked from OSchip/llvm-project
[mips] Accept 32-bit offsets for lb and lbu commands
`lb` and `lbu` commands accepts 16-bit signed offsets. But GAS accepts larger offsets for these commands. If an offset does not fit in 16-bit range, `lb` command is translated into lui/lb or lui/addu/lb series. It's interesting that initially LLVM assembler supported this feature, but later it was broken. This patch restores support for 32-bit offsets. It replaces `mem_simm16` operand for `LB` and `LBu` definitions by the new `mem_simmptr` operand. This operand is intended to check that offset fits to the same size as using for pointers. Later we will be able to extend this rule and accepts 64-bit offsets when it is possible. Some issues remain: - The regression also affects LD, SD, LH, LHU commands. I'm going to fix them by a separate patch. - GAS accepts any 32-bit values as an offset. Now LLVM accepts signed 16-bit values and this patch extends the range to signed 32-bit offsets. In other words, the following code accepted by GAS and still triggers an error by LLVM: ``` lb $4, 0x80000004 # gas lui a0, 0x8000 lb a0, 4(a0) ``` - In case of 64-bit pointers GAS accepts a 64-bit offset and translates it to the li/dsll/lb series of commands. LLVM still rejects it. Probably this feature has never been implemented in LLVM. This issue is for a separate patch. ``` lb $4, 0x800000001 # gas li a0, 0x8000 dsll a0, a0, 0x14 lb a0, 4(a0) ``` Differential Revision: https://reviews.llvm.org/D45020 llvm-svn: 330983
This commit is contained in:
parent
6a31a0d694
commit
d4d892ff9f
|
@ -1303,6 +1303,20 @@ public:
|
|||
return IsReloc && isShiftedInt<Bits, ShiftAmount>(Res.getConstant());
|
||||
}
|
||||
|
||||
bool isMemWithPtrSizeOffset() const {
|
||||
if (!isMem())
|
||||
return false;
|
||||
if (!getMemBase()->isGPRAsmReg())
|
||||
return false;
|
||||
const unsigned PtrBits = 32;
|
||||
if (isa<MCTargetExpr>(getMemOff()) ||
|
||||
(isConstantMemOff() && isIntN(PtrBits, getConstantMemOff())))
|
||||
return true;
|
||||
MCValue Res;
|
||||
bool IsReloc = getMemOff()->evaluateAsRelocatable(Res, nullptr, nullptr);
|
||||
return IsReloc && isIntN(PtrBits, Res.getConstant());
|
||||
}
|
||||
|
||||
bool isMemWithGRPMM16Base() const {
|
||||
return isMem() && getMemBase()->isMM16AsmReg();
|
||||
}
|
||||
|
@ -5452,6 +5466,9 @@ bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
|
|||
case Match_MemSImm16:
|
||||
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
|
||||
"expected memory with 16-bit signed offset");
|
||||
case Match_MemSImmPtr:
|
||||
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
|
||||
"expected memory with 32-bit signed offset");
|
||||
case Match_RequiresPosSizeRange0_32: {
|
||||
SMLoc ErrorStart = Operands[3]->getStartLoc();
|
||||
SMLoc ErrorEnd = Operands[4]->getEndLoc();
|
||||
|
|
|
@ -1108,6 +1108,15 @@ def MipsMemSimm16AsmOperand : AsmOperandClass {
|
|||
let DiagnosticType = "MemSImm16";
|
||||
}
|
||||
|
||||
def MipsMemSimmPtrAsmOperand : AsmOperandClass {
|
||||
let Name = "MemOffsetSimmPtr";
|
||||
let SuperClasses = [MipsMemAsmOperand];
|
||||
let RenderMethod = "addMemOperands";
|
||||
let ParserMethod = "parseMemOperand";
|
||||
let PredicateMethod = "isMemWithPtrSizeOffset";
|
||||
let DiagnosticType = "MemSImmPtr";
|
||||
}
|
||||
|
||||
def MipsInvertedImmoperand : AsmOperandClass {
|
||||
let Name = "InvNum";
|
||||
let RenderMethod = "addImmOperands";
|
||||
|
@ -1181,6 +1190,10 @@ def mem_simm16 : mem_generic {
|
|||
let ParserMatchClass = MipsMemSimm16AsmOperand;
|
||||
}
|
||||
|
||||
def mem_simmptr : mem_generic {
|
||||
let ParserMatchClass = MipsMemSimmPtrAsmOperand;
|
||||
}
|
||||
|
||||
def mem_ea : Operand<iPTR> {
|
||||
let PrintMethod = "printMemOperandEA";
|
||||
let MIOperandInfo = (ops ptr_rc, simm16);
|
||||
|
@ -1997,9 +2010,9 @@ let AdditionalPredicates = [NotInMicroMips] in {
|
|||
|
||||
/// Load and Store Instructions
|
||||
/// aligned
|
||||
def LB : LoadMemory<"lb", GPR32Opnd, mem_simm16, sextloadi8, II_LB>, MMRel,
|
||||
def LB : LoadMemory<"lb", GPR32Opnd, mem_simmptr, sextloadi8, II_LB>, MMRel,
|
||||
LW_FM<0x20>;
|
||||
def LBu : LoadMemory<"lbu", GPR32Opnd, mem_simm16, zextloadi8, II_LBU,
|
||||
def LBu : LoadMemory<"lbu", GPR32Opnd, mem_simmptr, zextloadi8, II_LBU,
|
||||
addrDefault>, MMRel, LW_FM<0x24>;
|
||||
let AdditionalPredicates = [NotInMicroMips] in {
|
||||
def LH : LoadMemory<"lh", GPR32Opnd, mem_simm16, sextloadi16, II_LH,
|
||||
|
|
|
@ -121,10 +121,10 @@
|
|||
xori $3, 65536 # CHECK: :[[@LINE]]:12: error: expected 16-bit unsigned immediate
|
||||
not $3, 4 # CHECK: :[[@LINE]]:11: error: invalid operand for instruction
|
||||
lb $32, 8($5) # CHECK: :[[@LINE]]:6: error: invalid register number
|
||||
lb $4, -32769($5) # CHECK: :[[@LINE]]:10: error: expected memory with 16-bit signed offset
|
||||
lb $4, 32768($5) # CHECK: :[[@LINE]]:10: error: expected memory with 16-bit signed offset
|
||||
lb $4, -2147483649($5) # CHECK: :[[@LINE]]:10: error: expected memory with 32-bit signed offset
|
||||
lb $4, 2147483648($5) # CHECK: :[[@LINE]]:10: error: expected memory with 32-bit signed offset
|
||||
lb $4, 8($32) # CHECK: :[[@LINE]]:12: error: invalid register number
|
||||
lbu $32, 8($5) # CHECK: :[[@LINE]]:7: error: invalid register number
|
||||
lbu $4, -32769($5) # CHECK: :[[@LINE]]:11: error: expected memory with 16-bit signed offset
|
||||
lbu $4, 32768($5) # CHECK: :[[@LINE]]:11: error: expected memory with 16-bit signed offset
|
||||
lbu $4, -2147483649($5) # CHECK: :[[@LINE]]:11: error: expected memory with 32-bit signed offset
|
||||
lbu $4, 2147483648($5) # CHECK: :[[@LINE]]:11: error: expected memory with 32-bit signed offset
|
||||
lbu $4, 8($32) # CHECK: :[[@LINE]]:13: error: invalid register number
|
||||
|
|
|
@ -253,12 +253,12 @@
|
|||
xori $3, 65536 # CHECK: :[[@LINE]]:12: error: expected 16-bit unsigned immediate
|
||||
not $3, 4 # CHECK: :[[@LINE]]:11: error: invalid operand for instruction
|
||||
lb $32, 8($5) # CHECK: :[[@LINE]]:6: error: invalid register number
|
||||
lb $4, -32769($5) # CHECK: :[[@LINE]]:10: error: expected memory with 16-bit signed offset
|
||||
lb $4, 32768($5) # CHECK: :[[@LINE]]:10: error: expected memory with 16-bit signed offset
|
||||
lb $4, -2147483649($5) # CHECK: :[[@LINE]]:10: error: expected memory with 32-bit signed offset
|
||||
lb $4, 2147483648($5) # CHECK: :[[@LINE]]:10: error: expected memory with 32-bit signed offset
|
||||
lb $4, 8($32) # CHECK: :[[@LINE]]:12: error: invalid register number
|
||||
lbu $32, 8($5) # CHECK: :[[@LINE]]:7: error: invalid register number
|
||||
lbu $4, -32769($5) # CHECK: :[[@LINE]]:11: error: expected memory with 16-bit signed offset
|
||||
lbu $4, 32768($5) # CHECK: :[[@LINE]]:11: error: expected memory with 16-bit signed offset
|
||||
lbu $4, -2147483649($5) # CHECK: :[[@LINE]]:11: error: expected memory with 32-bit signed offset
|
||||
lbu $4, 2147483648($5) # CHECK: :[[@LINE]]:11: error: expected memory with 32-bit signed offset
|
||||
lbu $4, 8($32) # CHECK: :[[@LINE]]:13: error: invalid register number
|
||||
ldc1 $f32, 300($10) # CHECK: :[[@LINE]]:8: error: invalid operand for instruction
|
||||
ldc1 $f7, -32769($10) # CHECK: :[[@LINE]]:13: error: expected memory with 16-bit signed offset
|
||||
|
|
|
@ -13,6 +13,24 @@
|
|||
# CHECK-LE: addiu $8, $8, %lo($tmp0) # encoding: [A,A,0x08,0x25]
|
||||
# CHECK-LE: # fixup A - offset: 0, value: %lo($tmp0), kind: fixup_Mips_LO16
|
||||
|
||||
lb $4, 0x8000
|
||||
# CHECK-LE: lui $4, 1 # encoding: [0x01,0x00,0x04,0x3c]
|
||||
# CHECK-LE: lb $4, -32768($4) # encoding: [0x00,0x80,0x84,0x80]
|
||||
|
||||
lb $4, 0x20004($3)
|
||||
# CHECK-LE: lui $4, 2 # encoding: [0x02,0x00,0x04,0x3c]
|
||||
# CHECK-LE: addu $4, $4, $3 # encoding: [0x21,0x20,0x83,0x00]
|
||||
# CHECK-LE: lb $4, 4($4) # encoding: [0x04,0x00,0x84,0x80]
|
||||
|
||||
lbu $4, 0x8000
|
||||
# CHECK-LE: lui $4, 1 # encoding: [0x01,0x00,0x04,0x3c]
|
||||
# CHECK-LE: lbu $4, -32768($4) # encoding: [0x00,0x80,0x84,0x90]
|
||||
|
||||
lbu $4, 0x20004($3)
|
||||
# CHECK-LE: lui $4, 2 # encoding: [0x02,0x00,0x04,0x3c]
|
||||
# CHECK-LE: addu $4, $4, $3 # encoding: [0x21,0x20,0x83,0x00]
|
||||
# CHECK-LE: lbu $4, 4($4) # encoding: [0x04,0x00,0x84,0x90]
|
||||
|
||||
# LW/SW and LDC1/SDC1 of symbol address, done by MipsAsmParser::expandMemInst():
|
||||
.set noat
|
||||
lw $10, symbol($4)
|
||||
|
|
|
@ -21,12 +21,12 @@
|
|||
mfc2 $4, $3, -1 # CHECK: :[[@LINE]]:23: error: expected 3-bit unsigned immediate
|
||||
mfc2 $4, $3, 8 # CHECK: :[[@LINE]]:23: error: expected 3-bit unsigned immediate
|
||||
lb $32, 8($5) # CHECK: :[[@LINE]]:12: error: invalid register number
|
||||
lb $4, -32769($5) # CHECK: :[[@LINE]]:16: error: expected memory with 16-bit signed offset
|
||||
lb $4, 32768($5) # CHECK: :[[@LINE]]:16: error: expected memory with 16-bit signed offset
|
||||
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, -32769($5) # CHECK: :[[@LINE]]:17: error: expected memory with 16-bit signed offset
|
||||
lbu $4, 32768($5) # CHECK: :[[@LINE]]:17: error: expected memory with 16-bit signed offset
|
||||
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
|
||||
|
|
|
@ -146,12 +146,12 @@ local_label:
|
|||
sync -1 # CHECK: :[[@LINE]]:14: error: expected 5-bit unsigned immediate
|
||||
sync 32 # CHECK: :[[@LINE]]:14: error: expected 5-bit unsigned immediate
|
||||
lb $32, 8($5) # CHECK: :[[@LINE]]:12: error: invalid register number
|
||||
lb $4, -32769($5) # CHECK: :[[@LINE]]:16: error: expected memory with 16-bit signed offset
|
||||
lb $4, 32768($5) # CHECK: :[[@LINE]]:16: error: expected memory with 16-bit signed offset
|
||||
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, -32769($5) # CHECK: :[[@LINE]]:17: error: expected memory with 16-bit signed offset
|
||||
lbu $4, 32768($5) # CHECK: :[[@LINE]]:17: error: expected memory with 16-bit signed offset
|
||||
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
|
||||
|
|
|
@ -20,12 +20,12 @@
|
|||
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, -32769($5) # CHECK: :[[@LINE]]:16: error: expected memory with 16-bit signed offset
|
||||
lb $4, 32768($5) # CHECK: :[[@LINE]]:16: error: expected memory with 16-bit signed offset
|
||||
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, -32769($5) # CHECK: :[[@LINE]]:17: error: expected memory with 16-bit signed offset
|
||||
lbu $4, 32768($5) # CHECK: :[[@LINE]]:17: error: expected memory with 16-bit signed offset
|
||||
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
|
||||
|
|
|
@ -195,12 +195,12 @@ 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, -32769($5) # CHECK: :[[@LINE]]:16: error: expected memory with 16-bit signed offset
|
||||
lb $4, 32768($5) # CHECK: :[[@LINE]]:16: error: expected memory with 16-bit signed offset
|
||||
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, -32769($5) # CHECK: :[[@LINE]]:17: error: expected memory with 16-bit signed offset
|
||||
lbu $4, 32768($5) # CHECK: :[[@LINE]]:17: error: expected memory with 16-bit signed offset
|
||||
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
|
||||
|
|
Loading…
Reference in New Issue