Encode VFP conversion instructions.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@59074 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Evan Cheng 2008-11-11 19:40:26 +00:00
parent 7d12b4b510
commit 78be83d7c2
4 changed files with 126 additions and 35 deletions

View File

@ -122,6 +122,8 @@ namespace {
void emitVFPArithInstruction(const MachineInstr &MI);
void emitVFPConversionInstruction(const MachineInstr &MI);
/// getBinaryCodeForInstr - This function, generated by the
/// CodeEmitterGenerator using TableGen, produces the binary encoding for
/// machine instructions.
@ -320,6 +322,10 @@ void ARMCodeEmitter::emitInstruction(const MachineInstr &MI) {
case ARMII::VFPBinaryFrm:
emitVFPArithInstruction(MI);
break;
case ARMII::VFPConv1Frm:
case ARMII::VFPConv2Frm:
emitVFPConversionInstruction(MI);
break;
}
}
@ -999,7 +1005,7 @@ void ARMCodeEmitter::emitVFPArithInstruction(const MachineInstr &MI) {
// Encode Dd / Sd.
unsigned RegD = getMachineOpValue(MI, OpIdx++);
Binary |= (RegD & 0x0f) << ARMII::RegFdShift;
Binary |= (RegD & 0x0f) << ARMII::RegRdShift;
Binary |= (RegD & 0x10) << ARMII::D_BitShift;
// If this is a two-address operand, skip it, e.g. FMACD.
@ -1009,7 +1015,7 @@ void ARMCodeEmitter::emitVFPArithInstruction(const MachineInstr &MI) {
// Encode Dn / Sn.
if ((TID.TSFlags & ARMII::FormMask) == ARMII::VFPBinaryFrm) {
unsigned RegN = getMachineOpValue(MI, OpIdx++);
Binary |= (RegN & 0x0f);
Binary |= (RegN & 0x0f) << ARMII::RegRnShift;
Binary |= (RegN & 0x10) << ARMII::N_BitShift;
}
@ -1021,4 +1027,41 @@ 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;
unsigned OpIdx = 0;
// Encode Dd / Sd.
unsigned RegD = getMachineOpValue(MI, OpIdx++);
Binary |= (RegD & 0x0f) << ARMII::RegRdShift;
Binary |= (RegD & 0x10) << ARMII::D_BitShift;
// Encode Dn / Sn.
if ((TID.TSFlags & ARMII::FormMask) == ARMII::VFPConv1Frm) {
unsigned RegN = getMachineOpValue(MI, OpIdx++);
Binary |= (RegN & 0x0f) << ARMII::RegRnShift;
Binary |= (RegN & 0x10) << ARMII::N_BitShift;
// FMRS / FMSR do not have Rm.
if (!TID.OpInfo[2].isPredicate()) {
unsigned RegM = getMachineOpValue(MI, OpIdx++);
Binary |= (RegM & 0x0f);
Binary |= (RegM & 0x10) << ARMII::M_BitShift;
}
} else {
unsigned RegM = getMachineOpValue(MI, OpIdx++);
Binary |= (RegM & 0x0f);
Binary |= (RegM & 0x10) << ARMII::M_BitShift;
}
emitWordLE(Binary);
}
#include "ARMGenCodeEmitter.inc"

View File

@ -39,7 +39,9 @@ def ExtFrm : Format<14>;
def VFPFrm : Format<15>;
def VFPUnaryFrm : Format<16>;
def VFPBinaryFrm: Format<17>;
def ThumbFrm : Format<18>;
def VFPConv1Frm : Format<18>;
def VFPConv2Frm : Format<19>;
def ThumbFrm : Format<20>;
// Misc flag for data processing instructions that indicates whether
// the instruction has a Rn register operand.
@ -798,6 +800,23 @@ 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>
: AI<oops, iops, VFPConv1Frm, 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, 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;
}
// Special cases.
class AXSI<dag oops, dag iops, string asm, list<dag> pattern>
: XI<oops, iops, AddrModeNone, Size4Bytes, IndexModeNone,

View File

@ -70,7 +70,7 @@ namespace ARMII {
// Instruction encoding formats.
//
FormShift = 10,
FormMask = 0xf << FormShift,
FormMask = 0x1f << FormShift,
// Pseudo instructions
Pseudo = 1 << FormShift,
@ -104,9 +104,11 @@ namespace ARMII {
VPFFrm = 15 << FormShift,
VFPUnaryFrm = 16 << FormShift,
VFPBinaryFrm = 17 << FormShift,
VFPConv1Frm = 18 << FormShift,
VFPConv2Frm = 19 << FormShift,
// Thumb format
ThumbFrm = 18 << FormShift,
ThumbFrm = 20 << FormShift,
//===------------------------------------------------------------------===//
// Field shifts - such shifts are used to set field while generating
@ -119,10 +121,8 @@ namespace ARMII {
ExtRotImmShift = 10,
RegRdLoShift = 12,
RegRdShift = 12,
RegFdShift = 12,
RegRdHiShift = 16,
RegRnShift = 16,
RegFnShift = 16,
S_BitShift = 20,
W_BitShift = 21,
AM3_I_BitShift = 22,

View File

@ -211,23 +211,23 @@ def FSQRTS : ASuI<0b11101011, 0b0001, 0b1100, (outs SPR:$dst), (ins SPR:$a),
// FP <-> GPR Copies. Int <-> FP Conversions.
//
def FMRS : ASI<(outs GPR:$dst), (ins SPR:$src),
def FMRS : AVConv1I<0b11100001, 0b1010, (outs GPR:$dst), (ins SPR:$src),
"fmrs", " $dst, $src",
[(set GPR:$dst, (bitconvert SPR:$src))]>;
def FMSR : ASI<(outs SPR:$dst), (ins GPR:$src),
def FMSR : AVConv1I<0b11100000, 0b1010, (outs SPR:$dst), (ins GPR:$src),
"fmsr", " $dst, $src",
[(set SPR:$dst, (bitconvert GPR:$src))]>;
def FMRRD : ADI<(outs GPR:$dst1, GPR:$dst2), (ins DPR:$src),
def FMRRD : AVConv1I<0b11000101, 0b1011,
(outs GPR:$dst1, GPR:$dst2), (ins DPR:$src),
"fmrrd", " $dst1, $dst2, $src",
[/* FIXME: Can't write pattern for multiple result instr*/]>;
// FMDHR: GPR -> SPR
// FMDLR: GPR -> SPR
def FMDRR : ADI<(outs DPR:$dst), (ins GPR:$src1, GPR:$src2),
def FMDRR : AVConv1I<0b11000100, 0b1011, (outs DPR:$dst), (ins GPR:$src1, GPR:$src2),
"fmdrr", " $dst, $src1, $src2",
[(set DPR:$dst, (arm_fmdrr GPR:$src1, GPR:$src2))]>;
@ -238,48 +238,65 @@ def FMDRR : ADI<(outs DPR:$dst), (ins GPR:$src1, GPR:$src2),
// FMSRR: GPR -> SPR
let Defs = [CPSR] in
def FMSTAT : ASI<(outs), (ins), "fmstat", "", [(arm_fmstat)]>;
// FMXR: GPR -> VFP Sstem reg
// Int to FP:
def FSITOD : ADI<(outs DPR:$dst), (ins SPR:$a),
def FSITOD : AVConv2I<0b11101011, 0b1000, 0b1011, (outs DPR:$dst), (ins SPR:$a),
"fsitod", " $dst, $a",
[(set DPR:$dst, (arm_sitof SPR:$a))]>;
[(set DPR:$dst, (arm_sitof SPR:$a))]> {
let Inst{7} = 1; // Z bit
}
def FSITOS : ASI<(outs SPR:$dst), (ins SPR:$a),
def FSITOS : AVConv2I<0b11101011, 0b1000, 0b1010, (outs SPR:$dst), (ins SPR:$a),
"fsitos", " $dst, $a",
[(set SPR:$dst, (arm_sitof SPR:$a))]>;
[(set SPR:$dst, (arm_sitof SPR:$a))]> {
let Inst{7} = 1; // Z bit
}
def FUITOD : ADI<(outs DPR:$dst), (ins SPR:$a),
def FUITOD : AVConv2I<0b11101011, 0b1000, 0b1011, (outs DPR:$dst), (ins SPR:$a),
"fuitod", " $dst, $a",
[(set DPR:$dst, (arm_uitof SPR:$a))]>;
[(set DPR:$dst, (arm_uitof SPR:$a))]> {
let Inst{7} = 0; // Z bit
}
def FUITOS : ASI<(outs SPR:$dst), (ins SPR:$a),
def FUITOS : AVConv2I<0b11101011, 0b1000, 0b1010, (outs SPR:$dst), (ins SPR:$a),
"fuitos", " $dst, $a",
[(set SPR:$dst, (arm_uitof SPR:$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 : ADI<(outs SPR:$dst), (ins DPR:$a),
def FTOSIZD : AVConv2I<0b11101011, 0b1101, 0b1011,
(outs SPR:$dst), (ins DPR:$a),
"ftosizd", " $dst, $a",
[(set SPR:$dst, (arm_ftosi DPR:$a))]>;
[(set SPR:$dst, (arm_ftosi DPR:$a))]> {
let Inst{7} = 1; // Z bit
}
def FTOSIZS : ASI<(outs SPR:$dst), (ins SPR:$a),
def FTOSIZS : AVConv2I<0b11101011, 0b1101, 0b1010,
(outs SPR:$dst), (ins SPR:$a),
"ftosizs", " $dst, $a",
[(set SPR:$dst, (arm_ftosi SPR:$a))]>;
[(set SPR:$dst, (arm_ftosi SPR:$a))]> {
let Inst{7} = 1; // Z bit
}
def FTOUIZD : ADI<(outs SPR:$dst), (ins DPR:$a),
def FTOUIZD : AVConv2I<0b11101011, 0b1100, 0b1011,
(outs SPR:$dst), (ins DPR:$a),
"ftouizd", " $dst, $a",
[(set SPR:$dst, (arm_ftoui DPR:$a))]>;
[(set SPR:$dst, (arm_ftoui DPR:$a))]> {
let Inst{7} = 1; // Z bit
}
def FTOUIZS : ASI<(outs SPR:$dst), (ins SPR:$a),
def FTOUIZS : AVConv2I<0b11101011, 0b1100, 0b1010,
(outs SPR:$dst), (ins SPR:$a),
"ftouizs", " $dst, $a",
[(set SPR:$dst, (arm_ftoui SPR:$a))]>;
[(set SPR:$dst, (arm_ftoui SPR:$a))]> {
let Inst{7} = 1; // Z bit
}
//===----------------------------------------------------------------------===//
// FP FMA Operations.
@ -337,22 +354,34 @@ def FNMSCS : ASbI<0b11100001, (outs SPR:$dst), (ins SPR:$dstin, SPR:$a, SPR:$b),
// FP Conditional moves.
//
def FCPYDcc : ADI<(outs DPR:$dst), (ins DPR:$false, DPR:$true),
def FCPYDcc : ADuI<0b11101011, 0b0000, 0b0100,
(outs DPR:$dst), (ins DPR:$false, DPR:$true),
"fcpyd", " $dst, $true",
[/*(set DPR:$dst, (ARMcmov DPR:$false, DPR:$true, imm:$cc))*/]>,
RegConstraint<"$false = $dst">;
def FCPYScc : ASI<(outs SPR:$dst), (ins SPR:$false, SPR:$true),
def FCPYScc : ASuI<0b11101011, 0b0000, 0b0100,
(outs SPR:$dst), (ins SPR:$false, SPR:$true),
"fcpys", " $dst, $true",
[/*(set SPR:$dst, (ARMcmov SPR:$false, SPR:$true, imm:$cc))*/]>,
RegConstraint<"$false = $dst">;
def FNEGDcc : ADI<(outs DPR:$dst), (ins DPR:$false, DPR:$true),
def FNEGDcc : ADuI<0b11101011, 0b0001, 0b0100,
(outs DPR:$dst), (ins DPR:$false, DPR:$true),
"fnegd", " $dst, $true",
[/*(set DPR:$dst, (ARMcneg DPR:$false, DPR:$true, imm:$cc))*/]>,
RegConstraint<"$false = $dst">;
def FNEGScc : ASI<(outs SPR:$dst), (ins SPR:$false, SPR:$true),
def FNEGScc : ASuI<0b11101011, 0b0001, 0b0100,
(outs SPR:$dst), (ins SPR:$false, SPR:$true),
"fnegs", " $dst, $true",
[/*(set SPR:$dst, (ARMcneg SPR:$false, SPR:$true, imm:$cc))*/]>,
RegConstraint<"$false = $dst">;
//===----------------------------------------------------------------------===//
// Misc.
//
let Defs = [CPSR] in
def FMSTAT : ASI<(outs), (ins), "fmstat", "", [(arm_fmstat)]>;