From 6b8f1e35eacba34a11e2a7d5f614efc47b43d2e3 Mon Sep 17 00:00:00 2001 From: Jim Grosbach Date: Mon, 27 Jun 2011 23:54:06 +0000 Subject: [PATCH] ARM Assembly support for Thumb mov-immediate. Correctly parse the forms of the Thumb mov-immediate instruction: 1. 8-bit immediate 0-255. 2. 12-bit shifted-immediate. The 16-bit immediate "movw" form is also legal with just a "mov" mnemonic, but is not yet supported. More parser logic necessary there due to fixups. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133966 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/ARM/ARMInstrThumb.td | 9 ++++---- lib/Target/ARM/ARMInstrThumb2.td | 9 ++++++++ lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 26 +++++++++++++++++++++++ test/MC/ARM/thumb2.s | 16 ++++++++++++++ utils/TableGen/EDEmitter.cpp | 1 + 5 files changed, 57 insertions(+), 4 deletions(-) diff --git a/lib/Target/ARM/ARMInstrThumb.td b/lib/Target/ARM/ARMInstrThumb.td index 44fbc021d86..328d330800b 100644 --- a/lib/Target/ARM/ARMInstrThumb.td +++ b/lib/Target/ARM/ARMInstrThumb.td @@ -34,9 +34,10 @@ def imm0_7_neg : PatLeaf<(i32 imm), [{ return (uint32_t)-N->getZExtValue() < 8; }], imm_neg_XFORM>; -def imm0_255 : ImmLeaf= 0 && Imm < 256; -}]>; +def imm0_255_asmoperand : AsmOperandClass { let Name = "Imm0_255"; } +def imm0_255 : Operand, ImmLeaf= 0 && Imm < 256; }]> { + let ParserMatchClass = imm0_255_asmoperand; +} def imm0_255_comp : PatLeaf<(i32 imm), [{ return ~((uint32_t)N->getZExtValue()) < 256; }]>; @@ -1072,7 +1073,7 @@ def tLSRrr : // A8.6.91 // Move register let isMoveImm = 1 in -def tMOVi8 : T1sI<(outs tGPR:$Rd), (ins i32imm:$imm8), IIC_iMOVi, +def tMOVi8 : T1sI<(outs tGPR:$Rd), (ins imm0_255:$imm8), IIC_iMOVi, "mov", "\t$Rd, $imm8", [(set tGPR:$Rd, imm0_255:$imm8)]>, T1General<{1,0,0,?,?}> { diff --git a/lib/Target/ARM/ARMInstrThumb2.td b/lib/Target/ARM/ARMInstrThumb2.td index 090670b8986..f36a49e9434 100644 --- a/lib/Target/ARM/ARMInstrThumb2.td +++ b/lib/Target/ARM/ARMInstrThumb2.td @@ -44,9 +44,11 @@ def t2_so_imm_neg_XFORM : SDNodeXForm, ImmLeaf { + let ParserMatchClass = t2_so_imm_asmoperand; let EncoderMethod = "getT2SOImmOpValue"; } @@ -1645,6 +1647,10 @@ def t2MOVi : T2sOneRegImm<(outs rGPR:$Rd), (ins t2_so_imm:$imm), IIC_iMOVi, let Inst{15} = 0; } +def : InstAlias<"mov${s}${p} $Rd, $imm", (t2MOVi rGPR:$Rd, t2_so_imm:$imm, + pred:$p, cc_out:$s)>, + Requires<[IsThumb2]>; + let isReMaterializable = 1, isAsCheapAsAMove = 1, isMoveImm = 1 in def t2MOVi16 : T2I<(outs rGPR:$Rd), (ins i32imm_hilo16:$imm), IIC_iMOVi, "movw", "\t$Rd, $imm", @@ -2709,6 +2715,8 @@ def t2MOVCCr : T2TwoReg< let Inst{7-4} = 0b0000; } +// FIXME: Pseudo-ize these. For now, just mark codegen only. +let isCodeGenOnly = 1 in { let isMoveImm = 1 in def t2MOVCCi : T2OneRegImm<(outs rGPR:$Rd), (ins rGPR:$false, t2_so_imm:$imm), IIC_iCMOVi, "mov", ".w\t$Rd, $imm", @@ -2789,6 +2797,7 @@ def t2MOVCCror : T2I_movcc_sh<0b11, (outs rGPR:$Rd), IIC_iCMOVsi, "ror", ".w\t$Rd, $Rm, $imm", []>, RegConstraint<"$false = $Rd">; } // neverHasSideEffects +} // isCodeGenOnly = 1 //===----------------------------------------------------------------------===// // Atomic operations intrinsics diff --git a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 8fe504fb2bb..178fe5229db 100644 --- a/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -350,6 +350,22 @@ public: bool isCondCode() const { return Kind == CondCode; } bool isCCOut() const { return Kind == CCOut; } bool isImm() const { return Kind == Immediate; } + bool isImm0_255() const { + if (Kind != Immediate) + return false; + const MCConstantExpr *CE = dyn_cast(getImm()); + if (!CE) return false; + int64_t Value = CE->getValue(); + return Value >= 0 && Value < 256; + } + bool isT2SOImm() const { + if (Kind != Immediate) + return false; + const MCConstantExpr *CE = dyn_cast(getImm()); + if (!CE) return false; + int64_t Value = CE->getValue(); + return ARM_AM::getT2SOImmVal(Value) != -1; + } bool isReg() const { return Kind == Register; } bool isRegList() const { return Kind == RegisterList; } bool isDPRRegList() const { return Kind == DPRRegisterList; } @@ -515,6 +531,16 @@ public: addExpr(Inst, getImm()); } + void addImm0_255Operands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + addExpr(Inst, getImm()); + } + + void addT2SOImmOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + addExpr(Inst, getImm()); + } + void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt()))); diff --git a/test/MC/ARM/thumb2.s b/test/MC/ARM/thumb2.s index 4e9d4e18597..1a268a970c5 100644 --- a/test/MC/ARM/thumb2.s +++ b/test/MC/ARM/thumb2.s @@ -49,6 +49,22 @@ @ CHECK: mov.w r0, #66846720 @ encoding: [0x7f,0x70,0x4f,0xf0] mov.w r0, #66846720 +@ Aliases w/ the vanilla 'mov' mnemonic, and explicit alternative selection. + mov r2, #0xbf000000 + mov r1, #0x100 + mov r3, #32 + mov.w r3, #32 + movw r3, #32 + +@ CHECK: mov.w r2, #3204448256 @ encoding: [0x4f,0xf0,0x3f,0x42] +@ CHECK: mov.w r1, #256 @ encoding: [0x4f,0xf4,0x80,0x71] +@ CHECK: mov r3, #32 @ encoding: [0x20,0x23] +@ CHECK: mov.w r3, #32 @ encoding: [0x4f,0xf0,0x20,0x03] +@ CHECK: movw r3, #32 @ encoding: [0x40,0xf2,0x20,0x03] + + + + @ CHECK: rrx r0, r0 @ encoding: [0x30,0x00,0x4f,0xea] rrx r0, r0 diff --git a/utils/TableGen/EDEmitter.cpp b/utils/TableGen/EDEmitter.cpp index daf96175545..4c0d385670d 100644 --- a/utils/TableGen/EDEmitter.cpp +++ b/utils/TableGen/EDEmitter.cpp @@ -588,6 +588,7 @@ static int ARMFlagFromOpName(LiteralConstantEmitter *type, IMM("imm0_31"); IMM("imm0_31_m1"); IMM("nModImm"); + IMM("imm0_255"); IMM("imm0_4095"); IMM("jt2block_operand"); IMM("t_imm_s4"); -- 2.34.1