Fix VFP conversion instruction encodings.

llvm-svn: 59104
This commit is contained in:
Evan Cheng 2008-11-12 06:41:41 +00:00
parent 4ad31fcc43
commit 4b6c7efbde
4 changed files with 124 additions and 87 deletions

View File

@ -347,6 +347,8 @@ void ARMCodeEmitter::emitInstruction(const MachineInstr &MI) {
case ARMII::VFPConv1Frm: case ARMII::VFPConv1Frm:
case ARMII::VFPConv2Frm: case ARMII::VFPConv2Frm:
case ARMII::VFPConv3Frm: case ARMII::VFPConv3Frm:
case ARMII::VFPConv4Frm:
case ARMII::VFPConv5Frm:
emitVFPConversionInstruction(MI); emitVFPConversionInstruction(MI);
break; break;
case ARMII::VFPLdStFrm: case ARMII::VFPLdStFrm:
@ -1095,22 +1097,9 @@ void ARMCodeEmitter::emitVFPArithInstruction(const MachineInstr &MI) {
emitWordLE(Binary); emitWordLE(Binary);
} }
void ARMCodeEmitter::emitVFPConversionInstruction(const MachineInstr &MI) { static unsigned encodeVFPRd(const MachineInstr &MI, unsigned OpIdx) {
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) << ARMII::CondShift;
// FMDRR encodes registers in reverse order.
unsigned Form = TID.TSFlags & ARMII::FormMask;
unsigned OpIdx = (Form == ARMII::VFPConv2Frm)
? MI.findFirstPredOperandIdx()-1 : 0;
// Encode Dd / Sd.
unsigned RegD = MI.getOperand(OpIdx).getReg(); unsigned RegD = MI.getOperand(OpIdx).getReg();
unsigned Binary = 0;
bool isSPVFP = false; bool isSPVFP = false;
RegD = ARMRegisterInfo::getRegisterNumbering(RegD, isSPVFP); RegD = ARMRegisterInfo::getRegisterNumbering(RegD, isSPVFP);
if (!isSPVFP) if (!isSPVFP)
@ -1119,29 +1108,13 @@ void ARMCodeEmitter::emitVFPConversionInstruction(const MachineInstr &MI) {
Binary |= ((RegD & 0x1E) >> 1) << ARMII::RegRdShift; Binary |= ((RegD & 0x1E) >> 1) << ARMII::RegRdShift;
Binary |= (RegD & 0x01) << ARMII::D_BitShift; Binary |= (RegD & 0x01) << ARMII::D_BitShift;
} }
if (Form == ARMII::VFPConv2Frm) return Binary;
--OpIdx; }
else
++OpIdx;
if (Form == ARMII::VFPConv3Frm) { static unsigned encodeVFPRn(const MachineInstr &MI, unsigned OpIdx) {
unsigned RegM = MI.getOperand(OpIdx).getReg();
isSPVFP = false;
RegM = ARMRegisterInfo::getRegisterNumbering(RegM, isSPVFP);
if (!isSPVFP)
Binary |= RegM;
else {
Binary |= ((RegM & 0x1E) >> 1);
Binary |= (RegM & 0x01) << ARMII::M_BitShift;
}
emitWordLE(Binary);
return;
}
// Encode Dn / Sn.
unsigned RegN = MI.getOperand(OpIdx).getReg(); unsigned RegN = MI.getOperand(OpIdx).getReg();
isSPVFP = false; unsigned Binary = 0;
bool isSPVFP = false;
RegN = ARMRegisterInfo::getRegisterNumbering(RegN, isSPVFP); RegN = ARMRegisterInfo::getRegisterNumbering(RegN, isSPVFP);
if (!isSPVFP) if (!isSPVFP)
Binary |= RegN << ARMII::RegRnShift; Binary |= RegN << ARMII::RegRnShift;
@ -1149,15 +1122,13 @@ void ARMCodeEmitter::emitVFPConversionInstruction(const MachineInstr &MI) {
Binary |= ((RegN & 0x1E) >> 1) << ARMII::RegRnShift; Binary |= ((RegN & 0x1E) >> 1) << ARMII::RegRnShift;
Binary |= (RegN & 0x01) << ARMII::N_BitShift; Binary |= (RegN & 0x01) << ARMII::N_BitShift;
} }
if (Form == ARMII::VFPConv2Frm) return Binary;
--OpIdx; }
else
++OpIdx;
// FMRS / FMSR do not have Rm. static unsigned encodeVFPRm(const MachineInstr &MI, unsigned OpIdx) {
if (TID.getNumOperands() > OpIdx && MI.getOperand(OpIdx).isReg()) {
unsigned RegM = MI.getOperand(OpIdx).getReg(); unsigned RegM = MI.getOperand(OpIdx).getReg();
isSPVFP = false; unsigned Binary = 0;
bool isSPVFP = false;
RegM = ARMRegisterInfo::getRegisterNumbering(RegM, isSPVFP); RegM = ARMRegisterInfo::getRegisterNumbering(RegM, isSPVFP);
if (!isSPVFP) if (!isSPVFP)
Binary |= RegM; Binary |= RegM;
@ -1165,8 +1136,61 @@ void ARMCodeEmitter::emitVFPConversionInstruction(const MachineInstr &MI) {
Binary |= ((RegM & 0x1E) >> 1); Binary |= ((RegM & 0x1E) >> 1);
Binary |= (RegM & 0x01) << ARMII::M_BitShift; Binary |= (RegM & 0x01) << ARMII::M_BitShift;
} }
return Binary;
}
void ARMCodeEmitter::emitVFPConversionInstruction(const MachineInstr &MI) {
const TargetInstrDesc &TID = MI.getDesc();
unsigned Form = TID.TSFlags & ARMII::FormMask;
// Part of binary is determined by TableGn.
unsigned Binary = getBinaryCodeForInstr(MI);
// Set the conditional execution predicate
Binary |= II->getPredicate(&MI) << ARMII::CondShift;
switch (Form) {
default: break;
case ARMII::VFPConv1Frm:
case ARMII::VFPConv2Frm:
case ARMII::VFPConv3Frm:
// Encode Dd / Sd.
Binary |= encodeVFPRd(MI, 0);
break;
case ARMII::VFPConv4Frm:
// Encode Dn / Sn.
Binary |= encodeVFPRn(MI, 0);
break;
case ARMII::VFPConv5Frm:
// Encode Dm / Sm.
Binary |= encodeVFPRm(MI, 0);
break;
} }
switch (Form) {
default: break;
case ARMII::VFPConv1Frm:
// Encode Dm / Sm.
Binary |= encodeVFPRm(MI, 1);
case ARMII::VFPConv2Frm:
case ARMII::VFPConv3Frm:
// Encode Dn / Sn.
Binary |= encodeVFPRn(MI, 1);
break;
case ARMII::VFPConv4Frm:
case ARMII::VFPConv5Frm:
// Encode Dd / Sd.
Binary |= encodeVFPRd(MI, 1);
break;
}
if (Form == ARMII::VFPConv5Frm)
// Encode Dn / Sn.
Binary |= encodeVFPRn(MI, 2);
else if (Form == ARMII::VFPConv3Frm)
// Encode Dm / Sm.
Binary |= encodeVFPRm(MI, 2);
emitWordLE(Binary); emitWordLE(Binary);
} }

View File

@ -42,11 +42,13 @@ def VFPBinaryFrm : Format<16>;
def VFPConv1Frm : Format<17>; def VFPConv1Frm : Format<17>;
def VFPConv2Frm : Format<18>; def VFPConv2Frm : Format<18>;
def VFPConv3Frm : Format<19>; def VFPConv3Frm : Format<19>;
def VFPLdStFrm : Format<20>; def VFPConv4Frm : Format<20>;
def VFPLdStMulFrm : Format<21>; def VFPConv5Frm : Format<21>;
def VFPMiscFrm : Format<22>; def VFPLdStFrm : Format<22>;
def VFPLdStMulFrm : Format<23>;
def VFPMiscFrm : Format<24>;
def ThumbFrm : Format<23>; def ThumbFrm : Format<25>;
// Misc flag for data processing instructions that indicates whether // Misc flag for data processing instructions that indicates whether
// the instruction has a Rn register operand. // the instruction has a Rn register operand.
@ -820,30 +822,39 @@ class ASbI<bits<8> opcod, dag oops, dag iops, string opc,
let Inst{11-8} = 0b1010; let Inst{11-8} = 0b1010;
} }
class AVConv1I<bits<8> opcod1, bits<4> opcod2, dag oops, dag iops, string opc, // VFP conversion instructions
string asm, list<dag> pattern> class AVConv1I<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, VFPConv1Frm, opc, asm, pattern> {
let Inst{27-20} = opcod1; let Inst{27-20} = opcod1;
let Inst{19-16} = opcod2;
let Inst{11-8} = opcod3;
let Inst{6} = 1;
}
class AVConvXI<bits<8> opcod1, bits<4> opcod2, dag oops, dag iops, Format f,
string opc, string asm, list<dag> pattern>
: AI<oops, iops, f, opc, asm, pattern> {
let Inst{27-20} = opcod1;
let Inst{11-8} = opcod2; let Inst{11-8} = opcod2;
let Inst{4} = 1; let Inst{4} = 1;
} }
class AVConv2I<bits<8> opcod1, bits<4> opcod2, dag oops, dag iops, string opc, class AVConv2I<bits<8> opcod1, bits<4> opcod2, dag oops, dag iops, string opc,
string asm, list<dag> pattern> string asm, list<dag> pattern>
: AI<oops, iops, VFPConv2Frm, opc, asm, pattern> { : AVConvXI<opcod1, opcod2, 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, class AVConv3I<bits<8> opcod1, bits<4> opcod2, dag oops, dag iops, string opc,
dag oops, dag iops, string opc, string asm, list<dag> pattern> string asm, list<dag> pattern>
: AI<oops, iops, VFPConv3Frm, opc, asm, pattern> { : AVConvXI<opcod1, opcod2, oops, iops, VFPConv3Frm, opc, asm, pattern>;
let Inst{27-20} = opcod1;
let Inst{19-16} = opcod2; class AVConv4I<bits<8> opcod1, bits<4> opcod2, dag oops, dag iops, string opc,
let Inst{11-8} = opcod3; string asm, list<dag> pattern>
let Inst{6} = 1; : AVConvXI<opcod1, opcod2, oops, iops, VFPConv4Frm, opc, asm, pattern>;
}
class AVConv5I<bits<8> opcod1, bits<4> opcod2, dag oops, dag iops, string opc,
string asm, list<dag> pattern>
: AVConvXI<opcod1, opcod2, oops, iops, VFPConv5Frm, opc, asm, pattern>;
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//

View File

@ -106,12 +106,14 @@ namespace ARMII {
VFPConv1Frm = 17 << FormShift, VFPConv1Frm = 17 << FormShift,
VFPConv2Frm = 18 << FormShift, VFPConv2Frm = 18 << FormShift,
VFPConv3Frm = 19 << FormShift, VFPConv3Frm = 19 << FormShift,
VFPLdStFrm = 20 << FormShift, VFPConv4Frm = 20 << FormShift,
VFPLdStMulFrm = 21 << FormShift, VFPConv5Frm = 21 << FormShift,
VFPMiscFrm = 22 << FormShift, VFPLdStFrm = 22 << FormShift,
VFPLdStMulFrm = 23 << FormShift,
VFPMiscFrm = 24 << FormShift,
// Thumb format // Thumb format
ThumbFrm = 23 << FormShift, ThumbFrm = 25 << FormShift,
//===------------------------------------------------------------------===// //===------------------------------------------------------------------===//
// Field shifts - such shifts are used to set field while generating // Field shifts - such shifts are used to set field while generating

View File

@ -219,15 +219,15 @@ def FSQRTS : ASuI<0b11101011, 0b0001, 0b1100, (outs SPR:$dst), (ins SPR:$a),
// FP <-> GPR Copies. Int <-> FP Conversions. // FP <-> GPR Copies. Int <-> FP Conversions.
// //
def FMRS : AVConv1I<0b11100001, 0b1010, (outs GPR:$dst), (ins SPR:$src), def FMRS : AVConv2I<0b11100001, 0b1010, (outs GPR:$dst), (ins SPR:$src),
"fmrs", " $dst, $src", "fmrs", " $dst, $src",
[(set GPR:$dst, (bitconvert SPR:$src))]>; [(set GPR:$dst, (bitconvert SPR:$src))]>;
def FMSR : AVConv2I<0b11100000, 0b1010, (outs SPR:$dst), (ins GPR:$src), def FMSR : AVConv4I<0b11100000, 0b1010, (outs SPR:$dst), (ins GPR:$src),
"fmsr", " $dst, $src", "fmsr", " $dst, $src",
[(set SPR:$dst, (bitconvert GPR:$src))]>; [(set SPR:$dst, (bitconvert GPR:$src))]>;
def FMRRD : AVConv1I<0b11000101, 0b1011, def FMRRD : AVConv3I<0b11000101, 0b1011,
(outs GPR:$dst1, GPR:$dst2), (ins DPR:$src), (outs GPR:$dst1, GPR:$dst2), (ins DPR:$src),
"fmrrd", " $dst1, $dst2, $src", "fmrrd", " $dst1, $dst2, $src",
[/* FIXME: Can't write pattern for multiple result instr*/]>; [/* FIXME: Can't write pattern for multiple result instr*/]>;
@ -235,7 +235,7 @@ def FMRRD : AVConv1I<0b11000101, 0b1011,
// FMDHR: GPR -> SPR // FMDHR: GPR -> SPR
// FMDLR: GPR -> SPR // FMDLR: GPR -> SPR
def FMDRR : AVConv2I<0b11000100, 0b1011, (outs DPR:$dst), (ins GPR:$src1, GPR:$src2), def FMDRR : AVConv5I<0b11000100, 0b1011, (outs DPR:$dst), (ins GPR:$src1, GPR:$src2),
"fmdrr", " $dst, $src1, $src2", "fmdrr", " $dst, $src1, $src2",
[(set DPR:$dst, (arm_fmdrr GPR:$src1, GPR:$src2))]>; [(set DPR:$dst, (arm_fmdrr GPR:$src1, GPR:$src2))]>;
@ -251,25 +251,25 @@ def FMDRR : AVConv2I<0b11000100, 0b1011, (outs DPR:$dst), (ins GPR:$src1, GPR:$s
// Int to FP: // Int to FP:
def FSITOD : AVConv3I<0b11101011, 0b1000, 0b1011, (outs DPR:$dst), (ins SPR:$a), def FSITOD : AVConv1I<0b11101011, 0b1000, 0b1011, (outs DPR:$dst), (ins SPR:$a),
"fsitod", " $dst, $a", "fsitod", " $dst, $a",
[(set DPR:$dst, (arm_sitof SPR:$a))]> { [(set DPR:$dst, (arm_sitof SPR:$a))]> {
let Inst{7} = 1; // Z bit let Inst{7} = 1; // Z bit
} }
def FSITOS : AVConv3I<0b11101011, 0b1000, 0b1010, (outs SPR:$dst), (ins SPR:$a), def FSITOS : AVConv1I<0b11101011, 0b1000, 0b1010, (outs SPR:$dst), (ins SPR:$a),
"fsitos", " $dst, $a", "fsitos", " $dst, $a",
[(set SPR:$dst, (arm_sitof SPR:$a))]> { [(set SPR:$dst, (arm_sitof SPR:$a))]> {
let Inst{7} = 1; // Z bit let Inst{7} = 1; // Z bit
} }
def FUITOD : AVConv3I<0b11101011, 0b1000, 0b1011, (outs DPR:$dst), (ins SPR:$a), def FUITOD : AVConv1I<0b11101011, 0b1000, 0b1011, (outs DPR:$dst), (ins SPR:$a),
"fuitod", " $dst, $a", "fuitod", " $dst, $a",
[(set DPR:$dst, (arm_uitof SPR:$a))]> { [(set DPR:$dst, (arm_uitof SPR:$a))]> {
let Inst{7} = 0; // Z bit let Inst{7} = 0; // Z bit
} }
def FUITOS : AVConv3I<0b11101011, 0b1000, 0b1010, (outs SPR:$dst), (ins SPR:$a), def FUITOS : AVConv1I<0b11101011, 0b1000, 0b1010, (outs SPR:$dst), (ins SPR:$a),
"fuitos", " $dst, $a", "fuitos", " $dst, $a",
[(set SPR:$dst, (arm_uitof SPR:$a))]> { [(set SPR:$dst, (arm_uitof SPR:$a))]> {
let Inst{7} = 1; // Z bit let Inst{7} = 1; // Z bit
@ -278,28 +278,28 @@ def FUITOS : AVConv3I<0b11101011, 0b1000, 0b1010, (outs SPR:$dst), (ins SPR:$a),
// FP to Int: // FP to Int:
// Always set Z bit in the instruction, i.e. "round towards zero" variants. // Always set Z bit in the instruction, i.e. "round towards zero" variants.
def FTOSIZD : AVConv3I<0b11101011, 0b1101, 0b1011, def FTOSIZD : AVConv1I<0b11101011, 0b1101, 0b1011,
(outs SPR:$dst), (ins DPR:$a), (outs SPR:$dst), (ins DPR:$a),
"ftosizd", " $dst, $a", "ftosizd", " $dst, $a",
[(set SPR:$dst, (arm_ftosi DPR:$a))]> { [(set SPR:$dst, (arm_ftosi DPR:$a))]> {
let Inst{7} = 1; // Z bit let Inst{7} = 1; // Z bit
} }
def FTOSIZS : AVConv3I<0b11101011, 0b1101, 0b1010, def FTOSIZS : AVConv1I<0b11101011, 0b1101, 0b1010,
(outs SPR:$dst), (ins SPR:$a), (outs SPR:$dst), (ins SPR:$a),
"ftosizs", " $dst, $a", "ftosizs", " $dst, $a",
[(set SPR:$dst, (arm_ftosi SPR:$a))]> { [(set SPR:$dst, (arm_ftosi SPR:$a))]> {
let Inst{7} = 1; // Z bit let Inst{7} = 1; // Z bit
} }
def FTOUIZD : AVConv3I<0b11101011, 0b1100, 0b1011, def FTOUIZD : AVConv1I<0b11101011, 0b1100, 0b1011,
(outs SPR:$dst), (ins DPR:$a), (outs SPR:$dst), (ins DPR:$a),
"ftouizd", " $dst, $a", "ftouizd", " $dst, $a",
[(set SPR:$dst, (arm_ftoui DPR:$a))]> { [(set SPR:$dst, (arm_ftoui DPR:$a))]> {
let Inst{7} = 1; // Z bit let Inst{7} = 1; // Z bit
} }
def FTOUIZS : AVConv3I<0b11101011, 0b1100, 0b1010, def FTOUIZS : AVConv1I<0b11101011, 0b1100, 0b1010,
(outs SPR:$dst), (ins SPR:$a), (outs SPR:$dst), (ins SPR:$a),
"ftouizs", " $dst, $a", "ftouizs", " $dst, $a",
[(set SPR:$dst, (arm_ftoui SPR:$a))]> { [(set SPR:$dst, (arm_ftoui SPR:$a))]> {