forked from OSchip/llvm-project
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:
parent
ce2417f4e1
commit
81889d010c
|
@ -102,12 +102,14 @@ def ARMInstrInfo : InstrInfo {
|
|||
"SizeFlag",
|
||||
"IndexModeBits",
|
||||
"Opcode",
|
||||
"isUnaryDataProc",
|
||||
"Form"];
|
||||
let TSFlagsShifts = [0,
|
||||
4,
|
||||
7,
|
||||
9,
|
||||
13];
|
||||
13,
|
||||
14];
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
@ -74,6 +73,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;
|
||||
|
|
|
@ -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,
|
||||
|
@ -63,56 +62,57 @@ namespace ARMII {
|
|||
// Opcode
|
||||
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,
|
||||
|
|
|
@ -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)),
|
||||
|
|
Loading…
Reference in New Issue