Fix VFP conversion instruction encodings.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@59104 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Evan Cheng 2008-11-12 06:41:41 +00:00
parent d06d48d2b5
commit 80a119842d
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::VFPConv2Frm:
case ARMII::VFPConv3Frm:
case ARMII::VFPConv4Frm:
case ARMII::VFPConv5Frm:
emitVFPConversionInstruction(MI);
break;
case ARMII::VFPLdStFrm:
@ -1095,22 +1097,9 @@ void ARMCodeEmitter::emitVFPArithInstruction(const MachineInstr &MI) {
emitWordLE(Binary);
}
void ARMCodeEmitter::emitVFPConversionInstruction(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) << 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.
static unsigned encodeVFPRd(const MachineInstr &MI, unsigned OpIdx) {
unsigned RegD = MI.getOperand(OpIdx).getReg();
unsigned Binary = 0;
bool isSPVFP = false;
RegD = ARMRegisterInfo::getRegisterNumbering(RegD, isSPVFP);
if (!isSPVFP)
@ -1119,29 +1108,13 @@ void ARMCodeEmitter::emitVFPConversionInstruction(const MachineInstr &MI) {
Binary |= ((RegD & 0x1E) >> 1) << ARMII::RegRdShift;
Binary |= (RegD & 0x01) << ARMII::D_BitShift;
}
if (Form == ARMII::VFPConv2Frm)
--OpIdx;
else
++OpIdx;
return Binary;
}
if (Form == ARMII::VFPConv3Frm) {
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.
static unsigned encodeVFPRn(const MachineInstr &MI, unsigned OpIdx) {
unsigned RegN = MI.getOperand(OpIdx).getReg();
isSPVFP = false;
unsigned Binary = 0;
bool isSPVFP = false;
RegN = ARMRegisterInfo::getRegisterNumbering(RegN, isSPVFP);
if (!isSPVFP)
Binary |= RegN << ARMII::RegRnShift;
@ -1149,23 +1122,74 @@ void ARMCodeEmitter::emitVFPConversionInstruction(const MachineInstr &MI) {
Binary |= ((RegN & 0x1E) >> 1) << ARMII::RegRnShift;
Binary |= (RegN & 0x01) << ARMII::N_BitShift;
}
if (Form == ARMII::VFPConv2Frm)
--OpIdx;
else
++OpIdx;
return Binary;
}
// FMRS / FMSR do not have Rm.
if (TID.getNumOperands() > OpIdx && MI.getOperand(OpIdx).isReg()) {
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;
}
static unsigned encodeVFPRm(const MachineInstr &MI, unsigned OpIdx) {
unsigned RegM = MI.getOperand(OpIdx).getReg();
unsigned Binary = 0;
bool isSPVFP = false;
RegM = ARMRegisterInfo::getRegisterNumbering(RegM, isSPVFP);
if (!isSPVFP)
Binary |= RegM;
else {
Binary |= ((RegM & 0x1E) >> 1);
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);
}

View File

@ -42,11 +42,13 @@ def VFPBinaryFrm : Format<16>;
def VFPConv1Frm : Format<17>;
def VFPConv2Frm : Format<18>;
def VFPConv3Frm : Format<19>;
def VFPLdStFrm : Format<20>;
def VFPLdStMulFrm : Format<21>;
def VFPMiscFrm : Format<22>;
def VFPConv4Frm : Format<20>;
def VFPConv5Frm : Format<21>;
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
// 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;
}
class AVConv1I<bits<8> opcod1, bits<4> opcod2, dag oops, dag iops, string opc,
string asm, list<dag> pattern>
// VFP conversion instructions
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> {
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{4} = 1;
}
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;
}
string asm, list<dag> pattern>
: AVConvXI<opcod1, opcod2, oops, iops, VFPConv2Frm, opc, asm, pattern>;
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, VFPConv3Frm, opc, asm, pattern> {
let Inst{27-20} = opcod1;
let Inst{19-16} = opcod2;
let Inst{11-8} = opcod3;
let Inst{6} = 1;
}
class AVConv3I<bits<8> opcod1, bits<4> opcod2, dag oops, dag iops, string opc,
string asm, list<dag> pattern>
: AVConvXI<opcod1, opcod2, oops, iops, VFPConv3Frm, opc, asm, pattern>;
class AVConv4I<bits<8> opcod1, bits<4> opcod2, dag oops, dag iops, string opc,
string asm, list<dag> pattern>
: 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,
VFPConv2Frm = 18 << FormShift,
VFPConv3Frm = 19 << FormShift,
VFPLdStFrm = 20 << FormShift,
VFPLdStMulFrm = 21 << FormShift,
VFPMiscFrm = 22 << FormShift,
VFPConv4Frm = 20 << FormShift,
VFPConv5Frm = 21 << FormShift,
VFPLdStFrm = 22 << FormShift,
VFPLdStMulFrm = 23 << FormShift,
VFPMiscFrm = 24 << FormShift,
// Thumb format
ThumbFrm = 23 << FormShift,
ThumbFrm = 25 << FormShift,
//===------------------------------------------------------------------===//
// 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.
//
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",
[(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",
[(set SPR:$dst, (bitconvert GPR:$src))]>;
def FMRRD : AVConv1I<0b11000101, 0b1011,
def FMRRD : AVConv3I<0b11000101, 0b1011,
(outs GPR:$dst1, GPR:$dst2), (ins DPR:$src),
"fmrrd", " $dst1, $dst2, $src",
[/* FIXME: Can't write pattern for multiple result instr*/]>;
@ -235,7 +235,7 @@ def FMRRD : AVConv1I<0b11000101, 0b1011,
// FMDHR: 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",
[(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:
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",
[(set DPR:$dst, (arm_sitof SPR:$a))]> {
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",
[(set SPR:$dst, (arm_sitof SPR:$a))]> {
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",
[(set DPR:$dst, (arm_uitof SPR:$a))]> {
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",
[(set SPR:$dst, (arm_uitof SPR:$a))]> {
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:
// 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),
"ftosizd", " $dst, $a",
[(set SPR:$dst, (arm_ftosi DPR:$a))]> {
let Inst{7} = 1; // Z bit
}
def FTOSIZS : AVConv3I<0b11101011, 0b1101, 0b1010,
def FTOSIZS : AVConv1I<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 : AVConv3I<0b11101011, 0b1100, 0b1011,
def FTOUIZD : AVConv1I<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 : AVConv3I<0b11101011, 0b1100, 0b1010,
def FTOUIZS : AVConv1I<0b11101011, 0b1100, 0b1010,
(outs SPR:$dst), (ins SPR:$a),
"ftouizs", " $dst, $a",
[(set SPR:$dst, (arm_ftoui SPR:$a))]> {