mirror of
https://github.com/RPCS3/llvm.git
synced 2024-12-06 10:58:04 +00:00
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:
parent
d06d48d2b5
commit
80a119842d
@ -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);
|
||||
}
|
||||
|
@ -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>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
@ -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
|
||||
|
@ -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))]> {
|
||||
|
Loading…
Reference in New Issue
Block a user