Restructure ARM code emitter to use instruction formats instead of addressing modes to determine how to encode instructions.

llvm-svn: 58764
This commit is contained in:
Evan Cheng 2008-11-05 18:35:52 +00:00
parent ce2417f4e1
commit 81889d010c
5 changed files with 297 additions and 280 deletions

View File

@ -102,12 +102,14 @@ def ARMInstrInfo : InstrInfo {
"SizeFlag",
"IndexModeBits",
"Opcode",
"isUnaryDataProc",
"Form"];
let TSFlagsShifts = [0,
4,
7,
9,
13];
13,
14];
}
//===----------------------------------------------------------------------===//

View File

@ -69,10 +69,6 @@ namespace {
void emitPseudoInstruction(const MachineInstr &MI);
unsigned getAddrModeNoneInstrBinary(const MachineInstr &MI,
const TargetInstrDesc &TID,
unsigned Binary);
unsigned getMachineSoRegOpValue(const MachineInstr &MI,
const TargetInstrDesc &TID,
const MachineOperand &MO,
@ -85,25 +81,19 @@ namespace {
unsigned getAddrModeSBit(const MachineInstr &MI,
const TargetInstrDesc &TID) const;
unsigned getAddrMode1InstrBinary(const MachineInstr &MI,
const TargetInstrDesc &TID,
unsigned Binary);
unsigned getAddrMode2InstrBinary(const MachineInstr &MI,
const TargetInstrDesc &TID,
unsigned Binary);
unsigned getAddrMode3InstrBinary(const MachineInstr &MI,
const TargetInstrDesc &TID,
unsigned Binary);
unsigned getAddrMode4InstrBinary(const MachineInstr &MI,
const TargetInstrDesc &TID,
unsigned Binary);
unsigned getAddrMode6InstrBinary(const MachineInstr &MI,
const TargetInstrDesc &TID,
unsigned Binary);
void emitDataProcessingInstruction(const MachineInstr &MI);
/// getInstrBinary - Return binary encoding for the specified
/// machine instruction.
unsigned getInstrBinary(const MachineInstr &MI);
void emitLoadStoreInstruction(const MachineInstr &MI);
void emitMiscLoadStoreInstruction(const MachineInstr &MI);
void emitLoadStoreMultipleInstruction(const MachineInstr &MI);
void emitMulFrm1Instruction(const MachineInstr &MI);
void emitBranchInstruction(const MachineInstr &MI);
void emitMiscBranchInstruction(const MachineInstr &MI);
/// getBinaryCodeForInstr - This function, generated by the
/// CodeEmitterGenerator using TableGen, produces the binary encoding for
@ -260,10 +250,39 @@ void ARMCodeEmitter::emitInstruction(const MachineInstr &MI) {
DOUT << "JIT: " << (void*)MCE.getCurrentPCValue() << ":\t" << MI;
NumEmitted++; // Keep track of the # of mi's emitted
if ((MI.getDesc().TSFlags & ARMII::FormMask) == ARMII::Pseudo)
switch (MI.getDesc().TSFlags & ARMII::FormMask) {
default:
assert(0 && "Unhandled instruction encoding format!");
break;
case ARMII::Pseudo:
emitPseudoInstruction(MI);
else
MCE.emitWordLE(getInstrBinary(MI));
break;
case ARMII::DPFrm:
case ARMII::DPSoRegFrm:
emitDataProcessingInstruction(MI);
break;
case ARMII::LdFrm:
case ARMII::StFrm:
emitLoadStoreInstruction(MI);
break;
case ARMII::LdMiscFrm:
case ARMII::StMiscFrm:
emitMiscLoadStoreInstruction(MI);
break;
case ARMII::LdMulFrm:
case ARMII::StMulFrm:
emitLoadStoreMultipleInstruction(MI);
break;
case ARMII::MulFrm1:
emitMulFrm1Instruction(MI);
break;
case ARMII::Branch:
emitBranchInstruction(MI);
break;
case ARMII::BranchMisc:
emitMiscBranchInstruction(MI);
break;
}
}
void ARMCodeEmitter::emitConstPoolInstruction(const MachineInstr &MI) {
@ -329,51 +348,13 @@ void ARMCodeEmitter::emitPseudoInstruction(const MachineInstr &MI) {
JTI->addPCLabelAddr(MO2.getImm(), MCE.getCurrentPCValue());
// PICADD is just an add instruction that implicitly read pc.
unsigned Binary = getBinaryCodeForInstr(MI);
const TargetInstrDesc &TID = MI.getDesc();
MCE.emitWordLE(getAddrMode1InstrBinary(MI, TID, Binary));
emitDataProcessingInstruction(MI);
break;
}
}
}
unsigned ARMCodeEmitter::getAddrModeNoneInstrBinary(const MachineInstr &MI,
const TargetInstrDesc &TID,
unsigned Binary) {
// Set the conditional execution predicate
Binary |= II->getPredicate(&MI) << 28;
switch (TID.TSFlags & ARMII::FormMask) {
default:
assert(0 && "Unknown instruction subtype!");
break;
case ARMII::Branch: {
// Set signed_immed_24 field
Binary |= getMachineOpValue(MI, 0);
// if it is a conditional branch, set cond field
if (TID.Opcode == ARM::Bcc) {
Binary &= 0x0FFFFFFF; // clear conditional field
Binary |= getMachineOpValue(MI, 1) << 28; // set conditional field
}
break;
}
case ARMII::BranchMisc: {
if (TID.Opcode == ARM::BX)
abort(); // FIXME
if (TID.Opcode == ARM::BX_RET)
Binary |= 0xe; // the return register is LR
else
// otherwise, set the return register
Binary |= getMachineOpValue(MI, 0);
break;
}
}
return Binary;
}
unsigned ARMCodeEmitter::getMachineSoRegOpValue(const MachineInstr &MI,
const TargetInstrDesc &TID,
const MachineOperand &MO,
@ -453,9 +434,14 @@ unsigned ARMCodeEmitter::getAddrModeSBit(const MachineInstr &MI,
return 0;
}
unsigned ARMCodeEmitter::getAddrMode1InstrBinary(const MachineInstr &MI,
const TargetInstrDesc &TID,
unsigned Binary) {
void ARMCodeEmitter::emitDataProcessingInstruction(const MachineInstr &MI) {
const TargetInstrDesc &TID = MI.getDesc();
if (TID.getOpcode() == ARM::MOVi2pieces)
abort(); // FIXME
// Part of binary is determined by TableGn.
unsigned Binary = getBinaryCodeForInstr(MI);
// Set the conditional execution predicate
Binary |= II->getPredicate(&MI) << 28;
@ -471,16 +457,12 @@ unsigned ARMCodeEmitter::getAddrMode1InstrBinary(const MachineInstr &MI,
}
// Encode first non-shifter register operand if there is one.
unsigned Format = TID.TSFlags & ARMII::FormMask;
bool HasRnReg = !(Format == ARMII::DPRdMisc ||
Format == ARMII::DPRdIm ||
Format == ARMII::DPRdReg ||
Format == ARMII::DPRdSoReg);
if (HasRnReg) {
bool isUnary = TID.TSFlags & ARMII::UnaryDP;
if (!isUnary) {
if (TID.getOpcode() == ARM::PICADD)
// Special handling for PICADD. It implicitly use add.
Binary |=
ARMRegisterInfo::getRegisterNumbering(ARM::PC) << ARMII::RegRnShift;
// Special handling for PICADD. It implicitly uses PC register.
Binary |= (ARMRegisterInfo::getRegisterNumbering(ARM::PC)
<< ARMII::RegRnShift);
else {
Binary |= getMachineOpValue(MI, OpIdx) << ARMII::RegRnShift;
++OpIdx;
@ -488,30 +470,33 @@ unsigned ARMCodeEmitter::getAddrMode1InstrBinary(const MachineInstr &MI,
}
// Encode shifter operand.
bool HasSoReg = (Format == ARMII::DPRdSoReg ||
Format == ARMII::DPRnSoReg ||
Format == ARMII::DPRSoReg ||
Format == ARMII::DPRSoRegS);
const MachineOperand &MO = MI.getOperand(OpIdx);
if (HasSoReg)
if ((TID.TSFlags & ARMII::FormMask) == ARMII::DPSoRegFrm) {
// Encode SoReg.
return Binary | getMachineSoRegOpValue(MI, TID, MO, OpIdx);
MCE.emitWordLE(Binary | getMachineSoRegOpValue(MI, TID, MO, OpIdx));
return;
}
if (MO.isReg())
if (MO.isReg()) {
// Encode register Rm.
return Binary | ARMRegisterInfo::getRegisterNumbering(MO.getReg());
MCE.emitWordLE(Binary | ARMRegisterInfo::getRegisterNumbering(MO.getReg()));
return;
}
// Encode so_imm.
// Set bit I(25) to identify this is the immediate form of <shifter_op>
Binary |= 1 << ARMII::I_BitShift;
Binary |= getMachineSoImmOpValue(MI, TID, MO);
return Binary;
MCE.emitWordLE(Binary);
}
unsigned ARMCodeEmitter::getAddrMode2InstrBinary(const MachineInstr &MI,
const TargetInstrDesc &TID,
unsigned Binary) {
void ARMCodeEmitter::emitLoadStoreInstruction(const MachineInstr &MI) {
const TargetInstrDesc &TID = MI.getDesc();
// Part of binary is determined by TableGn.
unsigned Binary = getBinaryCodeForInstr(MI);
// Set the conditional execution predicate
Binary |= II->getPredicate(&MI) << 28;
@ -531,7 +516,8 @@ unsigned ARMCodeEmitter::getAddrMode2InstrBinary(const MachineInstr &MI,
if (ARM_AM::getAM2Offset(MO3.getImm()))
// Set the value of offset_12 field
Binary |= ARM_AM::getAM2Offset(MO3.getImm());
return Binary;
MCE.emitWordLE(Binary);
return;
}
// Set bit I(25), because this is not in immediate enconding.
@ -547,12 +533,15 @@ unsigned ARMCodeEmitter::getAddrMode2InstrBinary(const MachineInstr &MI,
Binary |= ShImm << 7; // shift_immed
}
return Binary;
MCE.emitWordLE(Binary);
}
unsigned ARMCodeEmitter::getAddrMode3InstrBinary(const MachineInstr &MI,
const TargetInstrDesc &TID,
unsigned Binary) {
void ARMCodeEmitter::emitMiscLoadStoreInstruction(const MachineInstr &MI) {
const TargetInstrDesc &TID = MI.getDesc();
// Part of binary is determined by TableGn.
unsigned Binary = getBinaryCodeForInstr(MI);
// Set the conditional execution predicate
Binary |= II->getPredicate(&MI) << 28;
@ -573,7 +562,8 @@ unsigned ARMCodeEmitter::getAddrMode3InstrBinary(const MachineInstr &MI,
// to the corresponding Rm register.
if (MO2.getReg()) {
Binary |= ARMRegisterInfo::getRegisterNumbering(MO2.getReg());
return Binary;
MCE.emitWordLE(Binary);
return;
}
// if this instr is in immediate offset/index encoding, set bit 22 to 1
@ -584,12 +574,15 @@ unsigned ARMCodeEmitter::getAddrMode3InstrBinary(const MachineInstr &MI,
Binary |= (ImmOffs & ~0xF); // immedL
}
return Binary;
MCE.emitWordLE(Binary);
}
unsigned ARMCodeEmitter::getAddrMode4InstrBinary(const MachineInstr &MI,
const TargetInstrDesc &TID,
unsigned Binary) {
void ARMCodeEmitter::emitLoadStoreMultipleInstruction(const MachineInstr &MI) {
const TargetInstrDesc &TID = MI.getDesc();
// Part of binary is determined by TableGn.
unsigned Binary = getBinaryCodeForInstr(MI);
// Set the conditional execution predicate
Binary |= II->getPredicate(&MI) << 28;
@ -626,12 +619,15 @@ unsigned ARMCodeEmitter::getAddrMode4InstrBinary(const MachineInstr &MI,
Binary |= 0x1 << RegNum;
}
return Binary;
MCE.emitWordLE(Binary);
}
unsigned ARMCodeEmitter::getAddrMode6InstrBinary(const MachineInstr &MI,
const TargetInstrDesc &TID,
unsigned Binary) {
void ARMCodeEmitter::emitMulFrm1Instruction(const MachineInstr &MI) {
const TargetInstrDesc &TID = MI.getDesc();
// Part of binary is determined by TableGn.
unsigned Binary = getBinaryCodeForInstr(MI);
// Set the conditional execution predicate
Binary |= II->getPredicate(&MI) << 28;
@ -653,33 +649,49 @@ unsigned ARMCodeEmitter::getAddrMode6InstrBinary(const MachineInstr &MI,
// Encode Rs
Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRsShift;
return Binary;
MCE.emitWordLE(Binary);
}
/// getInstrBinary - Return binary encoding for the specified
/// machine instruction.
unsigned ARMCodeEmitter::getInstrBinary(const MachineInstr &MI) {
void ARMCodeEmitter::emitBranchInstruction(const MachineInstr &MI) {
const TargetInstrDesc &TID = MI.getDesc();
// Part of binary is determined by TableGn.
unsigned Binary = getBinaryCodeForInstr(MI);
const TargetInstrDesc &TID = MI.getDesc();
switch (TID.TSFlags & ARMII::AddrModeMask) {
case ARMII::AddrModeNone:
return getAddrModeNoneInstrBinary(MI, TID, Binary);
case ARMII::AddrMode1:
return getAddrMode1InstrBinary(MI, TID, Binary);
case ARMII::AddrMode2:
return getAddrMode2InstrBinary(MI, TID, Binary);
case ARMII::AddrMode3:
return getAddrMode3InstrBinary(MI, TID, Binary);
case ARMII::AddrMode4:
return getAddrMode4InstrBinary(MI, TID, Binary);
case ARMII::AddrMode6:
return getAddrMode6InstrBinary(MI, TID, Binary);
// Set the conditional execution predicate
Binary |= II->getPredicate(&MI) << 28;
// Set signed_immed_24 field
Binary |= getMachineOpValue(MI, 0);
// if it is a conditional branch, set cond field
if (TID.Opcode == ARM::Bcc) {
Binary &= 0x0FFFFFFF; // clear conditional field
Binary |= getMachineOpValue(MI, 1) << 28; // set conditional field
}
abort();
return 0;
MCE.emitWordLE(Binary);
}
void ARMCodeEmitter::emitMiscBranchInstruction(const MachineInstr &MI) {
const TargetInstrDesc &TID = MI.getDesc();
if (TID.Opcode == ARM::BX)
abort(); // FIXME
// Part of binary is determined by TableGn.
unsigned Binary = getBinaryCodeForInstr(MI);
// Set the conditional execution predicate
Binary |= II->getPredicate(&MI) << 28;
if (TID.Opcode == ARM::BX_RET)
// The return register is LR.
Binary |= ARMRegisterInfo::getRegisterNumbering(ARM::LR);
else
// otherwise, set the return register
Binary |= getMachineOpValue(MI, 0);
MCE.emitWordLE(Binary);
}
#include "ARMGenCodeEmitter.inc"

View File

@ -20,35 +20,32 @@ class Format<bits<5> val> {
}
def Pseudo : Format<1>;
def MulFrm : Format<2>;
def MulSMLAW : Format<3>;
def MulSMULW : Format<4>;
def MulSMLA : Format<5>;
def MulSMUL : Format<6>;
def Branch : Format<7>;
def BranchMisc : Format<8>;
def MulFrm1 : Format<2>;
def MulFrm2 : Format<3>;
def MulSMLAW : Format<4>;
def MulSMULW : Format<5>;
def MulSMLA : Format<6>;
def MulSMUL : Format<7>;
def Branch : Format<8>;
def BranchMisc : Format<9>;
def DPRdIm : Format<9>;
def DPRdReg : Format<10>;
def DPRdSoReg : Format<11>;
def DPRdMisc : Format<12>;
def DPRnIm : Format<13>;
def DPRnReg : Format<14>;
def DPRnSoReg : Format<15>;
def DPRIm : Format<16>;
def DPRReg : Format<17>;
def DPRSoReg : Format<18>;
def DPRImS : Format<19>;
def DPRRegS : Format<20>;
def DPRSoRegS : Format<21>;
def DPFrm : Format<10>;
def DPSoRegFrm : Format<11>;
def LdFrm : Format<22>;
def StFrm : Format<23>;
def LdFrm : Format<12>;
def StFrm : Format<13>;
def LdMiscFrm : Format<14>;
def StMiscFrm : Format<15>;
def LdMulFrm : Format<16>;
def StMulFrm : Format<17>;
def ArithMisc : Format<24>;
def ThumbFrm : Format<25>;
def VFPFrm : Format<26>;
def ArithMisc : Format<18>;
def ThumbFrm : Format<19>;
def VFPFrm : Format<20>;
// Misc flag for data processing instructions that indicates whether
// the instruction has a Rn register operand.
class UnaryDP { bit isUnaryDataProc = 1; }
//===----------------------------------------------------------------------===//
@ -63,6 +60,8 @@ class InstARM<bits<4> opcod, AddrMode am, SizeFlagVal sz, IndexMode im,
let Namespace = "ARM";
bits<4> Opcode = opcod;
// TSFlagsFields
AddrMode AM = am;
bits<4> AddrModeBits = AM.Value;
@ -75,6 +74,11 @@ class InstARM<bits<4> opcod, AddrMode am, SizeFlagVal sz, IndexMode im,
Format F = f;
bits<5> Form = F.Value;
//
// Attributes specific to ARM instructions...
//
bit isUnaryDataProc = 0;
let Constraints = cstr;
}
@ -658,23 +662,20 @@ class AXI4st<bits<4> opcod, dag oops, dag iops, Format f, string asm,
let Inst{27-25} = 0b100;
}
// addrmode6
// Unsigned multiply, multiply-accumulate instructions.
class AI6<bits<4> opcod, dag oops, dag iops, Format f, string opc,
class AMul1I<bits<4> opcod, dag oops, dag iops, string opc,
string asm, list<dag> pattern>
: I<opcod, oops, iops, AddrMode6, Size4Bytes, IndexModeNone, f, opc,
asm,"",pattern>
{
: I<opcod, oops, iops, AddrModeNone, Size4Bytes, IndexModeNone, MulFrm1, opc,
asm,"",pattern> {
// FIXME: bits 7-4 should be a sub-mode (for SMLAxx, SMLAWy, ...)
let Inst{7-4} = 0b1001;
let Inst{27-24} = 0b0000;
let Inst{23-20} = opcod;
}
class AsI6<bits<4> opcod, dag oops, dag iops, Format f, string opc,
class AsMul1I<bits<4> opcod, dag oops, dag iops, string opc,
string asm, list<dag> pattern>
: sI<opcod, oops, iops, AddrMode6, Size4Bytes, IndexModeNone, f, opc,
asm,"",pattern>
{
: sI<opcod, oops, iops, AddrModeNone, Size4Bytes, IndexModeNone, MulFrm1, opc,
asm,"",pattern> {
// FIXME: bits 7-4 should be a sub-mode (for SMLAxx, SMLAWy, ...)
let Inst{7-4} = 0b1001;
let Inst{27-24} = 0b0000;

View File

@ -39,11 +39,10 @@ namespace ARMII {
AddrMode3 = 3,
AddrMode4 = 4,
AddrMode5 = 5,
AddrMode6 = 6,
AddrModeT1 = 7,
AddrModeT2 = 8,
AddrModeT4 = 9,
AddrModeTs = 10, // i8 * 4 for pc and sp relative data
AddrModeT1 = 6,
AddrModeT2 = 7,
AddrModeT4 = 8,
AddrModeTs = 9, // i8 * 4 for pc and sp relative data
// Size* - Flags to keep track of the size of an instruction.
SizeShift = 4,
@ -64,55 +63,56 @@ namespace ARMII {
OpcodeShift = 9,
OpcodeMask = 0xf << OpcodeShift,
// Format
FormShift = 13,
FormMask = 31 << FormShift,
//===------------------------------------------------------------------===//
// Misc flags.
// UnaryDP - Indicates this is a unary data processing instruction, i.e.
// it doesn't have a Rn operand.
UnaryDP = 1 << 13,
//===------------------------------------------------------------------===//
// Instruction encoding formats.
//
FormShift = 14,
FormMask = 0x1f << FormShift,
// Pseudo instructions
Pseudo = 1 << FormShift,
// Multiply instructions
MulFrm = 2 << FormShift,
MulSMLAW = 3 << FormShift,
MulSMULW = 4 << FormShift,
MulSMLA = 5 << FormShift,
MulSMUL = 6 << FormShift,
MulFrm1 = 2 << FormShift,
MulFrm2 = 3 << FormShift,
MulSMLAW = 4 << FormShift,
MulSMULW = 5 << FormShift,
MulSMLA = 6 << FormShift,
MulSMUL = 7 << FormShift,
// Branch instructions
Branch = 7 << FormShift,
BranchMisc = 8 << FormShift,
Branch = 8 << FormShift,
BranchMisc = 9 << FormShift,
// Data Processing instructions
DPRdIm = 9 << FormShift,
DPRdReg = 10 << FormShift,
DPRdSoReg = 11 << FormShift,
DPRdMisc = 12 << FormShift,
DPRnIm = 13 << FormShift,
DPRnReg = 14 << FormShift,
DPRnSoReg = 15 << FormShift,
DPRIm = 16 << FormShift,
DPRReg = 17 << FormShift,
DPRSoReg = 18 << FormShift,
DPRImS = 19 << FormShift,
DPRRegS = 20 << FormShift,
DPRSoRegS = 21 << FormShift,
DPFrm = 10 << FormShift,
DPSoRegFrm = 11 << FormShift,
// Load and Store
LdFrm = 22 << FormShift,
StFrm = 23 << FormShift,
LdFrm = 12 << FormShift,
StFrm = 13 << FormShift,
LdMiscFrm = 14 << FormShift,
StMiscFrm = 15 << FormShift,
LdMulFrm = 16 << FormShift,
StMulFrm = 17 << FormShift,
// Miscellaneous arithmetic instructions
ArithMisc = 24 << FormShift,
ArithMisc = 18 << FormShift,
// Thumb format
ThumbFrm = 25 << FormShift,
ThumbFrm = 19 << FormShift,
// VFP format
VPFFrm = 26 << FormShift,
VPFFrm = 20 << FormShift,
//===------------------------------------------------------------------===//
// Field shifts - such shifts are used to set field while generating
// machine instructions.
RotImmShift = 8,

View File

@ -310,11 +310,10 @@ def AddrMode2 : AddrMode<2>;
def AddrMode3 : AddrMode<3>;
def AddrMode4 : AddrMode<4>;
def AddrMode5 : AddrMode<5>;
def AddrMode6 : AddrMode<6>;
def AddrModeT1 : AddrMode<7>;
def AddrModeT2 : AddrMode<8>;
def AddrModeT4 : AddrMode<9>;
def AddrModeTs : AddrMode<10>;
def AddrModeT1 : AddrMode<6>;
def AddrModeT2 : AddrMode<7>;
def AddrModeT4 : AddrMode<8>;
def AddrModeTs : AddrMode<9>;
// Instruction size.
class SizeFlagVal<bits<3> val> {
@ -345,13 +344,13 @@ include "ARMInstrFormats.td"
/// AsI1_bin_irs - Defines a set of (op r, {so_imm|r|so_reg}) patterns for a
/// binop that produces a value.
multiclass AsI1_bin_irs<bits<4> opcod, string opc, PatFrag opnode> {
def ri : AsI1<opcod, (outs GPR:$dst), (ins GPR:$a, so_imm:$b), DPRIm,
def ri : AsI1<opcod, (outs GPR:$dst), (ins GPR:$a, so_imm:$b), DPFrm,
opc, " $dst, $a, $b",
[(set GPR:$dst, (opnode GPR:$a, so_imm:$b))]>;
def rr : AsI1<opcod, (outs GPR:$dst), (ins GPR:$a, GPR:$b), DPRReg,
def rr : AsI1<opcod, (outs GPR:$dst), (ins GPR:$a, GPR:$b), DPFrm,
opc, " $dst, $a, $b",
[(set GPR:$dst, (opnode GPR:$a, GPR:$b))]>;
def rs : AsI1<opcod, (outs GPR:$dst), (ins GPR:$a, so_reg:$b), DPRSoReg,
def rs : AsI1<opcod, (outs GPR:$dst), (ins GPR:$a, so_reg:$b), DPSoRegFrm,
opc, " $dst, $a, $b",
[(set GPR:$dst, (opnode GPR:$a, so_reg:$b))]>;
}
@ -360,13 +359,13 @@ multiclass AsI1_bin_irs<bits<4> opcod, string opc, PatFrag opnode> {
/// instruction modifies the CSPR register.
let Defs = [CPSR] in {
multiclass ASI1_bin_s_irs<bits<4> opcod, string opc, PatFrag opnode> {
def ri : AI1<opcod, (outs GPR:$dst), (ins GPR:$a, so_imm:$b), DPRImS,
def ri : AI1<opcod, (outs GPR:$dst), (ins GPR:$a, so_imm:$b), DPFrm,
opc, "s $dst, $a, $b",
[(set GPR:$dst, (opnode GPR:$a, so_imm:$b))]>;
def rr : AI1<opcod, (outs GPR:$dst), (ins GPR:$a, GPR:$b), DPRRegS,
def rr : AI1<opcod, (outs GPR:$dst), (ins GPR:$a, GPR:$b), DPFrm,
opc, "s $dst, $a, $b",
[(set GPR:$dst, (opnode GPR:$a, GPR:$b))]>;
def rs : AI1<opcod, (outs GPR:$dst), (ins GPR:$a, so_reg:$b), DPRSoRegS,
def rs : AI1<opcod, (outs GPR:$dst), (ins GPR:$a, so_reg:$b), DPSoRegFrm,
opc, "s $dst, $a, $b",
[(set GPR:$dst, (opnode GPR:$a, so_reg:$b))]>;
}
@ -377,13 +376,13 @@ multiclass ASI1_bin_s_irs<bits<4> opcod, string opc, PatFrag opnode> {
/// a explicit result, only implicitly set CPSR.
let Defs = [CPSR] in {
multiclass AI1_cmp_irs<bits<4> opcod, string opc, PatFrag opnode> {
def ri : AI1<opcod, (outs), (ins GPR:$a, so_imm:$b), DPRnIm,
def ri : AI1<opcod, (outs), (ins GPR:$a, so_imm:$b), DPFrm,
opc, " $a, $b",
[(opnode GPR:$a, so_imm:$b)]>;
def rr : AI1<opcod, (outs), (ins GPR:$a, GPR:$b), DPRnReg,
def rr : AI1<opcod, (outs), (ins GPR:$a, GPR:$b), DPFrm,
opc, " $a, $b",
[(opnode GPR:$a, GPR:$b)]>;
def rs : AI1<opcod, (outs), (ins GPR:$a, so_reg:$b), DPRnSoReg,
def rs : AI1<opcod, (outs), (ins GPR:$a, so_reg:$b), DPSoRegFrm,
opc, " $a, $b",
[(opnode GPR:$a, so_reg:$b)]>;
}
@ -420,13 +419,13 @@ multiclass AI_bin_rrot<bits<4> opcod, string opc, PatFrag opnode> {
let Uses = [CPSR] in {
multiclass AsXI1_bin_c_irs<bits<4> opcod, string opc, PatFrag opnode> {
def ri : AXI1<opcod, (outs GPR:$dst), (ins GPR:$a, so_imm:$b, cc_out:$s),
DPRIm, !strconcat(opc, "${s} $dst, $a, $b"),
DPFrm, !strconcat(opc, "${s} $dst, $a, $b"),
[(set GPR:$dst, (opnode GPR:$a, so_imm:$b))]>;
def rr : AXI1<opcod, (outs GPR:$dst), (ins GPR:$a, GPR:$b, cc_out:$s),
DPRReg, !strconcat(opc, "${s} $dst, $a, $b"),
DPFrm, !strconcat(opc, "${s} $dst, $a, $b"),
[(set GPR:$dst, (opnode GPR:$a, GPR:$b))]>;
def rs : AXI1<opcod, (outs GPR:$dst), (ins GPR:$a, so_reg:$b, cc_out:$s),
DPRSoReg, !strconcat(opc, "${s} $dst, $a, $b"),
DPSoRegFrm, !strconcat(opc, "${s} $dst, $a, $b"),
[(set GPR:$dst, (opnode GPR:$a, so_reg:$b))]>;
}
}
@ -533,7 +532,7 @@ let isReturn = 1, isTerminator = 1 in
let isReturn = 1, isTerminator = 1 in
def LDM_RET : AXI4ldpc<0x0, (outs),
(ins addrmode4:$addr, pred:$p, reglist:$dst1, variable_ops),
LdFrm, "ldm${p}${addr:submode} $addr, $dst1",
LdMulFrm, "ldm${p}${addr:submode} $addr, $dst1",
[]>;
let isCall = 1,
@ -610,7 +609,7 @@ def LDRcp : AI2ldw<0x0, (outs GPR:$dst), (ins addrmode2:$addr), LdFrm,
"ldr", " $dst, $addr", []>;
// Loads with zero extension
def LDRH : AI3ldh<0xB, (outs GPR:$dst), (ins addrmode3:$addr), LdFrm,
def LDRH : AI3ldh<0xB, (outs GPR:$dst), (ins addrmode3:$addr), LdMiscFrm,
"ldr", "h $dst, $addr",
[(set GPR:$dst, (zextloadi16 addrmode3:$addr))]>;
@ -619,17 +618,17 @@ def LDRB : AI2ldb<0x1, (outs GPR:$dst), (ins addrmode2:$addr), LdFrm,
[(set GPR:$dst, (zextloadi8 addrmode2:$addr))]>;
// Loads with sign extension
def LDRSH : AI3ldsh<0xE, (outs GPR:$dst), (ins addrmode3:$addr), LdFrm,
def LDRSH : AI3ldsh<0xE, (outs GPR:$dst), (ins addrmode3:$addr), LdMiscFrm,
"ldr", "sh $dst, $addr",
[(set GPR:$dst, (sextloadi16 addrmode3:$addr))]>;
def LDRSB : AI3ldsb<0xD, (outs GPR:$dst), (ins addrmode3:$addr), LdFrm,
def LDRSB : AI3ldsb<0xD, (outs GPR:$dst), (ins addrmode3:$addr), LdMiscFrm,
"ldr", "sb $dst, $addr",
[(set GPR:$dst, (sextloadi8 addrmode3:$addr))]>;
let mayLoad = 1 in {
// Load doubleword
def LDRD : AI3ldd<0xD, (outs GPR:$dst), (ins addrmode3:$addr), LdFrm,
def LDRD : AI3ldd<0xD, (outs GPR:$dst), (ins addrmode3:$addr), LdMiscFrm,
"ldr", "d $dst, $addr",
[]>, Requires<[IsARM, HasV5T]>;
@ -643,11 +642,11 @@ def LDR_POST : AI2ldwpo<0x0, (outs GPR:$dst, GPR:$base_wb),
"ldr", " $dst, [$base], $offset", "$base = $base_wb", []>;
def LDRH_PRE : AI3ldhpr<0xB, (outs GPR:$dst, GPR:$base_wb),
(ins addrmode3:$addr), LdFrm,
(ins addrmode3:$addr), LdMiscFrm,
"ldr", "h $dst, $addr!", "$addr.base = $base_wb", []>;
def LDRH_POST : AI3ldhpo<0xB, (outs GPR:$dst, GPR:$base_wb),
(ins GPR:$base,am3offset:$offset), LdFrm,
(ins GPR:$base,am3offset:$offset), LdMiscFrm,
"ldr", "h $dst, [$base], $offset", "$base = $base_wb", []>;
def LDRB_PRE : AI2ldbpr<0x1, (outs GPR:$dst, GPR:$base_wb),
@ -659,19 +658,19 @@ def LDRB_POST : AI2ldbpo<0x1, (outs GPR:$dst, GPR:$base_wb),
"ldr", "b $dst, [$base], $offset", "$base = $base_wb", []>;
def LDRSH_PRE : AI3ldshpr<0xE, (outs GPR:$dst, GPR:$base_wb),
(ins addrmode3:$addr), LdFrm,
(ins addrmode3:$addr), LdMiscFrm,
"ldr", "sh $dst, $addr!", "$addr.base = $base_wb", []>;
def LDRSH_POST: AI3ldshpo<0xE, (outs GPR:$dst, GPR:$base_wb),
(ins GPR:$base,am3offset:$offset), LdFrm,
(ins GPR:$base,am3offset:$offset), LdMiscFrm,
"ldr", "sh $dst, [$base], $offset", "$base = $base_wb", []>;
def LDRSB_PRE : AI3ldsbpr<0xD, (outs GPR:$dst, GPR:$base_wb),
(ins addrmode3:$addr), LdFrm,
(ins addrmode3:$addr), LdMiscFrm,
"ldr", "sb $dst, $addr!", "$addr.base = $base_wb", []>;
def LDRSB_POST: AI3ldsbpo<0xD, (outs GPR:$dst, GPR:$base_wb),
(ins GPR:$base,am3offset:$offset), LdFrm,
(ins GPR:$base,am3offset:$offset), LdMiscFrm,
"ldr", "sb $dst, [$base], $offset", "$base = $base_wb", []>;
}
@ -681,7 +680,7 @@ def STR : AI2stw<0x0, (outs), (ins GPR:$src, addrmode2:$addr), StFrm,
[(store GPR:$src, addrmode2:$addr)]>;
// Stores with truncate
def STRH : AI3sth<0xB, (outs), (ins GPR:$src, addrmode3:$addr), StFrm,
def STRH : AI3sth<0xB, (outs), (ins GPR:$src, addrmode3:$addr), StMiscFrm,
"str", "h $src, $addr",
[(truncstorei16 GPR:$src, addrmode3:$addr)]>;
@ -691,7 +690,7 @@ def STRB : AI2stb<0x1, (outs), (ins GPR:$src, addrmode2:$addr), StFrm,
// Store doubleword
let mayStore = 1 in
def STRD : AI3std<0xF, (outs), (ins GPR:$src, addrmode3:$addr), StFrm,
def STRD : AI3std<0xF, (outs), (ins GPR:$src, addrmode3:$addr), StMiscFrm,
"str", "d $src, $addr",
[]>, Requires<[IsARM, HasV5T]>;
@ -709,13 +708,13 @@ def STR_POST : AI2stwpo<0x0, (outs GPR:$base_wb),
(post_store GPR:$src, GPR:$base, am2offset:$offset))]>;
def STRH_PRE : AI3sthpr<0xB, (outs GPR:$base_wb),
(ins GPR:$src, GPR:$base,am3offset:$offset), StFrm,
(ins GPR:$src, GPR:$base,am3offset:$offset), StMiscFrm,
"str", "h $src, [$base, $offset]!", "$base = $base_wb",
[(set GPR:$base_wb,
(pre_truncsti16 GPR:$src, GPR:$base,am3offset:$offset))]>;
def STRH_POST: AI3sthpo<0xB, (outs GPR:$base_wb),
(ins GPR:$src, GPR:$base,am3offset:$offset), StFrm,
(ins GPR:$src, GPR:$base,am3offset:$offset), StMiscFrm,
"str", "h $src, [$base], $offset", "$base = $base_wb",
[(set GPR:$base_wb, (post_truncsti16 GPR:$src,
GPR:$base, am3offset:$offset))]>;
@ -740,42 +739,42 @@ def STRB_POST: AI2stbpo<0x1, (outs GPR:$base_wb),
let mayLoad = 1 in
def LDM : AXI4ld<0x0, (outs),
(ins addrmode4:$addr, pred:$p, reglist:$dst1, variable_ops),
LdFrm, "ldm${p}${addr:submode} $addr, $dst1",
LdMulFrm, "ldm${p}${addr:submode} $addr, $dst1",
[]>;
let mayStore = 1 in
def STM : AXI4st<0x0, (outs),
(ins addrmode4:$addr, pred:$p, reglist:$src1, variable_ops),
StFrm, "stm${p}${addr:submode} $addr, $src1",
StMulFrm, "stm${p}${addr:submode} $addr, $src1",
[]>;
//===----------------------------------------------------------------------===//
// Move Instructions.
//
def MOVr : AsI1<0b1101, (outs GPR:$dst), (ins GPR:$src), DPRdReg,
"mov", " $dst, $src", []>;
def MOVs : AsI1<0b1101, (outs GPR:$dst), (ins so_reg:$src), DPRdSoReg,
"mov", " $dst, $src", [(set GPR:$dst, so_reg:$src)]>;
def MOVr : AsI1<0b1101, (outs GPR:$dst), (ins GPR:$src), DPFrm,
"mov", " $dst, $src", []>, UnaryDP;
def MOVs : AsI1<0b1101, (outs GPR:$dst), (ins so_reg:$src), DPSoRegFrm,
"mov", " $dst, $src", [(set GPR:$dst, so_reg:$src)]>, UnaryDP;
let isReMaterializable = 1 in
def MOVi : AsI1<0b1101, (outs GPR:$dst), (ins so_imm:$src), DPRdIm,
"mov", " $dst, $src", [(set GPR:$dst, so_imm:$src)]>;
def MOVi : AsI1<0b1101, (outs GPR:$dst), (ins so_imm:$src), DPFrm,
"mov", " $dst, $src", [(set GPR:$dst, so_imm:$src)]>, UnaryDP;
def MOVrx : AsI1<0b1101, (outs GPR:$dst), (ins GPR:$src), DPRdMisc,
def MOVrx : AsI1<0b1101, (outs GPR:$dst), (ins GPR:$src), DPFrm,
"mov", " $dst, $src, rrx",
[(set GPR:$dst, (ARMrrx GPR:$src))]>;
[(set GPR:$dst, (ARMrrx GPR:$src))]>, UnaryDP;
// These aren't really mov instructions, but we have to define them this way
// due to flag operands.
let Defs = [CPSR] in {
def MOVsrl_flag : AI1<0b1101, (outs GPR:$dst), (ins GPR:$src), DPRdMisc,
def MOVsrl_flag : AI1<0b1101, (outs GPR:$dst), (ins GPR:$src), DPFrm,
"mov", "s $dst, $src, lsr #1",
[(set GPR:$dst, (ARMsrl_flag GPR:$src))]>;
def MOVsra_flag : AI1<0b1101, (outs GPR:$dst), (ins GPR:$src), DPRdMisc,
[(set GPR:$dst, (ARMsrl_flag GPR:$src))]>, UnaryDP;
def MOVsra_flag : AI1<0b1101, (outs GPR:$dst), (ins GPR:$src), DPFrm,
"mov", "s $dst, $src, asr #1",
[(set GPR:$dst, (ARMsra_flag GPR:$src))]>;
[(set GPR:$dst, (ARMsra_flag GPR:$src))]>, UnaryDP;
}
//===----------------------------------------------------------------------===//
@ -839,20 +838,20 @@ defm SBC : AsXI1_bin_c_irs<0b0110, "sbc",
BinOpFrag<(sube node:$LHS, node:$RHS)>>;
// These don't define reg/reg forms, because they are handled above.
def RSBri : AsI1<0b0011, (outs GPR:$dst), (ins GPR:$a, so_imm:$b), DPRIm,
def RSBri : AsI1<0b0011, (outs GPR:$dst), (ins GPR:$a, so_imm:$b), DPFrm,
"rsb", " $dst, $a, $b",
[(set GPR:$dst, (sub so_imm:$b, GPR:$a))]>;
def RSBrs : AsI1<0b0011, (outs GPR:$dst), (ins GPR:$a, so_reg:$b), DPRSoReg,
def RSBrs : AsI1<0b0011, (outs GPR:$dst), (ins GPR:$a, so_reg:$b), DPSoRegFrm,
"rsb", " $dst, $a, $b",
[(set GPR:$dst, (sub so_reg:$b, GPR:$a))]>;
// RSB with 's' bit set.
let Defs = [CPSR] in {
def RSBSri : AI1<0b0011, (outs GPR:$dst), (ins GPR:$a, so_imm:$b), DPRIm,
def RSBSri : AI1<0b0011, (outs GPR:$dst), (ins GPR:$a, so_imm:$b), DPFrm,
"rsb", "s $dst, $a, $b",
[(set GPR:$dst, (subc so_imm:$b, GPR:$a))]>;
def RSBSrs : AI1<0b0011, (outs GPR:$dst), (ins GPR:$a, so_reg:$b), DPRSoReg,
def RSBSrs : AI1<0b0011, (outs GPR:$dst), (ins GPR:$a, so_reg:$b), DPSoRegFrm,
"rsb", "s $dst, $a, $b",
[(set GPR:$dst, (subc so_reg:$b, GPR:$a))]>;
}
@ -860,10 +859,10 @@ def RSBSrs : AI1<0b0011, (outs GPR:$dst), (ins GPR:$a, so_reg:$b), DPRSoReg,
// FIXME: Do not allow RSC to be predicated for now. But they can set CPSR.
let Uses = [CPSR] in {
def RSCri : AXI1<0b0111, (outs GPR:$dst), (ins GPR:$a, so_imm:$b, cc_out:$s),
DPRIm, "rsc${s} $dst, $a, $b",
DPFrm, "rsc${s} $dst, $a, $b",
[(set GPR:$dst, (sube so_imm:$b, GPR:$a))]>;
def RSCrs : AXI1<0b0111, (outs GPR:$dst), (ins GPR:$a, so_reg:$b, cc_out:$s),
DPRSoReg, "rsc${s} $dst, $a, $b",
DPSoRegFrm, "rsc${s} $dst, $a, $b",
[(set GPR:$dst, (sube so_reg:$b, GPR:$a))]>;
}
@ -896,13 +895,16 @@ defm EOR : AsI1_bin_irs<0b0001, "eor",
defm BIC : AsI1_bin_irs<0b1110, "bic",
BinOpFrag<(and node:$LHS, (not node:$RHS))>>;
def MVNr : AsI1<0b1111, (outs GPR:$dst), (ins GPR:$src), DPRdReg,
"mvn", " $dst, $src", [(set GPR:$dst, (not GPR:$src))]>;
def MVNs : AsI1<0b1111, (outs GPR:$dst), (ins so_reg:$src), DPRdSoReg,
"mvn", " $dst, $src", [(set GPR:$dst, (not so_reg:$src))]>;
def MVNr : AsI1<0b1111, (outs GPR:$dst), (ins GPR:$src), DPFrm,
"mvn", " $dst, $src",
[(set GPR:$dst, (not GPR:$src))]>, UnaryDP;
def MVNs : AsI1<0b1111, (outs GPR:$dst), (ins so_reg:$src), DPSoRegFrm,
"mvn", " $dst, $src",
[(set GPR:$dst, (not so_reg:$src))]>, UnaryDP;
let isReMaterializable = 1 in
def MVNi : AsI1<0b1111, (outs GPR:$dst), (ins so_imm:$imm), DPRdIm,
"mvn", " $dst, $imm", [(set GPR:$dst, so_imm_not:$imm)]>;
def MVNi : AsI1<0b1111, (outs GPR:$dst), (ins so_imm:$imm), DPFrm,
"mvn", " $dst, $imm",
[(set GPR:$dst, so_imm_not:$imm)]>,UnaryDP;
def : ARMPat<(and GPR:$src, so_imm_not:$imm),
(BICri GPR:$src, so_imm_not:$imm)>;
@ -911,48 +913,48 @@ def : ARMPat<(and GPR:$src, so_imm_not:$imm),
// Multiply Instructions.
//
def MUL : AsI6<0b0000, (outs GPR:$dst), (ins GPR:$a, GPR:$b), MulFrm,
def MUL : AsMul1I<0b0000, (outs GPR:$dst), (ins GPR:$a, GPR:$b),
"mul", " $dst, $a, $b",
[(set GPR:$dst, (mul GPR:$a, GPR:$b))]>;
def MLA : AsI6<0b0010, (outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$c),
MulFrm, "mla", " $dst, $a, $b, $c",
def MLA : AsMul1I<0b0010, (outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$c),
"mla", " $dst, $a, $b, $c",
[(set GPR:$dst, (add (mul GPR:$a, GPR:$b), GPR:$c))]>;
// Extra precision multiplies with low / high results
def SMULL : AsI6<0b1100, (outs GPR:$ldst, GPR:$hdst), (ins GPR:$a, GPR:$b),
MulFrm, "smull", " $ldst, $hdst, $a, $b", []>;
def SMULL : AsMul1I<0b1100, (outs GPR:$ldst, GPR:$hdst), (ins GPR:$a, GPR:$b),
"smull", " $ldst, $hdst, $a, $b", []>;
def UMULL : AsI6<0b1000, (outs GPR:$ldst, GPR:$hdst), (ins GPR:$a, GPR:$b),
MulFrm, "umull", " $ldst, $hdst, $a, $b", []>;
def UMULL : AsMul1I<0b1000, (outs GPR:$ldst, GPR:$hdst), (ins GPR:$a, GPR:$b),
"umull", " $ldst, $hdst, $a, $b", []>;
// Multiply + accumulate
def SMLAL : AsI6<0b1110, (outs GPR:$ldst, GPR:$hdst), (ins GPR:$a, GPR:$b),
MulFrm, "smlal", " $ldst, $hdst, $a, $b", []>;
def SMLAL : AsMul1I<0b1110, (outs GPR:$ldst, GPR:$hdst), (ins GPR:$a, GPR:$b),
"smlal", " $ldst, $hdst, $a, $b", []>;
def UMLAL : AsI6<0b1010, (outs GPR:$ldst, GPR:$hdst), (ins GPR:$a, GPR:$b),
MulFrm, "umlal", " $ldst, $hdst, $a, $b", []>;
def UMLAL : AsMul1I<0b1010, (outs GPR:$ldst, GPR:$hdst), (ins GPR:$a, GPR:$b),
"umlal", " $ldst, $hdst, $a, $b", []>;
def UMAAL : AI6 <0b0000, (outs GPR:$ldst, GPR:$hdst), (ins GPR:$a, GPR:$b),
MulFrm, "umaal", " $ldst, $hdst, $a, $b", []>,
Requires<[IsARM, HasV6]>;
def UMAAL : AMul1I<0b0000, (outs GPR:$ldst, GPR:$hdst), (ins GPR:$a, GPR:$b),
"umaal", " $ldst, $hdst, $a, $b", []>,
Requires<[IsARM, HasV6]>;
// Most significant word multiply
// FIXME: encoding
def SMMUL : AI<0x0, (outs GPR:$dst), (ins GPR:$a, GPR:$b), MulFrm,
def SMMUL : AI<0x0, (outs GPR:$dst), (ins GPR:$a, GPR:$b), MulFrm2,
"smmul", " $dst, $a, $b",
[(set GPR:$dst, (mulhs GPR:$a, GPR:$b))]>,
Requires<[IsARM, HasV6]>;
// FIXME: encoding
def SMMLA : AI<0x0, (outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$c), MulFrm,
def SMMLA : AI<0x0, (outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$c), MulFrm2,
"smmla", " $dst, $a, $b, $c",
[(set GPR:$dst, (add (mulhs GPR:$a, GPR:$b), GPR:$c))]>,
Requires<[IsARM, HasV6]>;
// FIXME: encoding
def SMMLS : AI<0x0, (outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$c), MulFrm,
def SMMLS : AI<0x0, (outs GPR:$dst), (ins GPR:$a, GPR:$b, GPR:$c), MulFrm2,
"smmls", " $dst, $a, $b, $c",
[(set GPR:$dst, (sub GPR:$c, (mulhs GPR:$a, GPR:$b)))]>,
Requires<[IsARM, HasV6]>;
@ -1133,20 +1135,20 @@ def : ARMPat<(ARMcmpNZ GPR:$src, so_imm_neg:$imm),
// Conditional moves
// FIXME: should be able to write a pattern for ARMcmov, but can't use
// a two-value operand where a dag node expects two operands. :(
def MOVCCr : AI<0xD, (outs GPR:$dst), (ins GPR:$false, GPR:$true),
DPRdReg, "mov", " $dst, $true",
def MOVCCr : AI<0xD, (outs GPR:$dst), (ins GPR:$false, GPR:$true), DPFrm,
"mov", " $dst, $true",
[/*(set GPR:$dst, (ARMcmov GPR:$false, GPR:$true, imm:$cc, CCR:$ccr))*/]>,
RegConstraint<"$false = $dst">;
def MOVCCs : AI<0xD, (outs GPR:$dst), (ins GPR:$false, so_reg:$true),
DPRdSoReg, "mov", " $dst, $true",
def MOVCCs : AI<0xD, (outs GPR:$dst), (ins GPR:$false, so_reg:$true), DPSoRegFrm,
"mov", " $dst, $true",
[/*(set GPR:$dst, (ARMcmov GPR:$false, so_reg:$true, imm:$cc, CCR:$ccr))*/]>,
RegConstraint<"$false = $dst">;
RegConstraint<"$false = $dst">, UnaryDP;
def MOVCCi : AI<0xD, (outs GPR:$dst), (ins GPR:$false, so_imm:$true),
DPRdIm, "mov", " $dst, $true",
def MOVCCi : AI<0xD, (outs GPR:$dst), (ins GPR:$false, so_imm:$true), DPFrm,
"mov", " $dst, $true",
[/*(set GPR:$dst, (ARMcmov GPR:$false, so_imm:$true, imm:$cc, CCR:$ccr))*/]>,
RegConstraint<"$false = $dst">;
RegConstraint<"$false = $dst">, UnaryDP;
// LEApcrel - Load a pc-relative address into a register without offending the
@ -1192,9 +1194,9 @@ def : ARMPat<(ARMWrapperJT tjumptable:$dst, imm:$id),
// Two piece so_imms.
let isReMaterializable = 1 in
def MOVi2pieces : AI1x2<0x0, (outs GPR:$dst), (ins so_imm2part:$src), DPRdMisc,
def MOVi2pieces : AI1x2<0x0, (outs GPR:$dst), (ins so_imm2part:$src), DPFrm,
"mov", " $dst, $src",
[(set GPR:$dst, so_imm2part:$src)]>;
[(set GPR:$dst, so_imm2part:$src)]>, UnaryDP;
def : ARMPat<(or GPR:$LHS, so_imm2part:$RHS),
(ORRri (ORRri GPR:$LHS, (so_imm2part_1 imm:$RHS)),