break;
case ARMII::VFPConv1Frm:
case ARMII::VFPConv2Frm:
+ case ARMII::VFPConv3Frm:
emitVFPConversionInstruction(MI);
break;
case ARMII::VFPLdStFrm:
// Set the conditional execution predicate
Binary |= II->getPredicate(&MI) << ARMII::CondShift;
- unsigned OpIdx = 0;
+ // FMDRR encodes registers in reverse order.
+ unsigned Form = TID.TSFlags & ARMII::FormMask;
+ unsigned OpIdx = (Form == ARMII::VFPConv2Frm) ? 2 : 0;
// Encode Dd / Sd.
- unsigned RegD = getMachineOpValue(MI, OpIdx++);
+ unsigned RegD = getMachineOpValue(MI, OpIdx);
Binary |= (RegD & 0x0f) << ARMII::RegRdShift;
Binary |= (RegD & 0x10) << ARMII::D_BitShift;
+ if (Form == ARMII::VFPConv2Frm)
+ --OpIdx;
+ else
+ ++OpIdx;
// Encode Dn / Sn.
- if ((TID.TSFlags & ARMII::FormMask) == ARMII::VFPConv1Frm) {
- unsigned RegN = getMachineOpValue(MI, OpIdx++);
+ if (Form == ARMII::VFPConv1Frm || Form == ARMII::VFPConv2Frm) {
+ unsigned RegN = getMachineOpValue(MI, OpIdx);
Binary |= (RegN & 0x0f) << ARMII::RegRnShift;
Binary |= (RegN & 0x10) << ARMII::N_BitShift;
+ if (Form == ARMII::VFPConv2Frm)
+ --OpIdx;
+ else
+ ++OpIdx;
// FMRS / FMSR do not have Rm.
- if (!TID.OpInfo[2].isPredicate()) {
- unsigned RegM = getMachineOpValue(MI, OpIdx++);
+ if (TID.getNumOperands() > OpIdx && MI.getOperand(OpIdx).isReg()) {
+ unsigned RegM = getMachineOpValue(MI, OpIdx);
Binary |= (RegM & 0x0f);
Binary |= (RegM & 0x10) << ARMII::M_BitShift;
+ } else if (Form == ARMII::VFPConv2Frm) {
+ // FMDRR encodes definition register in Dm field.
+ Binary |= getMachineOpValue(MI, 0);
}
} else {
- unsigned RegM = getMachineOpValue(MI, OpIdx++);
+ assert(Form == ARMII::VFPConv3Frm && "Unsupported format!");
+ unsigned RegM = getMachineOpValue(MI, OpIdx);
Binary |= (RegM & 0x0f);
Binary |= (RegM & 0x10) << ARMII::M_BitShift;
}
def VFPBinaryFrm : Format<16>;
def VFPConv1Frm : Format<17>;
def VFPConv2Frm : Format<18>;
-def VFPLdStFrm : Format<19>;
-def VFPLdStMulFrm : Format<20>;
-def VFPMiscFrm : Format<21>;
+def VFPConv3Frm : Format<19>;
+def VFPLdStFrm : Format<20>;
+def VFPLdStMulFrm : Format<21>;
+def VFPMiscFrm : Format<22>;
-def ThumbFrm : Format<22>;
+def ThumbFrm : Format<23>;
// Misc flag for data processing instructions that indicates whether
// the instruction has a Rn register operand.
let Inst{4} = 1;
}
-class AVConv2I<bits<8> opcod1, bits<4> opcod2, bits<4> opcod3,
+class AVConv2I<bits<8> opcod1, bits<4> opcod2, dag oops, dag iops, string opc,
+ string asm, list<dag> pattern>
+ : AI<oops, iops, VFPConv2Frm, opc, asm, pattern> {
+ let Inst{27-20} = opcod1;
+ let Inst{11-8} = opcod2;
+ let Inst{4} = 1;
+}
+
+class AVConv3I<bits<8> opcod1, bits<4> opcod2, bits<4> opcod3,
dag oops, dag iops, string opc, string asm, list<dag> pattern>
- : AI<oops, iops, VFPConv1Frm, opc, asm, pattern> {
+ : AI<oops, iops, VFPConv3Frm, opc, asm, pattern> {
let Inst{27-20} = opcod1;
let Inst{19-16} = opcod2;
let Inst{11-8} = opcod3;
VFPBinaryFrm = 16 << FormShift,
VFPConv1Frm = 17 << FormShift,
VFPConv2Frm = 18 << FormShift,
- VFPLdStFrm = 19 << FormShift,
- VFPLdStMulFrm = 20 << FormShift,
- VFPMiscFrm = 21 << FormShift,
+ VFPConv3Frm = 19 << FormShift,
+ VFPLdStFrm = 20 << FormShift,
+ VFPLdStMulFrm = 21 << FormShift,
+ VFPMiscFrm = 22 << FormShift,
// Thumb format
- ThumbFrm = 22 << FormShift,
+ ThumbFrm = 23 << FormShift,
//===------------------------------------------------------------------===//
// Field shifts - such shifts are used to set field while generating
// FMDHR: GPR -> SPR
// FMDLR: GPR -> SPR
-def FMDRR : AVConv1I<0b11000100, 0b1011, (outs DPR:$dst), (ins GPR:$src1, GPR:$src2),
+def FMDRR : AVConv2I<0b11000100, 0b1011, (outs DPR:$dst), (ins GPR:$src1, GPR:$src2),
"fmdrr", " $dst, $src1, $src2",
[(set DPR:$dst, (arm_fmdrr GPR:$src1, GPR:$src2))]>;
// Int to FP:
-def FSITOD : AVConv2I<0b11101011, 0b1000, 0b1011, (outs DPR:$dst), (ins SPR:$a),
+def FSITOD : AVConv3I<0b11101011, 0b1000, 0b1011, (outs DPR:$dst), (ins SPR:$a),
"fsitod", " $dst, $a",
[(set DPR:$dst, (arm_sitof SPR:$a))]> {
let Inst{7} = 1; // Z bit
}
-def FSITOS : AVConv2I<0b11101011, 0b1000, 0b1010, (outs SPR:$dst), (ins SPR:$a),
+def FSITOS : AVConv3I<0b11101011, 0b1000, 0b1010, (outs SPR:$dst), (ins SPR:$a),
"fsitos", " $dst, $a",
[(set SPR:$dst, (arm_sitof SPR:$a))]> {
let Inst{7} = 1; // Z bit
}
-def FUITOD : AVConv2I<0b11101011, 0b1000, 0b1011, (outs DPR:$dst), (ins SPR:$a),
+def FUITOD : AVConv3I<0b11101011, 0b1000, 0b1011, (outs DPR:$dst), (ins SPR:$a),
"fuitod", " $dst, $a",
[(set DPR:$dst, (arm_uitof SPR:$a))]> {
let Inst{7} = 0; // Z bit
}
-def FUITOS : AVConv2I<0b11101011, 0b1000, 0b1010, (outs SPR:$dst), (ins SPR:$a),
+def FUITOS : AVConv3I<0b11101011, 0b1000, 0b1010, (outs SPR:$dst), (ins SPR:$a),
"fuitos", " $dst, $a",
[(set SPR:$dst, (arm_uitof SPR:$a))]> {
let Inst{7} = 1; // Z bit
// FP to Int:
// Always set Z bit in the instruction, i.e. "round towards zero" variants.
-def FTOSIZD : AVConv2I<0b11101011, 0b1101, 0b1011,
+def FTOSIZD : AVConv3I<0b11101011, 0b1101, 0b1011,
(outs SPR:$dst), (ins DPR:$a),
"ftosizd", " $dst, $a",
[(set SPR:$dst, (arm_ftosi DPR:$a))]> {
let Inst{7} = 1; // Z bit
}
-def FTOSIZS : AVConv2I<0b11101011, 0b1101, 0b1010,
+def FTOSIZS : AVConv3I<0b11101011, 0b1101, 0b1010,
(outs SPR:$dst), (ins SPR:$a),
"ftosizs", " $dst, $a",
[(set SPR:$dst, (arm_ftosi SPR:$a))]> {
let Inst{7} = 1; // Z bit
}
-def FTOUIZD : AVConv2I<0b11101011, 0b1100, 0b1011,
+def FTOUIZD : AVConv3I<0b11101011, 0b1100, 0b1011,
(outs SPR:$dst), (ins DPR:$a),
"ftouizd", " $dst, $a",
[(set SPR:$dst, (arm_ftoui DPR:$a))]> {
let Inst{7} = 1; // Z bit
}
-def FTOUIZS : AVConv2I<0b11101011, 0b1100, 0b1010,
+def FTOUIZS : AVConv3I<0b11101011, 0b1100, 0b1010,
(outs SPR:$dst), (ins SPR:$a),
"ftouizs", " $dst, $a",
[(set SPR:$dst, (arm_ftoui SPR:$a))]> {