mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-12-13 19:24:21 +00:00
Encode VFP conversion instructions.
llvm-svn: 59074
This commit is contained in:
parent
1d7f2fcda8
commit
38c9a14a88
@ -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"
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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)]>;
|
||||
|
Loading…
Reference in New Issue
Block a user