summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/Target/ARM/ARMBaseInstrInfo.h5
-rw-r--r--llvm/lib/Target/ARM/ARMCodeEmitter.cpp33
-rw-r--r--llvm/lib/Target/ARM/ARMInstrFormats.td17
-rw-r--r--llvm/lib/Target/ARM/ARMInstrInfo.td12
-rw-r--r--llvm/lib/Target/ARM/ARMInstrVFP.td16
5 files changed, 51 insertions, 32 deletions
diff --git a/llvm/lib/Target/ARM/ARMBaseInstrInfo.h b/llvm/lib/Target/ARM/ARMBaseInstrInfo.h
index 01942319b21..767d5ec9265 100644
--- a/llvm/lib/Target/ARM/ARMBaseInstrInfo.h
+++ b/llvm/lib/Target/ARM/ARMBaseInstrInfo.h
@@ -58,12 +58,13 @@ namespace ARMII {
Size4Bytes = 3,
Size2Bytes = 4,
- // IndexMode - Unindex, pre-indexed, or post-indexed. Only valid for load
- // and store ops
+ // IndexMode - Unindex, pre-indexed, or post-indexed are valid for load
+ // and store ops only. Generic "updating" flag is used for ld/st multiple.
IndexModeShift = 7,
IndexModeMask = 3 << IndexModeShift,
IndexModePre = 1,
IndexModePost = 2,
+ IndexModeUpd = 3,
//===------------------------------------------------------------------===//
// Instruction encoding formats.
diff --git a/llvm/lib/Target/ARM/ARMCodeEmitter.cpp b/llvm/lib/Target/ARM/ARMCodeEmitter.cpp
index 60dce583693..5b5bd4f73bb 100644
--- a/llvm/lib/Target/ARM/ARMCodeEmitter.cpp
+++ b/llvm/lib/Target/ARM/ARMCodeEmitter.cpp
@@ -925,19 +925,26 @@ static unsigned getAddrModeUPBits(unsigned Mode) {
return Binary;
}
-void ARMCodeEmitter::emitLoadStoreMultipleInstruction(
- const MachineInstr &MI) {
+void ARMCodeEmitter::emitLoadStoreMultipleInstruction(const MachineInstr &MI) {
+ const TargetInstrDesc &TID = MI.getDesc();
+ bool IsUpdating = (TID.TSFlags & ARMII::IndexModeMask) != 0;
+
// Part of binary is determined by TableGn.
unsigned Binary = getBinaryCodeForInstr(MI);
// Set the conditional execution predicate
Binary |= II->getPredicate(&MI) << ARMII::CondShift;
+ // Skip operand 0 of an instruction with base register update.
+ unsigned OpIdx = 0;
+ if (IsUpdating)
+ ++OpIdx;
+
// Set base address operand
- Binary |= getMachineOpValue(MI, 0) << ARMII::RegRnShift;
+ Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRnShift;
// Set addressing mode by modifying bits U(23) and P(24)
- const MachineOperand &MO = MI.getOperand(1);
+ const MachineOperand &MO = MI.getOperand(OpIdx++);
Binary |= getAddrModeUPBits(ARM_AM::getAM4SubMode(MO.getImm()));
// Set bit W(21)
@@ -945,7 +952,7 @@ void ARMCodeEmitter::emitLoadStoreMultipleInstruction(
Binary |= 0x1 << ARMII::W_BitShift;
// Set registers
- for (unsigned i = 5, e = MI.getNumOperands(); i != e; ++i) {
+ for (unsigned i = OpIdx+2, e = MI.getNumOperands(); i != e; ++i) {
const MachineOperand &MO = MI.getOperand(i);
if (!MO.isReg() || MO.isImplicit())
break;
@@ -1322,17 +1329,25 @@ void ARMCodeEmitter::emitVFPLoadStoreInstruction(const MachineInstr &MI) {
void ARMCodeEmitter::emitVFPLoadStoreMultipleInstruction(
const MachineInstr &MI) {
+ const TargetInstrDesc &TID = MI.getDesc();
+ bool IsUpdating = (TID.TSFlags & ARMII::IndexModeMask) != 0;
+
// Part of binary is determined by TableGn.
unsigned Binary = getBinaryCodeForInstr(MI);
// Set the conditional execution predicate
Binary |= II->getPredicate(&MI) << ARMII::CondShift;
+ // Skip operand 0 of an instruction with base register update.
+ unsigned OpIdx = 0;
+ if (IsUpdating)
+ ++OpIdx;
+
// Set base address operand
- Binary |= getMachineOpValue(MI, 0) << ARMII::RegRnShift;
+ Binary |= getMachineOpValue(MI, OpIdx++) << ARMII::RegRnShift;
// Set addressing mode by modifying bits U(23) and P(24)
- const MachineOperand &MO = MI.getOperand(1);
+ const MachineOperand &MO = MI.getOperand(OpIdx++);
Binary |= getAddrModeUPBits(ARM_AM::getAM5SubMode(MO.getImm()));
// Set bit W(21)
@@ -1340,11 +1355,11 @@ void ARMCodeEmitter::emitVFPLoadStoreMultipleInstruction(
Binary |= 0x1 << ARMII::W_BitShift;
// First register is encoded in Dd.
- Binary |= encodeVFPRd(MI, 5);
+ Binary |= encodeVFPRd(MI, OpIdx+2);
// Number of registers are encoded in offset field.
unsigned NumRegs = 1;
- for (unsigned i = 6, e = MI.getNumOperands(); i != e; ++i) {
+ for (unsigned i = OpIdx+3, e = MI.getNumOperands(); i != e; ++i) {
const MachineOperand &MO = MI.getOperand(i);
if (!MO.isReg() || MO.isImplicit())
break;
diff --git a/llvm/lib/Target/ARM/ARMInstrFormats.td b/llvm/lib/Target/ARM/ARMInstrFormats.td
index 84eca85192c..258a96b9216 100644
--- a/llvm/lib/Target/ARM/ARMInstrFormats.td
+++ b/llvm/lib/Target/ARM/ARMInstrFormats.td
@@ -112,6 +112,7 @@ class IndexMode<bits<2> val> {
def IndexModeNone : IndexMode<0>;
def IndexModePre : IndexMode<1>;
def IndexModePost : IndexMode<2>;
+def IndexModeUpd : IndexMode<3>;
// Instruction execution domain.
class Domain<bits<2> val> {
@@ -852,17 +853,17 @@ class AI3stdpo<dag oops, dag iops, Format f, InstrItinClass itin,
// addrmode4 instructions
-class AXI4ld<dag oops, dag iops, Format f, InstrItinClass itin,
+class AXI4ld<dag oops, dag iops, IndexMode im, Format f, InstrItinClass itin,
string asm, string cstr, list<dag> pattern>
- : XI<oops, iops, AddrMode4, Size4Bytes, IndexModeNone, f, itin,
+ : XI<oops, iops, AddrMode4, Size4Bytes, im, f, itin,
asm, cstr, pattern> {
let Inst{20} = 1; // L bit
let Inst{22} = 0; // S bit
let Inst{27-25} = 0b100;
}
-class AXI4st<dag oops, dag iops, Format f, InstrItinClass itin,
+class AXI4st<dag oops, dag iops, IndexMode im, Format f, InstrItinClass itin,
string asm, string cstr, list<dag> pattern>
- : XI<oops, iops, AddrMode4, Size4Bytes, IndexModeNone, f, itin,
+ : XI<oops, iops, AddrMode4, Size4Bytes, im, f, itin,
asm, cstr, pattern> {
let Inst{20} = 0; // L bit
let Inst{22} = 0; // S bit
@@ -1314,9 +1315,9 @@ class ASI5<bits<4> opcod1, bits<2> opcod2, dag oops, dag iops,
}
// Load / store multiple
-class AXDI5<dag oops, dag iops, InstrItinClass itin,
+class AXDI5<dag oops, dag iops, IndexMode im, InstrItinClass itin,
string asm, string cstr, list<dag> pattern>
- : VFPXI<oops, iops, AddrMode5, Size4Bytes, IndexModeNone,
+ : VFPXI<oops, iops, AddrMode5, Size4Bytes, im,
VFPLdStMulFrm, itin, asm, cstr, pattern> {
// TODO: Mark the instructions with the appropriate subtarget info.
let Inst{27-25} = 0b110;
@@ -1326,9 +1327,9 @@ class AXDI5<dag oops, dag iops, InstrItinClass itin,
let Dom = VFPNeonDomain.Value;
}
-class AXSI5<dag oops, dag iops, InstrItinClass itin,
+class AXSI5<dag oops, dag iops, IndexMode im, InstrItinClass itin,
string asm, string cstr, list<dag> pattern>
- : VFPXI<oops, iops, AddrMode5, Size4Bytes, IndexModeNone,
+ : VFPXI<oops, iops, AddrMode5, Size4Bytes, im,
VFPLdStMulFrm, itin, asm, cstr, pattern> {
// TODO: Mark the instructions with the appropriate subtarget info.
let Inst{27-25} = 0b110;
diff --git a/llvm/lib/Target/ARM/ARMInstrInfo.td b/llvm/lib/Target/ARM/ARMInstrInfo.td
index a82a5d1e575..3fc37dae4e4 100644
--- a/llvm/lib/Target/ARM/ARMInstrInfo.td
+++ b/llvm/lib/Target/ARM/ARMInstrInfo.td
@@ -908,7 +908,7 @@ let isReturn = 1, isTerminator = 1, isBarrier = 1, mayLoad = 1,
hasExtraDefRegAllocReq = 1 in
def LDM_RET : AXI4ld<(outs GPR:$wb), (ins addrmode4:$addr, pred:$p,
reglist:$dsts, variable_ops),
- LdStMulFrm, IIC_Br,
+ IndexModeUpd, LdStMulFrm, IIC_Br,
"ldm${addr:submode}${p}\t$addr, $dsts",
"$addr.addr = $wb", []>;
@@ -1347,24 +1347,26 @@ def STRHT: AI3sthpo<(outs GPR:$base_wb),
let mayLoad = 1, hasExtraDefRegAllocReq = 1 in {
def LDM : AXI4ld<(outs), (ins addrmode4:$addr, pred:$p,
- reglist:$dsts, variable_ops), LdStMulFrm, IIC_iLoadm,
+ reglist:$dsts, variable_ops),
+ IndexModeNone, LdStMulFrm, IIC_iLoadm,
"ldm${addr:submode}${p}\t$addr, $dsts", "", []>;
def LDM_UPD : AXI4ld<(outs GPR:$wb), (ins addrmode4:$addr, pred:$p,
reglist:$dsts, variable_ops),
- LdStMulFrm, IIC_iLoadm,
+ IndexModeUpd, LdStMulFrm, IIC_iLoadm,
"ldm${addr:submode}${p}\t$addr, $dsts",
"$addr.addr = $wb", []>;
} // mayLoad, hasExtraDefRegAllocReq
let mayStore = 1, hasExtraSrcRegAllocReq = 1 in {
def STM : AXI4st<(outs), (ins addrmode4:$addr, pred:$p,
- reglist:$srcs, variable_ops), LdStMulFrm, IIC_iStorem,
+ reglist:$srcs, variable_ops),
+ IndexModeNone, LdStMulFrm, IIC_iStorem,
"stm${addr:submode}${p}\t$addr, $srcs", "", []>;
def STM_UPD : AXI4st<(outs GPR:$wb), (ins addrmode4:$addr, pred:$p,
reglist:$srcs, variable_ops),
- LdStMulFrm, IIC_iStorem,
+ IndexModeUpd, LdStMulFrm, IIC_iStorem,
"stm${addr:submode}${p}\t$addr, $srcs",
"$addr.addr = $wb", []>;
} // mayStore, hasExtraSrcRegAllocReq
diff --git a/llvm/lib/Target/ARM/ARMInstrVFP.td b/llvm/lib/Target/ARM/ARMInstrVFP.td
index 1d35a33fe53..44c02b4e4fb 100644
--- a/llvm/lib/Target/ARM/ARMInstrVFP.td
+++ b/llvm/lib/Target/ARM/ARMInstrVFP.td
@@ -78,20 +78,20 @@ def VSTRS : ASI5<0b1101, 0b00, (outs), (ins SPR:$src, addrmode5:$addr),
let mayLoad = 1, hasExtraDefRegAllocReq = 1 in {
def VLDMD : AXDI5<(outs), (ins addrmode5:$addr, pred:$p, reglist:$dsts,
- variable_ops), IIC_fpLoadm,
+ variable_ops), IndexModeNone, IIC_fpLoadm,
"vldm${addr:submode}${p}\t${addr:base}, $dsts", "", []> {
let Inst{20} = 1;
}
def VLDMS : AXSI5<(outs), (ins addrmode5:$addr, pred:$p, reglist:$dsts,
- variable_ops), IIC_fpLoadm,
+ variable_ops), IndexModeNone, IIC_fpLoadm,
"vldm${addr:submode}${p}\t${addr:base}, $dsts", "", []> {
let Inst{20} = 1;
}
def VLDMD_UPD : AXDI5<(outs GPR:$wb), (ins addrmode5:$addr, pred:$p,
reglist:$dsts, variable_ops),
- IIC_fpLoadm,
+ IndexModeUpd, IIC_fpLoadm,
"vldm${addr:submode}${p}\t${addr:base}, $dsts",
"$addr.base = $wb", []> {
let Inst{20} = 1;
@@ -99,7 +99,7 @@ def VLDMD_UPD : AXDI5<(outs GPR:$wb), (ins addrmode5:$addr, pred:$p,
def VLDMS_UPD : AXSI5<(outs GPR:$wb), (ins addrmode5:$addr, pred:$p,
reglist:$dsts, variable_ops),
- IIC_fpLoadm,
+ IndexModeUpd, IIC_fpLoadm,
"vldm${addr:submode}${p}\t${addr:base}, $dsts",
"$addr.base = $wb", []> {
let Inst{20} = 1;
@@ -108,20 +108,20 @@ def VLDMS_UPD : AXSI5<(outs GPR:$wb), (ins addrmode5:$addr, pred:$p,
let mayStore = 1, hasExtraSrcRegAllocReq = 1 in {
def VSTMD : AXDI5<(outs), (ins addrmode5:$addr, pred:$p, reglist:$srcs,
- variable_ops), IIC_fpStorem,
+ variable_ops), IndexModeNone, IIC_fpStorem,
"vstm${addr:submode}${p}\t${addr:base}, $srcs", "", []> {
let Inst{20} = 0;
}
def VSTMS : AXSI5<(outs), (ins addrmode5:$addr, pred:$p, reglist:$srcs,
- variable_ops), IIC_fpStorem,
+ variable_ops), IndexModeNone, IIC_fpStorem,
"vstm${addr:submode}${p}\t${addr:base}, $srcs", "", []> {
let Inst{20} = 0;
}
def VSTMD_UPD : AXDI5<(outs GPR:$wb), (ins addrmode5:$addr, pred:$p,
reglist:$srcs, variable_ops),
- IIC_fpStorem,
+ IndexModeUpd, IIC_fpStorem,
"vstm${addr:submode}${p}\t${addr:base}, $srcs",
"$addr.base = $wb", []> {
let Inst{20} = 0;
@@ -129,7 +129,7 @@ def VSTMD_UPD : AXDI5<(outs GPR:$wb), (ins addrmode5:$addr, pred:$p,
def VSTMS_UPD : AXSI5<(outs GPR:$wb), (ins addrmode5:$addr, pred:$p,
reglist:$srcs, variable_ops),
- IIC_fpStorem,
+ IndexModeUpd, IIC_fpStorem,
"vstm${addr:submode}${p}\t${addr:base}, $srcs",
"$addr.base = $wb", []> {
let Inst{20} = 0;
OpenPOWER on IntegriCloud