diff options
| author | Simon Atanasyan <simon@atanasyan.com> | 2018-04-26 19:55:28 +0000 |
|---|---|---|
| committer | Simon Atanasyan <simon@atanasyan.com> | 2018-04-26 19:55:28 +0000 |
| commit | d4d892ff9f1b64c9cb24323facb70d6cc3f5b969 (patch) | |
| tree | 25e411afd62b6353792ef073e9dde8cc43c5007a | |
| parent | 6a31a0d694a65f5cb11ae6d49c7fdb3f08b0d262 (diff) | |
| download | bcm5719-llvm-d4d892ff9f1b64c9cb24323facb70d6cc3f5b969.tar.gz bcm5719-llvm-d4d892ff9f1b64c9cb24323facb70d6cc3f5b969.zip | |
[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
| -rw-r--r-- | llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp | 17 | ||||
| -rw-r--r-- | llvm/lib/Target/Mips/MipsInstrInfo.td | 17 | ||||
| -rw-r--r-- | llvm/test/MC/Mips/micromips/invalid.s | 8 | ||||
| -rw-r--r-- | llvm/test/MC/Mips/micromips32r6/invalid.s | 8 | ||||
| -rw-r--r-- | llvm/test/MC/Mips/mips-expansions.s | 18 | ||||
| -rw-r--r-- | llvm/test/MC/Mips/mips32r5/invalid.s | 8 | ||||
| -rw-r--r-- | llvm/test/MC/Mips/mips32r6/invalid.s | 8 | ||||
| -rw-r--r-- | llvm/test/MC/Mips/mips64r5/invalid.s | 8 | ||||
| -rw-r--r-- | llvm/test/MC/Mips/mips64r6/invalid.s | 8 |
9 files changed, 74 insertions, 26 deletions
diff --git a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp index 869e037b22b..59eeefe2f68 100644 --- a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -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(); diff --git a/llvm/lib/Target/Mips/MipsInstrInfo.td b/llvm/lib/Target/Mips/MipsInstrInfo.td index 3ee92826ee7..31e568da741 100644 --- a/llvm/lib/Target/Mips/MipsInstrInfo.td +++ b/llvm/lib/Target/Mips/MipsInstrInfo.td @@ -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, diff --git a/llvm/test/MC/Mips/micromips/invalid.s b/llvm/test/MC/Mips/micromips/invalid.s index b376ebe56a8..02158bcce29 100644 --- a/llvm/test/MC/Mips/micromips/invalid.s +++ b/llvm/test/MC/Mips/micromips/invalid.s @@ -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 diff --git a/llvm/test/MC/Mips/micromips32r6/invalid.s b/llvm/test/MC/Mips/micromips32r6/invalid.s index abbce6a674f..1fb3145646e 100644 --- a/llvm/test/MC/Mips/micromips32r6/invalid.s +++ b/llvm/test/MC/Mips/micromips32r6/invalid.s @@ -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 diff --git a/llvm/test/MC/Mips/mips-expansions.s b/llvm/test/MC/Mips/mips-expansions.s index 7e900ec696c..f14294d48c2 100644 --- a/llvm/test/MC/Mips/mips-expansions.s +++ b/llvm/test/MC/Mips/mips-expansions.s @@ -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) diff --git a/llvm/test/MC/Mips/mips32r5/invalid.s b/llvm/test/MC/Mips/mips32r5/invalid.s index d0161673795..70d3d1097a2 100644 --- a/llvm/test/MC/Mips/mips32r5/invalid.s +++ b/llvm/test/MC/Mips/mips32r5/invalid.s @@ -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 diff --git a/llvm/test/MC/Mips/mips32r6/invalid.s b/llvm/test/MC/Mips/mips32r6/invalid.s index 2baa8ba3799..89bc8ac8e89 100644 --- a/llvm/test/MC/Mips/mips32r6/invalid.s +++ b/llvm/test/MC/Mips/mips32r6/invalid.s @@ -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 diff --git a/llvm/test/MC/Mips/mips64r5/invalid.s b/llvm/test/MC/Mips/mips64r5/invalid.s index 531ce91680e..ee2c41752d7 100644 --- a/llvm/test/MC/Mips/mips64r5/invalid.s +++ b/llvm/test/MC/Mips/mips64r5/invalid.s @@ -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 diff --git a/llvm/test/MC/Mips/mips64r6/invalid.s b/llvm/test/MC/Mips/mips64r6/invalid.s index 57564200664..d4ea1bfae66 100644 --- a/llvm/test/MC/Mips/mips64r6/invalid.s +++ b/llvm/test/MC/Mips/mips64r6/invalid.s @@ -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 |

