diff options
author | Ulrich Weigand <ulrich.weigand@de.ibm.com> | 2013-06-26 13:49:53 +0000 |
---|---|---|
committer | Ulrich Weigand <ulrich.weigand@de.ibm.com> | 2013-06-26 13:49:53 +0000 |
commit | 8950dd127ad4cccd9dadf616b5057cf130f24ade (patch) | |
tree | 8acf2ee447b8829ec3edf9a2c4cc013acf1a2895 /lib/Target | |
parent | 0b8594268feb1c804370541c7853e658caee0ae5 (diff) | |
download | external_llvm-8950dd127ad4cccd9dadf616b5057cf130f24ade.zip external_llvm-8950dd127ad4cccd9dadf616b5057cf130f24ade.tar.gz external_llvm-8950dd127ad4cccd9dadf616b5057cf130f24ade.tar.bz2 |
[PowerPC] Accept 17-bit signed immediates for addis
The assembler currently strictly verifies that immediates for
s16imm operands are in range (-32768 ... 32767). This matches
the behaviour of the GNU assembler, with one exception: gas
allows, as a special case, operands in an extended range
(-65536 .. 65535) for the addis instruction only (and its
extended mnemonic lis).
The main reason for this seems to be to allow using unsigned
16-bit operands for lis, e.g. like lis %r1, 0xfedc.
Since this has been supported by gas for a long time, and
assembler source code seen "in the wild" actually exploits
this feature, this patch adds equivalent support to LLVM
for compatibility reasons.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@184946 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target')
-rw-r--r-- | lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp | 2 | ||||
-rw-r--r-- | lib/Target/PowerPC/PPCInstr64Bit.td | 12 | ||||
-rw-r--r-- | lib/Target/PowerPC/PPCInstrInfo.td | 16 |
3 files changed, 26 insertions, 4 deletions
diff --git a/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp b/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp index 2310bb3..cbe1321 100644 --- a/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp +++ b/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp @@ -267,6 +267,8 @@ public: bool isS16ImmX4() const { return Kind == Expression || (Kind == Immediate && isInt<16>(getImm()) && (getImm() & 3) == 0); } + bool isS17Imm() const { return Kind == Expression || + (Kind == Immediate && isInt<17>(getImm())); } bool isDirectBr() const { return Kind == Expression || (Kind == Immediate && isInt<26>(getImm()) && (getImm() & 3) == 0); } diff --git a/lib/Target/PowerPC/PPCInstr64Bit.td b/lib/Target/PowerPC/PPCInstr64Bit.td index f63ca24..b0386c3 100644 --- a/lib/Target/PowerPC/PPCInstr64Bit.td +++ b/lib/Target/PowerPC/PPCInstr64Bit.td @@ -25,6 +25,14 @@ def u16imm64 : Operand<i64> { let EncoderMethod = "getImm16Encoding"; let ParserMatchClass = PPCU16ImmAsmOperand; } +def s17imm64 : Operand<i64> { + // This operand type is used for addis/lis to allow the assembler parser + // to accept immediates in the range -65536..65535 for compatibility with + // the GNU assembler. The operand is treated as 16-bit otherwise. + let PrintMethod = "printS16ImmOperand"; + let EncoderMethod = "getImm16Encoding"; + let ParserMatchClass = PPCS17ImmAsmOperand; +} def tocentry : Operand<iPTR> { let MIOperandInfo = (ops i64imm:$imm); } @@ -330,7 +338,7 @@ let isReMaterializable = 1, isAsCheapAsAMove = 1, isMoveImm = 1 in { def LI8 : DForm_2_r0<14, (outs g8rc:$rD), (ins s16imm64:$imm), "li $rD, $imm", IntSimple, [(set i64:$rD, imm64SExt16:$imm)]>; -def LIS8 : DForm_2_r0<15, (outs g8rc:$rD), (ins s16imm64:$imm), +def LIS8 : DForm_2_r0<15, (outs g8rc:$rD), (ins s17imm64:$imm), "lis $rD, $imm", IntSimple, [(set i64:$rD, imm16ShiftedSExt:$imm)]>; } @@ -406,7 +414,7 @@ def ADDIC8 : DForm_2<12, (outs g8rc:$rD), (ins g8rc:$rA, s16imm64:$imm), def ADDI8 : DForm_2<14, (outs g8rc:$rD), (ins g8rc_nox0:$rA, s16imm64:$imm), "addi $rD, $rA, $imm", IntSimple, [(set i64:$rD, (add i64:$rA, imm64SExt16:$imm))]>; -def ADDIS8 : DForm_2<15, (outs g8rc:$rD), (ins g8rc_nox0:$rA, s16imm64:$imm), +def ADDIS8 : DForm_2<15, (outs g8rc:$rD), (ins g8rc_nox0:$rA, s17imm64:$imm), "addis $rD, $rA, $imm", IntSimple, [(set i64:$rD, (add i64:$rA, imm16ShiftedSExt:$imm))]>; diff --git a/lib/Target/PowerPC/PPCInstrInfo.td b/lib/Target/PowerPC/PPCInstrInfo.td index a970696..28396fd 100644 --- a/lib/Target/PowerPC/PPCInstrInfo.td +++ b/lib/Target/PowerPC/PPCInstrInfo.td @@ -446,6 +446,18 @@ def u16imm : Operand<i32> { let EncoderMethod = "getImm16Encoding"; let ParserMatchClass = PPCU16ImmAsmOperand; } +def PPCS17ImmAsmOperand : AsmOperandClass { + let Name = "S17Imm"; let PredicateMethod = "isS17Imm"; + let RenderMethod = "addImmOperands"; +} +def s17imm : Operand<i32> { + // This operand type is used for addis/lis to allow the assembler parser + // to accept immediates in the range -65536..65535 for compatibility with + // the GNU assembler. The operand is treated as 16-bit otherwise. + let PrintMethod = "printS16ImmOperand"; + let EncoderMethod = "getImm16Encoding"; + let ParserMatchClass = PPCS17ImmAsmOperand; +} def PPCDirectBrAsmOperand : AsmOperandClass { let Name = "DirectBr"; let PredicateMethod = "isDirectBr"; let RenderMethod = "addBranchTargetOperands"; @@ -1519,7 +1531,7 @@ def ADDICo : DForm_2<13, (outs gprc:$rD), (ins gprc:$rA, s16imm:$imm), "addic. $rD, $rA, $imm", IntGeneral, []>, isDOT, RecFormRel; } -def ADDIS : DForm_2<15, (outs gprc:$rD), (ins gprc_nor0:$rA, s16imm:$imm), +def ADDIS : DForm_2<15, (outs gprc:$rD), (ins gprc_nor0:$rA, s17imm:$imm), "addis $rD, $rA, $imm", IntSimple, [(set i32:$rD, (add i32:$rA, imm16ShiftedSExt:$imm))]>; let isCodeGenOnly = 1 in @@ -1539,7 +1551,7 @@ let isReMaterializable = 1, isAsCheapAsAMove = 1, isMoveImm = 1 in { def LI : DForm_2_r0<14, (outs gprc:$rD), (ins s16imm:$imm), "li $rD, $imm", IntSimple, [(set i32:$rD, imm32SExt16:$imm)]>; - def LIS : DForm_2_r0<15, (outs gprc:$rD), (ins s16imm:$imm), + def LIS : DForm_2_r0<15, (outs gprc:$rD), (ins s17imm:$imm), "lis $rD, $imm", IntSimple, [(set i32:$rD, imm16ShiftedSExt:$imm)]>; } |